Commit b872e060 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.3.11

parent bb9c5bf1
......@@ -688,7 +688,9 @@ S: United Kingdom
N: Michael Neuffer
E: neuffer@goofy.zdv.uni-mainz.de
D: developer and maintainer of the eata_dma SCSI driver
D: Developer and maintainer of the EATA-DMA SCSI driver
D: Co-developer EATA-PIO SCSI driver
D: Assorted other snippets
S: Zum Schiersteiner Grund 2
S: 55127 Mainz
S: Germany
......
VERSION = 1
PATCHLEVEL = 3
SUBLEVEL = 10
SUBLEVEL = 11
ARCH = i386
......
......@@ -9,7 +9,7 @@
#define halt .long PAL_halt
#define rti .long PAL_rti
#define NR_SYSCALLS 310
#define NR_SYSCALLS 320
#define osf_vfork sys_fork
/*
......@@ -565,3 +565,6 @@ sys_call_table:
/* linux-specific system calls start at 300 */
/*300*/ .quad sys_bdflush, sys_sethae, sys_mount, sys_adjtimex, sys_swapoff
.quad sys_getdents, sys_create_module, sys_init_module, sys_delete_module, sys_get_kernel_syms
.quad sys_syslog, do_entSys, do_entSys, do_entSys, do_entSys
.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
......@@ -693,7 +693,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, int a4,
else
child->flags &= ~PF_TRACESYS;
child->exit_code = data;
child->state = TASK_RUNNING;
wake_up_process(child);
ptrace_cancel_bpt(child);
set_success(&regs,data);
return 0;
......@@ -705,7 +705,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, int a4,
* exit.
*/
case PTRACE_KILL: {
child->state = TASK_RUNNING;
wake_up_process(child);
child->exit_code = SIGKILL;
ptrace_cancel_bpt(child);
return 0;
......@@ -721,7 +721,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, int a4,
return res;
}
child->flags &= ~PF_TRACESYS;
child->state = TASK_RUNNING;
wake_up_process(child);
child->exit_code = data;
/* give it a chance to run. */
return 0;
......@@ -733,7 +733,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, int a4,
return -EIO;
}
child->flags &= ~(PF_PTRACED|PF_TRACESYS);
child->state = TASK_RUNNING;
wake_up_process(child);
child->exit_code = data;
REMOVE_LINKS(child);
child->p_pptr = child->p_opptr;
......
......@@ -8,7 +8,7 @@
$(CC) $(CFLAGS) -c $<
OBJS = __divqu.o __remqu.o __divlu.o __remlu.o memset.o memcpy.o io.o \
checksum.o
checksum.o strlen.o
lib.a: $(OBJS)
$(AR) rcs lib.a $(OBJS)
......
/*
* strlen.S (c) 1995 David Mosberger (davidm@cs.arizona.edu)
*
* Finds length of a 0-terminated string. Optimized for the
* Alpha architecture:
*
* - memory accessed as aligned quadwords only
* - uses bcmpge to compare 8 bytes in parallel
* - does binary search to find 0 byte in last
* quadword (HAKMEM needed 12 instructions to
* do this instead of the 9 instructions that
* binary search needs).
*/
.set noreorder
.set noat
.align 3
.globl strlen
.ent strlen
strlen:
ldq_u $1, 0($16) # load first quadword ($16 may be misaligned)
lda $2, -1($31)
insqh $2, $16, $2
andnot $16, 7, $0
or $2, $1, $1
cmpbge $31, $1, $2 # $2 <- bitmask: bit i == 1 <==> i-th byte == 0
bne $2, found
loop: ldq $1, 8($0)
addq $0, 8, $0 # addr += 8
nop # helps dual issue last two insns
cmpbge $31, $1, $2
beq $2, loop
found: blbs $2, done # make aligned case fast
negq $2, $3
and $2, $3, $2
and $2, 0x0f, $1
addq $0, 4, $3
cmoveq $1, $3, $0
and $2, 0x33, $1
addq $0, 2, $3
cmoveq $1, $3, $0
and $2, 0x55, $1
addq $0, 1, $3
cmoveq $1, $3, $0
done: subq $0, $16, $0
ret $31, ($26)
.end strlen
......@@ -466,7 +466,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
else
child->flags &= ~PF_TRACESYS;
child->exit_code = data;
child->state = TASK_RUNNING;
wake_up_process(child);
/* make sure the single step bit is not set. */
tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) & ~TRAP_FLAG;
put_stack_long(child, sizeof(long)*EFL-MAGICNUMBER,tmp);
......@@ -481,7 +481,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
case PTRACE_KILL: {
long tmp;
child->state = TASK_RUNNING;
wake_up_process(child);
child->exit_code = SIGKILL;
/* make sure the single step bit is not set. */
tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) & ~TRAP_FLAG;
......@@ -497,7 +497,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
child->flags &= ~PF_TRACESYS;
tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) | TRAP_FLAG;
put_stack_long(child, sizeof(long)*EFL-MAGICNUMBER,tmp);
child->state = TASK_RUNNING;
wake_up_process(child);
child->exit_code = data;
/* give it a chance to run. */
return 0;
......@@ -509,7 +509,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
if ((unsigned long) data > NSIG)
return -EIO;
child->flags &= ~(PF_PTRACED|PF_TRACESYS);
child->state = TASK_RUNNING;
wake_up_process(child);
child->exit_code = data;
REMOVE_LINKS(child);
child->p_pptr = child->p_opptr;
......
......@@ -448,7 +448,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
else
child->flags &= ~PF_TRACESYS;
child->exit_code = data;
child->state = TASK_RUNNING;
wake_up_process(child);
/* make sure the single step bit is not set. */
tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) & ~TRAP_FLAG;
put_stack_long(child, sizeof(long)*EFL-MAGICNUMBER,tmp);
......@@ -463,7 +463,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
case PTRACE_KILL: {
long tmp;
child->state = TASK_RUNNING;
wake_up_process(child);
child->exit_code = SIGKILL;
/* make sure the single step bit is not set. */
tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) & ~TRAP_FLAG;
......@@ -479,7 +479,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
child->flags &= ~PF_TRACESYS;
tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) | TRAP_FLAG;
put_stack_long(child, sizeof(long)*EFL-MAGICNUMBER,tmp);
child->state = TASK_RUNNING;
wake_up_process(child);
child->exit_code = data;
/* give it a chance to run. */
return 0;
......@@ -491,7 +491,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
if ((unsigned long) data > NSIG)
return -EIO;
child->flags &= ~(PF_PTRACED|PF_TRACESYS);
child->state = TASK_RUNNING;
wake_up_process(child);
child->exit_code = data;
REMOVE_LINKS(child);
child->p_pptr = child->p_opptr;
......
......@@ -15,7 +15,6 @@
$(CC) $(CFLAGS) -c $<
SUBDIRS = block char net #streams
ALL_SUBDIRS = block char net scsi #streams
ifdef CONFIG_PCI
SUBDIRS := $(SUBDIRS) pci
......@@ -35,9 +34,9 @@ driversubdirs: dummy
set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i; done
modules: dummy
set -e; for i in $(ALL_SUBDIRS); do $(MAKE) -C $$i modules; done
set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i modules; done
dep:
set -e; for i in $(ALL_SUBDIRS); do $(MAKE) -C $$i dep; done
set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i dep; done
include $(TOPDIR)/Rules.make
-- README.sjcd
80% of the work takes 20% of the time,
20% of the work takes 80% of the time...
(Murphy law)
......@@ -5,21 +6,36 @@
Once started, training can not be stopped...
(StarWars)
This is the README for the sjcd cdrom driver, version 1.3.
This file is meant as a tips & tricks edge for the usage of the SANYO CDR-H94A
cdrom drive. It will grow as the questions arise. ;-)
Since the drive often comes with an ISP16 soundcard, which can be used
as cdrom interface, this is also the place for ISP16 related issues.
The driver should work with any SoundBlaster/Panasonic style CDROM interface,
including the "soft configurable" MediaMagic sound card.
To make this sound card (and others like "Mozart") working, it has to get
"configured" by software.
So, you should boot DOS once (and by this, run the "configuration driver")
The suggestion to configure the ISP16 soundcard by booting DOS and
a warm reboot to boot Linux somehow doesn't work, at least not
on Eric's machine (IPC P90), with the version of the ISP16
card he has (there appear to be at least two versions: Eric's card with
no jumpered IDE support and Vadim's version with a jumper to enable
IDE support).
Therefore detection and configuration of the ISP16 interfaces is included
in the driver.
If we should support any other interfaces (which cannot be configured
through DOS) or if there are any more ISP16 types, please let us
know (maarel@marin.nl) and we'll see.
Otherwise, you should boot DOS once (and by this, run the "configuration driver")
and then switch to Linux by use of CTL-ALT-DEL. Each use of the RESET
button or the power switch makes this procedure necessary again.
If no ISP16 is detected, there's no harm done; a card configured trough DOS
may still work as expected.
Vadim has implemented a Linux "configuration driver" to set up the
registers of the MediaMagic (ISP-16) sound card. These routines have to get
integrated into the related CDROM and sound drivers directly at a later
time. Currently, they reside at Vadim's server
ISP16 configuration routines reside at Vadim's server
rbrf.msk.su:/linux/mediamagic/
and at Eberhard's mirror
ftp.gwdg.de:/pub/linux/cdrom/drivers/sanyo/
......@@ -29,6 +45,26 @@ Leo Spiekman's configuration routines for the ISP-16 card can get found at
and at Eberhard's mirror
ftp.gwdg.de:/pub/linux/cdrom/drivers/optics/
Eric van der Maarel's routines are included in sjcd.c.
This, and any related stuff may be found by anonymous ftp at
ftp.gwdg.de:/pub/linux/cdrom/drivers/sanyo/
The device major for sjcd is 18, and minor is 0. Create a block special
file in your /dev directory (e.g., /dev/sjcd) with these numbers.
(For those who don't know, being root and the following should do the trick:
mknod -m 644 /dev/sjcd b 18 0
and mount the cdrom by /dev/sjcd).
The default configuration parameters are:
base address 0x340
irq 10
no dma
As of version 1.2, setting base address, irq and dma at boot time is supported
through the use of command line options: type at the "boot:" prompt:
linux sjcd=<base address>,<irq>,<dma>
(where your kernel is assumed to be called by saying "linux" to
the boot manager).
If something is wrong, e-mail to vadim@rbrf.msk.su
or vadim@ipsun.ras.ru
or model@cecmow.enet.dec.com
......
......@@ -1358,7 +1358,7 @@ static int ide_open(struct inode * inode, struct file * filp)
sleep_on(&dev->wqueue);
dev->usage++;
restore_flags(flags);
if (dev->id->config & (1<<7)) /* for removeable disks */
if (dev->id && (dev->id->config & (1<<7))) /* for removeable disks */
check_disk_change(inode->i_rdev);
#ifdef CONFIG_BLK_DEV_IDECD
if (dev->type == cdrom)
......@@ -1654,7 +1654,7 @@ static int ide_check_media_change (dev_t full_dev)
if (dev->type == cdrom)
return cdrom_check_media_change (dev);
#endif /* CONFIG_BLK_DEV_IDECD */
if (dev->id->config & (1<<7)) /* for removeable disks */
if (dev->id && (dev->id->config & (1<<7))) /* for removeable disks */
return 1; /* always assume it was changed */
return 0;
}
......
/*
* Sanyo CD-ROM device driver implementation.
/* -- sjcd.c
*
* Sanyo CD-ROM device driver implementation, Version 1.3
* Copyright (C) 1995 Vadim V. Model
*
* model@cecmow.enet.dec.com
* vadim@rbrf.msk.su
* vadim@ipsun.ras.ru
*
* ISP16 detection and configuration.
* Copyright (C) 1995 Eric van der Maarel (maarel@marin.nl)
*
*
* This driver is based on pre-works by Eberhard Moenkeberg (emoenke@gwdg.de);
* it was developed under use of mcd.c from Martin Harriss, with help of
* E. van der Maarel (maarel@marin.nl).
* Eric van der Maarel (maarel@marin.nl).
*
* ISP16 detection and configuration by Eric van der Maarel (maarel@marin.nl),
* with some data communicated by Vadim V. Model (vadim@rbrf.msk.su)
* and Leo Spiekman (spiekman@et.tudelft.nl)
*
*
* It is planned to include these routines into sbpcd.c later - to make
* a "mixed use" on one cable possible for all kinds of drives which use
......@@ -29,6 +38,15 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* History:
* 1.1 First public release with kernel version 1.3.7.
* Written by Vadim Model.
* 1.2 Added detection and configuration of cdrom interface
* on ISP16 soundcard.
* Allow for command line options: sjcd=<io_base>,<irq>,<dma>
* 1.3 Some minor changes to README.sjcd.
*
*/
#include <linux/errno.h>
......@@ -49,11 +67,60 @@
#define MAJOR_NR SANYO_CDROM_MAJOR
#include "blk.h"
#ifdef CONFIG_ISP_16
#include <linux/isp16.h>
#endif
#include <linux/sjcd.h>
/* Some (Media)Magic */
/* define types of drive the interface on an ISP16 card may be looking at */
#define ISP16_DRIVE_X 0x00
#define ISP16_SONY 0x02
#define ISP16_PANASONIC0 0x02
#define ISP16_SANYO0 0x02
#define ISP16_MITSUMI 0x04
#define ISP16_PANASONIC1 0x06
#define ISP16_SANYO1 0x06
#define ISP16_DRIVE_NOT_USED 0x08 /* not used */
#define ISP16_DRIVE_SET_MASK 0xF1 /* don't change 0-bit or 4-7-bits*/
/* ...for port */
#define ISP16_DRIVE_SET_PORT 0xF8D
/* set io parameters */
#define ISP16_BASE_340 0x00
#define ISP16_BASE_330 0x40
#define ISP16_BASE_360 0x80
#define ISP16_BASE_320 0xC0
#define ISP16_IRQ_X 0x00
#define ISP16_IRQ_5 0x04 /* shouldn't be used due to soundcard conflicts */
#define ISP16_IRQ_7 0x08 /* shouldn't be used due to soundcard conflicts */
#define ISP16_IRQ_3 0x0C
#define ISP16_IRQ_9 0x10
#define ISP16_IRQ_10 0x14
#define ISP16_IRQ_11 0x18
#define ISP16_DMA_X 0x03
#define ISP16_DMA_3 0x00
#define ISP16_DMA_5 0x00
#define ISP16_DMA_6 0x01
#define ISP16_DMA_7 0x02
#define ISP16_IO_SET_MASK 0x20 /* don't change 5-bit */
/* ...for port */
#define ISP16_IO_SET_PORT 0xF8E
/* enable the drive */
#define ISP16_NO_IDE__ENABLE_CDROM_PORT 0xF90 /* ISP16 without IDE interface */
#define ISP16_IDE__ENABLE_CDROM_PORT 0xF91 /* ISP16 with IDE interface */
#define ISP16_ENABLE_CDROM 0x80 /* seven bit */
/* the magic stuff */
#define ISP16_CTRL_PORT 0xF8F
#define ISP16_NO_IDE__CTRL 0xE2 /* ISP16 without IDE interface */
#define ISP16_IDE__CTRL 0xE3 /* ISP16 with IDE interface */
static short isp16_detect(void);
static short isp16_no_ide__detect(void);
static short isp16_with_ide__detect(void);
static short isp16_config( int base, u_char drive_type, int irq, int dma );
static short isp16_type; /* dependent on type of interface card */
static u_char isp16_ctrl;
static u_short isp16_enable_cdrom_port;
static int sjcd_present = 0;
#define SJCD_BUF_SIZ 32 /* cdr-h94a has internal 64K buffer */
......@@ -86,6 +153,7 @@ static struct sjcd_play_msf sjcd_playing;
static short sjcd_port = SJCD_BASE_ADDR;
static int sjcd_irq = SJCD_INTR_NR;
static int sjcd_dma = SJCD_DMA;
static struct wait_queue *sjcd_waitq = NULL;
......@@ -131,10 +199,17 @@ static struct timer_list sjcd_delay_timer = { NULL, NULL, 0, 0, NULL };
#define CLEAR_TIMER del_timer( &sjcd_delay_timer )
/*
* Set up device. Not yet implemented.
* Set up device, i.e., use command line data to set
* base address, irq and dma.
*/
void sjcd_setup( char *str, int *ints ){
printk( "Sanyo CDR-H94A device driver setup is called (%s).\n", str );
if (ints[0] > 0)
sjcd_port = ints[1];
if (ints[0] > 1)
sjcd_irq = ints[2];
if (ints[0] > 2)
sjcd_dma = ints[3];
}
/*
......@@ -1266,7 +1341,7 @@ static struct file_operations sjcd_fops = {
};
/*
* Following staff is intended for initialization of the cdrom. It
* Following stuff is intended for initialization of the cdrom. It
* first looks for presence of device. If the device is present, it
* will be reset. Then read the version of the drive and load status.
*/
......@@ -1281,22 +1356,21 @@ static struct {
unsigned long sjcd_init( unsigned long mem_start, unsigned long mem_end ){
int i;
if( sjcd_port != 0x340 || sjcd_irq != 0x0A /* 10 */ ){
printk( "skip sjcd_init\n" );
return( mem_start );
}
#ifdef CONFIG_ISP_16
/*
* Initialize the CDROM interface of the card.
*/
isp16_cdi_setup( ISP_CDROM_SANYO, ISP_CDROM_IRQ_10,
ISP_CDROM_DMA_DISABLED, ISP_CDROM_PORT_340 );
#endif
if ( (isp16_type=isp16_detect()) < 0 )
printk( "No ISP16 cdrom interface found.\n" );
else {
u_char expected_drive;
#if 0
printk( "sjcd=0x%x,%d: ", sjcd_port, sjcd_irq );
#endif
printk( "ISP16 cdrom interface (%s optional IDE) detected.\n",
(isp16_type==2)?"with":"without" );
expected_drive = (isp16_type?ISP16_SANYO1:ISP16_SANYO0);
if ( isp16_config( sjcd_port, expected_drive, sjcd_irq, sjcd_dma ) < 0 ) {
printk( "ISP16 cdrom interface has not been properly configured.\n" );
return(mem_start);
}
}
if( register_blkdev( MAJOR_NR, "sjcd", &sjcd_fops ) != 0 ){
printk( "Unable to get major %d for Sanyo CD-ROM\n", MAJOR_NR );
......@@ -1356,3 +1430,189 @@ unsigned long sjcd_init( unsigned long mem_start, unsigned long mem_end ){
return( mem_start );
}
/*
* -- ISP16 detection and configuration
*
* Copyright (c) 1995, Eric van der Maarel <maarel@marin.nl>
*
* Version 0.5
*
* Detect cdrom interface on ISP16 soundcard.
* Configure cdrom interface.
*
* Algorithm for the card with no IDE support option taken
* from the CDSETUP.SYS driver for MSDOS,
* by OPTi Computers, version 2.03.
* Algorithm for the IDE supporting ISP16 as communicated
* to me by Vadim Model and Leo Spiekman.
*
* Use, modifification or redistribution of this software is
* allowed under the terms of the GPL.
*
*/
#define ISP16_IN(p) (outb(isp16_ctrl,ISP16_CTRL_PORT), inb(p))
#define ISP16_OUT(p,b) (outb(isp16_ctrl,ISP16_CTRL_PORT), outb(b,p))
static short
isp16_detect(void)
{
if ( !( isp16_with_ide__detect() < 0 ) )
return(2);
else
return( isp16_no_ide__detect() );
}
static short
isp16_no_ide__detect(void)
{
u_char ctrl;
u_char enable_cdrom;
u_char io;
short i = -1;
isp16_ctrl = ISP16_NO_IDE__CTRL;
isp16_enable_cdrom_port = ISP16_NO_IDE__ENABLE_CDROM_PORT;
/* read' and write' are a special read and write, respectively */
/* read' ISP16_CTRL_PORT, clear last two bits and write' back the result */
ctrl = ISP16_IN( ISP16_CTRL_PORT ) & 0xFC;
ISP16_OUT( ISP16_CTRL_PORT, ctrl );
/* read' 3,4 and 5-bit from the cdrom enable port */
enable_cdrom = ISP16_IN( ISP16_NO_IDE__ENABLE_CDROM_PORT ) & 0x38;
if ( !(enable_cdrom & 0x20) ) { /* 5-bit not set */
/* read' last 2 bits of ISP16_IO_SET_PORT */
io = ISP16_IN( ISP16_IO_SET_PORT ) & 0x03;
if ( ((io&0x01)<<1) == (io&0x02) ) { /* bits are the same */
if ( io == 0 ) { /* ...the same and 0 */
i = 0;
enable_cdrom |= 0x20;
}
else { /* ...the same and 1 */ /* my card, first time 'round */
i = 1;
enable_cdrom |= 0x28;
}
ISP16_OUT( ISP16_NO_IDE__ENABLE_CDROM_PORT, enable_cdrom );
}
else { /* bits are not the same */
ISP16_OUT( ISP16_CTRL_PORT, ctrl );
return(i); /* -> not detected: possibly incorrect conclusion */
}
}
else if ( enable_cdrom == 0x20 )
i = 0;
else if ( enable_cdrom == 0x28 ) /* my card, already initialised */
i = 1;
ISP16_OUT( ISP16_CTRL_PORT, ctrl );
return(i);
}
static short
isp16_with_ide__detect(void)
{
u_char ctrl;
u_char tmp;
isp16_ctrl = ISP16_IDE__CTRL;
isp16_enable_cdrom_port = ISP16_IDE__ENABLE_CDROM_PORT;
/* read' and write' are a special read and write, respectively */
/* read' ISP16_CTRL_PORT and save */
ctrl = ISP16_IN( ISP16_CTRL_PORT );
/* write' zero to the ctrl port and get response */
ISP16_OUT( ISP16_CTRL_PORT, 0 );
tmp = ISP16_IN( ISP16_CTRL_PORT );
if ( tmp != 2 ) /* isp16 with ide option not detected */
return(-1);
/* restore ctrl port value */
ISP16_OUT( ISP16_CTRL_PORT, ctrl );
return(2);
}
static short
isp16_config( int base, u_char drive_type, int irq, int dma )
{
u_char base_code;
u_char irq_code;
u_char dma_code;
u_char i;
if ( (drive_type == ISP16_MITSUMI) && (dma != 0) )
printk( "Mitsumi cdrom drive has no dma support.\n" );
switch (base) {
case 0x340: base_code = ISP16_BASE_340; break;
case 0x330: base_code = ISP16_BASE_330; break;
case 0x360: base_code = ISP16_BASE_360; break;
case 0x320: base_code = ISP16_BASE_320; break;
default:
printk( "Base address 0x%03X not supported by cdrom interface on ISP16.\n", base );
return(-1);
}
switch (irq) {
case 0: irq_code = ISP16_IRQ_X; break; /* disable irq */
case 5: irq_code = ISP16_IRQ_5;
printk( "Irq 5 shouldn't be used by cdrom interface on ISP16,"
" due to possible conflicts with the soundcard.\n");
break;
case 7: irq_code = ISP16_IRQ_7;
printk( "Irq 7 shouldn't be used by cdrom interface on ISP16,"
" due to possible conflicts with the soundcard.\n");
break;
case 3: irq_code = ISP16_IRQ_3; break;
case 9: irq_code = ISP16_IRQ_9; break;
case 10: irq_code = ISP16_IRQ_10; break;
case 11: irq_code = ISP16_IRQ_11; break;
default:
printk( "Irq %d not supported by cdrom interface on ISP16.\n", irq );
return(-1);
}
switch (dma) {
case 0: dma_code = ISP16_DMA_X; break; /* disable dma */
case 1: printk( "Dma 1 cannot be used by cdrom interface on ISP16,"
" due to conflict with the soundcard.\n");
return(-1); break;
case 3: dma_code = ISP16_DMA_3; break;
case 5: dma_code = ISP16_DMA_5; break;
case 6: dma_code = ISP16_DMA_6; break;
case 7: dma_code = ISP16_DMA_7; break;
default:
printk( "Dma %d not supported by cdrom interface on ISP16.\n", dma );
return(-1);
}
if ( drive_type != ISP16_SONY && drive_type != ISP16_PANASONIC0 &&
drive_type != ISP16_PANASONIC1 && drive_type != ISP16_SANYO0 &&
drive_type != ISP16_SANYO1 && drive_type != ISP16_MITSUMI &&
drive_type != ISP16_DRIVE_X ) {
printk( "Drive type (code 0x%02X) not supported by cdrom"
" interface on ISP16.\n", drive_type );
return(-1);
}
/* set type of interface */
i = ISP16_IN(ISP16_DRIVE_SET_PORT) & ISP16_DRIVE_SET_MASK; /* clear some bits */
ISP16_OUT( ISP16_DRIVE_SET_PORT, i|drive_type );
/* enable cdrom on interface with ide support */
if ( isp16_type > 1 )
ISP16_OUT( isp16_enable_cdrom_port, ISP16_ENABLE_CDROM );
/* set base address, irq and dma */
i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK; /* keep some bits */
ISP16_OUT( ISP16_IO_SET_PORT, i|base_code|irq_code|dma_code );
return(0);
}
#include <linux/autoconf.h> /* fastest method */
#ifdef CONFIG_SCC
#define RCS_ID "$Id: scc.c,v 1.17 1995/03/15 23:28:12 JReuter Exp JReuter $"
#define BANNER "Z8530 SCC driver v1.8.dl1bke (beta) by dl1bke\n"
#define BANNER "Z8530 SCC driver v1.8.17test.17.7.95 PE1AYX (c)\n"
/* ******************************************************************** */
/* * SCC.C - Linux driver for Z8530 based HDLC cards for AX.25 * */
......@@ -11,34 +10,45 @@
/* ********************************************************************
(c) 1995 by Joerg Reuter DL1BKE
(c) Hans Alblas PE1AYX 1993,1994,1995
Released for GNU
portions (c) 1995 by Joerg Reuter DL1BKE
(c) 1993 Guido ten Dolle PE1NNZ
portions (c) 1994 Hans Alblas PE1AYX
and (c) 1993 Guido ten Dolle PE1NNZ
for the complete copyright notice see >> Copying.Z8530DRV <<
******************************************************************** */
/*
940913 - started to rewrite the drive
950131 - changed copyright notice to GPL without limitations.
931100 - started with the projekt pe1ayx
9406?? - KISS-parameter setting and BayCom USCC support dl1bke
940613 - fixed memory leak ,main memory fragmentation problem,
speeded up the interupt routines ,has now its own
memory buffer pool and source cleanup. pe1ayx
940620 - bug fixed in line disipline change ,local ringbuf
reorganisation ,and some little bugfixes.
940715 - first release to the public (scc15b.tgz) pe1ayx
950228 - (hopefully) fixed the reason for kernel panics in
chk_rcv_queue() [stupid error]
950304 - fixed underrun/zcount handling
950305 - the driver registers port addresses now
950314 - fixed underrun interrupt handling again
chk_rcv_queue() [stupid error] dl1bke
950229 - buffer timeout for vergotten buffer :-( pe1ayx
950304 - fixed underrun/zcount handling dl1bke
950305 - the driver registers port addresses now dl1bke
950314 - fixed underrun interrupt handling again dl1bke
950514 - fixed slip tty wakeup (it wil now work again with kernel ax25)pe1ayx
950703 - rewrote the 8530 init/reset routines pe1ayx
950712 - rewrote the RXirq + buffering routines pe1ayx
950716 - It can now handle ax25 rx frame info > 256
O - rewrite TX + buffering (there is a little mem leak ,but
wil not be dangerous since my buffer timeout routine
wil put back vergotten buffers in the queue pe1ayx
O - change the tty i/o so that the tty wakeup is handled properly
pe1ayx
Thanks to:
DL1BKE Joerg - for some good ideas
PE1CHL Rob - for a lot of good ideas from his SCC driver for DOS
PE1NNZ Guido - for his port of the original driver to Linux
KA9Q Phil - from whom we stole the mbuf-structure
PA3AYX Hans - who rewrote the memory management and some minor,
but nevertheless useful changes
DL8MBT Flori - for support
DG0FT Rene - for the BayCom USCC support
PA3AOU Harry - for ESCC testing, information supply and support
PE1KOX Rob, DG1RTF Thomas, ON5QK Roland,
......@@ -46,13 +56,7 @@
and all who sent me bug reports and ideas...
NB -- if you find errors, change something, please let me know
first before you distribute it... And please don't touch
the version number. Just replace my callsign in
"v1.8.dl1bke" with your own. Just to avoid confusion...
Jrg Reuter DL1BKE
*/
......@@ -110,8 +114,6 @@ static void scc_stop(struct tty_struct *tty);
static void z8530_init(void);
static void scc_change_speed(struct scc_channel *scc);
static void kiss_encode(struct scc_channel *scc);
static void init_channel(struct scc_channel *scc);
static void scc_key_trx (struct scc_channel *scc, char tx);
static void scc_txint(register struct scc_channel *scc);
......@@ -124,6 +126,14 @@ static void scc_init_timer(struct scc_channel *scc);
/* from serial.c */
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
static unsigned char *tmp_buf = 0;
static struct semaphore tmp_buf_sem = MUTEX;
static unsigned int start_controle;
static int baud_table[] = {
0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
9600, 19200, 38400, 57600, 115200, 0 };
......@@ -142,6 +152,8 @@ unsigned char Driver_Initialized = 0;
static struct sccbuf *sccfreelist[MAX_IBUFS] = {0};
static int allocated_ibufs = 0;
#define SERIAL_TYPE_NORMAL 1
/* ******************************************************************** */
/* * Port Access Functions * */
......@@ -197,10 +209,6 @@ cl(register struct scc_channel *scc, register unsigned char reg, register unsign
/* * Memory Buffer Management */
/* ******************************************************************** */
/* mbuf concept lent from KA9Q. Tnx PE1AYX for the buffer pool concept */
/* (sorry, do you have any better ideas?) */
/* allocate memory for the interrupt buffer pool */
void scc_alloc_buffer_pool(void)
......@@ -209,6 +217,8 @@ void scc_alloc_buffer_pool(void)
struct sccbuf *sccb;
struct mbuf *bp;
start_controle = 0;
for (i = 0 ; i < MAX_IBUFS ; i++)
{
sccb = (struct sccbuf *)kmalloc(sizeof(struct sccbuf), GFP_ATOMIC);
......@@ -286,6 +296,7 @@ scc_get_buffer(char type)
sccfreelist[i]->bp->refcnt = 1;
sccfreelist[i]->bp->cnt = 0;
sccfreelist[i]->bp->in_use = 0;
sccfreelist[i]->bp->time_out = CURRENT_TIME + 300;
restore_flags(flags);
return sccfreelist[i]->bp;
......@@ -314,7 +325,33 @@ scc_return_buffer(register struct mbuf *bp, char type)
save_flags(flags); cli();
bpnext = bp->next;
/*=========================================================================*/
/*== THIS IS A LITTLE ROUTINE TO FIX THE TX MEM LEAK ==*/
/*== UNTIL I HAVE REWRITE THE TX ROUTINES ==*/
/*== PE1AYX@PI8HRL.AMPR.ORG ==*/
/*=========================================================================*/
start_controle++;
if(start_controle > 100){
if(bp->type == BT_TRANSMIT){
start_controle = 0;
for(i = 0 ; i < allocated_ibufs ; i++)
{
if(sccfreelist[i]->inuse == 1)
if(sccfreelist[i]->bp->type == BT_TRANSMIT)
if(sccfreelist[i]->bp->time_out < CURRENT_TIME)
{
sccfreelist[i]->bp->cnt = 0;
sccfreelist[i]->bp->refcnt = 0;
sccfreelist[i]->inuse = 0;
}
}
}
}
/*=========================================================================*/
/*== END OF THAT SILLY STUPID ROUTINE ==*/
/*=========================================================================*/
if (bp->dup)
{
for(i = 0 ; i < allocated_ibufs ; i++)
......@@ -481,13 +518,13 @@ scc_isr(int irq, struct pt_regs *regs)
if (Vector_Latch)
{
while(1) /* forever...? */
while(1)
{
Outb(Vector_Latch, 0); /* Generate INTACK */
/* Read the vector */
if((vector=Inb(Vector_Latch)) >= 16 * Nchips) break;
/* ...not forever! */
if((vector=Inb(Vector_Latch)) >= 16 * Nchips)
break;
/* Extract channel number and status from vector. */
/* Isolate channel nummer */
......@@ -618,21 +655,6 @@ scc_txint(register struct scc_channel *scc)
/* Throw away received mbuf(s) when an error occurred */
static inline void
scc_toss_buffer(register struct scc_channel *scc)
{
register struct mbuf *bp;
if((bp = scc->rbp) != NULLBUF)
{
scc_free_chain(bp->next, BT_RECEIVE);
bp->next = NULLBUF;
scc->rbp1 = bp; /* Don't throw this one away */
bp->cnt = 0; /* Simply rewind it */
bp->in_use = 0;
}
}
static inline void
flush_FIFO(register struct scc_channel *scc)
{
......@@ -640,18 +662,14 @@ flush_FIFO(register struct scc_channel *scc)
for (k=0; k<3; k++)
Inb(scc->data);
if(scc->rbp != NULLBUF) /* did we receive something? */
if(scc->rxbufcnt > 0)
{
if(scc->rbp->next != NULLBUF || scc->rbp->cnt > 0)
scc->stat.rxerrs++; /* then count it as an error */
scc_toss_buffer(scc); /* throw away buffer */
scc->stat.rxerrs++;
scc->rxbufcnt = 0; /* throw away frame */
}
}
/* External/Status interrupt handler */
static void
scc_exint(register struct scc_channel *scc)
......@@ -729,7 +747,7 @@ scc_exint(register struct scc_channel *scc)
static void
scc_rxint(register struct scc_channel *scc)
{
register struct mbuf *bp;
unsigned char ch;
scc->stat.rxints++;
......@@ -740,32 +758,36 @@ scc_rxint(register struct scc_channel *scc)
return;
}
if ((bp = scc->rbp1) == NULLBUF || bp->cnt >= bp->size)
{ /* no buffer available or buffer full */
if (scc->rbp == NULLBUF)
{
if ((bp = scc_get_buffer(BT_RECEIVE)) != NULLBUF)
scc->rbp = scc->rbp1 = bp;
}
else if ((bp = scc_get_buffer(BT_RECEIVE)))
{
scc_append_to_chain(&scc->rbp, bp);
scc->rbp1 = bp;
}
if (bp == NULLBUF) /* no buffer available? */
{
Inb(scc->data); /* discard character */
or(scc,R3,ENT_HM); /* enter hunt mode */
scc_toss_buffer(scc); /* throw away buffers */
scc->stat.nospace++; /* and count this error */
return;
}
if (scc->rxbufcnt > 2044) /* no buffer available? */
{
Inb(scc->data); /* discard character */
or(scc,R3,ENT_HM); /* enter hunt mode */
scc->rxbufcnt = 0; /* throw away frame */
scc->stat.nospace++; /* and count this error */
return;
}
if(scc->rxbufcnt == 0) /* make begin of kissframe */
{
scc->rxbuf[scc->rxbufcnt++] = FEND;
if (scc->kiss.not_slip)
scc->rxbuf[scc->rxbufcnt++] = 0;
}
switch( ch = Inb(scc->data) )
{
case FEND:
scc->rxbuf[scc->rxbufcnt++] = FESC;
scc->rxbuf[scc->rxbufcnt++] = TFEND;
break;
case FESC:
scc->rxbuf[scc->rxbufcnt++] = FESC;
scc->rxbuf[scc->rxbufcnt++] = TFESC;
break;
default:
scc->rxbuf[scc->rxbufcnt++] = ch;
}
/* now, we have a buffer. read character and store it */
bp->data[bp->cnt++] = Inb(scc->data);
}
......@@ -774,42 +796,82 @@ static void
scc_spint(register struct scc_channel *scc)
{
register unsigned char status;
register struct mbuf *bp;
int i;
unsigned char *cp;
char *fp;
int count;
scc->stat.spints++;
status = InReg(scc->ctrl,R1); /* read receiver status */
status = InReg(scc->ctrl,R1); /* read Special Receive Condition status */
Inb(scc->data); /* throw away Rx byte */
Inb(scc->data); /* read byte */
if(status & Rx_OVR) /* receiver overrun */
if(status & Rx_OVR) /* RX_OVerRrun? */
{
scc->stat.rx_over++; /* count them */
or(scc,R3,ENT_HM); /* enter hunt mode for next flag */
scc_toss_buffer(scc); /* rewind the buffer and toss */
scc->stat.rx_over++;
or(scc,R3,ENT_HM); /* enter hunt mode */
scc->rxbufcnt = 0; /* rewind the buffer */
}
if(status & END_FR && scc->rbp != NULLBUF) /* end of frame */
if(status & END_FR && scc->rxbufcnt != 0) /* END of FRame */
{
/* CRC okay, frame ends on 8 bit boundary and received something ? */
if (!(status & CRC_ERR) && (status & 0xe) == RES8 && scc->rbp->cnt)
if (!(status & CRC_ERR) && (status & 0xe) == RES8 && scc->rxbufcnt > 0)
{
/* ignore last received byte (first of the CRC bytes) */
scc->rxbufcnt--; /*strip the CRC */
scc->rxbuf[scc->rxbufcnt++] = FEND;
for(i = 0 ; i < scc->rxbufcnt ; i++)
{
if((scc->tty->flip.count + 1) < TTY_FLIPBUF_SIZE)
tty_insert_flip_char(scc->tty, scc->rxbuf[i], 0);
else {
if (scc->tty->flip.buf_num) {
cp = scc->tty->flip.char_buf + TTY_FLIPBUF_SIZE;
fp = scc->tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
scc->tty->flip.buf_num = 0;
scc->tty->flip.char_buf_ptr = scc->tty->flip.char_buf;
scc->tty->flip.flag_buf_ptr = scc->tty->flip.flag_buf;
} else {
cp = scc->tty->flip.char_buf;
fp = scc->tty->flip.flag_buf;
scc->tty->flip.buf_num = 1;
scc->tty->flip.char_buf_ptr = scc->tty->flip.char_buf + TTY_FLIPBUF_SIZE;
scc->tty->flip.flag_buf_ptr = scc->tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
}
count = scc->tty->flip.count;
scc->tty->flip.count = 0;
scc->tty->ldisc.receive_buf(scc->tty, cp, fp, count);
tty_insert_flip_char(scc->tty, scc->rxbuf[i], 0);
}
}
if (scc->tty->flip.buf_num) {
cp = scc->tty->flip.char_buf + TTY_FLIPBUF_SIZE;
fp = scc->tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
scc->tty->flip.buf_num = 0;
scc->tty->flip.char_buf_ptr = scc->tty->flip.char_buf;
scc->tty->flip.flag_buf_ptr = scc->tty->flip.flag_buf;
} else {
cp = scc->tty->flip.char_buf;
fp = scc->tty->flip.flag_buf;
scc->tty->flip.buf_num = 1;
scc->tty->flip.char_buf_ptr = scc->tty->flip.char_buf + TTY_FLIPBUF_SIZE;
scc->tty->flip.flag_buf_ptr = scc->tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
}
count = scc->tty->flip.count;
scc->tty->flip.count = 0;
scc->tty->ldisc.receive_buf(scc->tty, cp, fp, count);
scc->stat.rxframes++;
scc->rxbufcnt = 0;
for (bp = scc->rbp; bp->next != NULLBUF; bp = bp->next) ;
bp->cnt--; /* last byte is first CRC byte */
scc_enqueue(&scc->rcvq,scc->rbp);
scc->rbp = scc->rbp1 = NULLBUF;
scc->stat.rxframes++;
scc->stat.rx_queued++;
} else { /* a bad frame */
scc_toss_buffer(scc); /* throw away frame */
} else {
scc->rxbufcnt = 0; /* frame is not good */
scc->stat.rxerrs++;
}
}
}
Outb(scc->ctrl,ERR_RES);
}
......@@ -934,7 +996,7 @@ init_channel(register struct scc_channel *scc)
Outb(scc->ctrl,RES_EXT_INT); /* must be done twice */
scc->status = InReg(scc->ctrl,R0); /* read initial status */
scc->rxbufcnt = 0;
or(scc,R1,INT_ALL_Rx|TxINT_ENAB|EXT_INT_ENAB); /* enable interrupts */
or(scc,R9,MIE); /* master interrupt enable */
......@@ -1142,42 +1204,13 @@ static inline void maxk_idle_timeout(register struct scc_channel *scc)
scc->t_tail = scc->kiss.tailtime;
}
static inline void check_rcv_queue(register struct scc_channel *scc)
{
register struct mbuf *bp;
if (scc->stat.rx_queued > QUEUE_THRES)
{
if (scc->rcvq == NULLBUF)
{
printk("z8530drv: Warning - scc->stat.rx_queued shows overflow"
" (%d) but queue is empty\n", scc->stat.rx_queued);
scc->stat.rx_queued = 0; /* correct it */
scc->stat.nospace = 12345; /* draw attention to it */
return;
}
bp = scc->rcvq->anext; /* don't use the one we currently use */
while (bp && (scc->stat.rx_queued > QUEUE_HYST))
{
bp = scc_free_chain(bp, BT_RECEIVE);
scc->stat.rx_queued--;
scc->stat.nospace++;
}
scc->rcvq->anext = bp;
}
}
static void
scc_timer(void)
{
register struct scc_channel *scc;
register int chan;
unsigned long flags;
save_flags(flags); cli();
for (chan = 0; chan < (Nchips * 2); chan++)
......@@ -1186,11 +1219,7 @@ scc_timer(void)
if (scc->tty && scc->init)
{
kiss_encode(scc);
check_rcv_queue(scc);
/* KISS-TNC emulation */
if (Expired(t_dwait)) dw_slot_timeout(scc) ; else
if (Expired(t_slot)) dw_slot_timeout(scc) ; else
if (Expired(t_txdel)) txdel_timeout(scc) ; else
......@@ -1201,8 +1230,10 @@ scc_timer(void)
if (Expired(t_mbusy)) busy_timeout(scc);
if (Expired(t_maxk)) maxk_idle_timeout(scc);
if (Expired(t_idle)) maxk_idle_timeout(scc);
}
}
timer_table[SCC_TIMER].fn = scc_timer;
timer_table[SCC_TIMER].expires = jiffies + HZ/TPS;
......@@ -1259,7 +1290,7 @@ kiss_set_param(struct scc_channel *scc,char cmd, unsigned int val)
case PARAM_TXTAIL:
scc->kiss.tailtime = VAL; break;
case PARAM_FULLDUP:
scc->kiss.fulldup = val; break;
scc->kiss.fulldup = val; break;
case PARAM_WAIT:
scc->kiss.waittime = VAL; break;
case PARAM_MAXKEY:
......@@ -1423,97 +1454,6 @@ static inline int kiss_decode(struct scc_channel *scc, unsigned char ch)
}
/* ----> Encode received data and write it to the flip-buffer <---- */
/* receive raw frame from SCC. used for AX.25 */
static void
kiss_encode(register struct scc_channel *scc)
{
struct mbuf *bp,*bp2;
struct tty_struct * tty = scc->tty;
unsigned long flags;
unsigned char ch;
if(!scc->rcvq)
{
scc->stat.rx_kiss_state = KISS_IDLE;
return;
}
/* worst case: FEND 0 FESC TFEND -> 4 bytes */
while(tty->flip.count < TTY_FLIPBUF_SIZE-3)
{
if (scc->rcvq->cnt)
{
bp = scc->rcvq;
if (scc->stat.rx_kiss_state == KISS_IDLE)
{
tty_insert_flip_char(tty, FEND, 0);
if (scc->kiss.not_slip)
tty_insert_flip_char(tty, 0, 0);
scc->stat.rx_kiss_state = KISS_RXFRAME;
}
switch(ch = bp->data[bp->in_use++])
{
case FEND:
tty_insert_flip_char(tty, FESC, 0);
tty_insert_flip_char(tty, TFEND, 0);
break;
case FESC:
tty_insert_flip_char(tty, FESC, 0);
tty_insert_flip_char(tty, TFESC, 0);
break;
default:
tty_insert_flip_char(tty, ch, 0);
}
bp->cnt--;
} else {
save_flags(flags); cli();
while (!scc->rcvq->cnt)
{ /* buffer empty? */
bp = scc->rcvq->next; /* next buffer */
bp2 = scc->rcvq->anext; /* next packet */
scc_return_buffer(scc->rcvq, BT_RECEIVE);
if (!bp) /* end of frame ? */
{
scc->rcvq = bp2;
if (--scc->stat.rx_queued < 0)
scc->stat.rx_queued = 0;
if (scc->stat.rx_kiss_state == KISS_RXFRAME) /* new packet? */
{
tty_insert_flip_char(tty, FEND, 0); /* send FEND for old frame */
scc->stat.rx_kiss_state = KISS_IDLE; /* generate FEND for new frame */
}
restore_flags(flags);
queue_task(&tty->flip.tqueue, &tq_timer);
return;
} else scc->rcvq = bp; /* next buffer */
}
restore_flags(flags);
}
}
queue_task(&tty->flip.tqueue, &tq_timer); /* kick it... */
}
/* ******************************************************************* */
/* * Init channel structures, special HW, etc... * */
/* ******************************************************************* */
......@@ -1523,11 +1463,10 @@ static void
z8530_init(void)
{
struct scc_channel *scc;
int chip,chan;
int chip;
unsigned long flags;
int k;
/* reset and pre-init all chips in the system */
/* reset all scc chips */
for (chip = 0; chip < Nchips; chip++)
{
/* Special SCC cards */
......@@ -1538,30 +1477,25 @@ z8530_init(void)
if(Board & (PC100 | PRIMUS)) /* this is a PC100/EAGLE card */
Outb(Special_Port,Option); /* set the MODEM mode (22H normally) */
/* Init SCC */
scc=&SCC_Info[2*chip];
if (!scc->ctrl) continue;
save_flags(flags); cli();
Outb(scc->ctrl, 0);
OutReg(scc->ctrl,R9,FHWRES); /* force hardware reset */
for (k=1; k < 1000; k++) ;
for (chan = 0; chan < 2; chan++)
{
scc=&SCC_Info[2*chip+chan];
wr(scc,R1, 0);
wr(scc,R2, chip*16); /* No of chip is vector */
wr(scc,R9,VIS); /* vector includes status */
}
OutReg(scc->ctrl,R9,FHWRES); /* force hardware reset */
OutReg(scc->ctrl,R9,0); /* end hardware reset */
OutReg(scc->ctrl,R9,CHRA); /* reset channel A */
OutReg(scc->ctrl,R9,CHRB); /* reset channel B */
OutReg(scc->ctrl,R1, 0); /* No Rx irq from channel A */
scc=&SCC_Info[2*chip+1];
OutReg(scc->ctrl,R1, 0); /* No Rx irq from channel B */
scc=&SCC_Info[2*chip];
OutReg(scc->ctrl,R2, chip*16); /* Set Interrupt vector */
restore_flags(flags);
}
if (Ivec == 2) Ivec = 9; /* this f... IBM AT-design! */
if (Ivec == 2) Ivec = 9;
request_irq(Ivec, scc_isr, SA_INTERRUPT, "AX.25 SCC");
Driver_Initialized = 1;
......@@ -1613,6 +1547,9 @@ int scc_open(struct tty_struct *tty, struct file * filp)
scc = &SCC_Info[chan];
tty->driver_data = scc;
tty->termios->c_iflag = IGNBRK | IGNPAR;
tty->termios->c_cflag = B9600 | CS8 | CLOCAL;
tty->termios->c_cflag &= ~CBAUD;
if (!Driver_Initialized)
......@@ -1643,7 +1580,28 @@ int scc_open(struct tty_struct *tty, struct file * filp)
timer_table[SCC_TIMER].fn = scc_timer;
timer_table[SCC_TIMER].expires = 0; /* now! */
timer_active |= 1 << SCC_TIMER;
/*====================new pe1ayx====================
planed for the new TX routines
if (!scc->xmit_buf) {
scc->xmit_buf = (unsigned char *) get_free_page(GFP_KERNEL);
if (!scc->xmit_buf)
return -ENOMEM;
}
scc->xmit_cnt = scc->xmit_head = scc->xmit_tail = 0;
====================new pe1ayx end================*/
if (!tmp_buf) {
tmp_buf = (unsigned char *) get_free_page(GFP_KERNEL);
if (!tmp_buf)
return -ENOMEM;
}
return 0;
}
......@@ -1796,7 +1754,7 @@ scc_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned
scc->kiss.softdcd = 0; /* hardware dcd */
}
scc->init = 1;
scc->init = 1;
return 0;
}
......@@ -1821,7 +1779,7 @@ scc_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned
restore_flags(flags);
put_user(result,(unsigned int *) arg);
put_fs_long(result,(unsigned long *) arg);
return 0;
case TIOCMBIS:
case TIOCMBIC:
......@@ -1836,7 +1794,7 @@ scc_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned
scc->wreg[R5] &= ~RTS;
break;
case TIOCMSET:
value = get_user((unsigned int *) arg);
value = get_fs_long((unsigned long *) arg);
if(value & TIOCM_DTR)
scc->wreg[R5] |= DTR;
......@@ -2022,6 +1980,7 @@ static inline void check_tx_queue(register struct scc_channel *scc)
scc->sndq1->anext = bp;
}
}
......@@ -2031,12 +1990,14 @@ static inline void check_tx_queue(register struct scc_channel *scc)
/* send raw frame to SCC. used for AX.25 */
int scc_write(struct tty_struct *tty, int from_user, unsigned char *buf, int count)
{
unsigned long flags;
static unsigned char *p;
struct scc_channel * scc = tty->driver_data;
unsigned char tbuf[BUFSIZE], *p;
int cnt, cnt2;
if (!tty) return count;
if (!tty || !tmp_buf)
return 0;
if (scc_paranoia_check(scc, tty->device, "scc_write"))
return 0;
......@@ -2044,31 +2005,43 @@ int scc_write(struct tty_struct *tty, int from_user, unsigned char *buf, int cou
check_tx_queue(scc);
save_flags(flags);
cnt2 = count;
while (cnt2)
{
cnt = cnt2 > BUFSIZE? BUFSIZE:cnt2;
cli();
cnt = cnt2 > SERIAL_XMIT_SIZE? SERIAL_XMIT_SIZE:cnt2;
cnt2 -= cnt;
if (from_user)
memcpy_fromfs(tbuf, buf, cnt);
if (from_user){
down(&tmp_buf_sem);
memcpy_fromfs(tmp_buf, buf, cnt);
up(&tmp_buf_sem);
}
else
memcpy(tbuf, buf, cnt);
memcpy(tmp_buf, buf, cnt);
buf += cnt;
p=tbuf;
p=tmp_buf;
while(cnt--)
if (kiss_decode(scc, *p++))
{
scc->stat.nospace++;
restore_flags(flags);
return 0;
}
} /* while cnt2 */
if ((scc->tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
&& scc->tty->ldisc.write_wakeup)
(scc->tty->ldisc.write_wakeup)(scc->tty);
restore_flags(flags);
return count;
}
......@@ -2092,7 +2065,7 @@ static void scc_flush_chars(struct tty_struct * tty)
struct scc_channel *scc = tty->driver_data;
scc_paranoia_check(scc, tty->device, "scc_flush_chars"); /* just to annoy the user... */
return; /* no flush needed */
}
......@@ -2101,7 +2074,7 @@ static void scc_flush_chars(struct tty_struct * tty)
static int scc_write_room(struct tty_struct *tty)
{
struct scc_channel *scc = tty->driver_data;
if (scc_paranoia_check(scc, tty->device, "scc_write_room"))
return 0;
......@@ -2117,7 +2090,7 @@ static int scc_write_room(struct tty_struct *tty)
static int scc_chars_in_buffer(struct tty_struct *tty)
{
struct scc_channel *scc = tty->driver_data;
if (scc && scc->sndq2)
return scc->sndq2->cnt;
else
......@@ -2127,37 +2100,35 @@ static int scc_chars_in_buffer(struct tty_struct *tty)
static void scc_flush_buffer(struct tty_struct *tty)
{
struct scc_channel *scc = tty->driver_data;
if (scc_paranoia_check(scc, tty->device, "scc_flush_buffer"))
return;
scc->stat.tx_kiss_state = KISS_IDLE;
wake_up_interruptible(&tty->write_wait);
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
tty->ldisc.write_wakeup)
(tty->ldisc.write_wakeup)(tty);
}
static void scc_throttle(struct tty_struct *tty)
{
struct scc_channel *scc = tty->driver_data;
if (scc_paranoia_check(scc, tty->device, "scc_throttle"))
return;
/* dummy */
}
static void scc_unthrottle(struct tty_struct *tty)
{
struct scc_channel *scc = tty->driver_data;
if (scc_paranoia_check(scc, tty->device, "scc_unthrottle"))
return;
/* dummy */
}
static void scc_start(struct tty_struct *tty)
......@@ -2181,6 +2152,14 @@ static void scc_stop(struct tty_struct *tty)
/* dummy */
}
void scc_hangup(struct tty_struct *tty)
{
struct scc_channel *scc = tty->driver_data;
if (scc_paranoia_check(scc, tty->device, "scc_hangup"))
return;
}
/* ******************************************************************** */
/* * Init SCC driver * */
......@@ -2188,7 +2167,11 @@ static void scc_stop(struct tty_struct *tty)
long scc_init (long kmem_start)
{
int chip, chan;
int chip;
#ifdef VERBOSE_BOOTMSG
int chan;
#endif
register io_port ctrl;
long flags;
......@@ -2200,31 +2183,31 @@ long scc_init (long kmem_start)
scc_driver.minor_start = 96;
scc_driver.num = Nchips*2;
scc_driver.type = TTY_DRIVER_TYPE_SERIAL;
scc_driver.subtype = 0; /* not needed */
scc_driver.subtype = SERIAL_TYPE_NORMAL; /* not needed */
scc_driver.init_termios = tty_std_termios;
scc_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
scc_driver.init_termios.c_iflag = IGNBRK | IGNPAR;
scc_driver.init_termios.c_cflag = B9600 | CS8 | CLOCAL;
scc_driver.flags = TTY_DRIVER_REAL_RAW;
scc_driver.refcount = &scc_refcount; /* not needed yet */
scc_driver.table = scc_table;
scc_driver.termios = (struct termios **) scc_termios;
scc_driver.termios_locked = (struct termios **) scc_termios_locked;
scc_driver.open = scc_open;
scc_driver.close = scc_close;
scc_driver.write = scc_write;
scc_driver.start = scc_start;
scc_driver.stop = scc_stop;
scc_driver.put_char = scc_put_char;
scc_driver.flush_chars = scc_flush_chars;
scc_driver.write_room = scc_write_room;
scc_driver.chars_in_buffer = scc_chars_in_buffer;
scc_driver.flush_buffer = scc_flush_buffer;
scc_driver.ioctl = scc_ioctl;
scc_driver.throttle = scc_throttle;
scc_driver.unthrottle = scc_unthrottle;
scc_driver.ioctl = scc_ioctl;
scc_driver.set_termios = scc_set_termios;
scc_driver.stop = scc_stop;
scc_driver.start = scc_start;
scc_driver.hangup = scc_hangup;
if (tty_register_driver(&scc_driver))
panic("Couldn't register Z8530 SCC driver\n");
......
......@@ -42,6 +42,8 @@ endif
ifdef CONFIG_HP100
NETDRV_OBJS := $(NETDRV_OBJS) hp100.o
else
MODULES := $(MODULES) hp100.o
endif
ifdef CONFIG_WD80x3
......
......@@ -65,6 +65,7 @@
* 0.11 14-Jun-95 Reset interface bug fixed?
* Little bug in hp100_close function fixed.
* 100Mb/s connection debugged.
* 0.12 14-Jul-95 Link down is now handled better.
*
*/
......@@ -350,12 +351,6 @@ static int hp100_open( struct device *dev )
int ioaddr = dev -> base_addr;
struct hp100_private *lp = (struct hp100_private *)dev -> priv;
if ( ( lp -> lan_type = hp100_sense_lan( dev ) ) < 0 )
{
printk( "%s: no connection found - check wire\n", dev -> name );
return -EIO;
}
if ( request_irq( dev -> irq, hp100_interrupt, SA_INTERRUPT, lp -> id -> name ) )
{
printk( "%s: unable to get IRQ %d\n", dev -> name, dev -> irq );
......@@ -372,6 +367,7 @@ static int hp100_open( struct device *dev )
dev -> interrupt = 0;
dev -> start = 1;
lp -> lan_type = hp100_sense_lan( dev );
lp -> mac1_mode = HP100_MAC1MODE3;
lp -> mac2_mode = HP100_MAC2MODE3;
......@@ -424,11 +420,11 @@ static int hp100_close( struct device *dev )
struct hp100_private *lp = (struct hp100_private *)dev -> priv;
hp100_page( PERFORMANCE );
hp100_outw( 0xfefe, IRQ_MASK ); /* mask off all ints */
hp100_outw( 0xfefe, IRQ_MASK ); /* mask off all IRQs */
hp100_stop_interface( dev ); /* relogin */
hp100_stop_interface( dev );
if ( lp -> lan_type == HP100_LAN_100 )
if ( lp -> lan_type == HP100_LAN_100 ) /* relogin */
hp100_login_to_vg_hub( dev );
dev -> tbusy = 1;
......@@ -452,6 +448,20 @@ static int hp100_start_xmit( struct sk_buff *skb, struct device *dev )
int ioaddr = dev -> base_addr;
u_short val;
struct hp100_private *lp = (struct hp100_private *)dev -> priv;
if ( lp -> lan_type < 0 )
{
hp100_stop_interface( dev );
if ( ( lp -> lan_type = hp100_sense_lan( dev ) ) < 0 )
{
printk( "%s: no connection found - check wire\n", dev -> name );
hp100_start_interface( dev ); /* 10Mb/s RX packets maybe handled */
return -EIO;
}
if ( lp -> lan_type == HP100_LAN_100 )
lp -> hub_status = hp100_login_to_vg_hub( dev );
hp100_start_interface( dev );
}
if ( ( i = ( hp100_inl( TX_MEM_FREE ) & ~0x7fffffff ) ) < skb -> len + 16 )
{
......@@ -463,11 +473,9 @@ static int hp100_start_xmit( struct sk_buff *skb, struct device *dev )
/* 100Mb/s adapter isn't connected to hub */
{
printk( "%s: login to 100Mb/s hub retry\n", dev -> name );
hp100_ints_off();
hp100_stop_interface( dev );
lp -> hub_status = hp100_login_to_vg_hub( dev );
hp100_start_interface( dev );
hp100_ints_on();
}
else
{
......@@ -483,20 +491,16 @@ static int hp100_start_xmit( struct sk_buff *skb, struct device *dev )
/* it's very heavy - all network setting must be changed!!! */
printk( "%s: cable change 10Mb/s <-> 100Mb/s detected\n", dev -> name );
lp -> lan_type = i;
hp100_ints_off();
hp100_stop_interface( dev );
if ( lp -> lan_type == HP100_LAN_100 )
lp -> hub_status = hp100_login_to_vg_hub( dev );
hp100_start_interface( dev );
hp100_ints_on();
}
else
{
printk( "%s: interface reset\n", dev -> name );
hp100_ints_off();
hp100_stop_interface( dev );
hp100_start_interface( dev );
hp100_ints_on();
}
}
dev -> trans_start = jiffies;
......@@ -566,6 +570,15 @@ static void hp100_rx( struct device *dev )
u_int header;
struct sk_buff *skb;
#if 0
if ( lp -> lan_type < 0 )
{
if ( ( lp -> lan_type = hp100_sense_lan( dev ) ) == HP100_LAN_100 )
lp -> hub_status = hp100_login_to_vg_hub( dev );
hp100_page( PERFORMANCE );
}
#endif
packets = hp100_inb( RX_PKT_CNT );
#ifdef HP100_DEBUG
if ( packets > 1 )
......@@ -730,6 +743,7 @@ static void hp100_interrupt( int irq )
printk( "%s: re-entering the interrupt handler\n", dev -> name );
hp100_ints_off();
dev -> interrupt = 1;
hp100_page( PERFORMANCE );
val = hp100_inw( IRQ_STATUS );
#ifdef HP100_DEBUG_IRQ
printk( "hp100_interrupt: irq_status = 0x%x\n", val );
......
......@@ -49,6 +49,7 @@
April 23, 1995 (dp) Fixed ioctl so it works properly with piconfig program
when changing the baud rate or clock mode.
version 0.8 ALPHA
July 17, 1995 (ac) Finally polishing of AX25.030+ support
*/
......@@ -59,7 +60,7 @@
of each transmitted packet. If this causes you to lose sleep, #undefine it.
*/
#define STUFF2 1
/*#define STUFF2 1*/
/* The default configuration */
#define PI_DMA 3
......@@ -1429,10 +1430,10 @@ static int pi_probe(struct device *dev, int card_type)
dev->rebuild_header = pi_rebuild_header;
dev->set_mac_address = pi_set_mac_address;
dev->type = ARPHRD_AX25; /* AF_AX25 device */
dev->hard_header_len = 17; /* We don't do digipeaters */
dev->mtu = 1500; /* eth_mtu is the default */
dev->addr_len = 7; /* sizeof an ax.25 address */
dev->type = ARPHRD_AX25; /* AF_AX25 device */
dev->hard_header_len = 73; /* We do digipeaters now */
dev->mtu = 1500; /* eth_mtu is the default */
dev->addr_len = 7; /* sizeof an ax.25 address */
memcpy(dev->broadcast, ax25_bcast, 7);
memcpy(dev->dev_addr, ax25_test, 7);
......
......@@ -36,6 +36,7 @@
* statistics. Include CSLIP code only
* if it really needed.
* Alan Cox : Free slhc buffers in the right place.
* Alan Cox : Allow for digipeated IP over AX.25
*
*
*
......@@ -1014,7 +1015,7 @@ slip_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
#else
if ((tmp & SL_MODE_AX25) || (tmp & SL_MODE_AX25VC)) {
sl->dev->addr_len=AX25_ADDR_LEN; /* sizeof an AX.25 addr */
sl->dev->hard_header_len=AX25_HEADER_LEN; /* We don't do digipeaters */
sl->dev->hard_header_len=73; /* We don't do digipeaters */
} else {
sl->dev->addr_len=0; /* No mac addr in slip mode */
sl->dev->hard_header_len=0;
......
......@@ -3,36 +3,24 @@
*
* Copyright (c) 1994 John Aycock
* The University of Calgary Department of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of Calgary
* Department of Computer Science and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* An alternate version of this driver with a BSD-style copyright can
* be found on XXX.
*
* 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.
*
* Sources include the Adaptec 1740 driver (aha1740.c), the Ultrastor 24F
* driver (ultrastor.c), various Linux kernel source, the Adaptec EISA
* config file (!adp7771.cfg), the Adaptec AHA-2740A Series User's Guide,
......
......@@ -3,36 +3,24 @@
*
* Copyright (c) 1994 John Aycock
* The University of Calgary Department of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of Calgary
* Department of Computer Science and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* An alternate version of this driver with a BSD-style copyright can
* be found on XXX.
*
* $Id: aic7xxx.h,v 1.18 1995/06/22 04:17:56 deang Exp $
*-M*************************************************************************/
#ifndef _aic7xxx_h
......
......@@ -3,35 +3,23 @@
*
* Copyright (c) 1994 John Aycock
* The University of Calgary Department of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of Calgary
* Department of Computer Science and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* An alternate version of this driver with a BSD-style copyright can
* be found on XXX.
*
* Comments are started by `#' and continue to the end of the line; lines
* may be of the form:
......
/************************************************************
* *
* Linux EATA SCSI driver *
* *
* based on the CAM document CAM/89-004 rev. 2.0c, *
* *
* Linux EATA SCSI driver *
* *
* based on the CAM document CAM/89-004 rev. 2.0c, *
* DPT's driver kit, some internal documents and source, *
* and several other Linux scsi drivers and kernel docs. *
* *
* The driver currently: *
* -supports all ISA based EATA-DMA boards *
* -supports all EISA based EATA-DMA boards *
* -supports all PCI based EATA-DMA boards *
* -supports multiple HBAs with & without IRQ sharing *
* -supports all SCSI channels on multi channel boards *
* -can be loaded as module *
* -displays statistical and hardware information *
* in /proc/scsi/eata_dma *
* -needs identical HBA ids on all channels *
* *
* (c)1993,94,95 Michael Neuffer *
* neuffer@goofy.zdv.uni-mainz.de *
* *
* *
* The driver currently: *
* -supports all ISA based EATA-DMA boards *
* -supports all EISA based EATA-DMA boards *
* -supports all PCI based EATA-DMA boards *
* -supports multiple HBAs with & without IRQ sharing *
* -supports all SCSI channels on multi channel boards *
* -needs identical IDs on all channels of a HBA *
* -can be loaded as module *
* -displays statistical and hardware information *
* in /proc/scsi/eata_dma *
* -provides rudimentary latency measurement *
* possibilities via /proc/scsi/eata_dma/<hostnum> *
* *
* (c)1993,94,95 Michael Neuffer *
* neuffer@goofy.zdv.uni-mainz.de *
* *
* This program is free software; you can redistribute it *
* and/or modify it under the terms of the GNU General *
* Public License as published by the Free Software *
* Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* and/or modify it under the terms of the GNU General *
* Public License as published by the Free Software *
* Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be *
* useful, but WITHOUT ANY WARRANTY; without even the *
* useful, but WITHOUT ANY WARRANTY; without even the *
* implied warranty of MERCHANTABILITY or FITNESS FOR A *
* PARTICULAR PURPOSE. See the GNU General Public License *
* for more details. *
* *
* You should have received a copy of the GNU General *
* PARTICULAR PURPOSE. See the GNU General Public License *
* for more details. *
* *
* You should have received a copy of the GNU General *
* Public License along with this kernel; if not, write to *
* the Free Software Foundation, Inc., 675 Mass Ave, *
* Cambridge, MA 02139, USA. *
* *
* the Free Software Foundation, Inc., 675 Mass Ave, *
* Cambridge, MA 02139, USA. *
* *
* I have to thank DPT for their excellent support. I took *
* me almost a year and a stopover at their HQ, on my first *
* trip to the USA, to get it, but since then they've been *
* very helpful and tried to give me all the infos and *
* support I need. *
* *
* very helpful and tried to give me all the infos and *
* support I need. *
* *
* Thanks also to Greg Hosler who did a lot of testing and *
* found quite a number of bugs during the development. *
* found quite a number of bugs during the development. *
************************************************************
* last change: 95/06/28 OS: Linux 1.3.4 + pre1.3 SCSI pat.*
* last change: 95/07/11 OS: Linux 1.3.9 *
************************************************************/
/* Look in eata_dma.h for configuration and revision information */
......@@ -205,13 +207,33 @@ void eata_int_handler(int irq, struct pt_regs * regs)
eata_stat, hba_stat));
switch (hba_stat) {
case HA_NO_ERROR: /* NO Error */
case HA_NO_ERROR: /* NO Error */
if (scsi_stat == CONDITION_GOOD
&& cmd->device->type == TYPE_DISK
&& (HD(cmd)->t_state[cp->cp_channel][cp->cp_id] == RESET))
result = DID_BUS_BUSY << 16;
else if (scsi_stat == GOOD)
result = DID_BUS_BUSY << 16;
else if (scsi_stat == GOOD) {
HD(cmd)->t_state[cp->cp_channel][cp->cp_id] = OK;
if(HD(cmd)->do_latency == TRUE && cp->timestamp) {
uint time;
time = jiffies - cp->timestamp;
if((cp->rw_latency) == TRUE) { /* was WRITE */
if(HD(cmd)->writes_lat[cp->sizeindex][1] > time)
HD(cmd)->writes_lat[cp->sizeindex][1] = time;
if(HD(cmd)->writes_lat[cp->sizeindex][2] < time)
HD(cmd)->writes_lat[cp->sizeindex][2] = time;
HD(cmd)->writes_lat[cp->sizeindex][3] += time;
HD(cmd)->writes_lat[cp->sizeindex][0]++;
} else {
if(HD(cmd)->reads_lat[cp->sizeindex][1] > time)
HD(cmd)->reads_lat[cp->sizeindex][1] = time;
if(HD(cmd)->reads_lat[cp->sizeindex][2] < time)
HD(cmd)->reads_lat[cp->sizeindex][2] = time;
HD(cmd)->reads_lat[cp->sizeindex][3] += time;
HD(cmd)->reads_lat[cp->sizeindex][0]++;
}
}
}
else if (scsi_stat == CHECK_CONDITION
&& cmd->device->type == TYPE_DISK
&& (cmd->sense_buffer[2] & 0xf) == RECOVERED_ERROR)
......@@ -220,10 +242,10 @@ void eata_int_handler(int irq, struct pt_regs * regs)
result = DID_OK << 16;
HD(cmd)->t_timeout[cp->cp_channel][cp->cp_id] = OK;
break;
case HA_ERR_SEL_TO: /* Selection Timeout */
case HA_ERR_SEL_TO: /* Selection Timeout */
result = DID_BAD_TARGET << 16;
break;
case HA_ERR_CMD_TO: /* Command Timeout */
case HA_ERR_CMD_TO: /* Command Timeout */
if (HD(cmd)->t_timeout[cp->cp_channel][cp->cp_id] > 1)
result = DID_ERROR << 16;
else {
......@@ -231,8 +253,8 @@ void eata_int_handler(int irq, struct pt_regs * regs)
HD(cmd)->t_timeout[cp->cp_channel][cp->cp_id]++;
}
break;
case HA_ERR_RESET: /* SCSI Bus Reset Received */
case HA_INIT_POWERUP: /* Initial Controller Power-up */
case HA_ERR_RESET: /* SCSI Bus Reset Received */
case HA_INIT_POWERUP: /* Initial Controller Power-up */
if (cmd->device->type != TYPE_TAPE)
result = DID_BUS_BUSY << 16;
else
......@@ -241,14 +263,14 @@ void eata_int_handler(int irq, struct pt_regs * regs)
for (i = 0; i < MAXTARGET; i++)
HD(cmd)->t_state[cp->cp_channel][i] = RESET;
break;
case HA_UNX_BUSPHASE: /* Unexpected Bus Phase */
case HA_UNX_BUS_FREE: /* Unexpected Bus Free */
case HA_BUS_PARITY: /* Bus Parity Error */
case HA_SCSI_HUNG: /* SCSI Hung */
case HA_UNX_MSGRJCT: /* Unexpected Message Reject */
case HA_RESET_STUCK: /* SCSI Bus Reset Stuck */
case HA_RSENSE_FAIL: /* Auto Request-Sense Failed */
case HA_PARITY_ERR: /* Controller Ram Parity */
case HA_UNX_BUSPHASE: /* Unexpected Bus Phase */
case HA_UNX_BUS_FREE: /* Unexpected Bus Free */
case HA_BUS_PARITY: /* Bus Parity Error */
case HA_SCSI_HUNG: /* SCSI Hung */
case HA_UNX_MSGRJCT: /* Unexpected Message Reject */
case HA_RESET_STUCK: /* SCSI Bus Reset Stuck */
case HA_RSENSE_FAIL: /* Auto Request-Sense Failed */
case HA_PARITY_ERR: /* Controller Ram Parity */
default:
result = DID_ERROR << 16;
break;
......@@ -267,7 +289,7 @@ void eata_int_handler(int irq, struct pt_regs * regs)
DBG(DBG_INTR&&DBG_DELAY,DEL2(800));
#endif
cp->status = FREE; /* now we can release the slot */
cp->status = FREE; /* now we can release the slot */
restore_flags(flags);
if(cmd->scsi_done != eata_scsi_done) cmd->scsi_done(cmd);
......@@ -291,7 +313,7 @@ inline int eata_send_command(u32 addr, u32 base, u8 command)
if (--loop == 0)
return(FALSE);
outb( addr & 0x000000ff, base + HA_WDMAADDR);
outb( addr & 0x000000ff, base + HA_WDMAADDR);
outb((addr & 0x0000ff00) >> 8, base + HA_WDMAADDR + 1);
outb((addr & 0x00ff0000) >> 16, base + HA_WDMAADDR + 2);
outb((addr & 0xff000000) >> 24, base + HA_WDMAADDR + 3);
......@@ -304,8 +326,8 @@ inline int eata_send_immediate(u32 addr, u32 base, u8 cmnd, u8 cmnd2, u8 id,
u8 lun)
{
if(addr){
outb( addr & 0x000000ff, base + HA_WDMAADDR);
outb((addr & 0x0000ff00) >> 8, base + HA_WDMAADDR + 1);
outb( addr & 0x000000ff, base + HA_WDMAADDR);
outb((addr & 0x0000ff00) >> 8, base + HA_WDMAADDR + 1);
outb((addr & 0x00ff0000) >> 16, base + HA_WDMAADDR + 2);
outb((addr & 0xff000000) >> 24, base + HA_WDMAADDR + 3);
} else {
......@@ -314,7 +336,7 @@ inline int eata_send_immediate(u32 addr, u32 base, u8 cmnd, u8 cmnd2, u8 id,
}
outb(cmnd2, base + HA_WCOMMAND2);
outb(cmnd, base + HA_WCOMMAND);
outb(cmnd, base + HA_WCOMMAND);
return(TRUE);
}
#endif
......@@ -327,10 +349,10 @@ int eata_queue(Scsi_Cmnd * cmd, void (* done) (Scsi_Cmnd *))
struct Scsi_Host *sh;
struct eata_ccb *cp;
struct scatterlist *sl;
save_flags(flags);
cli();
queue_counter++;
if (done == (void *)eata_scsi_done) {
......@@ -354,61 +376,93 @@ int eata_queue(Scsi_Cmnd * cmd, void (* done) (Scsi_Cmnd *))
hd->last_ccb = y;
if (x == sh->can_queue) {
DBG(DBG_QUEUE, printk("can_queue %d, x %d, y %d\n",
sh->can_queue, x, y));
#if DEBUG_EATA
panic("eata_dma: run out of queue slots cmdno:%ld intrno: %ld\n",
queue_counter, int_counter);
#else
panic("eata_dma: run out of queue slots....\n");
#endif
}
cp = &hd->ccb[y];
memset(cp, 0, sizeof(struct eata_ccb) - sizeof(struct eata_sg_list *));
cp->status = USED; /* claim free slot */
cp->status = USED; /* claim free slot */
DBG(DBG_QUEUE, printk("eata_queue pid %ld, target: %x, lun: %x, y %d\n",
cmd->pid, cmd->target, cmd->lun, y));
DBG(DBG_QUEUE && DBG_DELAY, DEL2(250));
if(hd->do_latency == TRUE) {
int x, z;
short *sho;
long *lon;
x = 0; /* just to keep GCC quiet */
if (cmd->cmnd[0] == WRITE_6 || cmd->cmnd[0] == WRITE_10 ||
cmd->cmnd[0] == WRITE_12 || cmd->cmnd[0] == READ_6 ||
cmd->cmnd[0] == READ_10 || cmd->cmnd[0] == READ_12) {
cp->timestamp = jiffies; /* For latency measurements */
switch(cmd->cmnd[0]) {
case WRITE_6:
case READ_6:
x = cmd->cmnd[4]/2;
break;
case WRITE_10:
case READ_10:
sho = (short *) &cmd->cmnd[7];
x = ntohs(*sho)/2;
break;
case WRITE_12:
case READ_12:
lon = (long *) &cmd->cmnd[6];
x = ntohl(*lon)/2;
break;
}
for(z = 0; z <= 11, x > (1 << z); z++)
/* nothing */;
cp->sizeindex = z;
if (cmd->cmnd[0] == WRITE_6 || cmd->cmnd[0] == WRITE_10 ||
cmd->cmnd[0] == WRITE_12){
cp->rw_latency = TRUE;
}
}
}
cmd->scsi_done = (void *)done;
switch (cmd->cmnd[0]) {
case CHANGE_DEFINITION: case COMPARE: case COPY:
case COPY_VERIFY: case LOG_SELECT: case MODE_SELECT:
case CHANGE_DEFINITION: case COMPARE: case COPY:
case COPY_VERIFY: case LOG_SELECT: case MODE_SELECT:
case MODE_SELECT_10: case SEND_DIAGNOSTIC: case WRITE_BUFFER:
case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE:
case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW:
case WRITE_6: case WRITE_10: case WRITE_VERIFY:
case UPDATE_BLOCK: case WRITE_LONG: case WRITE_SAME:
case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE:
case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW:
case WRITE_6: case WRITE_10: case WRITE_VERIFY:
case UPDATE_BLOCK: case WRITE_LONG: case WRITE_SAME:
case SEARCH_HIGH_12: case SEARCH_EQUAL_12: case SEARCH_LOW_12:
case WRITE_12: case WRITE_VERIFY_12: case SET_WINDOW:
case MEDIUM_SCAN: case SEND_VOLUME_TAG:
case 0xea: /* alternate number for WRITE LONG */
cp->DataOut = TRUE; /* Output mode */
case WRITE_12: case WRITE_VERIFY_12: case SET_WINDOW:
case MEDIUM_SCAN: case SEND_VOLUME_TAG:
case 0xea: /* alternate number for WRITE LONG */
cp->DataOut = TRUE; /* Output mode */
break;
case TEST_UNIT_READY:
default:
cp->DataIn = TRUE; /* Input mode */
cp->DataIn = TRUE; /* Input mode */
}
if ((done == (void *) eata_scsi_done && HBA_interpret == TRUE)
|| cmd->target == sh->this_id)
cp->Interpret = TRUE; /* Interpret command */
cp->Interpret = TRUE; /* Interpret command */
if (cmd->use_sg) {
cp->scatter = TRUE; /* SG mode */
cp->scatter = TRUE; /* SG mode */
if (cp->sg_list == NULL) {
cp->sg_list = kmalloc(SG_SIZE_BIG*sizeof(struct eata_sg_list),
GFP_ATOMIC | GFP_DMA);
GFP_ATOMIC | GFP_DMA);
}
cp->cp_dataDMA = htonl((ulong)cp->sg_list);
if (cp->cp_dataDMA == 0)
panic("eata_dma: Run out of DMA memory for SG lists !\n");
cp->cp_datalen = htonl(cmd->use_sg * sizeof(struct eata_sg_list));
sl=(struct scatterlist *)cmd->request_buffer;
for(i = 0; i < cmd->use_sg; i++, sl++){
......@@ -436,7 +490,7 @@ int eata_queue(Scsi_Cmnd * cmd, void (* done) (Scsi_Cmnd *))
cp->cp_viraddr = cp;
cp->cmd = cmd;
cmd->host_scribble = (char *)&hd->ccb[y];
cmd->host_scribble = (char *)&hd->ccb[y];
if(eata_send_command((u32) cp, (u32) sh->base, EATA_CMD_DMA_SEND_CP) == FALSE) {
cmd->result = DID_ERROR << 16;
......@@ -563,7 +617,7 @@ int eata_reset(Scsi_Cmnd * cmd)
}
/* hard reset the HBA */
inb((u32) (cmd->host->base) + HA_RSTATUS); /* This might cause trouble */
inb((u32) (cmd->host->base) + HA_RSTATUS); /* This might cause trouble */
eata_send_command(0, (u32) cmd->host->base, EATA_CMD_RESET);
DBG(DBG_ABNORM, printk("eata_reset: board reset done, enabling interrupts.\n"));
......@@ -572,7 +626,7 @@ int eata_reset(Scsi_Cmnd * cmd)
restore_flags(flags);
time = jiffies;
while (jiffies < (time + 300) && limit++ < 10000000)
while (jiffies < (time + (3 * HZ)) && limit++ < 10000000)
/* nothing */;
save_flags(flags);
......@@ -635,7 +689,7 @@ char * get_board_data(u32 base, u32 irq, u32 id)
memset(sp, 0, sizeof(struct eata_sp));
memset(buff, 0, 256);
cp->DataIn = TRUE;
cp->DataIn = TRUE;
cp->Interpret = TRUE; /* Interpret command */
cp->cp_datalen = htonl(255);
......@@ -659,7 +713,7 @@ char * get_board_data(u32 base, u32 irq, u32 id)
eata_send_command((u32) cp, (u32) base, EATA_CMD_DMA_SEND_CP);
i = jiffies + 300;
i = jiffies + (3 * HZ) ;
while (fake_int_result == FALSE && jiffies <= i)
barrier();
......@@ -676,7 +730,7 @@ char * get_board_data(u32 base, u32 irq, u32 id)
inb((u32) (base) + HA_RSTATUS);
eata_send_command(0, base, EATA_CMD_RESET);
i = jiffies;
while (jiffies < (i + 300) && limit++ < 10000000)
while (jiffies < (i + (3 * HZ)) && limit++ < 10000000)
barrier();
return (NULL);
} else
......@@ -734,7 +788,7 @@ int get_conf_PIO(u32 base, struct get_conf *buf)
*p = inw(base + HA_RDATA);
}
if (!(inb(base + HA_RSTATUS) & HA_SERROR)) { /* Error ? */
if (!(inb(base + HA_RSTATUS) & HA_SERROR)) { /* Error ? */
if (htonl(EATA_SIGNATURE) == buf->signature) {
DBG(DBG_PIO&&DBG_PROBE, printk("EATA Controller found at %x "
"EATA Level: %x\n", (uint) base,
......@@ -767,7 +821,7 @@ void print_config(struct get_conf *gc)
gc->SG_64K, gc->SG_UAE, gc->MAX_ID, gc->MAX_CHAN, gc->MAX_LUN);
printk("RIDQ:%d PCI:%d EISA:%d\n",
gc->ID_qest, gc->is_PCI, gc->is_EISA);
DBG(DPT_DEBUG, DELAY(1400));
DBG(DPT_DEBUG, DELAY(14));
}
short register_HBA(u32 base, struct get_conf *gc, Scsi_Host_Template * tpnt,
......@@ -779,6 +833,7 @@ short register_HBA(u32 base, struct get_conf *gc, Scsi_Host_Template * tpnt,
unchar bugs = 0;
struct Scsi_Host *sh;
hostdata *hd;
int x;
DBG(DBG_REGISTER, print_config(gc));
......@@ -792,7 +847,7 @@ short register_HBA(u32 base, struct get_conf *gc, Scsi_Host_Template * tpnt,
if(gc->HAA_valid == FALSE || ntohl(gc->len) < 0x22)
gc->MAX_CHAN = 0;
if (reg_IRQ[gc->IRQ] == FALSE) { /* Interrupt already registered ? */
if (reg_IRQ[gc->IRQ] == FALSE) { /* Interrupt already registered ? */
if (!request_irq(gc->IRQ, (void *) eata_fake_int_handler, SA_INTERRUPT,
"eata_dma")){
reg_IRQ[gc->IRQ]++;
......@@ -802,7 +857,7 @@ short register_HBA(u32 base, struct get_conf *gc, Scsi_Host_Template * tpnt,
printk("Couldn't allocate IRQ %d, Sorry.", gc->IRQ);
return (FALSE);
}
} else { /* More than one HBA on this IRQ */
} else { /* More than one HBA on this IRQ */
if (reg_IRQL[gc->IRQ] == TRUE) {
printk("Can't support more than one HBA on this IRQ,\n"
" if the IRQ is edge triggered. Sorry.\n");
......@@ -861,7 +916,7 @@ short register_HBA(u32 base, struct get_conf *gc, Scsi_Host_Template * tpnt,
if(ntohs(gc->queuesiz) == 0) {
gc->queuesiz = ntohs(64);
printk("Warning: Queue size has to be corrected. Assuming 64 queueslots\n"
" This might be a PM2012B with a defective Firmware\n");
" This might be a PM2012B with a defective Firmware\n");
}
size = sizeof(hostdata) + ((sizeof(struct eata_ccb) + sizeof(long))
......@@ -883,7 +938,7 @@ short register_HBA(u32 base, struct get_conf *gc, Scsi_Host_Template * tpnt,
return (FALSE);
}
hd = SD(sh);
hd = SD(sh);
memset(hd->ccb, 0, sizeof(struct eata_ccb) * ntohs(gc->queuesiz));
memset(hd->reads, 0, sizeof(u32) * 26);
......@@ -894,7 +949,7 @@ short register_HBA(u32 base, struct get_conf *gc, Scsi_Host_Template * tpnt,
strcpy(SD(sh)->vendor, "DPT");
strcpy(SD(sh)->name, "??????????");
strcpy(SD(sh)->revision, "???.?");
} else {
} else {
strncpy(SD(sh)->vendor, &buff[8], 8);
SD(sh)->vendor[8] = 0;
strncpy(SD(sh)->name, &buff[16], 17);
......@@ -918,7 +973,7 @@ short register_HBA(u32 base, struct get_conf *gc, Scsi_Host_Template * tpnt,
SD(sh)->EATA_revision = 'c';
break;
case 0x24:
SD(sh)->EATA_revision = 'z';
SD(sh)->EATA_revision = 'z';
default:
SD(sh)->EATA_revision = '?';
}
......@@ -948,7 +1003,7 @@ short register_HBA(u32 base, struct get_conf *gc, Scsi_Host_Template * tpnt,
sh->max_lun = 8;
}
hd->channel = gc->MAX_CHAN;
hd->channel = gc->MAX_CHAN;
sh->max_channel = gc->MAX_CHAN;
sh->base = (char *) base;
sh->io_port = (u16) base;
......@@ -960,7 +1015,7 @@ short register_HBA(u32 base, struct get_conf *gc, Scsi_Host_Template * tpnt,
* SCSI midlevel code should support different HBA ids on every channel
*/
sh->this_id = gc->scsi_id[3];
sh->can_queue = ntohs(gc->queuesiz);
sh->can_queue = ntohs(gc->queuesiz) - 1; /* Keep one free for internals */
if (gc->OCS_enabled == TRUE)
if(hd->bustype != IS_ISA)
......@@ -997,15 +1052,20 @@ short register_HBA(u32 base, struct get_conf *gc, Scsi_Host_Template * tpnt,
else
hd->primary = TRUE;
sh->wish_block = FALSE;
sh->wish_block = FALSE;
if (hd->bustype != IS_ISA) {
sh->unchecked_isa_dma = FALSE;
} else {
sh->unchecked_isa_dma = TRUE; /* We're doing ISA DMA */
sh->unchecked_isa_dma = TRUE; /* We're doing ISA DMA */
}
hd->next = NULL; /* build a linked list of all HBAs */
for(x = 0; x <= 11; x++){ /* Initialize min. latency */
hd->writes_lat[x][1] = 0xffffffff;
hd->reads_lat[x][1] = 0xffffffff;
}
hd->next = NULL; /* build a linked list of all HBAs */
hd->prev = last_HBA;
if(hd->prev != NULL)
SD(hd->prev)->next = sh;
......@@ -1028,7 +1088,7 @@ void find_EISA(struct get_conf *buf, Scsi_Host_Template * tpnt)
#endif
for (i = 0; i < MAXEISA; i++) {
if (EISAbases[i] == TRUE) { /* Still a possibility ? */
if (EISAbases[i] == TRUE) { /* Still a possibility ? */
base = 0x1c88 + (i * 0x1000);
#if CHECKPAL
......@@ -1090,7 +1150,7 @@ void find_PCI(struct get_conf *buf, Scsi_Host_Template * tpnt)
#else
u8 pci_bus, pci_device_fn;
static s16 pci_index = 0; /* Device index to PCI BIOS calls */
static s16 pci_index = 0; /* Device index to PCI BIOS calls */
u32 base = 0;
u16 com_adr;
u16 rev_device;
......@@ -1142,8 +1202,8 @@ void find_PCI(struct get_conf *buf, Scsi_Host_Template * tpnt)
if (base != 0x1f8) {
/* We didn't find it in the primary search */
if (get_conf_PIO(base, buf) == TRUE) {
if (buf->FORCADR) /* If the address is forced */
continue; /* we'll find it later */
if (buf->FORCADR) /* If the address is forced */
continue; /* we'll find it later */
/* OK. We made it till here, so we can go now
* and register it. We only have to check and
......@@ -1177,7 +1237,7 @@ void find_PCI(struct get_conf *buf, Scsi_Host_Template * tpnt)
} else
printk("eata_dma: No BIOS32 extensions present. This driver release "
"still depends on it.\n"
" Skipping scan for PCI HBAs. \n");
" Skipping scan for PCI HBAs. \n");
#endif /* #ifndef CONFIG_PCI */
return;
}
......@@ -1210,14 +1270,14 @@ int eata_detect(Scsi_Host_Template * tpnt)
if (registered_HBAs != 0) {
printk("EATA (Extended Attachment) driver version: %d.%d%s\n"
"developed in co-operation with DPT\n"
"developed in co-operation with DPT\n"
"(c) 1993-95 Michael Neuffer, neuffer@goofy.zdv.uni-mainz.de\n",
VER_MAJOR, VER_MINOR, VER_SUB);
printk("Registered HBAs:");
printk("\nHBA no. Boardtype: Revis: EATA: Bus: BaseIO: IRQ: DMA: Ch: "
"ID: Pr: QS: SG: CPL:\n");
for (i = 1; i <= registered_HBAs; i++) {
printk("scsi%-2d: %.10s v%s 2.0%c %s %#.4x %2d",
printk("scsi%-2d: %.10s v%s 2.0%c %s %#.4x %2d",
HBA_ptr->host_no, SD(HBA_ptr)->name, SD(HBA_ptr)->revision,
SD(HBA_ptr)->EATA_revision, (SD(HBA_ptr)->bustype == 'P')?
"PCI ":(SD(HBA_ptr)->bustype == 'E')?"EISA":"ISA ",
......@@ -1226,7 +1286,7 @@ int eata_detect(Scsi_Host_Template * tpnt)
printk(" %2x ", HBA_ptr->dma_channel);
else
printk(" %s", "BMST");
printk(" %d %d %c %2d %2d %2d\n", SD(HBA_ptr)->channel,
printk(" %d %d %c %2d %2d %2d\n", SD(HBA_ptr)->channel,
HBA_ptr->this_id, (SD(HBA_ptr)->primary == TRUE)?'Y':'N',
HBA_ptr->can_queue, HBA_ptr->sg_tablesize, HBA_ptr->cmd_per_lun);
HBA_ptr = SD(HBA_ptr)->next;
......@@ -1237,7 +1297,7 @@ int eata_detect(Scsi_Host_Template * tpnt)
scsi_init_free((void *)dma_scratch, 512);
DBG(DPT_DEBUG, DELAY(1200));
DBG(DPT_DEBUG, DELAY(12));
return(registered_HBAs);
}
......@@ -1262,7 +1322,6 @@ Scsi_Host_Template driver_template = EATA_DMA;
* c-label-offset: -4
* c-continued-statement-offset: 4
* c-continued-brace-offset: 0
* indent-tabs-mode: nil
* tab-width: 8
* End:
*/
......@@ -16,7 +16,7 @@
#define VER_MAJOR 2
#define VER_MINOR 5
#define VER_SUB "6a"
#define VER_SUB "7a"
/************************************************************************
......
......@@ -4,11 +4,11 @@ const char *const scsi_dev_types[MAX_SCSI_DEVICE_CODE] =
{
"Direct-Access ",
"Sequential-Access",
"Printer ",
"Processor ",
"WORM ",
"CD-ROM ",
"Scanner ",
"Printer ",
"Processor ",
"WORM ",
"CD-ROM ",
"Scanner ",
"Optical Device ",
"Medium Changer ",
"Communications "
......@@ -47,8 +47,24 @@ void swap_statistics(u8 *p)
*/
int eata_set_info(char *buffer, int length, struct Scsi_Host *HBA_ptr)
{
DBG(DBG_PROC_WRITE, printk("%s\n", buffer));
return(-ENOSYS); /* Currently this is a no-op */
if (length >= 8 && strncmp(buffer, "eata_dma", 8) == 0) {
buffer += 9;
length -= 9;
if(length >= 8 && strncmp(buffer, "latency", 7) == 0) {
SD(HBA_ptr)->do_latency = TRUE;
return(length+9);
}
if(length >=10 && strncmp(buffer, "nolatency", 9) == 0) {
SD(HBA_ptr)->do_latency = FALSE;
return(length+9);
}
printk("Unknown command:%s length: %d\n", buffer, length);
} else
printk("Wrong Signature:%10s\n", (char *) ((ulong)buffer-9));
return(-EINVAL);
}
/*
......@@ -72,19 +88,19 @@ int eata_proc_info(char *buffer, char **start, off_t offset, int length,
static u8 buff[512];
static u8 buff2[512];
hst_cmd_stat *rhcs, *whcs;
coco *cc;
scsitrans *st;
scsimod *sm;
hobu *hb;
scbu *sb;
boty *bt;
memco *mc;
firm *fm;
subinf *si;
pcinf *pi;
arrlim *al;
coco *cc;
scsitrans *st;
scsimod *sm;
hobu *hb;
scbu *sb;
boty *bt;
memco *mc;
firm *fm;
subinf *si;
pcinf *pi;
arrlim *al;
int i, x;
int size, len = 0;
int size, len = 0;
off_t begin = 0;
off_t pos = 0;
......@@ -327,7 +343,7 @@ int eata_proc_info(char *buffer, char **start, off_t offset, int length,
SD(HBA_ptr)->writes[11]);
len += size;
pos = begin + len;
size = sprintf(buffer+len,"Sum :%12u %12u\n",
size = sprintf(buffer+len,"Sum : %12u %12u\n",
SD(HBA_ptr)->reads[12],
SD(HBA_ptr)->writes[12]);
len += size;
......@@ -341,6 +357,79 @@ int eata_proc_info(char *buffer, char **start, off_t offset, int length,
if (pos > offset + length)
goto stop_output;
if(SD(HBA_ptr)->do_latency == TRUE) {
size = sprintf(buffer + len, "Host Latency Command Statistics:\n"
"Current timer resolution: 10ms\n"
" Reads: Min:(ms) Max:(ms) Ave:(ms)\n");
len += size;
pos = begin + len;
for (x = 0; x <= 10; x++) {
size = sprintf(buffer+len,"%5dk:%12u %12u %12u %12u\n",
1 << x,
SD(HBA_ptr)->reads_lat[x][0],
(SD(HBA_ptr)->reads_lat[x][1] == 0xffffffff)
? 0:(SD(HBA_ptr)->reads_lat[x][1] * 10),
SD(HBA_ptr)->reads_lat[x][2] * 10,
SD(HBA_ptr)->reads_lat[x][3] * 10 /
((SD(HBA_ptr)->reads_lat[x][0])
? SD(HBA_ptr)->reads_lat[x][0]:1));
len += size;
pos = begin + len;
}
size = sprintf(buffer+len,">1024k:%12u %12u %12u %12u\n",
SD(HBA_ptr)->reads_lat[11][0],
(SD(HBA_ptr)->reads_lat[11][1] == 0xffffffff)
? 0:(SD(HBA_ptr)->reads_lat[11][1] * 10),
SD(HBA_ptr)->reads_lat[11][2] * 10,
SD(HBA_ptr)->reads_lat[11][3] * 10 /
((SD(HBA_ptr)->reads_lat[x][0])
? SD(HBA_ptr)->reads_lat[x][0]:1));
len += size;
pos = begin + len;
if (pos < offset) {
len = 0;
begin = pos;
}
if (pos > offset + length)
goto stop_output;
size = sprintf(buffer + len,
" Writes: Min:(ms) Max:(ms) Ave:(ms)\n");
len += size;
pos = begin + len;
for (x = 0; x <= 10; x++) {
size = sprintf(buffer+len,"%5dk:%12u %12u %12u %12u\n",
1 << x,
SD(HBA_ptr)->writes_lat[x][0],
(SD(HBA_ptr)->writes_lat[x][1] == 0xffffffff)
? 0:(SD(HBA_ptr)->writes_lat[x][1] * 10),
SD(HBA_ptr)->writes_lat[x][2] * 10,
SD(HBA_ptr)->writes_lat[x][3] * 10 /
((SD(HBA_ptr)->writes_lat[x][0])
? SD(HBA_ptr)->writes_lat[x][0]:1));
len += size;
pos = begin + len;
}
size = sprintf(buffer+len,">1024k:%12u %12u %12u %12u\n",
SD(HBA_ptr)->writes_lat[11][0],
(SD(HBA_ptr)->writes_lat[11][1] == 0xffffffff)
? 0:(SD(HBA_ptr)->writes_lat[x][1] * 10),
SD(HBA_ptr)->writes_lat[11][2] * 10,
SD(HBA_ptr)->writes_lat[11][3] * 10/
((SD(HBA_ptr)->writes_lat[x][0])
? SD(HBA_ptr)->writes_lat[x][0]:1));
len += size;
pos = begin + len;
if (pos < offset) {
len = 0;
begin = pos;
}
if (pos > offset + length)
goto stop_output;
}
scd = scsi_devices;
size = sprintf(buffer+len,"Attached devices: %s\n", (scd)?"":"none");
......@@ -350,7 +439,8 @@ int eata_proc_info(char *buffer, char **start, off_t offset, int length,
while (scd) {
if (scd->host == HBA_ptr) {
size = sprintf(buffer + len, "Channel: %02d Id: %02d Lun: %02d\n Vendor: ",
size = sprintf(buffer + len,
"Channel: %02d Id: %02d Lun: %02d\n Vendor: ",
scd->channel, scd->id, scd->lun);
for (x = 0; x < 8; x++) {
if (scd->vendor[x] >= 0x20)
......
......@@ -51,19 +51,19 @@
#define SG_SIZE_BIG 509 /* max. 509 */
#define C_P_L_DIV 2 /* 1 <= C_P_L_DIV <= 8
* You can use this parameter to fine-tune
* the driver. Depending on the number of
* devices and their speed and ability to queue
* commands, you will get the best results with a
* value
* ~= numdevices-(devices_unable_to_queue_commands/2)
* The reason for this is that the disk driver
* tends to flood the queue, so that other
* drivers have problems to queue commands
* themselves. This can for example result in
* the effect that the tape stops during disk
* accesses.
*/
* You can use this parameter to fine-tune
* the driver. Depending on the number of
* devices and their speed and ability to queue
* commands, you will get the best results with a
* value
* ~= numdevices-(devices_unable_to_queue_commands/2)
* The reason for this is that the disk driver
* tends to flood the queue, so that other
* drivers have problems to queue commands
* themselves. This can for example result in
* the effect that the tape stops during disk
* accesses.
*/
#define FREE 0
#define OK 0
......@@ -77,7 +77,7 @@
#define CD(cmd) ((struct eata_ccb *)(cmd->host_scribble))
#define SD(host) ((hostdata *)&(host->hostdata))
#define DELAY(x) { __u32 i; i = jiffies + x; while (jiffies < i); }
#define DELAY(x) { __u32 i; i = jiffies + (x * HZ); while (jiffies < i) barrier(); }
#define DEL2(x) { __u32 i; for (i = 0; i < 0xffff * x; i++); }
/***********************************************
......@@ -189,9 +189,9 @@ struct eata_register { /* EATA register set */
__u8 data_reg[2]; /* R, couldn't figure this one out */
__u8 cp_addr[4]; /* W, CP address register */
union {
__u8 command; /* W, command code: [read|set] conf, send CP*/
struct reg_bit status; /* R, see register_bit1 */
__u8 statusbyte;
__u8 command; /* W, command code: [read|set] conf, send CP*/
struct reg_bit status; /* R, see register_bit1 */
__u8 statusbyte;
} ovr;
struct reg_abit aux_stat; /* R, see register_bit2 */
};
......@@ -200,48 +200,48 @@ struct get_conf { /* Read Configuration Array */
__u32 len; /* Should return 0x22, 0x24, etc */
__u32 signature; /* Signature MUST be "EATA" */
__u8 version2:4,
version:4; /* EATA Version level */
version:4; /* EATA Version level */
__u8 OCS_enabled:1, /* Overlap Command Support enabled */
TAR_support:1, /* SCSI Target Mode supported */
TRNXFR:1, /* Truncate Transfer Cmd not necessary */
/* Only used in PIO Mode */
MORE_support:1, /* MORE supported (only PIO Mode) */
DMA_support:1, /* DMA supported Driver uses only */
/* this mode */
DMA_valid:1, /* DRQ value in Byte 30 is valid */
ATA:1, /* ATA device connected (not supported) */
HAA_valid:1; /* Hostadapter Address is valid */
__u16 cppadlen; /* Number of pad bytes send after CD data */
/* set to zero for DMA commands */
__u8 scsi_id[4]; /* SCSI ID of controller 2-0 Byte 0 res. */
/* if not, zero is returned */
TAR_support:1, /* SCSI Target Mode supported */
TRNXFR:1, /* Truncate Transfer Cmd not necessary *
* Only used in PIO Mode */
MORE_support:1, /* MORE supported (only PIO Mode) */
DMA_support:1, /* DMA supported Driver uses only *
* this mode */
DMA_valid:1, /* DRQ value in Byte 30 is valid */
ATA:1, /* ATA device connected (not supported) */
HAA_valid:1; /* Hostadapter Address is valid */
__u16 cppadlen; /* Number of pad bytes send after CD data *
* set to zero for DMA commands */
__u8 scsi_id[4]; /* SCSI ID of controller 2-0 Byte 0 res. *
* if not, zero is returned */
__u32 cplen; /* CP length: number of valid cp bytes */
__u32 splen; /* Number of bytes returned after */
/* Receive SP command */
__u32 splen; /* Number of bytes returned after *
* Receive SP command */
__u16 queuesiz; /* max number of queueable CPs */
__u16 dummy;
__u16 SGsiz; /* max number of SG table entries */
__u8 IRQ:4, /* IRQ used this HA */
IRQ_TR:1, /* IRQ Trigger: 0=edge, 1=level */
SECOND:1, /* This is a secondary controller */
IRQ_TR:1, /* IRQ Trigger: 0=edge, 1=level */
SECOND:1, /* This is a secondary controller */
DMA_channel:2; /* DRQ index, DRQ is 2comp of DRQX */
__u8 sync; /* device at ID 7 tru 0 is running in */
/* synchronous mode, this will disappear */
__u8 sync; /* device at ID 7 tru 0 is running in *
* synchronous mode, this will disappear */
__u8 DSBLE:1, /* ISA i/o addressing is disabled */
FORCADR:1, /* i/o address has been forced */
SG_64K:1,
SG_UAE:1,
:4;
FORCADR:1, /* i/o address has been forced */
SG_64K:1,
SG_UAE:1,
:4;
__u8 MAX_ID:5, /* Max number of SCSI target IDs */
MAX_CHAN:3; /* Number of SCSI busses on HBA */
MAX_CHAN:3; /* Number of SCSI busses on HBA */
__u8 MAX_LUN; /* Max number of LUNs */
__u8 :3,
AUTOTRM:1,
M1_inst:1,
ID_qest:1, /* Raidnum ID is questionable */
is_PCI:1, /* HBA is PCI */
is_EISA:1; /* HBA is EISA */
AUTOTRM:1,
M1_inst:1,
ID_qest:1, /* Raidnum ID is questionable */
is_PCI:1, /* HBA is PCI */
is_EISA:1; /* HBA is EISA */
__u8 unused[478];
};
......@@ -253,60 +253,62 @@ struct eata_sg_list
struct eata_ccb { /* Send Command Packet structure */
__u8 SCSI_Reset:1, /* Cause a SCSI Bus reset on the cmd */
HBA_Init:1, /* Cause Controller to reinitialize */
Auto_Req_Sen:1, /* Do Auto Request Sense on errors */
scatter:1, /* Data Ptr points to a SG Packet */
Resrvd:1, /* RFU */
Interpret:1, /* Interpret the SCSI cdb of own use */
DataOut:1, /* Data Out phase with command */
DataIn:1; /* Data In phase with command */
__u8 reqlen; /* Request Sense Length */
/* Valid if Auto_Req_Sen=1 */
__u8 SCSI_Reset:1, /* Cause a SCSI Bus reset on the cmd */
HBA_Init:1, /* Cause Controller to reinitialize */
Auto_Req_Sen:1, /* Do Auto Request Sense on errors */
scatter:1, /* Data Ptr points to a SG Packet */
Resrvd:1, /* RFU */
Interpret:1, /* Interpret the SCSI cdb of own use */
DataOut:1, /* Data Out phase with command */
DataIn:1; /* Data In phase with command */
__u8 reqlen; /* Request Sense Length *
* Valid if Auto_Req_Sen=1 */
__u8 unused[3];
__u8 FWNEST:1, /* send cmd to phys RAID component*/
unused2:7;
__u8 Phsunit:1, /* physical unit on mirrored pair */
I_AT:1, /* inhibit address translation */
I_HBA_C:1, /* HBA inhibit caching */
unused3:5;
__u8 cp_id:5, /* SCSI Device ID of target */
cp_channel:3; /* SCSI Channel # of HBA */
__u8 FWNEST:1, /* send cmd to phys RAID component */
unused2:7;
__u8 Phsunit:1, /* physical unit on mirrored pair */
I_AT:1, /* inhibit address translation */
I_HBA_C:1, /* HBA inhibit caching */
unused3:5;
__u8 cp_id:5, /* SCSI Device ID of target */
cp_channel:3; /* SCSI Channel # of HBA */
__u8 cp_lun:3,
:2,
cp_luntar:1, /* CP is for target ROUTINE */
cp_dispri:1, /* Grant disconnect privilege */
cp_identify:1; /* Always TRUE */
__u8 cp_msg1; /* Message bytes 0-3 */
:2,
cp_luntar:1, /* CP is for target ROUTINE */
cp_dispri:1, /* Grant disconnect privilege */
cp_identify:1; /* Always TRUE */
__u8 cp_msg1; /* Message bytes 0-3 */
__u8 cp_msg2;
__u8 cp_msg3;
__u8 cp_cdb[12]; /* Command Descriptor Block */
__u32 cp_datalen; /* Data Transfer Length */
/* If scatter=1 len of sg package */
void *cp_viraddr; /* address of this ccb */
__u32 cp_dataDMA; /* Data Address, if scatter=1 *
* address of scatter packet */
__u32 cp_statDMA; /* address for Status Packet */
__u32 cp_reqDMA; /* Request Sense Address, used if */
/* CP command ends with error */
/* Additional CP info begins here */
__u8 cp_cdb[12]; /* Command Descriptor Block */
__u32 cp_datalen; /* Data Transfer Length *
* If scatter=1 len of sg package */
void *cp_viraddr; /* address of this ccb */
__u32 cp_dataDMA; /* Data Address, if scatter=1 *
* address of scatter packet */
__u32 cp_statDMA; /* address for Status Packet */
__u32 cp_reqDMA; /* Request Sense Address, used if *
* CP command ends with error */
/* Additional CP info begins here */
__u32 timestamp; /* Needed to measure command latency */
__u32 timeout;
__u8 sizeindex;
__u8 rw_latency;
__u8 retries;
__u8 status; /* status of this queueslot */
Scsi_Cmnd *cmd; /* address of cmd */
__u8 status; /* status of this queueslot */
Scsi_Cmnd *cmd; /* address of cmd */
struct eata_sg_list *sg_list;
};
struct eata_sp {
__u8 hba_stat:7, /* HBA status */
EOC:1; /* True if command finished */
__u8 scsi_stat; /* Target SCSI status */
__u8 hba_stat:7, /* HBA status */
EOC:1; /* True if command finished */
__u8 scsi_stat; /* Target SCSI status */
__u8 reserved[2];
__u32 residue_len; /* Number of bytes not transferred */
struct eata_ccb *ccb; /* Address set in COMMAND PACKET */
__u32 residue_len; /* Number of bytes not transferred */
struct eata_ccb *ccb; /* Address set in COMMAND PACKET */
__u8 msg[12];
};
......@@ -320,12 +322,15 @@ typedef struct hstd {
__u8 state; /* state of HBA */
__u8 primary; /* true if primary */
__u8 broken_INQUIRY:1; /* This is an EISA HBA with *
* broken INQUIRY */
* broken INQUIRY */
__u8 do_latency; /* Latency measurement flag */
__u32 reads[13];
__u32 writes[13];
/* state of Target (RESET,..) */
__u32 reads_lat[12][4];
__u32 writes_lat[12][4];
/* state of Target (RESET,..) */
__u8 t_state[MAXCHANNEL][MAXTARGET];
/* timeouts on target */
/* timeouts on target */
__u32 t_timeout[MAXCHANNEL][MAXTARGET];
__u32 last_ccb; /* Last used ccb */
__u32 cplen; /* size of CP in words */
......@@ -372,7 +377,6 @@ struct geom_emul {
* c-label-offset: -4
* c-continued-statement-offset: 4
* c-continued-brace-offset: 0
* indent-tabs-mode: nil
* tab-width: 8
* End:
*/
......@@ -32,7 +32,7 @@
* Cambridge, MA 02139, USA. *
* *
************************************************************
* last change: 95/06/20 OS: Linux 1.3.3 + pre1.3 SCSI pat.*
* last change: 95/07/13 OS: Linux 1.3.9 *
************************************************************/
/* Look in eata_pio.h for configuration information */
......@@ -504,7 +504,7 @@ int eata_pio_reset(Scsi_Cmnd * cmd)
HD(cmd)->state = RESET;
time = jiffies;
while (jiffies < (time + 300) && limit++ < 10000000);
while (jiffies < (time + (3 * HZ)) && limit++ < 10000000);
DBG(DBG_ABNORM, printk("eata_pio_reset: interrupts disabled, loops %d.\n", limit));
DBG(DBG_ABNORM && DBG_DELAY, DEL2(500));
......@@ -650,7 +650,7 @@ void print_pio_config(struct get_conf *gc)
printk("IRQ:%d IRQT:%d FORCADR:%d MCH:%d RIDQ:%d\n",
gc->IRQ, gc->IRQ_TR, gc->FORCADR,
gc->MAX_CHAN, gc->ID_qest);
DBG(DPT_DEBUG, DELAY(1400));
DBG(DPT_DEBUG, DELAY(14));
}
static uint print_selftest(uint base)
......@@ -1014,7 +1014,7 @@ int eata_pio_detect(Scsi_Host_Template * tpnt)
HBA_ptr = SD(HBA_ptr)->next;
}
}
DBG(DPT_DEBUG,DELAY(1200));
DBG(DPT_DEBUG,DELAY(12));
return (registered_HBAs);
}
......
......@@ -80,6 +80,7 @@
#define LOG_SENSE 0x4d
#define MODE_SELECT_10 0x55
#define MODE_SENSE_10 0x5a
#define READ_12 0xa8
#define WRITE_12 0xaa
#define WRITE_VERIFY_12 0xae
#define SEARCH_HIGH_12 0xb0
......
......@@ -30,7 +30,7 @@
#include "sound_config.h"
#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_GUS)
#include "ultrasound.h"
#include <linux/ultrasound.h>
#include "gus_hw.h"
#define MIX_DEVS (SOUND_MASK_MIC|SOUND_MASK_LINE| \
......
......@@ -7,6 +7,10 @@
*
* Modularised by Alan Cox <Alan.Cox@linux.org>, while hacking some
* experimental NFS changes. Modularisation taken straight from SYS5 fs.
*
* Change to nfs_read_super() to permit NFS mounts to multi-homed hosts.
* J.S.Peatfield@damtp.cam.ac.uk
*
*/
#ifdef MODULE
......@@ -76,6 +80,7 @@ struct super_block *nfs_read_super(struct super_block *sb, void *raw_data,
struct nfs_server *server;
unsigned int fd;
struct file *filp;
dev_t dev = sb->s_dev;
MOD_INC_USE_COUNT;
......@@ -104,6 +109,7 @@ struct super_block *nfs_read_super(struct super_block *sb, void *raw_data,
}
filp->f_count++;
lock_super(sb);
sb->s_blocksize = 1024; /* XXX */
sb->s_blocksize_bits = 10;
sb->s_magic = NFS_SUPER_MAGIC;
......@@ -131,6 +137,31 @@ struct super_block *nfs_read_super(struct super_block *sb, void *raw_data,
server->acdirmin = data->acdirmin*HZ;
server->acdirmax = data->acdirmax*HZ;
strcpy(server->hostname, data->hostname);
/* Start of JSP NFS patch */
/* Check if passed address in data->addr */
if (data->addr.sin_addr.s_addr == INADDR_ANY) { /* No address passed */
if (((struct sockaddr_in *)(&server->toaddr))->sin_addr.s_addr == INADDR_ANY) {
printk("NFS: Error passed unconnected socket and no address\n") ;
return NULL ;
} else {
/* Need access to socket internals JSP */
struct socket *sock;
int dummylen ;
/* printk("NFS: using socket address\n") ;*/
sock = &((filp->f_inode)->u.socket_i);
/* extract the other end of the socket into server->toaddr */
sock->ops->getname(sock, &(server->toaddr), &dummylen, 1) ;
}
} else {
/* printk("NFS: coppying passed addr to server->toaddr\n") ;*/
memcpy((char *)&(server->toaddr),(char *)(&data->addr),sizeof(server->toaddr));
}
/* End of JSP NFS patch */
sb->u.nfs_sb.s_root = data->root;
unlock_super(sb);
if (!(sb->s_mounted = nfs_fhget(sb, &data->root, NULL))) {
......
......@@ -102,7 +102,10 @@ static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end, int
fs = get_fs();
set_fs(get_ds());
for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1) {
result = sock->ops->send(sock, (void *) start, len, 0, 0);
/* JSP 1995-07-01 Use sendto() not send() to cope with multi-homed hosts
as we have set the socket to have INADDR_ANY as it's desination */
result = sock->ops->sendto(sock, (void *) start, len, 0, 0,
&(server->toaddr), sizeof((server->toaddr))) ;
if (result < 0) {
printk("nfs_rpc_call: send error = %d\n", result);
break;
......
......@@ -85,7 +85,7 @@ __old_ipl; })
#define save_flags(flags) do { flags = getipl(); } while (0)
#define restore_flags(flags) setipl(flags)
extern inline unsigned long xchg_u32(int * m, unsigned long val)
extern inline unsigned long xchg_u32(volatile int * m, unsigned long val)
{
unsigned long dummy, dummy2;
......@@ -100,7 +100,7 @@ extern inline unsigned long xchg_u32(int * m, unsigned long val)
return val;
}
extern inline unsigned long xchg_u64(long * m, unsigned long val)
extern inline unsigned long xchg_u64(volatile long * m, unsigned long val)
{
unsigned long dummy, dummy2;
......@@ -115,9 +115,19 @@ extern inline unsigned long xchg_u64(long * m, unsigned long val)
return val;
}
extern inline void * xchg_ptr(void *m, void *val)
#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
#define tas(ptr) (xchg((ptr),1))
static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
{
return (void *) xchg_u64((long *) m, (unsigned long) val);
switch (size) {
case 4:
return xchg_u32(ptr, x);
case 8:
return xchg_u64(ptr, x);
}
printk("Argh.. xchg() with unsupported size\n");
return x;
}
#endif /* __ASSEMBLY__ */
......
......@@ -8,6 +8,123 @@
* yet. I'll have to see about this later..
*/
#define __NR_exit 1
#define __NR_fork 2
#define __NR_read 3
#define __NR_write 4
#define __NR_close 6
#define __NR_wait4 7
#define __NR_link 9
#define __NR_unlink 10
#define __NR_chdir 12
#define __NR_fchdir 13
#define __NR_mknod 14
#define __NR_chmod 15
#define __NR_chown 16
#define __NR_brk 17
#define __NR_lseek 19
#define __NR_getxpid 20
#define __NR_setuid 23
#define __NR_getxuid 24
#define __NR_ptrace 26
#define __NR_access 33
#define __NR_sync 36
#define __NR_kill 37
#define __NR_setpgid 39
#define __NR_dup 41
#define __NR_pipe 42
#define __NR_open 45
#define __NR_getxgid 47
#define __NR_ioctl 54
#define __NR_symlink 57
#define __NR_readlink 58
#define __NR_execve 59
#define __NR_umask 60
#define __NR_getpgrp 63
#define __NR_getpagesize 64
#define __NR_stat 67
#define __NR_lstat 68
#define __NR_munmap 73
#define __NR_mprotect 74
#define __NR_madvise 75
#define __NR_vhangup 76
#define __NR_getgroups 79
#define __NR_setgroups 80
#define __NR_setpgid 82
#define __NR_setitimer 83
#define __NR_getitimer 86
#define __NR_gethostname 87
#define __NR_sethostname 88
#define __NR_getdtablesize 89
#define __NR_dup2 90
#define __NR_fstat 91
#define __NR_fcntl 92
#define __NR_select 93
#define __NR_fsync 95
#define __NR_setpriority 96
#define __NR_socket 97
#define __NR_connect 98
#define __NR_accept 99
#define __NR_getpriority 100
#define __NR_send 101
#define __NR_recv 102
#define __NR_sigreturn 103
#define __NR_bind 104
#define __NR_setsockopt 105
#define __NR_listen 106
#define __NR_sigsuspend 111
#define __NR_gettimeofday 116
#define __NR_getrusage 117
#define __NR_getsockopt 118
#define __NR_settimeofday 122
#define __NR_fchown 123
#define __NR_fchmod 124
#define __NR_recvfrom 125
#define __NR_setreuid 126
#define __NR_setregid 127
#define __NR_rename 128
#define __NR_truncate 129
#define __NR_ftruncate 130
#define __NR_setgid 132
#define __NR_sendto 133
#define __NR_shutdown 134
#define __NR_socketpair 135
#define __NR_mkdir 136
#define __NR_rmdir 137
#define __NR_utimes 138
#define __NR_getpeername 141
#define __NR_getrlimit 144
#define __NR_setrlimit 145
#define __NR_setsid 147
#define __NR_getsockname 150
#define __NR_sigaction 156
#define __NR_msgctl 200
#define __NR_msgget 201
#define __NR_msgrcv 202
#define __NR_msgsnd 203
#define __NR_semctl 204
#define __NR_semget 205
#define __NR_semop 206
#define __NR_shmctl 210
#define __NR_shmdt 211
#define __NR_shmget 212
/*
* Linux-specific system calls begin at 300
*/
#define __NR_bdflush 300
#define __NR_sethae 301
#define __NR_mount 302
#define __NR_adjtimex 303
#define __NR_swapoff 304
#define __NR_getdents 305
#define __NR_create_module 306
#define __NR_init_module 307
#define __NR_delete_module 308
#define __NR_get_kernel_syms 309
#define __NR_syslog 310
#ifdef __LIBRARY__
/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
......
......@@ -138,32 +138,32 @@ __asm__ __volatile__ ( \
:"ax")
extern inline unsigned long xchg_u8(char * m, unsigned long val)
{
__asm__("xchgb %b0,%1":"=q" (val),"=m" (*m):"0" (val):"memory");
return val;
}
extern inline unsigned long xchg_u16(short * m, unsigned long val)
{
__asm__("xchgw %w0,%1":"=r" (val),"=m" (*m):"0" (val):"memory");
return val;
}
#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
#define tas(ptr) (xchg((ptr),1))
extern inline unsigned long xchg_u32(int * m, unsigned long val)
{
__asm__("xchgl %0,%1":"=r" (val),"=m" (*m):"0" (val):"memory");
return val;
}
extern inline int tas(char * m)
{
return xchg_u8(m,1);
}
struct __xchg_dummy { unsigned long a[100]; };
#define __xg(x) ((volatile struct __xchg_dummy *)(x))
extern inline void * xchg_ptr(void * m, void * val)
static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
{
return (void *) xchg_u32(m, (unsigned long) val);
switch (size) {
case 1:
__asm__("xchgb %b0,%1"
:"=q" (x), "=m" (*__xg(ptr))
:"0" (x), "m" (*__xg(ptr)));
break;
case 2:
__asm__("xchgw %w0,%1"
:"=r" (x), "=m" (*__xg(ptr))
:"0" (x), "m" (*__xg(ptr)));
break;
case 4:
__asm__("xchgl %0,%1"
:"=r" (x), "=m" (*__xg(ptr))
:"0" (x), "m" (*__xg(ptr)));
break;
}
return x;
}
#define mb() __asm__ __volatile__ ("" : : :"memory")
......
#ifndef _ASM_I386_UNISTD_H_
#define _ASM_I386_UNISTD_H_
/*
* This file contains the system call numbers.
*/
#define __NR_setup 0 /* used only by init, to get system going */
#define __NR_exit 1
#define __NR_fork 2
#define __NR_read 3
#define __NR_write 4
#define __NR_open 5
#define __NR_close 6
#define __NR_waitpid 7
#define __NR_creat 8
#define __NR_link 9
#define __NR_unlink 10
#define __NR_execve 11
#define __NR_chdir 12
#define __NR_time 13
#define __NR_mknod 14
#define __NR_chmod 15
#define __NR_chown 16
#define __NR_break 17
#define __NR_oldstat 18
#define __NR_lseek 19
#define __NR_getpid 20
#define __NR_mount 21
#define __NR_umount 22
#define __NR_setuid 23
#define __NR_getuid 24
#define __NR_stime 25
#define __NR_ptrace 26
#define __NR_alarm 27
#define __NR_oldfstat 28
#define __NR_pause 29
#define __NR_utime 30
#define __NR_stty 31
#define __NR_gtty 32
#define __NR_access 33
#define __NR_nice 34
#define __NR_ftime 35
#define __NR_sync 36
#define __NR_kill 37
#define __NR_rename 38
#define __NR_mkdir 39
#define __NR_rmdir 40
#define __NR_dup 41
#define __NR_pipe 42
#define __NR_times 43
#define __NR_prof 44
#define __NR_brk 45
#define __NR_setgid 46
#define __NR_getgid 47
#define __NR_signal 48
#define __NR_geteuid 49
#define __NR_getegid 50
#define __NR_acct 51
#define __NR_phys 52
#define __NR_lock 53
#define __NR_ioctl 54
#define __NR_fcntl 55
#define __NR_mpx 56
#define __NR_setpgid 57
#define __NR_ulimit 58
#define __NR_oldolduname 59
#define __NR_umask 60
#define __NR_chroot 61
#define __NR_ustat 62
#define __NR_dup2 63
#define __NR_getppid 64
#define __NR_getpgrp 65
#define __NR_setsid 66
#define __NR_sigaction 67
#define __NR_sgetmask 68
#define __NR_ssetmask 69
#define __NR_setreuid 70
#define __NR_setregid 71
#define __NR_sigsuspend 72
#define __NR_sigpending 73
#define __NR_sethostname 74
#define __NR_setrlimit 75
#define __NR_getrlimit 76
#define __NR_getrusage 77
#define __NR_gettimeofday 78
#define __NR_settimeofday 79
#define __NR_getgroups 80
#define __NR_setgroups 81
#define __NR_select 82
#define __NR_symlink 83
#define __NR_oldlstat 84
#define __NR_readlink 85
#define __NR_uselib 86
#define __NR_swapon 87
#define __NR_reboot 88
#define __NR_readdir 89
#define __NR_mmap 90
#define __NR_munmap 91
#define __NR_truncate 92
#define __NR_ftruncate 93
#define __NR_fchmod 94
#define __NR_fchown 95
#define __NR_getpriority 96
#define __NR_setpriority 97
#define __NR_profil 98
#define __NR_statfs 99
#define __NR_fstatfs 100
#define __NR_ioperm 101
#define __NR_socketcall 102
#define __NR_syslog 103
#define __NR_setitimer 104
#define __NR_getitimer 105
#define __NR_stat 106
#define __NR_lstat 107
#define __NR_fstat 108
#define __NR_olduname 109
#define __NR_iopl 110
#define __NR_vhangup 111
#define __NR_idle 112
#define __NR_vm86 113
#define __NR_wait4 114
#define __NR_swapoff 115
#define __NR_sysinfo 116
#define __NR_ipc 117
#define __NR_fsync 118
#define __NR_sigreturn 119
#define __NR_clone 120
#define __NR_setdomainname 121
#define __NR_uname 122
#define __NR_modify_ldt 123
#define __NR_adjtimex 124
#define __NR_mprotect 125
#define __NR_sigprocmask 126
#define __NR_create_module 127
#define __NR_init_module 128
#define __NR_delete_module 129
#define __NR_get_kernel_syms 130
#define __NR_quotactl 131
#define __NR_getpgid 132
#define __NR_fchdir 133
#define __NR_bdflush 134
#define __NR_sysfs 135
#define __NR_personality 136
#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
#define __NR_setfsuid 138
#define __NR_setfsgid 139
#define __NR__llseek 140
#define __NR_getdents 141
#define __NR__newselect 142
#define __NR_flock 143
/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
#define _syscall0(type,name) \
type name(void) \
......
......@@ -275,7 +275,7 @@ extern inline long find_in_swap_cache (unsigned long addr)
#ifdef SWAP_CACHE_INFO
swap_cache_find_total++;
#endif
entry = (unsigned long) xchg_ptr(swap_cache + MAP_NR(addr), NULL);
entry = xchg(swap_cache + MAP_NR(addr), 0);
#ifdef SWAP_CACHE_INFO
if (entry)
swap_cache_find_success++;
......@@ -290,7 +290,7 @@ extern inline int delete_from_swap_cache(unsigned long addr)
#ifdef SWAP_CACHE_INFO
swap_cache_del_total++;
#endif
entry= (unsigned long) xchg_ptr(swap_cache + MAP_NR(addr), NULL);
entry= xchg(swap_cache + MAP_NR(addr), 0);
if (entry) {
#ifdef SWAP_CACHE_INFO
swap_cache_del_success++;
......
......@@ -31,7 +31,11 @@
/* for future expansion when we will have different priorities. */
#define DEV_NUMBUFFS 3
#define MAX_ADDR_LEN 7
#define MAX_HEADER 38
#ifndef CONFIG_AX25
#define MAX_HEADER 32 /* We really need about 18 worst case .. so 32 is aligned */
#else
#define MAX_HEADER 96 /* AX.25 + NetROM */
#endif
#define IS_MYADDR 1 /* address is (one of) our own */
#define IS_LOOPBACK 2 /* address is for LOOPBACK */
......@@ -73,12 +77,12 @@ struct device
unsigned long mem_end; /* sahared mem end */
unsigned long mem_start; /* shared mem start */
unsigned long base_addr; /* device I/O address */
unsigned long tbusy; /* transmitter busy must be long for bitops */
unsigned char irq; /* device IRQ number */
/* Low-level status flags. */
volatile unsigned char start, /* start an operation */
interrupt; /* interrupt arrived */
unsigned long tbusy; /* transmitter busy must be long for bitops */
struct device *next;
......
......@@ -5,6 +5,7 @@
struct nfs_server {
struct file *file;
struct sockaddr toaddr ; /* Added for change to NFS code to use sendto() 1995-06-02 JSP */
int lock;
struct wait_queue *wait;
int flags;
......
/* $Id: scc.h,v 1.9 1995/01/12 18:24:40 JReuter Exp JReuter $ */
#ifndef _SCC_H
#define _SCC_H
......@@ -15,9 +14,9 @@
/* Constants */
#define MAXSCC 4 /* number of max. supported chips */
#define MAX_IBUFS 200 /* change this if you run out of memory */
#define BUFSIZE 128 /* must not exceed 4096 */
#define TPS 25 /* scc_timer(): Ticks Per Second */
#define MAX_IBUFS 300 /* change this if you run out of memory */
#define BUFSIZE 64 /* must not exceed 4096 */
#define TPS 25 /* scc_timer(): 25 Ticks Per Second */
#define SCC_TIMER 3
......@@ -134,15 +133,13 @@ typedef unsigned short ioaddr; /* old def */
/* Basic message buffer structure */
/* looks familiar? Hmm, yes... */
struct mbuf {
struct mbuf *next; /* Links mbufs belonging to single packets */
struct mbuf *anext; /* Links packets on queues */
char type; /* who allocated this buffer? */
int time_out; /* unimplemented yet */
unsigned long time_out;/* buffer time out */
int size; /* Size of associated data buffer */
int refcnt; /* Reference count */
struct mbuf *dup; /* Pointer to duplicated mbuf */
......@@ -240,16 +237,19 @@ struct scc_channel {
struct scc_stat stat; /* statistical information */
struct scc_modem modem; /* modem information */
struct mbuf *rbp; /* rx: Head of mbuf chain being filled */
struct mbuf *rbp1; /* rx: Pointer to mbuf currently being written */
struct mbuf *rcvq; /* Pointer to mbuf packets currently received */
char rxbuf[2048]; /* Rx frame buffer max framesize * 2 */
int rxbufcnt; /* Rx frame counter */
struct mbuf *sndq; /* tx: Packets awaiting transmission */
struct mbuf *tbp; /* tx: Transmit mbuf being sent */
struct mbuf *sndq1; /* Pointer to mbuf currently under construction */
struct mbuf *sndq2; /* Pointer to mbuf currently under construction */
/* unsigned char *xmit_buf;
int xmit_head;
int xmit_tail;
int xmit_cnt;*/
/* Timer */
......
......@@ -61,6 +61,7 @@ extern int nr_running, nr_tasks;
#include <linux/vm86.h>
#include <linux/math_emu.h>
#include <linux/ptrace.h>
#include <linux/timer.h>
#include <asm/processor.h>
......@@ -174,6 +175,7 @@ struct task_struct {
unsigned long timeout;
unsigned long it_real_value, it_prof_value, it_virt_value;
unsigned long it_real_incr, it_prof_incr, it_virt_incr;
struct timer_list real_timer;
long utime, stime, cutime, cstime, start_time;
struct rlimit rlim[RLIM_NLIMITS];
unsigned short used_math;
......@@ -237,7 +239,9 @@ struct task_struct {
/* suppl grps*/ {NOGROUP,}, \
/* proc links*/ &init_task,&init_task,NULL,NULL,NULL,NULL, \
/* uid etc */ 0,0,0,0,0,0,0,0, \
/* timeout */ 0,0,0,0,0,0,0,0,0,0,0,0, \
/* timeout */ 0,0,0,0,0,0,0, \
/* timer */ { NULL, NULL, 0, 0, it_real_fn }, \
/* utime */ 0,0,0,0,0, \
/* rlimits */ { {LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX}, \
{LONG_MAX, LONG_MAX}, {_STK_LIM, _STK_LIM}, \
{ 0, LONG_MAX}, {LONG_MAX, LONG_MAX}, \
......@@ -271,6 +275,7 @@ extern void sleep_on(struct wait_queue ** p);
extern void interruptible_sleep_on(struct wait_queue ** p);
extern void wake_up(struct wait_queue ** p);
extern void wake_up_interruptible(struct wait_queue ** p);
extern void wake_up_process(struct task_struct * tsk);
extern void notify_parent(struct task_struct * tsk);
extern int send_sig(unsigned long sig,struct task_struct * p,int priv);
......
/*
/* -- sjcd.h
*
* Definitions for a Sanyo CD-ROM interface
*
* Copyright (C) 1995 Vadim V. Model
......@@ -22,6 +23,11 @@
*/
#define SJCD_INTR_NR 10
/*
* Change this to set the dma channel.
*/
#define SJCD_DMA 0
/*
* port access macros
*/
......
......@@ -87,6 +87,8 @@ struct timer_list {
extern void add_timer(struct timer_list * timer);
extern int del_timer(struct timer_list * timer);
extern void it_real_fn(unsigned long);
extern inline void init_timer(struct timer_list * timer)
{
timer->next = NULL;
......
......@@ -143,7 +143,7 @@ _INLINE_ void run_task_queue(task_queue *list)
void (*f) (void *);
while(1) {
p = xchg_ptr(list,&tq_last);
p = xchg(list,&tq_last);
if(p == &tq_last)
break;
......
......@@ -28,9 +28,9 @@
#include <linux/if_tr.h>
#ifdef __KERNEL__
extern int tr_header(struct sk_buff *skb, struct device *dev,
extern int tr_header(unsigned char *buff, struct device *dev,
unsigned short type, void *daddr,
void *saddr, unsigned len);
void *saddr, unsigned len, struct sk_buff *skb);
extern int tr_rebuild_header(void *buff, struct device *dev,
unsigned long raddr, struct sk_buff *skb);
extern unsigned short tr_type_trans(struct sk_buff *skb, struct device *dev);
......
#ifndef _LINUX_UNISTD_H_
#define _LINUX_UNISTD_H_
/*
* This file contains the system call numbers.
*/
#define __NR_setup 0 /* used only by init, to get system going */
#define __NR_exit 1
#define __NR_fork 2
#define __NR_read 3
#define __NR_write 4
#define __NR_open 5
#define __NR_close 6
#define __NR_waitpid 7
#define __NR_creat 8
#define __NR_link 9
#define __NR_unlink 10
#define __NR_execve 11
#define __NR_chdir 12
#define __NR_time 13
#define __NR_mknod 14
#define __NR_chmod 15
#define __NR_chown 16
#define __NR_break 17
#define __NR_oldstat 18
#define __NR_lseek 19
#define __NR_getpid 20
#define __NR_mount 21
#define __NR_umount 22
#define __NR_setuid 23
#define __NR_getuid 24
#define __NR_stime 25
#define __NR_ptrace 26
#define __NR_alarm 27
#define __NR_oldfstat 28
#define __NR_pause 29
#define __NR_utime 30
#define __NR_stty 31
#define __NR_gtty 32
#define __NR_access 33
#define __NR_nice 34
#define __NR_ftime 35
#define __NR_sync 36
#define __NR_kill 37
#define __NR_rename 38
#define __NR_mkdir 39
#define __NR_rmdir 40
#define __NR_dup 41
#define __NR_pipe 42
#define __NR_times 43
#define __NR_prof 44
#define __NR_brk 45
#define __NR_setgid 46
#define __NR_getgid 47
#define __NR_signal 48
#define __NR_geteuid 49
#define __NR_getegid 50
#define __NR_acct 51
#define __NR_phys 52
#define __NR_lock 53
#define __NR_ioctl 54
#define __NR_fcntl 55
#define __NR_mpx 56
#define __NR_setpgid 57
#define __NR_ulimit 58
#define __NR_oldolduname 59
#define __NR_umask 60
#define __NR_chroot 61
#define __NR_ustat 62
#define __NR_dup2 63
#define __NR_getppid 64
#define __NR_getpgrp 65
#define __NR_setsid 66
#define __NR_sigaction 67
#define __NR_sgetmask 68
#define __NR_ssetmask 69
#define __NR_setreuid 70
#define __NR_setregid 71
#define __NR_sigsuspend 72
#define __NR_sigpending 73
#define __NR_sethostname 74
#define __NR_setrlimit 75
#define __NR_getrlimit 76
#define __NR_getrusage 77
#define __NR_gettimeofday 78
#define __NR_settimeofday 79
#define __NR_getgroups 80
#define __NR_setgroups 81
#define __NR_select 82
#define __NR_symlink 83
#define __NR_oldlstat 84
#define __NR_readlink 85
#define __NR_uselib 86
#define __NR_swapon 87
#define __NR_reboot 88
#define __NR_readdir 89
#define __NR_mmap 90
#define __NR_munmap 91
#define __NR_truncate 92
#define __NR_ftruncate 93
#define __NR_fchmod 94
#define __NR_fchown 95
#define __NR_getpriority 96
#define __NR_setpriority 97
#define __NR_profil 98
#define __NR_statfs 99
#define __NR_fstatfs 100
#define __NR_ioperm 101
#define __NR_socketcall 102
#define __NR_syslog 103
#define __NR_setitimer 104
#define __NR_getitimer 105
#define __NR_stat 106
#define __NR_lstat 107
#define __NR_fstat 108
#define __NR_olduname 109
#define __NR_iopl 110
#define __NR_vhangup 111
#define __NR_idle 112
#define __NR_vm86 113
#define __NR_wait4 114
#define __NR_swapoff 115
#define __NR_sysinfo 116
#define __NR_ipc 117
#define __NR_fsync 118
#define __NR_sigreturn 119
#define __NR_clone 120
#define __NR_setdomainname 121
#define __NR_uname 122
#define __NR_modify_ldt 123
#define __NR_adjtimex 124
#define __NR_mprotect 125
#define __NR_sigprocmask 126
#define __NR_create_module 127
#define __NR_init_module 128
#define __NR_delete_module 129
#define __NR_get_kernel_syms 130
#define __NR_quotactl 131
#define __NR_getpgid 132
#define __NR_fchdir 133
#define __NR_bdflush 134
#define __NR_sysfs 135
#define __NR_personality 136
#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
#define __NR_setfsuid 138
#define __NR_setfsgid 139
#define __NR__llseek 140
#define __NR_getdents 141
#define __NR__newselect 142
#define __NR_flock 143
extern int errno;
/*
......
......@@ -74,7 +74,7 @@ int request_dma(unsigned int dmanr, char * device_id)
if (dmanr >= MAX_DMA_CHANNELS)
return -EINVAL;
if (xchg_u32(&dma_chan_busy[dmanr].lock, 1) != 0)
if (xchg(&dma_chan_busy[dmanr].lock, 1) != 0)
return -EBUSY;
dma_chan_busy[dmanr].device_id = device_id;
......@@ -91,7 +91,7 @@ void free_dma(unsigned int dmanr)
return;
}
if (xchg_u32(&dma_chan_busy[dmanr].lock, 0) == 0) {
if (xchg(&dma_chan_busy[dmanr].lock, 0) == 0) {
printk("Trying to free free DMA%d\n", dmanr);
return;
}
......
......@@ -27,18 +27,18 @@ static int generate(unsigned long sig, struct task_struct * p)
struct sigaction * sa = sig + p->sigaction - 1;
/* always generate signals for traced processes ??? */
if (p->flags & PF_PTRACED) {
p->signal |= mask;
return 1;
if (!(p->flags & PF_PTRACED)) {
/* don't bother with ignored signals (but SIGCHLD is special) */
if (sa->sa_handler == SIG_IGN && sig != SIGCHLD)
return 0;
/* some signals are ignored by default.. (but SIGCONT already did its deed) */
if ((sa->sa_handler == SIG_DFL) &&
(sig == SIGCONT || sig == SIGCHLD || sig == SIGWINCH))
return 0;
}
/* don't bother with ignored signals (but SIGCHLD is special) */
if (sa->sa_handler == SIG_IGN && sig != SIGCHLD)
return 0;
/* some signals are ignored by default.. (but SIGCONT already did its deed) */
if ((sa->sa_handler == SIG_DFL) &&
(sig == SIGCONT || sig == SIGCHLD || sig == SIGWINCH))
return 0;
p->signal |= mask;
if (p->state == TASK_INTERRUPTIBLE && (p->signal & ~p->blocked))
wake_up_process(p);
return 1;
}
......@@ -58,7 +58,7 @@ int send_sig(unsigned long sig,struct task_struct * p,int priv)
return 0;
if ((sig == SIGKILL) || (sig == SIGCONT)) {
if (p->state == TASK_STOPPED)
p->state = TASK_RUNNING;
wake_up_process(p);
p->exit_code = 0;
p->signal &= ~( (1<<(SIGSTOP-1)) | (1<<(SIGTSTP-1)) |
(1<<(SIGTTIN-1)) | (1<<(SIGTTOU-1)) );
......@@ -382,6 +382,7 @@ NORET_TYPE void do_exit(long code)
}
fake_volatile:
current->flags |= PF_EXITING;
del_timer(&current->real_timer);
sem_exit();
exit_mmap(current);
free_page_tables(current);
......
......@@ -197,6 +197,8 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs)
p->signal = 0;
p->it_real_value = p->it_virt_value = p->it_prof_value = 0;
p->it_real_incr = p->it_virt_incr = p->it_prof_incr = 0;
init_timer(&p->real_timer);
p->real_timer.data = (unsigned long) p;
p->leader = 0; /* process leadership doesn't inherit */
p->tty_old_pgrp = 0;
p->utime = p->stime = 0;
......@@ -219,7 +221,7 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs)
p->mm->swappable = 1;
p->exit_signal = clone_flags & CSIGNAL;
p->counter = current->counter >> 1;
p->state = TASK_RUNNING; /* do this last, just in case */
wake_up_process(p); /* do this last, just in case */
return p->pid;
bad_fork_cleanup:
task[nr] = NULL;
......
......@@ -71,6 +71,17 @@ asmlinkage int sys_getitimer(int which, struct itimerval *value)
return 0;
}
void it_real_fn(unsigned long __data)
{
struct task_struct * p = (struct task_struct *) __data;
send_sig(SIGALRM, p, 1);
if (p->it_real_incr) {
p->real_timer.expires = p->it_real_incr;
add_timer(&p->real_timer);
}
}
int _setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
{
register unsigned long i, j;
......@@ -82,10 +93,10 @@ int _setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
return k;
switch (which) {
case ITIMER_REAL:
del_timer(&current->real_timer);
if (j) {
j += 1+itimer_ticks;
if (j < itimer_next)
itimer_next = j;
current->real_timer.expires = j;
add_timer(&current->real_timer);
}
current->it_real_value = j;
current->it_real_incr = i;
......
......@@ -151,6 +151,7 @@ struct symbol_table symbol_table = {
X(kfree_s),
X(vmalloc),
X(vfree),
X(mem_map),
/* filesystem internal functions */
X(getname),
......@@ -243,6 +244,7 @@ struct symbol_table symbol_table = {
X(tq_last),
X(timer_active),
X(timer_table),
X(intr_count),
/* dma handling */
X(request_dma),
......@@ -310,6 +312,7 @@ struct symbol_table symbol_table = {
X(slhc_remember),
X(slhc_compress),
X(slhc_uncompress),
X(slhc_toss),
#endif
#endif
/* Device callback registration */
......@@ -384,8 +387,6 @@ struct symbol_table symbol_table = {
X(generic_proc_info),
X(scsi_devices),
X(free_pages),
X(intr_count),
X(mem_map),
X(print_msg),
X(print_status),
X(gendisk_head), /* Needed for sd.c */
......@@ -395,8 +396,6 @@ struct symbol_table symbol_table = {
* With no scsi configured, we still need to export a few
* symbols so that scsi can be loaded later via insmod.
*/
X(intr_count),
X(mem_map),
X(gendisk_head),
X(resetup_one_dev),
......
......@@ -92,8 +92,27 @@ struct task_struct * task[NR_TASKS] = {&init_task, };
struct kernel_stat kstat = { 0 };
unsigned long itimer_ticks = 0;
unsigned long itimer_next = ~0;
/*
* Wake up a process. Put it on the run-queue if it's not
* already there. The "current" process is always on the
* run-queue, and as such you're allowed to do the simpler
* "current->state = TASK_RUNNING" to mark yourself runnable
* without the overhead of this.
*
* (actually, the run-queue isn't implemented yet, so this
* function is mostly a dummy one)
*/
inline void wake_up_process(struct task_struct * p)
{
long oldstate;
oldstate = xchg(&p->state, TASK_RUNNING);
/* already on run-queue? */
if (oldstate == TASK_RUNNING || p == current)
return;
if (p->counter > current->counter + 3)
need_resched = 1;
}
/*
* 'schedule()' is the scheduler function. It's a very simple and nice
......@@ -103,16 +122,12 @@ unsigned long itimer_next = ~0;
* NOTE!! Task 0 is the 'idle' task, which gets called when no other
* tasks can run. It can not be killed, and it cannot sleep. The 'state'
* information in task[0] is never used.
*
* The "confuse_gcc" goto is used only to get better assembly code..
* Dijkstra probably hates me.
*/
asmlinkage void schedule(void)
{
int c;
struct task_struct * p;
struct task_struct * next;
unsigned long ticks;
/* check alarm, wake up any interruptible tasks that have got a signal */
......@@ -121,69 +136,35 @@ asmlinkage void schedule(void)
intr_count = 0;
}
run_task_queue(&tq_scheduler);
cli();
ticks = itimer_ticks;
itimer_ticks = 0;
itimer_next = ~0;
sti();
if (current->state == TASK_INTERRUPTIBLE) {
if (current->signal & ~current->blocked)
current->state = TASK_RUNNING;
}
need_resched = 0;
nr_running = 0;
p = &init_task;
for (;;) {
if ((p = p->next_task) == &init_task)
goto confuse_gcc1;
if (ticks && p->it_real_value) {
if (p->it_real_value <= ticks) {
send_sig(SIGALRM, p, 1);
if (!p->it_real_incr) {
p->it_real_value = 0;
goto end_itimer;
}
do {
p->it_real_value += p->it_real_incr;
} while (p->it_real_value <= ticks);
}
p->it_real_value -= ticks;
if (p->it_real_value < itimer_next)
itimer_next = p->it_real_value;
}
end_itimer:
if (p->state != TASK_INTERRUPTIBLE)
continue;
if (p->signal & ~p->blocked) {
p->state = TASK_RUNNING;
continue;
}
if (p->timeout && p->timeout <= jiffies) {
p->timeout = 0;
p->state = TASK_RUNNING;
}
}
confuse_gcc1:
/* this is the scheduler proper: */
#if 0
/* give processes that go to sleep a bit higher priority.. */
/* This depends on the values for TASK_XXX */
/* This gives smoother scheduling for some things, but */
/* can be very unfair under some circumstances, so.. */
if (TASK_UNINTERRUPTIBLE >= (unsigned) current->state &&
current->counter < current->priority*2) {
++current->counter;
}
#endif
c = -1000;
next = p = &init_task;
for (;;) {
if ((p = p->next_task) == &init_task)
goto confuse_gcc2;
if (p->state == TASK_RUNNING) {
nr_running++;
if (p->counter > c)
c = p->counter, next = p;
next = &init_task;
for_each_task(p) {
switch (p->state) {
case TASK_INTERRUPTIBLE:
if (!p->timeout)
continue;
if (p->timeout > jiffies)
continue;
p->timeout = 0;
p->state = TASK_RUNNING;
/* fall through */
case TASK_RUNNING:
nr_running++;
if (p->counter > c)
c = p->counter, next = p;
}
}
confuse_gcc2:
/* if all runnable processes have "counter == 0", re-calculate counters */
if (!c) {
for_each_task(p)
p->counter = (p->counter >> 1) + p->priority;
......@@ -219,11 +200,8 @@ void wake_up(struct wait_queue **q)
do {
if ((p = tmp->task) != NULL) {
if ((p->state == TASK_UNINTERRUPTIBLE) ||
(p->state == TASK_INTERRUPTIBLE)) {
p->state = TASK_RUNNING;
if (p->counter > current->counter + 3)
need_resched = 1;
}
(p->state == TASK_INTERRUPTIBLE))
wake_up_process(p);
}
if (!tmp->next) {
printk("wait_queue is bad (eip = %p)\n",
......@@ -246,11 +224,8 @@ void wake_up_interruptible(struct wait_queue **q)
return;
do {
if ((p = tmp->task) != NULL) {
if (p->state == TASK_INTERRUPTIBLE) {
p->state = TASK_RUNNING;
if (p->counter > current->counter + 3)
need_resched = 1;
}
if (p->state == TASK_INTERRUPTIBLE)
wake_up_process(p);
}
if (!tmp->next) {
printk("wait_queue is bad (eip = %p)\n",
......@@ -665,9 +640,6 @@ static void do_timer(int irq, struct pt_regs * regs)
mark_bh(TIMER_BH);
}
cli();
itimer_ticks++;
if (itimer_ticks > itimer_next)
need_resched = 1;
if (timer_head.next->expires < jiffies)
mark_bh(TIMER_BH);
if (tq_timer != &tq_last)
......
......@@ -82,7 +82,7 @@ static int add_to_swap_cache(unsigned long addr, unsigned long entry)
swap_cache_add_total++;
#endif
if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) {
entry = (unsigned long) xchg_ptr(swap_cache + MAP_NR(addr), (void *) entry);
entry = xchg(swap_cache + MAP_NR(addr), entry);
if (entry) {
printk("swap_cache: replacing non-NULL entry\n");
}
......
......@@ -178,7 +178,6 @@ static void aarp_send_reply(struct device *dev, struct at_addr *us, struct at_ad
eah = (struct elapaarp *)skb_put(skb,sizeof(struct elapaarp));
skb->arp = 1;
skb->free = 1;
skb_put(skb,len);
skb->dev = dev;
/*
......@@ -243,7 +242,6 @@ void aarp_send_probe(struct device *dev, struct at_addr *us)
skb->arp = 1;
skb->free = 1;
skb_put(skb,len);
skb->dev = dev;
/*
......
......@@ -26,6 +26,7 @@
* Alan Cox : ARP only when compiled with CONFIG_INET
* Greg Page : 802.2 and SNAP stuff.
* Alan Cox : MAC layer pointers/new format.
* Paul Gortmaker : eth_copy_and_sum shouldn't csum padding.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -231,11 +232,13 @@ void eth_header_cache(struct device *dev, struct sock *sk, unsigned long saddr,
/*
* Copy from an ethernet device memory space to an sk_buff while checksumming if IP
* The magic "34" is Rx_addr+Tx_addr+type_field+sizeof(struct iphdr) == 6+6+2+20.
*/
void eth_copy_and_sum(struct sk_buff *dest, unsigned char *src, int length, int base)
{
struct ethhdr *eth;
struct iphdr *iph;
IS_SKB(dest);
eth=(struct ethhdr *)dest->data;
......@@ -246,6 +249,14 @@ void eth_copy_and_sum(struct sk_buff *dest, unsigned char *src, int length, int
memcpy(dest->data+34,src+34,length);
return;
}
/*
* We have to watch for padded packets. The csum doesn't include the
* padding, and there is no point in copying the padding anyway.
*/
iph=(struct iphdr*)(src+14); /* 14 = Rx_addr+Tx_addr+type_field */
if (ntohs(iph->tot_len)-sizeof(struct iphdr) <= length)
length=ntohs(iph->tot_len)-sizeof(struct iphdr);
dest->csum=csum_partial_copy(src+34,dest->data+34,length,base);
dest->ip_summed=1;
}
......@@ -733,7 +733,7 @@ void ip_fw_masquerade(struct sk_buff **skb_ptr, struct device *dev)
if (portptr[1]==htons(21))
{
skb = revamp(*skb_ptr, dev, ms);
skb = *skb_ptr;
*skb_ptr = skb;
iph = skb->h.iph;
portptr = (unsigned short *)&(((char *)iph)[iph->ihl*4]);
}
......
......@@ -145,6 +145,11 @@
* sk->retransmits misupdating fixed.
* Fixed tcp_write_timeout: stuck close,
* and TCP syn retries gets used now.
* Mark Yarvis : In tcp_read_wakeup(), don't send an
* ack if stat is TCP_CLOSED.
* Alan Cox : Look up device on a retransmit - routes may
* change. Doesn't yet cope with MSS shrink right
* but its a start!
*
*
* To Fix:
......@@ -439,6 +444,7 @@ void tcp_do_retransmit(struct sock *sk, int all)
struct proto *prot;
struct device *dev;
int ct=0;
struct rtable *rt;
prot = sk->prot;
skb = sk->send_head;
......@@ -453,6 +459,12 @@ void tcp_do_retransmit(struct sock *sk, int all)
IS_SKB(skb);
skb->when = jiffies;
/*
* Discard the surplus MAC header
*/
skb_pull(skb,((unsigned char *)skb->ip_hdr)-skb->data);
/*
* In general it's OK just to use the old packet. However we
* need to use the current ack and window fields. Urg and
......@@ -462,60 +474,89 @@ void tcp_do_retransmit(struct sock *sk, int all)
* changing the packet, we have to issue a new IP identifier.
*/
iph = (struct iphdr *)(skb->data + dev->hard_header_len);
iph = (struct iphdr *)skb->data;
th = (struct tcphdr *)(((char *)iph) + (iph->ihl << 2));
size = skb->len - (((unsigned char *) th) - skb->data);
size = ntohs(iph->tot_len) - (iph->ihl<<2);
/*
* Note: We ought to check for window limits here but
* currently this is done (less efficiently) elsewhere.
* We do need to check for a route change but can't handle
* that until we have the new 1.3.x buffers in.
*
*/
iph->id = htons(ip_id_count++);
ip_send_check(iph);
/*
* This is not the right way to handle this. We have to
* issue an up to date window and ack report with this
* retransmit to keep the odd buggy tcp that relies on
* the fact BSD does this happy.
* We don't however need to recalculate the entire
* checksum, so someone wanting a small problem to play
* with might like to implement RFC1141/RFC1624 and speed
* this up by avoiding a full checksum.
*/
th->ack_seq = ntohl(sk->acked_seq);
th->window = ntohs(tcp_select_window(sk));
tcp_send_check(th, sk->saddr, sk->daddr, size, sk);
/*
* If the interface is (still) up and running, kick it.
* Put a MAC header back on (may cause ARPing)
*/
if (dev->flags & IFF_UP)
if(skb->localroute)
rt=ip_rt_local(iph->daddr,NULL,NULL);
else
rt=ip_rt_route(iph->daddr,NULL,NULL);
if(rt==NULL) /* Deep poo */
{
if(skb->sk)
{
skb->sk->err=ENETUNREACH;
skb->sk->error_report(skb->sk);
}
}
else
{
dev=rt->rt_dev;
skb->raddr=rt->rt_gateway;
if(skb->raddr==0)
skb->raddr=iph->daddr;
skb->dev=dev;
skb->arp=1;
if(dev->hard_header)
{
if(dev->hard_header(skb, dev, ETH_P_IP, NULL, NULL, skb->len)<0)
skb->arp=0;
}
/*
* This is not the right way to handle this. We have to
* issue an up to date window and ack report with this
* retransmit to keep the odd buggy tcp that relies on
* the fact BSD does this happy.
* We don't however need to recalculate the entire
* checksum, so someone wanting a small problem to play
* with might like to implement RFC1141/RFC1624 and speed
* this up by avoiding a full checksum.
*/
th->ack_seq = ntohl(sk->acked_seq);
th->window = ntohs(tcp_select_window(sk));
tcp_send_check(th, sk->saddr, sk->daddr, size, sk);
/*
* If the packet is still being sent by the device/protocol
* below then don't retransmit. This is both needed, and good -
* especially with connected mode AX.25 where it stops resends
* occurring of an as yet unsent anyway frame!
* We still add up the counts as the round trip time wants
* adjusting.
* If the interface is (still) up and running, kick it.
*/
if (sk && !skb_device_locked(skb))
if (dev->flags & IFF_UP)
{
/* Remove it from any existing driver queue first! */
skb_unlink(skb);
/* Now queue it */
ip_statistics.IpOutRequests++;
dev_queue_xmit(skb, dev, sk->priority);
/*
* If the packet is still being sent by the device/protocol
* below then don't retransmit. This is both needed, and good -
* especially with connected mode AX.25 where it stops resends
* occurring of an as yet unsent anyway frame!
* We still add up the counts as the round trip time wants
* adjusting.
*/
if (sk && !skb_device_locked(skb))
{
/* Remove it from any existing driver queue first! */
skb_unlink(skb);
/* Now queue it */
ip_statistics.IpOutRequests++;
dev_queue_xmit(skb, dev, sk->priority);
}
}
}
/*
* Count retransmissions
*/
......@@ -1771,6 +1812,13 @@ static void tcp_read_wakeup(struct sock *sk)
if (!sk->ack_backlog)
return;
/*
* If we're closed, don't send an ack, or we'll get a RST
* from the closed destination.
*/
if ((sk->state == TCP_CLOSE) || (sk->state == TCP_TIME_WAIT))
return;
/*
* FIXME: we need to put code here to prevent this routine from
* being called. Being called once in a while is ok, so only check
......@@ -3034,8 +3082,7 @@ static void tcp_write_xmit(struct sock *sk)
* Ack and window will in general have changed since this packet was put
* on the write queue.
*/
iph = (struct iphdr *)(skb->data +
skb->dev->hard_header_len);
iph = skb->ip_hdr;
th = (struct tcphdr *)(((char *)iph) +(iph->ihl << 2));
size = skb->len - (((unsigned char *) th) - skb->data);
......
......@@ -45,8 +45,7 @@
* Arnt Gulbrandsen : New udp_send and stuff
* Alan Cox : Cache last socket
* Alan Cox : Route cache
* Alan Cox : Checksum precompute is bogus is some lame
* software is padding its udp frames in IP!
* Jon Peatfield : Minor efficientcy fix to sendto().
*
*
* This program is free software; you can redistribute it and/or
......@@ -301,10 +300,9 @@ static int udp_sendto(struct sock *sk, unsigned char *from, int len, int noblock
{
if (addr_len < sizeof(sin))
return(-EINVAL);
memcpy(&sin,usin,sizeof(sin));
if (sin.sin_family && sin.sin_family != AF_INET)
if (usin->sin_family && usin->sin_family != AF_INET)
return(-EINVAL);
if (sin.sin_port == 0)
if (usin->sin_port == 0)
return(-EINVAL);
}
else
......@@ -314,6 +312,7 @@ static int udp_sendto(struct sock *sk, unsigned char *from, int len, int noblock
sin.sin_family = AF_INET;
sin.sin_port = sk->dummy_th.dest;
sin.sin_addr.s_addr = sk->daddr;
usin = &sin;
}
/*
......@@ -321,16 +320,16 @@ static int udp_sendto(struct sock *sk, unsigned char *from, int len, int noblock
* broadcasting of data.
*/
if(sin.sin_addr.s_addr==INADDR_ANY)
sin.sin_addr.s_addr=ip_my_addr();
if(usin->sin_addr.s_addr==INADDR_ANY)
usin->sin_addr.s_addr=ip_my_addr();
if(!sk->broadcast && ip_chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
if(!sk->broadcast && ip_chk_addr(usin->sin_addr.s_addr)==IS_BROADCAST)
return -EACCES; /* Must turn broadcast on first */
sk->inuse = 1;
/* Send the packet. */
tmp = udp_send(sk, &sin, from, len, flags);
tmp = udp_send(sk, usin, from, len, flags);
/* The datagram has been sent off. Release the socket. */
release_sock(sk);
......@@ -538,9 +537,6 @@ int udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
ulen = ntohs(uh->len);
if(ulen!=len)
skb->ip_summed=0; /* Bogoid padded frame */
if (ulen > len || len < sizeof(*uh) || ulen < sizeof(*uh))
{
NETDEBUG(printk("UDP: short packet: %d/%d\n", ulen, len));
......
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