Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
e695b6a4
Commit
e695b6a4
authored
Nov 23, 2007
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Import 1.1.10
parent
ccec108f
Changes
56
Hide whitespace changes
Inline
Side-by-side
Showing
56 changed files
with
2817 additions
and
2146 deletions
+2817
-2146
Makefile
Makefile
+1
-1
drivers/net/3c509.c
drivers/net/3c509.c
+7
-4
drivers/sound/.blurb
drivers/sound/.blurb
+0
-6
drivers/sound/CHANGELOG
drivers/sound/CHANGELOG
+25
-2
drivers/sound/Makefile
drivers/sound/Makefile
+2
-2
drivers/sound/Readme
drivers/sound/Readme
+29
-87
drivers/sound/Readme.linux
drivers/sound/Readme.linux
+3
-2
drivers/sound/adlib_card.c
drivers/sound/adlib_card.c
+5
-5
drivers/sound/audio.c
drivers/sound/audio.c
+38
-35
drivers/sound/configure.c
drivers/sound/configure.c
+37
-35
drivers/sound/dev_table.c
drivers/sound/dev_table.c
+96
-84
drivers/sound/dev_table.h
drivers/sound/dev_table.h
+5
-1
drivers/sound/dmabuf.c
drivers/sound/dmabuf.c
+114
-113
drivers/sound/gus_card.c
drivers/sound/gus_card.c
+6
-6
drivers/sound/gus_hw.h
drivers/sound/gus_hw.h
+15
-0
drivers/sound/gus_linearvol.h
drivers/sound/gus_linearvol.h
+18
-0
drivers/sound/gus_midi.c
drivers/sound/gus_midi.c
+5
-5
drivers/sound/gus_vol.c
drivers/sound/gus_vol.c
+51
-16
drivers/sound/gus_wave.c
drivers/sound/gus_wave.c
+782
-635
drivers/sound/ics2101.c
drivers/sound/ics2101.c
+261
-0
drivers/sound/midibuf.c
drivers/sound/midibuf.c
+6
-6
drivers/sound/mpu401.c
drivers/sound/mpu401.c
+16
-59
drivers/sound/opl3.c
drivers/sound/opl3.c
+25
-16
drivers/sound/os.h
drivers/sound/os.h
+2
-2
drivers/sound/pas.h
drivers/sound/pas.h
+3
-3
drivers/sound/pas2_card.c
drivers/sound/pas2_card.c
+33
-33
drivers/sound/pas2_midi.c
drivers/sound/pas2_midi.c
+5
-5
drivers/sound/pas2_mixer.c
drivers/sound/pas2_mixer.c
+6
-6
drivers/sound/pas2_pcm.c
drivers/sound/pas2_pcm.c
+23
-22
drivers/sound/patmgr.c
drivers/sound/patmgr.c
+5
-5
drivers/sound/sb16_dsp.c
drivers/sound/sb16_dsp.c
+340
-330
drivers/sound/sb16_midi.c
drivers/sound/sb16_midi.c
+17
-48
drivers/sound/sb_card.c
drivers/sound/sb_card.c
+5
-5
drivers/sound/sb_dsp.c
drivers/sound/sb_dsp.c
+166
-135
drivers/sound/sb_midi.c
drivers/sound/sb_midi.c
+36
-9
drivers/sound/sb_mixer.c
drivers/sound/sb_mixer.c
+209
-140
drivers/sound/sb_mixer.h
drivers/sound/sb_mixer.h
+40
-0
drivers/sound/sequencer.c
drivers/sound/sequencer.c
+146
-122
drivers/sound/sound_calls.h
drivers/sound/sound_calls.h
+6
-1
drivers/sound/sound_switch.c
drivers/sound/sound_switch.c
+84
-56
drivers/sound/soundcard.c
drivers/sound/soundcard.c
+9
-8
fs/namei.c
fs/namei.c
+10
-0
include/asm/segment.h
include/asm/segment.h
+0
-14
include/linux/sched.h
include/linux/sched.h
+1
-3
include/linux/soundcard.h
include/linux/soundcard.h
+24
-4
include/linux/vm86.h
include/linux/vm86.h
+1
-9
ipc/msg.c
ipc/msg.c
+4
-4
ipc/sem.c
ipc/sem.c
+1
-1
ipc/shm.c
ipc/shm.c
+7
-7
kernel/sched.c
kernel/sched.c
+6
-5
kernel/sys.c
kernel/sys.c
+17
-0
kernel/vm86.c
kernel/vm86.c
+22
-12
mm/memory.c
mm/memory.c
+4
-23
mm/swap.c
mm/swap.c
+31
-11
net/inet/icmp.c
net/inet/icmp.c
+1
-0
net/inet/skbuff.c
net/inet/skbuff.c
+6
-3
No files found.
Makefile
View file @
e695b6a4
VERSION
=
1
PATCHLEVEL
=
1
SUBLEVEL
=
9
SUBLEVEL
=
10
all
:
Version zImage
...
...
drivers/net/3c509.c
View file @
e695b6a4
...
...
@@ -91,17 +91,20 @@ int el3_probe(struct device *dev)
/* First check for a board on the EISA bus. */
if
(
EISA_bus
)
{
for
(
ioaddr
=
0x1000
;
ioaddr
<
0x9000
;
ioaddr
+=
0x1000
)
{
if
(
inw
(
ioaddr
)
!=
0x6d50
)
/* Check the standard EISA ID register for an encoded '3Com'. */
if
(
inw
(
ioaddr
+
0xC80
)
!=
0x6d50
)
continue
;
/* Change the register set to the configuration window 0. */
outw
(
0x0800
,
ioaddr
+
0xC80
+
EL3_CMD
);
irq
=
inw
(
ioaddr
+
8
)
>>
12
;
if_port
=
inw
(
ioaddr
+
6
)
>>
14
;
for
(
i
=
0
;
i
<
3
;
i
++
)
phys_addr
[
i
]
=
htons
(
read_eeprom
(
ioaddr
,
i
));
/* Restore the "Manufacturer ID" to the EEPROM read register. */
/* The manual says to restore "Product ID" (reg. 3). !???! */
read_eeprom
(
ioaddr
,
7
);
/* Restore the "Product ID" to the EEPROM read register. */
read_eeprom
(
ioaddr
,
3
);
/* Was the EISA code an add-on hack? Nahhhhh... */
goto
found
;
...
...
drivers/sound/.blurb
View file @
e695b6a4
...
...
@@ -4,9 +4,3 @@ NOTE! This driver version is not compatible with the version 1.0c.
other
programs
using
ioctl
calls
of
the
driver
,
they
must
be
recompiled
.
Most
of
them
will
not
work
without
some
source
modifications
.
********
LINUX
VERSION
0.99.14
OR
LATER
IS
REQUIRED
*******
See
sound
/
Readme
for
more
details
Hannu
drivers/sound/CHANGELOG
View file @
e695b6a4
Changelog for version 2.4
-------------------------
Changelog for version 2.5a
--------------------------
Since 2.5
- Minor fix to read from /dev/sequencer
Since 2.5-beta2
- Some fine tuning to the GUS v3.7 mixer code.
- Fixed speed limits for the plain SB (1.0 to 2.0).
Since 2.5-beta
- Fixed OPL-3 detection with SB. Caused problems with PAS16.
- GUS v3.7 mixer support.
Since 2.4
- Mixer support for Sound Galaxy NX Pro (define __SGNXPRO__ on your local.h).
- Fixed truncated sound on /dev/dsp when the device is closed.
- Linear volume mode for GUS
- Pitch bends larger than +/- 2 octaves.
- MIDI recording for SB and SB Pro. (Untested).
- Some other fixes.
- SB16 MIDI and DSP drivers only initialized if SB16 actually installed.
- Implemented better detection for OPL-3. This should be usefull if you
have an old SB Pro (the non-OPL-3 one) or a SB 2.0 clone which has a OPL-3.
- SVR4.2 support by Ian Hartas. Initial ALPHA TEST version (untested).
Since 2.3b
- Fixed bug which made it impossible to make long recordings to disk.
...
...
drivers/sound/Makefile
View file @
e695b6a4
...
...
@@ -5,7 +5,7 @@
#
#
VERSION
=
2.
4
VERSION
=
2.
5a
TARGET_OS
=
linux
.c.s
:
...
...
@@ -19,7 +19,7 @@ OBJS = soundcard.o audio.o dmabuf.o sb_dsp.o dev_table.o \
opl3.o sequencer.o midibuf.o sb_card.o pas2_card.o adlib_card.o
\
pas2_pcm.o pas2_mixer.o pas2_midi.o gus_card.o gus_wave.o mpu401.o
\
gus_midi.o gus_vol.o patmgr.o sb_mixer.o sb16_dsp.o sb_midi.o
\
sb16_midi.o sound_switch.o
sb16_midi.o sound_switch.o
ics2101.o
all
:
local.h sound.a
...
...
drivers/sound/Readme
View file @
e695b6a4
Release notes for the Linux Sound Driver 2.4
--------------------------------------------
Release notes for the Linux Sound Driver 2.5a
---------------------------------------------
This directory contains just the Linux version. The portable version
(SCO/ISC, FreeBSD/NetBSD and SVR4.2) is available from sunsite.unc.edu:
pub/Linux/kernel/sound.
This is mainly a bug fix release. There are couple of new things such as
linear volume mode for GUS and MIDI recording for SB 2.0 and SB Pro.
Also this version supports the mixer of GUS v3.7. (Support for GUS MAX and
the 16-bit daughtercard is coming sooner or later).
NOTE! The sound driver is a part of the Linux kernel distribution also.
Check that your kernel doesn't have more recent version than this
...
...
@@ -17,17 +25,13 @@ time with the /dev/dsp. Also the WaveBlaster daughter board is supported.
No support for the ASP chip yet (the ASP chip can be installed but it's
not used by the driver).
You will need the snd-util-2.
4
.tar.gz and snd-data-0.1.tar.Z
You will need the snd-util-2.
5
.tar.gz and snd-data-0.1.tar.Z
packages to use this driver. They should be in the same
ftp site or BBS from where you got this driver. For
example at nic.funet.fi:pub/OS/Linux/*.
There is a new version of the tracker program available (tracker-3_19.lzh) but
I don't know where it is available. The tracker 3.10 has bugs and it don't work
without some fixes. Look at the README of the snd-util-2.3.
If you are looking for the installation instructions, please
look at
linux
/Readme.
look at
$OS
/Readme.
This version supports the following soundcards:
GUS, SoundBlaster, SB Pro, SB16, Pro Audio Spectrum 16 and AdLib.
...
...
@@ -36,19 +40,6 @@ In addition there is rather limited support for MPU-401.
Most of the features of the /dev/sequencer device file are
available just for GUS owners.
NOTE! There are separate driver for CD-ROMS supported by
some soundcards. The driver for CDU31A (Fusion 16) is
called cdu31a-0.6.diff.z. It will be contained in the
Linux version 0.99.12. The driver for the CD-ROM of SB Pro
is sbpcd0.4.tar.gz (these were the latest versions when I wrote
this). These files should be at least at sunsite.unc.edu.
Also the SCSI interface of the PAS16 should be supported by
Linux 0.99.13k and later.
There is also a driver for joystick. Look for file joystick-0.5.tar.gz
(sunsite).
Compatibility with the earlier versions
---------------------------------------
...
...
@@ -104,58 +95,6 @@ at the same time, the ioctl(SNDCTL_FM_LOAD_INSTR) is obsolete. In addition
there is some new fields which must be initialized. Look at the sbiset.c in
the snd-util-2.0 package for further info.
This version is almost 100% compatible with the alpha test version (1.99.9). The
difference is in the installation procedure.
Using this driver with other operating systems than Linux
---------------------------------------------------------
This package contains just the Linux version. The version 2.3
for SCO is available at nic.funet.fi:pub/OS/Linux/ALPHA/sound.
The version 2.3 doesn't work well with xxxxxBSD. Use the version
2.3 for them.
/dev/sndstat
------------
The /dev/sndstat is now available in the SCO and BSD versions also.
This is a new devicefile for debugging purposes. A better place for
it is in the /proc -directory but I was just too lazy to implement it
properly. The /dev/sndstat (major 14, minor 6) is a file which returns
info about the current configuration (see the example below). If you
send me a error/problem report, please include a printout from this
device to your message (cat /dev/sndstat).
Note! This device file is currently present only in the Linux version
of this driver.
------ cut here --- cat /dev/sndstat example --------
Sound Driver:1.99.7 (Fri Jul 9 17:01:47 GMT 1993 root@lucifer.savolai.fi)
Config options: 0x00000d4b
HW config:
Type 4: Gravis Ultrasound at 0x210 irq 15 drq 6
Type 3: ProAudioSpectrum at 0x388 irq 10 drq 3
Type 2: SoundBlaster at 0x220 irq 7 drq 1
Type 1: AdLib at 0x388 irq 0 drq 0
PCM devices:
00: Gravis UltraSound
01: Pro Audio Spectrum
02: SoundBlaster 2.0
Synth devices:
00: Gravis UltraSound
01: Yamaha OPL-3
Midi devices:
00: Gravis UltraSound
01: Pro Audio Spectrum
Mixer(s) installed
------ cut here ---- End of Example -----------
Known bugs/limitations
----------------------
...
...
@@ -164,7 +103,6 @@ Known bugs/limitations
recording process too much. A delay longer than 0.1 to 0.3 seconds is
too much.
- The SB16 driver sometimes swaps the left and right channels together.
- Midi input doesn't work with SB and SB Pro (SB16 works).
- It's not possible to open /dev/dsp (or /dev/audio) while the
/dev/sequencer is open for output and GUS is the only soundcard
installed. It's possible if /dev/dsp is opened before /dev/sequencer
...
...
@@ -173,9 +111,6 @@ Known bugs/limitations
- MPU-401 driver hangs the computer on boot if there is no MPU-401 installed.
It uses by default the I/O port 0x330 whic is used by Adaptec 1542 SCSI
adapter.
- There are some problems in midi input with MPU-401 and the SB16 midi
(MPU-401 emulation). This makes it impossible to read long sysex dumps
using these devices.
- The /dev/sequencer playback to GUS sounds sometimes rather weird. Hitting
^C and playing again should solve this problem. This is propably caused by
incompatibilities between GUS and certain VLB motherboards (like mine).
...
...
@@ -220,21 +155,28 @@ This driver contains code by several contributors. In addition several other
persons have given usefull suggestions. The following is a list of major
contributors. (I could have forgotten some names.)
Craig Metz 1/2 of the PAS16 Mixer and PCM support
Rob Hooft Volume computation algorithm for the FM synth.
Mika Liljeberg uLaw encoding and decoding routines
Greg Lee Volume computation algorithm for the GUS and
lot's of valuable suggestions.
Andy Warner ISC port
Jim Lowe FreeBSD port
Craig Metz
1/2 of the PAS16 Mixer and PCM support
Rob Hooft
Volume computation algorithm for the FM synth.
Mika Liljeberg
uLaw encoding and decoding routines
Greg Lee
Volume computation algorithm for the GUS and
lot's of valuable suggestions.
Andy Warner
Initial
ISC port
Jim Lowe
Initial
FreeBSD port
Anders Baekgaard Bughunting and valuable suggestions.
Joerg Schubert SB16 DSP support.
Andrew Robinson Improvements to the GUS driver
Joerg Schubert SB16 DSP support.
Andrew Robinson Improvements to the GUS driver
Megens SA MIDI recording for SB and SB Pro.
Mikael Nordqvist Linear volume support for GUS.
Ian Hartas SVR4.2 port
Markus Aroharju and
Risto Kankkunen Major contributions to the mixer support
of GUS v3.7.
Hunyue Yau Sound Galaxy NX Pro mixer support.
Regards,
Hannu Savolainen
h
savolai@cs.h
elsinki.fi
h
annu@voxware.pp.fi, Hannu.Savolainen@H
elsinki.fi
Snail mail: Hannu Savolainen
Pallaksentie 4 A 2
...
...
drivers/sound/Readme.linux
View file @
e695b6a4
Sound Driver version 2.
4
for Linux
Sound Driver version 2.
5
for Linux
----------------------------------
NOTE! The sound driver is now a part of the Linux kernel distribution.
...
...
@@ -174,7 +174,8 @@ If you want to play modules on a 386sx while recompiling the world, buy a GUS.
It runs without burning your CPU.
Hannu Savolainen
hsavolai@cs.helsinki.fi
Hannu.Savolainen@Helsinki.fi
(hannu@voxware.pp.fi (april 94 ->))
----------------- cut here ------------------------------
#!/bin/sh
...
...
drivers/sound/adlib_card.c
View file @
e695b6a4
/*
* sound/adlib_card.c
*
*
* Detection routine for the AdLib card.
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -12,7 +12,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -24,7 +24,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#include "sound_config.h"
...
...
drivers/sound/audio.c
View file @
e695b6a4
/*
* sound/audio.c
*
*
* Device file manager for /dev/audio
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -12,7 +12,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -24,7 +24,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#include "sound_config.h"
...
...
@@ -38,10 +38,12 @@
#define OFF 0
static
int
wr_buff_no
[
MAX_DSP_DEV
];
/* != -1, if there is a
* incomplete output block */
static
int
wr_buff_size
[
MAX_DSP_DEV
],
wr_buff_ptr
[
MAX_DSP_DEV
];
static
int
audio_mode
[
MAX_DSP_DEV
];
static
int
audio_mode
[
MAX_DSP_DEV
];
#define AM_NONE 0
#define AM_WRITE 1
#define AM_READ 2
...
...
@@ -52,16 +54,16 @@ int
audio_open
(
int
dev
,
struct
fileinfo
*
file
)
{
int
ret
;
int
bits
;
int
dev_type
=
dev
&
0x0f
;
int
mode
=
file
->
mode
&
O_ACCMODE
;
int
bits
;
int
dev_type
=
dev
&
0x0f
;
int
mode
=
file
->
mode
&
O_ACCMODE
;
dev
=
dev
>>
4
;
if
(
dev_type
==
SND_DEV_DSP16
)
bits
=
16
;
bits
=
16
;
else
bits
=
8
;
bits
=
8
;
if
((
ret
=
DMAbuf_open
(
dev
,
mode
))
<
0
)
return
ret
;
...
...
@@ -126,7 +128,7 @@ audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
{
int
c
,
p
,
l
;
int
err
;
int
dev_type
=
dev
&
0x0f
;
int
dev_type
=
dev
&
0x0f
;
dev
=
dev
>>
4
;
...
...
@@ -134,9 +136,9 @@ audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
c
=
count
;
if
(
audio_mode
[
dev
]
==
AM_READ
)
/* Direction changed */
{
{
wr_buff_no
[
dev
]
=
-
1
;
}
}
audio_mode
[
dev
]
=
AM_WRITE
;
...
...
@@ -170,19 +172,19 @@ audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
}
else
dsp_devs
[
dev
]
->
copy_from_user
(
dev
,
wr_dma_buf
[
dev
],
wr_buff_ptr
[
dev
],
buf
,
p
,
l
);
wr_dma_buf
[
dev
],
wr_buff_ptr
[
dev
],
buf
,
p
,
l
);
/* Insert local processing here */
if
(
dev_type
==
SND_DEV_AUDIO
)
{
{
#ifdef linux
/* This just allows interrupts while the conversion is running */
__asm__
(
"sti"
);
/* This just allows interrupts while the conversion is running */
__asm__
(
"sti"
);
#endif
translate_bytes
(
ulaw_dsp
,
&
wr_dma_buf
[
dev
][
wr_buff_ptr
[
dev
]],
l
);
}
translate_bytes
(
ulaw_dsp
,
(
unsigned
char
*
)
&
wr_dma_buf
[
dev
][
wr_buff_ptr
[
dev
]],
l
);
}
c
-=
l
;
p
+=
l
;
...
...
@@ -207,21 +209,21 @@ audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
int
c
,
p
,
l
;
char
*
dmabuf
;
int
buff_no
;
int
dev_type
=
dev
&
0x0f
;
int
dev_type
=
dev
&
0x0f
;
dev
=
dev
>>
4
;
p
=
0
;
c
=
count
;
if
(
audio_mode
[
dev
]
==
AM_WRITE
)
{
{
if
(
wr_buff_no
[
dev
]
>=
0
)
{
DMAbuf_start_output
(
dev
,
wr_buff_no
[
dev
],
wr_buff_ptr
[
dev
]);
wr_buff_no
[
dev
]
=
-
1
;
}
}
}
audio_mode
[
dev
]
=
AM_READ
;
...
...
@@ -236,14 +238,14 @@ audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
/* Insert any local processing here. */
if
(
dev_type
==
SND_DEV_AUDIO
)
{
{
#ifdef linux
/* This just allows interrupts while the conversion is running */
__asm__
(
"sti"
);
/* This just allows interrupts while the conversion is running */
__asm__
(
"sti"
);
#endif
translate_bytes
(
dsp_ulaw
,
dmabuf
,
l
);
}
translate_bytes
(
dsp_ulaw
,
(
unsigned
char
*
)
dmabuf
,
l
);
}
COPY_TO_USER
(
buf
,
p
,
dmabuf
,
l
);
...
...
@@ -260,7 +262,8 @@ int
audio_ioctl
(
int
dev
,
struct
fileinfo
*
file
,
unsigned
int
cmd
,
unsigned
int
arg
)
{
int
dev_type
=
dev
&
0x0f
;
int
dev_type
=
dev
&
0x0f
;
dev
=
dev
>>
4
;
switch
(
cmd
)
...
...
@@ -292,7 +295,7 @@ audio_ioctl (int dev, struct fileinfo *file,
default:
if
(
dev_type
==
SND_DEV_AUDIO
)
return
RET_ERROR
(
EIO
);
return
RET_ERROR
(
EIO
);
return
DMAbuf_ioctl
(
dev
,
cmd
,
arg
,
0
);
}
...
...
@@ -321,14 +324,14 @@ audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
int
audio_open
(
int
dev
,
struct
fileinfo
*
file
)
{
return
RET_ERROR
(
ENXIO
);
}
{
return
RET_ERROR
(
ENXIO
);
}
void
audio_release
(
int
dev
,
struct
fileinfo
*
file
)
{
};
{
};
int
audio_ioctl
(
int
dev
,
struct
fileinfo
*
file
,
unsigned
int
cmd
,
unsigned
int
arg
)
...
...
drivers/sound/configure.c
View file @
e695b6a4
/*
* sound/configure.c
- Configuration program for the Linux Sound Driver
*
* sound/configure.c
- Configuration program for the Linux Sound Driver
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -10,7 +10,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -22,7 +22,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#include <stdio.h>
...
...
@@ -48,12 +48,12 @@
#define OPT_MIDI_AUTO 8
#define OPT_MIDI 9
#define OPT_YM3812_AUTO 10
/* Select this automaticly if user selects
* MIDI or AdLib driver */
* MIDI or AdLib driver */
#define OPT_YM3812 11
/* Select this if the previous one was not
* selected */
* selected */
#define OPT_SEQUENCER 12
#define OPT_CHIP_MIDI 13
/* New support added at UW - Milwauklee UW -
* Milwauklee */
* Milwauklee */
#define OPT_LAST 12
#define ANY_DEVS (B(OPT_AUDIO)|B(OPT_MIDI)|B(OPT_SEQUENCER)|B(OPT_GUS)|B(OPT_MPU401))
...
...
@@ -65,7 +65,7 @@ typedef struct
char
macro
[
20
];
int
verify
;
int
alias
;
int
default_answ
;
int
default_answ
;
}
hw_entry
;
...
...
@@ -77,11 +77,11 @@ hw_entry;
* second field is a set of options which are not allowed with this one. If
* the fourth field is zero, the option is selected without asking
* confirmation from the user.
*
*
* With this version of the rule table it is possible to select just one type of
* hardware.
*
* NOTE!
Keep the following table and the questions array in sync with the
*
* NOTE!
Keep the following table and the questions array in sync with the
* option numbering!
*/
...
...
@@ -127,7 +127,7 @@ char *questions[] =
};
unsigned
long
selected_options
=
0
;
int
sb_dma
=
0
;
int
sb_dma
=
0
;
int
can_select_option
(
int
nr
)
...
...
@@ -272,11 +272,11 @@ main (int argc, char *argv[])
}
else
{
int
def_answ
=
hw_table
[
i
].
default_answ
;
int
def_answ
=
hw_table
[
i
].
default_answ
;
fprintf
(
stderr
,
def_answ
?
" %s (y/n) ? "
:
" %s (n/y) ? "
,
questions
[
i
]);
fprintf
(
stderr
,
def_answ
?
" %s (y/n) ? "
:
" %s (n/y) ? "
,
questions
[
i
]);
if
(
think_positively
(
def_answ
))
if
(
hw_table
[
i
].
alias
)
selected_options
|=
B
(
hw_table
[
i
].
alias
);
...
...
@@ -286,8 +286,8 @@ main (int argc, char *argv[])
}
}
if
(
selected_options
&
B
(
OPT_SB16
))
selected_options
|=
B
(
OPT_SBPRO
);
if
(
selected_options
&
B
(
OPT_SB16
))
selected_options
|=
B
(
OPT_SBPRO
);
if
(
!
(
selected_options
&
ANY_DEVS
))
{
...
...
@@ -319,8 +319,9 @@ main (int argc, char *argv[])
if
(
selected_options
&
B
(
OPT_SB
)
&&
selected_options
&
(
B
(
OPT_AUDIO
)
|
B
(
OPT_MIDI
)))
{
fprintf
(
stderr
,
"
\n
IRQ number for SoundBlaster?
\n
"
"The IRQ adress is defined by the jumpers on your card and
\n
"
"7 is the factory default. Valid values are 9, 5, 7 and 10.
\n
"
"The IRQ address is defined by the jumpers on your card.
\n
"
"The factory default is either 5 or 7 (depending on the model).
\n
"
"Valid values are 9, 5, 7 and 10.
\n
"
"Enter the value: "
);
num
=
ask_value
(
"%d"
,
7
);
...
...
@@ -331,9 +332,10 @@ main (int argc, char *argv[])
num
=
7
;
}
fprintf
(
stderr
,
"SoundBlaster IRQ set to %d
\n
"
,
num
);
printf
(
"#define SBC_BASE 0x220
\n
"
);
printf
(
"#define SBC_IRQ %d
\n
"
,
num
);
if
(
selected_options
&
B
(
OPT_SBPRO
))
if
(
selected_options
&
(
B
(
OPT_SBPRO
)
|
B
(
OPT_PAS
)
))
{
fprintf
(
stderr
,
"
\n
DMA channel for SoundBlaster?
\n
"
...
...
@@ -359,7 +361,7 @@ main (int argc, char *argv[])
{
fprintf
(
stderr
,
"
\n
16 bit DMA channel for SoundBlaster 16?
\n
"
"Possible values are 5, 6 or 7
\n
"
"Possible values are 5, 6 or 7
\n
"
"The default value is 6
\n
"
"Enter the value: "
);
...
...
@@ -373,14 +375,14 @@ main (int argc, char *argv[])
fprintf
(
stderr
,
"SoundBlaster DMA set to %d
\n
"
,
num
);
printf
(
"#define SB16_DMA %d
\n
"
,
num
);
fprintf
(
stderr
,
"
\n
I/O base for SB16 Midi?
\n
"
"Possible values are 300 and 330
\n
"
"The factory default is 330
\n
"
"Enter the SB16 Midi I/O base: "
);
fprintf
(
stderr
,
"
\n
I/O base for SB16 Midi?
\n
"
"Possible values are 300 and 330
\n
"
"The factory default is 330
\n
"
"Enter the SB16 Midi I/O base: "
);
num
=
ask_value
(
"%x"
,
0x330
);
fprintf
(
stderr
,
"SB16 Midi I/O base set to %03x
\n
"
,
num
);
printf
(
"#define SB16MIDI_BASE 0x%03x
\n
"
,
num
);
num
=
ask_value
(
"%x"
,
0x330
);
fprintf
(
stderr
,
"SB16 Midi I/O base set to %03x
\n
"
,
num
);
printf
(
"#define SB16MIDI_BASE 0x%03x
\n
"
,
num
);
}
}
...
...
@@ -428,7 +430,7 @@ main (int argc, char *argv[])
if
(
selected_options
&
B
(
OPT_GUS
))
{
fprintf
(
stderr
,
"
\n
I/O base for Gravis Ultrasound?
\n
"
"Valid choi
s
es are 210, 220, 230, 240, 250 or 260
\n
"
"Valid choi
c
es are 210, 220, 230, 240, 250 or 260
\n
"
"The factory default is 220
\n
"
"Enter the GUS I/O base: "
);
...
...
@@ -515,12 +517,12 @@ main (int argc, char *argv[])
{
def_size
=
16384
;
if
(
selected_options
&
(
B
(
OPT_SBPRO
)
|
B
(
OPT_PAS
)
|
B
(
OPT_SB16
)))
if
(
selected_options
&
(
B
(
OPT_SBPRO
)
|
B
(
OPT_PAS
)
|
B
(
OPT_SB16
)))
def_size
=
32768
;
#ifndef __386BSD__
if
(((
selected_options
&
B
(
OPT_PAS
))
||
(
selected_options
&
B
(
OPT_SB16
)))
&&
!
full_driver
)
if
(((
selected_options
&
B
(
OPT_PAS
))
||
(
selected_options
&
B
(
OPT_SB16
)))
&&
!
full_driver
)
def_size
=
65536
;
/* PAS16 or SB16 */
#endif
...
...
@@ -543,7 +545,7 @@ main (int argc, char *argv[])
fprintf
(
stderr
,
"The sound driver is now configured.
\n
"
);
#if defined(SCO) || defined(ISC) || defined(SYSV)
fprintf
(
stderr
,
"R
ember to update the System file
\n
"
);
fprintf
(
stderr
,
"Rem
ember to update the System file
\n
"
);
#endif
exit
(
0
);
...
...
drivers/sound/dev_table.c
View file @
e695b6a4
/*
* sound/dev_table.c
*
*
* Device call tables.
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -12,7 +12,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -24,7 +24,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#define _DEV_TABLE_C_
...
...
@@ -39,23 +39,23 @@ sndtable_init (long mem_start)
for
(
i
=
0
;
i
<
(
n
-
1
);
i
++
)
if
(
supported_drivers
[
i
].
enabled
)
if
(
supported_drivers
[
i
].
probe
(
&
supported_drivers
[
i
].
config
))
{
if
(
supported_drivers
[
i
].
probe
(
&
supported_drivers
[
i
].
config
))
{
#ifndef SHORT_BANNERS
printk
(
"snd%d"
,
supported_drivers
[
i
].
card_type
);
printk
(
"snd%d"
,
supported_drivers
[
i
].
card_type
);
#endif
mem_start
=
supported_drivers
[
i
].
attach
(
mem_start
,
&
supported_drivers
[
i
].
config
);
mem_start
=
supported_drivers
[
i
].
attach
(
mem_start
,
&
supported_drivers
[
i
].
config
);
#ifndef SHORT_BANNERS
printk
(
" at 0x%x irq %d drq %d
\n
"
,
supported_drivers
[
i
].
config
.
io_base
,
supported_drivers
[
i
].
config
.
irq
,
supported_drivers
[
i
].
config
.
dma
);
printk
(
" at 0x%x irq %d drq %d
\n
"
,
supported_drivers
[
i
].
config
.
io_base
,
supported_drivers
[
i
].
config
.
irq
,
supported_drivers
[
i
].
config
.
dma
);
#endif
}
else
supported_drivers
[
i
].
enabled
=
0
;
/* Mark as not detected */
}
else
supported_drivers
[
i
].
enabled
=
0
;
/* Mark as not detected */
return
mem_start
;
}
...
...
@@ -69,14 +69,15 @@ sndtable_probe (int unit, struct address_info *hw_config)
for
(
i
=
0
;
i
<
(
n
-
1
);
i
++
)
if
(
supported_drivers
[
i
].
card_type
==
unit
)
{
{
supported_drivers
[
i
].
config
.
io_base
=
hw_config
->
io_base
;
supported_drivers
[
i
].
config
.
irq
=
hw_config
->
irq
;
supported_drivers
[
i
].
config
.
dma
=
hw_config
->
dma
;
if
(
supported_drivers
[
i
].
probe
(
hw_config
))
return
1
;
supported_drivers
[
i
].
enabled
=
0
;
/* Mark as not detected */
return
0
;
}
if
(
supported_drivers
[
i
].
probe
(
hw_config
))
return
1
;
supported_drivers
[
i
].
enabled
=
0
;
/* Mark as not detected */
return
0
;
}
return
FALSE
;
}
...
...
@@ -115,91 +116,102 @@ sndtable_get_cardcount (void)
}
#ifdef linux
void
sound_setup
(
char
*
str
,
int
*
ints
)
void
sound_setup
(
char
*
str
,
int
*
ints
)
{
int
i
,
n
=
sizeof
(
supported_drivers
)
/
sizeof
(
struct
card_info
);
/*
/*
* First disable all drivers
*/
for
(
i
=
0
;
i
<
n
;
i
++
)
supported_drivers
[
i
].
enabled
=
0
;
for
(
i
=
0
;
i
<
n
;
i
++
)
supported_drivers
[
i
].
enabled
=
0
;
if
(
ints
[
0
]
==
0
||
ints
[
1
]
==
0
)
return
;
/*
if
(
ints
[
0
]
==
0
||
ints
[
1
]
==
0
)
return
;
/*
* Then enable them one by time
*/
for
(
i
=
1
;
i
<=
ints
[
0
];
i
++
)
{
int
card_type
,
ioaddr
,
irq
,
dma
,
ptr
,
j
;
unsigned
int
val
;
val
=
(
unsigned
int
)
ints
[
i
];
card_type
=
(
val
&
0x0ff00000
)
>>
20
;
if
(
card_type
>
127
)
{
/* Add any future extensions here
*/
return
;
}
ioaddr
=
(
val
&
0x000fff00
)
>>
8
;
irq
=
(
val
&
0x000000f0
)
>>
4
;
dma
=
(
val
&
0x0000000f
);
ptr
=
-
1
;
for
(
j
=
0
;
j
<
n
&&
ptr
==
-
1
;
j
++
)
if
(
supported_drivers
[
j
].
card_type
==
card_type
)
ptr
=
j
;
if
(
ptr
==
-
1
)
printk
(
"Sound: Invalid setup parameter 0x%08x
\n
"
,
val
);
else
{
supported_drivers
[
ptr
].
enabled
=
1
;
supported_drivers
[
ptr
].
config
.
io_base
=
ioaddr
;
supported_drivers
[
ptr
].
config
.
irq
=
irq
;
supported_drivers
[
ptr
].
config
.
dma
=
dma
;
}
}
for
(
i
=
1
;
i
<=
ints
[
0
];
i
++
)
{
int
card_type
,
ioaddr
,
irq
,
dma
,
ptr
,
j
;
unsigned
int
val
;
val
=
(
unsigned
int
)
ints
[
i
];
card_type
=
(
val
&
0x0ff00000
)
>>
20
;
if
(
card_type
>
127
)
{
/* Add any future extensions here
*/
return
;
}
ioaddr
=
(
val
&
0x000fff00
)
>>
8
;
irq
=
(
val
&
0x000000f0
)
>>
4
;
dma
=
(
val
&
0x0000000f
);
ptr
=
-
1
;
for
(
j
=
0
;
j
<
n
&&
ptr
==
-
1
;
j
++
)
if
(
supported_drivers
[
j
].
card_type
==
card_type
)
ptr
=
j
;
if
(
ptr
==
-
1
)
printk
(
"Sound: Invalid setup parameter 0x%08x
\n
"
,
val
);
else
{
supported_drivers
[
ptr
].
enabled
=
1
;
supported_drivers
[
ptr
].
config
.
io_base
=
ioaddr
;
supported_drivers
[
ptr
].
config
.
irq
=
irq
;
supported_drivers
[
ptr
].
config
.
dma
=
dma
;
}
}
}
#else
void
sound_chconf
(
int
card_type
,
int
ioaddr
,
int
irq
,
int
dma
)
void
sound_chconf
(
int
card_type
,
int
ioaddr
,
int
irq
,
int
dma
)
{
int
i
,
n
=
sizeof
(
supported_drivers
)
/
sizeof
(
struct
card_info
);
int
ptr
,
j
;
int
ptr
,
j
;
ptr
=
-
1
;
for
(
j
=
0
;
j
<
n
&&
ptr
==
-
1
;
j
++
)
if
(
supported_drivers
[
j
].
card_type
==
card_type
)
ptr
=
j
;
ptr
=
-
1
;
for
(
j
=
0
;
j
<
n
&&
ptr
==
-
1
;
j
++
)
if
(
supported_drivers
[
j
].
card_type
==
card_type
)
ptr
=
j
;
if
(
ptr
!=
-
1
)
{
supported_drivers
[
ptr
].
enabled
=
1
;
if
(
ioaddr
)
supported_drivers
[
ptr
].
config
.
io_base
=
ioaddr
;
if
(
irq
)
supported_drivers
[
ptr
].
config
.
irq
=
irq
;
if
(
dma
)
supported_drivers
[
ptr
].
config
.
dma
=
dma
;
}
if
(
ptr
!=
-
1
)
{
supported_drivers
[
ptr
].
enabled
=
1
;
if
(
ioaddr
)
supported_drivers
[
ptr
].
config
.
io_base
=
ioaddr
;
if
(
irq
)
supported_drivers
[
ptr
].
config
.
irq
=
irq
;
if
(
dma
)
supported_drivers
[
ptr
].
config
.
dma
=
dma
;
}
}
#endif
struct
address_info
*
sound_getconf
(
int
card_type
)
struct
address_info
*
sound_getconf
(
int
card_type
)
{
int
j
,
ptr
;
int
n
=
sizeof
(
supported_drivers
)
/
sizeof
(
struct
card_info
);
int
j
,
ptr
;
int
n
=
sizeof
(
supported_drivers
)
/
sizeof
(
struct
card_info
);
ptr
=
-
1
;
for
(
j
=
0
;
j
<
n
&&
ptr
==
-
1
;
j
++
)
if
(
supported_drivers
[
j
].
card_type
==
card_type
)
ptr
=
j
;
ptr
=
-
1
;
for
(
j
=
0
;
j
<
n
&&
ptr
==
-
1
;
j
++
)
if
(
supported_drivers
[
j
].
card_type
==
card_type
)
ptr
=
j
;
if
(
ptr
==
-
1
)
return
(
struct
address_info
*
)
NULL
;
if
(
ptr
==
-
1
)
return
(
struct
address_info
*
)
NULL
;
return
&
supported_drivers
[
ptr
].
config
;
return
&
supported_drivers
[
ptr
].
config
;
}
#endif
drivers/sound/dev_table.h
View file @
e695b6a4
...
...
@@ -58,6 +58,9 @@ struct generic_midi_info{
struct
audio_operations
{
char
name
[
32
];
int
flags
;
#define NOTHING_SPECIAL 0
#define NEEDS_RESTART 1
int
(
*
open
)
(
int
dev
,
int
mode
);
void
(
*
close
)
(
int
dev
);
void
(
*
output_block
)
(
int
dev
,
unsigned
long
buf
,
...
...
@@ -96,6 +99,7 @@ struct synth_operations {
void
(
*
aftertouch
)
(
int
dev
,
int
voice
,
int
pressure
);
void
(
*
controller
)
(
int
dev
,
int
voice
,
int
ctrl_num
,
int
value
);
void
(
*
panning
)
(
int
dev
,
int
voice
,
int
value
);
void
(
*
volume_method
)
(
int
dev
,
int
mode
);
int
(
*
pmgr_interface
)
(
int
dev
,
struct
patmgr_info
*
info
);
};
...
...
@@ -177,7 +181,7 @@ struct generic_midi_operations {
{
SBC_BASE
,
SBC_IRQ
,
SBC_DMA
},
SND_DEFAULT_ENABLE
},
#endif
#if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16)
#if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16)
&& !defined(EXCLUDE_SBPRO)
#ifndef EXCLUDE_AUDIO
{
SNDCARD_SB16
,
"SoundBlaster16"
,
sb16_dsp_init
,
sb16_dsp_detect
,
{
SBC_BASE
,
SBC_IRQ
,
SB16_DMA
},
SND_DEFAULT_ENABLE
},
...
...
drivers/sound/dmabuf.c
View file @
e695b6a4
/*
* sound/dmabuf.c
*
*
* The DMA buffer manager for digitized voice applications
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -12,7 +12,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -24,7 +24,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#include "sound_config.h"
...
...
@@ -88,12 +88,14 @@ static int bufferalloc_done[MAX_DSP_DEV] =
*/
static
int
dev_nbufs
[
MAX_DSP_DEV
];
/* # of logical buffers ( >=
* sound_buffcounts[dev] */
* sound_buffcounts[dev] */
static
int
dev_counts
[
MAX_DSP_DEV
][
MAX_SUB_BUFFERS
];
static
int
dev_subdivision
[
MAX_DSP_DEV
];
static
unsigned
long
dev_buf_phys
[
MAX_DSP_DEV
][
MAX_SUB_BUFFERS
];
static
char
*
dev_buf
[
MAX_DSP_DEV
][
MAX_SUB_BUFFERS
]
=
{{
NULL
}};
{
{
NULL
}};
static
int
dev_buffsize
[
MAX_DSP_DEV
];
static
void
...
...
@@ -103,8 +105,8 @@ reorganize_buffers (int dev)
* This routine breaks the physical device buffers to logical ones.
*/
unsigned
i
,
p
,
n
;
unsigned
sr
,
nc
,
sz
,
bsz
;
unsigned
i
,
p
,
n
;
unsigned
sr
,
nc
,
sz
,
bsz
;
sr
=
dsp_devs
[
dev
]
->
ioctl
(
dev
,
SOUND_PCM_READ_RATE
,
0
,
1
);
nc
=
dsp_devs
[
dev
]
->
ioctl
(
dev
,
SOUND_PCM_READ_CHANNELS
,
0
,
1
);
...
...
@@ -135,14 +137,15 @@ reorganize_buffers (int dev)
bsz
>>=
1
;
/* Need at least 2 buffers */
if
(
dev_subdivision
[
dev
]
==
0
)
dev_subdivision
[
dev
]
=
1
;
/* Default value */
dev_subdivision
[
dev
]
=
1
;
/* Default value */
bsz
/=
dev_subdivision
[
dev
];
/* Use smaller buffers */
if
(
bsz
==
0
)
bsz
=
4096
;
/* Just a sanity check */
if
(
bsz
==
0
)
bsz
=
4096
;
/* Just a sanity check */
while
((
sound_buffsizes
[
dev
]
*
sound_buffcounts
[
dev
])
/
bsz
>
MAX_SUB_BUFFERS
)
bsz
<<=
1
;
/* Too much buffers */
while
((
sound_buffsizes
[
dev
]
*
sound_buffcounts
[
dev
])
/
bsz
>
MAX_SUB_BUFFERS
)
bsz
<<=
1
;
/* Too much buffers */
dev_buffsize
[
dev
]
=
bsz
;
n
=
0
;
...
...
@@ -175,7 +178,7 @@ reorganize_buffers (int dev)
}
static
void
dma_init_buffers
(
int
dev
)
dma_init_buffers
(
int
dev
)
{
RESET_WAIT_QUEUE
(
dev_sleeper
[
dev
],
dev_sleep_flag
[
dev
]);
dev_underrun
[
dev
]
=
0
;
...
...
@@ -210,7 +213,7 @@ DMAbuf_open (int dev, int mode)
}
#ifdef USE_RUNTIME_DMAMEM
sound_dma_malloc
(
dev
);
sound_dma_malloc
(
dev
);
#endif
if
(
snd_raw_buf
[
dev
][
0
]
==
NULL
)
...
...
@@ -222,7 +225,7 @@ DMAbuf_open (int dev, int mode)
dev_modes
[
dev
]
=
mode
;
dev_subdivision
[
dev
]
=
0
;
dma_init_buffers
(
dev
);
dma_init_buffers
(
dev
);
dsp_devs
[
dev
]
->
ioctl
(
dev
,
SOUND_PCM_WRITE_BITS
,
8
,
1
);
dsp_devs
[
dev
]
->
ioctl
(
dev
,
SOUND_PCM_WRITE_CHANNELS
,
1
,
1
);
dsp_devs
[
dev
]
->
ioctl
(
dev
,
SOUND_PCM_WRITE_RATE
,
DSP_DEFAULT_SPEED
,
1
);
...
...
@@ -233,42 +236,37 @@ DMAbuf_open (int dev, int mode)
static
void
dma_reset
(
int
dev
)
{
int
retval
;
unsigned
long
flags
;
int
retval
;
unsigned
long
flags
;
DISABLE_INTR
(
flags
);
DISABLE_INTR
(
flags
);
dsp_devs
[
dev
]
->
reset
(
dev
);
dsp_devs
[
dev
]
->
close
(
dev
);
if
((
retval
=
dsp_devs
[
dev
]
->
open
(
dev
,
dev_modes
[
dev
]))
<
0
)
printk
(
"Sound: Reset failed - Can't reopen device
\n
"
);
RESTORE_INTR
(
flags
);
printk
(
"Sound: Reset failed - Can't reopen device
\n
"
);
RESTORE_INTR
(
flags
);
dma_init_buffers
(
dev
);
reorganize_buffers
(
dev
);
dma_init_buffers
(
dev
);
reorganize_buffers
(
dev
);
}
static
int
dma_sync
(
int
dev
)
{
unsigned
long
flags
;
unsigned
long
time
;
int
timed_out
;
if
(
dma_mode
[
dev
]
==
DMODE_OUTPUT
)
{
DISABLE_INTR
(
flags
);
timed_out
=
0
;
time
=
GET_TIME
();
while
((
!
(
PROCESS_ABORTING
(
dev_sleeper
[
dev
],
dev_sleep_flag
[
dev
])
||
dmabuf_interrupted
[
dev
])
&&
!
timed_out
)
dmabuf_interrupted
[
dev
]))
&&
dev_qlen
[
dev
])
{
DO_SLEEP
(
dev_sleeper
[
dev
],
dev_sleep_flag
[
dev
],
10
*
HZ
);
if
(
(
GET_TIME
()
-
time
)
>
(
10
*
HZ
))
timed_out
=
1
;
if
(
TIMED_OUT
(
dev_sleeper
[
dev
],
dev_sleep_flag
[
dev
]
))
return
dev_qlen
[
dev
]
;
}
RESTORE_INTR
(
flags
);
...
...
@@ -304,7 +302,7 @@ DMAbuf_release (int dev, int mode)
}
#ifdef USE_RUNTIME_DMAMEM
sound_dma_free
(
dev
);
sound_dma_free
(
dev
);
#endif
dsp_devs
[
dev
]
->
reset
(
dev
);
...
...
@@ -321,45 +319,45 @@ int
DMAbuf_getrdbuffer
(
int
dev
,
char
**
buf
,
int
*
len
)
{
unsigned
long
flags
;
int
err
=
EIO
;
int
err
=
EIO
;
DISABLE_INTR
(
flags
);
if
(
!
dev_qlen
[
dev
])
{
if
(
dev_needs_restart
[
dev
])
{
dma_reset
(
dev
);
dev_needs_restart
[
dev
]
=
0
;
}
{
dma_reset
(
dev
);
dev_needs_restart
[
dev
]
=
0
;
}
if
(
dma_mode
[
dev
]
==
DMODE_OUTPUT
)
/* Was output -> direction change */
{
dma_sync
(
dev
);
dma_reset
(
dev
);
dma_mode
[
dev
]
=
DMODE_NONE
;
}
if
(
dma_mode
[
dev
]
==
DMODE_OUTPUT
)
/* Was output -> direction change */
{
dma_sync
(
dev
);
dma_reset
(
dev
);
dma_mode
[
dev
]
=
DMODE_NONE
;
}
if
(
!
bufferalloc_done
[
dev
])
reorganize_buffers
(
dev
);
if
(
!
bufferalloc_done
[
dev
])
reorganize_buffers
(
dev
);
if
(
!
dma_mode
[
dev
])
{
int
err
;
if
(
!
dma_mode
[
dev
])
{
int
err
;
if
((
err
=
dsp_devs
[
dev
]
->
prepare_for_input
(
dev
,
if
((
err
=
dsp_devs
[
dev
]
->
prepare_for_input
(
dev
,
dev_buffsize
[
dev
],
dev_nbufs
[
dev
]))
<
0
)
{
RESTORE_INTR
(
flags
);
return
err
;
}
dma_mode
[
dev
]
=
DMODE_INPUT
;
}
{
RESTORE_INTR
(
flags
);
return
err
;
}
dma_mode
[
dev
]
=
DMODE_INPUT
;
}
if
(
!
dev_active
[
dev
])
{
dsp_devs
[
dev
]
->
start_input
(
dev
,
dev_buf_phys
[
dev
][
dev_qtail
[
dev
]],
dsp_devs
[
dev
]
->
start_input
(
dev
,
dev_buf_phys
[
dev
][
dev_qtail
[
dev
]],
dev_buffsize
[
dev
],
0
,
!
sound_dma_automode
[
dev
]
||
!
sound_dma_automode
[
dev
]
||
!
dev_started
[
dev
]);
dev_active
[
dev
]
=
1
;
dev_started
[
dev
]
=
1
;
...
...
@@ -454,25 +452,27 @@ DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
case
SNDCTL_DSP_SUBDIVIDE
:
{
int
fact
=
IOCTL_IN
(
arg
);
int
fact
=
IOCTL_IN
(
arg
);
if
(
fact
==
0
)
{
fact
=
dev_subdivision
[
dev
];
if
(
fact
==
0
)
fact
=
1
;
return
IOCTL_OUT
(
arg
,
fact
);
}
if
(
fact
==
0
)
{
fact
=
dev_subdivision
[
dev
];
if
(
fact
==
0
)
fact
=
1
;
return
IOCTL_OUT
(
arg
,
fact
);
}
if
(
dev_subdivision
[
dev
]
!=
0
)
/* Too late to change */
return
RET_ERROR
(
EINVAL
);
if
(
dev_subdivision
[
dev
]
!=
0
)
/* Too late to change */
return
RET_ERROR
(
EINVAL
);
if
(
fact
>
MAX_REALTIME_FACTOR
)
return
RET_ERROR
(
EINVAL
);
if
(
fact
>
MAX_REALTIME_FACTOR
)
return
RET_ERROR
(
EINVAL
);
if
(
fact
!=
1
&&
fact
!=
2
&&
fact
!=
4
&&
fact
!=
8
&&
fact
!=
16
)
return
RET_ERROR
(
EINVAL
);
if
(
fact
!=
1
&&
fact
!=
2
&&
fact
!=
4
&&
fact
!=
8
&&
fact
!=
16
)
return
RET_ERROR
(
EINVAL
);
dev_subdivision
[
dev
]
=
fact
;
return
IOCTL_OUT
(
arg
,
fact
);
dev_subdivision
[
dev
]
=
fact
;
return
IOCTL_OUT
(
arg
,
fact
);
}
break
;
...
...
@@ -480,6 +480,7 @@ DMAbuf_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
return
dsp_devs
[
dev
]
->
ioctl
(
dev
,
cmd
,
arg
,
local
);
}
/* NOTREACHED */
return
RET_ERROR
(
EIO
);
}
...
...
@@ -491,16 +492,15 @@ DMAbuf_getwrbuffer (int dev, char **buf, int *size)
if
(
dma_mode
[
dev
]
==
DMODE_INPUT
)
/* Was input -> Direction change */
{
dma_reset
(
dev
);
dma_mode
[
dev
]
=
DMODE_NONE
;
dma_reset
(
dev
);
dma_mode
[
dev
]
=
DMODE_NONE
;
}
else
if
(
dev_needs_restart
[
dev
])
/* Restart buffering */
else
if
(
dev_needs_restart
[
dev
])
/* Restart buffering */
{
dma_sync
(
dev
);
dma_reset
(
dev
);
dma_sync
(
dev
);
dma_reset
(
dev
);
}
dev_needs_restart
[
dev
]
=
0
;
if
(
!
bufferalloc_done
[
dev
])
...
...
@@ -563,17 +563,18 @@ DMAbuf_start_output (int dev, int buff_no, int l)
dev_counts
[
dev
][
dev_qtail
[
dev
]]
=
l
;
dev_needs_restart
[
dev
]
=
(
l
!=
dev_buffsize
[
dev
]);
dev_needs_restart
[
dev
]
=
(
l
!=
dev_buffsize
[
dev
])
&&
(
sound_dma_automode
[
dev
]
||
dsp_devs
[
dev
]
->
flags
&
NEEDS_RESTART
);
dev_qtail
[
dev
]
=
(
dev_qtail
[
dev
]
+
1
)
%
dev_nbufs
[
dev
];
if
(
!
dev_active
[
dev
])
{
dev_active
[
dev
]
=
1
;
dsp_devs
[
dev
]
->
output_block
(
dev
,
dev_buf_phys
[
dev
][
dev_qhead
[
dev
]],
dev_counts
[
dev
][
dev_qhead
[
dev
]],
0
,
!
sound_dma_automode
[
dev
]
||
!
dev_started
[
dev
]);
dev_started
[
dev
]
=
1
;
dsp_devs
[
dev
]
->
output_block
(
dev
,
dev_buf_phys
[
dev
][
dev_qhead
[
dev
]],
dev_counts
[
dev
][
dev_qhead
[
dev
]],
0
,
!
sound_dma_automode
[
dev
]
||
!
dev_started
[
dev
]);
dev_started
[
dev
]
=
1
;
}
return
0
;
...
...
@@ -606,7 +607,7 @@ DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
set_dma_count
(
chan
,
sound_buffsizes
[
dev
]);
enable_dma
(
chan
);
RESTORE_INTR
(
flags
);
#else
#else
/* linux */
#ifdef __386BSD__
printk
(
"sound: Invalid DMA mode for device %d
\n
"
,
dev
);
...
...
@@ -615,24 +616,24 @@ DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
snd_raw_buf_phys
[
dev
][
0
],
sound_buffsizes
[
dev
],
chan
);
#else
#if defined(ISC) || defined(SCO)
#else
/* __386BSD__ */
#if defined(ISC) || defined(SCO)
|| defined(SVR42)
#ifndef DMAMODE_AUTO
printk
(
"sound: Invalid DMA mode for device %d
\n
"
,
dev
);
#endif
#endif
/* DMAMODE_AUTO */
dma_param
(
chan
,
((
dma_mode
==
DMA_MODE_READ
)
?
DMA_Rdmode
:
DMA_Wrmode
)
#ifdef DMAMODE_AUTO
|
DMAMODE_AUTO
#endif
#endif
/* DMAMODE_AUTO */
,
snd_raw_buf_phys
[
dev
][
0
],
count
);
dma_enable
(
chan
);
#else
#
error This routine is not valid for this OS.
#endif
#endif
#else
/* SYSV */
#error This routine is not valid for this OS.
#endif
/* SYSV */
#endif
/* __386BSD__ */
#endif
#endif
/* linux */
}
else
{
...
...
@@ -645,24 +646,24 @@ DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
set_dma_count
(
chan
,
count
);
enable_dma
(
chan
);
RESTORE_INTR
(
flags
);
#else
#else
/* linux */
#ifdef __386BSD__
isa_dmastart
((
dma_mode
==
DMA_MODE_READ
)
?
B_READ
:
B_WRITE
,
physaddr
,
count
,
chan
);
#else
#else
/* __386BSD__ */
#if defined(ISC) || defined(SCO)
#if defined(ISC) || defined(SCO)
|| defined(SVR42)
dma_param
(
chan
,
((
dma_mode
==
DMA_MODE_READ
)
?
DMA_Rdmode
:
DMA_Wrmode
),
physaddr
,
count
);
dma_enable
(
chan
);
#else
#
error This routine is not valid for this OS.
#endif
/*
!ISC
*/
#endif
#else
/* SYSV */
#error This routine is not valid for this OS.
#endif
/*
SYSV
*/
#endif
/* __386BSD__ */
#endif
#endif
/* linux */
}
return
count
;
...
...
@@ -702,17 +703,17 @@ DMAbuf_outputintr (int dev, int underrun_flag)
if
(
dev_qlen
[
dev
])
{
dsp_devs
[
dev
]
->
output_block
(
dev
,
dev_buf_phys
[
dev
][
dev_qhead
[
dev
]],
dev_counts
[
dev
][
dev_qhead
[
dev
]],
1
,
!
sound_dma_automode
[
dev
]);
dsp_devs
[
dev
]
->
output_block
(
dev
,
dev_buf_phys
[
dev
][
dev_qhead
[
dev
]],
dev_counts
[
dev
][
dev_qhead
[
dev
]],
1
,
!
sound_dma_automode
[
dev
]);
dev_active
[
dev
]
=
1
;
}
else
if
(
underrun_flag
)
else
if
(
underrun_flag
)
{
dev_underrun
[
dev
]
++
;
dsp_devs
[
dev
]
->
halt_xfer
(
dev
);
dev_needs_restart
[
dev
]
=
1
;
dev_needs_restart
[
dev
]
=
(
sound_dma_automode
[
dev
]
||
dsp_devs
[
dev
]
->
flags
&
NEEDS_RESTART
);
}
DISABLE_INTR
(
flags
);
...
...
@@ -734,20 +735,20 @@ DMAbuf_inputintr (int dev)
}
else
if
(
dev_qlen
[
dev
]
==
(
dev_nbufs
[
dev
]
-
1
))
{
printk
(
"Sound: Recording overrun
\n
"
);
printk
(
"Sound: Recording overrun
\n
"
);
dev_underrun
[
dev
]
++
;
dsp_devs
[
dev
]
->
halt_xfer
(
dev
);
dev_active
[
dev
]
=
0
;
dev_needs_restart
[
dev
]
=
1
;
dev_needs_restart
[
dev
]
=
sound_dma_automode
[
dev
]
;
}
else
{
dev_qlen
[
dev
]
++
;
dev_qtail
[
dev
]
=
(
dev_qtail
[
dev
]
+
1
)
%
dev_nbufs
[
dev
];
dsp_devs
[
dev
]
->
start_input
(
dev
,
dev_buf_phys
[
dev
][
dev_qtail
[
dev
]],
dsp_devs
[
dev
]
->
start_input
(
dev
,
dev_buf_phys
[
dev
][
dev_qtail
[
dev
]],
dev_buffsize
[
dev
],
1
,
!
sound_dma_automode
[
dev
]);
!
sound_dma_automode
[
dev
]);
dev_active
[
dev
]
=
1
;
}
...
...
@@ -798,13 +799,13 @@ DMAbuf_reset_dma (int chan)
/*
* The sound_mem_init() is called by mem_init() immediately after mem_map is
* initialized and before free_page_list is created.
*
*
* This routine allocates DMA buffers at the end of available physical memory (
* <16M) and marks pages reserved at mem_map.
*/
#else
/* Stub versions if audio services not included
*/
/* Stub versions if audio services not included
*/
int
DMAbuf_open
(
int
dev
,
int
mode
)
...
...
drivers/sound/gus_card.c
View file @
e695b6a4
/*
* sound/gus_card.c
*
*
* Detection routine for the Gravis Ultrasound.
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -12,7 +12,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -24,7 +24,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#include "sound_config.h"
...
...
@@ -106,7 +106,7 @@ gusintr (int unit)
unsigned
char
src
;
#ifdef linux
sti
();
sti
();
#endif
while
(
1
)
...
...
drivers/sound/gus_hw.h
View file @
e695b6a4
...
...
@@ -24,6 +24,8 @@
#define u_Command (gus_base + 0x103)
#define u_DataLo (gus_base + 0x104)
#define u_DataHi (gus_base + 0x105)
#define u_MixData (gus_base + 0x106)
/* Rev. 3.7+ mixing */
#define u_MixSelect (gus_base + 0x506)
/* registers. */
#define u_IrqStatus u_Status
# define MIDI_TX_IRQ 0x01
/* pending MIDI xmit IRQ */
# define MIDI_RX_IRQ 0x02
/* pending MIDI recv IRQ */
...
...
@@ -32,4 +34,17 @@
# define WAVETABLE_IRQ 0x20
/* pending wavetable IRQ */
# define ENVELOPE_IRQ 0x40
/* pending volume envelope IRQ */
# define DMA_TC_IRQ 0x80
/* pending dma tc IRQ */
#define ICS2101 1
# define ICS_MIXDEVS 6
# define DEV_MIC 0
# define DEV_LINE 1
# define DEV_CD 2
# define DEV_GF1 3
# define DEV_UNUSED 4
# define DEV_VOL 5
# define CHN_LEFT 0
# define CHN_RIGHT 1
#define CS4231 2
#define u_DRAMIO (gus_base + 0x107)
drivers/sound/gus_linearvol.h
0 → 100644
View file @
e695b6a4
static
unsigned
short
gus_linearvol
[
128
]
=
{
0x0000
,
0x08ff
,
0x09ff
,
0x0a80
,
0x0aff
,
0x0b40
,
0x0b80
,
0x0bc0
,
0x0bff
,
0x0c20
,
0x0c40
,
0x0c60
,
0x0c80
,
0x0ca0
,
0x0cc0
,
0x0ce0
,
0x0cff
,
0x0d10
,
0x0d20
,
0x0d30
,
0x0d40
,
0x0d50
,
0x0d60
,
0x0d70
,
0x0d80
,
0x0d90
,
0x0da0
,
0x0db0
,
0x0dc0
,
0x0dd0
,
0x0de0
,
0x0df0
,
0x0dff
,
0x0e08
,
0x0e10
,
0x0e18
,
0x0e20
,
0x0e28
,
0x0e30
,
0x0e38
,
0x0e40
,
0x0e48
,
0x0e50
,
0x0e58
,
0x0e60
,
0x0e68
,
0x0e70
,
0x0e78
,
0x0e80
,
0x0e88
,
0x0e90
,
0x0e98
,
0x0ea0
,
0x0ea8
,
0x0eb0
,
0x0eb8
,
0x0ec0
,
0x0ec8
,
0x0ed0
,
0x0ed8
,
0x0ee0
,
0x0ee8
,
0x0ef0
,
0x0ef8
,
0x0eff
,
0x0f04
,
0x0f08
,
0x0f0c
,
0x0f10
,
0x0f14
,
0x0f18
,
0x0f1c
,
0x0f20
,
0x0f24
,
0x0f28
,
0x0f2c
,
0x0f30
,
0x0f34
,
0x0f38
,
0x0f3c
,
0x0f40
,
0x0f44
,
0x0f48
,
0x0f4c
,
0x0f50
,
0x0f54
,
0x0f58
,
0x0f5c
,
0x0f60
,
0x0f64
,
0x0f68
,
0x0f6c
,
0x0f70
,
0x0f74
,
0x0f78
,
0x0f7c
,
0x0f80
,
0x0f84
,
0x0f88
,
0x0f8c
,
0x0f90
,
0x0f94
,
0x0f98
,
0x0f9c
,
0x0fa0
,
0x0fa4
,
0x0fa8
,
0x0fac
,
0x0fb0
,
0x0fb4
,
0x0fb8
,
0x0fbc
,
0x0fc0
,
0x0fc4
,
0x0fc8
,
0x0fcc
,
0x0fd0
,
0x0fd4
,
0x0fd8
,
0x0fdc
,
0x0fe0
,
0x0fe4
,
0x0fe8
,
0x0fec
,
0x0ff0
,
0x0ff4
,
0x0ff8
,
0x0ffc
};
drivers/sound/gus_midi.c
View file @
e695b6a4
/*
* sound/gus2_midi.c
*
*
* The low level driver for the GUS Midi Interface.
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -12,7 +12,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -24,7 +24,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#include "sound_config.h"
...
...
drivers/sound/gus_vol.c
View file @
e695b6a4
/*
/*
* gus_vol.c - Compute volume for GUS.
*
*
* Greg Lee 1993.
*/
#include "sound_config.h"
#ifndef EXCLUDE_GUS
#include "gus_linearvol.h"
#define GUS_VOLUME gus_wave_volume
extern
int
gus_wave_volume
;
/*
/*
* Calculate gus volume from note velocity, main volume, expression, and
* intrinsic patch volume given in patch library. Expression is multiplied
* in, so it emphasizes differences in note velocity, while main volume is
...
...
@@ -20,7 +21,7 @@ extern int gus_wave_volume;
* to expression controller messages, if they were found to be used for
* dynamic volume adjustments, so here, main volume can be assumed to be
* constant throughout a song.)
*
*
* Intrinsic patch volume is added in, but if over 64 is also multiplied in, so
* we can give a big boost to very weak voices like nylon guitar and the
* basses. The normal value is 64. Strings are assigned lower values.
...
...
@@ -31,27 +32,27 @@ gus_adagio_vol (int vel, int mainv, int xpn, int voicev)
int
i
,
m
,
n
,
x
;
/*
/*
* A voice volume of 64 is considered neutral, so adjust the main volume if
* something other than this neutral value was assigned in the patch
* library.
*/
x
=
256
+
6
*
(
voicev
-
64
);
/*
* Boost expression by voice volume above neutral.
/*
* Boost expression by voice volume above neutral.
*/
if
(
voicev
>
65
)
xpn
+=
voicev
-
64
;
xpn
+=
(
voicev
-
64
)
/
2
;
/*
* Combine multiplicative and level components.
/*
* Combine multiplicative and level components.
*/
x
=
vel
*
xpn
*
6
+
(
voicev
/
4
)
*
x
;
#ifdef GUS_VOLUME
/*
/*
* Further adjustment by installation-specific master volume control
* (default 60).
*/
...
...
@@ -63,8 +64,8 @@ gus_adagio_vol (int vel, int mainv, int xpn, int voicev)
* Experimental support for the channel main volume
*/
mainv
=
(
mainv
/
2
)
+
64
;
/* Scale to 64 to 127 */
x
=
(
x
*
mainv
*
mainv
)
/
16384
;
mainv
=
(
mainv
/
2
)
+
64
;
/* Scale to 64 to 127 */
x
=
(
x
*
mainv
*
mainv
)
/
16384
;
#endif
if
(
x
<
2
)
...
...
@@ -72,7 +73,7 @@ gus_adagio_vol (int vel, int mainv, int xpn, int voicev)
else
if
(
x
>=
65535
)
return
((
15
<<
8
)
|
255
);
/*
/*
* Convert to gus's logarithmic form with 4 bit exponent i and 8 bit
* mantissa m.
*/
...
...
@@ -89,14 +90,14 @@ gus_adagio_vol (int vel, int mainv, int xpn, int voicev)
n
>>=
1
;
i
++
;
}
/*
/*
* Mantissa is part of linear volume not expressed in exponent. (This is
* not quite like real logs -- I wonder if it's right.)
*/
m
=
x
-
(
1
<<
i
);
/*
* Adjust mantissa to 8 bits.
/*
* Adjust mantissa to 8 bits.
*/
if
(
m
>
0
)
{
...
...
@@ -109,4 +110,38 @@ gus_adagio_vol (int vel, int mainv, int xpn, int voicev)
return
((
i
<<
8
)
+
m
);
}
/*
* Volume-values are interpreted as linear values. Volume is based on the
* value supplied with SEQ_START_NOTE(), channel main volume (if compiled in)
* and the volume set by the mixer-device (default 60%).
*/
unsigned
short
gus_linear_vol
(
int
vol
,
int
mainvol
)
{
int
mixer_mainvol
;
if
(
vol
<=
0
)
vol
=
0
;
else
if
(
vol
>=
127
)
vol
=
127
;
#ifdef GUS_VOLUME
mixer_mainvol
=
GUS_VOLUME
;
#else
mixer_mainvol
=
100
;
#endif
#ifdef GUS_USE_CHN_MAIN_VOLUME
if
(
mainvol
<=
0
)
mainvol
=
0
;
else
if
(
mainvol
>=
127
)
mainvol
=
127
;
#else
mainvol
=
128
;
#endif
return
gus_linearvol
[(((
vol
*
mainvol
)
/
128
)
*
mixer_mainvol
)
/
100
];
}
#endif
drivers/sound/gus_wave.c
View file @
e695b6a4
/*
/*
* sound/gus_wave.c
*
*
* Driver for the Gravis UltraSound wave table synth.
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -13,7 +12,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -25,7 +24,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#include "sound_config.h"
...
...
@@ -61,7 +60,7 @@ struct voice_info
unsigned
char
env_rate
[
6
];
unsigned
char
env_offset
[
6
];
/*
/*
* Volume computation parameters for gus_adagio_vol()
*/
int
main_vol
,
expression_vol
,
patch_vol
;
...
...
@@ -84,28 +83,27 @@ static int gus_busy = 0;
static
int
nr_voices
=
0
;
static
int
gus_devnum
=
0
;
static
int
volume_base
,
volume_scale
,
volume_method
;
static
int
gus_line_vol
=
100
,
gus_mic_vol
=
0
;
static
int
gus_recmask
=
SOUND_MASK_MIC
;
static
int
recording_active
=
0
;
static
int
gus_line_vol
=
100
,
gus_mic_vol
=
0
;
static
int
gus_recmask
=
SOUND_MASK_MIC
;
static
int
recording_active
=
0
;
#define VOL_METHOD_ADAGIO 1
int
gus_wave_volume
=
60
;
int
gus_pcm_volume
=
80
;
static
unsigned
char
mix_image
=
0x00
;
/*
/*
* Current version of this driver doesn't allow synth and PCM functions
* at the same time. The active_device specifies the active driver
*/
static
int
active_device
=
0
;
#define GUS_DEV_WAVE 1
/*
* * * Wave table synth */
#define GUS_DEV_PCM_DONE 2
/*
* * * PCM device, transfer done */
#define GUS_DEV_PCM_CONTINUE 3
/*
* * * PCM device, transfer the
* second * * * chn */
#define GUS_DEV_WAVE 1
/*
* * * Wave table synth */
#define GUS_DEV_PCM_DONE 2
/*
* * * PCM device, transfer done */
#define GUS_DEV_PCM_CONTINUE 3
/*
* * * PCM device, transfer the
* second * * * chn */
static
int
gus_sampling_speed
;
static
int
gus_sampling_channels
;
...
...
@@ -113,33 +111,33 @@ static int gus_sampling_bits;
DEFINE_WAIT_QUEUE
(
dram_sleeper
,
dram_sleep_flag
);
/*
/*
* Variables and buffers for PCM output
*/
#define MAX_PCM_BUFFERS (32*MAX_REALTIME_FACTOR)
/*
* * * Don't
* * * change
*
#define MAX_PCM_BUFFERS (32*MAX_REALTIME_FACTOR)
/*
* * * Don't
* * * change
*
*/
static
int
pcm_bsize
,
/*
* Current blocksize
static
int
pcm_bsize
,
/*
* Current blocksize
*/
pcm_nblk
,
/*
* Current # of blocks
pcm_nblk
,
/*
* Current # of blocks
*/
pcm_banksize
;
/*
pcm_banksize
;
/*
*
* * * * # bytes allocated for channels */
static
int
pcm_datasize
[
MAX_PCM_BUFFERS
];
/*
static
int
pcm_datasize
[
MAX_PCM_BUFFERS
];
/*
*
* * * * Actual # of bytes
* in blk * */
static
volatile
int
pcm_head
,
pcm_tail
,
pcm_qlen
;
/*
static
volatile
int
pcm_head
,
pcm_tail
,
pcm_qlen
;
/*
*
* * * * DRAM queue
* */
static
volatile
int
pcm_active
;
...
...
@@ -154,62 +152,62 @@ struct voice_info voices[32];
static
int
freq_div_table
[]
=
{
44100
,
/*
* 14
44100
,
/*
* 14
*/
41160
,
/*
* 15
41160
,
/*
* 15
*/
38587
,
/*
* 16
38587
,
/*
* 16
*/
36317
,
/*
* 17
36317
,
/*
* 17
*/
34300
,
/*
* 18
34300
,
/*
* 18
*/
32494
,
/*
* 19
32494
,
/*
* 19
*/
30870
,
/*
* 20
30870
,
/*
* 20
*/
29400
,
/*
* 21
29400
,
/*
* 21
*/
28063
,
/*
* 22
28063
,
/*
* 22
*/
26843
,
/*
* 23
26843
,
/*
* 23
*/
25725
,
/*
* 24
25725
,
/*
* 24
*/
24696
,
/*
* 25
24696
,
/*
* 25
*/
23746
,
/*
* 26
23746
,
/*
* 26
*/
22866
,
/*
* 27
22866
,
/*
* 27
*/
22050
,
/*
* 28
22050
,
/*
* 28
*/
21289
,
/*
* 29
21289
,
/*
* 29
*/
20580
,
/*
* 30
20580
,
/*
* 30
*/
19916
,
/*
* 31
19916
,
/*
* 31
*/
19293
/*
* 32
19293
/*
* 32
*/
};
...
...
@@ -228,14 +226,15 @@ static struct synth_info gus_info =
static
void
gus_poke
(
long
addr
,
unsigned
char
data
);
static
void
compute_and_set_volume
(
int
voice
,
int
volume
,
int
ramp_time
);
extern
unsigned
short
gus_adagio_vol
(
int
vel
,
int
mainv
,
int
xpn
,
int
voicev
);
extern
unsigned
short
gus_linear_vol
(
int
vol
,
int
mainvol
);
static
void
compute_volume
(
int
voice
,
int
volume
);
static
void
do_volume_irq
(
int
voice
);
static
void
set_input_volumes
(
void
);
static
void
set_input_volumes
(
void
);
#define INSTANT_RAMP -1
/*
* * * Dont use ramping */
#define FAST_RAMP 0
/*
* * * Fastest possible ramp */
#define INSTANT_RAMP -1
/*
* * * Dont use ramping */
#define FAST_RAMP 0
/*
* * * Fastest possible ramp */
static
void
reset_sample_memory
(
void
)
...
...
@@ -249,8 +248,8 @@ reset_sample_memory (void)
for
(
i
=
0
;
i
<
32
;
i
++
)
patch_map
[
i
]
=
-
1
;
gus_poke
(
0
,
0
);
/*
* Put silence here
gus_poke
(
0
,
0
);
/*
* Put silence here
*/
gus_poke
(
1
,
0
);
...
...
@@ -386,7 +385,7 @@ gus_write_addr (int reg, unsigned long address, int is16bit)
if
(
is16bit
)
{
/*
/*
* Special processing required for 16 bit patches
*/
...
...
@@ -398,6 +397,10 @@ gus_write_addr (int reg, unsigned long address, int is16bit)
gus_write16
(
reg
,
(
unsigned
short
)
((
address
>>
7
)
&
0xffff
));
gus_write16
(
reg
+
1
,
(
unsigned
short
)
((
address
<<
9
)
&
0xffff
));
/* Could writing twice fix problems with GUS_VOICE_POS() ? Lets try... */
gus_delay
();
gus_write16
(
reg
,
(
unsigned
short
)
((
address
>>
7
)
&
0xffff
));
gus_write16
(
reg
+
1
,
(
unsigned
short
)
((
address
<<
9
)
&
0xffff
));
}
static
void
...
...
@@ -441,13 +444,13 @@ gus_voice_mode (unsigned int m)
{
unsigned
char
mode
=
(
unsigned
char
)
(
m
&
0xff
);
gus_write8
(
0x00
,
(
gus_read8
(
0x00
)
&
0x03
)
|
(
mode
&
0xfc
));
/*
* Don't
* start
* or
gus_write8
(
0x00
,
(
gus_read8
(
0x00
)
&
0x03
)
|
(
mode
&
0xfc
));
/*
* Don't
* start
* or
* stop
* *
* voice
* voice
*/
gus_delay
();
gus_write8
(
0x00
,
(
gus_read8
(
0x00
)
&
0x03
)
|
(
mode
&
0xfc
));
...
...
@@ -468,8 +471,8 @@ gus_voice_freq (unsigned long freq)
static
void
gus_voice_volume
(
unsigned
int
vol
)
{
gus_write8
(
0x0d
,
0x03
);
/*
* Stop ramp before setting volume
gus_write8
(
0x0d
,
0x03
);
/*
* Stop ramp before setting volume
*/
gus_write16
(
0x09
,
(
unsigned
short
)
(
vol
<<
4
));
}
...
...
@@ -508,13 +511,13 @@ gus_ramp_mode (unsigned int m)
{
unsigned
char
mode
=
(
unsigned
char
)
(
m
&
0xff
);
gus_write8
(
0x0d
,
(
gus_read8
(
0x0d
)
&
0x03
)
|
(
mode
&
0xfc
));
/*
* Don't
* start
* or
gus_write8
(
0x0d
,
(
gus_read8
(
0x0d
)
&
0x03
)
|
(
mode
&
0xfc
));
/*
* Don't
* start
* or
* stop
* *
* ramping
* ramping
*/
gus_delay
();
gus_write8
(
0x0d
,
(
gus_read8
(
0x0d
)
&
0x03
)
|
(
mode
&
0xfc
));
...
...
@@ -548,14 +551,14 @@ gus_voice_init (int voice)
DISABLE_INTR
(
flags
);
gus_select_voice
(
voice
);
gus_voice_volume
(
0
);
gus_write_addr
(
0x0a
,
0
,
0
);
/*
* Set current position to 0
gus_write_addr
(
0x0a
,
0
,
0
);
/*
* Set current position to 0
*/
gus_write8
(
0x00
,
0x03
);
/*
* Voice off
gus_write8
(
0x00
,
0x03
);
/*
* Voice off
*/
gus_write8
(
0x0d
,
0x03
);
/*
* Ramping off
gus_write8
(
0x0d
,
0x03
);
/*
* Ramping off
*/
RESTORE_INTR
(
flags
);
...
...
@@ -588,18 +591,22 @@ step_envelope (int voice)
{
unsigned
vol
,
prev_vol
,
phase
;
unsigned
char
rate
;
long
int
flags
;
if
(
voices
[
voice
].
mode
&
WAVE_SUSTAIN_ON
&&
voices
[
voice
].
env_phase
==
2
)
{
DISABLE_INTR
(
flags
);
gus_select_voice
(
voice
);
gus_rampoff
();
return
;
/*
* Sustain
RESTORE_INTR
(
flags
);
return
;
/*
* Sustain
*/
}
if
(
voices
[
voice
].
env_phase
>=
5
)
{
/*
/*
* Shoot the voice off
*/
...
...
@@ -608,25 +615,30 @@ step_envelope (int voice)
}
prev_vol
=
voices
[
voice
].
current_volume
;
gus_voice_volume
(
prev_vol
);
phase
=
++
voices
[
voice
].
env_phase
;
compute_volume
(
voice
,
voices
[
voice
].
midi_volume
);
vol
=
voices
[
voice
].
initial_volume
*
voices
[
voice
].
env_offset
[
phase
]
/
255
;
rate
=
voices
[
voice
].
env_rate
[
phase
];
gus_write8
(
0x06
,
rate
);
/*
* Ramping rate
DISABLE_INTR
(
flags
);
gus_select_voice
(
voice
);
gus_voice_volume
(
prev_vol
);
gus_write8
(
0x06
,
rate
);
/*
* Ramping rate
*/
voices
[
voice
].
volume_irq_mode
=
VMODE_ENVELOPE
;
if
(((
vol
-
prev_vol
)
/
64
)
==
0
)
/*
* No significant volume change
if
(((
vol
-
prev_vol
)
/
64
)
==
0
)
/*
* No significant volume change
*/
{
step_envelope
(
voice
);
/*
* Continue with the next phase
RESTORE_INTR
(
flags
);
step_envelope
(
voice
);
/*
* Continue with the next phase
*/
return
;
}
...
...
@@ -636,8 +648,8 @@ step_envelope (int voice)
if
(
vol
>=
(
4096
-
64
))
vol
=
4096
-
65
;
gus_ramp_range
(
0
,
vol
);
gus_rampon
(
0x20
);
/*
* Increasing, irq
gus_rampon
(
0x20
);
/*
* Increasing, irq
*/
}
else
...
...
@@ -645,11 +657,12 @@ step_envelope (int voice)
if
(
vol
<=
64
)
vol
=
65
;
gus_ramp_range
(
vol
,
4030
);
gus_rampon
(
0x60
);
/*
* Decreasing, irq
gus_rampon
(
0x60
);
/*
* Decreasing, irq
*/
}
voices
[
voice
].
current_volume
=
vol
;
RESTORE_INTR
(
flags
);
}
static
void
...
...
@@ -662,25 +675,26 @@ init_envelope (int voice)
}
static
void
start_release
(
int
voice
)
start_release
(
int
voice
,
long
int
flags
)
{
if
(
gus_read8
(
0x00
)
&
0x03
)
return
;
/*
* Voice already stopped
return
;
/*
* Voice already stopped
*/
voices
[
voice
].
env_phase
=
2
;
/*
* Will be incremented by step_envelope
voices
[
voice
].
env_phase
=
2
;
/*
* Will be incremented by step_envelope
*/
voices
[
voice
].
current_volume
=
voices
[
voice
].
initial_volume
=
gus_read16
(
0x09
)
>>
4
;
/*
* Get current volume
gus_read16
(
0x09
)
>>
4
;
/*
* Get current volume
*/
voices
[
voice
].
mode
&=
~
WAVE_SUSTAIN_ON
;
gus_rampoff
();
RESTORE_INTR
(
flags
);
step_envelope
(
voice
);
}
...
...
@@ -688,32 +702,37 @@ static void
gus_voice_fade
(
int
voice
)
{
int
instr_no
=
sample_map
[
voice
],
is16bits
;
long
int
flags
;
DISABLE_INTR
(
flags
);
gus_select_voice
(
voice
);
if
(
instr_no
<
0
||
instr_no
>
MAX_SAMPLE
)
{
gus_write8
(
0x00
,
0x03
);
/*
* Hard stop
gus_write8
(
0x00
,
0x03
);
/*
* Hard stop
*/
RESTORE_INTR
(
flags
);
return
;
}
is16bits
=
(
samples
[
instr_no
].
mode
&
WAVE_16_BITS
)
?
1
:
0
;
/*
is16bits
=
(
samples
[
instr_no
].
mode
&
WAVE_16_BITS
)
?
1
:
0
;
/*
* 8 or 16
* bit
* samples
* samples
*/
if
(
voices
[
voice
].
mode
&
WAVE_ENVELOPES
)
{
start_release
(
voice
);
start_release
(
voice
,
flags
);
return
;
}
/*
/*
* Ramp the volume down but not too quickly.
*/
if
((
gus_read16
(
0x09
)
>>
4
)
<
100
)
/*
* Get current volume
if
((
gus_read16
(
0x09
)
>>
4
)
<
100
)
/*
* Get current volume
*/
{
gus_voice_off
();
...
...
@@ -724,10 +743,11 @@ gus_voice_fade (int voice)
gus_ramp_range
(
65
,
4030
);
gus_ramp_rate
(
2
,
4
);
gus_rampon
(
0x40
|
0x20
);
/*
* Down, once, irq
gus_rampon
(
0x40
|
0x20
);
/*
* Down, once, irq
*/
voices
[
voice
].
volume_irq_mode
=
VMODE_HALT
;
RESTORE_INTR
(
flags
);
}
static
void
...
...
@@ -742,24 +762,24 @@ gus_reset (void)
for
(
i
=
0
;
i
<
32
;
i
++
)
{
gus_voice_init
(
i
);
/*
* Turn voice off
gus_voice_init
(
i
);
/*
* Turn voice off
*/
gus_voice_init2
(
i
);
}
INB
(
u_Status
);
/*
* Touch the status register
INB
(
u_Status
);
/*
* Touch the status register
*/
gus_look8
(
0x41
);
/*
* Clear any pending DMA IRQs
gus_look8
(
0x41
);
/*
* Clear any pending DMA IRQs
*/
gus_look8
(
0x49
);
/*
* Clear any pending sample IRQs
gus_look8
(
0x49
);
/*
* Clear any pending sample IRQs
*/
gus_read8
(
0x0f
);
/*
* Clear pending IRQs
gus_read8
(
0x0f
);
/*
* Clear pending IRQs
*/
}
...
...
@@ -768,7 +788,7 @@ static void
gus_initialize
(
void
)
{
unsigned
long
flags
;
unsigned
char
dma_image
,
irq_image
,
tmp
;
register
unsigned
char
dma_image
,
irq_image
,
tmp
;
static
unsigned
char
gus_irq_map
[
16
]
=
{
0
,
0
,
1
,
3
,
0
,
2
,
0
,
4
,
0
,
0
,
0
,
5
,
6
,
0
,
0
,
7
};
...
...
@@ -778,74 +798,74 @@ gus_initialize (void)
DISABLE_INTR
(
flags
);
gus_write8
(
0x4c
,
0
);
/*
* Reset GF1
gus_write8
(
0x4c
,
0
);
/*
* Reset GF1
*/
gus_delay
();
gus_delay
();
gus_write8
(
0x4c
,
1
);
/*
* Release Reset
gus_write8
(
0x4c
,
1
);
/*
* Release Reset
*/
gus_delay
();
gus_delay
();
/*
/*
* Clear all interrupts
*/
gus_write8
(
0x41
,
0
);
/*
* DMA control
gus_write8
(
0x41
,
0
);
/*
* DMA control
*/
gus_write8
(
0x45
,
0
);
/*
* Timer control
gus_write8
(
0x45
,
0
);
/*
* Timer control
*/
gus_write8
(
0x49
,
0
);
/*
* Sample control
gus_write8
(
0x49
,
0
);
/*
* Sample control
*/
gus_select_max_voices
(
24
);
INB
(
u_Status
);
/*
* Touch the status register
INB
(
u_Status
);
/*
* Touch the status register
*/
gus_look8
(
0x41
);
/*
* Clear any pending DMA IRQs
gus_look8
(
0x41
);
/*
* Clear any pending DMA IRQs
*/
gus_look8
(
0x49
);
/*
* Clear any pending sample IRQs
gus_look8
(
0x49
);
/*
* Clear any pending sample IRQs
*/
gus_read8
(
0x0f
);
/*
* Clear pending IRQs
gus_read8
(
0x0f
);
/*
* Clear pending IRQs
*/
gus_reset
();
/*
* Resets all voices
gus_reset
();
/*
* Resets all voices
*/
gus_look8
(
0x41
);
/*
* Clear any pending DMA IRQs
gus_look8
(
0x41
);
/*
* Clear any pending DMA IRQs
*/
gus_look8
(
0x49
);
/*
* Clear any pending sample IRQs
gus_look8
(
0x49
);
/*
* Clear any pending sample IRQs
*/
gus_read8
(
0x0f
);
/*
* Clear pending IRQs
gus_read8
(
0x0f
);
/*
* Clear pending IRQs
*/
gus_write8
(
0x4c
,
7
);
/*
* Master reset | DAC enable | IRQ enable
gus_write8
(
0x4c
,
7
);
/*
* Master reset | DAC enable | IRQ enable
*/
/*
/*
* Set up for Digital ASIC
*/
OUTB
(
0x05
,
gus_base
+
0x0f
);
mix_image
|=
0x02
;
/*
* Disable line out
mix_image
|=
0x02
;
/*
* Disable line out
*/
OUTB
(
mix_image
,
u_Mixer
);
...
...
@@ -853,11 +873,11 @@ gus_initialize (void)
OUTB
(
0x00
,
gus_base
+
0x0f
);
/*
/*
* Now set up the DMA and IRQ interface
*
*
* The GUS supports two IRQs and two DMAs.
*
*
* Just one DMA channel is used. This prevents simultaneous ADC and DAC.
* Adding this support requires significant changes to the dmabuf.c, dsp.c
* and audio.c also.
...
...
@@ -868,79 +888,79 @@ gus_initialize (void)
if
(
!
tmp
)
printk
(
"Warning! GUS IRQ not selected
\n
"
);
irq_image
|=
tmp
;
irq_image
|=
0x40
;
/*
* Combine IRQ1 (GF1) and IRQ2 (Midi)
irq_image
|=
0x40
;
/*
* Combine IRQ1 (GF1) and IRQ2 (Midi)
*/
dma_image
=
0x40
;
/*
* Combine DMA1 (DRAM) and IRQ2 (ADC)
dma_image
=
0x40
;
/*
* Combine DMA1 (DRAM) and IRQ2 (ADC)
*/
tmp
=
gus_dma_map
[
gus_dma
];
if
(
!
tmp
)
printk
(
"Warning! GUS DMA not selected
\n
"
);
dma_image
|=
tmp
;
/*
/*
* For some reason the IRQ and DMA addresses must be written twice
*/
/*
* Doing it first time
/*
* Doing it first time
*/
OUTB
(
mix_image
,
u_Mixer
);
/*
* Select DMA control
OUTB
(
mix_image
,
u_Mixer
);
/*
* Select DMA control
*/
OUTB
(
dma_image
|
0x80
,
u_IRQDMAControl
);
/*
* Set DMA address
OUTB
(
dma_image
|
0x80
,
u_IRQDMAControl
);
/*
* Set DMA address
*/
OUTB
(
mix_image
|
0x40
,
u_Mixer
);
/*
* Select IRQ control
OUTB
(
mix_image
|
0x40
,
u_Mixer
);
/*
* Select IRQ control
*/
OUTB
(
irq_image
,
u_IRQDMAControl
);
/*
* Set IRQ address
OUTB
(
irq_image
,
u_IRQDMAControl
);
/*
* Set IRQ address
*/
/*
* Doing it second time
/*
* Doing it second time
*/
OUTB
(
mix_image
,
u_Mixer
);
/*
* Select DMA control
OUTB
(
mix_image
,
u_Mixer
);
/*
* Select DMA control
*/
OUTB
(
dma_image
,
u_IRQDMAControl
);
/*
* Set DMA address
OUTB
(
dma_image
,
u_IRQDMAControl
);
/*
* Set DMA address
*/
OUTB
(
mix_image
|
0x40
,
u_Mixer
);
/*
* Select IRQ control
OUTB
(
mix_image
|
0x40
,
u_Mixer
);
/*
* Select IRQ control
*/
OUTB
(
irq_image
,
u_IRQDMAControl
);
/*
* Set IRQ address
OUTB
(
irq_image
,
u_IRQDMAControl
);
/*
* Set IRQ address
*/
gus_select_voice
(
0
);
/*
* This disables writes to IRQ/DMA reg
gus_select_voice
(
0
);
/*
* This disables writes to IRQ/DMA reg
*/
mix_image
&=
~
0x02
;
/*
* Enable line out
mix_image
&=
~
0x02
;
/*
* Enable line out
*/
mix_image
|=
0x08
;
/*
* Enable IRQ
mix_image
|=
0x08
;
/*
* Enable IRQ
*/
OUTB
(
mix_image
,
u_Mixer
);
/*
* Turn mixer channels on
OUTB
(
mix_image
,
u_Mixer
);
/*
* Turn mixer channels on
* Note! Mic in is left off.
*/
gus_select_voice
(
0
);
/*
* This disables writes to IRQ/DMA reg
gus_select_voice
(
0
);
/*
* This disables writes to IRQ/DMA reg
*/
gusintr
(
0
);
/*
* Serve pending interrupts
gusintr
(
0
);
/*
* Serve pending interrupts
*/
RESTORE_INTR
(
flags
);
}
...
...
@@ -1048,13 +1068,13 @@ guswave_set_instr (int dev, int voice, int instr_no)
if
(
sample_no
<
0
)
{
printk
(
"GUS: Undefined patch %d for voice %d
\n
"
,
instr_no
,
voice
);
return
RET_ERROR
(
EINVAL
);
/*
* Patch not defined
return
RET_ERROR
(
EINVAL
);
/*
* Patch not defined
*/
}
if
(
sample_ptrs
[
sample_no
]
==
-
1
)
/*
* Sample not loaded
if
(
sample_ptrs
[
sample_no
]
==
-
1
)
/*
* Sample not loaded
*/
{
printk
(
"GUS: Sample #%d not loaded for patch %d (voice %d)
\n
"
,
sample_no
,
instr_no
,
voice
);
...
...
@@ -1077,13 +1097,15 @@ guswave_kill_note (int dev, int voice, int velocity)
DISABLE_INTR
(
flags
);
if
(
voices
[
voice
].
volume_irq_mode
==
VMODE_START_NOTE
)
voices
[
voice
].
kill_pending
=
1
;
{
voices
[
voice
].
kill_pending
=
1
;
RESTORE_INTR
(
flags
);
}
else
{
gus_select_voice
(
voice
);
RESTORE_INTR
(
flags
);
gus_voice_fade
(
voice
);
}
RESTORE_INTR
(
flags
);
return
0
;
}
...
...
@@ -1094,16 +1116,16 @@ guswave_aftertouch (int dev, int voice, int pressure)
short
lo_limit
,
hi_limit
;
unsigned
long
flags
;
return
;
/*
* Currently disabled
return
;
/*
* Currently disabled
*/
if
(
voice
<
0
||
voice
>
31
)
return
;
if
(
voices
[
voice
].
mode
&
WAVE_ENVELOPES
&&
voices
[
voice
].
env_phase
!=
2
)
return
;
/*
* Don't mix with envelopes
return
;
/*
* Don't mix with envelopes
*/
if
(
pressure
<
32
)
...
...
@@ -1111,8 +1133,8 @@ guswave_aftertouch (int dev, int voice, int pressure)
DISABLE_INTR
(
flags
);
gus_select_voice
(
voice
);
gus_rampoff
();
compute_and_set_volume
(
voice
,
255
,
0
);
/*
* Back to original volume
compute_and_set_volume
(
voice
,
255
,
0
);
/*
* Back to original volume
*/
RESTORE_INTR
(
flags
);
return
;
...
...
@@ -1132,8 +1154,8 @@ guswave_aftertouch (int dev, int voice, int pressure)
}
gus_ramp_range
(
lo_limit
,
hi_limit
);
gus_ramp_rate
(
3
,
8
);
gus_rampon
(
0x58
);
/*
* Bidirectional, Down, Loop
gus_rampon
(
0x58
);
/*
* Bidirectional, Down, Loop
*/
RESTORE_INTR
(
flags
);
}
...
...
@@ -1145,25 +1167,37 @@ guswave_panning (int dev, int voice, int value)
voices
[
voice
].
panning
=
value
;
}
static
void
guswave_volume_method
(
int
dev
,
int
mode
)
{
if
(
mode
==
VOL_METHOD_LINEAR
||
mode
==
VOL_METHOD_ADAGIO
)
volume_method
=
mode
;
}
static
void
compute_volume
(
int
voice
,
int
volume
)
{
if
(
volume
<
128
)
voices
[
voice
].
midi_volume
=
volume
;
switch
(
volume_method
)
{
case
VOL_METHOD_ADAGIO
:
voices
[
voice
].
initial_volume
=
gus_adagio_vol
(
voices
[
voice
].
midi_volume
,
voices
[
voice
].
main_vol
,
voices
[
voice
].
expression_vol
,
voices
[
voice
].
patch_vol
);
break
;
switch
(
volume_method
)
{
case
VOL_METHOD_ADAGIO
:
voices
[
voice
].
initial_volume
=
gus_adagio_vol
(
voices
[
voice
].
midi_volume
,
voices
[
voice
].
main_vol
,
voices
[
voice
].
expression_vol
,
voices
[
voice
].
patch_vol
);
break
;
default:
voices
[
voice
].
initial_volume
=
volume_base
+
(
voices
[
voice
].
midi_volume
*
volume_scale
);
}
case
VOL_METHOD_LINEAR
:
/* Totally ignores patch-volume and expression */
voices
[
voice
].
initial_volume
=
gus_linear_vol
(
volume
,
voices
[
voice
].
main_vol
);
break
;
default:
voices
[
voice
].
initial_volume
=
volume_base
+
(
voices
[
voice
].
midi_volume
*
volume_scale
);
}
if
(
voices
[
voice
].
initial_volume
>
4030
)
voices
[
voice
].
initial_volume
=
4030
;
...
...
@@ -1175,16 +1209,16 @@ compute_and_set_volume (int voice, int volume, int ramp_time)
int
current
,
target
,
rate
;
unsigned
long
flags
;
compute_volume
(
voice
,
volume
);
voices
[
voice
].
current_volume
=
voices
[
voice
].
initial_volume
;
DISABLE_INTR
(
flags
);
/*
/*
* CAUTION! Interrupts disabled. Enable them before returning
*/
gus_select_voice
(
voice
);
compute_volume
(
voice
,
volume
);
voices
[
voice
].
current_volume
=
voices
[
voice
].
initial_volume
;
current
=
gus_read16
(
0x09
)
>>
4
;
target
=
voices
[
voice
].
initial_volume
;
...
...
@@ -1202,8 +1236,8 @@ compute_and_set_volume (int voice, int volume, int ramp_time)
rate
=
16
;
gus_ramp_rate
(
0
,
rate
);
if
((
target
-
current
)
/
64
==
0
)
/*
* Too close
if
((
target
-
current
)
/
64
==
0
)
/*
* Too close
*/
{
gus_rampoff
();
...
...
@@ -1217,8 +1251,8 @@ compute_and_set_volume (int voice, int volume, int ramp_time)
if
(
target
>
(
4095
-
65
))
target
=
4095
-
65
;
gus_ramp_range
(
current
,
target
);
gus_rampon
(
0x00
);
/*
* Ramp up, once, no irq
gus_rampon
(
0x00
);
/*
* Ramp up, once, no irq
*/
}
else
...
...
@@ -1227,8 +1261,8 @@ compute_and_set_volume (int voice, int volume, int ramp_time)
target
=
65
;
gus_ramp_range
(
target
,
current
);
gus_rampon
(
0x40
);
/*
* Ramp down, once, no irq
gus_rampon
(
0x40
);
/*
* Ramp down, once, no irq
*/
}
RESTORE_INTR
(
flags
);
...
...
@@ -1242,14 +1276,14 @@ dynamic_volume_change (int voice)
DISABLE_INTR
(
flags
);
gus_select_voice
(
voice
);
status
=
gus_read8
(
0x00
);
/*
* Voice status
status
=
gus_read8
(
0x00
);
/*
* Voice status
*/
RESTORE_INTR
(
flags
);
if
(
status
&
0x03
)
return
;
/*
* Voice not started
return
;
/*
* Voice not started
*/
if
(
!
(
voices
[
voice
].
mode
&
WAVE_ENVELOPES
))
...
...
@@ -1258,19 +1292,19 @@ dynamic_volume_change (int voice)
return
;
}
/*
/*
* Voice is running and has envelopes.
*/
DISABLE_INTR
(
flags
);
gus_select_voice
(
voice
);
status
=
gus_read8
(
0x0d
);
/*
* Ramping status
status
=
gus_read8
(
0x0d
);
/*
* Ramping status
*/
RESTORE_INTR
(
flags
);
if
(
status
&
0x03
)
/*
* Sustain phase?
if
(
status
&
0x03
)
/*
* Sustain phase?
*/
{
compute_and_set_volume
(
voice
,
voices
[
voice
].
midi_volume
,
1
);
...
...
@@ -1282,11 +1316,11 @@ dynamic_volume_change (int voice)
compute_volume
(
voice
,
voices
[
voice
].
midi_volume
);
#if 0 /*
* * * Is this really required */
#if 0 /*
* * * Is this really required */
voices[voice].current_volume =
gus_read16 (0x09) >> 4; /*
* Get current volume
gus_read16 (0x09) >> 4; /*
* Get current volume
*/
voices[voice].env_phase--;
...
...
@@ -1309,15 +1343,15 @@ guswave_controller (int dev, int voice, int ctrl_num, int value)
voices
[
voice
].
bender
=
value
;
if
(
voices
[
voice
].
volume_irq_mode
!=
VMODE_START_NOTE
)
{
freq
=
compute_finetune
(
voices
[
voice
].
orig_freq
,
value
,
voices
[
voice
].
bender_range
);
voices
[
voice
].
current_freq
=
freq
;
DISABLE_INTR
(
flags
);
gus_select_voice
(
voice
);
gus_voice_freq
(
freq
);
RESTORE_INTR
(
flags
);
}
{
freq
=
compute_finetune
(
voices
[
voice
].
orig_freq
,
value
,
voices
[
voice
].
bender_range
);
voices
[
voice
].
current_freq
=
freq
;
DISABLE_INTR
(
flags
);
gus_select_voice
(
voice
);
gus_voice_freq
(
freq
);
RESTORE_INTR
(
flags
);
}
break
;
case
CTRL_PITCH_BENDER_RANGE
:
...
...
@@ -1328,10 +1362,12 @@ guswave_controller (int dev, int voice, int ctrl_num, int value)
value
/=
128
;
#endif
case
CTRL_EXPRESSION
:
volume_method
=
VOL_METHOD_ADAGIO
;
voices
[
voice
].
expression_vol
=
value
;
if
(
voices
[
voice
].
volume_irq_mode
!=
VMODE_START_NOTE
)
dynamic_volume_change
(
voice
);
if
(
volume_method
==
VOL_METHOD_ADAGIO
)
{
voices
[
voice
].
expression_vol
=
value
;
if
(
voices
[
voice
].
volume_irq_mode
!=
VMODE_START_NOTE
)
dynamic_volume_change
(
voice
);
}
break
;
#ifdef FUTURE_VERSION
...
...
@@ -1344,14 +1380,13 @@ guswave_controller (int dev, int voice, int ctrl_num, int value)
#endif
case
CTRL_MAIN_VOLUME
:
volume_method
=
VOL_METHOD_ADAGIO
;
voices
[
voice
].
main_vol
=
value
;
if
(
voices
[
voice
].
volume_irq_mode
!=
VMODE_START_NOTE
)
dynamic_volume_change
(
voice
);
dynamic_volume_change
(
voice
);
break
;
default:
/*
* Ignore
default:
/*
* Ignore
*/
break
;
}
...
...
@@ -1396,7 +1431,7 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
note_freq
=
note_to_freq
(
note_num
);
/*
/*
* Find a sample within a patch so that the note_freq is between low_note
* and high_note.
*/
...
...
@@ -1417,8 +1452,8 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
if
(
samples
[
samplep
].
low_note
<=
note_freq
&&
note_freq
<=
samples
[
samplep
].
high_note
)
sample
=
samplep
;
else
samplep
=
samples
[
samplep
].
key
;
/*
* Follow link
samplep
=
samples
[
samplep
].
key
;
/*
* Follow link
*/
}
if
(
sample
==
-
1
)
...
...
@@ -1427,15 +1462,15 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
if
(
sample
==
-
1
)
{
printk
(
"GUS: Patch %d not defined for note %d
\n
"
,
patch
,
note_num
);
return
0
;
/*
* Should play default patch ???
return
0
;
/*
* Should play default patch ???
*/
}
is16bits
=
(
samples
[
sample
].
mode
&
WAVE_16_BITS
)
?
1
:
0
;
/*
is16bits
=
(
samples
[
sample
].
mode
&
WAVE_16_BITS
)
?
1
:
0
;
/*
* 8 or 16
* bit
* samples
* samples
*/
voices
[
voice
].
mode
=
samples
[
sample
].
mode
;
voices
[
voice
].
patch_vol
=
samples
[
sample
].
volume
;
...
...
@@ -1453,8 +1488,8 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
sample_map
[
voice
]
=
sample
;
base_note
=
samples
[
sample
].
base_note
/
100
;
/*
* To avoid overflows
base_note
=
samples
[
sample
].
base_note
/
100
;
/*
* To avoid overflows
*/
note_freq
/=
100
;
...
...
@@ -1462,7 +1497,7 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
voices
[
voice
].
orig_freq
=
freq
;
/*
/*
* Since the pitch bender may have been set before playing the note, we
* have to calculate the bending now.
*/
...
...
@@ -1479,8 +1514,8 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
if
(
samples
[
sample
].
mode
&
WAVE_16_BITS
)
{
mode
|=
0x04
;
/*
* 16 bits
mode
|=
0x04
;
/*
* 16 bits
*/
if
((
sample_ptrs
[
sample
]
>>
18
)
!=
((
sample_ptrs
[
sample
]
+
samples
[
sample
].
len
)
>>
18
))
...
...
@@ -1493,10 +1528,13 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
DISABLE_INTR
(
flags
);
gus_select_voice
(
voice
);
gus_voice_off
();
/*
* It may still be running
gus_voice_off
();
/*
* It may still be running
*/
gus_rampoff
();
RESTORE_INTR
(
flags
);
if
(
voices
[
voice
].
mode
&
WAVE_ENVELOPES
)
{
compute_volume
(
voice
,
volume
);
...
...
@@ -1505,6 +1543,9 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
else
compute_and_set_volume
(
voice
,
volume
,
0
);
DISABLE_INTR
(
flags
);
gus_select_voice
(
voice
);
if
(
samples
[
sample
].
mode
&
WAVE_LOOP_BACK
)
gus_write_addr
(
0x0a
,
sample_ptrs
[
sample
]
+
samples
[
sample
].
len
-
voices
[
voice
].
offset_pending
,
is16bits
);
/* Sample
...
...
@@ -1515,13 +1556,13 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
if
(
samples
[
sample
].
mode
&
WAVE_LOOPING
)
{
mode
|=
0x08
;
/*
* Looping on
mode
|=
0x08
;
/*
* Looping on
*/
if
(
samples
[
sample
].
mode
&
WAVE_BIDIR_LOOP
)
mode
|=
0x10
;
/*
* Bidirectional looping on
mode
|=
0x10
;
/*
* Bidirectional looping on
*/
if
(
samples
[
sample
].
mode
&
WAVE_LOOP_BACK
)
...
...
@@ -1532,35 +1573,35 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
mode
|=
0x40
;
}
gus_write_addr
(
0x02
,
sample_ptrs
[
sample
]
+
samples
[
sample
].
loop_start
,
is16bits
);
/*
* Loop
* start
* location
gus_write_addr
(
0x02
,
sample_ptrs
[
sample
]
+
samples
[
sample
].
loop_start
,
is16bits
);
/*
* Loop
* start
* location
*/
gus_write_addr
(
0x04
,
sample_ptrs
[
sample
]
+
samples
[
sample
].
loop_end
,
is16bits
);
/*
* Loop
* end
* location
gus_write_addr
(
0x04
,
sample_ptrs
[
sample
]
+
samples
[
sample
].
loop_end
,
is16bits
);
/*
* Loop
* end
* location
*/
}
else
{
mode
|=
0x20
;
/*
* Loop irq at the end
mode
|=
0x20
;
/*
* Loop irq at the end
*/
voices
[
voice
].
loop_irq_mode
=
LMODE_FINISH
;
/*
voices
[
voice
].
loop_irq_mode
=
LMODE_FINISH
;
/*
* Ramp it down at
* the * end
* the * end
*/
voices
[
voice
].
loop_irq_parm
=
1
;
gus_write_addr
(
0x02
,
sample_ptrs
[
sample
],
is16bits
);
/*
* Loop start
* location
gus_write_addr
(
0x02
,
sample_ptrs
[
sample
],
is16bits
);
/*
* Loop start
* location
*/
gus_write_addr
(
0x04
,
sample_ptrs
[
sample
]
+
samples
[
sample
].
len
-
1
,
is16bits
);
/*
* Loop
* end
* location
gus_write_addr
(
0x04
,
sample_ptrs
[
sample
]
+
samples
[
sample
].
len
-
1
,
is16bits
);
/*
* Loop
* end
* location
*/
}
gus_voice_freq
(
freq
);
...
...
@@ -1571,9 +1612,9 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
return
0
;
}
/*
/*
* * New guswave_start_note by Andrew J. Robinson attempts to minimize
* clicking * when the note playing on the voice is changed. It uses volume
* clicking * when the note playing on the voice is changed. It uses volume
* ramping. */
static
int
...
...
@@ -1589,26 +1630,31 @@ guswave_start_note (int dev, int voice, int note_num, int volume)
if
(
voices
[
voice
].
volume_irq_mode
==
VMODE_START_NOTE
)
voices
[
voice
].
volume_pending
=
volume
;
else
ret_val
=
guswave_start_note2
(
dev
,
voice
,
note_num
,
volume
);
{
RESTORE_INTR
(
flags
);
ret_val
=
guswave_start_note2
(
dev
,
voice
,
note_num
,
volume
);
}
}
else
{
gus_select_voice
(
voice
);
mode
=
gus_read8
(
0x00
);
if
(
mode
&
0x20
)
gus_write8
(
0x00
,
mode
&
0xdf
);
/* No interrupt! */
gus_select_voice
(
voice
);
mode
=
gus_read8
(
0x00
);
if
(
mode
&
0x20
)
gus_write8
(
0x00
,
mode
&
0xdf
);
/* No interrupt! */
voices
[
voice
].
offset_pending
=
0
;
voices
[
voice
].
kill_pending
=
0
;
voices
[
voice
].
volume_irq_mode
=
0
;
voices
[
voice
].
loop_irq_mode
=
0
;
voices
[
voice
].
offset_pending
=
0
;
voices
[
voice
].
kill_pending
=
0
;
voices
[
voice
].
volume_irq_mode
=
0
;
voices
[
voice
].
loop_irq_mode
=
0
;
if
(
voices
[
voice
].
sample_pending
>=
0
)
{
guswave_set_instr
(
voices
[
voice
].
dev_pending
,
voice
,
voices
[
voice
].
sample_pending
);
voices
[
voice
].
sample_pending
=
-
1
;
}
if
(
voices
[
voice
].
sample_pending
>=
0
)
{
RESTORE_INTR
(
flags
);
guswave_set_instr
(
voices
[
voice
].
dev_pending
,
voice
,
voices
[
voice
].
sample_pending
);
voices
[
voice
].
sample_pending
=
-
1
;
DISABLE_INTR
(
flags
);
}
if
((
mode
&
0x01
)
||
((
gus_read16
(
0x09
)
>>
4
)
<
2065
))
{
...
...
@@ -1623,11 +1669,11 @@ guswave_start_note (int dev, int voice, int note_num, int volume)
gus_rampoff
();
gus_ramp_range
(
2000
,
4065
);
gus_ramp_rate
(
0
,
63
);
/* Fastest possible rate */
gus_ramp_rate
(
0
,
63
);
/* Fastest possible rate */
gus_rampon
(
0x20
|
0x40
);
/* Ramp down, once, irq */
RESTORE_INTR
(
flags
);
}
}
RESTORE_INTR
(
flags
);
return
ret_val
;
}
...
...
@@ -1685,10 +1731,10 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
unsigned
long
blk_size
,
blk_end
,
left
,
src_offs
,
target
;
sizeof_patch
=
(
long
)
&
patch
.
data
[
0
]
-
(
long
)
&
patch
;
/*
sizeof_patch
=
(
long
)
&
patch
.
data
[
0
]
-
(
long
)
&
patch
;
/*
* Size of
* the header
* * info
* * info
*/
if
(
format
!=
GUS_PATCH
)
...
...
@@ -1711,7 +1757,7 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
return
RET_ERROR
(
ENOSPC
);
}
/*
/*
* Copy the header from user space but ignore the first bytes which have
* been transferred already.
*/
...
...
@@ -1754,15 +1800,15 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
}
}
free_mem_ptr
=
(
free_mem_ptr
+
31
)
&
~
31
;
/*
* Alignment 32 bytes
free_mem_ptr
=
(
free_mem_ptr
+
31
)
&
~
31
;
/*
* Alignment 32 bytes
*/
#define GUS_BANK_SIZE (256*1024)
if
(
patch
.
mode
&
WAVE_16_BITS
)
{
/*
/*
* 16 bit samples must fit one 256k bank.
*/
if
(
patch
.
len
>=
GUS_BANK_SIZE
)
...
...
@@ -1774,16 +1820,16 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
if
((
free_mem_ptr
/
GUS_BANK_SIZE
)
!=
((
free_mem_ptr
+
patch
.
len
)
/
GUS_BANK_SIZE
))
{
unsigned
long
tmp_mem
=
/*
* Align to 256K*N
unsigned
long
tmp_mem
=
/*
* Align to 256K*N
*/
((
free_mem_ptr
/
GUS_BANK_SIZE
)
+
1
)
*
GUS_BANK_SIZE
;
if
((
tmp_mem
+
patch
.
len
)
>
gus_mem_size
)
return
RET_ERROR
(
ENOSPC
);
free_mem_ptr
=
tmp_mem
;
/*
* This leaves unusable memory
free_mem_ptr
=
tmp_mem
;
/*
* This leaves unusable memory
*/
}
}
...
...
@@ -1793,8 +1839,8 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
sample_ptrs
[
free_sample
]
=
free_mem_ptr
;
/*
* Tremolo is not possible with envelopes
/*
* Tremolo is not possible with envelopes
*/
if
(
patch
.
mode
&
WAVE_ENVELOPES
)
...
...
@@ -1802,14 +1848,14 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
memcpy
((
char
*
)
&
samples
[
free_sample
],
&
patch
,
sizeof_patch
);
/*
/*
* Link this_one sample to the list of samples for patch 'instr'.
*/
samples
[
free_sample
].
key
=
patch_table
[
instr
];
patch_table
[
instr
]
=
free_sample
;
/*
/*
* Use DMA to transfer the wave data to the DRAM
*/
...
...
@@ -1817,22 +1863,22 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
src_offs
=
0
;
target
=
free_mem_ptr
;
while
(
left
)
/*
* Not all moved
while
(
left
)
/*
* Not all moved
*/
{
blk_size
=
sound_buffsizes
[
gus_devnum
];
if
(
blk_size
>
left
)
blk_size
=
left
;
/*
/*
* DMA cannot cross 256k bank boundaries. Check for that.
*/
blk_end
=
target
+
blk_size
;
if
((
target
>>
18
)
!=
(
blk_end
>>
18
))
{
/*
* Have to split the block
{
/*
* Have to split the block
*/
blk_end
&=
~
(
256
*
1024
-
1
);
...
...
@@ -1840,7 +1886,7 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
}
#if defined(GUS_NO_DMA) || defined(GUS_PATCH_NO_DMA)
/*
/*
* For some reason the DMA is not possible. We have to use PIO.
*/
{
...
...
@@ -1853,20 +1899,20 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
if
(
patch
.
mode
&
WAVE_UNSIGNED
)
if
(
!
(
patch
.
mode
&
WAVE_16_BITS
)
||
(
i
&
0x01
))
data
^=
0x80
;
/*
* Convert to signed
data
^=
0x80
;
/*
* Convert to signed
*/
gus_poke
(
target
+
i
,
data
);
}
}
#else
/*
* * * GUS_NO_DMA */
#else
/*
* * * GUS_NO_DMA */
{
unsigned
long
address
,
hold_address
;
unsigned
char
dma_command
;
unsigned
long
flags
;
/*
/*
* OK, move now. First in and then out.
*/
...
...
@@ -1875,13 +1921,13 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
blk_size
);
DISABLE_INTR
(
flags
);
/******** INTERRUPTS DISABLED NOW ********/
gus_write8
(
0x41
,
0
);
/*
* Disable GF1 DMA
gus_write8
(
0x41
,
0
);
/*
* Disable GF1 DMA
*/
DMAbuf_start_dma
(
gus_devnum
,
snd_raw_buf_phys
[
gus_devnum
][
0
],
blk_size
,
DMA_MODE_WRITE
);
/*
/*
* Set the DRAM address for the wave data
*/
...
...
@@ -1895,35 +1941,35 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
address
|=
(
hold_address
&
0x000c0000L
);
}
gus_write16
(
0x42
,
(
address
>>
4
)
&
0xffff
);
/*
* DRAM DMA address
gus_write16
(
0x42
,
(
address
>>
4
)
&
0xffff
);
/*
* DRAM DMA address
*/
/*
/*
* Start the DMA transfer
*/
dma_command
=
0x21
;
/*
* IRQ enable, DMA start
dma_command
=
0x21
;
/*
* IRQ enable, DMA start
*/
if
(
patch
.
mode
&
WAVE_UNSIGNED
)
dma_command
|=
0x80
;
/*
* Invert MSB
dma_command
|=
0x80
;
/*
* Invert MSB
*/
if
(
patch
.
mode
&
WAVE_16_BITS
)
dma_command
|=
0x40
;
/*
* 16 bit _DATA_
dma_command
|=
0x40
;
/*
* 16 bit _DATA_
*/
if
(
sound_dsp_dmachan
[
gus_devnum
]
>
3
)
dma_command
|=
0x04
;
/*
* 16 bit DMA channel
dma_command
|=
0x04
;
/*
* 16 bit DMA channel
*/
gus_write8
(
0x41
,
dma_command
);
/*
* Let's go luteet (=bugs)
gus_write8
(
0x41
,
dma_command
);
/*
* Let's go luteet (=bugs)
*/
/*
/*
* Sleep here until the DRAM DMA done interrupt is served
*/
active_device
=
GUS_DEV_WAVE
;
...
...
@@ -1933,10 +1979,10 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
printk
(
"GUS: DMA Transfer timed out
\n
"
);
RESTORE_INTR
(
flags
);
}
#endif
/*
* * * GUS_NO_DMA */
#endif
/*
* * * GUS_NO_DMA */
/*
/*
* Now the next part
*/
...
...
@@ -1944,8 +1990,8 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
src_offs
+=
blk_size
;
target
+=
blk_size
;
gus_write8
(
0x41
,
0
);
/*
* Stop DMA
gus_write8
(
0x41
,
0
);
/*
* Stop DMA
*/
}
...
...
@@ -1991,8 +2037,8 @@ guswave_hw_control (int dev, unsigned char *event)
case
_GUS_VOICEON
:
DISABLE_INTR
(
flags
);
gus_select_voice
(
voice
);
p1
&=
~
0x20
;
/*
* Disable intr
p1
&=
~
0x20
;
/*
* Disable intr
*/
gus_voice_on
(
p1
);
RESTORE_INTR
(
flags
);
...
...
@@ -2006,17 +2052,14 @@ guswave_hw_control (int dev, unsigned char *event)
break
;
case
_GUS_VOICEFADE
:
DISABLE_INTR
(
flags
);
gus_select_voice
(
voice
);
gus_voice_fade
(
voice
);
RESTORE_INTR
(
flags
);
break
;
case
_GUS_VOICEMODE
:
DISABLE_INTR
(
flags
);
gus_select_voice
(
voice
);
p1
&=
~
0x20
;
/*
* Disable intr
p1
&=
~
0x20
;
/*
* Disable intr
*/
gus_voice_mode
(
p1
);
RESTORE_INTR
(
flags
);
...
...
@@ -2043,8 +2086,8 @@ guswave_hw_control (int dev, unsigned char *event)
RESTORE_INTR
(
flags
);
break
;
case
_GUS_VOICEVOL2
:
/*
* Just update the voice value
case
_GUS_VOICEVOL2
:
/*
* Just update the voice value
*/
voices
[
voice
].
initial_volume
=
voices
[
voice
].
current_volume
=
p1
;
...
...
@@ -2052,8 +2095,8 @@ guswave_hw_control (int dev, unsigned char *event)
case
_GUS_RAMPRANGE
:
if
(
voices
[
voice
].
mode
&
WAVE_ENVELOPES
)
break
;
/*
* NO-NO
break
;
/*
* NO-NO
*/
DISABLE_INTR
(
flags
);
gus_select_voice
(
voice
);
...
...
@@ -2063,8 +2106,8 @@ guswave_hw_control (int dev, unsigned char *event)
case
_GUS_RAMPRATE
:
if
(
voices
[
voice
].
mode
&
WAVE_ENVELOPES
)
break
;
/*
* NO-NO
break
;
/*
* NO-NO
*/
DISABLE_INTR
(
flags
);
gus_select_voice
(
voice
);
...
...
@@ -2074,13 +2117,13 @@ guswave_hw_control (int dev, unsigned char *event)
case
_GUS_RAMPMODE
:
if
(
voices
[
voice
].
mode
&
WAVE_ENVELOPES
)
break
;
/*
* NO-NO
break
;
/*
* NO-NO
*/
DISABLE_INTR
(
flags
);
gus_select_voice
(
voice
);
p1
&=
~
0x20
;
/*
* Disable intr
p1
&=
~
0x20
;
/*
* Disable intr
*/
gus_ramp_mode
(
p1
);
RESTORE_INTR
(
flags
);
...
...
@@ -2088,13 +2131,13 @@ guswave_hw_control (int dev, unsigned char *event)
case
_GUS_RAMPON
:
if
(
voices
[
voice
].
mode
&
WAVE_ENVELOPES
)
break
;
/*
* NO-NO
break
;
/*
* NO-NO
*/
DISABLE_INTR
(
flags
);
gus_select_voice
(
voice
);
p1
&=
~
0x20
;
/*
* Disable intr
p1
&=
~
0x20
;
/*
* Disable intr
*/
gus_rampon
(
p1
);
RESTORE_INTR
(
flags
);
...
...
@@ -2102,8 +2145,8 @@ guswave_hw_control (int dev, unsigned char *event)
case
_GUS_RAMPOFF
:
if
(
voices
[
voice
].
mode
&
WAVE_ENVELOPES
)
break
;
/*
* NO-NO
break
;
/*
* NO-NO
*/
DISABLE_INTR
(
flags
);
gus_select_voice
(
voice
);
...
...
@@ -2212,8 +2255,8 @@ gus_sampling_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
return
gus_sampling_bits
;
return
IOCTL_OUT
(
arg
,
gus_sampling_bits
);
case
SOUND_PCM_WRITE_FILTER
:
/*
* NOT YET IMPLEMENTED
case
SOUND_PCM_WRITE_FILTER
:
/*
* NOT YET IMPLEMENTED
*/
return
IOCTL_OUT
(
arg
,
RET_ERROR
(
EINVAL
));
break
;
...
...
@@ -2255,11 +2298,11 @@ gus_sampling_open (int dev, int mode)
pcm_active
=
0
;
pcm_opened
=
1
;
if
(
mode
&
OPEN_READ
)
{
recording_active
=
1
;
set_input_volumes
();
}
if
(
mode
&
OPEN_READ
)
{
recording_active
=
1
;
set_input_volumes
();
}
return
0
;
}
...
...
@@ -2273,7 +2316,7 @@ gus_sampling_close (int dev)
active_device
=
0
;
if
(
recording_active
)
set_input_volumes
();
set_input_volumes
();
recording_active
=
0
;
}
...
...
@@ -2313,14 +2356,14 @@ play_next_pcm_block (void)
for
(
chn
=
0
;
chn
<
gus_sampling_channels
;
chn
++
)
{
mode
[
chn
]
=
0x00
;
ramp_mode
[
chn
]
=
0x03
;
/*
* Ramping and rollover off
ramp_mode
[
chn
]
=
0x03
;
/*
* Ramping and rollover off
*/
if
(
chn
==
0
)
{
mode
[
chn
]
|=
0x20
;
/*
* Loop irq
mode
[
chn
]
|=
0x20
;
/*
* Loop irq
*/
voices
[
chn
].
loop_irq_mode
=
LMODE_PCM
;
}
...
...
@@ -2328,8 +2371,8 @@ play_next_pcm_block (void)
if
(
gus_sampling_bits
!=
8
)
{
is16bits
=
1
;
mode
[
chn
]
|=
0x04
;
/*
* 16 bit data
mode
[
chn
]
|=
0x04
;
/*
* 16 bit data
*/
}
else
...
...
@@ -2338,22 +2381,22 @@ play_next_pcm_block (void)
dram_loc
=
this_one
*
pcm_bsize
;
dram_loc
+=
chn
*
pcm_banksize
;
if
(
this_one
==
(
pcm_nblk
-
1
))
/*
* Last of the DRAM buffers
if
(
this_one
==
(
pcm_nblk
-
1
))
/*
* Last of the DRAM buffers
*/
{
mode
[
chn
]
|=
0x08
;
/*
* Enable loop
mode
[
chn
]
|=
0x08
;
/*
* Enable loop
*/
ramp_mode
[
chn
]
=
0x03
;
/*
* Disable rollover
ramp_mode
[
chn
]
=
0x03
;
/*
* Disable rollover
*/
}
else
{
if
(
chn
==
0
)
ramp_mode
[
chn
]
=
0x04
;
/*
* Enable rollover bit
ramp_mode
[
chn
]
=
0x04
;
/*
* Enable rollover bit
*/
}
...
...
@@ -2362,89 +2405,89 @@ play_next_pcm_block (void)
gus_voice_freq
(
speed
);
if
(
gus_sampling_channels
==
1
)
gus_voice_balance
(
7
);
/*
* mono
gus_voice_balance
(
7
);
/*
* mono
*/
else
if
(
chn
==
0
)
gus_voice_balance
(
0
);
/*
* left
gus_voice_balance
(
0
);
/*
* left
*/
else
gus_voice_balance
(
15
);
/*
* right
gus_voice_balance
(
15
);
/*
* right
*/
if
(
!
pcm_active
)
/*
* Voice not started yet
if
(
!
pcm_active
)
/*
* Voice not started yet
*/
{
/*
/*
* The playback was not started yet (or there has been a pause).
* Start the voice (again) and ask for a rollover irq at the end of
* this_one block. If this_one one is last of the buffers, use just
* the normal loop with irq.
*/
gus_voice_off
();
/*
* It could already be running
gus_voice_off
();
/*
* It could already be running
*/
gus_rampoff
();
gus_voice_volume
(
1530
+
(
25
*
gus_pcm_volume
));
gus_ramp_range
(
65
,
1530
+
(
25
*
gus_pcm_volume
));
gus_write_addr
(
0x0a
,
dram_loc
,
is16bits
);
/*
* Starting position
gus_write_addr
(
0x0a
,
dram_loc
,
is16bits
);
/*
* Starting position
*/
gus_write_addr
(
0x02
,
chn
*
pcm_banksize
,
is16bits
);
/*
* Loop start
* location
gus_write_addr
(
0x02
,
chn
*
pcm_banksize
,
is16bits
);
/*
* Loop start
* location
*/
if
(
chn
!=
0
)
gus_write_addr
(
0x04
,
pcm_banksize
+
(
pcm_bsize
*
pcm_nblk
),
is16bits
);
/*
* Loop end location
is16bits
);
/*
* Loop end location
*/
}
if
(
chn
==
0
)
gus_write_addr
(
0x04
,
dram_loc
+
pcm_datasize
[
this_one
],
is16bits
);
/*
* Loop
* end
* location
gus_write_addr
(
0x04
,
dram_loc
+
pcm_datasize
[
this_one
],
is16bits
);
/*
* Loop
* end
* location
*/
else
mode
[
chn
]
|=
0x08
;
/*
* Enable loop
mode
[
chn
]
|=
0x08
;
/*
* Enable loop
*/
if
(
pcm_datasize
[
this_one
]
!=
pcm_bsize
)
{
/*
* Incomplete block. Possibly the last one.
/*
* Incomplete block. Possibly the last one.
*/
if
(
chn
==
0
)
{
mode
[
chn
]
&=
~
0x08
;
/*
* Disable loop
mode
[
chn
]
&=
~
0x08
;
/*
* Disable loop
*/
mode
[
chn
]
|=
0x20
;
/*
* Enable loop IRQ
mode
[
chn
]
|=
0x20
;
/*
* Enable loop IRQ
*/
voices
[
0
].
loop_irq_mode
=
LMODE_PCM_STOP
;
ramp_mode
[
chn
]
=
0x03
;
/*
* No rollover bit
ramp_mode
[
chn
]
=
0x03
;
/*
* No rollover bit
*/
}
else
{
gus_write_addr
(
0x04
,
dram_loc
+
pcm_datasize
[
this_one
],
is16bits
);
/*
* Loop
* end
* location
gus_write_addr
(
0x04
,
dram_loc
+
pcm_datasize
[
this_one
],
is16bits
);
/*
* Loop
* end
* location
*/
mode
[
chn
]
&=
~
0x08
;
/*
* Disable loop
mode
[
chn
]
&=
~
0x08
;
/*
* Disable loop
*/
}
}
...
...
@@ -2468,11 +2511,11 @@ static void
gus_transfer_output_block
(
int
dev
,
unsigned
long
buf
,
int
total_count
,
int
intrflag
,
int
chn
)
{
/*
/*
* This routine transfers one block of audio data to the DRAM. In mono mode
* it's called just once. When in stereo mode, this_one routine is called
* once for both channels.
*
*
* The left/mono channel data is transferred to the beginning of dram and the
* right data to the area pointed by gus_page_size.
*/
...
...
@@ -2499,8 +2542,8 @@ gus_transfer_output_block (int dev, unsigned long buf,
else
this_one
=
pcm_current_block
;
gus_write8
(
0x41
,
0
);
/*
* Disable GF1 DMA
gus_write8
(
0x41
,
0
);
/*
* Disable GF1 DMA
*/
DMAbuf_start_dma
(
dev
,
buf
+
(
chn
*
count
),
count
,
DMA_MODE_WRITE
);
...
...
@@ -2515,38 +2558,38 @@ gus_transfer_output_block (int dev, unsigned long buf,
address
|=
(
hold_address
&
0x000c0000L
);
}
gus_write16
(
0x42
,
(
address
>>
4
)
&
0xffff
);
/*
* DRAM DMA address
gus_write16
(
0x42
,
(
address
>>
4
)
&
0xffff
);
/*
* DRAM DMA address
*/
dma_command
=
0x21
;
/*
* IRQ enable, DMA start
dma_command
=
0x21
;
/*
* IRQ enable, DMA start
*/
if
(
gus_sampling_bits
!=
8
)
dma_command
|=
0x40
;
/*
* 16 bit _DATA_
dma_command
|=
0x40
;
/*
* 16 bit _DATA_
*/
else
dma_command
|=
0x80
;
/*
* Invert MSB
dma_command
|=
0x80
;
/*
* Invert MSB
*/
if
(
sound_dsp_dmachan
[
dev
]
>
3
)
dma_command
|=
0x04
;
/*
* 16 bit DMA channel
dma_command
|=
0x04
;
/*
* 16 bit DMA channel
*/
gus_write8
(
0x41
,
dma_command
);
/*
* Kick on
gus_write8
(
0x41
,
dma_command
);
/*
* Kick on
*/
if
(
chn
==
(
gus_sampling_channels
-
1
))
/*
* Last channel
if
(
chn
==
(
gus_sampling_channels
-
1
))
/*
* Last channel
*/
{
/*
* Last (right or mono) channel data
/*
* Last (right or mono) channel data
*/
active_device
=
GUS_DEV_PCM_DONE
;
if
(
!
pcm_active
&&
(
pcm_qlen
>
2
||
count
<
pcm_bsize
))
...
...
@@ -2554,9 +2597,9 @@ gus_transfer_output_block (int dev, unsigned long buf,
play_next_pcm_block
();
}
}
else
/*
* * * Left channel data. The right channel
* is * * * transferred after DMA interrupt */
else
/*
* * * Left channel data. The right channel
* is * * * transferred after DMA interrupt */
active_device
=
GUS_DEV_PCM_CONTINUE
;
RESTORE_INTR
(
flags
);
...
...
@@ -2584,20 +2627,20 @@ gus_sampling_start_input (int dev, unsigned long buf, int count,
DMAbuf_start_dma
(
dev
,
buf
,
count
,
DMA_MODE_READ
);
mode
=
0xa0
;
/*
* DMA IRQ enable, invert MSB
mode
=
0xa0
;
/*
* DMA IRQ enable, invert MSB
*/
if
(
sound_dsp_dmachan
[
dev
]
>
3
)
mode
|=
0x04
;
/*
* 16 bit DMA channel
mode
|=
0x04
;
/*
* 16 bit DMA channel
*/
if
(
gus_sampling_channels
>
1
)
mode
|=
0x02
;
/*
* Stereo
mode
|=
0x02
;
/*
* Stereo
*/
mode
|=
0x01
;
/*
* DMA enable
mode
|=
0x01
;
/*
* DMA enable
*/
gus_write8
(
0x49
,
mode
);
...
...
@@ -2612,8 +2655,8 @@ gus_sampling_prepare_for_input (int dev, int bsize, int bcount)
rate
=
(
9878400
/
(
gus_sampling_speed
+
2
))
/
16
;
gus_write8
(
0x48
,
rate
&
0xff
);
/*
* Set sampling frequency
gus_write8
(
0x48
,
rate
&
0xff
);
/*
* Set sampling frequency
*/
if
(
gus_sampling_bits
!=
8
)
...
...
@@ -2716,6 +2759,7 @@ gus_copy_from_user (int dev, char *localbuf, int localoffs,
static
struct
audio_operations
gus_sampling_operations
=
{
"Gravis UltraSound"
,
NEEDS_RESTART
,
gus_sampling_open
,
gus_sampling_close
,
gus_sampling_output_block
,
...
...
@@ -2745,6 +2789,7 @@ guswave_bender (int dev, int voice, int value)
gus_voice_freq
(
freq
);
RESTORE_INTR
(
flags
);
}
#endif
static
int
...
...
@@ -2776,8 +2821,8 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
while
(
ptr
>=
0
&&
ptr
<
free_sample
)
{
rec
->
data
.
data8
[
i
]
++
;
ptr
=
samples
[
ptr
].
key
;
/*
* Follow link
ptr
=
samples
[
ptr
].
key
;
/*
* Follow link
*/
}
}
...
...
@@ -2793,8 +2838,8 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
while
(
ptr
>=
0
&&
ptr
<
free_sample
)
{
rec
->
data
.
data32
[
n
++
]
=
ptr
;
ptr
=
samples
[
ptr
].
key
;
/*
* Follow link
ptr
=
samples
[
ptr
].
key
;
/*
* Follow link
*/
}
}
...
...
@@ -2815,11 +2860,11 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
pat
=
(
struct
patch_info
*
)
rec
->
data
.
data8
;
pat
->
key
=
GUS_PATCH
;
/*
* Restore patch type
pat
->
key
=
GUS_PATCH
;
/*
* Restore patch type
*/
rec
->
parm1
=
sample_ptrs
[
ptr
];
/*
* DRAM address
rec
->
parm1
=
sample_ptrs
[
ptr
];
/*
* DRAM address
*/
rec
->
parm2
=
sizeof
(
struct
patch_info
);
}
...
...
@@ -2836,13 +2881,13 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
pat
=
(
struct
patch_info
*
)
rec
->
data
.
data8
;
if
(
pat
->
len
>
samples
[
ptr
].
len
)
/*
* Cannot expand sample
if
(
pat
->
len
>
samples
[
ptr
].
len
)
/*
* Cannot expand sample
*/
return
RET_ERROR
(
EINVAL
);
pat
->
key
=
samples
[
ptr
].
key
;
/*
* Ensure the link is correct
pat
->
key
=
samples
[
ptr
].
key
;
/*
* Ensure the link is correct
*/
memcpy
((
char
*
)
&
samples
[
ptr
],
rec
->
data
.
data8
,
...
...
@@ -2853,8 +2898,8 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
return
0
;
break
;
case
PM_READ_PATCH
:
/*
* Returns a block of wave data from the DRAM
case
PM_READ_PATCH
:
/*
* Returns a block of wave data from the DRAM
*/
{
int
sample
=
rec
->
parm1
;
...
...
@@ -2866,12 +2911,12 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
return
RET_ERROR
(
EINVAL
);
if
(
offs
<
0
||
offs
>=
samples
[
sample
].
len
)
return
RET_ERROR
(
EINVAL
);
/*
* Invalid offset
return
RET_ERROR
(
EINVAL
);
/*
* Invalid offset
*/
n
=
samples
[
sample
].
len
-
offs
;
/*
* Nr of bytes left
n
=
samples
[
sample
].
len
-
offs
;
/*
* Nr of bytes left
*/
if
(
l
>
n
)
...
...
@@ -2881,25 +2926,25 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
l
=
sizeof
(
rec
->
data
.
data8
);
if
(
l
<=
0
)
return
RET_ERROR
(
EINVAL
);
/*
* Was there a bug?
return
RET_ERROR
(
EINVAL
);
/*
* Was there a bug?
*/
offs
+=
sample_ptrs
[
sample
];
/*
* Begin offsess + offset to DRAM
offs
+=
sample_ptrs
[
sample
];
/*
* Begin offsess + offset to DRAM
*/
for
(
n
=
0
;
n
<
l
;
n
++
)
rec
->
data
.
data8
[
n
]
=
gus_peek
(
offs
++
);
rec
->
parm1
=
n
;
/*
* Nr of bytes copied
rec
->
parm1
=
n
;
/*
* Nr of bytes copied
*/
}
return
0
;
break
;
case
PM_WRITE_PATCH
:
/*
* Writes a block of wave data to the DRAM
case
PM_WRITE_PATCH
:
/*
* Writes a block of wave data to the DRAM
*/
{
int
sample
=
rec
->
parm1
;
...
...
@@ -2911,12 +2956,12 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
return
RET_ERROR
(
EINVAL
);
if
(
offs
<
0
||
offs
>=
samples
[
sample
].
len
)
return
RET_ERROR
(
EINVAL
);
/*
* Invalid offset
return
RET_ERROR
(
EINVAL
);
/*
* Invalid offset
*/
n
=
samples
[
sample
].
len
-
offs
;
/*
* Nr of bytes left
n
=
samples
[
sample
].
len
-
offs
;
/*
* Nr of bytes left
*/
if
(
l
>
n
)
...
...
@@ -2926,18 +2971,18 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
l
=
sizeof
(
rec
->
data
.
data8
);
if
(
l
<=
0
)
return
RET_ERROR
(
EINVAL
);
/*
* Was there a bug?
return
RET_ERROR
(
EINVAL
);
/*
* Was there a bug?
*/
offs
+=
sample_ptrs
[
sample
];
/*
* Begin offsess + offset to DRAM
offs
+=
sample_ptrs
[
sample
];
/*
* Begin offsess + offset to DRAM
*/
for
(
n
=
0
;
n
<
l
;
n
++
)
gus_poke
(
offs
++
,
rec
->
data
.
data8
[
n
]);
rec
->
parm1
=
n
;
/*
* Nr of bytes copied
rec
->
parm1
=
n
;
/*
* Nr of bytes copied
*/
}
return
0
;
...
...
@@ -2968,6 +3013,7 @@ static struct synth_operations guswave_operations =
guswave_aftertouch
,
guswave_controller
,
guswave_panning
,
guswave_volume_method
,
guswave_patchmgr
,
#ifdef FUTURE_VERSION
guswave_bender
...
...
@@ -2975,39 +3021,43 @@ static struct synth_operations guswave_operations =
};
static
void
set_input_volumes
(
void
)
set_input_volumes
(
void
)
{
unsigned
long
flags
;
unsigned
char
mask
=
0xff
&
~
0x06
;
/* Just line out enabled */
unsigned
long
flags
;
unsigned
char
mask
=
0xff
&
~
0x06
;
/* Just line out enabled */
DISABLE_INTR
(
flags
);
DISABLE_INTR
(
flags
);
/*
*
Enable channels having vol > 10%
*
Note! bit 0x01 means line in DISABLED while 0x04 means
*
mic in ENABLED.
/*
*
Enable channels having vol > 10%
*
Note! bit 0x01 means line in DISABLED while 0x04 means
*
mic in ENABLED.
*/
if
(
gus_line_vol
>
10
)
mask
&=
~
0x01
;
if
(
gus_mic_vol
>
10
)
mask
|=
0x04
;
if
(
gus_line_vol
>
10
)
mask
&=
~
0x01
;
if
(
gus_mic_vol
>
10
)
mask
|=
0x04
;
if
(
recording_active
)
{
/*
*
Disable channel, if not selected for recording
if
(
recording_active
)
{
/*
*
Disable channel, if not selected for recording
*/
if
(
!
(
gus_recmask
&
SOUND_MASK_LINE
))
mask
|=
0x01
;
if
(
!
(
gus_recmask
&
SOUND_MASK_MIC
))
mask
&=
~
0x04
;
}
if
(
!
(
gus_recmask
&
SOUND_MASK_LINE
))
mask
|=
0x01
;
if
(
!
(
gus_recmask
&
SOUND_MASK_MIC
))
mask
&=
~
0x04
;
}
mix_image
&=
~
0x07
;
mix_image
|=
mask
&
0x07
;
OUTB
(
mix_image
,
u_Mixer
);
mix_image
&=
~
0x07
;
mix_image
|=
mask
&
0x07
;
OUTB
(
mix_image
,
u_Mixer
);
RESTORE_INTR
(
flags
);
RESTORE_INTR
(
flags
);
}
static
int
gus_mixer_ioctl
(
int
dev
,
unsigned
int
cmd
,
unsigned
int
arg
)
int
gus_
default_
mixer_ioctl
(
int
dev
,
unsigned
int
cmd
,
unsigned
int
arg
)
{
#define MIX_DEVS (SOUND_MASK_MIC|SOUND_MASK_LINE| \
SOUND_MASK_SYNTH|SOUND_MASK_PCM)
...
...
@@ -3017,9 +3067,9 @@ gus_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
switch
(
cmd
&
0xff
)
{
case
SOUND_MIXER_RECSRC
:
gus_recmask
=
IOCTL_IN
(
arg
)
&
MIX_DEVS
;
if
(
!
(
gus_recmask
&
(
SOUND_MASK_MIC
|
SOUND_MASK_LINE
)))
gus_recmask
=
SOUND_MASK_MIC
;
gus_recmask
=
IOCTL_IN
(
arg
)
&
MIX_DEVS
;
if
(
!
(
gus_recmask
&
(
SOUND_MASK_MIC
|
SOUND_MASK_LINE
)))
gus_recmask
=
SOUND_MASK_MIC
;
/* Note! Input volumes are updated during next open for recording */
return
IOCTL_OUT
(
arg
,
gus_recmask
);
break
;
...
...
@@ -3027,10 +3077,13 @@ gus_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
case
SOUND_MIXER_MIC
:
{
int
vol
=
IOCTL_IN
(
arg
)
&
0xff
;
if
(
vol
<
0
)
vol
=
0
;
if
(
vol
>
100
)
vol
=
100
;
if
(
vol
<
0
)
vol
=
0
;
if
(
vol
>
100
)
vol
=
100
;
gus_mic_vol
=
vol
;
set_input_volumes
();
set_input_volumes
();
return
IOCTL_OUT
(
arg
,
vol
|
(
vol
<<
8
));
}
break
;
...
...
@@ -3038,27 +3091,30 @@ gus_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
case
SOUND_MIXER_LINE
:
{
int
vol
=
IOCTL_IN
(
arg
)
&
0xff
;
if
(
vol
<
0
)
vol
=
0
;
if
(
vol
>
100
)
vol
=
100
;
if
(
vol
<
0
)
vol
=
0
;
if
(
vol
>
100
)
vol
=
100
;
gus_line_vol
=
vol
;
set_input_volumes
();
set_input_volumes
();
return
IOCTL_OUT
(
arg
,
vol
|
(
vol
<<
8
));
}
break
;
case
SOUND_MIXER_PCM
:
gus_pcm_volume
=
IOCTL_IN
(
arg
)
&
0xff
;
if
(
gus_pcm_volume
<
0
)
gus_pcm_volume
=
0
;
if
(
gus_pcm_volume
>
100
)
gus_pcm_volume
=
100
;
gus_sampling_update_volume
();
return
IOCTL_OUT
(
arg
,
gus_pcm_volume
|
(
gus_pcm_volume
<<
8
));
gus_pcm_volume
=
IOCTL_IN
(
arg
)
&
0xff
;
if
(
gus_pcm_volume
<
0
)
gus_pcm_volume
=
0
;
if
(
gus_pcm_volume
>
100
)
gus_pcm_volume
=
100
;
gus_sampling_update_volume
();
return
IOCTL_OUT
(
arg
,
gus_pcm_volume
|
(
gus_pcm_volume
<<
8
));
break
;
case
SOUND_MIXER_SYNTH
:
{
int
voice
;
int
voice
;
gus_wave_volume
=
IOCTL_IN
(
arg
)
&
0xff
;
...
...
@@ -3069,9 +3125,9 @@ gus_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
if
(
active_device
==
GUS_DEV_WAVE
)
for
(
voice
=
0
;
voice
<
nr_voices
;
voice
++
)
dynamic_volume_change
(
voice
);
/*
dynamic_volume_change
(
voice
);
/*
* Apply the new
* volume
* volume
*/
return
IOCTL_OUT
(
arg
,
gus_wave_volume
|
(
gus_wave_volume
<<
8
));
...
...
@@ -3082,8 +3138,8 @@ gus_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
return
RET_ERROR
(
EINVAL
);
}
else
switch
(
cmd
&
0xff
)
/*
* Return parameters
switch
(
cmd
&
0xff
)
/*
* Return parameters
*/
{
...
...
@@ -3100,7 +3156,7 @@ gus_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
break
;
case
SOUND_MIXER_RECMASK
:
return
IOCTL_OUT
(
arg
,
SOUND_MASK_MIC
|
SOUND_MASK_LINE
);
return
IOCTL_OUT
(
arg
,
SOUND_MASK_MIC
|
SOUND_MASK_LINE
);
break
;
case
SOUND_MIXER_CAPS
:
...
...
@@ -3133,13 +3189,93 @@ gus_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
static
struct
mixer_operations
gus_mixer_operations
=
{
gus_mixer_ioctl
gus_
default_
mixer_ioctl
};
static
long
gus_default_mixer_init
(
long
mem_start
)
{
if
(
num_mixers
<
MAX_MIXER_DEV
)
/*
* Don't install if there is another
* mixer
*/
mixer_devs
[
num_mixers
++
]
=
&
gus_mixer_operations
;
return
mem_start
;
}
long
gus_wave_init
(
long
mem_start
,
int
irq
,
int
dma
)
{
printk
(
" <Gravis UltraSound %dk>"
,
(
int
)
gus_mem_size
/
1024
);
unsigned
long
flags
;
unsigned
char
val
;
char
*
model_num
=
"2.4"
;
int
gus_type
=
0x24
;
/* 2.4 */
int
mixer_type
=
0
;
/*
* Try to identify the GUS model.
*
* Versions < 3.6 don't have the digital ASIC. Try to probe it first.
*/
DISABLE_INTR
(
flags
);
OUTB
(
0x20
,
gus_base
+
0x0f
);
val
=
INB
(
gus_base
+
0x0f
);
RESTORE_INTR
(
flags
);
if
(
val
!=
0xff
&&
(
val
&
0x06
))
/* Should be 0x02? */
{
/*
* It has the digital ASIC so the card is at least v3.4.
* Next try to detect the true model.
*/
val
=
INB
(
u_MixSelect
);
/*
* Value 255 means pre-3.7 which don't have mixer.
* Values 5 thru 9 mean v3.7 which has a ICS2101 mixer.
* 10 and above is GUS MAX which has the CS4231 codec/mixer.
*
* Sorry. No GUS max support yet but it should be available
* soon after the SDK for GUS MAX is available.
*/
if
(
val
==
255
||
val
<
5
)
{
model_num
=
"3.4"
;
gus_type
=
0x34
;
}
else
if
(
val
<
10
)
{
model_num
=
"3.7"
;
gus_type
=
0x37
;
mixer_type
=
ICS2101
;
}
else
{
model_num
=
"MAX"
;
gus_type
=
0x40
;
mixer_type
=
CS4231
;
}
}
else
{
/*
* ASIC not detected so the card must be 2.2 or 2.4.
* There could still be the 16-bit/mixer daughter card.
* It has the same codec/mixer than MAX.
* At this time there is no support for it but it will appear soon.
*/
}
printk
(
" <Gravis UltraSound %s (%dk)>"
,
model_num
,
(
int
)
gus_mem_size
/
1024
);
#ifndef SCO
sprintf
(
gus_info
.
name
,
"Gravis UltraSound %s (%dk)"
,
model_num
,
(
int
)
gus_mem_size
/
1024
);
#endif
if
(
irq
<
0
||
irq
>
15
)
{
...
...
@@ -3179,11 +3315,21 @@ gus_wave_init (long mem_start, int irq, int dma)
else
printk
(
"GUS: Too many PCM devices available
\n
"
);
if
(
num_mixers
<
MAX_MIXER_DEV
)
/*
* Don't install if there is another
* mixer
*/
mixer_devs
[
num_mixers
++
]
=
&
gus_mixer_operations
;
/*
* Mixer dependent initialization.
*/
switch
(
mixer_type
)
{
case
ICS2101
:
gus_line_vol
=
gus_mic_vol
=
gus_wave_volume
=
gus_pcm_volume
=
100
;
return
ics2101_mixer_init
(
mem_start
);
case
CS4231
:
/* Available soon */
default:
return
gus_default_mixer_init
(
mem_start
);
}
return
mem_start
;
}
...
...
@@ -3199,8 +3345,8 @@ do_loop_irq (int voice)
gus_select_voice
(
voice
);
tmp
=
gus_read8
(
0x00
);
tmp
&=
~
0x20
;
/*
* Disable wave IRQ for this_one voice
tmp
&=
~
0x20
;
/*
* Disable wave IRQ for this_one voice
*/
gus_write8
(
0x00
,
tmp
);
...
...
@@ -3211,12 +3357,12 @@ do_loop_irq (int voice)
switch
(
mode
)
{
case
LMODE_FINISH
:
/*
* Final loop finished, shoot volume down
case
LMODE_FINISH
:
/*
* Final loop finished, shoot volume down
*/
if
((
gus_read16
(
0x09
)
>>
4
)
<
100
)
/*
* Get current volume
if
((
gus_read16
(
0x09
)
>>
4
)
<
100
)
/*
* Get current volume
*/
{
gus_voice_off
();
...
...
@@ -3225,18 +3371,18 @@ do_loop_irq (int voice)
break
;
}
gus_ramp_range
(
65
,
4065
);
gus_ramp_rate
(
0
,
63
);
/*
* Fastest possible rate
gus_ramp_rate
(
0
,
63
);
/*
* Fastest possible rate
*/
gus_rampon
(
0x20
|
0x40
);
/*
* Ramp down, once, irq
gus_rampon
(
0x20
|
0x40
);
/*
* Ramp down, once, irq
*/
voices
[
voice
].
volume_irq_mode
=
VMODE_HALT
;
break
;
case
LMODE_PCM_STOP
:
pcm_active
=
0
;
/*
* Requires extensive processing
pcm_active
=
0
;
/*
* Requires extensive processing
*/
case
LMODE_PCM
:
{
...
...
@@ -3249,8 +3395,8 @@ do_loop_irq (int voice)
play_next_pcm_block
();
}
else
{
/*
* Out of data. Just stop the voice
{
/*
* Out of data. Just stop the voice
*/
gus_voice_off
();
gus_rampoff
();
...
...
@@ -3281,8 +3427,8 @@ do_volume_irq (int voice)
gus_select_voice
(
voice
);
tmp
=
gus_read8
(
0x0d
);
tmp
&=
~
0x20
;
/*
* Disable volume ramp IRQ
tmp
&=
~
0x20
;
/*
* Disable volume ramp IRQ
*/
gus_write8
(
0x0d
,
tmp
);
...
...
@@ -3292,34 +3438,35 @@ do_volume_irq (int voice)
switch
(
mode
)
{
case
VMODE_HALT
:
/*
* Decay phase finished
case
VMODE_HALT
:
/*
* Decay phase finished
*/
RESTORE_INTR
(
flags
);
gus_voice_init
(
voice
);
break
;
case
VMODE_ENVELOPE
:
gus_rampoff
();
RESTORE_INTR
(
flags
);
step_envelope
(
voice
);
break
;
case
VMODE_START_NOTE
:
RESTORE_INTR
(
flags
);
guswave_start_note2
(
voices
[
voice
].
dev_pending
,
voice
,
voices
[
voice
].
note_pending
,
voices
[
voice
].
volume_pending
);
if
(
voices
[
voice
].
kill_pending
)
guswave_kill_note
(
voices
[
voice
].
dev_pending
,
voice
,
0
);
guswave_kill_note
(
voices
[
voice
].
dev_pending
,
voice
,
0
);
if
(
voices
[
voice
].
sample_pending
>=
0
)
{
guswave_set_instr
(
voices
[
voice
].
dev_pending
,
voice
,
voices
[
voice
].
sample_pending
);
voices
[
voice
].
sample_pending
=
-
1
;
}
{
guswave_set_instr
(
voices
[
voice
].
dev_pending
,
voice
,
voices
[
voice
].
sample_pending
);
voices
[
voice
].
sample_pending
=
-
1
;
}
break
;
default:
;
}
RESTORE_INTR
(
flags
);
}
void
...
...
@@ -3332,37 +3479,37 @@ gus_voice_irq (void)
while
(
1
)
{
src
=
gus_read8
(
0x0f
);
/*
* Get source info
src
=
gus_read8
(
0x0f
);
/*
* Get source info
*/
voice
=
src
&
0x1f
;
src
&=
0xc0
;
if
(
src
==
(
0x80
|
0x40
))
return
;
/*
* No interrupt
return
;
/*
* No interrupt
*/
voice_bit
=
1
<<
voice
;
if
(
!
(
src
&
0x80
))
/*
* Wave IRQ pending
if
(
!
(
src
&
0x80
))
/*
* Wave IRQ pending
*/
if
(
!
(
wave_ignore
&
voice_bit
)
&&
voice
<
nr_voices
)
/*
if
(
!
(
wave_ignore
&
voice_bit
)
&&
voice
<
nr_voices
)
/*
* Not done
* yet
* yet
*/
{
wave_ignore
|=
voice_bit
;
do_loop_irq
(
voice
);
}
if
(
!
(
src
&
0x40
))
/*
* Volume IRQ pending
if
(
!
(
src
&
0x40
))
/*
* Volume IRQ pending
*/
if
(
!
(
volume_ignore
&
voice_bit
)
&&
voice
<
nr_voices
)
/*
if
(
!
(
volume_ignore
&
voice_bit
)
&&
voice
<
nr_voices
)
/*
* Not done
* yet
* yet
*/
{
volume_ignore
|=
voice_bit
;
...
...
@@ -3376,11 +3523,11 @@ guswave_dma_irq (void)
{
unsigned
char
status
;
status
=
gus_look8
(
0x41
);
/*
* Get DMA IRQ Status
status
=
gus_look8
(
0x41
);
/*
* Get DMA IRQ Status
*/
if
(
status
&
0x40
)
/*
* DMA Irq pending
if
(
status
&
0x40
)
/*
* DMA Irq pending
*/
switch
(
active_device
)
{
...
...
@@ -3405,11 +3552,11 @@ guswave_dma_irq (void)
default:
;
}
status
=
gus_look8
(
0x49
);
/*
* Get Sampling IRQ Status
status
=
gus_look8
(
0x49
);
/*
* Get Sampling IRQ Status
*/
if
(
status
&
0x40
)
/*
* Sampling Irq pending
if
(
status
&
0x40
)
/*
* Sampling Irq pending
*/
{
DMAbuf_inputintr
(
gus_devnum
);
...
...
drivers/sound/ics2101.c
0 → 100644
View file @
e695b6a4
/*
* sound/ics2101.c
*
* Driver for the ICS2101 mixer of GUS v3.7.
*
* Copyright by Hannu Savolainen 1994
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2.
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include "sound_config.h"
#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_GUS)
#include <linux/ultrasound.h>
#include "gus_hw.h"
#define MIX_DEVS (SOUND_MASK_MIC|SOUND_MASK_LINE| \
SOUND_MASK_SYNTH| \
SOUND_MASK_CD | SOUND_MASK_VOLUME)
extern
int
gus_base
;
static
int
volumes
[
ICS_MIXDEVS
];
static
int
left_fix
[
ICS_MIXDEVS
]
=
{
1
,
1
,
1
,
2
,
1
,
2
};
static
int
right_fix
[
ICS_MIXDEVS
]
=
{
2
,
2
,
2
,
1
,
2
,
1
};
static
int
scale_vol
(
int
vol
)
{
#if 1
/*
* Experimental volume scaling by Risto Kankkunen.
* This should give smoother volume response than just
* a plain multiplication.
*/
int
e
;
if
(
vol
<
0
)
vol
=
0
;
if
(
vol
>
100
)
vol
=
100
;
vol
=
(
31
*
vol
+
50
)
/
100
;
e
=
0
;
if
(
vol
)
{
while
(
vol
<
16
)
{
vol
<<=
1
;
e
--
;
}
vol
-=
16
;
e
+=
7
;
}
return
((
e
<<
4
)
+
vol
);
#else
return
((
vol
*
127
)
+
50
)
/
100
;
#endif
}
static
void
write_mix
(
int
dev
,
int
chn
,
int
vol
)
{
int
*
selector
;
unsigned
long
flags
;
int
ctrl_addr
=
dev
<<
3
;
int
attn_addr
=
dev
<<
3
;
vol
=
scale_vol
(
vol
);
if
(
chn
==
CHN_LEFT
)
{
selector
=
left_fix
;
ctrl_addr
|=
0x00
;
attn_addr
|=
0x02
;
}
else
{
selector
=
right_fix
;
ctrl_addr
|=
0x01
;
attn_addr
|=
0x03
;
}
DISABLE_INTR
(
flags
);
OUTB
(
ctrl_addr
,
u_MixSelect
);
OUTB
(
selector
[
dev
],
u_MixData
);
OUTB
(
attn_addr
,
u_MixSelect
);
OUTB
((
unsigned
char
)
vol
,
u_MixData
);
RESTORE_INTR
(
flags
);
}
static
int
set_volumes
(
int
dev
,
int
vol
)
{
int
left
=
vol
&
0x00ff
;
int
right
=
(
vol
>>
8
)
&
0x00ff
;
if
(
left
<
0
)
left
=
0
;
if
(
left
>
100
)
left
=
100
;
if
(
right
<
0
)
right
=
0
;
if
(
right
>
100
)
right
=
100
;
write_mix
(
dev
,
CHN_LEFT
,
left
);
write_mix
(
dev
,
CHN_RIGHT
,
right
);
vol
=
left
+
(
right
<<
8
);
volumes
[
dev
]
=
vol
;
return
vol
;
}
static
int
ics2101_mixer_ioctl
(
int
dev
,
unsigned
int
cmd
,
unsigned
int
arg
)
{
if
(((
cmd
>>
8
)
&
0xff
)
==
'M'
)
{
if
(
cmd
&
IOC_IN
)
switch
(
cmd
&
0xff
)
{
case
SOUND_MIXER_RECSRC
:
return
gus_default_mixer_ioctl
(
dev
,
cmd
,
arg
);
break
;
case
SOUND_MIXER_MIC
:
return
IOCTL_OUT
(
arg
,
set_volumes
(
DEV_MIC
,
IOCTL_IN
(
arg
)));
break
;
case
SOUND_MIXER_CD
:
return
IOCTL_OUT
(
arg
,
set_volumes
(
DEV_CD
,
IOCTL_IN
(
arg
)));
break
;
case
SOUND_MIXER_LINE
:
return
IOCTL_OUT
(
arg
,
set_volumes
(
DEV_LINE
,
IOCTL_IN
(
arg
)));
break
;
case
SOUND_MIXER_SYNTH
:
return
IOCTL_OUT
(
arg
,
set_volumes
(
DEV_GF1
,
IOCTL_IN
(
arg
)));
break
;
case
SOUND_MIXER_VOLUME
:
return
IOCTL_OUT
(
arg
,
set_volumes
(
DEV_VOL
,
IOCTL_IN
(
arg
)));
break
;
default:
return
RET_ERROR
(
EINVAL
);
}
else
switch
(
cmd
&
0xff
)
/*
* Return parameters
*/
{
case
SOUND_MIXER_RECSRC
:
return
gus_default_mixer_ioctl
(
dev
,
cmd
,
arg
);
break
;
case
SOUND_MIXER_DEVMASK
:
return
IOCTL_OUT
(
arg
,
MIX_DEVS
);
break
;
case
SOUND_MIXER_STEREODEVS
:
return
IOCTL_OUT
(
arg
,
SOUND_MASK_LINE
|
SOUND_MASK_CD
|
SOUND_MASK_SYNTH
|
SOUND_MASK_VOLUME
|
SOUND_MASK_MIC
);
break
;
case
SOUND_MIXER_RECMASK
:
return
IOCTL_OUT
(
arg
,
SOUND_MASK_MIC
|
SOUND_MASK_LINE
);
break
;
case
SOUND_MIXER_CAPS
:
return
IOCTL_OUT
(
arg
,
0
);
break
;
case
SOUND_MIXER_MIC
:
return
IOCTL_OUT
(
arg
,
volumes
[
DEV_MIC
]);
break
;
case
SOUND_MIXER_LINE
:
return
IOCTL_OUT
(
arg
,
volumes
[
DEV_LINE
]);
break
;
case
SOUND_MIXER_CD
:
return
IOCTL_OUT
(
arg
,
volumes
[
DEV_CD
]);
break
;
case
SOUND_MIXER_VOLUME
:
return
IOCTL_OUT
(
arg
,
volumes
[
DEV_VOL
]);
break
;
case
SOUND_MIXER_SYNTH
:
return
IOCTL_OUT
(
arg
,
volumes
[
DEV_GF1
]);
break
;
default:
return
RET_ERROR
(
EINVAL
);
}
}
return
RET_ERROR
(
EINVAL
);
}
static
struct
mixer_operations
ics2101_mixer_operations
=
{
ics2101_mixer_ioctl
};
long
ics2101_mixer_init
(
long
mem_start
)
{
int
i
;
if
(
num_mixers
<
MAX_MIXER_DEV
)
{
mixer_devs
[
num_mixers
++
]
=
&
ics2101_mixer_operations
;
/*
* Some GUS v3.7 cards had some channels flipped. Disable
* the flipping feature if the model id is other than 5.
*/
if
(
INB
(
u_MixSelect
)
!=
5
)
{
for
(
i
=
0
;
i
<
ICS_MIXDEVS
;
i
++
)
left_fix
[
i
]
=
1
;
for
(
i
=
0
;
i
<
ICS_MIXDEVS
;
i
++
)
right_fix
[
i
]
=
2
;
}
set_volumes
(
DEV_GF1
,
0x5a5a
);
set_volumes
(
DEV_CD
,
0x5a5a
);
set_volumes
(
DEV_MIC
,
0x0000
);
set_volumes
(
DEV_LINE
,
0x5a5a
);
set_volumes
(
DEV_VOL
,
0x5a5a
);
set_volumes
(
DEV_UNUSED
,
0x0000
);
}
return
mem_start
;
}
#endif
drivers/sound/midibuf.c
View file @
e695b6a4
/*
* sound/midibuf.c
*
*
* Device file manager for /dev/midi
*
*
* NOTE! This part of the driver is currently just a stub.
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -14,7 +14,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -26,7 +26,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#include "sound_config.h"
...
...
drivers/sound/mpu401.c
View file @
e695b6a4
/*
* sound/mpu401.c
*
*
* The low level driver for Roland MPU-401 compatible Midi cards.
*
*
* This version supports just the DUMB UART mode.
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -14,7 +14,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -26,7 +26,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#include "sound_config.h"
...
...
@@ -35,7 +35,7 @@
#if !defined(EXCLUDE_MPU401) && !defined(EXCLUDE_MIDI)
#define DATAPORT (mpu401_base)
/* MPU-401 Data I/O Port on IBM */
#define DATAPORT (mpu401_base)
/* MPU-401 Data I/O Port on IBM */
#define COMDPORT (mpu401_base+1)
/* MPU-401 Command Port on IBM */
#define STATPORT (mpu401_base+1)
/* MPU-401 Status Port on IBM */
...
...
@@ -61,58 +61,16 @@ static int my_dev;
static
int
reset_mpu401
(
void
);
static
void
(
*
midi_input_intr
)
(
int
dev
,
unsigned
char
data
);
static
void
mpu401_input_loop
(
void
)
{
int
count
;
count
=
10
;
while
(
count
)
/* Not timed out */
if
(
input_avail
())
{
unsigned
char
c
=
mpu401_read
();
count
=
100
;
if
(
mpu401_opened
&
OPEN_READ
)
midi_input_intr
(
my_dev
,
c
);
}
else
while
(
!
input_avail
()
&&
count
)
count
--
;
}
void
mpuintr
(
int
unit
)
{
if
(
input_avail
())
mpu401_input_loop
();
}
/*
* It looks like there is no input interrupts in the UART mode. Let's try
* polling.
*/
static
void
poll_mpu401
(
unsigned
long
dummy
)
{
unsigned
long
flags
;
DEFINE_TIMER
(
mpu401_timer
,
poll_mpu401
);
if
(
!
(
mpu401_opened
&
OPEN_READ
))
return
;
/* No longer required */
DISABLE_INTR
(
flags
);
if
(
input_avail
())
mpu401_input_loop
();
ACTIVATE_TIMER
(
mpu401_timer
,
poll_mpu401
,
1
);
/* Come back later */
while
(
input_avail
())
{
unsigned
char
c
=
mpu401_read
();
RESTORE_INTR
(
flags
);
if
(
mpu401_opened
&
OPEN_READ
)
midi_input_intr
(
my_dev
,
c
);
}
}
static
int
...
...
@@ -127,11 +85,10 @@ mpu401_open (int dev, int mode,
return
RET_ERROR
(
EBUSY
);
}
mpu
401_input_loop
(
);
mpu
intr
(
0
);
midi_input_intr
=
input
;
mpu401_opened
=
mode
;
poll_mpu401
(
0
);
/* Enable input polling */
return
0
;
}
...
...
@@ -155,7 +112,7 @@ mpu401_out (int dev, unsigned char midi_byte)
DISABLE_INTR
(
flags
);
if
(
input_avail
())
mpu
401_input_loop
(
);
mpu
intr
(
0
);
RESTORE_INTR
(
flags
);
...
...
@@ -291,7 +248,7 @@ reset_mpu401 (void)
mpu401_opened
=
0
;
if
(
ok
)
mpu
401_input_loop
();
/* Flush input before enabling interrupts */
mpu
intr
(
0
);
/* Flush input before enabling interrupts */
RESTORE_INTR
(
flags
);
...
...
drivers/sound/opl3.c
View file @
e695b6a4
/*
* sound/opl3.c
*
*
* A low level driver for Yamaha YM3812 and OPL-3 -chips
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -12,7 +12,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -24,7 +24,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
/* Major improvements to the FM handling 30AUG92 by Rob Hooft, */
...
...
@@ -38,7 +38,7 @@
#define MAX_VOICE 18
#define OFFS_4OP 11
/* Definitions for the operators OP3 and OP4
* begin here */
* begin here */
static
int
opl3_enabled
=
0
;
static
int
left_address
=
0x388
,
right_address
=
0x388
,
both_address
=
0
;
...
...
@@ -70,7 +70,7 @@ static int already_initialized = 0;
static
int
opl3_ok
=
0
;
static
int
opl3_busy
=
0
;
static
int
fm_model
=
0
;
/* 0=no fm, 1=mono, 2=SB Pro 1, 3=SB Pro 2
*/
static
int
fm_model
=
0
;
/* 0=no fm, 1=mono, 2=SB Pro 1, 3=SB Pro 2
*/
static
int
store_instr
(
int
instr_no
,
struct
sbi_instrument
*
instr
);
static
void
freq_to_fnum
(
int
freq
,
int
*
block
,
int
*
fnum
);
...
...
@@ -81,6 +81,9 @@ static unsigned char connection_mask = 0x00;
void
enable_opl3_mode
(
int
left
,
int
right
,
int
both
)
{
if
(
opl3_enabled
)
return
;
opl3_enabled
=
1
;
left_address
=
left
;
right_address
=
right
;
...
...
@@ -168,10 +171,10 @@ opl3_detect (int ioaddr)
* This function returns 1 if the FM chicp is present at the given I/O port
* The detection algorithm plays with the timer built in the FM chip and
* looks for a change in the status register.
*
*
* Note! The timers of the FM chip are not connected to AdLib (and compatible)
* boards.
*
*
* Note2! The chip is initialized if detected.
*/
...
...
@@ -194,7 +197,7 @@ opl3_detect (int ioaddr)
if
((
stat1
&
0xE0
)
!=
0x00
)
{
return
0
;
/* Should be 0x00
*/
return
0
;
/* Should be 0x00
*/
}
opl3_command
(
ioaddr
,
TIMER1_REGISTER
,
0xff
);
/* Set timer 1 to 0xff */
...
...
@@ -364,7 +367,7 @@ set_voice_volume (int voice, int volume)
vol2
=
instr
->
operators
[
3
];
if
((
instr
->
operators
[
10
]
&
0x01
))
{
/* Additive synthesis
*/
{
/* Additive synthesis
*/
calc_vol
(
&
vol1
,
volume
);
calc_vol
(
&
vol2
,
volume
);
}
...
...
@@ -627,7 +630,7 @@ opl3_command (int io_addr, unsigned int addr, unsigned int val)
* register. The OPL-3 survives with just two INBs
*/
OUTB
((
unsigned
char
)
(
addr
&
0xff
),
io_addr
);
/* Select register
*/
OUTB
((
unsigned
char
)
(
addr
&
0xff
),
io_addr
);
/* Select register
*/
if
(
!
opl3_enabled
)
tenmicrosec
();
...
...
@@ -635,7 +638,7 @@ opl3_command (int io_addr, unsigned int addr, unsigned int val)
for
(
i
=
0
;
i
<
2
;
i
++
)
INB
(
io_addr
);
OUTB
((
unsigned
char
)
(
val
&
0xff
),
io_addr
+
1
);
/* Write to register
*/
OUTB
((
unsigned
char
)
(
val
&
0xff
),
io_addr
+
1
);
/* Write to register
*/
if
(
!
opl3_enabled
)
{
...
...
@@ -747,6 +750,11 @@ opl3_panning (int dev, int voice, int pressure)
{
}
static
void
opl3_volume_method
(
int
dev
,
int
mode
)
{
}
#define SET_VIBRATO(cell) { \
tmp = instr->operators[(cell-1)+(((cell-1)/2)*OFFS_4OP)]; \
if (pressure > 110) \
...
...
@@ -852,7 +860,7 @@ opl3_controller (int dev, int voice, int ctrl_num, int value)
opl3_command
(
map
->
ioaddr
,
FNUM_LOW
+
map
->
voice_num
,
data
);
data
=
0x20
|
((
block
&
0x7
)
<<
2
)
|
((
fnum
>>
8
)
&
0x3
);
/* KEYON|OCTAVE|MS bits
* of f-num */
* of f-num */
voices
[
voice
].
keyon_byte
=
data
;
opl3_command
(
map
->
ioaddr
,
KEYON_BLOCK
+
map
->
voice_num
,
data
);
break
;
...
...
@@ -886,6 +894,7 @@ static struct synth_operations opl3_operations =
opl3_aftertouch
,
opl3_controller
,
opl3_panning
,
opl3_volume_method
,
opl3_patchmgr
};
...
...
@@ -894,8 +903,8 @@ opl3_init (long mem_start)
{
int
i
;
PERMANENT_MALLOC
(
struct
sbi_instrument
*
,
instrmap
,
SBFM_MAXINSTR
*
sizeof
(
*
instrmap
),
mem_start
);
PERMANENT_MALLOC
(
struct
sbi_instrument
*
,
instrmap
,
SBFM_MAXINSTR
*
sizeof
(
*
instrmap
),
mem_start
);
synth_devs
[
num_synths
++
]
=
&
opl3_operations
;
fm_model
=
0
;
...
...
drivers/sound/os.h
View file @
e695b6a4
...
...
@@ -37,7 +37,6 @@
#include <linux/timer.h>
#include <linux/tty.h>
#include <linux/ctype.h>
#include <linux/string.h>
#include <asm/io.h>
#include <asm/segment.h>
#include <asm/system.h>
...
...
@@ -46,6 +45,7 @@
#include <linux/wait.h>
#include <linux/malloc.h>
#include <linux/soundcard.h>
#include <linux/string.h>
typedef
char
snd_rw_buf
;
...
...
@@ -141,7 +141,7 @@ struct snd_wait {
#define DEFINE_TIMER(name, proc) \
static struct timer_list name = \
{NULL,
NULL
, 0, 0, proc}
{NULL,
0
, 0, 0, proc}
/*
* The ACTIVATE_TIMER requests system to call 'proc' after 'time' ticks.
...
...
drivers/sound/pas.h
View file @
e695b6a4
...
...
@@ -138,11 +138,11 @@
char
I_C_2_PCM_DMA_translate
[]
=
/* R W PCM PCM DMA channel value translations */
{
4
,
1
,
2
,
3
,
0
,
5
,
6
,
7
};
char
I_C_3_PCM_IRQ_translate
[]
=
/* R W PCM PCM IRQ level value translation */
{
0
,
0
,
1
,
2
,
3
,
4
,
5
,
6
,
0
,
0
,
7
,
8
,
9
,
0
,
10
,
11
};
{
0
,
0
,
1
,
2
,
3
,
4
,
5
,
6
,
0
,
1
,
7
,
8
,
9
,
0
,
10
,
11
};
char
E_C_MPU401_IRQ_translate
[]
=
/* R W MIDI MPU401 emulation IRQ value translation */
{
0x00
,
0x00
,
0x01
,
0x02
,
0x00
,
0x03
,
0x00
,
0x04
,
0x00
,
0x0
0
,
0x05
,
0x06
,
0x07
};
{
0x00
,
0x00
,
0x01
,
0x02
,
0x00
,
0x03
,
0x00
,
0x04
,
0x00
,
0x0
1
,
0x05
,
0x06
,
0x07
};
char
E_C_SB_IRQ_translate
[]
=
/* R W PCM SB emulation IRQ translate */
{
0x00
,
0x00
,
0x08
,
0x10
,
0x00
,
0x18
,
0x00
,
0x20
,
0x00
,
0x0
0
,
0x28
,
0x30
,
0x38
,
0
,
0
};
{
0x00
,
0x00
,
0x08
,
0x10
,
0x00
,
0x18
,
0x00
,
0x20
,
0x00
,
0x0
8
,
0x28
,
0x30
,
0x38
,
0
,
0
};
char
E_C_SB_DMA_translate
[]
=
/* R W PCM SB emulation DMA translate */
{
0x00
,
0x40
,
0x80
,
0xC0
,
0
,
0
,
0
,
0
};
char
O_M_1_to_card
[]
=
/* R W Control Translate (OM1 & 0x0f) to card type */
...
...
drivers/sound/pas2_card.c
View file @
e695b6a4
...
...
@@ -2,11 +2,11 @@
#define SND_SA_INTERRUPT
/*
* sound/pas2_card.c
*
*
* Detection routine for the Pro Audio Spectrum cards.
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -14,7 +14,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -26,7 +26,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#include "sound_config.h"
...
...
@@ -196,14 +196,14 @@ config_pas_hw (struct address_info *hw_config)
ok
=
0
;
}
}
/*
/*
* This fixes the timing problems of the PAS due to the Symphony chipset
* as per Media Vision. Only define this if your PAS doesn't work correctly.
*/
#ifdef SYMPHONY_PAS
OUTB
(
0x05
,
0xa8
);
OUTB
(
0x60
,
0xa9
);
OUTB
(
0x05
,
0xa8
);
OUTB
(
0x60
,
0xa9
);
#endif
#ifdef BROKEN_BUS_CLOCK
...
...
@@ -228,35 +228,35 @@ config_pas_hw (struct address_info *hw_config)
#if !defined(EXCLUDE_SB_EMULATION) || !defined(EXCLUDE_SB)
{
struct
address_info
*
sb_config
;
{
struct
address_info
*
sb_config
;
if
((
sb_config
=
sound_getconf
(
SNDCARD_SB
)))
{
unsigned
char
irq_dma
;
if
((
sb_config
=
sound_getconf
(
SNDCARD_SB
)))
{
unsigned
char
irq_dma
;
/* Turn on Sound Blaster compatibility */
/* bit 1 = SB emulation */
/* bit 0 = MPU401 emulation (CDPC only :-( ) */
pas_write
(
0x02
,
COMPATIBILITY_ENABLE
);
/* Turn on Sound Blaster compatibility */
/* bit 1 = SB emulation */
/* bit 0 = MPU401 emulation (CDPC only :-( ) */
pas_write
(
0x02
,
COMPATIBILITY_ENABLE
);
/* "Emulation address"
*/
pas_write
((
sb_config
->
io_base
>>
4
)
&
0x0f
,
EMULATION_ADDRESS
);
/* "Emulation address"
*/
pas_write
((
sb_config
->
io_base
>>
4
)
&
0x0f
,
EMULATION_ADDRESS
);
if
(
!
E_C_SB_DMA_translate
[
sb_config
->
dma
])
printk
(
"
\n\n
PAS16 Warning: Invalid SB DMA %d
\n\n
"
,
sb_config
->
dma
);
if
(
!
E_C_SB_DMA_translate
[
sb_config
->
dma
])
printk
(
"
\n\n
PAS16 Warning: Invalid SB DMA %d
\n\n
"
,
sb_config
->
dma
);
if
(
!
E_C_SB_IRQ_translate
[
sb_config
->
irq
])
printk
(
"
\n\n
PAS16 Warning: Invalid SB IRQ %d
\n\n
"
,
sb_config
->
irq
);
if
(
!
E_C_SB_IRQ_translate
[
sb_config
->
irq
])
printk
(
"
\n\n
PAS16 Warning: Invalid SB IRQ %d
\n\n
"
,
sb_config
->
irq
);
irq_dma
=
E_C_SB_DMA_translate
[
sb_config
->
dma
]
|
E_C_SB_IRQ_translate
[
sb_config
->
irq
];
irq_dma
=
E_C_SB_DMA_translate
[
sb_config
->
dma
]
|
E_C_SB_IRQ_translate
[
sb_config
->
irq
];
pas_write
(
irq_dma
,
EMULATION_CONFIGURATION
);
}
}
pas_write
(
irq_dma
,
EMULATION_CONFIGURATION
);
}
}
#endif
if
(
!
ok
)
...
...
@@ -327,11 +327,11 @@ attach_pas_card (long mem_start, struct address_info *hw_config)
mem_start
=
pas_pcm_init
(
mem_start
,
hw_config
);
#endif
#
if !defined(EXCLUDE_SB_EMULATION) && !defined(EXCLUDE_SB)
#if !defined(EXCLUDE_SB_EMULATION) && !defined(EXCLUDE_SB)
sb_dsp_disable_midi
();
/* The SB emulation don't support
* midi */
#
endif
#endif
#ifndef EXCLUDE_YM3812
enable_opl3_mode
(
0x388
,
0x38a
,
0
);
...
...
drivers/sound/pas2_midi.c
View file @
e695b6a4
/*
* sound/pas2_midi.c
*
*
* The low level driver for the PAS Midi Interface.
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -12,7 +12,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -24,7 +24,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#include "sound_config.h"
...
...
drivers/sound/pas2_mixer.c
View file @
e695b6a4
...
...
@@ -2,11 +2,11 @@
/*
* sound/pas2_mixer.c
*
*
* Mixer routines for the Pro Audio Spectrum cards.
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -14,7 +14,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -26,7 +26,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#include "sound_config.h"
...
...
@@ -87,7 +87,7 @@ mixer_output (int right_vol, int left_vol, int div, int bits,
}
if
(
bits
==
P_M_MV508_BASS
||
bits
==
P_M_MV508_TREBLE
)
{
/* Bass and trebble are mono devices
*/
{
/* Bass and trebble are mono devices
*/
pas_write
(
P_M_MV508_ADDRESS
|
bits
,
PARALLEL_MIXER
);
pas_write
(
left
,
PARALLEL_MIXER
);
right_vol
=
left_vol
;
...
...
drivers/sound/pas2_pcm.c
View file @
e695b6a4
#define _PAS2_PCM_C_
/*
* sound/pas2_pcm.c
*
*
* The low level driver for the Pro Audio Spectrum ADC/DAC.
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -13,7 +13,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -25,7 +25,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#include "sound_config.h"
...
...
@@ -149,7 +149,7 @@ pas_pcm_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
case
SOUND_PCM_WRITE_CHANNELS
:
if
(
local
)
return
pcm_set_channels
(
arg
);
return
pcm_set_channels
(
arg
);
return
IOCTL_OUT
(
arg
,
pcm_set_channels
(
IOCTL_IN
(
arg
)));
break
;
...
...
@@ -234,7 +234,7 @@ pas_pcm_close (int dev)
}
static
void
pas_pcm_output_block
(
int
dev
,
unsigned
long
buf
,
int
count
,
pas_pcm_output_block
(
int
dev
,
unsigned
long
buf
,
int
count
,
int
intrflag
,
int
restart_dma
)
{
unsigned
long
flags
,
cnt
;
...
...
@@ -255,8 +255,8 @@ pas_pcm_output_block (int dev, unsigned long buf, int count,
pas_write
(
pas_read
(
PCM_CONTROL
)
&
~
P_C_PCM_ENABLE
,
PCM_CONTROL
);
if
(
restart_dma
)
DMAbuf_start_dma
(
dev
,
buf
,
count
,
DMA_MODE_WRITE
);
if
(
restart_dma
)
DMAbuf_start_dma
(
dev
,
buf
,
count
,
DMA_MODE_WRITE
);
if
(
sound_dsp_dmachan
[
dev
]
>
3
)
count
>>=
1
;
...
...
@@ -280,7 +280,7 @@ pas_pcm_output_block (int dev, unsigned long buf, int count,
}
static
void
pas_pcm_start_input
(
int
dev
,
unsigned
long
buf
,
int
count
,
pas_pcm_start_input
(
int
dev
,
unsigned
long
buf
,
int
count
,
int
intrflag
,
int
restart_dma
)
{
unsigned
long
flags
;
...
...
@@ -300,7 +300,7 @@ pas_pcm_start_input (int dev, unsigned long buf, int count,
DISABLE_INTR
(
flags
);
if
(
restart_dma
)
DMAbuf_start_dma
(
dev
,
buf
,
count
,
DMA_MODE_READ
);
DMAbuf_start_dma
(
dev
,
buf
,
count
,
DMA_MODE_READ
);
if
(
sound_dsp_dmachan
[
dev
]
>
3
)
count
>>=
1
;
...
...
@@ -337,14 +337,15 @@ pas_pcm_prepare_for_output (int dev, int bsize, int bcount)
static
struct
audio_operations
pas_pcm_operations
=
{
"Pro Audio Spectrum"
,
pas_pcm_open
,
/* */
pas_pcm_close
,
/* */
pas_pcm_output_block
,
/* */
pas_pcm_start_input
,
/* */
pas_pcm_ioctl
,
/* */
pas_pcm_prepare_for_input
,
/* */
pas_pcm_prepare_for_output
,
/* */
pas_pcm_reset
,
/* */
NOTHING_SPECIAL
,
pas_pcm_open
,
pas_pcm_close
,
pas_pcm_output_block
,
pas_pcm_start_input
,
pas_pcm_ioctl
,
pas_pcm_prepare_for_input
,
pas_pcm_prepare_for_output
,
pas_pcm_reset
,
pas_pcm_reset
,
/* halt_xfer */
NULL
,
/* has_output_drained */
NULL
/* copy_from_user */
...
...
@@ -379,9 +380,9 @@ pas_pcm_init (long mem_start, struct address_info *hw_config)
sound_dma_automode
[
my_devnum
]
=
1
;
}
#else
sound_buffcounts
[
my_devnum
]
=
2
;
sound_buffsizes
[
my_devnum
]
=
DSP_BUFFSIZE
;
sound_dma_automode
[
my_devnum
]
=
0
;
sound_buffcounts
[
my_devnum
]
=
2
;
sound_buffsizes
[
my_devnum
]
=
DSP_BUFFSIZE
;
sound_dma_automode
[
my_devnum
]
=
0
;
#endif
}
else
...
...
drivers/sound/patmgr.c
View file @
e695b6a4
/*
* sound/patmgr.c
*
*
* The patch maneger interface for the /dev/sequencer
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -12,7 +12,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -24,7 +24,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#define PATMGR_C
...
...
drivers/sound/sb16_dsp.c
View file @
e695b6a4
/*
* sound/sb16_dsp.c
*
*
* The low level driver for the SoundBlaster DSP chip.
*
*
* (C) 1993 J. Schubert (jsb@sth.ruhr-uni-bochum.de)
*
* based on SB-driver by (C) Hannu Savolainen
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -14,7 +14,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -26,53 +26,55 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#define DEB(x)
#define DEB1(x)
/*
#define DEB_DMARES
*/
#define DEB_DMARES
*/
#include "sound_config.h"
#include "sb.h"
#include "sb_mixer.h"
#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_AUDIO) && !defined(EXCLUDE_SBPRO)
extern
int
sbc_base
;
extern
int
sbc_base
,
sbc_minor
,
sbc_major
;
static
int
sb16_dsp_ok
=
0
;
/* Set to 1 after successful initialization */
static
int
dsp_16bit
=
0
;
static
int
dsp_stereo
=
0
;
static
int
dsp_current_speed
=
8000
;
/*DSP_DEFAULT_SPEED;
*/
static
int
dsp_busy
=
0
;
static
int
dma16
,
dma8
;
static
int
sb16_dsp_ok
=
0
;
/* Set to 1 after successful initialization */
static
int
dsp_16bit
=
0
;
static
int
dsp_stereo
=
0
;
static
int
dsp_current_speed
=
8000
;
/*DSP_DEFAULT_SPEED;
*/
static
int
dsp_busy
=
0
;
static
int
dma16
,
dma8
;
static
unsigned
long
dsp_count
=
0
;
static
int
irq_mode
=
IMODE_NONE
;
/* IMODE_INPUT, IMODE_OUTPUT or
static
int
irq_mode
=
IMODE_NONE
;
/* IMODE_INPUT, IMODE_OUTPUT or
IMODE_NONE */
static
int
my_dev
=
0
;
static
int
my_dev
=
0
;
static
volatile
int
intr_active
=
0
;
static
int
sb16_dsp_open
(
int
dev
,
int
mode
);
static
void
sb16_dsp_close
(
int
dev
);
static
void
sb16_dsp_output_block
(
int
dev
,
unsigned
long
buf
,
int
count
,
int
intrflag
,
int
dma_restart
);
static
void
sb16_dsp_start_input
(
int
dev
,
unsigned
long
buf
,
int
count
,
int
intrflag
,
int
dma_restart
);
static
int
sb16_dsp_ioctl
(
int
dev
,
unsigned
int
cmd
,
unsigned
int
arg
,
int
local
);
static
int
sb16_dsp_prepare_for_input
(
int
dev
,
int
bsize
,
int
bcount
);
static
int
sb16_dsp_prepare_for_output
(
int
dev
,
int
bsize
,
int
bcount
);
static
void
sb16_dsp_reset
(
int
dev
);
static
void
sb16_dsp_halt
(
int
dev
);
static
int
dsp_set_speed
(
int
);
static
int
dsp_set_stereo
(
int
);
static
void
dsp_cleanup
(
void
);
int
sb_reset_dsp
(
void
);
static
int
sb16_dsp_open
(
int
dev
,
int
mode
);
static
void
sb16_dsp_close
(
int
dev
);
static
void
sb16_dsp_output_block
(
int
dev
,
unsigned
long
buf
,
int
count
,
int
intrflag
,
int
dma_restart
);
static
void
sb16_dsp_start_input
(
int
dev
,
unsigned
long
buf
,
int
count
,
int
intrflag
,
int
dma_restart
);
static
int
sb16_dsp_ioctl
(
int
dev
,
unsigned
int
cmd
,
unsigned
int
arg
,
int
local
);
static
int
sb16_dsp_prepare_for_input
(
int
dev
,
int
bsize
,
int
bcount
);
static
int
sb16_dsp_prepare_for_output
(
int
dev
,
int
bsize
,
int
bcount
);
static
void
sb16_dsp_reset
(
int
dev
);
static
void
sb16_dsp_halt
(
int
dev
);
static
int
dsp_set_speed
(
int
);
static
int
dsp_set_stereo
(
int
);
static
void
dsp_cleanup
(
void
);
int
sb_reset_dsp
(
void
);
static
struct
audio_operations
sb16_dsp_operations
=
{
"SoundBlaster 16"
,
NOTHING_SPECIAL
,
sb16_dsp_open
,
sb16_dsp_close
,
sb16_dsp_output_block
,
...
...
@@ -86,203 +88,221 @@ static struct audio_operations sb16_dsp_operations =
NULL
};
static
int
sb_dsp_command01
(
unsigned
char
val
)
static
int
sb_dsp_command01
(
unsigned
char
val
)
{
int
i
=
1
<<
16
;
int
i
=
1
<<
16
;
while
(
--
i
&
(
!
INB
(
DSP_STATUS
)
&
0x80
));
if
(
!
i
)
printk
(
"SB16 sb_dsp_command01 Timeout
\n
"
);
return
sb_dsp_command
(
val
);
while
(
--
i
&
(
!
INB
(
DSP_STATUS
)
&
0x80
));
if
(
!
i
)
printk
(
"SB16 sb_dsp_command01 Timeout
\n
"
);
return
sb_dsp_command
(
val
);
}
static
int
wait_data_avail
(
int
t
)
static
int
wait_data_avail
(
unsigned
long
t
)
{
int
loopc
=
5000000
;
t
+=
GET_TIME
();
do
{
if
(
INB
(
DSP_DATA_AVAIL
)
&
0x80
)
return
1
;
}
while
(
--
loopc
&&
GET_TIME
()
<
t
);
printk
(
"!data_avail l=%d
\n
"
,
loopc
);
int
loopc
=
5000000
;
t
+=
GET_TIME
();
do
{
if
(
INB
(
DSP_DATA_AVAIL
)
&
0x80
)
return
1
;
}
while
(
--
loopc
&&
GET_TIME
()
<
t
);
printk
(
"!data_avail l=%d
\n
"
,
loopc
);
return
0
;
}
static
int
read_dsp
(
int
t
)
static
int
read_dsp
(
int
t
)
{
if
(
!
wait_data_avail
(
t
))
if
(
!
wait_data_avail
((
unsigned
long
)
t
))
return
-
1
;
else
return
INB
(
DSP_READ
);
}
return
INB
(
DSP_READ
);
}
static
int
dsp_ini2
(
void
)
static
int
dsp_ini2
(
void
)
{
#if 0
/* sb_setmixer(0x83, sb_getmixer(0x83) | 0x03);
*/
sb_dsp_command(0xe2);
sb_dsp_command(0x76); /* E0 ??? */
sb_dsp_command(0xe2);
sb_dsp_command(0x30); /* A0 ??? */
sb_dsp_command(0xe4);
sb_dsp_command(0xaa);
sb_dsp_command(0xe8);
if
(read_dsp(100)!=
0xaa)
printk("Error dsp_ini2\n");
/* sb_setmixer(0x83, sb_getmixer(0x83) | 0x03);
*/
sb_dsp_command
(0xe2);
sb_dsp_command
(0x76); /* E0 ??? */
sb_dsp_command
(0xe2);
sb_dsp_command
(0x30); /* A0 ??? */
sb_dsp_command
(0xe4);
sb_dsp_command
(0xaa);
sb_dsp_command
(0xe8);
if
(read_dsp (100) !=
0xaa)
printk
("Error dsp_ini2\n");
#endif
return
0
;
}
/*
static char *dsp_getmessage(unsigned char command,int maxn)
{
static char buff[100];
int n=0;
sb_dsp_command(command);
while(n<maxn && wait_data_avail(2)) {
buff[++n]=INB(DSP_READ);
if(!buff[n])
break;
}
buff[0]=n;
return buff;
}
/*
static char *dsp_getmessage(unsigned char command,int maxn)
{
static char buff[100];
int n=0;
sb_dsp_command(command);
while(n<maxn && wait_data_avail(2L)) {
buff[++n]=INB(DSP_READ);
if(!buff[n])
break;
}
buff[0]=n;
return buff;
}
static void dsp_showmessage(unsigned char command,int len)
{
int n;
unsigned char *c;
c=dsp_getmessage(command,len);
printk("DSP C=%x l=%d,lr=%d b=",command,len,c[0]);
for(n=1;n<=c[0];n++)
if(c[n]>=' ' & c[n]<='z')
printk("%c",c[n]);
else
printk("|%x|",c[n]);
printk("\n");
}
*/
static
int
dsp_set_speed
(
int
mode
)
static void dsp_showmessage(unsigned char command,int len)
{
int n;
unsigned char *c;
c=dsp_getmessage(command,len);
printk("DSP C=%x l=%d,lr=%d b=",command,len,c[0]);
for(n=1;n<=c[0];n++)
if(c[n]>=' ' & c[n]<='z')
printk("%c",c[n]);
else
printk("|%x|",c[n]);
printk("\n");
}
*/
static
int
dsp_set_speed
(
int
mode
)
{
DEB
(
printk
(
"dsp_set_speed(%d)
\n
"
,
mode
));
DEB
(
printk
(
"dsp_set_speed(%d)
\n
"
,
mode
));
if
(
mode
)
{
if
(
mode
<
5000
)
mode
=
5000
;
if
(
mode
>
44100
)
mode
=
44100
;
dsp_current_speed
=
mode
;
}
{
if
(
mode
<
5000
)
mode
=
5000
;
if
(
mode
>
44100
)
mode
=
44100
;
dsp_current_speed
=
mode
;
}
return
mode
;
}
static
int
dsp_set_stereo
(
int
mode
)
static
int
dsp_set_stereo
(
int
mode
)
{
DEB
(
printk
(
"dsp_set_stereo(%d)
\n
"
,
mode
));
DEB
(
printk
(
"dsp_set_stereo(%d)
\n
"
,
mode
));
dsp_stereo
=
mode
;
dsp_stereo
=
mode
;
return
mode
;
}
static
int
dsp_set_bits
(
int
arg
)
{
DEB
(
printk
(
"dsp_set_bits(%d)
\n
"
,
arg
));
static
int
dsp_set_bits
(
int
arg
)
{
DEB
(
printk
(
"dsp_set_bits(%d)
\n
"
,
arg
));
if
(
arg
)
switch
(
arg
)
{
case
8
:
dsp_16bit
=
0
;
break
;
case
16
:
dsp_16bit
=
1
;
break
;
default:
return
RET_ERROR
(
EINVAL
);
}
return
dsp_16bit
?
16
:
8
;
switch
(
arg
)
{
case
8
:
dsp_16bit
=
0
;
break
;
case
16
:
dsp_16bit
=
1
;
break
;
default:
return
RET_ERROR
(
EINVAL
);
}
return
dsp_16bit
?
16
:
8
;
}
static
int
sb16_dsp_ioctl
(
int
dev
,
unsigned
int
cmd
,
unsigned
int
arg
,
int
local
)
sb16_dsp_ioctl
(
int
dev
,
unsigned
int
cmd
,
unsigned
int
arg
,
int
local
)
{
switch
(
cmd
)
{
case
SOUND_PCM_WRITE_RATE
:
if
(
local
)
return
dsp_set_speed
(
arg
);
return
IOCTL_OUT
(
arg
,
dsp_set_speed
(
IOCTL_IN
(
arg
)));
case
SOUND_PCM_READ_RATE
:
if
(
local
)
return
dsp_current_speed
;
return
IOCTL_OUT
(
arg
,
dsp_current_speed
);
case
SNDCTL_DSP_STEREO
:
if
(
local
)
return
dsp_set_stereo
(
arg
);
return
IOCTL_OUT
(
arg
,
dsp_set_stereo
(
IOCTL_IN
(
arg
)));
case
SOUND_PCM_WRITE_CHANNELS
:
if
(
local
)
return
dsp_set_stereo
(
arg
-
1
)
+
1
;
return
IOCTL_OUT
(
arg
,
dsp_set_stereo
(
IOCTL_IN
(
arg
)
-
1
)
+
1
);
case
SOUND_PCM_READ_CHANNELS
:
if
(
local
)
return
dsp_stereo
+
1
;
return
IOCTL_OUT
(
arg
,
dsp_stereo
+
1
);
case
SNDCTL_DSP_SAMPLESIZE
:
if
(
local
)
return
dsp_set_bits
(
arg
);
return
IOCTL_OUT
(
arg
,
dsp_set_bits
(
IOCTL_IN
(
arg
)));
case
SOUND_PCM_READ_BITS
:
if
(
local
)
return
dsp_16bit
?
16
:
8
;
return
IOCTL_OUT
(
arg
,
dsp_16bit
?
16
:
8
);
case
SOUND_PCM_WRITE_FILTER
:
/* NOT YET IMPLEMENTED */
if
(
IOCTL_IN
(
arg
)
>
1
)
return
IOCTL_OUT
(
arg
,
RET_ERROR
(
EINVAL
));
default:
return
RET_ERROR
(
EINVAL
);
}
switch
(
cmd
)
{
case
SOUND_PCM_WRITE_RATE
:
if
(
local
)
return
dsp_set_speed
(
arg
);
return
IOCTL_OUT
(
arg
,
dsp_set_speed
(
IOCTL_IN
(
arg
)));
case
SOUND_PCM_READ_RATE
:
if
(
local
)
return
dsp_current_speed
;
return
IOCTL_OUT
(
arg
,
dsp_current_speed
);
case
SNDCTL_DSP_STEREO
:
if
(
local
)
return
dsp_set_stereo
(
arg
);
return
IOCTL_OUT
(
arg
,
dsp_set_stereo
(
IOCTL_IN
(
arg
)));
case
SOUND_PCM_WRITE_CHANNELS
:
if
(
local
)
return
dsp_set_stereo
(
arg
-
1
)
+
1
;
return
IOCTL_OUT
(
arg
,
dsp_set_stereo
(
IOCTL_IN
(
arg
)
-
1
)
+
1
);
case
SOUND_PCM_READ_CHANNELS
:
if
(
local
)
return
dsp_stereo
+
1
;
return
IOCTL_OUT
(
arg
,
dsp_stereo
+
1
);
case
SNDCTL_DSP_SAMPLESIZE
:
if
(
local
)
return
dsp_set_bits
(
arg
);
return
IOCTL_OUT
(
arg
,
dsp_set_bits
(
IOCTL_IN
(
arg
)));
case
SOUND_PCM_READ_BITS
:
if
(
local
)
return
dsp_16bit
?
16
:
8
;
return
IOCTL_OUT
(
arg
,
dsp_16bit
?
16
:
8
);
case
SOUND_PCM_WRITE_FILTER
:
/* NOT YET IMPLEMENTED */
if
(
IOCTL_IN
(
arg
)
>
1
)
return
IOCTL_OUT
(
arg
,
RET_ERROR
(
EINVAL
));
default:
return
RET_ERROR
(
EINVAL
);
}
return
RET_ERROR
(
EINVAL
);
}
static
int
sb16_dsp_open
(
int
dev
,
int
mode
)
{
int
retval
;
int
retval
;
DEB
(
printk
(
"sb16_dsp_open()
\n
"
));
DEB
(
printk
(
"sb16_dsp_open()
\n
"
));
if
(
!
sb16_dsp_ok
)
{
printk
(
"SB16 Error: SoundBlaster board not installed
\n
"
);
return
RET_ERROR
(
ENXIO
);
return
RET_ERROR
(
ENXIO
);
}
if
(
intr_active
)
return
RET_ERROR
(
EBUSY
);
return
RET_ERROR
(
EBUSY
);
retval
=
sb_get_irq
();
if
(
retval
<
0
)
if
(
retval
<
0
)
return
retval
;
if
(
ALLOC_DMA_CHN
(
dma8
))
{
printk
(
"SB16: Unable to grab DMA%d
\n
"
,
dma8
);
sb_free_irq
();
return
RET_ERROR
(
EBUSY
);
sb_free_irq
();
return
RET_ERROR
(
EBUSY
);
}
if
(
dma16
!=
dma8
)
if
(
ALLOC_DMA_CHN
(
dma16
))
{
printk
(
"SB16: Unable to grab DMA%d
\n
"
,
dma16
);
sb_free_irq
();
RELEASE_DMA_CHN
(
dma8
);
return
RET_ERROR
(
EBUSY
);
}
if
(
ALLOC_DMA_CHN
(
dma16
))
{
printk
(
"SB16: Unable to grab DMA%d
\n
"
,
dma16
);
sb_free_irq
();
RELEASE_DMA_CHN
(
dma8
);
return
RET_ERROR
(
EBUSY
);
}
dsp_ini2
();
dsp_ini2
();
irq_mode
=
IMODE_NONE
;
dsp_busy
=
1
;
...
...
@@ -294,15 +314,16 @@ static void
sb16_dsp_close
(
int
dev
)
{
unsigned
long
flags
;
DEB
(
printk
(
"sb16_dsp_close()
\n
"
));
sb_dsp_command01
(
0xd9
);
sb_dsp_command01
(
0xd5
);
DEB
(
printk
(
"sb16_dsp_close()
\n
"
));
sb_dsp_command01
(
0xd9
);
sb_dsp_command01
(
0xd5
);
DISABLE_INTR
(
flags
);
RELEASE_DMA_CHN
(
dma8
);
if
(
dma16
!=
dma8
)
RELEASE_DMA_CHN
(
dma16
);
RELEASE_DMA_CHN
(
dma16
);
sb_free_irq
();
dsp_cleanup
();
dsp_busy
=
0
;
...
...
@@ -310,7 +331,7 @@ DEB(printk("sb16_dsp_close()\n"));
}
static
void
sb16_dsp_output_block
(
int
dev
,
unsigned
long
buf
,
int
count
,
int
intrflag
,
int
dma_restart
)
sb16_dsp_output_block
(
int
dev
,
unsigned
long
buf
,
int
count
,
int
intrflag
,
int
dma_restart
)
{
unsigned
long
flags
,
cnt
;
...
...
@@ -320,51 +341,54 @@ sb16_dsp_output_block (int dev, unsigned long buf, int count,int intrflag, int d
cnt
--
;
#ifdef DEB_DMARES
printk
(
"output_block: %x %d %d
\n
"
,
buf
,
count
,
intrflag
);
if
(
intrflag
)
{
int
pos
,
chan
=
sound_dsp_dmachan
[
dev
];
DISABLE_INTR
(
flags
);
clear_dma_ff
(
chan
);
disable_dma
(
chan
);
pos
=
get_dma_residue
(
chan
);
enable_dma
(
chan
);
RESTORE_INTR
(
flags
);
printk
(
"dmapos=%d %x
\n
"
,
pos
,
pos
);
}
printk
(
"output_block: %x %d %d
\n
"
,
buf
,
count
,
intrflag
);
if
(
intrflag
)
{
int
pos
,
chan
=
sound_dsp_dmachan
[
dev
];
DISABLE_INTR
(
flags
);
clear_dma_ff
(
chan
);
disable_dma
(
chan
);
pos
=
get_dma_residue
(
chan
);
enable_dma
(
chan
);
RESTORE_INTR
(
flags
);
printk
(
"dmapos=%d %x
\n
"
,
pos
,
pos
);
}
#endif
if
(
sound_dma_automode
[
dev
]
&&
intrflag
&&
cnt
==
dsp_count
)
{
irq_mode
=
IMODE_OUTPUT
;
intr_active
=
1
;
return
;
/* Auto mode on. No need to react */
}
cnt
==
dsp_count
)
{
irq_mode
=
IMODE_OUTPUT
;
intr_active
=
1
;
return
;
/* Auto mode on. No need to react */
}
DISABLE_INTR
(
flags
);
if
(
dma_restart
)
{
sb16_dsp_halt
(
dev
);
DMAbuf_start_dma
(
dev
,
buf
,
count
,
DMA_MODE_WRITE
);
}
{
sb16_dsp_halt
(
dev
);
DMAbuf_start_dma
(
dev
,
buf
,
count
,
DMA_MODE_WRITE
);
}
sb_dsp_command
(
0x41
);
sb_dsp_command
((
unsigned
char
)((
dsp_current_speed
>>
8
)
&
0xff
));
sb_dsp_command
((
unsigned
char
)(
dsp_current_speed
&
0xff
));
sb_dsp_command
((
unsigned
char
)(
dsp_16bit
?
0xb6
:
0xc6
));
sb_dsp_command
((
unsigned
char
)
((
dsp_stereo
?
0x20
:
0
)
+
(
dsp_16bit
?
0x10
:
0
)));
sb_dsp_command01
((
unsigned
char
)
(
cnt
&
0xff
));
sb_dsp_command
((
unsigned
char
)
(
cnt
>>
8
));
sb_dsp_command
((
unsigned
char
)
((
dsp_current_speed
>>
8
)
&
0xff
));
sb_dsp_command
((
unsigned
char
)
(
dsp_current_speed
&
0xff
));
sb_dsp_command
((
unsigned
char
)
(
dsp_16bit
?
0xb6
:
0xc6
));
sb_dsp_command
((
unsigned
char
)
((
dsp_stereo
?
0x20
:
0
)
+
(
dsp_16bit
?
0x10
:
0
)));
sb_dsp_command01
((
unsigned
char
)
(
cnt
&
0xff
));
sb_dsp_command
((
unsigned
char
)
(
cnt
>>
8
));
/* sb_dsp_command (0);
sb_dsp_command (0); */
sb_dsp_command (0); */
RESTORE_INTR
(
flags
);
dsp_count
=
cnt
;
dsp_count
=
cnt
;
irq_mode
=
IMODE_OUTPUT
;
intr_active
=
1
;
}
static
void
sb16_dsp_start_input
(
int
dev
,
unsigned
long
buf
,
int
count
,
int
intrflag
,
int
dma_restart
)
sb16_dsp_start_input
(
int
dev
,
unsigned
long
buf
,
int
count
,
int
intrflag
,
int
dma_restart
)
{
unsigned
long
flags
,
cnt
;
...
...
@@ -374,46 +398,49 @@ sb16_dsp_start_input (int dev, unsigned long buf, int count,int intrflag, int dm
cnt
--
;
#ifdef DEB_DMARES
printk
(
"start_input: %x %d %d
\n
"
,
buf
,
count
,
intrflag
);
if
(
intrflag
)
{
int
pos
,
chan
=
sound_dsp_dmachan
[
dev
];
DISABLE_INTR
(
flags
);
clear_dma_ff
(
chan
);
disable_dma
(
chan
);
pos
=
get_dma_residue
(
chan
);
enable_dma
(
chan
);
RESTORE_INTR
(
flags
);
printk
(
"dmapos=%d %x
\n
"
,
pos
,
pos
);
}
printk
(
"start_input: %x %d %d
\n
"
,
buf
,
count
,
intrflag
);
if
(
intrflag
)
{
int
pos
,
chan
=
sound_dsp_dmachan
[
dev
];
DISABLE_INTR
(
flags
);
clear_dma_ff
(
chan
);
disable_dma
(
chan
);
pos
=
get_dma_residue
(
chan
);
enable_dma
(
chan
);
RESTORE_INTR
(
flags
);
printk
(
"dmapos=%d %x
\n
"
,
pos
,
pos
);
}
#endif
if
(
sound_dma_automode
[
dev
]
&&
intrflag
&&
cnt
==
dsp_count
)
{
irq_mode
=
IMODE_INPUT
;
intr_active
=
1
;
return
;
/* Auto mode on. No need to react */
}
cnt
==
dsp_count
)
{
irq_mode
=
IMODE_INPUT
;
intr_active
=
1
;
return
;
/* Auto mode on. No need to react */
}
DISABLE_INTR
(
flags
);
if
(
dma_restart
)
{
sb16_dsp_halt
(
dev
);
if
(
dma_restart
)
{
sb16_dsp_halt
(
dev
);
DMAbuf_start_dma
(
dev
,
buf
,
count
,
DMA_MODE_READ
);
}
}
sb_dsp_command
(
0x42
);
sb_dsp_command
((
unsigned
char
)((
dsp_current_speed
>>
8
)
&
0xff
));
sb_dsp_command
((
unsigned
char
)(
dsp_current_speed
&
0xff
));
sb_dsp_command
((
unsigned
char
)(
dsp_16bit
?
0xbe
:
0xce
));
sb_dsp_command
((
unsigned
char
)
((
dsp_stereo
?
0x20
:
0
)
+
(
dsp_16bit
?
0x10
:
0
)));
sb_dsp_command01
((
unsigned
char
)
(
cnt
&
0xff
));
sb_dsp_command
((
unsigned
char
)
(
cnt
>>
8
));
sb_dsp_command
((
unsigned
char
)
((
dsp_current_speed
>>
8
)
&
0xff
));
sb_dsp_command
((
unsigned
char
)
(
dsp_current_speed
&
0xff
));
sb_dsp_command
((
unsigned
char
)
(
dsp_16bit
?
0xbe
:
0xce
));
sb_dsp_command
((
unsigned
char
)
((
dsp_stereo
?
0x20
:
0
)
+
(
dsp_16bit
?
0x10
:
0
)));
sb_dsp_command01
((
unsigned
char
)
(
cnt
&
0xff
));
sb_dsp_command
((
unsigned
char
)
(
cnt
>>
8
));
/* sb_dsp_command (0);
sb_dsp_command (0); */
sb_dsp_command (0); */
RESTORE_INTR
(
flags
);
dsp_count
=
cnt
;
dsp_count
=
cnt
;
irq_mode
=
IMODE_INPUT
;
intr_active
=
1
;
}
...
...
@@ -421,7 +448,7 @@ printk("start_input: %x %d %d\n",buf,count,intrflag);
static
int
sb16_dsp_prepare_for_input
(
int
dev
,
int
bsize
,
int
bcount
)
{
sound_dsp_dmachan
[
my_dev
]
=
dsp_16bit
?
dma16
:
dma8
;
sound_dsp_dmachan
[
my_dev
]
=
dsp_16bit
?
dma16
:
dma8
;
dsp_count
=
0
;
dsp_cleanup
();
return
0
;
...
...
@@ -430,7 +457,7 @@ sb16_dsp_prepare_for_input (int dev, int bsize, int bcount)
static
int
sb16_dsp_prepare_for_output
(
int
dev
,
int
bsize
,
int
bcount
)
{
sound_dsp_dmachan
[
my_dev
]
=
dsp_16bit
?
dma16
:
dma8
;
sound_dsp_dmachan
[
my_dev
]
=
dsp_16bit
?
dma16
:
dma8
;
dsp_count
=
0
;
dsp_cleanup
();
return
0
;
...
...
@@ -446,7 +473,7 @@ dsp_cleanup (void)
static
void
sb16_dsp_reset
(
int
dev
)
{
unsigned
long
flags
;
unsigned
long
flags
;
DISABLE_INTR
(
flags
);
...
...
@@ -460,61 +487,52 @@ static void
sb16_dsp_halt
(
int
dev
)
{
if
(
dsp_16bit
)
{
sb_dsp_command01
(
0xd9
);
sb_dsp_command01
(
0xd5
);
}
{
sb_dsp_command01
(
0xd9
);
sb_dsp_command01
(
0xd5
);
}
else
{
sb_dsp_command01
(
0xda
);
sb_dsp_command01
(
0xd0
);
}
{
sb_dsp_command01
(
0xda
);
sb_dsp_command01
(
0xd0
);
}
}
static
void
set_irq_hw
(
int
level
)
{
int
ival
;
switch
(
level
)
{
case
5
:
ival
=
2
;
break
;
case
7
:
ival
=
4
;
break
;
case
10
:
ival
=
8
;
break
;
default:
printk
(
"SB16_IRQ_LEVEL %d does not exist
\n
"
,
level
);
return
;
}
sb_setmixer
(
IRQ_NR
,
ival
);
set_irq_hw
(
int
level
)
{
int
ival
;
switch
(
level
)
{
case
5
:
ival
=
2
;
break
;
case
7
:
ival
=
4
;
break
;
case
10
:
ival
=
8
;
break
;
default:
printk
(
"SB16_IRQ_LEVEL %d does not exist
\n
"
,
level
);
return
;
}
sb_setmixer
(
IRQ_NR
,
ival
);
}
long
sb16_dsp_init
(
long
mem_start
,
struct
address_info
*
hw_config
)
{
int
i
,
major
,
minor
;
major
=
minor
=
0
;
sb_dsp_command
(
0xe1
);
/* Get version */
for
(
i
=
1000
;
i
;
i
--
)
{
if
(
INB
(
DSP_DATA_AVAIL
)
&
0x80
)
{
/* wait for Data Ready */
if
(
major
==
0
)
major
=
INB
(
DSP_READ
);
else
{
minor
=
INB
(
DSP_READ
);
break
;
}
}
}
if
(
sbc_major
<
4
)
return
mem_start
;
#ifndef SCO
sprintf
(
sb16_dsp_operations
.
name
,
"SoundBlaster 16 %d.%d"
,
major
,
minor
);
#ifndef SCO
sprintf
(
sb16_dsp_operations
.
name
,
"SoundBlaster 16 %d.%d"
,
sbc_major
,
sbc_
minor
);
#endif
printk
(
" <%s>"
,
sb16_dsp_operations
.
name
);
if
(
num_dspdevs
<
MAX_DSP_DEV
)
{
dsp_devs
[
my_dev
=
num_dspdevs
++
]
=
&
sb16_dsp_operations
;
...
...
@@ -537,47 +555,37 @@ sb16_dsp_detect (struct address_info *hw_config)
if
(
sb16_dsp_ok
)
return
1
;
/* Already initialized */
if
(
!
(
sb_config
=
sound_getconf
(
SNDCARD_SB
)))
{
printk
(
"SB16 Error: Plain SB not configured
\n
"
);
return
0
;
}
if
(
sbc_base
!=
hw_config
->
io_base
)
printk
(
"Warning! SB16 I/O != SB I/O
\n
"
);
if
(
!
(
sb_config
=
sound_getconf
(
SNDCARD_SB
)))
{
printk
(
"SB16 Error: Plain SB not configured
\n
"
);
return
0
;
}
/* sb_setmixer(OPSW,0xf);
if(sb_getmixer(OPSW)!=0xf)
return 0; */
if(sb_getmixer(OPSW)!=0xf)
return 0; */
if
(
!
sb_reset_dsp
())
return
0
;
if
(
hw_config
->
irq
!=
sb_config
->
irq
)
{
printk
(
"SB16 Error: Invalid IRQ number %d/%d
\n
"
,
sb_config
->
irq
,
hw_config
->
irq
);
return
0
;
}
if
(
hw_config
->
dma
<
4
)
if
(
hw_config
->
dma
!=
sb_config
->
dma
)
{
printk
(
"SB16 Error: Invalid DMA channel %d/%d
\n
"
,
sb_config
->
dma
,
hw_config
->
dma
);
return
0
;
}
if
(
hw_config
->
dma
!=
sb_config
->
dma
)
{
printk
(
"SB16 Error: Invalid DMA channel %d/%d
\n
"
,
sb_config
->
dma
,
hw_config
->
dma
);
return
0
;
}
dma16
=
hw_config
->
dma
;
dma8
=
sb_config
->
dma
;
set_irq_hw
(
hw
_config
->
irq
);
sb_setmixer
(
DMA_NR
,
(
1
<<
hw_config
->
dma
)
|
(
1
<<
sb_config
->
dma
));
set_irq_hw
(
sb
_config
->
irq
);
sb_setmixer
(
DMA_NR
,
(
1
<<
hw_config
->
dma
)
|
(
1
<<
sb_config
->
dma
));
DEB
(
printk
(
"SoundBlaster 16: IRQ %d DMA %d OK
\n
"
,
hw_config
->
irq
,
hw_config
->
dma
));
/*
dsp_showmessage(0xe3,99);
*/
DEB
(
printk
(
"SoundBlaster 16: IRQ %d DMA %d OK
\n
"
,
sb_config
->
irq
,
hw_config
->
dma
));
/*
dsp_showmessage(0xe3,99);
*/
sb16_dsp_ok
=
1
;
return
1
;
}
...
...
@@ -585,24 +593,26 @@ sb16_dsp_detect (struct address_info *hw_config)
void
sb16_dsp_interrupt
(
int
unused
)
{
int
data
;
data
=
INB
(
DSP_DATA_AVL16
);
/* Interrupt acknowledge */
if
(
intr_active
)
switch
(
irq_mode
)
{
case
IMODE_OUTPUT
:
intr_active
=
0
;
DMAbuf_outputintr
(
my_dev
,
1
);
break
;
case
IMODE_INPUT
:
intr_active
=
0
;
DMAbuf_inputintr
(
my_dev
);
break
;
default:
printk
(
"SoundBlaster: Unexpected interrupt
\n
"
);
}
int
data
;
data
=
INB
(
DSP_DATA_AVL16
);
/* Interrupt acknowledge */
if
(
intr_active
)
switch
(
irq_mode
)
{
case
IMODE_OUTPUT
:
intr_active
=
0
;
DMAbuf_outputintr
(
my_dev
,
1
);
break
;
case
IMODE_INPUT
:
intr_active
=
0
;
DMAbuf_inputintr
(
my_dev
);
break
;
default:
printk
(
"SoundBlaster: Unexpected interrupt
\n
"
);
}
}
#endif
drivers/sound/sb16_midi.c
View file @
e695b6a4
/*
* sound/sb16_midi.c
*
*
* The low level driver for the MPU-401 UART emulation of the SB16.
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -12,7 +12,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -24,7 +24,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#include "sound_config.h"
...
...
@@ -58,26 +58,19 @@ static int my_dev;
static
int
reset_sb16midi
(
void
);
static
void
(
*
midi_input_intr
)
(
int
dev
,
unsigned
char
data
);
extern
int
sbc_major
;
static
void
sb16midi_input_loop
(
void
)
{
int
count
;
count
=
10
;
while
(
count
)
/* Not timed out */
if
(
input_avail
())
{
unsigned
char
c
=
sb16midi_read
();
count
=
100
;
while
(
input_avail
())
{
unsigned
char
c
=
sb16midi_read
();
if
(
sb16midi_opened
&
OPEN_READ
)
midi_input_intr
(
my_dev
,
c
);
}
else
while
(
!
input_avail
()
&&
count
)
count
--
;
if
(
sb16midi_opened
&
OPEN_READ
)
midi_input_intr
(
my_dev
,
c
);
}
}
void
...
...
@@ -87,35 +80,10 @@ sb16midiintr (int unit)
sb16midi_input_loop
();
}
/*
* It looks like there is no input interrupts in the UART mode. Let's try
* polling.
*/
static
void
poll_sb16midi
(
unsigned
long
dummy
)
{
unsigned
long
flags
;
DEFINE_TIMER
(
sb16midi_timer
,
poll_sb16midi
);
if
(
!
(
sb16midi_opened
&
OPEN_READ
))
return
;
/* No longer required */
DISABLE_INTR
(
flags
);
if
(
input_avail
())
sb16midi_input_loop
();
ACTIVATE_TIMER
(
sb16midi_timer
,
poll_sb16midi
,
1
);
/* Come back later */
RESTORE_INTR
(
flags
);
}
static
int
sb16midi_open
(
int
dev
,
int
mode
,
void
(
*
input
)
(
int
dev
,
unsigned
char
data
),
void
(
*
output
)
(
int
dev
)
void
(
*
input
)
(
int
dev
,
unsigned
char
data
),
void
(
*
output
)
(
int
dev
)
)
{
if
(
sb16midi_opened
)
...
...
@@ -127,7 +95,6 @@ sb16midi_open (int dev, int mode,
midi_input_intr
=
input
;
sb16midi_opened
=
mode
;
poll_sb16midi
(
0
);
/* Enable input polling */
return
0
;
}
...
...
@@ -299,6 +266,8 @@ probe_sb16midi (struct address_info *hw_config)
int
ok
=
0
;
sb16midi_base
=
hw_config
->
io_base
;
if
(
sbc_major
<
4
)
return
0
;
/* SB16 not detected */
if
(
sb_get_irq
()
<
0
)
return
0
;
...
...
drivers/sound/sb_card.c
View file @
e695b6a4
/*
* sound/sb_card.c
*
*
* Detection routine for the SoundBlaster cards.
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -12,7 +12,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -24,7 +24,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#include "sound_config.h"
...
...
drivers/sound/sb_dsp.c
View file @
e695b6a4
/*
* sound/sb_dsp.c
*
*
* The low level driver for the SoundBlaster DSP chip.
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -12,7 +12,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -24,7 +24,11 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
* Modified:
* Hunyue Yau Jan 6 1994
* Added code to support Sound Galaxy NX Pro
*
*/
#include "sound_config.h"
...
...
@@ -35,8 +39,9 @@
#include "sb_mixer.h"
#undef SB_TEST_IRQ
int
sbc_base
=
0
;
int
sbc_base
=
0
;
static
int
sbc_irq
=
0
;
static
int
open_mode
=
0
;
/*
* The DSP channel can be used either for input or output. Variable
...
...
@@ -46,32 +51,33 @@ static int sbc_irq = 0;
* future version of this driver.
*/
int
sb_dsp_ok
=
0
;
/* Set to 1 after successful initialization */
int
sb_dsp_ok
=
0
;
/* Set to 1 after successful initialization */
static
int
midi_disabled
=
0
;
int
sb_dsp_highspeed
=
0
;
static
int
major
=
1
,
minor
=
0
;
/* DSP version */
static
int
dsp_stereo
=
0
;
int
sb_dsp_highspeed
=
0
;
int
sbc_major
=
1
;
int
sbc_minor
=
0
;
/* DSP version */
static
int
dsp_stereo
=
0
;
static
int
dsp_current_speed
=
DSP_DEFAULT_SPEED
;
static
int
sb16
=
0
;
static
int
irq_verified
=
0
;
static
int
irq_verified
=
0
;
int
sb_midi_mode
=
NORMAL_MIDI
;
int
sb_midi_busy
=
0
;
/* 1 if the process has output to MIDI */
int
sb_dsp_busy
=
0
;
int
sb_midi_mode
=
NORMAL_MIDI
;
int
sb_midi_busy
=
0
;
/* 1 if the process has output to MIDI */
int
sb_dsp_busy
=
0
;
volatile
int
sb_irq_mode
=
IMODE_NONE
;
/* IMODE_INPUT, IMODE_OUTPUT
volatile
int
sb_irq_mode
=
IMODE_NONE
;
/* IMODE_INPUT, IMODE_OUTPUT
* or IMODE_NONE */
static
volatile
int
irq_ok
=
0
;
int
sb_dsp_model
=
1
;
/* 1=SB, 2=SB Pro */
int
sb_duplex_midi
=
0
;
int
sb_duplex_midi
=
0
;
static
int
my_dev
=
0
;
volatile
int
sb_intr_active
=
0
;
volatile
int
sb_intr_active
=
0
;
static
int
dsp_speed
(
int
);
static
int
dsp_set_stereo
(
int
mode
);
int
sb_dsp_command
(
unsigned
char
val
);
int
sb_dsp_command
(
unsigned
char
val
);
#if !defined(EXCLUDE_MIDI) || !defined(EXCLUDE_AUDIO)
...
...
@@ -80,9 +86,10 @@ int sb_dsp_command (unsigned char val);
int
sb_dsp_command
(
unsigned
char
val
)
{
int
i
,
limit
;
int
i
;
unsigned
long
limit
;
limit
=
GET_TIME
()
+
10
;
/* The timeout is 0.1 secods */
limit
=
GET_TIME
()
+
HZ
/
10
;
/* The timeout is 0.1 secods */
/*
* Note! the i<500000 is an emergency exit. The sb_dsp_command() is sometimes
...
...
@@ -109,7 +116,7 @@ sb_dsp_command (unsigned char val)
void
sbintr
(
int
unit
)
{
int
status
,
data
;
int
status
;
#ifndef EXCLUDE_SBPRO
if
(
sb16
)
...
...
@@ -117,10 +124,12 @@ sbintr (int unit)
unsigned
char
src
=
sb_getmixer
(
IRQ_STAT
);
/* Interrupt source register */
#ifndef EXCLUDE_SB16
if
(
src
&
3
)
sb16_dsp_interrupt
(
unit
);
if
(
src
&
3
)
sb16_dsp_interrupt
(
unit
);
#ifndef EXCLUDE_MIDI
if
(
src
&
4
)
sb16midiintr
(
unit
);
/* MPU401 interrupt */
if
(
src
&
4
)
sb16midiintr
(
unit
);
/* MPU401 interrupt */
#endif
#endif
...
...
@@ -152,10 +161,7 @@ sbintr (int unit)
break
;
case
IMODE_MIDI
:
printk
(
"+"
);
data
=
INB
(
DSP_READ
);
printk
(
"%x"
,
data
);
sb_midi_interrupt
(
unit
);
break
;
default:
...
...
@@ -163,29 +169,32 @@ sbintr (int unit)
}
}
static
int
sb_irq_usecount
=
0
;
static
int
sb_irq_usecount
=
0
;
int
sb_get_irq
(
void
)
sb_get_irq
(
void
)
{
int
ok
;
int
ok
;
if
(
!
sb_irq_usecount
)
if
((
ok
=
snd_set_irq_handler
(
sbc_irq
,
sbintr
))
<
0
)
return
ok
;
if
(
!
sb_irq_usecount
)
if
((
ok
=
snd_set_irq_handler
(
sbc_irq
,
sbintr
))
<
0
)
return
ok
;
sb_irq_usecount
++
;
sb_irq_usecount
++
;
return
0
;
return
0
;
}
void
sb_free_irq
(
void
)
void
sb_free_irq
(
void
)
{
if
(
!
sb_irq_usecount
)
return
;
if
(
!
sb_irq_usecount
)
return
;
sb_irq_usecount
--
;
sb_irq_usecount
--
;
if
(
!
sb_irq_usecount
)
snd_release_irq
(
sbc_irq
);
if
(
!
sb_irq_usecount
)
snd_release_irq
(
sbc_irq
);
}
int
...
...
@@ -227,17 +236,31 @@ dsp_speed (int speed)
{
unsigned
char
tconst
;
unsigned
long
flags
;
int
max_speed
=
44100
;
if
(
speed
<
4000
)
speed
=
4000
;
if
(
speed
>
44100
)
speed
=
44100
;
/* Invalid speed */
/*
* Older SB models don't support higher speeds than 22050.
*/
if
(
sbc_major
<
2
||
(
sbc_major
==
2
&&
sbc_minor
==
0
))
max_speed
=
22050
;
if
(
sb_dsp_model
==
1
&&
speed
>
22050
)
speed
=
22050
;
/* SB Classic doesn't support higher speed */
/*
* SB models earlier than SB Pro have low limit for the input speed.
*/
if
(
open_mode
!=
OPEN_WRITE
)
/* Recording is possible */
if
(
sbc_major
<
3
)
/* Limited input speed with these cards */
if
(
sbc_major
==
2
&&
sbc_minor
>
0
)
max_speed
=
15000
;
else
max_speed
=
13000
;
if
(
speed
>
max_speed
)
speed
=
max_speed
;
/* Invalid speed */
if
(
dsp_stereo
&&
speed
>
22050
)
speed
=
22050
;
...
...
@@ -256,10 +279,10 @@ dsp_speed (int speed)
if
(
speed
>
22050
)
{
/* High speed mode */
int
tmp
;
int
tmp
;
tconst
=
(
unsigned
char
)
((
65536
-
((
256000000
+
speed
/
2
)
/
speed
))
>>
8
);
tconst
=
(
unsigned
char
)
((
65536
-
((
256000000
+
speed
/
2
)
/
speed
))
>>
8
);
sb_dsp_highspeed
=
1
;
DISABLE_INTR
(
flags
);
...
...
@@ -268,22 +291,22 @@ dsp_speed (int speed)
RESTORE_INTR
(
flags
);
tmp
=
65536
-
(
tconst
<<
8
);
speed
=
(
256000000
+
tmp
/
2
)
/
tmp
;
speed
=
(
256000000
+
tmp
/
2
)
/
tmp
;
}
else
{
int
tmp
;
int
tmp
;
sb_dsp_highspeed
=
0
;
tconst
=
(
256
-
((
1000000
+
speed
/
2
)
/
speed
))
&
0xff
;
tconst
=
(
256
-
((
1000000
+
speed
/
2
)
/
speed
))
&
0xff
;
DISABLE_INTR
(
flags
);
if
(
sb_dsp_command
(
0x40
))
/* Set time constant */
if
(
sb_dsp_command
(
0x40
))
/* Set time constant */
sb_dsp_command
(
tconst
);
RESTORE_INTR
(
flags
);
tmp
=
256
-
tconst
;
speed
=
(
1000000
+
tmp
/
2
)
/
tmp
;
speed
=
(
1000000
+
tmp
/
2
)
/
tmp
;
}
if
(
dsp_stereo
)
...
...
@@ -301,7 +324,7 @@ dsp_set_stereo (int mode)
#ifdef EXCLUDE_SBPRO
return
0
;
#else
if
(
sb
_dsp_model
==
1
||
sb16
)
if
(
sb
c_major
<
3
||
sb16
)
return
0
;
/* Sorry no stereo */
if
(
mode
&&
sb_midi_busy
)
...
...
@@ -316,7 +339,7 @@ dsp_set_stereo (int mode)
}
static
void
sb_dsp_output_block
(
int
dev
,
unsigned
long
buf
,
int
count
,
sb_dsp_output_block
(
int
dev
,
unsigned
long
buf
,
int
count
,
int
intrflag
,
int
restart_dma
)
{
unsigned
long
flags
;
...
...
@@ -334,11 +357,11 @@ sb_dsp_output_block (int dev, unsigned long buf, int count,
if
(
sb_dsp_highspeed
)
{
DISABLE_INTR
(
flags
);
if
(
sb_dsp_command
(
0x48
))
/* High speed size */
if
(
sb_dsp_command
(
0x48
))
/* High speed size */
{
sb_dsp_command
((
unsigned
char
)(
count
&
0xff
));
sb_dsp_command
((
unsigned
char
)((
count
>>
8
)
&
0xff
));
sb_dsp_command
(
0x91
);
/* High speed 8 bit DAC */
sb_dsp_command
((
unsigned
char
)
(
count
&
0xff
));
sb_dsp_command
((
unsigned
char
)
((
count
>>
8
)
&
0xff
));
sb_dsp_command
(
0x91
);
/* High speed 8 bit DAC */
}
else
printk
(
"SB Error: Unable to start (high speed) DAC
\n
"
);
...
...
@@ -347,10 +370,10 @@ sb_dsp_output_block (int dev, unsigned long buf, int count,
else
{
DISABLE_INTR
(
flags
);
if
(
sb_dsp_command
(
0x14
))
/* 8-bit DAC (DMA) */
if
(
sb_dsp_command
(
0x14
))
/* 8-bit DAC (DMA) */
{
sb_dsp_command
((
unsigned
char
)(
count
&
0xff
));
sb_dsp_command
((
unsigned
char
)((
count
>>
8
)
&
0xff
));
sb_dsp_command
((
unsigned
char
)
(
count
&
0xff
));
sb_dsp_command
((
unsigned
char
)
((
count
>>
8
)
&
0xff
));
}
else
printk
(
"SB Error: Unable to start DAC
\n
"
);
...
...
@@ -380,11 +403,11 @@ sb_dsp_start_input (int dev, unsigned long buf, int count, int intrflag,
if
(
sb_dsp_highspeed
)
{
DISABLE_INTR
(
flags
);
if
(
sb_dsp_command
(
0x48
))
/* High speed size */
if
(
sb_dsp_command
(
0x48
))
/* High speed size */
{
sb_dsp_command
((
unsigned
char
)(
count
&
0xff
));
sb_dsp_command
((
unsigned
char
)((
count
>>
8
)
&
0xff
));
sb_dsp_command
(
0x99
);
/* High speed 8 bit ADC */
sb_dsp_command
((
unsigned
char
)
(
count
&
0xff
));
sb_dsp_command
((
unsigned
char
)
((
count
>>
8
)
&
0xff
));
sb_dsp_command
(
0x99
);
/* High speed 8 bit ADC */
}
else
printk
(
"SB Error: Unable to start (high speed) ADC
\n
"
);
...
...
@@ -393,10 +416,10 @@ sb_dsp_start_input (int dev, unsigned long buf, int count, int intrflag,
else
{
DISABLE_INTR
(
flags
);
if
(
sb_dsp_command
(
0x24
))
/* 8-bit ADC (DMA) */
if
(
sb_dsp_command
(
0x24
))
/* 8-bit ADC (DMA) */
{
sb_dsp_command
((
unsigned
char
)(
count
&
0xff
));
sb_dsp_command
((
unsigned
char
)((
count
>>
8
)
&
0xff
));
sb_dsp_command
((
unsigned
char
)
(
count
&
0xff
));
sb_dsp_command
((
unsigned
char
)
((
count
>>
8
)
&
0xff
));
}
else
printk
(
"SB Error: Unable to start ADC
\n
"
);
...
...
@@ -418,16 +441,16 @@ sb_dsp_prepare_for_input (int dev, int bsize, int bcount)
dsp_cleanup
();
dsp_speaker
(
OFF
);
if
(
major
==
3
)
/* SB Pro */
{
if
(
dsp_stereo
)
sb_dsp_command
(
0xa8
);
else
sb_dsp_command
(
0xa0
);
if
(
sbc_major
==
3
)
/* SB Pro */
{
if
(
dsp_stereo
)
sb_dsp_command
(
0xa8
);
else
sb_dsp_command
(
0xa0
);
dsp_speed
(
dsp_current_speed
);
/* Speed must be recalculated if #channels
* changes */
}
dsp_speed
(
dsp_current_speed
);
/* Speed must be recalculated if #channels
* changes */
}
return
0
;
}
...
...
@@ -438,12 +461,12 @@ sb_dsp_prepare_for_output (int dev, int bsize, int bcount)
dsp_speaker
(
ON
);
#ifndef EXCLUDE_SBPRO
if
(
major
==
3
)
/* SB Pro */
{
sb_mixer_set_stereo
(
dsp_stereo
);
dsp_speed
(
dsp_current_speed
);
/* Speed must be recalculated if #channels
* changes */
}
if
(
sbc_major
==
3
)
/* SB Pro */
{
sb_mixer_set_stereo
(
dsp_stereo
);
dsp_speed
(
dsp_current_speed
);
/* Speed must be recalculated if #channels
* changes */
}
#endif
return
0
;
}
...
...
@@ -457,7 +480,7 @@ static int
verify_irq
(
void
)
{
#if 0
DEFINE_WAIT_QUEUE(testq, testf);
DEFINE_WAIT_QUEUE
(testq, testf);
irq_ok = 0;
...
...
@@ -470,11 +493,11 @@ verify_irq (void)
sb_irq_mode = IMODE_INIT;
sb_dsp_command (0xf2);
/* This should cause immediate interrupt */
sb_dsp_command (0xf2); /* This should cause immediate interrupt */
DO_SLEEP(testq, testf, HZ / 5);
DO_SLEEP
(testq, testf, HZ / 5);
sb_free_irq();
sb_free_irq
();
if (!irq_ok)
{
...
...
@@ -506,13 +529,12 @@ sb_dsp_open (int dev, int mode)
if
(
!
irq_verified
)
{
verify_irq
();
irq_verified
=
1
;
verify_irq
();
irq_verified
=
1
;
}
else
if
(
!
irq_ok
)
printk
(
"SB Warning: Incorrect IRQ setting %d
\n
"
,
sbc_irq
);
else
if
(
!
irq_ok
)
printk
(
"SB Warning: Incorrect IRQ setting %d
\n
"
,
sbc_irq
);
retval
=
sb_get_irq
();
if
(
retval
)
...
...
@@ -528,6 +550,7 @@ sb_dsp_open (int dev, int mode)
sb_irq_mode
=
IMODE_NONE
;
sb_dsp_busy
=
1
;
open_mode
=
mode
;
return
0
;
}
...
...
@@ -541,6 +564,7 @@ sb_dsp_close (int dev)
dsp_speaker
(
OFF
);
sb_dsp_busy
=
0
;
sb_dsp_highspeed
=
0
;
open_mode
=
0
;
}
static
int
...
...
@@ -562,7 +586,7 @@ sb_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
case
SOUND_PCM_WRITE_CHANNELS
:
if
(
local
)
return
dsp_set_stereo
(
arg
-
1
)
+
1
;
return
dsp_set_stereo
(
arg
-
1
)
+
1
;
return
IOCTL_OUT
(
arg
,
dsp_set_stereo
(
IOCTL_IN
(
arg
)
-
1
)
+
1
);
break
;
...
...
@@ -605,6 +629,7 @@ sb_dsp_reset (int dev)
DISABLE_INTR
(
flags
);
sb_reset_dsp
();
dsp_speed
(
dsp_current_speed
);
dsp_cleanup
();
RESTORE_INTR
(
flags
);
...
...
@@ -631,6 +656,7 @@ sb_dsp_detect (struct address_info *hw_config)
static
struct
audio_operations
sb_dsp_operations
=
{
"SoundBlaster"
,
NOTHING_SPECIAL
,
sb_dsp_open
,
sb_dsp_close
,
sb_dsp_output_block
,
...
...
@@ -650,80 +676,85 @@ long
sb_dsp_init
(
long
mem_start
,
struct
address_info
*
hw_config
)
{
int
i
;
int
prostat
=
0
;
major
=
minor
=
0
;
sb_dsp_command
(
0xe1
);
/* Get version */
sbc_major
=
sbc_
minor
=
0
;
sb_dsp_command
(
0xe1
);
/* Get version */
for
(
i
=
1000
;
i
;
i
--
)
{
if
(
INB
(
DSP_DATA_AVAIL
)
&
0x80
)
{
/* wait for Data Ready */
if
(
major
==
0
)
major
=
INB
(
DSP_READ
);
if
(
sbc_
major
==
0
)
sbc_
major
=
INB
(
DSP_READ
);
else
{
minor
=
INB
(
DSP_READ
);
sbc_
minor
=
INB
(
DSP_READ
);
break
;
}
}
}
if
(
major
==
2
||
major
==
3
)
sb_duplex_midi
=
1
;
if
(
major
==
4
)
sb16
=
1
;
if
(
sbc_major
==
2
||
sbc_major
==
3
)
/* SB 2.0 or SB Pro */
sb_duplex_midi
=
1
;
if
(
major
>=
3
)
sb_dsp_model
=
2
;
if
(
sbc_major
==
4
)
sb16
=
1
;
#ifndef EXCLUDE_SBPRO
if
(
major
>=
3
)
sb_mixer_init
(
major
);
if
(
sbc_major
>=
3
||
(
sbc_major
==
2
&&
sbc_minor
==
1
))
/* Sound Galaxy ??? */
prostat
=
sb_mixer_init
(
sbc_major
);
#endif
#ifndef EXCLUDE_YM3812
if
(
major
>
3
||
(
major
==
3
&&
minor
>
0
))
/* SB Pro2 or later */
{
enable_opl3_mode
(
OPL3_LEFT
,
OPL3_RIGHT
,
OPL3_BOTH
);
}
if
(
sbc_major
>
3
||
(
sbc_major
==
3
&&
INB
(
0x388
)
==
0x00
))
/* Non OPL-3 should return 0x06 */
enable_opl3_mode
(
OPL3_LEFT
,
OPL3_RIGHT
,
OPL3_BOTH
);
#endif
if
(
major
>=
3
)
{
if
(
sbc_
major
>=
3
)
{
#ifndef SCO
sprintf
(
sb_dsp_operations
.
name
,
"SoundBlaster Pro %d.%d"
,
major
,
minor
);
if
(
prostat
)
{
sprintf
(
sb_dsp_operations
.
name
,
"Sound Galaxy NX Pro %d.%d"
,
sbc_major
,
sbc_minor
);
}
else
{
sprintf
(
sb_dsp_operations
.
name
,
"SoundBlaster Pro %d.%d"
,
sbc_major
,
sbc_minor
);
}
#endif
}
else
{
}
else
{
#ifndef SCO
sprintf
(
sb_dsp_operations
.
name
,
"SoundBlaster %d.%d"
,
major
,
minor
);
sprintf
(
sb_dsp_operations
.
name
,
"SoundBlaster %d.%d"
,
sbc_major
,
sbc_
minor
);
#endif
}
}
printk
(
" <%s>"
,
sb_dsp_operations
.
name
);
#ifndef EXCLUDE_AUDIO
#
if !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SBPRO)
if
(
!
sb16
)
/* There is a better driver for SB16
*/
#
endif
if
(
num_dspdevs
<
MAX_DSP_DEV
)
{
dsp_devs
[
my_dev
=
num_dspdevs
++
]
=
&
sb_dsp_operations
;
sound_buffcounts
[
my_dev
]
=
DSP_BUFFCOUNT
;
sound_buffsizes
[
my_dev
]
=
DSP_BUFFSIZE
;
sound_dsp_dmachan
[
my_dev
]
=
hw_config
->
dma
;
sound_dma_automode
[
my_dev
]
=
0
;
}
else
printk
(
"SB: Too many DSP devices available
\n
"
);
#if !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SBPRO)
if
(
!
sb16
)
/* There is a better driver for SB16
*/
#endif
if
(
num_dspdevs
<
MAX_DSP_DEV
)
{
dsp_devs
[
my_dev
=
num_dspdevs
++
]
=
&
sb_dsp_operations
;
sound_buffcounts
[
my_dev
]
=
DSP_BUFFCOUNT
;
sound_buffsizes
[
my_dev
]
=
DSP_BUFFSIZE
;
sound_dsp_dmachan
[
my_dev
]
=
hw_config
->
dma
;
sound_dma_automode
[
my_dev
]
=
0
;
}
else
printk
(
"SB: Too many DSP devices available
\n
"
);
#endif
#ifndef EXCLUDE_MIDI
if
(
!
midi_disabled
&&
!
sb16
)
/* Midi don't work in the SB emulation mode
* of PAS, SB16 has better midi interface */
sb_midi_init
(
major
);
sb_midi_init
(
sbc_
major
);
#endif
sb_dsp_ok
=
1
;
...
...
drivers/sound/sb_midi.c
View file @
e695b6a4
/*
* sound/sb_dsp.c
*
*
* The low level driver for the SoundBlaster DS chips.
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -12,7 +12,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -24,7 +24,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#include "sound_config.h"
...
...
@@ -49,11 +49,16 @@ extern int sb_midi_busy; /* 1 if the process has output to MIDI */
extern
int
sb_dsp_busy
;
extern
int
sb_dsp_highspeed
;
extern
volatile
int
sb_irq_mode
;
/* IMODE_INPUT, IMODE_OUTPUT
extern
volatile
int
sb_irq_mode
;
/* IMODE_INPUT, IMODE_OUTPUT
* or IMODE_NONE */
extern
int
sb_dsp_model
;
/* 1=SB, 2=SB Pro */
extern
int
sb_duplex_midi
;
extern
int
sb_intr_active
;
extern
int
sbc_base
;
static
int
input_opened
=
0
;
static
void
(
*
midi_input_intr
)
(
int
dev
,
unsigned
char
data
);
static
int
my_dev
=
0
;
static
int
sb_midi_open
(
int
dev
,
int
mode
,
...
...
@@ -72,7 +77,7 @@ sb_midi_open (int dev, int mode,
if
(
mode
!=
OPEN_WRITE
&&
!
sb_duplex_midi
)
{
if
(
num_midis
==
1
)
printk
(
"SoundBlaster: M
idi input not currently supported
\n
"
);
printk
(
"SoundBlaster: M
IDI input not supported with plain SB
\n
"
);
return
RET_ERROR
(
EPERM
);
}
...
...
@@ -96,6 +101,9 @@ sb_midi_open (int dev, int mode,
sb_reset_dsp
();
if
(
!
sb_dsp_command
(
0xf2
))
/* This is undodumented, isn't it */
return
RET_ERROR
(
EIO
);
/* be nice to DSP */
if
(
!
sb_dsp_command
(
0x35
))
return
RET_ERROR
(
EIO
);
/* Enter the UART mode */
sb_intr_active
=
1
;
...
...
@@ -105,6 +113,9 @@ sb_midi_open (int dev, int mode,
sb_reset_dsp
();
return
0
;
/* IRQ not free */
}
input_opened
=
1
;
my_dev
=
dev
;
midi_input_intr
=
input
;
}
sb_midi_busy
=
1
;
...
...
@@ -122,6 +133,7 @@ sb_midi_close (int dev)
}
sb_intr_active
=
0
;
sb_midi_busy
=
0
;
input_opened
=
0
;
}
static
int
...
...
@@ -174,6 +186,21 @@ sb_midi_ioctl (int dev, unsigned cmd, unsigned arg)
return
RET_ERROR
(
EPERM
);
}
void
sb_midi_interrupt
(
int
dummy
)
{
unsigned
long
flags
;
unsigned
char
data
;
DISABLE_INTR
(
flags
);
data
=
INB
(
DSP_READ
);
if
(
input_opened
)
midi_input_intr
(
my_dev
,
data
);
RESTORE_INTR
(
flags
);
}
static
struct
midi_operations
sb_midi_operations
=
{
{
"SoundBlaster"
,
0
,
0
,
SNDCARD_SB
},
...
...
@@ -189,7 +216,7 @@ static struct midi_operations sb_midi_operations =
};
void
sb_midi_init
(
int
model
)
sb_midi_init
(
int
model
)
{
midi_devs
[
num_midis
++
]
=
&
sb_midi_operations
;
}
...
...
drivers/sound/sb_mixer.c
View file @
e695b6a4
/*
* sound/sb_mixer.c
*
*
* The low level mixer driver for the SoundBlaster Pro and SB16 cards.
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -13,7 +13,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -25,7 +25,11 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
* Modified:
* Hunyue Yau Jan 6 1994
* Added code to support the Sound Galaxy NX Pro mixer.
*
*/
#include "sound_config.h"
...
...
@@ -39,56 +43,69 @@
extern
int
sbc_base
;
static
int
mixer_initialized
=
0
;
static
int
mixer_initialized
=
0
;
static
int
supported_rec_devices
;
static
int
supported_devices
;
static
int
recmask
=
0
;
static
int
mixer_model
;
static
int
mixer_caps
;
static
int
supported_rec_devices
;
static
int
supported_devices
;
static
int
recmask
=
0
;
static
int
mixer_model
;
static
int
mixer_caps
;
static
mixer_tab
*
iomap
;
void
sb_setmixer
(
unsigned
int
port
,
unsigned
int
value
)
{
unsigned
long
flags
;
unsigned
long
flags
;
DISABLE_INTR
(
flags
);
OUTB
((
unsigned
char
)(
port
&
0xff
),
MIXER_ADDR
);
/* Select register */
DISABLE_INTR
(
flags
);
OUTB
((
unsigned
char
)
(
port
&
0xff
),
MIXER_ADDR
);
/* Select register */
tenmicrosec
();
OUTB
((
unsigned
char
)(
value
&
0xff
),
MIXER_DATA
);
OUTB
((
unsigned
char
)
(
value
&
0xff
),
MIXER_DATA
);
tenmicrosec
();
RESTORE_INTR
(
flags
);
RESTORE_INTR
(
flags
);
}
int
sb_getmixer
(
unsigned
int
port
)
{
int
val
;
unsigned
long
flags
;
unsigned
long
flags
;
DISABLE_INTR
(
flags
);
OUTB
((
unsigned
char
)(
port
&
0xff
),
MIXER_ADDR
);
/* Select register */
DISABLE_INTR
(
flags
);
OUTB
((
unsigned
char
)
(
port
&
0xff
),
MIXER_ADDR
);
/* Select register */
tenmicrosec
();
val
=
INB
(
MIXER_DATA
);
tenmicrosec
();
RESTORE_INTR
(
flags
);
RESTORE_INTR
(
flags
);
return
val
;
}
void
sb_mixer_set_stereo
(
int
mode
)
sb_mixer_set_stereo
(
int
mode
)
{
if
(
!
mixer_initialized
)
return
;
if
(
!
mixer_initialized
)
return
;
sb_setmixer
(
OUT_FILTER
,
((
sb_getmixer
(
OUT_FILTER
)
&
~
STEREO_DAC
)
|
(
mode
?
STEREO_DAC
:
MONO_DAC
)));
|
(
mode
?
STEREO_DAC
:
MONO_DAC
)));
}
/*
* Returns:
* 0 No mixer detected.
* 1 Only a plain Sound Blaster Pro style mixer detected.
* 2 The Sound Galaxy NX Pro mixer detected.
*/
static
int
detect_mixer
(
void
)
{
#ifdef __SGNXPRO__
int
oldbass
,
oldtreble
;
#endif
int
retcode
=
1
;
/*
* Detect the mixer by changing parameters of two volume channels. If the
* values read back match with the values written, the mixer is there (is
...
...
@@ -102,95 +119,121 @@ detect_mixer (void)
if
(
sb_getmixer
(
VOC_VOL
)
!=
0x33
)
return
0
;
return
1
;
#ifdef __SGNXPRO__
/* Attempt to detect the SG NX Pro by check for valid bass/treble
* registers.
*/
oldbass
=
sb_getmixer
(
BASS_LVL
);
oldtreble
=
sb_getmixer
(
TREBLE_LVL
);
sb_setmixer
(
BASS_LVL
,
0xaa
);
sb_setmixer
(
TREBLE_LVL
,
0x55
);
if
((
sb_getmixer
(
BASS_LVL
)
!=
0xaa
)
||
(
sb_getmixer
(
TREBLE_LVL
)
!=
0x55
))
{
retcode
=
1
;
/* 1 == Only SB Pro detected */
}
else
retcode
=
2
;
/* 2 == SG NX Pro detected */
/* Restore register in either case since SG NX Pro has EEPROM with
* 'preferred' values stored.
*/
sb_setmixer
(
BASS_LVL
,
oldbass
);
sb_setmixer
(
TREBLE_LVL
,
oldtreble
);
#endif
return
retcode
;
}
static
void
change_bits
(
unsigned
char
*
regval
,
int
dev
,
int
chn
,
int
newval
)
change_bits
(
unsigned
char
*
regval
,
int
dev
,
int
chn
,
int
newval
)
{
unsigned
char
mask
;
int
shift
;
unsigned
char
mask
;
int
shift
;
mask
=
(
1
<<
(
*
iomap
)[
dev
][
chn
].
nbits
)
-
1
;
newval
=
((
newval
*
mask
)
+
50
)
/
100
;
/* Scale it */
mask
=
(
1
<<
(
*
iomap
)[
dev
][
chn
].
nbits
)
-
1
;
newval
=
((
newval
*
mask
)
+
50
)
/
100
;
/* Scale it */
shift
=
(
*
iomap
)[
dev
][
chn
].
bitoffs
-
(
*
iomap
)[
dev
][
LEFT_CHN
].
nbits
+
1
;
shift
=
(
*
iomap
)[
dev
][
chn
].
bitoffs
-
(
*
iomap
)[
dev
][
LEFT_CHN
].
nbits
+
1
;
*
regval
&=
~
(
mask
<<
shift
);
/* Filter out the previous value */
*
regval
|=
(
newval
&
mask
)
<<
shift
;
/* Set the new value */
*
regval
&=
~
(
mask
<<
shift
);
/* Filter out the previous value */
*
regval
|=
(
newval
&
mask
)
<<
shift
;
/* Set the new value */
}
static
int
sb_mixer_get
(
int
dev
)
sb_mixer_get
(
int
dev
)
{
if
(
!
((
1
<<
dev
)
&
supported_devices
))
return
RET_ERROR
(
EINVAL
);
if
(
!
((
1
<<
dev
)
&
supported_devices
))
return
RET_ERROR
(
EINVAL
);
return
levels
[
dev
];
return
levels
[
dev
];
}
static
int
sb_mixer_set
(
int
dev
,
int
value
)
{
int
left
=
value
&
0x000000ff
;
int
right
=
(
value
&
0x0000ff00
)
>>
8
;
int
left
=
value
&
0x000000ff
;
int
right
=
(
value
&
0x0000ff00
)
>>
8
;
int
regoffs
;
unsigned
char
val
;
int
regoffs
;
unsigned
char
val
;
if
(
left
>
100
)
left
=
100
;
if
(
right
>
100
)
right
=
100
;
if
(
left
>
100
)
left
=
100
;
if
(
right
>
100
)
right
=
100
;
if
(
dev
>
31
)
return
RET_ERROR
(
EINVAL
);
if
(
dev
>
31
)
return
RET_ERROR
(
EINVAL
);
if
(
!
(
supported_devices
&
(
1
<<
dev
)))
/* Not supported */
return
RET_ERROR
(
EINVAL
);
if
(
!
(
supported_devices
&
(
1
<<
dev
)))
/* Not supported */
return
RET_ERROR
(
EINVAL
);
regoffs
=
(
*
iomap
)[
dev
][
LEFT_CHN
].
regno
;
regoffs
=
(
*
iomap
)[
dev
][
LEFT_CHN
].
regno
;
if
(
regoffs
==
0
)
return
RET_ERROR
(
EINVAL
);
if
(
regoffs
==
0
)
return
RET_ERROR
(
EINVAL
);
val
=
sb_getmixer
(
regoffs
);
change_bits
(
&
val
,
dev
,
LEFT_CHN
,
left
);
val
=
sb_getmixer
(
regoffs
);
change_bits
(
&
val
,
dev
,
LEFT_CHN
,
left
);
levels
[
dev
]
=
left
|
(
left
<<
8
);
levels
[
dev
]
=
left
|
(
left
<<
8
);
if
((
*
iomap
)[
dev
][
RIGHT_CHN
].
regno
!=
regoffs
)
/* Change register */
{
sb_setmixer
(
regoffs
,
val
);
/* Save the old one */
regoffs
=
(
*
iomap
)[
dev
][
RIGHT_CHN
].
regno
;
if
((
*
iomap
)[
dev
][
RIGHT_CHN
].
regno
!=
regoffs
)
/* Change register */
{
sb_setmixer
(
regoffs
,
val
);
/* Save the old one */
regoffs
=
(
*
iomap
)[
dev
][
RIGHT_CHN
].
regno
;
if
(
regoffs
==
0
)
return
left
|
(
left
<<
8
);
/* Just left channel present */
if
(
regoffs
==
0
)
return
left
|
(
left
<<
8
);
/* Just left channel present */
val
=
sb_getmixer
(
regoffs
);
/* Read the new one */
}
val
=
sb_getmixer
(
regoffs
);
/* Read the new one */
}
change_bits
(
&
val
,
dev
,
RIGHT_CHN
,
right
);
sb_setmixer
(
regoffs
,
val
);
change_bits
(
&
val
,
dev
,
RIGHT_CHN
,
right
);
sb_setmixer
(
regoffs
,
val
);
levels
[
dev
]
=
left
|
(
right
<<
8
);
return
left
|
(
right
<<
8
);
levels
[
dev
]
=
left
|
(
right
<<
8
);
return
left
|
(
right
<<
8
);
}
static
void
set_recsrc
(
int
src
)
set_recsrc
(
int
src
)
{
sb_setmixer
(
RECORD_SRC
,
(
sb_getmixer
(
RECORD_SRC
)
&~
7
)
|
(
src
&
0x7
));
sb_setmixer
(
RECORD_SRC
,
(
sb_getmixer
(
RECORD_SRC
)
&
~
7
)
|
(
src
&
0x7
));
}
static
int
set_recmask
(
int
mask
)
set_recmask
(
int
mask
)
{
int
devmask
,
i
;
unsigned
char
regimageL
,
regimageR
;
int
devmask
,
i
;
unsigned
char
regimageL
,
regimageR
;
devmask
=
mask
&
supported_rec_devices
;
devmask
=
mask
&
supported_rec_devices
;
switch
(
mixer_model
)
{
case
3
:
switch
(
mixer_model
)
{
case
3
:
if
(
devmask
!=
SOUND_MASK_MIC
&&
devmask
!=
SOUND_MASK_LINE
&&
...
...
@@ -209,7 +252,7 @@ set_recmask(int mask)
}
if
(
devmask
^
recmask
)
/* Input source changed */
if
(
devmask
^
recmask
)
/* Input source changed */
{
switch
(
devmask
)
{
...
...
@@ -233,23 +276,24 @@ set_recmask(int mask)
break
;
case
4
:
if
(
!
devmask
)
devmask
=
SOUND_MASK_MIC
;
case
4
:
if
(
!
devmask
)
devmask
=
SOUND_MASK_MIC
;
regimageL
=
regimageR
=
0
;
for
(
i
=
0
;
i
<
SOUND_MIXER_NRDEVICES
;
i
++
)
if
((
1
<<
i
)
&
devmask
)
regimageL
=
regimageR
=
0
;
for
(
i
=
0
;
i
<
SOUND_MIXER_NRDEVICES
;
i
++
)
if
((
1
<<
i
)
&
devmask
)
{
regimageL
|=
sb16_recmasks_L
[
i
];
regimageR
|=
sb16_recmasks_R
[
i
];
}
sb_setmixer
(
SB16_IMASK_L
,
regimageL
);
sb_setmixer
(
SB16_IMASK_R
,
regimageR
);
sb_setmixer
(
SB16_IMASK_L
,
regimageL
);
sb_setmixer
(
SB16_IMASK_R
,
regimageR
);
break
;
}
}
recmask
=
devmask
;
return
recmask
;
recmask
=
devmask
;
return
recmask
;
}
static
int
...
...
@@ -258,43 +302,43 @@ sb_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
if
(((
cmd
>>
8
)
&
0xff
)
==
'M'
)
{
if
(
cmd
&
IOC_IN
)
switch
(
cmd
&
0xff
)
{
case
SOUND_MIXER_RECSRC
:
return
IOCTL_OUT
(
arg
,
set_recmask
(
IOCTL_IN
(
arg
)));
break
;
default:
return
IOCTL_OUT
(
arg
,
sb_mixer_set
(
cmd
&
0xff
,
IOCTL_IN
(
arg
)));
}
switch
(
cmd
&
0xff
)
{
case
SOUND_MIXER_RECSRC
:
return
IOCTL_OUT
(
arg
,
set_recmask
(
IOCTL_IN
(
arg
)));
break
;
default:
return
IOCTL_OUT
(
arg
,
sb_mixer_set
(
cmd
&
0xff
,
IOCTL_IN
(
arg
)));
}
else
switch
(
cmd
&
0xff
)
/* Return parameters */
{
switch
(
cmd
&
0xff
)
/* Return parameters */
{
case
SOUND_MIXER_RECSRC
:
return
IOCTL_OUT
(
arg
,
recmask
);
break
;
case
SOUND_MIXER_RECSRC
:
return
IOCTL_OUT
(
arg
,
recmask
);
break
;
case
SOUND_MIXER_DEVMASK
:
return
IOCTL_OUT
(
arg
,
supported_devices
);
break
;
case
SOUND_MIXER_DEVMASK
:
return
IOCTL_OUT
(
arg
,
supported_devices
);
break
;
case
SOUND_MIXER_STEREODEVS
:
return
IOCTL_OUT
(
arg
,
supported_devices
&
~
(
SOUND_MASK_MIC
|
SOUND_MASK_SPEAKER
));
break
;
case
SOUND_MIXER_STEREODEVS
:
return
IOCTL_OUT
(
arg
,
supported_devices
&
~
(
SOUND_MASK_MIC
|
SOUND_MASK_SPEAKER
));
break
;
case
SOUND_MIXER_RECMASK
:
return
IOCTL_OUT
(
arg
,
supported_rec_devices
);
break
;
case
SOUND_MIXER_RECMASK
:
return
IOCTL_OUT
(
arg
,
supported_rec_devices
);
break
;
case
SOUND_MIXER_CAPS
:
return
IOCTL_OUT
(
arg
,
mixer_caps
);
break
;
case
SOUND_MIXER_CAPS
:
return
IOCTL_OUT
(
arg
,
mixer_caps
);
break
;
default:
return
IOCTL_OUT
(
arg
,
sb_mixer_get
(
cmd
&
0xff
));
}
default:
return
IOCTL_OUT
(
arg
,
sb_mixer_get
(
cmd
&
0xff
));
}
}
else
return
RET_ERROR
(
EINVAL
);
...
...
@@ -306,48 +350,73 @@ static struct mixer_operations sb_mixer_operations =
};
static
void
sb_mixer_reset
(
void
)
sb_mixer_reset
(
void
)
{
int
i
;
int
i
;
for
(
i
=
0
;
i
<
SOUND_MIXER_NRDEVICES
;
i
++
)
sb_mixer_set
(
i
,
levels
[
i
]);
set_recmask
(
SOUND_MASK_MIC
);
set_recmask
(
SOUND_MASK_MIC
);
}
void
sb_mixer_init
(
int
major_model
)
/*
* Returns a code depending on whether a SG NX Pro was detected.
* 0 == Plain SB 16 or SB Pro
* 1 == SG NX Pro detected.
*
* Used to update message.
*/
int
sb_mixer_init
(
int
major_model
)
{
sb_setmixer
(
0x00
,
0
);
/* Reset mixer */
int
mixerstat
;
sb_setmixer
(
0x00
,
0
);
/* Reset mixer */
if
(
!
detect_mixer
())
return
;
/* No mixer. Why? */
mixerstat
=
detect_mixer
();
mixer_initialized
=
1
;
mixer_model
=
major_model
;
if
(
!
mixerstat
)
return
0
;
/* No mixer. Why? */
switch
(
major_model
)
{
case
3
:
mixer_caps
=
SOUND_CAP_EXCL_INPUT
;
mixer_initialized
=
1
;
mixer_model
=
major_model
;
switch
(
major_model
)
{
case
3
:
mixer_caps
=
SOUND_CAP_EXCL_INPUT
;
#ifdef __SGNXPRO__
if
(
mixerstat
==
2
)
{
/* A SGNXPRO was detected */
supported_devices
=
SGNXPRO_MIXER_DEVICES
;
supported_rec_devices
=
SGNXPRO_RECORDING_DEVICES
;
iomap
=
&
sgnxpro_mix
;
}
else
#endif
{
/* Otherwise plain SB Pro */
supported_devices
=
SBPRO_MIXER_DEVICES
;
supported_rec_devices
=
SBPRO_RECORDING_DEVICES
;
iomap
=
&
sbpro_mix
;
break
;
case
4
:
mixer_caps
=
0
;
supported_devices
=
SB16_MIXER_DEVICES
;
supported_rec_devices
=
SB16_RECORDING_DEVICES
;
iomap
=
&
sb16_mix
;
break
;
default:
printk
(
"SB Warning: Unsupported mixer type
\n
"
);
return
;
}
mixer_devs
[
num_mixers
++
]
=
&
sb_mixer_operations
;
sb_mixer_reset
();
break
;
case
4
:
mixer_caps
=
0
;
supported_devices
=
SB16_MIXER_DEVICES
;
supported_rec_devices
=
SB16_RECORDING_DEVICES
;
iomap
=
&
sb16_mix
;
break
;
default:
printk
(
"SB Warning: Unsupported mixer type
\n
"
);
return
0
;
}
mixer_devs
[
num_mixers
++
]
=
&
sb_mixer_operations
;
sb_mixer_reset
();
return
(
mixerstat
==
2
);
}
#endif
drivers/sound/sb_mixer.h
View file @
e695b6a4
...
...
@@ -24,13 +24,29 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Modified:
* Hunyue Yau Jan 6 1994
* Added defines for the Sound Galaxy NX Pro mixer.
*
*/
#define SBPRO_RECORDING_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD)
/* Same as SB Pro, unless I find otherwise */
#define SGNXPRO_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
#define SBPRO_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | \
SOUND_MASK_CD | SOUND_MASK_VOLUME)
/* SG NX Pro has treble and bass settings on the mixer. The 'speaker'
* channel is the COVOX/DisneySoundSource emulation volume control
* on the mixer. It does NOT control speaker volume. Should have own
* mask eventually?
*/
#define SGNXPRO_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_BASS| \
SOUND_MASK_TREBLE|SOUND_MASK_SPEAKER )
#define SB16_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \
SOUND_MASK_CD)
...
...
@@ -62,6 +78,13 @@
#define IRQ_STAT 0x82
#define OPSW 0x3c
/*
* Additional registers on the SG NX Pro
*/
#define COVOX_VOL 0x42
#define TREBLE_LVL 0x44
#define BASS_LVL 0x46
#define FREQ_HI (1 << 3)
/* Use High-frequency ANFI filters */
#define FREQ_LOW 0
/* Use Low-frequency ANFI filters */
#define FILT_ON 0
/* Yes, 0 to turn it on, 1 for off */
...
...
@@ -108,6 +131,23 @@ MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT
(
SOUND_MIXER_RECLEV
,
0x00
,
0
,
0
,
0x00
,
0
,
0
)
};
#ifdef __SGNXPRO__
mixer_tab
sgnxpro_mix
=
{
MIX_ENT
(
SOUND_MIXER_VOLUME
,
0x22
,
7
,
4
,
0x22
,
3
,
4
),
MIX_ENT
(
SOUND_MIXER_BASS
,
0x46
,
2
,
3
,
0x00
,
0
,
0
),
MIX_ENT
(
SOUND_MIXER_TREBLE
,
0x44
,
2
,
3
,
0x00
,
0
,
0
),
MIX_ENT
(
SOUND_MIXER_SYNTH
,
0x26
,
7
,
4
,
0x26
,
3
,
4
),
MIX_ENT
(
SOUND_MIXER_PCM
,
0x04
,
7
,
4
,
0x04
,
3
,
4
),
MIX_ENT
(
SOUND_MIXER_SPEAKER
,
0x42
,
2
,
3
,
0x00
,
0
,
0
),
MIX_ENT
(
SOUND_MIXER_LINE
,
0x2e
,
7
,
4
,
0x2e
,
3
,
4
),
MIX_ENT
(
SOUND_MIXER_MIC
,
0x0a
,
2
,
3
,
0x00
,
0
,
0
),
MIX_ENT
(
SOUND_MIXER_CD
,
0x28
,
7
,
4
,
0x28
,
3
,
4
),
MIX_ENT
(
SOUND_MIXER_IMIX
,
0x00
,
0
,
0
,
0x00
,
0
,
0
),
MIX_ENT
(
SOUND_MIXER_ALTPCM
,
0x00
,
0
,
0
,
0x00
,
0
,
0
),
MIX_ENT
(
SOUND_MIXER_RECLEV
,
0x00
,
0
,
0
,
0x00
,
0
,
0
)
};
#endif
mixer_tab
sb16_mix
=
{
MIX_ENT
(
SOUND_MIXER_VOLUME
,
0x30
,
7
,
5
,
0x31
,
7
,
5
),
MIX_ENT
(
SOUND_MIXER_BASS
,
0x46
,
7
,
4
,
0x47
,
7
,
4
),
...
...
drivers/sound/sequencer.c
View file @
e695b6a4
/*
* sound/sequencer.c
*
*
* The sequencer personality manager.
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -12,7 +12,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -24,7 +24,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#define SEQUENCER_C
...
...
@@ -46,7 +46,7 @@ static int midi_opened[MAX_MIDI_DEV] =
static
int
midi_written
[
MAX_MIDI_DEV
]
=
{
0
};
long
seq_time
=
0
;
/* Reference point for the timer */
unsigned
long
seq_time
=
0
;
/* Reference point for the timer */
#include "tuning.h"
...
...
@@ -77,6 +77,7 @@ int
sequencer_read
(
int
dev
,
struct
fileinfo
*
file
,
snd_rw_buf
*
buf
,
int
count
)
{
int
c
=
count
,
p
=
0
;
unsigned
long
flags
;
dev
=
dev
>>
4
;
...
...
@@ -85,12 +86,22 @@ sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
while
(
c
>
3
)
{
DISABLE_INTR
(
flags
);
if
(
!
iqlen
)
{
if
(
c
!=
count
)
/* Some data has been received */
{
RESTORE_INTR
(
flags
);
return
count
-
c
;
/* Return what we have */
}
DO_SLEEP
(
midi_sleeper
,
midi_sleep_flag
,
0
);
if
(
!
iqlen
)
return
count
-
c
;
{
RESTORE_INTR
(
flags
);
return
count
-
c
;
}
}
COPY_TO_USER
(
buf
,
p
,
&
iqueue
[
iqhead
*
IEV_SZ
],
IEV_SZ
);
...
...
@@ -99,6 +110,7 @@ sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
iqhead
=
(
iqhead
+
1
)
%
SEQ_MAX_QUEUE
;
iqlen
--
;
RESTORE_INTR
(
flags
);
}
return
count
-
c
;
...
...
@@ -118,11 +130,11 @@ copy_to_input (unsigned char *event)
if
(
iqlen
>=
(
SEQ_MAX_QUEUE
-
1
))
return
;
/* Overflow */
DISABLE_INTR
(
flags
);
memcpy
(
&
iqueue
[
iqtail
*
IEV_SZ
],
event
,
IEV_SZ
);
iqlen
++
;
iqtail
=
(
iqtail
+
1
)
%
SEQ_MAX_QUEUE
;
DISABLE_INTR
(
flags
);
if
(
SOMEONE_WAITING
(
midi_sleeper
,
midi_sleep_flag
))
{
WAKE_UP
(
midi_sleeper
,
midi_sleep_flag
);
...
...
@@ -327,6 +339,10 @@ extended_event (unsigned char *q)
synth_devs
[
dev
]
->
controller
(
dev
,
q
[
3
],
q
[
4
],
*
(
short
*
)
&
q
[
5
]);
break
;
case
SEQ_VOLMODE
:
synth_devs
[
dev
]
->
volume_method
(
dev
,
q
[
3
]);
break
;
default:
return
RET_ERROR
(
EINVAL
);
}
...
...
@@ -346,7 +362,7 @@ seq_startplay (void)
qhead
=
((
this_one
=
qhead
)
+
1
)
%
SEQ_MAX_QUEUE
;
qlen
--
;
q
=
&
queue
[
this_one
*
EV_SZ
];
q
=
&
queue
[
this_one
*
EV_SZ
];
switch
(
q
[
0
])
{
...
...
@@ -463,87 +479,87 @@ seq_startplay (void)
int
sequencer_open
(
int
dev
,
struct
fileinfo
*
file
)
{
int
retval
,
mode
,
i
;
{
int
retval
,
mode
,
i
;
dev
=
dev
>>
4
;
mode
=
file
->
mode
&
O_ACCMODE
;
dev
=
dev
>>
4
;
mode
=
file
->
mode
&
O_ACCMODE
;
DEB
(
printk
(
"sequencer_open(dev=%d)
\n
"
,
dev
));
DEB
(
printk
(
"sequencer_open(dev=%d)
\n
"
,
dev
));
if
(
!
sequencer_ok
)
{
printk
(
"Soundcard: Sequencer not initialized
\n
"
);
return
RET_ERROR
(
ENXIO
);
}
if
(
!
sequencer_ok
)
{
printk
(
"Soundcard: Sequencer not initialized
\n
"
);
return
RET_ERROR
(
ENXIO
);
}
if
(
dev
)
/* Patch manager device */
{
int
err
;
if
(
dev
)
/* Patch manager device */
{
int
err
;
dev
--
;
if
(
pmgr_present
[
dev
])
return
RET_ERROR
(
EBUSY
);
if
((
err
=
pmgr_open
(
dev
))
<
0
)
return
err
;
/* Failed */
dev
--
;
if
(
pmgr_present
[
dev
])
return
RET_ERROR
(
EBUSY
);
if
((
err
=
pmgr_open
(
dev
))
<
0
)
return
err
;
/* Failed */
pmgr_present
[
dev
]
=
1
;
return
err
;
}
pmgr_present
[
dev
]
=
1
;
return
err
;
}
if
(
sequencer_busy
)
{
printk
(
"Sequencer busy
\n
"
);
return
RET_ERROR
(
EBUSY
);
}
if
(
sequencer_busy
)
{
printk
(
"Sequencer busy
\n
"
);
return
RET_ERROR
(
EBUSY
);
}
if
(
!
(
num_synths
+
num_midis
))
return
RET_ERROR
(
ENXIO
);
if
(
!
(
num_synths
+
num_midis
))
return
RET_ERROR
(
ENXIO
);
synth_open_mask
=
0
;
synth_open_mask
=
0
;
if
(
mode
==
OPEN_WRITE
||
mode
==
OPEN_READWRITE
)
for
(
i
=
0
;
i
<
num_synths
;
i
++
)
/* Open synth devices */
if
(
synth_devs
[
i
]
->
open
(
i
,
mode
)
<
0
)
printk
(
"Sequencer: Warning! Cannot open synth device #%d
\n
"
,
i
);
else
synth_open_mask
|=
(
1
<<
i
);
if
(
mode
==
OPEN_WRITE
||
mode
==
OPEN_READWRITE
)
for
(
i
=
0
;
i
<
num_synths
;
i
++
)
/* Open synth devices */
if
(
synth_devs
[
i
]
->
open
(
i
,
mode
)
<
0
)
printk
(
"Sequencer: Warning! Cannot open synth device #%d
\n
"
,
i
);
else
synth_open_mask
|=
(
1
<<
i
);
seq_time
=
GET_TIME
();
seq_time
=
GET_TIME
();
for
(
i
=
0
;
i
<
num_midis
;
i
++
)
{
midi_opened
[
i
]
=
0
;
midi_written
[
i
]
=
0
;
}
for
(
i
=
0
;
i
<
num_midis
;
i
++
)
{
midi_opened
[
i
]
=
0
;
midi_written
[
i
]
=
0
;
}
if
(
mode
==
OPEN_READ
||
mode
==
OPEN_READWRITE
)
{
/* Initialize midi input devices */
if
(
!
num_midis
)
{
printk
(
"Sequencer: No Midi devices. Input not possible
\n
"
);
return
RET_ERROR
(
ENXIO
);
}
if
(
mode
==
OPEN_READ
||
mode
==
OPEN_READWRITE
)
{
/* Initialize midi input devices */
if
(
!
num_midis
)
{
printk
(
"Sequencer: No Midi devices. Input not possible
\n
"
);
return
RET_ERROR
(
ENXIO
);
}
for
(
i
=
0
;
i
<
num_midis
;
i
++
)
{
if
((
retval
=
midi_devs
[
i
]
->
open
(
i
,
mode
,
for
(
i
=
0
;
i
<
num_midis
;
i
++
)
{
if
((
retval
=
midi_devs
[
i
]
->
open
(
i
,
mode
,
sequencer_midi_input
,
sequencer_midi_output
))
>=
0
)
midi_opened
[
i
]
=
1
;
}
}
midi_opened
[
i
]
=
1
;
}
}
sequencer_busy
=
1
;
RESET_WAIT_QUEUE
(
seq_sleeper
,
seq_sleep_flag
);
RESET_WAIT_QUEUE
(
midi_sleeper
,
midi_sleep_flag
);
output_treshold
=
SEQ_MAX_QUEUE
/
2
;
sequencer_busy
=
1
;
RESET_WAIT_QUEUE
(
seq_sleeper
,
seq_sleep_flag
);
RESET_WAIT_QUEUE
(
midi_sleeper
,
midi_sleep_flag
);
output_treshold
=
SEQ_MAX_QUEUE
/
2
;
for
(
i
=
0
;
i
<
num_synths
;
i
++
)
if
(
pmgr_present
[
i
])
pmgr_inform
(
i
,
PM_E_OPENED
,
0
,
0
,
0
,
0
);
for
(
i
=
0
;
i
<
num_synths
;
i
++
)
if
(
pmgr_present
[
i
])
pmgr_inform
(
i
,
PM_E_OPENED
,
0
,
0
,
0
,
0
);
return
0
;
}
return
0
;
}
void
seq_drain_midi_queues
(
void
)
...
...
@@ -578,53 +594,53 @@ seq_drain_midi_queues (void)
void
sequencer_release
(
int
dev
,
struct
fileinfo
*
file
)
{
int
i
;
int
mode
=
file
->
mode
&
O_ACCMODE
;
{
int
i
;
int
mode
=
file
->
mode
&
O_ACCMODE
;
dev
=
dev
>>
4
;
dev
=
dev
>>
4
;
DEB
(
printk
(
"sequencer_release(dev=%d)
\n
"
,
dev
));
DEB
(
printk
(
"sequencer_release(dev=%d)
\n
"
,
dev
));
if
(
dev
)
/* Patch manager device */
{
dev
--
;
pmgr_release
(
dev
);
pmgr_present
[
dev
]
=
0
;
return
;
}
if
(
dev
)
/* Patch manager device */
{
dev
--
;
pmgr_release
(
dev
);
pmgr_present
[
dev
]
=
0
;
return
;
}
/*
/*
* Wait until the queue is empty
*/
while
(
!
PROCESS_ABORTING
(
seq_sleeper
,
seq_sleep_flag
)
&&
qlen
)
{
seq_sync
();
}
*/
if
(
mode
!=
OPEN_READ
)
seq_drain_midi_queues
();
/* Ensure the output queues are empty */
seq_reset
();
if
(
mode
!=
OPEN_READ
)
seq_drain_midi_queues
();
/* Flush the all notes off messages */
while
(
!
PROCESS_ABORTING
(
seq_sleeper
,
seq_sleep_flag
)
&&
qlen
)
{
seq_sync
();
}
for
(
i
=
0
;
i
<
num_midis
;
i
++
)
if
(
midi_opened
[
i
])
midi_devs
[
i
]
->
close
(
i
);
if
(
mode
!=
OPEN_READ
)
seq_drain_midi_queues
();
/* Ensure the output queues are empty */
seq_reset
();
if
(
mode
!=
OPEN_READ
)
seq_drain_midi_queues
();
/* Flush the all notes off messages */
if
(
mode
==
OPEN_WRITE
||
mode
==
OPEN_READWRITE
)
for
(
i
=
0
;
i
<
num_synths
;
i
++
)
if
(
synth_open_mask
&
(
1
<<
i
))
/* Actually opened */
if
(
synth_devs
[
i
])
synth_devs
[
i
]
->
close
(
i
);
for
(
i
=
0
;
i
<
num_midis
;
i
++
)
if
(
midi_opened
[
i
])
midi_devs
[
i
]
->
close
(
i
);
if
(
mode
==
OPEN_WRITE
||
mode
==
OPEN_READWRITE
)
for
(
i
=
0
;
i
<
num_synths
;
i
++
)
if
(
pmgr_present
[
i
])
pmgr_inform
(
i
,
PM_E_CLOSED
,
0
,
0
,
0
,
0
);
if
(
synth_open_mask
&
(
1
<<
i
))
/* Actually opened */
if
(
synth_devs
[
i
])
synth_devs
[
i
]
->
close
(
i
);
for
(
i
=
0
;
i
<
num_synths
;
i
++
)
if
(
pmgr_present
[
i
])
pmgr_inform
(
i
,
PM_E_CLOSED
,
0
,
0
,
0
,
0
);
sequencer_busy
=
0
;
}
sequencer_busy
=
0
;
}
static
int
seq_sync
(
void
)
...
...
@@ -686,8 +702,8 @@ seq_reset (void)
{
for
(
chn
=
0
;
chn
<
16
;
chn
++
)
{
midi_outc
(
i
,
(
unsigned
char
)(
0xb0
+
(
chn
&
0xff
)));
/* Channel msg */
midi_outc
(
i
,
(
unsigned
char
)
(
0xb0
+
(
chn
&
0xff
)));
/* Channel msg */
midi_outc
(
i
,
0x7b
);
/* All notes off */
midi_outc
(
i
,
0
);
/* Dummy parameter */
}
...
...
@@ -1040,7 +1056,7 @@ note_to_freq (int note_num)
else
if
(
octave
>
BASE_OCTAVE
)
note_freq
<<=
(
octave
-
BASE_OCTAVE
);
/* note_freq >>= 1;
*/
/* note_freq >>= 1;
*/
return
note_freq
;
}
...
...
@@ -1049,7 +1065,7 @@ unsigned long
compute_finetune
(
unsigned
long
base_freq
,
int
bend
,
int
range
)
{
unsigned
long
amount
;
int
negative
,
semitones
,
cents
;
int
negative
,
semitones
,
cents
,
multiplier
=
1
;
if
(
!
bend
)
return
base_freq
;
...
...
@@ -1073,13 +1089,20 @@ compute_finetune (unsigned long base_freq, int bend, int range)
if
(
bend
>
range
)
bend
=
range
;
if
(
bend
>
2399
)
bend
=
2399
;
/*
if (bend > 2399)
bend = 2399;
*/
while
(
bend
>
2399
)
{
multiplier
*=
4
;
bend
-=
2400
;
}
semitones
=
bend
/
100
;
cents
=
bend
%
100
;
amount
=
semitone_tuning
[
semitones
]
*
cent_tuning
[
cents
]
/
10000
;
amount
=
semitone_tuning
[
semitones
]
*
multiplier
*
cent_tuning
[
cents
]
/
10000
;
if
(
negative
)
return
(
base_freq
*
10000
)
/
amount
;
/* Bend down */
...
...
@@ -1093,8 +1116,9 @@ sequencer_init (long mem_start)
{
sequencer_ok
=
1
;
PERMANENT_MALLOC
(
unsigned
char
*
,
queue
,
SEQ_MAX_QUEUE
*
EV_SZ
,
mem_start
);
PERMANENT_MALLOC
(
unsigned
char
*
,
iqueue
,
SEQ_MAX_QUEUE
*
IEV_SZ
,
mem_start
);
PERMANENT_MALLOC
(
unsigned
char
*
,
queue
,
SEQ_MAX_QUEUE
*
EV_SZ
,
mem_start
);
PERMANENT_MALLOC
(
unsigned
char
*
,
iqueue
,
SEQ_MAX_QUEUE
*
IEV_SZ
,
mem_start
);
return
mem_start
;
}
...
...
@@ -1114,14 +1138,14 @@ sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
int
sequencer_open
(
int
dev
,
struct
fileinfo
*
file
)
{
return
RET_ERROR
(
ENXIO
);
}
{
return
RET_ERROR
(
ENXIO
);
}
void
sequencer_release
(
int
dev
,
struct
fileinfo
*
file
)
{
}
{
}
int
sequencer_ioctl
(
int
dev
,
struct
fileinfo
*
file
,
unsigned
int
cmd
,
unsigned
int
arg
)
...
...
drivers/sound/sound_calls.h
View file @
e695b6a4
...
...
@@ -129,12 +129,13 @@ int probe_sb16midi(struct address_info *hw_config);
/* From sb_midi.c */
void
sb_midi_init
(
int
model
);
void
sb_midi_interrupt
(
int
dummy
);
/* From sb_mixer.c */
void
sb_setmixer
(
unsigned
int
port
,
unsigned
int
value
);
int
sb_getmixer
(
unsigned
int
port
);
void
sb_mixer_set_stereo
(
int
mode
);
void
sb_mixer_init
(
int
major_model
);
int
sb_mixer_init
(
int
major_model
);
/* From opl3.c */
int
opl3_detect
(
int
ioaddr
);
...
...
@@ -181,6 +182,7 @@ unsigned char gus_read8 (int reg);
void
gus_write8
(
int
reg
,
unsigned
int
data
);
void
guswave_dma_irq
(
void
);
void
gus_delay
(
void
);
int
gus_default_mixer_ioctl
(
int
dev
,
unsigned
int
cmd
,
unsigned
int
arg
);
/* From gus_midi.c */
long
gus_midi_init
(
long
mem_start
);
...
...
@@ -201,3 +203,6 @@ int pmgr_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count);
int
pmgr_access
(
int
dev
,
struct
patmgr_info
*
rec
);
int
pmgr_inform
(
int
dev
,
int
event
,
unsigned
long
parm1
,
unsigned
long
parm2
,
unsigned
long
parm3
,
unsigned
long
parm4
);
/* From ics2101.c */
long
ics2101_mixer_init
(
long
mem_start
);
drivers/sound/sound_switch.c
View file @
e695b6a4
/*
* sound/sound_switch.c
*
*
* The system call switch
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -12,7 +12,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -24,7 +24,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#include "sound_config.h"
...
...
@@ -32,13 +32,16 @@
#ifdef CONFIGURE_SOUNDCARD
struct
sbc_device
{
int
usecount
;
};
{
int
usecount
;
};
static
struct
sbc_device
sbc_devices
[
SND_NDEVS
]
=
{{
0
}};
static
struct
sbc_device
sbc_devices
[
SND_NDEVS
]
=
{
{
0
}};
static
int
in_use
=
0
;
/* Total # of open device files (excluding
* minor 0) */
/*
...
...
@@ -53,7 +56,7 @@ put_status (char *s)
{
int
l
;
for
(
l
=
0
;
l
<
256
,
s
[
l
];
l
++
);
/* l=strlen(s); */
for
(
l
=
0
;
l
<
256
,
s
[
l
];
l
++
);
/* l=strlen(s); */
if
(
status_len
+
l
>=
4000
)
return
0
;
...
...
@@ -69,27 +72,28 @@ put_status_int (unsigned int val, int radix)
{
int
l
,
v
;
static
char
hx
[]
=
"0123456789abcdef"
;
char
buf
[
11
];
static
char
hx
[]
=
"0123456789abcdef"
;
char
buf
[
11
];
if
(
!
val
)
return
put_status
(
"0"
);
if
(
!
val
)
return
put_status
(
"0"
);
l
=
0
;
buf
[
10
]
=
0
;
buf
[
10
]
=
0
;
while
(
val
)
{
v
=
val
%
radix
;
val
=
val
/
radix
;
{
v
=
val
%
radix
;
val
=
val
/
radix
;
buf
[
9
-
l
]
=
hx
[
v
];
l
++
;
}
buf
[
9
-
l
]
=
hx
[
v
];
l
++
;
}
if
(
status_len
+
l
>=
4000
)
return
0
;
memcpy
(
&
status_buf
[
status_len
],
&
buf
[
10
-
l
],
l
);
memcpy
(
&
status_buf
[
status_len
],
&
buf
[
10
-
l
],
l
);
status_len
+=
l
;
return
1
;
...
...
@@ -114,33 +118,43 @@ init_status (void)
if
(
!
put_status
(
"Config options: "
))
return
;
if
(
!
put_status_int
(
SELECTED_SOUND_OPTIONS
,
16
))
return
;
if
(
!
put_status_int
(
SELECTED_SOUND_OPTIONS
,
16
))
return
;
if
(
!
put_status
(
"
\n\n
HW config:
\n
"
))
return
;
for
(
i
=
0
;
i
<
(
num_sound_drivers
-
1
);
i
++
)
{
if
(
!
supported_drivers
[
i
].
enabled
)
if
(
!
put_status
(
"("
))
return
;
if
(
!
supported_drivers
[
i
].
enabled
)
if
(
!
put_status
(
"("
))
return
;
if
(
!
put_status
(
"Type "
))
return
;
if
(
!
put_status_int
(
supported_drivers
[
i
].
card_type
,
10
))
return
;
if
(
!
put_status
(
": "
))
return
;
if
(
!
put_status
(
supported_drivers
[
i
].
name
))
return
;
if
(
!
put_status
(
" at 0x"
))
return
;
if
(
!
put_status_int
(
supported_drivers
[
i
].
config
.
io_base
,
16
))
return
;
if
(
!
put_status
(
" irq "
))
return
;
if
(
!
put_status_int
(
supported_drivers
[
i
].
config
.
irq
,
10
))
return
;
if
(
!
put_status
(
" drq "
))
return
;
if
(
!
put_status_int
(
supported_drivers
[
i
].
config
.
dma
,
10
))
return
;
if
(
!
supported_drivers
[
i
].
enabled
)
if
(
!
put_status
(
")"
))
if
(
!
put_status
(
"Type "
))
return
;
if
(
!
put_status_int
(
supported_drivers
[
i
].
card_type
,
10
))
return
;
if
(
!
put_status
(
": "
))
return
;
if
(
!
put_status
(
supported_drivers
[
i
].
name
))
return
;
if
(
!
put_status
(
" at 0x"
))
return
;
if
(
!
put_status_int
(
supported_drivers
[
i
].
config
.
io_base
,
16
))
return
;
if
(
!
put_status
(
" irq "
))
return
;
if
(
!
put_status_int
(
supported_drivers
[
i
].
config
.
irq
,
10
))
return
;
if
(
!
put_status
(
" drq "
))
return
;
if
(
!
put_status_int
(
supported_drivers
[
i
].
config
.
dma
,
10
))
return
;
if
(
!
supported_drivers
[
i
].
enabled
)
if
(
!
put_status
(
")"
))
return
;
if
(
!
put_status
(
"
\n
"
))
return
;
}
...
...
@@ -150,10 +164,14 @@ init_status (void)
for
(
i
=
0
;
i
<
num_dspdevs
;
i
++
)
{
if
(
!
put_status_int
(
i
,
10
))
return
;
if
(
!
put_status
(
": "
))
return
;
if
(
!
put_status
(
dsp_devs
[
i
]
->
name
))
return
;
if
(
!
put_status
(
"
\n
"
))
return
;
if
(
!
put_status_int
(
i
,
10
))
return
;
if
(
!
put_status
(
": "
))
return
;
if
(
!
put_status
(
dsp_devs
[
i
]
->
name
))
return
;
if
(
!
put_status
(
"
\n
"
))
return
;
}
if
(
!
put_status
(
"
\n
Synth devices:
\n
"
))
...
...
@@ -161,10 +179,14 @@ init_status (void)
for
(
i
=
0
;
i
<
num_synths
;
i
++
)
{
if
(
!
put_status_int
(
i
,
10
))
return
;
if
(
!
put_status
(
": "
))
return
;
if
(
!
put_status
(
synth_devs
[
i
]
->
info
->
name
))
return
;
if
(
!
put_status
(
"
\n
"
))
return
;
if
(
!
put_status_int
(
i
,
10
))
return
;
if
(
!
put_status
(
": "
))
return
;
if
(
!
put_status
(
synth_devs
[
i
]
->
info
->
name
))
return
;
if
(
!
put_status
(
"
\n
"
))
return
;
}
if
(
!
put_status
(
"
\n
Midi devices:
\n
"
))
...
...
@@ -172,10 +194,14 @@ init_status (void)
for
(
i
=
0
;
i
<
num_midis
;
i
++
)
{
if
(
!
put_status_int
(
i
,
10
))
return
;
if
(
!
put_status
(
": "
))
return
;
if
(
!
put_status
(
midi_devs
[
i
]
->
info
.
name
))
return
;
if
(
!
put_status
(
"
\n
"
))
return
;
if
(
!
put_status_int
(
i
,
10
))
return
;
if
(
!
put_status
(
": "
))
return
;
if
(
!
put_status
(
midi_devs
[
i
]
->
info
.
name
))
return
;
if
(
!
put_status
(
"
\n
"
))
return
;
}
if
(
num_mixers
)
...
...
@@ -191,7 +217,7 @@ init_status (void)
}
static
int
read_status
(
snd_rw_buf
*
buf
,
int
count
)
read_status
(
snd_rw_buf
*
buf
,
int
count
)
{
/*
* Return at most 'count' bytes from the status_buf.
...
...
@@ -206,14 +232,14 @@ read_status (snd_rw_buf *buf, int count)
if
(
l
<=
0
)
return
0
;
COPY_TO_USER
(
buf
,
0
,
&
status_buf
[
status_ptr
],
l
);
COPY_TO_USER
(
buf
,
0
,
&
status_buf
[
status_ptr
],
l
);
status_ptr
+=
l
;
return
l
;
}
int
sound_read_sw
(
int
dev
,
struct
fileinfo
*
file
,
snd_rw_buf
*
buf
,
int
count
)
sound_read_sw
(
int
dev
,
struct
fileinfo
*
file
,
snd_rw_buf
*
buf
,
int
count
)
{
DEB
(
printk
(
"sound_read_sw(dev=%d, count=%d)
\n
"
,
dev
,
count
));
...
...
@@ -246,7 +272,7 @@ sound_read_sw (int dev, struct fileinfo *file, snd_rw_buf *buf, int count)
}
int
sound_write_sw
(
int
dev
,
struct
fileinfo
*
file
,
snd_rw_buf
*
buf
,
int
count
)
sound_write_sw
(
int
dev
,
struct
fileinfo
*
file
,
snd_rw_buf
*
buf
,
int
count
)
{
DEB
(
printk
(
"sound_write_sw(dev=%d, count=%d)
\n
"
,
dev
,
count
));
...
...
@@ -275,6 +301,7 @@ int
sound_open_sw
(
int
dev
,
struct
fileinfo
*
file
)
{
int
retval
;
DEB
(
printk
(
"sound_open_sw(dev=%d) : usecount=%d
\n
"
,
dev
,
sbc_devices
[
dev
].
usecount
));
if
((
dev
>=
SND_NDEVS
)
||
(
dev
<
0
))
...
...
@@ -373,7 +400,7 @@ sound_release_sw (int dev, struct fileinfo *file)
int
sound_ioctl_sw
(
int
dev
,
struct
fileinfo
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
unsigned
int
cmd
,
unsigned
long
arg
)
{
DEB
(
printk
(
"sound_ioctl_sw(dev=%d, cmd=0x%x, arg=0x%x)
\n
"
,
dev
,
cmd
,
arg
));
...
...
@@ -414,4 +441,5 @@ sound_ioctl_sw (int dev, struct fileinfo *file,
return
RET_ERROR
(
EPERM
);
}
#endif
drivers/sound/soundcard.c
View file @
e695b6a4
/*
* linux/kernel/chr_drv/sound/soundcard.c
*
*
* Soundcard driver for Linux
*
*
* Copyright by Hannu Savolainen 1993
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
...
...
@@ -13,7 +13,7 @@
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -25,7 +25,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#include "sound_config.h"
...
...
@@ -37,6 +37,7 @@
extern
long
seq_time
;
static
int
soundcards_installed
=
0
;
/* Number of installed
* soundcards */
static
int
soundcard_configured
=
0
;
...
...
@@ -209,7 +210,7 @@ tenmicrosec (void)
}
int
snd_set_irq_handler
(
int
interrupt_level
,
void
(
*
hndlr
)
(
int
))
snd_set_irq_handler
(
int
interrupt_level
,
void
(
*
hndlr
)
(
int
))
{
int
retcode
;
...
...
@@ -237,9 +238,9 @@ snd_set_irq_handler (int interrupt_level, void(*hndlr)(int))
}
void
snd_release_irq
(
int
vect
)
snd_release_irq
(
int
vect
)
{
free_irq
(
vect
);
free_irq
(
vect
);
}
void
...
...
fs/namei.c
View file @
e695b6a4
...
...
@@ -407,9 +407,11 @@ int do_mknod(const char * filename, int mode, dev_t dev)
iput
(
dir
);
return
-
EPERM
;
}
dir
->
i_count
++
;
down
(
&
dir
->
i_sem
);
error
=
dir
->
i_op
->
mknod
(
dir
,
basename
,
namelen
,
mode
,
dev
);
up
(
&
dir
->
i_sem
);
iput
(
dir
);
return
error
;
}
...
...
@@ -462,9 +464,11 @@ static int do_mkdir(const char * pathname, int mode)
iput
(
dir
);
return
-
EPERM
;
}
dir
->
i_count
++
;
down
(
&
dir
->
i_sem
);
error
=
dir
->
i_op
->
mkdir
(
dir
,
basename
,
namelen
,
mode
);
up
(
&
dir
->
i_sem
);
iput
(
dir
);
return
error
;
}
...
...
@@ -588,9 +592,11 @@ static int do_symlink(const char * oldname, const char * newname)
iput
(
dir
);
return
-
EPERM
;
}
dir
->
i_count
++
;
down
(
&
dir
->
i_sem
);
error
=
dir
->
i_op
->
symlink
(
dir
,
basename
,
namelen
,
oldname
);
up
(
&
dir
->
i_sem
);
iput
(
dir
);
return
error
;
}
...
...
@@ -647,9 +653,11 @@ static int do_link(struct inode * oldinode, const char * newname)
iput
(
oldinode
);
return
-
EPERM
;
}
dir
->
i_count
++
;
down
(
&
dir
->
i_sem
);
error
=
dir
->
i_op
->
link
(
oldinode
,
dir
,
basename
,
namelen
);
up
(
&
dir
->
i_sem
);
iput
(
dir
);
return
error
;
}
...
...
@@ -723,10 +731,12 @@ static int do_rename(const char * oldname, const char * newname)
iput
(
new_dir
);
return
-
EPERM
;
}
new_dir
->
i_count
++
;
down
(
&
new_dir
->
i_sem
);
error
=
old_dir
->
i_op
->
rename
(
old_dir
,
old_base
,
old_len
,
new_dir
,
new_base
,
new_len
);
up
(
&
new_dir
->
i_sem
);
iput
(
new_dir
);
return
error
;
}
...
...
include/asm/segment.h
View file @
e695b6a4
...
...
@@ -52,20 +52,6 @@ __asm__ ("movl %0,%%fs:%1": /* no outputs */ :"ir" (val),"m" (*addr));
#define put_fs_long(x,addr) put_user_long((x),(int *)(addr))
static
inline
void
and_user_long
(
unsigned
long
val
,
int
*
addr
)
{
__asm__
(
"andl %0,%%fs:%1"
:
/* no outputs */
:
"ir"
(
val
),
"m"
(
*
addr
));
}
#define and_fs_long(x,addr) and_user_long((x),(int *)(addr))
static
inline
void
or_user_long
(
unsigned
long
val
,
int
*
addr
)
{
__asm__
(
"orl %0,%%fs:%1"
:
/* no outputs */
:
"ir"
(
val
),
"m"
(
*
addr
));
}
#define or_fs_long(x,addr) or_user_long((x),(int *)(addr))
static
inline
void
__generic_memcpy_tofs
(
void
*
to
,
const
void
*
from
,
unsigned
long
n
)
{
__asm__
(
"cld
\n\t
"
...
...
include/linux/sched.h
View file @
e695b6a4
...
...
@@ -365,9 +365,7 @@ __asm__("str %%ax\n\t" \
* tha math co-processor latest.
*/
#define switch_to(tsk) \
__asm__("cmpl %%ecx,_current\n\t" \
"je 1f\n\t" \
"cli\n\t" \
__asm__("cli\n\t" \
"xchgl %%ecx,_current\n\t" \
"ljmp %0\n\t" \
"sti\n\t" \
...
...
include/linux/soundcard.h
View file @
e695b6a4
...
...
@@ -34,7 +34,7 @@
*
* Regards,
* Hannu Savolainen
* h
savolai@cs.
helsinki.fi
* h
annu@voxware.pp.fi, Hannu.Savolainen@
helsinki.fi
*/
#define SOUND_VERSION 203
...
...
@@ -310,6 +310,14 @@ struct patmgr_info { /* Note! size must be < 4k since kmalloc() is used */
#define CTRL_EXPRESSION 253
#define CTRL_MAIN_VOLUME 252
#define SEQ_BALANCE 11
#define SEQ_VOLMODE 12
/*
* Volume mode decides how volumes are used
*/
#define VOL_METHOD_ADAGIO 1
#define VOL_METHOD_LINEAR 2
/*
* Note! SEQ_WAIT, SEQ_MIDIPUTC and SEQ_ECHO are used also as
...
...
@@ -630,7 +638,8 @@ void seqbuf_dump(void); /* This function must be provided by programs */
* }
*/
#define SEQ_DEFINEBUF(len) unsigned char _seqbuf[len]; int _seqbuflen = len, _seqbufptr = 0
#define SEQ_DEFINEBUF(len) unsigned char _seqbuf[len]; int _seqbuflen = len; int _seqbufptr = 0
#define SEQ_DECLAREBUF() extern unsigned char _seqbuf[]; extern int _seqbuflen;extern int _seqbufptr
#define SEQ_PM_DEFINES struct patmgr_info _pm_info
#define _SEQ_NEEDBUF(len) if ((_seqbufptr+(len)) > _seqbuflen) seqbuf_dump()
#define _SEQ_ADVBUF(len) _seqbufptr += len
...
...
@@ -644,6 +653,17 @@ void seqbuf_dump(void); /* This function must be provided by programs */
_pm_info.parm1 = bank, _pm_info.parm2 = 128, \
ioctl(seqfd, SNDCTL_PMGR_ACCESS, &_pm_info))
#define SEQ_VOLUME_MODE(dev, mode) {_SEQ_NEEDBUF(8);\
_seqbuf[_seqbufptr] = SEQ_EXTENDED;\
_seqbuf[_seqbufptr+1] = SEQ_VOLMODE;\
_seqbuf[_seqbufptr+2] = (dev);\
_seqbuf[_seqbufptr+3] = (mode);\
_seqbuf[_seqbufptr+4] = 0;\
_seqbuf[_seqbufptr+5] = 0;\
_seqbuf[_seqbufptr+6] = 0;\
_seqbuf[_seqbufptr+7] = 0;\
_SEQ_ADVBUF(8);}
#define SEQ_START_NOTE(dev, voice, note, vol) {_SEQ_NEEDBUF(8);\
_seqbuf[_seqbufptr] = SEQ_EXTENDED;\
_seqbuf[_seqbufptr+1] = SEQ_NOTEON;\
...
...
@@ -734,8 +754,8 @@ void seqbuf_dump(void); /* This function must be provided by programs */
_seqbuf[_seqbufptr+2] = (device);\
_seqbuf[_seqbufptr+3] = 0;\
_SEQ_ADVBUF(4);}
#define SEQ_WRPATCH(patch
, len)
{if (_seqbufptr) seqbuf_dump();\
if (write(seqfd, (char*)(patch), len)==-1) \
#define SEQ_WRPATCH(patch
x, len)
{if (_seqbufptr) seqbuf_dump();\
if (write(seqfd, (char*)(patch
x
), len)==-1) \
perror("Write patch: /dev/sequencer");}
#endif
...
...
include/linux/vm86.h
View file @
e695b6a4
...
...
@@ -40,7 +40,7 @@
#define VM86_SIGNAL 0
/* return due to signal */
#define VM86_UNKNOWN 1
/* unhandled GP fault - IO-instruction or similar */
#define VM86_INTx 2
/* int3/int x instruction (ARG = x) */
#define VM86_STI 3
/* sti/popf
l
instruction enabled virtual interrupts */
#define VM86_STI 3
/* sti/popf
/iret
instruction enabled virtual interrupts */
/*
* This is the stack-layout when we have done a "SAVE_ALL" from vm86
...
...
@@ -103,14 +103,6 @@ struct vm86_struct {
void
handle_vm86_fault
(
struct
vm86_regs
*
,
long
);
extern
inline
int
is_revectored
(
int
nr
,
struct
revectored_struct
*
bitmap
)
{
__asm__
__volatile__
(
"btl %2,%%fs:%1
\n\t
sbbl %0,%0"
:
"=r"
(
nr
)
:
"m"
(
*
bitmap
),
"r"
(
nr
));
return
nr
;
}
#endif
#endif
ipc/msg.c
View file @
e695b6a4
...
...
@@ -84,7 +84,7 @@ int sys_msgsnd (int msqid, struct msgbuf *msgp, int msgsz, int msgflg)
if
(
msgque
[
id
]
==
IPC_UNUSED
||
msgque
[
id
]
==
IPC_NOID
||
ipcp
->
seq
!=
msqid
/
MSGMNI
)
{
kfree
_s
(
msgh
,
sizeof
(
*
msgh
)
+
msgsz
);
kfree
(
msgh
);
return
-
EIDRM
;
}
...
...
@@ -194,7 +194,7 @@ int sys_msgrcv (int msqid, struct msgbuf *msgp, int msgsz, long msgtyp,
wake_up
(
&
msq
->
wwait
);
put_fs_long
(
nmsg
->
msg_type
,
&
msgp
->
mtype
);
memcpy_tofs
(
msgp
->
mtext
,
nmsg
->
msg_spot
,
msgsz
);
kfree
_s
(
nmsg
,
sizeof
(
*
nmsg
)
+
msgsz
);
kfree
(
nmsg
);
return
msgsz
;
}
else
{
/* did not find a message */
if
(
msgflg
&
IPC_NOWAIT
)
...
...
@@ -311,9 +311,9 @@ static void freeque (int id)
for
(
msgp
=
msq
->
msg_first
;
msgp
;
msgp
=
msgh
)
{
msgh
=
msgp
->
msg_next
;
msghdrs
--
;
kfree
_s
(
msgp
,
sizeof
(
*
msgp
)
+
msgp
->
msg_ts
);
kfree
(
msgp
);
}
kfree
_s
(
msq
,
sizeof
(
*
msq
)
);
kfree
(
msq
);
}
int
sys_msgctl
(
int
msqid
,
int
cmd
,
struct
msqid_ds
*
buf
)
...
...
ipc/sem.c
View file @
e695b6a4
...
...
@@ -144,7 +144,7 @@ static void freeary (int id)
wake_up
(
&
sma
->
eventn
);
schedule
();
}
kfree
_s
(
sma
,
sizeof
(
*
sma
)
+
sma
->
sem_nsems
*
sizeof
(
struct
sem
)
);
kfree
(
sma
);
return
;
}
...
...
ipc/shm.c
View file @
e695b6a4
...
...
@@ -95,7 +95,7 @@ static int newseg (key_t key, int shmflg, int size)
shm_segs
[
id
]
=
(
struct
shmid_ds
*
)
IPC_UNUSED
;
if
(
shm_lock
)
wake_up
(
&
shm_lock
);
kfree
_s
(
shp
,
sizeof
(
*
shp
)
);
kfree
(
shp
);
return
-
ENOMEM
;
}
...
...
@@ -186,9 +186,9 @@ static void killseg (int id)
shm_swp
--
;
}
}
kfree
_s
(
shp
->
shm_pages
,
numpages
*
sizeof
(
ulong
)
);
kfree
(
shp
->
shm_pages
);
shm_tot
-=
numpages
;
kfree
_s
(
shp
,
sizeof
(
*
shp
)
);
kfree
(
shp
);
return
;
}
...
...
@@ -439,7 +439,7 @@ int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
if
(
!
shmd
)
return
-
ENOMEM
;
if
((
shp
!=
shm_segs
[
id
])
||
(
shp
->
shm_perm
.
seq
!=
shmid
/
SHMMNI
))
{
kfree
_s
(
shmd
,
sizeof
(
*
shmd
)
);
kfree
(
shmd
);
return
-
EIDRM
;
}
shmd
->
shm_sgn
=
(
SHM_SWP_TYPE
<<
1
)
|
(
id
<<
SHM_ID_SHIFT
)
|
...
...
@@ -458,7 +458,7 @@ int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
if
((
err
=
shm_map
(
shmd
,
shmflg
&
SHM_REMAP
)))
{
if
(
--
shp
->
shm_nattch
<=
0
&&
shp
->
shm_perm
.
mode
&
SHM_DEST
)
killseg
(
id
);
kfree
_s
(
shmd
,
sizeof
(
*
shmd
)
);
kfree
(
shmd
);
return
err
;
}
...
...
@@ -497,7 +497,7 @@ static void detach (struct shm_desc **shmdp)
found:
unmap_page_range
(
shmd
->
start
,
shp
->
shm_segsz
);
/* sleeps */
kfree
_s
(
shmd
,
sizeof
(
*
shmd
)
);
kfree
(
shmd
);
shp
->
shm_lpid
=
current
->
pid
;
shp
->
shm_dtime
=
CURRENT_TIME
;
if
(
--
shp
->
shm_nattch
<=
0
&&
shp
->
shm_perm
.
mode
&
SHM_DEST
)
...
...
@@ -550,7 +550,7 @@ int shm_fork (struct task_struct *p1, struct task_struct *p2)
if
(
!
tmp
)
{
while
(
new_desc
)
{
tmp
=
new_desc
->
task_next
;
kfree
_s
(
new_desc
,
sizeof
(
*
new_desc
));
kfree
(
new_desc
);
new_desc
=
tmp
;
}
free_page_tables
(
p2
);
...
...
kernel/sched.c
View file @
e695b6a4
...
...
@@ -222,7 +222,7 @@ asmlinkage void schedule(void)
++current->counter;
}
#endif
c
=
-
1
;
c
=
-
1
000
;
next
=
p
=
&
init_task
;
for
(;;)
{
if
((
p
=
p
->
next_task
)
==
&
init_task
)
...
...
@@ -235,8 +235,9 @@ asmlinkage void schedule(void)
for_each_task
(
p
)
p
->
counter
=
(
p
->
counter
>>
1
)
+
p
->
priority
;
}
if
(
current
!=
next
)
kstat
.
context_swtch
++
;
if
(
current
==
next
)
return
;
kstat
.
context_swtch
++
;
switch_to
(
next
);
/* Now maybe reload the debug registers */
if
(
current
->
debugreg
[
7
]){
...
...
@@ -634,8 +635,8 @@ static void do_timer(struct pt_regs * regs)
}
#endif
}
if
(
current
==
task
[
0
]
||
(
--
current
->
counter
)
<=
0
)
{
current
->
counter
=
0
;
if
(
current
!=
task
[
0
]
&&
0
>
--
current
->
counter
)
{
current
->
counter
=
0
;
need_resched
=
1
;
}
/* Update ITIMER_PROF for the current task */
...
...
kernel/sys.c
View file @
e695b6a4
...
...
@@ -35,6 +35,23 @@ asmlinkage int sys_ni_syscall(void)
return
-
EINVAL
;
}
asmlinkage
int
sys_idle
(
void
)
{
int
i
;
/* Map out the low memory: it's no longer needed */
for
(
i
=
0
;
i
<
768
;
i
++
)
swapper_pg_dir
[
i
]
=
0
;
/* endless idle loop with no priority at all */
current
->
counter
=
-
100
;
for
(;;)
{
if
(
!
need_resched
)
__asm__
(
"hlt"
);
schedule
();
}
}
static
int
proc_sel
(
struct
task_struct
*
p
,
int
which
,
int
who
)
{
switch
(
which
)
{
...
...
kernel/vm86.c
View file @
e695b6a4
...
...
@@ -22,13 +22,14 @@
/*
* virtual flags (16 and 32-bit versions)
*/
#define VFLAGS
(regs)
(*(unsigned short *)&(current->v86flags))
#define VEFLAGS
(regs)
(current->v86flags)
#define VFLAGS (*(unsigned short *)&(current->v86flags))
#define VEFLAGS (current->v86flags)
#define set_flags(X,new,mask) \
((X) = ((X) & ~(mask)) | ((new) & (mask)))
#define SAFE_MASK (0xDD5)
#define RETURN_MASK (0xDFF)
asmlinkage
struct
pt_regs
*
save_v86_state
(
struct
vm86_regs
*
regs
)
{
...
...
@@ -38,6 +39,7 @@ asmlinkage struct pt_regs * save_v86_state(struct vm86_regs * regs)
printk
(
"no vm86_info: BAD
\n
"
);
do_exit
(
SIGSEGV
);
}
set_flags
(
regs
->
eflags
,
VEFLAGS
,
VIF_MASK
|
current
->
v86mask
);
memcpy_tofs
(
&
current
->
vm86_info
->
regs
,
regs
,
sizeof
(
*
regs
));
put_fs_long
(
current
->
screen_bitmap
,
&
current
->
vm86_info
->
screen_bitmap
);
tmp
=
current
->
tss
.
esp0
;
...
...
@@ -91,9 +93,9 @@ asmlinkage int sys_vm86(struct vm86_struct * v86)
* has set it up safely, so this makes sure interrupt etc flags are
* inherited from protected mode.
*/
current
->
v86flags
=
info
.
regs
.
eflags
;
VEFLAGS
=
info
.
regs
.
eflags
;
info
.
regs
.
eflags
&=
SAFE_MASK
;
info
.
regs
.
eflags
|=
~
SAFE_MASK
&
pt_regs
->
eflags
;
info
.
regs
.
eflags
|=
pt_regs
->
eflags
&
~
SAFE_MASK
;
info
.
regs
.
eflags
|=
VM_MASK
;
switch
(
info
.
cpu_type
)
{
...
...
@@ -142,14 +144,14 @@ static inline void return_to_32bit(struct vm86_regs * regs16, int retval)
static
inline
void
set_IF
(
struct
vm86_regs
*
regs
)
{
current
->
v86flags
|=
VIF_MASK
;
if
(
current
->
v86flags
&
VIP_MASK
)
VEFLAGS
|=
VIF_MASK
;
if
(
VEFLAGS
&
VIP_MASK
)
return_to_32bit
(
regs
,
VM86_STI
);
}
static
inline
void
clear_IF
(
struct
vm86_regs
*
regs
)
{
current
->
v86flags
&=
~
VIF_MASK
;
VEFLAGS
&=
~
VIF_MASK
;
}
static
inline
void
clear_TF
(
struct
vm86_regs
*
regs
)
...
...
@@ -159,7 +161,7 @@ static inline void clear_TF(struct vm86_regs * regs)
static
inline
void
set_vflags_long
(
unsigned
long
eflags
,
struct
vm86_regs
*
regs
)
{
set_flags
(
VEFLAGS
(
regs
)
,
eflags
,
current
->
v86mask
);
set_flags
(
VEFLAGS
,
eflags
,
current
->
v86mask
);
set_flags
(
regs
->
eflags
,
eflags
,
SAFE_MASK
);
if
(
eflags
&
IF_MASK
)
set_IF
(
regs
);
...
...
@@ -167,7 +169,7 @@ static inline void set_vflags_long(unsigned long eflags, struct vm86_regs * regs
static
inline
void
set_vflags_short
(
unsigned
short
flags
,
struct
vm86_regs
*
regs
)
{
set_flags
(
VFLAGS
(
regs
)
,
flags
,
current
->
v86mask
);
set_flags
(
VFLAGS
,
flags
,
current
->
v86mask
);
set_flags
(
regs
->
eflags
,
flags
,
SAFE_MASK
);
if
(
flags
&
IF_MASK
)
set_IF
(
regs
);
...
...
@@ -175,11 +177,19 @@ static inline void set_vflags_short(unsigned short flags, struct vm86_regs * reg
static
inline
unsigned
long
get_vflags
(
struct
vm86_regs
*
regs
)
{
unsigned
long
flags
=
regs
->
eflags
&
SAFE
_MASK
;
unsigned
long
flags
=
regs
->
eflags
&
RETURN
_MASK
;
if
(
current
->
v86flags
&
VIF_MASK
)
if
(
VEFLAGS
&
VIF_MASK
)
flags
|=
IF_MASK
;
return
flags
|
(
VEFLAGS
(
regs
)
&
current
->
v86mask
);
return
flags
|
(
VEFLAGS
&
current
->
v86mask
);
}
static
inline
int
is_revectored
(
int
nr
,
struct
revectored_struct
*
bitmap
)
{
__asm__
__volatile__
(
"btl %2,%%fs:%1
\n\t
sbbl %0,%0"
:
"=r"
(
nr
)
:
"m"
(
*
bitmap
),
"r"
(
nr
));
return
nr
;
}
/*
...
...
mm/memory.c
View file @
e695b6a4
...
...
@@ -1011,6 +1011,8 @@ void show_mem(void)
show_buffers
();
}
extern
unsigned
long
free_area_init
(
unsigned
long
,
unsigned
long
);
/*
* paging_init() sets up the page tables - note that the first 4MB are
* already mapped by head.S.
...
...
@@ -1056,7 +1058,7 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
}
}
invalidate
();
return
start_mem
;
return
free_area_init
(
start_mem
,
end_mem
)
;
}
void
mem_init
(
unsigned
long
start_low_mem
,
...
...
@@ -1065,33 +1067,12 @@ void mem_init(unsigned long start_low_mem,
int
codepages
=
0
;
int
reservedpages
=
0
;
int
datapages
=
0
;
unsigned
long
tmp
,
mask
;
unsigned
short
*
p
;
unsigned
long
tmp
;
extern
int
etext
;
cli
();
end_mem
&=
PAGE_MASK
;
high_memory
=
end_mem
;
start_mem
+=
0x0000000f
;
start_mem
&=
~
0x0000000f
;
tmp
=
MAP_NR
(
end_mem
);
mem_map
=
(
unsigned
short
*
)
start_mem
;
p
=
mem_map
+
tmp
;
start_mem
=
(
unsigned
long
)
p
;
while
(
p
>
mem_map
)
*--
p
=
MAP_PAGE_RESERVED
;
/* set up the free-area data structures */
for
(
mask
=
PAGE_MASK
,
tmp
=
0
;
tmp
<
NR_MEM_LISTS
;
tmp
++
,
mask
<<=
1
)
{
unsigned
long
bitmap_size
;
free_area_list
[
tmp
].
prev
=
free_area_list
[
tmp
].
next
=
&
free_area_list
[
tmp
];
end_mem
=
(
end_mem
+
~
mask
)
&
mask
;
bitmap_size
=
end_mem
>>
(
PAGE_SHIFT
+
tmp
);
bitmap_size
=
(
bitmap_size
+
7
)
>>
3
;
free_area_map
[
tmp
]
=
(
unsigned
char
*
)
start_mem
;
memset
((
void
*
)
start_mem
,
0
,
bitmap_size
);
start_mem
+=
bitmap_size
;
}
/* mark usable pages in the mem_map[] */
start_low_mem
=
PAGE_ALIGN
(
start_low_mem
);
...
...
mm/swap.c
View file @
e695b6a4
...
...
@@ -263,17 +263,6 @@ static inline int try_to_swap_out(unsigned long * table_ptr)
return
1
+
mem_map
[
MAP_NR
(
page
)];
}
/*
* sys_idle() does nothing much: it just searches for likely candidates for
* swapping out or forgetting about. This speeds up the search when we
* actually have to swap.
*/
asmlinkage
int
sys_idle
(
void
)
{
need_resched
=
1
;
return
0
;
}
/*
* A new implementation of swap_out(). We do not swap complete processes,
* but only a small number of blocks, before we continue with the next
...
...
@@ -896,3 +885,34 @@ void si_swapinfo(struct sysinfo *val)
val
->
totalswap
<<=
PAGE_SHIFT
;
return
;
}
/*
* set up the free-area data structures:
* - mark all pages MAP_PAGE_RESERVED
* - mark all memory queues empty
* - clear the memory bitmaps
*/
unsigned
long
free_area_init
(
unsigned
long
start_mem
,
unsigned
long
end_mem
)
{
unsigned
short
*
p
;
unsigned
long
mask
=
PAGE_MASK
;
int
i
;
mem_map
=
(
unsigned
short
*
)
start_mem
;
p
=
mem_map
+
MAP_NR
(
end_mem
);
start_mem
=
(
unsigned
long
)
p
;
while
(
p
>
mem_map
)
*--
p
=
MAP_PAGE_RESERVED
;
for
(
i
=
0
;
i
<
NR_MEM_LISTS
;
i
++
,
mask
<<=
1
)
{
unsigned
long
bitmap_size
;
free_area_list
[
i
].
prev
=
free_area_list
[
i
].
next
=
&
free_area_list
[
i
];
end_mem
=
(
end_mem
+
~
mask
)
&
mask
;
bitmap_size
=
end_mem
>>
(
PAGE_SHIFT
+
i
);
bitmap_size
=
(
bitmap_size
+
7
)
>>
3
;
free_area_map
[
i
]
=
(
unsigned
char
*
)
start_mem
;
memset
((
void
*
)
start_mem
,
0
,
bitmap_size
);
start_mem
+=
bitmap_size
;
}
return
start_mem
;
}
net/inet/icmp.c
View file @
e695b6a4
...
...
@@ -186,6 +186,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, struct device *dev)
icmp_statistics
.
IcmpOutErrors
++
;
return
;
}
skb
->
free
=
1
;
/*
* Build Layer 2-3 headers for message back to source.
...
...
net/inet/skbuff.c
View file @
e695b6a4
...
...
@@ -387,7 +387,8 @@ void kfree_skb(struct sk_buff *skb, int rw)
{
if
(
skb
==
NULL
)
{
printk
(
"kfree_skb: skb = NULL
\n
"
);
printk
(
"kfree_skb: skb = NULL (from %08lx)
\n
"
,
((
unsigned
long
*
)
&
skb
)[
-
1
]);
return
;
}
IS_SKB
(
skb
);
...
...
@@ -397,9 +398,11 @@ void kfree_skb(struct sk_buff *skb, int rw)
return
;
}
if
(
skb
->
free
==
2
)
printk
(
"Warning: kfree_skb passed an skb that nobody set the free flag on!
\n
"
);
printk
(
"Warning: kfree_skb passed an skb that nobody set the free flag on! (from %08lx)
\n
"
,
((
unsigned
long
*
)
&
skb
)[
-
1
]);
if
(
skb
->
next
)
printk
(
"Warning: kfree_skb passed an skb still on a list.
\n
"
);
printk
(
"Warning: kfree_skb passed an skb still on a list (from %08lx).
\n
"
,
((
unsigned
long
*
)
&
skb
)[
-
1
]);
if
(
skb
->
sk
)
{
if
(
skb
->
sk
->
prot
!=
NULL
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment