x86interface.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. #include "x86emu.h"
  2. #include "glue.h"
  3. /*
  4. * This isn't nice, but there are a lot of incompatibilities in the U-Boot and scitech include
  5. * files that this is the only really workable solution.
  6. * Might be cleaned out later.
  7. */
  8. #ifdef DEBUG
  9. #undef DEBUG
  10. #endif
  11. #undef IO_LOGGING
  12. #undef MEM_LOGGING
  13. #ifdef IO_LOGGING
  14. #define LOGIO(port, format, args...) if (dolog(port)) _printf(format , ## args)
  15. #else
  16. #define LOGIO(port, format, args...)
  17. #endif
  18. #ifdef MEM_LOGGIN
  19. #define LOGMEM(format, args...) _printf(format , ## args)
  20. #else
  21. #define LOGMEM(format, args...)
  22. #endif
  23. #ifdef DEBUG
  24. #define PRINTF(format, args...) _printf(format , ## args)
  25. #else
  26. #define PRINTF(format, argc...)
  27. #endif
  28. typedef unsigned char UBYTE;
  29. typedef unsigned short UWORD;
  30. typedef unsigned long ULONG;
  31. typedef char BYTE;
  32. typedef short WORT;
  33. typedef long LONG;
  34. #define EMULATOR_MEM_SIZE (1024*1024)
  35. #define EMULATOR_BIOS_OFFSET 0xC0000
  36. #define EMULATOR_STRAP_OFFSET 0x30000
  37. #define EMULATOR_STACK_OFFSET 0x20000
  38. #define EMULATOR_LOGO_OFFSET 0x40000 /* If you change this, change the strap code, too */
  39. #define VIDEO_BASE (void *)0xFD0B8000
  40. extern char *getenv(char *);
  41. extern int tstc(void);
  42. extern int getc(void);
  43. extern unsigned char video_get_attr(void);
  44. int atoi(char *string)
  45. {
  46. int res = 0;
  47. while (*string>='0' && *string <='9')
  48. {
  49. res *= 10;
  50. res += *string-'0';
  51. string++;
  52. }
  53. return res;
  54. }
  55. void cons_gets(char *buffer)
  56. {
  57. int i = 0;
  58. char c = 0;
  59. buffer[0] = 0;
  60. if (getenv("x86_runthru")) return; /*FIXME: */
  61. while (c != 0x0D && c != 0x0A)
  62. {
  63. while (!tstc());
  64. c = getc();
  65. if (c>=32 && c < 127)
  66. {
  67. buffer[i] = c;
  68. i++;
  69. buffer[i] = 0;
  70. putc(c);
  71. }
  72. else
  73. {
  74. if (c == 0x08)
  75. {
  76. if (i>0) i--;
  77. buffer[i] = 0;
  78. }
  79. }
  80. }
  81. buffer[i] = '\n';
  82. buffer[i+1] = 0;
  83. }
  84. char *bios_date = "08/14/02";
  85. UBYTE model = 0xFC;
  86. UBYTE submodel = 0x00;
  87. static inline UBYTE read_byte(volatile UBYTE* from)
  88. {
  89. int x;
  90. asm volatile ("lbz %0,%1\n eieio" : "=r" (x) : "m" (*from));
  91. return (UBYTE)x;
  92. }
  93. static inline void write_byte(volatile UBYTE *to, int x)
  94. {
  95. asm volatile ("stb %1,%0\n eieio" : "=m" (*to) : "r" (x));
  96. }
  97. static inline UWORD read_word_little(volatile UWORD *from)
  98. {
  99. int x;
  100. asm volatile ("lhbrx %0,0,%1\n eieio" : "=r" (x) : "r" (from), "m" (*from));
  101. return (UWORD)x;
  102. }
  103. static inline UWORD read_word_big(volatile UWORD *from)
  104. {
  105. int x;
  106. asm volatile ("lhz %0,%1\n eieio" : "=r" (x) : "m" (*from));
  107. return (UWORD)x;
  108. }
  109. static inline void write_word_little(volatile UWORD *to, int x)
  110. {
  111. asm volatile ("sthbrx %1,0,%2\n eieio" : "=m" (*to) : "r" (x), "r" (to));
  112. }
  113. static inline void write_word_big(volatile UWORD *to, int x)
  114. {
  115. asm volatile ("sth %1,%0\n eieio" : "=m" (*to) : "r" (x));
  116. }
  117. static inline ULONG read_long_little(volatile ULONG *from)
  118. {
  119. unsigned long x;
  120. asm volatile ("lwbrx %0,0,%1\n eieio" : "=r" (x) : "r" (from), "m"(*from));
  121. return (ULONG)x;
  122. }
  123. static inline ULONG read_long_big(volatile ULONG *from)
  124. {
  125. unsigned long x;
  126. asm volatile ("lwz %0,%1\n eieio" : "=r" (x) : "m" (*from));
  127. return (ULONG)x;
  128. }
  129. static inline void write_long_little(volatile ULONG *to, ULONG x)
  130. {
  131. asm volatile ("stwbrx %1,0,%2\n eieio" : "=m" (*to) : "r" (x), "r" (to));
  132. }
  133. static inline void write_long_big(volatile ULONG *to, ULONG x)
  134. {
  135. asm volatile ("stw %1,%0\n eieio" : "=m" (*to) : "r" (x));
  136. }
  137. static int log_init = 0;
  138. static int log_do = 0;
  139. static int log_low = 0;
  140. int dolog(int port)
  141. {
  142. if (log_init && log_do)
  143. {
  144. if (log_low && port > 0x400) return 0;
  145. return 1;
  146. }
  147. if (!log_init)
  148. {
  149. log_init = 1;
  150. log_do = (getenv("x86_logio") != (char *)0);
  151. log_low = (getenv("x86_loglow") != (char *)0);
  152. if (log_do)
  153. {
  154. if (log_low && port > 0x400) return 0;
  155. return 1;
  156. }
  157. }
  158. return 0;
  159. }
  160. /* Converts an emulator address to a physical address. */
  161. /* Handles all special cases (bios date, model etc), and might need work */
  162. u32 memaddr(u32 addr)
  163. {
  164. /* if (addr >= 0xF0000 && addr < 0xFFFFF) printf("WARNING: Segment F access (0x%x)\n", addr); */
  165. /* printf("MemAddr=%p\n", addr); */
  166. if (addr >= 0xA0000 && addr < 0xC0000)
  167. return 0xFD000000 + addr;
  168. else if (addr >= 0xFFFF5 && addr < 0xFFFFE)
  169. {
  170. return (u32)bios_date+addr-0xFFFF5;
  171. }
  172. else if (addr == 0xFFFFE)
  173. return (u32)&model;
  174. else if (addr == 0xFFFFF)
  175. return (u32)&submodel;
  176. else if (addr >= 0x80000000)
  177. {
  178. /*printf("Warning: High memory access at 0x%x\n", addr); */
  179. return addr;
  180. }
  181. else
  182. return (u32)M.mem_base+addr;
  183. }
  184. u8 A1_rdb(u32 addr)
  185. {
  186. u8 a = read_byte((UBYTE *)memaddr(addr));
  187. LOGMEM("rdb: %x -> %x\n", addr, a);
  188. return a;
  189. }
  190. u16 A1_rdw(u32 addr)
  191. {
  192. u16 a = read_word_little((UWORD *)memaddr(addr));
  193. LOGMEM("rdw: %x -> %x\n", addr, a);
  194. return a;
  195. }
  196. u32 A1_rdl(u32 addr)
  197. {
  198. u32 a = read_long_little((ULONG *)memaddr(addr));
  199. LOGMEM("rdl: %x -> %x\n", addr, a);
  200. return a;
  201. }
  202. void A1_wrb(u32 addr, u8 val)
  203. {
  204. LOGMEM("wrb: %x <- %x\n", addr, val);
  205. write_byte((UBYTE *)memaddr(addr), val);
  206. }
  207. void A1_wrw(u32 addr, u16 val)
  208. {
  209. LOGMEM("wrw: %x <- %x\n", addr, val);
  210. write_word_little((UWORD *)memaddr(addr), val);
  211. }
  212. void A1_wrl(u32 addr, u32 val)
  213. {
  214. LOGMEM("wrl: %x <- %x\n", addr, val);
  215. write_long_little((ULONG *)memaddr(addr), val);
  216. }
  217. X86EMU_memFuncs _A1_mem =
  218. {
  219. A1_rdb,
  220. A1_rdw,
  221. A1_rdl,
  222. A1_wrb,
  223. A1_wrw,
  224. A1_wrl,
  225. };
  226. #define ARTICIAS_PCI_CFGADDR 0xfec00cf8
  227. #define ARTICIAS_PCI_CFGDATA 0xfee00cfc
  228. #define IOBASE 0xFE000000
  229. #define in_byte(from) read_byte( (UBYTE *)port_to_mem(from))
  230. #define in_word(from) read_word_little((UWORD *)port_to_mem(from))
  231. #define in_long(from) read_long_little((ULONG *)port_to_mem(from))
  232. #define out_byte(to, val) write_byte((UBYTE *)port_to_mem(to), val)
  233. #define out_word(to, val) write_word_little((UWORD *)port_to_mem(to), val)
  234. #define out_long(to, val) write_long_little((ULONG *)port_to_mem(to), val)
  235. u32 port_to_mem(int port)
  236. {
  237. if (port >= 0xCFC && port <= 0xCFF) return 0xFEE00000+port;
  238. else if (port >= 0xCF8 && port <= 0xCFB) return 0xFEC00000+port;
  239. else return IOBASE + port;
  240. }
  241. u8 A1_inb(int port)
  242. {
  243. u8 a;
  244. /*if (port == 0x3BA) return 0; */
  245. a = in_byte(port);
  246. LOGIO(port, "inb: %Xh -> %d (%Xh)\n", port, a, a);
  247. return a;
  248. }
  249. u16 A1_inw(int port)
  250. {
  251. u16 a = in_word(port);
  252. LOGIO(port, "inw: %Xh -> %d (%Xh)\n", port, a, a);
  253. return a;
  254. }
  255. u32 A1_inl(int port)
  256. {
  257. u32 a = in_long(port);
  258. LOGIO(port, "inl: %Xh -> %d (%Xh)\n", port, a, a);
  259. return a;
  260. }
  261. void A1_outb(int port, u8 val)
  262. {
  263. LOGIO(port, "outb: %Xh <- %d (%Xh)\n", port, val, val);
  264. /* if (port == 0xCF8) port = 0xCFB;
  265. else if (port == 0xCF9) port = 0xCFA;
  266. else if (port == 0xCFA) port = 0xCF9;
  267. else if (port == 0xCFB) port = 0xCF8;*/
  268. out_byte(port, val);
  269. }
  270. void A1_outw(int port, u16 val)
  271. {
  272. LOGIO(port, "outw: %Xh <- %d (%Xh)\n", port, val, val);
  273. out_word(port, val);
  274. }
  275. void A1_outl(int port, u32 val)
  276. {
  277. LOGIO(port, "outl: %Xh <- %d (%Xh)\n", port, val, val);
  278. out_long(port, val);
  279. }
  280. X86EMU_pioFuncs _A1_pio =
  281. {
  282. A1_inb,
  283. A1_inw,
  284. A1_inl,
  285. A1_outb,
  286. A1_outw,
  287. A1_outl,
  288. };
  289. static int reloced_ops = 0;
  290. void reloc_ops(void *reloc_addr)
  291. {
  292. extern void (*x86emu_optab[256])(u8);
  293. extern void (*x86emu_optab2[256])(u8);
  294. extern void tables_relocate(unsigned int offset);
  295. int i;
  296. unsigned long delta;
  297. if (reloced_ops == 1) return;
  298. reloced_ops = 1;
  299. delta = TEXT_BASE - (unsigned long)reloc_addr;
  300. for (i=0; i<256; i++)
  301. {
  302. x86emu_optab[i] -= delta;
  303. x86emu_optab2[i] -= delta;
  304. }
  305. _A1_mem.rdb = A1_rdb;
  306. _A1_mem.rdw = A1_rdw;
  307. _A1_mem.rdl = A1_rdl;
  308. _A1_mem.wrb = A1_wrb;
  309. _A1_mem.wrw = A1_wrw;
  310. _A1_mem.wrl = A1_wrl;
  311. _A1_pio.inb = A1_inb;
  312. _A1_pio.inw = A1_inw;
  313. _A1_pio.inl = A1_inl;
  314. _A1_pio.outb = A1_outb;
  315. _A1_pio.outw = A1_outw;
  316. _A1_pio.outl = A1_outl;
  317. tables_relocate(delta);
  318. }
  319. #define ANY_KEY(text) \
  320. printf(text); \
  321. while (!tstc());
  322. unsigned char more_strap[] = {
  323. 0xb4, 0x0, 0xb0, 0x2, 0xcd, 0x10,
  324. };
  325. #define MORE_STRAP_BYTES 6 /* Additional bytes of strap code */
  326. unsigned char *done_msg="VGA Initialized\0";
  327. int execute_bios(pci_dev_t gr_dev, void *reloc_addr)
  328. {
  329. extern void bios_init(void);
  330. extern void remove_init_data(void);
  331. extern int video_rows(void);
  332. extern int video_cols(void);
  333. extern int video_size(int, int);
  334. u8 *strap;
  335. unsigned char *logo;
  336. u8 cfg;
  337. int i;
  338. char c;
  339. char *s;
  340. #ifdef EASTEREGG
  341. int easteregg_active = 0;
  342. #endif
  343. char *pal_reset;
  344. u8 *fb;
  345. unsigned char *msg;
  346. unsigned char current_attr;
  347. PRINTF("Trying to remove init data\n");
  348. remove_init_data();
  349. PRINTF("Removed init data from cache, now in RAM\n");
  350. reloc_ops(reloc_addr);
  351. PRINTF("Attempting to run emulator on %02x:%02x:%02x\n",
  352. PCI_BUS(gr_dev), PCI_DEV(gr_dev), PCI_FUNC(gr_dev));
  353. /* Enable compatibility hole for emulator access to frame buffer */
  354. PRINTF("Enabling compatibility hole\n");
  355. enable_compatibility_hole();
  356. /* Allocate memory */
  357. /* FIXME: We shouldn't use this much memory really. */
  358. memset(&M, 0, sizeof(X86EMU_sysEnv));
  359. M.mem_base = malloc(EMULATOR_MEM_SIZE);
  360. M.mem_size = EMULATOR_MEM_SIZE;
  361. if (!M.mem_base)
  362. {
  363. PRINTF("Unable to allocate one megabyte for emulator\n");
  364. return 0;
  365. }
  366. if (attempt_map_rom(gr_dev, M.mem_base + EMULATOR_BIOS_OFFSET) == 0)
  367. {
  368. PRINTF("Error mapping rom. Emulation terminated\n");
  369. return 0;
  370. }
  371. #if 1 /*def DEBUG*/
  372. s = getenv("x86_ask_start");
  373. if (s)
  374. {
  375. printf("Press 'q' to skip initialization, 'd' for dry init\n'i' for i/o session");
  376. while (!tstc());
  377. c = getc();
  378. if (c == 'q') return 0;
  379. if (c == 'd')
  380. {
  381. extern void bios_set_mode(int mode);
  382. bios_set_mode(0x03);
  383. return 0;
  384. }
  385. if (c == 'i') do_inout();
  386. }
  387. #endif
  388. #ifdef EASTEREGG
  389. /* if (tstc())
  390. {
  391. if (getc() == 'c')
  392. {
  393. easteregg_active = 1;
  394. }
  395. }
  396. */
  397. if (getenv("easteregg"))
  398. {
  399. easteregg_active = 1;
  400. }
  401. if (easteregg_active)
  402. {
  403. /* Yay! */
  404. setenv("x86_mode", "1");
  405. setenv("vga_fg_color", "11");
  406. setenv("vga_bg_color", "1");
  407. easteregg_active = 1;
  408. }
  409. #endif
  410. strap = (u8*)M.mem_base + EMULATOR_STRAP_OFFSET;
  411. {
  412. char *m = getenv("x86_mode");
  413. if (m)
  414. {
  415. more_strap[3] = atoi(m);
  416. if (more_strap[3] == 1) video_size(40, 25);
  417. else video_size(80, 25);
  418. }
  419. }
  420. /*
  421. * Poke the strap routine. This might need a bit of extending
  422. * if there is a mode switch involved, i.e. we want to int10
  423. * afterwards to set a different graphics mode, or alternatively
  424. * there might be a different start address requirement if the
  425. * ROM doesn't have an x86 image in its first image.
  426. */
  427. PRINTF("Poking strap...\n");
  428. /* FAR CALL c000:0003 */
  429. *strap++ = 0x9A; *strap++ = 0x03; *strap++ = 0x00;
  430. *strap++ = 0x00; *strap++ = 0xC0;
  431. #if 1
  432. /* insert additional strap code */
  433. for (i=0; i < MORE_STRAP_BYTES; i++)
  434. {
  435. *strap++ = more_strap[i];
  436. }
  437. #endif
  438. /* HALT */
  439. *strap++ = 0xF4;
  440. PRINTF("Setting up logo data\n");
  441. logo = (unsigned char *)M.mem_base + EMULATOR_LOGO_OFFSET;
  442. for (i=0; i<16; i++)
  443. {
  444. *logo++ = 0xFF;
  445. }
  446. /*
  447. * Setup the init parameters.
  448. * Per PCI specs, AH must contain the bus and AL
  449. * must contain the devfn, encoded as (dev<<3)|fn
  450. */
  451. /* Execution starts here */
  452. M.x86.R_CS = SEG(EMULATOR_STRAP_OFFSET);
  453. M.x86.R_IP = OFF(EMULATOR_STRAP_OFFSET);
  454. /* Stack at top of ram */
  455. M.x86.R_SS = SEG(EMULATOR_STACK_OFFSET);
  456. M.x86.R_SP = OFF(EMULATOR_STACK_OFFSET);
  457. /* Input parameters */
  458. M.x86.R_AH = PCI_BUS(gr_dev);
  459. M.x86.R_AL = (PCI_DEV(gr_dev)<<3) | PCI_FUNC(gr_dev);
  460. /* Set the I/O and memory access functions */
  461. X86EMU_setupMemFuncs(&_A1_mem);
  462. X86EMU_setupPioFuncs(&_A1_pio);
  463. /* Enable timer 2 */
  464. cfg = in_byte(0x61); /* Get Misc control */
  465. cfg |= 0x01; /* Enable timer 2 */
  466. out_byte(0x61, cfg); /* output again */
  467. /* Set up the timers */
  468. out_byte(0x43, 0x54);
  469. out_byte(0x41, 0x18);
  470. out_byte(0x43, 0x36);
  471. out_byte(0x40, 0x00);
  472. out_byte(0x40, 0x00);
  473. out_byte(0x43, 0xb6);
  474. out_byte(0x42, 0x31);
  475. out_byte(0x42, 0x13);
  476. /* Init the "BIOS". */
  477. bios_init();
  478. /* Video Card Reset */
  479. out_byte(0x3D8, 0);
  480. out_byte(0x3B8, 1);
  481. (void)in_byte(0x3BA);
  482. (void)in_byte(0x3DA);
  483. out_byte(0x3C0, 0);
  484. out_byte(0x61, 0xFC);
  485. #ifdef DEBUG
  486. s = _getenv("x86_singlestep");
  487. if (s && strcmp(s, "on")==0)
  488. {
  489. PRINTF("Enabling single stepping for debug\n");
  490. X86EMU_trace_on();
  491. }
  492. #endif
  493. /* Ready set go... */
  494. PRINTF("Running emulator\n");
  495. X86EMU_exec();
  496. PRINTF("Done running emulator\n");
  497. /* FIXME: Remove me */
  498. pal_reset = getenv("x86_palette_reset");
  499. if (pal_reset && strcmp(pal_reset, "on") == 0)
  500. {
  501. PRINTF("Palette reset\n");
  502. /*(void)in_byte(0x3da); */
  503. /*out_byte(0x3c0, 0); */
  504. out_byte(0x3C8, 0);
  505. out_byte(0x3C9, 0);
  506. out_byte(0x3C9, 0);
  507. out_byte(0x3C9, 0);
  508. for (i=0; i<254; i++)
  509. {
  510. out_byte(0x3C9, 63);
  511. out_byte(0x3C9, 63);
  512. out_byte(0x3C9, 63);
  513. }
  514. out_byte(0x3c0, 0x20);
  515. }
  516. /* FIXME: remove me */
  517. #ifdef EASTEREGG
  518. if (easteregg_active)
  519. {
  520. extern void video_easteregg(void);
  521. video_easteregg();
  522. }
  523. #endif
  524. /*
  525. current_attr = video_get_attr();
  526. fb = (u8 *)VIDEO_BASE;
  527. for (i=0; i<video_rows()*video_cols()*2; i+=2)
  528. {
  529. *(fb+i) = ' ';
  530. *(fb+i+1) = current_attr;
  531. }
  532. fb = (u8 *)VIDEO_BASE + (video_rows())-1*(video_cols()*2);
  533. for (i=0; i<video_cols(); i++)
  534. {
  535. *(fb + 2*i) = 32;
  536. *(fb + 2*i + 1) = 0x17;
  537. }
  538. msg = done_msg;
  539. while (*msg)
  540. {
  541. *fb = *msg;
  542. fb += 2;
  543. msg ++;
  544. }
  545. */
  546. #ifdef DEBUG
  547. if (getenv("x86_do_inout")) do_inout();
  548. #endif
  549. /*FIXME: dcache_disable(); */
  550. return 1;
  551. }
  552. /* Clean up the x86 mess */
  553. void shutdown_bios(void)
  554. {
  555. /* disable_compatibility_hole(); */
  556. /* Free the memory associated */
  557. free(M.mem_base);
  558. }
  559. int to_int(char *buffer)
  560. {
  561. int base = 0;
  562. int res = 0;
  563. if (*buffer == '$')
  564. {
  565. base = 16;
  566. buffer++;
  567. }
  568. else base = 10;
  569. for (;;)
  570. {
  571. switch(*buffer)
  572. {
  573. case '0' ... '9':
  574. res *= base;
  575. res += *buffer - '0';
  576. break;
  577. case 'A':
  578. case 'a':
  579. res *= base;
  580. res += 10;
  581. break;
  582. case 'B':
  583. case 'b':
  584. res *= base;
  585. res += 11;
  586. break;
  587. case 'C':
  588. case 'c':
  589. res *= base;
  590. res += 12;
  591. break;
  592. case 'D':
  593. case 'd':
  594. res *= base;
  595. res += 13;
  596. break;
  597. case 'E':
  598. case 'e':
  599. res *= base;
  600. res += 14;
  601. break;
  602. case 'F':
  603. case 'f':
  604. res *= base;
  605. res += 15;
  606. break;
  607. default:
  608. return res;
  609. }
  610. buffer++;
  611. }
  612. return res;
  613. }
  614. void one_arg(char *buffer, int *a)
  615. {
  616. while (*buffer && *buffer != '\n')
  617. {
  618. if (*buffer == ' ') buffer++;
  619. else break;
  620. }
  621. *a = to_int(buffer);
  622. }
  623. void two_args(char *buffer, int *a, int *b)
  624. {
  625. while (*buffer && *buffer != '\n')
  626. {
  627. if (*buffer == ' ') buffer++;
  628. else break;
  629. }
  630. *a = to_int(buffer);
  631. while (*buffer && *buffer != '\n')
  632. {
  633. if (*buffer != ' ') buffer++;
  634. else break;
  635. }
  636. while (*buffer && *buffer != '\n')
  637. {
  638. if (*buffer == ' ') buffer++;
  639. else break;
  640. }
  641. *b = to_int(buffer);
  642. }
  643. void do_inout(void)
  644. {
  645. char buffer[256];
  646. char *arg1, *arg2;
  647. int a,b;
  648. printf("In/Out Session\nUse 'i[bwl]' for in, 'o[bwl]' for out and 'q' to quit\n");
  649. do
  650. {
  651. cons_gets(buffer);
  652. printf("\n");
  653. *arg1 = buffer;
  654. while (*arg1 != ' ' ) arg1++;
  655. while (*arg1 == ' ') arg1++;
  656. if (buffer[0] == 'i')
  657. {
  658. one_arg(buffer+2, &a);
  659. switch (buffer[1])
  660. {
  661. case 'b':
  662. printf("in_byte(%xh) = %xh\n", a, A1_inb(a));
  663. break;
  664. case 'w':
  665. printf("in_word(%xh) = %xh\n", a, A1_inw(a));
  666. break;
  667. case 'l':
  668. printf("in_dword(%xh) = %xh\n", a, A1_inl(a));
  669. break;
  670. default:
  671. printf("Invalid length '%c'\n", buffer[1]);
  672. break;
  673. }
  674. }
  675. else if (buffer[0] == 'o')
  676. {
  677. two_args(buffer+2, &a, &b);
  678. switch (buffer[1])
  679. {
  680. case 'b':
  681. printf("out_byte(%d, %d)\n", a, b);
  682. A1_outb(a,b);
  683. break;
  684. case 'w':
  685. printf("out_word(%d, %d)\n", a, b);
  686. A1_outw(a, b);
  687. break;
  688. case 'l':
  689. printf("out_long(%d, %d)\n", a, b);
  690. A1_outl(a, b);
  691. break;
  692. default:
  693. printf("Invalid length '%c'\n", buffer[1]);
  694. break;
  695. }
  696. } else if (buffer[0] == 'q') return;
  697. } while (1);
  698. }