[BACK]Return to aha1742.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / i386 / eisa

Annotation of src/sys/arch/i386/eisa/aha1742.c, Revision 1.7

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

CVSweb <webmaster@jp.NetBSD.org>