1 /* $OpenBSD: pci_6600.c,v 1.2 2001/01/20 20:46:46 art Exp $ */ 2 /* $NetBSD: pci_6600.c,v 1.5 2000/06/06 00:50:15 thorpej Exp $ */ 3 4 /*- 5 * Copyright (c) 1999 by Ross Harvey. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Ross Harvey. 18 * 4. The name of Ross Harvey may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY ROSS HARVEY ``AS IS'' AND ANY EXPRESS 22 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURP0SE 24 * ARE DISCLAIMED. IN NO EVENT SHALL ROSS HARVEY BE LIABLE FOR ANY 25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 */ 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/kernel.h> 38 #include <sys/device.h> 39 #include <sys/malloc.h> 40 41 #include <vm/vm.h> 42 #include <uvm/uvm.h> 43 44 #include <machine/autoconf.h> 45 #define _ALPHA_BUS_DMA_PRIVATE 46 #include <machine/bus.h> 47 #include <machine/rpb.h> 48 49 #include <dev/pci/pcireg.h> 50 #include <dev/pci/pcivar.h> 51 #include <dev/pci/pciidereg.h> 52 #include <dev/pci/pciidevar.h> 53 54 #include <alpha/pci/tsreg.h> 55 #include <alpha/pci/tsvar.h> 56 #include <alpha/pci/pci_6600.h> 57 58 #define pci_6600() { Generate ctags(1) key. } 59 60 #include "sio.h" 61 #if NSIO 62 #include <alpha/pci/siovar.h> 63 #endif 64 65 #define PCI_NIRQ 64 66 #define PCI_STRAY_MAX 5 67 68 /* 69 * Some Tsunami models have a PCI device (the USB controller) with interrupts 70 * tied to ISA IRQ lines. The IRQ is encoded as: 71 * 72 * line = 0xe0 | isa_irq; 73 */ 74 #define DEC_6600_LINE_IS_ISA(line) ((line) >= 0xe0 && (line) <= 0xef) 75 #define DEC_6600_LINE_ISA_IRQ(line) ((line) & 0x0f) 76 77 static char *irqtype = "6600 irq"; 78 static struct tsp_config *sioprimary; 79 80 void dec_6600_intr_disestablish __P((void *, void *)); 81 void *dec_6600_intr_establish __P(( 82 void *, pci_intr_handle_t, int, int (*func)(void *), void *, char *)); 83 const char *dec_6600_intr_string __P((void *, pci_intr_handle_t)); 84 const struct evcnt *dec_6600_intr_evcnt __P((void *, pci_intr_handle_t)); 85 int dec_6600_intr_map __P((void *, pcitag_t, int, int, pci_intr_handle_t *)); 86 void *dec_6600_pciide_compat_intr_establish __P((void *, struct device *, 87 struct pci_attach_args *, int, int (*)(void *), void *)); 88 89 struct alpha_shared_intr *dec_6600_pci_intr; 90 91 void dec_6600_iointr __P((void *framep, unsigned long vec)); 92 extern void dec_6600_intr_enable __P((int irq)); 93 extern void dec_6600_intr_disable __P((int irq)); 94 95 void 96 pci_6600_pickintr(pcp) 97 struct tsp_config *pcp; 98 { 99 bus_space_tag_t iot = pcp->pc_iot; 100 pci_chipset_tag_t pc = &pcp->pc_pc; 101 #if 0 102 char *cp; 103 #endif 104 int i; 105 106 pc->pc_intr_v = pcp; 107 pc->pc_intr_map = dec_6600_intr_map; 108 pc->pc_intr_string = dec_6600_intr_string; 109 #if 0 110 pc->pc_intr_evcnt = dec_6600_intr_evcnt; 111 #endif 112 pc->pc_intr_establish = dec_6600_intr_establish; 113 pc->pc_intr_disestablish = dec_6600_intr_disestablish; 114 pc->pc_pciide_compat_intr_establish = NULL; 115 116 /* 117 * System-wide and Pchip-0-only logic... 118 */ 119 if (dec_6600_pci_intr == NULL) { 120 sioprimary = pcp; 121 pc->pc_pciide_compat_intr_establish = 122 dec_6600_pciide_compat_intr_establish; 123 dec_6600_pci_intr = alpha_shared_intr_alloc(PCI_NIRQ); 124 for (i = 0; i < PCI_NIRQ; i++) { 125 alpha_shared_intr_set_maxstrays(dec_6600_pci_intr, i, 126 PCI_STRAY_MAX); 127 alpha_shared_intr_set_private(dec_6600_pci_intr, i, 128 sioprimary); 129 130 #if 0 131 cp = alpha_shared_intr_string(dec_6600_pci_intr); 132 sprintf(cp, "irq %d", i); 133 evcnt_attach_dynamic(alpha_shared_intr_evcnt( 134 dec_6600_pci_intr, 1), EVCNT_TYPE_INTR, NULL, 135 "dec_6600", cp); 136 #endif 137 } 138 #if NSIO 139 sio_intr_setup(pc, iot); 140 dec_6600_intr_enable(55); /* irq line for sio */ 141 #endif 142 set_iointr(dec_6600_iointr); 143 } 144 } 145 146 int 147 dec_6600_intr_map(acv, bustag, buspin, line, ihp) 148 void *acv; 149 pcitag_t bustag; 150 int buspin, line; 151 pci_intr_handle_t *ihp; 152 { 153 struct tsp_config *pcp = acv; 154 pci_chipset_tag_t pc = &pcp->pc_pc; 155 int bus, device, function; 156 157 if (buspin == 0) { 158 /* No IRQ used. */ 159 return 1; 160 } 161 if (buspin > 4) { 162 printf("intr_map: bad interrupt pin %d\n", buspin); 163 return 1; 164 } 165 166 alpha_pci_decompose_tag(pc, bustag, &bus, &device, &function); 167 168 /* 169 * The console places the interrupt mapping in the "line" value. 170 * A value of (char)-1 indicates there is no mapping. 171 */ 172 if (line == 0xff) { 173 printf("dec_6600_intr_map: no mapping for %d/%d/%d\n", 174 bus, device, function); 175 return (1); 176 } 177 178 #if NSIO == 0 179 if (DEC_6600_LINE_IS_ISA(line)) { 180 printf("dec_6600_intr_map: ISA IRQ %d for %d/%d/%d\n", 181 DEC_6600_LINE_ISA_IRQ(line), bus, device, function); 182 return (1); 183 } 184 #endif 185 186 if (DEC_6600_LINE_IS_ISA(line) == 0 && line >= PCI_NIRQ) 187 panic("dec_6600_intr_map: dec 6600 irq too large (%d)\n", 188 line); 189 190 *ihp = line; 191 return (0); 192 } 193 194 const char * 195 dec_6600_intr_string(acv, ih) 196 void *acv; 197 pci_intr_handle_t ih; 198 { 199 200 static const char irqfmt[] = "dec 6600 irq %ld"; 201 static char irqstr[sizeof irqfmt]; 202 203 #if NSIO 204 if (DEC_6600_LINE_IS_ISA(ih)) 205 return (sio_intr_string(NULL /*XXX*/, 206 DEC_6600_LINE_ISA_IRQ(ih))); 207 #endif 208 209 snprintf(irqstr, sizeof irqstr, irqfmt, ih); 210 return (irqstr); 211 } 212 213 #if 0 214 const struct evcnt * 215 dec_6600_intr_evcnt(acv, ih) 216 void *acv; 217 pci_intr_handle_t ih; 218 { 219 220 #if NSIO 221 if (DEC_6600_LINE_IS_ISA(ih)) 222 return (sio_intr_evcnt(NULL /*XXX*/, 223 DEC_6600_LINE_ISA_IRQ(ih))); 224 #endif 225 226 return (alpha_shared_intr_evcnt(dec_6600_pci_intr, ih)); 227 } 228 #endif 229 230 void * 231 dec_6600_intr_establish(acv, ih, level, func, arg, name) 232 void *acv, *arg; 233 pci_intr_handle_t ih; 234 int level; 235 int (*func) __P((void *)); 236 char *name; 237 { 238 void *cookie; 239 240 #if NSIO 241 if (DEC_6600_LINE_IS_ISA(ih)) 242 return (sio_intr_establish(NULL /*XXX*/, 243 DEC_6600_LINE_ISA_IRQ(ih), IST_LEVEL, level, func, arg, 244 name)); 245 #endif 246 247 if (ih >= PCI_NIRQ) 248 panic("dec_6600_intr_establish: bogus dec 6600 IRQ 0x%lx\n", 249 ih); 250 251 cookie = alpha_shared_intr_establish(dec_6600_pci_intr, ih, IST_LEVEL, 252 level, func, arg, name); 253 254 if (cookie != NULL && alpha_shared_intr_isactive(dec_6600_pci_intr, ih)) 255 dec_6600_intr_enable(ih); 256 return (cookie); 257 } 258 259 void 260 dec_6600_intr_disestablish(acv, cookie) 261 void *acv, *cookie; 262 { 263 struct alpha_shared_intrhand *ih = cookie; 264 unsigned int irq = ih->ih_num; 265 int s; 266 267 #if NSIO 268 /* 269 * We have to determine if this is an ISA IRQ or not! We do this 270 * by checking to see if the intrhand points back to an intrhead 271 * that points to the sioprimary TSP. If not, it's an ISA IRQ. 272 * Pretty disgusting, eh? 273 */ 274 if (ih->ih_intrhead->intr_private != sioprimary) { 275 sio_intr_disestablish(NULL /*XXX*/, cookie); 276 return; 277 } 278 #endif 279 280 s = splhigh(); 281 282 alpha_shared_intr_disestablish(dec_6600_pci_intr, cookie, irqtype); 283 if (alpha_shared_intr_isactive(dec_6600_pci_intr, irq) == 0) { 284 dec_6600_intr_disable(irq); 285 alpha_shared_intr_set_dfltsharetype(dec_6600_pci_intr, irq, 286 IST_NONE); 287 } 288 289 splx(s); 290 } 291 292 void 293 dec_6600_iointr(framep, vec) 294 void *framep; 295 unsigned long vec; 296 { 297 int irq; 298 299 if (vec >= 0x900) { 300 irq = (vec - 0x900) >> 4; 301 302 if (irq >= PCI_NIRQ) 303 panic("iointr: irq %d is too high", irq); 304 305 if (!alpha_shared_intr_dispatch(dec_6600_pci_intr, irq)) { 306 alpha_shared_intr_stray(dec_6600_pci_intr, irq, 307 irqtype); 308 if (ALPHA_SHARED_INTR_DISABLE(dec_6600_pci_intr, irq)) 309 dec_6600_intr_disable(irq); 310 } 311 return; 312 } 313 #if NSIO 314 if (vec >= 0x800) { 315 sio_iointr(framep, vec); 316 return; 317 } 318 #endif 319 panic("iointr: weird vec 0x%lx\n", vec); 320 } 321 322 void 323 dec_6600_intr_enable(irq) 324 int irq; 325 { 326 alpha_mb(); 327 STQP(TS_C_DIM0) |= 1UL << irq; 328 alpha_mb(); 329 } 330 331 void 332 dec_6600_intr_disable(irq) 333 int irq; 334 { 335 alpha_mb(); 336 STQP(TS_C_DIM0) &= ~(1UL << irq); 337 alpha_mb(); 338 } 339 340 void * 341 dec_6600_pciide_compat_intr_establish(v, dev, pa, chan, func, arg) 342 void *v; 343 struct device *dev; 344 struct pci_attach_args *pa; 345 int chan; 346 int (*func) __P((void *)); 347 void *arg; 348 { 349 pci_chipset_tag_t pc = pa->pa_pc; 350 void *cookie = NULL; 351 int bus, irq; 352 353 alpha_pci_decompose_tag(pc, pa->pa_tag, &bus, NULL, NULL); 354 355 /* 356 * If this isn't PCI bus #0 on the TSP that holds the PCI-ISA 357 * bridge, all bets are off. 358 */ 359 if (bus != 0 || pc->pc_intr_v != sioprimary) 360 return (NULL); 361 362 irq = PCIIDE_COMPAT_IRQ(chan); 363 #if NSIO 364 cookie = sio_intr_establish(NULL /*XXX*/, irq, IST_EDGE, IPL_BIO, 365 func, arg, "dec 6600 irq"); 366 367 if (cookie == NULL) 368 return (NULL); 369 #endif 370 return (cookie); 371 } 372