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

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

1.1     ! nbrk        1: /*     $OpenBSD: ahc_eisa.c,v 1.18 2007/04/10 17:47:55 miod Exp $      */
        !             2: /*     $NetBSD: ahc_eisa.c,v 1.10 1996/10/21 22:30:58 thorpej Exp $    */
        !             3:
        !             4: /*
        !             5:  * Product specific probe and attach routines for:
        !             6:  *     27/284X and aic7770 motherboard SCSI controllers
        !             7:  *
        !             8:  * Copyright (c) 1994, 1995, 1996 Justin T. Gibbs.
        !             9:  * All rights reserved.
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice immediately at the beginning of the file, without modification,
        !            16:  *    this list of conditions, and the following disclaimer.
        !            17:  * 2. Redistributions in binary form must reproduce the above copyright
        !            18:  *    notice, this list of conditions and the following disclaimer in the
        !            19:  *    documentation and/or other materials provided with the distribution.
        !            20:  * 3. The name of the author may not be used to endorse or promote products
        !            21:  *    derived from this software without specific prior written permission.
        !            22:  *
        !            23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            26:  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
        !            27:  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            33:  * SUCH DAMAGE.
        !            34:  *
        !            35:  *     $Id: ahc_eisa.c,v 1.18 2007/04/10 17:47:55 miod Exp $
        !            36:  */
        !            37:
        !            38: #include "eisa.h"
        !            39: #if NEISA > 0
        !            40:
        !            41: #include <sys/param.h>
        !            42: #include <sys/systm.h>
        !            43: #include <sys/kernel.h>
        !            44: #include <sys/device.h>
        !            45: #include <machine/bus.h>
        !            46: #include <machine/intr.h>
        !            47:
        !            48: #include <scsi/scsi_all.h>
        !            49: #include <scsi/scsiconf.h>
        !            50:
        !            51: #include <dev/eisa/eisareg.h>
        !            52: #include <dev/eisa/eisavar.h>
        !            53: #include <dev/eisa/eisadevs.h>
        !            54: #include <dev/ic/aic7xxx_openbsd.h>
        !            55: #include <dev/ic/aic7xxx_inline.h>
        !            56:
        !            57: #define AHC_EISA_SLOT_OFFSET   0xc00
        !            58: #define AHC_EISA_IOSIZE                0x100
        !            59:
        !            60: int   ahc_eisa_irq(bus_space_tag_t, bus_space_handle_t);
        !            61: int   ahc_eisa_match(struct device *, void *, void *);
        !            62: void  ahc_eisa_attach(struct device *, struct device *, void *);
        !            63:
        !            64:
        !            65: struct cfattach ahc_eisa_ca = {
        !            66:        sizeof(struct ahc_softc), ahc_eisa_match, ahc_eisa_attach
        !            67: };
        !            68:
        !            69: /*
        !            70:  * Return irq setting of the board, otherwise -1.
        !            71:  */
        !            72: int
        !            73: ahc_eisa_irq(iot, ioh)
        !            74: bus_space_tag_t iot;
        !            75: bus_space_handle_t ioh;
        !            76: {
        !            77:        int irq;
        !            78:        u_char intdef;
        !            79:        u_char hcntrl;
        !            80:
        !            81:        /* Pause the card preserving the IRQ type */
        !            82:        hcntrl = bus_space_read_1(iot, ioh, HCNTRL) & IRQMS;
        !            83:        bus_space_write_1(iot, ioh, HCNTRL, hcntrl | PAUSE);
        !            84:
        !            85:        intdef = bus_space_read_1(iot, ioh, INTDEF);
        !            86:        switch (irq = (intdef & VECTOR)) {
        !            87:        case 9:
        !            88:        case 10:
        !            89:        case 11:
        !            90:        case 12:
        !            91:        case 14:
        !            92:        case 15:
        !            93:                break;
        !            94:        default:
        !            95:                printf("ahc_eisa_irq: illegal irq setting %d\n", intdef);
        !            96:                return -1;
        !            97:        }
        !            98:
        !            99:        /* Note that we are going and return (to probe) */
        !           100:        return irq;
        !           101: }
        !           102:
        !           103: /*
        !           104:  * Check the slots looking for a board we recognise
        !           105:  * If we find one, note its address (slot) and call
        !           106:  * the actual probe routine to check it out.
        !           107:  */
        !           108: int
        !           109: ahc_eisa_match(parent, match, aux)
        !           110: struct device *parent;
        !           111: void *match, *aux;
        !           112: {
        !           113:        struct eisa_attach_args *ea = aux;
        !           114:        bus_space_tag_t iot = ea->ea_iot;
        !           115:        bus_space_handle_t ioh;
        !           116:        int irq;
        !           117:
        !           118:        /* must match one of our known ID strings */
        !           119:        if (strcmp(ea->ea_idstring, "ADP7770") &&
        !           120:                 strcmp(ea->ea_idstring, "ADP7771")
        !           121: #if 0
        !           122:                 && strcmp(ea->ea_idstring, "ADP7756")  /* not EISA, but VL */
        !           123:                 && strcmp(ea->ea_idstring, "ADP7757")  /* not EISA, but VL */
        !           124: #endif
        !           125:                )
        !           126:                return (0);
        !           127:
        !           128:        if (bus_space_map(iot, EISA_SLOT_ADDR(ea->ea_slot) +
        !           129:                          AHC_EISA_SLOT_OFFSET, AHC_EISA_IOSIZE, 0, &ioh))
        !           130:                return (0);
        !           131:
        !           132:        irq = ahc_eisa_irq(iot, ioh);
        !           133:
        !           134:        bus_space_unmap(iot, ioh, AHC_EISA_IOSIZE);
        !           135:
        !           136:        return (irq >= 0);
        !           137: }
        !           138:
        !           139: void
        !           140: ahc_eisa_attach(parent, self, aux)
        !           141: struct device *parent, *self;
        !           142: void *aux;
        !           143: {
        !           144:        struct ahc_softc *ahc = (void *)self;
        !           145:        struct eisa_attach_args *ea = aux;
        !           146:        bus_space_tag_t iot = ea->ea_iot;
        !           147:        bus_space_handle_t ioh;
        !           148:        int irq;
        !           149:        eisa_chipset_tag_t ec = ea->ea_ec;
        !           150:        eisa_intr_handle_t ih;
        !           151:        const char *model, *intrstr;
        !           152:        u_int biosctrl;
        !           153:        u_int scsiconf;
        !           154:        u_int scsiconf1;
        !           155:        u_int intdef;
        !           156:
        !           157:        ahc_set_name(ahc, ahc->sc_dev.dv_xname);
        !           158:        ahc_set_unit(ahc, ahc->sc_dev.dv_unit);
        !           159:
        !           160:        /* set dma tags */
        !           161:        ahc->parent_dmat = ea->ea_dmat;
        !           162:
        !           163:        if (bus_space_map(iot, EISA_SLOT_ADDR(ea->ea_slot) +
        !           164:                          AHC_EISA_SLOT_OFFSET, AHC_EISA_IOSIZE, 0, &ioh))
        !           165:                panic("ahc_eisa_attach: could not map I/O addresses");
        !           166:        if ((irq = ahc_eisa_irq(iot, ioh)) < 0)
        !           167:                panic("ahc_eisa_attach: ahc_eisa_irq failed!");
        !           168:
        !           169:        if (strcmp(ea->ea_idstring, "ADP7770") == 0) {
        !           170:                model = EISA_PRODUCT_ADP7770;
        !           171:        } else if (strcmp(ea->ea_idstring, "ADP7771") == 0) {
        !           172:                model = EISA_PRODUCT_ADP7771;
        !           173:        } else {
        !           174:                panic("ahc_eisa_attach: Unknown device type %s",
        !           175:                                ea->ea_idstring);
        !           176:        }
        !           177:        printf(": %s\n", model);
        !           178:
        !           179:        ahc->channel = 'A';
        !           180:        ahc->chip = AHC_AIC7770|AHC_EISA;
        !           181:        ahc->features = AHC_AIC7770_FE;
        !           182:        ahc->bugs |= AHC_TMODE_WIDEODD_BUG;
        !           183:        ahc->flags |= AHC_PAGESCBS;
        !           184:
        !           185:        if (ahc_reset(ahc, /*reinit*/FALSE) != 0)
        !           186:                return;
        !           187:
        !           188:        /* See if we are edge triggered */
        !           189:        intdef = ahc_inb(ahc, INTDEF);
        !           190:        if ((intdef & EDGE_TRIG) != 0)
        !           191:                ahc->flags |= AHC_EDGE_INTERRUPT;
        !           192:
        !           193:        if (eisa_intr_map(ec, irq, &ih)) {
        !           194:                printf("%s: couldn't map interrupt (%d)\n",
        !           195:                       ahc->sc_dev.dv_xname, irq);
        !           196:                return;
        !           197:        }
        !           198:
        !           199:        /*
        !           200:         * Tell the user what type of interrupts we're using.
        !           201:         * useful for debugging irq problems
        !           202:         */
        !           203:        if (bootverbose) {
        !           204:                printf("%s: Using %s Interrupts\n",
        !           205:                       ahc_name(ahc),
        !           206:                       ahc->pause & IRQMS ?
        !           207:                       "Level Sensitive" : "Edge Triggered");
        !           208:        }
        !           209:
        !           210:        /*
        !           211:         * Now that we know we own the resources we need, do the
        !           212:         * card initialization.
        !           213:         *
        !           214:         * First, the aic7770 card specific setup.
        !           215:         */
        !           216:        biosctrl = ahc_inb(ahc, HA_274_BIOSCTRL);
        !           217:        scsiconf = ahc_inb(ahc, SCSICONF);
        !           218:        scsiconf1 = ahc_inb(ahc, SCSICONF + 1);
        !           219:
        !           220:        /* Get the primary channel information */
        !           221:        if ((biosctrl & CHANNEL_B_PRIMARY) != 0)
        !           222:                ahc->flags |= AHC_PRIMARY_CHANNEL;
        !           223:
        !           224:        if ((biosctrl & BIOSMODE) == BIOSDISABLED) {
        !           225:                ahc->flags |= AHC_USEDEFAULTS;
        !           226:        } else if ((ahc->features & AHC_WIDE) != 0) {
        !           227:                ahc->our_id = scsiconf1 & HWSCSIID;
        !           228:                if (scsiconf & TERM_ENB)
        !           229:                        ahc->flags |= AHC_TERM_ENB_A;
        !           230:        } else {
        !           231:                ahc->our_id = scsiconf & HSCSIID;
        !           232:                ahc->our_id_b = scsiconf1 & HSCSIID;
        !           233:                if (scsiconf & TERM_ENB)
        !           234:                        ahc->flags |= AHC_TERM_ENB_A;
        !           235:                if (scsiconf1 & TERM_ENB)
        !           236:                        ahc->flags |= AHC_TERM_ENB_B;
        !           237:        }
        !           238:        /*
        !           239:         * We have no way to tell, so assume extended
        !           240:         * translation is enabled.
        !           241:         */
        !           242:
        !           243:        ahc->flags |= AHC_EXTENDED_TRANS_A|AHC_EXTENDED_TRANS_B;
        !           244:
        !           245:        /*
        !           246:         * See if we have a Rev E or higher aic7770. Anything below a
        !           247:         * Rev E will have a R/O autoflush disable configuration bit.
        !           248:         * It's still not clear exactly what is different about the Rev E.
        !           249:         * We think it allows 8 bit entries in the QOUTFIFO to support
        !           250:         * "paging" SCBs so you can have more than 4 commands active at
        !           251:         * once.
        !           252:         */
        !           253:        {
        !           254:                char *id_string;
        !           255:                u_char sblkctl;
        !           256:                u_char sblkctl_orig;
        !           257:
        !           258:                sblkctl_orig = ahc_inb(ahc, SBLKCTL);
        !           259:                sblkctl = sblkctl_orig ^ AUTOFLUSHDIS;
        !           260:                ahc_outb(ahc, SBLKCTL, sblkctl);
        !           261:                sblkctl = ahc_inb(ahc, SBLKCTL);
        !           262:                if (sblkctl != sblkctl_orig) {
        !           263:                        id_string = "aic7770 >= Rev E, ";
        !           264:                        /*
        !           265:                         * Ensure autoflush is enabled
        !           266:                         */
        !           267:                        sblkctl &= ~AUTOFLUSHDIS;
        !           268:                        ahc_outb(ahc, SBLKCTL, sblkctl);
        !           269:
        !           270:                        /* Allow paging on this adapter */
        !           271:                        ahc->flags |= AHC_PAGESCBS;
        !           272:                } else
        !           273:                        id_string = "aic7770 <= Rev C, ";
        !           274:
        !           275:                printf("%s: %s", ahc_name(ahc), id_string);
        !           276:        }
        !           277:
        !           278:        /* Setup the FIFO threshold and the bus off time */
        !           279:        {
        !           280:                u_char hostconf = ahc_inb(ahc, HOSTCONF);
        !           281:                ahc_outb(ahc, BUSSPD, hostconf & DFTHRSH);
        !           282:                ahc_outb(ahc, BUSTIME, (hostconf << 2) & BOFF);
        !           283:        }
        !           284:
        !           285:        /*
        !           286:         * Generic aic7xxx initialization.
        !           287:         */
        !           288:        if (ahc_init(ahc)) {
        !           289:                ahc_free(ahc);
        !           290:                return;
        !           291:        }
        !           292:
        !           293:        /*
        !           294:         * Link this softc in with all other ahc instances.
        !           295:         */
        !           296:        ahc_softc_insert(ahc);
        !           297:
        !           298:        /*
        !           299:         * Enable the board's BUS drivers
        !           300:         */
        !           301:        ahc_outb(ahc, BCTL, ENABLE);
        !           302:
        !           303:        intrstr = eisa_intr_string(ec, ih);
        !           304:        /*
        !           305:         * The IRQMS bit enables level sensitive interrupts only allow
        !           306:         * IRQ sharing if its set.
        !           307:         */
        !           308:        ahc->ih = eisa_intr_establish(ec, ih,
        !           309:            ahc->pause & IRQMS ? IST_LEVEL : IST_EDGE, IPL_BIO,
        !           310:            ahc_platform_intr, ahc, ahc->sc_dev.dv_xname);
        !           311:        if (ahc->ih == NULL) {
        !           312:                printf("%s: couldn't establish interrupt",
        !           313:                       ahc->sc_dev.dv_xname);
        !           314:                if (intrstr != NULL)
        !           315:                        printf(" at %s", intrstr);
        !           316:                printf("\n");
        !           317:                ahc_free(ahc);
        !           318:                return;
        !           319:        }
        !           320:        if (intrstr != NULL)
        !           321:                printf("%s: interrupting at %s\n", ahc->sc_dev.dv_xname,
        !           322:                       intrstr);
        !           323:
        !           324:        ahc_intr_enable(ahc, TRUE);
        !           325:
        !           326:        /* Attach sub-devices - always succeeds */
        !           327:        ahc_attach(ahc);
        !           328:
        !           329: }
        !           330: #endif /* NEISA > 0 */

CVSweb