?? ide-taskfile.c
字號:
if (stat & (ERR_STAT|DRQ_STAT)) { if (!rq->bh) { rq->current_nr_sectors += drive->mult_count; /* * NOTE: could rewind beyond beginning :-/ */ } else { printk(KERN_ERR "%s: MULTI-WRITE assume all data " \ "transfered is bad status=0x%02x\n", drive->name, stat); } return DRIVER(drive)->error(drive, "task_mulout_intr", stat); } if (!rq->bh) DRIVER(drive)->end_request(drive, 1); return startstop; } /* * DON'T be lazy code the above and below togather !!! */ if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) { if (stat & (ERR_STAT|DRQ_STAT)) { if (!rq->bh) { rq->current_nr_sectors += drive->mult_count; /* * NOTE: could rewind beyond beginning :-/ */ } else { printk(KERN_ERR "%s: MULTI-WRITE assume all data " \ "transfered is bad status=0x%02x\n", drive->name, stat); } return DRIVER(drive)->error(drive, "task_mulout_intr", stat); } /* no data yet, so wait for another interrupt */ if (HWGROUP(drive)->handler == NULL) ide_set_handler(drive, &task_mulout_intr, WAIT_WORSTCASE, NULL); return ide_started; }#ifndef ALTERNATE_STATE_DIAGRAM_MULTI_OUT if (HWGROUP(drive)->handler != NULL) { unsigned long lflags; spin_lock_irqsave(&io_request_lock, lflags); HWGROUP(drive)->handler = NULL; del_timer(&HWGROUP(drive)->timer); spin_unlock_irqrestore(&io_request_lock, lflags); }#endif /* ALTERNATE_STATE_DIAGRAM_MULTI_OUT */ do { nsect = rq->current_nr_sectors; if (nsect > msect) nsect = msect; pBuf = task_map_rq(rq, &flags); DTF("Multiwrite: %p, nsect: %d, msect: %d, " \ "rq->current_nr_sectors: %ld\n", pBuf, nsect, msect, rq->current_nr_sectors); msect -= nsect; taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); task_unmap_rq(rq, pBuf, &flags); rq->current_nr_sectors -= nsect; /* * FIXME :: We really can not legally get a new page/bh * regardless, if this is the end of our segment. * BH walking or segment can only be updated after we * have a good hwif->INB(IDE_STATUS_REG); return. */ if (!rq->current_nr_sectors) { if (!DRIVER(drive)->end_request(drive, 1)) if (!rq->bh) return ide_stopped; } } while (msect); rq->errors = 0; if (HWGROUP(drive)->handler == NULL) ide_set_handler(drive, &task_mulout_intr, WAIT_WORSTCASE, NULL); return ide_started;}EXPORT_SYMBOL(task_mulout_intr);/* Called by internal to feature out type of command being called *///ide_pre_handler_t * ide_pre_handler_parser (task_struct_t *taskfile, hob_struct_t *hobfile)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_WRITE_LONG: // case WIN_WRITE_LONG_ONCE: case WIN_MULTWRITE: case WIN_MULTWRITE_EXT: return &pre_task_mulout_intr; /* IDE_DRIVE_TASK_OUT */ case WIN_WRITE: // case WIN_WRITE_ONCE: case WIN_WRITE_EXT: 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; case WIN_WRITEDMA: // case WIN_WRITEDMA_ONCE: case WIN_WRITEDMA_QUEUED: case WIN_WRITEDMA_EXT: case WIN_WRITEDMA_QUEUED_EXT: /* IDE_DRIVE_TASK_OUT */ default: break; } return(NULL);}EXPORT_SYMBOL(ide_pre_handler_parser);/* Called by internal to feature out type of command being called *///ide_handler_t * ide_handler_parser (task_struct_t *taskfile, hob_struct_t *hobfile)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_ONCE: 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_ONCE: case WIN_WRITE_EXT: return &task_out_intr; // case WIN_READ_LONG: // case WIN_READ_LONG_ONCE: case WIN_MULTREAD: case WIN_MULTREAD_EXT: return &task_mulin_intr; // case WIN_WRITE_LONG: // case WIN_WRITE_LONG_ONCE: 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_ONCE: case WIN_VERIFY_EXT: case WIN_SEEK: return &task_no_data_intr; case WIN_SPECIFY: return &set_geometry_intr; case WIN_RECAL: // case WIN_RESTORE: return &recal_intr; case WIN_NOP: 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_READDMA_ONCE: case WIN_IDENTIFY_DMA: case WIN_READDMA_QUEUED: case WIN_READDMA_EXT: case WIN_READDMA_QUEUED_EXT: case WIN_WRITEDMA: // case WIN_WRITEDMA_ONCE: 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); } }EXPORT_SYMBOL(ide_handler_parser);ide_post_handler_t * ide_post_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile){ switch(taskfile->command) { case WIN_SPECIFY: /* set_geometry_intr */ case WIN_RESTORE: /* recal_intr */ case WIN_SETMULT: /* set_multmode_intr */ default: return(NULL); }}EXPORT_SYMBOL(ide_post_handler_parser);/* Called by ioctl to feature out type of command being called */int ide_cmd_type_parser (ide_task_t *args){ task_struct_t *taskfile = (task_struct_t *) args->tfRegister; hob_struct_t *hobfile = (hob_struct_t *) args->hobRegister; args->prehandler = ide_pre_handler_parser(taskfile, hobfile); args->handler = ide_handler_parser(taskfile, hobfile); args->posthandler = ide_post_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_ONCE: case WIN_READ_EXT: case WIN_READ_BUFFER: return IDE_DRIVE_TASK_IN; case WIN_WRITE: // case WIN_WRITE_ONCE: case WIN_WRITE_EXT: 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_READ_LONG: // case WIN_READ_LONG_ONCE: case WIN_MULTREAD: case WIN_MULTREAD_EXT: return IDE_DRIVE_TASK_IN; // case WIN_WRITE_LONG: // case WIN_WRITE_LONG_ONCE: case CFA_WRITE_MULTI_WO_ERASE: case WIN_MULTWRITE: case WIN_MULTWRITE_EXT: 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_READDMA_ONCE: 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_ONCE: 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_EN_8BIT: case SETFEATURES_EN_WCACHE: return IDE_DRIVE_TASK_NO_DATA; case SETFEATURES_XFER: return IDE_DRIVE_TASK_SET_XFER; case SETFEATURES_DIS_DEFECT: case SETFEATURES_EN_APM: case SETFEATURES_DIS_MSN: case SETFEATURES_DIS_RETRY: case SETFEATURES_EN_AAM: case SETFEATURES_RW_LONG: case SETFEATURES_SET_CACHE: case SETFEATURES_DIS_RLA: 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_ECC: case SETFEATURES_EN_MSN: case SETFEATURES_EN_RETRY: case SETFEATURES_EN_RLA: case SETFEATURES_PREFETCH: case SETFEATURES_4B_RW_LONG: case SETFEATURES_DIS_AAM: 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_ONCE: 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; }}EXPORT_SYMBOL(ide_cmd_type_parser);/* * 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;}EXPORT_SYMBOL(ide_init_drive_taskfile);#if 1int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_size, u8 *buf){ struct request rq; ide_init_drive_taskfile(&rq); rq.cmd = IDE_DRIVE_TASKFILE; rq.buffer = buf; /* * (ks) We transfer currently only whole sectors. * This is suffient for now. But, it would be great, * if we would find a solution to transfer any size. * To support special commands like READ LONG. */ if (args->command_type != IDE_DRIVE_TASK_NO_DATA) { if (data_size == 0) rq.current_nr_sectors = rq.nr_sectors = (args->hobRegister[IDE_NSECTOR_OFFSET_HOB] << 8) | args->tfRegister[IDE_NSECTOR_OFFSET]; /* rq.hard_cur_sectors */ else rq.current_nr_sectors = rq.nr_sectors = data_size / SECTOR_SIZE; /* rq.hard_cur_sectors */ } if (args->tf_out_flags.all == 0) { /* * clean up kernel settings for driver sanity, regardless. * except for discrete diag services. */ args->posthandler = ide_post_handler_parser( (struct hd_drive_task_hdr *) args->tfRegister, (struct hd_drive_hob_hdr *) args->hobRegister); } rq.special = args; return ide_do_drive_cmd(drive, &rq, ide_wait);}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -