home *** CD-ROM | disk | FTP | other *** search
/ Black Box 4 / BlackBox.cdr / progc / djdoc106.arj / INTERNAL.DOC < prev    next >
Text File  |  1992-03-11  |  15KB  |  433 lines

  1. /* History:390,1 */
  2. This is the file internals.doc
  3.  
  4. Contents:
  5.  
  6. * Methods that go32 uses to perform the DOS extender function.
  7.  
  8. * How to add new graphics card support.
  9.  
  10.  
  11.  
  12. Note: This file includes PC graphics characters in some illustrations.
  13. It is intended to be viewed via PC or PC compatible printer.  If you are
  14. viewing it from Unix and the illustrations look strange, this is why.
  15.  
  16.  
  17.  
  18.  
  19.  
  20.  
  21.  
  22.  
  23.  
  24. Methods:
  25.  
  26. Go32 contains three basic parts:
  27.  
  28.  * a real-mode control program (code/data segments)
  29.  * a 16-bit protected mode interface section
  30.  * a 32-bit flat program arena, loaded from a.out file
  31.  
  32. The interface section provides Turbo-C routines that acces memory in the
  33. 32-bit arena, as well as a method for executing code in protected mode.
  34.  
  35.  
  36.  
  37.  
  38. Initialization:
  39.  
  40. Control.c is the starting point for the extender.  main() is here.  This
  41. is where all the system tables are created, like the GDT and TSSs.
  42.  
  43. TABLES.ASM contains the stubs for the exception handlers, and the
  44. exception tasks.  The IDT is mass-loaded by main() to point to these
  45. stubs, then the oddball exceptions are moved (ivec7, page fault handler, etc).
  46.  
  47.  
  48.  
  49. control assist functions:
  50.  
  51. utils.c, doutils.asm
  52.  
  53. All control assist functions use linear/physical addresses, not segment
  54. addresses!
  55.  
  56. The control assist functions allow the controller to read/write memory
  57. from real mode into the 32-bit arena.  The available functions are:
  58.  
  59.     word32    peek32(vaddr)
  60.         poke32(vaddr, word32)
  61.     word16    peek16(vaddr)
  62.         poke16(vaddr, word16)
  63.     word8    peek8(vaddr)
  64.         poke8(vaddr, word8)
  65.         memget(vaddr, void *, length)
  66.         memput(vaddr, void *, length)
  67.         zero32(vaddr) /* always 4K regions */
  68.  
  69.  
  70.  
  71.  
  72.  
  73. The main focal point for process control is a TSS structure with some
  74. additional fields at the end.  These additional fields record information
  75. such as CR2, the exception number, a temporary stack, and other
  76. information deduced by the extender.  There are many TSSs used:
  77.  
  78.  * c_tss is the control tasks.  This is the "real mode" task that is
  79.    initially switched to as part of entering protected mode.  A switch to
  80.    this task returns you to real mode.
  81.  
  82.  * a_tss is the arena's task state.  By using the fields in this
  83.    structure, the extender can get or change register contents.  When the
  84.    arena task causes an exception, the state of the task is recorded here
  85.    for the extender to use in servicing the exception.
  86.  
  87.  * o_tss is the task structure used by the utilities ("other" routines).
  88.  
  89.  * p_tss is the task switched to when a page fault occurs.
  90.  
  91.  * f_tss is the task used by the page fault handler when it calls the
  92.    utilities.  This is in case the utilites cause a page fault.
  93.  
  94.  * i_tss is the task most exceptions switch to.  Exception 7 is
  95.    redirected to a protected mode handler if a 387 is present.  Each
  96.    exception has a stub (in tables.asm) that saves the exception number
  97.    and jumps to this task.  This task just un-does the effects of the
  98.    interrupt, so the TSS points to the exception and not the exception
  99.    handler, and then returns to real mode.
  100.  
  101. The variable tss_ptr points to the currently active TSS.  This is the one
  102. the debugger uses when exceptions happen.
  103.  
  104.  
  105.  
  106.  
  107.  
  108. Running protected mode code:
  109.  
  110. MSWITCH.ASM is the gateway into the protected mode arena.  *ALL* accesses
  111. to protected mode go into go32() and come out through it.  A20 switching
  112. is also handled here.
  113.  
  114. go32() does a number of functions:
  115.  
  116. * Set the active task gate in the GDT to refer to tss_ptr.
  117. * Disable interrupts for all tasks except a_tss.
  118. * Clear all the TaskBusy bits for all tasks, to prevent exceptions.
  119. * Clear the exception flag (set when an exception occurs).
  120. * save the real mode stack state.
  121. * Disable sensitive interrupts (like the hard drive).  IRQ0-7 remain
  122.   enabled.
  123. * Make sure A20 is enabled (a20gate was a stupid idea).
  124. * Set up the GDT and IDT registers.
  125. * Go into protected mode.
  126. * Load the debug registers from _dr[].
  127. * Enable the paging hardware
  128. * Load the 387 state from the structure "npx", if the state had been
  129.   stored there (by an exception handler or the "npx" instruction).
  130. * Load the task register to point to c_tss
  131. * Switch to tss_ptr's task
  132.  
  133. . . . wait for switch back to c_tss . . .
  134.  
  135. * Save DR6 in _dr6 (debug status).
  136. * Reset IDT and stack
  137. * Re-enable interrupts
  138. * Handle certain time-critical exceptions, like timer tick and COM ports.
  139.   Keyboard and NPX interrupts, as well as all other exceptions, are
  140.   handled by exception_handler().
  141. * return to caller.
  142.  
  143.  
  144. The basic flow of control looks like this (in to top, out from bottom):
  145.  
  146.         ╔═══════════════════════╗
  147.         ║   Start - Real Mode   ║
  148.         ╚═══════════╤═══════════╝
  149.                 │    ┌───────────────────────────────────────┐
  150.         ╔═══════════╧═══╧═══════╗                │
  151.         ║ Protected Mode, c_tss ║                │
  152.         ╚═══════════╤═══════╤═══╝                │
  153.                 │        └────────┐                │
  154.         ╔═══════════╧═══════════╗  ╔═╧═════════════════════╗    │
  155.         ║    tss_ptr, a_tss     ║  ║ tss_ptr, o_tss/f_tss  ║    │
  156.         ╚═══╤═══════════════╤═══╝  ╚═╤═════════════════════╝    │
  157.             │            │         │                │
  158. ╔═══════════════════╧═══╗    ╔═══╧════════╧══════════╗        │
  159. ║       Exception       ║    ║   Page Fault, p_tss   ║        │
  160. ╚═══════════╤═══════════╝    ╚═══════╤═══════╤═══════╝        │
  161. ╔═══════════╧═══════════╗        │    ╔══╧═════════════════╗    │
  162. ║         i_tss*        ║        │    ║  Graphics handler  ║    │
  163. ╚═══════════╤═══════════╝        │    ╚══════════════════╤═╝    │
  164.             └──────────┐    ┌───────┘            └───────┘
  165.         ╔══════╧════════╧═══════╗
  166.         ║   Back to Real Mode   ║
  167.         ╚═══════════════════════╝
  168.  
  169.  
  170. * some hardware interrupts have their own tss's
  171.  
  172.  
  173.  
  174.  
  175. GDT entries:
  176.  
  177. * mandatory zero entry
  178. * GDT
  179. * IDT
  180. * real-mode code segment (for utilities)
  181. * real-mode data segment (for utilities)
  182. * real-mode code, but 32-bit (unused)
  183. * real-mode data, but 32-bit (unused)
  184. * core.  32-bits, mapped 1:1 with first 1M of memory.  Used to access screen.
  185. * arena code.  32-bit, starts at 0x10000000.
  186. * arena data.  32-bit, starts at 0x10000000.
  187. * c_tss task segment
  188. * a_tss task segment - changes to reflect what tss_ptr points to
  189. * p_tss task segment
  190. * i_tss task segment
  191. * graphics driver routines
  192. * real code 32-bits, was used for NPX routines (unused)
  193. * VCPI entries
  194. * TSS's for some hardware interrupts
  195.  
  196.  
  197.  
  198.  
  199.  
  200. Mappings:
  201.  
  202. * First 1M mapped 1:1 to linear address 0x0000000
  203. * Arena segments start at 0x10000000.  All utilities must be
  204.   adjusted to reflect this by adding the constant ARENA to addresses.
  205. * Symbol space is at 0xa000000 (used by debug32)
  206. * Core (0-1M) remapped to 0xF0000000 (0xE0000000 to arena)
  207. * VGA 256c paging at 0xE0000000 (0xD0000000 to arena)
  208.     Three 1M pages:
  209.       0xD0000000 - 0xD00FFFFF - read/write
  210.       0xD0100000 - 0xD01FFFFF - read only
  211.       0xD0200000 - 0xD02FFFFF - write only
  212.  
  213.  
  214.  
  215.  
  216.  
  217. Page management:
  218.  
  219. Valloc.c keeps track of what physical pages are available.  Pages are
  220. accessed via valloc() and vfree(), which use page *numbers* (not addresses).
  221. Up to 128M of RAM can be managed by this routine.  If valloc() is called
  222. and there aren't any free pages, page_out() is called to free one up.
  223. The application has the option of choosing memory from the lower 640K or
  224. above 1M.  The page directory and page tables are kept in low memory so
  225. the real mode functions can access them without going into protected mode.
  226.  
  227. The page table entries include extra information about the status of a
  228. given page, whether it is swappable, swapped, or uninitialized.
  229.  
  230. Paging.c keeps track of the page tables and directory.  It reads the
  231. a.out file and sets up various areas of memory (text, data, stack, etc).
  232. When page faults occur, page_in() pages in memory from disk, swap, or
  233. available memory (for bss and sbrk()).  It detects accesses outside the
  234. designated areas to flag a protection violation.  Page_out() selects a
  235. present page and swaps it to the swap file, to make space for an incoming
  236. page.
  237.  
  238. Dalloc.c keeps track of the disk-based swap space, through dalloc() and
  239. dfree().  Up to 128M of swap space can be used.
  240.  
  241.  
  242.  
  243.  
  244.  
  245. A20:
  246.  
  247. A20 is enabled if it was disabled, and never disabled by the extender. 
  248. If VCPI is running, then VCPI is used to enable and disable A20 as
  249. appropriate.  To determine if it is disabled, the extender compares 0:0
  250. with FFFF:0010 to see if they map to the same physical memory. 
  251.  
  252.  
  253.  
  254.  
  255.  
  256. Exceptions:
  257.  
  258. All exceptions are handled by exception_handler() in expnhdlr.c.  This
  259. function returns 1 if a fault happens, or 0 if it handles the exception.
  260. Control returns to the arena after an exception is handled.  Unhandled
  261. exceptions return you to the debugger or to DOS.
  262.  
  263.  
  264. Changes to the DOS INT 21H calls:
  265.  
  266. brk() and sbrk() replace the DOS memory management vector:
  267.     int 21,AH=4A (change memory allocation)
  268.         AL=0 brk(ebx) returns old brk in eax
  269.         AL=1 sbrk(ebx) returns old brk in eax
  270.  
  271. Some system calls are handled by the extender directly, instead of through
  272. DOS interrupts:
  273.     int 21,AH=FF - turbo assist.  Func in AL, parms (ebx,ecx,edx) ret eax
  274.         1: creat
  275.         2: open
  276.         3: fstat
  277.         4: gettimeofday
  278.         5: settimeofdat
  279.         6: stat
  280.         7: system
  281.  
  282.  
  283.     int 10, AH=FF - set video mode
  284.         0: 80x25 text
  285.         1: default text
  286.         2: text CX cols by DX rows
  287.         3: biggest text
  288.         4: 320x200 graphics
  289.         5: default graphics
  290.         6: graphics CX width by DX height
  291.         7: biggest non-interlaced graphics
  292.         8: biggest graphics
  293.  
  294.  
  295.  
  296.  
  297. 80387:
  298.  
  299. NPX.ASM has all the NPX code (except displaying it, that's in debug.c).
  300. When a numeric exception happens, the 387 state is stored in [_npx], and
  301. _npx_stored is set to 1.  go32() will restore the 387 from [_npx] if it
  302. is going to run a_tss (and if the state is stored there).  Most of the
  303. time, the 387 state remains in the 387 and _npx_stored remains 0.  The
  304. debugger can also move the 387 state from the 387 to [_npx] through
  305. save_npx() if it needs to look at it's state (or fix it, which it doesn't
  306. yet do).
  307.  
  308. Exception 7 (device not available) occurs the first time you use the 387
  309. after a task switch.  It just resets the task switch flag in CR0 and resumes.
  310. This vector points to the real mode handler if the 387 is not installed,
  311. to detect attempts to use the 387.
  312.  
  313. Exception 0x75 (IRQ13) is the numeric exception vector.  Currently, only
  314. divide-by-zero and invalid operation are unmasked.  This includes
  315. sqrt(-1), ln(-1), npx stack faults, acos(2), etc.
  316.  
  317.  
  318.  
  319.  
  320.  
  321. Debugging:
  322.  
  323. There are seven debug registers, and seven variables (_dr0.._dr7, or
  324. _dr[0..7]) that control them.  go32() loads the debug registers from
  325. these variables going into protected mode, and clears them coming out.
  326. Debug registers point to linear, not segment, addresses, so ad 0x10000000
  327. to them for arena addresses.
  328.  
  329. syms.c handles all symbol management, including register names and
  330. expression parsing.  Symbols are stored in virtual memory beginning
  331. at 0xa0000000.
  332.  
  333. unassmble.c handles unassembling machine instructions.  It's very table
  334. driven, and handles all known (I hope) 386/387 instructions and address
  335. modes.
  336.  
  337. debug.c is the central point for debuggin instructions.  The main loop
  338. for the debugger is here.  The utility function will longjump() to the
  339. beginning of the debugger() loop (if available) if they detect an exception.
  340.  
  341.  
  342.  
  343.  
  344.  
  345.  
  346.  
  347.  
  348.  
  349.  
  350.  
  351. Graphics Card support:
  352.  
  353. The files graphics.c and grprot.asm control the graphics handling.
  354. The system allows an external graphics driver to be loaded and used
  355. instead of the built-in VGA graphics driver.
  356.  
  357. The Graphics Driver:
  358.  
  359. Go32 includes the standard VGA driver built-in, as well as in an external
  360. driver.  To select an external driver, enter a DOS command like:
  361.  
  362.   C> set go32=driver c:\go32\drivers\tseng4k.grd tw 132 th 43 gw 800 gh 600
  363.  
  364. This says that the driver is "c:\go32\drivers\tseng4k.grd", that the
  365. default text mode is 132x43, and that the default graphics mode is
  366. 800x600.  The driver defines the resolutions for all the other modes.
  367. The parameters may be listed in any order, or omitted:
  368.  
  369.   C> set go32=driver c:\go32\drivers\tseng4k.grd gh 600 gw 800
  370.  
  371. There is also an "ansi" parameter that may be added to use an ansi
  372. screen driver to use colors while debugging.
  373.  
  374. For a listing of what the various modes are, see any of the following:
  375.   * listing earlier in this document
  376.   * code for the drivers
  377.   * include/graphics.h
  378.  
  379. Example drivers are in vga.asm, tseng4k.asm, and tseng3k.asm.
  380.  
  381. The first two words point to the two routines a driver provides.
  382. The next word indicates if "split page" is available (see below).
  383. The next four words are the default text and graphics sizes.
  384.  
  385. The "split page" feature of some vga's (like the TSENG, unlike PS/2)
  386. allow one bank to be used for reading and another for writing, so
  387. reading 0xa000:0x0400 talks to one byte in VRAM, and writing
  388. 0xa000:0x0400 talks to a different byte.  If your card supports this,
  389. set the split-bank word to 1.  If not, set it to 0.  You can return
  390. anything for PS/2's because they don't have enough memory to need page
  391. swapping, so can't really tell that you don't have that feature. 
  392.  
  393. GRAPHICS.C installs and calls the graphics driver for mode changes.
  394. The mode change function is pointed to by the first pointer (note: the
  395. pointers are only read when the file is installed).  It takes the mode
  396. in AX, and the size (when required) in CX and DX.  It should return
  397. the new size in CX and DX.
  398.  
  399. GRPROT.ASM handles the actual page faults.  It uses a page table's
  400. PRESENT bits to determine where the application can read/write to
  401. without having to reconfigure the graphics card.  There are two states
  402. the graphics system can be in:
  403.  
  404. 1: rw
  405.     Access to 0xd0000000 - 0xd00fffff are allowed.  Reads and writes
  406.     to the same address refer to the same physical byte of video memory
  407.         ┌───R───┐                0xD00xxxxx
  408.     ────────┼───────┼────────────────────────────────────── video ram
  409.         └───W───┘                0xD00xxxxx
  410.  
  411. 2: r_w
  412.     Reads to 0xd0100000 - 0xd01fffff and writes to 0xd0200000 - 0xd02fffff
  413.     are allowed.  The card is configured to read from one bank and
  414.     write to another.  This is "split bank" mode, and is used for fast
  415.     blits across the screen.
  416.         ┌───R───┐                0xD01xxxxxx
  417.     ────────┴───────┴───────┬───────┬────────────────────── video ram
  418.                 └───W───┘        0xD02xxxxxx
  419.  
  420.  
  421. When grprot determines that the VGA has to be reprogrammed, it calls the
  422. function pointed to by the second pointer (in protected mode), passing
  423. the read page in AH and the write page in AL. 
  424.  
  425. That's it! All knowlegde of card specifics are contained in the drivers,
  426. so libgr.a and your programs don't have to be recompiled!
  427.  
  428. If you can't manage to get your card to work, I may be persuaded to add
  429. it for you (as long as you provide technical manuals!).  If you add a
  430. card, please send me the sources for the driver so I can integrate it
  431. into future releases!
  432.  
  433.