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