-
- dprintk(KERN_NOTICE "opcode = %d table_id = %d parameter_id = %d parameter_size_bytes = %d\n", ioctl->opcode, ioctl->table_id, ioctl->parameter_id, ioctl->parameter_size_bytes);
- opcode = ioctl->opcode;
-
- switch (opcode) {
- case TW_OP_NOP:
- dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_NOP.\n");
- command_packet->byte0.opcode = TW_OP_NOP;
- break;
- case TW_OP_GET_PARAM:
- dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_GET_PARAM.\n");
- command_packet->byte0.opcode = TW_OP_GET_PARAM;
- command_packet->byte3.unit = ioctl->unit_index;
- param->table_id = ioctl->table_id;
- param->parameter_id = ioctl->parameter_id;
- param->parameter_size_bytes = ioctl->parameter_size_bytes;
- tw_dev->ioctl_size[request_id] = ioctl->parameter_size_bytes;
- dprintk(KERN_NOTICE "table_id = %d parameter_id = %d parameter_size_bytes %d\n", param->table_id, param->parameter_id, param->parameter_size_bytes);
- break;
- case TW_OP_SET_PARAM:
- dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_SET_PARAM: table_id = %d, parameter_id = %d, parameter_size_bytes = %d.\n",
- ioctl->table_id, ioctl->parameter_id, ioctl->parameter_size_bytes);
- if (ioctl->data != NULL) {
- command_packet->byte0.opcode = TW_OP_SET_PARAM;
- param->table_id = ioctl->table_id;
- param->parameter_id = ioctl->parameter_id;
- param->parameter_size_bytes = ioctl->parameter_size_bytes;
- memcpy(param->data, ioctl->data, ioctl->parameter_size_bytes);
- break;
- } else {
- printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n");
- return 1;
- }
- case TW_OP_AEN_LISTEN:
- dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_AEN_LISTEN.\n");
- if (tw_dev->aen_head == tw_dev->aen_tail) {
- /* aen queue empty */
- dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): Aen queue empty.\n");
- tw_aen_code = TW_AEN_QUEUE_EMPTY;
- memcpy(tw_dev->srb[request_id]->request_buffer, &tw_aen_code, ioctl->parameter_size_bytes);
- } else {
- /* Copy aen queue entry to request buffer */
- dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): Returning aen 0x%x\n", tw_dev->aen_queue[tw_dev->aen_head]);
- tw_aen_code = tw_dev->aen_queue[tw_dev->aen_head];
- memcpy(tw_dev->srb[request_id]->request_buffer, &tw_aen_code, ioctl->parameter_size_bytes);
- if (tw_dev->aen_head == TW_Q_LENGTH - 1) {
- tw_dev->aen_head = TW_Q_START;
- } else {
- tw_dev->aen_head = tw_dev->aen_head + 1;
- }
- }
- tw_dev->state[request_id] = TW_S_COMPLETED;
- tw_state_request_finish(tw_dev, request_id);
- tw_dev->srb[request_id]->result = (DID_OK << 16);
- tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
- return 0;
- case TW_ATA_PASSTHRU:
- if (ioctl->data != NULL) {
- memcpy(command_packet, ioctl->data, sizeof(TW_Command));
- command_packet->request_id = request_id;
- } else {
- printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n");
- return 1;
- }
-
- passthru = (TW_Passthru *)tw_dev->command_packet_virtual_address[request_id];
- /* Don't load sg_list for non-data ATA cmds */
- if ((passthru->param != 0) && (passthru->param != 0x8)) {
- passthru->sg_list[0].length = passthru->sector_count*512;
- if (passthru->sg_list[0].length > TW_MAX_PASSTHRU_BYTES) {
- printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Passthru size (%d) too big.\n", passthru->sg_list[0].length);
- return 1;
- }
- passthru->sg_list[0].address = tw_dev->alignment_physical_address[request_id];
- }
- tw_post_command_packet(tw_dev, request_id);
- return 0;
- case TW_CMD_PACKET:
- dprintk(KERN_WARNING "3w-xxxx: tw_ioctl(): caught TW_CMD_PACKET.\n");
- if (ioctl->data != NULL) {
- memcpy(command_packet, ioctl->data, sizeof(TW_Command));
- command_packet->request_id = request_id;
- tw_post_command_packet(tw_dev, request_id);
- return 0;
- } else {
- printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n");
- return 1;
- }
- case TW_CMD_PACKET_WITH_DATA:
- dprintk(KERN_WARNING "3w-xxxx: tw_ioctl(): caught TW_CMD_PACKET_WITH_DATA.\n");
- command_save = (TW_Command *)tw_dev->alignment_virtual_address[request_id];
- if (command_save == NULL) {
- printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad alignment virtual address.\n", tw_dev->host->host_no);
- return 1;
- }
- if (ioctl->data != NULL) {
- /* Copy down the command packet */
- memcpy(command_packet, ioctl->data, sizeof(TW_Command));
- memcpy(command_save, ioctl->data, sizeof(TW_Command));
- command_packet->request_id = request_id;
-
- /* Now deal with the two possible sglists */
- if (command_packet->byte0.sgl_offset == 2) {
- use_sg = command_packet->size - 3;
- for (i=0;i<use_sg;i++)
- total_bytes+=command_packet->byte8.param.sgl[i].length;
- tw_dev->ioctl_data[request_id] = pci_alloc_consistent(tw_dev->tw_pci_dev, total_bytes, &dma_handle);
-
- if (!tw_dev->ioctl_data[request_id]) {
- printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): pci_alloc_consistent() failed for request_id %d.\n", tw_dev->host->host_no, request_id);
- return 1;
- }
-
- /* Copy param sglist into the kernel */
- data_ptr = tw_dev->ioctl_data[request_id];
- for (i=0;i<use_sg;i++) {
- if (command_packet->byte8.param.sgl[i].address != 0) {
- error = copy_from_user(data_ptr, (void *)(unsigned long)command_packet->byte8.param.sgl[i].address, command_packet->byte8.param.sgl[i].length);
- if (error) {
- dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying param sglist from userspace.\n", tw_dev->host->host_no);
- goto tw_ioctl_bail;
- }
- } else {
- printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad param sgl address.\n", tw_dev->host->host_no);
- tw_dev->srb[request_id]->result = (DID_RESET << 16);
- goto tw_ioctl_bail;
- }
- data_ptr+=command_packet->byte8.param.sgl[i].length;
- }
- command_packet->size = 4;
- command_packet->byte8.param.sgl[0].address = dma_handle;
- command_packet->byte8.param.sgl[0].length = total_bytes;
- }
- if (command_packet->byte0.sgl_offset == 3) {
- use_sg = command_packet->size - 4;
- for (i=0;i<use_sg;i++)
- total_bytes+=command_packet->byte8.io.sgl[i].length;
- tw_dev->ioctl_data[request_id] = pci_alloc_consistent(tw_dev->tw_pci_dev, total_bytes, &dma_handle);
-
- if (!tw_dev->ioctl_data[request_id]) {
- printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): pci_alloc_consistent() failed for request_id %d.\n", tw_dev->host->host_no, request_id);
- return 1;
- }
- if (command_packet->byte0.opcode == TW_OP_WRITE) {
- /* Copy io sglist into the kernel */
- data_ptr = tw_dev->ioctl_data[request_id];
- for (i=0;i<use_sg;i++) {
- if (command_packet->byte8.io.sgl[i].address != 0) {
- error = copy_from_user(data_ptr, (void *)(unsigned long)command_packet->byte8.io.sgl[i].address, command_packet->byte8.io.sgl[i].length);
- if (error) {
- dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying io sglist from userspace.\n", tw_dev->host->host_no);
- goto tw_ioctl_bail;
- }
- } else {
- printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad io sgl address.\n", tw_dev->host->host_no);
- tw_dev->srb[request_id]->result = (DID_RESET << 16);
- goto tw_ioctl_bail;
- }
- data_ptr+=command_packet->byte8.io.sgl[i].length;
- }
- }
- command_packet->size = 5;
- command_packet->byte8.io.sgl[0].address = dma_handle;
- command_packet->byte8.io.sgl[0].length = total_bytes;
- }
-
- spin_unlock(&tw_dev->tw_lock);
- spin_unlock_irq(tw_dev->host->host_lock);
-
- set_bit(TW_IN_IOCTL, &tw_dev->flags);
-
- /* Finally post the command packet */
- tw_post_command_packet(tw_dev, request_id);
- posted = 1;
- do_gettimeofday(&before);
-
- tw_ioctl_retry:
- mdelay(TW_IOCTL_WAIT_TIME);
- if (test_bit(TW_IN_IOCTL, &tw_dev->flags)) {
- do_gettimeofday(&timeout);
- if (before.tv_sec + TW_IOCTL_TIMEOUT < timeout.tv_sec) {
- spin_lock_irq(tw_dev->host->host_lock);
- spin_lock(&tw_dev->tw_lock);
- goto tw_ioctl_bail;
- } else {
- goto tw_ioctl_retry;
- }
- }
-
- spin_lock_irq(tw_dev->host->host_lock);
- spin_lock(&tw_dev->tw_lock);
-
- if (signal_pending(current)) {
- dprintk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Signal pending, aborting ioctl().\n", tw_dev->host->host_no);
- tw_dev->srb[request_id]->result = (DID_OK << 16);
- goto tw_ioctl_bail;
- }
-
- tw_dev->srb[request_id]->result = (DID_OK << 16);
- /* Now copy up the param or io sglist to userspace */
- if (command_packet->byte0.sgl_offset == 2) {
- use_sg = command_save->size - 3;
- data_ptr = tw_dev->ioctl_data[request_id];
- for (i=0;i<use_sg;i++) {
- if (command_save->byte8.param.sgl[i].address != 0) {
- error = copy_to_user((void *)(unsigned long)command_save->byte8.param.sgl[i].address, data_ptr, command_save->byte8.param.sgl[i].length);
- if (error) {
- dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying param sglist to userspace.\n", tw_dev->host->host_no);
- goto tw_ioctl_bail;
- }
- dprintk(KERN_WARNING "3w-xxxx: scsi%d: Copied %ld bytes to pid %d.\n", tw_dev->host->host_no, command_save->byte8.param.sgl[i].length, current->pid);
- data_ptr+=command_save->byte8.param.sgl[i].length;
- } else {
- printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad param sgl address.\n", tw_dev->host->host_no);
- tw_dev->srb[request_id]->result = (DID_RESET << 16);
- goto tw_ioctl_bail;
- }
- }
- }
- if (command_packet->byte0.sgl_offset == 3) {
- use_sg = command_save->size - 4;
- if (command_packet->byte0.opcode == TW_OP_READ) {
- data_ptr = tw_dev->ioctl_data[request_id];
- for(i=0;i<use_sg;i++) {
- if (command_save->byte8.io.sgl[i].address != 0) {
- error = copy_to_user((void *)(unsigned long)command_save->byte8.io.sgl[i].address, data_ptr, command_save->byte8.io.sgl[i].length);
- if (error) {
- dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying io sglist to userspace.\n", tw_dev->host->host_no);
- goto tw_ioctl_bail;
- }
- dprintk(KERN_WARNING "3w-xxxx: scsi%d: Copied %ld bytes to pid %d.\n", tw_dev->host->host_no, command_save->byte8.io.sgl[i].length, current->pid);
- data_ptr+=command_save->byte8.io.sgl[i].length;
- } else {
- printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad io sgl address.\n", tw_dev->host->host_no);
- tw_dev->srb[request_id]->result = (DID_RESET << 16);
- goto tw_ioctl_bail;
- }
- }
- }
- }
-
- tw_ioctl_bail:
-
- /* Free up sglist memory */
- if (tw_dev->ioctl_data[request_id])
- pci_free_consistent(tw_dev->tw_pci_dev, total_bytes, tw_dev->ioctl_data[request_id], dma_handle);
- else
- printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Error freeing ioctl data.\n", tw_dev->host->host_no);
-
- /* Now complete the io */
- tw_dev->state[request_id] = TW_S_COMPLETED;
- tw_state_request_finish(tw_dev, request_id);
- if (posted)
- tw_dev->posted_request_count--;
- tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
- return 0;
- } else {
- printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n");
- return 1;
- }
- default:
- dprintk(KERN_WARNING "3w-xxxx: Unknown ioctl 0x%x.\n", opcode);
- tw_dev->state[request_id] = TW_S_COMPLETED;
- tw_state_request_finish(tw_dev, request_id);
- tw_dev->srb[request_id]->result = (DID_OK << 16);
- tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
- return 0;
- }
-
- param_value = tw_dev->alignment_physical_address[request_id];
- if (param_value == 0) {
- printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Bad alignment physical address.\n");
- tw_dev->state[request_id] = TW_S_COMPLETED;
- tw_state_request_finish(tw_dev, request_id);
- tw_dev->srb[request_id]->result = (DID_OK << 16);
- tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
- }
-
- command_packet->byte8.param.sgl[0].address = param_value;
- command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
-
- command_packet->byte0.sgl_offset = 2;
- command_packet->size = 4;
- command_packet->request_id = request_id;
- command_packet->byte3.host_id = 0;
- command_packet->status = 0;
- command_packet->flags = 0;
- command_packet->byte6.parameter_count = 1;