diff options
author | phk <phk@FreeBSD.org> | 2003-08-15 14:56:05 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 2003-08-15 14:56:05 +0000 |
commit | aed7f951ea06264f20ccf68cae719b83772c3e00 (patch) | |
tree | 569c11fdbf03b4625a98fddb28e3cfb8025ec98d | |
parent | 28f9f18fcde5f235daeac773d25cc668c67567e3 (diff) | |
download | FreeBSD-src-aed7f951ea06264f20ccf68cae719b83772c3e00.zip FreeBSD-src-aed7f951ea06264f20ccf68cae719b83772c3e00.tar.gz |
As warned: Initiate deorbit burn for the pcaudio driver.
-rw-r--r-- | sys/conf/files.i386 | 1 | ||||
-rw-r--r-- | sys/conf/files.pc98 | 1 | ||||
-rw-r--r-- | sys/conf/majors | 1 | ||||
-rw-r--r-- | sys/i386/conf/NOTES | 9 | ||||
-rw-r--r-- | sys/i386/isa/pcaudio.c | 563 | ||||
-rw-r--r-- | sys/pc98/conf/NOTES | 9 | ||||
-rw-r--r-- | sys/pc98/pc98/pcaudio.c | 604 |
7 files changed, 0 insertions, 1188 deletions
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 1985524..dcbaab7 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -254,7 +254,6 @@ i386/isa/istallion.c optional stli nowerror i386/isa/loran.c optional loran i386/isa/mse.c optional mse i386/isa/npx.c optional npx -i386/isa/pcaudio.c optional pca i386/isa/pcf.c optional pcf i386/isa/pcvt/pcvt_drv.c optional vt i386/isa/pcvt/pcvt_ext.c optional vt diff --git a/sys/conf/files.pc98 b/sys/conf/files.pc98 index 93a6736..641caf5 100644 --- a/sys/conf/files.pc98 +++ b/sys/conf/files.pc98 @@ -347,7 +347,6 @@ pc98/pc98/olpt.c optional olpt pc98/pc98/pc98gdc.c optional gdc pc98/pc98/pc98kbd.c optional pckbd pc98/pc98/pc98_machdep.c standard -pc98/pc98/pcaudio.c optional pca pc98/pc98/pmc.c optional pmc pc98/pc98/ppc.c optional ppc pc98/pc98/scgdcrndr.c optional sc gdc diff --git a/sys/conf/majors b/sys/conf/majors index d57c0b3..90333d4 100644 --- a/sys/conf/majors +++ b/sys/conf/majors @@ -37,7 +37,6 @@ 21 *psm PS/2 Mouse 22 *fd (/dev/stdin etc) 23 *bpf Berkeley Packet Filter -24 *pca PC speaker (/dev/pcaudio) 26 *spkr PC speaker (/dev/spkr) 27 *mse Microsoft bus-mouse 28 *sio 16450/16550 serial diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES index 15e2cb9..c94c84d 100644 --- a/sys/i386/conf/NOTES +++ b/sys/i386/conf/NOTES @@ -532,15 +532,6 @@ options WLCACHE # enables the signal-strength cache options WLDEBUG # enables verbose debugging output # -# Audio drivers: `pca' -# -# pca: PCM audio through your PC speaker - -device pca -hint.pca.0.at="isa" -hint.pca.0.port="0x040" - -# # ATA raid adapters # device pst diff --git a/sys/i386/isa/pcaudio.c b/sys/i386/isa/pcaudio.c deleted file mode 100644 index 1fc3b39..0000000 --- a/sys/i386/isa/pcaudio.c +++ /dev/null @@ -1,563 +0,0 @@ -/*- - * Copyright (c) 1994-1998 Søren Schmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/conf.h> -#include <sys/proc.h> -#include <sys/kernel.h> -#include <sys/bus.h> -#include <sys/filio.h> -#include <sys/poll.h> -#include <sys/vnode.h> - -#include <machine/clock.h> -#include <machine/pcaudioio.h> - -#include <isa/isareg.h> -#include <isa/isavar.h> -#include <i386/isa/timerreg.h> - -#define BUF_SIZE 8192 -#define SAMPLE_RATE 8000 -#define INTERRUPT_RATE 16000 - -static struct pca_status { - char open; /* device open */ - char queries; /* did others try opening */ - unsigned char *buf[3]; /* triple buffering */ - unsigned char *buffer; /* current buffer ptr */ - unsigned in_use[3]; /* buffers fill */ - unsigned index; /* index in current buffer */ - unsigned counter; /* sample counter */ - unsigned scale; /* sample counter scale */ - unsigned sample_rate; /* sample rate */ - unsigned processed; /* samples processed */ - unsigned volume; /* volume for pc-speaker */ - char encoding; /* Ulaw, Alaw or linear */ - u_char current; /* current buffer */ - unsigned char oldval; /* old timer port value */ - char timer_on; /* is playback running */ - struct selinfo wsel; /* select/poll status */ -} pca_status; - -static char buffer1[BUF_SIZE]; -static char buffer2[BUF_SIZE]; -static char buffer3[BUF_SIZE]; -static char volume_table[256]; - -static unsigned char ulaw_dsp[] = { - 3, 7, 11, 15, 19, 23, 27, 31, - 35, 39, 43, 47, 51, 55, 59, 63, - 66, 68, 70, 72, 74, 76, 78, 80, - 82, 84, 86, 88, 90, 92, 94, 96, - 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, - 113, 114, 114, 115, 115, 116, 116, 117, - 117, 118, 118, 119, 119, 120, 120, 121, - 121, 121, 122, 122, 122, 122, 123, 123, - 123, 123, 124, 124, 124, 124, 125, 125, - 125, 125, 125, 125, 126, 126, 126, 126, - 126, 126, 126, 126, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 253, 249, 245, 241, 237, 233, 229, 225, - 221, 217, 213, 209, 205, 201, 197, 193, - 190, 188, 186, 184, 182, 180, 178, 176, - 174, 172, 170, 168, 166, 164, 162, 160, - 158, 157, 156, 155, 154, 153, 152, 151, - 150, 149, 148, 147, 146, 145, 144, 143, - 143, 142, 142, 141, 141, 140, 140, 139, - 139, 138, 138, 137, 137, 136, 136, 135, - 135, 135, 134, 134, 134, 134, 133, 133, - 133, 133, 132, 132, 132, 132, 131, 131, - 131, 131, 131, 131, 130, 130, 130, 130, - 130, 130, 130, 130, 129, 129, 129, 129, - 129, 129, 129, 129, 129, 129, 129, 129, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, -}; - -static unsigned char alaw_linear[] = { - 45, 214, 122, 133, 0, 255, 107, 149, - 86, 171, 126, 129, 0, 255, 117, 138, - 13, 246, 120, 135, 0, 255, 99, 157, - 70, 187, 124, 131, 0, 255, 113, 142, - 61, 198, 123, 132, 0, 255, 111, 145, - 94, 163, 127, 128, 0, 255, 119, 136, - 29, 230, 121, 134, 0, 255, 103, 153, - 78, 179, 125, 130, 0, 255, 115, 140, - 37, 222, 122, 133, 0, 255, 105, 151, - 82, 175, 126, 129, 0, 255, 116, 139, - 5, 254, 120, 135, 0, 255, 97, 159, - 66, 191, 124, 131, 0, 255, 112, 143, - 53, 206, 123, 132, 0, 255, 109, 147, - 90, 167, 127, 128, 0, 255, 118, 137, - 21, 238, 121, 134, 0, 255, 101, 155, - 74, 183, 125, 130, 0, 255, 114, 141, - 49, 210, 123, 133, 0, 255, 108, 148, - 88, 169, 127, 129, 0, 255, 118, 138, - 17, 242, 121, 135, 0, 255, 100, 156, - 72, 185, 125, 131, 0, 255, 114, 142, - 64, 194, 124, 132, 0, 255, 112, 144, - 96, 161, 128, 128, 1, 255, 120, 136, - 33, 226, 122, 134, 0, 255, 104, 152, - 80, 177, 126, 130, 0, 255, 116, 140, - 41, 218, 122, 133, 0, 255, 106, 150, - 84, 173, 126, 129, 0, 255, 117, 139, - 9, 250, 120, 135, 0, 255, 98, 158, - 68, 189, 124, 131, 0, 255, 113, 143, - 57, 202, 123, 132, 0, 255, 110, 146, - 92, 165, 127, 128, 0, 255, 119, 137, - 25, 234, 121, 134, 0, 255, 102, 154, - 76, 181, 125, 130, 0, 255, 115, 141, -}; - -static int pca_sleep = 0; - -static void pcaintr(struct clockframe *frame); - -static d_open_t pcaopen; -static d_close_t pcaclose; -static d_write_t pcawrite; -static d_ioctl_t pcaioctl; -static d_poll_t pcapoll; - -#define CDEV_MAJOR 24 -static struct cdevsw pca_cdevsw = { - .d_open = pcaopen, - .d_close = pcaclose, - .d_write = pcawrite, - .d_ioctl = pcaioctl, - .d_poll = pcapoll, - .d_name = "pca", - .d_maj = CDEV_MAJOR, -}; - -static void pca_continue(void); -static void pca_init(void); -static void pca_pause(void); - -static void -conv(const unsigned char *table, unsigned char *buff, unsigned n) -{ - unsigned i; - - for (i = 0; i < n; i++) - buff[i] = table[buff[i]]; -} - - -static void -pca_volume(int volume) -{ - int i, j; - - for (i=0; i<256; i++) { - j = ((i-128)*volume)/25; -/* XXX - j = ((i-128)*volume)/100; -*/ - if (j<-128) - j = -128; - if (j>127) - j = 127; - volume_table[i] = (((255-(j + 128))/4)+1); - } -} - - -static void -pca_init(void) -{ - pca_status.open = 0; - pca_status.queries = 0; - pca_status.timer_on = 0; - pca_status.buf[0] = (unsigned char *)&buffer1[0]; - pca_status.buf[1] = (unsigned char *)&buffer2[0]; - pca_status.buf[2] = (unsigned char *)&buffer3[0]; - pca_status.buffer = pca_status.buf[0]; - pca_status.in_use[0] = pca_status.in_use[1] = pca_status.in_use[2] = 0; - pca_status.current = 0; - pca_status.sample_rate = SAMPLE_RATE; - pca_status.scale = (pca_status.sample_rate << 8) / INTERRUPT_RATE; - pca_status.encoding = AUDIO_ENCODING_ULAW; - pca_status.volume = 100; - - pca_volume(pca_status.volume); -} - - -static int -pca_start(void) -{ - int x = splhigh(); - int rv = 0; - - /* use the first buffer */ - pca_status.current = 0; - pca_status.index = 0; - pca_status.counter = 0; - pca_status.buffer = pca_status.buf[pca_status.current]; - pca_status.oldval = inb(IO_PPI) | 0x03; - /* acquire the timers */ - if (acquire_timer2(TIMER_LSB|TIMER_ONESHOT)) - rv = -1; - else if (acquire_timer0(INTERRUPT_RATE, pcaintr)) { - release_timer2(); - rv = -1; - } else - pca_status.timer_on = 1; - - splx(x); - return rv; -} - - -static void -pca_stop(void) -{ - int x = splhigh(); - - /* release the timers */ - release_timer0(); - release_timer2(); - /* reset the buffer */ - pca_status.in_use[0] = pca_status.in_use[1] = pca_status.in_use[2] = 0; - pca_status.index = 0; - pca_status.counter = 0; - pca_status.current = 0; - pca_status.buffer = pca_status.buf[pca_status.current]; - pca_status.timer_on = 0; - splx(x); -} - - -static void -pca_pause(void) -{ - int x = splhigh(); - - release_timer0(); - release_timer2(); - pca_status.timer_on = 0; - splx(x); -} - - -static void -pca_continue(void) -{ - int x = splhigh(); - - pca_status.oldval = inb(IO_PPI) | 0x03; - acquire_timer2(TIMER_LSB|TIMER_ONESHOT); - acquire_timer0(INTERRUPT_RATE, pcaintr); - pca_status.timer_on = 1; - splx(x); -} - - -static int -pca_wait(void) -{ - int error, x; - - if (!pca_status.timer_on) - return 0; - - while (pca_status.in_use[0] || pca_status.in_use[1] || - pca_status.in_use[2]) { - x = spltty(); - pca_sleep = 1; - error = tsleep(&pca_sleep, PZERO|PCATCH, "pca_drain", 0); - pca_sleep = 0; - splx(x); - if (error != 0 && error != ERESTART) { - pca_stop(); - return error; - } - } - return 0; -} - - -static struct isa_pnp_id pca_ids[] = { - {0x0008d041, "AT-style speaker sound"}, /* PNP0800 */ - {0} -}; - -static int -pcaprobe(device_t dev) -{ - /* Check isapnp ids */ - return ISA_PNP_PROBE(device_get_parent(dev), dev, pca_ids); -} - - -static int -pcaattach(device_t dev) -{ - pca_init(); - make_dev(&pca_cdevsw, 0, 0, 0, 0600, "pcaudio"); - make_dev(&pca_cdevsw, 128, 0, 0, 0600, "pcaudioctl"); - return 0; -} - -static device_method_t pca_methods[] = { - DEVMETHOD(device_probe, pcaprobe), - DEVMETHOD(device_attach, pcaattach), - { 0, 0 } -}; - -static driver_t pca_driver = { - "pca", - pca_methods, - 1 -}; - -static devclass_t pca_devclass; - -DRIVER_MODULE(pca, isa, pca_driver, pca_devclass, 0, 0); - - -static int -pcaopen(dev_t dev, int flags, int fmt, struct thread *td) -{ - /* audioctl device can always be opened */ - if (minor(dev) == 128) - return 0; - if (minor(dev) > 0) - return ENXIO; - - /* audio device can only be open by one process */ - if (pca_status.open) { - pca_status.queries = 1; - return EBUSY; - } - pca_status.buffer = pca_status.buf[0]; - pca_status.in_use[0] = pca_status.in_use[1] = pca_status.in_use[2] = 0; - pca_status.timer_on = 0; - pca_status.open = 1; - pca_status.processed = 0; - return 0; -} - - -static int -pcaclose(dev_t dev, int flags, int fmt, struct thread *td) -{ - /* audioctl device can always be closed */ - if (minor(dev) == 128) - return 0; - if (minor(dev) > 0) - return ENXIO; - /* audio device close drains all output and restores timers */ - pca_wait(); - pca_stop(); - pca_status.open = 0; - return 0; -} - - -static int -pcawrite(dev_t dev, struct uio *uio, int flag) -{ - int count, error, which, x; - - /* only audio device can be written */ - if (minor(dev) > 0) - return ENXIO; - - while ((count = min(BUF_SIZE, uio->uio_resid)) > 0) { - if (pca_status.in_use[0] && pca_status.in_use[1] && - pca_status.in_use[2]) { - if (flag & IO_NDELAY) - return EWOULDBLOCK; - x = spltty(); - pca_sleep = 1; - error = tsleep(&pca_sleep, PZERO|PCATCH, "pca_wait", 0); - pca_sleep = 0; - splx(x); - if (error != 0 && error != ERESTART) { - pca_stop(); - return error; - } - } - if (!pca_status.in_use[0]) - which = 0; - else if (!pca_status.in_use[1]) - which = 1; - else - which = 2; - 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: - conv(ulaw_dsp, pca_status.buf[which], count); - break; - - case AUDIO_ENCODING_ALAW: - conv(alaw_linear, pca_status.buf[which], count); - break; - - case AUDIO_ENCODING_RAW: - break; - } - pca_status.in_use[which] = count; - if (!pca_status.timer_on) - if (pca_start()) - return EBUSY; - } - } - return 0; -} - - -static int -pcaioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td) -{ - audio_info_t *auptr; - - switch(cmd) { - - case AUDIO_GETINFO: - auptr = (audio_info_t *)data; - auptr->play.sample_rate = pca_status.sample_rate; - auptr->play.channels = 1; - auptr->play.precision = 8; - auptr->play.encoding = pca_status.encoding; - - 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.error = 0; - auptr->play.waiting = pca_status.queries; - - auptr->play.open = pca_status.open; - auptr->play.active = pca_status.timer_on; - return 0; - - case AUDIO_SETINFO: - auptr = (audio_info_t *)data; - if (auptr->play.sample_rate != (unsigned int)~0) { - pca_status.sample_rate = auptr->play.sample_rate; - pca_status.scale = - (pca_status.sample_rate << 8) / INTERRUPT_RATE; - } - if (auptr->play.encoding != (unsigned int)~0) { - pca_status.encoding = auptr->play.encoding; - } - if (auptr->play.gain != (unsigned int)~0) { - pca_status.volume = auptr->play.gain; - pca_volume(pca_status.volume); - } - if (auptr->play.pause != (unsigned char)~0) { - if (auptr->play.pause) - pca_pause(); - else - pca_continue(); - } - - return 0; - - case AUDIO_DRAIN: - case AUDIO_COMPAT_DRAIN: - return pca_wait(); - - case AUDIO_FLUSH: - case AUDIO_COMPAT_FLUSH: - pca_stop(); - return 0; - case FIONBIO: - return 0; - } - return ENXIO; -} - - -static void -pcaintr(struct clockframe *frame) -{ - if (pca_status.index < pca_status.in_use[pca_status.current]) { - disable_intr(); - __asm__("outb %0,$0x61\n" - "andb $0xFE,%0\n" - "outb %0,$0x61" - : : "a" ((char)pca_status.oldval) ); - __asm__("xlatb\n" - "outb %0,$0x42" - : : "a" ((char)pca_status.buffer[pca_status.index]), - "b" (volume_table) ); - enable_intr(); - pca_status.counter += pca_status.scale; - pca_status.index = (pca_status.counter >> 8); - } - 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++; - if (pca_status.current > 2) - pca_status.current = 0; - pca_status.buffer = pca_status.buf[pca_status.current]; - if (pca_sleep) - wakeup(&pca_sleep); - if (SEL_WAITING(&pca_status.wsel)) - selwakeup(&pca_status.wsel); - } -} - - -static int -pcapoll(dev_t dev, int events, struct thread *td) -{ - int s; - int revents = 0; - - s = spltty(); - - if (events & (POLLOUT | POLLWRNORM)) { - if (!pca_status.in_use[0] || !pca_status.in_use[1] || - !pca_status.in_use[2]) - revents |= events & (POLLOUT | POLLWRNORM); - else - selrecord(td, &pca_status.wsel); - } - splx(s); - return (revents); -} diff --git a/sys/pc98/conf/NOTES b/sys/pc98/conf/NOTES index 5a2dc3a..1f0eaad 100644 --- a/sys/pc98/conf/NOTES +++ b/sys/pc98/conf/NOTES @@ -473,15 +473,6 @@ hint.wl.0.port="0x300" options WLCACHE # enables the signal-strength cache options WLDEBUG # enables verbose debugging output -# -# Audio drivers: `pca' -# -# pca: PCM audio through your PC speaker - -device pca -hint.pca.0.at="isa" -hint.pca.0.port="0x040" - # # SCSI host adapters: # diff --git a/sys/pc98/pc98/pcaudio.c b/sys/pc98/pc98/pcaudio.c deleted file mode 100644 index 8bab0f3..0000000 --- a/sys/pc98/pc98/pcaudio.c +++ /dev/null @@ -1,604 +0,0 @@ -/*- - * Copyright (c) 1994-1998 Sen Schmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/conf.h> -#include <sys/proc.h> -#include <sys/kernel.h> -#include <sys/bus.h> -#include <sys/filio.h> -#include <sys/poll.h> -#include <sys/vnode.h> - -#include <machine/clock.h> -#include <machine/pcaudioio.h> - -#ifdef PC98 -#include <pc98/pc98/pc98.h> -#else -#include <isa/isareg.h> -#endif -#include <isa/isavar.h> -#include <i386/isa/timerreg.h> - -#define BUF_SIZE 8192 -#define SAMPLE_RATE 8000 -#define INTERRUPT_RATE 16000 - -static struct pca_status { - char open; /* device open */ - char queries; /* did others try opening */ - unsigned char *buf[3]; /* triple buffering */ - unsigned char *buffer; /* current buffer ptr */ - unsigned in_use[3]; /* buffers fill */ - unsigned index; /* index in current buffer */ - unsigned counter; /* sample counter */ - unsigned scale; /* sample counter scale */ - unsigned sample_rate; /* sample rate */ - unsigned processed; /* samples processed */ - unsigned volume; /* volume for pc-speaker */ - char encoding; /* Ulaw, Alaw or linear */ - u_char current; /* current buffer */ - unsigned char oldval; /* old timer port value */ - char timer_on; /* is playback running */ - struct selinfo wsel; /* select/poll status */ -} pca_status; - -static char buffer1[BUF_SIZE]; -static char buffer2[BUF_SIZE]; -static char buffer3[BUF_SIZE]; -static char volume_table[256]; - -static unsigned char ulaw_dsp[] = { - 3, 7, 11, 15, 19, 23, 27, 31, - 35, 39, 43, 47, 51, 55, 59, 63, - 66, 68, 70, 72, 74, 76, 78, 80, - 82, 84, 86, 88, 90, 92, 94, 96, - 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, - 113, 114, 114, 115, 115, 116, 116, 117, - 117, 118, 118, 119, 119, 120, 120, 121, - 121, 121, 122, 122, 122, 122, 123, 123, - 123, 123, 124, 124, 124, 124, 125, 125, - 125, 125, 125, 125, 126, 126, 126, 126, - 126, 126, 126, 126, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 253, 249, 245, 241, 237, 233, 229, 225, - 221, 217, 213, 209, 205, 201, 197, 193, - 190, 188, 186, 184, 182, 180, 178, 176, - 174, 172, 170, 168, 166, 164, 162, 160, - 158, 157, 156, 155, 154, 153, 152, 151, - 150, 149, 148, 147, 146, 145, 144, 143, - 143, 142, 142, 141, 141, 140, 140, 139, - 139, 138, 138, 137, 137, 136, 136, 135, - 135, 135, 134, 134, 134, 134, 133, 133, - 133, 133, 132, 132, 132, 132, 131, 131, - 131, 131, 131, 131, 130, 130, 130, 130, - 130, 130, 130, 130, 129, 129, 129, 129, - 129, 129, 129, 129, 129, 129, 129, 129, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, -}; - -static unsigned char alaw_linear[] = { - 45, 214, 122, 133, 0, 255, 107, 149, - 86, 171, 126, 129, 0, 255, 117, 138, - 13, 246, 120, 135, 0, 255, 99, 157, - 70, 187, 124, 131, 0, 255, 113, 142, - 61, 198, 123, 132, 0, 255, 111, 145, - 94, 163, 127, 128, 0, 255, 119, 136, - 29, 230, 121, 134, 0, 255, 103, 153, - 78, 179, 125, 130, 0, 255, 115, 140, - 37, 222, 122, 133, 0, 255, 105, 151, - 82, 175, 126, 129, 0, 255, 116, 139, - 5, 254, 120, 135, 0, 255, 97, 159, - 66, 191, 124, 131, 0, 255, 112, 143, - 53, 206, 123, 132, 0, 255, 109, 147, - 90, 167, 127, 128, 0, 255, 118, 137, - 21, 238, 121, 134, 0, 255, 101, 155, - 74, 183, 125, 130, 0, 255, 114, 141, - 49, 210, 123, 133, 0, 255, 108, 148, - 88, 169, 127, 129, 0, 255, 118, 138, - 17, 242, 121, 135, 0, 255, 100, 156, - 72, 185, 125, 131, 0, 255, 114, 142, - 64, 194, 124, 132, 0, 255, 112, 144, - 96, 161, 128, 128, 1, 255, 120, 136, - 33, 226, 122, 134, 0, 255, 104, 152, - 80, 177, 126, 130, 0, 255, 116, 140, - 41, 218, 122, 133, 0, 255, 106, 150, - 84, 173, 126, 129, 0, 255, 117, 139, - 9, 250, 120, 135, 0, 255, 98, 158, - 68, 189, 124, 131, 0, 255, 113, 143, - 57, 202, 123, 132, 0, 255, 110, 146, - 92, 165, 127, 128, 0, 255, 119, 137, - 25, 234, 121, 134, 0, 255, 102, 154, - 76, 181, 125, 130, 0, 255, 115, 141, -}; - -static int pca_sleep = 0; - -static void pcaintr(struct clockframe *frame); - -static d_open_t pcaopen; -static d_close_t pcaclose; -static d_write_t pcawrite; -static d_ioctl_t pcaioctl; -static d_poll_t pcapoll; - -#define CDEV_MAJOR 24 -static struct cdevsw pca_cdevsw = { - .d_open = pcaopen, - .d_close = pcaclose, - .d_write = pcawrite, - .d_ioctl = pcaioctl, - .d_poll = pcapoll, - .d_name = "pca", - .d_maj = CDEV_MAJOR, -}; - -static void pca_continue(void); -static void pca_init(void); -static void pca_pause(void); - -static void -conv(const unsigned char *table, unsigned char *buff, unsigned n) -{ - unsigned i; - - for (i = 0; i < n; i++) - buff[i] = table[buff[i]]; -} - - -static void -pca_volume(int volume) -{ - int i, j; - - for (i=0; i<256; i++) { - j = ((i-128)*volume)/25; -/* XXX - j = ((i-128)*volume)/100; -*/ - if (j<-128) - j = -128; - if (j>127) - j = 127; - volume_table[i] = (((255-(j + 128))/4)+1); - } -} - - -static void -pca_init(void) -{ - pca_status.open = 0; - pca_status.queries = 0; - pca_status.timer_on = 0; - pca_status.buf[0] = (unsigned char *)&buffer1[0]; - pca_status.buf[1] = (unsigned char *)&buffer2[0]; - pca_status.buf[2] = (unsigned char *)&buffer3[0]; - pca_status.buffer = pca_status.buf[0]; - pca_status.in_use[0] = pca_status.in_use[1] = pca_status.in_use[2] = 0; - pca_status.current = 0; - pca_status.sample_rate = SAMPLE_RATE; - pca_status.scale = (pca_status.sample_rate << 8) / INTERRUPT_RATE; - pca_status.encoding = AUDIO_ENCODING_ULAW; - pca_status.volume = 100; - - pca_volume(pca_status.volume); -} - - -static int -pca_start(void) -{ - int x = splhigh(); - int rv = 0; - - /* use the first buffer */ - pca_status.current = 0; - pca_status.index = 0; - pca_status.counter = 0; - pca_status.buffer = pca_status.buf[pca_status.current]; -#ifdef PC98 - pca_status.oldval = inb(IO_PPI) & ~0x08; -#else - pca_status.oldval = inb(IO_PPI) | 0x03; -#endif - /* acquire the timers */ -#ifdef PC98 - if (acquire_timer1(TIMER_LSB|TIMER_ONESHOT)) -#else - if (acquire_timer2(TIMER_LSB|TIMER_ONESHOT)) -#endif - rv = -1; - else if (acquire_timer0(INTERRUPT_RATE, pcaintr)) { -#ifdef PC98 - release_timer1(); -#else - release_timer2(); -#endif - rv = -1; - } else - pca_status.timer_on = 1; - - splx(x); - return rv; -} - - -static void -pca_stop(void) -{ - int x = splhigh(); - - /* release the timers */ - release_timer0(); -#ifdef PC98 - release_timer1(); -#else - release_timer2(); -#endif - /* reset the buffer */ - pca_status.in_use[0] = pca_status.in_use[1] = pca_status.in_use[2] = 0; - pca_status.index = 0; - pca_status.counter = 0; - pca_status.current = 0; - pca_status.buffer = pca_status.buf[pca_status.current]; - pca_status.timer_on = 0; - splx(x); -} - - -static void -pca_pause(void) -{ - int x = splhigh(); - - release_timer0(); -#ifdef PC98 - release_timer1(); -#else - release_timer2(); -#endif - pca_status.timer_on = 0; - splx(x); -} - - -static void -pca_continue(void) -{ - int x = splhigh(); - -#ifdef PC98 - pca_status.oldval = inb(IO_PPI) & ~0x08; - acquire_timer1(TIMER_LSB|TIMER_ONESHOT); -#else - pca_status.oldval = inb(IO_PPI) | 0x03; - acquire_timer2(TIMER_LSB|TIMER_ONESHOT); -#endif - acquire_timer0(INTERRUPT_RATE, pcaintr); - pca_status.timer_on = 1; - splx(x); -} - - -static int -pca_wait(void) -{ - int error, x; - - if (!pca_status.timer_on) - return 0; - - while (pca_status.in_use[0] || pca_status.in_use[1] || - pca_status.in_use[2]) { - x = spltty(); - pca_sleep = 1; - error = tsleep(&pca_sleep, PZERO|PCATCH, "pca_drain", 0); - pca_sleep = 0; - splx(x); - if (error != 0 && error != ERESTART) { - pca_stop(); - return error; - } - } - return 0; -} - - -static struct isa_pnp_id pca_ids[] = { - {0x0008d041, "AT-style speaker sound"}, /* PNP0800 */ - {0} -}; - -static int -pcaprobe(device_t dev) -{ - /* Check isapnp ids */ - return ISA_PNP_PROBE(device_get_parent(dev), dev, pca_ids); -} - - -static int -pcaattach(device_t dev) -{ - pca_init(); - make_dev(&pca_cdevsw, 0, 0, 0, 0600, "pcaudio"); - make_dev(&pca_cdevsw, 128, 0, 0, 0600, "pcaudioctl"); - return 0; -} - -static device_method_t pca_methods[] = { - DEVMETHOD(device_probe, pcaprobe), - DEVMETHOD(device_attach, pcaattach), - { 0, 0 } -}; - -static driver_t pca_driver = { - "pca", - pca_methods, - 1 -}; - -static devclass_t pca_devclass; - -DRIVER_MODULE(pca, isa, pca_driver, pca_devclass, 0, 0); - - -static int -pcaopen(dev_t dev, int flags, int fmt, struct thread *td) -{ - /* audioctl device can always be opened */ - if (minor(dev) == 128) - return 0; - if (minor(dev) > 0) - return ENXIO; - - /* audio device can only be open by one process */ - if (pca_status.open) { - pca_status.queries = 1; - return EBUSY; - } - pca_status.buffer = pca_status.buf[0]; - pca_status.in_use[0] = pca_status.in_use[1] = pca_status.in_use[2] = 0; - pca_status.timer_on = 0; - pca_status.open = 1; - pca_status.processed = 0; - return 0; -} - - -static int -pcaclose(dev_t dev, int flags, int fmt, struct thread *td) -{ - /* audioctl device can always be closed */ - if (minor(dev) == 128) - return 0; - if (minor(dev) > 0) - return ENXIO; - /* audio device close drains all output and restores timers */ - pca_wait(); - pca_stop(); - pca_status.open = 0; - return 0; -} - - -static int -pcawrite(dev_t dev, struct uio *uio, int flag) -{ - int count, error, which, x; - - /* only audio device can be written */ - if (minor(dev) > 0) - return ENXIO; - - while ((count = min(BUF_SIZE, uio->uio_resid)) > 0) { - if (pca_status.in_use[0] && pca_status.in_use[1] && - pca_status.in_use[2]) { - if (flag & IO_NDELAY) - return EWOULDBLOCK; - x = spltty(); - pca_sleep = 1; - error = tsleep(&pca_sleep, PZERO|PCATCH, "pca_wait", 0); - pca_sleep = 0; - splx(x); - if (error != 0 && error != ERESTART) { - pca_stop(); - return error; - } - } - if (!pca_status.in_use[0]) - which = 0; - else if (!pca_status.in_use[1]) - which = 1; - else - which = 2; - 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: - conv(ulaw_dsp, pca_status.buf[which], count); - break; - - case AUDIO_ENCODING_ALAW: - conv(alaw_linear, pca_status.buf[which], count); - break; - - case AUDIO_ENCODING_RAW: - break; - } - pca_status.in_use[which] = count; - if (!pca_status.timer_on) - if (pca_start()) - return EBUSY; - } - } - return 0; -} - - -static int -pcaioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td) -{ - audio_info_t *auptr; - - switch(cmd) { - - case AUDIO_GETINFO: - auptr = (audio_info_t *)data; - auptr->play.sample_rate = pca_status.sample_rate; - auptr->play.channels = 1; - auptr->play.precision = 8; - auptr->play.encoding = pca_status.encoding; - - 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.error = 0; - auptr->play.waiting = pca_status.queries; - - auptr->play.open = pca_status.open; - auptr->play.active = pca_status.timer_on; - return 0; - - case AUDIO_SETINFO: - auptr = (audio_info_t *)data; - if (auptr->play.sample_rate != (unsigned int)~0) { - pca_status.sample_rate = auptr->play.sample_rate; - pca_status.scale = - (pca_status.sample_rate << 8) / INTERRUPT_RATE; - } - if (auptr->play.encoding != (unsigned int)~0) { - pca_status.encoding = auptr->play.encoding; - } - if (auptr->play.gain != (unsigned int)~0) { - pca_status.volume = auptr->play.gain; - pca_volume(pca_status.volume); - } - if (auptr->play.pause != (unsigned char)~0) { - if (auptr->play.pause) - pca_pause(); - else - pca_continue(); - } - - return 0; - - case AUDIO_DRAIN: - case AUDIO_COMPAT_DRAIN: - return pca_wait(); - - case AUDIO_FLUSH: - case AUDIO_COMPAT_FLUSH: - pca_stop(); - return 0; - case FIONBIO: - return 0; - } - return ENXIO; -} - - -static void -pcaintr(struct clockframe *frame) -{ - if (pca_status.index < pca_status.in_use[pca_status.current]) { - disable_intr(); -#ifdef PC98 - __asm__("outb %0,$0x35\n" - "orb $0x08,%0\n" - "outb %0,$0x35" -#else - __asm__("outb %0,$0x61\n" - "andb $0xFE,%0\n" - "outb %0,$0x61" -#endif - : : "a" ((char)pca_status.oldval) ); - __asm__("xlatb\n" -#ifdef PC98 - "outb %0,%%dx" - : : "a" ((char)pca_status.buffer[pca_status.index]), - "b" (volume_table), - "d" ((u_short)0x3fdb) ); -#else - "outb %0,$0x42" - : : "a" ((char)pca_status.buffer[pca_status.index]), - "b" (volume_table) ); -#endif - enable_intr(); - pca_status.counter += pca_status.scale; - pca_status.index = (pca_status.counter >> 8); - } - 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++; - if (pca_status.current > 2) - pca_status.current = 0; - pca_status.buffer = pca_status.buf[pca_status.current]; - if (pca_sleep) - wakeup(&pca_sleep); - if (SEL_WAITING(&pca_status.wsel)) - selwakeup(&pca_status.wsel); - } -} - - -static int -pcapoll(dev_t dev, int events, struct thread *td) -{ - int s; - int revents = 0; - - s = spltty(); - - if (events & (POLLOUT | POLLWRNORM)) { - if (!pca_status.in_use[0] || !pca_status.in_use[1] || - !pca_status.in_use[2]) - revents |= events & (POLLOUT | POLLWRNORM); - else - selrecord(td, &pca_status.wsel); - } - splx(s); - return (revents); -} |