1 /* $NetBSD: psc.c,v 1.6 1999/06/28 01:41:13 briggs Exp $ */ 2 3 /*- 4 * Copyright (c) 1997 David Huang <khym@bga.com> 5 * 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. The name of the author may not be used to endorse or promote products 13 * derived from this software without specific prior written permission 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 */ 27 28 /* 29 * This handles registration/unregistration of PSC (Peripheral 30 * Subsystem Controller) interrupts. The PSC is used only on the 31 * Centris/Quadra 660av and the Quadra 840av. 32 */ 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 37 #include <machine/bus.h> 38 #include <machine/cpu.h> 39 #include <machine/psc.h> 40 41 static void psc_kill_dma __P((void)); 42 int psc_lev3_intr __P((void *)); 43 static void psc_lev3_noint __P((void *)); 44 int psc_lev4_intr __P((void *)); 45 static int psc_lev4_noint __P((void *)); 46 int psc_lev5_intr __P((void *)); 47 static void psc_lev5_noint __P((void *)); 48 int psc_lev6_intr __P((void *)); 49 static void psc_lev6_noint __P((void *)); 50 51 void (*psc3_ihandler) __P((void *)) = psc_lev3_noint; 52 void *psc3_iarg; 53 54 int (*psc4_itab[4]) __P((void *)) = { 55 psc_lev4_noint, /* 0 */ 56 psc_lev4_noint, /* 1 */ 57 psc_lev4_noint, /* 2 */ 58 psc_lev4_noint /* 3 */ 59 }; 60 61 void *psc4_iarg[4] = { 62 (void *)0, (void *)1, (void *)2, (void *)3 63 }; 64 65 void (*psc5_itab[2]) __P((void *)) = { 66 psc_lev5_noint, /* 0 */ 67 psc_lev5_noint /* 1 */ 68 }; 69 70 void *psc5_iarg[2] = { 71 (void *)0, (void *)1 72 }; 73 74 void (*psc6_itab[3]) __P((void *)) = { 75 psc_lev6_noint, /* 0 */ 76 psc_lev6_noint, /* 1 */ 77 psc_lev6_noint /* 2 */ 78 }; 79 80 void *psc6_iarg[3] = { 81 (void *)0, (void *)1, (void *)2 82 }; 83 84 /* 85 * Make excessively sure that all PSC DMA is shut down. 86 */ 87 void 88 psc_kill_dma() 89 { 90 int i; 91 92 for (i = 0; i < 9; i++) { 93 psc_reg2(PSC_CTLBASE + (i << 4)) = 0x8800; 94 psc_reg2(PSC_CTLBASE + (i << 4)) = 0x1000; 95 psc_reg2(PSC_CMDBASE + (i << 5)) = 0x1100; 96 psc_reg2(PSC_CMDBASE + (i << 5) + PSC_SET1) = 0x1100; 97 } 98 } 99 100 /* 101 * Setup the interrupt vectors and disable most of the PSC interrupts 102 */ 103 void 104 psc_init() 105 { 106 int s, i; 107 108 /* 109 * Only Quadra AVs have a PSC. 110 */ 111 if (current_mac_model->class == MACH_CLASSAV) { 112 s = splhigh(); 113 psc_kill_dma(); 114 intr_establish(psc_lev3_intr, NULL, 3); 115 intr_establish(psc_lev4_intr, NULL, 4); 116 intr_establish(psc_lev5_intr, NULL, 5); 117 intr_establish(psc_lev6_intr, NULL, 6); 118 for (i = 3; i < 7; i++) { 119 /* Clear any flags */ 120 psc_reg1(PSC_ISR_BASE + 0x10 * i) = 0x0F; 121 /* Clear any interrupt enable */ 122 psc_reg1(PSC_IER_BASE + 0x10 * i) = 0x0F; 123 } 124 psc_reg1(PSC_LEV4_IER) = 0x86; /* enable SCC */ 125 splx(s); 126 } 127 } 128 129 int 130 add_psc_lev3_intr(handler, arg) 131 void (*handler)(void *); 132 void *arg; 133 { 134 int s; 135 136 s = splhigh(); 137 138 psc3_ihandler = handler; 139 psc3_iarg = arg; 140 141 splx(s); 142 143 return 1; 144 } 145 146 int 147 remove_psc_lev3_intr() 148 { 149 return add_psc_lev3_intr(psc_lev3_noint, (void *)0); 150 } 151 152 int 153 psc_lev3_intr(arg) 154 void *arg; 155 { 156 u_int8_t intbits; 157 158 while ((intbits = psc_reg1(PSC_LEV3_ISR)) != psc_reg1(PSC_LEV3_ISR)) 159 ; 160 intbits &= 0x1 & psc_reg1(PSC_LEV3_IER); 161 162 if (intbits) 163 psc3_ihandler(psc3_iarg); 164 165 return 0; 166 } 167 168 static void 169 psc_lev3_noint(arg) 170 void *arg; 171 { 172 printf("psc_lev3_noint\n"); 173 } 174 175 int 176 psc_lev4_intr(arg) 177 void *arg; 178 { 179 u_int8_t intbits, bitnum; 180 u_int mask; 181 182 while ((intbits = psc_reg1(PSC_LEV4_ISR)) != psc_reg1(PSC_LEV4_ISR)) 183 ; 184 intbits &= 0xf & psc_reg1(PSC_LEV4_IER); 185 186 mask = 1; 187 bitnum = 0; 188 do { 189 if (intbits & mask) 190 psc4_itab[bitnum](psc4_iarg[bitnum]); 191 mask <<= 1; 192 } while (intbits >= mask && ++bitnum); 193 194 return 0; 195 } 196 197 int 198 add_psc_lev4_intr(dev, handler, arg) 199 int dev; 200 int (*handler)(void *); 201 void *arg; 202 { 203 int s; 204 205 if ((dev < 0) || (dev > 3)) 206 return 0; 207 208 s = splhigh(); 209 210 psc4_itab[dev] = handler; 211 psc4_iarg[dev] = arg; 212 213 splx(s); 214 215 return 1; 216 } 217 218 int 219 remove_psc_lev4_intr(dev) 220 int dev; 221 { 222 return add_psc_lev4_intr(dev, psc_lev4_noint, (void *)dev); 223 } 224 225 int 226 psc_lev4_noint(arg) 227 void *arg; 228 { 229 printf("psc_lev4_noint: device %d\n", (int)arg); 230 return 0; 231 } 232 233 int 234 psc_lev5_intr(arg) 235 void *arg; 236 { 237 u_int8_t intbits, bitnum; 238 u_int mask; 239 240 while ((intbits = psc_reg1(PSC_LEV5_ISR)) != psc_reg1(PSC_LEV5_ISR)) 241 ; 242 intbits &= 0x3 & psc_reg1(PSC_LEV5_IER); 243 244 mask = 1; 245 bitnum = 0; 246 do { 247 if (intbits & mask) 248 psc5_itab[bitnum](psc5_iarg[bitnum]); 249 mask <<= 1; 250 } while (intbits >= mask && ++bitnum); 251 252 return 0; 253 } 254 255 int 256 add_psc_lev5_intr(dev, handler, arg) 257 int dev; 258 void (*handler)(void *); 259 void *arg; 260 { 261 int s; 262 263 if ((dev < 0) || (dev > 1)) 264 return 0; 265 266 s = splhigh(); 267 268 psc5_itab[dev] = handler; 269 psc5_iarg[dev] = arg; 270 271 splx(s); 272 273 return 1; 274 } 275 276 int 277 remove_psc_lev5_intr(dev) 278 int dev; 279 { 280 return add_psc_lev5_intr(dev, psc_lev5_noint, (void *)dev); 281 } 282 283 void 284 psc_lev5_noint(arg) 285 void *arg; 286 { 287 printf("psc_lev5_noint: device %d\n", (int)arg); 288 } 289 290 int 291 psc_lev6_intr(arg) 292 void *arg; 293 { 294 u_int8_t intbits, bitnum; 295 u_int mask; 296 297 while ((intbits = psc_reg1(PSC_LEV6_ISR)) != psc_reg1(PSC_LEV6_ISR)) 298 ; 299 intbits &= 0x7 & psc_reg1(PSC_LEV6_IER); 300 301 mask = 1; 302 bitnum = 0; 303 do { 304 if (intbits & mask) 305 psc6_itab[bitnum](psc6_iarg[bitnum]); 306 mask <<= 1; 307 } while (intbits >= mask && ++bitnum); 308 309 return 0; 310 } 311 312 int 313 add_psc_lev6_intr(dev, handler, arg) 314 int dev; 315 void (*handler)(void *); 316 void *arg; 317 { 318 int s; 319 320 if ((dev < 0) || (dev > 2)) 321 return 0; 322 323 s = splhigh(); 324 325 psc6_itab[dev] = handler; 326 psc6_iarg[dev] = arg; 327 328 splx(s); 329 330 return 1; 331 } 332 333 int 334 remove_psc_lev6_intr(dev) 335 int dev; 336 { 337 return add_psc_lev6_intr(dev, psc_lev6_noint, (void *)dev); 338 } 339 340 void 341 psc_lev6_noint(arg) 342 void *arg; 343 { 344 printf("psc_lev6_noint: device %d\n", (int)arg); 345 } 346