Main Page | Modules | File List | File Members

vm86.c

00001 /* ndk - [ vm86.c ]
00002  *
00003  * Contains code to handle vm86 tasks.
00004  * Currently being revamped (does not work).
00005  *
00006  * Please see:
00007  *   /src/drivers/video/vesa/vesa.c
00008  *
00009  * (c)2002 dcipher / neuraldk
00010  *           www.neuraldk.org
00011  */
00012 
00013 #include "vm86.h"
00014 
00015 // page directory to use when calling bios ints
00016 pageDirectory *vm86PageDir;
00017 TSS vm86TSS;
00018 
00019 void vm86Init(void) {
00020   vm86CreatePagingInfo();
00021   vm86FillTSS(&vm86TSS, 0, 0, 0);
00022   createGate(&IDT, 0x81, (long)vm86IntHandler, SEL_P0_CODE, D_INT);
00023 }
00024 
00025 void vm86CreatePagingInfo(void) {
00026   pageTable *pTable;
00027   long i;
00028 
00029   // find 4kb aligned address for page directory
00030   vm86PageDir = (pageDirectory *)0x00092000;
00031 
00032   // find 4kb aligned address for 1 page table
00033   pTable = (pageTable *)0x00093000;
00034 
00035   // assign 1st page directory entry to page table
00036   vm86PageDir->pageTable[0] = (long)pTable | PAGE_PRESENT
00037                                            | PAGE_READ_WRITE
00038                                            | PAGE_P3_ACCESS;
00039 
00040   // clear the rest of the page directory
00041   for(i = 1; i < 1024; i++)
00042     vm86PageDir->pageTable[i] = 0;
00043 
00044   // assign the first page to the real mode idt
00045   pTable->pageAddr[0] = 0x00001000;
00046 
00047   // and map the rest of the pages to their physical
00048   // equivalents
00049   for(i = 1; i < 1024; i++) {
00050     pTable->pageAddr[i] = (i * 4096) | PAGE_PRESENT
00051                                      | PAGE_READ_WRITE
00052                                      | PAGE_P3_ACCESS;
00053   }
00054 }
00055 
00056 // the next two might be better placed in task.c
00057 void vm86FillTSS(TSS *tss, long eip, long p0_esp, long p3_esp) {
00058   tss->ldtr = 0;
00059   tss->fs = tss->gs = SEL_P3_DATA | 3;
00060   tss->ds = tss->es = SEL_P3_DATA | 3;
00061   tss->ss = SEL_P3_STACK | 3;
00062   tss->cs = SEL_P3_CODE | 3;
00063   tss->eflags = 0x00023202L | 1 << 18;  // vm86, IOPL=3, STI, Alignment Check
00064   tss->esp = /*p0_esp;*/p3_esp;
00065   tss->eip = eip;
00066   tss->cr3 = getCR3();
00067 
00068   tss->esp0 = p0_esp;
00069   tss->ss0 = SEL_P0_STACK;
00070 
00071   tss->link = 0;
00072 }
00073 
00074 /*
00075 void vm86Int(long intNum, vm86Regs *regs) {
00076   // load registers with values in regs
00077 
00078   // push interrupt number onto stack
00079 
00080   // call real mode interrrupt interface
00081 
00082   // copy registers back in regs
00083 }
00084 */
00085 
00086 /*
00087 // Call this interrupt (0x??) with the real mode int you wish to call
00088 // pushed onto the stack (or in the top bits of eax?  real mode ints
00089 // wont use it anyway...).  All registers are set up as if you were
00090 // calling that real mode interrupt.
00091 void vm86IntHandler(void) {
00092   // at this point:
00093   //   an iret returns to vm86int function, or P3 app...
00094   //   interrupt number is on stack (which one?) above cs:eip, eflags
00095   //     currentTask->p3_stack... what if the kernel called?  It doesn't
00096   //     have a p3 stack... probably best to use high half of a register (eax?)
00097 
00098   // save stack frame (where?) -- perhaps not needed
00099 
00100   // add to stack frame
00101   //   point to real mode interrupt, set vm86 = 1
00102 
00103   // iret
00104 
00105   // ....
00106   // control is passed to real mode int, in vm86 mode...
00107   // upon vm86 iret, transfer is given to gpf routine:
00108 
00109   // get previous stack frame (again, from where?)
00110   //   -- not needed... pmode return address is on the stack!
00111 
00112   // change stack frame to point to this, set vm86 = 0
00113   //   -- again, not needed?
00114 
00115   // iret, returns to pmode function that called int
00116 }
00117 */

Generated on Sun Nov 21 18:26:11 2004 for ndk by doxygen 1.3.2