1 /* $NetBSD: aapic.c,v 1.2 2004/04/23 21:13:06 itojun Exp $ */ 2 3 #include <sys/cdefs.h> 4 __KERNEL_RCSID(0, "$NetBSD: aapic.c,v 1.2 2004/04/23 21:13:06 itojun Exp $"); 5 6 #include <sys/param.h> 7 #include <sys/systm.h> 8 #include <sys/kernel.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 <arch/x86/pci/amd8131reg.h> 16 17 static int aapic_match __P((struct device *, struct cfdata *, void *)); 18 static void aapic_attach __P((struct device *, struct device *, void *)); 19 20 struct aapic_softc { 21 struct device sc_dev; 22 }; 23 24 CFATTACH_DECL(aapic, sizeof(struct aapic_softc), 25 aapic_match, aapic_attach, NULL, NULL); 26 27 static int 28 aapic_match(parent, match, aux) 29 struct device *parent; 30 struct cfdata *match; 31 void *aux; 32 { 33 struct pci_attach_args *pa = aux; 34 35 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AMD && 36 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_PCIX8131_APIC) 37 return (1); 38 39 return (0); 40 } 41 42 static void 43 aapic_attach(parent, self, aux) 44 struct device *parent, *self; 45 void *aux; 46 { 47 struct pci_attach_args *pa = aux; 48 char devinfo[256]; 49 int bus, dev, func, rev; 50 pcitag_t tag; 51 pcireg_t reg; 52 53 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); 54 rev = PCI_REVISION(pa->pa_class); 55 printf(": %s (rev. 0x%02x)\n", devinfo, rev); 56 57 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AMD8131_IOAPIC_CTL); 58 if ((reg & AMD8131_IOAEN) == 0) { 59 reg |= AMD8131_IOAEN; 60 pci_conf_write(pa->pa_pc, pa->pa_tag, AMD8131_IOAPIC_CTL, reg); 61 } 62 63 /* 64 * Work around erratum #22 for A0 and B0 revisions. 65 */ 66 if (rev == 0x01 || rev == 0x11) { 67 pci_decompose_tag(pa->pa_pc, pa->pa_tag, &bus, &dev, &func); 68 func = 0; 69 tag = pci_make_tag(pa->pa_pc, bus, dev, func); 70 reg = pci_conf_read(pa->pa_pc, tag, AMD8131_PCIX_MISC); 71 reg &= ~0x00000001; 72 pci_conf_write(pa->pa_pc, tag, AMD8131_PCIX_MISC, reg); 73 } 74 } 75