1 /* $NetBSD: tx39icu.c,v 1.13 2001/09/18 17:37:28 uch Exp $ */ 2 3 /*- 4 * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include "opt_tx39_debug.h" 40 #include "opt_use_poll.h" 41 #include "opt_tx39icudebug.h" 42 #include "opt_tx39_watchdogtimer.h" 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/device.h> 47 #include <sys/malloc.h> 48 #include <sys/queue.h> 49 50 #include <mips/cpuregs.h> 51 #include <machine/bus.h> 52 53 #include <hpcmips/tx/tx39var.h> 54 #include <hpcmips/tx/tx39icureg.h> 55 #include <hpcmips/tx/tx39clockvar.h> 56 57 #include <machine/cpu.h> 58 #include <dev/dec/clockvar.h> 59 60 #undef TX39ICUDEBUG_PRINT_PENDING_INTERRUPT /* For explorer. good luck! */ 61 62 #ifdef TX39ICUDEBUG 63 #define DPRINTF(arg) printf arg 64 #else 65 #define DPRINTF(arg) 66 #endif 67 u_int32_t tx39intrvec; 68 69 /* IRQHIGH lines list */ 70 static const struct irqhigh_list { 71 int qh_pri; /* IRQHIGH priority */ 72 int qh_set; /* Register set */ 73 int qh_bit; /* bit offset in the register set */ 74 } irqhigh_list[] = { 75 {15, 5, 25}, /* POSPWROKINT */ 76 {15, 5, 24}, /* NEGPWROKINT */ 77 {14, 5, 30}, /* ALARMINT*/ 78 {13, 5, 29}, /* PERINT */ 79 #ifdef TX391X 80 {12, 2, 3}, /* MBUSPOSINT */ 81 {12, 2, 2}, /* MBUSNEGINT */ 82 {11, 2, 31}, /* UARTARXINT */ 83 {10, 2, 21}, /* UARTBRXINT */ 84 {9, 3, 19}, /* MFIOPOSINT19 */ 85 {9, 3, 18}, /* MFIOPOSINT18 */ 86 {9, 3, 17}, /* MFIOPOSINT17 */ 87 {9, 3, 16}, /* MFIOPOSINT16 */ 88 {8, 3, 1}, /* MFIOPOSINT1 */ 89 {8, 3, 0}, /* MFIOPOSINT0 */ 90 {8, 5, 13}, /* IOPOSINT6 */ 91 {8, 5, 12}, /* IOPOSINT5 */ 92 {7, 4, 19}, /* MFIONEGINT19 */ 93 {7, 4, 18}, /* MFIONEGINT18 */ 94 {7, 4, 17}, /* MFIONEGINT17 */ 95 {7, 4, 16}, /* MFIONEGINT16 */ 96 {6, 4, 1}, /* MFIONEGINT1 */ 97 {6, 4, 0}, /* MFIONEGINT0 */ 98 {6, 5, 6}, /* IONEGINT6 */ 99 {6, 5, 5}, /* IONEGINT5 */ 100 {5, 2, 5}, /* MBUSDMAFULLINT */ 101 #endif /* TX391X */ 102 #ifdef TX392X 103 {12, 2, 31}, /* UARTARXINT */ 104 {12, 2, 21}, /* UARTBRXINT */ 105 {11, 3, 19}, /* MFIOPOSINT19 */ 106 {11, 3, 18}, /* MFIOPOSINT18 */ 107 {11, 3, 17}, /* MFIOPOSINT17 */ 108 {11, 3, 16}, /* MFIOPOSINT16 */ 109 {10, 3, 1}, /* MFIOPOSINT1 */ 110 {10, 3, 0}, /* MFIOPOSINT0 */ 111 {10, 5, 13}, /* IOPOSINT6 */ 112 {10, 5, 12}, /* IOPOSINT5 */ 113 {9, 4, 19}, /* MFIONEGINT19 */ 114 {9, 4, 18}, /* MFIONEGINT18 */ 115 {9, 4, 17}, /* MFIONEGINT17 */ 116 {9, 4, 16}, /* MFIONEGINT16 */ 117 {8, 4, 1}, /* MFIONEGINT1 */ 118 {8, 4, 0}, /* MFIONEGINT0 */ 119 {8, 5, 6}, /* IONEGINT6 */ 120 {8, 5, 5}, /* IONEGINT5 */ 121 {5, 7, 19}, /* IRRXCINT */ 122 {5, 7, 17}, /* IRRXEINT */ 123 #endif /* TX392X */ 124 {4, 1, 18}, /* SNDDMACNTINT */ 125 {3, 1, 17}, /* TELDMACNTINT */ 126 {2, 1, 27}, /* CHIDMACNTINT */ 127 {1, 5, 7}, /* IOPOSINT0 */ 128 {1, 5, 0} /* IONEGINT0 */ 129 }; 130 131 struct txintr_high_entry { 132 int he_set; 133 txreg_t he_mask; 134 int (*he_fun)(void *); 135 void *he_arg; 136 TAILQ_ENTRY(txintr_high_entry) he_link; 137 }; 138 139 #ifdef USE_POLL 140 struct txpoll_entry{ 141 int p_cnt; /* dispatch interval */ 142 int p_desc; 143 int (*p_fun)(void *); 144 void *p_arg; 145 TAILQ_ENTRY(txpoll_entry) p_link; 146 }; 147 int tx39_poll_intr(void *); 148 #endif /* USE_POLL */ 149 150 struct tx39icu_softc { 151 struct device sc_dev; 152 tx_chipset_tag_t sc_tc; 153 /* IRQLOW */ 154 txreg_t sc_le_mask[TX39_INTRSET_MAX + 1]; 155 int (*sc_le_fun[TX39_INTRSET_MAX + 1][32])(void *); 156 void *sc_le_arg[TX39_INTRSET_MAX + 1][32]; 157 /* IRQHIGH */ 158 TAILQ_HEAD(, txintr_high_entry) sc_he_head[TX39_IRQHIGH_MAX]; 159 /* Register */ 160 txreg_t sc_regs[TX39_INTRSET_MAX + 1]; 161 #ifdef USE_POLL 162 unsigned sc_pollcnt; 163 int sc_polling; 164 void *sc_poll_ih; 165 TAILQ_HEAD(, txpoll_entry) sc_p_head; 166 #endif /* USE_POLL */ 167 }; 168 169 int tx39icu_match(struct device *, struct cfdata *, void *); 170 void tx39icu_attach(struct device *, struct device *, void *); 171 int tx39icu_intr(u_int32_t, u_int32_t, u_int32_t, u_int32_t); 172 173 void tx39_intr_dump(struct tx39icu_softc *); 174 void tx39_intr_decode(int, int *, int *); 175 void tx39_irqhigh_disestablish(tx_chipset_tag_t, int, int, int); 176 void tx39_irqhigh_establish(tx_chipset_tag_t, int, int, int, 177 int (*)(void *), void *); 178 void tx39_irqhigh_intr(u_int32_t, u_int32_t, u_int32_t, u_int32_t); 179 int tx39_irqhigh(int, int); 180 181 struct cfattach tx39icu_ca = { 182 sizeof(struct tx39icu_softc), tx39icu_match, tx39icu_attach 183 }; 184 185 int 186 tx39icu_match(struct device *parent, struct cfdata *cf, void *aux) 187 { 188 return (ATTACH_FIRST); 189 } 190 191 void 192 tx39icu_attach(struct device *parent, struct device *self, void *aux) 193 { 194 struct txsim_attach_args *ta = aux; 195 struct tx39icu_softc *sc = (void *)self; 196 tx_chipset_tag_t tc = ta->ta_tc; 197 txreg_t reg, *regs; 198 int i; 199 200 printf("\n"); 201 sc->sc_tc = ta->ta_tc; 202 203 regs = sc->sc_regs; 204 regs[0] = tx_conf_read(tc, TX39_INTRSTATUS6_REG); 205 regs[1] = tx_conf_read(tc, TX39_INTRSTATUS1_REG); 206 regs[2] = tx_conf_read(tc, TX39_INTRSTATUS2_REG); 207 regs[3] = tx_conf_read(tc, TX39_INTRSTATUS3_REG); 208 regs[4] = tx_conf_read(tc, TX39_INTRSTATUS4_REG); 209 regs[5] = tx_conf_read(tc, TX39_INTRSTATUS5_REG); 210 #ifdef TX392X 211 regs[7] = tx_conf_read(tc, TX39_INTRSTATUS7_REG); 212 regs[8] = tx_conf_read(tc, TX39_INTRSTATUS8_REG); 213 #endif 214 #ifdef TX39ICUDEBUG 215 printf("\t[Windows CE setting]\n"); 216 tx39_intr_dump(sc); 217 #endif /* TX39ICUDEBUG */ 218 219 #ifdef WINCE_DEFAULT_SETTING 220 #warning WINCE_DEFAULT_SETTING 221 #else /* WINCE_DEFAULT_SETTING */ 222 /* Disable IRQLOW */ 223 tx_conf_write(tc, TX39_INTRENABLE1_REG, 0); 224 tx_conf_write(tc, TX39_INTRENABLE2_REG, 0); 225 tx_conf_write(tc, TX39_INTRENABLE3_REG, 0); 226 tx_conf_write(tc, TX39_INTRENABLE4_REG, 0); 227 tx_conf_write(tc, TX39_INTRENABLE5_REG, 0); 228 #ifdef TX392X 229 tx_conf_write(tc, TX39_INTRENABLE7_REG, 0); 230 tx_conf_write(tc, TX39_INTRENABLE8_REG, 0); 231 #endif /* TX392X */ 232 233 /* Disable IRQHIGH */ 234 reg = tx_conf_read(tc, TX39_INTRENABLE6_REG); 235 reg &= ~TX39_INTRENABLE6_PRIORITYMASK_MASK; 236 tx_conf_write(tc, TX39_INTRENABLE6_REG, reg); 237 #endif /* WINCE_DEFAULT_SETTING */ 238 239 /* Clear all pending interrupts */ 240 tx_conf_write(tc, TX39_INTRCLEAR1_REG, 241 tx_conf_read(tc, TX39_INTRSTATUS1_REG)); 242 tx_conf_write(tc, TX39_INTRCLEAR2_REG, 243 tx_conf_read(tc, TX39_INTRSTATUS2_REG)); 244 tx_conf_write(tc, TX39_INTRCLEAR3_REG, 245 tx_conf_read(tc, TX39_INTRSTATUS3_REG)); 246 tx_conf_write(tc, TX39_INTRCLEAR4_REG, 247 tx_conf_read(tc, TX39_INTRSTATUS4_REG)); 248 tx_conf_write(tc, TX39_INTRCLEAR5_REG, 249 tx_conf_read(tc, TX39_INTRSTATUS5_REG)); 250 #ifdef TX392X 251 tx_conf_write(tc, TX39_INTRCLEAR7_REG, 252 tx_conf_read(tc, TX39_INTRSTATUS7_REG)); 253 tx_conf_write(tc, TX39_INTRCLEAR8_REG, 254 tx_conf_read(tc, TX39_INTRSTATUS8_REG)); 255 #endif /* TX392X */ 256 257 /* Enable global interrupts */ 258 reg = tx_conf_read(tc, TX39_INTRENABLE6_REG); 259 reg |= TX39_INTRENABLE6_GLOBALEN; 260 tx_conf_write(tc, TX39_INTRENABLE6_REG, reg); 261 262 /* Initialize IRQHIGH interrupt handler holder*/ 263 for (i = 0; i < TX39_IRQHIGH_MAX; i++) { 264 TAILQ_INIT(&sc->sc_he_head[i]); 265 } 266 #ifdef USE_POLL 267 /* Initialize polling handler holder */ 268 TAILQ_INIT(&sc->sc_p_head); 269 #endif /* USE_POLL */ 270 271 /* Register interrupt module myself */ 272 tx_conf_register_intr(tc, self); 273 } 274 275 int 276 tx39icu_intr(u_int32_t status, u_int32_t cause, u_int32_t pc, 277 u_int32_t ipending) 278 { 279 struct tx39icu_softc *sc; 280 tx_chipset_tag_t tc; 281 txreg_t reg, pend, *regs; 282 int i, j; 283 284 tc = tx_conf_get_tag(); 285 sc = tc->tc_intrt; 286 /* 287 * Read regsiter ASAP 288 */ 289 regs = sc->sc_regs; 290 regs[0] = tx_conf_read(tc, TX39_INTRSTATUS6_REG); 291 regs[1] = tx_conf_read(tc, TX39_INTRSTATUS1_REG); 292 regs[2] = tx_conf_read(tc, TX39_INTRSTATUS2_REG); 293 regs[3] = tx_conf_read(tc, TX39_INTRSTATUS3_REG); 294 regs[4] = tx_conf_read(tc, TX39_INTRSTATUS4_REG); 295 regs[5] = tx_conf_read(tc, TX39_INTRSTATUS5_REG); 296 #ifdef TX392X 297 regs[7] = tx_conf_read(tc, TX39_INTRSTATUS7_REG); 298 regs[8] = tx_conf_read(tc, TX39_INTRSTATUS8_REG); 299 #endif 300 301 #ifdef TX39ICUDEBUG 302 if (!(ipending & MIPS_INT_MASK_4) && !(ipending & MIPS_INT_MASK_2)) { 303 bitdisp(ipending); 304 panic("bogus HwInt"); 305 } 306 #ifdef TX39_DEBUG 307 if (tx39debugflag) { 308 tx39_intr_dump(sc); 309 } 310 #endif 311 #endif /* TX39ICUDEBUG */ 312 313 /* IRQHIGH */ 314 if (ipending & MIPS_INT_MASK_4) { 315 tx39_irqhigh_intr(ipending, pc, status, cause); 316 317 return (0); 318 } 319 320 /* IRQLOW */ 321 if (ipending & MIPS_INT_MASK_2) { 322 for (i = 1; i <= TX39_INTRSET_MAX; i++) { 323 int ofs; 324 #ifdef TX392X 325 if (i == 6) 326 continue; 327 #endif /* TX392X */ 328 ofs = TX39_INTRSTATUS_REG(i); 329 pend = sc->sc_regs[i]; 330 reg = sc->sc_le_mask[i] & pend; 331 /* Clear interrupts */ 332 tx_conf_write(tc, ofs, reg); 333 /* Dispatch handler */ 334 for (j = 0 ; j < 32; j++) { 335 if ((reg & (1 << j)) && 336 sc->sc_le_fun[i][j]) { 337 #ifdef TX39_DEBUG 338 tx39intrvec = (i << 16) | j; 339 if (tx39debugflag) { 340 DPRINTF(("IRQLOW %d:%d\n", 341 i, j)); 342 } 343 #endif /* TX39_DEBUG */ 344 (*sc->sc_le_fun[i][j]) 345 (sc->sc_le_arg[i][j]); 346 347 } 348 } 349 #ifdef TX39ICUDEBUG_PRINT_PENDING_INTERRUPT 350 pend &= ~reg; 351 if (pend) { 352 printf("%d pending:", i); 353 __bitdisp(pend, 0, 31, 0, 1); 354 } 355 #endif 356 357 } 358 } 359 #ifdef TX39_WATCHDOGTIMER 360 { 361 extern int tx39biu_intr(void *); 362 /* Bus error (If watch dog timer is enabled)*/ 363 if (ipending & MIPS_INT_MASK_1) { 364 tx39biu_intr(0); /* Clear bus error */ 365 } 366 } 367 #endif 368 #if 0 369 /* reset priority mask */ 370 reg = tx_conf_read(tc, TX39_INTRENABLE6_REG); 371 reg = TX39_INTRENABLE6_PRIORITYMASK_SET(reg, 0xffff); 372 tx_conf_write(tc, TX39_INTRENABLE6_REG, reg); 373 #endif 374 return (MIPS_SR_INT_IE | (status & ~cause & MIPS_HARD_INT_MASK)); 375 } 376 377 int 378 tx39_irqhigh(int set, int bit) 379 { 380 int i, n; 381 382 n = sizeof irqhigh_list / sizeof (struct irqhigh_list); 383 for (i = 0; i < n; i++) { 384 if (irqhigh_list[i].qh_set == set && 385 irqhigh_list[i].qh_bit == bit) 386 return (irqhigh_list[i].qh_pri); 387 } 388 389 return (0); 390 } 391 392 void 393 tx39_irqhigh_intr(u_int32_t ipending, u_int32_t pc, u_int32_t status, 394 u_int32_t cause) 395 { 396 struct txintr_high_entry *he; 397 struct tx39icu_softc *sc; 398 struct clockframe cf; 399 tx_chipset_tag_t tc; 400 int i, pri, ofs, set; 401 txreg_t he_mask; 402 403 tc = tx_conf_get_tag(); 404 sc = tc->tc_intrt; 405 pri = TX39_INTRSTATUS6_INTVECT(sc->sc_regs[0]); 406 407 if (pri == TX39_INTRPRI13_TIMER_PERIODIC) { 408 tx_conf_write(tc, TX39_INTRCLEAR5_REG, 409 TX39_INTRSTATUS5_PERINT); 410 cf.pc = pc; 411 cf.sr = status; 412 hardclock(&cf); 413 intrcnt[HARDCLOCK]++; 414 415 return; 416 } 417 418 /* Handle all pending IRQHIGH interrupts */ 419 for (i = pri; i > 0; i--) { 420 TAILQ_FOREACH(he, &sc->sc_he_head[i], he_link) { 421 set = he->he_set; 422 he_mask = he->he_mask; 423 if (he_mask & (sc->sc_regs[set])) { 424 ofs = TX39_INTRSTATUS_REG(set); 425 /* Clear interrupt */ 426 tx_conf_write(tc, ofs, he_mask); 427 #ifdef TX39_DEBUG 428 tx39intrvec = (set << 16) | 429 (ffs(he_mask) - 1); 430 if (tx39debugflag) { 431 DPRINTF(("IRQHIGH: %d:%d\n", 432 set, ffs(he_mask) - 1)); 433 } 434 #endif /* TX39_DEBUG */ 435 /* Dispatch handler */ 436 (*he->he_fun)(he->he_arg); 437 } 438 } 439 } 440 } 441 442 void 443 tx39_intr_decode(int intr, int *set, int *bit) 444 { 445 if (!intr || intr >= (TX39_INTRSET_MAX + 1) * 32 446 #ifdef TX392X 447 || intr == 6 448 #endif /* TX392X */ 449 ) { 450 panic("tx39icu_decode: bogus intrrupt line. %d", intr); 451 } 452 *set = intr / 32; 453 *bit = intr % 32; 454 } 455 456 void 457 tx39_irqhigh_establish(tx_chipset_tag_t tc, int set, int bit, int pri, 458 int (*ih_fun)(void *), void *ih_arg) 459 { 460 struct tx39icu_softc *sc; 461 struct txintr_high_entry *he; 462 txreg_t reg; 463 464 sc = tc->tc_intrt; 465 /* 466 * Add new entry to `pri' priority 467 */ 468 if (!(he = malloc(sizeof(struct txintr_high_entry), 469 M_DEVBUF, M_NOWAIT))) { 470 panic ("tx39_irqhigh_establish: no memory."); 471 } 472 memset(he, 0, sizeof(struct txintr_high_entry)); 473 he->he_set = set; 474 he->he_mask= (1 << bit); 475 he->he_fun = ih_fun; 476 he->he_arg = ih_arg; 477 TAILQ_INSERT_TAIL(&sc->sc_he_head[pri], he, he_link); 478 /* 479 * Enable interrupt on this priority. 480 */ 481 reg = tx_conf_read(tc, TX39_INTRENABLE6_REG); 482 reg = TX39_INTRENABLE6_PRIORITYMASK_SET(reg, (1 << pri)); 483 tx_conf_write(tc, TX39_INTRENABLE6_REG, reg); 484 } 485 486 void 487 tx39_irqhigh_disestablish(tx_chipset_tag_t tc, int set, int bit, int pri) 488 { 489 struct tx39icu_softc *sc; 490 struct txintr_high_entry *he; 491 txreg_t reg; 492 493 sc = tc->tc_intrt; 494 TAILQ_FOREACH(he, &sc->sc_he_head[pri], he_link) { 495 if (he->he_set == set && he->he_mask == (1 << bit)) { 496 TAILQ_REMOVE(&sc->sc_he_head[pri], he, he_link); 497 free(he, M_DEVBUF); 498 break; 499 } 500 } 501 502 if (TAILQ_EMPTY(&sc->sc_he_head[pri])) { 503 reg = tx_conf_read(tc, TX39_INTRENABLE6_REG); 504 reg &= ~(1 << pri); 505 tx_conf_write(tc, TX39_INTRENABLE6_REG, reg); 506 } 507 } 508 509 510 void * 511 tx_intr_establish(tx_chipset_tag_t tc, int line, int mode, int level, 512 int (*ih_fun)(void *), void *ih_arg) 513 { 514 struct tx39icu_softc *sc; 515 txreg_t reg; 516 int bit, set, highpri, ofs; 517 518 sc = tc->tc_intrt; 519 520 tx39_intr_decode(line, &set, &bit); 521 522 sc->sc_le_fun[set][bit] = ih_fun; 523 sc->sc_le_arg[set][bit] = ih_arg; 524 DPRINTF(("tx_intr_establish: %d:%d", set, bit)); 525 526 if ((highpri = tx39_irqhigh(set, bit))) { 527 tx39_irqhigh_establish(tc, set, bit, highpri, 528 ih_fun, ih_arg); 529 DPRINTF(("(high)\n")); 530 } else { 531 /* Set mask for acknowledge. */ 532 sc->sc_le_mask[set] |= (1 << bit); 533 /* Enable interrupt */ 534 ofs = TX39_INTRENABLE_REG(set); 535 reg = tx_conf_read(tc, ofs); 536 reg |= (1 << bit); 537 tx_conf_write(tc, ofs, reg); 538 DPRINTF(("(low)\n")); 539 } 540 541 return ((void *)line); 542 } 543 544 void 545 tx_intr_disestablish(tx_chipset_tag_t tc, void *arg) 546 { 547 struct tx39icu_softc *sc; 548 int set, bit, highpri, ofs; 549 txreg_t reg; 550 551 sc = tc->tc_intrt; 552 553 tx39_intr_decode((int)arg, &set, &bit); 554 DPRINTF(("tx_intr_disestablish: %d:%d", set, bit)); 555 556 if ((highpri = tx39_irqhigh(set, bit))) { 557 tx39_irqhigh_disestablish(tc, set, bit, highpri); 558 DPRINTF(("(high)\n")); 559 } else { 560 sc->sc_le_fun[set][bit] = 0; 561 sc->sc_le_arg[set][bit] = 0; 562 sc->sc_le_mask[set] &= ~(1 << bit); 563 ofs = TX39_INTRENABLE_REG(set); 564 reg = tx_conf_read(tc, ofs); 565 reg &= ~(1 << bit); 566 tx_conf_write(tc, ofs, reg); 567 DPRINTF(("(low)\n")); 568 } 569 } 570 571 u_int32_t 572 tx_intr_status(tx_chipset_tag_t tc, int r) 573 { 574 struct tx39icu_softc *sc = tc->tc_intrt; 575 576 if (r < 0 || r >= TX39_INTRSET_MAX + 1) 577 panic("tx_intr_status: invalid index %d", r); 578 579 return (u_int32_t)(sc->sc_regs[r]); 580 } 581 582 #ifdef USE_POLL 583 void * 584 tx39_poll_establish(tx_chipset_tag_t tc, int interval, int level, 585 int (*ih_fun)(void *), void *ih_arg) 586 { 587 struct tx39icu_softc *sc; 588 struct txpoll_entry *p; 589 int s; 590 void *ret; 591 592 s = splhigh(); 593 sc = tc->tc_intrt; 594 595 if (!(p = malloc(sizeof(struct txpoll_entry), 596 M_DEVBUF, M_NOWAIT))) { 597 panic ("tx39_poll_establish: no memory."); 598 } 599 memset(p, 0, sizeof(struct txpoll_entry)); 600 601 p->p_fun = ih_fun; 602 p->p_arg = ih_arg; 603 p->p_cnt = interval; 604 605 if (!sc->sc_polling) { 606 tx39clock_alarm_set(tc, 33); /* 33 msec */ 607 608 if (!(sc->sc_poll_ih = 609 tx_intr_establish( 610 tc, MAKEINTR(5, TX39_INTRSTATUS5_ALARMINT), 611 IST_EDGE, level, tx39_poll_intr, sc))) { 612 printf("tx39_poll_establish: can't hook\n"); 613 614 splx(s); 615 return (0); 616 } 617 } 618 619 sc->sc_polling++; 620 p->p_desc = sc->sc_polling; 621 TAILQ_INSERT_TAIL(&sc->sc_p_head, p, p_link); 622 ret = (void *)p->p_desc; 623 624 splx(s); 625 return (ret); 626 } 627 628 void 629 tx39_poll_disestablish(tx_chipset_tag_t tc, void *arg) 630 { 631 struct tx39icu_softc *sc; 632 struct txpoll_entry *p; 633 int s, desc; 634 635 s = splhigh(); 636 sc = tc->tc_intrt; 637 638 desc = (int)arg; 639 TAILQ_FOREACH(p, &sc->sc_p_head, p_link) { 640 if (p->p_desc == desc) { 641 TAILQ_REMOVE(&sc->sc_p_head, p, p_link); 642 free(p, M_DEVBUF); 643 break; 644 } 645 } 646 647 if (TAILQ_EMPTY(&sc->sc_p_head)) { 648 sc->sc_polling = 0; 649 tx_intr_disestablish(tc, sc->sc_poll_ih); 650 } 651 652 splx(s); 653 return; 654 } 655 656 int 657 tx39_poll_intr(void *arg) 658 { 659 struct tx39icu_softc *sc = arg; 660 struct txpoll_entry *p; 661 662 tx39clock_alarm_refill(sc->sc_tc); 663 664 if (!sc->sc_polling) { 665 return (0); 666 } 667 sc->sc_pollcnt++; 668 TAILQ_FOREACH(p, &sc->sc_p_head, p_link) { 669 if (sc->sc_pollcnt % p->p_cnt == 0) { 670 if ((*p->p_fun)(p->p_arg) == POLL_END) 671 goto disestablish; 672 } 673 } 674 675 return (0); 676 677 disestablish: 678 TAILQ_REMOVE(&sc->sc_p_head, p, p_link); 679 free(p, M_DEVBUF); 680 if (TAILQ_EMPTY(&sc->sc_p_head)) { 681 sc->sc_polling = 0; 682 tx_intr_disestablish(sc->sc_tc, sc->sc_poll_ih); 683 } 684 685 return (0); 686 } 687 #endif /* USE_POLL */ 688 689 void 690 tx39_intr_dump(struct tx39icu_softc *sc) 691 { 692 tx_chipset_tag_t tc = sc->sc_tc; 693 int i, j, ofs; 694 txreg_t reg; 695 char msg[16]; 696 697 for (i = 1; i <= TX39_INTRSET_MAX; i++) { 698 #ifdef TX392X 699 if (i == 6) 700 continue; 701 #endif /* TX392X */ 702 for (reg = j = 0; j < 32; j++) { 703 if (tx39_irqhigh(i, j)) { 704 reg |= (1 << j); 705 } 706 } 707 sprintf(msg, "%d high", i); 708 __bitdisp(reg, 32, 0, msg, 1); 709 sprintf(msg, "%d status", i); 710 __bitdisp(sc->sc_regs[i], 0, 31, msg, 1); 711 ofs = TX39_INTRENABLE_REG(i); 712 reg = tx_conf_read(tc, ofs); 713 sprintf(msg, "%d enable", i); 714 __bitdisp(reg, 0, 31, msg, 1); 715 } 716 reg = sc->sc_regs[0]; 717 printf("<%s><%s> vector=%2d\t\t[6 status]\n", 718 reg & TX39_INTRSTATUS6_IRQHIGH ? "HI" : "--", 719 reg & TX39_INTRSTATUS6_IRQLOW ? "LO" : "--", 720 TX39_INTRSTATUS6_INTVECT(reg)); 721 reg = tx_conf_read(tc, TX39_INTRENABLE6_REG); 722 __bitdisp(reg, 0, 18, "6 enable", 1); 723 724 } 725