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

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

unix.superglobalmegacorp.com

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