1 /* $OpenBSD: sio.c,v 1.27 2002/03/14 01:26:27 millert 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 #include "isadma.h" 49 50 struct sio_softc { 51 struct device sc_dv; 52 53 bus_space_tag_t sc_iot, sc_memt; 54 bus_dma_tag_t sc_dmat; 55 int sc_haseisa; 56 }; 57 58 #ifdef __BROKEN_INDIRECT_CONFIG 59 int siomatch(struct device *, void *, void *); 60 #else 61 int siomatch(struct device *, struct cfdata *, void *); 62 #endif 63 void sioattach(struct device *, struct device *, void *); 64 65 extern int sio_intr_alloc(isa_chipset_tag_t *, int, int, int *); 66 67 68 struct cfattach sio_ca = { 69 sizeof(struct sio_softc), siomatch, sioattach, 70 }; 71 72 struct cfdriver sio_cd = { 73 NULL, "sio", DV_DULL, 74 }; 75 76 #ifdef __BROKEN_INDIRECT_CONFIG 77 int pcebmatch(struct device *, void *, void *); 78 #else 79 int pcebmatch(struct device *, struct cfdata *, void *); 80 #endif 81 82 struct cfattach pceb_ca = { 83 sizeof(struct sio_softc), pcebmatch, sioattach, 84 }; 85 86 struct cfdriver pceb_cd = { 87 NULL, "pceb", DV_DULL, 88 }; 89 90 union sio_attach_args { 91 const char *sa_name; /* XXX should be common */ 92 struct isabus_attach_args sa_iba; 93 struct eisabus_attach_args sa_eba; 94 }; 95 96 int sioprint(void *, const char *pnp); 97 void sio_isa_attach_hook(struct device *, struct device *, 98 struct isabus_attach_args *); 99 void sio_eisa_attach_hook(struct device *, struct device *, 100 struct eisabus_attach_args *); 101 int sio_eisa_maxslots(void *); 102 int sio_eisa_intr_map(void *, u_int, eisa_intr_handle_t *); 103 void sio_bridge_callback(void *); 104 105 int 106 siomatch(parent, match, aux) 107 struct device *parent; 108 #ifdef __BROKEN_INDIRECT_CONFIG 109 void *match; 110 #else 111 struct cfdata *match; 112 #endif 113 void *aux; 114 { 115 struct pci_attach_args *pa = aux; 116 117 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CONTAQ && 118 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CONTAQ_82C693 && 119 pa->pa_function == 0) 120 return (1); 121 122 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL && 123 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_SIO) 124 return (1); 125 126 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ALI && 127 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ALI_M1543) 128 return(1); 129 return (0); 130 } 131 132 int 133 pcebmatch(parent, match, aux) 134 struct device *parent; 135 #ifdef __BROKEN_INDIRECT_CONFIG 136 void *match; 137 #else 138 struct cfdata *match; 139 #endif 140 void *aux; 141 { 142 struct pci_attach_args *pa = aux; 143 144 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL && 145 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_PCEB) 146 return (1); 147 148 return (0); 149 } 150 151 void 152 sioattach(parent, self, aux) 153 struct device *parent, *self; 154 void *aux; 155 { 156 struct sio_softc *sc = (struct sio_softc *)self; 157 struct pci_attach_args *pa = aux; 158 159 printf("\n"); 160 161 sc->sc_iot = pa->pa_iot; 162 sc->sc_memt = pa->pa_memt; 163 sc->sc_dmat = pa->pa_dmat; 164 sc->sc_haseisa = (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL && 165 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_PCEB); 166 167 #ifdef EVCNT_COUNTERS 168 evcnt_attach(&sc->sc_dv, "intr", &sio_intr_evcnt); 169 #endif 170 171 set_pci_isa_bridge_callback(sio_bridge_callback, sc); 172 } 173 174 void 175 sio_bridge_callback(v) 176 void *v; 177 { 178 struct sio_softc *sc = v; 179 struct alpha_eisa_chipset ec; 180 struct alpha_isa_chipset ic; 181 union sio_attach_args sa; 182 183 if (sc->sc_haseisa) { 184 ec.ec_v = NULL; 185 ec.ec_attach_hook = sio_eisa_attach_hook; 186 ec.ec_maxslots = sio_eisa_maxslots; 187 ec.ec_intr_map = sio_eisa_intr_map; 188 ec.ec_intr_string = sio_intr_string; 189 ec.ec_intr_establish = sio_intr_establish; 190 ec.ec_intr_disestablish = sio_intr_disestablish; 191 192 sa.sa_eba.eba_busname = "eisa"; 193 sa.sa_eba.eba_iot = sc->sc_iot; 194 sa.sa_eba.eba_memt = sc->sc_memt; 195 sa.sa_eba.eba_ec = &ec; 196 config_found(&sc->sc_dv, &sa.sa_eba, sioprint); 197 } 198 199 ic.ic_v = NULL; 200 ic.ic_attach_hook = sio_isa_attach_hook; 201 ic.ic_intr_establish = sio_intr_establish; 202 ic.ic_intr_disestablish = sio_intr_disestablish; 203 ic.ic_intr_alloc = sio_intr_alloc; 204 205 sa.sa_iba.iba_busname = "isa"; 206 sa.sa_iba.iba_iot = sc->sc_iot; 207 sa.sa_iba.iba_memt = sc->sc_memt; 208 #if NISADMA > 0 209 sa.sa_iba.iba_dmat = 210 alphabus_dma_get_tag(sc->sc_dmat, ALPHA_BUS_ISA); 211 #endif 212 sa.sa_iba.iba_ic = ⁣ 213 config_found(&sc->sc_dv, &sa.sa_iba, sioprint); 214 } 215 216 int 217 sioprint(aux, pnp) 218 void *aux; 219 const char *pnp; 220 { 221 register union sio_attach_args *sa = aux; 222 223 if (pnp) 224 printf("%s at %s", sa->sa_name, pnp); 225 return (UNCONF); 226 } 227 228 void 229 sio_isa_attach_hook(parent, self, iba) 230 struct device *parent, *self; 231 struct isabus_attach_args *iba; 232 { 233 /* Nothing to do. */ 234 } 235 236 void 237 sio_eisa_attach_hook(parent, self, eba) 238 struct device *parent, *self; 239 struct eisabus_attach_args *eba; 240 { 241 242 /* Nothing to do. */ 243 } 244 245 int 246 sio_eisa_maxslots(v) 247 void *v; 248 { 249 250 return 16; /* as good a number as any. only 8, maybe? */ 251 } 252 253 int 254 sio_eisa_intr_map(v, irq, ihp) 255 void *v; 256 u_int irq; 257 eisa_intr_handle_t *ihp; 258 { 259 260 #define ICU_LEN 16 /* number of ISA IRQs (XXX) */ 261 262 if (irq >= ICU_LEN) { 263 printf("sio_eisa_intr_map: bad IRQ %d\n", irq); 264 *ihp = -1; 265 return 1; 266 } 267 if (irq == 2) { 268 printf("sio_eisa_intr_map: changed IRQ 2 to IRQ 9\n"); 269 irq = 9; 270 } 271 272 *ihp = irq; 273 return 0; 274 } 275