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