1 /* $NetBSD: sio.c,v 1.20 1997/09/02 13:19:51 thorpej 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/cdefs.h> /* RCS ID & Copyright macro defns */ 31 32 __KERNEL_RCSID(0, "$NetBSD: sio.c,v 1.20 1997/09/02 13:19:51 thorpej Exp $"); 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/kernel.h> 37 #include <sys/device.h> 38 39 #include <machine/intr.h> 40 #include <machine/bus.h> 41 42 #include <dev/isa/isavar.h> 43 #include <dev/eisa/eisavar.h> 44 45 #include <dev/pci/pcireg.h> 46 #include <dev/pci/pcivar.h> 47 #include <dev/pci/pcidevs.h> 48 49 #include <alpha/pci/siovar.h> 50 51 struct sio_softc { 52 struct device sc_dv; 53 54 bus_space_tag_t sc_iot, sc_memt; 55 bus_dma_tag_t sc_parent_dmat; 56 int sc_haseisa; 57 }; 58 59 int siomatch __P((struct device *, struct cfdata *, void *)); 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 int pcebmatch __P((struct device *, struct cfdata *, void *)); 71 72 struct cfattach pceb_ca = { 73 sizeof(struct device), pcebmatch, sioattach, 74 }; 75 76 struct cfdriver pceb_cd = { 77 NULL, "pceb", DV_DULL, 78 }; 79 80 union sio_attach_args { 81 const char *sa_name; /* XXX should be common */ 82 struct isabus_attach_args sa_iba; 83 struct eisabus_attach_args sa_eba; 84 }; 85 86 int sioprint __P((void *, const char *pnp)); 87 void sio_isa_attach_hook __P((struct device *, struct device *, 88 struct isabus_attach_args *)); 89 void sio_eisa_attach_hook __P((struct device *, struct device *, 90 struct eisabus_attach_args *)); 91 int sio_eisa_maxslots __P((void *)); 92 int sio_eisa_intr_map __P((void *, u_int, eisa_intr_handle_t *)); 93 94 void sio_bridge_callback __P((void *)); 95 96 int 97 siomatch(parent, match, aux) 98 struct device *parent; 99 struct cfdata *match; 100 void *aux; 101 { 102 struct pci_attach_args *pa = aux; 103 104 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL || 105 PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_INTEL_SIO) 106 return (0); 107 108 return (1); 109 } 110 111 int 112 pcebmatch(parent, match, aux) 113 struct device *parent; 114 struct cfdata *match; 115 void *aux; 116 { 117 struct pci_attach_args *pa = aux; 118 119 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL || 120 PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_INTEL_PCEB) 121 return (0); 122 123 return (1); 124 } 125 126 void 127 sioattach(parent, self, aux) 128 struct device *parent, *self; 129 void *aux; 130 { 131 struct sio_softc *sc = (struct sio_softc *)self; 132 struct pci_attach_args *pa = aux; 133 char devinfo[256]; 134 135 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo); 136 printf(": %s (rev. 0x%02x)\n", devinfo, 137 PCI_REVISION(pa->pa_class)); 138 139 sc->sc_iot = pa->pa_iot; 140 sc->sc_memt = pa->pa_memt; 141 sc->sc_parent_dmat = pa->pa_dmat; 142 sc->sc_haseisa = (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_PCEB); 143 144 #ifdef EVCNT_COUNTERS 145 evcnt_attach(&sc->sc_dv, "intr", &sio_intr_evcnt); 146 #endif 147 148 set_pci_isa_bridge_callback(sio_bridge_callback, sc); 149 } 150 151 void 152 sio_bridge_callback(v) 153 void *v; 154 { 155 struct sio_softc *sc = v; 156 struct alpha_eisa_chipset ec; 157 struct alpha_isa_chipset ic; 158 union sio_attach_args sa; 159 160 if (sc->sc_haseisa) { 161 ec.ec_v = NULL; 162 ec.ec_attach_hook = sio_eisa_attach_hook; 163 ec.ec_maxslots = sio_eisa_maxslots; 164 ec.ec_intr_map = sio_eisa_intr_map; 165 ec.ec_intr_string = sio_intr_string; 166 ec.ec_intr_establish = sio_intr_establish; 167 ec.ec_intr_disestablish = sio_intr_disestablish; 168 169 sa.sa_eba.eba_busname = "eisa"; 170 sa.sa_eba.eba_iot = sc->sc_iot; 171 sa.sa_eba.eba_memt = sc->sc_memt; 172 sa.sa_eba.eba_dmat = 173 alphabus_dma_get_tag(sc->sc_parent_dmat, ALPHA_BUS_EISA); 174 sa.sa_eba.eba_ec = &ec; 175 config_found(&sc->sc_dv, &sa.sa_eba, sioprint); 176 } 177 178 ic.ic_v = NULL; 179 ic.ic_attach_hook = sio_isa_attach_hook; 180 ic.ic_intr_establish = sio_intr_establish; 181 ic.ic_intr_disestablish = sio_intr_disestablish; 182 183 sa.sa_iba.iba_busname = "isa"; 184 sa.sa_iba.iba_iot = sc->sc_iot; 185 sa.sa_iba.iba_memt = sc->sc_memt; 186 sa.sa_iba.iba_dmat = 187 alphabus_dma_get_tag(sc->sc_parent_dmat, ALPHA_BUS_ISA); 188 sa.sa_iba.iba_ic = ⁣ 189 config_found(&sc->sc_dv, &sa.sa_iba, sioprint); 190 } 191 192 int 193 sioprint(aux, pnp) 194 void *aux; 195 const char *pnp; 196 { 197 register union sio_attach_args *sa = aux; 198 199 if (pnp) 200 printf("%s at %s", sa->sa_name, pnp); 201 return (UNCONF); 202 } 203 204 void 205 sio_isa_attach_hook(parent, self, iba) 206 struct device *parent, *self; 207 struct isabus_attach_args *iba; 208 { 209 210 /* Nothing to do. */ 211 } 212 213 void 214 sio_eisa_attach_hook(parent, self, eba) 215 struct device *parent, *self; 216 struct eisabus_attach_args *eba; 217 { 218 219 /* Nothing to do. */ 220 } 221 222 int 223 sio_eisa_maxslots(v) 224 void *v; 225 { 226 227 return 16; /* as good a number as any. only 8, maybe? */ 228 } 229 230 int 231 sio_eisa_intr_map(v, irq, ihp) 232 void *v; 233 u_int irq; 234 eisa_intr_handle_t *ihp; 235 { 236 237 #define ICU_LEN 16 /* number of ISA IRQs (XXX) */ 238 239 if (irq >= ICU_LEN) { 240 printf("sio_eisa_intr_map: bad IRQ %d\n", irq); 241 *ihp = -1; 242 return 1; 243 } 244 if (irq == 2) { 245 printf("sio_eisa_intr_map: changed IRQ 2 to IRQ 9\n"); 246 irq = 9; 247 } 248 249 *ihp = irq; 250 return 0; 251 } 252