1 /* $NetBSD: pci_kn300.c,v 1.24 2002/05/15 16:57:42 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1998 by Matthew Jacob 5 * NASA AMES Research Center. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice immediately at the beginning of the file, without modification, 13 * this list of conditions, and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 34 35 __KERNEL_RCSID(0, "$NetBSD: pci_kn300.c,v 1.24 2002/05/15 16:57:42 thorpej Exp $"); 36 37 #include <sys/types.h> 38 #include <sys/param.h> 39 #include <sys/time.h> 40 #include <sys/systm.h> 41 #include <sys/errno.h> 42 #include <sys/malloc.h> 43 #include <sys/device.h> 44 #include <sys/syslog.h> 45 46 #include <uvm/uvm_extern.h> 47 48 #include <machine/autoconf.h> 49 50 #include <dev/pci/pcireg.h> 51 #include <dev/pci/pcivar.h> 52 53 #include <alpha/mcbus/mcbusvar.h> 54 #include <alpha/mcbus/mcbusreg.h> 55 #include <alpha/pci/mcpciareg.h> 56 #include <alpha/pci/mcpciavar.h> 57 #include <alpha/pci/pci_kn300.h> 58 59 #include "sio.h" 60 #if NSIO > 0 || NPCEB > 0 61 #include <alpha/pci/siovar.h> 62 #endif 63 64 int dec_kn300_intr_map __P((struct pci_attach_args *, 65 pci_intr_handle_t *)); 66 const char *dec_kn300_intr_string __P((void *, pci_intr_handle_t)); 67 const struct evcnt *dec_kn300_intr_evcnt __P((void *, pci_intr_handle_t)); 68 void *dec_kn300_intr_establish __P((void *, pci_intr_handle_t, 69 int, int (*func)(void *), void *)); 70 void dec_kn300_intr_disestablish __P((void *, void *)); 71 72 #define KN300_PCEB_IRQ 16 73 #define NPIN 4 74 75 #define NIRQ (MAX_MC_BUS * MCPCIA_PER_MCBUS * MCPCIA_MAXSLOT * NPIN) 76 static int savirqs[NIRQ]; 77 78 static struct alpha_shared_intr *kn300_pci_intr; 79 80 static struct mcpcia_config *mcpcia_eisaccp = NULL; 81 82 void kn300_iointr __P((void *, unsigned long)); 83 void kn300_enable_intr __P((struct mcpcia_config *, int)); 84 void kn300_disable_intr __P((struct mcpcia_config *, int)); 85 86 void 87 pci_kn300_pickintr(ccp, first) 88 struct mcpcia_config *ccp; 89 int first; 90 { 91 char *cp; 92 pci_chipset_tag_t pc = &ccp->cc_pc; 93 94 if (first) { 95 int g; 96 97 kn300_pci_intr = alpha_shared_intr_alloc(NIRQ, 16); 98 for (g = 0; g < NIRQ; g++) { 99 alpha_shared_intr_set_maxstrays(kn300_pci_intr, g, 25); 100 cp = alpha_shared_intr_string(kn300_pci_intr, g); 101 sprintf(cp, "irq %d", g); 102 evcnt_attach_dynamic(alpha_shared_intr_evcnt( 103 kn300_pci_intr, g), EVCNT_TYPE_INTR, NULL, 104 "kn300", cp); 105 savirqs[g] = (char) -1; 106 } 107 } 108 109 pc->pc_intr_v = ccp; 110 pc->pc_intr_map = dec_kn300_intr_map; 111 pc->pc_intr_string = dec_kn300_intr_string; 112 pc->pc_intr_evcnt = dec_kn300_intr_evcnt; 113 pc->pc_intr_establish = dec_kn300_intr_establish; 114 pc->pc_intr_disestablish = dec_kn300_intr_disestablish; 115 116 /* Not supported on KN300. */ 117 pc->pc_pciide_compat_intr_establish = NULL; 118 119 if (EISA_PRESENT(REGVAL(MCPCIA_PCI_REV(ccp)))) { 120 mcpcia_eisaccp = ccp; 121 #if NSIO > 0 || NPCEB > 0 122 sio_intr_setup(pc, &ccp->cc_iot); 123 kn300_enable_intr(ccp, KN300_PCEB_IRQ); 124 #endif 125 } 126 } 127 128 int 129 dec_kn300_intr_map(pa, ihp) 130 struct pci_attach_args *pa; 131 pci_intr_handle_t *ihp; 132 { 133 pcitag_t bustag = pa->pa_intrtag; 134 int buspin = pa->pa_intrpin; 135 pci_chipset_tag_t pc = pa->pa_pc; 136 struct mcpcia_config *ccp = (struct mcpcia_config *)pc->pc_intr_v; 137 int device; 138 int mcpcia_irq; 139 140 if (buspin == 0) { 141 /* No IRQ used. */ 142 return 1; 143 } 144 if (buspin > 4 || buspin < 0) { 145 printf("dec_kn300_intr_map: bad interrupt pin %d\n", buspin); 146 return 1; 147 } 148 149 pci_decompose_tag(pc, bustag, NULL, &device, NULL); 150 151 /* 152 * On MID 5 device 1 is the internal NCR 53c810. 153 */ 154 if (ccp->cc_mid == 5 && device == 1) { 155 mcpcia_irq = 16; 156 } else if (device >= 2 && device <= 5) { 157 mcpcia_irq = (device - 2) * 4; 158 } else { 159 printf("dec_kn300_intr_map: weird device number %d\n", device); 160 return(1); 161 } 162 163 /* 164 * handle layout: 165 * 166 * Determine kn300 IRQ (encoded in SCB vector): 167 * bits 0..1 buspin-1 168 * bits 2..4 PCI Slot (0..7- yes, some don't exist) 169 * bits 5..7 MID-4 170 * bits 8..10 7-GID 171 * 172 * Software only: 173 * bits 11-15 MCPCIA IRQ 174 */ 175 *ihp = (pci_intr_handle_t) 176 (buspin - 1 ) | 177 ((device & 0x7) << 2) | 178 ((ccp->cc_mid - 4) << 5) | 179 ((7 - ccp->cc_gid) << 8) | 180 (mcpcia_irq << 11); 181 return (0); 182 } 183 184 const char * 185 dec_kn300_intr_string(ccv, ih) 186 void *ccv; 187 pci_intr_handle_t ih; 188 { 189 static char irqstr[64]; 190 191 sprintf(irqstr, "kn300 irq %ld", ih & 0x3ff); 192 return (irqstr); 193 } 194 195 const struct evcnt * 196 dec_kn300_intr_evcnt(ccv, ih) 197 void *ccv; 198 pci_intr_handle_t ih; 199 { 200 201 return (alpha_shared_intr_evcnt(kn300_pci_intr, ih & 0x3ff)); 202 } 203 204 void * 205 dec_kn300_intr_establish(ccv, ih, level, func, arg) 206 void *ccv; 207 pci_intr_handle_t ih; 208 int level; 209 int (*func) __P((void *)); 210 void *arg; 211 { 212 struct mcpcia_config *ccp = ccv; 213 void *cookie; 214 int irq; 215 216 irq = ih & 0x3ff; 217 cookie = alpha_shared_intr_establish(kn300_pci_intr, irq, IST_LEVEL, 218 level, func, arg, "kn300 irq"); 219 220 if (cookie != NULL && 221 alpha_shared_intr_firstactive(kn300_pci_intr, irq)) { 222 scb_set(MCPCIA_VEC_PCI + SCB_IDXTOVEC(irq), 223 kn300_iointr, NULL); 224 alpha_shared_intr_set_private(kn300_pci_intr, irq, ccp); 225 savirqs[irq] = (ih >> 11) & 0x1f; 226 kn300_enable_intr(ccp, savirqs[irq]); 227 alpha_mb(); 228 } 229 return (cookie); 230 } 231 232 void 233 dec_kn300_intr_disestablish(ccv, cookie) 234 void *ccv, *cookie; 235 { 236 panic("dec_kn300_intr_disestablish not implemented"); 237 } 238 239 void 240 kn300_iointr(arg, vec) 241 void *arg; 242 unsigned long vec; 243 { 244 struct mcpcia_softc *mcp; 245 u_long irq; 246 247 irq = SCB_VECTOIDX(vec - MCPCIA_VEC_PCI); 248 249 if (alpha_shared_intr_dispatch(kn300_pci_intr, irq)) { 250 /* 251 * Any claim of an interrupt at this level is a hint to 252 * reset the stray interrupt count- elsewise a slow leak 253 * over time will cause this level to be shutdown. 254 */ 255 alpha_shared_intr_set_maxstrays(kn300_pci_intr, irq, 25); 256 return; 257 } 258 259 /* 260 * If we haven't finished configuring yet, or there is no mcp 261 * registered for this level yet, just return. 262 */ 263 mcp = alpha_shared_intr_get_private(kn300_pci_intr, irq); 264 if (mcp == NULL || mcp->mcpcia_cc == NULL) 265 return; 266 267 /* 268 * We're getting an interrupt for a device we haven't enabled. 269 * We had better not try and use -1 to find the right bit to disable. 270 */ 271 if (savirqs[irq] == -1) { 272 printf("kn300_iointr: stray interrupt vector 0x%lx\n", vec); 273 return; 274 } 275 276 /* 277 * Stray interrupt; disable the IRQ on the appropriate MCPCIA 278 * if we've reached the limit. 279 */ 280 alpha_shared_intr_stray(kn300_pci_intr, irq, "kn300 irq"); 281 if (ALPHA_SHARED_INTR_DISABLE(kn300_pci_intr, irq) == 0) 282 return; 283 kn300_disable_intr(mcp->mcpcia_cc, savirqs[irq]); 284 } 285 286 void 287 kn300_enable_intr(ccp, irq) 288 struct mcpcia_config *ccp; 289 int irq; 290 { 291 alpha_mb(); 292 REGVAL(MCPCIA_INT_MASK0(ccp)) |= (1 << irq); 293 alpha_mb(); 294 } 295 296 void 297 kn300_disable_intr(ccp, irq) 298 struct mcpcia_config *ccp; 299 int irq; 300 { 301 alpha_mb(); 302 REGVAL(MCPCIA_INT_MASK0(ccp)) &= ~(1 << irq); 303 alpha_mb(); 304 } 305