home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / comp / unix / amiga / 2597 < prev    next >
Encoding:
Text File  |  1992-12-22  |  17.8 KB  |  853 lines

  1. Path: sparky!uunet!cbmvax!yoda!ag
  2. From: ag@yoda.omnicron.com (Keith Gabryelski)
  3. Newsgroups: comp.unix.amiga
  4. Subject: Working audio driver source.
  5. Message-ID: <1005@yoda.omnicron.com>
  6. Date: 23 Dec 92 00:39:33 GMT
  7. Organization: Omnicron Data Systems
  8. Lines: 843
  9.  
  10. Here is a working audio driver I wrote about a month ago.  It replaces
  11. the code in /usr/sys/amiga/driver/audio.[ch] and has only one known
  12. bug which is that small samples may have the first part of their
  13. sample cut off.
  14.  
  15. I was away from home for the last month while this device driver was
  16. running and the sayclock (/usr/amiga/src/cmd/clksnd/sayclock) program
  17. was outputting a stream of data every ten minutes to it.  So I believe
  18. this is a mostly functional audio driver.
  19.  
  20. It currently supports stream audio data and repeated wave forms (via a
  21. repeat count ioctl) so this code can be used in the X server to
  22. produce console beeps.  I may update the X11R5 code someday to handle
  23. this.
  24.  
  25. I would also like this audio driver to be used for the console
  26. driver's ^G (beep).  I haven't thought of a good way of interfacing
  27. kernel accesses to the audio driver yet but will send patches when
  28. this has been completed.
  29.  
  30. I am currently in the midst of moving to Boston and working on a
  31. startup project so you will have to forgive me if I do not reply to
  32. mail reports very quickly.
  33.  
  34. Merry Christmas.
  35.  
  36. Pax, Keith
  37.  
  38.  
  39. # This is a shell archive.  Remove anything before this line,
  40. # then unpack it by saving it in a file and typing "sh file".
  41. #
  42. # This archive contains:
  43. #    audio.c    audio.h    
  44. #
  45.  
  46. echo x - audio.c
  47. cat >audio.c <<'@EOF'
  48. #include <sys/types.h>
  49. #include <sys/param.h>
  50. #include <sys/sysmacros.h>
  51. #include <sys/signal.h>
  52. #include <sys/file.h>
  53. #include <sys/user.h>
  54. #include <sys/proc.h>
  55. #include <sys/cmn_err.h>
  56. #include <sys/stream.h>
  57. #include <sys/stropts.h>
  58. #include <sys/errno.h>
  59. #include <sys/kmem.h>
  60. #include <sys/inline.h>
  61. #include <sys/mkdev.h>
  62. #include "memory.h"
  63. #include "amigahr.h"
  64. #include "audio.h"
  65.  
  66. extern char *panicstr;
  67.  
  68. static int audioopen(queue_t *, dev_t *, int, int, cred_t *);
  69. static int audioclose(queue_t *);
  70. static int audiowput(struct queue *, mblk_t *);
  71. static int audiowsrv(struct queue *);
  72. static void audioioctl(queue_t *, mblk_t *);
  73. static int audioinit(void);
  74. static int postaudio(struct audio_client *, mblk_t *);
  75. static struct audio_channel *grab_channel(struct audio_client *);
  76. static int fill_buffer(struct audio_buffer *, signed char *, int);
  77. static int allocate_channel_buffers(struct audio_channel *);
  78. static void loadup_dma(struct audio_channel *, struct audio_buffer *);
  79.  
  80. static struct module_info audiomiinfo =
  81. {
  82.     0, "audio", 0, INFPSZ, 1024, 0,
  83. };
  84.  
  85. static struct qinit audiorinit =
  86. {
  87.     NULL, NULL, audioopen, audioclose, NULL, &audiomiinfo,
  88. };
  89.  
  90. static struct module_info audiomoinfo =
  91. {
  92.     42, "audio", 0, INFPSZ, AUDIO_BUFFER_SIZE * 4, AUDIO_BUFFER_SIZE,
  93. };
  94.  
  95. static struct qinit audiowinit =
  96. {
  97.     audiowput, audiowsrv, audioopen, audioclose, NULL, &audiomoinfo,
  98. };
  99.  
  100. struct streamtab audioinfo =
  101. {
  102.     &audiorinit, &audiowinit, NULL, NULL,
  103. };
  104.  
  105. #define blklen(bp)    (bp->b_wptr - bp->b_rptr)
  106.  
  107. static struct audio_buffer silent_buffer, handfeed_buffer;
  108.  
  109. /*
  110.  * audio_channel: one for each audio port we have.  The standard
  111.  * amiga has four channels, two dedicated to the left speaker, and
  112.  * two to the right speaker.
  113.  */
  114. static struct audio_channel audio_channel[MAXCHANNELS] =
  115. {
  116.     { NULL, AIEAUD0, DMAAUD0, },
  117.     { NULL, AIEAUD1, DMAAUD1, },
  118.     { NULL, AIEAUD2, DMAAUD2, },
  119.     { NULL, AIEAUD3, DMAAUD3, },
  120. };
  121.  
  122. static struct audio_client *audio_clients;
  123.  
  124. static int audioinit(void)
  125. {
  126.     int i;
  127.     static boolean_t initialized;
  128.  
  129.     if (initialized)
  130.     return 0;
  131.  
  132.     silent_buffer.data = AllocMem(2, MEMF_CHIP);
  133.     if (!silent_buffer.data)
  134.     {
  135.     printf("audioinit: Couldn't allocate 2 bytes of chip memory\n");
  136.     return 1;
  137.     }
  138.     silent_buffer.data[0] = silent_buffer.data[1] = 0;
  139.     silent_buffer.size = 2;
  140.     silent_buffer.nbytes = 2;
  141.     silent_buffer.period = 1;
  142.     silent_buffer.volume = 0;
  143.     silent_buffer.repeat = 0;
  144.  
  145.     handfeed_buffer.data = silent_buffer.data;
  146.     handfeed_buffer.size = 2;
  147.     handfeed_buffer.nbytes = 2;
  148.     handfeed_buffer.period = 1;
  149.     handfeed_buffer.volume = 0;
  150.     handfeed_buffer.repeat = 0;
  151.  
  152.     for (i = 0; i < MAXCHANNELS; ++i)
  153.     {
  154.     /*
  155.      * Clear and disable channel
  156.      */
  157.     AMIGA->intena = AINTCLR | audio_channel[i].dmadone;
  158.     AMIGA->intreq = AINTCLR | audio_channel[i].dmadone;
  159.     AMIGA->dmacon =  DMACLR | audio_channel[i].enable;
  160.  
  161.     audio_channel[i].audio = &AMIGA->audio[i];
  162.     audio_channel[i].audio->buf = silent_buffer.data;
  163.     audio_channel[i].audio->size = 1;
  164.     audio_channel[i].audio->period = 1;
  165.     audio_channel[i].audio->loud = 0;
  166.     audio_channel[i].audio->data = 0;
  167.     if (allocate_channel_buffers(&audio_channel[i]))
  168.     {
  169.         printf("couldn't allocate channel buffer %d\n", i);
  170.  
  171.         /* XXX Need to free previously allocated audio buffers */
  172.          
  173.         return 1;
  174.     }
  175.  
  176.     /* <IMPLEMENT> There should be a timeout here incase */
  177.     /* <IMPLEMENT> the audio hardware is broken */
  178.     while (!(AMIGA->intreqr & audio_channel[i].dmadone))
  179.         ;
  180.  
  181.     AMIGA->intreq = AINTCLR | audio_channel[i].dmadone;
  182.     }
  183.  
  184.     initialized = B_TRUE;
  185.  
  186.     return 0;
  187. }
  188.  
  189. static int allocate_channel_buffers(struct audio_channel *ach)
  190. {
  191.     ach->buffer[0].data = AllocMem(AUDIO_BUFFER_SIZE, MEMF_CHIP);
  192.     if (!ach->buffer[0].data)
  193.     return ENOMEM;
  194.  
  195.     ach->buffer[0].size = AUDIO_BUFFER_SIZE;
  196.  
  197.     ach->buffer[1].data = AllocMem(AUDIO_BUFFER_SIZE, MEMF_CHIP);
  198.     if (!ach->buffer[1].data)
  199.     {
  200.     FreeMem(ach->buffer[0].data, AUDIO_BUFFER_SIZE);
  201.     return ENOMEM;
  202.     }
  203.  
  204.     ach->buffer[1].size = AUDIO_BUFFER_SIZE;
  205.  
  206.     ach->buffer[2].data = AllocMem(AUDIO_BUFFER_SIZE, MEMF_CHIP);
  207.     if (!ach->buffer[2].data)
  208.     {
  209.     FreeMem(ach->buffer[0].data, AUDIO_BUFFER_SIZE);
  210.     FreeMem(ach->buffer[1].data, AUDIO_BUFFER_SIZE);
  211.     return ENOMEM;
  212.     }
  213.  
  214.     ach->buffer[2].size = AUDIO_BUFFER_SIZE;
  215.  
  216.     ach->buffer[0].nbytes = ach->buffer[1].nbytes = ach->buffer[2].nbytes = 0;
  217.     ach->playing = ach->loaded = ach->filling = 0;
  218.  
  219.     return 0;
  220. }
  221.  
  222. static int audioopen(queue_t *q, dev_t *devp, int flag, int sflag,
  223.              cred_t *credp)
  224. {
  225.     struct audio_client *acl, *aclp;
  226.     minor_t mindev;
  227.     int s;
  228.  
  229.     if (q->q_ptr)
  230.     return EBUSY;
  231.  
  232.     if (sflag == MODOPEN || getminor(*devp))
  233.     return EINVAL;
  234.  
  235.     acl = kmem_alloc(sizeof *acl, 0);
  236.     if (!acl)
  237.     return ENOMEM;
  238.  
  239.     s = splaudio();
  240.  
  241.     if (audioinit())
  242.     {
  243.     splx(s);
  244.     return ENOMEM;
  245.     }
  246.  
  247.     for (mindev = 1; mindev <= MAXMIN; ++mindev)
  248.     {
  249.     for (aclp = audio_clients; aclp; aclp = aclp->next)
  250.     {
  251.         if (mindev == aclp->mindev)
  252.         break;
  253.     }
  254.  
  255.     if (!aclp)
  256.         break;
  257.     }
  258.     if (mindev > MAXMIN)
  259.     {
  260.     splx(s);
  261.     kmem_free(acl, sizeof *acl);
  262.     return ENXIO;
  263.     }
  264.  
  265.     acl->flags = 0;
  266.     acl->port = 0;
  267.     acl->volume = BLOUD;
  268.     acl->period = BPER;
  269.     acl->repeat = 0;
  270.     acl->wq = WR(q);
  271.     acl->mindev = mindev;
  272.     *devp = makedevice(getmajor(*devp), mindev);
  273.  
  274.     q->q_ptr = acl;
  275.     WR(q)->q_ptr = acl;
  276.  
  277.     acl->next = audio_clients;
  278.     audio_clients = acl;
  279.  
  280.     splx(s);
  281.  
  282.     return 0;
  283. }
  284.  
  285. static int audioclose(queue_t *q)
  286. {
  287.     struct audio_client **aclpp, *acl = (struct audio_client *)q->q_ptr;
  288.     int s = splaudio();
  289.  
  290.     while (WR(q)->q_first)
  291.     {
  292.     /*
  293.      * There are still some requests pending;  Wait for drain.
  294.      */
  295.  
  296.     acl->flags |= AUD_CCLOSING;
  297.     if (sleep(acl, PCATCH | PZERO))
  298.         break;
  299.     }
  300.  
  301.     if (audio_channel[acl->port].client == acl)
  302.     audio_channel[acl->port].client = 0;
  303.  
  304.     for (aclpp = &audio_clients; *aclpp; aclpp = &(*aclpp)->next)
  305.     {
  306.     if (*aclpp == acl)
  307.     {
  308.         *aclpp = (*aclpp)->next;
  309.         break;
  310.     }
  311.     }
  312.  
  313.     q->q_ptr = 0;
  314.     WR(q)->q_ptr = 0;
  315.  
  316.     splx(s);
  317.  
  318.     kmem_free(acl, sizeof *acl);
  319.  
  320.     return 0;
  321. }
  322.  
  323. static int audiowput(struct queue *q, mblk_t *mp)
  324. {
  325.     int s = splaudio();
  326.  
  327.     switch (mp->b_datap->db_type)
  328.     {
  329.     case M_DATA:
  330.     putq(q, mp);
  331.     break;
  332.  
  333.     case M_IOCTL:
  334.     case M_IOCDATA:
  335.     audioioctl(q, mp);
  336.     break;
  337.  
  338.     default:
  339.     freemsg(mp);
  340.     break;
  341.     }
  342.  
  343.     splx(s);
  344.  
  345.     return 0;
  346. }
  347.  
  348. static void audioioctl(queue_t *q, mblk_t *mp)
  349. {
  350.     struct iocblk *iocbp = (struct iocblk *)mp->b_rptr;
  351.     struct audio_client *audio_client = (struct audio_client *)q->q_ptr;
  352.     
  353.     if (mp->b_datap->db_type == M_IOCDATA)
  354.     {
  355.     /*
  356.      * For copyin/copyout failures, just free message.
  357.      */
  358.     if (((struct copyresp *)mp->b_rptr)->cp_rval)
  359.     {
  360.         freemsg(mp);
  361.         return;
  362.     }
  363.  
  364.     if (!((struct copyresp *)mp->b_rptr)->cp_private)
  365.     {
  366.         mp->b_datap->db_type = M_IOCACK;
  367.         freemsg(unlinkb(mp));
  368.         iocbp->ioc_count = 0;
  369.         iocbp->ioc_rval = 0;
  370.         iocbp->ioc_error = 0;
  371.         putnext(RD(q), mp);
  372.         return;
  373.     }
  374.     }
  375.  
  376.     switch (iocbp->ioc_cmd)
  377.     {
  378.     case AUDIO_VOLUME:
  379.     {
  380.         int *volume;
  381.  
  382.         if (mp->b_datap->db_type == M_IOCTL &&
  383.         iocbp->ioc_count == TRANSPARENT)
  384.         {
  385.         struct copyreq *creq = (struct copyreq *)mp->b_rptr;
  386.         mp->b_datap->db_type = M_COPYIN;
  387.         creq->cq_addr = *(caddr_t *)mp->b_cont->b_rptr;
  388.         mp->b_wptr = mp->b_rptr + sizeof *creq;
  389.         creq->cq_size = sizeof *volume;
  390.         creq->cq_flag = 0;
  391.         creq->cq_private = (mblk_t *)1;
  392.         putnext(RD(q), mp);
  393.         return;
  394.         }
  395.         else
  396.         {
  397.         mblk_t *bp1;
  398.         int i;
  399.  
  400.         (void) pullupmsg(mp->b_cont, -1);
  401.  
  402.         if (!mp->b_cont || blklen(mp->b_cont) != sizeof *volume)
  403.         {
  404.             iocbp->ioc_error = EINVAL;
  405.             mp->b_datap->db_type = M_IOCNAK;
  406.             iocbp->ioc_count = 0;
  407.             putnext(RD(q), mp);
  408.             break;
  409.         }
  410.  
  411.         volume = (int *)mp->b_cont->b_rptr;
  412.  
  413.         mp->b_datap->db_type = M_IOCACK;
  414.  
  415.         audio_client->volume = *volume;
  416.  
  417.         bp1 = unlinkb(mp);
  418.         if (bp1)
  419.             freeb(bp1);
  420.         iocbp->ioc_count = 0;
  421.         putnext(RD(q), mp);
  422.  
  423.         }
  424.         break;
  425.     }
  426.  
  427.     case AUDIO_PERIOD:
  428.     {
  429.         int *period;
  430.  
  431.         if (mp->b_datap->db_type == M_IOCTL &&
  432.         iocbp->ioc_count == TRANSPARENT)
  433.         {
  434.         struct copyreq *creq = (struct copyreq *)mp->b_rptr;
  435.         mp->b_datap->db_type = M_COPYIN;
  436.         creq->cq_addr = *(caddr_t *)mp->b_cont->b_rptr;
  437.         mp->b_wptr = mp->b_rptr + sizeof *creq;
  438.         creq->cq_size = sizeof *period;
  439.         creq->cq_flag = 0;
  440.         creq->cq_private = (mblk_t *)1;
  441.         putnext(RD(q), mp);
  442.         return;
  443.         }
  444.         else
  445.         {
  446.         mblk_t *bp1;
  447.         int i;
  448.  
  449.         (void) pullupmsg(mp->b_cont, -1);
  450.  
  451.         if (!mp->b_cont || blklen(mp->b_cont) != sizeof *period)
  452.         {
  453.             iocbp->ioc_error = EINVAL;
  454.             mp->b_datap->db_type = M_IOCNAK;
  455.             iocbp->ioc_count = 0;
  456.             putnext(RD(q), mp);
  457.             break;
  458.         }
  459.  
  460.         period = (int *)mp->b_cont->b_rptr;
  461.  
  462.         mp->b_datap->db_type = M_IOCACK;
  463.  
  464.         audio_client->period = *period;
  465.  
  466.         bp1 = unlinkb(mp);
  467.         if (bp1)
  468.             freeb(bp1);
  469.         iocbp->ioc_count = 0;
  470.         putnext(RD(q), mp);
  471.  
  472.         }
  473.         break;
  474.     }
  475.  
  476.     case AUDIO_REPEAT:
  477.     {
  478.         int *repeat;
  479.  
  480.         if (mp->b_datap->db_type == M_IOCTL &&
  481.         iocbp->ioc_count == TRANSPARENT)
  482.         {
  483.         struct copyreq *creq = (struct copyreq *)mp->b_rptr;
  484.         mp->b_datap->db_type = M_COPYIN;
  485.         creq->cq_addr = *(caddr_t *)mp->b_cont->b_rptr;
  486.         mp->b_wptr = mp->b_rptr + sizeof *creq;
  487.         creq->cq_size = sizeof *repeat;
  488.         creq->cq_flag = 0;
  489.         creq->cq_private = (mblk_t *)1;
  490.         putnext(RD(q), mp);
  491.         return;
  492.         }
  493.         else
  494.         {
  495.         mblk_t *bp1;
  496.         int i;
  497.  
  498.         (void) pullupmsg(mp->b_cont, -1);
  499.  
  500.         if (!mp->b_cont || blklen(mp->b_cont) != sizeof *repeat)
  501.         {
  502.             iocbp->ioc_error = EINVAL;
  503.             mp->b_datap->db_type = M_IOCNAK;
  504.             iocbp->ioc_count = 0;
  505.             putnext(RD(q), mp);
  506.             break;
  507.         }
  508.  
  509.         repeat = (int *)mp->b_cont->b_rptr;
  510.  
  511.         mp->b_datap->db_type = M_IOCACK;
  512.  
  513.         audio_client->repeat = *repeat;
  514.  
  515.         bp1 = unlinkb(mp);
  516.         if (bp1)
  517.             freeb(bp1);
  518.         iocbp->ioc_count = 0;
  519.         putnext(RD(q), mp);
  520.  
  521.         }
  522.         break;
  523.     }
  524.  
  525.     default:
  526.     mp->b_datap->db_type = M_IOCNAK;
  527.     freemsg(unlinkb(mp));
  528.     iocbp->ioc_count = 0;
  529.     iocbp->ioc_rval = 0;
  530.     iocbp->ioc_error = EINVAL;
  531.     putnext(RD(q), mp);
  532.     return;
  533.     }
  534.  
  535.     mp->b_datap->db_type = M_IOCACK;
  536.     freemsg(unlinkb(mp));
  537.     iocbp->ioc_count = 0;
  538.     iocbp->ioc_rval = 0;
  539.     iocbp->ioc_error = 0;
  540.     putnext(RD(q), mp);
  541. }
  542.  
  543. static int audiowsrv(queue_t *q)
  544. {
  545.     mblk_t *mp;
  546.     struct audio_client *acl = (struct audio_client *)q->q_ptr;
  547.     int s = splaudio();
  548.  
  549.     /*
  550.      * Service all requests possible.
  551.      */
  552.  
  553.     while ((mp = getq(q, mp)))
  554.     {
  555.     if (postaudio(acl, mp))
  556.     {
  557.         /*
  558.          * Couldn't service this request so places us on the
  559.          * audio_clients list and we will be qenabled after
  560.          * the next write interrupt.
  561.          */
  562.  
  563.         putbq(q, mp);
  564.         break;
  565.     }
  566.  
  567.     freemsg(mp);
  568.     }
  569.  
  570.     splx(s);
  571.  
  572.     return 0;
  573. }
  574.  
  575. static int fill_buffer(struct audio_buffer *buffer, signed char *data, int len)
  576. {
  577.     int size = min(len, buffer->size - buffer->nbytes);
  578.  
  579.     bcopy(data, buffer->data + buffer->nbytes, size);
  580.     buffer->nbytes += size;
  581.  
  582.     return size;
  583. }
  584.  
  585. static int postaudio(struct audio_client *acl, mblk_t *mp)
  586. {
  587.     struct audio_channel *ach;
  588.  
  589.     ach = grab_channel(acl);
  590.     if (!ach)
  591.     return 1;
  592.  
  593.     if (!ach->filling)
  594.     {
  595.     /*
  596.      * Find a buffer that we may use for filling
  597.      */
  598.  
  599.     ach->filling =
  600.         !ach->buffer[0].nbytes ? &ach->buffer[0] :
  601.         !ach->buffer[1].nbytes ? &ach->buffer[1] :
  602.             !ach->buffer[2].nbytes ? &ach->buffer[2] :
  603.             (panic("no fillable audio buffers"),
  604.              (struct audio_buffer *)0);
  605.  
  606.     ach->filling->volume = acl->volume;
  607.     ach->filling->period = acl->period;
  608.     ach->filling->repeat = acl->repeat;
  609.     }
  610.  
  611.     mp->b_rptr +=
  612.     fill_buffer(ach->filling, (signed char *)mp->b_rptr, blklen(mp));
  613.  
  614.     if (!ach->playing)
  615.     {
  616.     /*
  617.      * Handfeed first byte and load up the audio hardware to grab
  618.      * dma registers at next scan line.  This is the only way to
  619.      * garrantee that we will play the first dma'd audio sound to
  620.      * a channel.
  621.      */
  622.  
  623.     AMIGA->intena = AINTCLR | ach->dmadone; /* Disable interupts */
  624.     AMIGA->dmacon =  DMACLR | ach->enable;  /* Disable DMA for now */
  625.     AMIGA->intreq = AINTCLR | ach->dmadone; /* Clear interupt */
  626.  
  627.     if (!ach->loaded)
  628.         ach->loaded = &handfeed_buffer;
  629.  
  630.     ach->audio->buf = silent_buffer.data;
  631.     ach->audio->size = 1;
  632.     ach->audio->period = 1;
  633.     ach->audio->loud = 0;
  634.     ach->audio->data = 0;
  635.  
  636.     /*
  637.      * Busy-wait for hand fed word
  638.      */
  639.  
  640.     while (!(AMIGA->intreqr & ach->dmadone))
  641.         ;
  642.  
  643.     AMIGA->dmacon =  DMASET | ach->enable;  /* Enable DMA */
  644.     AMIGA->intreq = AINTCLR | ach->dmadone; /* Clear interupt */
  645.     AMIGA->intena = AINTSET | ach->dmadone; /* Enable interupts */
  646.     }
  647.  
  648.     return mp->b_wptr - mp->b_rptr;
  649. }
  650.  
  651. static struct audio_channel *grab_channel(struct audio_client *acl)
  652. {
  653.     if (audio_channel[acl->port].client != acl)
  654.     {
  655.     int i;
  656.  
  657.     for (i = 0; i < MAXCHANNELS; ++i)
  658.     {
  659.         if (!audio_channel[i].client)
  660.         {
  661.         /*
  662.          * This channel is not allocated--Use it.
  663.          */
  664.  
  665.         acl->port = i;
  666.         break;
  667.         }
  668.     }
  669.  
  670.     if (i >= MAXCHANNELS)
  671.         return 0;            /* No free channels */
  672.  
  673.     audio_channel[acl->port].client = acl;
  674.     }
  675.  
  676.     return &audio_channel[acl->port];
  677. }
  678.  
  679. static void loadup_dma(struct audio_channel *ach,
  680.                struct audio_buffer *load_buffer)
  681. {
  682.     ach->audio->buf = load_buffer->data;
  683.     ach->audio->size = load_buffer->nbytes / 2;
  684.  
  685.     ach->loaded = load_buffer;
  686. }
  687.  
  688. void audiointr(unsigned int reqbits)
  689. {
  690.     int i;
  691.  
  692.     if (panicstr)
  693.     {
  694.     /*
  695.      * The system has paniced; Turn off audio ports.
  696.      */
  697.  
  698.     AMIGA->intena = AINTCLR | AIEAUD0 | AIEAUD1 | AIEAUD2 | AIEAUD3;
  699.     AMIGA->dmacon =  DMACLR | DMAAUD0 | DMAAUD1 | DMAAUD2 | DMAAUD3;
  700.     return;
  701.     }
  702.  
  703.     for (i = 0; i < MAXCHANNELS; ++i)
  704.     {
  705.     /*
  706.      * If this channel is in use: Check to see if the DMA finished
  707.      * our last request and post another audio if it has.  If this
  708.      * queue is empty, remove it from the audio_channel queue,
  709.      * disable the audio channel and wake up the client if it is
  710.      * sleeping in close.
  711.      */
  712.  
  713.     if (reqbits & (1 << i))
  714.     {
  715.         struct audio_channel *ach = &audio_channel[i];
  716.         struct audio_client *acl = ach->client;
  717.  
  718.         if (ach->playing && ach->playing != &silent_buffer)
  719.         {
  720.         ach->audio->period = ach->playing->period;
  721.         ach->audio->loud = ach->playing->volume;
  722.         if (ach->playing->repeat > 0)
  723.         {
  724.             --ach->playing->repeat;
  725.             loadup_dma(ach, ach->playing);
  726.             continue;
  727.         }
  728.         else
  729.             ach->playing->nbytes = 0;
  730.         }
  731.  
  732.         if (acl)
  733.         {
  734.         qenable(acl->wq);
  735.  
  736.         if (!acl->wq->q_first && acl->flags & AUD_CCLOSING)
  737.         {
  738.             acl->flags &= ~AUD_CCLOSING;
  739.             wakeup(acl);
  740.             ach->client = 0;
  741.         }
  742.         }
  743.  
  744.         ach->playing = ach->loaded;
  745.  
  746.         if (ach->filling)
  747.         {
  748.         loadup_dma(ach, ach->filling);
  749.         ach->filling = 0;
  750.         if (acl)
  751.             qenable(acl->wq);
  752.         }
  753.         else
  754.         {
  755.         if (!ach->playing)
  756.         {
  757.             struct audio_client *aclp;
  758.  
  759.             AMIGA->intena = AINTCLR | ach->dmadone;
  760.             AMIGA->dmacon =  DMACLR | ach->enable;
  761.  
  762.             ach->client = 0;
  763.  
  764.             for (aclp = audio_clients; aclp; aclp = aclp->next)
  765.             qenable(aclp->wq);
  766.         }
  767.         else if (ach->playing == &silent_buffer)
  768.             ach->loaded = 0;
  769.         else
  770.             loadup_dma(ach, &silent_buffer);
  771.         }
  772.     }
  773.     }
  774. }
  775.  
  776. boolean_t play_audio(struct audio_client *client, struct audio_buffer *buffer,
  777.              boolean_t force)
  778. {
  779.     int s = splaudio();
  780.     
  781.     splx(s);
  782.  
  783.     return B_TRUE;
  784. }
  785. @EOF
  786.  
  787. chmod 644 audio.c
  788.  
  789. echo x - audio.h
  790. cat >audio.h <<'@EOF'
  791. #ifndef _AUDIO_H
  792. #define _AUDIO_H
  793.  
  794. #define MAXCHANNELS    (4)
  795.  
  796. #ifdef _KERNEL
  797.  
  798. #define AUD_CCLOSING    (0x01)        /* client in close */
  799.  
  800. struct audio_client
  801. {
  802.     int                 flags;
  803.     int                 port;
  804.     unsigned short         volume;
  805.     unsigned short         period;
  806.     int                 repeat;
  807.     queue_t            *wq;
  808.     struct audio_client        *next;
  809.     minor_t             mindev;
  810. };
  811.  
  812. struct audio_buffer
  813. {
  814.     signed char            *data;    /* chip memory */
  815.     int                 size;    /* size of buffer */
  816.     int                 nbytes; /* number of bytes copied in buffer */
  817.     unsigned short         volume;
  818.     unsigned short         period;
  819.     int                 repeat; /* number of interations for wave */
  820. };
  821.  
  822. struct audio_channel
  823. {
  824.     volatile struct amiga_audio    *audio;
  825.     int                 dmadone; /* AMIGA->intreqr; AUD block done */
  826.     int                 enable; /* AMIGA->dmacon; AUD chan enable */
  827.     struct audio_client        *client; /* Client connected to this channel */
  828.     struct audio_buffer         buffer[3];
  829.     struct audio_buffer        *playing, *loaded, *filling;
  830. };
  831.  
  832. #endif /* _KERNEL */
  833.  
  834. #define AUDIO_BUFFER_SIZE    8192
  835.  
  836. #define    AUIOC            ('U' << 8)
  837. #define AUDIO_VOLUME        (AUIOC | 1)
  838. #define AUDIO_PERIOD        (AUIOC | 2)
  839. #define AUDIO_REPEAT        (AUIOC | 3)
  840.  
  841.  
  842. #define BLOUD 63
  843. #define BPER  400
  844.  
  845. #define    splaudio    spl4
  846.  
  847. #endif /* _AUDIO_H */
  848. @EOF
  849.  
  850. chmod 644 audio.h
  851.  
  852. exit 0
  853.