📄 hpusbscsi.c
字号:
struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->host->hostdata[0]); usb_urb_callback usb_callback; int res; spin_unlock_irq(&io_request_lock); /* we don't answer for anything but our single device on any faked host controller */ if ( srb->device->lun || srb->device->id || srb->device->channel ) { srb->result = DID_BAD_TARGET; callback(srb); goto out; } /* Now we need to decide which callback to give to the urb we send the command with */ if (!srb->bufflen) { if (srb->cmnd[0] == REQUEST_SENSE){ /* the usual buffer is not used, needs a special case */ hpusbscsi->current_data_pipe = usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in); usb_callback = request_sense_callback; } else { usb_callback = simple_command_callback; } } else { if (srb->use_sg) { usb_callback = scatter_gather_callback; hpusbscsi->fragment = 0; } else { usb_callback = simple_payload_callback; } /* Now we find out which direction data is to be transfered in */ hpusbscsi->current_data_pipe = DIRECTION_IS_IN(srb->cmnd[0]) ? usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in) : usb_sndbulkpipe(hpusbscsi->dev, hpusbscsi->ep_out) ; } PDEBUG(2, "state= %s", states[hpusbscsi->state]); if (hpusbscsi->state != HP_STATE_FREE) { printk(KERN_CRIT"hpusbscsi - Ouch: queueing violation!\n"); return 1; /* This must not happen */ } /* We zero the sense buffer to avoid confusing user space */ memset(srb->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); hpusbscsi->state = HP_STATE_BEGINNING; PDEBUG(2, "state= %s", states[hpusbscsi->state]); /* We prepare the urb for writing out the scsi command */ FILL_BULK_URB( &hpusbscsi->dataurb, hpusbscsi->dev, usb_sndbulkpipe(hpusbscsi->dev,hpusbscsi->ep_out), srb->cmnd, srb->cmd_len, usb_callback, hpusbscsi ); hpusbscsi->scallback = callback; hpusbscsi->srb = srb; if (hpusbscsi->dev == NULL) { srb->result = DID_ERROR; callback(srb); goto out; } res = usb_submit_urb(&hpusbscsi->dataurb); if (res) { hpusbscsi->state = HP_STATE_FREE; PDEBUG(2, "state= %s", states[hpusbscsi->state]); srb->result = DID_ERROR; callback(srb); }out: spin_lock_irq(&io_request_lock); return 0;}static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb){ struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->host->hostdata[0]); PDEBUG(1, "SCSI reset requested"); //usb_reset_device(hpusbscsi->dev); //PDEBUG(1, "SCSI reset completed"); hpusbscsi->state = HP_STATE_FREE; return 0;}static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb){ struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->host->hostdata[0]); PDEBUG(1, "Request is canceled"); spin_unlock_irq(&io_request_lock); usb_unlink_urb(&hpusbscsi->dataurb); hpusbscsi->state = HP_STATE_FREE; spin_lock_irq(&io_request_lock); return SCSI_ABORT_PENDING;}/* usb interrupt handlers - they are all running IN INTERRUPT ! */static void handle_usb_error (struct hpusbscsi *hpusbscsi){ if (hpusbscsi->scallback != NULL) { hpusbscsi->srb->result = DID_ERROR; hpusbscsi->scallback(hpusbscsi->srb); } hpusbscsi->state = HP_STATE_FREE;}static void control_interrupt_callback (struct urb *u){ struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context; u8 scsi_state; PDEBUG(1, "Getting status byte %d",hpusbscsi->scsi_state_byte); if(u->status < 0) { if (hpusbscsi->state != HP_STATE_FREE) handle_usb_error(hpusbscsi); return; } scsi_state = hpusbscsi->scsi_state_byte; if (hpusbscsi->state != HP_STATE_ERROR) { hpusbscsi->srb->result &= SCSI_ERR_MASK; hpusbscsi->srb->result |= scsi_state; } if (scsi_state == CHECK_CONDITION << 1) { if (hpusbscsi->state == HP_STATE_WAIT) { issue_request_sense(hpusbscsi); } else { /* we request sense after an eventual data transfer */ hpusbscsi->state = HP_STATE_ERROR; } } if (hpusbscsi->scallback != NULL && hpusbscsi->state == HP_STATE_WAIT && scsi_state != CHECK_CONDITION <<1) /* we do a callback to the scsi layer if and only if all data has been transfered */ hpusbscsi->scallback(hpusbscsi->srb); PDEBUG(2, "state= %s", states[hpusbscsi->state]); switch (hpusbscsi->state) { case HP_STATE_WAIT: hpusbscsi->state = HP_STATE_FREE; PDEBUG(2, "state= %s", states[hpusbscsi->state]); break; case HP_STATE_WORKING: case HP_STATE_BEGINNING: hpusbscsi->state = HP_STATE_PREMATURE; PDEBUG(2, "state= %s", states[hpusbscsi->state]); break; case HP_STATE_ERROR: break; default: printk(KERN_ERR"hpusbscsi: Unexpected status report.\n"); PDEBUG(2, "state= %s", states[hpusbscsi->state]); hpusbscsi->state = HP_STATE_FREE; PDEBUG(2, "state= %s", states[hpusbscsi->state]); break; }}static void simple_command_callback(struct urb *u){ struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context; if (u->status<0) { handle_usb_error(hpusbscsi); return; } PDEBUG(2, "state= %s", states[hpusbscsi->state]); if (hpusbscsi->state != HP_STATE_PREMATURE) { PDEBUG(2, "state= %s", states[hpusbscsi->state]); hpusbscsi->state = HP_STATE_WAIT; } else { if (hpusbscsi->scallback != NULL) hpusbscsi->scallback(hpusbscsi->srb); hpusbscsi->state = HP_STATE_FREE; PDEBUG(2, "state= %s", states[hpusbscsi->state]); }}static void scatter_gather_callback(struct urb *u){ struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context; struct scatterlist *sg = hpusbscsi->srb->buffer; usb_urb_callback callback; int res; PDEBUG(1, "Going through scatter/gather"); // bonzo - this gets hit a lot - maybe make it a 2 if (u->status < 0) { handle_usb_error(hpusbscsi); return; } if (hpusbscsi->fragment + 1 != hpusbscsi->srb->use_sg) callback = scatter_gather_callback; else callback = simple_done; PDEBUG(2, "state= %s", states[hpusbscsi->state]); if (hpusbscsi->state != HP_STATE_PREMATURE) hpusbscsi->state = HP_STATE_WORKING; PDEBUG(2, "state= %s", states[hpusbscsi->state]); FILL_BULK_URB( u, hpusbscsi->dev, hpusbscsi->current_data_pipe, sg[hpusbscsi->fragment].address, sg[hpusbscsi->fragment++].length, callback, hpusbscsi ); res = usb_submit_urb(u); if (res) handle_usb_error(hpusbscsi); PDEBUG(2, "state= %s", states[hpusbscsi->state]);}static void simple_done (struct urb *u){ struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context; if (u->status < 0) { handle_usb_error(hpusbscsi); return; } PDEBUG(1, "Data transfer done"); PDEBUG(2, "state= %s", states[hpusbscsi->state]); if (hpusbscsi->state != HP_STATE_PREMATURE) { if (u->status < 0) { handle_usb_error(hpusbscsi); } else { if (hpusbscsi->state != HP_STATE_ERROR) { hpusbscsi->state = HP_STATE_WAIT; } else { issue_request_sense(hpusbscsi); } PDEBUG(2, "state= %s", states[hpusbscsi->state]); } } else { if (hpusbscsi->scallback != NULL) hpusbscsi->scallback(hpusbscsi->srb); hpusbscsi->state = HP_STATE_FREE; }}static void simple_payload_callback (struct urb *u){ struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context; int res; if (u->status<0) { handle_usb_error(hpusbscsi); return; } FILL_BULK_URB( u, hpusbscsi->dev, hpusbscsi->current_data_pipe, hpusbscsi->srb->buffer, hpusbscsi->srb->bufflen, simple_done, hpusbscsi ); res = usb_submit_urb(u); if (res) { handle_usb_error(hpusbscsi); return; } PDEBUG(2, "state= %s", states[hpusbscsi->state]); if (hpusbscsi->state != HP_STATE_PREMATURE) { hpusbscsi->state = HP_STATE_WORKING; PDEBUG(2, "state= %s", states[hpusbscsi->state]); }}static void request_sense_callback (struct urb *u){ struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context; if (u->status<0) { handle_usb_error(hpusbscsi); return; } FILL_BULK_URB( u, hpusbscsi->dev, hpusbscsi->current_data_pipe, hpusbscsi->srb->sense_buffer, SCSI_SENSE_BUFFERSIZE, simple_done, hpusbscsi ); if (0 > usb_submit_urb(u)) { handle_usb_error(hpusbscsi); return; } if (hpusbscsi->state != HP_STATE_PREMATURE && hpusbscsi->state != HP_STATE_ERROR) hpusbscsi->state = HP_STATE_WORKING;}static void issue_request_sense (struct hpusbscsi *hpusbscsi){ FILL_BULK_URB( &hpusbscsi->dataurb, hpusbscsi->dev, usb_sndbulkpipe(hpusbscsi->dev, hpusbscsi->ep_out), &hpusbscsi->sense_command, SENSE_COMMAND_SIZE, request_sense_callback, hpusbscsi ); hpusbscsi->current_data_pipe = usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in); if (0 > usb_submit_urb(&hpusbscsi->dataurb)) { handle_usb_error(hpusbscsi); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -