/************************************************************************** MISC Support Routines **************************************************************************/ #include "etherboot.h" /************************************************************************** SLEEP **************************************************************************/ void sleep(int secs) { unsigned long tmo; for (tmo = currticks()+secs*TICKS_PER_SEC; currticks() < tmo; ) /* Nothing */; } /************************************************************************** TWIDDLE **************************************************************************/ void twiddle() { static unsigned long lastticks = 0; static int count=0; static const char tiddles[]="-\\|/"; unsigned long ticks; if ((ticks = currticks()) == lastticks) return; lastticks = ticks; putchar(tiddles[(count++)&3]); putchar('\b'); } /************************************************************************** STRCASECMP (not entirely correct, but this will do for our purposes) **************************************************************************/ int strcasecmp(a,b) char *a, *b; { while (*a && *b && (*a & ~0x20) == (*b & ~0x20)) {a++; b++; } return((*a & ~0x20) - (*b & ~0x20)); } /************************************************************************** PRINTF and friends Formats: %[#]X - 4 bytes long (8 hex digits) %[#]x - 2 bytes int (4 hex digits) - optional # prefixes 0x %b - 1 byte int (2 hex digits) %d - decimal int %c - char %s - string %I - Internet address in x.x.x.x notation Note: width specification not supported **************************************************************************/ static char *do_printf(char *buf, const char *fmt, const int *dp) { register char *p; int alt; char tmp[16]; static const char hex[]="0123456789ABCDEF"; while (*fmt) { if (*fmt == '%') { /* switch() uses more space */ alt = 0; fmt++; if (*fmt == '#') { alt = 1; fmt++; } if (*fmt == 'X') { const long *lp = (const long *)dp; register long h = *lp++; dp = (const int *)lp; if (alt) { *buf++ = '0'; *buf++ = 'x'; } *(buf++) = hex[(h>>28)& 0x0F]; *(buf++) = hex[(h>>24)& 0x0F]; *(buf++) = hex[(h>>20)& 0x0F]; *(buf++) = hex[(h>>16)& 0x0F]; *(buf++) = hex[(h>>12)& 0x0F]; *(buf++) = hex[(h>>8)& 0x0F]; *(buf++) = hex[(h>>4)& 0x0F]; *(buf++) = hex[h& 0x0F]; } if (*fmt == 'x') { register int h = *(dp++); if (alt) { *buf++ = '0'; *buf++ = 'x'; } *(buf++) = hex[(h>>12)& 0x0F]; *(buf++) = hex[(h>>8)& 0x0F]; *(buf++) = hex[(h>>4)& 0x0F]; *(buf++) = hex[h& 0x0F]; } if (*fmt == 'b') { register int h = *(dp++); *(buf++) = hex[(h>>4)& 0x0F]; *(buf++) = hex[h& 0x0F]; } if (*fmt == 'd') { register int dec = *(dp++); p = tmp; if (dec < 0) { *(buf++) = '-'; dec = -dec; } do { *(p++) = '0' + (dec%10); dec = dec/10; } while(dec); while ((--p) >= tmp) *(buf++) = *p; } if (*fmt == 'I') { union { long l; unsigned char c[4]; } u; const long *lp = (const long *)dp; u.l = *lp++; dp = (const int *)lp; buf = sprintf(buf,"%d.%d.%d.%d", u.c[0], u.c[1], u.c[2], u.c[3]); } if (*fmt == 'c') *(buf++) = *(dp++); if (*fmt == 's') { p = (char *)*dp++; while (*p) *(buf++) = *p++; } } else *(buf++) = *fmt; fmt++; } *buf = '\0'; return(buf); } char *sprintf(char *buf, const char *fmt, ...) { return do_printf(buf, fmt, ((const int *)&fmt)+1); } void printf(const char *fmt, ...) { char buf[120], *p; p = buf; do_printf(buf, fmt, ((const int *)&fmt)+1); while (*p) putchar(*p++); } #ifdef IMAGE_MENU /************************************************************************** INET_ATON - Convert an ascii x.x.x.x to binary form **************************************************************************/ int inet_aton(char *p, in_addr *i) { unsigned long ip = 0; int val; if (((val = getdec(&p)) < 0) || (val > 255)) return(0); if (*p != '.') return(0); p++; ip = val; if (((val = getdec(&p)) < 0) || (val > 255)) return(0); if (*p != '.') return(0); p++; ip = (ip << 8) | val; if (((val = getdec(&p)) < 0) || (val > 255)) return(0); if (*p != '.') return(0); p++; ip = (ip << 8) | val; if (((val = getdec(&p)) < 0) || (val > 255)) return(0); i->s_addr = htonl((ip << 8) | val); return(1); } #endif /* IMAGE_MENU */ int getdec(char **ptr) { char *p = *ptr; int ret=0; if ((*p < '0') || (*p > '9')) return(-1); while ((*p >= '0') && (*p <= '9')) { ret = ret*10 + (*p - '0'); p++; } *ptr = p; return(ret); } #define K_RDWR 0x60 /* keyboard data & cmds (read/write) */ #define K_STATUS 0x64 /* keyboard status */ #define K_CMD 0x64 /* keybd ctlr command (write-only) */ #define K_OBUF_FUL 0x01 /* output buffer full */ #define K_IBUF_FUL 0x02 /* input buffer full */ #define KC_CMD_WIN 0xd0 /* read output port */ #define KC_CMD_WOUT 0xd1 /* write output port */ #define KB_SET_A20 0xdf /* enable A20, enable output buffer full interrupt enable data line disable clock line */ #define KB_UNSET_A20 0xdd /* enable A20, enable output buffer full interrupt enable data line disable clock line */ #ifndef IBM_L40 static void empty_8042(void) { unsigned long time; char st; time = currticks() + TICKS_PER_SEC; /* max wait of 1 second */ while ((((st = inb(K_CMD)) & K_OBUF_FUL) || (st & K_IBUF_FUL)) && currticks() < time) inb(K_RDWR); } #endif IBM_L40 /* * Gate A20 for high memory */ void gateA20_set(void) { #ifdef IBM_L40 outb(0x2, 0x92); #else /* IBM_L40 */ empty_8042(); outb(KC_CMD_WOUT, K_CMD); empty_8042(); outb(KB_SET_A20, K_RDWR); empty_8042(); #endif /* IBM_L40 */ } #ifdef TAGGED_IMAGE /* * Unset Gate A20 for high memory - some operating systems (mainly old 16 bit * ones) don't expect it to be set by the boot loader. */ void gateA20_unset(void) { #ifdef IBM_L40 outb(0x0, 0x92); #else /* IBM_L40 */ empty_8042(); outb(KC_CMD_WOUT, K_CMD); empty_8042(); outb(KB_UNSET_A20, K_RDWR); empty_8042(); #endif /* IBM_L40 */ } #endif #ifdef ETHERBOOT32 /* Serial console is only implemented in ETHERBOOT32 for now */ void putchar(int c) { #ifndef ANSIESC if (c == '\n') putchar('\r'); #endif #ifdef CONSOLE_CRT #ifdef ANSIESC handleansi(c); #else putc(c); #endif #endif #ifdef CONSOLE_SERIAL #ifdef ANSIESC if (c == '\n') serial_putc('\r'); #endif serial_putc(c); #endif } /************************************************************************** GETCHAR - Read the next character from the console WITHOUT ECHO **************************************************************************/ int getchar(void) { int c = 256; #if defined CONSOLE_CRT || defined CONSOLE_SERIAL do { #ifdef CONSOLE_CRT if (ischar()) c = getc(); #endif #ifdef CONSOLE_SERIAL if (serial_ischar()) c = serial_getc(); #endif } while (c==256); if (c == '\r') c = '\n'; #endif return c; } int iskey(void) { #ifdef CONSOLE_CRT if (ischar()) return 1; #endif #ifdef CONSOLE_SERIAL if (serial_ischar()) return 1; #endif return 0; } #endif /* ETHERBOOT32 */ /* * Local variables: * c-basic-offset: 8 * End: */ #include #define CPUCLOCK 166 unsigned long currticks(void) { register unsigned long l, h; long long unsigned p; long long unsigned hh,ll; rdtsc(l, h); ll = l, hh = h; p = (ll + hh * 0x100000000LL) * 182 / (CPUCLOCK * 100000LL); return (unsigned)p; }