Index: uspace/lib/net/netif/netif_skel.c
===================================================================
--- uspace/lib/net/netif/netif_skel.c	(revision 6643a19bb92cff616761e36c4c85f59b19676307)
+++ uspace/lib/net/netif/netif_skel.c	(revision 8136102462ea82df81d463ed906fdf403a01c19c)
@@ -130,6 +130,6 @@
 	if (result > NETIF_NULL) {
 		int phone = device->nil_phone;
+		nil_device_state_msg(phone, device_id, result);
 		fibril_rwlock_write_unlock(&netif_globals.lock);
-		nil_device_state_msg(phone, device_id, result);
 		return EOK;
 	}
@@ -166,6 +166,6 @@
 	if (result > NETIF_NULL) {
 		int phone = device->nil_phone;
+		nil_device_state_msg(phone, device_id, result);
 		fibril_rwlock_write_unlock(&netif_globals.lock);
-		nil_device_state_msg(phone, device_id, result);
 		return EOK;
 	}
Index: uspace/srv/hw/netif/dp8390/dp8390.c
===================================================================
--- uspace/srv/hw/netif/dp8390/dp8390.c	(revision 6643a19bb92cff616761e36c4c85f59b19676307)
+++ uspace/srv/hw/netif/dp8390/dp8390.c	(revision 8136102462ea82df81d463ed906fdf403a01c19c)
@@ -54,7 +54,5 @@
 #include <errno.h>
 #include <libarch/ddi.h>
-#include <netif_skel.h>
 #include <net/packet.h>
-#include <nil_interface.h>
 #include <packet_client.h>
 #include "dp8390.h"
@@ -81,5 +79,5 @@
 
 /** NE2000 retry count */
-#define NE2K_RETRY  100
+#define NE2K_RETRY  0x1000
 
 /** NE2000 error messages rate limiting */
@@ -186,4 +184,22 @@
 		memcpy(&word, buf, 1);
 		pio_write_16(ne2k->data_port, word);
+	}
+}
+
+static void ne2k_init(ne2k_t *ne2k)
+{
+	unsigned int i;
+	
+	/* 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 < NE2K_RETRY; i++) {
+		if (pio_read_8(ne2k->port + DP_ISR) != 0)
+			break;
 	}
 }
@@ -210,19 +226,8 @@
 	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;
-	}
+	ne2k_init(ne2k);
 	
 	/* Check if the DP8390 is really there */
-	val = pio_read_8(ne2k->port + DP_CR);
+	uint8_t val = pio_read_8(ne2k->port + DP_CR);
 	if ((val & (CR_STP | CR_DM_ABORT)) != (CR_STP | CR_DM_ABORT))
 		return EXDEV;
@@ -242,4 +247,23 @@
 	for (i = 0; i < ETH_ADDR; i++)
 		ne2k->mac[i] = pio_read_16(ne2k->data_port);
+	
+	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;
+	
+	ne2k_init(ne2k);
 	
 	/*
@@ -318,5 +342,5 @@
 	
 	/* Step 10: */
-	pio_write_8(ne2k->port + DP_CR, CR_DM_ABORT | CR_STA);
+	pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_DM_ABORT | CR_STA);
 	
 	/* Step 11: */
@@ -329,24 +353,4 @@
 	
 	/* 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;
@@ -362,10 +366,5 @@
 	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_init(ne2k);
 		ne2k->up = false;
 	}
@@ -420,5 +419,5 @@
 	pio_write_8(ne2k->port + DP_RBCR1, 0);
 	
-	for (i = 0; i < 0x1000; i++) {
+	for (i = 0; i < NE2K_RETRY; i++) {
 		if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RST) != 0)
 			break;
@@ -430,5 +429,5 @@
 	
 	/* Acknowledge the ISR_RDC (remote DMA) interrupt */
-	for (i = 0; i < 0x1000; i++) {
+	for (i = 0; i < NE2K_RETRY; i++) {
 		if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RDC) != 0)
 			break;
@@ -448,21 +447,19 @@
 }
 
-static uint8_t ne2k_isr_ack(ne2k_t *ne2k)
-{
-	uint8_t isr = pio_read_8(ne2k->port + DP_ISR);
-	if (isr != 0)
-		pio_write_8(ne2k->port + DP_ISR, isr);
-	
-	return isr;
-}
-
-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);
+static frame_t *ne2k_receive_frame(ne2k_t *ne2k, uint8_t page, size_t length)
+{
+	frame_t *frame = (frame_t *) malloc(sizeof(frame_t));
+	if (frame == NULL)
+		return NULL;
+	
+	link_initialize(&frame->link);
+	
+	frame->packet = netif_packet_get_1(length);
+	if (frame->packet == NULL) {
+		free(frame);
+		return NULL;
+	}
+	
+	void *buf = packet_suffix(frame->packet, length);
 	bzero(buf, length);
 	uint8_t last = page + length / DP_PAGE;
@@ -481,9 +478,18 @@
 	
 	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)
-{
+	return frame;
+}
+
+static link_t *ne2k_receive(ne2k_t *ne2k)
+{
+	/*
+	 * Allocate memory for the list of received frames.
+	 * If the allocation fails here we still receive the
+	 * frames from the network, but they will be lost.
+	 */
+	link_t *frames = (link_t *) malloc(sizeof(link_t));
+	if (frames != NULL)
+		list_initialize(frames);
+	
 	while (true) {
 		uint8_t boundary = pio_read_8(ne2k->port + DP_BNRY) + 1;
@@ -534,6 +540,9 @@
 			ne2k->overruns++;
 			next = current;
-		} else if ((header.status & RSR_PRX) && (ne2k->up))
-			ne2k_receive_frame(ne2k, boundary, length, nil_phone, device_id);
+		} else if ((header.status & RSR_PRX) && (ne2k->up)) {
+			frame_t *frame = ne2k_receive_frame(ne2k, boundary, length);
+			if ((frame != NULL) && (frames != NULL))
+				list_append(&frame->link, frames);
+		}
 		
 		/*
@@ -550,89 +559,79 @@
 		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)
-				ne2k->stats.send_errors++;
-			else {
-				uint8_t tsr = pio_read_8(ne2k->port + DP_TSR);
-				
-				if (tsr & TSR_PTX)
-					ne2k->stats.send_packets++;
-				
-				if (tsr & TSR_COL)
-					ne2k->stats.collisions++;
-				
-				if (tsr & TSR_ABT)
-					ne2k->stats.send_aborted_errors++;
-				
-				if (tsr & TSR_CRS)
-					ne2k->stats.send_carrier_errors++;
-				
-				if (tsr & TSR_FU) {
-					ne2k->underruns++;
-					if (ne2k->underruns < NE2K_ERL)
-						fprintf(stderr, "%s: FIFO underrun\n", NAME);
-				}
-				
-				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)
-					ne2k->stats.send_window_errors++;
+	
+	return frames;
+}
+
+link_t *ne2k_interrupt(ne2k_t *ne2k, uint8_t isr, uint8_t tsr)
+{
+	/* List of received frames */
+	link_t *frames = NULL;
+	
+	if (isr & (ISR_PTX | ISR_TXE)) {
+		if (isr & ISR_TXE)
+			ne2k->stats.send_errors++;
+		else {
+			if (tsr & TSR_PTX)
+				ne2k->stats.send_packets++;
+			
+			if (tsr & TSR_COL)
+				ne2k->stats.collisions++;
+			
+			if (tsr & TSR_ABT)
+				ne2k->stats.send_aborted_errors++;
+			
+			if (tsr & TSR_CRS)
+				ne2k->stats.send_carrier_errors++;
+			
+			if (tsr & TSR_FU) {
+				ne2k->underruns++;
+				if (ne2k->underruns < NE2K_ERL)
+					fprintf(stderr, "%s: FIFO underrun\n", NAME);
 			}
 			
-			fibril_mutex_lock(&ne2k->sq_mutex);
-			
-			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);
+			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);
 			}
 			
-			fibril_mutex_unlock(&ne2k->sq_mutex);
+			if (tsr & TSR_OWC)
+				ne2k->stats.send_window_errors++;
 		}
 		
-		if (isr & ISR_PRX)
-			ne2k_receive(ne2k, nil_phone, device_id);
-		
-		if (isr & ISR_RXE)
-			ne2k->stats.receive_errors++;
-		
-		if (isr & ISR_CNT) {
-			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);
+		fibril_mutex_lock(&ne2k->sq_mutex);
+		
+		if (ne2k->sq.dirty) {
+			/* Prepare the buffer for next packet */
+			ne2k->sq.dirty = false;
+			ne2k->sq.size = 0;
+			
+			/* Signal a next frame to be sent */
+			fibril_condvar_broadcast(&ne2k->sq_cv);
+		} else {
+			ne2k->misses++;
+			if (ne2k->misses < NE2K_ERL)
+				fprintf(stderr, "%s: Spurious PTX interrupt\n", NAME);
 		}
 		
-		if (isr & ISR_RST) {
-			/*
-			 * This means we got an interrupt but the ethernet
-			 * chip is shutdown. We set the flag 'stopped'
-			 * and continue processing arrived packets. When the
-			 * receive buffer is empty, we reset the DP8390.
-			 */
-			stopped = true;
-		}
-	}
-	
-	if (stopped) {
+		fibril_mutex_unlock(&ne2k->sq_mutex);
+	}
+	
+	if (isr & ISR_RXE)
+		ne2k->stats.receive_errors++;
+	
+	if (isr & ISR_CNT) {
+		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);
+	}
+	
+	if (isr & ISR_PRX)
+		frames = ne2k_receive(ne2k);
+	
+	if (isr & ISR_RST) {
 		/*
 		 * The chip is stopped, and all arrived
@@ -642,7 +641,9 @@
 	}
 	
-	/* Signal a next frame to be sent */
-	if (signal)
-		fibril_condvar_broadcast(&ne2k->sq_cv);
+	/* Unmask interrupts to be processed in the next round */
+	pio_write_8(ne2k->port + DP_IMR,
+	    IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE | IMR_CNTE);
+	
+	return frames;
 }
 
Index: uspace/srv/hw/netif/dp8390/dp8390.h
===================================================================
--- uspace/srv/hw/netif/dp8390/dp8390.h	(revision 6643a19bb92cff616761e36c4c85f59b19676307)
+++ uspace/srv/hw/netif/dp8390/dp8390.h	(revision 8136102462ea82df81d463ed906fdf403a01c19c)
@@ -50,5 +50,7 @@
 
 #include <fibril_synch.h>
+#include <adt/list.h>
 #include <net/packet.h>
+#include <netif_skel.h>
 
 /** Module name */
@@ -230,9 +232,14 @@
 } ne2k_t;
 
+typedef struct {
+	link_t link;
+	packet_t *packet;
+} frame_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);
+extern link_t *ne2k_interrupt(ne2k_t *, uint8_t, uint8_t);
 
 #endif
Index: uspace/srv/hw/netif/dp8390/ne2000.c
===================================================================
--- uspace/srv/hw/netif/dp8390/ne2000.c	(revision 6643a19bb92cff616761e36c4c85f59b19676307)
+++ uspace/srv/hw/netif/dp8390/ne2000.c	(revision 8136102462ea82df81d463ed906fdf403a01c19c)
@@ -68,4 +68,11 @@
 #define IRQ_GET_ISR(call)  ((int) IPC_GET_ARG2(call))
 
+/** Return the TSR from the interrupt call.
+ *
+ * @param[in] call The interrupt call.
+ *
+ */
+#define IRQ_GET_TSR(call)  ((int) IPC_GET_ARG3(call))
+
 static int irc_service = 0;
 static int irc_phone = -1;
@@ -76,4 +83,5 @@
 static irq_cmd_t ne2k_cmds[] = {
 	{
+		/* Read Interrupt Status Register */
 		.cmd = CMD_PIO_READ_8,
 		.addr = NULL,
@@ -81,18 +89,37 @@
 	},
 	{
+		/* Mask supported interrupt causes */
 		.cmd = CMD_BTEST,
-		.value = 0x7f,
+		.value = (ISR_PRX | ISR_PTX | ISR_RXE | ISR_TXE | ISR_OVW |
+		    ISR_CNT | ISR_RDC),
 		.srcarg = 2,
 		.dstarg = 3,
 	},
 	{
+		/* Predicate for accepting the interrupt */
 		.cmd = CMD_PREDICATE,
-		.value = 2,
+		.value = 4,
 		.srcarg = 3
 	},
 	{
+		/*
+		 * Mask future interrupts via
+		 * Interrupt Mask Register
+		 */
+		.cmd = CMD_PIO_WRITE_8,
+		.addr = NULL,
+		.value = 0
+	},
+	{
+		/* Acknowledge the current interrupt */
 		.cmd = CMD_PIO_WRITE_A_8,
 		.addr = NULL,
 		.srcarg = 3
+	},
+	{
+		/* Read Transmit Status Register */
+		.cmd = CMD_PIO_READ_8,
+		.addr = NULL,
+		.dstarg = 3
 	},
 	{
@@ -111,5 +138,9 @@
 /** Handle the interrupt notification.
  *
- * This is the interrupt notification function.
+ * This is the interrupt notification function. It is quarantied
+ * that there is only a single instance of this notification
+ * function running at one time until the return from the
+ * ne2k_interrupt() function (where the interrupts are unmasked
+ * again).
  *
  * @param[in] iid  Interrupt notification identifier.
@@ -134,6 +165,22 @@
 	fibril_rwlock_read_unlock(&netif_globals.lock);
 	
-	if (ne2k != NULL)
-		ne2k_interrupt(ne2k, IRQ_GET_ISR(*call), nil_phone, device_id);
+	if (ne2k != NULL) {
+		link_t *frames =
+		    ne2k_interrupt(ne2k, IRQ_GET_ISR(*call), IRQ_GET_TSR(*call));
+		
+		if (frames != NULL) {
+			while (!list_empty(frames)) {
+				frame_t *frame =
+				    list_get_instance(frames->next, frame_t, link);
+				
+				list_remove(&frame->link);
+				nil_received_msg(nil_phone, device_id, frame->packet,
+				    SERVICE_NONE);
+				free(frame);
+			}
+			
+			free(frames);
+		}
+	}
 }
 
@@ -265,5 +312,6 @@
 		
 		ne2k_cmds[0].addr = ne2k->port + DP_ISR;
-		ne2k_cmds[3].addr = ne2k_cmds[0].addr;
+		ne2k_cmds[3].addr = ne2k->port + DP_IMR;
+		ne2k_cmds[4].addr = ne2k_cmds[0].addr;
 		
 		int rc = ipc_register_irq(ne2k->irq, device->device_id,
@@ -278,8 +326,8 @@
 		}
 		
+		change_state(device, NETIF_ACTIVE);
+		
 		if (irc_service)
 			async_msg_1(irc_phone, IRC_ENABLE_INTERRUPT, ne2k->irq);
-		
-		change_state(device, NETIF_ACTIVE);
 	}
 	
