Annotation of coherent/b/STREAMS/io.386/haiAha.c, revision 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.