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

📄 megaraid.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*=================================================================== * *                    Linux MegaRAID device driver * * Copyright 1999 American Megatrends Inc. * *              This program is free software; you can redistribute it and/or *              modify it under the terms of the GNU General Public License *              as published by the Free Software Foundation; either version *              2 of the License, or (at your option) any later version. * * Version : 1.07b *  * Description: Linux device driver for AMI MegaRAID controller * * Supported controllers: MegaRAID 418, 428, 438, 466, 762, 467, 490 *  * History: * * Version 0.90: *     Original source contributed by Dell; integrated it into the kernel and *     cleaned up some things.  Added support for 438/466 controllers. * * Version 0.91: *     Aligned mailbox area on 16-byte boundry. *     Added schedule() at the end to properly clean up. *     Made improvements for conformity to linux driver standards. * * Version 0.92: *     Added support for 2.1 kernels. *         Reads from pci_dev struct, so it's not dependent on pcibios. *         Added some missing virt_to_bus() translations. *     Added support for SMP. *         Changed global cli()'s to spinlocks for 2.1, and simulated *          spinlocks for 2.0. *     Removed setting of SA_INTERRUPT flag when requesting Irq. * * Version 0.92ac: *     Small changes to the comments/formatting. Plus a couple of *      added notes. Returned to the authors. No actual code changes *      save printk levels. *     8 Oct 98        Alan Cox <alan.cox@linux.org> * *     Merged with 2.1.131 source tree. *     12 Dec 98       K. Baranowski <kgb@knm.org.pl>                           * * Version 0.93: *     Added support for vendor specific ioctl commands (0x80+xxh) *     Changed some fields in MEGARAID struct to better values. *     Added signature check for Rp controllers under 2.0 kernels *     Changed busy-wait loop to be time-based *     Fixed SMP race condition in isr *     Added kfree (sgList) on release *     Added #include linux/version.h to megaraid.h for hosts.h *     Changed max_id to represent max logical drives instead of targets. * * Version 0.94: *     Got rid of some excess locking/unlocking *     Fixed slight memory corruption problem while memcpy'ing into mailbox *     Changed logical drives to be reported as luns rather than targets *     Changed max_id to 16 since it is now max targets/chan again. *     Improved ioctl interface for upcoming megamgr * * Version 0.95: *     Fixed problem of queueing multiple commands to adapter; *       still has some strange problems on some setups, so still *       defaults to single.  To enable parallel commands change *       #define MULTI_IO in megaraid.h *     Changed kmalloc allocation to be done in beginning. *     Got rid of C++ style comments * * Version 0.96: *     762 fully supported. * * Version 0.97: *     Changed megaraid_command to use wait_queue. *     Fixed bug of undesirably detecting HP onboard controllers which *       are disabled. *      * Version 1.00: *     Checks to see if an irq ocurred while in isr, and runs through *       routine again. *     Copies mailbox to temp area before processing in isr *     Added barrier() in busy wait to fix volatility bug *     Uses separate list for freed Scbs, keeps track of cmd state *     Put spinlocks around entire queue function for now... *     Full multi-io commands working stablely without previous problems *     Added skipXX LILO option for Madrona motherboard support * * Version 1.01: *     Fixed bug in mega_cmd_done() for megamgr control commands, *       the host_byte in the result code from the scsi request to  *       scsi midlayer is set to DID_BAD_TARGET when adapter's  *       returned codes are 0xF0 and 0xF4.   * * Version 1.02: *     Fixed the tape drive bug by extending the adapter timeout value *       for passthrough command to 60 seconds in mega_build_cmd().  * * Version 1.03: *    Fixed Madrona support. *    Changed the adapter timeout value from 60 sec in 1.02 to 10 min *      for bigger and slower tape drive. *    Added driver version printout at driver loadup time * * Version 1.04 *    Added code for 40 ld FW support.  *    Added new ioctl command 0x81 to support NEW_READ/WRITE_CONFIG with *      data area greater than 4 KB, which is the upper bound for data *      tranfer through scsi_ioctl interface. *    The addtional 32 bit field for 64bit address in the newly defined *      mailbox64 structure is set to 0 at this point. * * Version 1.05 *    Changed the queing implementation for handling SCBs and completed *      commands. *    Added spinlocks in the interrupt service routine to enable the dirver *      function in the SMP environment. *    Fixed the problem of unnecessary aborts in the abort entry point, which *      also enables the driver to handle large amount of I/O requests for *      long duration of time. * * Version 1.07 *    Removed the usage of uaccess.h file for kernel versions less than *    2.0.36, as this file is not present in those versions. * * Version 1.07b *    The MegaRAID 466 cards with 3.00 firmware lockup and seem to very *    occasionally hang. We check such cards and report them. You can *    get firmware upgrades to flash the board to 3.10 for free. * * BUGS: *     Some older 2.1 kernels (eg. 2.1.90) have a bug in pci.c that *     fails to detect the controller as a pci device on the system. * *     Timeout period for upper scsi layer, i.e. SD_TIMEOUT in *     /drivers/scsi/sd.c, is too short for this controller. SD_TIMEOUT *     value must be increased to (30 * HZ) otherwise false timeouts  *     will occur in the upper layer. * *===================================================================*/#define CRLFSTR "\n"#define IOCTL_CMD_NEW  0x81#define MEGARAID_VERSION "v107 (December 22, 1999)"#include <linux/version.h>#ifdef MODULE#include <linux/modversions.h>#include <linux/module.h>char kernel_version[] = UTS_RELEASE;MODULE_AUTHOR ("American Megatrends Inc.");MODULE_DESCRIPTION ("AMI MegaRAID driver");#endif#include <linux/init.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/ioport.h>#include <linux/fcntl.h>#include <linux/delay.h>#include <linux/pci.h>#include <linux/proc_fs.h>#include <linux/blk.h>#include <linux/wait.h>#include <linux/tqueue.h>#include <linux/interrupt.h>#include <linux/stat.h>#include <linux/spinlock.h>#include <asm/io.h>#include <asm/irq.h>#if LINUX_VERSION_CODE > 0x020024#include <asm/uaccess.h>#endif#include "sd.h"#include "scsi.h"#include "hosts.h"#include "megaraid.h"/*================================================================ * *                          #Defines * *================================================================ */#define MAX_SERBUF 160#define COM_BASE 0x2f8u32 RDINDOOR (mega_host_config * megaCfg){  return readl (megaCfg->base + 0x20);}void WRINDOOR (mega_host_config * megaCfg, u32 value){  writel (value, megaCfg->base + 0x20);}u32 RDOUTDOOR (mega_host_config * megaCfg){  return readl (megaCfg->base + 0x2C);}void WROUTDOOR (mega_host_config * megaCfg, u32 value){  writel (value, megaCfg->base + 0x2C);}/*================================================================ * *                    Function prototypes * *================================================================ */static int __init megaraid_setup(char *);static int megaIssueCmd (mega_host_config * megaCfg,			 u_char * mboxData,			 mega_scb * scb,			 int intr);static int mega_build_sglist (mega_host_config * megaCfg, mega_scb * scb,			 u32 * buffer, u32 * length);static int mega_busyWaitMbox(mega_host_config *);static void mega_runpendq (mega_host_config *);static void mega_rundoneq (mega_host_config *);static void mega_cmd_done (mega_host_config *, mega_scb *, int);static mega_scb *mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt);static inline void mega_freeSgList(mega_host_config *megaCfg);static void mega_Convert8ldTo40ld(  mega_RAIDINQ  *inquiry,                                    mega_Enquiry3 *enquiry3,                                    megaRaidProductInfo *productInfo );#include <linux/smp.h>#define cpuid smp_processor_id()#define DRIVER_LOCK_T#define DRIVER_LOCK_INIT(p)#define DRIVER_LOCK(p)#define DRIVER_UNLOCK(p)#define IO_LOCK_T unsigned long io_flags = 0;#define IO_LOCK spin_lock_irqsave(&io_request_lock,io_flags);#define IO_UNLOCK spin_unlock_irqrestore(&io_request_lock,io_flags);/* set SERDEBUG to 1 to enable serial debugging */#define SERDEBUG 0#if SERDEBUGstatic void ser_init (void);static void ser_puts (char *str);static void ser_putc (char c);static int ser_printk (const char *fmt,...);#endif/*================================================================ * *                    Global variables * *================================================================ *//*  Use "megaraid=skipXX" as LILO option to prohibit driver from scanning    XX scsi id on each channel.  Used for Madrona motherboard, where SAF_TE    processor id cannot be scanned */#ifdef MODULEstatic char *megaraid = NULL;MODULE_PARM(megaraid, "s");#endifstatic int skip_id;static int numCtlrs = 0;static mega_host_config *megaCtlrs[FC_MAX_CHANNELS] = {0};#if DEBUGstatic u32 maxCmdTime = 0;#endifstatic mega_scb *pLastScb = NULL;#if SERDEBUGstatic spinlock_t serial_lock = SPIN_LOCK_UNLOCKED;#endif#if SERDEBUGstatic char strbuf[MAX_SERBUF + 1];static void ser_init (){  unsigned port = COM_BASE;  outb (0x80, port + 3);  outb (0, port + 1);  /* 9600 Baud, if 19200: outb(6,port) */  outb (12, port);  outb (3, port + 3);  outb (0, port + 1);}static void ser_puts (char *str){  char *ptr;  ser_init ();  for (ptr = str; *ptr; ++ptr)    ser_putc (*ptr);}static void ser_putc (char c){  unsigned port = COM_BASE;  while ((inb (port + 5) & 0x20) == 0);  outb (c, port);  if (c == 0x0a) {    while ((inb (port + 5) & 0x20) == 0);    outb (0x0d, port);  }}static int ser_printk (const char *fmt,...){  va_list args;  int i;  long flags;  spin_lock_irqsave(&serial_lock,flags);  va_start (args, fmt);  i = vsprintf (strbuf, fmt, args);  ser_puts (strbuf);  va_end (args);  spin_unlock_irqrestore(&serial_lock,flags);  return i;}#define TRACE(a)    { ser_printk a;}#else#define TRACE(A)#endifstatic void callDone (Scsi_Cmnd * SCpnt){  if (SCpnt->result) {    TRACE (("*** %.08lx %.02x <%d.%d.%d> = %x\n", SCpnt->serial_number,	    SCpnt->cmnd[0], SCpnt->channel, SCpnt->target, SCpnt->lun,	    SCpnt->result));  }  SCpnt->scsi_done (SCpnt);}/*------------------------------------------------------------------------- * *                      Local functions * *-------------------------------------------------------------------------*//*======================= * Free a SCB structure *======================= */static void mega_freeSCB (mega_host_config *megaCfg, mega_scb * pScb){  mega_scb *pScbtmp;  if ((pScb == NULL) || (pScb->idx >= 0xFE)) {    return ;  }  /* Unlink from pending queue */  if(pScb == megaCfg->qPendingH) {    if(megaCfg->qPendingH == megaCfg->qPendingT )       megaCfg->qPendingH = megaCfg->qPendingT = NULL;    else {      megaCfg->qPendingH = megaCfg->qPendingH->next;    }    megaCfg->qPcnt--;  }  else {    for(pScbtmp=megaCfg->qPendingH; pScbtmp; pScbtmp=pScbtmp->next) {      if (pScbtmp->next == pScb) {        pScbtmp->next = pScb->next;        if(pScb == megaCfg->qPendingT) {          megaCfg->qPendingT = pScbtmp;        }        megaCfg->qPcnt--;	break;    }  }  }  /* Link back into free list */  pScb->state = SCB_FREE;  pScb->SCpnt = NULL;  if(megaCfg->qFreeH == (mega_scb *) NULL ) {    megaCfg->qFreeH = megaCfg->qFreeT = pScb;  }  else {    megaCfg->qFreeT->next  = pScb;    megaCfg->qFreeT = pScb;  }  megaCfg->qFreeT->next = NULL;  megaCfg->qFcnt++;}/*=========================== * Allocate a SCB structure *=========================== */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;    return pScb;  }  printk (KERN_WARNING "Megaraid: Could not allocate free SCB!!!\n");  return NULL;}/*================================================ * Initialize SCB structures *================================================ */static int mega_initSCB (mega_host_config * megaCfg){  int idx;  megaCfg->qFreeH = NULL;  megaCfg->qFcnt = 0;#if DEBUGif(megaCfg->max_cmds >= MAX_COMMANDS) {printk("megaraid:ctlr max cmds = %x : MAX_CMDS = %x", megaCfg->max_cmds, MAX_COMMANDS);}#endif  for (idx = megaCfg->max_cmds-1; idx >= 0; idx--) {    megaCfg->scbList[idx].idx    = idx;    megaCfg->scbList[idx].sgList = kmalloc(sizeof(mega_sglist) * MAX_SGLIST,					   GFP_ATOMIC | GFP_DMA);    if (megaCfg->scbList[idx].sgList == NULL) {      printk(KERN_WARNING "Can't allocate sglist for id %d\n",idx);      mega_freeSgList(megaCfg);      return -1;    }        if (idx < MAX_COMMANDS) {      /* Link to free list */      mega_freeSCB(megaCfg, &megaCfg->scbList[idx]);    }  }  return 0;}/* Run through the list of completed requests */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 void mega_runpendq(mega_host_config *megaCfg){  mega_scb *pScb;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -