Commit 9d094864 authored by Linus Torvalds's avatar Linus Torvalds

Import 0.99.14g

parent 88ba9b13
VERSION = 0.99
PATCHLEVEL = 14
ALPHA = f
ALPHA = g
all: Version zImage
......
......@@ -16,6 +16,7 @@ bool 'Use -m486 flag for 486-specific optimizations' CONFIG_M486 y
* Program binary formats
*
bool 'Elf executables' CONFIG_BINFMT_ELF y
bool 'COFF executables' CONFIG_BINFMT_COFF y
*
* SCSI support
*
......@@ -98,6 +99,7 @@ bool '/proc filesystem support' CONFIG_PROC_FS y
bool 'NFS filesystem support' CONFIG_NFS_FS y
bool 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS n
bool 'OS/2 HPFS filesystem support (read only)' CONFIG_HPFS_FS n
bool 'System V and Coherent filesystem support' CONFIG_SYSV_FS n
*
* character devices
*
......
......@@ -1468,6 +1468,37 @@ static void get_scrmem(int currcons)
static void set_scrmem(int currcons)
{
#ifdef CONFIG_HGA
/* This works with XFree86 1.2, 1.3 and 2.0
This code could be extended and made more generally useful if we could
determine the actual video mode. It appears that this should be
possible on a genuine Hercules card, but I (WM) haven't been able to
read from any of the required registers on my clone card.
*/
/* This code should work with Hercules and MDA cards. */
if (video_type == VIDEO_TYPE_MDA)
{
if (vcmode == KD_TEXT)
{
/* Ensure that the card is in text mode. */
int i;
static char herc_txt_tbl[12] = {
0x61,0x50,0x52,0x0f,0x19,6,0x19,0x19,2,0x0d,0x0b,0x0c };
outb_p(0, 0x3bf); /* Back to power-on defaults */
outb_p(0, 0x3b8); /* Blank the screen, select page 0, etc */
for ( i = 0 ; i < 12 ; i++ )
{
outb_p(i, 0x3b4);
outb_p(herc_txt_tbl[i], 0x3b5);
}
}
#define HGA_BLINKER_ON 0x20
#define HGA_SCREEN_ON 8
/* Make sure that the hardware is not blanked */
outb_p(HGA_BLINKER_ON | HGA_SCREEN_ON, 0x3b8);
}
#endif CONFIG_HGA
video_mem_start = video_mem_base;
video_mem_end = video_mem_term;
origin = video_mem_start;
......
This diff is collapsed.
......@@ -219,18 +219,6 @@ static struct file_operations tty_fops = {
};
static struct file_operations hung_up_tty_fops = {
tty_lseek,
hung_up_tty_read,
hung_up_tty_write,
NULL, /* hung_up_tty_readdir */
hung_up_tty_select,
tty_ioctl,
NULL, /* hung_up_tty_mmap */
tty_open,
tty_release
};
static struct file_operations vhung_up_tty_fops = {
tty_lseek,
hung_up_tty_read,
hung_up_tty_write,
......@@ -238,22 +226,22 @@ static struct file_operations vhung_up_tty_fops = {
hung_up_tty_select,
hung_up_tty_ioctl,
NULL, /* hung_up_tty_mmap */
tty_open,
tty_release
NULL, /* hung_up_tty_open */
tty_release /* hung_up_tty_release */
};
void do_tty_hangup(struct tty_struct * tty, struct file_operations *fops)
{
int i;
struct file * filp;
struct task_struct **p;
struct task_struct *p;
int dev;
if (!tty)
return;
dev = 0x0400 + tty->line;
for (filp = first_file, i=0; i<nr_files; i++, filp = filp->f_next) {
if (!filp->f_count)
if (!filp->f_count)
continue;
if (filp->f_rdev != dev)
continue;
......@@ -263,38 +251,71 @@ void do_tty_hangup(struct tty_struct * tty, struct file_operations *fops)
continue;
filp->f_op = fops;
}
flush_input(tty);
flush_output(tty);
wake_up_interruptible(&tty->secondary.proc_list);
wake_up_interruptible(&tty->read_q.proc_list);
wake_up_interruptible(&tty->write_q.proc_list);
if (tty->session > 0)
kill_sl(tty->session,SIGHUP,1);
tty->session = 0;
tty->pgrp = -1;
for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
if ((*p) && (*p)->tty == tty->line)
(*p)->tty = -1;
for_each_task(p) {
if (p->tty == tty->line)
p->tty = -1;
}
if (tty->hangup)
(tty->hangup)(tty);
}
void tty_hangup(struct tty_struct * tty)
{
#ifdef TTY_DEBUG_HANGUP
printk("tty%d hangup...\n", tty->line);
#endif
do_tty_hangup(tty, &hung_up_tty_fops);
}
void tty_vhangup(struct tty_struct * tty)
{
do_tty_hangup(tty, &vhung_up_tty_fops);
#ifdef TTY_DEBUG_HANGUP
printk("tty%d vhangup...\n", tty->line);
#endif
do_tty_hangup(tty, &hung_up_tty_fops);
}
void tty_unhangup(struct file *filp)
int tty_hung_up_p(struct file * filp)
{
filp->f_op = &tty_fops;
return (filp->f_op == &hung_up_tty_fops);
}
int tty_hung_up_p(struct file * filp)
/*
* This function is typically called only by the session leader, when
* it wants to dissassociate itself from its controlling tty.
*
* It performs the following functions:
* (1) Sends a SIGHUP to the foreground process group
* (2) Clears the tty from being controlling the session
* (3) Clears the controlling tty for all processes in the
* session group.
*/
void disassociate_ctty(int priv)
{
return ((filp->f_op == &hung_up_tty_fops) ||
(filp->f_op == &vhung_up_tty_fops));
struct tty_struct *tty;
struct task_struct *p;
if (current->tty >= 0) {
tty = tty_table[current->tty];
if (tty) {
if (tty->pgrp > 0)
kill_pg(tty->pgrp, SIGHUP, priv);
tty->session = 0;
tty->pgrp = -1;
} else
printk("disassociate_ctty: ctty is NULL?!?");
}
for_each_task(p)
if (p->session == current->session)
p->tty = -1;
}
/*
......@@ -514,7 +535,7 @@ void copy_to_cooked(struct tty_struct * tty)
break;
}
if (special_flag) {
tty->char_error = c & 3;
tty->char_error = c & 7;
continue;
}
if (tty->char_error) {
......@@ -529,7 +550,12 @@ void copy_to_cooked(struct tty_struct * tty)
put_tty_queue('\0', &tty->secondary);
continue;
}
/* If not a break, then a parity or frame error */
if (tty->char_error == TTY_OVERRUN) {
tty->char_error = 0;
printk("tty%d: input overrun\n", tty->line);
continue;
}
/* Must be a parity or frame error */
tty->char_error = 0;
if (I_IGNPAR(tty)) {
continue;
......@@ -1204,6 +1230,9 @@ static void release_dev(int dev, struct file * filp)
printk("release_dev: tty_termios[%d] was NULL\n", dev);
return;
}
#ifdef TTY_DEBUG_HANGUP
printk("release_dev of tty%d (tty count=%d)...", dev, tty->count);
#endif
if (IS_A_PTY(dev)) {
o_tty = tty_table[PTY_OTHER(dev)];
o_tp = tty_termios[PTY_OTHER(dev)];
......@@ -1237,6 +1266,10 @@ static void release_dev(int dev, struct file * filp)
}
if (tty->count)
return;
#ifdef TTY_DEBUG_HANGUP
printk("freeing tty structure...");
#endif
/*
* Make sure there aren't any processes that still think this
......@@ -1247,9 +1280,15 @@ static void release_dev(int dev, struct file * filp)
(*p)->tty = -1;
}
/*
* Shutdown the current line discipline, and reset it to
* N_TTY.
*/
if (ldiscs[tty->disc].close != NULL)
ldiscs[tty->disc].close(tty);
tty->disc = N_TTY;
tty->termios->c_line = N_TTY;
if (o_tty) {
if (o_tty->count)
return;
......@@ -1298,7 +1337,7 @@ static int tty_open(struct inode * inode, struct file * filp)
major = TTY_MAJOR;
minor = current->tty;
}
noctty = 1;
/* noctty = 1; */
} else if (major == TTY_MAJOR) {
if (!minor) {
minor = fg_console + 1;
......@@ -1317,6 +1356,11 @@ static int tty_open(struct inode * inode, struct file * filp)
if (retval)
return retval;
tty = tty_table[minor];
#ifdef TTY_DEBUG_HANGUP
printk("opening tty%d...", tty->line);
#endif
if (test_bit(TTY_EXCLUSIVE, &tty->flags) && !suser())
return -EBUSY;
/* clean up the packet stuff. */
/*
......@@ -1337,6 +1381,10 @@ static int tty_open(struct inode * inode, struct file * filp)
retval = -ENODEV;
}
if (retval) {
#ifdef TTY_DEBUG_HANGUP
printk("error %d in opening tty%d...", retval, tty->line);
#endif
release_dev(minor, filp);
return retval;
}
......@@ -1453,6 +1501,9 @@ static int tty_select(struct inode * inode, struct file * filp, int sel_type, se
*/
void do_SAK( struct tty_struct *tty)
{
#ifdef TTY_SOFT_SAK
tty_hangup(tty);
#else
struct task_struct **p;
int line = tty->line;
int session = tty->session;
......@@ -1478,6 +1529,7 @@ void do_SAK( struct tty_struct *tty)
}
}
}
#endif
}
/*
......
......@@ -19,6 +19,7 @@
#include <linux/fcntl.h>
#include <asm/io.h>
#include <asm/bitops.h>
#include <asm/segment.h>
#include <asm/system.h>
......@@ -493,19 +494,42 @@ int tty_ioctl(struct inode * inode, struct file * file,
return -EINVAL;
return 0;
case TIOCEXCL:
return -EINVAL; /* not implemented */
set_bit(TTY_EXCLUSIVE, &tty->flags);
return 0;
case TIOCNXCL:
return -EINVAL; /* not implemented */
clear_bit(TTY_EXCLUSIVE, &tty->flags);
return 0;
case TIOCSCTTY:
if ((current->leader && current->tty < 0 &&
tty->session == 0) ||
(arg == 1 && suser())) {
current->tty = dev;
tty->session = current->session;
tty->pgrp = current->pgrp;
if (current->leader &&
(current->session == tty->session))
return 0;
/*
* The process must be a session leader and
* not have a controlling tty already.
*/
if (!current->leader || (current->tty >= 0))
return -EPERM;
if (tty->session > 0) {
/*
* This tty is already the controlling
* tty for another session group!
*/
if ((arg == 1) && suser()) {
/*
* Steal it away
*/
struct task_struct *p;
for_each_task(p)
if (p->tty == dev)
p->tty = -1;
} else
return -EPERM;
}
return -EPERM;
current->tty = dev;
tty->session = current->session;
tty->pgrp = current->pgrp;
return 0;
case TIOCGPGRP:
retval = verify_area(VERIFY_WRITE, (void *) arg,4);
if (!retval)
......@@ -540,7 +564,8 @@ int tty_ioctl(struct inode * inode, struct file * file,
(unsigned long *) arg);
return 0;
case TIOCSTI:
return -EINVAL; /* not implemented */
put_tty_queue(get_fs_byte((char *) arg), &tty->read_q);
return 0;
case TIOCGWINSZ:
return get_window_size(tty,(struct winsize *) arg);
case TIOCSWINSZ:
......@@ -595,13 +620,9 @@ int tty_ioctl(struct inode * inode, struct file * file,
case TIOCNOTTY:
if (MINOR(file->f_rdev) != current->tty)
return -EINVAL;
if (current->leader)
disassociate_ctty(0);
current->tty = -1;
if (current->leader) {
if (tty->pgrp > 0)
kill_pg(tty->pgrp, SIGHUP, 0);
tty->pgrp = -1;
tty->session = 0;
}
return 0;
case TIOCGETD:
retval = verify_area(VERIFY_WRITE, (void *) arg,4);
......
......@@ -2,9 +2,6 @@
/*
Copyright (C) 1992,1993 Donald Becker
This is alpha test code. No redistribution is permitted.
If this code is distributed, it will carry the following:
Copyright 1993 United States Government as represented by the
Director, National Security Agency. This software may be used and
distributed according to the terms of the GNU Public License,
......
......@@ -17,7 +17,7 @@
/* Routines for the NatSemi-based designs (NE[12]000). */
static char *version =
"ne.c:v0.99-13s 11/17/93 Donald Becker (becker@super.org)\n";
"ne.c:v0.99-14g 12/21/93 Donald Becker (becker@super.org)\n";
#include <linux/config.h>
#include <linux/kernel.h>
......@@ -104,7 +104,7 @@ static int neprobe1(int ioaddr, struct device *dev, int verbose)
int wordlength = 2;
char *name;
int start_page, stop_page;
int neX000, ctron, dlink;
int neX000, ctron, dlink, dfi;
int reg0 = inb(ioaddr);
if ( reg0 == 0xFF)
......@@ -151,8 +151,8 @@ static int neprobe1(int ioaddr, struct device *dev, int verbose)
outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
}
for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {
SA_prom[i] = inb_p(ioaddr + NE_DATAPORT);
SA_prom[i+1] = inb_p(ioaddr + NE_DATAPORT);
SA_prom[i] = inb(ioaddr + NE_DATAPORT);
SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);
if (SA_prom[i] != SA_prom[i+1])
wordlength = 1;
}
......@@ -179,12 +179,13 @@ static int neprobe1(int ioaddr, struct device *dev, int verbose)
}
#endif
neX000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57);
neX000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57);
ctron = (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
dlink = (SA_prom[0] == 0x00 && SA_prom[1] == 0xDE && SA_prom[2] == 0x01);
dfi = (SA_prom[0] == 'D' && SA_prom[1] == 'F' && SA_prom[2] == 'I');
/* Set up the rest of the parameters. */
if (neX000 || dlink) {
if (neX000 || dlink || dfi) {
if (wordlength == 2) {
name = dlink ? "DE200" : "NE2000";
start_page = NESM_START_PG;
......
......@@ -14,7 +14,7 @@
*/
static char *version =
"smc-ultra.c:v0.04 11/30/93 Donald Becker (becker@super.org)\n";
"smc-ultra.c:v0.05 12/21/93 Donald Becker (becker@super.org)\n";
#include <linux/config.h>
#include <linux/kernel.h>
......@@ -59,7 +59,7 @@ static int ultra_close_card(struct device *dev);
int ultra_probe(struct device *dev)
{
int *port, ports[] = {0x200, 0x220, 0x240, 0x280, 0x300, 0x380, 0};
int *port, ports[] = {0x200, 0x220, 0x240, 0x280, 0x300, 0x340, 0x380, 0};
unsigned short ioaddr = dev->base_addr;
if (ioaddr > 0x1ff)
......@@ -70,7 +70,7 @@ int ultra_probe(struct device *dev)
for (port = &ports[0]; *port; port++) {
if (check_region(*port, 32))
continue;
if ((inb(*port + 7) & 0xF0) == 0x20 /* Check chip ID nibble. */
if ((inb(*port + 7) & 0xF0) == 0x20 /* Check chip ID nibble. */
&& ultraprobe1(*port, dev) == 0)
return 0;
}
......@@ -84,12 +84,13 @@ int ultraprobe1(int ioaddr, struct device *dev)
unsigned char *station_addr = dev->dev_addr;
int checksum = 0;
char *model_name;
int num_pages;
unsigned char eeprom_irq = 0;
/* Values from various config regs. */
unsigned char num_pages, irqreg, addr, reg4 = inb(ioaddr + 4) & 0x7f;
/* Select the station address register set. */
outb(0x7f & inb(ioaddr + 4), ioaddr + 4);
outb(reg4, ioaddr + 4);
for (i = 0; i < 8; i++)
checksum += inb(ioaddr + 8 + i);
......@@ -100,14 +101,23 @@ int ultraprobe1(int ioaddr, struct device *dev)
for (i = 0; i < 6; i++)
printk(" %2.2X", station_addr[i] = inb(ioaddr + 8 + i));
/* Switch from the station address to the alternate register set. */
outb(0x80 | inb(ioaddr + 4), ioaddr + 4);
/* Switch from the station address to the alternate register set and
read the useful registers there. */
outb(0x80 | reg4, ioaddr + 4);
/* Enabled FINE16 mode to avoid BIOS ROM width mismatches during reboot. */
outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c);
irqreg = inb(ioaddr + 0xd);
addr = inb(ioaddr + 0xb);
/* Switch back to the station address register set so that the MS-DOS driver
can find the card after a warm boot. */
outb(reg4, ioaddr + 4);
model_name = "SMC Ultra";
if (dev->irq < 2) {
unsigned char irqmap[] = {0, 9, 3, 5, 7, 10, 11, 15};
int irqreg = inb(ioaddr + 0xd);
int irq;
/* The IRQ bits are split. */
......@@ -129,7 +139,6 @@ int ultraprobe1(int ioaddr, struct device *dev)
dev->base_addr = ioaddr+ULTRA_NIC_OFFSET;
{
int addr = inb(ioaddr + 0xb);
int addr_tbl[4] = {0x0C0000, 0x0D0000, 0xFC0000, 0xFD0000};
short num_pages_tbl[4] = {0x20, 0x40, 0x80, 0xff};
......@@ -172,8 +181,6 @@ ultra_open(struct device *dev)
if (irqaction(dev->irq, &ei_sigaction))
return -EAGAIN;
/* Enabled FINE16 mode. */
outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c);
outb(ULTRA_MEMENB, ioaddr); /* Enable memory, 16 bit mode. */
outb(0x80, ioaddr + 5);
outb(0x01, ioaddr + 6); /* Enable interrupts and memory. */
......
......@@ -30,8 +30,8 @@ static char *version =
/* Compatibility definitions for earlier kernel versions. */
#ifndef HAVE_PORTRESERVE
#define check_region(ioaddr, size) 0
#define snarf_region(ioaddr, size); do ; while (0)
#define check_region(ioaddr, size) 0
#define snarf_region(ioaddr, size) do ; while (0)
#endif
int wd_probe(struct device *dev);
......
......@@ -16,6 +16,7 @@
#include <linux/types.h>
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/config.h>
#include <linux/sched.h>
#include <asm/dma.h>
......@@ -50,8 +51,13 @@ static unsigned int bases[]={0x330, 0x334};
#define DMA_MASK_REG 0xd4
#define CASCADE 0xc0
#define BIOS_TRANSLATION_1632 0 /* Used by some old 1542A boards */
#define BIOS_TRANSLATION_6432 1 /* Default case these days */
#define BIOS_TRANSLATION_25563 2 /* Big disk case */
struct aha1542_hostdata{
/* This will effectively start both of them at the first mailbox */
int bios_translation; /* Mapping bios uses - for compatibility */
int aha1542_last_mbi_used;
int aha1542_last_mbo_used;
Scsi_Cmnd * SCint[AHA1542_MAILBOXES];
......@@ -174,6 +180,10 @@ static int makecode(unsigned hosterr, unsigned scsierr)
static int aha1542_test_port(int bse, struct Scsi_Host * shpnt)
{
int i;
unchar inquiry_cmd[] = {CMD_INQUIRY };
unchar inquiry_result[4];
unchar *cmdp;
int len;
volatile int debug = 0;
/* Quick and dirty test for presence of the card. */
......@@ -195,27 +205,22 @@ static int aha1542_test_port(int bse, struct Scsi_Host * shpnt)
debug = 2;
/* Shouldn't have generated any interrupts during reset */
if (inb(INTRFLAGS(bse))&INTRMASK) goto fail;
setup_mailboxes(bse, shpnt);
/* Perform a host adapter inquiry instead so we do not need to set
up the mailboxes ahead of time */
aha1542_out(bse, inquiry_cmd, 1);
debug = 3;
/* Test the basic ECHO command */
outb(CMD_ECHO, DATA(bse));
debug = 4;
/* Wait for CDF=0. If any of the others are set, it's bad */
WAIT(STATUS(bse), STATMASK, 0, STST|DIAGF|INVDCMD|DF|CDF);
debug = 5;
/* The meaning of life */
outb(42, DATA(bse));
debug = 6;
/* Expect only DF, that is, data ready */
WAIT(STATUS(bse), STATMASK, DF, STST|DIAGF|CDF|INVDCMD);
debug = 7;
/* Is the answer correct? */
if (inb(DATA(bse)) != 42) goto fail;
len = 4;
cmdp = &inquiry_result[0];
while (len--)
{
WAIT(STATUS(bse), DF, DF, 0);
*cmdp++ = inb(DATA(bse));
}
debug = 8;
/* Reading port should reset DF */
......@@ -298,10 +303,7 @@ static void aha1542_intr_handle(int foo)
sti();
/* Hmm, no mail. Must have read it the last time around */
if (number_serviced) return;
/* Virtually all of the time, this turns out to be the problem */
printk("aha1542.c: Unsupported BIOS options enabled."
" Please turn off.\n");
/* printk("aha1542.c: interrupt received, but no mail.\n"); */
printk("aha1542.c: interrupt received, but no mail.\n");
return;
};
......@@ -656,8 +658,41 @@ static int aha1542_getconfig(int base_io, unsigned char * irq_level, unsigned ch
return 0;
}
/* This function should only be called for 1542C boards - we can detect
the special firmware settings and unlock the board */
static int aha1542_mbenable(int base)
{
static unchar mbenable_cmd[3];
static unchar mbenable_result[2];
int retval;
retval = BIOS_TRANSLATION_6432;
mbenable_cmd[0]=CMD_EXTBIOS;
aha1542_out(base,mbenable_cmd,1);
aha1542_in(base,mbenable_result,2);
WAIT(INTRFLAGS(base),INTRMASK,HACC,0);
aha1542_intr_reset(base);
if (mbenable_result[0] & 0x08) {
mbenable_cmd[0]=CMD_MBENABLE;
mbenable_cmd[1]=0;
mbenable_cmd[2]=mbenable_result[1];
if(mbenable_result[1] & 1) retval = BIOS_TRANSLATION_25563;
aha1542_out(base,mbenable_cmd,3);
WAIT(INTRFLAGS(base),INTRMASK,HACC,0);
};
while(0) {
fail:
printk("aha1542_mbenable: Mailbox init failed\n");
}
aha1542_intr_reset(base);
return retval;
}
/* Query the board to find out if it is a 1542 or a 1740, or whatever. */
static int aha1542_query(int base_io)
static int aha1542_query(int base_io, int * transl)
{
unchar inquiry_cmd[] = {CMD_INQUIRY };
unchar inquiry_result[4];
......@@ -675,6 +710,8 @@ static int aha1542_query(int base_io)
}
aha1542_intr_reset(base_io);
*transl = BIOS_TRANSLATION_6432; /* Default case */
/* For an AHA1740 series board, we ignore the board since there is a
hardware bug which can lead to wrong blocks being returned if the board
is operating in the 1542 emulation mode. Since there is an extended mode
......@@ -685,15 +722,20 @@ static int aha1542_query(int base_io)
printk("aha1542.c: Emulation mode not supported for AHA 174N hardware.\n");
return 1;
};
if (inquiry_result[0] == 0x44) { /* Detect 1542C */
*transl = aha1542_mbenable(base_io);
};
return 0;
}
/* return non-zero on detection */
int aha1542_detect(int hostnum)
{
unsigned char dma_chan;
unsigned char irq_level;
unsigned int base_io;
int trans;
struct Scsi_Host * shpnt = NULL;
int count = 0;
int indx;
......@@ -727,7 +769,7 @@ int aha1542_detect(int hostnum)
}
aha1542_intr_reset(base_io);
}
if(aha1542_query(base_io)) goto unregister;
if(aha1542_query(base_io, &trans)) goto unregister;
if (aha1542_getconfig(base_io, &irq_level, &dma_chan) == -1) goto unregister;
......@@ -764,6 +806,9 @@ int aha1542_detect(int hostnum)
shpnt->io_port = base_io;
shpnt->dma_channel = dma_chan;
shpnt->irq = irq_level;
HOSTDATA(shpnt)->bios_translation = trans;
if(trans == 2)
printk("aha1542.c: Using extended bios translation\n");
HOSTDATA(shpnt)->aha1542_last_mbi_used = (2*AHA1542_MAILBOXES - 1);
HOSTDATA(shpnt)->aha1542_last_mbo_used = (AHA1542_MAILBOXES - 1);
memset(HOSTDATA(shpnt)->SCint, 0, sizeof(HOSTDATA(shpnt)->SCint));
......@@ -847,11 +892,30 @@ int aha1542_reset(Scsi_Cmnd * SCpnt)
return 0;
}
#ifdef CONFIG_BLK_DEV_SD
#include "sd.h"
#endif
int aha1542_biosparam(int size, int dev, int * ip)
{
ip[0] = 64;
ip[1] = 32;
ip[2] = size >> 11;
int translation_algorithm;
#ifdef CONFIG_BLK_DEV_SD
Scsi_Device *disk;
disk = rscsi_disks[MINOR(dev) >> 4].device;
translation_algorithm = HOSTDATA(disk->host)->bios_translation;
/* Should this be > 1024, or >= 1024? Enquiring minds want to know. */
if((size>>11) > 1024 && translation_algorithm == 2) {
/* Please verify that this is the same as what DOS returns */
ip[0] = 255;
ip[1] = 63;
ip[2] = size /255/63;
} else {
ip[0] = 64;
ip[1] = 32;
ip[2] = size >> 11;
};
/* if (ip[2] >= 1024) ip[2] = 1024; */
#endif
return 0;
}
......@@ -74,6 +74,9 @@
#define CMD_RETSETUP 0x0d /* Return Setup Data */
#define CMD_ECHO 0x1f /* ECHO Command Data */
#define CMD_EXTBIOS 0x28 /* Return extend bios information only 1542C */
#define CMD_MBENABLE 0x29 /* Set Mailbox Interface enable only 1542C */
/* Mailbox Definition 5.2.1 and 5.2.2 */
struct mailbox {
unchar status; /* Command/Status */
......
......@@ -362,7 +362,7 @@ static void scan_scsis (void)
break;
case TYPE_DISK:
case TYPE_MOD:
printk("Detected scsi disk sd%d at scsi%d, id %d, lun %d\n", MAX_SD,
printk("Detected scsi disk sd%c at scsi%d, id %d, lun %d\n", 'a'+MAX_SD,
shpnt->host_no , dev, lun);
if(NR_SD != -1) ++MAX_SD;
break;
......
......@@ -101,7 +101,12 @@ int check_cdrom_media_change(int full_dev, int flag){
};
retval = scsi_CDs[target].device->changed;
if(!flag) scsi_CDs[target].device->changed = 0;
if(!flag) {
scsi_CDs[target].device->changed = 0;
/* If the disk changed, the capacity will now be different,
so we force a re-read of this information */
if (retval) scsi_CDs[target].needs_sector_size = 1;
};
return retval;
}
......@@ -654,6 +659,8 @@ static void get_sectorsize(int i){
memset ((void *) &cmd[2], 0, 8);
SCpnt->request.dev = 0xffff; /* Mark as really busy */
memset(buffer, 0, 8);
scsi_do_cmd (SCpnt,
(void *) cmd, (void *) buffer,
512, sr_init_done, SR_TIMEOUT,
......@@ -692,6 +699,7 @@ static void get_sectorsize(int i){
printk ("scd%d : unsupported sector size %d.\n",
i, scsi_CDs[i].sector_size);
scsi_CDs[i].capacity = 0;
scsi_CDs[i].needs_sector_size = 1;
};
if(scsi_CDs[i].sector_size == 2048)
scsi_CDs[i].capacity *= 4;
......
NOTE! This driver version is not compatible with the version 1.0c.
This means you have to use the latest version of the snd-util
package. The earlier ones (from 1.0) will not work. If you have
package (2.0). The earlier ones (from 1.0) will not work. If you have
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
Changelog for version 2.2b
Changelog for version 2.3
-------------------------
Since 2.2b
- Full SB16 DSP support. 8/16 bit, mono/stereo
- The SCO and FreeBSD versions should be in sync now. There are some
problems with SB16 and GUS in the freebsd versions.
The DMA buffer allocation of the SCO version has been polished but
there could still be some problems. At least it hogs memory.
The DMA channel
configuration method used in the sco/System is a hack.
- Support for the MPU emulation of the SB16.
- Some big arrays are now allocated boot time. This makes the bss segment
smaller which makes it possible to use the full driver with
NetBSD. These arrays are not allocated if no suitable soundcard is available.
- Fixed a bug in the compute_and_set_volume in gus_wave.c
- Fixed the too fast mono playback problem of SB Pro and PAS16.
Since 2.2
- Stereo recording for SB Pro. Somehow it was missing and nobody
had noticed it earlier.
- Minor polishing.
- Interpreting of boot time arguments (sound=) for Linux.
- Breakup of sb_dsp.c. Parts of the code has been moved to
sb_mixer.c and sb_midi.c
Since 2.1
- Preliminary support for SB16.
......
......@@ -5,9 +5,8 @@
#
#
VERSION = 2.2b
VERSION = 2.3
TARGET_OS = linux
USRINCDIR = /usr/include
.c.s:
$(CC) $(CFLAGS) -S $<
......@@ -19,10 +18,21 @@ USRINCDIR = /usr/include
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
gus_midi.o gus_vol.o patmgr.o sb_mixer.o sb16_dsp.o sb_midi.o \
sb16_midi.o sound_switch.o
all: local.h sound.a
/usr/include/sys/soundcard.h:
@echo "WARNING! Your /usr/include/sys/soundcard.h not found."
@echo "Please make a new /usr/include/sys/soundcard.h containing
@echo "just a line #include <linux/soundcard.h>"
os.h:
@$(MAKE) setup-$(TARGET_OS)
@$(MAKE) config
@$(MAKE) dep
sound.a: $(OBJS)
-rm -f sound.a
$(AR) rcs sound.a $(OBJS)
......@@ -38,10 +48,16 @@ indent:
local.h:
$(MAKE) clean
$(MAKE) setup-$(TARGET_OS)
$(MAKE) config
$(MAKE) dep
config: configure
soundcard.c: $(TARGET_OS)/soundcard.c
ln -sf $(TARGET_OS)/soundcard.c soundcard.c
config: configure /usr/include/sys/soundcard.h
@$(MAKE) setup-$(TARGET_OS)
@echo Compiling Sound Driver v $(VERSION) for Linux
@./configure > local.h
@echo \#define SOUND_VERSION_STRING \"$(VERSION)\" >> local.h
@echo \#define SOUND_CONFIG_DATE \"`date`\" >> local.h
......@@ -49,11 +65,15 @@ config: configure
@echo \#define SOUND_CONFIG_HOST \"`hostname`\" >> local.h
@echo \#define SOUND_CONFIG_DOMAIN \"`domainname`\" >> local.h
configure: configure.c
clrconf:
rm -f local.h .depend os.h soundcard.c
configure: configure.c /usr/include/sys/soundcard.h
$(HOSTCC) -o configure configure.c
@cat .blurb
dep:
$(MAKE) /usr/include/sys/soundcard.h
$(CPP) -M *.c > .depend
#
......
This diff is collapsed.
Sound Card Driver version 2.2
This directory contains the driver for various PC soundcards.
The following cards are supported:
AdLib
SoundBlaster (1.0-2.0) and compatibles, including
ThunderBoard and Ati Stereo F/X.
SoundBlaster Pro and SB Pro 2
SoundBlaster 16
ProAudioSpectrum 16
(The original ProAudioSpectrum and the PAS+ are not supported
(and propably will remain unsupported)).
If you have any problems, please contact me.
Installation
------------
- Since this driver is a part of the Linux kernel distribution, no
special steps are required to build the driver itself.
- To build the device files you need to run the enclosed shell scrip
(see below).
- Copy the sound/ultrasound.h to /usr/include/sys
(Remove the old one from /usr/include/sys /usr/include/linux first).
- Ensure you have the following symlink:
ln -s /usr/include/linux/soundcard.h /usr/include/sys/soundcard.h
Boot time configuration (using lilo)
------------------------------------
This version of the sound driver has capability to accept the configuration
parameters from the boot loader (for example lilo). By default the
driver is booted using the parameters given before compiling the driver
('make config' or 'make soundconf'). If the kernel is booted using lilo and
the boot command is given manually, it's possible to give the configuration
parameters on the command line. Just hold down the <Alt> key when lilo
starts. Then give the boot command manually and append a sound= argument
to the boot command line. For example:
lilo boot: linux sound=0x222071,0x138800
The sound= argument could contain several configuration entries separated by a
comma. Each option gives the configuration for one sound device.
Give the options in the order given below. Other order of use is undefined.
Each option is encoded as the following:
0xTaaaId, where
|| ||
|| |+---- d = DMA channel (0, 1, 3, 5, 6 or 7)
|| +----- I = IRQ (HEXADECIMAL!!! 1=1, ..., 9=9, 10=a, ..., 15=f)
|+-------- aaa = I/O address (hexadecimal)
+---------- T = device type 1=FM Synth (YM3812 or OPL3)
2=SoundBlaster (1.0 to 2.0, Pro, 16)
3=ProAudioSpectrum16
4=Gravis UltraSound
5=MPU-401 UART midi
6=SB16 (16 bit DMA number)
7=SB16 Midi (MPU-401 emulation)
These are the configuration templates for various soundcards:
0) Disable the sound driver
sound=0
1) AdLib
sound=0x138800
2) SoundBlaster family and compatibles
sound=0x2220Id,0x138800 (remember to set the IRQ and DMA)
or if you have SB16 or SB16ASP, you have to use the following:
(use the same IRQ (the I colums) in all three places. The
the D is the 16 bit DMA channel (5 to 7) and the d is
the 8 bit one (1 or 3). The X is the 2nd digit of the
midi IO address (3 or 0)).
sound=0x2220Id,0x6220ID,0x73X0I0,0x138800
3) ProAudioSpectrum16, ProAudioStudio16, Logitech Soundman16 etc.
sound=0x3388Id,0x2220Id,0x138800 (set the DMAs and IRQs)
4) Gravis UltraSound
sound=0x42X0Id (X is 1, 2, 3 or 4. Set the DMA and IRQ)
5) MPU-401
sound=0x5aaaI0
If you have more than one soundcards, you have to concatenate the options
for each of the cards. There cannot be more than one sound= argument in the
command line. For example use "sound=0x5aaaI0,0x138800" if you have AdLib
and MPU-401 on your system.
If there are two or more sound= arguments
in the boot command line, just the last one takes effect. The earlier ones
will be ignored silently.
The boot time configuration feature is intended mainly for distributors of
precompiled kernels. When this feature is used, drivers for all of the
cards have to be enabled before compiling the driver. The configurator program
doesn't enable MPU-401 when the full driver option is selected. It must be
enabled by uncommenting "#define EXCLUDE_MPU401" in the sound/local.h.
Important note!
The sound driver is enabled by default. If the kernel is booted without
using the sound=0 option, the sound driver is initialized using the compile
time parameters. This could be dangerous (specially if the MPU-401 driver
is enabled with I/O address 0x330 (used by AHA-1542 also)). If you want to
compile the driver to be inactive by default, you have to append a
#define SND_DEFAULT_ENABLE 0
to the sound/local.h before compiling the driver.
Remember to check that the sound setup routine is included in the
bootparams structure in linux/init/main.c. It should contain the following
lines:
#ifdef CONFIG_SOUND
{ "sound=", sound_setup },
#endif
In case these lines were not there, you have to insert them (the driver works
without them but it's not possible to give the boot time parameters for the
sound driver). Add also the following line somewhere near the beginning of
linux/init/main.c:
extern void sound_setup(char *str, int *ints);
Problems
--------
If you have any kind of problems, there is a debugging feature which
could help you to solve the problem. To use it, just execute the
command:
cat /dev/sndstat
and look at the output. It should display some usefull info about the
driver configuration. If there is no /dev/sndstat
(/dev/sndstat: No such file or directory), ensure that you have executed the
soundinstall script (at the end of this file). The message:
/dev/dsp: No such device means that you don't have the sound driver installed
on your kernel or the driver version is earlier than 1.99.6.
- /dev/???????: No such file or directory.
Run the script at the end of this file.
- /dev/???????: No such device.
You have not booted with a kernel containing the driver or the I/O address
configuration doesn't match your hardaware.
- The module player (str) plays just a second and then stops completely.
You have incorrect IRQ settings (usual with SB cards).
- There is pauses in the playback of the module player (str).
The str program requires more than 40% of the speed of a 486/50 to play
without pauses at 44 kHz speed. A 386/25 can hardly play faster than 22 kHz.
You should use lower speed (-s speed), buy a faster computer or a Gravis
UltraSound card. (If you already have GUS, you should use gmod and not the
str). If the DSP_BUFFSIZE in the sound/local.h is less than (nr_channels*
speed_in_Hz * (bits/8))/2, it could explain the pausing problem. Also check
that the turbo swich is on and don't run applications like weather forecasting
on background. Sometimes (very rarely) an IRQ conflict can cause similar
problems with SB cards.
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
----------------- cut here ------------------------------
#!/bin/sh
#
# soudinstall
#
# by Craig Metz - cmetz@thor.tjhsst.edu
#
# Create the devices
#
# Mixer (14, 0)
#
if [ -e /dev/mixer ]; then
rm -f /dev/mixer
fi
mknod -m 666 /dev/mixer c 14 0
#
# Sequencer (14, 1)
#
if [ -e /dev/sequencer ]; then
rm -f /dev/sequencer
fi
mknod -m 666 /dev/sequencer c 14 1
#
# MIDI (14, 2) [ Not implemented ]
#
if [ -e /dev/midi ]; then
rm -f /dev/midi
fi
mknod -m 666 /dev/midi c 14 2
#
# DSP (14, 3)
#
if [ -e /dev/dsp ]; then
rm -f /dev/dsp
fi
mknod -m 666 /dev/dsp c 14 3
#
# SPARC audio (14, 4) [ Not fully implemented ]
#
if [ -e /dev/audio ]; then
rm -f /dev/audio
fi
mknod -m 666 /dev/audio c 14 4
#
# DSP2 (14, 19) /dev/dsp for the second soundcard.
# Also the SB emulation part of the
# PAS16 card.
#
if [ -e /dev/dsp1 ]; then
rm -f /dev/dsp1
fi
mknod -m 666 /dev/dsp1 c 14 19
#
# SPARC audio1 (14, 20) [ Not fully implemented ]
# /dev/audio for the second soundcard.
# Also the SB emulation part of the
# PAS16 card.
#
if [ -e /dev/audio1 ]; then
rm -f /dev/audio1
fi
mknod -m 666 /dev/audio1 c 14 20
#
# /dev/sndstat (14,6) For debugging purposes
#
if [ -e /dev/sndstat ]; then
rm -f /dev/sndstat
fi
mknod -m 666 /dev/sndstat c 14 6
exit 0
/*
* linux/kernel/chr_drv/sound/adlib_card.c
* sound/adlib_card.c
*
* Detection routine for the AdLib card.
*
......
/*
* linux/kernel/chr_drv/sound/audio.c
* sound/audio.c
*
* Device file manager for /dev/audio
*
......
......@@ -65,6 +65,7 @@ typedef struct
char macro[20];
int verify;
int alias;
int default_answ;
}
hw_entry;
......@@ -87,23 +88,23 @@ hw_entry;
hw_entry hw_table[] =
{
/* 0 */
{0, 0, "PAS", 1, 0},
{0, 0, "SB", 1, 0},
{0, B (OPT_PAS) | B (OPT_SB), "ADLIB", 1, 0},
{0, 0, "PAS", 1, 0, 0},
{0, 0, "SB", 1, 0, 0},
{0, B (OPT_PAS) | B (OPT_SB), "ADLIB", 1, 0, 0},
/* 3 */
{0, 0, "GUS", 1, 0},
{0, 0, "MPU401", 1, 0},
{B (OPT_SB), B (OPT_PAS), "SBPRO", 1, 0},
{B (OPT_SB) | B (OPT_SBPRO), B (OPT_PAS), "SB16", 1, 0},
{B (OPT_SB) | B (OPT_PAS) | B (OPT_GUS), 0, "AUDIO", 1, 0},
{B (OPT_MPU401), 0, "MIDI_AUTO", 0, OPT_MIDI},
{B (OPT_SB) | B (OPT_PAS) | B (OPT_MPU401) | B (OPT_GUS), 0, "MIDI", 1, 0},
{B (OPT_ADLIB), 0, "YM3812_AUTO", 0, OPT_YM3812},
{B (OPT_SB) | B (OPT_PAS) | B (OPT_ADLIB), B (OPT_YM3812_AUTO), "YM3812", 1, 0},
{0, 0, "GUS", 1, 0, 0},
{0, 0, "MPU401", 1, 0, 0},
{B (OPT_SB), B (OPT_PAS), "SBPRO", 1, 0, 1},
{B (OPT_SB) | B (OPT_SBPRO), B (OPT_PAS), "SB16", 1, 0, 1},
{B (OPT_SB) | B (OPT_PAS) | B (OPT_GUS), 0, "AUDIO", 1, 0, 1},
{B (OPT_MPU401), 0, "MIDI_AUTO", 0, OPT_MIDI, 0},
{B (OPT_SB) | B (OPT_PAS) | B (OPT_MPU401) | B (OPT_GUS), 0, "MIDI", 1, 0, 1},
{B (OPT_ADLIB), 0, "YM3812_AUTO", 0, OPT_YM3812, 0},
{B (OPT_SB) | B (OPT_PAS) | B (OPT_ADLIB), B (OPT_YM3812_AUTO), "YM3812", 1, 0, 1},
/* 10 */
{B (OPT_MIDI) | B (OPT_YM3812) | B (OPT_YM3812_AUTO) | B (OPT_GUS), 0, "SEQUENCER", 0, 0},
{0, 0, "CHIP_MIDI", 1, 0}
{B (OPT_MIDI) | B (OPT_YM3812) | B (OPT_YM3812_AUTO) | B (OPT_GUS), 0, "SEQUENCER", 0, 0, 1},
{0, 0, "CHIP_MIDI", 1, 0, 0}
};
char *questions[] =
......@@ -112,20 +113,21 @@ char *questions[] =
"SoundBlaster support",
"AdLib support",
"Gravis Ultrasound support",
"MPU-401 support",
"MPU-401 support (NOT for SB16)",
"SoundBlaster Pro support (required for SB16 also)",
"SoundBlaster Pro support",
"SoundBlaster 16 support",
"digitized voice support",
"This should not be asked",
"MIDI interface support",
"This should not be asked",
"Internal synthesizer (FM/GUS) support",
"FM synthesizer (YM3812/OPL-3) support",
"/dev/sequencer support",
"MIDI on CHIP support"
};
unsigned long selected_options = 0;
int sb_dma = 0;
int
can_select_option (int nr)
......@@ -168,7 +170,7 @@ can_select_option (int nr)
}
int
think_positively (void)
think_positively (int def_answ)
{
char answ[512];
int len;
......@@ -184,7 +186,7 @@ think_positively (void)
}
if (len < 2) /* There is an additional LF at the end */
return 0;
return def_answ;
answ[len - 1] = 0;
......@@ -238,7 +240,7 @@ main (int argc, char *argv[])
fprintf (stderr, "Do you want to include full version of the sound driver (n/y) ? ");
if (think_positively ())
if (think_positively (0))
{
selected_options = 0xffffffff & ~B (OPT_MPU401);
fprintf (stderr, "Note! MPU-401 driver was not enabled\n");
......@@ -247,7 +249,7 @@ main (int argc, char *argv[])
else
{
fprintf (stderr, "Do you want to DISABLE the Sound Driver (n/y) ?");
if (think_positively ())
if (think_positively (0))
{
printf ("#undef CONFIGURE_SOUNDCARD\n");
printf ("#undef KERNEL_SOUNDCARD\n");
......@@ -270,8 +272,12 @@ main (int argc, char *argv[])
}
else
{
fprintf (stderr, " %s (n/y) ? ", questions[i]);
if (think_positively ())
int def_answ = hw_table[i].default_answ;
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);
else
......@@ -280,6 +286,9 @@ main (int argc, char *argv[])
}
}
if (selected_options & B(OPT_SB16))
selected_options |= B(OPT_SBPRO);
if (!(selected_options & ANY_DEVS))
{
printf ("#undef CONFIGURE_SOUNDCARD\n");
......@@ -306,7 +315,7 @@ main (int argc, char *argv[])
*/
printf ("\n");
#ifdef linux
#if defined(linux)
if (selected_options & B (OPT_SB) && selected_options & (B (OPT_AUDIO) | B (OPT_MIDI)))
{
fprintf (stderr, "\nIRQ number for SoundBlaster?\n"
......@@ -343,6 +352,7 @@ main (int argc, char *argv[])
}
fprintf (stderr, "SoundBlaster DMA set to %d\n", num);
printf ("#define SBC_DMA %d\n", num);
sb_dma = num;
}
if (selected_options & B (OPT_SB16))
......@@ -354,7 +364,7 @@ main (int argc, char *argv[])
"Enter the value: ");
num = ask_value ("%d", 6);
if (num < 5 || num > 7)
if ((num < 5 || num > 7) && (num != sb_dma))
{
fprintf (stderr, "*** Illegal input! ***\n");
......@@ -362,6 +372,15 @@ main (int argc, char *argv[])
}
fprintf (stderr, "SoundBlaster DMA set to %d\n", num);
printf ("#define SB16_DMA %d\n", num);
fprintf (stderr, "\nI/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);
}
}
......@@ -476,7 +495,7 @@ main (int argc, char *argv[])
printf ("#define MPU_BASE 0x%03x\n", num);
fprintf (stderr, "\nIRQ number for MPU-401?\n"
"Valid numbers are: 3, 4, 5, 7 and 9.\n"
"Valid numbers are: 3, 4, 5, 7 and 9(=2).\n"
"The default value is 5.\n"
"Enter the value: ");
......@@ -496,10 +515,14 @@ main (int argc, char *argv[])
{
def_size = 16384;
if (selected_options & (B (OPT_SBPRO) | B (OPT_PAS)))
if (selected_options & (B (OPT_SBPRO) | B (OPT_PAS) | B(OPT_SB16)))
def_size = 32768;
if ((selected_options & B (OPT_PAS)) && !full_driver)
def_size = 65536; /* PAS16 alone */
#ifndef __386BSD__
if (((selected_options & B (OPT_PAS)) || (selected_options & B (OPT_SB16))) &&
!full_driver)
def_size = 65536; /* PAS16 or SB16 */
#endif
fprintf (stderr, "\nSelect the DMA buffer size (4096, 16384, 32768 or 65536 bytes)\n"
"%d is recommended value for this configuration.\n"
......@@ -519,5 +542,9 @@ main (int argc, char *argv[])
printf ("#define SELECTED_SOUND_OPTIONS\t0x%08x\n", selected_options);
fprintf (stderr, "The sound driver is now configured.\n");
#if defined(SCO) || defined(ISC) || defined(SYSV)
fprintf(stderr, "Rember to update the System file\n");
#endif
exit (0);
}
/*
* linux/kernel/chr_drv/sound/dev_table.c
* sound/dev_table.c
*
* Device call tables.
*
......@@ -48,12 +48,14 @@ sndtable_init (long mem_start)
mem_start = supported_drivers[i].attach (mem_start, &supported_drivers[i].config);
#ifndef SHORT_BANNERS
printk (" at 0x%3x irq %d drq %d\n",
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 */
return mem_start;
}
......@@ -67,7 +69,14 @@ sndtable_probe (int unit, struct address_info *hw_config)
for (i = 0; i < (n - 1); i++)
if (supported_drivers[i].card_type == unit)
return supported_drivers[i].probe (hw_config);
{
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;
}
return FALSE;
}
......@@ -87,6 +96,10 @@ sndtable_init_card (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].attach (0, hw_config) != 0)
panic ("snd#: Invalid memory allocation\n");
return TRUE;
......@@ -101,12 +114,11 @@ sndtable_get_cardcount (void)
return num_dspdevs + num_mixers + num_synths + num_midis;
}
#ifdef linux
void sound_setup(char *str, int *ints)
{
int i, n = sizeof (supported_drivers) / sizeof (struct card_info);
printk("sound_setup(%d) called\n", ints[0]);
/*
* First disable all drivers
*/
......@@ -154,6 +166,27 @@ void sound_setup(char *str, int *ints)
}
}
}
#else
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;
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;
}
}
#endif
struct address_info *sound_getconf(int card_type)
{
......
......@@ -182,10 +182,16 @@ struct generic_midi_operations {
{SBC_BASE, SBC_IRQ, SBC_DMA}, SND_DEFAULT_ENABLE},
#endif
#if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16) && !defined(EXCLUDE_AUDIO)
#if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16)
#ifndef EXCLUDE_AUDIO
{SNDCARD_SB16, "SoundBlaster16", sb16_dsp_init, sb16_dsp_detect,
{SBC_BASE, SBC_IRQ, SB16_DMA}, SND_DEFAULT_ENABLE},
#endif
#ifndef EXCLUDE_MIDI
{SNDCARD_SB16MIDI,"SB16 MPU-401", attach_sb16midi, probe_sb16midi,
{SB16MIDI_BASE, SBC_IRQ, 0}, SND_DEFAULT_ENABLE},
#endif
#endif
#ifndef EXCLUDE_YM3812
{SNDCARD_ADLIB, "AdLib", attach_adlib_card, probe_adlib,
......@@ -229,6 +235,7 @@ long sndtable_init(long mem_start);
int sndtable_get_cardcount (void);
long CMIDI_init(long mem_start); /* */
struct address_info *sound_getconf(int card_type);
void sound_chconf(int card_type, int ioaddr, int irq, int dma);
#endif
#endif
......
/*
* linux/kernel/chr_drv/sound/dmabuf.c
* sound/dmabuf.c
*
* The DMA buffer manager for digitized voice applications
*
......@@ -103,8 +103,8 @@ reorganize_buffers (int dev)
* This routine breaks the physical device buffers to logical ones.
*/
unsigned long i, p, n;
unsigned long 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);
......@@ -112,8 +112,7 @@ reorganize_buffers (int dev)
if (sr < 1 || nc < 1 || sz < 1)
{
printk ("SOUND: Invalid PCM parameters[%d] sr=%lu, nc=%lu, sz=%lu\n",
dev, sr, nc, sz);
printk ("SOUND: Invalid PCM parameters[%d] sr=%d, nc=%d, sz=%d\n", dev, sr, nc, sz);
sr = DSP_DEFAULT_SPEED;
nc = 1;
sz = 8;
......@@ -210,6 +209,10 @@ DMAbuf_open (int dev, int mode)
return RET_ERROR (ENXIO);
}
#ifdef USE_RUNTIME_DMAMEM
sound_dma_malloc(dev);
#endif
if (snd_raw_buf[dev][0] == NULL)
return RET_ERROR (ENOSPC); /* Memory allocation failed during boot */
......@@ -300,6 +303,10 @@ DMAbuf_release (int dev, int mode)
dma_sync (dev);
}
#ifdef USE_RUNTIME_DMAMEM
sound_dma_free(dev);
#endif
dsp_devs[dev]->reset (dev);
dsp_devs[dev]->close (dev);
......@@ -342,6 +349,7 @@ DMAbuf_getrdbuffer (int dev, char **buf, int *len)
if (dev_needs_restart[dev])
{
dma_reset(dev);
dev_needs_restart[dev] = 0;
}
if (!dev_active[dev])
......@@ -606,9 +614,11 @@ DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
chan);
#else
#if defined(ISC) || defined(SCO)
#ifndef DMAMODE_AUTO
printk ("sound: Invalid DMA mode for device %d\n", dev);
#endif
dma_param (chan, ((dma_mode == DMA_MODE_READ) ? DMA_Rdmode : DMA_Wrmode)
#ifdef ISC
#ifdef DMAMODE_AUTO
| DMAMODE_AUTO
#endif
,
......@@ -703,7 +713,7 @@ DMAbuf_outputintr (int dev, int underrun_flag)
}
DISABLE_INTR (flags);
if (SOMEONE_WAITING (dev_sleep_flag[dev]))
if (SOMEONE_WAITING (dev_sleeper[dev], dev_sleep_flag[dev]))
{
WAKE_UP (dev_sleeper[dev], dev_sleep_flag[dev]);
}
......@@ -721,6 +731,7 @@ DMAbuf_inputintr (int dev)
}
else if (dev_qlen[dev] == (dev_nbufs[dev] - 1))
{
printk("Sound: Recording overrun\n");
dev_underrun[dev]++;
dsp_devs[dev]->halt_xfer (dev);
dev_active[dev] = 0;
......@@ -738,7 +749,7 @@ DMAbuf_inputintr (int dev)
}
DISABLE_INTR (flags);
if (SOMEONE_WAITING (dev_sleep_flag[dev]))
if (SOMEONE_WAITING (dev_sleeper[dev], dev_sleep_flag[dev]))
{
WAKE_UP (dev_sleeper[dev], dev_sleep_flag[dev]);
}
......
/*
* linux/kernel/chr_drv/sound/gus_card.c
* sound/gus_card.c
*
* Detection routine for the Gravis Ultrasound.
*
......@@ -63,7 +63,7 @@ attach_gus_card (long mem_start, struct address_info *hw_config)
if (io_addr != hw_config->io_base) /* Already tested */
if (gus_wave_detect (io_addr))
{
printk (" WARNING! GUS found at %03x, config was %03x ", io_addr, hw_config->io_base);
printk (" WARNING! GUS found at %x, config was %x ", io_addr, hw_config->io_base);
mem_start = gus_wave_init (mem_start, hw_config->irq, hw_config->dma);
#ifndef EXCLUDE_MIDI
mem_start = gus_midi_init (mem_start);
......
/*
* linux/kernel/chr_drv/sound/gus2_midi.c
* sound/gus2_midi.c
*
* The low level driver for the GUS Midi Interface.
*
......
/*
* linux/kernel/chr_drv/sound/gus_wave.c
* sound/gus_wave.c
*
* Driver for the Gravis UltraSound wave table synth.
*
......@@ -36,7 +35,7 @@
#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_GUS)
#define MAX_SAMPLE 256
#define MAX_SAMPLE 128
#define MAX_PATCH 256
struct voice_info
......@@ -144,7 +143,7 @@ static int freq_div_table[] =
19293 /* 32 */
};
static struct patch_info samples[MAX_SAMPLE + 1];
static struct patch_info *samples;
static long sample_ptrs[MAX_SAMPLE + 1];
static int sample_map[32];
static int free_sample;
......@@ -231,14 +230,14 @@ gus_peek (long addr)
}
void
gus_write8 (int reg, unsigned char data)
gus_write8 (int reg, unsigned int data)
{
unsigned long flags;
DISABLE_INTR (flags);
OUTB (reg, u_Command);
OUTB (data, u_DataHi);
OUTB ((unsigned char)(data & 0xff), u_DataHi);
RESTORE_INTR (flags);
}
......@@ -272,7 +271,7 @@ gus_look8 (int reg)
}
void
gus_write16 (int reg, unsigned short data)
gus_write16 (int reg, unsigned int data)
{
unsigned long flags;
......@@ -280,8 +279,8 @@ gus_write16 (int reg, unsigned short data)
OUTB (reg, u_Command);
OUTB (data & 0xff, u_DataLo);
OUTB ((data >> 8) & 0xff, u_DataHi);
OUTB ((unsigned char)(data & 0xff), u_DataLo);
OUTB ((unsigned char)((data >> 8) & 0xff), u_DataHi);
RESTORE_INTR (flags);
}
......@@ -348,11 +347,11 @@ gus_select_max_voices (int nvoices)
}
static void
gus_voice_on (unsigned char mode)
gus_voice_on (unsigned int mode)
{
gus_write8 (0x00, mode & 0xfc);
gus_write8 (0x00, (unsigned char)(mode & 0xfc));
gus_delay ();
gus_write8 (0x00, mode & 0xfc);
gus_write8 (0x00, (unsigned char)(mode & 0xfc));
}
static void
......@@ -362,8 +361,9 @@ gus_voice_off (void)
}
static void
gus_voice_mode (unsigned char mode)
gus_voice_mode (unsigned int m)
{
unsigned char mode = (unsigned char)(m & 0xff);
gus_write8 (0x00, (gus_read8 (0x00) & 0x03) | (mode & 0xfc)); /* Don't start or stop
* voice */
gus_delay ();
......@@ -383,42 +383,46 @@ gus_voice_freq (unsigned long freq)
}
static void
gus_voice_volume (unsigned short vol)
gus_voice_volume (unsigned int vol)
{
gus_write8 (0x0d, 0x03); /* Stop ramp before setting volume */
gus_write16 (0x09, vol << 4);
gus_write16 (0x09, (unsigned short)(vol << 4));
}
static void
gus_voice_balance (unsigned char balance)
gus_voice_balance (unsigned int balance)
{
gus_write8 (0x0c, balance);
gus_write8 (0x0c, (unsigned char)(balance & 0xff));
}
static void
gus_ramp_range (unsigned short low, unsigned short high)
gus_ramp_range (unsigned int low, unsigned int high)
{
gus_write8 (0x07, (low >> 4) & 0xff);
gus_write8 (0x08, (high >> 4) & 0xff);
gus_write8 (0x07, (unsigned char)((low >> 4) & 0xff));
gus_write8 (0x08, (unsigned char)((high >> 4) & 0xff));
}
static void
gus_ramp_rate (unsigned char scale, unsigned char rate)
gus_ramp_rate (unsigned int scale, unsigned int rate)
{
gus_write8 (0x06, ((scale & 0x03) << 6) | (rate & 0x3f));
gus_write8 (0x06, (unsigned char)(((scale & 0x03) << 6) | (rate & 0x3f)));
}
static void
gus_rampon (unsigned char mode)
gus_rampon (unsigned int m)
{
unsigned char mode = (unsigned char)(m & 0xff);
gus_write8 (0x0d, mode & 0xfc);
gus_delay ();
gus_write8 (0x0d, mode & 0xfc);
}
static void
gus_ramp_mode (unsigned char mode)
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 stop
* ramping */
gus_delay ();
......@@ -911,6 +915,14 @@ static void
compute_and_set_volume (int voice, int volume, int ramp_time)
{
int current, target, rate;
unsigned long flags;
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;
......@@ -922,6 +934,7 @@ compute_and_set_volume (int voice, int volume, int ramp_time)
{
gus_rampoff ();
gus_voice_volume (target);
RESTORE_INTR(flags);
return;
}
......@@ -935,6 +948,7 @@ compute_and_set_volume (int voice, int volume, int ramp_time)
{
gus_rampoff ();
gus_voice_volume (target);
RESTORE_INTR(flags);
return;
}
......@@ -953,6 +967,7 @@ compute_and_set_volume (int voice, int volume, int ramp_time)
gus_ramp_range (target, current);
gus_rampon (0x40); /* Ramp down, once, no irq */
}
RESTORE_INTR(flags);
}
static void
......@@ -1274,7 +1289,7 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
if (format != GUS_PATCH)
{
printk ("GUS Error: Invalid patch format (key) 0x%04x\n", format);
printk ("GUS Error: Invalid patch format (key) 0x%x\n", format);
return RET_ERROR (EINVAL);
}
......@@ -1309,14 +1324,14 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
if (count < patch.len)
{
printk ("GUS Warning: Patch record too short (%d<%lu)\n",
count, patch.len);
printk ("GUS Warning: Patch record too short (%d<%d)\n",
count, (int)patch.len);
patch.len = count;
}
if (patch.len <= 0 || patch.len > gus_mem_size)
{
printk ("GUS: Invalid sample length %lu\n", patch.len);
printk ("GUS: Invalid sample length %d\n", (int)patch.len);
return RET_ERROR (EINVAL);
}
......@@ -1346,7 +1361,7 @@ guswave_load_patch (int dev, int format, snd_rw_buf * addr,
*/
if (patch.len >= GUS_BANK_SIZE)
{
printk ("GUS: Sample (16 bit) too long %lu\n", patch.len);
printk ("GUS: Sample (16 bit) too long %d\n", (int)patch.len);
return RET_ERROR (ENOSPC);
}
......@@ -2317,7 +2332,7 @@ static struct synth_operations guswave_operations =
long
gus_wave_init (long mem_start, int irq, int dma)
{
printk (" <Gravis UltraSound %luk>", gus_mem_size / 1024);
printk (" <Gravis UltraSound %dk>", (int)gus_mem_size / 1024);
if (irq < 0 || irq > 15)
{
......@@ -2339,6 +2354,9 @@ gus_wave_init (long mem_start, int irq, int dma)
else
synth_devs[num_synths++] = &guswave_operations;
PERMANENT_MALLOC(struct patch_info*, samples,
(MAX_SAMPLE+1)*sizeof(*samples), mem_start);
reset_sample_memory ();
gus_initialize ();
......@@ -2505,7 +2523,7 @@ guswave_dma_irq (void)
switch (active_device)
{
case GUS_DEV_WAVE:
if (SOMEONE_WAITING (dram_sleep_flag))
if (SOMEONE_WAITING (dram_sleeper, dram_sleep_flag))
WAKE_UP (dram_sleeper, dram_sleep_flag);
break;
......
/*
* linux/kernel/chr_drv/sound/midibuf.c
* sound/midibuf.c
*
* Device file manager for /dev/midi
*
......
/*
* linux/kernel/chr_drv/sound/mpu401.c
* sound/mpu401.c
*
* The low level driver for Roland MPU-401 compatible Midi cards.
*
......
/*
* linux/kernel/chr_drv/sound/opl3.c
* sound/opl3.c
*
* A low level driver for Yamaha YM3812 and OPL-3 -chips
*
......@@ -59,8 +59,7 @@ struct voice_info
static struct voice_info voices[MAX_VOICE];
typedef struct sbi_instrument instr_array[SBFM_MAXINSTR];
static instr_array instrmap;
static struct sbi_instrument *instrmap;
static struct sbi_instrument *active_instrument[MAX_VOICE] =
{NULL};
......@@ -75,7 +74,7 @@ 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);
static void opl3_command (int io_addr, const unsigned char addr, const unsigned char val);
static void opl3_command (int io_addr, unsigned int addr, unsigned int val);
static int opl3_kill_note (int dev, int voice, int velocity);
static unsigned char connection_mask = 0x00;
......@@ -273,7 +272,7 @@ store_instr (int instr_no, struct sbi_instrument *instr)
{
if (instr->key != FM_PATCH && (instr->key != OPL3_PATCH || !opl3_enabled))
printk ("FM warning: Invalid patch format field (key) 0x%04x\n", instr->key);
printk ("FM warning: Invalid patch format field (key) 0x%x\n", instr->key);
memcpy ((char *) &(instrmap[instr_no]), (char *) instr, sizeof (*instr));
return 0;
......@@ -619,7 +618,7 @@ freq_to_fnum (int freq, int *block, int *fnum)
}
static void
opl3_command (int io_addr, const unsigned char addr, const unsigned char val)
opl3_command (int io_addr, unsigned int addr, unsigned int val)
{
int i;
......@@ -628,7 +627,7 @@ opl3_command (int io_addr, const unsigned char addr, const unsigned char val)
* register. The OPL-3 survives with just two INBs
*/
OUTB (addr, io_addr); /* Select register */
OUTB ((unsigned char)(addr & 0xff), io_addr); /* Select register */
if (!opl3_enabled)
tenmicrosec ();
......@@ -636,7 +635,7 @@ opl3_command (int io_addr, const unsigned char addr, const unsigned char val)
for (i = 0; i < 2; i++)
INB (io_addr);
OUTB (val, io_addr + 1); /* Write to register */
OUTB ((unsigned char)(val & 0xff), io_addr + 1); /* Write to register */
if (!opl3_enabled)
{
......@@ -895,6 +894,9 @@ opl3_init (long mem_start)
{
int i;
PERMANENT_MALLOC(struct sbi_instrument*, instrmap,
SBFM_MAXINSTR*sizeof(*instrmap), mem_start);
synth_devs[num_synths++] = &opl3_operations;
fm_model = 0;
opl3_ok = 1;
......
......@@ -41,7 +41,7 @@
#include <asm/segment.h>
#include <asm/system.h>
#include <asm/dma.h>
#include <linux/kd.h>
#include <sys/kd.h>
#include <linux/wait.h>
#include <linux/malloc.h>
#include <linux/soundcard.h>
......@@ -63,15 +63,6 @@ typedef char snd_rw_buf;
#define IOCTL_IN(arg) get_fs_long((long *)(arg))
#define IOCTL_OUT(arg, ret) snd_ioctl_return((int *)arg, ret)
/*
#define DEFINE_WAIT_QUEUE(name, flag) static struct wait_queue *name = NULL; static int flag = 0
#define DEFINE_WAIT_QUEUES(name, flag) static struct wait_queue *name = {NULL}; static int flag = {0}
#define PROCESS_ABORTING(wqueue, flags) (current->signal & ~current->blocked)
#define REQUEST_TIMEOUT(nticks, wqueue) current->timeout = jiffies + (nticks);
#define INTERRUPTIBLE_SLEEP_ON(q, f) \
{f = 1;interruptible_sleep_on(&q);f=0;}
*/
struct snd_wait {
int mode; int aborting;
};
......@@ -98,7 +89,7 @@ struct snd_wait {
} \
f.mode &= ~WK_SLEEP; \
}
#define SOMEONE_WAITING(f) (f.mode & WK_SLEEP)
#define SOMEONE_WAITING(q, f) (f.mode & WK_SLEEP)
#define WAKE_UP(q, f) {f.mode = WK_WAKEUP;wake_up(&q);}
#define ALLOC_DMA_CHN(chn) request_dma(chn)
......@@ -128,6 +119,19 @@ struct snd_wait {
#define KERNEL_MALLOC(nbytes) kmalloc(nbytes, GFP_KERNEL)
#define KERNEL_FREE(addr) kfree(addr)
/*
* The macro PERMANENT_MALLOC(typecast, mem_ptr, size, linux_ptr)
* returns size bytes of
* (kernel virtual) memory which will never get freed by the driver.
* This macro is called only during boot. The linux_ptr is a linux specific
* parameter which should be ignored in other operating systems.
* The mem_ptr is a pointer variable where the macro assigns pointer to the
* memory area. The type is the type of the mem_ptr.
*/
#define PERMANENT_MALLOC(typecast, mem_ptr, size, linux_ptr) \
{mem_ptr = (typecast)linux_ptr; \
linux_ptr += (size);}
/*
* The macro DEFINE_TIMER defines variables for the ACTIVATE_TIMER if
* required. The name is the variable/name to be used and the proc is
......
......@@ -132,6 +132,7 @@
#define PAS_PLUS 1
#define PAS_CDPC 2
#define PAS_16 3
#define PAS_16D 4
#ifdef DEFINE_TRANSLATIONS
char I_C_2_PCM_DMA_translate[] = /* R W PCM PCM DMA channel value translations */
......
#define _PAS2_CARD_C_
#define SND_SA_INTERRUPT
/*
* linux/kernel/chr_drv/sound/pas2_card.c
* sound/pas2_card.c
*
* Detection routine for the Pro Audio Spectrum cards.
*
......@@ -218,7 +218,7 @@ config_pas_hw (struct address_info *hw_config)
* selects filter rate
* of 17.897 kHz */
if (pas_model == PAS_16)
if (pas_model == PAS_16 || pas_model == PAS_16D)
pas_write (8, PRESCALE_DIVIDER);
else
pas_write (0, PRESCALE_DIVIDER);
......
/*
* linux/kernel/chr_drv/sound/pas2_midi.c
* sound/pas2_midi.c
*
* The low level driver for the PAS Midi Interface.
*
......@@ -283,7 +283,7 @@ pas_midi_interrupt (void)
if (stat & M_S_OUTPUT_OVERRUN)
{
printk ("MIDI output overrun %02x,%02x,%d \n", pas_read (MIDI_FIFO_STATUS), stat, ofifo_bytes);
printk ("MIDI output overrun %x,%x,%d \n", pas_read (MIDI_FIFO_STATUS), stat, ofifo_bytes);
ofifo_bytes = 100;
}
......
#define _PAS2_MIXER_C_
/*
* linux/kernel/chr_drv/sound/pas2_mixer.c
* sound/pas2_mixer.c
*
* Mixer routines for the Pro Audio Spectrum cards.
*
......
#define _PAS2_PCM_C_
/*
* linux/kernel/chr_drv/sound/pas2_pcm.c
* sound/pas2_pcm.c
*
* The low level driver for the Pro Audio Spectrum ADC/DAC.
*
......@@ -148,6 +148,8 @@ pas_pcm_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
break;
case SOUND_PCM_WRITE_CHANNELS:
if (local)
return pcm_set_channels (arg);
return IOCTL_OUT (arg, pcm_set_channels (IOCTL_IN (arg)));
break;
......
/*
* linux/kernel/chr_drv/sound/patmgr.c
* sound/patmgr.c
*
* The patch maneger interface for the /dev/sequencer
*
......@@ -73,7 +73,7 @@ pmgr_release (int dev)
mbox[dev]->key = PM_ERROR;
mbox[dev]->parm1 = RET_ERROR (EIO);
if (SOMEONE_WAITING (appl_wait_flag))
if (SOMEONE_WAITING (appl_proc, appl_wait_flag))
WAKE_UP (appl_proc, appl_wait_flag);
}
......@@ -161,7 +161,7 @@ pmgr_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
COPY_FROM_USER (&((char *) mbox[dev])[4], buf, 4, count - 4);
msg_direction[dev] = S_TO_A;
if (SOMEONE_WAITING (appl_wait_flag))
if (SOMEONE_WAITING (appl_proc, appl_wait_flag))
{
WAKE_UP (appl_proc, appl_wait_flag);
}
......@@ -188,7 +188,7 @@ pmgr_access (int dev, struct patmgr_info *rec)
mbox[dev] = rec;
msg_direction[dev] = A_TO_S;
if (SOMEONE_WAITING (server_wait_flag[dev]))
if (SOMEONE_WAITING (server_procs[dev], server_wait_flag[dev]))
{
WAKE_UP (server_procs[dev], server_wait_flag[dev]);
}
......@@ -242,7 +242,7 @@ pmgr_inform (int dev, int event, unsigned long p1, unsigned long p2,
mbox[dev]->parm3 = p3;
msg_direction[dev] = A_TO_S;
if (SOMEONE_WAITING (server_wait_flag[dev]))
if (SOMEONE_WAITING (server_procs[dev], server_wait_flag[dev]))
{
WAKE_UP (server_procs[dev], server_wait_flag[dev]);
}
......
This diff is collapsed.
/*
* 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
* 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"
#ifdef CONFIGURE_SOUNDCARD
#if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16) && !defined(EXCLUDE_MIDI)
#define DATAPORT (sb16midi_base) /* MPU-401 Data I/O Port on IBM */
#define COMDPORT (sb16midi_base+1) /* MPU-401 Command Port on IBM */
#define STATPORT (sb16midi_base+1) /* MPU-401 Status Port on IBM */
#define sb16midi_status() INB(STATPORT)
#define input_avail() (!(sb16midi_status()&INPUT_AVAIL))
#define output_ready() (!(sb16midi_status()&OUTPUT_READY))
#define sb16midi_cmd(cmd) OUTB(cmd, COMDPORT)
#define sb16midi_read() INB(DATAPORT)
#define sb16midi_write(byte) OUTB(byte, DATAPORT)
#define OUTPUT_READY 0x40 /* Mask for Data Read Redy Bit */
#define INPUT_AVAIL 0x80 /* Mask for Data Send Ready Bit */
#define MPU_ACK 0xFE /* MPU-401 Acknowledge Response */
#define MPU_RESET 0xFF /* MPU-401 Total Reset Command */
#define UART_MODE_ON 0x3F /* MPU-401 "Dumb UART Mode" */
static int sb16midi_opened = 0;
static int sb16midi_base = 0x330;
static int sb16midi_detected = 0;
static int my_dev;
static int reset_sb16midi (void);
static void (*midi_input_intr) (int dev, unsigned char data);
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;
if (sb16midi_opened & OPEN_READ)
midi_input_intr (my_dev, c);
}
else
while (!input_avail () && count)
count--;
}
void
sb16midiintr (int unit)
{
if (input_avail ())
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)
)
{
if (sb16midi_opened)
{
return RET_ERROR (EBUSY);
}
sb16midi_input_loop ();
midi_input_intr = input;
sb16midi_opened = mode;
poll_sb16midi (0); /* Enable input polling */
return 0;
}
static void
sb16midi_close (int dev)
{
sb16midi_opened = 0;
}
static int
sb16midi_out (int dev, unsigned char midi_byte)
{
int timeout;
unsigned long flags;
/*
* Test for input since pending input seems to block the output.
*/
DISABLE_INTR (flags);
if (input_avail ())
sb16midi_input_loop ();
RESTORE_INTR (flags);
/*
* Sometimes it takes about 13000 loops before the output becomes ready
* (After reset). Normally it takes just about 10 loops.
*/
for (timeout = 30000; timeout > 0 && !output_ready (); timeout--); /* Wait */
if (!output_ready ())
{
printk ("MPU-401: Timeout\n");
return 0;
}
sb16midi_write (midi_byte);
return 1;
}
static int
sb16midi_command (int dev, unsigned char midi_byte)
{
return 1;
}
static int
sb16midi_start_read (int dev)
{
return 0;
}
static int
sb16midi_end_read (int dev)
{
return 0;
}
static int
sb16midi_ioctl (int dev, unsigned cmd, unsigned arg)
{
return RET_ERROR (EINVAL);
}
static void
sb16midi_kick (int dev)
{
}
static int
sb16midi_buffer_status (int dev)
{
return 0; /* No data in buffers */
}
static struct midi_operations sb16midi_operations =
{
{"SoundBlaster MPU-401", 0, 0, SNDCARD_SB16MIDI},
sb16midi_open,
sb16midi_close,
sb16midi_ioctl,
sb16midi_out,
sb16midi_start_read,
sb16midi_end_read,
sb16midi_kick,
sb16midi_command,
sb16midi_buffer_status
};
long
attach_sb16midi (long mem_start, struct address_info *hw_config)
{
int ok, timeout;
unsigned long flags;
sb16midi_base = hw_config->io_base;
if (!sb16midi_detected)
return RET_ERROR (EIO);
DISABLE_INTR (flags);
for (timeout = 30000; timeout < 0 && !output_ready (); timeout--); /* Wait */
sb16midi_cmd (UART_MODE_ON);
ok = 0;
for (timeout = 50000; timeout > 0 && !ok; timeout--)
if (input_avail ())
if (sb16midi_read () == MPU_ACK)
ok = 1;
RESTORE_INTR (flags);
printk (" <SoundBlaster MPU-401>");
my_dev = num_midis;
midi_devs[num_midis++] = &sb16midi_operations;
return mem_start;
}
static int
reset_sb16midi (void)
{
unsigned long flags;
int ok, timeout, n;
/*
* Send the RESET command. Try again if no success at the first time.
*/
ok = 0;
DISABLE_INTR (flags);
for (n = 0; n < 2 && !ok; n++)
{
for (timeout = 30000; timeout < 0 && !output_ready (); timeout--); /* Wait */
sb16midi_cmd (MPU_RESET); /* Send MPU-401 RESET Command */
/*
* Wait at least 25 msec. This method is not accurate so let's make the
* loop bit longer. Cannot sleep since this is called during boot.
*/
for (timeout = 50000; timeout > 0 && !ok; timeout--)
if (input_avail ())
if (sb16midi_read () == MPU_ACK)
ok = 1;
}
sb16midi_opened = 0;
if (ok)
sb16midi_input_loop (); /* Flush input before enabling interrupts */
RESTORE_INTR (flags);
return ok;
}
int
probe_sb16midi (struct address_info *hw_config)
{
int ok = 0;
sb16midi_base = hw_config->io_base;
if (sb_get_irq () < 0)
return 0;
ok = reset_sb16midi ();
sb16midi_detected = ok;
return ok;
}
#endif
#endif
/*
* linux/kernel/chr_drv/sound/sb_card.c
* sound/sb_card.c
*
* Detection routine for the SoundBlaster cards.
*
......
/*
* sound/sb_dsp.c
*
* The low level driver for the SoundBlaster DS chips.
* The low level driver for the SoundBlaster DSP chip.
*
* Copyright by Hannu Savolainen 1993
*
......@@ -101,7 +101,7 @@ sb_dsp_command (unsigned char val)
}
}
printk ("SoundBlaster: DSP Command(%02x) Timeout.\n", val);
printk ("SoundBlaster: DSP Command(%x) Timeout.\n", val);
printk ("IRQ conflict???\n");
return 0;
}
......@@ -114,11 +114,15 @@ sbintr (int unit)
#ifndef EXCLUDE_SBPRO
if (sb16)
{
unsigned char src = sb_getmixer (IRQ_STAT); /* Interrupt status register */
unsigned char src = sb_getmixer (IRQ_STAT); /* Interrupt source register */
#ifndef EXCLUDE_SB16
if (src & 2) sb16_dsp_interrupt(unit);
if (src & 3) sb16_dsp_interrupt(unit);
#ifndef EXCLUDE_MIDI
if (src & 4) sb16midiintr (unit); /* MPU401 interrupt */
#endif
#endif
if (!(src & 1))
......@@ -150,7 +154,7 @@ sbintr (int unit)
case IMODE_MIDI:
printk ("+");
data = INB (DSP_READ);
printk ("%02x", data);
printk ("%x", data);
break;
......@@ -332,8 +336,8 @@ sb_dsp_output_block (int dev, unsigned long buf, int count,
DISABLE_INTR (flags);
if (sb_dsp_command (0x48)) /* High speed size */
{
sb_dsp_command (count & 0xff);
sb_dsp_command ((count >> 8) & 0xff);
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
......@@ -345,8 +349,8 @@ sb_dsp_output_block (int dev, unsigned long buf, int count,
DISABLE_INTR (flags);
if (sb_dsp_command (0x14)) /* 8-bit DAC (DMA) */
{
sb_dsp_command (count & 0xff);
sb_dsp_command ((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");
......@@ -378,8 +382,8 @@ sb_dsp_start_input (int dev, unsigned long buf, int count, int intrflag,
DISABLE_INTR (flags);
if (sb_dsp_command (0x48)) /* High speed size */
{
sb_dsp_command (count & 0xff);
sb_dsp_command ((count >> 8) & 0xff);
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
......@@ -391,8 +395,8 @@ sb_dsp_start_input (int dev, unsigned long buf, int count, int intrflag,
DISABLE_INTR (flags);
if (sb_dsp_command (0x24)) /* 8-bit ADC (DMA) */
{
sb_dsp_command (count & 0xff);
sb_dsp_command ((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");
......@@ -557,6 +561,8 @@ sb_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
break;
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);
break;
......@@ -699,6 +705,9 @@ sb_dsp_init (long mem_start, struct address_info *hw_config)
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;
......@@ -712,8 +721,8 @@ sb_dsp_init (long mem_start, struct address_info *hw_config)
#endif
#ifndef EXCLUDE_MIDI
if (!midi_disabled) /* Midi don't work in the SB emulation mode
* of PAS */
if (!midi_disabled && !sb16) /* Midi don't work in the SB emulation mode
* of PAS, SB16 has better midi interface */
sb_midi_init(major);
#endif
......
......@@ -49,26 +49,26 @@ static int mixer_caps;
static mixer_tab *iomap;
void
sb_setmixer (unsigned char port, unsigned char value)
sb_setmixer (unsigned int port, unsigned int value)
{
unsigned long flags;
DISABLE_INTR(flags);
OUTB (port, MIXER_ADDR); /* Select register */
OUTB ((unsigned char)(port & 0xff), MIXER_ADDR); /* Select register */
tenmicrosec ();
OUTB (value, MIXER_DATA);
OUTB ((unsigned char)(value & 0xff), MIXER_DATA);
tenmicrosec ();
RESTORE_INTR(flags);
}
int
sb_getmixer (unsigned char port)
sb_getmixer (unsigned int port)
{
int val;
unsigned long flags;
DISABLE_INTR(flags);
OUTB (port, MIXER_ADDR); /* Select register */
OUTB ((unsigned char)(port & 0xff), MIXER_ADDR); /* Select register */
tenmicrosec ();
val = INB (MIXER_DATA);
tenmicrosec ();
......@@ -184,7 +184,7 @@ static int
set_recmask(int mask)
{
int devmask, i;
unsigned char regimage;
unsigned char regimageL, regimageR;
devmask = mask & supported_rec_devices;
......@@ -236,12 +236,15 @@ set_recmask(int mask)
case 4:
if (!devmask) devmask = SOUND_MASK_MIC;
regimage = 0;
regimageL = regimageR = 0;
for (i=0;i<SOUND_MIXER_NRDEVICES;i++)
if ((1<<i) & devmask)
regimage |= sb16_recmasks[i];
sb_setmixer(SB16_IMASK_L, regimage);
sb_setmixer(SB16_IMASK_R, regimage);
{
regimageL |= sb16_recmasks_L[i];
regimageR |= sb16_recmasks_R[i];
}
sb_setmixer(SB16_IMASK_L, regimageL);
sb_setmixer(SB16_IMASK_R, regimageR);
break;
}
......@@ -277,7 +280,8 @@ sb_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
break;
case SOUND_MIXER_STEREODEVS:
return IOCTL_OUT (arg, supported_devices & ~SOUND_MASK_MIC);
return IOCTL_OUT (arg, supported_devices &
~(SOUND_MASK_MIC|SOUND_MASK_SPEAKER));
break;
case SOUND_MIXER_RECMASK:
......
......@@ -31,7 +31,7 @@
#define SBPRO_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | \
SOUND_MASK_CD | SOUND_MASK_VOLUME)
#define SB16_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
#define SB16_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \
SOUND_MASK_CD)
#define SB16_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
......@@ -80,7 +80,6 @@
#define RIGHT_CHN 1
struct mixer_def {
char name[20];
unsigned int regno: 8;
unsigned int bitoffs:4;
unsigned int nbits:4;
......@@ -91,7 +90,7 @@ typedef struct mixer_def mixer_tab[32][2];
typedef struct mixer_def mixer_ent;
#define MIX_ENT(name, reg_l, bit_l, len_l, reg_r, bit_r, len_r) \
{{#name,reg_l, bit_l, len_l}, {" ", reg_r, bit_r, len_r}}
{{reg_l, bit_l, len_l}, {reg_r, bit_r, len_r}}
#ifdef __SB_MIXER_C__
mixer_tab sbpro_mix = {
......@@ -126,30 +125,46 @@ MIX_ENT(SOUND_MIXER_RECLEV, 0x3f, 7, 2, 0x40, 7, 2)
static unsigned short levels[SOUND_MIXER_NRDEVICES] =
{
0x4b4b, /* Master Volume */
0x5a5a, /* Master Volume */
0x3232, /* Bass */
0x3232, /* Treble */
0x4b4b, /* FM */
0x4b4b, /* PCM */
0x4b4b, /* PC Speaker */
0x4b4b, /* Ext Line */
0x3232, /* Mic */
0x0000, /* Mic */
0x4b4b, /* CD */
0x4b4b, /* Recording monitor */
0x4b4b, /* SB PCM */
0x4b4b}; /* Recording level */
static unsigned char sb16_recmasks[SOUND_MIXER_NRDEVICES] =
static unsigned char sb16_recmasks_L[SOUND_MIXER_NRDEVICES] =
{
0x00, /* SOUND_MIXER_VOLUME */
0x00, /* SOUND_MIXER_BASS */
0x00, /* SOUND_MIXER_TREBLE */
0x60, /* SOUND_MIXER_SYNTH */
0x40, /* SOUND_MIXER_SYNTH */
0x00, /* SOUND_MIXER_PCM */
0x00, /* SOUND_MIXER_SPEAKER */
0x18, /* SOUND_MIXER_LINE */
0x10, /* SOUND_MIXER_LINE */
0x01, /* SOUND_MIXER_MIC */
0x06, /* SOUND_MIXER_CD */
0x04, /* SOUND_MIXER_CD */
0x00, /* SOUND_MIXER_IMIX */
0x00, /* SOUND_MIXER_ALTPCM */
0x00 /* SOUND_MIXER_RECLEV */
};
static unsigned char sb16_recmasks_R[SOUND_MIXER_NRDEVICES] =
{
0x00, /* SOUND_MIXER_VOLUME */
0x00, /* SOUND_MIXER_BASS */
0x00, /* SOUND_MIXER_TREBLE */
0x20, /* SOUND_MIXER_SYNTH */
0x00, /* SOUND_MIXER_PCM */
0x00, /* SOUND_MIXER_SPEAKER */
0x08, /* SOUND_MIXER_LINE */
0x01, /* SOUND_MIXER_MIC */
0x02, /* SOUND_MIXER_CD */
0x00, /* SOUND_MIXER_IMIX */
0x00, /* SOUND_MIXER_ALTPCM */
0x00 /* SOUND_MIXER_RECLEV */
......
/*
* linux/kernel/chr_drv/sound/sequencer.c
* sound/sequencer.c
*
* The sequencer personality manager.
*
......@@ -51,8 +51,10 @@ long seq_time = 0; /* Reference point for the timer */
#include "tuning.h"
#define EV_SZ 8
static unsigned char queue[SEQ_MAX_QUEUE][EV_SZ];
static unsigned char iqueue[SEQ_MAX_QUEUE][4];
#define IEV_SZ 4
static unsigned char *queue = NULL; /* SEQ_MAX_QUEUE * EV_SZ bytes */
static unsigned char *iqueue = NULL; /* SEQ_MAX_QUEUE * IEV_SZ bytes */
static volatile int qhead = 0, qtail = 0, qlen = 0;
static volatile int iqhead = 0, iqtail = 0, iqlen = 0;
static volatile int seq_playing = 0;
......@@ -91,7 +93,7 @@ sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
return count - c;
}
COPY_TO_USER (buf, p, &iqueue[iqhead][0], 4);
COPY_TO_USER (buf, p, &iqueue[iqhead * IEV_SZ], IEV_SZ);
p += 4;
c -= 4;
......@@ -116,12 +118,12 @@ copy_to_input (unsigned char *event)
if (iqlen >= (SEQ_MAX_QUEUE - 1))
return; /* Overflow */
memcpy (iqueue[iqtail], event, 4);
memcpy (&iqueue[iqtail * IEV_SZ], event, IEV_SZ);
iqlen++;
iqtail = (iqtail + 1) % SEQ_MAX_QUEUE;
DISABLE_INTR (flags);
if (SOMEONE_WAITING (midi_sleep_flag))
if (SOMEONE_WAITING (midi_sleeper, midi_sleep_flag))
{
WAKE_UP (midi_sleeper, midi_sleep_flag);
}
......@@ -268,7 +270,7 @@ seq_queue (unsigned char *note)
if (!seq_playing)
seq_startplay (); /* Give chance to drain the queue */
if (qlen >= SEQ_MAX_QUEUE && !SOMEONE_WAITING (seq_sleep_flag))
if (qlen >= SEQ_MAX_QUEUE && !SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
{
/* Sleep until there is enough space on the queue */
DO_SLEEP (seq_sleeper, seq_sleep_flag, 0);
......@@ -277,7 +279,7 @@ seq_queue (unsigned char *note)
if (qlen >= SEQ_MAX_QUEUE)
return 0; /* To be sure */
memcpy (&queue[qtail][0], note, EV_SZ);
memcpy (&queue[qtail * EV_SZ], note, EV_SZ);
qtail = (qtail + 1) % SEQ_MAX_QUEUE;
qlen++;
......@@ -344,7 +346,7 @@ seq_startplay (void)
qhead = ((this_one = qhead) + 1) % SEQ_MAX_QUEUE;
qlen--;
q = &queue[this_one][0];
q = &queue[this_one*EV_SZ];
switch (q[0])
{
......@@ -380,7 +382,7 @@ seq_startplay (void)
unsigned long flags;
DISABLE_INTR (flags);
if (SOMEONE_WAITING (seq_sleep_flag))
if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
{
WAKE_UP (seq_sleeper, seq_sleep_flag);
}
......@@ -450,7 +452,7 @@ seq_startplay (void)
unsigned long flags;
DISABLE_INTR (flags);
if (SOMEONE_WAITING (seq_sleep_flag))
if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
{
WAKE_UP (seq_sleeper, seq_sleep_flag);
}
......@@ -630,7 +632,7 @@ seq_sync (void)
if (qlen && !seq_playing && !PROCESS_ABORTING (seq_sleeper, seq_sleep_flag))
seq_startplay ();
if (qlen && !SOMEONE_WAITING (seq_sleep_flag)) /* Queue not empty */
if (qlen && !SOMEONE_WAITING (seq_sleeper, seq_sleep_flag)) /* Queue not empty */
{
DO_SLEEP (seq_sleeper, seq_sleep_flag, 0);
}
......@@ -684,7 +686,8 @@ seq_reset (void)
{
for (chn = 0; chn < 16; chn++)
{
midi_outc (i, 0xb0 + chn); /* Channel message */
midi_outc (i,
(unsigned char)(0xb0 + (chn & 0xff))); /* Channel msg */
midi_outc (i, 0x7b);/* All notes off */
midi_outc (i, 0); /* Dummy parameter */
}
......@@ -697,7 +700,7 @@ seq_reset (void)
seq_playing = 0;
if (SOMEONE_WAITING (seq_sleep_flag))
if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
printk ("Sequencer Warning: Unexpected sleeping process\n");
}
......@@ -1090,6 +1093,8 @@ 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);
return mem_start;
}
......
......@@ -97,6 +97,16 @@ void sound_stop_timer(void);
int snd_ioctl_return(int *addr, int value);
int snd_set_irq_handler (int interrupt_level, void(*hndlr)(int));
void snd_release_irq(int vect);
void sound_dma_malloc(int dev);
void sound_dma_free(int dev);
/* From sound_switch.c */
int 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);
int sound_open_sw (int dev, struct fileinfo *file);
void sound_release_sw (int dev, struct fileinfo *file);
int sound_ioctl_sw (int dev, struct fileinfo *file,
unsigned int cmd, unsigned long arg);
/* From sb_dsp.c */
int sb_dsp_detect (struct address_info *hw_config);
......@@ -112,12 +122,17 @@ void sb16_dsp_interrupt (int unused);
long sb16_dsp_init(long mem_start, struct address_info *hw_config);
int sb16_dsp_detect(struct address_info *hw_config);
/* From sb16_midi.c */
void sb16midiintr (int unit);
long attach_sb16midi(long mem_start, struct address_info * hw_config);
int probe_sb16midi(struct address_info *hw_config);
/* From sb_midi.c */
void sb_midi_init(int model);
/* From sb_mixer.c */
void sb_setmixer (unsigned char port, unsigned char value);
int sb_getmixer (unsigned char port);
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);
......@@ -163,7 +178,7 @@ int gus_wave_detect(int baseaddr);
long gus_wave_init(long mem_start, int irq, int dma);
void gus_voice_irq(void);
unsigned char gus_read8 (int reg);
void gus_write8(int reg, unsigned char data);
void gus_write8(int reg, unsigned int data);
void guswave_dma_irq(void);
void gus_delay(void);
......
......@@ -85,6 +85,10 @@ If your card has nonstandard I/O address or IRQ number, change defines
#define SB16_DMA 6
#endif
#ifndef SB16MIDI_BASE
#define SB16MIDI_BASE 0x300
#endif
#ifndef PAS_BASE
#define PAS_BASE 0x388
#endif
......
/*
* 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
* 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"
#ifdef CONFIGURE_SOUNDCARD
struct sbc_device
{
int usecount;
};
static struct sbc_device sbc_devices[SND_NDEVS] = {{0}};
static int in_use = 0; /* Total # of open device files (excluding
* minor 0) */
/*
* /dev/sndstatus -device
*/
static char *status_buf = NULL;
static int status_len, status_ptr;
static int status_busy = 0;
static int
put_status (char *s)
{
int l;
for (l=0;l<256,s[l];l++); /* l=strlen(s); */
if (status_len + l >= 4000)
return 0;
memcpy (&status_buf[status_len], s, l);
status_len += l;
return 1;
}
static int
put_status_int (unsigned int val, int radix)
{
int l, v;
static char hx[] = "0123456789abcdef";
char buf[11];
if (!val) return put_status("0");
l = 0;
buf[10]=0;
while (val)
{
v = val % radix;
val = val / radix;
buf[9-l] = hx[v];
l++;
}
if (status_len + l >= 4000)
return 0;
memcpy (&status_buf[status_len], &buf[10-l], l);
status_len += l;
return 1;
}
static void
init_status (void)
{
/*
* Write the status information to the status_buf and update status_len.
* There is a limit of 4000 bytes for the data.
*/
int i;
status_ptr = 0;
put_status ("Sound Driver:" SOUND_VERSION_STRING
" (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY "@"
SOUND_CONFIG_HOST "." SOUND_CONFIG_DOMAIN ")"
"\n");
if (!put_status ("Config options: "))
return;
if (!put_status_int(SELECTED_SOUND_OPTIONS, 16))
return;
if (!put_status ("\n\nHW config: \n"))
return;
for (i = 0; i < (num_sound_drivers - 1); i++)
{
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 (")"))
return;
if (!put_status ("\n"))
return;
}
if (!put_status ("\nPCM devices:\n"))
return;
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 ("\nSynth devices:\n"))
return;
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 ("\nMidi devices:\n"))
return;
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 (num_mixers)
{
if (!put_status ("\nMixer(s) installed\n"))
return;
}
else
{
if (!put_status ("\nNo mixers installed\n"))
return;
}
}
static int
read_status (snd_rw_buf *buf, int count)
{
/*
* Return at most 'count' bytes from the status_buf.
*/
int l, c;
l = count;
c = status_len - status_ptr;
if (l > c)
l = c;
if (l <= 0)
return 0;
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)
{
DEB (printk ("sound_read_sw(dev=%d, count=%d)\n", dev, count));
switch (dev & 0x0f)
{
case SND_DEV_STATUS:
return read_status (buf, count);
break;
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
return audio_read (dev, file, buf, count);
break;
case SND_DEV_SEQ:
return sequencer_read (dev, file, buf, count);
break;
#ifndef EXCLUDE_MPU401
case SND_DEV_MIDIN:
return MIDIbuf_read (dev, file, buf, count);
#endif
default:
printk ("Sound: Undefined minor device %d\n", dev);
}
return RET_ERROR (EPERM);
}
int
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));
switch (dev & 0x0f)
{
case SND_DEV_SEQ:
return sequencer_write (dev, file, buf, count);
break;
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
return audio_write (dev, file, buf, count);
break;
default:
return RET_ERROR (EPERM);
}
return count;
}
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))
{
printk ("Invalid minor device %d\n", dev);
return RET_ERROR (ENODEV);
}
switch (dev & 0x0f)
{
case SND_DEV_STATUS:
if (status_busy)
return RET_ERROR (EBUSY);
status_busy = 1;
if ((status_buf = (char *) KERNEL_MALLOC (4000)) == NULL)
return RET_ERROR (EIO);
status_len = status_ptr = 0;
init_status ();
break;
case SND_DEV_CTL:
return 0;
break;
case SND_DEV_SEQ:
if ((retval = sequencer_open (dev, file)) < 0)
return retval;
break;
#ifndef EXCLUDE_MPU401
case SND_DEV_MIDIN:
if ((retval = MIDIbuf_open (dev, file)) < 0)
return retval;
break;
#endif
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
if ((retval = audio_open (dev, file)) < 0)
return retval;
break;
default:
printk ("Invalid minor device %d\n", dev);
return RET_ERROR (ENODEV);
}
sbc_devices[dev].usecount++;
in_use++;
return 0;
}
void
sound_release_sw (int dev, struct fileinfo *file)
{
DEB (printk ("sound_release_sw(dev=%d)\n", dev));
switch (dev & 0x0f)
{
case SND_DEV_STATUS:
if (status_buf)
KERNEL_FREE (status_buf);
status_buf = NULL;
status_busy = 0;
break;
case SND_DEV_CTL:
break;
case SND_DEV_SEQ:
sequencer_release (dev, file);
break;
#ifndef EXCLUDE_MPU401
case SND_DEV_MIDIN:
MIDIbuf_release (dev, file);
break;
#endif
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
audio_release (dev, file);
break;
default:
printk ("Sound error: Releasing unknown device 0x%02x\n", dev);
}
sbc_devices[dev].usecount--;
in_use--;
}
int
sound_ioctl_sw (int dev, struct fileinfo *file,
unsigned int cmd, unsigned long arg)
{
DEB (printk ("sound_ioctl_sw(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg));
switch (dev & 0x0f)
{
case SND_DEV_CTL:
if (!num_mixers)
return RET_ERROR (ENODEV);
if (dev >= num_mixers)
return RET_ERROR (ENODEV);
return mixer_devs[dev]->ioctl (dev, cmd, arg);
break;
case SND_DEV_SEQ:
return sequencer_ioctl (dev, file, cmd, arg);
break;
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
return audio_ioctl (dev, file, cmd, arg);
break;
#ifndef EXCLUDE_MPU401
case SND_DEV_MIDIN:
return MIDIbuf_ioctl (dev, file, cmd, arg);
break;
#endif
default:
return RET_ERROR (EPERM);
break;
}
return RET_ERROR (EPERM);
}
#endif
This diff is collapsed.
......@@ -7,7 +7,7 @@
#
# Note 2! The CFLAGS definitions are now in the main makefile...
SUBDIRS = minix ext ext2 msdos proc isofs nfs xiafs hpfs
SUBDIRS = minix ext ext2 msdos proc isofs nfs xiafs hpfs sysv
ifdef CONFIG_MINIX_FS
FS_SUBDIRS := $(FS_SUBDIRS) minix
......@@ -33,6 +33,9 @@ endif
ifdef CONFIG_XIA_FS
FS_SUBDIRS := $(FS_SUBDIRS) xiafs
endif
ifdef CONFIG_SYSV_FS
FS_SUBDIRS := $(FS_SUBDIRS) sysv
endif
ifdef CONFIG_HPFS_FS
FS_SUBDIRS := $(FS_SUBDIRS) hpfs
endif
......@@ -40,6 +43,9 @@ endif
ifdef CONFIG_BINFMT_ELF
BINFMTS := $(BINFMTS) binfmt_elf.o
endif
ifdef CONFIG_BINFMT_COFF
BINFMTS := $(BINFMTS) binfmt_coff.o
endif
.c.s:
$(CC) $(CFLAGS) -S $<
......
This diff is collapsed.
......@@ -307,7 +307,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
current->start_stack = p = elf_stack - 4;
#endif
bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
bprm->p = (unsigned long) create_tables((char *)bprm->p,bprm->argc,bprm->envc);
bprm->p = (unsigned long) create_tables((char *)bprm->p,bprm->argc,bprm->envc,0);
if(elf_interpreter) current->arg_start += strlen(passed_fileno) + 1;
current->start_brk = current->brk = elf_brk;
current->end_code = end_code;
......
......@@ -261,7 +261,7 @@ asmlinkage int sys_uselib(const char * library)
* memory and creates the pointer tables from them, and puts their
* addresses on the "stack", returning the new stack pointer value.
*/
unsigned long * create_tables(char * p,int argc,int envc)
unsigned long * create_tables(char * p,int argc,int envc,int ibcs)
{
unsigned long *argv,*envp;
unsigned long * sp;
......@@ -285,8 +285,10 @@ unsigned long * create_tables(char * p,int argc,int envc)
envp = sp;
sp -= argc+1;
argv = sp;
put_fs_long((unsigned long)envp,--sp);
put_fs_long((unsigned long)argv,--sp);
if (!ibcs) {
put_fs_long((unsigned long)envp,--sp);
put_fs_long((unsigned long)argv,--sp);
}
put_fs_long((unsigned long)argc,--sp);
current->arg_start = (unsigned long) p;
while (argc-->0) {
......@@ -723,15 +725,26 @@ extern int load_aout_binary(struct linux_binprm *,
struct pt_regs * regs);
extern int load_aout_library(int fd);
#ifdef CONFIG_BINFMT_ELF
extern int load_elf_binary(struct linux_binprm *,
struct pt_regs * regs);
extern int load_elf_library(int fd);
#endif
#ifdef CONFIG_BINFMT_COFF
extern int load_coff_binary(struct linux_binprm *,
struct pt_regs * regs);
extern int load_coff_library(int fd);
#endif
/* Here are the actual binaries that will be accepted */
struct linux_binfmt formats[] = {
{load_aout_binary, load_aout_library},
#ifdef CONFIG_BINFMT_ELF
{load_elf_binary, load_elf_library},
#endif
#ifdef CONFIG_BINFMT_COFF
{load_coff_binary, load_coff_library},
#endif
{NULL, NULL}
};
......@@ -828,7 +841,7 @@ int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
p += change_ldt(ex.a_text,bprm->page);
p -= MAX_ARG_PAGES*PAGE_SIZE;
p = (unsigned long) create_tables((char *)p,bprm->argc,bprm->envc);
p = (unsigned long) create_tables((char *)p,bprm->argc,bprm->envc,0);
current->start_stack = p;
regs->eip = ex.a_entry; /* eip, magic happens :-) */
regs->esp = p; /* stack pointer */
......
......@@ -35,6 +35,9 @@
#ifdef CONFIG_HPFS_FS
#include <linux/hpfs_fs.h>
#endif
#ifdef CONFIG_SYSV_FS
#include <linux/sysv_fs.h>
#endif
struct file_system_type file_systems[] = {
#ifdef CONFIG_MINIX_FS
......@@ -61,6 +64,11 @@ struct file_system_type file_systems[] = {
#ifdef CONFIG_ISO9660_FS
{isofs_read_super, "iso9660", 1},
#endif
#ifdef CONFIG_SYSV_FS
{sysv_read_super, "xenix", 1},
{sysv_read_super, "sysv", 1},
{sysv_read_super, "coherent", 1},
#endif
#ifdef CONFIG_HPFS_FS
{hpfs_read_super, "hpfs", 1},
#endif
......
This diff is collapsed.
......@@ -388,8 +388,10 @@ char * get_rock_ridge_symlink(struct inode * inode)
rpnt = 0;
block = inode->i_ino >> bufbits;
if (!(bh=bread(inode->i_dev,block, bufsize)))
panic("unable to read i-node block");
if (!(bh=bread(inode->i_dev,block, bufsize))) {
printk("unable to read i-node block");
return NULL;
};
pnt = ((unsigned char *) bh->b_data) + (inode->i_ino & (bufsize - 1));
......@@ -399,8 +401,11 @@ char * get_rock_ridge_symlink(struct inode * inode)
cpnt = kmalloc(1 << ISOFS_BLOCK_BITS, GFP_KERNEL);
memcpy(cpnt, bh->b_data, bufsize);
brelse(bh);
if (!(bh = bread(inode->i_dev,++block, bufsize)))
panic("unable to read i-node block");
if (!(bh = bread(inode->i_dev,++block, bufsize))) {
kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
printk("unable to read i-node block");
return NULL;
};
memcpy((char *)cpnt+bufsize, bh->b_data, bufsize);
pnt = ((unsigned char *) cpnt) + (inode->i_ino & (bufsize - 1));
raw_inode = ((struct iso_directory_record *) pnt);
......
......@@ -113,7 +113,7 @@ static inline int *xdr_decode_data(int *p, char *data, int *lenp, int maxlen)
static int *xdr_decode_fattr(int *p, struct nfs_fattr *fattr)
{
fattr->type = (enum nfs_stat) ntohl(*p++);
fattr->type = (enum nfs_ftype) ntohl(*p++);
fattr->mode = ntohl(*p++);
fattr->nlink = ntohl(*p++);
fattr->uid = ntohl(*p++);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment