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