Annotation of Gnu-Mach/i386/i386at/gpl/linux/scsi/aha1740.c, revision 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.