int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf) { ide_task_t args; memset(&args, 0, sizeof(ide_task_t)); args.tf.nsect = 0x01; if (drive->media == ide_disk) args.tf.command = ATA_CMD_ID_ATA; else args.tf.command = ATA_CMD_ID_ATAPI; args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; args.data_phase = TASKFILE_IN; return ide_raw_taskfile(drive, &args, buf, 1); }
int taskfile_lib_get_identify(ide_drive_t *drive, u8 *buf) { struct ide_cmd cmd; memset(&cmd, 0, sizeof(cmd)); cmd.tf.nsect = 0x01; if (drive->media == ide_disk) cmd.tf.command = ATA_CMD_ID_ATA; else cmd.tf.command = ATA_CMD_ID_ATAPI; cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; cmd.protocol = ATA_PROT_PIO; return ide_raw_taskfile(drive, &cmd, buf, 1); }
static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd) { struct ide_cmd cmd; struct ide_taskfile *tf = &cmd.tf; memset(&cmd, 0, sizeof(cmd)); tf->feature = sub_cmd; tf->nsect = 0x01; tf->lbam = ATA_SMART_LBAM_PASS; tf->lbah = ATA_SMART_LBAH_PASS; tf->command = ATA_CMD_SMART; cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; cmd.protocol = ATA_PROT_PIO; return ide_raw_taskfile(drive, &cmd, buf, 1); }
int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) { ide_task_request_t *req_task; ide_task_t args; u8 *outbuf = NULL; u8 *inbuf = NULL; u8 *data_buf = NULL; int err = 0; int tasksize = sizeof(struct ide_task_request_s); unsigned int taskin = 0; unsigned int taskout = 0; u16 nsect = 0; char __user *buf = (char __user *)arg; // printk("IDE Taskfile ...\n"); req_task = kzalloc(tasksize, GFP_KERNEL); if (req_task == NULL) return -ENOMEM; if (copy_from_user(req_task, buf, tasksize)) { kfree(req_task); return -EFAULT; } taskout = req_task->out_size; taskin = req_task->in_size; if (taskin > 65536 || taskout > 65536) { err = -EINVAL; goto abort; } if (taskout) { int outtotal = tasksize; outbuf = kzalloc(taskout, GFP_KERNEL); if (outbuf == NULL) { err = -ENOMEM; goto abort; } if (copy_from_user(outbuf, buf + outtotal, taskout)) { err = -EFAULT; goto abort; } } if (taskin) { int intotal = tasksize + taskout; inbuf = kzalloc(taskin, GFP_KERNEL); if (inbuf == NULL) { err = -ENOMEM; goto abort; } if (copy_from_user(inbuf, buf + intotal, taskin)) { err = -EFAULT; goto abort; } } memset(&args, 0, sizeof(ide_task_t)); memcpy(&args.tf_array[0], req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE - 2); memcpy(&args.tf_array[6], req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE); args.data_phase = req_task->data_phase; args.tf_flags = IDE_TFLAG_IO_16BIT | IDE_TFLAG_DEVICE | IDE_TFLAG_IN_TF; if (drive->dev_flags & IDE_DFLAG_LBA48) args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_IN_HOB); if (req_task->out_flags.all) { args.tf_flags |= IDE_TFLAG_FLAGGED; if (req_task->out_flags.b.data) args.tf_flags |= IDE_TFLAG_OUT_DATA; if (req_task->out_flags.b.nsector_hob) args.tf_flags |= IDE_TFLAG_OUT_HOB_NSECT; if (req_task->out_flags.b.sector_hob) args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAL; if (req_task->out_flags.b.lcyl_hob) args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAM; if (req_task->out_flags.b.hcyl_hob) args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAH; if (req_task->out_flags.b.error_feature) args.tf_flags |= IDE_TFLAG_OUT_FEATURE; if (req_task->out_flags.b.nsector) args.tf_flags |= IDE_TFLAG_OUT_NSECT; if (req_task->out_flags.b.sector) args.tf_flags |= IDE_TFLAG_OUT_LBAL; if (req_task->out_flags.b.lcyl) args.tf_flags |= IDE_TFLAG_OUT_LBAM; if (req_task->out_flags.b.hcyl) args.tf_flags |= IDE_TFLAG_OUT_LBAH; } else { args.tf_flags |= IDE_TFLAG_OUT_TF; if (args.tf_flags & IDE_TFLAG_LBA48) args.tf_flags |= IDE_TFLAG_OUT_HOB; } if (req_task->in_flags.b.data) args.tf_flags |= IDE_TFLAG_IN_DATA; switch(req_task->data_phase) { case TASKFILE_MULTI_OUT: if (!drive->mult_count) { /* (hs): give up if multcount is not set */ printk(KERN_ERR "%s: %s Multimode Write " \ "multcount is not set\n", drive->name, __func__); err = -EPERM; goto abort; } /* fall through */ case TASKFILE_OUT: /* fall through */ case TASKFILE_OUT_DMAQ: case TASKFILE_OUT_DMA: nsect = taskout / SECTOR_SIZE; data_buf = outbuf; break; case TASKFILE_MULTI_IN: if (!drive->mult_count) { /* (hs): give up if multcount is not set */ printk(KERN_ERR "%s: %s Multimode Read failure " \ "multcount is not set\n", drive->name, __func__); err = -EPERM; goto abort; } /* fall through */ case TASKFILE_IN: /* fall through */ case TASKFILE_IN_DMAQ: case TASKFILE_IN_DMA: nsect = taskin / SECTOR_SIZE; data_buf = inbuf; break; case TASKFILE_NO_DATA: break; default: err = -EFAULT; goto abort; } if (req_task->req_cmd == IDE_DRIVE_TASK_NO_DATA) nsect = 0; else if (!nsect) { nsect = (args.tf.hob_nsect << 8) | args.tf.nsect; if (!nsect) { printk(KERN_ERR "%s: in/out command without data\n", drive->name); err = -EFAULT; goto abort; } } if (req_task->req_cmd == IDE_DRIVE_TASK_RAW_WRITE) args.tf_flags |= IDE_TFLAG_WRITE; err = ide_raw_taskfile(drive, &args, data_buf, nsect); memcpy(req_task->hob_ports, &args.tf_array[0], HDIO_DRIVE_HOB_HDR_SIZE - 2); memcpy(req_task->io_ports, &args.tf_array[6], HDIO_DRIVE_TASK_HDR_SIZE); if ((args.tf_flags & IDE_TFLAG_FLAGGED_SET_IN_FLAGS) && req_task->in_flags.all == 0) { req_task->in_flags.all = IDE_TASKFILE_STD_IN_FLAGS; if (drive->dev_flags & IDE_DFLAG_LBA48) req_task->in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8); } if (copy_to_user(buf, req_task, tasksize)) { err = -EFAULT; goto abort; } if (taskout) { int outtotal = tasksize; if (copy_to_user(buf + outtotal, outbuf, taskout)) { err = -EFAULT; goto abort; } } if (taskin) { int intotal = tasksize + taskout; if (copy_to_user(buf + intotal, inbuf, taskin)) { err = -EFAULT; goto abort; } } abort: kfree(req_task); kfree(outbuf); kfree(inbuf); // printk("IDE Taskfile ioctl ended. rc = %i\n", err); return err; }
int ide_no_data_taskfile(ide_drive_t *drive, ide_task_t *task) { task->data_phase = TASKFILE_NO_DATA; return ide_raw_taskfile(drive, task, NULL, 0); }
int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) { u8 *buf = NULL; int bufsize = 0, err = 0; u8 args[4], xfer_rate = 0; ide_task_t tfargs; struct ide_taskfile *tf = &tfargs.tf; struct hd_driveid *id = drive->id; if (NULL == (void *) arg) { struct request rq; ide_init_drive_cmd(&rq); rq.cmd_type = REQ_TYPE_ATA_TASKFILE; return ide_do_drive_cmd(drive, &rq, ide_wait); } if (copy_from_user(args, (void __user *)arg, 4)) return -EFAULT; memset(&tfargs, 0, sizeof(ide_task_t)); tf->feature = args[2]; if (args[0] == WIN_SMART) { tf->nsect = args[3]; tf->lbal = args[1]; tf->lbam = 0x4f; tf->lbah = 0xc2; tfargs.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_IN_NSECT; } else { tf->nsect = args[1]; tfargs.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT | IDE_TFLAG_IN_NSECT; } tf->command = args[0]; tfargs.data_phase = args[3] ? TASKFILE_IN : TASKFILE_NO_DATA; if (args[3]) { tfargs.tf_flags |= IDE_TFLAG_IO_16BIT; bufsize = SECTOR_WORDS * 4 * args[3]; buf = kzalloc(bufsize, GFP_KERNEL); if (buf == NULL) return -ENOMEM; } if (tf->command == WIN_SETFEATURES && tf->feature == SETFEATURES_XFER && tf->nsect >= XFER_SW_DMA_0 && (id->dma_ultra || id->dma_mword || id->dma_1word)) { xfer_rate = args[1]; if (tf->nsect > XFER_UDMA_2 && !eighty_ninty_three(drive)) { printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot " "be set\n", drive->name); goto abort; } } err = ide_raw_taskfile(drive, &tfargs, buf, args[3]); args[0] = tf->status; args[1] = tf->error; args[2] = tf->nsect; if (!err && xfer_rate) { /* active-retuning-calls future */ ide_set_xfer_rate(drive, xfer_rate); ide_driveid_update(drive); } abort: if (copy_to_user((void __user *)arg, &args, 4)) err = -EFAULT; if (buf) { if (copy_to_user((void __user *)(arg + 4), buf, bufsize)) err = -EFAULT; kfree(buf); } return err; }