[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

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