Annotation of sys/arch/sgi/localbus/macebus.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: macebus.c,v 1.26 2007/07/09 21:40:24 jasper Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2000-2004 Opsycon AB (www.opsycon.se)
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions
! 8: * are met:
! 9: * 1. Redistributions of source code must retain the above copyright
! 10: * notice, this list of conditions and the following disclaimer.
! 11: * 2. Redistributions in binary form must reproduce the above copyright
! 12: * notice, this list of conditions and the following disclaimer in the
! 13: * documentation and/or other materials provided with the distribution.
! 14: *
! 15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
! 16: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
! 17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 18: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
! 19: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 20: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 21: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 22: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 23: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 24: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 25: * SUCH DAMAGE.
! 26: *
! 27: */
! 28:
! 29: /*
! 30: * This is a combined macebus/crimebus driver. It handles
! 31: * configuration of all devices on the processor bus.
! 32: */
! 33:
! 34: #include <sys/param.h>
! 35: #include <sys/systm.h>
! 36: #include <sys/kernel.h>
! 37: #include <sys/conf.h>
! 38: #include <sys/malloc.h>
! 39: #include <sys/device.h>
! 40: #include <sys/tty.h>
! 41: #include <sys/extent.h>
! 42: #include <net/netisr.h>
! 43: #include <uvm/uvm_extern.h>
! 44:
! 45: #include <dev/pci/pcidevs.h>
! 46: #include <dev/pci/pcivar.h>
! 47:
! 48: #include <dev/ic/comvar.h>
! 49:
! 50: #include <mips64/archtype.h>
! 51:
! 52: #include <machine/autoconf.h>
! 53: #include <machine/intr.h>
! 54: #include <machine/atomic.h>
! 55:
! 56: #include <sgi/localbus/macebus.h>
! 57: #include <sgi/localbus/crimebus.h>
! 58:
! 59: int macebusmatch(struct device *, void *, void *);
! 60: void macebusattach(struct device *, struct device *, void *);
! 61: int macebusprint(void *, const char *);
! 62: int macebusscan(struct device *, void *, void *);
! 63:
! 64: void *macebus_intr_establish(void *, u_long, int, int,
! 65: int (*)(void *), void *, char *);
! 66: void macebus_intr_disestablish(void *, void *);
! 67: void macebus_intr_makemasks(void);
! 68: void macebus_do_pending_int(int);
! 69: intrmask_t macebus_iointr(intrmask_t, struct trap_frame *);
! 70: intrmask_t macebus_aux(intrmask_t, struct trap_frame *);
! 71:
! 72: bus_addr_t macebus_pa_to_device(paddr_t);
! 73: paddr_t macebus_device_to_pa(bus_addr_t);
! 74:
! 75: int maceticks; /* Time tracker for special events */
! 76:
! 77: struct cfattach macebus_ca = {
! 78: sizeof(struct device), macebusmatch, macebusattach
! 79: };
! 80:
! 81: struct cfdriver macebus_cd = {
! 82: NULL, "macebus", DV_DULL, 1
! 83: };
! 84:
! 85: bus_space_t macebus_tag = {
! 86: NULL,
! 87: (bus_addr_t)MACEBUS_BASE,
! 88: NULL,
! 89: 0,
! 90: mace_read_1, mace_write_1,
! 91: mace_read_2, mace_write_2,
! 92: mace_read_4, mace_write_4,
! 93: mace_read_8, mace_write_8,
! 94: mace_space_map, mace_space_unmap, mace_space_region,
! 95: };
! 96:
! 97: bus_space_t crimebus_tag = {
! 98: NULL,
! 99: (bus_addr_t)CRIMEBUS_BASE,
! 100: NULL,
! 101: 0,
! 102: mace_read_1, mace_write_1,
! 103: mace_read_2, mace_write_2,
! 104: mace_read_4, mace_write_4,
! 105: mace_read_8, mace_write_8,
! 106: mace_space_map, mace_space_unmap, mace_space_region,
! 107: };
! 108:
! 109: bus_space_handle_t crime_h;
! 110: bus_space_handle_t mace_h;
! 111:
! 112: struct machine_bus_dma_tag mace_bus_dma_tag = {
! 113: NULL, /* _cookie */
! 114: _dmamap_create,
! 115: _dmamap_destroy,
! 116: _dmamap_load,
! 117: _dmamap_load_mbuf,
! 118: _dmamap_load_uio,
! 119: _dmamap_load_raw,
! 120: _dmamap_unload,
! 121: _dmamap_sync,
! 122: _dmamem_alloc,
! 123: _dmamem_free,
! 124: _dmamem_map,
! 125: _dmamem_unmap,
! 126: _dmamem_mmap,
! 127: macebus_pa_to_device,
! 128: macebus_device_to_pa,
! 129: CRIME_MEMORY_MASK
! 130: };
! 131:
! 132: /*
! 133: * Match bus only to targets which have this bus.
! 134: */
! 135: int
! 136: macebusmatch(struct device *parent, void *match, void *aux)
! 137: {
! 138: if (sys_config.system_type == SGI_O2)
! 139: return (1);
! 140: return (0);
! 141: }
! 142:
! 143: int
! 144: macebusprint(void *aux, const char *macebus)
! 145: {
! 146: /* XXXX print flags */
! 147: return (QUIET);
! 148: }
! 149:
! 150:
! 151: int
! 152: macebusscan(struct device *parent, void *child, void *args)
! 153: {
! 154: struct device *dev = child;
! 155: struct cfdata *cf = dev->dv_cfdata;
! 156: struct confargs lba;
! 157: struct abus lbus;
! 158:
! 159: if (cf->cf_fstate == FSTATE_STAR) {
! 160: printf("macebus '*' devs not allowed!\n");
! 161: return 0;
! 162: }
! 163:
! 164: lba.ca_sys = cf->cf_loc[0];
! 165: if (cf->cf_loc[1] == -1) {
! 166: lba.ca_baseaddr = 0;
! 167: } else {
! 168: lba.ca_baseaddr = cf->cf_loc[1];
! 169: }
! 170: if (cf->cf_loc[2] == -1) {
! 171: lba.ca_intr = 0;
! 172: lba.ca_nintr = 0;
! 173: } else {
! 174: lba.ca_intr = cf->cf_loc[2];
! 175: lba.ca_nintr = 1;
! 176: }
! 177:
! 178: lba.ca_bus = &lbus;
! 179:
! 180: /* Fill in what is needed for probing */
! 181: lba.ca_bus->ab_type = BUS_LOCAL;
! 182: lba.ca_bus->ab_matchname = NULL;
! 183: lba.ca_name = cf->cf_driver->cd_name;
! 184: lba.ca_num = dev->dv_unit;
! 185: lba.ca_iot = &macebus_tag;
! 186: lba.ca_memt = &macebus_tag;
! 187: lba.ca_dmat = &mace_bus_dma_tag;
! 188:
! 189: return (*cf->cf_attach->ca_match)(parent, cf, &lba);
! 190: }
! 191:
! 192: void
! 193: macebusattach(struct device *parent, struct device *self, void *aux)
! 194: {
! 195: struct device *dev;
! 196: struct confargs lba;
! 197: struct abus lbus;
! 198: u_int32_t creg;
! 199: u_int64_t mask;
! 200:
! 201: /*
! 202: * Create an extent for the localbus control registers.
! 203: */
! 204: macebus_tag.bus_extent = extent_create("mace_space",
! 205: macebus_tag.bus_base, macebus_tag.bus_base + 0x00400000,
! 206: M_DEVBUF, NULL, 0, EX_NOCOALESCE | EX_NOWAIT);
! 207:
! 208: crimebus_tag.bus_extent = extent_create("crime_space",
! 209: crimebus_tag.bus_base, crimebus_tag.bus_base + 0x00400000,
! 210: M_DEVBUF, NULL, 0, EX_NOCOALESCE | EX_NOWAIT);
! 211:
! 212: /*
! 213: * Map and set up CRIME control registers.
! 214: */
! 215: if (bus_space_map(&crimebus_tag, 0x00000000, 0x400, 0, &crime_h)) {
! 216: printf(": cannot map CRIME control registers\n");
! 217: return;
! 218: }
! 219: hwmask_addr = (void *)(PHYS_TO_XKPHYS(CRIMEBUS_BASE, CCA_NC) +
! 220: CRIME_INT_MASK);
! 221:
! 222: creg = bus_space_read_8(&crimebus_tag, crime_h, CRIME_REVISION);
! 223: printf(": crime rev %d.%d\n", (creg & 0xf0) >> 4, creg & 0xf);
! 224:
! 225: bus_space_write_8(&crimebus_tag, crime_h, CRIME_CPU_ERROR_STAT, 0);
! 226: bus_space_write_8(&crimebus_tag, crime_h, CRIME_MEM_ERROR_STAT, 0);
! 227:
! 228: mask = 0;
! 229: bus_space_write_8(&crimebus_tag, crime_h, CRIME_INT_MASK, mask);
! 230: bus_space_write_8(&crimebus_tag, crime_h, CRIME_INT_SOFT, 0);
! 231: bus_space_write_8(&crimebus_tag, crime_h, CRIME_INT_HARD, 0);
! 232: bus_space_write_8(&crimebus_tag, crime_h, CRIME_INT_STAT, 0);
! 233:
! 234:
! 235: /*
! 236: * Map and set up MACE ISA control registers.
! 237: */
! 238: if (bus_space_map(&macebus_tag, MACE_ISA_OFFS, 0x400, 0, &mace_h)) {
! 239: printf("UH-OH! Can't map MACE ISA control registers!\n");
! 240: return;
! 241: }
! 242:
! 243: bus_space_write_8(&macebus_tag, mace_h, MACE_ISA_INT_MASK, 0xffffffff);
! 244: bus_space_write_8(&macebus_tag, mace_h, MACE_ISA_INT_STAT, 0);
! 245:
! 246: /*
! 247: * Now attach all devices to macebus in proper order.
! 248: */
! 249: memset(&lba, 0, sizeof(lba));
! 250: memset(&lbus, 0, sizeof(lbus));
! 251: lba.ca_bus = &lbus;
! 252: lba.ca_bus->ab_type = BUS_LOCAL;
! 253: lba.ca_bus->ab_matchname = NULL;
! 254: lba.ca_iot = &macebus_tag;
! 255: lba.ca_memt = &macebus_tag;
! 256: lba.ca_dmat = &mace_bus_dma_tag;
! 257:
! 258: /*
! 259: * On O2 systems all interrupts are handled by the
! 260: * macebus interrupt handler. Register all except clock.
! 261: */
! 262: switch (sys_config.system_type) {
! 263: case SGI_O2:
! 264: set_intr(INTPRI_MACEIO, CR_INT_0, macebus_iointr);
! 265: lba.ca_bus->ab_intr_establish = macebus_intr_establish;
! 266: lba.ca_bus->ab_intr_disestablish = macebus_intr_disestablish;
! 267: register_pending_int_handler(macebus_do_pending_int);
! 268: break;
! 269: default:
! 270: panic("macebusscan: unknown macebus type!");
! 271: }
! 272:
! 273: /* DEBUG: Set up a handler called when clock interrupts go off. */
! 274: set_intr(INTPRI_MACEAUX, CR_INT_5, macebus_aux);
! 275:
! 276:
! 277: while ((dev = config_search(macebusscan, self, aux)) != NULL) {
! 278: struct cfdata *cf;
! 279:
! 280: cf = dev->dv_cfdata;
! 281: lba.ca_sys = cf->cf_loc[0];
! 282: if (cf->cf_loc[1] == -1)
! 283: lba.ca_baseaddr = 0;
! 284: else
! 285: lba.ca_baseaddr = cf->cf_loc[1];
! 286:
! 287: if (cf->cf_loc[2] == -1) {
! 288: lba.ca_intr = 0;
! 289: lba.ca_nintr = 0;
! 290: } else {
! 291: lba.ca_intr= cf->cf_loc[2];
! 292: lba.ca_nintr = 1;
! 293: }
! 294: lba.ca_name = cf->cf_driver->cd_name;
! 295: lba.ca_num = dev->dv_unit;
! 296:
! 297: config_attach(self, dev, &lba, macebusprint);
! 298: }
! 299: }
! 300:
! 301:
! 302: /*
! 303: * Bus access primitives. These are really ugly...
! 304: */
! 305:
! 306: u_int8_t
! 307: mace_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
! 308: {
! 309: return *(volatile u_int8_t *)(h + (o << 8) + 7);
! 310: }
! 311:
! 312: u_int16_t
! 313: mace_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
! 314: {
! 315: panic("mace_read_2");
! 316: }
! 317:
! 318: u_int32_t
! 319: mace_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
! 320: {
! 321: return *(volatile u_int32_t *)(h + o);
! 322: }
! 323:
! 324: u_int64_t
! 325: mace_read_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
! 326: {
! 327: #ifdef __LP64__
! 328: return *(volatile u_int64_t *)(h + o);
! 329: #else
! 330: return lp32_read8((u_int64_t *)(h + o));
! 331: #endif
! 332: }
! 333:
! 334: void
! 335: mace_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, u_int8_t v)
! 336: {
! 337: *(volatile u_int8_t *)(h + (o << 8) + 7) = v;
! 338: }
! 339:
! 340: void
! 341: mace_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, u_int16_t v)
! 342: {
! 343: panic("mace_write_2");
! 344: }
! 345:
! 346: void
! 347: mace_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, u_int32_t v)
! 348: {
! 349: *(volatile u_int32_t *)(h + o) = v;
! 350: }
! 351:
! 352: void
! 353: mace_write_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, u_int64_t v)
! 354: {
! 355: #ifdef __LP64__
! 356: *(volatile u_int64_t *)(h + o) = v;
! 357: #else
! 358: lp32_write8((u_int64_t *)(h + o), v);
! 359: #endif
! 360: }
! 361:
! 362: extern int extent_malloc_flags;
! 363:
! 364: int
! 365: mace_space_map(bus_space_tag_t t, bus_addr_t offs, bus_size_t size,
! 366: int cacheable, bus_space_handle_t *bshp)
! 367: {
! 368: bus_addr_t bpa;
! 369: int error;
! 370:
! 371: bpa = t->bus_base + offs;
! 372:
! 373: /* Handle special mapping separately */
! 374: if (bpa >= (MACEBUS_BASE + MACE_ISAX_OFFS) &&
! 375: (bpa + size) < (MACEBUS_BASE + MACE_ISAX_OFFS + MACE_ISAX_SIZE)) {
! 376: *bshp = PHYS_TO_XKPHYS(bpa, CCA_NC);
! 377: return 0;
! 378: }
! 379:
! 380: if ((error = extent_alloc_region(t->bus_extent, bpa, size,
! 381: EX_NOWAIT | extent_malloc_flags))) {
! 382: return error;
! 383: }
! 384:
! 385: if ((error = bus_mem_add_mapping(bpa, size, cacheable, bshp))) {
! 386: if (extent_free(t->bus_extent, bpa, size,
! 387: EX_NOWAIT | extent_malloc_flags)) {
! 388: printf("bus_space_map: pa %p, size %p\n", bpa, size);
! 389: printf("bus_space_map: can't free region\n");
! 390: }
! 391: }
! 392:
! 393: return (error);
! 394: }
! 395:
! 396: void
! 397: mace_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
! 398: {
! 399: bus_addr_t sva, paddr;
! 400: bus_size_t off, len;
! 401:
! 402: /* should this verify that the proper size is freed? */
! 403: sva = trunc_page(bsh);
! 404: off = bsh - sva;
! 405: len = size+off;
! 406:
! 407: if (IS_XKPHYS(bsh)) {
! 408: paddr = XKPHYS_TO_PHYS(bsh);
! 409: if (paddr >= (MACEBUS_BASE + MACE_ISAX_OFFS) &&
! 410: (paddr + size) <=
! 411: (MACEBUS_BASE + MACE_ISAX_OFFS + MACE_ISAX_SIZE))
! 412: return;
! 413: }
! 414:
! 415: if (pmap_extract(pmap_kernel(), bsh, (void *)&paddr) == 0) {
! 416: printf("bus_space_unmap: no pa for va %p\n", bsh);
! 417: return;
! 418: }
! 419:
! 420: uvm_km_free(kernel_map, sva, len);
! 421:
! 422: if (extent_free(t->bus_extent, paddr, size,
! 423: EX_NOWAIT | extent_malloc_flags)) {
! 424: printf("bus_space_map: pa %p, size %p\n", paddr, size);
! 425: printf("bus_space_map: can't free region\n");
! 426: }
! 427: }
! 428:
! 429: int
! 430: mace_space_region(bus_space_tag_t t, bus_space_handle_t bsh,
! 431: bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp)
! 432: {
! 433: *nbshp = bsh + offset;
! 434: return (0);
! 435: }
! 436:
! 437: /*
! 438: * Macebus bus_dma helpers.
! 439: * Mace accesses memory contiguously at 0x40000000 onwards.
! 440: */
! 441:
! 442: bus_addr_t
! 443: macebus_pa_to_device(paddr_t pa)
! 444: {
! 445: return (pa | CRIME_MEMORY_OFFSET);
! 446: }
! 447:
! 448: paddr_t
! 449: macebus_device_to_pa(bus_addr_t addr)
! 450: {
! 451: paddr_t pa = (paddr_t)addr & CRIME_MEMORY_MASK;
! 452:
! 453: if (pa >= 256 * 1024 * 1024)
! 454: pa |= CRIME_MEMORY_OFFSET;
! 455:
! 456: return (pa);
! 457: }
! 458:
! 459: /*
! 460: * Macebus interrupt handler driver.
! 461: */
! 462:
! 463: intrmask_t mace_intem = 0x0;
! 464: static intrmask_t intrtype[INTMASKSIZE];
! 465: static intrmask_t intrmask[INTMASKSIZE];
! 466: static intrmask_t intrlevel[INTMASKSIZE];
! 467:
! 468: static int fakeintr(void *);
! 469: static int fakeintr(void *a) {return 0;}
! 470:
! 471: /*
! 472: * Establish an interrupt handler called from the dispatcher.
! 473: * The interrupt function established should return zero if
! 474: * there was nothing to serve (no int) and non zero when an
! 475: * interrupt was serviced.
! 476: * Interrupts are numbered from 1 and up where 1 maps to HW int 0.
! 477: */
! 478: void *
! 479: macebus_intr_establish(void *icp, u_long irq, int type, int level,
! 480: int (*ih_fun)(void *), void *ih_arg, char *ih_what)
! 481: {
! 482: struct intrhand **p, *q, *ih;
! 483: static struct intrhand fakehand = {NULL, fakeintr};
! 484: int edge;
! 485: extern int cold;
! 486: static int initialized = 0;
! 487:
! 488: if (!initialized) {
! 489: /*INIT CODE HERE*/
! 490: initialized = 1;
! 491: }
! 492:
! 493: if (irq > 62 || irq < 1) {
! 494: panic("intr_establish: illegal irq %d", irq);
! 495: }
! 496: irq -= 1; /* Adjust for 1 being first (0 is no int) */
! 497:
! 498: /* no point in sleeping unless someone can free memory. */
! 499: ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
! 500: if (ih == NULL)
! 501: panic("intr_establish: can't malloc handler info");
! 502:
! 503: if (type == IST_NONE || type == IST_PULSE)
! 504: panic("intr_establish: bogus type");
! 505:
! 506: switch (intrtype[irq]) {
! 507: case IST_EDGE:
! 508: case IST_LEVEL:
! 509: if (type == intrtype[irq])
! 510: break;
! 511: }
! 512:
! 513: switch (type) {
! 514: case IST_EDGE:
! 515: edge |= 1 << irq;
! 516: break;
! 517: case IST_LEVEL:
! 518: edge &= ~(1 << irq);
! 519: break;
! 520: }
! 521:
! 522: /*
! 523: * Figure out where to put the handler.
! 524: * This is O(N^2), but we want to preserve the order, and N is
! 525: * generally small.
! 526: */
! 527: for (p = &intrhand[irq]; (q = *p) != NULL; p = &q->ih_next)
! 528: ;
! 529:
! 530: /*
! 531: * Actually install a fake handler momentarily, since we might be doing
! 532: * this with interrupts enabled and don't want the real routine called
! 533: * until masking is set up.
! 534: */
! 535: fakehand.ih_level = level;
! 536: *p = &fakehand;
! 537:
! 538: macebus_intr_makemasks();
! 539:
! 540: /*
! 541: * Poke the real handler in now.
! 542: */
! 543: ih->ih_fun = ih_fun;
! 544: ih->ih_arg = ih_arg;
! 545: ih->ih_next = NULL;
! 546: ih->ih_level = level;
! 547: ih->ih_irq = irq;
! 548: ih->ih_what = ih_what;
! 549: evcount_attach(&ih->ih_count, ih_what, (void *)&ih->ih_irq,
! 550: &evcount_intr);
! 551: *p = ih;
! 552:
! 553: return (ih);
! 554: }
! 555:
! 556: void
! 557: macebus_intr_disestablish(void *p1, void *p2)
! 558: {
! 559: }
! 560:
! 561: /*
! 562: * Regenerate interrupt masks to reflect reality.
! 563: */
! 564: void
! 565: macebus_intr_makemasks(void)
! 566: {
! 567: int irq, level;
! 568: struct intrhand *q;
! 569:
! 570: /* First, figure out which levels each IRQ uses. */
! 571: for (irq = 0; irq < INTMASKSIZE; irq++) {
! 572: int levels = 0;
! 573: for (q = intrhand[irq]; q; q = q->ih_next)
! 574: levels |= 1 << q->ih_level;
! 575: intrlevel[irq] = levels;
! 576: }
! 577:
! 578: /* Then figure out which IRQs use each level. */
! 579: for (level = IPL_NONE; level < NIPLS; level++) {
! 580: int irqs = 0;
! 581: for (irq = 0; irq < INTMASKSIZE; irq++)
! 582: if (intrlevel[irq] & (1 << level))
! 583: irqs |= 1 << irq;
! 584: imask[level] = irqs | SINT_ALLMASK;
! 585: }
! 586:
! 587: /*
! 588: * There are tty, network and disk drivers that use free() at interrupt
! 589: * time, so imp > (tty | net | bio).
! 590: *
! 591: * Enforce a hierarchy that gives slow devices a better chance at not
! 592: * dropping data.
! 593: */
! 594: imask[IPL_NET] |= imask[IPL_BIO];
! 595: imask[IPL_TTY] |= imask[IPL_NET];
! 596: imask[IPL_VM] |= imask[IPL_TTY];
! 597: imask[IPL_CLOCK] |= imask[IPL_VM] | SPL_CLOCKMASK;
! 598:
! 599: /*
! 600: * These are pseudo-levels.
! 601: */
! 602: imask[IPL_NONE] = 0;
! 603: imask[IPL_HIGH] = -1;
! 604:
! 605: /* And eventually calculate the complete masks. */
! 606: for (irq = 0; irq < INTMASKSIZE; irq++) {
! 607: int irqs = 1 << irq;
! 608: for (q = intrhand[irq]; q; q = q->ih_next)
! 609: irqs |= imask[q->ih_level];
! 610: intrmask[irq] = irqs | SINT_ALLMASK;
! 611: }
! 612:
! 613: /* Lastly, determine which IRQs are actually in use. */
! 614: irq = 0;
! 615: for (level = 0; level < INTMASKSIZE; level++) {
! 616: if (intrhand[level]) {
! 617: irq |= 1 << level;
! 618: }
! 619: }
! 620: mace_intem = irq & 0x0000ffff;
! 621: hw_setintrmask(0);
! 622: }
! 623:
! 624: void
! 625: macebus_do_pending_int(int newcpl)
! 626: {
! 627: #if 0
! 628: struct intrhand *ih;
! 629: int vector;
! 630: intrmask_t hwpend;
! 631: struct trap_frame cf;
! 632: static volatile int processing;
! 633:
! 634: /* Don't recurse... but change the mask */
! 635: if (processing) {
! 636: __asm__ (" .set noreorder\n");
! 637: cpl = newcpl;
! 638: __asm__ (" sync\n .set reorder\n");
! 639: return;
! 640: }
! 641: processing = 1;
! 642:
! 643:
! 644: /* XXX Fake a trapframe for clock pendings... */
! 645: cf.pc = (int)&macebus_do_pending_int;
! 646: cf.sr = 0;
! 647: cf.cpl = cpl;
! 648:
! 649: /* Hard mask current cpl so we don't get any new pendings */
! 650: hw_setintrmask(cpl);
! 651:
! 652: /* Get what interrupt we should process */
! 653: hwpend = ipending & ~newcpl;
! 654: hwpend &= ~SINT_ALLMASK;
! 655: atomic_clearbits_int(&ipending, hwpend);
! 656:
! 657: /* Enable all non pending non masked hardware interrupts */
! 658: __asm__ (" .set noreorder\n");
! 659: cpl = (cpl & SINT_ALLMASK) | (newcpl & ~SINT_ALLMASK) | hwpend;
! 660: __asm__ (" sync\n .set reorder\n");
! 661: hw_setintrmask(cpl);
! 662:
! 663: while (hwpend) {
! 664: vector = ffs(hwpend) - 1;
! 665: hwpend &= ~(1L << vector);
! 666: ih = intrhand[vector];
! 667: while (ih) {
! 668: ih->frame = &cf;
! 669: if ((*ih->ih_fun)(ih->ih_arg)) {
! 670: ih->ih_count.ec_count++;
! 671: }
! 672: ih = ih->ih_next;
! 673: }
! 674: }
! 675:
! 676: /* Enable all processed pending hardware interrupts */
! 677: __asm__ (" .set noreorder\n");
! 678: cpl &= ~hwpend;
! 679: __asm__ (" sync\n .set reorder\n");
! 680: hw_setintrmask(cpl);
! 681:
! 682: if ((ipending & SINT_CLOCKMASK) & ~newcpl) {
! 683: atomic_clearbits_int(&ipending, SINT_CLOCKMASK);
! 684: softclock();
! 685: }
! 686: if ((ipending & SINT_NETMASK) & ~newcpl) {
! 687: extern int netisr;
! 688: int isr;
! 689:
! 690: atomic_clearbits_int(&ipending, SINT_NETMASK);
! 691: while ((isr = netisr) != 0) {
! 692: atomic_clearbits_int(&netisr, isr);
! 693: #define DONETISR(b,f) if (isr & (1 << (b))) f();
! 694: #include <net/netisr_dispatch.h>
! 695: }
! 696: }
! 697:
! 698: #ifdef notyet
! 699: if ((ipending & SINT_TTYMASK) & ~newcpl) {
! 700: atomic_clearbits_int(&ipending, SINT_TTYMASK);
! 701: compoll(NULL);
! 702: }
! 703: #endif
! 704:
! 705: /* Update masks to new cpl. Order highly important! */
! 706: __asm__ (" .set noreorder\n");
! 707: cpl = newcpl;
! 708: __asm__ (" sync\n .set reorder\n");
! 709: hw_setintrmask(newcpl);
! 710:
! 711: processing = 0;
! 712: #else
! 713: /* Update masks to new cpl. Order highly important! */
! 714: __asm__ (" .set noreorder\n");
! 715: cpl = newcpl;
! 716: __asm__ (" sync\n .set reorder\n");
! 717: hw_setintrmask(newcpl);
! 718: /* If we still have softints pending trigg processing */
! 719: if (ipending & SINT_ALLMASK & ~newcpl)
! 720: setsoftintr0();
! 721: #endif
! 722: }
! 723:
! 724: /*
! 725: * Process interrupts. The parameter pending has non-masked interrupts.
! 726: */
! 727: intrmask_t
! 728: macebus_iointr(intrmask_t hwpend, struct trap_frame *cf)
! 729: {
! 730: struct intrhand *ih;
! 731: intrmask_t caught, vm;
! 732: int v;
! 733: intrmask_t pending;
! 734: u_int64_t intstat, isastat, mask;
! 735:
! 736: intstat = bus_space_read_8(&crimebus_tag, crime_h, CRIME_INT_STAT);
! 737: intstat &= 0xffff;
! 738:
! 739: isastat = bus_space_read_8(&macebus_tag, mace_h, MACE_ISA_INT_STAT);
! 740: caught = 0;
! 741:
! 742: /* Mask off masked interrupts and save them as pending */
! 743: if (intstat & cf->cpl) {
! 744: atomic_setbits_int(&ipending, intstat & cf->cpl);
! 745: mask = bus_space_read_8(&crimebus_tag, crime_h, CRIME_INT_MASK);
! 746: mask &= ~ipending;
! 747: bus_space_write_8(&crimebus_tag, crime_h, CRIME_INT_MASK, mask);
! 748: caught++;
! 749: }
! 750:
! 751: /* Scan all unmasked. Scan the first 16 for now */
! 752: pending = intstat & ~cf->cpl;
! 753: atomic_clearbits_int(&ipending, pending);
! 754:
! 755: for (v = 0, vm = 1; pending != 0 && v < 16 ; v++, vm <<= 1) {
! 756: if (pending & vm) {
! 757: ih = intrhand[v];
! 758:
! 759: while (ih) {
! 760: ih->frame = cf;
! 761: if ((*ih->ih_fun)(ih->ih_arg)) {
! 762: caught |= vm;
! 763: ih->ih_count.ec_count++;
! 764: }
! 765: ih = ih->ih_next;
! 766: }
! 767: }
! 768: }
! 769:
! 770: if (caught)
! 771: return CR_INT_0;
! 772:
! 773: return 0; /* Non found here */
! 774: }
! 775:
! 776:
! 777: /*
! 778: * Macebus auxilary functions run each clock interrupt.
! 779: */
! 780: intrmask_t
! 781: macebus_aux(intrmask_t hwpend, struct trap_frame *cf)
! 782: {
! 783: extern char idle[], e_idle[];
! 784: u_int64_t mask;
! 785:
! 786: mask = bus_space_read_8(&macebus_tag, mace_h, MACE_ISA_MISC_REG);
! 787: mask |= MACE_ISA_MISC_RLED_OFF | MACE_ISA_MISC_GLED_OFF;
! 788:
! 789: /* GREEN - Idle */
! 790: /* AMBER - System mode */
! 791: /* RED - User Mode */
! 792: if (cf->sr & SR_KSU_USER) {
! 793: mask &= ~MACE_ISA_MISC_RLED_OFF;
! 794: } else if (cf->pc >= (long)idle && cf->pc < (long)e_idle) {
! 795: mask &= ~MACE_ISA_MISC_GLED_OFF;
! 796: } else {
! 797: mask &= ~(MACE_ISA_MISC_RLED_OFF | MACE_ISA_MISC_GLED_OFF);
! 798: }
! 799: bus_space_write_8(&macebus_tag, mace_h, MACE_ISA_MISC_REG, mask);
! 800:
! 801: if (maceticks++ > 100*5) {
! 802: maceticks = 0;
! 803: }
! 804:
! 805: return 0; /* Real clock int handler registers */
! 806: }
CVSweb