1 /* $NetBSD: scb.c,v 1.19 2017/05/22 16:53:05 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 * 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 * Routines for dynamic allocation/release of SCB vectors. 28 */ 29 30 #include <sys/cdefs.h> 31 __KERNEL_RCSID(0, "$NetBSD: scb.c,v 1.19 2017/05/22 16:53:05 ragge Exp $"); 32 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/cpu.h> 36 #include <sys/device.h> 37 #include <sys/kernel.h> 38 39 #include <machine/trap.h> 40 #include <machine/scb.h> 41 #include <machine/frame.h> 42 #include <machine/sid.h> 43 44 struct scb *scb; 45 struct ivec_dsp *scb_vec; 46 47 void scb_stray(void *); 48 static volatile int vector, ipl, gotintr; 49 50 /* 51 * Generates a new SCB. 52 */ 53 paddr_t 54 scb_init(paddr_t avail_start) 55 { 56 struct ivec_dsp **ivec = (struct ivec_dsp **)avail_start; 57 struct ivec_dsp **old = (struct ivec_dsp **)KERNBASE; 58 vaddr_t vavail = avail_start + KERNBASE; 59 int scb_size = dep_call->cpu_scbsz; 60 int i; 61 62 scb = (struct scb *)vavail; 63 scb_vec = (struct ivec_dsp *)(vavail + (scb_size * VAX_NBPG)); 64 65 /* Init the whole SCB with interrupt catchers */ 66 for (i = 0; i < (scb_size * VAX_NBPG)/4; i++) { 67 ivec[i] = &scb_vec[i]; 68 *(uintptr_t *)&ivec[i] |= 1; /* On istack, please */ 69 scb_vec[i] = idsptch; 70 scb_vec[i].hoppaddr = scb_stray; 71 scb_vec[i].pushlarg = (void *) (i * 4); 72 scb_vec[i].ev = NULL; 73 } 74 /* 75 * Copy all pre-set interrupt vectors to the new SCB. 76 * It is known that these vectors is at KERNBASE from the 77 * beginning, and that if the vector is zero it should call 78 * stray instead. 79 */ 80 for (i = 0; i < 64; i++) 81 if (old[i]) 82 ivec[i] = old[i]; 83 /* Last action: set the SCB */ 84 mtpr(avail_start, PR_SCBB); 85 86 /* Return new avail_start. Also save space for the dispatchers. */ 87 return avail_start + (1 + sizeof(struct ivec_dsp) / sizeof(void *)) 88 * scb_size * VAX_NBPG; 89 }; 90 91 /* 92 * Stray interrupt handler. 93 * This function must _not_ save any registers (in the reg save mask). 94 */ 95 void 96 scb_stray(void *arg) 97 { 98 gotintr = 1; 99 vector = ((int) arg) & ~3; 100 ipl = mfpr(PR_IPL); 101 102 if (cold == 0) { 103 printf("stray interrupt: vector 0x%x, ipl %d\n", vector, ipl); 104 } else if (dep_call->cpu_flags & CPU_RAISEIPL) { 105 struct icallsframe *icf = (void *) __builtin_frame_address(0); 106 107 icf->ica_psl = (icf->ica_psl & ~PSL_IPL) | ipl << 16; 108 } 109 110 mtpr(ipl + 1, PR_IPL); 111 } 112 113 /* 114 * Fake interrupt handler, to fool some bus' autodetect system. 115 * (May I say DW780? :-) 116 */ 117 void 118 scb_fake(int vec, int br) 119 { 120 vector = vec; 121 ipl = br; 122 gotintr = 1; 123 } 124 125 /* 126 * Returns last vector/ipl referenced. Clears vector/ipl after reading. 127 */ 128 int 129 scb_vecref(int *rvec, int *ripl) 130 { 131 int save; 132 133 if (rvec) 134 *rvec = vector; 135 if (ripl) 136 *ripl = ipl; 137 save = gotintr; 138 gotintr = vector = ipl = 0; 139 mtpr(0, PR_IPL); 140 return save; 141 } 142 143 /* 144 * Sets a vector to the specified function. 145 * Arg may not be greater than 63. 146 */ 147 void 148 scb_vecalloc(int vecno, void (*func)(void *), void *arg, 149 int stack, struct evcnt *ev) 150 { 151 struct ivec_dsp *dsp = &scb_vec[vecno / 4]; 152 dsp->hoppaddr = func; 153 dsp->pushlarg = arg; 154 dsp->ev = ev; 155 ((intptr_t *) scb)[vecno/4] = (intptr_t)(dsp) | stack; 156 } 157