1 /* $OpenBSD: pci_1000a.c,v 1.12 2009/09/30 20:16:30 miod Exp $ */ 2 /* $NetBSD: pci_1000a.c,v 1.14 2001/07/27 00:25:20 thorpej Exp $ */ 3 4 /* 5 * Copyright (c) 1998 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is based on pci_kn20aa.c, written by Chris G. Demetriou at 9 * Carnegie-Mellon University. Platform support for Noritake, Pintake, and 10 * Corelle by Ross Harvey with copyright assignment by permission of Avalon 11 * Computer Systems, Inc. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 * POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 /* 36 * Copyright (c) 1995, 1996 Carnegie-Mellon University. 37 * All rights reserved. 38 * 39 * Author: Chris G. Demetriou 40 * 41 * Permission to use, copy, modify and distribute this software and 42 * its documentation is hereby granted, provided that both the copyright 43 * notice and this permission notice appear in all copies of the 44 * software, derivative works or modified versions, and any portions 45 * thereof, and that both notices appear in supporting documentation. 46 * 47 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 48 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 49 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 50 * 51 * Carnegie Mellon requests users of this software to return to 52 * 53 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 54 * School of Computer Science 55 * Carnegie Mellon University 56 * Pittsburgh PA 15213-3890 57 * 58 * any improvements or extensions that they make and grant Carnegie the 59 * rights to redistribute these changes. 60 */ 61 62 #include <sys/types.h> 63 #include <sys/param.h> 64 #include <sys/time.h> 65 #include <sys/systm.h> 66 #include <sys/errno.h> 67 #include <sys/malloc.h> 68 #include <sys/device.h> 69 70 #include <uvm/uvm_extern.h> 71 72 #include <machine/autoconf.h> 73 74 #include <dev/pci/pcireg.h> 75 #include <dev/pci/pcivar.h> 76 #include <dev/pci/ppbreg.h> 77 78 #include <alpha/pci/pci_1000a.h> 79 80 #include "sio.h" 81 #if NSIO > 0 || NPCEB > 0 82 #include <alpha/pci/siovar.h> 83 #endif 84 85 #define PCI_NIRQ 32 86 #define PCI_STRAY_MAX 5 87 88 #define IMR2IRQ(bn) ((bn) - 1) 89 #define IRQ2IMR(irq) ((irq) + 1) 90 91 static bus_space_tag_t mystery_icu_iot; 92 static bus_space_handle_t mystery_icu_ioh[2]; 93 94 int dec_1000a_intr_map(struct pci_attach_args *, pci_intr_handle_t *); 95 const char *dec_1000a_intr_string(void *, pci_intr_handle_t); 96 int dec_1000a_intr_line(void *, pci_intr_handle_t); 97 void *dec_1000a_intr_establish(void *, pci_intr_handle_t, 98 int, int (*func)(void *), void *, const char *); 99 void dec_1000a_intr_disestablish(void *, void *); 100 101 struct alpha_shared_intr *dec_1000a_pci_intr; 102 103 void dec_1000a_iointr(void *arg, unsigned long vec); 104 void dec_1000a_enable_intr(int irq); 105 void dec_1000a_disable_intr(int irq); 106 void pci_1000a_imi(void); 107 108 void 109 pci_1000a_pickintr(core, iot, memt, pc) 110 void *core; 111 bus_space_tag_t iot, memt; 112 pci_chipset_tag_t pc; 113 { 114 int i; 115 116 mystery_icu_iot = iot; 117 118 if (bus_space_map(iot, 0x54a, 2, 0, mystery_icu_ioh + 0) 119 || bus_space_map(iot, 0x54c, 2, 0, mystery_icu_ioh + 1)) 120 panic("pci_1000a_pickintr"); 121 pc->pc_intr_v = core; 122 pc->pc_intr_map = dec_1000a_intr_map; 123 pc->pc_intr_string = dec_1000a_intr_string; 124 pc->pc_intr_line = dec_1000a_intr_line; 125 pc->pc_intr_establish = dec_1000a_intr_establish; 126 pc->pc_intr_disestablish = dec_1000a_intr_disestablish; 127 128 pc->pc_pciide_compat_intr_establish = NULL; 129 pc->pc_pciide_compat_intr_disestablish = NULL; 130 131 dec_1000a_pci_intr = alpha_shared_intr_alloc(PCI_NIRQ); 132 for (i = 0; i < PCI_NIRQ; i++) { 133 alpha_shared_intr_set_maxstrays(dec_1000a_pci_intr, i, 134 PCI_STRAY_MAX); 135 } 136 137 pci_1000a_imi(); 138 #if NSIO > 0 || NPCEB > 0 139 sio_intr_setup(pc, iot); 140 #endif 141 } 142 143 int 144 dec_1000a_intr_map(pa, ihp) 145 struct pci_attach_args *pa; 146 pci_intr_handle_t *ihp; 147 { 148 pcitag_t bustag = pa->pa_intrtag; 149 int buspin = pa->pa_intrpin, line = pa->pa_intrline; 150 int imrbit = 0, bus, device; 151 /* 152 * Get bit number in mystery ICU imr 153 */ 154 static const signed char imrmap[][4] = { 155 # define IRQSPLIT(o) { (o), (o)+1, (o)+16, (o)+16+1 } 156 # define IRQNONE { 0, 0, 0, 0 } 157 /* 0 */ { 1, 0, 0, 0 }, /* Noritake and Pintake */ 158 /* 1 */ IRQSPLIT(8), 159 /* 2 */ IRQSPLIT(10), 160 /* 3 */ IRQSPLIT(12), 161 /* 4 */ IRQSPLIT(14), 162 /* 5 */ { 1, 0, 0, 0 }, /* Corelle */ 163 /* 6 */ { 10, 0, 0, 0 }, /* Corelle */ 164 /* 7 */ IRQNONE, 165 /* 8 */ IRQNONE, /* see imrmap2[] below */ 166 /* 9 */ IRQNONE, 167 /* 10 */ IRQNONE, 168 /* 11 */ IRQSPLIT(2), 169 /* 12 */ IRQSPLIT(4), 170 /* 13 */ IRQSPLIT(6), 171 /* 14 */ IRQSPLIT(8) /* Corelle */ 172 }, imrmap2[][4] = { 173 /* 0 */ { 1, 0, 0, 0 }, /* isp */ 174 /* 1 */ IRQSPLIT(8), 175 /* 2 */ IRQSPLIT(10), 176 /* 3 */ IRQSPLIT(12), 177 /* 4 */ IRQSPLIT(14) 178 }; 179 180 if (buspin == 0) /* No IRQ used. */ 181 return 1; 182 if (!(1 <= buspin && buspin <= 4)) 183 goto bad; 184 185 pci_decompose_tag(pa->pa_pc, bustag, &bus, &device, NULL); 186 187 /* 188 * The console places the interrupt mapping in the "line" value. 189 * We trust it whenever possible. 190 */ 191 if (line >= 0 && line < PCI_NIRQ) { 192 imrbit = line + 1; 193 } else { 194 if (pa->pa_bridgetag) { 195 buspin = pa->pa_rawintrpin; 196 bus = pa->pa_bus; 197 device = pa->pa_device; 198 199 if (bus == 2) { 200 /* 201 * Devices behind ppb1 (pci bus #2). 202 * Those use fixed per-slot assignments. 203 */ 204 if (0 <= device && device < 205 sizeof imrmap2 / sizeof imrmap2[0]) { 206 imrbit = imrmap2[device][buspin - 1]; 207 } 208 } else { 209 /* 210 * Devices behind further ppb. 211 * Those reuse ppb configured interrupts. 212 */ 213 buspin = PPB_INTERRUPT_SWIZZLE(buspin, device); 214 if (pa->pa_bridgeih[buspin - 1] != 0) { 215 imrbit = 216 IRQ2IMR(pa->pa_bridgeih[buspin - 1]); 217 } 218 } 219 } else { 220 if (0 <= device && 221 device < sizeof imrmap / sizeof imrmap[0]) 222 imrbit = imrmap[device][buspin - 1]; 223 } 224 } 225 226 if (imrbit) { 227 *ihp = IMR2IRQ(imrbit); 228 return 0; 229 } 230 bad: 231 return 1; 232 } 233 234 const char * 235 dec_1000a_intr_string(ccv, ih) 236 void *ccv; 237 pci_intr_handle_t ih; 238 { 239 static const char irqmsg_fmt[] = "dec_1000a irq %ld"; 240 static char irqstr[sizeof irqmsg_fmt]; 241 242 243 if (ih >= PCI_NIRQ) 244 panic("dec_1000a_intr_string: bogus dec_1000a IRQ 0x%lx", ih); 245 246 snprintf(irqstr, sizeof irqstr, irqmsg_fmt, ih); 247 return (irqstr); 248 } 249 250 int 251 dec_1000a_intr_line(ccv, ih) 252 void *ccv; 253 pci_intr_handle_t ih; 254 { 255 #if NSIO > 0 256 return sio_intr_line(NULL /*XXX*/, ih); 257 #else 258 return (ih); 259 #endif 260 } 261 262 void * 263 dec_1000a_intr_establish(ccv, ih, level, func, arg, name) 264 void *ccv; 265 pci_intr_handle_t ih; 266 int level; 267 int (*func)(void *); 268 void *arg; 269 const char *name; 270 { 271 void *cookie; 272 273 if (ih >= PCI_NIRQ) 274 panic("dec_1000a_intr_establish: IRQ too high, 0x%lx", ih); 275 276 cookie = alpha_shared_intr_establish(dec_1000a_pci_intr, ih, IST_LEVEL, 277 level, func, arg, name); 278 279 if (cookie != NULL && 280 alpha_shared_intr_firstactive(dec_1000a_pci_intr, ih)) { 281 scb_set(0x900 + SCB_IDXTOVEC(ih), dec_1000a_iointr, NULL); 282 dec_1000a_enable_intr(ih); 283 284 } 285 return (cookie); 286 } 287 288 void 289 dec_1000a_intr_disestablish(ccv, cookie) 290 void *ccv, *cookie; 291 { 292 struct alpha_shared_intrhand *ih = cookie; 293 unsigned int irq = ih->ih_num; 294 int s; 295 296 s = splhigh(); 297 298 alpha_shared_intr_disestablish(dec_1000a_pci_intr, cookie); 299 if (alpha_shared_intr_isactive(dec_1000a_pci_intr, irq) == 0) { 300 dec_1000a_disable_intr(irq); 301 alpha_shared_intr_set_dfltsharetype(dec_1000a_pci_intr, irq, 302 IST_NONE); 303 scb_free(0x900 + SCB_IDXTOVEC(irq)); 304 } 305 306 splx(s); 307 } 308 309 void 310 dec_1000a_iointr(framep, vec) 311 void *framep; 312 unsigned long vec; 313 { 314 int irq; 315 316 irq = SCB_VECTOIDX(vec - 0x900); 317 318 if (!alpha_shared_intr_dispatch(dec_1000a_pci_intr, irq)) { 319 alpha_shared_intr_stray(dec_1000a_pci_intr, irq, 320 "dec_1000a irq"); 321 if (ALPHA_SHARED_INTR_DISABLE(dec_1000a_pci_intr, irq)) 322 dec_1000a_disable_intr(irq); 323 } else 324 alpha_shared_intr_reset_strays(dec_1000a_pci_intr, irq); 325 } 326 327 /* 328 * Read and write the mystery ICU IMR registers 329 */ 330 331 #define IR(h) bus_space_read_2(mystery_icu_iot, mystery_icu_ioh[h], 0) 332 #define IW(h, v) bus_space_write_2(mystery_icu_iot, mystery_icu_ioh[h], 0, (v)) 333 334 /* 335 * Enable and disable interrupts at the ICU level 336 */ 337 338 void 339 dec_1000a_enable_intr(irq) 340 int irq; 341 { 342 int imrval = IRQ2IMR(irq); 343 int i = imrval >= 16; 344 345 IW(i, IR(i) | 1 << (imrval & 0xf)); 346 } 347 348 void 349 dec_1000a_disable_intr(irq) 350 int irq; 351 { 352 int imrval = IRQ2IMR(irq); 353 int i = imrval >= 16; 354 355 IW(i, IR(i) & ~(1 << (imrval & 0xf))); 356 } 357 /* 358 * Initialize mystery ICU 359 */ 360 void 361 pci_1000a_imi() 362 { 363 IW(0, IR(0) & 1); 364 IW(1, IR(0) & 3); 365 } 366