1 /* $NetBSD: pci_1000a.c,v 1.11 2000/06/05 21:47:22 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is based on pci_kn20aa.c, written by Chris G. Demetriou at 8 * Carnegie-Mellon University. Platform support for Noritake, Pintake, and 9 * Corelle by Ross Harvey with copyright assignment by permission of Avalon 10 * Computer Systems, Inc. 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/cdefs.h> /* RCS ID & Copyright macro defns */ 69 70 __KERNEL_RCSID(0, "$NetBSD: pci_1000a.c,v 1.11 2000/06/05 21:47:22 thorpej Exp $"); 71 72 #include <sys/types.h> 73 #include <sys/param.h> 74 #include <sys/time.h> 75 #include <sys/systm.h> 76 #include <sys/errno.h> 77 #include <sys/malloc.h> 78 #include <sys/device.h> 79 #include <sys/syslog.h> 80 81 #include <vm/vm.h> 82 83 #include <machine/autoconf.h> 84 85 #include <dev/pci/pcireg.h> 86 #include <dev/pci/pcivar.h> 87 88 #include <alpha/pci/pci_1000a.h> 89 90 #include "sio.h" 91 #if NSIO > 0 || NPCEB > 0 92 #include <alpha/pci/siovar.h> 93 #endif 94 95 #define PCI_NIRQ 32 96 #define PCI_STRAY_MAX 5 97 98 #define IMR2IRQ(bn) ((bn) - 1) 99 #define IRQ2IMR(irq) ((irq) + 1) 100 101 static bus_space_tag_t mystery_icu_iot; 102 static bus_space_handle_t mystery_icu_ioh[2]; 103 104 int dec_1000a_intr_map __P((void *, pcitag_t, int, int, 105 pci_intr_handle_t *)); 106 const char *dec_1000a_intr_string __P((void *, pci_intr_handle_t)); 107 const struct evcnt *dec_1000a_intr_evcnt __P((void *, pci_intr_handle_t)); 108 void *dec_1000a_intr_establish __P((void *, pci_intr_handle_t, 109 int, int (*func)(void *), void *)); 110 void dec_1000a_intr_disestablish __P((void *, void *)); 111 112 struct alpha_shared_intr *dec_1000a_pci_intr; 113 114 static void dec_1000a_iointr __P((void *framep, unsigned long vec)); 115 static void dec_1000a_enable_intr __P((int irq)); 116 static void dec_1000a_disable_intr __P((int irq)); 117 static void pci_1000a_imi __P((void)); 118 static pci_chipset_tag_t pc_tag; 119 120 void 121 pci_1000a_pickintr(core, iot, memt, pc) 122 void *core; 123 bus_space_tag_t iot, memt; 124 pci_chipset_tag_t pc; 125 { 126 char *cp; 127 int i; 128 129 mystery_icu_iot = iot; 130 131 pc_tag = pc; 132 if (bus_space_map(iot, 0x54a, 2, 0, mystery_icu_ioh + 0) 133 || bus_space_map(iot, 0x54c, 2, 0, mystery_icu_ioh + 1)) 134 panic("pci_1000a_pickintr"); 135 pc->pc_intr_v = core; 136 pc->pc_intr_map = dec_1000a_intr_map; 137 pc->pc_intr_string = dec_1000a_intr_string; 138 pc->pc_intr_evcnt = dec_1000a_intr_evcnt; 139 pc->pc_intr_establish = dec_1000a_intr_establish; 140 pc->pc_intr_disestablish = dec_1000a_intr_disestablish; 141 142 pc->pc_pciide_compat_intr_establish = NULL; 143 144 dec_1000a_pci_intr = alpha_shared_intr_alloc(PCI_NIRQ, 8); 145 for (i = 0; i < PCI_NIRQ; i++) { 146 alpha_shared_intr_set_maxstrays(dec_1000a_pci_intr, i, 147 PCI_STRAY_MAX); 148 149 cp = alpha_shared_intr_string(dec_1000a_pci_intr, i); 150 sprintf(cp, "irq %d", i); 151 evcnt_attach_dynamic(alpha_shared_intr_evcnt( 152 dec_1000a_pci_intr, i), EVCNT_TYPE_INTR, NULL, 153 "dec_1000a", cp); 154 } 155 156 pci_1000a_imi(); 157 #if NSIO > 0 || NPCEB > 0 158 sio_intr_setup(pc, iot); 159 #endif 160 set_iointr(dec_1000a_iointr); 161 } 162 163 int 164 dec_1000a_intr_map(ccv, bustag, buspin, line, ihp) 165 void *ccv; 166 pcitag_t bustag; 167 int buspin, line; 168 pci_intr_handle_t *ihp; 169 { 170 int imrbit, device; 171 /* 172 * Get bit number in mystery ICU imr 173 */ 174 static const signed char imrmap[][4] = { 175 # define IRQSPLIT(o) { (o), (o)+1, (o)+16, (o)+16+1 } 176 # define IRQNONE { 0, 0, 0, 0 } 177 /* 0 */ { 1, 0, 0, 0 }, /* Noritake and Pintake */ 178 /* 1 */ IRQSPLIT(8), 179 /* 2 */ IRQSPLIT(10), 180 /* 3 */ IRQSPLIT(12), 181 /* 4 */ IRQSPLIT(14), 182 /* 5 */ { 1, 0, 0, 0 }, /* Corelle */ 183 /* 6 */ { 10, 0, 0, 0 }, /* Corelle */ 184 /* 7 */ IRQNONE, 185 /* 8 */ { 1, 0, 0, 0 }, /* isp behind ppb */ 186 /* 9 */ IRQNONE, 187 /* 10 */ IRQNONE, 188 /* 11 */ IRQSPLIT(2), 189 /* 12 */ IRQSPLIT(4), 190 /* 13 */ IRQSPLIT(6), 191 /* 14 */ IRQSPLIT(8) /* Corelle */ 192 }; 193 194 if (buspin == 0) /* No IRQ used. */ 195 return 1; 196 if (!(1 <= buspin && buspin <= 4)) 197 goto bad; 198 alpha_pci_decompose_tag(pc_tag, bustag, NULL, &device, NULL); 199 if (0 <= device && device < sizeof imrmap / sizeof imrmap[0]) { 200 if (device == 0) 201 printf("dec_1000a_intr_map: ?! UNEXPECTED DEV 0\n"); 202 imrbit = imrmap[device][buspin - 1]; 203 if (imrbit) { 204 *ihp = IMR2IRQ(imrbit); 205 return 0; 206 } 207 } 208 bad: printf("dec_1000a_intr_map: can't map dev %d pin %d\n", device, buspin); 209 return 1; 210 } 211 212 const char * 213 dec_1000a_intr_string(ccv, ih) 214 void *ccv; 215 pci_intr_handle_t ih; 216 { 217 static const char irqmsg_fmt[] = "dec_1000a irq %ld"; 218 static char irqstr[sizeof irqmsg_fmt]; 219 220 221 if (ih >= PCI_NIRQ) 222 panic("dec_1000a_intr_string: bogus dec_1000a IRQ 0x%lx\n", ih); 223 224 snprintf(irqstr, sizeof irqstr, irqmsg_fmt, ih); 225 return (irqstr); 226 } 227 228 const struct evcnt * 229 dec_1000a_intr_evcnt(ccv, ih) 230 void *ccv; 231 pci_intr_handle_t ih; 232 { 233 234 if (ih >= PCI_NIRQ) 235 panic("dec_1000a_intr_evcnt: bogus dec_1000a IRQ 0x%lx\n", ih); 236 237 return (alpha_shared_intr_evcnt(dec_1000a_pci_intr, ih)); 238 } 239 240 void * 241 dec_1000a_intr_establish(ccv, ih, level, func, arg) 242 void *ccv, *arg; 243 pci_intr_handle_t ih; 244 int level; 245 int (*func) __P((void *)); 246 { 247 void *cookie; 248 249 if (ih >= PCI_NIRQ) 250 panic("dec_1000a_intr_establish: IRQ too high, 0x%lx\n", ih); 251 252 cookie = alpha_shared_intr_establish(dec_1000a_pci_intr, ih, IST_LEVEL, 253 level, func, arg, "dec_1000a irq"); 254 255 if (cookie != NULL && 256 alpha_shared_intr_isactive(dec_1000a_pci_intr, ih)) 257 dec_1000a_enable_intr(ih); 258 return (cookie); 259 } 260 261 void 262 dec_1000a_intr_disestablish(ccv, cookie) 263 void *ccv, *cookie; 264 { 265 struct alpha_shared_intrhand *ih = cookie; 266 unsigned int irq = ih->ih_num; 267 int s; 268 269 s = splhigh(); 270 271 alpha_shared_intr_disestablish(dec_1000a_pci_intr, cookie, 272 "dec_1000a irq"); 273 if (alpha_shared_intr_isactive(dec_1000a_pci_intr, irq) == 0) { 274 dec_1000a_disable_intr(irq); 275 alpha_shared_intr_set_dfltsharetype(dec_1000a_pci_intr, irq, 276 IST_NONE); 277 } 278 279 splx(s); 280 } 281 282 static void 283 dec_1000a_iointr(framep, vec) 284 void *framep; 285 unsigned long vec; 286 { 287 int irq; 288 289 if (vec >= 0x900) { 290 if (vec >= 0x900 + (PCI_NIRQ << 4)) 291 panic("dec_1000a_iointr: vec 0x%lx out of range\n", 292 vec); 293 irq = (vec - 0x900) >> 4; 294 if (!alpha_shared_intr_dispatch(dec_1000a_pci_intr, irq)) { 295 alpha_shared_intr_stray(dec_1000a_pci_intr, irq, 296 "dec_1000a irq"); 297 if (ALPHA_SHARED_INTR_DISABLE(dec_1000a_pci_intr, irq)) 298 dec_1000a_disable_intr(irq); 299 } 300 return; 301 } 302 #if NSIO > 0 || NPCEB > 0 303 if (vec >= 0x800) { 304 sio_iointr(framep, vec); 305 return; 306 } 307 #endif 308 panic("dec_1000a_iointr: weird vec 0x%lx\n", vec); 309 } 310 311 /* 312 * Read and write the mystery ICU IMR registers 313 */ 314 315 #define IR(h) bus_space_read_2(mystery_icu_iot, mystery_icu_ioh[h], 0) 316 #define IW(h, v) bus_space_write_2(mystery_icu_iot, mystery_icu_ioh[h], 0, (v)) 317 318 /* 319 * Enable and disable interrupts at the ICU level 320 */ 321 322 static void 323 dec_1000a_enable_intr(irq) 324 int irq; 325 { 326 int imrval = IRQ2IMR(irq); 327 int i = imrval >= 16; 328 329 IW(i, IR(i) | 1 << (imrval & 0xf)); 330 } 331 332 static void 333 dec_1000a_disable_intr(irq) 334 int irq; 335 { 336 int imrval = IRQ2IMR(irq); 337 int i = imrval >= 16; 338 339 IW(i, IR(i) & ~(1 << (imrval & 0xf))); 340 } 341 /* 342 * Initialize mystery ICU 343 */ 344 static void 345 pci_1000a_imi() 346 { 347 IW(0, IR(0) & 1); 348 IW(1, IR(0) & 3); 349 } 350