Annotation of coherent/b/STREAMS/io.386/hai154x.c, revision 1.1.1.1

1.1       root        1: /***********************************************************************
                      2:  *  Module: hai154x.c
                      3:  *
                      4:  *  Host Adapter Interface routines for the Adaptec AHA154XX series
                      5:  *  of host adapters.
                      6:  *
                      7:  *  Much of the information used to create this driver was obtained
                      8:  *  from the AHA1540B/1542B Technical Reference Manual available from
                      9:  *  Adaptec by phone or snail mail at:
                     10:  *
                     11:  *       Adaptec - Literature Department
                     12:  *       691 South Milpitas Blvd.
                     13:  *       Milpitas, CA 95035
                     14:  *       (408) 945-8600
                     15:  *
                     16:  *  Copyright (c), 1993 Christopher Sean Hilton, All Rights Reserved.
                     17:  *
                     18:  *  Last Modified: Sat Jul 24 08:44:54 1993 by [chris]
                     19:  *
                     20:  */
                     21: 
                     22: #define HA_MODULE         /* Host Adaptor Module */
                     23: #define LOUIS_HACK     1       /* defined for Louis' hacks */
                     24: 
                     25: #include <stddef.h>
                     26: #include <sys/coherent.h>
                     27: #include <sys/con.h>
                     28: #include <sys/devices.h>
                     29: #include <sys/types.h>
                     30: #include <sys/hdioctl.h>
                     31: 
                     32: #include <sys/haiscsi.h>
                     33: 
                     34: /*
                     35:  * Configurable variables - see /etc/conf/hai/Space.c
                     36:  */
                     37: extern unsigned short  AHABASE;
                     38: extern unsigned short  AHAINTR;
                     39: extern unsigned short  AHADMACHAN;
                     40: 
                     41: extern int     HAI_SD_HDS;
                     42: extern int     HAI_SD_SPT;
                     43: 
                     44: #define CTRLREG         (AHABASE + 0)   /* Control Register (Write) */
                     45: #define         HRST   bit(7)            /* Hard Reset */
                     46: #define         SRST   bit(6)            /* Soft Reset */
                     47: #define         IRST   bit(5)            /* Interrupt Reset */
                     48: #define         SCRST   bit(4)           /* SCSI Bus Reset */
                     49: 
                     50: #define STSREG   (AHABASE + 0)   /* Status Register (Read) */
                     51: #define         STST   bit(7)            /* Self Test in progress */
                     52: #define         DIAGF   bit(6)           /* Internal Diagnostic Failure */
                     53: #define         INIT   bit(5)            /* Mailbox Initialization Required */
                     54: #define         IDLE   bit(4)            /* SCSI Host Adapter Idle */
                     55: #define         CDF     bit(3)           /* Command/Data Out Port Full */
                     56: #define         DF       bit(2)                  /* Data In Port Full */
                     57: #define         INVDCMD bit(0)           /* Invalid HA Command */
                     58: 
                     59: #define CMDDATAOUT  (AHABASE + 1)   /* Command/Data Out (Write) */
                     60: #define         NOP             0x00           /* No Operation (really?) */
                     61: #define         MBINIT   0x01          /* Mail Box Initialization */
                     62: #define         STARTSCSI   0x02               /* Start a SCSI Command */
                     63: #define         STARTBIOS   0x03               /* Start a BIOS Command */
                     64: #define         HAINQUIRY   0x04               /* HA Inquiry */
                     65: #define         ENBLMBOA       0x05            /* Enable Mailbox Out Available Interrupt */
                     66: #define         STSELTO         0x06           /* Set Selection Timeout */
                     67: #define         SETBUSON       0x07            /* Set Bus on time */
                     68: #define         SETBUSOFF   0x08               /* Set Bus off time */
                     69: #define         SETXFER         0x09           /* Set transfer speed */
                     70: #define         RETINSTDEV  0x0a               /* Return Installed Devices */
                     71: #define         RETCFGDATA  0x0b               /* Return Configuration Data */
                     72: #define         ENBLTRGTMD  0x0c               /* Enable Target Mode */
                     73: #define         RETSUDATA   0x0d               /* Return Setup Data */
                     74: 
                     75: #define DATAIN   (AHABASE + 1)
                     76: 
                     77: #define INTRFLGS       (AHABASE + 2)
                     78: #define         ANYINTR bit(7)           /* Any Interrupt */
                     79: #define         SCRD   bit(3)            /* SCSI Reset Detected */
                     80: #define         HACC   bit(2)            /* HA Command Complete */
                     81: #define         MBOA   bit(1)            /* MBO Empty */
                     82: #define         MBIF   bit(0)            /* MBI Full */
                     83: 
                     84: #define MBOFREE         0x00           /* Mailbox out is free */
                     85: #define MBOSTART       0x01            /* Start CCB in this Mailbox */
                     86: #define MBOABORT       0x02            /* Abort CCB in this Mailbox */
                     87: 
                     88: #define MBIFREE         0x00           /* Mailbox in is free */
                     89: #define MBISUCCESS  0x01               /* Mailbox's CCB Completed Successfully */
                     90: #define MBIABORTED  0x02               /* Mailbox's CCB Aborted */
                     91: #define MBIABRTFLD  0x03               /* CCB to Abort not found */
                     92: #define MBIERROR       0x04            /* CCB Completed with error */
                     93: 
                     94: #define TIMEOUT         -1               /* Timeout from pollxxx() functions. */
                     95: 
                     96: #define ST_HAINIT   0x0001       /* Host Adapter being initialized */
                     97: #define ST_HAIDLE   0x0002       /* Host Adapter is idle */
                     98: 
                     99: /***********************************************************************
                    100:  *  Types
                    101:  */
                    102: 
                    103: #pragma align 1
                    104: 
                    105: typedef union addr3_u {                 /* addr3_u for big/little endian conversions */
                    106:        unsigned long   value;
                    107:        unsigned char   byteval[sizeof(unsigned long)];
                    108: } addr3_t;
                    109: 
                    110: typedef union mbo_u *mbo_p;     /* Out Box to host adapter */
                    111: 
                    112: typedef union mbo_u {
                    113:        unsigned char   cmd;
                    114:        paddr_t          ccbaddr;
                    115: } mbo_t;
                    116: 
                    117: typedef union mbi_u *mbi_p;     /* In Box from host adapter */
                    118: 
                    119: typedef union mbi_u {
                    120:        unsigned char   sts;
                    121:        paddr_t          ccbaddr;
                    122: } mbi_t;
                    123: 
                    124: typedef struct mb_s {             /* Host adapter mailbox type */
                    125:        mbo_t      o[MAXDEVS];   /* One out box for each device */
                    126:        mbi_t      i[MAXDEVS];   /* One in box for each possible reply */
                    127: } mb_t;
                    128: 
                    129: typedef struct haccb_s *haccb_p;       /* Host Adapter Command/Control Block */
                    130: 
                    131: typedef struct haccb_s {
                    132:        unsigned char   opcode;
                    133:        unsigned char   addrctrl;
                    134:        unsigned char   cdblen;
                    135:        unsigned char   senselen;
                    136:        unsigned char   datalen[3];
                    137:        unsigned char   bufaddr[3];
                    138:        unsigned char   linkaddr[3];
                    139:        unsigned char   linkid;
                    140:        unsigned char   hoststs;
                    141:        unsigned char   trgtsts;
                    142:        unsigned char   pad[2];
                    143:        cdb_t              cdb;
                    144: } haccb_t;
                    145: 
                    146: typedef struct dsentry_s *dsentry_p;
                    147: 
                    148: typedef struct dsentry_s {
                    149:        unsigned char   size[3];
                    150:        unsigned char   addr[3];
                    151: } dsentry_t;
                    152: 
                    153: typedef struct dslist_s *dslist_p;
                    154: 
                    155: typedef struct dslist_s {
                    156:        dsentry_t          entries[16];
                    157: } dslist_t;
                    158: 
                    159: #pragma align
                    160: 
                    161: /***********************************************************************
                    162:  *  Variables
                    163:  */
                    164: 
                    165: static int       hastate;              /* Host Adapter State */
                    166: static mb_t     mb;                     /* Mailboxes for host adapter */       
                    167: static haccb_t  ccb[MAXDEVS];   /* CCB's for mailboxes */
                    168: static paddr_t  ccbbase;               /* ccbbase address for quick checkmail */
                    169: static srb_p   actv[MAXDEVS];  /* Active srb's for each target */
                    170: static dslist_t ds[MAXDEVS];   /* Data segment lists one for each target */
                    171: static unsigned chkport = 0,   /* Port for chkset/ckhclr */
                    172:                                chkstop = 0,    /* Target value for chkset/chkclr */
                    173:                                chkval  = 0;    /* Value in port chkset/chkclr */
                    174: int                     hapresent;       /* Host adapter present flag */
                    175: 
                    176: /***********************************************************************
                    177:  *  Support Functions
                    178:  */
                    179: 
                    180: #define min(a, b)   (((a) <= (b)) ? (a) : (b))
                    181: 
                    182: /***********************************************************************
                    183:  *  chkclr()   --  Check port (chkport) for bits (chkstop) to be clear.
                    184:  *                               If clear return 1 else return 0.  Leave value of
                    185:  *                               port in chkval;
                    186:  */
                    187: 
                    188: static int chkclr()
                    189: 
                    190: {
                    191:        return ((chkval = inb(chkport)) & chkstop) == 0;
                    192: }   /* chkclr() */
                    193: 
                    194: /***********************************************************************
                    195:  *  chkset()   --  Check port (chkport) for bits (chkstop) to be set.
                    196:  *                               If all bits are set return 1 else return 0. Leave
                    197:  *                               value of port in chkval.
                    198:  */
                    199: 
                    200: static int chkset()
                    201: 
                    202: {
                    203:        return ((chkval = inb(chkport)) & chkstop) == chkstop;
                    204: }   /* chkset() */
                    205: 
                    206: /***********************************************************************
                    207:  *  pollclr()   --  Wait usec milliseconds for bit(s) to clear in a
                    208:  *                               port.
                    209:  */
                    210: 
                    211: static int pollclr(port, bits, usec)
                    212: register unsigned   port;         /* port to watch */
                    213: register unsigned   bits;         /* bits to watch for */
                    214: unsigned                       usec;      /* number of milliseconds to wait for */
                    215: {
                    216:        register s;
                    217: 
                    218:        s = sphi();
                    219:        chkport = port;
                    220:        chkstop = bits;
                    221:        busyWait(chkclr, usec);
                    222:        spl(s);
                    223:        
                    224: #if 1   /* DEBUG */
                    225:        if ((chkval & bits) == 0)
                    226:                return chkval;
                    227:        else {
                    228:                printf("pollclr: <Timeout Reg: 0x%x mask 0x%x value 0x%x>\n", port, bits, chkval);
                    229:                return TIMEOUT;
                    230:        }
                    231: #else
                    232:        return ((chkval & bits) == 0) ? chkval : TIMEOUT;
                    233: #endif 
                    234: }   /* pollclr() */
                    235: 
                    236: /***********************************************************************
                    237:  *  pollset()   --  Wait usec milliseconds for bit(s) set in a port.
                    238:  */
                    239: 
                    240: static int pollset(port, bits, usec)
                    241: register unsigned   port;         /* port to watch */
                    242: register unsigned   bits;         /* bits to watch for */
                    243: unsigned                       usec;      /* number of milliseconds to wait for */
                    244: {
                    245:        register s;
                    246: 
                    247:        s = sphi();
                    248:        chkport = port;
                    249:        chkstop = bits;
                    250:        busyWait(chkset, usec);
                    251:        spl(s);
                    252: 
                    253: #if 1   /* DEBUG */
                    254:        if ((chkval & bits) == bits)
                    255:                return chkval;
                    256:        else {
                    257:                printf("pollset: <Timeout Reg: 0x%x mask 0x%x value 0x%x>\n", port, bits, chkval);
                    258:                return TIMEOUT;
                    259:        }
                    260: #else
                    261:        return ((chkval & bits) == bits) ? chkval : TIMEOUT;
                    262: #endif 
                    263: }   /* pollset() */
                    264: 
                    265: /***********************************************************************
                    266:  *  hacc()
                    267:  *
                    268:  *  Host Adapter Command Completed - Returns 1 if last host adapter
                    269:  *  command completed without error.
                    270:  */
                    271: 
                    272: static int hacc()
                    273: 
                    274: {
                    275:        register unsigned stsreg;
                    276: 
                    277: #ifdef LOUIS_HACK
                    278:        register unsigned louis_stsreg;
                    279:        if((louis_stsreg = pollset(INTRFLGS, HACC, 350)) == TIMEOUT)
                    280:         return 0;
                    281:        printf("HACC - louis_stsreg: 0x%x\n", louis_stsreg);
                    282: #else
                    283:        if (pollset(INTRFLGS, HACC, 350) == TIMEOUT)
                    284:                return 0;
                    285: #endif
                    286: 
                    287:        stsreg = pollset(STSREG, IDLE, 350) & (IDLE | INIT | CDF | INVDCMD);
                    288:        if (stsreg != IDLE) {
                    289:                printf("Aha154x stuck - STSREG: 0x%x\n", stsreg);
                    290:                return 0;
                    291:        }
                    292:        return 1;
                    293: }   /* hacc() */
                    294: 
                    295: /***********************************************************************
                    296:  *  haidle()
                    297:  *
                    298:  *  Returns 1 if the Idle Bit is on in the adapter status register
                    299:  */
                    300: 
                    301: #define haidle()       (pollset(STSREG, IDLE, 350) != TIMEOUT)
                    302: 
                    303: /***********************************************************************
                    304:  *  gethabyte()
                    305:  *
                    306:  *  Get a byte from the host adapter Data In register.
                    307:  */
                    308: 
                    309: static int gethabyte()
                    310: 
                    311: {
                    312:        if (pollset(STSREG, DF, 350) == TIMEOUT) {
                    313:                printf("haiscsi: <gethabyte timeout (0x%x) 0x%x 0x%x>\n", STSREG, DF, chkval);
                    314:                return TIMEOUT;
                    315:        }
                    316:        else
                    317:                return (inb(DATAIN) & 0xff);
                    318: }   /* gethabyte() */
                    319: 
                    320: /***********************************************************************
                    321:  *  puthabyte()
                    322:  *
                    323:  *  Write a byte to the host adapter Command/Data Out Register.
                    324:  */
                    325: 
                    326: static int puthabyte(b)
                    327: unsigned char b;
                    328: 
                    329: {
                    330:        if (pollclr(STSREG, CDF, 350) == TIMEOUT)
                    331:                return 0;
                    332:        else {
                    333:                outb(CMDDATAOUT, b);
                    334:                return 1;
                    335:        }
                    336: }   /* puthabyte() */
                    337: 
                    338: /***********************************************************************
                    339:  *  is_154x()
                    340:  *
                    341:  *  Returns a string indicating the type and revision of the AHA154x
                    342:  *  host adapter on the bus if it is out there.  Caveat: if something
                    343:  *  else is out there that can respond to this message I don't know
                    344:  *  what will happen.
                    345:  */
                    346: 
                    347: static int is_154x(haport)
                    348: unsigned haport;
                    349: {
                    350:        char    buf[4],
                    351:                        *p;
                    352:        int      ch,
                    353:                        oldhaport,
                    354:                        s,
                    355:                        r = 0;
                    356: 
                    357:        oldhaport = AHABASE;
                    358:        s = sphi();
                    359:        AHABASE = haport;
                    360:        if (haidle() && puthabyte(HAINQUIRY)) {
                    361:                for (p = buf; p < buf + sizeof(buf); ++p) {
                    362:                        ch = gethabyte();
                    363:                        if (ch == TIMEOUT)
                    364:                                break;
                    365:                        else
                    366:                                *p = ch;
                    367:                }
                    368:                if (p >= buf + sizeof(buf)) {
                    369:                        outb(CTRLREG, IRST);
                    370:                        if ((pollset(STSREG, IDLE, 350) & IDLE) == IDLE) {
                    371:                                if (buf[0] == '\0') {
                    372:                                        printf("AHA-1540 with 16 Head BIOS Detected\n");
                    373:                                        /* SDS_HDS = 16; Should we? */
                    374:                                }
                    375:                                r = 1;
                    376:                        }
                    377:                }
                    378:        }
                    379:        AHABASE = oldhaport;
                    380:        spl(s);
                    381:        return r;
                    382: }   /* is_154x() */
                    383: 
                    384: /***********************************************************************
                    385:  *  hareset()
                    386:  *
                    387:  *  Reset the host adapter and leave it ready for operation.
                    388:  */
                    389: 
                    390: static int hareset()
                    391: 
                    392: {
                    393:        paddr_t mbaddr;  /* Mail box array's paddr. */
                    394:        int      mbiok,   /* Mail box initialization proceding ok */
                    395:                        stsreg,  /* local copy of STSREG */
                    396:                        retval,  /* return value */
                    397:                        s;
                    398: 
                    399:        retval = 0;
                    400:        s = sphi();
                    401:        outb(CTRLREG, SRST);
                    402:        if ((stsreg = pollclr(STSREG, STST, 350)) == TIMEOUT)
                    403:                printf("AHA-154x: Reset failed, host adapter stuck.\n");
                    404:        else
                    405: #ifdef LOUIS_HACK
                    406:        printf("Resetting - stsreg: 0x%x\n", stsreg);
                    407: #endif
                    408:                if ((stsreg & DIAGF) || (stsreg & (INIT | IDLE)) != (INIT | IDLE))
                    409:                        printf("AHA-154x: Reset/diagnostics failed.\n");
                    410:                else {
                    411: 
                    412:                mbaddr = vtop(&mb);
                    413: #ifdef LOUIS_HACK
                    414:        printf("init commands bytes will be:\n");
                    415:        printf(" MBINIT: 0x%x, COUNT: 0x%x, ADDR_MSB: 0x%x, ADDR_2: 0x%x, ADDR_LSB: 0x%x\n", \
                    416:                MBINIT, (sizeof(mb) / (sizeof(mbo_t) + sizeof(mbi_t))), ((unsigned char *) &mbaddr)[2], \
                    417:                ((unsigned char *) &mbaddr)[1], ((unsigned char *) &mbaddr)[0]);
                    418: #endif 
                    419:                        mbiok = 1;
                    420:                        mbiok &= puthabyte(MBINIT);
                    421:                        mbiok &= puthabyte(sizeof(mb) / (sizeof(mbo_t) + sizeof(mbi_t)));
                    422:                        mbiok &= puthabyte(((unsigned char *) &mbaddr)[2]);
                    423:                        mbiok &= puthabyte(((unsigned char *) &mbaddr)[1]);
                    424:                        mbiok &= puthabyte(((unsigned char *) &mbaddr)[0]);
                    425:                        if (!mbiok || !hacc())
                    426:                                printf("AHA-154x: Mailbox initialization failed.\n");
                    427:                        else
                    428:                                retval = 1;
                    429:                }
                    430:        spl(s);
                    431:        return retval;
                    432: }   /* hareset() */
                    433: 
                    434: /***********************************************************************
                    435:  *  dmacascade()
                    436:  *
                    437:  *  Set the selected (AHADMACHAN) dma channel to cascade mode.
                    438:  */
                    439: 
                    440: static void dmacascade()
                    441: 
                    442: {
                    443:        int dmaporta, dmaportb, s;
                    444: 
                    445:        s = sphi();
                    446:        if (AHADMACHAN == 0) {
                    447:                dmaporta = 0x0b;
                    448:                dmaportb = 0x0a;
                    449:        } else {
                    450:                dmaporta = 0xd6;
                    451:                dmaportb = 0xd4;
                    452:        }
                    453:        outb(dmaporta, 0xc0 | (AHADMACHAN & 3));
                    454:        outb(dmaportb, (AHADMACHAN & 3));
                    455:        spl(s);
                    456: }   /* dmacascade() */
                    457: 
                    458: /***********************************************************************
                    459:  *  checkmail()
                    460:  *
                    461:  *  Check the incoming mailboxes for messages.  Do this on any Mail
                    462:  *  Box In Full interrupt and before you fail a command for timeout.
                    463:  *  The code to determine which target device finished by tid is a
                    464:  *  bit tricky and relies on the following assumptions:
                    465:  *
                    466:  *       1)  The host adapter is installed in a Intel (big-endian)
                    467:  *               machine. Believe it or not there is (are) non-Intel CPU
                    468:  *               ISA bus machines. and the one that I know of is a M68000
                    469:  *               machine where this would not work.
                    470:  *
                    471:  *       2)  The kernel's data space is physically contiguous and is
                    472:  *               never swapped out.
                    473:  */
                    474: 
                    475: static int checkmail()
                    476: 
                    477: {
                    478:        static int startid = 0;
                    479:        int msgs = 0;
                    480:        int sts;
                    481:        int s;
                    482:        register int id;
                    483:        register srb_p r;
                    484:        register int i = startid;
                    485: 
                    486:        do {
                    487:                if (mb. i[i]. sts != MBIFREE) {
                    488:                        s = sphi();
                    489:                        sts = mb. i[i]. sts;
                    490:                        flip(mb. i[i]. ccbaddr);
                    491:                        id = (unsigned) ((mb. i[i]. ccbaddr & 0x00ffffffL) - ccbbase) / sizeof(haccb_t);
                    492:                        if (r = actv[id]) {
                    493:                                switch (sts) {
                    494:                                case MBIABRTFLD:
                    495:                                        devmsg(r->dev, "Command 0x%x abort failed\n", r->cdb. g0. opcode);
                    496:                                case MBISUCCESS:
                    497:                                case MBIERROR:
                    498:                                        r->status = ccb[id]. trgtsts;
                    499:                                        break;
                    500:                                case MBIABORTED:
                    501:                                        devmsg(r->dev, "Command 0x%x aborted successfully\n", r->cdb. g0. opcode);
                    502:                                        r->status = ST_DRVABRT;
                    503:                                        break;
                    504:                                default:
                    505:                                        printf("Host Adapter Mailbox In value corrupted\n");
                    506:                                        break;
                    507:                                }
                    508: 
                    509:                                actv[id] = NULL;
                    510:                                if (r->cleanup)
                    511:                                        (*(r->cleanup))(r);
                    512:                                msgs |= bit(id);
                    513:                        }
                    514:                        mb. i[i]. ccbaddr = 0;
                    515:                        spl(s);
                    516:                }
                    517:                else if (msgs)
                    518:                        break;
                    519:                i = (i + 1) & 7;
                    520:        } while (i != startid);
                    521:        startid = i;
                    522: 
                    523:        return msgs;
                    524: }   /* checkmail() */
                    525: 
                    526: /***********************************************************************
                    527:  *  Driver Interface Functions
                    528:  */
                    529: 
                    530: /***********************************************************************
                    531:  *  hatimer()
                    532:  *
                    533:  *  Host adapter Timeout handler.
                    534:  */
                    535: 
                    536: void hatimer()
                    537: 
                    538: {
                    539:        register int    id;
                    540:        register srb_p  r;
                    541:        register int    active;
                    542:        int                      s;
                    543: 
                    544:        s = sphi();
                    545:        checkmail();            /* Cleanup any missed interrupts, etc. */
                    546:        active = 0;
                    547:        for (id = 0; id < MAXDEVS; ++id) {
                    548:                if ((r = actv[id]) != NULL && r->timeout != 0) {
                    549:                        if (--r->timeout == 0) {
                    550:                                abortscsi(r);
                    551:                                r->status = ST_DRVABRT;
                    552:                        }
                    553:                        else
                    554:                                active = 1;
                    555:                }
                    556:        }
                    557:        drvl[SCSIMAJOR]. d_time = active;
                    558:        spl(s);
                    559: }   /* hatimer() */
                    560: 
                    561: /***********************************************************************
                    562:  *  haintr()
                    563:  *
                    564:  *  SCSI interrupt handler for host adapter.
                    565:  */
                    566: 
                    567: void haintr()
                    568: 
                    569: {
                    570:        int intrflgs;
                    571: 
                    572:        intrflgs = inb(INTRFLGS);
                    573:        if (intrflgs & ANYINTR)
                    574:                outb(CTRLREG, IRST);
                    575: 
                    576:        if (hastate == ST_HAINIT)
                    577:                return;
                    578:        if (intrflgs & MBIF) {
                    579:                checkmail();
                    580:                return;
                    581:        }
                    582: }   /* haintr() */
                    583: 
                    584: /***********************************************************************
                    585:  *  hainit()
                    586:  *
                    587:  *  Initialize the host adapter for operation.
                    588:  */
                    589: 
                    590: int hainit()
                    591: 
                    592: {
                    593:        register int i;
                    594: 
                    595:        hastate = ST_HAINIT;
                    596:        hapresent = 0;
                    597:        printf("Host Adapter Module: AHA-154x v1.1\n");
                    598:        if (!is_154x(AHABASE)) {
                    599:                printf("hainit() failed: Adaptec AHA-154x not found.\n");
                    600:                return 0;
                    601:        }
                    602: 
                    603:        setivec(AHAINTR, haintr);
                    604:        if (!(hapresent = hareset())) {
                    605:                printf("hainit() failed: Could not initialize AHA-154x at (0x%x)\n", AHABASE);
                    606:                return 0;
                    607:        }
                    608: 
                    609:        for (i = 0; i < MAXDEVS; ++i) {
                    610:                actv[i] = NULL;
                    611:                mb. o[i]. ccbaddr = vtop(ccb + i);
                    612:                flip(mb. o[i]. ccbaddr);
                    613:                mb. o[i]. cmd = MBOFREE;
                    614:        }
                    615:        ccbbase = vtop(ccb);
                    616:        dmacascade();
                    617:        hastate = ST_HAIDLE;
                    618:        return 1;
                    619: }   /* hainit() */
                    620: 
                    621: /***********************************************************************
                    622:  *  mkdslist()
                    623:  *
                    624:  *  Make an Adaptec Data Segment list for a Scatter/Gather Request.
                    625:  *  Input:       d - the memory area for the Scatter/Gather List.
                    626:  *                       b - the bufaddr structure for the memory block.
                    627:  */
                    628: 
                    629: static int mkdslist(d, b)
                    630: register dsentry_p  d;
                    631: bufaddr_p                 b;
                    632: {
                    633:        paddr_t                          p_start;
                    634:        size_t                            p_size;
                    635:        paddr_t                          p_next;
                    636:        int                                      segments = 1;
                    637:        register unsigned long  start;
                    638:        register unsigned long  end;
                    639:        dsentry_p                          l = d;
                    640: 
                    641:        switch (b->space) {
                    642:        case KRNL_ADDR:  /* Kernal Address */
                    643:        case USER_ADDR:  /* User Address (Anything goes) */
                    644:                start = b->addr. caddr;
                    645:                p_start = vtop(start);
                    646:                break;
                    647:        case SYSGLBL_ADDR:  /* System Global address (yeah) */
                    648:                start = b->addr. paddr;
                    649:                p_start = P2P(start);
                    650:                break;
                    651:        case PHYS_ADDR:  /* Physical Address - (who knows) */
                    652:        default:
                    653:                return 0;
                    654:        }
                    655:        end = start + b->size;
                    656:        p_size  = min(NBPC - (p_start & (NBPC - 1)), end - start);
                    657: 
                    658:        for ( ; ; ) {
                    659:                d->size[2] = ((unsigned char *) &p_size)[0];
                    660:                d->size[1] = ((unsigned char *) &p_size)[1];
                    661:                d->size[0] = ((unsigned char *) &p_size)[2];
                    662:                d->addr[2] = ((unsigned char *) &p_start)[0];
                    663:                d->addr[1] = ((unsigned char *) &p_start)[1];
                    664:                d->addr[0] = ((unsigned char *) &p_start)[2];
                    665:                if (start + p_size >= end)
                    666:                        return segments;
                    667: 
                    668:                p_next = (b->space == SYSGLBL_ADDR) ? P2P(start + p_size) :
                    669:                                                                                          vtop(start + p_size);
                    670:                if (p_next == p_start + p_size)
                    671:                        /* Continue Last Segment */
                    672:                        p_size += min(NBPC, end - start - p_size);
                    673:                else {
                    674:                        /* Start New Segment */
                    675:                        p_start = p_next;
                    676:                        start += p_size;
                    677:                        p_size = min(NBPC, end - start);
                    678:                        ++d;
                    679:                        if (++segments > (sizeof(dslist_t) / sizeof(dsentry_t)))
                    680:                                return 0;
                    681:                }
                    682:        }
                    683: }   /* mkdslist() */
                    684: 
                    685: /***********************************************************************
                    686:  *  startscsi()
                    687:  *
                    688:  *  Send a SCSI CDB to a target device on the bus.
                    689:  */
                    690: 
                    691: int startscsi(r)
                    692: register srb_p   r;
                    693: {
                    694:        register haccb_p        c;
                    695:        paddr_t                  bufaddr;
                    696:        size_t                    datalen;
                    697:        register int            s;
                    698: 
                    699:        if (r->target >= MAXDEVS || r->lun >= MAXUNITS) {
                    700:                printf("Illegal device ID: %d LUN: %d", r->target, r->lun);
                    701:                return 0;
                    702:        }
                    703: 
                    704:        ++r->tries;
                    705:        if (actv[r->target]) {
                    706:                devmsg(r->dev,
                    707:                           "Device busy: old opcode (0x%x) new opcode (0x%x)",
                    708:                           ccb[r->target]. cdb. g0. opcode,
                    709:                           r->cdb. g0. opcode);
                    710:                return 0;
                    711:        }
                    712: 
                    713:        s = sphi();
                    714:        r->status = ST_PENDING;
                    715:        c = ccb + r->target;
                    716:        memset(c, 0, sizeof(haccb_t));
                    717:        c->opcode = 0;                    /* Start SCSI CDB */
                    718:        c->addrctrl = (r->target << 5) | (r->lun & 7);
                    719:        if (r->xferdir & DMAREAD)  c->addrctrl |= 0x08;
                    720:        if (r->xferdir & DMAWRITE) c->addrctrl |= 0x10;
                    721:        c->cdblen = cpycdb(&(c->cdb), &(r->cdb));
                    722:        c->senselen = 1;
                    723: 
                    724: /***********************************************************************
                    725:  *  Set up the CCB's Address here. This turned out to be a bit more
                    726:  *  complicated than I thought it would be.
                    727:  */
                    728: 
                    729:        if (r->buf. space == PHYS_ADDR) {
                    730:                c->datalen[0] = ((unsigned char *) &(r->buf. size))[2];
                    731:                c->datalen[1] = ((unsigned char *) &(r->buf. size))[1];
                    732:                c->datalen[2] = ((unsigned char *) &(r->buf. size))[0];
                    733:                c->bufaddr[0] = ((unsigned char *) &(r->buf. addr. paddr))[2];
                    734:                c->bufaddr[1] = ((unsigned char *) &(r->buf. addr. paddr))[1];
                    735:                c->bufaddr[2] = ((unsigned char *) &(r->buf. addr. paddr))[0];
                    736:        }
                    737:        else {
                    738:                datalen = mkdslist(ds[r->target]. entries, &(r->buf));
                    739:                if (datalen == 0) {
                    740:                        printf("SCSI ID %d - Bad Scatter/Gather list\n", r->target);
                    741:                        spl(s);
                    742:                        return 0;
                    743:                }
                    744:                else if (datalen == 1)
                    745:                        memcpy(c->datalen, ds[r->target]. entries, 6);
                    746:                else {
                    747:                        c->opcode = 2;
                    748:                        bufaddr = vtop(ds[r->target]. entries);
                    749:                        datalen *= 6;
                    750:                        c->datalen[0] = ((unsigned char *) &datalen)[2];
                    751:                        c->datalen[1] = ((unsigned char *) &datalen)[1];
                    752:                        c->datalen[2] = ((unsigned char *) &datalen)[0];
                    753:                        c->bufaddr[0] = ((unsigned char *) &bufaddr)[2];
                    754:                        c->bufaddr[1] = ((unsigned char *) &bufaddr)[1];
                    755:                        c->bufaddr[2] = ((unsigned char *) &bufaddr)[0];
                    756:                }
                    757:        }
                    758: 
                    759:        mb. o[r->target]. cmd = MBOSTART;
                    760:        if (puthabyte(STARTSCSI) && (inb(STSREG) & INVDCMD) == 0) {
                    761:                actv[r->target] = r;
                    762:                if (r->timeout)
                    763:                        drvl[SCSIMAJOR]. d_time = 1;
                    764:        }
                    765:        else {
                    766:                printf("startscsi() failed: Resetting host adapter.\n");
                    767:                mb. o[r->target]. cmd = MBOFREE;
                    768:                actv[r->target] = NULL;
                    769:                r->status = ST_DRVABRT;
                    770:                if (r->cleanup)
                    771:                        (*r->cleanup)(r);
                    772:                hapresent = hareset();
                    773:                return 0;
                    774:        }
                    775: 
                    776:        spl(s);
                    777:        return 1;
                    778: }   /* startscsi() */
                    779: 
                    780: /***********************************************************************
                    781:  *  abortscsi()
                    782:  *
                    783:  *  Abort the SCSI Command at a target device on the bus.
                    784:  */
                    785: 
                    786: void abortscsi(r)
                    787: register srb_p   r;
                    788: {
                    789:        int s,
                    790:                tries;
                    791: 
                    792:        printf("abortscsi(id: %d opcode: (0x%x))\n", r->target, r->cdb. g0. opcode);
                    793:        s = sphi();
                    794:        r->timeout = 0;
                    795:        for (tries = 10; hapresent && tries > 0; --tries) {
                    796:                mb. o[r->target]. cmd = MBOABORT;
                    797:                if (puthabyte(STARTSCSI) && (inb(STSREG) & INVDCMD) == 0)
                    798:                        break;
                    799: 
                    800:                printf("abortscsi(): AHA-154x Command start failed.\n");
                    801:                hapresent = hareset();
                    802:        }
                    803: 
                    804:        if (tries <= 0)
                    805:                printf("abortscsi() failed: Cannot reach host adapter\n");
                    806:        else {
                    807:                busyWait(checkmail, 1000);
                    808: 
                    809:                if (r->status == ST_PENDING) {
                    810:                        printf("abortscsi() failed: id %d\n", r->target);
                    811:                        resetdevice(r->target);
                    812: 
                    813:                        actv[r->target] = NULL;
                    814:                        r->status = ST_DRVABRT;
                    815:                        if (r->cleanup)
                    816:                                (*r->cleanup)(r);
                    817:                }
                    818:        }
                    819: 
                    820:        spl(s);
                    821: }   /* abortscsi() */
                    822: 
                    823: /***********************************************************************
                    824:  *  resetdevice()
                    825:  *
                    826:  *  Reset a SCSI target.
                    827:  */
                    828: 
                    829: void resetdevice(id)
                    830: register int id;
                    831: {
                    832:        register haccb_p        c = &(ccb[HAI_HAID]);
                    833:        int                              tries;
                    834: 
                    835:        c->opcode = 0x81;
                    836:        c->addrctrl = (id << 5);
                    837:        for (tries = 10; tries > 0; --tries) {
                    838:                if (!hapresent)
                    839:                        hapresent = hareset();
                    840:                if (hapresent) {
                    841:                        mb. o[HAI_HAID]. cmd = MBOSTART;
                    842:                        if (puthabyte(STARTSCSI) && (inb(STSREG) & INVDCMD) == 0)
                    843:                                break;
                    844:                }
                    845:        }
                    846: }   /* resetdevice() */
                    847: 
                    848: /***********************************************************************
                    849:  *  haihdgeta()         --  Get disk driver paramters.
                    850:  *  
                    851:  *     This function is provided to support the HDGETA/HDSETA I/O Controls
                    852:  *  so you don't need the old Adaptec SCSI driver to set up the partition
                    853:  *  table on initial setup.  There is a catch-22 with this.  You need
                    854:  *  to know the drive's geometry in order to set up the partition table
                    855:  *  but cannot get the drive's geometry until you have set up the partition
                    856:  *  table.  We solve this by using the drive's size and then dividing
                    857:  *  down based upon SDS_HDS heads and SDS_SPT sectors per track.  Every
                    858:  *  host adapter will want to do this differently.  The Adaptec solution
                    859:  *  is the best that I've seen so far. (It allows you to use Huge (1.0
                    860:  *  GB) disks under DOS without trouble.
                    861:  */
                    862: 
                    863: void haihdgeta(hdp, diskcap)
                    864: register hdparm_t   *hdp;
                    865: register unsigned   diskcap;
                    866: {
                    867:        unsigned short  ncyl = (unsigned short) (diskcap / (HAI_SD_HDS * HAI_SD_SPT)),
                    868:                                        landc = ncyl,
                    869:                                        rwccp = 0xffff,
                    870:                                        wpcc = 0xffff;
                    871: 
                    872:        memset(hdp, 0, sizeof(hdparm_t));
                    873:        *((unsigned short *) hdp->ncyl) = ncyl;
                    874:        *((unsigned short *) hdp->rwccp) = rwccp;
                    875:        *((unsigned short *) hdp->wpcc) = wpcc;
                    876:        *((unsigned short *) hdp->landc) = landc;
                    877: 
                    878:        hdp->nhead = HAI_SD_HDS;
                    879:        if (hdp->nhead > 8)
                    880:                hdp->ctrl |= 8;
                    881:        hdp->nspt = HAI_SD_SPT;
                    882: }   /* haihdseta() */
                    883: 
                    884: /***********************************************************************
                    885:  *  haihdseta()         --  Set disk parameters in accordance with HDSETA
                    886:  *                                       I/O Control.
                    887:  *  
                    888:  *  Set the disk paramters accordingly for a request from the fdisk
                    889:  *  program.  This call really doesn't do anything on the adaptec or
                    890:  *  in the SCSI driver in general because SCSI Disks use Logical Block
                    891:  *  addressing rather than Cylinder/Head/Track addressing found with
                    892:  *  less intelligent Disk drive types.  What this will do is allow
                    893:  *  the fdisk program to work so a user can format his disk and install
                    894:  *  Coherent on it (A Good Thing).  This boils down to a fancy way to
                    895:  *  patch SDS_HDS and SDS_SPT.
                    896:  */
                    897: 
                    898: void haihdseta(hdp)
                    899: register hdparm_t *hdp;
                    900: {
                    901:        HAI_SD_HDS = hdp->nhead;
                    902:        HAI_SD_SPT = hdp->nspt;
                    903: }   /* haihdseta() */
                    904: 
                    905: /* End of file */

unix.superglobalmegacorp.com

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