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

1.1       root        1: /***********************************************************************
                      2:  *  Module: aha154x.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: Fri Jun  4 20:03:17 1993 by [chris]
                     19:  */
                     20: 
                     21: #define _COH_HA_                /* Host Adaptor Module */
                     22: 
                     23: #include <stddef.h>
                     24: #include <sys/coherent.h>
                     25: #include <sys/con.h>
                     26: #include <sys/types.h>
                     27: 
                     28: #include <sys/haiscsi.h>
                     29: 
                     30: /***********************************************************************
                     31:  *  Constants - Patch for your own circumstances.
                     32:  */
                     33: 
                     34: unsigned short  AHABASE =       0x330,      /* Port Base */
                     35:                 AHAINTR =       11,         /* Host Adapter Interrupt vector */
                     36:                 AHADMACHAN =    0x05;       /* DMA Channel */
                     37: 
                     38: #define CTRLREG     (AHABASE + 0)   /* Control Register (Write) */
                     39: #define     HRST    bit(7)          /* Hard Reset */
                     40: #define     SRST    bit(6)          /* Soft Reset */
                     41: #define     IRST    bit(5)          /* Interrupt Reset */
                     42: #define     SCRST   bit(4)          /* SCSI Bus Reset */
                     43: 
                     44: #define STSREG      (AHABASE + 0)   /* Status Register (Read) */
                     45: #define     STST    bit(7)          /* Self Test in progress */
                     46: #define     DIAGF   bit(6)          /* Internal Diagnostic Failure */
                     47: #define     INIT    bit(5)          /* Mailbox Initialization Required */
                     48: #define     IDLE    bit(4)          /* SCSI Host Adapter Idle */
                     49: #define     CDF     bit(3)          /* Command/Data Out Port Full */
                     50: #define     DF      bit(2)          /* Data In Port Full */
                     51: #define     INVDCMD bit(0)          /* Invalid HA Command */
                     52: 
                     53: #define CMDDATAOUT  (AHABASE + 1)   /* Command/Data Out (Write) */
                     54: #define     NOP         0x00        /* No Operation (really?) */
                     55: #define     MBINIT      0x01        /* Mail Box Initialization */
                     56: #define     STARTSCSI   0x02        /* Start a SCSI Command */
                     57: #define     STARTBIOS   0x03        /* Start a BIOS Command */
                     58: #define     HAINQUIRY   0x04        /* HA Inquiry */
                     59: #define     ENBLMBOA    0x05        /* Enable Mailbox Out Available Interrupt */
                     60: #define     STSELTO     0x06        /* Set Selection Timeout */
                     61: #define     SETBUSON    0x07        /* Set Bus on time */
                     62: #define     SETBUSOFF   0x08        /* Set Bus off time */
                     63: #define     SETXFER     0x09        /* Set transfer speed */
                     64: #define     RETINSTDEV  0x0a        /* Return Installed Devices */
                     65: #define     RETCFGDATA  0x0b        /* Return Configuration Data */
                     66: #define     ENBLTRGTMD  0x0c        /* Enable Target Mode */
                     67: #define     RETSUDATA   0x0d        /* Return Setup Data */
                     68: 
                     69: #define DATAIN      (AHABASE + 1)
                     70: 
                     71: #define INTRFLGS    (AHABASE + 2)
                     72: #define     ANYINTR bit(7)          /* Any Interrupt */
                     73: #define     SCRD    bit(3)          /* SCSI Reset Detected */
                     74: #define     HACC    bit(2)          /* HA Command Complete */
                     75: #define     MBOA    bit(1)          /* MBO Empty */
                     76: #define     MBIF    bit(0)          /* MBI Full */
                     77: 
                     78: #define MBOFREE     0x00        /* Mailbox out is free */
                     79: #define MBOSTART    0x01        /* Start CCB in this Mailbox */
                     80: #define MBOABORT    0x02        /* Abort CCB in this Mailbox */
                     81: 
                     82: #define MBIFREE     0x00        /* Mailbox in is free */
                     83: #define MBISUCCESS  0x01        /* Mailbox's CCB Completed Successfully */
                     84: #define MBIABORTED  0x02        /* Mailbox's CCB Aborted */
                     85: #define MBIABRTFLD  0x03        /* CCB to Abort not found */
                     86: #define MBIERROR    0x04        /* CCB Completed with error */
                     87: 
                     88: #define TIMEOUT     -1          /* Timeout from pollxxx() functions. */
                     89: 
                     90: #define ST_HAINIT   0x0001      /* Host Adapter being initialized */
                     91: #define ST_HAIDLE   0x0002      /* Host Adapter is idle */
                     92: 
                     93: /***********************************************************************
                     94:  *  Types
                     95:  */
                     96: 
                     97: #pragma align 1
                     98: 
                     99: typedef union addr3_u {         /* addr3_u for big/little endian conversions */
                    100:     unsigned long   value;
                    101:     unsigned char   byteval[sizeof(unsigned long)];
                    102: } addr3_t;
                    103: 
                    104: typedef union mbo_u *mbo_p;     /* Out Box to host adapter */
                    105: 
                    106: typedef union mbo_u {
                    107:     unsigned char   cmd;
                    108:     paddr_t         ccbaddr;
                    109: } mbo_t;
                    110: 
                    111: typedef union mbi_u *mbi_p;     /* In Box from host adapter */
                    112: 
                    113: typedef union mbi_u {
                    114:     unsigned char   sts;
                    115:     paddr_t         ccbaddr;
                    116: } mbi_t;
                    117: 
                    118: typedef struct mb_s {           /* Host adapter mailbox type */
                    119:     mbo_t       o[MAXDEVS];     /* One out box for each device */
                    120:     mbi_t       i[MAXDEVS];     /* One in box for each possible reply */
                    121: } mb_t;
                    122: 
                    123: typedef struct haccb_s *haccb_p;    /* Host Adapter Command/Control Block */
                    124: 
                    125: typedef struct haccb_s {
                    126:     unsigned char   opcode;
                    127:     unsigned char   addrctrl;
                    128:     unsigned char   cdblen;
                    129:     unsigned char   senselen;
                    130:     unsigned char   datalen[3];
                    131:     unsigned char   bufaddr[3];
                    132:     unsigned char   linkaddr[3];
                    133:     unsigned char   linkid;
                    134:     unsigned char   hoststs;
                    135:     unsigned char   trgtsts;
                    136:     unsigned char   pad[2];
                    137:     cdb_t           cdb;
                    138: } haccb_t;
                    139: 
                    140: typedef struct dsentry_s *dsentry_p;
                    141: 
                    142: typedef struct dsentry_s {
                    143:     unsigned char   size[3];
                    144:     unsigned char   addr[3];
                    145: } dsentry_t;
                    146: 
                    147: typedef struct dslist_s *dslist_p;
                    148: 
                    149: typedef struct dslist_s {
                    150:     dsentry_t       entries[16];
                    151: } dslist_t;
                    152: 
                    153: #pragma align
                    154: 
                    155: /***********************************************************************
                    156:  *  Variables
                    157:  */
                    158: 
                    159: static int      hastate;                /* Host Adapter State */
                    160: static mb_t     mb;
                    161: static haccb_t  ccb[MAXDEVS];
                    162: static paddr_t  ccbbase;
                    163: static srb_p    actv[MAXDEVS];
                    164: static dslist_t ds[MAXDEVS];
                    165: 
                    166: void abortscsi();
                    167: 
                    168: /***********************************************************************
                    169:  *  Support Functions
                    170:  */
                    171: 
                    172: #define min(a, b)   (((a) <= (b)) ? (a) : (b))
                    173: 
                    174: /***********************************************************************
                    175:  *  pollclr()
                    176:  *
                    177:  *  Wait for bit(s) to clear in a port.
                    178:  */
                    179: 
                    180: static int pollclr(port, bits)
                    181: unsigned port;
                    182: unsigned bits;
                    183: 
                    184: {
                    185:     long countdown = 1000000L;
                    186:     unsigned pval;
                    187: 
                    188:     while (countdown-- > 0L) {
                    189:         pval = inb(port) & 0xff;
                    190:         if ((pval & bits) == 0)
                    191:             return (pval & ~bits);
                    192:     }
                    193:     printf("pollclr() port 0x%x stuck at 0x%x waiting for 0x%x\n", port, pval, bits);
                    194:     return TIMEOUT;
                    195: }   /* pollclr() */
                    196: 
                    197: /***********************************************************************
                    198:  *  pollset()
                    199:  *
                    200:  *  Wait for bits in port to be set.
                    201:  */
                    202: 
                    203: static int pollset(port, bits)
                    204: unsigned port;
                    205: unsigned bits;
                    206: {
                    207:     long countdown = 1000000L;
                    208:     unsigned pval;
                    209: 
                    210:     while (countdown-- > 0L) {
                    211:         pval = inb(port) & 0xff;
                    212:         if ((pval & bits) == bits)
                    213:             return pval;
                    214:     }
                    215:     printf("pollset() port 0x%x stuck at 0x%x waiting for 0x%x\n", port, pval, bits);
                    216:     return TIMEOUT;
                    217: }   /* pollset() */
                    218: 
                    219: /***********************************************************************
                    220:  *  hacc()
                    221:  *
                    222:  *  Host Adapter Command Completed - Returns 1 if last host adapter
                    223:  *  command completed without error.
                    224:  */
                    225: 
                    226: static int hacc()
                    227: 
                    228: {
                    229:     unsigned stsreg;
                    230: 
                    231:     if (pollset(INTRFLGS, HACC) == TIMEOUT) {
                    232:         printf("Timeout waiting for Host Adapter Command Complete\n");
                    233:         return 0;
                    234:     }
                    235:     stsreg = inb(STSREG) & (IDLE | INIT | CDF | INVDCMD);
                    236:     if (stsreg != IDLE) {
                    237:         printf("Host Adapter Stuck - STSREG: 0x%x\n", stsreg);
                    238:         return 0;
                    239:     }
                    240:     return 1;
                    241: }   /* hacc() */
                    242: 
                    243: /***********************************************************************
                    244:  *  haidle()
                    245:  *
                    246:  *  Returns 1 if the Idle Bit is on in the adapter status register
                    247:  */
                    248: 
                    249: #define haidle()    (pollset(STSREG, IDLE) != TIMEOUT)
                    250: 
                    251: /***********************************************************************
                    252:  *  gethabyte()
                    253:  *
                    254:  *  Get a byte from the host adapter Data In register.
                    255:  */
                    256: 
                    257: static int gethabyte()
                    258: 
                    259: {
                    260:     return (pollset(STSREG, DF) == TIMEOUT) ? TIMEOUT : (inb(DATAIN) & 0xff);
                    261: }   /* gethabyte() */
                    262: 
                    263: /***********************************************************************
                    264:  *  puthabyte()
                    265:  *
                    266:  *  Write a byte to the host adapter Command/Data Out Register.
                    267:  */
                    268: 
                    269: static int puthabyte(b)
                    270: unsigned char b;
                    271: 
                    272: {
                    273:     if (pollclr(STSREG, CDF) == TIMEOUT)
                    274:         return 0;
                    275:     else {
                    276:         outb(CMDDATAOUT, b);
                    277:         return 1;
                    278:     }
                    279: }   /* puthabyte() */
                    280: 
                    281: /***********************************************************************
                    282:  *  isaha154x()
                    283:  *
                    284:  *  Returns a string indicating the type and revision of the AHA154x
                    285:  *  host adapter on the bus if it is out there.  Caveat: if something
                    286:  *  else is out there that can respond to this message I don't know
                    287:  *  what will happen.
                    288:  */
                    289: 
                    290: static char *isaha154x(haport)
                    291: unsigned haport;
                    292: 
                    293: {
                    294:     /*                      0123456789012345678901234 */
                    295:     static char brdid[] =  "Adaptec AHA-154x# Rev: ##";
                    296:     char buf[4], *p, *idstr = NULL;
                    297:     int ch, oldhaport, s;
                    298: 
                    299:     oldhaport = AHABASE;
                    300:     s = sphi();
                    301:     AHABASE = haport;
                    302:     if (haidle() && puthabyte(HAINQUIRY)) {
                    303:         for (p = buf; p < buf + sizeof(buf); ++p) {
                    304:             ch = gethabyte();
                    305:             if (ch == TIMEOUT)
                    306:                 break;
                    307:             else
                    308:                 *p = ch;
                    309:         }
                    310:         if (p >= buf + sizeof(buf)) {
                    311:             outb(CTRLREG, IRST);
                    312:             idstr = (inb(STSREG) & IDLE != IDLE) ? NULL : brdid;
                    313:             brdid[23] = buf[2];
                    314:             brdid[24] = buf[3];
                    315:             switch (buf[0]) {   /* Board Type Byte */
                    316:                 case 'B':   /* AHA-1640 with 64 Head BIOS */
                    317:                     brdid[13] = '6';
                    318:                 case '\0':  /* AHA-1540 with 16 head BIOS */
                    319:                 case '0':   /* AHA-1540 with 64 head BIOS */
                    320:                     brdid[16] = ' ';
                    321:                     break;
                    322:                 case 'A':   /* AHA-1540B with 64 head BIOS */
                    323:                     brdid[16] = 'B';
                    324:                     break;
                    325:                 default:
                    326:                     idstr = "AHA-154x Conformant Host Adapter";
                    327:                     break;
                    328:             }
                    329:         }
                    330:     }
                    331:     AHABASE = oldhaport;
                    332:     spl(s);
                    333:     return idstr;
                    334: }   /* isaha154x() */
                    335: 
                    336: /***********************************************************************
                    337:  *  hareset()
                    338:  *
                    339:  *  Reset the host adapter and leave it ready for operation.
                    340:  */
                    341: 
                    342: static char *hareset()
                    343: 
                    344: {
                    345:     addr3_t mbaddr;
                    346:     int mbinitok, stsreg, i, s;
                    347:     char *p;
                    348: 
                    349:     if (p = isaha154x(AHABASE)) {
                    350:         s = sphi();
                    351:         outb(CTRLREG, SRST);
                    352:         if ((stsreg = pollclr(STSREG, STST)) == TIMEOUT)
                    353:             panic("SCSI: Timeout waiting for Host Adapter Initialization\n");
                    354: 
                    355:         if ((stsreg & DIAGF) || (stsreg & (INIT | IDLE)) != (INIT | IDLE))
                    356:             panic("SCSI: Host Adapter Initialization Failed.\n");
                    357: 
                    358:         memset(&mb, 0, sizeof(mb));
                    359:         mbaddr. value = vtop(&mb);
                    360:         mbinitok = 1;
                    361:         mbinitok &= puthabyte(MBINIT);
                    362:         mbinitok &= puthabyte(sizeof(mb) / (sizeof(mbo_t) + sizeof(mbi_t)));
                    363:         mbinitok &= puthabyte(mbaddr. byteval[2]);
                    364:         mbinitok &= puthabyte(mbaddr. byteval[1]);
                    365:         mbinitok &= puthabyte(mbaddr. byteval[0]);
                    366:         if (mbinitok && hacc())
                    367:             for (i = 0; i < MAXDEVS; ++i) {
                    368:                 actv[i] = NULL;
                    369:                 mb. o[i]. ccbaddr = vtop(ccb + i);
                    370:                 flip(mb. o[i]. ccbaddr);
                    371:                 mb. o[i]. cmd = MBOFREE;
                    372:             }
                    373:         else
                    374:             panic("SCSI: AHA-154XB Mailbox Initialization Failed.\n");
                    375: 
                    376:         ccbbase = vtop(ccb);
                    377:         spl(s);
                    378:     }
                    379:     return p;
                    380: }   /* hareset() */
                    381: 
                    382: /***********************************************************************
                    383:  *  dmacascade()
                    384:  *
                    385:  *  Set the selected (AHADMACHAN) dma channel to cascade mode.
                    386:  */
                    387: 
                    388: static void dmacascade()
                    389: 
                    390: {
                    391:     int dmaporta, dmaportb, s;
                    392: 
                    393:     s = sphi();
                    394:     if (AHADMACHAN == 0) {
                    395:         dmaporta = 0x0b;
                    396:         dmaportb = 0x0a;
                    397:     } else {
                    398:         dmaporta = 0xd6;
                    399:         dmaportb = 0xd4;
                    400:     }
                    401:     outb(dmaporta, 0xc0 | (AHADMACHAN & 3));
                    402:     outb(dmaportb, (AHADMACHAN & 3));
                    403:     spl(s);
                    404: }   /* dmacascade() */
                    405: 
                    406: /***********************************************************************
                    407:  *  checkmail()
                    408:  *
                    409:  *  Check the incoming mailboxes for messages.  Do this on any Mail
                    410:  *  Box In Full interrupt and before you fail a command for timeout.
                    411:  *  The code to determine which target device finished by tid is a
                    412:  *  bit tricky and relies on the following assumptions:
                    413:  *
                    414:  *      1)  The host adapter is installed in a Intel (big-endian)
                    415:  *          machine. Believe it or not there is (are) non-Intel CPU
                    416:  *          ISA bus machines. and the one that I know of is a M68000
                    417:  *          machine where this would not work.
                    418:  *
                    419:  *      2)  The kernel's data space is physically contiguous and is
                    420:  *          never swapped out.
                    421:  */
                    422: 
                    423: static int checkmail()
                    424: 
                    425: {
                    426:     static int startid = 0;
                    427:     int msgs = 0;
                    428:     int sts;
                    429:     int s;
                    430:     register int id;
                    431:     register srb_p r;
                    432:     register int i = startid;
                    433: 
                    434:     do {
                    435:         if (mb. i[i]. sts != MBIFREE) {
                    436:             s = sphi();
                    437:             sts = mb. i[i]. sts;
                    438:             flip(mb. i[i]. ccbaddr);
                    439:             id = (unsigned) ((mb. i[i]. ccbaddr & 0x00ffffffL) - ccbbase) / sizeof(haccb_t);
                    440:             if (r = actv[id]) {
                    441:                 switch (sts) {
                    442:                 case MBISUCCESS:
                    443:                 case MBIERROR:
                    444:                 case MBIABRTFLD:
                    445:                     r->status = ccb[id]. trgtsts;
                    446:                     break;
                    447:                 case MBIABORTED:
                    448:                     r->status = ST_DRVABRT;
                    449:                     break;
                    450:                 default:
                    451:                     panic("Host Adapter Mailbox In value corrupted\n");
                    452:                 }
                    453:                 actv[id] = NULL;
                    454:                 if (r->cleanup)
                    455:                     (*(r->cleanup))(r);
                    456:                 msgs |= bit(id);
                    457:             }
                    458:             mb. i[i]. ccbaddr = 0;
                    459:             spl(s);
                    460:         }
                    461:         else if (msgs)
                    462:             break;
                    463:         i = (i + 1) & 7;
                    464:     } while (i != startid);
                    465:     startid = i;
                    466: 
                    467:     return msgs;
                    468: }   /* checkmail() */
                    469: 
                    470: /***********************************************************************
                    471:  *  Driver Interface Functions
                    472:  */
                    473: 
                    474: /***********************************************************************
                    475:  *  hatimer()
                    476:  *
                    477:  *  Host adapter Timeout handler.
                    478:  */
                    479: 
                    480: void hatimer()
                    481: 
                    482: {
                    483:     register int    id;
                    484:     register srb_p  r;
                    485:     register int    active;
                    486:     int             s;
                    487: 
                    488:     s = sphi();
                    489:     checkmail();        /* Cleanup any missed interrupts, etc. */
                    490:     active = 0;
                    491:     for (id = 0; id < MAXDEVS; ++id) {
                    492:         if ((r = actv[id]) != NULL && r->timeout != 0) {
                    493:             if (--r->timeout == 0) {
                    494:                 abortscsi(r);
                    495:                 r->status = ST_DRVABRT;
                    496:             }
                    497:             else
                    498:                 active = 1;
                    499:         }
                    500:     }
                    501:     drvl[SCSIMAJOR]. d_time = active;
                    502:     spl(s);
                    503: }   /* hatimer() */
                    504: 
                    505: /***********************************************************************
                    506:  *  haintr()
                    507:  *
                    508:  *  SCSI interrupt handler for host adapter.
                    509:  */
                    510: 
                    511: void haintr()
                    512: 
                    513: {
                    514:     int intrflgs;
                    515: 
                    516:     intrflgs = inb(INTRFLGS);
                    517:     if (intrflgs & ANYINTR)
                    518:         outb(CTRLREG, IRST);
                    519: 
                    520:     if (hastate == ST_HAINIT)
                    521:         return;
                    522:     if (intrflgs & MBIF) {
                    523:         checkmail();
                    524:         return;
                    525:     }
                    526: }   /* haintr() */
                    527: 
                    528: /***********************************************************************
                    529:  *  hainit()
                    530:  *
                    531:  *  Initialize the host adapter for operation.
                    532:  */
                    533: 
                    534: int hainit()
                    535: 
                    536: {
                    537:     char *p;
                    538: 
                    539:     hastate = ST_HAINIT;
                    540:     printf("Host Adapter Module: AHA-154x v1.0.0 beta\n");
                    541:     setivec(AHAINTR, haintr);
                    542:     p = hareset();
                    543:     if (!p)
                    544:         panic("AHA154x not found or init failed at port: 0x%x\n", AHABASE);
                    545:     else
                    546:         printf("Initializing %s at port 0x%x, IRQ 0x%x, DMA 0x%x\n", p, AHABASE, AHAINTR, AHADMACHAN);
                    547: 
                    548:     dmacascade();
                    549:     hastate = ST_HAIDLE;
                    550:     return 1;
                    551: }   /* hainit() */
                    552: 
                    553: /***********************************************************************
                    554:  *  mkdslist()
                    555:  *
                    556:  *  Make an Adaptec Data Segment list for a Scatter/Gather Request.
                    557:  *  Input:      d - the memory area for the Scatter/Gather List.
                    558:  *              b - the bufaddr structure for the memory block.
                    559:  */
                    560: 
                    561: static int mkdslist(d, b)
                    562: register dsentry_p  d;
                    563: bufaddr_p           b;
                    564: {
                    565:     paddr_t                 p_start;
                    566:     size_t                  p_size;
                    567:     paddr_t                 p_next;
                    568:     int                     segments = 1;
                    569:     register unsigned long  start;
                    570:     register unsigned long  end;
                    571:     dsentry_p               l = d;
                    572: 
                    573:     switch (b->space) {
                    574:     case KRNL_ADDR:     /* Kernal Address */
                    575:     case USER_ADDR:     /* User Address (Anything goes) */
                    576:         start = b->addr. vaddr;
                    577:         p_start = vtop(start);
                    578:         break;
                    579:     case SYSGLBL_ADDR:  /* System Global address (yeah) */
                    580:         start = b->addr. paddr;
                    581:         p_start = P2P(start);
                    582:         break;
                    583:     case PHYS_ADDR:     /* Physical Address - (who knows) */
                    584:     default:
                    585:         return 0;
                    586:     }
                    587:     end = start + b->size;
                    588:     p_size  = min(NBPC - (p_start & (NBPC - 1)), end - start);
                    589: 
                    590:     for ( ; ; ) {
                    591:         d->size[2] = ((unsigned char *) &p_size)[0];
                    592:         d->size[1] = ((unsigned char *) &p_size)[1];
                    593:         d->size[0] = ((unsigned char *) &p_size)[2];
                    594:         d->addr[2] = ((unsigned char *) &p_start)[0];
                    595:         d->addr[1] = ((unsigned char *) &p_start)[1];
                    596:         d->addr[0] = ((unsigned char *) &p_start)[2];
                    597:         if (start + p_size >= end)
                    598:             return segments;
                    599: 
                    600:         p_next = (b->space == SYSGLBL_ADDR) ? P2P(start + p_size) :
                    601:                                               vtop(start + p_size);
                    602:         if (p_next == p_start + p_size)
                    603:             /* Continue Last Segment */
                    604:             p_size += min(NBPC, end - start - p_size);
                    605:         else {
                    606:             /* Start New Segment */
                    607:             p_start = p_next;
                    608:             start += p_size;
                    609:             p_size = min(NBPC, end - start);
                    610:             ++d;
                    611:             if (++segments > (sizeof(dslist_t) / sizeof(dsentry_t)))
                    612:                 return 0;
                    613:         }
                    614:     }
                    615: }   /* mkdslist() */
                    616: 
                    617: /***********************************************************************
                    618:  *  startscsi()
                    619:  *
                    620:  *  Send a SCSI CDB to a target device on the bus.
                    621:  */
                    622: 
                    623: int startscsi(r)
                    624: register srb_p   r;
                    625: {
                    626:     register haccb_p    c;
                    627:     paddr_t             bufaddr;
                    628:     size_t              datalen;
                    629:     register int        s;
                    630: 
                    631:     if (r->target >= MAXDEVS || r->lun >= MAXUNITS) {
                    632:         printf("Illegal device ID: %d LUN: %d", r->target, r->lun);
                    633:         return 0;
                    634:     }
                    635: 
                    636:     ++r->tries;
                    637:     if (actv[r->target]) {
                    638:         devmsg(r->dev, "Device busy: opcode (0x%x)", r->cdb. g0. opcode);
                    639:         return 0;
                    640:     }
                    641: 
                    642:     s = sphi();
                    643:     r->status = ST_PENDING;
                    644:     c = ccb + r->target;
                    645:     memset(c, 0, sizeof(haccb_t));
                    646:     c->opcode = 0;              /* Start SCSI CDB */
                    647:     c->addrctrl = (r->target << 5) | (r->lun & 7);
                    648:     if (r->xferdir & DMAREAD)  c->addrctrl |= 0x08;
                    649:     if (r->xferdir & DMAWRITE) c->addrctrl |= 0x10;
                    650:     c->cdblen = cpycdb(&(c->cdb), &(r->cdb));
                    651:     c->senselen = 1;
                    652: 
                    653: /***********************************************************************
                    654:  *  Set up the CCB's Address here. This turned out to be a bit more
                    655:  *  complicated than I thought it would be.
                    656:  */
                    657: 
                    658:     if (r->buf. space == PHYS_ADDR) {
                    659:         c->datalen[0] = ((unsigned char *) &(r->buf. size))[2];
                    660:         c->datalen[1] = ((unsigned char *) &(r->buf. size))[1];
                    661:         c->datalen[2] = ((unsigned char *) &(r->buf. size))[0];
                    662:         c->bufaddr[0] = ((unsigned char *) &(r->buf. addr. paddr))[2];
                    663:         c->bufaddr[1] = ((unsigned char *) &(r->buf. addr. paddr))[1];
                    664:         c->bufaddr[2] = ((unsigned char *) &(r->buf. addr. paddr))[0];
                    665:     }
                    666:     else {
                    667:         datalen = mkdslist(ds[r->target]. entries, &(r->buf));
                    668:         if (datalen == 0) {
                    669:             printf("SCSI ID %d - Bad Scatter/Gather list\n", r->target);
                    670:             spl(s);
                    671:             return 0;
                    672:         }
                    673:         else if (datalen == 1)
                    674:             memcpy(c->datalen, ds[r->target]. entries, 6);
                    675:         else {
                    676:             c->opcode = 2;
                    677:             bufaddr = vtop(ds[r->target]. entries);
                    678:             datalen *= 6;
                    679:             c->datalen[0] = ((unsigned char *) &datalen)[2];
                    680:             c->datalen[1] = ((unsigned char *) &datalen)[1];
                    681:             c->datalen[2] = ((unsigned char *) &datalen)[0];
                    682:             c->bufaddr[0] = ((unsigned char *) &bufaddr)[2];
                    683:             c->bufaddr[1] = ((unsigned char *) &bufaddr)[1];
                    684:             c->bufaddr[2] = ((unsigned char *) &bufaddr)[0];
                    685:         }
                    686:     }
                    687: 
                    688:     mb. o[r->target]. cmd = MBOSTART;
                    689:     if (puthabyte(STARTSCSI) && (inb(STSREG) & INVDCMD) == 0) {
                    690:         actv[r->target] = r;
                    691:         if (r->timeout)
                    692:             drvl[SCSIMAJOR]. d_time = 1;
                    693:     }
                    694:     else
                    695:         panic("startscsi(): AHA-154x Command Start Failure\n");
                    696: 
                    697:     spl(s);
                    698:     return 1;
                    699: }   /* startscsi() */
                    700: 
                    701: /***********************************************************************
                    702:  *  abortscsi()
                    703:  *
                    704:  *  Abort the SCSI Command at a target device on the bus.
                    705:  */
                    706: 
                    707: void abortscsi(r)
                    708: register srb_p   r;
                    709: {
                    710:     int s,
                    711:         spin;
                    712: 
                    713:     printf("abortscsi(id: %d opcode: (0x%x)\n", r->target, r->cdb. g0. opcode);
                    714:     s = sphi();
                    715:     r->timeout = 0;
                    716:     mb. o[r->target]. cmd = MBOABORT;
                    717:     if (!puthabyte(STARTSCSI) || (inb(STSREG) & INVDCMD) != 0)
                    718:         panic("abortscsi(): AHA-154x Command Start Failure\n");
                    719: 
                    720:     spin = 0x200001;
                    721:     while (r->status == ST_PENDING && --spin > 0L)
                    722:         if ((spin & 0xFFF) == 0)
                    723:             checkmail();
                    724: 
                    725:     if (r->status == ST_PENDING) {
                    726:         if (r->xferdir == DMAREAD &&
                    727:             r->buf. space != KRNL_ADDR &&
                    728:             r->buf. size > 0)
                    729:             panic("abortscsi failed at id: %d\n", r->target);
                    730:         else {
                    731:             actv[r->target] = NULL;
                    732:             r->status = ST_DRVABRT;
                    733:             if (r->cleanup)
                    734:                 (*r->cleanup)(r);
                    735:         }
                    736:     }
                    737:     spl(s);
                    738: }   /* abortscsi() */
                    739: 
                    740: /***********************************************************************
                    741:  *  resetdevice()
                    742:  *
                    743:  *  Reset a SCSI target.  This is not used yet so it isn't coded but if
                    744:  *  you need to use it all you need to do is set up a CCB with opcode =
                    745:  *  0x81. Then send it to the Host Adapter.  It will do the rest.
                    746:  */
                    747: 
                    748: int resetdevice(id)
                    749: int id;
                    750: {
                    751:     panic("resetdevice() Called for ID: %d\n", id);
                    752: }   /* resetdevice() */
                    753: 
                    754: /* 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.