1 /* $NetBSD: systemsw.c,v 1.6 2002/06/04 05:42:41 simonb Exp $ */ 2 3 /* 4 * Copyright 2000, 2001 5 * Broadcom Corporation. All rights reserved. 6 * 7 * This software is furnished under license and may be used and copied only 8 * in accordance with the following terms and conditions. Subject to these 9 * conditions, you may download, copy, install, use, modify and distribute 10 * modified or unmodified copies of this software in source and/or binary 11 * form. No title or ownership is transferred hereby. 12 * 13 * 1) Any source code used, modified or distributed must reproduce and 14 * retain this copyright notice and list of conditions as they appear in 15 * the source file. 16 * 17 * 2) No right is granted to use any trade name, trademark, or logo of 18 * Broadcom Corporation. Neither the "Broadcom Corporation" name nor any 19 * trademark or logo of Broadcom Corporation may be used to endorse or 20 * promote products derived from this software without the prior written 21 * permission of Broadcom Corporation. 22 * 23 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED 24 * WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR 26 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE 27 * FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE 28 * LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 * OR OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/kernel.h> 39 40 #include <mips/locore.h> 41 #include <machine/intr.h> 42 #include <machine/systemsw.h> 43 44 /* trivial functions for function switch */ 45 static void clock_init_triv(void *); 46 static uint32_t clkread_triv(void); 47 static void cpu_intr_triv(uint32_t, uint32_t, uint32_t, uint32_t); 48 static void cpu_setsoftintr_triv(void); 49 static void delay_triv(u_long); 50 static void inittodr_triv(void *, time_t); 51 static void microtime_triv(struct timeval *); 52 static void resettodr_triv(void *); 53 54 /* system function switch */ 55 struct systemsw systemsw = { 56 cpu_intr_triv, 57 cpu_setsoftintr_triv, 58 microtime_triv, 59 clkread_triv, 60 delay_triv, 61 62 NULL, /* clock intr arg */ 63 clock_init_triv, 64 65 NULL, /* statclock arg */ 66 NULL, /* s_statclock_init: dflt no-op */ 67 NULL, /* s_statclock_setrate: dflt no-op */ 68 69 NULL, /* todr functions arg */ 70 inittodr_triv, 71 resettodr_triv, 72 NULL, /* intr_establish */ 73 }; 74 75 int 76 system_set_clockfns(void *arg, void (*init)(void *)) 77 { 78 79 if (systemsw.s_clock_init != clock_init_triv) 80 return 1; 81 systemsw.s_clock_arg = arg; 82 systemsw.s_clock_init = init; 83 return 0; 84 } 85 86 int 87 system_set_todrfns(void *arg, void (*init)(void *, time_t), 88 void (*reset)(void *)) 89 { 90 91 if (systemsw.s_inittodr != inittodr_triv || 92 systemsw.s_resettodr != resettodr_triv) 93 return 1; 94 systemsw.s_todr_arg = arg; 95 systemsw.s_inittodr = init; 96 systemsw.s_resettodr = reset; 97 return 0; 98 } 99 100 101 /* trivial microtime() implementation */ 102 static void 103 microtime_triv(struct timeval *tvp) 104 { 105 int s; 106 static struct timeval lasttime; 107 108 s = splclock(); 109 *tvp = time; 110 111 if (systemsw.s_clkread) 112 tvp->tv_usec += systemsw.s_clkread(); 113 114 if (tvp->tv_usec >= 1000000) { 115 tvp->tv_usec -= 1000000; 116 tvp->tv_sec++; 117 } 118 119 if (tvp->tv_sec == lasttime.tv_sec && 120 tvp->tv_usec <= lasttime.tv_usec && 121 (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) { 122 tvp->tv_sec++; 123 tvp->tv_usec -= 1000000; 124 } 125 lasttime = *tvp; 126 127 splx(s); 128 } 129 130 static uint32_t 131 clkread_triv(void) 132 { 133 uint32_t res, count; 134 135 count = mips3_cp0_count_read(); 136 MIPS_COUNT_TO_MHZ(curcpu(), count, res); 137 return (res); 138 } 139 140 141 /* trivial delay() implementation */ 142 static void 143 delay_triv(u_long n) 144 { 145 u_long i; 146 long divisor = curcpu()->ci_divisor_delay; 147 148 while (n-- > 0) 149 for (i = divisor; i > 0; i--) 150 ; 151 } 152 153 static void 154 cpu_intr_triv(uint32_t status, uint32_t cause, uint32_t pc, uint32_t ipending) 155 { 156 157 panic("cpu_intr_triv"); 158 } 159 160 void 161 cpu_setsoftintr_triv(void) 162 { 163 panic("cpu_setsoftintr_triv"); 164 } 165 166 void 167 cpu_intr(uint32_t status, uint32_t cause, uint32_t pc, uint32_t ipending) 168 { 169 170 (*systemsw.s_cpu_intr)(status, cause, pc, ipending); 171 } 172 173 void 174 microtime(struct timeval *tvp) 175 { 176 177 (*systemsw.s_microtime)(tvp); 178 } 179 180 static void 181 clock_init_triv(void *arg) 182 { 183 184 panic("clock_init_triv"); 185 } 186 187 static void 188 inittodr_triv(void *arg, time_t t) 189 { 190 191 time.tv_sec = t; 192 } 193 194 static void 195 resettodr_triv(void *arg) 196 { 197 198 /* do nothing */ 199 } 200 201 void 202 cpu_initclocks(void) 203 { 204 205 (*systemsw.s_clock_init)(systemsw.s_clock_arg); 206 207 if (systemsw.s_statclock_init != NULL) 208 (*systemsw.s_statclock_init)(systemsw.s_statclock_arg); 209 210 /* 211 * ``Disable'' the compare interrupt by setting it to it's largest 212 * value. The counter will be reset to 0 every hz. This is used 213 * for microtime. 214 */ 215 mips3_cp0_compare_write(~(uint32_t)0); 216 mips3_cp0_count_write(0); 217 } 218 219 void 220 setstatclockrate(int hzrate) 221 { 222 223 if (systemsw.s_statclock_setrate != NULL) 224 (*systemsw.s_statclock_setrate)(systemsw.s_statclock_arg, 225 hzrate); 226 } 227 228 void 229 inittodr(time_t t) 230 { 231 232 (*systemsw.s_inittodr)(systemsw.s_todr_arg, t); 233 } 234 235 void 236 resettodr(void) 237 { 238 239 (*systemsw.s_resettodr)(systemsw.s_todr_arg); 240 } 241