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