Commit 4cfb4152 authored by Linus Torvalds's avatar Linus Torvalds

Linux 2.2.5 - and a vacation

I made Linux-2.2.5 yesterday (as some people already have noticed: due to
popular demand I try to delay the announcement for some time in order to
let the thing percolate to mirror sites, in case anybody wondered).
The 2.2.5 release is meant to be a final cleanup release before I leave
for a two-week vacation. So please take these release notes to also mean
that it is probably a good idea to hold off emailing me stuff directly,
unless it is a major bug that you really think I should look at
immediately. I would suggest people discuss problems on the mailing list
and on the newsgroups, where other competent people are, rather than
expecting me to do much about it.

Also, note that there have been various indications that egcs potentially
miscompiles the kernel, or at least makes some problems worse. We don't
know whether that is due to one or more kernel bugs, compiler problems, or
just combinations of "features" in both. I would suggest that if you have
problems you at least verify whether the problems still exist with
gcc-2.7.2.

That said, I bet that both the kernel people and the egcs people would be
really happy the more people look into this - if somebody feels motivated
enough and sees problems with egcs, it would be extremely powerful to try
to pinpoint the particular file that seems to bring on the problems. I'm
afraid it needs a known failure mode and lots of legwork to find out what
triggers it, though.

 - compiles with accounting.
 - add support for Microgate SyncLink and Synchronous HDLC
 - stallion driver update
 - alpha EV6 and SMP fix for bootup with newer compilers
 - ptrace fix for sparc/i386
 - small sparc updates
 - floppy driver could oops at bootup under certain setups
 - random driver updates (bw-qcam, sound driver error codes, etc oneliners)
 - FIOASYNC ioctl fix
 - network locking fixes
 - SMP "struct user" and signal sending fixes

Have fun, because I will,

                        Linus
parent d3c37b33
......@@ -2,10 +2,10 @@
Stallion Multiport Serial Driver Readme
---------------------------------------
Copyright (C) 1994-1998, Stallion Technologies (support@stallion.com).
Copyright (C) 1994-1999, Stallion Technologies (support@stallion.com).
Version: 5.4.7
Date: 23OCT98
Version: 5.5.1
Date: 28MAR99
......@@ -15,28 +15,28 @@ There are two drivers that work with the different families of Stallion
multiport serial boards. One is for the Stallion smart boards - that is
EasyIO, EasyConnection 8/32 and EasyConnection 8/64-PCI, the other for
the true Stallion intelligent multiport boards - EasyConnection 8/64
(ISA and EISA), ONboard and Brumby.
(ISA, EISA, MCA), EasyConnection/RA-PCI, ONboard and Brumby.
If you are using any of the Stallion intelligent multiport boards (Brumby,
ONboard, EasyConnection 8/64 (ISA or EISA)) with Linux you will need to
get the driver utility package. This package is available at most of the
Linux archive sites (and on CD-ROMs that contain these archives). The file
will be called stallion-X.X.X.tar.gz where X.X.X will be the version
number. In particular this package contains the board embedded executable
images that are required for these boards. It also contains the downloader
program. These boards cannot be used without this.
ONboard, EasyConnection 8/64 (ISA, EISA, MCA), EasyConnection/RA-PCI) with
Linux you will need to get the driver utility package. This package is
available at most of the Linux archive sites (and on CD-ROMs that contain
these archives). The file will be called stallion-X.X.X.tar.gz where X.X.X
will be the version number. In particular this package contains the board
embedded executable images that are required for these boards. It also
contains the downloader program. These boards cannot be used without this.
The Stallion Technologies ftp site, ftp.stallion.com, will always have
the latest version of the driver utility package. Other sites that usually
have the latest version are tsx-11.mit.edu, sunsite.unc.edu and their
mirrors.
ftp.stallion.com:/drivers/ata5/Linux/v544.tar.gz
tsx-11.mit.edu:/pub/linux/packages/stallion/stallion-5.4.4.tar.gz
sunsite.unc.edu:/pub/Linux/kernel/patches/serial/stallion-5.4.4.tar.gz
ftp.stallion.com:/drivers/ata5/Linux/v550.tar.gz
tsx-11.mit.edu:/pub/linux/packages/stallion/stallion-5.5.0.tar.gz
sunsite.unc.edu:/pub/Linux/kernel/patches/serial/stallion-5.5.0.tar.gz
As of the printing of this document the latest version of the driver
utility package is 5.4.4. If a later version is now available then you
utility package is 5.5.0. If a later version is now available then you
should use the latest version.
If you are using the EasyIO, EasyConnection 8/32 or EasyConnection 8/64-PCI
......@@ -44,7 +44,7 @@ boards then you don't need this package. Although it does have a handy
script to create the /dev device nodes for these boards, and a serial stats
display program.
If you require DIP switch settings, EISA/MCA configuration files, or any
If you require DIP switch settings, EISA or MCA configuration files, or any
other information related to Stallion boards then have a look at Stallion's
web pages at http://www.stallion.com.
......@@ -55,12 +55,101 @@ web pages at http://www.stallion.com.
The drivers can be used as loadable modules or compiled into the kernel.
You can choose which when doing a "config" on the kernel.
All ISA, EISA and MCA boards that you want to use need to be entered into
the driver(s) configuration structures. All PCI boards will be automatically
detected when you load the driver - so they do not need to be entered into
the driver(s) configuration structure. (Note that kernel PCI BIOS32 support
is required to use PCI boards.)
All ISA, EISA and MCA boards that you want to use need to be configured into
the driver(s). All PCI boards will be automatically detected when you load
the driver - so they do not need to be entered into the driver(s)
configuration structure. Note that kernel PCI support is required to use PCI
boards.
There are two methods of configuring ISA, EISA and MCA boards into the drivers.
If using the driver as a loadable module then the simplist method is to pass
the driver configuration as module arguments. The other method is to modify
the driver source to add configuration lines for each board in use.
If you have pre-built Stallion driver modules then the module argument
configuration method should be used. A lot of Linux distributions come with
pre-built driver modules in /lib/modules/X.Y.Z/misc for the kernel in use.
That makes things pretty simple to get going.
2.1 MODULE DRIVER CONFIGURATION:
The simplest configuration for modules is to use the module load arguments
to configure any ISA, EISA or MCA boards. PCI boards are automatically
detected, so do not need any additional configuration at all.
If using EasyIO, EasyConnection 8/32 ISA or MCA, or EasyConnection 8/63-PCI
boards then use the "stallion" driver module, Otherwise if you are using
an EasyConnection 8/64 ISA, EISA or MCA, EasyConnection/RA-PCI, ONboard,
Brumby or original Stallion board then use the "istallion" driver module.
Typically to load up the smart board driver use:
insmod stallion.o
This will load the EasyIO and EasyConnection 8/32 driver. It will output a
message to say that it loaded and print the driver version number. It will
also print out whether it found the configured boards or not. These messages
may not appear on the console, but typically are always logged to
/var/adm/messages or /var/log/syslog files - depending on how the klogd and
syslogd daemons are setup on your system.
To load the intelligent board driver use:
insmod istallion.o
It will output similar messages to the smart board driver.
If not using an auto-detectable board type (that is a PCI board) then you
will also need to supply command line arguments to the "insmod" command
when loading the driver. The general form of the configuration argument is
board?=<name>[,<ioaddr>[,<addr>][,<irq>]]
where:
board? -- specifies the arbitary board number of this board,
can be in the range 0 to 3.
name -- textual name of this board. The board name is the comman
board name, or any "shortened" version of that. The board
type number may also be used here.
ioaddr -- specifies the I/O address of this board. This argument is
optional, but should generally be specified.
addr -- optional second address argument. Some board types require
a second I/O address, some require a memory address. The
exact meaning of this argument depends on the board type.
irq -- optional IRQ line used by this board.
Up to 4 board configuration arguments can be specified on the load line.
Here is some examples:
insmod stallion.o board0=easyio,0x2a0,5
This configures an EasyIO board as board 0 at I/O address 0x2a0 and IRQ 5.
insmod istallion.o board3=ec8/64,0x2c0,0xcc000
This configures an EasyConnection 8/64 ISA as board 3 at I/O address 0x2c0 at
memory address 0xcc000.
insmod stallion.o board1=ec8/32-at,0x2a0,0x280,10
This configures an EasyConnection 8/32 ISA board at primary I/O address 0x2a0,
secondary address 0x280 and IRQ 10.
You will probably want to enter this module load and configuration information
into your system startup scripts so that the drivers are loaded and configured
on each system boot. Typically the start up script would be something line
/etc/rc.d/rc.modules.
2.2 STATIC DRIVER CONFIGURATION:
For static driver configuration you need to modify the driver source code.
Entering ISA, EISA and MCA boards into the driver(s) configuration structure
involves editing the driver(s) source file. It's pretty easy if you follow
the instructions below. Both drivers can support up to 4 boards. The smart
......@@ -96,14 +185,16 @@ When the new kernel is booted, or the loadable module loaded then the
driver will emit some kernel trace messages about whether the configured
boards were detected or not. Depending on how your system logger is set
up these may come out on the console, or just be logged to
/var/adm/messages. You should check the messages to confirm that all is well.
/var/adm/messages or /var/log/syslog. You should check the messages to
confirm that all is well.
2.1 SHARING INTERRUPTS
2.3 SHARING INTERRUPTS
It is possible to share interrupts between multiple EasyIO and
EasyConnection 8/32 boards in an EISA system. To do this you will need to
do a couple of things:
EasyConnection 8/32 boards in an EISA system. To do this you must be using
static driver configuration, modifying the driver source code to add driver
configuration. Then a couple of extra things are required:
1. When entering the board resources into the stallion.c file you need to
mark the boards as using level triggered interrupts. Do this by replacing
......@@ -130,7 +221,7 @@ or load the driver your EasyIO and EasyConnection 8/32 boards will be
sharing interrupts.
2.2 USING HIGH SHARED MEMORY
2.4 USING HIGH SHARED MEMORY
The EasyConnection 8/64-EI, ONboard and Stallion boards are capable of
using shared memory addresses above the usual 640K - 1Mb range. The ONboard
......@@ -145,16 +236,18 @@ Just enter the address as you normally would for a lower than 1Mb address
2.3 TROUBLE SHOOTING
2.5 TROUBLE SHOOTING
If a board is not found by the driver but is actually in the system then the
most likely problem is that the I/O address is wrong. Change it in the driver
stallion.c or istallion.c configuration structure and rebuild the kernel or
modules, or change it on the board. On EasyIO and EasyConnection 8/32 boards
the IRQ is software programmable, so if there is a conflict you may need to
change the IRQ used for a board in the stallion.c configuration structure.
There are no interrupts to worry about for ONboard, Brumby or EasyConnection
8/64 (ISA, EISA and MCA) boards. The memory region on EasyConnection 8/64 and
most likely problem is that the I/O address is wrong. Change the module load
argument for the loadable module form. Or change it in the driver stallion.c
or istallion.c configuration structure and rebuild the kernel or modules, or
change it on the board.
On EasyIO and EasyConnection 8/32 boards the IRQ is software programmable, so
if there is a conflict you may need to change the IRQ used for a board. There
are no interrupts to worry about for ONboard, Brumby or EasyConnection 8/64
(ISA, EISA and MCA) boards. The memory region on EasyConnection 8/64 and
ONboard boards is software programmable, but not on the Brumby boards.
......@@ -167,9 +260,13 @@ The intelligent boards also need to have their "firmware" code downloaded
to them. This is done via a user level application supplied in the driver
utility package called "stlload". Compile this program wherever you dropped
the package files, by typing "make". In its simplest form you can then type
./stlload -i cdk.sys
in this directory and that will download board 0 (assuming board 0 is an
EasyConnection 8/64 board). To download to an ONboard, Brumby or Stallion do:
EasyConnection 8/64 or EasyConnection/RA board). To download to an
ONboard, Brumby or Stallion do:
./stlload -i 2681.sys
Normally you would want all boards to be downloaded as part of the standard
......@@ -182,6 +279,7 @@ file in the stlload down-loader is /usr/lib/stallion. Create that directory
and put the cdk.sys and 2681.sys files in it. (It's a convenient place to put
them anyway). As an example your /etc/rc.d/rc.S file might have the
following lines added to it (if you had 3 boards):
/usr/sbin/stlload -b 0 -i /usr/lib/stallion/cdk.sys
/usr/sbin/stlload -b 1 -i /usr/lib/stallion/2681.sys
/usr/sbin/stlload -b 2 -i /usr/lib/stallion/2681.sys
......
......@@ -499,6 +499,7 @@ secondary_cpu_start(int cpuid, struct task_struct *idle)
return;
}
mdelay(1);
barrier();
}
DBGS(("secondary_cpu_start: SUCCESS for CPU %d!!!\n", cpuid));
}
......@@ -541,6 +542,7 @@ send_cpu_msg(char *str, int cpuid)
if (!(hwrpb->txrdy & cpumask))
goto ready1;
udelay(100);
barrier();
}
goto timeout;
......@@ -549,6 +551,7 @@ send_cpu_msg(char *str, int cpuid)
if (!(hwrpb->txrdy & cpumask))
goto ready2;
udelay(100);
barrier();
}
goto timeout;
......
......@@ -347,6 +347,17 @@ extern unsigned long xcall_flush_tlb_all;
extern unsigned long xcall_tlbcachesync;
extern unsigned long xcall_flush_cache_all;
extern unsigned long xcall_report_regs;
extern unsigned long xcall_receive_signal;
void smp_receive_signal(int cpu)
{
if(smp_processors_ready &&
(cpu_present_map & (1UL<<cpu)) != 0) {
u64 pstate, data0 = (((u64)&xcall_receive_signal) & 0xffffffff);
__asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate));
xcall_deliver(data0, 0, 0, pstate, cpu);
}
}
void smp_report_regs(void)
{
......
/* $Id: init.c,v 1.124 1999/02/08 07:01:42 ecd Exp $
/* $Id: init.c,v 1.125 1999/03/28 08:39:33 davem Exp $
* arch/sparc64/mm/init.c
*
* Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
......@@ -142,9 +142,9 @@ void show_mem(void)
printk("%d reserved pages\n",reserved);
printk("%d pages shared\n",shared);
printk("%d pages swap cached\n",cached);
printk("%ld pages in page table cache\n",pgtable_cache_size);
printk("%d pages in page table cache\n",pgtable_cache_size);
#ifndef __SMP__
printk("%ld entries in page dir cache\n",pgd_cache_size);
printk("%d entries in page dir cache\n",pgd_cache_size);
#endif
show_buffers();
#ifdef CONFIG_NET
......
/* $Id: ultra.S,v 1.31 1998/11/07 06:39:21 davem Exp $
/* $Id: ultra.S,v 1.32 1999/03/28 08:39:34 davem Exp $
* ultra.S: Don't expand these all over the place...
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
......@@ -261,6 +261,21 @@ xcall_capture:
b,pt %xcc, rtrap
clr %l6
.globl xcall_receive_signal
xcall_receive_signal:
rdpr %pstate, %g2
wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate
rdpr %tstate, %g1
andcc %g1, TSTATE_PRIV, %g0
/* If we did not trap from user space, just ignore. */
bne,pn %xcc, 99f
sethi %hi(109f), %g7
b,pt %xcc, etrap
109: or %g7, %lo(109b), %g7
b,pt %xcc, rtrap
clr %l6
99: retry
/* These two are not performance critical... */
.globl xcall_flush_tlb_all
xcall_flush_tlb_all:
......
......@@ -3,7 +3,7 @@
/*
* istallion.c -- stallion intelligent multiport serial driver.
*
* Copyright (C) 1996-1998 Stallion Technologies (support@stallion.oz.au).
* Copyright (C) 1996-1999 Stallion Technologies (support@stallion.oz.au).
* Copyright (C) 1994-1996 Greg Ungerer (gerg@stallion.oz.au).
*
* This code is loosely based on the Linux serial driver, written by
......@@ -27,29 +27,24 @@
/*****************************************************************************/
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/wait.h>
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/termios.h>
#include <linux/fcntl.h>
#include <linux/tty_driver.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/cdk.h>
#include <linux/comstats.h>
#include <linux/istallion.h>
#include <linux/string.h>
#include <linux/malloc.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#ifdef CONFIG_PCI
#include <linux/pci.h>
#endif
/*****************************************************************************/
/*
......@@ -79,6 +74,7 @@
#define BRD_ECHPCI 26
#define BRD_ECH64PCI 27
#define BRD_EASYIOPCI 28
#define BRD_ECPPCI 29
#define BRD_BRUMBY BRD_BRUMBY4
......@@ -131,7 +127,7 @@ typedef struct {
} stlconf_t;
static stlconf_t stli_brdconf[] = {
{ BRD_ECP, 0x2a0, 0, 0xcc000, 0, 0 },
/*{ BRD_ECP, 0x2a0, 0, 0xcc000, 0, 0 },*/
};
static int stli_nrbrds = sizeof(stli_brdconf) / sizeof(stlconf_t);
......@@ -170,7 +166,7 @@ static int stli_nrbrds = sizeof(stli_brdconf) / sizeof(stlconf_t);
*/
static char *stli_drvtitle = "Stallion Intelligent Multiport Serial Driver";
static char *stli_drvname = "istallion";
static char *stli_drvversion = "5.4.7";
static char *stli_drvversion = "5.5.1";
static char *stli_serialname = "ttyE";
static char *stli_calloutname = "cue";
......@@ -296,8 +292,110 @@ static char *stli_brdnames[] = {
"EC8/32-PCI",
"EC8/64-PCI",
"EasyIO-PCI",
"EC/RA-PCI",
};
/*****************************************************************************/
#ifdef MODULE
/*
* Define some string labels for arguments passed from the module
* load line. These allow for easy board definitions, and easy
* modification of the io, memory and irq resoucres.
*/
static char *board0[8];
static char *board1[8];
static char *board2[8];
static char *board3[8];
static char **stli_brdsp[] = {
(char **) &board0,
(char **) &board1,
(char **) &board2,
(char **) &board3
};
/*
* Define a set of common board names, and types. This is used to
* parse any module arguments.
*/
typedef struct stlibrdtype {
char *name;
int type;
} stlibrdtype_t;
static stlibrdtype_t stli_brdstr[] = {
{ "stallion", BRD_STALLION },
{ "1", BRD_STALLION },
{ "brumby", BRD_BRUMBY },
{ "brumby4", BRD_BRUMBY },
{ "brumby/4", BRD_BRUMBY },
{ "brumby-4", BRD_BRUMBY },
{ "brumby8", BRD_BRUMBY },
{ "brumby/8", BRD_BRUMBY },
{ "brumby-8", BRD_BRUMBY },
{ "brumby16", BRD_BRUMBY },
{ "brumby/16", BRD_BRUMBY },
{ "brumby-16", BRD_BRUMBY },
{ "2", BRD_BRUMBY },
{ "onboard2", BRD_ONBOARD2 },
{ "onboard-2", BRD_ONBOARD2 },
{ "onboard/2", BRD_ONBOARD2 },
{ "onboard-mc", BRD_ONBOARD2 },
{ "onboard/mc", BRD_ONBOARD2 },
{ "onboard-mca", BRD_ONBOARD2 },
{ "onboard/mca", BRD_ONBOARD2 },
{ "3", BRD_ONBOARD2 },
{ "onboard", BRD_ONBOARD },
{ "onboardat", BRD_ONBOARD },
{ "4", BRD_ONBOARD },
{ "onboarde", BRD_ONBOARDE },
{ "onboard-e", BRD_ONBOARDE },
{ "onboard/e", BRD_ONBOARDE },
{ "onboard-ei", BRD_ONBOARDE },
{ "onboard/ei", BRD_ONBOARDE },
{ "7", BRD_ONBOARDE },
{ "ecp", BRD_ECP },
{ "ecpat", BRD_ECP },
{ "ec8/64", BRD_ECP },
{ "ec8/64-at", BRD_ECP },
{ "ec8/64-isa", BRD_ECP },
{ "23", BRD_ECP },
{ "ecpe", BRD_ECPE },
{ "ecpei", BRD_ECPE },
{ "ec8/64-e", BRD_ECPE },
{ "ec8/64-ei", BRD_ECPE },
{ "24", BRD_ECPE },
{ "ecpmc", BRD_ECPMC },
{ "ec8/64-mc", BRD_ECPMC },
{ "ec8/64-mca", BRD_ECPMC },
{ "25", BRD_ECPMC },
{ "ecppci", BRD_ECPPCI },
{ "ec/ra", BRD_ECPPCI },
{ "ec/ra-pc", BRD_ECPPCI },
{ "ec/ra-pci", BRD_ECPPCI },
{ "29", BRD_ECPPCI },
};
/*
* Define the module agruments.
*/
MODULE_AUTHOR("Greg Ungerer");
MODULE_DESCRIPTION("Stallion Intelligent Multiport Serial Driver");
MODULE_PARM(board0, "1-3s");
MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,memaddr]");
MODULE_PARM(board1, "1-3s");
MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,memaddr]");
MODULE_PARM(board2, "1-3s");
MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,memaddr]");
MODULE_PARM(board3, "1-3s");
MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,memaddr]");
#endif
/*
* Set up a default memory address table for EISA board probing.
* The default addresses are all bellow 1Mbyte, which has to be the
......@@ -317,18 +415,34 @@ static unsigned long stli_eisamemprobeaddrs[] = {
static int stli_eisamempsize = sizeof(stli_eisamemprobeaddrs) / sizeof(unsigned long);
int stli_eisaprobe = STLI_EISAPROBE;
/*
* Define the Stallion PCI vendor and device IDs.
*/
#ifdef CONFIG_PCI
#ifndef PCI_VENDOR_ID_STALLION
#define PCI_VENDOR_ID_STALLION 0x124d
#endif
#ifndef PCI_DEVICE_ID_ECRA
#define PCI_DEVICE_ID_ECRA 0x0004
#endif
#endif
/*****************************************************************************/
/*
* Hardware configuration info for ECP boards. These defines apply
* to the directly accessible io ports of the ECP. There is a set of
* defines for each ECP board type, ISA, EISA and MCA.
* defines for each ECP board type, ISA, EISA, MCA and PCI.
*/
#define ECP_IOSIZE 4
#define ECP_MEMSIZE (128 * 1024)
#define ECP_PCIMEMSIZE (256 * 1024)
#define ECP_ATPAGESIZE (4 * 1024)
#define ECP_EIPAGESIZE (64 * 1024)
#define ECP_MCPAGESIZE (4 * 1024)
#define ECP_EIPAGESIZE (64 * 1024)
#define ECP_PCIPAGESIZE (64 * 1024)
#define STL_EISAID 0x8c4e
......@@ -376,6 +490,14 @@ int stli_eisaprobe = STLI_EISAPROBE;
#define ECP_MCENABLE 0x80
#define ECP_MCDISABLE 0x00
/*
* Important defines for the PCI class of ECP board.
* (It has a lot in common with the other ECP boards.)
*/
#define ECP_PCIIREG 0
#define ECP_PCICONFR 1
#define ECP_PCISTOP 0x01
/*
* Hardware configuration info for ONboard and Brumby boards. These
* defines apply to the directly accessible io ports of these boards.
......@@ -516,8 +638,12 @@ static unsigned int stli_baudrates[] = {
/*
* Define some handy local macros...
*/
#undef MIN
#define MIN(a,b) (((a) <= (b)) ? (a) : (b))
#undef TOLOWER
#define TOLOWER(x) ((((x) >= 'A') && ((x) <= 'Z')) ? ((x) + 0x20) : (x))
/*****************************************************************************/
/*
......@@ -527,6 +653,10 @@ static unsigned int stli_baudrates[] = {
#ifdef MODULE
int init_module(void);
void cleanup_module(void);
static void stli_argbrds(void);
static int stli_parsebrd(stlconf_t *confp, char **argp);
static unsigned long stli_atol(char *str);
#endif
int stli_init(void);
......@@ -583,6 +713,7 @@ static int stli_clrportstats(stliport_t *portp, comstats_t *cp);
static int stli_getportstruct(unsigned long arg);
static int stli_getbrdstruct(unsigned long arg);
static void *stli_memalloc(int len);
static stlibrd_t *stli_allocbrd(void);
static void stli_ecpinit(stlibrd_t *brdp);
static void stli_ecpenable(stlibrd_t *brdp);
......@@ -599,6 +730,9 @@ static void stli_ecpmcenable(stlibrd_t *brdp);
static void stli_ecpmcdisable(stlibrd_t *brdp);
static char *stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
static void stli_ecpmcreset(stlibrd_t *brdp);
static void stli_ecppciinit(stlibrd_t *brdp);
static char *stli_ecppcigetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
static void stli_ecppcireset(stlibrd_t *brdp);
static void stli_onbinit(stlibrd_t *brdp);
static void stli_onbenable(stlibrd_t *brdp);
......@@ -625,6 +759,12 @@ static inline int stli_initonb(stlibrd_t *brdp);
static inline int stli_findeisabrds(void);
static inline int stli_eisamemprobe(stlibrd_t *brdp);
static inline int stli_initports(stlibrd_t *brdp);
static inline int stli_getbrdnr(void);
#ifdef CONFIG_PCI
static inline int stli_findpcibrds(void);
static inline int stli_initpcibrd(int brdtype, struct pci_dev *devp);
#endif
/*****************************************************************************/
......@@ -741,8 +881,7 @@ void cleanup_module()
kfree_s(stli_txcookbuf, STLI_TXBUFSIZE);
for (i = 0; (i < stli_nrbrds); i++) {
brdp = stli_brds[i];
if (brdp == (stlibrd_t *) NULL)
if ((brdp = stli_brds[i]) == (stlibrd_t *) NULL)
continue;
for (j = 0; (j < STL_MAXPORTS); j++) {
portp = brdp->ports[j];
......@@ -763,6 +902,114 @@ void cleanup_module()
restore_flags(flags);
}
/*****************************************************************************/
/*
* Check for any arguments passed in on the module load command line.
*/
static void stli_argbrds()
{
stlconf_t conf;
stlibrd_t *brdp;
int nrargs, i;
#if DEBUG
printk("stli_argbrds()\n");
#endif
nrargs = sizeof(stli_brdsp) / sizeof(char **);
for (i = stli_nrbrds; (i < nrargs); i++) {
memset(&conf, 0, sizeof(conf));
if (stli_parsebrd(&conf, stli_brdsp[i]) == 0)
continue;
if ((brdp = stli_allocbrd()) == (stlibrd_t *) NULL)
continue;
stli_nrbrds = i + 1;
brdp->brdnr = i;
brdp->brdtype = conf.brdtype;
brdp->iobase = conf.ioaddr1;
brdp->memaddr = conf.memaddr;
stli_brdinit(brdp);
}
}
/*****************************************************************************/
/*
* Convert an ascii string number into an unsigned long.
*/
static unsigned long stli_atol(char *str)
{
unsigned long val;
int base, c;
char *sp;
val = 0;
sp = str;
if ((*sp == '0') && (*(sp+1) == 'x')) {
base = 16;
sp += 2;
} else if (*sp == '0') {
base = 8;
sp++;
} else {
base = 10;
}
for (; (*sp != 0); sp++) {
c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0');
if ((c < 0) || (c >= base)) {
printk("STALLION: invalid argument %s\n", str);
val = 0;
break;
}
val = (val * base) + c;
}
return(val);
}
/*****************************************************************************/
/*
* Parse the supplied argument string, into the board conf struct.
*/
static int stli_parsebrd(stlconf_t *confp, char **argp)
{
char *sp;
int nrbrdnames, i;
#if DEBUG
printk("stli_parsebrd(confp=%x,argp=%x)\n", (int) confp, (int) argp);
#endif
if ((argp[0] == (char *) NULL) || (*argp[0] == 0))
return(0);
for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
*sp = TOLOWER(*sp);
nrbrdnames = sizeof(stli_brdstr) / sizeof(stlibrdtype_t);
for (i = 0; (i < nrbrdnames); i++) {
if (strcmp(stli_brdstr[i].name, argp[0]) == 0)
break;
}
if (i >= nrbrdnames) {
printk("STALLION: unknown board name, %s?\n", argp[0]);
return(0);
}
confp->brdtype = stli_brdstr[i].type;
if ((argp[1] != (char *) NULL) && (*argp[1] != 0))
confp->ioaddr1 = stli_atol(argp[1]);
if ((argp[2] != (char *) NULL) && (*argp[2] != 0))
confp->memaddr = stli_atol(argp[2]);
return(1);
}
#endif
/*****************************************************************************/
......@@ -1433,7 +1680,6 @@ static int stli_write(struct tty_struct *tty, int from_user, const unsigned char
down(&stli_tmpwritesem);
copy_from_user(stli_tmpwritebuf, chbuf, count);
up(&stli_tmpwritesem);
chbuf = &stli_tmpwritebuf[0];
}
......@@ -1485,8 +1731,10 @@ static int stli_write(struct tty_struct *tty, int from_user, const unsigned char
portp->portidx;
*bits |= portp->portbit;
set_bit(ST_TXBUSY, &portp->state);
EBRDDISABLE(brdp);
if (from_user)
up(&stli_tmpwritesem);
restore_flags(flags);
return(count);
......@@ -3362,6 +3610,60 @@ static void stli_ecpmcreset(stlibrd_t *brdp)
/*****************************************************************************/
/*
* The following set of functions act on ECP PCI boards.
*/
static void stli_ecppciinit(stlibrd_t *brdp)
{
#if DEBUG
printk("stli_ecppciinit(brdp=%x)\n", (int) brdp);
#endif
outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR));
udelay(10);
outb(0, (brdp->iobase + ECP_PCICONFR));
udelay(500);
}
/*****************************************************************************/
static char *stli_ecppcigetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
{
void *ptr;
unsigned char val;
#if DEBUG
printk("stli_ecppcigetmemptr(brdp=%x,offset=%x,line=%d)\n",
(int) brdp, (int) offset, line);
#endif
if (offset > brdp->memsize) {
printk("STALLION: shared memory pointer=%x out of range at "
"line=%d(%d), board=%d\n", (int) offset, line,
__LINE__, brdp->brdnr);
ptr = 0;
val = 0;
} else {
ptr = brdp->membase + (offset % ECP_PCIPAGESIZE);
val = (offset / ECP_PCIPAGESIZE) << 1;
}
outb(val, (brdp->iobase + ECP_PCICONFR));
return(ptr);
}
/*****************************************************************************/
static void stli_ecppcireset(stlibrd_t *brdp)
{
outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR));
udelay(10);
outb(0, (brdp->iobase + ECP_PCICONFR));
udelay(500);
}
/*****************************************************************************/
/*
* The following routines act on ONboards.
*/
......@@ -3678,7 +3980,7 @@ static inline int stli_initecp(stlibrd_t *brdp)
brdp->iosize = ECP_IOSIZE;
if (check_region(brdp->iobase, brdp->iosize))
printk("STALLION: Warning, unit %d I/O address %x conflicts "
printk("STALLION: Warning, board %d I/O address %x conflicts "
"with another device\n", brdp->brdnr, brdp->iobase);
/*
......@@ -3729,6 +4031,20 @@ static inline int stli_initecp(stlibrd_t *brdp)
name = "serial(EC8/64-MCA)";
break;
case BRD_ECPPCI:
brdp->membase = (void *) brdp->memaddr;
brdp->memsize = ECP_PCIMEMSIZE;
brdp->pagesize = ECP_PCIPAGESIZE;
brdp->init = stli_ecppciinit;
brdp->enable = NULL;
brdp->reenable = NULL;
brdp->disable = NULL;
brdp->getmemptr = stli_ecppcigetmemptr;
brdp->intr = stli_ecpintr;
brdp->reset = stli_ecppcireset;
name = "serial(EC/RA-PCI)";
break;
default:
return(-EINVAL);
}
......@@ -3817,7 +4133,7 @@ static inline int stli_initonb(stlibrd_t *brdp)
brdp->iosize = ONB_IOSIZE;
if (check_region(brdp->iobase, brdp->iosize))
printk("STALLION: Warning, unit %d I/O address %x conflicts "
printk("STALLION: Warning, board %d I/O address %x conflicts "
"with another device\n", brdp->brdnr, brdp->iobase);
/*
......@@ -4082,6 +4398,7 @@ __initfunc(static int stli_brdinit(stlibrd_t *brdp))
case BRD_ECP:
case BRD_ECPE:
case BRD_ECPMC:
case BRD_ECPPCI:
stli_initecp(brdp);
break;
case BRD_ONBOARD:
......@@ -4104,20 +4421,20 @@ __initfunc(static int stli_brdinit(stlibrd_t *brdp))
stli_brdnames[brdp->brdtype]);
return(ENODEV);
default:
printk("STALLION: unit=%d is unknown board type=%d\n",
printk("STALLION: board=%d is unknown board type=%d\n",
brdp->brdnr, brdp->brdtype);
return(ENODEV);
}
if ((brdp->state & BST_FOUND) == 0) {
printk("STALLION: %s board not found, unit=%d io=%x mem=%x\n",
printk("STALLION: %s board not found, board=%d io=%x mem=%x\n",
stli_brdnames[brdp->brdtype], brdp->brdnr,
brdp->iobase, (int) brdp->memaddr);
return(ENODEV);
}
stli_initports(brdp);
printk("STALLION: %s found, unit=%d io=%x mem=%x "
printk("STALLION: %s found, board=%d io=%x mem=%x "
"nrpanels=%d nrports=%d\n", stli_brdnames[brdp->brdtype],
brdp->brdnr, brdp->iobase, (int) brdp->memaddr,
brdp->nrpanels, brdp->nrports);
......@@ -4278,30 +4595,14 @@ static inline int stli_findeisabrds()
if (i < STL_MAXBRDS)
continue;
/*
* Check that we have room for this new board in our board
* info table.
*/
if (stli_nrbrds >= STL_MAXBRDS) {
printk("STALLION: no room for more probed boards, "
"maximum supported %d\n", STL_MAXBRDS);
break;
}
/*
* We have found a Stallion board and it is not configured already.
* Allocate a board structure and initialize it.
*/
brdp = (stlibrd_t *) stli_memalloc(sizeof(stlibrd_t));
if (brdp == (stlibrd_t *) NULL) {
printk("STALLION: failed to allocate memory "
"(size=%d)\n", sizeof(stlibrd_t));
if ((brdp = stli_allocbrd()) == (stlibrd_t *) NULL)
return(-ENOMEM);
if ((brdp->brdnr = stli_getbrdnr()) < 0)
return(-ENOMEM);
}
memset(brdp, 0, sizeof(stlibrd_t));
brdp->magic = STLI_BOARDMAGIC;
brdp->brdnr = stli_nrbrds++;
eid = inb(iobase + 0xc82);
if (eid == ECP_EISAID)
brdp->brdtype = BRD_ECPE;
......@@ -4321,6 +4622,123 @@ static inline int stli_findeisabrds()
/*****************************************************************************/
/*
* Find the next available board number that is free.
*/
static inline int stli_getbrdnr()
{
int i;
for (i = 0; (i < STL_MAXBRDS); i++) {
if (stli_brds[i] == (stlibrd_t *) NULL) {
if (i >= stli_nrbrds)
stli_nrbrds = i + 1;
return(i);
}
}
return(-1);
}
/*****************************************************************************/
#ifdef CONFIG_PCI
/*
* We have a Stallion board. Allocate a board structure and
* initialize it. Read its IO and MEMORY resources from PCI
* configuration space.
*/
static inline int stli_initpcibrd(int brdtype, struct pci_dev *devp)
{
stlibrd_t *brdp;
#if DEBUG
printk("stli_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n", brdtype,
dev->bus->number, dev->devfn);
#endif
if ((brdp = stli_allocbrd()) == (stlibrd_t *) NULL)
return(-ENOMEM);
if ((brdp->brdnr = stli_getbrdnr()) < 0) {
printk("STALLION: too many boards found, "
"maximum supported %d\n", STL_MAXBRDS);
return(0);
}
brdp->brdtype = brdtype;
#if DEBUG
printk("%s(%d): BAR[]=%x,%x,%x,%x\n", __FILE__, __LINE__,
devp->base_address[0], devp->base_address[1],
devp->base_address[2], devp->base_address[3]);
#endif
/*
* We have all resources from the board, so lets setup the actual
* board structure now.
*/
brdp->iobase = (devp->base_address[3] & PCI_BASE_ADDRESS_IO_MASK);
brdp->memaddr = (devp->base_address[2] & PCI_BASE_ADDRESS_MEM_MASK);
stli_brdinit(brdp);
return(0);
}
/*****************************************************************************/
/*
* Find all Stallion PCI boards that might be installed. Initialize each
* one as it is found.
*/
static inline int stli_findpcibrds()
{
struct pci_dev *dev = NULL;
int rc;
#if DEBUG
printk("stli_findpcibrds()\n");
#endif
if (! pci_present())
return(0);
while ((dev = pci_find_device(PCI_VENDOR_ID_STALLION,
PCI_DEVICE_ID_ECRA, dev))) {
if ((rc = stli_initpcibrd(BRD_ECPPCI, dev)))
return(rc);
}
return(0);
}
#endif
/*****************************************************************************/
/*
* Allocate a new board structure. Fill out the basic info in it.
*/
static stlibrd_t *stli_allocbrd()
{
stlibrd_t *brdp;
brdp = (stlibrd_t *) stli_memalloc(sizeof(stlibrd_t));
if (brdp == (stlibrd_t *) NULL) {
printk("STALLION: failed to allocate memory (size=%d)\n",
sizeof(stlibrd_t));
return((stlibrd_t *) NULL);
}
memset(brdp, 0, sizeof(stlibrd_t));
brdp->magic = STLI_BOARDMAGIC;
return(brdp);
}
/*****************************************************************************/
/*
* Scan through all the boards in the configuration and see what we
* can find.
......@@ -4344,19 +4762,16 @@ static inline int stli_initbrds()
/*
* Firstly scan the list of static boards configured. Allocate
* resources and initialize the boards as found.
* resources and initialize the boards as found. If this is a
* module then let the module args override static configuration.
*/
for (i = 0; (i < stli_nrbrds); i++) {
confp = &stli_brdconf[i];
brdp = (stlibrd_t *) stli_memalloc(sizeof(stlibrd_t));
if (brdp == (stlibrd_t *) NULL) {
printk("STALLION: failed to allocate memory "
"(size=%d)\n", sizeof(stlibrd_t));
#ifdef MODULE
stli_parsebrd(confp, stli_brdsp[i]);
#endif
if ((brdp = stli_allocbrd()) == (stlibrd_t *) NULL)
return(-ENOMEM);
}
memset(brdp, 0, sizeof(stlibrd_t));
brdp->magic = STLI_BOARDMAGIC;
brdp->brdnr = i;
brdp->brdtype = confp->brdtype;
brdp->iobase = confp->ioaddr1;
......@@ -4365,10 +4780,17 @@ static inline int stli_initbrds()
}
/*
* Now go probing for EISA boards if enabled.
* Static configuration table done, so now use dynamic methods to
* see if any more boards should be configured.
*/
#ifdef MODULE
stli_argbrds();
#endif
if (stli_eisaprobe)
stli_findeisabrds();
#ifdef CONFIG_PCI
stli_findpcibrds();
#endif
/*
* All found boards are initialized. Now for a little optimization, if
......
......@@ -3,7 +3,7 @@
/*
* stallion.c -- stallion multiport serial driver.
*
* Copyright (C) 1996-1998 Stallion Technologies (support@stallion.oz.au).
* Copyright (C) 1996-1999 Stallion Technologies (support@stallion.oz.au).
* Copyright (C) 1994-1996 Greg Ungerer (gerg@stallion.oz.au).
*
* This code is loosely based on the Linux serial driver, written by
......@@ -27,28 +27,18 @@
/*****************************************************************************/
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/termios.h>
#include <linux/fcntl.h>
#include <linux/tty_driver.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/cd1400.h>
#include <linux/sc26198.h>
#include <linux/comstats.h>
#include <linux/stallion.h>
#include <linux/string.h>
#include <linux/malloc.h>
#include <linux/ioport.h>
#include <linux/config.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/uaccess.h>
......@@ -78,7 +68,7 @@
* stl_brdconf[] array is a board. Each line contains io/irq/memory
* ranges for that board (as well as what type of board it is).
* Some examples:
* { BRD_EASYIO, 0x2a0, 0, 0, 10, 0 }
* { BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },
* This line would configure an EasyIO board (4 or 8, no difference),
* at io address 2a0 and irq 10.
* Another example:
......@@ -105,7 +95,7 @@ typedef struct {
} stlconf_t;
static stlconf_t stl_brdconf[] = {
{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },
/*{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },*/
};
static int stl_nrbrds = sizeof(stl_brdconf) / sizeof(stlconf_t);
......@@ -144,7 +134,7 @@ static int stl_nrbrds = sizeof(stl_brdconf) / sizeof(stlconf_t);
*/
static char *stl_drvtitle = "Stallion Multiport Serial Driver";
static char *stl_drvname = "stallion";
static char *stl_drvversion = "5.4.7";
static char *stl_drvversion = "5.5.1";
static char *stl_serialname = "ttyE";
static char *stl_calloutname = "cue";
......@@ -259,6 +249,85 @@ static char *stl_brdnames[] = {
/*****************************************************************************/
#ifdef MODULE
/*
* Define some string labels for arguments passed from the module
* load line. These allow for easy board definitions, and easy
* modification of the io, memory and irq resoucres.
*/
static char *board0[4];
static char *board1[4];
static char *board2[4];
static char *board3[4];
static char **stl_brdsp[] = {
(char **) &board0,
(char **) &board1,
(char **) &board2,
(char **) &board3
};
/*
* Define a set of common board names, and types. This is used to
* parse any module arguments.
*/
typedef struct stlbrdtype {
char *name;
int type;
} stlbrdtype_t;
static stlbrdtype_t stl_brdstr[] = {
{ "easyio", BRD_EASYIO },
{ "eio", BRD_EASYIO },
{ "20", BRD_EASYIO },
{ "ec8/32", BRD_ECH },
{ "ec8/32-at", BRD_ECH },
{ "ec8/32-isa", BRD_ECH },
{ "ech", BRD_ECH },
{ "echat", BRD_ECH },
{ "21", BRD_ECH },
{ "ec8/32-mc", BRD_ECHMC },
{ "ec8/32-mca", BRD_ECHMC },
{ "echmc", BRD_ECHMC },
{ "echmca", BRD_ECHMC },
{ "22", BRD_ECHMC },
{ "ec8/32-pc", BRD_ECHPCI },
{ "ec8/32-pci", BRD_ECHPCI },
{ "26", BRD_ECHPCI },
{ "ec8/64-pc", BRD_ECH64PCI },
{ "ec8/64-pci", BRD_ECH64PCI },
{ "ech-pci", BRD_ECH64PCI },
{ "echpci", BRD_ECH64PCI },
{ "echpc", BRD_ECH64PCI },
{ "27", BRD_ECH64PCI },
{ "easyio-pc", BRD_EASYIOPCI },
{ "easyio-pci", BRD_EASYIOPCI },
{ "eio-pci", BRD_EASYIOPCI },
{ "eiopci", BRD_EASYIOPCI },
{ "28", BRD_EASYIOPCI },
};
/*
* Define the module agruments.
*/
MODULE_AUTHOR("Greg Ungerer");
MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
MODULE_PARM(board0, "1-4s");
MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
MODULE_PARM(board1, "1-4s");
MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
MODULE_PARM(board2, "1-4s");
MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
MODULE_PARM(board3, "1-4s");
MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
#endif
/*****************************************************************************/
/*
* Hardware ID bits for the EasyIO and ECH boards. These defines apply
* to the directly accessible io ports of these boards (not the uarts -
......@@ -399,9 +468,11 @@ static unsigned int stl_baudrates[] = {
/*
* Define some handy local macros...
*/
#ifndef MIN
#undef MIN
#define MIN(a,b) (((a) <= (b)) ? (a) : (b))
#endif
#undef TOLOWER
#define TOLOWER(x) ((((x) >= 'A') && ((x) <= 'Z')) ? ((x) + 0x20) : (x))
/*****************************************************************************/
......@@ -412,6 +483,10 @@ static unsigned int stl_baudrates[] = {
#ifdef MODULE
int init_module(void);
void cleanup_module(void);
static void stl_argbrds(void);
static int stl_parsebrd(stlconf_t *confp, char **argp);
static unsigned long stl_atol(char *str);
#endif
int stl_init(void);
......@@ -459,15 +534,17 @@ static void stl_echpciintr(stlbrd_t *brdp);
static void stl_echpci64intr(stlbrd_t *brdp);
static void stl_offintr(void *private);
static void *stl_memalloc(int len);
static stlbrd_t *stl_allocbrd(void);
static stlport_t *stl_getport(int brdnr, int panelnr, int portnr);
static inline int stl_initbrds(void);
static inline int stl_initeio(stlbrd_t *brdp);
static inline int stl_initech(stlbrd_t *brdp);
static inline int stl_getbrdnr(void);
#ifdef CONFIG_PCI
static inline int stl_findpcibrds(void);
static inline int stl_initpcibrd(int brdtype, struct pci_dev *dev);
static inline int stl_initpcibrd(int brdtype, struct pci_dev *devp);
#endif
/*
......@@ -747,7 +824,8 @@ void cleanup_module()
kfree_s(stl_tmpwritebuf, STL_TXBUFSIZE);
for (i = 0; (i < stl_nrbrds); i++) {
brdp = stl_brds[i];
if ((brdp = stl_brds[i]) == (stlbrd_t *) NULL)
continue;
for (j = 0; (j < STL_MAXPANELS); j++) {
panelp = brdp->panels[j];
if (panelp == (stlpanel_t *) NULL)
......@@ -779,6 +857,124 @@ void cleanup_module()
restore_flags(flags);
}
/*****************************************************************************/
/*
* Check for any arguments passed in on the module load command line.
*/
static void stl_argbrds()
{
stlconf_t conf;
stlbrd_t *brdp;
int nrargs, i;
#if DEBUG
printk("stl_argbrds()\n");
#endif
nrargs = sizeof(stl_brdsp) / sizeof(char **);
for (i = stl_nrbrds; (i < nrargs); i++) {
memset(&conf, 0, sizeof(conf));
if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
continue;
if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL)
continue;
stl_nrbrds = i + 1;
brdp->brdnr = i;
brdp->brdtype = conf.brdtype;
brdp->ioaddr1 = conf.ioaddr1;
brdp->ioaddr2 = conf.ioaddr2;
brdp->irq = conf.irq;
brdp->irqtype = conf.irqtype;
stl_brdinit(brdp);
}
}
/*****************************************************************************/
/*
* Convert an ascii string number into an unsigned long.
*/
static unsigned long stl_atol(char *str)
{
unsigned long val;
int base, c;
char *sp;
val = 0;
sp = str;
if ((*sp == '0') && (*(sp+1) == 'x')) {
base = 16;
sp += 2;
} else if (*sp == '0') {
base = 8;
sp++;
} else {
base = 10;
}
for (; (*sp != 0); sp++) {
c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0');
if ((c < 0) || (c >= base)) {
printk("STALLION: invalid argument %s\n", str);
val = 0;
break;
}
val = (val * base) + c;
}
return(val);
}
/*****************************************************************************/
/*
* Parse the supplied argument string, into the board conf struct.
*/
static int stl_parsebrd(stlconf_t *confp, char **argp)
{
char *sp;
int nrbrdnames, i;
#if DEBUG
printk("stl_parsebrd(confp=%x,argp=%x)\n", (int) confp, (int) argp);
#endif
if ((argp[0] == (char *) NULL) || (*argp[0] == 0))
return(0);
for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
*sp = TOLOWER(*sp);
nrbrdnames = sizeof(stl_brdstr) / sizeof(stlbrdtype_t);
for (i = 0; (i < nrbrdnames); i++) {
if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
break;
}
if (i >= nrbrdnames) {
printk("STALLION: unknown board name, %s?\n", argp[0]);
return(0);
}
confp->brdtype = stl_brdstr[i].type;
i = 1;
if ((argp[i] != (char *) NULL) && (*argp[i] != 0))
confp->ioaddr1 = stl_atol(argp[i]);
i++;
if (confp->brdtype == BRD_ECH) {
if ((argp[i] != (char *) NULL) && (*argp[i] != 0))
confp->ioaddr2 = stl_atol(argp[i]);
i++;
}
if ((argp[i] != (char *) NULL) && (*argp[i] != 0))
confp->irq = stl_atol(argp[i]);
return(1);
}
#endif
/*****************************************************************************/
......@@ -794,6 +990,28 @@ static void *stl_memalloc(int len)
/*****************************************************************************/
/*
* Allocate a new board structure. Fill out the basic info in it.
*/
static stlbrd_t *stl_allocbrd()
{
stlbrd_t *brdp;
brdp = (stlbrd_t *) stl_memalloc(sizeof(stlbrd_t));
if (brdp == (stlbrd_t *) NULL) {
printk("STALLION: failed to allocate memory (size=%d)\n",
sizeof(stlbrd_t));
return((stlbrd_t *) NULL);
}
memset(brdp, 0, sizeof(stlbrd_t));
brdp->magic = STL_BOARDMAGIC;
return(brdp);
}
/*****************************************************************************/
static int stl_open(struct tty_struct *tty, struct file *filp)
{
stlport_t *portp;
......@@ -1121,7 +1339,6 @@ static int stl_write(struct tty_struct *tty, int from_user, const unsigned char
down(&stl_tmpwritesem);
copy_from_user(stl_tmpwritebuf, chbuf, count);
up(&stl_tmpwritesem);
chbuf = &stl_tmpwritebuf[0];
}
......@@ -1154,6 +1371,9 @@ static int stl_write(struct tty_struct *tty, int from_user, const unsigned char
clear_bit(ASYI_TXLOW, &portp->istate);
stl_startrxtx(portp, -1, 1);
if (from_user)
up(&stl_tmpwritesem);
return(count);
}
......@@ -2185,12 +2405,12 @@ static inline int stl_initeio(stlbrd_t *brdp)
}
if (check_region(brdp->ioaddr1, brdp->iosize1)) {
printk("STALLION: Warning, unit %d I/O address %x conflicts "
printk("STALLION: Warning, board %d I/O address %x conflicts "
"with another device\n", brdp->brdnr, brdp->ioaddr1);
}
if (brdp->iosize2 > 0) {
if (check_region(brdp->ioaddr2, brdp->iosize2)) {
printk("STALLION: Warning, unit %d I/O address %x "
printk("STALLION: Warning, board %d I/O address %x "
"conflicts with another device\n",
brdp->brdnr, brdp->ioaddr2);
}
......@@ -2376,7 +2596,7 @@ static int inline stl_initech(stlbrd_t *brdp)
conflict = check_region(brdp->ioaddr2, brdp->iosize2) ?
brdp->ioaddr2 : 0;
if (conflict) {
printk("STALLION: Warning, unit %d I/O address %x conflicts "
printk("STALLION: Warning, board %d I/O address %x conflicts "
"with another device\n", brdp->brdnr, conflict);
}
......@@ -2499,14 +2719,14 @@ __initfunc(static int stl_brdinit(stlbrd_t *brdp))
stl_initech(brdp);
break;
default:
printk("STALLION: unit=%d is unknown board type=%d\n",
printk("STALLION: board=%d is unknown board type=%d\n",
brdp->brdnr, brdp->brdtype);
return(ENODEV);
}
stl_brds[brdp->brdnr] = brdp;
if ((brdp->state & BRD_FOUND) == 0) {
printk("STALLION: %s board not found, unit=%d io=%x irq=%d\n",
printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
stl_brdnames[brdp->brdtype], brdp->brdnr,
brdp->ioaddr1, brdp->irq);
return(ENODEV);
......@@ -2516,7 +2736,7 @@ __initfunc(static int stl_brdinit(stlbrd_t *brdp))
if (brdp->panels[i] != (stlpanel_t *) NULL)
stl_initports(brdp, brdp->panels[i]);
printk("STALLION: %s found, unit=%d io=%x irq=%d "
printk("STALLION: %s found, board=%d io=%x irq=%d "
"nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
brdp->nrports);
......@@ -2525,6 +2745,26 @@ __initfunc(static int stl_brdinit(stlbrd_t *brdp))
/*****************************************************************************/
/*
* Find the next available board number that is free.
*/
static inline int stl_getbrdnr()
{
int i;
for (i = 0; (i < STL_MAXBRDS); i++) {
if (stl_brds[i] == (stlbrd_t *) NULL) {
if (i >= stl_nrbrds)
stl_nrbrds = i + 1;
return(i);
}
}
return(-1);
}
/*****************************************************************************/
#ifdef CONFIG_PCI
/*
......@@ -2533,42 +2773,32 @@ __initfunc(static int stl_brdinit(stlbrd_t *brdp))
* configuration space.
*/
static inline int stl_initpcibrd(int brdtype, struct pci_dev *dev)
static inline int stl_initpcibrd(int brdtype, struct pci_dev *devp)
{
unsigned int bar[4];
stlbrd_t *brdp;
int i;
unsigned char irq;
#if DEBUG
printk("stl_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n",
brdtype, dev->bus->number, dev->devfn);
printk("stl_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n", brdtype,
dev->bus->number, dev->devfn);
#endif
brdp = (stlbrd_t *) stl_memalloc(sizeof(stlbrd_t));
if (brdp == (stlbrd_t *) NULL) {
printk("STALLION: failed to allocate memory (size=%d)\n",
sizeof(stlbrd_t));
if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL)
return(-ENOMEM);
if ((brdp->brdnr = stl_getbrdnr()) < 0) {
printk("STALLION: too many boards found, "
"maximum supported %d\n", STL_MAXBRDS);
return(0);
}
memset(brdp, 0, sizeof(stlbrd_t));
brdp->magic = STL_BOARDMAGIC;
brdp->brdnr = stl_nrbrds++;
brdp->brdtype = brdtype;
/*
* Read in all the BAR registers from this board. Different Stallion
* boards use these in different ways, so we just read in the whole
* lot and then figure out what is what later.
* Different Stallion boards use the BAR registers in different ways,
* so set up io addresses based on board type.
*/
for (i = 0; (i < 4); i++)
bar[i] = dev->base_address[i];
irq = dev->irq;
#if DEBUG
printk("%s(%d): BAR[]=%x,%x,%x,%x IRQ=%x\n", __FILE__, __LINE__,
bar[0], bar[1], bar[2], bar[3], irq);
devp->base_address[0], devp->base_address[1],
devp->base_address[2], devp->base_address[3], devp->irq);
#endif
/*
......@@ -2577,29 +2807,34 @@ static inline int stl_initpcibrd(int brdtype, struct pci_dev *dev)
*/
switch (brdtype) {
case BRD_ECHPCI:
brdp->ioaddr2 = (bar[0] & PCI_BASE_ADDRESS_IO_MASK);
brdp->ioaddr1 = (bar[1] & PCI_BASE_ADDRESS_IO_MASK);
brdp->ioaddr2 = (devp->base_address[0] &
PCI_BASE_ADDRESS_IO_MASK);
brdp->ioaddr1 = (devp->base_address[1] &
PCI_BASE_ADDRESS_IO_MASK);
break;
case BRD_ECH64PCI:
brdp->ioaddr2 = (bar[2] & PCI_BASE_ADDRESS_IO_MASK);
brdp->ioaddr1 = (bar[1] & PCI_BASE_ADDRESS_IO_MASK);
brdp->ioaddr2 = (devp->base_address[2] &
PCI_BASE_ADDRESS_IO_MASK);
brdp->ioaddr1 = (devp->base_address[1] &
PCI_BASE_ADDRESS_IO_MASK);
break;
case BRD_EASYIOPCI:
brdp->ioaddr1 = (bar[2] & PCI_BASE_ADDRESS_IO_MASK);
brdp->ioaddr2 = (bar[1] & PCI_BASE_ADDRESS_IO_MASK);
brdp->ioaddr1 = (devp->base_address[2] &
PCI_BASE_ADDRESS_IO_MASK);
brdp->ioaddr2 = (devp->base_address[1] &
PCI_BASE_ADDRESS_IO_MASK);
break;
default:
printk("STALLION: unknown PCI board type=%d\n", brdtype);
break;
}
brdp->irq = irq;
brdp->irq = devp->irq;
stl_brdinit(brdp);
return(0);
}
/*****************************************************************************/
/*
......@@ -2621,17 +2856,8 @@ static inline int stl_findpcibrds()
return(0);
for (i = 0; (i < stl_nrpcibrds); i++)
while ((dev = pci_find_device(stl_pcibrds[i].vendid, stl_pcibrds[i].devid, dev))) {
/*
* Check that we can handle more boards...
*/
if (stl_nrbrds >= STL_MAXBRDS) {
printk("STALLION: too many boards found, "
"maximum supported %d\n", STL_MAXBRDS);
i = stl_nrpcibrds;
break;
}
while ((dev = pci_find_device(stl_pcibrds[i].vendid,
stl_pcibrds[i].devid, dev))) {
/*
* Found a device on the PCI bus that has our vendor and
......@@ -2680,15 +2906,11 @@ static inline int stl_initbrds()
*/
for (i = 0; (i < stl_nrbrds); i++) {
confp = &stl_brdconf[i];
brdp = (stlbrd_t *) stl_memalloc(sizeof(stlbrd_t));
if (brdp == (stlbrd_t *) NULL) {
printk("STALLION: failed to allocate memory "
"(size=%d)\n", sizeof(stlbrd_t));
#ifdef MODULE
stl_parsebrd(confp, stl_brdsp[i]);
#endif
if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL)
return(-ENOMEM);
}
memset(brdp, 0, sizeof(stlbrd_t));
brdp->magic = STL_BOARDMAGIC;
brdp->brdnr = i;
brdp->brdtype = confp->brdtype;
brdp->ioaddr1 = confp->ioaddr1;
......@@ -2698,11 +2920,14 @@ static inline int stl_initbrds()
stl_brdinit(brdp);
}
#ifdef CONFIG_PCI
/*
* If the PCI BIOS support is compiled in then let's go looking for
* ECH-PCI boards.
* Find any dynamically supported boards. That is via module load
* line options or auto-detected on the PCI bus.
*/
#ifdef MODULE
stl_argbrds();
#endif
#ifdef CONFIG_PCI
stl_findpcibrds();
#endif
......
......@@ -3626,7 +3626,7 @@ static inline int line_info(char *buf, struct mgsl_struct *info)
}
spin_unlock_irqrestore(&info->irq_spinlock,flags);
#if LINUX_VERSION_CODE >= VERSION(2,1,0)
#if 0 && LINUX_VERSION_CODE >= VERSION(2,1,0)
ret += sprintf(buf+ret, "irq_spinlock=%08X\n",
info->irq_spinlock.lock );
#endif
......
......@@ -73,6 +73,7 @@ static void socal_memcpy(void *d, void *s, int size)
}
}
#ifdef HAVE_SOCAL_UCODE
static void socal_bzero(void *d, int size)
{
u32 *dp = (u32 *)d;
......@@ -81,6 +82,7 @@ static void socal_bzero(void *d, int size)
size -= sizeof(u32);
}
}
#endif
static inline void socal_disable(struct socal *s)
{
......
......@@ -1587,7 +1587,7 @@ static int fbcon_do_set_font(int unit, struct console_font_op *op, u8 *data, int
if (CON_IS_VISIBLE(conp) && softback_buf) {
int l = fbcon_softback_size / conp->vc_size_row;
if (l > 5)
softback_end += l * conp->vc_size_row;
softback_end = softback_buf + l * conp->vc_size_row;
else {
/* Smaller scrollback makes no sense, and 0 would screw
the operation totally */
......
......@@ -39,7 +39,7 @@ static inline cycles_t get_cycles (void)
#else
unsigned long eax, edx;
__asm__("rdtsc":"=a" (eax), "=d" (edx));
__asm__ __volatile__("rdtsc":"=a" (eax), "=d" (edx));
return eax;
#endif
}
......
/* $Id: pgtable.h,v 1.102 1999/01/22 16:19:29 jj Exp $
/* $Id: pgtable.h,v 1.103 1999/03/28 08:40:04 davem Exp $
* pgtable.h: SpitFire page table operations.
*
* Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
......@@ -333,8 +333,8 @@ static __inline__ pte_t pte_mkdirty(pte_t _pte)
extern struct pgtable_cache_struct {
unsigned long *pgd_cache;
unsigned long *pte_cache;
unsigned long pgcache_size;
unsigned long pgdcache_size;
unsigned int pgcache_size;
unsigned int pgdcache_size;
} pgt_quicklists;
#endif
#define pgd_quicklist (pgt_quicklists.pgd_cache)
......
......@@ -98,8 +98,17 @@ extern __inline__ int hard_smp_processor_id(void)
/* This needn't do anything as we do not sleep the cpu
* inside of the idler task, so an interrupt is not needed
* to get a clean fast response.
*
* Addendum: We do want it to do something for the signal
* delivery case, we detect that by just seeing
* if we are trying to send this to an idler or not.
*/
extern __inline__ void smp_send_reschedule(int cpu) { }
extern __inline__ void smp_send_reschedule(int cpu)
{
extern void smp_receive_signal(int);
if(cpu_data[cpu].idle_volume == 0)
smp_receive_signal(cpu);
}
/* This is a nop as well because we capture all other cpus
* anyways when making the PROM active.
......
......@@ -70,7 +70,7 @@
#define ARPHRD_FCPP 784 /* Point to point fibrechanel */
#define ARPHRD_FCAL 785 /* Fibrechannel arbitrated loop */
#define ARPHRD_FCPL 786 /* Fibrechannel public loop */
#define ARPHRD_FCFABRIC 786 /* Fibrechannel fabric */
#define ARPHRD_FCFABRIC 787 /* Fibrechannel fabric */
/* 787->799 reserved for fibrechannel media types */
......
......@@ -113,6 +113,7 @@ struct sched_param {
*/
extern rwlock_t tasklist_lock;
extern spinlock_t scheduler_lock;
extern spinlock_t runqueue_lock;
extern void sched_init(void);
extern void show_state(void);
......
......@@ -845,6 +845,9 @@ extern __inline__ void skb_set_owner_r(struct sk_buff *skb, struct sock *sk)
extern __inline__ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
#ifdef CONFIG_FILTER
struct sk_filter *filter;
#endif
/* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
number of warnings when compiling with -W --ANK
*/
......@@ -852,7 +855,7 @@ extern __inline__ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
return -ENOMEM;
#ifdef CONFIG_FILTER
if (sk->filter && sk_filter(skb, sk->filter))
if ((filter = sk->filter) != NULL && sk_filter(skb, filter))
return -EPERM; /* Toss packet */
#endif /* CONFIG_FILTER */
......
......@@ -7,7 +7,7 @@
* handler for protocols to use and generic option handler.
*
*
* Version: $Id: sock.c,v 1.78 1999/03/25 10:03:55 davem Exp $
* Version: $Id: sock.c,v 1.79 1999/03/28 10:18:25 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
......@@ -150,6 +150,9 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
char *optval, int optlen)
{
struct sock *sk=sock->sk;
#ifdef CONFIG_FILTER
struct sk_filter *filter;
#endif
int val;
int valbool;
int err;
......@@ -341,15 +344,10 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
break;
case SO_DETACH_FILTER:
if(sk->filter) {
struct sk_filter *filter;
filter = sk->filter;
if(filter) {
sk->filter = NULL;
synchronize_bh();
if (filter)
sk_filter_release(sk, filter);
return 0;
}
......@@ -500,22 +498,16 @@ struct sock *sk_alloc(int family, int priority, int zero_it)
void sk_free(struct sock *sk)
{
if (sk->destruct)
sk->destruct(sk);
#ifdef CONFIG_FILTER
if (sk->filter) {
sk_filter_release(sk, sk->filter);
sk->filter = NULL;
}
struct sk_filter *filter;
#endif
if (atomic_read(&sk->omem_alloc))
printk(KERN_DEBUG "sk_free: optmem leakage (%d bytes) detected.\n", atomic_read(&sk->omem_alloc));
if (sk->destruct)
sk->destruct(sk);
#ifdef CONFIG_FILTER
if (sk->filter) {
sk_filter_release(sk, sk->filter);
filter = sk->filter;
if (filter) {
sk_filter_release(sk, filter);
sk->filter = NULL;
}
#endif
......
/*
* $Id: ipconfig.c,v 1.19 1999/01/15 06:54:00 davem Exp $
* $Id: ipconfig.c,v 1.20 1999/03/28 10:18:28 davem Exp $
*
* Automatic Configuration of IP -- use BOOTP or RARP or user-supplied
* information to configure own IP address and routes.
......@@ -825,9 +825,9 @@ int __init ip_auto_config(void)
*/
if (ic_myaddr == INADDR_NONE ||
#ifdef CONFIG_ROOT_NFS
root_server_addr == INADDR_NONE ||
(root_server_addr == INADDR_NONE && ic_servaddr == INADDR_NONE) ||
#endif
(ic_first_dev && ic_first_dev->next)) {
ic_first_dev->next) {
#ifdef CONFIG_IP_PNP_DYNAMIC
if (ic_dynamic() < 0) {
printk(KERN_ERR "IP-Config: Auto-configuration of network failed.\n");
......
......@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
* Version: $Id: tcp_ipv4.c,v 1.170 1999/03/21 05:22:47 davem Exp $
* Version: $Id: tcp_ipv4.c,v 1.171 1999/03/28 10:18:26 davem Exp $
*
* IPv4 specific functions
*
......@@ -1305,6 +1305,9 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
if(newsk != NULL) {
struct tcp_opt *newtp;
#ifdef CONFIG_FILTER
struct sk_filter *filter;
#endif
memcpy(newsk, sk, sizeof(*newsk));
newsk->sklist_next = NULL;
......@@ -1326,8 +1329,8 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
skb_queue_head_init(&newsk->back_log);
skb_queue_head_init(&newsk->error_queue);
#ifdef CONFIG_FILTER
if (newsk->filter)
sk_filter_charge(newsk, newsk->filter);
if ((filter = newsk->filter) != NULL)
sk_filter_charge(newsk, filter);
#endif
/* Now setup tcp_opt */
......@@ -1559,9 +1562,9 @@ static inline struct sock *tcp_v4_hnd_req(struct sock *sk,struct sk_buff *skb)
int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
{
#ifdef CONFIG_FILTER
if (sk->filter && sk_filter(skb, sk->filter))
struct sk_filter *filter = sk->filter;
if (filter && sk_filter(skb, filter))
goto discard;
#endif /* CONFIG_FILTER */
......
......@@ -5,7 +5,7 @@
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
* $Id: tcp_ipv6.c,v 1.100 1999/03/21 05:22:59 davem Exp $
* $Id: tcp_ipv6.c,v 1.101 1999/03/28 10:18:30 davem Exp $
*
* Based on:
* linux/net/ipv4/tcp.c
......@@ -1181,6 +1181,9 @@ static inline struct sock *tcp_v6_hnd_req(struct sock *sk, struct sk_buff *skb)
static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
{
#ifdef CONFIG_FILTER
struct sk_filter *filter;
#endif
int users = 0;
/* Imagine: socket is IPv6. IPv4 packet arrives,
......@@ -1195,7 +1198,8 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
return tcp_v4_do_rcv(sk, skb);
#ifdef CONFIG_FILTER
if (sk->filter && sk_filter(skb, sk->filter))
filter = sk->filter;
if (filter && sk_filter(skb, filter))
goto discard;
#endif /* CONFIG_FILTER */
......
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