diff -u --recursive --new-file v2.1.129/linux/CREDITS linux/CREDITS --- v2.1.129/linux/CREDITS Thu Nov 19 09:56:27 1998 +++ linux/CREDITS Mon Nov 23 10:00:31 1998 @@ -1423,6 +1423,10 @@ D: implemented kmod D: modularized BSD Unix domain sockets +N: Reed H. Petty +E: rhp@draper.net +D: Loop device driver extensions + N: Kai Petzke E: wpp@marie.physik.tu-berlin.de W: http://physik.tu-berlin.de/~wpp @@ -2011,7 +2015,7 @@ S: The Netherlands N: David Woodhouse -E: Dave@mvhi.com +E: David.Woodhouse@mvhi.com E: Dave@imladris.demon.co.uk D: Extensive ARCnet rewrite D: ARCnet COM20020, COM90xx IO-MAP drivers diff -u --recursive --new-file v2.1.129/linux/Makefile linux/Makefile --- v2.1.129/linux/Makefile Thu Nov 19 09:56:27 1998 +++ linux/Makefile Thu Nov 19 09:56:40 1998 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 129 +SUBLEVEL = 130 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) diff -u --recursive --new-file v2.1.129/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c --- v2.1.129/linux/arch/alpha/kernel/alpha_ksyms.c Fri Oct 23 22:01:19 1998 +++ linux/arch/alpha/kernel/alpha_ksyms.c Fri Nov 20 10:38:42 1998 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -26,6 +27,7 @@ #include #include #include +#include #define __KERNEL_SYSCALLS__ #include diff -u --recursive --new-file v2.1.129/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S --- v2.1.129/linux/arch/i386/kernel/entry.S Sun Nov 8 14:02:42 1998 +++ linux/arch/i386/kernel/entry.S Thu Nov 19 10:05:37 1998 @@ -150,14 +150,14 @@ jmp ret_from_sys_call -#ifdef __SMP__ ALIGN - .globl ret_from_smpfork -ret_from_smpfork: + .globl ret_from_fork +ret_from_fork: GET_CURRENT(%ebx) +#ifdef __SMP__ btrl $0, SYMBOL_NAME(scheduler_lock) - jmp ret_from_sys_call #endif /* __SMP__ */ + jmp ret_from_sys_call /* * Return to user mode is not as complex as all this looks, diff -u --recursive --new-file v2.1.129/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c --- v2.1.129/linux/arch/i386/kernel/process.c Fri Oct 9 13:27:05 1998 +++ linux/arch/i386/kernel/process.c Sun Nov 22 16:57:19 1998 @@ -50,11 +50,7 @@ spinlock_t semaphore_wake_lock = SPIN_LOCK_UNLOCKED; -#ifdef __SMP__ -asmlinkage void ret_from_fork(void) __asm__("ret_from_smpfork"); -#else -asmlinkage void ret_from_fork(void) __asm__("ret_from_sys_call"); -#endif +asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); #ifdef CONFIG_APM extern int apm_do_idle(void); @@ -506,6 +502,31 @@ mm->segments = NULL; vfree(ldt); } +} + +/* + * Create a kernel thread + */ +pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) +{ + long retval; + + __asm__ __volatile__( + "movl %%esp,%%esi\n\t" + "int $0x80\n\t" /* Linux/i386 system call */ + "cmpl %%esp,%%esi\n\t" /* child or parent? */ + "je 1f\n\t" /* parent - jump */ + "pushl %3\n\t" /* push argument */ + "call *%4\n\t" /* call fn */ + "movl %2,%0\n\t" /* exit */ + "int $0x80\n" + "1:\t" + :"=a" (retval) + :"0" (__NR_clone), "i" (__NR_exit), + "r" (arg), "r" (fn), + "b" (flags | CLONE_VM) + :"si"); + return retval; } /* diff -u --recursive --new-file v2.1.129/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c --- v2.1.129/linux/arch/i386/kernel/ptrace.c Mon Oct 5 13:13:35 1998 +++ linux/arch/i386/kernel/ptrace.c Sun Nov 22 09:38:19 1998 @@ -476,7 +476,7 @@ if(addr == (long) &dummy->u_debugreg[4]) return -EIO; if(addr == (long) &dummy->u_debugreg[5]) return -EIO; if(addr < (long) &dummy->u_debugreg[4] && - ((unsigned long) data) >= 0xbffffffd) return -EIO; + ((unsigned long) data) >= TASK_SIZE-3) return -EIO; ret = -EIO; if(addr == (long) &dummy->u_debugreg[7]) { diff -u --recursive --new-file v2.1.129/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c --- v2.1.129/linux/arch/i386/mm/fault.c Sun Nov 8 14:02:42 1998 +++ linux/arch/i386/mm/fault.c Sun Nov 22 09:38:19 1998 @@ -124,7 +124,7 @@ /* * accessing the stack below %esp is always a bug. * The "+ 32" is there due to some instructions (like - * pusha) doing pre-decrement on the stack and that + * pusha) doing post-decrement on the stack and that * doesn't show up until later.. */ if (address + 32 < regs->esp) diff -u --recursive --new-file v2.1.129/linux/drivers/Makefile linux/drivers/Makefile --- v2.1.129/linux/drivers/Makefile Wed Aug 26 11:37:34 1998 +++ linux/drivers/Makefile Fri Nov 20 08:59:01 1998 @@ -8,7 +8,7 @@ # Note 2! The CFLAGS definitions are now in the main makefile. SUB_DIRS := block char net misc sound -MOD_SUB_DIRS := $(SUB_DIRS) sbus +MOD_SUB_DIRS := $(SUB_DIRS) ALL_SUB_DIRS := $(SUB_DIRS) pci scsi sbus cdrom isdn pnp \ macintosh video dio zorro fc4 @@ -23,6 +23,7 @@ ifdef CONFIG_SBUS SUB_DIRS += sbus +MOD_SUB_DIRS += sbus endif ifdef CONFIG_ZORRO diff -u --recursive --new-file v2.1.129/linux/drivers/block/loop.c linux/drivers/block/loop.c --- v2.1.129/linux/drivers/block/loop.c Sun Nov 8 14:02:51 1998 +++ linux/drivers/block/loop.c Sun Nov 22 21:29:54 1998 @@ -17,6 +17,10 @@ * Handle sparse backing files correctly - Kenn Humborg, Jun 28, 1998 * * Loadable modules and other fixes by AK, 1998 + * + * Make real block number available to downstream transfer functions, enables + * CBC (and relatives) mode encryption requiring unique IVs per data block. + * Reed H. Petty, rhp@draper.net * * Still To Fix: * - Advisory locking is ignored here. @@ -67,7 +71,7 @@ * Transfer functions */ static int transfer_none(struct loop_device *lo, int cmd, char *raw_buf, - char *loop_buf, int size) + char *loop_buf, int size, int real_block) { if (cmd == READ) memcpy(loop_buf, raw_buf, size); @@ -77,7 +81,7 @@ } static int transfer_xor(struct loop_device *lo, int cmd, char *raw_buf, - char *loop_buf, int size) + char *loop_buf, int size, int real_block) { char *in, *out, *key; int i, keysize; @@ -245,7 +249,7 @@ } if ((lo->transfer)(lo, current_request->cmd, bh->b_data + offset, - dest_addr, size)) { + dest_addr, size, real_block)) { printk(KERN_ERR "loop: transfer error block %d\n", block); brelse(bh); goto error_out_lock; diff -u --recursive --new-file v2.1.129/linux/drivers/char/bttv.c linux/drivers/char/bttv.c --- v2.1.129/linux/drivers/char/bttv.c Thu Nov 12 16:21:18 1998 +++ linux/drivers/char/bttv.c Fri Nov 20 10:58:22 1998 @@ -2582,7 +2582,10 @@ btv->grabcount=0; btv->grab=0; btv->lastgrab=0; - btv->field=btv->last_field=0; + btv->field=btv->last_field=0; + btv->video_dev.minor = -1; + btv->vbi_dev.minor = -1; + btv->radio_dev.minor = -1; /* i2c */ memcpy(&(btv->i2c),&bttv_i2c_bus_template,sizeof(struct i2c_bus)); diff -u --recursive --new-file v2.1.129/linux/drivers/char/mem.c linux/drivers/char/mem.c --- v2.1.129/linux/drivers/char/mem.c Thu Nov 19 09:56:28 1998 +++ linux/drivers/char/mem.c Fri Nov 20 11:41:46 1998 @@ -512,7 +512,7 @@ case 3: filp->f_op = &null_fops; break; -#ifndef CONFIG_PPC +#if !defined(CONFIG_PPC) && !defined(__mc68000__) case 4: filp->f_op = &port_fops; break; @@ -568,6 +568,9 @@ tty_init(); #ifdef CONFIG_PRINTER lp_init(); +#endif +#ifdef CONFIG_M68K_PRINTER + lp_m68k_init(); #endif misc_init(); #ifdef CONFIG_SOUND diff -u --recursive --new-file v2.1.129/linux/drivers/char/misc.c linux/drivers/char/misc.c --- v2.1.129/linux/drivers/char/misc.c Thu Nov 19 09:56:28 1998 +++ linux/drivers/char/misc.c Fri Nov 20 11:42:15 1998 @@ -77,6 +77,8 @@ extern void acq_init(void); extern void pcwatchdog_init(void); extern int rtc_init(void); +extern int rtc_DP8570A_init(void); +extern int rtc_MK48T08_init(void); extern int dsp56k_init(void); extern int nvram_init(void); extern int radio_init(void); @@ -244,6 +246,12 @@ #endif #ifdef CONFIG_H8 h8_init(); +#endif +#ifdef CONFIG_MVME16x + rtc_MK48T08_init(); +#endif +#ifdef CONFIG_BVME6000 + rtc_DP8570A_init(); #endif #if defined(CONFIG_RTC) || defined(CONFIG_SUN_MOSTEK_RTC) rtc_init(); diff -u --recursive --new-file v2.1.129/linux/drivers/char/radio-sf16fmi.c linux/drivers/char/radio-sf16fmi.c --- v2.1.129/linux/drivers/char/radio-sf16fmi.c Sun Nov 8 14:02:55 1998 +++ linux/drivers/char/radio-sf16fmi.c Fri Nov 20 08:44:06 1998 @@ -77,13 +77,20 @@ static inline int fmi_setfreq(struct fmi_device *dev, unsigned long freq) { int myport = dev->port; - + int i; + outbits(16, RSF16_ENCODE(freq), myport); outbits(8, 0xC0, myport); - /* it is better than udelay(140000), isn't it? */ - current->state = TASK_INTERRUPTIBLE; + for(i=0; i< 100; i++) + { + udelay(1400); + if(current->need_resched) + schedule(); + } +/* If this becomes allowed use it ... + current->state = TASK_UNINTERRUPTIBLE; schedule_timeout(HZ/7); - /* ignore signals, we really should restore volume */ +*/ if (dev->curvol) fmi_unmute(myport); return 0; } @@ -93,17 +100,21 @@ int val; int res; int myport = dev->port; - + int i; + val = dev->curvol ? 0x08 : 0x00; /* unmute/mute */ outb(val, myport); outb(val | 0x10, myport); - /* it is better than udelay(140000), isn't it? */ - current->state = TASK_INTERRUPTIBLE; + for(i=0; i< 100; i++) + { + udelay(1400); + if(current->need_resched) + schedule(); + } +/* If this becomes allowed use it ... + current->state = TASK_UNINTERRUPTIBLE; schedule_timeout(HZ/7); - /* do not do it..., 140ms is very looong time to get signal in real program - if (signal_pending(current)) - return -EINTR; - */ +*/ res = (int)inb(myport+1); outb(val, myport); return (res & 2) ? 0 : 0xFFFF; diff -u --recursive --new-file v2.1.129/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v2.1.129/linux/drivers/char/tty_io.c Sun Nov 8 14:02:56 1998 +++ linux/drivers/char/tty_io.c Thu Nov 19 17:10:37 1998 @@ -1269,8 +1269,10 @@ filp->f_flags |= O_NONBLOCK; /* Don't let /dev/console block */ noctty = 1; } -#ifdef CONFIG_UNIX98_PTYS + if (device == PTMX_DEV) { +#ifdef CONFIG_UNIX98_PTYS + /* find a free pty. */ int major, minor; struct tty_driver *driver; @@ -1293,9 +1295,14 @@ devpts_pty_new(driver->other->name_base + minor, MKDEV(driver->other->major, minor + driver->other->minor_start)); noctty = 1; goto init_dev_done; + +#else /* CONFIG_UNIX_98_PTYS */ + + return -ENODEV; + +#endif /* CONFIG_UNIX_98_PTYS */ } -#endif - + retval = init_dev(device, &tty); if (retval) return retval; diff -u --recursive --new-file v2.1.129/linux/drivers/net/8390.c linux/drivers/net/8390.c --- v2.1.129/linux/drivers/net/8390.c Tue Jul 21 00:15:31 1998 +++ linux/drivers/net/8390.c Fri Nov 20 11:42:52 1998 @@ -950,7 +950,8 @@ int start_page) { int e8390_base = dev->base_addr; - + struct ei_device *ei_local = (struct ei_device *) dev->priv; + outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD); if (inb_p(e8390_base) & E8390_TRANS) diff -u --recursive --new-file v2.1.129/linux/drivers/net/at1700.c linux/drivers/net/at1700.c --- v2.1.129/linux/drivers/net/at1700.c Thu Nov 19 09:56:28 1998 +++ linux/drivers/net/at1700.c Fri Nov 20 08:44:06 1998 @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include diff -u --recursive --new-file v2.1.129/linux/drivers/net/atp.c linux/drivers/net/atp.c --- v2.1.129/linux/drivers/net/atp.c Thu Feb 12 20:56:07 1998 +++ linux/drivers/net/atp.c Fri Nov 20 08:44:06 1998 @@ -556,7 +556,7 @@ } num_tx_since_rx++; } else if (num_tx_since_rx > 8 - && jiffies > dev->last_rx + 100) { + && jiffies - dev->last_rx > 100) { if (net_debug > 2) printk("%s: Missed packet? No Rx after %d Tx and %ld jiffies" " status %02x CMR1 %02x.\n", dev->name, diff -u --recursive --new-file v2.1.129/linux/drivers/net/depca.c linux/drivers/net/depca.c --- v2.1.129/linux/drivers/net/depca.c Thu May 7 22:51:50 1998 +++ linux/drivers/net/depca.c Sun Nov 22 09:32:23 1998 @@ -1,212 +1,231 @@ /* depca.c: A DIGITAL DEPCA & EtherWORKS ethernet driver for linux. - Written 1994, 1995 by David C. Davies. + Written 1994, 1995 by David C. Davies. - Copyright 1994 David C. Davies - and - United States Government - (as represented by the Director, National Security Agency). - - Copyright 1995 Digital Equipment Corporation. - - - This software may be used and distributed according to the terms of - the GNU Public License, incorporated herein by reference. - - This driver is written for the Digital Equipment Corporation series - of DEPCA and EtherWORKS ethernet cards: - - DEPCA (the original) - DE100 - DE101 - DE200 Turbo - DE201 Turbo - DE202 Turbo (TP BNC) - DE210 - DE422 (EISA) - - The driver has been tested on DE100, DE200 and DE202 cards in a - relatively busy network. The DE422 has been tested a little. - - This driver will NOT work for the DE203, DE204 and DE205 series of - cards, since they have a new custom ASIC in place of the AMD LANCE - chip. See the 'ewrk3.c' driver in the Linux source tree for running - those cards. - - I have benchmarked the driver with a DE100 at 595kB/s to (542kB/s from) - a DECstation 5000/200. - - The author may be reached at davies@maniac.ultranet.com - - ========================================================================= - - The driver was originally based on the 'lance.c' driver from Donald - Becker which is included with the standard driver distribution for - linux. V0.4 is a complete re-write with only the kernel interface - remaining from the original code. - - 1) Lance.c code in /linux/drivers/net/ - 2) "Ethernet/IEEE 802.3 Family. 1992 World Network Data Book/Handbook", - AMD, 1992 [(800) 222-9323]. - 3) "Am79C90 CMOS Local Area Network Controller for Ethernet (C-LANCE)", - AMD, Pub. #17881, May 1993. - 4) "Am79C960 PCnet-ISA(tm), Single-Chip Ethernet Controller for ISA", - AMD, Pub. #16907, May 1992 - 5) "DEC EtherWORKS LC Ethernet Controller Owners Manual", - Digital Equipment corporation, 1990, Pub. #EK-DE100-OM.003 - 6) "DEC EtherWORKS Turbo Ethernet Controller Owners Manual", - Digital Equipment corporation, 1990, Pub. #EK-DE200-OM.003 - 7) "DEPCA Hardware Reference Manual", Pub. #EK-DEPCA-PR - Digital Equipment Corporation, 1989 - 8) "DEC EtherWORKS Turbo_(TP BNC) Ethernet Controller Owners Manual", - Digital Equipment corporation, 1991, Pub. #EK-DE202-OM.001 - - - Peter Bauer's depca.c (V0.5) was referred to when debugging V0.1 of this - driver. - - The original DEPCA card requires that the ethernet ROM address counter - be enabled to count and has an 8 bit NICSR. The ROM counter enabling is - only done when a 0x08 is read as the first address octet (to minimise - the chances of writing over some other hardware's I/O register). The - NICSR accesses have been changed to byte accesses for all the cards - supported by this driver, since there is only one useful bit in the MSB - (remote boot timeout) and it is not used. Also, there is a maximum of - only 48kB network RAM for this card. My thanks to Torbjorn Lindh for - help debugging all this (and holding my feet to the fire until I got it - right). - - The DE200 series boards have on-board 64kB RAM for use as a shared - memory network buffer. Only the DE100 cards make use of a 2kB buffer - mode which has not been implemented in this driver (only the 32kB and - 64kB modes are supported [16kB/48kB for the original DEPCA]). - - At the most only 2 DEPCA cards can be supported on the ISA bus because - there is only provision for two I/O base addresses on each card (0x300 - and 0x200). The I/O address is detected by searching for a byte sequence - in the Ethernet station address PROM at the expected I/O address for the - Ethernet PROM. The shared memory base address is 'autoprobed' by - looking for the self test PROM and detecting the card name. When a - second DEPCA is detected, information is placed in the base_addr - variable of the next device structure (which is created if necessary), - thus enabling ethif_probe initialization for the device. More than 2 - EISA cards can be supported, but care will be needed assigning the - shared memory to ensure that each slot has the correct IRQ, I/O address - and shared memory address assigned. - - ************************************************************************ - - NOTE: If you are using two ISA DEPCAs, it is important that you assign - the base memory addresses correctly. The driver autoprobes I/O 0x300 - then 0x200. The base memory address for the first device must be less - than that of the second so that the auto probe will correctly assign the - I/O and memory addresses on the same card. I can't think of a way to do - this unambiguously at the moment, since there is nothing on the cards to - tie I/O and memory information together. - - I am unable to test 2 cards together for now, so this code is - unchecked. All reports, good or bad, are welcome. - - ************************************************************************ - - The board IRQ setting must be at an unused IRQ which is auto-probed - using Donald Becker's autoprobe routines. DEPCA and DE100 board IRQs are - {2,3,4,5,7}, whereas the DE200 is at {5,9,10,11,15}. Note that IRQ2 is - really IRQ9 in machines with 16 IRQ lines. - - No 16MB memory limitation should exist with this driver as DMA is not - used and the common memory area is in low memory on the network card (my - current system has 20MB and I've not had problems yet). - - The ability to load this driver as a loadable module has been added. To - utilise this ability, you have to do <8 things: - - 0) have a copy of the loadable modules code installed on your system. - 1) copy depca.c from the /linux/drivers/net directory to your favourite - temporary directory. - 2) if you wish, edit the source code near line 1530 to reflect the I/O - address and IRQ you're using (see also 5). - 3) compile depca.c, but include -DMODULE in the command line to ensure - that the correct bits are compiled (see end of source code). - 4) if you are wanting to add a new card, goto 5. Otherwise, recompile a - kernel with the depca configuration turned off and reboot. - 5) insmod depca.o [irq=7] [io=0x200] [mem=0xd0000] [adapter_name=DE100] - [Alan Cox: Changed the code to allow command line irq/io assignments] - [Dave Davies: Changed the code to allow command line mem/name - assignments] - 6) run the net startup bits for your eth?? interface manually - (usually /etc/rc.inet[12] at boot time). - 7) enjoy! - - Note that autoprobing is not allowed in loadable modules - the system is - already up and running and you're messing with interrupts. - - To unload a module, turn off the associated interface - 'ifconfig eth?? down' then 'rmmod depca'. - - To assign a base memory address for the shared memory when running as a - loadable module, see 5 above. To include the adapter name (if you have - no PROM but know the card name) also see 5 above. Note that this last - option will not work with kernel built-in depca's. - - The shared memory assignment for a loadable module makes sense to avoid - the 'memory autoprobe' picking the wrong shared memory (for the case of - 2 depca's in a PC). - - - TO DO: - ------ - - - Revision History - ---------------- - - Version Date Description - - 0.1 25-jan-94 Initial writing. - 0.2 27-jan-94 Added LANCE TX hardware buffer chaining. - 0.3 1-feb-94 Added multiple DEPCA support. - 0.31 4-feb-94 Added DE202 recognition. - 0.32 19-feb-94 Tidy up. Improve multi-DEPCA support. - 0.33 25-feb-94 Fix DEPCA ethernet ROM counter enable. - Add jabber packet fix from murf@perftech.com - and becker@super.org - 0.34 7-mar-94 Fix DEPCA max network memory RAM & NICSR access. - 0.35 8-mar-94 Added DE201 recognition. Tidied up. - 0.351 30-apr-94 Added EISA support. Added DE422 recognition. - 0.36 16-may-94 DE422 fix released. - 0.37 22-jul-94 Added MODULE support - 0.38 15-aug-94 Added DBR ROM switch in depca_close(). - Multi DEPCA bug fix. - 0.38axp 15-sep-94 Special version for Alpha AXP Linux V1.0. - 0.381 12-dec-94 Added DE101 recognition, fix multicast bug. - 0.382 9-feb-95 Fix recognition bug reported by . - 0.383 22-feb-95 Fix for conflict with VESA SCSI reported by - - 0.384 17-mar-95 Fix a ring full bug reported by - 0.385 3-apr-95 Fix a recognition bug reported by - - 0.386 21-apr-95 Fix the last fix...sorry, must be galloping senility - 0.40 25-May-95 Rewrite for portability & updated. - ALPHA support from - 0.41 26-Jun-95 Added verify_area() calls in depca_ioctl() from - suggestion by - 0.42 27-Dec-95 Add 'mem' shared memory assignment for loadable - modules. - Add 'adapter_name' for loadable modules when no PROM. - Both above from a suggestion by - . - Add new multicasting code. - 0.421 22-Apr-96 Fix alloc_device() bug - 0.422 29-Apr-96 Fix depca_hw_init() bug - 0.423 7-Jun-96 Fix module load bug - 0.43 16-Aug-96 Update alloc_device() to conform to de4x5.c + Copyright 1994 David C. Davies + and + United States Government + (as represented by the Director, National Security Agency). + + Copyright 1995 Digital Equipment Corporation. + + + This software may be used and distributed according to the terms of + the GNU Public License, incorporated herein by reference. + + This driver is written for the Digital Equipment Corporation series + of DEPCA and EtherWORKS ethernet cards: + + DEPCA (the original) + DE100 + DE101 + DE200 Turbo + DE201 Turbo + DE202 Turbo (TP BNC) + DE210 + DE422 (EISA) + + The driver has been tested on DE100, DE200 and DE202 cards in a + relatively busy network. The DE422 has been tested a little. + + This driver will NOT work for the DE203, DE204 and DE205 series of + cards, since they have a new custom ASIC in place of the AMD LANCE + chip. See the 'ewrk3.c' driver in the Linux source tree for running + those cards. + + I have benchmarked the driver with a DE100 at 595kB/s to (542kB/s from) + a DECstation 5000/200. + + The author may be reached at davies@maniac.ultranet.com + + ========================================================================= + + The driver was originally based on the 'lance.c' driver from Donald + Becker which is included with the standard driver distribution for + linux. V0.4 is a complete re-write with only the kernel interface + remaining from the original code. + + 1) Lance.c code in /linux/drivers/net/ + 2) "Ethernet/IEEE 802.3 Family. 1992 World Network Data Book/Handbook", + AMD, 1992 [(800) 222-9323]. + 3) "Am79C90 CMOS Local Area Network Controller for Ethernet (C-LANCE)", + AMD, Pub. #17881, May 1993. + 4) "Am79C960 PCnet-ISA(tm), Single-Chip Ethernet Controller for ISA", + AMD, Pub. #16907, May 1992 + 5) "DEC EtherWORKS LC Ethernet Controller Owners Manual", + Digital Equipment corporation, 1990, Pub. #EK-DE100-OM.003 + 6) "DEC EtherWORKS Turbo Ethernet Controller Owners Manual", + Digital Equipment corporation, 1990, Pub. #EK-DE200-OM.003 + 7) "DEPCA Hardware Reference Manual", Pub. #EK-DEPCA-PR + Digital Equipment Corporation, 1989 + 8) "DEC EtherWORKS Turbo_(TP BNC) Ethernet Controller Owners Manual", + Digital Equipment corporation, 1991, Pub. #EK-DE202-OM.001 + + + Peter Bauer's depca.c (V0.5) was referred to when debugging V0.1 of this + driver. + + The original DEPCA card requires that the ethernet ROM address counter + be enabled to count and has an 8 bit NICSR. The ROM counter enabling is + only done when a 0x08 is read as the first address octet (to minimise + the chances of writing over some other hardware's I/O register). The + NICSR accesses have been changed to byte accesses for all the cards + supported by this driver, since there is only one useful bit in the MSB + (remote boot timeout) and it is not used. Also, there is a maximum of + only 48kB network RAM for this card. My thanks to Torbjorn Lindh for + help debugging all this (and holding my feet to the fire until I got it + right). + + The DE200 series boards have on-board 64kB RAM for use as a shared + memory network buffer. Only the DE100 cards make use of a 2kB buffer + mode which has not been implemented in this driver (only the 32kB and + 64kB modes are supported [16kB/48kB for the original DEPCA]). + + At the most only 2 DEPCA cards can be supported on the ISA bus because + there is only provision for two I/O base addresses on each card (0x300 + and 0x200). The I/O address is detected by searching for a byte sequence + in the Ethernet station address PROM at the expected I/O address for the + Ethernet PROM. The shared memory base address is 'autoprobed' by + looking for the self test PROM and detecting the card name. When a + second DEPCA is detected, information is placed in the base_addr + variable of the next device structure (which is created if necessary), + thus enabling ethif_probe initialization for the device. More than 2 + EISA cards can be supported, but care will be needed assigning the + shared memory to ensure that each slot has the correct IRQ, I/O address + and shared memory address assigned. + + ************************************************************************ + + NOTE: If you are using two ISA DEPCAs, it is important that you assign + the base memory addresses correctly. The driver autoprobes I/O 0x300 + then 0x200. The base memory address for the first device must be less + than that of the second so that the auto probe will correctly assign the + I/O and memory addresses on the same card. I can't think of a way to do + this unambiguously at the moment, since there is nothing on the cards to + tie I/O and memory information together. + + I am unable to test 2 cards together for now, so this code is + unchecked. All reports, good or bad, are welcome. + + ************************************************************************ + + The board IRQ setting must be at an unused IRQ which is auto-probed + using Donald Becker's autoprobe routines. DEPCA and DE100 board IRQs are + {2,3,4,5,7}, whereas the DE200 is at {5,9,10,11,15}. Note that IRQ2 is + really IRQ9 in machines with 16 IRQ lines. + + No 16MB memory limitation should exist with this driver as DMA is not + used and the common memory area is in low memory on the network card (my + current system has 20MB and I've not had problems yet). + + The ability to load this driver as a loadable module has been added. To + utilise this ability, you have to do <8 things: + + 0) have a copy of the loadable modules code installed on your system. + 1) copy depca.c from the /linux/drivers/net directory to your favourite + temporary directory. + 2) if you wish, edit the source code near line 1530 to reflect the I/O + address and IRQ you're using (see also 5). + 3) compile depca.c, but include -DMODULE in the command line to ensure + that the correct bits are compiled (see end of source code). + 4) if you are wanting to add a new card, goto 5. Otherwise, recompile a + kernel with the depca configuration turned off and reboot. + 5) insmod depca.o [irq=7] [io=0x200] [mem=0xd0000] [adapter_name=DE100] + [Alan Cox: Changed the code to allow command line irq/io assignments] + [Dave Davies: Changed the code to allow command line mem/name + assignments] + 6) run the net startup bits for your eth?? interface manually + (usually /etc/rc.inet[12] at boot time). + 7) enjoy! + + Note that autoprobing is not allowed in loadable modules - the system is + already up and running and you're messing with interrupts. + + To unload a module, turn off the associated interface + 'ifconfig eth?? down' then 'rmmod depca'. + + To assign a base memory address for the shared memory when running as a + loadable module, see 5 above. To include the adapter name (if you have + no PROM but know the card name) also see 5 above. Note that this last + option will not work with kernel built-in depca's. + + The shared memory assignment for a loadable module makes sense to avoid + the 'memory autoprobe' picking the wrong shared memory (for the case of + 2 depca's in a PC). + + ************************************************************************ + Support for MCA EtherWORKS cards added 11-3-98. + Verified to work with up to 2 DE212 cards in a system (although not + fully stress-tested). + + Currently known bugs/limitations: + + Note: with the MCA stuff as a module, it trusts the MCA configuration, + not the command line for IRQ and memory address. You can + specify them if you want, but it will throw your values out. + You still have to pass the IO address it was configured as + though. + + ************************************************************************ + TO DO: + ------ + + + Revision History + ---------------- + + Version Date Description + + 0.1 25-jan-94 Initial writing. + 0.2 27-jan-94 Added LANCE TX hardware buffer chaining. + 0.3 1-feb-94 Added multiple DEPCA support. + 0.31 4-feb-94 Added DE202 recognition. + 0.32 19-feb-94 Tidy up. Improve multi-DEPCA support. + 0.33 25-feb-94 Fix DEPCA ethernet ROM counter enable. + Add jabber packet fix from murf@perftech.com + and becker@super.org + 0.34 7-mar-94 Fix DEPCA max network memory RAM & NICSR access. + 0.35 8-mar-94 Added DE201 recognition. Tidied up. + 0.351 30-apr-94 Added EISA support. Added DE422 recognition. + 0.36 16-may-94 DE422 fix released. + 0.37 22-jul-94 Added MODULE support + 0.38 15-aug-94 Added DBR ROM switch in depca_close(). + Multi DEPCA bug fix. + 0.38axp 15-sep-94 Special version for Alpha AXP Linux V1.0. + 0.381 12-dec-94 Added DE101 recognition, fix multicast bug. + 0.382 9-feb-95 Fix recognition bug reported by . + 0.383 22-feb-95 Fix for conflict with VESA SCSI reported by + + 0.384 17-mar-95 Fix a ring full bug reported by + 0.385 3-apr-95 Fix a recognition bug reported by + + 0.386 21-apr-95 Fix the last fix...sorry, must be galloping senility + 0.40 25-May-95 Rewrite for portability & updated. + ALPHA support from + 0.41 26-Jun-95 Added verify_area() calls in depca_ioctl() from + suggestion by + 0.42 27-Dec-95 Add 'mem' shared memory assignment for loadable + modules. + Add 'adapter_name' for loadable modules when no PROM. + Both above from a suggestion by + . + Add new multicasting code. + 0.421 22-Apr-96 Fix alloc_device() bug + 0.422 29-Apr-96 Fix depca_hw_init() bug + 0.423 7-Jun-96 Fix module load bug + 0.43 16-Aug-96 Update alloc_device() to conform to de4x5.c + 0.44 1-Sep-97 Fix *_probe() to test check_region() first - bug + reported by + 0.45 3-Nov-98 Added support for MCA EtherWORKS (DE210/DE212) cards + by + 0.451 5-Nov-98 Fixed mca stuff cuz I'm a dummy. + 0.5 14-Nov-98 Re-spin for 2.1.x kernels. - ========================================================================= - */ + ========================================================================= +*/ -static const char *version = "depca.c:v0.43 96/8/16 davies@maniac.ultranet.com\n"; +static const char *version = "depca.c:v0.5 1998/11/14 davies@maniac.ultranet.com\n"; #include @@ -234,6 +253,10 @@ #include #include +#ifdef CONFIG_MCA +#include +#endif + #include "depca.h" #ifdef DEPCA_DEBUG @@ -242,1650 +265,1800 @@ static int depca_debug = 1; #endif -#define DEPCA_NDA 0xffe0 /* No Device Address */ +#define DEPCA_NDA 0xffe0 /* No Device Address */ /* - ** Ethernet PROM defines - */ +** Ethernet PROM defines +*/ #define PROBE_LENGTH 32 #define ETH_PROM_SIG 0xAA5500FFUL /* - ** Set the number of Tx and Rx buffers. Ensure that the memory requested - ** here is <= to the amount of shared memory set up by the board switches. - ** The number of descriptors MUST BE A POWER OF 2. - ** - ** total_memory = NUM_RX_DESC*(8+RX_BUFF_SZ) + NUM_TX_DESC*(8+TX_BUFF_SZ) - */ -#define NUM_RX_DESC 8 /* Number of RX descriptors */ -#define NUM_TX_DESC 8 /* Number of TX descriptors */ -#define RX_BUFF_SZ 1536 /* Buffer size for each Rx buffer */ -#define TX_BUFF_SZ 1536 /* Buffer size for each Tx buffer */ - -#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ -#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ - -/* - ** EISA bus defines - */ -#define DEPCA_EISA_IO_PORTS 0x0c00 /* I/O port base address, slot 0 */ +** Set the number of Tx and Rx buffers. Ensure that the memory requested +** here is <= to the amount of shared memory set up by the board switches. +** The number of descriptors MUST BE A POWER OF 2. +** +** total_memory = NUM_RX_DESC*(8+RX_BUFF_SZ) + NUM_TX_DESC*(8+TX_BUFF_SZ) +*/ +#define NUM_RX_DESC 8 /* Number of RX descriptors */ +#define NUM_TX_DESC 8 /* Number of TX descriptors */ +#define RX_BUFF_SZ 1536 /* Buffer size for each Rx buffer */ +#define TX_BUFF_SZ 1536 /* Buffer size for each Tx buffer */ + +#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ +#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ + +/* +** EISA bus defines +*/ +#define DEPCA_EISA_IO_PORTS 0x0c00 /* I/O port base address, slot 0 */ #define MAX_EISA_SLOTS 16 #define EISA_SLOT_INC 0x1000 /* - ** ISA Bus defines - */ +** ISA Bus defines +*/ #define DEPCA_RAM_BASE_ADDRESSES {0xc0000,0xd0000,0xe0000,0x00000} #define DEPCA_IO_PORTS {0x300, 0x200, 0} #define DEPCA_TOTAL_SIZE 0x10 static short mem_chkd = 0; /* - ** Name <-> Adapter mapping - */ +** Adapter ID for the MCA EtherWORKS DE210/212 adapter +*/ +#define DE212_ID 0x6def + +/* +** Name <-> Adapter mapping +*/ #define DEPCA_SIGNATURE {"DEPCA",\ "DE100","DE101",\ "DE200","DE201","DE202",\ - "DE210",\ + "DE210","DE212",\ "DE422",\ ""} static enum { - DEPCA, de100, de101, de200, de201, de202, de210, de422, unknown + DEPCA, de100, de101, de200, de201, de202, de210, de212, de422, unknown } adapter; /* - ** Miscellaneous info... - */ +** Miscellaneous info... +*/ #define DEPCA_STRLEN 16 #define MAX_NUM_DEPCAS 2 /* - ** Memory Alignment. Each descriptor is 4 longwords long. To force a - ** particular alignment on the TX descriptor, adjust DESC_SKIP_LEN and - ** DESC_ALIGN. ALIGN aligns the start address of the private memory area - ** and hence the RX descriptor ring's first entry. - */ -#define ALIGN4 ((u_long)4 - 1) /* 1 longword align */ -#define ALIGN8 ((u_long)8 - 1) /* 2 longword (quadword) align */ -#define ALIGN ALIGN8 /* Keep the LANCE happy... */ +** Memory Alignment. Each descriptor is 4 longwords long. To force a +** particular alignment on the TX descriptor, adjust DESC_SKIP_LEN and +** DESC_ALIGN. ALIGN aligns the start address of the private memory area +** and hence the RX descriptor ring's first entry. +*/ +#define ALIGN4 ((u_long)4 - 1) /* 1 longword align */ +#define ALIGN8 ((u_long)8 - 1) /* 2 longword (quadword) align */ +#define ALIGN ALIGN8 /* Keep the LANCE happy... */ /* - ** The DEPCA Rx and Tx ring descriptors. - */ +** The DEPCA Rx and Tx ring descriptors. +*/ struct depca_rx_desc { - volatile s32 base; - s16 buf_length; /* This length is negative 2's complement! */ - s16 msg_length; /* This length is "normal". */ + volatile s32 base; + s16 buf_length; /* This length is negative 2's complement! */ + s16 msg_length; /* This length is "normal". */ }; struct depca_tx_desc { - volatile s32 base; - s16 length; /* This length is negative 2's complement! */ - s16 misc; /* Errors and TDR info */ + volatile s32 base; + s16 length; /* This length is negative 2's complement! */ + s16 misc; /* Errors and TDR info */ }; -#define LA_MASK 0x0000ffff /* LANCE address mask for mapping network RAM +#define LA_MASK 0x0000ffff /* LANCE address mask for mapping network RAM to LANCE memory address space */ /* - ** The Lance initialization block, described in databook, in common memory. - */ +** The Lance initialization block, described in databook, in common memory. +*/ struct depca_init { - u16 mode; /* Mode register */ - u8 phys_addr[ETH_ALEN]; /* Physical ethernet address */ - u8 mcast_table[8]; /* Multicast Hash Table. */ - u32 rx_ring; /* Rx ring base pointer & ring length */ - u32 tx_ring; /* Tx ring base pointer & ring length */ + u16 mode; /* Mode register */ + u8 phys_addr[ETH_ALEN]; /* Physical ethernet address */ + u8 mcast_table[8]; /* Multicast Hash Table. */ + u32 rx_ring; /* Rx ring base pointer & ring length */ + u32 tx_ring; /* Tx ring base pointer & ring length */ }; #define DEPCA_PKT_STAT_SZ 16 -#define DEPCA_PKT_BIN_SZ 128 /* Should be >=100 unless you - increase DEPCA_PKT_STAT_SZ */ +#define DEPCA_PKT_BIN_SZ 128 /* Should be >=100 unless you + increase DEPCA_PKT_STAT_SZ */ struct depca_private { - char devname[DEPCA_STRLEN]; /* Device Product String */ - char adapter_name[DEPCA_STRLEN]; /* /proc/ioports string */ - char adapter; /* Adapter type */ - struct depca_rx_desc *rx_ring; /* Pointer to start of RX descriptor ring */ - struct depca_tx_desc *tx_ring; /* Pointer to start of TX descriptor ring */ - struct depca_init init_block; /* Shadow Initialization block */ - char *rx_memcpy[NUM_RX_DESC]; /* CPU virt address of sh'd memory buffs */ - char *tx_memcpy[NUM_TX_DESC]; /* CPU virt address of sh'd memory buffs */ - u_long bus_offset; /* (E)ISA bus address offset vs LANCE */ - u_long sh_mem; /* Physical start addr of shared mem area */ - u_long dma_buffs; /* LANCE Rx and Tx buffers start address. */ - int rx_new, tx_new; /* The next free ring entry */ - int rx_old, tx_old; /* The ring entries to be free()ed. */ - struct net_device_stats stats; - struct { /* Private stats counters */ - u32 bins[DEPCA_PKT_STAT_SZ]; - u32 unicast; - u32 multicast; - u32 broadcast; - u32 excessive_collisions; - u32 tx_underruns; - u32 excessive_underruns; - } pktStats; - int txRingMask; /* TX ring mask */ - int rxRingMask; /* RX ring mask */ - s32 rx_rlen; /* log2(rxRingMask+1) for the descriptors */ - s32 tx_rlen; /* log2(txRingMask+1) for the descriptors */ + char devname[DEPCA_STRLEN]; /* Device Product String */ + char adapter_name[DEPCA_STRLEN];/* /proc/ioports string */ + char adapter; /* Adapter type */ + char mca_slot; /* MCA slot, if MCA else -1 */ struct depca_rx_desc *rx_ring; /* Pointer to start of RX descriptor ring */ + struct depca_tx_desc *tx_ring; /* Pointer to start of TX descriptor ring */ + struct depca_init init_block;/* Shadow Initialization block */ + char *rx_memcpy[NUM_RX_DESC]; /* CPU virt address of sh'd memory buffs */ + char *tx_memcpy[NUM_TX_DESC]; /* CPU virt address of sh'd memory buffs */ + u_long bus_offset; /* (E)ISA bus address offset vs LANCE */ + u_long sh_mem; /* Physical start addr of shared mem area */ + u_long dma_buffs; /* LANCE Rx and Tx buffers start address. */ + int rx_new, tx_new; /* The next free ring entry */ + int rx_old, tx_old; /* The ring entries to be free()ed. */ + struct net_device_stats stats; + struct { /* Private stats counters */ + u32 bins[DEPCA_PKT_STAT_SZ]; + u32 unicast; + u32 multicast; + u32 broadcast; + u32 excessive_collisions; + u32 tx_underruns; + u32 excessive_underruns; + } pktStats; + int txRingMask; /* TX ring mask */ + int rxRingMask; /* RX ring mask */ + s32 rx_rlen; /* log2(rxRingMask+1) for the descriptors */ + s32 tx_rlen; /* log2(txRingMask+1) for the descriptors */ }; /* - ** The transmit ring full condition is described by the tx_old and tx_new - ** pointers by: - ** tx_old = tx_new Empty ring - ** tx_old = tx_new+1 Full ring - ** tx_old+txRingMask = tx_new Full ring (wrapped condition) - */ +** The transmit ring full condition is described by the tx_old and tx_new +** pointers by: +** tx_old = tx_new Empty ring +** tx_old = tx_new+1 Full ring +** tx_old+txRingMask = tx_new Full ring (wrapped condition) +*/ #define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\ lp->tx_old+lp->txRingMask-lp->tx_new:\ lp->tx_old -lp->tx_new-1) /* - ** Public Functions - */ -static int depca_open(struct device *dev); -static int depca_start_xmit(struct sk_buff *skb, struct device *dev); -static void depca_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static int depca_close(struct device *dev); -static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd); +** Public Functions +*/ +static int depca_open(struct device *dev); +static int depca_start_xmit(struct sk_buff *skb, struct device *dev); +static void depca_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static int depca_close(struct device *dev); +static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd); static struct net_device_stats *depca_get_stats(struct device *dev); -static void set_multicast_list(struct device *dev); +static void set_multicast_list(struct device *dev); /* - ** Private functions - */ -static int depca_hw_init(struct device *dev, u_long ioaddr); -static void depca_init_ring(struct device *dev); -static int depca_rx(struct device *dev); -static int depca_tx(struct device *dev); - -static void LoadCSRs(struct device *dev); -static int InitRestartDepca(struct device *dev); -static void DepcaSignature(char *name, u_long paddr); -static int DevicePresent(u_long ioaddr); -static int get_hw_addr(struct device *dev); -static int EISA_signature(char *name, s32 eisa_id); -static void SetMulticastFilter(struct device *dev); -static void isa_probe(struct device *dev, u_long iobase); -static void eisa_probe(struct device *dev, u_long iobase); +** Private functions +*/ +static int depca_hw_init(struct device *dev, u_long ioaddr, int mca_slot); +static void depca_init_ring(struct device *dev); +static int depca_rx(struct device *dev); +static int depca_tx(struct device *dev); + +static void LoadCSRs(struct device *dev); +static int InitRestartDepca(struct device *dev); +static void DepcaSignature(char *name, u_long paddr); +static int DevicePresent(u_long ioaddr); +static int get_hw_addr(struct device *dev); +static int EISA_signature(char *name, s32 eisa_id); +static void SetMulticastFilter(struct device *dev); +static void isa_probe(struct device *dev, u_long iobase); +static void eisa_probe(struct device *dev, u_long iobase); +#ifdef CONFIG_MCA +static void mca_probe(struct device *dev, u_long iobase); +#endif static struct device *alloc_device(struct device *dev, u_long iobase); -static int depca_dev_index(char *s); -static struct device *insert_device(struct device *dev, u_long iobase, int (*init) (struct device *)); -static int load_packet(struct device *dev, struct sk_buff *skb); -static void depca_dbg_open(struct device *dev); +static int depca_dev_index(char *s); +static struct device *insert_device(struct device *dev, u_long iobase, int (*init)(struct device *)); +static int load_packet(struct device *dev, struct sk_buff *skb); +static void depca_dbg_open(struct device *dev); #ifdef MODULE -int init_module(void); -void cleanup_module(void); -static int autoprobed = 1, loading_module = 1; -#else -static u_char de1xx_irq[] __initdata = -{2, 3, 4, 5, 7, 9, 0}; -static u_char de2xx_irq[] __initdata = -{5, 9, 10, 11, 15, 0}; -static u_char de422_irq[] __initdata = -{5, 9, 10, 11, 0}; +int init_module(void); +void cleanup_module(void); +static int autoprobed = 1, loading_module = 1; +# else +static u_char de1xx_irq[] __initdata = {2,3,4,5,7,9,0}; +static u_char de2xx_irq[] __initdata = {5,9,10,11,15,0}; +static u_char de422_irq[] __initdata = {5,9,10,11,0}; static u_char *depca_irq; -static int autoprobed = 0, loading_module = 0; -#endif /* MODULE */ +static int autoprobed = 0, loading_module = 0; +#endif /* MODULE */ -static char name[DEPCA_STRLEN]; -static int num_depcas = 0, num_eth = 0; -static int mem = 0; /* For loadable module assignment - use insmod mem=0x????? .... */ -static char *adapter_name = '\0'; /* If no PROM when loadable module - use insmod adapter_name=DE??? ... - */ +static char name[DEPCA_STRLEN]; +static int num_depcas = 0, num_eth = 0; +static int mem=0; /* For loadable module assignment + use insmod mem=0x????? .... */ +static char *adapter_name = '\0'; /* If no PROM when loadable module + use insmod adapter_name=DE??? ... + */ /* - ** Miscellaneous defines... - */ +** Miscellaneous defines... +*/ #define STOP_DEPCA \ outw(CSR0, DEPCA_ADDR);\ outw(STOP, DEPCA_DATA) - + -__initfunc(int depca_probe(struct device *dev)) +__initfunc(int +depca_probe(struct device *dev)) { - int tmp = num_depcas, status = -ENODEV; - u_long iobase = dev->base_addr; + int tmp = num_depcas, status = -ENODEV; + u_long iobase = dev->base_addr; - if ((iobase == 0) && loading_module) { - printk("Autoprobing is not supported when loading a module based driver.\n"); - status = -EIO; - } else { - isa_probe(dev, iobase); - eisa_probe(dev, iobase); + if ((iobase == 0) && loading_module){ + printk("Autoprobing is not supported when loading a module based driver.\n"); + status = -EIO; + } else { +#ifdef CONFIG_MCA + mca_probe(dev, iobase); +#endif + isa_probe(dev, iobase); + eisa_probe(dev, iobase); - if ((tmp == num_depcas) && (iobase != 0) && loading_module) { - printk("%s: depca_probe() cannot find device at 0x%04lx.\n", dev->name, - iobase); - } - /* - ** Walk the device list to check that at least one device - ** initialised OK - */ - for (; (dev->priv == NULL) && (dev->next != NULL); dev = dev->next); - - if (dev->priv) - status = 0; - if (iobase == 0) - autoprobed = 1; - } + if ((tmp == num_depcas) && (iobase != 0) && loading_module) { + printk("%s: depca_probe() cannot find device at 0x%04lx.\n", dev->name, + iobase); + } + + /* + ** Walk the device list to check that at least one device + ** initialised OK + */ + for (; (dev->priv == NULL) && (dev->next != NULL); dev = dev->next); + + if (dev->priv) status = 0; + if (iobase == 0) autoprobed = 1; + } - return status; + return status; } __initfunc(static int - depca_hw_init(struct device *dev, u_long ioaddr)) +depca_hw_init(struct device *dev, u_long ioaddr, int mca_slot)) { - struct depca_private *lp; - int i, j, offset, netRAM, mem_len, status = 0; - s16 nicsr; - u_long mem_start = 0, mem_base[] = DEPCA_RAM_BASE_ADDRESSES; - - STOP_DEPCA; - - nicsr = inb(DEPCA_NICSR); - nicsr = ((nicsr & ~SHE & ~RBE & ~IEN) | IM); - outb(nicsr, DEPCA_NICSR); - - if (inw(DEPCA_DATA) == STOP) { - do { - strcpy(name, (adapter_name ? adapter_name : "")); - mem_start = (mem ? mem & 0xf0000 : mem_base[mem_chkd++]); - DepcaSignature(name, mem_start); - } while (!mem && mem_base[mem_chkd] && (adapter == unknown)); - - if ((adapter != unknown) && mem_start) { /* found a DEPCA device */ - dev->base_addr = ioaddr; - - if ((ioaddr & 0x0fff) == DEPCA_EISA_IO_PORTS) { /* EISA slot address */ - printk("%s: %s at 0x%04lx (EISA slot %d)", - dev->name, name, ioaddr, (int) ((ioaddr >> 12) & 0x0f)); - } else { /* ISA port address */ - printk("%s: %s at 0x%04lx", dev->name, name, ioaddr); - } - - printk(", h/w address "); - status = get_hw_addr(dev); - for (i = 0; i < ETH_ALEN - 1; i++) { /* get the ethernet address */ - printk("%2.2x:", dev->dev_addr[i]); - } - printk("%2.2x", dev->dev_addr[i]); - - if (status == 0) { - /* Set up the maximum amount of network RAM(kB) */ - netRAM = ((adapter != DEPCA) ? 64 : 48); - if ((nicsr & _128KB) && (adapter == de422)) - netRAM = 128; - offset = 0x0000; - - /* Shared Memory Base Address */ - if (nicsr & BUF) { - offset = 0x8000; /* 32kbyte RAM offset */ - nicsr &= ~BS; /* DEPCA RAM in top 32k */ - netRAM -= 32; - } - mem_start += offset; /* (E)ISA start address */ - if ((mem_len = (NUM_RX_DESC * (sizeof(struct depca_rx_desc) + RX_BUFF_SZ) + - NUM_TX_DESC * (sizeof(struct depca_tx_desc) + TX_BUFF_SZ) + - sizeof(struct depca_init))) <= - (netRAM << 10)) { - printk(",\n has %dkB RAM at 0x%.5lx", netRAM, mem_start); - - /* Enable the shadow RAM. */ - if (adapter != DEPCA) { - nicsr |= SHE; - outb(nicsr, DEPCA_NICSR); - } - /* Define the device private memory */ - dev->priv = (void *) kmalloc(sizeof(struct depca_private), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - lp = (struct depca_private *) dev->priv; - memset((char *) dev->priv, 0, sizeof(struct depca_private)); - lp->adapter = adapter; - sprintf(lp->adapter_name, "%s (%s)", name, dev->name); - request_region(ioaddr, DEPCA_TOTAL_SIZE, lp->adapter_name); - - /* Initialisation Block */ - lp->sh_mem = mem_start; - mem_start += sizeof(struct depca_init); - - /* Tx & Rx descriptors (aligned to a quadword boundary) */ - mem_start = (mem_start + ALIGN) & ~ALIGN; - lp->rx_ring = (struct depca_rx_desc *) mem_start; - - mem_start += (sizeof(struct depca_rx_desc) * NUM_RX_DESC); - lp->tx_ring = (struct depca_tx_desc *) mem_start; - - mem_start += (sizeof(struct depca_tx_desc) * NUM_TX_DESC); - lp->bus_offset = mem_start & 0x00ff0000; - mem_start &= LA_MASK; /* LANCE re-mapped start address */ - - lp->dma_buffs = mem_start; - - /* Finish initialising the ring information. */ - lp->rxRingMask = NUM_RX_DESC - 1; - lp->txRingMask = NUM_TX_DESC - 1; - - /* Calculate Tx/Rx RLEN size for the descriptors. */ - for (i = 0, j = lp->rxRingMask; j > 0; i++) { - j >>= 1; - } - lp->rx_rlen = (s32) (i << 29); - for (i = 0, j = lp->txRingMask; j > 0; i++) { - j >>= 1; - } - lp->tx_rlen = (s32) (i << 29); - - /* Load the initialisation block */ - depca_init_ring(dev); - - /* Initialise the control and status registers */ - LoadCSRs(dev); - - /* Enable DEPCA board interrupts for autoprobing */ - nicsr = ((nicsr & ~IM) | IEN); - outb(nicsr, DEPCA_NICSR); - - /* To auto-IRQ we enable the initialization-done and DMA err, - interrupts. For now we will always get a DMA error. */ - if (dev->irq < 2) { + struct depca_private *lp; + int i, j, offset, netRAM, mem_len, status=0; + s16 nicsr; + u_long mem_start=0, mem_base[] = DEPCA_RAM_BASE_ADDRESSES; + + STOP_DEPCA; + + nicsr = inb(DEPCA_NICSR); + nicsr = ((nicsr & ~SHE & ~RBE & ~IEN) | IM); + outb(nicsr, DEPCA_NICSR); + + if (inw(DEPCA_DATA) == STOP) { + do { + strcpy(name, (adapter_name ? adapter_name : "")); + mem_start = (mem ? mem & 0xf0000 : mem_base[mem_chkd++]); + DepcaSignature(name, mem_start); + } while (!mem && mem_base[mem_chkd] && (adapter == unknown)); + + if ((adapter != unknown) && mem_start) { /* found a DEPCA device */ + dev->base_addr = ioaddr; + + if (mca_slot != -1) { + printk("%s: %s at 0x%04lx (MCA slot %d)", dev->name, name, + ioaddr, mca_slot); + } else if ((ioaddr & 0x0fff) == DEPCA_EISA_IO_PORTS) { /* EISA slot address */ + printk("%s: %s at 0x%04lx (EISA slot %d)", + dev->name, name, ioaddr, (int)((ioaddr>>12)&0x0f)); + } else { /* ISA port address */ + printk("%s: %s at 0x%04lx", dev->name, name, ioaddr); + } + + printk(", h/w address "); + status = get_hw_addr(dev); + for (i=0; idev_addr[i]); + } + printk("%2.2x", dev->dev_addr[i]); + + if (status == 0) { + /* Set up the maximum amount of network RAM(kB) */ + netRAM = ((adapter != DEPCA) ? 64 : 48); + if ((nicsr & _128KB) && (adapter == de422)) netRAM = 128; + offset = 0x0000; + + /* Shared Memory Base Address */ + if (nicsr & BUF) { + offset = 0x8000; /* 32kbyte RAM offset*/ + nicsr &= ~BS; /* DEPCA RAM in top 32k */ + netRAM -= 32; + } + mem_start += offset; /* (E)ISA start address */ + if ((mem_len = (NUM_RX_DESC*(sizeof(struct depca_rx_desc)+RX_BUFF_SZ) + + NUM_TX_DESC*(sizeof(struct depca_tx_desc)+TX_BUFF_SZ) + + sizeof(struct depca_init))) <= + (netRAM<<10)) { + printk(",\n has %dkB RAM at 0x%.5lx", netRAM, mem_start); + + /* Enable the shadow RAM. */ + if (adapter != DEPCA) { + nicsr |= SHE; + outb(nicsr, DEPCA_NICSR); + } + + /* Define the device private memory */ + dev->priv = (void *) kmalloc(sizeof(struct depca_private), GFP_KERNEL); + if (dev->priv == NULL) + return -ENOMEM; + lp = (struct depca_private *)dev->priv; + memset((char *)dev->priv, 0, sizeof(struct depca_private)); + lp->adapter = adapter; + lp->mca_slot = mca_slot; + sprintf(lp->adapter_name,"%s (%s)", name, dev->name); + request_region(ioaddr, DEPCA_TOTAL_SIZE, lp->adapter_name); + + /* Initialisation Block */ + lp->sh_mem = mem_start; + mem_start += sizeof(struct depca_init); + + /* Tx & Rx descriptors (aligned to a quadword boundary) */ + mem_start = (mem_start + ALIGN) & ~ALIGN; + lp->rx_ring = (struct depca_rx_desc *)mem_start; + + mem_start += (sizeof(struct depca_rx_desc) * NUM_RX_DESC); + lp->tx_ring = (struct depca_tx_desc *)mem_start; + + mem_start += (sizeof(struct depca_tx_desc) * NUM_TX_DESC); + lp->bus_offset = mem_start & 0x00ff0000; + mem_start &= LA_MASK; /* LANCE re-mapped start address */ + + lp->dma_buffs = mem_start; + + /* Finish initialising the ring information. */ + lp->rxRingMask = NUM_RX_DESC - 1; + lp->txRingMask = NUM_TX_DESC - 1; + + /* Calculate Tx/Rx RLEN size for the descriptors. */ + for (i=0, j = lp->rxRingMask; j>0; i++) { + j >>= 1; + } + lp->rx_rlen = (s32)(i << 29); + for (i=0, j = lp->txRingMask; j>0; i++) { + j >>= 1; + } + lp->tx_rlen = (s32)(i << 29); + + /* Load the initialisation block */ + depca_init_ring(dev); + + /* Initialise the control and status registers */ + LoadCSRs(dev); + + /* Enable DEPCA board interrupts for autoprobing */ + nicsr = ((nicsr & ~IM)|IEN); + outb(nicsr, DEPCA_NICSR); + + /* To auto-IRQ we enable the initialization-done and DMA err, + interrupts. For now we will always get a DMA error. */ + if (dev->irq < 2) { #ifndef MODULE - unsigned char irqnum; - autoirq_setup(0); - - /* Assign the correct irq list */ - switch (lp->adapter) { - case DEPCA: - case de100: - case de101: - depca_irq = de1xx_irq; - break; - case de200: - case de201: - case de202: - case de210: - depca_irq = de2xx_irq; - break; - case de422: - depca_irq = de422_irq; - break; - } - - /* Trigger an initialization just for the interrupt. */ - outw(INEA | INIT, DEPCA_DATA); - - irqnum = autoirq_report(1); - if (!irqnum) { - printk(" and failed to detect IRQ line.\n"); - status = -ENXIO; - } else { - for (dev->irq = 0, i = 0; (depca_irq[i]) && (!dev->irq); i++) { - if (irqnum == depca_irq[i]) { - dev->irq = irqnum; - printk(" and uses IRQ%d.\n", dev->irq); - } - } - - if (!dev->irq) { - printk(" but incorrect IRQ line detected.\n"); - status = -ENXIO; - } - } -#endif /* MODULE */ - } else { - printk(" and assigned IRQ%d.\n", dev->irq); - } - if (status) - release_region(ioaddr, DEPCA_TOTAL_SIZE); - } else { - printk(",\n requests %dkB RAM: only %dkB is available!\n", - (mem_len >> 10), netRAM); - status = -ENXIO; - } - } else { - printk(" which has an Ethernet PROM CRC error.\n"); - status = -ENXIO; - } - } else { - status = -ENXIO; - } - if (!status) { - if (depca_debug > 1) { - printk(version); - } - /* The DEPCA-specific entries in the device structure. */ - dev->open = &depca_open; - dev->hard_start_xmit = &depca_start_xmit; - dev->stop = &depca_close; - dev->get_stats = &depca_get_stats; - dev->set_multicast_list = &set_multicast_list; - dev->do_ioctl = &depca_ioctl; - - dev->mem_start = 0; - - /* Fill in the generic field of the device structure. */ - ether_setup(dev); - } else { /* Incorrectly initialised hardware */ - if (dev->priv) { - kfree_s(dev->priv, sizeof(struct depca_private)); - dev->priv = NULL; - } - } - } else { + unsigned char irqnum; + autoirq_setup(0); + + /* Assign the correct irq list */ + switch (lp->adapter) { + case DEPCA: + case de100: + case de101: + depca_irq = de1xx_irq; + break; + case de200: + case de201: + case de202: + case de210: + case de212: + depca_irq = de2xx_irq; + break; + case de422: + depca_irq = de422_irq; + break; + } + + /* Trigger an initialization just for the interrupt. */ + outw(INEA | INIT, DEPCA_DATA); + + irqnum = autoirq_report(1); + if (!irqnum) { + printk(" and failed to detect IRQ line.\n"); + status = -ENXIO; + } else { + for (dev->irq=0,i=0; (depca_irq[i]) && (!dev->irq); i++) { + if (irqnum == depca_irq[i]) { + dev->irq = irqnum; + printk(" and uses IRQ%d.\n", dev->irq); + } + } + + if (!dev->irq) { + printk(" but incorrect IRQ line detected.\n"); status = -ENXIO; - } - - return status; -} - - -static int depca_open(struct device *dev) -{ - struct depca_private *lp = (struct depca_private *) dev->priv; - u_long ioaddr = dev->base_addr; - s16 nicsr; - int status = 0; - - STOP_DEPCA; - nicsr = inb(DEPCA_NICSR); - - /* Make sure the shadow RAM is enabled */ - if (adapter != DEPCA) { - nicsr |= SHE; - outb(nicsr, DEPCA_NICSR); - } - /* Re-initialize the DEPCA... */ - depca_init_ring(dev); - LoadCSRs(dev); - - depca_dbg_open(dev); - - if (request_irq(dev->irq, &depca_interrupt, 0, lp->adapter_name, dev)) { - printk("depca_open(): Requested IRQ%d is busy\n", dev->irq); - status = -EAGAIN; + } + } +#endif /* MODULE */ + } else { + printk(" and assigned IRQ%d.\n", dev->irq); + } + if (status) release_region(ioaddr, DEPCA_TOTAL_SIZE); } else { + printk(",\n requests %dkB RAM: only %dkB is available!\n", + (mem_len>>10), netRAM); + status = -ENXIO; + } + } else { + printk(" which has an Ethernet PROM CRC error.\n"); + status = -ENXIO; + } + } else { + status = -ENXIO; + } + if (!status) { + if (depca_debug > 1) { + printk(version); + } + + /* The DEPCA-specific entries in the device structure. */ + dev->open = &depca_open; + dev->hard_start_xmit = &depca_start_xmit; + dev->stop = &depca_close; + dev->get_stats = &depca_get_stats; + dev->set_multicast_list = &set_multicast_list; + dev->do_ioctl = &depca_ioctl; + + dev->mem_start = 0; + + /* Fill in the generic field of the device structure. */ + ether_setup(dev); + } else { /* Incorrectly initialised hardware */ + if (dev->priv) { + kfree_s(dev->priv, sizeof(struct depca_private)); + dev->priv = NULL; + } + } + } else { + status = -ENXIO; + } - /* Enable DEPCA board interrupts and turn off LED */ - nicsr = ((nicsr & ~IM & ~LED) | IEN); - outb(nicsr, DEPCA_NICSR); - outw(CSR0, DEPCA_ADDR); - - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - - status = InitRestartDepca(dev); - - if (depca_debug > 1) { - printk("CSR0: 0x%4.4x\n", inw(DEPCA_DATA)); - printk("nicsr: 0x%02x\n", inb(DEPCA_NICSR)); - } - } - - MOD_INC_USE_COUNT; - - return status; + return status; } -/* Initialize the lance Rx and Tx descriptor rings. */ -static void depca_init_ring(struct device *dev) + +static int +depca_open(struct device *dev) { - struct depca_private *lp = (struct depca_private *) dev->priv; - u_int i; - u_long p; - - /* Lock out other processes whilst setting up the hardware */ - set_bit(0, (void *) &dev->tbusy); - - lp->rx_new = lp->tx_new = 0; - lp->rx_old = lp->tx_old = 0; - - /* Initialize the base addresses and length of each buffer in the ring */ - for (i = 0; i <= lp->rxRingMask; i++) { - writel((p = lp->dma_buffs + i * RX_BUFF_SZ) | R_OWN, &lp->rx_ring[i].base); - writew(-RX_BUFF_SZ, &lp->rx_ring[i].buf_length); - lp->rx_memcpy[i] = (char *) (p + lp->bus_offset); - } - for (i = 0; i <= lp->txRingMask; i++) { - writel((p = lp->dma_buffs + (i + lp->txRingMask + 1) * TX_BUFF_SZ) & 0x00ffffff, - &lp->tx_ring[i].base); - lp->tx_memcpy[i] = (char *) (p + lp->bus_offset); - } - - /* Set up the initialization block */ - lp->init_block.rx_ring = ((u32) ((u_long) lp->rx_ring) & LA_MASK) | lp->rx_rlen; - lp->init_block.tx_ring = ((u32) ((u_long) lp->tx_ring) & LA_MASK) | lp->tx_rlen; - - SetMulticastFilter(dev); - - for (i = 0; i < ETH_ALEN; i++) { - lp->init_block.phys_addr[i] = dev->dev_addr[i]; - } - - lp->init_block.mode = 0x0000; /* Enable the Tx and Rx */ - - return; -} - -/* - ** Writes a socket buffer to TX descriptor ring and starts transmission - */ -static int depca_start_xmit(struct sk_buff *skb, struct device *dev) -{ - struct depca_private *lp = (struct depca_private *) dev->priv; - u_long ioaddr = dev->base_addr; - int status = 0; - - /* Transmitter timeout, serious problems. */ - if (dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 1 * HZ) { - status = -1; - } else { - printk("%s: transmit timed out, status %04x, resetting.\n", - dev->name, inw(DEPCA_DATA)); - - STOP_DEPCA; - depca_init_ring(dev); - LoadCSRs(dev); - dev->interrupt = UNMASK_INTERRUPTS; - dev->start = 1; - dev->tbusy = 0; - dev->trans_start = jiffies; - InitRestartDepca(dev); - } - return status; - } - else if (skb->len > 0) - { - /* Enforce 1 process per h/w access */ - if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) { - printk("%s: Transmitter access conflict.\n", dev->name); - status = -1; - } else { - if (TX_BUFFS_AVAIL) { /* Fill in a Tx ring entry */ - status = load_packet(dev, skb); - - if (!status) { - /* Trigger an immediate send demand. */ - outw(CSR0, DEPCA_ADDR); - outw(INEA | TDMD, DEPCA_DATA); - - dev->trans_start = jiffies; - dev_kfree_skb(skb); - } - if (TX_BUFFS_AVAIL) { - dev->tbusy = 0; - } - } else { - status = -1; - } - } - } - return status; + struct depca_private *lp = (struct depca_private *)dev->priv; + u_long ioaddr = dev->base_addr; + s16 nicsr; + int status = 0; + + STOP_DEPCA; + nicsr = inb(DEPCA_NICSR); + + /* Make sure the shadow RAM is enabled */ + if (adapter != DEPCA) { + nicsr |= SHE; + outb(nicsr, DEPCA_NICSR); + } + + /* Re-initialize the DEPCA... */ + depca_init_ring(dev); + LoadCSRs(dev); + + depca_dbg_open(dev); + + if (request_irq(dev->irq, &depca_interrupt, 0, lp->adapter_name, dev)) { + printk("depca_open(): Requested IRQ%d is busy\n",dev->irq); + status = -EAGAIN; + } else { + + /* Enable DEPCA board interrupts and turn off LED */ + nicsr = ((nicsr & ~IM & ~LED)|IEN); + outb(nicsr, DEPCA_NICSR); + outw(CSR0,DEPCA_ADDR); + + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + status = InitRestartDepca(dev); + + if (depca_debug > 1){ + printk("CSR0: 0x%4.4x\n",inw(DEPCA_DATA)); + printk("nicsr: 0x%02x\n",inb(DEPCA_NICSR)); + } + } + + MOD_INC_USE_COUNT; + + return status; } -/* - ** The DEPCA interrupt handler. - */ -static void depca_interrupt(int irq, void *dev_id, struct pt_regs *regs) +/* Initialize the lance Rx and Tx descriptor rings. */ +static void +depca_init_ring(struct device *dev) { - struct device *dev = dev_id; - struct depca_private *lp; - s16 csr0, nicsr; - u_long ioaddr; - - if (dev == NULL) { - printk("depca_interrupt(): irq %d for unknown device.\n", irq); + struct depca_private *lp = (struct depca_private *)dev->priv; + u_int i; + u_long p; + + /* Lock out other processes whilst setting up the hardware */ + test_and_set_bit(0, (void *)&dev->tbusy); + + lp->rx_new = lp->tx_new = 0; + lp->rx_old = lp->tx_old = 0; + + /* Initialize the base addresses and length of each buffer in the ring */ + for (i = 0; i <= lp->rxRingMask; i++) { + writel((p=lp->dma_buffs+i*RX_BUFF_SZ) | R_OWN, &lp->rx_ring[i].base); + writew(-RX_BUFF_SZ, &lp->rx_ring[i].buf_length); + lp->rx_memcpy[i]=(char *)(p+lp->bus_offset); + } + for (i = 0; i <= lp->txRingMask; i++) { + writel((p=lp->dma_buffs+(i+lp->txRingMask+1)*TX_BUFF_SZ) & 0x00ffffff, + &lp->tx_ring[i].base); + lp->tx_memcpy[i]=(char *)(p+lp->bus_offset); + } + + /* Set up the initialization block */ + lp->init_block.rx_ring = ((u32)((u_long)lp->rx_ring)&LA_MASK) | lp->rx_rlen; + lp->init_block.tx_ring = ((u32)((u_long)lp->tx_ring)&LA_MASK) | lp->tx_rlen; + + SetMulticastFilter(dev); + + for (i = 0; i < ETH_ALEN; i++) { + lp->init_block.phys_addr[i] = dev->dev_addr[i]; + } + + lp->init_block.mode = 0x0000; /* Enable the Tx and Rx */ + + return; +} + +/* +** Writes a socket buffer to TX descriptor ring and starts transmission +*/ +static int +depca_start_xmit(struct sk_buff *skb, struct device *dev) +{ + struct depca_private *lp = (struct depca_private *)dev->priv; + u_long ioaddr = dev->base_addr; + int status = 0; + + /* Transmitter timeout, serious problems. */ + if (dev->tbusy) { + int tickssofar = jiffies - dev->trans_start; + if (tickssofar < 1*HZ) { + status = -1; + } else { + printk("%s: transmit timed out, status %04x, resetting.\n", + dev->name, inw(DEPCA_DATA)); + + STOP_DEPCA; + depca_init_ring(dev); + LoadCSRs(dev); + dev->interrupt = UNMASK_INTERRUPTS; + dev->start = 1; + dev->tbusy=0; + dev->trans_start = jiffies; + InitRestartDepca(dev); + } + return status; + } else if (skb->len > 0) { + /* Enforce 1 process per h/w access */ + if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { + printk("%s: Transmitter access conflict.\n", dev->name); + status = -1; + } else { + if (TX_BUFFS_AVAIL) { /* Fill in a Tx ring entry */ + status = load_packet(dev, skb); + + if (!status) { + /* Trigger an immediate send demand. */ + outw(CSR0, DEPCA_ADDR); + outw(INEA | TDMD, DEPCA_DATA); + + dev->trans_start = jiffies; + dev_kfree_skb(skb); + } + if (TX_BUFFS_AVAIL) { + dev->tbusy=0; + } + } else { + status = -1; + } + } + } + + return status; +} + +/* +** The DEPCA interrupt handler. +*/ +static void +depca_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct device *dev = dev_id; + struct depca_private *lp; + s16 csr0, nicsr; + u_long ioaddr; + + if (dev == NULL) { + printk ("depca_interrupt(): irq %d for unknown device.\n", irq); + } else { + lp = (struct depca_private *)dev->priv; + ioaddr = dev->base_addr; + + if (dev->interrupt) + printk("%s: Re-entering the interrupt handler.\n", dev->name); + + dev->interrupt = MASK_INTERRUPTS; + + /* mask the DEPCA board interrupts and turn on the LED */ + nicsr = inb(DEPCA_NICSR); + nicsr |= (IM|LED); + outb(nicsr, DEPCA_NICSR); + + outw(CSR0, DEPCA_ADDR); + csr0 = inw(DEPCA_DATA); + + /* Acknowledge all of the current interrupt sources ASAP. */ + outw(csr0 & INTE, DEPCA_DATA); + + if (csr0 & RINT) /* Rx interrupt (packet arrived) */ + depca_rx(dev); + + if (csr0 & TINT) /* Tx interrupt (packet sent) */ + depca_tx(dev); + + if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy) { /* any resources available? */ + dev->tbusy = 0; /* clear TX busy flag */ + mark_bh(NET_BH); + } + + /* Unmask the DEPCA board interrupts and turn off the LED */ + nicsr = (nicsr & ~IM & ~LED); + outb(nicsr, DEPCA_NICSR); + + dev->interrupt = UNMASK_INTERRUPTS; + } + + return; +} + +static int +depca_rx(struct device *dev) +{ + struct depca_private *lp = (struct depca_private *)dev->priv; + int i, entry; + s32 status; + + for (entry=lp->rx_new; + !(readl(&lp->rx_ring[entry].base) & R_OWN); + entry=lp->rx_new){ + status = readl(&lp->rx_ring[entry].base) >> 16 ; + if (status & R_STP) { /* Remember start of frame */ + lp->rx_old = entry; + } + if (status & R_ENP) { /* Valid frame status */ + if (status & R_ERR) { /* There was an error. */ + lp->stats.rx_errors++; /* Update the error stats. */ + if (status & R_FRAM) lp->stats.rx_frame_errors++; + if (status & R_OFLO) lp->stats.rx_over_errors++; + if (status & R_CRC) lp->stats.rx_crc_errors++; + if (status & R_BUFF) lp->stats.rx_fifo_errors++; + } else { + short len, pkt_len = readw(&lp->rx_ring[entry].msg_length); + struct sk_buff *skb; + + skb = dev_alloc_skb(pkt_len+2); + if (skb != NULL) { + unsigned char *buf; + skb_reserve(skb,2); /* 16 byte align the IP header */ + buf = skb_put(skb,pkt_len); + skb->dev = dev; + if (entry < lp->rx_old) { /* Wrapped buffer */ + len = (lp->rxRingMask - lp->rx_old + 1) * RX_BUFF_SZ; + memcpy_fromio(buf, lp->rx_memcpy[lp->rx_old], len); + memcpy_fromio(buf + len, lp->rx_memcpy[0], pkt_len-len); + } else { /* Linear buffer */ + memcpy_fromio(buf, lp->rx_memcpy[lp->rx_old], pkt_len); + } + + /* + ** Notify the upper protocol layers that there is another + ** packet to handle + */ + skb->protocol=eth_type_trans(skb,dev); + netif_rx(skb); + + /* + ** Update stats + */ + lp->stats.rx_packets++; + for (i=1; ipktStats.bins[i]++; + i = DEPCA_PKT_STAT_SZ; + } + } + if (buf[0] & 0x01) { /* Multicast/Broadcast */ + if ((*(s16 *)&buf[0] == -1) && + (*(s16 *)&buf[2] == -1) && + (*(s16 *)&buf[4] == -1)) { + lp->pktStats.broadcast++; + } else { + lp->pktStats.multicast++; + } + } else if ((*(s16 *)&buf[0] == *(s16 *)&dev->dev_addr[0]) && + (*(s16 *)&buf[2] == *(s16 *)&dev->dev_addr[2]) && + (*(s16 *)&buf[4] == *(s16 *)&dev->dev_addr[4])) { + lp->pktStats.unicast++; + } + + lp->pktStats.bins[0]++; /* Duplicates stats.rx_packets */ + if (lp->pktStats.bins[0] == 0) { /* Reset counters */ + memset((char *)&lp->pktStats, 0, sizeof(lp->pktStats)); + } } else { - lp = (struct depca_private *) dev->priv; - ioaddr = dev->base_addr; - - if (dev->interrupt) - printk("%s: Re-entering the interrupt handler.\n", dev->name); - - dev->interrupt = MASK_INTERRUPTS; - - /* mask the DEPCA board interrupts and turn on the LED */ - nicsr = inb(DEPCA_NICSR); - nicsr |= (IM | LED); - outb(nicsr, DEPCA_NICSR); - - outw(CSR0, DEPCA_ADDR); - csr0 = inw(DEPCA_DATA); - - /* Acknowledge all of the current interrupt sources ASAP. */ - outw(csr0 & INTE, DEPCA_DATA); - - if (csr0 & RINT) /* Rx interrupt (packet arrived) */ - depca_rx(dev); - - if (csr0 & TINT) /* Tx interrupt (packet sent) */ - depca_tx(dev); - - if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy) { /* any resources available? */ - dev->tbusy = 0; /* clear TX busy flag */ - mark_bh(NET_BH); - } - /* Unmask the DEPCA board interrupts and turn off the LED */ - nicsr = (nicsr & ~IM & ~LED); - outb(nicsr, DEPCA_NICSR); - - dev->interrupt = UNMASK_INTERRUPTS; - } - - return; -} - -static int depca_rx(struct device *dev) -{ - struct depca_private *lp = (struct depca_private *) dev->priv; - int i, entry; - s32 status; - - for (entry = lp->rx_new; - !(readl(&lp->rx_ring[entry].base) & R_OWN); - entry = lp->rx_new) { - status = readl(&lp->rx_ring[entry].base) >> 16; - if (status & R_STP) { /* Remember start of frame */ - lp->rx_old = entry; - } - if (status & R_ENP) { /* Valid frame status */ - if (status & R_ERR) { /* There was an error. */ - lp->stats.rx_errors++; /* Update the error stats. */ - if (status & R_FRAM) - lp->stats.rx_frame_errors++; - if (status & R_OFLO) - lp->stats.rx_over_errors++; - if (status & R_CRC) - lp->stats.rx_crc_errors++; - if (status & R_BUFF) - lp->stats.rx_fifo_errors++; - } else { - short len, pkt_len = readw(&lp->rx_ring[entry].msg_length); - struct sk_buff *skb; - - skb = dev_alloc_skb(pkt_len + 2); - if (skb != NULL) { - unsigned char *buf; - skb_reserve(skb, 2); /* 16 byte align the IP header */ - buf = skb_put(skb, pkt_len); - skb->dev = dev; - if (entry < lp->rx_old) { /* Wrapped buffer */ - len = (lp->rxRingMask - lp->rx_old + 1) * RX_BUFF_SZ; - memcpy_fromio(buf, lp->rx_memcpy[lp->rx_old], len); - memcpy_fromio(buf + len, lp->rx_memcpy[0], pkt_len - len); - } else { /* Linear buffer */ - memcpy_fromio(buf, lp->rx_memcpy[lp->rx_old], pkt_len); - } - - /* - ** Notify the upper protocol layers that there is another - ** packet to handle - */ - skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); - - /* - ** Update stats - */ - lp->stats.rx_packets++; - for (i = 1; i < DEPCA_PKT_STAT_SZ - 1; i++) { - if (pkt_len < (i * DEPCA_PKT_BIN_SZ)) { - lp->pktStats.bins[i]++; - i = DEPCA_PKT_STAT_SZ; - } - } - if (buf[0] & 0x01) { /* Multicast/Broadcast */ - if ((*(s16 *) & buf[0] == -1) && - (*(s16 *) & buf[2] == -1) && - (*(s16 *) & buf[4] == -1)) { - lp->pktStats.broadcast++; - } else { - lp->pktStats.multicast++; - } - } else if ((*(s16 *) & buf[0] == *(s16 *) & dev->dev_addr[0]) && - (*(s16 *) & buf[2] == *(s16 *) & dev->dev_addr[2]) && - (*(s16 *) & buf[4] == *(s16 *) & dev->dev_addr[4])) { - lp->pktStats.unicast++; - } - lp->pktStats.bins[0]++; /* Duplicates stats.rx_packets */ - if (lp->pktStats.bins[0] == 0) { /* Reset counters */ - memset((char *) &lp->pktStats, 0, sizeof(lp->pktStats)); - } - } else { - printk("%s: Memory squeeze, deferring packet.\n", dev->name); - lp->stats.rx_dropped++; /* Really, deferred. */ - break; - } - } - /* Change buffer ownership for this last frame, back to the adapter */ - for (; lp->rx_old != entry; lp->rx_old = (++lp->rx_old) & lp->rxRingMask) { - writel(readl(&lp->rx_ring[lp->rx_old].base) | R_OWN, - &lp->rx_ring[lp->rx_old].base); - } - writel(readl(&lp->rx_ring[entry].base) | R_OWN, &lp->rx_ring[entry].base); - } - /* - ** Update entry information - */ - lp->rx_new = (++lp->rx_new) & lp->rxRingMask; - } - - return 0; + printk("%s: Memory squeeze, deferring packet.\n", dev->name); + lp->stats.rx_dropped++; /* Really, deferred. */ + break; + } + } + /* Change buffer ownership for this last frame, back to the adapter */ + for (; lp->rx_old!=entry; lp->rx_old=(++lp->rx_old)&lp->rxRingMask) { + writel(readl(&lp->rx_ring[lp->rx_old].base) | R_OWN, + &lp->rx_ring[lp->rx_old].base); + } + writel(readl(&lp->rx_ring[entry].base) | R_OWN, &lp->rx_ring[entry].base); + } + + /* + ** Update entry information + */ + lp->rx_new = (++lp->rx_new) & lp->rxRingMask; + } + + return 0; } /* - ** Buffer sent - check for buffer errors. - */ -static int depca_tx(struct device *dev) -{ - struct depca_private *lp = (struct depca_private *) dev->priv; - int entry; - s32 status; - u_long ioaddr = dev->base_addr; - - for (entry = lp->tx_old; entry != lp->tx_new; entry = lp->tx_old) { - status = readl(&lp->tx_ring[entry].base) >> 16; - - if (status < 0) { /* Packet not yet sent! */ - break; - } else if (status & T_ERR) { /* An error occurred. */ - status = readl(&lp->tx_ring[entry].misc); - lp->stats.tx_errors++; - if (status & TMD3_RTRY) - lp->stats.tx_aborted_errors++; - if (status & TMD3_LCAR) - lp->stats.tx_carrier_errors++; - if (status & TMD3_LCOL) - lp->stats.tx_window_errors++; - if (status & TMD3_UFLO) - lp->stats.tx_fifo_errors++; - if (status & (TMD3_BUFF | TMD3_UFLO)) { - /* Trigger an immediate send demand. */ - outw(CSR0, DEPCA_ADDR); - outw(INEA | TDMD, DEPCA_DATA); - } - } else if (status & (T_MORE | T_ONE)) { - lp->stats.collisions++; - } else { - lp->stats.tx_packets++; - } - - /* Update all the pointers */ - lp->tx_old = (++lp->tx_old) & lp->txRingMask; - } - - return 0; -} - -static int depca_close(struct device *dev) -{ - struct depca_private *lp = (struct depca_private *) dev->priv; - s16 nicsr; - u_long ioaddr = dev->base_addr; - - dev->start = 0; - dev->tbusy = 1; - +** Buffer sent - check for buffer errors. +*/ +static int +depca_tx(struct device *dev) +{ + struct depca_private *lp = (struct depca_private *)dev->priv; + int entry; + s32 status; + u_long ioaddr = dev->base_addr; + + for (entry = lp->tx_old; entry != lp->tx_new; entry = lp->tx_old) { + status = readl(&lp->tx_ring[entry].base) >> 16 ; + + if (status < 0) { /* Packet not yet sent! */ + break; + } else if (status & T_ERR) { /* An error occurred. */ + status = readl(&lp->tx_ring[entry].misc); + lp->stats.tx_errors++; + if (status & TMD3_RTRY) lp->stats.tx_aborted_errors++; + if (status & TMD3_LCAR) lp->stats.tx_carrier_errors++; + if (status & TMD3_LCOL) lp->stats.tx_window_errors++; + if (status & TMD3_UFLO) lp->stats.tx_fifo_errors++; + if (status & (TMD3_BUFF | TMD3_UFLO)) { + /* Trigger an immediate send demand. */ outw(CSR0, DEPCA_ADDR); + outw(INEA | TDMD, DEPCA_DATA); + } + } else if (status & (T_MORE | T_ONE)) { + lp->stats.collisions++; + } else { + lp->stats.tx_packets++; + } + + /* Update all the pointers */ + lp->tx_old = (++lp->tx_old) & lp->txRingMask; + } + + return 0; +} + +static int +depca_close(struct device *dev) +{ + struct depca_private *lp = (struct depca_private *)dev->priv; + s16 nicsr; + u_long ioaddr = dev->base_addr; + + dev->start = 0; + dev->tbusy = 1; + + outw(CSR0, DEPCA_ADDR); + + if (depca_debug > 1) { + printk("%s: Shutting down ethercard, status was %2.2x.\n", + dev->name, inw(DEPCA_DATA)); + } + + /* + ** We stop the DEPCA here -- it occasionally polls + ** memory if we don't. + */ + outw(STOP, DEPCA_DATA); + + /* + ** Give back the ROM in case the user wants to go to DOS + */ + if (lp->adapter != DEPCA) { + nicsr = inb(DEPCA_NICSR); + nicsr &= ~SHE; + outb(nicsr, DEPCA_NICSR); + } + + /* + ** Free the associated irq + */ + free_irq(dev->irq, dev); - if (depca_debug > 1) { - printk("%s: Shutting down ethercard, status was %2.2x.\n", - dev->name, inw(DEPCA_DATA)); - } - /* - ** We stop the DEPCA here -- it occasionally polls - ** memory if we don't. - */ - outw(STOP, DEPCA_DATA); + MOD_DEC_USE_COUNT; - /* - ** Give back the ROM in case the user wants to go to DOS - */ - if (lp->adapter != DEPCA) { - nicsr = inb(DEPCA_NICSR); - nicsr &= ~SHE; - outb(nicsr, DEPCA_NICSR); - } - /* - ** Free the associated irq - */ - free_irq(dev->irq, dev); - - MOD_DEC_USE_COUNT; - - return 0; + return 0; } static void LoadCSRs(struct device *dev) { - struct depca_private *lp = (struct depca_private *) dev->priv; - u_long ioaddr = dev->base_addr; + struct depca_private *lp = (struct depca_private *)dev->priv; + u_long ioaddr = dev->base_addr; - outw(CSR1, DEPCA_ADDR); /* initialisation block address LSW */ - outw((u16) (lp->sh_mem & LA_MASK), DEPCA_DATA); - outw(CSR2, DEPCA_ADDR); /* initialisation block address MSW */ - outw((u16) ((lp->sh_mem & LA_MASK) >> 16), DEPCA_DATA); - outw(CSR3, DEPCA_ADDR); /* ALE control */ - outw(ACON, DEPCA_DATA); + outw(CSR1, DEPCA_ADDR); /* initialisation block address LSW */ + outw((u16)(lp->sh_mem & LA_MASK), DEPCA_DATA); + outw(CSR2, DEPCA_ADDR); /* initialisation block address MSW */ + outw((u16)((lp->sh_mem & LA_MASK) >> 16), DEPCA_DATA); + outw(CSR3, DEPCA_ADDR); /* ALE control */ + outw(ACON, DEPCA_DATA); - outw(CSR0, DEPCA_ADDR); /* Point back to CSR0 */ + outw(CSR0, DEPCA_ADDR); /* Point back to CSR0 */ - return; + return; } static int InitRestartDepca(struct device *dev) { - struct depca_private *lp = (struct depca_private *) dev->priv; - u_long ioaddr = dev->base_addr; - int i, status = 0; - - /* Copy the shadow init_block to shared memory */ - memcpy_toio((char *) lp->sh_mem, &lp->init_block, sizeof(struct depca_init)); - - outw(CSR0, DEPCA_ADDR); /* point back to CSR0 */ - outw(INIT, DEPCA_DATA); /* initialize DEPCA */ - - /* wait for lance to complete initialisation */ - for (i = 0; (i < 100) && !(inw(DEPCA_DATA) & IDON); i++); - - if (i != 100) { - /* clear IDON by writing a "1", enable interrupts and start lance */ - outw(IDON | INEA | STRT, DEPCA_DATA); - if (depca_debug > 2) { - printk("%s: DEPCA open after %d ticks, init block 0x%08lx csr0 %4.4x.\n", - dev->name, i, lp->sh_mem, inw(DEPCA_DATA)); - } - } else { - printk("%s: DEPCA unopen after %d ticks, init block 0x%08lx csr0 %4.4x.\n", - dev->name, i, lp->sh_mem, inw(DEPCA_DATA)); - status = -1; - } + struct depca_private *lp = (struct depca_private *)dev->priv; + u_long ioaddr = dev->base_addr; + int i, status=0; + + /* Copy the shadow init_block to shared memory */ + memcpy_toio((char *)lp->sh_mem, &lp->init_block, sizeof(struct depca_init)); + + outw(CSR0, DEPCA_ADDR); /* point back to CSR0 */ + outw(INIT, DEPCA_DATA); /* initialize DEPCA */ + + /* wait for lance to complete initialisation */ + for (i=0;(i<100) && !(inw(DEPCA_DATA) & IDON); i++); + + if (i!=100) { + /* clear IDON by writing a "1", enable interrupts and start lance */ + outw(IDON | INEA | STRT, DEPCA_DATA); + if (depca_debug > 2) { + printk("%s: DEPCA open after %d ticks, init block 0x%08lx csr0 %4.4x.\n", + dev->name, i, lp->sh_mem, inw(DEPCA_DATA)); + } + } else { + printk("%s: DEPCA unopen after %d ticks, init block 0x%08lx csr0 %4.4x.\n", + dev->name, i, lp->sh_mem, inw(DEPCA_DATA)); + status = -1; + } - return status; + return status; } static struct net_device_stats * - depca_get_stats(struct device *dev) +depca_get_stats(struct device *dev) { - struct depca_private *lp = (struct depca_private *) dev->priv; + struct depca_private *lp = (struct depca_private *)dev->priv; - /* Null body since there is no framing error counter */ + /* Null body since there is no framing error counter */ - return &lp->stats; + return &lp->stats; } /* - ** Set or clear the multicast filter for this adaptor. - */ -static void set_multicast_list(struct device *dev) +** Set or clear the multicast filter for this adaptor. +*/ +static void +set_multicast_list(struct device *dev) { - struct depca_private *lp = (struct depca_private *) dev->priv; - u_long ioaddr = dev->base_addr; - - while (dev->tbusy); /* Stop ring access */ - set_bit(0, (void *) &dev->tbusy); - while (lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ + struct depca_private *lp = (struct depca_private *)dev->priv; + u_long ioaddr = dev->base_addr; + + if (dev) { + while(dev->tbusy) barrier(); /* Stop ring access */ + set_bit(0, (void*)&dev->tbusy); + while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ - STOP_DEPCA; /* Temporarily stop the depca. */ - depca_init_ring(dev); /* Initialize the descriptor rings */ + STOP_DEPCA; /* Temporarily stop the depca. */ + depca_init_ring(dev); /* Initialize the descriptor rings */ - if (dev->flags & IFF_PROMISC) { /* Set promiscuous mode */ - lp->init_block.mode |= PROM; - } else { - SetMulticastFilter(dev); - lp->init_block.mode &= ~PROM; /* Unset promiscuous mode */ - } + if (dev->flags & IFF_PROMISC) { /* Set promiscuous mode */ + lp->init_block.mode |= PROM; + } else { + SetMulticastFilter(dev); + lp->init_block.mode &= ~PROM; /* Unset promiscuous mode */ + } - LoadCSRs(dev); /* Reload CSR3 */ - InitRestartDepca(dev); /* Resume normal operation. */ - dev->tbusy = 0; /* Unlock the TX ring */ + LoadCSRs(dev); /* Reload CSR3 */ + InitRestartDepca(dev); /* Resume normal operation. */ + dev->tbusy = 0; /* Unlock the TX ring */ + } } /* - ** Calculate the hash code and update the logical address filter - ** from a list of ethernet multicast addresses. - ** Big endian crc one liner is mine, all mine, ha ha ha ha! - ** LANCE calculates its hash codes big endian. - */ +** Calculate the hash code and update the logical address filter +** from a list of ethernet multicast addresses. +** Big endian crc one liner is mine, all mine, ha ha ha ha! +** LANCE calculates its hash codes big endian. +*/ static void SetMulticastFilter(struct device *dev) { - struct depca_private *lp = (struct depca_private *) dev->priv; - struct dev_mc_list *dmi = dev->mc_list; - char *addrs; - int i, j, bit, byte; - u16 hashcode; - s32 crc, poly = CRC_POLYNOMIAL_BE; - - if (dev->flags & IFF_ALLMULTI) { /* Set all multicast bits */ - for (i = 0; i < (HASH_TABLE_LEN >> 3); i++) { - lp->init_block.mcast_table[i] = (char) 0xff; - } - } else { - for (i = 0; i < (HASH_TABLE_LEN >> 3); i++) { /* Clear the multicast table */ - lp->init_block.mcast_table[i] = 0; - } - /* Add multicast addresses */ - for (i = 0; i < dev->mc_count; i++) { /* for each address in the list */ - addrs = dmi->dmi_addr; - dmi = dmi->next; - if ((*addrs & 0x01) == 1) { /* multicast address? */ - crc = 0xffffffff; /* init CRC for each address */ - for (byte = 0; byte < ETH_ALEN; byte++) { /* for each address byte */ - /* process each address bit */ - for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { - crc = (crc << 1) ^ ((((crc < 0 ? 1 : 0) ^ bit) & 0x01) ? poly : 0); - } - } - hashcode = (crc & 1); /* hashcode is 6 LSb of CRC ... */ - for (j = 0; j < 5; j++) { /* ... in reverse order. */ - hashcode = (hashcode << 1) | ((crc >>= 1) & 1); - } - - - byte = hashcode >> 3; /* bit[3-5] -> byte in filter */ - bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */ - lp->init_block.mcast_table[byte] |= bit; - } - } - } - - return; -} - -/* - ** ISA bus I/O device probe - */ -__initfunc(static void isa_probe(struct device *dev, u_long ioaddr)) -{ - int i = num_depcas, maxSlots; - s32 ports[] = DEPCA_IO_PORTS; - - if (!ioaddr && autoprobed) - return; /* Been here before ! */ - if (ioaddr > 0x400) - return; /* EISA Address */ - if (i >= MAX_NUM_DEPCAS) - return; /* Too many ISA adapters */ - - if (ioaddr == 0) { /* Autoprobing */ - maxSlots = MAX_NUM_DEPCAS; - } else { /* Probe a specific location */ - ports[i] = ioaddr; - maxSlots = i + 1; - } - - for (; (i < maxSlots) && (dev != NULL) && ports[i]; i++) { - if (DevicePresent(ports[i]) == 0) { - if (check_region(ports[i], DEPCA_TOTAL_SIZE) == 0) { - if ((dev = alloc_device(dev, ports[i])) != NULL) { - if (depca_hw_init(dev, ports[i]) == 0) { - num_depcas++; - } - num_eth++; - } - } else if (autoprobed) { - printk("%s: region already allocated at 0x%04x.\n", dev->name, ports[i]); - } - } - } - - return; -} + struct depca_private *lp = (struct depca_private *)dev->priv; + struct dev_mc_list *dmi=dev->mc_list; + char *addrs; + int i, j, bit, byte; + u16 hashcode; + s32 crc, poly = CRC_POLYNOMIAL_BE; + + if (dev->flags & IFF_ALLMULTI) { /* Set all multicast bits */ + for (i=0; i<(HASH_TABLE_LEN>>3); i++) { + lp->init_block.mcast_table[i] = (char)0xff; + } + } else { + for (i=0; i<(HASH_TABLE_LEN>>3); i++){ /* Clear the multicast table */ + lp->init_block.mcast_table[i]=0; + } + /* Add multicast addresses */ + for (i=0;imc_count;i++) { /* for each address in the list */ + addrs=dmi->dmi_addr; + dmi=dmi->next; + if ((*addrs & 0x01) == 1) { /* multicast address? */ + crc = 0xffffffff; /* init CRC for each address */ + for (byte=0;byte>=1) { + crc = (crc << 1) ^ ((((crc<0?1:0) ^ bit) & 0x01) ? poly : 0); + } + } + hashcode = (crc & 1); /* hashcode is 6 LSb of CRC ... */ + for (j=0;j<5;j++) { /* ... in reverse order. */ + hashcode = (hashcode << 1) | ((crc>>=1) & 1); + } + + + byte = hashcode >> 3; /* bit[3-5] -> byte in filter */ + bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */ + lp->init_block.mcast_table[byte] |= bit; + } + } + } + + return; +} + +#ifdef CONFIG_MCA +/* +** Microchannel bus I/O device probe +*/ +__initfunc(static void +mca_probe(struct device *dev, u_long ioaddr)) +{ + unsigned char pos[2]; + unsigned char where; + unsigned long iobase; + int irq; + int slot = 0; + + /* + ** See if we've been here before. + */ + if ((!ioaddr && autoprobed) || (ioaddr && !loading_module)) return; -/* - ** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually - ** the motherboard. Upto 15 EISA devices are supported. - */ -__initfunc(static void eisa_probe(struct device *dev, u_long ioaddr)) -{ - int i, maxSlots; - u_long iobase; - char name[DEPCA_STRLEN]; - - if (!ioaddr && autoprobed) - return; /* Been here before ! */ - if ((ioaddr < 0x400) && (ioaddr > 0)) - return; /* ISA Address */ - - if (ioaddr == 0) { /* Autoprobing */ - iobase = EISA_SLOT_INC; /* Get the first slot address */ - i = 1; - maxSlots = MAX_EISA_SLOTS; - } else { /* Probe a specific location */ - iobase = ioaddr; - i = (ioaddr >> 12); - maxSlots = i + 1; - } - if ((iobase & 0x0fff) == 0) - iobase += DEPCA_EISA_IO_PORTS; - - for (; (i < maxSlots) && (dev != NULL); i++, iobase += EISA_SLOT_INC) { - if (EISA_signature(name, EISA_ID)) { - if (DevicePresent(iobase) == 0) { - if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) { - if ((dev = alloc_device(dev, iobase)) != NULL) { - if (depca_hw_init(dev, iobase) == 0) { - num_depcas++; - } - num_eth++; - } - } else if (autoprobed) { - printk("%s: region already allocated at 0x%04lx.\n", dev->name, iobase); - } - } - } + if (MCA_bus) { + /* + ** Search for the adapter. If an address has been given, search + ** specifically for the card at that address. Otherwise find the + ** first card in the system. + */ + while ((dev!=NULL) && + ((slot=mca_find_adapter(DE212_ID, slot)) != MCA_NOTFOUND)) { + pos[0] = mca_read_stored_pos(slot, 2); + pos[1] = mca_read_stored_pos(slot, 3); + + /* + ** IO of card is handled by bits 1 and 2 of pos0. + ** + ** bit2 bit1 IO + ** 0 0 0x2c00 + ** 0 1 0x2c10 + ** 1 0 0x2c20 + ** 1 1 0x2c30 + */ + where = (pos[0] & 6) >> 1; + iobase = 0x2c00 + (0x10 * where); + + if ((ioaddr) && (ioaddr != iobase)) { + /* + ** Card was found, but not at the right IO location. Continue + ** scanning from the next MCA slot up for another card. + */ + slot++; + continue; + } + + /* + ** Found the adapter we were looking for. Now start setting it up. + ** + ** First work on decoding the IRQ. It's stored in the lower 4 bits + ** of pos1. Bits are as follows (from the ADF file): + ** + ** Bits + ** 3 2 1 0 IRQ + ** -------------------- + ** 0 0 1 0 5 + ** 0 0 0 1 9 + ** 0 1 0 0 10 + ** 1 0 0 0 11 + **/ + where = pos[1] & 0x0f; + switch(where) { + case 1: + irq = 9; + break; + case 2: + irq = 5; + break; + case 4: + irq = 10; + break; + case 8: + irq = 11; + break; + default: + printk("%s: mca_probe IRQ error. You should never get here (%d).\n", dev->name, where); + return; + } + + /* + ** Shared memory address of adapter is stored in bits 3-5 of pos0. + ** They are mapped as follows: + ** + ** Bit + ** 5 4 3 Memory Addresses + ** 0 0 0 C0000-CFFFF (64K) + ** 1 0 0 C8000-CFFFF (32K) + ** 0 0 1 D0000-DFFFF (64K) + ** 1 0 1 D8000-DFFFF (32K) + ** 0 1 0 E0000-EFFFF (64K) + ** 1 1 0 E8000-EFFFF (32K) + */ + where = (pos[0] & 0x18) >> 3; + mem = 0xc0000 + (where * 0x10000); + if (pos[0] & 0x20) { + mem += 0x8000; + } + + /* + ** Get everything allocated and initialized... (almost just + ** like the ISA and EISA probes) + */ + if (DevicePresent(iobase) != 0) { + /* + ** If the MCA configuration says the card should be here, + ** it really should be here. + */ + printk(KERN_ERR "%s: MCA reports card at 0x%lx but it is not +responding.\n", dev->name, iobase); + } + + if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) { + if ((dev = alloc_device(dev, iobase)) != NULL) { + dev->irq = irq; + if (depca_hw_init(dev, iobase, slot) == 0) { + /* + ** Adapter initialized correctly: Name it in + ** /proc/mca. + */ + mca_set_adapter_name(slot, "DE210/212 Ethernet Adapter"); + mca_mark_as_used(slot); + num_depcas++; + } + num_eth++; + } + } else if (autoprobed) { + printk(KERN_WARNING "%s: region already allocated at 0x%04lx.\n", dev->name, iobase); + } + + /* + ** If this is a probe by a module, return after setting up the + ** given card. + */ + if (ioaddr) return; + + /* + ** Set up to check the next slot and loop. + */ + slot++; } + } - return; + return; } +#endif /* - ** Search the entire 'eth' device list for a fixed probe. If a match isn't - ** found then check for an autoprobe or unused device location. If they - ** are not available then insert a new device structure at the end of - ** the current list. - */ +** ISA bus I/O device probe +*/ +__initfunc(static void +isa_probe(struct device *dev, u_long ioaddr)) +{ + int i = num_depcas, maxSlots; + s32 ports[] = DEPCA_IO_PORTS; + + if (!ioaddr && autoprobed) return ; /* Been here before ! */ + if (ioaddr > 0x400) return; /* EISA Address */ + if (i >= MAX_NUM_DEPCAS) return; /* Too many ISA adapters */ + + if (ioaddr == 0) { /* Autoprobing */ + maxSlots = MAX_NUM_DEPCAS; + } else { /* Probe a specific location */ + ports[i] = ioaddr; + maxSlots = i + 1; + } + + for (; (iname, ports[i]); + } + } + + return; +} + +/* +** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually +** the motherboard. Upto 15 EISA devices are supported. +*/ +__initfunc(static void +eisa_probe(struct device *dev, u_long ioaddr)) +{ + int i, maxSlots; + u_long iobase; + char name[DEPCA_STRLEN]; + + if (!ioaddr && autoprobed) return ; /* Been here before ! */ + if ((ioaddr < 0x400) && (ioaddr > 0)) return; /* ISA Address */ + + if (ioaddr == 0) { /* Autoprobing */ + iobase = EISA_SLOT_INC; /* Get the first slot address */ + i = 1; + maxSlots = MAX_EISA_SLOTS; + } else { /* Probe a specific location */ + iobase = ioaddr; + i = (ioaddr >> 12); + maxSlots = i + 1; + } + if ((iobase & 0x0fff) == 0) iobase += DEPCA_EISA_IO_PORTS; + + for (; (iname, iobase); + } + } + + return; +} + +/* +** Search the entire 'eth' device list for a fixed probe. If a match isn't +** found then check for an autoprobe or unused device location. If they +** are not available then insert a new device structure at the end of +** the current list. +*/ __initfunc(static struct device * - alloc_device(struct device *dev, u_long iobase)) +alloc_device(struct device *dev, u_long iobase)) { - struct device *adev = NULL; - int fixed = 0, new_dev = 0; + struct device *adev = NULL; + int fixed = 0, new_dev = 0; + num_eth = depca_dev_index(dev->name); + if (loading_module) return dev; + + while (1) { + if (((dev->base_addr == DEPCA_NDA) || (dev->base_addr==0)) && !adev) { + adev=dev; + } else if ((dev->priv == NULL) && (dev->base_addr==iobase)) { + fixed = 1; + } else { + if (dev->next == NULL) { + new_dev = 1; + } else if (strncmp(dev->next->name, "eth", 3) != 0) { + new_dev = 1; + } + } + if ((dev->next == NULL) || new_dev || fixed) break; + dev = dev->next; + num_eth++; + } + if (adev && !fixed) { + dev = adev; num_eth = depca_dev_index(dev->name); - if (loading_module) - return dev; + new_dev = 0; + } - while (1) { - if (((dev->base_addr == DEPCA_NDA) || (dev->base_addr == 0)) && !adev) { - adev = dev; - } else if ((dev->priv == NULL) && (dev->base_addr == iobase)) { - fixed = 1; - } else { - if (dev->next == NULL) { - new_dev = 1; - } else if (strncmp(dev->next->name, "eth", 3) != 0) { - new_dev = 1; - } - } - if ((dev->next == NULL) || new_dev || fixed) - break; - dev = dev->next; - num_eth++; - } - if (adev && !fixed) { - dev = adev; - num_eth = depca_dev_index(dev->name); - new_dev = 0; - } - if (((dev->next == NULL) && - ((dev->base_addr != DEPCA_NDA) && (dev->base_addr != 0)) && !fixed) || - new_dev) { - num_eth++; /* New device */ - dev = insert_device(dev, iobase, depca_probe); - } - return dev; + if (((dev->next == NULL) && + ((dev->base_addr != DEPCA_NDA) && (dev->base_addr != 0)) && !fixed) || + new_dev) { + num_eth++; /* New device */ + dev = insert_device(dev, iobase, depca_probe); + } + + return dev; } /* - ** If at end of eth device list and can't use current entry, malloc - ** one up. If memory could not be allocated, print an error message. - */ +** If at end of eth device list and can't use current entry, malloc +** one up. If memory could not be allocated, print an error message. +*/ __initfunc(static struct device * - insert_device(struct device *dev, u_long iobase, int (*init) (struct device *))) +insert_device(struct device *dev, u_long iobase, int (*init)(struct device *))) { - struct device *new; + struct device *new; - new = (struct device *) kmalloc(sizeof(struct device) + 8, GFP_KERNEL); - if (new == NULL) { - printk("eth%d: Device not initialised, insufficient memory\n", num_eth); - return NULL; + new = (struct device *)kmalloc(sizeof(struct device)+8, GFP_KERNEL); + if (new == NULL) { + printk("eth%d: Device not initialised, insufficient memory\n",num_eth); + return NULL; + } else { + new->next = dev->next; + dev->next = new; + dev = dev->next; /* point to the new device */ + dev->name = (char *)(dev + 1); + if (num_eth > 9999) { + sprintf(dev->name,"eth????");/* New device name */ } else { - new->next = dev->next; - dev->next = new; - dev = dev->next; /* point to the new device */ - dev->name = (char *) (dev + 1); - if (num_eth > 9999) { - sprintf(dev->name, "eth????"); /* New device name */ - } else { - sprintf(dev->name, "eth%d", num_eth); /* New device name */ - } - dev->base_addr = iobase; /* assign the io address */ - dev->init = init; /* initialisation routine */ + sprintf(dev->name,"eth%d", num_eth);/* New device name */ } + dev->base_addr = iobase; /* assign the io address */ + dev->init = init; /* initialisation routine */ + } - return dev; + return dev; } __initfunc(static int - depca_dev_index(char *s)) +depca_dev_index(char *s)) { - int i = 0, j = 0; + int i=0, j=0; - for (; *s; s++) { - if (isdigit(*s)) { - j = 1; - i = (i * 10) + (*s - '0'); - } else if (j) - break; - } - - return i; -} - -/* - ** Look for a particular board name in the on-board Remote Diagnostics - ** and Boot (readb) ROM. This will also give us a clue to the network RAM - ** base address. - */ -__initfunc(static void DepcaSignature(char *name, u_long paddr)) + for (;*s; s++) { + if (isdigit(*s)) { + j=1; + i = (i * 10) + (*s - '0'); + } else if (j) break; + } + + return i; +} + +/* +** Look for a particular board name in the on-board Remote Diagnostics +** and Boot (readb) ROM. This will also give us a clue to the network RAM +** base address. +*/ +__initfunc(static void +DepcaSignature(char *name, u_long paddr)) +{ + u_int i,j,k; + const char *signatures[] = DEPCA_SIGNATURE; + char tmpstr[16]; + + /* Copy the first 16 bytes of ROM */ + for (i=0;i<16;i++) { + tmpstr[i] = readb(paddr+0xc000+i); + } + + /* Check if PROM contains a valid string */ + for (i=0;*signatures[i]!='\0';i++) { + for (j=0,k=0;j<16 && kbase_addr; - int i, k, tmp, status = 0; - u_short j, x, chksum; + u_long ioaddr = dev->base_addr; + int i, k, tmp, status = 0; + u_short j, x, chksum; - x = (((adapter == de100) || (adapter == de101)) ? 1 : 0); + x = (((adapter == de100) || (adapter == de101)) ? 1 : 0); - for (i = 0, k = 0, j = 0; j < 3; j++) { - k <<= 1; - if (k > 0xffff) - k -= 0xffff; + for (i=0,k=0,j=0;j<3;j++) { + k <<= 1 ; + if (k > 0xffff) k-=0xffff; - k += (u_char) (tmp = inb(DEPCA_PROM + x)); - dev->dev_addr[i++] = (u_char) tmp; - k += (u_short) ((tmp = inb(DEPCA_PROM + x)) << 8); - dev->dev_addr[i++] = (u_char) tmp; + k += (u_char) (tmp = inb(DEPCA_PROM + x)); + dev->dev_addr[i++] = (u_char) tmp; + k += (u_short) ((tmp = inb(DEPCA_PROM + x)) << 8); + dev->dev_addr[i++] = (u_char) tmp; - if (k > 0xffff) - k -= 0xffff; - } - if (k == 0xffff) - k = 0; + if (k > 0xffff) k-=0xffff; + } + if (k == 0xffff) k=0; - chksum = (u_char) inb(DEPCA_PROM + x); - chksum |= (u_short) (inb(DEPCA_PROM + x) << 8); - if (k != chksum) - status = -1; + chksum = (u_char) inb(DEPCA_PROM + x); + chksum |= (u_short) (inb(DEPCA_PROM + x) << 8); + if (k != chksum) status = -1; - return status; + return status; } /* - ** Load a packet into the shared memory - */ +** Load a packet into the shared memory +*/ static int load_packet(struct device *dev, struct sk_buff *skb) { - struct depca_private *lp = (struct depca_private *) dev->priv; - int i, entry, end, len, status = 0; + struct depca_private *lp = (struct depca_private *)dev->priv; + int i, entry, end, len, status = 0; - entry = lp->tx_new; /* Ring around buffer number. */ - end = (entry + (skb->len - 1) / TX_BUFF_SZ) & lp->txRingMask; - if (!(readl(&lp->tx_ring[end].base) & T_OWN)) { /* Enough room? */ - /* - ** Caution: the write order is important here... don't set up the - ** ownership rights until all the other information is in place. - */ - if (end < entry) { /* wrapped buffer */ - len = (lp->txRingMask - entry + 1) * TX_BUFF_SZ; - memcpy_toio(lp->tx_memcpy[entry], skb->data, len); - memcpy_toio(lp->tx_memcpy[0], skb->data + len, skb->len - len); - } else { /* linear buffer */ - memcpy_toio(lp->tx_memcpy[entry], skb->data, skb->len); - } - - /* set up the buffer descriptors */ - len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len; - for (i = entry; i != end; i = (++i) & lp->txRingMask) { - /* clean out flags */ - writel(readl(&lp->tx_ring[i].base) & ~T_FLAGS, &lp->tx_ring[i].base); - writew(0x0000, &lp->tx_ring[i].misc); /* clears other error flags */ - writew(-TX_BUFF_SZ, &lp->tx_ring[i].length); /* packet length in buffer */ - len -= TX_BUFF_SZ; - } - /* clean out flags */ - writel(readl(&lp->tx_ring[end].base) & ~T_FLAGS, &lp->tx_ring[end].base); - writew(0x0000, &lp->tx_ring[end].misc); /* clears other error flags */ - writew(-len, &lp->tx_ring[end].length); /* packet length in last buff */ - - /* start of packet */ - writel(readl(&lp->tx_ring[entry].base) | T_STP, &lp->tx_ring[entry].base); - /* end of packet */ - writel(readl(&lp->tx_ring[end].base) | T_ENP, &lp->tx_ring[end].base); - - for (i = end; i != entry; --i) { - /* ownership of packet */ - writel(readl(&lp->tx_ring[i].base) | T_OWN, &lp->tx_ring[i].base); - if (i == 0) - i = lp->txRingMask + 1; - } - writel(readl(&lp->tx_ring[entry].base) | T_OWN, &lp->tx_ring[entry].base); - - lp->tx_new = (++end) & lp->txRingMask; /* update current pointers */ - } else { - status = -1; - } + entry = lp->tx_new; /* Ring around buffer number. */ + end = (entry + (skb->len - 1) / TX_BUFF_SZ) & lp->txRingMask; + if (!(readl(&lp->tx_ring[end].base) & T_OWN)) {/* Enough room? */ + /* + ** Caution: the write order is important here... don't set up the + ** ownership rights until all the other information is in place. + */ + if (end < entry) { /* wrapped buffer */ + len = (lp->txRingMask - entry + 1) * TX_BUFF_SZ; + memcpy_toio(lp->tx_memcpy[entry], skb->data, len); + memcpy_toio(lp->tx_memcpy[0], skb->data + len, skb->len - len); + } else { /* linear buffer */ + memcpy_toio(lp->tx_memcpy[entry], skb->data, skb->len); + } + + /* set up the buffer descriptors */ + len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len; + for (i = entry; i != end; i = (++i) & lp->txRingMask) { + /* clean out flags */ + writel(readl(&lp->tx_ring[i].base) & ~T_FLAGS, &lp->tx_ring[i].base); + writew(0x0000, &lp->tx_ring[i].misc); /* clears other error flags */ + writew(-TX_BUFF_SZ, &lp->tx_ring[i].length);/* packet length in buffer */ + len -= TX_BUFF_SZ; + } + /* clean out flags */ + writel(readl(&lp->tx_ring[end].base) & ~T_FLAGS, &lp->tx_ring[end].base); + writew(0x0000, &lp->tx_ring[end].misc); /* clears other error flags */ + writew(-len, &lp->tx_ring[end].length); /* packet length in last buff */ + + /* start of packet */ + writel(readl(&lp->tx_ring[entry].base) | T_STP, &lp->tx_ring[entry].base); + /* end of packet */ + writel(readl(&lp->tx_ring[end].base) | T_ENP, &lp->tx_ring[end].base); + + for (i=end; i!=entry; --i) { + /* ownership of packet */ + writel(readl(&lp->tx_ring[i].base) | T_OWN, &lp->tx_ring[i].base); + if (i == 0) i=lp->txRingMask+1; + } + writel(readl(&lp->tx_ring[entry].base) | T_OWN, &lp->tx_ring[entry].base); + + lp->tx_new = (++end) & lp->txRingMask; /* update current pointers */ + } else { + status = -1; + } - return status; + return status; } /* - ** Look for a particular board name in the EISA configuration space - */ -__initfunc(static int EISA_signature(char *name, s32 eisa_id)) -{ - u_int i; - const char *signatures[] = DEPCA_SIGNATURE; - char ManCode[DEPCA_STRLEN]; - union { - s32 ID; - char Id[4]; - } Eisa; - int status = 0; - - *name = '\0'; - Eisa.ID = inl(eisa_id); - - ManCode[0] = (((Eisa.Id[0] >> 2) & 0x1f) + 0x40); - ManCode[1] = (((Eisa.Id[1] & 0xe0) >> 5) + ((Eisa.Id[0] & 0x03) << 3) + 0x40); - ManCode[2] = (((Eisa.Id[2] >> 4) & 0x0f) + 0x30); - ManCode[3] = ((Eisa.Id[2] & 0x0f) + 0x30); - ManCode[4] = (((Eisa.Id[3] >> 4) & 0x0f) + 0x30); - ManCode[5] = '\0'; - - for (i = 0; (*signatures[i] != '\0') && (*name == '\0'); i++) { - if (strstr(ManCode, signatures[i]) != NULL) { - strcpy(name, ManCode); - status = 1; - } - } +** Look for a particular board name in the EISA configuration space +*/ +__initfunc(static int +EISA_signature(char *name, s32 eisa_id)) +{ + u_int i; + const char *signatures[] = DEPCA_SIGNATURE; + char ManCode[DEPCA_STRLEN]; + union { + s32 ID; + char Id[4]; + } Eisa; + int status = 0; + + *name = '\0'; + Eisa.ID = inl(eisa_id); + + ManCode[0]=(((Eisa.Id[0]>>2)&0x1f)+0x40); + ManCode[1]=(((Eisa.Id[1]&0xe0)>>5)+((Eisa.Id[0]&0x03)<<3)+0x40); + ManCode[2]=(((Eisa.Id[2]>>4)&0x0f)+0x30); + ManCode[3]=(( Eisa.Id[2]&0x0f)+0x30); + ManCode[4]=(((Eisa.Id[3]>>4)&0x0f)+0x30); + ManCode[5]='\0'; + + for (i=0;(*signatures[i] != '\0') && (*name == '\0');i++) { + if (strstr(ManCode, signatures[i]) != NULL) { + strcpy(name,ManCode); + status = 1; + } + } - return status; + return status; } static void depca_dbg_open(struct device *dev) { - struct depca_private *lp = (struct depca_private *) dev->priv; - u_long ioaddr = dev->base_addr; - struct depca_init *p = (struct depca_init *) lp->sh_mem; - int i; - - if (depca_debug > 1) { - /* Copy the shadow init_block to shared memory */ - memcpy_toio((char *) lp->sh_mem, &lp->init_block, sizeof(struct depca_init)); - - printk("%s: depca open with irq %d\n", dev->name, dev->irq); - printk("Descriptor head addresses:\n"); - printk("\t0x%lx 0x%lx\n", (u_long) lp->rx_ring, (u_long) lp->tx_ring); - printk("Descriptor addresses:\nRX: "); - for (i = 0; i < lp->rxRingMask; i++) { - if (i < 3) { - printk("0x%8.8lx ", (long) &lp->rx_ring[i].base); - } - } - printk("...0x%8.8lx\n", (long) &lp->rx_ring[i].base); - printk("TX: "); - for (i = 0; i < lp->txRingMask; i++) { - if (i < 3) { - printk("0x%8.8lx ", (long) &lp->tx_ring[i].base); - } - } - printk("...0x%8.8lx\n", (long) &lp->tx_ring[i].base); - printk("\nDescriptor buffers:\nRX: "); - for (i = 0; i < lp->rxRingMask; i++) { - if (i < 3) { - printk("0x%8.8x ", readl(&lp->rx_ring[i].base)); - } - } - printk("...0x%8.8x\n", readl(&lp->rx_ring[i].base)); - printk("TX: "); - for (i = 0; i < lp->txRingMask; i++) { - if (i < 3) { - printk("0x%8.8x ", readl(&lp->tx_ring[i].base)); - } - } - printk("...0x%8.8x\n", readl(&lp->tx_ring[i].base)); - printk("Initialisation block at 0x%8.8lx\n", lp->sh_mem); - printk("\tmode: 0x%4.4x\n", readw(&p->mode)); - printk("\tphysical address: "); - for (i = 0; i < ETH_ALEN - 1; i++) { - printk("%2.2x:", (u_char) readb(&p->phys_addr[i])); - } - printk("%2.2x\n", (u_char) readb(&p->phys_addr[i])); - printk("\tmulticast hash table: "); - for (i = 0; i < (HASH_TABLE_LEN >> 3) - 1; i++) { - printk("%2.2x:", (u_char) readb(&p->mcast_table[i])); - } - printk("%2.2x\n", (u_char) readb(&p->mcast_table[i])); - printk("\trx_ring at: 0x%8.8x\n", readl(&p->rx_ring)); - printk("\ttx_ring at: 0x%8.8x\n", readl(&p->tx_ring)); - printk("dma_buffs: 0x%8.8lx\n", lp->dma_buffs); - printk("Ring size:\nRX: %d Log2(rxRingMask): 0x%8.8x\n", - (int) lp->rxRingMask + 1, - lp->rx_rlen); - printk("TX: %d Log2(txRingMask): 0x%8.8x\n", - (int) lp->txRingMask + 1, - lp->tx_rlen); - outw(CSR2, DEPCA_ADDR); - printk("CSR2&1: 0x%4.4x", inw(DEPCA_DATA)); - outw(CSR1, DEPCA_ADDR); - printk("%4.4x\n", inw(DEPCA_DATA)); - outw(CSR3, DEPCA_ADDR); - printk("CSR3: 0x%4.4x\n", inw(DEPCA_DATA)); - } - return; -} - -/* - ** Perform IOCTL call functions here. Some are privileged operations and the - ** effective uid is checked in those cases. - ** All MCA IOCTLs will not work here and are for testing purposes only. - */ + struct depca_private *lp = (struct depca_private *)dev->priv; + u_long ioaddr = dev->base_addr; + struct depca_init *p = (struct depca_init *)lp->sh_mem; + int i; + + if (depca_debug > 1){ + /* Copy the shadow init_block to shared memory */ + memcpy_toio((char *)lp->sh_mem,&lp->init_block,sizeof(struct depca_init)); + + printk("%s: depca open with irq %d\n",dev->name,dev->irq); + printk("Descriptor head addresses:\n"); + printk("\t0x%lx 0x%lx\n",(u_long)lp->rx_ring, (u_long)lp->tx_ring); + printk("Descriptor addresses:\nRX: "); + for (i=0;irxRingMask;i++){ + if (i < 3) { + printk("0x%8.8lx ", (long) &lp->rx_ring[i].base); + } + } + printk("...0x%8.8lx\n", (long) &lp->rx_ring[i].base); + printk("TX: "); + for (i=0;itxRingMask;i++){ + if (i < 3) { + printk("0x%8.8lx ", (long) &lp->tx_ring[i].base); + } + } + printk("...0x%8.8lx\n", (long) &lp->tx_ring[i].base); + printk("\nDescriptor buffers:\nRX: "); + for (i=0;irxRingMask;i++){ + if (i < 3) { + printk("0x%8.8x ", readl(&lp->rx_ring[i].base)); + } + } + printk("...0x%8.8x\n", readl(&lp->rx_ring[i].base)); + printk("TX: "); + for (i=0;itxRingMask;i++){ + if (i < 3) { + printk("0x%8.8x ", readl(&lp->tx_ring[i].base)); + } + } + printk("...0x%8.8x\n", readl(&lp->tx_ring[i].base)); + printk("Initialisation block at 0x%8.8lx\n",lp->sh_mem); + printk("\tmode: 0x%4.4x\n",readw(&p->mode)); + printk("\tphysical address: "); + for (i=0;iphys_addr[i])); + } + printk("%2.2x\n",(u_char)readb(&p->phys_addr[i])); + printk("\tmulticast hash table: "); + for (i=0;i<(HASH_TABLE_LEN >> 3)-1;i++){ + printk("%2.2x:",(u_char)readb(&p->mcast_table[i])); + } + printk("%2.2x\n",(u_char)readb(&p->mcast_table[i])); + printk("\trx_ring at: 0x%8.8x\n",readl(&p->rx_ring)); + printk("\ttx_ring at: 0x%8.8x\n",readl(&p->tx_ring)); + printk("dma_buffs: 0x%8.8lx\n",lp->dma_buffs); + printk("Ring size:\nRX: %d Log2(rxRingMask): 0x%8.8x\n", + (int)lp->rxRingMask + 1, + lp->rx_rlen); + printk("TX: %d Log2(txRingMask): 0x%8.8x\n", + (int)lp->txRingMask + 1, + lp->tx_rlen); + outw(CSR2,DEPCA_ADDR); + printk("CSR2&1: 0x%4.4x",inw(DEPCA_DATA)); + outw(CSR1,DEPCA_ADDR); + printk("%4.4x\n",inw(DEPCA_DATA)); + outw(CSR3,DEPCA_ADDR); + printk("CSR3: 0x%4.4x\n",inw(DEPCA_DATA)); + } + + return; +} + +/* +** Perform IOCTL call functions here. Some are privileged operations and the +** effective uid is checked in those cases. +** All multicast IOCTLs will not work here and are for testing purposes only. +*/ static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd) { - struct depca_private *lp = (struct depca_private *) dev->priv; - struct depca_ioctl *ioc = (struct depca_ioctl *) &rq->ifr_data; - int i, status = 0; - u_long ioaddr = dev->base_addr; - union { - u8 addr[(HASH_TABLE_LEN * ETH_ALEN)]; - u16 sval[(HASH_TABLE_LEN * ETH_ALEN) >> 1]; - u32 lval[(HASH_TABLE_LEN * ETH_ALEN) >> 2]; - } tmp; - - switch (ioc->cmd) { - case DEPCA_GET_HWADDR: /* Get the hardware address */ - for (i = 0; i < ETH_ALEN; i++) { - tmp.addr[i] = dev->dev_addr[i]; - } - ioc->len = ETH_ALEN; - if (!(status = verify_area(VERIFY_WRITE, (void *) ioc->data, ioc->len))) { - copy_to_user(ioc->data, tmp.addr, ioc->len); - } - break; - case DEPCA_SET_HWADDR: /* Set the hardware address */ - if (capable(CAP_NET_ADMIN)) { - if (!(status = verify_area(VERIFY_READ, (void *) ioc->data, ETH_ALEN))) { - copy_from_user(tmp.addr, ioc->data, ETH_ALEN); - for (i = 0; i < ETH_ALEN; i++) { - dev->dev_addr[i] = tmp.addr[i]; - } - while (dev->tbusy); /* Stop ring access */ - set_bit(0, (void *) &dev->tbusy); - while (lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ - - STOP_DEPCA; /* Temporarily stop the depca. */ - depca_init_ring(dev); /* Initialize the descriptor rings */ - LoadCSRs(dev); /* Reload CSR3 */ - InitRestartDepca(dev); /* Resume normal operation. */ - dev->tbusy = 0; /* Unlock the TX ring */ - } - } else { - status = -EPERM; - } - - break; - case DEPCA_SET_PROM: /* Set Promiscuous Mode */ - if (capable(CAP_NET_ADMIN)) { - while (dev->tbusy); /* Stop ring access */ - set_bit(0, (void *) &dev->tbusy); - while (lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ - - STOP_DEPCA; /* Temporarily stop the depca. */ - depca_init_ring(dev); /* Initialize the descriptor rings */ - lp->init_block.mode |= PROM; /* Set promiscuous mode */ - - LoadCSRs(dev); /* Reload CSR3 */ - InitRestartDepca(dev); /* Resume normal operation. */ - dev->tbusy = 0; /* Unlock the TX ring */ - } else { - status = -EPERM; - } - - break; - case DEPCA_CLR_PROM: /* Clear Promiscuous Mode */ - if (capable(CAP_NET_ADMIN)) { - while (dev->tbusy); /* Stop ring access */ - set_bit(0, (void *) &dev->tbusy); - while (lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ - - STOP_DEPCA; /* Temporarily stop the depca. */ - depca_init_ring(dev); /* Initialize the descriptor rings */ - lp->init_block.mode &= ~PROM; /* Clear promiscuous mode */ - - LoadCSRs(dev); /* Reload CSR3 */ - InitRestartDepca(dev); /* Resume normal operation. */ - dev->tbusy = 0; /* Unlock the TX ring */ - } else { - status = -EPERM; - } - - break; - case DEPCA_SAY_BOO: /* Say "Boo!" to the kernel log file */ - printk("%s: Boo!\n", dev->name); + struct depca_private *lp = (struct depca_private *)dev->priv; + struct depca_ioctl *ioc = (struct depca_ioctl *) &rq->ifr_data; + int i, status = 0; + u_long ioaddr = dev->base_addr; + union { + u8 addr[(HASH_TABLE_LEN * ETH_ALEN)]; + u16 sval[(HASH_TABLE_LEN * ETH_ALEN) >> 1]; + u32 lval[(HASH_TABLE_LEN * ETH_ALEN) >> 2]; + } tmp; + + switch(ioc->cmd) { + case DEPCA_GET_HWADDR: /* Get the hardware address */ + for (i=0; idev_addr[i]; + } + ioc->len = ETH_ALEN; + if (verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len)) return -EFAULT; + copy_to_user(ioc->data, tmp.addr, ioc->len); + break; + + case DEPCA_SET_HWADDR: /* Set the hardware address */ + if (!capable(CAP_NET_ADMIN)) return -EPERM; + if (verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN)) return -EFAULT; + copy_from_user(tmp.addr,ioc->data,ETH_ALEN); + for (i=0; idev_addr[i] = tmp.addr[i]; + } + while(dev->tbusy) barrier(); /* Stop ring access */ + test_and_set_bit(0, (void*)&dev->tbusy); + while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ + + STOP_DEPCA; /* Temporarily stop the depca. */ + depca_init_ring(dev); /* Initialize the descriptor rings */ + LoadCSRs(dev); /* Reload CSR3 */ + InitRestartDepca(dev); /* Resume normal operation. */ + dev->tbusy = 0; /* Unlock the TX ring */ + break; + + case DEPCA_SET_PROM: /* Set Promiscuous Mode */ + if (!capable(CAP_NET_ADMIN)) return -EPERM; + while(dev->tbusy) barrier(); /* Stop ring access */ + test_and_set_bit(0, (void*)&dev->tbusy); + while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ + + STOP_DEPCA; /* Temporarily stop the depca. */ + depca_init_ring(dev); /* Initialize the descriptor rings */ + lp->init_block.mode |= PROM; /* Set promiscuous mode */ + + LoadCSRs(dev); /* Reload CSR3 */ + InitRestartDepca(dev); /* Resume normal operation. */ + dev->tbusy = 0; /* Unlock the TX ring */ + break; + + case DEPCA_CLR_PROM: /* Clear Promiscuous Mode */ + if (!capable(CAP_NET_ADMIN)) return -EPERM; + while(dev->tbusy) barrier(); /* Stop ring access */ + test_and_set_bit(0, (void*)&dev->tbusy); + while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ + + STOP_DEPCA; /* Temporarily stop the depca. */ + depca_init_ring(dev); /* Initialize the descriptor rings */ + lp->init_block.mode &= ~PROM; /* Clear promiscuous mode */ + + LoadCSRs(dev); /* Reload CSR3 */ + InitRestartDepca(dev); /* Resume normal operation. */ + dev->tbusy = 0; /* Unlock the TX ring */ + break; + + case DEPCA_SAY_BOO: /* Say "Boo!" to the kernel log file */ + printk("%s: Boo!\n", dev->name); + break; + + case DEPCA_GET_MCA: /* Get the multicast address table */ + ioc->len = (HASH_TABLE_LEN >> 3); + if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT; + copy_to_user(ioc->data, lp->init_block.mcast_table, ioc->len); + break; + + case DEPCA_SET_MCA: /* Set a multicast address */ + if (!capable(CAP_NET_ADMIN)) return -EPERM; + if (verify_area(VERIFY_READ, ioc->data, ETH_ALEN*ioc->len)) return -EFAULT; + copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len); + set_multicast_list(dev); + break; + + case DEPCA_CLR_MCA: /* Clear all multicast addresses */ + if (!capable(CAP_NET_ADMIN)) return -EPERM; + set_multicast_list(dev); + break; + + case DEPCA_MCA_EN: /* Enable pass all multicast addressing */ + if (!capable(CAP_NET_ADMIN)) return -EPERM; + set_multicast_list(dev); + break; + + case DEPCA_GET_STATS: /* Get the driver statistics */ + cli(); + ioc->len = sizeof(lp->pktStats); + if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) { + status = -EFAULT; + } else { + copy_to_user(ioc->data, &lp->pktStats, ioc->len); + } + sti(); + break; + + case DEPCA_CLR_STATS: /* Zero out the driver statistics */ + if (!capable(CAP_NET_ADMIN)) return -EPERM; + cli(); + memset(&lp->pktStats, 0, sizeof(lp->pktStats)); + sti(); + break; + + case DEPCA_GET_REG: /* Get the DEPCA Registers */ + i=0; + tmp.sval[i++] = inw(DEPCA_NICSR); + outw(CSR0, DEPCA_ADDR); /* status register */ + tmp.sval[i++] = inw(DEPCA_DATA); + memcpy(&tmp.sval[i], &lp->init_block, sizeof(struct depca_init)); + ioc->len = i+sizeof(struct depca_init); + if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT; + copy_to_user(ioc->data, tmp.addr, ioc->len); + break; + + default: + return -EOPNOTSUPP; + } - break; - case DEPCA_GET_MCA: /* Get the multicast address table */ - ioc->len = (HASH_TABLE_LEN >> 3); - if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { - copy_to_user(ioc->data, lp->init_block.mcast_table, ioc->len); - } - break; - case DEPCA_SET_MCA: /* Set a multicast address */ - if (capable(CAP_NET_ADMIN)) { - if (!(status = verify_area(VERIFY_READ, ioc->data, ETH_ALEN * ioc->len))) { - copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len); - set_multicast_list(dev); - } - } else { - status = -EPERM; - } - - break; - case DEPCA_CLR_MCA: /* Clear all multicast addresses */ - if (capable(CAP_NET_ADMIN)) { - set_multicast_list(dev); - } else { - status = -EPERM; - } - - break; - case DEPCA_MCA_EN: /* Enable pass all multicast addressing */ - if (capable(CAP_NET_ADMIN)) { - set_multicast_list(dev); - } else { - status = -EPERM; - } - - break; - case DEPCA_GET_STATS: /* Get the driver statistics */ - cli(); - ioc->len = sizeof(lp->pktStats); - if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { - copy_to_user(ioc->data, &lp->pktStats, ioc->len); - } - sti(); - - break; - case DEPCA_CLR_STATS: /* Zero out the driver statistics */ - if (capable(CAP_NET_ADMIN)) { - cli(); - memset(&lp->pktStats, 0, sizeof(lp->pktStats)); - sti(); - } else { - status = -EPERM; - } - - break; - case DEPCA_GET_REG: /* Get the DEPCA Registers */ - i = 0; - tmp.sval[i++] = inw(DEPCA_NICSR); - outw(CSR0, DEPCA_ADDR); /* status register */ - tmp.sval[i++] = inw(DEPCA_DATA); - memcpy(&tmp.sval[i], &lp->init_block, sizeof(struct depca_init)); - ioc->len = i + sizeof(struct depca_init); - if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { - copy_to_user(ioc->data, tmp.addr, ioc->len); - } - break; - default: - status = -EOPNOTSUPP; - } - - return status; + return status; } #ifdef MODULE -static char devicename[9] = -{0,}; -static struct device thisDepca = -{ - devicename, /* device name is inserted by /linux/drivers/net/net_init.c */ - 0, 0, 0, 0, - 0x200, 7, /* I/O address, IRQ */ - 0, 0, 0, NULL, depca_probe}; +static char devicename[9] = {0,}; +static struct device thisDepca = { + devicename, /* device name is inserted by /linux/drivers/net/net_init.c */ + 0, 0, 0, 0, + 0x200, 7, /* I/O address, IRQ */ + 0, 0, 0, NULL, depca_probe +}; -static int irq = 7; /* EDIT THESE LINE FOR YOUR CONFIGURATION */ -static int io = 0x200; /* Or use the irq= io= options to insmod */ +static int irq=7; /* EDIT THESE LINE FOR YOUR CONFIGURATION */ +static int io=0x200; /* Or use the irq= io= options to insmod */ MODULE_PARM(irq, "i"); MODULE_PARM(io, "i"); -/* See depca_probe() for autoprobe messages when a module */ -int init_module(void) +/* See depca_probe() for autoprobe messages when a module */ +int +init_module(void) { - thisDepca.irq = irq; - thisDepca.base_addr = io; + thisDepca.irq=irq; + thisDepca.base_addr=io; - if (register_netdev(&thisDepca) != 0) - return -EIO; + if (register_netdev(&thisDepca) != 0) + return -EIO; - return 0; + return 0; } -void cleanup_module(void) +void +cleanup_module(void) { - if (thisDepca.priv) { - kfree(thisDepca.priv); - thisDepca.priv = NULL; - } - thisDepca.irq = 0; + struct depca_private *lp = thisDepca.priv; + if (lp) { +#ifdef CONFIG_MCA + if(lp->mca_slot != -1) + mca_mark_as_unused(lp->mca_slot); +#endif + kfree(lp); + thisDepca.priv = NULL; + } + thisDepca.irq=0; - unregister_netdev(&thisDepca); - release_region(thisDepca.base_addr, DEPCA_TOTAL_SIZE); + unregister_netdev(&thisDepca); + release_region(thisDepca.base_addr, DEPCA_TOTAL_SIZE); } -#endif /* MODULE */ - +#endif /* MODULE */ + /* * Local variables: * compile-command: "gcc -D__KERNEL__ -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c depca.c" diff -u --recursive --new-file v2.1.129/linux/drivers/net/hamradio/6pack.c linux/drivers/net/hamradio/6pack.c --- v2.1.129/linux/drivers/net/hamradio/6pack.c Wed Apr 8 19:36:27 1998 +++ linux/drivers/net/hamradio/6pack.c Fri Nov 20 08:44:06 1998 @@ -726,7 +726,7 @@ #ifdef MODULE static int sixpack_init_ctrl_dev(void) #else /* !MODULE */ -__initfunc sixpack_init_ctrl_dev(struct device *dummy) +__initfunc(int sixpack_init_ctrl_dev(struct device *dummy)) #endif /* !MODULE */ { int status; diff -u --recursive --new-file v2.1.129/linux/drivers/net/hamradio/baycom_epp.c linux/drivers/net/hamradio/baycom_epp.c --- v2.1.129/linux/drivers/net/hamradio/baycom_epp.c Fri Oct 23 22:01:21 1998 +++ linux/drivers/net/hamradio/baycom_epp.c Fri Nov 20 08:44:06 1998 @@ -1540,7 +1540,7 @@ return; } baycom_ports[i].mode = str; - baycom_ports[i].irq = ints[1]; + baycom_ports[i].iobase = ints[1]; if (i < NR_PORTS-1) baycom_ports[i+1].mode = NULL; } diff -u --recursive --new-file v2.1.129/linux/drivers/net/hamradio/hdlcdrv.c linux/drivers/net/hamradio/hdlcdrv.c --- v2.1.129/linux/drivers/net/hamradio/hdlcdrv.c Tue Jun 9 11:57:29 1998 +++ linux/drivers/net/hamradio/hdlcdrv.c Fri Nov 20 08:44:06 1998 @@ -42,6 +42,7 @@ #include #include +#include #include #include #include diff -u --recursive --new-file v2.1.129/linux/drivers/net/hamradio/soundmodem/sm.c linux/drivers/net/hamradio/soundmodem/sm.c --- v2.1.129/linux/drivers/net/hamradio/soundmodem/sm.c Tue Jun 9 11:57:29 1998 +++ linux/drivers/net/hamradio/soundmodem/sm.c Fri Nov 20 08:44:06 1998 @@ -554,17 +554,17 @@ cp = hi->data.modename; while (*hwp) { if ((*hwp)->hw_name) - cp += sprintf("%s:,", (*hwp)->hw_name); + cp += sprintf(cp, "%s:,", (*hwp)->hw_name); hwp++; } while (*mtp) { if ((*mtp)->name) - cp += sprintf(">%s,", (*mtp)->name); + cp += sprintf(cp, ">%s,", (*mtp)->name); mtp++; } while (*mrp) { if ((*mrp)->name) - cp += sprintf("<%s,", (*mrp)->name); + cp += sprintf(cp, "<%s,", (*mrp)->name); mrp++; } cp[-1] = '\0'; diff -u --recursive --new-file v2.1.129/linux/drivers/net/rtl8139.c linux/drivers/net/rtl8139.c --- v2.1.129/linux/drivers/net/rtl8139.c Thu Nov 19 09:56:28 1998 +++ linux/drivers/net/rtl8139.c Sun Nov 22 09:47:52 1998 @@ -56,17 +56,8 @@ /* Time in jiffies before concluding the transmitter is hung. */ #define TX_TIMEOUT (4*HZ) -#ifdef MODULE -#ifdef MODVERSIONS -#include -#endif #include #include -#else -#define MOD_INC_USE_COUNT -#define MOD_DEC_USE_COUNT -#endif - #include #include #include diff -u --recursive --new-file v2.1.129/linux/drivers/net/syncppp.c linux/drivers/net/syncppp.c --- v2.1.129/linux/drivers/net/syncppp.c Thu Nov 19 09:56:28 1998 +++ linux/drivers/net/syncppp.c Fri Nov 20 08:44:06 1998 @@ -1266,7 +1266,7 @@ void sync_ppp_init(void) { printk(KERN_INFO "Cronyx Ltd, Synchronous PPP and CISCO HDLC (c) 1994\n"); - printk(KERN_INFO "Linux port (c) 1998 Building Number Three Ltd & Jan 'Yenya' Kasprzak.\n"); + printk(KERN_INFO "Linux port (c) 1998 Building Number Three Ltd & Jan \"Yenya\" Kasprzak.\n"); sppp_packet_type.type=htons(ETH_P_WAN_PPP); dev_add_pack(&sppp_packet_type); } diff -u --recursive --new-file v2.1.129/linux/drivers/sbus/audio/Makefile linux/drivers/sbus/audio/Makefile --- v2.1.129/linux/drivers/sbus/audio/Makefile Thu Nov 19 09:56:28 1998 +++ linux/drivers/sbus/audio/Makefile Fri Nov 20 08:58:21 1998 @@ -14,6 +14,8 @@ O_TARGET := sparcaudio.o O_OBJS := M_OBJS := +M := +MM := ifeq ($(CONFIG_SPARCAUDIO),y) M=y diff -u --recursive --new-file v2.1.129/linux/drivers/sbus/audio/cs4231.c linux/drivers/sbus/audio/cs4231.c --- v2.1.129/linux/drivers/sbus/audio/cs4231.c Thu Nov 19 09:56:28 1998 +++ linux/drivers/sbus/audio/cs4231.c Fri Nov 20 11:42:33 1998 @@ -14,7 +14,6 @@ * The APC DMA controller support unfortunately is not documented. Thanks, Sun */ -#include #include #include #include diff -u --recursive --new-file v2.1.129/linux/drivers/scsi/BusLogic.h linux/drivers/scsi/BusLogic.h --- v2.1.129/linux/drivers/scsi/BusLogic.h Tue Aug 18 22:02:04 1998 +++ linux/drivers/scsi/BusLogic.h Mon Nov 23 13:44:18 1998 @@ -1800,10 +1800,8 @@ static boolean BusLogic_AcquireResources(BusLogic_HostAdapter_T *) __init; static void BusLogic_ReleaseResources(BusLogic_HostAdapter_T *) __init; static boolean BusLogic_TargetDeviceInquiry(BusLogic_HostAdapter_T *) __init; -static void BusLogic_ReportTargetDeviceInfo(BusLogic_HostAdapter_T *) __init; static void BusLogic_InitializeHostStructure(BusLogic_HostAdapter_T *, SCSI_Host_T *) __init; -static void BusLogic_SelectQueueDepths(SCSI_Host_T *, SCSI_Device_T *) __init; int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *) __init; int BusLogic_ReleaseHostAdapter(SCSI_Host_T *) __init; static boolean BusLogic_ParseKeyword(char **, char *) __init; diff -u --recursive --new-file v2.1.129/linux/drivers/scsi/README.ncr53c7xx linux/drivers/scsi/README.ncr53c7xx --- v2.1.129/linux/drivers/scsi/README.ncr53c7xx Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/README.ncr53c7xx Fri Nov 20 11:43:01 1998 @@ -0,0 +1,40 @@ +README for WarpEngine/A4000T/A4091 SCSI kernels. + +Use the following options to disable options in the SCSI driver. + +Using amiboot for example..... + +To disable Synchronous Negotiation.... + + amiboot -k kernel 53c7xx=nosync:0 + +To disable Disconnection.... + + amiboot -k kernel 53c7xx=nodisconnect:0 + +To disable certain SCSI devices... + + amiboot -k kernel 53c7xx=validids:0x3F + + this allows only device ID's 0,1,2,3,4 and 5 for linux to handle. + (this is a bitmasked field - i.e. each bit represents a SCSI ID) + +These commands work on a per controller basis and use the option 'next' to +move to the next controller in the system. + +e.g. + amiboot -k kernel 53c7xx=nodisconnect:0,next,nosync:0 + + this uses No Disconnection on the first controller and Asynchronous + SCSI on the second controller. + +Known Issues: + +Two devices are known not to function with the default settings of using +synchronous SCSI. These are the Archive Viper 150 Tape Drive and the +SyQuest SQ555 removeable hard drive. When using these devices on a controller +use the 'nosync:0' option. + +Please try these options and post any problems/successes to me. + +Alan Hourihane diff -u --recursive --new-file v2.1.129/linux/drivers/scsi/ibmmca.c linux/drivers/scsi/ibmmca.c --- v2.1.129/linux/drivers/scsi/ibmmca.c Wed Sep 9 14:51:08 1998 +++ linux/drivers/scsi/ibmmca.c Fri Nov 20 08:45:06 1998 @@ -822,6 +822,7 @@ #ifdef MODULE_PARM MODULE_PARM(io_port, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i"); MODULE_PARM(scsi_id, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i"); +MODULE_PARM(display, "1i"); #endif /*counter of concurrent disk read/writes, to turn on/off disk led */ @@ -857,7 +858,6 @@ /*--------------------------------------------------------------------*/ - static void do_interrupt_handler (int irq, void *dev_id, struct pt_regs *regs) { @@ -1520,8 +1520,9 @@ use_display = 1; } else if( ints ) { int i; - for (i = 0; i < IM_MAX_HOSTS && i < ints[0]; i++) { - io_port[i] = ints[i+1]; + for (i = 0; i < IM_MAX_HOSTS && 2*i+2 < ints[0]; i++) { + io_port[i] = ints[2*i+2]; + scsi_id[i] = ints[2*i+2]; } } } @@ -1558,13 +1559,23 @@ } if (found) return found; + /* + * Patched by ZP Gu to work with the 9556 as well; the 9556 has + * pos2 = 05, but it should be 00, as it should be interfaced + * via port = 0x3540. + */ + /* first look for the SCSI integrated on the motherboard */ pos2 = mca_read_stored_pos(MCA_INTEGSCSI, 2); - if ((pos2 & 1) == 0) - { - pos3 = mca_read_stored_pos(MCA_INTEGSCSI, 3); + if (pos2 != 0xff) { + if ((pos2 & 1) == 0) { port = IM_IO_PORT + ((pos2 & 0x0e) << 2); + } else { + port = IM_IO_PORT; + } + pos3 = mca_read_stored_pos(MCA_INTEGSCSI, 3); id = (pos3 & 0xe0) >> 5; + printk("IBM MCA SCSI: integrated SCSI found, io=0x%x, scsi id=%d.\n", port, id); if ((shpnt = ibmmca_register(template, port, id))) diff -u --recursive --new-file v2.1.129/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c --- v2.1.129/linux/drivers/sound/sb_card.c Thu Sep 17 17:53:37 1998 +++ linux/drivers/sound/sb_card.c Fri Nov 20 08:53:30 1998 @@ -12,6 +12,9 @@ */ #include +#ifdef CONFIG_MCA +#include +#endif #include #include "sound_config.h" @@ -34,6 +37,67 @@ int probe_sb(struct address_info *hw_config) { +#ifdef CONFIG_MCA + /* MCA code added by ZP Gu (zpg@castle.net) */ + if (MCA_bus) { /* no multiple REPLY card probing */ + int slot; + u8 pos2, pos3, pos4; + + slot = mca_find_adapter( 0x5138, 0 ); + if( slot == MCA_NOTFOUND ) + { + slot = mca_find_adapter( 0x5137, 0 ); + + if (slot != MCA_NOTFOUND) + mca_set_adapter_name( slot, "REPLY SB16 & SCSI Adapter" ); + } + else + { + mca_set_adapter_name( slot, "REPLY SB16 Adapter" ); + } + + if (slot != MCA_NOTFOUND) + { + mca_mark_as_used(slot); + pos2 = mca_read_stored_pos( slot, 2 ); + pos3 = mca_read_stored_pos( slot, 3 ); + pos4 = mca_read_stored_pos( slot, 4 ); + + if (pos2 & 0x4) + { + /* enabled? */ + static unsigned short irq[] = { 0, 5, 7, 10 }; + /* + static unsigned short midiaddr[] = {0, 0x330, 0, 0x300 }; + */ + + hw_config->io_base = 0x220 + 0x20 * (pos2 >> 6); + hw_config->irq = irq[(pos4 >> 5) & 0x3]; + hw_config->dma = pos3 & 0xf; + /* Reply ADF wrong on High DMA, pos[1] should start w/ 00 */ + hw_config->dma2 = (pos3 >> 4) & 0x3; + if (hw_config->dma2 == 0) + hw_config->dma2 = hw_config->dma; + else + hw_config->dma2 += 4; + /* + hw_config->driver_use_2 = midiaddr[(pos2 >> 3) & 0x3]; + */ + + printk("SB: Reply MCA SB at slot=%d \ +iobase=0x%x irq=%d lo_dma=%d hi_dma=%d\n", + slot+1, + hw_config->io_base, hw_config->irq, + hw_config->dma, hw_config->dma2); + } + else + { + printk ("Reply SB Base I/O address disabled\n"); + } + } + } +#endif + if (check_region(hw_config->io_base, 16)) { printk(KERN_ERR "sb_card: I/O port %x is already in use\n\n", hw_config->io_base); diff -u --recursive --new-file v2.1.129/linux/fs/minix/inode.c linux/fs/minix/inode.c --- v2.1.129/linux/fs/minix/inode.c Thu Nov 12 16:21:22 1998 +++ linux/fs/minix/inode.c Sun Nov 22 09:34:01 1998 @@ -26,6 +26,11 @@ #include +static void minix_read_inode(struct inode * inode); +static void minix_write_inode(struct inode * inode); +static int minix_statfs(struct super_block *sb, struct statfs *buf, int bufsiz); +static int minix_remount (struct super_block * sb, int * flags, char * data); + static void minix_delete_inode(struct inode *inode) { inode->i_size = 0; diff -u --recursive --new-file v2.1.129/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c --- v2.1.129/linux/fs/ncpfs/dir.c Wed Aug 26 11:37:41 1998 +++ linux/fs/ncpfs/dir.c Mon Nov 23 09:44:00 1998 @@ -298,7 +298,8 @@ #ifdef CONFIG_NCPFS_STRONG static int ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name, - struct inode *new_dir, struct dentry* new_dentry, char *_new_name) + struct inode *new_dir, struct dentry* new_dentry, char *_new_name, + int *done_flag) { int res=0x90,res2; struct iattr ia; @@ -321,19 +322,34 @@ old_dir, _old_name, new_dir, _new_name); + if (!res) { + ncp_invalid_dir_cache(old_dir); + ncp_invalid_dir_cache(new_dir); + d_move(old_dentry,new_dentry); + *done_flag=1; + + if (!old_dentry->d_inode) { + DPRINTK(KERN_INFO "ncpfs: no inode -- file remains rw\n"); + goto leave_me; + } + if ((res2=ncp_lookup_validate(old_dentry))) { + DPRINTK(KERN_DEBUG "ncpfs: ncp_lookup_validate returned %d\n",res2); + } + } + memset(&ia,0,sizeof(struct iattr)); ia.ia_mode = old_dentry->d_inode->i_mode; ia.ia_mode &= ~(NCP_SERVER(old_dentry->d_inode)->m.file_mode & 0222); /* clear write bits */ ia.ia_valid = ATTR_MODE; - /* FIXME: uses only inode info, no dentry info... so it is safe to call */ - /* it now with old dentry. If we use name (in future), we have to move */ - /* it after dentry_move in caller */ + DPRINTK(KERN_INFO "calling ncp_notify_change() with %s/%s\n", + old_dentry->d_parent->d_name.name,old_dentry->d_name.name); + res2=ncp_notify_change(old_dentry, &ia); if (res2) { printk(KERN_INFO "ncpfs: ncp_notify_change (2) failed: %08x\n",res2); - goto leave_me; + /* goto leave_me; */ } leave_me: @@ -755,7 +771,7 @@ int len = dentry->d_name.len; struct ncpfs_inode_info finfo; __u8 __name[dentry->d_name.len + 1]; - + error = -ENOENT; if (!dir || !S_ISDIR(dir->i_mode)) { printk(KERN_WARNING "ncp_lookup: inode is NULL or not a directory.\n"); @@ -1067,7 +1083,7 @@ { int old_len = old_dentry->d_name.len; int new_len = new_dentry->d_name.len; - int error; + int error, done_flag=0; char _old_name[old_dentry->d_name.len + 1]; char _new_name[new_dentry->d_name.len + 1]; @@ -1105,16 +1121,21 @@ new_dir, _new_name); #ifdef CONFIG_NCPFS_STRONG if (error == 0x90 && NCP_SERVER(old_dir)->m.flags & NCP_MOUNT_STRONG) { /* RO */ - error = ncp_force_rename(old_dir, old_dentry, _old_name, new_dir, new_dentry, _new_name); + error = ncp_force_rename(old_dir, old_dentry, _old_name, + new_dir, new_dentry, _new_name, + &done_flag); } #endif if (error == 0) { - DPRINTK(KERN_DEBUG "ncp renamed %s -> %s.\n", - old_dentry->d_name.name,new_dentry->d_name.name); - ncp_invalid_dir_cache(old_dir); - ncp_invalid_dir_cache(new_dir); - d_move(old_dentry,new_dentry); + if (done_flag == 0) /* if 1, the following already happened */ + { /* in ncp_force_rename() */ + DPRINTK(KERN_DEBUG "ncp renamed %s -> %s.\n", + old_dentry->d_name.name,new_dentry->d_name.name); + ncp_invalid_dir_cache(old_dir); + ncp_invalid_dir_cache(new_dir); + d_move(old_dentry,new_dentry); + } } else { if (error == 0x9E) error = -ENAMETOOLONG; diff -u --recursive --new-file v2.1.129/linux/fs/nfs/dir.c linux/fs/nfs/dir.c --- v2.1.129/linux/fs/nfs/dir.c Thu Nov 19 09:56:28 1998 +++ linux/fs/nfs/dir.c Mon Nov 23 22:03:29 1998 @@ -474,26 +474,6 @@ } /* - * Called to free the inode from the dentry. We must flush - * any pending writes for this dentry before freeing the inode. - */ -static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode) -{ - dfprintk(VFS, "NFS: dentry_iput(%s/%s, cnt=%d, ino=%ld)\n", - dentry->d_parent->d_name.name, dentry->d_name.name, - dentry->d_count, inode->i_ino); - - if (NFS_WRITEBACK(inode)) { -#ifdef NFS_PARANOIA -printk("nfs_dentry_iput: pending writes for %s/%s, i_count=%d\n", -dentry->d_parent->d_name.name, dentry->d_name.name, inode->i_count); -#endif - nfs_wbinval(inode); - } - iput(inode); -} - -/* * Called when the dentry is being freed to release private memory. */ static void nfs_dentry_release(struct dentry *dentry) @@ -508,7 +488,7 @@ NULL, /* d_compare */ nfs_dentry_delete, /* d_delete(struct dentry *) */ nfs_dentry_release, /* d_release(struct dentry *) */ - nfs_dentry_iput /* d_iput(struct dentry *, struct inode *) */ + NULL /* d_iput */ }; #ifdef NFS_PARANOIA @@ -932,18 +912,7 @@ /* N.B. not needed now that d_delete is done in advance? */ error = -EBUSY; - if (inode) { - if (NFS_WRITEBACK(inode)) { - nfs_wbinval(inode); - if (NFS_WRITEBACK(inode)) { -#ifdef NFS_PARANOIA -printk("nfs_safe_remove: %s/%s writes pending, d_count=%d\n", -dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_count); -#endif - goto out; - } - } - } else { + if (!inode) { #ifdef NFS_PARANOIA printk("nfs_safe_remove: %s/%s already negative??\n", dentry->d_parent->d_name.name, dentry->d_name.name); @@ -1190,29 +1159,14 @@ if (new_dir == old_dir) goto do_rename; /* - * Cross-directory move ... check whether it's a file. - */ - if (S_ISREG(old_inode->i_mode)) { - if (NFS_WRITEBACK(old_inode)) { -#ifdef NFS_PARANOIA -printk("nfs_rename: %s/%s has pending writes\n", -old_dentry->d_parent->d_name.name, old_dentry->d_name.name); -#endif - nfs_wbinval(old_inode); - if (NFS_WRITEBACK(old_inode)) { -#ifdef NFS_PARANOIA -printk("nfs_rename: %s/%s has pending writes after flush\n", -old_dentry->d_parent->d_name.name, old_dentry->d_name.name); -#endif - goto out; - } - } - } - /* - * Moving a directory ... prune child dentries if needed. + * Cross-directory move ... + * + * ... prune child dentries and writebacks if needed. */ - else if (old_dentry->d_count > 1) + if (old_dentry->d_count > 1) { + nfs_wb_all(old_inode); shrink_dcache_parent(old_dentry); + } /* * Now check the use counts ... we can't safely do the diff -u --recursive --new-file v2.1.129/linux/fs/nfs/file.c linux/fs/nfs/file.c --- v2.1.129/linux/fs/nfs/file.c Thu Nov 19 09:56:28 1998 +++ linux/fs/nfs/file.c Mon Nov 23 13:46:35 1998 @@ -91,14 +91,13 @@ static int nfs_file_close(struct inode *inode, struct file *file) { - int status, error; + int status; dfprintk(VFS, "nfs: close(%x/%ld)\n", inode->i_dev, inode->i_ino); - status = nfs_wbinval(inode); - error = nfs_write_error(inode); + status = nfs_wb_all(inode); if (!status) - status = error; + status = nfs_write_error(inode); return status; } @@ -158,14 +157,13 @@ nfs_fsync(struct file *file, struct dentry *dentry) { struct inode *inode = dentry->d_inode; - int status, error; + int status; dfprintk(VFS, "nfs: fsync(%x/%ld)\n", inode->i_dev, inode->i_ino); - status = nfs_wbinval_pid(inode, current->pid); - error = nfs_write_error(inode); + status = nfs_wb_pid(inode, current->pid); if (!status) - status = error; + status = nfs_write_error(inode); return status; } diff -u --recursive --new-file v2.1.129/linux/fs/nfs/write.c linux/fs/nfs/write.c --- v2.1.129/linux/fs/nfs/write.c Thu Nov 19 09:56:28 1998 +++ linux/fs/nfs/write.c Mon Nov 23 22:04:27 1998 @@ -210,27 +210,6 @@ } /* - * Find any requests for the specified dentry. - */ -int -nfs_find_dentry_request(struct inode *inode, struct dentry *dentry) -{ - struct nfs_wreq *head, *req; - int found = 0; - - req = head = NFS_WRITEBACK(inode); - while (req != NULL) { - if (req->wb_dentry == dentry && !WB_CANCELLED(req)) { - found = 1; - break; - } - if ((req = WB_NEXT(req)) == head) - break; - } - return found; -} - -/* * Find and release all failed requests for this inode. */ int @@ -477,9 +456,10 @@ /* * Ok, there's another user of this page with the new request.. - * The IO completion will then free the page. + * The IO completion will then free the page and the dentry. */ atomic_inc(&page->count); + dget(dentry); /* Schedule request */ synchronous = schedule_write_request(req, sync); @@ -767,6 +747,7 @@ clear_bit(PG_uptodate, &page->flags); __free_page(page); + dput(req->wb_dentry); wake_up(&req->wb_wait); diff -u --recursive --new-file v2.1.129/linux/fs/proc/array.c linux/fs/proc/array.c --- v2.1.129/linux/fs/proc/array.c Thu Nov 12 16:21:23 1998 +++ linux/fs/proc/array.c Sun Nov 22 11:38:46 1998 @@ -617,7 +617,7 @@ if ((tsk)->tss.esp0 > PAGE_SIZE && \ MAP_NR((tsk)->tss.esp0) < max_mapnr) \ eip = ((struct pt_regs *) (tsk)->tss.esp0)->pc; \ - eip; }) + eip; }) #define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->tss.usp) #elif defined(__powerpc__) #define KSTK_EIP(tsk) ((tsk)->tss.regs->nip) @@ -701,16 +701,24 @@ static inline char * task_state(struct task_struct *p, char *buffer) { + int g; + buffer += sprintf(buffer, "State:\t%s\n" "Pid:\t%d\n" "PPid:\t%d\n" "Uid:\t%d\t%d\t%d\t%d\n" - "Gid:\t%d\t%d\t%d\t%d\n", + "Gid:\t%d\t%d\t%d\t%d\n" + "Groups:\t", get_task_state(p), p->pid, p->p_pptr->pid, p->uid, p->euid, p->suid, p->fsuid, p->gid, p->egid, p->sgid, p->fsgid); + + for (g = 0; g < p->ngroups; g++) + buffer += sprintf(buffer, "%d ", p->groups[g]); + + buffer += sprintf(buffer, "\n"); return buffer; } diff -u --recursive --new-file v2.1.129/linux/fs/select.c linux/fs/select.c --- v2.1.129/linux/fs/select.c Thu Nov 19 09:56:29 1998 +++ linux/fs/select.c Sun Nov 22 10:08:50 1998 @@ -202,6 +202,9 @@ * Update: ERESTARTSYS breaks at least the xview clock binary, so * I'm trying ERESTARTNOHAND which restart only when you want to. */ +#define MAX_SELECT_SECONDS \ + ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1) + asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp) { @@ -218,8 +221,10 @@ || (ret = __get_user(usec, &tvp->tv_usec))) goto out_nofds; - timeout = ROUND_UP(usec, 1000000/HZ); - timeout += sec * (unsigned long) HZ; + if ((unsigned long) sec < MAX_SELECT_SECONDS) { + timeout = ROUND_UP(usec, 1000000/HZ); + timeout += sec * (unsigned long) HZ; + } } ret = -ENOMEM; diff -u --recursive --new-file v2.1.129/linux/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h --- v2.1.129/linux/include/asm-i386/unistd.h Fri Oct 9 13:27:15 1998 +++ linux/include/asm-i386/unistd.h Sun Nov 22 16:55:45 1998 @@ -306,35 +306,7 @@ return waitpid(-1,wait_stat,0); } -/* - * This is the mechanism for creating a new kernel thread. - * - * NOTE! Only a kernel-only process(ie the swapper or direct descendants - * who haven't done an "execve()") should use this: it will work within - * a system call from a "real" process, but the process memory space will - * not be free'd until both the parent and the child have exited. - */ -static inline pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -{ - long retval; - - __asm__ __volatile__( - "movl %%esp,%%esi\n\t" - "int $0x80\n\t" /* Linux/i386 system call */ - "cmpl %%esp,%%esi\n\t" /* child or parent? */ - "je 1f\n\t" /* parent - jump */ - "pushl %3\n\t" /* push argument */ - "call *%4\n\t" /* call fn */ - "movl %2,%0\n\t" /* exit */ - "int $0x80\n" - "1:\t" - :"=a" (retval) - :"0" (__NR_clone), "i" (__NR_exit), - "r" (arg), "r" (fn), - "b" (flags | CLONE_VM) - :"si"); - return retval; -} +extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); #endif diff -u --recursive --new-file v2.1.129/linux/include/asm-m68k/atomic.h linux/include/asm-m68k/atomic.h --- v2.1.129/linux/include/asm-m68k/atomic.h Sat May 24 09:10:24 1997 +++ linux/include/asm-m68k/atomic.h Fri Nov 20 11:43:55 1998 @@ -18,35 +18,35 @@ static __inline__ void atomic_add(int i, atomic_t *v) { - __asm__ __volatile__("addl %1,%0" : : "m" (*v), "id" (i)); + __asm__ __volatile__("addl %1,%0" : "=m" (*v) : "id" (i), "0" (*v)); } static __inline__ void atomic_sub(int i, atomic_t *v) { - __asm__ __volatile__("subl %1,%0" : : "m" (*v), "id" (i)); + __asm__ __volatile__("subl %1,%0" : "=m" (*v) : "id" (i), "0" (*v)); } static __inline__ void atomic_inc(volatile atomic_t *v) { - __asm__ __volatile__("addql #1,%0" : : "m" (*v)); + __asm__ __volatile__("addql #1,%0" : "=m" (*v): "0" (*v)); } static __inline__ void atomic_dec(volatile atomic_t *v) { - __asm__ __volatile__("subql #1,%0" : : "m" (*v)); + __asm__ __volatile__("subql #1,%0" : "=m" (*v): "0" (*v)); } static __inline__ int atomic_dec_and_test(volatile atomic_t *v) { char c; - __asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c) : "m" (*v)); + __asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c), "=m" (*v): "1" (*v)); return c != 0; } #define atomic_clear_mask(mask, v) \ - __asm__ __volatile__("andl %1,%0" : : "m" (*v), "id" (~(mask))) + __asm__ __volatile__("andl %1,%0" : "=m" (*v) : "id" (~(mask)),"0"(*v)) #define atomic_set_mask(mask, v) \ - __asm__ __volatile__("orl %1,%0" : : "m" (*v), "id" (mask)); + __asm__ __volatile__("orl %1,%0" : "=m" (*v) : "id" (mask),"0"(*v)) #endif /* __ARCH_M68K_ATOMIC __ */ diff -u --recursive --new-file v2.1.129/linux/include/linux/loop.h linux/include/linux/loop.h --- v2.1.129/linux/include/linux/loop.h Fri Oct 23 22:01:26 1998 +++ linux/include/linux/loop.h Sun Nov 22 21:29:54 1998 @@ -27,7 +27,8 @@ int lo_encrypt_key_size; int lo_flags; int (*transfer)(struct loop_device *, int cmd, - char *raw_buf, char *loop_buf, int size); + char *raw_buf, char *loop_buf, int size, + int real_block); char lo_name[LO_NAME_SIZE]; char lo_encrypt_key[LO_KEY_SIZE]; __u32 lo_init[2]; @@ -41,7 +42,8 @@ }; typedef int (* transfer_proc_t)(struct loop_device *, int cmd, - char *raw_buf, char *loop_buf, int size); + char *raw_buf, char *loop_buf, int size, + int real_block); #endif /* __KERNEL__ */ @@ -101,7 +103,8 @@ struct loop_func_table { int number; /* filter type */ int (*transfer)(struct loop_device *lo, int cmd, - char *raw_buf, char *loop_buf, int size); + char *raw_buf, char *loop_buf, int size, + int real_block); int (*init)(struct loop_device *, struct loop_info *); /* release is called from loop_unregister_transfer or clr_fd */ int (*release)(struct loop_device *); diff -u --recursive --new-file v2.1.129/linux/include/linux/lp_m68k.h linux/include/linux/lp_m68k.h --- v2.1.129/linux/include/linux/lp_m68k.h Mon Aug 3 12:45:47 1998 +++ linux/include/linux/lp_m68k.h Fri Nov 20 11:44:06 1998 @@ -128,7 +128,7 @@ extern unsigned int lp_irq; void lp_interrupt(int dev); -int lp_init(void); +int lp_m68k_init(void); int register_parallel(struct lp_struct *, int); void unregister_parallel(int); diff -u --recursive --new-file v2.1.129/linux/include/linux/minix_fs.h linux/include/linux/minix_fs.h --- v2.1.129/linux/include/linux/minix_fs.h Tue Jun 23 10:01:29 1998 +++ linux/include/linux/minix_fs.h Sun Nov 22 09:34:01 1998 @@ -113,14 +113,7 @@ extern struct buffer_head * minix_bread(struct inode *, int, int); extern void minix_truncate(struct inode *); -extern void minix_put_super(struct super_block *); -extern struct super_block *minix_read_super(struct super_block *,void *,int); extern int init_minix_fs(void); -extern void minix_write_super(struct super_block *); -extern int minix_remount (struct super_block * sb, int * flags, char * data); -extern void minix_read_inode(struct inode *); -extern void minix_write_inode(struct inode *); -extern int minix_statfs(struct super_block *, struct statfs *, int); extern int minix_sync_inode(struct inode *); extern int minix_sync_file(struct file *, struct dentry *); diff -u --recursive --new-file v2.1.129/linux/include/linux/nfs_fs.h linux/include/linux/nfs_fs.h --- v2.1.129/linux/include/linux/nfs_fs.h Thu Nov 19 09:56:29 1998 +++ linux/include/linux/nfs_fs.h Mon Nov 23 22:04:55 1998 @@ -212,7 +212,6 @@ * linux/fs/nfs/write.c */ extern int nfs_writepage(struct file *, struct page *); -extern int nfs_find_dentry_request(struct inode *, struct dentry *); extern int nfs_check_failed_request(struct inode *); extern int nfs_check_error(struct inode *); diff -u --recursive --new-file v2.1.129/linux/include/linux/pci.h linux/include/linux/pci.h --- v2.1.129/linux/include/linux/pci.h Sun Nov 8 14:03:11 1998 +++ linux/include/linux/pci.h Mon Nov 23 13:43:36 1998 @@ -467,6 +467,7 @@ #define PCI_DEVICE_ID_OPTI_82C701 0xc701 #define PCI_DEVICE_ID_OPTI_82C814 0xc814 #define PCI_DEVICE_ID_OPTI_82C822 0xc822 +#define PCI_DEVICE_ID_OPTI_82C861 0xc861 #define PCI_DEVICE_ID_OPTI_82C825 0xd568 #define PCI_VENDOR_ID_SGS 0x104a diff -u --recursive --new-file v2.1.129/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h --- v2.1.129/linux/include/linux/proc_fs.h Thu Nov 19 09:56:29 1998 +++ linux/include/linux/proc_fs.h Mon Nov 23 13:45:34 1998 @@ -1,8 +1,6 @@ #ifndef _LINUX_PROC_FS_H #define _LINUX_PROC_FS_H -#include -#include #include /* diff -u --recursive --new-file v2.1.129/linux/include/linux/time.h linux/include/linux/time.h --- v2.1.129/linux/include/linux/time.h Fri Jul 31 17:05:52 1998 +++ linux/include/linux/time.h Thu Nov 19 16:56:39 1998 @@ -13,17 +13,27 @@ #endif /* _STRUCT_TIMESPEC */ /* - * change timeval to jiffies, trying to avoid the + * Change timeval to jiffies, trying to avoid the * most obvious overflows.. + * + * And some not so obvious. + * + * Note that we don't want to return MAX_LONG, because + * for various timeout reasons we often end up having + * to wait "jiffies+1" in order to guarantee that we wait + * at _least_ "jiffies" - so "jiffies+1" had better still + * be positive. */ +#define MAX_JIFFY_OFFSET ((~0UL >> 1)-1) + static __inline__ unsigned long timespec_to_jiffies(struct timespec *value) { unsigned long sec = value->tv_sec; long nsec = value->tv_nsec; - if (sec > ((long)(~0UL >> 1) / HZ)) - return ~0UL >> 1; + if (sec >= (MAX_JIFFY_OFFSET / HZ)) + return MAX_JIFFY_OFFSET; nsec += 1000000000L / HZ - 1; nsec /= 1000000000L / HZ; return HZ * sec + nsec; diff -u --recursive --new-file v2.1.129/linux/init/main.c linux/init/main.c --- v2.1.129/linux/init/main.c Thu Nov 19 09:56:29 1998 +++ linux/init/main.c Fri Nov 20 11:43:19 1998 @@ -11,28 +11,17 @@ #define __KERNEL_SYSCALLS__ -#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 diff -u --recursive --new-file v2.1.129/linux/ipc/msg.c linux/ipc/msg.c --- v2.1.129/linux/ipc/msg.c Tue Aug 18 22:02:08 1998 +++ linux/ipc/msg.c Fri Nov 20 11:43:19 1998 @@ -10,13 +10,9 @@ * */ -#include -#include -#include -#include #include +#include #include -#include #include #include diff -u --recursive --new-file v2.1.129/linux/ipc/sem.c linux/ipc/sem.c --- v2.1.129/linux/ipc/sem.c Sat Sep 5 16:46:42 1998 +++ linux/ipc/sem.c Fri Nov 20 11:43:19 1998 @@ -31,14 +31,7 @@ * what behavior is mandated. */ -#include -#include -#include -#include -#include -#include #include -#include #include #include diff -u --recursive --new-file v2.1.129/linux/ipc/shm.c linux/ipc/shm.c --- v2.1.129/linux/ipc/shm.c Fri Oct 23 22:01:27 1998 +++ linux/ipc/shm.c Fri Nov 20 11:43:19 1998 @@ -6,16 +6,9 @@ * Fixed the shm swap deallocation (shm_unuse()), August 1998 Andrea Arcangeli. */ -#include -#include -#include -#include -#include -#include -#include #include +#include #include -#include #include #include #include diff -u --recursive --new-file v2.1.129/linux/ipc/util.c linux/ipc/util.c --- v2.1.129/linux/ipc/util.c Sat Sep 5 16:46:42 1998 +++ linux/ipc/util.c Fri Nov 20 11:43:19 1998 @@ -8,14 +8,8 @@ * Chris Evans, */ -#include -#include -#include #include -#include -#include #include -#include #include #include diff -u --recursive --new-file v2.1.129/linux/kernel/acct.c linux/kernel/acct.c --- v2.1.129/linux/kernel/acct.c Thu Nov 19 09:56:29 1998 +++ linux/kernel/acct.c Fri Nov 20 11:43:19 1998 @@ -45,13 +45,8 @@ #include #ifdef CONFIG_BSD_PROCESS_ACCT -#include -#include -#include -#include #include #include -#include #include #include diff -u --recursive --new-file v2.1.129/linux/kernel/capability.c linux/kernel/capability.c --- v2.1.129/linux/kernel/capability.c Thu Nov 12 16:21:24 1998 +++ linux/kernel/capability.c Fri Nov 20 11:43:19 1998 @@ -5,11 +5,7 @@ * Integrated into 2.1.97+, Andrew G. Morgan */ -#include -#include #include -#include - #include /* Note: never hold tasklist_lock while spinning for this one */ diff -u --recursive --new-file v2.1.129/linux/kernel/exec_domain.c linux/kernel/exec_domain.c --- v2.1.129/linux/kernel/exec_domain.c Thu Nov 12 16:21:24 1998 +++ linux/kernel/exec_domain.c Fri Nov 20 11:43:19 1998 @@ -1,4 +1,3 @@ -#include #include #include #include diff -u --recursive --new-file v2.1.129/linux/kernel/exit.c linux/kernel/exit.c --- v2.1.129/linux/kernel/exit.c Thu Nov 12 16:21:24 1998 +++ linux/kernel/exit.c Fri Nov 20 11:43:19 1998 @@ -4,18 +4,10 @@ * Copyright (C) 1991, 1992 Linus Torvalds */ -#include -#include -#include -#include -#include -#include #include -#include #include #include #include -#include #ifdef CONFIG_BSD_PROCESS_ACCT #include #endif diff -u --recursive --new-file v2.1.129/linux/kernel/fork.c linux/kernel/fork.c --- v2.1.129/linux/kernel/fork.c Thu Nov 12 16:21:24 1998 +++ linux/kernel/fork.c Fri Nov 20 11:43:19 1998 @@ -11,13 +11,9 @@ * management can be a bitch. See 'mm/mm.c': 'copy_page_tables()' */ +#include #include -#include -#include -#include -#include #include -#include #include #include diff -u --recursive --new-file v2.1.129/linux/kernel/info.c linux/kernel/info.c --- v2.1.129/linux/kernel/info.c Thu Nov 12 16:21:24 1998 +++ linux/kernel/info.c Fri Nov 20 11:43:19 1998 @@ -6,10 +6,8 @@ /* This implements the sysinfo() system call */ -#include -#include -#include #include +#include #include #include diff -u --recursive --new-file v2.1.129/linux/kernel/itimer.c linux/kernel/itimer.c --- v2.1.129/linux/kernel/itimer.c Thu Nov 12 16:21:24 1998 +++ linux/kernel/itimer.c Fri Nov 20 11:43:19 1998 @@ -6,9 +6,6 @@ /* These are all the functions necessary to implement itimers */ -#include -#include -#include #include #include diff -u --recursive --new-file v2.1.129/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v2.1.129/linux/kernel/ksyms.c Thu Nov 12 16:21:24 1998 +++ linux/kernel/ksyms.c Fri Nov 20 11:43:19 1998 @@ -9,31 +9,23 @@ * by Bjorn Ekwall */ -#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 -#include #include #include #include @@ -50,7 +42,6 @@ #ifdef CONFIG_KMOD #include #endif -#include extern char *get_options(char *str, int *ints); extern void set_device_ro(kdev_t dev,int flag); diff -u --recursive --new-file v2.1.129/linux/kernel/module.c linux/kernel/module.c --- v2.1.129/linux/kernel/module.c Thu Nov 12 16:21:24 1998 +++ linux/kernel/module.c Fri Nov 20 11:43:19 1998 @@ -1,9 +1,5 @@ -#include -#include -#include /* defines GFP_KERNEL */ -#include +#include #include -#include #include #include #include diff -u --recursive --new-file v2.1.129/linux/kernel/panic.c linux/kernel/panic.c --- v2.1.129/linux/kernel/panic.c Thu Nov 12 16:21:25 1998 +++ linux/kernel/panic.c Fri Nov 20 11:43:19 1998 @@ -8,8 +8,6 @@ * This function is used through-out the kernel (including mm and fs) * to indicate a major problem. */ -#include - #include #include #include diff -u --recursive --new-file v2.1.129/linux/kernel/printk.c linux/kernel/printk.c --- v2.1.129/linux/kernel/printk.c Thu Nov 19 09:56:29 1998 +++ linux/kernel/printk.c Fri Nov 20 11:43:19 1998 @@ -12,10 +12,6 @@ * Modified for sysctl support, 1/8/97, Chris Horn. */ -#include - -#include -#include #include #include #include diff -u --recursive --new-file v2.1.129/linux/kernel/sched.c linux/kernel/sched.c --- v2.1.129/linux/kernel/sched.c Thu Nov 12 16:21:25 1998 +++ linux/kernel/sched.c Fri Nov 20 11:43:19 1998 @@ -16,15 +16,11 @@ * current-task */ -#include +#include #include #include -#include #include #include -#include -#include -#include #include #include @@ -32,7 +28,6 @@ #include #include #include -#include #include diff -u --recursive --new-file v2.1.129/linux/kernel/signal.c linux/kernel/signal.c --- v2.1.129/linux/kernel/signal.c Thu Nov 19 09:56:29 1998 +++ linux/kernel/signal.c Fri Nov 20 11:43:19 1998 @@ -6,14 +6,10 @@ * 1997-11-02 Modified for POSIX.1b signals by Richard Henderson */ +#include #include -#include -#include -#include #include -#include #include -#include #include #include diff -u --recursive --new-file v2.1.129/linux/kernel/softirq.c linux/kernel/softirq.c --- v2.1.129/linux/kernel/softirq.c Thu Nov 12 16:21:25 1998 +++ linux/kernel/softirq.c Fri Nov 20 11:43:19 1998 @@ -8,17 +8,12 @@ * bottom_half handler need not be re-entrant. */ -#include -#include +#include #include #include -#include #include #include -#include -#include -#include /* intr_count died a painless death... -DaveM */ diff -u --recursive --new-file v2.1.129/linux/kernel/sys.c linux/kernel/sys.c --- v2.1.129/linux/kernel/sys.c Thu Nov 12 16:21:25 1998 +++ linux/kernel/sys.c Fri Nov 20 11:43:19 1998 @@ -4,15 +4,9 @@ * Copyright (C) 1991, 1992 Linus Torvalds */ -#include -#include +#include #include -#include -#include -#include #include -#include -#include #include #include #include diff -u --recursive --new-file v2.1.129/linux/kernel/sysctl.c linux/kernel/sysctl.c --- v2.1.129/linux/kernel/sysctl.c Thu Nov 12 16:21:25 1998 +++ linux/kernel/sysctl.c Fri Nov 20 11:43:19 1998 @@ -11,21 +11,16 @@ * Made sysctl support optional via CONFIG_SYSCTL, 1/10/97, Chris Horn. */ -#include -#include -#include +#include #include #include #include -#include -#include #include #include #include #include #include -#include #include #ifdef CONFIG_ROOT_NFS diff -u --recursive --new-file v2.1.129/linux/kernel/time.c linux/kernel/time.c --- v2.1.129/linux/kernel/time.c Thu Nov 12 16:21:25 1998 +++ linux/kernel/time.c Fri Nov 20 11:43:19 1998 @@ -18,9 +18,6 @@ * kernel PLL updated to 1994-12-13 specs (rfc-1589) */ -#include -#include -#include #include #include #include diff -u --recursive --new-file v2.1.129/linux/mm/filemap.c linux/mm/filemap.c --- v2.1.129/linux/mm/filemap.c Thu Nov 19 09:56:29 1998 +++ linux/mm/filemap.c Mon Nov 23 22:28:00 1998 @@ -9,26 +9,17 @@ * most "normal" filesystems (but you don't /have/ to use this: * the NFS filesystem used to do this differently, for example) */ -#include -#include -#include -#include +#include #include -#include #include -#include -#include -#include #include #include #include -#include #include #include #include #include -#include #include #include @@ -167,15 +158,14 @@ case 1: /* is it a swap-cache or page-cache page? */ if (page->inode) { - /* Throw swap-cache pages away more aggressively */ - if (PageSwapCache(page)) { - delete_from_swap_cache(page); - return 1; - } if (test_and_clear_bit(PG_referenced, &page->flags)) break; if (pgcache_under_min()) break; + if (PageSwapCache(page)) { + delete_from_swap_cache(page); + return 1; + } remove_inode_page(page); return 1; } diff -u --recursive --new-file v2.1.129/linux/mm/memory.c linux/mm/memory.c --- v2.1.129/linux/mm/memory.c Sun Nov 8 14:03:13 1998 +++ linux/mm/memory.c Fri Nov 20 11:43:19 1998 @@ -33,23 +33,13 @@ * Idea by Alex Bligh (alex@cconcepts.co.uk) */ -#include -#include -#include -#include -#include -#include -#include -#include #include +#include #include -#include #include -#include #include #include -#include unsigned long max_mapnr = 0; unsigned long num_physpages = 0; diff -u --recursive --new-file v2.1.129/linux/mm/mlock.c linux/mm/mlock.c --- v2.1.129/linux/mm/mlock.c Wed Jul 1 19:38:57 1998 +++ linux/mm/mlock.c Fri Nov 20 11:43:19 1998 @@ -3,20 +3,12 @@ * * (C) Copyright 1995 Linus Torvalds */ -#include -#include -#include -#include #include #include -#include #include -#include -#include #include #include -#include #include static inline int mlock_fixup_all(struct vm_area_struct * vma, int newflags) diff -u --recursive --new-file v2.1.129/linux/mm/mmap.c linux/mm/mmap.c --- v2.1.129/linux/mm/mmap.c Sun Nov 8 14:03:13 1998 +++ linux/mm/mmap.c Sun Nov 22 11:34:52 1998 @@ -3,24 +3,16 @@ * * Written by obz. */ -#include -#include -#include -#include #include #include -#include #include -#include #include #include -#include #include #include #include #include -#include #include /* description of effects of mapping type and prot in current implementation. @@ -176,7 +168,7 @@ { struct mm_struct * mm = current->mm; struct vm_area_struct * vma; - int correct_wcount = 0, error; + int error; if ((len = PAGE_ALIGN(len)) == 0) return addr; @@ -300,30 +292,28 @@ !vm_enough_memory(len >> PAGE_SHIFT)) goto free_vma; - error = 0; if (file) { + int correct_wcount = 0; if (vma->vm_flags & VM_DENYWRITE) { - if (file->f_dentry->d_inode->i_writecount > 0) + if (file->f_dentry->d_inode->i_writecount > 0) { error = -ETXTBSY; - else { - /* f_op->mmap might possibly sleep - * (generic_file_mmap doesn't, but other code - * might). In any case, this takes care of any - * race that this might cause. - */ - file->f_dentry->d_inode->i_writecount--; - correct_wcount = 1; + goto free_vma; } + /* f_op->mmap might possibly sleep + * (generic_file_mmap doesn't, but other code + * might). In any case, this takes care of any + * race that this might cause. + */ + file->f_dentry->d_inode->i_writecount--; + correct_wcount = 1; } - if (!error) - error = file->f_op->mmap(file, vma); - + error = file->f_op->mmap(file, vma); + /* Fix up the count if necessary, then check for an error */ + if (correct_wcount) + file->f_dentry->d_inode->i_writecount++; + if (error) + goto unmap_and_free_vma; } - /* Fix up the count if necessary, then check for an error */ - if (correct_wcount) - file->f_dentry->d_inode->i_writecount++; - if (error) - goto free_vma; /* * merge_segments may merge our vma, so we can't refer to it @@ -341,6 +331,11 @@ } return addr; +unmap_and_free_vma: + /* Undo any partial mapping done by a device driver. */ + flush_cache_range(mm, vma->vm_start, vma->vm_end); + zap_page_range(mm, vma->vm_start, vma->vm_end - vma->vm_start); + flush_tlb_range(mm, vma->vm_start, vma->vm_end); free_vma: kmem_cache_free(vm_area_cachep, vma); return error; @@ -432,6 +427,7 @@ mpnt->vm_ops = area->vm_ops; mpnt->vm_offset = area->vm_offset + (end - area->vm_start); mpnt->vm_file = area->vm_file; + mpnt->vm_pte = area->vm_pte; if (mpnt->vm_file) mpnt->vm_file->f_count++; if (mpnt->vm_ops && mpnt->vm_ops->open) diff -u --recursive --new-file v2.1.129/linux/mm/mprotect.c linux/mm/mprotect.c --- v2.1.129/linux/mm/mprotect.c Tue Jun 23 10:01:30 1998 +++ linux/mm/mprotect.c Fri Nov 20 11:43:19 1998 @@ -3,20 +3,12 @@ * * (C) Copyright 1994 Linus Torvalds */ -#include -#include -#include -#include -#include +#include #include #include -#include #include -#include -#include #include -#include #include static inline void change_pte_range(pmd_t * pmd, unsigned long address, diff -u --recursive --new-file v2.1.129/linux/mm/mremap.c linux/mm/mremap.c --- v2.1.129/linux/mm/mremap.c Wed Jul 1 19:38:57 1998 +++ linux/mm/mremap.c Sun Nov 22 09:38:19 1998 @@ -4,21 +4,13 @@ * (C) Copyright 1996 Linus Torvalds */ -#include -#include -#include -#include -#include +#include #include #include -#include #include -#include -#include #include #include -#include #include extern int vm_enough_memory(long pages); @@ -142,7 +134,6 @@ new_vma->vm_start = new_addr; new_vma->vm_end = new_addr+new_len; new_vma->vm_offset = vma->vm_offset + (addr - vma->vm_start); - new_vma->vm_file = vma->vm_file; if (new_vma->vm_file) new_vma->vm_file->f_count++; if (new_vma->vm_ops && new_vma->vm_ops->open) @@ -151,6 +142,11 @@ merge_segments(current->mm, new_vma->vm_start, new_vma->vm_end); do_munmap(addr, old_len); current->mm->total_vm += new_len >> PAGE_SHIFT; + if (new_vma->vm_flags & VM_LOCKED) { + current->mm->locked_vm += new_len >> PAGE_SHIFT; + make_pages_present(new_vma->vm_start, + new_vma->vm_end); + } return new_addr; } kmem_cache_free(vm_area_cachep, new_vma); @@ -224,8 +220,11 @@ int pages = (new_len - old_len) >> PAGE_SHIFT; vma->vm_end = addr + new_len; current->mm->total_vm += pages; - if (vma->vm_flags & VM_LOCKED) + if (vma->vm_flags & VM_LOCKED) { current->mm->locked_vm += pages; + make_pages_present(addr + old_len, + addr + new_len); + } ret = addr; goto out; } diff -u --recursive --new-file v2.1.129/linux/mm/page_alloc.c linux/mm/page_alloc.c --- v2.1.129/linux/mm/page_alloc.c Thu Nov 19 09:56:29 1998 +++ linux/mm/page_alloc.c Fri Nov 20 11:43:19 1998 @@ -5,27 +5,17 @@ * Swap reorganised 29.12.95, Stephen Tweedie */ -#include #include -#include -#include #include -#include -#include -#include #include -#include #include #include #include #include #include -#include /* for cli()/sti() */ #include /* for copy_to/from_user */ -#include #include -#include int nr_swap_pages = 0; int nr_free_pages = 0; diff -u --recursive --new-file v2.1.129/linux/mm/page_io.c linux/mm/page_io.c --- v2.1.129/linux/mm/page_io.c Thu Nov 19 09:56:29 1998 +++ linux/mm/page_io.c Fri Nov 20 11:43:19 1998 @@ -10,21 +10,13 @@ */ #include -#include -#include #include -#include -#include -#include #include -#include #include #include #include -#include /* for cli()/sti() */ #include /* for copy_to/from_user */ -#include #include static struct wait_queue * lock_queue = NULL; diff -u --recursive --new-file v2.1.129/linux/mm/slab.c linux/mm/slab.c --- v2.1.129/linux/mm/slab.c Sun Nov 8 14:03:13 1998 +++ linux/mm/slab.c Fri Nov 20 11:43:19 1998 @@ -100,16 +100,9 @@ * is less than 512 (PAGE_SIZE<<3), but greater than 256. */ -#include #include #include -#include #include -#include - -#include -#include -#include /* If there is a different PAGE_SIZE around, and it works with this allocator, * then change the following. diff -u --recursive --new-file v2.1.129/linux/mm/swap.c linux/mm/swap.c --- v2.1.129/linux/mm/swap.c Wed Sep 9 14:51:13 1998 +++ linux/mm/swap.c Fri Nov 20 11:43:19 1998 @@ -14,22 +14,14 @@ */ #include -#include -#include #include -#include -#include -#include #include -#include #include #include #include #include -#include /* for cli()/sti() */ #include /* for copy_to/from_user */ -#include #include /* diff -u --recursive --new-file v2.1.129/linux/mm/swap_state.c linux/mm/swap_state.c --- v2.1.129/linux/mm/swap_state.c Fri Oct 23 22:01:27 1998 +++ linux/mm/swap_state.c Fri Nov 20 11:43:19 1998 @@ -8,19 +8,12 @@ */ #include -#include -#include #include -#include -#include -#include #include -#include #include #include #include -#include #include /* diff -u --recursive --new-file v2.1.129/linux/mm/swapfile.c linux/mm/swapfile.c --- v2.1.129/linux/mm/swapfile.c Thu Nov 19 09:56:29 1998 +++ linux/mm/swapfile.c Fri Nov 20 11:43:19 1998 @@ -5,25 +5,16 @@ * Swap reorganised 29.12.95, Stephen Tweedie */ -#include -#include +#include #include -#include -#include #include -#include -#include -#include #include -#include #include -#include #include /* for blk_size */ #include #include #include -#include #include unsigned int nr_swapfiles = 0; diff -u --recursive --new-file v2.1.129/linux/mm/vmalloc.c linux/mm/vmalloc.c --- v2.1.129/linux/mm/vmalloc.c Tue Jul 21 00:15:33 1998 +++ linux/mm/vmalloc.c Fri Nov 20 11:43:19 1998 @@ -8,7 +8,6 @@ #include #include -#include static struct vm_struct * vmlist = NULL; diff -u --recursive --new-file v2.1.129/linux/mm/vmscan.c linux/mm/vmscan.c --- v2.1.129/linux/mm/vmscan.c Thu Nov 19 09:56:29 1998 +++ linux/mm/vmscan.c Fri Nov 20 11:43:19 1998 @@ -10,22 +10,14 @@ * Version: $Id: vmscan.c,v 1.5 1998/02/23 22:14:28 sct Exp $ */ -#include -#include -#include +#include #include -#include -#include #include #include #include -#include -#include -#include #include #include -#include #include /* diff -u --recursive --new-file v2.1.129/linux/net/ipv4/ip_masq.c linux/net/ipv4/ip_masq.c --- v2.1.129/linux/net/ipv4/ip_masq.c Sun Nov 8 14:03:14 1998 +++ linux/net/ipv4/ip_masq.c Fri Nov 20 17:40:07 1998 @@ -4,7 +4,7 @@ * * Copyright (c) 1994 Pauline Middelink * - * $Id: ip_masq.c,v 1.27 1998/11/07 14:59:24 davem Exp $ + * $Id: ip_masq.c,v 1.28 1998/11/21 00:33:30 davem Exp $ * * * See ip_fw.c for original log @@ -43,6 +43,7 @@ * Juan Jose Ciarlante : u-space context => locks reworked * Juan Jose Ciarlante : fixed stupid SMP locking bug * Juan Jose Ciarlante : fixed "tap"ing in demasq path by copy-on-w + * Juan Jose Ciarlante : make masq_proto_doff() robust against fake sized/corrupted packets * */ @@ -337,6 +338,9 @@ #define PORT_MASQ_MUL 10 #endif +/* + * At the moment, hardcore in sync with masq_proto_num + */ atomic_t ip_masq_free_ports[3] = { ATOMIC_INIT((PORT_MASQ_END-PORT_MASQ_BEGIN) * PORT_MASQ_MUL),/* UDP */ ATOMIC_INIT((PORT_MASQ_END-PORT_MASQ_BEGIN) * PORT_MASQ_MUL),/* TCP */ @@ -960,15 +964,40 @@ return NULL; } -static __inline__ unsigned proto_doff(unsigned proto, char *th) +/* + * Get transport protocol data offset, check against size + */ +static __inline__ int proto_doff(unsigned proto, char *th, unsigned size) { + int ret = -1; switch (proto) { + case IPPROTO_ICMP: + if (size >= sizeof(struct icmphdr)) + ret = sizeof(struct icmphdr); + break; case IPPROTO_UDP: - return sizeof(struct udphdr); + if (size >= sizeof(struct udphdr)) + ret = sizeof(struct udphdr); + break; case IPPROTO_TCP: - return ((struct tcphdr*)th)->doff << 2; + /* + * Is this case, this check _also_ avoids + * touching an invalid pointer if + * size is invalid + */ + if (size >= sizeof(struct tcphdr)) { + ret = ((struct tcphdr*)th)->doff << 2; + if (ret > size) { + ret = -1 ; + } + } + + break; } - return 0; + if (ret < 0) + IP_MASQ_DEBUG(0, "mess proto_doff for proto=%d, size =%d\n", + proto, size); + return ret; } int ip_fw_masquerade(struct sk_buff **skb_p, __u32 maddr) @@ -980,19 +1009,26 @@ int size; /* - * Magic "doff" csum semantics - * !0: saved payload csum IS valid, doff is correct - * 0: csum not valid + * doff holds transport protocol data offset + * csum holds its checksum + * csum_ok says if csum is valid */ - unsigned doff = 0; + int doff = 0; int csum = 0; + int csum_ok = 0; /* * We can only masquerade protocols with ports... and hack some ICMPs */ h.raw = (char*) iph + iph->ihl * 4; + size = ntohs(iph->tot_len) - (iph->ihl * 4); + doff = proto_doff(iph->protocol, h.raw, size); + if (doff < 0) { + IP_MASQ_DEBUG(0, "O-pkt invalid packet data size\n"); + return -1; + } switch (iph->protocol) { case IPPROTO_ICMP: return(ip_fw_masq_icmp(skb_p, maddr)); @@ -1002,22 +1038,21 @@ break; case IPPROTO_TCP: /* Make sure packet is in the masq range */ - size = ntohs(iph->tot_len) - (iph->ihl * 4); IP_MASQ_DEBUG(3, "O-pkt: %s size=%d\n", masq_proto_name(iph->protocol), size); +#ifdef CONFIG_IP_MASQ_DEBUG + if (ip_masq_get_debug_level() > 3) { + skb->ip_summed = CHECKSUM_NONE; + } +#endif /* Check that the checksum is OK */ switch (skb->ip_summed) { case CHECKSUM_NONE: { - int datasz; - doff = proto_doff(iph->protocol, h.raw); - datasz = size - doff; - if (datasz < 0) - return -1; - csum = csum_partial(h.raw + doff, datasz, 0); + csum = csum_partial(h.raw + doff, size - doff, 0); IP_MASQ_DEBUG(3, "O-pkt: %s I-datacsum=%d\n", masq_proto_name(iph->protocol), csum); @@ -1138,7 +1173,7 @@ */ if (ms->app) - doff = 0; + csum_ok = 0; /* * Attempt ip_masq_app call. @@ -1153,6 +1188,7 @@ iph = skb->nh.iph; h.raw = (char*) iph + iph->ihl *4; size = skb->len - (h.raw - skb->nh.raw); + /* doff should have not changed */ } /* @@ -1163,8 +1199,7 @@ * Transport's payload partial csum */ - if (!doff) { - doff = proto_doff(iph->protocol, h.raw); + if (!csum_ok) { csum = csum_partial(h.raw + doff, size - doff, 0); } skb->csum = csum; @@ -1715,8 +1750,9 @@ union ip_masq_tphdr h; struct ip_masq *ms; unsigned short size; - unsigned doff = 0; + int doff = 0; int csum = 0; + int csum_ok = 0; __u32 maddr; /* @@ -1732,9 +1768,20 @@ return 0; } - maddr = iph->daddr; h.raw = (char*) iph + iph->ihl * 4; + /* + * IP payload size + */ + size = ntohs(iph->tot_len) - (iph->ihl * 4); + + doff = proto_doff(iph->protocol, h.raw, size); + if (doff < 0) { + IP_MASQ_DEBUG(0, "I-pkt invalid packet data size\n"); + return -1; + } + + maddr = iph->daddr; switch (iph->protocol) { case IPPROTO_ICMP: return(ip_fw_demasq_icmp(skb_p)); @@ -1754,16 +1801,20 @@ return 0; /* Check that the checksum is OK */ - size = ntohs(iph->tot_len) - (iph->ihl * 4); if ((iph->protocol == IPPROTO_UDP) && (h.uh->check == 0)) /* No UDP checksum */ break; +#ifdef CONFIG_IP_MASQ_DEBUG + if (ip_masq_get_debug_level() > 3) { + skb->ip_summed = CHECKSUM_NONE; + } +#endif switch (skb->ip_summed) { case CHECKSUM_NONE: - doff = proto_doff(iph->protocol, h.raw); csum = csum_partial(h.raw + doff, size - doff, 0); + csum_ok++; skb->csum = csum_partial(h.raw , doff, csum); case CHECKSUM_HW: @@ -1851,7 +1902,7 @@ */ if (ms->app) - doff = 0; + csum_ok = 0; /* * Attempt ip_masq_app call. @@ -1878,8 +1929,7 @@ * Transport's payload partial csum */ - if (!doff) { - doff = proto_doff(iph->protocol, h.raw); + if (!csum_ok) { csum = csum_partial(h.raw + doff, size - doff, 0); } skb->csum = csum; diff -u --recursive --new-file v2.1.129/linux/net/socket.c linux/net/socket.c --- v2.1.129/linux/net/socket.c Thu Nov 12 16:21:25 1998 +++ linux/net/socket.c Fri Nov 20 11:43:19 1998 @@ -54,18 +54,9 @@ * */ -#include -#include -#include -#include #include -#include #include -#include -#include -#include #include -#include #include #include #include @@ -80,17 +71,14 @@ #include #endif -#include #include #include #include -#include +#include #include #include #include -#include -#include #include static int sock_no_open(struct inode *irrelevant, struct file *dontcare);