1 /* $NetBSD: pci_eb164.c,v 1.24 1999/02/12 06:25:13 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * Copyright (c) 1995, 1996 Carnegie-Mellon University. 42 * All rights reserved. 43 * 44 * Author: Chris G. Demetriou 45 * 46 * Permission to use, copy, modify and distribute this software and 47 * its documentation is hereby granted, provided that both the copyright 48 * notice and this permission notice appear in all copies of the 49 * software, derivative works or modified versions, and any portions 50 * thereof, and that both notices appear in supporting documentation. 51 * 52 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 53 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 54 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 55 * 56 * Carnegie Mellon requests users of this software to return to 57 * 58 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 59 * School of Computer Science 60 * Carnegie Mellon University 61 * Pittsburgh PA 15213-3890 62 * 63 * any improvements or extensions that they make and grant Carnegie the 64 * rights to redistribute these changes. 65 */ 66 67 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 68 69 __KERNEL_RCSID(0, "$NetBSD: pci_eb164.c,v 1.24 1999/02/12 06:25:13 thorpej Exp $"); 70 71 #include <sys/types.h> 72 #include <sys/param.h> 73 #include <sys/time.h> 74 #include <sys/systm.h> 75 #include <sys/errno.h> 76 #include <sys/malloc.h> 77 #include <sys/device.h> 78 #include <sys/syslog.h> 79 80 #include <vm/vm.h> 81 82 #include <machine/autoconf.h> 83 #include <machine/rpb.h> 84 85 #include <dev/pci/pcireg.h> 86 #include <dev/pci/pcivar.h> 87 #include <dev/pci/pciidereg.h> 88 #include <dev/pci/pciidevar.h> 89 90 #include <alpha/pci/ciareg.h> 91 #include <alpha/pci/ciavar.h> 92 93 #include <alpha/pci/pci_eb164.h> 94 95 #ifndef EVCNT_COUNTERS 96 #include <machine/intrcnt.h> 97 #endif 98 99 #include "sio.h" 100 #if NSIO 101 #include <alpha/pci/siovar.h> 102 #endif 103 104 int dec_eb164_intr_map __P((void *, pcitag_t, int, int, 105 pci_intr_handle_t *)); 106 const char *dec_eb164_intr_string __P((void *, pci_intr_handle_t)); 107 void *dec_eb164_intr_establish __P((void *, pci_intr_handle_t, 108 int, int (*func)(void *), void *)); 109 void dec_eb164_intr_disestablish __P((void *, void *)); 110 111 void *dec_eb164_pciide_compat_intr_establish __P((void *, struct device *, 112 struct pci_attach_args *, int, int (*)(void *), void *)); 113 114 #define EB164_SIO_IRQ 4 115 #define EB164_MAX_IRQ 24 116 #define PCI_STRAY_MAX 5 117 118 struct alpha_shared_intr *eb164_pci_intr; 119 #ifdef EVCNT_COUNTERS 120 struct evcnt eb164_intr_evcnt; 121 #endif 122 123 bus_space_tag_t eb164_intrgate_iot; 124 bus_space_handle_t eb164_intrgate_ioh; 125 126 void eb164_iointr __P((void *framep, unsigned long vec)); 127 extern void eb164_intr_enable __P((int irq)); /* pci_eb164_intr.S */ 128 extern void eb164_intr_disable __P((int irq)); /* pci_eb164_intr.S */ 129 130 void 131 pci_eb164_pickintr(ccp) 132 struct cia_config *ccp; 133 { 134 bus_space_tag_t iot = &ccp->cc_iot; 135 pci_chipset_tag_t pc = &ccp->cc_pc; 136 int i; 137 138 pc->pc_intr_v = ccp; 139 pc->pc_intr_map = dec_eb164_intr_map; 140 pc->pc_intr_string = dec_eb164_intr_string; 141 pc->pc_intr_establish = dec_eb164_intr_establish; 142 pc->pc_intr_disestablish = dec_eb164_intr_disestablish; 143 144 pc->pc_pciide_compat_intr_establish = 145 dec_eb164_pciide_compat_intr_establish; 146 147 eb164_intrgate_iot = iot; 148 if (bus_space_map(eb164_intrgate_iot, 0x804, 3, 0, 149 &eb164_intrgate_ioh) != 0) 150 panic("pci_eb164_pickintr: couldn't map interrupt PLD"); 151 for (i = 0; i < EB164_MAX_IRQ; i++) 152 eb164_intr_disable(i); 153 154 eb164_pci_intr = alpha_shared_intr_alloc(EB164_MAX_IRQ); 155 for (i = 0; i < EB164_MAX_IRQ; i++) { 156 /* 157 * Systems with a Pyxis seem to have problems with 158 * stray interrupts, so just ignore them. Sigh, 159 * I hate buggy hardware. 160 */ 161 alpha_shared_intr_set_maxstrays(eb164_pci_intr, i, 162 (ccp->cc_flags & CCF_ISPYXIS) ? 0 : PCI_STRAY_MAX); 163 } 164 165 #if NSIO 166 sio_intr_setup(pc, iot); 167 eb164_intr_enable(EB164_SIO_IRQ); 168 #endif 169 170 set_iointr(eb164_iointr); 171 } 172 173 int 174 dec_eb164_intr_map(ccv, bustag, buspin, line, ihp) 175 void *ccv; 176 pcitag_t bustag; 177 int buspin, line; 178 pci_intr_handle_t *ihp; 179 { 180 struct cia_config *ccp = ccv; 181 pci_chipset_tag_t pc = &ccp->cc_pc; 182 int bus, device, function; 183 u_int64_t variation; 184 185 if (buspin == 0) { 186 /* No IRQ used. */ 187 return 1; 188 } 189 if (buspin > 4) { 190 printf("dec_eb164_intr_map: bad interrupt pin %d\n", buspin); 191 return 1; 192 } 193 194 alpha_pci_decompose_tag(pc, bustag, &bus, &device, &function); 195 196 variation = hwrpb->rpb_variation & SV_ST_MASK; 197 198 /* 199 * 200 * The AlphaPC 164 and AlphaPC 164LX have a CMD PCI IDE controller 201 * at bus 0 device 11. These are wired to compatibility mode, 202 * so do not map their interrupts. 203 * 204 * The AlphaPC 164SX has PCI IDE on functions 1 and 2 of the 205 * Cypress PCI-ISA bridge at bus 0 device 8. These, too, are 206 * wired to compatibility mode. 207 * 208 * Real EB164s have ISA IDE on the Super I/O chip. 209 */ 210 if (bus == 0) { 211 if (variation >= SV_ST_ALPHAPC164_366 && 212 variation <= SV_ST_ALPHAPC164LX_600) { 213 if (device == 8) 214 panic("dec_eb164_intr_map: SIO device"); 215 if (device == 11) 216 return (1); 217 } else if (variation >= SV_ST_ALPHAPC164SX_400 && 218 variation <= SV_ST_ALPHAPC164SX_600) { 219 if (device == 8) { 220 if (function == 0) 221 panic("dec_eb164_intr_map: SIO device"); 222 return (1); 223 } 224 } else { 225 if (device == 8) 226 panic("dec_eb164_intr_map: SIO device"); 227 } 228 } 229 230 /* 231 * The console places the interrupt mapping in the "line" value. 232 * A value of (char)-1 indicates there is no mapping. 233 */ 234 if (line == 0xff) { 235 printf("dec_eb164_intr_map: no mapping for %d/%d/%d\n", 236 bus, device, function); 237 return (1); 238 } 239 240 if (line > EB164_MAX_IRQ) 241 panic("dec_eb164_intr_map: eb164 irq too large (%d)\n", 242 line); 243 244 *ihp = line; 245 return (0); 246 } 247 248 const char * 249 dec_eb164_intr_string(ccv, ih) 250 void *ccv; 251 pci_intr_handle_t ih; 252 { 253 #if 0 254 struct cia_config *ccp = ccv; 255 #endif 256 static char irqstr[15]; /* 11 + 2 + NULL + sanity */ 257 258 if (ih > EB164_MAX_IRQ) 259 panic("dec_eb164_intr_string: bogus eb164 IRQ 0x%lx\n", ih); 260 sprintf(irqstr, "eb164 irq %ld", ih); 261 return (irqstr); 262 } 263 264 void * 265 dec_eb164_intr_establish(ccv, ih, level, func, arg) 266 void *ccv, *arg; 267 pci_intr_handle_t ih; 268 int level; 269 int (*func) __P((void *)); 270 { 271 #if 0 272 struct cia_config *ccp = ccv; 273 #endif 274 void *cookie; 275 276 if (ih > EB164_MAX_IRQ) 277 panic("dec_eb164_intr_establish: bogus eb164 IRQ 0x%lx\n", ih); 278 279 cookie = alpha_shared_intr_establish(eb164_pci_intr, ih, IST_LEVEL, 280 level, func, arg, "eb164 irq"); 281 282 if (cookie != NULL && alpha_shared_intr_isactive(eb164_pci_intr, ih)) 283 eb164_intr_enable(ih); 284 return (cookie); 285 } 286 287 void 288 dec_eb164_intr_disestablish(ccv, cookie) 289 void *ccv, *cookie; 290 { 291 #if 0 292 struct cia_config *ccp = ccv; 293 #endif 294 struct alpha_shared_intrhand *ih = cookie; 295 unsigned int irq = ih->ih_num; 296 int s; 297 298 s = splhigh(); 299 300 alpha_shared_intr_disestablish(eb164_pci_intr, cookie, 301 "eb164 irq"); 302 if (alpha_shared_intr_isactive(eb164_pci_intr, irq) == 0) { 303 eb164_intr_disable(irq); 304 alpha_shared_intr_set_dfltsharetype(eb164_pci_intr, irq, 305 IST_NONE); 306 } 307 308 splx(s); 309 } 310 311 void * 312 dec_eb164_pciide_compat_intr_establish(v, dev, pa, chan, func, arg) 313 void *v; 314 struct device *dev; 315 struct pci_attach_args *pa; 316 int chan; 317 int (*func) __P((void *)); 318 void *arg; 319 { 320 pci_chipset_tag_t pc = pa->pa_pc; 321 void *cookie = NULL; 322 int bus, irq; 323 324 alpha_pci_decompose_tag(pc, pa->pa_tag, &bus, NULL, NULL); 325 326 /* 327 * If this isn't PCI bus #0, all bets are off. 328 */ 329 if (bus != 0) 330 return (NULL); 331 332 irq = PCIIDE_COMPAT_IRQ(chan); 333 #if NSIO 334 cookie = sio_intr_establish(NULL /*XXX*/, irq, IST_EDGE, IPL_BIO, 335 func, arg); 336 #endif 337 return (cookie); 338 } 339 340 void 341 eb164_iointr(framep, vec) 342 void *framep; 343 unsigned long vec; 344 { 345 int irq; 346 347 if (vec >= 0x900) { 348 if (vec >= 0x900 + (EB164_MAX_IRQ << 4)) 349 panic("eb164_iointr: vec 0x%lx out of range\n", vec); 350 irq = (vec - 0x900) >> 4; 351 352 #ifdef EVCNT_COUNTERS 353 eb164_intr_evcnt.ev_count++; 354 #else 355 if (EB164_MAX_IRQ != INTRCNT_EB164_IRQ_LEN) 356 panic("eb164 interrupt counter sizes inconsistent"); 357 intrcnt[INTRCNT_EB164_IRQ + irq]++; 358 #endif 359 360 if (!alpha_shared_intr_dispatch(eb164_pci_intr, irq)) { 361 alpha_shared_intr_stray(eb164_pci_intr, irq, 362 "eb164 irq"); 363 if (ALPHA_SHARED_INTR_DISABLE(eb164_pci_intr, irq)) 364 eb164_intr_disable(irq); 365 } 366 return; 367 } 368 #if NSIO 369 if (vec >= 0x800) { 370 sio_iointr(framep, vec); 371 return; 372 } 373 #endif 374 panic("eb164_iointr: weird vec 0x%lx\n", vec); 375 } 376 377 #if 0 /* THIS DOES NOT WORK! see pci_eb164_intr.S. */ 378 u_int8_t eb164_intr_mask[3] = { 0xff, 0xff, 0xff }; 379 380 void 381 eb164_intr_enable(irq) 382 int irq; 383 { 384 int byte = (irq / 8), bit = (irq % 8); 385 386 #if 1 387 printf("eb164_intr_enable: enabling %d (%d:%d)\n", irq, byte, bit); 388 #endif 389 eb164_intr_mask[byte] &= ~(1 << bit); 390 391 bus_space_write_1(eb164_intrgate_iot, eb164_intrgate_ioh, byte, 392 eb164_intr_mask[byte]); 393 } 394 395 void 396 eb164_intr_disable(irq) 397 int irq; 398 { 399 int byte = (irq / 8), bit = (irq % 8); 400 401 #if 1 402 printf("eb164_intr_disable: disabling %d (%d:%d)\n", irq, byte, bit); 403 #endif 404 eb164_intr_mask[byte] |= (1 << bit); 405 406 bus_space_write_1(eb164_intrgate_iot, eb164_intrgate_ioh, byte, 407 eb164_intr_mask[byte]); 408 } 409 #endif 410