From 4cfb4152630eb36444cb33c28cbaffbb6378fa56 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:18:31 -0500 Subject: [PATCH] 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 --- Documentation/stallion.txt | 168 ++++++++--- arch/alpha/kernel/smp.c | 3 + arch/sparc64/kernel/smp.c | 11 + arch/sparc64/mm/init.c | 6 +- arch/sparc64/mm/ultra.S | 17 +- drivers/char/istallion.c | 532 ++++++++++++++++++++++++++++++---- drivers/char/stallion.c | 383 +++++++++++++++++++----- drivers/char/synclink.c | 2 +- drivers/fc4/socal.c | 2 + drivers/video/fbcon.c | 2 +- include/asm-i386/timex.h | 2 +- include/asm-sparc64/pgtable.h | 6 +- include/asm-sparc64/smp.h | 11 +- include/linux/if_arp.h | 2 +- include/linux/sched.h | 1 + include/net/sock.h | 5 +- net/core/sock.c | 34 +-- net/ipv4/ipconfig.c | 6 +- net/ipv4/tcp_ipv4.c | 13 +- net/ipv6/tcp_ipv6.c | 8 +- 20 files changed, 1001 insertions(+), 213 deletions(-) diff --git a/Documentation/stallion.txt b/Documentation/stallion.txt index 5a1a30320a97..65f4bcb8a52f 100644 --- a/Documentation/stallion.txt +++ b/Documentation/stallion.txt @@ -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?=[,[,][,]] + +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 diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 25615e43de0c..b905a66b73ca 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -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 @@ delay1: if (!(hwrpb->txrdy & cpumask)) goto ready1; udelay(100); + barrier(); } goto timeout; @@ -549,6 +551,7 @@ delay2: if (!(hwrpb->txrdy & cpumask)) goto ready2; udelay(100); + barrier(); } goto timeout; diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 54b100e33148..f2c921ab3f8a 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -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< -#include -#include -#include -#include +#include #include -#include -#include -#include -#include #include #include #include #include #include -#include -#include #include #include #include -#include + #include #include +#ifdef CONFIG_PCI +#include +#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,7 +638,11 @@ static unsigned int stli_baudrates[] = { /* * Define some handy local macros... */ -#define MIN(a,b) (((a) <= (b)) ? (a) : (b)) +#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 diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index dd27a4e26a79..5093d2237a7f 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -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 -#include -#include -#include +#include #include -#include -#include -#include -#include #include #include #include #include #include #include -#include -#include #include -#include #include #include -#include #include #include @@ -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 -#define MIN(a,b) (((a) <= (b)) ? (a) : (b)) -#endif +#undef MIN +#define MIN(a,b) (((a) <= (b)) ? (a) : (b)) + +#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 diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index fd7fb4688555..0881c88218c2 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -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 diff --git a/drivers/fc4/socal.c b/drivers/fc4/socal.c index e3a1c28e19fb..bf76123a6b9d 100644 --- a/drivers/fc4/socal.c +++ b/drivers/fc4/socal.c @@ -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) { diff --git a/drivers/video/fbcon.c b/drivers/video/fbcon.c index 64abb5a0126b..6e79fa5fcdef 100644 --- a/drivers/video/fbcon.c +++ b/drivers/video/fbcon.c @@ -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 */ diff --git a/include/asm-i386/timex.h b/include/asm-i386/timex.h index bca879f733ef..f50fe1c46131 100644 --- a/include/asm-i386/timex.h +++ b/include/asm-i386/timex.h @@ -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 } diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h index 958a924da74f..b4782e72f617 100644 --- a/include/asm-sparc64/pgtable.h +++ b/include/asm-sparc64/pgtable.h @@ -1,4 +1,4 @@ -/* $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) diff --git a/include/asm-sparc64/smp.h b/include/asm-sparc64/smp.h index 21eb76a22a29..c5e99dab3d94 100644 --- a/include/asm-sparc64/smp.h +++ b/include/asm-sparc64/smp.h @@ -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. diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h index 24e001e9781a..39007c8bf55c 100644 --- a/include/linux/if_arp.h +++ b/include/linux/if_arp.h @@ -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 */ diff --git a/include/linux/sched.h b/include/linux/sched.h index 1e6c27a622ef..a5bbd135504f 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -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); diff --git a/include/net/sock.h b/include/net/sock.h index 31261fd69b18..6c7f51202f8e 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -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 */ diff --git a/net/core/sock.c b/net/core/sock.c index 2266a9641db4..90e2ad495ca6 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -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, * Fred N. van Kempen, @@ -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,16 +344,11 @@ 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; - + filter = sk->filter; + if(filter) { sk->filter = NULL; synchronize_bh(); - - if (filter) - sk_filter_release(sk, filter); + sk_filter_release(sk, filter); return 0; } return -ENOENT; @@ -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 diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 94e64eec65e8..abe93ec2776e 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -1,5 +1,5 @@ /* - * $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"); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 3afdb55a5521..cc94ced0f36f 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -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 */ diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index f27c6148a3bc..d42542145316 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $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 */ -- 2.39.5