1 /* $OpenBSD: sio.c,v 1.40 2015/08/15 19:26:00 miod 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 "eisa.h" 49 #include "isadma.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_dmat; 56 int sc_haseisa; 57 58 struct alpha_eisa_chipset sc_ec; 59 struct alpha_isa_chipset sc_ic; 60 }; 61 62 int siomatch(struct device *, void *, void *); 63 void sioattach(struct device *, struct device *, void *); 64 int sioactivate(struct device *, int); 65 66 extern int sio_intr_alloc(isa_chipset_tag_t, int, int, int *); 67 extern int sio_intr_check(isa_chipset_tag_t, int, int); 68 69 const struct cfattach sio_ca = { 70 .ca_devsize = sizeof(struct sio_softc), 71 .ca_match = siomatch, 72 .ca_attach = sioattach, 73 .ca_activate = sioactivate 74 }; 75 76 struct cfdriver sio_cd = { 77 NULL, "sio", DV_DULL, 78 }; 79 80 int pcebmatch(struct device *, void *, void *); 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_intr_map(void *, u_int, eisa_intr_handle_t *); 102 void sio_bridge_callback(struct device *); 103 104 int 105 siomatch(parent, match, aux) 106 struct device *parent; 107 void *match; 108 void *aux; 109 { 110 struct pci_attach_args *pa = aux; 111 112 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CONTAQ && 113 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CONTAQ_82C693 && 114 pa->pa_function == 0) 115 return (1); 116 117 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL && 118 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_SIO) 119 return (1); 120 121 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ALI && 122 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ALI_M1533) 123 return(1); 124 125 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ALI && 126 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ALI_M1543) 127 return(1); 128 return (0); 129 } 130 131 int 132 pcebmatch(parent, match, aux) 133 struct device *parent; 134 void *match; 135 void *aux; 136 { 137 struct pci_attach_args *pa = aux; 138 139 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL && 140 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_PCEB) 141 return (1); 142 143 return (0); 144 } 145 146 void 147 sioattach(parent, self, aux) 148 struct device *parent, *self; 149 void *aux; 150 { 151 struct sio_softc *sc = (struct sio_softc *)self; 152 struct pci_attach_args *pa = aux; 153 154 printf("\n"); 155 156 sc->sc_iot = pa->pa_iot; 157 sc->sc_memt = pa->pa_memt; 158 sc->sc_dmat = pa->pa_dmat; 159 sc->sc_haseisa = (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL && 160 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_PCEB); 161 162 config_defer(self, sio_bridge_callback); 163 } 164 165 int 166 sioactivate(struct device *self, int act) 167 { 168 int rv = 0; 169 170 switch (act) { 171 case DVACT_POWERDOWN: 172 rv = config_activate_children(self, act); 173 sio_intr_shutdown(); 174 break; 175 default: 176 rv = config_activate_children(self, act); 177 break; 178 } 179 return (rv); 180 } 181 182 void 183 sio_bridge_callback(self) 184 struct device *self; 185 { 186 struct sio_softc *sc = (struct sio_softc *)self; 187 union sio_attach_args sa; 188 189 if (sc->sc_haseisa) { 190 sc->sc_ec.ec_v = NULL; 191 sc->sc_ec.ec_maxslots = 0; /* will be filled by attach_hook */ 192 sc->sc_ec.ec_attach_hook = sio_eisa_attach_hook; 193 sc->sc_ec.ec_intr_map = sio_eisa_intr_map; 194 sc->sc_ec.ec_intr_string = sio_intr_string; 195 sc->sc_ec.ec_intr_establish = sio_intr_establish; 196 sc->sc_ec.ec_intr_disestablish = sio_intr_disestablish; 197 198 sa.sa_eba.eba_busname = "eisa"; 199 sa.sa_eba.eba_iot = sc->sc_iot; 200 sa.sa_eba.eba_memt = sc->sc_memt; 201 sa.sa_eba.eba_dmat = 202 alphabus_dma_get_tag(sc->sc_dmat, ALPHA_BUS_EISA); 203 sa.sa_eba.eba_ec = &sc->sc_ec; 204 config_found(&sc->sc_dv, &sa.sa_eba, sioprint); 205 } 206 207 sc->sc_ic.ic_v = NULL; 208 sc->sc_ic.ic_attach_hook = sio_isa_attach_hook; 209 sc->sc_ic.ic_intr_establish = sio_intr_establish; 210 sc->sc_ic.ic_intr_disestablish = sio_intr_disestablish; 211 sc->sc_ic.ic_intr_alloc = sio_intr_alloc; 212 sc->sc_ic.ic_intr_check = sio_intr_check; 213 214 sa.sa_iba.iba_busname = "isa"; 215 sa.sa_iba.iba_iot = sc->sc_iot; 216 sa.sa_iba.iba_memt = sc->sc_memt; 217 #if NISADMA > 0 218 sa.sa_iba.iba_dmat = 219 alphabus_dma_get_tag(sc->sc_dmat, ALPHA_BUS_ISA); 220 #endif 221 sa.sa_iba.iba_ic = &sc->sc_ic; 222 config_found(&sc->sc_dv, &sa.sa_iba, sioprint); 223 } 224 225 int 226 sioprint(aux, pnp) 227 void *aux; 228 const char *pnp; 229 { 230 register union sio_attach_args *sa = aux; 231 232 if (pnp) 233 printf("%s at %s", sa->sa_name, pnp); 234 return (UNCONF); 235 } 236 237 void 238 sio_isa_attach_hook(parent, self, iba) 239 struct device *parent, *self; 240 struct isabus_attach_args *iba; 241 { 242 /* Nothing to do. */ 243 } 244 245 void 246 sio_eisa_attach_hook(parent, self, eba) 247 struct device *parent, *self; 248 struct eisabus_attach_args *eba; 249 { 250 #if NEISA > 0 251 eisa_init(eba->eba_ec); 252 #endif 253 } 254 255 int 256 sio_eisa_intr_map(v, irq, ihp) 257 void *v; 258 u_int irq; 259 eisa_intr_handle_t *ihp; 260 { 261 262 #define ICU_LEN 16 /* number of ISA IRQs (XXX) */ 263 264 if (irq >= ICU_LEN) { 265 printf("sio_eisa_intr_map: bad IRQ %d\n", irq); 266 *ihp = -1; 267 return 1; 268 } 269 if (irq == 2) { 270 printf("sio_eisa_intr_map: changed IRQ 2 to IRQ 9\n"); 271 irq = 9; 272 } 273 274 *ihp = irq; 275 return 0; 276 } 277