[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.24

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

CVSweb <webmaster@jp.NetBSD.org>