📄 aachba.c
字号:
printk(KERN_WARNING "aac_write: fib_send failed with status: %d\n", status); /* * For some reason, the Fib didn't queue, return QUEUE_FULL */ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL; scsicmd->scsi_done(scsicmd); fib_complete(cmd_fibcontext); fib_free(cmd_fibcontext); return 0;}static void synchronize_callback(void *context, struct fib *fibptr){ struct aac_synchronize_reply *synchronizereply; struct scsi_cmnd *cmd; cmd = context; dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies)); BUG_ON(fibptr == NULL); synchronizereply = fib_data(fibptr); if (le32_to_cpu(synchronizereply->status) == CT_OK) cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; else { struct scsi_device *sdev = cmd->device; struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata; u32 cid = ID_LUN_TO_CONTAINER(sdev->id, sdev->lun); printk(KERN_WARNING "synchronize_callback: synchronize failed, status = %d\n", le32_to_cpu(synchronizereply->status)); cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; set_sense((u8 *)&dev->fsa_dev[cid].sense_data, HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE, ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0, 0, 0); memcpy(cmd->sense_buffer, &dev->fsa_dev[cid].sense_data, min(sizeof(dev->fsa_dev[cid].sense_data), sizeof(cmd->sense_buffer))); } fib_complete(fibptr); fib_free(fibptr); cmd->scsi_done(cmd);}static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid){ int status; struct fib *cmd_fibcontext; struct aac_synchronize *synchronizecmd; struct scsi_cmnd *cmd; struct scsi_device *sdev = scsicmd->device; int active = 0; unsigned long flags; /* * Wait for all commands to complete to this specific * target (block). */ spin_lock_irqsave(&sdev->list_lock, flags); list_for_each_entry(cmd, &sdev->cmd_list, list) if (cmd != scsicmd && cmd->serial_number != 0) { ++active; break; } spin_unlock_irqrestore(&sdev->list_lock, flags); /* * Yield the processor (requeue for later) */ if (active) return SCSI_MLQUEUE_DEVICE_BUSY; /* * Allocate and initialize a Fib */ if (!(cmd_fibcontext = fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata))) return SCSI_MLQUEUE_HOST_BUSY; fib_init(cmd_fibcontext); synchronizecmd = fib_data(cmd_fibcontext); synchronizecmd->command = cpu_to_le32(VM_ContainerConfig); synchronizecmd->type = cpu_to_le32(CT_FLUSH_CACHE); synchronizecmd->cid = cpu_to_le32(cid); synchronizecmd->count = cpu_to_le32(sizeof(((struct aac_synchronize_reply *)NULL)->data)); /* * Now send the Fib to the adapter */ status = fib_send(ContainerCommand, cmd_fibcontext, sizeof(struct aac_synchronize), FsaNormal, 0, 1, (fib_callback)synchronize_callback, (void *)scsicmd); /* * Check that the command queued to the controller */ if (status == -EINPROGRESS) return 0; printk(KERN_WARNING "aac_synchronize: fib_send failed with status: %d.\n", status); fib_complete(cmd_fibcontext); fib_free(cmd_fibcontext); return SCSI_MLQUEUE_HOST_BUSY;}/** * aac_scsi_cmd() - Process SCSI command * @scsicmd: SCSI command block * * Emulate a SCSI command and queue the required request for the * aacraid firmware. */ int aac_scsi_cmd(struct scsi_cmnd * scsicmd){ u32 cid = 0; struct Scsi_Host *host = scsicmd->device->host; struct aac_dev *dev = (struct aac_dev *)host->hostdata; struct fsa_dev_info *fsa_dev_ptr = dev->fsa_dev; int ret; /* * If the bus, id or lun is out of range, return fail * Test does not apply to ID 16, the pseudo id for the controller * itself. */ if (scmd_id(scsicmd) != host->this_id) { if ((scsicmd->device->channel == 0) ){ if( (scsicmd->device->id >= dev->maximum_num_containers) || (scsicmd->device->lun != 0)){ scsicmd->result = DID_NO_CONNECT << 16; scsicmd->scsi_done(scsicmd); return 0; } cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun); /* * If the target container doesn't exist, it may have * been newly created */ if ((fsa_dev_ptr[cid].valid & 1) == 0) { switch (scsicmd->cmnd[0]) { case SERVICE_ACTION_IN: if (!(dev->raw_io_interface) || !(dev->raw_io_64) || ((scsicmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16)) break; case INQUIRY: case READ_CAPACITY: case TEST_UNIT_READY: spin_unlock_irq(host->host_lock); probe_container(dev, cid); if ((fsa_dev_ptr[cid].valid & 1) == 0) fsa_dev_ptr[cid].valid = 0; spin_lock_irq(host->host_lock); if (fsa_dev_ptr[cid].valid == 0) { scsicmd->result = DID_NO_CONNECT << 16; scsicmd->scsi_done(scsicmd); return 0; } default: break; } } /* * If the target container still doesn't exist, * return failure */ if (fsa_dev_ptr[cid].valid == 0) { scsicmd->result = DID_BAD_TARGET << 16; scsicmd->scsi_done(scsicmd); return 0; } } else { /* check for physical non-dasd devices */ if(dev->nondasd_support == 1){ return aac_send_srb_fib(scsicmd); } else { scsicmd->result = DID_NO_CONNECT << 16; scsicmd->scsi_done(scsicmd); return 0; } } } /* * else Command for the controller itself */ else if ((scsicmd->cmnd[0] != INQUIRY) && /* only INQUIRY & TUR cmnd supported for controller */ (scsicmd->cmnd[0] != TEST_UNIT_READY)) { dprintk((KERN_WARNING "Only INQUIRY & TUR command supported for controller, rcvd = 0x%x.\n", scsicmd->cmnd[0])); scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; set_sense((u8 *) &dev->fsa_dev[cid].sense_data, ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND, ASENCODE_INVALID_COMMAND, 0, 0, 0, 0); memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(scsicmd->sense_buffer)) ? sizeof(scsicmd->sense_buffer) : sizeof(dev->fsa_dev[cid].sense_data)); scsicmd->scsi_done(scsicmd); return 0; } /* Handle commands here that don't really require going out to the adapter */ switch (scsicmd->cmnd[0]) { case INQUIRY: { struct inquiry_data inq_data; dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scsicmd->device->id)); memset(&inq_data, 0, sizeof (struct inquiry_data)); inq_data.inqd_ver = 2; /* claim compliance to SCSI-2 */ inq_data.inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */ inq_data.inqd_len = 31; /*Format for "pad2" is RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe */ inq_data.inqd_pad2= 0x32 ; /*WBus16|Sync|CmdQue */ /* * Set the Vendor, Product, and Revision Level * see: <vendor>.c i.e. aac.c */ if (scmd_id(scsicmd) == host->this_id) { setinqstr(dev, (void *) (inq_data.inqd_vid), (sizeof(container_types)/sizeof(char *))); inq_data.inqd_pdt = INQD_PDT_PROC; /* Processor device */ aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data)); scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; scsicmd->scsi_done(scsicmd); return 0; } setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type); inq_data.inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data)); return aac_get_container_name(scsicmd, cid); } case SERVICE_ACTION_IN: if (!(dev->raw_io_interface) || !(dev->raw_io_64) || ((scsicmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16)) break; { u64 capacity; char cp[13]; dprintk((KERN_DEBUG "READ CAPACITY_16 command.\n")); capacity = fsa_dev_ptr[cid].size - 1; cp[0] = (capacity >> 56) & 0xff; cp[1] = (capacity >> 48) & 0xff; cp[2] = (capacity >> 40) & 0xff; cp[3] = (capacity >> 32) & 0xff; cp[4] = (capacity >> 24) & 0xff; cp[5] = (capacity >> 16) & 0xff; cp[6] = (capacity >> 8) & 0xff; cp[7] = (capacity >> 0) & 0xff; cp[8] = 0; cp[9] = 0; cp[10] = 2; cp[11] = 0; cp[12] = 0; aac_internal_transfer(scsicmd, cp, 0, min((unsigned int)scsicmd->cmnd[13], sizeof(cp))); if (sizeof(cp) < scsicmd->cmnd[13]) { unsigned int len, offset = sizeof(cp); memset(cp, 0, offset); do { len = min(scsicmd->cmnd[13]-offset, sizeof(cp)); aac_internal_transfer(scsicmd, cp, offset, len); } while ((offset += len) < scsicmd->cmnd[13]); } /* Do not cache partition table for arrays */ scsicmd->device->removable = 1; scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; scsicmd->scsi_done(scsicmd); return 0; } case READ_CAPACITY: { u32 capacity; char cp[8]; dprintk((KERN_DEBUG "READ CAPACITY command.\n")); if (fsa_dev_ptr[cid].size <= 0x100000000ULL) capacity = fsa_dev_ptr[cid].size - 1; else capacity = (u32)-1; cp[0] = (capacity >> 24) & 0xff; cp[1] = (capacity >> 16) & 0xff; cp[2] = (capacity >> 8) & 0xff; cp[3] = (capacity >> 0) & 0xff; cp[4] = 0; cp[5] = 0; cp[6] = 2; cp[7] = 0; aac_internal_transfer(scsicmd, cp, 0, sizeof(cp)); /* Do not cache partition table for arrays */ scsicmd->device->removable = 1; scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; scsicmd->scsi_done(scsicmd); return 0; } case MODE_SENSE: { char mode_buf[4]; dprintk((KERN_DEBUG "MODE SENSE command.\n")); mode_buf[0] = 3; /* Mode data length */ mode_buf[1] = 0; /* Medium type - default */ mode_buf[2] = 0; /* Device-specific param, bit 8: 0/1 = write enabled/protected */ mode_buf[3] = 0; /* Block descriptor length */ aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf)); scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; scsicmd->scsi_done(scsicmd); return 0; } case MODE_SENSE_10: { char mode_buf[8]; dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n")); mode_buf[0] = 0; /* Mode data length (MSB) */ mode_buf[1] = 6; /* Mode data length (LSB) */ mode_buf[2] = 0; /* Medium type - default */ mode_buf[3] = 0; /* Device-specific param, bit 8: 0/1 = write enabled/protected */ mode_buf[4] = 0; /* reserved */ mode_buf[5] = 0; /* reserved */ mode_buf[6] = 0; /* Block descriptor length (MSB) */ mode_buf[7] = 0; /* Block descriptor length (LSB) */ aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf)); scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; scsicmd->scsi_done(scsicmd); return 0; } case REQUEST_SENSE: dprintk((KERN_DEBUG "REQUEST SENSE command.\n")); memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, sizeof (struct sense_data)); memset(&dev->fsa_dev[cid].sense_data, 0, sizeof (struct sense_data)); scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; scsicmd->scsi_done(scsicmd); return 0; case ALLOW_MEDIUM_REMOVAL: dprintk((KERN_DEBUG "LOCK command.\n")); if (scsicmd->cmnd[4]) fsa_dev_ptr[cid].locked = 1; else fsa_dev_ptr[cid].locked = 0; scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; scsicmd->scsi_done(scsicmd); return 0; /* * These commands are all No-Ops */ case TEST_UNIT_READY: case RESERVE: case RELEASE: case REZERO_UNIT: case REASSIGN_BLOCKS: case SEEK_10: case START_STOP: scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; scsicmd->scsi_done(scsicmd); return 0; } switch (scsicmd->cmnd[0]) { case READ_6: case READ_10: case READ_12: case READ_16: /* * Hack to keep track of ordinal number of the device that * corresponds to a container. Needed to convert * containers to /dev/sd device names */ spin_unlock_irq(host->host_lock); if (scsicmd->request->rq_disk) strlcpy(fsa_dev_ptr[cid].devname, scsicmd->request->rq_disk->disk_name, min(sizeof(fsa_dev_ptr[cid].devname), sizeof(scsicmd->request->rq_disk->disk_name) + 1)); ret = aac_read(scsicmd, cid); spin_lock_irq(host->host_lock); return ret; case WRITE_6: case WRITE_10: case WRITE_12: case WRITE_16: spin_unlock_irq(host->host_lock); ret = aac_write(scsicmd, cid); spin_lock_irq(host->host_lock); return ret; case SYNCHRONIZE_CACHE: /* Issue FIB to tell Firmware to flush it's cache */ return aac_synchronize(scsicmd, cid); default: /* * Unhandled commands */ dprintk((KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", scsicmd->cmnd[0])); scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; set_sense((u8 *) &dev->fsa_dev[cid].sense_data, ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND, ASENCODE_INVALID_COMMAND, 0, 0, 0, 0); memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(scsicmd->sense_buffer)) ? sizeof(scsicmd->sense_buffer)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -