static void debug_swoc(struct swoc_info *swocInfo) { US_DEBUGP("SWIMS: SWoC Rev: %02d \n", swocInfo->rev); US_DEBUGP("SWIMS: Linux SKU: %04X \n", swocInfo->LinuxSKU); US_DEBUGP("SWIMS: Linux Version: %04X \n", swocInfo->LinuxVer); }
/* 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(Scsi_Cmnd *srb, struct us_data *us) { int need_auto_sense; int result; /* send the command to the transport layer */ result = us->transport(srb, us); /* if the command gets aborted by the higher layers, we need to * short-circuit all other processing */ if (result == USB_STOR_TRANSPORT_ABORTED) { US_DEBUGP("-- transport indicates command was aborted\n"); srb->result = DID_ABORT << 16; return; } /* 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"); us->transport_reset(us); srb->result = DID_ERROR << 16; return; } /* 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 it's own, we need to auto-sense almost * every time. */ if (us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) { US_DEBUGP("-- CB transport device requiring auto-sense\n"); need_auto_sense = 1; /* There are some exceptions to this. Notably, if this is * a UFI device and the command is REQUEST_SENSE or INQUIRY, * then it is impossible to truly determine status. */ if (us->subclass == US_SC_UFI && ((srb->cmnd[0] == REQUEST_SENSE) || (srb->cmnd[0] == INQUIRY))) { US_DEBUGP("** no auto-sense for a special command\n"); need_auto_sense = 0; } } /* * 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; } /* * Also, if we have a short transfer on a command that can't have * a short transfer, we're going to do this. */ if ((srb->result == US_BULK_TRANSFER_SHORT) && !((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"); need_auto_sense = 1; } /* 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_cmnd[MAX_COMMAND_SIZE]; US_DEBUGP("Issuing auto-REQUEST_SENSE\n"); /* save the old command */ memcpy(old_cmnd, srb->cmnd, MAX_COMMAND_SIZE); /* set the command and the LUN */ #ifndef CONFIG_BOARD_W90N745 srb->cmnd[0] = REQUEST_SENSE; srb->cmnd[1] = old_cmnd[1] & 0xE0; srb->cmnd[2] = 0; srb->cmnd[3] = 0; srb->cmnd[4] = 18; srb->cmnd[5] = 0; #else ((unsigned char *)((unsigned long)srb->cmnd|0x80000000))[0] = REQUEST_SENSE; ((unsigned char *)((unsigned long)srb->cmnd|0x80000000))[1] = old_cmnd[1] & 0xE0; ((unsigned char *)((unsigned long)srb->cmnd|0x80000000))[2] = 0; ((unsigned char *)((unsigned long)srb->cmnd|0x80000000))[3] = 0; ((unsigned char *)((unsigned long)srb->cmnd|0x80000000))[4] = 18; ((unsigned char *)((unsigned long)srb->cmnd|0x80000000))[5] = 0; srb->cmnd[0] = REQUEST_SENSE; srb->cmnd[1] = old_cmnd[1] & 0xE0; srb->cmnd[2] = 0; srb->cmnd[3] = 0; srb->cmnd[4] = 18; srb->cmnd[5] = 0; #endif /* set the transfer direction */ old_sc_data_direction = srb->sc_data_direction; srb->sc_data_direction = SCSI_DATA_READ; /* use the new buffer we have */ old_request_buffer = srb->request_buffer; srb->request_buffer = srb->sense_buffer; /* set the buffer length for transfer */ old_request_bufflen = srb->request_bufflen; srb->request_bufflen = 18; /* set up for no scatter-gather use */ old_sg = srb->use_sg; srb->use_sg = 0; /* issue the auto-sense command */ temp_result = us->transport(us->srb, us); /* let's clean up right away */ 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; #ifndef CONFIG_BOARD_W90N745 memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE); #else memcpy(((unsigned char *)((unsigned long)srb->cmnd|0x80000000)), old_cmnd, MAX_COMMAND_SIZE); memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE); #endif if (temp_result == USB_STOR_TRANSPORT_ABORTED) { US_DEBUGP("-- auto-sense aborted\n"); srb->result = DID_ABORT << 16; return; } 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 */ if (!(us->flags & US_FL_SCM_MULT_TARG)) { us->transport_reset(us); } srb->result = DID_ERROR << 16; 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 = CHECK_CONDITION << 1; /* If things are really okay, then let's show that */ if ((srb->sense_buffer[2] & 0xf) == 0x0) srb->result = GOOD << 1; } else /* if (need_auto_sense) */ srb->result = GOOD << 1; /* Regardless of auto-sense, if we _know_ we have an error * condition, show that in the result code */ if (result == USB_STOR_TRANSPORT_FAILED) srb->result = CHECK_CONDITION << 1; /* If we think we're good, then make sure the sense data shows it. * This is necessary because the auto-sense for some devices always * sets byte 0 == 0x70, even if there is no error */ if ((us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) && (result == USB_STOR_TRANSPORT_GOOD) && ((srb->sense_buffer[2] & 0xf) == 0x0)) srb->sense_buffer[0] = 0x0; }
int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us) { int result; /* Set up for status notification */ atomic_set(us->ip_wanted, 1); /* re-initialize the mutex so that we avoid any races with * early/late IRQs from previous commands */ init_MUTEX_LOCKED(&(us->ip_waitq)); /* COMMAND STAGE */ /* let's send the command via the control pipe */ result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev,0), US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, us->ifnum, srb->cmnd, srb->cmd_len); /* check the return code for the command */ US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result); if (result < 0) { /* Reset flag for status notification */ atomic_set(us->ip_wanted, 0); } /* if the command was aborted, indicate that */ if (result == -ENOENT) return USB_STOR_TRANSPORT_ABORTED; /* STALL must be cleared when it is detected */ if (result == -EPIPE) { US_DEBUGP("-- Stall on control pipe. Clearing\n"); result = usb_stor_clear_halt(us, usb_sndctrlpipe(us->pusb_dev, 0)); /* if the command was aborted, indicate that */ if (result == -ENOENT) return USB_STOR_TRANSPORT_ABORTED; return USB_STOR_TRANSPORT_FAILED; } if (result < 0) { /* Uh oh... serious problem here */ return USB_STOR_TRANSPORT_ERROR; } /* DATA STAGE */ /* transfer the data payload for this command, if one exists*/ if (usb_stor_transfer_length(srb)) { usb_stor_transfer(srb, us); result = srb->result; US_DEBUGP("CBI data stage result is 0x%x\n", result); /* report any errors */ if (result == US_BULK_TRANSFER_ABORTED) { atomic_set(us->ip_wanted, 0); return USB_STOR_TRANSPORT_ABORTED; } if (result == US_BULK_TRANSFER_FAILED) { atomic_set(us->ip_wanted, 0); return USB_STOR_TRANSPORT_FAILED; } } /* STATUS STAGE */ /* go to sleep until we get this interrupt */ US_DEBUGP("Current value of ip_waitq is: %d\n", atomic_read(&us->ip_waitq.count)); down(&(us->ip_waitq)); /* if we were woken up by an abort instead of the actual interrupt */ if (atomic_read(us->ip_wanted)) { US_DEBUGP("Did not get interrupt on CBI\n"); atomic_set(us->ip_wanted, 0); return USB_STOR_TRANSPORT_ABORTED; } US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n", us->irqdata[0], us->irqdata[1]); /* UFI gives us ASC and ASCQ, like a request sense * * REQUEST_SENSE and INQUIRY don't affect the sense data on UFI * devices, so we ignore the information for those commands. Note * that this means we could be ignoring a real error on these * commands, but that can't be helped. */ if (us->subclass == US_SC_UFI) { if (srb->cmnd[0] == REQUEST_SENSE || srb->cmnd[0] == INQUIRY) return USB_STOR_TRANSPORT_GOOD; else #ifndef CONFIG_BOARD_W90N745 if (((unsigned char*)us->irq_urb->transfer_buffer)[0]) #else if (((unsigned char*)((unsigned long)us->irq_urb->transfer_buffer|0x80000000))[0]) #endif return USB_STOR_TRANSPORT_FAILED; else return USB_STOR_TRANSPORT_GOOD; } /* If not UFI, we interpret the data as a result code * The first byte should always be a 0x0 * The second byte & 0x0F should be 0x0 for good, otherwise error */ if (us->irqdata[0]) { US_DEBUGP("CBI IRQ data showed reserved bType %d\n", us->irqdata[0]); return USB_STOR_TRANSPORT_ERROR; } switch (us->irqdata[1] & 0x0F) { case 0x00: return USB_STOR_TRANSPORT_GOOD; case 0x01: return USB_STOR_TRANSPORT_FAILED; default: return USB_STOR_TRANSPORT_ERROR; } /* we should never get here, but if we do, we're in trouble */ return USB_STOR_TRANSPORT_ERROR; }
/* This is the common part of the URB message submission code * * All URBs from the usb-storage driver involved in handling a queued scsi * command _must_ pass through this function (or something like it) for the * abort mechanisms to work properly. */ static int usb_stor_msg_common(struct us_data *us, int timeout) { struct completion urb_done; long timeleft; int status; /* don't submit URBs during abort processing */ if (test_bit(US_FLIDX_ABORTING, &us->dflags)) return -EIO; /* set up data structures for the wakeup system */ init_completion(&urb_done); /* fill the common fields in the URB */ us->current_urb->context = &urb_done; us->current_urb->transfer_flags = 0; /* we assume that if transfer_buffer isn't us->iobuf then it * hasn't been mapped for DMA. Yes, this is clunky, but it's * easier than always having the caller tell us whether the * transfer buffer has already been mapped. */ if (us->current_urb->transfer_buffer == us->iobuf) us->current_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; us->current_urb->transfer_dma = us->iobuf_dma; /* submit the URB */ status = usb_submit_urb(us->current_urb, GFP_NOIO); if (status) { /* something went wrong */ return status; } /* since the URB has been submitted successfully, it's now okay * to cancel it */ set_bit(US_FLIDX_URB_ACTIVE, &us->dflags); /* did an abort occur during the submission? */ if (test_bit(US_FLIDX_ABORTING, &us->dflags)) { /* cancel the URB, if it hasn't been cancelled already */ if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) { US_DEBUGP("-- cancelling URB\n"); usb_unlink_urb(us->current_urb); } } /* wait for the completion of the URB */ timeleft = wait_for_completion_interruptible_timeout( &urb_done, timeout ? : MAX_SCHEDULE_TIMEOUT); clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags); if (timeleft <= 0) { US_DEBUGP("%s -- cancelling URB\n", timeleft == 0 ? "Timeout" : "Signal"); usb_kill_urb(us->current_urb); } /* return the URB status */ return us->current_urb->status; }
int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us) { unsigned int transfer_length = scsi_bufflen(srb); unsigned int pipe = 0; int result; /* COMMAND STAGE */ /* let's send the command via the control pipe */ result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe, US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, us->ifnum, srb->cmnd, srb->cmd_len); /* check the return code for the command */ US_DEBUGP("Call to usb_stor_ctrl_transfer() returned %d\n", result); /* if we stalled the command, it means command failed */ if (result == USB_STOR_XFER_STALLED) { return USB_STOR_TRANSPORT_FAILED; } /* Uh oh... serious problem here */ if (result != USB_STOR_XFER_GOOD) { return USB_STOR_TRANSPORT_ERROR; } /* DATA STAGE */ /* transfer the data payload for this command, if one exists*/ if (transfer_length) { pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? us->recv_bulk_pipe : us->send_bulk_pipe; result = usb_stor_bulk_srb(us, pipe, srb); US_DEBUGP("CBI data stage result is 0x%x\n", result); /* if we stalled the data transfer it means command failed */ if (result == USB_STOR_XFER_STALLED) return USB_STOR_TRANSPORT_FAILED; if (result > USB_STOR_XFER_STALLED) return USB_STOR_TRANSPORT_ERROR; } /* STATUS STAGE */ /* NOTE: CB does not have a status stage. Silly, I know. So * we have to catch this at a higher level. */ if (us->protocol != USB_PR_CBI) return USB_STOR_TRANSPORT_GOOD; result = usb_stor_intr_transfer(us, us->iobuf, 2); US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n", us->iobuf[0], us->iobuf[1]); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; /* UFI gives us ASC and ASCQ, like a request sense * * REQUEST_SENSE and INQUIRY don't affect the sense data on UFI * devices, so we ignore the information for those commands. Note * that this means we could be ignoring a real error on these * commands, but that can't be helped. */ if (us->subclass == USB_SC_UFI) { if (srb->cmnd[0] == REQUEST_SENSE || srb->cmnd[0] == INQUIRY) return USB_STOR_TRANSPORT_GOOD; if (us->iobuf[0]) goto Failed; return USB_STOR_TRANSPORT_GOOD; } /* If not UFI, we interpret the data as a result code * The first byte should always be a 0x0. * * Some bogus devices don't follow that rule. They stuff the ASC * into the first byte -- so if it's non-zero, call it a failure. */ if (us->iobuf[0]) { US_DEBUGP("CBI IRQ data showed reserved bType 0x%x\n", us->iobuf[0]); goto Failed; } /* The second byte & 0x0F should be 0x0 for good, otherwise error */ switch (us->iobuf[1] & 0x0F) { case 0x00: return USB_STOR_TRANSPORT_GOOD; case 0x01: goto Failed; } return USB_STOR_TRANSPORT_ERROR; /* the CBI spec requires that the bulk pipe must be cleared * following any data-in/out command failure (section 2.4.3.1.3) */ Failed: if (pipe) usb_stor_clear_halt(us, pipe); return USB_STOR_TRANSPORT_FAILED; }
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); }
/* * Transport for the Freecom USB/IDE adaptor. * */ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) { struct freecom_cb_wrap *fcb; struct freecom_status *fst; unsigned int ipipe, opipe; /* We need both pipes. */ int result; unsigned int partial; int length; fcb = (struct freecom_cb_wrap *) us->iobuf; fst = (struct freecom_status *) us->iobuf; US_DEBUGP("Freecom TRANSPORT STARTED\n"); /* Get handles for both transports. */ opipe = us->send_bulk_pipe; ipipe = us->recv_bulk_pipe; /* The ATAPI Command always goes out first. */ fcb->Type = FCM_PACKET_ATAPI | 0x00; fcb->Timeout = 0; memcpy (fcb->Atapi, srb->cmnd, 12); memset (fcb->Filler, 0, sizeof (fcb->Filler)); US_DEBUG(pdump (srb->cmnd, 12)); /* Send it out. */ result = usb_stor_bulk_transfer_buf (us, opipe, fcb, FCM_PACKET_LENGTH, NULL); /* The Freecom device will only fail if there is something wrong in * USB land. It returns the status in its own registers, which * come back in the bulk pipe. */ if (result != USB_STOR_XFER_GOOD) { US_DEBUGP ("freecom transport error\n"); return USB_STOR_TRANSPORT_ERROR; } /* There are times we can optimize out this status read, but it * doesn't hurt us to always do it now. */ result = usb_stor_bulk_transfer_buf (us, ipipe, fst, FCM_STATUS_PACKET_LENGTH, &partial); US_DEBUGP("foo Status result %d %u\n", result, partial); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; US_DEBUG(pdump ((void *) fst, partial)); /* The firmware will time-out commands after 20 seconds. Some commands * can legitimately take longer than this, so we use a different * command that only waits for the interrupt and then sends status, * without having to send a new ATAPI command to the device. * * NOTE: There is some indication that a data transfer after a timeout * may not work, but that is a condition that should never happen. */ while (fst->Status & FCM_STATUS_BUSY) { US_DEBUGP("20 second USB/ATAPI bridge TIMEOUT occurred!\n"); US_DEBUGP("fst->Status is %x\n", fst->Status); /* Get the status again */ fcb->Type = FCM_PACKET_STATUS; fcb->Timeout = 0; memset (fcb->Atapi, 0, sizeof(fcb->Atapi)); memset (fcb->Filler, 0, sizeof (fcb->Filler)); /* Send it out. */ result = usb_stor_bulk_transfer_buf (us, opipe, fcb, FCM_PACKET_LENGTH, NULL); /* The Freecom device will only fail if there is something * wrong in USB land. It returns the status in its own * registers, which come back in the bulk pipe. */ if (result != USB_STOR_XFER_GOOD) { US_DEBUGP ("freecom transport error\n"); return USB_STOR_TRANSPORT_ERROR; } /* get the data */ result = usb_stor_bulk_transfer_buf (us, ipipe, fst, FCM_STATUS_PACKET_LENGTH, &partial); US_DEBUGP("bar Status result %d %u\n", result, partial); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; US_DEBUG(pdump ((void *) fst, partial)); } if (partial != 4) return USB_STOR_TRANSPORT_ERROR; if ((fst->Status & 1) != 0) { US_DEBUGP("operation failed\n"); return USB_STOR_TRANSPORT_FAILED; } /* The device might not have as much data available as we * requested. If you ask for more than the device has, this reads * and such will hang. */ US_DEBUGP("Device indicates that it has %d bytes available\n", le16_to_cpu (fst->Count)); US_DEBUGP("SCSI requested %d\n", scsi_bufflen(srb)); /* Find the length we desire to read. */ switch (srb->cmnd[0]) { case INQUIRY: case REQUEST_SENSE: /* 16 or 18 bytes? spec says 18, lots of devices only have 16 */ case MODE_SENSE: case MODE_SENSE_10: length = le16_to_cpu(fst->Count); break; default: length = scsi_bufflen(srb); } /* verify that this amount is legal */ if (length > scsi_bufflen(srb)) { length = scsi_bufflen(srb); US_DEBUGP("Truncating request to match buffer length: %d\n", length); } /* What we do now depends on what direction the data is supposed to * move in. */ switch (us->srb->sc_data_direction) { case DMA_FROM_DEVICE: /* catch bogus "read 0 length" case */ if (!length) break; /* Make sure that the status indicates that the device * wants data as well. */ if ((fst->Status & DRQ_STAT) == 0 || (fst->Reason & 3) != 2) { US_DEBUGP("SCSI wants data, drive doesn't have any\n"); return USB_STOR_TRANSPORT_FAILED; } result = freecom_readdata (srb, us, ipipe, opipe, length); if (result != USB_STOR_TRANSPORT_GOOD) return result; US_DEBUGP("FCM: Waiting for status\n"); result = usb_stor_bulk_transfer_buf (us, ipipe, fst, FCM_PACKET_LENGTH, &partial); US_DEBUG(pdump ((void *) fst, partial)); if (partial != 4 || result > USB_STOR_XFER_SHORT) return USB_STOR_TRANSPORT_ERROR; if ((fst->Status & ERR_STAT) != 0) { US_DEBUGP("operation failed\n"); return USB_STOR_TRANSPORT_FAILED; } if ((fst->Reason & 3) != 3) { US_DEBUGP("Drive seems still hungry\n"); return USB_STOR_TRANSPORT_FAILED; } US_DEBUGP("Transfer happy\n"); break; case DMA_TO_DEVICE: /* catch bogus "write 0 length" case */ if (!length) break; /* Make sure the status indicates that the device wants to * send us data. */ /* !!IMPLEMENT!! */ result = freecom_writedata (srb, us, ipipe, opipe, length); if (result != USB_STOR_TRANSPORT_GOOD) return result; US_DEBUGP("FCM: Waiting for status\n"); result = usb_stor_bulk_transfer_buf (us, ipipe, fst, FCM_PACKET_LENGTH, &partial); if (partial != 4 || result > USB_STOR_XFER_SHORT) return USB_STOR_TRANSPORT_ERROR; if ((fst->Status & ERR_STAT) != 0) { US_DEBUGP("operation failed\n"); return USB_STOR_TRANSPORT_FAILED; } if ((fst->Reason & 3) != 3) { US_DEBUGP("Drive seems still hungry\n"); return USB_STOR_TRANSPORT_FAILED; } US_DEBUGP("Transfer happy\n"); break; case DMA_NONE: /* Easy, do nothing. */ break; default: /* should never hit here -- filtered in usb.c */ US_DEBUGP ("freecom unimplemented direction: %d\n", us->srb->sc_data_direction); /* Return fail, SCSI seems to handle this better. */ return USB_STOR_TRANSPORT_FAILED; break; } return USB_STOR_TRANSPORT_GOOD; }
static int sddr55_write_data(struct us_data *us, unsigned int lba, unsigned int page, unsigned short sectors, unsigned char *content, int use_sg) { int result; unsigned char command[8] = { 0, 0, 0, 0, 0, 0xb0, 0, 0x86 }; unsigned char status[8]; struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; unsigned int pba; unsigned int new_pba; unsigned long address; unsigned short pages; unsigned char *buffer = NULL; unsigned char *ptr; struct scatterlist *sg = NULL; int i; int len; int transferred; /* check if we are allowed to write */ if (info->read_only || info->force_read_only) { set_sense_info (7, 0x27, 0); /* read only */ return USB_STOR_TRANSPORT_FAILED; } // If we're using scatter-gather, we have to create a new // buffer to write all of the data in first, since a // scatter-gather buffer could in theory start in the middle // of a page, which would be bad. A developer who wants a // challenge might want to write a limited-buffer // version of this code. len = sectors * PAGESIZE; if (use_sg) { sg = (struct scatterlist *)content; buffer = kmalloc(len, GFP_NOIO); if (buffer == NULL) return USB_STOR_TRANSPORT_ERROR; transferred = 0; for (i=0; i<use_sg && transferred<len; i++) { memcpy(buffer+transferred, sg[i].address, len-transferred > sg[i].length ? sg[i].length : len-transferred); transferred += sg[i].length; } ptr = buffer; } else ptr = content; while (sectors > 0) { /* have we got to end? */ if (lba >= info->max_log_blks) break; pba = info->lba_to_pba[lba]; // Write as many sectors as possible in this block pages = info->blocksize - page; if (pages > (sectors << info->smallpageshift)) pages = (sectors << info->smallpageshift); US_DEBUGP("Write %02X pages, to PBA %04X" " (LBA %04X) page %02X\n", pages, pba, lba, page); command[4] = 0; if (pba == NOT_ALLOCATED) { /* no pba allocated for this lba, find a free pba to use */ int max_pba = (info->max_log_blks / 250 ) * 256; int found_count = 0; int found_pba = -1; /* set pba to first block in zone lba is in */ pba = (lba / 1000) * 1024; US_DEBUGP("No PBA for LBA %04X\n",lba); if (max_pba > 1024) max_pba = 1024; /* scan through the map lookiong for an unused block * leave 16 unused blocks at start (or as many as possible) * since the sddr55 seems to reuse a used block when it shouldn't * if we don't leave space */ for (i = 0; i < max_pba; i++, pba++) { if (info->pba_to_lba[pba] == UNUSED_BLOCK) { found_pba = pba; if (found_count++ > 16) break; } } pba = found_pba; if (pba == -1) { /* oh dear, couldn't find an unallocated block */ US_DEBUGP("Couldn't find unallocated block\n"); set_sense_info (3, 0x31, 0); /* medium error */ if (use_sg) kfree(buffer); return USB_STOR_TRANSPORT_FAILED; } US_DEBUGP("Allocating PBA %04X for LBA %04X\n", pba, lba); /* set writing to unallocated block flag */ command[4] = 0x40; } address = (pba << info->blockshift) + page; command[1] = LSB_of(address>>16); command[2] = LSB_of(address>>8); command[3] = LSB_of(address); /* set the lba into the command, modulo 1000 */ command[0] = LSB_of(lba % 1000); command[6] = MSB_of(lba % 1000); command[4] |= LSB_of(pages >> info->smallpageshift); /* send command */ result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8); if (result != US_BULK_TRANSFER_GOOD) { US_DEBUGP("Result for send_command in write_data %d\n", result); set_sense_info (3, 0x3, 0); /* peripheral write error */ if (use_sg) kfree(buffer); return result; } /* send the data */ result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, ptr, pages<<info->pageshift); if (result != US_BULK_TRANSFER_GOOD) { US_DEBUGP("Result for send_data in write_data %d\n", result); set_sense_info (3, 0x3, 0); /* peripheral write error */ if (use_sg) kfree(buffer); return result; } /* now read status */ result = sddr55_bulk_transport(us, SCSI_DATA_READ, status, 6); if (result != US_BULK_TRANSFER_GOOD) { US_DEBUGP("Result for get_status in write_data %d\n", result); set_sense_info (3, 0x3, 0); /* peripheral write error */ if (use_sg) kfree(buffer); return result; } new_pba = (status[3] + (status[4] << 8) + (status[5] << 16)) >> info->blockshift; /* check status for error */ if (status[0] == 0xff && status[1] == 0x4) { set_sense_info (3, 0x0c, 0); if (use_sg) kfree(buffer); info->pba_to_lba[new_pba] = BAD_BLOCK; return USB_STOR_TRANSPORT_FAILED; } US_DEBUGP("Updating maps for LBA %04X: old PBA %04X, new PBA %04X\n", lba, pba, new_pba); /* update the lba<->pba maps, note new_pba might be the same as pba */ info->lba_to_pba[lba] = new_pba; info->pba_to_lba[pba] = UNUSED_BLOCK; /* check that new_pba wasn't already being used */ if (info->pba_to_lba[new_pba] != UNUSED_BLOCK) { printk(KERN_ERR "sddr55 error: new PBA %04X already in use for LBA %04X\n", new_pba, info->pba_to_lba[new_pba]); info->fatal_error = 1; set_sense_info (3, 0x31, 0); if (use_sg) kfree(buffer); return USB_STOR_TRANSPORT_FAILED; } /* update the pba<->lba maps for new_pba */ info->pba_to_lba[new_pba] = lba % 1000; page = 0; lba++; sectors -= pages >> info->smallpageshift; ptr += (pages << info->pageshift); } if (use_sg) { kfree(buffer); } return USB_STOR_TRANSPORT_GOOD; }
static int sddr55_raw_bulk(struct us_data *us, int direction, unsigned char *data, unsigned int len) { int result; int act_len; int pipe; if (direction == SCSI_DATA_READ) pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); else pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); result = usb_stor_bulk_msg(us, data, pipe, len, &act_len); /* if we stall, we need to clear it before we go on */ if (result == -EPIPE) { US_DEBUGP("EPIPE: clearing endpoint halt for" " pipe 0x%x, stalled at %d bytes\n", pipe, act_len); usb_clear_halt(us->pusb_dev, pipe); } if (result) { /* NAK - that means we've retried a few times already */ if (result == -ETIMEDOUT) { US_DEBUGP("usbat_raw_bulk():" " device NAKed\n"); return US_BULK_TRANSFER_FAILED; } /* -ENOENT -- we canceled this transfer */ if (result == -ENOENT) { US_DEBUGP("usbat_raw_bulk():" " transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; } if (result == -EPIPE) { US_DEBUGP("usbat_raw_bulk():" " output pipe stalled\n"); return US_BULK_TRANSFER_FAILED; } /* the catch-all case */ US_DEBUGP("us_transfer_partial(): unknown error\n"); return US_BULK_TRANSFER_FAILED; } if (act_len != len) { US_DEBUGP("Warning: Transferred only %d bytes\n", act_len); return US_BULK_TRANSFER_SHORT; } US_DEBUGP("Transferred %d of %d bytes\n", act_len, len); return US_BULK_TRANSFER_GOOD; }
static int sddr55_bulk_transport(struct us_data *us, int direction, unsigned char *data, unsigned int len) { int result = USB_STOR_TRANSPORT_GOOD; struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; if (len==0) return USB_STOR_TRANSPORT_GOOD; info->last_access = jiffies; #ifdef CONFIG_USB_STORAGE_DEBUG if (direction == SCSI_DATA_WRITE) { int i; char string[64]; /* Debug-print the first 48 bytes of the write transfer */ strcpy(string, "wr: "); for (i=0; i<len && i<48; i++) { sprintf(string+strlen(string), "%02X ", data[i]); if ((i%16)==15) { US_DEBUGP("%s\n", string); strcpy(string, "wr: "); } } if ((i%16)!=0) US_DEBUGP("%s\n", string); } #endif /* transfer the data */ US_DEBUGP("SCM data %s transfer %d\n", ( direction==SCSI_DATA_READ ? "in" : "out"), len); result = sddr55_raw_bulk(us, direction, data, len); #ifdef CONFIG_USB_STORAGE_DEBUG if (direction == SCSI_DATA_READ) { int i; char string[64]; /* Debug-print the first 48 bytes of the read transfer */ strcpy(string, "rd: "); for (i=0; i<len && i<48; i++) { sprintf(string+strlen(string), "%02X ", data[i]); if ((i%16)==15) { US_DEBUGP("%s\n", string); strcpy(string, "rd: "); } } if ((i%16)!=0) US_DEBUGP("%s\n", string); } #endif return result; }
static int sddr55_read_data(struct us_data *us, unsigned int lba, unsigned int page, unsigned short sectors, unsigned char *content, int use_sg) { int result; unsigned char command[8] = { 0, 0, 0, 0, 0, 0xb0, 0, 0x85 }; unsigned char status[8]; struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; unsigned int pba; unsigned long address; unsigned short pages; unsigned char *buffer = NULL; unsigned char *ptr; struct scatterlist *sg = NULL; int i; int len; int transferred; // If we're using scatter-gather, we have to create a new // buffer to read all of the data in first, since a // scatter-gather buffer could in theory start in the middle // of a page, which would be bad. A developer who wants a // challenge might want to write a limited-buffer // version of this code. len = sectors * PAGESIZE; if (use_sg) { sg = (struct scatterlist *)content; buffer = kmalloc(len, GFP_NOIO); if (buffer == NULL) return USB_STOR_TRANSPORT_ERROR; ptr = buffer; } else ptr = content; // This could be made much more efficient by checking for // contiguous LBA's. Another exercise left to the student. while (sectors>0) { /* have we got to end? */ if (lba >= info->max_log_blks) break; pba = info->lba_to_pba[lba]; // Read as many sectors as possible in this block pages = info->blocksize - page; if (pages > (sectors << info->smallpageshift)) pages = (sectors << info->smallpageshift); US_DEBUGP("Read %02X pages, from PBA %04X" " (LBA %04X) page %02X\n", pages, pba, lba, page); if (pba == NOT_ALLOCATED) { /* no pba for this lba, fill with zeroes */ memset (ptr, 0, pages << info->pageshift); } else { address = (pba << info->blockshift) + page; command[1] = LSB_of(address>>16); command[2] = LSB_of(address>>8); command[3] = LSB_of(address); command[6] = LSB_of(pages << (1 - info->smallpageshift)); /* send command */ result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8); US_DEBUGP("Result for send_command in read_data %d\n", result); if (result != US_BULK_TRANSFER_GOOD) { if (use_sg) kfree(buffer); return result; } /* read data */ result = sddr55_bulk_transport(us, SCSI_DATA_READ, ptr, pages<<info->pageshift); if (result != US_BULK_TRANSFER_GOOD) { if (use_sg) kfree(buffer); return result; } /* now read status */ result = sddr55_bulk_transport(us, SCSI_DATA_READ, status, 2); if (result != US_BULK_TRANSFER_GOOD) { if (use_sg) kfree(buffer); return result; } /* check status for error */ if (status[0] == 0xff && status[1] == 0x4) { set_sense_info (3, 0x11, 0); if (use_sg) kfree(buffer); return USB_STOR_TRANSPORT_FAILED; } } page = 0; lba++; sectors -= pages >> info->smallpageshift; ptr += (pages << info->pageshift); } if (use_sg) { transferred = 0; for (i=0; i<use_sg && transferred<len; i++) { memcpy(sg[i].address, buffer+transferred, len-transferred > sg[i].length ? sg[i].length : len-transferred); transferred += sg[i].length; } kfree(buffer); } return USB_STOR_TRANSPORT_GOOD; }
/* * Interpret the results of a URB transfer * * This function prints appropriate debugging messages, clears halts on * non-control endpoints, and translates the status to the corresponding * USB_STOR_XFER_xxx return code. */ static int interpret_urb_result(struct us_data *us, unsigned int pipe, unsigned int length, int result, unsigned int partial) { US_DEBUGP("Status code %d; transferred %u/%u\n", result, partial, length); switch (result) { /* no error code; did we send all the data? */ case 0: if (partial != length) { US_DEBUGP("-- short transfer\n"); return USB_STOR_XFER_SHORT; } US_DEBUGP("-- transfer complete\n"); return USB_STOR_XFER_GOOD; /* stalled */ case -EPIPE: /* for control endpoints, (used by CB[I]) a stall indicates * a failed command */ if (usb_pipecontrol(pipe)) { US_DEBUGP("-- stall on control pipe\n"); #ifdef CONFIG_USB_STORAGE_DETECT printk(KERN_INFO "usb storage -- stall on control pipe\n"); #endif return USB_STOR_XFER_STALLED; } /* for other sorts of endpoint, clear the stall */ US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); if (usb_stor_clear_halt(us, pipe) < 0) return USB_STOR_XFER_ERROR; return USB_STOR_XFER_STALLED; /* babble - the device tried to send more than we wanted to read */ case -EOVERFLOW: US_DEBUGP("-- babble\n"); #ifdef CONFIG_USB_STORAGE_DETECT printk(KERN_INFO "usb storage -- babble\n"); #endif return USB_STOR_XFER_LONG; /* the transfer was cancelled by abort, disconnect, or timeout */ case -ECONNRESET: US_DEBUGP("-- transfer cancelled\n"); #ifdef CONFIG_USB_STORAGE_DETECT printk(KERN_INFO "usb storage -- transfer cancelled\n"); #endif return USB_STOR_XFER_ERROR; /* short scatter-gather read transfer */ case -EREMOTEIO: US_DEBUGP("-- short read transfer\n"); return USB_STOR_XFER_SHORT; /* abort or disconnect in progress */ case -EIO: US_DEBUGP("-- abort or disconnect in progress\n"); #ifdef CONFIG_USB_STORAGE_DETECT printk(KERN_INFO "usb storage -- abort or disconnect in progress\n"); #endif return USB_STOR_XFER_ERROR; /* the catch-all error case */ default: US_DEBUGP("-- unknown error\n"); #ifdef CONFIG_USB_STORAGE_DETECT printk(KERN_INFO "usb storage -- unknown error %d\n", result); #endif return USB_STOR_XFER_ERROR; } }
/* 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"); goto Handle_Abort; } /* 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"); us->transport_reset(us); srb->result = DID_ERROR << 16; return; } /* 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]; unsigned long old_serial_number; 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 = srb->sense_buffer; /* set the buffer length for transfer */ old_request_bufflen = srb->request_bufflen; srb->request_bufflen = 18; /* set up for no scatter-gather use */ old_sg = srb->use_sg; srb->use_sg = 0; /* change the serial number -- toggle the high bit*/ old_serial_number = srb->serial_number; srb->serial_number ^= 0x80000000; /* 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 */ srb->resid = old_resid; srb->request_buffer = old_request_buffer; srb->request_bufflen = old_request_bufflen; srb->use_sg = old_sg; srb->serial_number = old_serial_number; 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"); goto Handle_Abort; } 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 */ if (!(us->flags & US_FL_SCM_MULT_TARG)) us->transport_reset(us); srb->result = DID_ERROR << 16; 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; /* abort processing: the bulk-only transport requires a reset * following an abort */ Handle_Abort: srb->result = DID_ABORT << 16; if (us->protocol == US_PR_BULK) us->transport_reset(us); }
/* This is the common part of the URB message submission code * * All URBs from the usb-storage driver involved in handling a queued scsi * command _must_ pass through this function (or something like it) for the * abort mechanisms to work properly. */ static int usb_stor_msg_common(struct us_data *us, int timeout) { struct completion urb_done; struct timer_list to_timer; int status; /* don't submit URBs during abort/disconnect processing */ if (us->flags & ABORTING_OR_DISCONNECTING) return -EIO; /* set up data structures for the wakeup system */ init_completion(&urb_done); /* fill the common fields in the URB */ us->current_urb->context = &urb_done; us->current_urb->actual_length = 0; us->current_urb->error_count = 0; us->current_urb->status = 0; /* we assume that if transfer_buffer isn't us->iobuf then it * hasn't been mapped for DMA. Yes, this is clunky, but it's * easier than always having the caller tell us whether the * transfer buffer has already been mapped. */ us->current_urb->transfer_flags = URB_ASYNC_UNLINK | URB_NO_SETUP_DMA_MAP; if (us->current_urb->transfer_buffer == us->iobuf) us->current_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; us->current_urb->transfer_dma = us->iobuf_dma; us->current_urb->setup_dma = us->cr_dma; /* submit the URB */ status = usb_submit_urb(us->current_urb, GFP_NOIO); if (status) { /* something went wrong */ return status; } /* since the URB has been submitted successfully, it's now okay * to cancel it */ set_bit(US_FLIDX_URB_ACTIVE, &us->flags); /* did an abort/disconnect occur during the submission? */ if (us->flags & ABORTING_OR_DISCONNECTING) { /* cancel the URB, if it hasn't been cancelled already */ if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) { US_DEBUGP("-- cancelling URB\n"); usb_unlink_urb(us->current_urb); } } /* submit the timeout timer, if a timeout was requested */ if (timeout > 0) { init_timer(&to_timer); to_timer.expires = jiffies + timeout; to_timer.function = timeout_handler; to_timer.data = (unsigned long) us; add_timer(&to_timer); } /* wait for the completion of the URB */ wait_for_completion(&urb_done); clear_bit(US_FLIDX_URB_ACTIVE, &us->flags); /* clean up the timeout timer */ if (timeout > 0) del_timer_sync(&to_timer); /* return the URB status */ return us->current_urb->status; }
static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) { struct freecom_cb_wrap *fcb; struct freecom_status *fst; unsigned int ipipe, opipe; int result; unsigned int partial; int length; fcb = (struct freecom_cb_wrap *) us->iobuf; fst = (struct freecom_status *) us->iobuf; US_DEBUGP("Freecom TRANSPORT STARTED\n"); opipe = us->send_bulk_pipe; ipipe = us->recv_bulk_pipe; fcb->Type = FCM_PACKET_ATAPI | 0x00; fcb->Timeout = 0; memcpy (fcb->Atapi, srb->cmnd, 12); memset (fcb->Filler, 0, sizeof (fcb->Filler)); US_DEBUG(pdump (srb->cmnd, 12)); result = usb_stor_bulk_transfer_buf (us, opipe, fcb, FCM_PACKET_LENGTH, NULL); if (result != USB_STOR_XFER_GOOD) { US_DEBUGP ("freecom transport error\n"); return USB_STOR_TRANSPORT_ERROR; } result = usb_stor_bulk_transfer_buf (us, ipipe, fst, FCM_STATUS_PACKET_LENGTH, &partial); US_DEBUGP("foo Status result %d %u\n", result, partial); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; US_DEBUG(pdump ((void *) fst, partial)); while (fst->Status & FCM_STATUS_BUSY) { US_DEBUGP("20 second USB/ATAPI bridge TIMEOUT occurred!\n"); US_DEBUGP("fst->Status is %x\n", fst->Status); fcb->Type = FCM_PACKET_STATUS; fcb->Timeout = 0; memset (fcb->Atapi, 0, sizeof(fcb->Atapi)); memset (fcb->Filler, 0, sizeof (fcb->Filler)); result = usb_stor_bulk_transfer_buf (us, opipe, fcb, FCM_PACKET_LENGTH, NULL); if (result != USB_STOR_XFER_GOOD) { US_DEBUGP ("freecom transport error\n"); return USB_STOR_TRANSPORT_ERROR; } result = usb_stor_bulk_transfer_buf (us, ipipe, fst, FCM_STATUS_PACKET_LENGTH, &partial); US_DEBUGP("bar Status result %d %u\n", result, partial); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; US_DEBUG(pdump ((void *) fst, partial)); } if (partial != 4) return USB_STOR_TRANSPORT_ERROR; if ((fst->Status & 1) != 0) { US_DEBUGP("operation failed\n"); return USB_STOR_TRANSPORT_FAILED; } US_DEBUGP("Device indicates that it has %d bytes available\n", le16_to_cpu (fst->Count)); US_DEBUGP("SCSI requested %d\n", scsi_bufflen(srb)); switch (srb->cmnd[0]) { case INQUIRY: case REQUEST_SENSE: case MODE_SENSE: case MODE_SENSE_10: length = le16_to_cpu(fst->Count); break; default: length = scsi_bufflen(srb); } if (length > scsi_bufflen(srb)) { length = scsi_bufflen(srb); US_DEBUGP("Truncating request to match buffer length: %d\n", length); } switch (us->srb->sc_data_direction) { case DMA_FROM_DEVICE: if (!length) break; if ((fst->Status & DRQ_STAT) == 0 || (fst->Reason & 3) != 2) { US_DEBUGP("SCSI wants data, drive doesn't have any\n"); return USB_STOR_TRANSPORT_FAILED; } result = freecom_readdata (srb, us, ipipe, opipe, length); if (result != USB_STOR_TRANSPORT_GOOD) return result; US_DEBUGP("FCM: Waiting for status\n"); result = usb_stor_bulk_transfer_buf (us, ipipe, fst, FCM_PACKET_LENGTH, &partial); US_DEBUG(pdump ((void *) fst, partial)); if (partial != 4 || result > USB_STOR_XFER_SHORT) return USB_STOR_TRANSPORT_ERROR; if ((fst->Status & ERR_STAT) != 0) { US_DEBUGP("operation failed\n"); return USB_STOR_TRANSPORT_FAILED; } if ((fst->Reason & 3) != 3) { US_DEBUGP("Drive seems still hungry\n"); return USB_STOR_TRANSPORT_FAILED; } US_DEBUGP("Transfer happy\n"); break; case DMA_TO_DEVICE: if (!length) break; result = freecom_writedata (srb, us, ipipe, opipe, length); if (result != USB_STOR_TRANSPORT_GOOD) return result; US_DEBUGP("FCM: Waiting for status\n"); result = usb_stor_bulk_transfer_buf (us, ipipe, fst, FCM_PACKET_LENGTH, &partial); if (partial != 4 || result > USB_STOR_XFER_SHORT) return USB_STOR_TRANSPORT_ERROR; if ((fst->Status & ERR_STAT) != 0) { US_DEBUGP("operation failed\n"); return USB_STOR_TRANSPORT_FAILED; } if ((fst->Reason & 3) != 3) { US_DEBUGP("Drive seems still hungry\n"); return USB_STOR_TRANSPORT_FAILED; } US_DEBUGP("Transfer happy\n"); break; case DMA_NONE: break; default: US_DEBUGP ("freecom unimplemented direction: %d\n", us->srb->sc_data_direction); return USB_STOR_TRANSPORT_FAILED; break; } return USB_STOR_TRANSPORT_GOOD; }
static int sddr55_status(struct us_data *us) { int result; unsigned char *command = us->iobuf; unsigned char *status = us->iobuf; struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; /* send command */ memset(command, 0, 8); command[5] = 0xB0; command[7] = 0x80; result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8); US_DEBUGP("Result for send_command in status %d\n", result); if (result != USB_STOR_XFER_GOOD) { set_sense_info (4, 0, 0); /* hardware error */ return USB_STOR_TRANSPORT_ERROR; } result = sddr55_bulk_transport(us, SCSI_DATA_READ, status, 4); /* expect to get short transfer if no card fitted */ if (result == USB_STOR_XFER_SHORT || result == USB_STOR_XFER_STALLED) { /* had a short transfer, no card inserted, free map memory */ if (info->lba_to_pba) kfree(info->lba_to_pba); if (info->pba_to_lba) kfree(info->pba_to_lba); info->lba_to_pba = NULL; info->pba_to_lba = NULL; info->fatal_error = 0; info->force_read_only = 0; set_sense_info (2, 0x3a, 0); /* not ready, medium not present */ return USB_STOR_TRANSPORT_FAILED; } if (result != USB_STOR_XFER_GOOD) { set_sense_info (4, 0, 0); /* hardware error */ return USB_STOR_TRANSPORT_FAILED; } /* check write protect status */ info->read_only = (status[0] & 0x20); /* now read status */ result = sddr55_bulk_transport(us, SCSI_DATA_READ, status, 2); if (result != USB_STOR_XFER_GOOD) { set_sense_info (4, 0, 0); /* hardware error */ } return (result == USB_STOR_XFER_GOOD ? USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_FAILED); }
/* * Transport for the Freecom USB/IDE adaptor. * */ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) { struct freecom_cb_wrap *fcb; struct freecom_status *fst; unsigned int ipipe, opipe; /* We need both pipes. */ int result; unsigned int partial; int length; fcb = (struct freecom_cb_wrap *) us->iobuf; fst = (struct freecom_status *) us->iobuf; US_DEBUGP("Freecom TRANSPORT STARTED\n"); /* Get handles for both transports. */ opipe = us->send_bulk_pipe; ipipe = us->recv_bulk_pipe; /* The ATAPI Command always goes out first. */ fcb->Type = FCM_PACKET_ATAPI | 0x00; fcb->Timeout = 0; memcpy (fcb->Atapi, srb->cmnd, 12); memset (fcb->Filler, 0, sizeof (fcb->Filler)); US_DEBUG(pdump (srb->cmnd, 12)); /* Send it out. */ result = usb_stor_bulk_transfer_buf (us, opipe, fcb, FCM_PACKET_LENGTH, NULL); /* The Freecom device will only fail if there is something wrong in * USB land. It returns the status in its own registers, which * come back in the bulk pipe. */ if (result != USB_STOR_XFER_GOOD) { US_DEBUGP ("freecom transport error\n"); return USB_STOR_TRANSPORT_ERROR; } /* There are times we can optimize out this status read, but it * doesn't hurt us to always do it now. */ result = usb_stor_bulk_transfer_buf (us, ipipe, fst, FCM_STATUS_PACKET_LENGTH, &partial); US_DEBUGP("foo Status result %d %u\n", result, partial); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; US_DEBUG(pdump ((void *) fst, partial)); /* The firmware will time-out commands after 20 seconds. Some commands * can legitimately take longer than this, so we use a different * command that only waits for the interrupt and then sends status, <<<<<<< HEAD * without having to send a new ATAPI command to the device. ======= * without having to send a new ATAPI command to the device. >>>>>>> 296c66da8a02d52243f45b80521febece5ed498a * * NOTE: There is some indication that a data transfer after a timeout * may not work, but that is a condition that should never happen. */ while (fst->Status & FCM_STATUS_BUSY) { US_DEBUGP("20 second USB/ATAPI bridge TIMEOUT occurred!\n"); US_DEBUGP("fst->Status is %x\n", fst->Status); /* Get the status again */ fcb->Type = FCM_PACKET_STATUS; fcb->Timeout = 0; memset (fcb->Atapi, 0, sizeof(fcb->Atapi)); memset (fcb->Filler, 0, sizeof (fcb->Filler)); /* Send it out. */ result = usb_stor_bulk_transfer_buf (us, opipe, fcb, FCM_PACKET_LENGTH, NULL); /* The Freecom device will only fail if there is something * wrong in USB land. It returns the status in its own * registers, which come back in the bulk pipe. */ if (result != USB_STOR_XFER_GOOD) { US_DEBUGP ("freecom transport error\n"); return USB_STOR_TRANSPORT_ERROR; } /* get the data */ result = usb_stor_bulk_transfer_buf (us, ipipe, fst, FCM_STATUS_PACKET_LENGTH, &partial); US_DEBUGP("bar Status result %d %u\n", result, partial); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; US_DEBUG(pdump ((void *) fst, partial)); } if (partial != 4) return USB_STOR_TRANSPORT_ERROR; if ((fst->Status & 1) != 0) { US_DEBUGP("operation failed\n"); return USB_STOR_TRANSPORT_FAILED; } /* The device might not have as much data available as we * requested. If you ask for more than the device has, this reads * and such will hang. */ US_DEBUGP("Device indicates that it has %d bytes available\n", le16_to_cpu (fst->Count)); US_DEBUGP("SCSI requested %d\n", scsi_bufflen(srb)); /* Find the length we desire to read. */ switch (srb->cmnd[0]) { <<<<<<< HEAD case INQUIRY: case REQUEST_SENSE: /* 16 or 18 bytes? spec says 18, lots of devices only have 16 */ case MODE_SENSE: case MODE_SENSE_10: length = le16_to_cpu(fst->Count); break; default: length = scsi_bufflen(srb); ======= case INQUIRY:
/* 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->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 ((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; US_DEBUGP("Issuing auto-REQUEST_SENSE\n"); scsi_eh_prep_cmnd(srb, &ses, NULL, 0, US_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->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 && scsi_bufflen(srb) - scsi_get_resid(srb) < 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_show_sense( unsigned char key, unsigned char asc, unsigned char ascq) { char *keys[] = { "No Sense", "Recovered Error", "Not Ready", "Medium Error", "Hardware Error", "Illegal Request", "Unit Attention", "Data Protect", "Blank Check", "Vendor Specific", "Copy Aborted", "Aborted Command", "(Obsolete)", "Volume Overflow", "Miscompare" }; unsigned short qual = asc; char *what = 0; char *keystr = 0; qual <<= 8; qual |= ascq; if (key>0x0E) keystr = "(Unknown Key)"; else keystr = keys[key]; switch (qual) { case 0x0000: what="no additional sense information"; break; case 0x0001: what="filemark detected"; break; case 0x0002: what="end of partition/medium detected"; break; case 0x0003: what="setmark detected"; break; case 0x0004: what="beginning of partition/medium detected"; break; case 0x0005: what="end of data detected"; break; case 0x0006: what="I/O process terminated"; break; case 0x0011: what="audio play operation in progress"; break; case 0x0012: what="audio play operation paused"; break; case 0x0013: what="audio play operation stopped due to error"; break; case 0x0014: what="audio play operation successfully completed"; break; case 0x0015: what="no current audio status to return"; break; case 0x0016: what="operation in progress"; break; case 0x0017: what="cleaning requested"; break; case 0x0100: what="no index/sector signal"; break; case 0x0200: what="no seek complete"; break; case 0x0300: what="peripheral device write fault"; break; case 0x0301: what="no write current"; break; case 0x0302: what="excessive write errors"; break; case 0x0400: what="LUN not ready, cause not reportable"; break; case 0x0401: what="LUN in process of becoming ready"; break; case 0x0402: what="LUN not ready, initializing cmd. required"; break; case 0x0403: what="LUN not ready, manual intervention required"; break; case 0x0404: what="LUN not ready, format in progress"; break; case 0x0405: what="LUN not ready, rebuild in progress"; break; case 0x0406: what="LUN not ready, recalculation in progress"; break; case 0x0407: what="LUN not ready, operation in progress"; break; case 0x0408: what="LUN not ready, long write in progress"; break; case 0x0500: what="LUN doesn't respond to selection"; break; case 0x0A00: what="error log overflow"; break; case 0x0C04: what="compression check miscompare error"; break; case 0x0C05: what="data expansion occurred during compression"; break; case 0x0C06: what="block not compressible"; break; case 0x1102: what="error too long to correct"; break; case 0x1106: what="CIRC unrecovered error"; break; case 0x1107: what="data resynchronization error"; break; case 0x110D: what="decompression CRC error"; break; case 0x110E: what="can't decompress using declared algorithm"; break; case 0x110F: what="error reading UPC/EAN number"; break; case 0x1110: what="error reading ISRC number"; break; case 0x1200: what="address mark not found for ID field"; break; case 0x1300: what="address mark not found for data field"; break; case 0x1403: what="end of data not found"; break; case 0x1404: what="block sequence error"; break; case 0x1600: what="data sync mark error"; break; case 0x1601: what="data sync error: data rewritten"; break; case 0x1602: what="data sync error: recommend rewrite"; break; case 0x1603: what="data sync error: data auto-reallocated"; break; case 0x1604: what="data sync error: recommend reassignment"; break; case 0x1900: what="defect list error"; break; case 0x1901: what="defect list not available"; break; case 0x1902: what="defect list error in primary list"; break; case 0x1903: what="defect list error in grown list"; break; case 0x1C00: what="defect list not found"; break; case 0x2400: what="invalid field in CDB"; break; case 0x2703: what="associated write protect"; break; case 0x2800: what="not ready to ready transition"; break; case 0x2903: what="bus device reset function occurred"; break; case 0x2904: what="device internal reset"; break; case 0x2B00: what="copy can't execute / host can't disconnect"; break; case 0x2C00: what="command sequence error"; break; case 0x2C03: what="current program area is not empty"; break; case 0x2C04: what="current program area is empty"; break; case 0x2F00: what="commands cleared by another initiator"; break; case 0x3001: what="can't read medium: unknown format"; break; case 0x3002: what="can't read medium: incompatible format"; break; case 0x3003: what="cleaning cartridge installed"; break; case 0x3004: what="can't write medium: unknown format"; break; case 0x3005: what="can't write medium: incompatible format"; break; case 0x3006: what="can't format medium: incompatible medium"; break; case 0x3007: what="cleaning failure"; break; case 0x3008: what="can't write: application code mismatch"; break; case 0x3009: what="current session not fixated for append"; break; case 0x3201: what="defect list update failure"; break; case 0x3400: what="enclosure failure"; break; case 0x3500: what="enclosure services failure"; break; case 0x3502: what="enclosure services unavailable"; break; case 0x3503: what="enclosure services transfer failure"; break; case 0x3504: what="enclosure services transfer refused"; break; case 0x3B0F: what="end of medium reached"; break; case 0x3F02: what="changed operating definition"; break; case 0x4100: what="data path failure (should use 40 NN)"; break; case 0x4A00: what="command phase error"; break; case 0x4B00: what="data phase error"; break; case 0x5100: what="erase failure"; break; case 0x5200: what="cartridge fault"; break; case 0x6300: what="end of user area encountered on this track"; break; case 0x6600: what="automatic document feeder cover up"; break; case 0x6601: what="automatic document feeder lift up"; break; case 0x6602: what="document jam in auto doc feeder"; break; case 0x6603: what="document miss feed auto in doc feeder"; break; case 0x6700: what="configuration failure"; break; case 0x6701: what="configuration of incapable LUN's failed"; break; case 0x6702: what="add logical unit failed"; break; case 0x6706: what="attachment of logical unit failed"; break; case 0x6707: what="creation of logical unit failed"; break; case 0x6900: what="data loss on logical unit"; break; case 0x6E00: what="command to logical unit failed"; break; case 0x7100: what="decompression exception long algorithm ID"; break; case 0x7204: what="empty or partially written reserved track"; break; case 0x7300: what="CD control error"; break; default: if (asc==0x40) { US_DEBUGP("%s: diagnostic failure on component" " %02X\n", keystr, ascq); return; } if (asc==0x70) { US_DEBUGP("%s: decompression exception short" " algorithm ID of %02X\n", keystr, ascq); return; } what = "(unknown ASC/ASCQ)"; } US_DEBUGP("%s: %s\n", keystr, what); }
static int sddr55_read_data(struct us_data *us, unsigned int lba, unsigned int page, unsigned short sectors) { int result = USB_STOR_TRANSPORT_GOOD; unsigned char *command = us->iobuf; unsigned char *status = us->iobuf; struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; unsigned char *buffer; unsigned int pba; unsigned long address; unsigned short pages; unsigned int len, offset; struct scatterlist *sg; // Since we only read in one block at a time, we have to create // a bounce buffer and move the data a piece at a time between the // bounce buffer and the actual transfer buffer. len = min((unsigned int) sectors, (unsigned int) info->blocksize >> info->smallpageshift) * PAGESIZE; buffer = kmalloc(len, GFP_NOIO); if (buffer == NULL) return USB_STOR_TRANSPORT_ERROR; /* out of memory */ offset = 0; sg = NULL; while (sectors>0) { /* have we got to end? */ if (lba >= info->max_log_blks) break; pba = info->lba_to_pba[lba]; // Read as many sectors as possible in this block pages = min((unsigned int) sectors << info->smallpageshift, info->blocksize - page); len = pages << info->pageshift; US_DEBUGP("Read %02X pages, from PBA %04X" " (LBA %04X) page %02X\n", pages, pba, lba, page); if (pba == NOT_ALLOCATED) { /* no pba for this lba, fill with zeroes */ memset (buffer, 0, len); } else { address = (pba << info->blockshift) + page; command[0] = 0; command[1] = LSB_of(address>>16); command[2] = LSB_of(address>>8); command[3] = LSB_of(address); command[4] = 0; command[5] = 0xB0; command[6] = LSB_of(pages << (1 - info->smallpageshift)); command[7] = 0x85; /* send command */ result = sddr55_bulk_transport(us, DMA_TO_DEVICE, command, 8); US_DEBUGP("Result for send_command in read_data %d\n", result); if (result != USB_STOR_XFER_GOOD) { result = USB_STOR_TRANSPORT_ERROR; goto leave; } /* read data */ result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, buffer, len); if (result != USB_STOR_XFER_GOOD) { result = USB_STOR_TRANSPORT_ERROR; goto leave; } /* now read status */ result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, status, 2); if (result != USB_STOR_XFER_GOOD) { result = USB_STOR_TRANSPORT_ERROR; goto leave; } /* check status for error */ if (status[0] == 0xff && status[1] == 0x4) { set_sense_info (3, 0x11, 0); result = USB_STOR_TRANSPORT_FAILED; goto leave; } } // Store the data in the transfer buffer usb_stor_access_xfer_buf(buffer, len, us->srb, &sg, &offset, TO_XFER_BUF); page = 0; lba++; sectors -= pages >> info->smallpageshift; } result = USB_STOR_TRANSPORT_GOOD; leave: kfree(buffer); return result; }
int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) { struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf; unsigned int transfer_length = scsi_bufflen(srb); unsigned int residue; int result; int fake_sense = 0; unsigned int cswlen; unsigned int cbwlen = US_BULK_CB_WRAP_LEN; /* Take care of BULK32 devices; set extra byte to 0 */ if (unlikely(us->fflags & US_FL_BULK32)) { cbwlen = 32; us->iobuf[31] = 0; } /* set up the command wrapper */ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = cpu_to_le32(transfer_length); bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? US_BULK_FLAG_IN : 0; bcb->Tag = ++us->tag; bcb->Lun = srb->device->lun; if (us->fflags & US_FL_SCM_MULT_TARG) bcb->Lun |= srb->device->id << 4; bcb->Length = srb->cmd_len; /* copy the command payload */ memset(bcb->CDB, 0, sizeof(bcb->CDB)); memcpy(bcb->CDB, srb->cmnd, bcb->Length); /* send it to out endpoint */ US_DEBUGP("Bulk Command S 0x%x T 0x%x L %d F %d Trg %d LUN %d CL %d\n", le32_to_cpu(bcb->Signature), bcb->Tag, le32_to_cpu(bcb->DataTransferLength), bcb->Flags, (bcb->Lun >> 4), (bcb->Lun & 0x0F), bcb->Length); result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcb, cbwlen, NULL); US_DEBUGP("Bulk command transfer result=%d\n", result); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; /* DATA STAGE */ /* send/receive data payload, if there is any */ /* Some USB-IDE converter chips need a 100us delay between the * command phase and the data phase. Some devices need a little * more than that, probably because of clock rate inaccuracies. */ if (unlikely(us->fflags & US_FL_GO_SLOW)) udelay(125); if (transfer_length) { unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? us->recv_bulk_pipe : us->send_bulk_pipe; result = usb_stor_bulk_srb(us, pipe, srb); US_DEBUGP("Bulk data transfer result 0x%x\n", result); if (result == USB_STOR_XFER_ERROR) return USB_STOR_TRANSPORT_ERROR; /* If the device tried to send back more data than the * amount requested, the spec requires us to transfer * the CSW anyway. Since there's no point retrying the * the command, we'll return fake sense data indicating * Illegal Request, Invalid Field in CDB. */ if (result == USB_STOR_XFER_LONG) fake_sense = 1; } /* See flow chart on pg 15 of the Bulk Only Transport spec for * an explanation of how this code works. */ /* get CSW for device status */ US_DEBUGP("Attempting to get CSW...\n"); result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, US_BULK_CS_WRAP_LEN, &cswlen); /* Some broken devices add unnecessary zero-length packets to the * end of their data transfers. Such packets show up as 0-length * CSWs. If we encounter such a thing, try to read the CSW again. */ if (result == USB_STOR_XFER_SHORT && cswlen == 0) { US_DEBUGP("Received 0-length CSW; retrying...\n"); result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, US_BULK_CS_WRAP_LEN, &cswlen); } /* did the attempt to read the CSW fail? */ if (result == USB_STOR_XFER_STALLED) { /* get the status again */ US_DEBUGP("Attempting to get CSW (2nd try)...\n"); result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, US_BULK_CS_WRAP_LEN, NULL); } /* if we still have a failure at this point, we're in trouble */ US_DEBUGP("Bulk status result = %d\n", result); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; /* check bulk status */ residue = le32_to_cpu(bcs->Residue); US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n", le32_to_cpu(bcs->Signature), bcs->Tag, residue, bcs->Status); if (!(bcs->Tag == us->tag || (us->fflags & US_FL_BULK_IGNORE_TAG)) || bcs->Status > US_BULK_STAT_PHASE) { US_DEBUGP("Bulk logical error\n"); return USB_STOR_TRANSPORT_ERROR; } /* Some broken devices report odd signatures, so we do not check them * for validity against the spec. We store the first one we see, * and check subsequent transfers for validity against this signature. */ if (!us->bcs_signature) { us->bcs_signature = bcs->Signature; if (us->bcs_signature != cpu_to_le32(US_BULK_CS_SIGN)) US_DEBUGP("Learnt BCS signature 0x%08X\n", le32_to_cpu(us->bcs_signature)); } else if (bcs->Signature != us->bcs_signature) { US_DEBUGP("Signature mismatch: got %08X, expecting %08X\n", le32_to_cpu(bcs->Signature), le32_to_cpu(us->bcs_signature)); return USB_STOR_TRANSPORT_ERROR; } /* try to compute the actual residue, based on how much data * was really transferred and what the device tells us */ if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE)) { /* Heuristically detect devices that generate bogus residues * by seeing what happens with INQUIRY and READ CAPACITY * commands. */ if (bcs->Status == US_BULK_STAT_OK && scsi_get_resid(srb) == 0 && ((srb->cmnd[0] == INQUIRY && transfer_length == 36) || (srb->cmnd[0] == READ_CAPACITY && transfer_length == 8))) { us->fflags |= US_FL_IGNORE_RESIDUE; } else { residue = min(residue, transfer_length); scsi_set_resid(srb, max(scsi_get_resid(srb), (int) residue)); } } /* based on the status code, we report good or bad */ switch (bcs->Status) { case US_BULK_STAT_OK: /* device babbled -- return fake sense data */ if (fake_sense) { memcpy(srb->sense_buffer, usb_stor_sense_invalidCDB, sizeof(usb_stor_sense_invalidCDB)); return USB_STOR_TRANSPORT_NO_SENSE; } /* command good -- note that data could be short */ return USB_STOR_TRANSPORT_GOOD; case US_BULK_STAT_FAIL: /* command failed */ return USB_STOR_TRANSPORT_FAILED; case US_BULK_STAT_PHASE: /* phase error -- note that a transport reset will be * invoked by the invoke_transport() function */ return USB_STOR_TRANSPORT_ERROR; } /* we should never get here, but if we do, we're in trouble */ return USB_STOR_TRANSPORT_ERROR; }
static int sddr55_write_data(struct us_data *us, unsigned int lba, unsigned int page, unsigned short sectors) { int result = USB_STOR_TRANSPORT_GOOD; unsigned char *command = us->iobuf; unsigned char *status = us->iobuf; struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; unsigned char *buffer; unsigned int pba; unsigned int new_pba; unsigned long address; unsigned short pages; int i; unsigned int len, offset; struct scatterlist *sg; /* check if we are allowed to write */ if (info->read_only || info->force_read_only) { set_sense_info (7, 0x27, 0); /* read only */ return USB_STOR_TRANSPORT_FAILED; } // Since we only write one block at a time, we have to create // a bounce buffer and move the data a piece at a time between the // bounce buffer and the actual transfer buffer. len = min((unsigned int) sectors, (unsigned int) info->blocksize >> info->smallpageshift) * PAGESIZE; buffer = kmalloc(len, GFP_NOIO); if (buffer == NULL) return USB_STOR_TRANSPORT_ERROR; offset = 0; sg = NULL; while (sectors > 0) { /* have we got to end? */ if (lba >= info->max_log_blks) break; pba = info->lba_to_pba[lba]; // Write as many sectors as possible in this block pages = min((unsigned int) sectors << info->smallpageshift, info->blocksize - page); len = pages << info->pageshift; // Get the data from the transfer buffer usb_stor_access_xfer_buf(buffer, len, us->srb, &sg, &offset, FROM_XFER_BUF); US_DEBUGP("Write %02X pages, to PBA %04X" " (LBA %04X) page %02X\n", pages, pba, lba, page); command[4] = 0; if (pba == NOT_ALLOCATED) { /* no pba allocated for this lba, find a free pba to use */ int max_pba = (info->max_log_blks / 250 ) * 256; int found_count = 0; int found_pba = -1; /* set pba to first block in zone lba is in */ pba = (lba / 1000) * 1024; US_DEBUGP("No PBA for LBA %04X\n",lba); if (max_pba > 1024) max_pba = 1024; /* * Scan through the map looking for an unused block * leave 16 unused blocks at start (or as many as * possible) since the sddr55 seems to reuse a used * block when it shouldn't if we don't leave space. */ for (i = 0; i < max_pba; i++, pba++) { if (info->pba_to_lba[pba] == UNUSED_BLOCK) { found_pba = pba; if (found_count++ > 16) break; } } pba = found_pba; if (pba == -1) { /* oh dear */ US_DEBUGP("Couldn't find unallocated block\n"); set_sense_info (3, 0x31, 0); /* medium error */ result = USB_STOR_TRANSPORT_FAILED; goto leave; } US_DEBUGP("Allocating PBA %04X for LBA %04X\n", pba, lba); /* set writing to unallocated block flag */ command[4] = 0x40; } address = (pba << info->blockshift) + page; command[1] = LSB_of(address>>16); command[2] = LSB_of(address>>8); command[3] = LSB_of(address); /* set the lba into the command, modulo 1000 */ command[0] = LSB_of(lba % 1000); command[6] = MSB_of(lba % 1000); command[4] |= LSB_of(pages >> info->smallpageshift); command[5] = 0xB0; command[7] = 0x86; /* send command */ result = sddr55_bulk_transport(us, DMA_TO_DEVICE, command, 8); if (result != USB_STOR_XFER_GOOD) { US_DEBUGP("Result for send_command in write_data %d\n", result); /* set_sense_info is superfluous here? */ set_sense_info (3, 0x3, 0);/* peripheral write error */ result = USB_STOR_TRANSPORT_FAILED; goto leave; } /* send the data */ result = sddr55_bulk_transport(us, DMA_TO_DEVICE, buffer, len); if (result != USB_STOR_XFER_GOOD) { US_DEBUGP("Result for send_data in write_data %d\n", result); /* set_sense_info is superfluous here? */ set_sense_info (3, 0x3, 0);/* peripheral write error */ result = USB_STOR_TRANSPORT_FAILED; goto leave; } /* now read status */ result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, status, 6); if (result != USB_STOR_XFER_GOOD) { US_DEBUGP("Result for get_status in write_data %d\n", result); /* set_sense_info is superfluous here? */ set_sense_info (3, 0x3, 0);/* peripheral write error */ result = USB_STOR_TRANSPORT_FAILED; goto leave; } new_pba = (status[3] + (status[4] << 8) + (status[5] << 16)) >> info->blockshift; /* check status for error */ if (status[0] == 0xff && status[1] == 0x4) { info->pba_to_lba[new_pba] = BAD_BLOCK; set_sense_info (3, 0x0c, 0); result = USB_STOR_TRANSPORT_FAILED; goto leave; } US_DEBUGP("Updating maps for LBA %04X: old PBA %04X, new PBA %04X\n", lba, pba, new_pba); /* update the lba<->pba maps, note new_pba might be the same as pba */ info->lba_to_pba[lba] = new_pba; info->pba_to_lba[pba] = UNUSED_BLOCK; /* check that new_pba wasn't already being used */ if (info->pba_to_lba[new_pba] != UNUSED_BLOCK) { printk(KERN_ERR "sddr55 error: new PBA %04X already in use for LBA %04X\n", new_pba, info->pba_to_lba[new_pba]); info->fatal_error = 1; set_sense_info (3, 0x31, 0); result = USB_STOR_TRANSPORT_FAILED; goto leave; } /* update the pba<->lba maps for new_pba */ info->pba_to_lba[new_pba] = lba % 1000; page = 0; lba++; sectors -= pages >> info->smallpageshift; } result = USB_STOR_TRANSPORT_GOOD; leave: kfree(buffer); return result; }
/* 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); }
static unsigned long sddr55_get_capacity(struct us_data *us) { unsigned char uninitialized_var(manufacturerID); unsigned char uninitialized_var(deviceID); int result; struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; US_DEBUGP("Reading capacity...\n"); result = sddr55_read_deviceID(us, &manufacturerID, &deviceID); US_DEBUGP("Result of read_deviceID is %d\n", result); if (result != USB_STOR_XFER_GOOD) return 0; US_DEBUGP("Device ID = %02X\n", deviceID); US_DEBUGP("Manuf ID = %02X\n", manufacturerID); info->pageshift = 9; info->smallpageshift = 0; info->blocksize = 16; info->blockshift = 4; info->blockmask = 15; switch (deviceID) { case 0x6e: // 1MB case 0xe8: case 0xec: info->pageshift = 8; info->smallpageshift = 1; return 0x00100000; case 0xea: // 2MB case 0x64: info->pageshift = 8; info->smallpageshift = 1; case 0x5d: // 5d is a ROM card with pagesize 512. return 0x00200000; case 0xe3: // 4MB case 0xe5: case 0x6b: case 0xd5: return 0x00400000; case 0xe6: // 8MB case 0xd6: return 0x00800000; case 0x73: // 16MB info->blocksize = 32; info->blockshift = 5; info->blockmask = 31; return 0x01000000; case 0x75: // 32MB info->blocksize = 32; info->blockshift = 5; info->blockmask = 31; return 0x02000000; case 0x76: // 64MB info->blocksize = 32; info->blockshift = 5; info->blockmask = 31; return 0x04000000; case 0x79: // 128MB info->blocksize = 32; info->blockshift = 5; info->blockmask = 31; return 0x08000000; default: // unknown return 0; } }
int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) { struct bulk_cb_wrap *bcb; struct bulk_cs_wrap *bcs; int result; int pipe; int partial; int ret = USB_STOR_TRANSPORT_ERROR; bcb = kmalloc(sizeof *bcb, in_interrupt() ? GFP_ATOMIC : GFP_NOIO); if (!bcb) { return USB_STOR_TRANSPORT_ERROR; } bcs = kmalloc(sizeof *bcs, in_interrupt() ? GFP_ATOMIC : GFP_NOIO); if (!bcs) { kfree(bcb); return USB_STOR_TRANSPORT_ERROR; } #ifdef CONFIG_BOARD_W90N745 bcb = (struct bulk_cb_wrap *)((unsigned long)bcb|0x80000000); bcs = (struct bulk_cs_wrap *)((unsigned long)bcs|0x80000000); #endif /* set up the command wrapper */ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = cpu_to_le32(usb_stor_transfer_length(srb)); bcb->Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0; bcb->Tag = srb->serial_number; bcb->Lun = srb->cmnd[1] >> 5; if (us->flags & US_FL_SCM_MULT_TARG) bcb->Lun |= srb->target << 4; bcb->Length = srb->cmd_len; /* construct the pipe handle */ pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); /* copy the command payload */ memset(bcb->CDB, 0, sizeof(bcb->CDB)); memcpy(bcb->CDB, srb->cmnd, bcb->Length); /* send it to out endpoint */ US_DEBUGP("Bulk command S 0x%x T 0x%x Trg %d LUN %d L %d F %d CL %d\n", le32_to_cpu(bcb->Signature), bcb->Tag, (bcb->Lun >> 4), (bcb->Lun & 0x0F), bcb->DataTransferLength, bcb->Flags, bcb->Length); result = usb_stor_bulk_msg(us, bcb, pipe, US_BULK_CB_WRAP_LEN, &partial); US_DEBUGP("Bulk command transfer result=%d\n", result); /* if the command was aborted, indicate that */ if (result == -ENOENT) { ret = USB_STOR_TRANSPORT_ABORTED; goto out; } /* if we stall, we need to clear it before we go on */ if (result == -EPIPE) { US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); result = usb_stor_clear_halt(us, pipe); /* if the command was aborted, indicate that */ if (result == -ENOENT) { ret = USB_STOR_TRANSPORT_ABORTED; goto out; } result = -EPIPE; } else if (result) { /* unknown error -- we've got a problem */ ret = USB_STOR_TRANSPORT_ERROR; goto out; } /* if the command transfered well, then we go to the data stage */ if (result == 0) { /* send/receive data payload, if there is any */ if (bcb->DataTransferLength) { usb_stor_transfer(srb, us); result = srb->result; US_DEBUGP("Bulk data transfer result 0x%x\n", result); /* if it was aborted, we need to indicate that */ if (result == US_BULK_TRANSFER_ABORTED) { ret = USB_STOR_TRANSPORT_ABORTED; goto out; } } } /* See flow chart on pg 15 of the Bulk Only Transport spec for * an explanation of how this code works. */ /* construct the pipe handle */ pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); /* get CSW for device status */ US_DEBUGP("Attempting to get CSW...\n"); result = usb_stor_bulk_msg(us, bcs, pipe, US_BULK_CS_WRAP_LEN, &partial); /* if the command was aborted, indicate that */ if (result == -ENOENT) { ret = USB_STOR_TRANSPORT_ABORTED; goto out; } /* did the attempt to read the CSW fail? */ if (result == -EPIPE) { US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); result = usb_stor_clear_halt(us, pipe); /* if the command was aborted, indicate that */ if (result == -ENOENT) { ret = USB_STOR_TRANSPORT_ABORTED; goto out; } /* get the status again */ US_DEBUGP("Attempting to get CSW (2nd try)...\n"); result = usb_stor_bulk_msg(us, bcs, pipe, US_BULK_CS_WRAP_LEN, &partial); /* if the command was aborted, indicate that */ if (result == -ENOENT) { ret = USB_STOR_TRANSPORT_ABORTED; goto out; } /* if it fails again, we need a reset and return an error*/ if (result == -EPIPE) { US_DEBUGP("clearing halt for pipe 0x%x\n", pipe); result = usb_stor_clear_halt(us, pipe); /* if the command was aborted, indicate that */ if (result == -ENOENT) { ret = USB_STOR_TRANSPORT_ABORTED; } else { ret = USB_STOR_TRANSPORT_ERROR; } goto out; } } /* if we still have a failure at this point, we're in trouble */ US_DEBUGP("Bulk status result = %d\n", result); if (result) { ret = USB_STOR_TRANSPORT_ERROR; goto out; } /* check bulk status */ US_DEBUGP("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n", le32_to_cpu(bcs->Signature), bcs->Tag, bcs->Residue, bcs->Status); if (bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN) || bcs->Tag != bcb->Tag || bcs->Status > US_BULK_STAT_PHASE || partial != 13) { US_DEBUGP("Bulk logical error\n"); ret = USB_STOR_TRANSPORT_ERROR; goto out; } /* based on the status code, we report good or bad */ switch (bcs->Status) { case US_BULK_STAT_OK: /* command good -- note that data could be short */ ret = USB_STOR_TRANSPORT_GOOD; goto out; case US_BULK_STAT_FAIL: /* command failed */ ret = USB_STOR_TRANSPORT_FAILED; goto out; case US_BULK_STAT_PHASE: /* phase error -- note that a transport reset will be * invoked by the invoke_transport() function */ ret = USB_STOR_TRANSPORT_ERROR; goto out; } /* we should never get here, but if we do, we're in trouble */ out: kfree(bcb); kfree(bcs); return ret; }
static int sddr55_read_map(struct us_data *us) { struct sddr55_card_info *info = (struct sddr55_card_info *)(us->extra); int numblocks; unsigned char *buffer; unsigned char *command = us->iobuf; int i; unsigned short lba; unsigned short max_lba; int result; if (!info->capacity) return -1; numblocks = info->capacity >> (info->blockshift + info->pageshift); buffer = kmalloc( numblocks * 2, GFP_NOIO ); if (!buffer) return -1; memset(command, 0, 8); command[5] = 0xB0; command[6] = numblocks * 2 / 256; command[7] = 0x8A; result = sddr55_bulk_transport(us, DMA_TO_DEVICE, command, 8); if ( result != USB_STOR_XFER_GOOD) { kfree (buffer); return -1; } result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, buffer, numblocks * 2); if ( result != USB_STOR_XFER_GOOD) { kfree (buffer); return -1; } result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, command, 2); if ( result != USB_STOR_XFER_GOOD) { kfree (buffer); return -1; } kfree(info->lba_to_pba); kfree(info->pba_to_lba); info->lba_to_pba = kmalloc(numblocks*sizeof(int), GFP_NOIO); info->pba_to_lba = kmalloc(numblocks*sizeof(int), GFP_NOIO); if (info->lba_to_pba == NULL || info->pba_to_lba == NULL) { kfree(info->lba_to_pba); kfree(info->pba_to_lba); info->lba_to_pba = NULL; info->pba_to_lba = NULL; kfree(buffer); return -1; } memset(info->lba_to_pba, 0xff, numblocks*sizeof(int)); memset(info->pba_to_lba, 0xff, numblocks*sizeof(int)); /* set maximum lba */ max_lba = info->max_log_blks; if (max_lba > 1000) max_lba = 1000; // Each block is 64 bytes of control data, so block i is located in // scatterlist block i*64/128k = i*(2^6)*(2^-17) = i*(2^-11) for (i=0; i<numblocks; i++) { int zone = i / 1024; lba = short_pack(buffer[i * 2], buffer[i * 2 + 1]); /* Every 1024 physical blocks ("zone"), the LBA numbers * go back to zero, but are within a higher * block of LBA's. Also, there is a maximum of * 1000 LBA's per zone. In other words, in PBA * 1024-2047 you will find LBA 0-999 which are * really LBA 1000-1999. Yes, this wastes 24 * physical blocks per zone. Go figure. * These devices can have blocks go bad, so there * are 24 spare blocks to use when blocks do go bad. */ /* SDDR55 returns 0xffff for a bad block, and 0x400 for the * CIS block. (Is this true for cards 8MB or less??) * Record these in the physical to logical map */ info->pba_to_lba[i] = lba; if (lba >= max_lba) { continue; } if (info->lba_to_pba[lba + zone * 1000] != NOT_ALLOCATED && !info->force_read_only) { printk("sddr55: map inconsistency at LBA %04X\n", lba + zone * 1000); info->force_read_only = 1; } if (lba<0x10 || (lba>=0x3E0 && lba<0x3EF)) US_DEBUGP("LBA %04X <-> PBA %04X\n", lba, i); info->lba_to_pba[lba + zone * 1000] = i; } kfree(buffer); return 0; }
/* Calculate the length of the data transfer (not the command) for any * given SCSI command */ unsigned int usb_stor_transfer_length(Scsi_Cmnd *srb) { int i; int doDefault = 0; unsigned int len = 0; unsigned int total = 0; struct scatterlist *sg; /* This table tells us: X = command not supported L = return length in cmnd[4] (8 bits). M = return length in cmnd[8] (8 bits). G = return length in cmnd[3] and cmnd[4] (16 bits) H = return length in cmnd[7] and cmnd[8] (16 bits) I = return length in cmnd[8] and cmnd[9] (16 bits) C = return length in cmnd[2] to cmnd[5] (32 bits) D = return length in cmnd[6] to cmnd[9] (32 bits) B = return length in blocksize so we use buff_len R = return length in cmnd[2] to cmnd[4] (24 bits) S = return length in cmnd[3] to cmnd[5] (24 bits) T = return length in cmnd[6] to cmnd[8] (24 bits) U = return length in cmnd[7] to cmnd[9] (24 bits) 0-9 = fixed return length V = 20 bytes W = 24 bytes Z = return length is mode dependant or not in command, use buff_len */ static char *lengths = /* 0123456789ABCDEF 0123456789ABCDEF */ "00XLZ6XZBXBBXXXB" "00LBBLG0R0L0GG0X" /* 00-1F */ "XXXXT8XXB4B0BBBB" "ZZZ0B00HCSSZTBHH" /* 20-3F */ "M0HHB0X000H0HH0X" "XHH0HHXX0TH0H0XX" /* 40-5F */ "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 60-7F */ "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 80-9F */ "X0XXX00XB0BXBXBB" "ZZZ0XUIDU000XHBX" /* A0-BF */ "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* C0-DF */ "XDXXXXXXXXXXXXXX" "XXW00HXXXXXXXXXX"; /* E0-FF */ /* Commands checked in table: CHANGE_DEFINITION 40 COMPARE 39 COPY 18 COPY_AND_VERIFY 3a ERASE 19 ERASE_10 2c ERASE_12 ac EXCHANGE_MEDIUM a6 FORMAT_UNIT 04 GET_DATA_BUFFER_STATUS 34 GET_MESSAGE_10 28 GET_MESSAGE_12 a8 GET_WINDOW 25 !!! Has more data than READ_CAPACITY, need to fix table INITIALIZE_ELEMENT_STATUS 07 !!! REASSIGN_BLOCKS luckily uses buff_len INQUIRY 12 LOAD_UNLOAD 1b LOCATE 2b LOCK_UNLOCK_CACHE 36 LOG_SELECT 4c LOG_SENSE 4d MEDIUM_SCAN 38 !!! This was M MODE_SELECT6 15 MODE_SELECT_10 55 MODE_SENSE_6 1a MODE_SENSE_10 5a MOVE_MEDIUM a5 OBJECT_POSITION 31 !!! Same as SEARCH_DATA_EQUAL PAUSE_RESUME 4b PLAY_AUDIO_10 45 PLAY_AUDIO_12 a5 PLAY_AUDIO_MSF 47 PLAY_AUDIO_TRACK_INDEX 48 PLAY_AUDIO_TRACK_RELATIVE_10 49 PLAY_AUDIO_TRACK_RELATIVE_12 a9 POSITION_TO_ELEMENT 2b PRE-FETCH 34 PREVENT_ALLOW_MEDIUM_REMOVAL 1e PRINT 0a !!! Same as WRITE_6 but is always in bytes READ_6 08 READ_10 28 READ_12 a8 READ_BLOCK_LIMITS 05 READ_BUFFER 3c READ_CAPACITY 25 READ_CDROM_CAPACITY 25 READ_DEFECT_DATA 37 READ_DEFECT_DATA_12 b7 READ_ELEMENT_STATUS b8 !!! Think this is in bytes READ_GENERATION 29 !!! Could also be M? READ_HEADER 44 !!! This was L READ_LONG 3e READ_POSITION 34 !!! This should be V but conflicts with PRE-FETCH READ_REVERSE 0f READ_SUB-CHANNEL 42 !!! Is this in bytes? READ_TOC 43 !!! Is this in bytes? READ_UPDATED_BLOCK 2d REASSIGN_BLOCKS 07 RECEIVE 08 !!! Same as READ_6 probably in bytes though RECEIVE_DIAGNOSTIC_RESULTS 1c RECOVER_BUFFERED_DATA 14 !!! For PRINTERs this is bytes RELEASE_UNIT 17 REQUEST_SENSE 03 REQUEST_VOLUME_ELEMENT_ADDRESS b5 !!! Think this is in bytes RESERVE_UNIT 16 REWIND 01 REZERO_UNIT 01 SCAN 1b !!! Conflicts with various commands, should be L SEARCH_DATA_EQUAL 31 SEARCH_DATA_EQUAL_12 b1 SEARCH_DATA_LOW 30 SEARCH_DATA_LOW_12 b0 SEARCH_DATA_HIGH 32 SEARCH_DATA_HIGH_12 b2 SEEK_6 0b !!! Conflicts with SLEW_AND_PRINT SEEK_10 2b SEND 0a !!! Same as WRITE_6, probably in bytes though SEND 2a !!! Similar to WRITE_10 but for scanners SEND_DIAGNOSTIC 1d SEND_MESSAGE_6 0a !!! Same as WRITE_6 - is in bytes SEND_MESSAGE_10 2a !!! Same as WRITE_10 - is in bytes SEND_MESSAGE_12 aa !!! Same as WRITE_12 - is in bytes SEND_OPC 54 SEND_VOLUME_TAG b6 !!! Think this is in bytes SET_LIMITS 33 SET_LIMITS_12 b3 SET_WINDOW 24 SLEW_AND_PRINT 0b !!! Conflicts with SEEK_6 SPACE 11 START_STOP_UNIT 1b STOP_PRINT 1b SYNCHRONIZE_BUFFER 10 SYNCHRONIZE_CACHE 35 TEST_UNIT_READY 00 UPDATE_BLOCK 3d VERIFY 13 VERIFY 2f VERIFY_12 af WRITE_6 0a WRITE_10 2a WRITE_12 aa WRITE_AND_VERIFY 2e WRITE_AND_VERIFY_12 ae WRITE_BUFFER 3b WRITE_FILEMARKS 10 WRITE_LONG 3f WRITE_SAME 41 */ if (srb->sc_data_direction == SCSI_DATA_WRITE) { doDefault = 1; } else switch (lengths[srb->cmnd[0]]) { case 'L': len = srb->cmnd[4]; break; case 'M': len = srb->cmnd[8]; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': len = lengths[srb->cmnd[0]]-'0'; break; case 'G': len = (((unsigned int)srb->cmnd[3])<<8) | srb->cmnd[4]; break; case 'H': len = (((unsigned int)srb->cmnd[7])<<8) | srb->cmnd[8]; break; case 'I': len = (((unsigned int)srb->cmnd[8])<<8) | srb->cmnd[9]; break; case 'R': len = (((unsigned int)srb->cmnd[2])<<16) | (((unsigned int)srb->cmnd[3])<<8) | srb->cmnd[4]; break; case 'S': len = (((unsigned int)srb->cmnd[3])<<16) | (((unsigned int)srb->cmnd[4])<<8) | srb->cmnd[5]; break; case 'T': len = (((unsigned int)srb->cmnd[6])<<16) | (((unsigned int)srb->cmnd[7])<<8) | srb->cmnd[8]; break; case 'U': len = (((unsigned int)srb->cmnd[7])<<16) | (((unsigned int)srb->cmnd[8])<<8) | srb->cmnd[9]; break; case 'C': len = (((unsigned int)srb->cmnd[2])<<24) | (((unsigned int)srb->cmnd[3])<<16) | (((unsigned int)srb->cmnd[4])<<8) | srb->cmnd[5]; break; case 'D': len = (((unsigned int)srb->cmnd[6])<<24) | (((unsigned int)srb->cmnd[7])<<16) | (((unsigned int)srb->cmnd[8])<<8) | srb->cmnd[9]; break; case 'V': len = 20; break; case 'W': len = 24; break; case 'B': /* Use buffer size due to different block sizes */ doDefault = 1; break; case 'X': US_DEBUGP("Error: UNSUPPORTED COMMAND %02X\n", srb->cmnd[0]); doDefault = 1; break; case 'Z': /* Use buffer size due to mode dependence */ doDefault = 1; break; default: US_DEBUGP("Error: COMMAND %02X out of range or table inconsistent (%c).\n", srb->cmnd[0], lengths[srb->cmnd[0]] ); doDefault = 1; } if ( doDefault == 1 ) { /* Are we going to scatter gather? */ if (srb->use_sg) { /* Add up the sizes of all the sg segments */ sg = (struct scatterlist *) srb->request_buffer; for (i = 0; i < srb->use_sg; i++) total += sg[i].length; len = total; } else /* Just return the length of the buffer */ len = srb->request_bufflen; } return len; }
/* * Transport for the Sandisk SDDR-55 */ int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us) { int result; static unsigned char inquiry_response[8] = { 0x00, 0x80, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x00 }; // write-protected for now, no block descriptor support static unsigned char mode_page_01[20] = { 0x0, 0x12, 0x00, 0x80, 0x0, 0x0, 0x0, 0x0, 0x01, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; unsigned char *ptr = us->iobuf; unsigned long capacity; unsigned int lba; unsigned int pba; unsigned int page; unsigned short pages; struct sddr55_card_info *info; if (!us->extra) { us->extra = kzalloc( sizeof(struct sddr55_card_info), GFP_NOIO); if (!us->extra) return USB_STOR_TRANSPORT_ERROR; us->extra_destructor = sddr55_card_info_destructor; } info = (struct sddr55_card_info *)(us->extra); if (srb->cmnd[0] == REQUEST_SENSE) { US_DEBUGP("SDDR55: request sense %02x/%02x/%02x\n", info->sense_data[2], info->sense_data[12], info->sense_data[13]); memcpy (ptr, info->sense_data, sizeof info->sense_data); ptr[0] = 0x70; ptr[7] = 11; usb_stor_set_xfer_buf (ptr, sizeof info->sense_data, srb); memset (info->sense_data, 0, sizeof info->sense_data); return USB_STOR_TRANSPORT_GOOD; } memset (info->sense_data, 0, sizeof info->sense_data); /* Dummy up a response for INQUIRY since SDDR55 doesn't respond to INQUIRY commands */ if (srb->cmnd[0] == INQUIRY) { memcpy(ptr, inquiry_response, 8); fill_inquiry_response(us, ptr, 36); return USB_STOR_TRANSPORT_GOOD; } /* only check card status if the map isn't allocated, ie no card seen yet * or if it's been over half a second since we last accessed it */ if (info->lba_to_pba == NULL || time_after(jiffies, info->last_access + HZ/2)) { /* check to see if a card is fitted */ result = sddr55_status (us); if (result) { result = sddr55_status (us); if (!result) { set_sense_info (6, 0x28, 0); /* new media, set unit attention, not ready to ready */ } return USB_STOR_TRANSPORT_FAILED; } } /* if we detected a problem with the map when writing, don't allow any more access */ if (info->fatal_error) { set_sense_info (3, 0x31, 0); return USB_STOR_TRANSPORT_FAILED; } if (srb->cmnd[0] == READ_CAPACITY) { capacity = sddr55_get_capacity(us); if (!capacity) { set_sense_info (3, 0x30, 0); /* incompatible medium */ return USB_STOR_TRANSPORT_FAILED; } info->capacity = capacity; /* figure out the maximum logical block number, allowing for * the fact that only 250 out of every 256 are used */ info->max_log_blks = ((info->capacity >> (info->pageshift + info->blockshift)) / 256) * 250; /* Last page in the card, adjust as we only use 250 out of * every 256 pages */ capacity = (capacity / 256) * 250; capacity /= PAGESIZE; capacity--; ((__be32 *) ptr)[0] = cpu_to_be32(capacity); ((__be32 *) ptr)[1] = cpu_to_be32(PAGESIZE); usb_stor_set_xfer_buf(ptr, 8, srb); sddr55_read_map(us); return USB_STOR_TRANSPORT_GOOD; }
void usb_stor_show_command(struct scsi_cmnd *srb) { char *what = NULL; int i; switch (srb->cmnd[0]) { case TEST_UNIT_READY: what = "TEST_UNIT_READY"; break; case REZERO_UNIT: what = "REZERO_UNIT"; break; case REQUEST_SENSE: what = "REQUEST_SENSE"; break; case FORMAT_UNIT: what = "FORMAT_UNIT"; break; case READ_BLOCK_LIMITS: what = "READ_BLOCK_LIMITS"; break; case REASSIGN_BLOCKS: what = "REASSIGN_BLOCKS"; break; case READ_6: what = "READ_6"; break; case WRITE_6: what = "WRITE_6"; break; case SEEK_6: what = "SEEK_6"; break; case READ_REVERSE: what = "READ_REVERSE"; break; case WRITE_FILEMARKS: what = "WRITE_FILEMARKS"; break; case SPACE: what = "SPACE"; break; case INQUIRY: what = "INQUIRY"; break; case RECOVER_BUFFERED_DATA: what = "RECOVER_BUFFERED_DATA"; break; case MODE_SELECT: what = "MODE_SELECT"; break; case RESERVE: what = "RESERVE"; break; case RELEASE: what = "RELEASE"; break; case COPY: what = "COPY"; break; case ERASE: what = "ERASE"; break; case MODE_SENSE: what = "MODE_SENSE"; break; case START_STOP: what = "START_STOP"; break; case RECEIVE_DIAGNOSTIC: what = "RECEIVE_DIAGNOSTIC"; break; case SEND_DIAGNOSTIC: what = "SEND_DIAGNOSTIC"; break; case ALLOW_MEDIUM_REMOVAL: what = "ALLOW_MEDIUM_REMOVAL"; break; case SET_WINDOW: what = "SET_WINDOW"; break; case READ_CAPACITY: what = "READ_CAPACITY"; break; case READ_10: what = "READ_10"; break; case WRITE_10: what = "WRITE_10"; break; case SEEK_10: what = "SEEK_10"; break; case WRITE_VERIFY: what = "WRITE_VERIFY"; break; case VERIFY: what = "VERIFY"; break; case SEARCH_HIGH: what = "SEARCH_HIGH"; break; case SEARCH_EQUAL: what = "SEARCH_EQUAL"; break; case SEARCH_LOW: what = "SEARCH_LOW"; break; case SET_LIMITS: what = "SET_LIMITS"; break; case READ_POSITION: what = "READ_POSITION"; break; case SYNCHRONIZE_CACHE: what = "SYNCHRONIZE_CACHE"; break; case LOCK_UNLOCK_CACHE: what = "LOCK_UNLOCK_CACHE"; break; case READ_DEFECT_DATA: what = "READ_DEFECT_DATA"; break; case MEDIUM_SCAN: what = "MEDIUM_SCAN"; break; case COMPARE: what = "COMPARE"; break; case COPY_VERIFY: what = "COPY_VERIFY"; break; case WRITE_BUFFER: what = "WRITE_BUFFER"; break; case READ_BUFFER: what = "READ_BUFFER"; break; case UPDATE_BLOCK: what = "UPDATE_BLOCK"; break; case READ_LONG: what = "READ_LONG"; break; case WRITE_LONG: what = "WRITE_LONG"; break; case CHANGE_DEFINITION: what = "CHANGE_DEFINITION"; break; case WRITE_SAME: what = "WRITE_SAME"; break; case GPCMD_READ_SUBCHANNEL: what = "READ SUBCHANNEL"; break; case READ_TOC: what = "READ_TOC"; break; case GPCMD_READ_HEADER: what = "READ HEADER"; break; case GPCMD_PLAY_AUDIO_10: what = "PLAY AUDIO (10)"; break; case GPCMD_PLAY_AUDIO_MSF: what = "PLAY AUDIO MSF"; break; case GPCMD_GET_EVENT_STATUS_NOTIFICATION: what = "GET EVENT/STATUS NOTIFICATION"; break; case GPCMD_PAUSE_RESUME: what = "PAUSE/RESUME"; break; case LOG_SELECT: what = "LOG_SELECT"; break; case LOG_SENSE: what = "LOG_SENSE"; break; case GPCMD_STOP_PLAY_SCAN: what = "STOP PLAY/SCAN"; break; case GPCMD_READ_DISC_INFO: what = "READ DISC INFORMATION"; break; case GPCMD_READ_TRACK_RZONE_INFO: what = "READ TRACK INFORMATION"; break; case GPCMD_RESERVE_RZONE_TRACK: what = "RESERVE TRACK"; break; case GPCMD_SEND_OPC: what = "SEND OPC"; break; case MODE_SELECT_10: what = "MODE_SELECT_10"; break; case GPCMD_REPAIR_RZONE_TRACK: what = "REPAIR TRACK"; break; case 0x59: what = "READ MASTER CUE"; break; case MODE_SENSE_10: what = "MODE_SENSE_10"; break; case GPCMD_CLOSE_TRACK: what = "CLOSE TRACK/SESSION"; break; case 0x5C: what = "READ BUFFER CAPACITY"; break; case 0x5D: what = "SEND CUE SHEET"; break; case GPCMD_BLANK: what = "BLANK"; break; case REPORT_LUNS: what = "REPORT LUNS"; break; case MOVE_MEDIUM: what = "MOVE_MEDIUM or PLAY AUDIO (12)"; break; case READ_12: what = "READ_12"; break; case WRITE_12: what = "WRITE_12"; break; case WRITE_VERIFY_12: what = "WRITE_VERIFY_12"; break; case SEARCH_HIGH_12: what = "SEARCH_HIGH_12"; break; case SEARCH_EQUAL_12: what = "SEARCH_EQUAL_12"; break; case SEARCH_LOW_12: what = "SEARCH_LOW_12"; break; case SEND_VOLUME_TAG: what = "SEND_VOLUME_TAG"; break; case READ_ELEMENT_STATUS: what = "READ_ELEMENT_STATUS"; break; case GPCMD_READ_CD_MSF: what = "READ CD MSF"; break; case GPCMD_SCAN: what = "SCAN"; break; case GPCMD_SET_SPEED: what = "SET CD SPEED"; break; case GPCMD_MECHANISM_STATUS: what = "MECHANISM STATUS"; break; case GPCMD_READ_CD: what = "READ CD"; break; case 0xE1: what = "WRITE CONTINUE"; break; case WRITE_LONG_2: what = "WRITE_LONG_2"; break; default: what = "(unknown command)"; break; } US_DEBUGP("Command %s (%d bytes)\n", what, srb->cmd_len); US_DEBUGP(""); for (i = 0; i < srb->cmd_len && i < 16; i++) US_DEBUGPX(" %02x", srb->cmnd[i]); US_DEBUGPX("\n"); }
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; }