home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional Developers Kit 1992 November / Disc01 / Disc01.mdf / runnable / mmos2 / mmtoolkt / samples / audiodd / audiodd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-06  |  19.1 KB  |  505 lines

  1. /**************************START OF SPECIFICATIONS **************************/
  2. /*                                                                          */
  3. /* SOURCE FILE NAME:  AUDIODD.C         (TEMPLATE SAMPLE)                   */
  4. /*                                                                          */
  5. /* DISCRIPTIVE NAME: Audio device driver strategy and IOCTL routines        */
  6. /*                                                                          */
  7. /* LINKAGE: Called from Startup.asm                                         */
  8. /*                                                                          */
  9. /* DESCRIPTION:                                                             */
  10. /*    This audio device driver is an OS/2 16-bit Physical Device driver     */
  11. /*    designed to demonstrate audio device communication with the           */
  12. /*    MMPM/2 stream handler.                                                */
  13. /*    Information on OS/2 Physical Device Drivers architecture and          */
  14. /*    programming is in the "OS/2 2.0 Physical Device Driver reference"     */
  15. /*                                                                          */
  16. /*    MMPM/2 streaming architecture is outlined in                          */
  17. /*    "MMPM/2 Programmers Workbook"                                         */
  18. /*       - Data Streaming & synchronization chapter                         */
  19. /*    Specifix information on interdevice communication is in the           */
  20. /*    same document in the "Stream Handler" Chapter in the section on       */
  21. /*    "Interdevice-driver-communication                                     */
  22. /************************** END OF SPECIFICATIONS ***************************/
  23.  
  24.  
  25. #define NUMGDTS 1L
  26. #define  INCL_DOSINFOSEG
  27. #include <os2.h>
  28.  
  29. #include <os2medef.h>
  30. #include <ssm.h>
  31. #include <audio.h>
  32. #include "audiodd.h"
  33. #include "audsubs.h"
  34. #include "cdevhlp.h"
  35.  
  36. extern ULONG   (*IOCTLFuncs[])(PREQPACKET rp);
  37. extern MaxIOCTLFuncs;
  38. extern ULONG   (*AudioIOCTLFuncs[])(PVOID pParm);
  39. extern MaxAudioIOCTLFuncs;
  40. extern FPVOID  DevHlp;
  41. extern EndOfData;
  42. extern GLOBAL GlobalTable;
  43.  
  44. int   mode = MIDI;
  45. unsigned long flags = 0;
  46. long  srate;
  47. long  bits_per_sample;
  48. long  bsize;
  49. int   channels;
  50. unsigned long  operation;
  51. int   position_type;
  52.  
  53.  
  54. /*********************************************************************/
  55. /* STRATEGY_C                                                        */
  56. /* DD strategy control after entry from assembler Strategy routine.  */
  57. /*********************************************************************/
  58.  
  59. ULONG   Strategy_c(PREQPACKET rp)
  60. {
  61.         if (rp->RPcommand > (UCHAR)MaxIOCTLFuncs) // check for valid function
  62.                 return(RPDONE | RPERR | RPBADCMD);
  63.  
  64.         return(IOCTLFuncs[rp->RPcommand](rp));  // call request function
  65.                                                 // then return its rc
  66. }
  67.  
  68.  
  69. /*******************************************************************************/
  70. /*                         INVALID REQUEST                                     */
  71. /*******************************************************************************/
  72. ULONG   IOCTL_Invalid(PREQPACKET rp)
  73. {
  74.         return(RPDONE | RPERR | RPBADCMD);
  75. }
  76.  
  77. /*****************************************************************************/
  78. /*                      Hardware communication routines                      */
  79. /* Implementation of these functions is dependant on interfaces and physical */
  80. /* characteristics of the card.                                              */
  81. /* IOCTLs listed below are OS/2 defined IOCTLs.  Additional IOCTLs arrive    */
  82. /* from applications and MMPM/2 through the OS/2 generic IOCTL.              */
  83. /*****************************************************************************/
  84.  
  85. /*****************************************************************************/
  86. /*                              READ                                         */
  87. /* Stub, read from device.  Implemention dependant on hardware architecture. */
  88. /*****************************************************************************/
  89. ULONG   IOCTL_Read(PREQPACKET rp)
  90. {
  91.         ReadDataFromCard();     // Stub routine
  92.         return(RPDONE);
  93. }
  94.  
  95. /*****************************************************************************/
  96. /*                        NONDESTRUCTIVE READ                                */
  97. /* Stub, routine performing nondestructive read operation.                   */
  98. /* This read operation reads data from a buffer without removing that data.  */
  99. /*****************************************************************************/
  100. ULONG   IOCTL_NondestructiveRead(PREQPACKET rp)
  101. {
  102.         return(RPDONE);
  103. }
  104.  
  105. /*****************************************************************************/
  106. /*                           READ STATUS                                     */
  107. /* Stub routine                                                              */
  108. /*****************************************************************************/
  109. ULONG   IOCTL_ReadStatus(PREQPACKET rp)
  110. {
  111.         ReadStatus();
  112.         return(RPDONE);
  113. }
  114.  
  115. /*****************************************************************************/
  116. /*                            FLUSH INPUT                                    */
  117. /*****************************************************************************/
  118. ULONG   IOCTL_FlushInput(PREQPACKET rp)
  119. {
  120.         FlushInputBuffers();
  121.         return(RPDONE);
  122. }
  123.  
  124. /*****************************************************************************/
  125. /*                          WRITE                                            */
  126. /* Stub, write to device.                                                    */
  127. /*****************************************************************************/
  128. ULONG   IOCTL_Write(PREQPACKET rp)
  129. {
  130.         WriteDataToCard();
  131.         return(RPDONE);
  132. }
  133.  
  134. /*****************************************************************************/
  135. /*                         WRITE  STATUS                                     */
  136. /* Stub routine                                                              */
  137. /*****************************************************************************/
  138. ULONG   IOCTL_WriteStatus(PREQPACKET rp)
  139. {
  140.         WriteStatus();
  141.         return (RPDONE);
  142. }
  143.  
  144. /*****************************************************************************/
  145. /*                        FLUSH OUTPUT                                       */
  146. /*****************************************************************************/
  147. ULONG   IOCTL_FlushOutput(PREQPACKET rp)
  148. {
  149.         FlushOutputBuffers();
  150.         return (RPDONE);
  151. }
  152.  
  153. /*****************************************************************************/
  154. /*                        OPEN                                               */
  155. /* Prepare device for operations.                                            */
  156. /*****************************************************************************/
  157. ULONG   IOCTL_Open(PREQPACKET rp)
  158. {
  159.         /*****************************
  160.         ** Open device, hook interrupts
  161.         **
  162.         ** For this sample, no interrupts will be
  163.         ** hooked, generated or received as there
  164.         ** is no hardare.
  165.         ** Still, AUDINTR.C contains a sample
  166.         ** interrupt handler demonstrating
  167.         ** communication with the MMPM/2 stream handler.
  168.         ******************************/
  169.         DevOpen();
  170.         return (RPDONE);
  171. }
  172.  
  173. /*****************************************************************************/
  174. /*                          CLOSE                                            */
  175. /* Opposite of open.  Clean up system resources.  If any activity is in      */
  176. /* process, it needs to be ended.                                            */
  177. /*****************************************************************************/
  178. ULONG   IOCTL_Close(PREQPACKET rp)
  179. {
  180.         //*****************************
  181.         // Destroy streams, turn off
  182.         // any hung notes, close device
  183.         //*****************************
  184.         DestroyStreams();
  185.         DevClose();
  186.         return(RPDONE);
  187. }
  188.  
  189.  
  190. /*****************************************************************************/
  191. /*                      IOCTL INPUT/OUTPUT                                   */
  192. /*****************************************************************************/
  193. ULONG   IOCTL_Input(PREQPACKET rp)
  194. {
  195.         return(RPDONE);
  196. }
  197.  
  198. ULONG   IOCTL_Output(PREQPACKET rp)
  199. {
  200.         return(RPDONE);
  201. }
  202.  
  203.  
  204.  
  205. /*****************************************************************************/
  206. /*                       GENERIC IOCTL                                       */
  207. /*****************************************************************************/
  208. ULONG   IOCTL_GenIOCTL(PREQPACKET rp)                   // GENERAL IOCTL (OS/2)
  209. {
  210.         PVOID   pParm;
  211.         //*****************************
  212.         // Valid category : 0x80
  213.         // Valid functions: 0x40 - 0x5f
  214.         //*****************************
  215.         if (rp->RPcommand > (UCHAR)MaxAudioIOCTLFuncs)  // Is function invalid?
  216.                 return(RPDONE | RPERR | RPBADCMD);
  217.  
  218.         pParm = rp->s.IOCtl.parameters;
  219.         AudioIOCTLFuncs[rp->RPcommand](pParm);         // call request function
  220.                                                        // using table of funcs
  221.                                                        // set up at compile
  222.                                                        // time.
  223.         return (RPDONE);
  224. }
  225.  
  226.  
  227.  
  228.  
  229. /*****************************************************************************/
  230. /*                     AUDIO_INIT IOCTL                                      */
  231. /*****************************************************************************/
  232. ULONG   Audio_IOCTL_Init(PVOID pParm)
  233. {
  234.         MCI_AUDIO_INIT FAR *pInit;
  235.  
  236.         pInit = (MCI_AUDIO_INIT FAR *)pParm;
  237.  
  238.         //****************************************
  239.         // Copy parameters to our global variables
  240.         // in case any of them have changed.
  241.         //****************************************
  242.         operation = pInit->ulOperation;
  243.         flags = pInit->ulFlags;
  244.         mode = pInit->sMode;
  245.         srate = pInit->lSRate;
  246.         bits_per_sample = pInit->lBitsPerSRate;
  247.         bsize = pInit->lBsize;
  248.         channels = pInit->sChannels;
  249.         return(RPDONE);
  250. }
  251.  
  252.  
  253. /*****************************************************************************/
  254. /*                    AUDIO_STATUS IOCTL                                     */
  255. /* Query status of audio device in accordance with stream handler spec.      */
  256. /*****************************************************************************/
  257. ULONG   Audio_IOCTL_Status(PREQPACKET rp)
  258. {
  259.         DevIOCTLstatus();
  260.         return(RPDONE);
  261. }
  262.  
  263.  
  264. /*****************************************************************************/
  265. /*                    AUDIO_CONTROL IOCTL                                    */
  266. /*****************************************************************************/
  267. ULONG   Audio_IOCTL_Control(PREQPACKET rp)
  268. {
  269.         switch(rp->RPcommand)
  270.         {
  271.            /****************/
  272.            /* AUDIO_CHANGE */
  273.            /****************/
  274.            case AUDIO_CHANGE:                  /* Change adapter  */
  275.                    DevChange ();               /* characteristics */
  276.                    break;
  277.  
  278.            /***************/
  279.            /* AUDIO_START */
  280.            /***************/
  281.            case AUDIO_START:                   /* Start new operation        */
  282.                    DevStart();
  283.                    break;
  284.  
  285.            /**************/
  286.            /* AUDIO_STOP */
  287.            /**************/
  288.            case AUDIO_STOP:                 /* Stop current operation        */
  289.                    DevStop();
  290.                    break;
  291.  
  292.            /***************/
  293.            /* AUDIO_PAUSE */
  294.            /***************/
  295.            case AUDIO_PAUSE:                /* suspend current operation     */
  296.                    DevPause();
  297.                    break;
  298.  
  299.            /****************/
  300.            /* AUDIO_RESUME */
  301.            /****************/
  302.            case AUDIO_RESUME:               /* resume a suspended operation  */
  303.                    DevResume();
  304.                    break;
  305.  
  306.            default:                         /* Unknown control               */
  307.                    return (-1);             /* return an error */
  308.                    break;
  309.         }
  310.         return(RPDONE);
  311. }
  312.  
  313. /*****************************************************************************/
  314. /*                     AUDIO_BUFFER IOCTL                                    */
  315. /*****************************************************************************/
  316. ULONG   Audio_IOCTL_Buffer(PREQPACKET rp)   /* AUDIO_BUFFER IOCTL */
  317. {
  318.         PVOID   pParm;
  319.         pParm = rp->s.IOCtl.parameters;
  320.         DevAudioBuffer();
  321.         return(RPDONE);
  322. }
  323.  
  324.  
  325. /*****************************************************************************/
  326. /*                      AUDIO_LOAD IOCTL                                     */
  327. /*****************************************************************************/
  328. ULONG   Audio_IOCTL_Load(PREQPACKET rp)
  329. {
  330.         PVOID   pParm;
  331.         pParm = rp->s.IOCtl.parameters;
  332.         DevIOCTLload();
  333.         return(RPDONE);
  334. }
  335.  
  336.  
  337. /*****************************************************************************/
  338. /*                           AUDIO_WAIT IOCTL                                */
  339. /*****************************************************************************/
  340. ULONG   Audio_IOCTL_Wait(PREQPACKET rp)   /* AUDIO_WAIT */
  341. {
  342.         PVOID   pParm;
  343.         pParm = rp->s.IOCtl.parameters;
  344.         DevIOCTLwait();
  345.         return(RPDONE);
  346. }
  347.  
  348.  
  349.  
  350. /*****************************************************************************/
  351. /*                     HIGH PERFORMANCE INTERFACE IOCTL                      */
  352. /*****************************************************************************/
  353. ULONG   Audio_IOCTL_Hpi(PREQPACKET rp)
  354. {
  355.         PVOID   pParm;
  356.         pParm = rp->s.IOCtl.parameters;
  357.  
  358.         DevIOCTLhpi ();
  359.         return(RPDONE);
  360. }
  361.  
  362.  
  363. /*****************************************************************************/
  364. /*                      PDD INITIALIZATION CODE                              */
  365. /*****************************************************************************/
  366.  
  367. /*****************************************************************************/
  368. /*                                INIT                                       */
  369. /*****************************************************************************/
  370. ULONG   IOCTL_Init(PREQPACKET rp)
  371. {
  372.         /*
  373.         ** Set varable in data segement to point to the
  374.         ** OS/2 DevHlp entry point.  The address of this
  375.         ** routine is in the DevHdr data structure.
  376.         ** This address will be referenced on later calls
  377.         ** to DevHlp.
  378.         */
  379.         DevHlp = (char far *) rp->s.Init.DevHlp;
  380.  
  381.         /*
  382.         ** As return values, tell the operating system the
  383.         ** address (offset) of the end of the code and data segments.
  384.         */
  385.         rp->s.InitExit.finalCS = (OFFSET)&InitStreams;
  386.         rp->s.InitExit.finalDS = (OFFSET)&EndOfData;
  387.  
  388.         /*
  389.         ** Call routine to get streaming initialized with MMPM/2
  390.         ** and then return to the kernel via our assembler code.
  391.         */
  392.         return(InitStreams());
  393. }
  394.  
  395. /********************* START OF SPECIFICATIONS *********************
  396. *
  397. * SUBROUTINE NAME:          InitStreams
  398. *
  399. * DESCRIPTIVE NAME:
  400. *
  401. * FUNCTION:         Initializes the stream table at device init time.
  402. *
  403. * NOTES: This routine is removed from the code segment after boot time.
  404. *
  405. *
  406. * ENTRY POINTS:
  407. *     LINKAGE:  Near from IOCTL_Init()
  408. *
  409. * INPUT:
  410. *
  411. * EXIT-NORMAL:  NO_ERROR
  412. *
  413. * EXIT_ERROR:
  414. *
  415. * EFFECTS:
  416. *
  417. * INTERNAL REFERENCES: none
  418. *
  419. * EXTERNAL REFERENCES: DevHlps
  420. *
  421. *********************** END OF SPECIFICATIONS **********************/
  422.  
  423.  
  424. ULONG InitStreams(VOID)
  425. {
  426.         USHORT          i, j, BlkSize;
  427.         USHORT          usGDT[NUMGDTS];
  428.         PVOID           PhysAddress;
  429.         ULONG           rc;
  430.         BOOL            bErrFlg = FALSE;
  431.         PSTREAM         pStream;
  432.  
  433.         /**********************************/
  434.         /* alloc memory for stream table, */
  435.         /**********************************/
  436.  
  437.         BlkSize = sizeof(STREAM) * GlobalTable.usMaxNumStreams;
  438.  
  439.         // Allocate in high memory first.  If it fails allocate in low mem
  440.  
  441.         if ( DevHlp_AllocPhys(BlkSize, 0, &PhysAddress) ) // Allocate high
  442.            {
  443.               // If that fails, allocate low
  444.               rc = DevHlp_AllocPhys(BlkSize, 1, &PhysAddress);
  445.               // If that fails, installation fails
  446.               if (rc)
  447.                  return(RPDONE | RPERR);
  448.            }
  449.  
  450.         /*********************************************************/
  451.         /* allocate GDTs                                         */
  452.         /* The GDT addresses are copied from the local variable  */
  453.         /* into the GlobalTable so they can be used when running */
  454.         /* at ring 0 (after initialization)                      */
  455.         /*********************************************************/
  456.         rc = DevHlp_AllocGDTSelector(NUMGDTS, &usGDT[0]);
  457.  
  458.         /*********************************************************/
  459.         /* Set up a temporary virtual address.                   */
  460.         /* Note, cannot use GDT at init time as init is ring 3.  */
  461.         /* The GDT is allocated during init, but cannot be used  */
  462.         /* until executing at ring 0.                            */
  463.         /*********************************************************/
  464.         rc = DevHlp_PhysToVirt(PhysAddress,
  465.                                BlkSize,
  466.                                &GlobalTable.paStream);
  467.         if (rc)
  468.                 return(RPDONE | RPERR);
  469.  
  470.         //*********************
  471.         // Initialize stream table
  472.         //*********************
  473.         pStream = GlobalTable.paStream;
  474.         for (i=0; i<GlobalTable.usMaxNumStreams; i++)
  475.         {
  476.                 pStream->hStream = -1;
  477.                 pStream->ulFlags = 0;
  478.  
  479.                 for (j=0; j<MAXIOBUFFS; j++)
  480.                 {
  481.                        pStream->IOBuff[j].usRunFlags = 0;
  482.                        pStream->IOBuff[j].lCount  = 1;
  483.                        pStream->IOBuff[j].pBuffer = NULL;
  484.                 }
  485.                 pStream++;
  486.         }
  487.  
  488.         //***********************************************
  489.         // Map to GDT selector to address of stream table
  490.         //***********************************************
  491.         if (rc = DevHlp_PhysToGDTSelector(PhysAddress,  // Physical address
  492.                                       BlkSize,          // Length
  493.                                       usGDT[0]))        // Selector to map
  494.                 bErrFlg = TRUE;
  495.  
  496.         else
  497.                 GlobalTable.paStream =
  498.                    MAKEP(usGDT[0],0);  // set to virtual GDT pointer
  499.  
  500.         if (bErrFlg)
  501.                 return(RPERR | RPDONE);
  502.         else
  503.                 return(RPDONE);
  504. }
  505.