Initial revision
[etherboot.git] / contrib / baremetal / misc.c
1 /**************************************************************************
2 MISC Support Routines
3 **************************************************************************/
4
5 #include "etherboot.h"
6
7 /**************************************************************************
8 SLEEP
9 **************************************************************************/
10 void sleep(int secs)
11 {
12         unsigned long tmo;
13
14         for (tmo = currticks()+secs*TICKS_PER_SEC; currticks() < tmo; )
15                 /* Nothing */;
16 }
17
18 /**************************************************************************
19 TWIDDLE
20 **************************************************************************/
21 void twiddle()
22 {
23         static unsigned long lastticks = 0;
24         static int count=0;
25         static const char tiddles[]="-\\|/";
26         unsigned long ticks;
27         if ((ticks = currticks()) == lastticks)
28                 return;
29         lastticks = ticks;
30         putchar(tiddles[(count++)&3]);
31         putchar('\b');
32 }
33
34 /**************************************************************************
35 STRCASECMP (not entirely correct, but this will do for our purposes)
36 **************************************************************************/
37 int strcasecmp(a,b)
38         char *a, *b;
39 {
40         while (*a && *b && (*a & ~0x20) == (*b & ~0x20)) {a++; b++; }
41         return((*a & ~0x20) - (*b & ~0x20));
42 }
43
44 /**************************************************************************
45 PRINTF and friends
46
47         Formats:
48                 %[#]X   - 4 bytes long (8 hex digits)
49                 %[#]x   - 2 bytes int (4 hex digits)
50                         - optional # prefixes 0x
51                 %b      - 1 byte int (2 hex digits)
52                 %d      - decimal int
53                 %c      - char
54                 %s      - string
55                 %I      - Internet address in x.x.x.x notation
56         Note: width specification not supported
57 **************************************************************************/
58 static char *do_printf(char *buf, const char *fmt, const int *dp)
59 {
60         register char *p;
61         int alt;
62         char tmp[16];
63         static const char hex[]="0123456789ABCDEF";
64
65         while (*fmt) {
66                 if (*fmt == '%') {      /* switch() uses more space */
67                         alt = 0;
68                         fmt++;
69                         if (*fmt == '#') {
70                                 alt = 1;
71                                 fmt++;
72                         }
73                         if (*fmt == 'X') {
74                                 const long *lp = (const long *)dp;
75                                 register long h = *lp++;
76                                 dp = (const int *)lp;
77                                 if (alt) {
78                                         *buf++ = '0';
79                                         *buf++ = 'x';
80                                 }
81                                 *(buf++) = hex[(h>>28)& 0x0F];
82                                 *(buf++) = hex[(h>>24)& 0x0F];
83                                 *(buf++) = hex[(h>>20)& 0x0F];
84                                 *(buf++) = hex[(h>>16)& 0x0F];
85                                 *(buf++) = hex[(h>>12)& 0x0F];
86                                 *(buf++) = hex[(h>>8)& 0x0F];
87                                 *(buf++) = hex[(h>>4)& 0x0F];
88                                 *(buf++) = hex[h& 0x0F];
89                         }
90                         if (*fmt == 'x') {
91                                 register int h = *(dp++);
92                                 if (alt) {
93                                         *buf++ = '0';
94                                         *buf++ = 'x';
95                                 }
96                                 *(buf++) = hex[(h>>12)& 0x0F];
97                                 *(buf++) = hex[(h>>8)& 0x0F];
98                                 *(buf++) = hex[(h>>4)& 0x0F];
99                                 *(buf++) = hex[h& 0x0F];
100                         }
101                         if (*fmt == 'b') {
102                                 register int h = *(dp++);
103                                 *(buf++) = hex[(h>>4)& 0x0F];
104                                 *(buf++) = hex[h& 0x0F];
105                         }
106                         if (*fmt == 'd') {
107                                 register int dec = *(dp++);
108                                 p = tmp;
109                                 if (dec < 0) {
110                                         *(buf++) = '-';
111                                         dec = -dec;
112                                 }
113                                 do {
114                                         *(p++) = '0' + (dec%10);
115                                         dec = dec/10;
116                                 } while(dec);
117                                 while ((--p) >= tmp) *(buf++) = *p;
118                         }
119                         if (*fmt == 'I') {
120                                 union {
121                                         long            l;
122                                         unsigned char   c[4];
123                                 } u;
124                                 const long *lp = (const long *)dp;
125                                 u.l = *lp++;
126                                 dp = (const int *)lp;
127                                 buf = sprintf(buf,"%d.%d.%d.%d",
128                                         u.c[0], u.c[1], u.c[2], u.c[3]);
129                         }
130                         if (*fmt == 'c')
131                                 *(buf++) = *(dp++);
132                         if (*fmt == 's') {
133                                 p = (char *)*dp++;
134                                 while (*p) *(buf++) = *p++;
135                         }
136                 } else *(buf++) = *fmt;
137                 fmt++;
138         }
139         *buf = '\0';
140         return(buf);
141 }
142
143 char *sprintf(char *buf, const char *fmt, ...)
144 {
145         return do_printf(buf, fmt, ((const int *)&fmt)+1);
146 }
147
148 void printf(const char *fmt, ...)
149 {
150         char buf[120], *p;
151
152         p = buf;
153         do_printf(buf, fmt, ((const int *)&fmt)+1);
154         while (*p) putchar(*p++);
155 }
156
157 #ifdef  IMAGE_MENU
158 /**************************************************************************
159 INET_ATON - Convert an ascii x.x.x.x to binary form
160 **************************************************************************/
161 int inet_aton(char *p, in_addr *i)
162 {
163         unsigned long ip = 0;
164         int val;
165         if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
166         if (*p != '.') return(0);
167         p++;
168         ip = val;
169         if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
170         if (*p != '.') return(0);
171         p++;
172         ip = (ip << 8) | val;
173         if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
174         if (*p != '.') return(0);
175         p++;
176         ip = (ip << 8) | val;
177         if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
178         i->s_addr = htonl((ip << 8) | val);
179         return(1);
180 }
181
182 #endif  /* IMAGE_MENU */
183
184 int getdec(char **ptr)
185 {
186         char *p = *ptr;
187         int ret=0;
188         if ((*p < '0') || (*p > '9')) return(-1);
189         while ((*p >= '0') && (*p <= '9')) {
190                 ret = ret*10 + (*p - '0');
191                 p++;
192         }
193         *ptr = p;
194         return(ret);
195 }
196
197 #define K_RDWR          0x60            /* keyboard data & cmds (read/write) */
198 #define K_STATUS        0x64            /* keyboard status */
199 #define K_CMD           0x64            /* keybd ctlr command (write-only) */
200
201 #define K_OBUF_FUL      0x01            /* output buffer full */
202 #define K_IBUF_FUL      0x02            /* input buffer full */
203
204 #define KC_CMD_WIN      0xd0            /* read  output port */
205 #define KC_CMD_WOUT     0xd1            /* write output port */
206 #define KB_SET_A20      0xdf            /* enable A20,
207                                            enable output buffer full interrupt
208                                            enable data line
209                                            disable clock line */
210 #define KB_UNSET_A20    0xdd            /* enable A20,
211                                            enable output buffer full interrupt
212                                            enable data line
213                                            disable clock line */
214 #ifndef IBM_L40
215 static void empty_8042(void)
216 {
217         unsigned long time;
218         char st;
219
220         time = currticks() + TICKS_PER_SEC;     /* max wait of 1 second */
221         while ((((st = inb(K_CMD)) & K_OBUF_FUL) ||
222                (st & K_IBUF_FUL)) &&
223                currticks() < time)
224                 inb(K_RDWR);
225 }
226 #endif  IBM_L40
227
228 /*
229  * Gate A20 for high memory
230  */
231 void gateA20_set(void)
232 {
233 #ifdef  IBM_L40
234         outb(0x2, 0x92);
235 #else   /* IBM_L40 */
236         empty_8042();
237         outb(KC_CMD_WOUT, K_CMD);
238         empty_8042();
239         outb(KB_SET_A20, K_RDWR);
240         empty_8042();
241 #endif  /* IBM_L40 */
242 }
243
244 #ifdef  TAGGED_IMAGE
245 /*
246  * Unset Gate A20 for high memory - some operating systems (mainly old 16 bit
247  * ones) don't expect it to be set by the boot loader.
248  */
249 void gateA20_unset(void)
250 {
251 #ifdef  IBM_L40
252         outb(0x0, 0x92);
253 #else   /* IBM_L40 */
254         empty_8042();
255         outb(KC_CMD_WOUT, K_CMD);
256         empty_8042();
257         outb(KB_UNSET_A20, K_RDWR);
258         empty_8042();
259 #endif  /* IBM_L40 */
260 }
261 #endif
262
263 #ifdef  ETHERBOOT32
264 /* Serial console is only implemented in ETHERBOOT32 for now */
265 void
266 putchar(int c)
267 {
268 #ifndef ANSIESC
269         if (c == '\n')
270                 putchar('\r');
271 #endif
272
273 #ifdef  CONSOLE_CRT
274 #ifdef  ANSIESC
275         handleansi(c);
276 #else
277         putc(c);
278 #endif
279 #endif
280 #ifdef  CONSOLE_SERIAL
281 #ifdef  ANSIESC
282         if (c == '\n')
283                 serial_putc('\r');
284 #endif
285         serial_putc(c);
286 #endif
287 }
288
289 /**************************************************************************
290 GETCHAR - Read the next character from the console WITHOUT ECHO
291 **************************************************************************/
292 int
293 getchar(void)
294 {
295         int c = 256;
296
297 #if defined CONSOLE_CRT || defined CONSOLE_SERIAL
298         do {
299 #ifdef  CONSOLE_CRT
300                 if (ischar())
301                         c = getc();
302 #endif
303 #ifdef  CONSOLE_SERIAL
304                 if (serial_ischar())
305                         c = serial_getc();
306 #endif
307         } while (c==256);
308         if (c == '\r')
309                 c = '\n';
310 #endif          
311         return c;
312 }
313
314 int
315 iskey(void)
316 {
317 #ifdef  CONSOLE_CRT
318         if (ischar())
319                 return 1;
320 #endif
321 #ifdef  CONSOLE_SERIAL
322         if (serial_ischar())
323                 return 1;
324 #endif
325         return 0;
326 }
327 #endif  /* ETHERBOOT32 */
328
329 /*
330  * Local variables:
331  *  c-basic-offset: 8
332  * End:
333  */
334  
335 #include <asm/msr.h>
336
337 #define CPUCLOCK 166
338
339 unsigned long currticks(void)
340 {
341     register unsigned long l, h;
342     long long unsigned p;
343     long long unsigned hh,ll;
344     
345     rdtsc(l, h);
346     ll = l, hh = h;
347
348     p = (ll + hh * 0x100000000LL) * 182 / (CPUCLOCK * 100000LL);
349     return (unsigned)p;
350 }
351