void ahc_pci_resume(struct ahc_softc *ahc) { ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, ahc->bus_softc.pci_softc.devconfig, 4); ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, ahc->bus_softc.pci_softc.command, 1); ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, ahc->bus_softc.pci_softc.csize_lattime, 1); if ((ahc->flags & AHC_HAS_TERM_LOGIC) != 0) { struct seeprom_descriptor sd; u_int sxfrctl1; sd.sd_ahc = ahc; sd.sd_control_offset = SEECTL; sd.sd_status_offset = SEECTL; sd.sd_dataout_offset = SEECTL; ahc_acquire_seeprom(ahc, &sd); configure_termination(ahc, &sd, ahc->seep_config->adapter_control, &sxfrctl1); ahc_release_seeprom(&sd); } }
static int ahc_proc_write_seeprom(struct ahc_softc *ahc, char *buffer, int length) { struct seeprom_descriptor sd; int have_seeprom; u_long s; int paused; int written; /* Default to failure. */ written = -EINVAL; ahc_lock(ahc, &s); paused = ahc_is_paused(ahc); if (!paused) ahc_pause(ahc); if (length != sizeof(struct seeprom_config)) { printf("ahc_proc_write_seeprom: incorrect buffer size\n"); goto done; } have_seeprom = ahc_verify_cksum((struct seeprom_config*)buffer); if (have_seeprom == 0) { printf("ahc_proc_write_seeprom: cksum verification failed\n"); goto done; } sd.sd_ahc = ahc; #if AHC_PCI_CONFIG > 0 if ((ahc->chip & AHC_PCI) != 0) { sd.sd_control_offset = SEECTL; sd.sd_status_offset = SEECTL; sd.sd_dataout_offset = SEECTL; if (ahc->flags & AHC_LARGE_SEEPROM) sd.sd_chip = C56_66; else sd.sd_chip = C46; sd.sd_MS = SEEMS; sd.sd_RDY = SEERDY; sd.sd_CS = SEECS; sd.sd_CK = SEECK; sd.sd_DO = SEEDO; sd.sd_DI = SEEDI; have_seeprom = ahc_acquire_seeprom(ahc, &sd); } else #endif if ((ahc->chip & AHC_VL) != 0) { sd.sd_control_offset = SEECTL_2840; sd.sd_status_offset = STATUS_2840; sd.sd_dataout_offset = STATUS_2840; sd.sd_chip = C46; sd.sd_MS = 0; sd.sd_RDY = EEPROM_TF; sd.sd_CS = CS_2840; sd.sd_CK = CK_2840; sd.sd_DO = DO_2840; sd.sd_DI = DI_2840; have_seeprom = TRUE; } else { printf("ahc_proc_write_seeprom: unsupported adapter type\n"); goto done; } if (!have_seeprom) { printf("ahc_proc_write_seeprom: No Serial EEPROM\n"); goto done; } else { u_int start_addr; if (ahc->seep_config == NULL) { ahc->seep_config = malloc(sizeof(*ahc->seep_config), M_DEVBUF, M_NOWAIT); if (ahc->seep_config == NULL) { printf("aic7xxx: Unable to allocate serial " "eeprom buffer. Write failing\n"); goto done; } } printf("aic7xxx: Writing Serial EEPROM\n"); start_addr = 32 * (ahc->channel - 'A'); ahc_write_seeprom(&sd, (u_int16_t *)buffer, start_addr, sizeof(struct seeprom_config)/2); ahc_read_seeprom(&sd, (uint16_t *)ahc->seep_config, start_addr, sizeof(struct seeprom_config)/2); #if AHC_PCI_CONFIG > 0 if ((ahc->chip & AHC_VL) == 0) ahc_release_seeprom(&sd); #endif written = length; } done: if (!paused) ahc_unpause(ahc); ahc_unlock(ahc, &s); return (written); }
static void check_extport(struct ahc_softc *ahc, u_int *sxfrctl1) { struct seeprom_descriptor sd; struct seeprom_config *sc; int have_seeprom; int have_autoterm; sd.sd_ahc = ahc; sd.sd_control_offset = SEECTL; sd.sd_status_offset = SEECTL; sd.sd_dataout_offset = SEECTL; sc = ahc->seep_config; if (ahc->flags & AHC_LARGE_SEEPROM) sd.sd_chip = C56_66; else sd.sd_chip = C46; sd.sd_MS = SEEMS; sd.sd_RDY = SEERDY; sd.sd_CS = SEECS; sd.sd_CK = SEECK; sd.sd_DO = SEEDO; sd.sd_DI = SEEDI; have_seeprom = ahc_acquire_seeprom(ahc, &sd); if (have_seeprom) { if (bootverbose) printf("%s: Reading SEEPROM...", ahc_name(ahc)); for (;;) { u_int start_addr; start_addr = 32 * (ahc->channel - 'A'); have_seeprom = ahc_read_seeprom(&sd, (uint16_t *)sc, start_addr, sizeof(*sc)/2); if (have_seeprom) have_seeprom = ahc_verify_cksum(sc); if (have_seeprom != 0 || sd.sd_chip == C56_66) { if (bootverbose) { if (have_seeprom == 0) printf ("checksum error\n"); else printf ("done.\n"); } break; } sd.sd_chip = C56_66; } ahc_release_seeprom(&sd); if (sd.sd_chip == C56_66) ahc->flags |= AHC_LARGE_SEEPROM; } if (!have_seeprom) { ahc_outb(ahc, SCBPTR, 2); if (ahc_inb(ahc, SCB_BASE) == 'A' && ahc_inb(ahc, SCB_BASE + 1) == 'D' && ahc_inb(ahc, SCB_BASE + 2) == 'P' && ahc_inb(ahc, SCB_BASE + 3) == 'T') { uint16_t *sc_data; int i; sc_data = (uint16_t *)sc; for (i = 0; i < 32; i++, sc_data++) { int j; j = i * 2; *sc_data = ahc_inb(ahc, SRAM_BASE + j) | ahc_inb(ahc, SRAM_BASE + j + 1) << 8; } have_seeprom = ahc_verify_cksum(sc); if (have_seeprom) ahc->flags |= AHC_SCB_CONFIG_USED; } ahc_outb(ahc, CLRINT, CLRPARERR); ahc_outb(ahc, CLRINT, CLRBRKADRINT); } if (!have_seeprom) { if (bootverbose) printf("%s: No SEEPROM available.\n", ahc_name(ahc)); ahc->flags |= AHC_USEDEFAULTS; free(ahc->seep_config, M_DEVBUF); ahc->seep_config = NULL; sc = NULL; } else { ahc_parse_pci_eeprom(ahc, sc); } have_autoterm = have_seeprom; if ((ahc->features & AHC_SPIOCAP) != 0) { if ((ahc_inb(ahc, SPIOCAP) & SSPIOCPS) == 0) have_autoterm = FALSE; } if (have_autoterm) { ahc->flags |= AHC_HAS_TERM_LOGIC; ahc_acquire_seeprom(ahc, &sd); configure_termination(ahc, &sd, sc->adapter_control, sxfrctl1); ahc_release_seeprom(&sd); } else if (have_seeprom) { *sxfrctl1 &= ~STPWEN; if ((sc->adapter_control & CFSTERM) != 0) *sxfrctl1 |= STPWEN; if (bootverbose) printf("%s: Low byte termination %sabled\n", ahc_name(ahc), (*sxfrctl1 & STPWEN) ? "en" : "dis"); } }
/* * Check the external port logic for a serial eeprom * and termination/cable detection contrls. */ void ahc_check_extport(struct ahc_softc *ahc, u_int *sxfrctl1) { struct seeprom_descriptor sd; struct seeprom_config *sc; int have_seeprom; int have_autoterm; sd.sd_tag = ahc->tag; sd.sd_bsh = ahc->bsh; sd.sd_regsize = 1; sd.sd_control_offset = SEECTL; sd.sd_status_offset = SEECTL; sd.sd_dataout_offset = SEECTL; sc = ahc->seep_config; /* * For some multi-channel devices, the c46 is simply too * small to work. For the other controller types, we can * get our information from either SEEPROM type. Set the * type to start our probe with accordingly. */ if (ahc->flags & AHC_LARGE_SEEPROM) sd.sd_chip = C56_66; else sd.sd_chip = C46; sd.sd_MS = SEEMS; sd.sd_RDY = SEERDY; sd.sd_CS = SEECS; sd.sd_CK = SEECK; sd.sd_DO = SEEDO; sd.sd_DI = SEEDI; have_seeprom = ahc_acquire_seeprom(ahc, &sd); if (have_seeprom) { if (bootverbose) printf("%s: Reading SEEPROM...", ahc_name(ahc)); for (;;) { u_int start_addr; start_addr = 32 * (ahc->channel - 'A'); have_seeprom = read_seeprom(&sd, (uint16_t *)sc, start_addr, sizeof(*sc)/2); if (have_seeprom) have_seeprom = verify_seeprom_cksum(sc); if (have_seeprom != 0 || sd.sd_chip == C56_66) { if (bootverbose) { if (have_seeprom == 0) printf ("checksum error\n"); else printf ("done.\n"); } break; } sd.sd_chip = C56_66; } ahc_release_seeprom(&sd); } if (!have_seeprom) { /* * Pull scratch ram settings and treat them as * if they are the contents of an seeprom if * the 'ADPT' signature is found in SCB2. * We manually compose the data as 16bit values * to avoid endian issues. */ ahc_outb(ahc, SCBPTR, 2); if (ahc_inb(ahc, SCB_BASE) == 'A' && ahc_inb(ahc, SCB_BASE + 1) == 'D' && ahc_inb(ahc, SCB_BASE + 2) == 'P' && ahc_inb(ahc, SCB_BASE + 3) == 'T') { uint16_t *sc_data; int i; sc_data = (uint16_t *)sc; for (i = 0; i < 32; i++, sc_data++) { int j; j = i * 2; *sc_data = ahc_inb(ahc, SRAM_BASE + j) | ahc_inb(ahc, SRAM_BASE + j + 1) << 8; } have_seeprom = verify_seeprom_cksum(sc); if (have_seeprom) ahc->flags |= AHC_SCB_CONFIG_USED; } /* * Clear any SCB parity errors in case this data and * its associated parity was not initialized by the BIOS */ ahc_outb(ahc, CLRINT, CLRPARERR); ahc_outb(ahc, CLRINT, CLRBRKADRINT); } if (!have_seeprom) { if (bootverbose) printf("%s: No SEEPROM available.\n", ahc_name(ahc)); ahc->flags |= AHC_USEDEFAULTS; free(ahc->seep_config, M_DEVBUF); ahc->seep_config = NULL; sc = NULL; } else { ahc_parse_pci_eeprom(ahc, sc); } /* * Cards that have the external logic necessary to talk to * a SEEPROM, are almost certain to have the remaining logic * necessary for auto-termination control. This assumption * hasn't failed yet... */ have_autoterm = have_seeprom; /* * Some low-cost chips have SEEPROM and auto-term control built * in, instead of using a GAL. They can tell us directly * if the termination logic is enabled. */ if ((ahc->features & AHC_SPIOCAP) != 0) { if ((ahc_inb(ahc, SPIOCAP) & SSPIOCPS) == 0) have_autoterm = FALSE; } if (have_autoterm) { ahc_acquire_seeprom(ahc, &sd); configure_termination(ahc, &sd, sc->adapter_control, sxfrctl1); ahc_release_seeprom(&sd); } else if (have_seeprom) { *sxfrctl1 &= ~STPWEN; if ((sc->adapter_control & CFSTERM) != 0) *sxfrctl1 |= STPWEN; if (bootverbose) printf("%s: Low byte termination %sabled\n", ahc_name(ahc), (*sxfrctl1 & STPWEN) ? "en" : "dis"); } }