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

Annotation of sys/dev/isa/uha_isa.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: uha_isa.c,v 1.8 2007/04/10 17:47:55 miod Exp $        */
                      2: /*     $NetBSD: uha_isa.c,v 1.5 1996/10/21 22:41:21 thorpej Exp $      */
                      3:
                      4: /*
                      5:  * Copyright (c) 1994, 1996 Charles M. 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 M. 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: #include <sys/types.h>
                     34: #include <sys/param.h>
                     35: #include <sys/systm.h>
                     36: #include <sys/device.h>
                     37: #include <sys/kernel.h>
                     38: #include <sys/proc.h>
                     39: #include <sys/user.h>
                     40:
                     41: #include <machine/bus.h>
                     42: #include <machine/intr.h>
                     43:
                     44: #include <scsi/scsi_all.h>
                     45: #include <scsi/scsiconf.h>
                     46:
                     47: #include <dev/isa/isavar.h>
                     48: #include <dev/isa/isadmavar.h>
                     49:
                     50: #include <dev/ic/uhareg.h>
                     51: #include <dev/ic/uhavar.h>
                     52:
                     53: #define        UHA_ISA_IOSIZE  16
                     54:
                     55: #ifndef DDB
                     56: #define        Debugger() panic("should call debugger here (uha_isa.c)")
                     57: #endif
                     58:
                     59: int    uha_isa_probe(struct device *, void *, void *);
                     60: void   uha_isa_attach(struct device *, struct device *, void *);
                     61:
                     62: struct cfattach uha_isa_ca = {
                     63:        sizeof(struct uha_softc), uha_isa_probe, uha_isa_attach
                     64: };
                     65:
                     66: #define KVTOPHYS(x)    vtophys((vaddr_t)(x))
                     67:
                     68: int u14_find(bus_space_tag_t, bus_space_handle_t, struct uha_softc *);
                     69: void u14_start_mbox(struct uha_softc *, struct uha_mscp *);
                     70: int u14_poll(struct uha_softc *, struct scsi_xfer *, int);
                     71: int u14_intr(void *);
                     72: void u14_init(struct uha_softc *);
                     73:
                     74: /*
                     75:  * Check the slots looking for a board we recognise
                     76:  * If we find one, note its address (slot) and call
                     77:  * the actual probe routine to check it out.
                     78:  */
                     79: int
                     80: uha_isa_probe(parent, match, aux)
                     81:        struct device *parent;
                     82:        void *match, *aux;
                     83: {
                     84:        struct isa_attach_args *ia = aux;
                     85:        struct uha_softc sc;
                     86:        bus_space_tag_t iot = ia->ia_iot;
                     87:        bus_space_handle_t ioh;
                     88:        int rv;
                     89:
                     90:        if (bus_space_map(iot, ia->ia_iobase, UHA_ISA_IOSIZE, 0, &ioh))
                     91:                return (0);
                     92:
                     93:        rv = u14_find(iot, ioh, &sc);
                     94:
                     95:        bus_space_unmap(iot, ioh, UHA_ISA_IOSIZE);
                     96:
                     97:        if (rv) {
                     98:                if (ia->ia_irq != -1 && ia->ia_irq != sc.sc_irq)
                     99:                        return (0);
                    100:                if (ia->ia_drq != -1 && ia->ia_drq != sc.sc_drq)
                    101:                        return (0);
                    102:                ia->ia_irq = sc.sc_irq;
                    103:                ia->ia_drq = sc.sc_drq;
                    104:                ia->ia_msize = 0;
                    105:                ia->ia_iosize = UHA_ISA_IOSIZE;
                    106:        }
                    107:        return (rv);
                    108: }
                    109:
                    110: /*
                    111:  * Attach all the sub-devices we can find
                    112:  */
                    113: void
                    114: uha_isa_attach(parent, self, aux)
                    115:        struct device *parent, *self;
                    116:        void *aux;
                    117: {
                    118:        struct isa_attach_args *ia = aux;
                    119:        struct uha_softc *sc = (void *)self;
                    120:        bus_space_tag_t iot = ia->ia_iot;
                    121:        bus_space_handle_t ioh;
                    122:        isa_chipset_tag_t ic = ia->ia_ic;
                    123:
                    124:        printf("\n");
                    125:
                    126:        if (bus_space_map(iot, ia->ia_iobase, UHA_ISA_IOSIZE, 0, &ioh))
                    127:                panic("uha_attach: bus_space_map failed!");
                    128:
                    129:        sc->sc_iot = iot;
                    130:        sc->sc_ioh = ioh;
                    131:        if (!u14_find(iot, ioh, sc))
                    132:                panic("uha_attach: u14_find failed!");
                    133:
                    134:        if (sc->sc_drq != -1)
                    135:                isadma_cascade(sc->sc_drq);
                    136:
                    137:        sc->sc_ih = isa_intr_establish(ic, sc->sc_irq, IST_EDGE, IPL_BIO,
                    138:            u14_intr, sc, sc->sc_dev.dv_xname);
                    139:        if (sc->sc_ih == NULL) {
                    140:                printf("%s: couldn't establish interrupt\n",
                    141:                    sc->sc_dev.dv_xname);
                    142:                return;
                    143:        }
                    144:
                    145:        /* Save function pointers for later use. */
                    146:        sc->start_mbox = u14_start_mbox;
                    147:        sc->poll = u14_poll;
                    148:        sc->init = u14_init;
                    149:
                    150:        uha_attach(sc);
                    151: }
                    152:
                    153: /*
                    154:  * Start the board, ready for normal operation
                    155:  */
                    156: int
                    157: u14_find(iot, ioh, sc)
                    158:        bus_space_tag_t iot;
                    159:        bus_space_handle_t ioh;
                    160:        struct uha_softc *sc;
                    161: {
                    162:        u_int16_t model, config;
                    163:        int irq, drq;
                    164:        int resetcount = 4000;  /* 4 secs? */
                    165:
                    166:        model = (bus_space_read_1(iot, ioh, U14_ID + 0) << 8) |
                    167:                (bus_space_read_1(iot, ioh, U14_ID + 1) << 0);
                    168:        if ((model & 0xfff0) != 0x5640)
                    169:                return (0);
                    170:
                    171:        config = (bus_space_read_1(iot, ioh, U14_CONFIG + 0) << 8) |
                    172:                 (bus_space_read_1(iot, ioh, U14_CONFIG + 1) << 0);
                    173:
                    174:        switch (model & 0x000f) {
                    175:        case 0x0000:
                    176:                switch (config & U14_DMA_MASK) {
                    177:                case U14_DMA_CH5:
                    178:                        drq = 5;
                    179:                        break;
                    180:                case U14_DMA_CH6:
                    181:                        drq = 6;
                    182:                        break;
                    183:                case U14_DMA_CH7:
                    184:                        drq = 7;
                    185:                        break;
                    186:                default:
                    187:                        printf("u14_find: illegal drq setting %x\n",
                    188:                            config & U14_DMA_MASK);
                    189:                        return (0);
                    190:                }
                    191:                break;
                    192:        case 0x0001:
                    193:                /* This is a 34f, and doesn't need an ISA DMA channel. */
                    194:                drq = -1;
                    195:                break;
                    196:        default:
                    197:                printf("u14_find: unknown model %x\n", model);
                    198:                return (0);
                    199:        }
                    200:
                    201:        switch (config & U14_IRQ_MASK) {
                    202:        case U14_IRQ10:
                    203:                irq = 10;
                    204:                break;
                    205:        case U14_IRQ11:
                    206:                irq = 11;
                    207:                break;
                    208:        case U14_IRQ14:
                    209:                irq = 14;
                    210:                break;
                    211:        case U14_IRQ15:
                    212:                irq = 15;
                    213:                break;
                    214:        default:
                    215:                printf("u14_find: illegal irq setting %x\n",
                    216:                    config & U14_IRQ_MASK);
                    217:                return (0);
                    218:        }
                    219:
                    220:        bus_space_write_1(iot, ioh, U14_LINT, UHA_ASRST);
                    221:
                    222:        while (--resetcount) {
                    223:                if (bus_space_read_1(iot, ioh, U14_LINT))
                    224:                        break;
                    225:                delay(1000);    /* 1 mSec per loop */
                    226:        }
                    227:        if (!resetcount) {
                    228:                printf("u14_find: board timed out during reset\n");
                    229:                return (0);
                    230:        }
                    231:
                    232:        /* if we want to fill in softc, do so now */
                    233:        if (sc != NULL) {
                    234:                sc->sc_irq = irq;
                    235:                sc->sc_drq = drq;
                    236:                sc->sc_scsi_dev = config & U14_HOSTID_MASK;
                    237:        }
                    238:
                    239:        return (1);
                    240: }
                    241:
                    242: /*
                    243:  * Function to send a command out through a mailbox
                    244:  */
                    245: void
                    246: u14_start_mbox(sc, mscp)
                    247:        struct uha_softc *sc;
                    248:        struct uha_mscp *mscp;
                    249: {
                    250:        bus_space_tag_t iot = sc->sc_iot;
                    251:        bus_space_handle_t ioh = sc->sc_ioh;
                    252:        int spincount = 100000; /* 1s should be enough */
                    253:
                    254:        while (--spincount) {
                    255:                if ((bus_space_read_1(iot, ioh, U14_LINT) & U14_LDIP) == 0)
                    256:                        break;
                    257:                delay(100);
                    258:        }
                    259:        if (!spincount) {
                    260:                printf("%s: uha_start_mbox, board not responding\n",
                    261:                    sc->sc_dev.dv_xname);
                    262:                Debugger();
                    263:        }
                    264:
                    265:        bus_space_write_4(iot, ioh, U14_OGMPTR, KVTOPHYS(mscp));
                    266:        if (mscp->flags & MSCP_ABORT)
                    267:                bus_space_write_1(iot, ioh, U14_LINT, U14_ABORT);
                    268:        else
                    269:                bus_space_write_1(iot, ioh, U14_LINT, U14_OGMFULL);
                    270:
                    271:        if ((mscp->xs->flags & SCSI_POLL) == 0)
                    272:                timeout_add(&mscp->xs->stimeout, (mscp->timeout * hz) / 1000);
                    273: }
                    274:
                    275: /*
                    276:  * Function to poll for command completion when in poll mode.
                    277:  *
                    278:  *     wait = timeout in msec
                    279:  */
                    280: int
                    281: u14_poll(sc, xs, count)
                    282:        struct uha_softc *sc;
                    283:        struct scsi_xfer *xs;
                    284:        int count;
                    285: {
                    286:        bus_space_tag_t iot = sc->sc_iot;
                    287:        bus_space_handle_t ioh = sc->sc_ioh;
                    288:
                    289:        while (count) {
                    290:                /*
                    291:                 * If we had interrupts enabled, would we
                    292:                 * have got an interrupt?
                    293:                 */
                    294:                if (bus_space_read_1(iot, ioh, U14_SINT) & U14_SDIP)
                    295:                        u14_intr(sc);
                    296:                if (xs->flags & ITSDONE)
                    297:                        return (0);
                    298:                delay(1000);
                    299:                count--;
                    300:        }
                    301:        return (1);
                    302: }
                    303:
                    304: /*
                    305:  * Catch an interrupt from the adaptor
                    306:  */
                    307: int
                    308: u14_intr(arg)
                    309:        void *arg;
                    310: {
                    311:        struct uha_softc *sc = arg;
                    312:        bus_space_tag_t iot = sc->sc_iot;
                    313:        bus_space_handle_t ioh = sc->sc_ioh;
                    314:        struct uha_mscp *mscp;
                    315:        u_char uhastat;
                    316:        u_long mboxval;
                    317:
                    318: #ifdef UHADEBUG
                    319:        printf("%s: uhaintr ", sc->sc_dev.dv_xname);
                    320: #endif /*UHADEBUG */
                    321:
                    322:        if ((bus_space_read_1(iot, ioh, U14_SINT) & U14_SDIP) == 0)
                    323:                return (0);
                    324:
                    325:        for (;;) {
                    326:                /*
                    327:                 * First get all the information and then
                    328:                 * acknowledge the interrupt
                    329:                 */
                    330:                uhastat = bus_space_read_1(iot, ioh, U14_SINT);
                    331:                mboxval = bus_space_read_4(iot, ioh, U14_ICMPTR);
                    332:                /* XXX Send an ABORT_ACK instead? */
                    333:                bus_space_write_1(iot, ioh, U14_SINT, U14_ICM_ACK);
                    334:
                    335: #ifdef UHADEBUG
                    336:                printf("status = 0x%x ", uhastat);
                    337: #endif /*UHADEBUG*/
                    338:
                    339:                /*
                    340:                 * Process the completed operation
                    341:                 */
                    342:                mscp = uha_mscp_phys_kv(sc, mboxval);
                    343:                if (!mscp) {
                    344:                        printf("%s: BAD MSCP RETURNED!\n",
                    345:                            sc->sc_dev.dv_xname);
                    346:                        continue;       /* whatever it was, it'll timeout */
                    347:                }
                    348:
                    349:                timeout_del(&mscp->xs->stimeout);
                    350:                uha_done(sc, mscp);
                    351:
                    352:                if ((bus_space_read_1(iot, ioh, U14_SINT) & U14_SDIP) == 0)
                    353:                        return (1);
                    354:        }
                    355: }
                    356:
                    357: void
                    358: u14_init(sc)
                    359:        struct uha_softc *sc;
                    360: {
                    361:        bus_space_tag_t iot = sc->sc_iot;
                    362:        bus_space_handle_t ioh = sc->sc_ioh;
                    363:
                    364:        /* make sure interrupts are enabled */
                    365: #ifdef UHADEBUG
                    366:        printf("u14_init: lmask=%02x, smask=%02x\n",
                    367:            bus_space_read_1(iot, ioh, U14_LMASK),
                    368:            bus_space_read_1(iot, ioh, U14_SMASK));
                    369: #endif
                    370:        bus_space_write_1(iot, ioh, U14_LMASK, 0xd1);   /* XXX */
                    371:        bus_space_write_1(iot, ioh, U14_SMASK, 0x91);   /* XXX */
                    372: }

CVSweb