1 /* $NetBSD: sio.c,v 1.18 1997/04/07 23:40:46 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 <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.18 1997/04/07 23:40:46 cgd 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 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_haseisa = (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_PCEB); 142 143 #ifdef EVCNT_COUNTERS 144 evcnt_attach(&sc->sc_dv, "intr", &sio_intr_evcnt); 145 #endif 146 147 set_pci_isa_bridge_callback(sio_bridge_callback, sc); 148 } 149 150 void 151 sio_bridge_callback(v) 152 void *v; 153 { 154 struct sio_softc *sc = v; 155 struct alpha_eisa_chipset ec; 156 struct alpha_isa_chipset ic; 157 union sio_attach_args sa; 158 159 if (sc->sc_haseisa) { 160 ec.ec_v = NULL; 161 ec.ec_attach_hook = sio_eisa_attach_hook; 162 ec.ec_maxslots = sio_eisa_maxslots; 163 ec.ec_intr_map = sio_eisa_intr_map; 164 ec.ec_intr_string = sio_intr_string; 165 ec.ec_intr_establish = sio_intr_establish; 166 ec.ec_intr_disestablish = sio_intr_disestablish; 167 168 sa.sa_eba.eba_busname = "eisa"; 169 sa.sa_eba.eba_iot = sc->sc_iot; 170 sa.sa_eba.eba_memt = sc->sc_memt; 171 sa.sa_eba.eba_ec = &ec; 172 config_found(&sc->sc_dv, &sa.sa_eba, sioprint); 173 } 174 175 ic.ic_v = NULL; 176 ic.ic_attach_hook = sio_isa_attach_hook; 177 ic.ic_intr_establish = sio_intr_establish; 178 ic.ic_intr_disestablish = sio_intr_disestablish; 179 180 sa.sa_iba.iba_busname = "isa"; 181 sa.sa_iba.iba_iot = sc->sc_iot; 182 sa.sa_iba.iba_memt = sc->sc_memt; 183 sa.sa_iba.iba_ic = ⁣ 184 config_found(&sc->sc_dv, &sa.sa_iba, sioprint); 185 } 186 187 int 188 sioprint(aux, pnp) 189 void *aux; 190 const char *pnp; 191 { 192 register union sio_attach_args *sa = aux; 193 194 if (pnp) 195 printf("%s at %s", sa->sa_name, pnp); 196 return (UNCONF); 197 } 198 199 void 200 sio_isa_attach_hook(parent, self, iba) 201 struct device *parent, *self; 202 struct isabus_attach_args *iba; 203 { 204 205 /* Nothing to do. */ 206 } 207 208 void 209 sio_eisa_attach_hook(parent, self, eba) 210 struct device *parent, *self; 211 struct eisabus_attach_args *eba; 212 { 213 214 /* Nothing to do. */ 215 } 216 217 int 218 sio_eisa_maxslots(v) 219 void *v; 220 { 221 222 return 16; /* as good a number as any. only 8, maybe? */ 223 } 224 225 int 226 sio_eisa_intr_map(v, irq, ihp) 227 void *v; 228 u_int irq; 229 eisa_intr_handle_t *ihp; 230 { 231 232 #define ICU_LEN 16 /* number of ISA IRQs (XXX) */ 233 234 if (irq >= ICU_LEN) { 235 printf("sio_eisa_intr_map: bad IRQ %d\n", irq); 236 *ihp = -1; 237 return 1; 238 } 239 if (irq == 2) { 240 printf("sio_eisa_intr_map: changed IRQ 2 to IRQ 9\n"); 241 irq = 9; 242 } 243 244 *ihp = irq; 245 return 0; 246 } 247