📄 aachba.c
字号:
}/** * * 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 - 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 = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))? sizeof(scsicmd->sense_buffer):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) && (scsicmd->device->channel == 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: 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) && (scsicmd->device->channel == 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 = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))? sizeof(scsicmd->sense_buffer):srbreply->sense_data_size;#ifdef AAC_DETAILED_STATUS_INFO dprintk((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); aac_io_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; if( scsicmd->device->id > 15 || 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-jiffies)/HZ; if(timeout == 0){ timeout = 1; } srbcmd->timeout = cpu_to_le32(timeout); // timeout in seconds srbcmd->retry_limit =cpu_to_le32(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) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry64)); /* * 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) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry)); /* * Now send the Fib to the adapter */ status = fib_send(ScsiPortCommand, cmd_fibcontext, fibsize, FsaNormal, 0, 1, (fib_callback) aac_srb_callback, (void *) scsicmd); } /* * Check that the command queued to the controller */ if (status == -EINPROGRESS){ return 0; } printk(KERN_WARNING "aac_srb: fib_send failed with status: %d\n", status); fib_complete(cmd_fibcontext); fib_free(cmd_fibcontext); return -1;}static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg){ struct aac_dev *dev; unsigned long byte_count = 0; dev = (struct aac_dev *)scsicmd->device->host->hostdata; // Get rid of old data psg->count = cpu_to_le32(0); psg->sg[0].addr = cpu_to_le32(0); psg->sg[0].count = cpu_to_le32(0); if (scsicmd->use_sg) { struct scatterlist *sg; int i; int sg_count; sg = (struct scatterlist *) scsicmd->request_buffer; sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg, scsicmd->sc_data_direction); psg->count = cpu_to_le32(sg_count); byte_count = 0; for (i = 0; i < sg_count; i++) { psg->sg[i].addr = cpu_to_le32(sg_dma_address(sg)); psg->sg[i].count = cpu_to_le32(sg_dma_len(sg)); byte_count += sg_dma_len(sg); sg++; } /* hba wants the size to be exact */ if(byte_count > scsicmd->request_bufflen){ psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen); byte_count = scsicmd->request_bufflen; } /* Check for command underflow */ if(scsicmd->underflow && (byte_count < scsicmd->underflow)){ printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n", byte_count, scsicmd->underflow); } } else if(scsicmd->request_bufflen) { dma_addr_t addr; addr = pci_map_single(dev->pdev, scsicmd->request_buffer, scsicmd->request_bufflen, scsicmd->sc_data_direction); psg->count = cpu_to_le32(1); psg->sg[0].addr = cpu_to_le32(addr); psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen); scsicmd->SCp.dma_handle = addr; byte_count = scsicmd->request_bufflen; } return byte_count;}static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg){ struct aac_dev *dev; unsigned long byte_count = 0; u64 le_addr; dev = (struct aac_dev *)scsicmd->device->host->hostdata; // Get rid of old data psg->count = cpu_to_le32(0); psg->sg[0].addr[0] = cpu_to_le32(0); psg->sg[0].addr[1] = cpu_to_le32(0); psg->sg[0].count = cpu_to_le32(0); if (scsicmd->use_sg) { struct scatterlist *sg; int i; int sg_count; sg = (struct scatterlist *) scsicmd->request_buffer; sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg, scsicmd->sc_data_direction); psg->count = cpu_to_le32(sg_count); byte_count = 0; for (i = 0; i < sg_count; i++) { le_addr = cpu_to_le64(sg_dma_address(sg)); psg->sg[i].addr[1] = (u32)(le_addr>>32); psg->sg[i].addr[0] = (u32)(le_addr & 0xffffffff); psg->sg[i].count = cpu_to_le32(sg_dma_len(sg)); byte_count += sg_dma_len(sg); sg++; } /* hba wants the size to be exact */ if(byte_count > scsicmd->request_bufflen){ psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen); byte_count = scsicmd->request_bufflen; } /* Check for command underflow */ if(scsicmd->underflow && (byte_count < scsicmd->underflow)){ printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n", byte_count, scsicmd->underflow); } } else if(scsicmd->request_bufflen) { dma_addr_t addr; addr = pci_map_single(dev->pdev, scsicmd->request_buffer, scsicmd->request_bufflen, scsicmd->sc_data_direction); psg->count = cpu_to_le32(1); le_addr = cpu_to_le64(addr); psg->sg[0].addr[1] = (u32)(le_addr>>32); psg->sg[0].addr[0] = (u32)(le_addr & 0xffffffff); psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen); scsicmd->SCp.dma_handle = addr; byte_count = scsicmd->request_bufflen; } return byte_count;}#ifdef AAC_DETAILED_STATUS_INFOstruct aac_srb_status_info { u32 status; char *str;};static struct aac_srb_status_info srb_status_info[] = { { SRB_STATUS_PENDING, "Pending Status"}, { SRB_STATUS_SUCCESS, "Success"}, { SRB_STATUS_ABORTED, "Aborted Command"}, { SRB_STATUS_ABORT_FAILED, "Abort Failed"}, { SRB_STATUS_ERROR, "Error Event"}, { SRB_STATUS_BUSY, "Device Busy"}, { SRB_STATUS_INVALID_REQUEST, "Invalid Request"}, { SRB_STATUS_INVALID_PATH_ID, "Invalid Path ID"}, { SRB_STATUS_NO_DEVICE, "No Device"}, { SRB_STATUS_TIMEOUT, "Timeout"}, { SRB_STATUS_SELECTION_TIMEOUT, "Selection Timeout"}, { SRB_STATUS_COMMAND_TIMEOUT, "Command Timeout"}, { SRB_STATUS_MESSAGE_REJECTED, "Message Rejected"}, { SRB_STATUS_BUS_RESET, "Bus Reset"}, { SRB_STATUS_PARITY_ERROR, "Parity Error"}, { SRB_STATUS_REQUEST_SENSE_FAILED,"Request Sense Failed"}, { SRB_STATUS_NO_HBA, "No HBA"}, { SRB_STATUS_DATA_OVERRUN, "Data Overrun/Data Underrun"}, { SRB_STATUS_UNEXPECTED_BUS_FREE,"Unexpected Bus Free"}, { SRB_STATUS_PHASE_SEQUENCE_FAILURE,"Phase Error"}, { SRB_STATUS_BAD_SRB_BLOCK_LENGTH,"Bad Srb Block Length"}, { SRB_STATUS_REQUEST_FLUSHED, "Request Flushed"}, { SRB_STATUS_DELAYED_RETRY, "Delayed Retry"}, { SRB_STATUS_INVALID_LUN, "Invalid LUN"}, { SRB_STATUS_INVALID_TARGET_ID, "Invalid TARGET ID"}, { SRB_STATUS_BAD_FUNCTION, "Bad Function"}, { SRB_STATUS_ERROR_RECOVERY, "Error Recovery"}, { SRB_STATUS_NOT_STARTED, "Not Started"}, { SRB_STATUS_NOT_IN_USE, "Not In Use"}, { SRB_STATUS_FORCE_ABORT, "Force Abort"}, { SRB_STATUS_DOMAIN_VALIDATION_FAIL,"Domain Validation Failure"}, { 0xff, "Unknown Error"}};char *aac_get_status_string(u32 status){ int i; for(i=0; i < (sizeof(srb_status_info)/sizeof(struct aac_srb_status_info)); i++ ){ if(srb_status_info[i].status == status){ return srb_status_info[i].str; } } return "Bad Status Code";}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -