Index: uspace/drv/nic/rtl8169/Makefile
===================================================================
--- uspace/drv/nic/rtl8169/Makefile	(revision fef725d8052254677081e5d39dec1e6d409accb3)
+++ uspace/drv/nic/rtl8169/Makefile	(revision 90782c360313d69e3e1acc99bb45f4ebd3a668d2)
@@ -34,7 +34,5 @@
 
 SOURCES = \
-	driver.c \
-	general.c \
-	defs.c
+	driver.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/nic/rtl8169/defs.h
===================================================================
--- uspace/drv/nic/rtl8169/defs.h	(revision fef725d8052254677081e5d39dec1e6d409accb3)
+++ uspace/drv/nic/rtl8169/defs.h	(revision 90782c360313d69e3e1acc99bb45f4ebd3a668d2)
@@ -87,6 +87,6 @@
 	WAKEUP3LD = 0xa4, /**< Power Management Wakeup frame3 low dword, 8b */
 	WAKEUP3HD = 0xac, /**< Power Management Wakeup frame3 high dword, 8b */
-	WAKEUP2LD = 0xb4, /**< Power Management Wakeup frame4 low dword, 8b */
-	WAKEUP2HD = 0xbc, /**< Power Management Wakeup frame4 high dword, 8b */
+	WAKEUP4LD = 0xb4, /**< Power Management Wakeup frame4 low dword, 8b */
+	WAKEUP4HD = 0xbc, /**< Power Management Wakeup frame4 high dword, 8b */
 	CRC0 = 0xc4, /**< 16-bit CRC of wakeup frame 0, 2b */
 	CRC1 = 0xc6, /**< 16-bit CRC of wakeup frame 1, 2b */
@@ -132,5 +132,5 @@
 	CONFIG2_PCICLKF_SHIFT = 0,
 	CONFIG2_PCICLKF_SIZE = 2
-}'
+};
 
 enum rtl8169_config3 {
@@ -240,5 +240,16 @@
 	ANAR_10_FD = (1 << 6), /**< 10BASE_T full duplex */
 	ANAR_10_HD = (1 << 5), /**< 10BASE_T half duplex */
-	ANAR_SELECTOR = 0x1. /**< Selector */
+	ANAR_SELECTOR = 0x1, /**< Selector */
+};
+
+enum rtl8169_phystatus {
+	PHYSTATUS_TBIEN = (1 << 7), /**< TBI enabled */
+	PHYSTATUS_TXFLOW = (1 << 6), /**< TX flow control enabled */
+	PHYSTATUS_RXFLOW = (1 << 5), /**< RX flow control enabled */
+	PHYSTATUS_1000M = (1 << 4), /**< Link speed is 1000Mbit/s */
+	PHYSTATUS_100M = (1 << 3), /**< Link speed is 100Mbit/s */
+	PHYSTATUS_10M = (1 << 2), /**< Link speed is 10Mbit/s */
+	PHYSTATUS_LINK = (1 << 1), /**< Link up */
+	PHYSTATUS_FDX = (1 << 0), /**< Link is full duplex */
 };
 
Index: uspace/drv/nic/rtl8169/driver.c
===================================================================
--- uspace/drv/nic/rtl8169/driver.c	(revision fef725d8052254677081e5d39dec1e6d409accb3)
+++ uspace/drv/nic/rtl8169/driver.c	(revision 90782c360313d69e3e1acc99bb45f4ebd3a668d2)
@@ -55,4 +55,36 @@
 FIBRIL_MUTEX_INITIALIZE(irq_reg_lock);
 
+static int rtl8169_set_addr(ddf_fun_t *fun, const nic_address_t *addr);
+static int rtl8169_get_device_info(ddf_fun_t *fun, nic_device_info_t *info);
+static int rtl8169_get_cable_state(ddf_fun_t *fun, nic_cable_state_t *state);
+static int rtl8169_get_operation_mode(ddf_fun_t *fun, int *speed,
+    nic_channel_mode_t *duplex, nic_role_t *role);
+static int rtl8169_set_operation_mode(ddf_fun_t *fun, int speed,
+    nic_channel_mode_t duplex, nic_role_t role);
+static int rtl8169_pause_get(ddf_fun_t *fun, nic_result_t *we_send, 
+    nic_result_t *we_receive, uint16_t *time);
+static int rtl8169_pause_set(ddf_fun_t *fun, int allow_send, int allow_receive, 
+    uint16_t time);
+static int rtl8169_autoneg_enable(ddf_fun_t *fun, uint32_t advertisement);
+static int rtl8169_autoneg_disable(ddf_fun_t *fun);
+static int rtl8169_autoneg_probe(ddf_fun_t *fun, uint32_t *advertisement,
+    uint32_t *their_adv, nic_result_t *result, nic_result_t *their_result);
+static int rtl8169_autoneg_restart(ddf_fun_t *fun);
+static int rtl8169_defective_get_mode(ddf_fun_t *fun, uint32_t *mode);
+static int rtl8169_defective_set_mode(ddf_fun_t *fun, uint32_t mode);
+static int rtl8169_on_activated(nic_t *nic_data);
+static int rtl8169_on_stopped(nic_t *nic_data);
+static void rtl8169_send_frame(nic_t *nic_data, void *data, size_t size);
+static void rtl8169_irq_handler(ddf_dev_t *dev, ipc_callid_t iid,
+    ipc_call_t *icall);
+static inline int rtl8169_register_int_handler(nic_t *nic_data);
+static inline void rtl8169_get_hwaddr(rtl8169_t *rtl8169, nic_address_t *addr);
+static inline void rtl8169_set_hwaddr(rtl8169_t *rtl8169, nic_address_t *addr);
+
+static void rtl8169_reset(rtl8169_t *rtl8169);
+static int rtl8169_get_resource_info(ddf_dev_t *dev);
+static int rtl8169_fill_resource_info(ddf_dev_t *dev, const hw_res_list_parsed_t *hw_resources);
+static rtl8169_t *rtl8169_create_dev_data(ddf_dev_t *dev);
+
 /** Network interface options for RTL8169 card driver */
 static nic_iface_t rtl8169_nic_iface = {
@@ -75,4 +107,48 @@
 };
 
+irq_pio_range_t rtl8169_irq_pio_ranges[] = {
+	{
+		.base = 0,
+		.size = RTL8169_IO_SIZE
+	}
+};
+
+irq_cmd_t rtl8169_irq_commands[] = {
+	{
+		/* Get the interrupt status */
+		.cmd = CMD_PIO_READ_16,
+		.addr = NULL,
+		.dstarg = 2
+	},
+	{
+		.cmd = CMD_PREDICATE,
+		.value = 3,
+		.srcarg = 2
+	},
+	{
+		/* Mark interrupts as solved */
+		.cmd = CMD_PIO_WRITE_16,
+		.addr = NULL,
+		.value = 0xFFFF
+	},
+	{
+		/* Disable interrupts until interrupt routine is finished */
+		.cmd = CMD_PIO_WRITE_16,
+		.addr = NULL,
+		.value = 0x0000
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
+
+/** Interrupt code definition */
+irq_code_t rtl8169_irq_code = {
+	.rangecount = sizeof(rtl8169_irq_pio_ranges) / sizeof(irq_pio_range_t),
+	.ranges = rtl8169_irq_pio_ranges,
+	.cmdcount = sizeof(rtl8169_irq_commands) / sizeof(irq_cmd_t),
+	.cmds = rtl8169_irq_commands
+};
+
 /** Basic device operations for RTL8169 driver */
 static ddf_dev_ops_t rtl8169_dev_ops;
@@ -91,7 +167,138 @@
 };
 
+static int rtl8169_get_resource_info(ddf_dev_t *dev)
+{
+	assert(dev);
+
+	nic_t *nic_data = nic_get_from_ddf_dev(dev);
+	assert(nic_data);
+
+	hw_res_list_parsed_t hw_res_parsed;
+	hw_res_list_parsed_init(&hw_res_parsed);
+
+	/* Get hw resources form parent driver */
+	int rc = nic_get_resources(nic_data, &hw_res_parsed);
+	if (rc != EOK)
+		return rc;
+
+	/* Fill resources information to the device */
+	int ret = rtl8169_fill_resource_info(dev, &hw_res_parsed);
+	hw_res_list_parsed_clean(&hw_res_parsed);
+
+	return ret;
+}
+
+static int rtl8169_fill_resource_info(ddf_dev_t *dev, const hw_res_list_parsed_t
+    *hw_resources)
+{
+	assert(dev);
+	assert(hw_resources);
+
+	rtl8169_t *rtl8169 = nic_get_specific(nic_get_from_ddf_dev(dev));
+	assert(rtl8169);
+
+	if (hw_resources->irqs.count != 1) {
+		ddf_msg(LVL_ERROR, "%s device: unexpected irq count", ddf_dev_get_name(dev));
+		return EINVAL;
+	};
+	if (hw_resources->io_ranges.count != 1) {
+		ddf_msg(LVL_ERROR, "%s device: unexpected io ranges count", ddf_dev_get_name(dev));
+		return EINVAL;
+	}
+
+	rtl8169->irq = hw_resources->irqs.irqs[0];
+	ddf_msg(LVL_DEBUG, "%s device: irq 0x%x assigned", ddf_dev_get_name(dev), rtl8169->irq);
+
+	rtl8169->regs_phys = (void *)((size_t)RNGABS(hw_resources->io_ranges.ranges[0]));
+	if (hw_resources->io_ranges.ranges[0].size < RTL8169_IO_SIZE) {
+		ddf_msg(LVL_ERROR, "I/O range assigned to the device "
+		    "%s is too small.", ddf_dev_get_name(dev));
+		return EINVAL;
+	}
+	ddf_msg(LVL_DEBUG, "%s device: i/o addr %p assigned.", ddf_dev_get_name(dev), rtl8169->regs_phys);
+
+	return EOK;
+}
+
+static rtl8169_t *rtl8169_create_dev_data(ddf_dev_t *dev)
+{
+	assert(dev);
+	assert(!nic_get_from_ddf_dev(dev));
+
+	nic_t *nic_data = nic_create_and_bind(dev);
+	if (!nic_data)
+		return NULL;
+
+	rtl8169_t *rtl8169 = malloc(sizeof(rtl8169_t));
+	if (!rtl8169) {
+		nic_unbind_and_destroy(dev);
+		return NULL;
+	}
+
+	memset(rtl8169, 0, sizeof(rtl8169_t));
+
+	rtl8169->nic_data = nic_data;
+	nic_set_specific(nic_data, rtl8169);
+	nic_set_send_frame_handler(nic_data, rtl8169_send_frame);
+	nic_set_state_change_handlers(nic_data,
+		rtl8169_on_activated, NULL, rtl8169_on_stopped);
+	nic_set_filtering_change_handlers(nic_data,
+		NULL, NULL, NULL, NULL, NULL);
+
+	fibril_mutex_initialize(&rtl8169->rx_lock);
+	fibril_mutex_initialize(&rtl8169->tx_lock);
+
+	nic_set_wol_max_caps(nic_data, NIC_WV_BROADCAST, 1);
+	nic_set_wol_max_caps(nic_data, NIC_WV_LINK_CHANGE, 1);
+	nic_set_wol_max_caps(nic_data, NIC_WV_MAGIC_PACKET, 1);
+
+	return rtl8169;
+}
+
+
+static int rtl8169_dev_initialize(ddf_dev_t *dev)
+{
+	int ret;
+
+	rtl8169_t *rtl8169 = rtl8169_create_dev_data(dev);
+	if (rtl8169 == NULL) {
+		ddf_msg(LVL_ERROR, "Not enough memory for initializing %s.", ddf_dev_get_name(dev));
+		return ENOMEM;
+	}
+
+	ret = rtl8169_get_resource_info(dev);
+	if (ret != EOK) {
+		ddf_msg(LVL_ERROR, "Can't obtain H/W resources information");
+		goto failed;
+	}
+
+	ddf_msg(LVL_DEBUG, "The device is initialized");
+	return ret;
+	
+failed:
+	ddf_msg(LVL_ERROR, "The device initialization failed");
+//	rtl8139_dev_cleanup(dev);
+	return ret;
+
+}
+
+inline static int rtl8169_register_int_handler(nic_t *nic_data)
+{
+	rtl8169_t *rtl8169 = nic_get_specific(nic_data);
+
+	rtl8169_irq_code.ranges[0].base = (uintptr_t) rtl8169->regs;
+	rtl8169_irq_code.cmds[0].addr = rtl8169->regs + ISR;
+	rtl8169_irq_code.cmds[2].addr = rtl8169->regs + ISR;
+	rtl8169_irq_code.cmds[3].addr = rtl8169->regs + IMR;
+	int rc = register_interrupt_handler(nic_get_ddf_dev(nic_data),
+	    rtl8169->irq, rtl8169_irq_handler, &rtl8169_irq_code);
+
+	return rc;
+}
+
 static int rtl8169_dev_add(ddf_dev_t *dev)
 {
 	ddf_fun_t *fun;
+	nic_address_t nic_addr;
 	int rc;
 
@@ -99,4 +306,5 @@
 	ddf_msg(LVL_NOTE, "RTL8169_dev_add %s (handle = %zu)",
 	    ddf_dev_get_name(dev), ddf_dev_get_handle(dev));
+
 
 	/* Init structures */
@@ -105,4 +313,86 @@
 		return rc;
 
+	nic_t *nic_data = nic_get_from_ddf_dev(dev);
+	rtl8169_t *rtl8169 = nic_get_specific(nic_data);
+
+	/* Map register space */
+	rc = pio_enable(rtl8169->regs_phys, RTL8169_IO_SIZE, &rtl8169->regs);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Cannot map register space for device %s.",
+		    ddf_dev_get_name(dev));
+		goto err_destroy;
+	}
+
+	/* Read MAC address and print it */
+	rtl8169_get_hwaddr(rtl8169, &nic_addr);
+	ddf_msg(LVL_NOTE, "MAC address: %02x:%02x:%02x:%02x:%02x:%02x",
+	    nic_addr.address[0], nic_addr.address[1],
+	    nic_addr.address[2], nic_addr.address[3],
+	    nic_addr.address[4], nic_addr.address[5]);
+
+	rc = nic_report_address(nic_data, &nic_addr);
+	if (rc != EOK)
+		goto err_pio;
+
+	rc = rtl8169_register_int_handler(nic_data);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed to register IRQ handler (%d)", rc);
+		goto err_irq;
+
+	}
+
+	ddf_msg(LVL_DEBUG, "Interrupt handler installed");
+
+	rtl8169_reset(rtl8169);
+	pio_write_16(rtl8169->regs + IMR, 0xffff);
+
+	uint8_t cr_value = pio_read_8(rtl8169->regs + CR);
+	pio_write_8(rtl8169->regs + CR, cr_value | CR_TE | CR_RE);
+
+	rc = nic_connect_to_services(nic_data);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed to connect to services (%d)", rc);
+		goto err_irq;
+	}
+
+	fun = ddf_fun_create(nic_get_ddf_dev(nic_data), fun_exposed, "port0");
+	if (fun == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating device function");
+		goto err_srv;
+	}
+
+	nic_set_ddf_fun(nic_data, fun);
+	ddf_fun_set_ops(fun, &rtl8169_dev_ops);
+	ddf_fun_data_implant(fun, nic_data);
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding device function");
+		goto err_fun_create;
+	}
+
+	rc = ddf_fun_add_to_category(fun, DEVICE_CATEGORY_NIC);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed adding function to category");
+		goto err_fun_bind;
+	}
+
+	ddf_msg(LVL_NOTE, "The %s device has been successfully initialized.",
+	    ddf_dev_get_name(dev));
+	return EOK;
+
+err_fun_bind:
+	ddf_fun_unbind(fun);
+err_fun_create:
+	ddf_fun_destroy(fun);
+err_srv:
+	/* XXX Disconnect from services */
+err_irq:
+	//unregister_interrupt_handler(dev, rtl8169->irq);
+err_pio:
+err_destroy:
+	//rtl8169_dev_cleanup(dev);
+	return rc;
+
 	return EOK;
 }
@@ -139,5 +429,5 @@
 {
 	return EOK;
-{
+}
 
 static int rtl8169_pause_set(ddf_fun_t *fun, int allow_send, int allow_receive, 
@@ -178,7 +468,103 @@
 }
 
+static int rtl8169_on_activated(nic_t *nic_data)
+{
+	ddf_msg(LVL_NOTE, "Activating device");
+
+	rtl8169_t *rtl8169 = nic_get_specific(nic_data);
+
+	pio_write_16(rtl8169->regs + IMR, 0xffff);
+
+	return EOK;
+}
+
+static int rtl8169_on_stopped(nic_t *nic_data)
+{
+	return EOK;
+}
+
+inline static void rtl8169_reset(rtl8169_t *rtl8169)
+{
+	pio_write_8(rtl8169->regs + CR, CR_RST);
+	memory_barrier();
+	while (pio_read_8(rtl8169->regs + CR) & CR_RST) {
+		usleep(1);
+		read_barrier();
+	}
+}
+
+static void rtl8169_link_change(ddf_dev_t *dev)
+{
+	nic_t *nic_data = nic_get_from_ddf_dev(dev);
+	rtl8169_t *rtl8169 = nic_get_specific(nic_data);
+
+	uint8_t phystatus = pio_read_8(rtl8169->regs + PHYSTATUS);
+
+	if (phystatus & PHYSTATUS_LINK) {
+		ddf_msg(LVL_NOTE, "%s: Link up", ddf_dev_get_name(dev));
+
+		int speed;
+		const char *fdx = phystatus & PHYSTATUS_FDX ? "full duplex" : "half duplex";
+
+		if (phystatus & PHYSTATUS_10M)
+			speed = 10;
+
+		if (phystatus & PHYSTATUS_100M)
+			speed = 100;
+
+		if (phystatus & PHYSTATUS_1000M)
+			speed = 1000;
+
+		ddf_msg(LVL_NOTE, "%s: Speed %dMbit/s, %s", ddf_dev_get_name(dev), speed, fdx);
+	} else {
+		ddf_msg(LVL_NOTE, "%s: Link down", ddf_dev_get_name(dev));
+	}
+
+}
+
+static void rtl8169_irq_handler(ddf_dev_t *dev, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	assert(dev);
+	assert(icall);
+
+	ddf_msg(LVL_NOTE, "rtl8169_irq_handler()");
+
+	uint16_t isr = (uint16_t) IPC_GET_ARG2(*icall);
+	nic_t *nic_data = nic_get_from_ddf_dev(dev);
+	rtl8169_t *rtl8169 = nic_get_specific(nic_data);
+
+	/* Packet underrun or link change */
+	if (isr & INT_PUN)
+		rtl8169_link_change(dev);	
+
+	pio_write_16(rtl8169->regs + IMR, 0xffff);
+}
+
 static void rtl8169_send_frame(nic_t *nic_data, void *data, size_t size)
 {
 
+}
+
+static inline void rtl8169_get_hwaddr(rtl8169_t *rtl8169, nic_address_t *addr)
+{
+	int i;
+
+	assert(rtl8169);
+	assert(addr);
+
+	for (i = 0; i < 6; i++)
+		addr->address[i] = pio_read_8(rtl8169->regs + MAC0 + i);
+}
+
+static inline void rtl8169_set_hwaddr(rtl8169_t *rtl8169, nic_address_t *addr)
+{
+	int i;
+
+	assert(rtl8169);
+	assert(addr);
+
+	for (i = 0; i < 6; i++)
+		addr->address[i] = pio_read_8(rtl8169->regs + MAC0 + i);
 }
 
Index: uspace/drv/nic/rtl8169/driver.h
===================================================================
--- uspace/drv/nic/rtl8169/driver.h	(revision fef725d8052254677081e5d39dec1e6d409accb3)
+++ uspace/drv/nic/rtl8169/driver.h	(revision 90782c360313d69e3e1acc99bb45f4ebd3a668d2)
@@ -38,3 +38,50 @@
 #define NAME  "rtl8169"
 
+#define	TX_BUFF_COUNT	16
+
+/** RTL8139 device data */
+typedef struct rtl8169_data {
+	/** I/O address of the device */
+	void *regs_phys;
+	/** Mapped I/O port */
+	void *regs;
+	/** The irq assigned */
+	int irq;
+
+	/** Mask of the turned interupts (IMR value) */
+	uint16_t int_mask;
+
+	/** The memory allocated for the transmittion buffers
+	 *  Each buffer takes 2kB
+	 */
+	uintptr_t tx_buff_phys;
+	void *tx_buff_virt;
+
+	/** Virtual adresses of the Tx buffers */
+	void *tx_buff[TX_BUFF_COUNT];
+
+	/** The nubmer of the next buffer to use, index = tx_next % TX_BUFF_COUNT */
+	size_t tx_next;
+	/** The number of the first used buffer in the row
+	 *
+	 *  tx_used is in the interval tx_next - TX_BUFF_COUNT and tx_next:
+	 *  	tx_next - TX_BUFF_COUNT: there is no useable Tx descriptor
+	 *  	tx_next: all Tx descriptors are can be used
+	 */
+	size_t tx_used;
+
+	/** Buffer for receiving frames */
+	uintptr_t rx_buff_phys;
+	void *rx_buff_virt;
+
+	/** Lock for receiver */
+	fibril_mutex_t rx_lock;
+	/** Lock for transmitter */
+	fibril_mutex_t tx_lock;
+
+	/** Backward pointer to nic_data */
+	nic_t *nic_data;
+
+} rtl8169_t;
+
 #endif
