1 /* $NetBSD: sio.c,v 1.13 1996/11/13 21:13:33 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 <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/kernel.h> 33 #include <sys/device.h> 34 35 #include <machine/intr.h> 36 #include <machine/bus.h> 37 38 #include <dev/isa/isavar.h> 39 #include <dev/eisa/eisavar.h> 40 41 #include <dev/pci/pcireg.h> 42 #include <dev/pci/pcivar.h> 43 #include <dev/pci/pcidevs.h> 44 45 #include <alpha/pci/siovar.h> 46 47 int siomatch __P((struct device *, void *, void *)); 48 void sioattach __P((struct device *, struct device *, void *)); 49 50 struct cfattach sio_ca = { 51 sizeof(struct device), siomatch, sioattach, 52 }; 53 54 struct cfdriver sio_cd = { 55 NULL, "sio", DV_DULL, 56 }; 57 58 int pcebmatch __P((struct device *, void *, void *)); 59 60 struct cfattach pceb_ca = { 61 sizeof(struct device), pcebmatch, sioattach, 62 }; 63 64 struct cfdriver pceb_cd = { 65 NULL, "pceb", DV_DULL, 66 }; 67 68 union sio_attach_args { 69 const char *sa_name; /* XXX should be common */ 70 struct isabus_attach_args sa_iba; 71 struct eisabus_attach_args sa_eba; 72 }; 73 74 int sioprint __P((void *, const char *pnp)); 75 void sio_isa_attach_hook __P((struct device *, struct device *, 76 struct isabus_attach_args *)); 77 void sio_eisa_attach_hook __P((struct device *, struct device *, 78 struct eisabus_attach_args *)); 79 int sio_eisa_maxslots __P((void *)); 80 int sio_eisa_intr_map __P((void *, u_int, eisa_intr_handle_t *)); 81 82 int 83 siomatch(parent, match, aux) 84 struct device *parent; 85 void *match, *aux; 86 { 87 struct pci_attach_args *pa = aux; 88 89 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL || 90 PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_INTEL_SIO) 91 return (0); 92 93 return (1); 94 } 95 96 int 97 pcebmatch(parent, match, aux) 98 struct device *parent; 99 void *match, *aux; 100 { 101 struct pci_attach_args *pa = aux; 102 103 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL || 104 PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_INTEL_PCEB) 105 return (0); 106 107 return (1); 108 } 109 110 void 111 sioattach(parent, self, aux) 112 struct device *parent, *self; 113 void *aux; 114 { 115 struct pci_attach_args *pa = aux; 116 struct alpha_isa_chipset ic; 117 struct alpha_eisa_chipset ec; 118 union sio_attach_args sa; 119 int sio, haseisa; 120 char devinfo[256]; 121 122 sio = (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_SIO); 123 haseisa = (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_PCEB); 124 125 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo); 126 printf(": %s (rev. 0x%02x)\n", devinfo, 127 PCI_REVISION(pa->pa_class)); 128 129 if (sio) { 130 pci_revision_t rev; 131 132 rev = PCI_REVISION(pa->pa_class); 133 134 if (rev < 3) 135 printf("%s: WARNING: SIO I SUPPORT UNTESTED\n", 136 self->dv_xname); 137 } 138 139 #ifdef EVCNT_COUNTERS 140 evcnt_attach(self, "intr", &sio_intr_evcnt); 141 #endif 142 143 if (haseisa) { 144 ec.ec_v = NULL; 145 ec.ec_attach_hook = sio_eisa_attach_hook; 146 ec.ec_maxslots = sio_eisa_maxslots; 147 ec.ec_intr_map = sio_eisa_intr_map; 148 ec.ec_intr_string = sio_intr_string; 149 ec.ec_intr_establish = sio_intr_establish; 150 ec.ec_intr_disestablish = sio_intr_disestablish; 151 152 sa.sa_eba.eba_busname = "eisa"; 153 sa.sa_eba.eba_iot = pa->pa_iot; 154 sa.sa_eba.eba_memt = pa->pa_memt; 155 sa.sa_eba.eba_ec = &ec; 156 config_found(self, &sa.sa_eba, sioprint); 157 } 158 159 ic.ic_v = NULL; 160 ic.ic_attach_hook = sio_isa_attach_hook; 161 ic.ic_intr_establish = sio_intr_establish; 162 ic.ic_intr_disestablish = sio_intr_disestablish; 163 164 sa.sa_iba.iba_busname = "isa"; 165 sa.sa_iba.iba_iot = pa->pa_iot; 166 sa.sa_iba.iba_memt = pa->pa_memt; 167 sa.sa_iba.iba_ic = ⁣ 168 config_found(self, &sa.sa_iba, sioprint); 169 } 170 171 int 172 sioprint(aux, pnp) 173 void *aux; 174 const char *pnp; 175 { 176 register union sio_attach_args *sa = aux; 177 178 if (pnp) 179 printf("%s at %s", sa->sa_name, pnp); 180 return (UNCONF); 181 } 182 183 void 184 sio_isa_attach_hook(parent, self, iba) 185 struct device *parent, *self; 186 struct isabus_attach_args *iba; 187 { 188 189 /* Nothing to do. */ 190 } 191 192 void 193 sio_eisa_attach_hook(parent, self, eba) 194 struct device *parent, *self; 195 struct eisabus_attach_args *eba; 196 { 197 198 /* Nothing to do. */ 199 } 200 201 int 202 sio_eisa_maxslots(v) 203 void *v; 204 { 205 206 return 16; /* as good a number as any. only 8, maybe? */ 207 } 208 209 int 210 sio_eisa_intr_map(v, irq, ihp) 211 void *v; 212 u_int irq; 213 eisa_intr_handle_t *ihp; 214 { 215 216 #define ICU_LEN 16 /* number of ISA IRQs (XXX) */ 217 218 if (irq >= ICU_LEN) { 219 printf("sio_eisa_intr_map: bad IRQ %d\n", irq); 220 *ihp = -1; 221 return 1; 222 } 223 if (irq == 2) { 224 printf("sio_eisa_intr_map: changed IRQ 2 to IRQ 9\n"); 225 irq = 9; 226 } 227 228 *ihp = irq; 229 return 0; 230 } 231