VERSION = 1
PATCHLEVEL = 3
-SUBLEVEL = 5
+SUBLEVEL = 6
ARCH = i386
.c.o:
$(CC) $(CFLAGS) -c -o $*.o $<
.S.s:
- $(CC) -D__ASSEMBLY__ -traditional -E -o $*.o $<
+ $(CC) -D__ASSEMBLY__ -traditional -E -o $*.s $<
.S.o:
$(CC) -D__ASSEMBLY__ -traditional -c -o $*.o $<
bool 'EtherExpress support' CONFIG_EEXPRESS n
bool 'NI5210 support' CONFIG_NI52 n
bool 'NI6510 support' CONFIG_NI65 n
+ if [ "$CONFIG_AX25" = "y" ]; then
+ bool 'Ottawa PI and PI/2 support' CONFIG_PI y
+ fi
bool 'WaveLAN support' CONFIG_WAVELAN n
fi
bool 'HP PCLAN+ (27247B and 27252A) support' CONFIG_HPLAN_PLUS n
bool 'HP PCLAN (27245 and other 27xxx series) support' CONFIG_HPLAN n
bool 'HP 10/100VG PCLAN (257X series) support' CONFIG_HP100 y
bool 'NE2000/NE1000 support' CONFIG_NE2000 y
- if [ "$CONFIG_AX25" = "y" ]; then
- bool 'Ottawa PI and PI/2 support' CONFIG_PI y
- fi
bool 'SK_G16 support' CONFIG_SK_G16 n
fi
bool 'EISA, VLB, PCI and on board controllers' CONFIG_NET_EISA n
*
* Authors: Jorge Cwik, <jorge@laser.satlink.net>
* Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ * Tom May, <ftom@netcom.com>
* Lots of code moved from tcp.c and ip.c; see those files
* for more names.
*
*/
unsigned int csum_partial(unsigned char * buff, int len, unsigned int sum) {
-#ifdef __i386__
+ /*
+ * Experiments with ethernet and slip connections show that buff
+ * is aligned on either a 2-byte or 4-byte boundary. We get at
+ * least a 2x speedup on 486 and Pentium if it is 4-byte aligned.
+ * Fortunately, it is easy to convert 2-byte alignment to 4-byte
+ * alignment for the unrolled loop.
+ */
__asm__("
+ testl $2, %%esi # Check alignment.
+ jz 2f # Jump if alignment is ok.
+ subl $2, %%ecx # Alignment uses up two bytes.
+ jae 1f # Jump if we had at least two bytes.
+ addl $2, %%ecx # ecx was < 2. Deal with it.
+ jmp 4f
+1: movw (%%esi), %%bx
+ addl $2, %%esi
+ addw %%bx, %%ax
+ adcl $0, %%eax
+2:
movl %%ecx, %%edx
- cld
shrl $5, %%ecx
jz 2f
- orl %%ecx, %%ecx
-1: movl (%%esi), %%eax
- adcl %%eax, %%ebx
- movl 4(%%esi), %%eax
- adcl %%eax, %%ebx
- movl 8(%%esi), %%eax
- adcl %%eax, %%ebx
- movl 12(%%esi), %%eax
- adcl %%eax, %%ebx
- movl 16(%%esi), %%eax
- adcl %%eax, %%ebx
- movl 20(%%esi), %%eax
- adcl %%eax, %%ebx
- movl 24(%%esi), %%eax
- adcl %%eax, %%ebx
- movl 28(%%esi), %%eax
- adcl %%eax, %%ebx
+ testl %%esi, %%esi
+1: movl (%%esi), %%ebx
+ adcl %%ebx, %%eax
+ movl 4(%%esi), %%ebx
+ adcl %%ebx, %%eax
+ movl 8(%%esi), %%ebx
+ adcl %%ebx, %%eax
+ movl 12(%%esi), %%ebx
+ adcl %%ebx, %%eax
+ movl 16(%%esi), %%ebx
+ adcl %%ebx, %%eax
+ movl 20(%%esi), %%ebx
+ adcl %%ebx, %%eax
+ movl 24(%%esi), %%ebx
+ adcl %%ebx, %%eax
+ movl 28(%%esi), %%ebx
+ adcl %%ebx, %%eax
lea 32(%%esi), %%esi
dec %%ecx
jne 1b
- adcl $0, %%ebx
+ adcl $0, %%eax
2: movl %%edx, %%ecx
- andl $28, %%ecx
+ andl $0x1c, %%edx
je 4f
- shrl $2, %%ecx
- orl %%ecx, %%ecx
-3: adcl (%%esi), %%ebx
+ shrl $2, %%edx
+ testl %%esi, %%esi
+3: adcl (%%esi), %%eax
lea 4(%%esi), %%esi
- dec %%ecx
+ dec %%edx
jne 3b
- adcl $0, %%ebx
-4: movl $0, %%eax
- testw $2, %%dx
- je 5f
- lodsw
- addl %%eax, %%ebx
- adcl $0, %%ebx
- movw $0, %%ax
-5: test $1, %%edx
+ adcl $0, %%eax
+4: andl $3, %%ecx
+ jz 7f
+ cmpl $2, %%ecx
+ jb 5f
+ movw (%%esi),%%cx
+ leal 2(%%esi),%%esi
je 6f
- lodsb
- addl %%eax, %%ebx
- adcl $0, %%ebx
-6: "
- : "=b"(sum)
+ shll $16,%%ecx
+5: movb (%%esi),%%cl
+6: addl %%ecx,%%eax
+ adcl $0, %%eax
+7: "
+ : "=a"(sum)
: "0"(sum), "c"(len), "S"(buff)
- : "ax", "bx", "cx", "dx", "si" );
-#else
-#error Not implemented for this CPU
-#endif
+ : "bx", "cx", "dx", "si");
return(sum);
}
unsigned int csum_partial_copyffs( char *src, char *dst,
int len, int sum) {
-#ifdef __i386__
__asm__("
- push %%ds
- push %%es
- movw %%ds, %%dx
- movw %%dx, %%es
- movw %%fs, %%dx
- movw %%dx, %%ds
- cld
- cmpl $32, %%ecx
- jb 2f
- pushl %%ecx
+ testl $2, %%edi # Check alignment.
+ jz 2f # Jump if alignment is ok.
+ subl $2, %%ecx # Alignment uses up two bytes.
+ jae 1f # Jump if we had at least two bytes.
+ addl $2, %%ecx # ecx was < 2. Deal with it.
+ jmp 4f
+1: movw %%fs:(%%esi), %%bx
+ addl $2, %%esi
+ movw %%bx, (%%edi)
+ addl $2, %%edi
+ addw %%bx, %%ax
+ adcl $0, %%eax
+2:
+ movl %%ecx, %%edx
shrl $5, %%ecx
- orl %%ecx, %%ecx
-1: movl (%%esi), %%eax
- movl 4(%%esi), %%edx
- adcl %%eax, %%ebx
- movl %%eax, %%es:(%%edi)
- adcl %%edx, %%ebx
- movl %%edx, %%es:4(%%edi)
-
- movl 8(%%esi), %%eax
- movl 12(%%esi), %%edx
- adcl %%eax, %%ebx
- movl %%eax, %%es:8(%%edi)
- adcl %%edx, %%ebx
- movl %%edx, %%es:12(%%edi)
-
- movl 16(%%esi), %%eax
- movl 20(%%esi), %%edx
- adcl %%eax, %%ebx
- movl %%eax, %%es:16(%%edi)
- adcl %%edx, %%ebx
- movl %%edx, %%es:20(%%edi)
-
- movl 24(%%esi), %%eax
- movl 28(%%esi), %%edx
- adcl %%eax, %%ebx
- movl %%eax, %%es:24(%%edi)
- adcl %%edx, %%ebx
- movl %%edx, %%es:28(%%edi)
+ jz 2f
+ testl %%esi, %%esi
+1: movl %%fs:(%%esi), %%ebx
+ adcl %%ebx, %%eax
+ movl %%ebx, (%%edi)
+
+ movl %%fs:4(%%esi), %%ebx
+ adcl %%ebx, %%eax
+ movl %%ebx, 4(%%edi)
+
+ movl %%fs:8(%%esi), %%ebx
+ adcl %%ebx, %%eax
+ movl %%ebx, 8(%%edi)
+
+ movl %%fs:12(%%esi), %%ebx
+ adcl %%ebx, %%eax
+ movl %%ebx, 12(%%edi)
+
+ movl %%fs:16(%%esi), %%ebx
+ adcl %%ebx, %%eax
+ movl %%ebx, 16(%%edi)
+
+ movl %%fs:20(%%esi), %%ebx
+ adcl %%ebx, %%eax
+ movl %%ebx, 20(%%edi)
+
+ movl %%fs:24(%%esi), %%ebx
+ adcl %%ebx, %%eax
+ movl %%ebx, 24(%%edi)
+
+ movl %%fs:28(%%esi), %%ebx
+ adcl %%ebx, %%eax
+ movl %%ebx, 28(%%edi)
lea 32(%%esi), %%esi
lea 32(%%edi), %%edi
dec %%ecx
jne 1b
- adcl $0, %%ebx
- popl %%ecx
-2: movl %%ecx, %%edx
- andl $28, %%ecx
+ adcl $0, %%eax
+2: movl %%edx, %%ecx
+ andl $28, %%edx
je 4f
- shrl $2, %%ecx
- orl %%ecx, %%ecx
-3: movl (%%esi), %%eax
- adcl %%eax, %%ebx
- movl %%eax, %%es:(%%edi)
+ shrl $2, %%edx
+ testl %%esi, %%esi
+3: movl %%fs:(%%esi), %%ebx
+ adcl %%ebx, %%eax
+ movl %%ebx, (%%edi)
lea 4(%%esi), %%esi
lea 4(%%edi), %%edi
- dec %%ecx
+ dec %%edx
jne 3b
- adcl $0, %%ebx
-4: movl $0, %%eax
- testl $2, %%edx
- je 5f
- lodsw
- stosw
- addl %%eax, %%ebx
- movw $0, %%ax
- adcl %%eax, %%ebx
-5: test $1, %%edx
+ adcl $0, %%eax
+4: andl $3, %%ecx
+ jz 7f
+ cmpl $2, %%ecx
+ jb 5f
+ movw %%fs:(%%esi), %%dx
+ leal 2(%%esi), %%esi
+ movw %%dx, (%%edi)
+ leal 2(%%edi), %%edi
je 6f
- lodsb
- stosb
- addl %%eax, %%ebx
- adcl $0, %%ebx
-6: pop %%es
- pop %%ds
+ shll $16,%%edx
+5: movb %%fs:(%%esi), %%dl
+ movb %%dl, (%%edi)
+6: addl %%edx, %%eax
+ adcl $0, %%eax
+7:
"
- : "=b"(sum)
- : "0"(sum), "c"(len), "S"(src), "D"(dst)
- : "ax", "bx", "cx", "dx", "si", "di" );
-#else
-#error Not implemented for this CPU
-#endif
+ : "=a" (sum)
+ : "0"(sum), "c"(len), "S"(src), "D" (dst)
+ : "bx", "cx", "dx", "si", "di" );
return(sum);
}
$(CC) $(CFLAGS) $(MATH_EMULATION) -c $<
.S.o:
- $(CC) -D__ASSEMBLER__ $(PARANOID) -c $<
+ $(CC) -D__ASSEMBLY__ $(PARANOID) -c $<
.s.o:
$(CC) -c $<
dep:
$(CPP) -M *.c > .depend
- $(CPP) -D__ASSEMBLER__ -M *.S >> .depend
+ $(CPP) -D__ASSEMBLY__ -M *.S >> .depend
proto:
cproto -e -DMAKING_PROTO *.c >fpu_proto.h
#ifndef _CONTROLW_H_
#define _CONTROLW_H_
-#ifdef __ASSEMBLER__
+#ifdef __ASSEMBLY__
#define _Const_(x) $##x
#else
#define _Const_(x) x
#define _EXCEPTION_H_
-#ifdef __ASSEMBLER__
+#ifdef __ASSEMBLY__
#define Const_(x) $##x
#else
#define Const_(x) x
#define PRECISION_LOST_DOWN Const_(EX_Precision)
-#ifndef __ASSEMBLER__
+#ifndef __ASSEMBLY__
#ifdef DEBUG
#define EXCEPTION(x) { printk("exception in %s at line %d\n", \
#define EXCEPTION(x) exception(x)
#endif
-#endif __ASSEMBLER__
+#endif __ASSEMBLY__
#endif _EXCEPTION_H_
*/
#define PECULIAR_486
-#ifdef __ASSEMBLER__
+#ifdef __ASSEMBLY__
#include "fpu_asm.h"
#define Const(x) $##x
#else
#define TW_Empty Const(7) /* empty */
-#ifndef __ASSEMBLER__
+#ifndef __ASSEMBLY__
#include <linux/math_emu.h>
#include <linux/linkage.h>
#include "fpu_proto.h"
#endif
-#endif __ASSEMBLER__
+#endif __ASSEMBLY__
#endif _FPU_EMU_H_
#include "fpu_emu.h" /* for definition of PECULIAR_486 */
-#ifdef __ASSEMBLER__
+#ifdef __ASSEMBLY__
#define Const__(x) $##x
#else
#define Const__(x) x
#define SW_Exc_Mask Const__(0x27f) /* Status word exception bit mask */
-#ifndef __ASSEMBLER__
+#ifndef __ASSEMBLY__
#define COMP_A_gt_B 1
#define COMP_A_eq_B 2
# define clear_C1()
#endif PECULIAR_486
-#endif __ASSEMBLER__
+#endif __ASSEMBLY__
#endif _STATUS_H_
outb_p (6, 0x3cf) ;
#endif
- /* normalise the palette registers, to point the * 16 screen colours to the first 16 DAC entries */
+ /* normalise the palette registers, to point the
+ * 16 screen colours to the first 16 DAC entries */
for (i=0; i<16; i++) {
inb_p (0x3da) ;
if (video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_VGAC) {
charmap = colourmap;
- beg = (video_type == VIDEO_TYPE_VGAC ? 0x06 : 0x0e) ;
+ beg = 0x0e;
+#ifdef VGA_CAN_DO_64KB
+ if (video_type == VIDEO_TYPE_VGAC)
+ beg = 0x06;
+#endif
} else if (video_type == VIDEO_TYPE_EGAM) {
charmap = blackwmap;
beg = 0x0a;
outb(AX_SYS, AX_CMD);
- skb = alloc_skb(pkt_len, GFP_ATOMIC);
+ skb = dev_alloc_skb(pkt_len);
/*
* Start of frame
*/
lp->stats.rx_dropped++;
return;
} else {
- skb->len = pkt_len;
skb->dev = dev;
/*
* receive mode.
*/
- insb(DATAPORT, skb->data, pkt_len);
+ insb(DATAPORT, skb_put(skb,pkt_len), pkt_len);
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
lp->stats.rx_packets++;
rlen = (len+1) & ~1;
- skb = alloc_skb(rlen, GFP_ATOMIC);
+ skb = dev_alloc_skb(rlen);
/*
* make sure the data register is going the right way
adapter->stats.rx_dropped++;
} else {
- skb->len = rlen;
skb->dev = dev;
/*
* now read the data from the adapter
*/
- ptr = (unsigned short *)(skb->data);
+ ptr = (unsigned short *)skb_put(skb,len);
for (i = 0; i < (rlen/2); i++) {
timeout = 0;
while ((inb_status(dev->base_addr)&HRDY) == 0 && timeout++ < 20000)
struct sk_buff *skb;
pkt_len &= 0x3fff;
- skb = alloc_skb(pkt_len, GFP_ATOMIC);
+ skb = dev_alloc_skb(pkt_len);
if (skb == NULL) {
printk("%s: Memory squeeze, dropping packet.\n", dev->name);
lp->stats.rx_dropped++;
skb->dev = dev;
/* 'skb->data' points to the start of sk_buff data area. */
- memcpy(skb->data, data_frame + 5, pkt_len);
+ memcpy(skb_put(skb,pkt_len), data_frame + 5, pkt_len);
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
short pkt_len = rx_status & 0x7ff;
struct sk_buff *skb;
- skb = alloc_skb(pkt_len+3, GFP_ATOMIC);
+ skb = dev_alloc_skb(pkt_len+3);
if (el3_debug > 4)
printk("Receiving packet size %d status %4.4x.\n",
pkt_len, rx_status);
if (skb != NULL) {
- skb->len = pkt_len;
skb->dev = dev;
/* 'skb->data' points to the start of sk_buff data area. */
- insl(ioaddr+RX_FIFO, skb->data,
+ insl(ioaddr+RX_FIFO, skb_put(skb,pkt_len),
(pkt_len + 3) >> 2);
skb->protocol=eth_type_trans(skb,dev);
} else if ((rx_frame.status & 0x0F) == ENRSR_RXOK) {
struct sk_buff *skb;
- skb = alloc_skb(pkt_len, GFP_ATOMIC);
+ skb = dev_alloc_skb(pkt_len);
if (skb == NULL) {
if (ei_debug > 1)
printk("%s: Couldn't allocate a sk_buff of size %d.\n",
ei_local->stat.rx_dropped++;
break;
} else {
- skb->len = pkt_len;
skb->dev = dev;
- ei_block_input(dev, pkt_len, (char *) skb->data,
+ ei_block_input(dev, pkt_len, skb_put(skb,pkt_len),
current_offset + sizeof(rx_frame));
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
{
/* a good frame */
int pkt_len = lp->scb.rfd->count & 0x3fff;
- struct sk_buff *skb = alloc_skb(pkt_len, GFP_ATOMIC);
+ struct sk_buff *skb = dev_alloc_skb(pkt_len);
frames++;
break;
}
- skb->len = pkt_len;
skb->dev = dev;
- memcpy(skb->data, lp->scb.rfd->data, pkt_len);
+ memcpy(skb_put(skb,pkt_len), lp->scb.rfd->data, pkt_len);
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
/* annoying functions for header/arp/etc building */
-int arc_header(unsigned char *buff,struct device *dev,unsigned short type,
- void *daddr,void *saddr,unsigned len,struct sk_buff *skb);
+int arc_header(struct sk_buff *skb,struct device *dev,unsigned short type,
+ void *daddr,void *saddr,unsigned len);
int arc_rebuild_header(void *eth,struct device *dev,unsigned long raddr,
struct sk_buff *skb);
unsigned short arc_type_trans(struct sk_buff *skb,struct device *dev);
in->sequence=arcsoft->sequence;
- skb = alloc_skb(length, GFP_ATOMIC);
+ skb = dev_alloc_skb(length);
if (skb == NULL) {
printk("%s: Memory squeeze, dropping packet.\n",
dev->name);
lp->stats.rx_dropped++;
return;
}
- soft=(struct ClientData *)skb->data;
+ soft=(struct ClientData *)skb_put(skb,length);
- skb->len = length;
skb->dev = dev;
memcpy((u_char *)soft+EXTRA_CLIENTDATA,
return;
}
- in->skb=skb=alloc_skb(508*in->numpackets
- + sizeof(struct ClientData),
- GFP_ATOMIC);
+ in->skb=skb=dev_alloc_skb(508*in->numpackets
+ + sizeof(struct ClientData));
if (skb == NULL) {
printk("%s: (split) memory squeeze, dropping packet.\n",
dev->name);
*/
skb->free=1;
- soft=(struct ClientData *)skb->data;
+ soft=(struct ClientData *)skb_put(skb,sizeof(struct ClientData));
- skb->len=sizeof(struct ClientData);
skb->dev=dev;
memcpy((u_char *)soft+EXTRA_CLIENTDATA,
return;
}
- soft=(struct ClientData *)in->skb->data;
+ soft=(struct ClientData *)skb->data;
}
skb=in->skb;
- memcpy(skb->data+skb->len,
+ memcpy(skb_put(skb,length-sizeof(struct ClientData)),
(u_char *)arcsoft+sizeof(struct ClientData),
length-sizeof(struct ClientData));
- skb->len+=length-sizeof(struct ClientData);
-
soft->daddr=daddr;
soft->saddr=saddr;
* saddr=NULL means use device source address (always will anyway)
* daddr=NULL means leave destination address (eg unresolved arp)
*/
-int arc_header(unsigned char *buff,struct device *dev,unsigned short type,
- void *daddr,void *saddr,unsigned len,struct sk_buff *skb)
+int arc_header(struct sk_buff *skb,struct device *dev,unsigned short type,
+ void *daddr,void *saddr,unsigned len)
{
- struct ClientData *head = (struct ClientData *)buff;
+ struct ClientData *head = (struct ClientData *)
+ skb_push(skb,dev->hard_header_len);
struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
/* set the protocol ID according to RFC-1201 */
lp->stats.rx_errors++;
break;
}
- skb = alloc_skb(pkt_len+1, GFP_ATOMIC);
+ skb = dev_alloc_skb(pkt_len+1);
if (skb == NULL) {
printk("%s: Memory squeeze, dropping packet (len %d).\n",
dev->name, pkt_len);
skb->len = pkt_len;
skb->dev = dev;
- insw(ioaddr + DATAPORT, skb->data, (pkt_len + 1) >> 1);
+ insw(ioaddr + DATAPORT, skb_put(skb,pkt_len), (pkt_len + 1) >> 1);
skb->protocol=eth_type_trans(skb, dev);
netif_rx(skb);
lp->stats.rx_packets++;
int pkt_len = (rx_head.rx_count & 0x7ff) - 4; /* The "-4" is omits the FCS (CRC). */
struct sk_buff *skb;
- skb = alloc_skb(pkt_len, GFP_ATOMIC);
+ skb = dev_alloc_skb(pkt_len);
if (skb == NULL) {
printk("%s: Memory squeeze, dropping packet.\n", dev->name);
lp->stats.rx_dropped++;
goto done;
}
- skb->len = pkt_len;
skb->dev = dev;
- read_block(ioaddr, pkt_len, skb->data, dev->if_port);
+ read_block(ioaddr, pkt_len, skb_put(skb,pkt_len), dev->if_port);
if (net_debug > 6) {
unsigned char *data = skb->data;
struct sk_buff *skb;
short pkt_len = (short)(lp->rx_ring[entry].status >> 16) - 4;
- if ((skb = alloc_skb(pkt_len, GFP_ATOMIC)) != NULL) {
- skb->len = pkt_len;
+ if ((skb = dev_alloc_skb(pkt_len)) != NULL) {
skb->dev = dev;
if (entry < lp->rx_old) { /* Wrapped buffer */
short len = (lp->rxRingSize - lp->rx_old) * RX_BUFF_SZ;
- memcpy(skb->data, bus_to_virt(lp->rx_ring[lp->rx_old].buf), len);
- memcpy(skb->data + len, bus_to_virt(lp->rx_ring[0].buf), pkt_len - len);
+ memcpy(skb_put(skb,len), bus_to_virt(lp->rx_ring[lp->rx_old].buf), len);
+ memcpy(skb_put(skb,pkt_len-len), bus_to_virt(lp->rx_ring[0].buf), pkt_len - len);
} else { /* Linear buffer */
- memcpy(skb->data, bus_to_virt(lp->rx_ring[lp->rx_old].buf), pkt_len);
+ memcpy(skb_put(skb,pkt_len), bus_to_virt(lp->rx_ring[lp->rx_old].buf), pkt_len);
}
/* Push up the protocol stack */
switch(ioc->cmd) {
case DE4X5_GET_HWADDR: /* Get the hardware address */
+ ioc->len = ETH_ALEN;
+ status = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len);
+ if (status)
+ break;
for (i=0; i<ETH_ALEN; i++) {
tmp.addr[i] = dev->dev_addr[i];
}
- ioc->len = ETH_ALEN;
- if (!(status = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len))) {
- memcpy_tofs(ioc->data, tmp.addr, ioc->len);
- }
-
+ memcpy_tofs(ioc->data, tmp.addr, ioc->len);
+
break;
case DE4X5_SET_HWADDR: /* Set the hardware address */
- if (suser()) {
- if (!(status = verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN))) {
- memcpy_fromfs(tmp.addr, ioc->data, ETH_ALEN);
- for (i=0; i<ETH_ALEN; i++) {
- dev->dev_addr[i] = tmp.addr[i];
- }
- build_setup_frame(dev, PHYS_ADDR_ONLY);
- /* Set up the descriptor and give ownership to the card */
- while (set_bit(0, (void *)&dev->tbusy) != 0);/* Wait for lock to free*/
- if (lp->setup_f == HASH_PERF) {
- load_packet(dev, lp->setup_frame, TD_IC | HASH_F | TD_SET |
- SETUP_FRAME_LEN, NULL);
- } else {
- load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET |
- SETUP_FRAME_LEN, NULL);
- }
- lp->tx_new = (++lp->tx_new) % lp->txRingSize;
- outl(POLL_DEMAND, DE4X5_TPD); /* Start the TX */
- dev->tbusy = 0; /* Unlock the TX ring */
- }
+ status = verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN);
+ if (status)
+ break;
+ status = -EPERM;
+ if (!suser())
+ break;
+ status = 0;
+ memcpy_fromfs(tmp.addr, ioc->data, ETH_ALEN);
+ for (i=0; i<ETH_ALEN; i++) {
+ dev->dev_addr[i] = tmp.addr[i];
+ }
+ build_setup_frame(dev, PHYS_ADDR_ONLY);
+ /* Set up the descriptor and give ownership to the card */
+ while (set_bit(0, (void *)&dev->tbusy) != 0);/* Wait for lock to free*/
+ if (lp->setup_f == HASH_PERF) {
+ load_packet(dev, lp->setup_frame, TD_IC | HASH_F | TD_SET |
+ SETUP_FRAME_LEN, NULL);
} else {
- status = -EPERM;
+ load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET |
+ SETUP_FRAME_LEN, NULL);
}
+ lp->tx_new = (++lp->tx_new) % lp->txRingSize;
+ outl(POLL_DEMAND, DE4X5_TPD); /* Start the TX */
+ dev->tbusy = 0; /* Unlock the TX ring */
break;
case DE4X5_SET_PROM: /* Set Promiscuous Mode */
break;
case DE4X5_GET_MCA: /* Get the multicast address table */
ioc->len = (HASH_TABLE_LEN >> 3);
- if (!(status = verify_area(VERIFY_WRITE, ioc->data, 192))) {
- memcpy_tofs(ioc->data, lp->setup_frame, 192);
- }
+ status = verify_area(VERIFY_WRITE, ioc->data, ioc->len);
+ if (status)
+ break;
+ memcpy_tofs(ioc->data, lp->setup_frame, ioc->len);
break;
case DE4X5_SET_MCA: /* Set a multicast address */
break;
case DE4X5_GET_STATS: /* Get the driver statistics */
- cli();
ioc->len = sizeof(lp->pktStats);
- if (!(status = verify_area(VERIFY_WRITE, (void *)ioc->data, sizeof(lp->pktStats)))) {
- memcpy_tofs(ioc->data, &lp->pktStats, ioc->len);
- }
+ status = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len);
+ if (status)
+ break;
+
+ cli();
+ memcpy_tofs(ioc->data, &lp->pktStats, ioc->len);
sti();
break;
return;
}
- skb = alloc_skb(size, GFP_ATOMIC);
+ skb = dev_alloc_skb(size);
sti();
if (skb == NULL) {
printk("%s: Couldn't allocate a sk_buff of size %d.\n",
}
/* else */
- skb->lock = 0;
+ skb->dev = dev;
+
/* 'skb->data' points to the start of sk_buff data area. */
- buffer = skb->data;
+ buffer = skb_put(skb,size);
/* copy the packet into the buffer */
de600_setup_address(read_from, RW_ADDR);
((struct netstats *)(dev->priv))->rx_packets++; /* count all receives */
skb->protocol=eth_type_trans(skb,dev);
- if (dev_rint((unsigned char *)skb, size, IN_SKBUFF, dev))
- printk("%s: receive buffers full.\n", dev->name);
+
+ netif_rx(skb);
/*
- * If any worth-while packets have been received, dev_rint()
+ * If any worth-while packets have been received, netif_rx()
* has done a mark_bh(INET_BH) for us and will work on them
* when we get to the bottom-half routine.
*/
printk("%s: Illegal packet size: %d!\n", dev->name, size);
}
else { /* Good packet? */
- skb = alloc_skb(size, GFP_ATOMIC);
+ skb = dev_alloc_skb(size);
if (skb == NULL) { /* Yeah, but no place to put it... */
printk("%s: Couldn't allocate a sk_buff of size %d.\n",
dev->name, size);
((struct netstats *)(dev->priv))->rx_dropped++;
}
else { /* Yep! Go get it! */
- skb->len = size; skb->dev = dev; skb->free = 1;
+ skb->dev = dev;
+ skb->free = 1;
/* skb->data points to the start of sk_buff data area */
- buffer = skb->data;
+ buffer = skb_put(skb,size);
/* copy the packet into the buffer */
de620_read_block(buffer, size);
PRINTK(("Read %d bytes\n", size));
struct depca_private *lp = (struct depca_private *)dev->priv;
int i, entry;
s32 status;
- char *buf;
for (entry=lp->rx_new;
!(readl(&lp->rx_ring[entry].base) & R_OWN);
short len, pkt_len = readw(&lp->rx_ring[entry].msg_length);
struct sk_buff *skb;
- skb = alloc_skb(pkt_len, GFP_ATOMIC);
+ skb = dev_alloc_skb(pkt_len);
if (skb != NULL) {
- skb->len = pkt_len;
+ unsigned char * 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(skb->data, lp->rx_memcpy[lp->rx_old], len);
- memcpy_fromio(skb->data+len, lp->rx_memcpy[0], pkt_len-len);
+ 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(skb->data, lp->rx_memcpy[lp->rx_old], pkt_len);
+ memcpy_fromio(buf, lp->rx_memcpy[lp->rx_old], pkt_len);
}
/*
i = DEPCA_PKT_STAT_SZ;
}
}
- buf = skb->data; /* Look at the dest addr */
if (buf[0] & 0x01) { /* Multicast/Broadcast */
if ((*(s32 *)&buf[0] == -1) && (*(s16 *)&buf[4] == -1)) {
lp->pktStats.broadcast++;
struct sk_buff *skb;
rcv_size &= 0x3fff;
- skb = alloc_skb(rcv_size, GFP_ATOMIC);
+ skb = dev_alloc_skb(rcv_size);
if (skb == NULL) {
printk("%s: Memory squeeze, dropping packet.\n", dev->name);
lp->stats.rx_dropped++;
break;
}
- skb->len = rcv_size;
skb->dev = dev;
- insw(ioaddr+IO_PORT, skb->data, (rcv_size + 1) >> 1);
+ insw(ioaddr+IO_PORT, skb_put(skb,rcv_size), (rcv_size + 1) >> 1);
skb->protocol = eth_type_trans(skb,dev);
netif_rx(skb);
struct sk_buff *skb;
pkt_len &= 0x3fff;
- skb = alloc_skb(pkt_len, GFP_ATOMIC);
+ skb = dev_alloc_skb(pkt_len);
if (skb == NULL) {
printk("%s: Memory squeeze, dropping packet.\n", dev->name);
lp->stats.rx_dropped++;
break;
}
- skb->len = pkt_len;
skb->dev = dev;
outw(data_buffer_addr + 10, ioaddr + READ_PTR);
- insw(ioaddr, skb->data, (pkt_len + 1) >> 1);
+ insw(ioaddr, skb_put(skb,pkt_len), (pkt_len + 1) >> 1);
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
static int eql_slave_xmit(struct sk_buff *skb, struct device *dev); /* */
static struct enet_statistics *eql_get_stats(struct device *dev); /* */
-static int eql_header(unsigned char *buff, struct device *dev,
+static int eql_header(struct sk_buff *skb, struct device *dev,
unsigned short type, void *daddr, void *saddr,
- unsigned len, struct sk_buff *skb); /* */
+ unsigned len); /* */
static int eql_rebuild_header(void *buff, struct device *dev,
unsigned long raddr, struct sk_buff *skb); /* */
static
int
-eql_header(unsigned char *buff, struct device *dev,
+eql_header(struct sk_buff *skb, struct device *dev,
unsigned short type, void *daddr, void *saddr,
- unsigned len, struct sk_buff *skb)
+ unsigned len)
{
return 0;
}
struct device *master_dev;
struct device *slave_dev;
slaving_request_t srq;
+ int err;
+
+ err = verify_area(VERIFY_READ, (void *)srqp, sizeof (slaving_request_t));
+ if (err) return err;
memcpy_fromfs (&srq, srqp, sizeof (slaving_request_t));
struct device *master_dev;
struct device *slave_dev;
slaving_request_t srq;
+ int err;
+
+ err = verify_area(VERIFY_READ, (void *)srqp, sizeof (slaving_request_t));
+ if (err) return err;
memcpy_fromfs (&srq, srqp, sizeof (slaving_request_t));
equalizer_t *eql;
struct device *slave_dev;
slave_config_t sc;
+ int err;
+
+ err = verify_area(VERIFY_READ, (void *)scp, sizeof (slave_config_t));
+ if (err) return err;
memcpy_fromfs (&sc, scp, sizeof (slave_config_t));
if (slave != 0)
{
sc.priority = slave->priority;
+
+ err = verify_area(VERIFY_WRITE, (void *)scp, sizeof (slave_config_t));
+ if (err) return err;
+
memcpy_tofs (scp, &sc, sizeof (slave_config_t));
return 0;
}
equalizer_t *eql;
struct device *slave_dev;
slave_config_t sc;
+ int err;
+
+ err = verify_area(VERIFY_READ, (void *)scp, sizeof (slave_config_t));
+ if (err) return err;
#ifdef EQL_DEBUG
if (eql_debug >= 20)
if ( eql_is_master (dev) )
{
+ int err;
+
+ err = verify_area(VERIFY_WRITE, (void *)mcp, sizeof (master_config_t));
+ if (err) return err;
+
eql = (equalizer_t *) dev->priv;
mc.max_slaves = eql->max_slaves;
mc.min_slaves = eql->min_slaves;
{
equalizer_t *eql;
master_config_t mc;
+ int err;
+
+ err = verify_area(VERIFY_READ, (void *)mcp, sizeof (master_config_t));
+ if (err) return err;
#if EQL_DEBUG
if (eql_debug >= 20)
} else {
struct sk_buff *skb;
- if ((skb = alloc_skb(pkt_len, GFP_ATOMIC)) != NULL) {
- skb->len = pkt_len;
+ if ((skb = dev_alloc_skb(pkt_len)) != NULL) {
skb->dev = dev;
if (lp->shmem_length == IO_ONLY) {
- unsigned char *p = skb->data;
+ unsigned char *p = skb_put(skb,pkt_len);
*p = inb(EWRK3_DATA); /* dummy read */
for (i=0; i<skb->len; i++) {
unsigned char addr[HASH_TABLE_LEN * ETH_ALEN];
unsigned short val[(HASH_TABLE_LEN * ETH_ALEN) >> 1];
} tmp;
+ int err;
switch(ioc->cmd) {
case EWRK3_GET_HWADDR: /* Get the hardware address */
tmp.addr[i] = dev->dev_addr[i];
}
ioc->len = ETH_ALEN;
+
+ err = verify_area(VERIFY_WRITE, (void *)ioc->data, ETH_ALEN);
+ if (err) return err;
memcpy_tofs(ioc->data, tmp.addr, ioc->len);
break;
csr |= (TXD|RXD);
outb(csr, EWRK3_CSR); /* Disable the TX and RX */
+ err = verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN);
+ if (err) return err;
memcpy_fromfs(tmp.addr,ioc->data,ETH_ALEN);
for (i=0; i<ETH_ALEN; i++) {
dev->dev_addr[i] = tmp.addr[i];
break;
case EWRK3_GET_MCA: /* Get the multicast address table */
+ err = verify_area(VERIFY_WRITE, (void *)ioc->data, HASH_TABLE_LEN >> 3);
+ if (err) return err;
+
while (set_bit(0, (void *)&lp->lock) != 0); /* Wait for lock to free */
if (lp->shmem_length == IO_ONLY) {
outb(0, EWRK3_IOPR);
break;
case EWRK3_SET_MCA: /* Set a multicast address */
if (suser()) {
+ err = verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN * ioc->len);
+ if (err) return err;
+
if (ioc->len != HASH_TABLE_LEN) { /* MCA changes */
memcpy_fromfs(tmp.addr, ioc->data, ETH_ALEN * ioc->len);
}
break;
case EWRK3_GET_STATS: /* Get the driver statistics */
+ err = verify_area(VERIFY_WRITE, (void *)ioc->data, sizeof(lp->pktStats)));
+ if (err) return err;
+
cli();
memcpy_tofs(ioc->data, &lp->pktStats, sizeof(lp->pktStats));
ioc->len = EWRK3_PKT_STAT_SZ;
break;
case EWRK3_GET_CSR: /* Get the CSR Register contents */
+ err = verify_area(VERIFY_WRITE, (void *)ioc->data, 1);
+ if (err) return err;
+
tmp.addr[0] = inb(EWRK3_CSR);
memcpy_tofs(ioc->data, tmp.addr, 1);
break;
case EWRK3_SET_CSR: /* Set the CSR Register contents */
+ err = verify_area(VERIFY_READ, (void *)ioc->data, 1);
+ if (err) return err;
+
if (suser()) {
memcpy_fromfs(tmp.addr, ioc->data, 1);
outb(tmp.addr[0], EWRK3_CSR);
break;
case EWRK3_GET_EEPROM: /* Get the EEPROM contents */
if (suser()) {
+ err = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len);
+ if (err) return err;
+
for (i=0; i<(EEPROM_MAX>>1); i++) {
tmp.val[i] = (short)Read_EEPROM(iobase, i);
}
break;
case EWRK3_SET_EEPROM: /* Set the EEPROM contents */
if (suser()) {
+ err = verify_area(VERIFY_READ, (void *)ioc->data, EEPROM_MAX);
+ if (err) return err;
+
memcpy_fromfs(tmp.addr, ioc->data, EEPROM_MAX);
for (i=0; i<(EEPROM_MAX>>1); i++) {
Write_EEPROM(tmp.val[i], iobase, i);
break;
case EWRK3_GET_CMR: /* Get the CMR Register contents */
+ err = verify_area(VERIFY_WRITE, (void *)ioc->data, 1);
+ if (err) return err;
+
tmp.addr[0] = inb(EWRK3_CMR);
memcpy_tofs(ioc->data, tmp.addr, 1);
printk( "hp100_rx: new packet - length = %d, errors = 0x%x, dest = 0x%x\n",
header & HP100_PKT_LEN_MASK, ( header >> 16 ) & 0xfff8, ( header >> 16 ) & 7 );
#endif
- skb = alloc_skb( ( pkt_len + 3 ) & ~3, GFP_ATOMIC );
+ /*
+ * NOTE! This (and the skb_put() below) depends on the skb-functions
+ * allocating more than asked (notably, aligning the request up to
+ * the next 16-byte length).
+ */
+ skb = dev_alloc_skb(pkt_len);
if ( skb == NULL )
{
#ifdef HP100_DEBUG
}
else
{
- skb -> len = pkt_len;
skb -> dev = dev;
- insl( ioaddr + HP100_REG_DATA32, skb -> data, ( pkt_len + 3 ) >> 2 );
+ insl( ioaddr + HP100_REG_DATA32, skb_put(pkt_len), ( pkt_len + 3 ) >> 2 );
skb->protocol=eth_type_trans(skb,dev);
netif_rx( skb );
lp -> stats.rx_packets++;
#endif
- if(!(skb=alloc_skb(ntohs(rec_req->frame_len)-lan_hdr_len+sizeof(struct trh_hdr), GFP_ATOMIC))) {
+ if(!(skb=dev_alloc_skb(ntohs(rec_req->frame_len)-lan_hdr_len+sizeof(struct trh_hdr)))) {
DPRINTK("out of memory. frame dropped.\n");
ti->tr_stats.rx_dropped++;
rec_resp->ret_code=DATA_LOST;
return;
}
- skb->len=ntohs(rec_req->frame_len)-lan_hdr_len+sizeof(struct trh_hdr);
+ skb_put(skb,ntohs(rec_req->frame_len)-lan_hdr_len+sizeof(struct trh_hdr));
skb->dev=dev;
#if 0
short pkt_len = (lp->rx_ring[entry].msg_length & 0xfff)-4;
struct sk_buff *skb;
- skb = alloc_skb(pkt_len, GFP_ATOMIC);
+ skb = dev_alloc_skb(pkt_len);
if (skb == NULL) {
printk("%s: Memory squeeze, deferring packet.\n", dev->name);
for (i=0; i < RX_RING_SIZE; i++)
}
break;
}
- skb->len = pkt_len;
skb->dev = dev;
- memcpy(skb->data,
+ memcpy(skb_put(skb,pkt_len),
(unsigned char *)(lp->rx_ring[entry].base & 0x00ffffff),
pkt_len);
skb->protocol=eth_type_trans(skb,dev);
*/
save_flags(flags);
cli();
- skb->sk->wmem_alloc-=skb->mem_len;
+ skb->sk->wmem_alloc-=skb->truesize;
skb->sk->write_space(skb->sk);
restore_flags(flags);
}
return dev;
}
+
+static int eth_mac_addr(struct device *dev, void * addr)
+{
+ struct ifreq * ifr = (struct ifreq *) addr;
+
+ if(dev->start)
+ return -EBUSY;
+ memcpy(dev->dev_addr, ifr->ifr_hwaddr.sa_data,dev->hard_header_len);
+ return 0;
+}
+
void ether_setup(struct device *dev)
{
int i;
dev->hard_header = eth_header;
dev->rebuild_header = eth_rebuild_header;
+ dev->set_mac_address = eth_mac_addr;
dev->type = ARPHRD_ETHER;
dev->hard_header_len = ETH_HLEN;
{
totlen &= RBD_MASK; /* length of this frame */
rbd->status = 0;
- skb = (struct sk_buff *) alloc_skb(totlen, GFP_ATOMIC);
+ skb = (struct sk_buff *) dev_alloc_skb(totlen);
if(skb != NULL)
{
- skb->len = totlen;
skb->dev = dev;
- memcpy( (char *) skb->data,(char *) p->base+(unsigned long) rbd->buffer, totlen);
+ memcpy(skb_put(skb,totlen),(char *) p->base+(unsigned long) rbd->buffer, totlen);
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
p->stats.rx_packets++;
for(i=0;i<RMDNUM;i++)
{
- if( (p->recv_skb[i] = (struct sk_buff *) alloc_skb(R_BUF_SIZE,GFP_ATOMIC)) == NULL) {
+ if( (p->recv_skb[i] = dev_alloc_skb(R_BUF_SIZE)) == NULL) {
printk("%s: unable to alloc recv-mem\n",dev->name);
return EAGAIN;
}
else
{
len = (rmdp->mlen & 0x0fff) - 4; /* -4: ignore FCS */
- skb = alloc_skb(R_BUF_SIZE,GFP_ATOMIC);
+ skb = dev_alloc_skb(R_BUF_SIZE);
if(skb != NULL)
{
if( (unsigned long) (skb->data + R_BUF_SIZE) & 0xff000000) {
- memcpy(skb->data,p->recv_skb[p->rmdnum]->data,len);
+ memcpy(skb_put(skb,len),p->recv_skb[p->rmdnum]->data,len);
skb1 = skb;
}
else {
skb1 = p->recv_skb[p->rmdnum];
p->recv_skb[p->rmdnum] = skb;
- rmdp->u.buffer = (unsigned long) (skb->data);
+ rmdp->u.buffer = (unsigned long) skb_put(skb1,len);
}
rmdp->u.s.status = RCV_OWN;
rmdp->mlen = 0; /* not necc ???? */
- skb1->len = len;
skb1->dev = dev;
p->stats.rx_packets++;
skb1->protocol=eth_type_trans(skb1,dev);
struct sk_buff *skb;
int sksize, pkt_len;
struct mbuf *cur_buf;
+ unsigned char *cfix;
save_flags(flags);
cli(); /* disable interrupts */
/* Malloc up new buffer. */
sksize = pkt_len;
- skb = alloc_skb(sksize, GFP_ATOMIC);
+ skb = dev_alloc_skb(sksize);
if (skb == NULL) {
printk("PI: %s: Memory squeeze, dropping packet.\n", dev->name);
lp->stats.rx_dropped++;
restore_flags(flags);
return;
}
- skb->len = (unsigned long) pkt_len;
skb->dev = dev;
/* KISS kludge - prefix with a 0 byte */
- skb->data[0] = 0;
+ cfix=skb_put(skb,pkt_len);
+ *cfix++=0;
/* 'skb->data' points to the start of sk_buff data area. */
- memcpy(&skb->data[1], (char *) cur_buf->data,
+ memcpy(cfix, (char *) cur_buf->data,
pkt_len - 1);
- skb->protocol=ntohs(ETH_P_AX25);
+ skb->protocol=htons(ETH_P_AX25);
+ IS_SKB(skb);
netif_rx(skb);
lp->stats.rx_packets++;
} /* end good frame */
struct sk_buff *skb;
int sksize;
int pkt_len;
+ unsigned char *cfix;
save_flags(flags);
cli(); /* disable interrupts */
/* Malloc up new buffer. */
sksize = pkt_len;
- skb = alloc_skb(sksize, GFP_ATOMIC);
+ skb = dev_alloc_skb(sksize);
if (skb == NULL) {
printk("PI: %s: Memory squeeze, dropping packet.\n", dev->name);
lp->stats.rx_dropped++;
restore_flags(flags);
return;
}
- skb->len = pkt_len;
skb->dev = dev;
/* KISS kludge - prefix with a 0 byte */
- skb->data[0] = 0;
+ cfix=skb_put(skb,pkt_len);
+ *cfix++=0;
/* 'skb->data' points to the start of sk_buff data area. */
- memcpy(&skb->data[1], lp->rcvbuf->data, pkt_len - 1);
+ memcpy(cfix, lp->rcvbuf->data, pkt_len - 1);
skb->protocol=ntohs(ETH_P_AX25);
+ IS_SKB(skb);
netif_rx(skb);
lp->stats.rx_packets++;
/* packet queued - initialize buffer for next frame */
}
/* Fill in the MAC-level header. */
-static int pi_header(unsigned char *buff, struct device *dev, unsigned short type,
- void *daddr, void *saddr, unsigned len, struct sk_buff *skb)
+static int pi_header(struct sk_buff *skb, struct device *dev, unsigned short type,
+ void *daddr, void *saddr, unsigned len)
{
- return ax25_encapsulate(buff, dev, type, daddr, saddr, len, skb);
+ return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
}
/* Rebuild the MAC-level header. */
dev->rebuild_header = pi_rebuild_header;
dev->set_mac_address = pi_set_mac_address;
- dev->type = AF_AX25; /* AF_AX25 device */
+ dev->type = ARPHRD_AX25; /* AF_AX25 device */
dev->hard_header_len = 17; /* We don't do digipeaters */
dev->mtu = 1500; /* eth_mtu is the default */
dev->addr_len = 7; /* sizeof an ax.25 address */
- for (i = 0; i < ETH_ALEN; i++) {
- dev->broadcast[i] = 0xff;
- }
memcpy(dev->broadcast, ax25_bcast, 7);
memcpy(dev->dev_addr, ax25_test, 7);
return ERROR;
}
/* Malloc up new buffer. */
- rcv->skb = alloc_skb(rcv->length.h, GFP_ATOMIC);
+ rcv->skb = dev_alloc_skb(rcv->length.h);
if (rcv->skb == NULL) {
printk("%s: Memory squeeze.\n", dev->name);
return ERROR;
}
- rcv->skb->len = rcv->length.h;
+ skb_put(rcv->skb,rcv->length.h);
rcv->skb->dev = dev;
rcv->state = PLIP_PK_DATA;
rcv->byte = 0;
-/*
- PPP for Linux
+/* PPP for Linux
*/
/*
static int ppp_do_ip(struct ppp *, unsigned short, unsigned char *, int);
static int ppp_us_queue(struct ppp *, unsigned short, unsigned char *, int);
static int ppp_xmit(struct sk_buff *, struct device *);
-static unsigned short ppp_type_trans(struct sk_buff *, struct device *);
#ifdef NET02D
static int ppp_header(unsigned char *buff, struct device *dev,
static void ppp_add_arp(unsigned long addr, struct sk_buff *skb,
struct device *dev);
#else
-static int ppp_header(unsigned char *, struct device *, unsigned short,
- void *, void *, unsigned, struct sk_buff *);
+static int ppp_header(struct sk_buff *, struct device *, unsigned short,
+ void *, void *, unsigned);
static int ppp_rebuild_header(void *, struct device *, unsigned long,
struct sk_buff *);
#endif
struct slcompress slhc;
} *result;
- error = verify_area (VERIFY_READ,
+ error = verify_area (VERIFY_WRITE,
ifr->ifr_ifru.ifru_data,
sizeof (struct stats));
/* receive the frame through the network software */
- skb=alloc_skb(count, GFP_ATOMIC);
+ skb=dev_alloc_skb(count);
if(skb)
{
- memcpy(skb->data, c,count);
+ memcpy(skb_put(skb,count), c,count);
skb->protocol=htons(ETH_P_IP);
skb->dev=ppp->dev;
skb->len=count;
#else
static int
-ppp_header(unsigned char *buff, struct device *dev, unsigned short type,
- void *daddr, void *saddr, unsigned len, struct sk_buff *skb)
+ppp_header(struct sk_buff *skb, struct device *dev, unsigned short type,
+ void *daddr, void *saddr, unsigned len)
{
return(0);
}
int len = (rmdp->mlen & 0x0fff); /* extract message length from receive buffer */
struct sk_buff *skb;
- skb = alloc_skb(len, GFP_ATOMIC); /* allocate socket buffer */
+ skb = dev_alloc_skb(len); /* allocate socket buffer */
if (skb == NULL) /* Could not get mem ? */
{
/* Prepare sk_buff to queue for upper layers */
- skb->len = len;
skb->dev = dev;
/*
* ignore status fields)
*/
- memcpy(skb->data, (unsigned char *) (rmdp->u.buffer & 0x00ffffff),
+ memcpy(skb_put(skb,len), (unsigned char *) (rmdp->u.buffer & 0x00ffffff),
len);
/* Malloc up new buffer. */
struct sk_buff *skb;
- skb = alloc_skb(pkt_len, GFP_ATOMIC);
+ skb = dev_alloc_skb(pkt_len);
if (skb == NULL) {
printk("%s: Memory squeeze, dropping packet.\n", dev->name);
lp->stats.rx_dropped++;
break;
}
- skb->len = pkt_len;
skb->dev = dev;
/* 'skb->data' points to the start of sk_buff data area. */
- memcpy(skb->data, (void*)dev->rmem_start,
+ memcpy(skb_put(skb,pkt_len), (void*)dev->rmem_start,
pkt_len);
/* or */
insw(ioaddr, skb->data, (pkt_len + 1) >> 1);
}
#endif /* SL_INCLUDE_CSLIP */
- skb = alloc_skb(count, GFP_ATOMIC);
+ skb = dev_alloc_skb(count);
if (skb == NULL) {
printk("%s: memory squeeze, dropping packet.\n", sl->dev->name);
sl->rx_dropped++;
return;
}
- skb->len = count;
skb->dev = sl->dev;
- memcpy(skb->data, sl->rbuff, count);
+ memcpy(skb_put(skb,count), sl->rbuff, count);
if(sl->mode&(SL_MODE_AX25|SL_MODE_AX25VC))
skb->protocol=htons(ETH_P_AX25);
else
/* Fill in the MAC-level header. Not used by SLIP. */
static int
-sl_header(unsigned char *buff, struct device *dev, unsigned short type,
- void *daddr, void *saddr, unsigned len, struct sk_buff *skb)
+sl_header(struct sk_buff *skb, struct device *dev, unsigned short type,
+ void *daddr, void *saddr, unsigned len)
{
#ifdef CONFIG_AX25
#ifdef CONFIG_INET
struct slip *sl = &sl_ctrl[dev->base_addr];
if (((sl->mode & SL_MODE_AX25) || (sl->mode & SL_MODE_AX25VC)) && type != htons(ETH_P_AX25)) {
- return ax25_encapsulate(buff, dev, type, daddr, saddr, len, skb);
+ return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
}
#endif
#endif
switch(cmd) {
case SIOCGIFNAME:
- err = verify_area(VERIFY_WRITE, arg, 16);
+ err = verify_area(VERIFY_WRITE, arg, strlen(sl->dev->name) + 1);
if (err) {
return -err;
}
short pkt_len = lp->rx_ring[entry].status >> 16;
struct sk_buff *skb;
- skb = alloc_skb(pkt_len, GFP_ATOMIC);
+ skb = dev_alloc_skb(pkt_len);
if (skb == NULL) {
printk("%s: Memory squeeze, deferring packet.\n", dev->name);
/* Check that at least two ring entries are free.
}
break;
}
- skb->len = pkt_len;
skb->dev = dev;
- memcpy(skb->data, lp->rx_ring[entry].buffer1, pkt_len);
+ memcpy(skb_put(skb,pkt_len), lp->rx_ring[entry].buffer1, pkt_len);
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
lp->stats.rx_packets++;
*/
newlen = (skb->len + ip_header_len);
- if ( !(skb2 = alloc_skb(newlen, GFP_ATOMIC)) )
+ if ( !(skb2 = dev_alloc_skb(newlen)) )
{
printk("%s: No free memory.\n",dev->name);
dev_kfree_skb(skb, FREE_WRITE);
/* Copy the packet to a new buffer, adding a new ip header */
skb2->free=1;
- skb2->len=newlen;
+ skb_put(skb2,newlen);
iph=skb2->h.iph=(struct iphdr *)skb2->data;
memcpy(skb2->h.iph, skb->data, ip_header_len );
memcpy(skb2->data + ip_header_len, skb->data, skb->len);
sksize = pkt_len;
- if ((skb = alloc_skb(sksize, GFP_ATOMIC)) == (struct sk_buff *)0)
+ if ((skb = dev_alloc_skb(sksize)) == (struct sk_buff *)0)
{
printk("%s: could not alloc_skb(%d, GFP_ATOMIC).\n", dev->name, sksize);
lp->stats.rx_dropped++;
}
else
{
- skb->len = pkt_len;
skb->dev = dev;
- obram_read(ioaddr, rbd.rbd_bufl, skb->data, pkt_len);
+ obram_read(ioaddr, rbd.rbd_bufl, skb_put(skb,pkt_len), pkt_len);
if (wavelan_debug > 5)
{
/* Malloc up new buffer. */
struct sk_buff *skb;
- skb = alloc_skb(pkt_len, GFP_ATOMIC);
+ skb = dev_alloc_skb(pkt_len);
if (skb == NULL) {
if (znet_debug)
printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
lp->stats.rx_dropped++;
break;
}
- skb->len = pkt_len;
skb->dev = dev;
if (&zn.rx_cur[(pkt_len+1)>>1] > zn.rx_end) {
int semi_cnt = (zn.rx_end - zn.rx_cur)<<1;
- memcpy((unsigned char *) (skb + 1), zn.rx_cur, semi_cnt);
- memcpy((unsigned char *) (skb + 1) + semi_cnt, zn.rx_start,
+ memcpy(skb_put(skb,semi_cnt), zn.rx_cur, semi_cnt);
+ memcpy(skb_put(skb,pkt_len-semi_cnt), zn.rx_start,
pkt_len - semi_cnt);
} else {
- memcpy((unsigned char *) (skb + 1), zn.rx_cur, pkt_len);
+ memcpy(skb_put(skb,pkt_len), zn.rx_cur, pkt_len);
if (znet_debug > 6) {
unsigned int *packet = (unsigned int *) (skb + 1);
printk(KERN_DEBUG "Packet data is %08x %08x %08x %08x.\n", packet[0],
{
#ifndef CONFIG_PCI
- printk("Kernel PCI support not enabled. Skipping scan for PCI HBAs.\n");
+ printk("eata_dma: kernel PCI support not enabled. Skipping scan for PCI HBAs.\n");
#else
u8 pci_bus, pci_device_fn;
"PCI_BASE_ADDRESS_0\n", error);
}
} else
- printk("No BIOS32 extensions present. This eata_dma release "
- "still depends on it.\nSkipping scan for PCI HBAs. Sorry.\n");
+ printk("eata_dma: No BIOS32 extensions present. This driver release "
+ "still depends on it.\n"
+ " Skipping scan for PCI HBAs. \n");
#endif /* #ifndef CONFIG_PCI */
return;
}
* c-continued-statement-offset: 4
* c-continued-brace-offset: 0
* indent-tabs-mode: nil
- * tab-width: 4
+ * tab-width: 8
* End:
*/
struct lun_map {
__u8 id:5,
- chan:3;
+ chan:3;
__u8 lun;
};
typedef struct emul_pp {
__u8 p_code:6,
- null:1,
- p_save:1;
+ null:1,
+ p_save:1;
__u8 p_length;
__u16 cylinder;
__u8 heads;
__u8 sectors;
__u8 null2;
__u8 s_lunmap:4,
- ems:1;
- __u16 drive_type; /* In Little Endian ! */
+ ems:1;
+ __u16 drive_type; /* In Little Endian ! */
struct lun_map lunmap[4];
}emulpp;
typedef struct log_sheader {
__u8 page_code,
- reserved;
+ reserved;
__u16 length;
}logsh;
/* Log Sense Statistics */
typedef struct read_command_statistics {
- __u16 code; /* 0x01 */
+ __u16 code; /* 0x01 */
__u8 flags;
__u8 length; /* 0x24 */
__u32 h_commands,
- uncached,
- la_cmds,
- la_blks,
- la_hits,
- missed,
- hits,
- seq_la_blks,
- seq_la_hits;
+ uncached,
+ la_cmds,
+ la_blks,
+ la_hits,
+ missed,
+ hits,
+ seq_la_blks,
+ seq_la_hits;
}r_cmd_stat;
typedef struct write_command_statistics {
- __u16 code; /* 0x03 */
+ __u16 code; /* 0x03 */
__u8 flags;
__u8 length; /* 0x28 */
__u32 h_commands,
- uncached,
- thru,
- bypass,
- soft_err,
- hits,
- b_idle,
- b_activ,
- b_blks,
- b_blks_clean;
+ uncached,
+ thru,
+ bypass,
+ soft_err,
+ hits,
+ b_idle,
+ b_activ,
+ b_blks,
+ b_blks_clean;
}w_cmd_stat;
typedef struct host_command_statistics {
- __u16 code; /* 0x02, 0x04 */
+ __u16 code; /* 0x02, 0x04 */
__u8 flags;
- __u8 length; /* 0x30 */
+ __u8 length; /* 0x30 */
__u32 sizes[12];
}hst_cmd_stat;
typedef struct physical_command_statistics {
- __u16 code; /* 0x06, 0x07 */
+ __u16 code; /* 0x06, 0x07 */
__u8 flags;
- __u8 length; /* 0x34 */
+ __u8 length; /* 0x34 */
__u32 sizes[13];
}phy_cmd_stat;
typedef struct misc_device_statistics {
- __u16 code; /* 0x05 */
+ __u16 code; /* 0x05 */
__u8 flags;
- __u8 length; /* 0x10 */
+ __u8 length; /* 0x10 */
__u32 disconnect,
- pass_thru,
- sg_commands,
- stripe_boundary_crosses;
+ pass_thru,
+ sg_commands,
+ stripe_boundary_crosses;
}msc_stats;
/* Configuration Pages */
typedef struct controller_configuration {
- __u16 code; /* 0x01 */
+ __u16 code; /* 0x01 */
__u8 flags;
- __u8 length; /* 0x02 */
+ __u8 length; /* 0x02 */
__u8 intt:1,
- sec:1,
- csh:1,
- key:1,
- tmr:1,
- srs:1,
- nvr:1;
+ sec:1,
+ csh:1,
+ key:1,
+ tmr:1,
+ srs:1,
+ nvr:1;
__u8 interrupt;
}coco;
typedef struct controller_hardware_errors {
- __u16 code; /* 0x02 */
+ __u16 code; /* 0x02 */
__u8 flags;
- __u8 length; /* 0x02 */
+ __u8 length; /* 0x02 */
__u8 unused:1,
- per:1;
+ per:1;
__u8 interrupt;
}coher;
typedef struct memory_map {
- __u16 code; /* 0x03, 0x04 */
+ __u16 code; /* 0x03, 0x04 */
__u8 flags;
- __u8 length; /* 0x04 */
+ __u8 length; /* 0x04 */
__u32 memory_map;
}mema;
typedef struct scsi_transfer {
- __u16 code; /* 0x05 */
+ __u16 code; /* 0x05 */
__u8 flags;
- __u8 length; /* 0x04 */
+ __u8 length; /* 0x04 */
__u8 offset,
- period;
+ period;
__u16 speed;
}scsitrans;
typedef struct scsi_modes {
- __u16 code; /* 0x06 */
+ __u16 code; /* 0x06 */
__u8 flags;
- __u8 length; /* 0x02 */
+ __u8 length; /* 0x02 */
__u8 que:1,
- cdis:1,
- wtru:1,
- dasd:1,
- ncr:1,
- awre:1;
+ cdis:1,
+ wtru:1,
+ dasd:1,
+ ncr:1,
+ awre:1;
__u8 reserved;
}scsimod;
typedef struct host_bus {
- __u16 code; /* 0x07 */
+ __u16 code; /* 0x07 */
__u8 flags;
- __u8 length; /* 0x02 */
+ __u8 length; /* 0x02 */
__u8 speed:6,
- pci:1,
- eisa:1;
+ pci:1,
+ eisa:1;
__u8 reserved;
}hobu;
typedef struct scsi_bus {
- __u16 code; /* 0x08 */
+ __u16 code; /* 0x08 */
__u8 flags;
- __u8 length; /* 0x02 */
+ __u8 length; /* 0x02 */
__u8 speed:4,
- res:1,
- ext:1,
- wide:1,
- dif:1;
+ res:1,
+ ext:1,
+ wide:1,
+ dif:1;
__u8 busnum;
}scbu;
typedef struct board_type {
- __u16 code; /* 0x09 */
+ __u16 code; /* 0x09 */
__u8 flags;
- __u8 length; /* 0x04 */
+ __u8 length; /* 0x04 */
__u8 unused:1,
- cmi:1,
- dmi:1,
- cm4k:1,
- cm4:1,
- dm4k:1,
- dm4:1,
- hba:1;
+ cmi:1,
+ dmi:1,
+ cm4k:1,
+ cm4:1,
+ dm4k:1,
+ dm4:1,
+ hba:1;
__u8 cpu_type,
- cpu_speed;
+ cpu_speed;
__u8 sx1:1,
- sx2:1,
- unused2:4,
- alrm:1,
- srom:1;
+ sx2:1,
+ unused2:4,
+ alrm:1,
+ srom:1;
}boty;
typedef struct memory_config {
- __u16 code; /* 0x0a */
+ __u16 code; /* 0x0a */
__u8 flags;
- __u8 length; /* 0x04 */
+ __u8 length; /* 0x04 */
__u8 banksize[4];
}memco;
typedef struct firmware_info {
- __u16 code; /* 0x0b */
+ __u16 code; /* 0x0b */
__u8 flags;
- __u8 length; /* 0x04 */
+ __u8 length; /* 0x04 */
__u8 dnld:1,
- bs528:1,
- fmt:1,
- fw528:1;
+ bs528:1,
+ fmt:1,
+ fw528:1;
__u8 unused1,
- fw_type,
- unused;
+ fw_type,
+ unused;
}firm;
typedef struct subsystem_info {
- __u16 code; /* 0x0c */
+ __u16 code; /* 0x0c */
__u8 flags;
- __u8 length; /* 0x02 */
+ __u8 length; /* 0x02 */
__u8 shlf:1,
- swap:1,
- noss:1;
+ swap:1,
+ noss:1;
__u8 reserved;
}subinf;
typedef struct per_channel_info {
- __u16 code; /* 0x0d */
+ __u16 code; /* 0x0d */
__u8 flags;
- __u8 length; /* 0x02 */
+ __u8 length; /* 0x02 */
__u8 channel;
__u8 shlf:1,
- swap:1,
- noss:1,
- srs:1,
- que:1,
- ext:1,
- wide:1,
- diff:1;
+ swap:1,
+ noss:1,
+ srs:1,
+ que:1,
+ ext:1,
+ wide:1,
+ diff:1;
}pcinf;
typedef struct array_limits {
- __u16 code; /* 0x0e */
+ __u16 code; /* 0x0e */
__u8 flags;
- __u8 length; /* 0x04 */
+ __u8 length; /* 0x04 */
__u8 max_groups,
- raid0_drv,
- raid35_drv,
- unused;
+ raid0_drv,
+ raid35_drv,
+ unused;
}arrlim;
/*
* c-continued-statement-offset: 4
* c-continued-brace-offset: 0
* indent-tabs-mode: nil
- * tab-width: 4
+ * tab-width: 8
* End:
*/
/********************************************************
-* Header file for eata_dma.c and eata_pio.c *
-* Linux EATA SCSI drivers *
-* (c) 1993,94,95 Michael Neuffer *
+* Header file for eata_dma.c and eata_pio.c *
+* Linux EATA SCSI drivers *
+* (c) 1993,94,95 Michael Neuffer *
*********************************************************
-* last change: 95/06/20 *
+* last change: 95/06/20 *
********************************************************/
/*********************************************
- * Misc. definitions *
+ * Misc. definitions *
*********************************************/
#ifndef TRUE
#define R_LIMIT 0x20000
-#define MAXISA 4
-#define MAXEISA 16
-#define MAXPCI 16
-#define MAXIRQ 16
+#define MAXISA 4
+#define MAXEISA 16
+#define MAXPCI 16
+#define MAXIRQ 16
#define MAXTARGET 16
#define MAXCHANNEL 3
-#define IS_ISA 'I'
-#define IS_EISA 'E'
-#define IS_PCI 'P'
-
-#define BROKEN_INQUIRY 1
-
-#define EATA_SIGNATURE 0x45415441 /* BIG ENDIAN coded "EATA" sig. */
-#define EATA_CP_SIZE 44
-
-#define MAX_PCI_DEVICES 32 /* Maximum # Of Devices Per Bus */
-#define MAX_METHOD_2 16 /* Max Devices For Method 2 */
-#define MAX_PCI_BUS 16 /* Maximum # Of Busses Allowed */
-
-#define SG_SIZE 64
-#define SG_SIZE_BIG 509 /* max. 509 */
-
-#define C_P_L_DIV 2 /* 1 <= C_P_L_DIV <= 8
- * You can use this parameter to fine-tune
- * the driver. Depending on the number of
- * devices and their speed and ability to queue
- * commands, you will get the best results with a
- * value
- * ~= numdevices-(devices_unable_to_queue_commands/2)
- * The reason for this is that the disk driver
- * tends to flood the queue, so that other
- * drivers have problems to queue commands
- * themselves. This can for example result in
- * the effect that the tape stops during disk
- * accesses.
- */
-
-#define FREE 0
-#define OK 0
+#define IS_ISA 'I'
+#define IS_EISA 'E'
+#define IS_PCI 'P'
+
+#define BROKEN_INQUIRY 1
+
+#define EATA_SIGNATURE 0x45415441 /* BIG ENDIAN coded "EATA" sig. */
+#define EATA_CP_SIZE 44
+
+#define MAX_PCI_DEVICES 32 /* Maximum # Of Devices Per Bus */
+#define MAX_METHOD_2 16 /* Max Devices For Method 2 */
+#define MAX_PCI_BUS 16 /* Maximum # Of Busses Allowed */
+
+#define SG_SIZE 64
+#define SG_SIZE_BIG 509 /* max. 509 */
+
+#define C_P_L_DIV 2 /* 1 <= C_P_L_DIV <= 8
+ * You can use this parameter to fine-tune
+ * the driver. Depending on the number of
+ * devices and their speed and ability to queue
+ * commands, you will get the best results with a
+ * value
+ * ~= numdevices-(devices_unable_to_queue_commands/2)
+ * The reason for this is that the disk driver
+ * tends to flood the queue, so that other
+ * drivers have problems to queue commands
+ * themselves. This can for example result in
+ * the effect that the tape stops during disk
+ * accesses.
+ */
+
+#define FREE 0
+#define OK 0
#define NO_TIMEOUT 0
-#define USED 1
-#define TIMEOUT 2
-#define RESET 4
-#define LOCKED 8
+#define USED 1
+#define TIMEOUT 2
+#define RESET 4
+#define LOCKED 8
-#define HD(cmd) ((hostdata *)&(cmd->host->hostdata))
-#define CD(cmd) ((struct eata_ccb *)(cmd->host_scribble))
+#define HD(cmd) ((hostdata *)&(cmd->host->hostdata))
+#define CD(cmd) ((struct eata_ccb *)(cmd->host_scribble))
#define SD(host) ((hostdata *)&(host->hostdata))
#define DELAY(x) { __u32 i; i = jiffies + x; while (jiffies < i); }
-#define DEL2(x) { __u32 i; for (i = 0; i < 0xffff * x; i++); }
+#define DEL2(x) { __u32 i; for (i = 0; i < 0xffff * x; i++); }
/***********************************************
* EATA Command & Register definitions *
***********************************************/
-#define PCI_REG_DPTconfig 0x40
-#define PCI_REG_PumpModeAddress 0x44
-#define PCI_REG_PumpModeData 0x48
-#define PCI_REG_ConfigParam1 0x50
-#define PCI_REG_ConfigParam2 0x54
+#define PCI_REG_DPTconfig 0x40
+#define PCI_REG_PumpModeAddress 0x44
+#define PCI_REG_PumpModeData 0x48
+#define PCI_REG_ConfigParam1 0x50
+#define PCI_REG_ConfigParam2 0x54
-#define EATA_CMD_PIO_SETUPTEST 0xc6
+#define EATA_CMD_PIO_SETUPTEST 0xc6
#define EATA_CMD_PIO_READ_CONFIG 0xf0
-#define EATA_CMD_PIO_SET_CONFIG 0xf1
-#define EATA_CMD_PIO_SEND_CP 0xf2
-#define EATA_CMD_PIO_RECEIVE_SP 0xf3
-#define EATA_CMD_PIO_TRUNC 0xf4
+#define EATA_CMD_PIO_SET_CONFIG 0xf1
+#define EATA_CMD_PIO_SEND_CP 0xf2
+#define EATA_CMD_PIO_RECEIVE_SP 0xf3
+#define EATA_CMD_PIO_TRUNC 0xf4
-#define EATA_CMD_RESET 0xf9
-#define EATA_CMD_IMMEDIATE 0xfa
+#define EATA_CMD_RESET 0xf9
+#define EATA_CMD_IMMEDIATE 0xfa
#define EATA_CMD_DMA_READ_CONFIG 0xfd
-#define EATA_CMD_DMA_SET_CONFIG 0xfe
-#define EATA_CMD_DMA_SEND_CP 0xff
+#define EATA_CMD_DMA_SET_CONFIG 0xfe
+#define EATA_CMD_DMA_SEND_CP 0xff
-#define ECS_EMULATE_SENSE 0xd4
+#define ECS_EMULATE_SENSE 0xd4
#define GENERIC_ABORT 0x00
#define BUS_RESET 0x02
#define SPECIFIC_ABORT 0x03
#define QUIET_INTR 0x04
-#define COLD_BOOT_HBA 0x06 /* Only as a last resort */
+#define COLD_BOOT_HBA 0x06 /* Only as a last resort */
#define FORCE_IO 0x07
-#define HA_WCOMMAND 0x07 /* command register offset */
-#define HA_WCOMMAND2 0x06 /* immediate command offset */
+#define HA_WCOMMAND 0x07 /* command register offset */
+#define HA_WCOMMAND2 0x06 /* immediate command offset */
#define HA_WSUBCODE 0x05
#define HA_WSUBLUN 0x04
-#define HA_WDMAADDR 0x02 /* DMA address LSB offset */
-#define HA_RAUXSTAT 0x08 /* aux status register offset*/
-#define HA_RSTATUS 0x07 /* status register offset */
-#define HA_RDATA 0x00 /* data register (16bit) */
-
-#define HA_ABUSY 0x01 /* aux busy bit */
-#define HA_AIRQ 0x02 /* aux IRQ pending bit */
-#define HA_SERROR 0x01 /* pr. command ended in error*/
-#define HA_SMORE 0x02 /* more data soon to come */
-#define HA_SCORR 0x04 /* data corrected */
-#define HA_SDRQ 0x08 /* data request active */
-#define HA_SSC 0x10 /* seek complete */
-#define HA_SFAULT 0x20 /* write fault */
-#define HA_SREADY 0x40 /* drive ready */
-#define HA_SBUSY 0x80 /* drive busy */
+#define HA_WDMAADDR 0x02 /* DMA address LSB offset */
+#define HA_RAUXSTAT 0x08 /* aux status register offset*/
+#define HA_RSTATUS 0x07 /* status register offset */
+#define HA_RDATA 0x00 /* data register (16bit) */
+
+#define HA_ABUSY 0x01 /* aux busy bit */
+#define HA_AIRQ 0x02 /* aux IRQ pending bit */
+#define HA_SERROR 0x01 /* pr. command ended in error*/
+#define HA_SMORE 0x02 /* more data soon to come */
+#define HA_SCORR 0x04 /* data corrected */
+#define HA_SDRQ 0x08 /* data request active */
+#define HA_SSC 0x10 /* seek complete */
+#define HA_SFAULT 0x20 /* write fault */
+#define HA_SREADY 0x40 /* drive ready */
+#define HA_SBUSY 0x80 /* drive busy */
#define HA_SDRDY HA_SSC+HA_SREADY+HA_SDRQ
/**********************************************
- * Message definitions *
+ * Message definitions *
**********************************************/
-#define HA_NO_ERROR 0x00 /* No Error */
-#define HA_ERR_SEL_TO 0x01 /* Selection Timeout */
-#define HA_ERR_CMD_TO 0x02 /* Command Timeout */
-#define HA_ERR_RESET 0x03 /* SCSI Bus Reset Received */
-#define HA_INIT_POWERUP 0x04 /* Initial Controller Power-up */
-#define HA_UNX_BUSPHASE 0x05 /* Unexpected Bus Phase */
-#define HA_UNX_BUS_FREE 0x06 /* Unexpected Bus Free */
-#define HA_BUS_PARITY 0x07 /* Bus Parity Error */
-#define HA_SCSI_HUNG 0x08 /* SCSI Hung */
-#define HA_UNX_MSGRJCT 0x09 /* Unexpected Message Rejected */
-#define HA_RESET_STUCK 0x0a /* SCSI Bus Reset Stuck */
-#define HA_RSENSE_FAIL 0x0b /* Auto Request-Sense Failed */
-#define HA_PARITY_ERR 0x0c /* Controller Ram Parity Error */
-#define HA_CP_ABORT_NA 0x0d /* Abort Message sent to non-active cmd */
-#define HA_CP_ABORTED 0x0e /* Abort Message sent to active cmd */
-#define HA_CP_RESET_NA 0x0f /* Reset Message sent to non-active cmd */
-#define HA_CP_RESET 0x10 /* Reset Message sent to active cmd */
-#define HA_ECC_ERR 0x11 /* Controller Ram ECC Error */
-#define HA_PCI_PARITY 0x12 /* PCI Parity Error */
-#define HA_PCI_MABORT 0x13 /* PCI Master Abort */
-#define HA_PCI_TABORT 0x14 /* PCI Target Abort */
-#define HA_PCI_STABORT 0x15 /* PCI Signaled Target Abort */
+#define HA_NO_ERROR 0x00 /* No Error */
+#define HA_ERR_SEL_TO 0x01 /* Selection Timeout */
+#define HA_ERR_CMD_TO 0x02 /* Command Timeout */
+#define HA_ERR_RESET 0x03 /* SCSI Bus Reset Received */
+#define HA_INIT_POWERUP 0x04 /* Initial Controller Power-up */
+#define HA_UNX_BUSPHASE 0x05 /* Unexpected Bus Phase */
+#define HA_UNX_BUS_FREE 0x06 /* Unexpected Bus Free */
+#define HA_BUS_PARITY 0x07 /* Bus Parity Error */
+#define HA_SCSI_HUNG 0x08 /* SCSI Hung */
+#define HA_UNX_MSGRJCT 0x09 /* Unexpected Message Rejected */
+#define HA_RESET_STUCK 0x0a /* SCSI Bus Reset Stuck */
+#define HA_RSENSE_FAIL 0x0b /* Auto Request-Sense Failed */
+#define HA_PARITY_ERR 0x0c /* Controller Ram Parity Error */
+#define HA_CP_ABORT_NA 0x0d /* Abort Message sent to non-active cmd */
+#define HA_CP_ABORTED 0x0e /* Abort Message sent to active cmd */
+#define HA_CP_RESET_NA 0x0f /* Reset Message sent to non-active cmd */
+#define HA_CP_RESET 0x10 /* Reset Message sent to active cmd */
+#define HA_ECC_ERR 0x11 /* Controller Ram ECC Error */
+#define HA_PCI_PARITY 0x12 /* PCI Parity Error */
+#define HA_PCI_MABORT 0x13 /* PCI Master Abort */
+#define HA_PCI_TABORT 0x14 /* PCI Target Abort */
+#define HA_PCI_STABORT 0x15 /* PCI Signaled Target Abort */
/**********************************************
- * Other definitions *
+ * Other definitions *
**********************************************/
struct reg_bit { /* reading this one will clear the interrupt */
- __u8 error:1; /* previous command ended in an error */
+ __u8 error:1; /* previous command ended in an error */
__u8 more:1; /* more DATA coming soon, poll BSY & DRQ (PIO) */
__u8 corr:1; /* data read was successfully corrected with ECC*/
- __u8 drq:1; /* data request active */
- __u8 sc:1; /* seek complete */
- __u8 fault:1; /* write fault */
- __u8 ready:1; /* drive ready */
+ __u8 drq:1; /* data request active */
+ __u8 sc:1; /* seek complete */
+ __u8 fault:1; /* write fault */
+ __u8 ready:1; /* drive ready */
__u8 busy:1; /* controller busy */
};
struct reg_abit { /* reading this won't clear the interrupt */
- __u8 abusy:1; /* auxiliary busy */
- __u8 irq:1; /* set when drive interrupt is asserted */
+ __u8 abusy:1; /* auxiliary busy */
+ __u8 irq:1; /* set when drive interrupt is asserted */
__u8 dummy:6;
};
-struct eata_register { /* EATA register set */
- __u8 data_reg[2]; /* R, couldn't figure this one out */
- __u8 cp_addr[4]; /* W, CP address register */
+struct eata_register { /* EATA register set */
+ __u8 data_reg[2]; /* R, couldn't figure this one out */
+ __u8 cp_addr[4]; /* W, CP address register */
union {
- __u8 command; /* W, command code: [read|set] conf, send CP*/
- struct reg_bit status; /* R, see register_bit1 */
- __u8 statusbyte;
+ __u8 command; /* W, command code: [read|set] conf, send CP*/
+ struct reg_bit status; /* R, see register_bit1 */
+ __u8 statusbyte;
} ovr;
- struct reg_abit aux_stat; /* R, see register_bit2 */
+ struct reg_abit aux_stat; /* R, see register_bit2 */
};
-struct get_conf { /* Read Configuration Array */
- __u32 len; /* Should return 0x22, 0x24, etc */
- __u32 signature; /* Signature MUST be "EATA" */
+struct get_conf { /* Read Configuration Array */
+ __u32 len; /* Should return 0x22, 0x24, etc */
+ __u32 signature; /* Signature MUST be "EATA" */
__u8 version2:4,
- version:4; /* EATA Version level */
- __u8 OCS_enabled:1, /* Overlap Command Support enabled */
- TAR_support:1, /* SCSI Target Mode supported */
- TRNXFR:1, /* Truncate Transfer Cmd not necessary */
- /* Only used in PIO Mode */
- MORE_support:1, /* MORE supported (only PIO Mode) */
- DMA_support:1, /* DMA supported Driver uses only */
- /* this mode */
- DMA_valid:1, /* DRQ value in Byte 30 is valid */
- ATA:1, /* ATA device connected (not supported) */
- HAA_valid:1; /* Hostadapter Address is valid */
-
- __u16 cppadlen; /* Number of pad bytes send after CD data */
- /* set to zero for DMA commands */
- __u8 scsi_id[4]; /* SCSI ID of controller 2-0 Byte 0 res. */
- /* if not, zero is returned */
- __u32 cplen; /* CP length: number of valid cp bytes */
- __u32 splen; /* Number of bytes returned after */
- /* Receive SP command */
- __u16 queuesiz; /* max number of queueable CPs */
+ version:4; /* EATA Version level */
+ __u8 OCS_enabled:1, /* Overlap Command Support enabled */
+ TAR_support:1, /* SCSI Target Mode supported */
+ TRNXFR:1, /* Truncate Transfer Cmd not necessary */
+ /* Only used in PIO Mode */
+ MORE_support:1, /* MORE supported (only PIO Mode) */
+ DMA_support:1, /* DMA supported Driver uses only */
+ /* this mode */
+ DMA_valid:1, /* DRQ value in Byte 30 is valid */
+ ATA:1, /* ATA device connected (not supported) */
+ HAA_valid:1; /* Hostadapter Address is valid */
+
+ __u16 cppadlen; /* Number of pad bytes send after CD data */
+ /* set to zero for DMA commands */
+ __u8 scsi_id[4]; /* SCSI ID of controller 2-0 Byte 0 res. */
+ /* if not, zero is returned */
+ __u32 cplen; /* CP length: number of valid cp bytes */
+ __u32 splen; /* Number of bytes returned after */
+ /* Receive SP command */
+ __u16 queuesiz; /* max number of queueable CPs */
__u16 dummy;
- __u16 SGsiz; /* max number of SG table entries */
- __u8 IRQ:4, /* IRQ used this HA */
- IRQ_TR:1, /* IRQ Trigger: 0=edge, 1=level */
- SECOND:1, /* This is a secondary controller */
- DMA_channel:2; /* DRQ index, DRQ is 2comp of DRQX */
- __u8 sync; /* device at ID 7 tru 0 is running in */
- /* synchronous mode, this will disappear */
- __u8 DSBLE:1, /* ISA i/o addressing is disabled */
- FORCADR:1, /* i/o address has been forced */
- SG_64K:1,
- SG_UAE:1,
- :4;
- __u8 MAX_ID:5, /* Max number of SCSI target IDs */
- MAX_CHAN:3; /* Number of SCSI busses on HBA */
- __u8 MAX_LUN; /* Max number of LUNs */
- __u8 :3,
- AUTOTRM:1,
- M1_inst:1,
- ID_qest:1, /* Raidnum ID is questionable */
- is_PCI:1, /* HBA is PCI */
- is_EISA:1; /* HBA is EISA */
+ __u16 SGsiz; /* max number of SG table entries */
+ __u8 IRQ:4, /* IRQ used this HA */
+ IRQ_TR:1, /* IRQ Trigger: 0=edge, 1=level */
+ SECOND:1, /* This is a secondary controller */
+ DMA_channel:2; /* DRQ index, DRQ is 2comp of DRQX */
+ __u8 sync; /* device at ID 7 tru 0 is running in */
+ /* synchronous mode, this will disappear */
+ __u8 DSBLE:1, /* ISA i/o addressing is disabled */
+ FORCADR:1, /* i/o address has been forced */
+ SG_64K:1,
+ SG_UAE:1,
+ :4;
+ __u8 MAX_ID:5, /* Max number of SCSI target IDs */
+ MAX_CHAN:3; /* Number of SCSI busses on HBA */
+ __u8 MAX_LUN; /* Max number of LUNs */
+ __u8 :3,
+ AUTOTRM:1,
+ M1_inst:1,
+ ID_qest:1, /* Raidnum ID is questionable */
+ is_PCI:1, /* HBA is PCI */
+ is_EISA:1; /* HBA is EISA */
__u8 unused[478];
};
__u32 len;
};
-struct eata_ccb { /* Send Command Packet structure */
+struct eata_ccb { /* Send Command Packet structure */
- __u8 SCSI_Reset:1, /* Cause a SCSI Bus reset on the cmd */
- HBA_Init:1, /* Cause Controller to reinitialize */
- Auto_Req_Sen:1, /* Do Auto Request Sense on errors */
- scatter:1, /* Data Ptr points to a SG Packet */
- Resrvd:1, /* RFU */
- Interpret:1, /* Interpret the SCSI cdb of own use */
- DataOut:1, /* Data Out phase with command */
- DataIn:1; /* Data In phase with command */
- __u8 reqlen; /* Request Sense Length */
- /* Valid if Auto_Req_Sen=1 */
+ __u8 SCSI_Reset:1, /* Cause a SCSI Bus reset on the cmd */
+ HBA_Init:1, /* Cause Controller to reinitialize */
+ Auto_Req_Sen:1, /* Do Auto Request Sense on errors */
+ scatter:1, /* Data Ptr points to a SG Packet */
+ Resrvd:1, /* RFU */
+ Interpret:1, /* Interpret the SCSI cdb of own use */
+ DataOut:1, /* Data Out phase with command */
+ DataIn:1; /* Data In phase with command */
+ __u8 reqlen; /* Request Sense Length */
+ /* Valid if Auto_Req_Sen=1 */
__u8 unused[3];
- __u8 FWNEST:1, /* send cmd to phys RAID component*/
- unused2:7;
- __u8 Phsunit:1, /* physical unit on mirrored pair */
- I_AT:1, /* inhibit address translation */
- I_HBA_C:1, /* HBA inhibit caching */
- unused3:5;
-
- __u8 cp_id:5, /* SCSI Device ID of target */
- cp_channel:3; /* SCSI Channel # of HBA */
+ __u8 FWNEST:1, /* send cmd to phys RAID component*/
+ unused2:7;
+ __u8 Phsunit:1, /* physical unit on mirrored pair */
+ I_AT:1, /* inhibit address translation */
+ I_HBA_C:1, /* HBA inhibit caching */
+ unused3:5;
+
+ __u8 cp_id:5, /* SCSI Device ID of target */
+ cp_channel:3; /* SCSI Channel # of HBA */
__u8 cp_lun:3,
- :2,
- cp_luntar:1, /* CP is for target ROUTINE */
- cp_dispri:1, /* Grant disconnect privilege */
- cp_identify:1; /* Always TRUE */
- __u8 cp_msg1; /* Message bytes 0-3 */
+ :2,
+ cp_luntar:1, /* CP is for target ROUTINE */
+ cp_dispri:1, /* Grant disconnect privilege */
+ cp_identify:1; /* Always TRUE */
+ __u8 cp_msg1; /* Message bytes 0-3 */
__u8 cp_msg2;
__u8 cp_msg3;
- __u8 cp_cdb[12]; /* Command Descriptor Block */
- __u32 cp_datalen; /* Data Transfer Length */
- /* If scatter=1 len of sg package */
- void *cp_viraddr; /* address of this ccb */
- __u32 cp_dataDMA; /* Data Address, if scatter=1 *
- * address of scatter packet */
- __u32 cp_statDMA; /* address for Status Packet */
- __u32 cp_reqDMA; /* Request Sense Address, used if */
- /* CP command ends with error */
- /* Additional CP info begins here */
+ __u8 cp_cdb[12]; /* Command Descriptor Block */
+ __u32 cp_datalen; /* Data Transfer Length */
+ /* If scatter=1 len of sg package */
+ void *cp_viraddr; /* address of this ccb */
+ __u32 cp_dataDMA; /* Data Address, if scatter=1 *
+ * address of scatter packet */
+ __u32 cp_statDMA; /* address for Status Packet */
+ __u32 cp_reqDMA; /* Request Sense Address, used if */
+ /* CP command ends with error */
+ /* Additional CP info begins here */
__u32 timeout;
__u8 retries;
- __u8 status; /* status of this queueslot */
+ __u8 status; /* status of this queueslot */
- Scsi_Cmnd *cmd; /* address of cmd */
+ Scsi_Cmnd *cmd; /* address of cmd */
struct eata_sg_list *sg_list;
};
struct eata_sp {
- __u8 hba_stat:7, /* HBA status */
- EOC:1; /* True if command finished */
- __u8 scsi_stat; /* Target SCSI status */
+ __u8 hba_stat:7, /* HBA status */
+ EOC:1; /* True if command finished */
+ __u8 scsi_stat; /* Target SCSI status */
__u8 reserved[2];
- __u32 residue_len; /* Number of bytes not transferred */
- struct eata_ccb *ccb; /* Address set in COMMAND PACKET */
+ __u32 residue_len; /* Number of bytes not transferred */
+ struct eata_ccb *ccb; /* Address set in COMMAND PACKET */
__u8 msg[12];
};
__u8 name[18];
__u8 revision[6];
__u8 EATA_revision;
- __u8 bustype; /* bustype of HBA */
- __u8 channel; /* # of avail. scsi channels */
- __u8 state; /* state of HBA */
- __u8 primary; /* true if primary */
- __u8 broken_INQUIRY:1; /* This is an EISA HBA with *
- * broken INQUIRY */
+ __u8 bustype; /* bustype of HBA */
+ __u8 channel; /* # of avail. scsi channels */
+ __u8 state; /* state of HBA */
+ __u8 primary; /* true if primary */
+ __u8 broken_INQUIRY:1; /* This is an EISA HBA with *
+ * broken INQUIRY */
__u32 reads[13];
__u32 writes[13];
- /* state of Target (RESET,..) */
+ /* state of Target (RESET,..) */
__u8 t_state[MAXCHANNEL][MAXTARGET];
- /* timeouts on target */
+ /* timeouts on target */
__u32 t_timeout[MAXCHANNEL][MAXTARGET];
- __u32 last_ccb; /* Last used ccb */
- __u32 cplen; /* size of CP in words */
- __u16 cppadlen; /* pad length of cp in words */
- __u8 hostid; /* SCSI ID of HBA */
- __u8 devflags; /* bits set for detected devices */
- __u8 moresupport; /* HBA supports MORE flag */
- struct Scsi_Host *next;
+ __u32 last_ccb; /* Last used ccb */
+ __u32 cplen; /* size of CP in words */
+ __u16 cppadlen; /* pad length of cp in words */
+ __u8 hostid; /* SCSI ID of HBA */
+ __u8 devflags; /* bits set for detected devices */
+ __u8 moresupport; /* HBA supports MORE flag */
+ struct Scsi_Host *next;
struct Scsi_Host *prev;
- struct eata_sp sp; /* status packet */
- struct eata_ccb ccb[0]; /* ccb array begins here */
+ struct eata_sp sp; /* status packet */
+ struct eata_ccb ccb[0]; /* ccb array begins here */
}hostdata;
/* structure for max. 2 emulated drives */
struct drive_geom_emul {
- __u8 trans; /* translation flag 1=transl */
- __u8 channel; /* SCSI channel number */
- __u8 HBA; /* HBA number (prim/sec) */
- __u8 id; /* drive id */
- __u8 lun; /* drive lun */
- __u32 heads; /* number of heads */
- __u32 sectors; /* number of sectors */
- __u32 cylinder; /* number of cylinders */
+ __u8 trans; /* translation flag 1=transl */
+ __u8 channel; /* SCSI channel number */
+ __u8 HBA; /* HBA number (prim/sec) */
+ __u8 id; /* drive id */
+ __u8 lun; /* drive lun */
+ __u32 heads; /* number of heads */
+ __u32 sectors; /* number of sectors */
+ __u32 cylinder; /* number of cylinders */
};
struct geom_emul {
- __u8 bios_drives; /* number of emulated drives */
- struct drive_geom_emul drv[2]; /* drive structures */
+ __u8 bios_drives; /* number of emulated drives */
+ struct drive_geom_emul drv[2]; /* drive structures */
};
#endif /* _EATA_GENERIC_H */
* c-continued-statement-offset: 4
* c-continued-brace-offset: 0
* indent-tabs-mode: nil
- * tab-width: 4
+ * tab-width: 8
* End:
*/
{
#ifndef CONFIG_PCI
- printk("Kernel PCI support not enabled. Skipping scan for PCI HBAs.\n");
+ printk("eata_pio: kernel PCI support not enabled. Skipping scan for PCI HBAs.\n");
#else
u8 pci_bus, pci_device_fn;
"PCI_BASE_ADDRESS_0\n", error);
}
} else
- printk("No BIOS32 extensions present. This eata_pio release "
+ printk("eata_pio: No BIOS32 extensions present. This driver release "
"still depends on it.\n"
- "Skipping scan for PCI HBAs. Sorry.\n");
+ " Skipping scan for PCI HBAs.\n");
#endif /* #ifndef CONFIG_PCI */
return;
}
DBG((DBG_PROBE && DBG_DELAY) || DPT_DEBUG,
printk("Using lots of delays to let you read the debugging output\n"));
-#ifndef DBG_EISA
-
-printk("DBG_EISA not defined !!!\n");
-
-#endif
find_pio_PCI(&gc, tpnt);
/********************************************************
* Header file for eata_pio.c Linux EATA-PIO SCSI driver *
-* (c) 1993,94,95 Michael Neuffer *
+* (c) 1993,94,95 Michael Neuffer *
*********************************************************
-* last change: 95/06/21 *
+* last change: 95/06/21 *
********************************************************/
#define VER_MAJOR 0
#define VER_MINOR 0
-#define VER_SUB "1a"
+#define VER_SUB "1a"
/************************************************************************
- * Here you can switch parts of the code on and of *
+ * Here you can switch parts of the code on and of *
************************************************************************/
-#define VERBOSE_SETUP /* show startup screen of 2001 */
-#define ALLOW_DMA_BOARDS 1
+#define VERBOSE_SETUP /* show startup screen of 2001 */
+#define ALLOW_DMA_BOARDS 0
/************************************************************************
- * Debug options. *
- * Enable DEBUG and whichever options you require. *
+ * Debug options. *
+ * Enable DEBUG and whichever options you require. *
************************************************************************/
-#define DEBUG_EATA 1 /* Enable debug code. */
-#define DPT_DEBUG 0 /* Bobs special */
-#define DBG_DELAY 0 /* Build in delays so debug messages can be
- * be read before they vanish of the top of
- * the screen!
- */
-#define DBG_PROBE 0 /* Debug probe routines. */
-#define DBG_ISA 0 /* Trace ISA routines */
-#define DBG_EISA 0 /* Trace EISA routines */
-#define DBG_PCI 0 /* Trace PCI routines */
-#define DBG_PIO 0 /* Trace get_config_PIO */
-#define DBG_COM 0 /* Trace command call */
-#define DBG_QUEUE 0 /* Trace command queueing. */
-#define DBG_INTR 0 /* Trace interrupt service routine. */
-#define DBG_INTR2 0 /* Trace interrupt service routine. */
-#define DBG_PROC 0 /* Debug proc-fs related statistics */
-#define DBG_PROC_WRITE 0
-#define DBG_REGISTER 0 /* */
-#define DBG_ABNORM 1 /* Debug abnormal actions (reset, abort) */
+#define DEBUG_EATA 1 /* Enable debug code. */
+#define DPT_DEBUG 0 /* Bobs special */
+#define DBG_DELAY 0 /* Build in delays so debug messages can be
+ * be read before they vanish of the top of
+ * the screen!
+ */
+#define DBG_PROBE 0 /* Debug probe routines. */
+#define DBG_ISA 0 /* Trace ISA routines */
+#define DBG_EISA 0 /* Trace EISA routines */
+#define DBG_PCI 0 /* Trace PCI routines */
+#define DBG_PIO 0 /* Trace get_config_PIO */
+#define DBG_COM 0 /* Trace command call */
+#define DBG_QUEUE 0 /* Trace command queueing. */
+#define DBG_INTR 0 /* Trace interrupt service routine. */
+#define DBG_INTR2 0 /* Trace interrupt service routine. */
+#define DBG_PROC 0 /* Debug proc-fs related statistics */
+#define DBG_PROC_WRITE 0
+#define DBG_REGISTER 0 /* */
+#define DBG_ABNORM 1 /* Debug abnormal actions (reset, abort) */
#if DEBUG_EATA
#define DBG(x, y) if ((x)) {y;}
extern int generic_proc_info(char *, char **, off_t, int, int, int);
-#define EATA_PIO { \
- NULL, NULL, \
- eata_pio_proc_info,/* procinfo */ \
- "eata_pio", /* proc dir entry */ \
- PROC_SCSI_EATA_PIO,/* proc dir inode */ \
- "EATA (Extended Attachment) PIO driver",\
- eata_pio_detect, \
- eata_pio_release, \
- NULL, NULL, \
- eata_pio_queue, \
- eata_pio_abort, \
- eata_pio_reset, \
- NULL, /* Slave attach */ \
- scsicam_bios_param, \
- 0, /* Canqueue */ \
- 0, /* this_id */ \
- 0, /* sg_tablesize */ \
- 0, /* cmd_per_lun */ \
- 0, /* present */ \
- 1, /* True if ISA */ \
- ENABLE_CLUSTERING }
+#define EATA_PIO { \
+ NULL, NULL, \
+ eata_pio_proc_info,/* procinfo */ \
+ "eata_pio", /* proc dir entry */ \
+ PROC_SCSI_EATA_PIO,/* proc dir inode */ \
+ "EATA (Extended Attachment) PIO driver",\
+ eata_pio_detect, \
+ eata_pio_release, \
+ NULL, NULL, \
+ eata_pio_queue, \
+ eata_pio_abort, \
+ eata_pio_reset, \
+ NULL, /* Slave attach */ \
+ scsicam_bios_param, \
+ 0, /* Canqueue */ \
+ 0, /* this_id */ \
+ 0, /* sg_tablesize */ \
+ 0, /* cmd_per_lun */ \
+ 0, /* present */ \
+ 1, /* True if ISA */ \
+ ENABLE_CLUSTERING }
#endif /* _EATA_PIO_H */
* c-continued-statement-offset: 4
* c-continued-brace-offset: 0
* indent-tabs-mode: nil
- * tab-width: 4
+ * tab-width: 8
* End:
*/
/*
* hosts.h Copyright (C) 1992 Drew Eckhardt
- * mid to low-level SCSI driver interface header by
- * Drew Eckhardt
+ * mid to low-level SCSI driver interface header by
+ * Drew Eckhardt
*
* <drew@colorado.edu>
*
- * Modified by Eric Youngdale eric@tantalus.nrl.navy.mil to
- * add scatter-gather, multiple outstanding request, and other
- * enhancements.
+ * Modified by Eric Youngdale eric@tantalus.nrl.navy.mil to
+ * add scatter-gather, multiple outstanding request, and other
+ * enhancements.
*
* Further modified by Eric Youngdale to support multiple host adapters
* of the same type.
#define ENABLE_CLUSTERING 1
/* The various choices mean:
- * NONE: Self evident. Host adapter is not capable of scatter-gather.
- * ALL: Means that the host adapter module can do scatter-gather,
- * and that there is no limit to the size of the table to which
- * we scatter/gather data.
+ * NONE: Self evident. Host adapter is not capable of scatter-gather.
+ * ALL: Means that the host adapter module can do scatter-gather,
+ * and that there is no limit to the size of the table to which
+ * we scatter/gather data.
* Anything else: Indicates the maximum number of chains that can be
- * used in one scatter-gather request.
+ * used in one scatter-gather request.
*/
/*
* The Scsi_Host_Template type has all that is needed to interface with a SCSI
- * host in a device independent matter. There is one entry for each different
+ * host in a device independent matter. There is one entry for each different
* type of host adapter that is supported on the system.
*/
typedef struct scsi_disk Disk;
-typedef struct SHT
+typedef struct SHT
{
/* Used with loadable modules so we can construct a linked list. */
/*
* The detect function shall return non zero on detection,
* indicating the number of host adapters of this particular
- * type were found. It should also
+ * type were found. It should also
* initialize all data necessary for this particular
* SCSI driver. It is passed the host number, so this host
* knows where the first entry is in the scsi_hosts[] array.
/*
* The QueueCommand function works in a similar manner
- * to the command function. It takes an additional parameter,
+ * to the command function. It takes an additional parameter,
* void (* done)(int host, int code) which is passed the host
- * # and exit result when the command is complete.
+ * # and exit result when the command is complete.
* Host number is the POSITION IN THE hosts array of THIS
* host adapter.
*/
/*
* Since the mid level driver handles time outs, etc, we want to
* be able to abort the current command. Abort returns 0 if the
- * abortion was successful. The field SCpnt->abort reason
+ * abortion was successful. The field SCpnt->abort reason
* can be filled in with the appropriate reason why we wanted
* the abort in the first place, and this will be used
* in the mid-level code instead of the host_byte().
* DID_ABORT should be returned.
*
* Note that the scsi driver should "clean up" after itself,
- * resetting the bus, etc. if necessary.
+ * resetting the bus, etc. if necessary.
*/
int (* abort)(Scsi_Cmnd *);
* The Scsi_Cmnd is passed so that the reset routine can figure
* out which host adapter should be reset, and also which command
* within the command block was responsible for the reset in
- * the first place. Some hosts do not implement a reset function,
+ * the first place. Some hosts do not implement a reset function,
* and these hosts must call scsi_request_sense(SCpnt) to keep
* the command alive.
*/
Scsi_Host_Template * hostt;
/*
- * These three parameters can be used to allow for wide scsi,
- * and for host adapters that support multiple busses
- * The first two should be set to 1 more than the actual max id
- * or lun (i.e. 8 for normal systems).
+ * These three parameters can be used to allow for wide scsi,
+ * and for host adapters that support multiple busses
+ * The first two should be set to 1 more than the actual max id
+ * or lun (i.e. 8 for normal systems).
*/
unsigned int max_id;
unsigned int max_lun;
/*
* We use these goofy things because the MM is not set up when we init
- * the scsi subsystem. By using these functions we can write code that
+ * the scsi subsystem. By using these functions we can write code that
* looks normal. Also, it makes it possible to use the same code for a
* loadable module.
*/
extern void scsi_init_free(char * ptr, unsigned int size);
void scan_scsis (struct Scsi_Host * shpnt, unchar hardcoded,
- unchar hchannel, unchar hid, unchar hlun);
+ unchar hchannel, unchar hid, unchar hlun);
extern int next_scsi_host;
struct Scsi_Device_Template * next;
char * name;
char * tag;
- int * usage_count; /* Used for loadable modules */
+ int * usage_count; /* Used for loadable modules */
unsigned char scsi_type;
unsigned char major;
- unsigned char nr_dev; /* Number currently attached */
- unsigned char dev_noticed; /* Number of devices detected. */
- unsigned char dev_max; /* Current size of arrays */
- unsigned blk:1; /* 0 if character device */
+ unsigned char nr_dev; /* Number currently attached */
+ unsigned char dev_noticed; /* Number of devices detected. */
+ unsigned char dev_max; /* Current size of arrays */
+ unsigned blk:1; /* 0 if character device */
int (*detect)(Scsi_Device *); /* Returns 1 if we can attach this device */
- void (*init)(void); /* Sizes arrays based upon number of devices
- * detected */
- void (*finish)(void); /* Perform initialization after attachment */
+ void (*init)(void); /* Sizes arrays based upon number of devices
+ * detected */
+ void (*finish)(void); /* Perform initialization after attachment */
int (*attach)(Scsi_Device *); /* Attach devices to arrays */
void (*detach)(Scsi_Device *);
};
/*
* This is an ugly hack. If we expect to be able to load devices at run time,
- * we need to leave extra room in some of the data structures. Doing a
+ * we need to leave extra room in some of the data structures. Doing a
* realloc to enlarge the structures would be riddled with race conditions,
* so until a better solution is discovered, we use this crude approach
*/
* c-continued-statement-offset: 4
* c-continued-brace-offset: 0
* indent-tabs-mode: nil
- * tab-width: 4
+ * tab-width: 8
* End:
*/
/* These elements define the operation we are about to perform */
unsigned char cmnd[12];
- unsigned request_bufflen; /* Actual request size */
+ unsigned request_bufflen; /* Actual request size */
- void * request_buffer; /* Actual requested buffer */
+ void * request_buffer; /* Actual requested buffer */
/* These elements define the operation we ultimately want to perform */
unsigned char data_cmnd[12];
- unsigned short old_use_sg; /* We save use_sg here when requesting
+ unsigned short old_use_sg; /* We save use_sg here when requesting
* sense info */
- unsigned short use_sg; /* Number of pieces of scatter-gather */
- unsigned short sglist_len; /* size of malloc'd scatter-gather list */
+ unsigned short use_sg; /* Number of pieces of scatter-gather */
+ unsigned short sglist_len; /* size of malloc'd scatter-gather list */
unsigned short abort_reason;/* If the mid-level code requests an
* abort, this is the reason. */
- unsigned bufflen; /* Size of data buffer */
- void *buffer; /* Data buffer */
+ unsigned bufflen; /* Size of data buffer */
+ void *buffer; /* Data buffer */
- unsigned underflow; /* Return error if less than this amount is
+ unsigned underflow; /* Return error if less than this amount is
* transfered */
- unsigned transfersize; /* How much we are guaranteed to transfer with
+ unsigned transfersize; /* How much we are guaranteed to transfer with
* each SCSI transfer (ie, between disconnect /
- * reconnects. Probably == sector size */
+ * reconnects. Probably == sector size */
- struct request request; /* A copy of the command we are working on */
+ struct request request; /* A copy of the command we are working on */
unsigned char sense_buffer[16]; /* Sense for this command, if needed */
int timeout_per_command, timeout_total, timeout;
/*
- * We handle the timeout differently if it happens when a reset,
- * abort, etc are in process.
+ * We handle the timeout differently if it happens when a reset,
+ * abort, etc are in process.
*/
unsigned volatile char internal_timeout;
/* End of special cdrom variables */
/* Low-level done function - can be used by low-level driver to point
- * to completion function. Not used by mid/upper level code. */
+ * to completion function. Not used by mid/upper level code. */
void (*scsi_done)(struct scsi_cmnd *);
void (*done)(struct scsi_cmnd *); /* Mid-level done function */
* Everything else should be left alone.
*/
- Scsi_Pointer SCp; /* Scratchpad used by some host adapters */
+ Scsi_Pointer SCp; /* Scratchpad used by some host adapters */
unsigned char * host_scribble; /* The host adapter is allowed to
* call scsi_malloc and get some memory
- * and hang it here. The host adapter
+ * and hang it here. The host adapter
* is also expected to call scsi_free
* to release this memory. (The memory
* obtained by scsi_malloc is guaranteed
* to be at an address < 16Mb). */
- int result; /* Status code from lower level driver */
+ int result; /* Status code from lower level driver */
- unsigned char tag; /* SCSI-II queued command tag */
- unsigned long pid; /* Process ID, starts at 0 */
-} Scsi_Cmnd;
+ unsigned char tag; /* SCSI-II queued command tag */
+ unsigned long pid; /* Process ID, starts at 0 */
+} Scsi_Cmnd;
/*
* scsi_abort aborts the current command that is executing on host host.
extern void build_proc_dir_entries(void);
extern int kernel_scsi_ioctl (Scsi_Device *dev, int cmd, void *arg);
-extern int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg);
+extern int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg);
extern void print_command(unsigned char *);
-extern void print_sense(char *, Scsi_Cmnd *);
+extern void print_sense(char *, Scsi_Cmnd *);
#if defined(MAJOR_NR) && (MAJOR_NR != SCSI_TAPE_MAJOR)
#define INIT_SCSI_REQUEST \
if (!CURRENT) {\
CLEAR_INTR; \
- restore_flags(flags); \
+ restore_flags(flags); \
return; \
} \
if (MAJOR(CURRENT->dev) != MAJOR_NR) \
}
#endif
-#define SCSI_SLEEP(QUEUE, CONDITION) { \
- if (CONDITION) { \
+#define SCSI_SLEEP(QUEUE, CONDITION) { \
+ if (CONDITION) { \
struct wait_queue wait = { current, NULL}; \
- add_wait_queue(QUEUE, &wait); \
- for(;;) { \
- current->state = TASK_UNINTERRUPTIBLE; \
- if (CONDITION) { \
- if (intr_count) \
+ add_wait_queue(QUEUE, &wait); \
+ for(;;) { \
+ current->state = TASK_UNINTERRUPTIBLE; \
+ if (CONDITION) { \
+ if (intr_count) \
panic("scsi: trying to call schedule() in interrupt" \
", file %s, line %d.\n", __FILE__, __LINE__); \
- schedule(); \
- } \
- else \
- break; \
- } \
- remove_wait_queue(QUEUE, &wait); \
- current->state = TASK_RUNNING; \
+ schedule(); \
+ } \
+ else \
+ break; \
+ } \
+ remove_wait_queue(QUEUE, &wait); \
+ current->state = TASK_RUNNING; \
}; }
#endif
* c-continued-statement-offset: 4
* c-continued-brace-offset: 0
* indent-tabs-mode: nil
- * tab-width: 4
+ * tab-width: 8
* End:
*/
/*
- * sd.h Copyright (C) 1992 Drew Eckhardt
- * SCSI disk driver header file by
- * Drew Eckhardt
+ * sd.h Copyright (C) 1992 Drew Eckhardt
+ * SCSI disk driver header file by
+ * Drew Eckhardt
*
- * <drew@colorado.edu>
+ * <drew@colorado.edu>
*
- * Modified by Eric Youngdale eric@tantalus.nrl.navy.mil to
- * add scatter-gather, multiple outstanding request, and other
- * enhancements.
+ * Modified by Eric Youngdale eric@tantalus.nrl.navy.mil to
+ * add scatter-gather, multiple outstanding request, and other
+ * enhancements.
*/
#ifndef _SD_H
#define _SD_H
/*
- $Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/sd.h,v 1.1 1992/07/24 06:27:38 root Exp root $
+ $Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/sd.h,v 1.1 1992/07/24 06:27:38 root Exp root $
*/
#ifndef _SCSI_H
extern struct hd_struct * sd;
typedef struct scsi_disk {
- unsigned capacity; /* size in blocks */
- unsigned sector_size; /* size in bytes */
- Scsi_Device *device;
+ unsigned capacity; /* size in blocks */
+ unsigned sector_size; /* size in bytes */
+ Scsi_Device *device;
unsigned char sector_bit_size; /* sector_size = 2 to the bit size power */
unsigned char sector_bit_shift; /* power of 2 sectors per FS block */
- unsigned ten:1; /* support ten byte read / write */
- unsigned remap:1; /* support remapping */
- unsigned has_part_table:1; /* has partition table */
+ unsigned ten:1; /* support ten byte read / write */
+ unsigned remap:1; /* support remapping */
+ unsigned has_part_table:1; /* has partition table */
} Scsi_Disk;
extern Scsi_Disk * rscsi_disks;
* c-continued-statement-offset: 4
* c-continued-brace-offset: 0
* indent-tabs-mode: nil
- * tab-width: 4
+ * tab-width: 8
* End:
*/
#ifdef CONFIG_AX25
extern int ax25_get_info(char *, char **, off_t, int);
extern int ax25_rt_get_info(char *, char **, off_t, int);
+extern int ax25_cs_get_info(char *, char **, off_t, int);
#ifdef CONFIG_NETROM
extern int nr_get_info(char *, char **, off_t, int);
extern int nr_nodes_get_info(char *, char **, off_t, int);
#ifdef CONFIG_AX25
{ PROC_NET_AX25_ROUTE, 10, "ax25_route" },
{ PROC_NET_AX25, 4, "ax25" },
+ { PROC_NET_AX25_CALLS, 10, "ax25_calls" },
#ifdef CONFIG_NETROM
{ PROC_NET_NR_NODES, 8, "nr_nodes" },
{ PROC_NET_NR_NEIGH, 8, "nr_neigh" },
case PROC_NET_AX25:
length = ax25_get_info(page,&start,file->f_pos,thistime);
break;
+ case PROC_NET_AX25_CALLS:
+ length = ax25_cs_get_info(page,&start,file->f_pos,thistime);
+ break;
#ifdef CONFIG_NETROM
case PROC_NET_NR_NODES:
length = nr_nodes_get_info(page,&start,file->f_pos,thistime);
*
* Initial version: March '95
* 95/15/05 Added subdirectories for each driver and show every
- * registered HBA as a single file.
+ * registered HBA as a single file.
* 95/30/05 Added rudimentary write support for parameter passing
*
* TODO: Improve support to write to the driver files
- * Optimize directory handling
- * Add some more comments
+ * Optimize directory handling
+ * Add some more comments
*/
#include <linux/autoconf.h>
#include <asm/segment.h>
/* forward references */
static int proc_readscsi(struct inode * inode, struct file * file,
- char * buf, int count);
+ char * buf, int count);
static int proc_writescsi(struct inode * inode, struct file * file,
- char * buf, int count);
+ char * buf, int count);
static int proc_readscsidir(struct inode *, struct file *,
- void *, filldir_t filldir);
+ void *, filldir_t filldir);
static int proc_lookupscsi(struct inode *,const char *,int,struct inode **);
static int proc_scsilseek(struct inode *, struct file *, off_t, int);
static struct file_operations proc_scsi_operations = {
- proc_scsilseek, /* lseek */
- proc_readscsi, /* read */
- proc_writescsi, /* write */
- proc_readscsidir, /* readdir */
- NULL, /* select */
- NULL, /* ioctl */
- NULL, /* mmap */
- NULL, /* no special open code */
- NULL, /* no special release code */
- NULL /* can't fsync */
+ proc_scsilseek, /* lseek */
+ proc_readscsi, /* read */
+ proc_writescsi, /* write */
+ proc_readscsidir, /* readdir */
+ NULL, /* select */
+ NULL, /* ioctl */
+ NULL, /* mmap */
+ NULL, /* no special open code */
+ NULL, /* no special release code */
+ NULL /* can't fsync */
};
/*
*/
struct inode_operations proc_scsi_inode_operations = {
&proc_scsi_operations, /* default scsi directory file-ops */
- NULL, /* create */
- proc_lookupscsi,/* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* bmap */
- NULL, /* truncate */
- NULL /* permission */
+ NULL, /* create */
+ proc_lookupscsi,/* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ NULL, /* bmap */
+ NULL, /* truncate */
+ NULL /* permission */
};
struct proc_dir_entry scsi_dir[PROC_SCSI_FILE - PROC_SCSI_SCSI + 3];
struct proc_dir_entry scsi_hba_dir[(PROC_SCSI_LAST - PROC_SCSI_FILE) * 4];
static struct proc_dir_entry scsi_dir2[] = {
- { PROC_SCSI, 1, "." },
- { PROC_ROOT_INO, 2, ".." },
- { PROC_SCSI_NOT_PRESENT, 11, "not.present" },
+ { PROC_SCSI, 1, "." },
+ { PROC_ROOT_INO, 2, ".." },
+ { PROC_SCSI_NOT_PRESENT, 11, "not.present" },
{ 0, 0, NULL }
};
if(dispatch_scsi_info_ptr)
- if (inode <= PROC_SCSI_SCSI_DEBUG)
- dir = scsi_dir;
- else
- dir = scsi_hba_dir;
+ if (inode <= PROC_SCSI_SCSI_DEBUG)
+ dir = scsi_dir;
+ else
+ dir = scsi_hba_dir;
else dir = scsi_dir2;
while(dir[i].low_ino)
- i++;
+ i++;
return(i);
}
static int proc_lookupscsi(struct inode * dir, const char * name, int len,
- struct inode ** result)
+ struct inode ** result)
{
struct proc_dir_entry *de = NULL;
*result = NULL;
if (!dir)
- return(-ENOENT);
+ return(-ENOENT);
if (!S_ISDIR(dir->i_mode)) {
- iput(dir);
- return(-ENOENT);
+ iput(dir);
+ return(-ENOENT);
}
if (dispatch_scsi_info_ptr != NULL)
- if (dir->i_ino <= PROC_SCSI_SCSI)
- de = scsi_dir;
- else {
- de = &scsi_hba_dir[dispatch_scsi_info_ptr(dir->i_ino, 0, 0, 0, 0, 2)];
- }
+ if (dir->i_ino <= PROC_SCSI_SCSI)
+ de = scsi_dir;
+ else {
+ de = &scsi_hba_dir[dispatch_scsi_info_ptr(dir->i_ino, 0, 0, 0, 0, 2)];
+ }
else
- de = scsi_dir2;
+ de = scsi_dir2;
for (; de->name ; de++) {
- if (!proc_match(len, name, de))
- continue;
- *result = iget(dir->i_sb, de->low_ino);
- iput(dir);
- if (!*result)
- return(-ENOENT);
- return(0);
+ if (!proc_match(len, name, de))
+ continue;
+ *result = iget(dir->i_sb, de->low_ino);
+ iput(dir);
+ if (!*result)
+ return(-ENOENT);
+ return(0);
}
iput(dir);
return(-ENOENT);
}
static int proc_readscsidir(struct inode * inode, struct file * filp,
- void * dirent, filldir_t filldir)
+ void * dirent, filldir_t filldir)
{
struct proc_dir_entry * de;
unsigned int ino;
if (!inode || !S_ISDIR(inode->i_mode))
- return(-EBADF);
+ return(-EBADF);
ino = inode->i_ino;
- while (((unsigned) filp->f_pos) < count_dir_entries(ino)) {
- if (dispatch_scsi_info_ptr)
- if (ino <= PROC_SCSI_SCSI)
- de = scsi_dir + filp->f_pos;
- else
- de = scsi_hba_dir + filp->f_pos;
- else
- de = scsi_dir2 + filp->f_pos;
- if (filldir(dirent, de->name, de->namelen, filp->f_pos, de->low_ino)<0)
- break;
- filp->f_pos++;
+ while (((unsigned) filp->f_pos) < count_dir_entries(ino)) {
+ if (dispatch_scsi_info_ptr)
+ if (ino <= PROC_SCSI_SCSI)
+ de = scsi_dir + filp->f_pos;
+ else
+ de = scsi_hba_dir + filp->f_pos;
+ else
+ de = scsi_dir2 + filp->f_pos;
+ if (filldir(dirent, de->name, de->namelen, filp->f_pos, de->low_ino)<0)
+ break;
+ filp->f_pos++;
}
return(0);
}
begin = 0;
pos = len = sprintf(buffer,
- "The scsi core module is currently not present\n");
+ "The scsi core module is currently not present\n");
if(pos < offset) {
- len = 0;
- begin = pos;
+ len = 0;
+ begin = pos;
}
- *start = buffer + (offset - begin); /* Start of wanted data */
+ *start = buffer + (offset - begin); /* Start of wanted data */
len -= (offset - begin);
if(len > length)
- len = length;
+ len = length;
return(len);
}
#define PROC_BLOCK_SIZE (3*1024) /* 4K page size, but our output routines
- * use some slack for overruns
- */
+ * use some slack for overruns
+ */
static int proc_readscsi(struct inode * inode, struct file * file,
- char * buf, int count)
+ char * buf, int count)
{
uint ino;
int length;
char * page;
char * start;
- if (count < -1) /* Normally I wouldn't do this, */
- return(-EINVAL); /* but it saves some redundant code.
- * Now it is possible to seek to the
- * end of the file */
+ if (count < -1) /* Normally I wouldn't do this, */
+ return(-EINVAL); /* but it saves some redundant code.
+ * Now it is possible to seek to the
+ * end of the file */
if (!(page = (char *) __get_free_page(GFP_KERNEL)))
- return(-ENOMEM);
+ return(-ENOMEM);
ino = inode->i_ino;
while(bytes > 0 || count == -1)
{
-
- thistime = bytes;
- if(bytes > PROC_BLOCK_SIZE || count == -1)
- thistime = PROC_BLOCK_SIZE;
-
- if(dispatch_scsi_info_ptr)
- length = dispatch_scsi_info_ptr(ino, page, &start,
- file->f_pos, thistime, 0);
- else
- length = get_not_present_info(page, &start, file->f_pos, thistime);
- if(length < 0) {
- free_page((ulong) page);
- return(length);
- }
-
- /*
- * We have been given a non page aligned block of
- * the data we asked for + a bit. We have been given
- * the start pointer and we know the length..
- */
- if (length <= 0)
- break;
- /*
- * Copy the bytes, if we're not doing a seek to
- * the end of the file
- */
- if (count != -1)
- memcpy_tofs(buf + copied, start, length);
- file->f_pos += length; /* Move down the file */
- bytes -= length;
- copied += length;
-
- if(length < thistime)
- break; /* End of file */
-
+
+ thistime = bytes;
+ if(bytes > PROC_BLOCK_SIZE || count == -1)
+ thistime = PROC_BLOCK_SIZE;
+
+ if(dispatch_scsi_info_ptr)
+ length = dispatch_scsi_info_ptr(ino, page, &start,
+ file->f_pos, thistime, 0);
+ else
+ length = get_not_present_info(page, &start, file->f_pos, thistime);
+ if(length < 0) {
+ free_page((ulong) page);
+ return(length);
+ }
+
+ /*
+ * We have been given a non page aligned block of
+ * the data we asked for + a bit. We have been given
+ * the start pointer and we know the length..
+ */
+ if (length <= 0)
+ break;
+ /*
+ * Copy the bytes, if we're not doing a seek to
+ * the end of the file
+ */
+ if (count != -1)
+ memcpy_tofs(buf + copied, start, length);
+ file->f_pos += length; /* Move down the file */
+ bytes -= length;
+ copied += length;
+
+ if(length < thistime)
+ break; /* End of file */
+
}
free_page((ulong) page);
static int proc_writescsi(struct inode * inode, struct file * file,
- char * buf, int count)
+ char * buf, int count)
{
uint ino;
int ret = 0;
char * page;
if (!(page = (char *) __get_free_page(GFP_KERNEL)))
- return(-ENOMEM);
+ return(-ENOMEM);
if(count > PROC_BLOCK_SIZE) {
- return(-EOVERFLOW);
+ return(-EOVERFLOW);
}
ino = inode->i_ino;
if(dispatch_scsi_info_ptr != NULL) {
- memcpy_fromfs(page, buf, count);
- ret = dispatch_scsi_info_ptr(ino, page, 0, 0, count, 1);
+ memcpy_fromfs(page, buf, count);
+ ret = dispatch_scsi_info_ptr(ino, page, 0, 0, count, 1);
} else {
- free_page((ulong) page);
- return(-ENOPKG); /* Nothing here */
+ free_page((ulong) page);
+ return(-ENOPKG); /* Nothing here */
}
free_page((ulong) page);
static int proc_scsilseek(struct inode * inode, struct file * file,
- off_t offset, int orig)
+ off_t offset, int orig)
{
switch (orig) {
case 0:
- file->f_pos = offset;
- return(file->f_pos);
+ file->f_pos = offset;
+ return(file->f_pos);
case 1:
- file->f_pos += offset;
- return(file->f_pos);
- case 2: /* This ugly hack allows us to */
- if (offset) /* to determine the length of the */
- return(-EINVAL); /* file and then later savely to */
- proc_readscsi(inode, file, 0, -1); /* seek in it */
- return(file->f_pos);
+ file->f_pos += offset;
+ return(file->f_pos);
+ case 2: /* This ugly hack allows us to */
+ if (offset) /* to determine the length of the */
+ return(-EINVAL); /* file and then later savely to */
+ proc_readscsi(inode, file, 0, -1); /* seek in it */
+ return(file->f_pos);
default:
- return(-EINVAL);
+ return(-EINVAL);
}
}
* c-continued-statement-offset: 4
* c-continued-brace-offset: 0
* indent-tabs-mode: nil
- * tab-width: 4
+ * tab-width: 8
* End:
*/
*/
static inline unsigned short ip_fast_csum(unsigned char * iph,
unsigned int ihl) {
- unsigned short int sum;
+ unsigned int sum;
__asm__("
- movl (%%esi), %%eax
- andl $15, %%ecx
- subl $4, %%ecx
+ movl (%1), %0
+ subl $4, %2
jbe 2f
- addl 4(%%esi), %%eax
- adcl 8(%%esi), %%eax
- adcl 12(%%esi), %%eax
-1: adcl 16(%%esi), %%eax
- lea 4(%%esi), %%esi
- decl %%ecx
+ addl 4(%1), %0
+ adcl 8(%1), %0
+ adcl 12(%1), %0
+1: adcl 16(%1), %0
+ lea 4(%1), %1
+ decl %2
jne 1b
- adcl $0, %%eax
- movl %%eax, %%ecx
- shrl $16, %%eax
- addw %%ecx, %%eax
- adcl $0, %%eax
- notl %%eax
- andl $65535, %%eax
+ adcl $0, %0
+ movl %0, %2
+ shrl $16, %0
+ addw %w2, %w0
+ adcl $0, %0
+ notl %0
2:
"
- : "=a" (sum)
- : "S" (iph), "c"(ihl)
- : "ax", "cx", "si");
+ : "=&r" (sum), "=&r" (iph), "=&r" (ihl)
+ : "1" (iph), "2" (ihl));
return(sum);
}
unsigned short proto,
unsigned int sum) {
__asm__("
- addl %2, %0
- adcl %3, %0
+ addl %1, %0
adcl %4, %0
+ adcl %5, %0
adcl $0, %0
- movl %0, %2
- shrl $16, %2
- addw %2, %0
+ movl %0, %1
+ shrl $16, %1
+ addw %w1, %w0
adcl $0, %0
notl %0
- andl $65535, %0
"
- : "=r" (sum)
- : "0" (daddr), "S"(saddr), "r"((ntohs(len)<<16)+proto*256), "r"(sum)
- : "si" );
+ : "=&r" (sum), "=&r" (saddr)
+ : "0" (daddr), "1"(saddr), "r"((ntohs(len)<<16)+proto*256), "r"(sum));
return((unsigned short)sum);
}
*/
static inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
- unsigned short int sum;
+ unsigned int sum;
+ unsigned int scratch;
__asm__("
- movl %%eax, %%ecx
- shrl $16, %%ecx
- addw %%cx, %%ax
- adcl $0, %%eax
- notl %%eax
- andl $65535, %%eax
+ movl %0, %1
+ shrl $16, %1
+ addw %w1, %w0
+ adcl $0, %0
+ notl %0
"
- : "=a"(sum)
- : "a" (csum_partial(buff, len, 0))
- : "cx");
+ : "=a"(sum), "=r" (scratch)
+ : "0" (csum_partial(buff, len, 0)));
return(sum);
}
#define AX25_N2 3
#define AX25_T3 4
#define AX25_T2 5
+#define AX25_BACKOFF 6
#define SIOCAX25GETUID (SIOCPROTOPRIVATE)
#define SIOCAX25ADDUID (SIOCPROTOPRIVATE+1)
#include <linux/if_ether.h>
#ifdef __KERNEL__
-extern int eth_header(unsigned char *buff, struct device *dev,
+extern int eth_header(struct sk_buff *skb, struct device *dev,
unsigned short type, void *daddr,
- void *saddr, unsigned len,
- struct sk_buff *skb);
+ void *saddr, unsigned len);
extern int eth_rebuild_header(void *buff, struct device *dev,
- unsigned long raddr, struct sk_buff *skb);
+ unsigned long dst, struct sk_buff *skb);
extern unsigned short eth_type_trans(struct sk_buff *skb, struct device *dev);
#endif
int (*stop)(struct device *dev);
int (*hard_start_xmit) (struct sk_buff *skb,
struct device *dev);
- int (*hard_header) (unsigned char *buff,
+ int (*hard_header) (struct sk_buff *skb,
struct device *dev,
unsigned short type,
void *daddr,
void *saddr,
- unsigned len,
- struct sk_buff *skb);
+ unsigned len);
int (*rebuild_header)(void *eth, struct device *dev,
unsigned long raddr, struct sk_buff *skb);
#define HAVE_MULTICAST
#define NETROM_T2 2
#define NETROM_N2 3
-#define SIOCNRADDNODE (SIOCPROTOPRIVATE)
-#define SIOCNRDELNODE (SIOCPROTOPRIVATE+1)
-#define SIOCNRADDNEIGH (SIOCPROTOPRIVATE+2)
-#define SIOCNRDELNEIGH (SIOCPROTOPRIVATE+3)
-#define SIOCNRGETPARMS (SIOCPROTOPRIVATE+4)
-#define SIOCNRSETPARMS (SIOCPROTOPRIVATE+5)
-#define SIOCNRDECOBS (SIOCPROTOPRIVATE+6)
+#define SIOCNRGETPARMS (SIOCPROTOPRIVATE+0)
+#define SIOCNRSETPARMS (SIOCPROTOPRIVATE+1)
+#define SIOCNRDECOBS (SIOCPROTOPRIVATE+2)
-struct nr_node_struct {
+struct nr_route_struct {
+#define NETROM_NEIGH 0
+#define NETROM_NODE 1
+ int type;
ax25_address callsign;
- char mnemonic[7];
- ax25_address neighbour;
char device[16];
unsigned int quality;
+ char mnemonic[7];
+ ax25_address neighbour;
unsigned int obs_count;
};
-struct nr_neigh_struct {
- ax25_address callsign;
- char device[16];
- unsigned int quality;
-};
-
struct nr_parms_struct {
unsigned int quality;
unsigned int obs_count;
#ifdef CONFIG_AX25
PROC_NET_AX25_ROUTE,
PROC_NET_AX25,
+ PROC_NET_AX25_CALLS,
#ifdef CONFIG_NETROM
PROC_NET_NR_NODES,
PROC_NET_NR_NEIGH,
#include <linux/time.h>
#include <linux/config.h>
-#undef CONFIG_SKB_CHECK
+/* #define CONFIG_SKB_CHECK 1 */
#define HAVE_ALLOC_SKB /* For the drivers to know */
volatile unsigned long when; /* used to compute rtt's */
struct timeval stamp; /* Time we arrived */
struct device *dev; /* Device we arrived on/are leaving by */
- struct sk_buff *mem_addr; /* Self reference (obsolete) */
union {
struct tcphdr *th;
struct ethhdr *eth;
unsigned long seq;
} h;
struct iphdr *ip_hdr; /* For IPPROTO_RAW */
- unsigned long mem_len; /* Length of allocated memory */
unsigned long len; /* Length of actual data */
- unsigned long fraglen; /* Unused (yet) */
- struct sk_buff *fraglist; /* Fragment list */
- unsigned long truesize; /* True buffer size (obsolete) */
unsigned long saddr; /* IP source address */
unsigned long daddr; /* IP target address */
unsigned long raddr; /* IP next hop address */
#define PACKET_OTHERHOST 3 /* To someone else */
unsigned short users; /* User count - see datagram.c,tcp.c */
unsigned short protocol; /* Packet protocol from driver. */
-#ifdef CONFIG_SLAVE_BALANCING
- unsigned short in_dev_queue;
-#endif
- unsigned long padding[0]; /* Force long word alignment */
- unsigned char data[0]; /* Data follows */
+ unsigned short truesize; /* Buffer size */
+ unsigned char *head; /* Head of buffer */
+ unsigned char *data; /* Data head pointer */
+ unsigned char *tail; /* Tail pointer */
+ unsigned char *end; /* End pointer */
};
#define SK_WMEM_MAX 32767
extern void skb_unlink(struct sk_buff *buf);
extern struct sk_buff * skb_peek_copy(struct sk_buff_head *list);
extern struct sk_buff * alloc_skb(unsigned int size, int priority);
-extern void kfree_skbmem(struct sk_buff *skb, unsigned size);
+extern struct sk_buff * dev_alloc_skb(unsigned int size);
+extern void kfree_skbmem(struct sk_buff *skb);
extern struct sk_buff * skb_clone(struct sk_buff *skb, int priority);
extern void skb_device_lock(struct sk_buff *skb);
extern void skb_device_unlock(struct sk_buff *skb);
extern void dev_kfree_skb(struct sk_buff *skb, int mode);
extern int skb_device_locked(struct sk_buff *skb);
+extern unsigned char * skb_put(struct sk_buff *skb, int len);
+extern unsigned char * skb_push(struct sk_buff *skb, int len);
+extern int skb_pull(struct sk_buff *skb, int len);
+extern int skb_headroom(struct sk_buff *skb);
+extern int skb_tailroom(struct sk_buff *skb);
+extern void skb_reserve(struct sk_buff *skb, int len);
+extern void skb_trim(struct sk_buff *skb, int len);
+
/*
* Peek an sk_buff. Unlike most other operations you _MUST_
* be careful with this one. A peek leaves the buffer on the
restore_flags(flags);
}
+/*
+ * Add data to an sk_buff
+ */
+
+extern __inline__ unsigned char *skb_put(struct sk_buff *skb, int len)
+{
+ unsigned char *tmp=skb->tail;
+ skb->tail+=len;
+ skb->len+=len;
+ if(skb->tail>skb->end)
+ panic("skput:over: %p:%d", __builtin_return_address(0),len);
+ return tmp;
+}
+
+extern __inline__ unsigned char *skb_push(struct sk_buff *skb, int len)
+{
+ skb->data-=len;
+ skb->len+=len;
+ if(skb->data<skb->head)
+ panic("skpush:under: %p:%d", __builtin_return_address(0),len);
+ return skb->data;
+}
+
+extern __inline__ int skb_pull(struct sk_buff *skb, int len)
+{
+ if(len>skb->len)
+ len=skb->len;
+ skb->data+=len;
+ skb->len-=len;
+ return len;
+}
+
+extern __inline__ int skb_headroom(struct sk_buff *skb)
+{
+ return skb->data-skb->head;
+}
+
+extern __inline__ int skb_tailroom(struct sk_buff *skb)
+{
+ return skb->end-skb->tail;
+}
+
+extern __inline__ void skb_reserve(struct sk_buff *skb, int len)
+{
+ skb->data+=len;
+ skb->tail+=len;
+}
+
+extern __inline__ void skb_trim(struct sk_buff *skb, int len)
+{
+ if(skb->len>len)
+ {
+ skb->len=len;
+ skb->tail=skb->data+len;
+ }
+}
+
#endif
extern struct sk_buff * skb_recv_datagram(struct sock *sk,unsigned flags,int noblock, int *err);
#include <linux/if_tr.h>
#ifdef __KERNEL__
-extern int tr_header(unsigned char *buff, struct device *dev,
+extern int tr_header(struct sk_buff *skb, struct device *dev,
unsigned short type, void *daddr,
- void *saddr, unsigned len,
- struct sk_buff *skb);
+ void *saddr, unsigned len);
extern int tr_rebuild_header(void *buff, struct device *dev,
unsigned long raddr, struct sk_buff *skb);
extern unsigned short tr_type_trans(struct sk_buff *skb, struct device *dev);
struct device *device;
unsigned char state;
unsigned short vs, vr, va;
- unsigned char condition;
+ unsigned char condition, backoff;
unsigned char n2, n2count;
unsigned short t1, t2, t3, rtt;
unsigned short t1timer, t2timer, t3timer;
extern int ax25_rcv(struct sk_buff *,struct device *,struct packet_type *);
extern void ax25_destroy_socket(ax25_cb *);
extern struct device *ax25rtr_get_dev(ax25_address *);
-extern int ax25_encapsulate(unsigned char *, struct device *, unsigned short,
- void *, void *, unsigned int, struct sk_buff *);
+extern int ax25_encapsulate(struct sk_buff *, struct device *, unsigned short,
+ void *, void *, unsigned int);
extern int ax25_rebuild_header(unsigned char *, struct device *, unsigned long, struct sk_buff *);
extern int ax25_get_info(char *, char **, off_t, int);
extern ax25_uid_assoc *ax25_uid_list;
extern char *eth_print(unsigned char *ptr);
extern void eth_dump(struct ethhdr *eth);
-extern int eth_header(unsigned char *buff, struct device *dev,
- unsigned short type, unsigned long daddr,
- unsigned long saddr, unsigned len);
-extern int eth_rebuild_header(void *buff, struct device *dev);
+extern int eth_header(struct sk_buff *skb, struct device *dev,
+ unsigned short type, void *daddr,
+ void *saddr, unsigned len);
+extern int eth_rebuild_header(void *buff, struct device *dev,
+ unsigned long dst, struct sk_buff *skb);
extern void eth_add_arp(unsigned long addr, struct sk_buff *skb,
struct device *dev);
extern unsigned short eth_type_trans(struct sk_buff *skb, struct device *dev);
ax25_address user_addr, source_addr, dest_addr;
unsigned char my_index, my_id;
unsigned char your_index, your_id;
- unsigned char state;
+ unsigned char state, bpqext;
unsigned short vs, vr, va, vl;
unsigned char condition;
unsigned char n2, n2count;
extern void ip_rt_flush(struct device *dev);
extern void ip_rt_add(short flags, unsigned long addr, unsigned long mask,
- unsigned long gw, struct device *dev, unsigned short mss, unsigned long window, unsigned short irtt);
+ unsigned long gw, struct device *dev, unsigned short mss, unsigned long window, unsigned short irtt, unsigned char metric);
extern struct rtable *ip_rt_route(unsigned long daddr, struct options *opt, unsigned long *src_addr);
extern struct rtable *ip_rt_local(unsigned long daddr, struct options *opt, unsigned long *src_addr);
extern int rt_get_info(char * buffer, char **start, off_t offset, int length);
struct sk_buff * (*rmalloc)(struct sock *sk,
unsigned long size, int force,
int priority);
- void (*wfree)(struct sock *sk, struct sk_buff *skb,
- unsigned long size);
- void (*rfree)(struct sock *sk, struct sk_buff *skb,
- unsigned long size);
+ void (*wfree)(struct sock *sk, struct sk_buff *skb);
+ void (*rfree)(struct sock *sk, struct sk_buff *skb);
unsigned long (*rspace)(struct sock *sk);
unsigned long (*wspace)(struct sock *sk);
void (*close)(struct sock *sk, int timeout);
extern struct sk_buff *sock_rmalloc(struct sock *sk,
unsigned long size, int force,
int priority);
-extern void sock_wfree(struct sock *sk, struct sk_buff *skb,
- unsigned long size);
-extern void sock_rfree(struct sock *sk, struct sk_buff *skb,
- unsigned long size);
+extern void sock_wfree(struct sock *sk, struct sk_buff *skb);
+extern void sock_rfree(struct sock *sk, struct sk_buff *skb);
extern unsigned long sock_rspace(struct sock *sk);
extern unsigned long sock_wspace(struct sock *sk);
extern __inline__ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
unsigned long flags;
- if(sk->rmem_alloc + skb->mem_len >= sk->rcvbuf)
+ if(sk->rmem_alloc + skb->truesize >= sk->rcvbuf)
return -ENOMEM;
save_flags(flags);
cli();
- sk->rmem_alloc+=skb->mem_len;
+ sk->rmem_alloc+=skb->truesize;
skb->sk=sk;
restore_flags(flags);
skb_queue_tail(&sk->receive_queue,skb);
struct task_struct *p;
if (stat_addr) {
- flag = verify_area(VERIFY_WRITE, stat_addr, 4);
+ flag = verify_area(VERIFY_WRITE, stat_addr, sizeof(*stat_addr));
if (flag)
return flag;
}
#ifdef CONFIG_NET
#include <linux/net.h>
#include <linux/netdevice.h>
+#include <net/eth.h>
#ifdef CONFIG_INET
#include <linux/ip.h>
#include <linux/etherdevice.h>
X(eth_type_trans),
X(alloc_skb),
X(kfree_skb),
+ X(dev_alloc_skb),
X(dev_kfree_skb),
X(netif_rx),
X(dev_rint),
{
int error;
/* fill in "set" with signals pending but blocked. */
- error = verify_area(VERIFY_WRITE, set, 4);
+ error = verify_area(VERIFY_WRITE, set, sizeof(sigset_t));
if (!error)
put_user(current->blocked & current->signal, set);
return error;
return -EPERM;
if (gidsetsize > NGROUPS)
return -EINVAL;
+ i = verify_area(VERIFY_READ, grouplist, sizeof(gid_t) * gidsetsize);
+ if (i)
+ return i;
for (i = 0; i < gidsetsize; i++, grouplist++) {
current->groups[i] = get_user(grouplist);
}
*/
asmlinkage int sys_setdomainname(char *name, int len)
{
- int i;
+ int error;
if (!suser())
return -EPERM;
if (len > __NEW_UTS_LEN)
return -EINVAL;
- for (i=0; i < len; i++) {
- if ((system_utsname.domainname[i] = get_user(name+i)) == 0)
- return 0;
- }
- system_utsname.domainname[i] = 0;
+ error = verify_area(VERIFY_READ, name, len);
+ if (error)
+ return error;
+ memcpy_fromfs(system_utsname.domainname, name, len);
+ system_utsname.domainname[len] = 0;
return 0;
}
return;
}
+#define LONG_ALIGN(x) (((x)+(sizeof(long))-1)&~((sizeof(long))-1))
+
/*
* set up the free-area data structures:
* - mark all pages MAP_PAGE_RESERVED
start_mem = init_swap_cache(start_mem, end_mem);
mem_map = (mem_map_t *) start_mem;
p = mem_map + MAP_NR(end_mem);
- start_mem = (unsigned long) p;
+ start_mem = LONG_ALIGN((unsigned long) p);
while (p > mem_map)
*--p = MAP_PAGE_RESERVED;
end_mem = (end_mem + ~mask) & mask;
bitmap_size = (end_mem - PAGE_OFFSET) >> (PAGE_SHIFT + i);
bitmap_size = (bitmap_size + 7) >> 3;
- bitmap_size = (bitmap_size + sizeof(unsigned long) - 1) & ~(sizeof(unsigned long)-1);
+ bitmap_size = LONG_ALIGN(bitmap_size);
free_area_map[i] = (unsigned char *) start_mem;
memset((void *) start_mem, 0, bitmap_size);
start_mem += bitmap_size;
proto = find_8022_client(*(skb->h.raw));
if (proto != NULL) {
skb->h.raw += 3;
- skb->len -= 3;
+ skb_pull(skb,3);
return proto->rcvfunc(skb, dev, pt);
}
unsigned long hard_len = dev->hard_header_len;
unsigned char *rawp;
- dev->hard_header(skb->data, dev, len - hard_len,
- dest_node, NULL, len - hard_len, skb);
- rawp = skb->data + hard_len;
+ dev->hard_header(skb, dev, len - hard_len,
+ dest_node, NULL, len - hard_len);
+ rawp = skb_push(skb,3);
*rawp = dl->type[0];
rawp++;
*rawp = dl->type[0];
unsigned long len = skb->len;
unsigned long hard_len = dev->hard_header_len;
- dev->hard_header(skb->data, dev, len - hard_len,
- dest_node, NULL, len - hard_len, skb);
+ dev->hard_header(skb, dev, len - hard_len,
+ dest_node, NULL, len - hard_len);
skb->h.raw = skb->data + hard_len;
}
*/
skb->h.raw += 5;
- skb->len -= 5;
+ skb_pull(skb,5);
if (psnap_packet_type.type == 0)
psnap_packet_type.type=htons(ETH_P_SNAP);
return proto->rcvfunc(skb, dev, &psnap_packet_type);
static void snap_datalink_header(struct datalink_proto *dl, struct sk_buff *skb, unsigned char *dest_node)
{
- struct device *dev = skb->dev;
unsigned char *rawp;
- rawp = skb->data + snap_dl->header_length+dev->hard_header_len;
+ rawp = skb_push(skb,5);
memcpy(rawp,dl->type,5);
skb->h.raw = rawp+5;
snap_dl->datalink_header(snap_dl, skb, dest_node);
int tr_header(unsigned char *buff, struct device *dev, unsigned short type,
void *daddr, void *saddr, unsigned len, struct sk_buff *skb) {
- struct trh_hdr *trh=(struct trh_hdr *)buff;
+ struct trh_hdr *trh=(struct trh_hdr *)skb_push(skb,dev->hard_header_len);
struct trllc *trllc=(struct trllc *)(buff+sizeof(struct trh_hdr));
-
+
trh->ac=AC;
trh->fc=LLC_FRAME;
o SCC driver from Joerg Reuter [IN]
o IP Firewall accounting zero bug [IN]
-////////////////////////////1.3.0/////////////////////////// ??
+////////////////////////////1.3.0///////////////////////////
+
+
+o Merged loadable firewall code [NOT INCLUDED YET]
+o New buffers used totally non optimally [SEEMS OK]
+o Fast ip_forwarding (needs changing) [NOT INCLUDED YET]
+o Fixed connection hang bug in new SWS code [TESTED]
+o Buffer management hack putting skbuff control
+ after data in the frame because kmalloc is
+ totally cache non-optimal [TESTED]
+o Faster checksum [Tom May] [IN]
+o Appletalk router fixes [Michael Callahan] [IN]
+o TCP state error fixes [Mark Tamsky] [IN]
+o Verify area fixes [Heiko Eissfeldt] [IN]
+o Routes use metric field [John Naylor] [IN]
+o Major AX.25/NetROM fixes [John Nalor] [IN]
+
+------->>>>> NET3 030 <<<<<----------
o Finish merging the bridge code
o Device locking
o SIOCSLEEPRT patch
o Options support in ip_build_xmit [PENDING]
o Fast checksum/copy on outgoing TCP
-o New buffers. Used totally non-optimally
-o Long word align ethernet IP headers (64byte align for pentium)
+o Long word align ethernet IP headers (64byte align for pentium) [TESTING - EMAIL FOR INFO]
o Explode/implode headers for alpha,mips etc.
o Fast dev_grab_next() transmit reload function
and dev_push_failed() ??
o Faster ip_forward
o Faster loopback frame forwarding.
o Forwarding queue control (+ fairness algorithms ??)
-o Merge loadable firewall code.
o IP forward flow control.
o Infinite PPP/SLIP devices.
+o PI2 card doesn't do AX.25 VC yet
+o AX.25 set protocol type
+o Clean up RAW AX.25 sockets.
+o Finish 802.2 Class I code to be compliant to the oddities of 802.2
0.2
---
o PPP for Sonix ISDN.
o Loadable firewall extensions.
o Screend loadable firewall module
-o LZ SLIP
+o LZ SLIP [Done, resolving patent issues]
0.3
---
skb->arp = 1;
skb->free = 1;
- skb->len = len;
+ skb_put(skb,len);
skb->dev = a->dev;
/*
skb->arp = 1;
skb->free = 1;
- skb->len = len;
+ skb_put(skb,len);
skb->dev = dev;
/*
skb->arp = 1;
skb->free = 1;
- skb->len = len;
+ skb_put(skb,len);
skb->dev = dev;
/*
return 0;
}
+ skb_pull(skb,dev->hard_header_len);
+
/*
* Frame size ok ?
*/
- if(skb->len<sizeof(*ea))
+ if(skb_pull(skb,sizeof(*ea))<sizeof(*ea))
{
kfree_skb(skb, FREE_READ);
return 0;
*
* Wesley Craig <netatalk@umich.edu>
*
+ * Fixes:
+ * Michael Callahan : Made routing work
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
*
* TODO
* ASYNC I/O
- * Testing.
*/
#include <asm/segment.h>
struct ddpehdr *ddp=(void *)skb->h.raw;
struct atalk_iface *atif;
struct sockaddr_at tosat;
+ int origlen;
+
+ /* First strip the MAC header */
+
+ skb_pull(skb,dev->hard_header_len);
/* Size check */
if(skb->len<sizeof(*ddp))
* Trim buffer in case of stray trailing data
*/
- skb->len=min(skb->len,ddp->deh_len);
+ origlen = skb->len;
+
+ skb_trim(skb,min(skb->len,ddp->deh_len));
/*
* Size check to see if ddp->deh_len was crap
{
struct atalk_route *rt;
struct at_addr ta;
+
+ /* Don't route multicast, etc., packets, or packets
+ sent to "this network" */
+ if (skb->pkt_type != PACKET_HOST || ddp->deh_dnet == 0)
+ {
+ kfree_skb(skb, FREE_READ);
+ return(0);
+ }
+
ta.s_net=ddp->deh_dnet;
ta.s_node=ddp->deh_dnode;
+
/* Route the packet */
rt=atrtr_find(&ta);
if(rt==NULL || ddp->deh_hops==15)
return(0);
}
ddp->deh_hops++;
+
+ /* Fix up skb->len field */
+ skb_trim(skb,min(origlen, rt->dev->hard_header_len +
+ ddp_dl->header_length + ddp->deh_len));
+
*((__u16 *)ddp)=ntohs(*((__u16 *)ddp)); /* Mend the byte order */
/*
* Send the buffer onwards
*/
- if(aarp_send_ddp(dev,skb, &ta, NULL)==-1)
+ if(aarp_send_ddp(rt->dev, skb, &ta, NULL)==-1)
kfree_skb(skb, FREE_READ);
return 0;
}
skb->sk=sk;
skb->free=1;
skb->arp=1;
- skb->len=size;
+ skb_reserve(skb,ddp_dl->header_length);
+ skb_reserve(skb,dev->hard_header_len);
+ skb_put(skb,size);
skb->dev=dev;
if(sk->debug)
printk("SK %p: Begin build.\n", sk);
- skb->h.raw=skb->data+ddp_dl->header_length+dev->hard_header_len;
+ skb->h.raw=skb->data;
ddp=(struct ddpehdr *)skb->h.raw;
ddp->deh_pad=0;
if(sk->debug)
printk("SK %p: Loop back.\n", sk);
/* loop back */
- sk->wmem_alloc-=skb->mem_len;
+ sk->wmem_alloc-=skb->truesize;
ddp_dl->datalink_header(ddp_dl, skb, dev->dev_addr);
skb->sk = NULL;
skb->h.raw = skb->data + ddp_dl->header_length + dev->hard_header_len;
- skb->len -= ddp_dl->header_length ;
- skb->len -= dev->hard_header_len ;
+ skb_pull(skb,dev->hard_header_len);
+ skb_pull(skb,ddp_dl->header_length);
atalk_rcv(skb,dev,NULL);
}
else
printk("Unable to register DDP with SNAP.\n");
register_netdevice_notifier(&ddp_notifier);
aarp_proto_init();
- printk("Appletalk ALPHA 0.08 for Linux NET3.029\n");
+ printk("Appletalk BETA 0.11 for Linux NET3.030\n");
}
#endif
* Jonathan(G4KLX) and removed all the old Berkeley, added IP mode registration.
* Darryl(G7LED) stuff. Cross-port digipeating. Minor fixes and enhancements.
* Alan(GW4PTS) Missed suser() on axassociate checks
+ * AX.25 030 Alan(GW4PTS) Switched to new buffers. Not tested netrom/new buffers yet.
*
* To do:
* Support use as digipeater, including an on/off ioctl
* copy only when needed.
* Consider better arbitary protocol support.
* Fix non-blocking connect failure.
+ * VC mode doesnt work on the PI card.
+ * Settable protocol id for SEQPACKET sockets
*/
#include <linux/config.h>
return;
copy->sk = sk;
- sk->rmem_alloc += copy->mem_len;
+ sk->rmem_alloc += copy->truesize;
skb_queue_tail(&sk->receive_queue, copy);
if (!sk->dead)
- sk->data_ready(sk, skb->len - 2);
+ sk->data_ready(sk, skb->len);
}
sk = sk->next;
ax25->n2 = DEFAULT_N2;
ax25->t3 = DEFAULT_T3;
+ ax25->backoff = 1;
ax25->condition = 0x00;
ax25->t1timer = 0;
ax25->t2timer = 0;
case AX25_T1:
if (opt < 1)
return -EINVAL;
- sk->ax25->t1 = opt * PR_SLOWHZ;
+ sk->ax25->rtt = (opt * PR_SLOWHZ) / 2;
return 0;
case AX25_T2:
sk->ax25->t3 = opt * PR_SLOWHZ;
return 0;
+ case AX25_BACKOFF:
+ sk->ax25->backoff = opt ? 1 : 0;
+ return 0;
+
default:
return -ENOPROTOOPT;
}
val = sk->ax25->t3 / PR_SLOWHZ;
break;
+ case AX25_BACKOFF:
+ val = sk->ax25->backoff;
+ break;
+
default:
return -ENOPROTOOPT;
}
sk->write_space = def_callback1;
sk->error_report = def_callback1;
- ax25->rtt = osk->ax25->rtt;
- ax25->t1 = osk->ax25->t1;
- ax25->t2 = osk->ax25->t2;
- ax25->t3 = osk->ax25->t3;
- ax25->n2 = osk->ax25->n2;
+ ax25->backoff = osk->ax25->backoff;
+ ax25->rtt = osk->ax25->rtt;
+ ax25->t1 = osk->ax25->t1;
+ ax25->t2 = osk->ax25->t2;
+ ax25->t3 = osk->ax25->t3;
+ ax25->n2 = osk->ax25->n2;
- ax25->window = osk->ax25->window;
- ax25->device = dev;
+ ax25->window = osk->ax25->window;
+ ax25->device = dev;
memcpy(&ax25->source_addr, &osk->ax25->source_addr, sizeof(ax25_address));
int ax25_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *ptype)
{
- unsigned char *data = skb->data;
+ unsigned char *data;
struct sock *make;
struct sock *sk;
int type = 0;
ax25_address src, dest;
struct sock *raw;
int mine = 0;
+
+ data=skb->data;
+
+ /*
+ * Process the AX.25/LAPB frame.
+ */
skb->sk = NULL; /* Initially we don't know who its for */
}
#endif
build_ax25_addr(skb->data + 1, &src, &dest, &dp, type);
- skb->len += dev->hard_header_len;
skb->arp = 1;
dev_queue_xmit(skb, dev, SOPRI_NORMAL);
} else {
return 0;
}
- /*
- * Adjust the lengths for digipeated input
- */
- skb->len -= sizeof(ax25_address) * dp.ndigi;
-
+
/* For our port addreses ? */
if (ax25cmp(&dest, (ax25_address *)dev->dev_addr) == 0)
mine = 1;
if ((raw = ax25_addr_match(&dest)) != NULL)
ax25_send_to_raw(raw, skb, (int)*data);
- if (!mine && ax25cmp(&dest, (ax25_address *)dev->broadcast) != 0) {
+ if (!mine && ax25cmp(&dest, (ax25_address *)dev->broadcast) != 0)
+ {
kfree_skb(skb, FREE_READ);
return 0;
}
if (sk->rmem_alloc >= sk->rcvbuf) {
kfree_skb(skb, FREE_READ);
} else {
+ /*
+ * Remove kiss/headers
+ */
+ skb_pull(skb,3+size_ax25_addr(&dp));
skb_queue_tail(&sk->receive_queue, skb);
skb->sk = sk;
- sk->rmem_alloc += skb->mem_len;
+ sk->rmem_alloc += skb->truesize;
if (!sk->dead)
- sk->data_ready(sk, skb->len - 2);
+ sk->data_ready(sk, skb->len);
}
} else {
kfree_skb(skb, FREE_READ);
}
/* LAPB */
+
+ /*
+ * Pull of the AX.25 headers leaving the CTRL/PID bytes
+ */
+ skb_pull(skb, 1+size_ax25_addr(&dp));
+
if ((ax25 = ax25_find_cb(&dest, &src, dev)) != NULL) {
skb->h.raw = data;
/* Process the frame. If it is queued up internally it returns one otherwise we
if (sk != NULL) {
if (!sk->dead)
- sk->data_ready(sk, skb->len - 2);
+ sk->data_ready(sk, skb->len );
} else {
kfree_skb(skb, FREE_READ);
}
skb->sk = sk;
skb->free = 1;
skb->arp = 1;
- skb->len = size;
-
- asmptr = skb->data;
+ skb_reserve(skb, 3+size_ax25_addr(dp));
+ asmptr = skb_push(skb,3+size_ax25_addr(dp));
if (sk->debug) {
printk("Building AX.25 Header (dp=%p).\n", dp);
if (dp != 0)
printk("AX.25: Appending user data\n");
/* User data follows immediately after the AX.25 data */
- memcpy_fromfs(asmptr, ubuf, len);
+ memcpy_fromfs(skb_put(skb,len), ubuf, len);
if (sk->debug)
printk("AX.25: Transmitting buffer\n");
if (sk->type == SOCK_SEQPACKET) {
int copied = 0;
struct sk_buff *skb;
int er;
+ int bias=0;
if (sk->err) {
er = -sk->err;
*addr_len = sizeof(*sax);
/* This works for seqpacket too. The receiver has ordered the queue for us! We do one quick check first though */
- if (sk->type == SOCK_SEQPACKET && sk->state != TCP_ESTABLISHED)
- return -ENOTCONN;
+ if (sk->type == SOCK_SEQPACKET)
+ {
+ if(sk->state != TCP_ESTABLISHED)
+ return -ENOTCONN;
+ bias=2;
+ }
/* Now we can treat all alike */
if ((skb = skb_recv_datagram(sk, flags, noblock, &er)) == NULL)
return er;
- copied= (size < skb->len) ? size : skb->len;
- skb_copy_datagram(skb, sk->type == SOCK_SEQPACKET ? 2 : 0, ubuf, copied);
+ copied= (size < skb->len-bias) ? size : skb->len-bias;
+ skb_copy_datagram(skb, bias, ubuf, copied);
if (sax) {
struct sockaddr_ax25 addr;
#ifdef CONFIG_INET
-int ax25_encapsulate(unsigned char *buff, struct device *dev, unsigned short type, void *daddr,
- void *saddr, unsigned len, struct sk_buff *skb)
+int ax25_encapsulate(struct sk_buff *skb, struct device *dev, unsigned short type, void *daddr,
+ void *saddr, unsigned len)
{
/* header is an AX.25 UI frame from us to them */
+ unsigned char *buff=skb_push(skb,17);
*buff++ = 0; /* KISS DATA */
if (daddr != NULL)
#ifdef CONFIG_INET
case AX25_P_IP:
ax25_ip_mode_set(&ax25->dest_addr, ax25->device, 'V');
- skb->h.raw = ((char *)(iframe)) + 2;
- skb->len -= 2;
+ skb->h.raw = skb->data;
ip_rcv(skb, skb->dev, NULL); /* Wrong ptype */
queued = 1;
break;
int queued = 0, frametype;
unsigned char *frame;
+ if (ax25->state != AX25_STATE_1 && ax25->state != AX25_STATE_2 &&
+ ax25->state != AX25_STATE_3 && ax25->state != AX25_STATE_4) {
+ printk("ax25_process_rx_frame: frame received - state = %d\n", ax25->state);
+ return queued;
+ }
+
del_timer(&ax25->timer);
frame = skb->h.raw;
case AX25_STATE_4:
queued = ax25_state4_machine(ax25, skb, frame, frametype, type);
break;
- default:
- printk("ax25_process_rx_frame: frame received - state = %d\n", ax25->state);
- break;
}
ax25_set_timer(ax25);
- return(queued);
+ return queued;
}
#endif
len += sprintf(buffer, "callsign dev count time mode\n");
for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
- len += sprintf(buffer + len, "%-9s %-3s %5d %9ld",
+ len += sprintf(buffer + len, "%-9s %-3s %5d %9d",
ax2asc(&ax25_rt->callsign),
ax25_rt->dev ? ax25_rt->dev->name : "???",
ax25_rt->n,
#include <linux/mm.h>
#include <linux/interrupt.h>
+/* #define NO_BACKOFF */
+
/*
* This routine purges the input queue of frames.
*/
{
struct sk_buff *skb;
unsigned char *dptr;
- int len;
struct device *dev;
+ int asize;
if ((dev = ax25->device) == NULL)
return; /* Route died */
- if ((skb = alloc_skb(16 + 1 + size_ax25_addr(ax25->digipeat), GFP_ATOMIC)) == NULL)
+ asize= 1+size_ax25_addr(ax25->digipeat);
+
+ if ((skb = alloc_skb(16 + asize, GFP_ATOMIC)) == NULL)
return;
-
+ skb_reserve(skb, asize);
+
if (ax25->sk != NULL) {
skb->sk = ax25->sk;
- ax25->sk->wmem_alloc += skb->mem_len;
+ ax25->sk->wmem_alloc += skb->truesize;
}
- dptr = skb->data;
-
- dptr += 1 + size_ax25_addr(ax25->digipeat); /* KISS byte & 2 calls */
-
/* Assume a response - address structure for DTE */
- len = 1; /* Normal size */
+ dptr = skb_put(skb,1);
+
if ((frametype & U) == S) /* S frames carry NR */
frametype |= (ax25->vr << 5);
*dptr = frametype;
skb->free = 1;
- skb->len = len + size_ax25_addr(ax25->digipeat) + 1;
-
+ skb_push(skb,asize);
ax25_transmit_buffer(ax25, skb, type);
}
if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)
return; /* Next SABM will get DM'd */
- skb->len = len;
+ skb_reserve(skb,len-1);
ax25_digi_invert(digi, &retdigi);
- dptr = skb->data + 1 + size_ax25_addr(digi);
+ dptr = skb_put(skb,1);
skb->sk = NULL;
- *dptr = DM;
+ *dptr = DM | PF;
if (dev == NULL)
return;
- dptr = skb->data;
+ /*
+ * Do the address ourselves.
+ */
+
+ dptr = skb_push(skb, len-1);
*dptr++ = 0;
dptr += build_ax25_addr(dptr, dest, src, &retdigi, C_RESPONSE);
*/
unsigned short ax25_calculate_t1(ax25_cb *ax25)
{
- int t, n;
-
- for (t = 2, n = 0; n < ax25->n2count; n++)
- t *= 2;
-
+#ifndef NO_BACKOFF
+ int n, t = 2;
+
+ if (ax25->backoff)
+ for (n = 0; n < ax25->n2count; n++)
+ t *= 2;
+
return t * ax25->rtt;
+#else
+ return 2 * ax25->rtt;
+#endif
}
/*
*/
void ax25_calculate_rtt(ax25_cb *ax25)
{
- if (ax25->n2count == 0)
+ if (ax25->t1timer > 0 && ax25->n2count == 0)
ax25->rtt = (9 * ax25->rtt + ax25->t1 - ax25->t1timer) / 10;
/* Don't go below one second */
struct sk_buff *skb2;
if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL)
break;
- /*
- * The protocol knows this has (for other paths) been taken off
- * and adds it back.
- */
- skb2->len-=skb->dev->hard_header_len;
+ skb2->h.raw = skb2->data + dev->hard_header_len;
ptype->func(skb2, skb->dev, ptype);
nitcount--;
}
* in effect handle the incoming data as if it were from a circular buffer
*/
- to = skb->data;
+ to = skb_put(skb,len);
left = len;
len2 = len;
* Tag the frame and kick it to the proper receive routine
*/
- skb->len = len;
skb->dev = dev;
skb->free = 1;
/*
* Bump the pointer to the next structure.
- * This assumes that the basic 'skb' pointer points to
- * the MAC header, if any (as indicated by its "length"
- * field). Take care now!
+ *
+ * On entry to the protocol layer. skb->data and
+ * skb->h.raw point to the MAC and encapsulated data
*/
- skb->h.raw = skb->data + skb->dev->hard_header_len;
- skb->len -= skb->dev->hard_header_len;
+ skb->h.raw = skb->data+skb->dev->hard_header_len;
/*
* Fetch the packet protocol ID.
(*(struct sockaddr_in *) &ifr.ifr_addr).sin_family = dev->family;
(*(struct sockaddr_in *) &ifr.ifr_addr).sin_addr.s_addr = dev->pa_addr;
- /*
- * Write this block to the caller's space.
- */
-
- memcpy_tofs(pos, &ifr, sizeof(struct ifreq));
- pos += sizeof(struct ifreq);
- len -= sizeof(struct ifreq);
-
/*
* Have we run out of space here ?
*/
if (len < sizeof(struct ifreq))
break;
+
+ /*
+ * Write this block to the caller's space.
+ */
+
+ memcpy_tofs(pos, &ifr, sizeof(struct ifreq));
+ pos += sizeof(struct ifreq);
+ len -= sizeof(struct ifreq);
}
/*
(*(struct sockaddr_in *)
&ifr.ifr_broadaddr).sin_port = 0;
goto rarok;
- memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
- ret = 0;
- break;
case SIOCSIFBRDADDR: /* Set the broadcast address */
dev->pa_brdaddr = (*(struct sockaddr_in *)
&ifr.ifr_dstaddr).sin_family = dev->family;
(*(struct sockaddr_in *)
&ifr.ifr_dstaddr).sin_port = 0;
- memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
- ret = 0;
- break;
+ goto rarok;
case SIOCSIFDSTADDR: /* Set the destination address (for point-to-point links) */
dev->pa_dstaddr = (*(struct sockaddr_in *)
ifr.ifr_map.irq=dev->irq;
ifr.ifr_map.dma=dev->dma;
ifr.ifr_map.port=dev->if_port;
- memcpy_tofs(arg,&ifr,sizeof(struct ifreq));
- ret=0;
- break;
+ goto rarok;
case SIOCSIFMAP:
if(dev->set_config==NULL)
*
* Fixes:
* Alan Cox : Fixed the worst of the load balancer bugs.
- * Dave Platt : Interrupt stacking fix
+ * Dave Platt : Interrupt stacking fix.
* Richard Kooijman : Timestamp fixes.
+ * Alan Cox : Changed buffer format.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* Resource tracking variables
*/
-volatile unsigned long net_memory = 0;
volatile unsigned long net_skbcount = 0;
volatile unsigned long net_locked = 0;
volatile unsigned long net_allocs = 0;
void show_net_buffers(void)
{
printk("Networking buffers in use : %lu\n",net_skbcount);
- printk("Memory committed to network buffers: %lu\n",net_memory);
printk("Network buffers locked by drivers : %lu\n",net_locked);
printk("Total network buffer allocations : %lu\n",net_allocs);
printk("Total failed network buffer allocs : %lu\n",net_fails);
{
printk("File: %s Line %d, found a freed skb lurking in the undergrowth!\n",
file,line);
- printk("skb=%p, real size=%ld, claimed size=%ld, free=%d\n",
- skb,skb->truesize,skb->mem_len,skb->free);
+ printk("skb=%p, real size=%d, free=%d\n",
+ skb,skb->truesize,skb->free);
return -1;
}
if(skb->magic_debug_cookie!=SK_GOOD_SKB)
{
printk("File: %s Line %d, passed a non skb!\n", file,line);
- printk("skb=%p, real size=%ld, claimed size=%ld, free=%d\n",
- skb,skb->truesize,skb->mem_len,skb->free);
+ printk("skb=%p, real size=%d, free=%d\n",
+ skb,skb->truesize,skb->free);
return -1;
}
- if(skb->mem_len!=skb->truesize)
+ if(skb->head>skb->data)
{
- printk("File: %s Line %d, Dubious size setting!\n",file,line);
- printk("skb=%p, real size=%ld, claimed size=%ld\n",
- skb,skb->truesize,skb->mem_len);
+ printk("File: %s Line %d, head > data !\n", file,line);
+ printk("skb=%p, head=%p, data=%p\n",
+ skb,skb->head,skb->data);
return -1;
}
+ if(skb->tail>skb->end)
+ {
+ printk("File: %s Line %d, tail > end!\n", file,line);
+ printk("skb=%p, tail=%p, end=%p\n",
+ skb,skb->tail,skb->end);
+ return -1;
+ }
+ if(skb->data>skb->tail)
+ {
+ printk("File: %s Line %d, data > tail!\n", file,line);
+ printk("skb=%p, data=%p, tail=%p\n",
+ skb,skb->data,skb->tail);
+ return -1;
+ }
+ if(skb->tail-skb->data!=skb->len)
+ {
+ printk("File: %s Line %d, wrong length\n", file,line);
+ printk("skb=%p, data=%p, end=%p len=%ld\n",
+ skb,skb->data,skb->end,skb->len);
+ return -1;
+ }
+ if((unsigned long) skb->end > (unsigned long) skb)
+ {
+ printk("File: %s Line %d, control overrun\n", file,line);
+ printk("skb=%p, end=%p\n",
+ skb,skb->end);
+ return -1;
+ }
+
/* Guess it might be acceptable then */
return 0;
}
restore_flags(flags);
}
+/*
+ * Add data to an sk_buff
+ */
+
+unsigned char *skb_put(struct sk_buff *skb, int len)
+{
+ unsigned char *tmp=skb->tail;
+ IS_SKB(skb);
+ skb->tail+=len;
+ skb->len+=len;
+ IS_SKB(skb);
+ if(skb->tail>skb->end)
+ panic("skput:over: %p:%d", __builtin_return_address(0),len);
+ return tmp;
+}
+
+unsigned char *skb_push(struct sk_buff *skb, int len)
+{
+ IS_SKB(skb);
+ skb->data-=len;
+ skb->len+=len;
+ IS_SKB(skb);
+ if(skb->data<skb->head)
+ panic("skpush:under: %p:%d", __builtin_return_address(0),len);
+ return skb->data;
+}
+
+int skb_pull(struct sk_buff *skb, int len)
+{
+ IS_SKB(skb);
+ if(len>skb->len)
+ len=skb->len;
+ skb->data+=len;
+ skb->len-=len;
+ return len;
+}
+
+int skb_headroom(struct sk_buff *skb)
+{
+ IS_SKB(skb);
+ return skb->data-skb->head;
+}
+
+int skb_tailroom(struct sk_buff *skb)
+{
+ IS_SKB(skb);
+ return skb->end-skb->tail;
+}
+
+void skb_reserve(struct sk_buff *skb, int len)
+{
+ IS_SKB(skb);
+ skb->data+=len;
+ skb->tail+=len;
+ if(skb->tail>skb->end)
+ panic("sk_res: over");
+ if(skb->data<skb->head)
+ panic("sk_res: under");
+ IS_SKB(skb);
+}
+
+void skb_trim(struct sk_buff *skb, int len)
+{
+ IS_SKB(skb);
+ if(skb->len>len)
+ {
+ skb->len=len;
+ skb->tail=skb->data+len;
+ }
+}
+
+
+
#endif
/*
if(skb->sk->prot!=NULL)
{
if (rw)
- skb->sk->prot->rfree(skb->sk, skb, skb->mem_len);
+ skb->sk->prot->rfree(skb->sk, skb);
else
- skb->sk->prot->wfree(skb->sk, skb, skb->mem_len);
+ skb->sk->prot->wfree(skb->sk, skb);
}
else
save_flags(flags);
cli();
if (rw)
- skb->sk->rmem_alloc-=skb->mem_len;
+ skb->sk->rmem_alloc-=skb->truesize;
else
- skb->sk->wmem_alloc-=skb->mem_len;
+ skb->sk->wmem_alloc-=skb->truesize;
restore_flags(flags);
if(!skb->sk->dead)
skb->sk->write_space(skb->sk);
- kfree_skbmem(skb,skb->mem_len);
+ kfree_skbmem(skb);
}
}
else
- kfree_skbmem(skb, skb->mem_len);
+ kfree_skbmem(skb);
}
/*
{
struct sk_buff *skb;
unsigned long flags;
+ int len=size;
+ unsigned char *bptr;
- if (intr_count && priority!=GFP_ATOMIC) {
+ if (intr_count && priority!=GFP_ATOMIC)
+ {
static int count = 0;
if (++count < 5) {
printk("alloc_skb called nonatomically from interrupt %p\n",
}
}
- size+=sizeof(struct sk_buff);
- skb=(struct sk_buff *)kmalloc(size,priority);
- if (skb == NULL)
+ size=(size+15)&~15; /* Allow for alignments. Make a multiple of 16 bytes */
+ size+=sizeof(struct sk_buff); /* And stick the control itself on the end */
+
+ /*
+ * Allocate some space
+ */
+
+ bptr=(unsigned char *)kmalloc(size,priority);
+ if (bptr == NULL)
{
net_fails++;
return NULL;
if(skb->magic_debug_cookie == SK_GOOD_SKB)
printk("Kernel kmalloc handed us an existing skb (%p)\n",skb);
#endif
-
+ /*
+ * Now we play a little game with the caches. Linux kmalloc is
+ * a bit cache dumb, in fact its just about maximally non
+ * optimal for typical kernel buffers. We actually run faster
+ * by doing the following. Which is to deliberately put the
+ * skb at the _end_ not the start of the memory block.
+ */
net_allocs++;
+
+ skb=(struct sk_buff *)(bptr+size)-1;
skb->free = 2; /* Invalid so we pick up forgetful users */
skb->lock = 0;
skb->pkt_type = PACKET_HOST; /* Default type */
- skb->truesize = size;
- skb->mem_len = size;
- skb->mem_addr = skb;
-#ifdef CONFIG_SLAVE_BALANCING
- skb->in_dev_queue = 0;
-#endif
- skb->fraglist = NULL;
skb->prev = skb->next = NULL;
skb->link3 = NULL;
skb->sk = NULL;
+ skb->truesize=size;
skb->localroute=0;
skb->stamp.tv_sec=0; /* No idea about time */
skb->localroute = 0;
save_flags(flags);
cli();
- net_memory += size;
net_skbcount++;
restore_flags(flags);
#if CONFIG_SKB_CHECK
skb->magic_debug_cookie = SK_GOOD_SKB;
#endif
skb->users = 0;
+ /* Load the data pointers */
+ skb->head=bptr;
+ skb->data=bptr;
+ skb->tail=bptr;
+ skb->end=bptr+len;
+ skb->len=0;
return skb;
}
* Free an skbuff by memory
*/
-void kfree_skbmem(struct sk_buff *skb,unsigned size)
+void kfree_skbmem(struct sk_buff *skb)
{
unsigned long flags;
-#ifdef CONFIG_SLAVE_BALANCING
- save_flags(flags);
- cli();
- if(skb->in_dev_queue && skb->dev!=NULL)
- skb->dev->pkt_queue--;
- restore_flags(flags);
-#endif
-#ifdef CONFIG_SKB_CHECK
- IS_SKB(skb);
- if(size!=skb->truesize)
- printk("kfree_skbmem: size mismatch.\n");
-
- if(skb->magic_debug_cookie == SK_GOOD_SKB)
- {
- save_flags(flags);
- cli();
- IS_SKB(skb);
- skb->magic_debug_cookie = SK_FREED_SKB;
- kfree_s((void *)skb,size);
- net_skbcount--;
- net_memory -= size;
- restore_flags(flags);
- }
- else
- printk("kfree_skbmem: bad magic cookie\n");
-#else
save_flags(flags);
cli();
- kfree_s((void *)skb,size);
+ kfree((void *)skb->head);
net_skbcount--;
- net_memory -= size;
restore_flags(flags);
-#endif
}
/*
struct sk_buff *n;
unsigned long offset;
- n=alloc_skb(skb->mem_len-sizeof(struct sk_buff),priority);
+ /*
+ * Allocate the copy buffer
+ */
+
+ IS_SKB(skb);
+
+ n=alloc_skb(skb->truesize-sizeof(struct sk_buff),priority);
if(n==NULL)
return NULL;
- offset=((char *)n)-((char *)skb);
-
- memcpy(n->data,skb->data,skb->mem_len-sizeof(struct sk_buff));
- n->len=skb->len;
+ /*
+ * Shift between the two data areas in bytes
+ */
+
+ offset=n->head-skb->head;
+
+ /* Set the data pointer */
+ skb_reserve(n,skb->data-skb->head);
+ /* Set the tail pointer and length */
+ skb_put(n,skb->len);
+ /* Copy the bytes */
+ memcpy(n->head,skb->head,skb->end-skb->head);
n->link3=NULL;
n->sk=NULL;
n->when=skb->when;
n->dev=skb->dev;
n->h.raw=skb->h.raw+offset;
n->ip_hdr=(struct iphdr *)(((char *)skb->ip_hdr)+offset);
- n->fraglen=skb->fraglen;
- n->fraglist=skb->fraglist;
n->saddr=skb->saddr;
n->daddr=skb->daddr;
n->raddr=skb->raddr;
n->users=0;
n->pkt_type=skb->pkt_type;
n->stamp=skb->stamp;
+
+ IS_SKB(n);
return n;
}
restore_flags(flags);
}
+struct sk_buff *dev_alloc_skb(unsigned int length)
+{
+ struct sk_buff *skb=alloc_skb(length+16, GFP_ATOMIC);
+ skb_reserve(skb,16);
+ return skb;
+}
+
int skb_device_locked(struct sk_buff *skb)
{
return skb->lock? 1 : 0;
unsigned long flags;
save_flags(flags);
cli();
- sk->wmem_alloc+= c->mem_len;
+ sk->wmem_alloc+= c->truesize;
restore_flags(flags); /* was sti(); */
}
return c;
unsigned long flags;
save_flags(flags);
cli();
- sk->rmem_alloc += c->mem_len;
+ sk->rmem_alloc += c->truesize;
restore_flags(flags); /* was sti(); */
}
return(c);
}
-void sock_wfree(struct sock *sk, struct sk_buff *skb, unsigned long size)
+void sock_wfree(struct sock *sk, struct sk_buff *skb)
{
+ int s=skb->truesize;
#ifdef CONFIG_SKB_CHECK
IS_SKB(skb);
#endif
- kfree_skbmem(skb, size);
+ kfree_skbmem(skb);
if (sk)
{
unsigned long flags;
save_flags(flags);
cli();
- sk->wmem_alloc -= size;
+ sk->wmem_alloc -= s;
restore_flags(flags);
/* In case it might be waiting for more memory. */
sk->write_space(sk);
}
-void sock_rfree(struct sock *sk, struct sk_buff *skb, unsigned long size)
+void sock_rfree(struct sock *sk, struct sk_buff *skb)
{
+ int s=skb->truesize;
#ifdef CONFIG_SKB_CHECK
IS_SKB(skb);
#endif
- kfree_skbmem(skb, size);
+ kfree_skbmem(skb);
if (sk)
{
unsigned long flags;
save_flags(flags);
cli();
- sk->rmem_alloc -= size;
+ sk->rmem_alloc -= s;
restore_flags(flags);
}
}
* daddr=NULL means leave destination address (eg unresolved arp)
*/
-int eth_header(unsigned char *buff, struct device *dev, unsigned short type,
- void *daddr, void *saddr, unsigned len,
- struct sk_buff *skb)
+int eth_header(struct sk_buff *skb, struct device *dev, unsigned short type,
+ void *daddr, void *saddr, unsigned len)
{
- struct ethhdr *eth = (struct ethhdr *)buff;
+ struct ethhdr *eth = (struct ethhdr *)skb_push(skb,14);
/*
* Set the protocol type. For a packet of type ETH_P_802_3 we put the length
unsigned long len = skb->len;
unsigned long hard_len = dev->hard_header_len;
- dev->hard_header(skb->data, dev, ETH_P_IPX,
- dest_node, NULL, len - hard_len, skb);
+ dev->hard_header(skb, dev, ETH_P_IPX,
+ dest_node, NULL, len - hard_len);
skb->h.raw = skb->data + hard_len;
}
* Alan Cox : Allow large numbers of pending sockets
* (eg for big web sites), but only if
* specifically application requested.
+ * Alan Cox : New buffering throughout IP. Used dumbly.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
int i;
- printk("Swansea University Computer Society TCP/IP for NET3.029 (Snapshot #6)\n");
+ printk("Swansea University Computer Society TCP/IP for NET3.030 (Snapshot #1)\n");
/*
* Tell SOCKET that we are alive...
printk("ARP: no memory to send an arp packet\n");
return;
}
- skb->len = sizeof(struct arphdr) + dev->hard_header_len + 2*(dev->addr_len+4);
+ skb_reserve(skb, dev->hard_header_len);
+ arp = (struct arphdr *) skb_put(skb,sizeof(struct arphdr) + 2*(dev->addr_len+4));
skb->arp = 1;
skb->dev = dev;
skb->free = 1;
* Fill the device header for the ARP frame
*/
- dev->hard_header(skb->data,dev,ptype,dest_hw?dest_hw:dev->broadcast,src_hw?src_hw:NULL,skb->len,skb);
+ dev->hard_header(skb,dev,ptype,dest_hw?dest_hw:dev->broadcast,src_hw?src_hw:NULL,skb->len);
/* Fill out the arp protocol part. */
- arp = (struct arphdr *) (skb->data + dev->hard_header_len);
arp->ar_hrd = htons(dev->type);
#ifdef CONFIG_AX25
#ifdef CONFIG_NETROM
unsigned char ha[MAX_ADDR_LEN]; /* So we can enable ints again. */
long sip,tip;
unsigned char *sha,*tha;
-
+
+/*
+ * ARP carries the MAC addresses wrapped in the packet. We can't sanity
+ * check this as proxy arp has them different.
+ */
+ skb_pull(skb,dev->hard_header_len);
/*
* The hardware length of the packet should match the hardware length
* of the device. Similarly, the hardware types should match. The
* Find the original IP header.
*/
- iph = (struct iphdr *) (skb_in->data + dev->hard_header_len);
+ iph = (struct iphdr *) skb_in->data;
/*
* No replies to MAC multicast
* Re-adjust length according to actual IP header size.
*/
- skb->len = offset + sizeof(struct icmphdr) + sizeof(struct iphdr) + 8;
+ skb_put(skb,sizeof(struct icmphdr) + sizeof(struct iphdr) + 8);
/*
* Fill in the frame
static void icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb,
struct device *dev, unsigned long source)
{
+#ifndef CONFIG_IP_FORWARD
struct rtable *rt;
+#endif
struct iphdr *iph;
unsigned long ip;
*/
#ifdef not_a_good_idea
ip_rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY),
- ip, 0, icmph->un.gateway, dev,0, 0);
+ ip, 0, icmph->un.gateway, dev,0, 0, 0);
break;
#endif
case ICMP_REDIR_HOST:
break;
printk("ICMP redirect from %s\n", in_ntoa(source));
ip_rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_HOST | RTF_GATEWAY),
- ip, 0, icmph->un.gateway, dev,0, 0, 0);
+ ip, 0, icmph->un.gateway, dev,0, 0, 0, 0);
break;
case ICMP_REDIR_NETTOS:
case ICMP_REDIR_HOSTTOS:
* Re-adjust length according to actual IP header size.
*/
- skb2->len = offset + len;
+ skb_put(skb2,len);
/*
* Build ICMP_ECHO Response message.
unsigned long *timeptr, midtime;
struct device *ndev=NULL;
- if (len != 20)
+ if (len < 12)
{
printk(
"ICMP: Size (%d) of ICMP_TIMESTAMP request should be 20!\n",
len);
icmp_statistics.IcmpInErrors++;
/* correct answers are possible for everything >= 12 */
- if (len < 12)
- return;
}
size = dev->hard_header_len + 84;
/*
* Re-adjust length according to actual IP header size.
*/
- skb2->len = offset + 20;
+ skb_put(skb2,20);
/*
* Build ICMP_TIMESTAMP Response message.
* Re-adjust length according to actual IP header size.
*/
- skb2->len = offset + len;
+ skb_put(skb2,len);
/*
* Build ICMP ADDRESS MASK Response message.
if(skb==NULL)
return;
tmp=ip_build_header(skb, INADDR_ANY, address, &dev, IPPROTO_IGMP, NULL,
- skb->mem_len, 0, 1);
+ skb->truesize, 0, 1);
if(tmp<0)
{
kfree_skb(skb, FREE_WRITE);
return;
}
dp=skb->data+tmp;
- skb->len=tmp+sizeof(struct igmphdr);
+ skb_put(skb,sizeof(struct igmphdr));
*dp++=type;
*dp++=0;
* Build a hardware header. Source address is our mac, destination unknown
* (rebuild header will sort this out)
*/
- mac = dev->hard_header(skb->data, dev, ETH_P_IP, NULL, NULL, len, skb);
+ skb_reserve(skb,dev->hard_header_len);
+ mac = dev->hard_header(skb, dev, ETH_P_IP, NULL, NULL, len);
if (mac < 0)
{
mac = -mac;
struct device **dev, int type, struct options *opt, int len, int tos, int ttl)
{
struct rtable *rt;
- unsigned char *buff;
unsigned long raddr;
int tmp;
unsigned long src;
struct iphdr *iph;
- buff = skb->data;
-
/*
* See if we need to look up the device.
*/
*/
tmp = ip_send(skb, raddr, len, *dev, saddr);
- buff += tmp;
- len -= tmp;
/*
* Book keeping
* Build the IP addresses
*/
- iph=(struct iphdr *)buff;
+ iph=(struct iphdr *)skb_put(skb,sizeof(struct iphdr));
iph->version = 4;
iph->tos = tos;
fp = xp;
}
- /* Release the MAC header. */
- kfree_s(qp->mac, qp->maclen);
-
/* Release the IP header. */
kfree_s(qp->iph, 64 + 8);
static struct ipq *ip_create(struct sk_buff *skb, struct iphdr *iph, struct device *dev)
{
struct ipq *qp;
- int maclen;
int ihlen;
qp = (struct ipq *) kmalloc(sizeof(struct ipq), GFP_ATOMIC);
}
memset(qp, 0, sizeof(struct ipq));
- /*
- * Allocate memory for the MAC header.
- *
- * FIXME: We have a maximum MAC address size limit and define
- * elsewhere. We should use it here and avoid the 3 kmalloc() calls
- */
-
- maclen = ((unsigned long) iph) - ((unsigned long) skb->data);
- qp->mac = (unsigned char *) kmalloc(maclen, GFP_ATOMIC);
- if (qp->mac == NULL)
- {
- NETDEBUG(printk("IP: create: no memory left !\n"));
- kfree_s(qp, sizeof(struct ipq));
- return(NULL);
- }
-
/*
* Allocate memory for the IP header (plus 8 octets for ICMP).
*/
if (qp->iph == NULL)
{
NETDEBUG(printk("IP: create: no memory left !\n"));
- kfree_s(qp->mac, maclen);
kfree_s(qp, sizeof(struct ipq));
return(NULL);
}
- /* Fill in the structure. */
- memcpy(qp->mac, skb->data, maclen);
memcpy(qp->iph, iph, ihlen + 8);
qp->len = 0;
qp->ihlen = ihlen;
- qp->maclen = maclen;
qp->fragments = NULL;
qp->dev = dev;
*
* FIXME: We copy here because we lack an effective way of handling lists
* of bits on input. Until the new skb data handling is in I'm not going
- * to touch this with a bargepole. This also causes a 4Kish limit on
- * packet sizes.
+ * to touch this with a bargepole.
*/
static struct sk_buff *ip_glue(struct ipq *qp)
/*
* Allocate a new buffer for the datagram.
*/
+ len = qp->ihlen + qp->len;
- len = qp->maclen + qp->ihlen + qp->len;
-
- if ((skb = alloc_skb(len,GFP_ATOMIC)) == NULL)
+ if ((skb = dev_alloc_skb(len)) == NULL)
{
ip_statistics.IpReasmFails++;
NETDEBUG(printk("IP: queue_glue: no memory for gluing queue %p\n", qp));
}
/* Fill in the basic details. */
- skb->len = (len - qp->maclen);
+ skb_put(skb,len);
skb->h.raw = skb->data;
skb->free = 1;
- /* Copy the original MAC and IP headers into the new buffer. */
+ /* Copy the original IP headers into the new buffer. */
ptr = (unsigned char *) skb->h.raw;
- memcpy(ptr, ((unsigned char *) qp->mac), qp->maclen);
- ptr += qp->maclen;
memcpy(ptr, ((unsigned char *) qp->iph), qp->ihlen);
ptr += qp->ihlen;
- skb->h.raw += qp->maclen;
count = 0;
* Point into the IP datagram 'data' part.
*/
- ptr = skb->data + dev->hard_header_len + ihl;
+ ptr = skb->data + ihl;
/*
* Is this the final fragment?
* **Protocol Violation**
* We copy all the options to each fragment. !FIXME!
*/
+
void ip_fragment(struct sock *sk, struct sk_buff *skb, struct device *dev, int is_frag)
{
struct iphdr *iph;
if(skb->free==0)
printk("IP fragmenter: BUG free!=1 in fragmenter\n");
skb2->free = 1;
- skb2->len = len + hlen;
+ skb_put(skb2,len + hlen);
skb2->h.raw=(char *) skb2->data;
/*
* Charge the memory for the fragment to any owner
if (sk)
{
cli();
- sk->wmem_alloc += skb2->mem_len;
+ sk->wmem_alloc += skb2->truesize;
skb2->sk=sk;
}
restore_flags(flags);
*/
skb2 = alloc_skb(dev2->hard_header_len + skb->len, GFP_ATOMIC);
+
/*
* This is rare and since IP is tolerant of network failures
* quite harmless.
*/
+
if (skb2 == NULL)
{
NETDEBUG(printk("\nIP: No memory available for IP forward\n"));
return;
}
- ptr = skb2->data;
+
+
+ /* Now build the MAC header. */
+ (void) ip_send(skb2, raddr, skb->len, dev2, dev2->pa_addr);
+
+ ptr = skb_put(skb2,skb->len);
skb2->free = 1;
- skb2->len = skb->len + dev2->hard_header_len;
skb2->h.raw = ptr;
/*
* Copy the packet data into the new buffer.
*/
- memcpy(ptr + dev2->hard_header_len, skb->h.raw, skb->len);
+ memcpy(ptr, skb->h.raw, skb->len);
- /* Now build the MAC header. */
- (void) ip_send(skb2, raddr, skb->len, dev2, dev2->pa_addr);
ip_statistics.IpForwDatagrams++;
/*
* This function receives all incoming IP datagrams.
+ *
+ * On entry skb->data points to the start of the IP header and
+ * the MAC header has been removed.
*/
int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
int err;
#endif
+ /*
+ * IP is layered, throw away the
+ * MAC addresses.
+ */
+
+ skb_pull(skb,dev->hard_header_len);
+
ip_statistics.IpInReceives++;
/*
* is IP we can trim to the true length of the frame.
*/
- skb->len=ntohs(iph->tot_len);
+ skb_trim(skb,ntohs(iph->tot_len));
/*
* See if the firewall wants to dispose of the packet.
extern struct device loopback_dev;
struct device *dev=&loopback_dev;
int len=skb->len-old_dev->hard_header_len;
- struct sk_buff *newskb=alloc_skb(len+dev->hard_header_len, GFP_ATOMIC);
+ struct sk_buff *newskb=dev_alloc_skb(len+dev->hard_header_len);
if(newskb==NULL)
return;
newskb->lock=0;
newskb->users=0;
newskb->pkt_type=skb->pkt_type;
- newskb->len=len+dev->hard_header_len;
-
- newskb->ip_hdr=(struct iphdr *)(newskb->data+ip_send(newskb, skb->ip_hdr->daddr, len, dev, skb->ip_hdr->saddr));
+ /*
+ * Put a MAC header on the packet
+ */
+ ip_send(newskb, skb->ip_hdr->daddr, len, dev, skb->ip_hdr->saddr);
+ /*
+ * Add the rest of the data space.
+ */
+ newskb->ip_hdr=(struct iphdr *)skb_put(skb, len);
+ /*
+ * Copy the data
+ */
memcpy(newskb->ip_hdr,skb->ip_hdr,len);
/* Recurse. The device check against IFF_LOOPBACK will stop infinite recursion */
skb->arp = 0;
skb->saddr = saddr;
skb->raddr = (rt&&rt->rt_gateway) ? rt->rt_gateway : daddr;
- skb->len = fraglen;
+ skb_reserve(skb,dev->hard_header_len);
+ data = skb_put(skb, fraglen-dev->hard_header_len);
/*
* Save us ARP and stuff. In the optimal case we do no route lookup (route cache ok)
}
else if (dev->hard_header)
{
- if(dev->hard_header(skb->data, dev, ETH_P_IP,
- NULL, NULL, 0, NULL)>0)
+ if(dev->hard_header(skb, dev, ETH_P_IP,
+ NULL, NULL, 0)>0)
skb->arp=1;
}
* Find where to start putting bytes.
*/
- data = (char *)skb->data + dev->hard_header_len;
iph = (struct iphdr *)data;
/*
if (!ftp->init_seq)
ftp->init_seq = th->seq;
- skb2 = alloc_skb(skb->mem_len-sizeof(struct sk_buff)+ftp->delta, GFP_ATOMIC);
+ skb2 = alloc_skb(skb->len+ftp->delta, GFP_ATOMIC);
if (skb2 == NULL) {
printk("MASQUERADE: No memory available\n");
return skb;
}
skb2->free = skb->free;
- skb2->len = skb->len + ftp->delta;
+ skb_put(skb2,skb->len + ftp->delta);
skb2->h.raw = &skb2->data[skb->h.raw - skb->data];
/*
memcpy(skb2->data, skb->data, (p - (char *)skb->data));
memcpy(&skb2->data[(p - (char *)skb->data)], buf, strlen(buf));
memcpy(&skb2->data[(p - (char *)skb->data) + strlen(buf)], data,
- skb->mem_len - sizeof(struct sk_buff) - ((char *)skb->h.raw - data));
+ skb->len - ((char *)skb->h.raw - data));
/*
* Problem, how to replace the new skb with old one,
uh->check=csum_tcpudp_magic(saddr,daddr,len,
IPPROTO_UDP, csum_partial((char *)uh,len,0));
if(uh->check==0)
- uh->check=-0xFFFF;
+ uh->check=0xFFFF;
}
void ip_fw_masquerade(struct sk_buff **skb_ptr, struct device *dev)
sk = (struct sock *) pt->data;
/*
- * The SOCK_PACKET socket receives _all_ frames, and as such
- * therefore needs to put the header back onto the buffer.
- * (it was removed by inet_bh()).
+ * The SOCK_PACKET socket receives _all_ frames.
*/
skb->dev = dev;
- skb->len += dev->hard_header_len;
/*
* Charge the memory to the socket. This is done specifically
sk->rmem_alloc = 0;
}
- if (sk->rmem_alloc + skb->mem_len >= sk->rcvbuf)
+ if (sk->rmem_alloc + skb->truesize >= sk->rcvbuf)
{
-/* printk("packet_rcv: drop, %d+%d>%d\n", sk->rmem_alloc, skb->mem_len, sk->rcvbuf); */
+/* printk("packet_rcv: drop, %d+%d>%d\n", sk->rmem_alloc, skb->truesize, sk->rcvbuf); */
skb->sk = NULL;
kfree_skb(skb, FREE_READ);
return(0);
cli();
skb->sk = sk;
- sk->rmem_alloc += skb->mem_len;
+ sk->rmem_alloc += skb->truesize;
/*
* Queue the packet up, and wake anyone waiting for it.
skb->sk = sk;
skb->free = 1;
- memcpy_fromfs(skb->data, from, len);
- skb->len = len;
+ memcpy_fromfs(skb_put(skb,len), from, len);
skb->arp = 1; /* No ARP needs doing on this (complete) frame */
/*
struct sk_buff *skb;
struct sockaddr *saddr;
int err;
- int truesize;
saddr = (struct sockaddr *)sin;
* user program they can ask the device for its MTU anyway.
*/
- truesize = skb->len;
- copied = min(len, truesize);
+ copied = min(len, skb->len);
memcpy_tofs(to, skb->data, copied); /* We can't use skb_copy_datagram here */
sk->stamp=skb->stamp;
*/
release_sock(sk);
- return(truesize);
+ return(copied);
}
struct rarp_table *entry;
long sip,tip;
unsigned char *sha,*tha; /* s for "source", t for "target" */
+
+ skb_pull(skb,dev->hard_header_len);
/*
* If this test doesn't pass, it's not IP, or we should ignore it anyway
{
/* Now we need to copy this into memory. */
skb->sk = sk;
- skb->len = ntohs(skb->ip_hdr->tot_len);
+ skb_trim(skb,ntohs(skb->ip_hdr->tot_len));
skb->h.raw = (unsigned char *) skb->ip_hdr;
skb->dev = dev;
skb->saddr = daddr;
* Alan Cox : Removed compatibility cruft.
* Alan Cox : RTF_REJECT support.
* Alan Cox : TCP irtt support.
+ * Jonathan Naylor : Added Metric support.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
*/
void ip_rt_add(short flags, unsigned long dst, unsigned long mask,
- unsigned long gw, struct device *dev, unsigned short mtu, unsigned long window, unsigned short irtt)
+ unsigned long gw, struct device *dev, unsigned short mtu, unsigned long window, unsigned short irtt, unsigned char metric)
{
struct rtable *r, *rt;
struct rtable **rp;
rt->rt_gateway = gw;
rt->rt_mask = mask;
rt->rt_mss = dev->mtu - HEADER_SIZE;
+ rt->rt_metric = metric;
rt->rt_window = 0; /* Default is no clamping */
/* Are the MSS/Window valid ? */
while ((r = *rp) != NULL)
{
if (r->rt_dst != dst ||
- r->rt_mask != mask)
+ r->rt_mask != mask ||
+ r->rt_metric < metric)
{
rp = &r->rt_next;
continue;
* Add the route
*/
- ip_rt_add(flags, daddr, mask, gw, dev, r->rt_mss, r->rt_window, r->rt_irtt);
+ ip_rt_add(flags, daddr, mask, gw, dev, r->rt_mss, r->rt_window, r->rt_irtt, r->rt_metric);
return 0;
}
* Alan Cox : Cache last socket.
* Alan Cox : Per route irtt.
* Matt Day : Select() match BSD precisely on error
+ * Alan Cox : New buffers
+ * Mark Tamsky : Various sk->prot->retransmits and
+ * sk->retransmits misupdating fixed.
+ * Fixed tcp_write_timeout: stuck close,
+ * and TCP syn retries gets used now.
*
*
* To Fix:
ct++;
sk->prot->retransmits ++;
+ tcp_statistics.TcpRetransSegs++;
+
/*
* Only one retransmit requested.
*/
sk->retransmits++;
+ sk->prot->retransmits++;
sk->backoff++;
sk->rto = min(sk->rto << 1, 120*HZ);
reset_xmit_timer(sk, TIME_WRITE, sk->rto);
arp_destroy (sk->daddr, 0);
/*ip_route_check (sk->daddr);*/
}
+
+ /*
+ * Have we tried to SYN too many times (repent repent 8))
+ */
+
+ if(sk->retransmits > TCP_SYN_RETRIES && sk->state==TCP_SYN_SENT)
+ {
+ sk->err=ETIMEDOUT;
+ sk->error_report(sk);
+ del_timer(&sk->retransmit_timer);
+ tcp_statistics.TcpAttemptFails++; /* Is this right ??? - FIXME - */
+ tcp_set_state(sk,TCP_CLOSE);
+ /* Don't FIN, we got nothing back */
+ release_sock(sk);
+ return 0;
+ }
/*
* Has it gone just too far ?
*/
* Clean up time.
*/
tcp_set_state(sk, TCP_CLOSE);
+ release_sock(sk);
return 0;
}
}
if (sk->prot->write_wakeup)
sk->prot->write_wakeup (sk);
sk->retransmits++;
+ sk->prot->retransmits++;
tcp_write_timeout(sk);
break;
default:
* Assemble a suitable TCP frame
*/
- buff->len = sizeof(struct tcphdr);
buff->sk = sk;
buff->localroute = sk->localroute;
- t1 =(struct tcphdr *) buff->data;
/*
* Put in the IP header and routing stuff.
if (tmp < 0)
{
buff->free = 1;
- sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
+ sk->prot->wfree(sk, buff);
return;
}
- buff->len += tmp;
- t1 =(struct tcphdr *)((char *)t1 +tmp);
+ t1 =(struct tcphdr *)skb_put(buff,sizeof(struct tcphdr));
memcpy(t1, th, sizeof(*t1));
int tmp;
struct sk_buff *skb;
struct sk_buff *send_tmp;
- unsigned char *buff;
struct proto *prot;
struct device *dev = NULL;
copy = 0;
}
- memcpy_fromfs(skb->data + skb->len, from, copy);
- skb->len += copy;
+ memcpy_fromfs(skb_put(skb,copy), from, copy);
from += copy;
copied += copy;
len -= copy;
continue;
}
- skb->len = 0;
skb->sk = sk;
skb->free = 0;
skb->localroute = sk->localroute|(flags&MSG_DONTROUTE);
- buff = skb->data;
-
/*
* FIXME: we need to optimize this.
* Perhaps some hints here would be good.
*/
tmp = prot->build_header(skb, sk->saddr, sk->daddr, &dev,
- IPPROTO_TCP, sk->opt, skb->mem_len,sk->ip_tos,sk->ip_ttl);
+ IPPROTO_TCP, sk->opt, skb->truesize,sk->ip_tos,sk->ip_ttl);
if (tmp < 0 )
{
- prot->wfree(sk, skb->mem_addr, skb->mem_len);
+ prot->wfree(sk, skb);
release_sock(sk);
if (copied)
return(copied);
return(tmp);
}
- skb->len += tmp;
skb->dev = dev;
- buff += tmp;
- skb->h.th =(struct tcphdr *) buff;
- tmp = tcp_build_header((struct tcphdr *)buff, sk, len-copy);
+ skb->h.th =(struct tcphdr *)skb_put(skb,sizeof(struct tcphdr));
+ tmp = tcp_build_header(skb->h.th, sk, len-copy);
if (tmp < 0)
{
- prot->wfree(sk, skb->mem_addr, skb->mem_len);
+ prot->wfree(sk, skb);
release_sock(sk);
if (copied)
return(copied);
if (flags & MSG_OOB)
{
- ((struct tcphdr *)buff)->urg = 1;
- ((struct tcphdr *)buff)->urg_ptr = ntohs(copy);
+ skb->h.th->urg = 1;
+ skb->h.th->urg_ptr = ntohs(copy);
}
- skb->len += tmp;
- memcpy_fromfs(buff+tmp, from, copy);
+ memcpy_fromfs(skb_put(skb,copy), from, copy);
+
from += copy;
copied += copy;
len -= copy;
- skb->len += copy;
skb->free = 0;
sk->write_seq += copy;
return;
}
- buff->len = sizeof(struct tcphdr);
buff->sk = sk;
buff->localroute = sk->localroute;
if (tmp < 0)
{
buff->free = 1;
- sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
+ sk->prot->wfree(sk, buff);
return;
}
- buff->len += tmp;
- t1 =(struct tcphdr *)(buff->data +tmp);
+ t1 =(struct tcphdr *)skb_put(buff,sizeof(struct tcphdr));
memcpy(t1,(void *) &sk->dummy_th, sizeof(*t1));
t1->seq = htonl(sk->sent_seq);
*/
buff->sk = sk;
- buff->len = sizeof(*t1);
buff->localroute = sk->localroute;
- t1 =(struct tcphdr *) buff->data;
/*
* Put in the IP header and routing stuff.
*/
buff->free = 1;
- prot->wfree(sk,buff->mem_addr, buff->mem_len);
+ prot->wfree(sk,buff);
sk->write_seq++;
t=del_timer(&sk->timer);
if(t)
* if so simply add the fin to that buffer, not send it ahead.
*/
- t1 =(struct tcphdr *)((char *)t1 +tmp);
- buff->len += tmp;
+ t1 =(struct tcphdr *)skb_put(buff,sizeof(struct tcphdr));
buff->dev = dev;
memcpy(t1, th, sizeof(*t1));
t1->seq = ntohl(sk->write_seq);
if (buff == NULL)
return;
- buff->len = sizeof(*t1);
buff->sk = NULL;
buff->dev = dev;
buff->localroute = 0;
- t1 =(struct tcphdr *) buff->data;
-
/*
* Put in the IP header and routing stuff.
*/
if (tmp < 0)
{
buff->free = 1;
- prot->wfree(NULL, buff->mem_addr, buff->mem_len);
+ prot->wfree(NULL, buff);
return;
}
- t1 =(struct tcphdr *)((char *)t1 +tmp);
- buff->len += tmp;
+ t1 =(struct tcphdr *)skb_put(buff,sizeof(struct tcphdr));
memcpy(t1, th, sizeof(*t1));
/*
return;
}
- buff->len = sizeof(struct tcphdr)+4;
buff->sk = newsk;
buff->localroute = newsk->localroute;
- t1 =(struct tcphdr *) buff->data;
-
/*
* Put in the IP header and routing stuff.
*/
return;
}
- buff->len += tmp;
- t1 =(struct tcphdr *)((char *)t1 +tmp);
+ t1 =(struct tcphdr *)skb_put(buff,sizeof(struct tcphdr));
memcpy(t1, skb->h.th, sizeof(*t1));
buff->h.seq = newsk->write_seq;
t1->syn = 1;
t1->ack_seq = ntohl(skb->h.th->seq+1);
t1->doff = sizeof(*t1)/4+1;
- ptr =(unsigned char *)(t1+1);
+ ptr = skb_put(buff,4);
ptr[0] = 2;
ptr[1] = 4;
ptr[2] = ((newsk->mtu) >> 8) & 0xff;
* Charge the sock_buff to newsk.
*/
- sk->rmem_alloc -= skb->mem_len;
- newsk->rmem_alloc += skb->mem_len;
+ sk->rmem_alloc -= skb->truesize;
+ newsk->rmem_alloc += skb->truesize;
skb_queue_tail(&sk->receive_queue,skb);
sk->ack_backlog++;
u32 new_seq, shut_seq;
th = skb->h.th;
- skb->len = len -(th->doff*4);
+ skb_pull(skb,th->doff*4);
+ skb_trim(skb,len-(th->doff*4));
/*
* The bytes in the receive read/assembly queue has increased. Needed for the
return(-ENOMEM);
}
sk->inuse = 1;
- buff->len = 24;
buff->sk = sk;
buff->free = 0;
buff->localroute = sk->localroute;
- t1 = (struct tcphdr *) buff->data;
/*
* Put in the IP header and routing stuff.
IPPROTO_TCP, NULL, MAX_SYN_SIZE,sk->ip_tos,sk->ip_ttl);
if (tmp < 0)
{
- sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
+ sk->prot->wfree(sk, buff);
release_sock(sk);
return(-ENETUNREACH);
}
- buff->len += tmp;
- t1 = (struct tcphdr *)((char *)t1 +tmp);
+ t1 = (struct tcphdr *) skb_put(buff,sizeof(struct tcphdr));
memcpy(t1,(void *)&(sk->dummy_th), sizeof(*t1));
t1->seq = ntohl(sk->write_seq++);
* Put in the TCP options to say MTU.
*/
- ptr = (unsigned char *)(t1+1);
+ ptr = skb_put(buff,4);
ptr[0] = 2;
ptr[1] = 4;
ptr[2] = (sk->mtu) >> 8;
sk->retransmit_timer.function=&retransmit_timer;
sk->retransmit_timer.data = (unsigned long)sk;
reset_xmit_timer(sk, TIME_WRITE, sk->rto); /* Timer for repeating the SYN until an answer */
- sk->retransmits = TCP_SYN_RETRIES;
+ sk->retransmits = 0; /* Now works the right way instead of a hacked initial setting */
sk->prot->queue_xmit(sk, dev, buff, 0);
reset_xmit_timer(sk, TIME_WRITE, sk->rto);
/*
* A TCP packet has arrived.
+ * skb->h.raw is the TCP header.
*/
int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
if (!redo)
{
+ /*
+ * Pull up the IP header.
+ */
+ skb_pull(skb, skb->h.raw-skb->data);
if (tcp_check(th, len, saddr, daddr ))
{
skb->sk = NULL;
return(0);
}
- skb->len = len;
+/* skb->len = len;*/
skb->acked = 0;
skb->used = 0;
skb->free = 0;
* Charge the memory to the socket.
*/
- if (sk->rmem_alloc + skb->mem_len >= sk->rcvbuf)
+ if (sk->rmem_alloc + skb->truesize >= sk->rcvbuf)
{
kfree_skb(skb, FREE_READ);
release_sock(sk);
}
skb->sk=sk;
- sk->rmem_alloc += skb->mem_len;
+ sk->rmem_alloc += skb->truesize;
/*
* This basically follows the flow suggested by RFC793, with the corrections in RFC1122. We
if(sk->debug)
printk("Doing a BSD time wait\n");
tcp_statistics.TcpEstabResets++;
- sk->rmem_alloc -= skb->mem_len;
+ sk->rmem_alloc -= skb->truesize;
skb->sk = NULL;
sk->err=ECONNRESET;
tcp_set_state(sk, TCP_CLOSE);
{
sk->inuse=1;
skb->sk = sk;
- sk->rmem_alloc += skb->mem_len;
+ sk->rmem_alloc += skb->truesize;
tcp_conn_request(sk, skb, daddr, saddr,opt, dev,seq+128000);
release_sock(sk);
return 0;
{
return;
}
-
- if (before(sk->sent_seq, sk->window_seq) &&
+ if ( before(sk->sent_seq, sk->window_seq) &&
(skb=skb_peek(&sk->write_queue)))
{
/*
unsigned long win_size, ow_size;
void * tcp_data_start;
+ /*
+ * How many bytes can we send ?
+ */
+
win_size = sk->window_seq - sk->sent_seq;
+ /*
+ * Recover the buffer pointers
+ */
+
iph = (struct iphdr *)(skb->data + skb->dev->hard_header_len);
th = (struct tcphdr *)(((char *)iph) +(iph->ihl << 2));
+ /*
+ * Grab the data for a temporary frame
+ */
+
buff = sk->prot->wmalloc(sk, win_size + th->doff * 4 +
(iph->ihl << 2) +
skb->dev->hard_header_len,
if ( buff == NULL )
return;
- buff->len = 0;
-
/*
* If we strip the packet on the write queue we must
* be ready to retransmit this one
*/
- buff->free = 0;
+ buff->free = /*0*/1;
buff->sk = sk;
buff->localroute = sk->localroute;
+
+ /*
+ * Put headers on the new packet
+ */
tmp = sk->prot->build_header(buff, sk->saddr, sk->daddr, &dev,
- IPPROTO_TCP, sk->opt, buff->mem_len,
+ IPPROTO_TCP, sk->opt, buff->truesize,
sk->ip_tos,sk->ip_ttl);
if (tmp < 0)
{
- sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
+ sk->prot->wfree(sk, buff);
return;
}
+
+ /*
+ * Move the TCP header over
+ */
- buff->len += tmp;
buff->dev = dev;
- nth = (struct tcphdr *) (buff->data + buff->len);
- buff->len += th->doff * 4;
+ nth = (struct tcphdr *) skb_put(buff,th->doff*4);
memcpy(nth, th, th->doff * 4);
-
+
+ /*
+ * Correct the new header
+ */
+
nth->ack = 1;
nth->ack_seq = ntohl(sk->acked_seq);
nth->window = ntohs(tcp_select_window(sk));
nth->check = 0;
+ /*
+ * Find the first data byte.
+ */
+
tcp_data_start = skb->data + skb->dev->hard_header_len +
(iph->ihl << 2) + th->doff * 4;
- memcpy(buff->data + buff->len, tcp_data_start, win_size);
- buff->len += win_size;
+ /*
+ * Add it to our new buffer
+ */
+ memcpy(skb_put(buff,win_size), tcp_data_start, win_size);
+
+ /*
+ * Remember our right edge sequence number.
+ */
+
buff->h.seq = sk->sent_seq + win_size;
+ sk->sent_seq = buff->h.seq; /* Hack */
+#if 0
/*
* now: shrink the queue head segment
((unsigned long) (tcp_data_start - (void *) skb->data));
memmove(tcp_data_start, tcp_data_start + win_size, ow_size);
- skb->len -= win_size;
+ skb_trim(skb,skb->len-win_size);
sk->sent_seq += win_size;
th->seq = htonl(sk->sent_seq);
-
if (th->urg)
{
unsigned short urg_ptr;
nth->urg_ptr = htons(win_size);
}
}
+#else
+ if(th->urg && ntohs(th->urg_ptr) < win_size)
+ nth->urg = 0;
+#endif
+ /*
+ * Checksum the split buffer
+ */
+
tcp_send_check(nth, sk->saddr, sk->daddr,
nth->doff * 4 + win_size , sk);
}
else
- {
+ {
buff = sk->prot->wmalloc(sk,MAX_ACK_SIZE,1, GFP_ATOMIC);
if (buff == NULL)
return;
- buff->len = sizeof(struct tcphdr);
buff->free = 1;
buff->sk = sk;
buff->localroute = sk->localroute;
- t1 = (struct tcphdr *) buff->data;
-
/*
* Put in the IP header and routing stuff.
*/
IPPROTO_TCP, sk->opt, MAX_ACK_SIZE,sk->ip_tos,sk->ip_ttl);
if (tmp < 0)
{
- sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
+ sk->prot->wfree(sk, buff);
return;
}
- buff->len += tmp;
- t1 = (struct tcphdr *)((char *)t1 +tmp);
-
+ t1 = (struct tcphdr *)skb_put(buff,sizeof(struct tcphdr));
memcpy(t1,(void *) &sk->dummy_th, sizeof(*t1));
/*
if(skb==NULL)
return er;
- truesize = skb->len;
+ truesize = skb->len - sizeof(struct udphdr);
copied = min(len, truesize);
/*
skb_free_datagram(skb);
release_sock(sk);
- return(truesize);
+ return(copied);
}
/*
{
skb->sk = sk;
skb->dev = dev;
- skb->len = len;
+ skb_trim(skb,len);
/*
* These are supposed to be switched.
* Charge it to the socket, dropping if the queue is full.
*/
- skb->len = len - sizeof(*uh);
-
if (sock_queue_rcv_skb(sk,skb)<0)
{
udp_statistics.UdpInErrors++;
* Asynchronous I/O support.
* Changed to use notifiers and the newer packet_type stuff.
* Assorted major fixes <Alejandro Liu>
- * Revision 0.30: Moved to net/ipx/...
+ * Revision 0.30: Moved to net/ipx/... <Alan Cox>
* Don't set address length on recvfrom that errors.
* Incorrect verify_area.
+ * Revision 0.31: New sk_buffs. This still needs a lot of testing. <Alan Cox>
*
* TODO: use sock_alloc_send_skb to allocate sending buffers. Check with Caldera first
*
ipx_packet *ipx = (ipx_packet *)(skb->h.raw);
ipx_socket *sock1 = NULL, *sock2 = NULL;
struct sk_buff *skb1 = NULL, *skb2 = NULL;
- int ipx_offset;
sock1 = ipxitf_find_socket(intrfc, ipx->ipx_dest.sock);
return 0;
}
- ipx_offset = (char *)(skb->h.raw) - (char *)(skb->data);
-
/* This next segment of code is a little awkward, but it sets it up
* so that the appropriate number of copies of the SKB are made and
* that skb1 and skb2 point to it (them) so that it (they) can be
if (copy) {
skb1 = skb_clone(skb, GFP_ATOMIC);
if (skb1 != NULL) {
- skb1->h.raw = (unsigned char *)&(skb1->data[ipx_offset]);
skb1->arp = skb1->free = 1;
}
} else {
if (sock1 && sock2) {
skb2 = skb_clone(skb1, GFP_ATOMIC);
if (skb2 != NULL) {
- skb2->h.raw = (unsigned char *)&(skb2->data[ipx_offset]);
skb2->arp = skb2->free = 1;
}
} else {
struct sk_buff *skb2;
int in_offset = skb->h.raw - skb->data;
int out_offset = intrfc->if_ipx_offset;
+#if 0
char *oldraw;
+#endif
int len;
/* Hopefully, most cases */
- if (in_offset == out_offset) {
- skb->len += out_offset;
+ if (in_offset >= out_offset) {
+/* skb_push(skb,out_offset);*/
skb->arp = skb->free = 1;
return skb;
}
+#if 0
/* Existing SKB will work, just need to move things around a little */
if (in_offset > out_offset) {
oldraw = skb->h.raw;
skb->arp = skb->free = 1;
return skb;
}
+#endif
/* Need new SKB */
len = skb->len + out_offset;
skb2 = alloc_skb(len, GFP_ATOMIC);
if (skb2 != NULL) {
- skb2->h.raw = &(skb2->data[out_offset]);
- skb2->len = len;
+ skb_reserve(skb2,out_offset);
+ skb2->h.raw=skb_put(skb2,skb->len);
skb2->free=1;
skb2->arp=1;
memcpy(skb2->h.raw, skb->h.raw, skb->len);
/* This is an outbound packet from this host. We need to
* increment the write count.
*/
- skb->sk->wmem_alloc += skb->mem_len;
+ skb->sk->wmem_alloc += skb->truesize;
}
/* Send it out */
if(skb==NULL) return -ENOMEM;
skb->sk=sk;
- skb->len=size;
+ skb_reserve(skb,ipx_offset);
skb->free=1;
skb->arp=1;
/* Fill in IPX header */
- ipx=(ipx_packet *)&(skb->data[ipx_offset]);
+ ipx=(ipx_packet *)skb_put(skb,sizeof(ipx_packet));
ipx->ipx_checksum=0xFFFF;
ipx->ipx_pktsize=htons(len+sizeof(ipx_packet));
ipx->ipx_tctrl=0;
memcpy(ipx->ipx_dest.node,usipx->sipx_node,IPX_NODE_LEN);
ipx->ipx_dest.sock=usipx->sipx_port;
- memcpy_fromfs((char *)(ipx+1),ubuf,len);
+ memcpy_fromfs(skb_put(skb,len),ubuf,len);
return ipxitf_send(intrfc, skb, (rt && rt->ir_routed) ?
rt->ir_router_node : ipx->ipx_dest.node);
}
ipx_interface *intrfc;
ipx_packet *ipx;
+
+ /*
+ * Throw away the MAC layer
+ */
+
+ skb_pull(skb,dev->hard_header_len);
+
ipx=(ipx_packet *)skb->h.raw;
if(ipx->ipx_checksum!=IPX_NO_CHECKSUM) {
register_netdevice_notifier(&ipx_dev_notifier);
- printk("Swansea University Computer Society IPX 0.30 for NET3.029\n");
+ printk("Swansea University Computer Society IPX 0.31 for NET3.030\n");
printk("IPX Portions Copyright (c) 1995 Caldera, Inc.\n");
}
#endif
* NET/ROM 002 Darryl(G7LED) Fixes and address enhancement.
* Jonathan(G4KLX) Complete bind re-think.
* Alan(GW4PTS) Trivial tweaks into new format.
+ * NET/ROM 003 Jonathan(G4KLX) Added G8BPQ extensions.
*
* To do:
* Fix non-blocking connect failure.
- * Make it use normal SIOCADDRT/DELRT not funny node ioctl() calls.
*/
#include <linux/config.h>
case NETROM_T1:
if (opt < 1)
return -EINVAL;
- sk->nr->t1 = opt * PR_SLOWHZ;
+ sk->nr->rtt = (opt * PR_SLOWHZ) / 2;
return 0;
case NETROM_T2:
nr->my_index = 0;
nr->my_id = 0;
+ nr->bpqext = 1;
nr->state = NR_STATE_0;
memset(&nr->source_addr, '\0', sizeof(ax25_address));
nr->t2 = osk->nr->t2;
nr->n2 = osk->nr->n2;
+ nr->bpqext = osk->nr->bpqext;
+
nr->t1timer = 0;
nr->t2timer = 0;
nr->t4timer = 0;
struct sock *make;
ax25_address *src, *dest, *user;
unsigned short circuit_index, circuit_id;
- unsigned short frametype, window;
+ unsigned short frametype, window, timeout;
skb->sk = NULL; /* Initially we don't know who its for */
- src = (ax25_address *)(skb->data + 17);
- dest = (ax25_address *)(skb->data + 24);
+ /*
+ * skb->data points to the netrom frame start
+ */
+
+ src = (ax25_address *)(skb->data);
+ dest = (ax25_address *)(skb->data + 7);
- circuit_index = skb->data[32];
- circuit_id = skb->data[33];
- frametype = skb->data[36];
+ circuit_index = skb->data[15];
+ circuit_id = skb->data[16];
+ frametype = skb->data[19];
#ifdef CONFIG_INET
/*
* Check for an incoming IP over NET/ROM frame.
*/
if ((frametype & 0x0F) == NR_PROTOEXT && circuit_index == NR_PROTO_IP && circuit_id == NR_PROTO_IP) {
- skb->h.raw = skb->data + 37;
+ skb->h.raw = skb->data + 20;
return nr_rx_ip(skb, dev);
}
* a Connect Request base it on their circuit ID.
*/
if (((frametype & 0x0F) != NR_CONNREQ && (sk = nr_find_socket(circuit_index, circuit_id, SOCK_SEQPACKET)) != NULL) ||
- ((frametype & 0x0F) == NR_CONNREQ && (sk = nr_find_peer(circuit_index, circuit_id, SOCK_SEQPACKET)) != NULL)) {
- skb->h.raw = skb->data + 37;
- skb->len -= 20;
-
+ ((frametype & 0x0F) == NR_CONNREQ && (sk = nr_find_peer(circuit_index, circuit_id, SOCK_SEQPACKET)) != NULL))
+ {
+ if((frametype & 0x0F) == NR_CONNACK && skb->len == 39) /* ??? size check --FIXME-- */
+ sk->nr->bpqext = 1;
+ else
+ sk->nr->bpqext = 0;
return nr_process_rx_frame(sk, skb);
}
return 0;
}
- user = (ax25_address *)(skb->data + 38);
- window = skb->data[37];
+ user = (ax25_address *)(skb->data + 11);
+ window = skb->data[20];
skb->sk = make;
make->state = TCP_ESTABLISHED;
if (window < make->window)
make->window = window;
+ /* L4 timeout negotiation */
+ if (skb->len == 37) {
+ timeout = skb->data[53] * 256 + skb->data[52];
+ if (timeout * PR_SLOWHZ < make->nr->rtt * 2)
+ make->nr->rtt = (timeout * PR_SLOWHZ) / 2;
+ make->nr->bpqext = 1;
+ } else {
+ make->nr->bpqext = 0;
+ }
+
nr_write_internal(make, NR_CONNACK);
make->nr->condition = 0x00;
skb->sk = sk;
skb->free = 1;
skb->arp = 1;
- skb->len = size;
+ skb_reserve(skb,37);
- asmptr = skb->data + 16;
+ /*
+ * Push down the NetROM header
+ */
+
+ asmptr = skb_push(skb,20);
if (sk->debug)
printk("Building NET/ROM Header.\n");
if (sk->debug)
printk("Built header.\n");
- skb->h.raw = asmptr;
+ /*
+ * Put the data on the end.
+ */
+
+ skb->h.raw = skb_put(skb,len);
+ asmptr=skb->h.raw;
if (sk->debug)
printk("NET/ROM: Appending user data\n");
if ((skb = skb_recv_datagram(sk, flags, noblock, &er)) == NULL)
return er;
- copied = (size < skb->len) ? size : skb->len;
+ /* Allow for the 20 byte netrom header */
+ copied = (size < skb->len-20) ? size : skb->len-20;
- skb_copy_datagram(skb, 0, ubuf, copied);
+ skb_copy_datagram(skb, 20, ubuf, copied);
if (sax != NULL) {
struct sockaddr_ax25 addr;
addr.sax25_family = AF_NETROM;
- memcpy(&addr.sax25_call, skb->data + 24, sizeof(ax25_address));
+ memcpy(&addr.sax25_call, skb->data + 7, sizeof(ax25_address));
memcpy(sax, &addr, sizeof(*sax));
struct sk_buff *skb;
/* These two are safe on a single CPU system as only user tasks fiddle here */
if ((skb = skb_peek(&sk->receive_queue)) != NULL)
- amount = skb->len;
+ amount = skb->len-20;
if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(unsigned long))) != 0)
return err;
put_fs_long(amount, (unsigned long *)arg);
case SIOCSIFMETRIC:
return -EINVAL;
- case SIOCNRADDNODE:
- case SIOCNRDELNODE:
- case SIOCNRADDNEIGH:
- case SIOCNRDELNEIGH:
+ case SIOCADDRT:
+ case SIOCDELRT:
case SIOCNRDECOBS:
if (!suser()) return -EPERM;
return nr_rt_ioctl(cmd, (void *)arg);
{
sock_register(nr_proto_ops.family, &nr_proto_ops);
register_netdevice_notifier(&nr_dev_notifier);
- printk("G4KLX NET/ROM for Linux. Version 0.2 ALPHA for AX.25 029 for Linux 1.3.0\n");
+ printk("G4KLX NET/ROM for Linux. Version 0.3 ALPHA for AX25 029 Linux 1.3.0\n");
nr_default.quality = NR_DEFAULT_QUAL;
nr_default.obs_count = NR_DEFAULT_OBS;
/*
- * NET/ROM release 002
+ * NET/ROM release 003
*
* This is ALPHA test software. This code may break your machine, randomly fail to work with new
* releases, misbehave and/or generally screw up. It might even work.
* packet so that the transmit routine can identify it, and throw it away.
*/
-static int nr_header(unsigned char *buff, struct device *dev, unsigned short type,
- void *daddr, void *saddr, unsigned len, struct sk_buff *skb)
+static int nr_header(struct sk_buff *skb, struct device *dev, unsigned short type,
+ void *daddr, void *saddr, unsigned len)
{
+ unsigned char *buff=skb_push(skb,37);
if (type == ETH_P_ARP) {
*buff++ = 0xFF; /* Mark it */
*buff++ = 0xFE;
/*
- * NET/ROM release 002
+ * NET/ROM release 003
*
* This is ALPHA test software. This code may break your machine, randomly fail to work with new
* releases, misbehave and/or generally screw up. It might even work.
unsigned short nr, ns;
int queued = 0;
- nr = skb->data[35];
- ns = skb->data[34];
+ nr = skb->data[18];
+ ns = skb->data[17];
switch (frametype) {
do {
save_vr = sk->nr->vr;
while ((skbn = skb_dequeue(&sk->nr->reseq_queue)) != NULL) {
- ns = skbn->data[34];
+ ns = skbn->data[17];
if (ns == sk->nr->vr) {
if (sock_queue_rcv_skb(sk, skbn) == 0) {
sk->nr->vr = (sk->nr->vr + 1) % NR_MODULUS;
{
int queued = 0, frametype;
+ if (sk->nr->state != NR_STATE_1 && sk->nr->state != NR_STATE_2 &&
+ sk->nr->state != NR_STATE_3) {
+ printk("nr_process_rx_frame: frame received - state: %d\n", sk->nr->state);
+ return queued;
+ }
+
del_timer(&sk->timer);
- frametype = skb->data[36];
+ frametype = skb->data[19];
switch (sk->nr->state)
{
case NR_STATE_3:
queued = nr_state3_machine(sk, skb, frametype);
break;
- default:
- printk("nr_process_rx_frame: frame received - state: %d\n", sk->nr->state);
- break;
}
nr_set_timer(sk);
- return(queued);
+ return queued;
}
#endif
/*
- * NET/ROM release 002
+ * NET/ROM release 003
*
* This is ALPHA test software. This code may break your machine, randomly fail to work with new
* releases, misbehave and/or generally screw up. It might even work.
if (skb == NULL)
return;
- dptr = skb->data + 34;
+ dptr = skb->data + 17;
*dptr++ = sk->nr->vs;
*dptr++ = sk->nr->vr;
{
unsigned char *dptr;
- dptr = skb->data + 16;
+ /*
+ * Add the protocol byte
+ */
+
+ dptr = skb_push(skb,1);
*dptr++ = AX25_P_NETROM;
/*
- * NET/ROM release 002
+ * NET/ROM release 003
*
* This is ALPHA test software. This code may break your machine, randomly fail to work with new
* releases, misbehave and/or generally screw up. It might even work.
*
* History
* NET/ROM 001 Jonathan(G4KLX) First attempt.
+ * NET/ROM 003 Jonathan(G4KLX) Use SIOCADDRT/SIOCDELRT ioctl values
+ * for NET/ROM routes.
*
* TO DO
* Sort out the which pointer when shuffling entries in the routes
*/
int nr_rt_ioctl(unsigned int cmd, void *arg)
{
- struct nr_node_struct nr_node;
- struct nr_neigh_struct nr_neigh;
+ struct nr_route_struct nr_route;
struct device *dev;
int err;
switch (cmd) {
- case SIOCNRADDNODE:
- if ((err = verify_area(VERIFY_READ, arg, sizeof(struct nr_node_struct))) != 0)
+ case SIOCADDRT:
+ if ((err = verify_area(VERIFY_READ, arg, sizeof(struct nr_route_struct))) != 0)
return err;
- memcpy_fromfs(&nr_node, arg, sizeof(struct nr_node_struct));
- if ((dev = nr_ax25_dev_get(nr_node.device)) == NULL)
+ memcpy_fromfs(&nr_route, arg, sizeof(struct nr_route_struct));
+ if ((dev = nr_ax25_dev_get(nr_route.device)) == NULL)
return -EINVAL;
- return nr_add_node(&nr_node.callsign, nr_node.mnemonic,
- &nr_node.neighbour, dev, nr_node.quality, nr_node.obs_count);
-
- case SIOCNRDELNODE:
- if ((err = verify_area(VERIFY_READ, arg, sizeof(struct nr_node_struct))) != 0)
- return err;
- memcpy_fromfs(&nr_node, arg, sizeof(struct nr_node_struct));
- if ((dev = nr_ax25_dev_get(nr_node.device)) == NULL)
- return -EINVAL;
- return nr_del_node(&nr_node.callsign, &nr_node.neighbour, dev);
-
- case SIOCNRADDNEIGH:
- if ((err = verify_area(VERIFY_READ, arg, sizeof(struct nr_neigh_struct))) != 0)
- return err;
- memcpy_fromfs(&nr_neigh, arg, sizeof(struct nr_neigh_struct));
- if ((dev = nr_ax25_dev_get(nr_neigh.device)) == NULL)
- return -EINVAL;
- return nr_add_neigh(&nr_neigh.callsign, dev, nr_neigh.quality);
+ switch (nr_route.type) {
+ case NETROM_NODE:
+ return nr_add_node(&nr_route.callsign,
+ nr_route.mnemonic,
+ &nr_route.neighbour,
+ dev, nr_route.quality,
+ nr_route.obs_count);
+ case NETROM_NEIGH:
+ return nr_add_neigh(&nr_route.callsign,
+ dev, nr_route.quality);
+ default:
+ return -EINVAL;
+ }
- case SIOCNRDELNEIGH:
- if ((err = verify_area(VERIFY_READ, arg, sizeof(struct nr_neigh_struct))) != 0)
+ case SIOCDELRT:
+ if ((err = verify_area(VERIFY_READ, arg, sizeof(struct nr_route_struct))) != 0)
return err;
- memcpy_fromfs(&nr_neigh, arg, sizeof(struct nr_neigh_struct));
- if ((dev = nr_ax25_dev_get(nr_neigh.device)) == NULL)
+ memcpy_fromfs(&nr_route, arg, sizeof(struct nr_route_struct));
+ if ((dev = nr_ax25_dev_get(nr_route.device)) == NULL)
return -EINVAL;
- return nr_del_neigh(&nr_neigh.callsign, dev, nr_neigh.quality);
+ switch (nr_route.type) {
+ case NETROM_NODE:
+ return nr_del_node(&nr_route.callsign,
+ &nr_route.neighbour, dev);
+ case NETROM_NEIGH:
+ return nr_del_neigh(&nr_route.callsign,
+ dev, nr_route.quality);
+ default:
+ return -EINVAL;
+ }
case SIOCNRDECOBS:
return nr_dec_obs();
if ((dev = nr_dev_first()) == NULL)
return 0;
- if (device != NULL)
- skb->len += dev->hard_header_len;
+/* if (device != NULL)
+ skb->len += dev->hard_header_len;*/
+ skb_push(skb,17);
ax25_send_frame(skb, (ax25_address *)dev->dev_addr, &nr_neigh->callsign, nr_neigh->dev);
return 1;
/*
- * NET/ROM release 002
+ * NET/ROM release 003
*
* This is ALPHA test software. This code may break your machine, randomly fail to work with new
* releases, misbehave and/or generally screw up. It might even work.
*
* History
* NET/ROM 001 Jonathan(G4KLX) Cloned from ax25_subr.c
+ * NET/ROM 003 Jonathan(G4KLX) Added G8BPQ NET/ROM extensions.
*/
#include <linux/config.h>
{
struct sk_buff *skb;
unsigned char *dptr;
- int len;
+ int len, timeout;
switch (frametype & 0x0F) {
- case NR_CONNREQ: len = 52; break;
- case NR_CONNACK: len = 38; break;
+ case NR_CONNREQ: len = 54; break;
+ case NR_CONNACK: len = (sk->nr->bpqext) ? 39 : 38; break;
case NR_DISCREQ: len = 37; break;
case NR_DISCACK: len = 37; break;
case NR_INFOACK: len = 37; break;
if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)
return;
- dptr = skb->data + 32;
+ /*
+ * Space for AX.25
+ */
+ skb_reserve(skb,17);
+
+ dptr = skb_put(skb,len-17);
switch (frametype & 0x0F) {
case NR_CONNREQ:
+ timeout = (sk->nr->rtt / PR_SLOWHZ) * 2;
*dptr++ = sk->nr->my_index;
*dptr++ = sk->nr->my_id;
*dptr++ = 0;
dptr[6] &= ~LAPB_C;
dptr[6] &= ~LAPB_E;
dptr[6] |= SSID_SPARE;
+ dptr += 7;
+ *dptr++ = timeout % 256;
+ *dptr++ = timeout / 256;
break;
case NR_CONNACK:
*dptr++ = sk->nr->my_id;
*dptr++ = frametype;
*dptr++ = sk->window;
+ if (sk->nr->bpqext) *dptr++ = nr_default.ttl;
break;
case NR_DISCREQ:
}
skb->free = 1;
- skb->len = len;
nr_transmit_buffer(sk, skb);
}
if ((skbn = alloc_skb(38, GFP_ATOMIC)) == NULL)
return;
- dptr = skbn->data + 16;
+ skb_reserve(skbn,17);
+ dptr = skb_put(skbn,21);
*dptr++ = AX25_P_NETROM;
*dptr++ = 0;
skbn->free = 1;
- skbn->len = 38;
skbn->sk = NULL;
if (!nr_route_frame(skbn, NULL))
*/
void nr_calculate_rtt(struct sock *sk)
{
- if (sk->nr->n2count == 0)
+ if (sk->nr->t1timer > 0 && sk->nr->n2count == 0)
sk->nr->rtt = (9 * sk->nr->rtt + sk->nr->t1 - sk->nr->t1timer) / 10;
/* Don't go below one second */
/*
- * NET/ROM release 002
+ * NET/ROM release 003
*
* This is ALPHA test software. This code may break your machine, randomly fail to work with new
* releases, misbehave and/or generally screw up. It might even work.
{
int i;
- printk("Swansea University Computer Society NET3.029 Snap #6 for Linux 1.3.0\n");
+ printk("Swansea University Computer Society NET3.030 Snap #1 for Linux 1.3.4\n");
/*
* Initialize all address (protocol) families.