📄 megaraid.c
字号:
while (RDINDOOR (megaCfg) & 0x02); } else { CLEAR_INTR (megaCfg->host->io_port); }#if DEBUG if(qCnt >= MAX_FIRMWARE_STATUS) { printk("megaraid_isr: cmplt=%d ", qCnt); }#endif for (idx = 0; idx < qCnt; idx++) { sIdx = completed[idx]; if ((sIdx > 0) && (sIdx <= MAX_COMMANDS)) { pScb = &megaCfg->scbList[sIdx - 1]; /* ASSERT(pScb->state == SCB_ISSUED); */#if DEBUG if (((jiffies) - pScb->isrcount) > maxCmdTime) { maxCmdTime = (jiffies) - pScb->isrcount; printk("megaraid_isr : cmd time = %u\n", maxCmdTime); }#endif/* * Assuming that the scsi command, for which an abort request was received * earlier has completed. */ if (pScb->state == SCB_ABORTED) { SCpnt = pScb->SCpnt; } if (pScb->state == SCB_RESET) { SCpnt = pScb->SCpnt; mega_freeSCB (megaCfg, pScb); SCpnt->result = (DID_RESET << 16) ; 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++; continue; } if (*(pScb->SCpnt->cmnd)==IOCTL_CMD_NEW) { /* external user buffer */ up(&pScb->sem); } /* Mark command as completed */ mega_cmd_done(megaCfg, pScb, qStatus); } else { printk(KERN_ERR "megaraid: wrong cmd id completed from firmware:id=%x\n",sIdx); } } mega_rundoneq(megaCfg); megaCfg->flag &= ~IN_ISR; /* Loop through any pending requests */ mega_runpendq(megaCfg);#if LINUX_VERSION_CODE >= 0x20100 IO_UNLOCK;#endif }}/*==================================================*//* Wait until the controller's mailbox is available *//*==================================================*/static int mega_busyWaitMbox (mega_host_config * megaCfg){ mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox; long counter; for (counter = 0; counter < 10000; counter++) { if (!mbox->busy) { return 0; } udelay (100); barrier(); } return -1; /* give up after 1 second */}/*===================================================== * Post a command to the card * * Arguments: * mega_host_config *megaCfg - Controller structure * u_char *mboxData - Mailbox area, 16 bytes * mega_scb *pScb - SCB posting (or NULL if N/A) * int intr - if 1, interrupt, 0 is blocking * Return Value: (added on 7/26 for 40ld/64bit) * -1: the command was not actually issued out * othercases: * intr==0, return ScsiStatus, i.e. mbox->status * intr==1, return 0 *===================================================== */static int megaIssueCmd (mega_host_config * megaCfg, u_char * mboxData, mega_scb * pScb, int intr){ mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox; u_char byte; u32 cmdDone; u32 phys_mbox; u8 retval=-1; mboxData[0x1] = (pScb ? pScb->idx + 1: 0x0); /* Set cmdid */ mboxData[0xF] = 1; /* Set busy */ phys_mbox = virt_to_bus (megaCfg->mbox);#if DEBUG showMbox(pScb);#endif /* Wait until mailbox is free */ if (mega_busyWaitMbox (megaCfg)) { printk("Blocked mailbox......!!\n"); udelay(1000);#if DEBUG showMbox(pLastScb);#endif /* Abort command */ if (pScb == NULL) { TRACE(("NULL pScb in megaIssue\n")); printk("NULL pScb in megaIssue\n"); } mega_cmd_done (megaCfg, pScb, 0x08); return -1; } pLastScb = pScb; /* Copy mailbox data into host structure */ megaCfg->mbox64->xferSegment = 0; memcpy (mbox, mboxData, 16); /* Kick IO */ if (intr) { /* Issue interrupt (non-blocking) command */ if (megaCfg->flag & BOARD_QUARTZ) { mbox->mraid_poll = 0; mbox->mraid_ack = 0; WRINDOOR (megaCfg, phys_mbox | 0x1); } else { ENABLE_INTR (megaCfg->host->io_port); ISSUE_COMMAND (megaCfg->host->io_port); } pScb->state = SCB_ISSUED; retval=0; } else { /* Issue non-ISR (blocking) command */ disable_irq(megaCfg->host->irq); if (megaCfg->flag & BOARD_QUARTZ) { mbox->mraid_poll = 0; mbox->mraid_ack = 0; WRINDOOR (megaCfg, phys_mbox | 0x1); while ((cmdDone = RDOUTDOOR (megaCfg)) != 0x10001234); WROUTDOOR (megaCfg, cmdDone); if (pScb) { mega_cmd_done (megaCfg, pScb, mbox->status); } WRINDOOR (megaCfg, phys_mbox | 0x2); while (RDINDOOR (megaCfg) & 0x2); } else { DISABLE_INTR (megaCfg->host->io_port); ISSUE_COMMAND (megaCfg->host->io_port); while (!((byte = READ_PORT (megaCfg->host->io_port, INTR_PORT)) & INTR_VALID)); WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte); ENABLE_INTR (megaCfg->host->io_port); CLEAR_INTR (megaCfg->host->io_port); if (pScb) { mega_cmd_done (megaCfg, pScb, mbox->status); } else { TRACE (("Error: NULL pScb!\n")); } } enable_irq(megaCfg->host->irq); retval=mbox->status; }#if DEBUG while (mega_busyWaitMbox (megaCfg)) { printk("Blocked mailbox on exit......!\n"); udelay(1000); }#endif return retval;}/*------------------------------------------------------------------- * Copies data to SGLIST *-------------------------------------------------------------------*/static int mega_build_sglist (mega_host_config * megaCfg, mega_scb * scb, u32 * buffer, u32 * length){ struct scatterlist *sgList; int idx; /* Scatter-gather not used */ if (scb->SCpnt->use_sg == 0) { *buffer = virt_to_bus (scb->SCpnt->request_buffer); *length = (u32) scb->SCpnt->request_bufflen; return 0; } sgList = (struct scatterlist *) scb->SCpnt->request_buffer; if (scb->SCpnt->use_sg == 1) { *buffer = virt_to_bus (sgList[0].address); *length = (u32) sgList[0].length; return 0; } /* Copy Scatter-Gather list info into controller structure */ for (idx = 0; idx < scb->SCpnt->use_sg; idx++) { scb->sgList[idx].address = virt_to_bus (sgList[idx].address); scb->sgList[idx].length = (u32) sgList[idx].length; } /* Reset pointer and length fields */ *buffer = virt_to_bus (scb->sgList); *length = 0; /* Return count of SG requests */ return scb->SCpnt->use_sg;}/*-------------------------------------------------------------------- * Initializes the adress of the controller's mailbox register * The mailbox register is used to issue commands to the card. * Format of the mailbox area: * 00 01 command * 01 01 command id * 02 02 # of sectors * 04 04 logical bus address * 08 04 physical buffer address * 0C 01 logical drive # * 0D 01 length of scatter/gather list * 0E 01 reserved * 0F 01 mailbox busy * 10 01 numstatus byte * 11 01 status byte *--------------------------------------------------------------------*/static int mega_register_mailbox (mega_host_config * megaCfg, u32 paddr){ /* align on 16-byte boundry */ megaCfg->mbox = &megaCfg->mailbox64.mailbox; megaCfg->mbox = (mega_mailbox *) ((((u32) megaCfg->mbox) + 16) & 0xfffffff0); megaCfg->mbox64 = (mega_mailbox64 *) (megaCfg->mbox - 4); paddr = (paddr + 4 + 16) & 0xfffffff0; /* Register mailbox area with the firmware */ if (!(megaCfg->flag & BOARD_QUARTZ)) { WRITE_PORT (megaCfg->host->io_port, MBOX_PORT0, paddr & 0xFF); WRITE_PORT (megaCfg->host->io_port, MBOX_PORT1, (paddr >> 8) & 0xFF); WRITE_PORT (megaCfg->host->io_port, MBOX_PORT2, (paddr >> 16) & 0xFF); WRITE_PORT (megaCfg->host->io_port, MBOX_PORT3, (paddr >> 24) & 0xFF); WRITE_PORT (megaCfg->host->io_port, ENABLE_MBOX_REGION, ENABLE_MBOX_BYTE); CLEAR_INTR (megaCfg->host->io_port); ENABLE_INTR (megaCfg->host->io_port); } return 0;}/*--------------------------------------------------------------------------- * mega_Convert8ldTo40ld() -- takes all info in AdapterInquiry structure and * puts it into ProductInfo and Enquiry3 structures for later use *---------------------------------------------------------------------------*/static void mega_Convert8ldTo40ld( mega_RAIDINQ *inquiry, mega_Enquiry3 *enquiry3, megaRaidProductInfo *productInfo ){ int i; productInfo->MaxConcCmds = inquiry->AdpInfo.MaxConcCmds; enquiry3->rbldRate = inquiry->AdpInfo.RbldRate; productInfo->SCSIChanPresent = inquiry->AdpInfo.ChanPresent; for (i=0;i<4;i++) { productInfo->FwVer[i] = inquiry->AdpInfo.FwVer[i]; productInfo->BiosVer[i] = inquiry->AdpInfo.BiosVer[i]; } enquiry3->cacheFlushInterval = inquiry->AdpInfo.CacheFlushInterval; productInfo->DramSize = inquiry->AdpInfo.DramSize; enquiry3->numLDrv = inquiry->LogdrvInfo.NumLDrv; for (i=0;i<MAX_LOGICAL_DRIVES;i++) { enquiry3->lDrvSize[i] = inquiry->LogdrvInfo.LDrvSize[i]; enquiry3->lDrvProp[i] = inquiry->LogdrvInfo.LDrvProp[i]; enquiry3->lDrvState[i] = inquiry->LogdrvInfo.LDrvState[i]; } for (i=0;i<(MAX_PHYSICAL_DRIVES);i++) { enquiry3->pDrvState[i] = inquiry->PhysdrvInfo.PDrvState[i]; }}/*------------------------------------------------------------------- * Issue an adapter info query to the controller *-------------------------------------------------------------------*/static int mega_i_query_adapter (mega_host_config * megaCfg){ mega_Enquiry3 *enquiry3Pnt; mega_mailbox *mbox; u_char mboxData[16]; u32 paddr; u8 retval; /* Initialize adapter inquiry mailbox*/ paddr = virt_to_bus (megaCfg->mega_buffer); mbox = (mega_mailbox *) mboxData; memset ((void *) megaCfg->mega_buffer, 0, sizeof (megaCfg->mega_buffer)); memset (mbox, 0, 16);/* * Try to issue Enquiry3 command * if not suceeded, then issue MEGA_MBOXCMD_ADAPTERINQ command and * update enquiry3 structure */ mbox->xferaddr = virt_to_bus ( (void*) megaCfg->mega_buffer); /* Initialize mailbox databuffer addr */ enquiry3Pnt = (mega_Enquiry3 *) megaCfg->mega_buffer; /* point mega_Enguiry3 to the data buf */ mboxData[0]=FC_NEW_CONFIG ; /* i.e. mbox->cmd=0xA1 */ mboxData[2]=NC_SUBOP_ENQUIRY3; /* i.e. 0x0F */ mboxData[3]=ENQ3_GET_SOLICITED_FULL; /* i.e. 0x02 */ /* Issue a blocking command to the card */ if ( (retval=megaIssueCmd(megaCfg, mboxData, NULL, 0)) != 0 ) { /* the adapter does not support 40ld*/ mega_RAIDINQ adapterInquiryData; mega_RAIDINQ *adapterInquiryPnt = &adapterInquiryData; mbox->xferaddr = virt_to_bus ( (void*) adapterInquiryPnt); mbox->cmd = MEGA_MBOXCMD_ADAPTERINQ; /*issue old 0x05 command to adapter*/ /* Issue a blocking command to the card */; retval=megaIssueCmd (megaCfg, mboxData, NULL, 0); /*update Enquiry3 and ProductInfo structures with mega_RAIDINQ structure*/ mega_Convert8ldTo40ld( adapterInquiryPnt, enquiry3Pnt, (megaRaidProductInfo * ) &megaCfg->productInfo ); } else{ /* adapter supports 40ld */ megaCfg->flag |= BOARD_40LD; /*get productInfo, which is static information and will be unchanged*/ mbox->xferaddr = virt_to_bus ( (void*) &megaCfg->productInfo ); mboxData[0]=FC_NEW_CONFIG ; /* i.e. mbox->cmd=0xA1 */ mboxData[2]=NC_SUBOP_PRODUCT_INFO; /* i.e. 0x0E */ if( (retval=megaIssueCmd(megaCfg, mboxData, NULL, 0)) != 0 ) printk("ami:Product_info (0x0E) cmd failed with error: %d\n", retval); } megaCfg->host->max_channel = megaCfg->productInfo.SCSIChanPresent; megaCfg->host->max_id = 16; /* max targets per channel */ /*(megaCfg->flag & BOARD_40LD)?FC_MAX_TARGETS_PER_CHANNEL:MAX_TARGET+1;*/ megaCfg->host->max_lun = /* max lun */ (megaCfg->flag & BOARD_40LD) ? FC_MAX_LOGICAL_DRIVES : MAX_LOGICAL_DRIVES; megaCfg->host->cmd_per_lun = MAX_CMD_PER_LUN; megaCfg->numldrv = enquiry3Pnt->numLDrv; megaCfg->max_cmds = megaCfg->productInfo.MaxConcCmds; if(megaCfg->max_cmds > MAX_COMMANDS) megaCfg->max_cmds = MAX_COMMANDS - 1; megaCfg->host->can_queue = megaCfg->max_cmds; if (megaCfg->host->can_queue >= MAX_COMMANDS) { megaCfg->host->can_queue = MAX_COMMANDS-1; }#ifdef HP /* use HP firmware and bios version encoding */ sprintf (megaCfg->fwVer, "%c%d%d.%d%d", megaCfg->productInfo.FwVer[2], megaCfg->productInfo.FwVer[1] >> 8, megaCfg->productInfo.FwVer[1] & 0x0f, megaCfg->productInfo.FwVer[2] >> 8, megaCfg->productInfo.FwVer[2] & 0x0f); sprintf (megaCfg->biosVer, "%c%d%d.%d%d", megaCfg->productInfo.BiosVer[2], megaCfg->productInfo.BiosVer[1] >> 8, megaCfg->productInfo.BiosVer[1] & 0x0f, megaCfg->productInfo.BiosVer[2] >> 8, megaCfg->productInfo.BiosVer[2] & 0x0f);#else memcpy (megaCfg->fwVer, (void *)megaCfg->productInfo.FwVer, 4); megaCfg->fwVer[4] = 0; memcpy (megaCfg->biosVer, (void *)megaCfg->productInfo.BiosVer, 4); megaCfg->biosVer[4] = 0;#endif printk ("megaraid: [%s:%s] detected %d logical drives" CRLFSTR, megaCfg->fwVer, megaCfg->biosVer, megaCfg->numldrv); return 0;}/*------------------------------------------------------------------------- * * Driver interface functions * *-------------------------------------------------------------------------*//*---------------------------------------------------------- * Returns data to be displayed in /proc/scsi/megaraid/X *----------------------------------------------------------*/int megaraid_proc_info (char *buffer, char **start, off_t offset, int length, int host_no, int inout){ *start = buffer; return 0;}int mega_findCard (Scsi_Host_Template * pHostTmpl, u16 pciVendor, u16 pciDev, long flag){ mega_host_config *megaCfg; struct Scsi_Host *host; u_char megaIrq; u32 megaBase; u16 numFound = 0; struct pci_dev *pdev = NULL; while ((pdev = pci_find_device (pciVendor, pciDev, pdev))) { if (pci_enable_device(pdev)) continue; if ((flag & BOARD_QUARTZ) && (skip_id == -1)) { u16 magic; pci_read_config_word(pdev, PCI_CONF_AMISIG, &magic); if ((magic != AMI_SIGNATURE) && (magic != AMI_SIGNATURE_471)) continue; /* not an AMI board */ } printk (KERN_INFO "megaraid: found 0x%4.04x:0x%4.04x: in %s\n", pciVendor, pciDev, pdev->slot_name); /* Read the base port and IRQ from PCI */ megaBase = pci_resource_start (pdev, 0); megaIrq = pdev->irq; if (flag & BOARD_QUARTZ) megaBase = (long) ioremap (megaBase, 128); else megaBase += 0x10; /* Initialize SCSI Host structure */ host = scsi_register (pHostTmpl, sizeof (mega_host_config)); if(host == NULL) continue; megaCfg = (mega_host_config *) host->hostdata; memset (megaCfg, 0, sizeof (mega_host_config)); printk ("scsi%d : Found a MegaRAID controller at 0x%x, IRQ: %d" CRLFSTR, host->host_no, (u_int) megaBase, megaIrq); /* Copy resource info into structure */ megaCfg->qCompletedH = NULL; megaCfg->qCompletedT = NULL; megaCfg->qPendingH = NULL; megaCfg->qPendingT = NULL; megaCfg->qFreeH = NULL; megaCfg->qFreeT = NULL; megaCfg->qFcnt = 0; megaCfg->qPcnt = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -