home *** CD-ROM | disk | FTP | other *** search
/ Internet MPEG Audio Archive / IMAA.mdf / util / dos / l3v100n / rsx / source / cdosx32.c < prev    next >
C/C++ Source or Header  |  1994-01-19  |  12KB  |  465 lines

  1. /* This file is CDOSX32.C
  2. **
  3. ** contains :
  4. **
  5. **              - int21 handler
  6. **
  7. ** Copyright (c) Rainer Schnitker 92 93
  8. */
  9.  
  10. #include <stdio.h>
  11. #include <io.h>
  12.  
  13. #include "DPMI.H"
  14. #include "PROCESS.H"
  15. #include "START32.H"
  16. #include "CDOSX32.H"
  17. #include "COPY32.H"
  18. #include "TERMIO.H"
  19. #include "DOSERRNO.H"
  20.  
  21. static char iobuffer[IOBUF_SIZE + 3];    /* I/O buffer for real-mode operations */
  22. char *iobuf = iobuffer;
  23. TRANSLATION tr;            /* registers set for mode-switching */
  24. static DWORD user_dta;        /* prot-mode DTA address */
  25. extern WORD _psp;        /* PSP after protected mode switch */
  26.  
  27. static void illegal_param(void)
  28. {
  29.     puts("Illegal Parameter in syscall");
  30.     send_signal(npz, SIGSEGV);
  31.     EAX = EMX_EINTR;
  32. }
  33.  
  34. #define TEST_ILLEGAL( OFFSET , LENGHT ) \
  35.     if ( OFFSET < 0x1000L || OFFSET + LENGHT >= npz->membytes ) {  \
  36.     illegal_param();    \
  37.     return CARRY_ON;    \
  38.     }
  39.  
  40. void align_iobuf(void)
  41. {
  42.     iobuf = (char *) ((unsigned) (iobuf + 3) & ~3);
  43. }
  44.  
  45. static void put_regs(void)
  46. {
  47.     tr.eax = EAX;
  48.     tr.ebx = EBX;
  49.     tr.ecx = ECX;
  50.     tr.edx = EDX;
  51.     tr.flags = FLAGS & ~1;
  52. }
  53.  
  54. static void get_regs(void)
  55. {
  56.     EAX = tr.eax;
  57.     EBX = tr.ebx;
  58.     ECX = tr.ecx;
  59.     EDX = tr.edx;
  60.     FLAGS = tr.flags;
  61. }
  62.  
  63. static char rm_stack[512];
  64. unsigned real_mode_stack = (unsigned) (rm_stack + 510);
  65.  
  66. /* call Real-Mode INT0x21 */
  67. int realdos(void)
  68. {
  69.     /* int rsp; */
  70.     /* tr.sp = (WORD) & rsp - 40; */
  71.  
  72.     tr.eax &= 0xFFFF;
  73.     tr.cs = cs16real;
  74.     tr.ds = tr.ss = tr.es = tr.fs = tr.gs = ds16real;
  75.     tr.sp = real_mode_stack;
  76.  
  77.     /* DPMI-Call to Real-Mode DOS */
  78.     SimulateRMint(0x21, 0, 0, &tr);
  79.  
  80.     /* return Carry-bit */
  81.     return (tr.flags & 1);
  82. }
  83.  
  84. /*
  85. ** INT 0x21 handler returns:
  86. **
  87. ** CARRY_ON :    error, set carry-bit, errno in eax
  88. ** CARRY_OFF:    no error, clear carry-bit
  89. ** CARRY_NON:    carry-bit set by realdos -> dos error code in ax,
  90. **        translate ax to errno
  91. */
  92. int int21normal(void)
  93. {
  94.     int i;
  95.     char rAH, rAL;
  96.  
  97.     rAH = (BYTE) (AX >> 8);
  98.     rAL = (BYTE) EAX;
  99.  
  100.     switch (rAH) {
  101.  
  102. /************ register based functions ***************/
  103. /* no changes needed - only ax,dx,flags (bx,cx) used */
  104.  
  105.     case 0x01:            /* read char */
  106.     case 0x02:            /* write char */
  107.     case 0x03:            /* read char stdaux */
  108.     case 0x04:            /* write char stdaux */
  109.     case 0x05:            /* read char prn */
  110.     case 0x06:            /* con output&input */
  111.     case 0x07:            /* char input & echo */
  112.     case 0x08:            /* char output & echo */
  113.     case 0x0b:            /* get stdin stat */
  114.     case 0x0c:            /* flush buffer & read std input */
  115.     case 0x0d:            /* disk reset */
  116.     case 0x0e:            /* select drive */
  117.     case 0x19:            /* get drive */
  118.     case 0x2a:            /* get system date (cx) */
  119.     case 0x2b:            /* set system date (cx) */
  120.     case 0x2c:            /* get time (cx) */
  121.     case 0x2d:            /* set time (cx) */
  122.     case 0x2e:            /* set verify */
  123.     case 0x30:            /* get DOS version (bx) */
  124.     case 0x33:            /* extended break check */
  125.     case 0x36:            /* get free disk space (bx,cx) */
  126.     case 0x37:            /* get&set switch char */
  127.     case 0x3e:            /* close file (bx) */
  128.     case 0x45:            /* dup file (bx) */
  129.     case 0x46:            /* dup2 file */
  130.     case 0x54:            /* get verify flag */
  131.     case 0x57:            /* get file state (bx,cx) */
  132.     case 0x5c:            /* un-&lock file */
  133.     case 0x66:            /* code page */
  134.     case 0x68:            /* fflush file */
  135.     if (rAH == 0x3E && EBX < 3) {
  136.         EAX = 0;
  137.         return CARRY_OFF;
  138.     }
  139.     put_regs();
  140.     realdos();
  141.     get_regs();
  142.     return CARRY_NON;
  143.  
  144.     case 0x42:                  /* lseek file */
  145.     put_regs();
  146.         if (npz->p_flags & PF_EMX_FILE) {
  147.             /* convert edx to cx:dx */
  148.             tr.ecx = tr.edx >> 16;
  149.             tr.edx &= 0xffff;
  150.         }
  151.     if (realdos())
  152.         EAX = tr.eax;    /* dos error code */
  153.         else {
  154.             if (npz->p_flags & PF_EMX_FILE) {
  155.                 EAX = (tr.edx << 16) | (WORD) tr.eax;
  156.                 FLAGS = tr.flags;
  157.             }
  158.             else get_regs();
  159.         }
  160.         return CARRY_NON;
  161.  
  162.     case 0x44:            /* IOCTL */
  163.     switch (rAL) {
  164.     case 0x00:        /* get device info */
  165.     case 0x01:        /* set device info */
  166.     case 0x06:        /* get input status */
  167.     case 0x07:        /* get output status */
  168.     case 0x08:        /* check block device remove */
  169.     case 0x09:        /* check block device remote */
  170.     case 0x0a:        /* check handle remote */
  171.     case 0x0b:        /* set sharing */
  172.     case 0x0e:        /* get log drive map */
  173.     case 0x0f:        /* set log drive map */
  174.     case 0x10:        /* query ioctl handle */
  175.     case 0x11:        /* query ioctl drive */
  176.         put_regs();
  177.         realdos();
  178.         get_regs();
  179.         return CARRY_NON;
  180.     default:
  181.         EAX = EMX_EIO;
  182.         return CARRY_ON;
  183.     }
  184.  
  185. /*****    some special handling *****/
  186.  
  187.     case 0x1a:            /* SET DTA */
  188.     TEST_ILLEGAL(EDX, 2);
  189.     user_dta = EDX;
  190.     tr.eax = 0x1a00;
  191.     tr.edx = (DWORD) (WORD) iobuf;
  192.     realdos();
  193.     return CARRY_OFF;
  194.  
  195.     case 0x2f:            /* GET DTA */
  196.     EBX = user_dta;
  197.     return CARRY_OFF;
  198.  
  199.     case 0x62:            /* GET PSP */
  200.     EBX = (DWORD) _psp;
  201.     return CARRY_OFF;
  202.  
  203. /*********** ASCiiZero functions ***********/
  204. /* copy name -> real_buffer , call realdos */
  205.  
  206.     case 0x09:            /* string to output */
  207.     TEST_ILLEGAL(EDX, 2);
  208.     getstr32_16(DS, EDX, iobuf, '$');
  209.     tr.eax = EAX;
  210.     tr.edx = (DWORD) (WORD) iobuf;
  211.     realdos();
  212.     return CARRY_NON;
  213.  
  214.     case 0x39:            /* MKDIR name */
  215.     case 0x3a:            /* RMDIR name */
  216.     case 0x3b:            /* CHDIR name */
  217.     case 0x3c:            /* CREATE name */
  218.     case 0x3d:            /* OPEN name */
  219.     case 0x41:            /* UNLINK name */
  220.     case 0x43:            /* ATTRIB name */
  221.     case 0x5b:            /* CREATE New file */
  222.     TEST_ILLEGAL(EDX, 2);
  223.     if (rAH == 0x3c)    /* fix umask bug */
  224.         ECX &= ~1L;
  225.     put_regs();
  226.     strcpy32_16(DS, EDX, iobuf);
  227.     tr.edx = (DWORD) (WORD) iobuf;
  228.     realdos();
  229.     get_regs();
  230.     return CARRY_NON;
  231.  
  232.     case 0x56:            /* RENAME oldname name (strlen < 1024) */
  233.     TEST_ILLEGAL(EDX, 2);
  234.     TEST_ILLEGAL(EDI, 2);
  235.     put_regs();
  236.     strcpy32_16(DS, EDX, iobuf);
  237.     strcpy32_16(DS, EDI, iobuf + 1024);
  238.     tr.edx = (DWORD) (WORD) iobuf;
  239.     tr.edi = (DWORD) ((WORD) iobuf + 1024);
  240.     realdos();
  241.     get_regs();
  242.     return CARRY_NON;
  243.  
  244.     case 0x5a:            /* CREATE TEMP name */
  245.     TEST_ILLEGAL(EDX, 2);
  246.     put_regs();
  247.     strcpy32_16(DS, EDX, iobuf);
  248.     tr.edx = (DWORD) (WORD) iobuf;
  249.     if (!realdos())
  250.         strcpy16_32(DS, EDX, iobuf);
  251.     get_regs();
  252.     return CARRY_NON;
  253.  
  254.     case 0x6c:            /* EXTENDED OPEN/CREATE file */
  255.     TEST_ILLEGAL(ESI, 2);
  256.     put_regs();
  257.     strcpy32_16(DS, ESI, iobuf);
  258.     tr.esi = (DWORD) (WORD) iobuf;
  259.     realdos();
  260.     get_regs();
  261.     return CARRY_NON;
  262.  
  263. /********** buffer functions *********/
  264. /* copy data before or after realdos */
  265.  
  266.     case 0x0a:            /* BUFFERED INPUT */
  267.     {
  268.         BYTE no_chars;
  269.  
  270.         TEST_ILLEGAL(EDX, 4);
  271.         put_regs();
  272.         no_chars = (BYTE) read32(DS, EDX);
  273.         iobuf[0] = no_chars;/* no of chars */
  274.         tr.edx = (DWORD) (WORD) iobuf;
  275.         realdos();
  276.         cpy16_32(DS, EDX, iobuf, (DWORD) no_chars + 2);    /* copy of chars */
  277.         return CARRY_OFF;
  278.     }
  279.     case 0x3f:            /* READ from file */
  280.     {
  281.         long count;
  282.         DWORD off_edx, bytes;
  283.  
  284.         if ((npz->p_flags & PF_DJGPP_FILE) && EDX == 0) {
  285.                 printf("read.o not ok ; run DPMIFIX from DJGPP 1.10\n");
  286.         EAX = EMX_EIO;
  287.         return CARRY_ON;
  288.         }
  289.         TEST_ILLEGAL(EDX, ECX);
  290.         if (ECX == 0) {    /* some prgs(ld) use 0 */
  291.         EAX = 0;
  292.         return CARRY_OFF;
  293.         }
  294.         if ((npz->p_flags & PF_TERMIO) && EBX == 0) { /* termio */
  295.         if ((i = termio_read(DS, EDX, CX)) < 0) {
  296.             EAX = (long) -i;
  297.             return CARRY_ON;
  298.         } else {
  299.             EAX = (DWORD) i;
  300.             return CARRY_OFF;
  301.         }
  302.         }
  303.         count = ECX;
  304.         off_edx = EDX;
  305.         tr.ebx = EBX;
  306.         tr.edx = (DWORD) (WORD) iobuf;
  307.         tr.flags = FLAGS & ~1;
  308.         while (count > 0) {    /* bytes left */
  309.         tr.ecx = (count <= IOBUF_SIZE) ? count : (DWORD) IOBUF_SIZE;
  310.  
  311.                 if (npz->p_flags & PF_DJGPP_FILE) {
  312.                     bytes = tr.ecx;
  313.                     if ((i = read(BX, iobuf, (WORD) tr.ecx)) == -1) {
  314.                         EAX = (DWORD) doserror_to_errno(_doserrno);
  315.                         return CARRY_ON;
  316.                     }
  317.                     tr.eax = (DWORD) i;
  318.                     tr.ecx = bytes;
  319.                 }
  320.                 else {
  321.                     tr.eax = 0x3f00;
  322.                     if (realdos()) {
  323.                         EAX = tr.eax;
  324.                         FLAGS = tr.flags;
  325.                         return CARRY_NON;
  326.             }
  327.                 }
  328.         cpy16_32(DS, off_edx, iobuf, tr.eax);
  329.         count -= tr.eax;/* sub read bytes */
  330.         if ((WORD) tr.eax < (WORD) tr.ecx)
  331.             break;
  332.         off_edx += tr.ecx;    /* seek user32_buf */
  333.         }
  334.         EAX = ECX - count;
  335.         return CARRY_OFF;
  336.     }
  337.  
  338.     case 0x40:            /* WRITE to file */
  339.     {
  340.         long count;
  341.         DWORD off_edx, bytes;
  342.  
  343.         TEST_ILLEGAL(EDX, ECX);
  344.         count = ECX;
  345.         off_edx = EDX;
  346.         tr.ebx = EBX;
  347.         tr.edx = (DWORD) (WORD) iobuf;
  348.         tr.flags = FLAGS & ~1;
  349.         while (count > 0) {
  350.         tr.ecx = (count <= IOBUF_SIZE) ? count : (DWORD) IOBUF_SIZE;
  351.         cpy32_16(DS, off_edx, iobuf, tr.ecx);
  352.  
  353.                 if (npz->p_flags & PF_DJGPP_FILE) {
  354.                     bytes = tr.ecx;
  355.                     if ((i = write(BX, iobuf, (WORD) tr.ecx)) == -1) {
  356.                         EAX = (DWORD) doserror_to_errno(_doserrno);
  357.                         return CARRY_ON;
  358.                     }
  359.                     tr.eax = (DWORD) i;
  360.                     tr.ecx = bytes;
  361.                 }
  362.                 else {
  363.                     tr.eax = 0x4000;
  364.                     if (realdos()) {
  365.                         EAX = tr.eax;
  366.                         FLAGS = tr.flags;
  367.                         return CARRY_NON;
  368.                     }
  369.                 }
  370.         count -= tr.eax;
  371.         if ((WORD) tr.ecx != (WORD) tr.eax)
  372.             break;
  373.         off_edx += tr.ecx;    /* seek user32_buf */
  374.         }
  375.         EAX = ECX - count;
  376.         return CARRY_OFF;
  377.     }
  378.  
  379.     case 0x47:            /* GET CURR DIRECTORY */
  380.     TEST_ILLEGAL(ESI, 64);
  381.     put_regs();
  382.     tr.esi = (DWORD) (WORD) iobuf;
  383.     if (!realdos())
  384.         cpy16_32(DS, ESI, iobuf, 64L);
  385.     get_regs();
  386.     return CARRY_NON;
  387.  
  388.     case 0x4e:            /* FINDFIRST */
  389.     /* DTA: iobuf byte 0-42 , wild _string: iobuf + 64 */
  390.         if (npz->p_flags & PF_EMX_FILE) {
  391.             /* set dta address to iobuf */
  392.             user_dta = ESI;
  393.             tr.edx = (DWORD) (WORD) iobuf;
  394.             tr.eax = 0x1a00;
  395.             realdos();
  396.         }
  397.     TEST_ILLEGAL(user_dta, 43);
  398.     TEST_ILLEGAL(EDX, 2);
  399.     strcpy32_16(DS, EDX, iobuf + 64);
  400.     tr.eax = EAX;
  401.     tr.ecx = ECX;
  402.     tr.edx = (DWORD) ((WORD) iobuf + 64);
  403.     tr.flags = FLAGS & ~1;
  404.     if (realdos())
  405.         EAX = tr.eax;
  406.     else
  407.         cpy16_32(DS, user_dta, iobuf, 43);
  408.     FLAGS = tr.flags;
  409.     return CARRY_NON;
  410.  
  411.     case 0x4f:            /* FINDNEXT */
  412.     /* DTA: iobuf byte 0-42 */
  413.         if (npz->p_flags & PF_EMX_FILE) {
  414.             user_dta = ESI;
  415.             tr.edx = (DWORD) (WORD) iobuf;
  416.             tr.eax = 0x1a00;
  417.             /* set dta address */
  418.             realdos();
  419.         }
  420.     TEST_ILLEGAL(user_dta, 43);
  421.     /* put user dta in iobuf */
  422.     cpy32_16(DS, user_dta, iobuf, 43);
  423.     tr.eax = EAX;
  424.     tr.flags = FLAGS & ~1;
  425.     if (realdos())
  426.         EAX = tr.eax;
  427.     else
  428.         cpy16_32(DS, user_dta, iobuf, 43);
  429.     FLAGS = tr.flags;
  430.     return CARRY_NON;
  431.  
  432. /***** functions complete changed *****/
  433. /***** need to call DPMI-functions ****/
  434.  
  435.     case 0x48:            /* ALLOC MEM */
  436.     case 0x49:            /* FREE MEM */
  437.     EAX = EMX_EIO;
  438.     return CARRY_ON;
  439.  
  440.     case 0x4a:            /* RESIZE MEM */
  441.     if (npz->p_flags & PF_EMX_FILE) {
  442.         EAX = EMX_EIO;
  443.             return CARRY_ON;
  444.     }
  445.         else {
  446.             if (EAX & 0xff)
  447.                 EAX = getmem(EBX, npz);
  448.             else
  449.                 EAX = npz->brk_value;
  450.             if (EAX == -1)
  451.                 EAX = 0;
  452.             return CARRY_OFF;       /* sbrk.s didn't check carry */
  453.         }
  454.  
  455.     case 0x4c:
  456.     return do_exit4c(0);
  457.  
  458.     default:
  459.     printf("Warning: Not implemented DOS function ah=%02X\n", rAH);
  460.     EAX = EMX_EIO;
  461.     return CARRY_ON;
  462.  
  463.     }                /* switch R_AH */
  464. }
  465.