N: Ray Dassen
E: jdassen@wi.LeidenUniv.nl
W: http://www.wi.leidenuniv.nl/~jdassen/
+P: 1024/672D05C1 DD 60 32 60 F7 90 64 80 E7 6F D4 E4 F8 C9 4A 58
D: Debian GNU/Linux: www.debian.org maintainer, FAQ co-maintainer,
D: packages testing, nit-picking & fixing. Enjoying BugFree (TM) kernels.
S: Zuidsingel 10A
VERSION = 2
PATCHLEVEL = 1
-SUBLEVEL = 2
+SUBLEVEL = 3
ARCH = i386
X(__remlu),
X(__divqu),
X(__remqu),
- X(insl),
+ X(insb),
X(insw),
- X(outsl),
+ X(insl),
+ X(outsb),
X(outsw),
+ X(outsl),
X(strcat),
X(strcmp),
X(strcpy),
switch (el.c->size) {
case sizeof(struct el_lca_mcheck_short):
printk(KERN_CRIT
- " Reason: %s (short frame%s, dc_stat=%lx):\pn",
+ " Reason: %s (short frame%s, dc_stat=%lx):\n",
reason, el.c->retry ? ", retryable" : "", el.s->dc_stat);
if (el.s->esr & ESR_EAV) {
mem_error(el.s->esr, el.s->ear);
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/malloc.h>
-#include <linux/ldt.h>
#include <linux/user.h>
#include <linux/a.out.h>
#include <linux/utsname.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/malloc.h>
-#include <linux/ldt.h>
#include <linux/user.h>
#include <linux/a.out.h>
#include <linux/utsname.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/malloc.h>
-#include <linux/ldt.h>
#include <linux/user.h>
#include <linux/a.out.h>
#include <linux/tty.h>
#include <linux/elfcore.h>
#include <asm/semaphore.h>
+#include <asm/processor.h>
#include <asm/io.h>
extern void dump_thread(struct pt_regs *, struct user *);
static struct symbol_table arch_symbol_table = {
#include <linux/symtab_begin.h>
/* platform dependent support */
+ X(EISA_bus),
+ X(wp_works_ok),
X(dump_thread),
X(dump_fpu),
X(ioremap),
0x242 in div_Xsig.S
*/
-void exception(int n)
+void FPU_exception(int n)
{
int i, int_type;
}
else
{
- exception(flags);
+ EXCEPTION(flags);
return 1;
}
}
if ( control_word & CW_Precision )
partial_status |= (SW_Precision | SW_C1); /* The masked response */
else
- exception(EX_Precision | SW_C1);
+ EXCEPTION(EX_Precision | SW_C1);
}
partial_status |= SW_Precision;
}
else
- exception(EX_Precision);
+ EXCEPTION(EX_Precision);
}
}
else
{
- exception(EX_Denormal);
+ EXCEPTION(EX_Denormal);
return 1;
}
}
#ifdef DEBUG
#define EXCEPTION(x) { printk("exception in %s at line %d\n", \
- __FILE__, __LINE__); exception(x); }
+ __FILE__, __LINE__); FPU_exception(x); }
#else
-#define EXCEPTION(x) exception(x)
+#define EXCEPTION(x) FPU_exception(x)
#endif
#endif __ASSEMBLY__
#include <linux/linkage.h>
-#define EXCEPTION SYMBOL_NAME(exception)
+#define EXCEPTION SYMBOL_NAME(FPU_exception)
#define PARAM1 8(%ebp)
extern void stack_underflow_i(int i);
extern void stack_underflow_pop(int i);
extern int set_precision_flag(int flags);
-asmlinkage void exception(int n);
+asmlinkage void FPU_exception(int n);
asmlinkage int real_2op_NaN(FPU_REG const *a, FPU_REG const *b, FPU_REG *dest);
asmlinkage int arith_invalid(FPU_REG *dest);
asmlinkage int divide_by_zero(int sign, FPU_REG *dest);
je L_ok
pushl $0x220
- call SYMBOL_NAME(exception)
+ call SYMBOL_NAME(FPU_exception)
addl $4,%esp
L_ok:
je L_ok_nuo
pushl $0x221
- call SYMBOL_NAME(exception)
+ call SYMBOL_NAME(FPU_exception)
addl $4,%esp
L_ok_nuo:
/* There must be a masked underflow */
push %eax
pushl EX_Underflow
- call SYMBOL_NAME(exception)
+ call SYMBOL_NAME(FPU_exception)
popl %eax
popl %eax
jmp xL_Normalised
push %eax
pushl EX_Underflow
- call SYMBOL_NAME(exception)
+ call SYMBOL_NAME(FPU_exception)
popl %eax
popl %eax
extern void die_if_kernel(const char *,struct pt_regs *,long);
+/*
+ * Ugly, ugly, but the goto's result in better assembly..
+ */
+int __verify_write(const void * addr, unsigned long size)
+{
+ struct vm_area_struct * vma;
+ unsigned long start = (unsigned long) addr;
+
+ if (!size)
+ return 0;
+
+ vma = find_vma(current->mm, start);
+ if (!vma)
+ goto bad_area;
+ if (vma->vm_start > start)
+ goto check_stack;
+
+good_area:
+ if (!(vma->vm_flags & VM_WRITE))
+ goto bad_area;
+ size--;
+ size += start & ~PAGE_MASK;
+ size >>= PAGE_SHIFT;
+ start &= PAGE_MASK;
+
+ for (;;) {
+ do_wp_page(current, vma, start, 1);
+ if (!size)
+ break;
+ size--;
+ start += PAGE_SIZE;
+ if (start < vma->vm_end)
+ continue;
+ vma = vma->vm_next;
+ if (!vma || vma->vm_start != start)
+ goto bad_area;
+ if (!(vma->vm_flags & VM_WRITE))
+ goto bad_area;;
+ }
+ return 0;
+
+check_stack:
+ if (!(vma->vm_flags & VM_GROWSDOWN))
+ goto bad_area;
+ if (expand_stack(vma, start) == 0)
+ goto good_area;
+
+bad_area:
+ return -EFAULT;
+}
+
/*
* This routine handles page faults. It determines the address,
* and the problem, and then passes it off to one of the appropriate
#include <linux/symtab_end.h>
};
+static struct proc_dir_entry proc_md = {
+ PROC_MD, 6, "mdstat",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+};
static void md_geninit (struct gendisk *gdisk)
{
blksize_size[MAJOR_NR] = md_blocksizes;
register_symtab (&md_symbol_table);
- proc_register(&proc_root,
- &(struct proc_dir_entry)
- {
- PROC_MD, 6, "mdstat",
- S_IFREG | S_IRUGO, 1, 0, 0,
- });
+ proc_register(&proc_root, &proc_md);
}
#include <linux/symtab_end.h>
};
+static struct proc_dir_entry proc_misc = {
+ 0, 4, "misc",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, NULL /* ops -- default to array */,
+ &proc_misc_read /* get_info */,
+};
+
int misc_init(void)
{
#ifndef MODULE
#ifdef CONFIG_PROC_FS
- proc_register_dynamic(&proc_root, &(struct proc_dir_entry) {
- 0, 4, "misc",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, NULL /* ops -- default to array */,
- &proc_misc_read /* get_info */,
- });
+ proc_register_dynamic(&proc_root, &proc_misc);
#endif /* PROC_FS */
#ifdef CONFIG_BUSMOUSE
bus_mouse_init();
} /* ifc_init */
-static void report_exception(unsigned n)
+static void report_qic_exception(unsigned n)
{
- if (n >= NR_OF_EXC) { tpqputs(TPQD_ALWAYS, "Oops -- report_exception"); n = 0; }
+ if (n >= NR_OF_EXC) { tpqputs(TPQD_ALWAYS, "Oops -- report_qic_exception"); n = 0; }
if (TPQDBG(SENSE_TEXT) || n==0)
printk(TPQIC02_NAME ": sense: %s\n", exception_list[n].msg);
-} /* report_exception */
+} /* report_qic_exception */
/* Try to map the drive-exception bits `s' to a predefined "exception number",
* exception table (`exception_list[]').
* It is assumed that s!=0.
*/
-static int decode_exception_nr(unsigned s)
+static int decode_qic_exception_nr(unsigned s)
{
int i;
if ((s & exception_list[i].mask)==exception_list[i].code)
return i;
}
- printk(TPQIC02_NAME ": decode_exception_nr: exception(%x) not recognized\n", s);
+ printk(TPQIC02_NAME ": decode_qic_exception_nr: exception(%x) not recognized\n", s);
return 0;
-} /* decode_exception_nr */
+} /* decode_qic_exception_nr */
#ifdef OBSOLETE
/* Perform appropriate action for certain exceptions.
* should return a value to indicate stop/continue (in case of bad blocks)
*/
-static void handle_exception(int exnr, int exbits)
+static void handle_qic_exception(int exnr, int exbits)
{
if (exnr==EXC_NCART) {
/* Cartridge was changed. Redo sense().
doing_read = NO;
} else if (exnr==EXC_FM)
doing_read = NO;
-} /* handle_exception */
+} /* handle_qic_exception */
static inline int is_exception(void)
if (err & (TP_ST0|TP_ST1)) {
/* My Wangtek occasionally reports `status' 1212 which should be ignored. */
- exnr = decode_exception_nr(err);
- handle_exception(exnr, err); /* update driver state wrt drive status */
- report_exception(exnr);
+ exnr = decode_qic_exception_nr(err);
+ handle_qic_exception(exnr, err); /* update driver state wrt drive status */
+ report_qic_exception(exnr);
}
err &= ~ignore; /* mask unwanted errors -- not the correct way, use exception nrs?? */
if (((err & TP_ST0) && (err & REPORT_ERR0)) ||
tristate 'ICL EtherTeam 16i/32 support' CONFIG_ETH16I
fi
tristate 'NE2000/NE1000 support' CONFIG_NE2000
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- tristate 'NI5210 support' CONFIG_NI52
- bool 'NI6510 support' CONFIG_NI65
- fi
+ tristate 'NI5210 support' CONFIG_NI52
+ tristate 'NI6510 support' CONFIG_NI65
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
bool 'SEEQ8005 support (EXPERIMENTAL)' CONFIG_SEEQ8005
fi
ifeq ($(CONFIG_NI65),y)
L_OBJS += ni65.o
+else
+ ifeq ($(CONFIG_NI65),m)
+ M_OBJS += ni65.o
+ endif
endif
ifeq ($(CONFIG_ELPLUS),y)
#ifdef CONFIG_NI52
&& ni52_probe(dev)
#endif
+#ifdef CONFIG_NI65
+ && ni65_probe(dev)
+#endif
#ifdef CONFIG_ATARILANCE /* Lance-based Atari ethernet boards */
&& atarilance_probe(dev)
#endif
* This is an extension to the Linux operating system, and is covered by the
* same Gnu Public License that covers that work.
*
- * Alphacode 0.80 (96/02/19) for Linux 1.3.66 (or later)
+ * Alphacode 0.82 (96/09/29) for Linux 2.0.0 (or later)
* Copyrights (c) 1994,1995,1996 by M.Hipp (Michael.Hipp@student.uni-tuebingen.de)
* [feel free to mail ....]
*
* when using as module: (no autoprobing!)
- * compile with: gcc -D__KERNEL__ -DMODULE -O2 -c ni52.c
- * run with e.g: insmod ni52.o io=0x360 irq=9 memstart=0xd0000 memend=0xd4000
+ * compile with:
+ * gcc -O2 -fomit-frame-pointer -m486 -D__KERNEL__ -DMODULE -c ni52.c
+ * run with e.g:
+ * insmod ni52.o io=0x360 irq=9 memstart=0xd0000 memend=0xd4000
*
* CAN YOU PLEASE REPORT ME YOUR PERFORMANCE EXPERIENCES !!.
*
*/
/*
+ * 29.Sept.96: virt_to_bus changes for new memory scheme
* 19.Feb.96: more Mcast changes, module support (MH)
*
* 18.Nov.95: Mcast changes (AC).
#define ni_enaint() {outb(0,dev->base_addr+NI52_INTENA);}
#define make32(ptr16) (p->memtop + (short) (ptr16) )
-#define make24(ptr32) ((char *) (ptr32) - p->base)
-#define make16(ptr32) ((unsigned short) ((unsigned long) (ptr32) - (unsigned long) p->memtop ))
+#define make24(ptr32) ( ((char *) (ptr32)) - p->base)
+#define make16(ptr32) ((unsigned short) ((unsigned long)(ptr32) - (unsigned long) p->memtop ))
/******************* how to calculate the buffers *****************************
char *iscp_addrs[2];
int i;
- p->base = (unsigned long) where + size - 0x01000000;
- p->memtop = where + size;
+ p->base = (unsigned long) bus_to_virt((unsigned long)where) + size - 0x01000000;
+ p->memtop = bus_to_virt((unsigned long)where) + size;
p->scp = (struct scp_struct *)(p->base + SCP_DEFAULT_ADDRESS);
memset((char *)p->scp,0, sizeof(struct scp_struct));
for(i=0;i<sizeof(struct scp_struct);i++) /* memory was writeable? */
if(p->scp->sysbus != SYSBUSVAL)
return 0;
- iscp_addrs[0] = where;
+ iscp_addrs[0] = bus_to_virt((unsigned long)where);
iscp_addrs[1]= (char *) p->scp - sizeof(struct iscp_struct);
for(i=0;i<2;i++)
DELAY(1);
p->scp = (struct scp_struct *) (p->base + SCP_DEFAULT_ADDRESS);
- p->scb = (struct scb_struct *) (dev->mem_start);
+ p->scb = (struct scb_struct *) bus_to_virt(dev->mem_start);
p->iscp = (struct iscp_struct *) ((char *)p->scp - sizeof(struct iscp_struct));
memset((char *) p->iscp,0,sizeof(struct iscp_struct));
/* warning: we don't free it on errors */
memset((char *) dev->priv,0,sizeof(struct priv));
- ((struct priv *) (dev->priv))->memtop = (char *) dev->mem_start + size;
- ((struct priv *) (dev->priv))->base = dev->mem_start + size - 0x01000000;
+ ((struct priv *) (dev->priv))->memtop = bus_to_virt(dev->mem_start) + size;
+ ((struct priv *) (dev->priv))->base = (unsigned long) bus_to_virt(dev->mem_start) + size - 0x01000000;
alloc586(dev);
/* set number of receive-buffs according to memsize */
/*
- * ni6510 (am7990 'lance' chip) driver for Linux-net-3 by MH
- * Alphacode v0.51 (96/02/20) for 1.3.66 (or later)
+ * ni6510 (am7990 'lance' chip) driver for Linux-net-3
+ * BETAcode v0.71 (96/09/29) for 2.0.0 (or later)
+ * copyrights (c) 1994,1995,1996 by M.Hipp
+ *
+ * This driver can handle the old ni6510 board and the newer ni6510
+ * EtherBlaster. (probably it also works with every full NE2100
+ * compatible card)
*
- * copyright (c) 1994,1995,1996 by M.Hipp
+ * To compile as module, type:
+ * gcc -O2 -fomit-frame-pointer -m486 -D__KERNEL__ -DMODULE -c ni65.c
+ * driver probes: io: 0x360,0x300,0x320,0x340 / dma: 3,5,6,7
*
* This is an extension to the Linux operating system, and is covered by the
* same Gnu Public License that covers the Linux-kernel.
* and from the original drivers by D.Becker
*
* known problems:
- * on some PCI boards (including my own) the card/board/ISA-bridge has
- * problems with bus master DMA. This results in lotsa overruns.
- * It may help to '#define RCV_PARANOIA_CHECK'
- * or just play with your BIOS options to optimize ISA-DMA access.
+ * - on some PCI boards (including my own) the card/board/ISA-bridge has
+ * problems with bus master DMA. This results in lotsa overruns.
+ * It may help to '#define RCV_PARANOIA_CHECK' or try to #undef
+ * the XMT and RCV_VIA_SKB option .. this reduces driver performance.
+ * Or just play with your BIOS options to optimize ISA-DMA access.
+ * Maybe you also wanna play with the LOW_PERFORAMCE and MID_PERFORMANCE
+ * defines -> please report me your experience then
+ * - Harald reported for ASUS SP3G mainboards, that you should use
+ * the 'optimal settings' from the user's manual on page 3-12!
*
* credits:
* thanx to Jason Sullivan for sending me a ni6510 card!
+ * lot of debug runs with ASUS SP3G Boards (Intel Saturn) by Harald Koenig
*
- * simple performance test:
- * 8.1 seconds for getting a 8MB file via FTP -> near 1MB/s
+ * simple performance test: (486DX-33/Ni6510-EB receives from 486DX4-100/Ni6510-EB)
+ * average: FTP -> 8384421 bytes received in 8.5 seconds
+ * (no RCV_VIA_SKB,no XMT_VIA_SKB,PARANOIA_CHECK,4 XMIT BUFS, 8 RCV_BUFFS)
+ * peak: FTP -> 8384421 bytes received in 7.5 seconds
+ * (RCV_VIA_SKB,XMT_VIA_SKB,no PARANOIA_CHECK,1(!) XMIT BUF, 16 RCV BUFFS)
*/
/*
- * 96.Feb.19: fixed a few bugs .. cleanups .. tested for 1.3.66
+ * 96.Sept.29: virt_to_bus stuff added for new memory modell
+ * 96.April.29: Added Harald Koenig's Patches (MH)
+ * 96.April.13: enhanced error handling .. more tests (MH)
+ * 96.April.5/6: a lot of performance tests. Got it stable now (hopefully) (MH)
+ * 96.April.1: (no joke ;) .. added EtherBlaster and Module support (MH)
+ * 96.Feb.19: fixed a few bugs .. cleanups .. tested for 1.3.66 (MH)
* hopefully no more 16MB limit
*
* 95.Nov.18: multicast tweaked (AC).
*
* 94.Aug.22: changes in xmit_intr (ack more than one xmitted-packet), ni65_send_packet (p->lock) (MH)
*
- * 94,July.16: fixed bugs in recv_skb and skb-alloc stuff (MH)
+ * 94.July.16: fixed bugs in recv_skb and skb-alloc stuff (MH)
*/
#include <linux/kernel.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
+#include <linux/version.h>
+#include <linux/module.h>
+
#include "ni65.h"
/*
- * the current setting allows max. performance
+ * the current setting allows an acceptable performance
* for 'RCV_PARANOIA_CHECK' read the 'known problems' part in
* the header of this file
+ * 'invert' the defines for max. performance. This may cause DMA problems
+ * on some boards (e.g on my ASUS SP3G)
*/
-#define RCV_VIA_SKB
-#undef RCV_PARANOIA_CHECK
-#define XMT_VIA_SKB
+#undef XMT_VIA_SKB
+#undef RCV_VIA_SKB
+#define RCV_PARANOIA_CHECK
+
+#define MID_PERFORMANCE
+
+#if defined( LOW_PERFORMANCE )
+ static int isa0=7,isa1=7,csr80=0x0c10;
+#elif defined( MID_PERFORMANCE )
+ static int isa0=5,isa1=5,csr80=0x2810;
+#else /* high performance */
+ static int isa0=4,isa1=4,csr80=0x0017;
+#endif
/*
- * a few card specific defines
+ * a few card/vendor specific defines
*/
-#define NI65_TOTAL_SIZE 16
-#define NI65_ADDR0 0x02
-#define NI65_ADDR1 0x07
-#define NI65_ADDR2 0x01
-#define NI65_ID0 0x00
-#define NI65_ID1 0x55
+#define NI65_ID0 0x00
+#define NI65_ID1 0x55
+#define NI65_EB_ID0 0x52
+#define NI65_EB_ID1 0x44
+#define NE2100_ID0 0x57
+#define NE2100_ID1 0x57
-#define PORT dev->base_addr
+#define PORT p->cmdr_addr
/*
* buffer configuration
*/
+#if 1
+#define RMDNUM 16
+#define RMDNUMMASK 0x80000000
+#else
#define RMDNUM 8
#define RMDNUMMASK 0x60000000 /* log2(RMDNUM)<<29 */
+#endif
+
+#if 0
+#define TMDNUM 1
+#define TMDNUMMASK 0x00000000
+#else
#define TMDNUM 4
#define TMDNUMMASK 0x40000000 /* log2(TMDNUM)<<29 */
+#endif
-#define R_BUF_SIZE 1536
-#define T_BUF_SIZE 1536
+/* slightly oversized */
+#define R_BUF_SIZE 1544
+#define T_BUF_SIZE 1544
/*
* lance register defines
*/
#define L_DATAREG 0x00
#define L_ADDRREG 0x02
-
#define L_RESET 0x04
#define L_CONFIG 0x05
-#define L_EBASE 0x08
+#define L_BUSIF 0x06
/*
- * to access the am7990-regs, you have to write
+ * to access the lance/am7990-regs, you have to write
* reg-number into L_ADDRREG, then you can access it using L_DATAREG
*/
-#define CSR0 0x00
-#define CSR1 0x01
-#define CSR2 0x02
-#define CSR3 0x03
+#define CSR0 0x00
+#define CSR1 0x01
+#define CSR2 0x02
+#define CSR3 0x03
+
+#define INIT_RING_BEFORE_START 0x1
+#define FULL_RESET_ON_ERROR 0x2
+#if 0
#define writereg(val,reg) {outw(reg,PORT+L_ADDRREG);inw(PORT+L_ADDRREG); \
outw(val,PORT+L_DATAREG);inw(PORT+L_DATAREG);}
#define readreg(reg) (outw(reg,PORT+L_ADDRREG),inw(PORT+L_ADDRREG),\
inw(PORT+L_DATAREG))
+#if 0
#define writedatareg(val) {outw(val,PORT+L_DATAREG);inw(PORT+L_DATAREG);}
+#else
+#define writedatareg(val) { writereg(val,CSR0); }
+#endif
+#else
+#define writereg(val,reg) {outw(reg,PORT+L_ADDRREG);outw(val,PORT+L_DATAREG);}
+#define readreg(reg) (outw(reg,PORT+L_ADDRREG),inw(PORT+L_DATAREG))
+#define writedatareg(val) { writereg(val,CSR0); }
+#endif
-static int ni65_probe1(struct device **dev,int);
-static void ni65_interrupt(int irq, void * dev_id, struct pt_regs *regs);
-static void ni65_recv_intr(struct device *dev,int);
-static void ni65_xmit_intr(struct device *dev,int);
-static int ni65_open(struct device *dev);
-static int ni65_am7990_reinit(struct device *dev);
-static int ni65_send_packet(struct sk_buff *skb, struct device *dev);
-static int ni65_close(struct device *dev);
-static struct enet_statistics *ni65_get_stats(struct device *);
-static void set_multicast_list(struct device *dev);
+static unsigned char ni_vendor[] = { 0x02,0x07,0x01 };
+
+static struct card {
+ unsigned char id0,id1;
+ short id_offset;
+ short total_size;
+ short cmd_offset;
+ short addr_offset;
+ unsigned char *vendor_id;
+ char *cardname;
+ unsigned char config;
+} cards[] = {
+ { NI65_ID0,NI65_ID1,0x0e,0x10,0x0,0x8,ni_vendor,"ni6510", 0x1 } ,
+ { NI65_EB_ID0,NI65_EB_ID1,0x0e,0x18,0x10,0x0,ni_vendor,"ni6510 EtherBlaster", 0x2 } ,
+ { NE2100_ID0,NE2100_ID1,0x0e,0x18,0x10,0x0,NULL,"generic NE2100", 0x0 }
+};
+#define NUM_CARDS 3
struct priv
{
struct sk_buff *tmd_skb[TMDNUM];
#endif
void *tmdbounce[TMDNUM];
+ int tmdbouncenum;
int lock,xmit_queued;
struct enet_statistics stats;
+ void *self;
+ int cmdr_addr;
+ int cardno;
+ int features;
};
+static int ni65_probe1(struct device *dev,int);
+static void ni65_interrupt(int irq, void * dev_id, struct pt_regs *regs);
+static void ni65_recv_intr(struct device *dev,int);
+static void ni65_xmit_intr(struct device *dev,int);
+static int ni65_open(struct device *dev);
+static int ni65_lance_reinit(struct device *dev);
+static void ni65_init_lance(struct priv *p,unsigned char*,int,int);
+static int ni65_send_packet(struct sk_buff *skb, struct device *dev);
+static int ni65_close(struct device *dev);
+static int ni65_alloc_buffer(struct device *dev);
+static void ni65_free_buffer(struct priv *p);
+static struct enet_statistics *ni65_get_stats(struct device *);
+static void set_multicast_list(struct device *dev);
+
static int irqtab[] = { 9,12,15,5 }; /* irq config-translate */
-static int dmatab[] = { 0,3,5,6 }; /* dma config-translate */
-static int debuglevel = 0;
+static int dmatab[] = { 0,3,5,6,7 }; /* dma config-translate and autodetect */
+
+static int debuglevel = 1;
/*
- * open (most done by init)
+ * set 'performance' registers .. we must STOP lance for that
+ */
+static void ni65_set_performance(struct priv *p)
+{
+ writereg(CSR0_STOP | CSR0_CLRALL,CSR0); /* STOP */
+
+ if( !(cards[p->cardno].config & 0x02) )
+ return;
+
+ outw(80,PORT+L_ADDRREG);
+ if(inw(PORT+L_ADDRREG) != 80)
+ return;
+
+ writereg( (csr80 & 0x3fff) ,80); /* FIFO watermarks */
+ outw(0,PORT+L_ADDRREG);
+ outw((short)isa0,PORT+L_BUSIF); /* write ISA 0: DMA_R : isa0 * 50ns */
+ outw(1,PORT+L_ADDRREG);
+ outw((short)isa1,PORT+L_BUSIF); /* write ISA 1: DMA_W : isa1 * 50ns */
+
+ outw(CSR0,PORT+L_ADDRREG); /* switch back to CSR0 */
+}
+
+/*
+ * open interface (up)
*/
static int ni65_open(struct device *dev)
{
- if(ni65_am7990_reinit(dev))
+ struct priv *p = (struct priv *) dev->priv;
+ int irqval = request_irq(dev->irq, &ni65_interrupt,0,
+ cards[p->cardno].cardname,NULL);
+ if (irqval) {
+ printk ("%s: unable to get IRQ %d (irqval=%d).\n",
+ dev->name,dev->irq, irqval);
+ return -EAGAIN;
+ }
+ irq2dev_map[dev->irq] = dev;
+
+ if(ni65_lance_reinit(dev))
{
dev->tbusy = 0;
dev->interrupt = 0;
dev->start = 1;
+ MOD_INC_USE_COUNT;
return 0;
}
else
{
+ irq2dev_map[dev->irq] = NULL;
+ free_irq(dev->irq,NULL);
dev->start = 0;
return -EAGAIN;
}
}
+/*
+ * close interface (down)
+ */
static int ni65_close(struct device *dev)
{
- outw(0,PORT+L_RESET); /* that's the hard way */
+ struct priv *p = (struct priv *) dev->priv;
+
+ outw(inw(PORT+L_RESET),PORT+L_RESET); /* that's the hard way */
+
+#ifdef XMT_VIA_SKB
+ {
+ int i;
+ for(i=0;i<TMDNUM;i++)
+ {
+ if(p->tmd_skb[i]) {
+ dev_kfree_skb(p->tmd_skb[i],FREE_WRITE);
+ p->tmd_skb[i] = NULL;
+ }
+ }
+ }
+#endif
+ irq2dev_map[dev->irq] = NULL;
+ free_irq(dev->irq,NULL);
dev->tbusy = 1;
dev->start = 0;
+ MOD_DEC_USE_COUNT;
return 0;
}
/*
* Probe The Card (not the lance-chip)
- * and set hardaddress
*/
+#ifdef MODULE
+static
+#endif
int ni65_probe(struct device *dev)
{
int *port;
- static int ports[] = {0x300,0x320,0x340,0x360, 0};
+ static int ports[] = {0x360,0x300,0x320,0x340, 0};
- if(dev) {
- int base_addr = dev->base_addr;
- if (base_addr > 0x1ff) /* Check a single specified location. */
- return ni65_probe1(&dev, base_addr);
- else if (base_addr > 0) /* Don't probe at all. */
- return -ENXIO;
- dev->base_addr = base_addr;
- }
+ if (dev->base_addr > 0x1ff) /* Check a single specified location. */
+ return ni65_probe1(dev, dev->base_addr);
+ else if (dev->base_addr > 0) /* Don't probe at all. */
+ return -ENXIO;
for (port = ports; *port; port++)
{
- int ioaddr = *port;
-
- if (check_region(ioaddr, NI65_TOTAL_SIZE))
- continue;
- if( !(inb(ioaddr+L_EBASE+6) == NI65_ID0) ||
- !(inb(ioaddr+L_EBASE+7) == NI65_ID1) )
- continue;
- if (ni65_probe1(&dev, ioaddr) == 0)
+ if (ni65_probe1(dev, *port) == 0)
return 0;
}
return -ENODEV;
}
-int ni65_init(void)
-{
- ni65_probe(NULL);
- return 0;
-}
-
-static int ni65_probe1(struct device **dev1,int ioaddr)
+/*
+ * this is the real card probe ..
+ */
+static int ni65_probe1(struct device *dev,int ioaddr)
{
- int i;
- unsigned char *ptr;
+ int i,j;
struct priv *p;
- struct device *dev = *dev1;
- if(inb(ioaddr+L_EBASE+0) != NI65_ADDR0 || inb(ioaddr+L_EBASE+1) != NI65_ADDR1
- || inb(ioaddr+L_EBASE+2) != NI65_ADDR2)
- {
- printk("%s: wrong Hardaddress \n",dev ? dev->name : "ni6510" );
+ for(i=0;i<NUM_CARDS;i++) {
+ if(check_region(ioaddr, cards[i].total_size))
+ continue;
+ if(cards[i].id_offset >= 0) {
+ if(inb(ioaddr+cards[i].id_offset+0) != cards[i].id0 ||
+ inb(ioaddr+cards[i].id_offset+1) != cards[i].id1) {
+ continue;
+ }
+ }
+ if(cards[i].vendor_id) {
+ for(j=0;j<3;j++)
+ if(inb(ioaddr+cards[i].addr_offset+j) != cards[i].vendor_id[j])
+ continue;
+ }
+ break;
+ }
+ if(i == NUM_CARDS)
return -ENODEV;
+
+ for(j=0;j<6;j++)
+ dev->dev_addr[j] = inb(ioaddr+cards[i].addr_offset+j);
+
+ if( (j=ni65_alloc_buffer(dev)) < 0)
+ return j;
+ p = (struct priv *) dev->priv;
+ p->cmdr_addr = ioaddr + cards[i].cmd_offset;
+ p->cardno = i;
+
+ printk("%s: %s found at %#3x, ", dev->name, cards[p->cardno].cardname , ioaddr);
+
+ outw(inw(PORT+L_RESET),PORT+L_RESET); /* first: reset the card */
+ if( (j=readreg(CSR0)) != 0x4) {
+ printk(KERN_ERR "can't RESET card: %04x\n",j);
+ ni65_free_buffer(p);
+ return -EAGAIN;
}
- if(!dev) {
- dev = init_etherdev(0,0);
- *dev1 = dev;
+ outw(88,PORT+L_ADDRREG);
+ if(inw(PORT+L_ADDRREG) == 88) {
+ unsigned long v;
+ v = inw(PORT+L_DATAREG);
+ v <<= 16;
+ outw(89,PORT+L_ADDRREG);
+ v |= inw(PORT+L_DATAREG);
+ printk("Version %#08lx, ",v);
+ p->features = INIT_RING_BEFORE_START;
+ }
+ else {
+ printk("ancient LANCE, ");
+ p->features = 0x0;
}
- dev->base_addr = ioaddr;
- for(i=0;i<6;i++)
- dev->dev_addr[i] = inb(PORT+L_EBASE+i);
-
- if(dev->irq == 0)
- dev->irq = irqtab[(inw(PORT+L_CONFIG)>>2)&3];
- if(dev->dma == 0)
- dev->dma = dmatab[inw(PORT+L_CONFIG)&3];
-
- printk("%s: %s found at %#3lx, IRQ %d DMA %d.\n", dev->name,
- "ni6510", dev->base_addr, dev->irq,dev->dma);
-
- {
- int irqval = request_irq(dev->irq, &ni65_interrupt,0,"ni6510",NULL);
- if (irqval) {
- printk ("%s: unable to get IRQ %d (irqval=%d).\n",
- dev->name,dev->irq, irqval);
- return -EAGAIN;
+ if(test_bit(0,&cards[i].config)) {
+ dev->irq = irqtab[(inw(ioaddr+L_CONFIG)>>2)&3];
+ dev->dma = dmatab[inw(ioaddr+L_CONFIG)&3];
+ printk("IRQ %d (from card), DMA %d (from card).\n",dev->irq,dev->dma);
+ }
+ else {
+ if(dev->dma == 0) {
+ /* 'stuck test' from lance.c */
+ int dma_channels = ((inb(DMA1_STAT_REG) >> 4) & 0x0f) | (inb(DMA2_STAT_REG) & 0xf0);
+ for(i=1;i<5;i++) {
+ int dma = dmatab[i];
+ if(test_bit(dma,&dma_channels) || request_dma(dma,"ni6510"))
+ continue;
+ disable_dma(dma);
+ set_dma_mode(dma,DMA_MODE_CASCADE);
+ enable_dma(dma);
+ ni65_init_lance(p,dev->dev_addr,0,0); /* trigger memory access */
+ disable_dma(dma);
+ free_dma(dma);
+ if(readreg(CSR0) & CSR0_IDON)
+ break;
+ }
+ if(i == 5) {
+ printk("Can't detect DMA channel!\n");
+ ni65_free_buffer(p);
+ return -EAGAIN;
+ }
+ dev->dma = dmatab[i];
+ printk("DMA %d (autodetected), ",dev->dma);
}
- if(request_dma(dev->dma, "ni6510") != 0)
+ else
+ printk("DMA %d (assigned), ",dev->dma);
+
+ if(dev->irq < 2)
{
- printk("%s: Can't request dma-channel %d\n",dev->name,(int) dev->dma);
- free_irq(dev->irq,NULL);
- return -EAGAIN;
+ ni65_init_lance(p,dev->dev_addr,0,0);
+ autoirq_setup(0);
+ writereg(CSR0_INIT|CSR0_INEA,CSR0); /* trigger interrupt */
+
+ if(!(dev->irq = autoirq_report(2)))
+ {
+ printk("Failed to detect IRQ line!\n");
+ ni65_free_buffer(p);
+ return -EAGAIN;
+ }
+ printk("IRQ %d (autodetected).\n",dev->irq);
}
+ else
+ printk("IRQ %d (assigned).\n",dev->irq);
+ }
+
+ if(request_dma(dev->dma, cards[p->cardno].cardname ) != 0)
+ {
+ printk("%s: Can't request dma-channel %d\n",dev->name,(int) dev->dma);
+ ni65_free_buffer(p);
+ return -EAGAIN;
}
- irq2dev_map[dev->irq] = dev;
/*
- * Grab the region so we can find another board if autoIRQ fails.
+ * Grab the region so we can find another board.
*/
- request_region(ioaddr,NI65_TOTAL_SIZE,"ni6510");
+ request_region(ioaddr,cards[p->cardno].total_size,cards[p->cardno].cardname);
+
+ dev->base_addr = ioaddr;
dev->open = ni65_open;
dev->stop = ni65_close;
dev->tbusy = 0;
dev->start = 0;
+ return 0; /* everything is OK */
+}
+
+/*
+ * set lance register and trigger init
+ */
+static void ni65_init_lance(struct priv *p,unsigned char *daddr,int filter,int mode)
+{
+ int i;
+ u32 pib;
+
+ writereg(CSR0_CLRALL|CSR0_STOP,CSR0);
+
+ for(i=0;i<6;i++)
+ p->ib.eaddr[i] = daddr[i];
+
+ for(i=0;i<8;i++)
+ p->ib.filter[i] = filter;
+ p->ib.mode = mode;
+
+ p->ib.trp = (u32) virt_to_bus(p->tmdhead) | TMDNUMMASK;
+ p->ib.rrp = (u32) virt_to_bus(p->rmdhead) | RMDNUMMASK;
+ writereg(0,CSR3); /* busmaster/no word-swap */
+ pib = (u32) virt_to_bus(&p->ib);
+ writereg(pib & 0xffff,CSR1);
+ writereg(pib >> 16,CSR2);
+
+ writereg(CSR0_INIT,CSR0); /* this changes L_ADDRREG to CSR0 */
+
+ for(i=0;i<32;i++)
+ {
+ udelay(4000);
+ if(inw(PORT+L_DATAREG) & (CSR0_IDON | CSR0_MERR) )
+ break; /* init ok ? */
+ }
+}
+
+/*
+ * allocate memory area and check the 16MB border
+ */
+static void *ni65_alloc_mem(struct device *dev,char *what,int size,int type)
+{
+ struct sk_buff *skb=NULL;
+ unsigned char *ptr;
+ void *ret;
+
+ if(type) {
+ ret = skb = alloc_skb(2+16+size,GFP_KERNEL|GFP_DMA);
+ if(!skb) {
+ printk("%s: unable to allocate %s memory.\n",dev->name,what);
+ return NULL;
+ }
+ skb->dev = dev;
+ skb_reserve(skb,2+16);
+ skb_put(skb,R_BUF_SIZE); /* grab the whole space .. (not necessary) */
+ ptr = skb->data;
+ }
+ else {
+ ret = ptr = kmalloc(T_BUF_SIZE,GFP_KERNEL | GFP_DMA);
+ if(!ret) {
+ printk("%s: unable to allocate %s memory.\n",dev->name,what);
+ return NULL;
+ }
+ }
+ if( (u32) virt_to_bus(ptr+size) > 0x1000000) {
+ printk("%s: unable to allocate %s memory in lower 16MB!\n",dev->name,what);
+ if(type)
+ kfree_skb(skb,FREE_WRITE);
+ else
+ kfree(ptr);
+ return NULL;
+ }
+ return ret;
+}
+
+/*
+ * allocate all memory structures .. send/recv buffers etc ...
+ */
+static int ni65_alloc_buffer(struct device *dev)
+{
+ unsigned char *ptr;
+ struct priv *p;
+ int i;
+
/*
* we need 8-aligned memory ..
*/
- ptr = kmalloc(sizeof(struct priv)+8,GFP_KERNEL|GFP_DMA);
+ ptr = ni65_alloc_mem(dev,"BUFFER",sizeof(struct priv)+8,0);
if(!ptr)
return -ENOMEM;
- ptr = (unsigned char *) (((unsigned long) ptr + 7) & ~0x7);
- if( (unsigned long) ptr + sizeof(struct priv) > 0x1000000) {
- printk("%s: Can't alloc buffer in lower 16MB!\n",dev->name);
- return -EAGAIN;
- }
- p = dev->priv = (struct priv *) ptr;
+
+ p = dev->priv = (struct priv *) (((unsigned long) ptr + 7) & ~0x7);
memset((char *) dev->priv,0,sizeof(struct priv));
+ p->self = ptr;
for(i=0;i<TMDNUM;i++)
{
- if( (ptr = kmalloc(T_BUF_SIZE,GFP_KERNEL | GFP_DMA )) == NULL) {
- printk("%s: Can't alloc Xmit-Mem.\n",dev->name);
+#ifdef XMT_VIA_SKB
+ p->tmd_skb[i] = NULL;
+#endif
+ p->tmdbounce[i] = ni65_alloc_mem(dev,"XMIT",T_BUF_SIZE,0);
+ if(!p->tmdbounce[i]) {
+ ni65_free_buffer(p);
+ return -ENOMEM;
+ }
+ }
+
+ for(i=0;i<RMDNUM;i++)
+ {
+#ifdef RCV_VIA_SKB
+ p->recv_skb[i] = ni65_alloc_mem(dev,"RECV",R_BUF_SIZE,1);
+ if(!p->recv_skb[i]) {
+ ni65_free_buffer(p);
return -ENOMEM;
}
- if( (unsigned long) (ptr+T_BUF_SIZE) > 0x1000000) {
- printk("%s: Can't alloc Xmit-Mem in lower 16MB!\n",dev->name);
- return -EAGAIN;
+#else
+ p->recvbounce[i] = ni65_alloc_mem(dev,"RECV",R_BUF_SIZE,0);
+ if(!p->recvbounce[i]) {
+ ni65_free_buffer(p);
+ return -ENOMEM;
}
- p->tmdbounce[i] = ptr;
+#endif
+ }
+
+ return 0; /* everything is OK */
+}
+
+/*
+ * free buffers and private struct
+ */
+static void ni65_free_buffer(struct priv *p)
+{
+ int i;
+
+ if(!p)
+ return;
+
+ for(i=0;i<TMDNUM;i++) {
+ if(p->tmdbounce[i])
+ kfree(p->tmdbounce[i]);
#ifdef XMT_VIA_SKB
- p->tmd_skb[i] = NULL;
+ if(p->tmd_skb[i])
+ dev_kfree_skb(p->tmd_skb[i],FREE_WRITE);
#endif
}
+ for(i=0;i<RMDNUM;i++)
+ {
#ifdef RCV_VIA_SKB
- for(i=0;i<RMDNUM;i++)
- {
- struct sk_buff *skb;
- if( !(skb = dev_alloc_skb(R_BUF_SIZE+2)) ) {
- printk("%s: unable to alloc recv-mem\n",dev->name);
- return -ENOMEM;
- }
- skb->dev = dev;
- skb_reserve(skb,2);
- skb_put(skb,R_BUF_SIZE); /* grab the whole space .. (not necessary) */
- if( (unsigned long) (skb->data + R_BUF_SIZE) > 0x1000000 ) {
- printk("%s: unable to alloc receive-memory in lower 16MB!\n",dev->name);
- return -EAGAIN;
- }
- p->recv_skb[i] = skb;
- }
+ if(p->recv_skb[i])
+ dev_kfree_skb(p->recv_skb[i],FREE_WRITE);
#else
- for(i=0;i<RMDNUM;i++)
- {
- if( !(p->recvbounce[i] = kmalloc(R_BUF_SIZE,GFP_KERNEL | GFP_DMA )) ) {
- printk("%s: unable to alloc recv-mem\n",dev->name);
- return -ENOMEM;
- }
- if( (unsigned long) p->recvbounce[i] + R_BUF_SIZE > 0x1000000 ) {
- printk("%s: unable to alloc receive-memory in lower 16MB!\n",dev->name);
- return -EAGAIN;
- }
- }
+ if(p->recvbounce[i])
+ kfree(p->recvbounce[i]);
#endif
+ }
+ if(p->self)
+ kfree(p->self);
+}
+
- return 0; /* we've found everything */
+/*
+ * stop and (re)start lance .. e.g after an error
+ */
+static void ni65_stop_start(struct device *dev,struct priv *p)
+{
+ int csr0 = CSR0_INEA;
+
+ writedatareg(CSR0_STOP);
+
+ if(debuglevel > 1)
+ printk("ni65_stop_start\n");
+
+ if(p->features & INIT_RING_BEFORE_START) {
+ int i;
+#ifdef XMT_VIA_SKB
+ struct sk_buff *skb_save[TMDNUM];
+#endif
+ unsigned long buffer[TMDNUM];
+ short blen[TMDNUM];
+
+ if(p->xmit_queued) {
+ while(1) {
+ if((p->tmdhead[p->tmdlast].u.s.status & XMIT_OWN))
+ break;
+ p->tmdlast = (p->tmdlast + 1) & (TMDNUM-1);
+ if(p->tmdlast == p->tmdnum)
+ break;
+ }
+ }
+
+ for(i=0;i<TMDNUM;i++) {
+ struct tmd *tmdp = p->tmdhead + i;
+#ifdef XMT_VIA_SKB
+ skb_save[i] = p->tmd_skb[i];
+#endif
+ buffer[i] = (u32) bus_to_virt(tmdp->u.buffer);
+ blen[i] = tmdp->blen;
+ tmdp->u.s.status = 0x0;
+ }
+
+ for(i=0;i<RMDNUM;i++) {
+ struct rmd *rmdp = p->rmdhead + i;
+ rmdp->u.s.status = RCV_OWN;
+ }
+ p->tmdnum = p->xmit_queued = 0;
+ writedatareg(CSR0_STRT | csr0);
+
+ for(i=0;i<TMDNUM;i++) {
+ int num = (i + p->tmdlast) & (TMDNUM-1);
+ p->tmdhead[i].u.buffer = (u32) virt_to_bus((char *)buffer[num]); /* status is part of buffer field */
+ p->tmdhead[i].blen = blen[num];
+ if(p->tmdhead[i].u.s.status & XMIT_OWN) {
+ p->tmdnum = (p->tmdnum + 1) & (TMDNUM-1);
+ p->xmit_queued = 1;
+ writedatareg(CSR0_TDMD | CSR0_INEA | csr0);
+ }
+#ifdef XMT_VIA_SKB
+ p->tmd_skb[i] = skb_save[num];
+#endif
+ }
+ p->rmdnum = p->tmdlast = 0;
+ if(!p->lock)
+ dev->tbusy = (p->tmdnum || !p->xmit_queued) ? 0 : 1;
+ dev->trans_start = jiffies;
+ }
+ else
+ writedatareg(CSR0_STRT | csr0);
}
/*
* init lance (write init-values .. init-buffers) (open-helper)
*/
-
-static int ni65_am7990_reinit(struct device *dev)
+static int ni65_lance_reinit(struct device *dev)
{
int i;
struct priv *p = (struct priv *) dev->priv;
set_dma_mode(dev->dma,DMA_MODE_CASCADE);
enable_dma(dev->dma);
- outw(0,PORT+L_RESET); /* first: reset the card */
- if(inw(PORT+L_DATAREG) != 0x4)
+ outw(inw(PORT+L_RESET),PORT+L_RESET); /* first: reset the card */
+ if( (i=readreg(CSR0) ) != 0x4)
{
- printk(KERN_ERR "%s: can't RESET ni6510 card: %04x\n",dev->name,(int) inw(PORT+L_DATAREG));
+ printk(KERN_ERR "%s: can't RESET %s card: %04x\n",dev->name,
+ cards[p->cardno].cardname,(int) i);
disable_dma(dev->dma);
- free_dma(dev->dma);
- free_irq(dev->irq, NULL);
return 0;
}
- p->tmdnum = 0; p->tmdlast = 0;
+ p->rmdnum = p->tmdnum = p->tmdlast = p->tmdbouncenum = 0;
for(i=0;i<TMDNUM;i++)
{
struct tmd *tmdp = p->tmdhead + i;
tmdp->blen = tmdp->status2 = 0;
}
- p->rmdnum = 0;
for(i=0;i<RMDNUM;i++)
{
struct rmd *rmdp = p->rmdhead + i;
#ifdef RCV_VIA_SKB
- rmdp->u.buffer = (unsigned long) p->recv_skb[i]->data;
+ rmdp->u.buffer = (u32) virt_to_bus(p->recv_skb[i]->data);
#else
- rmdp->u.buffer = (unsigned long) p->recvbounce[i];
+ rmdp->u.buffer = (u32) virt_to_bus(p->recvbounce[i]);
#endif
rmdp->blen = -(R_BUF_SIZE-8);
rmdp->mlen = 0;
rmdp->u.s.status = RCV_OWN;
}
- for(i=0;i<6;i++)
- p->ib.eaddr[i] = dev->dev_addr[i];
-
- for(i=0;i<8;i++)
- p->ib.filter[i] = 0x0;
- p->ib.mode = 0x0;
-
- if(dev->flags & IFF_PROMISC) {
- p->ib.mode = M_PROM;
- }
- else if(dev->mc_count || dev->flags & IFF_ALLMULTI) {
- for(i=0;i<8;i++)
- p->ib.filter[i] = 0xff;
- }
-
- p->ib.trp = (unsigned long) p->tmdhead | TMDNUMMASK;
- p->ib.rrp = (unsigned long) p->rmdhead | RMDNUMMASK;
-
- writereg(0,CSR3); /* busmaster/no word-swap */
- writereg((unsigned short) (((unsigned long) &(p->ib)) & 0xffff),CSR1);
- writereg((unsigned short) (((unsigned long) &(p->ib))>>16),CSR2);
-
- writereg(CSR0_INIT,CSR0); /* this changes L_ADDRREG to CSR0 */
+ if(dev->flags & IFF_PROMISC)
+ ni65_init_lance(p,dev->dev_addr,0x00,M_PROM);
+ else if(dev->mc_count || dev->flags & IFF_ALLMULTI)
+ ni65_init_lance(p,dev->dev_addr,0xff,0x0);
+ else
+ ni65_init_lance(p,dev->dev_addr,0x00,0x00);
/*
+ * ni65_set_lance_mem() sets L_ADDRREG to CSR0
* NOW, WE WILL NEVER CHANGE THE L_ADDRREG, CSR0 IS ALWAYS SELECTED
*/
- for(i=0;i<32;i++)
- {
- __delay((loops_per_sec>>8)); /* wait a while */
- if(inw(PORT+L_DATAREG) & CSR0_IDON)
- break; /* init ok ? */
- }
- if(i == 32)
- {
- printk(KERN_ERR "%s: can't init am7990/lance, status: %04x\n",dev->name,(int) inw(PORT+L_DATAREG));
- disable_dma(dev->dma);
- free_dma(dev->dma);
- free_irq(dev->irq, NULL);
- return 0; /* false */
- }
-
- writedatareg(CSR0_CLRALL | CSR0_INEA | CSR0_STRT); /* start lance , enable interrupts */
-
- return 1; /* OK */
+ if(inw(PORT+L_DATAREG) & CSR0_IDON) {
+ ni65_set_performance(p);
+ /* init OK: start lance , enable interrupts */
+ writedatareg(CSR0_CLRALL | CSR0_INEA | CSR0_STRT);
+ return 1; /* ->OK */
+ }
+ printk(KERN_ERR "%s: can't init lance, status: %04x\n",dev->name,(int) inw(PORT+L_DATAREG));
+ disable_dma(dev->dma);
+ return 0; /* ->Error */
}
/*
{
int csr0;
struct device *dev = (struct device *) irq2dev_map[irq];
+ struct priv *p;
int bcnt = 32;
if (dev == NULL) {
return;
}
- dev->interrupt = 1;
+ if(set_bit(0,(int *) &dev->interrupt)) {
+ printk("ni65: oops .. interrupt while proceeding interrupt\n");
+ return;
+ }
+ p = (struct priv *) dev->priv;
while(--bcnt) {
-
csr0 = inw(PORT+L_DATAREG);
- writedatareg(csr0 & CSR0_CLRALL); /* ack interrupts, disable int. */
+
+#if 0
+ writedatareg( (csr0 & CSR0_CLRALL) ); /* ack interrupts, disable int. */
+#else
+ writedatareg( (csr0 & CSR0_CLRALL) | CSR0_INEA ); /* ack interrupts, interrupts enabled */
+#endif
if(!(csr0 & (CSR0_ERR | CSR0_RINT | CSR0_TINT)))
break;
+ if(csr0 & CSR0_RINT) /* RECV-int? */
+ ni65_recv_intr(dev,csr0);
+ if(csr0 & CSR0_TINT) /* XMIT-int? */
+ ni65_xmit_intr(dev,csr0);
+
if(csr0 & CSR0_ERR)
{
struct priv *p = (struct priv *) dev->priv;
-
+ if(debuglevel > 1)
+ printk("%s: general error: %04x.\n",dev->name,csr0);
if(csr0 & CSR0_BABL)
p->stats.tx_errors++;
- if(csr0 & CSR0_MISS)
+ if(csr0 & CSR0_MISS) {
+ int i;
+ for(i=0;i<RMDNUM;i++)
+ printk("%02x ",p->rmdhead[i].u.s.status);
+ printk("\n");
p->stats.rx_errors++;
+ }
if(csr0 & CSR0_MERR) {
- writedatareg(CSR0_STOP);
- writedatareg(CSR0_STRT);
+ if(debuglevel > 1)
+ printk("%s: Ooops .. memory error: %04x.\n",dev->name,csr0);
+ ni65_stop_start(dev,p);
}
}
- if(csr0 & CSR0_RINT) /* RECV-int? */
- ni65_recv_intr(dev,csr0);
- if(csr0 & CSR0_TINT) /* XMIT-int? */
- ni65_xmit_intr(dev,csr0);
}
#ifdef RCV_PARANOIA_CHECK
{
+ int j;
+ for(j=0;j<RMDNUM;j++)
+ {
struct priv *p = (struct priv *) dev->priv;
- int i,f=0;
- for(i=0;i<RMDNUM;i++) {
- struct rmd *rmdp = p->rmdhead + ((p->rmdnum - i - 1) & (RMDNUM-1));
- if(! (rmdp->u.s.status & RCV_OWN) )
- f = 1;
- else if(f)
+ int i,k,num1,num2;
+ for(i=RMDNUM-1;i>0;i--) {
+ num2 = (p->rmdnum + i) & (RMDNUM-1);
+ if(!(p->rmdhead[num2].u.s.status & RCV_OWN))
break;
}
- if(i < RMDNUM) {
- p->rmdnum = (p->rmdnum + 8 - i) & (RMDNUM - 1);
- printk(KERN_ERR "%s: Ooops, receive ring corrupted\n",dev->name);
+ if(i) {
+ for(k=0;k<RMDNUM;k++) {
+ num1 = (p->rmdnum + k) & (RMDNUM-1);
+ if(!(p->rmdhead[num1].u.s.status & RCV_OWN))
+ break;
+ }
+ if(!k)
+ break;
+
+ if(debuglevel > 0)
+ {
+ char buf[256],*buf1;
+ int k;
+ buf1 = buf;
+ for(k=0;k<RMDNUM;k++) {
+ sprintf(buf1,"%02x ",(p->rmdhead[k].u.s.status)); /* & RCV_OWN) ); */
+ buf1 += 3;
+ }
+ *buf1 = 0;
+ printk(KERN_ERR "%s: Ooops, receive ring corrupted %2d %2d | %s\n",dev->name,p->rmdnum,i,buf);
+ }
+ p->rmdnum = num1;
ni65_recv_intr(dev,csr0);
+ if((p->rmdhead[num2].u.s.status & RCV_OWN))
+ break; /* ok, we are 'in sync' again */
}
+ else
+ break;
+ }
}
#endif
- if(csr0 & (CSR0_RXON | CSR0_TXON) != (CSR0_RXON | CSR0_TXON) ) {
- writedatareg(CSR0_STOP);
- writedatareg(CSR0_STRT | CSR0_INEA);
+ if( (csr0 & (CSR0_RXON | CSR0_TXON)) != (CSR0_RXON | CSR0_TXON) ) {
+ printk("%s: RX or TX was offline -> restart\n",dev->name);
+ ni65_stop_start(dev,p);
}
else
writedatareg(CSR0_INEA);
+
dev->interrupt = 0;
return;
if(tmdstat & XMIT_OWN)
break;
-#ifdef XMT_VIA_SKB
- if(p->tmd_skb[p->tmdlast]) {
- dev_kfree_skb(p->tmd_skb[p->tmdlast],FREE_WRITE);
- p->tmd_skb[p->tmdlast] = NULL;
- }
-#endif
-
if(tmdstat & XMIT_ERR)
{
#if 0
if(tmdp->status2 & XMIT_LCAR)
p->stats.tx_carrier_errors++;
if(tmdp->status2 & (XMIT_BUFF | XMIT_UFLO )) {
+ /* this stops the xmitter */
p->stats.tx_fifo_errors++;
- writedatareg(CSR0_STOP);
- writedatareg(CSR0_STRT);
- if(debuglevel > 1)
+ if(debuglevel > 0)
printk(KERN_ERR "%s: Xmit FIFO/BUFF error\n",dev->name);
+ if(p->features & INIT_RING_BEFORE_START) {
+ tmdp->u.s.status = XMIT_OWN | XMIT_START | XMIT_END; /* test: resend this frame */
+ ni65_stop_start(dev,p);
+ break; /* no more Xmit processing .. */
+ }
+ else
+ ni65_stop_start(dev,p);
}
if(debuglevel > 2)
printk(KERN_ERR "%s: xmit-error: %04x %02x-%04x\n",dev->name,csr0,(int) tmdstat,(int) tmdp->status2);
- p->stats.tx_errors++;
+ if(!(csr0 & CSR0_BABL)) /* don't count errors twice */
+ p->stats.tx_errors++;
tmdp->status2 = 0;
}
else
p->stats.tx_packets++;
+#ifdef XMT_VIA_SKB
+ if(p->tmd_skb[p->tmdlast]) {
+ dev_kfree_skb(p->tmd_skb[p->tmdlast],FREE_WRITE);
+ p->tmd_skb[p->tmdlast] = NULL;
+ }
+#endif
+
p->tmdlast = (p->tmdlast + 1) & (TMDNUM-1);
if(p->tmdlast == p->tmdnum)
p->xmit_queued = 0;
/*
* We have received a packet
*/
-
static void ni65_recv_intr(struct device *dev,int csr0)
{
struct rmd *rmdp;
int rmdstat,len;
+ int cnt=0;
struct priv *p = (struct priv *) dev->priv;
rmdp = p->rmdhead + p->rmdnum;
while(!( (rmdstat = rmdp->u.s.status) & RCV_OWN))
{
+ cnt++;
if( (rmdstat & (RCV_START | RCV_END | RCV_ERR)) != (RCV_START | RCV_END) ) /* error or oversized? */
{
if(!(rmdstat & RCV_ERR)) {
}
}
else {
- printk(KERN_ERR "%s: receive-error: %04x, lance-status: %04x/%04x\n",
- dev->name,(int) rmdstat,csr0,(int) inw(PORT+L_DATAREG) );
+ if(debuglevel > 2)
+ printk(KERN_ERR "%s: receive-error: %04x, lance-status: %04x/%04x\n",
+ dev->name,(int) rmdstat,csr0,(int) inw(PORT+L_DATAREG) );
if(rmdstat & RCV_FRAM)
p->stats.rx_frame_errors++;
if(rmdstat & RCV_OFLO)
p->stats.rx_over_errors++;
- if(rmdstat & (RCV_OFLO | RCV_BUF_ERR) ) {
- writedatareg(CSR0_STOP);
- writedatareg(CSR0_STRT);
- if(debuglevel > 1)
- printk(KERN_ERR "%s: Rcv FIFO/BUFF error.\n",dev->name);
- }
- if(rmdstat & RCV_CRC) p->stats.rx_crc_errors++;
+ if(rmdstat & RCV_CRC)
+ p->stats.rx_crc_errors++;
+ if(rmdstat & RCV_BUF_ERR)
+ p->stats.rx_fifo_errors++;
}
- rmdp->u.s.status = RCV_OWN; /* change owner */
- p->stats.rx_errors++;
+ if(!(csr0 & CSR0_MISS)) /* don't count errors twice */
+ p->stats.rx_errors++;
}
else if( (len = (rmdp->mlen & 0x0fff) - 4) >= 60)
{
#ifdef RCV_VIA_SKB
- struct sk_buff *skb = dev_alloc_skb(R_BUF_SIZE+2);
+ struct sk_buff *skb = alloc_skb(R_BUF_SIZE+2+16,GFP_ATOMIC);
+ if (skb)
+ skb_reserve(skb,16);
#else
struct sk_buff *skb = dev_alloc_skb(len+2);
#endif
struct sk_buff *skb1 = p->recv_skb[p->rmdnum];
skb_put(skb,R_BUF_SIZE);
p->recv_skb[p->rmdnum] = skb;
- rmdp->u.buffer = (unsigned long) skb->data;
+ rmdp->u.buffer = (u32) virt_to_bus(skb->data);
skb = skb1;
skb_trim(skb,len);
}
skb_put(skb,len);
eth_copy_and_sum(skb, (unsigned char *) p->recvbounce[p->rmdnum],len,0);
#endif
- rmdp->u.s.status = RCV_OWN;
p->stats.rx_packets++;
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
}
else
{
- rmdp->u.s.status = RCV_OWN;
printk(KERN_ERR "%s: can't alloc new sk_buff\n",dev->name);
p->stats.rx_dropped++;
}
}
else {
- rmdp->u.s.status = RCV_OWN;
printk(KERN_INFO "%s: received runt packet\n",dev->name);
p->stats.rx_errors++;
}
+ rmdp->blen = -(R_BUF_SIZE-8);
+ rmdp->mlen = 0;
+ rmdp->u.s.status = RCV_OWN; /* change owner */
p->rmdnum = (p->rmdnum + 1) & (RMDNUM-1);
rmdp = p->rmdhead + p->rmdnum;
}
if(dev->tbusy)
{
int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 5)
+ if (tickssofar < 50)
return 1;
printk(KERN_ERR "%s: xmitter timed out, try to restart!\n",dev->name);
- ni65_am7990_reinit(dev);
+{
+ int i;
+ for(i=0;i<TMDNUM;i++)
+ printk("%02x ",p->tmdhead[i].u.s.status);
+ printk("\n");
+}
+ ni65_lance_reinit(dev);
dev->tbusy=0;
dev->trans_start = jiffies;
}
{
short len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- struct tmd *tmdp = p->tmdhead + p->tmdnum;
+ struct tmd *tmdp;
long flags;
#ifdef XMT_VIA_SKB
if( (unsigned long) (skb->data + skb->len) > 0x1000000) {
#endif
- tmdp->u.buffer = (unsigned long ) p->tmdbounce[p->tmdnum];
- memcpy((char *) tmdp->u.buffer,(char *)skb->data,
+
+ memcpy((char *) p->tmdbounce[p->tmdbouncenum] ,(char *)skb->data,
(skb->len > T_BUF_SIZE) ? T_BUF_SIZE : skb->len);
dev_kfree_skb (skb, FREE_WRITE);
+
+ save_flags(flags);
+ cli();
+
+ tmdp = p->tmdhead + p->tmdnum;
+ tmdp->u.buffer = (u32) virt_to_bus(p->tmdbounce[p->tmdbouncenum]);
+ p->tmdbouncenum = (p->tmdbouncenum + 1) & (TMDNUM - 1);
+
#ifdef XMT_VIA_SKB
}
else {
- tmdp->u.buffer = (unsigned long) skb->data;
+ save_flags(flags);
+ cli();
+
+ tmdp = p->tmdhead + p->tmdnum;
+ tmdp->u.buffer = (u32) virt_to_bus(skb->data);
p->tmd_skb[p->tmdnum] = skb;
}
#endif
tmdp->blen = -len;
- save_flags(flags);
- cli();
-
tmdp->u.s.status = XMIT_OWN | XMIT_START | XMIT_END;
writedatareg(CSR0_TDMD | CSR0_INEA); /* enable xmit & interrupt */
static struct enet_statistics *ni65_get_stats(struct device *dev)
{
+
+#if 0
+ int i;
+ struct priv *p = (struct priv *) dev->priv;
+ for(i=0;i<RMDNUM;i++) {
+ struct rmd *rmdp = p->rmdhead + ((p->rmdnum + i) & (RMDNUM-1));
+ printk("%02x ",rmdp->u.s.status);
+ }
+ printk("\n");
+#endif
+
return &((struct priv *) dev->priv)->stats;
}
static void set_multicast_list(struct device *dev)
{
- if(!ni65_am7990_reinit(dev))
+ if(!ni65_lance_reinit(dev))
printk(KERN_ERR "%s: Can't switch card into MC mode!\n",dev->name);
dev->tbusy = 0;
}
+#ifdef MODULE
+static struct device dev_ni65 = {
+ " ", /* "ni6510": device name inserted by net_init.c */
+ 0, 0, 0, 0,
+ 0x360, 9, /* I/O address, IRQ */
+ 0, 0, 0, NULL, ni65_probe };
+
+/* set: io,irq,dma or set it when calling insmod */
+static int irq=0;
+static int io=0;
+static int dma=0;
+
+int init_module(void)
+{
+#if 0
+ if(io <= 0x0 || irq < 2) {
+ printk("ni65: Autoprobing not allowed for modules.\n");
+ printk("ni65: Set symbols 'io' 'irq' and 'dma'\n");
+ return -ENODEV;
+ }
+#endif
+ dev_ni65.irq = irq;
+ dev_ni65.dma = dma;
+ dev_ni65.base_addr = io;
+ if (register_netdev(&dev_ni65) != 0)
+ return -EIO;
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ struct priv *p;
+ p = (struct priv *) dev_ni65.priv;
+ if(!p) {
+ printk("Ooops .. no privat struct\n");
+ return;
+ }
+ disable_dma(dev_ni65.dma);
+ free_dma(dev_ni65.dma);
+ release_region(dev_ni65.base_addr,cards[p->cardno].total_size);
+ ni65_free_buffer(p);
+ dev_ni65.priv = NULL;
+ unregister_netdev(&dev_ni65);
+}
+#endif /* MODULE */
+
/*
* END of ni65.c
*/
+
unsigned char eaddr[6];
unsigned char filter[8];
/* bit 29-31: number of rmd's (power of 2) */
- unsigned long rrp; /* receive ring pointer (align 8) */
+ u32 rrp; /* receive ring pointer (align 8) */
/* bit 29-31: number of tmd's (power of 2) */
- unsigned long trp; /* transmit ring pointer (align 8) */
+ u32 trp; /* transmit ring pointer (align 8) */
};
struct rmd /* Receive Message Descriptor */
{
union
{
- volatile unsigned long buffer;
+ volatile u32 buffer;
struct
{
volatile unsigned char dummy[3];
volatile unsigned char status;
} s;
} u;
- short blen;
+ volatile short blen;
volatile unsigned short mlen;
};
{
union
{
- volatile unsigned long buffer;
+ volatile u32 buffer;
struct
{
volatile unsigned char dummy[3];
volatile unsigned char status;
} s;
} u;
- unsigned short blen;
+ volatile unsigned short blen;
volatile unsigned short status2;
};
*/
len = skb->len;
data = skb_data(skb);
+/*
+ * Bug trap for null data. Release the skb and bail out.
+ */
+ if(data == NULL) {
+ printk("ppp_dev_xmit: data=NULL before ppp_dev_xmit_ip.\n");
+ dev_kfree_skb (skb, FREE_WRITE);
+ return 0;
+ }
/*
* Look at the protocol in the skb to determine the difference between
* an IP frame and an IPX frame.
/* Log any net taps. */
printk("%s: Promiscuous mode enabled.\n", dev->name);
}
- else if (dev->mc_count > 15 || (dev->flags&IFF_ALLMULTI))
+ else if (dev->mc_count > 14 || (dev->flags&IFF_ALLMULTI))
{
/* Too many to filter perfectly -- accept all multicasts. */
tio_write(csr6 | TCMOD_ALLMCAST, CSR6);
unsigned short *eaddrs;
int i;
- /* We have <= 15 addresses that we can use the wonderful
+ /* We have < 15 addresses that we can use the wonderful
16 address perfect filtering of the Tulip. Note that only
the low shortword of setup_frame[] is valid. */
tio_write(csr6 | 0x0000, CSR6);
}
/* Fill the rest of the table with our physical address. */
eaddrs = (unsigned short *)dev->dev_addr;
+ /* Always accept broadcast packets */
+ *setup_frm++ = 0xffff;
+ *setup_frm++ = 0xffff;
+ *setup_frm++ = 0xffff;
do {
*setup_frm++ = eaddrs[0];
*setup_frm++ = eaddrs[1];
*setup_frm++ = eaddrs[2];
- } while (++i < 16);
+ } while (++i < 15);
/* Now add this frame to the Tx list. */
}
static int sync_buffers(kdev_t dev, int wait)
{
int i, retry, pass = 0, err = 0;
- int nlist, ncount;
struct buffer_head * bh, *next;
/* One pass for no-wait, three for wait:
0) write out all dirty, unlocked buffers;
1) write out all dirty buffers, waiting if locked;
2) wait for completion by waiting for all buffers to unlock. */
- repeat:
- retry = 0;
- repeat2:
- ncount = 0;
+ do {
+ retry = 0;
+repeat:
/* We search all lists as a failsafe mechanism, not because we expect
there to be dirty buffers on any of the other lists. */
- for(nlist = 0; nlist < NR_LIST; nlist++)
- {
- repeat1:
- bh = lru_list[nlist];
- if(!bh) continue;
- for (i = nr_buffers_type[nlist]*2 ; i-- > 0 ; bh = next) {
- if(bh->b_list != nlist) goto repeat1;
- next = bh->b_next_free;
- if(!lru_list[nlist]) break;
- if (dev && bh->b_dev != dev)
- continue;
- if (buffer_locked(bh))
- {
- /* Buffer is locked; skip it unless wait is
- requested AND pass > 0. */
- if (!wait || !pass) {
- retry = 1;
- continue;
- }
- wait_on_buffer (bh);
- goto repeat2;
- }
- /* If an unlocked buffer is not uptodate, there has
- been an IO error. Skip it. */
- if (wait && buffer_req(bh) && !buffer_locked(bh) &&
- !buffer_dirty(bh) && !buffer_uptodate(bh)) {
- err = 1;
- continue;
- }
- /* Don't write clean buffers. Don't write ANY buffers
- on the third pass. */
- if (!buffer_dirty(bh) || pass>=2)
- continue;
- /* don't bother about locked buffers */
- if (buffer_locked(bh))
- continue;
- bh->b_count++;
- bh->b_flushtime = 0;
- ll_rw_block(WRITE, 1, &bh);
-
- if(nlist != BUF_DIRTY) {
- printk("[%d %s %ld] ", nlist,
- kdevname(bh->b_dev), bh->b_blocknr);
- ncount++;
- }
- bh->b_count--;
- retry = 1;
- }
- }
- if (ncount)
- printk("sys_sync: %d dirty buffers not on dirty list\n", ncount);
+ bh = lru_list[BUF_DIRTY];
+ if (!bh)
+ break;
+ for (i = nr_buffers_type[BUF_DIRTY]*2 ; i-- > 0 ; bh = next) {
+ if (bh->b_list != BUF_DIRTY)
+ goto repeat;
+ next = bh->b_next_free;
+ if (!lru_list[BUF_DIRTY])
+ break;
+ if (dev && bh->b_dev != dev)
+ continue;
+ if (buffer_locked(bh)) {
+ /* Buffer is locked; skip it unless wait is
+ requested AND pass > 0. */
+ if (!wait || !pass) {
+ retry = 1;
+ continue;
+ }
+ wait_on_buffer (bh);
+ goto repeat;
+ }
+ /* If an unlocked buffer is not uptodate, there has
+ been an IO error. Skip it. */
+ if (wait && buffer_req(bh) && !buffer_locked(bh) &&
+ !buffer_dirty(bh) && !buffer_uptodate(bh)) {
+ err = 1;
+ continue;
+ }
+ /* Don't write clean buffers. Don't write ANY buffers
+ on the third pass. */
+ if (!buffer_dirty(bh) || pass >= 2)
+ continue;
+ /* don't bother about locked buffers */
+ if (buffer_locked(bh))
+ continue;
+ bh->b_count++;
+ next->b_count++;
+ bh->b_flushtime = 0;
+ ll_rw_block(WRITE, 1, &bh);
+ bh->b_count--;
+ next->b_count--;
+ retry = 1;
+ }
/* If we are waiting for the sync to succeed, and if any dirty
blocks were written, then repeat; on the second pass, only
wait for buffers being written (do not pass to write any
more buffers on the second pass). */
- if (wait && retry && ++pass<=2)
- goto repeat;
+ } while (wait && retry && ++pass<=2);
return err;
}
#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
-/*
- * How long a filename can we get from user space?
- * -EFAULT if invalid area
- * 0 if ok (ENAMETOOLONG before EFAULT)
- * >0 EFAULT after xx bytes
- */
-static inline int get_max_filename(unsigned long address)
-{
- struct vm_area_struct * vma;
-
- if (get_fs() == KERNEL_DS)
- return 0;
- vma = find_vma(current->mm, address);
- if (!vma || vma->vm_start > address || !(vma->vm_flags & VM_READ))
- return -EFAULT;
- address = vma->vm_end - address;
- if (address > PAGE_SIZE)
- return 0;
- if (vma->vm_next && vma->vm_next->vm_start == vma->vm_end &&
- (vma->vm_next->vm_flags & VM_READ))
- return 0;
- return address;
-}
-
/*
* In order to reduce some races, while at the same time doing additional
* checking and hopefully speeding things up, we copy filenames to the
*
* POSIX.1 2.4: an empty pathname is invalid (ENOENT).
*/
-int getname(const char * filename, char **result)
+static inline int do_getname(const char * filename, char *buf)
{
- int i, error;
- unsigned long page;
- char * tmp, c;
-
- i = get_max_filename((unsigned long) filename);
- if (i < 0)
- return i;
- error = -EFAULT;
- if (!i) {
- error = -ENAMETOOLONG;
- i = PAGE_SIZE;
- }
- c = get_user(filename++);
+ int error, maxlen = PAGE_SIZE;
+ int c;
+
+ error = -ENAMETOOLONG;
+ if (get_fs() != KERNEL_DS) {
+ error = -EFAULT;
+ if (TASK_SIZE <= (unsigned long) filename)
+ return error;
+ maxlen = TASK_SIZE - (unsigned long) filename;
+ if (maxlen >= PAGE_SIZE) {
+ maxlen = PAGE_SIZE;
+ error = -ENAMETOOLONG;
+ }
+ }
+
+ c = (unsigned char) get_user(filename++);
if (!c)
return -ENOENT;
- if(!(page = __get_free_page(GFP_KERNEL)))
- return -ENOMEM;
- *result = tmp = (char *) page;
- while (--i) {
- *(tmp++) = c;
+
+ while (--maxlen) {
+ *(buf++) = c;
c = get_user(filename++);
if (!c) {
- *tmp = '\0';
+ *buf = '\0';
return 0;
}
}
- free_page(page);
return error;
}
+int getname(const char *filename, char **result)
+{
+ int error;
+ unsigned long page = __get_free_page(GFP_KERNEL);
+
+ error = -ENOMEM;
+ if (page) {
+ error = -EFAULT;
+ if (!exception()) {
+ int retval = do_getname(filename, (char *) page);
+ end_exception();
+ if (!retval) {
+ *result = (char *) page;
+ return 0;
+ }
+ error = retval;
+ }
+ free_page(page);
+ }
+ return error;
+}
+
void putname(char * name)
{
free_page((unsigned long) name);
NULL, &proc_root, NULL
};
+static struct proc_dir_entry proc_pid_status = {
+ PROC_PID_STATUS, 6, "status",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_array_inode_operations,
+ NULL, proc_pid_fill_inode,
+};
+static struct proc_dir_entry proc_pid_mem = {
+ PROC_PID_MEM, 3, "mem",
+ S_IFREG | S_IRUSR | S_IWUSR, 1, 0, 0,
+ 0, &proc_mem_inode_operations,
+ NULL, proc_pid_fill_inode,
+};
+static struct proc_dir_entry proc_pid_cwd = {
+ PROC_PID_CWD, 3, "cwd",
+ S_IFLNK | S_IRWXU, 1, 0, 0,
+ 0, &proc_link_inode_operations,
+ NULL, proc_pid_fill_inode,
+};
+static struct proc_dir_entry proc_pid_root = {
+ PROC_PID_ROOT, 4, "root",
+ S_IFLNK | S_IRWXU, 1, 0, 0,
+ 0, &proc_link_inode_operations,
+ NULL, proc_pid_fill_inode,
+};
+static struct proc_dir_entry proc_pid_exe = {
+ PROC_PID_EXE, 3, "exe",
+ S_IFLNK | S_IRWXU, 1, 0, 0,
+ 0, &proc_link_inode_operations,
+ NULL, proc_pid_fill_inode,
+};
+static struct proc_dir_entry proc_pid_fd = {
+ PROC_PID_FD, 2, "fd",
+ S_IFDIR | S_IRUSR | S_IXUSR, 1, 0, 0,
+ 0, &proc_fd_inode_operations,
+ NULL, proc_pid_fill_inode,
+};
+static struct proc_dir_entry proc_pid_environ = {
+ PROC_PID_ENVIRON, 7, "environ",
+ S_IFREG | S_IRUSR, 1, 0, 0,
+ 0, &proc_array_inode_operations,
+ NULL, proc_pid_fill_inode,
+};
+static struct proc_dir_entry proc_pid_cmdline = {
+ PROC_PID_CMDLINE, 7, "cmdline",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_array_inode_operations,
+ NULL, proc_pid_fill_inode,
+};
+static struct proc_dir_entry proc_pid_stat = {
+ PROC_PID_STAT, 4, "stat",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_array_inode_operations,
+ NULL, proc_pid_fill_inode,
+};
+static struct proc_dir_entry proc_pid_statm = {
+ PROC_PID_STATM, 5, "statm",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_array_inode_operations,
+ NULL, proc_pid_fill_inode,
+};
+static struct proc_dir_entry proc_pid_maps = {
+ PROC_PID_MAPS, 4, "maps",
+ S_IFIFO | S_IRUGO, 1, 0, 0,
+ 0, &proc_arraylong_inode_operations,
+ NULL, proc_pid_fill_inode,
+};
void proc_base_init(void)
{
- proc_register(&proc_pid, &(struct proc_dir_entry) {
- PROC_PID_STATUS, 6, "status",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_array_inode_operations,
- NULL, proc_pid_fill_inode,
- });
- proc_register(&proc_pid, &(struct proc_dir_entry) {
- PROC_PID_MEM, 3, "mem",
- S_IFREG | S_IRUSR | S_IWUSR, 1, 0, 0,
- 0, &proc_mem_inode_operations,
- NULL, proc_pid_fill_inode,
- });
- proc_register(&proc_pid, &(struct proc_dir_entry) {
- PROC_PID_CWD, 3, "cwd",
- S_IFLNK | S_IRWXU, 1, 0, 0,
- 0, &proc_link_inode_operations,
- NULL, proc_pid_fill_inode,
- });
- proc_register(&proc_pid, &(struct proc_dir_entry) {
- PROC_PID_ROOT, 4, "root",
- S_IFLNK | S_IRWXU, 1, 0, 0,
- 0, &proc_link_inode_operations,
- NULL, proc_pid_fill_inode,
- });
- proc_register(&proc_pid, &(struct proc_dir_entry) {
- PROC_PID_EXE, 3, "exe",
- S_IFLNK | S_IRWXU, 1, 0, 0,
- 0, &proc_link_inode_operations,
- NULL, proc_pid_fill_inode,
- });
- proc_register(&proc_pid, &(struct proc_dir_entry) {
- PROC_PID_FD, 2, "fd",
- S_IFDIR | S_IRUSR | S_IXUSR, 1, 0, 0,
- 0, &proc_fd_inode_operations,
- NULL, proc_pid_fill_inode,
- });
- proc_register(&proc_pid, &(struct proc_dir_entry) {
- PROC_PID_ENVIRON, 7, "environ",
- S_IFREG | S_IRUSR, 1, 0, 0,
- 0, &proc_array_inode_operations,
- NULL, proc_pid_fill_inode,
- });
- proc_register(&proc_pid, &(struct proc_dir_entry) {
- PROC_PID_CMDLINE, 7, "cmdline",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_array_inode_operations,
- NULL, proc_pid_fill_inode,
- });
- proc_register(&proc_pid, &(struct proc_dir_entry) {
- PROC_PID_STAT, 4, "stat",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_array_inode_operations,
- NULL, proc_pid_fill_inode,
- });
- proc_register(&proc_pid, &(struct proc_dir_entry) {
- PROC_PID_STATM, 5, "statm",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_array_inode_operations,
- NULL, proc_pid_fill_inode,
- });
- proc_register(&proc_pid, &(struct proc_dir_entry) {
- PROC_PID_MAPS, 4, "maps",
- S_IFIFO | S_IRUGO, 1, 0, 0,
- 0, &proc_arraylong_inode_operations,
- NULL, proc_pid_fill_inode,
- });
+ proc_register(&proc_pid, &proc_pid_status);
+ proc_register(&proc_pid, &proc_pid_mem);
+ proc_register(&proc_pid, &proc_pid_cwd);
+ proc_register(&proc_pid, &proc_pid_root);
+ proc_register(&proc_pid, &proc_pid_exe);
+ proc_register(&proc_pid, &proc_pid_fd);
+ proc_register(&proc_pid, &proc_pid_environ);
+ proc_register(&proc_pid, &proc_pid_cmdline);
+ proc_register(&proc_pid, &proc_pid_stat);
+ proc_register(&proc_pid, &proc_pid_statm);
+ proc_register(&proc_pid, &proc_pid_maps);
};
NULL /* permission */
};
+static struct proc_dir_entry proc_root_loadavg = {
+ PROC_LOADAVG, 7, "loadavg",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_uptime = {
+ PROC_UPTIME, 6, "uptime",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_meminfo = {
+ PROC_MEMINFO, 7, "meminfo",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_kmsg = {
+ PROC_KMSG, 4, "kmsg",
+ S_IFREG | S_IRUSR, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_version = {
+ PROC_VERSION, 7, "version",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+};
+#ifdef CONFIG_PCI
+static struct proc_dir_entry proc_root_pci = {
+ PROC_PCI, 3, "pci",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+};
+#endif
+static struct proc_dir_entry proc_root_cpuinfo = {
+ PROC_CPUINFO, 7, "cpuinfo",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_self = {
+ PROC_SELF, 4, "self",
+ S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, 1, 0, 0,
+ 64, &proc_self_inode_operations,
+};
+#ifdef CONFIG_DEBUG_MALLOC
+static struct proc_dir_entry proc_root_malloc = {
+ PROC_MALLOC, 6, "malloc",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+};
+#endif
+static struct proc_dir_entry proc_root_kcore = {
+ PROC_KCORE, 5, "kcore",
+ S_IFREG | S_IRUSR, 1, 0, 0,
+};
+#ifdef CONFIG_MODULES
+static struct proc_dir_entry proc_root_modules = {
+ PROC_MODULES, 7, "modules",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_ksyms = {
+ PROC_KSYMS, 5, "ksyms",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+};
+#endif
+static struct proc_dir_entry proc_root_stat = {
+ PROC_STAT, 4, "stat",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_devices = {
+ PROC_DEVICES, 7, "devices",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_interrupts = {
+ PROC_INTERRUPTS, 10,"interrupts",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+};
+#ifdef __SMP_PROF__
+static struct proc_dir_entry proc_root_smp = {
+ PROC_SMP_PROF, 3,"smp",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+};
+#endif
+static struct proc_dir_entry proc_root_filesystems = {
+ PROC_FILESYSTEMS, 11,"filesystems",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_dma = {
+ PROC_DMA, 3, "dma",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_ioports = {
+ PROC_IOPORTS, 7, "ioports",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_cmdline = {
+ PROC_CMDLINE, 7, "cmdline",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+};
+#ifdef CONFIG_RTC
+static struct proc_dir_entry proc_root_rtc = {
+ PROC_RTC, 3, "rtc",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+};
+#endif
+static struct proc_dir_entry proc_root_locks = {
+ PROC_LOCKS, 5, "locks",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_mounts = {
+ PROC_MTAB, 6, "mounts",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+};
+static struct proc_dir_entry proc_root_profile = {
+ PROC_PROFILE, 7, "profile",
+ S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
+};
+
void proc_root_init(void)
{
static int done = 0;
return;
done = 1;
proc_base_init();
- proc_register(&proc_root, &(struct proc_dir_entry) {
- PROC_LOADAVG, 7, "loadavg",
- S_IFREG | S_IRUGO, 1, 0, 0,
- });
- proc_register(&proc_root, &(struct proc_dir_entry) {
- PROC_UPTIME, 6, "uptime",
- S_IFREG | S_IRUGO, 1, 0, 0,
- });
- proc_register(&proc_root, &(struct proc_dir_entry) {
- PROC_MEMINFO, 7, "meminfo",
- S_IFREG | S_IRUGO, 1, 0, 0,
- });
- proc_register(&proc_root, &(struct proc_dir_entry) {
- PROC_KMSG, 4, "kmsg",
- S_IFREG | S_IRUSR, 1, 0, 0,
- });
- proc_register(&proc_root, &(struct proc_dir_entry) {
- PROC_VERSION, 7, "version",
- S_IFREG | S_IRUGO, 1, 0, 0,
- });
+ proc_register(&proc_root, &proc_root_loadavg);
+ proc_register(&proc_root, &proc_root_uptime);
+ proc_register(&proc_root, &proc_root_meminfo);
+ proc_register(&proc_root, &proc_root_kmsg);
+ proc_register(&proc_root, &proc_root_version);
#ifdef CONFIG_PCI
- proc_register(&proc_root, &(struct proc_dir_entry) {
- PROC_PCI, 3, "pci",
- S_IFREG | S_IRUGO, 1, 0, 0,
- });
+ proc_register(&proc_root, &proc_root_pci);
#endif
- proc_register(&proc_root, &(struct proc_dir_entry) {
- PROC_CPUINFO, 7, "cpuinfo",
- S_IFREG | S_IRUGO, 1, 0, 0,
- });
- proc_register(&proc_root, &(struct proc_dir_entry) {
- PROC_SELF, 4, "self",
- S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, 1, 0, 0,
- 64, &proc_self_inode_operations,
- });
+ proc_register(&proc_root, &proc_root_cpuinfo);
+ proc_register(&proc_root, &proc_root_self);
proc_register(&proc_root, &proc_net);
proc_register(&proc_root, &proc_scsi);
proc_register(&proc_root, &proc_sys_root);
#ifdef CONFIG_DEBUG_MALLOC
- proc_register(&proc_root, &(struct proc_dir_entry) {
- PROC_MALLOC, 6, "malloc",
- S_IFREG | S_IRUGO, 1, 0, 0,
- });
+ proc_register(&proc_root, &proc_root_malloc);
#endif
- proc_register(&proc_root, &(struct proc_dir_entry) {
- PROC_KCORE, 5, "kcore",
- S_IFREG | S_IRUSR, 1, 0, 0,
- });
+ proc_register(&proc_root, &proc_root_kcore);
#ifdef CONFIG_MODULES
- proc_register(&proc_root, &(struct proc_dir_entry) {
- PROC_MODULES, 7, "modules",
- S_IFREG | S_IRUGO, 1, 0, 0,
- });
- proc_register(&proc_root, &(struct proc_dir_entry) {
- PROC_KSYMS, 5, "ksyms",
- S_IFREG | S_IRUGO, 1, 0, 0,
- });
+ proc_register(&proc_root, &proc_root_modules);
+ proc_register(&proc_root, &proc_root_ksyms);
#endif
- proc_register(&proc_root, &(struct proc_dir_entry) {
- PROC_STAT, 4, "stat",
- S_IFREG | S_IRUGO, 1, 0, 0,
- });
- proc_register(&proc_root, &(struct proc_dir_entry) {
- PROC_DEVICES, 7, "devices",
- S_IFREG | S_IRUGO, 1, 0, 0,
- });
- proc_register(&proc_root, &(struct proc_dir_entry) {
- PROC_INTERRUPTS, 10,"interrupts",
- S_IFREG | S_IRUGO, 1, 0, 0,
- });
+ proc_register(&proc_root, &proc_root_stat);
+ proc_register(&proc_root, &proc_root_devices);
+ proc_register(&proc_root, &proc_root_interrupts);
#ifdef __SMP_PROF__
- proc_register(&proc_root, &(struct proc_dir_entry) {
- PROC_SMP_PROF, 3,"smp",
- S_IFREG | S_IRUGO, 1, 0, 0,
- });
+ proc_register(&proc_root, &proc_root_smp);
#endif
- proc_register(&proc_root, &(struct proc_dir_entry) {
- PROC_FILESYSTEMS, 11,"filesystems",
- S_IFREG | S_IRUGO, 1, 0, 0,
- });
- proc_register(&proc_root, &(struct proc_dir_entry) {
- PROC_DMA, 3, "dma",
- S_IFREG | S_IRUGO, 1, 0, 0,
- });
- proc_register(&proc_root, &(struct proc_dir_entry) {
- PROC_IOPORTS, 7, "ioports",
- S_IFREG | S_IRUGO, 1, 0, 0,
- });
- proc_register(&proc_root, &(struct proc_dir_entry) {
- PROC_CMDLINE, 7, "cmdline",
- S_IFREG | S_IRUGO, 1, 0, 0,
- });
+ proc_register(&proc_root, &proc_root_filesystems);
+ proc_register(&proc_root, &proc_root_dma);
+ proc_register(&proc_root, &proc_root_ioports);
+ proc_register(&proc_root, &proc_root_cmdline);
#ifdef CONFIG_RTC
- proc_register(&proc_root, &(struct proc_dir_entry) {
- PROC_RTC, 3, "rtc",
- S_IFREG | S_IRUGO, 1, 0, 0,
- });
+ proc_register(&proc_root, &proc_root_rtc);
#endif
- proc_register(&proc_root, &(struct proc_dir_entry) {
- PROC_LOCKS, 5, "locks",
- S_IFREG | S_IRUGO, 1, 0, 0,
- });
+ proc_register(&proc_root, &proc_root_locks);
- proc_register( &proc_root, &(struct proc_dir_entry)
- { PROC_MTAB, 6, "mounts", S_IFREG | S_IRUGO, 1, 0, 0, } );
+ proc_register(&proc_root, &proc_root_mounts);
if (prof_shift) {
- proc_register(&proc_root, &(struct proc_dir_entry) {
- PROC_PROFILE, 7, "profile",
- S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
- });
+ proc_register(&proc_root, &proc_root_profile);
}
}
set_hae(addr);
}
+#ifdef __KERNEL__
+
/*
* IO functions
*
#define outb(x, port) \
(__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
+#endif /* __KERNEL__ */
+
/*
* The Alpha Jensen hardware for some rather strange reason puts
* the RTC clock at 0x170 instead of 0x70. Probably due to some
#define MCA_bus 0
#define MCA_bus__is_a_macro /* for versions in ksyms.c */
-/*
- * The alpha has no problems with write protection
- */
-#define wp_works_ok 1
-#define wp_works_ok__is_a_macro /* for versions in ksyms.c */
-
/*
* The VM exception save area. We need to save
* return address (r26)
return 0;
}
+/* Hardware write protection */
+#define verify_write(type, addr, size) 0
+
#endif /* _ASM_SEGMENT_H */
#define SLOW_DOWN_IO __SLOW_DOWN_IO
#endif
-#include <asm/page.h>
-
-#define __io_virt(x) ((void *)(PAGE_OFFSET | (unsigned long)(x)))
-#define __io_phys(x) ((unsigned long)(x) & ~PAGE_OFFSET)
-/*
- * Change virtual addresses to physical addresses and vv.
- * These are pretty trivial
- */
-extern inline unsigned long virt_to_phys(volatile void * address)
-{
- return __io_phys(address);
-}
-
-extern inline void * phys_to_virt(unsigned long address)
-{
- return __io_virt(address);
-}
-
-extern void * ioremap(unsigned long offset, unsigned long size);
-extern void iounmap(void *addr);
-
-/*
- * IO bus memory addresses are also 1:1 with the physical address
- */
-#define virt_to_bus virt_to_phys
-#define bus_to_virt phys_to_virt
-
-/*
- * readX/writeX() are used to access memory mapped devices. On some
- * architectures the memory mapped IO stuff needs to be accessed
- * differently. On the x86 architecture, we just read/write the
- * memory location directly.
- */
-
-#define readb(addr) (*(volatile unsigned char *) __io_virt(addr))
-#define readw(addr) (*(volatile unsigned short *) __io_virt(addr))
-#define readl(addr) (*(volatile unsigned int *) __io_virt(addr))
-
-#define writeb(b,addr) (*(volatile unsigned char *) __io_virt(addr) = (b))
-#define writew(b,addr) (*(volatile unsigned short *) __io_virt(addr) = (b))
-#define writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b))
-
-#define memset_io(a,b,c) memset(__io_virt(a),(b),(c))
-#define memcpy_fromio(a,b,c) memcpy((a),__io_virt(b),(c))
-#define memcpy_toio(a,b,c) memcpy(__io_virt(a),(b),(c))
-
-/*
- * Again, i386 does not require mem IO specific function.
- */
-
-#define eth_io_copy_and_sum(a,b,c,d) eth_copy_and_sum((a),__io_virt(b),(c),(d))
-
/*
* Talk about misusing macros..
*/
__inlc_p(port) : \
__inl_p(port))
+#ifdef __KERNEL__
+
+#include <asm/page.h>
+
+#define __io_virt(x) ((void *)(PAGE_OFFSET | (unsigned long)(x)))
+#define __io_phys(x) ((unsigned long)(x) & ~PAGE_OFFSET)
+/*
+ * Change virtual addresses to physical addresses and vv.
+ * These are pretty trivial
+ */
+extern inline unsigned long virt_to_phys(volatile void * address)
+{
+ return __io_phys(address);
+}
+
+extern inline void * phys_to_virt(unsigned long address)
+{
+ return __io_virt(address);
+}
+
+extern void * ioremap(unsigned long offset, unsigned long size);
+extern void iounmap(void *addr);
+
+/*
+ * IO bus memory addresses are also 1:1 with the physical address
+ */
+#define virt_to_bus virt_to_phys
+#define bus_to_virt phys_to_virt
+
+/*
+ * readX/writeX() are used to access memory mapped devices. On some
+ * architectures the memory mapped IO stuff needs to be accessed
+ * differently. On the x86 architecture, we just read/write the
+ * memory location directly.
+ */
+
+#define readb(addr) (*(volatile unsigned char *) __io_virt(addr))
+#define readw(addr) (*(volatile unsigned short *) __io_virt(addr))
+#define readl(addr) (*(volatile unsigned int *) __io_virt(addr))
+
+#define writeb(b,addr) (*(volatile unsigned char *) __io_virt(addr) = (b))
+#define writew(b,addr) (*(volatile unsigned short *) __io_virt(addr) = (b))
+#define writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b))
+
+#define memset_io(a,b,c) memset(__io_virt(a),(b),(c))
+#define memcpy_fromio(a,b,c) memcpy((a),__io_virt(b),(c))
+#define memcpy_toio(a,b,c) memcpy(__io_virt(a),(b),(c))
+
+/*
+ * Again, i386 does not require mem IO specific function.
+ */
+
+#define eth_io_copy_and_sum(a,b,c,d) eth_copy_and_sum((a),__io_virt(b),(c),(d))
+
static inline int check_signature(unsigned long io_addr,
const unsigned char *signature, int length)
{
return retval;
}
+#endif /* __KERNEL__ */
+
#endif
*/
extern int EISA_bus;
#define MCA_bus 0
-#define MCA_bus__is_a_macro /* for versions in ksyms.c */
/*
* User space process size: 3GB. This is hardcoded into a few places,
#define set_fs(x) (current->tss.segment = (x))
#define get_ds() (KERNEL_DS)
+extern int __verify_write(const void *addr, unsigned long size);
+
+#if CPU > 386
+
+#define verify_write(type,addr,size) 0
+
+#else
+
+/*
+ * The intel i386 CPU needs to check writability by hand, as the
+ * CPU does not honour the write protect bit in supervisor mode
+ */
+#define verify_write(type,addr,size) \
+(((type) && !wp_works_ok)?__verify_write((addr),(size)):0)
+
+#endif
+
#endif /* __ASSEMBLY__ */
#endif /* _ASM_SEGMENT_H */
/*
* This is the old layout of "struct pt_regs", and
- * is still the layout used by user more (the new
+ * is still the layout used by user mode (the new
* pt_regs doesn't have all registers as the kernel
* doesn't use the extra segment registers)
*/
#define VERIFY_READ 0
#define VERIFY_WRITE 1
-extern int __verify_write(const void *, unsigned long);
-
-#define verify_write(type,addr,size) \
-(((type) && !wp_works_ok)?__verify_write((addr),(size)):0)
-
extern inline int verify_area(int type, const void * addr, unsigned long size)
{
int retval = 0;
unsigned short rcv_ack_cnt; /* count of same ack */
__u32 window_seq;
__u32 fin_seq;
+ __u32 syn_seq;
__u32 urg_seq;
__u32 urg_data;
int users; /* user count */
#endif
X(get_options),
- /* system info variables */
- /* These check that they aren't defines (0/1) */
-#ifndef EISA_bus__is_a_macro
- X(EISA_bus),
-#endif
-#ifndef MCA_bus__is_a_macro
- X(MCA_bus),
-#endif
-#ifndef wp_works_ok__is_a_macro
- X(wp_works_ok),
-#endif
-
#ifdef CONFIG_PCI
/* PCI BIOS support */
X(pcibios_present),
return;
}
-/*
- * Ugly, ugly, but the goto's result in better assembly..
- */
-int __verify_write(const void * addr, unsigned long size)
-{
- struct vm_area_struct * vma;
- unsigned long start = (unsigned long) addr;
-
- if (!size)
- return 0;
-
- vma = find_vma(current->mm, start);
- if (!vma)
- goto bad_area;
- if (vma->vm_start > start)
- goto check_stack;
-
-good_area:
- if (!(vma->vm_flags & VM_WRITE))
- goto bad_area;
- size--;
- size += start & ~PAGE_MASK;
- size >>= PAGE_SHIFT;
- start &= PAGE_MASK;
-
- for (;;) {
- do_wp_page(current, vma, start, 1);
- if (!size)
- break;
- size--;
- start += PAGE_SIZE;
- if (start < vma->vm_end)
- continue;
- vma = vma->vm_next;
- if (!vma || vma->vm_start != start)
- goto bad_area;
- if (!(vma->vm_flags & VM_WRITE))
- goto bad_area;;
- }
- return 0;
-
-check_stack:
- if (!(vma->vm_flags & VM_GROWSDOWN))
- goto bad_area;
- if (expand_stack(vma, start) == 0)
- goto good_area;
-
-bad_area:
- return -EFAULT;
-}
-
/*
* This function zeroes out partial mmap'ed pages at truncation time..
*/
static char ddp_snap_id[]={0x08,0x00,0x07,0x80,0x9B};
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_appletalk = {
+ PROC_NET_ATALK, 9, "appletalk",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ atalk_get_info
+};
+static struct proc_dir_entry proc_atalk_route = {
+ PROC_NET_AT_ROUTE, 11,"atalk_route",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ atalk_rt_get_info
+};
+static struct proc_dir_entry proc_atalk_iface = {
+ PROC_NET_ATIF, 11,"atalk_iface",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ atalk_if_get_info
+};
+#endif
/* Called by proto.c on kernel start up */
aarp_proto_init();
#ifdef CONFIG_PROC_FS
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_ATALK, 9, "appletalk",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- atalk_get_info
- });
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_AT_ROUTE, 11,"atalk_route",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- atalk_rt_get_info
- });
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_ATIF, 11,"atalk_iface",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- atalk_if_get_info
- });
+ proc_net_register(&proc_appletalk);
+ proc_net_register(&proc_atalk_route);
+ proc_net_register(&proc_atalk_iface);
#endif
printk(KERN_INFO "Appletalk 0.17 for Linux NET3.035\n");
0
};
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_ax25_route = {
+ PROC_NET_AX25_ROUTE, 10, "ax25_route",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ ax25_rt_get_info
+};
+static struct proc_dir_entry proc_ax25 = {
+ PROC_NET_AX25, 4, "ax25",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ ax25_get_info
+};
+static struct proc_dir_entry proc_ax25_calls = {
+ PROC_NET_AX25_CALLS, 10, "ax25_calls",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ ax25_cs_get_info
+};
+#endif
+#ifdef CONFIG_BPQETHER
+static struct proc_dir_entry proc_ax25_bpqether = {
+ PROC_NET_AX25_BPQETHER, 13, "ax25_bpqether",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ ax25_bpq_get_info
+};
+#endif
+
void ax25_proto_init(struct net_proto *pro)
{
sock_register(ax25_proto_ops.family, &ax25_proto_ops);
#endif
register_netdevice_notifier(&ax25_dev_notifier);
#ifdef CONFIG_PROC_FS
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_AX25_ROUTE, 10, "ax25_route",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- ax25_rt_get_info
- });
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_AX25, 4, "ax25",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- ax25_get_info
- });
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_AX25_CALLS, 10, "ax25_calls",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- ax25_cs_get_info
- });
+ proc_net_register(&proc_ax25_route);
+ proc_net_register(&proc_ax25);
+ proc_net_register(&proc_ax25_calls);
#endif
printk(KERN_INFO "G4KLX/GW4PTS AX.25 for Linux. Version 0.32 for Linux NET3.035 (Linux 2.0)\n");
#ifdef CONFIG_BPQETHER
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_AX25_BPQETHER, 13, "ax25_bpqether",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- ax25_bpq_get_info
- });
+ proc_net_register(&proc_ax25_bpqether);
printk(KERN_INFO "G8BPQ Encapsulation of AX.25 frames enabled\n");
#endif
extern void sdla_setup(void);
extern void dlci_setup(void);
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_net_dev = {
+ PROC_NET_DEV, 3, "dev",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ dev_get_info
+};
+#endif
+
int net_dev_init(void)
{
struct device *dev, **dp;
#if defined(CONFIG_LANCE)
lance_init();
#endif
-#if defined(CONFIG_NI65)
- ni65_init();
-#endif
#if defined(CONFIG_PI)
pi_init();
#endif
}
#ifdef CONFIG_PROC_FS
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_DEV, 3, "dev",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- dev_get_info
- });
+ proc_net_register(&proc_net_dev);
#endif
/*
0
};
+#ifndef ALIAS_USER_LAND_DEBUG
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_net_alias_types = {
+ PROC_NET_ALIAS_TYPES, 11, "alias_types",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ net_alias_types_getinfo
+};
+static struct proc_dir_entry proc_net_aliases = {
+ PROC_NET_ALIASES, 7, "aliases",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ net_alias_getinfo
+};
+#endif
+#endif
/*
* net_alias initialisation
#ifndef ALIAS_USER_LAND_DEBUG
#ifdef CONFIG_PROC_FS
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_ALIAS_TYPES, 11, "alias_types",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- net_alias_types_getinfo
- });
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_ALIASES, 7, "aliases",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- net_alias_getinfo
- });
+ proc_net_register(&proc_net_alias_types);
+ proc_net_register(&proc_net_aliases);
#endif
#endif
extern unsigned long seq_offset;
+#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_INET_RARP
+static struct proc_dir_entry proc_net_rarp = {
+ PROC_NET_RARP, 4, "rarp",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ rarp_get_info
+};
+#endif /* RARP */
+static struct proc_dir_entry proc_net_raw = {
+ PROC_NET_RAW, 3, "raw",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ raw_get_info
+};
+static struct proc_dir_entry proc_net_snmp = {
+ PROC_NET_SNMP, 4, "snmp",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ snmp_get_info
+};
+static struct proc_dir_entry proc_net_sockstat = {
+ PROC_NET_SOCKSTAT, 8, "sockstat",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ afinet_get_info
+};
+static struct proc_dir_entry proc_net_tcp = {
+ PROC_NET_TCP, 3, "tcp",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ tcp_get_info
+};
+static struct proc_dir_entry proc_net_udp = {
+ PROC_NET_UDP, 3, "udp",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ udp_get_info
+};
+static struct proc_dir_entry proc_net_route = {
+ PROC_NET_ROUTE, 5, "route",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ rt_get_info
+};
+static struct proc_dir_entry proc_net_rtcache = {
+ PROC_NET_RTCACHE, 8, "rt_cache",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ rt_cache_get_info
+};
+#endif /* CONFIG_PROC_FS */
+
/*
* Called by socket.c on kernel startup.
*/
#ifdef CONFIG_PROC_FS
#ifdef CONFIG_INET_RARP
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_RARP, 4, "rarp",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- rarp_get_info
- });
+ proc_net_register(&proc_net_rarp);
#endif /* RARP */
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_RAW, 3, "raw",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- raw_get_info
- });
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_SNMP, 4, "snmp",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- snmp_get_info
- });
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_SOCKSTAT, 8, "sockstat",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- afinet_get_info
- });
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_TCP, 3, "tcp",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- tcp_get_info
- });
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_UDP, 3, "udp",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- udp_get_info
- });
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_ROUTE, 5, "route",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- rt_get_info
- });
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_RTCACHE, 8, "rt_cache",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- rt_cache_get_info
- });
+ proc_net_register(&proc_net_raw);
+ proc_net_register(&proc_net_snmp);
+ proc_net_register(&proc_net_sockstat);
+ proc_net_register(&proc_net_tcp);
+ proc_net_register(&proc_net_udp);
+ proc_net_register(&proc_net_route);
+ proc_net_register(&proc_net_rtcache);
#endif /* CONFIG_PROC_FS */
}
0
};
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_net_arp = {
+ PROC_NET_ARP, 3, "arp",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ arp_get_info
+};
+#endif
+
void arp_init (void)
{
/* Register the packet type */
register_netdevice_notifier(&arp_dev_notifier);
#ifdef CONFIG_PROC_FS
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_ARP, 3, "arp",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- arp_get_info
- });
+ proc_net_register(&proc_net_arp);
#endif
#ifdef CONFIG_ARPD
if (iph->protocol == IPPROTO_ICMP)
{
if ((fw_res = ip_fw_masq_icmp(&skb, dev2)) < 0)
+ {
+ if (rt)
+ ip_rt_put(rt);
/* Problem - ie bad checksum */
return -1;
+ }
if (fw_res)
/* ICMP matched - skip firewall */
#endif
+#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_IP_ACCT
+static struct proc_dir_entry proc_net_ipacct = {
+ PROC_NET_IPACCT, 7, "ip_acct",
+ S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ ip_acct_procinfo
+};
+#endif
+#endif
+
+#ifdef CONFIG_IP_FIREWALL
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_net_ipfwin = {
+ PROC_NET_IPFWIN, 8, "ip_input",
+ S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ ip_fw_in_procinfo
+};
+static struct proc_dir_entry proc_net_ipfwout = {
+ PROC_NET_IPFWOUT, 9, "ip_output",
+ S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ ip_fw_out_procinfo
+};
+static struct proc_dir_entry proc_net_ipfwfwd = {
+ PROC_NET_IPFWFWD, 10, "ip_forward",
+ S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ ip_fw_fwd_procinfo
+};
+#endif
+#endif
+
void ip_fw_init(void)
{
#ifdef CONFIG_PROC_FS
#ifdef CONFIG_IP_ACCT
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_IPACCT, 7, "ip_acct",
- S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
- 0, &proc_net_inode_operations,
- ip_acct_procinfo
- });
+ proc_net_register(&proc_net_ipacct);
#endif
#endif
#ifdef CONFIG_IP_FIREWALL
panic("Unable to register IP firewall.\n");
#ifdef CONFIG_PROC_FS
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_IPFWIN, 8, "ip_input",
- S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
- 0, &proc_net_inode_operations,
- ip_fw_in_procinfo
- });
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_IPFWOUT, 9, "ip_output",
- S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
- 0, &proc_net_inode_operations,
- ip_fw_out_procinfo
- });
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_IPFWFWD, 10, "ip_forward",
- S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
- 0, &proc_net_inode_operations,
- ip_fw_fwd_procinfo
- });
+ proc_net_register(&proc_net_ipfwin);
+ proc_net_register(&proc_net_ipfwout);
+ proc_net_register(&proc_net_ipfwfwd);
#endif
#endif
#ifdef CONFIG_IP_MASQUERADE
return len;
}
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_net_ipmsqhst = {
+ PROC_NET_IPMSQHST, 13, "ip_masquerade",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ ip_msqhst_procinfo
+};
+#endif
+
/*
* Initialize ip masquerading
*/
{
register_symtab (&ip_masq_syms);
#ifdef CONFIG_PROC_FS
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_IPMSQHST, 13, "ip_masquerade",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- ip_msqhst_procinfo
- });
+ proc_net_register(&proc_net_ipmsqhst);
#endif
ip_masq_app_init();
}
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_net_ip_masq_app = {
+ PROC_NET_IP_MASQ_APP, 11, "ip_masq_app",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ ip_masq_app_getinfo
+};
+#endif
+
/*
* Initialization routine
*/
register_symtab (&ip_masq_app_syms);
#ifdef CONFIG_PROC_FS
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_IP_MASQ_APP, 11, "ip_masq_app",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- ip_masq_app_getinfo
- });
+ proc_net_register(&proc_net_ip_masq_app);
#endif
return 0;
}
0
};
+#ifdef CONFIG_IP_MULTICAST
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_net_igmp = {
+ PROC_NET_IGMP, 4, "igmp",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ ip_mc_procinfo
+};
+#endif
+#endif
+
/*
* IP registers the packet type and then calls the subprotocol initialisers
*/
#ifdef CONFIG_IP_MULTICAST
#ifdef CONFIG_PROC_FS
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_IGMP, 4, "igmp",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- ip_mc_procinfo
- });
+ proc_net_register(&proc_net_igmp);
#endif
#endif
}
return len;
}
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_net_ipmr_vif = {
+ PROC_NET_IPMR_VIF, 9 ,"ip_mr_vif",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ ipmr_vif_info
+};
+static struct proc_dir_entry proc_net_ipmr_mfc = {
+ PROC_NET_IPMR_MFC, 11 ,"ip_mr_cache",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ ipmr_mfc_info
+};
+#endif
+
/*
* Setup for IP multicast routing
*/
printk(KERN_INFO "Linux IP multicast router 0.06.\n");
register_netdevice_notifier(&ip_mr_notifier);
#ifdef CONFIG_PROC_FS
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_IPMR_VIF, 9 ,"ip_mr_vif",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- ipmr_vif_info
- });
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_IPMR_MFC, 11 ,"ip_mr_cache",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- ipmr_mfc_info
- });
+ proc_net_register(&proc_net_ipmr_vif);
+ proc_net_register(&proc_net_ipmr_mfc);
#endif
}
return len;
}
+struct proc_dir_entry proc_net_rarp = {
+ PROC_NET_RARP, 4, "rarp",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ rarp_get_info
+};
+
void
rarp_init(void)
{
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_RARP, 4, "rarp",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- rarp_get_info
- });
+ proc_net_register(&proc_net_rarp);
rarp_ioctl_hook = rarp_ioctl;
}
sk->socket->flags &= ~SO_NOSPACE;
add_wait_queue(sk->sleep, &wait);
for (;;) {
+ if (current->signal & ~current->blocked)
+ break;
current->state = TASK_INTERRUPTIBLE;
if (tcp_memory_free(sk))
break;
skb->tail += copy;
skb->len += copy;
skb->csum = csum_partial(skb->tail - tcp_size, tcp_size, 0);
+ sk->write_seq += copy;
if (!sk->packets_out)
send = tcp_send_skb;
send(sk, skb);
from += retval;
copied += retval;
len -= retval;
- sk->write_seq += retval;
continue;
}
tcp_send_skb(sk, skb);
newsk->delay_acks = 1;
newsk->copied_seq = skb->seq+1;
newsk->fin_seq = skb->seq;
+ newsk->syn_seq = skb->seq;
newsk->state = TCP_SYN_RECV;
newsk->timeout = 0;
newsk->ip_xmit_timeout = 0;
* moved inline now as tcp_urg is only called from one
* place. We handle URGent data wrong. We have to - as
* BSD still doesn't use the correction from RFC961.
+ *
+ * For 1003.1g we should support a new option TCP_STDURG to permit
+ * either form.
*/
static void tcp_check_urg(struct sock * sk, struct tcphdr * th)
kill_pg(-sk->proc, SIGURG, 1);
}
}
+ /*
+ * We may be adding urgent data when the last byte read was
+ * urgent. To do this requires some care. We cannot just ignore
+ * sk->copied_seq since we would read the last urgent byte again
+ * as data, nor can we alter copied_seq until this data arrives
+ * or we break the sematics of SIOCATMARK (and thus sockatmark())
+ */
+ if (sk->urg_seq == sk->copied_seq)
+ sk->copied_seq++; /* Move the copied sequence on correctly */
sk->urg_data = URG_NOTYET;
sk->urg_seq = ptr;
}
{
struct tcphdr *th;
struct sock *sk;
- int syn_ok=0;
__u32 seq;
#ifdef CONFIG_IP_TRANSPARENT_PROXY
int r;
* Ok.. it's good. Set up sequence numbers and
* move to established.
*/
- syn_ok=1; /* Don't reset this connection for the syn */
sk->acked_seq = skb->seq+1;
sk->lastwin_seq = skb->seq+1;
sk->fin_seq = skb->seq;
return tcp_reset(sk,skb);
/*
- * !syn_ok is effectively the state test in RFC793.
+ * Check for a SYN, and ensure it matches the SYN we were
+ * first sent. We have to handle the rather unusual (but valid)
+ * sequence that KA9Q derived products may generate of
+ *
+ * SYN
+ * SYN|ACK Data
+ * ACK (lost)
+ * SYN|ACK Data + More Data
+ * .. we must ACK not RST...
+ *
+ * We keep syn_seq as the sequence space occupied by the
+ * original syn.
*/
- if(th->syn && !syn_ok)
+ if(th->syn && skb->seq!=sk->syn_seq)
{
tcp_send_reset(daddr,saddr,th, &tcp_prot, opt, dev, skb->ip_hdr->tos, 255);
return tcp_reset(sk,skb);
0
};
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_net_nr = {
+ PROC_NET_NR, 2, "nr",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ nr_get_info
+};
+static struct proc_dir_entry proc_net_nr_neigh = {
+ PROC_NET_NR_NEIGH, 8, "nr_neigh",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ nr_neigh_get_info
+};
+static struct proc_dir_entry proc_net_nr_nodes = {
+ PROC_NET_NR_NODES, 8, "nr_nodes",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ nr_nodes_get_info
+};
+#endif
+
void nr_proto_init(struct net_proto *pro)
{
sock_register(nr_proto_ops.family, &nr_proto_ops);
nr_default.paclen = NR_DEFAULT_PACLEN;
#ifdef CONFIG_PROC_FS
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_NR, 2, "nr",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- nr_get_info
- });
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_NR_NEIGH, 8, "nr_neigh",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- nr_neigh_get_info
- });
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_NR_NODES, 8, "nr_nodes",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- nr_nodes_get_info
- });
+ proc_net_register(&proc_net_nr);
+ proc_net_register(&proc_net_nr_neigh);
+ proc_net_register(&proc_net_nr_nodes);
#endif
}
unix_recvmsg
};
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_net_unix = {
+ PROC_NET_UNIX, 4, "unix",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ unix_get_info
+};
+#endif
void unix_proto_init(struct net_proto *pro)
{
printk(KERN_INFO "NET3: Unix domain sockets 0.12 for Linux NET3.035.\n");
sock_register(unix_proto_ops.family, &unix_proto_ops);
#ifdef CONFIG_PROC_FS
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_UNIX, 4, "unix",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- unix_get_info
- });
+ proc_net_register(&proc_net_unix);
#endif
}
/*