Annotation of Gnu-Mach/linux/src/drivers/scsi/aha1740.c, revision 1.1

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