void ahc_isa_attach(device_t parent, device_t self, void *aux) { struct ahc_softc *ahc = device_private(self); struct isa_attach_args *ia = aux; bus_space_tag_t iot = ia->ia_iot; bus_space_handle_t ioh; int irq, intrtype; const char *intrtypestr; char idstring[EISA_IDSTRINGLEN]; u_char intdef; ahc->sc_dev = self; aprint_naive(": SCSI controller\n"); if (bus_space_map(iot, ia->ia_io[0].ir_addr, ia->ia_io[0].ir_size, 0, &ioh)) { aprint_error(": can't map i/o space\n"); return; } if (!ahc_isa_idstring(iot, ioh, idstring)) { aprint_error(": can't read ID string\n"); goto free_io; } if ((irq = ahc_aic77xx_irq(iot, ioh)) < 0) { aprint_error(": ahc_aic77xx_irq failed\n"); goto free_io; } if (strcmp(idstring, "ADP7756") == 0) { aprint_normal(": %s\n", EISA_PRODUCT_ADP7756); } else if (strcmp(idstring, "ADP7757") == 0) { aprint_normal(": %s\n", EISA_PRODUCT_ADP7757); } else { aprint_error(": unknown device type %s\n", idstring); goto free_io; } /* * Tell the bus-DMA interface that we can do 32bit DMA * NOTE: this variable is first referenced in ahc_init(). */ ahc->sc_dmaflags = ISABUS_DMA_32BIT; ahc_set_name(ahc, device_xname(ahc->sc_dev)); ahc->parent_dmat = ia->ia_dmat; ahc->channel = 'A'; ahc->chip = AHC_AIC7770|AHC_VL; ahc->features = AHC_AIC7770_FE; ahc->bugs |= AHC_TMODE_WIDEODD_BUG; ahc->flags |= AHC_PAGESCBS; ahc->tag = iot; ahc->bsh = ioh; if (ahc_softc_init(ahc) != 0) goto free_io; ahc_intr_enable(ahc, false); if (ahc_reset(ahc) != 0) goto free_io; intdef = bus_space_read_1(iot, ioh, INTDEF); if (intdef & EDGE_TRIG) { intrtype = IST_EDGE; intrtypestr = "edge triggered"; } else { intrtype = IST_LEVEL; intrtypestr = "level sensitive"; } ahc->ih = isa_intr_establish(ia->ia_ic, irq, intrtype, IPL_BIO, ahc_intr, ahc); if (ahc->ih == NULL) { aprint_error_dev(ahc->sc_dev, "couldn't establish %s interrupt\n", intrtypestr); goto free_io; } /* * Tell the user what type of interrupts we're using. * useful for debugging irq problems */ if (bootverbose) { aprint_verbose_dev(ahc->sc_dev, "Using %s interrupts\n", intrtypestr); } /* * Now that we know we own the resources we need, do the * card initialization. */ aha2840_load_seeprom(ahc); /* Attach sub-devices */ if (ahc_aic77xx_attach(ahc) == 0) return; /* succeed */ /* failed */ isa_intr_disestablish(ia->ia_ic, ahc->ih); free_io: bus_space_unmap(iot, ioh, ia->ia_io[0].ir_size); }
int aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io) { u_long l; u_long s; int error; int have_seeprom; u_int hostconf; u_int irq; u_int intdef; error = entry->setup(ahc); have_seeprom = 0; if (error != 0) return (error); error = aic7770_map_registers(ahc, io); if (error != 0) return (error); /* * Before we continue probing the card, ensure that * its interrupts are *disabled*. We don't want * a misstep to hang the machine in an interrupt * storm. */ ahc_intr_enable(ahc, FALSE); ahc->description = entry->name; error = ahc_softc_init(ahc); error = ahc_reset(ahc); if (error != 0) return (error); /* Make sure we have a valid interrupt vector */ intdef = ahc_inb(ahc, INTDEF); irq = intdef & VECTOR; switch (irq) { case 9: case 10: case 11: case 12: case 14: case 15: break; default: printf("aic7770_config: illegal irq setting %d\n", intdef); return (ENXIO); } if ((intdef & EDGE_TRIG) != 0) ahc->flags |= AHC_EDGE_INTERRUPT; switch (ahc->chip & (AHC_EISA|AHC_VL)) { case AHC_EISA: { u_int biosctrl; u_int scsiconf; u_int scsiconf1; biosctrl = ahc_inb(ahc, HA_274_BIOSCTRL); scsiconf = ahc_inb(ahc, SCSICONF); scsiconf1 = ahc_inb(ahc, SCSICONF + 1); /* Get the primary channel information */ if ((biosctrl & CHANNEL_B_PRIMARY) != 0) ahc->flags |= 1; if ((biosctrl & BIOSMODE) == BIOSDISABLED) { ahc->flags |= AHC_USEDEFAULTS; } else { if ((ahc->features & AHC_WIDE) != 0) { ahc->our_id = scsiconf1 & HWSCSIID; if (scsiconf & TERM_ENB) ahc->flags |= AHC_TERM_ENB_A; } else { ahc->our_id = scsiconf & HSCSIID; ahc->our_id_b = scsiconf1 & HSCSIID; if (scsiconf & TERM_ENB) ahc->flags |= AHC_TERM_ENB_A; if (scsiconf1 & TERM_ENB) ahc->flags |= AHC_TERM_ENB_B; } } if ((ahc_inb(ahc, HA_274_BIOSGLOBAL) & HA_274_EXTENDED_TRANS)) ahc->flags |= AHC_EXTENDED_TRANS_A|AHC_EXTENDED_TRANS_B; break; } case AHC_VL: { have_seeprom = aha2840_load_seeprom(ahc); break; } default: break; } if (have_seeprom == 0) { free(ahc->seep_config, M_DEVBUF); ahc->seep_config = NULL; } /* * Ensure autoflush is enabled */ ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~AUTOFLUSHDIS); /* Setup the FIFO threshold and the bus off time */ hostconf = ahc_inb(ahc, HOSTCONF); ahc_outb(ahc, BUSSPD, hostconf & DFTHRSH); ahc_outb(ahc, BUSTIME, (hostconf << 2) & BOFF); /* * Generic aic7xxx initialization. */ error = ahc_init(ahc); if (error != 0) return (error); error = aic7770_map_int(ahc, irq); if (error != 0) return (error); ahc_list_lock(&l); /* * Link this softc in with all other ahc instances. */ ahc_softc_insert(ahc); /* * Enable the board's BUS drivers */ ahc_outb(ahc, BCTL, ENABLE); /* * Allow interrupts. */ ahc_lock(ahc, &s); ahc_intr_enable(ahc, TRUE); ahc_unlock(ahc, &s); ahc_list_unlock(&l); return (0); }
void ahc_isa_attach(struct device *parent, struct device *self, void *aux) { struct ahc_softc *ahc = (void *)self; struct isa_attach_args *ia = aux; bus_space_tag_t iot = ia->ia_iot; bus_space_handle_t ioh; int irq; char idstring[EISA_IDSTRINGLEN]; const char *model; u_int intdef; ahc_set_name(ahc, ahc->sc_dev.dv_xname); ahc_set_unit(ahc, ahc->sc_dev.dv_unit); /* set dma tags */ ahc->parent_dmat = ia->ia_dmat; ahc->chip = AHC_VL; /* We are a VL Bus Controller */ if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh)) panic("ahc_isa_attach: can't map slot i/o addresses"); if (!ahc_isa_idstring(iot, ioh, idstring)) panic("ahc_isa_attach: could not read ID string"); if ((irq = ahc_isa_irq(iot, ioh)) < 0) panic("ahc_isa_attach: ahc_isa_irq failed!"); if (strcmp(idstring, "ADP7756") == 0) { model = EISA_PRODUCT_ADP7756; } else if (strcmp(idstring, "ADP7757") == 0) { model = EISA_PRODUCT_ADP7757; } else { panic("ahc_isa_attach: Unknown device type %s", idstring); } printf(": %s\n", model); ahc->channel = 'A'; ahc->chip = AHC_AIC7770; ahc->features = AHC_AIC7770_FE; ahc->bugs |= AHC_TMODE_WIDEODD_BUG; ahc->flags |= AHC_PAGESCBS; /* set tag and handle */ ahc->tag = iot; ahc->bsh = ioh; #ifdef DEBUG /* * Tell the user what type of interrupts we're using. * useful for debugging irq problems */ printf( "%s: Using %s Interrupts\n", ahc_name(ahc), ahc->pause & IRQMS ? "Level Sensitive" : "Edge Triggered"); #endif if (ahc_reset(ahc, /*reinit*/FALSE) != 0) return; /* See if we are edge triggered */ intdef = ahc_inb(ahc, INTDEF); if ((intdef & EDGE_TRIG) != 0) ahc->flags |= AHC_EDGE_INTERRUPT; /* * Now that we know we own the resources we need, do the * card initialization. */ aha2840_load_seeprom(ahc); /* * See if we have a Rev E or higher aic7770. Anything below a * Rev E will have a R/O autoflush disable configuration bit. * It's still not clear exactly what is differenent about the Rev E. * We think it allows 8 bit entries in the QOUTFIFO to support * "paging" SCBs so you can have more than 4 commands active at * once. */ { char *id_string; u_char sblkctl; u_char sblkctl_orig; sblkctl_orig = ahc_inb(ahc, SBLKCTL); sblkctl = sblkctl_orig ^ AUTOFLUSHDIS; ahc_outb(ahc, SBLKCTL, sblkctl); sblkctl = ahc_inb(ahc, SBLKCTL); if(sblkctl != sblkctl_orig) { id_string = "aic7770 >= Rev E, "; /* * Ensure autoflush is enabled */ sblkctl &= ~AUTOFLUSHDIS; ahc_outb(ahc, SBLKCTL, sblkctl); /* Allow paging on this adapter */ ahc->flags |= AHC_PAGESCBS; } else id_string = "aic7770 <= Rev C, "; printf("%s: %s", ahc_name(ahc), id_string); } /* Setup the FIFO threshold and the bus off time */ { u_char hostconf = ahc_inb(ahc, HOSTCONF); ahc_outb(ahc, BUSSPD, hostconf & DFTHRSH); ahc_outb(ahc, BUSTIME, (hostconf << 2) & BOFF); } /* * Generic aic7xxx initialization. */ if(ahc_init(ahc)){ ahc_free(ahc); return; } /* * Link this softc in with all other ahc instances. */ ahc_softc_insert(ahc); /* * Enable the board's BUS drivers */ ahc_outb(ahc, BCTL, ENABLE); /* * The IRQMS bit enables level sensitive interrupts only allow * IRQ sharing if its set. */ ahc->ih = isa_intr_establish(ia->ia_ic, irq, ahc->pause & IRQMS ? IST_LEVEL : IST_EDGE, IPL_BIO, ahc_platform_intr, ahc, ahc->sc_dev.dv_xname); if (ahc->ih == NULL) { printf("%s: couldn't establish interrupt\n", ahc->sc_dev.dv_xname); ahc_free(ahc); return; } ahc_intr_enable(ahc, TRUE); /* Attach sub-devices - always succeeds */ ahc_attach(ahc); }