1 /* $NetBSD: pci_1000a.c,v 1.28 2014/03/21 16:39:29 christos 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 * 21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * Copyright (c) 1995, 1996 Carnegie-Mellon University. 36 * All rights reserved. 37 * 38 * Author: Chris G. Demetriou 39 * 40 * Permission to use, copy, modify and distribute this software and 41 * its documentation is hereby granted, provided that both the copyright 42 * notice and this permission notice appear in all copies of the 43 * software, derivative works or modified versions, and any portions 44 * thereof, and that both notices appear in supporting documentation. 45 * 46 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 47 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 48 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 49 * 50 * Carnegie Mellon requests users of this software to return to 51 * 52 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 53 * School of Computer Science 54 * Carnegie Mellon University 55 * Pittsburgh PA 15213-3890 56 * 57 * any improvements or extensions that they make and grant Carnegie the 58 * rights to redistribute these changes. 59 */ 60 61 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 62 63 __KERNEL_RCSID(0, "$NetBSD: pci_1000a.c,v 1.28 2014/03/21 16:39:29 christos Exp $"); 64 65 #include <sys/types.h> 66 #include <sys/param.h> 67 #include <sys/time.h> 68 #include <sys/systm.h> 69 #include <sys/errno.h> 70 #include <sys/malloc.h> 71 #include <sys/device.h> 72 #include <sys/syslog.h> 73 74 #include <machine/autoconf.h> 75 76 #include <dev/pci/pcireg.h> 77 #include <dev/pci/pcivar.h> 78 79 #include <alpha/pci/pci_1000a.h> 80 81 #include "sio.h" 82 #if NSIO > 0 || NPCEB > 0 83 #include <alpha/pci/siovar.h> 84 #endif 85 86 #define PCI_NIRQ 32 87 #define PCI_STRAY_MAX 5 88 89 #define IMR2IRQ(bn) ((bn) - 1) 90 #define IRQ2IMR(irq) ((irq) + 1) 91 92 static bus_space_tag_t mystery_icu_iot; 93 static bus_space_handle_t mystery_icu_ioh[2]; 94 95 int dec_1000a_intr_map(const struct pci_attach_args *, 96 pci_intr_handle_t *); 97 const char *dec_1000a_intr_string(void *, pci_intr_handle_t, char *, size_t); 98 const struct evcnt *dec_1000a_intr_evcnt(void *, pci_intr_handle_t); 99 void *dec_1000a_intr_establish(void *, pci_intr_handle_t, 100 int, int (*func)(void *), void *); 101 void dec_1000a_intr_disestablish(void *, void *); 102 103 struct alpha_shared_intr *dec_1000a_pci_intr; 104 105 static void dec_1000a_iointr(void *arg, unsigned long vec); 106 static void dec_1000a_enable_intr(int irq); 107 static void dec_1000a_disable_intr(int irq); 108 static void pci_1000a_imi(void); 109 static pci_chipset_tag_t pc_tag; 110 111 void 112 pci_1000a_pickintr(void *core, bus_space_tag_t iot, bus_space_tag_t memt, pci_chipset_tag_t pc) 113 { 114 char *cp; 115 int i; 116 117 mystery_icu_iot = iot; 118 119 pc_tag = pc; 120 if (bus_space_map(iot, 0x54a, 2, 0, mystery_icu_ioh + 0) 121 || bus_space_map(iot, 0x54c, 2, 0, mystery_icu_ioh + 1)) 122 panic("pci_1000a_pickintr"); 123 pc->pc_intr_v = core; 124 pc->pc_intr_map = dec_1000a_intr_map; 125 pc->pc_intr_string = dec_1000a_intr_string; 126 pc->pc_intr_evcnt = dec_1000a_intr_evcnt; 127 pc->pc_intr_establish = dec_1000a_intr_establish; 128 pc->pc_intr_disestablish = dec_1000a_intr_disestablish; 129 130 pc->pc_pciide_compat_intr_establish = NULL; 131 132 #define PCI_1000A_IRQ_STR 8 133 dec_1000a_pci_intr = alpha_shared_intr_alloc(PCI_NIRQ, 134 PCI_1000A_IRQ_STR); 135 for (i = 0; i < PCI_NIRQ; i++) { 136 alpha_shared_intr_set_maxstrays(dec_1000a_pci_intr, i, 137 PCI_STRAY_MAX); 138 139 cp = alpha_shared_intr_string(dec_1000a_pci_intr, i); 140 snprintf(cp, PCI_1000A_IRQ_STR, "irq %d", i); 141 evcnt_attach_dynamic(alpha_shared_intr_evcnt( 142 dec_1000a_pci_intr, i), EVCNT_TYPE_INTR, NULL, 143 "dec_1000a", cp); 144 } 145 146 pci_1000a_imi(); 147 #if NSIO > 0 || NPCEB > 0 148 sio_intr_setup(pc, iot); 149 #endif 150 } 151 152 int 153 dec_1000a_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp) 154 { 155 pcitag_t bustag = pa->pa_intrtag; 156 int buspin = pa->pa_intrpin; 157 pci_chipset_tag_t pc = pa->pa_pc; 158 int imrbit, device = 0; /* XXX gcc */ 159 /* 160 * Get bit number in mystery ICU imr 161 */ 162 static const signed char imrmap[][4] = { 163 # define IRQSPLIT(o) { (o), (o)+1, (o)+16, (o)+16+1 } 164 # define IRQNONE { 0, 0, 0, 0 } 165 /* 0 */ { 1, 0, 0, 0 }, /* Noritake and Pintake */ 166 /* 1 */ IRQSPLIT(8), 167 /* 2 */ IRQSPLIT(10), 168 /* 3 */ IRQSPLIT(12), 169 /* 4 */ IRQSPLIT(14), 170 /* 5 */ { 1, 0, 0, 0 }, /* Corelle */ 171 /* 6 */ { 10, 0, 0, 0 }, /* Corelle */ 172 /* 7 */ IRQNONE, 173 /* 8 */ { 1, 0, 0, 0 }, /* isp behind ppb */ 174 /* 9 */ IRQNONE, 175 /* 10 */ IRQNONE, 176 /* 11 */ IRQSPLIT(2), 177 /* 12 */ IRQSPLIT(4), 178 /* 13 */ IRQSPLIT(6), 179 /* 14 */ IRQSPLIT(8) /* Corelle */ 180 }; 181 182 if (buspin == 0) /* No IRQ used. */ 183 return 1; 184 if (!(1 <= buspin && buspin <= 4)) 185 goto bad; 186 pci_decompose_tag(pc, bustag, NULL, &device, NULL); 187 if (0 <= device && device < sizeof imrmap / sizeof imrmap[0]) { 188 if (device == 0) 189 printf("dec_1000a_intr_map: ?! UNEXPECTED DEV 0\n"); 190 imrbit = imrmap[device][buspin - 1]; 191 if (imrbit) { 192 *ihp = IMR2IRQ(imrbit); 193 return 0; 194 } 195 } 196 bad: printf("dec_1000a_intr_map: can't map dev %d pin %d\n", device, buspin); 197 return 1; 198 } 199 200 const char * 201 dec_1000a_intr_string(void *ccv, pci_intr_handle_t ih, char *buf, size_t len) 202 { 203 static const char irqmsg_fmt[] = "dec_1000a irq %ld"; 204 205 if (ih >= PCI_NIRQ) 206 panic("%s: bogus dec_1000a IRQ 0x%lx", __func__, ih); 207 208 snprintf(buf, len, irqmsg_fmt, ih); 209 return buf; 210 } 211 212 const struct evcnt * 213 dec_1000a_intr_evcnt(void *ccv, pci_intr_handle_t ih) 214 { 215 216 if (ih >= PCI_NIRQ) 217 panic("%s: bogus dec_1000a IRQ 0x%lx", __func__, ih); 218 219 return (alpha_shared_intr_evcnt(dec_1000a_pci_intr, ih)); 220 } 221 222 void * 223 dec_1000a_intr_establish( 224 void *ccv, 225 pci_intr_handle_t ih, 226 int level, 227 int (*func)(void *), 228 void *arg) 229 { 230 void *cookie; 231 232 if (ih >= PCI_NIRQ) 233 panic("dec_1000a_intr_establish: IRQ too high, 0x%lx", ih); 234 235 cookie = alpha_shared_intr_establish(dec_1000a_pci_intr, ih, IST_LEVEL, 236 level, func, arg, "dec_1000a irq"); 237 238 if (cookie != NULL && 239 alpha_shared_intr_firstactive(dec_1000a_pci_intr, ih)) { 240 scb_set(0x900 + SCB_IDXTOVEC(ih), dec_1000a_iointr, NULL, 241 level); 242 dec_1000a_enable_intr(ih); 243 } 244 return (cookie); 245 } 246 247 void 248 dec_1000a_intr_disestablish(void *ccv, void *cookie) 249 { 250 struct alpha_shared_intrhand *ih = cookie; 251 unsigned int irq = ih->ih_num; 252 int s; 253 254 s = splhigh(); 255 256 alpha_shared_intr_disestablish(dec_1000a_pci_intr, cookie, 257 "dec_1000a irq"); 258 if (alpha_shared_intr_isactive(dec_1000a_pci_intr, irq) == 0) { 259 dec_1000a_disable_intr(irq); 260 alpha_shared_intr_set_dfltsharetype(dec_1000a_pci_intr, irq, 261 IST_NONE); 262 scb_free(0x900 + SCB_IDXTOVEC(irq)); 263 } 264 265 splx(s); 266 } 267 268 static void 269 dec_1000a_iointr(void *framep, unsigned long vec) 270 { 271 int irq; 272 273 irq = SCB_VECTOIDX(vec - 0x900); 274 275 if (!alpha_shared_intr_dispatch(dec_1000a_pci_intr, irq)) { 276 alpha_shared_intr_stray(dec_1000a_pci_intr, irq, 277 "dec_1000a irq"); 278 if (ALPHA_SHARED_INTR_DISABLE(dec_1000a_pci_intr, irq)) 279 dec_1000a_disable_intr(irq); 280 } else 281 alpha_shared_intr_reset_strays(dec_1000a_pci_intr, irq); 282 } 283 284 /* 285 * Read and write the mystery ICU IMR registers 286 */ 287 288 #define IR(h) bus_space_read_2(mystery_icu_iot, mystery_icu_ioh[h], 0) 289 #define IW(h, v) bus_space_write_2(mystery_icu_iot, mystery_icu_ioh[h], 0, (v)) 290 291 /* 292 * Enable and disable interrupts at the ICU level 293 */ 294 295 static void 296 dec_1000a_enable_intr(int irq) 297 { 298 int imrval = IRQ2IMR(irq); 299 int i = imrval >= 16; 300 301 IW(i, IR(i) | 1 << (imrval & 0xf)); 302 } 303 304 static void 305 dec_1000a_disable_intr(int irq) 306 { 307 int imrval = IRQ2IMR(irq); 308 int i = imrval >= 16; 309 310 IW(i, IR(i) & ~(1 << (imrval & 0xf))); 311 } 312 /* 313 * Initialize mystery ICU 314 */ 315 static void 316 pci_1000a_imi(void) 317 { 318 IW(0, IR(0) & 1); 319 IW(1, IR(0) & 3); 320 } 321