1 /* $NetBSD: sio.c,v 1.9 1996/08/27 21:54:03 cgd Exp $ */ 2 3 /* 4 * Copyright (c) 1995, 1996 Carnegie-Mellon University. 5 * All rights reserved. 6 * 7 * Author: Chris G. Demetriou 8 * 9 * Permission to use, copy, modify and distribute this software and 10 * its documentation is hereby granted, provided that both the copyright 11 * notice and this permission notice appear in all copies of the 12 * software, derivative works or modified versions, and any portions 13 * thereof, and that both notices appear in supporting documentation. 14 * 15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 17 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 18 * 19 * Carnegie Mellon requests users of this software to return to 20 * 21 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 22 * School of Computer Science 23 * Carnegie Mellon University 24 * Pittsburgh PA 15213-3890 25 * 26 * any improvements or extensions that they make and grant Carnegie the 27 * rights to redistribute these changes. 28 */ 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/kernel.h> 33 #include <sys/device.h> 34 35 #include <machine/intr.h> 36 #include <machine/bus.h> 37 38 #include <dev/isa/isavar.h> 39 #include <dev/eisa/eisavar.h> 40 41 #include <dev/pci/pcireg.h> 42 #include <dev/pci/pcivar.h> 43 #include <dev/pci/pcidevs.h> 44 45 #include <alpha/pci/siovar.h> 46 47 int siomatch __P((struct device *, void *, void *)); 48 void sioattach __P((struct device *, struct device *, void *)); 49 50 struct cfattach sio_ca = { 51 sizeof(struct device), siomatch, sioattach, 52 }; 53 54 struct cfdriver sio_cd = { 55 NULL, "sio", DV_DULL, 56 }; 57 58 int pcebmatch __P((struct device *, void *, void *)); 59 60 struct cfattach pceb_ca = { 61 sizeof(struct device), pcebmatch, sioattach, 62 }; 63 64 struct cfdriver pceb_cd = { 65 NULL, "pceb", DV_DULL, 66 }; 67 68 union sio_attach_args { 69 const char *sa_name; /* XXX should be common */ 70 struct isabus_attach_args sa_iba; 71 struct eisabus_attach_args sa_eba; 72 }; 73 74 int sioprint __P((void *, const char *pnp)); 75 void sio_isa_attach_hook __P((struct device *, struct device *, 76 struct isabus_attach_args *)); 77 void sio_eisa_attach_hook __P((struct device *, struct device *, 78 struct eisabus_attach_args *)); 79 int sio_eisa_maxslots __P((void *)); 80 int sio_eisa_intr_map __P((void *, u_int, eisa_intr_handle_t *)); 81 82 int 83 siomatch(parent, match, aux) 84 struct device *parent; 85 void *match, *aux; 86 { 87 struct cfdata *cf = match; 88 struct pci_attach_args *pa = aux; 89 90 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL || 91 PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_INTEL_SIO) 92 return (0); 93 94 return (1); 95 } 96 97 int 98 pcebmatch(parent, match, aux) 99 struct device *parent; 100 void *match, *aux; 101 { 102 struct cfdata *cf = match; 103 struct pci_attach_args *pa = aux; 104 105 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL || 106 PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_INTEL_PCEB) 107 return (0); 108 109 return (1); 110 } 111 112 void 113 sioattach(parent, self, aux) 114 struct device *parent, *self; 115 void *aux; 116 { 117 struct pci_attach_args *pa = aux; 118 struct alpha_isa_chipset ic; 119 struct alpha_eisa_chipset ec; 120 union sio_attach_args sa; 121 int sio, haseisa; 122 char devinfo[256]; 123 124 sio = (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_SIO); 125 haseisa = (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_PCEB); 126 127 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo); 128 printf(": %s (rev. 0x%02x)\n", devinfo, 129 PCI_REVISION(pa->pa_class)); 130 131 if (sio) { 132 pci_revision_t rev; 133 134 rev = PCI_REVISION(pa->pa_class); 135 136 if (rev < 3) 137 printf("%s: WARNING: SIO I SUPPORT UNTESTED\n", 138 self->dv_xname); 139 } 140 141 #ifdef EVCNT_COUNTERS 142 evcnt_attach(self, "intr", &sio_intr_evcnt); 143 #endif 144 145 if (haseisa) { 146 ec.ec_v = NULL; 147 ec.ec_attach_hook = sio_eisa_attach_hook; 148 ec.ec_maxslots = sio_eisa_maxslots; 149 ec.ec_intr_map = sio_eisa_intr_map; 150 ec.ec_intr_string = sio_intr_string; 151 ec.ec_intr_establish = sio_intr_establish; 152 ec.ec_intr_disestablish = sio_intr_disestablish; 153 154 sa.sa_eba.eba_busname = "eisa"; 155 sa.sa_eba.eba_bc = pa->pa_bc; 156 sa.sa_eba.eba_ec = &ec; 157 config_found(self, &sa.sa_eba, sioprint); 158 } 159 160 ic.ic_v = NULL; 161 ic.ic_attach_hook = sio_isa_attach_hook; 162 ic.ic_intr_establish = sio_intr_establish; 163 ic.ic_intr_disestablish = sio_intr_disestablish; 164 165 sa.sa_iba.iba_busname = "isa"; 166 sa.sa_iba.iba_bc = pa->pa_bc; 167 sa.sa_iba.iba_ic = ⁣ 168 config_found(self, &sa.sa_iba, sioprint); 169 } 170 171 int 172 sioprint(aux, pnp) 173 void *aux; 174 const char *pnp; 175 { 176 register union sio_attach_args *sa = aux; 177 178 if (pnp) 179 printf("%s at %s", sa->sa_name, pnp); 180 return (UNCONF); 181 } 182 183 void 184 sio_isa_attach_hook(parent, self, iba) 185 struct device *parent, *self; 186 struct isabus_attach_args *iba; 187 { 188 189 /* Nothing to do. */ 190 } 191 192 void 193 sio_eisa_attach_hook(parent, self, eba) 194 struct device *parent, *self; 195 struct eisabus_attach_args *eba; 196 { 197 198 /* Nothing to do. */ 199 } 200 201 int 202 sio_eisa_maxslots(v) 203 void *v; 204 { 205 206 return 16; /* as good a number as any. only 8, maybe? */ 207 } 208 209 int 210 sio_eisa_intr_map(v, irq, ihp) 211 void *v; 212 u_int irq; 213 eisa_intr_handle_t *ihp; 214 { 215 216 #define ICU_LEN 16 /* number of ISA IRQs (XXX) */ 217 218 if (irq >= ICU_LEN) { 219 printf("sio_eisa_intr_map: bad IRQ %d\n", irq); 220 *ihp = -1; 221 return 1; 222 } 223 if (irq == 2) { 224 printf("sio_eisa_intr_map: changed IRQ 2 to IRQ 9\n"); 225 irq = 9; 226 } 227 228 *ihp = irq; 229 return 0; 230 } 231