diff -uNr old/usb-eth.c new/usb-eth.c
--- old/usb-eth.c	Tue Mar 13 01:59:55 2001
+++ new/usb-eth.c	Thu Mar 15 03:46:46 2001
@@ -1,4 +1,4 @@
-/*
+ /*
  * Ethernet driver for the SA1100 USB client function
  * Copyright (c) 2001 by Nicolas Pitre
  *
@@ -12,7 +12,16 @@
  * This is still work in progress...
  * 
  * 19/02/2001 - Now we are compatible with generic usbnet driver. green@iXcelerator.com
- * 
+ * 09/03/2001 - Dropped 'framing' scheme, as it seems to cause a lot of problems with little benefit.
+ *		Now, since we do not know what size of packet we are receiving
+ *		last usb packet in sequence will always be less than max packet
+ *		receive endpoint can accept.
+ *		Now the only way to check correct start of frame is to compare
+ *		MAC address. Also now we are stalling on each receive error.
+ *
+ * 15/03/2001 - Using buffer to get data from UDC. DMA needs to have 8 byte
+ *		aligned buffer, but this breaks IP code (unaligned access).
+ *
  */
 
 #include <linux/module.h>
@@ -25,49 +34,21 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
-#include <asm/unaligned.h>
+#include <linux/random.h>
 
 #include "sa1100_usb.h"
-#include "usb_ctl.h"
 
 
 #define ETHERNET_VENDOR_ID 0x49f
 #define ETHERNET_PRODUCT_ID 0x505A
+#define MAX_PACKET 32768
 
 // Should be global, so that insmod can change these
 int usb_rsize=64;
 int usb_wsize=64;
 
-/* FIXME - this should go into common include, once usbnet.c goes into 
-   standart kernel */
-// packets are always ethernet inside
-// ... except they can be bigger (up to 64K with this framing)
-#define MIN_PACKET      sizeof(struct ethhdr)
-#define MAX_PACKET      32768
-
-struct nc_header {		// packed:
-	u16	hdr_len;		// sizeof nc_header (LE, all)
-	u16	packet_len;		// payload size (including ethhdr)
-	u16	packet_id;		// detects dropped packets
-#define MIN_HEADER	6
-} __attribute__((__packed__));
-
-#define PAD_BYTE	((unsigned char)0xAC)
-struct nc_trailer {
-	u16	packet_id;
-} __attribute__((__packed__));
-
-#define FRAMED_SIZE(mtu) (sizeof (struct nc_header) \
-				+ sizeof (struct ethhdr) \
-				+ (mtu) \
-				+ 1 \
-				+ sizeof (struct nc_trailer))
-
-#define MIN_FRAMED	FRAMED_SIZE(0)
-
 static struct usbe_info_t {
   struct net_device *dev;
-  char host_addr[ETH_ALEN];
   u16 packet_id;
   struct net_device_stats stats;
 } usbe_info;
@@ -77,14 +58,16 @@
 static struct sk_buff *cur_tx_skb, *next_tx_skb;
 static struct sk_buff *cur_rx_skb, *next_rx_skb;
 static volatile int terminating;
+static char *dmabuf; // we need that, as dma expect it's buffers to be aligned on 8 bytes boundary
 
 static int usb_change_mtu (struct net_device *net, int new_mtu)
 {
 	if (new_mtu <= sizeof (struct ethhdr) || new_mtu > MAX_PACKET)
 		return -EINVAL;
-	if (FRAMED_SIZE (new_mtu) > MAX_PACKET)
-		return -EINVAL;
 	// no second zero-length packet read wanted after mtu-sized packets
+	if (((new_mtu + sizeof (struct ethhdr)) % usb_rsize) == 0)
+		return -EDOM;
+
 	net->mtu = new_mtu;
 	return 0;
 }
@@ -92,58 +75,55 @@
 static struct sk_buff * 
 usb_new_recv_skb(void)
 {
-	struct sk_buff *skb = dev_alloc_skb((12 + FRAMED_SIZE (usb_eth_device.mtu)));
+	struct sk_buff *skb = alloc_skb( 2 + sizeof (struct ethhdr) + usb_eth_device.mtu,GFP_ATOMIC);
+
 	if (skb) {
-		skb_reserve(skb, 12);
+		skb_reserve(skb, 2);
 	}
 	return skb;
 }
 
+static u8 bcast_hwaddr[ETH_ALEN]={0xff,0xff,0xff,0xff,0xff,0xff};
 static void 
 usb_recv_callback(int flag, int size)
 {
 	struct sk_buff *skb;
-	int pktlen, templen;
-	struct nc_header	*header = NULL;
-	struct nc_trailer	*trailer = NULL;
 	
 	if (terminating) 
 		return;
 	
 	skb = cur_rx_skb;
-	pktlen = 0;
 
 	/* flag validation */
 	if (flag == 0) {
+		if ( skb_tailroom (skb) < size ) { // hey! we are overloaded!!!
+			usbe_info.stats.rx_over_errors++;
+			sa1100_usb_recv_stall();
+			goto error;
+		}
+		memcpy(skb->tail,dmabuf,size);
 		skb_put(skb, size);
-		if (skb->len > MIN_FRAMED) {
-			header = (struct nc_header *) skb->data;
-			le16_to_cpus (&header->hdr_len);
-			le16_to_cpus (&header->packet_len);
-			if (header->hdr_len == MIN_HEADER ) {
-				pktlen = header->packet_len;
-			}
-			if (pktlen < MIN_FRAMED || pktlen > FRAMED_SIZE(usb_eth_device.mtu)) {
-				pktlen = 0;
+		if ( skb->len >= sizeof(struct ethhdr)) {
+			if (memcmp(skb->data,usb_eth_device.dev_addr,ETH_ALEN) && memcmp(skb->data,bcast_hwaddr,ETH_ALEN) ) {
 				usbe_info.stats.rx_frame_errors++;
+				sa1100_usb_recv_stall();
+				goto error;
 			}
 		}
-	} else if (flag == -EIO) {
-		usbe_info.stats.rx_errors++;
+	} else { 
+		if (flag == -EIO) {
+			usbe_info.stats.rx_errors++;
+			sa1100_usb_recv_stall();
+		}
+		goto error;
 	}
 
-	templen = pktlen + header->hdr_len + sizeof (struct nc_trailer);
-	templen += (templen & 0x01) ? 0:1;
 	/* validate packet length */
-	if (skb->len < templen ) {
+	if (size == usb_rsize ) {
 		/* packet not complete yet */
 		skb = NULL;
 	}
 	
-	if (pktlen == 0) {
-		goto error;
-	}
-	
 	/* 
 	 * At this point skb is non null if we have a complete packet.
 	 * If so take a fresh skb right away and restart USB receive without
@@ -153,7 +133,7 @@
 
 	if (skb)
 		cur_rx_skb = next_rx_skb;
-	sa1100_usb_recv(cur_rx_skb->tail, skb_tailroom(cur_rx_skb), 
+	sa1100_usb_recv(dmabuf, skb_tailroom(cur_rx_skb), 
 			usb_recv_callback);
 	if (!skb)
 		return;
@@ -171,32 +151,6 @@
 		return;
 	}
 
-	if (FRAMED_SIZE (header->packet_len) > MAX_PACKET) {
-		usbe_info.stats.rx_frame_errors++;
-		goto error;
-	}
-	skb_pull (skb, header->hdr_len);
-	trailer = (struct nc_trailer *)
-		(skb->data + skb->len - sizeof (struct nc_trailer));
-	skb_trim (skb, skb->len - sizeof (struct nc_trailer));
-
-	if ((header->packet_len & 0x01) == 0) {
-		if (skb->data [header->packet_len] != PAD_BYTE) {
-			usbe_info.stats.rx_frame_errors++;
-			goto error;
-		}
-		skb_trim (skb, skb->len - 1);
-	}
-	if (skb->len != header->packet_len) {
-		usbe_info.stats.rx_frame_errors++;
-		goto error;
-	}
-
-	if (header->packet_id != get_unaligned (&trailer->packet_id)) {
-		usbe_info.stats.rx_fifo_errors++;
-		goto error;
-	}
-
 	if (skb->len) {
 		int     status;
 // FIXME: eth_copy_and_csum "small" packets to new SKB (small < ~200 bytes) ?
@@ -205,20 +159,19 @@
 		skb->protocol = eth_type_trans (skb, &usb_eth_device);
 		usbe_info.stats.rx_packets++;
 		usbe_info.stats.rx_bytes += skb->len;
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
+		skb->ip_summed = CHECKSUM_NONE;
 		status = netif_rx (skb);
+		if (status != NET_RX_SUCCESS)
+			printk("netif_rx failed with code %d\n",status);
 	} else {
 error:
-		usbe_info.stats.rx_errors++;
 		/* 
-		 * Error due to bad frame, bad pktlen, etc.
+		 * Error due to HW addr mismatch, or IO error.
 		 * Recycle the current skb and reset USB reception.
 		 */
 		skb_trim(cur_rx_skb, 0);
-		if (flag != -EINTR)
-			sa1100_usb_recv_reset();
-		sa1100_usb_recv(cur_rx_skb->tail, skb_tailroom(cur_rx_skb),
-			usb_recv_callback);
+//		if ( flag == -EINTR || flag == -EAGAIN ) // only if we are coming out of stall
+			sa1100_usb_recv(dmabuf, skb_tailroom(cur_rx_skb), usb_recv_callback);
 	}
 }
 
@@ -265,48 +218,12 @@
 	netif_wake_queue(dev);
 }
 
-
-static inline struct sk_buff *fixup_skb (struct sk_buff *skb, int flags)
-{
-	int			padlen;
-	struct sk_buff		*skb2;
-
-	padlen = ((skb->len + sizeof (struct nc_header)
-			+ sizeof (struct nc_trailer)) & 0x01) ? 0 : 1;
-	if (!skb_cloned (skb)) {
-		int	headroom = skb_headroom (skb);
-		int	tailroom = skb_tailroom (skb);
-
-		if ((padlen + sizeof (struct nc_trailer)) <= tailroom
-			    && sizeof (struct nc_header) <= headroom)
-			return skb;
-/*		if ((sizeof (struct nc_header) + padlen
-					+ sizeof (struct nc_trailer)) <
-				(headroom + tailroom)) {
-			skb->data = memmove (skb->head
-						+ sizeof (struct nc_header),
-					    skb->data, skb->len);
-			skb->tail = skb->data + skb->len;
-			return skb;
-		}*/
-	}
-	skb2 = skb_copy_expand (skb,
-				sizeof (struct nc_header),
-				sizeof (struct nc_trailer) + padlen,
-				flags);
-	dev_kfree_skb_any (skb);
-	return skb2;
-}
-
 static int 
 usb_eth_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	int ret;
 	struct sk_buff  *skb2;
 	long flags;
-	int length = skb->len;
-	struct nc_header *header = 0;
-	struct nc_trailer *trailer = 0;
 	
 	if (next_tx_skb) {
 		printk("%s: called with next_tx_skb != NULL\n", __FUNCTION__);
@@ -323,22 +240,9 @@
 		skb = skb2;
 	}
 
-	skb2 = fixup_skb (skb, GFP_ATOMIC);
-	if (!skb2) {
-		usbe_info.stats.tx_dropped++;
-		dev_kfree_skb(skb);
-		return 1;
+	if ((skb->len % usb_wsize) == 0) {
+		skb->len++; // other side will ignore this one, anyway.
 	}
-	skb = skb2;
-	
-	header = (struct nc_header *) skb_push (skb, sizeof (struct nc_header));
-	header->hdr_len = cpu_to_le16 (sizeof (struct nc_header));
-	header->packet_len = cpu_to_le16 (length);
-	if (!((skb->len + sizeof (struct nc_trailer)) & 0x01))
-		*skb_put (skb, 1) = PAD_BYTE;
-	trailer = (struct nc_trailer *) skb_put (skb, sizeof (struct nc_trailer));
-	header->packet_id = cpu_to_le16 (usbe_info.packet_id++);
-	put_unaligned (header->packet_id, &trailer->packet_id);
 
 	save_flags_cli(flags);
 	if (cur_tx_skb) {
@@ -385,7 +289,7 @@
 	}
 	
 	MOD_INC_USE_COUNT;
-	sa1100_usb_recv(cur_rx_skb->tail, skb_tailroom(cur_rx_skb), 
+	sa1100_usb_recv(dmabuf, skb_tailroom(cur_rx_skb), 
 			usb_recv_callback);
 	return 0;
 }
@@ -422,29 +326,18 @@
 static int 
 usb_eth_probe(struct net_device *dev)
 {
+	u8 node_id [ETH_ALEN];
+
+	get_random_bytes (node_id, sizeof node_id);
+	node_id [0] &= 0xfe;    // clear multicast bit
+
 	/* 
-	 * Assign the hardware address of the board: use 
-	 * 40 00 00 00 00 XX, where XX is the USB address of the
-	 * device
+	 * Assign the hardware address of the board: 
+	 * generate it randomly, as there can be many such
+	 * devices on the bus.
 	 */
-	dev->dev_addr[0] = 0x40;
-	dev->dev_addr[1] = 0;
-	dev->dev_addr[2] = 0;
-	dev->dev_addr[3] = 0;
-	dev->dev_addr[4] = 0;
-	dev->dev_addr[5] = 1; 
+	memcpy (dev->dev_addr, node_id, sizeof node_id);
    
-	/* 
-	 * we know the host mac address because it is derived from
-	 * the USB address.
-	 */
-	usbe_info.host_addr[0] = 0x40;
-	usbe_info.host_addr[1] = 0;
-	usbe_info.host_addr[2] = 0;
-	usbe_info.host_addr[3] = 0;
-	usbe_info.host_addr[4] = 0xff;
-	usbe_info.host_addr[5] = 1;
-
 	dev->open = usb_eth_open;
 	dev->change_mtu = usb_change_mtu;
 	dev->stop = usb_eth_release;
@@ -479,6 +372,9 @@
 {
 	int rc; 
 
+	dmabuf = kmalloc( usb_rsize, GFP_KERNEL | GFP_DMA );
+	if (!dmabuf)
+		return -ENOMEM;
 	strncpy(usb_eth_device.name, usb_eth_name, IFNAMSIZ);
 	usb_eth_device.init = usb_eth_probe;
 	if (register_netdev(&usb_eth_device) != 0)
@@ -513,6 +409,7 @@
 	 sa1100_usb_close();
 	 if ( (pstr = sa1100_usb_get_string_descriptor(1)) != NULL )
 		  kfree( pstr );
+	kfree(dmabuf);
 	unregister_netdev(&usb_eth_device);
 }
 
diff -uNr old/usb_ctl.h new/usb_ctl.h
--- old/usb_ctl.h	Tue Mar 13 01:59:55 2001
+++ new/usb_ctl.h	Thu Mar 15 01:59:35 2001
@@ -119,5 +119,5 @@
 }
 
 
-
+#define CHECK_ADDRESS { if ( Ser0UDCAR == 1 ) { printk("%s:%d I lost my address!!!\n",__FUNCTION__, __LINE__);}}
 #endif /* _USB_CTL_H */
diff -uNr old/usb_ep0.c new/usb_ep0.c
--- old/usb_ep0.c	Tue Mar 13 01:59:55 2001
+++ new/usb_ep0.c	Thu Mar 15 03:40:07 2001
@@ -215,6 +215,7 @@
 	 current_handler = sh_setup_begin;
 	 wr.p = NULL;
 	 wr.bytes_left = 0;
+	 usbd_info.address=0;
 }
 
 /* handle interrupt for endpoint zero */
@@ -325,6 +326,7 @@
 			 ..it and pray...
 		  */
 		  Ser0UDCAR = address;
+		  usbd_info.address = address;
 		  usbctl_next_state_on_event( kEvAddress );
 		  set_cs_bits( UDCCS0_SO | UDCCS0_DE );  /* no data phase */
 		  printk( "%sI have been assigned address: %d\n", pszMe, address );
diff -uNr old/usb_recv.c new/usb_recv.c
--- old/usb_recv.c	Fri Mar  2 14:34:47 2001
+++ new/usb_recv.c	Thu Mar 15 03:21:59 2001
@@ -112,7 +112,7 @@
 	unsigned int len;
 	int status = Ser0UDCCS1;
 
-	if ( naking ) printk( "%sEh? in ISR but nakking = %d\n", "usbrx: ", naking );
+	if ( naking ) printk( "%sEh? in ISR but naking = %d\n", "usbrx: ", naking );
 
 	if (status & UDCCS1_RPC) {
 
@@ -192,4 +192,12 @@
 }
 
 EXPORT_SYMBOL(sa1100_usb_recv_reset);
+
+void
+sa1100_usb_recv_stall(void)
+{
+	ep1_stall();
+}
+
+EXPORT_SYMBOL(sa1100_usb_recv_stall);
 
diff -uNr old/usb_send.c new/usb_send.c
--- old/usb_send.c	Tue Mar 13 01:59:55 2001
+++ new/usb_send.c	Thu Mar 15 03:54:53 2001
@@ -12,6 +12,8 @@
  * This is still work in progress...
  * 
  * Please see linux/Documentation/arm/SA1100/SA1100_USB for details.
+ * 15/03/2001 - ep2_start now sets UDCAR to overcome something that is hardware
+ * 		bug, I think. green@iXcelerator.com
  */
 
 #include <linux/module.h>
@@ -84,6 +86,7 @@
 	}
 	/* End remove if never seen... 8Mar01ww */
 
+	Ser0UDCAR = usbd_info.address; // fighting stupid silicon bug
 	sa1100_dma_queue_buffer(dmachn_tx, NULL, ep2_curdmapos, ep2_curdmalen);
 }
 
@@ -124,6 +127,9 @@
 ep2_int_hndlr(int udcsr)
 {
 	int status = Ser0UDCCS2;
+
+	if (Ser0UDCAR != usbd_info.address) // check for stupid silicon bug.
+		Ser0UDCAR = usbd_info.address; 
 
 	UDC_flip(Ser0UDCCS2, UDCCS2_SST);
 

