1 /* $OpenBSD: aapic.c,v 1.8 2024/11/05 18:58:59 miod 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 const struct cfattach aapic_ca = {
35 sizeof(struct aapic_softc), aapic_match, aapic_attach
36 };
37
38 struct cfdriver aapic_cd = {
39 NULL, "aapic", DV_DULL
40 };
41
42 int
aapic_match(struct device * parent,void * match,void * aux)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
aapic_attach(struct device * parent,struct device * self,void * aux)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