Index: uspace/drv/nic/e1k/e1k.c
===================================================================
--- uspace/drv/nic/e1k/e1k.c	(revision f991b6babc87e0deb9b4bf9442366643a976866e)
+++ uspace/drv/nic/e1k/e1k.c	(revision a1347a7d9d2bcb49b7e781408978b65acb44ea89)
@@ -67,4 +67,6 @@
 #define E1000_RECEIVE_ADDRESS  16
 
+/** Maximum sending packet size */
+#define E1000_MAX_SEND_FRAME_SIZE  2048
 /** Maximum receiving packet size */
 #define E1000_MAX_RECEIVE_PACKET_SIZE  2048
@@ -125,6 +127,8 @@
 	void *tx_ring_virt;
 	
-	/** Packets in tx ring  */
-	packet_t **tx_ring_packets;
+	/** Ring of TX frames, physical address */
+	void **tx_frame_phys;
+	/** Ring of TX frames, virtual address */
+	void **tx_frame_virt;
 	
 	/** Physical rx ring address */
@@ -223,5 +227,5 @@
 static int e1000_on_activating(nic_t *);
 static int e1000_on_stopping(nic_t *);
-static void e1000_write_packet(nic_t *, packet_t *);
+static void e1000_send_frame(nic_t *, void *, size_t);
 
 /** Commands to deal with interrupt
@@ -1126,10 +1130,4 @@
 	    (e1000->tx_ring_virt + offset * sizeof(e1000_tx_descriptor_t));
 	
-	if (tx_descriptor->length) {
-		packet_t *old_packet = *(e1000->tx_ring_packets + offset);
-		if (old_packet)
-			nic_release_packet(nic, old_packet);
-	}
-	
 	tx_descriptor->phys_addr = 0;
 	tx_descriptor->length = 0;
@@ -1522,5 +1520,12 @@
 static int e1000_initialize_tx_structure(e1000_t *e1000)
 {
+	size_t i;
+	
 	fibril_mutex_lock(&e1000->tx_lock);
+	
+	e1000->tx_ring_phys = NULL;
+	e1000->tx_ring_virt = NULL;
+	e1000->tx_frame_phys = NULL;
+	e1000->tx_frame_virt = NULL;
 	
 	int rc = dmamem_map_anonymous(
@@ -1529,8 +1534,24 @@
 	    &e1000->tx_ring_virt);
 	if (rc != EOK)
-		return rc;
+		goto error;
 	
 	bzero(e1000->tx_ring_virt,
 	    E1000_TX_PACKETS_COUNT * sizeof(e1000_tx_descriptor_t));
+	
+	e1000->tx_frame_phys = calloc(E1000_TX_PACKETS_COUNT, sizeof(void *));
+	e1000->tx_frame_virt = calloc(E1000_TX_PACKETS_COUNT, sizeof(void *));
+
+	if (e1000->tx_frame_phys == NULL || e1000->tx_frame_virt == NULL) {
+		rc = ENOMEM;
+		goto error;
+	}
+	
+	for (i = 0; i < E1000_TX_PACKETS_COUNT; i++) {
+		rc = dmamem_map_anonymous(
+		    E1000_MAX_SEND_FRAME_SIZE, AS_AREA_READ | AS_AREA_WRITE,
+		    0, &e1000->tx_frame_phys[i], &e1000->tx_frame_virt[i]);
+		if (rc != EOK)
+			goto error;
+	}
 	
 	E1000_REG_WRITE(e1000, E1000_TDBAH,
@@ -1539,12 +1560,36 @@
 	    (uint32_t) PTR_TO_U64(e1000->tx_ring_phys));
 	
-	e1000->tx_ring_packets =
-	    malloc(E1000_TX_PACKETS_COUNT * sizeof(packet_t *));
-	// FIXME: Check return value
-	
 	e1000_initialize_tx_registers(e1000);
 	
 	fibril_mutex_unlock(&e1000->tx_lock);
 	return EOK;
+	
+error:
+	if (e1000->tx_ring_virt != NULL) {
+		dmamem_unmap_anonymous(e1000->tx_ring_virt);
+		e1000->tx_ring_virt = NULL;
+	}
+	
+	if (e1000->tx_frame_phys != NULL && e1000->tx_frame_virt != NULL) {
+		for (i = 0; i < E1000_TX_PACKETS_COUNT; i++) {
+			if (e1000->tx_frame_virt[i] != NULL) {
+				dmamem_unmap_anonymous(e1000->tx_frame_virt[i]);
+				e1000->tx_frame_virt[i] = NULL;
+				e1000->tx_frame_phys[i] = NULL;
+			}
+		}
+	}
+	
+	if (e1000->tx_frame_phys != NULL) {
+		free(e1000->tx_frame_phys);
+		e1000->tx_frame_phys = NULL;
+	}
+	
+	if (e1000->tx_frame_virt != NULL) {
+		free(e1000->tx_frame_virt);
+		e1000->tx_frame_phys = NULL;
+	}
+	
+	return rc;
 }
 
@@ -1556,5 +1601,21 @@
 static void e1000_uninitialize_tx_structure(e1000_t *e1000)
 {
-	free(e1000->tx_ring_packets);
+	size_t i;
+	
+	for (i = 0; i < E1000_TX_PACKETS_COUNT; i++) {
+		dmamem_unmap_anonymous(e1000->tx_frame_virt[i]);
+		e1000->tx_frame_virt[i] = NULL;
+		e1000->tx_frame_phys[i] = NULL;
+	}
+	
+	if (e1000->tx_frame_phys != NULL) {
+		free(e1000->tx_frame_phys);
+		e1000->tx_frame_phys = NULL;
+	}
+	
+	if (e1000->tx_frame_virt != NULL) {
+		free(e1000->tx_frame_virt);
+		e1000->tx_frame_phys = NULL;
+	}
 	dmamem_unmap_anonymous(e1000->tx_ring_virt);
 }
@@ -1771,5 +1832,5 @@
 	
 	nic_set_specific(nic, e1000);
-	nic_set_write_packet_handler(nic, e1000_write_packet);
+	nic_set_send_frame_handler(nic, e1000_send_frame);
 	nic_set_state_change_handlers(nic, e1000_on_activating,
 	    e1000_on_down, e1000_on_stopping);
@@ -2190,8 +2251,9 @@
 }
 
-/** Send packet
+/** Send frame
  *
  * @param nic    NIC driver data structure
- * @param packet Packet to send
+ * @param data   Frame data
+ * @param size   Frame size in bytes
  *
  * @return EOK if succeed
@@ -2199,5 +2261,5 @@
  *
  */
-static void e1000_write_packet(nic_t *nic, packet_t *packet)
+static void e1000_send_frame(nic_t *nic, void *data, size_t size)
 {
 	assert(nic);
@@ -2217,13 +2279,6 @@
 	
 	/* Descriptor done */
-	if (tx_descriptor_addr->status & TXDESCRIPTOR_STATUS_DD) {
+	if (tx_descriptor_addr->status & TXDESCRIPTOR_STATUS_DD)
 		descriptor_available = true;
-		packet_t *old_packet = *(e1000->tx_ring_packets + tdt);
-		if (old_packet) {
-			size_t old_packet_size = packet_get_data_length(old_packet);
-			nic_dma_unlock_packet(old_packet, old_packet_size);
-			nic_release_packet(nic, old_packet);
-		}
-	}
 	
 	if (!descriptor_available) {
@@ -2233,18 +2288,8 @@
 	}
 	
-	size_t packet_size = packet_get_data_length(packet);
-	
-	void *phys;
-	int rc = nic_dma_lock_packet(packet, packet_size, &phys);
-	if (rc != EOK) {
-		fibril_mutex_unlock(&e1000->tx_lock);
-		return;
-	}
-	
-	*(e1000->tx_ring_packets + tdt) = packet;
-	
-	tx_descriptor_addr->phys_addr =
-	    PTR_TO_U64(phys + packet->data_start);
-	tx_descriptor_addr->length = packet_size;
+	memcpy(e1000->tx_frame_virt[tdt], data, size);
+	
+	tx_descriptor_addr->phys_addr = PTR_TO_U64(e1000->tx_frame_phys[tdt]);
+	tx_descriptor_addr->length = size;
 	
 	/*
Index: uspace/drv/nic/lo/lo.c
===================================================================
--- uspace/drv/nic/lo/lo.c	(revision f991b6babc87e0deb9b4bf9442366643a976866e)
+++ uspace/drv/nic/lo/lo.c	(revision a1347a7d9d2bcb49b7e781408978b65acb44ea89)
@@ -59,7 +59,18 @@
 };
 
-static void lo_write_packet(nic_t *nic_data, packet_t *packet)
+static void lo_send_frame(nic_t *nic_data, void *data, size_t size)
 {
-	nic_report_send_ok(nic_data, 1, packet_get_data_length(packet));
+	packet_t *packet;
+	int rc;
+
+	packet = nic_alloc_packet(nic_data, size);
+	if (packet == NULL)
+		return;
+
+	rc = packet_copy_data(packet, data, size);
+	if (rc != EOK)
+		return;
+
+	nic_report_send_ok(nic_data, 1, size);
 	nic_received_noneth_packet(nic_data, packet);
 }
@@ -88,5 +99,5 @@
 	
 	dev->driver_data = nic_data;
-	nic_set_write_packet_handler(nic_data, lo_write_packet);
+	nic_set_send_frame_handler(nic_data, lo_send_frame);
 	
 	int rc = nic_connect_to_services(nic_data);
Index: uspace/drv/nic/ne2k/dp8390.c
===================================================================
--- uspace/drv/nic/ne2k/dp8390.c	(revision f991b6babc87e0deb9b4bf9442366643a976866e)
+++ uspace/drv/nic/ne2k/dp8390.c	(revision a1347a7d9d2bcb49b7e781408978b65acb44ea89)
@@ -404,8 +404,9 @@
  *
  * @param[in,out] ne2k   Network interface structure.
- * @param[in]     packet Frame to be sent.
- *
- */
-void ne2k_send(nic_t *nic_data, packet_t *packet)
+ * @param[in]     data   Pointer to frame data
+ * @param[in]     size   Frame size in bytes
+ *
+ */
+void ne2k_send(nic_t *nic_data, void *data, size_t size)
 {
 	ne2k_t *ne2k = (ne2k_t *) nic_get_specific(nic_data);
@@ -419,6 +420,4 @@
 		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)) {
@@ -428,5 +427,5 @@
 
 	/* Upload the frame to the ethernet card */
-	ne2k_upload(ne2k, buf, ne2k->sq.page * DP_PAGE, size);
+	ne2k_upload(ne2k, data, ne2k->sq.page * DP_PAGE, size);
 	ne2k->sq.dirty = true;
 	ne2k->sq.size = size;
@@ -438,7 +437,4 @@
 	pio_write_8(ne2k->port + DP_CR, CR_TXP | CR_STA);
 	fibril_mutex_unlock(&ne2k->sq_mutex);
-
-	/* Relase packet */
-	nic_release_packet(nic_data, packet);
 }
 
Index: uspace/drv/nic/ne2k/dp8390.h
===================================================================
--- uspace/drv/nic/ne2k/dp8390.h	(revision f991b6babc87e0deb9b4bf9442366643a976866e)
+++ uspace/drv/nic/ne2k/dp8390.h	(revision a1347a7d9d2bcb49b7e781408978b65acb44ea89)
@@ -262,5 +262,5 @@
 extern int ne2k_up(ne2k_t *);
 extern void ne2k_down(ne2k_t *);
-extern void ne2k_send(nic_t *, packet_t *);
+extern void ne2k_send(nic_t *, void *, size_t);
 extern void ne2k_interrupt(nic_t *, uint8_t, uint8_t);
 extern packet_t *ne2k_alloc_packet(nic_t *, size_t);
Index: uspace/drv/nic/ne2k/ne2k.c
===================================================================
--- uspace/drv/nic/ne2k/ne2k.c	(revision f991b6babc87e0deb9b4bf9442366643a976866e)
+++ uspace/drv/nic/ne2k/ne2k.c	(revision a1347a7d9d2bcb49b7e781408978b65acb44ea89)
@@ -343,5 +343,5 @@
 		return ENOMEM;
 	
-	nic_set_write_packet_handler(nic_data, ne2k_send);
+	nic_set_send_frame_handler(nic_data, ne2k_send);
 	nic_set_state_change_handlers(nic_data,
 		ne2k_on_activating, NULL, ne2k_on_stopping);
Index: uspace/drv/nic/rtl8139/driver.c
===================================================================
--- uspace/drv/nic/rtl8139/driver.c	(revision f991b6babc87e0deb9b4bf9442366643a976866e)
+++ uspace/drv/nic/rtl8139/driver.c	(revision a1347a7d9d2bcb49b7e781408978b65acb44ea89)
@@ -389,5 +389,5 @@
 static int rtl8139_on_activated(nic_t *nic_data);
 static int rtl8139_on_stopped(nic_t *nic_data);
-static void rtl8139_write_packet(nic_t *nic_data, packet_t *packet);
+static void rtl8139_send_frame(nic_t *nic_data, void *data, size_t size);
 
 /** Check if the transmit buffer is busy */
@@ -399,9 +399,10 @@
  *
  * @param nic_data  The nic driver data structure
- * @param packet    The packet to send
+ * @param data      Frame data
+ * @param size      Frame size in bytes
  *
  * @return EOK if succeed, error code in the case of error
  */
-static void rtl8139_write_packet(nic_t *nic_data, packet_t *packet)
+static void rtl8139_send_frame(nic_t *nic_data, void *data, size_t size)
 {
 	assert(nic_data);
@@ -409,20 +410,14 @@
 	rtl8139_t *rtl8139 = nic_get_specific(nic_data);
 	assert(rtl8139);
-	ddf_msg(LVL_DEBUG, "Sending packet");
-
-	/* Get the packet data and check if it can be send */
-	size_t packet_length = packet_get_data_length(packet);
-	void *packet_data = packet_get_data(packet);
-
-	assert(packet_data);
-
-	if ((packet_length > RTL8139_PACKET_MAX_LENGTH) || !packet_data) {
-		ddf_msg(LVL_ERROR, "Write packet length error: data %p, length %z", 
-		    packet_data, packet_length);
+	ddf_msg(LVL_DEBUG, "Sending frame");
+
+	if (size > RTL8139_PACKET_MAX_LENGTH) {
+		ddf_msg(LVL_ERROR, "Send frame: frame too long, %zu bytes",
+		    size);
 		nic_report_send_error(rtl8139->nic_data, NIC_SEC_OTHER, 1);
 		goto err_size;
 	}
 
-	assert((packet_length & TSD_SIZE_MASK) == packet_length);
+	assert((size & TSD_SIZE_MASK) == size);
 
 	/* Lock transmitter structure for obtaining next buffer */
@@ -449,10 +444,10 @@
 	assert(!rtl8139_tbuf_busy(tsd));
 
-	/* Write packet data to the buffer, set the size to TSD and clear OWN bit */
-	memcpy(buf_addr, packet_data, packet_length);
+	/* Write frame data to the buffer, set the size to TSD and clear OWN bit */
+	memcpy(buf_addr, data, size);
 
 	/* Set size of the data to send */
 	uint32_t tsd_value = pio_read_32(tsd);
-	tsd_value = rtl8139_tsd_set_size(tsd_value, packet_length);
+	tsd_value = rtl8139_tsd_set_size(tsd_value, size);
 	pio_write_32(tsd, tsd_value);
 
@@ -462,10 +457,8 @@
 	tsd_value &= ~(uint32_t)TSD_OWN;
 	pio_write_32(tsd, tsd_value);
-	nic_release_packet(nic_data, packet);
 	return;
 
 err_busy_no_inc:
 err_size:
-	nic_release_packet(nic_data, packet);
 	return;
 };
@@ -1022,5 +1015,5 @@
 	rtl8139->nic_data = nic_data;
 	nic_set_specific(nic_data, rtl8139);
-	nic_set_write_packet_handler(nic_data, rtl8139_write_packet);
+	nic_set_send_frame_handler(nic_data, rtl8139_send_frame);
 	nic_set_state_change_handlers(nic_data,
 		rtl8139_on_activated, NULL, rtl8139_on_stopped);
