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 ahc_pci_intr(struct ahc_softc *ahc) { u_int error; u_int status1; error = ahc_inb(ahc, ERROR); if ((error & PCIERRSTAT) == 0) return; status1 = ahc_pci_read_config(ahc->dev_softc, PCIR_STATUS + 1, 1); printf("%s: PCI error Interrupt at seqaddr = 0x%x\n", ahc_name(ahc), ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8)); if (status1 & DPE) { ahc->pci_target_perr_count++; printf("%s: Data Parity Error Detected during address " "or write data phase\n", ahc_name(ahc)); } if (status1 & SSE) { printf("%s: Signal System Error Detected\n", ahc_name(ahc)); } if (status1 & RMA) { printf("%s: Received a Master Abort\n", ahc_name(ahc)); } if (status1 & RTA) { printf("%s: Received a Target Abort\n", ahc_name(ahc)); } if (status1 & STA) { printf("%s: Signaled a Target Abort\n", ahc_name(ahc)); } if (status1 & DPR) { printf("%s: Data Parity Error has been reported via PERR#\n", ahc_name(ahc)); } ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, status1, 1); if ((status1 & (DPE|SSE|RMA|RTA|STA|DPR)) == 0) { printf("%s: Latched PCIERR interrupt with " "no status bits set\n", ahc_name(ahc)); } else { ahc_outb(ahc, CLRINT, CLRPARERR); } if (ahc->pci_target_perr_count > AHC_PCI_TARGET_PERR_THRESH) { printf( "%s: WARNING WARNING WARNING WARNING\n" "%s: Too many PCI parity errors observed as a target.\n" "%s: Some device on this bus is generating bad parity.\n" "%s: This is an error *observed by*, not *generated by*, this controller.\n" "%s: PCI parity error checking has been disabled.\n" "%s: WARNING WARNING WARNING WARNING\n", ahc_name(ahc), ahc_name(ahc), ahc_name(ahc), ahc_name(ahc), ahc_name(ahc), ahc_name(ahc)); ahc->seqctl |= FAILDIS; ahc_outb(ahc, SEQCTL, ahc->seqctl); } ahc_unpause(ahc); }