diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/Configure.help linux.22p1/Documentation/Configure.help --- linux.vanilla/Documentation/Configure.help Mon Jul 22 22:52:14 2002 +++ linux.22p1/Documentation/Configure.help Fri Aug 16 00:07:33 2002 @@ -2088,7 +2088,7 @@ Also SL/SLC/SLC2/SLC3/SX/SX2, NexGen Nx586 and UMC U5D or U5S. "586/K5/5x86/6x86" Select this for an x586 or x686 processor such - as the AMD K5, the Intel 5x86 or 6x86, or the Intel 6x86MX. + as the AMD K5, the Cyrix 5x86 or 6x86, or the Cyrix 6x86MX. This choice does not assume the RDTSC (time stamp counter) instruction. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Makefile linux.22p1/Makefile --- linux.vanilla/Makefile Mon Jul 22 22:52:14 2002 +++ linux.22p1/Makefile Fri Aug 16 00:34:06 2002 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 2 -SUBLEVEL = 21 -EXTRAVERSION = +SUBLEVEL = 22 +EXTRAVERSION = rc1 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/alpha/kernel/entry.S linux.22p1/arch/alpha/kernel/entry.S --- linux.vanilla/arch/alpha/kernel/entry.S Fri Nov 2 16:39:05 2001 +++ linux.22p1/arch/alpha/kernel/entry.S Fri Aug 16 00:14:20 2002 @@ -556,7 +556,7 @@ lda $5,sys_call_table lda $27,sys_ni_syscall cmpult $0,$4,$4 - ldq $3,TASK_FLAGS($8) + ldq $3,TASK_PTRACE($8) stq $17,SP_OFF+32($30) s8addq $0,$5,$5 and $3,PT_PTRACED,$3 Binary files linux.vanilla/arch/i386/boot/bbootsect and linux.22p1/arch/i386/boot/bbootsect differ Binary files linux.vanilla/arch/i386/boot/bsetup and linux.22p1/arch/i386/boot/bsetup differ Binary files linux.vanilla/arch/i386/boot/compressed/bvmlinux and linux.22p1/arch/i386/boot/compressed/bvmlinux differ Binary files linux.vanilla/arch/i386/boot/compressed/bvmlinux.out and linux.22p1/arch/i386/boot/compressed/bvmlinux.out differ Binary files linux.vanilla/arch/i386/boot/tools/build and linux.22p1/arch/i386/boot/tools/build differ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/kernel/apm.c linux.22p1/arch/i386/kernel/apm.c --- linux.vanilla/arch/i386/kernel/apm.c Sun Mar 25 17:37:29 2001 +++ linux.22p1/arch/i386/kernel/apm.c Fri Aug 16 00:14:52 2002 @@ -1072,7 +1072,7 @@ as = fp->private_data; if (check_apm_user(as, "read")) return -EIO; - if (count < sizeof(apm_event_t)) + if ((int)count < sizeof(apm_event_t)) return -EINVAL; if (queue_empty(as)) { if (fp->f_flags & O_NONBLOCK) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/kernel/mtrr.c linux.22p1/arch/i386/kernel/mtrr.c --- linux.vanilla/arch/i386/kernel/mtrr.c Sun Mar 25 17:31:45 2001 +++ linux.22p1/arch/i386/kernel/mtrr.c Fri Aug 16 00:15:03 2002 @@ -1337,8 +1337,11 @@ static ssize_t mtrr_read (struct file *file, char *buf, size_t len, loff_t *ppos) { + if (*ppos < 0) return -EINVAL; if (*ppos >= ascii_buf_bytes) return 0; - if (*ppos + len > ascii_buf_bytes) len = ascii_buf_bytes - *ppos; + if (len > ascii_buf_bytes || + *ppos + len > ascii_buf_bytes) + len = ascii_buf_bytes - *ppos; if ( copy_to_user (buf, ascii_buffer + *ppos, len) ) return -EFAULT; *ppos += len; return len; @@ -1359,6 +1362,7 @@ if ( !suser () ) return -EPERM; /* Can't seek (pwrite) on this device */ if (ppos != &file->f_pos) return -ESPIPE; + if (len < 1) return -EINVAL; memset (line, 0, LINE_SIZE); if (len > LINE_SIZE) len = LINE_SIZE; if ( copy_from_user (line, buf, len - 1) ) return -EFAULT; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/kernel/setup.c linux.22p1/arch/i386/kernel/setup.c --- linux.vanilla/arch/i386/kernel/setup.c Mon Jul 22 22:52:14 2002 +++ linux.22p1/arch/i386/kernel/setup.c Fri Aug 16 00:07:33 2002 @@ -635,6 +635,15 @@ l2size = 64; } + /* VIA C3 CPUs (Samuel2, Ezra & Ezra-T) need further shifting. */ + if (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR && + boot_cpu_data.x86 == 6 && + (boot_cpu_data.x86_model == 7 || + boot_cpu_data.x86_model == 8)) + { + l2size = l2size >> 8; + } + if (l2size == 0) return; /* Again, no L2 cache is possible */ @@ -1056,13 +1065,18 @@ } /* Set 3DNow! on Winchip 2 and above. */ - if (c->x86_model >=8) + if (c->x86_model >=8) { c->x86_capability |= X86_FEATURE_AMD3D; - + get_model_name(c); + display_cacheinfo(c); + } c->x86_capability |=X86_FEATURE_CX8; } /* Cyrix III 'Samuel' CPU */ - if(c->x86 == 6 && c->x86_model == 6) + if(c->x86 == 6 && + (c->x86_model == 6 || + c->x86_model == 7 || + c->x86_model == 8)) { rdmsr(0x1107, lv, hv); lv|=(1<<1); /* Report CX8 */ @@ -1075,6 +1089,9 @@ cpuid(0x80000001, &lv, &lv, &lv, &hv); if(hv&(1<<31)) c->x86_capability |= X86_FEATURE_AMD3D; + + get_model_name(c); + display_cacheinfo(c); } } @@ -1278,6 +1295,10 @@ { X86_VENDOR_CENTAUR, 5, { NULL, NULL, NULL, NULL, "C6", NULL, NULL, NULL, "C6-2", NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, + { X86_VENDOR_CENTAUR, 6, + { NULL, NULL, NULL, NULL, NULL, NULL, "Samuel 1", + "Samuel 2/Ezra", "Ezra-T", NULL, NULL, + NULL, NULL, NULL, NULL, NULL }}, { X86_VENDOR_NEXGEN, 5, { "Nx586", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/vmlinux.lds linux.22p1/arch/i386/vmlinux.lds --- linux.vanilla/arch/i386/vmlinux.lds Thu Jan 1 01:00:00 1970 +++ linux.22p1/arch/i386/vmlinux.lds Fri Aug 16 01:03:53 2002 @@ -0,0 +1,77 @@ +/* ld script to make i386 Linux kernel + * Written by Martin Mares ; + */ +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(_start) +SECTIONS +{ + . = 0xC0000000 + 0x100000; + _text = .; /* Text and read-only data */ + .text : { + *(.text) + *(.fixup) + *(.gnu.warning) + } = 0x9090 + .text.lock : { *(.text.lock) } /* out-of-line lock text */ + .rodata : { *(.rodata) } + .kstrtab : { *(.kstrtab) } + + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + __ksymtab : { *(__ksymtab) } + __stop___ksymtab = .; + + _etext = .; /* End of text section */ + + .data : { /* Data */ + *(.data) + CONSTRUCTORS + } + + _edata = .; /* End of data section */ + + . = ALIGN(8192); /* init_task */ + .data.init_task : { *(.data.init_task) } + + . = ALIGN(4096); /* Init code and data */ + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(16); /* __setup() commandline parameters */ + __setup_start = .; + .setup.init : { *(.setup.init) } + __setup_end = .; + __initcall_start = .; /* the init functions to be called */ + .initcall.init : { *(.initcall.init) } + __initcall_end = .; + . = ALIGN(4096); + __init_end = .; + + + . = ALIGN(32); + .data.cacheline_aligned : { *(.data.cacheline_aligned) } + + . = ALIGN(4096); + .data.page_aligned : { *(.data.idt) } + + + __bss_start = .; /* BSS */ + .bss : { + *(.bss) + } + _end = . ; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc64/kernel/ioctl32.c linux.22p1/arch/sparc64/kernel/ioctl32.c --- linux.vanilla/arch/sparc64/kernel/ioctl32.c Mon Jul 22 22:52:14 2002 +++ linux.22p1/arch/sparc64/kernel/ioctl32.c Fri Aug 16 00:16:13 2002 @@ -249,7 +249,7 @@ return -EINVAL; /* Peculiar interface... */ - if(nclips < 0) + if(nclips < 0 || nclips > VIDEO_CLIPMAP_SIZE) nclips = VIDEO_CLIPMAP_SIZE; kcp = kmalloc(nclips * sizeof(struct video_clip), GFP_KERNEL); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/bttv.c linux.22p1/drivers/char/bttv.c --- linux.vanilla/drivers/char/bttv.c Mon Jul 22 22:52:15 2002 +++ linux.22p1/drivers/char/bttv.c Fri Aug 16 00:16:20 2002 @@ -1979,8 +1979,8 @@ vfree(vcp); return -EFAULT; } - } else if (vw.clipcount > 2048) - return -ENOMEM; + } else if (vw.clipcount > 2048) + return -EINVAL; else if (vw.clipcount) { if((vcp=vmalloc(sizeof(struct video_clip)* (vw.clipcount))) == NULL) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/buz.c linux.22p1/drivers/char/buz.c --- linux.vanilla/drivers/char/buz.c Sun Mar 25 17:31:27 2001 +++ linux.22p1/drivers/char/buz.c Fri Aug 16 00:16:20 2002 @@ -2586,7 +2586,8 @@ /* Check for vaild parameters */ if (vw.width < BUZ_MIN_WIDTH || vw.height < BUZ_MIN_HEIGHT || - vw.width > BUZ_MAX_WIDTH || vw.height > BUZ_MAX_HEIGHT) { + vw.width > BUZ_MAX_WIDTH || vw.height > BUZ_MAX_HEIGHT || + vw.clipcount < 0 || vw.clipcount > 2048) { return -EINVAL; } #ifdef XAWTV_HACK diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/hfmodem/tables.h linux.22p1/drivers/char/hfmodem/tables.h --- linux.vanilla/drivers/char/hfmodem/tables.h Thu Jan 1 01:00:00 1970 +++ linux.22p1/drivers/char/hfmodem/tables.h Fri Aug 16 00:54:03 2002 @@ -0,0 +1,90 @@ +/* + * This file is automatically generated by ./gentbl, DO NOT EDIT! +*/ + +#define SINTABBITS 9 +#define SINTABSIZE (1<mask, 0xff, (pb->maxlines * ((PLANB_MAXPIXELS + 7) & ~7)) / 8); + /* XXX: The first check may be optimized away if the + * compiler thinks a pointer can't wraparound */ + if (vw.clips + vw.clipcount < vw.clips || + vw.clipcount < 0 || vw.clipcount > 2048) + return -EINVAL; /* Add any clip rects */ for (i = 0; i < vw.clipcount; i++) { if (copy_from_user(&clip, vw.clips + i, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/pcbit/drv.c linux.22p1/drivers/isdn/pcbit/drv.c --- linux.vanilla/drivers/isdn/pcbit/drv.c Mon Jul 22 22:52:17 2002 +++ linux.22p1/drivers/isdn/pcbit/drv.c Fri Aug 16 00:16:32 2002 @@ -408,7 +408,7 @@ switch(dev->l2_state) { case L2_LWMODE: /* check (size <= rdp_size); write buf into board */ - if (len > BANK4 + 1) + if (len < 0 || len > BANK4 + 1 || len > 1024) { printk("pcbit_writecmd: invalid length %d\n", len); return -EFAULT; @@ -418,7 +418,7 @@ { u_char cbuf[1024]; - copy_from_user(cbuf, buf, len); + copy_from_user_ret(cbuf, buf, len, -EFAULT); for (i=0; ish_mem + i); } @@ -436,7 +436,7 @@ /* get it into kernel space */ if ((ptr = kmalloc(len, GFP_KERNEL))==NULL) return -ENOMEM; - copy_from_user(ptr, buf, len); + copy_from_user_ret(ptr, buf, len, -EFAULT); loadbuf = ptr; } else diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/comx-hw-comx.c linux.22p1/drivers/net/comx-hw-comx.c --- linux.vanilla/drivers/net/comx-hw-comx.c Sun Mar 25 17:31:21 2001 +++ linux.22p1/drivers/net/comx-hw-comx.c Fri Aug 16 00:16:32 2002 @@ -1061,10 +1061,17 @@ if (!(page = (char *)__get_free_page(GFP_KERNEL))) { return -ENOMEM; } - copy_from_user(page, buffer, count = (min(count, PAGE_SIZE))); - if (*(page + count - 1) == '\n') { + if (copy_from_user(page, buffer, + count = min(count, PAGE_SIZE))) { + free_page((unsigned long)page); + return -EFAULT; + } + if (count && *(page + count - 1) == '\n') { *(page + count - 1) = 0; } + if (count < PAGE_SIZE) + *(page + count) = 0; + *(page + PAGE_SIZE - 1) = 0; } else { byte *tmp; @@ -1077,6 +1084,8 @@ hw->firmware->data = NULL; } + if (file->f_pos > 0x10000 || count > 0x10000) + return -EINVAL; if ((tmp = kmalloc(count + file->f_pos, GFP_KERNEL)) == NULL) { return -ENOMEM; } @@ -1089,7 +1098,10 @@ if (hw->firmware->data) { kfree(hw->firmware->data); } - copy_from_user(tmp + file->f_pos, buffer, count); + if (copy_from_user(tmp + file->f_pos, buffer, count)) { + kfree(tmp); + return -EFAULT; + } hw->firmware->len = entry->size = file->f_pos + count; hw->firmware->data = tmp; file->f_pos += count; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/comx-hw-locomx.c linux.22p1/drivers/net/comx-hw-locomx.c --- linux.vanilla/drivers/net/comx-hw-locomx.c Sun Mar 25 17:31:21 2001 +++ linux.22p1/drivers/net/comx-hw-locomx.c Fri Aug 16 00:16:32 2002 @@ -346,10 +346,16 @@ return -ENOMEM; } - copy_from_user(page, buffer, count = min(count, PAGE_SIZE)); - if (*(page + count - 1) == '\n') { + if (copy_from_user(page, buffer, count = min(count, PAGE_SIZE))) { + free_page((unsigned long)page); + return -EFAULT; + } + if (count && *(page + count - 1) == '\n') { *(page + count - 1) = 0; } + if (count < PAGE_SIZE) + *(page + count) = 0; + *(page + PAGE_SIZE - 1) = 0; if (strcmp(entry->name, FILENAME_IO) == 0) { val = simple_strtoul(page, NULL, 0); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/comx-hw-mixcom.c linux.22p1/drivers/net/comx-hw-mixcom.c --- linux.vanilla/drivers/net/comx-hw-mixcom.c Sun Mar 25 17:31:21 2001 +++ linux.22p1/drivers/net/comx-hw-mixcom.c Fri Aug 16 00:16:32 2002 @@ -758,10 +758,16 @@ return -ENOMEM; } - copy_from_user(page, buffer, count = min(count, PAGE_SIZE)); - if (*(page + count - 1) == '\n') { + if (copy_from_user(page, buffer, count = min(count, PAGE_SIZE))) { + free_page((unsigned long)page); + return -EFAULT; + } + if (count && *(page + count - 1) == '\n') { *(page + count - 1) = 0; } + if (count < PAGE_SIZE) + *(page + count) = 0; + *(page + PAGE_SIZE - 1) = 0; if (strcmp(entry->name, FILENAME_IO) == 0) { value = simple_strtoul(page, NULL, 0); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/comx-proto-fr.c linux.22p1/drivers/net/comx-proto-fr.c --- linux.vanilla/drivers/net/comx-proto-fr.c Sun Mar 25 17:31:21 2001 +++ linux.22p1/drivers/net/comx-proto-fr.c Fri Aug 16 00:16:32 2002 @@ -666,10 +666,16 @@ return -ENOMEM; } - copy_from_user(page, buffer, count); - if (*(page + count - 1) == '\n') { + if (copy_from_user(page, buffer, count = min(count, PAGE_SIZE))) { + free_page((unsigned long)page); + return -EFAULT; + } + if (count && *(page + count - 1) == '\n') { *(page + count - 1) = 0; } + if (count < PAGE_SIZE) + *(page + count) = 0; + *(page + PAGE_SIZE - 1) = 0; if (strcmp(entry->name, FILENAME_DLCI) == 0) { u16 dlci_new = simple_strtoul(page, NULL, 10); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/comx-proto-lapb.c linux.22p1/drivers/net/comx-proto-lapb.c --- linux.vanilla/drivers/net/comx-proto-lapb.c Sun Mar 25 17:31:21 2001 +++ linux.22p1/drivers/net/comx-proto-lapb.c Fri Aug 16 00:16:32 2002 @@ -239,10 +239,16 @@ return -ENOMEM; } - copy_from_user(page, buffer, count); - if (*(page + count - 1) == '\n') { + if (copy_from_user(page, buffer, count = min(count, PAGE_SIZE))) { + free_page((unsigned long)page); + return -EFAULT; + } + if (count && *(page + count - 1) == '\n') { *(page + count - 1) = 0; } + if (count < PAGE_SIZE) + *(page + count) = 0; + *(page + PAGE_SIZE - 1) = 0; if (strcmp(entry->name, FILENAME_T1) == 0) { parm=simple_strtoul(page,NULL,10); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/comx.c linux.22p1/drivers/net/comx.c --- linux.vanilla/drivers/net/comx.c Sun Mar 25 17:31:21 2001 +++ linux.22p1/drivers/net/comx.c Fri Aug 16 00:16:32 2002 @@ -636,9 +636,16 @@ if (!(page = (char *)__get_free_page(GFP_KERNEL))) return -ENOMEM; - copy_from_user(page, buffer, count); - - if (*(page + count - 1) == '\n') *(page + count - 1) = 0; + if (copy_from_user(page, buffer, count = min(count, PAGE_SIZE))) { + free_page((unsigned long)page); + return -EFAULT; + } + if (count && *(page + count - 1) == '\n') { + *(page + count - 1) = 0; + } + if (count < PAGE_SIZE) + *(page + count) = 0; + *(page + PAGE_SIZE - 1) = 0; if (strcmp(entry->name, FILENAME_DEBUG) == 0) { int i; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/depca.c linux.22p1/drivers/net/depca.c --- linux.vanilla/drivers/net/depca.c Sun Mar 25 17:31:16 2001 +++ linux.22p1/drivers/net/depca.c Fri Aug 16 01:03:47 2002 @@ -268,7 +268,7 @@ static int depca_debug = 1; #endif -#define DEPCA_NDA 0xffe0 /* No Device Address */ +#define DEPCA_NDA 0xffe0 /* No Device Address */ /* ** Ethernet PROM defines @@ -283,18 +283,18 @@ ** ** 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 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 */ +#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 DEPCA_EISA_IO_PORTS 0x0c00 /* I/O port base address, slot 0 */ #define MAX_EISA_SLOTS 16 #define EISA_SLOT_INC 0x1000 @@ -321,7 +321,7 @@ "DE422",\ ""} static enum { - DEPCA, de100, de101, de200, de201, de202, de210, de212, de422, unknown + DEPCA, de100, de101, de200, de201, de202, de210, de212, de422, unknown } adapter; /* @@ -336,70 +336,71 @@ ** 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... */ +#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. */ 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. */ 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 */ - 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 */ + 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 */ }; /* @@ -416,783 +417,766 @@ /* ** 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 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, 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); +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; +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 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... */ #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 { -#ifdef CONFIG_MCA - mca_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); + 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); + } - 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; -} - -__initfunc(static int -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 (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) { + /* + ** 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; +} + +__initfunc(static int 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 (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; 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; + 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: - 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; - } - } -#endif /* MODULE */ - } else { - printk(" and assigned IRQ%d.\n", dev->irq); - } - if (status) release_region(ioaddr, DEPCA_TOTAL_SIZE); + 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; + } + } +#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 { - 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; - } + status = -ENXIO; + } - return status; + return status; } - -static int -depca_open(struct device *dev) + +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; - } 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; + 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; } /* Initialize the lance Rx and Tx descriptor rings. */ -static void -depca_init_ring(struct device *dev) +static void depca_init_ring(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 */ - 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]; - } + 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); + } - lp->init_block.mode = 0x0000; /* Enable the Tx and Rx */ + /* 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; - return; + 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) +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; + 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) +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) - 4; - 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)); - } + 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 { - 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; - } + 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); + } - return 0; + /* 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) - 4; + 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; } /* ** Buffer sent - check for buffer errors. */ -static int -depca_tx(struct device *dev) +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); + 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++; + } - MOD_DEC_USE_COUNT; + /* Update all the pointers */ + lp->tx_old = (++lp->tx_old) & lp->txRingMask; + } - return 0; + return 0; } -static void LoadCSRs(struct device *dev) +static int depca_close(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; + 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)); + } - 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); + /* + ** We stop the DEPCA here -- it occasionally polls + ** memory if we don't. + */ + outw(STOP, DEPCA_DATA); - outw(CSR0, DEPCA_ADDR); /* Point back to CSR0 */ + /* + ** 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); + } - return; + /* + ** Free the associated irq + */ + free_irq(dev->irq, dev); + + MOD_DEC_USE_COUNT; + + return 0; } -static int InitRestartDepca(struct device *dev) +static void LoadCSRs(struct device *dev) { - struct depca_private *lp = (struct depca_private *)dev->priv; - u_long ioaddr = dev->base_addr; - int i, status=0; + struct depca_private *lp = (struct depca_private *) dev->priv; + u_long ioaddr = dev->base_addr; - /* Copy the shadow init_block to shared memory */ - memcpy_toio((char *)lp->sh_mem, &lp->init_block, sizeof(struct depca_init)); + 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(INIT, DEPCA_DATA); /* initialize DEPCA */ + outw(CSR0, DEPCA_ADDR); /* Point back to CSR0 */ - /* wait for lance to complete initialisation */ - for (i=0;(i<100) && !(inw(DEPCA_DATA) & IDON); i++); + return; +} - 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; - } +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; + } - return status; + return status; } -static struct net_device_stats * -depca_get_stats(struct device *dev) +static struct net_device_stats *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) +static void set_multicast_list(struct device *dev) { - 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 */ - - 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 */ - } + 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 */ + + 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 */ + } } /* @@ -1203,280 +1187,284 @@ */ 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;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; - } - } - } + 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; + return; } #ifdef CONFIG_MCA /* ** Microchannel bus I/O device probe */ -__initfunc(static void -mca_probe(struct device *dev, u_long ioaddr)) +__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; + unsigned char pos[2]; + unsigned char where; + unsigned long iobase; + int irq; + int slot = 0; - 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); + ** See if we've been here before. + */ + if ((!ioaddr && autoprobed) || (ioaddr && !loading_module)) 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 (MCA_bus) { /* - ** 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 + ** 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) { + } + + 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; + /* - ** 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++; + ** Set up to check the next slot and loop. + */ + slot++; + } } - } - return; + return; } #endif /* ** ISA bus I/O device probe */ -__initfunc(static void -isa_probe(struct device *dev, u_long ioaddr)) +__initfunc(static void isa_probe(struct device *dev, u_long ioaddr)) { - int i = num_depcas, maxSlots; - s32 ports[] = DEPCA_IO_PORTS; + 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; + } - 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]); - } - } + for (; (i < maxSlots) && (dev != NULL) && ports[i]; i++) { + if (check_region(ports[i], DEPCA_TOTAL_SIZE) == 0) { + if (DevicePresent(ports[i]) == 0) { + if ((dev = alloc_device(dev, ports[i])) != NULL) { + if (depca_hw_init(dev, ports[i], -1) == 0) { + num_depcas++; + } + num_eth++; + } + } + } else if (autoprobed) { + printk("%s: region already allocated at 0x%04x.\n", dev->name, ports[i]); + } + } - return; + 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)) +__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); - } - } + 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; - return; + for (; (i < maxSlots) && (dev != NULL); i++, iobase += EISA_SLOT_INC) { + if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) { + if (EISA_signature(name, EISA_ID)) { + if (DevicePresent(iobase) == 0) { + if ((dev = alloc_device(dev, iobase)) != NULL) { + if (depca_hw_init(dev, iobase, -1) == 0) { + num_depcas++; + } + num_eth++; + } + } + } + } else if (autoprobed) { + printk("%s: region already allocated at 0x%04lx.\n", dev->name, iobase); + } + } + + return; } /* @@ -1485,90 +1473,88 @@ ** 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)) +__initfunc(static struct device * 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); - new_dev = 0; - } + if (loading_module) + 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; + 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 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 *))) +__initfunc(static 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; - } 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 */ + 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 { - sprintf(dev->name,"eth%d", num_eth);/* New device name */ + 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 */ } - 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)) +__initfunc(static int 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; - } + for (; *s; s++) { + if (isdigit(*s)) { + j = 1; + i = (i * 10) + (*s - '0'); + } else if (j) + break; + } - return i; + return i; } /* @@ -1576,42 +1562,43 @@ ** 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)) +__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; - - x = (((adapter == de100) || (adapter == de101)) ? 1 : 0); - - 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; + u_long ioaddr = dev->base_addr; + int i, k, tmp, status = 0; + u_short j, x, chksum; + + x = (((adapter == de100) || (adapter == de101)) ? 1 : 0); + + 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; - 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; } /* @@ -1716,165 +1706,161 @@ */ 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); + } - return status; + /* 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; } /* ** Look for a particular board name in the EISA configuration space */ -__initfunc(static int -EISA_signature(char *name, s32 eisa_id)) +__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; - } - } + 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;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)); - } + 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; + return; } /* @@ -1884,176 +1870,191 @@ */ 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; idev_addr[i]; - } - ioc->len = ETH_ALEN; - if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT; - break; - - case DEPCA_SET_HWADDR: /* Set the hardware address */ - if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (copy_from_user(tmp.addr,ioc->data,ETH_ALEN)) return -EFAULT; - 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 (copy_to_user(ioc->data, lp->init_block.mcast_table, ioc->len)) return -EFAULT; - break; - - case DEPCA_SET_MCA: /* Set a multicast address */ - if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len)) return -EFAULT; - 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 (copy_to_user(ioc->data, &lp->pktStats, ioc->len)) - status = -EFAULT; - 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 (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT; - break; - - default: - return -EOPNOTSUPP; - } + 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 (copy_to_user(ioc->data, tmp.addr, ioc->len)) + return -EFAULT; + break; - return status; + case DEPCA_SET_HWADDR: /* Set the hardware address */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN)) + return -EFAULT; + for (i = 0; i < ETH_ALEN; i++) { + dev->dev_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 (copy_to_user(ioc->data, lp->init_block.mcast_table, ioc->len)) + return -EFAULT; + break; + + case DEPCA_SET_MCA: /* Set a multicast address */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (ioc->len > HASH_TABLE_LEN >> 3) + return -EINVAL; + if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len)) + return -EFAULT; + 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 (copy_to_user(ioc->data, &lp->pktStats, ioc->len)) + status = -EFAULT; + 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 (copy_to_user(ioc->data, tmp.addr, ioc->len)) + return -EFAULT; + break; + + default: + return -EOPNOTSUPP; + } + + return status; } #ifdef MODULE -static char devicename[9] = {0,}; +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 + 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) { - 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; + 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 --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/eepro.c linux.22p1/drivers/net/eepro.c --- linux.vanilla/drivers/net/eepro.c Mon Jul 22 22:52:18 2002 +++ linux.22p1/drivers/net/eepro.c Fri Aug 16 00:02:34 2002 @@ -23,6 +23,8 @@ This is a compatibility hardware problem. Versions: + 0.13a in memory shortage, drop packets also in board + (Michael Westermann , 07/30/2002) 0.13 irq sharing, rewrote probe function, fixed a nasty bug in hardware_send_packet and a major cleanup (aris, 11/08/2001) 0.12d tottaly isolated old code to new code (blue cards). @@ -633,37 +635,37 @@ i = inb(dev->base_addr + ID_REG); printk(KERN_DEBUG " id: %#x ",i); - printk(KERN_DEBUG " io: %#x ", (unsigned)dev->base_addr); + printk(" io: %#x ", (unsigned)dev->base_addr); switch (lp->eepro) { case LAN595FX_10ISA: - printk(KERN_INFO "%s: Intel EtherExpress 10 ISA\n at %#x,", + printk("%s: Intel EtherExpress 10 ISA\n at %#x,", dev->name, (unsigned)dev->base_addr); break; case LAN595FX: - printk(KERN_INFO "%s: Intel EtherExpress Pro/10+ ISA\n at %#x,", + printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,", dev->name, (unsigned)dev->base_addr); break; case LAN595TX: - printk(KERN_INFO "%s: Intel EtherExpress Pro/10 ISA at %#x,", + printk("%s: Intel EtherExpress Pro/10 ISA at %#x,", dev->name, (unsigned)dev->base_addr); break; case LAN595: - printk(KERN_INFO "%s: Intel 82595-based lan card at %#x,", + printk("%s: Intel 82595-based lan card at %#x,", dev->name, (unsigned)dev->base_addr); } for (i=0; i < 6; i++) - printk(KERN_INFO "%c%02x", i ? ':' : ' ', dev->dev_addr[i]); + printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]); if (net_debug > 3) printk(KERN_DEBUG ", %dK RCV buffer", (int)(lp->rcv_ram)/1024); if (dev->irq > 2) - printk(KERN_INFO ", IRQ %d, %s.\n", dev->irq, ifmap[dev->if_port]); + printk(", IRQ %d, %s.\n", dev->irq, ifmap[dev->if_port]); else - printk(KERN_INFO ", %s.\n", ifmap[dev->if_port]); + printk(", %s.\n", ifmap[dev->if_port]); if (net_debug > 3) { i = read_eeprom(dev->base_addr, 5, dev); @@ -1548,6 +1550,10 @@ if (skb == NULL) { printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); lp->stats.rx_dropped++; + rcv_car = lp->rx_start + RCV_HEADER + rcv_size; + lp->rx_start = rcv_next_frame; + outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG); + break; } skb->dev = dev; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/ewrk3.c linux.22p1/drivers/net/ewrk3.c --- linux.vanilla/drivers/net/ewrk3.c Sun Mar 25 17:31:16 2001 +++ linux.22p1/drivers/net/ewrk3.c Fri Aug 16 00:16:52 2002 @@ -1754,6 +1754,10 @@ break; case EWRK3_SET_MCA: /* Set a multicast address */ if (capable(CAP_NET_ADMIN)) { + if (ioc->len > 1024) { + status = -EINVAL; + break; + } if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len)) { status = -EFAULT; break; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/sdla_fr.c linux.22p1/drivers/net/sdla_fr.c --- linux.vanilla/drivers/net/sdla_fr.c Fri Nov 2 16:39:07 2001 +++ linux.22p1/drivers/net/sdla_fr.c Fri Aug 16 00:16:52 2002 @@ -884,6 +884,7 @@ if(copy_from_user((void*)&cmd, u_cmd, sizeof(cmd))) return -EFAULT; + /* XXX: should check cmd.length against size allocated for mbox->data */ /* execute command */ do diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/sdla_ppp.c linux.22p1/drivers/net/sdla_ppp.c --- linux.vanilla/drivers/net/sdla_ppp.c Sun Mar 25 17:31:19 2001 +++ linux.22p1/drivers/net/sdla_ppp.c Fri Aug 16 00:16:52 2002 @@ -533,6 +533,7 @@ if (copy_from_user((void*)&mbox->cmd, u_cmd, sizeof(ppp_cmd_t))) return -EFAULT; + /* XXX: should check cmd.length against size allocated for mbox->data */ len = mbox->cmd.length; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/sdla_x25.c linux.22p1/drivers/net/sdla_x25.c --- linux.vanilla/drivers/net/sdla_x25.c Sun Mar 25 17:31:19 2001 +++ linux.22p1/drivers/net/sdla_x25.c Fri Aug 16 00:17:04 2002 @@ -495,6 +495,7 @@ if(copy_from_user((void*)&cmd, u_cmd, sizeof(cmd))) return -EFAULT; + /* XXX: should check cmd.length against size allocated for mbox->data */ /* execute command */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/sdlamain.c linux.22p1/drivers/net/sdlamain.c --- linux.vanilla/drivers/net/sdlamain.c Sun Mar 25 17:31:19 2001 +++ linux.22p1/drivers/net/sdlamain.c Fri Aug 16 00:17:04 2002 @@ -589,6 +589,9 @@ sdla_t* card; int err; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + /* sanity checks */ if ((wandev == NULL) || (wandev->private == NULL)) return -EFAULT; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/wanxl.c linux.22p1/drivers/net/wanxl.c --- linux.vanilla/drivers/net/wanxl.c Sun Mar 25 17:31:22 2001 +++ linux.22p1/drivers/net/wanxl.c Fri Aug 16 00:17:04 2002 @@ -552,6 +552,9 @@ if (copy_from_user(&length, ifr->ifr_data, 4)!=0) return -EFAULT; + if (length > INT_MAX) + return -EINVAL; + switch(cmd) { case HDLCRUN: if (port->card->first_port != port) /* Not initial port */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/zlib.c linux.22p1/drivers/net/zlib.c --- linux.vanilla/drivers/net/zlib.c Mon Jul 22 22:52:18 2002 +++ linux.22p1/drivers/net/zlib.c Fri Aug 16 00:17:05 2002 @@ -3938,7 +3938,6 @@ r = t; LEAVE } - ZFREE(z, s->sub.trees.blens); Tracev((stderr, "inflate: trees ok, %d * %d bytes used\n", inflate_hufts, sizeof(inflate_huft))); if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/s390/block/dasd.c linux.22p1/drivers/s390/block/dasd.c --- linux.vanilla/drivers/s390/block/dasd.c Mon Jul 22 22:52:18 2002 +++ linux.22p1/drivers/s390/block/dasd.c Fri Aug 16 00:17:11 2002 @@ -2883,8 +2883,12 @@ static ssize_t dasd_devices_write ( struct file *file, const char* user_buf, size_t user_len, loff_t* offset ) { - char * buffer = vmalloc(user_len); + char *buffer; + if (user_len > PAGE_SIZE) + return -EINVAL; + + buffer = vmalloc(user_len + 1); if ( buffer == NULL) return -ENOMEM; copy_from_user ( buffer, user_buf, user_len); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sbus/char/openprom.c linux.22p1/drivers/sbus/char/openprom.c --- linux.vanilla/drivers/sbus/char/openprom.c Sun Mar 25 17:31:39 2001 +++ linux.22p1/drivers/sbus/char/openprom.c Fri Aug 16 00:17:11 2002 @@ -75,7 +75,7 @@ get_user_ret(bufsize, &info->oprom_size, -EFAULT); - if (bufsize == 0 || bufsize > OPROMMAXPARAM) + if (bufsize <= 0 || bufsize > OPROMMAXPARAM) return -EINVAL; if (!(*opp_p = kmalloc(sizeof(int) + bufsize + 1, GFP_KERNEL))) @@ -331,6 +331,8 @@ { char *tmp; + if (len + 1 < len) + return -EINVAL; tmp = kmalloc(len + 1, GFP_KERNEL); if (!tmp) return -ENOMEM; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/3w-xxxx.c linux.22p1/drivers/scsi/3w-xxxx.c --- linux.vanilla/drivers/scsi/3w-xxxx.c Mon Jul 22 22:52:18 2002 +++ linux.22p1/drivers/scsi/3w-xxxx.c Fri Aug 16 00:10:06 2002 @@ -132,12 +132,23 @@ Empty stale responses before draining aen queue. Fix tw_scsi_eh_abort() to not reset on every io abort. Set can_queue in SHT to 255 to prevent hang from AEN. + 1.02.00.020 - Fix possible null pointer dereference in tw_scsi_release(). + 1.02.00.021 - Fix bug in tw_aen_drain_queue() where unit # was always zero. + 1.02.00.022 - Add severity levels to AEN strings. + 1.02.00.023 - Fix command interrupt spurious error messages. + 1.02.00.024 - Fix bug in raw command post with data ioctl method. + Fix bug where rollcall sometimes failed with cable errors. + 1.02.00.025 - Print unit # on all command timeouts. */ #include MODULE_AUTHOR ("3ware Inc."); +#ifdef __SMP__ +MODULE_DESCRIPTION ("3ware Storage Controller Linux Driver (SMP)"); +#else MODULE_DESCRIPTION ("3ware Storage Controller Linux Driver"); +#endif #include #include @@ -183,7 +194,7 @@ }; /* Globals */ -char *tw_driver_version="1.02.00.019"; +char *tw_driver_version="1.02.00.025"; TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT]; int tw_device_extension_count = 0; @@ -206,7 +217,7 @@ /* Print some useful info when certain aen codes come out */ if (aen == 0x0ff) { - printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: AEN queue overflow.\n", tw_dev->host->host_no); + printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: INFO: AEN queue overflow.\n", tw_dev->host->host_no); } else { if ((aen & 0x0ff) < TW_AEN_STRING_MAX) { if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') { @@ -278,7 +289,7 @@ status_reg_addr = tw_dev->registers.status_reg_addr; response_que_addr = tw_dev->registers.response_que_addr; - if (tw_poll_status(tw_dev, TW_STATUS_ATTENTION_INTERRUPT, 30)) { + if (tw_poll_status(tw_dev, TW_STATUS_ATTENTION_INTERRUPT | TW_STATUS_MICROCONTROLLER_READY, 30)) { dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): No attention interrupt for card %d\n", tw_device_extension_count); return 1; } @@ -388,7 +399,7 @@ break; default: if (aen == 0x0ff) { - printk(KERN_WARNING "3w-xxxx: AEN: AEN queue overflow.\n"); + printk(KERN_WARNING "3w-xxxx: AEN: INFO: AEN queue overflow.\n"); } else { if ((aen & 0x0ff) < TW_AEN_STRING_MAX) { if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') { @@ -405,7 +416,7 @@ /* Now put the aen on the aen_queue */ if (queue == 1) { - tw_dev->aen_queue[tw_dev->aen_tail] = aen_code; + tw_dev->aen_queue[tw_dev->aen_tail] = aen; if (tw_dev->aen_tail == TW_Q_LENGTH - 1) { tw_dev->aen_tail = TW_Q_START; } else { @@ -974,7 +985,7 @@ } } if (numcards == 0) - printk(KERN_WARNING "3w-xxxx: tw_findcards(): No cards found.\n"); + printk(KERN_WARNING "3w-xxxx: No cards with valid units found.\n"); else register_reboot_notifier(&tw_notifier); @@ -1433,7 +1444,7 @@ } tw_dev->pending_request_count--; } else { - printk(KERN_WARNING "3w-xxxx: scsi%d: Error posting pending commands.\n", tw_dev->host->host_no); + /* If we get here, we will continue re-posting on the next command interrupt */ break; } } @@ -1464,8 +1475,13 @@ /* Check for correct state */ if (tw_dev->state[request_id] != TW_S_POSTED) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Received a request id (%d) (opcode = 0x%x) that wasn't posted.\n", tw_dev->host->host_no, request_id, command_packet->byte0.opcode); - error = 1; + /* Handle timed out ioctl's */ + if (tw_dev->srb[request_id] != 0) { + if (tw_dev->srb[request_id]->cmnd[0] != TW_IOCTL) { + printk(KERN_WARNING "3w-xxxx: scsi%d: Received a request id (%d) (opcode = 0x%x) that wasn't posted.\n", tw_dev->host->host_no, request_id, command_packet->byte0.opcode); + error = 1; + } + } } dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Response queue request id: %d.\n", request_id); @@ -1555,7 +1571,8 @@ TW_Passthru *passthru = NULL; int tw_aen_code, i, use_sg; char *data_ptr; - int total_bytes = 0; + int total_bytes = 0, posted = 0; + struct timeval before, timeout; ioctl = (TW_Ioctl *)tw_dev->srb[request_id]->request_buffer; if (ioctl == NULL) { @@ -1706,7 +1723,7 @@ if ((u32 *)command_packet->byte8.param.sgl[i].address != NULL) { error = copy_from_user(data_ptr, (u32 *)command_packet->byte8.param.sgl[i].address, command_packet->byte8.param.sgl[i].length); if (error) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Error copying param sglist from userspace.\n", tw_dev->host->host_no); + dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying param sglist from userspace.\n", tw_dev->host->host_no); goto tw_ioctl_bail; } } else { @@ -1736,7 +1753,7 @@ if ((u32 *)command_packet->byte8.io.sgl[i].address != NULL) { error = copy_from_user(data_ptr, (u32 *)command_packet->byte8.io.sgl[i].address, command_packet->byte8.io.sgl[i].length); if (error) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Error copying io sglist from userspace.\n", tw_dev->host->host_no); + dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying io sglist from userspace.\n", tw_dev->host->host_no); goto tw_ioctl_bail; } } else { @@ -1752,15 +1769,31 @@ command_packet->byte8.io.sgl[0].length = total_bytes; } + spin_unlock(&tw_dev->tw_lock); spin_unlock_irq(&io_request_lock); - spin_unlock_irq(&tw_dev->tw_lock); + + set_bit(TW_IN_IOCTL, &tw_dev->flags); /* Finally post the command packet */ tw_post_command_packet(tw_dev, request_id); + posted = 1; + do_gettimeofday(&before); + tw_ioctl_retry: mdelay(TW_IOCTL_WAIT_TIME); - spin_lock_irq(&tw_dev->tw_lock); + if (test_bit(TW_IN_IOCTL, &tw_dev->flags)) { + do_gettimeofday(&timeout); + if (before.tv_sec + TW_IOCTL_TIMEOUT < timeout.tv_sec) { + spin_lock_irq(&io_request_lock); + spin_lock(&tw_dev->tw_lock); + goto tw_ioctl_bail; + } else { + goto tw_ioctl_retry; + } + } + spin_lock_irq(&io_request_lock); + spin_lock(&tw_dev->tw_lock); if (signal_pending(current)) { dprintk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Signal pending, aborting ioctl().\n", tw_dev->host->host_no); @@ -1778,7 +1811,7 @@ if ((u32 *)command_save->byte8.param.sgl[i].address != NULL) { error = copy_to_user((u32 *)command_save->byte8.param.sgl[i].address, data_ptr, command_save->byte8.param.sgl[i].length); if (error) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Error copying param sglist to userspace.\n", tw_dev->host->host_no); + dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying param sglist to userspace.\n", tw_dev->host->host_no); goto tw_ioctl_bail; } dprintk(KERN_WARNING "3w-xxxx: scsi%d: Copied %ld bytes to pid %d.\n", tw_dev->host->host_no, command_save->byte8.param.sgl[i].length, current->pid); @@ -1798,7 +1831,7 @@ if ((u32 *)command_save->byte8.io.sgl[i].address != NULL) { error = copy_to_user((u32 *)command_save->byte8.io.sgl[i].address, data_ptr, command_save->byte8.io.sgl[i].length); if (error) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Error copying io sglist to userspace.\n", tw_dev->host->host_no); + dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying io sglist to userspace.\n", tw_dev->host->host_no); goto tw_ioctl_bail; } dprintk(KERN_WARNING "3w-xxxx: scsi%d: Copied %ld bytes to pid %d.\n", tw_dev->host->host_no, command_save->byte8.io.sgl[i].length, current->pid); @@ -1823,7 +1856,8 @@ /* Now complete the io */ tw_dev->state[request_id] = TW_S_COMPLETED; tw_state_request_finish(tw_dev, request_id); - tw_dev->posted_request_count--; + if (posted) + tw_dev->posted_request_count--; tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); return 0; @@ -1900,6 +1934,7 @@ break; case TW_CMD_PACKET_WITH_DATA: dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_complete(): caught TW_CMD_PACKET_WITH_DATA.\n"); + clear_bit(TW_IN_IOCTL, &tw_dev->flags); return TW_ISR_DONT_COMPLETE; /* Special case for isr to not complete io */ default: memset(buff, 0, tw_dev->srb[request_id]->request_bufflen); @@ -2170,14 +2205,14 @@ for (i=0;isrb[i] == SCpnt) { if (tw_dev->state[i] == TW_S_STARTED) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Command (0x%x) timed out.\n", tw_dev->host->host_no, (u32)SCpnt); + printk(KERN_WARNING "3w-xxxx: scsi%d: Unit #%d: Command (0x%x) timed out.\n", tw_dev->host->host_no, tw_dev->srb[i]==0 ? 0 : tw_dev->srb[i]->target, (u32)SCpnt); tw_dev->state[i] = TW_S_COMPLETED; tw_state_request_finish(tw_dev, i); spin_unlock(&tw_dev->tw_lock); return (SUCCESS); } if (tw_dev->state[i] == TW_S_PENDING) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Command (0x%x) timed out.\n", tw_dev->host->host_no, (u32)SCpnt); + printk(KERN_WARNING "3w-xxxx: scsi%d: Unit #%d: Command (0x%x) timed out.\n", tw_dev->host->host_no, tw_dev->srb[i]==0 ? 0 : tw_dev->srb[i]->target, (u32)SCpnt); if (tw_dev->pending_head == TW_Q_LENGTH-1) { tw_dev->pending_head = TW_Q_START; } else { @@ -2191,7 +2226,7 @@ } if (tw_dev->state[i] == TW_S_POSTED) { /* If the command has already been posted, we have to reset the card */ - printk(KERN_WARNING "3w-xxxx: scsi%d: Command (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, (u32)SCpnt); + printk(KERN_WARNING "3w-xxxx: scsi%d: Unit #%d: Command (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, tw_dev->srb[i]==0 ? 0 : tw_dev->srb[i]->target, (u32)SCpnt); /* We have to let AEN requests through before the reset */ spin_unlock(&tw_dev->tw_lock); spin_unlock_irq(&io_request_lock); @@ -2410,6 +2445,11 @@ dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_release()\n"); + /* Fake like we just shut down, so notify the card that + * we "shut down cleanly". + */ + tw_halt(0, 0, 0); // parameters aren't actually used + /* Free up the IO region */ release_region((tw_dev->tw_pci_dev->base_address[0]), TW_IO_ADDRESS_RANGE); @@ -2422,11 +2462,6 @@ /* Tell kernel scsi-layer we are gone */ scsi_unregister(tw_host); - /* Fake like we just shut down, so notify the card that - * we "shut down cleanly". - */ - tw_halt(0, 0, 0); // parameters aren't actually used - return 0; } /* End tw_scsi_release() */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/3w-xxxx.h linux.22p1/drivers/scsi/3w-xxxx.h --- linux.vanilla/drivers/scsi/3w-xxxx.h Mon Jul 22 22:52:18 2002 +++ linux.22p1/drivers/scsi/3w-xxxx.h Fri Aug 16 00:56:24 2002 @@ -60,43 +60,44 @@ /* AEN strings */ static char *tw_aen_string[] = { - "AEN queue empty", // 0x000 - "Soft reset occurred", // 0x001 - "Unit degraded: Unit #", // 0x002 - "Controller error", // 0x003 - "Rebuild failed: Unit #", // 0x004 - "Rebuild complete: Unit #", // 0x005 - "Incomplete unit detected: Unit #", // 0x006 - "Initialization complete: Unit #", // 0x007 - "Unclean shutdown detected: Unit #", // 0x008 - "ATA port timeout: Port #", // 0x009 - "Drive error: Port #", // 0x00A - "Rebuild started: Unit #", // 0x00B - "Initialization started: Unit #", // 0x00C - "Logical unit deleted: Unit #", // 0x00D - NULL, // 0x00E unused - "SMART threshold exceeded: Port #", // 0x00F + "INFO: AEN queue empty", // 0x000 + "INFO: Soft reset occurred", // 0x001 + "ERROR: Unit degraded: Unit #", // 0x002 + "ERROR: Controller error", // 0x003 + "ERROR: Rebuild failed: Unit #", // 0x004 + "INFO: Rebuild complete: Unit #", // 0x005 + "ERROR: Incomplete unit detected: Unit #", // 0x006 + "INFO: Initialization complete: Unit #", // 0x007 + "WARNING: Unclean shutdown detected: Unit #", // 0x008 + "WARNING: ATA port timeout: Port #", // 0x009 + "ERROR: Drive error: Port #", // 0x00A + "INFO: Rebuild started: Unit #", // 0x00B + "INFO: Initialization started: Unit #", // 0x00C + "ERROR: Logical unit deleted: Unit #", // 0x00D + NULL, // 0x00E unused + "WARNING: SMART threshold exceeded: Port #", // 0x00F NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, // 0x010-0x020 unused - "ATA UDMA downgrade: Port #", // 0x021 - "ATA UDMA upgrade: Port #", // 0x022 - "Sector repair occurred: Port #", // 0x023 - "SBUF integrity check failure", // 0x024 - "Lost cached write: Port #", // 0x025 - "Drive ECC error detected: Port #", // 0x026 - "DCB checksum error: Port #", // 0x027 - "DCB unsupported version: Port #", // 0x028 - "Verify started: Unit #", // 0x029 - "Verify failed: Port #", // 0x02A - "Verify complete: Unit #", // 0x02B - "Overwrote bad sector during rebuild: Port #", //0x2C - "Encountered bad sector during rebuild: Port #", //0x2D - "Replacement drive is too small: Port #" //0x2E + NULL, NULL, // 0x010-0x020 unused + "WARNING: ATA UDMA downgrade: Port #", // 0x021 + "WARNING: ATA UDMA upgrade: Port #", // 0x022 + "WARNING: Sector repair occurred: Port #", // 0x023 + "ERROR: SBUF integrity check failure", // 0x024 + "ERROR: Lost cached write: Port #", // 0x025 + "ERROR: Drive ECC error detected: Port #", // 0x026 + "ERROR: DCB checksum error: Port #", // 0x027 + "ERROR: DCB unsupported version: Port #", // 0x028 + "INFO: Verify started: Unit #", // 0x029 + "ERROR: Verify failed: Port #", // 0x02A + "INFO: Verify complete: Unit #", // 0x02B + "ERROR: Overwrote bad sector during rebuild: Port #", //0x02C + "ERROR: Encountered bad sector during rebuild: Port #", //0x02D + "INFO: Replacement drive is too small: Port #", //0x02E + "WARNING: Verify error: Unit not previously initialized: Unit #" //0x02F }; -#define TW_AEN_STRING_MAX 0x02F +#define TW_AEN_STRING_MAX 0x030 /* Sense key lookup table @@ -226,11 +227,13 @@ #define TW_MAX_AEN_TRIES 100 #define TW_UNIT_ONLINE 1 #define TW_IN_INTR 1 +#define TW_IN_IOCTL 2 #define TW_MAX_SECTORS 128 #define TW_AEN_WAIT_TIME 1000 #define TW_IOCTL_WAIT_TIME (1 * HZ) /* 1 second */ #define TW_ISR_DONT_COMPLETE 2 #define TW_ISR_DONT_RESULT 3 +#define TW_IOCTL_TIMEOUT 25 /* 25 seconds */ /* Macros */ #define TW_STATUS_ERRORS(x) \ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/st.c linux.22p1/drivers/scsi/st.c --- linux.vanilla/drivers/scsi/st.c Fri Nov 2 16:39:08 2001 +++ linux.22p1/drivers/scsi/st.c Fri Aug 16 00:17:11 2002 @@ -1463,7 +1463,7 @@ if (transfer < 0) { if (STps->drv_block >= 0) STps->drv_block += 1; - return (-ENOMEM); + return (-EIO); } (STp->buffer)->buffer_bytes = bytes - transfer; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/printer.c linux.22p1/drivers/usb/printer.c --- linux.vanilla/drivers/usb/printer.c Fri Nov 2 16:39:08 2001 +++ linux.22p1/drivers/usb/printer.c Fri Aug 16 00:17:22 2002 @@ -331,7 +331,7 @@ if (usblp->writeurb.status == -EINPROGRESS) { if (file->f_flags & O_NONBLOCK) - return -EAGAIN; + return writecount ? writecount : -EAGAIN; timeout = USBLP_WRITE_TIMEOUT; while (timeout && usblp->writeurb.status == -EINPROGRESS) { @@ -370,7 +370,9 @@ (count - writecount) : USBLP_BUF_SIZE; if (copy_from_user(usblp->writeurb.transfer_buffer, buffer + writecount, - usblp->writeurb.transfer_buffer_length)) return -EFAULT; + usblp->writeurb.transfer_buffer_length)) { + return writecount ? writecount : -EFAULT; + } usblp->writeurb.dev = usblp->dev; usb_submit_urb(&usblp->writeurb); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/rio500.c linux.22p1/drivers/usb/rio500.c --- linux.vanilla/drivers/usb/rio500.c Fri Nov 2 16:39:08 2001 +++ linux.22p1/drivers/usb/rio500.c Mon Jul 22 22:55:54 2002 @@ -132,7 +132,7 @@ retval = -EFAULT; goto err_out; } - if (rio_cmd.length > PAGE_SIZE) { + if (rio_cmd.length < 0 || rio_cmd.length > PAGE_SIZE) { retval = -EINVAL; goto err_out; } @@ -201,7 +201,7 @@ break; if (copy_from_user(&rio_cmd, data, sizeof(struct RioCommand))) return -EFAULT; - if (rio_cmd.length > PAGE_SIZE) + if (rio_cmd.length < 0 || rio_cmd.length > PAGE_SIZE) return -EINVAL; buffer = (unsigned char *) __get_free_page(GFP_KERNEL); if (buffer == NULL) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/serial/usbserial.c linux.22p1/drivers/usb/serial/usbserial.c --- linux.vanilla/drivers/usb/serial/usbserial.c Mon Jul 22 22:52:19 2002 +++ linux.22p1/drivers/usb/serial/usbserial.c Fri Aug 16 00:17:25 2002 @@ -840,8 +840,8 @@ dbg(__FUNCTION__ " - port %d", port->number); - if (count == 0) { - dbg(__FUNCTION__ " - write request of 0 bytes"); + if (count <= 0) { + dbg(__FUNCTION__ " - write request of %d bytes", count); return (0); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/binfmt_elf.c linux.22p1/fs/binfmt_elf.c --- linux.vanilla/fs/binfmt_elf.c Fri Nov 2 16:39:08 2001 +++ linux.22p1/fs/binfmt_elf.c Fri Aug 16 00:17:54 2002 @@ -1164,7 +1164,7 @@ set_fs(fs); len = current->mm->arg_end - current->mm->arg_start; - if (len >= ELF_PRARGSZ) + if (len < 0 /* overflow */ || len >= ELF_PRARGSZ) len = ELF_PRARGSZ-1; copy_from_user(&psinfo.pr_psargs, (const char *)current->mm->arg_start, len); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/dcache.c linux.22p1/fs/dcache.c --- linux.vanilla/fs/dcache.c Fri Nov 2 16:39:08 2001 +++ linux.22p1/fs/dcache.c Fri Aug 16 00:12:04 2002 @@ -68,7 +68,7 @@ } /* - * Release the dentry's inode, using the fileystem + * Release the dentry's inode, using the filesystem * d_iput() operation if defined. */ static inline int dentry_iput(struct dentry * dentry) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ext2/file.c linux.22p1/fs/ext2/file.c --- linux.vanilla/fs/ext2/file.c Sun Mar 25 17:30:58 2001 +++ linux.22p1/fs/ext2/file.c Fri Aug 16 00:18:26 2002 @@ -164,15 +164,15 @@ int err; int i,buffercount,write_error, new_buffer; unsigned long limit; - + /* POSIX: mtime/ctime may not change for 0 count */ if (!count) return 0; /* This makes the bounds-checking arithmetic later on much more * sane. */ - if (((signed) count) < 0) + if (((ssize_t) count) < 0) return -EINVAL; - + write_error = buffercount = 0; if (!inode) { printk("ext2_file_write: inode = NULL\n"); @@ -206,15 +206,15 @@ /* If the fd's pos is already greater than or equal to the file * descriptor's offset maximum, then we need to return EFBIG for * any non-zero count (and we already tested for zero above). */ - if (((unsigned) pos) >= 0x7FFFFFFFUL) + if (((unsigned long) pos) >= 0x7FFFFFFFUL) return -EFBIG; /* If we are about to overflow the maximum file size, we also * need to return the error, but only if no bytes can be written * successfully. */ - if (((unsigned) pos + count) > 0x7FFFFFFFUL) { + if (((unsigned long) pos + count) > 0x7FFFFFFFUL) { count = 0x7FFFFFFFL - pos; - if (((signed) count) < 0) + if (((ssize_t) count) < 0) return -EFBIG; } #else @@ -246,9 +246,9 @@ limit = current->rlim[RLIMIT_FSIZE].rlim_cur; if (limit < RLIM_INFINITY) { - if (((unsigned) pos+count) >= limit) { + if (((unsigned long) pos + count) >= limit) { count = limit - pos; - if (((signed) count) <= 0) { + if (((ssize_t) count) <= 0) { send_sig(SIGXFSZ, current, 0); return -EFBIG; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/proc/generic.c linux.22p1/fs/proc/generic.c --- linux.vanilla/fs/proc/generic.c Sun Mar 25 17:30:58 2001 +++ linux.22p1/fs/proc/generic.c Fri Aug 16 00:18:53 2002 @@ -194,24 +194,42 @@ static long long -proc_file_lseek(struct file * file, long long offset, int orig) +proc_file_lseek(struct file * file, long long offset, int origin) { - switch (orig) { - case 0: + struct inode *inode = file->f_dentry->d_inode; + if (offset < 0) - return -EINVAL; - file->f_pos = offset; - return(file->f_pos); - case 1: - if (offset + file->f_pos < 0) - return -EINVAL; - file->f_pos += offset; - return(file->f_pos); - case 2: - return(-EINVAL); - default: - return(-EINVAL); - } + return -EINVAL; + + switch (origin) { + case 2: + /* + * XXX: We don't always have a size, but older 2.2.x + * kernels didn't support SEEK_END with procfs at all + * so this should be OK for 2.2.x. + */ + if (!inode->i_size) + return -EINVAL; + offset += inode->i_size; + break; + + case 1: + offset += file->f_pos; + } + + /* + * No reason to seek beyond end of file for what we have on procfs. + * XXX: Assume that files for which we don't have a size are small. + */ + if (offset < 0 || offset > (inode->i_size ?: 0x10000000)) + return -EINVAL; + + if (offset != file->f_pos) { + file->f_pos = offset; + file->f_reada = 0; + } + + return offset; } /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/proc/omirr.c linux.22p1/fs/proc/omirr.c --- linux.vanilla/fs/proc/omirr.c Sun Mar 25 17:30:58 2001 +++ linux.22p1/fs/proc/omirr.c Fri Aug 16 00:19:07 2002 @@ -112,7 +112,7 @@ if(!count) goto done; error = -EINVAL; - if(!buf || count < 0) + if(!buf || count > INT_MAX) goto done; error = verify_area(VERIFY_WRITE, buf, count); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/proc/proc_tty.c linux.22p1/fs/proc/proc_tty.c --- linux.vanilla/fs/proc/proc_tty.c Sun Mar 25 17:30:58 2001 +++ linux.22p1/fs/proc/proc_tty.c Fri Aug 16 00:19:07 2002 @@ -36,10 +36,15 @@ { int len = 0; off_t begin = 0; + off_t end; struct tty_driver *p; char range[20], deftype[20]; char *type; + end = off + count; /* XXX: undefined on overflow per ISO C99 */ + if (end < off) + return -EINVAL; + for (p = tty_drivers; p; p = p->next) { if (p->num > 1) sprintf(range, "%d-%d", p->minor_start, @@ -82,7 +87,7 @@ len += sprintf(page+len, "%-20s /dev/%-8s %3d %7s %s\n", p->driver_name ? p->driver_name : "unknown", p->name, p->major, range, type); - if (len+begin > off+count) + if (len+begin > end) break; if (len+begin < off) { begin += len; @@ -106,13 +111,18 @@ int i; int len = 0; off_t begin = 0; + off_t end; + + end = off + count; /* XXX: undefined on overflow per ISO C99 */ + if (end < off) + return -EINVAL; for (i=0; i < NR_LDISCS; i++) { if (!(ldiscs[i].flags & LDISC_FLAG_DEFINED)) continue; len += sprintf(page+len, "%-10s %2d\n", ldiscs[i].name ? ldiscs[i].name : "???", i); - if (len+begin > off+count) + if (len+begin > end) break; if (len+begin < off) { begin += len; @@ -178,7 +188,14 @@ if (!ent) return; proc_tty_ldisc = create_proc_entry("tty/ldisc", S_IFDIR, 0); - proc_tty_driver = create_proc_entry("tty/driver", S_IFDIR, 0); + /* + * /proc/tty/driver/serial reveals the exact character counts for + * serial links which is just too easy to abuse for inferring + * password lengths and inter-keystroke timings during password + * entry. + */ + proc_tty_driver = create_proc_entry("tty/driver", + S_IFDIR | S_IRUSR | S_IXUSR, 0); ent = create_proc_entry("tty/ldiscs", 0, 0); ent->read_proc = tty_ldiscs_read_proc; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/select.c linux.22p1/fs/select.c --- linux.vanilla/fs/select.c Sun Mar 25 17:30:58 2001 +++ linux.22p1/fs/select.c Fri Aug 16 00:20:56 2002 @@ -412,7 +412,7 @@ lock_kernel(); /* Do a sanity check on nfds ... */ err = -EINVAL; - if (nfds > current->files->max_fds) + if (nfds > current->files->max_fds || nfds > 0x100000) goto out; if (timeout) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-i386/ioctls.h linux.22p1/include/asm-i386/ioctls.h --- linux.vanilla/include/asm-i386/ioctls.h Sun Mar 25 17:31:05 2001 +++ linux.22p1/include/asm-i386/ioctls.h Fri Aug 16 00:10:51 2002 @@ -6,7 +6,7 @@ /* 0x54 is just a magic number to make these relatively unique ('T') */ #define TCGETS 0x5401 -#define TCSETS 0x5402 +#define TCSETS 0x5402 /* Clashes with SNDCTL_TMR_START sound ioctl */ #define TCSETSW 0x5403 #define TCSETSF 0x5404 #define TCGETA 0x5405 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/stat.h linux.22p1/include/linux/stat.h --- linux.vanilla/include/linux/stat.h Sun Mar 25 17:31:03 2001 +++ linux.22p1/include/linux/stat.h Fri Aug 16 00:21:25 2002 @@ -52,6 +52,7 @@ #define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH) #define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH) #define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH) +#define S_IRXUG (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP) #endif #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/kernel/module.c linux.22p1/kernel/module.c --- linux.vanilla/kernel/module.c Fri Nov 2 16:39:16 2001 +++ linux.22p1/kernel/module.c Fri Aug 16 00:21:44 2002 @@ -937,6 +937,11 @@ int len = 0; /* code from net/ipv4/proc.c */ off_t pos = 0; off_t begin = 0; + off_t end; + + end = offset + length; /* XXX: undefined on overflow per ISO C99 */ + if (end < offset) + return -EINVAL; for (mod = module_list; mod; mod = mod->next) { unsigned i; @@ -963,7 +968,7 @@ begin = pos; } pos = begin + len; - if (pos > offset+length) + if (pos > end) goto leave_the_loop; } } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/kernel/printk.c linux.22p1/kernel/printk.c --- linux.vanilla/kernel/printk.c Sun Mar 25 17:31:02 2001 +++ linux.22p1/kernel/printk.c Fri Aug 16 00:22:03 2002 @@ -260,7 +260,7 @@ spin_lock_irqsave(&console_lock, flags); va_start(args, fmt); - i = vsprintf(buf + 3, fmt, args); /* hopefully i < sizeof(buf)-4 */ + i = _vsnprintf(buf + 3, sizeof(buf) - sizeof(buf) / 8 - 3, fmt, args); buf_end = buf + 3 + i; va_end(args); for (p = buf + 3; p < buf_end; p++) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/kernel/sys.c linux.22p1/kernel/sys.c --- linux.vanilla/kernel/sys.c Sun Mar 25 17:37:40 2001 +++ linux.22p1/kernel/sys.c Fri Aug 16 00:22:19 2002 @@ -507,8 +507,8 @@ if (euid != current->euid) current->dumpable = 0; current->euid = euid; - current->fsuid = euid; } + current->fsuid = current->euid; if (suid != (uid_t) -1) current->suid = suid; @@ -554,8 +554,8 @@ if (egid != current->egid) current->dumpable = 0; current->egid = egid; - current->fsgid = egid; } + current->fsgid = current->egid; if (sgid != (gid_t) -1) current->sgid = sgid; return 0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/kernel/sysctl.c linux.22p1/kernel/sysctl.c --- linux.vanilla/kernel/sysctl.c Sun Mar 25 17:37:40 2001 +++ linux.22p1/kernel/sysctl.c Fri Aug 16 00:22:19 2002 @@ -338,8 +338,11 @@ size_t old_len; if (!oldlenp) return -EFAULT; - if(get_user(old_len, oldlenp)) + if (get_user(old_len, oldlenp)) return -EFAULT; + /* XXX: insufficient for SMP, but should be redundant anyway */ + if ((ssize_t)old_len < 0) + return -EINVAL; } tmp = &root_table_header; do { @@ -459,7 +462,8 @@ * zero, proceed with automatic r/w */ if (table->data && table->maxlen) { if (oldval && oldlenp) { - get_user(len, oldlenp); + if (get_user(len, oldlenp)) + return -EFAULT; if (len) { if (len > table->maxlen) len = table->maxlen; @@ -853,7 +857,7 @@ vleft = table->maxlen / sizeof(int); left = *lenp; - for (; left && vleft--; i++, first=0) { + for (; left && vleft--; i++, min++, max++, first=0) { if (write) { while (left) { char c; @@ -889,9 +893,7 @@ buffer += len; left -= len; - if (min && val < *min++) - continue; - if (max && val > *max++) + if ((min && val < *min) || (max && val > *max)) continue; *i = val; } else { @@ -1047,7 +1049,8 @@ for (i = 0; i < length; i++) { int value; - get_user(value, vec + i); + if (get_user(value, vec + i)) + return -EFAULT; if (min && value < min[i]) return -EINVAL; if (max && value > max[i]) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/lib/vsprintf.c linux.22p1/lib/vsprintf.c --- linux.vanilla/lib/vsprintf.c Sun Mar 25 17:31:02 2001 +++ linux.22p1/lib/vsprintf.c Fri Aug 16 00:22:19 2002 @@ -142,7 +142,7 @@ /* Forward decl. needed for IP address printing stuff... */ int sprintf(char * buf, const char *fmt, ...); -int vsprintf(char *buf, const char *fmt, va_list args) +int _vsnprintf(char *buf, int n, const char *fmt, va_list args) { int len; unsigned long num; @@ -157,7 +157,7 @@ number of chars for from string */ int qualifier; /* 'h', 'l', or 'L' for integer fields */ - for (str=buf ; *fmt ; ++fmt) { + for (str = buf; *fmt && (n == -1 || str - buf < n); ++fmt) { if (*fmt != '%') { *str++ = *fmt; continue; @@ -231,6 +231,12 @@ len = strnlen(s, precision); + if (n != -1 && len >= n - (str - buf)) { + len = n - 1 - (str - buf); + if (len <= 0) break; + if (len < field_width) field_width = len; + } + if (!(flags & LEFT)) while (len < field_width--) *str++ = ' '; @@ -306,6 +312,11 @@ return str-buf; } +int vsprintf(char *buf, const char *fmt, va_list args) +{ + return _vsnprintf(buf, -1, fmt, args); +} + int sprintf(char * buf, const char *fmt, ...) { va_list args; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/core/neighbour.c linux.22p1/net/core/neighbour.c --- linux.vanilla/net/core/neighbour.c Sun Mar 25 17:31:12 2001 +++ linux.22p1/net/core/neighbour.c Fri Aug 16 00:01:53 2002 @@ -621,11 +621,11 @@ if (skb) { if (skb_queue_len(&neigh->arp_queue) >= neigh->parms->queue_len) { struct sk_buff *buff; - buff = neigh->arp_queue.prev; + buff = neigh->arp_queue.next; __skb_unlink(buff, &neigh->arp_queue); kfree_skb(buff); } - __skb_queue_head(&neigh->arp_queue, skb); + __skb_queue_tail(&neigh->arp_queue, skb); } end_bh_atomic(); return 1; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv4/ip_fw.c linux.22p1/net/ipv4/ip_fw.c --- linux.vanilla/net/ipv4/ip_fw.c Sun Mar 25 17:31:12 2001 +++ linux.22p1/net/ipv4/ip_fw.c Fri Aug 16 00:22:41 2002 @@ -747,6 +747,7 @@ src_port, dst_port, count, tcpsyn)) { ret = FW_BLOCK; + cleanup(chain, 0, slot); goto out; } break; @@ -1132,8 +1133,13 @@ unsigned int i; struct ip_chain *label = kmalloc(SIZEOF_STRUCT_IP_CHAIN, GFP_KERNEL); - if (label == NULL) - panic("Can't kmalloc for firewall chains.\n"); + if (label == NULL) { + /* Only pre-defined chains are created with a non-zero ref */ + if (ref) + panic("Can't kmalloc for firewall chains.\n"); + else + return NULL; + } strcpy(label->label,name); label->next = NULL; label->chain = NULL; @@ -1171,7 +1177,7 @@ * user defined chain * * and therefore can be * deleted */ - return 0; + return tmp->next ? 0 : ENOMEM; } /* This function simply changes the policy on one of the built in diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/scripts/Menuconfig linux.22p1/scripts/Menuconfig --- linux.vanilla/scripts/Menuconfig Sun Mar 25 17:31:56 2001 +++ linux.22p1/scripts/Menuconfig Fri Aug 16 00:12:49 2002 @@ -54,7 +54,7 @@ # Change a lot of places to call set_x_info uniformly. # Take out message about preparing version (old sound driver cruft). # -# 13 Dec 1998, Riley H Williams +# 13 Dec 1998, Riley H Williams # When an error occurs, actually display the error message as well as # our comments thereon. #