Annotation of Gnu-Mach/linux/src/drivers/scsi/qlogicfas.c, revision 1.1.1.1

1.1       root        1: /*----------------------------------------------------------------*/
                      2: /*
                      3:    Qlogic linux driver - work in progress. No Warranty express or implied.
                      4:    Use at your own risk.  Support Tort Reform so you won't have to read all
                      5:    these silly disclaimers.
                      6: 
                      7:    Copyright 1994, Tom Zerucha.   
                      8:    [email protected]
                      9: 
                     10:    Additional Code, and much appreciated help by
                     11:    Michael A. Griffith
                     12:    [email protected]
                     13: 
                     14:    Thanks to Eric Youngdale and Dave Hinds for loadable module and PCMCIA
                     15:    help respectively, and for suffering through my foolishness during the
                     16:    debugging process.
                     17: 
                     18:    Reference Qlogic FAS408 Technical Manual, 53408-510-00A, May 10, 1994
                     19:    (you can reference it, but it is incomplete and inaccurate in places)
                     20: 
                     21:    Version 0.45 6/9/96 - kernel 1.2.0+
                     22: 
                     23:    Functions as standalone, loadable, and PCMCIA driver, the latter from
                     24:    Dave Hind's PCMCIA package.
                     25: 
                     26:    Redistributable under terms of the GNU Public License
                     27: 
                     28: */
                     29: /*----------------------------------------------------------------*/
                     30: /* Configuration */
                     31: 
                     32: /* Set the following to 2 to use normal interrupt (active high/totempole-
                     33:    tristate), otherwise use 0 (REQUIRED FOR PCMCIA) for active low, open
                     34:    drain */
                     35: #define QL_INT_ACTIVE_HIGH 2
                     36: 
                     37: /* Set the following to 1 to enable the use of interrupts.  Note that 0 tends
                     38:    to be more stable, but slower (or ties up the system more) */
                     39: #define QL_USE_IRQ 1
                     40: 
                     41: /* Set the following to max out the speed of the PIO PseudoDMA transfers,
                     42:    again, 0 tends to be slower, but more stable.  */
                     43: #define QL_TURBO_PDMA 1
                     44: 
                     45: /* This should be 1 to enable parity detection */
                     46: #define QL_ENABLE_PARITY 1
                     47: 
                     48: /* This will reset all devices when the driver is initialized (during bootup).
                     49:    The other linux drivers don't do this, but the DOS drivers do, and after
                     50:    using DOS or some kind of crash or lockup this will bring things back
                     51:    without requiring a cold boot.  It does take some time to recover from a
                     52:    reset, so it is slower, and I have seen timeouts so that devices weren't
                     53:    recognized when this was set. */
                     54: #define QL_RESET_AT_START 0
                     55: 
                     56: /* crystal frequency in megahertz (for offset 5 and 9)
                     57:    Please set this for your card.  Most Qlogic cards are 40 Mhz.  The
                     58:    Control Concepts ISA (not VLB) is 24 Mhz */
                     59: #define XTALFREQ       40
                     60: 
                     61: /**********/
                     62: /* DANGER! modify these at your own risk */
                     63: /* SLOWCABLE can usually be reset to zero if you have a clean setup and
                     64:    proper termination.  The rest are for synchronous transfers and other
                     65:    advanced features if your device can transfer faster than 5Mb/sec.
                     66:    If you are really curious, email me for a quick howto until I have
                     67:    something official */
                     68: /**********/
                     69: 
                     70: /*****/
                     71: /* config register 1 (offset 8) options */
                     72: /* This needs to be set to 1 if your cabling is long or noisy */
                     73: #define SLOWCABLE 1
                     74: 
                     75: /*****/
                     76: /* offset 0xc */
                     77: /* This will set fast (10Mhz) synchronous timing when set to 1
                     78:    For this to have an effect, FASTCLK must also be 1 */
                     79: #define FASTSCSI 0
                     80: 
                     81: /* This when set to 1 will set a faster sync transfer rate */
                     82: #define FASTCLK 0
                     83: /*(XTALFREQ>25?1:0)*/
                     84: 
                     85: /*****/
                     86: /* offset 6 */
                     87: /* This is the sync transfer divisor, XTALFREQ/X will be the maximum
                     88:    achievable data rate (assuming the rest of the system is capable
                     89:    and set properly) */
                     90: #define SYNCXFRPD 5
                     91: /*(XTALFREQ/5)*/
                     92: 
                     93: /*****/
                     94: /* offset 7 */
                     95: /* This is the count of how many synchronous transfers can take place
                     96:        i.e. how many reqs can occur before an ack is given.
                     97:        The maximum value for this is 15, the upper bits can modify
                     98:        REQ/ACK assertion and deassertion during synchronous transfers
                     99:        If this is 0, the bus will only transfer asynchronously */
                    100: #define SYNCOFFST 0
                    101: /* for the curious, bits 7&6 control the deassertion delay in 1/2 cycles
                    102:        of the 40Mhz clock. If FASTCLK is 1, specifying 01 (1/2) will
                    103:        cause the deassertion to be early by 1/2 clock.  Bits 5&4 control
                    104:        the assertion delay, also in 1/2 clocks (FASTCLK is ignored here). */
                    105: 
                    106: /*----------------------------------------------------------------*/
                    107: #ifdef PCMCIA
                    108: #undef QL_INT_ACTIVE_HIGH
                    109: #define QL_INT_ACTIVE_HIGH 0
                    110: #define MODULE
                    111: #endif 
                    112: 
                    113: #include <linux/module.h>
                    114: 
                    115: #ifdef PCMCIA
                    116: #undef MODULE
                    117: #endif 
                    118: 
                    119: #include <linux/blk.h> /* to get disk capacity */
                    120: #include <linux/kernel.h>
                    121: #include <linux/string.h>
                    122: #include <linux/ioport.h>
                    123: #include <linux/sched.h>
                    124: #include <linux/proc_fs.h>
                    125: #include <linux/unistd.h>
                    126: #include <asm/io.h>
                    127: #include <asm/irq.h>
                    128: #include "sd.h"
                    129: #include "hosts.h"
                    130: #include "qlogicfas.h"
                    131: #include<linux/stat.h>
                    132: 
                    133: struct proc_dir_entry proc_scsi_qlogicfas = {
                    134:     PROC_SCSI_QLOGICFAS, 6, "qlogicfas",
                    135:     S_IFDIR | S_IRUGO | S_IXUGO, 2
                    136: };
                    137: 
                    138: /*----------------------------------------------------------------*/
                    139: /* driver state info, local to driver */
                    140: static int         qbase = 0;  /* Port */
                    141: static int         qinitid;    /* initiator ID */
                    142: static int         qabort;     /* Flag to cause an abort */
                    143: static int         qlirq = -1; /* IRQ being used */
                    144: static char        qinfo[80];  /* description */
                    145: static Scsi_Cmnd   *qlcmd;     /* current command being processed */
                    146: 
                    147: static int         qlcfg5 = ( XTALFREQ << 5 ); /* 15625/512 */
                    148: static int         qlcfg6 = SYNCXFRPD;
                    149: static int         qlcfg7 = SYNCOFFST;
                    150: static int         qlcfg8 = ( SLOWCABLE << 7 ) | ( QL_ENABLE_PARITY << 4 );
                    151: static int         qlcfg9 = ( ( XTALFREQ + 4 ) / 5 );
                    152: static int         qlcfgc = ( FASTCLK << 3 ) | ( FASTSCSI << 4 );
                    153: 
                    154: /*----------------------------------------------------------------*/
                    155: /* The qlogic card uses two register maps - These macros select which one */
                    156: #define REG0 ( outb( inb( qbase + 0xd ) & 0x7f , qbase + 0xd ), outb( 4 , qbase + 0xd ))
                    157: #define REG1 ( outb( inb( qbase + 0xd ) | 0x80 , qbase + 0xd ), outb( 0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd ))
                    158: 
                    159: /* following is watchdog timeout in microseconds */
                    160: #define WATCHDOG 5000000
                    161: 
                    162: /*----------------------------------------------------------------*/
                    163: /* the following will set the monitor border color (useful to find
                    164:    where something crashed or gets stuck at and as a simple profiler) */
                    165: 
                    166: #if 0
                    167: #define rtrc(i) {inb(0x3da);outb(0x31,0x3c0);outb((i),0x3c0);}
                    168: #else
                    169: #define rtrc(i) {}
                    170: #endif
                    171: 
                    172: /*----------------------------------------------------------------*/
                    173: /* local functions */
                    174: /*----------------------------------------------------------------*/
                    175: static void    ql_zap(void);
                    176: /* error recovery - reset everything */
                    177: void   ql_zap()
                    178: {
                    179: int    x;
                    180: unsigned long  flags;
                    181:        save_flags( flags );
                    182:        cli();
                    183:        x = inb(qbase + 0xd);
                    184:        REG0;
                    185:        outb(3, qbase + 3);                             /* reset SCSI */
                    186:        outb(2, qbase + 3);                             /* reset chip */
                    187:        if (x & 0x80)
                    188:                REG1;
                    189:        restore_flags( flags );
                    190: }
                    191: 
                    192: /*----------------------------------------------------------------*/
                    193: /* do pseudo-dma */
                    194: static int     ql_pdma(int phase, char *request, int reqlen)
                    195: {
                    196: int    j;
                    197:        j = 0;
                    198:        if (phase & 1) {        /* in */
                    199: #if QL_TURBO_PDMA
                    200: rtrc(4)
                    201:                /* empty fifo in large chunks */
                    202:                if( reqlen >= 128 && (inb( qbase + 8 ) & 2) ) { /* full */
                    203:                        insl( qbase + 4, request, 32 );
                    204:                        reqlen -= 128;
                    205:                        request += 128;
                    206:                }
                    207:                while( reqlen >= 84 && !( j & 0xc0 ) ) /* 2/3 */
                    208:                        if( (j=inb( qbase + 8 )) & 4 ) {
                    209:                                insl( qbase + 4, request, 21 );
                    210:                                reqlen -= 84;
                    211:                                request += 84;
                    212:                        }
                    213:                if( reqlen >= 44 && (inb( qbase + 8 ) & 8) ) {  /* 1/3 */
                    214:                        insl( qbase + 4, request, 11 );
                    215:                        reqlen -= 44;
                    216:                        request += 44;
                    217:                }
                    218: #endif
                    219:                /* until both empty and int (or until reclen is 0) */
                    220: rtrc(7)
                    221:                j = 0;
                    222:                while( reqlen && !( (j & 0x10) && (j & 0xc0) ) ) {
                    223:                        /* while bytes to receive and not empty */
                    224:                        j &= 0xc0;
                    225:                        while ( reqlen && !( (j=inb(qbase + 8)) & 0x10 ) ) {
                    226:                                *request++ = inb(qbase + 4);
                    227:                                reqlen--;
                    228:                        }
                    229:                        if( j & 0x10 )
                    230:                                j = inb(qbase+8);
                    231: 
                    232:                }
                    233:        }
                    234:        else {  /* out */
                    235: #if QL_TURBO_PDMA
                    236: rtrc(4)
                    237:                if( reqlen >= 128 && inb( qbase + 8 ) & 0x10 ) { /* empty */
                    238:                        outsl(qbase + 4, request, 32 );
                    239:                        reqlen -= 128;
                    240:                        request += 128;
                    241:                }
                    242:                while( reqlen >= 84 && !( j & 0xc0 ) ) /* 1/3 */
                    243:                        if( !((j=inb( qbase + 8 )) & 8) ) {
                    244:                                outsl( qbase + 4, request, 21 );
                    245:                                reqlen -= 84;
                    246:                                request += 84;
                    247:                        }
                    248:                if( reqlen >= 40 && !(inb( qbase + 8 ) & 4 ) ) { /* 2/3 */
                    249:                        outsl( qbase + 4, request, 10 );
                    250:                        reqlen -= 40;
                    251:                        request += 40;
                    252:                }
                    253: #endif
                    254:                /* until full and int (or until reclen is 0) */
                    255: rtrc(7)
                    256:                j = 0;
                    257:                while( reqlen && !( (j & 2) && (j & 0xc0) ) ) {
                    258:                        /* while bytes to send and not full */
                    259:                        while ( reqlen && !( (j=inb(qbase + 8)) & 2 ) ) {
                    260:                                outb(*request++, qbase + 4);
                    261:                                reqlen--;
                    262:                        }
                    263:                        if( j & 2 )
                    264:                                j = inb(qbase+8);
                    265:                }
                    266:        }
                    267: /* maybe return reqlen */
                    268:        return inb( qbase + 8 ) & 0xc0;
                    269: }
                    270: 
                    271: /*----------------------------------------------------------------*/
                    272: /* wait for interrupt flag (polled - not real hardware interrupt) */
                    273: static int     ql_wai(void)
                    274: {
                    275: int    i,k;
                    276:        k = 0;
                    277:        i = jiffies + WATCHDOG;
                    278:        while ( i > jiffies && !qabort && !((k = inb(qbase + 4)) & 0xe0))
                    279:                barrier();
                    280:        if (i <= jiffies)
                    281:                return (DID_TIME_OUT);
                    282:        if (qabort)
                    283:                return (qabort == 1 ? DID_ABORT : DID_RESET);
                    284:        if (k & 0x60)
                    285:                ql_zap();
                    286:        if (k & 0x20)
                    287:                return (DID_PARITY);
                    288:        if (k & 0x40)
                    289:                return (DID_ERROR);
                    290:        return 0;
                    291: }
                    292: 
                    293: /*----------------------------------------------------------------*/
                    294: /* initiate scsi command - queueing handler */
                    295: static void    ql_icmd(Scsi_Cmnd * cmd)
                    296: {
                    297: unsigned int       i;
                    298: unsigned long  flags;
                    299: 
                    300:        qabort = 0;
                    301: 
                    302:        save_flags( flags );
                    303:        cli();
                    304:        REG0;
                    305: /* clearing of interrupts and the fifo is needed */
                    306:        inb(qbase + 5);                         /* clear interrupts */
                    307:        if (inb(qbase + 5))                     /* if still interrupting */
                    308:                outb(2, qbase + 3);             /* reset chip */
                    309:        else if (inb(qbase + 7) & 0x1f)
                    310:                outb(1, qbase + 3);             /* clear fifo */
                    311:        while (inb(qbase + 5));                 /* clear ints */
                    312:        REG1;
                    313:        outb(1, qbase + 8);                     /* set for PIO pseudo DMA */
                    314:        outb(0, qbase + 0xb);                   /* disable ints */
                    315:        inb(qbase + 8);                         /* clear int bits */
                    316:        REG0;
                    317:        outb(0x40, qbase + 0xb);                /* enable features */
                    318: 
                    319: /* configurables */
                    320:        outb( qlcfgc , qbase + 0xc);
                    321: /* config: no reset interrupt, (initiator) bus id */
                    322:        outb( 0x40 | qlcfg8 | qinitid, qbase + 8);
                    323:        outb( qlcfg7 , qbase + 7 );
                    324:        outb( qlcfg6 , qbase + 6 );
                    325: /**/
                    326:        outb(qlcfg5, qbase + 5);                /* select timer */
                    327:        outb(qlcfg9 & 7, qbase + 9);                    /* prescaler */
                    328: /*     outb(0x99, qbase + 5);  */
                    329:        outb(cmd->target, qbase + 4);
                    330: 
                    331:        for (i = 0; i < cmd->cmd_len; i++)
                    332:                outb(cmd->cmnd[i], qbase + 2);
                    333:        qlcmd = cmd;
                    334:        outb(0x41, qbase + 3);  /* select and send command */
                    335:        restore_flags( flags );
                    336: }
                    337: /*----------------------------------------------------------------*/
                    338: /* process scsi command - usually after interrupt */
                    339: static unsigned int    ql_pcmd(Scsi_Cmnd * cmd)
                    340: {
                    341: unsigned int   i, j, k;
                    342: unsigned int   result;                 /* ultimate return result */
                    343: unsigned int   status;                 /* scsi returned status */
                    344: unsigned int   message;                /* scsi returned message */
                    345: unsigned int   phase;                  /* recorded scsi phase */
                    346: unsigned int   reqlen;                 /* total length of transfer */
                    347: struct scatterlist     *sglist;        /* scatter-gather list pointer */
                    348: unsigned int   sgcount;                /* sg counter */
                    349: 
                    350: rtrc(1)
                    351:        j = inb(qbase + 6);
                    352:        i = inb(qbase + 5);
                    353:        if (i == 0x20) {
                    354:                return (DID_NO_CONNECT << 16);
                    355:        }
                    356:        i |= inb(qbase + 5);    /* the 0x10 bit can be set after the 0x08 */
                    357:        if (i != 0x18) {
                    358:                printk("Ql:Bad Interrupt status:%02x\n", i);
                    359:                ql_zap();
                    360:                return (DID_BAD_INTR << 16);
                    361:        }
                    362:        j &= 7; /* j = inb( qbase + 7 ) >> 5; */
                    363: /* correct status is supposed to be step 4 */
                    364: /* it sometimes returns step 3 but with 0 bytes left to send */
                    365: /* We can try stuffing the FIFO with the max each time, but we will get a
                    366:    sequence of 3 if any bytes are left (but we do flush the FIFO anyway */
                    367:        if(j != 3 && j != 4) {
                    368:                printk("Ql:Bad sequence for command %d, int %02X, cmdleft = %d\n", j, i, inb( qbase+7 ) & 0x1f );
                    369:                ql_zap();
                    370:                return (DID_ERROR << 16);
                    371:        }
                    372:        result = DID_OK;
                    373:        if (inb(qbase + 7) & 0x1f)      /* if some bytes in fifo */
                    374:                outb(1, qbase + 3);             /* clear fifo */
                    375: /* note that request_bufflen is the total xfer size when sg is used */
                    376:        reqlen = cmd->request_bufflen;
                    377: /* note that it won't work if transfers > 16M are requested */
                    378:        if (reqlen && !((phase = inb(qbase + 4)) & 6)) {        /* data phase */
                    379: rtrc(2)
                    380:                outb(reqlen, qbase);                    /* low-mid xfer cnt */
                    381:                outb(reqlen >> 8, qbase+1);                     /* low-mid xfer cnt */
                    382:                outb(reqlen >> 16, qbase + 0xe);        /* high xfer cnt */
                    383:                outb(0x90, qbase + 3);                  /* command do xfer */
                    384: /* PIO pseudo DMA to buffer or sglist */
                    385:                REG1;
                    386:                if (!cmd->use_sg)
                    387:                        ql_pdma(phase, cmd->request_buffer, cmd->request_bufflen);
                    388:                else {
                    389:                        sgcount = cmd->use_sg;
                    390:                        sglist = cmd->request_buffer;
                    391:                        while (sgcount--) {
                    392:                                if (qabort) {
                    393:                                        REG0;
                    394:                                        return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16);
                    395:                                }
                    396:                                if (ql_pdma(phase, sglist->address, sglist->length))
                    397:                                        break;
                    398:                                sglist++;
                    399:                        }
                    400:                }
                    401:                REG0;
                    402: rtrc(2)
                    403: /* wait for irq (split into second state of irq handler if this can take time) */
                    404:                if ((k = ql_wai()))
                    405:                        return (k << 16);
                    406:                k = inb(qbase + 5);     /* should be 0x10, bus service */
                    407:        }
                    408: /*** Enter Status (and Message In) Phase ***/
                    409:        k = jiffies + WATCHDOG;
                    410:        while ( k > jiffies && !qabort && !(inb(qbase + 4) & 6));       /* wait for status phase */
                    411:        if ( k <= jiffies ) {
                    412:                ql_zap();
                    413:                return (DID_TIME_OUT << 16);
                    414:        }
                    415:        while (inb(qbase + 5));                                 /* clear pending ints */
                    416:        if (qabort)
                    417:                return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16);
                    418:        outb(0x11, qbase + 3);                                  /* get status and message */
                    419:        if ((k = ql_wai()))
                    420:                return (k << 16);
                    421:        i = inb(qbase + 5);                                     /* get chip irq stat */
                    422:        j = inb(qbase + 7) & 0x1f;                              /* and bytes rec'd */
                    423:        status = inb(qbase + 2);
                    424:        message = inb(qbase + 2);
                    425: /* should get function complete int if Status and message, else bus serv if only status */
                    426:        if (!((i == 8 && j == 2) || (i == 0x10 && j == 1))) {
                    427:                printk("Ql:Error during status phase, int=%02X, %d bytes recd\n", i, j);
                    428:                result = DID_ERROR;
                    429:        }
                    430:        outb(0x12, qbase + 3);  /* done, disconnect */
                    431: rtrc(1)
                    432:        if ((k = ql_wai()))
                    433:                return (k << 16);
                    434: /* should get bus service interrupt and disconnect interrupt */
                    435:        i = inb(qbase + 5);     /* should be bus service */
                    436:        while (!qabort && ((i & 0x20) != 0x20)) {
                    437:                barrier();
                    438:                i |= inb(qbase + 5);
                    439:        }
                    440: rtrc(0)
                    441:        if (qabort)
                    442:                return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16);
                    443:        return (result << 16) | (message << 8) | (status & STATUS_MASK);
                    444: }
                    445: 
                    446: #if QL_USE_IRQ
                    447: /*----------------------------------------------------------------*/
                    448: /* interrupt handler */
                    449: static void           ql_ihandl(int irq, void *dev_id, struct pt_regs * regs)
                    450: {
                    451: Scsi_Cmnd         *icmd;
                    452:        REG0;
                    453:        if (!(inb(qbase + 4) & 0x80))   /* false alarm? */
                    454:                return;
                    455:        if (qlcmd == NULL) {            /* no command to process? */
                    456:                int     i;
                    457:                i = 16;
                    458:                while (i-- && inb(qbase + 5)); /* maybe also ql_zap() */
                    459:                return;
                    460:        }
                    461:        icmd = qlcmd;
                    462:        icmd->result = ql_pcmd(icmd);
                    463:        qlcmd = NULL;
                    464: /* if result is CHECK CONDITION done calls qcommand to request sense */
                    465:        (icmd->scsi_done) (icmd);
                    466: }
                    467: #endif
                    468: 
                    469: /*----------------------------------------------------------------*/
                    470: /* global functions */
                    471: /*----------------------------------------------------------------*/
                    472: /* non queued command */
                    473: #if QL_USE_IRQ
                    474: static void    qlidone(Scsi_Cmnd * cmd) {};            /* null function */
                    475: #endif
                    476: 
                    477: /* command process */
                    478: int    qlogicfas_command(Scsi_Cmnd * cmd)
                    479: {
                    480: int    k;
                    481: #if QL_USE_IRQ
                    482:        if (qlirq >= 0) {
                    483:                qlogicfas_queuecommand(cmd, qlidone);
                    484:                while (qlcmd != NULL);
                    485:                return cmd->result;
                    486:        }
                    487: #endif
                    488: /* non-irq version */
                    489:        if (cmd->target == qinitid)
                    490:                return (DID_BAD_TARGET << 16);
                    491:        ql_icmd(cmd);
                    492:        if ((k = ql_wai()))
                    493:                return (k << 16);
                    494:        return ql_pcmd(cmd);
                    495: 
                    496: }
                    497: 
                    498: #if QL_USE_IRQ
                    499: /*----------------------------------------------------------------*/
                    500: /* queued command */
                    501: int    qlogicfas_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
                    502: {
                    503:        if(cmd->target == qinitid) {
                    504:                cmd->result = DID_BAD_TARGET << 16;
                    505:                done(cmd);
                    506:                return 0;
                    507:        }
                    508: 
                    509:        cmd->scsi_done = done;
                    510: /* wait for the last command's interrupt to finish */
                    511:        while (qlcmd != NULL)
                    512:                barrier();
                    513:        ql_icmd(cmd);
                    514:        return 0;
                    515: }
                    516: #else
                    517: int    qlogicfas_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
                    518: {
                    519:        return 1;
                    520: }
                    521: #endif
                    522: 
                    523: #ifdef PCMCIA
                    524: /*----------------------------------------------------------------*/
                    525: /* allow PCMCIA code to preset the port */
                    526: /* port should be 0 and irq to -1 respectively for autoprobing */
                    527: void   qlogicfas_preset(int port, int irq)
                    528: {
                    529:        qbase=port;
                    530:        qlirq=irq;
                    531: }
                    532: #endif
                    533: 
                    534: /*----------------------------------------------------------------*/
                    535: /* look for qlogic card and init if found */
                    536: int    qlogicfas_detect(Scsi_Host_Template * host)
                    537: {
                    538: int    i, j;                   /* these are only used by IRQ detect */
                    539: int    qltyp;                  /* type of chip */
                    540: struct Scsi_Host       *hreg;  /* registered host structure */
                    541: unsigned long  flags;
                    542: 
                    543: host->proc_dir =  &proc_scsi_qlogicfas;
                    544: 
                    545: /* Qlogic Cards only exist at 0x230 or 0x330 (the chip itself decodes the
                    546:    address - I check 230 first since MIDI cards are typically at 330
                    547: 
                    548:    Theoretically, two Qlogic cards can coexist in the same system.  This
                    549:    should work by simply using this as a loadable module for the second
                    550:    card, but I haven't tested this.
                    551: */
                    552: 
                    553:        if( !qbase ) {
                    554:                for (qbase = 0x230; qbase < 0x430; qbase += 0x100) {
                    555:                        if( check_region( qbase , 0x10 ) )
                    556:                                continue;
                    557:                        REG1;
                    558:                        if ( ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 )
                    559:                          && ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 ) )
                    560:                                break;
                    561:                }
                    562:                if (qbase == 0x430)
                    563:                        return 0;
                    564:        }
                    565:        else
                    566:                printk( "Ql: Using preset base address of %03x\n", qbase );
                    567: 
                    568:        qltyp = inb(qbase + 0xe) & 0xf8;
                    569:        qinitid = host->this_id;
                    570:        if (qinitid < 0)
                    571:                qinitid = 7;                    /* if no ID, use 7 */
                    572:        outb(1, qbase + 8);                     /* set for PIO pseudo DMA */
                    573:        REG0;
                    574:        outb(0x40 | qlcfg8 | qinitid, qbase + 8);       /* (ini) bus id, disable scsi rst */
                    575:        outb(qlcfg5, qbase + 5);                /* select timer */
                    576:        outb(qlcfg9, qbase + 9);                        /* prescaler */
                    577: #if QL_RESET_AT_START
                    578:        outb( 3 , qbase + 3 );
                    579:        REG1;
                    580:        while( inb( qbase + 0xf ) & 4 );
                    581:        REG0;
                    582: #endif
                    583: #if QL_USE_IRQ
                    584: /* IRQ probe - toggle pin and check request pending */
                    585: 
                    586:        if( qlirq == -1 ) {
                    587:                save_flags( flags );
                    588:                cli();
                    589:                i = 0xffff;
                    590:                j = 3;
                    591:                outb(0x90, qbase + 3);  /* illegal command - cause interrupt */
                    592:                REG1;
                    593:                outb(10, 0x20); /* access pending interrupt map */
                    594:                outb(10, 0xa0);
                    595:                while (j--) {
                    596:                        outb(0xb0 | QL_INT_ACTIVE_HIGH , qbase + 0xd);  /* int pin off */
                    597:                        i &= ~(inb(0x20) | (inb(0xa0) << 8));   /* find IRQ off */
                    598:                        outb(0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd);  /* int pin on */
                    599:                        i &= inb(0x20) | (inb(0xa0) << 8);      /* find IRQ on */
                    600:                }
                    601:                REG0;
                    602:                while (inb(qbase + 5));                         /* purge int */
                    603:                j = -1;
                    604:                while (i)                                       /* find on bit */
                    605:                        i >>= 1, j++;   /* should check for exactly 1 on */
                    606:                qlirq = j;
                    607:                restore_flags( flags );
                    608:        }
                    609:        else
                    610:                printk( "Ql: Using preset IRQ %d\n", qlirq );
                    611: 
                    612:        if (qlirq >= 0 && !request_irq(qlirq, ql_ihandl, 0, "qlogicfas", NULL))
                    613:                host->can_queue = 1;
                    614: #endif
                    615:        request_region( qbase , 0x10 ,"qlogicfas");
                    616:        hreg = scsi_register( host , 0 );       /* no host data */
                    617:        hreg->io_port = qbase;
                    618:        hreg->n_io_port = 16;
                    619:        hreg->dma_channel = -1;
                    620:        if( qlirq != -1 )
                    621:                hreg->irq = qlirq;
                    622: 
                    623:        sprintf(qinfo, "Qlogicfas Driver version 0.45, chip %02X at %03X, IRQ %d, TPdma:%d",
                    624:            qltyp, qbase, qlirq, QL_TURBO_PDMA );
                    625:        host->name = qinfo;
                    626: 
                    627:        return 1;
                    628: }
                    629: 
                    630: /*----------------------------------------------------------------*/
                    631: /* return bios parameters */
                    632: int    qlogicfas_biosparam(Disk * disk, kdev_t dev, int ip[])
                    633: {
                    634: /* This should mimic the DOS Qlogic driver's behavior exactly */
                    635:        ip[0] = 0x40;
                    636:        ip[1] = 0x20;
                    637:        ip[2] = disk->capacity / (ip[0] * ip[1]);
                    638:        if (ip[2] > 1024) {
                    639:                ip[0] = 0xff;
                    640:                ip[1] = 0x3f;
                    641:                ip[2] = disk->capacity / (ip[0] * ip[1]);
                    642:                if (ip[2] > 1023)
                    643:                        ip[2] = 1023;
                    644:        }
                    645:        return 0;
                    646: }
                    647: 
                    648: /*----------------------------------------------------------------*/
                    649: /* abort command in progress */
                    650: int    qlogicfas_abort(Scsi_Cmnd * cmd)
                    651: {
                    652:        qabort = 1;
                    653:        ql_zap();
                    654:        return 0;
                    655: }
                    656: 
                    657: /*----------------------------------------------------------------*/
                    658: /* reset SCSI bus */
                    659: int    qlogicfas_reset(Scsi_Cmnd * cmd, unsigned int flags)
                    660: {
                    661:        qabort = 2;
                    662:        ql_zap();
                    663:        return 1;
                    664: }
                    665: 
                    666: /*----------------------------------------------------------------*/
                    667: /* return info string */
                    668: const char     *qlogicfas_info(struct Scsi_Host * host)
                    669: {
                    670:        return qinfo;
                    671: }
                    672: 
                    673: #ifdef MODULE
                    674: /* Eventually this will go into an include file, but this will be later */
                    675: Scsi_Host_Template driver_template = QLOGICFAS;
                    676: 
                    677: #include "scsi_module.c"
                    678: #endif
                    679: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.