📄 ide-taskfile.c
字号:
args.hobRegister[IDE_SELECT_OFFSET_HOB] = hobfile->device_head; args.hobRegister[IDE_CONTROL_OFFSET_HOB] = hobfile->control; ide_init_drive_taskfile(&rq); /* This is kept for internal use only !!! */ args.command_type = ide_cmd_type_parser (&args); if (args.command_type != IDE_DRIVE_TASK_NO_DATA) rq.current_nr_sectors = rq.nr_sectors = (hobfile->sector_count << 8) | taskfile->sector_count; rq.cmd = IDE_DRIVE_TASKFILE; rq.buffer = buf; rq.special = &args; return ide_do_drive_cmd(drive, &rq, ide_wait);}int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, byte *buf){ struct request rq; ide_init_drive_taskfile(&rq); rq.cmd = IDE_DRIVE_TASKFILE; rq.buffer = buf; if (args->command_type != IDE_DRIVE_TASK_NO_DATA) rq.current_nr_sectors = rq.nr_sectors = (args->hobRegister[IDE_NSECTOR_OFFSET_HOB] << 8) | args->tfRegister[IDE_NSECTOR_OFFSET]; rq.special = args; return ide_do_drive_cmd(drive, &rq, ide_wait);}#ifdef CONFIG_IDE_TASK_IOCTL_DEBUGchar * ide_ioctl_verbose (unsigned int cmd){ return("unknown");}char * ide_task_cmd_verbose (byte task){ return("unknown");}#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG *//* * The taskfile glue table * * reqtask.data_phase reqtask.req_cmd * args.command_type args.handler * * TASKFILE_P_OUT_DMAQ ?? ?? * TASKFILE_P_IN_DMAQ ?? ?? * TASKFILE_P_OUT_DMA ?? ?? * TASKFILE_P_IN_DMA ?? ?? * TASKFILE_P_OUT ?? ?? * TASKFILE_P_IN ?? ?? * * TASKFILE_OUT_DMAQ IDE_DRIVE_TASK_RAW_WRITE NULL * TASKFILE_IN_DMAQ IDE_DRIVE_TASK_IN NULL * * TASKFILE_OUT_DMA IDE_DRIVE_TASK_RAW_WRITE NULL * TASKFILE_IN_DMA IDE_DRIVE_TASK_IN NULL * * TASKFILE_IN_OUT ?? ?? * * TASKFILE_MULTI_OUT IDE_DRIVE_TASK_RAW_WRITE task_mulout_intr * TASKFILE_MULTI_IN IDE_DRIVE_TASK_IN task_mulin_intr * * TASKFILE_OUT IDE_DRIVE_TASK_RAW_WRITE task_out_intr * TASKFILE_OUT IDE_DRIVE_TASK_OUT task_out_intr * * TASKFILE_IN IDE_DRIVE_TASK_IN task_in_intr * TASKFILE_NO_DATA IDE_DRIVE_TASK_NO_DATA task_no_data_intr * * IDE_DRIVE_TASK_SET_XFER task_no_data_intr * IDE_DRIVE_TASK_INVALID * */#define MAX_DMA (256*SECTOR_WORDS)int ide_taskfile_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ ide_task_request_t *req_task; ide_task_t args; byte *outbuf = NULL; byte *inbuf = NULL; task_ioreg_t *argsptr = args.tfRegister; task_ioreg_t *hobsptr = args.hobRegister; int err = 0; int tasksize = sizeof(struct ide_task_request_s); int taskin = 0; int taskout = 0; req_task = kmalloc(tasksize, GFP_KERNEL); if (req_task == NULL) return -ENOMEM; memset(req_task, 0, tasksize); if (copy_from_user(req_task, (void *) arg, tasksize)) { kfree(req_task); return -EFAULT; } taskout = (int) req_task->out_size; taskin = (int) req_task->in_size; if (taskout) { int outtotal = tasksize; outbuf = kmalloc(taskout, GFP_KERNEL); if (outbuf == NULL) { err = -ENOMEM; goto abort; } memset(outbuf, 0, taskout); if (copy_from_user(outbuf, (void *)arg + outtotal, taskout)) { err = -EFAULT; goto abort; } } if (taskin) { int intotal = tasksize + taskout; inbuf = kmalloc(taskin, GFP_KERNEL); if (inbuf == NULL) { err = -ENOMEM; goto abort; } memset(inbuf, 0, taskin); if (copy_from_user(inbuf, (void *)arg + intotal , taskin)) { err = -EFAULT; goto abort; } } memset(argsptr, 0, HDIO_DRIVE_TASK_HDR_SIZE); memset(hobsptr, 0, HDIO_DRIVE_HOB_HDR_SIZE); memcpy(argsptr, req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE); memcpy(hobsptr, req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE); args.tf_in_flags = req_task->in_flags; args.tf_out_flags = req_task->out_flags; args.data_phase = req_task->data_phase; args.command_type = req_task->req_cmd;#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG DTF("%s: ide_ioctl_cmd %s: ide_task_cmd %s\n", drive->name, ide_ioctl_verbose(cmd), ide_task_cmd_verbose(args.tfRegister[IDE_COMMAND_OFFSET]));#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ switch(req_task->data_phase) { case TASKFILE_OUT_DMAQ: case TASKFILE_OUT_DMA: args.prehandler = NULL; args.handler = NULL; args.posthandler = NULL; err = ide_raw_taskfile(drive, &args, outbuf); break; case TASKFILE_IN_DMAQ: case TASKFILE_IN_DMA: args.prehandler = NULL; args.handler = NULL; args.posthandler = NULL; err = ide_raw_taskfile(drive, &args, inbuf); break; case TASKFILE_IN_OUT:#if 0 args.prehandler = &pre_task_out_intr; args.handler = &task_out_intr; args.posthandler = NULL; err = ide_raw_taskfile(drive, &args, outbuf); args.prehandler = NULL; args.handler = &task_in_intr; args.posthandler = NULL; err = ide_raw_taskfile(drive, &args, inbuf); break;#else err = -EFAULT; goto abort;#endif case TASKFILE_MULTI_OUT: if (drive->mult_count) { args.prehandler = &pre_task_out_intr; args.handler = &task_mulout_intr; args.posthandler = NULL; err = ide_raw_taskfile(drive, &args, outbuf); } else { /* (hs): give up if multcount is not set */ printk("%s: %s Multimode Write " \ "multcount is not set\n", drive->name, __FUNCTION__); err = -EPERM; goto abort; } break; case TASKFILE_OUT: args.prehandler = &pre_task_out_intr; args.handler = &task_out_intr; args.posthandler = NULL; err = ide_raw_taskfile(drive, &args, outbuf); break; case TASKFILE_MULTI_IN: if (drive->mult_count) { args.prehandler = NULL; args.handler = &task_mulin_intr; args.posthandler = NULL; err = ide_raw_taskfile(drive, &args, inbuf); } else { /* (hs): give up if multcount is not set */ printk("%s: %s Multimode Read failure " \ "multcount is not set\n", drive->name, __FUNCTION__); err = -EPERM; goto abort; } break; case TASKFILE_IN: args.prehandler = NULL; args.handler = &task_in_intr; args.posthandler = NULL; err = ide_raw_taskfile(drive, &args, inbuf); break; case TASKFILE_NO_DATA: args.prehandler = NULL; args.handler = &task_no_data_intr; args.posthandler = NULL; err = ide_raw_taskfile(drive, &args, NULL); break; default: args.prehandler = NULL; args.handler = NULL; args.posthandler = NULL; err = -EFAULT; goto abort; } memcpy(req_task->io_ports, &(args.tfRegister), HDIO_DRIVE_TASK_HDR_SIZE); memcpy(req_task->hob_ports, &(args.hobRegister), HDIO_DRIVE_HOB_HDR_SIZE); req_task->in_flags = args.tf_in_flags; req_task->out_flags = args.tf_out_flags; if (copy_to_user((void *)arg, req_task, tasksize)) { err = -EFAULT; goto abort; } if (taskout) { int outtotal = tasksize; if (copy_to_user((void *)arg+outtotal, outbuf, taskout)) { err = -EFAULT; goto abort; } } if (taskin) { int intotal = tasksize + taskout; if (copy_to_user((void *)arg+intotal, inbuf, taskin)) { err = -EFAULT; goto abort; } }abort: kfree(req_task); if (outbuf != NULL) kfree(outbuf); if (inbuf != NULL) kfree(inbuf); return err;}EXPORT_SYMBOL(task_read_24);EXPORT_SYMBOL(do_rw_taskfile);EXPORT_SYMBOL(do_taskfile);// EXPORT_SYMBOL(flagged_taskfile);//EXPORT_SYMBOL(ide_end_taskfile);EXPORT_SYMBOL(set_multmode_intr);EXPORT_SYMBOL(set_geometry_intr);EXPORT_SYMBOL(recal_intr);EXPORT_SYMBOL(task_no_data_intr);EXPORT_SYMBOL(task_in_intr);EXPORT_SYMBOL(task_mulin_intr);EXPORT_SYMBOL(pre_task_out_intr);EXPORT_SYMBOL(task_out_intr);EXPORT_SYMBOL(task_mulout_intr);EXPORT_SYMBOL(ide_init_drive_taskfile);EXPORT_SYMBOL(ide_wait_taskfile);EXPORT_SYMBOL(ide_raw_taskfile);EXPORT_SYMBOL(ide_pre_handler_parser);EXPORT_SYMBOL(ide_handler_parser);EXPORT_SYMBOL(ide_cmd_type_parser);EXPORT_SYMBOL(ide_taskfile_ioctl);#ifdef CONFIG_PKT_TASK_IOCTL#if 0{{ /* start cdrom */ struct cdrom_info *info = drive->driver_data; if (info->dma) { if (info->cmd == READ) { info->dma = !HWIF(drive)->dmaproc(ide_dma_read, drive); } else if (info->cmd == WRITE) { info->dma = !HWIF(drive)->dmaproc(ide_dma_write, drive); } else { printk("ide-cd: DMA set, but not allowed\n"); } } /* Set up the controller registers. */ OUT_BYTE (info->dma, IDE_FEATURE_REG); OUT_BYTE (0, IDE_NSECTOR_REG); OUT_BYTE (0, IDE_SECTOR_REG); OUT_BYTE (xferlen & 0xff, IDE_LCYL_REG); OUT_BYTE (xferlen >> 8 , IDE_HCYL_REG); if (IDE_CONTROL_REG) OUT_BYTE (drive->ctl, IDE_CONTROL_REG); if (info->dma) (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { ide_set_handler (drive, handler, WAIT_CMD, cdrom_timer_expiry); OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ return ide_started; } else { OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ return (*handler) (drive); }} /* end cdrom */{ /* start floppy */ idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_bcount_reg_t bcount; int dma_ok = 0; floppy->pc=pc; /* Set the current packet command */ pc->retries++; pc->actually_transferred=0; /* We haven't transferred any data yet */ pc->current_position=pc->buffer; bcount.all = IDE_MIN(pc->request_transfer, 63 * 1024);#ifdef CONFIG_BLK_DEV_IDEDMA if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) { (void) HWIF(drive)->dmaproc(ide_dma_off, drive); } if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);#endif /* CONFIG_BLK_DEV_IDEDMA */ if (IDE_CONTROL_REG) OUT_BYTE (drive->ctl,IDE_CONTROL_REG); OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG); /* Use PIO/DMA */ OUT_BYTE (bcount.b.high,IDE_BCOUNTH_REG); OUT_BYTE (bcount.b.low,IDE_BCOUNTL_REG); OUT_BYTE (drive->select.all,IDE_SELECT_REG);#ifdef CONFIG_BLK_DEV_IDEDMA if (dma_ok) { /* Begin DMA, if necessary */ set_bit (PC_DMA_IN_PROGRESS, &pc->flags); (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); }#endif /* CONFIG_BLK_DEV_IDEDMA */} /* end floppy */{ /* start tape */ idetape_tape_t *tape = drive->driver_data;#ifdef CONFIG_BLK_DEV_IDEDMA if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) { printk (KERN_WARNING "ide-tape: DMA disabled, reverting to PIO\n"); (void) HWIF(drive)->dmaproc(ide_dma_off, drive); } if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);#endif /* CONFIG_BLK_DEV_IDEDMA */ if (IDE_CONTROL_REG) OUT_BYTE (drive->ctl,IDE_CONTROL_REG); OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG); /* Use PIO/DMA */ OUT_BYTE (bcount.b.high,IDE_BCOUNTH_REG); OUT_BYTE (bcount.b.low,IDE_BCOUNTL_REG); OUT_BYTE (drive->select.all,IDE_SELECT_REG);#ifdef CONFIG_BLK_DEV_IDEDMA if (dma_ok) { /* Begin DMA, if necessary */ set_bit (PC_DMA_IN_PROGRESS, &pc->flags); (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); }#endif /* CONFIG_BLK_DEV_IDEDMA */ if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) { ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL); OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); return ide_started; } else { OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); return idetape_transfer_pc(drive); }} /* end tape */}#endifint 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 + -