xref: /openbsd-src/sys/arch/amd64/pci/aapic.c (revision 91f110e064cd7c194e59e019b83bb7496c1c84d4)
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