home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1998 November / VPR9811A.BIN / BENCH / CWSDPMI2 / CWSDPMI2.LZH / SRC.LZH / CONTROL.C < prev    next >
C/C++ Source or Header  |  1996-08-07  |  14KB  |  466 lines

  1. /* Copyright (C) 1995,1996 CW Sandmann (sandmann@clio.rice.edu) 1206 Braelinn, Sugarland, TX 77479
  2. ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  3. **
  4. ** This file is distributed under the terms listed in the document
  5. ** "copying.cws", available from CW Sandmann at the address above.
  6. ** A copy of "copying.cws" should accompany this file; if not, a copy
  7. ** should be available from where this file was obtained.  This file
  8. ** may not be distributed without a verbatim copy of "copying.cws".
  9. **
  10. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  11. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. */
  13. /* PC98 support contributed 6-95 tantan SGL00213@niftyserve.or.jp */
  14.  
  15. #include <dos.h>
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <fcntl.h>
  19. #include <string.h>
  20. #include <io.h>
  21.  
  22. #include "gotypes.h"
  23. #include "gdt.h"
  24. #include "idt.h"
  25. #include "tss.h"
  26. #include "valloc.h"
  27. #include "utils.h"
  28. #include "vcpi.h"
  29. #include "paging.h"
  30. #include "exphdlr.h"
  31. #include "dalloc.h"
  32. #include "mswitch.h"
  33. #include "xms.h"
  34. #include "control.h"
  35. #include "dpmisim.h"
  36.  
  37. /* Note, the near heap and stack are pooled.  EHDRFIX.C reads the lines below */
  38. /* and adds paragraphs required to the exe header.  Each task takes 304 bytes */
  39. /* (dpmisim stack + 0x30), each memory zone 14 bytes, each HW int around 850 */
  40. extern unsigned _stklen = 4096U;    /* Plus heap added in exe hdr */
  41. extern unsigned int _brklvl[2];        /* hi word is free seg after our prog */
  42. extern void _restorezero(void);
  43.  
  44. static word16 current_es = 0;
  45. static word16 old_env,current_psp;
  46. static word8 one_pass = 1;
  47. word8 mtype = 0;            /* Machine type */
  48.  
  49. DESC_S gdt[g_num];
  50. DESC_S ldt[l_num];
  51. IDT idt[256];
  52. TSS *tss_ptr;
  53.  
  54. word8 vcpi_installed = 0;    /*  VCPI Installed Flag  */
  55. word8 use_xms=0;
  56.  
  57. CWSDPMI_pblk CWSpar = { "CWSPBLK", "c:\\cwsdpmi.swp", 0, 0, 128, 3840 };
  58.  
  59. static char *exception_names[] = {
  60.   "Division by Zero",
  61.   "Debug",
  62.   "NMI",
  63.   "Breakpoint",
  64.   "Overflow",
  65.   "Bounds Check",
  66.   "Invalid Opcode",
  67.   "Coprocessor unavailable",
  68.   "Double Fault",
  69.   "Coprocessor overrun",
  70.   "Invalid TSS",
  71.   "Segment Not Present",
  72.   "Stack Fault",
  73.   "General Protection Fault",
  74.   "Page fault",
  75.   0,
  76.   "Coprocessor Error",
  77. };
  78. #define EXCEPTION_COUNT (sizeof(exception_names)/sizeof(exception_names[0]))
  79.  
  80. word16 get_pid(void)
  81. {
  82.   _AH = 0x62;
  83.   geninterrupt(0x21);
  84.   return _BX;
  85. }
  86.  
  87. void set_pid(word16 pid)
  88. {
  89.   _BX = pid;
  90.   _AH = 0x50;
  91.   geninterrupt(0x21);
  92. }
  93.  
  94. static void fill_desc(DESC_S *g, word32 limit, word32 base, word8 type, int G)
  95. {
  96.   if (G & 2)            /* Granularity bit = 4K */
  97.     limit = limit >> 12;
  98.   g->lim0 = (word16)limit;
  99.   g->lim1 = (limit>>16) & 0x0f;
  100.   g->base0 = (word16)base;
  101.   g->base1 = (word8)(base>>16);
  102.   g->base2 = (word8)(base>>24);
  103.   g->stype = type;
  104.   g->lim1 |= G * 0x40;        /* Shift field to set G & D bits */
  105. }
  106.  
  107. static void setup_tss(TSS *t, void (*eip)())
  108. {
  109.   memset(t, 0, sizeof(TSS));
  110.   /* At this point EFLAGS = 0 (interrupt disabled) and all selectors null */
  111.   t->tss_cs = g_rcode*8;
  112.   (word16)t->tss_eip = FP_OFF(eip);
  113.   t->tss_ss0 = t->tss_ss = t->tss_ds = g_rdata*8;
  114.   (word16)t->tss_esp0 = (word16)t->tss_esp = FP_OFF(t->tss_stack);
  115.   t->tss_ldt = g_ldt*8;
  116. }
  117.  
  118. /* This routine is called in context of the other process */
  119. void cleanup(int exitcode)
  120. {
  121.   int lastused;
  122.   word16 far *envptr;
  123.   envptr = MK_FP(current_psp,0x2c);
  124.   *envptr = old_env;
  125.  
  126.   lastused = a_tss.tss_lastused;
  127.   current_es = a_tss.tss_cur_es;        /* Saved ES if needed */
  128.   old_env = a_tss.tss_old_env;
  129.   current_psp = a_tss.tss_cur_psp;
  130.   if (current_es) {            /* There is back link, restore old TSS */
  131.     AREAS *area = firstarea;
  132.     AREAS **lasta = &firstarea;
  133.     word16 lua = (word16)lastused >> 8;
  134.     while (lua--) {
  135.       lasta = &area->next;
  136.       area = area->next;
  137.     }
  138.     while (*lasta && free_memory_area((*lasta)->first_addr)) ;
  139.     lastused &= 0xff;
  140.     for(lastused++; lastused<l_num; lastused++)
  141.       ldt[lastused].stype = 0;        /* Mark them all as available */
  142.  
  143.     movedata(current_es, 0, _DS, FP_OFF(&a_tss), 6*16);
  144.   } else {                /* This is the last nested process */
  145.     dalloc_uninit();
  146.     uninit_controllers();
  147.     valloc_uninit();
  148.     if (one_pass || a_tss.tss_ebx == ONE_PASS_MAGIC) { /* "magic" for unload */
  149.       setvect(0x2f,oldint2f);
  150.  
  151.       ems_free();        /* Deallocated EMS Page */
  152.  
  153.       disable();
  154.       _ES = _psp;        /* Deallocate TSR we are currently executing! */
  155.       _AH = 0x49;
  156.       geninterrupt(0x21);
  157.     }
  158.   }
  159.  
  160.   _AL = (word8)exitcode;
  161.   _AH = 0x4c;
  162.   geninterrupt(0x21);
  163. }
  164.  
  165. void itox(char *buf, int v)
  166. {
  167.   _DX = v;
  168.   buf += 3;
  169.   for(_CX=4;_CX;_CX--) {
  170.     _AL = _DL & 15;
  171.     _DX >>= 4;
  172.     _AL += '0';
  173.     if (_AL > '9')
  174.       _AL += 'a' - '9' - 1;
  175.     *buf-- = _AL;
  176.   }
  177. }
  178.  
  179. void errmsg(char *fmt, ...)
  180. {
  181.   char *p,*s;
  182.   int *q;
  183.   q = &(int)fmt + 1;
  184.   p = s = fmt;
  185.   while((_AL=*p) != 0) {
  186.     if(_AL == '\n'){
  187.       _write(2,s,p-s);
  188.       _write(2,"\r\n",2);
  189.       s = ++p;
  190.     } else if(_AL == '%') {
  191.       _write(2,s,p-s);
  192.       _AL = *++p;
  193.       if(_AL == 's')
  194.         errmsg((char *)(*q++));
  195.       else {
  196.         int n = 0;
  197.         int v2 = 0;
  198.         int v1 = *q++;
  199.         char buf[8];
  200.         _AL = *p;
  201.         while(_AL != 'x') {
  202.           if(_AL >= '0' && _AL <= '8')
  203.             n = _AL - '0';
  204.           else if(_AL == 'l')
  205.             v2 = *q++;
  206.           _AL = *++p;
  207.         }
  208.         itox(buf,v2);
  209.         itox(buf+4,v1);
  210.         if(n == 0) {
  211.           n=8;
  212.           while(buf[8-n] == '0' && n > 1) n--;
  213.         }
  214.         _write(2,buf+8-n,n);
  215.       }
  216.       s = ++p;
  217.     } else
  218.       p++;
  219.   }
  220.   _write(2,s,p-s);
  221. }
  222.  
  223. void do_faulting_finish_message(void)
  224. {
  225.   extern char in_rmcb;
  226.   char *en = (tss_ptr->tss_irqn >= EXCEPTION_COUNT) ? 0 : exception_names[tss_ptr->tss_irqn];
  227.   if (en == 0)
  228.     errmsg("Interrupt 0x%02x", tss_ptr->tss_irqn);
  229.   else
  230.     errmsg("%s", en);
  231.   if(tss_ptr->tss_irqn == 14)
  232.     errmsg(" cr2=%08lx", tss_ptr->tss_cr2);
  233.   if(in_rmcb)
  234.     errmsg(" in RMCB");
  235.   errmsg(" at eip=%lx; flags=%x\n", tss_ptr->tss_eip, (word16)tss_ptr->tss_eflags);
  236.   errmsg("eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx esi=%08lx edi=%08lx\n",
  237.     tss_ptr->tss_eax, tss_ptr->tss_ebx, tss_ptr->tss_ecx, tss_ptr->tss_edx,
  238.     tss_ptr->tss_esi, tss_ptr->tss_edi);
  239.   errmsg("ebp=%08lx esp=%08lx cs=%x ds=%x es=%x fs=%x gs=%x ss=%x error=%04x\n",
  240.     tss_ptr->tss_ebp, tss_ptr->tss_esp,
  241.     tss_ptr->tss_cs, tss_ptr->tss_ds, tss_ptr->tss_es, tss_ptr->tss_fs,
  242.     tss_ptr->tss_gs, tss_ptr->tss_ss, (word16)tss_ptr->tss_error);
  243.   cleanup(1);
  244. }
  245.  
  246. void main1(void)    /* int argc, char **argv) */
  247. {
  248.   /* Check for cpu type in assembly main to avoid 8088 problems with 'enter' */
  249.  
  250.   if (_osmajor < 3) {
  251.     errmsg("DOS 3 required.\n");
  252.     exit(1);
  253.   }
  254.  
  255.   if(*(word16 far *)MK_FP(0xf000, 0xfff3) == 0xfd80) {
  256.     hard_slave_lo = 0x10;        /* PC98 slave */
  257.     mtype = PC98;
  258.   }
  259.  
  260.   _restorezero();
  261.  
  262. #if run_ring != 0
  263.   dalloc_file(CWSpar.swapname);        /* default */
  264. #endif
  265.   {
  266.   char far *ptr;
  267.   int i,nc;
  268.  
  269.   ptr = MK_FP(_psp, 0x80);
  270.   nc = *ptr++;
  271.   ptr[nc] = 0;
  272.   for(i=0;i<nc;i++) {
  273.     if(ptr[i] == '-') {
  274.       char test = 0x20 | ptr[++i];    /* make lower case if upper */
  275.       errmsg("CWSDPMI V0.90+ (r3) Copyright (C) 1995 CW Sandmann  ABSOLUTELY NO WARRANTY\n");
  276.       if(test == 'p')            /* persistent, permanent */
  277.         one_pass = 0;
  278.       else if(test == 'u') {        /* unload */
  279.         extern void unload_tsr(void);
  280.         unload_tsr();
  281.       } else if(test == 's'){        /* swapfile; -s- means no virtual mem */
  282.         int j;
  283.         char t;
  284.         char *swap = malloc(nc-i);
  285.         for(j=0,i++,t=32;t;i++){
  286.           t = ptr[i];
  287.           if(t != ' ' && t != 9)    /* skip whitespace */
  288.             swap[j++] = t;
  289.         }
  290. #if run_ring != 0
  291.         if(swap[0] == '-')
  292.           swap[0] = 0;
  293.         dalloc_file(swap);
  294. #endif
  295.       }
  296.     }
  297.   }
  298.   }
  299.   _ES = peek(_psp,0x2c);    /* Deallocate TSR environment */
  300.   _AH = 0x49;
  301.   geninterrupt(0x21);
  302.   _close(0); _close(1);        /* Close stdin, stdout, AUX, PRN */
  303.   _close(3); _close(4);
  304.  
  305.   use_xms = xms_installed();
  306.  
  307.   ems_init();
  308.   if (cpumode()) {        /* We are in V86 mode */
  309.     if (!(vcpi_installed = vcpi_present())) {
  310.       ems_free();
  311.       errmsg("Protected mode not accessible.\n");
  312.       exit(1);
  313.     }
  314.   }
  315.  
  316.   _BX = 2; _AH = 0x3e; geninterrupt(0x21);    /* Close stderr, tc thinks open */
  317. #if run_ring != 0
  318.   gdt[g_iret].lim0 = (word16)ring0_iret;    /* Call gate to do IRET */
  319.   gdt[g_iret].base0 = g_rcode*8;
  320.   gdt[g_iret].stype = SEL_PRV | 0x8c;
  321. #else
  322.   fill_desc(&gdt[g_iret], sizeof(TSS)-1, ptr2linear(&f_tss), 0x89, 1);
  323. #endif
  324.   fill_desc(&gdt[g_gdt], sizeof(gdt)-1, ptr2linear(gdt), 0x92, 0);
  325.   fill_desc(&gdt[g_idt], sizeof(idt)-1, ptr2linear(idt), 0x92, 0);
  326.   fill_desc(&gdt[g_ldt], sizeof(ldt)-1, ptr2linear(ldt), 0x82, 1);
  327.   fill_desc(&gdt[g_rcode], 0xffff, (word32)_CS*16L, 0x9a, 0);
  328.   fill_desc(&gdt[g_rdata], 0xffff, (word32)_DS*16L, 0x92, 1); /* 1 for ring 3 */
  329.   fill_desc(&gdt[g_core], 0xffffffffL, 0, SEL_PRV | 0x92, 3);
  330.   fill_desc(&gdt[g_BIOSdata], 0xffff, (word32)0x400, SEL_PRV | 0x92, 0);
  331.   fill_desc(&gdt[g_pcode], 0xffff, (word32)_CS*16L, SEL_PRV | 0x9a, 0);
  332.   fill_desc(&gdt[g_pdata], 0xffff, (word32)_DS*16L, SEL_PRV | 0x92, 1);
  333.  
  334.   fill_desc(&gdt[g_ctss], sizeof(TSS)-1, ptr2linear(&c_tss), SEL_PRV | 0x89, 1);
  335.   fill_desc(&gdt[g_atss], sizeof(TSS)-1, ptr2linear(&a_tss), 0x89, 1);
  336.   fill_desc(&gdt[g_itss], sizeof(TSS)-1, ptr2linear(&i_tss), SEL_PRV | 0x89, 1);
  337.  
  338.   oldint2f = getvect(0x2f);
  339.   setvect(0x2f, dpmiint2f);
  340.  
  341.   DPMIsp = _SP;
  342.   _DX = _brklvl[1] - _psp;
  343.   _AX = 0x3100;
  344.   geninterrupt(0x21);
  345. }
  346.  
  347. void DPMIstartup(void)
  348. {
  349.   {
  350.   int use32,myES;
  351.   int acode,adata,apsp,aenv,astack;
  352.   int lastused;        /* Keep track of selectors */
  353.   word16 dpmipsp;
  354.   word16 far *envptr;
  355.   myES = _ES;
  356.   tss_ptr = &a_tss;
  357.   if (current_es){
  358.     int lua = 0;        /* Last used area */
  359.     AREAS *area = firstarea;
  360.     while (area) {
  361.      lua++;
  362.      area = area->next;
  363.     }
  364.     for(lastused=l_num-1;lastused>l_free && !(ldt[lastused].stype); lastused--);
  365.     lastused |= lua << 8;
  366.     movedata(_DS, FP_OFF(&a_tss), current_es, 0, 6*16); /* Save old TSS */
  367.     acode = alloc_ldt(1);
  368.     adata = alloc_ldt(1);
  369.     apsp = alloc_ldt(1);
  370.     if((aenv = alloc_ldt(1)) == 0) {
  371.       errmsg("Descriptors exhausted.\n");
  372.       exit(1);
  373.     }
  374.   } else {
  375.     int i,n;
  376.     setup_tss(&c_tss, go_real_mode);
  377.     setup_tss(&a_tss, go_real_mode);
  378.     setup_tss(&o_tss, go_real_mode);
  379. #if run_ring == 0
  380.     { void double_fault(void); setup_tss(&f_tss, double_fault); }
  381. #else
  382.     setup_tss(&f_tss, go_real_mode);
  383. #endif
  384.     setup_tss(&i_tss, interrupt_common);
  385.  
  386.     memset(ldt,0,sizeof(ldt));    /* Zero it; this make all stypes = 0 not used */
  387.     lastused=l_free-1;        /* lua = 0 */
  388.     /* Note - this shortcut will make these look free to alloc_ldt until set */
  389.     acode = l_acode;
  390.     adata = l_adata;
  391.     apsp = l_apsp;
  392.     aenv = l_aenv;
  393.     dr[7] = 0L;            /* Clear all breakpoints */
  394.  
  395.     valloc_init();
  396.     dalloc_init();
  397.     paging_setup();
  398.     init_controllers();
  399.  
  400.     n = (int)ivec1-(int)ivec0;
  401.     for (i=0; i<256; i++)
  402.     {
  403.       idt[i].selector = GDT_SEL(g_pcode);
  404.       idt[i].stype = 0xee00;
  405.       idt[i].offset0 = (int)FP_OFF(ivec0) + n*i;
  406.       idt[i].offset1 = 0;
  407.     }
  408.     for (i=0; i<16; i++)
  409.       idt[i].selector = g_rcode*8;
  410.     for (i=hard_master_lo; i<=hard_master_hi; i++)
  411.       idt[i].selector = g_rcode*8;
  412.     for (i=hard_slave_lo; i<=hard_slave_hi; i++)
  413.       idt[i].selector = g_rcode*8;
  414. #ifdef I31PROT
  415.     idt[0x31].offset0 = (int)FP_OFF(ivec31);
  416. #endif
  417.     idt[7].offset0 = (int)ivec7;        /* To handle TS bit set faults */
  418. #if run_ring == 0
  419.     i = 8;    /* Double fault */
  420.     idt[i].selector = g_iret*8; idt[i].stype = 0xe500; idt[i].offset0 = 0;
  421. #endif
  422.   }
  423.   movedata(myES, 32, _DS, FP_OFF(&a_tss.tss_eip), 4*14);
  424.  
  425.   use32 = (word16)a_tss.tss_eax & 1;
  426.  
  427.   /* Hack alert! Since ring1 & ring2 not used, I re-used this storage to keep
  428.      track of selector usage (to aid clean up), back link to the previous
  429.      allocated area segment, the old environment segment, and the PSP */
  430.  
  431.   a_tss.tss_cur_es = current_es;    /* Back link to saved TSS */
  432.   a_tss.tss_lastused = lastused;
  433.   current_es = myES;            /* Save mine for child if any */
  434.   a_tss.tss_old_env = old_env;        /* Saved */
  435.   a_tss.tss_cur_psp = current_psp;
  436.  
  437.   a_tss.tss_fs = a_tss.tss_gs = 0;
  438.   fill_desc(&ldt[acode], 0xffff, (word32)a_tss.tss_cs*16L, SEL_PRV | 0x9a, 0);
  439.   a_tss.tss_cs = LDT_SEL(acode);
  440.   fill_desc(&ldt[adata], 0xffff, (word32)a_tss.tss_ds*16L, SEL_PRV | 0x92, use32);
  441.   a_tss.tss_eflags = 0x3202;
  442.  
  443.   _AH = 0x62;                /* Get PSP */
  444.   geninterrupt(0x21);
  445.   dpmipsp = _BX;
  446.   current_psp = dpmipsp;
  447.   envptr = MK_FP(dpmipsp,0x2c);
  448.   old_env = *envptr;
  449.   *envptr = LDT_SEL(aenv);
  450.   fill_desc(&ldt[apsp], 0xffff, (word32)dpmipsp*16L, SEL_PRV | 0x92, 0); /* lim should be ff */
  451.   a_tss.tss_es = LDT_SEL(apsp);
  452.   fill_desc(&ldt[aenv], 0xffff, (word32)old_env*16L, SEL_PRV | 0x92, 0);
  453.   /* Must come after all other descriptors set up, since calls alloc_ldt() */
  454.   if (a_tss.tss_ds != a_tss.tss_ss) {
  455.     astack = alloc_ldt(1);
  456.     fill_desc(&ldt[astack], 0xffff, (word32)a_tss.tss_ss*16L, SEL_PRV | 0x92, use32);
  457.   } else
  458.     astack = adata;
  459.  
  460.   a_tss.tss_ds = LDT_SEL(adata);
  461.   a_tss.tss_ss = LDT_SEL(astack);
  462.   setvect(0x23,int23);
  463.   setvect(0x24,int24);
  464.   }
  465. }
  466.