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