Annotation of Net2/arch/i386/isa/aha1742.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Written by Julian Elischer ([email protected])
        !             3:  * for TRW Financial Systems for use under the MACH(2.5) operating system.
        !             4:  *
        !             5:  * TRW Financial Systems, in accordance with their agreement with Carnegie
        !             6:  * Mellon University, makes this software available to CMU to distribute
        !             7:  * or use in any manner that they see fit as long as this message is kept with
        !             8:  * the software. For this reason TFS also grants any other persons or
        !             9:  * organisations permission to use or modify this software.
        !            10:  *
        !            11:  * TFS supplies this software to be publicly redistributed
        !            12:  * on the understanding that TFS is not responsible for the correct
        !            13:  * functioning of this software in any circumstances.
        !            14:  *
        !            15:  *
        !            16:  * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
        !            17:  * --------------------         -----   ----------------------
        !            18:  * CURRENT PATCH LEVEL:         1       00098
        !            19:  * --------------------         -----   ----------------------
        !            20:  *
        !            21:  * 16 Feb 93   Julian Elischer         ADDED for SCSI system
        !            22:  * commenced: Sun Sep 27 18:14:01 PDT 1992
        !            23:  */
        !            24: 
        !            25: #include <sys/types.h>
        !            26: #include <ahb.h>
        !            27: 
        !            28: #include <sys/param.h>
        !            29: #include <sys/systm.h>
        !            30: #include <sys/errno.h>
        !            31: #include <sys/ioctl.h>
        !            32: #include <sys/buf.h>
        !            33: #include <sys/proc.h>
        !            34: #include <sys/user.h>
        !            35: 
        !            36: #ifdef  MACH    /* EITHER CMU OR OSF */
        !            37: #include <i386/ipl.h>
        !            38: #include <i386at/scsi.h>
        !            39: #include <i386at/scsiconf.h>
        !            40: 
        !            41: #ifdef  OSF     /* OSF ONLY */
        !            42: #include <sys/table.h>
        !            43: #include <i386/handler.h>
        !            44: #include <i386/dispatcher.h>
        !            45: #include <i386/AT386/atbus.h>
        !            46: 
        !            47: #else   OSF     /* CMU ONLY */
        !            48: #include <i386at/atbus.h>
        !            49: #include <i386/pio.h>
        !            50: #endif  OSF
        !            51: #endif  MACH    /* end of MACH specific */
        !            52: 
        !            53: #ifdef  __386BSD__      /* 386BSD specific */
        !            54: #define isa_dev isa_device
        !            55: #define dev_unit id_unit
        !            56: #define dev_addr id_iobase
        !            57: 
        !            58: #include <i386/include/pio.h>
        !            59: #include <i386/isa/isa_device.h>
        !            60: #include <scsi/scsi_all.h>
        !            61: #include <scsi/scsiconf.h>
        !            62: #endif  __386BSD__
        !            63: 
        !            64: /**/
        !            65: 
        !            66: #ifdef  __386BSD__
        !            67: #ifdef DDB
        !            68: int     Debugger();
        !            69: #else 
        !            70: #define Debugger() panic("should call debugger here (adaptec.c)")
        !            71: #endif  /*DDB*/
        !            72: #endif  __386BSD__
        !            73: 
        !            74: #ifdef  MACH
        !            75: int     Debugger();
        !            76: #endif  MACH
        !            77: 
        !            78: typedef unsigned long int physaddr;
        !            79: 
        !            80: #ifdef        MACH
        !            81: extern physaddr kvtophys();
        !            82: #define PHYSTOKV(x)   phystokv(x)
        !            83: #define KVTOPHYS(x)   kvtophys(x)
        !            84: #endif MACH
        !            85: 
        !            86: #ifdef        __386BSD__
        !            87: #define PHYSTOKV(x)   (x | 0xFE000000)
        !            88: #define KVTOPHYS(x)   vtophys(x)
        !            89: #endif        __386BSD__
        !            90: 
        !            91: extern int delaycount;  /* from clock setup code */
        !            92: #define        NUM_CONCURRENT  16      /* number of concurrent ops per board */
        !            93: #define        AHB_NSEG        33      /* number of dma segments supported     */
        !            94: #define FUDGE(X)       (X>>1)  /* our loops are slower than spinwait() */
        !            95: /**/
        !            96: /***********************************************************************\
        !            97: * AHA1740 standard EISA Host ID regs  (Offset from slot base)          *
        !            98: \***********************************************************************/
        !            99: #define HID0           0xC80 /* 0,1: msb of ID2, 3-7: ID1      */
        !           100: #define HID1           0xC81 /* 0-4: ID3, 4-7: LSB ID2         */
        !           101: #define HID2           0xC82 /* product, 0=174[20] 1 = 1744    */
        !           102: #define HID3           0xC83 /* firmware revision              */
        !           103: 
        !           104: #define CHAR1(B1,B2) (((B1>>2) & 0x1F) | '@')
        !           105: #define CHAR2(B1,B2) (((B1<<3) & 0x18) | ((B2>>5) & 0x7)|'@')
        !           106: #define CHAR3(B1,B2) ((B2 & 0x1F) | '@')
        !           107: 
        !           108: /* AHA1740 EISA board control registers (Offset from slot base) */
        !           109: #define        EBCTRL          0xC84
        !           110: #define  CDEN          0x01
        !           111: /***********************************************************************\
        !           112: * AHA1740 EISA board mode registers (Offset from slot base)            *
        !           113: \***********************************************************************/
        !           114: #define PORTADDR       0xCC0
        !           115: #define         PORTADDR_ENHANCED      0x80
        !           116: #define BIOSADDR       0xCC1
        !           117: #define        INTDEF          0xCC2
        !           118: #define        SCSIDEF         0xCC3
        !           119: #define        BUSDEF          0xCC4
        !           120: #define        RESV0           0xCC5
        !           121: #define        RESV1           0xCC6
        !           122: #define        RESV2           0xCC7
        !           123: /**** bit definitions for INTDEF ****/
        !           124: #define        INT9    0x00
        !           125: #define        INT10   0x01
        !           126: #define        INT11   0x02
        !           127: #define        INT12   0x03
        !           128: #define        INT14   0x05
        !           129: #define        INT15   0x06
        !           130: #define INTHIGH 0x08    /* int high=ACTIVE (else edge) */
        !           131: #define        INTEN   0x10
        !           132: /**** bit definitions for SCSIDEF ****/
        !           133: #define        HSCSIID 0x0F    /* our SCSI ID */
        !           134: #define        RSTPWR  0x10    /* reset scsi bus on power up or reset */
        !           135: /**** bit definitions for BUSDEF ****/
        !           136: #define        B0uS    0x00    /* give up bus immediatly */
        !           137: #define        B4uS    0x01    /* delay 4uSec. */
        !           138: #define        B8uS    0x02
        !           139: /***********************************************************************\
        !           140: * AHA1740 ENHANCED mode mailbox control regs (Offset from slot base)   *
        !           141: \***********************************************************************/
        !           142: #define MBOXOUT0       0xCD0
        !           143: #define MBOXOUT1       0xCD1
        !           144: #define MBOXOUT2       0xCD2
        !           145: #define MBOXOUT3       0xCD3
        !           146: 
        !           147: #define        ATTN            0xCD4
        !           148: #define        G2CNTRL         0xCD5
        !           149: #define        G2INTST         0xCD6
        !           150: #define G2STAT         0xCD7
        !           151: 
        !           152: #define        MBOXIN0         0xCD8
        !           153: #define        MBOXIN1         0xCD9
        !           154: #define        MBOXIN2         0xCDA
        !           155: #define        MBOXIN3         0xCDB
        !           156: 
        !           157: #define G2STAT2                0xCDC
        !           158: 
        !           159: /*******************************************************\
        !           160: * Bit definitions for the 5 control/status registers   *
        !           161: \*******************************************************/
        !           162: #define        ATTN_TARGET             0x0F
        !           163: #define        ATTN_OPCODE             0xF0
        !           164: #define  OP_IMMED              0x10
        !           165: #define          AHB_TARG_RESET        0x80
        !           166: #define  OP_START_ECB          0x40
        !           167: #define  OP_ABORT_ECB          0x50
        !           168: 
        !           169: #define        G2CNTRL_SET_HOST_READY  0x20
        !           170: #define        G2CNTRL_CLEAR_EISA_INT  0x40
        !           171: #define        G2CNTRL_HARD_RESET      0x80
        !           172: 
        !           173: #define        G2INTST_TARGET          0x0F
        !           174: #define        G2INTST_INT_STAT        0xF0
        !           175: #define         AHB_ECB_OK             0x10
        !           176: #define         AHB_ECB_RECOVERED      0x50
        !           177: #define         AHB_HW_ERR             0x70
        !           178: #define         AHB_IMMED_OK           0xA0
        !           179: #define         AHB_ECB_ERR            0xC0
        !           180: #define         AHB_ASN                0xD0    /* for target mode */
        !           181: #define         AHB_IMMED_ERR          0xE0
        !           182: 
        !           183: #define        G2STAT_BUSY             0x01
        !           184: #define        G2STAT_INT_PEND         0x02
        !           185: #define        G2STAT_MBOX_EMPTY       0x04
        !           186: 
        !           187: #define        G2STAT2_HOST_READY      0x01
        !           188: /**/
        !           189: 
        !           190: struct ahb_dma_seg
        !           191: {
        !           192:        physaddr        addr;
        !           193:        long            len;
        !           194: };
        !           195: 
        !           196: struct ahb_ecb_status
        !           197: {
        !           198:        u_short status;
        !           199: #       define ST_DON  0x0001
        !           200: #       define ST_DU   0x0002
        !           201: #       define ST_QF   0x0008
        !           202: #       define ST_SC   0x0010
        !           203: #       define ST_DO   0x0020
        !           204: #       define ST_CH   0x0040
        !           205: #       define ST_INT  0x0080
        !           206: #       define ST_ASA  0x0100
        !           207: #       define ST_SNS  0x0200
        !           208: #       define ST_INI  0x0800
        !           209: #       define ST_ME   0x1000
        !           210: #       define ST_ECA  0x4000
        !           211:        u_char  ha_status;
        !           212: #       define HS_OK                   0x00
        !           213: #       define HS_CMD_ABORTED_HOST     0x04
        !           214: #       define HS_CMD_ABORTED_ADAPTER  0x05
        !           215: #       define HS_TIMED_OUT            0x11
        !           216: #       define HS_HARDWARE_ERR         0x20
        !           217: #       define HS_SCSI_RESET_ADAPTER   0x22
        !           218: #       define HS_SCSI_RESET_INCOMING  0x23
        !           219:        u_char  targ_status;
        !           220: #       define TS_OK                   0x00
        !           221: #       define TS_CHECK_CONDITION      0x02
        !           222: #       define TS_BUSY                 0x08
        !           223:        u_long  resid_count;
        !           224:        u_long  resid_addr;
        !           225:        u_short addit_status;
        !           226:        u_char  sense_len;
        !           227:        u_char  unused[9];
        !           228:        u_char  cdb[6];
        !           229: };
        !           230: 
        !           231: /**/
        !           232: 
        !           233: struct ecb
        !           234: {
        !           235:        u_char  opcode;
        !           236: #       define ECB_SCSI_OP     0x01
        !           237:        u_char  :4;
        !           238:        u_char  options:3;
        !           239:        u_char  :1;
        !           240:        short opt1;
        !           241: #       define ECB_CNE 0x0001
        !           242: #       define ECB_DI  0x0080
        !           243: #       define ECB_SES 0x0400
        !           244: #       define ECB_S_G 0x1000
        !           245: #       define ECB_DSB 0x4000
        !           246: #       define ECB_ARS 0x8000
        !           247:        short opt2;
        !           248: #       define ECB_LUN 0x0007
        !           249: #       define ECB_TAG 0x0008
        !           250: #       define ECB_TT  0x0030
        !           251: #       define ECB_ND  0x0040
        !           252: #       define ECB_DAT 0x0100
        !           253: #       define ECB_DIR 0x0200
        !           254: #       define ECB_ST  0x0400
        !           255: #       define ECB_CHK 0x0800
        !           256: #       define ECB_REC 0x4000
        !           257: #       define ECB_NRB 0x8000
        !           258:        u_short         unused1;
        !           259:        physaddr        data;
        !           260:        u_long          datalen;
        !           261:        physaddr        status;
        !           262:        physaddr        chain;
        !           263:        short           unused2;
        !           264:        short           unused3;
        !           265:        physaddr        sense;
        !           266:        u_char          senselen;
        !           267:        u_char          cdblen;
        !           268:        short           cksum;
        !           269:        u_char          cdb[12];
        !           270:        /*-----------------end of hardware supported fields----------------*/
        !           271:        struct  ecb     *next;  /* in free list */
        !           272:        struct  scsi_xfer *xs; /* the scsi_xfer for this cmd */
        !           273:        long    int     delta;  /* difference from previous*/
        !           274:        struct  ecb     *later,*sooner;
        !           275:        int             flags;
        !           276: #define ECB_FREE       0
        !           277: #define ECB_ACTIVE     1
        !           278: #define ECB_ABORTED    2
        !           279: #define ECB_IMMED      4
        !           280: #define ECB_IMMED_FAIL 8
        !           281:        struct  ahb_dma_seg     ahb_dma[AHB_NSEG];
        !           282:        struct  ahb_ecb_status  ecb_status;
        !           283:        struct  scsi_sense_data ecb_sense;
        !           284: };
        !           285: 
        !           286: struct ecb     *ahb_soonest    = (struct ecb *)0;
        !           287: struct ecb     *ahb_latest     = (struct ecb *)0;
        !           288: long   int     ahb_furtherest  = 0; /* longest time in the timeout queue */
        !           289: /**/
        !           290: 
        !           291: struct ahb_data
        !           292: {
        !           293:        int     flags;
        !           294: #define        AHB_INIT        0x01;
        !           295:        int     baseport;
        !           296:        struct  ecb ecbs[NUM_CONCURRENT];
        !           297:        struct  ecb *free_ecb;
        !           298:        int     our_id;                 /* our scsi id */
        !           299:        int     vect;
        !           300:        struct  ecb *immed_ecb;         /* an outstanding immediete command */
        !           301: } ahb_data[NAHB];
        !           302: 
        !           303: int    ahbprobe();
        !           304: int    ahb_attach();
        !           305: int    ahbintr();
        !           306: int    ahb_scsi_cmd();
        !           307: int    ahb_timeout();
        !           308: struct ecb *cheat;
        !           309: void   ahbminphys();
        !           310: long int ahb_adapter_info();
        !           311: 
        !           312: #ifdef  MACH
        !           313: struct  isa_driver      ahbdriver = { ahbprobe, 0, ahb_attach, "ahb", 0, 0, 0};
        !           314: int (*ahbintrs[])() = {ahbintr, 0};
        !           315: #endif  MACH
        !           316: 
        !           317: #ifdef  __386BSD__
        !           318: struct  isa_driver      ahbdriver = { ahbprobe, ahb_attach, "ahb"};
        !           319: #endif  __386BSD__
        !           320: 
        !           321: #define        MAX_SLOTS       8
        !           322: static ahb_slot = 0;   /* slot last board was found in */
        !           323: static ahb_unit = 0;
        !           324: int    ahb_debug = 0;
        !           325: #define AHB_SHOWECBS 0x01
        !           326: #define AHB_SHOWINTS 0x02
        !           327: #define AHB_SHOWCMDS 0x04
        !           328: #define AHB_SHOWMISC 0x08
        !           329: #define FAIL   1
        !           330: #define SUCCESS 0
        !           331: #define PAGESIZ 4096
        !           332: 
        !           333: struct scsi_switch     ahb_switch = 
        !           334: {
        !           335:        ahb_scsi_cmd,
        !           336:        ahbminphys,
        !           337:        0,
        !           338:        0,
        !           339:        ahb_adapter_info,
        !           340:        0,0,0
        !           341: };
        !           342: 
        !           343: /**/
        !           344: /***********************************************************************\
        !           345: * Function to send a command out through a mailbox                     *
        !           346: \***********************************************************************/
        !           347: ahb_send_mbox( int             unit
        !           348:                ,int            opcode
        !           349:                ,int            target
        !           350:                ,struct ecb     *ecb)
        !           351: {
        !           352:        int     port = ahb_data[unit].baseport;
        !           353:        int     spincount = FUDGE(delaycount) * 1; /* 1ms should be enough */
        !           354:        int     s = splbio();
        !           355:        int     stport = port + G2STAT;
        !           356: 
        !           357:        while(      ((inb(stport) & (G2STAT_BUSY | G2STAT_MBOX_EMPTY))
        !           358:                                        != (G2STAT_MBOX_EMPTY))
        !           359:                && (spincount--));
        !           360:        if(spincount == -1)
        !           361:        {
        !           362:                printf("ahb%d: board not responding\n",unit);
        !           363:                Debugger();
        !           364:        }
        !           365: 
        !           366:        outl(port + MBOXOUT0,KVTOPHYS(ecb));    /* don't know this will work */
        !           367:        outb(port + ATTN, opcode|target);
        !           368: 
        !           369:        splx(s);
        !           370: }
        !           371: 
        !           372: /***********************************************************************\
        !           373: * Function to poll for command completion when in poll mode            *
        !           374: \***********************************************************************/
        !           375: ahb_poll(int unit ,int wait) /* in msec  */
        !           376: {
        !           377:        int     port = ahb_data[unit].baseport;
        !           378:        int     spincount = FUDGE(delaycount) * wait; /* in msec */
        !           379:        int     stport = port + G2STAT;
        !           380: int    start = spincount;
        !           381: 
        !           382: retry:
        !           383:        while( (spincount--) && (!(inb(stport) &  G2STAT_INT_PEND)));
        !           384:        if(spincount == -1)
        !           385:        {
        !           386:                printf("ahb%d: board not responding\n",unit);
        !           387:                return(EIO);
        !           388:        }
        !           389: if ((int)cheat != PHYSTOKV(inl(port + MBOXIN0)))
        !           390: {
        !           391:        printf("discarding %x ",inl(port + MBOXIN0));
        !           392:        outb(port + G2CNTRL, G2CNTRL_CLEAR_EISA_INT);
        !           393:        spinwait(50);
        !           394:        goto retry;
        !           395: }/* don't know this will work */
        !           396:        ahbintr(unit);
        !           397:        return(0);
        !           398: }
        !           399: /***********************************************************************\
        !           400: * Function to  send an immediate type command to the adapter           *
        !           401: \***********************************************************************/
        !           402: ahb_send_immed(        int             unit
        !           403:                ,int            target
        !           404:                ,u_long         cmd)
        !           405: {
        !           406:        int     port = ahb_data[unit].baseport;
        !           407:        int     spincount = FUDGE(delaycount) * 1; /* 1ms should be enough */
        !           408:        int     s = splbio();
        !           409:        int     stport = port + G2STAT;
        !           410: 
        !           411:        while(      ((inb(stport) & (G2STAT_BUSY | G2STAT_MBOX_EMPTY))
        !           412:                                        != (G2STAT_MBOX_EMPTY))
        !           413:                && (spincount--));
        !           414:        if(spincount == -1)
        !           415:        {
        !           416:                printf("ahb%d: board not responding\n",unit);
        !           417:                Debugger();
        !           418:        }
        !           419: 
        !           420:        outl(port + MBOXOUT0,cmd);      /* don't know this will work */
        !           421:        outb(port + G2CNTRL, G2CNTRL_SET_HOST_READY);
        !           422:        outb(port + ATTN, OP_IMMED | target);
        !           423:        splx(s);
        !           424: }
        !           425: 
        !           426: /**/
        !           427: 
        !           428: /*******************************************************\
        !           429: * Check  the slots looking for a board we recognise    *
        !           430: * If we find one, note it's address (slot) and call    *
        !           431: * the actual probe routine to check it out.            *
        !           432: \*******************************************************/
        !           433: ahbprobe(dev)
        !           434: struct isa_dev *dev;
        !           435: {
        !           436:        int     port;
        !           437:        u_char  byte1,byte2,byte3;
        !           438:        ahb_slot++;
        !           439:        while (ahb_slot<8)
        !           440:        {
        !           441:                port = 0x1000 * ahb_slot;
        !           442:                byte1 = inb(port + HID0);
        !           443:                byte2 = inb(port + HID1);
        !           444:                byte3 = inb(port + HID2);
        !           445:                if(byte1 == 0xff)
        !           446:                {
        !           447:                        ahb_slot++;
        !           448:                        continue;
        !           449:                }
        !           450:                if ((CHAR1(byte1,byte2) == 'A')
        !           451:                 && (CHAR2(byte1,byte2) == 'D')
        !           452:                 && (CHAR3(byte1,byte2) == 'P')
        !           453:                 && ((byte3 == 0 ) || (byte3 == 1)))
        !           454:                {
        !           455:                        dev->dev_addr = port;
        !           456:                        return(ahbprobe1(dev) ? 0x1000 : 0);
        !           457:                }
        !           458:                ahb_slot++;
        !           459:        }
        !           460:        return(0);
        !           461: }
        !           462: /*******************************************************\
        !           463: * Check if the device can be found at the port given    *
        !           464: * and if so, set it up ready for further work           *
        !           465: * as an argument, takes the isa_dev structure from      *
        !           466: * autoconf.c                                            *
        !           467: \*******************************************************/
        !           468: ahbprobe1(dev)
        !           469: struct isa_dev *dev;
        !           470: {
        !           471:        /***********************************************\
        !           472:        * find unit and check we have that many defined *
        !           473:        \***********************************************/
        !           474:        int     unit = ahb_unit;
        !           475: #if defined(OSF)
        !           476:        static ihandler_t ahb_handler[NAHB];
        !           477:        static ihandler_id_t *ahb_handler_id[NAHB];
        !           478:        register ihandler_t *chp = &ahb_handler[unit];;
        !           479: #endif /* defined(OSF) */
        !           480: 
        !           481:        dev->dev_unit = unit;
        !           482:        ahb_data[unit].baseport = dev->dev_addr;
        !           483:        if(unit >= NAHB) 
        !           484:        {
        !           485:                printf("ahb: unit number (%d) too high\n",unit);
        !           486:                return(0);
        !           487:        }
        !           488:        /***********************************************\
        !           489:        * Try initialise a unit at this location        *
        !           490:        * sets up dma and bus speed, loads ahb_data[unit].vect*
        !           491:        \***********************************************/
        !           492:        if (ahb_init(unit) != 0)
        !           493:        {
        !           494:                return(0);
        !           495:        }
        !           496: 
        !           497:        /***********************************************\
        !           498:        * If it's there, put in it's interrupt vectors  *
        !           499:        \***********************************************/
        !           500: #ifdef MACH
        !           501: #if defined(OSF)                               /* OSF */
        !           502:        chp->ih_level = dev->dev_pic;
        !           503:        chp->ih_handler = dev->dev_intr[0];
        !           504:        chp->ih_resolver = i386_resolver;
        !           505:        chp->ih_rdev = dev;
        !           506:        chp->ih_stats.intr_type = INTR_DEVICE;
        !           507:        chp->ih_stats.intr_cnt = 0;
        !           508:        chp->ih_hparam[0].intparam = unit;
        !           509:        if ((ahb_handler_id[unit] = handler_add(chp)) != NULL)
        !           510:                handler_enable(ahb_handler_id[unit]);
        !           511:        else
        !           512:                panic("Unable to add ahb interrupt handler");
        !           513: #else                                          /* CMU */
        !           514:        dev->dev_pic = ahb_data[unit].vect;
        !           515:        take_dev_irq(dev);
        !           516: #endif /* !defined(OSF) */
        !           517:        printf("port=%x spl=%d\n", dev->dev_addr, dev->dev_spl);
        !           518: #endif MACH
        !           519: #ifdef  __386BSD__                             /* 386BSD */
        !           520:         dev->id_irq = (1 << ahb_data[unit].vect);
        !           521:         dev->id_drq = -1; /* use EISA dma */
        !           522:        printf("\n  **");
        !           523: #endif  __386BSD__
        !           524: 
        !           525:        ahb_unit++;
        !           526:        return(1);
        !           527: }
        !           528: 
        !           529: /***********************************************\
        !           530: * Attach all the sub-devices we can find       *
        !           531: \***********************************************/
        !           532: ahb_attach(dev)
        !           533: struct isa_dev *dev;
        !           534: {
        !           535:        int     unit = dev->dev_unit;
        !           536: 
        !           537: 
        !           538: #ifdef  __386BSD__
        !           539:        printf("ahb%d: probing for scsi devices..\n", unit);
        !           540: #endif  __386BSD__
        !           541: 
        !           542:        /***********************************************\
        !           543:        * ask the adapter what subunits are present     *
        !           544:        \***********************************************/
        !           545:        scsi_attachdevs( unit, ahb_data[unit].our_id, &ahb_switch);
        !           546: #if defined(OSF)
        !           547:        ahb_attached[unit]=1;
        !           548: #endif /* defined(OSF) */
        !           549:        if(!unit) /* only one for all boards */
        !           550:        {
        !           551:                ahb_timeout(0);
        !           552:        }
        !           553:        return;
        !           554: }
        !           555: 
        !           556: /***********************************************\
        !           557: * Return some information to the caller about   *
        !           558: * the adapter and it's capabilities             *
        !           559: \***********************************************/
        !           560: long int ahb_adapter_info(unit)
        !           561: int    unit;
        !           562: {
        !           563:        return(2);      /* 2 outstanding requests at a time per device */
        !           564: }
        !           565: 
        !           566: /***********************************************\
        !           567: * Catch an interrupt from the adaptor          *
        !           568: \***********************************************/
        !           569: ahbintr(unit)
        !           570: {
        !           571:        struct ecb      *ecb;
        !           572:        unsigned char   stat;
        !           573:        register        i;
        !           574:        u_char          ahbstat;
        !           575:        int             target;
        !           576:        long int        mboxval;
        !           577: 
        !           578:        int     port = ahb_data[unit].baseport;
        !           579: 
        !           580:        if(scsi_debug & PRINTROUTINES)
        !           581:                printf("ahbintr ");
        !           582: 
        !           583: #if defined(OSF)
        !           584:        if (!ahb_attached[unit])
        !           585:        {
        !           586:                return(1);
        !           587:        }
        !           588: #endif /* defined(OSF) */
        !           589:        while(inb(port + G2STAT) & G2STAT_INT_PEND)
        !           590:        {
        !           591:                /***********************************************\
        !           592:                * First get all the information and then        *
        !           593:                * acknowlege the interrupt                      *
        !           594:                \***********************************************/
        !           595:                ahbstat = inb(port + G2INTST);
        !           596:                target = ahbstat & G2INTST_TARGET;
        !           597:                stat = ahbstat & G2INTST_INT_STAT;
        !           598:                mboxval = inl(port + MBOXIN0);/* don't know this will work */
        !           599:                outb(port + G2CNTRL, G2CNTRL_CLEAR_EISA_INT);
        !           600:                if(scsi_debug & TRACEINTERRUPTS)
        !           601:                        printf("status = 0x%x ",stat);
        !           602:                /***********************************************\
        !           603:                * Process the completed operation               *
        !           604:                \***********************************************/
        !           605:        
        !           606:                if(stat == AHB_ECB_OK) /* common case is fast */
        !           607:                {
        !           608:                        ecb = (struct ecb *)PHYSTOKV(mboxval); 
        !           609:                }
        !           610:                else
        !           611:                {
        !           612:                        switch(stat)
        !           613:                        {
        !           614:                        case    AHB_IMMED_OK:
        !           615:                                ecb = ahb_data[unit].immed_ecb;
        !           616:                                ahb_data[unit].immed_ecb = 0;
        !           617:                                break;
        !           618:                        case    AHB_IMMED_ERR:
        !           619:                                ecb = ahb_data[unit].immed_ecb;
        !           620:                                ecb->flags |= ECB_IMMED_FAIL;
        !           621:                                ahb_data[unit].immed_ecb = 0;
        !           622:                                break;
        !           623:                        case    AHB_ASN:        /* for target mode */
        !           624:                                ecb = 0;
        !           625:                                break;
        !           626:                        case    AHB_HW_ERR:
        !           627:                                ecb = 0;
        !           628:                                break;
        !           629:                        case    AHB_ECB_RECOVERED:
        !           630:                                ecb = (struct ecb *)PHYSTOKV(mboxval); 
        !           631:                                break;
        !           632:                        case    AHB_ECB_ERR:
        !           633:                                ecb = (struct ecb *)PHYSTOKV(mboxval); 
        !           634:                                break;
        !           635:                        default:
        !           636:                                printf(" Unknown return from ahb%d(%x)\n",unit,ahbstat);
        !           637:                                ecb=0;
        !           638:                        }
        !           639:                }
        !           640:                if(ecb)
        !           641:                {
        !           642:                        if(ahb_debug & AHB_SHOWCMDS )
        !           643:                        {
        !           644:                                ahb_show_scsi_cmd(ecb->xs);
        !           645:                        }
        !           646:                        if((ahb_debug & AHB_SHOWECBS) && ecb)
        !           647:                                printf("<int ecb(%x)>",ecb);
        !           648:                        ahb_remove_timeout(ecb);
        !           649:                        ahb_done(unit,ecb,((stat == AHB_ECB_OK)?SUCCESS:FAIL));
        !           650:                }
        !           651:        }
        !           652:        return(1);
        !           653: }
        !           654: 
        !           655: /***********************************************\
        !           656: * We have a ecb which has been processed by the        *
        !           657: * adaptor, now we look to see how the operation        *
        !           658: * went.                                                *
        !           659: \***********************************************/
        !           660: ahb_done(unit,ecb,state)
        !           661: int    unit,state;
        !           662: struct ecb *ecb;
        !           663: {
        !           664:        struct  ahb_ecb_status  *stat = &ecb->ecb_status;
        !           665:        struct  scsi_sense_data *s1,*s2;
        !           666:        struct  scsi_xfer *xs = ecb->xs;
        !           667: 
        !           668:        if(scsi_debug & (PRINTROUTINES | TRACEINTERRUPTS))
        !           669:                printf("ahb_done ");
        !           670:        /***********************************************\
        !           671:        * Otherwise, put the results of the operation   *
        !           672:        * into the xfer and call whoever started it     *
        !           673:        \***********************************************/
        !           674:        if(ecb->flags & ECB_IMMED)
        !           675:        {
        !           676:                if(ecb->flags & ECB_IMMED_FAIL)
        !           677:                {
        !           678:                        xs->error = XS_DRIVER_STUFFUP;
        !           679:                }
        !           680:                goto done;
        !           681:        }
        !           682:        if ( (state == SUCCESS) || (xs->flags & SCSI_ERR_OK))
        !           683:        {               /* All went correctly  OR errors expected */
        !           684:                xs->resid = 0;
        !           685:                xs->error = 0;
        !           686:        }
        !           687:        else
        !           688:        {
        !           689: 
        !           690:                s1 = &(ecb->ecb_sense);
        !           691:                s2 = &(xs->sense);
        !           692: 
        !           693:                if(stat->ha_status)
        !           694:                {
        !           695:                        switch(stat->ha_status)
        !           696:                        {
        !           697:                        case    HS_SCSI_RESET_ADAPTER:
        !           698:                                break;
        !           699:                        case    HS_SCSI_RESET_INCOMING:
        !           700:                                break;
        !           701:                        case    HS_CMD_ABORTED_HOST:    /* No response */
        !           702:                        case    HS_CMD_ABORTED_ADAPTER: /* No response */
        !           703:                                break;
        !           704:                        case    HS_TIMED_OUT:           /* No response */
        !           705:                                if (ahb_debug & AHB_SHOWMISC)
        !           706:                                {
        !           707:                                        printf("timeout reported back\n");
        !           708:                                }
        !           709:                                xs->error = XS_TIMEOUT;
        !           710:                                break;
        !           711:                        default:        /* Other scsi protocol messes */
        !           712:                                xs->error = XS_DRIVER_STUFFUP;
        !           713:                                if (ahb_debug & AHB_SHOWMISC)
        !           714:                                {
        !           715:                                        printf("unexpected ha_status: %x\n",
        !           716:                                                stat->ha_status);
        !           717:                                }
        !           718:                        }
        !           719: 
        !           720:                }
        !           721:                else
        !           722:                {
        !           723:                        switch(stat->targ_status)
        !           724:                        {
        !           725:                        case TS_CHECK_CONDITION:
        !           726:                                /* structure copy!!!!!*/
        !           727:                                *s2=*s1;
        !           728:                                xs->error = XS_SENSE;
        !           729:                                break;
        !           730:                        case TS_BUSY:
        !           731:                                xs->error = XS_BUSY;
        !           732:                                break;
        !           733:                        default:
        !           734:                                if (ahb_debug & AHB_SHOWMISC)
        !           735:                                {
        !           736:                                        printf("unexpected targ_status: %x\n",
        !           737:                                                stat->targ_status);
        !           738:                                }
        !           739:                                xs->error = XS_DRIVER_STUFFUP;
        !           740:                        }
        !           741:                }
        !           742:        }
        !           743: done:  xs->flags |= ITSDONE;
        !           744:        ahb_free_ecb(unit,ecb, xs->flags);
        !           745:        if(xs->when_done)
        !           746:                (*(xs->when_done))(xs->done_arg,xs->done_arg2);
        !           747: }
        !           748: 
        !           749: /***********************************************\
        !           750: * A ecb (and hence a mbx-out is put onto the   *
        !           751: * free list.                                   *
        !           752: \***********************************************/
        !           753: ahb_free_ecb(unit,ecb, flags)
        !           754: struct ecb *ecb;
        !           755: {
        !           756:        unsigned int opri;
        !           757:        
        !           758:        if(scsi_debug & PRINTROUTINES)
        !           759:                printf("ecb%d(0x%x)> ",unit,flags);
        !           760:        if (!(flags & SCSI_NOMASK)) 
        !           761:                opri = splbio();
        !           762: 
        !           763:        ecb->next = ahb_data[unit].free_ecb;
        !           764:        ahb_data[unit].free_ecb = ecb;
        !           765:        ecb->flags = ECB_FREE;
        !           766:        /***********************************************\
        !           767:        * If there were none, wake abybody waiting for  *
        !           768:        * one to come free, starting with queued entries*
        !           769:        \***********************************************/
        !           770:        if (!ecb->next) {
        !           771:                wakeup(&ahb_data[unit].free_ecb);
        !           772:        }
        !           773:        if (!(flags & SCSI_NOMASK)) 
        !           774:                splx(opri);
        !           775: }
        !           776: 
        !           777: /***********************************************\
        !           778: * Get a free ecb (and hence mbox-out entry)    *
        !           779: \***********************************************/
        !           780: struct ecb *
        !           781: ahb_get_ecb(unit,flags)
        !           782: {
        !           783:        unsigned opri;
        !           784:        struct ecb *rc;
        !           785: 
        !           786:        if(scsi_debug & PRINTROUTINES)
        !           787:                printf("<ecb%d(0x%x) ",unit,flags);
        !           788:        if (!(flags & SCSI_NOMASK)) 
        !           789:                opri = splbio();
        !           790:        /***********************************************\
        !           791:        * If we can and have to, sleep waiting for one  *
        !           792:        * to come free                                  *
        !           793:        \***********************************************/
        !           794:        while ((!(rc = ahb_data[unit].free_ecb)) && (!(flags & SCSI_NOSLEEP)))
        !           795:        {
        !           796:                sleep(&ahb_data[unit].free_ecb, PRIBIO);
        !           797:        }
        !           798:        if (rc) 
        !           799:        {
        !           800:                ahb_data[unit].free_ecb = rc->next;
        !           801:                rc->flags = ECB_ACTIVE;
        !           802:        }
        !           803:        if (!(flags & SCSI_NOMASK)) 
        !           804:                splx(opri);
        !           805:        return(rc);
        !           806: }
        !           807:                
        !           808: 
        !           809: 
        !           810: /***********************************************\
        !           811: * Start the board, ready for normal operation  *
        !           812: \***********************************************/
        !           813: ahb_init(unit)
        !           814: int    unit;
        !           815: {
        !           816:        int     port = ahb_data[unit].baseport;
        !           817:        int     intdef;
        !           818:        int     spincount = FUDGE(delaycount) * 1000; /* 1 sec enough? */
        !           819:        int     i;
        !           820:        int     stport = port + G2STAT;
        !           821: #define        NO_NO 1
        !           822: #ifdef NO_NO
        !           823:        /***********************************************\
        !           824:        * reset board, If it doesn't respond, assume    *
        !           825:        * that it's not there.. good for the probe      *
        !           826:        \***********************************************/
        !           827:        outb(port + EBCTRL,CDEN);       /* enable full card */
        !           828:        outb(port + PORTADDR,PORTADDR_ENHANCED);
        !           829: 
        !           830:        outb(port + G2CNTRL,G2CNTRL_HARD_RESET);
        !           831:        spinwait(1);
        !           832:        outb(port + G2CNTRL,0);
        !           833:        spinwait(10);
        !           834:        while(      ((inb(stport) & G2STAT_BUSY ))
        !           835:                && (spincount--));
        !           836:        if(spincount == -1)
        !           837:        {
        !           838:                if (ahb_debug & AHB_SHOWMISC)
        !           839:                        printf("ahb_init: No answer from bt742a board\n");
        !           840:                return(ENXIO);
        !           841:        }
        !           842:        i = inb(port + MBOXIN0) & 0xff;
        !           843:        if(i)
        !           844:        {
        !           845:                printf("self test failed, val = 0x%x\n",i);
        !           846:                return(EIO);
        !           847:        }
        !           848: #endif
        !           849:        while( inb(stport) &  G2STAT_INT_PEND)
        !           850:        {
        !           851:                printf(".");
        !           852:                outb(port + G2CNTRL, G2CNTRL_CLEAR_EISA_INT);
        !           853:                spinwait(10);
        !           854:        }
        !           855:        outb(port + EBCTRL,CDEN);       /* enable full card */
        !           856:        outb(port + PORTADDR,PORTADDR_ENHANCED);
        !           857:        /***********************************************\
        !           858:        * Assume we have a board at this stage          *
        !           859:        * setup dma channel from jumpers and save int   *
        !           860:        * level                                         *
        !           861:        \***********************************************/
        !           862: #ifdef __386BSD__
        !           863:        printf("ahb%d reading board settings, ",unit);
        !           864: #define        PRNT(x)
        !           865: #else  __386BSD__
        !           866:        printf("ahb%d:",unit);
        !           867: #define        PRNT(x) printf(x)
        !           868: #endif __386BSD__
        !           869: 
        !           870:        intdef = inb(port + INTDEF);
        !           871:        switch(intdef & 0x07)
        !           872:        {
        !           873:        case    INT9:
        !           874:                ahb_data[unit].vect = 9;
        !           875:                PRNT("int=9 ");
        !           876:                break;
        !           877:        case    INT10:
        !           878:                ahb_data[unit].vect = 10;
        !           879:                PRNT("int=10 ");
        !           880:                break;
        !           881:        case    INT11:
        !           882:                ahb_data[unit].vect = 11;
        !           883:                PRNT("int=11 ");
        !           884:                break;
        !           885:        case    INT12:
        !           886:                ahb_data[unit].vect = 12;
        !           887:                PRNT("int=12 ");
        !           888:                break;
        !           889:        case    INT14:
        !           890:                ahb_data[unit].vect = 14;
        !           891:                PRNT("int=14 ");
        !           892:                break;
        !           893:        case    INT15:
        !           894:                ahb_data[unit].vect = 15;
        !           895:                PRNT("int=15 ");
        !           896:                break;
        !           897:        default:
        !           898:                printf("illegal int setting\n");
        !           899:                return(EIO);
        !           900:        }
        !           901:        outb(port + INTDEF ,(intdef | INTEN)); /* make sure we can interrupt */
        !           902:        /* who are we on the scsi bus */
        !           903:        ahb_data[unit].our_id = (inb(port + SCSIDEF) & HSCSIID);
        !           904: 
        !           905:        /***********************************************\
        !           906:        * link up all our ECBs into a free list         *
        !           907:        \***********************************************/
        !           908:        for (i=0; i < NUM_CONCURRENT; i++)
        !           909:        {
        !           910:                ahb_data[unit].ecbs[i].next = ahb_data[unit].free_ecb;
        !           911:                ahb_data[unit].free_ecb = &ahb_data[unit].ecbs[i];
        !           912:                ahb_data[unit].free_ecb->flags = ECB_FREE;
        !           913:        }
        !           914: 
        !           915:        /***********************************************\
        !           916:        * Note that we are going and return (to probe)  *
        !           917:        \***********************************************/
        !           918:        ahb_data[unit].flags |= AHB_INIT;
        !           919:        return( 0 );
        !           920: }
        !           921: 
        !           922: 
        !           923: #ifndef        min
        !           924: #define min(x,y) (x < y ? x : y)
        !           925: #endif min
        !           926: 
        !           927: 
        !           928: void ahbminphys(bp)
        !           929: struct buf *bp;
        !           930: {
        !           931: #ifdef MACH
        !           932: #if    !defined(OSF)
        !           933:        bp->b_flags |= B_NPAGES;                /* can support scat/gather */
        !           934: #endif /* defined(OSF) */
        !           935: #endif MACH
        !           936:        if(bp->b_bcount > ((AHB_NSEG-1) * PAGESIZ))
        !           937:        {
        !           938:                bp->b_bcount = ((AHB_NSEG-1) * PAGESIZ);
        !           939:        }
        !           940: }
        !           941:        
        !           942: /***********************************************\
        !           943: * start a scsi operation given the command and *
        !           944: * the data address. Also needs the unit, target        *
        !           945: * and lu                                       *
        !           946: \***********************************************/
        !           947: int    ahb_scsi_cmd(xs)
        !           948: struct scsi_xfer *xs;
        !           949: {
        !           950:        struct  scsi_sense_data *s1,*s2;
        !           951:        struct ecb *ecb;
        !           952:        struct ahb_dma_seg *sg;
        !           953:        int     seg;    /* scatter gather seg being worked on */
        !           954:        int i   = 0;
        !           955:        int rc  =  0;
        !           956:        int     thiskv;
        !           957:        physaddr        thisphys,nextphys;
        !           958:        int     unit =xs->adapter;
        !           959:        int     bytes_this_seg,bytes_this_page,datalen,flags;
        !           960:        struct  iovec   *iovp;
        !           961:        int     s;
        !           962:        if(scsi_debug & PRINTROUTINES)
        !           963:                printf("ahb_scsi_cmd ");
        !           964:        /***********************************************\
        !           965:        * get a ecb (mbox-out) to use. If the transfer  *
        !           966:        * is from a buf (possibly from interrupt time)  *
        !           967:        * then we can't allow it to sleep               *
        !           968:        \***********************************************/
        !           969:        flags = xs->flags;
        !           970:        if(xs->bp) flags |= (SCSI_NOSLEEP); /* just to be sure */
        !           971:        if(flags & ITSDONE)
        !           972:        {
        !           973:                printf("Already done?");
        !           974:                xs->flags &= ~ITSDONE;
        !           975:        }
        !           976:        if(!(flags & INUSE))
        !           977:        {
        !           978:                printf("Not in use?");
        !           979:                xs->flags |= INUSE;
        !           980:        }
        !           981:        if (!(ecb = ahb_get_ecb(unit,flags)))
        !           982:        {
        !           983:                xs->error = XS_DRIVER_STUFFUP;
        !           984:                return(TRY_AGAIN_LATER);
        !           985:        }
        !           986: 
        !           987: cheat = ecb;
        !           988:        if(ahb_debug & AHB_SHOWECBS)
        !           989:                                printf("<start ecb(%x)>",ecb);
        !           990:        if(scsi_debug & SHOWCOMMANDS)
        !           991:        {
        !           992:                ahb_show_scsi_cmd(xs);
        !           993:        }
        !           994:        ecb->xs = xs;
        !           995:        /***********************************************\
        !           996:        * If it's a reset, we need to do an 'immediate' *
        !           997:        * command, and store it's ccb for later         *
        !           998:        * if there is already an immediate waiting,     *
        !           999:        * then WE must wait                             *
        !          1000:        \***********************************************/
        !          1001:        if(flags & SCSI_RESET)
        !          1002:        {
        !          1003:                ecb->flags |= ECB_IMMED;
        !          1004:                if(ahb_data[unit].immed_ecb)
        !          1005:                {
        !          1006:                        return(TRY_AGAIN_LATER);
        !          1007:                }
        !          1008:                ahb_data[unit].immed_ecb = ecb;
        !          1009:                if (!(flags & SCSI_NOMASK))
        !          1010:                {
        !          1011:                        s = splbio();
        !          1012:                        ahb_send_immed(unit,xs->targ,AHB_TARG_RESET);
        !          1013:                        ahb_add_timeout(ecb,xs->timeout);
        !          1014:                        splx(s);
        !          1015:                        return(SUCCESSFULLY_QUEUED);
        !          1016:                }
        !          1017:                else
        !          1018:                {
        !          1019:                        ahb_send_immed(unit,xs->targ,AHB_TARG_RESET);
        !          1020:                        /***********************************************\
        !          1021:                        * If we can't use interrupts, poll on completion*
        !          1022:                        \***********************************************/
        !          1023:                        if(scsi_debug & TRACEINTERRUPTS)
        !          1024:                                printf("wait ");
        !          1025:                        if( ahb_poll(unit,xs->timeout))
        !          1026:                        {
        !          1027:                                ahb_free_ecb(unit,ecb,flags);
        !          1028:                                xs->error = XS_TIMEOUT;
        !          1029:                                return(HAD_ERROR);
        !          1030:                        }
        !          1031:                        return(COMPLETE);
        !          1032:                }
        !          1033:        }       
        !          1034:        /***********************************************\
        !          1035:        * Put all the arguments for the xfer in the ecb *
        !          1036:        \***********************************************/
        !          1037:        ecb->opcode = ECB_SCSI_OP;
        !          1038:        ecb->opt1 = ECB_SES|ECB_DSB|ECB_ARS;
        !          1039:        if(xs->datalen)
        !          1040:        {
        !          1041:                ecb->opt1 |= ECB_S_G;
        !          1042:        }
        !          1043:        ecb->opt2               =       xs->lu | ECB_NRB;
        !          1044:        ecb->cdblen             =       xs->cmdlen;
        !          1045:        ecb->sense              =       KVTOPHYS(&(ecb->ecb_sense));
        !          1046:        ecb->senselen           =       sizeof(ecb->ecb_sense);
        !          1047:        ecb->status             =       KVTOPHYS(&(ecb->ecb_status));
        !          1048: 
        !          1049:        if(xs->datalen)
        !          1050:        { /* should use S/G only if not zero length */
        !          1051:                ecb->data       =       KVTOPHYS(ecb->ahb_dma);
        !          1052:                sg              =       ecb->ahb_dma ;
        !          1053:                seg             =       0;
        !          1054:                if(flags & SCSI_DATA_UIO)
        !          1055:                {
        !          1056:                        iovp = ((struct uio *)xs->data)->uio_iov;
        !          1057:                        datalen = ((struct uio *)xs->data)->uio_iovcnt;
        !          1058:                        xs->datalen = 0;
        !          1059:                        while ((datalen) && (seg < AHB_NSEG))
        !          1060:                        {
        !          1061:                                sg->addr = (physaddr)iovp->iov_base;
        !          1062:                                xs->datalen += sg->len = iovp->iov_len; 
        !          1063:                                if(scsi_debug & SHOWSCATGATH)
        !          1064:                                        printf("(0x%x@0x%x)"
        !          1065:                                                        ,iovp->iov_len
        !          1066:                                                        ,iovp->iov_base);
        !          1067:                                sg++;
        !          1068:                                iovp++;
        !          1069:                                seg++;
        !          1070:                                datalen--;
        !          1071:                        }
        !          1072:                }
        !          1073:                else
        !          1074:                {
        !          1075:                        /***********************************************\
        !          1076:                        * Set up the scatter gather block               *
        !          1077:                        \***********************************************/
        !          1078:                
        !          1079:                        if(scsi_debug & SHOWSCATGATH)
        !          1080:                                printf("%d @0x%x:- ",xs->datalen,xs->data);
        !          1081:                        datalen         =       xs->datalen;
        !          1082:                        thiskv          =       (int)xs->data;
        !          1083:                        thisphys        =       KVTOPHYS(thiskv);
        !          1084:                
        !          1085:                        while ((datalen) && (seg < AHB_NSEG))
        !          1086:                        {
        !          1087:                                bytes_this_seg  = 0;
        !          1088:        
        !          1089:                                /* put in the base address */
        !          1090:                                sg->addr = thisphys;
        !          1091:                
        !          1092:                                if(scsi_debug & SHOWSCATGATH)
        !          1093:                                        printf("0x%x",thisphys);
        !          1094:        
        !          1095:                                /* do it at least once */
        !          1096:                                nextphys = thisphys;    
        !          1097:                                while ((datalen) && (thisphys == nextphys))
        !          1098:                                /*********************************************\
        !          1099:                                * This page is contiguous (physically) with   *
        !          1100:                                * the the last, just extend the length        *
        !          1101:                                \*********************************************/
        !          1102:                                {
        !          1103:                                        /* how far to the end of the page */
        !          1104:                                        nextphys= (thisphys & (~(PAGESIZ - 1)))
        !          1105:                                                                + PAGESIZ;
        !          1106:                                        bytes_this_page = nextphys - thisphys;
        !          1107:                                        /**** or the data ****/
        !          1108:                                        bytes_this_page = min(bytes_this_page
        !          1109:                                                                ,datalen);
        !          1110:                                        bytes_this_seg  += bytes_this_page;
        !          1111:                                        datalen         -= bytes_this_page;
        !          1112:                
        !          1113:                                        /* get more ready for the next page */
        !          1114:                                        thiskv  = (thiskv & (~(PAGESIZ - 1)))
        !          1115:                                                                + PAGESIZ;
        !          1116:                                        if(datalen)
        !          1117:                                                thisphys = KVTOPHYS(thiskv);
        !          1118:                                }
        !          1119:                                /********************************************\
        !          1120:                                * next page isn't contiguous, finish the seg *
        !          1121:                                \********************************************/
        !          1122:                                if(scsi_debug & SHOWSCATGATH)
        !          1123:                                        printf("(0x%x)",bytes_this_seg);
        !          1124:                                sg->len = bytes_this_seg;       
        !          1125:                                sg++;
        !          1126:                                seg++;
        !          1127:                        }
        !          1128:                } /*end of iov/kv decision */
        !          1129:                ecb->datalen = seg * sizeof(struct ahb_dma_seg);
        !          1130:                if(scsi_debug & SHOWSCATGATH)
        !          1131:                        printf("\n");
        !          1132:                if (datalen)
        !          1133:                { /* there's still data, must have run out of segs! */
        !          1134:                        printf("ahb_scsi_cmd%d: more than %d DMA segs\n",
        !          1135:                                unit,AHB_NSEG);
        !          1136:                        xs->error = XS_DRIVER_STUFFUP;
        !          1137:                        ahb_free_ecb(unit,ecb,flags);
        !          1138:                        return(HAD_ERROR);
        !          1139:                }
        !          1140: 
        !          1141:        }
        !          1142:        else
        !          1143:        {       /* No data xfer, use non S/G values */
        !          1144:                ecb->data = (physaddr)0;
        !          1145:                ecb->datalen = 0;
        !          1146:        }
        !          1147:        ecb->chain = (physaddr)0;
        !          1148:        /***********************************************\
        !          1149:        * Put the scsi command in the ecb and start it  *
        !          1150:        \***********************************************/
        !          1151:        bcopy(xs->cmd, ecb->cdb, xs->cmdlen);
        !          1152:        /***********************************************\
        !          1153:        * Usually return SUCCESSFULLY QUEUED            *
        !          1154:        \***********************************************/
        !          1155:        if (!(flags & SCSI_NOMASK))
        !          1156:        {
        !          1157:                s = splbio();
        !          1158:                ahb_send_mbox(unit,OP_START_ECB,xs->targ,ecb);
        !          1159:                ahb_add_timeout(ecb,xs->timeout);
        !          1160:                splx(s);
        !          1161:                if(scsi_debug & TRACEINTERRUPTS)
        !          1162:                        printf("cmd_sent ");
        !          1163:                return(SUCCESSFULLY_QUEUED);
        !          1164:        }
        !          1165:        /***********************************************\
        !          1166:        * If we can't use interrupts, poll on completion*
        !          1167:        \***********************************************/
        !          1168:        ahb_send_mbox(unit,OP_START_ECB,xs->targ,ecb);
        !          1169:        if(scsi_debug & TRACEINTERRUPTS)
        !          1170:                printf("cmd_wait ");
        !          1171:        do
        !          1172:        {
        !          1173:                if(ahb_poll(unit,xs->timeout))
        !          1174:                {
        !          1175:                        if (!(xs->flags & SCSI_SILENT)) printf("cmd fail\n");
        !          1176:                        ahb_send_mbox(unit,OP_ABORT_ECB,xs->targ,ecb);
        !          1177:                        if(ahb_poll(unit,2000))
        !          1178:                        {
        !          1179:                                printf("abort failed in wait\n");
        !          1180:                                ahb_free_ecb(unit,ecb,flags);
        !          1181:                        }
        !          1182:                        xs->error = XS_DRIVER_STUFFUP;
        !          1183:                        splx(s);
        !          1184:                        return(HAD_ERROR);
        !          1185:                }
        !          1186:        } while (!(xs->flags & ITSDONE));/* something (?) else finished */
        !          1187:        splx(s);
        !          1188: scsi_debug = 0;ahb_debug = 0;
        !          1189:        if(xs->error)
        !          1190:        {
        !          1191:                return(HAD_ERROR);
        !          1192:        }
        !          1193:        return(COMPLETE);
        !          1194: }
        !          1195: 
        !          1196: /*
        !          1197:  *                +----------+    +----------+    +----------+
        !          1198:  * ahb_soonest--->|    later |--->|     later|--->|     later|--->0
        !          1199:  *                | [Delta]  |    | [Delta]  |    | [Delta]  |
        !          1200:  *           0<---|sooner    |<---|sooner    |<---|sooner    |<---ahb_latest
        !          1201:  *                +----------+    +----------+    +----------+
        !          1202:  *
        !          1203:  *     ahb_furtherest = sum(Delta[1..n])
        !          1204:  */
        !          1205: ahb_add_timeout(ecb,time)
        !          1206: struct ecb     *ecb;
        !          1207: int    time;
        !          1208: {
        !          1209:        int     timeprev;
        !          1210:        struct ecb *prev;
        !          1211:        int     s = splbio();
        !          1212: 
        !          1213:        if(prev = ahb_latest) /* yes, an assign */
        !          1214:        {
        !          1215:                timeprev = ahb_furtherest;
        !          1216:        }
        !          1217:        else
        !          1218:        {
        !          1219:                timeprev = 0;
        !          1220:        }
        !          1221:        while(prev && (timeprev > time)) 
        !          1222:        {
        !          1223:                timeprev -= prev->delta;
        !          1224:                prev = prev->sooner;
        !          1225:        }
        !          1226:        if(prev)
        !          1227:        {
        !          1228:                ecb->delta = time - timeprev;
        !          1229:                if( ecb->later = prev->later) /* yes an assign */
        !          1230:                {
        !          1231:                        ecb->later->sooner = ecb;
        !          1232:                        ecb->later->delta -= ecb->delta;
        !          1233:                }
        !          1234:                else
        !          1235:                {
        !          1236:                        ahb_furtherest = time;
        !          1237:                        ahb_latest = ecb;
        !          1238:                }
        !          1239:                ecb->sooner = prev;
        !          1240:                prev->later = ecb;
        !          1241:        }
        !          1242:        else
        !          1243:        {
        !          1244:                if( ecb->later = ahb_soonest) /* yes, an assign*/
        !          1245:                {
        !          1246:                        ecb->later->sooner = ecb;
        !          1247:                        ecb->later->delta -= time;
        !          1248:                }
        !          1249:                else
        !          1250:                {
        !          1251:                        ahb_furtherest = time;
        !          1252:                        ahb_latest = ecb;
        !          1253:                }
        !          1254:                ecb->delta = time;
        !          1255:                ecb->sooner = (struct ecb *)0;
        !          1256:                ahb_soonest = ecb;
        !          1257:        }
        !          1258:        splx(s);
        !          1259: }
        !          1260: 
        !          1261: ahb_remove_timeout(ecb)
        !          1262: struct ecb     *ecb;
        !          1263: {
        !          1264:        int     s = splbio();
        !          1265: 
        !          1266:        if(ecb->sooner)
        !          1267:        {
        !          1268:                ecb->sooner->later = ecb->later;
        !          1269:        }
        !          1270:        else
        !          1271:        {
        !          1272:                ahb_soonest = ecb->later;
        !          1273:        }
        !          1274:        if(ecb->later)
        !          1275:        {
        !          1276:                ecb->later->sooner = ecb->sooner;
        !          1277:                ecb->later->delta += ecb->delta;
        !          1278:        }
        !          1279:        else
        !          1280:        {
        !          1281:                ahb_latest = ecb->sooner;
        !          1282:                ahb_furtherest -= ecb->delta;
        !          1283:        }
        !          1284:        ecb->sooner = ecb->later = (struct ecb *)0;
        !          1285:        splx(s);
        !          1286: }
        !          1287: 
        !          1288: 
        !          1289: extern int     hz;
        !          1290: #define ONETICK 500 /* milliseconds */
        !          1291: #define SLEEPTIME ((hz * 1000) / ONETICK)
        !          1292: ahb_timeout(arg)
        !          1293: int    arg;
        !          1294: {
        !          1295:        struct  ecb  *ecb;
        !          1296:        int     unit;
        !          1297:        int     s       = splbio();
        !          1298: 
        !          1299:        while( ecb = ahb_soonest )
        !          1300:        {
        !          1301:                if(ecb->delta <= ONETICK)
        !          1302:                /***********************************************\
        !          1303:                * It has timed out, we need to do some work     *
        !          1304:                \***********************************************/
        !          1305:                {
        !          1306:                        unit = ecb->xs->adapter;
        !          1307:                        printf("ahb%d:%d device timed out\n",unit
        !          1308:                                        ,ecb->xs->targ);
        !          1309:                        if(ahb_debug & AHB_SHOWECBS)
        !          1310:                                ahb_print_active_ecb();
        !          1311: 
        !          1312:                        /***************************************\
        !          1313:                        * Unlink it from the queue              *
        !          1314:                        \***************************************/
        !          1315:                        ahb_remove_timeout(ecb);
        !          1316: 
        !          1317:                        /***************************************\
        !          1318:                        * If it's immediate, don't try abort it *
        !          1319:                        \***************************************/
        !          1320:                        if(ecb->flags & ECB_IMMED)
        !          1321:                        {
        !          1322:                                ecb->xs->retries = 0; /* I MEAN IT ! */
        !          1323:                                ecb->flags |= ECB_IMMED_FAIL;
        !          1324:                                 ahb_done(unit,ecb,FAIL);
        !          1325:                                continue;
        !          1326:                        }
        !          1327:                        /***************************************\
        !          1328:                        * If it has been through before, then   *
        !          1329:                        * a previous abort has failed, don't    *
        !          1330:                        * try abort again                       *
        !          1331:                        \***************************************/
        !          1332:                        if(ecb->flags == ECB_ABORTED) /* abort timed out */
        !          1333:                        {
        !          1334:                                printf("AGAIN");
        !          1335:                                ecb->xs->retries = 0; /* I MEAN IT ! */
        !          1336:                                ecb->ecb_status.ha_status = HS_CMD_ABORTED_HOST;
        !          1337:                                ahb_done(unit,ecb,FAIL);
        !          1338:                        }
        !          1339:                        else    /* abort the operation that has timed out */
        !          1340:                        {
        !          1341:                                printf("\n");
        !          1342:                                ahb_send_mbox(unit,OP_ABORT_ECB,ecb->xs->targ,ecb);
        !          1343:                                        /* 2 secs for the abort */
        !          1344:                                ahb_add_timeout(ecb,2000 + ONETICK);
        !          1345:                                ecb->flags = ECB_ABORTED;
        !          1346:                        }
        !          1347:                }
        !          1348:                else
        !          1349:                /***********************************************\
        !          1350:                * It has not timed out, adjust and leave        *
        !          1351:                \***********************************************/
        !          1352:                {
        !          1353:                        ecb->delta -= ONETICK;
        !          1354:                        ahb_furtherest -= ONETICK;
        !          1355:                        break;
        !          1356:                }
        !          1357:        }
        !          1358:        splx(s);
        !          1359:        timeout(ahb_timeout,arg,SLEEPTIME);
        !          1360: }
        !          1361: 
        !          1362: ahb_show_scsi_cmd(struct scsi_xfer *xs)
        !          1363: {
        !          1364:        u_char  *b = (u_char *)xs->cmd;
        !          1365:        int i = 0;
        !          1366:        if(!(xs->flags & SCSI_RESET))
        !          1367:        {
        !          1368:                printf("ahb%d:%d:%d-"
        !          1369:                        ,xs->adapter
        !          1370:                        ,xs->targ
        !          1371:                        ,xs->lu);
        !          1372:                while(i < xs->cmdlen )
        !          1373:                {
        !          1374:                        if(i) printf(",");
        !          1375:                        printf("%x",b[i++]);
        !          1376:                }
        !          1377:                printf("-\n");
        !          1378:        }
        !          1379:        else
        !          1380:        {
        !          1381:                printf("ahb%d:%d:%d-RESET-\n" 
        !          1382:                        ,xs->adapter 
        !          1383:                        ,xs->targ
        !          1384:                        ,xs->lu
        !          1385:                );
        !          1386:        }
        !          1387: }
        !          1388: ahb_print_ecb(ecb)
        !          1389: struct ecb *ecb;
        !          1390: {
        !          1391:        printf("ecb:%x op:%x cmdlen:%d senlen:%d\n"
        !          1392:                ,ecb
        !          1393:                ,ecb->opcode
        !          1394:                ,ecb->cdblen
        !          1395:                ,ecb->senselen);
        !          1396:        printf("        datlen:%d hstat:%x tstat:%x delta:%d flags:%x\n"
        !          1397:                ,ecb->datalen
        !          1398:                ,ecb->ecb_status.ha_status
        !          1399:                ,ecb->ecb_status.targ_status
        !          1400:                ,ecb->delta
        !          1401:                ,ecb->flags);
        !          1402:        ahb_show_scsi_cmd(ecb->xs);
        !          1403: }
        !          1404: 
        !          1405: ahb_print_active_ecb()
        !          1406: {
        !          1407:        struct  ecb *ecb;
        !          1408:        ecb = ahb_soonest;
        !          1409: 
        !          1410:        while(ecb)
        !          1411:        {
        !          1412:                ahb_print_ecb(ecb);
        !          1413:                ecb = ecb->later;
        !          1414:        }
        !          1415:        printf("Furtherest = %d\n",ahb_furtherest);
        !          1416: }

unix.superglobalmegacorp.com

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