📄 aic7xxx_pci.c
字号:
uint8_t brdctl; uint8_t spiocap; spiocap = ahc_inb(ahc, SPIOCAP); spiocap &= ~SOFTCMDEN; spiocap |= EXT_BRDCTL; ahc_outb(ahc, SPIOCAP, spiocap); ahc_outb(ahc, BRDCTL, BRDRW|BRDCS); ahc_flush_device_writes(ahc); ahc_delay(500); ahc_outb(ahc, BRDCTL, 0); ahc_flush_device_writes(ahc); ahc_delay(500); brdctl = ahc_inb(ahc, BRDCTL); *internal50_present = (brdctl & BRDDAT5) ? 0 : 1; *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1; *eeprom_present = (ahc_inb(ahc, SPIOCAP) & EEPROM) ? 1 : 0;} intahc_acquire_seeprom(struct ahc_softc *ahc, struct seeprom_descriptor *sd){ int wait; if ((ahc->features & AHC_SPIOCAP) != 0 && (ahc_inb(ahc, SPIOCAP) & SEEPROM) == 0) return (0); /* * Request access of the memory port. When access is * granted, SEERDY will go high. We use a 1 second * timeout which should be near 1 second more than * is needed. Reason: after the chip reset, there * should be no contention. */ SEEPROM_OUTB(sd, sd->sd_MS); wait = 1000; /* 1 second timeout in msec */ while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) { ahc_delay(1000); /* delay 1 msec */ } if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) { SEEPROM_OUTB(sd, 0); return (0); } return(1);}voidahc_release_seeprom(struct seeprom_descriptor *sd){ /* Release access to the memory port and the serial EEPROM. */ SEEPROM_OUTB(sd, 0);}static voidwrite_brdctl(struct ahc_softc *ahc, uint8_t value){ uint8_t brdctl; if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) { brdctl = BRDSTB; if (ahc->channel == 'B') brdctl |= BRDCS; } else if ((ahc->features & AHC_ULTRA2) != 0) { brdctl = 0; } else { brdctl = BRDSTB|BRDCS; } ahc_outb(ahc, BRDCTL, brdctl); ahc_flush_device_writes(ahc); brdctl |= value; ahc_outb(ahc, BRDCTL, brdctl); ahc_flush_device_writes(ahc); if ((ahc->features & AHC_ULTRA2) != 0) brdctl |= BRDSTB_ULTRA2; else brdctl &= ~BRDSTB; ahc_outb(ahc, BRDCTL, brdctl); ahc_flush_device_writes(ahc); if ((ahc->features & AHC_ULTRA2) != 0) brdctl = 0; else brdctl &= ~BRDCS; ahc_outb(ahc, BRDCTL, brdctl);}static uint8_tread_brdctl(struct ahc_softc *ahc){ uint8_t brdctl; uint8_t value; if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) { brdctl = BRDRW; if (ahc->channel == 'B') brdctl |= BRDCS; } else if ((ahc->features & AHC_ULTRA2) != 0) { brdctl = BRDRW_ULTRA2; } else { brdctl = BRDRW|BRDCS; } ahc_outb(ahc, BRDCTL, brdctl); ahc_flush_device_writes(ahc); value = ahc_inb(ahc, BRDCTL); ahc_outb(ahc, BRDCTL, 0); return (value);}static voidahc_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, /*bytes*/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)); } /* Clear latched errors. */ ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, status1, /*bytes*/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);}static intahc_pci_chip_init(struct ahc_softc *ahc){ ahc_outb(ahc, DSCOMMAND0, ahc->bus_softc.pci_softc.dscommand0); ahc_outb(ahc, DSPCISTATUS, ahc->bus_softc.pci_softc.dspcistatus); if ((ahc->features & AHC_DT) != 0) { u_int sfunct; sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE; ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE); ahc_outb(ahc, OPTIONMODE, ahc->bus_softc.pci_softc.optionmode); ahc_outw(ahc, TARGCRCCNT, ahc->bus_softc.pci_softc.targcrccnt); ahc_outb(ahc, SFUNCT, sfunct); ahc_outb(ahc, CRCCONTROL1, ahc->bus_softc.pci_softc.crccontrol1); } if ((ahc->features & AHC_MULTI_FUNC) != 0) ahc_outb(ahc, SCBBADDR, ahc->bus_softc.pci_softc.scbbaddr); if ((ahc->features & AHC_ULTRA2) != 0) ahc_outb(ahc, DFF_THRSH, ahc->bus_softc.pci_softc.dff_thrsh); return (ahc_chip_init(ahc));}static intahc_pci_suspend(struct ahc_softc *ahc){ return (ahc_suspend(ahc));}static intahc_pci_resume(struct ahc_softc *ahc){ pci_set_power_state(ahc->dev_softc, AHC_POWER_STATE_D0); /* * We assume that the OS has restored our register * mappings, etc. Just update the config space registers * that the OS doesn't know about and rely on our chip * reset handler to handle the rest. */ ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4, ahc->bus_softc.pci_softc.devconfig); ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1, ahc->bus_softc.pci_softc.command); ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1, ahc->bus_softc.pci_softc.csize_lattime); 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); } return (ahc_resume(ahc));}static intahc_aic785X_setup(struct ahc_softc *ahc){ ahc_dev_softc_t pci; uint8_t rev; pci = ahc->dev_softc; ahc->channel = 'A'; ahc->chip = AHC_AIC7850; ahc->features = AHC_AIC7850_FE; ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev >= 1) ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; ahc->instruction_ram_size = 512; return (0);}static intahc_aic7860_setup(struct ahc_softc *ahc){ ahc_dev_softc_t pci; uint8_t rev; pci = ahc->dev_softc; ahc->channel = 'A'; ahc->chip = AHC_AIC7860; ahc->features = AHC_AIC7860_FE; ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev >= 1) ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; ahc->instruction_ram_size = 512; return (0);}static intahc_apa1480_setup(struct ahc_softc *ahc){ int error; error = ahc_aic7860_setup(ahc); if (error != 0) return (error); ahc->features |= AHC_REMOVABLE; return (0);}static intahc_aic7870_setup(struct ahc_softc *ahc){ ahc->channel = 'A'; ahc->chip = AHC_AIC7870; ahc->features = AHC_AIC7870_FE; ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; ahc->instruction_ram_size = 512; return (0);}static intahc_aha394X_setup(struct ahc_softc *ahc){ int error; error = ahc_aic7870_setup(ahc); if (error == 0) error = ahc_aha394XX_setup(ahc); return (error);}static intahc_aha398X_setup(struct ahc_softc *ahc){ int error; error = ahc_aic7870_setup(ahc); if (error == 0) error = ahc_aha398XX_setup(ahc); return (error);}static intahc_aha494X_setup(struct ahc_softc *ahc){ int error; error = ahc_aic7870_setup(ahc); if (error == 0) error = ahc_aha494XX_setup(ahc); return (error);}static intahc_aic7880_setup(struct ahc_softc *ahc){ ahc_dev_softc_t pci; uint8_t rev; pci = ahc->dev_softc; ahc->channel = 'A'; ahc->chip = AHC_AIC7880; ahc->features = AHC_AIC7880_FE; ahc->bugs |= AHC_TMODE_WIDEODD_BUG; rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev >= 1) { ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; } else { ahc->bugs |= AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; } ahc->instruction_ram_size = 512; return (0);}static intahc_aha2940Pro_setup(struct ahc_softc *ahc){ ahc->flags |= AHC_INT50_SPEEDFLEX; return (ahc_aic7880_setup(ahc));}static intahc_aha394XU_setup(struct ahc_softc *ahc){ int error; error = ahc_aic7880_setup(ahc); if (error == 0) error = ahc_aha394XX_setup(ahc); return (error);}static intahc_aha398XU_setup(struct ahc_softc *ahc){ int error; error = ahc_aic7880_setup(ahc); if (error == 0) error = ahc_aha398XX_setup(ahc); return (error);}static intahc_aic7890_setup(struct ahc_softc *ahc){ ahc_dev_softc_t pci; uint8_t rev; pci = ahc->dev_softc; ahc->channel = 'A'; ahc->chip = AHC_AIC7890; ahc->features = AHC_AIC7890_FE; ahc->flags |= AHC_NEWEEPROM_FMT; rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev == 0) ahc->bugs |= AHC_AUTOFLUSH_BUG|AHC_CACHETHEN_BUG; ahc->instruction_ram_size = 768; return (0);}static intahc_aic7892_setup(struct ahc_softc *ahc){ ahc->channel = 'A'; ahc->chip = AHC_AIC7892; ahc->features = AHC_AIC7892_FE; ahc->flags |= AHC_NEWEEPROM_FMT; ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG; ahc->instruction_ram_size = 1024; return (0);}static intahc_aic7895_setup(struct ahc_softc *ahc){ ahc_dev_softc_t pci; uint8_t rev; pci = ahc->dev_softc; ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; /* * The 'C' revision of the aic7895 has a few additional features. */ rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); if (rev >= 4) { ahc->chip = AHC_AIC7895C; ahc->features = AHC_AIC7895C_FE; } else { u_int command; ahc->chip = AHC_AIC7895; ahc->features = AHC_AIC7895_FE; /* * The BIOS disables the use of MWI transactions * since it does not have the MWI bug work around * we have. Disabling MWI reduces performance, so * turn it on again. */ command = ahc_pci_read_config(pci, PCIR_COMMAND, /*bytes*/1); command |= PCIM_CMD_MWRICEN; ahc_pci_write_config(pci, PCIR_COMMAND, command, /*bytes*/1); ahc->bugs |= AHC_PCI_MWI_BUG; } /* * XXX Does CACHETHEN really not work??? What about PCI retry? * on C level chips. Need to test, but for now, play it safe. */ ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_PCI_2_1_RETRY_BUG | AHC_CACHETHEN_BUG;#if 0 uint32_t devconfig; /* * Cachesize must also be zero due to stray DAC * problem when sitting behind some bridges. */ ahc_pci_write_config(pci, CSIZE_LATTIME, 0, /*bytes*/1); devconfig = ahc_pci_read_config(pci, DEVCONFIG, /*bytes*/1); devconfig |= MRDCEN; ahc_pci_write_config(pci, DEVCONFIG, devconfig, /*bytes*/1);#endif ahc->flags |= AHC_NEWEEPROM_FMT; ahc->instruction_ram_size = 512; return (0);}static intahc_aic7896_setup(struct ahc_softc *ahc){ ahc_dev_softc_t pci; pci = ahc->dev_softc; ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; ahc->chip = AHC_AIC7896; ahc->features = AHC_AIC7896_FE; ahc->flags |= AHC_NEWEEPROM_FMT; ahc->bugs |= AHC_CACHETHEN_DIS_BUG; ahc->instruction_ram_size = 768; return (0);}static intahc_aic7899_setup(struct ahc_softc *ahc){ ahc_dev_softc_t pci; pci = ahc->dev_softc; ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; ahc->chip = AHC_AIC7899; ahc->features = AHC_AIC7899_FE; ahc->flags |= AHC_NEWEEPROM_FMT; ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG; ahc->instruction_ram_size = 1024; return (0);}static intahc_aha29160C_setup(struct ahc_softc *ahc){ int error; error = ahc_aic7899_setup(ahc); if (error != 0) return (error); ahc->features |= AHC_REMOVABLE; return (0);}static intahc_raid_setup(struct ahc_softc *ahc){ printf("RAID functionality unsupported\n"); return (ENXIO);}static intahc_aha394XX_setup(struct ahc_softc *ahc){ ahc_dev_softc_t pci; pci = ahc->dev_softc; switch (ahc_get_pci_slot(pci)) { case AHC_394X_SLOT_CHANNEL_A: ahc->channel = 'A'; break; case AHC_394X_SLOT_CHANNEL_B: ahc->channel = 'B'; break; default: printf("adapter at unexpected slot %d\n" "unable to map to a channel\n", ahc_get_pci_slot(pci)); ahc->channel = 'A'; } return (0);}static intahc_aha398XX_setup(struct ahc_softc *ahc){ ahc_dev_softc_t pci; pci = ahc->dev_softc; switch (ahc_get_pci_slot(pci)) { case AHC_398X_SLOT_CHANNEL_A: ahc->channel = 'A'; break; case AHC_398X_SLOT_CHANNEL_B: ahc->channel = 'B'; break; case AHC_398X_SLOT_CHANNEL_C: ahc->channel = 'C'; break; default: printf("adapter at unexpected slot %d\n" "unable to map to a channel\n", ahc_get_pci_slot(pci)); ahc->channel = 'A'; break; } ahc->flags |= AHC_LARGE_SEEPROM; return (0);}static intahc_aha494XX_setup(struct ahc_softc *ahc){ ahc_dev_softc_t pci; pci = ahc->dev_softc; switch (ahc_get_pci_slot(pci)) { case AHC_494X_SLOT_CHANNEL_A: ahc->channel = 'A'; break; case AHC_494X_SLOT_CHANNEL_B: ahc->channel = 'B'; break; case AHC_494X_SLOT_CHANNEL_C: ahc->channel = 'C'; break; case AHC_494X_SLOT_CHANNEL_D: ahc->channel = 'D'; break; default: printf("adapter at unexpected slot %d\n" "unable to map to a channel\n", ahc_get_pci_slot(pci)); ahc->channel = 'A'; } ahc->flags |= AHC_LARGE_SEEPROM; return (0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -