📄 aachba.c
字号:
: sizeof(dev->fsa_dev[cid].sense_data)); scsicmd->scsi_done(scsicmd); return 0; }}static int query_disk(struct aac_dev *dev, void __user *arg){ struct aac_query_disk qd; struct fsa_dev_info *fsa_dev_ptr; fsa_dev_ptr = dev->fsa_dev; if (copy_from_user(&qd, arg, sizeof (struct aac_query_disk))) return -EFAULT; if (qd.cnum == -1) qd.cnum = ID_LUN_TO_CONTAINER(qd.id, qd.lun); else if ((qd.bus == -1) && (qd.id == -1) && (qd.lun == -1)) { if (qd.cnum < 0 || qd.cnum >= dev->maximum_num_containers) return -EINVAL; qd.instance = dev->scsi_host_ptr->host_no; qd.bus = 0; qd.id = CONTAINER_TO_ID(qd.cnum); qd.lun = CONTAINER_TO_LUN(qd.cnum); } else return -EINVAL; qd.valid = fsa_dev_ptr[qd.cnum].valid; qd.locked = fsa_dev_ptr[qd.cnum].locked; qd.deleted = fsa_dev_ptr[qd.cnum].deleted; if (fsa_dev_ptr[qd.cnum].devname[0] == '\0') qd.unmapped = 1; else qd.unmapped = 0; strlcpy(qd.name, fsa_dev_ptr[qd.cnum].devname, min(sizeof(qd.name), sizeof(fsa_dev_ptr[qd.cnum].devname) + 1)); if (copy_to_user(arg, &qd, sizeof (struct aac_query_disk))) return -EFAULT; return 0;}static int force_delete_disk(struct aac_dev *dev, void __user *arg){ struct aac_delete_disk dd; struct fsa_dev_info *fsa_dev_ptr; fsa_dev_ptr = dev->fsa_dev; if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk))) return -EFAULT; if (dd.cnum >= dev->maximum_num_containers) return -EINVAL; /* * Mark this container as being deleted. */ fsa_dev_ptr[dd.cnum].deleted = 1; /* * Mark the container as no longer valid */ fsa_dev_ptr[dd.cnum].valid = 0; return 0;}static int delete_disk(struct aac_dev *dev, void __user *arg){ struct aac_delete_disk dd; struct fsa_dev_info *fsa_dev_ptr; fsa_dev_ptr = dev->fsa_dev; if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk))) return -EFAULT; if (dd.cnum >= dev->maximum_num_containers) return -EINVAL; /* * If the container is locked, it can not be deleted by the API. */ if (fsa_dev_ptr[dd.cnum].locked) return -EBUSY; else { /* * Mark the container as no longer being valid. */ fsa_dev_ptr[dd.cnum].valid = 0; fsa_dev_ptr[dd.cnum].devname[0] = '\0'; return 0; }}int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg){ switch (cmd) { case FSACTL_QUERY_DISK: return query_disk(dev, arg); case FSACTL_DELETE_DISK: return delete_disk(dev, arg); case FSACTL_FORCE_DELETE_DISK: return force_delete_disk(dev, arg); case FSACTL_GET_CONTAINERS: return aac_get_containers(dev); default: return -ENOTTY; }}/** * * aac_srb_callback * @context: the context set in the fib - here it is scsi cmd * @fibptr: pointer to the fib * * Handles the completion of a scsi command to a non dasd device * */static void aac_srb_callback(void *context, struct fib * fibptr){ struct aac_dev *dev; struct aac_srb_reply *srbreply; struct scsi_cmnd *scsicmd; scsicmd = (struct scsi_cmnd *) context; dev = (struct aac_dev *)scsicmd->device->host->hostdata; if (fibptr == NULL) BUG(); srbreply = (struct aac_srb_reply *) fib_data(fibptr); scsicmd->sense_buffer[0] = '\0'; /* Initialize sense valid flag to false */ /* * Calculate resid for sg */ scsicmd->resid = scsicmd->request_bufflen - le32_to_cpu(srbreply->data_xfer_length); if(scsicmd->use_sg) pci_unmap_sg(dev->pdev, (struct scatterlist *)scsicmd->buffer, scsicmd->use_sg, scsicmd->sc_data_direction); else if(scsicmd->request_bufflen) pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle, scsicmd->request_bufflen, scsicmd->sc_data_direction); /* * First check the fib status */ if (le32_to_cpu(srbreply->status) != ST_OK){ int len; printk(KERN_WARNING "aac_srb_callback: srb failed, status = %d\n", le32_to_cpu(srbreply->status)); len = (le32_to_cpu(srbreply->sense_data_size) > sizeof(scsicmd->sense_buffer)) ? sizeof(scsicmd->sense_buffer) : le32_to_cpu(srbreply->sense_data_size); scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; memcpy(scsicmd->sense_buffer, srbreply->sense_data, len); } /* * Next check the srb status */ switch( (le32_to_cpu(srbreply->srb_status))&0x3f){ case SRB_STATUS_ERROR_RECOVERY: case SRB_STATUS_PENDING: case SRB_STATUS_SUCCESS: if(scsicmd->cmnd[0] == INQUIRY ){ u8 b; u8 b1; /* We can't expose disk devices because we can't tell whether they * are the raw container drives or stand alone drives. If they have * the removable bit set then we should expose them though. */ b = (*(u8*)scsicmd->buffer)&0x1f; b1 = ((u8*)scsicmd->buffer)[1]; if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER || (b==TYPE_DISK && (b1&0x80)) ){ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; /* * We will allow disk devices if in RAID/SCSI mode and * the channel is 2 */ } else if ((dev->raid_scsi_mode) && (scmd_channel(scsicmd) == 2)) { scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; } else { scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; } } else { scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; } break; case SRB_STATUS_DATA_OVERRUN: switch(scsicmd->cmnd[0]){ case READ_6: case WRITE_6: case READ_10: case WRITE_10: case READ_12: case WRITE_12: case READ_16: case WRITE_16: if(le32_to_cpu(srbreply->data_xfer_length) < scsicmd->underflow ) { printk(KERN_WARNING"aacraid: SCSI CMD underflow\n"); } else { printk(KERN_WARNING"aacraid: SCSI CMD Data Overrun\n"); } scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8; break; case INQUIRY: { u8 b; u8 b1; /* We can't expose disk devices because we can't tell whether they * are the raw container drives or stand alone drives */ b = (*(u8*)scsicmd->buffer)&0x0f; b1 = ((u8*)scsicmd->buffer)[1]; if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER || (b==TYPE_DISK && (b1&0x80)) ){ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; /* * We will allow disk devices if in RAID/SCSI mode and * the channel is 2 */ } else if ((dev->raid_scsi_mode) && (scmd_channel(scsicmd) == 2)) { scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; } else { scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; } break; } default: scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; break; } break; case SRB_STATUS_ABORTED: scsicmd->result = DID_ABORT << 16 | ABORT << 8; break; case SRB_STATUS_ABORT_FAILED: // Not sure about this one - but assuming the hba was trying to abort for some reason scsicmd->result = DID_ERROR << 16 | ABORT << 8; break; case SRB_STATUS_PARITY_ERROR: scsicmd->result = DID_PARITY << 16 | MSG_PARITY_ERROR << 8; break; case SRB_STATUS_NO_DEVICE: case SRB_STATUS_INVALID_PATH_ID: case SRB_STATUS_INVALID_TARGET_ID: case SRB_STATUS_INVALID_LUN: case SRB_STATUS_SELECTION_TIMEOUT: scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; break; case SRB_STATUS_COMMAND_TIMEOUT: case SRB_STATUS_TIMEOUT: scsicmd->result = DID_TIME_OUT << 16 | COMMAND_COMPLETE << 8; break; case SRB_STATUS_BUSY: scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; break; case SRB_STATUS_BUS_RESET: scsicmd->result = DID_RESET << 16 | COMMAND_COMPLETE << 8; break; case SRB_STATUS_MESSAGE_REJECTED: scsicmd->result = DID_ERROR << 16 | MESSAGE_REJECT << 8; break; case SRB_STATUS_REQUEST_FLUSHED: case SRB_STATUS_ERROR: case SRB_STATUS_INVALID_REQUEST: case SRB_STATUS_REQUEST_SENSE_FAILED: case SRB_STATUS_NO_HBA: case SRB_STATUS_UNEXPECTED_BUS_FREE: case SRB_STATUS_PHASE_SEQUENCE_FAILURE: case SRB_STATUS_BAD_SRB_BLOCK_LENGTH: case SRB_STATUS_DELAYED_RETRY: case SRB_STATUS_BAD_FUNCTION: case SRB_STATUS_NOT_STARTED: case SRB_STATUS_NOT_IN_USE: case SRB_STATUS_FORCE_ABORT: case SRB_STATUS_DOMAIN_VALIDATION_FAIL: default:#ifdef AAC_DETAILED_STATUS_INFO printk("aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n", le32_to_cpu(srbreply->srb_status) & 0x3F, aac_get_status_string( le32_to_cpu(srbreply->srb_status) & 0x3F), scsicmd->cmnd[0], le32_to_cpu(srbreply->scsi_status));#endif scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8; break; } if (le32_to_cpu(srbreply->scsi_status) == 0x02 ){ // Check Condition int len; scsicmd->result |= SAM_STAT_CHECK_CONDITION; len = (le32_to_cpu(srbreply->sense_data_size) > sizeof(scsicmd->sense_buffer)) ? sizeof(scsicmd->sense_buffer) : le32_to_cpu(srbreply->sense_data_size);#ifdef AAC_DETAILED_STATUS_INFO printk(KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n", le32_to_cpu(srbreply->status), len);#endif memcpy(scsicmd->sense_buffer, srbreply->sense_data, len); } /* * OR in the scsi status (already shifted up a bit) */ scsicmd->result |= le32_to_cpu(srbreply->scsi_status); fib_complete(fibptr); fib_free(fibptr); scsicmd->scsi_done(scsicmd);}/** * * aac_send_scb_fib * @scsicmd: the scsi command block * * This routine will form a FIB and fill in the aac_srb from the * scsicmd passed in. */static int aac_send_srb_fib(struct scsi_cmnd* scsicmd){ struct fib* cmd_fibcontext; struct aac_dev* dev; int status; struct aac_srb *srbcmd; u16 fibsize; u32 flag; u32 timeout; dev = (struct aac_dev *)scsicmd->device->host->hostdata; if (scsicmd->device->id >= dev->maximum_num_physicals || scsicmd->device->lun > 7) { scsicmd->result = DID_NO_CONNECT << 16; scsicmd->scsi_done(scsicmd); return 0; } dev = (struct aac_dev *)scsicmd->device->host->hostdata; switch(scsicmd->sc_data_direction){ case DMA_TO_DEVICE: flag = SRB_DataOut; break; case DMA_BIDIRECTIONAL: flag = SRB_DataIn | SRB_DataOut; break; case DMA_FROM_DEVICE: flag = SRB_DataIn; break; case DMA_NONE: default: /* shuts up some versions of gcc */ flag = SRB_NoDataXfer; break; } /* * Allocate and initialize a Fib then setup a BlockWrite command */ if (!(cmd_fibcontext = fib_alloc(dev))) { return -1; } fib_init(cmd_fibcontext); srbcmd = (struct aac_srb*) fib_data(cmd_fibcontext); srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); srbcmd->channel = cpu_to_le32(aac_logical_to_phys(scsicmd->device->channel)); srbcmd->id = cpu_to_le32(scsicmd->device->id); srbcmd->lun = cpu_to_le32(scsicmd->device->lun); srbcmd->flags = cpu_to_le32(flag); timeout = scsicmd->timeout_per_command/HZ; if(timeout == 0){ timeout = 1; } srbcmd->timeout = cpu_to_le32(timeout); // timeout in seconds srbcmd->retry_limit = 0; /* Obsolete parameter */ srbcmd->cdb_size = cpu_to_le32(scsicmd->cmd_len); if( dev->dac_support == 1 ) { aac_build_sg64(scsicmd, (struct sgmap64*) &srbcmd->sg); srbcmd->count = cpu_to_le32(scsicmd->request_bufflen); memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len); /* * Build Scatter/Gather list */ fibsize = sizeof (struct aac_srb) - sizeof (struct sgentry) + ((le32_to_cpu(srbcmd->sg.count) & 0xff) * sizeof (struct sgentry64)); BUG_ON (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))); /* * Now send the Fib to the adapter */ status = fib_send(ScsiPortCommand64, cmd_fibcontext, fibsize, FsaNormal, 0, 1, (fib_callback) aac_srb_callback, (void *) scsicmd); } else { aac_build_sg(scsicmd, (struct sgmap*)&srbcmd->sg); srbcmd->count = cpu_to_le32(scsicmd->request_bufflen); memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len); /* * Build Scatter/Gather list */ fibsize = sizeof (struct aac_srb) + (((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) * sizeof (struct sgentry)); BUG_ON (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))); /* * Now send the Fib to the adapte
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -