📄 ide-taskfile.c
字号:
taskfile_output_data(drive, rq->buffer, SECTOR_WORDS); rq->current_nr_sectors--; return ide_started; } else { /* * (ks/hs): Stuff the first sector(s) * by implicitly calling the handler */ if (!(drive_is_ready(drive))) { int i; /* * (ks/hs): FIXME: Replace hard-coded * 100, error handling? */ for (i=0; i<100; i++) { if (drive_is_ready(drive)) break; } } return args->handler(drive); } return ide_started;}/* * Handler for command with PIO data-out phase */ide_startstop_t task_out_intr (ide_drive_t *drive){ byte stat = GET_STAT(); byte io_32bit = drive->io_32bit; struct request *rq = HWGROUP(drive)->rq; char *pBuf = NULL; if (!rq->current_nr_sectors) { ide_end_request(1, HWGROUP(drive)); return ide_stopped; } if (!OK_STAT(stat,DRIVE_READY,drive->bad_wstat)) { return ide_error(drive, "task_out_intr", stat); } if ((rq->current_nr_sectors==1) ^ (stat & DRQ_STAT)) { rq = HWGROUP(drive)->rq; pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); DTF("write: %p, rq->current_nr_sectors: %d\n", pBuf, (int) rq->current_nr_sectors); drive->io_32bit = 0; taskfile_output_data(drive, pBuf, SECTOR_WORDS); drive->io_32bit = io_32bit; rq->errors = 0; rq->current_nr_sectors--; } if (rq->current_nr_sectors <= 0) { ide_end_request(1, HWGROUP(drive)); } else { ide_set_handler(drive, &task_out_intr, WAIT_CMD, NULL); return ide_started; } return ide_stopped;}/* * Handler for command write multiple * Called directly from execute_drive_cmd for the first bunch of sectors, * afterwards only by the ISR */ide_startstop_t task_mulout_intr (ide_drive_t *drive){ unsigned int msect, nsect;#ifdef ALTSTAT_SCREW_UP byte stat = altstat_multi_busy(drive, GET_ALTSTAT(), "write");#else byte stat = GET_STAT();#endif /* ALTSTAT_SCREW_UP */ byte io_32bit = drive->io_32bit; struct request *rq = HWGROUP(drive)->rq; ide_hwgroup_t *hwgroup = HWGROUP(drive); char *pBuf = NULL; /* * (ks/hs): Handle last IRQ on multi-sector transfer, * occurs after all data was sent */ if (rq->current_nr_sectors == 0) { if (stat & (ERR_STAT|DRQ_STAT)) return ide_error(drive, "task_mulout_intr", stat); ide_end_request(1, HWGROUP(drive)); return ide_stopped; } if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) { if (stat & (ERR_STAT|DRQ_STAT)) { return ide_error(drive, "task_mulout_intr", stat); } /* no data yet, so wait for another interrupt */ if (hwgroup->handler == NULL) ide_set_handler(drive, &task_mulout_intr, WAIT_CMD, NULL); return ide_started; } /* (ks/hs): See task_mulin_intr */ msect = drive->mult_count;#ifdef ALTSTAT_SCREW_UP /* * Screw the request we do not support bad data-phase setups! * Either read and learn the ATA standard or crash yourself! */ if (!msect) { nsect = 1; while (rq->current_nr_sectors) { pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); DTF("Multiwrite: %p, nsect: %d, rq->current_nr_sectors: %ld\n", pBuf, nsect, rq->current_nr_sectors); drive->io_32bit = 0; taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); drive->io_32bit = io_32bit; rq->errors = 0; rq->current_nr_sectors -= nsect; stat = altstat_multi_poll(drive, GET_ALTSTAT(), "write"); } ide_end_request(1, HWGROUP(drive)); return ide_stopped; }#endif /* ALTSTAT_SCREW_UP */ nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors; pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); DTF("Multiwrite: %p, nsect: %d , rq->current_nr_sectors: %ld\n", pBuf, nsect, rq->current_nr_sectors); drive->io_32bit = 0; taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); drive->io_32bit = io_32bit; rq->errors = 0; rq->current_nr_sectors -= nsect; if (hwgroup->handler == NULL) ide_set_handler(drive, &task_mulout_intr, WAIT_CMD, NULL); return ide_started;}/* Called by internal to feature out type of command being called */ide_pre_handler_t * ide_pre_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile){ switch(taskfile->command) { /* IDE_DRIVE_TASK_RAW_WRITE */ case CFA_WRITE_MULTI_WO_ERASE: case WIN_MULTWRITE: case WIN_MULTWRITE_EXT:// case WIN_WRITEDMA:// case WIN_WRITEDMA_QUEUED:// case WIN_WRITEDMA_EXT:// case WIN_WRITEDMA_QUEUED_EXT: /* IDE_DRIVE_TASK_OUT */ case WIN_WRITE: case WIN_WRITE_VERIFY: case WIN_WRITE_BUFFER: case CFA_WRITE_SECT_WO_ERASE: case WIN_DOWNLOAD_MICROCODE: return &pre_task_out_intr; /* IDE_DRIVE_TASK_OUT */ case WIN_SMART: if (taskfile->feature == SMART_WRITE_LOG_SECTOR) return &pre_task_out_intr; default: break; } return(NULL);}/* Called by internal to feature out type of command being called */ide_handler_t * ide_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile){ switch(taskfile->command) { case WIN_IDENTIFY: case WIN_PIDENTIFY: case CFA_TRANSLATE_SECTOR: case WIN_READ_BUFFER: case WIN_READ: case WIN_READ_EXT: return &task_in_intr; case WIN_SECURITY_DISABLE: case WIN_SECURITY_ERASE_UNIT: case WIN_SECURITY_SET_PASS: case WIN_SECURITY_UNLOCK: case WIN_DOWNLOAD_MICROCODE: case CFA_WRITE_SECT_WO_ERASE: case WIN_WRITE_BUFFER: case WIN_WRITE_VERIFY: case WIN_WRITE: case WIN_WRITE_EXT: return &task_out_intr; case WIN_MULTREAD: case WIN_MULTREAD_EXT: return &task_mulin_intr; case CFA_WRITE_MULTI_WO_ERASE: case WIN_MULTWRITE: case WIN_MULTWRITE_EXT: return &task_mulout_intr; case WIN_SMART: switch(taskfile->feature) { case SMART_READ_VALUES: case SMART_READ_THRESHOLDS: case SMART_READ_LOG_SECTOR: return &task_in_intr; case SMART_WRITE_LOG_SECTOR: return &task_out_intr; default: return &task_no_data_intr; } case CFA_REQ_EXT_ERROR_CODE: case CFA_ERASE_SECTORS: case WIN_VERIFY: case WIN_VERIFY_EXT: case WIN_SEEK: return &task_no_data_intr; case WIN_SPECIFY: return &set_geometry_intr; case WIN_RESTORE: return &recal_intr; case WIN_DIAGNOSE: case WIN_FLUSH_CACHE: case WIN_FLUSH_CACHE_EXT: case WIN_STANDBYNOW1: case WIN_STANDBYNOW2: case WIN_SLEEPNOW1: case WIN_SLEEPNOW2: case WIN_SETIDLE1: case WIN_CHECKPOWERMODE1: case WIN_CHECKPOWERMODE2: case WIN_GETMEDIASTATUS: case WIN_MEDIAEJECT: return &task_no_data_intr; case WIN_SETMULT: return &set_multmode_intr; case WIN_READ_NATIVE_MAX: case WIN_SET_MAX: case WIN_READ_NATIVE_MAX_EXT: case WIN_SET_MAX_EXT: case WIN_SECURITY_ERASE_PREPARE: case WIN_SECURITY_FREEZE_LOCK: case WIN_DOORLOCK: case WIN_DOORUNLOCK: case WIN_SETFEATURES: return &task_no_data_intr; case DISABLE_SEAGATE: case EXABYTE_ENABLE_NEST: return &task_no_data_intr;#ifdef CONFIG_BLK_DEV_IDEDMA case WIN_READDMA: case WIN_IDENTIFY_DMA: case WIN_READDMA_QUEUED: case WIN_READDMA_EXT: case WIN_READDMA_QUEUED_EXT: case WIN_WRITEDMA: case WIN_WRITEDMA_QUEUED: case WIN_WRITEDMA_EXT: case WIN_WRITEDMA_QUEUED_EXT:#endif case WIN_FORMAT: case WIN_INIT: case WIN_DEVICE_RESET: case WIN_QUEUED_SERVICE: case WIN_PACKETCMD: default: return(NULL); } }/* Called by ioctl to feature out type of command being called */int ide_cmd_type_parser (ide_task_t *args){ struct hd_drive_task_hdr *taskfile = (struct hd_drive_task_hdr *) args->tfRegister; struct hd_drive_hob_hdr *hobfile = (struct hd_drive_hob_hdr *) args->hobRegister; args->prehandler = ide_pre_handler_parser(taskfile, hobfile); args->handler = ide_handler_parser(taskfile, hobfile); switch(args->tfRegister[IDE_COMMAND_OFFSET]) { case WIN_IDENTIFY: case WIN_PIDENTIFY: return IDE_DRIVE_TASK_IN; case CFA_TRANSLATE_SECTOR: case WIN_READ: case WIN_READ_BUFFER: return IDE_DRIVE_TASK_IN; case WIN_WRITE: case WIN_WRITE_VERIFY: case WIN_WRITE_BUFFER: case CFA_WRITE_SECT_WO_ERASE: case WIN_DOWNLOAD_MICROCODE: return IDE_DRIVE_TASK_RAW_WRITE; case WIN_MULTREAD: return IDE_DRIVE_TASK_IN; case CFA_WRITE_MULTI_WO_ERASE: case WIN_MULTWRITE: return IDE_DRIVE_TASK_RAW_WRITE; case WIN_SECURITY_DISABLE: case WIN_SECURITY_ERASE_UNIT: case WIN_SECURITY_SET_PASS: case WIN_SECURITY_UNLOCK: return IDE_DRIVE_TASK_OUT; case WIN_SMART: args->tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS; args->tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS; switch(args->tfRegister[IDE_FEATURE_OFFSET]) { case SMART_READ_VALUES: case SMART_READ_THRESHOLDS: case SMART_READ_LOG_SECTOR: return IDE_DRIVE_TASK_IN; case SMART_WRITE_LOG_SECTOR: return IDE_DRIVE_TASK_OUT; default: return IDE_DRIVE_TASK_NO_DATA; }#ifdef CONFIG_BLK_DEV_IDEDMA case WIN_READDMA: case WIN_IDENTIFY_DMA: case WIN_READDMA_QUEUED: case WIN_READDMA_EXT: case WIN_READDMA_QUEUED_EXT: return IDE_DRIVE_TASK_IN; case WIN_WRITEDMA: case WIN_WRITEDMA_QUEUED: case WIN_WRITEDMA_EXT: case WIN_WRITEDMA_QUEUED_EXT: return IDE_DRIVE_TASK_RAW_WRITE;#endif case WIN_SETFEATURES: switch(args->tfRegister[IDE_FEATURE_OFFSET]) { case SETFEATURES_XFER: return IDE_DRIVE_TASK_SET_XFER; case SETFEATURES_DIS_DEFECT: case SETFEATURES_EN_APM: case SETFEATURES_DIS_MSN: case SETFEATURES_EN_RI: case SETFEATURES_EN_SI: case SETFEATURES_DIS_RPOD: case SETFEATURES_DIS_WCACHE: case SETFEATURES_EN_DEFECT: case SETFEATURES_DIS_APM: case SETFEATURES_EN_MSN: case SETFEATURES_EN_RLA: case SETFEATURES_PREFETCH: case SETFEATURES_EN_RPOD: case SETFEATURES_DIS_RI: case SETFEATURES_DIS_SI: default: return IDE_DRIVE_TASK_NO_DATA; } case WIN_NOP: case CFA_REQ_EXT_ERROR_CODE: case CFA_ERASE_SECTORS: case WIN_VERIFY: case WIN_VERIFY_EXT: case WIN_SEEK: case WIN_SPECIFY: case WIN_RESTORE: case WIN_DIAGNOSE: case WIN_FLUSH_CACHE: case WIN_FLUSH_CACHE_EXT: case WIN_STANDBYNOW1: case WIN_STANDBYNOW2: case WIN_SLEEPNOW1: case WIN_SLEEPNOW2: case WIN_SETIDLE1: case DISABLE_SEAGATE: case WIN_CHECKPOWERMODE1: case WIN_CHECKPOWERMODE2: case WIN_GETMEDIASTATUS: case WIN_MEDIAEJECT: case WIN_SETMULT: case WIN_READ_NATIVE_MAX: case WIN_SET_MAX: case WIN_READ_NATIVE_MAX_EXT: case WIN_SET_MAX_EXT: case WIN_SECURITY_ERASE_PREPARE: case WIN_SECURITY_FREEZE_LOCK: case EXABYTE_ENABLE_NEST: case WIN_DOORLOCK: case WIN_DOORUNLOCK: return IDE_DRIVE_TASK_NO_DATA; case WIN_FORMAT: case WIN_INIT: case WIN_DEVICE_RESET: case WIN_QUEUED_SERVICE: case WIN_PACKETCMD: default: return IDE_DRIVE_TASK_INVALID; }}/* * This function is intended to be used prior to invoking ide_do_drive_cmd(). */void ide_init_drive_taskfile (struct request *rq){ memset(rq, 0, sizeof(*rq)); rq->cmd = IDE_DRIVE_TASK_NO_DATA;}/* * This is kept for internal use only !!! * This is an internal call and nobody in user-space has a damn * reason to call this taskfile. * * ide_raw_taskfile is the one that user-space executes. */int ide_wait_taskfile (ide_drive_t *drive, struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile, byte *buf){ struct request rq; ide_task_t args; memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_DATA_OFFSET] = taskfile->data; args.tfRegister[IDE_FEATURE_OFFSET] = taskfile->feature; args.tfRegister[IDE_NSECTOR_OFFSET] = taskfile->sector_count; args.tfRegister[IDE_SECTOR_OFFSET] = taskfile->sector_number; args.tfRegister[IDE_LCYL_OFFSET] = taskfile->low_cylinder; args.tfRegister[IDE_HCYL_OFFSET] = taskfile->high_cylinder; args.tfRegister[IDE_SELECT_OFFSET] = taskfile->device_head; args.tfRegister[IDE_COMMAND_OFFSET] = taskfile->command; args.hobRegister[IDE_DATA_OFFSET_HOB] = hobfile->data; args.hobRegister[IDE_FEATURE_OFFSET_HOB] = hobfile->feature; args.hobRegister[IDE_NSECTOR_OFFSET_HOB] = hobfile->sector_count; args.hobRegister[IDE_SECTOR_OFFSET_HOB] = hobfile->sector_number; args.hobRegister[IDE_LCYL_OFFSET_HOB] = hobfile->low_cylinder; args.hobRegister[IDE_HCYL_OFFSET_HOB] = hobfile->high_cylinder;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -