sb16drv.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:24k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* sb16drv.c - Sound Blaster 16 driver implemented for Cyrix MediaGXi CPU */
  2. /* $Revision: 1.5 $ */
  3. /* Copyright 1999-2001 Wind River Systems, Inc. */
  4. /*
  5. modification history
  6. --------------------
  7. 01d,21sep01,dat  Fix ANSI violations for diab compiler
  8. 01c,27jan00,dmh  Corrected loop bug for audio on small buffers
  9. 01b,27oct99,spm  Sounds clean now, but record is still not implemented.
  10. 01a,03oct99,spm  created.  8 bit sound is still not working right.
  11. */
  12. #include "vxWorks.h"
  13. #include "errno.h"
  14. #include "fcntl.h"
  15. #include "intLib.h"
  16. #include "ioLib.h"
  17. #include "iosLib.h"
  18. #include "iv.h"
  19. #include "logLib.h"
  20. #include "lstLib.h"
  21. #include "msgQLib.h"
  22. #include "semLib.h"
  23. #include "stdlib.h"
  24. #include "string.h"
  25. #include "taskLib.h"
  26. #include "drv/sound/sb16drv.h"
  27. /* System function not in any include file.
  28.  */
  29. /* extern char *sysDmaMalloc (int); */
  30. char snd_dmaBuffer[MAX_DMA_MSGS * MAX_DMA_SIZE];
  31. LOCAL int DrvNum;
  32. static const MIXER_INFO mixerTable[] =
  33. {
  34.   {"master",  SB_MIXER_MASTER_DEV,  31, 3, 0},
  35.   {"pcm",     SB_MIXER_PCM_DEV,     31, 3, 0},
  36.   {"synth",   SB_MIXER_SYNTH_DEV,   31, 3, 0},
  37.   {"cd",      SB_MIXER_CD_DEV,      31, 3, 0},
  38.   {"line",    SB_MIXER_LINE_DEV,    31, 3, 0},
  39.   {"mic",     SB_MIXER_MIC_DEV,     31, 3, 0},
  40.   {"speaker", SB_MIXER_SPEAKER_DEV,  3, 6, 1},
  41.   {"igain",   SB_MIXER_OGAIN_DEV,    3, 6, 1},
  42.   {"ogain",   SB_MIXER_IGAIN_DEV,    3, 6, 1},
  43.   {"treble",  SB_MIXER_TREBLE_DEV,   7, 4, 1},
  44.   {"bass",    SB_MIXER_BASS_DEV,     7, 4, 1},
  45.   {NULL,      0,                     0, 0, 0}
  46. };
  47. /**
  48.     uLaw to PCM table
  49.     Used only for uLaw 8 bit.
  50. */
  51. char ulaw_dsp[] = {
  52.      3,    7,   11,   15,   19,   23,   27,   31,
  53.     35,   39,   43,   47,   51,   55,   59,   63,
  54.     66,   68,   70,   72,   74,   76,   78,   80,
  55.     82,   84,   86,   88,   90,   92,   94,   96,
  56.     98,   99,  100,  101,  102,  103,  104,  105,
  57.     106,  107,  108,  109,  110,  111,  112,  113,
  58.     113,  114,  114,  115,  115,  116,  116,  117,
  59.     117,  118,  118,  119,  119,  120,  120,  121,
  60.     121,  121,  122,  122,  122,  122,  123,  123,
  61.     123,  123,  124,  124,  124,  124,  125,  125,
  62.     125,  125,  125,  125,  126,  126,  126,  126,
  63.     126,  126,  126,  126,  127,  127,  127,  127,
  64.     127,  127,  127,  127,  127,  127,  127,  127,
  65.     128,  128,  128,  128,  128,  128,  128,  128,
  66.     128,  128,  128,  128,  128,  128,  128,  128,
  67.     128,  128,  128,  128,  128,  128,  128,  128,
  68.     253,  249,  245,  241,  237,  233,  229,  225,
  69.     221,  217,  213,  209,  205,  201,  197,  193,
  70.     190,  188,  186,  184,  182,  180,  178,  176,
  71.     174,  172,  170,  168,  166,  164,  162,  160,
  72.     158,  157,  156,  155,  154,  153,  152,  151,
  73.     150,  149,  148,  147,  146,  145,  144,  143,
  74.     143,  142,  142,  141,  141,  140,  140,  139,
  75.     139,  138,  138,  137,  137,  136,  136,  135,
  76.     135,  135,  134,  134,  134,  134,  133,  133,
  77.     133,  133,  132,  132,  132,  132,  131,  131,
  78.     131,  131,  131,  131,  130,  130,  130,  130,
  79.     130,  130,  130,  130,  129,  129,  129,  129,
  80.     129,  129,  129,  129,  129,  129,  129,  129,
  81.     128,  128,  128,  128,  128,  128,  128,  128,
  82.     128,  128,  128,  128,  128,  128,  128,  128,
  83.     128,  128,  128,  128,  128,  128,  128,  128,
  84. };
  85. /* Useful macros.
  86.  */
  87. #define IS_16BITS(x) ((x)->info.sampleSize == 16)
  88. /* Device Methods...
  89.  */
  90. static int sndCreate (SND_DEV *pDev, char *fileName, int mode);
  91. static int sndOpen (SND_DEV *pDev, char *fileName, int flags, int mode);
  92. static int sndClose (int devId);
  93. static int sndRead (int devId, char *buffer, int maxbytes);
  94. static int sndWrite (int devId, char *buffer, int nbytes);
  95. static int sndIoctl (int devId, int function, int arg);
  96. static int dspClose (int devId);
  97. static int dspRead (int devId, char *buffer, int maxbytes);
  98. static int dspWrite (int devId, char *buffer, int nbytes);
  99. static int dspIoctl (int devId, int function, int arg);
  100. static int mixerClose (int devId);
  101. static int mixerRead (int devId, char *buffer, int maxbytes);
  102. static int mixerWrite (int devId, char *buffer, int nbytes);
  103. static int mixerIoctl (int devId, int function, int arg);
  104. /* Interrupt handler and Helper task
  105.  */
  106. static void dspInterrupt (SND_DEV *pDev);
  107. static int dspHelperTask (SND_DEV *pDev);
  108. /* DMA buffer management routines
  109.  */
  110. static int createDmaBuffer (void);
  111. static char *getDmaBuffer (SND_DEV *pDev);
  112. static void freeDmaBuffer (SND_DEV *pDev);
  113. /* Low level register access routines.
  114.  */
  115. static int dsp_init (SND_DEV *pDev);
  116. static int dsp_version (SND_DEV *pDev);
  117. static int dsp_reset (SND_DEV *pDev);
  118. /* OPL3 functions...
  119.  */
  120. static int opl3_init (SND_DEV *pDev);
  121. /* Mixer functions...
  122.  */
  123. static int mixer_init (SND_DEV *pDev);
  124. /* Inlined small functions
  125.  */
  126. static __inline__ int dsp_command (SND_DEV *pDev, unsigned char val)
  127. {
  128.   int i;
  129.   for (i = 10000; i; i--)
  130.     if ((sysInByte (SBP(pDev, STATUS)) & 0x80) == 0)
  131.     {
  132.       sysOutByte (SBP(pDev, COMMAND), val);
  133.       return 1;
  134.     }
  135.   return 0;
  136. }
  137. static __inline__ int opl3_command (unsigned short port,
  138.     unsigned char reg, unsigned char val)
  139. {
  140.   sysOutByte (port, reg);
  141.   sysInByte (port);
  142.   sysInByte (port);
  143.   sysOutByte (port + 1, val);
  144.   sysInByte (port + 1);
  145.   sysInByte (port + 1);
  146.   return 1;
  147. }
  148. static __inline__ int dsp_ack_8bit (SND_DEV * pDev)
  149. {
  150.   return sysInByte (SBP(pDev, DATA_AVAIL));
  151. }
  152. static __inline__ int dsp_ack_16bit (SND_DEV * pDev)
  153. {
  154.   return sysInByte (SBP(pDev, DATA_AVAIL_16));
  155. }
  156. static __inline__ void mixer_write (SND_DEV *pDev,
  157.     unsigned char reg, unsigned char data)
  158. {
  159.   sysOutByte (SBP(pDev, MIXER_ADDR), reg);
  160.   sysOutByte (SBP(pDev, MIXER_DATA), data);
  161. }
  162. static __inline__ unsigned char mixer_read (SND_DEV *pDev, unsigned char reg)
  163. {
  164.   unsigned char result;
  165.   sysOutByte (SBP(pDev, MIXER_ADDR), reg);
  166.   result = sysInByte (SBP(pDev, MIXER_DATA));
  167.   return result;
  168. }
  169. static __inline__ void mixer_set_level (SND_DEV * pDev, char *name, int value)
  170. {
  171.   const MIXER_INFO *info;
  172.   int lvalue = value%256;
  173.   int rvalue = value/256;
  174.   for (info=mixerTable; info->name && strcmp (info->name, name); info++);
  175.   if (info->name)
  176.   {
  177.       if (lvalue > 100) lvalue = 100;
  178.       else if (lvalue<0) lvalue = 0;
  179.       
  180.       lvalue = (lvalue * info->max_value / 100) << info->shift;
  181.       if (rvalue > 100) rvalue = 100;
  182.       else if (rvalue<0) rvalue = 0;
  183.       
  184.       rvalue = (rvalue * info->max_value / 100) << info->shift;
  185.       mixer_write (pDev, info->reg, lvalue);
  186.       mixer_write (pDev, info->reg + 1, rvalue);
  187.   }
  188. }
  189. static __inline__ int mixer_get_level (SND_DEV * pDev, char *name)
  190. {
  191.   const MIXER_INFO *info;
  192.   for (info=mixerTable; info->name && strcmp (info->name, name); info++);
  193.   if (info->name)
  194.   {
  195.       int lvalue = mixer_read (pDev, info->reg) >> info->shift;
  196.       int rvalue = mixer_read (pDev, info->reg + 1) >> info->shift;
  197.       lvalue = lvalue * 100 / info->max_value;
  198.       rvalue = rvalue * 100 / info->max_value;
  199.       return rvalue << 8 | lvalue;
  200.   }
  201.   return 0;
  202. }
  203. /* Routine to initiate Sound blaster DMAs.
  204.  */
  205. static void dsp_output (DSP_FD *pDsp, int length)
  206. {
  207.   SND_DEV *pDev = pDsp->dev.pDev;
  208.   unsigned long count;
  209.   unsigned char format;
  210.   /* setup the sample rate.
  211.    */
  212.   dsp_command (pDev, SB_DSP_SAMPLE_RATE_IN);
  213.   dsp_command (pDev, pDsp->info.rate >> 8);
  214.   dsp_command (pDev, pDsp->info.rate & 0xff);
  215.   dsp_command (pDev, SB_DSP_SAMPLE_RATE_OUT);
  216.   dsp_command (pDev, pDsp->info.rate >> 8);
  217.   dsp_command (pDev, pDsp->info.rate & 0xff);
  218.   /* Determine the proper format of the output.
  219.    */
  220.   if (IS_16BITS(pDsp))
  221.     format = pDsp->info.stereo ?
  222.       SB_DSP4_MODE_SIGN_STEREO : SB_DSP4_MODE_SIGN_MONO;
  223.   else
  224.     format = pDsp->info.stereo ?
  225.       SB_DSP4_MODE_UNS_STEREO : SB_DSP4_MODE_UNS_MONO;
  226.   /* Tell the sound hardware how many samples.
  227.    */
  228.   count = (IS_16BITS(pDsp) ? (length >> 1) : length) - 1;
  229.   dsp_command (pDev, IS_16BITS(pDsp) ? SB_DSP4_OUT16_AI : SB_DSP4_OUT8_AI);
  230.   dsp_command (pDev, format);
  231.   dsp_command (pDev, count & 0xff);
  232.   dsp_command (pDev, count >> 8);
  233.   dsp_command (pDev, IS_16BITS(pDev->pDsp) ?
  234.        SB_DSP_DMA16_ON : SB_DSP_DMA8_ON);
  235. }
  236. /* Device creation routines...
  237.  */
  238. STATUS sb16Drv (void)
  239. {
  240.   if (DrvNum > 0) return OK;
  241.   DrvNum = iosDrvInstall (sndCreate, NULL, sndOpen, sndClose,
  242.   sndRead, sndWrite, sndIoctl);
  243.   return (DrvNum == ERROR) ? ERROR : OK;
  244. }
  245. STATUS sb16DevCreate (char *devName, int port, int irq, int dma8, int dma16)
  246. {
  247.   SND_DEV *pDev;
  248.   if (DrvNum < 1)
  249.   {
  250.     errno = S_ioLib_NO_DRIVER;
  251.     return ERROR;
  252.   }
  253.   pDev = (SND_DEV *)malloc (sizeof(SND_DEV));
  254.   if (!pDev) return ERROR;
  255.   bzero ((char *)pDev, sizeof(SND_DEV));
  256.   pDev->port   = port;
  257.   pDev->irq    = irq;
  258.   pDev->dma8   = dma8;
  259.   pDev->dma16  = dma16;
  260.   pDev->devSem = semBCreate (SEM_Q_FIFO, SEM_FULL);
  261.   pDev->intSem = semCCreate (SEM_Q_FIFO, 0);
  262.   pDev->bufSem = semCCreate (SEM_Q_FIFO, MAX_DMA_MSGS);
  263.   pDev->dmaQ   = msgQCreate (MAX_DMA_MSGS, sizeof (DMA_MSG), MSG_Q_FIFO);
  264.   pDev->dmaIndex = 0;
  265.   if (createDmaBuffer () < 0)
  266.   {
  267.     free (pDev);
  268.     return ERROR;
  269.   }
  270.   if (dsp_init (pDev) < 0)
  271.   {
  272.     free (pDev);
  273.     return ERROR;
  274.   }
  275.   /* This belongs in the mixer device...
  276.    */
  277.   if (mixer_init (pDev) < 0)
  278.   {
  279.     free (pDev);
  280.     return ERROR;
  281.   }
  282.   if (iosDevAdd (&pDev->devHdr, devName, DrvNum) == ERROR)
  283.   {
  284.     free ((char *)pDev);
  285.     return ERROR;
  286.   }
  287.   pDev->tid = taskSpawn ("tSndTask", TASK_PRIORITY, TASK_OPTIONS,
  288.  TASK_STACK_SIZE, dspHelperTask, (int)pDev,
  289.  0, 0, 0, 0, 0, 0, 0, 0, 0);
  290.   if (pDev->tid == ERROR)
  291.   {
  292.     free (pDev);
  293.     return ERROR;
  294.   }
  295.   intConnect (INUM_TO_IVEC (INT_VEC_GET (irq)), dspInterrupt, (int)pDev);
  296.   return OK;
  297. }
  298. /* Device methods...
  299.  */
  300. static int sndCreate (SND_DEV *pDev, char *fileName, int mode)
  301. {
  302.   return ERROR;
  303. }
  304. static int sndOpen (SND_DEV *pDev, char *fileName, int flags, int mode)
  305. {
  306.   SND_FD *pSnd = NULL;
  307.   if (semTake (pDev->devSem, 30 * sysClkRateGet()))
  308.   {
  309.     errno = S_ioLib_DEVICE_ERROR;
  310.     return ERROR;
  311.   }
  312.   if (strcmp (fileName, "/dsp") == 0)
  313.   {
  314.     DSP_FD *pDsp;
  315.     if (pDev->pDsp)
  316.     {
  317.       errno = EBUSY;
  318.       goto error;
  319.     }
  320.     if (! (pDsp = malloc (sizeof(DSP_FD))))
  321.     {
  322.       errno = ENOMEM;
  323.       goto error;
  324.     }
  325.     pDsp->dev.pDev    = pDev;
  326.     pDsp->dev.fdClose = dspClose;
  327.     pDsp->dev.fdRead  = dspRead;
  328.     pDsp->dev.fdWrite = dspWrite;
  329.     pDsp->dev.fdIoctl = dspIoctl;
  330.     pDsp->info.rate       = RATE_MAX;
  331.     pDsp->info.stereo     = 1;
  332.     pDsp->info.sampleSize = 16;
  333.     pDsp->info.uLaw       = 0; /* PCM format is default */
  334.     pDev->pDsp = pDsp;
  335.     pSnd = (SND_FD *)pDsp;
  336.   }
  337.   else if (strcmp (fileName, "/mixer") == 0)
  338.   {
  339.     MIXER_FD *pMixer;
  340.     if (pDev->pMixer)
  341.     {
  342.       errno = EBUSY;
  343.       goto error;
  344.     }
  345.     if (! (pMixer = malloc (sizeof(MIXER_FD))))
  346.     {
  347.       errno = ENOMEM;
  348.       goto error;
  349.     }
  350.     pMixer->dev.pDev    = pDev;
  351.     pMixer->dev.fdClose = mixerClose;
  352.     pMixer->dev.fdRead  = mixerRead;
  353.     pMixer->dev.fdWrite = mixerWrite;
  354.     pMixer->dev.fdIoctl = mixerIoctl;
  355.     pDev->pMixer = pMixer;
  356.     pSnd = (SND_FD *)pMixer;
  357.   }
  358.   else
  359.   {
  360.     errno = ENODEV;
  361.     goto error;
  362.   }
  363. error:
  364.   semGive (pDev->devSem);
  365.   return pSnd ? (int)pSnd : ERROR;
  366. }
  367. static int sndClose (int devId)
  368. {
  369.   SND_FD *pSnd = (SND_FD *)devId;
  370.   return pSnd->fdClose (devId);
  371. }
  372. static int sndRead (int devId, char *buffer, int maxbytes)
  373. {
  374.   SND_FD *pSnd = (SND_FD *)devId;
  375.   return pSnd->fdRead (devId, buffer, maxbytes);
  376. }
  377. static int sndWrite (int devId, char *buffer, int nbytes)
  378. {
  379.   SND_FD *pSnd = (SND_FD *)devId;
  380.   return pSnd->fdWrite (devId, buffer, nbytes);
  381. }
  382. static int sndIoctl (int devId, int function, int arg)
  383. {
  384.   SND_FD *pSnd = (SND_FD *)devId;
  385.   return pSnd->fdIoctl (devId, function, arg);
  386. }
  387. /* DSP device methods.
  388.  */
  389. static int dspClose (int devId)
  390. {
  391.   DSP_FD *pDsp = (DSP_FD *)devId;
  392.   SND_DEV *pDev = pDsp->dev.pDev;
  393.   if (semTake (pDev->devSem, 30 * sysClkRateGet()))
  394.   {
  395.     errno = S_ioLib_DEVICE_ERROR;
  396.     return ERROR;
  397.   }
  398.   while (pDev->taskBusy) taskDelay (1);
  399.   pDev->pDsp = NULL;
  400.   free (pDsp);
  401.   semGive (pDev->devSem);
  402.   return OK;
  403. }
  404. static int dspRead (int devId, char *buffer, int maxbytes)
  405. {
  406.   errno = S_ioLib_UNKNOWN_REQUEST;
  407.   return ERROR;
  408. }
  409. static int dspWrite (int devId, char *buffer, int nbytes)
  410. {
  411.   DSP_FD *pDsp = (DSP_FD *)devId;
  412.   SND_DEV *pDev = pDsp->dev.pDev;
  413.   int bytesLeft = nbytes;
  414.   int x;
  415.   DMA_MSG mDma;
  416.   /**
  417.     Convert from uLaw to PCM if needed -- note, we only
  418.     support 8-bit uLaw
  419.   */
  420.   if (pDsp->info.uLaw) {
  421.       for (x=0; x<nbytes; x++) {
  422.           buffer[x] = ulaw_dsp[((unsigned char)buffer[x])];
  423.       } /* endfor */
  424.   } /* endfor */
  425.   /* Check if we were recording.  If so, wait till all is clear.
  426.    */
  427.   if (pDev->pDsp->dmaDirection != O_WRONLY)
  428.     while (pDev->taskBusy) taskDelay (1);
  429.   while (bytesLeft > 0)
  430.   {
  431.     mDma.buffer    = getDmaBuffer (pDev);
  432.     mDma.length    = bytesLeft > MAX_DMA_SIZE ? MAX_DMA_SIZE : bytesLeft;
  433.     mDma.direction = O_WRONLY;
  434.     memcpy (mDma.buffer, buffer, mDma.length);
  435.     if (mDma.length<MAX_DMA_SIZE) {
  436.         bzero(mDma.buffer+mDma.length,MAX_DMA_SIZE-mDma.length);
  437.     } /* endif */
  438.     msgQSend (pDev->dmaQ, (char *)&mDma, sizeof (mDma),
  439.       WAIT_FOREVER, MSG_PRI_NORMAL);
  440.     buffer    += mDma.length;
  441.     bytesLeft -= mDma.length;
  442.   }
  443.   return nbytes - bytesLeft;
  444. }
  445. static int dspIoctl (int devId, int function, int arg)
  446. {
  447.   DSP_FD *pDsp = (DSP_FD *)devId;
  448.   SND_DEV *pDev = pDsp->dev.pDev;
  449.   union arg_union
  450.   {
  451.     int i;
  452.     long l;
  453.     int *pInt;
  454.     long *pLong;
  455.     snd_info_t *pInfo;
  456.   } u_arg;
  457.   
  458.   u_arg.i = arg;
  459.   switch (function)
  460.   {
  461.     case SNDCTL_DSP_SYNC:
  462.       while (pDev->taskBusy) taskDelay (1);
  463.       return OK;
  464.     case SNDCTL_DSP_GETBLKSIZE:
  465.       *u_arg.pInt = MAX_DMA_SIZE;
  466.       return OK;
  467.     case SNDCTL_DSP_SPEED:
  468.       {
  469. int i = *u_arg.pLong;
  470. if (i < RATE_MIN) i = RATE_MIN;
  471. if (i > RATE_MAX) i = RATE_MAX;
  472. while (pDev->taskBusy) taskDelay (1);
  473. pDsp->info.rate = i;
  474. return OK;
  475.       }
  476.     case SNDCTL_DSP_STEREO:
  477.       while (pDev->taskBusy) taskDelay (1);
  478.       pDsp->info.stereo = *u_arg.pInt;
  479.       return OK;
  480.     case SNDCTL_DSP_SAMPLESIZE:
  481.       if (*u_arg.pInt == 8 || *u_arg.pInt == 16)
  482.       {
  483. while (pDev->taskBusy) taskDelay (1);
  484. pDsp->info.sampleSize = *u_arg.pInt;
  485. return OK;
  486.       }
  487.       break;
  488.     case SNDCTL_DSP_SETFORMAT:
  489.       pDsp->info.uLaw = *u_arg.pInt;
  490.       return OK;
  491.       break;
  492.     case SNDCTL_GET_INFO:
  493.       *u_arg.pInfo = pDsp->info;
  494.       return OK;
  495.     case SNDCTL_SET_INFO:
  496.       while (pDev->taskBusy) taskDelay (1);
  497.       pDsp->info = *u_arg.pInfo;
  498.       return OK;
  499.   }
  500.   errno = S_ioLib_UNKNOWN_REQUEST;
  501.   return ERROR;
  502. }
  503. /* Mixer device methods.
  504.  */
  505. static int mixerClose (int devId)
  506. {
  507.   MIXER_FD *pMixer = (MIXER_FD *)devId;
  508.   SND_DEV *pDev = pMixer->dev.pDev;
  509.   if (semTake (pDev->devSem, 30 * sysClkRateGet()))
  510.   {
  511.     errno = S_ioLib_DEVICE_ERROR;
  512.     return ERROR;
  513.   }
  514.   pDev->pMixer = NULL;
  515.   free (pMixer);
  516.   semGive (pDev->devSem);
  517.   return OK;
  518. }
  519. static int mixerRead (int devId, char *buffer, int maxbytes)
  520. {
  521.   errno = S_ioLib_DEVICE_ERROR;
  522.   return ERROR;
  523. }
  524. static int mixerWrite (int devId, char *buffer, int nbytes)
  525. {
  526.   errno = S_ioLib_DEVICE_ERROR;
  527.   return ERROR;
  528. }
  529. static int mixerIoctl (int devId, int function, int arg)
  530. {
  531.   MIXER_FD *pMixer = (MIXER_FD *)devId;
  532.   union arg_union
  533.   {
  534.     int i;
  535.     long l;
  536.     int *pInt;
  537.     long *pLong;
  538.     snd_info_t *pInfo;
  539.   } u_arg;
  540.   
  541.   u_arg.i = arg;
  542.   switch (function)
  543.   {
  544.     case SNDCTL_SET_VOLUME:
  545.       {
  546. int volume = *u_arg.pLong;
  547. mixer_set_level (pMixer->dev.pDev, "master", volume);
  548. return OK;
  549.       }
  550.     case SNDCTL_GET_VOLUME:
  551.       {
  552. *u_arg.pLong = mixer_get_level (pMixer->dev.pDev, "master");
  553. return OK;
  554.       }
  555.   }
  556.   errno = S_ioLib_UNKNOWN_REQUEST;
  557.   return ERROR;
  558. }
  559. static void processOutput (SND_DEV *pDev, DMA_MSG mDma)
  560. {
  561.   int dmaChannel = IS_16BITS(pDev->pDsp) ? pDev->dma16 : pDev->dma8;
  562.   if (pDev->pDsp->dmaDirection != O_WRONLY ||
  563.       pDev->pDsp->dmaChannel   != dmaChannel)
  564.   {
  565.     pDev->dmaAuto = 0;
  566.     pDev->pDsp->dmaDirection = mDma.direction;
  567.     pDev->pDsp->dmaChannel   = dmaChannel;
  568.   }
  569.   if (pDev->dmaAuto)
  570.   {
  571.     if (mDma.length != MAX_DMA_SIZE)
  572.     {
  573.       /* If this was the interrupt from the middle of the block,
  574.        * then wait around for the next one.
  575.        */
  576.       if (pDev->dmaAuto)
  577.       {
  578. pDev->dmaAuto = 0;
  579. if (semTake (pDev->intSem, 5 * sysClkRateGet()))
  580.   logMsg ("SB16: Interrupt timeoutn", 0, 0, 0, 0, 0, 0);
  581. freeDmaBuffer (pDev);
  582.       }
  583.       /* We are done with auto init mode.
  584.        */
  585.       dsp_command (pDev, IS_16BITS(pDev->pDsp) ?
  586.    SB_DSP_DMA16_EXIT : SB_DSP_DMA8_EXIT);
  587.       /* Setup a one-shot.
  588.        */
  589.       dmaSetup (DMA_MODE_SINGLE | DMA_MODE_WRITE,
  590. mDma.buffer, mDma.length, dmaChannel);
  591.       /* Send out this block.
  592.        */
  593.       dsp_output (pDev->pDsp, mDma.length);
  594.     }
  595.   }
  596.   else
  597.   {
  598.     dsp_command (pDev, SB_DSP_DMA8_OFF);
  599.     dsp_command (pDev, SB_DSP_DMA16_OFF);
  600.     if (mDma.buffer == snd_dmaBuffer && mDma.length == MAX_DMA_SIZE)
  601.     {
  602.       pDev->dmaAuto = 2;
  603.       dmaSetup (DMA_MODE_SINGLE | DMA_MODE_WRITE | DMA_MODE_AUTO_ENABLE,
  604. snd_dmaBuffer, MAX_DMA_MSGS * MAX_DMA_SIZE, dmaChannel);
  605.       /* Check for the next buffer available when half the buffer
  606.        * has been transferred.
  607.        */
  608.       mDma.length >>= 1;
  609.     }
  610.     else
  611.     {
  612.       dmaSetup (DMA_MODE_SINGLE | DMA_MODE_WRITE,
  613. mDma.buffer, mDma.length, dmaChannel);
  614.     }
  615.     /* Send out this block.
  616.      */
  617.     dsp_output (pDev->pDsp, mDma.length);
  618.   }
  619. }
  620. /* Interrupt handler and Helper task
  621.  */
  622. static void dspInterrupt (SND_DEV *pDev)
  623. {
  624.   int status;
  625.   sysOutByte (SBP(pDev, MIXER_ADDR), SB_MIXER_IRQ_STAT);
  626.   status = sysInByte (SBP(pDev, MIXER_DATA));
  627.   /* 8bit DMA interrupt
  628.    */
  629.   if (status & 1)
  630.   {
  631.     dsp_ack_8bit (pDev);
  632.     semGive (pDev->intSem);
  633.   }
  634.   /* 16bit DMA interrupt
  635.    */
  636.   if (status & 2)
  637.   {
  638.     dsp_ack_16bit (pDev);
  639.     semGive (pDev->intSem);
  640.   }
  641. }
  642. static int dspHelperTask (SND_DEV *pDev)
  643. {
  644.   DMA_MSG mDma;
  645.   while (1)
  646.   {
  647.     pDev->taskBusy = pDev->dmaAuto = 0;
  648.     dsp_command (pDev, SB_DSP_SPEAKER_OFF);
  649.     dsp_command (pDev, SB_DSP_DMA8_OFF);
  650.     dsp_command (pDev, SB_DSP_DMA16_OFF);
  651.     if (msgQReceive (pDev->dmaQ, (char *)&mDma,
  652.      sizeof (mDma), WAIT_FOREVER) != sizeof (mDma))
  653.       return 0;
  654.     pDev->taskBusy = 1;
  655.     dsp_command (pDev, SB_DSP_SPEAKER_ON);
  656.     do
  657.     {
  658.       switch (mDma.direction)
  659.       {
  660. case O_WRONLY:
  661.   processOutput (pDev, mDma);
  662.   break;
  663. case O_RDONLY:
  664.   break;
  665.       }
  666.       /* wait for a DMA interrupt
  667.        */
  668.       if (semTake (pDev->intSem, 5 * sysClkRateGet()))
  669. logMsg ("SB16: Interrupt timeoutn", 0, 0, 0, 0, 0, 0);
  670.       if (pDev->dmaAuto)
  671.       {
  672. /* We can do this, because we know the stream will be
  673.  * non-contiguous if any properties change (rate, direction, etc).
  674.  */
  675. while (pDev->dmaAuto)
  676. {
  677.   pDev->dmaAuto--;
  678.   if (pDev->dmaAuto)
  679.   {
  680.     if (msgQReceive (pDev->dmaQ, (char *)&mDma,
  681.      sizeof (mDma), NO_WAIT) != sizeof (mDma))
  682.     {
  683.       pDev->dmaAuto = 0;
  684.     }
  685.   }
  686.   else
  687.   {
  688.     /* Great, we can keep going with 2 more interrupts to follow.
  689.      */
  690.     pDev->dmaAuto = 2;
  691.     freeDmaBuffer (pDev);
  692.   }
  693.   /* wait for the next DMA interrupt
  694.    */
  695.   if (semTake (pDev->intSem, 5 * sysClkRateGet()))
  696.     logMsg ("SB16: Interrupt timeoutn", 0, 0, 0, 0, 0, 0);
  697. }
  698. /* We can't do any more DMA continuously.
  699.  */
  700. dsp_command (pDev, IS_16BITS(pDev->pDsp) ?
  701.      SB_DSP_DMA16_EXIT : SB_DSP_DMA8_EXIT);
  702.       }
  703.       freeDmaBuffer (pDev);
  704.     } while (msgQReceive (pDev->dmaQ, (char *)&mDma,
  705.   sizeof (mDma), NO_WAIT) == sizeof (mDma));
  706.   }
  707. }
  708. /* DMA buffer management routines
  709.  */
  710. /* DMA buffers are never grabbed by the interrupt routine
  711.  */
  712. static int createDmaBuffer (void)
  713. {
  714. /*   snd_dmaBuffer = sysDmaMalloc (MAX_DMA_MSGS * MAX_DMA_SIZE); */
  715.   bzero (snd_dmaBuffer, MAX_DMA_MSGS * MAX_DMA_SIZE);
  716.   return snd_dmaBuffer ? OK : ERROR;
  717. }
  718. static char *getDmaBuffer (SND_DEV *pDev)
  719. {
  720.   char *dmaBuffer;
  721.   semTake (pDev->bufSem, WAIT_FOREVER);
  722.   semTake (pDev->devSem, WAIT_FOREVER);
  723.   dmaBuffer = snd_dmaBuffer + pDev->dmaIndex * MAX_DMA_SIZE;
  724.   pDev->dmaIndex = (pDev->dmaIndex + 1) % MAX_DMA_MSGS;
  725.   semGive (pDev->devSem);
  726.   return dmaBuffer;
  727. }
  728. /* DMA buffers are always freed by the interrupt routine
  729.  */
  730. static void freeDmaBuffer (SND_DEV *pDev)
  731. {
  732.   semGive (pDev->bufSem);
  733. }
  734. /* Low level register access routines.
  735.  */
  736. static int dsp_init (SND_DEV *pDev)
  737. {
  738.   int version;
  739.   /* Initialization the DSP
  740.    */
  741.   if (dsp_reset (pDev) < 0)
  742.   {
  743.     logMsg ("SB16: [0x%x] reset failed... 0x%xn",
  744.     pDev->port, sysInByte (SBP(pDev, READ)), 0, 0, 0, 0);
  745.     return -ENODEV;
  746.   }
  747.   /* Get the version number of the DSP
  748.    */
  749.   if ((version = dsp_version (pDev)) < 0)
  750.   {
  751.     logMsg ("SB16: [0x%x] get version failed... 0x%xn",
  752.     pDev->port, sysInByte (SBP(pDev, READ)), 0, 0, 0, 0);
  753.     return -ENODEV;
  754.   }
  755.   pDev->version = version;
  756.   switch (pDev->version >> 8)
  757.   {
  758.     case 1: case 2: case 3:
  759.       logMsg ("SB16: [0x%x] DSP chip version %i.%i is not supported"
  760.       " with the SB16 coden", pDev->port, pDev->version >> 8,
  761.       pDev->version & 0xff, 0, 0, 0);
  762.       return -ENODEV;
  763.     case 4:
  764.       break;
  765.     default:
  766.       logMsg ("SB16: [0x%x] unknown DSP chip version %i.%in",
  767.       pDev->port, pDev->version >> 8, pDev->version & 0xff, 0, 0, 0);
  768.       return -ENODEV;
  769.   }
  770.   dsp_command (pDev, SB_DSP_SPEAKER_OFF);
  771.   opl3_init (pDev);
  772.   return 0;
  773. }
  774. static int dsp_version (SND_DEV *pDev)
  775. {
  776.   int i;
  777.   unsigned int result = -1;
  778.   sysIntDisablePIC (pDev->irq);
  779.   dsp_command (pDev, SB_DSP_GET_VERSION);
  780.   for (i = 100000; i; i--)
  781.     if (sysInByte (SBP(pDev, DATA_AVAIL)) & 0x80)
  782.     {
  783.       result = (short) sysInByte (SBP(pDev, READ)) << 8;
  784.       break;
  785.     }
  786.   for (i = 100000; i; i--)
  787.     if (sysInByte (SBP(pDev, DATA_AVAIL)) & 0x80)
  788.     {
  789.       result |= (short) sysInByte (SBP(pDev, READ));
  790.       break;
  791.     }
  792.   sysIntEnablePIC (pDev->irq);
  793.   return result;
  794. }
  795. static int dsp_reset (SND_DEV *pDev)
  796. {
  797.   int i;
  798.   sysIntDisablePIC (pDev->irq);
  799.   sysOutByte (SBP(pDev, RESET), 1);
  800.   sysDelay ();
  801.   sysOutByte (SBP(pDev, RESET), 0);
  802.   sysDelay ();
  803.   for (i = 0; i < 1000 && !(sysInByte (SBP(pDev, DATA_AVAIL)) & 0x80); i++);
  804.   i = sysInByte (SBP(pDev, READ));
  805.   sysIntEnablePIC (pDev->irq);
  806.   if (i == 0xaa) return 0;
  807.   return -ENODEV;
  808. }
  809. /* OPL3 functions...
  810.  */
  811. static int opl3_init (SND_DEV *pDev)
  812. {
  813.   int i;
  814.   /* Reset opl3 timers 1 and 2
  815.    */
  816.   opl3_command (SBP(pDev, OPL3_LEFT), TIMER_CONTROL_REGISTER,
  817. TIMER1_MASK | TIMER2_MASK);
  818.   /* Reset the IRQ of the FM chip
  819.    */
  820.   opl3_command (SBP(pDev, OPL3_LEFT), TIMER_CONTROL_REGISTER, IRQ_RESET);
  821.   i = sysInByte (SBP(pDev, OPL3_LEFT));
  822.   if (i == 0x00 || i == 0x0f)
  823.   {
  824.     opl3_command (SBP(pDev, OPL3_RIGHT), OPL3_MODE_REGISTER, 0x00);
  825.     opl3_command (SBP(pDev, OPL3_RIGHT), OPL3_MODE_REGISTER, OPL3_ENABLE);
  826.     opl3_command (SBP(pDev, OPL3_RIGHT), CONNECTION_SELECT_REGISTER, 0x00);
  827.     for (i=0; i<9; i++)
  828.       opl3_command (SBP(pDev, OPL3_LEFT), KEYON_BLOCK, 0);
  829.     opl3_command (SBP(pDev, OPL3_LEFT), TEST_REGISTER, ENABLE_WAVE_SELECT);
  830.     opl3_command (SBP(pDev, OPL3_LEFT), PERCUSSION_REGISTER, 0x00);
  831.     opl3_command (SBP(pDev, OPL3_RIGHT), OPL3_MODE_REGISTER, 0x00);
  832.   }
  833.   else
  834.     logMsg ("SB16: [0x%x] OPL3 detect failed... 0x%xn",
  835.     pDev->port, i, 0, 0, 0, 0);
  836.   return 0;
  837. }
  838. /* Mixer stuff.  Really belongs in it's own device....
  839.  */
  840. static int mixer_init (SND_DEV *pDev)
  841. {
  842.   int irq;
  843.   int mpu;
  844.   switch (pDev->irq)
  845.   {
  846.     case 2: case 9: irq = 0x01; break;
  847.     case 5:         irq = 0x02; break;
  848.     case 7:         irq = 0x04; break;
  849.     case 10:        irq = 0x08; break;
  850.     default:        irq = 0x00;
  851.   }
  852.   mixer_write (pDev, 0x0, 0x0); /* reset mixer */
  853.   sysDelay ();
  854.   mpu = mixer_read (pDev, SB_MIXER_MPU_NR) & ~0x06;
  855.   mixer_write (pDev, SB_MIXER_IRQ_NR, irq);
  856.   mixer_write (pDev, SB_MIXER_DMA_NR, (1 << pDev->dma16) | (1 << pDev->dma8));
  857.   mixer_write (pDev, SB_MIXER_MPU_NR, mpu & 0x02); /* disable mpu */
  858.   /* Turn on all inputs.
  859.    */
  860.   mixer_write (pDev, SB_MIXER_OUTPUT_SW, 0x1f);
  861.   /* Set volumes to reasonable values for now...
  862.    */
  863.   mixer_set_level (pDev, "master", 90 << 8 | 90);
  864.   mixer_set_level (pDev, "pcm", 90 << 8 | 90);
  865.   mixer_set_level (pDev, "speaker", 0);
  866.   mixer_set_level (pDev, "ogain", 0);
  867.   mixer_set_level (pDev, "igain", 0);
  868.   mixer_set_level (pDev, "treble", 50);
  869.   mixer_set_level (pDev, "bass",   50);
  870.   return 0;
  871. }
  872. /**
  873. $Log: sb16drv.c,v $
  874. Revision 1.5  1999/12/18 00:01:38  steveh
  875. Corrected loop bug for audio on small buffers.
  876. Connected up fwd,back and stop buttons.
  877. Attempted to connect up logic to display link that mouse is over,
  878. but api seems to not work for this.
  879. Revision 1.4  1999/12/03 06:52:09  steveh
  880. Created new IOCTL to set 8-bit uLaw format in SB driver.
  881. Moved uLaw code from java to driver.
  882. */