Annotation of sys/arch/sgi/localbus/macebus.c, Revision 1.1.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