void ahc_cardbus_attach(device_t parent, device_t self, void *aux) { struct cardbus_attach_args *ca = aux; struct ahc_cardbus_softc *csc = device_private(self); struct ahc_softc *ahc = &csc->sc_ahc; cardbus_devfunc_t ct = ca->ca_ct; bus_space_tag_t bst; bus_space_handle_t bsh; pcireg_t reg; u_int sxfrctl1 = 0; u_char sblkctl; ahc->sc_dev = self; csc->sc_ct = ct; csc->sc_tag = ca->ca_tag; printf(": Adaptec ADP-1480 SCSI\n"); /* * Map the device. */ csc->sc_csr = PCI_COMMAND_MASTER_ENABLE; if (Cardbus_mapreg_map(csc->sc_ct, AHC_CARDBUS_MMBA, PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &bst, &bsh, NULL, &csc->sc_size) == 0) { csc->sc_bar = AHC_CARDBUS_MMBA; csc->sc_csr |= PCI_COMMAND_MEM_ENABLE; } else if (Cardbus_mapreg_map(csc->sc_ct, AHC_CARDBUS_IOBA, PCI_MAPREG_TYPE_IO, 0, &bst, &bsh, NULL, &csc->sc_size) == 0) { csc->sc_bar = AHC_CARDBUS_IOBA; csc->sc_csr |= PCI_COMMAND_IO_ENABLE; } else { csc->sc_bar = 0; aprint_error("%s: unable to map device registers\n", ahc_name(ahc)); return; } /* Enable the appropriate bits in the PCI CSR. */ reg = Cardbus_conf_read(ct, ca->ca_tag, PCI_COMMAND_STATUS_REG); reg &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE); reg |= csc->sc_csr; Cardbus_conf_write(ct, ca->ca_tag, PCI_COMMAND_STATUS_REG, reg); /* * Make sure the latency timer is set to some reasonable * value. */ reg = Cardbus_conf_read(ct, ca->ca_tag, PCI_BHLC_REG); if (PCI_LATTIMER(reg) < 0x20) { reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT); reg |= (0x20 << PCI_LATTIMER_SHIFT); Cardbus_conf_write(ct, ca->ca_tag, PCI_BHLC_REG, reg); } ahc_set_name(ahc, device_xname(ahc->sc_dev)); ahc->parent_dmat = ca->ca_dmat; ahc->tag = bst; ahc->bsh = bsh; /* * ADP-1480 is always an AIC-7860. */ ahc->chip = AHC_AIC7860 | AHC_PCI; ahc->features = AHC_AIC7860_FE|AHC_REMOVABLE; ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; if (PCI_REVISION(ca->ca_class) >= 1) ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; if (ahc_softc_init(ahc) != 0) return; /* * On all CardBus adapters, we allow SCB paging. */ ahc->flags = AHC_PAGESCBS; ahc->channel = 'A'; ahc_intr_enable(ahc, FALSE); ahc_reset(ahc); /* * Establish the interrupt. */ ahc->ih = Cardbus_intr_establish(ct, IPL_BIO, ahc_intr, ahc); if (ahc->ih == NULL) { aprint_error("%s: unable to establish interrupt\n", ahc_name(ahc)); return; } ahc->seep_config = malloc(sizeof(*ahc->seep_config), M_DEVBUF, M_NOWAIT); if (ahc->seep_config == NULL) return; ahc_check_extport(ahc, &sxfrctl1); /* * Take the LED out of diagnostic mode. */ sblkctl = ahc_inb(ahc, SBLKCTL); ahc_outb(ahc, SBLKCTL, (sblkctl & ~(DIAGLEDEN|DIAGLEDON))); /* * I don't know where this is set in the SEEPROM or by the * BIOS, so we default to 100%. */ ahc_outb(ahc, DSPCISTATUS, DFTHRSH_100); if (ahc->flags & AHC_USEDEFAULTS) { int our_id; /* * Assume only one connector and always turn * on termination. */ our_id = AHC_CARDBUS_DEFAULT_SCSI_ID; sxfrctl1 = STPWEN; ahc_outb(ahc, SCSICONF, our_id | ENSPCHK | RESET_SCSI); ahc->our_id = our_id; } printf("%s: aic7860", ahc_name(ahc)); /* * Record our termination setting for the * generic initialization routine. */ if ((sxfrctl1 & STPWEN) != 0) ahc->flags |= AHC_TERM_ENB_A; if (ahc_init(ahc)) { ahc_free(ahc); return; } ahc_attach(ahc); }
static void ahc_eisa_attach(device_t parent, device_t self, void *aux) { struct ahc_softc *ahc = device_private(self); struct eisa_attach_args *ea = aux; eisa_chipset_tag_t ec = ea->ea_ec; eisa_intr_handle_t ih; bus_space_tag_t iot = ea->ea_iot; bus_space_handle_t ioh; int irq, intrtype; const char *intrstr, *intrtypestr; u_int biosctrl; u_int scsiconf; u_int scsiconf1; u_char intdef; #ifdef AHC_DEBUG int i; #endif char intrbuf[EISA_INTRSTR_LEN]; ahc->sc_dev = self; if (bus_space_map(iot, EISA_SLOT_ADDR(ea->ea_slot) + AHC_EISA_SLOT_OFFSET, AHC_EISA_IOSIZE, 0, &ioh)) { aprint_error_dev(ahc->sc_dev, "could not map I/O addresses"); return; } if ((irq = ahc_aic77xx_irq(iot, ioh)) < 0) { aprint_error_dev(ahc->sc_dev, "ahc_aic77xx_irq failed!"); goto free_io; } if (strcmp(ea->ea_idstring, "ADP7770") == 0) { printf(": %s\n", EISA_PRODUCT_ADP7770); } else if (strcmp(ea->ea_idstring, "ADP7771") == 0) { printf(": %s\n", EISA_PRODUCT_ADP7771); } else { printf(": Unknown device type %s", ea->ea_idstring); goto free_io; } ahc_set_name(ahc, device_xname(ahc->sc_dev)); ahc->parent_dmat = ea->ea_dmat; ahc->chip = AHC_AIC7770|AHC_EISA; ahc->features = AHC_AIC7770_FE; ahc->flags = AHC_PAGESCBS; ahc->bugs = AHC_TMODE_WIDEODD_BUG; ahc->tag = iot; ahc->bsh = ioh; ahc->channel = 'A'; if (ahc_softc_init(ahc) != 0) goto free_io; ahc_intr_enable(ahc, FALSE); if (ahc_reset(ahc) != 0) goto free_io; if (eisa_intr_map(ec, irq, &ih)) { aprint_error_dev(ahc->sc_dev, "couldn't map interrupt (%d)\n", irq); 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"; } intrstr = eisa_intr_string(ec, ih, intrbuf, sizeof(intrbuf)); ahc->ih = eisa_intr_establish(ec, ih, intrtype, IPL_BIO, ahc_intr, ahc); if (ahc->ih == NULL) { aprint_error_dev(ahc->sc_dev, "couldn't establish %s interrupt", intrtypestr); if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); goto free_io; } if (intrstr != NULL) aprint_normal_dev(ahc->sc_dev, "%s interrupting at %s\n", intrtypestr, intrstr); /* * Now that we know we own the resources we need, do the * card initialization. * * First, the aic7770 card specific setup. */ biosctrl = ahc_inb(ahc, HA_274_BIOSCTRL); scsiconf = ahc_inb(ahc, SCSICONF); scsiconf1 = ahc_inb(ahc, SCSICONF + 1); #ifdef AHC_DEBUG for (i = TARG_SCSIRATE; i <= HA_274_BIOSCTRL; i+=8) { printf("0x%x, 0x%x, 0x%x, 0x%x, " "0x%x, 0x%x, 0x%x, 0x%x\n", ahc_inb(ahc, i), ahc_inb(ahc, i+1), ahc_inb(ahc, i+2), ahc_inb(ahc, i+3), ahc_inb(ahc, i+4), ahc_inb(ahc, i+5), ahc_inb(ahc, i+6), ahc_inb(ahc, i+7)); } #endif /* Get the primary channel information */ if ((biosctrl & CHANNEL_B_PRIMARY) != 0) ahc->flags |= AHC_PRIMARY_CHANNEL; 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; /* Attach sub-devices */ if (ahc_aic77xx_attach(ahc) == 0) return; /* succeed */ /* failed */ eisa_intr_disestablish(ec, ahc->ih); free_io: bus_space_unmap(iot, ioh, AHC_EISA_IOSIZE); }
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); }
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); }