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
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
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.
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
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
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
-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.
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
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
return;
}
mdelay(1);
+ barrier();
}
DBGS(("secondary_cpu_start: SUCCESS for CPU %d!!!\n", cpuid));
}
if (!(hwrpb->txrdy & cpumask))
goto ready1;
udelay(100);
+ barrier();
}
goto timeout;
if (!(hwrpb->txrdy & cpumask))
goto ready2;
udelay(100);
+ barrier();
}
goto timeout;
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)
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)
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:
/*
* 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
/*****************************************************************************/
#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
+
/*****************************************************************************/
/*
#define BRD_ECHPCI 26
#define BRD_ECH64PCI 27
#define BRD_EASYIOPCI 28
+#define BRD_ECPPCI 29
#define BRD_BRUMBY BRD_BRUMBY4
} 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);
*/
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";
"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
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
#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.
/*
* 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))
/*****************************************************************************/
#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);
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);
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);
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
/*****************************************************************************/
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];
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
/*****************************************************************************/
down(&stli_tmpwritesem);
copy_from_user(stli_tmpwritebuf, chbuf, count);
- up(&stli_tmpwritesem);
chbuf = &stli_tmpwritebuf[0];
}
portp->portidx;
*bits |= portp->portbit;
set_bit(ST_TXBUSY, &portp->state);
-
EBRDDISABLE(brdp);
+
+ if (from_user)
+ up(&stli_tmpwritesem);
restore_flags(flags);
return(count);
/*****************************************************************************/
+/*
+ * 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.
*/
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);
/*
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);
}
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);
/*
case BRD_ECP:
case BRD_ECPE:
case BRD_ECPMC:
+ case BRD_ECPPCI:
stli_initecp(brdp);
break;
case BRD_ONBOARD:
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);
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;
/*****************************************************************************/
+/*
+ * 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.
/*
* 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;
}
/*
- * 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
/*
* 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
/*****************************************************************************/
#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>
* 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:
} 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);
*/
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";
/*****************************************************************************/
+#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 -
/*
* 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))
/*****************************************************************************/
#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);
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
/*
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)
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
/*****************************************************************************/
/*****************************************************************************/
+/*
+ * 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;
down(&stl_tmpwritesem);
copy_from_user(stl_tmpwritebuf, chbuf, count);
- up(&stl_tmpwritesem);
chbuf = &stl_tmpwritebuf[0];
}
clear_bit(ASYI_TXLOW, &portp->istate);
stl_startrxtx(portp, -1, 1);
+ if (from_user)
+ up(&stl_tmpwritesem);
+
return(count);
}
}
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);
}
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);
}
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);
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);
/*****************************************************************************/
+/*
+ * 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
/*
* 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
/*
*/
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);
}
-
/*****************************************************************************/
/*
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
*/
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;
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
}
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
}
}
+#ifdef HAVE_SOCAL_UCODE
static void socal_bzero(void *d, int size)
{
u32 *dp = (u32 *)d;
size -= sizeof(u32);
}
}
+#endif
static inline void socal_disable(struct socal *s)
{
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 */
#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)
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)
/* 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.
#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 */
*/
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);
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
*/
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 */
* 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>
char *optval, int optlen)
{
struct sock *sk=sock->sk;
+#ifdef CONFIG_FILTER
+ struct sk_filter *filter;
+#endif
int val;
int valbool;
int err;
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;
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.
*/
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");
*
* 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
*
if(newsk != NULL) {
struct tcp_opt *newtp;
+#ifdef CONFIG_FILTER
+ struct sk_filter *filter;
+#endif
memcpy(newsk, sk, sizeof(*newsk));
newsk->sklist_next = NULL;
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 */
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 */
* 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
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,
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 */