⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 megaraid.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
      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 + -