You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

misc.c 7.5KB

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