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