1*3836e7c7Smiod /* $OpenBSD: aapic.c,v 1.8 2024/11/05 18:58:59 miod Exp $ */ 2f2c92e93Sbrad /* $NetBSD: aapic.c,v 1.3 2005/01/13 23:40:01 fvdl Exp $ */ 3f2c92e93Sbrad 45ebf4d33Sbrad /* 55ebf4d33Sbrad * The AMD 8131 IO APIC can hang the box when an APIC IRQ is masked. 65ebf4d33Sbrad */ 7f2c92e93Sbrad #include <sys/param.h> 8f2c92e93Sbrad #include <sys/systm.h> 9f2c92e93Sbrad #include <sys/device.h> 10f2c92e93Sbrad 11f2c92e93Sbrad #include <dev/pci/pcireg.h> 12f2c92e93Sbrad #include <dev/pci/pcivar.h> 13f2c92e93Sbrad #include <dev/pci/pcidevs.h> 14f2c92e93Sbrad 15f2c92e93Sbrad #include "ioapic.h" 16f2c92e93Sbrad 17f2c92e93Sbrad #if NIOAPIC > 0 18f2c92e93Sbrad extern int nioapics; 19f2c92e93Sbrad #endif 20f2c92e93Sbrad 2112318b15Sthib #define AMD8131_PCIX_MISC 0x40 2212318b15Sthib #define AMD8131_NIOAMODE 0x00000001 2312318b15Sthib 2412318b15Sthib #define AMD8131_IOAPIC_CTL 0x44 2512318b15Sthib #define AMD8131_IOAEN 0x00000002 2612318b15Sthib 27f2c92e93Sbrad int aapic_match(struct device *, void *, void *); 28f2c92e93Sbrad void aapic_attach(struct device *, struct device *, void *); 29f2c92e93Sbrad 30f2c92e93Sbrad struct aapic_softc { 31f2c92e93Sbrad struct device sc_dev; 32f2c92e93Sbrad }; 33f2c92e93Sbrad 3406a6f48eSmpi const struct cfattach aapic_ca = { 35f2c92e93Sbrad sizeof(struct aapic_softc), aapic_match, aapic_attach 36f2c92e93Sbrad }; 37f2c92e93Sbrad 38f2c92e93Sbrad struct cfdriver aapic_cd = { 39*3836e7c7Smiod NULL, "aapic", DV_DULL 40f2c92e93Sbrad }; 41f2c92e93Sbrad 42f2c92e93Sbrad int 432bb6026aSjsg aapic_match(struct device *parent, void *match, void *aux) 44f2c92e93Sbrad { 45f2c92e93Sbrad struct pci_attach_args *pa = aux; 46f2c92e93Sbrad 47f2c92e93Sbrad if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AMD && 48f2c92e93Sbrad PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_8131_PCIX_IOAPIC) 49f2c92e93Sbrad return (1); 50f2c92e93Sbrad 51f2c92e93Sbrad return (0); 52f2c92e93Sbrad } 53f2c92e93Sbrad 54f2c92e93Sbrad void 552bb6026aSjsg aapic_attach(struct device *parent, struct device *self, void *aux) 56f2c92e93Sbrad { 57f2c92e93Sbrad struct pci_attach_args *pa = aux; 58f2c92e93Sbrad int bus, dev, func; 59f2c92e93Sbrad pcitag_t tag; 60f2c92e93Sbrad pcireg_t reg; 61f2c92e93Sbrad 62f2c92e93Sbrad printf("\n"); 63f2c92e93Sbrad 64f2c92e93Sbrad #if NIOAPIC > 0 65f2c92e93Sbrad if (nioapics == 0) 66f2c92e93Sbrad return; 67f2c92e93Sbrad #else 68f2c92e93Sbrad return; 69f2c92e93Sbrad #endif 70f2c92e93Sbrad 71f2c92e93Sbrad reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AMD8131_IOAPIC_CTL); 72f2c92e93Sbrad reg |= AMD8131_IOAEN; 73f2c92e93Sbrad pci_conf_write(pa->pa_pc, pa->pa_tag, AMD8131_IOAPIC_CTL, reg); 74f2c92e93Sbrad 75f2c92e93Sbrad pci_decompose_tag(pa->pa_pc, pa->pa_tag, &bus, &dev, &func); 76f2c92e93Sbrad func = 0; 77f2c92e93Sbrad tag = pci_make_tag(pa->pa_pc, bus, dev, func); 78f2c92e93Sbrad reg = pci_conf_read(pa->pa_pc, tag, AMD8131_PCIX_MISC); 79f2c92e93Sbrad reg &= ~AMD8131_NIOAMODE; 80f2c92e93Sbrad pci_conf_write(pa->pa_pc, tag, AMD8131_PCIX_MISC, reg); 81f2c92e93Sbrad } 82