home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 4 Drivers / 04-Drivers.zip / cs0929a.zip / init.c < prev    next >
C/C++ Source or Header  |  1999-09-29  |  27KB  |  874 lines

  1. //
  2. // init.c
  3. // 3-Feb-99
  4. //
  5. // USHORT stratMode2Init(REQPACK __far *rpPtr);
  6. //
  7. // will make call into slam basedev to get resources (won't use RM... but have to
  8. // write a slam, with IDC hook, probably use assembly like wacker...?)
  9.  
  10. #include "cs40.h"
  11.  
  12. // if these are put in initdata they'll increase file size by 8K
  13.  
  14. const CHAR   signOnMsg[] = "\r\nCS423x & OPL3SAx audio driver [CS40:990929]\r\n";
  15. const CHAR      irqMsg[] = "     IRQ=  ";
  16. const CHAR basePortMsg[] = "basePort=0x";
  17. const CHAR ctrlPortMsg[] = "ctrlPort=0x";
  18. const CHAR     modeMsg[] = "    mode=  ";
  19. const CHAR   deviceMsg[] = "  device=  ";
  20. const CHAR  playDMAMsg[] = "play DMA=  ";
  21. const CHAR playSizeMsg[] = "    size=0x";
  22. const CHAR  playIPBMsg[] = "     IPB=  ";
  23. const CHAR playModeMsg[] = "    mode=  ";
  24. const CHAR   recDMAMsg[] = " rec DMA=  ";
  25. const CHAR  recSizeMsg[] = "    size=0x";
  26. const CHAR   recIPBMsg[] = "     IPB=  ";
  27. const CHAR  recModeMsg[] = "    mode=  ";
  28. const CHAR  clFlagsMsg[] = "   flags=0x";
  29.  
  30. const CHAR  errorPrepMsg[] = "CS40.SYS cmdline parse error: ";
  31. const CHAR *errorMsg[] = {"--X--\r\n",
  32.                           "IRQ (-i:n)\r\n",
  33.                           "Base port (-bp:x)\r\n",
  34.                           "Control port (-cp:x)\r\n",
  35.                           "Mode (-xm:n)\r\n",
  36.                           "Device (-dev:n)\r\n",
  37.                           "Play DMA (-dp:n)\r\n",
  38.                           "Play DMA size (-dps:x)\r\n",
  39.                           "Play DMA IPB (-dpi:n)\r\n",
  40.                           "Play DMA mode (-dpm:n)\r\n",
  41.                           "Rec DMA (-dr:n)\r\n",
  42.                           "Rec DMA size (-drs:x)\r\n",
  43.                           "Rec DMA IPB (-dri:n)\r\n",
  44.                           "Rec DMA mode (-drm:n)\r\n",
  45.                           "Flags (various)\r\n",
  46.                           "Unknown (?)\r\n"};
  47.  
  48. const CHAR *deviceStr[] = {" (CS423x)",
  49.                            " (1?)",
  50.                            " (2?)",
  51.                            " (OPL3SA3)"};
  52.  
  53. const CHAR  initExitMsg[] = "CS40.SYS install error, rc=";
  54.  
  55. #pragma code_seg ("_INITTEXT");
  56. #pragma data_seg ("_INITDATA","ENDDS");
  57.  
  58. #pragma intrinsic (strlen,strcat);
  59. #include "d:\w10a\h\string.h"   // use explicit else uses ddk, etc.
  60.  
  61. extern USHORT endCode;
  62. extern USHORT endData;
  63.  
  64. USHORT ParseCL(UCHAR __far *clPtr);
  65. char __far * __cdecl _itoa (int val,char __far *buf,int radix);
  66. char __far * __cdecl _ltoa (long val,char __far *buf,int radix);
  67. char __far * __cdecl _ultoa (unsigned long val,char __far *buf,int radix);
  68. long __cdecl strtol (const char __far *nptr,char __far * __far *endptr,int ibase);
  69. unsigned long __cdecl strtoul (const char __far *nptr,char __far * __far *endptr,int ibase);
  70.  
  71. // -------------------------------------
  72. // in:
  73. //out:
  74. //nts:
  75.  
  76. USHORT stratMode2Init(REQPACK __far *rpPtr) {
  77.  
  78.  USHORT rc = 0;
  79.  USHORT heapSize;
  80.  USHORT flags = 0;
  81.  CHAR __far *errPtr = 0;
  82.  CHAR valueMsg[64];
  83.  
  84.  Device_Help = rpPtr->init.Device_Help;
  85.  
  86.  rpPtr->status = RPDONE | RPERR | RPGENFAIL;
  87.  rpPtr->init.sizeCS = 0;
  88.  rpPtr->init.sizeDS = 0;
  89.  
  90.  heapSize = HeapInit(8192);
  91.  
  92.  // do any log setup here...
  93.  
  94.  rc = ParseCL(rpPtr->init.argsPtr);
  95.  if (rc) goto ExitRightNow;
  96.  
  97.  errPtr = "CS40: Installed\r\n";
  98.  
  99.  // resource manager access here (create, detect PnP, etc.) here...
  100.  
  101.  // had created IRQ object for timer here...
  102.  // had setup more hardware types here (FMSYNTH or MPU...)
  103.  
  104.  flags = 0;
  105.  if (gDMAplay != gDMArec) flags = flags | FLAGS_WAVEAUDIO_FULLDUPLEX;
  106.  if (gDMAplay >= 4)       flags = flags | FLAGS_WAVEAUDIO_DMA16;
  107.  if (gDMAplayMode != 0)   flags = flags | FLAGS_WAVEAUDIO_FTYPEDMA;
  108.  
  109.  rc = waveplayInit(gDMAplay, flags, gIRQ);
  110.  
  111.  if (rc) {
  112. if (gCLflags & FLAGS_CL_DDPRINT) ddprintf("waveplayInit() failed, rc=%u\n");
  113.     goto ExitNow;
  114.  }
  115.  
  116.  flags = 0;
  117.  if (gDMAplay != gDMArec) flags = flags | FLAGS_WAVEAUDIO_FULLDUPLEX;
  118.  if (gDMArec >= 4)        flags = flags | FLAGS_WAVEAUDIO_DMA16;
  119.  if (gDMArecMode != 0)    flags = flags | FLAGS_WAVEAUDIO_FTYPEDMA;
  120.  
  121.  rc = waverecInit(gDMArec, flags, gIRQ);
  122.  
  123.  if (rc) {
  124.     errPtr = "waverecInit() failed";
  125. if (gCLflags & FLAGS_CL_DDPRINT) ddprintf("waverecInit() failed, rc=%u\n");
  126.     goto ExitNow;
  127.  }
  128.  
  129.  rc = chipsetInit();
  130.  if (rc) goto ExitNow;
  131.  
  132.  if (gCLflags & FLAGS_CL_SETDTM) chipsetSetDTM(gCLflags & FLAGS_CL_SETDTM);
  133.  
  134.  // had init'ed mixer here...
  135.  //InitMixer();
  136.  
  137.  // had done VDD setup here...
  138.  // fill in the ADAPTERINFO
  139.  //codec_info.ulNumPorts = NUMIORANGES;
  140.  //codec_info.Range[0].ulPort  =  pResourcesWSS->uIOBase[0];
  141.  //codec_info.Range[0].ulRange =  pResourcesWSS->uIOLength[0];
  142.  //...
  143.  //// set up the addressing to the codec data for the vdd
  144.  //pfcodec_info = (ADAPTERINFO __far *)&codec_info;
  145.  //DevHelp_VirtToLin (SELECTOROF(pfcodec_info), (ULONG)(OFFSETOF(pfcodec_info)),(PLIN)&pLincodec);
  146.  // copy the pdd name out of the header.
  147.  //for (i = 0; i < sizeof(szPddName)-1 ; i++) {
  148.  //   if (phdr->abName[i] <= ' ')
  149.  //      break;
  150.  //   szPddName[i] = phdr->abName[i];
  151.  //}
  152.  //// register the VDD IDC entry point..
  153.  //DevHelp_RegisterPDD ((NPSZ)szPddName, (PFN)IDCEntry_VDD);
  154.  
  155.  if (gCLflags & FLAGS_CL_TESTONLY) rc = 666;
  156.  
  157.  if (rc) goto ExitNow;
  158.  
  159.  rpPtr->status = RPDONE;
  160.  rpPtr->init.sizeCS = (USHORT)&endCode;
  161.  rpPtr->init.sizeDS = (USHORT)&endData;
  162.  
  163. if (gCLflags & FLAGS_CL_DDPRINT) ddprintf("stratMode2Init:endCode=%x, endData=%x, ds=%x\n",rpPtr->init.sizeCS,rpPtr->init.sizeDS,_DS());
  164.  
  165. ExitNow:
  166.  
  167.  if (rc && (gCLflags & FLAGS_CL_QUIET) == 0) {
  168.     DosPutMessage(STDOUT,_fstrlen(initExitMsg),initExitMsg);
  169.     _ultoa(rc,valueMsg,10);
  170.     _fstrcat(valueMsg,"\r\n");
  171.     DosPutMessage(STDOUT,_fstrlen(valueMsg),valueMsg);
  172.  }
  173.  
  174. ExitRightNow:
  175.  return rc;
  176. }
  177.  
  178. // ------------------------------------------------------
  179. //USHORT gIRQ          = 99;       // 1  -i:5
  180. //USHORT gBasePort     = 0;        // 2  -bp:534
  181. //USHORT gCtrlPort     = 0;        // 3  -cp:390
  182. //USHORT gMode         = 2;        // 4  -xm:2
  183. //USHORT gDevice       = 99;       // 5  -dev:3       0=CS 3=OPL3SA3
  184. //USHORT gDMAplay      = 99;       // 6  -dp:1
  185. //USHORT gDMAplaySize  = 0x8000;   // 7  -dps:8000    DMA buffer size (max is 60KB)
  186. //USHORT gDMAplayIPB   = 2;        // 8  -dpi:2       ints per buffer -- power of 2 (2,4,8,16,32)
  187. //USHORT gDMAplayMode  = 1;        // 9  -dpm:1       1=typeF DMA, else not
  188. //USHORT gDMArec       = 99;       //10  -dr:0        can be same -dp: (then is not full duplex)
  189. //USHORT gDMArecSize   = 0x8000;   //11  -drs:8000    DMA buffer size (max is 60KB)
  190. //USHORT gDMArecIPB    = 2;        //12  -dri:2       ints per buffer -- power of 2 (2,4,8,16,32)
  191. //USHORT gDMArecMode   = 1;        //13  -drm:1       1=typeF DMA, else not
  192. //USHORT gCLflags      = 0;        //14  various flags (-v bit0=1, ...)
  193. //                                 //15 none of the above
  194. //#define FLAGS_CL_VERBOSE  1
  195.  
  196. USHORT ParseCL(UCHAR __far *clPtr) {
  197.  
  198.  USHORT rc = 0;
  199.  ULONG tVal;
  200.  UCHAR __far *tPtr = clPtr;
  201.  UCHAR __far *ePtr = 0;
  202.  UCHAR __far *argListPtr = 0;
  203.  
  204.  UCHAR sw0, sw1, sw2, sw3;
  205.  CHAR valueMsg[64];
  206.  
  207.  // cs40.sys -
  208.  // skip over filename
  209.  
  210.  while (*tPtr && *tPtr != ' ') {
  211.     tPtr++;
  212.  }
  213.  
  214.  while (*tPtr && (rc == 0)) {
  215.  
  216.     tPtr++;            // skip to next
  217.  
  218.     if (*tPtr == '-') {
  219.  
  220.        if (argListPtr == 0) argListPtr = tPtr;
  221.  
  222.        tPtr++;          // after - switch
  223.        sw0 = *(tPtr+0); // first (eg, d)
  224.        sw1 = *(tPtr+1); // next char, eg, ':'
  225.        sw2 = *(tPtr+2); // ...
  226.        sw3 = *(tPtr+3); // ... (if used can only be :)
  227.  
  228.        switch(sw0) {
  229.        case 'i':
  230.           rc = 1;
  231.           if (sw1 == ':') {
  232.              tVal = strtoul((tPtr+2),&ePtr,10);
  233.              switch(tVal) {
  234.              case 3:
  235.              case 5:
  236.              case 7:
  237.              case 9:
  238.              case 10:
  239.              case 11:
  240.              case 12: // i12 not for OPL3SA3 though
  241.                 gIRQ = tVal;
  242.                 rc = 0;
  243.                 break;
  244.              }
  245.              tPtr = ePtr;
  246.           }
  247.           break;
  248.  
  249.        case 'b':
  250.           rc = 2;
  251.           if (sw1 == 'p' && sw2 == ':') {
  252. int3();
  253.              tVal = strtoul((tPtr+3),&ePtr,16);
  254.              if (tVal >= 0x100 && tVal <= 0xFFF) {
  255.                 gBasePort = tVal;
  256.                 rc = 0;
  257.              }
  258.              tPtr = ePtr;
  259.           }
  260.           break;
  261.  
  262.        case 'c':
  263.           rc = 3;
  264.           if (sw1 == 'p' && sw2 == ':') {
  265.              tVal = strtoul((tPtr+3),&ePtr,16);
  266.              if (tVal >= 0x100 && tVal <= 0xFFF) {
  267.                 gCtrlPort = tVal;
  268.                 rc = 0;
  269.              }
  270.              tPtr = ePtr;
  271.           }
  272.           break;
  273.  
  274.        case 'x':
  275.           rc = 4;
  276.           if (sw1 == 'm' && sw2 == ':') {
  277.              // only know mode2
  278.              rc = 0;
  279.           }
  280.           break;
  281.  
  282.        case 'd':
  283.           rc = 5;
  284.           switch(sw1) {
  285.           case 'e':                                    // dev:
  286.              if (sw2 == 'v' && sw3 == ':') {
  287.                 tVal = strtoul((tPtr+4),&ePtr,10);
  288.                 if (tVal == 0 || tVal == 3) {
  289.                    gDevice = tVal;
  290.                    rc = 0;
  291.                 }
  292.                 tPtr = ePtr;
  293.              }
  294.              break;
  295.  
  296.           case 'p':                                    // dp*:
  297.              rc = 6;
  298.              switch(sw2) {
  299.              case ':':                                 // dp:
  300.                 tVal = strtoul((tPtr+3),&ePtr,10);
  301.                 switch(tVal) {
  302.                 case 0:
  303.                 case 1:
  304.                 case 3:
  305.                    gDMAplay = tVal;
  306.                    rc = 0;
  307.                 }
  308.                 tPtr = ePtr;
  309.                 break; // case dp:
  310.  
  311.              case 's':
  312.                 rc = 7;
  313.                 if (sw3 == ':') {
  314.                    tVal = strtoul((tPtr+4),&ePtr,16);
  315.                    if ((tVal & 0xFFF) == 0) {  // align 4K
  316.                       gDMAplaySize = tVal;
  317.                       rc = 0;
  318.                    }
  319.                    tPtr = ePtr;
  320.                 }
  321.                 break; // case dps
  322.  
  323.              case 'i':
  324.                 rc = 8;
  325.                 if (sw3 == ':') {
  326.                    tVal = strtoul((tPtr+4),&ePtr,10);
  327.                    switch(tVal) {
  328.                    case 2:
  329.                    case 4:
  330.                    case 8:
  331.                    case 16:
  332.                    case 32:
  333.                       gDMAplayIPB = tVal;
  334.                       rc = 0;
  335.                    }
  336.                    tPtr = ePtr;
  337.                 }
  338.                 break; // case dpi
  339.  
  340.              case 'm':
  341.                 rc = 9;
  342.                 if (sw3 == ':') {
  343.                    tVal = strtoul((tPtr+4),&ePtr,10);
  344.                    if (tVal == 0 || tVal == 1) {
  345.                       gDMAplayMode = tVal;
  346.                       rc = 0;
  347.                    }
  348.                    tPtr = ePtr;
  349.                 }
  350.                 break;  // case dpm
  351.              }
  352.              break;  // case dp
  353.  
  354.           case 'r':                                    // dr*:
  355.              rc = 10;
  356.              switch(sw2) {
  357.              case ':':                                 // dp:
  358.                 tVal = strtoul((tPtr+3),&ePtr,10);
  359.                 switch(tVal) {
  360.                 case 0:
  361.                 case 1:
  362.                 case 3:
  363.                    gDMArec = tVal;
  364.                    rc = 0;
  365.                 }
  366.                 tPtr = ePtr;
  367.                 break; // case dr:
  368.  
  369.              case 's':
  370.                 rc = 11;
  371.                 if (sw3 == ':') {
  372.                    tVal = strtoul((tPtr+4),&ePtr,16);
  373.                    if ((tVal & 0xFFF) == 0) {  // align 4K
  374.                       gDMArecSize = tVal;
  375.                       rc = 0;
  376.                    }
  377.                    tPtr = ePtr;
  378.                 }
  379.                 break; // case drs
  380.  
  381.              case 'i':
  382.                 rc = 12;
  383.                 if (sw3 == ':') {
  384.                    tVal = strtoul((tPtr+4),&ePtr,10);
  385.                    switch(tVal) {
  386.                    case 2:
  387.                    case 4:
  388.                    case 8:
  389.                    case 16:
  390.                    case 32:
  391.                       gDMArecIPB = tVal;
  392.                       rc = 0;
  393.                    }
  394.                    tPtr = ePtr;
  395.                 }
  396.                 break; // case dri
  397.  
  398.              case 'm':
  399.                 rc = 13;
  400.                 if (sw3 == ':') {
  401.                    tVal = strtoul((tPtr+4),&ePtr,10);
  402.                    if (tVal == 0 || tVal == 1) {
  403.                       gDMArecMode = tVal;
  404.                       rc = 0;
  405.                    }
  406.                    tPtr = ePtr;
  407.                 }
  408.                 break; // case drm
  409.                 //
  410.              }
  411.              break; // case 'dr'
  412.           }
  413.           break;  // case 'd'
  414.  
  415.        case 'v':
  416.           rc = 30;
  417.           if (sw1 == ' ' || sw1 == 0) {
  418.              gCLflags = gCLflags | FLAGS_CL_VERBOSE;
  419.              rc = 0;
  420.           }
  421.           break;
  422.  
  423.        case 'z':
  424.           rc = 30;
  425.           switch(sw1) {
  426.           case '1':
  427.              gCLflags = gCLflags | FLAGS_CL_SETDTM;
  428.              rc = 0;
  429.              break;
  430.           case '2':
  431.              gCLflags = gCLflags | FLAGS_CL_SETACAL;
  432.              rc = 0;
  433.              break;
  434.  
  435.           case 'e':
  436.              gCLflags = gCLflags | FLAGS_CL_DDPRINT;
  437.              rc = 0;
  438.              break;
  439.           }
  440.           break;
  441.  
  442.        case 'Q':
  443.           rc = 30;
  444.           if (sw1 == ' ' || sw1 == 0) {
  445.              gCLflags = gCLflags | FLAGS_CL_QUIET;
  446.              rc = 0;
  447.           }
  448.           break;
  449.  
  450.        case 't':
  451.           rc = 30;
  452.           if (sw1 == ' ' || sw1 == 0) {
  453.              gCLflags = gCLflags | FLAGS_CL_TESTONLY;
  454.              rc = 0;
  455.           }
  456.           break;
  457.  
  458.        default:
  459.           rc = 31;
  460.        }
  461.  
  462.     } // if *tPtr = '-'
  463.  }    // while (*tPtr && (rc == 0)) {
  464.  
  465.  if ((gCLflags & FLAGS_CL_QUIET) == 0) {
  466.     DosPutMessage(STDOUT,_fstrlen(signOnMsg),signOnMsg);
  467.  }
  468.  
  469.  if (gCLflags & FLAGS_CL_VERBOSE) {
  470.  
  471.     if (argListPtr) {
  472.        _fstrcpy(valueMsg,"device=cs40.sys ");
  473.        DosPutMessage(STDOUT,_fstrlen(valueMsg),valueMsg);
  474.        DosPutMessage(STDOUT,_fstrlen(argListPtr),argListPtr);
  475.        _fstrcpy(valueMsg,"\r\n");
  476.        DosPutMessage(STDOUT,_fstrlen(valueMsg),valueMsg);
  477.     }
  478.  
  479.     DosPutMessage(STDOUT,_fstrlen(irqMsg),irqMsg);
  480.     if (gIRQ == 99) {
  481.        _fstrcpy(valueMsg," *not set*\r\n");
  482.     }
  483.     else {
  484.        valueMsg[0] = 0;
  485.        _ultoa(gIRQ,valueMsg,10);
  486.        _fstrcat(valueMsg,"\r\n");
  487.     }
  488.     DosPutMessage(STDOUT,_fstrlen(valueMsg),valueMsg);
  489.  
  490.     DosPutMessage(STDOUT,_fstrlen(basePortMsg),basePortMsg);
  491.     if (gBasePort == 99) {
  492.        _fstrcpy(valueMsg," *not set*\r\n");
  493.     }
  494.     else {
  495.        valueMsg[0] = 0;
  496.        _ultoa(gBasePort,valueMsg,16);
  497.        _fstrcat(valueMsg,"\r\n");
  498.     }
  499.     DosPutMessage(STDOUT,_fstrlen(valueMsg),valueMsg);
  500.  
  501.     DosPutMessage(STDOUT,_fstrlen(ctrlPortMsg),ctrlPortMsg);
  502.     if (gCtrlPort == 99) {
  503.        _fstrcpy(valueMsg," *not set*\r\n");
  504.     }
  505.     else {
  506.        valueMsg[0] = 0;
  507.        _ultoa(gCtrlPort,valueMsg,16);
  508.        _fstrcat(valueMsg,"\r\n");
  509.     }
  510.     DosPutMessage(STDOUT,_fstrlen(valueMsg),valueMsg);
  511.  
  512.     DosPutMessage(STDOUT,_fstrlen(modeMsg),modeMsg);
  513.     valueMsg[0] = 0;
  514.     _ultoa(gMode,valueMsg,10);
  515.     _fstrcat(valueMsg,"\r\n");
  516.     DosPutMessage(STDOUT,_fstrlen(valueMsg),valueMsg);
  517.  
  518.     DosPutMessage(STDOUT,_fstrlen(deviceMsg),deviceMsg);
  519.     if (gDevice > 3) gDevice = 99;
  520.     if (gDevice == 99) {
  521.        _fstrcpy(valueMsg," *not set*\r\n");
  522.     }
  523.     else {
  524.        valueMsg[0] = 0;
  525.        _ultoa(gDevice,valueMsg,10);
  526.        _fstrcat(valueMsg,deviceStr[gDevice]);
  527.        _fstrcat(valueMsg,"\r\n");
  528.     }
  529.     DosPutMessage(STDOUT,_fstrlen(valueMsg),valueMsg);
  530.  
  531.     DosPutMessage(STDOUT,_fstrlen(playDMAMsg),playDMAMsg);
  532.     if (gDMAplay == 99) {
  533.        _fstrcpy(valueMsg," *not set*\r\n");
  534.     }
  535.     else {
  536.        valueMsg[0] = 0;
  537.        _ultoa(gDMAplay,valueMsg,10);
  538.        _fstrcat(valueMsg,"\r\n");
  539.     }
  540.     DosPutMessage(STDOUT,_fstrlen(valueMsg),valueMsg);
  541.  
  542.     DosPutMessage(STDOUT,_fstrlen(playSizeMsg),playSizeMsg);
  543.     valueMsg[0] = 0;
  544.     _ultoa(gDMAplaySize,valueMsg,16);
  545.     _fstrcat(valueMsg,"\r\n");
  546.     DosPutMessage(STDOUT,_fstrlen(valueMsg),valueMsg);
  547.  
  548.     DosPutMessage(STDOUT,_fstrlen(playIPBMsg),playIPBMsg);
  549.     valueMsg[0] = 0;
  550.     _ultoa(gDMAplayIPB,valueMsg,10);
  551.     _fstrcat(valueMsg,"\r\n");
  552.     DosPutMessage(STDOUT,_fstrlen(valueMsg),valueMsg);
  553.  
  554.     DosPutMessage(STDOUT,_fstrlen(playModeMsg),playModeMsg);
  555.     valueMsg[0] = 0;
  556.     _ultoa(gDMAplayMode,valueMsg,10);
  557.     _fstrcat(valueMsg,"\r\n");
  558.     DosPutMessage(STDOUT,_fstrlen(valueMsg),valueMsg);
  559.  
  560.     DosPutMessage(STDOUT,_fstrlen(recDMAMsg),recDMAMsg);
  561.     if (gDMArec == 99) {
  562.        _fstrcpy(valueMsg," *not set*\r\n");
  563.     }
  564.     else {
  565.        valueMsg[0] = 0;
  566.        _ultoa(gDMArec,valueMsg,10);
  567.        _fstrcat(valueMsg,"\r\n");
  568.     }
  569.     DosPutMessage(STDOUT,_fstrlen(valueMsg),valueMsg);
  570.  
  571.     DosPutMessage(STDOUT,_fstrlen(recSizeMsg),recSizeMsg);
  572.     valueMsg[0] = 0;
  573.     _ultoa(gDMArecSize,valueMsg,16);
  574.     _fstrcat(valueMsg,"\r\n");
  575.     DosPutMessage(STDOUT,_fstrlen(valueMsg),valueMsg);
  576.  
  577.     DosPutMessage(STDOUT,_fstrlen(recIPBMsg),recIPBMsg);
  578.     valueMsg[0] = 0;
  579.     _ultoa(gDMArecIPB,valueMsg,10);
  580.     _fstrcat(valueMsg,"\r\n");
  581.     DosPutMessage(STDOUT,_fstrlen(valueMsg),valueMsg);
  582.  
  583.     DosPutMessage(STDOUT,_fstrlen(recModeMsg),recModeMsg);
  584.     valueMsg[0] = 0;
  585.     _ultoa(gDMArecMode,valueMsg,10);
  586.     _fstrcat(valueMsg,"\r\n");
  587.     DosPutMessage(STDOUT,_fstrlen(valueMsg),valueMsg);
  588.  
  589.     DosPutMessage(STDOUT,_fstrlen(clFlagsMsg),clFlagsMsg);
  590.     valueMsg[0] = 0;
  591.     _ultoa(gCLflags,valueMsg,16);
  592.     _fstrcat(valueMsg,"\r\n");
  593.     DosPutMessage(STDOUT,_fstrlen(valueMsg),valueMsg);
  594.  
  595.  }
  596.  
  597.  if (gIRQ == 99)           rc = 1;
  598.  else if (gBasePort == 99) rc = 2;
  599.  else if (gCtrlPort == 99) rc = 3;
  600.  else if (gDevice == 99)   rc = 5;
  601.  else if (gDMAplay == 99)  rc = 6;
  602.  else if (gDMArec == 99)   rc = 10;
  603.  // rest are optional
  604.  
  605.  if (rc) {
  606.     USHORT trc = rc;
  607.     if (trc > 14) trc = 15;
  608.     DosPutMessage(STDOUT,_fstrlen(errorPrepMsg),errorPrepMsg);
  609.     DosPutMessage(STDOUT,_fstrlen(errorMsg[trc]),errorMsg[trc]);
  610.  }
  611.  
  612.  return rc;
  613.  
  614. }
  615.  
  616. //*******************************************************************************
  617. //*strtol, strtoul(nptr,endptr,ibase) - Convert ascii string to long un/signed int
  618. //
  619. //*       Convert an ascii string to a long 32-bit value.  The base
  620. //*       used for the caculations is supplied by the caller.  The base
  621. //*       must be in the range 0, 2-36.  If a base of 0 is supplied, the
  622. //*       ascii string must be examined to determine the base of the
  623. //*       number:
  624. //*               (a) First char = '0', second char = 'x' or 'X', use base 16
  625. //*               (b) First char = '0', use base 8
  626. //*               (c) First char in range '1' - '9', use base 10
  627. //*
  628. //*       If the 'endptr' value is non-NULL, then strtol/strtoul places
  629. //*       a pointer to the terminating character in this value
  630. //*
  631. //*Entry:
  632. //*       nptr == NEAR/FAR pointer to the start of string.
  633. //*       endptr == NEAR/FAR pointer to the end of the string.
  634. //*       ibase == integer base to use for the calculations.
  635. //*
  636. //*       string format: [whitespace] [sign] [0] [x] [digits/letters]
  637. //*
  638. //*Exit:
  639. //*       Good return:
  640. //*               result
  641. //*
  642. //*       Overflow return:
  643. //*               strtol -- LONG_MAX or LONG_MIN
  644. //*               strtoul -- ULONG_MAX
  645. //*               strtol/strtoul -- errno == ERANGE
  646. //*
  647. //*       No digits or bad base return:
  648. //*               0
  649. //*               endptr = nptr*
  650. //*******************************************************************************
  651.  
  652. /* flag values */
  653. #define FL_UNSIGNED   1       /* strtoul called */
  654. #define FL_NEG        2       /* negative sign found */
  655. #define FL_OVERFLOW   4       /* overflow occured */
  656. #define FL_READDIGIT  8       /* we've read at least one correct digit */
  657.  
  658. #define ULONG_MAX 0xFFFFFFFF
  659. #define LONG_MAX  0x7FFFFFFF
  660. #define LONG_MIN  0x80000000
  661.  
  662. static unsigned long __cdecl strtoxl (const char __far *nptr,const char __far * __far *endptr,int ibase,int flags) {
  663.  
  664.  const char __far *p;
  665.  char c;
  666.  unsigned long number;
  667.  unsigned digval;
  668.  unsigned long maxval;
  669.  
  670.  p = nptr;                       /* p is our scanning pointer */
  671.  number = 0;                     /* start with zero */
  672.  
  673.  c = *p++;                       /* read char */
  674.  while ((unsigned char)c == ' ')
  675.          c = *p++;               /* skip whitespace */
  676.  
  677.  if (c == '-') {
  678.          flags |= FL_NEG;        /* remember minus sign */
  679.          c = *p++;
  680.  }
  681.  else if (c == '+')
  682.          c = *p++;               /* skip sign */
  683.  
  684.  if (ibase < 0 || ibase == 1 || ibase > 36) {
  685.          /* bad base! */
  686.          if (endptr)
  687.                  /* store beginning of string in endptr */
  688.                  *endptr = nptr;
  689.          return 0L;              /* return 0 */
  690.  }
  691.  else if (ibase == 0) {
  692.          /* determine base free-lance, based on first two chars of
  693.             string */
  694.          if (c != '0')
  695.                  ibase = 10;
  696.          else if (*p == 'x' || *p == 'X')
  697.                  ibase = 16;
  698.          else
  699.                  ibase = 8;
  700.  }
  701.  
  702.  if (ibase == 16) {
  703.          /* we might have 0x in front of number; remove if there */
  704.          if (c == '0' && (*p == 'x' || *p == 'X')) {
  705.                  ++p;
  706.                  c = *p++;       /* advance past prefix */
  707.          }
  708.  }
  709.  
  710.  /* if our number exceeds this, we will overflow on multiply */
  711.  maxval = ULONG_MAX / ibase;
  712.  
  713.  
  714.  for (;;) {      /* exit in middle of loop */
  715.          /* convert c to value */
  716.          //if ( isdigit((int)(unsigned char)c) )
  717.          //        digval = c - '0';
  718.          //else if ( isalpha((int)(unsigned char)c) )
  719.          //        digval = toupper(c) - 'A' + 10;
  720.          //else
  721.          //        break;
  722.  
  723.          if (c >= '0' && c <= '9') {
  724.             digval = c - '0';
  725.          }
  726.          else if (c >= 'a' && c <= 'z') {
  727.             digval = c - 'a' + 10;
  728.          }
  729.          else if (c >= 'A' && c <= 'Z') {
  730.             digval = c - 'A' + 10;
  731.          }
  732.          else {
  733.             break;
  734.          }
  735.  
  736.          if (digval >= (unsigned)ibase) break;          /* exit loop if bad digit found */
  737.  
  738.          /* record the fact we have read one digit */
  739.          flags |= FL_READDIGIT;
  740.  
  741.          /* we now need to compute number = number * base + digval,
  742.             but we need to know if overflow occured.  This requires
  743.             a tricky pre-check. */
  744.  
  745.          if (number < maxval || (number == maxval &&
  746.          (unsigned long)digval <= ULONG_MAX % ibase)) {
  747.                  /* we won't overflow, go ahead and multiply */
  748.                  number = number * ibase + digval;
  749.          }
  750.          else {
  751.                  /* we would have overflowed -- set the overflow flag */
  752.                  flags |= FL_OVERFLOW;
  753.          }
  754.  
  755.          c = *p++;               /* read next digit */
  756.  }
  757.  
  758.  --p;                            /* point to place that stopped scan */
  759.  
  760.  if (!(flags & FL_READDIGIT)) {
  761.          /* no number there; return 0 and point to beginning of string */
  762.          if (endptr)
  763.                  /* store beginning of string in endptr later on */
  764.                  p = nptr;
  765.          number = 0L;            /* return 0 */
  766.  }
  767.  else if ( (flags & FL_OVERFLOW) ||
  768.            ( !(flags & FL_UNSIGNED) &&
  769.              ( ( (flags & FL_NEG) && (number > -LONG_MIN) ) ||
  770.                ( !(flags & FL_NEG) && (number > LONG_MAX) ) ) ) )
  771.  {
  772.          /* overflow or signed overflow occurred */
  773.          //chh removederrno = ERANGE;
  774.          if ( flags & FL_UNSIGNED )
  775.                  number = ULONG_MAX;
  776.          else if ( flags & FL_NEG )
  777.                  number = (unsigned long)(-LONG_MIN);
  778.          else
  779.                  number = LONG_MAX;
  780.  }
  781.  
  782.  if (endptr != NULL) *endptr = p;
  783.  if (flags & FL_NEG) number = (unsigned long)(-(long)number);
  784.  
  785.  return number;     
  786. }
  787.  
  788. long __cdecl strtol (const char __far *nptr,char __far * __far *endptr,int ibase) {
  789.  return (long) strtoxl(nptr, endptr, ibase, 0);
  790. }
  791.  
  792. unsigned long __cdecl strtoul (const char __far *nptr,char __far * __far *endptr,int ibase) {
  793.  return strtoxl(nptr, endptr, ibase, FL_UNSIGNED);
  794. }
  795.  
  796.  
  797. //*******************************************************************************
  798. //*char *_itoa, *_ltoa, *_ultoa(val, buf, radix) - convert int to ASCII string
  799. //*Entry:
  800. //*       val - number to be converted (int, long or unsigned long)
  801. //*       int radix - base to convert into
  802. //*       char *buf - ptr to buffer to place result
  803. //*Exit:
  804. //*       fills in space pointed to by buf with string result
  805. //*       returns a pointer to this buffer
  806. //*******************************************************************************
  807.  
  808. /* helper routine that does the main job. */
  809.  
  810. static void __cdecl xtoa (unsigned long val,char __far *buf,unsigned radix,int is_neg) {
  811.  
  812.  char __far *p;                /* pointer to traverse string */
  813.  char __far *firstdig;         /* pointer to first digit */
  814.  char temp;              /* temp char */
  815.  unsigned digval;        /* value of digit */
  816.  
  817.  p = buf;
  818.  
  819.  if (is_neg) {
  820.      /* negative, so output '-' and negate */
  821.      *p++ = '-';
  822.      val = (unsigned long)(-(long)val);
  823.  }
  824.  
  825.  firstdig = p;           /* save pointer to first digit */
  826.  
  827.  do {
  828.      digval = (unsigned) (val % radix);
  829.      val /= radix;       /* get next digit */
  830.  
  831.      /* convert to ascii and store */
  832.      if (digval > 9)
  833.          *p++ = (char) (digval - 10 + 'a');  /* a letter */
  834.      else
  835.          *p++ = (char) (digval + '0');       /* a digit */
  836.  } while (val > 0);
  837.  
  838.  /* We now have the digit of the number in the buffer, but in reverse
  839.     order.  Thus we reverse them now. */
  840.  
  841.  *p-- = '\0';            /* terminate string; p points to last digit */
  842.  
  843.  do {
  844.      temp = *p;
  845.      *p = *firstdig;
  846.      *firstdig = temp;   /* swap *p and *firstdig */
  847.      --p;
  848.      ++firstdig;         /* advance to next two digits */
  849.  } while (firstdig < p); /* repeat until halfway */
  850. }
  851.  
  852. /* Actual functions just call conversion helper with neg flag set correctly,
  853.    and return pointer to buffer. */
  854.  
  855. char __far * __cdecl _itoa (int val,char __far *buf,int radix) {
  856.  if (radix == 10 && val < 0)
  857.     xtoa((unsigned long)val, buf, radix, 1);
  858.  else
  859.     xtoa((unsigned long)(unsigned int)val, buf, radix, 0);
  860.  return buf;
  861. }
  862.  
  863. char __far * __cdecl _ltoa (long val,char __far *buf,int radix) {
  864.  xtoa((unsigned long)val, buf, radix, (radix == 10 && val < 0));
  865.  return buf;
  866. }
  867.  
  868. char __far * __cdecl _ultoa (unsigned long val,char __far *buf,int radix) {
  869.  xtoa(val, buf, radix, 0);
  870.  return buf;
  871. }
  872.  
  873.  
  874.