1 /* $OpenBSD: sio.c,v 1.36 2010/06/06 11:26:11 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 config_defer(self, sio_bridge_callback); 156 } 157 158 void 159 sio_bridge_callback(self) 160 struct device *self; 161 { 162 struct sio_softc *sc = (struct sio_softc *)self; 163 struct alpha_eisa_chipset ec; 164 struct alpha_isa_chipset ic; 165 union sio_attach_args sa; 166 167 if (sc->sc_haseisa) { 168 ec.ec_v = NULL; 169 ec.ec_maxslots = 0; /* will be filled by attach_hook */ 170 ec.ec_attach_hook = sio_eisa_attach_hook; 171 ec.ec_intr_map = sio_eisa_intr_map; 172 ec.ec_intr_string = sio_intr_string; 173 ec.ec_intr_establish = sio_intr_establish; 174 ec.ec_intr_disestablish = sio_intr_disestablish; 175 176 sa.sa_eba.eba_busname = "eisa"; 177 sa.sa_eba.eba_iot = sc->sc_iot; 178 sa.sa_eba.eba_memt = sc->sc_memt; 179 sa.sa_eba.eba_dmat = 180 alphabus_dma_get_tag(sc->sc_dmat, ALPHA_BUS_EISA); 181 sa.sa_eba.eba_ec = &ec; 182 config_found(&sc->sc_dv, &sa.sa_eba, sioprint); 183 } 184 185 ic.ic_v = NULL; 186 ic.ic_attach_hook = sio_isa_attach_hook; 187 ic.ic_intr_establish = sio_intr_establish; 188 ic.ic_intr_disestablish = sio_intr_disestablish; 189 ic.ic_intr_alloc = sio_intr_alloc; 190 191 sa.sa_iba.iba_busname = "isa"; 192 sa.sa_iba.iba_iot = sc->sc_iot; 193 sa.sa_iba.iba_memt = sc->sc_memt; 194 #if NISADMA > 0 195 sa.sa_iba.iba_dmat = 196 alphabus_dma_get_tag(sc->sc_dmat, ALPHA_BUS_ISA); 197 #endif 198 sa.sa_iba.iba_ic = ⁣ 199 config_found(&sc->sc_dv, &sa.sa_iba, sioprint); 200 } 201 202 int 203 sioprint(aux, pnp) 204 void *aux; 205 const char *pnp; 206 { 207 register union sio_attach_args *sa = aux; 208 209 if (pnp) 210 printf("%s at %s", sa->sa_name, pnp); 211 return (UNCONF); 212 } 213 214 void 215 sio_isa_attach_hook(parent, self, iba) 216 struct device *parent, *self; 217 struct isabus_attach_args *iba; 218 { 219 /* Nothing to do. */ 220 } 221 222 void 223 sio_eisa_attach_hook(parent, self, eba) 224 struct device *parent, *self; 225 struct eisabus_attach_args *eba; 226 { 227 #if NEISA > 0 228 eisa_init(eba->eba_ec); 229 #endif 230 } 231 232 int 233 sio_eisa_intr_map(v, irq, ihp) 234 void *v; 235 u_int irq; 236 eisa_intr_handle_t *ihp; 237 { 238 239 #define ICU_LEN 16 /* number of ISA IRQs (XXX) */ 240 241 if (irq >= ICU_LEN) { 242 printf("sio_eisa_intr_map: bad IRQ %d\n", irq); 243 *ihp = -1; 244 return 1; 245 } 246 if (irq == 2) { 247 printf("sio_eisa_intr_map: changed IRQ 2 to IRQ 9\n"); 248 irq = 9; 249 } 250 251 *ihp = irq; 252 return 0; 253 } 254