[BACK]Return to aha1742.c CVS log [TXT][DIR] Up to [local] / sys / dev / eisa

Annotation of sys/dev/eisa/aha1742.c, Revision 1.1

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

CVSweb