1 /* $NetBSD: scb.c,v 1.14 2002/06/04 19:04:32 ragge Exp $ */ 2 /* 3 * Copyright (c) 1999 Ludd, University of Lule}, Sweden. 4 * All rights reserved. 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 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed at Ludd, University of 17 * Lule}, Sweden and its contributors. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 /* 33 * Routines for dynamic allocation/release of SCB vectors. 34 */ 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/kernel.h> 39 #include <sys/device.h> 40 41 #include <machine/trap.h> 42 #include <machine/scb.h> 43 #include <machine/frame.h> 44 #include <machine/cpu.h> 45 #include <machine/sid.h> 46 #include <machine/mtpr.h> 47 48 struct scb *scb; 49 struct ivec_dsp *scb_vec; 50 51 void scb_stray(void *); 52 static volatile int vector, ipl, gotintr; 53 54 /* 55 * Generates a new SCB. 56 */ 57 paddr_t 58 scb_init(paddr_t avail_start) 59 { 60 struct ivec_dsp **ivec = (struct ivec_dsp **)avail_start; 61 struct ivec_dsp **old = (struct ivec_dsp **)KERNBASE; 62 vaddr_t vavail = avail_start + KERNBASE; 63 int scb_size = dep_call->cpu_scbsz; 64 int i; 65 66 scb = (struct scb *)vavail; 67 scb_vec = (struct ivec_dsp *)(vavail + (scb_size * VAX_NBPG)); 68 69 /* Init the whole SCB with interrupt catchers */ 70 for (i = 0; i < (scb_size * VAX_NBPG)/4; i++) { 71 ivec[i] = &scb_vec[i]; 72 (int)ivec[i] |= 1; /* On istack, please */ 73 scb_vec[i] = idsptch; 74 scb_vec[i].hoppaddr = scb_stray; 75 scb_vec[i].pushlarg = (void *) (i * 4); 76 scb_vec[i].ev = NULL; 77 } 78 /* 79 * Copy all pre-set interrupt vectors to the new SCB. 80 * It is known that these vectors is at KERNBASE from the 81 * beginning, and that if the vector is zero it should call 82 * stray instead. 83 */ 84 for (i = 0; i < 64; i++) 85 if (old[i]) 86 ivec[i] = old[i]; 87 /* Last action: set the SCB */ 88 mtpr(avail_start, PR_SCBB); 89 90 /* Return new avail_start. Also save space for the dispatchers. */ 91 return avail_start + (1 + sizeof(struct ivec_dsp) / sizeof(void *)) 92 * scb_size * VAX_NBPG; 93 }; 94 95 /* 96 * Stray interrupt handler. 97 * This function must _not_ save any registers (in the reg save mask). 98 */ 99 void 100 scb_stray(void *arg) 101 { 102 gotintr = 1; 103 vector = ((int) arg) & ~3; 104 ipl = mfpr(PR_IPL); 105 106 if (cold == 0) { 107 printf("stray interrupt: vector 0x%x, ipl %d\n", vector, ipl); 108 } else if (dep_call->cpu_flags & CPU_RAISEIPL) { 109 struct icallsframe *icf = (void *) __builtin_frame_address(0); 110 111 icf->ica_psl = (icf->ica_psl & ~PSL_IPL) | ipl << 16; 112 } 113 114 mtpr(ipl + 1, PR_IPL); 115 } 116 117 /* 118 * Fake interrupt handler, to fool some bus' autodetect system. 119 * (May I say DW780? :-) 120 */ 121 void 122 scb_fake(int vec, int br) 123 { 124 vector = vec; 125 ipl = br; 126 gotintr = 1; 127 } 128 129 /* 130 * Returns last vector/ipl referenced. Clears vector/ipl after reading. 131 */ 132 int 133 scb_vecref(int *rvec, int *ripl) 134 { 135 int save; 136 137 if (rvec) 138 *rvec = vector; 139 if (ripl) 140 *ripl = ipl; 141 save = gotintr; 142 gotintr = vector = ipl = 0; 143 mtpr(0, PR_IPL); 144 return save; 145 } 146 147 /* 148 * Sets a vector to the specified function. 149 * Arg may not be greater than 63. 150 */ 151 void 152 scb_vecalloc(int vecno, void (*func)(void *), void *arg, 153 int stack, struct evcnt *ev) 154 { 155 struct ivec_dsp *dsp = &scb_vec[vecno / 4]; 156 dsp->hoppaddr = func; 157 dsp->pushlarg = arg; 158 dsp->ev = ev; 159 ((intptr_t *) scb)[vecno/4] = (intptr_t)(dsp) | stack; 160 } 161