aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@cc.helsinki.fi>1994-01-21 13:59:51 +0000
committerNicolas Pitre <nico@cam.org>2007-08-19 14:19:28 -0400
commit5ba11befea43b83546e0cefa25f2551a7bd17e07 (patch)
tree42973c35cb5d9758404c146edfd210411cde3b9a
parentc5002faf69a59a022ae0d51a35e4836858fea1d0 (diff)
downloadarchive-5ba11befea43b83546e0cefa25f2551a7bd17e07.tar.gz
ALPHA-pl14t
-rw-r--r--Makefile2
-rw-r--r--config.in4
-rw-r--r--drivers/block/README.sbpcd0
-rw-r--r--drivers/block/hd.c8
-rw-r--r--drivers/block/sbpcd.c0
-rw-r--r--drivers/char/atixlmouse.c43
-rw-r--r--drivers/char/kbd_kern.h0
-rw-r--r--drivers/char/mem.c14
-rw-r--r--drivers/char/serial.c47
-rw-r--r--drivers/char/tty_io.c10
-rw-r--r--drivers/net/slip.c1
-rw-r--r--drivers/sound/.indent.pro5
-rw-r--r--drivers/sound/CHANGELOG12
-rw-r--r--drivers/sound/Makefile2
-rw-r--r--drivers/sound/Readme36
-rw-r--r--drivers/sound/Readme.linux46
-rw-r--r--drivers/sound/dev_table.h10
-rw-r--r--drivers/sound/dmabuf.c27
-rw-r--r--drivers/sound/gus_card.c4
-rw-r--r--drivers/sound/gus_vol.c43
-rw-r--r--drivers/sound/gus_wave.c1616
-rw-r--r--drivers/sound/sb16_dsp.c14
-rw-r--r--drivers/sound/sound_config.h2
-rw-r--r--drivers/sound/sound_switch.c12
-rw-r--r--drivers/sound/soundcard.c2
-rw-r--r--fs/open.c18
-rw-r--r--include/linux/if_ether.h1
-rw-r--r--include/linux/kernel_stat.h0
-rw-r--r--include/linux/sbpcd.h0
-rw-r--r--include/linux/sys.h1
-rw-r--r--include/linux/termios.h1
-rw-r--r--include/linux/tty.h9
-rw-r--r--include/linux/ultrasound.h3
-rw-r--r--include/linux/unistd.h1
-rw-r--r--kernel/sched.c2
-rw-r--r--kernel/signal.c3
-rw-r--r--kernel/sys.c2
-rw-r--r--kernel/traps.c2
-rw-r--r--mm/vmalloc.c21
-rw-r--r--net/inet/dev.c59
-rw-r--r--net/inet/ip.c2
-rw-r--r--net/inet/raw.c3
-rw-r--r--net/inet/sock.c8
-rw-r--r--net/inet/sock.h3
-rw-r--r--net/inet/tcp.c30
-rw-r--r--net/inet/tcp.h42
46 files changed, 1611 insertions, 560 deletions
diff --git a/Makefile b/Makefile
index 49dbefd..19d502e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 0.99
PATCHLEVEL = 14
-ALPHA = r
+ALPHA = t
all: Version zImage
diff --git a/config.in b/config.in
index 75a3812..1e7dc95 100644
--- a/config.in
+++ b/config.in
@@ -115,6 +115,10 @@ bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n
bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n
bool 'Selection (cut and paste for virtual consoles)' CONFIG_SELECTION y
bool 'QIC-02 tape support' CONFIG_TAPE_QIC02 n
+bool 'QIC-117 tape support' CONFIG_FTAPE n
+if [ "$CONFIG_FTAPE" = "y" ]
+int ' number of ftape buffers' NR_FTAPE_BUFFERS 3
+fi
*
* Sound
*
diff --git a/drivers/block/README.sbpcd b/drivers/block/README.sbpcd
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/drivers/block/README.sbpcd
diff --git a/drivers/block/hd.c b/drivers/block/hd.c
index 4391cc3..c26348f 100644
--- a/drivers/block/hd.c
+++ b/drivers/block/hd.c
@@ -227,8 +227,8 @@ static void reset_controller(void)
{
int i;
- printk("HD-controller reset\n");
- outb(4,HD_CMD);
+ printk(KERN_DEBUG "HD-controller reset\n");
+ outb_p(4,HD_CMD);
for(i = 0; i < 1000; i++) nop();
outb(hd_info[0].ctl & 0x0f ,HD_CMD);
if (drive_busy())
@@ -269,7 +269,7 @@ repeat:
void unexpected_hd_interrupt(void)
{
sti();
- printk("Unexpected HD interrupt\n");
+ printk(KERN_DEBUG "Unexpected HD interrupt\n");
SET_TIMER;
}
@@ -421,7 +421,7 @@ static void hd_times_out(void)
reset = 1;
if (!CURRENT)
return;
- printk("HD timeout\n");
+ printk(KERN_DEBUG "HD timeout\n");
cli();
if (++CURRENT->errors >= MAX_ERRORS) {
#ifdef DEBUG
diff --git a/drivers/block/sbpcd.c b/drivers/block/sbpcd.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/drivers/block/sbpcd.c
diff --git a/drivers/char/atixlmouse.c b/drivers/char/atixlmouse.c
index 350e557..9b9f114 100644
--- a/drivers/char/atixlmouse.c
+++ b/drivers/char/atixlmouse.c
@@ -4,6 +4,8 @@
*
* Uses VFS interface for linux 0.98 (01OCT92)
*
+ * Modified by Chris Colohan (colohan@eecg.toronto.edu)
+ *
* version 0.3
*/
@@ -52,8 +54,8 @@
/* Same general mouse structure */
static struct mouse_status {
- unsigned char buttons;
- unsigned char latch_buttons;
+ char buttons;
+ char latch_buttons;
int dx;
int dy;
int present;
@@ -64,16 +66,23 @@ static struct mouse_status {
void mouse_interrupt(int unused)
{
+ char dx, dy, buttons;
+
ATIXL_MSE_DISABLE_UPDATE(); /* Note that interrupts are still enabled */
outb(ATIXL_MSE_READ_X, ATIXL_MSE_CONTROL_PORT); /* Select IR1 - X movement */
- mouse.dx += inb( ATIXL_MSE_DATA_PORT);
+ dx = inb( ATIXL_MSE_DATA_PORT);
outb(ATIXL_MSE_READ_Y, ATIXL_MSE_CONTROL_PORT); /* Select IR2 - Y movement */
- mouse.dy += inb( ATIXL_MSE_DATA_PORT);
+ dy = inb( ATIXL_MSE_DATA_PORT);
outb(ATIXL_MSE_READ_BUTTONS, ATIXL_MSE_CONTROL_PORT); /* Select IR0 - Button Status */
- mouse.latch_buttons |= inb(ATIXL_MSE_DATA_PORT);
+ buttons = inb( ATIXL_MSE_DATA_PORT);
+ if (dx != 0 || dy != 0 || buttons != mouse.latch_buttons) {
+ mouse.latch_buttons |= buttons;
+ mouse.dx += dx;
+ mouse.dy += dy;
+ mouse.ready = 1;
+ wake_up_interruptible(&mouse.wait);
+ }
ATIXL_MSE_ENABLE_UPDATE();
- mouse.ready = 1;
- wake_up_interruptible(&mouse.wait);
}
static void release_mouse(struct inode * inode, struct file * file)
@@ -112,21 +121,33 @@ static int write_mouse(struct inode * inode, struct file * file, char * buffer,
static int read_mouse(struct inode * inode, struct file * file, char * buffer, int count)
{
+ int i;
+
if (count < 3)
return -EINVAL;
if (!mouse.ready)
return -EAGAIN;
ATIXL_MSE_DISABLE_UPDATE();
/* Allowed interrupts to occur during data gathering - shouldn't hurt */
- put_fs_byte((~mouse.latch_buttons & 7) | 0x80 , buffer);
- put_fs_byte(mouse.dx, buffer + 1);
- put_fs_byte(-mouse.dy, buffer + 2);
+ put_fs_byte((char)(~mouse.latch_buttons&7) | 0x80 , buffer);
+ if (mouse.dx < -127)
+ mouse.dx = -127;
+ if (mouse.dx > 127)
+ mouse.dx = 127;
+ put_fs_byte((char)mouse.dx, buffer + 1);
+ if (mouse.dy < -127)
+ mouse.dy = -127;
+ if (mouse.dy > 127)
+ mouse.dy = 127;
+ put_fs_byte((char)-mouse.dy, buffer + 2);
+ for(i = 3; i < count; i++)
+ put_fs_byte(0x00, buffer + i);
mouse.dx = 0;
mouse.dy = 0;
mouse.latch_buttons = mouse.buttons;
mouse.ready = 0;
ATIXL_MSE_ENABLE_UPDATE();
- return 3; /* 3 data bytes returned */
+ return i; /* i data bytes returned */
}
static int mouse_select(struct inode *inode, struct file *file, int sel_type, select_table * wait)
diff --git a/drivers/char/kbd_kern.h b/drivers/char/kbd_kern.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/drivers/char/kbd_kern.h
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 8a74b8f..7fa9dee 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -387,6 +387,10 @@ static struct file_operations memory_fops = {
NULL /* fsync */
};
+#ifdef CONFIG_FTAPE
+char* ftape_big_buffer;
+#endif
+
long chr_dev_init(long mem_start, long mem_end)
{
if (register_chrdev(MEM_MAJOR,"mem",&memory_fops))
@@ -406,5 +410,15 @@ long chr_dev_init(long mem_start, long mem_end)
#if CONFIG_TAPE_QIC02
mem_start = tape_qic02_init(mem_start);
#endif
+/*
+ * Rude way to allocate kernel memory buffer for tape device
+ */
+#ifdef CONFIG_FTAPE
+ /* allocate NR_FTAPE_BUFFERS 32Kb buffers at aligned address */
+ ftape_big_buffer= (char*) ((mem_start + 0x7fff) & ~0x7fff);
+ printk( "ftape: allocated %d buffers alligned at: %p\n",
+ NR_FTAPE_BUFFERS, ftape_big_buffer);
+ mem_start = (long) ftape_big_buffer + NR_FTAPE_BUFFERS * 0x8000;
+#endif
return mem_start;
}
diff --git a/drivers/char/serial.c b/drivers/char/serial.c
index c25c17b..ffb7f93 100644
--- a/drivers/char/serial.c
+++ b/drivers/char/serial.c
@@ -492,6 +492,7 @@ static void rs_interrupt(int irq)
pass_number = 0;
while (info) {
if (info->tty &&
+ info->tty->termios &&
(!pass_number ||
!(serial_inp(info, UART_IIR) & UART_IIR_NO_INT))) {
done = 0;
@@ -1489,7 +1490,24 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
#ifdef SERIAL_DEBUG_OPEN
printk("rs_close ttys%d, count = %d\n", info->line, info->count);
#endif
- if (--info->count > 0)
+ if ((tty->count == 1) && (info->count != 1)) {
+ /*
+ * Uh, oh. tty->count is 1, which means that the tty
+ * structure will be freed. Info->count should always
+ * be one in these conditions. If it's greater than
+ * one, we've got real problems, since it means the
+ * serial port won't be shutdown.
+ */
+ printk("rs_close: bad serial port count; tty->count is 1, "
+ "info->count is %d\n", info->count);
+ info->count = 1;
+ }
+ if (--info->count < 0) {
+ printk("rs_close: bad serial port count for ttys%d: %d\n",
+ info->line, info->count);
+ info->count = 0;
+ }
+ if (info->count)
return;
info->flags |= ASYNC_CLOSING;
/*
@@ -1502,8 +1520,16 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
info->callout_termios = *tty->termios;
tty->stopped = 0; /* Force flush to succeed */
tty->hw_stopped = 0;
- rs_start(tty);
- wait_until_sent(tty);
+ if (info->flags & ASYNC_INITIALIZED) {
+ rs_start(tty);
+ /*
+ * XXX There should be a timeout added to
+ * wait_until_sent, eventually. TYT 1/19/94
+ */
+ wait_until_sent(tty);
+ } else
+ flush_output(tty);
+ flush_input(tty);
cli();
/*
* Make sure the UART transmitter has completely drained; this
@@ -1517,7 +1543,6 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
shutdown(info, 1);
clear_bit(line, rs_event);
info->event = 0;
- info->count = 0;
info->tty = 0;
if (info->blocked_open) {
if (info->close_delay) {
@@ -1574,7 +1599,14 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
*/
if (info->flags & ASYNC_CLOSING) {
interruptible_sleep_on(&info->close_wait);
+#ifdef SERIAL_DO_RESTART
+ if (info->flags & ASYNC_HUP_NOTIFY)
+ return -EAGAIN;
+ else
+ return -ERESTARTSYS;
+#else
return -EAGAIN;
+#endif
}
/*
@@ -1632,7 +1664,14 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
current->state = TASK_INTERRUPTIBLE;
if (tty_hung_up_p(filp) ||
!(info->flags & ASYNC_INITIALIZED)) {
+#ifdef SERIAL_DO_RESTART
+ if (info->flags & ASYNC_HUP_NOTIFY)
+ retval = -EAGAIN;
+ else
+ retval = -ERESTARTSYS;
+#else
retval = -EAGAIN;
+#endif
break;
}
if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 77fb28a..c07c194 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -1430,6 +1430,15 @@ static int tty_select(struct inode * inode, struct file * filp, int sel_type, se
printk("tty_select: tty struct for dev %d was NULL\n", dev);
return 0;
}
+ if (ldiscs[tty->disc].select)
+ return (ldiscs[tty->disc].select)(tty, inode, filp,
+ sel_type, wait);
+ return 0;
+}
+
+static int normal_select(struct tty_struct * tty, struct inode * inode,
+ struct file * file, int sel_type, select_table *wait)
+{
switch (sel_type) {
case SEL_IN:
if (L_CANON(tty)) {
@@ -1681,6 +1690,7 @@ static struct tty_ldisc tty_ldisc_N_TTY = {
read_chan, /* read */
write_chan, /* write */
NULL, /* ioctl */
+ normal_select, /* select */
copy_to_cooked /* handler */
};
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 2753824..2f3ea0d 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -1200,6 +1200,7 @@ slip_init(struct device *dev)
sl_ldisc.write = NULL;
sl_ldisc.ioctl = (int (*)(struct tty_struct *, struct file *,
unsigned int, unsigned long)) slip_ioctl;
+ sl_ldisc.select = NULL;
sl_ldisc.handler = slip_recv;
if ((i = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0)
printk("ERROR: %d\n", i);
diff --git a/drivers/sound/.indent.pro b/drivers/sound/.indent.pro
index f10c3dd..4668655 100644
--- a/drivers/sound/.indent.pro
+++ b/drivers/sound/.indent.pro
@@ -1,9 +1,6 @@
-bad
-bap
--fca
--fc1
--cdb
--sc
+-nfca
-bl
-psl
-di16
diff --git a/drivers/sound/CHANGELOG b/drivers/sound/CHANGELOG
index 6839b1e..78168dd 100644
--- a/drivers/sound/CHANGELOG
+++ b/drivers/sound/CHANGELOG
@@ -1,6 +1,16 @@
-Changelog for version 2.3
+Changelog for version 2.4
-------------------------
+Since 2.3b
+- Fixed bug which made it impossible to make long recordings to disk.
+ Recording was not restarted after a buffer overflow situation.
+- Limited mixer support for GUS.
+- Numerous improvements to the GUS driver by Andrew Robinson. Including
+ some click removal etc.
+
+Since 2.3
+- Fixed some minor bugs in the SB16 driver.
+
Since 2.2b
- Full SB16 DSP support. 8/16 bit, mono/stereo
- The SCO and FreeBSD versions should be in sync now. There are some
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
index d8518d7..dcf00d5 100644
--- a/drivers/sound/Makefile
+++ b/drivers/sound/Makefile
@@ -5,7 +5,7 @@
#
#
-VERSION = 2.3b
+VERSION = 2.4
TARGET_OS = linux
.c.s:
diff --git a/drivers/sound/Readme b/drivers/sound/Readme
index 452733f..bd47ede 100644
--- a/drivers/sound/Readme
+++ b/drivers/sound/Readme
@@ -1,32 +1,30 @@
-Release notes for the Linux Sound Driver 2.3
------------------------------------------------
-
-This version has finally the SB16 support. It seems to work
-well but there is some problems with recording. If the recording
-process cannot read the data from the device fast enough the
-driver will return EIO. Usually this happens when there is no more
-memory for the disk buffers.
-The SB16 DSP support is by Joerg Schubert (jsb@sth.ruhr-uni-bochum.de).
-Currently the SB16 support is an ALPHA test version since it has been
-tested just by me.
+Release notes for the Linux Sound Driver 2.4
+--------------------------------------------
+
+NOTE! The sound driver is a part of the Linux kernel distribution also.
+ Check that your kernel doesn't have more recent version than this
+ when installing a separately distributed sound driver. The
+ version number of this driver is defined in the makefile.
+This version contains a driver for the SB16 also.
The SB16 driver requires separate DMA channels for the 8 and 16 bit
modes. There should be a way to share the 8 bit DMA channels between
these modes but this feature is not supported yet.
+The SB16 DSP support is by Joerg Schubert (jsb@sth.ruhr-uni-bochum.de).
The SB16 driver has also the Midi input capability even at the same
time with the /dev/dsp. Also the WaveBlaster daughter board is supported.
No support for the ASP chip yet (the ASP chip can be installed but it's
not used by the driver).
-You will need the snd-util-2.0.tar.gz and snd-data-0.1.tar.Z
+You will need the snd-util-2.4.tar.gz and snd-data-0.1.tar.Z
packages to use this driver. They should be in the same
ftp site or BBS from where you got this driver. For
example at nic.funet.fi:pub/OS/Linux/*.
-There is a new version of the tracker program available (tracker-3.19) but
-I don't know how to find it. The tracker 3.10 has bugs and it don't work
-without some fixes. Look at the README of the snd-util-2.0.
+There is a new version of the tracker program available (tracker-3_19.lzh) but
+I don't know where it is available. The tracker 3.10 has bugs and it don't work
+without some fixes. Look at the README of the snd-util-2.3.
If you are looking for the installation instructions, please
look at linux/Readme.
@@ -161,7 +159,12 @@ Mixer(s) installed
Known bugs/limitations
----------------------
-- Midi input doesn't work with SB and SB Pro (SB16 works somehow).
+- High speed recording of long audio samples (>20 second) to disk
+ is not possible. Everything works until next sync() which delays the
+ recording process too much. A delay longer than 0.1 to 0.3 seconds is
+ too much.
+- The SB16 driver sometimes swaps the left and right channels together.
+- Midi input doesn't work with SB and SB Pro (SB16 works).
- It's not possible to open /dev/dsp (or /dev/audio) while the
/dev/sequencer is open for output and GUS is the only soundcard
installed. It's possible if /dev/dsp is opened before /dev/sequencer
@@ -226,6 +229,7 @@ contributors. (I could have forgotten some names.)
Jim Lowe FreeBSD port
Anders Baekgaard Bughunting and valuable suggestions.
Joerg Schubert SB16 DSP support.
+ Andrew Robinson Improvements to the GUS driver
Regards,
diff --git a/drivers/sound/Readme.linux b/drivers/sound/Readme.linux
index 0bf8d92..d585f59 100644
--- a/drivers/sound/Readme.linux
+++ b/drivers/sound/Readme.linux
@@ -1,18 +1,10 @@
-Sound Card Driver version 2.2
+Sound Driver version 2.4 for Linux
+----------------------------------
-This directory contains the driver for various PC soundcards.
-The following cards are supported:
-
-AdLib
-SoundBlaster (1.0-2.0) and compatibles, including
- ThunderBoard and Ati Stereo F/X.
-SoundBlaster Pro and SB Pro 2
-SoundBlaster 16
-ProAudioSpectrum 16
- (The original ProAudioSpectrum and the PAS+ are not supported
- (and propably will remain unsupported)).
-
-If you have any problems, please contact me.
+NOTE! The sound driver is now a part of the Linux kernel distribution.
+ Check that your kernel doesn't have more recent version than this
+ when installing a separately distributed sound driver. The
+ version number of this driver is defined in the makefile.
Installation
------------
@@ -20,14 +12,23 @@ Installation
- Since this driver is a part of the Linux kernel distribution, no
special steps are required to build the driver itself.
-- To build the device files you need to run the enclosed shell scrip
- (see below).
+- In case you are installing a separately distributed sound driver,
+ you have to do some additional steps.
+ - Remove all files from the linux/drivers/sound. Old files could
+ sometimes cause trouble.
+ - cd linux/drivers.
+ - gunzip -c snd-driv-X.Y.tar.gz|tar xvf -
+ - cd ./sound
+ - cp soundcard.h ultrasound.h /usr/include/linux
+
+- To build the device files for this driver, you need to run the enclosed
+ shell script (at the end of this file).
-- Copy the sound/ultrasound.h to /usr/include/sys
- (Remove the old one from /usr/include/sys /usr/include/linux first).
+- Create /usr/include/sys/soundcard.h whic contains just a line:
+#include <linux/soundcard.h>
-- Ensure you have the following symlink:
- ln -s /usr/include/linux/soundcard.h /usr/include/sys/soundcard.h
+- Create /usr/include/sys/ultrasound.h whic contains just a line:
+#include <linux/ultrasound.h>
Boot time configuration (using lilo)
------------------------------------
@@ -190,6 +191,11 @@ if [ -e /dev/mixer ]; then
rm -f /dev/mixer
fi
mknod -m 666 /dev/mixer c 14 0
+
+if [ -e /dev/mixer1 ]; then
+ rm -f /dev/mixer1
+fi
+mknod -m 666 /dev/mixer1 c 14 16
#
# Sequencer (14, 1)
#
diff --git a/drivers/sound/dev_table.h b/drivers/sound/dev_table.h
index d95137b..d917a46 100644
--- a/drivers/sound/dev_table.h
+++ b/drivers/sound/dev_table.h
@@ -167,11 +167,6 @@ struct generic_midi_operations {
{MPU_BASE, MPU_IRQ, 0}, SND_DEFAULT_ENABLE},
#endif
-#ifndef EXCLUDE_GUS
- {SNDCARD_GUS, "Gravis Ultrasound", attach_gus_card, probe_gus,
- {GUS_BASE, GUS_IRQ, GUS_DMA}, SND_DEFAULT_ENABLE},
-#endif
-
#ifndef EXCLUDE_PAS
{SNDCARD_PAS, "ProAudioSpectrum", attach_pas_card, probe_pas,
{PAS_BASE, PAS_IRQ, PAS_DMA}, SND_DEFAULT_ENABLE},
@@ -193,6 +188,11 @@ struct generic_midi_operations {
#endif
#endif
+#ifndef EXCLUDE_GUS
+ {SNDCARD_GUS, "Gravis Ultrasound", attach_gus_card, probe_gus,
+ {GUS_BASE, GUS_IRQ, GUS_DMA}, SND_DEFAULT_ENABLE},
+#endif
+
#ifndef EXCLUDE_YM3812
{SNDCARD_ADLIB, "AdLib", attach_adlib_card, probe_adlib,
{FM_MONO, 0, 0}, SND_DEFAULT_ENABLE},
diff --git a/drivers/sound/dmabuf.c b/drivers/sound/dmabuf.c
index 82f427a..b3a6ae2 100644
--- a/drivers/sound/dmabuf.c
+++ b/drivers/sound/dmabuf.c
@@ -323,6 +323,15 @@ DMAbuf_getrdbuffer (int dev, char **buf, int *len)
unsigned long flags;
int err = EIO;
+ DISABLE_INTR (flags);
+ if (!dev_qlen[dev])
+ {
+ if (dev_needs_restart[dev])
+ {
+ dma_reset(dev);
+ dev_needs_restart[dev] = 0;
+ }
+
if (dma_mode[dev] == DMODE_OUTPUT) /* Was output -> direction change */
{
dma_sync(dev);
@@ -339,19 +348,13 @@ DMAbuf_getrdbuffer (int dev, char **buf, int *len)
if ((err = dsp_devs[dev]->prepare_for_input (dev,
dev_buffsize[dev], dev_nbufs[dev])) < 0)
- return err;
+ {
+ RESTORE_INTR (flags);
+ return err;
+ }
dma_mode[dev] = DMODE_INPUT;
}
- DISABLE_INTR (flags);
- if (!dev_qlen[dev])
- {
- if (dev_needs_restart[dev])
- {
- dma_reset(dev);
- dev_needs_restart[dev] = 0;
- }
-
if (!dev_active[dev])
{
dsp_devs[dev]->start_input (dev, dev_buf_phys[dev][dev_qtail[dev]],
@@ -366,7 +369,7 @@ DMAbuf_getrdbuffer (int dev, char **buf, int *len)
DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 2 * HZ);
if (TIMED_OUT (dev_sleeper[dev], dev_sleep_flag[dev]))
{
- printk ("Sound: DMA timed out\n");
+ printk ("Sound: DMA timed out - IRQ/DRQ config error?\n");
err = EIO;
SET_ABORT_FLAG (dev_sleeper[dev], dev_sleep_flag[dev]);
}
@@ -531,7 +534,7 @@ DMAbuf_getwrbuffer (int dev, char **buf, int *size)
DO_SLEEP (dev_sleeper[dev], dev_sleep_flag[dev], 2 * HZ);
if (TIMED_OUT (dev_sleeper[dev], dev_sleep_flag[dev]))
{
- printk ("Sound: DMA timed out\n");
+ printk ("Sound: DMA timed out - IRQ/DRQ config error?\n");
err = EIO;
SET_ABORT_FLAG (dev_sleeper[dev], dev_sleep_flag[dev]);
}
diff --git a/drivers/sound/gus_card.c b/drivers/sound/gus_card.c
index e7967e8..d031a45 100644
--- a/drivers/sound/gus_card.c
+++ b/drivers/sound/gus_card.c
@@ -105,6 +105,10 @@ gusintr (int unit)
{
unsigned char src;
+#ifdef linux
+ sti();
+#endif
+
while (1)
{
if (!(src = INB (u_IrqStatus)))
diff --git a/drivers/sound/gus_vol.c b/drivers/sound/gus_vol.c
index b3f1e84..ea3ece3 100644
--- a/drivers/sound/gus_vol.c
+++ b/drivers/sound/gus_vol.c
@@ -1,4 +1,4 @@
-/*
+/*
* gus_vol.c - Compute volume for GUS.
*
* Greg Lee 1993.
@@ -11,7 +11,7 @@
extern int gus_wave_volume;
-/*
+/*
* Calculate gus volume from note velocity, main volume, expression, and
* intrinsic patch volume given in patch library. Expression is multiplied
* in, so it emphasizes differences in note velocity, while main volume is
@@ -31,35 +31,48 @@ gus_adagio_vol (int vel, int mainv, int xpn, int voicev)
int i, m, n, x;
- /*
+ /*
* A voice volume of 64 is considered neutral, so adjust the main volume if
* something other than this neutral value was assigned in the patch
* library.
*/
x = 256 + 6 * (voicev - 64);
- /* Boost expression by voice volume above neutral. */
+ /*
+ * Boost expression by voice volume above neutral.
+ */
if (voicev > 65)
xpn += voicev - 64;
xpn += (voicev - 64) / 2;
- /* Combine multiplicative and level components. */
+ /*
+ * Combine multiplicative and level components.
+ */
x = vel * xpn * 6 + (voicev / 4) * x;
#ifdef GUS_VOLUME
- /*
+ /*
* Further adjustment by installation-specific master volume control
- * (default 50).
+ * (default 60).
*/
x = (x * GUS_VOLUME * GUS_VOLUME) / 10000;
#endif
- if (x < (1 << 11))
- return (11 << 8);
+#ifdef GUS_USE_CHN_MAIN_VOLUME
+ /*
+ * Experimental support for the channel main volume
+ */
+
+ mainv = (mainv / 2) + 64; /* Scale to 64 to 127 */
+ x = (x * mainv * mainv) / 16384;
+#endif
+
+ if (x < 2)
+ return (0);
else if (x >= 65535)
return ((15 << 8) | 255);
- /*
+ /*
* Convert to gus's logarithmic form with 4 bit exponent i and 8 bit
* mantissa m.
*/
@@ -76,13 +89,15 @@ gus_adagio_vol (int vel, int mainv, int xpn, int voicev)
n >>= 1;
i++;
}
- /*
+ /*
* Mantissa is part of linear volume not expressed in exponent. (This is
* not quite like real logs -- I wonder if it's right.)
*/
m = x - (1 << i);
- /* Adjust mantissa to 8 bits. */
+ /*
+ * Adjust mantissa to 8 bits.
+ */
if (m > 0)
{
if (i > 8)
@@ -91,10 +106,6 @@ gus_adagio_vol (int vel, int mainv, int xpn, int voicev)
m <<= 8 - i;
}
- /* low volumes give occasional sour notes */
- if (i < 11)
- return (11 << 8);
-
return ((i << 8) + m);
}
diff --git a/drivers/sound/gus_wave.c b/drivers/sound/gus_wave.c
index 51186d3..aea174d 100644
--- a/drivers/sound/gus_wave.c
+++ b/drivers/sound/gus_wave.c
@@ -1,4 +1,5 @@
-/*
+
+/*
* sound/gus_wave.c
*
* Driver for the Gravis UltraSound wave table synth.
@@ -27,8 +28,6 @@
*
*/
-/* #define GUS_LINEAR_VOLUME */
-
#include "sound_config.h"
#include <linux/ultrasound.h>
#include "gus_hw.h"
@@ -56,16 +55,22 @@ struct voice_info
int volume_irq_mode, volume_irq_parm;
#define VMODE_HALT 1
#define VMODE_ENVELOPE 2
+#define VMODE_START_NOTE 3
int env_phase;
unsigned char env_rate[6];
unsigned char env_offset[6];
- /*
+ /*
* Volume computation parameters for gus_adagio_vol()
*/
int main_vol, expression_vol, patch_vol;
+ /* Variables for "Ultraclick" removal */
+ int dev_pending, note_pending, volume_pending, sample_pending;
+ char kill_pending;
+ long offset_pending;
+
};
extern int gus_base;
@@ -76,24 +81,31 @@ extern int snd_raw_count[MAX_DSP_DEV];
static long gus_mem_size = 0;
static long free_mem_ptr = 0;
static int gus_busy = 0;
-static int nr_voices = 0; /* Number of currently allowed voices */
+static int nr_voices = 0;
static int gus_devnum = 0;
static int volume_base, volume_scale, volume_method;
+static int gus_line_vol = 100, gus_mic_vol = 0;
+static int gus_recmask = SOUND_MASK_MIC;
+static int recording_active = 0;
#define VOL_METHOD_ADAGIO 1
-int gus_wave_volume = 60; /* Master wolume for wave (0 to 100) */
+int gus_wave_volume = 60;
+int gus_pcm_volume = 80;
static unsigned char mix_image = 0x00;
-/*
- * Current version of this_one driver doesn't allow synth and PCM functions
+/*
+ * Current version of this driver doesn't allow synth and PCM functions
* at the same time. The active_device specifies the active driver
*/
static int active_device = 0;
-#define GUS_DEV_WAVE 1 /* Wave table synth */
-#define GUS_DEV_PCM_DONE 2 /* PCM device, transfer done */
-#define GUS_DEV_PCM_CONTINUE 3 /* PCM device, transfer the second
- * chn */
+#define GUS_DEV_WAVE 1 /*
+ * * * Wave table synth */
+#define GUS_DEV_PCM_DONE 2 /*
+ * * * PCM device, transfer done */
+#define GUS_DEV_PCM_CONTINUE 3 /*
+ * * * PCM device, transfer the
+ * second * * * chn */
static int gus_sampling_speed;
static int gus_sampling_channels;
@@ -101,17 +113,37 @@ static int gus_sampling_bits;
DEFINE_WAIT_QUEUE (dram_sleeper, dram_sleep_flag);
-/*
+/*
* Variables and buffers for PCM output
*/
-#define MAX_PCM_BUFFERS (32*MAX_REALTIME_FACTOR) /* Don't change */
-
-static int pcm_bsize, /* Current blocksize */
- pcm_nblk, /* Current # of blocks */
- pcm_banksize; /* # bytes allocated for channels */
-static int pcm_datasize[MAX_PCM_BUFFERS]; /* Actual # of bytes in blk */
-static volatile int pcm_head, pcm_tail, pcm_qlen; /* DRAM queue */
+#define MAX_PCM_BUFFERS (32*MAX_REALTIME_FACTOR) /*
+ * * * Don't
+ * * * change
+ *
+ */
+
+static int pcm_bsize, /*
+ * Current blocksize
+ */
+ pcm_nblk, /*
+ * Current # of blocks
+ */
+ pcm_banksize; /*
+
+ *
+ * * * * # bytes allocated for channels */
+static int pcm_datasize[MAX_PCM_BUFFERS]; /*
+
+ *
+ * * * * Actual # of bytes
+ * in blk * */
+static volatile int pcm_head, pcm_tail, pcm_qlen; /*
+
+ *
+ * * * * DRAM queue
+ * */
static volatile int pcm_active;
+static int pcm_opened = 0;
static int pcm_current_dev;
static int pcm_current_block;
static unsigned long pcm_current_buf;
@@ -122,28 +154,66 @@ struct voice_info voices[32];
static int freq_div_table[] =
{
- 44100, /* 14 */
- 41160, /* 15 */
- 38587, /* 16 */
- 36317, /* 17 */
- 34300, /* 18 */
- 32494, /* 19 */
- 30870, /* 20 */
- 29400, /* 21 */
- 28063, /* 22 */
- 26843, /* 23 */
- 25725, /* 24 */
- 24696, /* 25 */
- 23746, /* 26 */
- 22866, /* 27 */
- 22050, /* 28 */
- 21289, /* 29 */
- 20580, /* 30 */
- 19916, /* 31 */
- 19293 /* 32 */
+ 44100, /*
+ * 14
+ */
+ 41160, /*
+ * 15
+ */
+ 38587, /*
+ * 16
+ */
+ 36317, /*
+ * 17
+ */
+ 34300, /*
+ * 18
+ */
+ 32494, /*
+ * 19
+ */
+ 30870, /*
+ * 20
+ */
+ 29400, /*
+ * 21
+ */
+ 28063, /*
+ * 22
+ */
+ 26843, /*
+ * 23
+ */
+ 25725, /*
+ * 24
+ */
+ 24696, /*
+ * 25
+ */
+ 23746, /*
+ * 26
+ */
+ 22866, /*
+ * 27
+ */
+ 22050, /*
+ * 28
+ */
+ 21289, /*
+ * 29
+ */
+ 20580, /*
+ * 30
+ */
+ 19916, /*
+ * 31
+ */
+ 19293 /*
+ * 32
+ */
};
-static struct patch_info *samples;
+static struct patch_info *samples;
static long sample_ptrs[MAX_SAMPLE + 1];
static int sample_map[32];
static int free_sample;
@@ -159,9 +229,13 @@ static void gus_poke (long addr, unsigned char data);
static void compute_and_set_volume (int voice, int volume, int ramp_time);
extern unsigned short gus_adagio_vol (int vel, int mainv, int xpn, int voicev);
static void compute_volume (int voice, int volume);
+static void do_volume_irq (int voice);
+static void set_input_volumes(void);
-#define INSTANT_RAMP -1 /* Dont use ramping */
-#define FAST_RAMP 0 /* Fastest possible ramp */
+#define INSTANT_RAMP -1 /*
+ * * * Dont use ramping */
+#define FAST_RAMP 0 /*
+ * * * Fastest possible ramp */
static void
reset_sample_memory (void)
@@ -175,7 +249,9 @@ reset_sample_memory (void)
for (i = 0; i < 32; i++)
patch_map[i] = -1;
- gus_poke (0, 0); /* Put silence here */
+ gus_poke (0, 0); /*
+ * Put silence here
+ */
gus_poke (1, 0);
free_mem_ptr = 2;
@@ -237,7 +313,7 @@ gus_write8 (int reg, unsigned int data)
DISABLE_INTR (flags);
OUTB (reg, u_Command);
- OUTB ((unsigned char)(data & 0xff), u_DataHi);
+ OUTB ((unsigned char) (data & 0xff), u_DataHi);
RESTORE_INTR (flags);
}
@@ -279,8 +355,8 @@ gus_write16 (int reg, unsigned int data)
OUTB (reg, u_Command);
- OUTB ((unsigned char)(data & 0xff), u_DataLo);
- OUTB ((unsigned char)((data >> 8) & 0xff), u_DataHi);
+ OUTB ((unsigned char) (data & 0xff), u_DataLo);
+ OUTB ((unsigned char) ((data >> 8) & 0xff), u_DataHi);
RESTORE_INTR (flags);
}
@@ -310,7 +386,7 @@ gus_write_addr (int reg, unsigned long address, int is16bit)
if (is16bit)
{
- /*
+ /*
* Special processing required for 16 bit patches
*/
@@ -349,9 +425,9 @@ gus_select_max_voices (int nvoices)
static void
gus_voice_on (unsigned int mode)
{
- gus_write8 (0x00, (unsigned char)(mode & 0xfc));
+ gus_write8 (0x00, (unsigned char) (mode & 0xfc));
gus_delay ();
- gus_write8 (0x00, (unsigned char)(mode & 0xfc));
+ gus_write8 (0x00, (unsigned char) (mode & 0xfc));
}
static void
@@ -363,9 +439,16 @@ gus_voice_off (void)
static void
gus_voice_mode (unsigned int m)
{
- unsigned char mode = (unsigned char)(m & 0xff);
- gus_write8 (0x00, (gus_read8 (0x00) & 0x03) | (mode & 0xfc)); /* Don't start or stop
- * voice */
+ unsigned char mode = (unsigned char) (m & 0xff);
+
+ gus_write8 (0x00, (gus_read8 (0x00) & 0x03) | (mode & 0xfc)); /*
+ * Don't
+ * start
+ * or
+ * stop
+ * *
+ * voice
+ */
gus_delay ();
gus_write8 (0x00, (gus_read8 (0x00) & 0x03) | (mode & 0xfc));
}
@@ -385,33 +468,35 @@ gus_voice_freq (unsigned long freq)
static void
gus_voice_volume (unsigned int vol)
{
- gus_write8 (0x0d, 0x03); /* Stop ramp before setting volume */
- gus_write16 (0x09, (unsigned short)(vol << 4));
+ gus_write8 (0x0d, 0x03); /*
+ * Stop ramp before setting volume
+ */
+ gus_write16 (0x09, (unsigned short) (vol << 4));
}
static void
gus_voice_balance (unsigned int balance)
{
- gus_write8 (0x0c, (unsigned char)(balance & 0xff));
+ gus_write8 (0x0c, (unsigned char) (balance & 0xff));
}
static void
gus_ramp_range (unsigned int low, unsigned int high)
{
- gus_write8 (0x07, (unsigned char)((low >> 4) & 0xff));
- gus_write8 (0x08, (unsigned char)((high >> 4) & 0xff));
+ gus_write8 (0x07, (unsigned char) ((low >> 4) & 0xff));
+ gus_write8 (0x08, (unsigned char) ((high >> 4) & 0xff));
}
static void
gus_ramp_rate (unsigned int scale, unsigned int rate)
{
- gus_write8 (0x06, (unsigned char)(((scale & 0x03) << 6) | (rate & 0x3f)));
+ gus_write8 (0x06, (unsigned char) (((scale & 0x03) << 6) | (rate & 0x3f)));
}
static void
gus_rampon (unsigned int m)
{
- unsigned char mode = (unsigned char)(m & 0xff);
+ unsigned char mode = (unsigned char) (m & 0xff);
gus_write8 (0x0d, mode & 0xfc);
gus_delay ();
@@ -421,10 +506,16 @@ gus_rampon (unsigned int m)
static void
gus_ramp_mode (unsigned int m)
{
- unsigned char mode = (unsigned char)(m & 0xff);
+ unsigned char mode = (unsigned char) (m & 0xff);
- gus_write8 (0x0d, (gus_read8 (0x0d) & 0x03) | (mode & 0xfc)); /* Don't start or stop
- * ramping */
+ gus_write8 (0x0d, (gus_read8 (0x0d) & 0x03) | (mode & 0xfc)); /*
+ * Don't
+ * start
+ * or
+ * stop
+ * *
+ * ramping
+ */
gus_delay ();
gus_write8 (0x0d, (gus_read8 (0x0d) & 0x03) | (mode & 0xfc));
}
@@ -436,6 +527,20 @@ gus_rampoff (void)
}
static void
+gus_set_voice_pos (int voice, long position)
+{
+ int sample_no;
+
+ if ((sample_no = sample_map[voice]) != -1)
+ if (position < samples[sample_no].len)
+ if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
+ voices[voice].offset_pending = position;
+ else
+ gus_write_addr (0x0a, sample_ptrs[sample_no] + position,
+ samples[sample_no].mode & WAVE_16_BITS);
+}
+
+static void
gus_voice_init (int voice)
{
unsigned long flags;
@@ -443,11 +548,22 @@ gus_voice_init (int voice)
DISABLE_INTR (flags);
gus_select_voice (voice);
gus_voice_volume (0);
- gus_write_addr (0x0a, 0, 0); /* Set current position to 0 */
- gus_write8 (0x00, 0x03); /* Voice off */
- gus_write8 (0x0d, 0x03); /* Ramping off */
+ gus_write_addr (0x0a, 0, 0); /*
+ * Set current position to 0
+ */
+ gus_write8 (0x00, 0x03); /*
+ * Voice off
+ */
+ gus_write8 (0x0d, 0x03); /*
+ * Ramping off
+ */
RESTORE_INTR (flags);
+}
+
+static void
+gus_voice_init2 (int voice)
+{
voices[voice].panning = 0;
voices[voice].mode = 0;
voices[voice].orig_freq = 20000;
@@ -464,6 +580,7 @@ gus_voice_init (int voice)
voices[voice].main_vol = 127;
voices[voice].patch_vol = 127;
voices[voice].expression_vol = 127;
+ voices[voice].sample_pending = -1;
}
static void
@@ -475,12 +592,14 @@ step_envelope (int voice)
if (voices[voice].mode & WAVE_SUSTAIN_ON && voices[voice].env_phase == 2)
{
gus_rampoff ();
- return; /* Sustain */
+ return; /*
+ * Sustain
+ */
}
if (voices[voice].env_phase >= 5)
{
- /*
+ /*
* Shoot the voice off
*/
@@ -496,13 +615,19 @@ step_envelope (int voice)
vol = voices[voice].initial_volume * voices[voice].env_offset[phase] / 255;
rate = voices[voice].env_rate[phase];
- gus_write8 (0x06, rate); /* Ramping rate */
+ gus_write8 (0x06, rate); /*
+ * Ramping rate
+ */
voices[voice].volume_irq_mode = VMODE_ENVELOPE;
- if (((vol - prev_vol) / 64) == 0) /* No significant volume change */
+ if (((vol - prev_vol) / 64) == 0) /*
+ * No significant volume change
+ */
{
- step_envelope (voice); /* Continue with the next phase */
+ step_envelope (voice); /*
+ * Continue with the next phase
+ */
return;
}
@@ -511,14 +636,18 @@ step_envelope (int voice)
if (vol >= (4096 - 64))
vol = 4096 - 65;
gus_ramp_range (0, vol);
- gus_rampon (0x20); /* Increasing, irq */
+ gus_rampon (0x20); /*
+ * Increasing, irq
+ */
}
else
{
if (vol <= 64)
vol = 65;
- gus_ramp_range (vol, 4095);
- gus_rampon (0x60); /* Decreasing, irq */
+ gus_ramp_range (vol, 4030);
+ gus_rampon (0x60); /*
+ * Decreasing, irq
+ */
}
voices[voice].current_volume = vol;
}
@@ -536,13 +665,19 @@ static void
start_release (int voice)
{
if (gus_read8 (0x00) & 0x03)
- return; /* Voice already stopped */
+ return; /*
+ * Voice already stopped
+ */
- voices[voice].env_phase = 2; /* Will be incremented by step_envelope */
+ voices[voice].env_phase = 2; /*
+ * Will be incremented by step_envelope
+ */
voices[voice].current_volume =
voices[voice].initial_volume =
- gus_read16 (0x09) >> 4; /* Get current volume */
+ gus_read16 (0x09) >> 4; /*
+ * Get current volume
+ */
voices[voice].mode &= ~WAVE_SUSTAIN_ON;
gus_rampoff ();
@@ -556,11 +691,17 @@ gus_voice_fade (int voice)
if (instr_no < 0 || instr_no > MAX_SAMPLE)
{
- gus_write8 (0x00, 0x03); /* Hard stop */
+ gus_write8 (0x00, 0x03); /*
+ * Hard stop
+ */
return;
}
- is16bits = (samples[instr_no].mode & WAVE_16_BITS) ? 1 : 0; /* 8 or 16 bit samples */
+ is16bits = (samples[instr_no].mode & WAVE_16_BITS) ? 1 : 0; /*
+ * 8 or 16
+ * bit
+ * samples
+ */
if (voices[voice].mode & WAVE_ENVELOPES)
{
@@ -568,10 +709,12 @@ gus_voice_fade (int voice)
return;
}
- /*
+ /*
* Ramp the volume down but not too quickly.
*/
- if ((gus_read16 (0x09) >> 4) < 100) /* Get current volume */
+ if ((gus_read16 (0x09) >> 4) < 100) /*
+ * Get current volume
+ */
{
gus_voice_off ();
gus_rampoff ();
@@ -579,9 +722,11 @@ gus_voice_fade (int voice)
return;
}
- gus_ramp_range (65, 4095);
+ gus_ramp_range (65, 4030);
gus_ramp_rate (2, 4);
- gus_rampon (0x40 | 0x20); /* Down, once, irq */
+ gus_rampon (0x40 | 0x20); /*
+ * Down, once, irq
+ */
voices[voice].volume_irq_mode = VMODE_HALT;
}
@@ -597,14 +742,25 @@ gus_reset (void)
for (i = 0; i < 32; i++)
{
- gus_voice_init (i); /* Turn voice off */
+ gus_voice_init (i); /*
+ * Turn voice off
+ */
+ gus_voice_init2 (i);
}
- INB (u_Status); /* Touch the status register */
+ INB (u_Status); /*
+ * Touch the status register
+ */
- gus_look8 (0x41); /* Clear any pending DMA IRQs */
- gus_look8 (0x49); /* Clear any pending sample IRQs */
- gus_read8 (0x0f); /* Clear pending IRQs */
+ gus_look8 (0x41); /*
+ * Clear any pending DMA IRQs
+ */
+ gus_look8 (0x49); /*
+ * Clear any pending sample IRQs
+ */
+ gus_read8 (0x0f); /*
+ * Clear pending IRQs
+ */
}
@@ -622,52 +778,82 @@ gus_initialize (void)
DISABLE_INTR (flags);
- gus_write8 (0x4c, 0); /* Reset GF1 */
+ gus_write8 (0x4c, 0); /*
+ * Reset GF1
+ */
gus_delay ();
gus_delay ();
- gus_write8 (0x4c, 1); /* Release Reset */
+ gus_write8 (0x4c, 1); /*
+ * Release Reset
+ */
gus_delay ();
gus_delay ();
- /*
+ /*
* Clear all interrupts
*/
- gus_write8 (0x41, 0); /* DMA control */
- gus_write8 (0x45, 0); /* Timer control */
- gus_write8 (0x49, 0); /* Sample control */
+ gus_write8 (0x41, 0); /*
+ * DMA control
+ */
+ gus_write8 (0x45, 0); /*
+ * Timer control
+ */
+ gus_write8 (0x49, 0); /*
+ * Sample control
+ */
gus_select_max_voices (24);
- INB (u_Status); /* Touch the status register */
-
- gus_look8 (0x41); /* Clear any pending DMA IRQs */
- gus_look8 (0x49); /* Clear any pending sample IRQs */
- gus_read8 (0x0f); /* Clear pending IRQs */
-
- gus_reset (); /* Resets all voices */
-
- gus_look8 (0x41); /* Clear any pending DMA IRQs */
- gus_look8 (0x49); /* Clear any pending sample IRQs */
- gus_read8 (0x0f); /* Clear pending IRQs */
-
- gus_write8 (0x4c, 7); /* Master reset | DAC enable | IRQ enable */
-
- /*
+ INB (u_Status); /*
+ * Touch the status register
+ */
+
+ gus_look8 (0x41); /*
+ * Clear any pending DMA IRQs
+ */
+ gus_look8 (0x49); /*
+ * Clear any pending sample IRQs
+ */
+ gus_read8 (0x0f); /*
+ * Clear pending IRQs
+ */
+
+ gus_reset (); /*
+ * Resets all voices
+ */
+
+ gus_look8 (0x41); /*
+ * Clear any pending DMA IRQs
+ */
+ gus_look8 (0x49); /*
+ * Clear any pending sample IRQs
+ */
+ gus_read8 (0x0f); /*
+ * Clear pending IRQs
+ */
+
+ gus_write8 (0x4c, 7); /*
+ * Master reset | DAC enable | IRQ enable
+ */
+
+ /*
* Set up for Digital ASIC
*/
OUTB (0x05, gus_base + 0x0f);
- mix_image |= 0x02; /* Disable line out */
+ mix_image |= 0x02; /*
+ * Disable line out
+ */
OUTB (mix_image, u_Mixer);
OUTB (0x00, u_IRQDMAControl);
OUTB (0x00, gus_base + 0x0f);
- /*
+ /*
* Now set up the DMA and IRQ interface
*
* The GUS supports two IRQs and two DMAs.
@@ -682,49 +868,89 @@ gus_initialize (void)
if (!tmp)
printk ("Warning! GUS IRQ not selected\n");
irq_image |= tmp;
- irq_image |= 0x40; /* Combine IRQ1 (GF1) and IRQ2 (Midi) */
+ irq_image |= 0x40; /*
+ * Combine IRQ1 (GF1) and IRQ2 (Midi)
+ */
- dma_image = 0x40; /* Combine DMA1 (DRAM) and IRQ2 (ADC) */
+ dma_image = 0x40; /*
+ * Combine DMA1 (DRAM) and IRQ2 (ADC)
+ */
tmp = gus_dma_map[gus_dma];
if (!tmp)
printk ("Warning! GUS DMA not selected\n");
dma_image |= tmp;
- /*
+ /*
* For some reason the IRQ and DMA addresses must be written twice
*/
- /* Doing it first time */
-
- OUTB (mix_image, u_Mixer); /* Select DMA control */
- OUTB (dma_image | 0x80, u_IRQDMAControl); /* Set DMA address */
-
- OUTB (mix_image | 0x40, u_Mixer); /* Select IRQ control */
- OUTB (irq_image, u_IRQDMAControl); /* Set IRQ address */
-
- /* Doing it second time */
-
- OUTB (mix_image, u_Mixer); /* Select DMA control */
- OUTB (dma_image, u_IRQDMAControl); /* Set DMA address */
-
- OUTB (mix_image | 0x40, u_Mixer); /* Select IRQ control */
- OUTB (irq_image, u_IRQDMAControl); /* Set IRQ address */
-
- gus_select_voice (0); /* This disables writes to IRQ/DMA reg */
-
- mix_image &= ~0x02; /* Enable line out */
- mix_image |= 0x08; /* Enable IRQ */
- OUTB (mix_image, u_Mixer); /* Turn mixer channels on */
+ /*
+ * Doing it first time
+ */
- gus_select_voice (0); /* This disables writes to IRQ/DMA reg */
+ OUTB (mix_image, u_Mixer); /*
+ * Select DMA control
+ */
+ OUTB (dma_image | 0x80, u_IRQDMAControl); /*
+ * Set DMA address
+ */
+
+ OUTB (mix_image | 0x40, u_Mixer); /*
+ * Select IRQ control
+ */
+ OUTB (irq_image, u_IRQDMAControl); /*
+ * Set IRQ address
+ */
+
+ /*
+ * Doing it second time
+ */
- gusintr (0); /* Serve pending interrupts */
+ OUTB (mix_image, u_Mixer); /*
+ * Select DMA control
+ */
+ OUTB (dma_image, u_IRQDMAControl); /*
+ * Set DMA address
+ */
+
+ OUTB (mix_image | 0x40, u_Mixer); /*
+ * Select IRQ control
+ */
+ OUTB (irq_image, u_IRQDMAControl); /*
+ * Set IRQ address
+ */
+
+ gus_select_voice (0); /*
+ * This disables writes to IRQ/DMA reg
+ */
+
+ mix_image &= ~0x02; /*
+ * Enable line out
+ */
+ mix_image |= 0x08; /*
+ * Enable IRQ
+ */
+ OUTB (mix_image, u_Mixer); /*
+ * Turn mixer channels on
+ * Note! Mic in is left off.
+ */
+
+ gus_select_voice (0); /*
+ * This disables writes to IRQ/DMA reg
+ */
+
+ gusintr (0); /*
+ * Serve pending interrupts
+ */
RESTORE_INTR (flags);
}
int
gus_wave_detect (int baseaddr)
{
+ unsigned long i;
+ unsigned long loc;
+
gus_base = baseaddr;
gus_write8 (0x4c, 0); /* Reset GF1 */
@@ -735,31 +961,37 @@ gus_wave_detect (int baseaddr)
gus_delay ();
gus_delay ();
- gus_poke (0x000, 0xaa);
- gus_poke (0x100, 0x55);
+ /* See if there is first block there.... */
+ gus_poke (0L, 0xaa);
+ if (gus_peek (0L) != 0xaa)
+ return (0);
- if (gus_peek (0x000) != 0xaa)
- return 0;
- if (gus_peek (0x100) != 0x55)
- return 0;
-
- gus_mem_size = 0x40000; /* 256k */
- gus_poke (0x40000, 0xaa);
- if (gus_peek (0x40000) != 0xaa)
- return 1;
+ /* Now zero it out so that I can check for mirroring .. */
+ gus_poke (0L, 0x00);
+ for (i = 1L; i < 1024L; i++)
+ {
+ int n, failed;
- gus_mem_size = 0x80000; /* 512k */
- gus_poke (0x80000, 0xaa);
- if (gus_peek (0x80000) != 0xaa)
- return 1;
+ /* check for mirroring ... */
+ if (gus_peek (0L) != 0)
+ break;
+ loc = i << 10;
- gus_mem_size = 0xc0000; /* 768k */
- gus_poke (0xc0000, 0xaa);
- if (gus_peek (0xc0000) != 0xaa)
- return 1;
+ for (n = loc - 1, failed = 0; n <= loc; n++)
+ {
+ gus_poke (loc, 0xaa);
+ if (gus_peek (loc) != 0xaa)
+ failed = 1;
- gus_mem_size = 0x100000; /* 1M */
+ gus_poke (loc, 0x55);
+ if (gus_peek (loc) != 0x55)
+ failed = 1;
+ }
+ if (failed)
+ break;
+ }
+ gus_mem_size = i << 10;
return 1;
}
@@ -804,16 +1036,26 @@ guswave_set_instr (int dev, int voice, int instr_no)
if (voice < 0 || voice > 31)
return RET_ERROR (EINVAL);
+ if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
+ {
+ voices[voice].sample_pending = instr_no;
+ return 0;
+ }
+
sample_no = patch_table[instr_no];
patch_map[voice] = -1;
if (sample_no < 0)
{
printk ("GUS: Undefined patch %d for voice %d\n", instr_no, voice);
- return RET_ERROR (EINVAL);/* Patch not defined */
+ return RET_ERROR (EINVAL); /*
+ * Patch not defined
+ */
}
- if (sample_ptrs[sample_no] == -1) /* Sample not loaded */
+ if (sample_ptrs[sample_no] == -1) /*
+ * Sample not loaded
+ */
{
printk ("GUS: Sample #%d not loaded for patch %d (voice %d)\n", sample_no, instr_no, voice);
return RET_ERROR (EINVAL);
@@ -825,13 +1067,22 @@ guswave_set_instr (int dev, int voice, int instr_no)
}
static int
+#ifdef FUTURE_VERSION
+guswave_kill_note (int dev, int voice, int note, int velocity)
+#else
guswave_kill_note (int dev, int voice, int velocity)
+#endif
{
unsigned long flags;
DISABLE_INTR (flags);
- gus_select_voice (voice);
- gus_voice_fade (voice);
+ if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
+ voices[voice].kill_pending = 1;
+ else
+ {
+ gus_select_voice (voice);
+ gus_voice_fade (voice);
+ }
RESTORE_INTR (flags);
return 0;
@@ -843,20 +1094,26 @@ guswave_aftertouch (int dev, int voice, int pressure)
short lo_limit, hi_limit;
unsigned long flags;
- return; /* Currently disabled */
+ return; /*
+ * Currently disabled
+ */
if (voice < 0 || voice > 31)
return;
if (voices[voice].mode & WAVE_ENVELOPES && voices[voice].env_phase != 2)
- return; /* Don't mix with envelopes */
+ return; /*
+ * Don't mix with envelopes
+ */
if (pressure < 32)
{
DISABLE_INTR (flags);
gus_select_voice (voice);
gus_rampoff ();
- compute_and_set_volume (voice, 255, 0); /* Back to original volume */
+ compute_and_set_volume (voice, 255, 0); /*
+ * Back to original volume
+ */
RESTORE_INTR (flags);
return;
}
@@ -875,7 +1132,9 @@ guswave_aftertouch (int dev, int voice, int pressure)
}
gus_ramp_range (lo_limit, hi_limit);
gus_ramp_rate (3, 8);
- gus_rampon (0x58); /* Bidirectional, Down, Loop */
+ gus_rampon (0x58); /*
+ * Bidirectional, Down, Loop
+ */
RESTORE_INTR (flags);
}
@@ -890,39 +1149,38 @@ static void
compute_volume (int voice, int volume)
{
if (volume < 128)
- {
- voices[voice].midi_volume = volume;
+ voices[voice].midi_volume = volume;
- switch (volume_method)
- {
- case VOL_METHOD_ADAGIO:
- voices[voice].initial_volume =
- gus_adagio_vol (volume, voices[voice].main_vol,
- voices[voice].expression_vol,
- voices[voice].patch_vol);
- break;
+ switch (volume_method)
+ {
+ case VOL_METHOD_ADAGIO:
+ voices[voice].initial_volume =
+ gus_adagio_vol (voices[voice].midi_volume, voices[voice].main_vol,
+ voices[voice].expression_vol,
+ voices[voice].patch_vol);
+ break;
- default:
- voices[voice].initial_volume = volume_base + (volume * volume_scale);
- }
- }
+ default:
+ voices[voice].initial_volume = volume_base +
+ (voices[voice].midi_volume * volume_scale);
+ }
- if (voices[voice].initial_volume > 4095)
- voices[voice].initial_volume = 4095;
+ if (voices[voice].initial_volume > 4030)
+ voices[voice].initial_volume = 4030;
}
static void
compute_and_set_volume (int voice, int volume, int ramp_time)
{
int current, target, rate;
- unsigned long flags;
+ unsigned long flags;
- DISABLE_INTR(flags);
-/*
+ DISABLE_INTR (flags);
+/*
* CAUTION! Interrupts disabled. Enable them before returning
*/
- gus_select_voice(voice);
+ gus_select_voice (voice);
compute_volume (voice, volume);
voices[voice].current_volume = voices[voice].initial_volume;
@@ -934,7 +1192,7 @@ compute_and_set_volume (int voice, int volume, int ramp_time)
{
gus_rampoff ();
gus_voice_volume (target);
- RESTORE_INTR(flags);
+ RESTORE_INTR (flags);
return;
}
@@ -944,11 +1202,13 @@ compute_and_set_volume (int voice, int volume, int ramp_time)
rate = 16;
gus_ramp_rate (0, rate);
- if ((target - current) / 64 == 0) /* Too close */
+ if ((target - current) / 64 == 0) /*
+ * Too close
+ */
{
gus_rampoff ();
gus_voice_volume (target);
- RESTORE_INTR(flags);
+ RESTORE_INTR (flags);
return;
}
@@ -957,7 +1217,9 @@ compute_and_set_volume (int voice, int volume, int ramp_time)
if (target > (4095 - 65))
target = 4095 - 65;
gus_ramp_range (current, target);
- gus_rampon (0x00); /* Ramp up, once, no irq */
+ gus_rampon (0x00); /*
+ * Ramp up, once, no irq
+ */
}
else
{
@@ -965,9 +1227,11 @@ compute_and_set_volume (int voice, int volume, int ramp_time)
target = 65;
gus_ramp_range (target, current);
- gus_rampon (0x40); /* Ramp down, once, no irq */
+ gus_rampon (0x40); /*
+ * Ramp down, once, no irq
+ */
}
- RESTORE_INTR(flags);
+ RESTORE_INTR (flags);
}
static void
@@ -978,11 +1242,15 @@ dynamic_volume_change (int voice)
DISABLE_INTR (flags);
gus_select_voice (voice);
- status = gus_read8 (0x00); /* Voice status */
+ status = gus_read8 (0x00); /*
+ * Voice status
+ */
RESTORE_INTR (flags);
if (status & 0x03)
- return; /* Voice not started */
+ return; /*
+ * Voice not started
+ */
if (!(voices[voice].mode & WAVE_ENVELOPES))
{
@@ -990,16 +1258,20 @@ dynamic_volume_change (int voice)
return;
}
- /*
+ /*
* Voice is running and has envelopes.
*/
DISABLE_INTR (flags);
gus_select_voice (voice);
- status = gus_read8 (0x0d); /* Ramping status */
+ status = gus_read8 (0x0d); /*
+ * Ramping status
+ */
RESTORE_INTR (flags);
- if (status & 0x03) /* Sustain phase? */
+ if (status & 0x03) /*
+ * Sustain phase?
+ */
{
compute_and_set_volume (voice, voices[voice].midi_volume, 1);
return;
@@ -1010,9 +1282,12 @@ dynamic_volume_change (int voice)
compute_volume (voice, voices[voice].midi_volume);
-#if 0 /* Is this really required */
+#if 0 /*
+ * * * Is this really required */
voices[voice].current_volume =
- gus_read16 (0x09) >> 4; /* Get current volume */
+ gus_read16 (0x09) >> 4; /*
+ * Get current volume
+ */
voices[voice].env_phase--;
step_envelope (voice);
@@ -1032,38 +1307,58 @@ guswave_controller (int dev, int voice, int ctrl_num, int value)
{
case CTRL_PITCH_BENDER:
voices[voice].bender = value;
- freq = compute_finetune (voices[voice].orig_freq, value, voices[voice].bender_range);
- voices[voice].current_freq = freq;
- DISABLE_INTR (flags);
- gus_select_voice (voice);
- gus_voice_freq (freq);
- RESTORE_INTR (flags);
+ if (voices[voice].volume_irq_mode != VMODE_START_NOTE)
+ {
+ freq = compute_finetune (voices[voice].orig_freq, value, voices[voice].bender_range);
+ voices[voice].current_freq = freq;
+
+ DISABLE_INTR (flags);
+ gus_select_voice (voice);
+ gus_voice_freq (freq);
+ RESTORE_INTR (flags);
+ }
break;
case CTRL_PITCH_BENDER_RANGE:
voices[voice].bender_range = value;
break;
-
+#ifdef FUTURE_VERSION
+ case CTL_EXPRESSION:
+ value /= 128;
+#endif
case CTRL_EXPRESSION:
volume_method = VOL_METHOD_ADAGIO;
voices[voice].expression_vol = value;
- dynamic_volume_change (voice);
+ if (voices[voice].volume_irq_mode != VMODE_START_NOTE)
+ dynamic_volume_change (voice);
+ break;
+
+#ifdef FUTURE_VERSION
+ case CTL_PAN:
+ voices[voice].panning = (value * 2) - 128;
break;
+ case CTL_MAIN_VOLUME:
+ value = (value * 100) / 16383;
+#endif
+
case CTRL_MAIN_VOLUME:
volume_method = VOL_METHOD_ADAGIO;
voices[voice].main_vol = value;
- dynamic_volume_change (voice);
+ if (voices[voice].volume_irq_mode != VMODE_START_NOTE)
+ dynamic_volume_change (voice);
break;
- default: /* Ignore */
+ default: /*
+ * Ignore
+ */
break;
}
}
static int
-guswave_start_note (int dev, int voice, int note_num, int volume)
+guswave_start_note2 (int dev, int voice, int note_num, int volume)
{
int sample, best_sample, best_delta, delta_freq;
int is16bits, samplep, patch, pan;
@@ -1101,7 +1396,7 @@ guswave_start_note (int dev, int voice, int note_num, int volume)
note_freq = note_to_freq (note_num);
- /*
+ /*
* Find a sample within a patch so that the note_freq is between low_note
* and high_note.
*/
@@ -1122,7 +1417,9 @@ guswave_start_note (int dev, int voice, int note_num, int volume)
if (samples[samplep].low_note <= note_freq && note_freq <= samples[samplep].high_note)
sample = samplep;
else
- samplep = samples[samplep].key; /* Follow link */
+ samplep = samples[samplep].key; /*
+ * Follow link
+ */
}
if (sample == -1)
sample = best_sample;
@@ -1130,10 +1427,16 @@ guswave_start_note (int dev, int voice, int note_num, int volume)
if (sample == -1)
{
printk ("GUS: Patch %d not defined for note %d\n", patch, note_num);
- return 0; /* Should play default patch ??? */
+ return 0; /*
+ * Should play default patch ???
+ */
}
- is16bits = (samples[sample].mode & WAVE_16_BITS) ? 1 : 0; /* 8 or 16 bit samples */
+ is16bits = (samples[sample].mode & WAVE_16_BITS) ? 1 : 0; /*
+ * 8 or 16
+ * bit
+ * samples
+ */
voices[voice].mode = samples[sample].mode;
voices[voice].patch_vol = samples[sample].volume;
@@ -1150,14 +1453,16 @@ guswave_start_note (int dev, int voice, int note_num, int volume)
sample_map[voice] = sample;
- base_note = samples[sample].base_note / 100; /* To avoid overflows */
+ base_note = samples[sample].base_note / 100; /*
+ * To avoid overflows
+ */
note_freq /= 100;
freq = samples[sample].base_freq * note_freq / base_note;
voices[voice].orig_freq = freq;
- /*
+ /*
* Since the pitch bender may have been set before playing the note, we
* have to calculate the bending now.
*/
@@ -1174,19 +1479,23 @@ guswave_start_note (int dev, int voice, int note_num, int volume)
if (samples[sample].mode & WAVE_16_BITS)
{
- mode |= 0x04; /* 16 bits */
+ mode |= 0x04; /*
+ * 16 bits
+ */
if ((sample_ptrs[sample] >> 18) !=
((sample_ptrs[sample] + samples[sample].len) >> 18))
printk ("GUS: Sample address error\n");
}
/*************************************************************************
- * CAUTION! Interrupts disabled. Don't return before enabling
- *************************************************************************/
+ * CAUTION! Interrupts disabled. Don't return before enabling
+ *************************************************************************/
DISABLE_INTR (flags);
gus_select_voice (voice);
- gus_voice_off (); /* It may still be running */
+ gus_voice_off (); /*
+ * It may still be running
+ */
gus_rampoff ();
if (voices[voice].mode & WAVE_ENVELOPES)
{
@@ -1197,35 +1506,62 @@ guswave_start_note (int dev, int voice, int note_num, int volume)
compute_and_set_volume (voice, volume, 0);
if (samples[sample].mode & WAVE_LOOP_BACK)
- gus_write_addr (0x0a, sample_ptrs[sample] + samples[sample].len, is16bits); /* Sample start=end */
+ gus_write_addr (0x0a, sample_ptrs[sample] + samples[sample].len -
+ voices[voice].offset_pending, is16bits); /* Sample
+ * start=end */
else
- gus_write_addr (0x0a, sample_ptrs[sample], is16bits); /* Sample start=begin */
+ gus_write_addr (0x0a, sample_ptrs[sample] + voices[voice].offset_pending,
+ is16bits); /* Sample start=begin */
if (samples[sample].mode & WAVE_LOOPING)
{
- mode |= 0x08; /* Looping on */
+ mode |= 0x08; /*
+ * Looping on
+ */
if (samples[sample].mode & WAVE_BIDIR_LOOP)
- mode |= 0x10; /* Bidirectional looping on */
+ mode |= 0x10; /*
+ * Bidirectional looping on
+ */
if (samples[sample].mode & WAVE_LOOP_BACK)
{
- gus_write_addr (0x0a, /* Put the current location = loop_end */
- sample_ptrs[sample] + samples[sample].loop_end, is16bits);
- mode |= 0x40; /* Loop backwards */
+ gus_write_addr (0x0a,
+ sample_ptrs[sample] + samples[sample].loop_end -
+ voices[voice].offset_pending, is16bits);
+ mode |= 0x40;
}
- gus_write_addr (0x02, sample_ptrs[sample] + samples[sample].loop_start, is16bits); /* Loop start location */
- gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].loop_end, is16bits); /* Loop end location */
+ gus_write_addr (0x02, sample_ptrs[sample] + samples[sample].loop_start, is16bits); /*
+ * Loop
+ * start
+ * location
+ */
+ gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].loop_end, is16bits); /*
+ * Loop
+ * end
+ * location
+ */
}
else
{
- mode |= 0x20; /* Loop irq at the end */
- voices[voice].loop_irq_mode = LMODE_FINISH; /* Ramp it down at the
- * end */
+ mode |= 0x20; /*
+ * Loop irq at the end
+ */
+ voices[voice].loop_irq_mode = LMODE_FINISH; /*
+ * Ramp it down at
+ * the * end
+ */
voices[voice].loop_irq_parm = 1;
- gus_write_addr (0x02, sample_ptrs[sample], is16bits); /* Loop start location */
- gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].len, is16bits); /* Loop end location */
+ gus_write_addr (0x02, sample_ptrs[sample], is16bits); /*
+ * Loop start
+ * location
+ */
+ gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].len-1, is16bits); /*
+ * Loop
+ * end
+ * location
+ */
}
gus_voice_freq (freq);
gus_voice_balance (pan);
@@ -1235,13 +1571,76 @@ guswave_start_note (int dev, int voice, int note_num, int volume)
return 0;
}
+/*
+ * * New guswave_start_note by Andrew J. Robinson attempts to minimize
+ * clicking * when the note playing on the voice is changed. It uses volume
+ * ramping. */
+
+static int
+guswave_start_note (int dev, int voice, int note_num, int volume)
+{
+ long int flags;
+ int mode;
+ int ret_val = 0;
+
+ DISABLE_INTR (flags);
+ if (note_num == 255)
+ {
+ if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
+ voices[voice].volume_pending = volume;
+ else
+ ret_val = guswave_start_note2 (dev, voice, note_num, volume);
+ }
+ else
+ {
+ gus_select_voice (voice);
+ mode = gus_read8 (0x00);
+ if (mode & 0x20)
+ gus_write8 (0x00, mode & 0xdf); /* No interrupt! */
+
+ voices[voice].offset_pending = 0;
+ voices[voice].kill_pending = 0;
+ voices[voice].volume_irq_mode = 0;
+ voices[voice].loop_irq_mode = 0;
+
+ if (voices[voice].sample_pending >= 0)
+ {
+ guswave_set_instr (voices[voice].dev_pending, voice,
+ voices[voice].sample_pending);
+ voices[voice].sample_pending = -1;
+ }
+
+ if ((mode & 0x01) || ((gus_read16 (0x09) >> 4) < 2065))
+ {
+ ret_val = guswave_start_note2 (dev, voice, note_num, volume);
+ }
+ else
+ {
+ voices[voice].dev_pending = dev;
+ voices[voice].note_pending = note_num;
+ voices[voice].volume_pending = volume;
+ voices[voice].volume_irq_mode = VMODE_START_NOTE;
+
+ gus_rampoff ();
+ gus_ramp_range (2000, 4065);
+ gus_ramp_rate (0, 63); /* Fastest possible rate */
+ gus_rampon (0x20 | 0x40); /* Ramp down, once, irq */
+ }
+ }
+ RESTORE_INTR (flags);
+ return ret_val;
+}
+
static void
guswave_reset (int dev)
{
int i;
for (i = 0; i < 32; i++)
- gus_voice_init (i);
+ {
+ gus_voice_init (i);
+ gus_voice_init2 (i);
+ }
}
static int
@@ -1252,6 +1651,8 @@ guswave_open (int dev, int mode)
if (gus_busy)
return RET_ERROR (EBUSY);
+ gus_initialize ();
+
if ((err = DMAbuf_open_dma (gus_devnum)))
return err;
@@ -1284,8 +1685,11 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
unsigned long blk_size, blk_end, left, src_offs, target;
- sizeof_patch = (long) &patch.data[0] - (long) &patch; /* Size of the header
- * info */
+ sizeof_patch = (long) &patch.data[0] - (long) &patch; /*
+ * Size of
+ * the header
+ * * info
+ */
if (format != GUS_PATCH)
{
@@ -1307,7 +1711,7 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
return RET_ERROR (ENOSPC);
}
- /*
+ /*
* Copy the header from user space but ignore the first bytes which have
* been transferred already.
*/
@@ -1325,13 +1729,13 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
if (count < patch.len)
{
printk ("GUS Warning: Patch record too short (%d<%d)\n",
- count, (int)patch.len);
+ count, (int) patch.len);
patch.len = count;
}
if (patch.len <= 0 || patch.len > gus_mem_size)
{
- printk ("GUS: Invalid sample length %d\n", (int)patch.len);
+ printk ("GUS: Invalid sample length %d\n", (int) patch.len);
return RET_ERROR (EINVAL);
}
@@ -1350,31 +1754,37 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
}
}
- free_mem_ptr = (free_mem_ptr + 31) & ~31; /* Alignment 32 bytes */
+ free_mem_ptr = (free_mem_ptr + 31) & ~31; /*
+ * Alignment 32 bytes
+ */
#define GUS_BANK_SIZE (256*1024)
if (patch.mode & WAVE_16_BITS)
{
- /*
+ /*
* 16 bit samples must fit one 256k bank.
*/
if (patch.len >= GUS_BANK_SIZE)
{
- printk ("GUS: Sample (16 bit) too long %d\n", (int)patch.len);
+ printk ("GUS: Sample (16 bit) too long %d\n", (int) patch.len);
return RET_ERROR (ENOSPC);
}
if ((free_mem_ptr / GUS_BANK_SIZE) !=
((free_mem_ptr + patch.len) / GUS_BANK_SIZE))
{
- unsigned long tmp_mem = /* Align to 256K*N */
+ unsigned long tmp_mem = /*
+ * Align to 256K*N
+ */
((free_mem_ptr / GUS_BANK_SIZE) + 1) * GUS_BANK_SIZE;
if ((tmp_mem + patch.len) > gus_mem_size)
return RET_ERROR (ENOSPC);
- free_mem_ptr = tmp_mem; /* This leaves unusable memory */
+ free_mem_ptr = tmp_mem; /*
+ * This leaves unusable memory
+ */
}
}
@@ -1383,21 +1793,23 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
sample_ptrs[free_sample] = free_mem_ptr;
- /* Tremolo is not possible with envelopes */
+ /*
+ * Tremolo is not possible with envelopes
+ */
if (patch.mode & WAVE_ENVELOPES)
patch.mode &= ~WAVE_TREMOLO;
memcpy ((char *) &samples[free_sample], &patch, sizeof_patch);
- /*
+ /*
* Link this_one sample to the list of samples for patch 'instr'.
*/
samples[free_sample].key = patch_table[instr];
patch_table[instr] = free_sample;
- /*
+ /*
* Use DMA to transfer the wave data to the DRAM
*/
@@ -1405,26 +1817,30 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
src_offs = 0;
target = free_mem_ptr;
- while (left) /* Not all moved */
+ while (left) /*
+ * Not all moved
+ */
{
blk_size = sound_buffsizes[gus_devnum];
if (blk_size > left)
blk_size = left;
- /*
+ /*
* DMA cannot cross 256k bank boundaries. Check for that.
*/
blk_end = target + blk_size;
if ((target >> 18) != (blk_end >> 18))
- { /* Have to split the block */
+ { /*
+ * Have to split the block
+ */
blk_end &= ~(256 * 1024 - 1);
blk_size = blk_end - target;
}
#if defined(GUS_NO_DMA) || defined(GUS_PATCH_NO_DMA)
- /*
+ /*
* For some reason the DMA is not possible. We have to use PIO.
*/
{
@@ -1436,17 +1852,21 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
GET_BYTE_FROM_USER (data, addr, sizeof_patch + i);
if (patch.mode & WAVE_UNSIGNED)
- if (!(patch.mode & WAVE_16_BITS) || (i & 0x01))
- data ^= 0x80; /* Convert to signed */
+ if (!(patch.mode & WAVE_16_BITS) || (i & 0x01))
+ data ^= 0x80; /*
+ * Convert to signed
+ */
gus_poke (target + i, data);
}
}
-#else /* GUS_NO_DMA */
+#else /*
+ * * * GUS_NO_DMA */
{
unsigned long address, hold_address;
unsigned char dma_command;
+ unsigned long flags;
- /*
+ /*
* OK, move now. First in and then out.
*/
@@ -1454,11 +1874,14 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
addr, sizeof_patch + src_offs,
blk_size);
- gus_write8 (0x41, 0); /* Disable GF1 DMA */
+ DISABLE_INTR (flags); /******** INTERRUPTS DISABLED NOW ********/
+ gus_write8 (0x41, 0); /*
+ * Disable GF1 DMA
+ */
DMAbuf_start_dma (gus_devnum, snd_raw_buf_phys[gus_devnum][0],
blk_size, DMA_MODE_WRITE);
- /*
+ /*
* Set the DRAM address for the wave data
*/
@@ -1472,23 +1895,35 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
address |= (hold_address & 0x000c0000L);
}
- gus_write16 (0x42, (address >> 4) & 0xffff); /* DRAM DMA address */
+ gus_write16 (0x42, (address >> 4) & 0xffff); /*
+ * DRAM DMA address
+ */
- /*
+ /*
* Start the DMA transfer
*/
- dma_command = 0x21; /* IRQ enable, DMA start */
+ dma_command = 0x21; /*
+ * IRQ enable, DMA start
+ */
if (patch.mode & WAVE_UNSIGNED)
- dma_command |= 0x80; /* Invert MSB */
+ dma_command |= 0x80; /*
+ * Invert MSB
+ */
if (patch.mode & WAVE_16_BITS)
- dma_command |= 0x40; /* 16 bit _DATA_ */
+ dma_command |= 0x40; /*
+ * 16 bit _DATA_
+ */
if (sound_dsp_dmachan[gus_devnum] > 3)
- dma_command |= 0x04; /* 16 bit DMA channel */
+ dma_command |= 0x04; /*
+ * 16 bit DMA channel
+ */
- gus_write8 (0x41, dma_command); /* Let's go luteet (=bugs) */
+ gus_write8 (0x41, dma_command); /*
+ * Let's go luteet (=bugs)
+ */
- /*
+ /*
* Sleep here until the DRAM DMA done interrupt is served
*/
active_device = GUS_DEV_WAVE;
@@ -1496,10 +1931,12 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
DO_SLEEP (dram_sleeper, dram_sleep_flag, HZ);
if (TIMED_OUT (dram_sleeper, dram_sleep_flag))
printk ("GUS: DMA Transfer timed out\n");
+ RESTORE_INTR (flags);
}
-#endif /* GUS_NO_DMA */
+#endif /*
+ * * * GUS_NO_DMA */
- /*
+ /*
* Now the next part
*/
@@ -1507,7 +1944,9 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
src_offs += blk_size;
target += blk_size;
- gus_write8 (0x41, 0); /* Stop DMA */
+ gus_write8 (0x41, 0); /*
+ * Stop DMA
+ */
}
free_mem_ptr += patch.len;
@@ -1531,6 +1970,10 @@ guswave_hw_control (int dev, unsigned char *event)
p2 = *(unsigned short *) &event[6];
plong = *(unsigned long *) &event[4];
+ if ((voices[voice].volume_irq_mode == VMODE_START_NOTE) &&
+ (cmd != _GUS_VOICESAMPLE) && (cmd != _GUS_VOICE_POS))
+ do_volume_irq (voice);
+
switch (cmd)
{
@@ -1548,7 +1991,9 @@ guswave_hw_control (int dev, unsigned char *event)
case _GUS_VOICEON:
DISABLE_INTR (flags);
gus_select_voice (voice);
- p1 &= ~0x20; /* Disable intr */
+ p1 &= ~0x20; /*
+ * Disable intr
+ */
gus_voice_on (p1);
RESTORE_INTR (flags);
break;
@@ -1570,7 +2015,9 @@ guswave_hw_control (int dev, unsigned char *event)
case _GUS_VOICEMODE:
DISABLE_INTR (flags);
gus_select_voice (voice);
- p1 &= ~0x20; /* Disable intr */
+ p1 &= ~0x20; /*
+ * Disable intr
+ */
gus_voice_mode (p1);
RESTORE_INTR (flags);
break;
@@ -1596,14 +2043,18 @@ guswave_hw_control (int dev, unsigned char *event)
RESTORE_INTR (flags);
break;
- case _GUS_VOICEVOL2: /* Just update the voice value */
+ case _GUS_VOICEVOL2: /*
+ * Just update the voice value
+ */
voices[voice].initial_volume =
voices[voice].current_volume = p1;
break;
case _GUS_RAMPRANGE:
if (voices[voice].mode & WAVE_ENVELOPES)
- break; /* NO-NO */
+ break; /*
+ * NO-NO
+ */
DISABLE_INTR (flags);
gus_select_voice (voice);
gus_ramp_range (p1, p2);
@@ -1612,7 +2063,9 @@ guswave_hw_control (int dev, unsigned char *event)
case _GUS_RAMPRATE:
if (voices[voice].mode & WAVE_ENVELOPES)
- break; /* NO-NO */
+ break; /*
+ * NO-NO
+ */
DISABLE_INTR (flags);
gus_select_voice (voice);
gus_ramp_rate (p1, p2);
@@ -1621,27 +2074,37 @@ guswave_hw_control (int dev, unsigned char *event)
case _GUS_RAMPMODE:
if (voices[voice].mode & WAVE_ENVELOPES)
- break; /* NO-NO */
+ break; /*
+ * NO-NO
+ */
DISABLE_INTR (flags);
gus_select_voice (voice);
- p1 &= ~0x20; /* Disable intr */
+ p1 &= ~0x20; /*
+ * Disable intr
+ */
gus_ramp_mode (p1);
RESTORE_INTR (flags);
break;
case _GUS_RAMPON:
if (voices[voice].mode & WAVE_ENVELOPES)
- break; /* NO-NO */
+ break; /*
+ * NO-NO
+ */
DISABLE_INTR (flags);
gus_select_voice (voice);
- p1 &= ~0x20; /* Disable intr */
+ p1 &= ~0x20; /*
+ * Disable intr
+ */
gus_rampon (p1);
RESTORE_INTR (flags);
break;
case _GUS_RAMPOFF:
if (voices[voice].mode & WAVE_ENVELOPES)
- break; /* NO-NO */
+ break; /*
+ * NO-NO
+ */
DISABLE_INTR (flags);
gus_select_voice (voice);
gus_rampoff ();
@@ -1653,6 +2116,13 @@ guswave_hw_control (int dev, unsigned char *event)
volume_scale = p2;
break;
+ case _GUS_VOICE_POS:
+ DISABLE_INTR (flags);
+ gus_select_voice (voice);
+ gus_set_voice_pos (voice, plong);
+ RESTORE_INTR (flags);
+ break;
+
default:;
}
}
@@ -1720,7 +2190,8 @@ gus_sampling_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
break;
case SOUND_PCM_WRITE_CHANNELS:
- if (local) return gus_sampling_set_channels(arg);
+ if (local)
+ return gus_sampling_set_channels (arg);
return IOCTL_OUT (arg, gus_sampling_set_channels (IOCTL_IN (arg)));
break;
@@ -1741,7 +2212,9 @@ gus_sampling_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
return gus_sampling_bits;
return IOCTL_OUT (arg, gus_sampling_bits);
- case SOUND_PCM_WRITE_FILTER: /* NOT YET IMPLEMENTED */
+ case SOUND_PCM_WRITE_FILTER: /*
+ * NOT YET IMPLEMENTED
+ */
return IOCTL_OUT (arg, RET_ERROR (EINVAL));
break;
@@ -1771,6 +2244,8 @@ gus_sampling_open (int dev, int mode)
if (gus_busy)
return RET_ERROR (EBUSY);
+ gus_initialize ();
+
gus_busy = 1;
active_device = 0;
@@ -1779,6 +2254,12 @@ gus_sampling_open (int dev, int mode)
gus_select_max_voices (14);
pcm_active = 0;
+ pcm_opened = 1;
+ if (mode & OPEN_READ)
+ {
+ recording_active = 1;
+ set_input_volumes();
+ }
return 0;
}
@@ -1788,7 +2269,31 @@ gus_sampling_close (int dev)
{
gus_reset ();
gus_busy = 0;
+ pcm_opened = 0;
active_device = 0;
+
+ if (recording_active)
+ set_input_volumes();
+
+ recording_active = 0;
+}
+
+static void
+gus_sampling_update_volume (void)
+{
+ unsigned long flags;
+ int voice;
+
+ DISABLE_INTR (flags);
+ if (pcm_active && pcm_opened)
+ for (voice = 0; voice < gus_sampling_channels; voice++)
+ {
+ gus_select_voice (voice);
+ gus_rampoff ();
+ gus_voice_volume (1530 + (25 * gus_pcm_volume));
+ gus_ramp_range (65, 1530 + (25 * gus_pcm_volume));
+ }
+ RESTORE_INTR (flags);
}
static void
@@ -1808,18 +2313,24 @@ play_next_pcm_block (void)
for (chn = 0; chn < gus_sampling_channels; chn++)
{
mode[chn] = 0x00;
- ramp_mode[chn] = 0x03; /* Ramping and rollover off */
+ ramp_mode[chn] = 0x03; /*
+ * Ramping and rollover off
+ */
if (chn == 0)
{
- mode[chn] |= 0x20; /* Loop irq */
+ mode[chn] |= 0x20; /*
+ * Loop irq
+ */
voices[chn].loop_irq_mode = LMODE_PCM;
}
if (gus_sampling_bits != 8)
{
is16bits = 1;
- mode[chn] |= 0x04; /* 16 bit data */
+ mode[chn] |= 0x04; /*
+ * 16 bit data
+ */
}
else
is16bits = 0;
@@ -1827,15 +2338,23 @@ play_next_pcm_block (void)
dram_loc = this_one * pcm_bsize;
dram_loc += chn * pcm_banksize;
- if (this_one == (pcm_nblk - 1)) /* Last of the DRAM buffers */
+ if (this_one == (pcm_nblk - 1)) /*
+ * Last of the DRAM buffers
+ */
{
- mode[chn] |= 0x08; /* Enable loop */
- ramp_mode[chn] = 0x03;/* Disable rollover */
+ mode[chn] |= 0x08; /*
+ * Enable loop
+ */
+ ramp_mode[chn] = 0x03; /*
+ * Disable rollover
+ */
}
else
{
if (chn == 0)
- ramp_mode[chn] = 0x04; /* Enable rollover bit */
+ ramp_mode[chn] = 0x04; /*
+ * Enable rollover bit
+ */
}
DISABLE_INTR (flags);
@@ -1843,53 +2362,90 @@ play_next_pcm_block (void)
gus_voice_freq (speed);
if (gus_sampling_channels == 1)
- gus_voice_balance (7); /* mono */
+ gus_voice_balance (7); /*
+ * mono
+ */
else if (chn == 0)
- gus_voice_balance (0); /* left */
+ gus_voice_balance (0); /*
+ * left
+ */
else
- gus_voice_balance (15); /* right */
+ gus_voice_balance (15); /*
+ * right
+ */
- if (!pcm_active) /* Voice not started yet */
+ if (!pcm_active) /*
+ * Voice not started yet
+ */
{
- /*
+ /*
* The playback was not started yet (or there has been a pause).
* Start the voice (again) and ask for a rollover irq at the end of
* this_one block. If this_one one is last of the buffers, use just
* the normal loop with irq.
*/
- gus_voice_off (); /* It could already be running */
+ gus_voice_off (); /*
+ * It could already be running
+ */
gus_rampoff ();
- gus_voice_volume (4000);
- gus_ramp_range (65, 4030);
+ gus_voice_volume (1530 + (25 * gus_pcm_volume));
+ gus_ramp_range (65, 1530 + (25 * gus_pcm_volume));
- gus_write_addr (0x0a, dram_loc, is16bits); /* Starting position */
- gus_write_addr (0x02, chn * pcm_banksize, is16bits); /* Loop start location */
+ gus_write_addr (0x0a, dram_loc, is16bits); /*
+ * Starting position
+ */
+ gus_write_addr (0x02, chn * pcm_banksize, is16bits); /*
+ * Loop start
+ * location
+ */
if (chn != 0)
gus_write_addr (0x04, pcm_banksize + (pcm_bsize * pcm_nblk),
- is16bits); /* Loop end location */
+ is16bits); /*
+ * Loop end location
+ */
}
if (chn == 0)
- gus_write_addr (0x04, dram_loc + pcm_datasize[this_one], is16bits); /* Loop end location */
+ gus_write_addr (0x04, dram_loc + pcm_datasize[this_one], is16bits); /*
+ * Loop
+ * end
+ * location
+ */
else
- mode[chn] |= 0x08; /* Enable loop */
+ mode[chn] |= 0x08; /*
+ * Enable loop
+ */
if (pcm_datasize[this_one] != pcm_bsize)
{
- /* Incomplete block. Possibly the last one. */
+ /*
+ * Incomplete block. Possibly the last one.
+ */
if (chn == 0)
{
- mode[chn] &= ~0x08; /* Disable loop */
- mode[chn] |= 0x20;/* Enable loop IRQ */
+ mode[chn] &= ~0x08; /*
+ * Disable loop
+ */
+ mode[chn] |= 0x20; /*
+ * Enable loop IRQ
+ */
voices[0].loop_irq_mode = LMODE_PCM_STOP;
- ramp_mode[chn] = 0x03; /* No rollover bit */
+ ramp_mode[chn] = 0x03; /*
+ * No rollover bit
+ */
}
else
{
- gus_write_addr (0x04, dram_loc + pcm_datasize[this_one], is16bits); /* Loop end location */
- mode[chn] &= ~0x08; /* Disable loop */
+ gus_write_addr (0x04, dram_loc + pcm_datasize[this_one], is16bits); /*
+ * Loop
+ * end
+ * location
+ */
+ mode[chn] &= ~0x08; /*
+ * Disable loop
+ */
}
}
@@ -1912,7 +2468,7 @@ static void
gus_transfer_output_block (int dev, unsigned long buf,
int total_count, int intrflag, int chn)
{
- /*
+ /*
* This routine transfers one block of audio data to the DRAM. In mono mode
* it's called just once. When in stereo mode, this_one routine is called
* once for both channels.
@@ -1943,7 +2499,9 @@ gus_transfer_output_block (int dev, unsigned long buf,
else
this_one = pcm_current_block;
- gus_write8 (0x41, 0); /* Disable GF1 DMA */
+ gus_write8 (0x41, 0); /*
+ * Disable GF1 DMA
+ */
DMAbuf_start_dma (dev, buf + (chn * count), count, DMA_MODE_WRITE);
address = this_one * pcm_bsize;
@@ -1957,38 +2515,55 @@ gus_transfer_output_block (int dev, unsigned long buf,
address |= (hold_address & 0x000c0000L);
}
- gus_write16 (0x42, (address >> 4) & 0xffff); /* DRAM DMA address */
+ gus_write16 (0x42, (address >> 4) & 0xffff); /*
+ * DRAM DMA address
+ */
- dma_command = 0x21; /* IRQ enable, DMA start */
+ dma_command = 0x21; /*
+ * IRQ enable, DMA start
+ */
if (gus_sampling_bits != 8)
- dma_command |= 0x40; /* 16 bit _DATA_ */
+ dma_command |= 0x40; /*
+ * 16 bit _DATA_
+ */
else
- dma_command |= 0x80; /* Invert MSB */
+ dma_command |= 0x80; /*
+ * Invert MSB
+ */
if (sound_dsp_dmachan[dev] > 3)
- dma_command |= 0x04; /* 16 bit DMA channel */
+ dma_command |= 0x04; /*
+ * 16 bit DMA channel
+ */
- gus_write8 (0x41, dma_command); /* Kick on */
+ gus_write8 (0x41, dma_command); /*
+ * Kick on
+ */
- if (chn == (gus_sampling_channels - 1)) /* Last channel */
+ if (chn == (gus_sampling_channels - 1)) /*
+ * Last channel
+ */
{
- /* Last (right or mono) channel data */
+ /*
+ * Last (right or mono) channel data
+ */
active_device = GUS_DEV_PCM_DONE;
if (!pcm_active && (pcm_qlen > 2 || count < pcm_bsize))
{
play_next_pcm_block ();
}
}
- else /* Left channel data. The right channel is
- * transferred after DMA interrupt */
+ else /*
+ * * * Left channel data. The right channel
+ * is * * * transferred after DMA interrupt */
active_device = GUS_DEV_PCM_CONTINUE;
RESTORE_INTR (flags);
}
static void
-gus_sampling_output_block (int dev, unsigned long buf, int total_count,
+gus_sampling_output_block (int dev, unsigned long buf, int total_count,
int intrflag, int restart_dma)
{
pcm_current_buf = buf;
@@ -1999,7 +2574,7 @@ gus_sampling_output_block (int dev, unsigned long buf, int total_count,
}
static void
-gus_sampling_start_input (int dev, unsigned long buf, int count,
+gus_sampling_start_input (int dev, unsigned long buf, int count,
int intrflag, int restart_dma)
{
unsigned long flags;
@@ -2009,13 +2584,21 @@ gus_sampling_start_input (int dev, unsigned long buf, int count,
DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
- mode = 0xa0; /* DMA IRQ enable, invert MSB */
+ mode = 0xa0; /*
+ * DMA IRQ enable, invert MSB
+ */
if (sound_dsp_dmachan[dev] > 3)
- mode |= 0x04; /* 16 bit DMA channel */
+ mode |= 0x04; /*
+ * 16 bit DMA channel
+ */
if (gus_sampling_channels > 1)
- mode |= 0x02; /* Stereo */
- mode |= 0x01; /* DMA enable */
+ mode |= 0x02; /*
+ * Stereo
+ */
+ mode |= 0x01; /*
+ * DMA enable
+ */
gus_write8 (0x49, mode);
@@ -2029,7 +2612,9 @@ gus_sampling_prepare_for_input (int dev, int bsize, int bcount)
rate = (9878400 / (gus_sampling_speed + 2)) / 16;
- gus_write8 (0x48, rate & 0xff); /* Set sampling frequency */
+ gus_write8 (0x48, rate & 0xff); /*
+ * Set sampling frequency
+ */
if (gus_sampling_bits != 8)
{
@@ -2131,19 +2716,37 @@ gus_copy_from_user (int dev, char *localbuf, int localoffs,
static struct audio_operations gus_sampling_operations =
{
"Gravis UltraSound",
- gus_sampling_open, /* */
- gus_sampling_close, /* */
- gus_sampling_output_block, /* */
- gus_sampling_start_input, /* */
- gus_sampling_ioctl, /* */
- gus_sampling_prepare_for_input, /* */
- gus_sampling_prepare_for_output, /* */
- gus_sampling_reset, /* */
- gus_sampling_reset, /* halt_xfer */
+ gus_sampling_open,
+ gus_sampling_close,
+ gus_sampling_output_block,
+ gus_sampling_start_input,
+ gus_sampling_ioctl,
+ gus_sampling_prepare_for_input,
+ gus_sampling_prepare_for_output,
+ gus_sampling_reset,
+ gus_sampling_reset,
gus_has_output_drained,
gus_copy_from_user
};
+#ifdef FUTURE_VERSION
+static void
+guswave_bender (int dev, int voice, int value)
+{
+ int freq;
+ unsigned long flags;
+
+ voices[voice].bender = value - 8192;
+ freq = compute_finetune (voices[voice].orig_freq, value, voices[voice].bender_range);
+ voices[voice].current_freq = freq;
+
+ DISABLE_INTR (flags);
+ gus_select_voice (voice);
+ gus_voice_freq (freq);
+ RESTORE_INTR (flags);
+}
+#endif
+
static int
guswave_patchmgr (int dev, struct patmgr_info *rec)
{
@@ -2173,7 +2776,9 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
while (ptr >= 0 && ptr < free_sample)
{
rec->data.data8[i]++;
- ptr = samples[ptr].key; /* Follow link */
+ ptr = samples[ptr].key; /*
+ * Follow link
+ */
}
}
return 0;
@@ -2188,7 +2793,9 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
while (ptr >= 0 && ptr < free_sample)
{
rec->data.data32[n++] = ptr;
- ptr = samples[ptr].key; /* Follow link */
+ ptr = samples[ptr].key; /*
+ * Follow link
+ */
}
}
rec->parm1 = n;
@@ -2208,8 +2815,12 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
pat = (struct patch_info *) rec->data.data8;
- pat->key = GUS_PATCH; /* Restore patch type */
- rec->parm1 = sample_ptrs[ptr]; /* DRAM address */
+ pat->key = GUS_PATCH; /*
+ * Restore patch type
+ */
+ rec->parm1 = sample_ptrs[ptr]; /*
+ * DRAM address
+ */
rec->parm2 = sizeof (struct patch_info);
}
return 0;
@@ -2225,10 +2836,14 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
pat = (struct patch_info *) rec->data.data8;
- if (pat->len > samples[ptr].len) /* Cannot expand sample */
+ if (pat->len > samples[ptr].len) /*
+ * Cannot expand sample
+ */
return RET_ERROR (EINVAL);
- pat->key = samples[ptr].key; /* Ensure the link is correct */
+ pat->key = samples[ptr].key; /*
+ * Ensure the link is correct
+ */
memcpy ((char *) &samples[ptr], rec->data.data8,
sizeof (struct patch_info));
@@ -2238,7 +2853,9 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
return 0;
break;
- case PM_READ_PATCH: /* Returns a block of wave data from the DRAM */
+ case PM_READ_PATCH: /*
+ * Returns a block of wave data from the DRAM
+ */
{
int sample = rec->parm1;
int n;
@@ -2249,9 +2866,13 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
return RET_ERROR (EINVAL);
if (offs < 0 || offs >= samples[sample].len)
- return RET_ERROR (EINVAL); /* Invalid offset */
+ return RET_ERROR (EINVAL); /*
+ * Invalid offset
+ */
- n = samples[sample].len - offs; /* Nr of bytes left */
+ n = samples[sample].len - offs; /*
+ * Nr of bytes left
+ */
if (l > n)
l = n;
@@ -2260,18 +2881,26 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
l = sizeof (rec->data.data8);
if (l <= 0)
- return RET_ERROR (EINVAL); /* Was there a bug? */
+ return RET_ERROR (EINVAL); /*
+ * Was there a bug?
+ */
- offs += sample_ptrs[sample]; /* Begin offsess + offset to DRAM */
+ offs += sample_ptrs[sample]; /*
+ * Begin offsess + offset to DRAM
+ */
for (n = 0; n < l; n++)
rec->data.data8[n] = gus_peek (offs++);
- rec->parm1 = n; /* Nr of bytes copied */
+ rec->parm1 = n; /*
+ * Nr of bytes copied
+ */
}
return 0;
break;
- case PM_WRITE_PATCH: /* Writes a block of wave data to the DRAM */
+ case PM_WRITE_PATCH: /*
+ * Writes a block of wave data to the DRAM
+ */
{
int sample = rec->parm1;
int n;
@@ -2282,9 +2911,13 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
return RET_ERROR (EINVAL);
if (offs < 0 || offs >= samples[sample].len)
- return RET_ERROR (EINVAL); /* Invalid offset */
+ return RET_ERROR (EINVAL); /*
+ * Invalid offset
+ */
- n = samples[sample].len - offs; /* Nr of bytes left */
+ n = samples[sample].len - offs; /*
+ * Nr of bytes left
+ */
if (l > n)
l = n;
@@ -2293,13 +2926,19 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
l = sizeof (rec->data.data8);
if (l <= 0)
- return RET_ERROR (EINVAL); /* Was there a bug? */
+ return RET_ERROR (EINVAL); /*
+ * Was there a bug?
+ */
- offs += sample_ptrs[sample]; /* Begin offsess + offset to DRAM */
+ offs += sample_ptrs[sample]; /*
+ * Begin offsess + offset to DRAM
+ */
for (n = 0; n < l; n++)
gus_poke (offs++, rec->data.data8[n]);
- rec->parm1 = n; /* Nr of bytes copied */
+ rec->parm1 = n; /*
+ * Nr of bytes copied
+ */
}
return 0;
break;
@@ -2312,6 +2951,9 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
static struct synth_operations guswave_operations =
{
&gus_info,
+#ifdef FUTURE_VERSION
+ 0,
+#endif
SYNTH_TYPE_SAMPLE,
SAMPLE_TYPE_GUS,
guswave_open,
@@ -2326,13 +2968,178 @@ static struct synth_operations guswave_operations =
guswave_aftertouch,
guswave_controller,
guswave_panning,
- guswave_patchmgr
+ guswave_patchmgr,
+#ifdef FUTURE_VERSION
+ guswave_bender
+#endif
+};
+
+static void
+set_input_volumes(void)
+{
+ unsigned long flags;
+ unsigned char mask = 0xff & ~0x06; /* Just line out enabled */
+
+ DISABLE_INTR(flags);
+
+/*
+ * Enable channels having vol > 10%
+ * Note! bit 0x01 means line in DISABLED while 0x04 means
+ * mic in ENABLED.
+ */
+ if (gus_line_vol > 10) mask &= ~0x01;
+ if (gus_mic_vol > 10) mask |= 0x04;
+
+ if (recording_active)
+ {
+/*
+ * Disable channel, if not selected for recording
+ */
+ if (!(gus_recmask & SOUND_MASK_LINE)) mask |= 0x01;
+ if (!(gus_recmask & SOUND_MASK_MIC)) mask &= ~0x04;
+ }
+
+ mix_image &= ~0x07;
+ mix_image |= mask & 0x07;
+ OUTB (mix_image, u_Mixer);
+
+ RESTORE_INTR(flags);
+}
+
+static int
+gus_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
+{
+#define MIX_DEVS (SOUND_MASK_MIC|SOUND_MASK_LINE| \
+ SOUND_MASK_SYNTH|SOUND_MASK_PCM)
+ if (((cmd >> 8) & 0xff) == 'M')
+ {
+ if (cmd & IOC_IN)
+ switch (cmd & 0xff)
+ {
+ case SOUND_MIXER_RECSRC:
+ gus_recmask = IOCTL_IN(arg) & MIX_DEVS;
+ if (!(gus_recmask & (SOUND_MASK_MIC|SOUND_MASK_LINE)))
+ gus_recmask = SOUND_MASK_MIC;
+ /* Note! Input volumes are updated during next open for recording */
+ return IOCTL_OUT (arg, gus_recmask);
+ break;
+
+ case SOUND_MIXER_MIC:
+ {
+ int vol = IOCTL_IN (arg) & 0xff;
+ if (vol < 0) vol = 0;
+ if (vol > 100) vol = 100;
+ gus_mic_vol = vol;
+ set_input_volumes();
+ return IOCTL_OUT (arg, vol | (vol << 8));
+ }
+ break;
+
+ case SOUND_MIXER_LINE:
+ {
+ int vol = IOCTL_IN (arg) & 0xff;
+ if (vol < 0) vol = 0;
+ if (vol > 100) vol = 100;
+ gus_line_vol = vol;
+ set_input_volumes();
+ return IOCTL_OUT (arg, vol | (vol << 8));
+ }
+ break;
+
+ case SOUND_MIXER_PCM:
+ gus_pcm_volume = IOCTL_IN (arg) & 0xff;
+ if (gus_pcm_volume < 0)
+ gus_pcm_volume = 0;
+ if (gus_pcm_volume > 100)
+ gus_pcm_volume = 100;
+ gus_sampling_update_volume ();
+ return IOCTL_OUT (arg, gus_pcm_volume | (gus_pcm_volume << 8));
+ break;
+
+ case SOUND_MIXER_SYNTH:
+ {
+ int voice;
+
+ gus_wave_volume = IOCTL_IN (arg) & 0xff;
+
+ if (gus_wave_volume < 0)
+ gus_wave_volume = 0;
+ if (gus_wave_volume > 100)
+ gus_wave_volume = 100;
+
+ if (active_device == GUS_DEV_WAVE)
+ for (voice = 0; voice < nr_voices; voice++)
+ dynamic_volume_change (voice); /*
+ * Apply the new
+ * volume
+ */
+
+ return IOCTL_OUT (arg, gus_wave_volume | (gus_wave_volume << 8));
+ }
+ break;
+
+ default:
+ return RET_ERROR (EINVAL);
+ }
+ else
+ switch (cmd & 0xff) /*
+ * Return parameters
+ */
+ {
+
+ case SOUND_MIXER_RECSRC:
+ return IOCTL_OUT (arg, gus_recmask);
+ break;
+
+ case SOUND_MIXER_DEVMASK:
+ return IOCTL_OUT (arg, MIX_DEVS);
+ break;
+
+ case SOUND_MIXER_STEREODEVS:
+ return IOCTL_OUT (arg, 0);
+ break;
+
+ case SOUND_MIXER_RECMASK:
+ return IOCTL_OUT (arg, SOUND_MASK_MIC|SOUND_MASK_LINE);
+ break;
+
+ case SOUND_MIXER_CAPS:
+ return IOCTL_OUT (arg, 0);
+ break;
+
+ case SOUND_MIXER_MIC:
+ return IOCTL_OUT (arg, gus_mic_vol | (gus_mic_vol << 8));
+ break;
+
+ case SOUND_MIXER_LINE:
+ return IOCTL_OUT (arg, gus_line_vol | (gus_line_vol << 8));
+ break;
+
+ case SOUND_MIXER_PCM:
+ return IOCTL_OUT (arg, gus_pcm_volume | (gus_pcm_volume << 8));
+ break;
+
+ case SOUND_MIXER_SYNTH:
+ return IOCTL_OUT (arg, gus_wave_volume | (gus_wave_volume << 8));
+ break;
+
+ default:
+ return RET_ERROR (EINVAL);
+ }
+ }
+ else
+ return RET_ERROR (EINVAL);
+}
+
+static struct mixer_operations gus_mixer_operations =
+{
+ gus_mixer_ioctl
};
long
gus_wave_init (long mem_start, int irq, int dma)
{
- printk (" <Gravis UltraSound %dk>", (int)gus_mem_size / 1024);
+ printk (" <Gravis UltraSound %dk>", (int) gus_mem_size / 1024);
if (irq < 0 || irq > 15)
{
@@ -2354,8 +3161,8 @@ gus_wave_init (long mem_start, int irq, int dma)
else
synth_devs[num_synths++] = &guswave_operations;
- PERMANENT_MALLOC(struct patch_info*, samples,
- (MAX_SAMPLE+1)*sizeof(*samples), mem_start);
+ PERMANENT_MALLOC (struct patch_info *, samples,
+ (MAX_SAMPLE + 1) * sizeof (*samples), mem_start);
reset_sample_memory ();
@@ -2372,6 +3179,12 @@ gus_wave_init (long mem_start, int irq, int dma)
else
printk ("GUS: Too many PCM devices available\n");
+ if (num_mixers < MAX_MIXER_DEV) /*
+ * Don't install if there is another
+ * mixer
+ */
+ mixer_devs[num_mixers++] = &gus_mixer_operations;
+
return mem_start;
}
@@ -2386,7 +3199,9 @@ do_loop_irq (int voice)
gus_select_voice (voice);
tmp = gus_read8 (0x00);
- tmp &= ~0x20; /* Disable wave IRQ for this_one voice */
+ tmp &= ~0x20; /*
+ * Disable wave IRQ for this_one voice
+ */
gus_write8 (0x00, tmp);
mode = voices[voice].loop_irq_mode;
@@ -2396,23 +3211,33 @@ do_loop_irq (int voice)
switch (mode)
{
- case LMODE_FINISH: /* Final loop finished, shoot volume down */
+ case LMODE_FINISH: /*
+ * Final loop finished, shoot volume down
+ */
- if ((gus_read16 (0x09) >> 4) < 100) /* Get current volume */
+ if ((gus_read16 (0x09) >> 4) < 100) /*
+ * Get current volume
+ */
{
gus_voice_off ();
gus_rampoff ();
gus_voice_init (voice);
- return;
+ break;
}
gus_ramp_range (65, 4065);
- gus_ramp_rate (0, 63); /* Fastest possible rate */
- gus_rampon (0x20 | 0x40); /* Ramp down, once, irq */
+ gus_ramp_rate (0, 63); /*
+ * Fastest possible rate
+ */
+ gus_rampon (0x20 | 0x40); /*
+ * Ramp down, once, irq
+ */
voices[voice].volume_irq_mode = VMODE_HALT;
break;
case LMODE_PCM_STOP:
- pcm_active = 0; /* Requires extensive processing */
+ pcm_active = 0; /*
+ * Requires extensive processing
+ */
case LMODE_PCM:
{
int orig_qlen = pcm_qlen;
@@ -2424,7 +3249,9 @@ do_loop_irq (int voice)
play_next_pcm_block ();
}
else
- { /* Out of data. Just stop the voice */
+ { /*
+ * Out of data. Just stop the voice
+ */
gus_voice_off ();
gus_rampoff ();
pcm_active = 0;
@@ -2454,7 +3281,9 @@ do_volume_irq (int voice)
gus_select_voice (voice);
tmp = gus_read8 (0x0d);
- tmp &= ~0x20; /* Disable volume ramp IRQ */
+ tmp &= ~0x20; /*
+ * Disable volume ramp IRQ
+ */
gus_write8 (0x0d, tmp);
mode = voices[voice].volume_irq_mode;
@@ -2463,7 +3292,9 @@ do_volume_irq (int voice)
switch (mode)
{
- case VMODE_HALT: /* Decay phase finished */
+ case VMODE_HALT: /*
+ * Decay phase finished
+ */
gus_voice_init (voice);
break;
@@ -2472,6 +3303,19 @@ do_volume_irq (int voice)
step_envelope (voice);
break;
+ case VMODE_START_NOTE:
+ guswave_start_note2 (voices[voice].dev_pending, voice,
+ voices[voice].note_pending, voices[voice].volume_pending);
+ if (voices[voice].kill_pending)
+ guswave_kill_note (voices[voice].dev_pending, voice, 0);
+ if (voices[voice].sample_pending >= 0)
+ {
+ guswave_set_instr (voices[voice].dev_pending, voice,
+ voices[voice].sample_pending);
+ voices[voice].sample_pending = -1;
+ }
+ break;
+
default:;
}
@@ -2488,24 +3332,38 @@ gus_voice_irq (void)
while (1)
{
- src = gus_read8 (0x0f); /* Get source info */
+ src = gus_read8 (0x0f); /*
+ * Get source info
+ */
voice = src & 0x1f;
src &= 0xc0;
if (src == (0x80 | 0x40))
- return; /* No interrupt */
+ return; /*
+ * No interrupt
+ */
voice_bit = 1 << voice;
- if (!(src & 0x80)) /* Wave IRQ pending */
- if (!(wave_ignore & voice_bit) && voice < nr_voices) /* Not done yet */
+ if (!(src & 0x80)) /*
+ * Wave IRQ pending
+ */
+ if (!(wave_ignore & voice_bit) && voice < nr_voices) /*
+ * Not done
+ * yet
+ */
{
wave_ignore |= voice_bit;
do_loop_irq (voice);
}
- if (!(src & 0x40)) /* Volume IRQ pending */
- if (!(volume_ignore & voice_bit) && voice < nr_voices) /* Not done yet */
+ if (!(src & 0x40)) /*
+ * Volume IRQ pending
+ */
+ if (!(volume_ignore & voice_bit) && voice < nr_voices) /*
+ * Not done
+ * yet
+ */
{
volume_ignore |= voice_bit;
do_volume_irq (voice);
@@ -2518,8 +3376,12 @@ guswave_dma_irq (void)
{
unsigned char status;
- status = gus_look8 (0x41); /* Get DMA IRQ Status */
- if (status & 0x40) /* DMA Irq pending */
+ status = gus_look8 (0x41); /*
+ * Get DMA IRQ Status
+ */
+ if (status & 0x40) /*
+ * DMA Irq pending
+ */
switch (active_device)
{
case GUS_DEV_WAVE:
@@ -2543,8 +3405,12 @@ guswave_dma_irq (void)
default:;
}
- status = gus_look8 (0x49); /* Get Sampling IRQ Status */
- if (status & 0x40) /* Sampling Irq pending */
+ status = gus_look8 (0x49); /*
+ * Get Sampling IRQ Status
+ */
+ if (status & 0x40) /*
+ * Sampling Irq pending
+ */
{
DMAbuf_inputintr (gus_devnum);
}
diff --git a/drivers/sound/sb16_dsp.c b/drivers/sound/sb16_dsp.c
index f3f18a1..02040c7 100644
--- a/drivers/sound/sb16_dsp.c
+++ b/drivers/sound/sb16_dsp.c
@@ -256,7 +256,7 @@ DEB(printk("sb16_dsp_open()\n"));
if (!sb16_dsp_ok)
{
printk ("SB16 Error: SoundBlaster board not installed\n");
- return RET_ERROR(ENODEV);
+ return RET_ERROR(ENXIO);
}
if (intr_active)
@@ -459,8 +459,16 @@ sb16_dsp_reset (int dev)
static void
sb16_dsp_halt (int dev)
{
- sb_dsp_command01(0xd9);
- sb_dsp_command01(0xd5);
+ if (dsp_16bit)
+ {
+ sb_dsp_command01(0xd9);
+ sb_dsp_command01(0xd5);
+ }
+ else
+ {
+ sb_dsp_command01(0xda);
+ sb_dsp_command01(0xd0);
+ }
}
static void
diff --git a/drivers/sound/sound_config.h b/drivers/sound/sound_config.h
index a088ff0..1cad333 100644
--- a/drivers/sound/sound_config.h
+++ b/drivers/sound/sound_config.h
@@ -195,7 +195,7 @@ If your card has nonstandard I/O address or IRQ number, change defines
#define OFF 0
#define MAX_DSP_DEV 4
-#define MAX_MIXER_DEV 1
+#define MAX_MIXER_DEV 2
#define MAX_SYNTH_DEV 3
#define MAX_MIDI_DEV 4
diff --git a/drivers/sound/sound_switch.c b/drivers/sound/sound_switch.c
index cf36807..0cc8150 100644
--- a/drivers/sound/sound_switch.c
+++ b/drivers/sound/sound_switch.c
@@ -280,7 +280,7 @@ sound_open_sw (int dev, struct fileinfo *file)
if ((dev >= SND_NDEVS) || (dev < 0))
{
printk ("Invalid minor device %d\n", dev);
- return RET_ERROR (ENODEV);
+ return RET_ERROR (ENXIO);
}
switch (dev & 0x0f)
@@ -320,7 +320,7 @@ sound_open_sw (int dev, struct fileinfo *file)
default:
printk ("Invalid minor device %d\n", dev);
- return RET_ERROR (ENODEV);
+ return RET_ERROR (ENXIO);
}
sbc_devices[dev].usecount++;
@@ -383,12 +383,12 @@ sound_ioctl_sw (int dev, struct fileinfo *file,
case SND_DEV_CTL:
if (!num_mixers)
- return RET_ERROR (ENODEV);
+ return RET_ERROR (ENXIO);
- if (dev >= num_mixers)
- return RET_ERROR (ENODEV);
+ if ((dev >> 4) >= num_mixers)
+ return RET_ERROR (ENXIO);
- return mixer_devs[dev]->ioctl (dev, cmd, arg);
+ return mixer_devs[dev >> 4]->ioctl (dev >> 4, cmd, arg);
break;
case SND_DEV_SEQ:
diff --git a/drivers/sound/soundcard.c b/drivers/sound/soundcard.c
index a41bd9d..ddf7180 100644
--- a/drivers/sound/soundcard.c
+++ b/drivers/sound/soundcard.c
@@ -95,7 +95,7 @@ sound_open (struct inode *inode, struct file *file)
if (!soundcard_configured && dev != SND_DEV_CTL && dev != SND_DEV_STATUS)
{
printk ("SoundCard Error: The soundcard system has not been configured\n");
- return RET_ERROR (ENODEV);
+ return RET_ERROR (ENXIO);
}
files[dev].mode = 0;
diff --git a/fs/open.c b/fs/open.c
index bef97e9..1871392 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -210,6 +210,24 @@ asmlinkage int sys_chdir(const char * filename)
return (0);
}
+asmlinkage int sys_fchdir(unsigned int fd)
+{
+ struct inode * inode;
+ struct file * file;
+
+ if (fd >= NR_OPEN || !(file = current->filp[fd]))
+ return -EBADF;
+ if (!(inode = file->f_inode))
+ return -ENOENT;
+ if (!S_ISDIR(inode->i_mode))
+ return -ENOTDIR;
+ if (!permission(inode,MAY_EXEC))
+ return -EACCES;
+ iput(current->pwd);
+ current->pwd = inode;
+ return (0);
+}
+
asmlinkage int sys_chroot(const char * filename)
{
struct inode * inode;
diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h
index 2fabe9b..6eeee46 100644
--- a/include/linux/if_ether.h
+++ b/include/linux/if_ether.h
@@ -36,6 +36,7 @@
#define ETH_P_IPX 0x8137 /* IPX over DIX */
#define ETH_P_802_3 0x0001 /* Dummy type for 802.3 frames */
#define ETH_P_AX25 0x0002 /* Dummy protocol id for AX.25 */
+#define ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */
/* Define the Ethernet Broadcast Address (48 bits set to "1"). */
#define ETH_A_BCAST "\377\377\377\377\377\377"
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include/linux/kernel_stat.h
diff --git a/include/linux/sbpcd.h b/include/linux/sbpcd.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include/linux/sbpcd.h
diff --git a/include/linux/sys.h b/include/linux/sys.h
index 78d21a0..cb51d7b 100644
--- a/include/linux/sys.h
+++ b/include/linux/sys.h
@@ -143,6 +143,7 @@ extern int sys_delete_module();
extern int sys_get_kernel_syms(); /* 130 */
extern int sys_quotactl();
extern int sys_getpgid();
+extern int sys_fchdir();
/*
* These are system calls that will be removed at some time
diff --git a/include/linux/termios.h b/include/linux/termios.h
index 741c24e..85948ec 100644
--- a/include/linux/termios.h
+++ b/include/linux/termios.h
@@ -237,5 +237,6 @@ struct termios {
#define N_TTY 0
#define N_SLIP 1
#define N_MOUSE 2
+#define N_PPP 3
#endif
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 38fb5d1..12530e7 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -78,8 +78,8 @@ struct serial_struct {
int xmit_fifo_size;
int custom_divisor;
int baud_base;
- char close_delay;
- char reserved_char[3];
+ unsigned short close_delay;
+ char reserved_char[2];
int hub6;
int reserved[5];
};
@@ -97,6 +97,8 @@ struct serial_struct {
/*
* Definitions for async_struct (and serial_struct) flags field
*/
+#define ASYNC_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes
+ on the callout port */
#define ASYNC_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */
#define ASYNC_SAK 0x0004 /* Secure Attention Key (Orange book) */
#define ASYNC_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */
@@ -259,6 +261,9 @@ struct tty_ldisc {
char * buf, int nr);
int (*ioctl)(struct tty_struct * tty, struct file * file,
unsigned int cmd, unsigned long arg);
+ int (*select)(struct tty_struct * tty, struct inode * inode,
+ struct file * file, int sel_type,
+ select_table *wait);
/*
* The following routines are called from below.
*/
diff --git a/include/linux/ultrasound.h b/include/linux/ultrasound.h
index 745e007..40e2443 100644
--- a/include/linux/ultrasound.h
+++ b/include/linux/ultrasound.h
@@ -84,6 +84,7 @@
#define _GUS_VOICEFADE 0x0d
#define _GUS_VOLUME_SCALE 0x0e
#define _GUS_VOICEVOL2 0x0f
+#define _GUS_VOICE_POS 0x10
/*
* GUS API macros
@@ -114,5 +115,7 @@
#define GUS_RAMPON(chn, voice, p1) _GUS_CMD(chn, voice, _GUS_RAMPON, (p1), 0)
#define GUS_RAMPOFF(chn, voice) _GUS_CMD(chn, voice, _GUS_RAMPOFF, 0, 0)
#define GUS_VOLUME_SCALE(chn, voice, p1, p2) _GUS_CMD(chn, voice, _GUS_VOLUME_SCALE, (p1), (p2))
+#define GUS_VOICE_POS(chn, voice, p) _GUS_CMD(chn, voice, _GUS_VOICE_POS, \
+ (p) & 0xffff, ((p) >> 16) & 0xffff)
#endif
diff --git a/include/linux/unistd.h b/include/linux/unistd.h
index 16e05d1..36f4882 100644
--- a/include/linux/unistd.h
+++ b/include/linux/unistd.h
@@ -139,6 +139,7 @@
#define __NR_get_kernel_syms 130
#define __NR_quotactl 131
#define __NR_getpgid 132
+#define __NR_fchdir 133
extern int errno;
diff --git a/kernel/sched.c b/kernel/sched.c
index 034fcbc..5374207 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -138,7 +138,7 @@ sys_wait4, sys_swapoff, sys_sysinfo, sys_ipc, sys_fsync, sys_sigreturn,
sys_clone, sys_setdomainname, sys_newuname, sys_modify_ldt,
sys_adjtimex, sys_mprotect, sys_sigprocmask, sys_create_module,
sys_init_module, sys_delete_module, sys_get_kernel_syms, sys_quotactl,
-sys_getpgid };
+sys_getpgid, sys_fchdir };
/* So we don't have to do any more manual updating.... */
int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);
diff --git a/kernel/signal.c b/kernel/signal.c
index 9616297..a284eea 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -252,7 +252,8 @@ static void setup_frame(struct sigaction * sa, unsigned long ** fp, unsigned lon
if (regs->ss != USER_DS)
frame = (unsigned long *) sa->sa_restorer;
frame -= 32;
- verify_area(VERIFY_WRITE,frame,32*4);
+ if (verify_area(VERIFY_WRITE,frame,32*4))
+ do_exit(SIGSEGV);
/* set up the "normal" stack seen by the signal handler (iBCS2) */
put_fs_long(__CODE,frame);
put_fs_long(signr, frame+1);
diff --git a/kernel/sys.c b/kernel/sys.c
index 4a9a446..1327564 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -495,7 +495,7 @@ asmlinkage int sys_getpgid(pid_t pid)
struct task_struct * p;
if (!pid)
- pid = current->pid;
+ return current->pgrp;
for_each_task(p) {
if (p->pid == pid)
return p->pgrp;
diff --git a/kernel/traps.c b/kernel/traps.c
index 776dff0..d99817e 100644
--- a/kernel/traps.c
+++ b/kernel/traps.c
@@ -95,7 +95,7 @@ asmlinkage void alignment_check(void);
regs->ds, regs->es, regs->fs, regs->gs);
store_TR(i);
printk("Pid: %d, process nr: %d\n", current->pid, 0xffff & i);
- for(i=0;i<10;i++)
+ for(i=0;i<20;i++)
printk("%02x ",0xff & get_seg_byte(regs->cs,(i+(char *)regs->eip)));
printk("\n");
do_exit(SIGSEGV);
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 99845dd..b9cb640 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -53,19 +53,19 @@ static int free_area_pages(unsigned long dindex, unsigned long index, unsigned l
return 0;
page &= PAGE_MASK;
pte = index + (unsigned long *) page;
- for ( ; nr > 0 ; nr--, pte++) {
+ do {
unsigned long pg = *pte;
*pte = 0;
- if (!(pg & PAGE_PRESENT))
- continue;
- free_page(pg);
- }
+ if (pg & PAGE_PRESENT)
+ free_page(pg);
+ pte++;
+ } while (--nr);
pte = (unsigned long *) page;
for (nr = 0 ; nr < 1024 ; nr++, pte++)
if (*pte)
return 0;
set_pgdir(dindex,0);
- mem_map[MAP_NR(page)] &= ~MAP_PAGE_RESERVED;
+ mem_map[MAP_NR(page)] = 1;
free_page(page);
return 0;
}
@@ -83,20 +83,21 @@ static int alloc_area_pages(unsigned long dindex, unsigned long index, unsigned
free_page(page);
page = swapper_pg_dir[dindex];
} else {
- mem_map[MAP_NR(page)] |= MAP_PAGE_RESERVED;
+ mem_map[MAP_NR(page)] = MAP_PAGE_RESERVED;
set_pgdir(dindex, page | PAGE_SHARED);
}
}
page &= PAGE_MASK;
pte = index + (unsigned long *) page;
*pte = PAGE_SHARED; /* remove a race with vfree() */
- for ( ; nr > 0 ; nr--, pte++) {
+ do {
unsigned long pg = get_free_page(GFP_KERNEL);
if (!pg)
return -ENOMEM;
*pte = pg | PAGE_SHARED;
- }
+ pte++;
+ } while (--nr);
return 0;
}
@@ -113,9 +114,9 @@ static int do_area(void * addr, unsigned long size,
if (i > nr)
i = nr;
+ nr -= i;
if (area_fn(dindex, index, i))
return -1;
- nr -= i;
index = 0;
dindex++;
}
diff --git a/net/inet/dev.c b/net/inet/dev.c
index 159e8c4..22002f0 100644
--- a/net/inet/dev.c
+++ b/net/inet/dev.c
@@ -114,8 +114,12 @@ static struct packet_type arp_packet_type = {
&ax25_packet_type
#endif
#else
+#ifdef CONFIG_AX25
+ &ax25_packet_type
+#else
NULL /* next */
#endif
+#endif
};
@@ -287,22 +291,49 @@ my_addr(void)
}
+static int dev_nit=0; /* Number of network taps running */
+
/* Add a protocol ID to the list. This will change soon. */
void
dev_add_pack(struct packet_type *pt)
{
struct packet_type *p1;
-
pt->next = ptype_base;
- /* See if we need to copy it. */
- for (p1 = ptype_base; p1 != NULL; p1 = p1->next) {
- if (p1->type == pt->type) {
- pt->copy = 1;
- break;
+ /* Don't use copy counts on ETH_P_ALL. Instead keep a global
+ count of number of these and use it and pt->copy to decide
+ copies */
+ pt->copy=0;
+ if(pt->type==NET16(ETH_P_ALL))
+ dev_nit++; /* I'd like a /dev/nit too one day 8) */
+ else
+ {
+ /* See if we need to copy it. */
+ for (p1 = ptype_base; p1 != NULL; p1 = p1->next) {
+ if (p1->type == pt->type) {
+ pt->copy = 1;
+ break;
+ }
+ }
+ }
+
+ /*
+ * NIT taps must go at the end or inet_bh will leak!
+ */
+
+ if(pt->type==NET16(ETH_P_ALL))
+ {
+ pt->next=NULL;
+ if(ptype_base==NULL)
+ ptype_base=pt;
+ else
+ {
+ for(p1=ptype_base;p1->next!=NULL;p1=p1->next);
+ p1->next=pt;
}
}
- ptype_base = pt;
+ else
+ ptype_base = pt;
}
@@ -312,6 +343,8 @@ dev_remove_pack(struct packet_type *pt)
{
struct packet_type *lpt, *pt1;
+ if (pt->type == NET16(ETH_P_ALL))
+ dev_nit--;
if (pt == ptype_base) {
ptype_base = pt->next;
return;
@@ -328,7 +361,7 @@ dev_remove_pack(struct packet_type *pt)
return;
}
- if (pt1->next -> type == pt ->type) {
+ if (pt1->next -> type == pt ->type && pt->type != NET16(ETH_P_ALL)) {
lpt = pt1->next;
}
}
@@ -594,7 +627,7 @@ inet_bh(void *tmp)
struct packet_type *ptype;
unsigned short type;
unsigned char flag = 0;
-
+ int nitcount;
/* Atomically check and mark our BUSY state. */
if (set_bit(1, (void*)&in_bh))
@@ -606,6 +639,7 @@ inet_bh(void *tmp)
/* Any data left to process? */
while((skb=skb_dequeue(&backlog))!=NULL)
{
+ nitcount=dev_nit;
flag=0;
sti();
/*
@@ -625,7 +659,6 @@ inet_bh(void *tmp)
* header (the h_proto field in struct ethhdr), but drivers like
* SLIP and PLIP have no alternative but to force the type to be
* IP or something like that. Sigh- FvK
- * FIXME: Ethernet drivers need potty training in 802.3 packets -AC
*/
type = skb->dev->type_trans(skb, skb->dev);
@@ -636,10 +669,12 @@ inet_bh(void *tmp)
* to anyone who wants it.
*/
for (ptype = ptype_base; ptype != NULL; ptype = ptype->next) {
- if (ptype->type == type) {
+ if (ptype->type == type || ptype->type == NET16(ETH_P_ALL)) {
struct sk_buff *skb2;
- if (ptype->copy) { /* copy if we need to */
+ if (ptype->type==NET16(ETH_P_ALL))
+ nitcount--;
+ if (ptype->copy || nitcount) { /* copy if we need to */
skb2 = alloc_skb(skb->mem_len, GFP_ATOMIC);
if (skb2 == NULL)
continue;
diff --git a/net/inet/ip.c b/net/inet/ip.c
index ea1877b..4cd04a4 100644
--- a/net/inet/ip.c
+++ b/net/inet/ip.c
@@ -1544,7 +1544,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
sk->ip_tos=val;
return 0;
case IP_TTL:
- if(val<1||val<255)
+ if(val<1||val>255)
return -EINVAL;
sk->ip_ttl=val;
return 0;
diff --git a/net/inet/raw.c b/net/inet/raw.c
index 72a4702..3e44d19 100644
--- a/net/inet/raw.c
+++ b/net/inet/raw.c
@@ -114,7 +114,8 @@ raw_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
/* Now we need to copy this into memory. */
skb->sk = sk;
- skb->len = len;
+ skb->len = len + skb->ip_hdr->ihl*sizeof(long);
+ skb->h.raw = skb->ip_hdr;
skb->dev = dev;
skb->saddr = daddr;
skb->daddr = saddr;
diff --git a/net/inet/sock.c b/net/inet/sock.c
index 1781697..d21791d 100644
--- a/net/inet/sock.c
+++ b/net/inet/sock.c
@@ -51,6 +51,7 @@
* Alan Cox : inet sockets don't set sk->type!
* Alan Cox : Split socket option code
* Alan Cox : Callbacks
+ * Alan Cox : Nagle flag for Charles & Johannes stuff
*
* To Fix:
*
@@ -824,6 +825,11 @@ inet_create(struct socket *sock, int protocol)
return(-ESOCKTNOSUPPORT);
}
sk->socket = sock;
+#ifdef CONFIG_TCP_NAGLE_OFF
+ sk->nonagle = 1;
+#else
+ sk->nonagle = 0;
+#endif
sk->type = sock->type;
sk->protocol = protocol;
sk->wmem_alloc = 0;
@@ -1792,6 +1798,8 @@ inet_fioctl(struct inode *inode, struct file *file,
}
+
+
static struct file_operations inet_fops = {
NULL, /* LSEEK */
NULL, /* READ */
diff --git a/net/inet/sock.h b/net/inet/sock.h
index cf8397a..56c3fd8 100644
--- a/net/inet/sock.h
+++ b/net/inet/sock.h
@@ -81,7 +81,8 @@ struct sock {
no_check,
exp_growth,
zapped, /* In ax25 & ipx means not linked */
- broadcast;
+ broadcast,
+ nonagle;
unsigned long lingertime;
int proc;
struct sock *next;
diff --git a/net/inet/tcp.c b/net/inet/tcp.c
index ade26c8..944f156 100644
--- a/net/inet/tcp.c
+++ b/net/inet/tcp.c
@@ -57,6 +57,8 @@
* Alan Cox : Added tcp_select_window() aka NET2E
* window non shrink trick.
* Alan Cox : Added a couple of small NET2E timer fixes
+ * Charles Hedrick : TCP fixes
+ * Toomas Tamm : TCP window fixes
*
*
* To Fix:
@@ -99,8 +101,6 @@
#include <asm/segment.h>
#include <linux/mm.h>
-#define USE_NAGLE
-
#define SEQ_TICK 3
unsigned long seq_offset;
@@ -1018,20 +1018,17 @@ tcp_write(struct sock *sk, unsigned char *from,
sk->err = 0;
/*
- * In its original form, the following code implements
- * Nagle's rule. Everybody recommends it, and probably
- * production code should use it. But it slows down response enough
- * that I dont' like it. So as long as we're not bumping into
- * the window, I go ahead and send it. If you want Nagle, just
- * define USE_NAGLE --C. Hedrick
+ * Nagles rule. Turn Nagle off with TCP_NODELAY for highly
+ * interactive fast network servers. It's meant to be on and
+ * it really improves the throughput though not the echo time
+ * on my slow slip link - Alan
*/
/* Avoid possible race on send_tmp - c/o Johannes Stille */
if(sk->send_tmp &&
((!sk->packets_out)
-#ifndef USE_NAGLE
- || before(sk->send_seq , sk->window_seq)
-#endif
+ /* If not nagling we can send on the before case too.. */
+ || (sk->nonagle && before(sk->send_seq , sk->window_seq))
))
tcp_send_partial(sk);
/* -- */
@@ -1273,7 +1270,6 @@ tcp_read_urg(struct sock * sk, int nonblock,
amt = min(ntohs(skb->h.th->urg_ptr),len);
if(amt)
{
- verify_area(VERIFY_WRITE, to, amt);
memcpy_tofs(to,(unsigned char *)(skb->h.th) +
skb->h.th->doff*4, amt);
}
@@ -2132,7 +2128,7 @@ tcp_write_xmit(struct sock *sk)
return;
while(sk->wfront != NULL &&
- before(sk->wfront->h.seq, sk->window_seq) &&
+ before(sk->wfront->h.seq, sk->window_seq +1) &&
(sk->retransmits == 0 ||
sk->timeout != TIME_WRITE ||
before(sk->wfront->h.seq, sk->rcv_ack_seq +1))
@@ -2395,7 +2391,7 @@ tcp_ack(struct sock *sk, struct tcphdr *th, unsigned long saddr, int len)
* and put it onto the xmit queue.
*/
if (sk->wfront != NULL) {
- if (after (sk->window_seq, sk->wfront->h.seq) &&
+ if (after (sk->window_seq+1, sk->wfront->h.seq) &&
(sk->retransmits == 0 ||
sk->timeout != TIME_WRITE ||
before(sk->wfront->h.seq, sk->rcv_ack_seq +1))
@@ -3534,12 +3530,12 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char *optval, int op
switch(optname)
{
case TCP_MSS:
- if(val<200||val>2048)
+ if(val<200||val>2048 || val>sk->mtu)
return -EINVAL;
sk->mss=val;
return 0;
case TCP_NODELAY:
- /* Ready for Johannes delayed ACK code */
+ sk->nonagle=(val==0)?0:1;
return 0;
default:
return(-ENOPROTOOPT);
@@ -3559,7 +3555,7 @@ int tcp_getsockopt(struct sock *sk, int level, int optname, char *optval, int *o
val=sk->mss;
break;
case TCP_NODELAY:
- val=1; /* Until Johannes stuff is in */
+ val=sk->nonagle; /* Until Johannes stuff is in */
break;
default:
return(-ENOPROTOOPT);
diff --git a/net/inet/tcp.h b/net/inet/tcp.h
index cb051e4..4aae2a3 100644
--- a/net/inet/tcp.h
+++ b/net/inet/tcp.h
@@ -71,47 +71,27 @@
/*
* The next routines deal with comparing 32 bit unsigned ints
- * and worry about wraparound. The general strategy is to do a
- * normal compare so long as neither of the numbers is within
- * 4K of wrapping. Otherwise we must check for the wrap.
+ * and worry about wraparound (automatic with unsigned arithmetic).
*/
-static inline int
-before (unsigned long seq1, unsigned long seq2)
+static inline int before(unsigned long seq1, unsigned long seq2)
{
- /* this inequality is strict. */
- if (seq1 == seq2) return(0);
-
- if (seq1 < seq2) {
- if ((unsigned long)seq2-(unsigned long)seq1 < 65536UL) {
- return(1);
- } else {
- return(0);
- }
- }
-
- /*
- * Now we know seq1 > seq2. So all we need to do is check
- * to see if seq1 has wrapped.
- */
- if (seq2 < 8192UL && seq1 > (0xffffffffUL - 8192UL)) {
- return(1);
- }
- return(0);
+ /* this inequality is strict. */
+ if (seq1 == seq2)
+ return 0;
+ seq2 -= seq1;
+ return (seq2 < 65536);
}
-
-static inline int
-after(unsigned long seq1, unsigned long seq2)
+static inline int after(unsigned long seq1, unsigned long seq2)
{
- return(before(seq2, seq1));
+ return before(seq2, seq1);
}
/* is s2<=s1<=s3 ? */
-static inline int
-between(unsigned long seq1, unsigned long seq2, unsigned long seq3)
+static inline int between(unsigned long seq1, unsigned long seq2, unsigned long seq3)
{
- return(after(seq1+1, seq2) && before(seq1, seq3+1));
+ return (after(seq1+1, seq2) && before(seq1, seq3+1));
}