summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--drivers/isdn/isdn_net.c2
-rw-r--r--drivers/pnp/parport_procfs.c2
-rw-r--r--drivers/pnp/parport_share.c1
-rw-r--r--drivers/scsi/README.st42
-rw-r--r--drivers/scsi/st.c165
-rw-r--r--drivers/scsi/st.h3
-rw-r--r--drivers/scsi/st_options.h8
-rw-r--r--drivers/sound/.version4
-rw-r--r--drivers/sound/CHANGELOG10
-rw-r--r--drivers/sound/Config.in2
-rw-r--r--drivers/sound/Config.std2
-rw-r--r--drivers/sound/Makefile28
-rw-r--r--drivers/sound/Readme8
-rw-r--r--drivers/sound/Readme.cards74
-rw-r--r--drivers/sound/Readme.linux177
-rw-r--r--drivers/sound/ad1848.c186
-rw-r--r--drivers/sound/ad1848_mixer.h119
-rw-r--r--drivers/sound/audio.c191
-rw-r--r--drivers/sound/configure.c2
-rw-r--r--drivers/sound/dev_table.c24
-rw-r--r--drivers/sound/dev_table.h41
-rw-r--r--drivers/sound/dmabuf.c510
-rw-r--r--drivers/sound/gus_card.c2
-rw-r--r--drivers/sound/gus_midi.c1
-rw-r--r--drivers/sound/gus_wave.c274
-rw-r--r--drivers/sound/lowlevel/Config.tmpl2
-rw-r--r--drivers/sound/lowlevel/aci.c4
-rw-r--r--drivers/sound/maui.c2
-rw-r--r--drivers/sound/midi_synth.c2
-rw-r--r--drivers/sound/midibuf.c1
-rw-r--r--drivers/sound/mpu401.c1
-rw-r--r--drivers/sound/opl3.c2
-rw-r--r--drivers/sound/os.h6
-rw-r--r--drivers/sound/pas2_card.c2
-rw-r--r--drivers/sound/pas2_midi.c1
-rw-r--r--drivers/sound/pas2_pcm.c4
-rw-r--r--drivers/sound/sb.h1
-rw-r--r--drivers/sound/sb_common.c37
-rw-r--r--drivers/sound/sb_midi.c13
-rw-r--r--drivers/sound/sequencer.c38
-rw-r--r--drivers/sound/sound_calls.h18
-rw-r--r--drivers/sound/sound_switch.c13
-rw-r--r--drivers/sound/soundcard.c121
-rw-r--r--drivers/sound/soundvers.h4
-rw-r--r--drivers/sound/sscape.c110
-rw-r--r--drivers/sound/trix.c10
-rw-r--r--drivers/sound/uart401.c1
-rw-r--r--drivers/sound/uart6850.c1
-rw-r--r--drivers/sound/ulaw.h128
-rw-r--r--fs/autofs/autofs_i.h14
-rw-r--r--fs/autofs/inode.c1
-rw-r--r--fs/autofs/root.c25
-rw-r--r--fs/autofs/waitq.c44
-rw-r--r--fs/nfs/write.c2
-rw-r--r--fs/proc/array.c12
-rw-r--r--include/linux/.cvsignore1
-rw-r--r--include/linux/mtio.h4
-rw-r--r--include/linux/soundcard.h27
-rw-r--r--kernel/exit.c15
-rw-r--r--mm/page_alloc.c1
-rw-r--r--mm/slab.c1
-rw-r--r--mm/vmscan.c18
63 files changed, 1473 insertions, 1094 deletions
diff --git a/Makefile b/Makefile
index b4a619f7f..3705b42b1 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 2
PATCHLEVEL = 1
-SUBLEVEL = 40
+SUBLEVEL = 41
ARCH = mips
diff --git a/drivers/isdn/isdn_net.c b/drivers/isdn/isdn_net.c
index b6b076360..7d7bdad8d 100644
--- a/drivers/isdn/isdn_net.c
+++ b/drivers/isdn/isdn_net.c
@@ -374,7 +374,7 @@ isdn_net_stat_callback(int idx, int cmd)
return 1;
}
}
- if (clear_bit(0, (void *) &(p->dev.tbusy)))
+ if (test_and_clear_bit(0, (void *) &(p->dev.tbusy)))
mark_bh(NET_BH);
}
return 1;
diff --git a/drivers/pnp/parport_procfs.c b/drivers/pnp/parport_procfs.c
index 896abbdd4..77574991b 100644
--- a/drivers/pnp/parport_procfs.c
+++ b/drivers/pnp/parport_procfs.c
@@ -16,10 +16,10 @@
#include <linux/config.h>
#include <linux/delay.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/malloc.h>
+#include <linux/interrupt.h>
#include <linux/proc_fs.h>
diff --git a/drivers/pnp/parport_share.c b/drivers/pnp/parport_share.c
index fc19fffd4..9b854f138 100644
--- a/drivers/pnp/parport_share.c
+++ b/drivers/pnp/parport_share.c
@@ -220,6 +220,7 @@ struct ppd *parport_register_device(struct parport *port, const char *name,
tmp->preempt = pf;
tmp->wakeup = kf;
tmp->private = handle;
+ tmp->flags = flags;
tmp->irq_func = irq_func;
tmp->ctr = port->ctr;
tmp->ecr = port->ecr;
diff --git a/drivers/scsi/README.st b/drivers/scsi/README.st
index fc3ff8e39..06d2c71df 100644
--- a/drivers/scsi/README.st
+++ b/drivers/scsi/README.st
@@ -2,7 +2,7 @@ This file contains brief information about the SCSI tape driver.
The driver is currently maintained by Kai M{kisara (email
Kai.Makisara@metla.fi)
-Last modified: Wed Jan 1 15:44:49 1997 by makisara@kai.makisara.fi
+Last modified: Tue May 27 22:29:24 1997 by makisara@home
BASICS
@@ -159,6 +159,15 @@ where
buffers is bounded also by the number of drives detected)
+MODULE PARAMETERS
+
+The same parameters can be also set when the driver is loaded as a
+module. The keywords are:
+
+buffer_kbs=xxx the buffer size in kilobytes is set to xxx
+write_threshold_kbs=xxx the write threshold in kilobytes set to xxx
+max_buffers=xxx the maximum number of tape buffer set to xxx
+
IOCTLS
The tape is positioned and the drive parameters are set with ioctls
@@ -253,6 +262,7 @@ MTSETDRVBUFFER
the device dependent address. It is recommended to set
this flag unless there are tapes using the device
dependent (from the old times) (global)
+ MT_ST_SYSV sets the SYSV sematics (mode)
MT_ST_DEBUGGING debugging (global; debugging must be
compiled into the driver)
MT_ST_SETBOOLEANS
@@ -272,6 +282,16 @@ MTSETDRVBUFFER
MT_ST_CLEAR_DEFAULT (0xfffff), the default will not be used
any more. Otherwise the lower-most bits of the value contain
the new value of the parameter.
+ MT_ST_SET_TIMEOUT
+ Set the normal timeout in seconds for this device. The
+ default is 900 seconds (15 minutes). The timeout should be
+ long enough for the retries done by the device while
+ reading/writing.
+ MT_ST_SET_LONG_TIMEOUT
+ Set the long timeout that is used for operations that are
+ known to take a long time. The default is 14000 seconds
+ (3.9 hours). For erase this value is further multiplied by
+ eight.
The following ioctl uses the structure mtpos:
MTIOCPOS Reads the current position from the drive. Uses
@@ -331,3 +351,23 @@ within file can be obtained if ST_IN_FILE_POS is defined at compile
time or the MT_ST_CAN_BSR bit is set for the drive with an ioctl.
(The driver always backs over a filemark crossed by read ahead if the
user does not request data that far.)
+
+
+DEBUGGING HINTS
+
+To enable debugging messages, edit st.c and #define DEBUG 1. As seen
+above, debugging can be switched off with an ioctl if debugging is
+compiled into the driver. The debugging output is not not voluminuous.
+
+If the tape seems to hang, I would be very interested to hear where
+the driver is waiting. With the command 'ps -l' you can see the state
+of the process using the tape. If the state is D, the process is
+waiting for something. The field WCHAN tells where the driver is
+waiting. If you have the current System.map in the correct place (in
+/boot for the procps I use) or have updated /etc/psdatabase (for kmem
+ps), ps writes the function name in the WCHAN field. If not, you have
+to look up the function from System.map.
+
+Note also that the timeouts are very long compared to most other
+drivers. This means that the Linux driver may appear hung although the
+real reason is that the tape firmware has got confused.
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 339ba6714..07fa2bf58 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -11,7 +11,7 @@
Copyright 1992 - 1997 Kai Makisara
email Kai.Makisara@metla.fi
- Last modified: Wed Jan 1 15:26:54 1997 by makisara@kai.makisara.fi
+ Last modified: Tue May 27 22:29:00 1997 by makisara@home
Some small formal changes - aeb, 950809
*/
@@ -21,6 +21,7 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/init.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/mtio.h>
@@ -48,14 +49,23 @@
#include "st.h"
#include "constants.h"
+#ifdef MODULE
+MODULE_PARM(buffer_kbs, "i");
+MODULE_PARM(write_threshold_kbs, "i");
+MODULE_PARM(max_buffers, "i");
+static int buffer_kbs = 0;
+static int write_threshold_kbs = 0;
+static int max_buffers = 0;
+#endif
+
/* The default definitions have been moved to st_options.h */
-#define ST_BLOCK_SIZE 1024
+#define ST_KILOBYTE 1024
#include "st_options.h"
-#define ST_BUFFER_SIZE (ST_BUFFER_BLOCKS * ST_BLOCK_SIZE)
-#define ST_WRITE_THRESHOLD (ST_WRITE_THRESHOLD_BLOCKS * ST_BLOCK_SIZE)
+#define ST_BUFFER_SIZE (ST_BUFFER_BLOCKS * ST_KILOBYTE)
+#define ST_WRITE_THRESHOLD (ST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
/* The buffer size should fit into the 24 bits for length in the
6-byte SCSI read and write commands. */
@@ -220,6 +230,7 @@ st_sleep_done (Scsi_Cmnd * SCpnt)
}
else
(STp->buffer)->last_result = SCpnt->result;
+#if 0
if ((STp->buffer)->writing) {
/* Process errors before releasing request */
(STp->buffer)->last_result_fatal = st_chk_result(SCpnt);
@@ -227,6 +238,10 @@ st_sleep_done (Scsi_Cmnd * SCpnt)
}
else
SCpnt->request.rq_status = RQ_SCSI_DONE;
+#else
+ SCpnt->request.rq_status = RQ_SCSI_DONE;
+ (STp->buffer)->last_SCpnt = SCpnt;
+#endif
#if DEBUG
STp->write_pending = 0;
@@ -286,6 +301,9 @@ write_behind_check(Scsi_Tape *STp)
down(&(STp->sem));
+ (STp->buffer)->last_result_fatal = st_chk_result((STp->buffer)->last_SCpnt);
+ ((STp->buffer)->last_SCpnt)->request.rq_status = RQ_INACTIVE;
+
if (STbuffer->writing < STbuffer->buffer_bytes)
memcpy(STbuffer->b_data,
STbuffer->b_data + STbuffer->writing,
@@ -327,7 +345,7 @@ cross_eof(Scsi_Tape *STp, int forward)
TAPE_NR(STp->devt), forward ? "forward" : "backward");
#endif
- SCpnt = st_do_scsi(NULL, STp, cmd, 0, ST_TIMEOUT, MAX_RETRIES);
+ SCpnt = st_do_scsi(NULL, STp, cmd, 0, STp->timeout, MAX_RETRIES);
if (!SCpnt)
return (-EBUSY);
@@ -387,7 +405,7 @@ flush_write_buffer(Scsi_Tape *STp)
cmd[3] = blks >> 8;
cmd[4] = blks;
- SCpnt = st_do_scsi(NULL, STp, cmd, transfer, ST_TIMEOUT, MAX_WRITE_RETRIES);
+ SCpnt = st_do_scsi(NULL, STp, cmd, transfer, STp->timeout, MAX_WRITE_RETRIES);
if (!SCpnt)
return (-EBUSY);
@@ -594,7 +612,7 @@ scsi_tape_open(struct inode * inode, struct file * filp)
memset ((void *) &cmd[0], 0, 10);
cmd[0] = TEST_UNIT_READY;
- SCpnt = st_do_scsi(NULL, STp, cmd, 0, ST_LONG_TIMEOUT, MAX_READY_RETRIES);
+ SCpnt = st_do_scsi(NULL, STp, cmd, 0, STp->long_timeout, MAX_READY_RETRIES);
if (!SCpnt) {
if (scsi_tapes[dev].device->host->hostt->module)
__MOD_DEC_USE_COUNT(scsi_tapes[dev].device->host->hostt->module);
@@ -608,7 +626,7 @@ scsi_tape_open(struct inode * inode, struct file * filp)
memset ((void *) &cmd[0], 0, 10);
cmd[0] = TEST_UNIT_READY;
- SCpnt = st_do_scsi(SCpnt, STp, cmd, 0, ST_LONG_TIMEOUT, MAX_READY_RETRIES);
+ SCpnt = st_do_scsi(SCpnt, STp, cmd, 0, STp->long_timeout, MAX_READY_RETRIES);
(STp->device)->was_reset = 0;
STp->partition = STp->new_partition = 0;
@@ -649,7 +667,7 @@ scsi_tape_open(struct inode * inode, struct file * filp)
memset ((void *) &cmd[0], 0, 10);
cmd[0] = READ_BLOCK_LIMITS;
- SCpnt = st_do_scsi(SCpnt, STp, cmd, 6, ST_TIMEOUT, MAX_READY_RETRIES);
+ SCpnt = st_do_scsi(SCpnt, STp, cmd, 6, STp->timeout, MAX_READY_RETRIES);
if (!SCpnt->result && !SCpnt->sense_buffer[0]) {
STp->max_block = ((STp->buffer)->b_data[1] << 16) |
@@ -675,7 +693,7 @@ scsi_tape_open(struct inode * inode, struct file * filp)
cmd[0] = MODE_SENSE;
cmd[4] = 12;
- SCpnt = st_do_scsi(SCpnt, STp, cmd, 12, ST_TIMEOUT, MAX_READY_RETRIES);
+ SCpnt = st_do_scsi(SCpnt, STp, cmd, 12, STp->timeout, MAX_READY_RETRIES);
if ((STp->buffer)->last_result_fatal != 0) {
#if DEBUG
@@ -807,7 +825,7 @@ scsi_tape_open(struct inode * inode, struct file * filp)
static int
scsi_tape_close(struct inode * inode, struct file * filp)
{
- int result;
+ int result = 0, result2;
static unsigned char cmd[10];
Scsi_Cmnd * SCpnt;
Scsi_Tape * STp;
@@ -823,7 +841,7 @@ scsi_tape_close(struct inode * inode, struct file * filp)
STps = &(STp->ps[STp->partition]);
if (STp->can_partitions &&
- update_partition(inode) < 0) {
+ (result = update_partition(inode)) < 0) {
#if DEBUG
if (debugging)
printk(ST_DEB_MSG "st%d: update_partition at close failed.\n", dev);
@@ -850,7 +868,7 @@ scsi_tape_close(struct inode * inode, struct file * filp)
cmd[0] = WRITE_FILEMARKS;
cmd[4] = 1 + STp->two_fm;
- SCpnt = st_do_scsi(NULL, STp, cmd, 0, ST_TIMEOUT, MAX_WRITE_RETRIES);
+ SCpnt = st_do_scsi(NULL, STp, cmd, 0, STp->timeout, MAX_WRITE_RETRIES);
if (!SCpnt)
goto out;
@@ -862,8 +880,12 @@ scsi_tape_close(struct inode * inode, struct file * filp)
((SCpnt->sense_buffer[0] & 0x80) != 0 &&
(SCpnt->sense_buffer[3] | SCpnt->sense_buffer[4] |
SCpnt->sense_buffer[5] |
- SCpnt->sense_buffer[6]) == 0))) /* Filter out successful write at EOM */
- printk(KERN_ERR "st%d: Error on write filemark.\n", dev);
+ SCpnt->sense_buffer[6]) == 0))) {
+ /* Filter out successful write at EOM */
+ printk(KERN_ERR "st%d: Error on write filemark.\n", dev);
+ if (result == 0)
+ result = (-EIO);
+ }
else {
if (STps->drv_file >= 0)
STps->drv_file++ ;
@@ -884,9 +906,10 @@ scsi_tape_close(struct inode * inode, struct file * filp)
STps = &(STp->ps[STp->partition]);
if (!STm->sysv || STps->rw != ST_READING) {
if (STp->can_bsr)
- flush_buffer(inode, filp, 0);
+ result = flush_buffer(inode, filp, 0);
else if (STps->eof == ST_FM_HIT) {
- if (cross_eof(STp, FALSE)) {
+ result = cross_eof(STp, FALSE);
+ if (result) {
if (STps->drv_file >= 0)
STps->drv_file++;
STps->drv_block = 0;
@@ -896,7 +919,8 @@ scsi_tape_close(struct inode * inode, struct file * filp)
STps->eof = ST_NOEOF;
}
}
- else if ((STps->eof == ST_NOEOF && !cross_eof(STp, TRUE)) ||
+ else if ((STps->eof == ST_NOEOF &&
+ !(result = cross_eof(STp, TRUE))) ||
STps->eof == ST_FM_HIT) {
if (STps->drv_file >= 0)
STps->drv_file++;
@@ -906,8 +930,11 @@ scsi_tape_close(struct inode * inode, struct file * filp)
}
out:
- if (STp->rew_at_close)
- st_int_ioctl(inode, MTREW, 1);
+ if (STp->rew_at_close) {
+ result2 = st_int_ioctl(inode, MTREW, 1);
+ if (result == 0)
+ result = result2;
+ }
if (STp->door_locked == ST_LOCKED_AUTO)
st_int_ioctl(inode, MTUNLOCK, 0);
@@ -923,7 +950,7 @@ out:
if(st_template.module)
__MOD_DEC_USE_COUNT(st_template.module);
- return 0;
+ return result;
}
@@ -1083,7 +1110,7 @@ st_write(struct inode * inode, struct file * filp, const char * buf,
cmd[3] = blks >> 8;
cmd[4] = blks;
- SCpnt = st_do_scsi(SCpnt, STp, cmd, transfer, ST_TIMEOUT, MAX_WRITE_RETRIES);
+ SCpnt = st_do_scsi(SCpnt, STp, cmd, transfer, STp->timeout, MAX_WRITE_RETRIES);
if (!SCpnt)
return (-EBUSY);
@@ -1177,7 +1204,8 @@ st_write(struct inode * inode, struct file * filp, const char * buf,
}
if (STm->do_async_writes &&
- ((STp->buffer)->buffer_bytes >= STp->write_threshold ||
+ (((STp->buffer)->buffer_bytes >= STp->write_threshold &&
+ (STp->buffer)->buffer_bytes >= STp->block_size) ||
STp->block_size == 0) ) {
/* Schedule an asynchronous write */
if (!SCpnt) {
@@ -1211,7 +1239,7 @@ st_write(struct inode * inode, struct file * filp, const char * buf,
scsi_do_cmd (SCpnt,
(void *) cmd, (STp->buffer)->b_data,
(STp->buffer)->writing,
- st_sleep_done, ST_TIMEOUT, MAX_WRITE_RETRIES);
+ st_sleep_done, STp->timeout, MAX_WRITE_RETRIES);
}
else if (SCpnt != NULL)
SCpnt->request.rq_status = RQ_INACTIVE; /* Mark as not busy */
@@ -1270,7 +1298,7 @@ read_tape(struct inode *inode, long count, Scsi_Cmnd **aSCpnt)
cmd[4] = blks;
SCpnt = *aSCpnt;
- SCpnt = st_do_scsi(SCpnt, STp, cmd, bytes, ST_TIMEOUT, MAX_RETRIES);
+ SCpnt = st_do_scsi(SCpnt, STp, cmd, bytes, STp->timeout, MAX_RETRIES);
*aSCpnt = SCpnt;
if (!SCpnt)
return (-EBUSY);
@@ -1572,6 +1600,8 @@ st_log_options(Scsi_Tape *STp, ST_mode *STm, int dev)
"st%d: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
dev, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
STp->scsi2_logical);
+ printk(KERN_INFO
+"st%d: sysv: %d\n", dev, STm->sysv);
#if DEBUG
printk(KERN_INFO
"st%d: debugging: %d\n",
@@ -1615,6 +1645,7 @@ st_set_options(struct inode * inode, long options)
if ((STp->device)->scsi_level >= SCSI_2)
STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
+ STm->sysv = (options & MT_ST_SYSV) != 0;
#if DEBUG
debugging = (options & MT_ST_DEBUGGING) != 0;
#endif
@@ -1645,6 +1676,8 @@ st_set_options(struct inode * inode, long options)
STp->can_partitions = value;
if ((options & MT_ST_SCSI2LOGICAL) != 0)
STp->scsi2_logical = value;
+ if ((options & MT_ST_SYSV) != 0)
+ STm->sysv = value;
#if DEBUG
if ((options & MT_ST_DEBUGGING) != 0)
debugging = value;
@@ -1652,7 +1685,7 @@ st_set_options(struct inode * inode, long options)
st_log_options(STp, STm, dev);
}
else if (code == MT_ST_WRITE_THRESHOLD) {
- value = (options & ~MT_ST_OPTIONS) * ST_BLOCK_SIZE;
+ value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE;
if (value < 1 || value > st_buffer_size) {
printk(KERN_WARNING "st%d: Write threshold %d too small or too large.\n",
dev, value);
@@ -1674,6 +1707,19 @@ st_set_options(struct inode * inode, long options)
dev, STm->default_blksize);
}
}
+ else if (code == MT_ST_TIMEOUTS) {
+ value = (options & ~MT_ST_OPTIONS);
+ if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
+ STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
+ printk(KERN_INFO "st%d: Long timeout set to %d seconds.\n", dev,
+ (value & ~MT_ST_SET_LONG_TIMEOUT));
+ }
+ else {
+ STp->timeout = value * HZ;
+ printk(KERN_INFO "st%d: Normal timeout set to %d seconds.\n", dev,
+ value);
+ }
+ }
else if (code == MT_ST_DEF_OPTIONS) {
code = (options & ~MT_ST_CLEAR_DEFAULT);
value = (options & MT_ST_CLEAR_DEFAULT);
@@ -1746,7 +1792,7 @@ st_compression(Scsi_Tape * STp, int state)
cmd[2] = COMPRESSION_PAGE;
cmd[4] = COMPRESSION_PAGE_LENGTH + MODE_HEADER_LENGTH;
- SCpnt = st_do_scsi(SCpnt, STp, cmd, cmd[4], ST_TIMEOUT, 0);
+ SCpnt = st_do_scsi(SCpnt, STp, cmd, cmd[4], STp->timeout, 0);
if (SCpnt == NULL)
return (-EBUSY);
dev = TAPE_NR(SCpnt->request.rq_dev);
@@ -1789,7 +1835,7 @@ st_compression(Scsi_Tape * STp, int state)
(STp->buffer)->b_data[0] = 0; /* Reserved data length */
(STp->buffer)->b_data[1] = 0; /* Reserved media type byte */
(STp->buffer)->b_data[MODE_HEADER_LENGTH] &= 0x3f;
- SCpnt = st_do_scsi(SCpnt, STp, cmd, cmd[4], ST_TIMEOUT, 0);
+ SCpnt = st_do_scsi(SCpnt, STp, cmd, cmd[4], STp->timeout, 0);
if ((STp->buffer)->last_result_fatal != 0) {
#if DEBUG
@@ -1817,7 +1863,7 @@ st_compression(Scsi_Tape * STp, int state)
st_int_ioctl(struct inode * inode,
unsigned int cmd_in, unsigned long arg)
{
- int timeout = ST_LONG_TIMEOUT;
+ int timeout;
long ltmp;
int i, ioctl_result;
int chg_eof = TRUE;
@@ -1831,6 +1877,7 @@ st_int_ioctl(struct inode * inode,
STp = &(scsi_tapes[dev]);
if (STp->ready != ST_READY && cmd_in != MTLOAD)
return (-EIO);
+ timeout = STp->long_timeout;
STps = &(STp->ps[STp->partition]);
fileno = STps->drv_file;
blkno = STps->drv_block;
@@ -1961,7 +2008,7 @@ st_int_ioctl(struct inode * inode,
cmd[2] = (arg >> 16);
cmd[3] = (arg >> 8);
cmd[4] = arg;
- timeout = ST_TIMEOUT;
+ timeout = STp->timeout;
#if DEBUG
if (debugging) {
if (cmd_in == MTWEOF)
@@ -1981,7 +2028,7 @@ st_int_ioctl(struct inode * inode,
cmd[0] = REZERO_UNIT;
#if ST_NOWAIT
cmd[1] = 1; /* Don't wait for completion */
- timeout = ST_TIMEOUT;
+ timeout = STp->timeout;
#endif
#if DEBUG
if (debugging)
@@ -2012,9 +2059,9 @@ st_int_ioctl(struct inode * inode,
}
#if ST_NOWAIT
cmd[1] = 1; /* Don't wait for completion */
- timeout = ST_TIMEOUT;
+ timeout = STp->timeout;
#else
- timeout = ST_LONG_TIMEOUT * 8;
+ timeout = STp->long_timeout;
#endif
#if DEBUG
if (debugging) {
@@ -2037,7 +2084,7 @@ st_int_ioctl(struct inode * inode,
cmd[0] = START_STOP;
#if ST_NOWAIT
cmd[1] = 1; /* Don't wait for completion */
- timeout = ST_TIMEOUT;
+ timeout = STp->timeout;
#endif
cmd[4] = 3;
#if DEBUG
@@ -2076,9 +2123,9 @@ st_int_ioctl(struct inode * inode,
cmd[1] = 1; /* To the end of tape */
#if ST_NOWAIT
cmd[1] |= 2; /* Don't wait for completion */
- timeout = ST_TIMEOUT;
+ timeout = STp->timeout;
#else
- timeout = ST_LONG_TIMEOUT * 8;
+ timeout = STp->long_timeout * 8;
#endif
#if DEBUG
if (debugging)
@@ -2147,7 +2194,7 @@ st_int_ioctl(struct inode * inode,
(STp->buffer)->b_data[9] = (ltmp >> 16);
(STp->buffer)->b_data[10] = (ltmp >> 8);
(STp->buffer)->b_data[11] = ltmp;
- timeout = ST_TIMEOUT;
+ timeout = STp->timeout;
#if DEBUG
if (debugging) {
if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK)
@@ -2338,7 +2385,7 @@ get_location(struct inode * inode, unsigned int *block, int *partition,
if (!logical && !STp->scsi2_logical)
scmd[1] = 1;
}
- SCpnt = st_do_scsi(NULL, STp, scmd, 20, ST_TIMEOUT, MAX_READY_RETRIES);
+ SCpnt = st_do_scsi(NULL, STp, scmd, 20, STp->timeout, MAX_READY_RETRIES);
if (!SCpnt)
return (-EBUSY);
@@ -2394,13 +2441,14 @@ set_location(struct inode * inode, unsigned int block, int partition,
int dev = TAPE_NR(inode->i_rdev);
int result, p;
unsigned int blk;
- int timeout = ST_LONG_TIMEOUT;
+ int timeout;
unsigned char scmd[10];
Scsi_Cmnd *SCpnt;
STp = &(scsi_tapes[dev]);
if (STp->ready != ST_READY)
return (-EIO);
+ timeout = STp->long_timeout;
STps = &(STp->ps[STp->partition]);
#if DEBUG
@@ -2457,7 +2505,7 @@ set_location(struct inode * inode, unsigned int block, int partition,
}
#if ST_NOWAIT
scmd[1] |= 1; /* Don't wait for completion */
- timeout = ST_TIMEOUT;
+ timeout = STp->timeout;
#endif
SCpnt = st_do_scsi(NULL, STp, scmd, 20, timeout, MAX_READY_RETRIES);
@@ -2554,7 +2602,7 @@ nbr_partitions(struct inode * inode)
cmd[2] = PART_PAGE;
cmd[4] = 200;
- SCpnt = st_do_scsi(SCpnt, STp, cmd, 200, ST_TIMEOUT, MAX_READY_RETRIES);
+ SCpnt = st_do_scsi(SCpnt, STp, cmd, 200, STp->timeout, MAX_READY_RETRIES);
if (SCpnt == NULL)
return (-EBUSY);
SCpnt->request.rq_status = RQ_INACTIVE; /* Mark as not busy */
@@ -2628,7 +2676,7 @@ partition_tape(struct inode * inode, int size)
cmd[1] = 0x10;
cmd[4] = length + MODE_HEADER_LENGTH;
- SCpnt = st_do_scsi(SCpnt, STp, cmd, cmd[4], ST_LONG_TIMEOUT, MAX_READY_RETRIES);
+ SCpnt = st_do_scsi(SCpnt, STp, cmd, cmd[4], STp->long_timeout, MAX_READY_RETRIES);
if (SCpnt == NULL)
return (-EBUSY);
SCpnt->request.rq_status = RQ_INACTIVE; /* Mark as not busy */
@@ -2979,13 +3027,13 @@ normalize_buffer(ST_buffer *STbuffer)
/* Set the boot options. Syntax: st=xxx,yyy
where xxx is buffer size in 1024 byte blocks and yyy is write threshold
in 1024 byte blocks. */
- void
-st_setup(char *str, int *ints)
+ __initfunc( void
+st_setup(char *str, int *ints))
{
if (ints[0] > 0 && ints[1] > 0)
- st_buffer_size = ints[1] * ST_BLOCK_SIZE;
+ st_buffer_size = ints[1] * ST_KILOBYTE;
if (ints[0] > 1 && ints[2] > 0) {
- st_write_threshold = ints[2] * ST_BLOCK_SIZE;
+ st_write_threshold = ints[2] * ST_KILOBYTE;
if (st_write_threshold > st_buffer_size)
st_write_threshold = st_buffer_size;
}
@@ -3045,12 +3093,14 @@ static int st_attach(Scsi_Device * SDp){
tpnt->can_partitions = 0;
tpnt->two_fm = ST_TWO_FM;
tpnt->fast_mteom = ST_FAST_MTEOM;
- tpnt->scsi2_logical = 0;
+ tpnt->scsi2_logical = ST_SCSI2LOGICAL;
tpnt->write_threshold = st_write_threshold;
tpnt->default_drvbuffer = 0xff; /* No forced buffering */
tpnt->partition = 0;
tpnt->new_partition = 0;
tpnt->nbr_partitions = 0;
+ tpnt->timeout = ST_TIMEOUT;
+ tpnt->long_timeout = ST_LONG_TIMEOUT;
for (i=0; i < ST_NBR_MODES; i++) {
STm = &(tpnt->modes[i]);
@@ -3099,7 +3149,7 @@ static int st_detect(Scsi_Device * SDp)
static int st_registered = 0;
-/* Driver initialization */
+/* Driver initialization (not __initfunc because may be called later) */
static int st_init()
{
int i;
@@ -3213,8 +3263,25 @@ static void st_detach(Scsi_Device * SDp)
#ifdef MODULE
int init_module(void) {
+ int result;
+
st_template.module = &__this_module;
- return scsi_register_module(MODULE_SCSI_DEV, &st_template);
+ result = scsi_register_module(MODULE_SCSI_DEV, &st_template);
+ if (result)
+ return result;
+
+ if (buffer_kbs > 0)
+ st_buffer_size = buffer_kbs * ST_KILOBYTE;
+ if (write_threshold_kbs > 0)
+ st_write_threshold = write_threshold_kbs * ST_KILOBYTE;
+ if (st_write_threshold > st_buffer_size)
+ st_write_threshold = st_buffer_size;
+ if (max_buffers > 0)
+ st_max_buffers = max_buffers;
+printk(KERN_INFO "st: bufsize %d, wrt %d, max buffers %d.\n",
+st_buffer_size, st_write_threshold, st_max_buffers);
+
+ return 0;
}
void cleanup_module( void)
diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
index c29455fa6..c25c80cc7 100644
--- a/drivers/scsi/st.h
+++ b/drivers/scsi/st.h
@@ -20,6 +20,7 @@ typedef struct {
int writing;
int last_result;
int last_result_fatal;
+ Scsi_Cmnd *last_SCpnt;
unsigned char *b_data;
int orig_size;
unsigned char *orig_b_data;
@@ -78,6 +79,8 @@ typedef struct {
unsigned char scsi2_logical;
unsigned char default_drvbuffer; /* 0xff = don't touch, value 3 bits */
int write_threshold;
+ int timeout; /* timeout for normal commands */
+ int long_timeout; /* timeout for commands known to take long time*/
/* Mode characteristics */
ST_mode modes[ST_NBR_MODES];
diff --git a/drivers/scsi/st_options.h b/drivers/scsi/st_options.h
index f60418608..205940441 100644
--- a/drivers/scsi/st_options.h
+++ b/drivers/scsi/st_options.h
@@ -3,7 +3,7 @@
Copyright 1995 Kai Makisara.
- Last modified: Thu Dec 14 21:51:27 1995 by root@kai.makisara.fi
+ Last modified: Tue May 27 22:29:15 1997 by makisara@home
*/
#ifndef _ST_OPTIONS_H
@@ -88,8 +88,14 @@
files and the file number status is retained. */
#define ST_FAST_MTEOM 0
+/* If ST_SCSI2LOGICAL is nonzero, the logical block addresses are used for
+ MTIOCPOS and MTSEEK by default. Vendor addresses are used if ST_SCSI2LOGICAL
+ is zero. */
+#define ST_SCSI2LOGICAL 0
+
/* If ST_SYSV is non-zero, the tape behaves according to the SYS V semantics.
The default is BSD semantics. */
#define ST_SYSV 0
+
#endif
diff --git a/drivers/sound/.version b/drivers/sound/.version
index b344e143c..56cbb7db2 100644
--- a/drivers/sound/.version
+++ b/drivers/sound/.version
@@ -1,2 +1,2 @@
-3.8-beta9
-0x030803
+3.8a
+0x030804
diff --git a/drivers/sound/CHANGELOG b/drivers/sound/CHANGELOG
index 3b82d35ce..17c2dad5f 100644
--- a/drivers/sound/CHANGELOG
+++ b/drivers/sound/CHANGELOG
@@ -1,5 +1,11 @@
-Changelog for version 3.8-beta8
--------------------------------
+Changelog for version 3.8
+--------------------------
+
+Since 3.8-beta21
+- Fixed all known bugs (I think).
+
+Since 3.8-beta8
+- Lot of fixes to audio playback code in dmabuf.c
Since 3.8-beta6
- Fixed the famous Quake delay bug.
diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in
index fb8a76753..310bf01bf 100644
--- a/drivers/sound/Config.in
+++ b/drivers/sound/Config.in
@@ -44,7 +44,7 @@ if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then
fi
fi
- if [ "$CONFIG_MIDI" = "y" ]; then
+ if [ "$CONFIG_MPU401" = "y" ]; then
bool 'Audio Excel DSP 16 (MPU401 emulation)' CONFIG_AEDSP16_MPU401
if [ "$CONFIG_AEDSP16_MPU401" = "y" ]; then
comment 'Audio Excel DSP 16 [MPU-401]'
diff --git a/drivers/sound/Config.std b/drivers/sound/Config.std
index fb8a76753..310bf01bf 100644
--- a/drivers/sound/Config.std
+++ b/drivers/sound/Config.std
@@ -44,7 +44,7 @@ if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then
fi
fi
- if [ "$CONFIG_MIDI" = "y" ]; then
+ if [ "$CONFIG_MPU401" = "y" ]; then
bool 'Audio Excel DSP 16 (MPU401 emulation)' CONFIG_AEDSP16_MPU401
if [ "$CONFIG_AEDSP16_MPU401" = "y" ]; then
comment 'Audio Excel DSP 16 [MPU-401]'
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
index 499521c9f..b0a3483d5 100644
--- a/drivers/sound/Makefile
+++ b/drivers/sound/Makefile
@@ -4,7 +4,33 @@
# parent makes. (hopefully)
#
#
+#
+#
+ifeq ($(ARCH),m68k)
+ L_TARGET := sound.a
+ L_OBJS :=
+ M_OBJS :=
+ ifeq ($(CONFIG_DMASOUND),y)
+ L_OBJS += dmasound.o
+ else
+ ifeq ($(CONFIG_DMASOUND),m)
+ M_OBJS += dmasound.o
+ endif
+ endif
+
+ include $(TOPDIR)/Rules.make
+
+ clean:
+ rm -f core *.o *.a *.s
+
+ # dummy rule to keep 'make xconfig' happy
+ mkscript:
+
+# More dummy targets for make [menu]config
+mkscript:
+kernelconfig:
+else
.PHONY: dummy
SUB_DIRS = lowlevel
VERSION = `head -1 .version`
@@ -36,6 +62,7 @@ build:
install: sound.o
cp sound.o $(MODULEDIR)
+else
endif
.c.o:
@@ -161,3 +188,4 @@ ifeq (.depend,$(wildcard .depend))
include .depend
endif
endif
+endif
diff --git a/drivers/sound/Readme b/drivers/sound/Readme
index a859afb12..c5002a1f7 100644
--- a/drivers/sound/Readme
+++ b/drivers/sound/Readme
@@ -1,5 +1,5 @@
-OSS Lite version 3.8-beta release notes
----------------------------------------
+OSS Lite version 3.8 release notes
+----------------------------------
Most up to date information about this driver is available from
http://www.4front-tech.com/ossfree or http://personal.eunet.fi/pp/voxware
@@ -16,10 +16,10 @@ Please check http://www.4front-tech.com/pguide for more info about programming
with OSS.
====================================================
-- THIS VERSION ____REQUIRES____ Linux 2.1.26 OR LATER.
+- THIS VERSION ____REQUIRES____ Linux 2.1.36 OR LATER.
====================================================
-Packages "snd-util-3.7.tar.gz" and "snd-data-0.1.tar.Z"
+Packages "snd-util-3.8.tar.gz" and "snd-data-0.1.tar.Z"
contain useful utilities to be used with this driver.
See http://www.4front-tech.com/ossfree/getting.html for
download instructions.
diff --git a/drivers/sound/Readme.cards b/drivers/sound/Readme.cards
index 7f89cf17c..148afd6b0 100644
--- a/drivers/sound/Readme.cards
+++ b/drivers/sound/Readme.cards
@@ -43,8 +43,8 @@ IMPORTANT! This document covers only cards that were "known" when
-THE BIGGEST MISTAKE YOU CAN DO
-==============================
+THE BIGGEST MISTAKES YOU CAN DO
+===============================
1. Assuming that the card is Sound Blaster compatible when it's not.
--------------------------------------------------------------------
@@ -106,21 +106,24 @@ for PnP models of soudcards even you have managed to wake up the card properly.
Many PnP cards are simply too much different than their original non PnP
ancestors which are covered by this document.
+
Cards that are not (fully) supported by this driver
===================================================
See http://www.4front-tech.com/ossfree for information about soundcards
to be supported in future.
+
How to use sound without recompiling kernel and/or sound driver
----------------------------------------------------------------
+===============================================================
There is commercial sound driver which should be released during Apr 96.
It comes in precompiled form and doesn't require recompiling of kernel. See
http://www.4Front-tech.com/oss.html for more info.
+
Configuring PnP cards
----------------------
+=====================
New versions of most soundcards use so called ISA PnP protocol for
soft configuring their I/O, IRQ, DMA and shared memory resources.
@@ -170,8 +173,9 @@ See http://www.4front-tech.com/linux.html for more info. This is the way
you probably like to do it if you don't waste hours of time in recompiling
kernel and the required tools.
+
Read this before trying to configure the driver
------------------------------------------------
+===============================================
There are currently many cards that work with this driver. Some of the cards
have native support while others work since they emulate some other
@@ -196,12 +200,14 @@ Sound Blasters
SB 1.0 to 2.0
SB Pro
SB 16
- SB32/AWE
- Configure SB32/AWE just like SB16. See lowlevel/README.awe
+ SB32/64/AWE
+ Configure SB32/64/AWE just like SB16. See lowlevel/README.awe
for information about using the wave table synth.
+ NOTE! AWE63/Gold and 16/32/AWE "PnP" cards need to be activated
+ using isapnptools before they work with OSS/Free.
SB16 compatible cards by other manufacturers than Creative.
You have been fooled since there are _no_ SB16 compatible
- cards on the market (Feb 96). It's likely that your card
+ cards on the market (May 97). It's likely that your card
is compatible just with SB Pro but there is also a non-SB-
compatible 16 bit mode. Usually it's MSS/WSS but it could also
be a proprietary one like MV Jazz16 or ESS ES688. OPTi
@@ -237,7 +243,7 @@ Gravis Ultrasound (GUS)
GUS + the 16 bit option
GUS MAX
GUS ACE (No MIDI port and audio recording)
- GUS PnP (in GUS MAX compatible mode)
+ GUS PnP (with RAM)
MPU-401 and compatibles
The driver works both with the full (intelligent mode) MPU-401
@@ -267,10 +273,6 @@ Windows Sound System (MSS/WSS)
cause a conflict. So check if your card is listed in this file before
enabling the MSS support.
-6850 UART MIDI
- This UART chip is used in the MIDI interface of some (rare)
- soundcards. It's supported by the driver in case you need it.
-
Yamaha FM synthesizers (OPL2, OPL3 (not OPL3-SA) and OPL4)
Most soundcards have a FM synthesizer chip. The OPL2 is a 2
operator chip used in the original AdLib card. Currently it's used
@@ -321,7 +323,9 @@ Ensoniq SoundScape and compatibles
Several companies (including Ensoniq, Reveal and Spea) are selling
cards based on this architecture.
- NOTE! The new PnP SoundScape is not supported yet.
+ NOTE! The SoundScape PnP is not supported by OSS/Free. Ensoniq VIVO and
+ VIVO90 cards are not compatible with Soundscapes so the Soundscape driver
+ will not work with them. You may want to use OSS/Linux with these cards.
MAD16 and Mozart based cards
The Mozart (OAK OTI-601), MAD16 (OPTi 82C928), MAD16 Pro (OPTi 82C929),
@@ -332,20 +336,32 @@ MAD16 and Mozart based cards
interface chip performs address decoding for the other chips.
NOTE! Tropez Plus is not MAD16 but CS4232 based.
NOTE! MAD16 PnP cards (82C924, 82C925, 82C931) are not MAD16 compatible
- in the PnP mode. You will have to use them in MAD16 mode after having
- initialized them using isapnptools or DOS.
+ in the PnP mode. You will have to use them in MSS mode after having
+ initialized them using isapnptools or DOS. 82C931 probably requires
+ initialization using DOS/Windows (running isapnptools is not enough).
+ It's possible to use 82C931 with OSS/Free by jumpering it to non-PnP
+ mode (provided that the card has a jumper for this). In non-PnP mode
+ 82C931 is compatible with 82C930 and should work with the MAD16 driver
+ (without need to use isapnptools or DOS to initialize it). All OPTi
+ chips are supported by OSS/Linux (both in PnP and non-PnP modes).
Audio Excel DSP16
Support for this card was written by Riccardo Faccetti
(riccardo@cdc8g5.cdc.polimi.it). The AEDSP16 driver included in
the lowlevel/ directory. To use it you should use the "new" config
script and to enable the "Additional low level drivers" option.
-Crystal CS4232 and 4236 based cards such as AcerMagic S23, TB Tropez _Plus_ and
+
+Crystal CS4232 and CS4236 based cards such as AcerMagic S23, TB Tropez _Plus_ and
many PC motherboards (Compaq, HP, Intel, ...)
CS4232 is a PnP multimedia chip which contains a CS3231A codec,
SB and MPU401 emulations. There is support for OPL3 too.
Unfortunately the MPU401 mode doesn't work (I don't know how to
- initialize it). CS4236 is an enhanced (compatible) version of 4232.
+ initialize it). CS4236 is an enhanced (compatible) version of CS4232.
+ NOTE! Don't ever try to use isapnptools with CS4232 since this just
+ freezes your machine (due to chip bugs). If you have problems in getting
+ CS4232 working you could try initializing it with DOS (CS4232C.EXE) and
+ then booting Linux using loadlin. CS4232C.EXE loads a secret firmware
+ patch which is not documented by Crystal.
Turtle Beach Maui and Tropez "classic"
This driver version supports sample, patch and program loading commands
@@ -354,9 +370,13 @@ Turtle Beach Maui and Tropez "classic"
the Tropez is based on the MAD16 chip (see above).
NOTE! You will have to use the "old" config script when configuring
Maui or Tropez.
+ NOTE! Tropez Plus is different card than Tropez "classic" and will not
+ work fully in Linux. You can get audio features working by configuring
+ the card as a CS4232 based card (above).
+
Jumpers and software configuration
-----------------------------------
+==================================
Some of the earliest soundcards were jumper configurable. You have to
configure the driver use I/O, IRQ and DMA settings
@@ -388,8 +408,9 @@ how the card must be initialized. It cannot initialize unknown cards
even if they are otherwise compatible with some other cards (like SB,
MPU401 or Windows Sound System).
+
What if your card was not listed above?
----------------------------------------
+=======================================
The first thing to do is to look at the major IC chips on the card.
Many of the latest soundcards are based on some standard chips. If you
@@ -518,8 +539,19 @@ select some options automatically as well.
that doesn't really have a MPU401 could cause some trouble. If your
card was in the list of supported cards (above), please look at
the card specific instructions later in this file.
+
+ In MOST cases this MPU401 driver should only be used with "true"
+ MIDI-only MPU401 professional cards. In most other cases there
+ is another way to get the MPU401 compatible interface of a
+ soundcard to work.
+ Support for the MPU401 compatible MIDI port of SB16, ESS1688
+ and MV Jazz16 cards is included in the SB driver. Use it instead
+ of this separate MPU401 driver with these cards. As well
+ Soundscape, PSS and Maui drivers include their own MPU401
+ options.
+
It's safe to answer 'y' if you have a true MPU401 MIDI interface
- card.
+ card.
"6850 UART Midi support",
- It's safe to answer 'n' to this question in all cases. The 6850
UART interface is so rarely used.
diff --git a/drivers/sound/Readme.linux b/drivers/sound/Readme.linux
index 053880e84..b1121ebbe 100644
--- a/drivers/sound/Readme.linux
+++ b/drivers/sound/Readme.linux
@@ -72,171 +72,14 @@ Please check http://www.4front-tech.com/osslite for more info.
Hannu Savolainen
hannu@voxware.pp.fi
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-NOTE!
-
-Running the script enclosed below is usually not required. All known Linux
-distributions build them automaticly during installation. You need to run
-this script only if "ls /dev/sndstat" displays "No such file or directory".
-In case of any other error message you should start looking for the reason
-from somewhere else (see above).
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
----------------- cut here ------------------------------
-#!/bin/sh
-# *****************************************
-# * NOTICE!
-# *
-# * For security reasons read access to /dev/dsp* and /dev/audio* has been
-# * disabled from other than root. Otherwise any user may be able to spy
-# * what is being talked about near the microphone.
-# * This effectively disables audio recording by other than root. In case
-# * this capability is required, you should change AUDIOPERMS (below) to 666
-# * before executing this script.
-# *****************************************
-AUDIOPERMS=622
-#
-#
-#
-#
-# Create the devices
-#
-# Mixer devices
-#
-if [ -e /dev/mixer ]; then
- rm -f /dev/mixer
-fi
-
-if [ -e /dev/mixer0 ]; then
- rm -f /dev/mixer0
-fi
-
-mknod -m 666 /dev/mixer0 c 14 0
-ln -sf /dev/mixer0 /dev/mixer
-
-if [ -e /dev/mixer1 ]; then
- rm -f /dev/mixer1
-fi
-mknod -m 666 /dev/mixer1 c 14 16
-
-
-# Sequencer (14, 1)
-#
-if [ -e /dev/sequencer ]; then
- rm -f /dev/sequencer
-fi
-mknod -m 666 /dev/sequencer c 14 1
-
-if [ -e /dev/patmgr0 ]; then
- rm -f /dev/patmgr0
-fi
-mknod -m 666 /dev/patmgr0 c 14 17
-if [ -e /dev/patmgr1 ]; then
- rm -f /dev/patmgr1
-fi
-mknod -m 666 /dev/patmgr1 c 14 33
-
- # music (14, 8)
- #
- if [ -e /dev/music ]; then
- rm -f /dev/music
- fi
-
- mknod -m 666 /dev/music c 14 8
- if [ -e /dev/sequencer2 ]; then
- rm -f /dev/sequencer2
- fi
- ln -s /dev/music /dev/sequencer2
-
-# Midi devices
-#
-if [ -e /dev/midi ]; then
- rm -f /dev/midi # Old name. Don't use it
-fi
- if [ -e /dev/midi00 ]; then
- rm -f /dev/midi00
- fi
- mknod -m 666 /dev/midi00 c 14 2
- ln -sf /dev/midi00 /dev/midi
-
- if [ -e /dev/midi01 ]; then
- rm -f /dev/midi01
- fi
- mknod -m 666 /dev/midi01 c 14 18
-
- if [ -e /dev/midi02 ]; then
- rm -f /dev/midi02
- fi
- mknod -m 666 /dev/midi02 c 14 34
-
- if [ -e /dev/midi03 ]; then
- rm -f /dev/midi03
- fi
- mknod -m 666 /dev/midi03 c 14 50
-#
-# DSP (14, 3)
-#
-if [ -e /dev/dsp ]; then
- rm -f /dev/dsp
-fi
-if [ -e /dev/dsp0 ]; then
- rm -f /dev/dsp0
-fi
-mknod -m $AUDIOPERMS /dev/dsp0 c 14 3
-ln -s /dev/dsp0 /dev/dsp
-
-#
-# DSPW (14, 5)
-#
-if [ -e /dev/dspW ]; then
- rm -f /dev/dspW
-fi
-if [ -e /dev/dspW0 ]; then
- rm -f /dev/dspW0
-fi
-mknod -m $AUDIOPERMS /dev/dspW0 c 14 5
-ln -s /dev/dspW0 /dev/dspW
-
-if [ -e /dev/dspW1 ]; then
- rm -f /dev/dspW1
-fi
-mknod -m $AUDIOPERMS /dev/dspW1 c 14 37
-
-#
-# SPARC compatible /dev/audio (14, 4)
-#
-if [ -e /dev/audio ]; then
- rm -f /dev/audio
-fi
-if [ -e /dev/audio0 ]; then
- rm -f /dev/audio0
-fi
-mknod -m $AUDIOPERMS /dev/audio0 c 14 4
-ln -s /dev/audio0 /dev/audio
-
-#
-# DSP1 (14, 19) /dev/dsp for the second soundcard.
-# Also the SB emulation part of the
-# PAS16 card.
-#
-if [ -e /dev/dsp1 ]; then
- rm -f /dev/dsp1
-fi
-mknod -m $AUDIOPERMS /dev/dsp1 c 14 19
-#
-# SPARC audio1 (14, 20)
-# /dev/audio for the second soundcard.
-# Also the SB emulation part of the
-# PAS16 card.
-#
-if [ -e /dev/audio1 ]; then
- rm -f /dev/audio1
-fi
-mknod -m $AUDIOPERMS /dev/audio1 c 14 20
-#
-# /dev/sndstat (14,6) For debugging purposes
-#
-if [ -e /dev/sndstat ]; then
- rm -f /dev/sndstat
-fi
-mknod -m 666 /dev/sndstat c 14 6
-exit 0
+SURPRISE SURPRISE!!!
+
+The device file creation script that used to be here earlier is
+obviously not here any more.
+
+Why?
+
+Because you do not need it. All Linux distributions have the
+device files properly created (yes they are) so you should not
+try to run any scripts which create them.
diff --git a/drivers/sound/ad1848.c b/drivers/sound/ad1848.c
index 92a71fcdf..82ec86f03 100644
--- a/drivers/sound/ad1848.c
+++ b/drivers/sound/ad1848.c
@@ -71,6 +71,7 @@ typedef struct
int irq_ok;
mixer_ents *mix_devices;
int mixer_output_port;
+ int c930_password_port;
}
ad1848_info;
@@ -107,7 +108,7 @@ static int ad_format_mask[8 /*devc->model */ ] =
AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM
};
-static ad1848_info dev_info[MAX_AUDIO_DEV];
+static ad1848_info adev_info[MAX_AUDIO_DEV];
#define io_Index_Addr(d) ((d)->base)
#define io_Indexed_Data(d) ((d)->base+1)
@@ -200,7 +201,6 @@ wait_for_calibration (ad1848_info * devc)
if (ad_read (devc, 11) & 0x20)
if (devc->model != MD_1845)
printk ("ad1848: Auto calibration timed out(3).\n");
- ad_write (devc, 9, ad_read (devc, 9) & ~0x18); /* Disable autocalibration */
}
static void
@@ -215,7 +215,6 @@ ad_mute (ad1848_info * devc)
for (i = 6; i < 8; i++)
{
prev = devc->saved_regs[i] = ad_read (devc, i);
- ad_write (devc, i, prev | 0x80);
}
}
@@ -223,21 +222,6 @@ ad_mute (ad1848_info * devc)
static void
ad_unmute (ad1848_info * devc)
{
- int i, dummy;
-
-/*
- * Let's have some delay
- */
- for (i = 0; i < 1000; i++)
- dummy = inb (devc->base);
-
- /*
- * Restore back old volume registers (unmute)
- */
- for (i = 6; i < 8; i++)
- {
- ad_write (devc, i, devc->saved_regs[i] & ~0x80);
- }
}
static void
@@ -296,7 +280,6 @@ ad_leave_MCE (ad1848_info * devc)
restore_flags (flags);
}
-
static int
ad1848_set_recmask (ad1848_info * devc, int mask)
{
@@ -381,16 +364,32 @@ change_bits (ad1848_info * devc, unsigned char *regval, int dev, int chn, int ne
{
unsigned char mask;
int shift;
+ int mute;
+ int mutemask;
+ int set_mute_bit;
+
+ set_mute_bit = (newval == 0);
if (devc->mix_devices[dev][chn].polarity == 1) /* Reverse */
newval = 100 - newval;
mask = (1 << devc->mix_devices[dev][chn].nbits) - 1;
shift = devc->mix_devices[dev][chn].bitpos;
- newval = (int) ((newval * mask) + 50) / 100; /* Scale it */
- *regval &= ~(mask << shift); /* Clear bits */
- *regval |= (newval & mask) << shift; /* Set new value */
+ if (devc->mix_devices[dev][chn].mutepos == 8)
+ { /* if there is no mute bit */
+ mute = 0; /* No mute bit; do nothing special */
+ mutemask = ~0; /* No mute bit; do nothing special */
+ }
+ else
+ {
+ mute = (set_mute_bit << devc->mix_devices[dev][chn].mutepos);
+ mutemask = ~(1 << devc->mix_devices[dev][chn].mutepos);
+ }
+
+ newval = (int) ((newval * mask) + 50) / 100; /* Scale it */
+ *regval &= (~(mask << shift)) & (mutemask); /* Clear bits */
+ *regval |= ((newval & mask) << shift) | mute; /* Set new value */
}
static int
@@ -969,13 +968,12 @@ ad1848_start_input (int dev, unsigned long buf, int count, int intrflag)
save_flags (flags);
cli ();
- if (devc->model == MD_1848 || !devc->dual_dma) /* Single DMA channel mode */
+ if (devc->model == MD_1848)
{
ad_write (devc, 15, (unsigned char) (cnt & 0xff));
ad_write (devc, 14, (unsigned char) ((cnt >> 8) & 0xff));
}
else
- /* Dual DMA channel mode */
{
ad_write (devc, 31, (unsigned char) (cnt & 0xff));
ad_write (devc, 30, (unsigned char) ((cnt >> 8) & 0xff));
@@ -1007,6 +1005,8 @@ ad1848_prepare_for_output (int dev, int bsize, int bcount)
if (portc->channels > 1)
fs |= 0x10;
+ ad_enter_MCE (devc); /* Enables changes to the format select reg */
+
if (devc->model == MD_1845) /* Use alternate speed select registers */
{
fs &= 0xf0; /* Mask off the rate select bits */
@@ -1017,14 +1017,15 @@ ad1848_prepare_for_output (int dev, int bsize, int bcount)
old_fs = ad_read (devc, 8);
- ad_enter_MCE (devc); /* Enables changes to the format select reg */
-
if (devc->model == MD_4232)
{
tmp = ad_read (devc, 16);
ad_write (devc, 16, tmp | 0x30);
}
+ if (devc->model == MD_IWAVE)
+ ad_write (devc, 17, 0xc2); /* Disable variable frequency select */
+
ad_write (devc, 8, fs);
/*
* Write to I8 starts resynchronization. Wait until it completes.
@@ -1075,6 +1076,8 @@ ad1848_prepare_for_input (int dev, int bsize, int bcount)
if (portc->channels > 1)
fs |= 0x10;
+ ad_enter_MCE (devc); /* Enables changes to the format select reg */
+
if (devc->model == MD_1845) /* Use alternate speed select registers */
{
fs &= 0xf0; /* Mask off the rate select bits */
@@ -1083,32 +1086,21 @@ ad1848_prepare_for_input (int dev, int bsize, int bcount)
ad_write (devc, 23, portc->speed & 0xff); /* Speed LSB */
}
- old_fs = ad_read (devc, 8);
-
- ad_enter_MCE (devc); /* Enables changes to the format select reg */
-
if (devc->model == MD_4232)
{
tmp = ad_read (devc, 16);
ad_write (devc, 16, tmp | 0x30);
}
- ad_write (devc, 8, fs);
- /*
- * Write to I8 starts resynchronization. Wait until it completes.
- */
- timeout = 0;
- while (timeout < 100 && inb (devc->base) != 0x80)
- timeout++;
- timeout = 0;
- while (timeout < 10000 && inb (devc->base) == 0x80)
- timeout++;
+ if (devc->model == MD_IWAVE)
+ ad_write (devc, 17, 0xc2); /* Disable variable frequency select */
/*
- * If mode >= 2 (CS4231), set I28 also. It's the capture format register.
+ * If mode >= 2 (CS4231), set I28. It's the capture format register.
*/
if (devc->model != MD_1848)
{
+ old_fs = ad_read (devc, 28);
ad_write (devc, 28, fs);
/*
@@ -1121,6 +1113,43 @@ ad1848_prepare_for_input (int dev, int bsize, int bcount)
timeout = 0;
while (timeout < 10000 && inb (devc->base) == 0x80)
timeout++;
+
+ if (devc->model != MD_1848 && devc->model != MD_1845)
+ {
+ /*
+ * CS4231 compatible devices don't have separate sampling rate selection
+ * register for recording an playback. The I8 register is shared so we have to
+ * set the speed encoding bits of it too.
+ */
+ unsigned char tmp = portc->speed_bits | (ad_read (devc, 8) & 0xf0);
+
+ ad_write (devc, 8, tmp);
+ /*
+ * Write to I8 starts resynchronization. Wait until it completes.
+ */
+ timeout = 0;
+ while (timeout < 100 && inb (devc->base) != 0x80)
+ timeout++;
+
+ timeout = 0;
+ while (timeout < 10000 && inb (devc->base) == 0x80)
+ timeout++;
+ }
+ }
+ else
+ { /* For AD1848 set I8. */
+
+ old_fs = ad_read (devc, 8);
+ ad_write (devc, 8, fs);
+ /*
+ * Write to I8 starts resynchronization. Wait until it completes.
+ */
+ timeout = 0;
+ while (timeout < 100 && inb (devc->base) != 0x80)
+ timeout++;
+ timeout = 0;
+ while (timeout < 10000 && inb (devc->base) == 0x80)
+ timeout++;
}
if (devc->model == MD_4232)
@@ -1176,14 +1205,14 @@ ad1848_halt_input (int dev)
{
int tmout;
- disable_dma (audio_devs[dev]->dmap_out->dma);
+ disable_dma (audio_devs[dev]->dmap_in->dma);
for (tmout = 0; tmout < 100000; tmout++)
if (ad_read (devc, 11) & 0x10)
break;
ad_write (devc, 9, ad_read (devc, 9) & ~0x02); /* Stop capture */
- enable_dma (audio_devs[dev]->dmap_out->dma);
+ enable_dma (audio_devs[dev]->dmap_in->dma);
devc->audio_mode &= ~PCM_ENABLE_INPUT;
}
@@ -1306,6 +1335,9 @@ ad1848_init_hw (ad1848_info * devc)
for (i = 16; i < 32; i++)
ad_write (devc, i, init_values[i]);
+ if (devc->model == MD_IWAVE)
+ ad_write (devc, 16, 0x30); /* Playback and capture counters enabled */
+
}
if (devc->model > MD_1848)
@@ -1321,6 +1353,7 @@ ad1848_init_hw (ad1848_info * devc)
if (devc->model == MD_IWAVE)
{ /* Some magic Interwave specific initialization */
ad_write (devc, 12, 0x6c); /* Select codec mode 3 */
+ ad_write (devc, 16, 0x30); /* Playback and capture counters enabled */
ad_write (devc, 17, 0xc2); /* Alternate feature enable */
}
}
@@ -1347,11 +1380,12 @@ ad1848_detect (int io_base, int *ad_flags, int *osp)
{
unsigned char tmp;
- ad1848_info *devc = &dev_info[nr_ad1848_devs];
+ ad1848_info *devc = &adev_info[nr_ad1848_devs];
unsigned char tmp1 = 0xff, tmp2 = 0xff;
int optiC930 = 0; /* OPTi 82C930 flag */
int interwave = 0;
int ad1847_flag = 0;
+ int cs4248_flag = 0;
int i;
@@ -1364,16 +1398,22 @@ ad1848_detect (int io_base, int *ad_flags, int *osp)
interwave = 1;
*ad_flags = 0;
}
+
+ if (*ad_flags == 0x12345677)
+ {
+ cs4248_flag = 1;
+ *ad_flags = 0;
+ }
}
if (nr_ad1848_devs >= MAX_AUDIO_DEV)
{
- DDB (printk ("ad1848 detect error - step 0\n"));
+ printk ("ad1848 - Too many audio devices\n");
return 0;
}
if (check_region (io_base, 4))
{
- printk ("\n\nad1848.c: Port %x not free.\n\n", io_base);
+ printk ("ad1848.c: Port %x not free.\n", io_base);
return 0;
}
@@ -1386,6 +1426,7 @@ ad1848_detect (int io_base, int *ad_flags, int *osp)
devc->chip_name = "AD1848";
devc->model = MD_1848; /* AD1848 or CS4248 */
devc->levels = NULL;
+ devc->c930_password_port = 0;
devc->debug_flag = 0;
/*
@@ -1413,6 +1454,9 @@ ad1848_detect (int io_base, int *ad_flags, int *osp)
DDB (printk ("ad1848_detect() - step A\n"));
+ if (inb (devc->base) == 0x80) /* Not ready. Let's wait */
+ ad_leave_MCE (devc);
+
if ((inb (devc->base) & 0x80) != 0x00) /* Not a AD1848 */
{
DDB (printk ("ad1848 detect error - step A (%02x)\n",
@@ -1420,11 +1464,6 @@ ad1848_detect (int io_base, int *ad_flags, int *osp)
return 0;
}
- DDB (printk ("ad1848: regs: "));
- for (i = 0; i < 32; i++)
- DDB (printk ("%02x ", ad_read (devc, i)));
- DDB (printk ("\n"));
-
/*
* Test if it's possible to change contents of the indirect registers.
* Registers 0 and 1 are ADC volume registers. The bit 0x10 is read only
@@ -1480,6 +1519,8 @@ ad1848_detect (int io_base, int *ad_flags, int *osp)
/*
* The original AD1848/CS4248 has just 15 indirect registers. This means
* that I0 and I16 should return the same value (etc.).
+ * However this doesn't work with CS4248. Actually it seems to be impossible
+ * to detect if the chip is a CS4231 or CS4248.
* Ensure that the Mode2 enable bit of I12 is 0. Otherwise this test fails
* with CS4231.
*/
@@ -1513,6 +1554,7 @@ ad1848_detect (int io_base, int *ad_flags, int *osp)
else
ad_write (devc, 12, 0x40); /* Set mode2, clear 0x80 */
+
if (ad_flags)
*ad_flags = 0;
@@ -1630,6 +1672,15 @@ ad1848_detect (int io_base, int *ad_flags, int *osp)
devc->chip_name = "AD1845";
devc->model = MD_1845;
}
+ else if (cs4248_flag)
+ {
+ if (ad_flags)
+ *ad_flags |= AD_F_CS4248;
+
+ devc->chip_name = "CS4248";
+ devc->model = MD_1848;
+ ad_write (devc, 12, ad_read (devc, 12) & ~0x40); /* Mode2 off */
+ }
ad_write (devc, 23, tmp); /* Restore */
}
@@ -1686,7 +1737,7 @@ ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture
int my_dev;
char dev_name[100];
- ad1848_info *devc = &dev_info[nr_ad1848_devs];
+ ad1848_info *devc = &adev_info[nr_ad1848_devs];
ad1848_port_info *portc = NULL;
@@ -1749,7 +1800,7 @@ ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture
if (irq > 0)
{
irq2dev[irq] = devc->dev_no = my_dev;
- if (snd_set_irq_handler (devc->irq, ad1848_interrupt,
+ if (snd_set_irq_handler (devc->irq, adintr,
"SoundPort",
NULL) < 0)
{
@@ -1819,7 +1870,7 @@ ad1848_control (int cmd, int arg)
if (nr_ad1848_devs < 1)
return;
- devc = &dev_info[nr_ad1848_devs - 1];
+ devc = &adev_info[nr_ad1848_devs - 1];
switch (cmd)
{
@@ -1871,9 +1922,9 @@ ad1848_unload (int io_base, int irq, int dma_playback, int dma_capture, int shar
ad1848_info *devc = NULL;
for (i = 0; devc == NULL && i < nr_ad1848_devs; i++)
- if (dev_info[i].base == io_base)
+ if (adev_info[i].base == io_base)
{
- devc = &dev_info[i];
+ devc = &adev_info[i];
dev = devc->dev_no;
}
@@ -1898,7 +1949,7 @@ ad1848_unload (int io_base, int irq, int dma_playback, int dma_capture, int shar
}
void
-ad1848_interrupt (int irq, void *dev_id, struct pt_regs *dummy)
+adintr (int irq, void *dev_id, struct pt_regs *dummy)
{
unsigned char status;
ad1848_info *devc;
@@ -1937,7 +1988,7 @@ interrupt_again: /* Jump back here if int status doesn't reset */
status = inb (io_Status (devc));
if (status == 0x80)
- printk ("ad1848_interrupt: Why?\n");
+ printk ("adintr: Why?\n");
if (devc->model == MD_1848)
outb ((0), io_Status (devc)); /* Clear interrupt status */
@@ -1952,6 +2003,8 @@ interrupt_again: /* Jump back here if int status doesn't reset */
alt_stat = 0;
+ if (devc->c930_password_port)
+ outb ((0xe4), devc->c930_password_port); /* Password */
outb ((11), 0xe0e);
c930_stat = inb (0xe0f);
@@ -1972,6 +2025,8 @@ interrupt_again: /* Jump back here if int status doesn't reset */
save_flags (flags);
cli ();
+ if (devc->c930_password_port)
+ outb ((0xe4), devc->c930_password_port); /* Password */
outb ((11), 0xe0e);
outb ((~c930_stat), 0xe0f);
restore_flags (flags);
@@ -2319,7 +2374,6 @@ attach_ms_sound (struct address_info *hw_config)
-1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20
};
char bits, dma2_bit = 0;
- int ad_flags = 0;
static char dma_bits[4] =
{
@@ -2347,7 +2401,10 @@ attach_ms_sound (struct address_info *hw_config)
bits = interrupt_bits[hw_config->irq];
if (bits == -1)
- return;
+ {
+ printk ("MSS: Bad IRQ %d\n", hw_config->irq);
+ return;
+ }
outb ((bits | 0x40), config_port);
if ((inb (version_port) & 0x40) == 0)
@@ -2357,7 +2414,7 @@ attach_ms_sound (struct address_info *hw_config)
* Handle the capture DMA channel
*/
- if (ad_flags & AD_F_CS4231 && dma2 != -1 && dma2 != dma)
+ if (dma2 != -1 && dma2 != dma)
{
if (!((dma == 0 && dma2 == 1) ||
(dma == 1 && dma2 == 0) ||
@@ -2382,7 +2439,12 @@ attach_ms_sound (struct address_info *hw_config)
}
}
else
- dma2 = dma;
+ {
+ dma2 = dma;
+ }
+
+ hw_config->dma = dma;
+ hw_config->dma2 = dma2;
outb ((bits | dma_bits[dma] | dma2_bit), config_port); /* Write IRQ+DMA setup */
diff --git a/drivers/sound/ad1848_mixer.h b/drivers/sound/ad1848_mixer.h
index 8267aed08..f6ea1c006 100644
--- a/drivers/sound/ad1848_mixer.h
+++ b/drivers/sound/ad1848_mixer.h
@@ -48,10 +48,11 @@
SOUND_MASK_IGAIN | SOUND_MASK_PCM)
struct mixer_def {
- unsigned int regno: 7;
+ unsigned int regno: 5;
unsigned int polarity:1; /* 0=normal, 1=reversed */
- unsigned int bitpos:4;
- unsigned int nbits:4;
+ unsigned int bitpos:3;
+ unsigned int nbits:3;
+ unsigned int mutepos:4;
};
static char mix_cvt[101] = {
@@ -75,47 +76,47 @@ typedef mixer_ent mixer_ents[2];
* The current version doesn't try to compensate this.
*/
-#define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r) \
- {{reg_l, pola_l, pos_l, len_l}, {reg_r, pola_r, pos_r, len_r}}
+#define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r, mute_bit) \
+ {{reg_l, pola_l, pos_l, len_l}, {reg_r, pola_r, pos_r, len_r, mute_bit}}
static mixer_ents ad1848_mix_devices[32] = {
-MIX_ENT(SOUND_MIXER_VOLUME, 27, 1, 0, 4, 29, 1, 0, 4),
-MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6),
-MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1),
-MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_IMIX, 13, 1, 2, 6, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4),
-MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 0, 5, 19, 1, 0, 5)
+MIX_ENT(SOUND_MIXER_VOLUME, 27, 1, 0, 4, 29, 1, 0, 4, 8),
+MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5, 7),
+MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6, 7),
+MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0, 8),
+MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5, 7),
+MIX_ENT(SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1, 8),
+MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5, 7),
+MIX_ENT(SOUND_MIXER_IMIX, 13, 1, 2, 6, 0, 0, 0, 0, 8),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8),
+MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5, 7),
+MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5, 7),
+MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 0, 5, 19, 1, 0, 5, 7)
};
static mixer_ents iwave_mix_devices[32] = {
-MIX_ENT(SOUND_MIXER_VOLUME, 25, 1, 0, 5, 27, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6),
-MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1),
-MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_IMIX, 16, 1, 0, 5, 17, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4),
-MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 0, 5, 19, 1, 0, 5)
+MIX_ENT(SOUND_MIXER_VOLUME, 25, 1, 0, 5, 27, 1, 0, 5, 8),
+MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5, 7),
+MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6, 7),
+MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0, 8),
+MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5, 7),
+MIX_ENT(SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1, 8),
+MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5, 7),
+MIX_ENT(SOUND_MIXER_IMIX, 16, 1, 0, 5, 17, 1, 0, 5, 8),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8),
+MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5, 7),
+MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5, 7),
+MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 0, 5, 19, 1, 0, 5, 7)
};
/* OPTi 82C930 has somewhat different port addresses.
@@ -124,23 +125,23 @@ MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 0, 5, 19, 1, 0, 5)
* MIC is level of mic monitoring direct to output. Same for CD, LINE, etc.
*/
static mixer_ents c930_mix_devices[32] = {
-MIX_ENT(SOUND_MIXER_VOLUME, 22, 1, 0, 5, 23, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6),
-MIX_ENT(SOUND_MIXER_SPEAKER, 22, 1, 0, 5, 23, 1, 0, 5),
-MIX_ENT(SOUND_MIXER_LINE, 18, 1, 1, 4, 19, 1, 1, 4),
-MIX_ENT(SOUND_MIXER_MIC, 20, 1, 0, 4, 21, 1, 0, 4),
-MIX_ENT(SOUND_MIXER_CD, 2, 1, 1, 4, 3, 1, 1, 4),
-MIX_ENT(SOUND_MIXER_IMIX, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4),
-MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 1, 4, 3, 1, 1, 4),
-MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 1, 4, 5, 1, 1, 4),
-MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 1, 4, 19, 1, 1, 4)
+MIX_ENT(SOUND_MIXER_VOLUME, 22, 1, 0, 5, 23, 1, 0, 5, 7),
+MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5, 7),
+MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6, 7),
+MIX_ENT(SOUND_MIXER_SPEAKER, 22, 1, 0, 5, 23, 1, 0, 5, 8),
+MIX_ENT(SOUND_MIXER_LINE, 18, 1, 1, 4, 19, 1, 1, 4, 7),
+MIX_ENT(SOUND_MIXER_MIC, 20, 1, 0, 4, 21, 1, 0, 4, 8),
+MIX_ENT(SOUND_MIXER_CD, 2, 1, 1, 4, 3, 1, 1, 4, 7),
+MIX_ENT(SOUND_MIXER_IMIX, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8),
+MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 1, 4, 3, 1, 1, 4, 7),
+MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 1, 4, 5, 1, 1, 4, 7),
+MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 1, 4, 19, 1, 1, 4, 7)
};
static int default_mixer_levels[32] =
@@ -155,12 +156,12 @@ static int default_mixer_levels[32] =
0x1010, /* Mic */
0x4b4b, /* CD */
0x0000, /* Recording monitor */
- 0x4b4b, /* SB PCM */
+ 0x4b4b, /* Second PCM */
0x4b4b, /* Recording level */
0x4b4b, /* Input gain */
0x4b4b, /* Output gain */
- 0x4040, /* Line1 */
- 0x4040, /* Line2 */
+ 0x2020, /* Line1 */
+ 0x2020, /* Line2 */
0x1515 /* Line3 (usually line in)*/
};
diff --git a/drivers/sound/audio.c b/drivers/sound/audio.c
index 0ce7c0a9d..d1ba581b1 100644
--- a/drivers/sound/audio.c
+++ b/drivers/sound/audio.c
@@ -21,9 +21,6 @@
#include "ulaw.h"
#include "coproc.h"
-#define ON 1
-#define OFF 0
-
#define NEUTRAL8 0x80
#define NEUTRAL16 0x00
@@ -31,11 +28,12 @@ static int audio_mode[MAX_AUDIO_DEV];
static int dev_nblock[MAX_AUDIO_DEV]; /* 1 if in nonblocking mode */
#define AM_NONE 0
-#define AM_WRITE 1
-#define AM_READ 2
+#define AM_WRITE OPEN_WRITE
+#define AM_READ OPEN_READ
+static int dma_ioctl (int dev, unsigned int cmd, caddr_t arg);
-static int audio_format[MAX_AUDIO_DEV];
+static int local_format[MAX_AUDIO_DEV], audio_format[MAX_AUDIO_DEV];
static int local_conversion[MAX_AUDIO_DEV];
#define CNV_MU_LAW 0x00000001
@@ -44,7 +42,6 @@ set_format (int dev, int fmt)
{
if (fmt != AFMT_QUERY)
{
-
local_conversion[dev] = 0;
if (!(audio_devs[dev]->format_mask & fmt)) /* Not supported */
@@ -57,10 +54,10 @@ set_format (int dev, int fmt)
fmt = AFMT_U8; /* This is always supported */
audio_format[dev] = audio_devs[dev]->d->set_bits (dev, fmt);
+ local_format[dev] = fmt;
}
-
- if (local_conversion[dev]) /* This shadows the HW format */
- return local_conversion[dev];
+ else
+ return local_format[dev];
return audio_format[dev];
}
@@ -98,7 +95,6 @@ audio_open (int dev, struct fileinfo *file)
local_conversion[dev] = 0;
-
if (dev_type == SND_DEV_AUDIO)
{
set_format (dev, AFMT_MU_LAW);
@@ -127,19 +123,12 @@ sync_output (int dev)
/* Align the write pointer with fragment boundaries */
if ((l = dmap->user_counter % dmap->fragment_size) > 0)
{
- char *ptr;
- int err, dummylen, len = dmap->fragment_size - l;
+ int len;
+ unsigned long offs = dmap->user_counter % dmap->bytes_in_use;
- if ((err = DMAbuf_getwrbuffer (dev, &ptr, &dummylen, 1)) >= 0)
- if (dummylen >= len && ((long) ptr % dmap->fragment_size) == l)
- {
- if ((ptr + len) > (dmap->raw_buf + audio_devs[dev]->buffsize))
- printk ("audio: Buffer error 1\n");
- if (ptr < dmap->raw_buf)
- printk ("audio: Buffer error 11\n");
- memset (ptr, dmap->neutral_byte, len);
- DMAbuf_move_wrpointer (dev, len);
- }
+ len = dmap->fragment_size - l;
+ memset (dmap->raw_buf + offs, dmap->neutral_byte, len);
+ DMAbuf_move_wrpointer (dev, len);
}
/*
@@ -153,7 +142,7 @@ sync_output (int dev)
{
p = (p + 1) % dmap->nbufs;
if (((dmap->raw_buf + p * dmap->fragment_size) + dmap->fragment_size) >
- (dmap->raw_buf + audio_devs[dev]->buffsize))
+ (dmap->raw_buf + dmap->buffsize))
printk ("audio: Buffer error 2\n");
memset (dmap->raw_buf + p * dmap->fragment_size,
@@ -241,7 +230,7 @@ audio_write (int dev, struct fileinfo *file, const char *buf, int count)
while (c)
{
- if ((err = DMAbuf_getwrbuffer (dev, &dma_buf, &buf_size, dev_nblock[dev]) < 0))
+ if ((err = DMAbuf_getwrbuffer (dev, &dma_buf, &buf_size, dev_nblock[dev])) < 0)
{
/* Handle nonblocking mode */
if (dev_nblock[dev] && err == -EAGAIN)
@@ -250,17 +239,18 @@ audio_write (int dev, struct fileinfo *file, const char *buf, int count)
}
l = c;
+
if (l > buf_size)
l = buf_size;
if (!audio_devs[dev]->d->copy_user)
{
if ((dma_buf + l) >
- (audio_devs[dev]->dmap_out->raw_buf + audio_devs[dev]->buffsize))
+ (audio_devs[dev]->dmap_out->raw_buf + audio_devs[dev]->dmap_out->buffsize))
printk ("audio: Buffer error 3 (%lx,%d), (%lx, %d)\n",
(long) dma_buf, l,
(long) audio_devs[dev]->dmap_out->raw_buf,
- (int) audio_devs[dev]->buffsize);
+ (int) audio_devs[dev]->dmap_out->buffsize);
if (dma_buf < audio_devs[dev]->dmap_out->raw_buf)
printk ("audio: Buffer error 13\n");
copy_from_user (dma_buf, &(buf)[p], l);
@@ -541,46 +531,10 @@ void
audio_init_devices (void)
{
/*
- * NOTE! This routine could be called several times during boot.
+ * NOTE! This routine could be called several times during boot.
*/
}
-int
-audio_select (int dev, struct fileinfo *file, int sel_type, poll_table * wait)
-{
- dev = dev >> 4;
-
- switch (sel_type)
- {
- case SEL_IN:
- if (!(audio_devs[dev]->open_mode & OPEN_READ))
- return 0;
- if (audio_mode[dev] & AM_WRITE && !(audio_devs[dev]->flags & DMA_DUPLEX))
- {
- return 0; /* Not recording */
- }
-
- return DMAbuf_select (dev, file, sel_type, wait);
- break;
-
- case SEL_OUT:
- if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
- return 0;
- if (audio_mode[dev] & AM_READ && !(audio_devs[dev]->flags & DMA_DUPLEX))
- {
- return 0; /* Wrong direction */
- }
-
- return DMAbuf_select (dev, file, sel_type, wait);
- break;
-
- case SEL_EX:
- return 0;
- }
-
- return 0;
-}
-
#endif
@@ -632,11 +586,11 @@ reorganize_buffers (int dev, struct dma_buffparms *dmap, int recording)
* of sound (using the current speed, sample size and #channels).
*/
- bsz = dsp_dev->buffsize;
+ bsz = dmap->buffsize;
while (bsz > sz)
bsz /= 2;
- if (bsz == dsp_dev->buffsize)
+ if (bsz == dmap->buffsize)
bsz /= 2; /* Needs at least 2 buffers */
/*
@@ -668,17 +622,23 @@ reorganize_buffers (int dev, struct dma_buffparms *dmap, int recording)
* The process has specified the buffer size with SNDCTL_DSP_SETFRAGMENT or
* the buffer size computation has already been done.
*/
- if (dmap->fragment_size > (audio_devs[dev]->buffsize / 2))
- dmap->fragment_size = (audio_devs[dev]->buffsize / 2);
+ if (dmap->fragment_size > (dmap->buffsize / 2))
+ dmap->fragment_size = (dmap->buffsize / 2);
bsz = dmap->fragment_size;
}
- bsz &= ~0x03; /* Force size which is multiple of 4 bytes */
+ if (audio_devs[dev]->min_fragment)
+ if (bsz < (1 << audio_devs[dev]->min_fragment))
+ bsz = 1 << audio_devs[dev]->min_fragment;
+ if (audio_devs[dev]->max_fragment)
+ if (bsz > (1 << audio_devs[dev]->max_fragment))
+ bsz = 1 << audio_devs[dev]->max_fragment;
+ bsz &= ~0x07; /* Force size which is multiple of 8 bytes */
#ifdef OS_DMA_ALIGN_CHECK
OS_DMA_ALIGN_CHECK (bsz);
#endif
- n = dsp_dev->buffsize / bsz;
+ n = dmap->buffsize / bsz;
if (n > MAX_SUB_BUFFERS)
n = MAX_SUB_BUFFERS;
if (n > dmap->max_fragments)
@@ -693,6 +653,8 @@ reorganize_buffers (int dev, struct dma_buffparms *dmap, int recording)
dmap->nbufs = n;
dmap->bytes_in_use = n * bsz;
dmap->fragment_size = bsz;
+ dmap->max_byte_counter = (dmap->data_rate * 60 * 60) +
+ dmap->bytes_in_use; /* Approximately one hour */
if (dmap->raw_buf)
{
@@ -751,6 +713,8 @@ dma_set_fragment (int dev, struct dma_buffparms *dmap, caddr_t arg, int fact)
if (count == 0)
count = MAX_SUB_BUFFERS;
+ else if (count < MAX_SUB_BUFFERS)
+ count++;
if (bytes < 4 || bytes > 17) /* <16 || > 512k */
return -EINVAL;
@@ -762,6 +726,10 @@ dma_set_fragment (int dev, struct dma_buffparms *dmap, caddr_t arg, int fact)
if (bytes < audio_devs[dev]->min_fragment)
bytes = audio_devs[dev]->min_fragment;
+ if (audio_devs[dev]->max_fragment > 0)
+ if (bytes > audio_devs[dev]->max_fragment)
+ bytes = audio_devs[dev]->max_fragment;
+
#ifdef OS_DMA_MINBITS
if (bytes < OS_DMA_MINBITS)
bytes = OS_DMA_MINBITS;
@@ -770,16 +738,16 @@ dma_set_fragment (int dev, struct dma_buffparms *dmap, caddr_t arg, int fact)
dmap->fragment_size = (1 << bytes);
dmap->max_fragments = count;
- if (dmap->fragment_size > audio_devs[dev]->buffsize)
- dmap->fragment_size = audio_devs[dev]->buffsize;
+ if (dmap->fragment_size > dmap->buffsize)
+ dmap->fragment_size = dmap->buffsize;
- if (dmap->fragment_size == audio_devs[dev]->buffsize &&
+ if (dmap->fragment_size == dmap->buffsize &&
audio_devs[dev]->flags & DMA_AUTOMODE)
dmap->fragment_size /= 2; /* Needs at least 2 buffers */
dmap->subdivision = 1; /* Disable SNDCTL_DSP_SUBDIVIDE */
if (arg)
- return (*(int *) arg = bytes | (count << 16));
+ return (*(int *) arg = bytes | ((count - 1) << 16));
else
return 0;
}
@@ -797,16 +765,18 @@ dma_ioctl (int dev, unsigned int cmd, caddr_t arg)
case SNDCTL_DSP_SUBDIVIDE:
{
int fact;
- int ret;
+ int ret = 0;
fact = *(int *) arg;
- ret = dma_subdivide (dev, dmap_out, arg, fact);
+ if (audio_devs[dev]->open_mode & OPEN_WRITE)
+ ret = dma_subdivide (dev, dmap_out, arg, fact);
if (ret < 0)
return ret;
- if (audio_devs[dev]->flags & DMA_DUPLEX &&
- audio_devs[dev]->open_mode & OPEN_READ)
+ if (audio_devs[dev]->open_mode != OPEN_WRITE ||
+ (audio_devs[dev]->flags & DMA_DUPLEX &&
+ audio_devs[dev]->open_mode & OPEN_READ))
ret = dma_subdivide (dev, dmap_in, arg, fact);
return ret;
@@ -824,6 +794,10 @@ dma_ioctl (int dev, unsigned int cmd, caddr_t arg)
!(audio_devs[dev]->open_mode & OPEN_READ))
return -EINVAL;
+ if (cmd == SNDCTL_DSP_GETOSPACE &&
+ !(audio_devs[dev]->open_mode & OPEN_WRITE))
+ return -EINVAL;
+
if (cmd == SNDCTL_DSP_GETISPACE && audio_devs[dev]->flags & DMA_DUPLEX)
dmap = dmap_in;
@@ -843,14 +817,14 @@ dma_ioctl (int dev, unsigned int cmd, caddr_t arg)
info->fragments = 0;
else
{
- info->fragments = dmap->nbufs - dmap->qlen;
+ info->fragments = DMAbuf_space_in_queue (dev);
if (audio_devs[dev]->d->local_qlen)
{
int tmp = audio_devs[dev]->d->local_qlen (dev);
if (tmp && info->fragments)
tmp--; /*
- * This buffer has been counted twice
+ * This buffer has been counted twice
*/
info->fragments -= tmp;
}
@@ -904,6 +878,7 @@ dma_ioctl (int dev, unsigned int cmd, caddr_t arg)
dmap_in->fragment_size, dmap_in->nbufs)) < 0)
return -err;
+ dmap_in->dma_mode = DMODE_INPUT;
audio_devs[dev]->enable_bits = bits;
DMAbuf_activate_recording (dev, dmap_in);
}
@@ -919,7 +894,9 @@ dma_ioctl (int dev, unsigned int cmd, caddr_t arg)
reorganize_buffers (dev, dmap_out, 0);
}
+ dmap_out->dma_mode = DMODE_OUTPUT;
;
+ audio_devs[dev]->enable_bits = bits;
dmap_out->counts[dmap_out->qhead] = dmap_out->fragment_size;
DMAbuf_launch_output (dev, dmap_out);
;
@@ -950,20 +927,24 @@ dma_ioctl (int dev, unsigned int cmd, caddr_t arg)
{
count_info info;
unsigned long flags;
+ struct dma_buffparms *dmap = dmap_in;
if (!(audio_devs[dev]->open_mode & OPEN_READ))
return -EINVAL;
save_flags (flags);
cli ();
- info.bytes = audio_devs[dev]->dmap_in->byte_counter;
- info.ptr = DMAbuf_get_buffer_pointer (dev, audio_devs[dev]->dmap_in) & ~3;
- info.blocks = audio_devs[dev]->dmap_in->qlen;
+ info.bytes = dmap->byte_counter;
+ info.ptr = DMAbuf_get_buffer_pointer (dev, dmap, DMODE_INPUT) & ~3;
+ if (info.ptr < dmap->fragment_size && dmap->qtail != 0)
+ info.bytes += dmap->bytes_in_use; /* Pointer wrap not handled yet */
+
+ info.blocks = dmap->qlen;
info.bytes += info.ptr;
memcpy ((&((char *) arg)[0]), (char *) &info, sizeof (info));
- if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED)
- audio_devs[dev]->dmap_in->qlen = 0; /* Reset interrupt counter */
+ if (dmap->mapping_flags & DMA_MAP_MAPPED)
+ dmap->qlen = 0; /* Reset interrupt counter */
restore_flags (flags);
return 0;
}
@@ -973,20 +954,23 @@ dma_ioctl (int dev, unsigned int cmd, caddr_t arg)
{
count_info info;
unsigned long flags;
+ struct dma_buffparms *dmap = dmap_out;
if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
return -EINVAL;
save_flags (flags);
cli ();
- info.bytes = audio_devs[dev]->dmap_out->byte_counter;
- info.ptr = DMAbuf_get_buffer_pointer (dev, audio_devs[dev]->dmap_out) & ~3;
- info.blocks = audio_devs[dev]->dmap_out->qlen;
+ info.bytes = dmap->byte_counter;
+ info.ptr = DMAbuf_get_buffer_pointer (dev, dmap, DMODE_OUTPUT) & ~3;
+ if (info.ptr < dmap->fragment_size && dmap->qhead != 0)
+ info.bytes += dmap->bytes_in_use; /* Pointer wrap not handled yet */
+ info.blocks = dmap->qlen;
info.bytes += info.ptr;
memcpy ((&((char *) arg)[0]), (char *) &info, sizeof (info));
- if (audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED)
- audio_devs[dev]->dmap_out->qlen = 0; /* Reset interrupt counter */
+ if (dmap->mapping_flags & DMA_MAP_MAPPED)
+ dmap->qlen = 0; /* Reset interrupt counter */
restore_flags (flags);
return 0;
@@ -1004,18 +988,23 @@ dma_ioctl (int dev, unsigned int cmd, caddr_t arg)
break;
case SNDCTL_DSP_GETBLKSIZE:
- if (!(dmap_out->flags & DMA_ALLOC_DONE))
- {
- if (audio_devs[dev]->open_mode & OPEN_WRITE)
- reorganize_buffers (dev, dmap_out,
- (audio_devs[dev]->open_mode == OPEN_READ));
- if (audio_devs[dev]->flags & DMA_DUPLEX &&
- audio_devs[dev]->open_mode & OPEN_READ)
- reorganize_buffers (dev, dmap_in,
- (audio_devs[dev]->open_mode == OPEN_READ));
- }
+ {
+ int fragment_size;
+ struct dma_buffparms *dmap = dmap_out;
- return (*(int *) arg = dmap_out->fragment_size);
+ if (audio_devs[dev]->open_mode & OPEN_WRITE)
+ reorganize_buffers (dev, dmap_out,
+ (audio_devs[dev]->open_mode == OPEN_READ));
+ if (audio_devs[dev]->open_mode != OPEN_WRITE ||
+ (audio_devs[dev]->flags & DMA_DUPLEX &&
+ audio_devs[dev]->open_mode & OPEN_READ))
+ reorganize_buffers (dev, dmap_in,
+ (audio_devs[dev]->open_mode == OPEN_READ));
+ if (audio_devs[dev]->open_mode == OPEN_READ)
+ dmap = dmap_in;
+ fragment_size = dmap->fragment_size;
+ return (*(int *) arg = fragment_size);
+ }
break;
case SNDCTL_DSP_SETFRAGMENT:
diff --git a/drivers/sound/configure.c b/drivers/sound/configure.c
index f5d2a8344..ee6830b2a 100644
--- a/drivers/sound/configure.c
+++ b/drivers/sound/configure.c
@@ -145,7 +145,7 @@ hw_entry hw_table[] =
char *questions[] =
{
"ProAudioSpectrum 16 support",
- "_TRUE_ Sound Blaster (SB, SBPro, SB16/32/64, ESS, Jazz16) support",
+ "100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support",
"Generic OPL2/OPL3 FM synthesizer support",
"Gravis Ultrasound support",
"MPU-401 support (NOT for SB16)",
diff --git a/drivers/sound/dev_table.c b/drivers/sound/dev_table.c
index 7f24da62a..10daa50ad 100644
--- a/drivers/sound/dev_table.c
+++ b/drivers/sound/dev_table.c
@@ -15,6 +15,7 @@
#define _DEV_TABLE_C_
#include "sound_config.h"
+int sb_be_quiet = 0;
int sound_started = 0;
@@ -43,20 +44,15 @@ start_services (void)
#ifdef CONFIG_AUDIO
if (num_audiodevs) /* Audio devices present */
{
- DMAbuf_init ();
+ int dev;
+
+ for (dev = 0; dev < num_audiodevs; dev++)
+ {
+ }
audio_init_devices ();
}
#endif
-#ifdef CONFIG_MIDI
- if (num_midis)
- MIDIbuf_init ();
-#endif
-
-#ifdef CONFIG_SEQUENCER
- if (num_midis + num_synths)
- sequencer_init ();
-#endif
return;
}
@@ -493,17 +489,11 @@ sound_install_audiodrv (int vers,
/*
* Hardcoded defaults
*/
- op->buffsize = DSP_BUFFSIZE;
-
audio_devs[num_audiodevs] = op;
num = num_audiodevs++;
- DMAbuf_init ();
-
- op->dmap_out->dma = dma1;
- op->dmap_in->dma = dma2;
+ DMAbuf_init (num, dma1, dma2);
- DMAbuf_init ();
audio_init_devices ();
return num;
#else
diff --git a/drivers/sound/dev_table.h b/drivers/sound/dev_table.h
index cef6dc113..7013c3c8d 100644
--- a/drivers/sound/dev_table.h
+++ b/drivers/sound/dev_table.h
@@ -70,6 +70,7 @@ struct dma_buffparms {
char *raw_buf;
unsigned long raw_buf_phys;
+ int buffsize;
/*
* Device state tables
@@ -85,6 +86,8 @@ struct dma_buffparms {
#define DMA_SYNCING 0x00000040
#define DMA_DIRTY 0x00000080
#define DMA_POST 0x00000100
+#define DMA_NODMA 0x00000200
+#define DMA_NOTIMEOUT 0x00000400
int open_mode;
@@ -109,6 +112,7 @@ struct dma_buffparms {
int underrun_count;
unsigned long byte_counter;
unsigned long user_counter;
+ unsigned long max_byte_counter;
int data_rate; /* Bytes/second */
int mapping_flags;
@@ -120,6 +124,9 @@ struct dma_buffparms {
OS_DMA_PARMS
#endif
int applic_profile; /* Application profile (APF_*) */
+ int buf_flags[MAX_SUB_BUFFERS];
+#define BUFF_EOF 0x00000001 /* Increment eof count */
+#define BUFF_DIRTY 0x00000002 /* Buffer written */
};
/*
@@ -156,6 +163,8 @@ struct audio_driver {
int (*set_speed)(int dev, int speed);
unsigned int (*set_bits)(int dev, unsigned int bits);
short (*set_channels)(int dev, short channels);
+ void (*postprocess_write)(int dev); /* Device spesific postprocessing for written data */
+ void (*preprocess_read)(int dev); /* Device spesific preprocessing for read data */
};
struct audio_operations {
@@ -167,13 +176,12 @@ struct audio_operations {
#define DMA_DUPLEX 0x04
#define DMA_PSEUDO_AUTOMODE 0x08
#define DMA_HARDSTOP 0x10
-#define DMA_NODMA 0x20
#define DMA_EXACT 0x40
+#define DMA_NORESET 0x80
int format_mask; /* Bitmask for supported audio formats */
void *devc; /* Driver specific info */
struct audio_driver *d;
void *portc; /* Driver spesific info */
- long buffsize;
struct dma_buffparms *dmap_in, *dmap_out;
struct coproc_operations *coproc;
int mixer_dev;
@@ -181,6 +189,7 @@ struct audio_operations {
int open_mode;
int go;
int min_fragment; /* 0 == unlimited */
+ int max_fragment; /* 0 == unlimited */
int parent_dev; /* 0 -> no parent, 1 to n -> parent=parent_dev+1 */
};
@@ -292,7 +301,7 @@ struct sound_timer_operations {
struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV] = {NULL}; int num_synths = 0;
struct midi_operations *midi_devs[MAX_MIDI_DEV] = {NULL}; int num_midis = 0;
-#if defined(CONFIG_SEQUENCER) && !defined(EXCLUDE_TIMERS)
+#if defined(CONFIG_SEQUENCER) && !defined(EXCLUDE_TIMERS) && !defined(VMIDI)
extern struct sound_timer_operations default_sound_timer;
struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] =
{&default_sound_timer, NULL};
@@ -313,6 +322,15 @@ struct sound_timer_operations {
{"PSSMPU", 0, SNDCARD_PSS_MPU, "PSS-MPU", attach_pss_mpu, probe_pss_mpu, unload_pss_mpu},
{"PSSMSS", 0, SNDCARD_PSS_MSS, "PSS-MSS", attach_pss_mss, probe_pss_mss, unload_pss_mss},
#endif
+
+#ifdef CONFIG_GUS16
+ {"GUS16", 0, SNDCARD_GUS16, "Ultrasound 16-bit opt.", attach_gus_db16, probe_gus_db16, unload_gus_db16},
+#endif
+#ifdef CONFIG_GUSHW
+ {"GUS", 0, SNDCARD_GUS, "Gravis Ultrasound", attach_gus_card, probe_gus, unload_gus},
+ {"GUSPNP", 1, SNDCARD_GUSPNP, "GUS PnP", attach_gus_card, probe_gus, unload_gus},
+#endif
+
#ifdef CONFIG_MSS
{"MSS", 0, SNDCARD_MSS, "MS Sound System", attach_ms_sound, probe_ms_sound, unload_ms_sound},
/* Compaq Deskpro XL */
@@ -358,15 +376,6 @@ struct sound_timer_operations {
# endif
#endif
-
-
-#ifdef CONFIG_GUS16
- {"GUS16", 0, SNDCARD_GUS16, "Ultrasound 16-bit opt.", attach_gus_db16, probe_gus_db16, unload_gus_db16},
-#endif
-#ifdef CONFIG_GUSHW
- {"GUS", 0, SNDCARD_GUS, "Gravis Ultrasound", attach_gus_card, probe_gus, unload_gus},
- {"GUSPNP", 1, SNDCARD_GUSPNP, "GUS PnP", attach_gus_card, probe_gus, unload_gus},
-#endif
#ifdef CONFIG_SSCAPEHW
{"SSCAPE", 0, SNDCARD_SSCAPE, "Ensoniq SoundScape", attach_sscape, probe_sscape, unload_sscape},
{"SSCAPEMSS", 0, SNDCARD_SSCAPE_MSS, "MS Sound System (SoundScape)", attach_ss_ms_sound, probe_ss_ms_sound, unload_ss_ms_sound},
@@ -377,6 +386,10 @@ struct sound_timer_operations {
{"TRXPROMPU", 0, SNDCARD_TRXPRO_MPU, "AudioTrix MIDI", attach_trix_mpu, probe_trix_mpu, unload_trix_mpu},
#endif
+
+
+
+
{NULL, 0, 0, "*?*", NULL, NULL, NULL}
};
@@ -439,6 +452,10 @@ struct sound_timer_operations {
#ifdef CONFIG_MSS
+# ifndef MSS_DMA2
+# define MSS_DMA2 -1
+# endif
+
# ifdef DESKPROXL
{SNDCARD_DESKPROXL, {MSS_BASE, MSS_IRQ, MSS_DMA, MSS_DMA2}, SND_DEFAULT_ENABLE},
# else
diff --git a/drivers/sound/dmabuf.c b/drivers/sound/dmabuf.c
index 6be1cfe64..38b7af597 100644
--- a/drivers/sound/dmabuf.c
+++ b/drivers/sound/dmabuf.c
@@ -12,7 +12,7 @@
*/
#include <linux/config.h>
-#undef BE_CONSERVATIVE
+#define BE_CONSERVATIVE
#include "sound_config.h"
@@ -44,18 +44,11 @@ static int local_start_dma (int dev, unsigned long physaddr, int count, int
static void
dma_init_buffers (int dev, struct dma_buffparms *dmap)
{
- if (dmap == audio_devs[dev]->dmap_out)
- {
- out_sleep_flag[dev].opts = WK_NONE;
- }
- else
- {
- in_sleep_flag[dev].opts = WK_NONE;
- }
dmap->qlen = dmap->qhead = dmap->qtail = dmap->user_counter = 0;
dmap->byte_counter = 0;
- dmap->bytes_in_use = audio_devs[dev]->buffsize;
+ dmap->max_byte_counter = 8000 * 60 * 60;
+ dmap->bytes_in_use = dmap->buffsize;
dmap->dma_mode = DMODE_NONE;
dmap->mapping_flags = 0;
@@ -92,16 +85,25 @@ open_dmap (int dev, int mode, struct dma_buffparms *dmap, int chan)
return -EBUSY;
}
+ dma_init_buffers (dev, dmap);
dmap->open_mode = mode;
dmap->subdivision = dmap->underrun_count = 0;
dmap->fragment_size = 0;
dmap->max_fragments = 65536; /* Just a large value */
dmap->byte_counter = 0;
+ dmap->max_byte_counter = 8000 * 60 * 60;
dmap->applic_profile = APF_NORMAL;
dmap->needs_reorg = 1;
- dma_init_buffers (dev, dmap);
+ if (dmap->dma_mode & DMODE_OUTPUT)
+ {
+ out_sleep_flag[dev].opts = WK_NONE;
+ }
+ else
+ {
+ in_sleep_flag[dev].opts = WK_NONE;
+ }
return 0;
}
@@ -224,6 +226,13 @@ DMAbuf_open (int dev, int mode)
audio_devs[dev]->d->set_channels (dev, 1);
audio_devs[dev]->d->set_speed (dev, DSP_DEFAULT_SPEED);
+ if (audio_devs[dev]->dmap_out->dma_mode == DMODE_OUTPUT)
+ {
+ memset (audio_devs[dev]->dmap_out->raw_buf,
+ audio_devs[dev]->dmap_out->neutral_byte,
+ audio_devs[dev]->dmap_out->bytes_in_use);
+ }
+
return 0;
}
@@ -335,7 +344,12 @@ dma_reset_input (int dev)
void
DMAbuf_launch_output (int dev, struct dma_buffparms *dmap)
{
- if (!(dmap->flags & DMA_ACTIVE) || !(audio_devs[dev]->flags & DMA_AUTOMODE))
+ if (!((audio_devs[dev]->enable_bits * audio_devs[dev]->go) & PCM_ENABLE_OUTPUT))
+ return; /* Don't start DMA yet */
+
+ dmap->dma_mode = DMODE_OUTPUT;
+
+ if (!(dmap->flags & DMA_ACTIVE) || !(audio_devs[dev]->flags & DMA_AUTOMODE) || dmap->flags & DMA_NODMA)
{
if (!(dmap->flags & DMA_STARTED))
{
@@ -345,12 +359,17 @@ DMAbuf_launch_output (int dev, struct dma_buffparms *dmap)
dmap->fragment_size, dmap->nbufs))
return;
- local_start_dma (dev, dmap->raw_buf_phys, dmap->bytes_in_use,
- DMA_MODE_WRITE);
+ if (!(dmap->flags & DMA_NODMA))
+ {
+ local_start_dma (dev, dmap->raw_buf_phys, dmap->bytes_in_use,
+ DMA_MODE_WRITE);
+ }
+ dmap->flags |= DMA_STARTED;
}
if (dmap->counts[dmap->qhead] == 0)
dmap->counts[dmap->qhead] = dmap->fragment_size;
+ dmap->dma_mode = DMODE_OUTPUT;
audio_devs[dev]->d->output_block (dev, dmap->raw_buf_phys +
dmap->qhead * dmap->fragment_size,
dmap->counts[dmap->qhead], 1);
@@ -560,7 +579,7 @@ int
DMAbuf_getrdbuffer (int dev, char **buf, int *len, int dontblock)
{
unsigned long flags;
- int err = EIO;
+ int err = 0, n = 0;
struct dma_buffparms *dmap = audio_devs[dev]->dmap_in;
if (!(audio_devs[dev]->open_mode & OPEN_READ))
@@ -575,77 +594,82 @@ DMAbuf_getrdbuffer (int dev, char **buf, int *len, int dontblock)
printk ("Sound: Can't read from mmapped device (1)\n");
return -EINVAL;
}
- else if (!dmap->qlen)
- {
- int tmout;
+ else
+ while (dmap->qlen <= 0 && n++ < 10)
+ {
+ int tmout;
- if (!(audio_devs[dev]->enable_bits & PCM_ENABLE_INPUT) ||
- !audio_devs[dev]->go)
- {
- restore_flags (flags);
- return -EAGAIN;
- }
+ if (!(audio_devs[dev]->enable_bits & PCM_ENABLE_INPUT) ||
+ !audio_devs[dev]->go)
+ {
+ restore_flags (flags);
+ return -EAGAIN;
+ }
- if ((err = DMAbuf_activate_recording (dev, dmap)) < 0)
- {
- restore_flags (flags);
- return err;
- }
+ if ((err = DMAbuf_activate_recording (dev, dmap)) < 0)
+ {
+ restore_flags (flags);
+ return err;
+ }
- /* Wait for the next block */
+ /* Wait for the next block */
- if (dontblock)
- {
- restore_flags (flags);
- return -EAGAIN;
- }
+ if (dontblock)
+ {
+ restore_flags (flags);
+ return -EAGAIN;
+ }
- if (!audio_devs[dev]->go)
- tmout = 0;
- else
- {
- tmout =
- (dmap->fragment_size * HZ) / dmap->data_rate;
+ if (!audio_devs[dev]->go)
+ tmout = 0;
+ else
+ {
+ tmout =
+ (dmap->fragment_size * HZ) / dmap->data_rate;
- tmout += HZ / 10; /* Some safety distance */
+ tmout += HZ / 10; /* Some safety distance */
- if (tmout < (HZ / 2))
- tmout = HZ / 2;
- if (tmout > 20 * HZ)
- tmout = 20 * HZ;
- }
+ if (tmout < (HZ / 2))
+ tmout = HZ / 2;
+ if (tmout > 20 * HZ)
+ tmout = 20 * HZ;
+ }
- {
- unsigned long tlimit;
+ {
+ unsigned long tlimit;
- if (tmout)
- current->timeout = tlimit = jiffies + (tmout);
- else
- tlimit = (unsigned long) -1;
- in_sleep_flag[dev].opts = WK_SLEEP;
- interruptible_sleep_on (&in_sleeper[dev]);
- if (!(in_sleep_flag[dev].opts & WK_WAKEUP))
+ if (tmout)
+ current->timeout = tlimit = jiffies + (tmout);
+ else
+ tlimit = (unsigned long) -1;
+ in_sleep_flag[dev].opts = WK_SLEEP;
+ interruptible_sleep_on (&in_sleeper[dev]);
+ if (!(in_sleep_flag[dev].opts & WK_WAKEUP))
+ {
+ if (jiffies >= tlimit)
+ in_sleep_flag[dev].opts |= WK_TIMEOUT;
+ }
+ in_sleep_flag[dev].opts &= ~WK_SLEEP;
+ };
+ if ((in_sleep_flag[dev].opts & WK_TIMEOUT))
{
- if (jiffies >= tlimit)
- in_sleep_flag[dev].opts |= WK_TIMEOUT;
+ err = -EIO;
+ printk ("Sound: DMA (input) timed out - IRQ/DRQ config error?\n");
+ dma_reset_input (dev);
+ ;
}
- in_sleep_flag[dev].opts &= ~WK_SLEEP;
- };
- if ((in_sleep_flag[dev].opts & WK_TIMEOUT))
- {
- printk ("Sound: DMA (input) timed out - IRQ/DRQ config error?\n");
- err = EIO;
- dma_reset_input (dev);
- ;
- }
- else
- err = EINTR;
- }
+ else
+ err = -EINTR;
+ }
restore_flags (flags);
- if (!dmap->qlen)
- return -err;
+ if (dmap->qlen <= 0)
+ {
+ if (err == 0)
+ err = -EINTR;
+ return err;
+ }
*buf = &dmap->raw_buf[dmap->qhead * dmap->fragment_size + dmap->counts[dmap->qhead]];
*len = dmap->fragment_size - dmap->counts[dmap->qhead];
@@ -660,17 +684,16 @@ DMAbuf_rmchars (int dev, int buff_no, int c)
int p = dmap->counts[dmap->qhead] + c;
- if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED)
+ if (dmap->mapping_flags & DMA_MAP_MAPPED)
{
printk ("Sound: Can't read from mmapped device (2)\n");
return -EINVAL;
}
+ else if (dmap->qlen <= 0)
+ return -EIO;
else if (p >= dmap->fragment_size)
{ /* This buffer is completely empty */
dmap->counts[dmap->qhead] = 0;
- if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)
- printk ("\nSound: Audio queue1 corrupted for dev%d (%d/%d)\n",
- dev, dmap->qlen, dmap->nbufs);
dmap->qlen--;
dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;
}
@@ -681,7 +704,7 @@ DMAbuf_rmchars (int dev, int buff_no, int c)
}
int
-DMAbuf_get_buffer_pointer (int dev, struct dma_buffparms *dmap)
+DMAbuf_get_buffer_pointer (int dev, struct dma_buffparms *dmap, int direction)
{
/*
* Try to approximate the active byte position of the DMA pointer within the
@@ -689,7 +712,6 @@ DMAbuf_get_buffer_pointer (int dev, struct dma_buffparms *dmap)
*/
int pos;
unsigned long flags;
- int chan = dmap->dma;
save_flags (flags);
cli ();
@@ -697,26 +719,31 @@ DMAbuf_get_buffer_pointer (int dev, struct dma_buffparms *dmap)
pos = 0;
else
{
+ int chan = dmap->dma;
+
clear_dma_ff (chan);
disable_dma (dmap->dma);
pos = get_dma_residue (chan);
pos = dmap->bytes_in_use - pos;
- if (dmap->flags & DMODE_OUTPUT)
- {
- if (dmap->qhead == 0)
- pos %= dmap->bytes_in_use;
- }
- else
- {
- if (dmap->qtail == 0)
- pos %= dmap->bytes_in_use;
- }
+ if (!(dmap->mapping_flags & DMA_MAP_MAPPED))
+ if (direction == DMODE_OUTPUT)
+ {
+ if (dmap->qhead == 0)
+ if (pos > dmap->fragment_size)
+ pos = 0;
+ }
+ else
+ {
+ if (dmap->qtail == 0)
+ if (pos > dmap->fragment_size)
+ pos = 0;
+ }
if (pos < 0)
pos = 0;
- if (pos > dmap->bytes_in_use)
- pos = dmap->bytes_in_use;
+ if (pos >= dmap->bytes_in_use)
+ pos = 0;
enable_dma (dmap->dma);
}
restore_flags (flags);
@@ -760,8 +787,8 @@ DMAbuf_space_in_queue (int dev)
int len, max, tmp;
struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
- /* Don't allow touching pages too close to the playing ones */
- int lim = dmap->nbufs - 1;
+ int lim = dmap->nbufs;
+
if (lim < 2)
lim = 2;
@@ -789,7 +816,7 @@ DMAbuf_space_in_queue (int dev)
if (len >= max)
return 0;
- return 1;
+ return max - len;
}
static int
@@ -812,7 +839,7 @@ output_sleep (int dev, int dontblock)
/*
* Wait for free space
*/
- if (!audio_devs[dev]->go)
+ if (!audio_devs[dev]->go || dmap->flags & DMA_NOTIMEOUT)
tmout = 0;
else
{
@@ -850,13 +877,12 @@ output_sleep (int dev, int dontblock)
if ((out_sleep_flag[dev].opts & WK_TIMEOUT))
{
printk ("Sound: DMA (output) timed out - IRQ/DRQ config error?\n");
- err = EIO;
;
dma_reset_output (dev);
}
else if ((current->signal & ~current->blocked))
{
- err = EINTR;
+ err = -EINTR;
}
return err;
@@ -869,19 +895,24 @@ find_output_space (int dev, char **buf, int *size)
unsigned long flags;
unsigned long offs, active_offs;
long len;
+ int maxfrags;
- if (!DMAbuf_space_in_queue (dev))
- return 0;
+ if (!(maxfrags = DMAbuf_space_in_queue (dev)))
+ {
+ return 0;
+ }
save_flags (flags);
cli ();
#ifdef BE_CONSERVATIVE
- active_offs = dmap->byte_counter + (dmap->qhead + 1) * dmap->fragment_size;
+ active_offs = dmap->byte_counter + dmap->qhead * dmap->fragment_size;
#else
- active_offs = ((dmap->byte_counter + DMAbuf_get_buffer_pointer (dev, dmap)));
- /* / dmap->fragment_size) * dmap->fragment_size; */
-
+ active_offs = DMAbuf_get_buffer_pointer (dev, dmap, DMODE_OUTPUT);
+ /* Check for pointer wrapping situation */
+ if (active_offs < 0 || active_offs >= dmap->bytes_in_use)
+ active_offs = 0;
+ active_offs += dmap->byte_counter;
#endif
offs = (dmap->user_counter % dmap->bytes_in_use) & ~3;
@@ -898,13 +929,12 @@ find_output_space (int dev, char **buf, int *size)
return 0;
}
- if ((offs + len) > dmap->bytes_in_use)
- len = dmap->bytes_in_use - offs;
+ if (len > maxfrags * dmap->fragment_size)
+ len = maxfrags * dmap->fragment_size;
*size = len & ~3;
restore_flags (flags);
-
return (len > 0);
}
@@ -912,7 +942,7 @@ int
DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock)
{
unsigned long flags;
- int err = EIO;
+ int err = -EIO;
struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
if (dmap->needs_reorg)
@@ -944,14 +974,8 @@ DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock)
}
}
- if (!find_output_space (dev, buf, size))
- {
- restore_flags (flags);
- return -EIO; /* Caught a signal ? */
- }
restore_flags (flags);
- dmap->flags |= DMA_DIRTY;
return 0;
}
@@ -962,7 +986,7 @@ DMAbuf_move_wrpointer (int dev, int l)
unsigned long ptr = (dmap->user_counter / dmap->fragment_size)
* dmap->fragment_size;
- unsigned long end_ptr, p, prev_count;
+ unsigned long end_ptr, p;
int post = (dmap->flags & DMA_POST);
;
@@ -971,12 +995,16 @@ DMAbuf_move_wrpointer (int dev, int l)
dmap->cfrag = -1;
- prev_count = dmap->user_counter;
dmap->user_counter += l;
+ dmap->flags |= DMA_DIRTY;
+
+ if (dmap->user_counter >= dmap->max_byte_counter)
+ { /* Wrap the byte counters */
+ long decr = dmap->user_counter;
- if (dmap->user_counter < prev_count) /* Wrap? */
- { /* Wrap the device counter too */
- dmap->byte_counter %= dmap->bytes_in_use;
+ dmap->user_counter = (dmap->user_counter % dmap->bytes_in_use) + dmap->bytes_in_use;
+ decr -= dmap->user_counter;
+ dmap->byte_counter -= decr;
}
end_ptr = (dmap->user_counter / dmap->fragment_size) * dmap->fragment_size;
@@ -995,6 +1023,13 @@ DMAbuf_move_wrpointer (int dev, int l)
dmap->counts[dmap->qtail] = dmap->user_counter - ptr;
+/*
+ * Let the low level driver to perform some postprocessing to
+ * the written data.
+ */
+ if (audio_devs[dev]->d->postprocess_write)
+ audio_devs[dev]->d->postprocess_write (dev);
+
if (!(dmap->flags & DMA_ACTIVE))
if (dmap->qlen > 1 ||
(dmap->qlen > 0 && (post || dmap->qlen >= dmap->nbufs - 1)))
@@ -1034,11 +1069,6 @@ DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
if (chan < 0)
return 0;
- /*
- * The count must be one less than the actual size. This is handled by
- * set_dma_addr()
- */
-
sound_start_dma (dev, dmap, chan, physaddr, count, dma_mode, 0);
return count;
@@ -1069,14 +1099,14 @@ local_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
return 0;
}
+ if (dmap->flags & DMA_NODMA)
+ {
+ return 1;
+ }
+
if (chan < 0)
return 0;
- /*
- * The count must be one less than the actual size. This is handled by
- * set_dma_addr()
- */
-
sound_start_dma (dev, dmap, chan, dmap->raw_buf_phys, dmap->bytes_in_use, dma_mode, 1);
dmap->flags |= DMA_STARTED;
@@ -1100,19 +1130,9 @@ finish_output_interrupt (int dev, struct dma_buffparms *dmap)
restore_flags (flags);
}
-void
-DMAbuf_outputintr (int dev, int event_type)
+static void
+do_outputintr (int dev, int dummy)
{
- /*
- * Event types:
- * 0 = DMA transfer done. Device still has more data in the local
- * buffer.
- * 1 = DMA transfer done. Device doesn't have local buffer or it's
- * empty now.
- * 2 = No DMA transfer but the device has now more space in it's local
- * buffer.
- */
-
unsigned long flags;
struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
int this_fragment;
@@ -1128,18 +1148,20 @@ DMAbuf_outputintr (int dev, int event_type)
return;
}
- if (dmap->mapping_flags & DMA_MAP_MAPPED)
+ if (dmap->mapping_flags & DMA_MAP_MAPPED) /* Virtual memory mapped access */
{
- unsigned long prev_counter = dmap->byte_counter;
-
/* mmapped access */
dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;
if (dmap->qhead == 0) /* Wrapped */
{
dmap->byte_counter += dmap->bytes_in_use;
- if (dmap->byte_counter < prev_counter) /* Overflow */
+ if (dmap->byte_counter >= dmap->max_byte_counter) /* Overflow */
{
- dmap->user_counter %= dmap->bytes_in_use;
+ long decr = dmap->byte_counter;
+
+ dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use;
+ decr -= dmap->byte_counter;
+ dmap->user_counter -= decr;
}
}
@@ -1153,21 +1175,6 @@ DMAbuf_outputintr (int dev, int event_type)
return;
}
- if (event_type == 2)
- {
- finish_output_interrupt (dev, dmap);
- return;
- }
-
- if (dmap->qlen > dmap->nbufs)
- dmap->qlen = dmap->nbufs;
-
- if (dmap->qlen <= 0)
- {
- finish_output_interrupt (dev, dmap);
- return;
- }
-
save_flags (flags);
cli ();
@@ -1177,32 +1184,34 @@ DMAbuf_outputintr (int dev, int event_type)
if (dmap->qhead == 0) /* Wrapped */
{
- unsigned long prev_counter = dmap->byte_counter;
-
dmap->byte_counter += dmap->bytes_in_use;
- if (dmap->byte_counter < prev_counter) /* Overflow */
+ if (dmap->byte_counter >= dmap->max_byte_counter) /* Overflow */
{
- dmap->user_counter %= dmap->bytes_in_use;
+ long decr = dmap->byte_counter;
+
+ dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use;
+ decr -= dmap->byte_counter;
+ dmap->user_counter -= decr;
}
}
if (!(audio_devs[dev]->flags & DMA_AUTOMODE))
dmap->flags &= ~DMA_ACTIVE;
- if (event_type == 1 && dmap->qlen < 1)
+ while (dmap->qlen < 0)
{
dmap->underrun_count++;
- dmap->qlen = 0;
+ dmap->qlen++;
if (dmap->flags & DMA_DIRTY && dmap->applic_profile != APF_CPUINTENS)
{
dmap->flags &= ~DMA_DIRTY;
memset (audio_devs[dev]->dmap_out->raw_buf,
audio_devs[dev]->dmap_out->neutral_byte,
- audio_devs[dev]->dmap_out->bytes_in_use);
+ audio_devs[dev]->dmap_out->buffsize);
}
dmap->user_counter += dmap->fragment_size;
- dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;
+ dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
}
if (dmap->qlen > 0)
@@ -1213,10 +1222,43 @@ DMAbuf_outputintr (int dev, int event_type)
}
void
-DMAbuf_inputintr (int dev)
+DMAbuf_outputintr (int dev, int notify_only)
{
unsigned long flags;
+ struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
+
+ save_flags (flags);
+ cli ();
+
+ if (!(dmap->flags & DMA_NODMA))
+ {
+ int chan = dmap->dma, pos, n;
+
+ clear_dma_ff (chan);
+ disable_dma (dmap->dma);
+ pos = dmap->bytes_in_use - get_dma_residue (chan);
+ enable_dma (dmap->dma);
+
+ pos = pos / dmap->fragment_size; /* Actual qhead */
+ if (pos < 0 || pos >= dmap->nbufs)
+ pos = 0;
+
+ n = 0;
+ while (dmap->qhead != pos && n++ < dmap->nbufs)
+ {
+ do_outputintr (dev, notify_only);
+ }
+ }
+ else
+ do_outputintr (dev, notify_only);
+ restore_flags (flags);
+}
+
+static void
+do_inputintr (int dev)
+{
struct dma_buffparms *dmap = audio_devs[dev]->dmap_in;
+ unsigned long flags;
#ifdef OS_DMA_INTR
if (audio_devs[dev]->dmap_in->dma >= 0)
@@ -1234,12 +1276,14 @@ DMAbuf_inputintr (int dev)
dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
if (dmap->qtail == 0) /* Wrapped */
{
- unsigned long prev_counter = dmap->byte_counter;
-
dmap->byte_counter += dmap->bytes_in_use;
- if (dmap->byte_counter < prev_counter) /* Overflow */
+ if (dmap->byte_counter >= dmap->max_byte_counter) /* Overflow */
{
- dmap->user_counter %= dmap->bytes_in_use;
+ long decr = dmap->byte_counter;
+
+ dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use;
+ decr -= dmap->byte_counter;
+ dmap->user_counter -= decr;
}
}
dmap->qlen++;
@@ -1267,30 +1311,28 @@ DMAbuf_inputintr (int dev)
/* Just throw away the oldest fragment but keep the engine running */
dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;
+ dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
}
- else
+ else if (dmap->qlen >= 0 && dmap->qlen < dmap->nbufs)
{
dmap->qlen++;
- if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)
- printk ("\nSound: Audio queue4 corrupted for dev%d (%d/%d)\n",
- dev, dmap->qlen, dmap->nbufs);
dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
if (dmap->qtail == 0) /* Wrapped */
{
- unsigned long prev_counter = dmap->byte_counter;
-
dmap->byte_counter += dmap->bytes_in_use;
- if (dmap->byte_counter < prev_counter) /* Overflow */
+ if (dmap->byte_counter >= dmap->max_byte_counter) /* Overflow */
{
- dmap->user_counter %= dmap->bytes_in_use;
+ long decr = dmap->byte_counter;
+
+ dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use;
+ decr -= dmap->byte_counter;
+ dmap->user_counter -= decr;
}
}
}
- if (!(audio_devs[dev]->flags & DMA_AUTOMODE))
+ if (!(audio_devs[dev]->flags & DMA_AUTOMODE) || dmap->flags & DMA_NODMA)
{
- if (dmap->needs_reorg)
- reorganize_buffers (dev, dmap, 0);
local_start_dma (dev, dmap->raw_buf_phys, dmap->bytes_in_use,
DMA_MODE_READ);
audio_devs[dev]->d->start_input (dev, dmap->raw_buf_phys +
@@ -1305,13 +1347,47 @@ DMAbuf_inputintr (int dev)
save_flags (flags);
cli ();
- if ((in_sleep_flag[dev].opts & WK_SLEEP))
- {
+ if (dmap->qlen > 0)
+ if ((in_sleep_flag[dev].opts & WK_SLEEP))
{
- in_sleep_flag[dev].opts = WK_WAKEUP;
- wake_up (&in_sleeper[dev]);
- };
+ {
+ in_sleep_flag[dev].opts = WK_WAKEUP;
+ wake_up (&in_sleeper[dev]);
+ };
+ }
+ restore_flags (flags);
+}
+
+void
+DMAbuf_inputintr (int dev)
+{
+ struct dma_buffparms *dmap = audio_devs[dev]->dmap_in;
+ unsigned long flags;
+
+ save_flags (flags);
+ cli ();
+
+ if (!(dmap->flags & DMA_NODMA))
+ {
+ int chan = dmap->dma, pos, n;
+
+ clear_dma_ff (chan);
+ disable_dma (dmap->dma);
+ pos = dmap->bytes_in_use - get_dma_residue (chan);
+ enable_dma (dmap->dma);
+
+ pos = pos / dmap->fragment_size; /* Actual qhead */
+ if (pos < 0 || pos >= dmap->nbufs)
+ pos = 0;
+
+ n = 0;
+ while (dmap->qtail != pos && ++n < dmap->nbufs)
+ {
+ do_inputintr (dev);
+ }
}
+ else
+ do_inputintr (dev);
restore_flags (flags);
}
@@ -1330,8 +1406,9 @@ DMAbuf_open_dma (int dev)
return -EBUSY;
}
dma_init_buffers (dev, audio_devs[dev]->dmap_out);
+ out_sleep_flag[dev].opts = WK_NONE;
audio_devs[dev]->dmap_out->flags |= DMA_ALLOC_DONE;
- audio_devs[dev]->dmap_out->fragment_size = audio_devs[dev]->buffsize;
+ audio_devs[dev]->dmap_out->fragment_size = audio_devs[dev]->dmap_out->buffsize;
if (chan >= 0)
{
@@ -1339,7 +1416,7 @@ DMAbuf_open_dma (int dev)
save_flags (flags);
cli ();
- disable_dma (chan);
+ disable_dma (audio_devs[dev]->dmap_out->dma);
clear_dma_ff (chan);
restore_flags (flags);
}
@@ -1354,37 +1431,39 @@ DMAbuf_close_dma (int dev)
}
void
-DMAbuf_init (void)
+DMAbuf_init (int dev, int dma1, int dma2)
{
- int dev;
-
/*
* NOTE! This routine could be called several times.
*/
- for (dev = 0; dev < num_audiodevs; dev++)
- if (audio_devs[dev]->dmap_out == NULL)
- {
- if (audio_devs[dev]->d == NULL)
- panic ("OSS: audio_devs[%d]->d == NULL\n", dev);
- if (audio_devs[dev]->parent_dev)
- { /* Use DMA map of the parent dev */
- int parent = audio_devs[dev]->parent_dev - 1;
-
- audio_devs[dev]->dmap_out = audio_devs[parent]->dmap_out;
- audio_devs[dev]->dmap_in = audio_devs[parent]->dmap_in;
- }
- else
- {
- audio_devs[dev]->dmap_out =
- audio_devs[dev]->dmap_in =
- &dmaps[ndmaps++];
+ if (audio_devs[dev]->dmap_out == NULL)
+ {
+ if (audio_devs[dev]->d == NULL)
+ panic ("OSS: audio_devs[%d]->d == NULL\n", dev);
+
+ if (audio_devs[dev]->parent_dev)
+ { /* Use DMA map of the parent dev */
+ int parent = audio_devs[dev]->parent_dev - 1;
- if (audio_devs[dev]->flags & DMA_DUPLEX)
+ audio_devs[dev]->dmap_out = audio_devs[parent]->dmap_out;
+ audio_devs[dev]->dmap_in = audio_devs[parent]->dmap_in;
+ }
+ else
+ {
+ audio_devs[dev]->dmap_out =
+ audio_devs[dev]->dmap_in =
+ &dmaps[ndmaps++];
+ audio_devs[dev]->dmap_out->dma = dma1;
+
+ if (audio_devs[dev]->flags & DMA_DUPLEX)
+ {
audio_devs[dev]->dmap_in =
&dmaps[ndmaps++];
- }
- }
+ audio_devs[dev]->dmap_in->dma = dma2;
+ }
+ }
+ }
}
int
@@ -1396,7 +1475,7 @@ DMAbuf_select (int dev, struct fileinfo *file, int sel_type, poll_table * wait)
switch (sel_type)
{
case SEL_IN:
- if (!(audio_devs[dev]->open_mode))
+ if (!(audio_devs[dev]->open_mode & OPEN_READ))
return 0;
dmap = audio_devs[dev]->dmap_in;
@@ -1448,6 +1527,9 @@ DMAbuf_select (int dev, struct fileinfo *file, int sel_type, poll_table * wait)
case SEL_OUT:
dmap = audio_devs[dev]->dmap_out;
+ if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
+ return 0;
+
if (dmap->mapping_flags & DMA_MAP_MAPPED)
{
if (dmap->qlen)
diff --git a/drivers/sound/gus_card.c b/drivers/sound/gus_card.c
index b844e4363..1c8881684 100644
--- a/drivers/sound/gus_card.c
+++ b/drivers/sound/gus_card.c
@@ -123,7 +123,7 @@ gusintr (int irq, void *dev_id, struct pt_regs *dummy)
#ifdef CONFIG_GUSMAX
if (have_gus_max)
- ad1848_interrupt (irq, NULL, NULL);
+ adintr (irq, NULL, NULL);
#endif
while (1)
diff --git a/drivers/sound/gus_midi.c b/drivers/sound/gus_midi.c
index 61c644007..9fc38fc88 100644
--- a/drivers/sound/gus_midi.c
+++ b/drivers/sound/gus_midi.c
@@ -248,6 +248,7 @@ gus_midi_init (void)
std_midi_synth.midi_dev = my_dev = num_midis;
midi_devs[num_midis++] = &gus_midi_operations;
+ sequencer_init ();
return;
}
diff --git a/drivers/sound/gus_wave.c b/drivers/sound/gus_wave.c
index 5c579b846..8c1523750 100644
--- a/drivers/sound/gus_wave.c
+++ b/drivers/sound/gus_wave.c
@@ -21,7 +21,7 @@
#if defined(CONFIG_GUSHW)
-#define GUS_BANK_SIZE (256*1024)
+#define GUS_BANK_SIZE (((iw_mode) ? 256*1024*1024 : 256*1024))
#define MAX_SAMPLE 150
#define MAX_PATCH 256
@@ -73,6 +73,7 @@ extern int gus_pnp_flag;
static int gus_dma2 = -1;
static int dual_dma_mode = 0;
static long gus_mem_size = 0;
+static long gus_rom_size = 0;
static long free_mem_ptr = 0;
static int gus_busy = 0;
static int gus_no_dma = 0;
@@ -84,6 +85,7 @@ static int recording_active = 0;
static int only_read_access = 0;
static int only_8_bits = 0;
+int iw_mode = 0;
int gus_wave_volume = 60;
int gus_pcm_volume = 80;
int have_gus_max = 0;
@@ -105,6 +107,8 @@ static int active_device = 0;
static int gus_audio_speed;
static int gus_audio_channels;
static int gus_audio_bits;
+static int gus_audio_bsize;
+static char bounce_buf[8 * 1024]; /* Must match value set to max_fragment */
static struct wait_queue *dram_sleeper = NULL;
static volatile struct snd_wait dram_sleep_flag =
@@ -113,7 +117,7 @@ static volatile struct snd_wait dram_sleep_flag =
/*
* Variables and buffers for PCM output
*/
-#define MAX_PCM_BUFFERS (32*MAX_REALTIME_FACTOR) /* Don't change */
+#define MAX_PCM_BUFFERS (128*MAX_REALTIME_FACTOR) /* Don't change */
static int pcm_bsize, pcm_nblk, pcm_banksize;
static int pcm_datasize[MAX_PCM_BUFFERS];
@@ -356,14 +360,22 @@ gus_write_addr (int reg, unsigned long address, int frac, int is16bit)
cli ();
if (is16bit)
{
- /*
- * Special processing required for 16 bit patches
- */
+ if (iw_mode)
+ {
+ /* Interwave spesific address translations */
+ address >>= 1;
+ }
+ else
+ {
+ /*
+ * Special processing required for 16 bit patches
+ */
- hold_address = address;
- address = address >> 1;
- address &= 0x0001ffffL;
- address |= (hold_address & 0x000c0000L);
+ hold_address = address;
+ address = address >> 1;
+ address &= 0x0001ffffL;
+ address |= (hold_address & 0x000c0000L);
+ }
}
gus_write16 (reg, (unsigned short) ((address >> 7) & 0xffff));
@@ -389,6 +401,8 @@ gus_select_voice (int voice)
static void
gus_select_max_voices (int nvoices)
{
+ if (iw_mode)
+ nvoices = 32;
if (nvoices < 14)
nvoices = 14;
if (nvoices > 32)
@@ -430,7 +444,11 @@ gus_voice_freq (unsigned long freq)
unsigned long divisor = freq_div_table[nr_voices - 14];
unsigned short fc;
- fc = (unsigned short) (((freq << 9) + (divisor >> 1)) / divisor);
+ /* Interwave plays at 44100 Hz with any number of voices */
+ if (iw_mode)
+ fc = (unsigned short) (((freq << 9) + (44100 >> 1)) / 44100);
+ else
+ fc = (unsigned short) (((freq << 9) + (divisor >> 1)) / divisor);
fc = fc << 1;
gus_write16 (0x01, fc);
@@ -851,6 +869,8 @@ gus_initialize (void)
gus_read8 (0x0f); /* Clear pending IRQs */
+ if (iw_mode)
+ gus_write8 (0x19, gus_read8 (0x19) | 0x01);
restore_flags (flags);
}
@@ -1022,10 +1042,10 @@ pnp_mem_init (void)
*/
gus_write16 (0x52, (gus_look16 (0x52) & 0xfff0) | bits);
-/*
- * Return the chip back to GUS compatible mode.
- */
- gus_write8 (0x19, gus_read8 (0x19) & ~0x01);
+/* Leave the chip into enhanced mode. Disable LFO */
+ gus_mem_size = total;
+ iw_mode = 1;
+ gus_write8 (0x19, (gus_read8 (0x19) | 0x01) & ~0x02);
}
int
@@ -1065,6 +1085,8 @@ gus_wave_detect (int baseaddr)
if (gus_pnp_flag)
pnp_mem_init ();
+ if (iw_mode)
+ return 1;
/* See if there is first block there.... */
gus_poke (0L, 0xaa);
@@ -1479,6 +1501,9 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
voices[voice].mode = samples[sample].mode;
voices[voice].patch_vol = samples[sample].volume;
+ if (iw_mode)
+ gus_write8 (0x15, 0x00); /* RAM, Reset voice deactivate bit of SMSI */
+
if (voices[voice].mode & WAVE_ENVELOPES)
{
int i;
@@ -1897,7 +1922,7 @@ guswave_load_patch (int dev, int format, const char *addr,
for (i = 0; i < blk_sz; i++)
{
- get_user (data, (unsigned char *) &((addr)[sizeof_patch + i]));
+ get_user (*(unsigned char *) &data, (unsigned char *) &((addr)[sizeof_patch + i]));
if (patch.mode & WAVE_UNSIGNED)
if (!(patch.mode & WAVE_16_BITS) || (i & 0x01))
data ^= 0x80; /* Convert to signed */
@@ -1934,17 +1959,37 @@ guswave_load_patch (int dev, int format, const char *addr,
* Set the DRAM address for the wave data
*/
- address = target;
-
- if (audio_devs[gus_devnum]->dmap_out->dma > 3)
+ if (iw_mode)
{
- hold_address = address;
- address = address >> 1;
- address &= 0x0001ffffL;
- address |= (hold_address & 0x000c0000L);
+ /* Different address translation in enhanced mode */
+
+ unsigned char hi;
+
+ if (gus_dma > 4)
+ address = target >> 1; /* Convert to 16 bit word address */
+ else
+ address = target;
+
+ hi = (unsigned char) ((address >> 16) & 0xf0);
+ hi += (unsigned char) (address & 0x0f);
+
+ gus_write16 (0x42, (address >> 4) & 0xffff); /* DMA address (low) */
+ gus_write8 (0x50, hi);
}
+ else
+ {
+ address = target;
+
+ if (audio_devs[gus_devnum]->dmap_out->dma > 3)
+ {
+ hold_address = address;
+ address = address >> 1;
+ address &= 0x0001ffffL;
+ 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
@@ -2280,6 +2325,7 @@ gus_audio_reset (int dev)
}
}
+static int saved_iw_mode; /* A hack hack hack */
static int
gus_audio_open (int dev, int mode)
@@ -2300,6 +2346,13 @@ gus_audio_open (int dev, int mode)
gus_reset ();
reset_sample_memory ();
gus_select_max_voices (14);
+ saved_iw_mode = iw_mode;
+ if (iw_mode)
+ {
+ /* There are some problems with audio in enhanced mode so disable it */
+ gus_write8 (0x19, gus_read8 (0x19) & ~0x01); /* Disable enhanced mode */
+ iw_mode = 0;
+ }
pcm_active = 0;
dma_active = 0;
@@ -2322,6 +2375,7 @@ gus_audio_open (int dev, int mode)
static void
gus_audio_close (int dev)
{
+ iw_mode = saved_iw_mode;
gus_reset ();
gus_busy = 0;
pcm_opened = 0;
@@ -2428,7 +2482,7 @@ play_next_pcm_block (void)
gus_voice_volume (1530 + (25 * gus_pcm_volume));
gus_ramp_range (65, 1530 + (25 * gus_pcm_volume));
- gus_write_addr (0x0a, dram_loc, 0, is16bits); /* Starting position */
+ gus_write_addr (0x0a, chn * pcm_banksize, 0, is16bits); /* Starting position */
gus_write_addr (0x02, chn * pcm_banksize, 0, is16bits); /* Loop start */
if (chn != 0)
@@ -2437,30 +2491,11 @@ play_next_pcm_block (void)
}
if (chn == 0)
- gus_write_addr (0x04, dram_loc + pcm_datasize[this_one] - 1,
+ gus_write_addr (0x04, dram_loc + pcm_bsize - 1,
0, is16bits); /* Loop end location */
else
mode[chn] |= 0x08; /* Enable looping */
- if (pcm_datasize[this_one] != pcm_bsize)
- {
- /*
- * Incompletely filled block. Possibly the last one.
- */
- if (chn == 0)
- {
- mode[chn] &= ~0x08; /* Disable looping */
- mode[chn] |= 0x20; /* Enable IRQ at the end */
- voices[0].loop_irq_mode = LMODE_PCM_STOP;
- ramp_mode[chn] = 0x03; /* No rollover bit */
- }
- else
- {
- gus_write_addr (0x04, dram_loc + pcm_datasize[this_one],
- 0, is16bits); /* Loop end location */
- mode[chn] &= ~0x08; /* Disable looping */
- }
- }
restore_flags (flags);
}
@@ -2471,6 +2506,8 @@ play_next_pcm_block (void)
cli ();
gus_select_voice (chn);
gus_write8 (0x0d, ramp_mode[chn]);
+ if (iw_mode)
+ gus_write8 (0x15, 0x00); /* Reset voice deactivate bit of SMSI */
gus_voice_on (mode[chn]);
restore_flags (flags);
}
@@ -2549,7 +2586,7 @@ gus_transfer_output_block (int dev, unsigned long buf,
*/
dma_active = 1; /* DMA started. There is a unacknowledged buffer */
active_device = GUS_DEV_PCM_DONE;
- if (!pcm_active && (pcm_qlen > 0 || count < pcm_bsize))
+ if (!pcm_active && (pcm_qlen > 1 || count < pcm_bsize))
{
play_next_pcm_block ();
}
@@ -2567,13 +2604,58 @@ gus_transfer_output_block (int dev, unsigned long buf,
}
static void
+gus_uninterleave8 (char *buf, int l)
+{
+/* This routine uninterleaves 8 bit stereo output (LRLRLR->LLLRRR) */
+ int i, p = 0, halfsize = l / 2;
+ char *buf2 = buf + halfsize, *src = bounce_buf;
+
+ memcpy (bounce_buf, buf, l);
+
+ for (i = 0; i < halfsize; i++)
+ {
+ buf[i] = src[p++]; /* Left channel */
+ buf2[i] = src[p++]; /* Right channel */
+ }
+}
+
+static void
+gus_uninterleave16 (short *buf, int l)
+{
+/* This routine uninterleaves 16 bit stereo output (LRLRLR->LLLRRR) */
+ int i, p = 0, halfsize = l / 2;
+ short *buf2 = buf + halfsize, *src = (short *) bounce_buf;
+
+ memcpy (bounce_buf, (char *) buf, l * 2);
+
+ for (i = 0; i < halfsize; i++)
+ {
+ buf[i] = src[p++]; /* Left channel */
+ buf2[i] = src[p++]; /* Right channel */
+ }
+}
+
+static void
gus_audio_output_block (int dev, unsigned long buf, int total_count,
int intrflag)
{
+ struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
+
+ dmap->flags |= DMA_NODMA | DMA_NOTIMEOUT;
+
pcm_current_buf = buf;
pcm_current_count = total_count;
pcm_current_intrflag = intrflag;
pcm_current_dev = dev;
+ if (gus_audio_channels == 2)
+ {
+ char *b = dmap->raw_buf + (buf - dmap->raw_buf_phys);
+
+ if (gus_audio_bits == 8)
+ gus_uninterleave8 (b, total_count);
+ else
+ gus_uninterleave16 ((short *) b, total_count / 2);
+ }
gus_transfer_output_block (dev, buf, total_count, intrflag, 0);
}
@@ -2587,7 +2669,7 @@ gus_audio_start_input (int dev, unsigned long buf, int count,
save_flags (flags);
cli ();
- /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); */
+ DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
mode = 0xa0; /* DMA IRQ enabled, invert MSB */
@@ -2607,6 +2689,8 @@ gus_audio_prepare_for_input (int dev, int bsize, int bcount)
{
unsigned int rate;
+ gus_audio_bsize = bsize;
+ audio_devs[dev]->dmap_in->flags |= DMA_NODMA;
rate = (((9878400 + gus_audio_speed / 2) / (gus_audio_speed + 2)) + 8) / 16;
gus_write8 (0x48, rate & 0xff); /* Set sampling rate */
@@ -2627,6 +2711,7 @@ gus_audio_prepare_for_output (int dev, int bsize, int bcount)
long mem_ptr, mem_size;
+ audio_devs[dev]->dmap_out->flags |= DMA_NODMA | DMA_NOTIMEOUT;
mem_ptr = 0;
mem_size = gus_mem_size / gus_audio_channels;
@@ -2636,7 +2721,7 @@ gus_audio_prepare_for_output (int dev, int bsize, int bcount)
pcm_bsize = bsize / gus_audio_channels;
pcm_head = pcm_tail = pcm_qlen = 0;
- pcm_nblk = MAX_PCM_BUFFERS;
+ pcm_nblk = 2; /* MAX_PCM_BUFFERS; */
if ((pcm_bsize * pcm_nblk) > mem_size)
pcm_nblk = mem_size / pcm_bsize;
@@ -2658,56 +2743,6 @@ gus_local_qlen (int dev)
return pcm_qlen;
}
-static void
-gus_copy_from_user (int dev, char *localbuf, int localoffs,
- const char *userbuf, int useroffs, int len)
-{
- if (gus_audio_channels == 1)
- {
- copy_from_user (&localbuf[localoffs], &(userbuf)[useroffs], len);
- }
- else if (gus_audio_bits == 8)
- {
- int in_left = useroffs;
- int in_right = useroffs + 1;
- char *out_left, *out_right;
- int i;
-
- len /= 2;
- localoffs /= 2;
- out_left = localbuf + localoffs;
- out_right = out_left + pcm_bsize;
-
- for (i = 0; i < len; i++)
- {
- get_user (*out_left++, (unsigned char *) &((userbuf)[in_left]));
- in_left += 2;
- get_user (*out_right++, (unsigned char *) &((userbuf)[in_right]));
- in_right += 2;
- }
- }
- else
- {
- int in_left = useroffs;
- int in_right = useroffs + 2;
- short *out_left, *out_right;
- int i;
-
- len /= 4;
- localoffs /= 4;
-
- out_left = ((short *) localbuf) + localoffs;
- out_right = out_left + (pcm_bsize / 2);
-
- for (i = 0; i < len; i++)
- {
- get_user (*out_left++, (unsigned short *) &((userbuf)[in_left]));
- in_left += 4;
- get_user (*out_right++, (unsigned short *) &((userbuf)[in_right]));
- in_right += 4;
- }
- }
-}
static struct audio_driver gus_audio_driver =
{
@@ -2720,7 +2755,7 @@ static struct audio_driver gus_audio_driver =
gus_audio_prepare_for_output,
gus_audio_reset,
gus_local_qlen,
- gus_copy_from_user
+ NULL
};
static void
@@ -3218,7 +3253,10 @@ gus_wave_init (struct address_info *hw_config)
else
{
voice_alloc = &guswave_operations.alloc;
+ if (iw_mode)
+ guswave_operations.id = "IWAVE";
synth_devs[num_synths++] = &guswave_operations;
+ sequencer_init ();
#ifdef CONFIG_SEQUENCER
gus_tmr_install (gus_base + 8);
#endif
@@ -3237,15 +3275,16 @@ gus_wave_init (struct address_info *hw_config)
&gus_audio_driver,
sizeof (struct audio_driver),
NEEDS_RESTART |
- ((dma2 != dma && dma2 != -1) ?
- DMA_DUPLEX : 0),
+ ((!iw_mode && dma2 != dma && dma2 != -1) ?
+ DMA_DUPLEX : 0),
AFMT_U8 | AFMT_S16_LE,
NULL,
dma,
dma2)) < 0)
return;
- audio_devs[gus_devnum]->min_fragment = 9;
+ audio_devs[gus_devnum]->min_fragment = 9; /* 512k */
+ audio_devs[gus_devnum]->max_fragment = 11; /* 8k (must match size of bounce_buf */
audio_devs[gus_devnum]->mixer_dev = num_mixers; /* Next mixer# */
audio_devs[gus_devnum]->flags |= DMA_HARDSTOP;
}
@@ -3347,7 +3386,6 @@ do_loop_irq (int voice)
pcm_active = 0; /* Signal to the play_next_pcm_block routine */
case LMODE_PCM:
{
- int flag; /* 0 or 2 */
pcm_qlen--;
pcm_head = (pcm_head + 1) % pcm_nblk;
@@ -3367,20 +3405,11 @@ do_loop_irq (int voice)
}
/*
- * If the queue was full before this interrupt, the DMA transfer was
- * suspended. Let it continue now.
+ * If the queue was full before this interrupt, the DMA transfer was
+ * suspended. Let it continue now.
*/
- if (dma_active)
- {
- if (pcm_qlen == 0)
- flag = 1; /* Underflow */
- else
- flag = 0;
- dma_active = 0;
- }
- else
- flag = 2; /* Just notify the dmabuf.c */
- DMAbuf_outputintr (gus_devnum, flag);
+ if (audio_devs[gus_devnum]->dmap_out->qlen > 0)
+ DMAbuf_outputintr (gus_devnum, 0);
}
break;
@@ -3413,9 +3442,9 @@ do_volume_irq (int voice)
switch (mode)
{
- case VMODE_HALT: /*
- * Decay phase finished
- */
+ case VMODE_HALT: /* Decay phase finished */
+ if (iw_mode)
+ gus_write8 (0x15, 0x02); /* Set voice deactivate bit of SMSI */
restore_flags (flags);
gus_voice_init (voice);
break;
@@ -3523,13 +3552,12 @@ guswave_dma_irq (void)
gus_write8 (0x41, 0); /* Disable GF1 DMA */
if (pcm_qlen < pcm_nblk)
{
- int flag = (1 - dma_active) * 2; /* 0 or 2 */
-
- if (pcm_qlen == 0)
- flag = 1; /* Underrun */
dma_active = 0;
if (gus_busy)
- DMAbuf_outputintr (gus_devnum, flag);
+ {
+ if (audio_devs[gus_devnum]->dmap_out->qlen > 0)
+ DMAbuf_outputintr (gus_devnum, 0);
+ }
}
break;
diff --git a/drivers/sound/lowlevel/Config.tmpl b/drivers/sound/lowlevel/Config.tmpl
index ff107a819..a3864b96f 100644
--- a/drivers/sound/lowlevel/Config.tmpl
+++ b/drivers/sound/lowlevel/Config.tmpl
@@ -32,7 +32,7 @@ if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then
fi
fi
- if [ "$CONFIG_MIDI" = "y" ]; then
+ if [ "$CONFIG_MPU401" = "y" ]; then
bool 'Audio Excel DSP 16 (MPU401 emulation)' CONFIG_AEDSP16_MPU401
if [ "$CONFIG_AEDSP16_MPU401" = "y" ]; then
comment 'Audio Excel DSP 16 [MPU-401]'
diff --git a/drivers/sound/lowlevel/aci.c b/drivers/sound/lowlevel/aci.c
index 657fa697d..7599d5a6c 100644
--- a/drivers/sound/lowlevel/aci.c
+++ b/drivers/sound/lowlevel/aci.c
@@ -22,9 +22,9 @@
* First version written.
* 1995-12-31 Markus Kuhn
* Second revision, general code cleanup.
- * 1997-05-16 Hannu Savolainen
+ * 1996-05-16 Hannu Savolainen
* Integrated with other parts of the driver.
- * 1997-05-28 Markus Kuhn
+ * 1996-05-28 Markus Kuhn
* Initialize CS4231A mixer, make ACI first mixer,
* use new private mixer API for solo mode.
*/
diff --git a/drivers/sound/maui.c b/drivers/sound/maui.c
index 8c416a632..6fa104905 100644
--- a/drivers/sound/maui.c
+++ b/drivers/sound/maui.c
@@ -333,7 +333,7 @@ maui_load_patch (int dev, int format, const char *addr,
{
unsigned char data;
- get_user (data, (unsigned char *) &((addr)[hdr_size + i]));
+ get_user (*(unsigned char *) &data, (unsigned char *) &((addr)[hdr_size + i]));
if (i == 0 && !(data & 0x80))
return -EINVAL;
diff --git a/drivers/sound/midi_synth.c b/drivers/sound/midi_synth.c
index 512fc2bb7..454fc7471 100644
--- a/drivers/sound/midi_synth.c
+++ b/drivers/sound/midi_synth.c
@@ -537,7 +537,7 @@ midi_synth_load_patch (int dev, int format, const char *addr,
{
unsigned char data;
- get_user (data, (unsigned char *) &((addr)[hdr_size + i]));
+ get_user (*(unsigned char *) &data, (unsigned char *) &((addr)[hdr_size + i]));
eox_seen = (i > 0 && data & 0x80); /* End of sysex */
diff --git a/drivers/sound/midibuf.c b/drivers/sound/midibuf.c
index cfe2879d1..c4271e87b 100644
--- a/drivers/sound/midibuf.c
+++ b/drivers/sound/midibuf.c
@@ -12,6 +12,7 @@
*/
#include <linux/config.h>
+#define MIDIBUF_C
#include "sound_config.h"
diff --git a/drivers/sound/mpu401.c b/drivers/sound/mpu401.c
index 7c6111003..5a5e90e27 100644
--- a/drivers/sound/mpu401.c
+++ b/drivers/sound/mpu401.c
@@ -1183,6 +1183,7 @@ attach_mpu401 (struct address_info *hw_config)
irq2dev[devc->irq] = num_midis;
midi_devs[num_midis++] = &mpu401_midi_operations[devc->devno];
+ sequencer_init ();
}
static int
diff --git a/drivers/sound/opl3.c b/drivers/sound/opl3.c
index 28ce6da15..5c71dc585 100644
--- a/drivers/sound/opl3.c
+++ b/drivers/sound/opl3.c
@@ -112,6 +112,7 @@ opl3_ioctl (int dev,
struct sbi_instrument ins;
memcpy ((char *) &ins, (&((char *) arg)[0]), sizeof (ins));
+ printk("Warning: Obsolete ioctl(SNDCTL_FM_LOAD_INSTR) used. Fix the program.\n");
if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR)
{
@@ -1168,6 +1169,7 @@ opl3_init (int ioaddr, int *osp)
opl3_operations.info = &devc->fm_info;
synth_devs[num_synths++] = &opl3_operations;
+ sequencer_init ();
devc->v_alloc = &opl3_operations.alloc;
devc->chn_info = &opl3_operations.chn_info[0];
diff --git a/drivers/sound/os.h b/drivers/sound/os.h
index 4ab565960..4b1abd06e 100644
--- a/drivers/sound/os.h
+++ b/drivers/sound/os.h
@@ -7,6 +7,7 @@
#undef NO_INLINE_ASM
#define SHORT_BANNERS
#define MANUAL_PNP
+#undef DO_TIMINGS
#ifdef MODULE
#define __NO_VERSION__
@@ -20,6 +21,7 @@
#define LINUX21X
#endif
+#ifdef __KERNEL__
#include <linux/utsname.h>
#include <linux/string.h>
#include <linux/fs.h>
@@ -37,6 +39,10 @@
#include <linux/vmalloc.h>
#include <asm/uaccess.h>
#include <linux/poll.h>
+#include <linux/pci.h>
+#include <linux/bios32.h>
+#else
+#endif
#include <linux/wrapper.h>
diff --git a/drivers/sound/pas2_card.c b/drivers/sound/pas2_card.c
index a162ce993..b109b22f1 100644
--- a/drivers/sound/pas2_card.c
+++ b/drivers/sound/pas2_card.c
@@ -283,7 +283,7 @@ detect_pas_hw (struct address_info *hw_config)
foo = board_id ^ 0xe0;
pas_write (foo, 0x0B8B);
- foo = inb (0x0B8B);
+ foo = pas_read (0x0B8B);
pas_write (board_id, 0x0B8B);
if (board_id != foo)
diff --git a/drivers/sound/pas2_midi.c b/drivers/sound/pas2_midi.c
index b9dce0b41..05a509f91 100644
--- a/drivers/sound/pas2_midi.c
+++ b/drivers/sound/pas2_midi.c
@@ -236,6 +236,7 @@ pas_midi_init (void)
std_midi_synth.midi_dev = my_dev = num_midis;
midi_devs[num_midis++] = &pas_midi_operations;
+ sequencer_init ();
}
void
diff --git a/drivers/sound/pas2_pcm.c b/drivers/sound/pas2_pcm.c
index 87446e147..e082fc9cc 100644
--- a/drivers/sound/pas2_pcm.c
+++ b/drivers/sound/pas2_pcm.c
@@ -55,12 +55,12 @@ pcm_set_speed (int arg)
if (pcm_channels & 2)
{
foo = (596590 + (arg / 2)) / arg;
- arg = 596590 / foo;
+ arg = (596590 + (foo / 2)) / foo;
}
else
{
foo = (1193180 + (arg / 2)) / arg;
- arg = 1193180 / foo;
+ arg = (1193180 + (foo / 2)) / foo;
}
pcm_speed = arg;
diff --git a/drivers/sound/sb.h b/drivers/sound/sb.h
index b229549bb..ba2f3be18 100644
--- a/drivers/sound/sb.h
+++ b/drivers/sound/sb.h
@@ -105,6 +105,7 @@ typedef struct sb_devc {
/* MIDI fields */
int my_mididev;
int input_opened;
+ int midi_broken;
void (*midi_input_intr) (int dev, unsigned char data);
} sb_devc;
diff --git a/drivers/sound/sb_common.c b/drivers/sound/sb_common.c
index 3faf6b690..bd9e05704 100644
--- a/drivers/sound/sb_common.c
+++ b/drivers/sound/sb_common.c
@@ -58,10 +58,7 @@ sb_dsp_command (sb_devc * devc, unsigned char val)
int i;
unsigned long limit;
- limit = jiffies + HZ / 10; /*
- * The timeout is 0.1 seconds
- */
-
+ limit = jiffies + HZ / 10; /* Timeout */
/*
* Note! the i<500000 is an emergency exit. The sb_dsp_command() is sometimes
* called while interrupts are disabled. This means that the timer is
@@ -173,7 +170,8 @@ sbintr (int irq, void *dev_id, struct pt_regs *dummy)
break;
default:
- printk ("Sound Blaster: Unexpected interrupt\n");
+ /* printk ("Sound Blaster: Unexpected interrupt\n"); */
+ ;
}
/*
* Acknowledge interrupts
@@ -633,6 +631,7 @@ sb_dsp_detect (struct address_info *hw_config)
for (i = 0; i < 10000; i++)
inb (DSP_DATA_AVAIL);
devc->caps = SB_NO_AUDIO | SB_NO_MIDI; /* Mixer only */
+ devc->model = MDL_AZTECH;
}
}
}
@@ -666,6 +665,7 @@ sb_dsp_init (struct address_info *hw_config)
sb_devc *devc;
int n;
char name[100];
+ extern int sb_be_quiet;
/*
* Check if we had detected a SB device earlier
@@ -776,7 +776,7 @@ sb_dsp_init (struct address_info *hw_config)
{
devc->model = hw_config->card_subtype = MDL_SBPRO;
if (hw_config->name == NULL)
- hw_config->name = "Sound Blaster Pro";
+ hw_config->name = "Sound Blaster Pro (8 BIT ONLY)";
}
break;
@@ -809,10 +809,33 @@ sb_dsp_init (struct address_info *hw_config)
#endif
if (hw_config->name == NULL)
- hw_config->name = "Sound Blaster";
+ hw_config->name = "Sound Blaster (8 BIT/MONO ONLY)";
sprintf (name, "%s (%d.%d)", hw_config->name, devc->major, devc->minor);
conf_printf (name, hw_config);
+
+/*
+ * Assuming that a soundcard is Sound Blaster (compatible) is the most common
+ * configuration error and the mother of all problems. Usually soundcards
+ * emulate SB Pro but in addition they have a 16 bit native mode which should be
+ * used in Unix. See Readme.cards for more information about configuring OSS/Free
+ * properly.
+ */
+ if (devc->model <= MDL_SBPRO)
+ if (devc->major == 3 && devc->minor != 1) /* "True" SB Pro should have v3.1. */
+ {
+ printk ("This soundcard doesn't seem to be fully Sound Blaster Pro compatible.\n");
+ printk ("Almost certainly there is another way to configure OSS so that\n");
+ printk ("it works properly with OSS (for example in 16 bit mode).\n");
+ }
+ else if (!sb_be_quiet && devc->model == MDL_SBPRO)
+ {
+ printk ("SB DSP version is just %d.%d which means that your card is\n",
+ devc->major, devc->minor);
+ printk ("several years old (8 bit only device)\n");
+ printk ("or alternatively the sound driver is incorrectly configured.\n");
+ }
+
hw_config->card_subtype = devc->model;
last_devc = devc; /* For SB MPU detection */
diff --git a/drivers/sound/sb_midi.c b/drivers/sound/sb_midi.c
index 2bdeef1ba..cffaafc7b 100644
--- a/drivers/sound/sb_midi.c
+++ b/drivers/sound/sb_midi.c
@@ -52,6 +52,7 @@ sb_midi_open (int dev, int mode,
restore_flags (flags);
devc->irq_mode = IMODE_MIDI;
+ devc->midi_broken = 0;
sb_dsp_reset (devc);
@@ -96,9 +97,16 @@ sb_midi_out (int dev, unsigned char midi_byte)
sb_devc *devc = midi_devs[dev]->devc;
if (devc == NULL)
- return -ENXIO;
+ return 1;
+
+ if (devc->midi_broken)
+ return 1;
- sb_dsp_command (devc, midi_byte);
+ if (!sb_dsp_command (devc, midi_byte))
+ {
+ devc->midi_broken = 1;
+ return 1;
+ }
return 1;
}
@@ -220,6 +228,7 @@ sb_dsp_midi_init (sb_devc * devc)
midi_devs[num_midis]->converter->id = "SBMIDI";
num_midis++;
+ sequencer_init ();
}
#endif
diff --git a/drivers/sound/sequencer.c b/drivers/sound/sequencer.c
index 6ffced88e..14d2f24de 100644
--- a/drivers/sound/sequencer.c
+++ b/drivers/sound/sequencer.c
@@ -24,6 +24,9 @@ static int sequencer_ok = 0;
static struct sound_timer_operations *tmr;
static int tmr_no = -1; /* Currently selected timer */
static int pending_timer = -1; /* For timer change operation */
+extern unsigned long seq_time;
+
+static int obsolete_api_used = 0;
/*
* Local counts for number of synth and MIDI devices. These are initialized
@@ -56,7 +59,6 @@ static int midi_written[MAX_MIDI_DEV] =
unsigned long prev_input_time = 0;
int prev_event_time;
-unsigned long seq_time = 0;
#include "tuning.h"
@@ -312,6 +314,9 @@ sequencer_write (int dev, struct fileinfo *file, const char *buf, int count)
return -EINVAL;
}
ev_size = 4;
+
+ if (event_rec[0] != SEQ_MIDIPUTC)
+ obsolete_api_used = 1;
}
if (event_rec[0] == SEQ_MIDIPUTC)
@@ -498,11 +503,12 @@ alloc_voice (int dev, int chn, int note)
static void
seq_chn_voice_event (unsigned char *event_rec)
{
- unsigned char dev = event_rec[1];
- unsigned char cmd = event_rec[2];
- unsigned char chn = event_rec[3];
- unsigned char note = event_rec[4];
- unsigned char parm = event_rec[5];
+#define dev event_rec[1]
+#define cmd event_rec[2]
+#define chn event_rec[3]
+#define note event_rec[4]
+#define parm event_rec[5]
+
int voice = -1;
if ((int) dev > max_synthdev)
@@ -570,6 +576,11 @@ seq_chn_voice_event (unsigned char *event_rec)
default:;
}
+#undef dev
+#undef cmd
+#undef chn
+#undef note
+#undef parm
}
@@ -1105,6 +1116,7 @@ sequencer_open (int dev, struct fileinfo *file)
return -EBUSY;
}
sequencer_busy = 1;
+ obsolete_api_used = 0;
restore_flags (flags);
max_mididev = num_midis;
@@ -1322,6 +1334,8 @@ sequencer_release (int dev, struct fileinfo *file)
if (seq_mode == SEQ_2)
tmr->close (tmr_no);
+ if (obsolete_api_used)
+ printk ("/dev/music: Obsolete (4 byte) API was used by this program\n");
sequencer_busy = 0;
}
@@ -1628,6 +1642,8 @@ sequencer_ioctl (int dev, struct fileinfo *file,
break;
case SNDCTL_SEQ_RESETSAMPLES:
+ case SNDCTL_SYNTH_REMOVESAMPLE:
+ case SNDCTL_SYNTH_CONTROL:
{
int err;
@@ -1870,7 +1886,7 @@ note_to_freq (int note_num)
*/
int note, octave, note_freq;
- int notes[] =
+ static int notes[] =
{
261632, 277189, 293671, 311132, 329632, 349232,
369998, 391998, 415306, 440000, 466162, 493880
@@ -1937,6 +1953,8 @@ compute_finetune (unsigned long base_freq, int bend, int range,
}
semitones = bend / 100;
+ if (semitones > 99)
+ semitones = 99;
cents = bend % 100;
amount = (int) (semitone_tuning[semitones] * multiplier * cent_tuning[cents])
@@ -1955,6 +1973,10 @@ sequencer_init (void)
if (sequencer_ok)
return;
+#ifdef CONFIG_MIDI
+ MIDIbuf_init ();
+#endif
+
queue = (unsigned char *) (sound_mem_blocks[sound_nblocks] = vmalloc (SEQ_MAX_QUEUE * EV_SZ));
sound_mem_sizes[sound_nblocks] = SEQ_MAX_QUEUE * EV_SZ;
@@ -1971,7 +1993,7 @@ sequencer_init (void)
sound_mem_sizes[sound_nblocks] = SEQ_MAX_QUEUE * IEV_SZ;
if (sound_nblocks < 1024)
sound_nblocks++;;
- if (queue == NULL)
+ if (iqueue == NULL)
{
printk ("Sound: Can't allocate memory for sequencer input queue\n");
return;
diff --git a/drivers/sound/sound_calls.h b/drivers/sound/sound_calls.h
index f5587cc3f..8bb54fa9d 100644
--- a/drivers/sound/sound_calls.h
+++ b/drivers/sound/sound_calls.h
@@ -10,7 +10,7 @@ int DMAbuf_rmchars(int dev, int buff_no, int c);
int DMAbuf_start_output(int dev, int buff_no, int l);
int DMAbuf_move_wrpointer(int dev, int l);
/* int DMAbuf_ioctl(int dev, unsigned int cmd, caddr_t arg, int local); */
-void DMAbuf_init(void);
+void DMAbuf_init(int dev, int dma1, int dma2);
void DMAbuf_deinit(int dev);
int DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode);
int DMAbuf_open_dma (int dev);
@@ -20,7 +20,7 @@ void DMAbuf_outputintr(int dev, int underflow_flag);
struct dma_buffparms;
int DMAbuf_space_in_queue (int dev);
int DMAbuf_activate_recording (int dev, struct dma_buffparms *dmap);
-int DMAbuf_get_buffer_pointer (int dev, struct dma_buffparms *dmap);
+int DMAbuf_get_buffer_pointer (int dev, struct dma_buffparms *dmap, int direction);
void DMAbuf_launch_output(int dev, struct dma_buffparms *dmap);
int DMAbuf_select(int dev, struct fileinfo *file, int sel_type, poll_table * wait);
void DMAbuf_start_devices(unsigned int devmask);
@@ -52,7 +52,8 @@ int sequencer_open (int dev, struct fileinfo *file);
void sequencer_release (int dev, struct fileinfo *file);
int sequencer_ioctl (int dev, struct fileinfo *file,
unsigned int cmd, caddr_t arg);
-int sequencer_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
+int sequencer_select(int dev, struct fileinfo *file, int sel_type, poll_table * wait);
+
void sequencer_init (void);
void sequencer_timer(unsigned long dummy);
int note_to_freq(int note_num);
@@ -61,8 +62,6 @@ unsigned long compute_finetune(unsigned long base_freq, int bend, int range,
void seq_input_event(unsigned char *event, int len);
void seq_copy_to_input (unsigned char *event, int len);
-int sequencer_select(int dev, struct fileinfo *file, int sel_type, poll_table * wait);
-
/*
* System calls for the /dev/midi
*/
@@ -73,19 +72,20 @@ int MIDIbuf_open (int dev, struct fileinfo *file);
void MIDIbuf_release (int dev, struct fileinfo *file);
int MIDIbuf_ioctl (int dev, struct fileinfo *file,
unsigned int cmd, caddr_t arg);
-int MIDIbuf_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
+int MIDIbuf_select(int dev, struct fileinfo *file, int sel_type, poll_table * wait);
+
void MIDIbuf_bytes_received(int dev, unsigned char *buf, int count);
void MIDIbuf_init(void);
-int MIDIbuf_select(int dev, struct fileinfo *file, int sel_type, poll_table * wait);
-
/*
*
* Misc calls from various sources
*/
/* From soundcard.c */
+#ifndef __bsdi__
void tenmicrosec(int *osp);
+#endif
void request_sound_timer (int count);
void sound_stop_timer(void);
int snd_set_irq_handler (int interrupt_level, void(*iproc)(int, void*, struct pt_regs *), char *name, int *osp);
@@ -205,7 +205,7 @@ void ad1848_control(int cmd, int arg);
#define AD1848_REROUTE(oldctl, newctl) \
ad1848_control(AD1848_MIXER_REROUTE, ((oldctl)<<8)|(newctl))
-void ad1848_interrupt (int irq, void *dev_id, struct pt_regs * dummy);
+void adintr(int irq, void *dev_id, struct pt_regs * dummy);
void attach_ms_sound(struct address_info * hw_config);
int probe_ms_sound(struct address_info *hw_config);
void attach_pnp_ad1848(struct address_info * hw_config);
diff --git a/drivers/sound/sound_switch.c b/drivers/sound/sound_switch.c
index 122825440..bacdccb66 100644
--- a/drivers/sound/sound_switch.c
+++ b/drivers/sound/sound_switch.c
@@ -16,6 +16,7 @@
#include "sound_config.h"
static int in_use = 0; /* Total # of open devices */
+unsigned long seq_time = 0; /* Time for /dev/sequencer */
/*
* Table for configurable mixer volume handling
@@ -167,17 +168,22 @@ init_status (void)
status_ptr = 0;
#ifdef SOUND_UNAME_A
- put_status ("Sound Driver:" SOUND_VERSION_STRING
+ put_status ("OSS/Free" SOUND_VERSION_STRING
" (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY ",\n"
SOUND_UNAME_A ")"
"\n");
#else
- put_status ("Sound Driver:" SOUND_VERSION_STRING
+ put_status ("OSS/Free:" SOUND_VERSION_STRING
" (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY "@"
SOUND_CONFIG_HOST "." SOUND_CONFIG_DOMAIN ")"
"\n");
#endif
+#ifdef MODULE
+ put_status ("Load type: Driver loaded as a module.\n");
+#else
+ put_status ("Load type: Driver compiled into kernel\n");
+#endif
put_status ("Kernel: ");
put_status (system_utsname.sysname);
put_status (" ");
@@ -189,6 +195,9 @@ init_status (void)
put_status (" ");
put_status (system_utsname.machine);
put_status ("\n");
+#ifdef MODULE
+ put_status ("Driver loaded as a module\n");
+#endif
if (!put_status ("Config options: "))
diff --git a/drivers/sound/soundcard.c b/drivers/sound/soundcard.c
index fc6a5a94c..088591b9d 100644
--- a/drivers/sound/soundcard.c
+++ b/drivers/sound/soundcard.c
@@ -139,8 +139,8 @@ sound_release (struct inode *inode, struct file *file)
sound_release_sw (dev, &files[dev]);
#ifdef MODULE
MOD_DEC_USE_COUNT;
-#endif
return 0;
+#endif
}
static int
@@ -156,7 +156,7 @@ sound_ioctl (struct inode *inode, struct file *file,
files[dev].flags = file->f_flags;
- if (_SIOC_DIR (cmd) != _SIOC_NONE)
+ if (_SIOC_DIR (cmd) != _SIOC_NONE && _SIOC_DIR (cmd) != 0)
{
/*
* Have to validate the address given by the process.
@@ -196,7 +196,7 @@ sound_ioctl (struct inode *inode, struct file *file,
if (ptr != NULL && alloced)
vfree (ptr);
- return err;
+ return ((err < 0) ? err : 0);
}
static int
@@ -229,7 +229,7 @@ sound_select (struct inode *inode, struct file *file, int sel_type, poll_table *
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
- return audio_select (dev, &files[dev], sel_type, wait);
+ return DMAbuf_select (dev >> 4, &files[dev], sel_type, wait);
break;
#endif
@@ -275,20 +275,14 @@ sound_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma)
return -EINVAL;
}
- if ((vma->vm_flags & (VM_READ | VM_WRITE)) == (VM_READ | VM_WRITE))
+ if (vma->vm_flags & VM_WRITE) /* Map write and read/write to the output buf */
{
- printk ("Sound: Cannot do read/write mmap()\n");
- return -EINVAL;
+ dmap = audio_devs[dev]->dmap_out;
}
-
- if (vma->vm_flags & VM_READ)
+ else if (vma->vm_flags & VM_READ)
{
dmap = audio_devs[dev]->dmap_in;
}
- else if (vma->vm_flags & VM_WRITE)
- {
- dmap = audio_devs[dev]->dmap_out;
- }
else
{
printk ("Sound: Undefined mmap() access\n");
@@ -379,20 +373,10 @@ soundcard_init (void)
#ifdef CONFIG_AUDIO
if (num_audiodevs) /* Audio devices present */
{
- DMAbuf_init ();
audio_init_devices ();
}
#endif
-#ifdef CONFIG_MIDI
- if (num_midis)
- MIDIbuf_init ();
-#endif
-
-#ifdef CONFIG_SEQUENCER
- if (num_midis + num_synths)
- sequencer_init ();
-#endif
}
@@ -616,9 +600,15 @@ sound_close_dma (int chn)
#ifdef CONFIG_SEQUENCER
+static void
+do_sequencer_timer (unsigned long dummy)
+{
+ sequencer_timer (0);
+}
+
static struct timer_list seq_timer =
-{NULL, NULL, 0, 0, sequencer_timer};
+{NULL, NULL, 0, 0, do_sequencer_timer};
void
request_sound_timer (int count)
@@ -681,33 +671,31 @@ sound_alloc_dmap (int dev, struct dma_buffparms *dmap, int chan)
dmap->raw_buf = NULL;
- if (debugmem)
- printk ("sound: buffsize[%d] = %lu\n", dev, audio_devs[dev]->buffsize);
-
- audio_devs[dev]->buffsize = dma_buffsize;
+ dmap->buffsize = dma_buffsize;
- if (audio_devs[dev]->buffsize > dma_pagesize)
- audio_devs[dev]->buffsize = dma_pagesize;
+ if (dmap->buffsize > dma_pagesize)
+ dmap->buffsize = dma_pagesize;
start_addr = NULL;
/*
* Now loop until we get a free buffer. Try to get smaller buffer if
- * it fails.
+ * it fails. Don't accept smaller than 8k buffer for performance
+ * reasons.
*/
- while (start_addr == NULL && audio_devs[dev]->buffsize > PAGE_SIZE)
+ while (start_addr == NULL && dmap->buffsize > PAGE_SIZE)
{
int sz, size;
for (sz = 0, size = PAGE_SIZE;
- size < audio_devs[dev]->buffsize;
+ size < dmap->buffsize;
sz++, size <<= 1);
- audio_devs[dev]->buffsize = PAGE_SIZE * (1 << sz);
+ dmap->buffsize = PAGE_SIZE * (1 << sz);
if ((start_addr = (char *) __get_free_pages (GFP_ATOMIC, sz, MAX_DMA_ADDRESS)) == NULL)
- audio_devs[dev]->buffsize /= 2;
+ dmap->buffsize /= 2;
}
if (start_addr == NULL)
@@ -718,7 +706,7 @@ sound_alloc_dmap (int dev, struct dma_buffparms *dmap, int chan)
else
{
/* make some checks */
- end_addr = start_addr + audio_devs[dev]->buffsize - 1;
+ end_addr = start_addr + dmap->buffsize - 1;
if (debugmem)
printk ("sound: start 0x%lx, end 0x%lx\n",
@@ -731,9 +719,9 @@ sound_alloc_dmap (int dev, struct dma_buffparms *dmap, int chan)
|| end_addr >= (char *) (MAX_DMA_ADDRESS))
{
printk (
- "sound: Got invalid address 0x%lx for %ldb DMA-buffer\n",
+ "sound: Got invalid address 0x%lx for %db DMA-buffer\n",
(long) start_addr,
- audio_devs[dev]->buffsize);
+ dmap->buffsize);
return -EFAULT;
}
}
@@ -761,11 +749,11 @@ sound_free_dmap (int dev, struct dma_buffparms *dmap, int chan)
return; /* Don't free mmapped buffer. Will use it next time */
for (sz = 0, size = PAGE_SIZE;
- size < audio_devs[dev]->buffsize;
+ size < dmap->buffsize;
sz++, size <<= 1);
start_addr = (unsigned long) dmap->raw_buf;
- end_addr = start_addr + audio_devs[dev]->buffsize;
+ end_addr = start_addr + dmap->buffsize;
for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++)
{
@@ -776,6 +764,33 @@ sound_free_dmap (int dev, struct dma_buffparms *dmap, int chan)
dmap->raw_buf = NULL;
}
+
+/* Intel version !!!!!!!!! */
+int
+sound_start_dma (int dev, struct dma_buffparms *dmap, int chan,
+ unsigned long physaddr,
+ int count, int dma_mode, int autoinit)
+{
+ unsigned long flags;
+
+ /* printk("Start DMA%d %d, %d\n", chan, (int)(physaddr-dmap->raw_buf_phys), count); */
+ if (autoinit)
+ dma_mode |= DMA_AUTOINIT;
+ save_flags (flags);
+ cli ();
+ disable_dma (chan);
+ clear_dma_ff (chan);
+ set_dma_mode (chan, dma_mode);
+ set_dma_addr (chan, physaddr);
+ set_dma_count (chan, count);
+ enable_dma (chan);
+ restore_flags (flags);
+
+ return 0;
+}
+
+#endif
+
void
conf_printf (char *name, struct address_info *hw_config)
{
@@ -817,29 +832,3 @@ conf_printf2 (char *name, int base, int irq, int dma, int dma2)
printk ("\n");
}
-
-/* Intel version !!!!!!!!! */
-int
-sound_start_dma (int dev, struct dma_buffparms *dmap, int chan,
- unsigned long physaddr,
- int count, int dma_mode, int autoinit)
-{
- unsigned long flags;
-
-/* printk("Start DMA %d, %d\n", (int)(physaddr-dmap->raw_buf_phys), count); */
- if (autoinit)
- dma_mode |= DMA_AUTOINIT;
- save_flags (flags);
- cli ();
- disable_dma (chan);
- clear_dma_ff (chan);
- set_dma_mode (chan, dma_mode);
- set_dma_addr (chan, physaddr);
- set_dma_count (chan, count);
- enable_dma (chan);
- restore_flags (flags);
-
- return 0;
-}
-
-#endif
diff --git a/drivers/sound/soundvers.h b/drivers/sound/soundvers.h
index 6bcb5c3b6..5b9b6a5c6 100644
--- a/drivers/sound/soundvers.h
+++ b/drivers/sound/soundvers.h
@@ -1,2 +1,2 @@
-#define SOUND_VERSION_STRING "3.8-beta9-970226"
-#define SOUND_INTERNAL_VERSION 0x030803
+#define SOUND_VERSION_STRING "3.8a"
+#define SOUND_INTERNAL_VERSION 0x030804
diff --git a/drivers/sound/sscape.c b/drivers/sound/sscape.c
index ea8d6b800..c5cf7de3f 100644
--- a/drivers/sound/sscape.c
+++ b/drivers/sound/sscape.c
@@ -59,16 +59,16 @@
#define CMD_GEN_HOST_ACK 0x80
#define CMD_GEN_MPU_ACK 0x81
#define CMD_GET_BOARD_TYPE 0x82
-#define CMD_SET_CONTROL 0x88
-#define CMD_GET_CONTROL 0x89
+#define CMD_SET_CONTROL 0x88 /* Old firmware only */
+#define CMD_GET_CONTROL 0x89 /* Old firmware only */
#define CTL_MASTER_VOL 0
#define CTL_MIC_MODE 2
#define CTL_SYNTH_VOL 4
#define CTL_WAVE_VOL 7
-#define CMD_SET_MT32 0x96
-#define CMD_GET_MT32 0x97
-#define CMD_SET_EXTMIDI 0x9b
-#define CMD_GET_EXTMIDI 0x9c
+#define CMD_SET_EXTMIDI 0x8a
+#define CMD_GET_EXTMIDI 0x8b
+#define CMD_SET_MT32 0x8c
+#define CMD_GET_MT32 0x8d
#define CMD_ACK 0x80
@@ -78,15 +78,16 @@ typedef struct sscape_info
int ok; /* Properly detected */
int failed;
int dma_allocated;
- int my_audiodev;
+ int codec_audiodev;
int opened;
int *osp;
}
-
sscape_info;
-static struct sscape_info dev_info =
+
+static struct sscape_info adev_info =
{0};
-static struct sscape_info *devc = &dev_info;
+static struct sscape_info *devc = &adev_info;
+static int sscape_mididev = -1;
static struct wait_queue *sscape_sleeper = NULL;
static volatile struct snd_wait sscape_sleep_flag =
@@ -270,19 +271,7 @@ set_control (struct sscape_info *devc, int ctrl, int value)
host_close (devc);
}
-static int
-get_board_type (struct sscape_info *devc)
-{
- int tmp;
- host_open (devc);
- if (!host_command1 (devc, CMD_GET_BOARD_TYPE))
- tmp = -1;
- else
- tmp = host_read (devc);
- host_close (devc);
- return tmp;
-}
@@ -297,11 +286,11 @@ do_dma (struct sscape_info *devc, int dma_chan, unsigned long buf, int blk_size,
return;
}
- audio_devs[devc->my_audiodev]->flags &= ~DMA_AUTOMODE;
- DMAbuf_start_dma (devc->my_audiodev,
+ audio_devs[devc->codec_audiodev]->flags &= ~DMA_AUTOMODE;
+ DMAbuf_start_dma (devc->codec_audiodev,
buf,
blk_size, mode);
- audio_devs[devc->my_audiodev]->flags |= DMA_AUTOMODE;
+ audio_devs[devc->codec_audiodev]->flags |= DMA_AUTOMODE;
temp = devc->dma << 4; /* Setup DMA channel select bits */
if (devc->dma <= 3)
@@ -384,7 +373,7 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size,
{
unsigned long flags;
unsigned char temp;
- int done, timeout_val;
+ volatile int done, timeout_val;
static unsigned char codec_dma_bits = 0;
if (flag & CPF_FIRST)
@@ -418,13 +407,19 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size,
/*
* Transfer one code block using DMA
*/
- memcpy (audio_devs[devc->my_audiodev]->dmap_out->raw_buf, block, size);
+ if (audio_devs[devc->codec_audiodev]->dmap_out->raw_buf == NULL)
+ {
+ printk ("SSCAPE: Error: DMA buffer not available\n");
+ return 0;
+ }
+
+ memcpy (audio_devs[devc->codec_audiodev]->dmap_out->raw_buf, block, size);
save_flags (flags);
cli ();
/******** INTERRUPTS DISABLED NOW ********/
do_dma (devc, SSCAPE_DMA_A,
- audio_devs[devc->my_audiodev]->dmap_out->raw_buf_phys,
+ audio_devs[devc->codec_audiodev]->dmap_out->raw_buf_phys,
size, DMA_MODE_WRITE);
/*
@@ -432,17 +427,16 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size,
*/
sscape_sleep_flag.opts = WK_NONE;
done = 0;
- timeout_val = 100;
+ timeout_val = 30;
while (!done && timeout_val-- > 0)
{
int resid;
-
{
unsigned long tlimit;
- if (1)
- current->timeout = tlimit = jiffies + (1);
+ if (HZ / 50)
+ current->timeout = tlimit = jiffies + (HZ / 50);
else
tlimit = (unsigned long) -1;
sscape_sleep_flag.opts = WK_SLEEP;
@@ -509,7 +503,7 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size,
x = inb (PORT (HOST_DATA));
if (x == 0xff || x == 0xfe) /* OBP startup acknowledge */
{
- printk ("Soundscape: Acknowledge = %x\n", x);
+ DDB (printk ("Soundscape: Acknowledge = %x\n", x));
done = 1;
}
}
@@ -555,9 +549,7 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size,
return 0;
}
- printk ("SoundScape board of type %d initialized OK\n",
- get_board_type (devc));
-
+ printk ("SoundScape board initialized OK\n");
set_control (devc, CTL_MASTER_VOL, 100);
set_control (devc, CTL_SYNTH_VOL, 100);
@@ -633,7 +625,7 @@ static coproc_operations sscape_coproc_operations =
sscape_coproc_close,
sscape_coproc_ioctl,
sscape_coproc_reset,
- &dev_info
+ &adev_info
};
static int sscape_detected = 0;
@@ -678,6 +670,7 @@ attach_sscape (struct address_info *hw_config)
if (sscape_detected != hw_config->io_base)
return;
+ request_region (devc->base + 2, 6, "SoundScape");
if (old_hardware)
{
valid_interrupts = valid_interrupts_old;
@@ -765,13 +758,17 @@ attach_sscape (struct address_info *hw_config)
hw_config->irq *= -1; /* Restore it */
if (num_midis == (prev_devs + 1)) /* The MPU driver installed itself */
- midi_devs[prev_devs]->coproc = &sscape_coproc_operations;
+ {
+ sscape_mididev = prev_devs;
+ midi_devs[prev_devs]->coproc = &sscape_coproc_operations;
+ }
}
#endif
sscape_write (devc, GA_INTENA_REG, 0x80); /* Master IRQ enable */
devc->ok = 1;
devc->failed = 0;
+
}
static int
@@ -841,17 +838,13 @@ int
probe_sscape (struct address_info *hw_config)
{
- devc->base = hw_config->io_base;
- devc->irq = hw_config->irq;
- devc->dma = hw_config->dma;
-
if (sscape_detected != 0 && sscape_detected != hw_config->io_base)
return 0;
- devc->failed = 1;
-
- if (!detect_ga (devc))
- return 0;
+ devc->base = hw_config->io_base;
+ devc->irq = hw_config->irq;
+ devc->dma = hw_config->dma;
+ devc->osp = hw_config->osp;
#ifdef SSCAPE_DEBUG1
/*
@@ -866,6 +859,12 @@ probe_sscape (struct address_info *hw_config)
}
#endif
+
+ devc->failed = 1;
+
+ if (!detect_ga (devc))
+ return 0;
+
if (old_hardware) /* Check that it's really an old Spea/Reveal card. */
{
unsigned char tmp;
@@ -877,8 +876,6 @@ probe_sscape (struct address_info *hw_config)
for (cc = 0; cc < 200000; ++cc)
inb (devc->base + ODIE_ADDR);
}
- else
- old_hardware = 0;
}
@@ -891,6 +888,7 @@ int
probe_ss_ms_sound (struct address_info *hw_config)
{
int i, irq_bits = 0xff;
+ int ad_flags = 0;
if (devc->failed)
{
@@ -917,7 +915,9 @@ probe_ss_ms_sound (struct address_info *hw_config)
}
- return ad1848_detect (hw_config->io_base, NULL, hw_config->osp);
+ if (old_hardware)
+ ad_flags = 0x12345677; /* Tell that we may have a CS4248 chip (Spea-V7 Media FX) */
+ return ad1848_detect (hw_config->io_base, &ad_flags, hw_config->osp);
}
void
@@ -970,8 +970,13 @@ attach_ss_ms_sound (struct address_info *hw_config)
devc->osp);
if (num_audiodevs == (prev_devs + 1)) /* The AD1848 driver installed itself */
- audio_devs[prev_devs]->coproc = &sscape_coproc_operations;
- devc->my_audiodev = prev_devs;
+ {
+ audio_devs[prev_devs]->coproc = &sscape_coproc_operations;
+ devc->codec_audiodev = prev_devs;
+
+ /* Set proper routings here (what are they) */
+ AD1848_REROUTE (SOUND_MIXER_LINE1, SOUND_MIXER_LINE);
+ }
#ifdef SSCAPE_DEBUG5
/*
@@ -991,10 +996,10 @@ attach_ss_ms_sound (struct address_info *hw_config)
void
unload_sscape (struct address_info *hw_config)
{
+ release_region (devc->base + 2, 6);
#if defined(CONFIG_MPU_EMU) && defined(CONFIG_MIDI)
unload_mpu401 (hw_config);
#endif
- snd_release_irq (hw_config->irq);
}
void
@@ -1008,4 +1013,5 @@ unload_ss_ms_sound (struct address_info *hw_config)
}
+
#endif
diff --git a/drivers/sound/trix.c b/drivers/sound/trix.c
index 0dcd88a25..5bb60ea6a 100644
--- a/drivers/sound/trix.c
+++ b/drivers/sound/trix.c
@@ -339,9 +339,19 @@ probe_trix_sb (struct address_info *hw_config)
void
attach_trix_sb (struct address_info *hw_config)
{
+ extern int sb_be_quiet;
+ int old_quiet;
+
#ifdef CONFIG_SBDSP
hw_config->driver_use_1 = SB_NO_MIDI | SB_NO_MIXER | SB_NO_RECORDING;
+
+ /* Prevent false alarms */
+ old_quiet = sb_be_quiet;
+ sb_be_quiet = 1;
+
sb_dsp_init (hw_config);
+
+ sb_be_quiet = old_quiet;
#endif
}
diff --git a/drivers/sound/uart401.c b/drivers/sound/uart401.c
index f2fef6d07..e8a399cb6 100644
--- a/drivers/sound/uart401.c
+++ b/drivers/sound/uart401.c
@@ -346,6 +346,7 @@ attach_uart401 (struct address_info *hw_config)
strcpy (midi_devs[num_midis]->info.name, name);
midi_devs[num_midis]->converter->id = "UART401";
num_midis++;
+ sequencer_init ();
devc->opened = 0;
}
diff --git a/drivers/sound/uart6850.c b/drivers/sound/uart6850.c
index 0610d1247..547cbba92 100644
--- a/drivers/sound/uart6850.c
+++ b/drivers/sound/uart6850.c
@@ -294,6 +294,7 @@ attach_uart6850 (struct address_info *hw_config)
std_midi_synth.midi_dev = my_dev = num_midis;
midi_devs[num_midis++] = &uart6850_operations;
+ sequencer_init ();
}
static int
diff --git a/drivers/sound/ulaw.h b/drivers/sound/ulaw.h
index be9f92d99..0ff8c0a3b 100644
--- a/drivers/sound/ulaw.h
+++ b/drivers/sound/ulaw.h
@@ -1,69 +1,69 @@
static unsigned char ulaw_dsp[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 2,
- 5, 9, 13, 17, 21, 25, 29, 33,
- 37, 41, 45, 49, 53, 57, 61, 65,
- 68, 70, 72, 74, 76, 78, 80, 82,
- 84, 86, 88, 90, 92, 94, 96, 98,
- 100, 101, 102, 103, 104, 105, 106, 107,
- 108, 109, 110, 111, 112, 113, 114, 115,
- 115, 116, 116, 117, 117, 118, 118, 119,
- 119, 120, 120, 121, 121, 122, 122, 123,
- 123, 123, 124, 124, 124, 124, 125, 125,
- 125, 125, 126, 126, 126, 126, 127, 127,
- 127, 127, 127, 127, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255,
- 252, 248, 244, 240, 236, 232, 228, 224,
- 220, 216, 212, 208, 204, 200, 196, 192,
- 189, 187, 185, 183, 181, 179, 177, 175,
- 173, 171, 169, 167, 165, 163, 161, 159,
- 157, 156, 155, 154, 153, 152, 151, 150,
- 149, 148, 147, 146, 145, 144, 143, 142,
- 142, 141, 141, 140, 140, 139, 139, 138,
- 138, 137, 137, 136, 136, 135, 135, 134,
- 134, 134, 133, 133, 133, 133, 132, 132,
- 132, 132, 131, 131, 131, 131, 130, 130,
- 130, 130, 130, 130, 129, 129, 129, 129,
- 129, 129, 129, 129, 128, 128, 128, 128,
+ 3, 7, 11, 15, 19, 23, 27, 31,
+ 35, 39, 43, 47, 51, 55, 59, 63,
+ 66, 68, 70, 72, 74, 76, 78, 80,
+ 82, 84, 86, 88, 90, 92, 94, 96,
+ 98, 99, 100, 101, 102, 103, 104, 105,
+ 106, 107, 108, 109, 110, 111, 112, 113,
+ 113, 114, 114, 115, 115, 116, 116, 117,
+ 117, 118, 118, 119, 119, 120, 120, 121,
+ 121, 121, 122, 122, 122, 122, 123, 123,
+ 123, 123, 124, 124, 124, 124, 125, 125,
+ 125, 125, 125, 125, 126, 126, 126, 126,
+ 126, 126, 126, 126, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 253, 249, 245, 241, 237, 233, 229, 225,
+ 221, 217, 213, 209, 205, 201, 197, 193,
+ 190, 188, 186, 184, 182, 180, 178, 176,
+ 174, 172, 170, 168, 166, 164, 162, 160,
+ 158, 157, 156, 155, 154, 153, 152, 151,
+ 150, 149, 148, 147, 146, 145, 144, 143,
+ 143, 142, 142, 141, 141, 140, 140, 139,
+ 139, 138, 138, 137, 137, 136, 136, 135,
+ 135, 135, 134, 134, 134, 134, 133, 133,
+ 133, 133, 132, 132, 132, 132, 131, 131,
+ 131, 131, 131, 131, 130, 130, 130, 130,
+ 130, 130, 130, 130, 129, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 129, 129,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
};
static unsigned char dsp_ulaw[] = {
- 31, 31, 31, 32, 32, 32, 32, 33,
- 33, 33, 33, 34, 34, 34, 34, 35,
- 35, 35, 35, 36, 36, 36, 36, 37,
- 37, 37, 37, 38, 38, 38, 38, 39,
- 39, 39, 39, 40, 40, 40, 40, 41,
- 41, 41, 41, 42, 42, 42, 42, 43,
- 43, 43, 43, 44, 44, 44, 44, 45,
- 45, 45, 45, 46, 46, 46, 46, 47,
- 47, 47, 47, 48, 48, 49, 49, 50,
- 50, 51, 51, 52, 52, 53, 53, 54,
- 54, 55, 55, 56, 56, 57, 57, 58,
- 58, 59, 59, 60, 60, 61, 61, 62,
- 62, 63, 63, 64, 65, 66, 67, 68,
- 69, 70, 71, 72, 73, 74, 75, 76,
- 77, 78, 79, 81, 83, 85, 87, 89,
- 91, 93, 95, 99, 103, 107, 111, 119,
- 255, 247, 239, 235, 231, 227, 223, 221,
- 219, 217, 215, 213, 211, 209, 207, 206,
- 205, 204, 203, 202, 201, 200, 199, 198,
- 197, 196, 195, 194, 193, 192, 191, 191,
- 190, 190, 189, 189, 188, 188, 187, 187,
- 186, 186, 185, 185, 184, 184, 183, 183,
- 182, 182, 181, 181, 180, 180, 179, 179,
- 178, 178, 177, 177, 176, 176, 175, 175,
- 175, 175, 174, 174, 174, 174, 173, 173,
- 173, 173, 172, 172, 172, 172, 171, 171,
- 171, 171, 170, 170, 170, 170, 169, 169,
- 169, 169, 168, 168, 168, 168, 167, 167,
- 167, 167, 166, 166, 166, 166, 165, 165,
- 165, 165, 164, 164, 164, 164, 163, 163,
- 163, 163, 162, 162, 162, 162, 161, 161,
- 161, 161, 160, 160, 160, 160, 159, 159,
+ 0, 0, 0, 0, 0, 1, 1, 1,
+ 1, 2, 2, 2, 2, 3, 3, 3,
+ 3, 4, 4, 4, 4, 5, 5, 5,
+ 5, 6, 6, 6, 6, 7, 7, 7,
+ 7, 8, 8, 8, 8, 9, 9, 9,
+ 9, 10, 10, 10, 10, 11, 11, 11,
+ 11, 12, 12, 12, 12, 13, 13, 13,
+ 13, 14, 14, 14, 14, 15, 15, 15,
+ 15, 16, 16, 17, 17, 18, 18, 19,
+ 19, 20, 20, 21, 21, 22, 22, 23,
+ 23, 24, 24, 25, 25, 26, 26, 27,
+ 27, 28, 28, 29, 29, 30, 30, 31,
+ 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 49, 51, 53, 55, 57, 59, 61,
+ 63, 66, 70, 74, 78, 84, 92, 104,
+ 254, 231, 219, 211, 205, 201, 197, 193,
+ 190, 188, 186, 184, 182, 180, 178, 176,
+ 175, 174, 173, 172, 171, 170, 169, 168,
+ 167, 166, 165, 164, 163, 162, 161, 160,
+ 159, 159, 158, 158, 157, 157, 156, 156,
+ 155, 155, 154, 154, 153, 153, 152, 152,
+ 151, 151, 150, 150, 149, 149, 148, 148,
+ 147, 147, 146, 146, 145, 145, 144, 144,
+ 143, 143, 143, 143, 142, 142, 142, 142,
+ 141, 141, 141, 141, 140, 140, 140, 140,
+ 139, 139, 139, 139, 138, 138, 138, 138,
+ 137, 137, 137, 137, 136, 136, 136, 136,
+ 135, 135, 135, 135, 134, 134, 134, 134,
+ 133, 133, 133, 133, 132, 132, 132, 132,
+ 131, 131, 131, 131, 130, 130, 130, 130,
+ 129, 129, 129, 129, 128, 128, 128, 128,
};
diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h
index d3b6e484f..4183b88b1 100644
--- a/fs/autofs/autofs_i.h
+++ b/fs/autofs/autofs_i.h
@@ -12,6 +12,8 @@
/* Internal header file for autofs */
+#define DEBUG_WAITLIST 1
+
#include <linux/auto_fs.h>
/* This is the range of ioctl() numbers we claim as ours */
@@ -120,7 +122,10 @@ struct autofs_symlink {
#define END_OF_TIME ((time_t)((unsigned long)((time_t)(~0UL)) >> 1))
#endif
+#define AUTOFS_SBI_MAGIC 0x6d4a556d
+
struct autofs_sb_info {
+ u32 magic;
struct file *pipe;
pid_t oz_pgrp;
int catatonic;
@@ -137,6 +142,15 @@ static inline int autofs_oz_mode(struct autofs_sb_info *sbi) {
return sbi->catatonic || current->pgrp == sbi->oz_pgrp;
}
+/* Debug the mysteriously disappearing wait list */
+
+#ifdef DEBUG_WAITLIST
+#define CHECK_WAITLIST(S,O) autofs_check_waitlist_integrity(S,O)
+void autofs_check_waitlist_integrity(struct autofs_sb_info *,char *);
+#else
+#define CHECK_WAITLIST(S,O)
+#endif
+
/* Hash operations */
autofs_hash_t autofs_hash(const char *,int);
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
index a8c176a02..20ca0907a 100644
--- a/fs/autofs/inode.c
+++ b/fs/autofs/inode.c
@@ -150,6 +150,7 @@ struct super_block *autofs_read_super(struct super_block *s, void *data,
DPRINTK(("autofs: starting up, sbi = %p\n",sbi));
s->u.generic_sbp = sbi;
+ sbi->magic = AUTOFS_SBI_MAGIC;
sbi->catatonic = 0;
sbi->exp_timeout = 0;
sbi->oz_pgrp = current->pgrp;
diff --git a/fs/autofs/root.c b/fs/autofs/root.c
index 57449e816..69e62f823 100644
--- a/fs/autofs/root.c
+++ b/fs/autofs/root.c
@@ -190,30 +190,33 @@ static int autofs_root_symlink(struct inode *dir, const char *name, int len, con
DPRINTK(("autofs_root_symlink: %s <- ", symname));
autofs_say(name,len);
- iput(dir);
-
- if ( !autofs_oz_mode(sbi) )
+ if ( !autofs_oz_mode(sbi) ) {
+ iput(dir);
return -EPERM;
-
- if ( autofs_hash_lookup(dh,hash,name,len) )
+ }
+ if ( autofs_hash_lookup(dh,hash,name,len) ) {
+ iput(dir);
return -EEXIST;
-
+ }
n = find_first_zero_bit(sbi->symlink_bitmap,AUTOFS_MAX_SYMLINKS);
- if ( n >= AUTOFS_MAX_SYMLINKS )
+ if ( n >= AUTOFS_MAX_SYMLINKS ) {
+ iput(dir);
return -ENOSPC;
-
+ }
set_bit(n,sbi->symlink_bitmap);
sl = &sbi->symlink[n];
sl->len = strlen(symname);
sl->data = kmalloc(slsize = sl->len+1, GFP_KERNEL);
if ( !sl->data ) {
clear_bit(n,sbi->symlink_bitmap);
+ iput(dir);
return -ENOSPC;
}
ent = kmalloc(sizeof(struct autofs_dir_ent), GFP_KERNEL);
if ( !ent ) {
kfree(sl->data);
clear_bit(n,sbi->symlink_bitmap);
+ iput(dir);
return -ENOSPC;
}
ent->name = kmalloc(len, GFP_KERNEL);
@@ -221,6 +224,7 @@ static int autofs_root_symlink(struct inode *dir, const char *name, int len, con
kfree(sl->data);
kfree(ent);
clear_bit(n,sbi->symlink_bitmap);
+ iput(dir);
return -ENOSPC;
}
memcpy(sl->data,symname,slsize);
@@ -231,6 +235,7 @@ static int autofs_root_symlink(struct inode *dir, const char *name, int len, con
memcpy(ent->name,name,ent->len = len);
autofs_hash_insert(dh,ent);
+ iput(dir);
return 0;
}
@@ -243,15 +248,19 @@ static int autofs_root_unlink(struct inode *dir, const char *name, int len)
struct autofs_dir_ent *ent;
unsigned int n;
+ iput(dir); /* Nothing below can sleep */
+
if ( !autofs_oz_mode(sbi) )
return -EPERM;
ent = autofs_hash_lookup(dh,hash,name,len);
if ( !ent )
return -ENOENT;
+
n = ent->ino - AUTOFS_FIRST_SYMLINK;
if ( n >= AUTOFS_MAX_SYMLINKS || !test_bit(n,sbi->symlink_bitmap) )
return -EINVAL; /* Not a symlink inode, can't unlink */
+
autofs_hash_delete(ent);
clear_bit(n,sbi->symlink_bitmap);
kfree(sbi->symlink[n].data);
diff --git a/fs/autofs/waitq.c b/fs/autofs/waitq.c
index b37745f19..719e04eb4 100644
--- a/fs/autofs/waitq.c
+++ b/fs/autofs/waitq.c
@@ -16,6 +16,46 @@
#include <linux/file.h>
#include "autofs_i.h"
+#ifdef DEBUG_WAITLIST
+#ifndef i386
+#error Only i386 implemented
+#endif
+
+static inline int sane_pointer(void *p)
+{
+ return (p == NULL) || ((unsigned) p > 0xc0000000);
+}
+
+void autofs_check_waitlist_integrity(struct autofs_sb_info *sbi, char *op)
+{
+ struct autofs_wait_queue **wqp, *wq;
+
+ if ( sbi->magic != AUTOFS_SBI_MAGIC ) {
+ printk("autofs: CHECK_WAITLIST with bogus sbi pointer: %p\n",
+ sbi);
+ return;
+ }
+
+ wqp = &(sbi->queues);
+ while ( (wq = *wqp) ) {
+ if ( !sane_pointer(wq) ) {
+ printk("autofs(%s): wait queue pointer corrupt: ", op);
+ wqp = &(sbi->queues);
+ do {
+ wq = *wqp;
+ printk(" %p", wq);
+ wqp = &(wq->next);
+ } while ( sane_pointer(*wqp) );
+ printk("\n");
+ *wqp = NULL;
+ break;
+ } else {
+ wqp = &(wq->next);
+ }
+ }
+}
+#endif
+
/* We make this a static variable rather than a part of the superblock; it
is better if we don't reassign numbers easily even across filesystems */
static int autofs_next_wait_queue = 1;
@@ -95,6 +135,8 @@ int autofs_wait(struct autofs_sb_info *sbi, autofs_hash_t hash, const char *name
struct autofs_wait_queue *wq;
int status;
+ CHECK_WAITLIST(sbi,"wait");
+
for ( wq = sbi->queues ; wq ; wq = wq->next ) {
if ( wq->hash == hash &&
wq->len == len &&
@@ -148,6 +190,8 @@ int autofs_wait_release(struct autofs_sb_info *sbi, unsigned long wait_queue_tok
{
struct autofs_wait_queue *wq, **wql;
+ CHECK_WAITLIST(sbi,"release");
+
for ( wql = &sbi->queues ; (wq = *wql) ; wql = &wq->next ) {
if ( wq->wait_queue_token == wait_queue_token )
break;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 3c17b6eec..4e2de9cfc 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -178,7 +178,7 @@ nfs_writepage_sync(struct inode *inode, struct page *page,
wsize = count;
result = nfs_proc_write(NFS_SERVER(inode), NFS_FH(inode),
- offset, wsize, IS_SWAPFILE(inode),
+ IS_SWAPFILE(inode), offset, wsize,
buffer, &fattr);
if (result < 0) {
diff --git a/fs/proc/array.c b/fs/proc/array.c
index f8d5d3464..516e87813 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -297,20 +297,14 @@ static int get_uptime(char * buffer)
static int get_meminfo(char * buffer)
{
struct sysinfo i;
- int len;
si_meminfo(&i);
si_swapinfo(&i);
- len = sprintf(buffer, " total: used: free: shared: buffers: cached:\n"
- "Mem: %8lu %8lu %8lu %8lu %8lu %8lu\n"
- "Swap: %8lu %8lu %8lu\n",
- i.totalram, i.totalram-i.freeram, i.freeram, i.sharedram, i.bufferram, page_cache_size*PAGE_SIZE,
- i.totalswap, i.totalswap-i.freeswap, i.freeswap);
+
/*
- * Tagged format, for easy grepping and expansion. The above will go away
- * eventually, once the tools have been updated.
+ * Tagged format, for easy grepping and expansion.
*/
- return len + sprintf(buffer+len,
+ return sprintf(buffer,
"MemTotal: %8lu kB\n"
"MemFree: %8lu kB\n"
"MemShared: %8lu kB\n"
diff --git a/include/linux/.cvsignore b/include/linux/.cvsignore
index c4ff4db8f..24864670e 100644
--- a/include/linux/.cvsignore
+++ b/include/linux/.cvsignore
@@ -1,3 +1,4 @@
autoconf.h
version.h
compile.h
+modules
diff --git a/include/linux/mtio.h b/include/linux/mtio.h
index 65e15f92e..d2c4d70e8 100644
--- a/include/linux/mtio.h
+++ b/include/linux/mtio.h
@@ -225,6 +225,9 @@ struct mtconfiginfo {
#define MT_ST_WRITE_THRESHOLD 0x20000000
#define MT_ST_DEF_BLKSIZE 0x50000000
#define MT_ST_DEF_OPTIONS 0x60000000
+#define MT_ST_TIMEOUTS 0x70000000
+#define MT_ST_SET_TIMEOUT (MT_ST_TIMEOUTS | 0x000000)
+#define MT_ST_SET_LONG_TIMEOUT (MT_ST_TIMEOUTS | 0x100000)
#define MT_ST_BUFFER_WRITES 0x1
#define MT_ST_ASYNC_WRITES 0x2
@@ -238,6 +241,7 @@ struct mtconfiginfo {
#define MT_ST_NO_BLKLIMS 0x200
#define MT_ST_CAN_PARTITIONS 0x400
#define MT_ST_SCSI2LOGICAL 0x800
+#define MT_ST_SYSV 0x1000
/* The mode parameters to be controlled. Parameter chosen with bits 20-28 */
#define MT_ST_CLEAR_DEFAULT 0xfffff
diff --git a/include/linux/soundcard.h b/include/linux/soundcard.h
index bb338c462..1626ea917 100644
--- a/include/linux/soundcard.h
+++ b/include/linux/soundcard.h
@@ -33,7 +33,7 @@
* Use ioctl(fd, OSS_GETVERSION, &int) to get the version number of
* the currently active driver.
*/
-#define SOUND_VERSION 0x0307f1
+#define SOUND_VERSION 0x030800
#define OPEN_SOUND_SYSTEM
/* In Linux we need to be prepared for cross compiling */
@@ -76,7 +76,7 @@
*/
#ifndef _SIOWR
-#if defined(_IOWR) && !defined(sun) && !defined(sparc)
+#if defined(_IOWR) && (defined(_AIX) || (!defined(sun) && !defined(sparc) && !defined(__INCioctlh) && !defined(__Lynx__)))
/* Use already defined ioctl defines if they exist (except with Sun) */
#define SIOCPARM_MASK IOCPARM_MASK
#define SIOC_VOID IOC_VOID
@@ -127,7 +127,7 @@
#define SNDCTL_SEQ_GETOUTCOUNT _SIOR ('Q', 4, int)
#define SNDCTL_SEQ_GETINCOUNT _SIOR ('Q', 5, int)
#define SNDCTL_SEQ_PERCMODE _SIOW ('Q', 6, int)
-#define SNDCTL_FM_LOAD_INSTR _SIOW ('Q', 7, struct sbi_instrument) /* Obsolete */
+#define SNDCTL_FM_LOAD_INSTR _SIOW ('Q', 7, struct sbi_instrument) /* Obsolete. Don't use. */
#define SNDCTL_SEQ_TESTMIDI _SIOW ('Q', 8, int)
#define SNDCTL_SEQ_RESETSAMPLES _SIOW ('Q', 9, int)
#define SNDCTL_SEQ_NRSYNTHS _SIOR ('Q',10, int)
@@ -140,10 +140,25 @@
#define SNDCTL_SEQ_OUTOFBAND _SIOW ('Q',18, struct seq_event_rec)
#define SNDCTL_SEQ_GETTIME _SIOR ('Q',19, int)
#define SNDCTL_SYNTH_ID _SIOWR('Q',20, struct synth_info)
+#define SNDCTL_SYNTH_CONTROL _SIOWR('Q',21, struct synth_control)
+#define SNDCTL_SYNTH_REMOVESAMPLE _SIOWR('Q',22, struct remove_sample)
- struct seq_event_rec {
- unsigned char arr[8];
- };
+typedef struct synth_control
+{
+ int devno; /* Synthesizer # */
+ char data[4000]; /* Device spesific command/data record */
+}synth_control;
+
+typedef struct remove_sample
+{
+ int devno; /* Synthesizer # */
+ int bankno; /* MIDI bank # (0=General MIDI) */
+ int instrno; /* MIDI instrument number */
+} remove_sample;
+
+typedef struct seq_event_rec {
+ unsigned char arr[8];
+} seq_event_rec;
#define SNDCTL_TMR_TIMEBASE _SIOWR('T', 1, int)
#define SNDCTL_TMR_START _SIO ('T', 2)
diff --git a/kernel/exit.c b/kernel/exit.c
index 3fce2a2d7..88e012ba3 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -33,6 +33,7 @@ int getrusage(struct task_struct *, int, struct rusage *);
static inline void generate(unsigned long sig, struct task_struct * p)
{
+ unsigned flags;
unsigned long mask = 1 << (sig-1);
struct sigaction * sa = sig + p->sig->action - 1;
@@ -41,7 +42,7 @@ static inline void generate(unsigned long sig, struct task_struct * p)
* be handled immediately (ie non-blocked and untraced)
* and that is ignored (either explicitly or by default)
*/
- spin_lock_irq(&p->sig->siglock);
+ spin_lock_irqsave(&p->sig->siglock, flags);
if (!(mask & p->blocked) && !(p->flags & PF_PTRACED)) {
/* don't bother with ignored signals (but SIGCHLD is special) */
if (sa->sa_handler == SIG_IGN && sig != SIGCHLD)
@@ -57,7 +58,7 @@ static inline void generate(unsigned long sig, struct task_struct * p)
if (p->state == TASK_INTERRUPTIBLE && (p->signal & ~p->blocked))
wake_up_process(p);
out:
- spin_unlock_irq(&p->sig->siglock);
+ spin_unlock_irqrestore(&p->sig->siglock, flags);
}
/*
@@ -68,10 +69,11 @@ void force_sig(unsigned long sig, struct task_struct * p)
{
sig--;
if (p->sig) {
+ unsigned flags;
unsigned long mask = 1UL << sig;
struct sigaction *sa = p->sig->action + sig;
- spin_lock_irq(&p->sig->siglock);
+ spin_lock_irqsave(&p->sig->siglock, flags);
spin_lock(&p->sigmask_lock);
p->signal |= mask;
@@ -83,7 +85,7 @@ void force_sig(unsigned long sig, struct task_struct * p)
if (p->state == TASK_INTERRUPTIBLE)
wake_up_process(p);
- spin_unlock_irq(&p->sig->siglock);
+ spin_unlock_irqrestore(&p->sig->siglock, flags);
}
}
@@ -98,7 +100,8 @@ int send_sig(unsigned long sig,struct task_struct * p,int priv)
return -EPERM;
if (sig && p->sig) {
- spin_lock_irq(&p->sigmask_lock);
+ unsigned flags;
+ spin_lock_irqsave(&p->sigmask_lock, flags);
if ((sig == SIGKILL) || (sig == SIGCONT)) {
if (p->state == TASK_STOPPED)
wake_up_process(p);
@@ -108,7 +111,7 @@ int send_sig(unsigned long sig,struct task_struct * p,int priv)
}
if (sig == SIGSTOP || sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
p->signal &= ~(1<<(SIGCONT-1));
- spin_unlock_irq(&p->sigmask_lock);
+ spin_unlock_irqrestore(&p->sigmask_lock, flags);
/* Actually generate the signal */
generate(sig,p);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 19b3aa125..e32f1a92e 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -343,4 +343,3 @@ void swap_in(struct task_struct * tsk, struct vm_area_struct * vma,
swap_free(entry);
return;
}
-
diff --git a/mm/slab.c b/mm/slab.c
index addd0796a..e4db9e9e3 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1433,6 +1433,7 @@ alloc_new_slab:
/* Someone may have stolen our objs. Doesn't matter, we'll
* just come back here again.
*/
+ spin_lock_irq(&cachep->c_spinlock);
goto try_again;
}
/* Couldn't grow, but some objs may have been freed. */
diff --git a/mm/vmscan.c b/mm/vmscan.c
index d890be5df..875f668ee 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -345,7 +345,7 @@ out:
* to be. This works out OK, because we now do proper aging on page
* contents.
*/
-int try_to_free_page(int priority, int dma, int wait)
+static inline int do_try_to_free_page(int priority, int dma, int wait)
{
static int state = 0;
int i=6;
@@ -379,6 +379,22 @@ int try_to_free_page(int priority, int dma, int wait)
return 0;
}
+/*
+ * This is REALLY ugly.
+ *
+ * We need to make the locks finer granularity, but right
+ * now we need this so that we can do page allocations
+ * without holding the kernel lock etc.
+ */
+int try_to_free_page(int priority, int dma, int wait)
+{
+ int retval;
+
+ lock_kernel();
+ retval = do_try_to_free_page(priority,dma,wait);
+ unlock_kernel();
+ return retval;
+}
/*
* The background pageout daemon.