static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr, struct bio *bio) { int r, ret = 0; /* * fill in all the output members */ hdr->status = rq->errors & 0xff; hdr->masked_status = status_byte(rq->errors); hdr->msg_status = msg_byte(rq->errors); hdr->host_status = host_byte(rq->errors); hdr->driver_status = driver_byte(rq->errors); hdr->info = 0; if (hdr->masked_status || hdr->host_status || hdr->driver_status) hdr->info |= SG_INFO_CHECK; hdr->resid = rq->resid_len; hdr->sb_len_wr = 0; if (rq->sense_len && hdr->sbp) { int len = min((unsigned int) hdr->mx_sb_len, rq->sense_len); if (!copy_to_user(hdr->sbp, rq->sense, len)) hdr->sb_len_wr = len; else ret = -EFAULT; } r = blk_rq_unmap_user(bio); if (!ret) ret = r; blk_put_request(rq); return ret; }
/* * This function is called by the interrupt handler when we * actually have a command that is complete. Change the * flags to indicate that we have a result. */ static void sg_command_done(Scsi_Cmnd * SCpnt) { int dev = MINOR(SCpnt->request.rq_dev); struct scsi_generic *device = &scsi_generics[dev]; if (!device->pending) { printk("unexpected done for sg %d\n",dev); scsi_release_command(SCpnt); SCpnt = NULL; return; } /* * See if the command completed normally, or whether something went * wrong. */ memcpy(device->header.sense_buffer, SCpnt->sense_buffer, sizeof(SCpnt->sense_buffer)); switch (host_byte(SCpnt->result)) { case DID_OK: device->header.result = 0; break; case DID_NO_CONNECT: case DID_BUS_BUSY: case DID_TIME_OUT: device->header.result = EBUSY; break; case DID_BAD_TARGET: case DID_ABORT: case DID_PARITY: case DID_RESET: case DID_BAD_INTR: device->header.result = EIO; break; case DID_ERROR: /* * There really should be DID_UNDERRUN and DID_OVERRUN error values, * and a means for callers of scsi_do_cmd to indicate whether an * underrun or overrun should signal an error. Until that can be * implemented, this kludge allows for returning useful error values * except in cases that return DID_ERROR that might be due to an * underrun. */ if (SCpnt->sense_buffer[0] == 0 && status_byte(SCpnt->result) == GOOD) device->header.result = 0; else device->header.result = EIO; break; } /* * Now wake up the process that is waiting for the * result. */ device->complete=1; scsi_release_command(SCpnt); SCpnt = NULL; wake_up(&scsi_generics[dev].read_wait); }
/* * hp_sw_error_is_retryable - Is an HP-specific check condition retryable? * @req: path activation request * * Examine error codes of request and determine whether the error is retryable. * Some error codes are already retried by scsi-ml (see * scsi_decide_disposition), but some HP specific codes are not. * The intent of this routine is to supply the logic for the HP specific * check conditions. * * Returns: * 1 - command completed with retryable error * 0 - command completed with non-retryable error * * Possible optimizations * 1. More hardware-specific error codes */ static int hp_sw_error_is_retryable(struct request *req) { /* * NOT_READY is known to be retryable * For now we just dump out the sense data and call it retryable */ if (status_byte(req->errors) == CHECK_CONDITION) __scsi_print_sense(DM_HP_HWH_NAME, req->sense, req->sense_len); /* * At this point we don't have complete information about all the error * codes from this hardware, so we are just conservative and retry * when in doubt. */ return 1; }
/* * Parse MODE_SELECT cmd reply. */ static int trespass_endio(struct scsi_device *sdev, int result) { int err = SCSI_DH_OK; struct scsi_sense_hdr sshdr; struct clariion_dh_data *csdev = get_clariion_data(sdev); char *sense = csdev->sense; if (status_byte(result) == CHECK_CONDITION && scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, &sshdr)) { sdev_printk(KERN_ERR, sdev, "Found valid sense data 0x%2x, " "0x%2x, 0x%2x while sending CLARiiON trespass " "command.\n", sshdr.sense_key, sshdr.asc, sshdr.ascq); if ((sshdr.sense_key == 0x05) && (sshdr.asc == 0x04) && (sshdr.ascq == 0x00)) { /* * Array based copy in progress -- do not send * mode_select or copy will be aborted mid-stream. */ sdev_printk(KERN_INFO, sdev, "Array Based Copy in " "progress while sending CLARiiON trespass " "command.\n"); err = SCSI_DH_DEV_TEMP_BUSY; } else if ((sshdr.sense_key == 0x02) && (sshdr.asc == 0x04) && (sshdr.ascq == 0x03)) { /* * LUN Not Ready - Manual Intervention Required * indicates in-progress ucode upgrade (NDU). */ sdev_printk(KERN_INFO, sdev, "Detected in-progress " "ucode upgrade NDU operation while sending " "CLARiiON trespass command.\n"); err = SCSI_DH_DEV_TEMP_BUSY; } else err = SCSI_DH_DEV_FAILED; } else if (result) { sdev_printk(KERN_ERR, sdev, "Error 0x%x while sending " "CLARiiON trespass command.\n", result); err = SCSI_DH_IO; } return err; }
static int sg_io(struct file *file, request_queue_t *q, struct gendisk *bd_disk, struct sg_io_hdr *hdr) { unsigned long start_time, timeout; int writing = 0, ret = 0; struct request *rq; char sense[SCSI_SENSE_BUFFERSIZE]; unsigned char cmd[BLK_MAX_CDB]; struct bio *bio; if (hdr->interface_id != 'S') return -EINVAL; if (hdr->cmd_len > BLK_MAX_CDB) return -EINVAL; if (copy_from_user(cmd, hdr->cmdp, hdr->cmd_len)) return -EFAULT; if (verify_command(file, cmd)) return -EPERM; if (hdr->dxfer_len > (q->max_hw_sectors << 9)) return -EIO; if (hdr->dxfer_len) switch (hdr->dxfer_direction) { default: return -EINVAL; case SG_DXFER_TO_DEV: writing = 1; break; case SG_DXFER_TO_FROM_DEV: case SG_DXFER_FROM_DEV: break; } rq = blk_get_request(q, writing ? WRITE : READ, GFP_KERNEL); if (!rq) return -ENOMEM; /* * fill in request structure */ rq->cmd_len = hdr->cmd_len; memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */ memcpy(rq->cmd, cmd, hdr->cmd_len); memset(sense, 0, sizeof(sense)); rq->sense = sense; rq->sense_len = 0; rq->cmd_type = REQ_TYPE_BLOCK_PC; timeout = msecs_to_jiffies(hdr->timeout); rq->timeout = (timeout < INT_MAX) ? timeout : INT_MAX; if (!rq->timeout) rq->timeout = q->sg_timeout; if (!rq->timeout) rq->timeout = BLK_DEFAULT_TIMEOUT; if (hdr->iovec_count) { const int size = sizeof(struct sg_iovec) * hdr->iovec_count; struct sg_iovec *iov; iov = kmalloc(size, GFP_KERNEL); if (!iov) { ret = -ENOMEM; goto out; } if (copy_from_user(iov, hdr->dxferp, size)) { kfree(iov); ret = -EFAULT; goto out; } ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count, hdr->dxfer_len); kfree(iov); } else if (hdr->dxfer_len) ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len); if (ret) goto out; bio = rq->bio; rq->retries = 0; start_time = jiffies; /* ignore return value. All information is passed back to caller * (if he doesn't check that is his problem). * N.B. a non-zero SCSI status is _not_ necessarily an error. */ blk_execute_rq(q, bd_disk, rq, 0); /* write to all output members */ hdr->status = 0xff & rq->errors; hdr->masked_status = status_byte(rq->errors); hdr->msg_status = msg_byte(rq->errors); hdr->host_status = host_byte(rq->errors); hdr->driver_status = driver_byte(rq->errors); hdr->info = 0; if (hdr->masked_status || hdr->host_status || hdr->driver_status) hdr->info |= SG_INFO_CHECK; hdr->resid = rq->data_len; hdr->duration = ((jiffies - start_time) * 1000) / HZ; hdr->sb_len_wr = 0; if (rq->sense_len && hdr->sbp) { int len = min((unsigned int) hdr->mx_sb_len, rq->sense_len); if (!copy_to_user(hdr->sbp, rq->sense, len)) hdr->sb_len_wr = len; } if (blk_rq_unmap_user(bio)) ret = -EFAULT; /* may not have succeeded, but output values written to control * structure (struct sg_io_hdr). */ out: blk_put_request(rq); return ret; }
void UMAS_UfiCommand(SCSI_CMD_T *srb, UMAS_DATA_T *umas) { int old_cmnd = 0; /* * fix some commands -- this is a form of mode translation * UFI devices only accept 12 byte long commands * * NOTE: This only works because a SCSI_CMD_T struct field contains * a uint8_t cmnd[12], so we know we have storage available */ /* set command length to 12 bytes (this affects the transport layer) */ srb->cmd_len = 12; /* determine the correct (or minimum) data length for these commands */ switch(srb->cmnd[0]) { /* for INQUIRY, UFI devices only ever return 36 bytes */ case INQUIRY: srb->cmnd[4] = 36; break; /* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */ case MODE_SENSE: case MODE_SELECT: /* save the command so we can tell what it was */ old_cmnd = srb->cmnd[0]; srb->cmnd[11] = 0; srb->cmnd[10] = 0; srb->cmnd[9] = 0; /* * If we're sending data, we send all. If getting data, * get the minimum */ if(srb->cmnd[0] == MODE_SELECT) srb->cmnd[8] = srb->cmnd[4]; else srb->cmnd[8] = 8; srb->cmnd[7] = 0; srb->cmnd[6] = 0; srb->cmnd[5] = 0; srb->cmnd[4] = 0; srb->cmnd[3] = 0; srb->cmnd[2] = srb->cmnd[2]; srb->cmnd[1] = srb->cmnd[1]; srb->cmnd[0] = srb->cmnd[0] | 0x40; break; /* again, for MODE_SENSE_10, we get the minimum (8) */ case MODE_SENSE_10: srb->cmnd[7] = 0; srb->cmnd[8] = 8; break; /* for REQUEST_SENSE, UFI devices only ever return 18 bytes */ case REQUEST_SENSE: srb->cmnd[4] = 18; break; /* change READ_6/WRITE_6 to READ_10/WRITE_10, which are UFI commands */ case WRITE_6: case READ_6: srb->cmnd[11] = 0; srb->cmnd[10] = 0; srb->cmnd[9] = 0; srb->cmnd[8] = srb->cmnd[4]; srb->cmnd[7] = 0; srb->cmnd[6] = 0; srb->cmnd[5] = srb->cmnd[3]; srb->cmnd[4] = srb->cmnd[2]; srb->cmnd[3] = srb->cmnd[1] & 0x1F; srb->cmnd[2] = 0; srb->cmnd[1] = srb->cmnd[1] & 0xE0; srb->cmnd[0] = srb->cmnd[0] | 0x20; break; } /* end switch on cmnd[0] */ /* convert MODE_SELECT data here */ if(old_cmnd == MODE_SELECT) usb_stor_scsiSense6to10(srb); /* send the command to the transport layer */ UMAS_InvokeTransport(srb, umas); /* Fix the MODE_SENSE data if we translated the command */ if((old_cmnd == MODE_SENSE) && (status_byte(srb->result) == GOOD)) usb_stor_scsiSense10to6(srb); /* Fix the data for an INQUIRY, if necessary */ fix_inquiry_data(srb); }
void UMAS_AtapiCommand(SCSI_CMD_T *srb, UMAS_DATA_T *umas) { int old_cmnd = 0; /* * Fix some commands -- this is a form of mode translation * ATAPI devices only accept 12 byte long commands * * NOTE: This only works because a SCSI_CMD_T struct field contains * a uint8_t cmnd[12], so we know we have storage available */ /* Pad the ATAPI command with zeros */ for(; srb->cmd_len < 12; srb->cmd_len++) srb->cmnd[srb->cmd_len] = 0; /* set command length to 12 bytes */ srb->cmd_len = 12; /* determine the correct (or minimum) data length for these commands */ switch(srb->cmnd[0]) { /* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */ case MODE_SENSE: case MODE_SELECT: /* save the command so we can tell what it was */ old_cmnd = srb->cmnd[0]; srb->cmnd[11] = 0; srb->cmnd[10] = 0; srb->cmnd[9] = 0; srb->cmnd[8] = srb->cmnd[4]; srb->cmnd[7] = 0; srb->cmnd[6] = 0; srb->cmnd[5] = 0; srb->cmnd[4] = 0; srb->cmnd[3] = 0; srb->cmnd[2] = srb->cmnd[2]; srb->cmnd[1] = srb->cmnd[1]; srb->cmnd[0] = srb->cmnd[0] | 0x40; break; /* change READ_6/WRITE_6 to READ_10/WRITE_10, which are ATAPI commands */ case WRITE_6: case READ_6: srb->cmnd[11] = 0; srb->cmnd[10] = 0; srb->cmnd[9] = 0; srb->cmnd[8] = srb->cmnd[4]; srb->cmnd[7] = 0; srb->cmnd[6] = 0; srb->cmnd[5] = srb->cmnd[3]; srb->cmnd[4] = srb->cmnd[2]; srb->cmnd[3] = srb->cmnd[1] & 0x1F; srb->cmnd[2] = 0; srb->cmnd[1] = srb->cmnd[1] & 0xE0; srb->cmnd[0] = srb->cmnd[0] | 0x20; break; } /* end switch on cmnd[0] */ /* convert MODE_SELECT data here */ if(old_cmnd == MODE_SELECT) usb_stor_scsiSense6to10(srb); /* send the command to the transport layer */ UMAS_InvokeTransport(srb, umas); /* Fix the MODE_SENSE data if we translated the command */ if((old_cmnd == MODE_SENSE) && (status_byte(srb->result) == GOOD)) usb_stor_scsiSense10to6(srb); /* fix the INQUIRY data if necessary */ fix_inquiry_data(srb); }