/* This is always called with scsi_lock(srb->host) held */ static int device_reset(struct scsi_cmnd *srb) { struct us_data *us = host_to_us(srb->device->host); int result; US_DEBUGP("%s called\n", __FUNCTION__); if (us->sm_state != US_STATE_IDLE) { printk(KERN_ERR USB_STORAGE "Error in %s: " "invalid state %d\n", __FUNCTION__, us->sm_state); return FAILED; } /* set the state and release the lock */ us->sm_state = US_STATE_RESETTING; scsi_unlock(us_to_host(us)); /* lock the device pointers and do the reset */ down(&(us->dev_semaphore)); if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { result = FAILED; US_DEBUGP("No reset during disconnect\n"); } else result = us->transport_reset(us); up(&(us->dev_semaphore)); /* lock access to the state and clear it */ scsi_lock(us_to_host(us)); us->sm_state = US_STATE_IDLE; return result; }
/* Command timeout and abort */ static int command_abort(struct scsi_cmnd *srb) { struct us_data *us = host_to_us(srb->device->host); US_DEBUGP("%s called\n", __FUNCTION__); /* us->srb together with the TIMED_OUT, RESETTING, and ABORTING * bits are protected by the host lock. */ scsi_lock(us_to_host(us)); /* Is this command still active? */ if (us->srb != srb) { scsi_unlock(us_to_host(us)); US_DEBUGP ("-- nothing to abort\n"); return FAILED; } /* Set the TIMED_OUT bit. Also set the ABORTING bit, but only if * a device reset isn't already in progress (to avoid interfering * with the reset). Note that we must retain the host lock while * calling usb_stor_stop_transport(); otherwise it might interfere * with an auto-reset that begins as soon as we release the lock. */ set_bit(US_FLIDX_TIMED_OUT, &us->flags); if (!test_bit(US_FLIDX_RESETTING, &us->flags)) { set_bit(US_FLIDX_ABORTING, &us->flags); usb_stor_stop_transport(us); } scsi_unlock(us_to_host(us)); /* Wait for the aborted command to finish */ wait_for_completion(&us->notify); return SUCCESS; }
/* This is the common part of the device reset code. * * It's handy that every transport mechanism uses the control endpoint for * resets. * * Basically, we send a reset with a 20-second timeout, so we don't get * jammed attempting to do the reset. */ static int usb_stor_reset_common(struct us_data *us, u8 request, u8 requesttype, u16 value, u16 index, void *data, u16 size) { int result; int result2; int rc = FAILED; /* Let the SCSI layer know we are doing a reset, set the * RESETTING bit, and clear the ABORTING bit so that the reset * may proceed. */ scsi_lock(us_to_host(us)); usb_stor_report_device_reset(us); set_bit(US_FLIDX_RESETTING, &us->flags); clear_bit(US_FLIDX_ABORTING, &us->flags); scsi_unlock(us_to_host(us)); /* A 20-second timeout may seem rather long, but a LaCie * StudioDrive USB2 device takes 16+ seconds to get going * following a powerup or USB attach event. */ result = usb_stor_control_msg(us, us->send_ctrl_pipe, request, requesttype, value, index, data, size, 20*HZ); if (result < 0) { US_DEBUGP("Soft reset failed: %d\n", result); goto Done; } /* Give the device some time to recover from the reset, * but don't delay disconnect processing. */ wait_event_interruptible_timeout(us->delay_wait, test_bit(US_FLIDX_DISCONNECTING, &us->flags), HZ*6); if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { US_DEBUGP("Reset interrupted by disconnect\n"); goto Done; } US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n"); result = usb_stor_clear_halt(us, us->recv_bulk_pipe); US_DEBUGP("Soft reset: clearing bulk-out endpoint halt\n"); result2 = usb_stor_clear_halt(us, us->send_bulk_pipe); /* return a result code based on the result of the control message */ if (result < 0 || result2 < 0) { US_DEBUGP("Soft reset failed\n"); goto Done; } US_DEBUGP("Soft reset done\n"); rc = SUCCESS; Done: clear_bit(US_FLIDX_RESETTING, &us->flags); return rc; }
/* This is always called with scsi_lock(srb->host) held */ static int bus_reset(struct scsi_cmnd *srb) { struct us_data *us = host_to_us(srb->device->host); int result; US_DEBUGP("%s called\n", __FUNCTION__); if (us->sm_state != US_STATE_IDLE) { printk(KERN_ERR USB_STORAGE "Error in %s: " "invalid state %d\n", __FUNCTION__, us->sm_state); return FAILED; } /* set the state and release the lock */ us->sm_state = US_STATE_RESETTING; scsi_unlock(us_to_host(us)); /* The USB subsystem doesn't handle synchronisation between * a device's several drivers. Therefore we reset only devices * with just one interface, which we of course own. */ down(&(us->dev_semaphore)); if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { result = -EIO; US_DEBUGP("No reset during disconnect\n"); } else if (us->pusb_dev->actconfig->desc.bNumInterfaces != 1) { result = -EBUSY; US_DEBUGP("Refusing to reset a multi-interface device\n"); } else { /* * The lock can be taken when khubd is executing scsi_scan() * at the very tail of our ->probe routine. * If a device fails there, it has to be replugged. */ result = usb_reset_device_trylock(us->pusb_dev); US_DEBUGP("usb_reset_device returns %d\n", result); } up(&(us->dev_semaphore)); /* lock access to the state and clear it */ scsi_lock(us_to_host(us)); us->sm_state = US_STATE_IDLE; /* We must return succes, or else the device is offlined forever */ if (result < 0) { printk(KERN_NOTICE USB_STORAGE "Bus reset ended with %d\n", result); } return SUCCESS; }
static void quiesce_and_remove_host(struct us_data *us) { struct Scsi_Host *host = us_to_host(us); //--------------------------- pr_info("17 quiesce and remove host\n"); /* If the device is really gone, cut short reset delays */ if (us->pusb_dev->state == USB_STATE_NOTATTACHED) { set_bit(US_FLIDX_DISCONNECTING, &us->dflags); wake_up(&us->delay_wait); } /* Prevent SCSI scanning (if it hasn't started yet) * or wait for the SCSI-scanning routine to stop. */ cancel_delayed_work_sync(&us->scan_dwork); /* Balance autopm calls if scanning was cancelled */ if (test_bit(US_FLIDX_SCAN_PENDING, &us->dflags)) usb_autopm_put_interface_no_suspend(us->pusb_intf); /* Removing the host will perform an orderly shutdown: caches * synchronized, disks spun down, etc. */ scsi_remove_host(host); /* Prevent any new commands from being accepted and cut short * reset delays. */ scsi_lock(host); set_bit(US_FLIDX_DISCONNECTING, &us->dflags); scsi_unlock(host); wake_up(&us->delay_wait); }
/* Report a driver-initiated bus reset to the SCSI layer. * Calling this for a SCSI-initiated reset is unnecessary but harmless. * The caller must not own the SCSI host lock. */ void usb_stor_report_bus_reset(struct us_data *us) { struct Scsi_Host *host = us_to_host(us); scsi_lock(host); scsi_report_bus_reset(host, 0); scsi_unlock(host); }
/* This is always called with scsi_lock(srb->host) held */ static int command_abort(struct scsi_cmnd *srb ) { struct us_data *us = host_to_us(srb->device->host); US_DEBUGP("%s called\n", __FUNCTION__); /* Is this command still active? */ if (us->srb != srb) { US_DEBUGP ("-- nothing to abort\n"); return FAILED; } /* Normally the current state is RUNNING. If the control thread * hasn't even started processing this command, the state will be * IDLE. Anything else is a bug. */ if (us->sm_state != US_STATE_RUNNING && us->sm_state != US_STATE_IDLE) { printk(KERN_ERR USB_STORAGE "Error in %s: " "invalid state %d\n", __FUNCTION__, us->sm_state); return FAILED; } /* Set state to ABORTING and set the ABORTING bit, but only if * a device reset isn't already in progress (to avoid interfering * with the reset). To prevent races with auto-reset, we must * stop any ongoing USB transfers while still holding the host * lock. */ us->sm_state = US_STATE_ABORTING; if (!test_bit(US_FLIDX_RESETTING, &us->flags)) { set_bit(US_FLIDX_ABORTING, &us->flags); usb_stor_stop_transport(us); } scsi_unlock(us_to_host(us)); /* Wait for the aborted command to finish */ wait_for_completion(&us->notify); /* Reacquire the lock and allow USB transfers to resume */ scsi_lock(us_to_host(us)); clear_bit(US_FLIDX_ABORTING, &us->flags); return SUCCESS; }
/* Report a driver-initiated device reset to the SCSI layer. * Calling this for a SCSI-initiated reset is unnecessary but harmless. * The caller must own the SCSI host lock. */ void usb_stor_report_device_reset(struct us_data *us) { int i; struct Scsi_Host *host = us_to_host(us); scsi_report_device_reset(host, 0, 0); if (us->flags & US_FL_SCM_MULT_TARG) { for (i = 1; i < host->max_id; ++i) scsi_report_device_reset(host, 0, i); } }
static void release_everything(struct us_data *us) { //--------------------------- pr_info("18 release_everything\n"); usb_stor_release_resources(us); dissociate_dev(us); /* Drop our reference to the host; the SCSI core will free it * (and "us" along with it) when the refcount becomes 0. */ scsi_host_put(us_to_host(us)); }
/** * @fn usb_stor_sm331_init * @brief initialize of this driver * @param us : USB Storage device structure * @return success : 0 failure : not zero * @date 2008/07/10 */ int usb_stor_sm331_init (struct us_data *us) { struct Scsi_Host *scsi_host = us_to_host(us); if(is_av_slot(us->pusb_dev)) { if(scsi_host) { scsi_host->max_sectors = 256; } } return USB_STOR_TRANSPORT_GOOD; }
/* Delayed-work routine to carry out SCSI-device scanning */ static void usb_stor_scan_dwork(struct work_struct *work) { struct us_data *us = container_of(work, struct us_data, scan_dwork.work); struct device *dev = &us->pusb_intf->dev; //--------------------------- pr_info("19 usb stor scan dwork\n"); dev_dbg(dev, "starting scan\n"); /* For bulk-only devices, determine the max LUN value */ if (us->protocol == USB_PR_BULK && !(us->fflags & US_FL_SINGLE_LUN)) { mutex_lock(&us->dev_mutex); us->max_lun = usb_stor_Bulk_max_lun(us); mutex_unlock(&us->dev_mutex); } scsi_scan_host(us_to_host(us)); dev_dbg(dev, "scan complete\n"); /* Should we unbind if no devices were detected? */ usb_autopm_put_interface(us->pusb_intf); clear_bit(US_FLIDX_SCAN_PENDING, &us->dflags); }
int sierra_ms_init(struct us_data *us) { int result, retries; signed long delay_t; struct swoc_info *swocInfo; struct usb_device *udev; struct Scsi_Host *sh; struct scsi_device *sd; delay_t = 2; retries = 3; result = 0; udev = us->pusb_dev; sh = us_to_host(us); sd = scsi_get_host_dev(sh); US_DEBUGP("SWIMS: sierra_ms_init called\n"); /* Force Modem mode */ if (swi_tru_install == TRU_FORCE_MODEM) { US_DEBUGP("SWIMS: %s", "Forcing Modem Mode\n"); result = sierra_set_ms_mode(udev, SWIMS_SET_MODE_Modem); if (result < 0) US_DEBUGP("SWIMS: Failed to switch to modem mode.\n"); return -EIO; } /* Force Mass Storage mode (keep CD-Rom) */ else if (swi_tru_install == TRU_FORCE_MS) { US_DEBUGP("SWIMS: %s", "Forcing Mass Storage Mode\n"); goto complete; } /* Normal TRU-Install Logic */ else { US_DEBUGP("SWIMS: %s", "Normal SWoC Logic\n"); swocInfo = kmalloc(sizeof(struct swoc_info), GFP_KERNEL); if (!swocInfo) { US_DEBUGP("SWIMS: %s", "Allocation failure\n"); return -ENOMEM; } retries = 3; do { retries--; result = sierra_get_swoc_info(udev, swocInfo); if (result < 0) { US_DEBUGP("SWIMS: %s", "Failed SWoC query\n"); schedule_timeout_uninterruptible(2*HZ); } } while (retries && result < 0); if (result < 0) { US_DEBUGP("SWIMS: %s", "Completely failed SWoC query\n"); kfree(swocInfo); return -EIO; } debug_swoc(swocInfo); /* If there is not Linux software on the TRU-Install device * then switch to modem mode */ if (!containsFullLinuxPackage(swocInfo)) { US_DEBUGP("SWIMS: %s", "Switching to Modem Mode\n"); result = sierra_set_ms_mode(udev, SWIMS_SET_MODE_Modem); if (result < 0) US_DEBUGP("SWIMS: Failed to switch modem\n"); kfree(swocInfo); return -EIO; } kfree(swocInfo); } complete: result = device_create_file(&us->pusb_intf->dev, &dev_attr_truinst); return 0; }
/* Invoke the transport and basic error-handling/recovery methods * * This is used by the protocol layers to actually send the message to * the device and receive the response. */ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) { int need_auto_sense; int result; /* send the command to the transport layer */ scsi_set_resid(srb, 0); result = us->transport(srb, us); /* if the command gets aborted by the higher layers, we need to * short-circuit all other processing */ if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { US_DEBUGP("-- command was aborted\n"); srb->result = DID_ABORT << 16; goto Handle_Errors; } /* if there is a transport error, reset and don't auto-sense */ if (result == USB_STOR_TRANSPORT_ERROR) { US_DEBUGP("-- transport indicates error, resetting\n"); srb->result = DID_ERROR << 16; goto Handle_Errors; } /* if the transport provided its own sense data, don't auto-sense */ if (result == USB_STOR_TRANSPORT_NO_SENSE) { srb->result = SAM_STAT_CHECK_CONDITION; last_sector_hacks(us, srb); return; } srb->result = SAM_STAT_GOOD; /* Determine if we need to auto-sense * * I normally don't use a flag like this, but it's almost impossible * to understand what's going on here if I don't. */ need_auto_sense = 0; /* * If we're running the CB transport, which is incapable * of determining status on its own, we will auto-sense * unless the operation involved a data-in transfer. Devices * can signal most data-in errors by stalling the bulk-in pipe. */ if ((us->protocol == USB_PR_CB || us->protocol == USB_PR_DPCM_USB) && srb->sc_data_direction != DMA_FROM_DEVICE) { US_DEBUGP("-- CB transport device requiring auto-sense\n"); need_auto_sense = 1; } /* * If we have a failure, we're going to do a REQUEST_SENSE * automatically. Note that we differentiate between a command * "failure" and an "error" in the transport mechanism. */ if (result == USB_STOR_TRANSPORT_FAILED) { US_DEBUGP("-- transport indicates command failure\n"); need_auto_sense = 1; } /* * Determine if this device is SAT by seeing if the * command executed successfully. Otherwise we'll have * to wait for at least one CHECK_CONDITION to determine * SANE_SENSE support */ if (unlikely((srb->cmnd[0] == ATA_16 || srb->cmnd[0] == ATA_12) && result == USB_STOR_TRANSPORT_GOOD && !(us->fflags & US_FL_SANE_SENSE) && !(us->fflags & US_FL_BAD_SENSE) && !(srb->cmnd[2] & 0x20))) { US_DEBUGP("-- SAT supported, increasing auto-sense\n"); us->fflags |= US_FL_SANE_SENSE; } /* * A short transfer on a command where we don't expect it * is unusual, but it doesn't mean we need to auto-sense. */ if ((scsi_get_resid(srb) > 0) && !((srb->cmnd[0] == REQUEST_SENSE) || (srb->cmnd[0] == INQUIRY) || (srb->cmnd[0] == MODE_SENSE) || (srb->cmnd[0] == LOG_SENSE) || (srb->cmnd[0] == MODE_SENSE_10))) { US_DEBUGP("-- unexpectedly short transfer\n"); } /* Now, if we need to do the auto-sense, let's do it */ if (need_auto_sense) { int temp_result; struct scsi_eh_save ses; int sense_size = US_SENSE_SIZE; struct scsi_sense_hdr sshdr; const u8 *scdd; u8 fm_ili; /* device supports and needs bigger sense buffer */ if (us->fflags & US_FL_SANE_SENSE) sense_size = ~0; Retry_Sense: US_DEBUGP("Issuing auto-REQUEST_SENSE\n"); scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sense_size); /* FIXME: we must do the protocol translation here */ if (us->subclass == USB_SC_RBC || us->subclass == USB_SC_SCSI || us->subclass == USB_SC_CYP_ATACB) srb->cmd_len = 6; else srb->cmd_len = 12; /* issue the auto-sense command */ scsi_set_resid(srb, 0); temp_result = us->transport(us->srb, us); /* let's clean up right away */ scsi_eh_restore_cmnd(srb, &ses); if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { US_DEBUGP("-- auto-sense aborted\n"); srb->result = DID_ABORT << 16; /* If SANE_SENSE caused this problem, disable it */ if (sense_size != US_SENSE_SIZE) { us->fflags &= ~US_FL_SANE_SENSE; us->fflags |= US_FL_BAD_SENSE; } goto Handle_Errors; } /* Some devices claim to support larger sense but fail when * trying to request it. When a transport failure happens * using US_FS_SANE_SENSE, we always retry with a standard * (small) sense request. This fixes some USB GSM modems */ if (temp_result == USB_STOR_TRANSPORT_FAILED && sense_size != US_SENSE_SIZE) { US_DEBUGP("-- auto-sense failure, retry small sense\n"); sense_size = US_SENSE_SIZE; us->fflags &= ~US_FL_SANE_SENSE; us->fflags |= US_FL_BAD_SENSE; goto Retry_Sense; } /* Other failures */ if (temp_result != USB_STOR_TRANSPORT_GOOD) { US_DEBUGP("-- auto-sense failure\n"); /* we skip the reset if this happens to be a * multi-target device, since failure of an * auto-sense is perfectly valid */ srb->result = DID_ERROR << 16; if (!(us->fflags & US_FL_SCM_MULT_TARG)) goto Handle_Errors; return; } /* If the sense data returned is larger than 18-bytes then we * assume this device supports requesting more in the future. * The response code must be 70h through 73h inclusive. */ if (srb->sense_buffer[7] > (US_SENSE_SIZE - 8) && !(us->fflags & US_FL_SANE_SENSE) && !(us->fflags & US_FL_BAD_SENSE) && (srb->sense_buffer[0] & 0x7C) == 0x70) { US_DEBUGP("-- SANE_SENSE support enabled\n"); us->fflags |= US_FL_SANE_SENSE; /* Indicate to the user that we truncated their sense * because we didn't know it supported larger sense. */ US_DEBUGP("-- Sense data truncated to %i from %i\n", US_SENSE_SIZE, srb->sense_buffer[7] + 8); srb->sense_buffer[7] = (US_SENSE_SIZE - 8); } scsi_normalize_sense(srb->sense_buffer, SCSI_SENSE_BUFFERSIZE, &sshdr); US_DEBUGP("-- Result from auto-sense is %d\n", temp_result); US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n", sshdr.response_code, sshdr.sense_key, sshdr.asc, sshdr.ascq); #ifdef CONFIG_USB_STORAGE_DEBUG usb_stor_show_sense(sshdr.sense_key, sshdr.asc, sshdr.ascq); #endif /* set the result so the higher layers expect this data */ srb->result = SAM_STAT_CHECK_CONDITION; scdd = scsi_sense_desc_find(srb->sense_buffer, SCSI_SENSE_BUFFERSIZE, 4); fm_ili = (scdd ? scdd[3] : srb->sense_buffer[2]) & 0xA0; /* We often get empty sense data. This could indicate that * everything worked or that there was an unspecified * problem. We have to decide which. */ if (sshdr.sense_key == 0 && sshdr.asc == 0 && sshdr.ascq == 0 && fm_ili == 0) { /* If things are really okay, then let's show that. * Zero out the sense buffer so the higher layers * won't realize we did an unsolicited auto-sense. */ if (result == USB_STOR_TRANSPORT_GOOD) { srb->result = SAM_STAT_GOOD; srb->sense_buffer[0] = 0x0; /* If there was a problem, report an unspecified * hardware error to prevent the higher layers from * entering an infinite retry loop. */ } else { srb->result = DID_ERROR << 16; if ((sshdr.response_code & 0x72) == 0x72) srb->sense_buffer[1] = HARDWARE_ERROR; else srb->sense_buffer[2] = HARDWARE_ERROR; } } } /* * Some devices don't work or return incorrect data the first * time they get a READ(10) command, or for the first READ(10) * after a media change. If the INITIAL_READ10 flag is set, * keep track of whether READ(10) commands succeed. If the * previous one succeeded and this one failed, set the REDO_READ10 * flag to force a retry. */ if (unlikely((us->fflags & US_FL_INITIAL_READ10) && srb->cmnd[0] == READ_10)) { if (srb->result == SAM_STAT_GOOD) { set_bit(US_FLIDX_READ10_WORKED, &us->dflags); } else if (test_bit(US_FLIDX_READ10_WORKED, &us->dflags)) { clear_bit(US_FLIDX_READ10_WORKED, &us->dflags); set_bit(US_FLIDX_REDO_READ10, &us->dflags); } /* * Next, if the REDO_READ10 flag is set, return a result * code that will cause the SCSI core to retry the READ(10) * command immediately. */ if (test_bit(US_FLIDX_REDO_READ10, &us->dflags)) { clear_bit(US_FLIDX_REDO_READ10, &us->dflags); srb->result = DID_IMM_RETRY << 16; srb->sense_buffer[0] = 0; } } /* Did we transfer less than the minimum amount required? */ if ((srb->result == SAM_STAT_GOOD || srb->sense_buffer[2] == 0) && scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow) srb->result = DID_ERROR << 16; last_sector_hacks(us, srb); return; /* Error and abort processing: try to resynchronize with the device * by issuing a port reset. If that fails, try a class-specific * device reset. */ Handle_Errors: /* Set the RESETTING bit, and clear the ABORTING bit so that * the reset may proceed. */ scsi_lock(us_to_host(us)); set_bit(US_FLIDX_RESETTING, &us->dflags); clear_bit(US_FLIDX_ABORTING, &us->dflags); scsi_unlock(us_to_host(us)); /* We must release the device lock because the pre_reset routine * will want to acquire it. */ mutex_unlock(&us->dev_mutex); result = usb_stor_port_reset(us); mutex_lock(&us->dev_mutex); if (result < 0) { scsi_lock(us_to_host(us)); usb_stor_report_device_reset(us); scsi_unlock(us_to_host(us)); us->transport_reset(us); } clear_bit(US_FLIDX_RESETTING, &us->dflags); last_sector_hacks(us, srb); }
/* * ENE_stor_invoke_transport() */ void ENE_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) { int result = 0; /* pr_info("transport --- ENE_stor_invoke_transport\n"); */ usb_stor_print_cmd(srb); /* send the command to the transport layer */ scsi_set_resid(srb, 0); if (!(us->MS_Status.Ready || us->SM_Status.Ready)) result = ENE_InitMedia(us); if (us->Power_IsResum == true) { result = ENE_InitMedia(us); us->Power_IsResum = false; } if (us->MS_Status.Ready) result = MS_SCSIIrp(us, srb); if (us->SM_Status.Ready) result = SM_SCSIIrp(us, srb); /* if the command gets aborted by the higher layers, we need to short-circuit all other processing */ if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { /* pr_info("-- command was aborted\n"); */ srb->result = DID_ABORT << 16; goto Handle_Errors; } /* if there is a transport error, reset and don't auto-sense */ if (result == USB_STOR_TRANSPORT_ERROR) { /* pr_info("-- transport indicates error, resetting\n"); */ srb->result = DID_ERROR << 16; goto Handle_Errors; } /* if the transport provided its own sense data, don't auto-sense */ if (result == USB_STOR_TRANSPORT_NO_SENSE) { srb->result = SAM_STAT_CHECK_CONDITION; return; } srb->result = SAM_STAT_GOOD; if (result == USB_STOR_TRANSPORT_FAILED) { /* pr_info("-- transport indicates command failure\n"); */ /* need_auto_sense = 1; */ BuildSenseBuffer(srb, us->SrbStatus); srb->result = SAM_STAT_CHECK_CONDITION; } /* Did we transfer less than the minimum amount required? */ if (srb->result == SAM_STAT_GOOD && scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow) srb->result = (DID_ERROR << 16); /* v02 | (SUGGEST_RETRY << 24); */ return; Handle_Errors: scsi_lock(us_to_host(us)); set_bit(US_FLIDX_RESETTING, &us->dflags); clear_bit(US_FLIDX_ABORTING, &us->dflags); scsi_unlock(us_to_host(us)); mutex_unlock(&us->dev_mutex); result = usb_stor_port_reset(us); mutex_lock(&us->dev_mutex); if (result < 0) { scsi_lock(us_to_host(us)); usb_stor_report_device_reset(us); scsi_unlock(us_to_host(us)); us->transport_reset(us); } clear_bit(US_FLIDX_RESETTING, &us->dflags); }
/* * usb_stor_invoke_transport() */ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) { int need_auto_sense; int result; /* pr_info("transport --- usb_stor_invoke_transport\n"); */ usb_stor_print_cmd(srb); /* send the command to the transport layer */ scsi_set_resid(srb, 0); result = us->transport(srb, us); /* usb_stor_Bulk_transport; */ /* if the command gets aborted by the higher layers, we need to short-circuit all other processing */ if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { /* pr_info("-- command was aborted\n"); */ srb->result = DID_ABORT << 16; goto Handle_Errors; } /* if there is a transport error, reset and don't auto-sense */ if (result == USB_STOR_TRANSPORT_ERROR) { /* pr_info("-- transport indicates error, resetting\n"); */ srb->result = DID_ERROR << 16; goto Handle_Errors; } /* if the transport provided its own sense data, don't auto-sense */ if (result == USB_STOR_TRANSPORT_NO_SENSE) { srb->result = SAM_STAT_CHECK_CONDITION; return; } srb->result = SAM_STAT_GOOD; /* Determine if we need to auto-sense */ need_auto_sense = 0; if ((us->protocol == USB_PR_CB || us->protocol == USB_PR_DPCM_USB) && srb->sc_data_direction != DMA_FROM_DEVICE) { /* pr_info("-- CB transport device requiring auto-sense\n"); */ need_auto_sense = 1; } if (result == USB_STOR_TRANSPORT_FAILED) { /* pr_info("-- transport indicates command failure\n"); */ need_auto_sense = 1; } /* Now, if we need to do the auto-sense, let's do it */ if (need_auto_sense) { int temp_result; struct scsi_eh_save ses; pr_info("Issuing auto-REQUEST_SENSE\n"); scsi_eh_prep_cmnd(srb, &ses, NULL, 0, US_SENSE_SIZE); /* we must do the protocol translation here */ if (us->subclass == USB_SC_RBC || us->subclass == USB_SC_SCSI || us->subclass == USB_SC_CYP_ATACB) { srb->cmd_len = 6; } else { srb->cmd_len = 12; } /* issue the auto-sense command */ scsi_set_resid(srb, 0); temp_result = us->transport(us->srb, us); /* let's clean up right away */ scsi_eh_restore_cmnd(srb, &ses); if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { /* pr_info("-- auto-sense aborted\n"); */ srb->result = DID_ABORT << 16; goto Handle_Errors; } if (temp_result != USB_STOR_TRANSPORT_GOOD) { /* pr_info("-- auto-sense failure\n"); */ srb->result = DID_ERROR << 16; if (!(us->fflags & US_FL_SCM_MULT_TARG)) goto Handle_Errors; return; } /* set the result so the higher layers expect this data */ srb->result = SAM_STAT_CHECK_CONDITION; if (result == USB_STOR_TRANSPORT_GOOD && (srb->sense_buffer[2] & 0xaf) == 0 && srb->sense_buffer[12] == 0 && srb->sense_buffer[13] == 0) { srb->result = SAM_STAT_GOOD; srb->sense_buffer[0] = 0x0; } } /* Did we transfer less than the minimum amount required? */ if (srb->result == SAM_STAT_GOOD && scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow) srb->result = (DID_ERROR << 16); /* v02 | (SUGGEST_RETRY << 24); */ return; Handle_Errors: scsi_lock(us_to_host(us)); set_bit(US_FLIDX_RESETTING, &us->dflags); clear_bit(US_FLIDX_ABORTING, &us->dflags); scsi_unlock(us_to_host(us)); mutex_unlock(&us->dev_mutex); result = usb_stor_port_reset(us); mutex_lock(&us->dev_mutex); if (result < 0) { scsi_lock(us_to_host(us)); usb_stor_report_device_reset(us); scsi_unlock(us_to_host(us)); us->transport_reset(us); } clear_bit(US_FLIDX_RESETTING, &us->dflags); }
/* Invoke the transport and basic error-handling/recovery methods * * This is used by the protocol layers to actually send the message to * the device and receive the response. */ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) { int need_auto_sense; int result; /* send the command to the transport layer */ scsi_set_resid(srb, 0); result = us->transport(srb, us); /* if the command gets aborted by the higher layers, we need to * short-circuit all other processing */ if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { US_DEBUGP("-- command was aborted\n"); srb->result = DID_ABORT << 16; goto Handle_Errors; } /* if there is a transport error, reset and don't auto-sense */ if (result == USB_STOR_TRANSPORT_ERROR) { US_DEBUGP("-- transport indicates error, resetting\n"); srb->result = DID_ERROR << 16; goto Handle_Errors; } /* if the transport provided its own sense data, don't auto-sense */ if (result == USB_STOR_TRANSPORT_NO_SENSE) { srb->result = SAM_STAT_CHECK_CONDITION; last_sector_hacks(us, srb); return; } srb->result = SAM_STAT_GOOD; /* Determine if we need to auto-sense * * I normally don't use a flag like this, but it's almost impossible * to understand what's going on here if I don't. */ need_auto_sense = 0; /* * If we're running the CB transport, which is incapable * of determining status on its own, we will auto-sense * unless the operation involved a data-in transfer. Devices * can signal most data-in errors by stalling the bulk-in pipe. */ if ((us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) && srb->sc_data_direction != DMA_FROM_DEVICE) { US_DEBUGP("-- CB transport device requiring auto-sense\n"); need_auto_sense = 1; } /* * If we have a failure, we're going to do a REQUEST_SENSE * automatically. Note that we differentiate between a command * "failure" and an "error" in the transport mechanism. */ if (result == USB_STOR_TRANSPORT_FAILED) { US_DEBUGP("-- transport indicates command failure\n"); need_auto_sense = 1; } /* * Determine if this device is SAT by seeing if the * command executed successfully. Otherwise we'll have * to wait for at least one CHECK_CONDITION to determine * SANE_SENSE support */ if ((srb->cmnd[0] == ATA_16 || srb->cmnd[0] == ATA_12) && result == USB_STOR_TRANSPORT_GOOD && !(us->fflags & US_FL_SANE_SENSE) && !(srb->cmnd[2] & 0x20)) { US_DEBUGP("-- SAT supported, increasing auto-sense\n"); us->fflags |= US_FL_SANE_SENSE; } /* * A short transfer on a command where we don't expect it * is unusual, but it doesn't mean we need to auto-sense. */ if ((scsi_get_resid(srb) > 0) && !((srb->cmnd[0] == REQUEST_SENSE) || (srb->cmnd[0] == INQUIRY) || (srb->cmnd[0] == MODE_SENSE) || (srb->cmnd[0] == LOG_SENSE) || (srb->cmnd[0] == MODE_SENSE_10))) { US_DEBUGP("-- unexpectedly short transfer\n"); } /* Now, if we need to do the auto-sense, let's do it */ if (need_auto_sense) { int temp_result; struct scsi_eh_save ses; int sense_size = US_SENSE_SIZE; /* device supports and needs bigger sense buffer */ if (us->fflags & US_FL_SANE_SENSE) sense_size = ~0; US_DEBUGP("Issuing auto-REQUEST_SENSE\n"); scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sense_size); /* FIXME: we must do the protocol translation here */ if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI || us->subclass == US_SC_CYP_ATACB) srb->cmd_len = 6; else srb->cmd_len = 12; /* issue the auto-sense command */ scsi_set_resid(srb, 0); temp_result = us->transport(us->srb, us); /* let's clean up right away */ scsi_eh_restore_cmnd(srb, &ses); if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { US_DEBUGP("-- auto-sense aborted\n"); srb->result = DID_ABORT << 16; goto Handle_Errors; } if (temp_result != USB_STOR_TRANSPORT_GOOD) { US_DEBUGP("-- auto-sense failure\n"); /* we skip the reset if this happens to be a * multi-target device, since failure of an * auto-sense is perfectly valid */ srb->result = DID_ERROR << 16; if (!(us->fflags & US_FL_SCM_MULT_TARG)) goto Handle_Errors; return; } /* If the sense data returned is larger than 18-bytes then we * assume this device supports requesting more in the future. * The response code must be 70h through 73h inclusive. */ if (srb->sense_buffer[7] > (US_SENSE_SIZE - 8) && !(us->fflags & US_FL_SANE_SENSE) && (srb->sense_buffer[0] & 0x7C) == 0x70) { US_DEBUGP("-- SANE_SENSE support enabled\n"); us->fflags |= US_FL_SANE_SENSE; /* Indicate to the user that we truncated their sense * because we didn't know it supported larger sense. */ US_DEBUGP("-- Sense data truncated to %i from %i\n", US_SENSE_SIZE, srb->sense_buffer[7] + 8); srb->sense_buffer[7] = (US_SENSE_SIZE - 8); } US_DEBUGP("-- Result from auto-sense is %d\n", temp_result); US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n", srb->sense_buffer[0], srb->sense_buffer[2] & 0xf, srb->sense_buffer[12], srb->sense_buffer[13]); #ifdef CONFIG_USB_STORAGE_DEBUG usb_stor_show_sense( srb->sense_buffer[2] & 0xf, srb->sense_buffer[12], srb->sense_buffer[13]); #endif /* set the result so the higher layers expect this data */ srb->result = SAM_STAT_CHECK_CONDITION; /* If things are really okay, then let's show that. Zero * out the sense buffer so the higher layers won't realize * we did an unsolicited auto-sense. */ if (result == USB_STOR_TRANSPORT_GOOD && /* Filemark 0, ignore EOM, ILI 0, no sense */ (srb->sense_buffer[2] & 0xaf) == 0 && /* No ASC or ASCQ */ srb->sense_buffer[12] == 0 && srb->sense_buffer[13] == 0) { srb->result = SAM_STAT_GOOD; srb->sense_buffer[0] = 0x0; } } /* Did we transfer less than the minimum amount required? */ if ((srb->result == SAM_STAT_GOOD || srb->sense_buffer[2] == 0) && scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow) srb->result = DID_ERROR << 16; last_sector_hacks(us, srb); return; /* Error and abort processing: try to resynchronize with the device * by issuing a port reset. If that fails, try a class-specific * device reset. */ Handle_Errors: /* Set the RESETTING bit, and clear the ABORTING bit so that * the reset may proceed. */ scsi_lock(us_to_host(us)); set_bit(US_FLIDX_RESETTING, &us->dflags); clear_bit(US_FLIDX_ABORTING, &us->dflags); scsi_unlock(us_to_host(us)); /* We must release the device lock because the pre_reset routine * will want to acquire it. */ mutex_unlock(&us->dev_mutex); result = usb_stor_port_reset(us); mutex_lock(&us->dev_mutex); if (result < 0) { scsi_lock(us_to_host(us)); usb_stor_report_device_reset(us); scsi_unlock(us_to_host(us)); us->transport_reset(us); } clear_bit(US_FLIDX_RESETTING, &us->dflags); last_sector_hacks(us, srb); }
/* Invoke the transport and basic error-handling/recovery methods * * This is used by the protocol layers to actually send the message to * the device and receive the response. */ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) { int need_auto_sense; int result; /* send the command to the transport layer */ srb->resid = 0; result = us->transport(srb, us); /* if the command gets aborted by the higher layers, we need to * short-circuit all other processing */ if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { US_DEBUGP("-- command was aborted\n"); srb->result = DID_ABORT << 16; goto Handle_Errors; } /* if there is a transport error, reset and don't auto-sense */ if (result == USB_STOR_TRANSPORT_ERROR) { US_DEBUGP("-- transport indicates error, resetting\n"); srb->result = DID_ERROR << 16; goto Handle_Errors; } /* if the transport provided its own sense data, don't auto-sense */ if (result == USB_STOR_TRANSPORT_NO_SENSE) { srb->result = SAM_STAT_CHECK_CONDITION; return; } srb->result = SAM_STAT_GOOD; /* Determine if we need to auto-sense * * I normally don't use a flag like this, but it's almost impossible * to understand what's going on here if I don't. */ need_auto_sense = 0; /* * If we're running the CB transport, which is incapable * of determining status on its own, we will auto-sense * unless the operation involved a data-in transfer. Devices * can signal most data-in errors by stalling the bulk-in pipe. */ if ((us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) && srb->sc_data_direction != DMA_FROM_DEVICE) { US_DEBUGP("-- CB transport device requiring auto-sense\n"); need_auto_sense = 1; } /* * If we have a failure, we're going to do a REQUEST_SENSE * automatically. Note that we differentiate between a command * "failure" and an "error" in the transport mechanism. */ if (result == USB_STOR_TRANSPORT_FAILED) { US_DEBUGP("-- transport indicates command failure\n"); need_auto_sense = 1; } /* * A short transfer on a command where we don't expect it * is unusual, but it doesn't mean we need to auto-sense. */ if ((srb->resid > 0) && !((srb->cmnd[0] == REQUEST_SENSE) || (srb->cmnd[0] == INQUIRY) || (srb->cmnd[0] == MODE_SENSE) || (srb->cmnd[0] == LOG_SENSE) || (srb->cmnd[0] == MODE_SENSE_10))) { US_DEBUGP("-- unexpectedly short transfer\n"); } /* Now, if we need to do the auto-sense, let's do it */ if (need_auto_sense) { int temp_result; void* old_request_buffer; unsigned short old_sg; unsigned old_request_bufflen; unsigned char old_sc_data_direction; unsigned char old_cmd_len; unsigned char old_cmnd[MAX_COMMAND_SIZE]; int old_resid; US_DEBUGP("Issuing auto-REQUEST_SENSE\n"); /* save the old command */ memcpy(old_cmnd, srb->cmnd, MAX_COMMAND_SIZE); old_cmd_len = srb->cmd_len; /* set the command and the LUN */ memset(srb->cmnd, 0, MAX_COMMAND_SIZE); srb->cmnd[0] = REQUEST_SENSE; srb->cmnd[1] = old_cmnd[1] & 0xE0; srb->cmnd[4] = 18; /* FIXME: we must do the protocol translation here */ if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI) srb->cmd_len = 6; else srb->cmd_len = 12; /* set the transfer direction */ old_sc_data_direction = srb->sc_data_direction; srb->sc_data_direction = DMA_FROM_DEVICE; /* use the new buffer we have */ old_request_buffer = srb->request_buffer; srb->request_buffer = us->sensebuf; /* set the buffer length for transfer */ old_request_bufflen = srb->request_bufflen; srb->request_bufflen = US_SENSE_SIZE; /* set up for no scatter-gather use */ old_sg = srb->use_sg; srb->use_sg = 0; /* issue the auto-sense command */ old_resid = srb->resid; srb->resid = 0; temp_result = us->transport(us->srb, us); /* let's clean up right away */ memcpy(srb->sense_buffer, us->sensebuf, US_SENSE_SIZE); srb->resid = old_resid; srb->request_buffer = old_request_buffer; srb->request_bufflen = old_request_bufflen; srb->use_sg = old_sg; srb->sc_data_direction = old_sc_data_direction; srb->cmd_len = old_cmd_len; memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE); if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { US_DEBUGP("-- auto-sense aborted\n"); srb->result = DID_ABORT << 16; goto Handle_Errors; } if (temp_result != USB_STOR_TRANSPORT_GOOD) { US_DEBUGP("-- auto-sense failure\n"); /* we skip the reset if this happens to be a * multi-target device, since failure of an * auto-sense is perfectly valid */ srb->result = DID_ERROR << 16; if (!(us->flags & US_FL_SCM_MULT_TARG)) goto Handle_Errors; return; } US_DEBUGP("-- Result from auto-sense is %d\n", temp_result); US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n", srb->sense_buffer[0], srb->sense_buffer[2] & 0xf, srb->sense_buffer[12], srb->sense_buffer[13]); #ifdef CONFIG_USB_STORAGE_DEBUG usb_stor_show_sense( srb->sense_buffer[2] & 0xf, srb->sense_buffer[12], srb->sense_buffer[13]); #endif /* set the result so the higher layers expect this data */ srb->result = SAM_STAT_CHECK_CONDITION; /* If things are really okay, then let's show that. Zero * out the sense buffer so the higher layers won't realize * we did an unsolicited auto-sense. */ if (result == USB_STOR_TRANSPORT_GOOD && /* Filemark 0, ignore EOM, ILI 0, no sense */ (srb->sense_buffer[2] & 0xaf) == 0 && /* No ASC or ASCQ */ srb->sense_buffer[12] == 0 && srb->sense_buffer[13] == 0) { srb->result = SAM_STAT_GOOD; srb->sense_buffer[0] = 0x0; } } /* Did we transfer less than the minimum amount required? */ if (srb->result == SAM_STAT_GOOD && srb->request_bufflen - srb->resid < srb->underflow) srb->result = (DID_ERROR << 16) | (SUGGEST_RETRY << 24); return; /* Error and abort processing: try to resynchronize with the device * by issuing a port reset. If that fails, try a class-specific * device reset. */ Handle_Errors: /* Let the SCSI layer know we are doing a reset, set the * RESETTING bit, and clear the ABORTING bit so that the reset * may proceed. */ scsi_lock(us_to_host(us)); usb_stor_report_bus_reset(us); set_bit(US_FLIDX_RESETTING, &us->flags); clear_bit(US_FLIDX_ABORTING, &us->flags); scsi_unlock(us_to_host(us)); result = usb_stor_port_reset(us); if (result < 0) { scsi_lock(us_to_host(us)); usb_stor_report_device_reset(us); scsi_unlock(us_to_host(us)); us->transport_reset(us); } clear_bit(US_FLIDX_RESETTING, &us->flags); }
/* Report a driver-initiated bus reset to the SCSI layer. * Calling this for a SCSI-initiated reset is unnecessary but harmless. * The caller must own the SCSI host lock. */ void usb_stor_report_bus_reset(struct us_data *us) { scsi_report_bus_reset(us_to_host(us), 0); }
/** * @fn sm331_transport * @brief interface of transport SCSI Command. * @param srb : SCSI command structure * @param us : USB Storage device structure * @return success : 0 failure : not zero * @date 2008/07/10 */ int sm331_transport(struct scsi_cmnd *srb, struct us_data *us) { int ret = -EIO; unsigned char key; u8 slot = us->pusb_dev->portnum - CONFIG_SM331_AV_SLOT_OFFSET; if(!is_av_slot(us->pusb_dev)) return sm331_normal_transport(srb, us); /* if(!srb->device->minimum_timeout) srb->device->minimum_timeout = SD_MINIMUM_TIMEOUT; */ if(!us->extra) { if(likely(set_func && (alloc_card_info != NULL))) { ret = alloc_card_info( us, &us->extra, us->pusb_dev, us_to_host(us), &us->dev_mutex, &us->fflags, US_FLIDX_RESETTING, US_FLIDX_ABORTING, slot ); if(ret) { return ret; }; us->extra_destructor = __sm331_card_info_destructor; } } if(!srb->device->notify_ops) { srb->device->extra = us; srb->device->notify_ops = &scsi_ops; } if(!srb->device->use_10_for_rw) { srb->device->use_10_for_rw = 1; } /* if(srb->device->notify_mount){ srb->device->notify_mount = 0; sm331_card_info_destructor(us->extra, 1); } */ switch(srb->cmnd[0]) { case WRITE_6: case WRITE_10: case WRITE_12: ret = sm331_write_transport(srb, us); break; case WRITE_16: printk("WRITE_16 is not support\n"); return sm331_normal_transport(srb, us); case WRITE_LONG: printk("WRITE_LONG is not support\n"); return sm331_normal_transport(srb, us); case READ_6: case READ_10: case READ_12: ret = sm331_read_transport(srb, us); break; case READ_16: printk("READ_16 is not support\n"); return sm331_normal_transport(srb, us); case READ_LONG: printk("READ_LONG is not support\n"); return sm331_normal_transport(srb, us); default: ret = sm331_other_transport(srb, us); } if(ret == SM331_SDOP_FSERR) { memcpy(srb->sense_buffer, usb_stor_sense_invalidCDB, sizeof(usb_stor_sense_invalidCDB)); ret = USB_STOR_XFER_ERROR; } key = srb->sense_buffer[2] & 0xF; if(key) { if(key == NOT_READY || key == UNIT_ATTENTION) sm331_card_info_destructor(us->extra, 0); } return ret; }
//probe书中有教 static int our_probe(struct usb_interface *intf, const struct usb_device_id *id){ struct us_data *us; int result; //device struct device *dev; //scsihost struct Scsi_Host *host; //检测id是否符合 和intf struct us_unusual_dev *unusual_dev; unusual_dev=(id - usb_storage_usb_ids) + us_unusual_dev_list; if(usb_usual_check_type(id,USB_US_TYPE_STOR) || usb_usual_ignore_device(intf)) return -ENXIO; printk(KERN_ALERT "probe usb usb detected!\n"); //分配个host host = scsi_host_alloc(&usb_stor_host_template,sizeof(*us)); if(!host){ dev_warn(&intf->dev,"fail to allocate the scsi host\n"); return -ENOMEM; } //host中的一些初始化 host->max_cmd_len = 16; host-> sg_tablesize = usb_stor_sg_tablesize(intf); us= host_to_us(host);//us 作为host中 的us //分内存? memset(us,0,sizeof(struct us_data)); mutex_init(&(us->dev_mutex)); init_completion(&us->cmnd_ready); init_completion(&(us->notify)); init_waitqueue_head(&us->delay_wait); INIT_DELAYED_WORK(&us->scan_dwork,usb_stor_scan_dwork); result = associate_dev(us,intf); if(result) goto Bad; result = get_device_info(us,id,unusual_dev); if(result) goto Bad; //transport protocol get_transport(us); get_protocol(us); if(!us->transport ||!us->proto_handler){ result=-ENXIO; goto Bad; } printk(KERN_ALERT"Transport: %s\n",us->transport_name); printk(KERN_ALERT"Protocol: %s\n",us->transport_name); dev = &us->pusb_intf->dev; //设置max lun if(us->fflags & US_FL_SINGLE_LUN) us->max_lun =0; //endpoint get pipe result = get_pipes(us); if(result) goto Bad; //如果u盘前十个指令错误,重置 if (us->fflags & US_FL_INITIAL_READ10) set_bit(US_FLIDX_REDO_READ10, &us->dflags); //申请子资源,添加进host result=usb_stor_acquire_sesources(us); if(result) goto Bad; snprintf(us->scsi_name,sizeof(us->scsi_name),"our-usb-storage%s",dev_name(&us->pusb_intf->dev)); result= scsi_add_host(us_to_host(us),dev); if(result){ printk(KERN_ALERT"UNable to add the host\n"); goto Bad; } //scsi设备延时探测 usb_autopm_get_interface_no_resume(us->pusb_intf); set_bit(US_FLIDX_SCAN_PENDING,&us->dflags); if(delay_use>0) dev_dbg(dev,"waiting for device before scanning\n"); queue_delayed_work(system_freezable_wq,&us->scan_dwork,delay_use * HZ); return 0; Bad: printk(KERN_ALERT "probe false!\n"); release_everything(us); return result; }
//仔细研读 static int usb_stor_control_thread(void * __us) { struct us_data *us = (struct us_data *)__us; struct Scsi_Host *host = us_to_host(us); //--------------------------- pr_info("7 usb stor control thread\n"); for(;;) { US_DEBUGP("*** thread sleeping.\n"); if (wait_for_completion_interruptible(&us->cmnd_ready)) break; US_DEBUGP("*** thread awakened.\n"); /* lock the device pointers */ mutex_lock(&(us->dev_mutex)); /* lock access to the state */ scsi_lock(host); /* When we are called with no command pending, we're done */ if (us->srb == NULL) { scsi_unlock(host); mutex_unlock(&us->dev_mutex); US_DEBUGP("-- exiting\n"); break; } /* has the command timed out *already* ? */ if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { us->srb->result = DID_ABORT << 16; goto SkipForAbort; } scsi_unlock(host); /* reject the command if the direction indicator * is UNKNOWN */ if (us->srb->sc_data_direction == DMA_BIDIRECTIONAL) { US_DEBUGP("UNKNOWN data direction\n"); us->srb->result = DID_ERROR << 16; } /* reject if target != 0 or if LUN is higher than * the maximum known LUN */ else if (us->srb->device->id && !(us->fflags & US_FL_SCM_MULT_TARG)) { US_DEBUGP("Bad target number (%d:%d)\n", us->srb->device->id, us->srb->device->lun); us->srb->result = DID_BAD_TARGET << 16; } else if (us->srb->device->lun > us->max_lun) { US_DEBUGP("Bad LUN (%d:%d)\n", us->srb->device->id, us->srb->device->lun); us->srb->result = DID_BAD_TARGET << 16; } /* Handle those devices which need us to fake * their inquiry data */ else if ((us->srb->cmnd[0] == INQUIRY) && (us->fflags & US_FL_FIX_INQUIRY)) { unsigned char data_ptr[36] = { 0x00, 0x80, 0x02, 0x02, 0x1F, 0x00, 0x00, 0x00}; US_DEBUGP("Faking INQUIRY command\n"); fill_inquiry_response(us, data_ptr, 36); us->srb->result = SAM_STAT_GOOD; } /* we've got a command, let's do it! */ else { US_DEBUG(usb_stor_show_command(us->srb)); us->proto_handler(us->srb, us); usb_mark_last_busy(us->pusb_dev); } /* lock access to the state */ scsi_lock(host); /* indicate that the command is done */ if (us->srb->result != DID_ABORT << 16) { US_DEBUGP("scsi cmd done, result=0x%x\n", us->srb->result); us->srb->scsi_done(us->srb); } else { SkipForAbort: US_DEBUGP("scsi command aborted\n"); } /* If an abort request was received we need to signal that * the abort has finished. The proper test for this is * the TIMED_OUT flag, not srb->result == DID_ABORT, because * the timeout might have occurred after the command had * already completed with a different result code. */ if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { complete(&(us->notify)); /* Allow USB transfers to resume */ clear_bit(US_FLIDX_ABORTING, &us->dflags); clear_bit(US_FLIDX_TIMED_OUT, &us->dflags); } /* finished working on this command */ us->srb = NULL; scsi_unlock(host); /* unlock the device pointers */ mutex_unlock(&us->dev_mutex); } /* for (;;) */ /* Wait until we are told to stop */ for (;;) { set_current_state(TASK_INTERRUPTIBLE); if (kthread_should_stop()) break; schedule(); } __set_current_state(TASK_RUNNING); return 0; }
/* Invoke the transport and basic error-handling/recovery methods * * This is used by the protocol layers to actually send the message to * the device and receive the response. */ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) { int need_auto_sense; int result; /* send the command to the transport layer */ srb->resid = 0; result = us->transport(srb, us); /* if the command gets aborted by the higher layers, we need to * short-circuit all other processing */ if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { _VMKLNX_USB_STOR_MSG("-- command was aborted\n", srb); US_DEBUGP("-- command was aborted\n"); srb->result = DID_ABORT << 16; goto Handle_Errors; } #if defined(__VMKLNX__) if (unlikely(scsi_dump_active(srb))) { /* can't do much in panic */ if (result != USB_STOR_TRANSPORT_GOOD) { srb->result = DID_ABORT << 16; goto Handle_Errors; } } #endif /* if there is a transport error, reset and don't auto-sense */ if (result == USB_STOR_TRANSPORT_ERROR) { _VMKLNX_USB_STOR_WARN("-- transport indicates error, resetting\n", srb); US_DEBUGP("-- transport indicates error, resetting\n"); srb->result = DID_ERROR << 16; goto Handle_Errors; } /* if the transport provided its own sense data, don't auto-sense */ if (result == USB_STOR_TRANSPORT_NO_SENSE) { #if defined(__VMKLNX__) BUG_ON(srb->sense_buffer[0] == 0); #endif srb->result = SAM_STAT_CHECK_CONDITION; return; } srb->result = SAM_STAT_GOOD; /* Determine if we need to auto-sense * * I normally don't use a flag like this, but it's almost impossible * to understand what's going on here if I don't. */ need_auto_sense = 0; /* * If we're running the CB transport, which is incapable * of determining status on its own, we will auto-sense * unless the operation involved a data-in transfer. Devices * can signal most data-in errors by stalling the bulk-in pipe. */ if ((us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) && srb->sc_data_direction != DMA_FROM_DEVICE) { _VMKLNX_USB_STOR_MSG("-- CB transport device requiring auto-sense\n", srb); US_DEBUGP("-- CB transport device requiring auto-sense\n"); need_auto_sense = 1; } /* * If we have a failure, we're going to do a REQUEST_SENSE * automatically. Note that we differentiate between a command * "failure" and an "error" in the transport mechanism. */ if (result == USB_STOR_TRANSPORT_FAILED) { _VMKLNX_USB_STOR_MSG("-- transport indicates command failure\n", srb); US_DEBUGP("-- transport indicates command failure\n"); need_auto_sense = 1; } /* * A short transfer on a command where we don't expect it * is unusual, but it doesn't mean we need to auto-sense. */ if ((srb->resid > 0) && !((srb->cmnd[0] == REQUEST_SENSE) || (srb->cmnd[0] == INQUIRY) || (srb->cmnd[0] == MODE_SENSE) || (srb->cmnd[0] == LOG_SENSE) || (srb->cmnd[0] == MODE_SENSE_10))) { _VMKLNX_USB_STOR_MSG("-- unexpectedly short transfer\n", srb); US_DEBUGP("-- unexpectedly short transfer\n"); } /* Now, if we need to do the auto-sense, let's do it */ if (need_auto_sense) { int temp_result; struct scsi_eh_save ses; US_DEBUGP("Issuing auto-REQUEST_SENSE\n"); #if defined(__VMKLNX__) /* use us->senebuf to get sense data; srb->sense_buffer might be above 4G, * yet device's dma_mask is set to 32-bit */ usb_stor_prep_cmd(srb, &ses, us->sensebuf); #else scsi_eh_prep_cmnd(srb, &ses, NULL, 0, US_SENSE_SIZE); #endif /* FIXME: we must do the protocol translation here */ if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI) srb->cmd_len = 6; else srb->cmd_len = 12; /* issue the auto-sense command */ srb->resid = 0; temp_result = us->transport(us->srb, us); /* let's clean up right away */ #if defined(__VMKLNX__) usb_stor_restore_cmnd(srb, &ses); #else scsi_eh_restore_cmnd(srb, &ses); #endif if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { US_DEBUGP("-- auto-sense aborted\n"); srb->result = DID_ABORT << 16; goto Handle_Errors; } if (temp_result != USB_STOR_TRANSPORT_GOOD) { US_DEBUGP("-- auto-sense failure\n"); /* we skip the reset if this happens to be a * multi-target device, since failure of an * auto-sense is perfectly valid */ srb->result = DID_ERROR << 16; if (!(us->flags & US_FL_SCM_MULT_TARG)) goto Handle_Errors; return; } US_DEBUGP("-- Result from auto-sense is %d\n", temp_result); US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n", srb->sense_buffer[0], srb->sense_buffer[2] & 0xf, srb->sense_buffer[12], srb->sense_buffer[13]); #ifdef CONFIG_USB_STORAGE_DEBUG usb_stor_show_sense( srb->sense_buffer[2] & 0xf, srb->sense_buffer[12], srb->sense_buffer[13]); #endif /* set the result so the higher layers expect this data */ srb->result = SAM_STAT_CHECK_CONDITION; #if defined(__VMKLNX__) if (unlikely(srb->sense_buffer[0] == 0)) _VMKLNX_USB_STOR_MSG("srb->sense_buffer[0] unexpectedly 0 for srb %p\n", srb, srb); BUG_ON(srb->sense_buffer[0] == 0); #endif /* If things are really okay, then let's show that. Zero * out the sense buffer so the higher layers won't realize * we did an unsolicited auto-sense. */ if (result == USB_STOR_TRANSPORT_GOOD && /* Filemark 0, ignore EOM, ILI 0, no sense */ (srb->sense_buffer[2] & 0xaf) == 0 && /* No ASC or ASCQ */ srb->sense_buffer[12] == 0 && srb->sense_buffer[13] == 0) { srb->result = SAM_STAT_GOOD; srb->sense_buffer[0] = 0x0; } } /* Did we transfer less than the minimum amount required? */ if (srb->result == SAM_STAT_GOOD && srb->request_bufflen - srb->resid < srb->underflow) srb->result = (DID_ERROR << 16) | (SUGGEST_RETRY << 24); return; /* Error and abort processing: try to resynchronize with the device * by issuing a port reset. If that fails, try a class-specific * device reset. */ Handle_Errors: /* Set the RESETTING bit, and clear the ABORTING bit so that * the reset may proceed. */ scsi_lock(us_to_host(us)); set_bit(US_FLIDX_RESETTING, &us->flags); clear_bit(US_FLIDX_ABORTING, &us->flags); scsi_unlock(us_to_host(us)); /* We must release the device lock because the pre_reset routine * will want to acquire it. */ mutex_unlock(&us->dev_mutex); result = usb_stor_port_reset(us); mutex_lock(&us->dev_mutex); if (result < 0) { scsi_lock(us_to_host(us)); usb_stor_report_device_reset(us); scsi_unlock(us_to_host(us)); us->transport_reset(us); } clear_bit(US_FLIDX_RESETTING, &us->flags); }
void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) { int need_auto_sense; int result; scsi_set_resid(srb, 0); result = us->transport(srb, us); if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { US_DEBUGP("-- command was aborted\n"); srb->result = DID_ABORT << 16; goto Handle_Errors; } if (result == USB_STOR_TRANSPORT_ERROR) { US_DEBUGP("-- transport indicates error, resetting\n"); srb->result = DID_ERROR << 16; goto Handle_Errors; } if (result == USB_STOR_TRANSPORT_NO_SENSE) { srb->result = SAM_STAT_CHECK_CONDITION; last_sector_hacks(us, srb); return; } srb->result = SAM_STAT_GOOD; need_auto_sense = 0; if ((us->protocol == USB_PR_CB || us->protocol == USB_PR_DPCM_USB) && srb->sc_data_direction != DMA_FROM_DEVICE) { US_DEBUGP("-- CB transport device requiring auto-sense\n"); need_auto_sense = 1; } if (result == USB_STOR_TRANSPORT_FAILED) { US_DEBUGP("-- transport indicates command failure\n"); need_auto_sense = 1; } if (unlikely((srb->cmnd[0] == ATA_16 || srb->cmnd[0] == ATA_12) && result == USB_STOR_TRANSPORT_GOOD && !(us->fflags & US_FL_SANE_SENSE) && !(us->fflags & US_FL_BAD_SENSE) && !(srb->cmnd[2] & 0x20))) { US_DEBUGP("-- SAT supported, increasing auto-sense\n"); us->fflags |= US_FL_SANE_SENSE; } if ((scsi_get_resid(srb) > 0) && !((srb->cmnd[0] == REQUEST_SENSE) || (srb->cmnd[0] == INQUIRY) || (srb->cmnd[0] == MODE_SENSE) || (srb->cmnd[0] == LOG_SENSE) || (srb->cmnd[0] == MODE_SENSE_10))) { US_DEBUGP("-- unexpectedly short transfer\n"); } if (need_auto_sense) { int temp_result; struct scsi_eh_save ses; int sense_size = US_SENSE_SIZE; struct scsi_sense_hdr sshdr; const u8 *scdd; u8 fm_ili; if (us->fflags & US_FL_SANE_SENSE) sense_size = ~0; Retry_Sense: US_DEBUGP("Issuing auto-REQUEST_SENSE\n"); scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sense_size); if (us->subclass == USB_SC_RBC || us->subclass == USB_SC_SCSI || us->subclass == USB_SC_CYP_ATACB) srb->cmd_len = 6; else srb->cmd_len = 12; scsi_set_resid(srb, 0); temp_result = us->transport(us->srb, us); scsi_eh_restore_cmnd(srb, &ses); if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { US_DEBUGP("-- auto-sense aborted\n"); srb->result = DID_ABORT << 16; if (sense_size != US_SENSE_SIZE) { us->fflags &= ~US_FL_SANE_SENSE; us->fflags |= US_FL_BAD_SENSE; } goto Handle_Errors; } if (temp_result == USB_STOR_TRANSPORT_FAILED && sense_size != US_SENSE_SIZE) { US_DEBUGP("-- auto-sense failure, retry small sense\n"); sense_size = US_SENSE_SIZE; us->fflags &= ~US_FL_SANE_SENSE; us->fflags |= US_FL_BAD_SENSE; goto Retry_Sense; } if (temp_result != USB_STOR_TRANSPORT_GOOD) { US_DEBUGP("-- auto-sense failure\n"); srb->result = DID_ERROR << 16; if (!(us->fflags & US_FL_SCM_MULT_TARG)) goto Handle_Errors; return; } if (srb->sense_buffer[7] > (US_SENSE_SIZE - 8) && !(us->fflags & US_FL_SANE_SENSE) && !(us->fflags & US_FL_BAD_SENSE) && (srb->sense_buffer[0] & 0x7C) == 0x70) { US_DEBUGP("-- SANE_SENSE support enabled\n"); us->fflags |= US_FL_SANE_SENSE; US_DEBUGP("-- Sense data truncated to %i from %i\n", US_SENSE_SIZE, srb->sense_buffer[7] + 8); srb->sense_buffer[7] = (US_SENSE_SIZE - 8); } scsi_normalize_sense(srb->sense_buffer, SCSI_SENSE_BUFFERSIZE, &sshdr); US_DEBUGP("-- Result from auto-sense is %d\n", temp_result); US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n", sshdr.response_code, sshdr.sense_key, sshdr.asc, sshdr.ascq); #ifdef CONFIG_USB_STORAGE_DEBUG usb_stor_show_sense(sshdr.sense_key, sshdr.asc, sshdr.ascq); #endif srb->result = SAM_STAT_CHECK_CONDITION; scdd = scsi_sense_desc_find(srb->sense_buffer, SCSI_SENSE_BUFFERSIZE, 4); fm_ili = (scdd ? scdd[3] : srb->sense_buffer[2]) & 0xA0; if (sshdr.sense_key == 0 && sshdr.asc == 0 && sshdr.ascq == 0 && fm_ili == 0) { if (result == USB_STOR_TRANSPORT_GOOD) { srb->result = SAM_STAT_GOOD; srb->sense_buffer[0] = 0x0; } else { srb->result = DID_ERROR << 16; if ((sshdr.response_code & 0x72) == 0x72) srb->sense_buffer[1] = HARDWARE_ERROR; else srb->sense_buffer[2] = HARDWARE_ERROR; } } } if (unlikely((us->fflags & US_FL_INITIAL_READ10) && srb->cmnd[0] == READ_10)) { if (srb->result == SAM_STAT_GOOD) { set_bit(US_FLIDX_READ10_WORKED, &us->dflags); } else if (test_bit(US_FLIDX_READ10_WORKED, &us->dflags)) { clear_bit(US_FLIDX_READ10_WORKED, &us->dflags); set_bit(US_FLIDX_REDO_READ10, &us->dflags); } if (test_bit(US_FLIDX_REDO_READ10, &us->dflags)) { clear_bit(US_FLIDX_REDO_READ10, &us->dflags); srb->result = DID_IMM_RETRY << 16; srb->sense_buffer[0] = 0; } } if ((srb->result == SAM_STAT_GOOD || srb->sense_buffer[2] == 0) && scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow) srb->result = DID_ERROR << 16; last_sector_hacks(us, srb); return; Handle_Errors: scsi_lock(us_to_host(us)); set_bit(US_FLIDX_RESETTING, &us->dflags); clear_bit(US_FLIDX_ABORTING, &us->dflags); scsi_unlock(us_to_host(us)); mutex_unlock(&us->dev_mutex); result = usb_stor_port_reset(us); mutex_lock(&us->dev_mutex); if (result < 0) { scsi_lock(us_to_host(us)); usb_stor_report_device_reset(us); scsi_unlock(us_to_host(us)); us->transport_reset(us); } clear_bit(US_FLIDX_RESETTING, &us->dflags); last_sector_hacks(us, srb); }
static int usb_stor_control_thread(void * __us) { struct us_data *us = (struct us_data *)__us; struct Scsi_Host *host = us_to_host(us); //--------------------------- pr_info("7 usb stor control thread\n"); for(;;) { //若有u盘拔插或者有命令才会awake,否则一直就在这睡觉觉 if (wait_for_completion_interruptible(&us->cmnd_ready)) break; //从此处wake /* */ mutex_lock(&(us->dev_mutex)); /*每当需要写us->srb时候就需要锁之 */ scsi_lock(host); if (us->srb == NULL) { scsi_unlock(host); mutex_unlock(&us->dev_mutex); US_DEBUGP("-- exiting\n"); break; } if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { us->srb->result = DID_ABORT << 16; goto SkipForAbort; } scsi_unlock(host); if (us->srb->sc_data_direction == DMA_BIDIRECTIONAL) { US_DEBUGP("UNKNOWN data direction\n"); us->srb->result = DID_ERROR << 16; } else if (us->srb->device->id && !(us->fflags & US_FL_SCM_MULT_TARG)) { US_DEBUGP("Bad target number (%d:%d)\n", us->srb->device->id, us->srb->device->lun); us->srb->result = DID_BAD_TARGET << 16; } else if (us->srb->device->lun > us->max_lun) { US_DEBUGP("Bad LUN (%d:%d)\n", us->srb->device->id, us->srb->device->lun); us->srb->result = DID_BAD_TARGET << 16; } else if ((us->srb->cmnd[0] == INQUIRY) && (us->fflags & US_FL_FIX_INQUIRY)) { unsigned char data_ptr[36] = { 0x00, 0x80, 0x02, 0x02, 0x1F, 0x00, 0x00, 0x00}; US_DEBUGP("Faking INQUIRY command\n"); fill_inquiry_response(us, data_ptr, 36); us->srb->result = SAM_STAT_GOOD; } else { US_DEBUG(usb_stor_show_command(us->srb)); us->proto_handler(us->srb, us); usb_mark_last_busy(us->pusb_dev); } scsi_lock(host); if (us->srb->result != DID_ABORT << 16) { US_DEBUGP("scsi cmd done, result=0x%x\n", us->srb->result); us->srb->scsi_done(us->srb); } else { SkipForAbort: US_DEBUGP("scsi command aborted\n"); } /* */ if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { complete(&(us->notify)); clear_bit(US_FLIDX_ABORTING, &us->dflags); clear_bit(US_FLIDX_TIMED_OUT, &us->dflags); } us->srb = NULL; scsi_unlock(host); / mutex_unlock(&us->dev_mutex); }