1 /* $OpenBSD: aapic.c,v 1.5 2008/04/24 20:47:05 thib 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/kernel.h> 10 #include <sys/device.h> 11 12 #include <dev/pci/pcireg.h> 13 #include <dev/pci/pcivar.h> 14 #include <dev/pci/pcidevs.h> 15 16 #include "ioapic.h" 17 18 #if NIOAPIC > 0 19 extern int nioapics; 20 #endif 21 22 #define AMD8131_PCIX_MISC 0x40 23 #define AMD8131_NIOAMODE 0x00000001 24 25 #define AMD8131_IOAPIC_CTL 0x44 26 #define AMD8131_IOAEN 0x00000002 27 28 int aapic_match(struct device *, void *, void *); 29 void aapic_attach(struct device *, struct device *, void *); 30 31 struct aapic_softc { 32 struct device sc_dev; 33 }; 34 35 struct cfattach aapic_ca = { 36 sizeof(struct aapic_softc), aapic_match, aapic_attach 37 }; 38 39 struct cfdriver aapic_cd = { 40 0, "aapic", DV_DULL 41 }; 42 43 int 44 aapic_match(struct device *parent, void *match, void *aux) 45 { 46 struct pci_attach_args *pa = aux; 47 48 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AMD && 49 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_8131_PCIX_IOAPIC) 50 return (1); 51 52 return (0); 53 } 54 55 void 56 aapic_attach(struct device *parent, struct device *self, void *aux) 57 { 58 struct pci_attach_args *pa = aux; 59 int bus, dev, func; 60 pcitag_t tag; 61 pcireg_t reg; 62 63 printf("\n"); 64 65 #if NIOAPIC > 0 66 if (nioapics == 0) 67 return; 68 #else 69 return; 70 #endif 71 72 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AMD8131_IOAPIC_CTL); 73 reg |= AMD8131_IOAEN; 74 pci_conf_write(pa->pa_pc, pa->pa_tag, AMD8131_IOAPIC_CTL, reg); 75 76 pci_decompose_tag(pa->pa_pc, pa->pa_tag, &bus, &dev, &func); 77 func = 0; 78 tag = pci_make_tag(pa->pa_pc, bus, dev, func); 79 reg = pci_conf_read(pa->pa_pc, tag, AMD8131_PCIX_MISC); 80 reg &= ~AMD8131_NIOAMODE; 81 pci_conf_write(pa->pa_pc, tag, AMD8131_PCIX_MISC, reg); 82 } 83