1/* $OpenBSD: aapic.c,v 1.7 2022/02/21 11:03:39 mpi 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 18extern 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 27int aapic_match(struct device *, void *, void *); 28void aapic_attach(struct device *, struct device *, void *); 29 30struct aapic_softc { 31 struct device sc_dev; 32}; 33 34const struct cfattach aapic_ca = { 35 sizeof(struct aapic_softc), aapic_match, aapic_attach 36}; 37 38struct cfdriver aapic_cd = { 39 0, "aapic", DV_DULL 40}; 41 42int 43aapic_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 54void 55aapic_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