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