📄 megaraid.c
字号:
*=========================== */static mega_scb *mega_allocateSCB (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt){ mega_scb *pScb; /* Unlink command from Free List */ if ((pScb = megaCfg->qFreeH) != NULL) { megaCfg->qFreeH = pScb->next; megaCfg->qFcnt--; pScb->isrcount = jiffies; pScb->next = NULL; pScb->state = SCB_ACTIVE; pScb->SCpnt = SCpnt;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pScb->dma_type = M_RD_DMA_TYPE_NONE;#endif return pScb; } printk (KERN_WARNING "Megaraid: Could not allocate free SCB!!!\n"); return NULL;}/* Run through the list of completed requests and finish it */static void mega_rundoneq (mega_host_config * megaCfg){ Scsi_Cmnd *SCpnt; while ((SCpnt = megaCfg->qCompletedH) != NULL) { megaCfg->qCompletedH = (Scsi_Cmnd *) SCpnt->host_scribble; megaCfg->qCcnt--; SCpnt->host_scribble = (unsigned char *) NULL; /* XC : sep 14 */ /* Callback */ callDone (SCpnt); } megaCfg->qCompletedH = megaCfg->qCompletedT = NULL;}/* * Runs through the list of pending requests * Assumes that mega_lock spin_lock has been acquired. */static int mega_runpendq (mega_host_config * megaCfg){ mega_scb *pScb; int rc; /* Issue any pending commands to the card */ for (pScb = megaCfg->qPendingH; pScb; pScb = pScb->next) { if (pScb->state == SCB_ACTIVE) { if ((rc = megaIssueCmd (megaCfg, pScb->mboxData, pScb, 1)) == -1) return rc; } } return 0;}/* Add command to the list of completed requests */static void mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb, int status){ int islogical; Scsi_Cmnd *SCpnt; mega_passthru *pthru; mega_ext_passthru *epthru; mega_mailbox *mbox; struct scatterlist *sgList; u8 c; if (pScb == NULL) { TRACE (("NULL pScb in mega_cmd_done!")); printk(KERN_CRIT "NULL pScb in mega_cmd_done!"); } SCpnt = pScb->SCpnt;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pthru = pScb->pthru; epthru = pScb->epthru;#else pthru = &pScb->pthru; epthru = &pScb->epthru;#endif mbox = (mega_mailbox *) & pScb->mboxData; if (SCpnt == NULL) { TRACE (("NULL SCpnt in mega_cmd_done!")); TRACE (("pScb->idx = ", pScb->idx)); TRACE (("pScb->state = ", pScb->state)); TRACE (("pScb->state = ", pScb->state)); panic(KERN_ERR "megaraid:Problem...!\n"); } islogical = ( (SCpnt->channel >= megaCfg->productInfo.SCSIChanPresent) && (SCpnt->channel <= megaCfg->host->max_channel) );#if 0 islogical = (SCpnt->channel == megaCfg->host->max_channel);#endif#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* Special Case to handle PassThrough->XferAddrress > 4GB */ switch (SCpnt->cmnd[0]) { case INQUIRY: case READ_CAPACITY: memcpy (SCpnt->request_buffer, pScb->bounce_buffer, SCpnt->request_bufflen); break; }#endif mega_freeSCB (megaCfg, pScb); /* * Do not return the presence of hard disk on the channel so, inquiry * sent, and returned data==hard disk or removable hard disk and not * logical, request should return failure! - PJ */#if 0 if (SCpnt->cmnd[0] == INQUIRY && ((((u_char *) SCpnt->request_buffer)[0] & 0x1F) == TYPE_DISK) && !islogical) { status = 0xF0; }#endif if (SCpnt->cmnd[0] == INQUIRY && !islogical) { if ( SCpnt->use_sg ) { sgList = (struct scatterlist *)SCpnt->request_buffer; memcpy(&c, sgList[0].address, 0x1); } else { memcpy(&c, SCpnt->request_buffer, 0x1); }#if 0 if( (c & 0x1F ) == TYPE_DISK ) { status = 0xF0; }#endif if( IS_RAID_CH(SCpnt->channel) && ((c & 0x1F ) == TYPE_DISK) ) { status = 0xF0; } } /* clear result; otherwise, success returns corrupt value */ SCpnt->result = 0; if ((SCpnt->cmnd[0] & M_RD_IOCTL_CMD)) { /* i.e. ioctl cmd such as M_RD_IOCTL_CMD, M_RD_IOCTL_CMD_NEW of megamgr */ switch (status) { case 2: case 0xF0: case 0xF4: SCpnt->result = (DID_BAD_TARGET << 16) | status; break; default: SCpnt->result |= status; } /*end of switch */ } else { /* Convert MegaRAID status to Linux error code */ switch (status) { case 0x00: /* SUCCESS , i.e. SCSI_STATUS_GOOD */ SCpnt->result |= (DID_OK << 16); break; case 0x02: /* ERROR_ABORTED, i.e. SCSI_STATUS_CHECK_CONDITION */ /*set sense_buffer and result fields */ if (mbox->cmd == MEGA_MBOXCMD_PASSTHRU) { memcpy (SCpnt->sense_buffer, pthru->reqsensearea, 14); } else if (mbox->cmd == MEGA_MBOXCMD_EXTPASSTHRU) { SCpnt->result = (DRIVER_SENSE << 24) | (DID_OK << 16) | (CHECK_CONDITION << 1); memcpy( SCpnt->sense_buffer, epthru->reqsensearea, 14 ); SCpnt->result = (DRIVER_SENSE << 24) | (DID_OK << 16) | (CHECK_CONDITION << 1); /*SCpnt->result = (DRIVER_SENSE << 24) | (DID_ERROR << 16) | status;*/ } else { SCpnt->sense_buffer[0] = 0x70; SCpnt->sense_buffer[2] = ABORTED_COMMAND; SCpnt->result |= (CHECK_CONDITION << 1); } break; case 0x08: /* ERR_DEST_DRIVE_FAILED, i.e. SCSI_STATUS_BUSY */ SCpnt->result |= (DID_BUS_BUSY << 16) | status; break; default: SCpnt->result |= (DID_BAD_TARGET << 16) | status; break; } } /* Add Scsi_Command to end of completed queue */ if (megaCfg->qCompletedH == NULL) { megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt; } else { megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt; megaCfg->qCompletedT = SCpnt; } megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL; megaCfg->qCcnt++;}/*------------------------------------------------------------------- * * Build a SCB from a Scsi_Cmnd * * Returns a SCB pointer, or NULL * If NULL is returned, the scsi_done function MUST have been called * *-------------------------------------------------------------------*/static mega_scb *mega_build_cmd (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt){ mega_scb *pScb; mega_mailbox *mbox; mega_passthru *pthru; mega_ext_passthru *epthru; long seg; char islogical; int lun = SCpnt->lun; int max_lun; if ((SCpnt->cmnd[0] == MEGADEVIOC)) return megadev_doioctl (megaCfg, SCpnt); if ((SCpnt->cmnd[0] == M_RD_IOCTL_CMD) || (SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW))#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) return mega_ioctl (megaCfg, SCpnt); /* Handle IOCTL command */#else { printk(KERN_WARNING "megaraid ioctl: older interface - " "not supported.\n"); return NULL; }#endif islogical = ( (SCpnt->channel >= megaCfg->productInfo.SCSIChanPresent) && (SCpnt->channel <= megaCfg->host->max_channel) );#if 0 islogical = (IS_RAID_CH(SCpnt->channel) && /* virtual ch is raid - AM */ (SCpnt->channel == megaCfg->host->max_channel));#endif if ( ! megaCfg->support_ext_cdb ) { if (!islogical && lun != 0) { SCpnt->result = (DID_BAD_TARGET << 16); callDone (SCpnt); return NULL; } } if (!islogical && SCpnt->target == skip_id) { SCpnt->result = (DID_BAD_TARGET << 16); callDone (SCpnt); return NULL; } if (islogical) { /* have just LUN 0 for each target on virtual channels */ if( SCpnt->lun != 0 ) { SCpnt->result = (DID_BAD_TARGET << 16); callDone (SCpnt); return NULL; } lun = mega_get_lun(megaCfg, SCpnt); max_lun = (megaCfg->flag & BOARD_40LD) ? FC_MAX_LOGICAL_DRIVES : MAX_LOGICAL_DRIVES; /* * max_lun increases by 0x80 if some logical drive was deleted. */ if(megaCfg->read_ldidmap) { max_lun += 0x80; } if( lun > max_lun ) { SCpnt->result = (DID_BAD_TARGET << 16); callDone (SCpnt); return NULL; } /* * If we have a logical drive with boot enabled, project it first */ if( megaCfg->boot_ldrv_enabled ) { if( lun == 0 ) { lun = megaCfg->boot_ldrv; } else { if( lun <= megaCfg->boot_ldrv ) { lun--; } } } } else { if ( lun > 7) { /* Do not support lun >7 for physically accessed devices */ SCpnt->result = (DID_BAD_TARGET << 16); callDone (SCpnt); return NULL; } } /*----------------------------------------------------- * * Logical drive commands * *-----------------------------------------------------*/ if (islogical) { switch (SCpnt->cmnd[0]) { case TEST_UNIT_READY: memset (SCpnt->request_buffer, 0, SCpnt->request_bufflen); SCpnt->result = (DID_OK << 16); callDone (SCpnt); return NULL; case MODE_SENSE: memset (SCpnt->request_buffer, 0, SCpnt->cmnd[4]); SCpnt->result = (DID_OK << 16); callDone (SCpnt); return NULL; case READ_CAPACITY: case INQUIRY: /* Allocate a SCB and initialize passthru */ if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) { SCpnt->result = (DID_ERROR << 16); callDone (SCpnt); return NULL; }#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pthru = pScb->pthru;#else pthru = &pScb->pthru;#endif mbox = (mega_mailbox *) & pScb->mboxData; memset (mbox, 0, sizeof (pScb->mboxData)); memset (pthru, 0, sizeof (mega_passthru)); pthru->timeout = 0; pthru->ars = 1; pthru->reqsenselen = 14; pthru->islogical = 1; pthru->logdrv = lun; pthru->cdblen = SCpnt->cmd_len;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /*Not sure about the direction */ pScb->dma_direction = PCI_DMA_BIDIRECTIONAL; pScb->dma_type = M_RD_PTHRU_WITH_BULK_DATA;#if 0/* Normal Code w/o the need for bounce buffer */ pScb->dma_h_bulkdata = pci_map_single (megaCfg->dev, SCpnt->request_buffer, SCpnt->request_bufflen, pScb->dma_direction); pthru->dataxferaddr = pScb->dma_h_bulkdata;#else/* Special Code to use bounce buffer for READ_CAPA/INQ */ pthru->dataxferaddr = pScb->dma_bounce_buffer; pScb->dma_type = M_RD_DMA_TYPE_NONE;#endif#else pthru->dataxferaddr = virt_to_bus (SCpnt->request_buffer);#endif pthru->dataxferlen = SCpnt->request_bufflen; memcpy (pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len); /* Initialize mailbox area */ mbox->cmd = MEGA_MBOXCMD_PASSTHRU;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) mbox->xferaddr = pScb->dma_passthruhandle64; TRACE1 (("M_RD_PTHRU_WITH_BULK_DATA Enabled \n"));#else mbox->xferaddr = virt_to_bus (pthru);#endif return pScb; case READ_6: case WRITE_6: case READ_10: case WRITE_10: /* Allocate a SCB and initialize mailbox */ if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) { SCpnt->result = (DID_ERROR << 16); callDone (SCpnt); return NULL; } mbox = (mega_mailbox *) & pScb->mboxData; memset (mbox, 0, sizeof (pScb->mboxData)); mbox->logdrv = lun; if (megaCfg->flag & BOARD_64BIT) { mbox->cmd = (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == READ_10) ? MEGA_MBOXCMD_LREAD64 : MEGA_MBOXCMD_LWRITE64; } else { mbox->cmd = (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == READ_10) ? MEGA_MBOXCMD_LREAD : MEGA_MBOXCMD_LWRITE; } /* 6-byte */ if (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == WRITE_6) { mbox->numsectors = (u32) SCpnt->cmnd[4]; mbox->lba = ((u32) SCpnt->cmnd[1] << 16) | ((u32) SCpnt->cmnd[2] << 8) | (u32) SCpnt->cmnd[3]; mbox->lba &= 0x1FFFFF; if (*SCpnt->cmnd == READ_6) { megaCfg->nReads[(int) lun]++; megaCfg->nReadBlocks[(int) lun] += mbox->numsectors; } else { megaCfg->nWrites[(int) lun]++; megaCfg->nWriteBlocks[(int) lun] += mbox->numsectors; } } /* 10-byte */ if (*SCpnt->cmnd == READ_10 || *SCpnt->cmnd == WRITE_10) { mbox->numsectors = (u32) SCpnt->cmnd[8] | ((u32) SCpnt->cmnd[7] << 8); mbox->lba = ((u32) SCpnt->cmnd[2] << 24) | ((u32) SCpnt->cmnd[3] << 16) | ((u32) SCpnt->cmnd[4] << 8) | (u32) SCpnt->cmnd[5]; if (*SCpnt->cmnd == READ_10) { megaCfg->nReads[(int) lun]++; megaCfg->nReadBlocks[(int) lun] += mbox->numsectors; } else { megaCfg->nWrites[(int) lun]++; megaCfg->nWriteBlocks[(int) lun] += mbox->numsectors; } } /* 12-byte */ if (*SCpnt->cmnd == READ_12 || *SCpnt->cmnd == WRITE_12) { mbox->lba = ((u32) SCpnt->cmnd[2] << 24) | ((u32) SCpnt->cmnd[3] << 16) | ((u32) SCpnt->cmnd[4] << 8) | (u32) SCpnt->cmnd[5]; mbox->numsectors = ((u32) SCpnt->cmnd[6] << 24) | ((u32) SCpnt->cmnd[7] << 16) | ((u32) SCpnt->cmnd[8] << 8) | (u32) SCpnt->cmnd[9]; if (*SCpnt->cmnd == READ_12) { megaCfg->nReads[(int) lun]++; megaCfg->nReadBlocks[(int) lun] += mbox->numsectors; } else { megaCfg->nWrites[(int) lun]++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -