Bump up the SYMTAB_SPACE for LINT. It was already too small again.
[unix-history] / sys / i386 / isa / pcaudio.c
index 73f2ad7..68d4bf9 100644 (file)
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *     $Id: 
+ *     $Id$ 
  */
 
  */
 
-#include "param.h"
+#include "systm.h"
 #include "uio.h"
 #include "ioctl.h"
 #include "uio.h"
 #include "ioctl.h"
+#include "proc.h"
+#include "file.h"
 #include "sound/ulaw.h"
 #include "machine/cpufunc.h"
 #include "machine/pio.h"
 #include "machine/pcaudioio.h"
 #include "sound/ulaw.h"
 #include "machine/cpufunc.h"
 #include "machine/pio.h"
 #include "machine/pcaudioio.h"
+#include "i386/isa/isa.h"
 #include "i386/isa/isa_device.h"
 #include "i386/isa/timerreg.h"
 
 #include "pca.h"
 #if NPCA > 0
 
 #include "i386/isa/isa_device.h"
 #include "i386/isa/timerreg.h"
 
 #include "pca.h"
 #if NPCA > 0
 
-#define BUF_SIZE       8192
+#define BUF_SIZE       4*8192
 #define SAMPLE_RATE    8000
 #define INTERRUPT_RATE 16000
 
 #define SAMPLE_RATE    8000
 #define INTERRUPT_RATE 16000
 
@@ -60,6 +63,8 @@ static struct pca_status {
        char            current;        /* current buffer */
        unsigned char   oldval;         /* old timer port value */
        char            timer_on;       /* is playback running */
        char            current;        /* current buffer */
        unsigned char   oldval;         /* old timer port value */
        char            timer_on;       /* is playback running */
+       char            coll;           /* select collision */
+       pid_t           wsel;           /* pid of select'ing proc */
 } pca_status;
 
 static char buffer1[BUF_SIZE];
 } pca_status;
 
 static char buffer1[BUF_SIZE];
@@ -76,22 +81,24 @@ int pcaclose(dev_t dev, int flag);
 int pcaopen(dev_t dev, int flag);
 int pcawrite(dev_t dev, struct uio *uio, int flag);
 int pcaioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p);
 int pcaopen(dev_t dev, int flag);
 int pcawrite(dev_t dev, struct uio *uio, int flag);
 int pcaioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p);
+int pcaselect(dev_t dev, int rw, struct proc *p);
 
 struct isa_driver pcadriver = {
        pcaprobe, pcaattach, "pca",
 };
 
 
 
 struct isa_driver pcadriver = {
        pcaprobe, pcaattach, "pca",
 };
 
 
-inline void translate_bytes(const void *table, void *buff, unsigned long n)
+inline void conv(const void *table, void *buff, unsigned long n)
 {
 {
-  __asm__("cld\n"
-          "1:\tlodsb\n\t"
-          "xlatb\n\t"
-          "stosb\n\t"
-          "loop 1b\n\t"
+  __asm__("1:\tmovb (%2), %3\n"
+          "\txlatb\n"
+          "\tmovb %3, (%2)\n"
+         "\tinc %2\n"
+         "\tdec %1\n"
+         "\tjnz 1b\n"
           :
           :
-          :"b" ((long)table), "c" (n), "D" ((long)buff), "S" ((long)buff)
-          :"bx","cx","di","si","ax");
+          :"b" ((long)table), "c" (n), "D" ((long)buff), "a" ((char)n)
+          :"bx","cx","di","ax");
 }
 
 
 }
 
 
@@ -101,7 +108,7 @@ pca_volume(int volume)
        int i, j;
 
        for (i=0; i<256; i++) {
        int i, j;
 
        for (i=0; i<256; i++) {
-               j = ((i-128)*volume) >> 8;
+               j = ((i-128)*volume)/100;
                if (j<-128)
                        j = -128;
                if (j>127)
                if (j<-128)
                        j = -128;
                if (j>127)
@@ -139,7 +146,7 @@ pca_start(void)
        pca_status.index = 0;
        pca_status.counter = 0;
         pca_status.buffer  = pca_status.buf[pca_status.current];
        pca_status.index = 0;
        pca_status.counter = 0;
         pca_status.buffer  = pca_status.buf[pca_status.current];
-        pca_status.oldval = inb(0x61) | 0x03;
+        pca_status.oldval = inb(IO_PPI) | 0x03;
         /* acquire the timers */
        if (acquire_timer2(TIMER_LSB|TIMER_ONESHOT)) {
                return -1;
         /* acquire the timers */
        if (acquire_timer2(TIMER_LSB|TIMER_ONESHOT)) {
                return -1;
@@ -181,7 +188,7 @@ pca_pause()
 static void 
 pca_continue()
 {
 static void 
 pca_continue()
 {
-        pca_status.oldval = inb(0x61) | 0x03;
+        pca_status.oldval = inb(IO_PPI) | 0x03;
        acquire_timer2(TIMER_LSB|TIMER_ONESHOT);
        acquire_timer0(INTERRUPT_RATE, pcaintr);
        pca_status.timer_on = 1;
        acquire_timer2(TIMER_LSB|TIMER_ONESHOT);
        acquire_timer0(INTERRUPT_RATE, pcaintr);
        pca_status.timer_on = 1;
@@ -191,7 +198,7 @@ pca_continue()
 static void 
 pca_wait(void)
 {
 static void 
 pca_wait(void)
 {
-       while (pca_status.in_use[1] || pca_status.in_use[2]) {
+       while (pca_status.in_use[0] || pca_status.in_use[1]) {
                pca_sleep = 1;
                tsleep((caddr_t)&pca_sleep, PZERO|PCATCH, "pca_drain", 0);
         }
                pca_sleep = 1;
                tsleep((caddr_t)&pca_sleep, PZERO|PCATCH, "pca_drain", 0);
         }
@@ -208,7 +215,7 @@ pcaprobe(struct isa_device *dvp)
 int
 pcaattach(struct isa_device *dvp)
 {
 int
 pcaattach(struct isa_device *dvp)
 {
-       printf(" internal speaker audio driver\n", dvp->id_unit);
+       printf(" PCM audio driver\n", dvp->id_unit);
        pca_init();
        return 1;
 }
        pca_init();
        return 1;
 }
@@ -268,14 +275,17 @@ pcawrite(dev_t dev, struct uio *uio, int flag)
                return ENXIO;
 
        while ((count = min(BUF_SIZE, uio->uio_resid)) > 0) {
                return ENXIO;
 
        while ((count = min(BUF_SIZE, uio->uio_resid)) > 0) {
+               if (pca_status.in_use[0] && pca_status.in_use[1]) {
+                       pca_sleep = 1;
+                       tsleep((caddr_t)&pca_sleep, PZERO|PCATCH, "pca_wait",0);
+               }
                which = pca_status.in_use[0] ? 1 : 0;
                if (count && !pca_status.in_use[which]) {
                        uiomove(pca_status.buf[which], count, uio);
                        pca_status.processed += count;
                        switch (pca_status.encoding) {
                        case AUDIO_ENCODING_ULAW:
                which = pca_status.in_use[0] ? 1 : 0;
                if (count && !pca_status.in_use[which]) {
                        uiomove(pca_status.buf[which], count, uio);
                        pca_status.processed += count;
                        switch (pca_status.encoding) {
                        case AUDIO_ENCODING_ULAW:
-                               translate_bytes(ulaw_dsp, 
-                                               pca_status.buf[which], count);
+                               conv(ulaw_dsp, pca_status.buf[which], count);
                                break;
 
                        case AUDIO_ENCODING_ALAW:
                                break;
 
                        case AUDIO_ENCODING_ALAW:
@@ -289,10 +299,6 @@ pcawrite(dev_t dev, struct uio *uio, int flag)
                                if (pca_start()) 
                                        return EBUSY;
                }
                                if (pca_start()) 
                                        return EBUSY;
                }
-               if (pca_status.in_use[0] && pca_status.in_use[1]) {
-                       pca_sleep = 1;
-                       tsleep((caddr_t)&pca_sleep, PZERO|PCATCH, "pca_wait",0);
-               }
        } 
        return 0;
 }
        } 
        return 0;
 }
@@ -301,7 +307,7 @@ pcawrite(dev_t dev, struct uio *uio, int flag)
 int
 pcaioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
 {
 int
 pcaioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
 {
-audio_info_t *auptr;
+       audio_info_t *auptr;
 
        switch(cmd) {
 
 
        switch(cmd) {
 
@@ -315,7 +321,6 @@ audio_info_t *auptr;
                auptr->play.gain = pca_status.volume;
                auptr->play.port = 0;
 
                auptr->play.gain = pca_status.volume;
                auptr->play.port = 0;
 
-
                auptr->play.samples = pca_status.processed;
                auptr->play.eof = 0;
                auptr->play.pause = !pca_status.timer_on;
                auptr->play.samples = pca_status.processed;
                auptr->play.eof = 0;
                auptr->play.pause = !pca_status.timer_on;
@@ -366,18 +371,20 @@ void
 pcaintr(int regs)
 {
        if (pca_status.index < pca_status.in_use[pca_status.current]) {
 pcaintr(int regs)
 {
        if (pca_status.index < pca_status.in_use[pca_status.current]) {
-               outb(0x61, pca_status.oldval);
-               __asm__("xorb $1,%0\n\t"
-                       "outb %0,$97"
+               disable_intr();
+               __asm__("outb %0,$0x61\n"
+                       "andb $0xFE,%0\n"
+                       "outb %0,$0x61"
                        : : "a" ((char)pca_status.oldval) );
                        : : "a" ((char)pca_status.oldval) );
-               __asm__("xlatb\n\t"
-                       "outb %0,$66"
+               __asm__("xlatb\n"
+                       "outb %0,$0x42"
                        : : "a" ((char)pca_status.buffer[pca_status.index]),
                            "b" ((long)volume_table) );
                        : : "a" ((char)pca_status.buffer[pca_status.index]),
                            "b" ((long)volume_table) );
+               enable_intr();
                pca_status.counter += pca_status.scale;
                pca_status.index = (pca_status.counter >> 8);
        }
                pca_status.counter += pca_status.scale;
                pca_status.index = (pca_status.counter >> 8);
        }
-       else {
+       if (pca_status.index >= pca_status.in_use[pca_status.current]) {
                pca_status.index = pca_status.counter = 0;
                pca_status.in_use[pca_status.current] = 0;
                pca_status.current ^= 1;
                pca_status.index = pca_status.counter = 0;
                pca_status.in_use[pca_status.current] = 0;
                pca_status.current ^= 1;
@@ -386,7 +393,38 @@ pcaintr(int regs)
                        wakeup((caddr_t)&pca_sleep);
                        pca_sleep = 0;
                }
                        wakeup((caddr_t)&pca_sleep);
                        pca_sleep = 0;
                }
+               if (pca_status.wsel) {
+                       selwakeup(pca_status.wsel, pca_status.coll);
+                       pca_status.wsel = 0;
+                       pca_status.coll = 0;
+               }
        }
 }
 
        }
 }
 
+
+int
+pcaselect(dev_t dev, int rw, struct proc *p)
+{
+       int s = spltty();
+       struct proc *p1;
+
+       switch (rw) {
+
+       case FWRITE:
+               if (!pca_status.in_use[0] || !pca_status.in_use[1]) {
+                       splx(s);
+                       return(1);
+               }
+               if (pca_status.wsel && (p1 = pfind(pca_status.wsel))
+                   && p1->p_wchan == (caddr_t)&selwait)
+                       pca_status.coll = 1;
+               else
+                       pca_status.wsel = p->p_pid;
+               splx(s);
+               return 0;
+       default:
+               splx(s);
+               return(0); 
+       }
+}
 #endif
 #endif