Index: uspace/srv/hw/netif/dp8390/Makefile
===================================================================
--- uspace/srv/hw/netif/dp8390/Makefile	(revision 7ea7db31d35d3bcb84a5f1220696fa0c75b775c3)
+++ uspace/srv/hw/netif/dp8390/Makefile	(revision 3c106e8814a50268257db9a33c79a75e51e871ec)
@@ -43,5 +43,4 @@
 SOURCES = \
 	dp8390.c \
-	dp8390_module.c \
 	ne2000.c
 
Index: uspace/srv/hw/netif/dp8390/dp8390.c
===================================================================
--- uspace/srv/hw/netif/dp8390/dp8390.c	(revision 7ea7db31d35d3bcb84a5f1220696fa0c75b775c3)
+++ uspace/srv/hw/netif/dp8390/dp8390.c	(revision 3c106e8814a50268257db9a33c79a75e51e871ec)
@@ -38,10 +38,14 @@
  */
 
-/** @addtogroup dp8390
+/** @addtogroup ne2000
  *  @{
  */
 
 /** @file
- *  DP8390 network interface core implementation.
+ *
+ * NE2000 (based on DP8390) network interface core implementation.
+ * Only the basic NE2000 PIO (ISA) interface is supported, remote
+ * DMA is completely absent from this code for simplicity.
+ *
  */
 
@@ -49,222 +53,215 @@
 #include <byteorder.h>
 #include <errno.h>
-#include <netif_local.h>
+#include <libarch/ddi.h>
+#include <netif_skel.h>
 #include <net/packet.h>
 #include <nil_interface.h>
 #include <packet_client.h>
-#include "dp8390_drv.h"
-#include "dp8390_port.h"
 #include "dp8390.h"
-#include "ne2000.h"
-
-/** Read a memory block byte by byte.
- *
- *  @param[in] port The source address.
- *  @param[out] buf The destination buffer.
- *  @param[in] size The memory block size in bytes.
- *
- */
-static void outsb(port_t port, void * buf, size_t size);
+
+/** Page size */
+#define DP_PAGE  256
+
+/** 6 * DP_PAGE >= 1514 bytes */
+#define SQ_PAGES  6
+
+/* NE2000 implementation. */
+
+/** NE2000 Data Register */
+#define NE2K_DATA  0x0010
+
+/** NE2000 Reset register */
+#define NE2K_RESET  0x001f
+
+/** NE2000 data start */
+#define NE2K_START  0x4000
+
+/** NE2000 data size */
+#define NE2K_SIZE  0x4000
+
+/** NE2000 retry count */
+#define NE2K_RETRY  100
+
+/** NE2000 error messages rate limiting */
+#define NE2K_ERL  10
+
+/** Minimum Ethernet packet size in bytes */
+#define ETH_MIN_PACK_SIZE  60
+
+/** Maximum Ethernet packet size in bytes */
+#define ETH_MAX_PACK_SIZE_TAGGED  1518
+
+/** Type definition of the receive header
+ *
+ */
+typedef struct {
+	/** Copy of RSR */
+	uint8_t status;
+	
+	/** Pointer to next packet */
+	uint8_t next;
+	
+	/** Receive Byte Count Low */
+	uint8_t rbcl;
+	
+	/** Receive Byte Count High */
+	uint8_t rbch;
+} recv_header_t;
 
 /** Read a memory block word by word.
  *
- *  @param[in] port The source address.
- *  @param[out] buf The destination buffer.
- *  @param[in] size The memory block size in bytes.
- *
- */
-static void outsw(port_t port, void * buf, size_t size);
-
-/*
- * Some clones of the dp8390 and the PC emulator 'Bochs' require the CR_STA
- * on writes to the CR register. Additional CR_STAs do not appear to hurt
- * genuine dp8390s.
- */
-#define CR_EXTRA  CR_STA
-
-static void dp_init(dpeth_t *dep);
-static void dp_reinit(dpeth_t *dep);
-static void dp_reset(dpeth_t *dep);
-static void dp_recv(int nil_phone, device_id_t device_id, dpeth_t *dep);
-static int dp_pkt2user(int nil_phone, device_id_t device_id, dpeth_t *dep, int page, int length);
-static void conf_hw(dpeth_t *dep);
-static void insb(port_t port, void *buf, size_t size);
-static void insw(port_t port, void *buf, size_t size);
-
-int do_probe(dpeth_t *dep)
-{
-	/* This is the default, try to (re)locate the device. */
-	conf_hw(dep);
-	if (!dep->up)
-		/* Probe failed, or the device is configured off. */
+ * @param[in]  port Source address.
+ * @param[out] buf  Destination buffer.
+ * @param[in]  size Memory block size in bytes.
+ *
+ */
+static void pio_read_buf_16(void *port, void *buf, size_t size)
+{
+	size_t i;
+	
+	for (i = 0; (i << 1) < size; i++)
+		*((uint16_t *) buf + i) = pio_read_16((ioport16_t *) (port));
+}
+
+/** Write a memory block word by word.
+ *
+ * @param[in] port Destination address.
+ * @param[in] buf  Source buffer.
+ * @param[in] size Memory block size in bytes.
+ *
+ */
+static void pio_write_buf_16(void *port, void *buf, size_t size)
+{
+	size_t i;
+	
+	for (i = 0; (i << 1) < size; i++)
+		pio_write_16((ioport16_t *) port, *((uint16_t *) buf + i));
+}
+
+static void ne2k_download(ne2k_t *ne2k, void *buf, size_t addr, size_t size)
+{
+	size_t esize = size & ~1;
+	
+	pio_write_8(ne2k->port + DP_RBCR0, esize & 0xff);
+	pio_write_8(ne2k->port + DP_RBCR1, (esize >> 8) & 0xff);
+	pio_write_8(ne2k->port + DP_RSAR0, addr & 0xff);
+	pio_write_8(ne2k->port + DP_RSAR1, (addr >> 8) & 0xff);
+	pio_write_8(ne2k->port + DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+	
+	if (esize != 0) {
+		pio_read_buf_16(ne2k->data_port, buf, esize);
+		size -= esize;
+		buf += esize;
+	}
+	
+	if (size) {
+		assert(size == 1);
+		
+		uint16_t word = pio_read_16(ne2k->data_port);
+		memcpy(buf, &word, 1);
+	}
+}
+
+static void ne2k_upload(ne2k_t *ne2k, void *buf, size_t addr, size_t size)
+{
+	size_t esize = size & ~1;
+	
+	pio_write_8(ne2k->port + DP_RBCR0, esize & 0xff);
+	pio_write_8(ne2k->port + DP_RBCR1, (esize >> 8) & 0xff);
+	pio_write_8(ne2k->port + DP_RSAR0, addr & 0xff);
+	pio_write_8(ne2k->port + DP_RSAR1, (addr >> 8) & 0xff);
+	pio_write_8(ne2k->port + DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
+	
+	if (esize != 0) {
+		pio_write_buf_16(ne2k->data_port, buf, esize);
+		size -= esize;
+		buf += esize;
+	}
+	
+	if (size) {
+		assert(size == 1);
+		
+		uint16_t word = 0;
+		
+		memcpy(&word, buf, 1);
+		pio_write_16(ne2k->data_port, word);
+	}
+}
+
+/** Probe and initialize the network interface.
+ *
+ * @param[in,out] ne2k Network interface structure.
+ * @param[in]     port Device address.
+ * @param[in]     irq  Device interrupt vector.
+ *
+ * @return EOK on success.
+ * @return EXDEV if the network interface was not recognized.
+ *
+ */
+int ne2k_probe(ne2k_t *ne2k, void *port, int irq)
+{
+	unsigned int i;
+	
+	/* General initialization */
+	ne2k->port = port;
+	ne2k->data_port = ne2k->port + NE2K_DATA;
+	ne2k->irq = irq;
+	ne2k->probed = false;
+	ne2k->up = false;
+	
+	/* Reset the ethernet card */
+	uint8_t val = pio_read_8(ne2k->port + NE2K_RESET);
+	usleep(2000);
+	pio_write_8(ne2k->port + NE2K_RESET, val);
+	usleep(2000);
+	
+	/* Reset the DP8390 */
+	pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT);
+	for (i = 0; i < 0x1000; i++) {
+		if (pio_read_8(ne2k->port + DP_ISR) != 0)
+			break;
+	}
+	
+	/* Check if the DP8390 is really there */
+	val = pio_read_8(ne2k->port + DP_CR);
+	if ((val & (CR_STP | CR_DM_ABORT)) != (CR_STP | CR_DM_ABORT))
 		return EXDEV;
 	
-	if (dep->up)
-		dp_init(dep);
-	
-	return EOK;
-}
-
-/** Initialize and/or start the network interface.
- *
- *  @param[in,out] dep The network interface structure.
- *
- *  @return EOK on success.
- *  @return EXDEV if the network interface is disabled.
- *
- */
-int do_init(dpeth_t *dep)
-{
-	if (!dep->up)
-		/* FIXME: Perhaps call do_probe()? */
-		return EXDEV;
-	
-	assert(dep->up);
-	assert(dep->enabled);
-	
-	dp_reinit(dep);
-	return EOK;
-}
-
-void do_stop(dpeth_t *dep)
-{
-	if ((dep->up) && (dep->enabled)) {
-		outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
-		ne_stop(dep);
-		
-		dep->enabled = false;
-		dep->stopped = false;
-		dep->sending = false;
-		dep->send_avail = false;
-	}
-}
-
-static void dp_user2nic(dpeth_t *dep, void *buf, size_t offset, int nic_addr, size_t size)
-{
-	size_t ecount = size & ~1;
-	
-	outb_reg0(dep, DP_ISR, ISR_RDC);
-	
-	if (dep->de_16bit) {
-		outb_reg0(dep, DP_RBCR0, ecount & 0xff);
-		outb_reg0(dep, DP_RBCR1, ecount >> 8);
-	} else {
-		outb_reg0(dep, DP_RBCR0, size & 0xff);
-		outb_reg0(dep, DP_RBCR1, size >> 8);
-	}
-	
-	outb_reg0(dep, DP_RSAR0, nic_addr & 0xff);
-	outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
-	outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
-	
-	if (dep->de_16bit) {
-		void *ptr = buf + offset;
-		
-		if (ecount != 0) {
-			outsw(dep->de_data_port, ptr, ecount);
-			size -= ecount;
-			offset += ecount;
-			ptr += ecount;
-		}
-		
-		if (size) {
-			assert(size == 1);
-			
-			uint16_t two_bytes;
-			
-			memcpy(&(((uint8_t *) &two_bytes)[0]), ptr, 1);
-			outw(dep->de_data_port, two_bytes);
-		}
-	} else
-		outsb(dep->de_data_port, buf + offset, size);
-	
-	unsigned int i;
-	for (i = 0; i < 100; i++) {
-		if (inb_reg0(dep, DP_ISR) & ISR_RDC)
-			break;
-	}
-	
-	if (i == 100)
-		fprintf(stderr, "Remote DMA failed to complete\n");
-}
-
-int do_pwrite(dpeth_t *dep, packet_t *packet, int from_int)
-{
-	int size;
-	int sendq_head;
-	
-	assert(dep->up);
-	assert(dep->enabled);
-	
-	if (dep->send_avail) {
-		fprintf(stderr, "Send already in progress\n");
-		return EBUSY;
-	}
-	
-	sendq_head = dep->de_sendq_head;
-	if (dep->de_sendq[sendq_head].sq_filled) {
-		if (from_int)
-			fprintf(stderr, "dp8390: should not be sending\n");
-		dep->send_avail = true;
-		dep->sending = false;
-		
-		return EBUSY;
-	}
-	
-	assert(!dep->sending);
-	
-	void *buf = packet_get_data(packet);
-	size = packet_get_data_length(packet);
-	
-	if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED) {
-		fprintf(stderr, "dp8390: invalid packet size\n");
-		return EINVAL;
-	}
-	
-	dp_user2nic(dep, buf, 0, dep->de_sendq[sendq_head].sq_sendpage
-	    * DP_PAGESIZE, size);
-	dep->de_sendq[sendq_head].sq_filled = true;
-	
-	if (dep->de_sendq_tail == sendq_head) {
-		outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage);
-		outb_reg0(dep, DP_TBCR1, size >> 8);
-		outb_reg0(dep, DP_TBCR0, size & 0xff);
-		outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);  /* there it goes .. */
-	} else
-		dep->de_sendq[sendq_head].sq_size = size;
-	
-	if (++sendq_head == dep->de_sendq_nr)
-		sendq_head = 0;
-	
-	assert(sendq_head < SENDQ_NR);
-	dep->de_sendq_head = sendq_head;
-	dep->sending = true;
-	
-	if (from_int)
-		return EOK;
-	
-	dep->sending = false;
-	
-	return EOK;
-}
-
-void dp_init(dpeth_t *dep)
-{
-	int dp_rcr_reg;
-	int i;
-	
-	/* General initialization */
-	dep->enabled = false;
-	dep->stopped = false;
-	dep->sending = false;
-	dep->send_avail = false;
-	ne_init(dep);
-	
-	printf("Ethernet address ");
-	for (i = 0; i < 6; i++)
-		printf("%02x%c", dep->de_address.ea_addr[i], i < 5 ? ':' : '\n');
+	/* Disable the receiver and init TCR and DCR */
+	pio_write_8(ne2k->port + DP_RCR, RCR_MON);
+	pio_write_8(ne2k->port + DP_TCR, TCR_NORMAL);
+	pio_write_8(ne2k->port + DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
+	
+	/* Setup a transfer to get the MAC address */
+	pio_write_8(ne2k->port + DP_RBCR0, ETH_ADDR << 1);
+	pio_write_8(ne2k->port + DP_RBCR1, 0);
+	pio_write_8(ne2k->port + DP_RSAR0, 0);
+	pio_write_8(ne2k->port + DP_RSAR1, 0);
+	pio_write_8(ne2k->port + DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+	
+	for (i = 0; i < ETH_ADDR; i++)
+		ne2k->mac[i] = pio_read_16(ne2k->data_port);
 	
 	/*
-	 * Initialization of the dp8390 following the mandatory procedure
+	 * Setup send queue. Use the first
+	 * SQ_PAGES of NE2000 memory for the send
+	 * buffer.
+	 */
+	ne2k->sq.dirty = false;
+	ne2k->sq.page = NE2K_START / DP_PAGE;
+	fibril_mutex_initialize(&ne2k->sq_mutex);
+	fibril_condvar_initialize(&ne2k->sq_cv);
+	
+	/*
+	 * Setup receive ring buffer. Use all the rest
+	 * of the NE2000 memory (except the first SQ_PAGES
+	 * reserved for the send buffer) for the receive
+	 * ring buffer.
+	 */
+	ne2k->start_page = ne2k->sq.page + SQ_PAGES;
+	ne2k->stop_page = ne2k->sq.page + NE2K_SIZE / DP_PAGE;
+	
+	/*
+	 * Initialization of the DP8390 following the mandatory procedure
 	 * in reference manual ("DP8390D/NS32490D NIC Network Interface
 	 * Controller", National Semiconductor, July 1995, Page 29).
@@ -272,211 +269,356 @@
 	
 	/* Step 1: */
-	outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
+	pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
 	
 	/* Step 2: */
-	if (dep->de_16bit)
-		outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
-	else
-		outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | DCR_BMS);
+	pio_write_8(ne2k->port + DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
 	
 	/* Step 3: */
-	outb_reg0(dep, DP_RBCR0, 0);
-	outb_reg0(dep, DP_RBCR1, 0);
+	pio_write_8(ne2k->port + DP_RBCR0, 0);
+	pio_write_8(ne2k->port + DP_RBCR1, 0);
 	
 	/* Step 4: */
-	dp_rcr_reg = RCR_AB;  /* Enable broadcasts */
-	
-	outb_reg0(dep, DP_RCR, dp_rcr_reg);
+	pio_write_8(ne2k->port + DP_RCR, RCR_AB);
 	
 	/* Step 5: */
-	outb_reg0(dep, DP_TCR, TCR_INTERNAL);
+	pio_write_8(ne2k->port + DP_TCR, TCR_INTERNAL);
 	
 	/* Step 6: */
-	outb_reg0(dep, DP_BNRY, dep->de_startpage);
-	outb_reg0(dep, DP_PSTART, dep->de_startpage);
-	outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
+	pio_write_8(ne2k->port + DP_BNRY, ne2k->start_page);
+	pio_write_8(ne2k->port + DP_PSTART, ne2k->start_page);
+	pio_write_8(ne2k->port + DP_PSTOP, ne2k->stop_page);
 	
 	/* Step 7: */
-	outb_reg0(dep, DP_ISR, 0xFF);
+	pio_write_8(ne2k->port + DP_ISR, 0xff);
 	
 	/* Step 8: */
-	outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
-	    IMR_OVWE | IMR_CNTE);
+	pio_write_8(ne2k->port + DP_IMR,
+	    IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE | IMR_CNTE);
 	
 	/* Step 9: */
-	outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
-	
-	outb_reg1(dep, DP_PAR0, dep->de_address.ea_addr[0]);
-	outb_reg1(dep, DP_PAR1, dep->de_address.ea_addr[1]);
-	outb_reg1(dep, DP_PAR2, dep->de_address.ea_addr[2]);
-	outb_reg1(dep, DP_PAR3, dep->de_address.ea_addr[3]);
-	outb_reg1(dep, DP_PAR4, dep->de_address.ea_addr[4]);
-	outb_reg1(dep, DP_PAR5, dep->de_address.ea_addr[5]);
-	
-	outb_reg1(dep, DP_MAR0, 0xff);
-	outb_reg1(dep, DP_MAR1, 0xff);
-	outb_reg1(dep, DP_MAR2, 0xff);
-	outb_reg1(dep, DP_MAR3, 0xff);
-	outb_reg1(dep, DP_MAR4, 0xff);
-	outb_reg1(dep, DP_MAR5, 0xff);
-	outb_reg1(dep, DP_MAR6, 0xff);
-	outb_reg1(dep, DP_MAR7, 0xff);
-	
-	outb_reg1(dep, DP_CURR, dep->de_startpage + 1);
+	pio_write_8(ne2k->port + DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
+	
+	pio_write_8(ne2k->port + DP_PAR0, ne2k->mac[0]);
+	pio_write_8(ne2k->port + DP_PAR1, ne2k->mac[1]);
+	pio_write_8(ne2k->port + DP_PAR2, ne2k->mac[2]);
+	pio_write_8(ne2k->port + DP_PAR3, ne2k->mac[3]);
+	pio_write_8(ne2k->port + DP_PAR4, ne2k->mac[4]);
+	pio_write_8(ne2k->port + DP_PAR5, ne2k->mac[5]);
+	
+	pio_write_8(ne2k->port + DP_MAR0, 0xff);
+	pio_write_8(ne2k->port + DP_MAR1, 0xff);
+	pio_write_8(ne2k->port + DP_MAR2, 0xff);
+	pio_write_8(ne2k->port + DP_MAR3, 0xff);
+	pio_write_8(ne2k->port + DP_MAR4, 0xff);
+	pio_write_8(ne2k->port + DP_MAR5, 0xff);
+	pio_write_8(ne2k->port + DP_MAR6, 0xff);
+	pio_write_8(ne2k->port + DP_MAR7, 0xff);
+	
+	pio_write_8(ne2k->port + DP_CURR, ne2k->start_page + 1);
 	
 	/* Step 10: */
-	outb_reg0(dep, DP_CR, CR_DM_ABORT | CR_STA);
+	pio_write_8(ne2k->port + DP_CR, CR_DM_ABORT | CR_STA);
 	
 	/* Step 11: */
-	outb_reg0(dep, DP_TCR, TCR_NORMAL);
-	
-	inb_reg0(dep, DP_CNTR0);  /* Reset counters by reading */
-	inb_reg0(dep, DP_CNTR1);
-	inb_reg0(dep, DP_CNTR2);
-	
-	/* Finish the initialization. */
-	dep->enabled = true;
-	for (i = 0; i < dep->de_sendq_nr; i++)
-		dep->de_sendq[i].sq_filled= 0;
-	
-	dep->de_sendq_head = 0;
-	dep->de_sendq_tail = 0;
-}
-
-static void dp_reinit(dpeth_t *dep)
-{
-	int dp_rcr_reg;
-	
-	outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
-	
-	/* Enable broadcasts */
-	dp_rcr_reg = RCR_AB;
-	
-	outb_reg0(dep, DP_RCR, dp_rcr_reg);
-}
-
-static void dp_reset(dpeth_t *dep)
-{
-	int i;
-	
-	/* Stop chip */
-	outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
-	outb_reg0(dep, DP_RBCR0, 0);
-	outb_reg0(dep, DP_RBCR1, 0);
-	
-	for (i = 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
-		; /* Do nothing */
-	
-	outb_reg0(dep, DP_TCR, TCR_1EXTERNAL | TCR_OFST);
-	outb_reg0(dep, DP_CR, CR_STA | CR_DM_ABORT);
-	outb_reg0(dep, DP_TCR, TCR_NORMAL);
-	
-	/* Acknowledge the ISR_RDC (remote DMA) interrupt. */
-	for (i = 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) &ISR_RDC) == 0); i++)
-		; /* Do nothing */
-	
-	outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & ~ISR_RDC);
+	pio_write_8(ne2k->port + DP_TCR, TCR_NORMAL);
+	
+	/* Reset counters by reading */
+	pio_read_8(ne2k->port + DP_CNTR0);
+	pio_read_8(ne2k->port + DP_CNTR1);
+	pio_read_8(ne2k->port + DP_CNTR2);
+	
+	/* Finish the initialization */
+	ne2k->probed = true;
+	return EOK;
+}
+
+/** Start the network interface.
+ *
+ * @param[in,out] ne2k Network interface structure.
+ *
+ * @return EOK on success.
+ * @return EXDEV if the network interface is disabled.
+ *
+ */
+int ne2k_up(ne2k_t *ne2k)
+{
+	if (!ne2k->probed)
+		return EXDEV;
+	
+	pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_STA);
+	pio_write_8(ne2k->port + DP_RCR, RCR_AB);
+	
+	ne2k->up = true;
+	return EOK;
+}
+
+/** Stop the network interface.
+ *
+ * @param[in,out] ne2k Network interface structure.
+ *
+ */
+void ne2k_down(ne2k_t *ne2k)
+{
+	if ((ne2k->probed) && (ne2k->up)) {
+		pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT);
+		
+		/* Reset the ethernet card */
+		uint8_t val = pio_read_8(ne2k->port + NE2K_RESET);
+		usleep(2000);
+		pio_write_8(ne2k->port + NE2K_RESET, val);
+		
+		ne2k->up = false;
+	}
+}
+
+/** Send a frame.
+ *
+ * @param[in,out] ne2k   Network interface structure.
+ * @param[in]     packet Frame to be sent.
+ *
+ */
+void ne2k_send(ne2k_t *ne2k, packet_t *packet)
+{
+	assert(ne2k->probed);
+	assert(ne2k->up);
+	
+	fibril_mutex_lock(&ne2k->sq_mutex);
+	
+	while (ne2k->sq.dirty)
+		fibril_condvar_wait(&ne2k->sq_cv, &ne2k->sq_mutex);
+	
+	void *buf = packet_get_data(packet);
+	size_t size = packet_get_data_length(packet);
+	
+	if ((size < ETH_MIN_PACK_SIZE) || (size > ETH_MAX_PACK_SIZE_TAGGED)) {
+		fprintf(stderr, "%s: Frame dropped (invalid size %zu bytes)\n",
+		    NAME, size);
+		return;
+	}
+	
+	/* Upload the frame to the ethernet card */
+	ne2k_upload(ne2k, buf, ne2k->sq.page * DP_PAGE, size);
+	ne2k->sq.dirty = true;
+	ne2k->sq.size = size;
+	
+	/* Initialize the transfer */
+	pio_write_8(ne2k->port + DP_TPSR, ne2k->sq.page);
+	pio_write_8(ne2k->port + DP_TBCR0, size & 0xff);
+	pio_write_8(ne2k->port + DP_TBCR1, (size >> 8) & 0xff);
+	pio_write_8(ne2k->port + DP_CR, CR_TXP | CR_STA);
+	
+	fibril_mutex_unlock(&ne2k->sq_mutex);
+}
+
+static void ne2k_reset(ne2k_t *ne2k)
+{
+	unsigned int i;
+	
+	/* Stop the chip */
+	pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT);
+	pio_write_8(ne2k->port + DP_RBCR0, 0);
+	pio_write_8(ne2k->port + DP_RBCR1, 0);
+	
+	for (i = 0; i < 0x1000; i++) {
+		if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RST) != 0)
+			break;
+	}
+	
+	pio_write_8(ne2k->port + DP_TCR, TCR_1EXTERNAL | TCR_OFST);
+	pio_write_8(ne2k->port + DP_CR, CR_STA | CR_DM_ABORT);
+	pio_write_8(ne2k->port + DP_TCR, TCR_NORMAL);
+	
+	/* Acknowledge the ISR_RDC (remote DMA) interrupt */
+	for (i = 0; i < 0x1000; i++) {
+		if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RDC) != 0)
+			break;
+	}
+	
+	uint8_t val = pio_read_8(ne2k->port + DP_ISR);
+	pio_write_8(ne2k->port + DP_ISR, val & ~ISR_RDC);
 	
 	/*
-	 * Reset the transmit ring. If we were transmitting a packet, we
-	 * pretend that the packet is processed. Higher layers will
+	 * Reset the transmit ring. If we were transmitting a frame,
+	 * we pretend that the packet is processed. Higher layers will
 	 * retransmit if the packet wasn't actually sent.
 	 */
-	dep->de_sendq_head = 0;
-	dep->de_sendq_tail = 0;
-	
-	for (i = 0; i < dep->de_sendq_nr; i++)
-		dep->de_sendq[i].sq_filled = 0;
-	
-	dep->send_avail = false;
-	dep->stopped = false;
-}
-
-static uint8_t isr_acknowledge(dpeth_t *dep)
-{
-	uint8_t isr = inb_reg0(dep, DP_ISR);
+	fibril_mutex_lock(&ne2k->sq_mutex);
+	ne2k->sq.dirty = false;
+	fibril_mutex_unlock(&ne2k->sq_mutex);
+}
+
+static uint8_t ne2k_isr_ack(ne2k_t *ne2k)
+{
+	uint8_t isr = pio_read_8(ne2k->port + DP_ISR);
 	if (isr != 0)
-		outb_reg0(dep, DP_ISR, isr);
+		pio_write_8(ne2k->port + DP_ISR, isr);
 	
 	return isr;
 }
 
-void dp_check_ints(int nil_phone, device_id_t device_id, dpeth_t *dep, uint8_t isr)
-{
-	int tsr;
-	int size, sendq_tail;
-	
-	for (; (isr & 0x7f) != 0; isr = isr_acknowledge(dep)) {
+static void ne2k_receive_frame(ne2k_t *ne2k, uint8_t page, size_t length,
+    int nil_phone, device_id_t device_id)
+{
+	packet_t *packet = netif_packet_get_1(length);
+	if (!packet)
+		return;
+	
+	void *buf = packet_suffix(packet, length);
+	bzero(buf, length);
+	uint8_t last = page + length / DP_PAGE;
+	
+	if (last >= ne2k->stop_page) {
+		size_t left = (ne2k->stop_page - page) * DP_PAGE
+		    - sizeof(recv_header_t);
+		
+		ne2k_download(ne2k, buf, page * DP_PAGE + sizeof(recv_header_t),
+		    left);
+		ne2k_download(ne2k, buf + left, ne2k->start_page * DP_PAGE,
+		    length - left);
+	} else
+		ne2k_download(ne2k, buf, page * DP_PAGE + sizeof(recv_header_t),
+		    length);
+	
+	ne2k->stats.receive_packets++;
+	nil_received_msg(nil_phone, device_id, packet, SERVICE_NONE);
+}
+
+static void ne2k_receive(ne2k_t *ne2k, int nil_phone, device_id_t device_id)
+{
+	while (true) {
+		uint8_t boundary = pio_read_8(ne2k->port + DP_BNRY) + 1;
+		
+		if (boundary == ne2k->stop_page)
+			boundary = ne2k->start_page;
+		
+		pio_write_8(ne2k->port + DP_CR, CR_PS_P1 | CR_STA);
+		uint8_t current = pio_read_8(ne2k->port + DP_CURR);
+		pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_STA);
+		
+		if (current == boundary)
+			/* No more frames to process */
+			break;
+		
+		recv_header_t header;
+		size_t size = sizeof(header);
+		size_t offset = boundary * DP_PAGE;
+		
+		/* Get the frame header */
+		pio_write_8(ne2k->port + DP_RBCR0, size & 0xff);
+		pio_write_8(ne2k->port + DP_RBCR1, (size >> 8) & 0xff);
+		pio_write_8(ne2k->port + DP_RSAR0, offset & 0xff);
+		pio_write_8(ne2k->port + DP_RSAR1, (offset >> 8) & 0xff);
+		pio_write_8(ne2k->port + DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+		
+		pio_read_buf_16(ne2k->data_port, (void *) &header, size);
+		
+		size_t length =
+		    (((size_t) header.rbcl) | (((size_t) header.rbch) << 8)) - size;
+		uint8_t next = header.next;
+		
+		if ((length < ETH_MIN_PACK_SIZE)
+		    || (length > ETH_MAX_PACK_SIZE_TAGGED)) {
+			fprintf(stderr, "%s: Rant frame (%zu bytes)\n", NAME, length);
+			next = current;
+		} else if ((header.next < ne2k->start_page)
+		    || (header.next > ne2k->stop_page)) {
+			fprintf(stderr, "%s: Malformed next frame %u\n", NAME,
+			    header.next);
+			next = current;
+		} else if (header.status & RSR_FO) {
+			/*
+			 * This is very serious, so we issue a warning and
+			 * reset the buffers.
+			 */
+			fprintf(stderr, "%s: FIFO overrun\n", NAME);
+			ne2k->overruns++;
+			next = current;
+		} else if ((header.status & RSR_PRX) && (ne2k->up))
+			ne2k_receive_frame(ne2k, boundary, length, nil_phone, device_id);
+		
+		/*
+		 * Update the boundary pointer
+		 * to the value of the page
+		 * prior to the next packet to
+		 * be processed.
+		 */
+		if (next == ne2k->start_page)
+			next = ne2k->stop_page - 1;
+		else
+			next--;
+		
+		pio_write_8(ne2k->port + DP_BNRY, next);
+	}
+}
+
+void ne2k_interrupt(ne2k_t *ne2k, uint8_t isr, int nil_phone, device_id_t device_id)
+{
+	bool signal = false;
+	bool stopped = false;
+	
+	for (; (isr & 0x7f) != 0; isr = ne2k_isr_ack(ne2k)) {
 		if (isr & (ISR_PTX | ISR_TXE)) {
 			if (isr & ISR_TXE)
-				dep->de_stat.ets_sendErr++;
+				ne2k->stats.send_errors++;
 			else {
-				tsr = inb_reg0(dep, DP_TSR);
+				uint8_t tsr = pio_read_8(ne2k->port + DP_TSR);
 				
 				if (tsr & TSR_PTX)
-					dep->de_stat.ets_packetT++;
+					ne2k->stats.send_packets++;
 				
 				if (tsr & TSR_COL)
-					dep->de_stat.ets_collision++;
+					ne2k->stats.collisions++;
 				
 				if (tsr & TSR_ABT)
-					dep->de_stat.ets_transAb++;
+					ne2k->stats.send_aborted_errors++;
 				
 				if (tsr & TSR_CRS)
-					dep->de_stat.ets_carrSense++;
+					ne2k->stats.send_carrier_errors++;
 				
-				if ((tsr & TSR_FU) && (++dep->de_stat.ets_fifoUnder <= 10))
-					printf("FIFO underrun\n");
+				if (tsr & TSR_FU) {
+					ne2k->underruns++;
+					if (ne2k->underruns < NE2K_ERL)
+						fprintf(stderr, "%s: FIFO underrun\n", NAME);
+				}
 				
-				if ((tsr & TSR_CDH) && (++dep->de_stat.ets_CDheartbeat <= 10))
-					printf("CD heart beat failure\n");
+				if (tsr & TSR_CDH) {
+					ne2k->stats.send_heartbeat_errors++;
+					if (ne2k->stats.send_heartbeat_errors < NE2K_ERL)
+						fprintf(stderr, "%s: CD heartbeat failure\n", NAME);
+				}
 				
 				if (tsr & TSR_OWC)
-					dep->de_stat.ets_OWC++;
+					ne2k->stats.send_window_errors++;
 			}
 			
-			sendq_tail = dep->de_sendq_tail;
+			fibril_mutex_lock(&ne2k->sq_mutex);
 			
-			if (!(dep->de_sendq[sendq_tail].sq_filled)) {
-				printf("PTX interrupt, but no frame to send\n");
-				continue;
+			if (ne2k->sq.dirty) {
+				/* Prepare the buffer for next packet */
+				ne2k->sq.dirty = false;
+				ne2k->sq.size = 0;
+				signal = true;
+			} else {
+				ne2k->misses++;
+				if (ne2k->misses < NE2K_ERL)
+					fprintf(stderr, "%s: Spurious PTX interrupt\n", NAME);
 			}
 			
-			dep->de_sendq[sendq_tail].sq_filled = false;
-			
-			if (++sendq_tail == dep->de_sendq_nr)
-				sendq_tail = 0;
-			
-			dep->de_sendq_tail = sendq_tail;
-			
-			if (dep->de_sendq[sendq_tail].sq_filled) {
-				size = dep->de_sendq[sendq_tail].sq_size;
-				outb_reg0(dep, DP_TPSR,
-				    dep->de_sendq[sendq_tail].sq_sendpage);
-				outb_reg0(dep, DP_TBCR1, size >> 8);
-				outb_reg0(dep, DP_TBCR0, size & 0xff);
-				outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);
-			}
-			
-			dep->send_avail = false;
+			fibril_mutex_unlock(&ne2k->sq_mutex);
 		}
 		
 		if (isr & ISR_PRX)
-			dp_recv(nil_phone, device_id, dep);
+			ne2k_receive(ne2k, nil_phone, device_id);
 		
 		if (isr & ISR_RXE)
-			dep->de_stat.ets_recvErr++;
+			ne2k->stats.receive_errors++;
 		
 		if (isr & ISR_CNT) {
-			dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
-			dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
-			dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
-		}
-		
-		if (isr & ISR_OVW)
-			dep->de_stat.ets_OVW++;
-		
-		if (isr & ISR_RDC) {
-			/* Nothing to do */
+			ne2k->stats.receive_crc_errors +=
+			    pio_read_8(ne2k->port + DP_CNTR0);
+			ne2k->stats.receive_frame_errors +=
+			    pio_read_8(ne2k->port + DP_CNTR1);
+			ne2k->stats.receive_missed_errors +=
+			    pio_read_8(ne2k->port + DP_CNTR2);
 		}
 		
@@ -486,208 +628,21 @@
 			 * chip is shutdown. We set the flag 'stopped'
 			 * and continue processing arrived packets. When the
-			 * receive buffer is empty, we reset the dp8390.
+			 * receive buffer is empty, we reset the DP8390.
 			 */
-			dep->stopped = true;
-			break;
+			stopped = true;
 		}
 	}
 	
-	if (dep->stopped) {
+	if (stopped) {
 		/*
 		 * The chip is stopped, and all arrived
 		 * frames are delivered.
 		 */
-		dp_reset(dep);
-	}
-	
-	dep->sending = false;
-}
-
-static void dp_getblock(dpeth_t *dep, int page, size_t offset, size_t size, void *dst)
-{
-	offset = page * DP_PAGESIZE + offset;
-	
-	outb_reg0(dep, DP_RBCR0, size & 0xff);
-	outb_reg0(dep, DP_RBCR1, size >> 8);
-	outb_reg0(dep, DP_RSAR0, offset & 0xff);
-	outb_reg0(dep, DP_RSAR1, offset >> 8);
-	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
-	
-	if (dep->de_16bit) {
-		assert((size % 2) == 0);
-		insw(dep->de_data_port, dst, size);
-	} else
-		insb(dep->de_data_port, dst, size);
-}
-
-static void dp_recv(int nil_phone, device_id_t device_id, dpeth_t *dep)
-{
-	dp_rcvhdr_t header;
-	int pageno, curr, next;
-	size_t length;
-	int packet_processed, r;
-	uint16_t eth_type;
-	
-	packet_processed = false;
-	pageno = inb_reg0(dep, DP_BNRY) + 1;
-	if (pageno == dep->de_stoppage)
-		pageno = dep->de_startpage;
-	
-	do {
-		outb_reg0(dep, DP_CR, CR_PS_P1 | CR_EXTRA);
-		curr = inb_reg1(dep, DP_CURR);
-		outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
-		
-		if (curr == pageno)
-			break;
-		
-		dp_getblock(dep, pageno, (size_t) 0, sizeof(header), &header);
-		dp_getblock(dep, pageno, sizeof(header) +
-		    2 * sizeof(ether_addr_t), sizeof(eth_type), &eth_type);
-		
-		length = (header.dr_rbcl | (header.dr_rbch << 8)) - sizeof(dp_rcvhdr_t);
-		next = header.dr_next;
-		if ((length < ETH_MIN_PACK_SIZE) || (length > ETH_MAX_PACK_SIZE_TAGGED)) {
-			printf("Packet with strange length arrived: %zu\n", length);
-			next = curr;
-		} else if ((next < dep->de_startpage) || (next >= dep->de_stoppage)) {
-			printf("Strange next page\n");
-			next = curr;
-		} else if (header.dr_status & RSR_FO) {
-			/*
-			 * This is very serious, so we issue a warning and
-			 * reset the buffers
-			 */
-			printf("FIFO overrun, resetting receive buffer\n");
-			dep->de_stat.ets_fifoOver++;
-			next = curr;
-		} else if ((header.dr_status & RSR_PRX) && (dep->enabled)) {
-			r = dp_pkt2user(nil_phone, device_id, dep, pageno, length);
-			if (r != EOK)
-				return;
-			
-			packet_processed = true;
-			dep->de_stat.ets_packetR++;
-		}
-		
-		if (next == dep->de_startpage)
-			outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1);
-		else
-			outb_reg0(dep, DP_BNRY, next - 1);
-		
-		pageno = next;
-	} while (!packet_processed);
-}
-
-static void dp_nic2user(dpeth_t *dep, int nic_addr, void *buf, size_t offset, size_t size)
-{
-	size_t ecount = size & ~1;
-	
-	if (dep->de_16bit) {
-		outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
-		outb_reg0(dep, DP_RBCR1, ecount >> 8);
-	} else {
-		outb_reg0(dep, DP_RBCR0, size & 0xff);
-		outb_reg0(dep, DP_RBCR1, size >> 8);
-	}
-	
-	outb_reg0(dep, DP_RSAR0, nic_addr & 0xff);
-	outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
-	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
-	
-	if (dep->de_16bit) {
-		void *ptr = buf + offset;
-		
-		if (ecount != 0) {
-			insw(dep->de_data_port, ptr, ecount);
-			size -= ecount;
-			offset += ecount;
-			ptr += ecount;
-		}
-		
-		if (size) {
-			assert(size == 1);
-			
-			uint16_t two_bytes = inw(dep->de_data_port);
-			memcpy(ptr, &(((uint8_t *) &two_bytes)[0]), 1);
-		}
-	} else
-		insb(dep->de_data_port, buf + offset, size);
-}
-
-static int dp_pkt2user(int nil_phone, device_id_t device_id, dpeth_t *dep, int page, int length)
-{
-	int last, count;
-	packet_t *packet;
-	
-	packet = netif_packet_get_1(length);
-	if (!packet)
-		return ENOMEM;
-	
-	void *buf = packet_suffix(packet, length);
-	
-	last = page + (length - 1) / DP_PAGESIZE;
-	if (last >= dep->de_stoppage) {
-		count = (dep->de_stoppage - page) * DP_PAGESIZE - sizeof(dp_rcvhdr_t);
-		
-		dp_nic2user(dep, page * DP_PAGESIZE + sizeof(dp_rcvhdr_t),
-		    buf, 0, count);
-		dp_nic2user(dep, dep->de_startpage * DP_PAGESIZE,
-		    buf, count, length - count);
-	} else {
-		dp_nic2user(dep, page * DP_PAGESIZE + sizeof(dp_rcvhdr_t),
-		    buf, 0, length);
-	}
-	
-	nil_received_msg(nil_phone, device_id, packet, SERVICE_NONE);
-	
-	return EOK;
-}
-
-static void conf_hw(dpeth_t *dep)
-{
-	if (!ne_probe(dep)) {
-		printf("No ethernet card found at %#lx\n", dep->de_base_port);
-		dep->up = false;
-		return;
-	}
-	
-	dep->up = true;
-	dep->enabled = false;
-	dep->stopped = false;
-	dep->sending = false;
-	dep->send_avail = false;
-}
-
-static void insb(port_t port, void *buf, size_t size)
-{
-	size_t i;
-	
-	for (i = 0; i < size; i++)
-		*((uint8_t *) buf + i) = inb(port);
-}
-
-static void insw(port_t port, void *buf, size_t size)
-{
-	size_t i;
-	
-	for (i = 0; i * 2 < size; i++)
-		*((uint16_t *) buf + i) = inw(port);
-}
-
-static void outsb(port_t port, void *buf, size_t size)
-{
-	size_t i;
-	
-	for (i = 0; i < size; i++)
-		outb(port, *((uint8_t *) buf + i));
-}
-
-static void outsw(port_t port, void *buf, size_t size)
-{
-	size_t i;
-	
-	for (i = 0; i * 2 < size; i++)
-		outw(port, *((uint16_t *) buf + i));
+		ne2k_reset(ne2k);
+	}
+	
+	/* Signal a next frame to be sent */
+	if (signal)
+		fibril_condvar_broadcast(&ne2k->sq_cv);
 }
 
Index: uspace/srv/hw/netif/dp8390/dp8390.h
===================================================================
--- uspace/srv/hw/netif/dp8390/dp8390.h	(revision 7ea7db31d35d3bcb84a5f1220696fa0c75b775c3)
+++ uspace/srv/hw/netif/dp8390/dp8390.h	(revision 3c106e8814a50268257db9a33c79a75e51e871ec)
@@ -38,5 +38,5 @@
  */
 
-/** @addtogroup dp8390
+/** @addtogroup ne2000
  *  @{
  */
@@ -49,9 +49,15 @@
 #define __NET_NETIF_DP8390_H__
 
+#include <fibril_synch.h>
 #include <net/packet.h>
-#include "dp8390_port.h"
+
+/** Module name */
+#define NAME  "ne2000"
 
 /** Input/output size */
-#define DP8390_IO_SIZE  0x0020
+#define NE2K_IO_SIZE  0x0020
+
+/** Ethernet address length */
+#define ETH_ADDR  6
 
 /* National Semiconductor DP8390 Network Interface Controller. */
@@ -105,187 +111,128 @@
 #define DP_MAR7  0x0f  /**< Multicast Address Register 7 */
 
-/* Bits in dp_cr */
-#define CR_STP		0x01	/* Stop: software reset              */
-#define CR_STA		0x02	/* Start: activate NIC               */
-#define CR_TXP		0x04	/* Transmit Packet                   */
-#define CR_DMA		0x38	/* Mask for DMA control              */
-#define CR_DM_NOP	0x00	/* DMA: No Operation                 */
-#define CR_DM_RR	0x08	/* DMA: Remote Read                  */
-#define CR_DM_RW	0x10	/* DMA: Remote Write                 */
-#define CR_DM_SP	0x18	/* DMA: Send Packet                  */
-#define CR_DM_ABORT	0x20	/* DMA: Abort Remote DMA Operation   */
-#define CR_PS		0xC0	/* Mask for Page Select              */
-#define CR_PS_P0	0x00	/* Register Page 0                   */
-#define CR_PS_P1	0x40	/* Register Page 1                   */
-#define CR_PS_P2	0x80	/* Register Page 2                   */
-#define CR_PS_T1	0xC0	/* Test Mode Register Map            */
-
-/* Bits in dp_isr */
-#define ISR_PRX		0x01	/* Packet Received with no errors    */
-#define ISR_PTX		0x02	/* Packet Transmitted with no errors */
-#define ISR_RXE		0x04	/* Receive Error                     */
-#define ISR_TXE		0x08	/* Transmit Error                    */
-#define ISR_OVW		0x10	/* Overwrite Warning                 */
-#define ISR_CNT		0x20	/* Counter Overflow                  */
-#define ISR_RDC		0x40	/* Remote DMA Complete               */
-#define ISR_RST		0x80	/* Reset Status                      */
-
-/* Bits in dp_imr */
-#define IMR_PRXE	0x01	/* Packet Received iEnable           */
-#define IMR_PTXE	0x02	/* Packet Transmitted iEnable        */
-#define IMR_RXEE	0x04	/* Receive Error iEnable             */
-#define IMR_TXEE	0x08	/* Transmit Error iEnable            */
-#define IMR_OVWE	0x10	/* Overwrite Warning iEnable         */
-#define IMR_CNTE	0x20	/* Counter Overflow iEnable          */
-#define IMR_RDCE	0x40	/* DMA Complete iEnable              */
-
-/* Bits in dp_dcr */
-#define DCR_WTS		0x01	/* Word Transfer Select              */
-#define DCR_BYTEWIDE	0x00	/* WTS: byte wide transfers          */
-#define DCR_WORDWIDE	0x01	/* WTS: word wide transfers          */
-#define DCR_BOS		0x02	/* Byte Order Select                 */
-#define DCR_LTLENDIAN	0x00	/* BOS: Little Endian                */
-#define DCR_BIGENDIAN	0x02	/* BOS: Big Endian                   */
-#define DCR_LAS		0x04	/* Long Address Select               */
-#define DCR_BMS		0x08	/* Burst Mode Select
-				 * Called Loopback Select (LS) in 
-				 * later manuals. Should be set.     */
-#define DCR_AR		0x10	/* Autoinitialize Remote             */
-#define DCR_FTS		0x60	/* Fifo Threshold Select             */
-#define DCR_2BYTES	0x00	/* 2 bytes                           */
-#define DCR_4BYTES	0x40	/* 4 bytes                           */
-#define DCR_8BYTES	0x20	/* 8 bytes                           */
-#define DCR_12BYTES	0x60	/* 12 bytes                          */
-
-/* Bits in dp_tcr */
-#define TCR_CRC		0x01	/* Inhibit CRC                       */
-#define TCR_ELC		0x06	/* Encoded Loopback Control          */
-#define TCR_NORMAL	0x00	/* ELC: Normal Operation             */
-#define TCR_INTERNAL	0x02	/* ELC: Internal Loopback            */
-#define TCR_0EXTERNAL	0x04	/* ELC: External Loopback LPBK=0     */
-#define TCR_1EXTERNAL	0x06	/* ELC: External Loopback LPBK=1     */
-#define TCR_ATD		0x08	/* Auto Transmit Disable             */
-#define TCR_OFST	0x10	/* Collision Offset Enable (be nice) */
-
-/* Bits in dp_tsr */
-#define TSR_PTX		0x01	/* Packet Transmitted (without error)*/
-#define TSR_DFR		0x02	/* Transmit Deferred, reserved in
-				 * later manuals.		     */
-#define TSR_COL		0x04	/* Transmit Collided                 */
-#define TSR_ABT		0x08	/* Transmit Aborted                  */
-#define TSR_CRS		0x10	/* Carrier Sense Lost                */
-#define TSR_FU		0x20	/* FIFO Underrun                     */
-#define TSR_CDH		0x40	/* CD Heartbeat                      */
-#define TSR_OWC		0x80	/* Out of Window Collision           */
-
-/* Bits in tp_rcr */
-#define RCR_SEP		0x01	/* Save Errored Packets              */
-#define RCR_AR		0x02	/* Accept Runt Packets               */
-#define RCR_AB		0x04	/* Accept Broadcast                  */
-#define RCR_AM		0x08	/* Accept Multicast                  */
-#define RCR_PRO		0x10	/* Physical Promiscuous              */
-#define RCR_MON		0x20	/* Monitor Mode                      */
-
-/* Bits in dp_rsr */
-#define RSR_PRX		0x01	/* Packet Received Intact            */
-#define RSR_CRC		0x02	/* CRC Error                         */
-#define RSR_FAE		0x04	/* Frame Alignment Error             */
-#define RSR_FO		0x08	/* FIFO Overrun                      */
-#define RSR_MPA		0x10	/* Missed Packet                     */
-#define RSR_PHY		0x20	/* Multicast Address Match           */
-#define RSR_DIS		0x40	/* Receiver Disabled                 */
-#define RSR_DFR		0x80	/* In later manuals: Deferring       */
-
-/** Type definition of the receive header
- *
- */
-typedef struct dp_rcvhdr {
-	/** Copy of rsr */
-	uint8_t dr_status;
-	
-	/** Pointer to next packet */
-	uint8_t dr_next;
-	
-	/** Receive Byte Count Low */
-	uint8_t dr_rbcl;
-	
-	/** Receive Byte Count High */
-	uint8_t dr_rbch;
-} dp_rcvhdr_t;
-
-/** Page size */
-#define DP_PAGESIZE  256
-
-/** Read 1 byte from the zero page register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @returns The read value.
- */
-#define inb_reg0(dep, reg)  (inb(dep->de_dp8390_port + reg))
-
-/** Write 1 byte zero page register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @param[in] data The value to be written.
- */
-#define outb_reg0(dep, reg, data)  (outb(dep->de_dp8390_port + reg, data))
-
-/** Read 1 byte from the first page register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @returns The read value.
- */
-#define inb_reg1(dep, reg)  (inb(dep->de_dp8390_port + reg))
-
-/** Write 1 byte first page register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @param[in] data The value to be written.
- */
-#define outb_reg1(dep, reg, data)  (outb(dep->de_dp8390_port + reg, data))
-
-#define SENDQ_NR     1  /* Maximum size of the send queue */
-#define SENDQ_PAGES  6  /* 6 * DP_PAGESIZE >= 1514 bytes */
-
-typedef struct dpeth {
-	/*
-	 * The de_base_port field is the starting point of the probe.
-	 * The conf routine also fills de_irq. If the probe
-	 * routine knows the irq and/or memory address because they are
-	 * hardwired in the board, the probe should modify these fields.
-	 */
-	port_t de_base_port;
-	int de_irq;
-	
-	ether_addr_t de_address;
-	port_t de_dp8390_port;
-	port_t de_data_port;
-	int de_16bit;
-	long de_ramsize;
-	int de_offset_page;
-	int de_startpage;
-	int de_stoppage;
-	
-	/* Do it yourself send queue */
-	struct sendq {
-		int sq_filled;    /* this buffer contains a packet */
-		int sq_size;      /* with this size */
-		int sq_sendpage;  /* starting page of the buffer */
-	} de_sendq[SENDQ_NR];
-	
-	int de_sendq_nr;
-	int de_sendq_head;  /* Enqueue at the head */
-	int de_sendq_tail;  /* Dequeue at the tail */
-	
-	/* Fields for internal use by the dp8390 driver. */
-	eth_stat_t de_stat;
-	
-	/* Driver flags */
+/* Bits in Command Register */
+#define CR_STP       0x01  /**< Stop (software reset) */
+#define CR_STA       0x02  /**< Start (activate NIC) */
+#define CR_TXP       0x04  /**< Transmit Packet */
+#define CR_DMA       0x38  /**< Mask for DMA control */
+#define CR_DM_NOP    0x00  /**< DMA: No Operation */
+#define CR_DM_RR     0x08  /**< DMA: Remote Read */
+#define CR_DM_RW     0x10  /**< DMA: Remote Write */
+#define CR_DM_SP     0x18  /**< DMA: Send Packet */
+#define CR_DM_ABORT  0x20  /**< DMA: Abort Remote DMA Operation */
+#define CR_PS        0xc0  /**< Mask for Page Select */
+#define CR_PS_P0     0x00  /**< Register Page 0 */
+#define CR_PS_P1     0x40  /**< Register Page 1 */
+#define CR_PS_P2     0x80  /**< Register Page 2 */
+#define CR_PS_T1     0xc0  /**< Test Mode Register Map */
+
+/* Bits in Interrupt State Register */
+#define ISR_PRX  0x01  /**< Packet Received with no errors */
+#define ISR_PTX  0x02  /**< Packet Transmitted with no errors */
+#define ISR_RXE  0x04  /**< Receive Error */
+#define ISR_TXE  0x08  /**< Transmit Error */
+#define ISR_OVW  0x10  /**< Overwrite Warning */
+#define ISR_CNT  0x20  /**< Counter Overflow */
+#define ISR_RDC  0x40  /**< Remote DMA Complete */
+#define ISR_RST  0x80  /**< Reset Status */
+
+/* Bits in Interrupt Mask Register */
+#define IMR_PRXE  0x01  /**< Packet Received Interrupt Enable */
+#define IMR_PTXE  0x02  /**< Packet Transmitted Interrupt Enable */
+#define IMR_RXEE  0x04  /**< Receive Error Interrupt Enable */
+#define IMR_TXEE  0x08  /**< Transmit Error Interrupt Enable */
+#define IMR_OVWE  0x10  /**< Overwrite Warning Interrupt Enable */
+#define IMR_CNTE  0x20  /**< Counter Overflow Interrupt Enable */
+#define IMR_RDCE  0x40  /**< DMA Complete Interrupt Enable */
+
+/* Bits in Data Configuration Register */
+#define DCR_WTS        0x01  /**< Word Transfer Select */
+#define DCR_BYTEWIDE   0x00  /**< WTS: byte wide transfers */
+#define DCR_WORDWIDE   0x01  /**< WTS: word wide transfers */
+#define DCR_BOS        0x02  /**< Byte Order Select */
+#define DCR_LTLENDIAN  0x00  /**< BOS: Little Endian */
+#define DCR_BIGENDIAN  0x02  /**< BOS: Big Endian */
+#define DCR_LAS        0x04  /**< Long Address Select */
+#define DCR_BMS        0x08  /**< Burst Mode Select */
+#define DCR_AR         0x10  /**< Autoinitialize Remote */
+#define DCR_FTS        0x60  /**< Fifo Threshold Select */
+#define DCR_2BYTES     0x00  /**< 2 bytes */
+#define DCR_4BYTES     0x40  /**< 4 bytes */
+#define DCR_8BYTES     0x20  /**< 8 bytes */
+#define DCR_12BYTES    0x60  /**< 12 bytes */
+
+/* Bits in Transmit Configuration Register */
+#define TCR_CRC        0x01  /**< Inhibit CRC */
+#define TCR_ELC        0x06  /**< Encoded Loopback Control */
+#define TCR_NORMAL     0x00  /**< ELC: Normal Operation */
+#define TCR_INTERNAL   0x02  /**< ELC: Internal Loopback */
+#define TCR_0EXTERNAL  0x04  /**< ELC: External Loopback LPBK=0 */
+#define TCR_1EXTERNAL  0x06  /**< ELC: External Loopback LPBK=1 */
+#define TCR_ATD        0x08  /**< Auto Transmit Disable */
+#define TCR_OFST       0x10  /**< Collision Offset Enable (be nice) */
+
+/* Bits in Interrupt Status Register */
+#define TSR_PTX  0x01  /**< Packet Transmitted (without error) */
+#define TSR_DFR  0x02  /**< Transmit Deferred (reserved) */
+#define TSR_COL  0x04  /**< Transmit Collided */
+#define TSR_ABT  0x08  /**< Transmit Aborted */
+#define TSR_CRS  0x10  /**< Carrier Sense Lost */
+#define TSR_FU   0x20  /**< FIFO Underrun */
+#define TSR_CDH  0x40  /**< CD Heartbeat */
+#define TSR_OWC  0x80  /**< Out of Window Collision */
+
+/* Bits in Receive Configuration Register */
+#define RCR_SEP  0x01  /**< Save Errored Packets */
+#define RCR_AR   0x02  /**< Accept Runt Packets */
+#define RCR_AB   0x04  /**< Accept Broadcast */
+#define RCR_AM   0x08  /**< Accept Multicast */
+#define RCR_PRO  0x10  /**< Physical Promiscuous */
+#define RCR_MON  0x20  /**< Monitor Mode */
+
+/* Bits in Receive Status Register */
+#define RSR_PRX  0x01  /**< Packet Received Intact */
+#define RSR_CRC  0x02  /**< CRC Error */
+#define RSR_FAE  0x04  /**< Frame Alignment Error */
+#define RSR_FO   0x08  /**< FIFO Overrun */
+#define RSR_MPA  0x10  /**< Missed Packet */
+#define RSR_PHY  0x20  /**< Multicast Address Match */
+#define RSR_DIS  0x40  /**< Receiver Disabled */
+#define RSR_DFR  0x80  /**< In later manuals: Deferring */
+
+typedef struct {
+	/* Device configuration */
+	void *port;
+	void *data_port;
+	int irq;
+	uint8_t mac[ETH_ADDR];
+	
+	uint8_t start_page;  /**< Ring buffer start page */
+	uint8_t stop_page;   /**< Ring buffer stop page */
+	
+	/* Send queue */
+	struct {
+		bool dirty;    /**< Buffer contains a packet */
+		size_t size;   /**< Packet size */
+		uint8_t page;  /**< Starting page of the buffer */
+	} sq;
+	fibril_mutex_t sq_mutex;
+	fibril_condvar_t sq_cv;
+	
+	/* Driver run-time variables */
+	bool probed;
 	bool up;
-	bool enabled;
-	bool stopped;
-	bool sending;
-	bool send_avail;
-} dpeth_t;
+	
+	/* Device statistics */
+	device_stats_t stats;
+	uint64_t misses;     /**< Receive frame misses */
+	uint64_t underruns;  /**< FIFO underruns */
+	uint64_t overruns;   /**< FIFO overruns */
+} ne2k_t;
+
+extern int ne2k_probe(ne2k_t *, void *, int);
+extern int ne2k_up(ne2k_t *);
+extern void ne2k_down(ne2k_t *);
+extern void ne2k_send(ne2k_t *, packet_t *);
+extern void ne2k_interrupt(ne2k_t *, uint8_t isr, int, device_id_t);
 
 #endif
Index: uspace/srv/hw/netif/dp8390/dp8390_drv.h
===================================================================
--- uspace/srv/hw/netif/dp8390/dp8390_drv.h	(revision 7ea7db31d35d3bcb84a5f1220696fa0c75b775c3)
+++ 	(revision )
@@ -1,72 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - 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.
- * - 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.
- */
-
-/** @addtogroup dp8390
- *  @{
- */
-
-/** @file
- *  DP8390 network interface driver interface.
- */
-
-#ifndef __NET_NETIF_DP8390_DRIVER_H__
-#define __NET_NETIF_DP8390_DRIVER_H__
-
-#include "dp8390.h"
-
-int do_init(dpeth_t *dep);
-
-/** Stops the network interface.
- *  @param[in,out] dep The network interface structure.
- */
-void do_stop(dpeth_t *dep);
-
-/** Processes the interrupt.
- *  @param[in,out] dep The network interface structure.
- */
-void dp_check_ints(int nil_phone, device_id_t device_id, dpeth_t *dep, uint8_t isr);
-
-/** Probes and initializes the network interface.
- *  @param[in,out] dep The network interface structure.
- *  @returns EOK on success.
- *  @returns EXDEV if the network interface was not recognized.
- */
-int do_probe(dpeth_t * dep);
-
-/** Sends a packet.
- *  @param[in,out] dep The network interface structure.
- *  @param[in] packet The packet t be sent.
- *  @param[in] from_int The value indicating whether the sending is initialized from the interrupt handler.
- *  @returns
- */
-int do_pwrite(dpeth_t * dep, packet_t *packet, int from_int);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/hw/netif/dp8390/dp8390_module.c
===================================================================
--- uspace/srv/hw/netif/dp8390/dp8390_module.c	(revision 7ea7db31d35d3bcb84a5f1220696fa0c75b775c3)
+++ 	(revision )
@@ -1,424 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - 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.
- * - 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.
- */
-
-/** @addtogroup dp8390
- *  @{
- */
-
-/** @file
- *  DP8390 network interface implementation.
- */
-
-#include <assert.h>
-#include <async.h>
-#include <ddi.h>
-#include <errno.h>
-#include <err.h>
-#include <malloc.h>
-#include <sysinfo.h>
-#include <ipc/ipc.h>
-#include <ipc/services.h>
-#include <ipc/irc.h>
-#include <net/modules.h>
-#include <packet_client.h>
-#include <adt/measured_strings.h>
-#include <net/device.h>
-#include <nil_interface.h>
-#include <netif_interface.h>
-#include <netif_local.h>
-#include "dp8390.h"
-#include "dp8390_drv.h"
-#include "dp8390_port.h"
-
-/** DP8390 module name.
- */
-#define NAME  "dp8390"
-
-/** Return the device from the interrupt call.
- *
- *  @param[in] call The interrupt call.
- *
- */
-#define IRQ_GET_DEVICE(call)  ((device_id_t) IPC_GET_IMETHOD(call))
-
-/** Return the ISR from the interrupt call.
- *
- *  @param[in] call The interrupt call.
- *
- */
-#define IRQ_GET_ISR(call)  ((int) IPC_GET_ARG2(call))
-
-static int irc_service = 0;
-static int irc_phone = -1;
-
-/** DP8390 kernel interrupt command sequence.
- */
-static irq_cmd_t dp8390_cmds[] = {
-	{
-		.cmd = CMD_PIO_READ_8,
-		.addr = NULL,
-		.dstarg = 2
-	},
-	{
-		.cmd = CMD_BTEST,
-		.value = 0x7f,
-		.srcarg = 2,
-		.dstarg = 3,
-	},
-	{
-		.cmd = CMD_PREDICATE,
-		.value = 2,
-		.srcarg = 3
-	},
-	{
-		.cmd = CMD_PIO_WRITE_A_8,
-		.addr = NULL,
-		.srcarg = 3
-	},
-	{
-		.cmd = CMD_ACCEPT
-	}
-};
-
-/** DP8390 kernel interrupt code.
- */
-static irq_code_t dp8390_code = {
-	sizeof(dp8390_cmds) / sizeof(irq_cmd_t),
-	dp8390_cmds
-};
-
-/** Handles the interrupt messages.
- *  This is the interrupt handler callback function.
- *  @param[in] iid The interrupt message identifier.
- *  @param[in] call The interrupt message.
- */
-static void irq_handler(ipc_callid_t iid, ipc_call_t *call)
-{
-	device_id_t device_id = IRQ_GET_DEVICE(*call);
-	netif_device_t *device;
-	int nil_phone;
-	dpeth_t *dep;
-	
-	fibril_rwlock_write_lock(&netif_globals.lock);
-	
-	if (find_device(device_id, &device) == EOK) {
-		nil_phone = device->nil_phone;
-		dep = (dpeth_t *) device->specific;
-	} else
-		dep = NULL;
-	
-	fibril_rwlock_write_unlock(&netif_globals.lock);
-	
-	if ((dep != NULL) && (dep->up)) {
-		assert(dep->enabled);
-		dp_check_ints(nil_phone, device_id, dep, IRQ_GET_ISR(*call));
-	}
-}
-
-/** Change the network interface state.
- *
- *  @param[in,out] device The network interface.
- *  @param[in]     state  The new state.
- *
- *  @return The new state.
- *
- */
-static int change_state(netif_device_t *device, device_state_t state)
-{
-	if (device->state != state) {
-		device->state = state;
-		
-		printf("%s: State changed to %s\n", NAME,
-		    (state == NETIF_ACTIVE) ? "active" : "stopped");
-		
-		return state;
-	}
-	
-	return EOK;
-}
-
-int netif_specific_message(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, int *answer_count)
-{
-	return ENOTSUP;
-}
-
-int netif_get_device_stats(device_id_t device_id, device_stats_t *stats)
-{
-	netif_device_t * device;
-	eth_stat_t * de_stat;
-	int rc;
-	
-	if (!stats)
-		return EBADMEM;
-	
-	rc = find_device(device_id, &device);
-	if (rc != EOK)
-		return rc;
-	
-	de_stat = &((dpeth_t *) device->specific)->de_stat;
-	
-	null_device_stats(stats);
-	stats->receive_errors = de_stat->ets_recvErr;
-	stats->send_errors = de_stat->ets_sendErr;
-	stats->receive_crc_errors = de_stat->ets_CRCerr;
-	stats->receive_frame_errors = de_stat->ets_frameAll;
-	stats->receive_missed_errors = de_stat->ets_missedP;
-	stats->receive_packets = de_stat->ets_packetR;
-	stats->send_packets = de_stat->ets_packetT;
-	stats->collisions = de_stat->ets_collision;
-	stats->send_aborted_errors = de_stat->ets_transAb;
-	stats->send_carrier_errors = de_stat->ets_carrSense;
-	stats->send_heartbeat_errors = de_stat->ets_CDheartbeat;
-	stats->send_window_errors = de_stat->ets_OWC;
-	
-	return EOK;
-}
-
-int netif_get_addr_message(device_id_t device_id, measured_string_t *address)
-{
-	netif_device_t *device;
-	int rc;
-	
-	if (!address)
-		return EBADMEM;
-	
-	rc = find_device(device_id, &device);
-	if (rc != EOK)
-		return rc;
-	
-	address->value = (uint8_t *) &((dpeth_t *) device->specific)->de_address;
-	address->length = sizeof(ether_addr_t);
-	return EOK;
-}
-
-int netif_probe_message(device_id_t device_id, int irq, uintptr_t io)
-{
-	netif_device_t *device;
-	dpeth_t *dep;
-	int rc;
-	
-	device = (netif_device_t *) malloc(sizeof(netif_device_t));
-	if (!device)
-		return ENOMEM;
-	
-	dep = (dpeth_t *) malloc(sizeof(dpeth_t));
-	if (!dep) {
-		free(device);
-		return ENOMEM;
-	}
-	
-	bzero(device, sizeof(netif_device_t));
-	bzero(dep, sizeof(dpeth_t));
-	device->device_id = device_id;
-	device->nil_phone = -1;
-	device->specific = (void *) dep;
-	device->state = NETIF_STOPPED;
-	dep->de_irq = irq;
-	dep->up = false;
-	
-	//TODO address?
-	rc = pio_enable((void *) io, DP8390_IO_SIZE, (void **) &dep->de_base_port);
-	if (rc != EOK) {
-		free(dep);
-		free(device);
-		return rc;
-	}
-	
-	rc = do_probe(dep);
-	if (rc != EOK) {
-		free(dep);
-		free(device);
-		return rc;
-	}
-	
-	rc = netif_device_map_add(&netif_globals.device_map, device->device_id, device);
-	if (rc != EOK) {
-		free(dep);
-		free(device);
-		return rc;
-	}
-	
-	return EOK;
-}
-
-int netif_send_message(device_id_t device_id, packet_t *packet,
-    services_t sender)
-{
-	netif_device_t *device;
-	dpeth_t *dep;
-	packet_t *next;
-	int rc;
-	
-	rc = find_device(device_id, &device);
-	if (rc != EOK)
-		return rc;
-	
-	if (device->state != NETIF_ACTIVE) {
-		netif_pq_release(packet_get_id(packet));
-		return EFORWARD;
-	}
-	
-	dep = (dpeth_t *) device->specific;
-	
-	/* Process packet queue */
-	do {
-		next = pq_detach(packet);
-		
-		if (do_pwrite(dep, packet, false) != EBUSY)
-			netif_pq_release(packet_get_id(packet));
-		
-		packet = next;
-	} while (packet);
-	
-	return EOK;
-}
-
-int netif_start_message(netif_device_t * device)
-{
-	dpeth_t *dep;
-	int rc;
-	
-	if (device->state != NETIF_ACTIVE) {
-		dep = (dpeth_t *) device->specific;
-		dp8390_cmds[0].addr = (void *) (uintptr_t) (dep->de_dp8390_port + DP_ISR);
-		dp8390_cmds[3].addr = dp8390_cmds[0].addr;
-		
-		rc = ipc_register_irq(dep->de_irq, device->device_id, device->device_id, &dp8390_code);
-		if (rc != EOK)
-			return rc;
-		
-		rc = do_init(dep);
-		if (rc != EOK) {
-			ipc_unregister_irq(dep->de_irq, device->device_id);
-			return rc;
-		}
-		
-		rc = change_state(device, NETIF_ACTIVE);
-		
-		if (irc_service)
-			async_msg_1(irc_phone, IRC_ENABLE_INTERRUPT, dep->de_irq);
-		
-		return rc;
-	}
-	
-	return EOK;
-}
-
-int netif_stop_message(netif_device_t * device)
-{
-	dpeth_t *dep;
-	
-	if (device->state != NETIF_STOPPED) {
-		dep = (dpeth_t *) device->specific;
-		do_stop(dep);
-		ipc_unregister_irq(dep->de_irq, device->device_id);
-		return change_state(device, NETIF_STOPPED);
-	}
-	
-	return EOK;
-}
-
-int netif_initialize(void)
-{
-	sysarg_t apic;
-	sysarg_t i8259;
-	
-	if ((sysinfo_get_value("apic", &apic) == EOK) && (apic))
-		irc_service = SERVICE_APIC;
-	else if ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259))
-		irc_service = SERVICE_I8259;
-	
-	if (irc_service) {
-		while (irc_phone < 0) {
-			irc_phone = ipc_connect_me_to_blocking(PHONE_NS, irc_service,
-			    0, 0);
-		}
-	}
-	
-	async_set_interrupt_received(irq_handler);
-	
-	sysarg_t phonehash;
-	return ipc_connect_to_me(PHONE_NS, SERVICE_DP8390, 0, 0, &phonehash);
-}
-
-/** Default thread for new connections.
- *
- *  @param[in] iid The initial message identifier.
- *  @param[in] icall The initial message call structure.
- *
- */
-static void netif_client_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/*
-	 * Accept the connection
-	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
-	 */
-	ipc_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t answer;
-		int answer_count;
-		
-		/* Clear the answer structure */
-		refresh_answer(&answer, &answer_count);
-		
-		/* Fetch the next message */
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		/* Process the message */
-		int res = netif_module_message(NAME, callid, &call, &answer,
-		    &answer_count);
-		
-		/* End if said to either by the message or the processing result */
-		if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
-			return;
-		
-		/* Answer the message */
-		answer_call(callid, res, &answer, answer_count);
-	}
-}
-
-/** Start the module.
- *
- *  @param argc The count of the command line arguments. Ignored parameter.
- *  @param argv The command line parameters. Ignored parameter.
- *
- *  @returns EOK on success.
- *  @returns Other error codes as defined for each specific module start function.
- *
- */
-int main(int argc, char *argv[])
-{
-	/* Start the module */
-	return netif_module_start(netif_client_connection);
-}
-
-/** @}
- */
Index: uspace/srv/hw/netif/dp8390/dp8390_port.h
===================================================================
--- uspace/srv/hw/netif/dp8390/dp8390_port.h	(revision 7ea7db31d35d3bcb84a5f1220696fa0c75b775c3)
+++ 	(revision )
@@ -1,146 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - 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.
- * - 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.
- */
-
-/** @addtogroup dp8390
- *  @{
- */
-
-/** @file
- *  DP8390 network interface types and structures ports.
- */
-
-#ifndef __NET_NETIF_DP8390_PORT_H__
-#define __NET_NETIF_DP8390_PORT_H__
-
-#include <errno.h>
-#include <mem.h>
-#include <stdio.h>
-#include <libarch/ddi.h>
-#include <sys/types.h>
-
-/** Reads 1 byte.
- *  @param[in] port The address to be read.
- *  @returns The read value.
- */
-#define inb(port)  pio_read_8((ioport8_t *) (port))
-
-/** Reads 1 word (2 bytes).
- *  @param[in] port The address to be read.
- *  @returns The read value.
- */
-#define inw(port)  pio_read_16((ioport16_t *) (port))
-
-/** Writes 1 byte.
- *  @param[in] port The address to be written.
- *  @param[in] value The value to be written.
- */
-#define outb(port, value)  pio_write_8((ioport8_t *) (port), (value))
-
-/** Writes 1 word (2 bytes).
- *  @param[in] port The address to be written.
- *  @param[in] value The value to be written.
- */
-#define outw(port, value)  pio_write_16((ioport16_t *) (port), (value))
-
-/** Type definition of a port.
- */
-typedef long port_t;
-
-/** Ethernet statistics.
- */
-typedef struct eth_stat {
-	/** Number of receive errors.
-	 */
-	unsigned long ets_recvErr;
-	/** Number of send error.
-	 */
-	unsigned long ets_sendErr;
-	/** Number of buffer overwrite warnings.
-	 */
-	unsigned long ets_OVW;
-	/** Number of crc errors of read.
-	 */
-	unsigned long ets_CRCerr;
-	/** Number of frames not alligned (number of bits % 8 != 0).
-	 */
-	unsigned long ets_frameAll;
-	/** Number of packets missed due to slow processing.
-	 */
-	unsigned long ets_missedP;
-	/** Number of packets received.
-	 */
-	unsigned long ets_packetR;
-	/** Number of packets transmitted.
-	 */
-	unsigned long ets_packetT;
-	/** Number of transmission defered (Tx was busy).
-	 */
-	unsigned long ets_transDef;
-	/** Number of collissions.
-	 */
-	unsigned long ets_collision;
-	/** Number of Tx aborted due to excess collisions.
-	 */
-	unsigned long ets_transAb;
-	/** Number of carrier sense lost.
-	 */
-	unsigned long ets_carrSense;
-	/** Number of FIFO underruns (processor too busy).
-	 */
-	unsigned long ets_fifoUnder;
-	/** Number of FIFO overruns (processor too busy).
-	 */
-	unsigned long ets_fifoOver;
-	/** Number of times unable to transmit collision sig.
-	 */
-	unsigned long ets_CDheartbeat;
-	/** Number of times out of window collision.
-	 */
-	unsigned long ets_OWC;
-} eth_stat_t;
-
-/** Minimum Ethernet packet size in bytes.
- */
-#define ETH_MIN_PACK_SIZE  60
-
-/** Maximum Ethernet packet size in bytes.
- */
-#define ETH_MAX_PACK_SIZE_TAGGED  1518
-
-/** Ethernet address type definition.
- */
-typedef struct ether_addr {
-	/** Address data.
-	 */
-	uint8_t ea_addr[6];
-} ether_addr_t;
-
-#endif
-
-/** @}
- */
Index: uspace/srv/hw/netif/dp8390/ne2000.c
===================================================================
--- uspace/srv/hw/netif/dp8390/ne2000.c	(revision 7ea7db31d35d3bcb84a5f1220696fa0c75b775c3)
+++ uspace/srv/hw/netif/dp8390/ne2000.c	(revision 3c106e8814a50268257db9a33c79a75e51e871ec)
@@ -28,270 +28,332 @@
  */
 
-/*
- * This code is based upon the NE2000 driver for MINIX,
- * distributed according to a BSD-style license.
- *
- * Copyright (c) 1987, 1997, 2006 Vrije Universiteit
- * Copyright (c) 1992, 1994 Philip Homburg
- * Copyright (c) 1996 G. Falzoni
- *
- */
-
-/** @addtogroup ne2k
+/** @addtogroup ne2000
  *  @{
  */
 
 /** @file
- *  NE1000 and NE2000 network interface initialization and probe functions implementation.
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include "dp8390_port.h"
+ *  NE2000 network interface implementation.
+ */
+
+#include <assert.h>
+#include <async.h>
+#include <ddi.h>
+#include <errno.h>
+#include <err.h>
+#include <malloc.h>
+#include <sysinfo.h>
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+#include <ipc/irc.h>
+#include <net/modules.h>
+#include <packet_client.h>
+#include <adt/measured_strings.h>
+#include <net/device.h>
+#include <netif_skel.h>
+#include <nil_interface.h>
 #include "dp8390.h"
-#include "ne2000.h"
-
-/** Number of bytes to transfer */
-#define N  100
-
-typedef int (*testf_t)(dpeth_t *dep, int pos, uint8_t *pat);
-
-/** Data patterns */
-uint8_t pat0[] = {0x00, 0x00, 0x00, 0x00};
-uint8_t pat1[] = {0xFF, 0xFF, 0xFF, 0xFF};
-uint8_t pat2[] = {0xA5, 0x5A, 0x69, 0x96};
-uint8_t pat3[] = {0x96, 0x69, 0x5A, 0xA5};
-
-/** Tests 8 bit NE2000 network interface.
- *  @param[in,out] dep The network interface structure.
- *  @param[in] pos The starting position.
- *  @param[in] pat The data pattern to be written.
- *  @returns True on success.
- *  @returns false otherwise.
- */
-static int test_8(dpeth_t *dep, int pos, uint8_t *pat);
-
-/** Tests 16 bit NE2000 network interface.
- *  @param[in,out] dep The network interface structure.
- *  @param[in] pos The starting position.
- *  @param[in] pat The data pattern to be written.
- *  @returns True on success.
- *  @returns false otherwise.
- */
-static int test_16(dpeth_t *dep, int pos, uint8_t *pat);
-
-int ne_probe(dpeth_t *dep)
-{
-	int byte;
-	int i;
-	int loc1, loc2;
-	testf_t f;
-	
-	dep->de_dp8390_port = dep->de_base_port + NE_DP8390;
+
+/** Return the device from the interrupt call.
+ *
+ *  @param[in] call The interrupt call.
+ *
+ */
+#define IRQ_GET_DEVICE(call)  ((device_id_t) IPC_GET_IMETHOD(call))
+
+/** Return the ISR from the interrupt call.
+ *
+ * @param[in] call The interrupt call.
+ *
+ */
+#define IRQ_GET_ISR(call)  ((int) IPC_GET_ARG2(call))
+
+static int irc_service = 0;
+static int irc_phone = -1;
+
+/** DP8390 kernel interrupt command sequence.
+ *
+ */
+static irq_cmd_t ne2k_cmds[] = {
+	{
+		.cmd = CMD_PIO_READ_8,
+		.addr = NULL,
+		.dstarg = 2
+	},
+	{
+		.cmd = CMD_BTEST,
+		.value = 0x7f,
+		.srcarg = 2,
+		.dstarg = 3,
+	},
+	{
+		.cmd = CMD_PREDICATE,
+		.value = 2,
+		.srcarg = 3
+	},
+	{
+		.cmd = CMD_PIO_WRITE_A_8,
+		.addr = NULL,
+		.srcarg = 3
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
+
+/** DP8390 kernel interrupt code.
+ *
+ */
+static irq_code_t ne2k_code = {
+	sizeof(ne2k_cmds) / sizeof(irq_cmd_t),
+	ne2k_cmds
+};
+
+/** Handle the interrupt notification.
+ *
+ * This is the interrupt notification function.
+ *
+ * @param[in] iid  Interrupt notification identifier.
+ * @param[in] call Interrupt notification.
+ *
+ */
+static void irq_handler(ipc_callid_t iid, ipc_call_t *call)
+{
+	device_id_t device_id = IRQ_GET_DEVICE(*call);
+	netif_device_t *device;
+	int nil_phone;
+	ne2k_t *ne2k;
+	
+	fibril_rwlock_read_lock(&netif_globals.lock);
+	
+	if (find_device(device_id, &device) == EOK) {
+		nil_phone = device->nil_phone;
+		ne2k = (ne2k_t *) device->specific;
+	} else
+		ne2k = NULL;
+	
+	fibril_rwlock_read_unlock(&netif_globals.lock);
+	
+	if (ne2k != NULL)
+		ne2k_interrupt(ne2k, IRQ_GET_ISR(*call), nil_phone, device_id);
+}
+
+/** Change the network interface state.
+ *
+ * @param[in,out] device Network interface.
+ * @param[in]     state  New state.
+ *
+ */
+static void change_state(netif_device_t *device, device_state_t state)
+{
+	if (device->state != state) {
+		device->state = state;
+		
+		const char *desc;
+		switch (state) {
+		case NETIF_ACTIVE:
+			desc = "active";
+			break;
+		case NETIF_STOPPED:
+			desc = "stopped";
+			break;
+		default:
+			desc = "unknown";
+		}
+		
+		printf("%s: State changed to %s\n", NAME, desc);
+	}
+}
+
+int netif_specific_message(ipc_callid_t callid, ipc_call_t *call,
+    ipc_call_t *answer, size_t *count)
+{
+	return ENOTSUP;
+}
+
+int netif_get_device_stats(device_id_t device_id, device_stats_t *stats)
+{
+	if (!stats)
+		return EBADMEM;
+	
+	netif_device_t *device;
+	int rc = find_device(device_id, &device);
+	if (rc != EOK)
+		return rc;
+	
+	ne2k_t *ne2k = (ne2k_t *) device->specific;
+	
+	memcpy(stats, &ne2k->stats, sizeof(device_stats_t));
+	return EOK;
+}
+
+int netif_get_addr_message(device_id_t device_id, measured_string_t *address)
+{
+	if (!address)
+		return EBADMEM;
+	
+	netif_device_t *device;
+	int rc = find_device(device_id, &device);
+	if (rc != EOK)
+		return rc;
+	
+	ne2k_t *ne2k = (ne2k_t *) device->specific;
+	
+	address->value = ne2k->mac;
+	address->length = ETH_ADDR;
+	return EOK;
+}
+
+int netif_probe_message(device_id_t device_id, int irq, void *io)
+{
+	netif_device_t *device =
+	    (netif_device_t *) malloc(sizeof(netif_device_t));
+	if (!device)
+		return ENOMEM;
+	
+	ne2k_t *ne2k = (ne2k_t *) malloc(sizeof(ne2k_t));
+	if (!ne2k) {
+		free(device);
+		return ENOMEM;
+	}
+	
+	void *port;
+	int rc = pio_enable((void *) io, NE2K_IO_SIZE, &port);
+	if (rc != EOK) {
+		free(ne2k);
+		free(device);
+		return rc;
+	}
+	
+	bzero(device, sizeof(netif_device_t));
+	bzero(ne2k, sizeof(ne2k_t));
+	
+	device->device_id = device_id;
+	device->nil_phone = -1;
+	device->specific = (void *) ne2k;
+	device->state = NETIF_STOPPED;
+	
+	rc = ne2k_probe(ne2k, port, irq);
+	if (rc != EOK) {
+		printf("%s: No ethernet card found at I/O address %p\n",
+		    NAME, port);
+		free(ne2k);
+		free(device);
+		return rc;
+	}
+	
+	rc = netif_device_map_add(&netif_globals.device_map, device->device_id, device);
+	if (rc != EOK) {
+		free(ne2k);
+		free(device);
+		return rc;
+	}
+	
+	printf("%s: Ethernet card at I/O address %p, IRQ %d, MAC ",
+	    NAME, port, irq);
+	
+	unsigned int i;
+	for (i = 0; i < ETH_ADDR; i++)
+		printf("%02x%c", ne2k->mac[i], i < 5 ? ':' : '\n');
+	
+	return EOK;
+}
+
+int netif_start_message(netif_device_t *device)
+{
+	if (device->state != NETIF_ACTIVE) {
+		ne2k_t *ne2k = (ne2k_t *) device->specific;
+		
+		ne2k_cmds[0].addr = ne2k->port + DP_ISR;
+		ne2k_cmds[3].addr = ne2k_cmds[0].addr;
+		
+		int rc = ipc_register_irq(ne2k->irq, device->device_id,
+		    device->device_id, &ne2k_code);
+		if (rc != EOK)
+			return rc;
+		
+		rc = ne2k_up(ne2k);
+		if (rc != EOK) {
+			ipc_unregister_irq(ne2k->irq, device->device_id);
+			return rc;
+		}
+		
+		if (irc_service)
+			async_msg_1(irc_phone, IRC_ENABLE_INTERRUPT, ne2k->irq);
+		
+		change_state(device, NETIF_ACTIVE);
+	}
+	
+	return device->state;
+}
+
+int netif_stop_message(netif_device_t *device)
+{
+	if (device->state != NETIF_STOPPED) {
+		ne2k_t *ne2k = (ne2k_t *) device->specific;
+		
+		ne2k_down(ne2k);
+		ipc_unregister_irq(ne2k->irq, device->device_id);
+		change_state(device, NETIF_STOPPED);
+	}
+	
+	return EOK;
+}
+
+int netif_send_message(device_id_t device_id, packet_t *packet,
+    services_t sender)
+{
+	netif_device_t *device;
+	int rc = find_device(device_id, &device);
+	if (rc != EOK)
+		return rc;
+	
+	if (device->state != NETIF_ACTIVE) {
+		netif_pq_release(packet_get_id(packet));
+		return EFORWARD;
+	}
+	
+	ne2k_t *ne2k = (ne2k_t *) device->specific;
 	
 	/*
-	 * We probe for an ne1000 or an ne2000 by testing whether the
-	 * on board is reachable through the dp8390. Note that the
-	 * ne1000 is an 8bit card and has a memory region distict from
-	 * the 16bit ne2000
+	 * Process the packet queue
 	 */
 	
-	for (dep->de_16bit = 0; dep->de_16bit < 2; dep->de_16bit++) {
-		/* Reset the ethernet card */
-		byte= inb_ne(dep, NE_RESET);
-		usleep(2000);
-		outb_ne(dep, NE_RESET, byte);
-		usleep(2000);
-		
-		/* Reset the dp8390 */
-		outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
-		for (i = 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
-			; /* Do nothing */
-		
-		/* Check if the dp8390 is really there */
-		if ((inb_reg0(dep, DP_CR) & (CR_STP | CR_DM_ABORT)) !=
-		    (CR_STP | CR_DM_ABORT))
-			return 0;
-		
-		/* Disable the receiver and init TCR and DCR. */
-		outb_reg0(dep, DP_RCR, RCR_MON);
-		outb_reg0(dep, DP_TCR, TCR_NORMAL);
-		if (dep->de_16bit) {
-			outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES |
-			    DCR_BMS);
-		} else {
-			outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES |
-			    DCR_BMS);
+	do {
+		packet_t *next = pq_detach(packet);
+		ne2k_send(ne2k, packet);
+		netif_pq_release(packet_get_id(packet));
+		packet = next;
+	} while (packet);
+	
+	return EOK;
+}
+
+int netif_initialize(void)
+{
+	sysarg_t apic;
+	sysarg_t i8259;
+	
+	if ((sysinfo_get_value("apic", &apic) == EOK) && (apic))
+		irc_service = SERVICE_APIC;
+	else if ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259))
+		irc_service = SERVICE_I8259;
+	
+	if (irc_service) {
+		while (irc_phone < 0) {
+			irc_phone = ipc_connect_me_to_blocking(PHONE_NS, irc_service,
+			    0, 0);
 		}
-		
-		if (dep->de_16bit) {
-			loc1 = NE2000_START;
-			loc2 = NE2000_START + NE2000_SIZE - 4;
-			f = test_16;
-		} else {
-			loc1 = NE1000_START;
-			loc2 = NE1000_START + NE1000_SIZE - 4;
-			f = test_8;
-		}
-		
-		if (f(dep, loc1, pat0) && f(dep, loc1, pat1) &&
-		    f(dep, loc1, pat2) && f(dep, loc1, pat3) &&
-		    f(dep, loc2, pat0) && f(dep, loc2, pat1) &&
-		    f(dep, loc2, pat2) && f(dep, loc2, pat3)) {
-			return 1;
-		}
-	}
-	
-	return 0;
-}
-
-/** Initializes the NE2000 network interface.
- *
- *  @param[in,out] dep The network interface structure.
- *
- */
-void ne_init(dpeth_t *dep)
-{
-	int i;
-	int word, sendq_nr;
-	
-	/* Setup a transfer to get the ethernet address. */
-	if (dep->de_16bit)
-		outb_reg0(dep, DP_RBCR0, 6*2);
-	else
-		outb_reg0(dep, DP_RBCR0, 6);
-	
-	outb_reg0(dep, DP_RBCR1, 0);
-	outb_reg0(dep, DP_RSAR0, 0);
-	outb_reg0(dep, DP_RSAR1, 0);
-	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
-	
-	for (i = 0; i < 6; i++) {
-		if (dep->de_16bit) {
-			word = inw_ne(dep, NE_DATA);
-			dep->de_address.ea_addr[i] = word;
-		} else
-			dep->de_address.ea_addr[i] = inb_ne(dep, NE_DATA);
-	}
-	
-	dep->de_data_port= dep->de_base_port + NE_DATA;
-	if (dep->de_16bit) {
-		dep->de_ramsize = NE2000_SIZE;
-		dep->de_offset_page = NE2000_START / DP_PAGESIZE;
-	} else {
-		dep->de_ramsize = NE1000_SIZE;
-		dep->de_offset_page = NE1000_START / DP_PAGESIZE;
-	}
-	
-	/* Allocate one send buffer (1.5KB) per 8KB of on board memory. */
-	sendq_nr = dep->de_ramsize / 0x2000;
-	
-	if (sendq_nr < 1)
-		sendq_nr = 1;
-	else if (sendq_nr > SENDQ_NR)
-		sendq_nr = SENDQ_NR;
-	
-	dep->de_sendq_nr = sendq_nr;
-	for (i = 0; i < sendq_nr; i++)
-		dep->de_sendq[i].sq_sendpage = dep->de_offset_page + i * SENDQ_PAGES;
-	
-	dep->de_startpage = dep->de_offset_page + i * SENDQ_PAGES;
-	dep->de_stoppage = dep->de_offset_page + dep->de_ramsize / DP_PAGESIZE;
-	
-	printf("Novell NE%d000 ethernet card at I/O address "
-	    "%#lx, memory size %#lx, irq %d\n",
-	    dep->de_16bit ? 2 : 1, dep->de_base_port, dep->de_ramsize,
-	    dep->de_irq);
-}
-
-static int test_8(dpeth_t *dep, int pos, uint8_t *pat)
-{
-	uint8_t buf[4];
-	int i;
-	
-	outb_reg0(dep, DP_ISR, 0xff);
-	
-	/* Setup a transfer to put the pattern. */
-	outb_reg0(dep, DP_RBCR0, 4);
-	outb_reg0(dep, DP_RBCR1, 0);
-	outb_reg0(dep, DP_RSAR0, pos & 0xff);
-	outb_reg0(dep, DP_RSAR1, pos >> 8);
-	outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
-	
-	for (i = 0; i < 4; i++)
-		outb_ne(dep, NE_DATA, pat[i]);
-	
-	for (i = 0; i < N; i++) {
-		if (inb_reg0(dep, DP_ISR) & ISR_RDC)
-			break;
-	}
-	
-	if (i == N) {
-		printf("NE1000 remote DMA test failed\n");
-		return 0;
-	}
-	
-	outb_reg0(dep, DP_RBCR0, 4);
-	outb_reg0(dep, DP_RBCR1, 0);
-	outb_reg0(dep, DP_RSAR0, pos & 0xff);
-	outb_reg0(dep, DP_RSAR1, pos >> 8);
-	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
-	
-	for (i = 0; i < 4; i++)
-		buf[i] = inb_ne(dep, NE_DATA);
-	
-	return (bcmp(buf, pat, 4) == 0);
-}
-
-static int test_16(dpeth_t *dep, int pos, uint8_t *pat)
-{
-	uint8_t buf[4];
-	int i;
-	
-	outb_reg0(dep, DP_ISR, 0xff);
-	
-	/* Setup a transfer to put the pattern. */
-	outb_reg0(dep, DP_RBCR0, 4);
-	outb_reg0(dep, DP_RBCR1, 0);
-	outb_reg0(dep, DP_RSAR0, pos & 0xff);
-	outb_reg0(dep, DP_RSAR1, pos >> 8);
-	outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
-	
-	for (i = 0; i < 4; i += 2)
-		outw_ne(dep, NE_DATA, *(uint16_t *)(pat + i));
-	
-	for (i = 0; i < N; i++) {
-		if (inb_reg0(dep, DP_ISR) &ISR_RDC)
-			break;
-	}
-	
-	if (i == N) {
-		printf("NE2000 remote DMA test failed\n");
-		return 0;
-	}
-	
-	outb_reg0(dep, DP_RBCR0, 4);
-	outb_reg0(dep, DP_RBCR1, 0);
-	outb_reg0(dep, DP_RSAR0, pos & 0xff);
-	outb_reg0(dep, DP_RSAR1, pos >> 8);
-	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
-	
-	for (i = 0; i < 4; i += 2)
-		*(uint16_t *)(buf + i) = inw_ne(dep, NE_DATA);
-	
-	return (bcmp(buf, pat, 4) == 0);
-}
-
-/** Stop the NE2000 network interface.
- *
- *  @param[in,out] dep The network interface structure.
- *
- */
-void ne_stop(dpeth_t *dep)
-{
-	/* Reset the ethernet card */
-	int byte = inb_ne(dep, NE_RESET);
-	usleep(2000);
-	outb_ne(dep, NE_RESET, byte);
+	}
+	
+	async_set_interrupt_received(irq_handler);
+	
+	sysarg_t phonehash;
+	return ipc_connect_to_me(PHONE_NS, SERVICE_DP8390, 0, 0, &phonehash);
+}
+
+int main(int argc, char *argv[])
+{
+	/* Start the module */
+	return netif_module_start();
 }
 
Index: uspace/srv/hw/netif/dp8390/ne2000.h
===================================================================
--- uspace/srv/hw/netif/dp8390/ne2000.h	(revision 7ea7db31d35d3bcb84a5f1220696fa0c75b775c3)
+++ 	(revision )
@@ -1,119 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * Copyright (c) 2011 Martin Decky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - 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.
- * - 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.
- */
-
-/*
- * This code is based upon the NE2000 driver for MINIX,
- * distributed according to a BSD-style license.
- *
- * Copyright (c) 1987, 1997, 2006 Vrije Universiteit
- * Copyright (c) 1992, 1994 Philip Homburg
- * Copyright (c) 1996 G. Falzoni
- *
- */
-
-/** @addtogroup ne2k
- *  @{
- */
-
-/** @file
- *  NE1000 and NE2000 network interface definitions.
- */
-
-#ifndef __NET_NETIF_NE2000_H__
-#define __NET_NETIF_NE2000_H__
-
-#include <libarch/ddi.h>
-#include "dp8390_port.h"
-
-/** DP8390 register offset.
- */
-#define NE_DP8390  0x00
-
-/** Data register.
- */
-#define NE_DATA  0x10
-
-/** Reset register.
- */
-#define NE_RESET  0x1f
-
-/** NE1000 data start.
- */
-#define NE1000_START  0x2000
-
-/** NE1000 data size.
- */
-#define NE1000_SIZE  0x2000
-
-/** NE2000 data start.
- */
-#define NE2000_START  0x4000
-
-/** NE2000 data size.
- */
-#define NE2000_SIZE  0x4000
-
-/** Reads 1 byte register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @returns The read value.
- */
-#define inb_ne(dep, reg)  (inb(dep->de_base_port + reg))
-
-/** Writes 1 byte register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @param[in] data The value to be written.
- */
-#define outb_ne(dep, reg, data)  (outb(dep->de_base_port + reg, data))
-
-/** Reads 1 word (2 bytes) register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @returns The read value.
- */
-#define inw_ne(dep, reg)  (inw(dep->de_base_port + reg))
-
-/** Writes 1 word (2 bytes) register.
- *  @param[in] dep The network interface structure.
- *  @param[in] reg The register offset.
- *  @param[in] data The value to be written.
- */
-#define outw_ne(dep, reg, data)  (outw(dep->de_base_port + reg, data))
-
-struct dpeth;
-
-extern int ne_probe(struct dpeth *);
-extern void ne_init(struct dpeth *);
-extern void ne_stop(struct dpeth *);
-
-#endif
-
-/** @}
- */
