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; }
static void start_stop_endio(struct request *req, int error) { struct hp_sw_dh_data *h = req->end_io_data; unsigned err = SCSI_DH_OK; if (error || host_byte(req->errors) != DID_OK || msg_byte(req->errors) != COMMAND_COMPLETE) { sdev_printk(KERN_WARNING, h->sdev, "%s: sending start_stop_unit failed with %x\n", HP_SW_NAME, req->errors); err = SCSI_DH_IO; goto done; } if (req->sense_len > 0) { err = start_done(h->sdev, h->sense); if (err == SCSI_DH_RETRY) { err = SCSI_DH_IO; if (--h->retry_cnt) { blk_put_request(req); err = hp_sw_start_stop(h); if (err == SCSI_DH_OK) return; } } } done: blk_put_request(req); if (h->callback_fn) { h->callback_fn(h->callback_data, err); h->callback_fn = h->callback_data = NULL; } return; }
int seagate_st0x_queue_command (Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) { int result, reconnect; Scsi_Cmnd * SCtmp; done_fn = done; current_target = SCpnt->target; current_lun = SCpnt->lun; current_cmnd = SCpnt->cmnd; current_data = (unsigned char *) SCpnt->request_buffer; current_bufflen = SCpnt->request_bufflen; SCint = SCpnt; if(recursion_depth) { return 0; }; recursion_depth++; do{ #ifdef LINKED /* * Set linked command bit in control field of SCSI command. */ current_cmnd[SCpnt->cmd_len] |= 0x01; if (linked_connected) { #if (DEBUG & DEBUG_LINKED) printk("scsi%d : using linked commands, current I_T_L nexus is ", hostno); #endif if ((linked_target == current_target) && (linked_lun == current_lun)) { #if (DEBUG & DEBUG_LINKED) printk("correct\n"); #endif reconnect = LINKED_RIGHT; } else { #if (DEBUG & DEBUG_LINKED) printk("incorrect\n"); #endif reconnect = LINKED_WRONG; } } else #endif /* LINKED */ reconnect = CAN_RECONNECT; result = internal_command (SCint->target, SCint->lun, SCint->cmnd, SCint->request_buffer, SCint->request_bufflen, reconnect); if (msg_byte(result) == DISCONNECT) break; SCtmp = SCint; SCint = NULL; SCtmp->result = result; done_fn (SCtmp); } while(SCint); recursion_depth--; return 0; }
/* print - print a message */ void print(int msg) { int ch; msg_open(msg); while (ch = msg_byte()) trm_chr(ch); }
/* * alua_stpg - Evaluate SET TARGET GROUP STATES * @sdev: the device to be evaluated * @state: the new target group state * * Send a SET TARGET GROUP STATES command to the device. * We only have to test here if we should resubmit the command; * any other error is assumed as a failure. */ static void stpg_endio(struct request *req, int error) { struct alua_dh_data *h = req->end_io_data; struct scsi_sense_hdr sense_hdr; unsigned err = SCSI_DH_OK; if (host_byte(req->errors) != DID_OK || msg_byte(req->errors) != COMMAND_COMPLETE) { err = SCSI_DH_IO; goto done; } if (req->sense_len > 0) { err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE, &sense_hdr); if (!err) { err = SCSI_DH_IO; goto done; } err = alua_check_sense(h->sdev, &sense_hdr); if (err == ADD_TO_MLQUEUE) { err = SCSI_DH_RETRY; goto done; } sdev_printk(KERN_INFO, h->sdev, "%s: stpg sense code: %02x/%02x/%02x\n", ALUA_DH_NAME, sense_hdr.sense_key, sense_hdr.asc, sense_hdr.ascq); err = SCSI_DH_IO; } else if (error) err = SCSI_DH_IO; if (err == SCSI_DH_OK) { h->state = TPGS_STATE_OPTIMIZED; sdev_printk(KERN_INFO, h->sdev, "%s: port group %02x switched to state %c\n", ALUA_DH_NAME, h->group_id, print_alua_state(h->state)); } done: req->end_io_data = NULL; __blk_put_request(req->q, req); if (h->callback_fn) { h->callback_fn(h->callback_data, err); h->callback_fn = h->callback_data = NULL; } return; }
/* * stpg_endio - Evaluate SET TARGET GROUP STATES * @sdev: the device to be evaluated * @state: the new target group state * * Evaluate a SET TARGET GROUP STATES command response. */ static void stpg_endio(struct request *req, int error) { struct alua_dh_data *h = req->end_io_data; struct scsi_sense_hdr sense_hdr; unsigned err = SCSI_DH_OK; if (host_byte(req->errors) != DID_OK || msg_byte(req->errors) != COMMAND_COMPLETE) { err = SCSI_DH_IO; goto done; } if (scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE, &sense_hdr)) { if (sense_hdr.sense_key == NOT_READY && sense_hdr.asc == 0x04 && sense_hdr.ascq == 0x0a) { /* ALUA state transition already in progress */ err = SCSI_DH_OK; goto done; } if (sense_hdr.sense_key == UNIT_ATTENTION) { err = SCSI_DH_RETRY; goto done; } sdev_printk(KERN_INFO, h->sdev, "%s: stpg failed\n", ALUA_DH_NAME); scsi_print_sense_hdr(h->sdev, ALUA_DH_NAME, &sense_hdr); err = SCSI_DH_IO; } else if (error) err = SCSI_DH_IO; if (err == SCSI_DH_OK) { h->state = TPGS_STATE_OPTIMIZED; sdev_printk(KERN_INFO, h->sdev, "%s: port group %02x switched to state %c\n", ALUA_DH_NAME, h->group_id, print_alua_state(h->state)); } done: req->end_io_data = NULL; __blk_put_request(req->q, req); if (h->callback_fn) { h->callback_fn(h->callback_data, err); h->callback_fn = h->callback_data = NULL; } return; }
static void seagate_reconnect_intr(int irq, void *dev_id, struct pt_regs *regs) { int temp; Scsi_Cmnd * SCtmp; /* enable all other interrupts. */ sti(); #if (DEBUG & PHASE_RESELECT) printk("scsi%d : seagate_reconnect_intr() called\n", hostno); #endif if (!should_reconnect) printk("scsi%d: unexpected interrupt.\n", hostno); else { should_reconnect = 0; #if (DEBUG & PHASE_RESELECT) printk("scsi%d : internal_command(" "%d, %08x, %08x, %d, RECONNECT_NOW\n", hostno, current_target, current_data, current_bufflen); #endif temp = internal_command (current_target, current_lun, current_cmnd, current_data, current_bufflen, RECONNECT_NOW); if (msg_byte(temp) != DISCONNECT) { if (done_fn) { #if (DEBUG & PHASE_RESELECT) printk("scsi%d : done_fn(%d,%08x)", hostno, hostno, temp); #endif if(!SCint) panic("SCint == NULL in seagate"); SCtmp = SCint; SCint = NULL; SCtmp->result = temp; done_fn (SCtmp); } else printk("done_fn() not defined.\n"); } } }
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; }