Annotation of Gnu-Mach/i386/i386at/gpl/linux/scsi/aha1740.c, revision 1.1.1.1

1.1       root        1: /*  $Id: aha1740.c,v 1.2 1997/03/24 21:51:17 thomas Exp $
                      2:  *  1993/03/31
                      3:  *  linux/kernel/aha1740.c
                      4:  *
                      5:  *  Based loosely on aha1542.c which is
                      6:  *  Copyright (C) 1992  Tommy Thorn and
                      7:  *  Modified by Eric Youngdale
                      8:  *
                      9:  *  This file is aha1740.c, written and
                     10:  *  Copyright (C) 1992,1993  Brad McLean
                     11:  *  
                     12:  *  Modifications to makecode and queuecommand
                     13:  *  for proper handling of multiple devices courteously
                     14:  *  provided by Michael Weller, March, 1993
                     15:  *
                     16:  * aha1740_makecode may still need even more work
                     17:  * if it doesn't work for your devices, take a look.
                     18:  */
                     19: 
                     20: #ifdef MODULE
                     21: #include <linux/module.h>
                     22: #endif
                     23: 
                     24: #include <linux/kernel.h>
                     25: #include <linux/head.h>
                     26: #include <linux/types.h>
                     27: #include <linux/string.h>
                     28: #include <linux/ioport.h>
                     29: #include <linux/proc_fs.h>
                     30: #include <linux/sched.h>
                     31: #include <asm/dma.h>
                     32: 
                     33: #include <asm/system.h>
                     34: #include <asm/io.h>
                     35: #include <linux/blk.h>
                     36: #include "scsi.h"
                     37: #include "hosts.h"
                     38: #include "sd.h"
                     39: 
                     40: #include "aha1740.h"
                     41: #include<linux/stat.h>
                     42: 
                     43: struct proc_dir_entry proc_scsi_aha1740 = {
                     44:     PROC_SCSI_AHA1740, 7, "aha1740",
                     45:     S_IFDIR | S_IRUGO | S_IXUGO, 2
                     46: };
                     47: 
                     48: /* IF YOU ARE HAVING PROBLEMS WITH THIS DRIVER, AND WANT TO WATCH
                     49:    IT WORK, THEN:
                     50: #define DEBUG
                     51: */
                     52: #ifdef DEBUG
                     53: #define DEB(x) x
                     54: #else
                     55: #define DEB(x)
                     56: #endif
                     57: 
                     58: /*
                     59: static const char RCSid[] = "$Header: /gd4/gnu/cvsroot/gnumach/i386/i386at/gpl/linux/scsi/aha1740.c,v 1.2 1997/03/24 21:51:17 thomas Exp $";
                     60: */
                     61: 
                     62: static unsigned int slot, base;
                     63: static unsigned char irq_level;
                     64: 
                     65: static struct ecb ecb[AHA1740_ECBS];   /* One for each queued operation */
                     66: 
                     67: static int aha1740_last_ecb_used  = 0; /* optimization */
                     68: 
                     69: int aha1740_makecode(unchar *sense, unchar *status)
                     70: {
                     71:     struct statusword
                     72:     {
                     73:        ushort  don:1,  /* Command Done - No Error */
                     74:                du:1,   /* Data underrun */
                     75:        :1,     qf:1,   /* Queue full */
                     76:                sc:1,   /* Specification Check */
                     77:                dor:1,  /* Data overrun */
                     78:                ch:1,   /* Chaining Halted */
                     79:                intr:1, /* Interrupt issued */
                     80:                asa:1,  /* Additional Status Available */
                     81:                sns:1,  /* Sense information Stored */
                     82:        :1,     ini:1,  /* Initialization Required */
                     83:                me:1,   /* Major error or exception */
                     84:        :1,     eca:1,  /* Extended Contingent alliance */
                     85:        :1;
                     86:     } status_word;
                     87:     int retval = DID_OK;
                     88: 
                     89:     status_word = * (struct statusword *) status;
                     90: #ifdef DEBUG
                     91: printk("makecode from %x,%x,%x,%x %x,%x,%x,%x",status[0],status[1],status[2],status[3],
                     92: sense[0],sense[1],sense[2],sense[3]);
                     93: #endif
                     94:     if (!status_word.don) /* Anything abnormal was detected */
                     95:     {
                     96:        if ( (status[1]&0x18) || status_word.sc ) /*Additional info available*/
                     97:        {
                     98:            /* Use the supplied info for further diagnostics */
                     99:            switch ( status[2] )
                    100:            {
                    101:            case 0x12:
                    102:                if ( status_word.dor )
                    103:                    retval=DID_ERROR;   /* It's an Overrun */
                    104:                /* If not overrun, assume underrun and ignore it! */
                    105:            case 0x00: /* No info, assume no error, should not occur */
                    106:                break;
                    107:            case 0x11:
                    108:            case 0x21:
                    109:                retval=DID_TIME_OUT;
                    110:                break;
                    111:            case 0x0a:
                    112:                retval=DID_BAD_TARGET;
                    113:                break;
                    114:            case 0x04:
                    115:            case 0x05:
                    116:                retval=DID_ABORT; /* Either by this driver or the AHA1740
                    117:                                         itself */
                    118:                break;
                    119:            default:
                    120:                retval=DID_ERROR; /* No further diagnostics possible */
                    121:            } 
                    122:        }
                    123:        else
                    124:        { /* Michael suggests, and Brad concurs: */
                    125:            if ( status_word.qf )
                    126:            {
                    127:                retval = DID_TIME_OUT; /* forces a redo */
                    128:                /* I think this specific one should not happen -Brad */
                    129:                printk("aha1740.c: WARNING: AHA1740 queue overflow!\n");
                    130:            }
                    131:            else if ( status[0]&0x60 )
                    132:            {
                    133:                retval = DID_ERROR; /* Didn't find a better error */
                    134:            }
                    135:            /* In any other case return DID_OK so for example
                    136:               CONDITION_CHECKS make it through to the appropriate
                    137:               device driver */
                    138:        }
                    139:     }
                    140:     /* Under all circumstances supply the target status -Michael */
                    141:     return status[3] | retval << 16;
                    142: }
                    143: 
                    144: int aha1740_test_port(void)
                    145: {
                    146:     char    name[4],tmp;
                    147: 
                    148:     /* Okay, look for the EISA ID's */
                    149:     name[0]= 'A' -1 + ((tmp = inb(HID0)) >> 2); /* First character */
                    150:     name[1]= 'A' -1 + ((tmp & 3) << 3);
                    151:     name[1]+= ((tmp = inb(HID1)) >> 5)&0x7;    /* Second Character */
                    152:     name[2]= 'A' -1 + (tmp & 0x1f);            /* Third Character */
                    153:     name[3]=0;
                    154:     tmp = inb(HID2);
                    155:     if ( strcmp ( name, HID_MFG ) || inb(HID2) != HID_PRD )
                    156:        return 0;   /* Not an Adaptec 174x */
                    157: 
                    158: /*  if ( inb(HID3) != HID_REV )
                    159:        printk("aha1740: Warning; board revision of %d; expected %d\n",
                    160:            inb(HID3),HID_REV); */
                    161: 
                    162:     if ( inb(EBCNTRL) != EBCNTRL_VALUE )
                    163:     {
                    164:        printk("aha1740: Board detected, but EBCNTRL = %x, so disabled it.\n",
                    165:            inb(EBCNTRL));
                    166:        return 0;
                    167:     }
                    168: 
                    169:     /* Try and turn on enhanced mode */
                    170:     tmp = inb (PORTADR);
                    171:     outb (PORTADR, tmp | PORTADDR_ENH);
                    172:     if ( inb(PORTADR) & PORTADDR_ENH )
                    173:        return 1;   /* Okay, we're all set */
                    174:        
                    175:     printk("aha1740: Board detected, but not in enhanced mode, so disabled it.\n");
                    176:     return 0;
                    177: }
                    178: 
                    179: /* A "high" level interrupt handler */
                    180: void aha1740_intr_handle(int irq, struct pt_regs * regs)
                    181: {
                    182:     void (*my_done)(Scsi_Cmnd *);
                    183:     int errstatus, adapstat;
                    184:     int number_serviced;
                    185:     struct ecb *ecbptr;
                    186:     Scsi_Cmnd *SCtmp;
                    187: 
                    188:     number_serviced = 0;
                    189: 
                    190:     while(inb(G2STAT) & G2STAT_INTPEND)
                    191:     {
                    192:        DEB(printk("aha1740_intr top of loop.\n"));
                    193:        adapstat = inb(G2INTST);
                    194:        ecbptr = (struct ecb *) bus_to_virt(inl(MBOXIN0));
                    195:        outb(G2CNTRL_IRST,G2CNTRL); /* interrupt reset */
                    196:       
                    197:        switch ( adapstat & G2INTST_MASK )
                    198:        {
                    199:        case    G2INTST_CCBRETRY:
                    200:        case    G2INTST_CCBERROR:
                    201:        case    G2INTST_CCBGOOD:
                    202:            outb(G2CNTRL_HRDY,G2CNTRL); /* Host Ready -> Mailbox in complete */
                    203:            if (!ecbptr)
                    204:            {
                    205:                printk("Aha1740 null ecbptr in interrupt (%x,%x,%x,%d)\n",
                    206:                        inb(G2STAT),adapstat,inb(G2INTST),number_serviced++);
                    207:                continue;
                    208:            }
                    209:            SCtmp = ecbptr->SCpnt;
                    210:            if (!SCtmp)
                    211:            {
                    212:                printk("Aha1740 null SCtmp in interrupt (%x,%x,%x,%d)\n",
                    213:                        inb(G2STAT),adapstat,inb(G2INTST),number_serviced++);
                    214:                continue;
                    215:            }
                    216:            if (SCtmp->host_scribble)
                    217:                scsi_free(SCtmp->host_scribble, 512);
                    218:          /* Fetch the sense data, and tuck it away, in the required slot.  The
                    219:             Adaptec automatically fetches it, and there is no guarantee that
                    220:             we will still have it in the cdb when we come back */
                    221:            if ( (adapstat & G2INTST_MASK) == G2INTST_CCBERROR )
                    222:              {
                    223:                memcpy(SCtmp->sense_buffer, ecbptr->sense, 
                    224:                       sizeof(SCtmp->sense_buffer));
                    225:                errstatus = aha1740_makecode(ecbptr->sense,ecbptr->status);
                    226:              }
                    227:            else
                    228:                errstatus = 0;
                    229:            DEB(if (errstatus) printk("aha1740_intr_handle: returning %6x\n", errstatus));
                    230:            SCtmp->result = errstatus;
                    231:            my_done = ecbptr->done;
                    232:            memset(ecbptr,0,sizeof(struct ecb)); 
                    233:            if ( my_done )
                    234:                my_done(SCtmp);
                    235:            break;
                    236:        case    G2INTST_HARDFAIL:
                    237:            printk("aha1740 hardware failure!\n");
                    238:            panic("aha1740.c"); /* Goodbye */
                    239:        case    G2INTST_ASNEVENT:
                    240:            printk("aha1740 asynchronous event: %02x %02x %02x %02x %02x\n",adapstat,
                    241:                inb(MBOXIN0),inb(MBOXIN1),inb(MBOXIN2),inb(MBOXIN3)); /* Say What? */
                    242:            outb(G2CNTRL_HRDY,G2CNTRL); /* Host Ready -> Mailbox in complete */
                    243:            break;
                    244:        case    G2INTST_CMDGOOD:
                    245:            /* set immediate command success flag here: */
                    246:            break;
                    247:        case    G2INTST_CMDERROR:
                    248:            /* Set immediate command failure flag here: */
                    249:            break;
                    250:        }
                    251:       number_serviced++;
                    252:     }
                    253: }
                    254: 
                    255: int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
                    256: {
                    257:     unchar direction;
                    258:     unchar *cmd = (unchar *) SCpnt->cmnd;
                    259:     unchar target = SCpnt->target;
                    260:     unsigned long flags;
                    261:     void *buff = SCpnt->request_buffer;
                    262:     int bufflen = SCpnt->request_bufflen;
                    263:     int ecbno;
                    264:     DEB(int i);
                    265: 
                    266:     
                    267:     if(*cmd == REQUEST_SENSE)
                    268:     {
                    269:        if (bufflen != sizeof(SCpnt->sense_buffer))
                    270:        {
                    271:            printk("Wrong buffer length supplied for request sense (%d)\n",bufflen);
                    272:        }
                    273:        SCpnt->result = 0;
                    274:        done(SCpnt); 
                    275:        return 0;
                    276:     }
                    277: 
                    278: #ifdef DEBUG
                    279:     if (*cmd == READ_10 || *cmd == WRITE_10)
                    280:        i = xscsi2int(cmd+2);
                    281:     else if (*cmd == READ_6 || *cmd == WRITE_6)
                    282:        i = scsi2int(cmd+2);
                    283:     else
                    284:        i = -1;
                    285:     printk("aha1740_queuecommand: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
                    286:     printk("scsi cmd:");
                    287:     for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]);
                    288:     printk("\n");
                    289: #endif
                    290: 
                    291:     /* locate an available ecb */
                    292: 
                    293:     save_flags(flags);
                    294:     cli();
                    295:     ecbno = aha1740_last_ecb_used + 1;         /* An optimization */
                    296:     if (ecbno >= AHA1740_ECBS) ecbno = 0;
                    297: 
                    298:     do{
                    299:       if( ! ecb[ecbno].cmdw )
                    300:        break;
                    301:       ecbno++;
                    302:       if (ecbno >= AHA1740_ECBS ) ecbno = 0;
                    303:     } while (ecbno != aha1740_last_ecb_used);
                    304: 
                    305:     if( ecb[ecbno].cmdw )
                    306:       panic("Unable to find empty ecb for aha1740.\n");
                    307: 
                    308:     ecb[ecbno].cmdw = AHA1740CMD_INIT; /* SCSI Initiator Command doubles as reserved flag */
                    309: 
                    310:     aha1740_last_ecb_used = ecbno;    
                    311:     restore_flags(flags);
                    312: 
                    313: #ifdef DEBUG
                    314:     printk("Sending command (%d %x)...",ecbno, done);
                    315: #endif
                    316: 
                    317:     ecb[ecbno].cdblen = SCpnt->cmd_len;        /* SCSI Command Descriptor Block Length */
                    318: 
                    319:     direction = 0;
                    320:     if (*cmd == READ_10 || *cmd == READ_6)
                    321:        direction = 1;
                    322:     else if (*cmd == WRITE_10 || *cmd == WRITE_6)
                    323:        direction = 0;
                    324: 
                    325:     memcpy(ecb[ecbno].cdb, cmd, ecb[ecbno].cdblen);
                    326: 
                    327:     if (SCpnt->use_sg)
                    328:     {
                    329:        struct scatterlist * sgpnt;
                    330:        struct aha1740_chain * cptr;
                    331:        int i;
                    332: #ifdef DEBUG
                    333:        unsigned char * ptr;
                    334: #endif
                    335:        ecb[ecbno].sg = 1;        /* SCSI Initiator Command  w/scatter-gather*/
                    336:        SCpnt->host_scribble = (unsigned char *) scsi_malloc(512);
                    337:        sgpnt = (struct scatterlist *) SCpnt->request_buffer;
                    338:        cptr = (struct aha1740_chain *) SCpnt->host_scribble; 
                    339:        if (cptr == NULL) panic("aha1740.c: unable to allocate DMA memory\n");
                    340:        for(i=0; i<SCpnt->use_sg; i++)
                    341:        {
                    342:            cptr[i].dataptr = (long) sgpnt[i].address;
                    343:            cptr[i].datalen = sgpnt[i].length;
                    344:        }
                    345:        ecb[ecbno].datalen = SCpnt->use_sg * sizeof(struct aha1740_chain);
                    346:        ecb[ecbno].dataptr = (long) cptr;
                    347: #ifdef DEBUG
                    348:        printk("cptr %x: ",cptr);
                    349:        ptr = (unsigned char *) cptr;
                    350:        for(i=0;i<24;i++) printk("%02x ", ptr[i]);
                    351: #endif
                    352:     }
                    353:     else
                    354:     {
                    355:        SCpnt->host_scribble = NULL;
                    356:        ecb[ecbno].datalen = bufflen;
                    357:        ecb[ecbno].dataptr = (long) buff;
                    358:     }
                    359:     ecb[ecbno].lun = SCpnt->lun;
                    360:     ecb[ecbno].ses = 1;        /* Suppress underrun errors */
                    361:     ecb[ecbno].dir= direction;
                    362:     ecb[ecbno].ars=1;  /* Yes, get the sense on an error */
                    363:     ecb[ecbno].senselen = 12;
                    364:     ecb[ecbno].senseptr = (long) ecb[ecbno].sense;
                    365:     ecb[ecbno].statusptr = (long) ecb[ecbno].status;
                    366:     ecb[ecbno].done = done;
                    367:     ecb[ecbno].SCpnt = SCpnt;
                    368: #ifdef DEBUG
                    369:     {
                    370:        int i;
                    371:        printk("aha1740_command: sending.. ");
                    372:        for (i = 0; i < sizeof(ecb[ecbno])-10; i++)
                    373:            printk("%02x ", ((unchar *)&ecb[ecbno])[i]);
                    374:     }
                    375:     printk("\n");
                    376: #endif
                    377:     if (done)
                    378:     { /*  You may question the code below, which contains potentially
                    379:          non-terminating while loops with interrupts disabled.  So did
                    380:          I when I wrote it, but the Adaptec Spec says the card is so fast,
                    381:          that this problem virtually never occurs so I've kept it.  We
                    382:          do printk a warning first, so that you'll know if it happens.
                    383:          In practice the only time we've seen this message is when some-
                    384:          thing else is in the driver was broken, like _makecode(), or
                    385:          when a scsi device hung the scsi bus.  Even under these conditions,
                    386:          The loop actually only cycled < 3 times (we instrumented it). */
                    387: 
                    388:        DEB(printk("aha1740[%d] critical section\n",ecbno));
                    389:        save_flags(flags);
                    390:        cli();
                    391:        if ( ! (inb(G2STAT) & G2STAT_MBXOUT) )
                    392:        {
                    393:            printk("aha1740[%d]_mbxout wait!\n",ecbno);
                    394:            cli(); /* printk may have done a sti()! */
                    395:        }
                    396:        mb();
                    397:        while ( ! (inb(G2STAT) & G2STAT_MBXOUT) );      /* Oh Well. */
                    398:        outl(virt_to_bus(ecb+ecbno), MBOXOUT0);
                    399:        if ( inb(G2STAT) & G2STAT_BUSY )
                    400:        {
                    401:            printk("aha1740[%d]_attn wait!\n",ecbno);
                    402:            cli();
                    403:        }
                    404:        while ( inb(G2STAT) & G2STAT_BUSY );            /* And Again! */
                    405:        outb(ATTN_START | (target & 7), ATTN);  /* Start it up */
                    406:        restore_flags(flags);
                    407:        DEB(printk("aha1740[%d] request queued.\n",ecbno));
                    408:     }
                    409:     else
                    410:       printk("aha1740_queuecommand: done can't be NULL\n");
                    411:     
                    412:     return 0;
                    413: }
                    414: 
                    415: static volatile int internal_done_flag = 0;
                    416: static volatile int internal_done_errcode = 0;
                    417: 
                    418: static void internal_done(Scsi_Cmnd * SCpnt)
                    419: {
                    420:     internal_done_errcode = SCpnt->result;
                    421:     ++internal_done_flag;
                    422: }
                    423: 
                    424: int aha1740_command(Scsi_Cmnd * SCpnt)
                    425: {
                    426:     aha1740_queuecommand(SCpnt, internal_done);
                    427: 
                    428:     while (!internal_done_flag);
                    429:     internal_done_flag = 0;
                    430:     return internal_done_errcode;
                    431: }
                    432: 
                    433: /* Query the board for its irq_level.  Nothing else matters
                    434:    in enhanced mode on an EISA bus. */
                    435: 
                    436: void aha1740_getconfig(void)
                    437: {
                    438:   static int intab[] = { 9,10,11,12,0,14,15,0 };
                    439: 
                    440:   irq_level = intab [ inb(INTDEF)&0x7 ];
                    441:   outb(inb(INTDEF) | 0x10, INTDEF);
                    442: }
                    443: 
                    444: int aha1740_detect(Scsi_Host_Template * tpnt)
                    445: {
                    446:     tpnt->proc_dir = &proc_scsi_aha1740;
                    447: 
                    448:     memset(&ecb, 0, sizeof(struct ecb));
                    449:     DEB(printk("aha1740_detect: \n"));
                    450:     
                    451:     for ( slot=MINEISA; slot <= MAXEISA; slot++ )
                    452:     {
                    453:        base = SLOTBASE(slot);
                    454:        /*
                    455:         * The ioports for eisa boards are generally beyond that used in the
                    456:         * check/allocate region code, but this may change at some point,
                    457:         * so we go through the motions.
                    458:         */
                    459:        if(check_region(base, 0x5c)) continue;  /* See if in use */
                    460:        if ( aha1740_test_port())  break;
                    461:     }
                    462:     if ( slot > MAXEISA )
                    463:        return 0;
                    464: 
                    465:     aha1740_getconfig();
                    466: 
                    467:     if ( (inb(G2STAT) & (G2STAT_MBXOUT | G2STAT_BUSY) ) != G2STAT_MBXOUT )
                    468:     {  /* If the card isn't ready, hard reset it */
                    469:        outb(G2CNTRL_HRST,G2CNTRL);
                    470:        outb(0,G2CNTRL);    
                    471:     }
                    472: 
                    473:     printk("Configuring Adaptec at IO:%x, IRQ %d\n",base,
                    474:           irq_level);
                    475: 
                    476:     DEB(printk("aha1740_detect: enable interrupt channel %d\n", irq_level));
                    477: 
                    478:     if (request_irq(irq_level,aha1740_intr_handle, 0, "aha1740"))
                    479:     {
                    480:        printk("Unable to allocate IRQ for adaptec controller.\n");
                    481:        return 0;
                    482:     }
                    483:     request_region(base, 0x5c,"aha1740");  /* Reserve the space that we need to use */
                    484:     return 1;
                    485: }
                    486: 
                    487: /* Note:  They following two functions do not apply very well to the Adaptec,
                    488: which basically manages its own affairs quite well without our interference,
                    489: so I haven't put anything into them.  I can faintly imagine someone with a
                    490: *very* badly behaved SCSI target (perhaps an old tape?) wanting the abort(),
                    491: but it hasn't happened yet, and doing aborts brings the Adaptec to its
                    492: knees.  I cannot (at this moment in time) think of any reason to reset the
                    493: card once it's running.  So there. */
                    494: 
                    495: int aha1740_abort(Scsi_Cmnd * SCpnt)
                    496: {
                    497:     DEB(printk("aha1740_abort called\n"));
                    498:     return SCSI_ABORT_SNOOZE;
                    499: }
                    500: 
                    501: /* We do not implement a reset function here, but the upper level code assumes
                    502:    that it will get some kind of response for the command in SCpnt.  We must
                    503:    oblige, or the command will hang the scsi system */
                    504: 
                    505: int aha1740_reset(Scsi_Cmnd * SCpnt)
                    506: {
                    507:     DEB(printk("aha1740_reset called\n"));
                    508:     return SCSI_RESET_PUNT;
                    509: }
                    510: 
                    511: int aha1740_biosparam(Disk * disk, kdev_t dev, int* ip)
                    512: {
                    513:   int size = disk->capacity;
                    514: DEB(printk("aha1740_biosparam\n"));
                    515:   ip[0] = 64;
                    516:   ip[1] = 32;
                    517:   ip[2] = size >> 11;
                    518: /*  if (ip[2] >= 1024) ip[2] = 1024; */
                    519:   return 0;
                    520: }
                    521: 
                    522: #ifdef MODULE
                    523: /* Eventually this will go into an include file, but this will be later */
                    524: Scsi_Host_Template driver_template = AHA1740;
                    525: 
                    526: #include "scsi_module.c"
                    527: #endif
                    528: 
                    529: /* Okay, you made it all the way through.  As of this writing, 3/31/93, I'm
                    530: [email protected] or [email protected].  I'll try to help as time
                    531: permits if you have any trouble with this driver.  Happy Linuxing! */

unix.superglobalmegacorp.com

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