?? ide-taskfile.c
字號:
EXPORT_SYMBOL(ide_wait_cmd_task);/* * FIXME : this needs to map into at taskfile. <andre@linux-ide.org> */int ide_task_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ int err = 0; u8 args[7], *argbuf = args; int argsize = 7; if (copy_from_user(args, (void *)arg, 7)) return -EFAULT; err = ide_wait_cmd_task(drive, argbuf); if (copy_to_user((void *)arg, argbuf, argsize)) err = -EFAULT; return err;}EXPORT_SYMBOL(ide_task_ioctl);/* * NOTICE: This is additions from IBM to provide a discrete interface, * for selective taskregister access operations. Nice JOB Klaus!!! * Glad to be able to work and co-develop this with you and IBM. */ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task){ ide_hwif_t *hwif = HWIF(drive); task_struct_t *taskfile = (task_struct_t *) task->tfRegister; hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister;#if DEBUG_TASKFILE u8 status;#endif#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG void debug_taskfile(drive, task);#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ /* * (ks) Check taskfile in/out flags. * If set, then execute as it is defined. * If not set, then define default settings. * The default values are: * write and read all taskfile registers (except data) * write and read the hob registers (sector,nsector,lcyl,hcyl) */ if (task->tf_out_flags.all == 0) { task->tf_out_flags.all = IDE_TASKFILE_STD_OUT_FLAGS; if (drive->addressing == 1) task->tf_out_flags.all |= (IDE_HOB_STD_OUT_FLAGS << 8); } if (task->tf_in_flags.all == 0) { task->tf_in_flags.all = IDE_TASKFILE_STD_IN_FLAGS; if (drive->addressing == 1) task->tf_in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8); } /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */ if (IDE_CONTROL_REG) /* clear nIEN */ hwif->OUTB(drive->ctl, IDE_CONTROL_REG); SELECT_MASK(drive, 0);#if DEBUG_TASKFILE status = hwif->INB(IDE_STATUS_REG); if (status & 0x80) { printk("flagged_taskfile -> Bad status. Status = %02x. wait 100 usec ...\n", status); udelay(100); status = hwif->INB(IDE_STATUS_REG); printk("flagged_taskfile -> Status = %02x\n", status); }#endif if (task->tf_out_flags.b.data) { u16 data = taskfile->data + (hobfile->data << 8); hwif->OUTW(data, IDE_DATA_REG); } /* (ks) send hob registers first */ if (task->tf_out_flags.b.nsector_hob) hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG); if (task->tf_out_flags.b.sector_hob) hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG); if (task->tf_out_flags.b.lcyl_hob) hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG); if (task->tf_out_flags.b.hcyl_hob) hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG); /* (ks) Send now the standard registers */ if (task->tf_out_flags.b.error_feature) hwif->OUTB(taskfile->feature, IDE_FEATURE_REG); /* refers to number of sectors to transfer */ if (task->tf_out_flags.b.nsector) hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG); /* refers to sector offset or start sector */ if (task->tf_out_flags.b.sector) hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG); if (task->tf_out_flags.b.lcyl) hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG); if (task->tf_out_flags.b.hcyl) hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG); /* * (ks) In the flagged taskfile approch, we will used all specified * registers and the register value will not be changed. Except the * select bit (master/slave) in the drive_head register. We must make * sure that the desired drive is selected. */ hwif->OUTB(taskfile->device_head | drive->select.all, IDE_SELECT_REG); switch(task->data_phase) { case TASKFILE_OUT_DMAQ: case TASKFILE_OUT_DMA: hwif->ide_dma_write(drive); break; case TASKFILE_IN_DMAQ: case TASKFILE_IN_DMA: hwif->ide_dma_read(drive); break; default: if (task->handler == NULL) return ide_stopped; /* Issue the command */ ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL); if (task->prehandler != NULL) return task->prehandler(drive, HWGROUP(drive)->rq); } return ide_started;}EXPORT_SYMBOL(flagged_taskfile);ide_startstop_t flagged_task_no_data_intr (ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); u8 stat; local_irq_enable(); if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG), READY_STAT, BAD_STAT)) { if (stat & ERR_STAT) { return DRIVER(drive)->error(drive, "flagged_task_no_data_intr", stat); } /* * (ks) Unexpected ATA data phase detected. * This should not happen. But, it can ! * I am not sure, which function is best to clean up * this situation. I choose: ide_error(...) */ return DRIVER(drive)->error(drive, "flagged_task_no_data_intr (unexpected phase)", stat); } ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG)); return ide_stopped;}/* * Handler for command with PIO data-in phase */ide_startstop_t flagged_task_in_intr (ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); u8 stat = hwif->INB(IDE_STATUS_REG); struct request *rq = HWGROUP(drive)->rq; char *pBuf = NULL; int retries = 5; if (rq->current_nr_sectors == 0) return DRIVER(drive)->error(drive, "flagged_task_in_intr (no data requested)", stat); if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { if (stat & ERR_STAT) { return DRIVER(drive)->error(drive, "flagged_task_in_intr", stat); } /* * (ks) Unexpected ATA data phase detected. * This should not happen. But, it can ! * I am not sure, which function is best to clean up * this situation. I choose: ide_error(...) */ return DRIVER(drive)->error(drive, "flagged_task_in_intr (unexpected data phase)", stat); } pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); DTF("Read - rq->current_nr_sectors: %d, status: %02x\n", (int) rq->current_nr_sectors, stat); taskfile_input_data(drive, pBuf, SECTOR_WORDS); if (--rq->current_nr_sectors != 0) { /* * (ks) We don't know which command was executed. * So, we wait the 'WORSTCASE' value. */ ide_set_handler(drive, &flagged_task_in_intr, WAIT_WORSTCASE, NULL); return ide_started; } /* * (ks) Last sector was transfered, wait until drive is ready. * This can take up to 10 usec. We willl wait max 50 us. */ while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--) udelay(10); ide_end_drive_cmd (drive, stat, hwif->INB(IDE_ERROR_REG)); return ide_stopped;}ide_startstop_t flagged_task_mulin_intr (ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); u8 stat = hwif->INB(IDE_STATUS_REG); struct request *rq = HWGROUP(drive)->rq; char *pBuf = NULL; int retries = 5; unsigned int msect, nsect; if (rq->current_nr_sectors == 0) return DRIVER(drive)->error(drive, "flagged_task_mulin_intr (no data requested)", stat); msect = drive->mult_count; if (msect == 0) return DRIVER(drive)->error(drive, "flagged_task_mulin_intr (multimode not set)", stat); if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { if (stat & ERR_STAT) { return DRIVER(drive)->error(drive, "flagged_task_mulin_intr", stat); } /* * (ks) Unexpected ATA data phase detected. * This should not happen. But, it can ! * I am not sure, which function is best to clean up * this situation. I choose: ide_error(...) */ return DRIVER(drive)->error(drive, "flagged_task_mulin_intr (unexpected data phase)", stat); } nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors; pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); DTF("Multiread: %p, nsect: %d , rq->current_nr_sectors: %ld\n", pBuf, nsect, rq->current_nr_sectors); taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS); rq->current_nr_sectors -= nsect; if (rq->current_nr_sectors != 0) { /* * (ks) We don't know which command was executed. * So, we wait the 'WORSTCASE' value. */ ide_set_handler(drive, &flagged_task_mulin_intr, WAIT_WORSTCASE, NULL); return ide_started; } /* * (ks) Last sector was transfered, wait until drive is ready. * This can take up to 10 usec. We willl wait max 50 us. */ while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--) udelay(10); ide_end_drive_cmd (drive, stat, hwif->INB(IDE_ERROR_REG)); return ide_stopped;}/* * Pre handler for command with PIO data-out phase */ide_startstop_t flagged_pre_task_out_intr (ide_drive_t *drive, struct request *rq){ ide_hwif_t *hwif = HWIF(drive); u8 stat = hwif->INB(IDE_STATUS_REG); ide_startstop_t startstop; if (!rq->current_nr_sectors) { return DRIVER(drive)->error(drive, "flagged_pre_task_out_intr (write data not specified)", stat); } if (ide_wait_stat(&startstop, drive, DATA_READY, BAD_W_STAT, WAIT_DRQ)) { printk(KERN_ERR "%s: No DRQ bit after issuing write command.\n", drive->name); return startstop; } taskfile_output_data(drive, rq->buffer, SECTOR_WORDS); --rq->current_nr_sectors; return ide_started;}ide_startstop_t flagged_task_out_intr (ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); u8 stat = hwif->INB(IDE_STATUS_REG); struct request *rq = HWGROUP(drive)->rq; char *pBuf = NULL; if (!OK_STAT(stat, DRIVE_READY, BAD_W_STAT)) return DRIVER(drive)->error(drive, "flagged_task_out_intr", stat); if (!rq->current_nr_sectors) { ide_end_drive_cmd (drive, stat, hwif->INB(IDE_ERROR_REG)); return ide_stopped; } if (!OK_STAT(stat, DATA_READY, BAD_W_STAT)) { /* * (ks) Unexpected ATA data phase detected. * This should not happen. But, it can ! * I am not sure, which function is best to clean up * this situation. I choose: ide_error(...) */ return DRIVER(drive)->error(drive, "flagged_task_out_intr (unexpected data phase)", stat); } pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); DTF("Write - rq->current_nr_sectors: %d, status: %02x\n", (int) rq->current_nr_sectors, stat); taskfile_output_data(drive, pBuf, SECTOR_WORDS); --rq->current_nr_sectors; /* * (ks) We don't know which command was executed. * So, we wait the 'WORSTCASE' value. */ ide_set_handler(drive, &flagged_task_out_intr, WAIT_WORSTCASE, NULL); return ide_started;}ide_startstop_t flagged_pre_task_mulout_intr (ide_drive_t *drive, struct request *rq){ ide_hwif_t *hwif = HWIF(drive); u8 stat = hwif->INB(IDE_STATUS_REG); char *pBuf = NULL; ide_startstop_t startstop; unsigned int msect, nsect; if (!rq->current_nr_sectors) return DRIVER(drive)->error(drive, "flagged_pre_task_mulout_intr (write data not specified)", stat); msect = drive->mult_count; if (msect == 0) return DRIVER(drive)->error(drive, "flagged_pre_task_mulout_intr (multimode not set)", stat); if (ide_wait_stat(&startstop, drive, DATA_READY, BAD_W_STAT, WAIT_DRQ)) { printk(KERN_ERR "%s: No DRQ bit after issuing write command.\n", drive->name); return startstop; } 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); taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); rq->current_nr_sectors -= nsect; return ide_started;}ide_startstop_t flagged_task_mulout_intr (ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); u8 stat = hwif->INB(IDE_STATUS_REG); struct request *rq = HWGROUP(drive)->rq; char *pBuf = NULL; unsigned int msect, nsect; msect = drive->mult_count; if (msect == 0) return DRIVER(drive)->error(drive, "flagged_task_mulout_intr (multimode not set)", stat); if (!OK_STAT(stat, DRIVE_READY, BAD_W_STAT)) return DRIVER(drive)->error(drive, "flagged_task_mulout_intr", stat); if (!rq->current_nr_sectors) { ide_end_drive_cmd (drive, stat, hwif->INB(IDE_ERROR_REG)); return ide_stopped; } if (!OK_STAT(stat, DATA_READY, BAD_W_STAT)) { /* * (ks) Unexpected ATA data phase detected. * This should not happen. But, it can ! * I am not sure, which function is best to clean up * this situation. I choose: ide_error(...) */ return DRIVER(drive)->error(drive, "flagged_task_mulout_intr (unexpected data phase)", stat); } 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); taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); rq->current_nr_sectors -= nsect; /* * (ks) We don't know which command was executed. * So, we wait the 'WORSTCASE' value. */ ide_set_handler(drive, &flagged_task_mulout_intr, WAIT_WORSTCASE, NULL); return ide_started;}/* * Beginning of Taskfile OPCODE Library and feature sets. */#ifdef CONFIG_PKT_TASK_IOCTLint pkt_taskfile_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){#if 0 switch(req_task->data_phase) { case TASKFILE_P_OUT_DMAQ: case TASKFILE_P_IN_DMAQ: case TASKFILE_P_OUT_DMA: case TASKFILE_P_IN_DMA: case TASKFILE_P_OUT: case TASKFILE_P_IN: }#endif return -ENOMSG;}EXPORT_SYMBOL(pkt_taskfile_ioctl);#endif /* CONFIG_PKT_TASK_IOCTL */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -