/* Flush the write buffer */ static int flush_write_buffer(int dev) { int offset, transfer, blks; int result; unsigned char cmd[10]; Scsi_Cmnd *SCpnt; #if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS if (scsi_tapes[dev].buffer->writing) { write_behind_check(dev); if (scsi_tapes[dev].buffer->last_result) { #ifdef DEBUG printk("st%d: Async write error %x.\n", dev, scsi_tapes[dev].buffer->last_result); #endif return (-EIO); } } #endif result = 0; if (scsi_tapes[dev].dirty==1) { SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1); offset = scsi_tapes[dev].buffer->buffer_bytes; transfer = ((offset + scsi_tapes[dev].block_size - 1) / scsi_tapes[dev].block_size) * scsi_tapes[dev].block_size; #ifdef DEBUG printk("st%d: Flushing %d bytes.\n", dev, transfer); #endif memset(scsi_tapes[dev].buffer->b_data + offset, 0, transfer - offset); SCpnt->sense_buffer[0] = 0; memset(cmd, 0, 10); cmd[0] = WRITE_6; cmd[1] = 1; blks = transfer / scsi_tapes[dev].block_size; cmd[2] = blks >> 16; cmd[3] = blks >> 8; cmd[4] = blks; SCpnt->request.dev = dev; scsi_do_cmd (SCpnt, (void *) cmd, scsi_tapes[dev].buffer->b_data, transfer, st_sleep_done, ST_TIMEOUT, MAX_RETRIES); if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting ); if (SCpnt->result != 0) { printk("st%d: Error on flush:\n", dev); #ifdef DEBUG st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer); #endif result = (-EIO); } else { scsi_tapes[dev].dirty = 0; scsi_tapes[dev].buffer->buffer_bytes = 0; } SCpnt->request.dev = -1; /* Mark as not busy */ }
static int ioctl_internal_command(Scsi_Device *dev, char * cmd, int timeout, int retries) { int result; Scsi_Cmnd * SCpnt; SCpnt = allocate_device(NULL, dev, 1); { struct semaphore sem = MUTEX_LOCKED; SCpnt->request.sem = &sem; scsi_do_cmd(SCpnt, cmd, NULL, 0, scsi_ioctl_done, timeout, retries); down(&sem); } if(driver_byte(SCpnt->result) != 0) switch(SCpnt->sense_buffer[2] & 0xf) { case ILLEGAL_REQUEST: if(cmd[0] == ALLOW_MEDIUM_REMOVAL) dev->lockable = 0; else printk("SCSI device (ioctl) reports ILLEGAL REQUEST.\n"); break; case NOT_READY: /* This happens if there is no disc in drive */ if(dev->removable){ printk(KERN_INFO "Device not ready. Make sure there is a disc in the drive.\n"); break; }; case UNIT_ATTENTION: if (dev->removable){ dev->changed = 1; SCpnt->result = 0; /* This is no longer considered an error */ printk(KERN_INFO "Disc change detected.\n"); break; }; default: /* Fall through for non-removable media */ printk("SCSI error: host %d id %d lun %d return code = %x\n", dev->host->host_no, dev->id, dev->lun, SCpnt->result); printk("\tSense class %x, sense error %x, extended sense %x\n", sense_class(SCpnt->sense_buffer[0]), sense_error(SCpnt->sense_buffer[0]), SCpnt->sense_buffer[2] & 0xf); }; result = SCpnt->result; SCpnt->request.rq_status = RQ_INACTIVE; if (!SCpnt->device->was_reset && SCpnt->device->scsi_request_fn) (*SCpnt->device->scsi_request_fn)(); wake_up(&SCpnt->device->device_wait); return result; }
static int ioctl_internal_command(Scsi_Device *dev, char * cmd) { int host, result; Scsi_Cmnd * SCpnt; host = dev->host_no; SCpnt = allocate_device(NULL, dev->index, 1); scsi_do_cmd(SCpnt, cmd, NULL, 0, scsi_ioctl_done, MAX_TIMEOUT, MAX_RETRIES); if (SCpnt->request.dev != 0xfffe){ SCpnt->request.waiting = current; current->state = TASK_UNINTERRUPTIBLE; while (SCpnt->request.dev != 0xfffe) schedule(); }; if(driver_byte(SCpnt->result) != 0) switch(SCpnt->sense_buffer[2] & 0xf) { case ILLEGAL_REQUEST: if(cmd[0] == ALLOW_MEDIUM_REMOVAL) dev->lockable = 0; else printk("SCSI device (ioctl) reports ILLEGAL REQUEST.\n"); break; case NOT_READY: /* This happens if there is no disc in drive */ if(dev->removable){ printk("Device not ready. Make sure there is a disc in the drive.\n"); break; }; case UNIT_ATTENTION: if (dev->removable){ dev->changed = 1; SCpnt->result = 0; /* This is no longer considered an error */ printk("Disc change detected.\n"); break; }; default: /* Fall through for non-removable media */ printk("SCSI CD error: host %d id %d lun %d return code = %x\n", dev->host_no, dev->id, dev->lun, SCpnt->result); printk("\tSense class %x, sense error %x, extended sense %x\n", sense_class(SCpnt->sense_buffer[0]), sense_error(SCpnt->sense_buffer[0]), SCpnt->sense_buffer[2] & 0xf); }; result = SCpnt->result; SCpnt->request.dev = -1; /* Mark as not busy */ wake_up(&scsi_devices[SCpnt->index].device_wait); return result; }
static int do_ioctl(int target, unsigned char * sr_cmd, void * buffer, unsigned buflength) { Scsi_Cmnd * SCpnt; int result; SCpnt = allocate_device(NULL, scsi_CDs[target].device->index, 1); scsi_do_cmd(SCpnt, (void *) sr_cmd, buffer, buflength, sr_ioctl_done, IOCTL_TIMEOUT, IOCTL_RETRIES); if (SCpnt->request.dev != 0xfffe) { SCpnt->request.waiting = current; current->state = TASK_UNINTERRUPTIBLE; while (SCpnt->request.dev != 0xfffe) schedule(); }; result = SCpnt->result; /* Minimal error checking. Ignore cases we know about, and report the rest. */ if(driver_byte(result) != 0) switch(SCpnt->sense_buffer[2] & 0xf) { case UNIT_ATTENTION: scsi_CDs[target].device->changed = 1; printk("Disc change detected.\n"); break; case NOT_READY: /* This happens if there is no disc in drive */ printk("CDROM not ready. Make sure there is a disc in the drive.\n"); break; case ILLEGAL_REQUEST: printk("CDROM (ioctl) reports ILLEGAL REQUEST.\n"); break; default: printk("SCSI CD error: host %d id %d lun %d return code = %03x\n", scsi_CDs[target].device->host_no, scsi_CDs[target].device->id, scsi_CDs[target].device->lun, result); printk("\tSense class %x, sense error %x, extended sense %x\n", sense_class(SCpnt->sense_buffer[0]), sense_error(SCpnt->sense_buffer[0]), SCpnt->sense_buffer[2] & 0xf); }; result = SCpnt->result; SCpnt->request.dev = -1; /* Deallocate */ wake_up(&scsi_devices[SCpnt->index].device_wait); /* Wake up a process waiting for device*/ return result; }
static int ntrig_usbhid_probe(struct hid_device *hdev, const struct hid_device_id *id) { char phys_path[256]; int ret; struct ntrig_usbhid_data* nd; struct usb_interface* intf; struct usb_device* dev; struct usb_host_interface* interface; struct usb_endpoint_descriptor* endpoint; struct _ntrig_dev_ncp_func ncp_func; struct _ntrig_dev_hid_func hid_func; intf = to_usb_interface(hdev->dev.parent); dev = interface_to_usbdev(intf); interface= intf->cur_altsetting; endpoint = &interface->endpoint[0].desc; nd = kmalloc(sizeof(struct ntrig_usbhid_data), GFP_KERNEL); if (!nd) { dev_err(&hdev->dev, "cannot allocate N-Trig data\n"); return -ENOMEM; } if(DTRG_NO_ERROR != allocate_device(&nd->ntrig_dispatcher)){ dev_err(&hdev->dev, "cannot allocate N-Trig dispatcher\n"); return DTRG_FAILED; } hid_set_drvdata(hdev, nd); ret = hid_parse(hdev); if (ret) { dev_err(&hdev->dev, "parse failed, error code=%d\n", ret); goto err_free; } if (NCP_EP_ADDRESS == endpoint->bEndpointAddress) { ret = hid_hw_start(hdev, ~HID_QUIRK_MULTI_INPUT); if (ret) { dev_err(&hdev->dev, "hw start failed NCP, error code=%d\n", ret); goto err_free; } /* register device in the dispatcher - set device and function pointers for ncp set sensor id in the device data structure */ // NOTE: registration of ncp_read, ncp_write & dev is linked. // It's the resposibility of this function to set these parameters together ncp_func.dev = (void *) hdev; ncp_func.read = NTRIGReadNCP; ncp_func.write = NTRIGWriteNCP; nd->sensor_id = RegNtrigDispatcher(TYPE_BUS_USB_HID, hdev->uniq, &ncp_func, NULL); // TODO: define behavior in case of fail if (nd->sensor_id == DTRG_FAILED) { ntrig_dbg("%s: Cannot register device to dispatcher\n", __FUNCTION__); goto err_free; } ntrig_dbg("%s NCP dev registered with dispatcher, bus_id = %s, sensor_id = %d\n", __FUNCTION__, hdev->uniq, nd->sensor_id); return 0; } else { ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); if (ret) { dev_err(&hdev->dev, "hw start failed TOUCH, error code=%d\n", ret); goto err_free; } ret = ntrig_usbhid_send_report(hdev, REPORTID_DRIVER_ALIVE, NULL, 0); if (ret < 0) { dev_err(&hdev->dev, "send set feature failed, error code=%d\n", ret); goto err_free; } /* register device in the dispatcher - no need to set device and function pointers for touch events set sensor id in the device data structure */ // NOTE: registration of ncp_read, ncp_write & dev is linked. // It's the resposibility of this function to set these parameters together hid_func.dev = (void *)hdev; hid_func.read = NTRIGReadSensor; hid_func.write = NTRIGWriteSensor; nd->sensor_id = RegNtrigDispatcher(TYPE_BUS_USB_HID, hdev->uniq, NULL, &hid_func); // TODO: define behavior in case of fail if (nd->sensor_id == DTRG_FAILED) { ntrig_dbg("%s: Cannot register device to dispatcher\n", __FUNCTION__); goto err_free; } ntrig_dbg("%s HID dev registered with dispatcher, bus_id = %s, sensor_id = %d\n", __FUNCTION__, hdev->uniq, nd->sensor_id); } /** * Create additional single touch queue */ usb_make_path(dev, phys_path, sizeof(phys_path)); strlcat(phys_path, "/input0", sizeof(phys_path)); nd->ntrig_dispatcher->phys = phys_path; nd->ntrig_dispatcher->name = "USBHID"; nd->ntrig_dispatcher->pressure_min= 0; nd->ntrig_dispatcher->pressure_max= 0xFF; create_single_touch(nd->ntrig_dispatcher, nd->sensor_id); create_multi_touch (nd->ntrig_dispatcher, nd->sensor_id); nd->battery_status = PEN_BUTTON_BATTERY_NOT_AVAILABLE; ntrig_dbg("Iside %s, bus_id = %d, name = %s, phys = %s, uniq = %s\n", __FUNCTION__, hdev->bus, hdev->name, hdev->phys, hdev->uniq ); ntrig_dbg("End of %s\n", __FUNCTION__); return DTRG_NO_ERROR; err_free: ntrig_dbg("Error End of %s\n", __FUNCTION__); remove_device(&nd->ntrig_dispatcher); kfree(nd); return DTRG_FAILED; }
static int ioctl_command(Scsi_Device *dev, void *buffer) { char * buf; char cmd[12]; char * cmd_in; Scsi_Cmnd * SCpnt; unsigned char opcode; int inlen, outlen, cmdlen; int needed; int result; if (!buffer) return -EINVAL; inlen = get_fs_long((unsigned long *) buffer); outlen = get_fs_long( ((unsigned long *) buffer) + 1); cmd_in = (char *) ( ((int *)buffer) + 2); opcode = get_fs_byte(cmd_in); needed = (inlen > outlen ? inlen : outlen); if(needed){ needed = (needed + 511) & ~511; if (needed > MAX_BUF) needed = MAX_BUF; buf = (char *) scsi_malloc(needed); if (!buf) return -ENOMEM; } else buf = NULL; memcpy_fromfs ((void *) cmd, cmd_in, cmdlen = COMMAND_SIZE (opcode)); memcpy_fromfs ((void *) buf, (void *) (cmd_in + cmdlen), inlen > MAX_BUF ? MAX_BUF : inlen); cmd[1] = ( cmd[1] & 0x1f ) | (dev->lun << 5); #ifndef DEBUG_NO_CMD SCpnt = allocate_device(NULL, dev->index, 1); scsi_do_cmd(SCpnt, cmd, buf, needed, scsi_ioctl_done, MAX_TIMEOUT, MAX_RETRIES); if (SCpnt->request.dev != 0xfffe){ SCpnt->request.waiting = current; current->state = TASK_UNINTERRUPTIBLE; while (SCpnt->request.dev != 0xfffe) schedule(); }; /* If there was an error condition, pass the info back to the user. */ if(SCpnt->result) { result = verify_area(VERIFY_WRITE, cmd_in, sizeof(SCpnt->sense_buffer)); if (result) return result; memcpy_tofs((void *) cmd_in, SCpnt->sense_buffer, sizeof(SCpnt->sense_buffer)); } else { result = verify_area(VERIFY_WRITE, cmd_in, (outlen > MAX_BUF) ? MAX_BUF : outlen); if (result) return result; memcpy_tofs ((void *) cmd_in, buf, (outlen > MAX_BUF) ? MAX_BUF : outlen); }; result = SCpnt->result; SCpnt->request.dev = -1; /* Mark as not busy */ if (buf) scsi_free(buf, needed); wake_up(&scsi_devices[SCpnt->index].device_wait); return result; #else { int i; printk("scsi_ioctl : device %d. command = ", dev->id); for (i = 0; i < 12; ++i) printk("%02x ", cmd[i]); printk("\nbuffer ="); for (i = 0; i < 20; ++i) printk("%02x ", buf[i]); printk("\n"); printk("inlen = %d, outlen = %d, cmdlen = %d\n", inlen, outlen, cmdlen); printk("buffer = %d, cmd_in = %d\n", buffer, cmd_in); } return 0; #endif }
/* * This interface is depreciated - users should use the scsi generics * interface instead, as this is a more flexible approach to performing * generic SCSI commands on a device. */ static int ioctl_command(Scsi_Device *dev, void *buffer) { char * buf; unsigned char cmd[12]; char * cmd_in; Scsi_Cmnd * SCpnt; unsigned char opcode; int inlen, outlen, cmdlen; int needed, buf_needed; int timeout, retries, result; if (!buffer) return -EINVAL; /* * Verify that we can read at least this much. */ result = verify_area(VERIFY_READ, buffer, 2*sizeof(long) + 1); if (result) return result; /* * The structure that we are passed should look like: * * struct sdata { * unsigned int inlen; * unsigned int outlen; * unsigned char cmd[]; # However many bytes are used for cmd. * unsigned char data[]; * }; */ inlen = get_user((unsigned int *) buffer); outlen = get_user( ((unsigned int *) buffer) + 1); /* * We do not transfer more than MAX_BUF with this interface. * If the user needs to transfer more data than this, they * should use scsi_generics instead. */ if( inlen > MAX_BUF ) return -EINVAL; if( outlen > MAX_BUF ) return -EINVAL; cmd_in = (char *) ( ((int *)buffer) + 2); opcode = get_user(cmd_in); needed = buf_needed = (inlen > outlen ? inlen : outlen); if(buf_needed){ buf_needed = (buf_needed + 511) & ~511; if (buf_needed > MAX_BUF) buf_needed = MAX_BUF; buf = (char *) scsi_malloc(buf_needed); if (!buf) return -ENOMEM; memset(buf, 0, buf_needed); } else buf = NULL; /* * Obtain the command from the user's address space. */ cmdlen = COMMAND_SIZE(opcode); result = verify_area(VERIFY_READ, cmd_in, cmdlen + inlen > MAX_BUF ? MAX_BUF : inlen); if (result) return result; memcpy_fromfs ((void *) cmd, cmd_in, cmdlen); /* * Obtain the data to be sent to the device (if any). */ memcpy_fromfs ((void *) buf, (void *) (cmd_in + cmdlen), inlen); /* * Set the lun field to the correct value. */ cmd[1] = ( cmd[1] & 0x1f ) | (dev->lun << 5); switch (opcode) { case FORMAT_UNIT: timeout = FORMAT_UNIT_TIMEOUT; retries = 1; break; case START_STOP: timeout = START_STOP_TIMEOUT; retries = NORMAL_RETRIES; break; case MOVE_MEDIUM: timeout = MOVE_MEDIUM_TIMEOUT; retries = NORMAL_RETRIES; break; case READ_ELEMENT_STATUS: timeout = READ_ELEMENT_STATUS_TIMEOUT; retries = NORMAL_RETRIES; break; default: timeout = NORMAL_TIMEOUT; retries = NORMAL_RETRIES; break; } #ifndef DEBUG_NO_CMD SCpnt = allocate_device(NULL, dev, 1); { struct semaphore sem = MUTEX_LOCKED; SCpnt->request.sem = &sem; scsi_do_cmd(SCpnt, cmd, buf, needed, scsi_ioctl_done, timeout, retries); down(&sem); } /* * If there was an error condition, pass the info back to the user. */ if(SCpnt->result) { result = verify_area(VERIFY_WRITE, cmd_in, sizeof(SCpnt->sense_buffer)); if (result) return result; memcpy_tofs((void *) cmd_in, SCpnt->sense_buffer, sizeof(SCpnt->sense_buffer)); } else { result = verify_area(VERIFY_WRITE, cmd_in, outlen); if (result) return result; memcpy_tofs ((void *) cmd_in, buf, outlen); } result = SCpnt->result; SCpnt->request.rq_status = RQ_INACTIVE; if (buf) scsi_free(buf, buf_needed); if(SCpnt->device->scsi_request_fn) (*SCpnt->device->scsi_request_fn)(); wake_up(&SCpnt->device->device_wait); return result; #else { int i; printk("scsi_ioctl : device %d. command = ", dev->id); for (i = 0; i < 12; ++i) printk("%02x ", cmd[i]); printk("\nbuffer ="); for (i = 0; i < 20; ++i) printk("%02x ", buf[i]); printk("\n"); printk("inlen = %d, outlen = %d, cmdlen = %d\n", inlen, outlen, cmdlen); printk("buffer = %d, cmd_in = %d\n", buffer, cmd_in); } return 0; #endif }