home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 27 / CDROM27.iso / linux / lg / issue32 / megaraid.patch < prev    next >
Encoding:
Text File  |  1998-08-29  |  50.3 KB  |  3,345 lines

  1. patch -p0 -s -d /usr/src << '_EOF_'
  2.  
  3. diff -urN linux/drivers/scsi/Config.in linux-2.0.32-megaraid/drivers/scsi/Config.in
  4.  
  5. --- linux/drivers/scsi/Config.in    Mon Sep 15 12:41:28 1997
  6.  
  7. +++ linux-2.0.32-megaraid/drivers/scsi/Config.in    Tue Aug 11 09:40:32 1998
  8.  
  9. @@ -32,6 +32,7 @@
  10.  
  11.  dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI
  12.  
  13.  dep_tristate 'Always IN2000 SCSI support' CONFIG_SCSI_IN2000 $CONFIG_SCSI
  14.  
  15.  dep_tristate 'AM53/79C974 PCI SCSI support' CONFIG_SCSI_AM53C974 $CONFIG_SCSI
  16.  
  17. +dep_tristate 'AMI MegaRAID support' CONFIG_SCSI_MEGARAID $CONFIG_SCSI
  18.  
  19.  dep_tristate 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC $CONFIG_SCSI
  20.  
  21.  if [ "$CONFIG_SCSI_BUSLOGIC" != "n" ]; then
  22.  
  23.      bool '  Omit FlashPoint support' CONFIG_SCSI_OMIT_FLASHPOINT
  24.  
  25. diff -urN linux/drivers/scsi/Makefile linux-2.0.32-megaraid/drivers/scsi/Makefile
  26.  
  27. --- linux/drivers/scsi/Makefile    Thu Aug 14 13:31:20 1997
  28.  
  29. +++ linux-2.0.32-megaraid/drivers/scsi/Makefile    Tue Aug 11 18:09:11 1998
  30.  
  31. @@ -363,6 +363,13 @@
  32.  
  33.    endif
  34.  
  35.  endif
  36.  
  37.  
  38.  
  39. +ifeq ($(CONFIG_SCSI_MEGARAID),y)
  40.  
  41. +L_OBJS += megaraid.o
  42.  
  43. +else
  44.  
  45. +  ifeq ($(CONFIG_SCSI_MEGARAID),m)
  46.  
  47. +  M_OBJS += megaraid.o
  48.  
  49. +  endif
  50.  
  51. +endif
  52.  
  53.  
  54.  
  55.  ifeq ($(CONFIG_BLK_DEV_IDESCSI),y)
  56.  
  57.  L_OBJS += ide-scsi.o
  58.  
  59. @@ -400,6 +407,9 @@
  60.  
  61.  
  62.  
  63.  g_NCR5380.o: g_NCR5380.c
  64.  
  65.      $(CC) $(CFLAGS) -DGENERIC_NCR5380_OVERRIDE="{{(NCR5380_map_type)0x350,5,0, BOARD_NCR53C400}};" -c g_NCR5380.c
  66.  
  67. +
  68.  
  69. +megaraid.o: megaraid.c
  70.  
  71. +    $(CC) $(CFLAGS) -c megaraid.c
  72.  
  73.  
  74.  
  75.  scsi_mod.o: $(MX_OBJS) hosts.o scsi.o scsi_ioctl.o constants.o \
  76.  
  77.          scsicam.o scsi_proc.o
  78.  
  79. diff -urN linux/drivers/scsi/hosts.c linux-2.0.32-megaraid/drivers/scsi/hosts.c
  80.  
  81. --- linux/drivers/scsi/hosts.c    Thu Aug 14 13:31:20 1997
  82.  
  83. +++ linux-2.0.32-megaraid/drivers/scsi/hosts.c    Tue Aug 11 09:42:40 1998
  84.  
  85. @@ -161,6 +161,10 @@
  86.  
  87.  #include "AM53C974.h"
  88.  
  89.  #endif
  90.  
  91.  
  92.  
  93. +#ifdef CONFIG_SCSI_MEGARAID
  94.  
  95. +#include "megaraid.h"
  96.  
  97. +#endif
  98.  
  99. +
  100.  
  101.  #ifdef CONFIG_SCSI_PPA
  102.  
  103.  #include "ppa.h"
  104.  
  105.  #endif
  106.  
  107. @@ -311,6 +315,9 @@
  108.  
  109.  #endif
  110.  
  111.  #ifdef CONFIG_SCSI_AM53C974
  112.  
  113.      AM53C974,
  114.  
  115. +#endif
  116.  
  117. +#ifdef CONFIG_SCSI_MEGARAID
  118.  
  119. +    MEGARAID,
  120.  
  121.  #endif
  122.  
  123.  #ifdef CONFIG_SCSI_PPA
  124.  
  125.      PPA,
  126.  
  127. diff -urN linux/drivers/scsi/megaraid.c linux-2.0.32-megaraid/drivers/scsi/megaraid.c
  128.  
  129. --- linux/drivers/scsi/megaraid.c    Wed Dec 31 19:00:00 1969
  130.  
  131. +++ linux-2.0.32-megaraid/drivers/scsi/megaraid.c    Wed Aug 19 18:53:01 1998
  132.  
  133. @@ -0,0 +1,1299 @@
  134.  
  135. +/*===================================================================
  136.  
  137. + *
  138.  
  139. + *                    Linux MegaRAID device driver
  140.  
  141. + * 
  142.  
  143. + * Copyright 1998 American Megatrends Inc.
  144.  
  145. + *
  146.  
  147. + * Version : 0.91
  148.  
  149. + * 
  150.  
  151. + * Description: Linux device driver for AMI MegaRAID controller
  152.  
  153. + *
  154.  
  155. + * History:
  156.  
  157. + *
  158.  
  159. + * Version 0.90:
  160.  
  161. + *     Works and has been tested with the MegaRAID 428 controller, and
  162.  
  163. + *     the MegaRAID 438 controller.  Probably works with the 466 also,
  164.  
  165. + *     but not tested.
  166.  
  167. + *
  168.  
  169. + * Version 0.91:
  170.  
  171. + *     Aligned mailbox area on 16-byte boundry.
  172.  
  173. + *     Added schedule() at the end to properly clean up.
  174.  
  175. + *     Made improvements for conformity to linux driver standards.
  176.  
  177. + *
  178.  
  179. + *
  180.  
  181. + *===================================================================*/
  182.  
  183. +#define QISR 1
  184.  
  185. +
  186.  
  187. +#define CRLFSTR "\n"
  188.  
  189. +
  190.  
  191. +#define MULTIQ 1
  192.  
  193. +
  194.  
  195. +#include <linux/config.h>
  196.  
  197. +
  198.  
  199. +#ifdef MODULE
  200.  
  201. +#include <linux/version.h>
  202.  
  203. +#include <linux/module.h>
  204.  
  205. +
  206.  
  207. +#if LINUX_VERSION_CODE > 0x20118
  208.  
  209. +char kernel_version[] = UTS_RELEASE;
  210.  
  211. +
  212.  
  213. +/* originally ported by Dell Corporation; updated, released, and maintained by
  214.  
  215. +   American Megatrends */
  216.  
  217. +MODULE_AUTHOR("American Megatrends Inc."); 
  218.  
  219. +MODULE_DESCRIPTION("AMI MegaRAID driver");    
  220.  
  221. +#endif
  222.  
  223. +#endif
  224.  
  225. +
  226.  
  227. +#include <linux/types.h>
  228.  
  229. +#include <linux/errno.h>
  230.  
  231. +#include <linux/kernel.h>
  232.  
  233. +#include <linux/sched.h>
  234.  
  235. +#include <linux/malloc.h>
  236.  
  237. +#include <linux/ioport.h>
  238.  
  239. +#include <linux/fcntl.h>
  240.  
  241. +#include <linux/delay.h>
  242.  
  243. +#include <linux/pci.h>
  244.  
  245. +#include <linux/proc_fs.h>
  246.  
  247. +#include <linux/blk.h>
  248.  
  249. +#include <linux/wait.h>
  250.  
  251. +#include <linux/tqueue.h>
  252.  
  253. +#include <linux/interrupt.h>
  254.  
  255. +
  256.  
  257. +#include <linux/sched.h>
  258.  
  259. +#include <linux/stat.h>
  260.  
  261. +#include <linux/malloc.h>    /* for kmalloc() */
  262.  
  263. +#include <linux/config.h>    /* for CONFIG_PCI */
  264.  
  265. +#if LINUX_VERSION_CODE <= 0x20100
  266.  
  267. +#include <linux/bios32.h>
  268.  
  269. +#endif
  270.  
  271. +
  272.  
  273. +#include <asm/io.h>
  274.  
  275. +#include <asm/irq.h>
  276.  
  277. +
  278.  
  279. +#include "sd.h"
  280.  
  281. +#include "scsi.h"
  282.  
  283. +#include "hosts.h"
  284.  
  285. +
  286.  
  287. +#include "megaraid.h"
  288.  
  289. +
  290.  
  291. +//================================================================
  292.  
  293. +//
  294.  
  295. +//                          #Defines
  296.  
  297. +//
  298.  
  299. +//================================================================
  300.  
  301. +#if LINUX_VERSION_CODE < 0x020100
  302.  
  303. +#define ioremap vremap
  304.  
  305. +#define iounmap vfree
  306.  
  307. +#endif
  308.  
  309. +
  310.  
  311. +#define MAX_SERBUF 160
  312.  
  313. +#define COM_BASE 0x2f8
  314.  
  315. +
  316.  
  317. +#define ENQUEUE(obj,type,list,next) \
  318.  
  319. +{ type **node; long cpuflag; \
  320.  
  321. +  save_flags(cpuflag); cli(); \
  322.  
  323. +  for(node=&(list); *node; node=(type **)&(*node)->##next); \
  324.  
  325. +  (*node) = obj; \
  326.  
  327. +  (*node)->##next = NULL; \
  328.  
  329. +  restore_flags(cpuflag); \
  330.  
  331. +};
  332.  
  333. +
  334.  
  335. +#define DEQUEUE(obj,type,list,next) \
  336.  
  337. +{ long cpuflag; \
  338.  
  339. +  save_flags(cpuflag); cli(); \
  340.  
  341. +  if ((obj=list) != NULL) {\
  342.  
  343. +    list = (type *)(list)->##next; \
  344.  
  345. +  } \
  346.  
  347. +  restore_flags(cpuflag); \
  348.  
  349. +};
  350.  
  351. +
  352.  
  353. +u_long RDINDOOR(mega_host_config *megaCfg)
  354.  
  355. +{
  356.  
  357. +  return readl(megaCfg->base + 0x20);
  358.  
  359. +}
  360.  
  361. +
  362.  
  363. +void WRINDOOR(mega_host_config *megaCfg, u_long value)
  364.  
  365. +{
  366.  
  367. +  writel(value,megaCfg->base+0x20);
  368.  
  369. +}
  370.  
  371. +
  372.  
  373. +u_long RDOUTDOOR(mega_host_config *megaCfg)
  374.  
  375. +{
  376.  
  377. +  return readl(megaCfg->base+0x2C);
  378.  
  379. +}
  380.  
  381. +
  382.  
  383. +void WROUTDOOR(mega_host_config *megaCfg, u_long value)
  384.  
  385. +{
  386.  
  387. +  writel(value,megaCfg->base+0x2C);
  388.  
  389. +}
  390.  
  391. +
  392.  
  393. +//================================================================
  394.  
  395. +//
  396.  
  397. +//                    Function prototypes
  398.  
  399. +//
  400.  
  401. +//================================================================
  402.  
  403. +static int  MegaIssueCmd(mega_host_config *megaCfg,
  404.  
  405. +             u_char *mboxData,
  406.  
  407. +             mega_scb *scb,
  408.  
  409. +             int intr);
  410.  
  411. +static int  build_sglist(mega_host_config *megaCfg, mega_scb *scb, 
  412.  
  413. +             u_long *buffer, u_long *length);
  414.  
  415. +
  416.  
  417. +static void mega_runque(void *);
  418.  
  419. +static void mega_rundoneq(void);
  420.  
  421. +static void mega_cmd_done(mega_scb *, int);
  422.  
  423. +
  424.  
  425. +#define SERDEBUG 0
  426.  
  427. +#if SERDEBUG
  428.  
  429. +static void ser_init(void);
  430.  
  431. +static void ser_puts(char *str);
  432.  
  433. +static void ser_putc(char c);
  434.  
  435. +static int  ser_printk(const char *fmt, ...);
  436.  
  437. +#endif
  438.  
  439. +
  440.  
  441. +//================================================================
  442.  
  443. +//
  444.  
  445. +//                    Global variables
  446.  
  447. +//
  448.  
  449. +//================================================================
  450.  
  451. +static int               numCtlrs = 0;
  452.  
  453. +static mega_host_config *megaCtlrs[4] = { 0 };
  454.  
  455. +
  456.  
  457. +/* Change this to 0 if you want to see the raw drives */
  458.  
  459. +static int use_raid   = 1;
  460.  
  461. +
  462.  
  463. +/* Queue of pending/completed SCBs */
  464.  
  465. +static mega_scb  *qPending   = NULL;
  466.  
  467. +static Scsi_Cmnd *qCompleted = NULL;
  468.  
  469. +
  470.  
  471. +static struct tq_struct runq = {0,0,mega_runque,NULL};
  472.  
  473. +
  474.  
  475. +struct proc_dir_entry proc_scsi_megaraid = {
  476.  
  477. +  PROC_SCSI_MEGARAID, 8, "megaraid",
  478.  
  479. +  S_IFDIR | S_IRUGO | S_IXUGO, 2
  480.  
  481. +};
  482.  
  483. +
  484.  
  485. +#if SERDEBUG
  486.  
  487. +static char strbuf[MAX_SERBUF+1];
  488.  
  489. +
  490.  
  491. +static void ser_init()
  492.  
  493. +{
  494.  
  495. +    unsigned port=COM_BASE;
  496.  
  497. +
  498.  
  499. +    outb(0x80,port+3);
  500.  
  501. +    outb(0,port+1);
  502.  
  503. +    /* 9600 Baud, if 19200: outb(6,port) */
  504.  
  505. +    outb(12, port);
  506.  
  507. +    outb(3,port+3);
  508.  
  509. +    outb(0,port+1);
  510.  
  511. +}
  512.  
  513. +
  514.  
  515. +static void ser_puts(char *str)
  516.  
  517. +{
  518.  
  519. +    char *ptr;
  520.  
  521. +
  522.  
  523. +    ser_init();
  524.  
  525. +    for (ptr=str;*ptr;++ptr)
  526.  
  527. +        ser_putc(*ptr);
  528.  
  529. +}
  530.  
  531. +
  532.  
  533. +static void ser_putc(char c)
  534.  
  535. +{
  536.  
  537. +    unsigned port=COM_BASE;
  538.  
  539. +
  540.  
  541. +    while ((inb(port+5) & 0x20)==0);
  542.  
  543. +    outb(c,port);
  544.  
  545. +    if (c==0x0a)
  546.  
  547. +    {
  548.  
  549. +        while ((inb(port+5) & 0x20)==0);
  550.  
  551. +        outb(0x0d,port);
  552.  
  553. +    }
  554.  
  555. +}
  556.  
  557. +
  558.  
  559. +static int ser_printk(const char *fmt, ...)
  560.  
  561. +{
  562.  
  563. +    va_list args;
  564.  
  565. +    int i;
  566.  
  567. +    long flags;
  568.  
  569. +
  570.  
  571. +    save_flags(flags);
  572.  
  573. +    cli();
  574.  
  575. +    va_start(args,fmt);
  576.  
  577. +    i = vsprintf(strbuf,fmt,args);
  578.  
  579. +    ser_puts(strbuf);
  580.  
  581. +    va_end(args);
  582.  
  583. +    restore_flags(flags);
  584.  
  585. +
  586.  
  587. +    return i;
  588.  
  589. +}
  590.  
  591. +
  592.  
  593. +#define TRACE(a)    { ser_printk a;}
  594.  
  595. +
  596.  
  597. +#else
  598.  
  599. +#define TRACE(A)
  600.  
  601. +#endif
  602.  
  603. +
  604.  
  605. +void callDone(Scsi_Cmnd *SCpnt)
  606.  
  607. +{
  608.  
  609. +  long flags;
  610.  
  611. +
  612.  
  613. +  if (SCpnt->result) {
  614.  
  615. +    TRACE(("*** %.08lx %.02x <%d.%d.%d> = %x\n", SCpnt->serial_number, 
  616.  
  617. +       SCpnt->cmnd[0], SCpnt->channel, SCpnt->target, SCpnt->lun, 
  618.  
  619. +       SCpnt->result));
  620.  
  621. +  }
  622.  
  623. +  save_flags(flags);
  624.  
  625. +  sti();
  626.  
  627. +  SCpnt->scsi_done(SCpnt);
  628.  
  629. +  restore_flags(flags);
  630.  
  631. +}
  632.  
  633. +
  634.  
  635. +/*-------------------------------------------------------------------------
  636.  
  637. + *
  638.  
  639. + *                      Local functions
  640.  
  641. + *
  642.  
  643. + *-------------------------------------------------------------------------*/
  644.  
  645. +
  646.  
  647. +//================================================
  648.  
  649. +// Initialize SCB structures
  650.  
  651. +//================================================
  652.  
  653. +static void initSCB(mega_host_config *megaCfg)
  654.  
  655. +{
  656.  
  657. +  int idx;
  658.  
  659. +
  660.  
  661. +  for(idx=0; idx<megaCfg->max_cmds; idx++) {
  662.  
  663. +    megaCfg->scbList[idx].idx    = -1;
  664.  
  665. +    megaCfg->scbList[idx].flag   = 0;
  666.  
  667. +    megaCfg->scbList[idx].sgList = NULL;
  668.  
  669. +    megaCfg->scbList[idx].SCpnt  = NULL;
  670.  
  671. +  }
  672.  
  673. +}
  674.  
  675. +
  676.  
  677. +//===========================
  678.  
  679. +// Allocate a SCB structure
  680.  
  681. +//===========================
  682.  
  683. +static mega_scb *allocateSCB(mega_host_config *megaCfg, Scsi_Cmnd *SCpnt)
  684.  
  685. +{
  686.  
  687. +  int        idx;
  688.  
  689. +  long       flags;
  690.  
  691. +
  692.  
  693. +  save_flags(flags);
  694.  
  695. +  cli();
  696.  
  697. +  for(idx=0; idx<megaCfg->max_cmds; idx++) {
  698.  
  699. +    if (megaCfg->scbList[idx].idx < 0) {
  700.  
  701. +
  702.  
  703. +      /* Set Index and SCB pointer */ 
  704.  
  705. +      megaCfg->scbList[idx].flag  = 0;
  706.  
  707. +      megaCfg->scbList[idx].idx   = idx;
  708.  
  709. +      megaCfg->scbList[idx].SCpnt = SCpnt;
  710.  
  711. +      megaCfg->scbList[idx].next  = NULL;
  712.  
  713. +
  714.  
  715. +      /* Lazy allocate Scatter-gather list */
  716.  
  717. +      if (megaCfg->scbList[idx].sgList == NULL) {
  718.  
  719. +    megaCfg->scbList[idx].sgList = kmalloc(sizeof(mega_sglist)*MAX_SGLIST,
  720.  
  721. +                           GFP_ATOMIC|GFP_DMA);
  722.  
  723. +      }
  724.  
  725. +#if 0
  726.  
  727. +      TRACE(("kmalloc() = 0x%x\n",megaCfg->scbList[idx].sgList));
  728.  
  729. +#endif
  730.  
  731. +      restore_flags(flags);
  732.  
  733. +
  734.  
  735. +      return &megaCfg->scbList[idx];
  736.  
  737. +    }
  738.  
  739. +  }
  740.  
  741. +  restore_flags(flags);
  742.  
  743. +
  744.  
  745. +  printk("Megaraid: Could not allocate free SCB!!!\n");
  746.  
  747. +  
  748.  
  749. +  return NULL;
  750.  
  751. +}
  752.  
  753. +
  754.  
  755. +//=======================
  756.  
  757. +// Free a SCB structure
  758.  
  759. +//=======================
  760.  
  761. +static void freeSCB(mega_scb *scb)
  762.  
  763. +{
  764.  
  765. +  long flags;
  766.  
  767. +
  768.  
  769. +  save_flags(flags);
  770.  
  771. +  cli();
  772.  
  773. +  scb->flag  = 0;
  774.  
  775. +  scb->idx   = -1;
  776.  
  777. +  scb->next  = NULL;
  778.  
  779. +  scb->SCpnt = NULL;
  780.  
  781. +  restore_flags(flags);
  782.  
  783. +}
  784.  
  785. +
  786.  
  787. +/* Run through the list of completed requests */
  788.  
  789. +static void mega_rundoneq()
  790.  
  791. +{
  792.  
  793. +  mega_host_config *megaCfg;
  794.  
  795. +  Scsi_Cmnd        *SCpnt;
  796.  
  797. +  long              islogical;
  798.  
  799. +
  800.  
  801. +  while(1) {
  802.  
  803. +    DEQUEUE(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
  804.  
  805. +    if (SCpnt == NULL) return;
  806.  
  807. +
  808.  
  809. +    megaCfg = (mega_host_config *)SCpnt->host->hostdata;
  810.  
  811. +
  812.  
  813. +    /* Check if we're allowing access to RAID drives or physical
  814.  
  815. +     *  if use_raid == 1 and this wasn't a disk on the max channel or
  816.  
  817. +     *  if use_raid == 0 and this was a disk on the max channel
  818.  
  819. +     *  then fail.
  820.  
  821. +     */
  822.  
  823. +    islogical = (SCpnt->channel == megaCfg->host->max_channel) ? 1 : 0;
  824.  
  825. +    if (SCpnt->cmnd[0] == INQUIRY &&
  826.  
  827. +    ((((u_char*)SCpnt->request_buffer)[0] & 0x1F) == TYPE_DISK) &&
  828.  
  829. +    (islogical != use_raid)) {
  830.  
  831. +       SCpnt->result = 0xF0;
  832.  
  833. +    }
  834.  
  835. +
  836.  
  837. +    /* Convert result to error */
  838.  
  839. +    switch(SCpnt->result) {
  840.  
  841. +    case 0x00: case 0x02:
  842.  
  843. +      SCpnt->result |= (DID_OK << 16);
  844.  
  845. +      break;
  846.  
  847. +    case 0x8:
  848.  
  849. +      SCpnt->result |= (DID_BUS_BUSY << 16);
  850.  
  851. +      break;
  852.  
  853. +    default:
  854.  
  855. +      SCpnt->result |= (DID_BAD_TARGET << 16);
  856.  
  857. +      break;
  858.  
  859. +    }
  860.  
  861. +
  862.  
  863. +    /* Callback */
  864.  
  865. +    callDone(SCpnt);
  866.  
  867. +  }
  868.  
  869. +}
  870.  
  871. +
  872.  
  873. +/* Add command to the list of completed requests */
  874.  
  875. +static void mega_cmd_done(mega_scb *pScb, int status)
  876.  
  877. +{
  878.  
  879. +  pScb->SCpnt->result = status;
  880.  
  881. +  ENQUEUE(pScb->SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
  882.  
  883. +  freeSCB(pScb);
  884.  
  885. +}
  886.  
  887. +
  888.  
  889. +/*----------------------------------------------------
  890.  
  891. + * Process pending queue list
  892.  
  893. + *
  894.  
  895. + * Run as a scheduled task 
  896.  
  897. + *----------------------------------------------------*/
  898.  
  899. +static void mega_runque(void *dummy)
  900.  
  901. +{
  902.  
  903. +  mega_host_config *megaCfg;
  904.  
  905. +  mega_scb         *pScb;
  906.  
  907. +  long              flags;
  908.  
  909. +
  910.  
  911. +  /* Take care of any completed requests */
  912.  
  913. +  mega_rundoneq();
  914.  
  915. +
  916.  
  917. +  DEQUEUE(pScb,mega_scb,qPending,next);
  918.  
  919. +
  920.  
  921. +  if (pScb) {
  922.  
  923. +    megaCfg = (mega_host_config *)pScb->SCpnt->host->hostdata;
  924.  
  925. +
  926.  
  927. +    if (megaCfg->mbox->busy || megaCfg->flag & (IN_ISR|PENDING)) {
  928.  
  929. +      printk("PENDING = %x, IN_ISR = %x, mbox.busy = %x\n",(u_int)(megaCfg->flag
  930.  
  931. +            & PENDING), (u_int)(megaCfg->flag & IN_ISR), megaCfg->mbox->busy);
  932.  
  933. +      TRACE(("%.08lx %.02x <%d.%d.%d> intr%d busy%d isr%d pending%d\n",
  934.  
  935. +         pScb->SCpnt->serial_number,
  936.  
  937. +         pScb->SCpnt->cmnd[0],
  938.  
  939. +         pScb->SCpnt->channel,
  940.  
  941. +         pScb->SCpnt->target,
  942.  
  943. +         pScb->SCpnt->lun,
  944.  
  945. +         intr_count,
  946.  
  947. +         megaCfg->mbox->busy,
  948.  
  949. +         (megaCfg->flag & IN_ISR)  ? 1 : 0,
  950.  
  951. +         (megaCfg->flag & PENDING) ? 1 : 0));
  952.  
  953. +    }
  954.  
  955. +    if (MegaIssueCmd(megaCfg, pScb->mboxData, pScb, 1)) {
  956.  
  957. +      printk("MegaIssueCmd returned BUSY.  Rescheduling command.\n");
  958.  
  959. +      /* We're BUSY... come back later */
  960.  
  961. +      save_flags(flags);
  962.  
  963. +      cli();
  964.  
  965. +      pScb->next = qPending;
  966.  
  967. +      qPending   = pScb;
  968.  
  969. +      restore_flags(flags);
  970.  
  971. +
  972.  
  973. +      if (!(megaCfg->flag & PENDING)) { /* If PENDING, irq will schedule task */
  974.  
  975. +          queue_task(&runq, &tq_scheduler);
  976.  
  977. +      }
  978.  
  979. +    }
  980.  
  981. +  }
  982.  
  983. +}
  984.  
  985. +
  986.  
  987. +/*-------------------------------------------------------------------
  988.  
  989. + *
  990.  
  991. + *                 Build a SCB from a Scsi_Cmnd
  992.  
  993. + *
  994.  
  995. + * Returns a SCB pointer, or NULL
  996.  
  997. + * If NULL is returned, the scsi_done function MUST have been called
  998.  
  999. + *
  1000.  
  1001. + *-------------------------------------------------------------------*/
  1002.  
  1003. +static mega_scb *mega_build_cmd(mega_host_config *megaCfg, Scsi_Cmnd *SCpnt)
  1004.  
  1005. +{
  1006.  
  1007. +  mega_scb      *pScb;
  1008.  
  1009. +  mega_mailbox  *mbox;
  1010.  
  1011. +  mega_passthru *pthru;
  1012.  
  1013. +  long           seg;
  1014.  
  1015. +
  1016.  
  1017. +  /* We don't support multi-luns */
  1018.  
  1019. +  if (SCpnt->lun != 0) {
  1020.  
  1021. +    SCpnt->result = (DID_BAD_TARGET << 16);
  1022.  
  1023. +    callDone(SCpnt);
  1024.  
  1025. +    return NULL;
  1026.  
  1027. +  }
  1028.  
  1029. +
  1030.  
  1031. +  /*-----------------------------------------------------
  1032.  
  1033. +   *
  1034.  
  1035. +   *               Logical drive commands
  1036.  
  1037. +   *
  1038.  
  1039. +   *-----------------------------------------------------*/
  1040.  
  1041. +  if (SCpnt->channel == megaCfg->host->max_channel) {
  1042.  
  1043. +    switch(SCpnt->cmnd[0]) {
  1044.  
  1045. +    case TEST_UNIT_READY:
  1046.  
  1047. +      memset(SCpnt->request_buffer, 0, SCpnt->request_bufflen);
  1048.  
  1049. +      SCpnt->result = (DID_OK << 16);
  1050.  
  1051. +      callDone(SCpnt);
  1052.  
  1053. +      return NULL;
  1054.  
  1055. +
  1056.  
  1057. +    case MODE_SENSE:
  1058.  
  1059. +      memset(SCpnt->request_buffer, 0, SCpnt->cmnd[4]);
  1060.  
  1061. +      SCpnt->result = (DID_OK << 16);
  1062.  
  1063. +      callDone(SCpnt);
  1064.  
  1065. +      return NULL;
  1066.  
  1067. +
  1068.  
  1069. +    case READ_CAPACITY:
  1070.  
  1071. +    case INQUIRY:
  1072.  
  1073. +      /* Allocate a SCB and initialize passthru */
  1074.  
  1075. +      if ((pScb = allocateSCB(megaCfg, SCpnt)) == NULL) {
  1076.  
  1077. +    SCpnt->result = (DID_ERROR << 16);
  1078.  
  1079. +    callDone(SCpnt);
  1080.  
  1081. +    return NULL;
  1082.  
  1083. +      }
  1084.  
  1085. +      pthru = &pScb->pthru;
  1086.  
  1087. +      mbox  = (mega_mailbox *)&pScb->mboxData;
  1088.  
  1089. +
  1090.  
  1091. +      memset(mbox,  0, sizeof(pScb->mboxData));
  1092.  
  1093. +      memset(pthru, 0, sizeof(mega_passthru));
  1094.  
  1095. +      pthru->timeout      = 0;
  1096.  
  1097. +      pthru->ars          = 0;
  1098.  
  1099. +      pthru->islogical    = 1;
  1100.  
  1101. +      pthru->logdrv       = SCpnt->target;
  1102.  
  1103. +      pthru->cdblen       = SCpnt->cmd_len;
  1104.  
  1105. +      pthru->dataxferaddr = (u_long)SCpnt->request_buffer;
  1106.  
  1107. +      pthru->dataxferlen  = SCpnt->request_bufflen;
  1108.  
  1109. +      memcpy(pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len);
  1110.  
  1111. +
  1112.  
  1113. +      /* Initialize mailbox area */
  1114.  
  1115. +      mbox->cmd      = MEGA_MBOXCMD_PASSTHRU;
  1116.  
  1117. +      mbox->xferaddr = (u_long)pthru;
  1118.  
  1119. +
  1120.  
  1121. +      return pScb;
  1122.  
  1123. +
  1124.  
  1125. +    case READ_6:
  1126.  
  1127. +    case WRITE_6:
  1128.  
  1129. +    case READ_10:
  1130.  
  1131. +    case WRITE_10:
  1132.  
  1133. +      /* Allocate a SCB and initialize mailbox */
  1134.  
  1135. +      if ((pScb = allocateSCB(megaCfg, SCpnt)) == NULL) {
  1136.  
  1137. +    SCpnt->result = (DID_ERROR << 16);
  1138.  
  1139. +    callDone(SCpnt);
  1140.  
  1141. +    return NULL;
  1142.  
  1143. +      }
  1144.  
  1145. +      mbox = (mega_mailbox *)&pScb->mboxData;
  1146.  
  1147. +
  1148.  
  1149. +      memset(mbox, 0, sizeof(pScb->mboxData));
  1150.  
  1151. +      mbox->logdrv = SCpnt->target;
  1152.  
  1153. +      mbox->cmd    = (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == READ_10) ?
  1154.  
  1155. +    MEGA_MBOXCMD_LREAD : MEGA_MBOXCMD_LWRITE;
  1156.  
  1157. +      
  1158.  
  1159. +      /* 6-byte */
  1160.  
  1161. +      if (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == WRITE_6) {
  1162.  
  1163. +    mbox->numsectors = 
  1164.  
  1165. +      (u_long)SCpnt->cmnd[4];
  1166.  
  1167. +    mbox->lba = 
  1168.  
  1169. +      ((u_long)SCpnt->cmnd[1] << 16) |
  1170.  
  1171. +      ((u_long)SCpnt->cmnd[2] << 8) |
  1172.  
  1173. +      (u_long)SCpnt->cmnd[3];
  1174.  
  1175. +    mbox->lba &= 0x1FFFFF;
  1176.  
  1177. +      }
  1178.  
  1179. +      
  1180.  
  1181. +      /* 10-byte */
  1182.  
  1183. +      if (*SCpnt->cmnd == READ_10 || *SCpnt->cmnd == WRITE_10) {
  1184.  
  1185. +    mbox->numsectors = 
  1186.  
  1187. +      (u_long)SCpnt->cmnd[8] |
  1188.  
  1189. +      ((u_long)SCpnt->cmnd[7] << 8);
  1190.  
  1191. +    mbox->lba =
  1192.  
  1193. +      ((u_long)SCpnt->cmnd[2] << 24) |
  1194.  
  1195. +      ((u_long)SCpnt->cmnd[3] << 16) |
  1196.  
  1197. +      ((u_long)SCpnt->cmnd[4] << 8) |
  1198.  
  1199. +      (u_long)SCpnt->cmnd[5];
  1200.  
  1201. +      }
  1202.  
  1203. +      
  1204.  
  1205. +      /* Calculate Scatter-Gather info */
  1206.  
  1207. +      mbox->numsgelements = build_sglist(megaCfg, pScb, 
  1208.  
  1209. +                     (u_long*)&mbox->xferaddr,
  1210.  
  1211. +                     (u_long*)&seg);
  1212.  
  1213. +
  1214.  
  1215. +      return pScb;
  1216.  
  1217. +      
  1218.  
  1219. +    default:
  1220.  
  1221. +      SCpnt->result = (DID_BAD_TARGET << 16);
  1222.  
  1223. +      callDone(SCpnt);
  1224.  
  1225. +      return NULL;
  1226.  
  1227. +    }
  1228.  
  1229. +  }
  1230.  
  1231. +  /*-----------------------------------------------------
  1232.  
  1233. +   *
  1234.  
  1235. +   *               Passthru drive commands
  1236.  
  1237. +   *
  1238.  
  1239. +   *-----------------------------------------------------*/
  1240.  
  1241. +  else {
  1242.  
  1243. +    /* Allocate a SCB and initialize passthru */
  1244.  
  1245. +    if ((pScb = allocateSCB(megaCfg, SCpnt)) == NULL) {
  1246.  
  1247. +      SCpnt->result = (DID_ERROR << 16);
  1248.  
  1249. +      callDone(SCpnt);
  1250.  
  1251. +      return NULL;
  1252.  
  1253. +    }
  1254.  
  1255. +    pthru = &pScb->pthru;
  1256.  
  1257. +    mbox  = (mega_mailbox *)pScb->mboxData;
  1258.  
  1259. +    
  1260.  
  1261. +    memset(mbox,  0, sizeof(pScb->mboxData));
  1262.  
  1263. +    memset(pthru, 0, sizeof(mega_passthru));
  1264.  
  1265. +    pthru->timeout   = 0;
  1266.  
  1267. +    pthru->ars       = 0;
  1268.  
  1269. +    pthru->islogical = 0;
  1270.  
  1271. +    pthru->channel   = SCpnt->channel;
  1272.  
  1273. +    pthru->target    = SCpnt->target;
  1274.  
  1275. +    pthru->cdblen    = SCpnt->cmd_len;
  1276.  
  1277. +    memcpy(pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len);
  1278.  
  1279. +    
  1280.  
  1281. +    pthru->numsgelements = build_sglist(megaCfg, pScb,
  1282.  
  1283. +                    (u_long *)&pthru->dataxferaddr,
  1284.  
  1285. +                    (u_long *)&pthru->dataxferlen);
  1286.  
  1287. +    
  1288.  
  1289. +    /* Initialize mailbox */
  1290.  
  1291. +    mbox->cmd      = MEGA_MBOXCMD_PASSTHRU;
  1292.  
  1293. +    mbox->xferaddr = (u_long)pthru;
  1294.  
  1295. +
  1296.  
  1297. +    return pScb;
  1298.  
  1299. +  }
  1300.  
  1301. +  return NULL;
  1302.  
  1303. +}
  1304.  
  1305. +
  1306.  
  1307. +/*--------------------------------------------------------------------
  1308.  
  1309. + * Interrupt service routine
  1310.  
  1311. + *--------------------------------------------------------------------*/
  1312.  
  1313. +static void megaraid_isr(int irq, void *devp, struct pt_regs *regs)
  1314.  
  1315. +{
  1316.  
  1317. +  mega_host_config *megaCfg;
  1318.  
  1319. +  u_char            byte, idx, sIdx;
  1320.  
  1321. +  u_long            dword;
  1322.  
  1323. +  mega_mailbox     *mbox;
  1324.  
  1325. +  mega_scb         *pScb;
  1326.  
  1327. +  long              flags;
  1328.  
  1329. +  int               qCnt, qStatus;
  1330.  
  1331. +
  1332.  
  1333. +  megaCfg = (mega_host_config *)devp;
  1334.  
  1335. +  mbox    = (mega_mailbox *)megaCfg->mbox;
  1336.  
  1337. +
  1338.  
  1339. +  if (megaCfg->host->irq == irq) {
  1340.  
  1341. +    save_flags(flags);
  1342.  
  1343. +    cli();
  1344.  
  1345. +
  1346.  
  1347. +    if (megaCfg->flag & IN_ISR) {
  1348.  
  1349. +      TRACE(("ISR called reentrantly!!\n"));
  1350.  
  1351. +    }
  1352.  
  1353. +
  1354.  
  1355. +    megaCfg->flag |= IN_ISR;
  1356.  
  1357. +
  1358.  
  1359. +    /* Check if a valid interrupt is pending */
  1360.  
  1361. +    if (megaCfg->flag & BOARD_QUARTZ) {
  1362.  
  1363. +        dword = RDOUTDOOR(megaCfg);
  1364.  
  1365. +        if (dword != 0x10001234) {
  1366.  
  1367. +            /* Spurious interrupt */
  1368.  
  1369. +            megaCfg->flag &= ~IN_ISR;
  1370.  
  1371. +            restore_flags(flags);
  1372.  
  1373. +            return;
  1374.  
  1375. +        }
  1376.  
  1377. +        WROUTDOOR(megaCfg,dword);
  1378.  
  1379. +    } else {
  1380.  
  1381. +        byte = READ_PORT(megaCfg->host->io_port, INTR_PORT);
  1382.  
  1383. +        if ((byte & VALID_INTR_BYTE) == 0) {
  1384.  
  1385. +          /* Spurious interrupt */
  1386.  
  1387. +          megaCfg->flag &= ~IN_ISR;
  1388.  
  1389. +          restore_flags(flags);
  1390.  
  1391. +          return;
  1392.  
  1393. +        }
  1394.  
  1395. +        WRITE_PORT(megaCfg->host->io_port, INTR_PORT, byte);
  1396.  
  1397. +    }
  1398.  
  1399. +    
  1400.  
  1401. +    qCnt    = mbox->numstatus;
  1402.  
  1403. +    qStatus = mbox->status;
  1404.  
  1405. +
  1406.  
  1407. +    if (qCnt > 1) {TRACE(("ISR: Received %d status\n", qCnt))
  1408.  
  1409. +        printk("Got numstatus = %d\n",qCnt);
  1410.  
  1411. +    }
  1412.  
  1413. +    
  1414.  
  1415. +    for(idx=0; idx<qCnt; idx++) {
  1416.  
  1417. +      sIdx = mbox->completed[idx];
  1418.  
  1419. +      if (sIdx > 0) {
  1420.  
  1421. +    pScb = &megaCfg->scbList[sIdx-1];
  1422.  
  1423. +    mega_cmd_done(&megaCfg->scbList[sIdx-1], qStatus);
  1424.  
  1425. +      }
  1426.  
  1427. +    }
  1428.  
  1429. +    if (megaCfg->flag & BOARD_QUARTZ) {
  1430.  
  1431. +        WRINDOOR(megaCfg,virt_to_bus(megaCfg->mbox)|0x2);
  1432.  
  1433. +        while (RDINDOOR(megaCfg) & 0x02);
  1434.  
  1435. +    } else {
  1436.  
  1437. +        CLEAR_INTR(megaCfg->host->io_port);
  1438.  
  1439. +    }
  1440.  
  1441. +
  1442.  
  1443. +    megaCfg->flag &= ~IN_ISR;
  1444.  
  1445. +    megaCfg->flag &= ~PENDING;
  1446.  
  1447. +
  1448.  
  1449. +    /* Queue as a delayed ISR routine */
  1450.  
  1451. +    queue_task_irq_off(&runq, &tq_immediate);
  1452.  
  1453. +    mark_bh(IMMEDIATE_BH);
  1454.  
  1455. +
  1456.  
  1457. +    restore_flags(flags);
  1458.  
  1459. +  }
  1460.  
  1461. +}
  1462.  
  1463. +
  1464.  
  1465. +/*==================================================*/
  1466.  
  1467. +/* Wait until the controller's mailbox is available */
  1468.  
  1469. +/*==================================================*/
  1470.  
  1471. +static int busyWaitMbox(mega_host_config *megaCfg)
  1472.  
  1473. +{
  1474.  
  1475. +  mega_mailbox *mbox = (mega_mailbox *)megaCfg->mbox;
  1476.  
  1477. +  long          counter;
  1478.  
  1479. +
  1480.  
  1481. +  for(counter=0; counter<0xFFFFFF; counter++) {
  1482.  
  1483. +    if (!mbox->busy) return 0;
  1484.  
  1485. +  }
  1486.  
  1487. +  return -1;
  1488.  
  1489. +}
  1490.  
  1491. +
  1492.  
  1493. +//=====================================================
  1494.  
  1495. +// Post a command to the card
  1496.  
  1497. +//
  1498.  
  1499. +// Arguments:
  1500.  
  1501. +//   mega_host_config *megaCfg - Controller structure
  1502.  
  1503. +//   u_char *mboxData - Mailbox area, 16 bytes
  1504.  
  1505. +//   mega_scb *pScb   - SCB posting (or NULL if N/A)
  1506.  
  1507. +//   int intr         - if 1, interrupt, 0 is blocking
  1508.  
  1509. +//=====================================================
  1510.  
  1511. +static int MegaIssueCmd(mega_host_config *megaCfg,
  1512.  
  1513. +            u_char *mboxData,
  1514.  
  1515. +            mega_scb *pScb,
  1516.  
  1517. +            int intr)
  1518.  
  1519. +{
  1520.  
  1521. +  mega_mailbox *mbox = (mega_mailbox *)megaCfg->mbox;
  1522.  
  1523. +  long          flags;
  1524.  
  1525. +  u_char        byte;
  1526.  
  1527. +  u_long        cmdDone;
  1528.  
  1529. +
  1530.  
  1531. +#if 0
  1532.  
  1533. +    if (pScb) {
  1534.  
  1535. +      pScb->SCpnt->result = DID_BAD_TARGET << 16;
  1536.  
  1537. +      callDone(pScb->SCpnt);
  1538.  
  1539. +      freeSCB(pScb);
  1540.  
  1541. +    }
  1542.  
  1543. +    return 0;
  1544.  
  1545. +#endif
  1546.  
  1547. +
  1548.  
  1549. +  mboxData[0x1] = (pScb ? pScb->idx+1 : 0x00);  /* Set cmdid */
  1550.  
  1551. +  mboxData[0xF] = 1;                            /* Set busy */
  1552.  
  1553. +
  1554.  
  1555. +  /* gah.. issuing a command while pending seems to fall through
  1556.  
  1557. +   * the cracks.. 
  1558.  
  1559. +   */
  1560.  
  1561. +  if (megaCfg->flag & PENDING) {
  1562.  
  1563. +    return -1;
  1564.  
  1565. +  }
  1566.  
  1567. +
  1568.  
  1569. +  /* Wait until mailbox is free */
  1570.  
  1571. +  if (busyWaitMbox(megaCfg)) {
  1572.  
  1573. +    if (pScb) {
  1574.  
  1575. +      TRACE(("Mailbox busy %.08lx <%d.%d.%d>\n", pScb->SCpnt->serial_number,
  1576.  
  1577. +         pScb->SCpnt->channel, pScb->SCpnt->target, pScb->SCpnt->lun));
  1578.  
  1579. +    }
  1580.  
  1581. +    return -1;
  1582.  
  1583. +  }
  1584.  
  1585. +
  1586.  
  1587. +  /* Copy mailbox data into host structure */
  1588.  
  1589. +  save_flags(flags);
  1590.  
  1591. +  cli();
  1592.  
  1593. +  memset(mbox, 0, sizeof(mega_mailbox));
  1594.  
  1595. +  memcpy(mbox, mboxData, 16);
  1596.  
  1597. +  restore_flags(flags);
  1598.  
  1599. +
  1600.  
  1601. +  /* Kick IO */
  1602.  
  1603. +  megaCfg->flag |= PENDING;
  1604.  
  1605. +  if (intr) {
  1606.  
  1607. +    /* Issue interrupt (non-blocking) command */
  1608.  
  1609. +    if (megaCfg->flag & BOARD_QUARTZ) {
  1610.  
  1611. +        mbox->mraid_poll = 0; 
  1612.  
  1613. +        mbox->mraid_ack = 0; 
  1614.  
  1615. +        WRINDOOR(megaCfg, virt_to_bus(megaCfg->mbox) | 0x1);
  1616.  
  1617. +    } else {
  1618.  
  1619. +        ENABLE_INTR(megaCfg->host->io_port);
  1620.  
  1621. +        ISSUE_COMMAND(megaCfg->host->io_port);
  1622.  
  1623. +    }
  1624.  
  1625. +  }
  1626.  
  1627. +  else {      /* Issue non-ISR (blocking) command */
  1628.  
  1629. +
  1630.  
  1631. +    if (megaCfg->flag & BOARD_QUARTZ) {
  1632.  
  1633. +
  1634.  
  1635. +      mbox->mraid_poll = 0; 
  1636.  
  1637. +      mbox->mraid_ack = 0; 
  1638.  
  1639. +      WRINDOOR(megaCfg, virt_to_bus(megaCfg->mbox) | 0x1);
  1640.  
  1641. +
  1642.  
  1643. +      while((cmdDone=RDOUTDOOR(megaCfg)) != 0x10001234);
  1644.  
  1645. +      WROUTDOOR(megaCfg, cmdDone);
  1646.  
  1647. +
  1648.  
  1649. +      if (pScb) {
  1650.  
  1651. +    mega_cmd_done(pScb, mbox->status);
  1652.  
  1653. +    mega_rundoneq();
  1654.  
  1655. +      }
  1656.  
  1657. +
  1658.  
  1659. +      WRINDOOR(megaCfg,virt_to_bus(megaCfg->mbox) | 0x2);
  1660.  
  1661. +      while(RDINDOOR(megaCfg) & 0x2);
  1662.  
  1663. +
  1664.  
  1665. +      megaCfg->flag &= ~PENDING;
  1666.  
  1667. +    }
  1668.  
  1669. +    else {
  1670.  
  1671. +      DISABLE_INTR(megaCfg->host->io_port);
  1672.  
  1673. +      ISSUE_COMMAND(megaCfg->host->io_port);
  1674.  
  1675. +      
  1676.  
  1677. +      while(!((byte=READ_PORT(megaCfg->host->io_port,INTR_PORT))&INTR_VALID));
  1678.  
  1679. +      WRITE_PORT(megaCfg->host->io_port, INTR_PORT, byte);
  1680.  
  1681. +      
  1682.  
  1683. +      ENABLE_INTR(megaCfg->host->io_port);
  1684.  
  1685. +      CLEAR_INTR(megaCfg->host->io_port);
  1686.  
  1687. +      
  1688.  
  1689. +      if (pScb) {
  1690.  
  1691. +    mega_cmd_done(pScb, mbox->status);
  1692.  
  1693. +    mega_rundoneq();
  1694.  
  1695. +      }
  1696.  
  1697. +      megaCfg->flag &= ~PENDING;
  1698.  
  1699. +    }
  1700.  
  1701. +  }
  1702.  
  1703. +
  1704.  
  1705. +  return 0;
  1706.  
  1707. +}
  1708.  
  1709. +
  1710.  
  1711. +/*-------------------------------------------------------------------
  1712.  
  1713. + * Copies data to SGLIST
  1714.  
  1715. + *-------------------------------------------------------------------*/
  1716.  
  1717. +static int build_sglist(mega_host_config *megaCfg, mega_scb *scb, 
  1718.  
  1719. +            u_long *buffer, u_long *length)
  1720.  
  1721. +{
  1722.  
  1723. +  struct scatterlist *sgList;
  1724.  
  1725. +  int idx;
  1726.  
  1727. +
  1728.  
  1729. +  /* Scatter-gather not used */
  1730.  
  1731. +  if (scb->SCpnt->use_sg == 0) {
  1732.  
  1733. +    *buffer = (u_long)scb->SCpnt->request_buffer;
  1734.  
  1735. +    *length = (u_long)scb->SCpnt->request_bufflen;
  1736.  
  1737. +    return 0;
  1738.  
  1739. +  }
  1740.  
  1741. +
  1742.  
  1743. +  sgList = (struct scatterlist *)scb->SCpnt->buffer;
  1744.  
  1745. +  if (scb->SCpnt->use_sg == 1) {
  1746.  
  1747. +    *buffer = (u_long)sgList[0].address;
  1748.  
  1749. +    *length = (u_long)sgList[0].length;
  1750.  
  1751. +    return 0;
  1752.  
  1753. +  }
  1754.  
  1755. +
  1756.  
  1757. +  /* Copy Scatter-Gather list info into controller structure */
  1758.  
  1759. +  for(idx=0; idx<scb->SCpnt->use_sg; idx++) {
  1760.  
  1761. +    scb->sgList[idx].address = (u_long)sgList[idx].address;
  1762.  
  1763. +    scb->sgList[idx].length  = (u_long)sgList[idx].length;
  1764.  
  1765. +  }
  1766.  
  1767. +  
  1768.  
  1769. +  /* Reset pointer and length fields */
  1770.  
  1771. +  *buffer = (u_long)scb->sgList;
  1772.  
  1773. +  *length = 0;
  1774.  
  1775. +
  1776.  
  1777. +  /* Return count of SG requests */
  1778.  
  1779. +  return scb->SCpnt->use_sg;
  1780.  
  1781. +}
  1782.  
  1783. +    
  1784.  
  1785. +/*--------------------------------------------------------------------
  1786.  
  1787. + * Initializes the adress of the controller's mailbox register
  1788.  
  1789. + *  The mailbox register is used to issue commands to the card.
  1790.  
  1791. + *  Format of the mailbox area:
  1792.  
  1793. + *   00 01 command
  1794.  
  1795. + *   01 01 command id
  1796.  
  1797. + *   02 02 # of sectors
  1798.  
  1799. + *   04 04 logical bus address
  1800.  
  1801. + *   08 04 physical buffer address
  1802.  
  1803. + *   0C 01 logical drive #
  1804.  
  1805. + *   0D 01 length of scatter/gather list
  1806.  
  1807. + *   0E 01 reserved
  1808.  
  1809. + *   0F 01 mailbox busy
  1810.  
  1811. + *   10 01 numstatus byte
  1812.  
  1813. + *   11 01 status byte
  1814.  
  1815. + *--------------------------------------------------------------------*/
  1816.  
  1817. +static int mega_register_mailbox(mega_host_config *megaCfg, u_long paddr)
  1818.  
  1819. +{
  1820.  
  1821. +  /* align on 16-byte boundry */
  1822.  
  1823. +  megaCfg->mbox = &megaCfg->mailbox;
  1824.  
  1825. +  megaCfg->mbox = (mega_mailbox *) ((((ulong)megaCfg->mbox) + 16)&0xfffffff0);
  1826.  
  1827. +  paddr = (paddr+16)&0xfffffff0;
  1828.  
  1829. +
  1830.  
  1831. +  /* Register mailbox area with the firmware */
  1832.  
  1833. +  if (megaCfg->flag & BOARD_QUARTZ) {
  1834.  
  1835. +  }
  1836.  
  1837. +  else {
  1838.  
  1839. +    WRITE_PORT(megaCfg->host->io_port, MBOX_PORT0, paddr         & 0xFF);
  1840.  
  1841. +    WRITE_PORT(megaCfg->host->io_port, MBOX_PORT1, (paddr >>  8) & 0xFF);
  1842.  
  1843. +    WRITE_PORT(megaCfg->host->io_port, MBOX_PORT2, (paddr >> 16) & 0xFF);
  1844.  
  1845. +    WRITE_PORT(megaCfg->host->io_port, MBOX_PORT3, (paddr >> 24) & 0xFF);
  1846.  
  1847. +    WRITE_PORT(megaCfg->host->io_port, ENABLE_MBOX_REGION, ENABLE_MBOX_BYTE);
  1848.  
  1849. +    
  1850.  
  1851. +    CLEAR_INTR(megaCfg->host->io_port);
  1852.  
  1853. +    ENABLE_INTR(megaCfg->host->io_port);
  1854.  
  1855. +  }
  1856.  
  1857. +  return 0;
  1858.  
  1859. +}
  1860.  
  1861. +
  1862.  
  1863. +/*-------------------------------------------------------------------
  1864.  
  1865. + * Issue an adapter info query to the controller
  1866.  
  1867. + *-------------------------------------------------------------------*/
  1868.  
  1869. +static int mega_i_query_adapter(mega_host_config *megaCfg)
  1870.  
  1871. +{
  1872.  
  1873. +  mega_RAIDINQ *adapterInfo;
  1874.  
  1875. +  mega_mailbox *mbox;
  1876.  
  1877. +  u_char        mboxData[16];
  1878.  
  1879. +  u_long        paddr;
  1880.  
  1881. +
  1882.  
  1883. +  /* Initialize adapter inquiry */
  1884.  
  1885. +  paddr = virt_to_bus(megaCfg->mega_buffer);
  1886.  
  1887. +  mbox  = (mega_mailbox *)mboxData;
  1888.  
  1889. +
  1890.  
  1891. +  memset((void *)megaCfg->mega_buffer, 0, sizeof(megaCfg->mega_buffer));
  1892.  
  1893. +  memset(mbox, 0, 16);
  1894.  
  1895. +
  1896.  
  1897. +  /* Initialize mailbox registers */
  1898.  
  1899. +  mbox->cmd      = MEGA_MBOXCMD_ADAPTERINQ;
  1900.  
  1901. +  mbox->xferaddr = paddr;
  1902.  
  1903. +
  1904.  
  1905. +  /* Issue a blocking command to the card */
  1906.  
  1907. +  MegaIssueCmd(megaCfg, mboxData, NULL, 0);
  1908.  
  1909. +  
  1910.  
  1911. +  /* Initialize host/local structures with Adapter info */
  1912.  
  1913. +  adapterInfo = (mega_RAIDINQ *)megaCfg->mega_buffer;
  1914.  
  1915. +  megaCfg->host->max_channel = adapterInfo->AdpInfo.ChanPresent;
  1916.  
  1917. +  megaCfg->host->max_id      = adapterInfo->AdpInfo.MaxTargPerChan;
  1918.  
  1919. +  megaCfg->numldrv           = adapterInfo->LogdrvInfo.NumLDrv;
  1920.  
  1921. +
  1922.  
  1923. +#if 0
  1924.  
  1925. +  printk("---- Logical drive info ----\n");
  1926.  
  1927. +  for(i=0; i<megaCfg->numldrv; i++) {
  1928.  
  1929. +    printk("%d: size: %ld prop: %x state: %x\n",i,
  1930.  
  1931. +       adapterInfo->LogdrvInfo.LDrvSize[i],
  1932.  
  1933. +       adapterInfo->LogdrvInfo.LDrvProp[i],
  1934.  
  1935. +       adapterInfo->LogdrvInfo.LDrvState[i]);
  1936.  
  1937. +  }
  1938.  
  1939. +  printk("---- Physical drive info ----\n");
  1940.  
  1941. +  for(i=0; i<MAX_PHYSICAL_DRIVES; i++) {
  1942.  
  1943. +    if (i && !(i % 8)) printk("\n");
  1944.  
  1945. +    printk("%d: %x   ", i, adapterInfo->PhysdrvInfo.PDrvState[i]);
  1946.  
  1947. +  }
  1948.  
  1949. +  printk("\n");
  1950.  
  1951. +#endif
  1952.  
  1953. +
  1954.  
  1955. +  megaCfg->max_cmds = adapterInfo->AdpInfo.MaxConcCmds;
  1956.  
  1957. +
  1958.  
  1959. +#ifdef HP            /* use HP firmware and bios version encoding */
  1960.  
  1961. +      sprintf(megaCfg->fwVer,"%c%d%d.%d%d",
  1962.  
  1963. +          adapterInfo->AdpInfo.FwVer[2],
  1964.  
  1965. +          adapterInfo->AdpInfo.FwVer[1] >> 8,
  1966.  
  1967. +          adapterInfo->AdpInfo.FwVer[1] & 0x0f,
  1968.  
  1969. +          adapterInfo->AdpInfo.FwVer[2] >> 8,
  1970.  
  1971. +          adapterInfo->AdpInfo.FwVer[2] & 0x0f);
  1972.  
  1973. +      sprintf(megaCfg->biosVer,"%c%d%d.%d%d",
  1974.  
  1975. +          adapterInfo->AdpInfo.BiosVer[2],
  1976.  
  1977. +          adapterInfo->AdpInfo.BiosVer[1] >> 8,
  1978.  
  1979. +          adapterInfo->AdpInfo.BiosVer[1] & 0x0f,
  1980.  
  1981. +          adapterInfo->AdpInfo.BiosVer[2] >> 8,
  1982.  
  1983. +          adapterInfo->AdpInfo.BiosVer[2] & 0x0f);
  1984.  
  1985. +#else
  1986.  
  1987. +      memcpy(megaCfg->fwVer, adapterInfo->AdpInfo.FwVer, 4);
  1988.  
  1989. +      megaCfg->fwVer[4] = 0;
  1990.  
  1991. +
  1992.  
  1993. +      memcpy(megaCfg->biosVer, adapterInfo->AdpInfo.BiosVer, 4);
  1994.  
  1995. +      megaCfg->biosVer[4] = 0;
  1996.  
  1997. +#endif
  1998.  
  1999. +
  2000.  
  2001. +  printk("megaraid: [%s:%s] detected %d logical drives" CRLFSTR,
  2002.  
  2003. +     megaCfg->fwVer,
  2004.  
  2005. +     megaCfg->biosVer,
  2006.  
  2007. +     megaCfg->numldrv);
  2008.  
  2009. +  return 0;
  2010.  
  2011. +}
  2012.  
  2013. +
  2014.  
  2015. +/*-------------------------------------------------------------------------
  2016.  
  2017. + *
  2018.  
  2019. + *                      Driver interface functions
  2020.  
  2021. + *
  2022.  
  2023. + *-------------------------------------------------------------------------*/
  2024.  
  2025. +
  2026.  
  2027. +/*----------------------------------------------------------
  2028.  
  2029. + * Returns data to be displayed in /proc/scsi/megaraid/X
  2030.  
  2031. + *----------------------------------------------------------*/
  2032.  
  2033. +int megaraid_proc_info(char *buffer, char **start, off_t offset,
  2034.  
  2035. +               int length, int inode, int inout)
  2036.  
  2037. +{
  2038.  
  2039. +  *start = buffer;
  2040.  
  2041. +  return 0;
  2042.  
  2043. +}
  2044.  
  2045. +
  2046.  
  2047. +int findCard(Scsi_Host_Template *pHostTmpl, 
  2048.  
  2049. +         u_short pciVendor, u_short pciDev,
  2050.  
  2051. +         long flag)
  2052.  
  2053. +{
  2054.  
  2055. +  mega_host_config *megaCfg;
  2056.  
  2057. +  struct Scsi_Host *host;
  2058.  
  2059. +  u_char            pciBus, pciDevFun, megaIrq;
  2060.  
  2061. +  u_long            megaBase;
  2062.  
  2063. +  u_short           pciIdx;
  2064.  
  2065. +
  2066.  
  2067. +  pciIdx = 0;
  2068.  
  2069. +  while(!pcibios_find_device(pciVendor, pciDev, pciIdx,&pciBus,&pciDevFun)) {
  2070.  
  2071. +    printk("megaraid: found 0x%4.04x:0x%4.04x:idx %d:bus %d:slot %d:fun %d\n",
  2072.  
  2073. +       pciVendor, 
  2074.  
  2075. +       pciDev, 
  2076.  
  2077. +       pciIdx, pciBus, 
  2078.  
  2079. +       PCI_SLOT(pciDevFun), 
  2080.  
  2081. +       PCI_FUNC(pciDevFun));
  2082.  
  2083. +    
  2084.  
  2085. +    /* Read the base port and IRQ from PCI */
  2086.  
  2087. +    pcibios_read_config_dword(pciBus, pciDevFun,
  2088.  
  2089. +                 PCI_BASE_ADDRESS_0,
  2090.  
  2091. +                 (u_int *)&megaBase);
  2092.  
  2093. +    pcibios_read_config_byte(pciBus, pciDevFun,                   
  2094.  
  2095. +                 PCI_INTERRUPT_LINE,
  2096.  
  2097. +                 &megaIrq);
  2098.  
  2099. +    pciIdx++;
  2100.  
  2101. +
  2102.  
  2103. +    if (flag & BOARD_QUARTZ) {
  2104.  
  2105. +      megaBase &= PCI_BASE_ADDRESS_MEM_MASK;
  2106.  
  2107. +      megaBase = (long) ioremap(megaBase,128);
  2108.  
  2109. +    }
  2110.  
  2111. +    else {
  2112.  
  2113. +      megaBase &= PCI_BASE_ADDRESS_IO_MASK;
  2114.  
  2115. +      megaBase += 0x10;
  2116.  
  2117. +    }
  2118.  
  2119. +
  2120.  
  2121. +    /* Initialize SCSI Host structure */
  2122.  
  2123. +    host    = scsi_register(pHostTmpl, sizeof(mega_host_config));
  2124.  
  2125. +    megaCfg = (mega_host_config *)host->hostdata;
  2126.  
  2127. +    memset(megaCfg, 0, sizeof(mega_host_config));
  2128.  
  2129. +
  2130.  
  2131. +    printk(" scsi%d: Found a MegaRAID controller at 0x%x, IRQ: %d" CRLFSTR, 
  2132.  
  2133. +       host->host_no, (u_int)megaBase, megaIrq);
  2134.  
  2135. +    
  2136.  
  2137. +    /* Copy resource info into structure */
  2138.  
  2139. +    megaCfg->flag            = flag;
  2140.  
  2141. +    megaCfg->host            = host;
  2142.  
  2143. +    megaCfg->base            = megaBase;
  2144.  
  2145. +    megaCfg->host->irq       = megaIrq;
  2146.  
  2147. +    megaCfg->host->io_port   = megaBase;
  2148.  
  2149. +    megaCfg->host->n_io_port = 16;
  2150.  
  2151. +    megaCfg->host->unique_id = (pciBus << 8) | pciDevFun;
  2152.  
  2153. +    megaCtlrs[numCtlrs++]    = megaCfg;
  2154.  
  2155. +
  2156.  
  2157. +    if (flag != BOARD_QUARTZ) {
  2158.  
  2159. +      /* Request our IO Range */
  2160.  
  2161. +      if (check_region(megaBase, 16)) {
  2162.  
  2163. +    printk(KERN_WARNING "megaraid: Couldn't register I/O range!" CRLFSTR);
  2164.  
  2165. +    scsi_unregister(host);
  2166.  
  2167. +    continue;
  2168.  
  2169. +      }
  2170.  
  2171. +      request_region(megaBase, 16, "megaraid");
  2172.  
  2173. +    }
  2174.  
  2175. +
  2176.  
  2177. +    /* Request our IRQ */
  2178.  
  2179. +    if (request_irq(megaIrq, megaraid_isr, SA_INTERRUPT|SA_SHIRQ, 
  2180.  
  2181. +            "megaraid", megaCfg)) {
  2182.  
  2183. +      printk(KERN_WARNING "megaraid: Couldn't register IRQ %d!" CRLFSTR,
  2184.  
  2185. +         megaIrq);
  2186.  
  2187. +      scsi_unregister(host);
  2188.  
  2189. +      continue;
  2190.  
  2191. +    }
  2192.  
  2193. +
  2194.  
  2195. +    mega_register_mailbox(megaCfg, virt_to_bus((void*)&megaCfg->mailbox));
  2196.  
  2197. +    mega_i_query_adapter(megaCfg);
  2198.  
  2199. +
  2200.  
  2201. +    /* Initialize SCBs */
  2202.  
  2203. +    initSCB(megaCfg);
  2204.  
  2205. +
  2206.  
  2207. +  }
  2208.  
  2209. +  return pciIdx;
  2210.  
  2211. +}
  2212.  
  2213. +
  2214.  
  2215. +/*---------------------------------------------------------
  2216.  
  2217. + * Detects if a megaraid controller exists in this system
  2218.  
  2219. + *---------------------------------------------------------*/
  2220.  
  2221. +int megaraid_detect(Scsi_Host_Template *pHostTmpl)
  2222.  
  2223. +{
  2224.  
  2225. +  int count = 0;
  2226.  
  2227. +
  2228.  
  2229. +  pHostTmpl->proc_dir = &proc_scsi_megaraid;
  2230.  
  2231. +
  2232.  
  2233. +  if (!pcibios_present()) 
  2234.  
  2235. +    {
  2236.  
  2237. +      printk("megaraid: PCI bios not present." CRLFSTR);
  2238.  
  2239. +      return 0;
  2240.  
  2241. +    }
  2242.  
  2243. +
  2244.  
  2245. +  count += findCard(pHostTmpl, 0x101E, 0x9010, 0);
  2246.  
  2247. +  count += findCard(pHostTmpl, 0x101E, 0x9060, 0);
  2248.  
  2249. +  count += findCard(pHostTmpl, 0x8086, 0x1960, BOARD_QUARTZ);
  2250.  
  2251. +
  2252.  
  2253. +  return count;
  2254.  
  2255. +}
  2256.  
  2257. +
  2258.  
  2259. +/*---------------------------------------------------------------------
  2260.  
  2261. + * Release the controller's resources
  2262.  
  2263. + *---------------------------------------------------------------------*/
  2264.  
  2265. +int megaraid_release(struct Scsi_Host *pSHost)
  2266.  
  2267. +{
  2268.  
  2269. +  mega_host_config *megaCfg;
  2270.  
  2271. +  mega_mailbox         *mbox;
  2272.  
  2273. +  u_char                mboxData[16];
  2274.  
  2275. +
  2276.  
  2277. +  megaCfg = (mega_host_config*)pSHost->hostdata;
  2278.  
  2279. +  mbox    = (mega_mailbox *)mboxData;
  2280.  
  2281. +
  2282.  
  2283. +  /* Flush cache to disk */
  2284.  
  2285. +  memset(mbox, 0, 16);
  2286.  
  2287. +  mboxData[0] = 0xA;
  2288.  
  2289. +
  2290.  
  2291. +  /* Issue a blocking (interrupts disabled) command to the card */
  2292.  
  2293. +  MegaIssueCmd(megaCfg, mboxData, NULL, 0);
  2294.  
  2295. +
  2296.  
  2297. +  schedule();
  2298.  
  2299. +
  2300.  
  2301. +  /* Free our resources */
  2302.  
  2303. +  if (megaCfg->flag & BOARD_QUARTZ) {
  2304.  
  2305. +      iounmap((void *)megaCfg->base);
  2306.  
  2307. +  } else {
  2308.  
  2309. +      release_region(megaCfg->host->io_port, 16);
  2310.  
  2311. +  }
  2312.  
  2313. +  free_irq(megaCfg->host->irq, megaCfg); /* Must be freed first, otherwise
  2314.  
  2315. +                                            extra interrupt is generated */
  2316.  
  2317. +  scsi_unregister(pSHost);
  2318.  
  2319. +
  2320.  
  2321. +  return 0;
  2322.  
  2323. +}
  2324.  
  2325. +
  2326.  
  2327. +/*----------------------------------------------
  2328.  
  2329. + * Get information about the card/driver 
  2330.  
  2331. + *----------------------------------------------*/
  2332.  
  2333. +const char *megaraid_info(struct Scsi_Host *pSHost)
  2334.  
  2335. +{
  2336.  
  2337. +  static char           buffer[512];
  2338.  
  2339. +  mega_host_config  *megaCfg;
  2340.  
  2341. +  mega_RAIDINQ          *adapterInfo;
  2342.  
  2343. +
  2344.  
  2345. +  megaCfg     = (mega_host_config *)pSHost->hostdata;
  2346.  
  2347. +  adapterInfo = (mega_RAIDINQ *)megaCfg->mega_buffer;
  2348.  
  2349. +
  2350.  
  2351. +  sprintf(buffer, "AMI MegaRAID %s %d commands %d targs %d chans",
  2352.  
  2353. +      megaCfg->fwVer,
  2354.  
  2355. +      adapterInfo->AdpInfo.MaxConcCmds,
  2356.  
  2357. +      megaCfg->host->max_id,
  2358.  
  2359. +      megaCfg->host->max_channel);
  2360.  
  2361. +  return buffer;
  2362.  
  2363. +}
  2364.  
  2365. +
  2366.  
  2367. +/*-----------------------------------------------------------------
  2368.  
  2369. + * Perform a SCSI command
  2370.  
  2371. + * Mailbox area:
  2372.  
  2373. + *   00 01 command
  2374.  
  2375. + *   01 01 command id
  2376.  
  2377. + *   02 02 # of sectors
  2378.  
  2379. + *   04 04 logical bus address
  2380.  
  2381. + *   08 04 physical buffer address
  2382.  
  2383. + *   0C 01 logical drive #
  2384.  
  2385. + *   0D 01 length of scatter/gather list
  2386.  
  2387. + *   0E 01 reserved
  2388.  
  2389. + *   0F 01 mailbox busy
  2390.  
  2391. + *   10 01 numstatus byte
  2392.  
  2393. + *   11 01 status byte 
  2394.  
  2395. + *-----------------------------------------------------------------*/
  2396.  
  2397. +int megaraid_queue(Scsi_Cmnd *SCpnt, void (*pktComp)(Scsi_Cmnd *))
  2398.  
  2399. +{
  2400.  
  2401. +  mega_host_config *megaCfg;
  2402.  
  2403. +  mega_scb         *pScb;
  2404.  
  2405. +
  2406.  
  2407. +  megaCfg = (mega_host_config *)SCpnt->host->hostdata;
  2408.  
  2409. +
  2410.  
  2411. +  if (!(megaCfg->flag & (1L << SCpnt->channel))) {
  2412.  
  2413. +    printk("scsi%d: scanning channel %c for devices.\n",
  2414.  
  2415. +       megaCfg->host->host_no,
  2416.  
  2417. +       SCpnt->channel + 'A');
  2418.  
  2419. +    megaCfg->flag |= (1L << SCpnt->channel);
  2420.  
  2421. +  }
  2422.  
  2423. +
  2424.  
  2425. +  SCpnt->scsi_done = pktComp;
  2426.  
  2427. +
  2428.  
  2429. +  /* Allocate and build a SCB request */
  2430.  
  2431. +  if ((pScb = mega_build_cmd(megaCfg, SCpnt)) != NULL) {
  2432.  
  2433. +    /* Add SCB to the head of the pending queue */
  2434.  
  2435. +    ENQUEUE(pScb, mega_scb, qPending, next);
  2436.  
  2437. +
  2438.  
  2439. +    /* Issue the command to the card */
  2440.  
  2441. +      mega_runque(NULL);
  2442.  
  2443. +  }
  2444.  
  2445. +
  2446.  
  2447. +#if 0
  2448.  
  2449. +  SCpnt->result = (DID_BAD_TARGET << 16);
  2450.  
  2451. +  SCpnt->scsi_done = pktComp;
  2452.  
  2453. +  callDone(SCpnt);
  2454.  
  2455. +#endif
  2456.  
  2457. +  return 0;
  2458.  
  2459. +}
  2460.  
  2461. +
  2462.  
  2463. +/*----------------------------------------------------------------------
  2464.  
  2465. + * Issue a blocking command to the controller
  2466.  
  2467. + *----------------------------------------------------------------------*/
  2468.  
  2469. +volatile static int internal_done_flag    = 0;
  2470.  
  2471. +volatile static int internal_done_errcode = 0;
  2472.  
  2473. +
  2474.  
  2475. +static void internal_done(Scsi_Cmnd *SCpnt)
  2476.  
  2477. +{
  2478.  
  2479. +  internal_done_errcode = SCpnt->result;
  2480.  
  2481. +  internal_done_flag++;
  2482.  
  2483. +}
  2484.  
  2485. +
  2486.  
  2487. +int megaraid_command(Scsi_Cmnd *SCpnt)
  2488.  
  2489. +{
  2490.  
  2491. +  internal_done_flag = 0;
  2492.  
  2493. +
  2494.  
  2495. +  /* Queue command, and wait until it has completed */
  2496.  
  2497. +  megaraid_queue(SCpnt, internal_done);
  2498.  
  2499. +
  2500.  
  2501. +  while(!internal_done_flag)
  2502.  
  2503. +    barrier();
  2504.  
  2505. +
  2506.  
  2507. +  return internal_done_errcode;
  2508.  
  2509. +}
  2510.  
  2511. +
  2512.  
  2513. +/*---------------------------------------------------------------------
  2514.  
  2515. + * Abort a previous SCSI request
  2516.  
  2517. + *---------------------------------------------------------------------*/
  2518.  
  2519. +int megaraid_abort(Scsi_Cmnd *SCpnt)
  2520.  
  2521. +{
  2522.  
  2523. +  mega_host_config *megaCfg;
  2524.  
  2525. +  int       idx;
  2526.  
  2527. +  long      flags;
  2528.  
  2529. +
  2530.  
  2531. +  save_flags(flags);
  2532.  
  2533. +  cli();
  2534.  
  2535. +
  2536.  
  2537. +  megaCfg = (mega_host_config *)SCpnt->host->hostdata;
  2538.  
  2539. +
  2540.  
  2541. +  TRACE(("ABORT!!! %.08lx %.02x <%d.%d.%d>\n",
  2542.  
  2543. +     SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target, 
  2544.  
  2545. +     SCpnt->lun));
  2546.  
  2547. +  /*
  2548.  
  2549. +   * Walk list of SCBs for any that are still outstanding
  2550.  
  2551. +   */
  2552.  
  2553. +  for(idx=0; idx<megaCfg->max_cmds; idx++) {
  2554.  
  2555. +    if (megaCfg->scbList[idx].idx >= 0) {
  2556.  
  2557. +      if (megaCfg->scbList[idx].SCpnt == SCpnt) {
  2558.  
  2559. +    freeSCB(&megaCfg->scbList[idx]);
  2560.  
  2561. +
  2562.  
  2563. +    SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY<<24);
  2564.  
  2565. +    callDone(SCpnt);
  2566.  
  2567. +      }
  2568.  
  2569. +    }
  2570.  
  2571. +  }
  2572.  
  2573. +  restore_flags(flags);
  2574.  
  2575. +  return SCSI_ABORT_SNOOZE;
  2576.  
  2577. +}
  2578.  
  2579. +
  2580.  
  2581. +/*---------------------------------------------------------------------
  2582.  
  2583. + * Reset a previous SCSI request
  2584.  
  2585. + *---------------------------------------------------------------------*/
  2586.  
  2587. +int megaraid_reset(Scsi_Cmnd *SCpnt, unsigned int rstflags)
  2588.  
  2589. +{
  2590.  
  2591. +  mega_host_config *megaCfg;
  2592.  
  2593. +  int       idx;
  2594.  
  2595. +  long      flags;
  2596.  
  2597. +
  2598.  
  2599. +  save_flags(flags);
  2600.  
  2601. +  cli();
  2602.  
  2603. +
  2604.  
  2605. +  megaCfg = (mega_host_config *)SCpnt->host->hostdata;
  2606.  
  2607. +
  2608.  
  2609. +  TRACE(("RESET: %.08lx %.02x <%d.%d.%d>\n",
  2610.  
  2611. +     SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target, 
  2612.  
  2613. +     SCpnt->lun));
  2614.  
  2615. +
  2616.  
  2617. +  /*
  2618.  
  2619. +   * Walk list of SCBs for any that are still outstanding
  2620.  
  2621. +   */
  2622.  
  2623. +  for(idx=0; idx<megaCfg->max_cmds; idx++) {
  2624.  
  2625. +    if (megaCfg->scbList[idx].idx >= 0) {
  2626.  
  2627. +      SCpnt = megaCfg->scbList[idx].SCpnt;
  2628.  
  2629. +      freeSCB(&megaCfg->scbList[idx]);
  2630.  
  2631. +      SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY<<24);
  2632.  
  2633. +      callDone(SCpnt);
  2634.  
  2635. +    }
  2636.  
  2637. +  }
  2638.  
  2639. +  restore_flags(flags);
  2640.  
  2641. +  return SCSI_RESET_PUNT;
  2642.  
  2643. +} 
  2644.  
  2645. +
  2646.  
  2647. +/*-------------------------------------------------------------
  2648.  
  2649. + * Return the disk geometry for a particular disk
  2650.  
  2651. + * Input:
  2652.  
  2653. + *   Disk *disk - Disk geometry
  2654.  
  2655. + *   kdev_t dev - Device node
  2656.  
  2657. + *   int *geom  - Returns geometry fields
  2658.  
  2659. + *     geom[0] = heads
  2660.  
  2661. + *     geom[1] = sectors
  2662.  
  2663. + *     geom[2] = cylinders
  2664.  
  2665. + *-------------------------------------------------------------*/
  2666.  
  2667. +int megaraid_biosparam(Disk *disk, kdev_t dev, int *geom)
  2668.  
  2669. +{
  2670.  
  2671. +  int                   heads, sectors, cylinders;
  2672.  
  2673. +  mega_host_config *megaCfg;
  2674.  
  2675. +
  2676.  
  2677. +  /* Get pointer to host config structure */
  2678.  
  2679. +  megaCfg = (mega_host_config *)disk->device->host->hostdata;
  2680.  
  2681. +
  2682.  
  2683. +  /* Default heads (64) & sectors (32) */
  2684.  
  2685. +  heads     = 64;
  2686.  
  2687. +  sectors   = 32;
  2688.  
  2689. +  cylinders = disk->capacity / (heads * sectors);
  2690.  
  2691. +
  2692.  
  2693. +  /* Handle extended translation size for logical drives > 1Gb */
  2694.  
  2695. +  if (disk->capacity >= 0x200000) {
  2696.  
  2697. +    heads     = 255;
  2698.  
  2699. +    sectors   = 63;
  2700.  
  2701. +    cylinders = disk->capacity / (heads * sectors);
  2702.  
  2703. +  }
  2704.  
  2705. +
  2706.  
  2707. +  /* return result */
  2708.  
  2709. +  geom[0] = heads;
  2710.  
  2711. +  geom[1] = sectors;
  2712.  
  2713. +  geom[2] = cylinders;
  2714.  
  2715. +
  2716.  
  2717. +  return 0;
  2718.  
  2719. +}
  2720.  
  2721. +
  2722.  
  2723. +#ifdef MODULE
  2724.  
  2725. +Scsi_Host_Template driver_template = MEGARAID;
  2726.  
  2727. +
  2728.  
  2729. +#include "scsi_module.c"
  2730.  
  2731. +#endif
  2732.  
  2733. diff -urN linux/drivers/scsi/megaraid.h linux-2.0.32-megaraid/drivers/scsi/megaraid.h
  2734.  
  2735. --- linux/drivers/scsi/megaraid.h    Wed Dec 31 19:00:00 1969
  2736.  
  2737. +++ linux-2.0.32-megaraid/drivers/scsi/megaraid.h    Mon Aug 17 17:38:49 1998
  2738.  
  2739. @@ -0,0 +1,291 @@
  2740.  
  2741. +#ifndef __MEGARAID_H__
  2742.  
  2743. +#define __MEGARAID_H__
  2744.  
  2745. +
  2746.  
  2747. +#define IN_ISR                  0x80000000L
  2748.  
  2749. +#define NO_INTR                 0x40000000L
  2750.  
  2751. +#define IN_TIMEOUT              0x20000000L
  2752.  
  2753. +#define PENDING                 0x10000000L
  2754.  
  2755. +#define BOARD_QUARTZ            0x08000000L
  2756.  
  2757. +
  2758.  
  2759. +#define SCB_ACTIVE 0x1
  2760.  
  2761. +#define SCB_WAITQ  0x2
  2762.  
  2763. +#define SCB_ISSUED 0x4
  2764.  
  2765. +
  2766.  
  2767. +#define SCB_FREE                -1
  2768.  
  2769. +#define SCB_RESET               -2
  2770.  
  2771. +#define SCB_ABORT               -3
  2772.  
  2773. +#define SCB_LOCKED              -4
  2774.  
  2775. +
  2776.  
  2777. +#define MEGA_CMD_TIMEOUT        10
  2778.  
  2779. +
  2780.  
  2781. +#define MAX_SGLIST              20
  2782.  
  2783. +#define MAX_COMMANDS            254
  2784.  
  2785. +
  2786.  
  2787. +#define MAX_LOGICAL_DRIVES      8
  2788.  
  2789. +#define MAX_CHANNEL             5
  2790.  
  2791. +#define MAX_TARGET              15
  2792.  
  2793. +#define MAX_PHYSICAL_DRIVES     MAX_CHANNEL*MAX_TARGET
  2794.  
  2795. +
  2796.  
  2797. +#define INQUIRY_DATA_SIZE       0x24
  2798.  
  2799. +#define MAX_CDB_LEN             0x0A
  2800.  
  2801. +#define MAX_REQ_SENSE_LEN       0x20
  2802.  
  2803. +
  2804.  
  2805. +#define INTR_VALID              0x40
  2806.  
  2807. +
  2808.  
  2809. +/* Mailbox commands */
  2810.  
  2811. +#define MEGA_MBOXCMD_LREAD      0x01
  2812.  
  2813. +#define MEGA_MBOXCMD_LWRITE     0x02
  2814.  
  2815. +#define MEGA_MBOXCMD_PASSTHRU   0x03
  2816.  
  2817. +#define MEGA_MBOXCMD_ADAPTERINQ 0x05
  2818.  
  2819. +
  2820.  
  2821. +/* Offsets into Mailbox */
  2822.  
  2823. +#define COMMAND_PORT       0x00
  2824.  
  2825. +#define COMMAND_ID_PORT    0x01
  2826.  
  2827. +#define SG_LIST_PORT0      0x08
  2828.  
  2829. +#define SG_LIST_PORT1      0x09
  2830.  
  2831. +#define SG_LIST_PORT2      0x0a
  2832.  
  2833. +#define SG_LIST_PORT3      0x0b
  2834.  
  2835. +#define SG_ELEMENT_PORT    0x0d
  2836.  
  2837. +#define NO_FIRED_PORT      0x0f
  2838.  
  2839. +
  2840.  
  2841. +/* I/O Port offsets */
  2842.  
  2843. +#define I_CMD_PORT         0x00
  2844.  
  2845. +#define I_ACK_PORT         0x00
  2846.  
  2847. +#define I_TOGGLE_PORT      0x01
  2848.  
  2849. +#define INTR_PORT          0x0a
  2850.  
  2851. +
  2852.  
  2853. +#define MAILBOX_SIZE       70
  2854.  
  2855. +#define MBOX_BUSY_PORT     0x00
  2856.  
  2857. +#define MBOX_PORT0         0x04
  2858.  
  2859. +#define MBOX_PORT1         0x05
  2860.  
  2861. +#define MBOX_PORT2         0x06
  2862.  
  2863. +#define MBOX_PORT3         0x07
  2864.  
  2865. +#define ENABLE_MBOX_REGION 0x0B
  2866.  
  2867. +
  2868.  
  2869. +/* I/O Port Values */
  2870.  
  2871. +#define ISSUE_BYTE         0x10
  2872.  
  2873. +#define ACK_BYTE           0x08
  2874.  
  2875. +#define ENABLE_INTR_BYTE   0xc0
  2876.  
  2877. +#define DISABLE_INTR_BYTE  0x00
  2878.  
  2879. +#define VALID_INTR_BYTE    0x40
  2880.  
  2881. +#define MBOX_BUSY_BYTE     0x10
  2882.  
  2883. +#define ENABLE_MBOX_BYTE   0x00
  2884.  
  2885. +
  2886.  
  2887. +/* Setup some port macros here */
  2888.  
  2889. +#define WRITE_MAILBOX(base,offset,value)   *(base+offset)=value
  2890.  
  2891. +#define READ_MAILBOX(base,offset)          *(base+offset)
  2892.  
  2893. +
  2894.  
  2895. +#define WRITE_PORT(base,offset,value)      outb_p(value,base+offset)
  2896.  
  2897. +#define READ_PORT(base,offset)             inb_p(base+offset)
  2898.  
  2899. +
  2900.  
  2901. +#define ISSUE_COMMAND(base)   WRITE_PORT(base,I_CMD_PORT,ISSUE_BYTE)
  2902.  
  2903. +#define CLEAR_INTR(base)      WRITE_PORT(base,I_ACK_PORT,ACK_BYTE)
  2904.  
  2905. +#define ENABLE_INTR(base)     WRITE_PORT(base,I_TOGGLE_PORT,ENABLE_INTR_BYTE)
  2906.  
  2907. +#define DISABLE_INTR(base)    WRITE_PORT(base,I_TOGGLE_PORT,DISABLE_INTR_BYTE)
  2908.  
  2909. +
  2910.  
  2911. +/* Define AMI's PCI codes */
  2912.  
  2913. +#undef PCI_VENDOR_ID_AMI
  2914.  
  2915. +#undef PCI_DEVICE_ID_AMI_MEGARAID
  2916.  
  2917. +
  2918.  
  2919. +#ifndef PCI_VENDOR_ID_AMI
  2920.  
  2921. +#define PCI_VENDOR_ID_AMI          0x101E
  2922.  
  2923. +#define PCI_DEVICE_ID_AMI_MEGARAID 0x9010
  2924.  
  2925. +#endif
  2926.  
  2927. +
  2928.  
  2929. +#define PCI_CONF_BASE_ADDR_OFFSET  0x10
  2930.  
  2931. +#define PCI_CONF_IRQ_OFFSET        0x3c
  2932.  
  2933. +
  2934.  
  2935. +#if LINUX_VERSION_CODE < 0x20100
  2936.  
  2937. +#define MEGARAID \
  2938.  
  2939. +  { NULL,                               /* Next                      */\
  2940.  
  2941. +    NULL,                               /* Usage Count Pointer       */\
  2942.  
  2943. +    NULL,                               /* /proc Directory Entry     */\
  2944.  
  2945. +    megaraid_proc_info,                 /* /proc Info Function       */\
  2946.  
  2947. +    "MegaRAID",                         /* Driver Name               */\
  2948.  
  2949. +    megaraid_detect,                    /* Detect Host Adapter       */\
  2950.  
  2951. +    megaraid_release,                   /* Release Host Adapter      */\
  2952.  
  2953. +    megaraid_info,                      /* Driver Info Function      */\
  2954.  
  2955. +    megaraid_command,                   /* Command Function          */\
  2956.  
  2957. +    megaraid_queue,                     /* Queue Command Function    */\
  2958.  
  2959. +    megaraid_abort,                     /* Abort Command Function    */\
  2960.  
  2961. +    megaraid_reset,                     /* Reset Command Function    */\
  2962.  
  2963. +    NULL,                               /* Slave Attach Function     */\
  2964.  
  2965. +    megaraid_biosparam,                 /* Disk BIOS Parameters      */\
  2966.  
  2967. +    1,                                  /* # of cmds that can be\
  2968.  
  2969. +                                           outstanding at any time */\
  2970.  
  2971. +    7,                                  /* HBA Target ID             */\
  2972.  
  2973. +    MAX_SGLIST,                         /* Scatter/Gather Table Size */\
  2974.  
  2975. +    1,                                  /* SCSI Commands per LUN     */\
  2976.  
  2977. +    0,                                  /* Present                   */\
  2978.  
  2979. +    0,                                  /* Default Unchecked ISA DMA */\
  2980.  
  2981. +    ENABLE_CLUSTERING }                 /* Enable Clustering         */
  2982.  
  2983. +#else
  2984.  
  2985. +#define MEGARAID \
  2986.  
  2987. +  { NULL,                               /* Next                      */\
  2988.  
  2989. +    NULL,                               /* Module                    */\
  2990.  
  2991. +    NULL,                               /* /proc Directory Entry     */\
  2992.  
  2993. +    NULL,                               /* /proc/fs entry            */\
  2994.  
  2995. +    "MegaRAID",                         /* Driver Name               */\
  2996.  
  2997. +    megaraid_detect,                    /* Detect Host Adapter       */\
  2998.  
  2999. +    megaraid_release,                   /* Release Host Adapter      */\
  3000.  
  3001. +    megaraid_info,                      /* Driver Info Function      */\
  3002.  
  3003. +    NULL,                               /* Ioctl interface           */\
  3004.  
  3005. +    megaraid_command,                   /* Command Function          */\
  3006.  
  3007. +    megaraid_queue,                     /* Queue Command Function    */\
  3008.  
  3009. +    NULL,\
  3010.  
  3011. +    NULL,\
  3012.  
  3013. +    NULL,\
  3014.  
  3015. +    NULL,\
  3016.  
  3017. +    NULL,\
  3018.  
  3019. +    megaraid_abort,                     /* Abort Command Function    */\
  3020.  
  3021. +    megaraid_reset,                     /* Reset Command Function    */\
  3022.  
  3023. +    NULL,                               /* Slave Attach Function     */\
  3024.  
  3025. +    megaraid_biosparam,                 /* Disk BIOS Parameters      */\
  3026.  
  3027. +    255,                                /* Can Queue                 */\
  3028.  
  3029. +    7,                                  /* HBA Target ID             */\
  3030.  
  3031. +    MAX_SGLIST,                         /* Scatter/Gather Table Size */\
  3032.  
  3033. +    1,                                  /* SCSI Commands per LUN     */\
  3034.  
  3035. +    0,                                  /* Present                   */\
  3036.  
  3037. +    0,                                  /* Default Unchecked ISA DMA */\
  3038.  
  3039. +    ENABLE_CLUSTERING }                 /* Enable Clustering         */
  3040.  
  3041. +#endif
  3042.  
  3043. +
  3044.  
  3045. +
  3046.  
  3047. +/* Structures */
  3048.  
  3049. +typedef struct _mega_ADP_INFO
  3050.  
  3051. +{
  3052.  
  3053. +  u_char    MaxConcCmds;
  3054.  
  3055. +  u_char    RbldRate;
  3056.  
  3057. +  u_char    MaxTargPerChan;
  3058.  
  3059. +  u_char    ChanPresent;
  3060.  
  3061. +  u_char    FwVer[4];
  3062.  
  3063. +  u_short   AgeOfFlash;
  3064.  
  3065. +  u_char    ChipSet;
  3066.  
  3067. +  u_char    DRAMSize;
  3068.  
  3069. +  u_char    CacheFlushInterval;
  3070.  
  3071. +  u_char    BiosVer[4];
  3072.  
  3073. +  u_char    resvd[7];
  3074.  
  3075. +} mega_ADP_INFO;
  3076.  
  3077. +
  3078.  
  3079. +typedef struct _mega_LDRV_INFO
  3080.  
  3081. +{
  3082.  
  3083. +  u_char   NumLDrv;
  3084.  
  3085. +  u_char   resvd[3];
  3086.  
  3087. +  u_long   LDrvSize[MAX_LOGICAL_DRIVES];
  3088.  
  3089. +  u_char   LDrvProp[MAX_LOGICAL_DRIVES];
  3090.  
  3091. +  u_char   LDrvState[MAX_LOGICAL_DRIVES];
  3092.  
  3093. +} mega_LDRV_INFO;
  3094.  
  3095. +
  3096.  
  3097. +typedef struct _mega_PDRV_INFO
  3098.  
  3099. +{
  3100.  
  3101. +  u_char   PDrvState[MAX_PHYSICAL_DRIVES];
  3102.  
  3103. +  u_char   resvd;
  3104.  
  3105. +} mega_PDRV_INFO;
  3106.  
  3107. +
  3108.  
  3109. +// RAID inquiry: Mailbox command 0x5
  3110.  
  3111. +typedef struct _mega_RAIDINQ
  3112.  
  3113. +{
  3114.  
  3115. +  mega_ADP_INFO    AdpInfo;
  3116.  
  3117. +  mega_LDRV_INFO   LogdrvInfo;
  3118.  
  3119. +  mega_PDRV_INFO   PhysdrvInfo;
  3120.  
  3121. +} mega_RAIDINQ;
  3122.  
  3123. +
  3124.  
  3125. +// Passthrough command: Mailbox command 0x3
  3126.  
  3127. +typedef struct mega_passthru
  3128.  
  3129. +{
  3130.  
  3131. +  u_char            timeout:3;              /* 0=6sec/1=60sec/2=10min/3=3hrs */
  3132.  
  3133. +  u_char            ars:1;
  3134.  
  3135. +  u_char            reserved:3;
  3136.  
  3137. +  u_char            islogical:1;
  3138.  
  3139. +  u_char            logdrv;                 /* if islogical == 1 */
  3140.  
  3141. +  u_char            channel;                /* if islogical == 0 */
  3142.  
  3143. +  u_char            target;                 /* if islogical == 0 */
  3144.  
  3145. +  u_char            queuetag;               /* unused */
  3146.  
  3147. +  u_char            queueaction;            /* unused */
  3148.  
  3149. +  u_char            cdb[MAX_CDB_LEN];
  3150.  
  3151. +  u_char            cdblen;
  3152.  
  3153. +  u_char            reqsenselen;
  3154.  
  3155. +  u_char            reqsensearea[MAX_REQ_SENSE_LEN];
  3156.  
  3157. +  u_char            numsgelements;
  3158.  
  3159. +  u_char            scsistatus;
  3160.  
  3161. +  u_long            dataxferaddr;
  3162.  
  3163. +  u_long            dataxferlen;
  3164.  
  3165. +} mega_passthru;
  3166.  
  3167. +
  3168.  
  3169. +typedef struct _mega_mailbox
  3170.  
  3171. +{
  3172.  
  3173. +  /* 0x0 */ u_char    cmd;
  3174.  
  3175. +  /* 0x1 */ u_char    cmdid;
  3176.  
  3177. +  /* 0x2 */ u_short   numsectors;
  3178.  
  3179. +  /* 0x4 */ u_long    lba;
  3180.  
  3181. +  /* 0x8 */ u_long    xferaddr;
  3182.  
  3183. +  /* 0xC */ u_char    logdrv;
  3184.  
  3185. +  /* 0xD */ u_char    numsgelements;
  3186.  
  3187. +  /* 0xE */ u_char    resvd;
  3188.  
  3189. +  /* 0xF */ u_char    busy;
  3190.  
  3191. +  /* 0x10*/ u_char    numstatus;
  3192.  
  3193. +  /* 0x11*/ u_char    status;
  3194.  
  3195. +  /* 0x12*/ u_char    completed[46];
  3196.  
  3197. +            u_char    mraid_poll;
  3198.  
  3199. +            u_char    mraid_ack;
  3200.  
  3201. +            u_char    pad[16];
  3202.  
  3203. +} mega_mailbox;
  3204.  
  3205. +
  3206.  
  3207. +typedef struct _mega_sglist
  3208.  
  3209. +{
  3210.  
  3211. +  u_long     address;
  3212.  
  3213. +  u_long     length;
  3214.  
  3215. +} mega_sglist;
  3216.  
  3217. +
  3218.  
  3219. +/* Queued command data */
  3220.  
  3221. +typedef struct _mega_scb mega_scb;
  3222.  
  3223. +
  3224.  
  3225. +struct _mega_scb
  3226.  
  3227. +{
  3228.  
  3229. +  int             idx;
  3230.  
  3231. +  u_long          flag;
  3232.  
  3233. +  Scsi_Cmnd      *SCpnt;
  3234.  
  3235. +  u_char          mboxData[16];
  3236.  
  3237. +  mega_passthru   pthru;
  3238.  
  3239. +  mega_sglist    *sgList;
  3240.  
  3241. +  mega_scb       *next;
  3242.  
  3243. +};
  3244.  
  3245. +
  3246.  
  3247. +/* Per-controller data */
  3248.  
  3249. +typedef struct _mega_host_config
  3250.  
  3251. +{
  3252.  
  3253. +  u_char               numldrv;
  3254.  
  3255. +  u_long               flag;
  3256.  
  3257. +  u_long               base;
  3258.  
  3259. +
  3260.  
  3261. +  struct tq_struct     megaTq;
  3262.  
  3263. +
  3264.  
  3265. +  /* Host adapter parameters */
  3266.  
  3267. +  u_char               fwVer[7];
  3268.  
  3269. +  u_char               biosVer[7];
  3270.  
  3271. +
  3272.  
  3273. +  struct Scsi_Host     *host;
  3274.  
  3275. +
  3276.  
  3277. +  /* The following must be DMA-able!! */
  3278.  
  3279. +  volatile mega_mailbox *mbox;
  3280.  
  3281. +  volatile mega_mailbox mailbox;
  3282.  
  3283. +  volatile u_char       mega_buffer[2*1024L];
  3284.  
  3285. +
  3286.  
  3287. +  u_char                max_cmds;
  3288.  
  3289. +  mega_scb              scbList[MAX_COMMANDS];
  3290.  
  3291. +} mega_host_config;
  3292.  
  3293. +
  3294.  
  3295. +extern struct proc_dir_entry proc_scsi_megaraid;
  3296.  
  3297. +
  3298.  
  3299. +const char *megaraid_info( struct Scsi_Host * );
  3300.  
  3301. +int        megaraid_detect( Scsi_Host_Template * );
  3302.  
  3303. +int        megaraid_release(struct Scsi_Host *);
  3304.  
  3305. +int        megaraid_command( Scsi_Cmnd * );
  3306.  
  3307. +int        megaraid_abort( Scsi_Cmnd * );
  3308.  
  3309. +int        megaraid_reset( Scsi_Cmnd *, unsigned int); 
  3310.  
  3311. +int        megaraid_queue( Scsi_Cmnd *, void (*done)(Scsi_Cmnd *) );
  3312.  
  3313. +int        megaraid_biosparam( Disk *, kdev_t, int * );
  3314.  
  3315. +int        megaraid_proc_info( char *buffer, char **start, off_t offset,
  3316.  
  3317. +                   int length, int hostno, int inout );
  3318.  
  3319. +
  3320.  
  3321. +#endif
  3322.  
  3323. diff -urN linux/include/linux/proc_fs.h linux-2.0.32-megaraid/include/linux/proc_fs.h
  3324.  
  3325. --- linux/include/linux/proc_fs.h    Tue Nov 18 14:46:46 1997
  3326.  
  3327. +++ linux-2.0.32-megaraid/include/linux/proc_fs.h    Tue Aug 11 10:54:47 1998
  3328.  
  3329. @@ -137,6 +137,7 @@
  3330.  
  3331.      PROC_SCSI_AM53C974,
  3332.  
  3333.      PROC_SCSI_SSC,
  3334.  
  3335.      PROC_SCSI_NCR53C406A,
  3336.  
  3337. +    PROC_SCSI_MEGARAID,
  3338.  
  3339.      PROC_SCSI_PPA,
  3340.  
  3341.      PROC_SCSI_ESP,
  3342.  
  3343.      PROC_SCSI_A3000,
  3344.  
  3345.