Initial revision
diff --git a/contiki-cpc/uip/lan91c96.c b/contiki-cpc/uip/lan91c96.c
new file mode 100644
index 0000000..d830eb0
--- /dev/null
+++ b/contiki-cpc/uip/lan91c96.c
@@ -0,0 +1,486 @@
+/*
+ * uIP lan91c96 (smc9194) driver
+ * Based on cs8900a driver, copyrighted (c) 2001, by Adam Dunkels
+ * Copyright (c) 2003, Josef Soucek
+ * All rights reserved.
+ *
+ * Ethernet card for Commodore 64, based on lan91c96 chip
+ * is a device created by IDE64 Project team.
+ * More information: http://ide64.come.to
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: lan91c96.c,v 1.1 2006/04/17 15:02:40 kthacker Exp $
+ *
+ */
+
+#define UIP_ETHADDR0 0x00
+#define UIP_ETHADDR1 0x0d
+#define UIP_ETHADDR2 0x60
+#define UIP_ETHADDR3 0x80
+#define UIP_ETHADDR4 0x3d
+#define UIP_ETHADDR5 0xb9
+
+#include "lan91c96.h"
+#include "uip.h"
+#include "uip_arp.h"
+
+#include <stdio.h>
+
+// #define DEBUG
+
+#define ETHBASE 0xde10
+
+#define ETHBSR     ETHBASE+0x0e  //Bank select register             R/W (2B)
+
+/* Register bank 0 */
+
+#define ETHTCR     ETHBASE       //Transmition control register     R/W (2B)
+#define ETHEPHSR   ETHBASE+2     //EPH status register              R/O (2B)
+#define ETHRCR     ETHBASE+4     //Receive control register         R/W (2B)
+#define ETHECR     ETHBASE+6     //Counter register                 R/O (2B)
+#define ETHMIR     (ETHBASE+8)     //Memory information register      R/O (2B)
+#define ETHMCR     ETHBASE+0x0a  //Memory Config. reg.    +0 R/W +1 R/O (2B)
+
+/* Register bank 1 */
+
+#define ETHCR      ETHBASE       //Configuration register           R/W (2B)
+#define ETHBAR     ETHBASE+2     //Base address register            R/W (2B)
+#define ETHIAR     ETHBASE+4     //Individual address register      R/W (6B)
+#define ETHGPR     ETHBASE+0x0a  //General address register         R/W (2B)
+#define ETHCTR     ETHBASE+0x0c  //Control register                 R/W (2B)
+
+/* Register bank 2 */
+
+#define ETHMMUCR   ETHBASE       //MMU command register             W/O (1B)
+#define ETHAUTOTX  ETHBASE+1     //AUTO TX start register           R/W (1B)
+#define ETHPNR     ETHBASE+2     //Packet number register           R/W (1B)
+#define ETHARR     ETHBASE+3     //Allocation result register       R/O (1B)
+#define ETHFIFO    ETHBASE+4     //FIFO ports register              R/O (2B)
+#define ETHPTR     ETHBASE+6     //Pointer register                 R/W (2B)
+#define ETHDATA    ETHBASE+8     //Data register                    R/W (4B)
+#define ETHIST     (ETHBASE+0x0c)  //Interrupt status register        R/O (1B)
+#define ETHACK     ETHBASE+0x0c  //Interrupt acknowledge register   W/O (1B)
+#define ETHMSK     ETHBASE+0x0d  //Interrupt mask register          R/W (1B)
+
+/* Register bank 3 */
+
+#define ETHMT      ETHBASE       //Multicast table                  R/W (8B)
+#define ETHMGMT    ETHBASE+8     //Management interface             R/W (2B)
+#define ETHREV     ETHBASE+0x0a  //Revision register                R/W (2B)
+#define ETHERCV    ETHBASE+0x0c  //Early RCV register               R/W (2B)
+
+#define BANK(num) asm("lda #%b",num); asm("sta %w",ETHBSR);
+
+#ifdef DEBUG
+static void print_packet(u8_t *, u16_t);
+#endif
+
+static u8_t packet_status;
+static u16_t packet_length;
+
+extern u16_t uip_len;
+
+
+#pragma optimize(push, off)
+void lan91c96_init(void)
+{
+  /* Check if high byte is 0x33 */
+  asm("lda %w", ETHBSR+1);
+  asm("cmp #$33");
+  asm("beq @L1");
+
+  asm("inc $d021");              // Error
+
+  asm("@L1:");
+
+  /* Reset ETH card */
+  BANK(0);
+  asm("lda #%%10000000");        //Software reset
+  asm("sta %w", ETHRCR+1);
+
+  asm("lda #0");
+  asm("sta %w", ETHRCR);
+  asm("sta %w", ETHRCR+1);
+
+  /* delay */
+  asm("ldx #0");
+  asm("@L2:");
+  asm("cmp ($ff,x)");            //6 cycles
+  asm("cmp ($ff,x)");            //6 cycles
+  asm("dex");                    //2 cycles
+  asm("bne @L2");                //3 cycles
+                                 //17*256=4352 => 4,4 ms
+
+  /* Enable transmit and receive */
+  asm("lda #%%10000001");        //Enable transmit TXENA, PAD_EN
+  asm("sta %w", ETHTCR);
+  asm("lda #%%00000011");        //Enable receive, strip CRC ???
+  asm("sta %w", ETHRCR+1);
+
+  BANK(1);
+  asm("lda %w", ETHCR+1);
+  asm("ora #%%00010000");        //No wait (IOCHRDY)
+  asm("sta %w", ETHCR+1);
+
+  asm("lda #%%00001001");        //Auto release
+  asm("sta %w", ETHCTR+1);
+  
+  /* Set MAC address */
+  asm("lda #%b", (unsigned)UIP_ETHADDR0);
+  asm("sta %w", ETHIAR);
+  asm("lda #%b", (unsigned)UIP_ETHADDR1);
+  asm("sta %w", ETHIAR+1);
+  asm("lda #%b", (unsigned)UIP_ETHADDR2);
+  asm("sta %w", ETHIAR+2);
+  asm("lda #%b", (unsigned)UIP_ETHADDR3);
+  asm("sta %w", ETHIAR+3);
+  asm("lda #%b", (unsigned)UIP_ETHADDR4);
+  asm("sta %w", ETHIAR+4);
+  asm("lda #%b", (unsigned)UIP_ETHADDR5);
+  asm("sta %w", ETHIAR+5);
+
+  BANK(2);
+  asm("lda #%%00001111");               //RCV INT, ALLOC INT, TX INT, TX EMPTY 
+  asm("sta %w", ETHMSK);
+}
+#pragma optimize(pop)
+
+
+#pragma optimize(push, off)
+#if UIP_BUFSIZE > 255
+u16_t lan91c96_poll(void)
+#else
+u8_t lan91c96_poll(void)
+#endif
+{
+  // #######
+//  BANK(0);
+//  printf("RAM: %d ", ((*(unsigned int *)ETHMIR) & 0xff00));
+//  BANK(2);
+  // #######
+
+  asm("lda %w", ETHIST);
+  asm("and #%%00000001");                //RCV INT
+  asm("bne @L1");
+
+  /* No packet available */
+  return 0;
+
+  asm("@L1:");
+
+  #ifdef DEBUG
+  printf("RCV: IRQ\n");
+  #endif
+
+  asm("lda #0");
+  asm("sta %w", ETHPTR);
+  asm("lda #%%11100000");               //RCV,AUTO INCR.,READ
+  asm("sta %w", ETHPTR+1);
+
+  asm("lda %w", ETHDATA);               //Status word
+  asm("lda %w", ETHDATA);
+  asm("sta _packet_status");            //High byte only
+
+  asm("lda %w", ETHDATA);               //Total number of bytes
+  asm("sta _packet_length");
+  asm("lda %w", ETHDATA);
+  asm("sta _packet_length+1");
+
+  /* Last word contain 'last data byte' and 0x60 */
+  /* or 'fill byte' and 0x40 */
+
+  packet_length -= 6;            //The packet contains 3 extra words
+
+  asm("lda _packet_status");
+  asm("and #$10");
+  asm("beq @L2");
+
+  packet_length++;
+
+  #ifdef DEBUG
+  printf("RCV: odd number of bytes\n");
+  #endif
+
+  asm("@L2:");
+                    
+  #ifdef DEBUG
+  printf("RCV: L:%d ST-HIGH:0x%02x ",packet_length,packet_status);
+  #endif
+
+  if (packet_length > UIP_BUFSIZE)
+  {
+    /* Remove and release RX packet from FIFO*/ 
+    asm("lda #%%10000000");
+    asm("sta %w", ETHMMUCR);
+
+    #ifdef DEBUG
+    printf("RCV: UIP_BUFSIZE exceeded - packet dropped!\n");
+    #endif
+
+    return 0;
+  }
+
+  asm("lda #<_uip_buf");
+  asm("sta ptr1");
+  asm("lda #>_uip_buf");
+  asm("sta ptr1+1");
+
+  asm("ldy #0");
+  asm("ldx _packet_length+1");
+  asm("beq @RE1");               //packet_length < 256
+
+  asm("@RL1:");
+  asm("lda %w", ETHDATA);
+  asm("sta (ptr1),y");
+  asm("iny");
+  asm("bne @RL1");
+  asm("inc ptr1+1");
+  asm("dex");
+  asm("bne @RL1");
+
+  asm("@RE1:");
+  asm("lda %w", ETHDATA);
+  asm("sta (ptr1),y");
+  asm("iny");
+  asm("cpy _packet_length");
+  asm("bne @RE1");
+
+  /* Remove and release RX packet from FIFO*/ 
+  asm("lda #%%10000000");
+  asm("sta %w", ETHMMUCR);
+
+  #ifdef DEBUG
+//  print_packet(uip_buf, packet_length);
+  #endif
+
+  return packet_length;
+}
+#pragma optimize(pop)
+
+/* First 40+14 (IP nad TCP header) is send from uip_buf */
+/* than data from uip_appdata                           */
+
+#pragma optimize(push, off)
+void lan91c96_send(void)
+{
+  #ifdef DEBUG
+  printf("SND: send packet\n");
+  #endif
+
+  #if UIP_BUFSIZE > 255
+  asm("lda _uip_len+1");  
+  #else
+  asm("lda #0");
+  #endif
+  asm("ora #%%00100000");        //Allocate memory for TX
+  asm("sta %w", ETHMMUCR);
+
+  asm("ldx #8");                 //Wait...
+  asm("@L1:");                   //Wait for allocation ready
+  asm("lda %w", ETHIST);
+  asm("and #%%00001000");        //ALLOC INT
+  asm("bne @X1");
+  asm("dex");
+  asm("bne @L1");
+
+    #ifdef DEBUG
+    printf("SND: ERR: memory alloc timeout\n");
+    #endif
+
+    return;
+
+  asm("@X1:");
+  #ifdef DEBUG
+  printf("SND: packet memory allocated\n");
+  #endif
+
+  asm("lda #%%00001000");        //Acknowledge int, is it necessary ???
+  asm("sta %w", ETHACK);
+
+  asm("lda %w", ETHARR);
+  asm("sta %w", ETHPNR);         //Set packet address
+
+  asm("lda #0");
+  asm("sta %w", ETHPTR);
+  asm("lda #%%01000000");        //AUTO INCR.
+  asm("sta %w", ETHPTR+1);
+
+  #ifdef DEBUG
+  printf("SND: L:%d ", uip_len);
+  #endif
+
+  asm("lda #0");                 //Status written by CSMA
+  asm("sta %w", ETHDATA);
+  asm("sta %w", ETHDATA);
+
+  asm("lda _uip_len");
+  asm("and #$01");
+  asm("beq @SD1");
+
+    packet_length=uip_len+5;
+    asm("jmp @LC1");
+
+  asm("@SD1:");
+
+    packet_length=uip_len+6;       //+6 for status word, length and ctl byte
+
+  asm("@LC1:");
+
+//  printf("SND: L:%d ", packet_length);
+
+  asm("lda _packet_length");
+  asm("sta %w", ETHDATA);
+  asm("lda _packet_length+1");
+  asm("sta %w", ETHDATA);
+
+  #ifdef DEBUG
+//  print_packet(uip_buf, uip_len);
+  #endif
+
+  /* Send 40+14=54 bytes of header */
+
+  if(uip_len <= 54) {
+
+    #ifdef DEBUG
+    printf("SND: short packet sent.\n");
+    #endif
+
+    asm("ldx _uip_len");
+    asm("ldy #0");
+    asm("@WL1:");
+    asm("lda _uip_buf,y");
+    asm("sta %w", ETHDATA);
+    asm("iny");
+    asm("dex");
+    asm("bne @WL1");
+
+  } else {
+
+    asm("ldx #54");
+    asm("ldy #0");
+    asm("@WL2:");
+    asm("lda _uip_buf,y");
+    asm("sta %w", ETHDATA);
+    asm("iny");
+    asm("dex");
+    asm("bne @WL2");
+
+    uip_len -= 54;
+
+    asm("lda _uip_appdata");       //uip_appdata is pointer
+    asm("sta ptr1");
+    asm("lda _uip_appdata+1");
+    asm("sta ptr1+1");
+
+    asm("ldy #0");
+    #if UIP_BUFSIZE > 255
+    asm("ldx _uip_len+1");
+    #else
+    asm("ldx #0");
+    #endif
+    asm("beq @RE1");               //packet_length < 256
+
+    asm("@RL1:");
+    asm("lda (ptr1),y");
+    asm("sta %w", ETHDATA);
+    asm("iny");
+    asm("bne @RL1");
+    asm("inc ptr1+1");
+    asm("dex");
+    asm("bne @RL1");
+
+    asm("@RE1:");
+    asm("lda (ptr1),y");
+    asm("sta %w", ETHDATA);
+    asm("iny");
+    asm("cpy _uip_len");
+    asm("bne @RE1");
+
+  }
+
+  asm("lda _uip_len");
+  asm("and #$01");
+  asm("beq @R3");
+
+  asm("lda #%%00100000");
+  asm("sta %w", ETHDATA);        //Control byte
+
+  asm("lda #%%11000000");        //ENQUEUE PACKET - transmit packet
+  asm("sta %w", ETHMMUCR);
+
+//  printf("\n## %02x", *(unsigned char *)ETHIST);
+
+  return;
+
+  asm("@R3:");
+
+  asm("lda #0");
+  asm("sta %w", ETHDATA);        //Fill byte
+  asm("sta %w", ETHDATA);        //Control byte
+
+  asm("lda #%%11000000");        //ENQUEUE PACKET - transmit packet
+  asm("sta %w", ETHMMUCR);
+
+//  printf("\n## %02x\n", *(unsigned char *)ETHIST);
+  return;
+}
+#pragma optimize(pop)
+
+#ifdef DEBUG
+static void print_packet(u8_t *buf, u16_t length)
+{
+  int i;
+  int remainder;
+  int lines;
+  u8_t a;
+  int cur;
+  int address=0;
+
+  printf("\nPacket of length %d \n", length );
+
+  lines = length / 8;
+  remainder = length % 8;
+
+  for ( i = 0; i < lines ; i ++ ) {
+    printf(":%04x ", address=i*8);
+
+    for ( cur = 0; cur < 8; cur ++ ) {
+      a = *(buf ++ );
+      printf("%02x ", a);
+    }
+    printf("\n");
+  }
+
+  printf(":%04x ", address+8);
+
+  for ( i = 0; i < remainder ; i++ ) {
+    a = *(buf ++ );
+    printf("%02x ", a);
+  }
+  printf("\n");
+}
+#endif /* DEBUG */
+