Index: uspace/drv/block/ahci/ahci.c
===================================================================
--- uspace/drv/block/ahci/ahci.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/block/ahci/ahci.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -34,5 +34,4 @@
 #include <errno.h>
 #include <stdio.h>
-#include <devman.h>
 #include <ddf/interrupt.h>
 #include <ddf/log.h>
@@ -160,4 +159,16 @@
 };
 
+/** Get SATA structure from DDF function. */
+static sata_dev_t *fun_sata_dev(ddf_fun_t *fun)
+{
+	return ddf_fun_data_get(fun);
+}
+
+/** Get AHCI structure from DDF device. */
+static ahci_dev_t *dev_ahci_dev(ddf_dev_t *dev)
+{
+	return ddf_dev_data_get(dev);
+}
+
 /** Get SATA device name.
  *
@@ -172,5 +183,5 @@
     size_t sata_dev_name_length, char *sata_dev_name)
 {
-	sata_dev_t *sata = (sata_dev_t *) fun->driver_data;
+	sata_dev_t *sata = fun_sata_dev(fun);
 	str_cpy(sata_dev_name, sata_dev_name_length, sata->model);
 	return EOK;
@@ -187,5 +198,5 @@
 static int ahci_get_num_blocks(ddf_fun_t *fun, uint64_t *num_blocks)
 {
-	sata_dev_t *sata = (sata_dev_t *) fun->driver_data;
+	sata_dev_t *sata = fun_sata_dev(fun);
 	*num_blocks = sata->blocks;
 	return EOK;
@@ -202,5 +213,5 @@
 static int ahci_get_block_size(ddf_fun_t *fun, size_t *block_size)
 {
-	sata_dev_t *sata = (sata_dev_t *) fun->driver_data;
+	sata_dev_t *sata = fun_sata_dev(fun);
 	*block_size = sata->block_size;
 	return EOK;
@@ -220,5 +231,5 @@
     size_t count, void *buf)
 {
-	sata_dev_t *sata = (sata_dev_t *) fun->driver_data;
+	sata_dev_t *sata = fun_sata_dev(fun);
 	
 	void *phys;
@@ -263,5 +274,5 @@
     size_t count, void *buf)
 {
-	sata_dev_t *sata = (sata_dev_t *) fun->driver_data;
+	sata_dev_t *sata = fun_sata_dev(fun);
 	
 	void *phys;
@@ -885,5 +896,5 @@
 static void ahci_interrupt(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
 {
-	ahci_dev_t *ahci = (ahci_dev_t *) dev->driver_data;
+	ahci_dev_t *ahci = dev_ahci_dev(dev);
 	unsigned int port = IPC_GET_ARG1(*icall);
 	ahci_port_is_t pxis = IPC_GET_ARG2(*icall);
@@ -919,5 +930,5 @@
  *
  */
-static sata_dev_t *ahci_sata_allocate(volatile ahci_port_t *port)
+static sata_dev_t *ahci_sata_allocate(ahci_dev_t *ahci, volatile ahci_port_t *port)
 {
 	size_t size = 4096;
@@ -926,11 +937,13 @@
 	void *virt_cmd = NULL;
 	void *virt_table = NULL;
-	
-	sata_dev_t *sata = malloc(sizeof(sata_dev_t));
+	ddf_fun_t *fun;
+	
+	fun = ddf_fun_create(ahci->dev, fun_exposed, NULL);
+	
+	sata_dev_t *sata = ddf_fun_data_alloc(fun, sizeof(sata_dev_t));
 	if (sata == NULL)
 		return NULL;
 	
-	bzero(sata, sizeof(sata_dev_t));
-	
+	sata->fun = fun;
 	sata->port = port;
 	
@@ -1029,5 +1042,7 @@
 {
 	ddf_fun_t *fun = NULL;
-	sata_dev_t *sata = ahci_sata_allocate(port);
+	int rc;
+	
+	sata_dev_t *sata = ahci_sata_allocate(ahci, port);
 	if (sata == NULL)
 		return EINTR;
@@ -1061,13 +1076,13 @@
 	fibril_mutex_unlock(&sata_devices_count_lock);
 	
-	fun = ddf_fun_create(dev, fun_exposed, sata_dev_name);
-	if (fun == NULL) {
-		ddf_msg(LVL_ERROR, "Failed creating function.");
+	rc= ddf_fun_set_name(sata->fun, sata_dev_name);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed setting function name.");
 		goto error;
 	}
 	
-	fun->ops = &ahci_ops;
-	fun->driver_data = sata;
-	int rc = ddf_fun_bind(fun);
+	ddf_fun_set_ops(fun, &ahci_ops);
+	
+	rc = ddf_fun_bind(fun);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed binding function.");
@@ -1119,9 +1134,12 @@
 static ahci_dev_t *ahci_ahci_create(ddf_dev_t *dev)
 {
-	ahci_dev_t *ahci = malloc(sizeof(ahci_dev_t));
+	ahci_dev_t *ahci = ddf_dev_data_alloc(dev, sizeof(ahci_dev_t));
 	if (!ahci)
 		return NULL;
 	
-	bzero(ahci, sizeof(ahci_dev_t));
+	/* Connect to parent device */
+	ahci->parent_sess = ddf_dev_parent_sess_create(dev, EXCHANGE_SERIALIZE);
+	if (ahci->parent_sess == NULL)
+		return NULL;
 	
 	ahci->dev = dev;
@@ -1129,5 +1147,5 @@
 	hw_res_list_parsed_t hw_res_parsed;
 	hw_res_list_parsed_init(&hw_res_parsed);
-	if (hw_res_get_list_parsed(dev->parent_sess, &hw_res_parsed, 0) != EOK)
+	if (hw_res_get_list_parsed(ahci->parent_sess, &hw_res_parsed, 0) != EOK)
 		goto error_get_res_parsed;
 	
@@ -1211,13 +1229,13 @@
 	
 	/* Set master latency timer. */
-	pci_config_space_write_8(ahci->dev->parent_sess, AHCI_PCI_MLT, 32);
+	pci_config_space_write_8(ahci->parent_sess, AHCI_PCI_MLT, 32);
 	
 	/* Enable PCI interrupt and bus mastering */
 	ahci_pcireg_cmd_t cmd;
 	
-	pci_config_space_read_16(ahci->dev->parent_sess, AHCI_PCI_CMD, &cmd.u16);
+	pci_config_space_read_16(ahci->parent_sess, AHCI_PCI_CMD, &cmd.u16);
 	cmd.id = 0;
 	cmd.bme = 1;
-	pci_config_space_write_16(ahci->dev->parent_sess, AHCI_PCI_CMD, cmd.u16);
+	pci_config_space_write_16(ahci->parent_sess, AHCI_PCI_CMD, cmd.u16);
 	
 	/* Enable AHCI and interrupt. */
@@ -1237,16 +1255,8 @@
 static int ahci_dev_add(ddf_dev_t *dev)	
 {
-	/* Connect to parent device */
-	dev->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
-	    dev->handle, IPC_FLAG_BLOCKING);
-	if (dev->parent_sess == NULL)
-		return EINTR;
-	
 	ahci_dev_t *ahci = ahci_ahci_create(dev);
 	if (ahci == NULL)
 		goto error;
 	
-	dev->driver_data = ahci;
-	
 	/* Start AHCI hardware. */
 	ahci_ahci_hw_start(ahci);
@@ -1258,5 +1268,4 @@
 	
 error:
-	async_hangup(dev->parent_sess);
 	return EINTR;
 }
Index: uspace/drv/block/ahci/ahci.h
===================================================================
--- uspace/drv/block/ahci/ahci.h	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/block/ahci/ahci.h	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -34,4 +34,5 @@
 #define __AHCI_H__
 
+#include <async.h>
 #include <sys/types.h>
 #include <devman.h>
@@ -50,4 +51,7 @@
 	/** Pointers to sata devices. */
 	void *sata_devs[AHCI_MAX_PORTS];
+
+	/** Parent session */
+	async_sess_t *parent_sess;
 } ahci_dev_t;
 
@@ -56,4 +60,7 @@
 	/** Pointer to AHCI device. */
 	ahci_dev_t *ahci;
+	
+	/** Pointer to ddf function. */
+	ddf_fun_t *fun;
 	
 	/** SATA port number (0-31). */
Index: uspace/drv/bus/isa/isa.c
===================================================================
--- uspace/drv/bus/isa/isa.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/isa/isa.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -73,10 +73,4 @@
 #define CHILD_FUN_CONF_PATH "/drv/isa/isa.dev"
 
-/** Obtain soft-state from device node */
-#define ISA_BUS(dev) ((isa_bus_t *) ((dev)->driver_data))
-
-/** Obtain soft-state from function node */
-#define ISA_FUN(fun) ((isa_fun_t *) ((fun)->driver_data))
-
 #define ISA_MAX_HW_RES 5
 
@@ -95,7 +89,19 @@
 } isa_fun_t;
 
+/** Obtain soft-state from device node */
+static isa_bus_t *isa_bus(ddf_dev_t *dev)
+{
+	return ddf_dev_data_get(dev);
+}
+
+/** Obtain soft-state from function node */
+static isa_fun_t *isa_fun(ddf_fun_t *fun)
+{
+	return ddf_fun_data_get(fun);
+}
+
 static hw_resource_list_t *isa_get_fun_resources(ddf_fun_t *fnode)
 {
-	isa_fun_t *fun = ISA_FUN(fnode);
+	isa_fun_t *fun = isa_fun(fnode);
 	assert(fun != NULL);
 
@@ -107,5 +113,5 @@
 	/* This is an old ugly way, copied from pci driver */
 	assert(fnode);
-	isa_fun_t *isa_fun = fnode->driver_data;
+	isa_fun_t *fun = isa_fun(fnode);
 
 	sysarg_t apic;
@@ -123,6 +129,5 @@
 		return false;
 
-	assert(isa_fun);
-	const hw_resource_list_t *res = &isa_fun->hw_resources;
+	const hw_resource_list_t *res = &fun->hw_resources;
 	assert(res);
 	for (size_t i = 0; i < res->count; ++i) {
@@ -150,6 +155,6 @@
 {
 	assert(fnode);
-	isa_fun_t *isa_fun = fnode->driver_data;
-	const hw_resource_list_t *res = &isa_fun->hw_resources;
+	isa_fun_t *fun = isa_fun(fnode);
+	const hw_resource_list_t *res = &fun->hw_resources;
 	assert(res);
 	
@@ -339,5 +344,5 @@
 
 		ddf_msg(LVL_NOTE, "Added irq 0x%x to function %s", irq,
-		    fun->fnode->name);
+		    ddf_fun_get_name(fun->fnode));
 	}
 }
@@ -355,5 +360,5 @@
 			fun->hw_resources.count++;
 			ddf_msg(LVL_NOTE, "Added dma 0x%x to function %s", dma,
-			    fun->fnode->name);
+			    ddf_fun_get_name(fun->fnode));
 			
 			return;
@@ -366,5 +371,5 @@
 			fun->hw_resources.count++;
 			ddf_msg(LVL_NOTE, "Added dma 0x%x to function %s", dma,
-			    fun->fnode->name);
+			    ddf_fun_get_name(fun->fnode));
 			
 			return;
@@ -372,5 +377,5 @@
 		
 		ddf_msg(LVL_WARN, "Skipped dma 0x%x for function %s", dma,
-		    fun->fnode->name);
+		    ddf_fun_get_name(fun->fnode));
 	}
 }
@@ -391,5 +396,5 @@
 		ddf_msg(LVL_NOTE, "Added io range (addr=0x%x, size=0x%x) to "
 		    "function %s", (unsigned int) addr, (unsigned int) len,
-		    fun->fnode->name);
+		    ddf_fun_get_name(fun->fnode));
 	}
 }
@@ -463,5 +468,5 @@
 	if (val == end) {
 		ddf_msg(LVL_ERROR, "Cannot read match score for function "
-		    "%s.", fun->fnode->name);
+		    "%s.", ddf_fun_get_name(fun->fnode));
 		return;
 	}
@@ -471,10 +476,10 @@
 	if (id == NULL) {
 		ddf_msg(LVL_ERROR, "Cannot read match ID for function %s.",
-		    fun->fnode->name);
+		    ddf_fun_get_name(fun->fnode));
 		return;
 	}
 
 	ddf_msg(LVL_DEBUG, "Adding match id '%s' with score %d to "
-	    "function %s", id, score, fun->fnode->name);
+	    "function %s", id, score, ddf_fun_get_name(fun->fnode));
 
 	rc = ddf_fun_add_match_id(fun->fnode, id, score);
@@ -579,7 +584,7 @@
 
 	/* Set device operations to the device. */
-	fun->fnode->ops = &isa_fun_ops;
-
-	ddf_msg(LVL_DEBUG, "Binding function %s.", fun->fnode->name);
+	ddf_fun_set_ops(fun->fnode, &isa_fun_ops);
+
+	ddf_msg(LVL_DEBUG, "Binding function %s.", ddf_fun_get_name(fun->fnode));
 
 	/* XXX Handle error */
@@ -614,5 +619,5 @@
 
 	ddf_msg(LVL_DEBUG, "isa_dev_add, device handle = %d",
-	    (int) dev->handle);
+	    (int) ddf_dev_get_handle(dev));
 
 	isa = ddf_dev_data_alloc(dev, sizeof(isa_bus_t));
@@ -652,5 +657,5 @@
 static int isa_dev_remove(ddf_dev_t *dev)
 {
-	isa_bus_t *isa = ISA_BUS(dev);
+	isa_bus_t *isa = isa_bus(dev);
 	int rc;
 
@@ -664,5 +669,5 @@
 		if (rc != EOK) {
 			fibril_mutex_unlock(&isa->mutex);
-			ddf_msg(LVL_ERROR, "Failed offlining %s", fun->fnode->name);
+			ddf_msg(LVL_ERROR, "Failed offlining %s", ddf_fun_get_name(fun->fnode));
 			return rc;
 		}
@@ -671,5 +676,5 @@
 		if (rc != EOK) {
 			fibril_mutex_unlock(&isa->mutex);
-			ddf_msg(LVL_ERROR, "Failed unbinding %s", fun->fnode->name);
+			ddf_msg(LVL_ERROR, "Failed unbinding %s", ddf_fun_get_name(fun->fnode));
 			return rc;
 		}
Index: uspace/drv/bus/pci/pciintel/pci.c
===================================================================
--- uspace/drv/bus/pci/pciintel/pci.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/pci/pciintel/pci.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -50,6 +50,4 @@
 #include <ddf/driver.h>
 #include <ddf/log.h>
-#include <devman.h>
-#include <ipc/devman.h>
 #include <ipc/dev_iface.h>
 #include <ipc/irc.h>
@@ -71,11 +69,22 @@
 
 /** Obtain PCI function soft-state from DDF function node */
-#define PCI_FUN(fnode) ((pci_fun_t *) (fnode)->driver_data)
+static pci_fun_t *pci_fun(ddf_fun_t *fnode)
+{
+	return ddf_fun_data_get(fnode);
+}
 
 /** Obtain PCI bus soft-state from DDF device node */
-#define PCI_BUS(dnode) ((pci_bus_t *) (dnode)->driver_data)
+#if 0
+static pci_bus_t *pci_bus(ddf_dev_t *dnode)
+{
+	return ddf_dev_data_get(dnode);
+}
+#endif
 
 /** Obtain PCI bus soft-state from function soft-state */
-#define PCI_BUS_FROM_FUN(fun) ((fun)->busptr)
+static pci_bus_t *pci_bus_from_fun(pci_fun_t *fun)
+{
+	return fun->busptr;
+}
 
 /** Max is 47, align to something nice. */
@@ -84,5 +93,5 @@
 static hw_resource_list_t *pciintel_get_resources(ddf_fun_t *fnode)
 {
-	pci_fun_t *fun = PCI_FUN(fnode);
+	pci_fun_t *fun = pci_fun(fnode);
 	
 	if (fun == NULL)
@@ -95,5 +104,5 @@
 	/* This is an old ugly way */
 	assert(fnode);
-	pci_fun_t *dev_data = (pci_fun_t *) fnode->driver_data;
+	pci_fun_t *dev_data = pci_fun(fnode);
 	
 	sysarg_t apic;
@@ -138,5 +147,5 @@
 	if (address > 252)
 		return EINVAL;
-	pci_conf_write_32(PCI_FUN(fun), address, data);
+	pci_conf_write_32(pci_fun(fun), address, data);
 	return EOK;
 }
@@ -147,5 +156,5 @@
 	if (address > 254)
 		return EINVAL;
-	pci_conf_write_16(PCI_FUN(fun), address, data);
+	pci_conf_write_16(pci_fun(fun), address, data);
 	return EOK;
 }
@@ -156,5 +165,5 @@
 	if (address > 255)
 		return EINVAL;
-	pci_conf_write_8(PCI_FUN(fun), address, data);
+	pci_conf_write_8(pci_fun(fun), address, data);
 	return EOK;
 }
@@ -165,5 +174,5 @@
 	if (address > 252)
 		return EINVAL;
-	*data = pci_conf_read_32(PCI_FUN(fun), address);
+	*data = pci_conf_read_32(pci_fun(fun), address);
 	return EOK;
 }
@@ -174,5 +183,5 @@
 	if (address > 254)
 		return EINVAL;
-	*data = pci_conf_read_16(PCI_FUN(fun), address);
+	*data = pci_conf_read_16(pci_fun(fun), address);
 	return EOK;
 }
@@ -183,5 +192,5 @@
 	if (address > 255)
 		return EINVAL;
-	*data = pci_conf_read_8(PCI_FUN(fun), address);
+	*data = pci_conf_read_8(pci_fun(fun), address);
 	return EOK;
 }
@@ -225,5 +234,5 @@
 static void pci_conf_read(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
 {
-	pci_bus_t *bus = PCI_BUS_FROM_FUN(fun);
+	pci_bus_t *bus = pci_bus_from_fun(fun);
 	
 	fibril_mutex_lock(&bus->conf_mutex);
@@ -252,5 +261,5 @@
 static void pci_conf_write(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
 {
-	pci_bus_t *bus = PCI_BUS_FROM_FUN(fun);
+	pci_bus_t *bus = pci_bus_from_fun(fun);
 	
 	fibril_mutex_lock(&bus->conf_mutex);
@@ -480,5 +489,5 @@
 	if (range_addr != 0) {
 		ddf_msg(LVL_DEBUG, "Function %s : address = %" PRIx64
-		    ", size = %x", fun->fnode->name, range_addr,
+		    ", size = %x", ddf_fun_get_name(fun->fnode), range_addr,
 		    (unsigned int) range_size);
 	}
@@ -506,5 +515,5 @@
 	hw_res_list->count++;
 	
-	ddf_msg(LVL_NOTE, "Function %s uses irq %x.", fun->fnode->name, irq);
+	ddf_msg(LVL_NOTE, "Function %s uses irq %x.", ddf_fun_get_name(fun->fnode), irq);
 }
 
@@ -523,6 +532,6 @@
 void pci_bus_scan(pci_bus_t *bus, int bus_num) 
 {
-	ddf_fun_t *fnode;
 	pci_fun_t *fun;
+	int rc;
 	
 	int child_bus = 0;
@@ -531,11 +540,12 @@
 	uint8_t header_type;
 	
-	fun = pci_fun_new(bus);
-	
 	for (dnum = 0; dnum < 32; dnum++) {
 		multi = true;
 		for (fnum = 0; multi && fnum < 8; fnum++) {
+			fun = pci_fun_new(bus);
+			
 			pci_fun_init(fun, bus_num, dnum, fnum);
 			if (fun->vendor_id == 0xffff) {
+				pci_fun_delete(fun);
 				/*
 				 * The device is not present, go on scanning the
@@ -559,15 +569,15 @@
 			if (fun_name == NULL) {
 				ddf_msg(LVL_ERROR, "Out of memory.");
+				pci_fun_delete(fun);
 				return;
 			}
 			
-			fnode = ddf_fun_create(bus->dnode, fun_inner, fun_name);
+			rc = ddf_fun_set_name(fun->fnode, fun_name);
 			free(fun_name);
-			if (fnode == NULL) {
-				ddf_msg(LVL_ERROR, "Failed creating function.");
+			if (rc != EOK) {
+				ddf_msg(LVL_ERROR, "Failed setting function name.");
+				pci_fun_delete(fun);
 				return;
 			}
-			
-			fun->fnode = fnode;
 			
 			pci_alloc_resource_list(fun);
@@ -575,17 +585,14 @@
 			pci_read_interrupt(fun);
 			
-			fnode->ops = &pci_fun_ops;
-			fnode->driver_data = fun;
+			ddf_fun_set_ops(fun->fnode, &pci_fun_ops);
 			
 			ddf_msg(LVL_DEBUG, "Adding new function %s.",
-			    fnode->name);
+			    ddf_fun_get_name(fun->fnode));
 			
 			pci_fun_create_match_ids(fun);
 			
-			if (ddf_fun_bind(fnode) != EOK) {
+			if (ddf_fun_bind(fun->fnode) != EOK) {
 				pci_clean_resource_list(fun);
-				clean_match_ids(&fnode->match_ids);
-				free((char *) fnode->name);
-				fnode->name = NULL;
+				pci_fun_delete(fun);
 				continue;
 			}
@@ -601,12 +608,5 @@
 					pci_bus_scan(bus, child_bus);
 			}
-			
-			fun = pci_fun_new(bus);
 		}
-	}
-	
-	if (fun->vendor_id == 0xffff) {
-		/* Free the auxiliary function structure. */
-		pci_fun_delete(fun);
 	}
 }
@@ -617,8 +617,8 @@
 	ddf_fun_t *ctl = NULL;
 	bool got_res = false;
+	async_sess_t *sess;
 	int rc;
 	
 	ddf_msg(LVL_DEBUG, "pci_dev_add");
-	dnode->parent_sess = NULL;
 	
 	bus = ddf_dev_data_alloc(dnode, sizeof(pci_bus_t));
@@ -631,9 +631,7 @@
 
 	bus->dnode = dnode;
-	dnode->driver_data = bus;
-	
-	dnode->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
-	    dnode->handle, IPC_FLAG_BLOCKING);
-	if (!dnode->parent_sess) {
+	
+	sess = ddf_dev_parent_sess_create(dnode, EXCHANGE_SERIALIZE);
+	if (sess == NULL) {
 		ddf_msg(LVL_ERROR, "pci_dev_add failed to connect to the "
 		    "parent driver.");
@@ -644,5 +642,5 @@
 	hw_resource_list_t hw_resources;
 	
-	rc = hw_res_get_resource_list(dnode->parent_sess, &hw_resources);
+	rc = hw_res_get_resource_list(sess, &hw_resources);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "pci_dev_add failed to get hw resources "
@@ -708,7 +706,4 @@
 	
 fail:
-	if (dnode->parent_sess)
-		async_hangup(dnode->parent_sess);
-	
 	if (got_res)
 		hw_res_clean_resource_list(&hw_resources);
@@ -742,10 +737,16 @@
 {
 	pci_fun_t *fun;
-	
-	fun = (pci_fun_t *) calloc(1, sizeof(pci_fun_t));
+	ddf_fun_t *fnode;
+	
+	fnode = ddf_fun_create(bus->dnode, fun_inner, NULL);
+	if (fnode == NULL)
+		return NULL;
+
+	fun = ddf_fun_data_alloc(fnode, sizeof(pci_fun_t));
 	if (fun == NULL)
 		return NULL;
 
 	fun->busptr = bus;
+	fun->fnode = fnode;
 	return fun;
 }
@@ -766,7 +767,7 @@
 void pci_fun_delete(pci_fun_t *fun)
 {
-	assert(fun != NULL);
 	hw_res_clean_resource_list(&fun->hw_resources);
-	free(fun);
+	if (fun->fnode != NULL)
+		ddf_fun_destroy(fun->fnode);
 }
 
Index: uspace/drv/bus/usb/ehci/main.c
===================================================================
--- uspace/drv/bus/usb/ehci/main.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/ehci/main.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -84,5 +84,5 @@
 	CHECK_RET_RETURN(ret,
 	    "Failed to get memory addresses for %" PRIun ": %s.\n",
-	    device->handle, str_error(ret));
+	    ddf_dev_get_handle(device), str_error(ret));
 	usb_log_info("Memory mapped regs at 0x%" PRIxn " (size %zu), IRQ %d.\n",
 	    reg_base, reg_size, irq);
@@ -104,5 +104,5 @@
 	/* High Speed, no bandwidth */
 	hcd_init(ehci_hc, USB_SPEED_HIGH, 0, NULL);
-	hc_fun->ops = &hc_ops;
+	ddf_fun_set_ops(hc_fun,  &hc_ops);
 
 	ret = ddf_fun_bind(hc_fun);
@@ -116,5 +116,5 @@
 
 	usb_log_info("Controlling new EHCI device `%s' (handle %" PRIun ").\n",
-	    device->name, device->handle);
+	    ddf_dev_get_name(device), ddf_dev_get_handle(device));
 
 	return EOK;
Index: uspace/drv/bus/usb/ehci/res.c
===================================================================
--- uspace/drv/bus/usb/ehci/res.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/ehci/res.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -76,5 +76,5 @@
  * @return Error code.
  */
-int get_my_registers(const ddf_dev_t *dev,
+int get_my_registers(ddf_dev_t *dev,
     uintptr_t *mem_reg_address, size_t *mem_reg_size, int *irq_no)
 {
@@ -82,5 +82,5 @@
 	
 	async_sess_t *parent_sess = devman_parent_device_connect(
-	    EXCHANGE_SERIALIZE, dev->handle, IPC_FLAG_BLOCKING);
+	    EXCHANGE_SERIALIZE, ddf_dev_get_handle(dev), IPC_FLAG_BLOCKING);
 	if (!parent_sess)
 		return ENOMEM;
@@ -115,8 +115,8 @@
  * @return Error code.
  */
-int enable_interrupts(const ddf_dev_t *device)
+int enable_interrupts(ddf_dev_t *device)
 {
 	async_sess_t *parent_sess = devman_parent_device_connect(
-	    EXCHANGE_SERIALIZE, device->handle, IPC_FLAG_BLOCKING);
+	    EXCHANGE_SERIALIZE, ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);
 	if (!parent_sess)
 		return ENOMEM;
@@ -134,5 +134,5 @@
  * @return Error code.
  */
-static int disable_extended_caps(const ddf_dev_t *device, unsigned eecp)
+static int disable_extended_caps(ddf_dev_t *device, unsigned eecp)
 {
 	/* nothing to do */
@@ -141,5 +141,5 @@
 
 	async_sess_t *parent_sess = devman_parent_device_connect(
-	    EXCHANGE_SERIALIZE, device->handle, IPC_FLAG_BLOCKING);
+	    EXCHANGE_SERIALIZE, ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);
 	if (!parent_sess)
 		return ENOMEM;
@@ -234,5 +234,5 @@
 }
 
-int disable_legacy(const ddf_dev_t *device, uintptr_t reg_base, size_t reg_size)
+int disable_legacy(ddf_dev_t *device, uintptr_t reg_base, size_t reg_size)
 {
 	assert(device);
Index: uspace/drv/bus/usb/ehci/res.h
===================================================================
--- uspace/drv/bus/usb/ehci/res.h	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/ehci/res.h	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -38,7 +38,7 @@
 #include <ddf/driver.h>
 
-int get_my_registers(const ddf_dev_t *, uintptr_t *, size_t *, int *);
-int enable_interrupts(const ddf_dev_t *);
-int disable_legacy(const ddf_dev_t *, uintptr_t, size_t);
+int get_my_registers(ddf_dev_t *, uintptr_t *, size_t *, int *);
+int enable_interrupts(ddf_dev_t *);
+int disable_legacy(ddf_dev_t *, uintptr_t, size_t);
 
 #endif
Index: uspace/drv/bus/usb/ohci/hc.c
===================================================================
--- uspace/drv/bus/usb/ohci/hc.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/ohci/hc.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -187,5 +187,5 @@
 
 	ret = usb_device_manager_bind_address(&instance->generic.dev_manager,
-	    instance->rh.address, hub_fun->handle);
+	    instance->rh.address, ddf_fun_get_handle(hub_fun));
 	if (ret != EOK)
 		usb_log_warning("Failed to bind root hub address: %s.\n",
Index: uspace/drv/bus/usb/ohci/main.c
===================================================================
--- uspace/drv/bus/usb/ohci/main.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/ohci/main.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -59,5 +59,5 @@
 		return ret;
 	}
-	usb_log_info("Controlling new OHCI device '%s'.\n", device->name);
+	usb_log_info("Controlling new OHCI device '%s'.\n", ddf_dev_get_name(device));
 
 	return EOK;
Index: uspace/drv/bus/usb/ohci/ohci.c
===================================================================
--- uspace/drv/bus/usb/ohci/ohci.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/ohci/ohci.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -33,4 +33,8 @@
  * @brief OHCI driver
  */
+
+/* XXX Fix this */
+#define _DDF_DATA_IMPLANT
+
 #include <errno.h>
 #include <str_error.h>
@@ -52,8 +56,7 @@
 } ohci_t;
 
-static inline ohci_t * dev_to_ohci(ddf_dev_t *dev)
-{
-	assert(dev);
-	return dev->driver_data;
+static inline ohci_t *dev_to_ohci(ddf_dev_t *dev)
+{
+	return ddf_dev_data_get(dev);
 }
 /** IRQ handling callback, identifies device
@@ -87,5 +90,5 @@
 
 	if (address != NULL) {
-		*address = dev_to_ohci(fun->dev)->hc.rh.address;
+		*address = dev_to_ohci(ddf_fun_get_dev(fun))->hc.rh.address;
 	}
 
@@ -103,9 +106,9 @@
 {
 	assert(fun);
-	ddf_fun_t *hc_fun = dev_to_ohci(fun->dev)->hc_fun;
+	ddf_fun_t *hc_fun = dev_to_ohci(ddf_fun_get_dev(fun))->hc_fun;
 	assert(hc_fun);
 
 	if (handle != NULL)
-		*handle = hc_fun->handle;
+		*handle = ddf_fun_get_handle(hc_fun);
 	return EOK;
 }
@@ -152,9 +155,7 @@
 if (ret != EOK) { \
 	if (instance->hc_fun) { \
-		instance->hc_fun->driver_data = NULL; \
 		ddf_fun_destroy(instance->hc_fun); \
 	} \
 	if (instance->rh_fun) { \
-		instance->rh_fun->driver_data = NULL; \
 		ddf_fun_destroy(instance->rh_fun); \
 	} \
@@ -167,6 +168,6 @@
 	CHECK_RET_DEST_FREE_RETURN(ret,
 	    "Failed to create OHCI HC function: %s.\n", str_error(ret));
-	instance->hc_fun->ops = &hc_ops;
-	instance->hc_fun->driver_data = &instance->hc;
+	ddf_fun_set_ops(instance->hc_fun, &hc_ops);
+	ddf_fun_data_implant(instance->hc_fun, &instance->hc);
 
 	instance->rh_fun = ddf_fun_create(device, fun_inner, "ohci_rh");
@@ -174,5 +175,5 @@
 	CHECK_RET_DEST_FREE_RETURN(ret,
 	    "Failed to create OHCI RH function: %s.\n", str_error(ret));
-	instance->rh_fun->ops = &rh_ops;
+	ddf_fun_set_ops(instance->rh_fun, &rh_ops);
 
 	uintptr_t reg_base = 0;
@@ -183,5 +184,5 @@
 	CHECK_RET_DEST_FREE_RETURN(ret,
 	    "Failed to get register memory addresses for %" PRIun ": %s.\n",
-	    device->handle, str_error(ret));
+	    ddf_dev_get_handle(device), str_error(ret));
 	usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
 	    (void *) reg_base, reg_size, irq);
Index: uspace/drv/bus/usb/ohci/res.c
===================================================================
--- uspace/drv/bus/usb/ohci/res.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/ohci/res.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -53,5 +53,5 @@
  * @return Error code.
  */
-int get_my_registers(const ddf_dev_t *dev,
+int get_my_registers(ddf_dev_t *dev,
     uintptr_t *mem_reg_address, size_t *mem_reg_size, int *irq_no)
 {
@@ -59,6 +59,6 @@
 
 	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
-	    IPC_FLAG_BLOCKING);
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE,
+	    ddf_dev_get_handle(dev), IPC_FLAG_BLOCKING);
 	if (!parent_sess)
 		return ENOMEM;
@@ -94,9 +94,9 @@
  * @return Error code.
  */
-int enable_interrupts(const ddf_dev_t *device)
+int enable_interrupts(ddf_dev_t *device)
 {
 	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle,
-	    IPC_FLAG_BLOCKING);
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE,
+	    ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);
 	if (!parent_sess)
 		return ENOMEM;
Index: uspace/drv/bus/usb/ohci/res.h
===================================================================
--- uspace/drv/bus/usb/ohci/res.h	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/ohci/res.h	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -37,6 +37,6 @@
 #include <ddf/driver.h>
 
-int get_my_registers(const ddf_dev_t *, uintptr_t *, size_t *, int *);
-int enable_interrupts(const ddf_dev_t *);
+int get_my_registers(ddf_dev_t *, uintptr_t *, size_t *, int *);
+int enable_interrupts(ddf_dev_t *);
 
 #endif
Index: uspace/drv/bus/usb/uhci/main.c
===================================================================
--- uspace/drv/bus/usb/uhci/main.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/uhci/main.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -70,5 +70,5 @@
 	} else {
 		usb_log_info("Controlling new UHCI device '%s'.\n",
-		    device->name);
+		    ddf_dev_get_name(device));
 	}
 
Index: uspace/drv/bus/usb/uhci/res.c
===================================================================
--- uspace/drv/bus/usb/uhci/res.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/uhci/res.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -51,5 +51,5 @@
  * @return Error code.
  */
-int get_my_registers(const ddf_dev_t *dev,
+int get_my_registers(ddf_dev_t *dev,
     uintptr_t *io_reg_address, size_t *io_reg_size, int *irq_no)
 {
@@ -57,6 +57,6 @@
 
 	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
-	    IPC_FLAG_BLOCKING);
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE,
+	    ddf_dev_get_handle(dev), IPC_FLAG_BLOCKING);
 	if (!parent_sess)
 		return ENOMEM;
@@ -92,9 +92,9 @@
  * @return Error code.
  */
-int enable_interrupts(const ddf_dev_t *device)
+int enable_interrupts(ddf_dev_t *device)
 {
 	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle,
-	    IPC_FLAG_BLOCKING);
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE,
+	    ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);
 	if (!parent_sess)
 		return ENOMEM;
@@ -111,10 +111,10 @@
  * @return Error code.
  */
-int disable_legacy(const ddf_dev_t *device)
+int disable_legacy(ddf_dev_t *device)
 {
 	assert(device);
 
 	async_sess_t *parent_sess = devman_parent_device_connect(
-	    EXCHANGE_SERIALIZE, device->handle, IPC_FLAG_BLOCKING);
+	    EXCHANGE_SERIALIZE, ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);
 	if (!parent_sess)
 		return ENOMEM;
Index: uspace/drv/bus/usb/uhci/res.h
===================================================================
--- uspace/drv/bus/usb/uhci/res.h	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/uhci/res.h	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -38,7 +38,7 @@
 #include <ddf/driver.h>
 
-int get_my_registers(const ddf_dev_t *, uintptr_t *, size_t *, int *);
-int enable_interrupts(const ddf_dev_t *);
-int disable_legacy(const ddf_dev_t *);
+int get_my_registers(ddf_dev_t *, uintptr_t *, size_t *, int *);
+int enable_interrupts(ddf_dev_t *);
+int disable_legacy(ddf_dev_t *);
 
 #endif
Index: uspace/drv/bus/usb/uhci/uhci.c
===================================================================
--- uspace/drv/bus/usb/uhci/uhci.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/uhci/uhci.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -33,4 +33,8 @@
  * @brief UHCI driver
  */
+
+/* XXX Fix this */
+#define _DDF_DATA_IMPLANT
+
 #include <errno.h>
 #include <str_error.h>
@@ -60,8 +64,7 @@
 } uhci_t;
 
-static inline uhci_t * dev_to_uhci(const ddf_dev_t *dev)
-{
-	assert(dev);
-	return dev->driver_data;
+static inline uhci_t *dev_to_uhci(ddf_dev_t *dev)
+{
+	return ddf_dev_data_get(dev);
 }
 
@@ -97,10 +100,9 @@
 static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle)
 {
-	assert(fun);
-	ddf_fun_t *hc_fun = dev_to_uhci(fun->dev)->hc_fun;
+	ddf_fun_t *hc_fun = dev_to_uhci(ddf_fun_get_dev(fun))->hc_fun;
 	assert(hc_fun);
 
 	if (handle != NULL)
-		*handle = hc_fun->handle;
+		*handle = ddf_fun_get_handle(hc_fun);
 	return EOK;
 }
@@ -118,6 +120,5 @@
 static hw_resource_list_t *get_resource_list(ddf_fun_t *fun)
 {
-	assert(fun);
-	rh_t *rh = fun->driver_data;
+	rh_t *rh = ddf_fun_data_get(fun);
 	assert(rh);
 	return &rh->resource_list;
@@ -160,8 +161,6 @@
 if (ret != EOK) { \
 	if (instance->hc_fun) \
-		instance->hc_fun->driver_data = NULL; \
 		ddf_fun_destroy(instance->hc_fun); \
 	if (instance->rh_fun) {\
-		instance->rh_fun->driver_data = NULL; \
 		ddf_fun_destroy(instance->rh_fun); \
 	} \
@@ -174,12 +173,12 @@
 	int ret = (instance->hc_fun == NULL) ? ENOMEM : EOK;
 	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI HC function.\n");
-	instance->hc_fun->ops = &hc_ops;
-	instance->hc_fun->driver_data = &instance->hc.generic;
+	ddf_fun_set_ops(instance->hc_fun, &hc_ops);
+	ddf_fun_data_implant(instance->hc_fun, &instance->hc.generic);
 
 	instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci_rh");
 	ret = (instance->rh_fun == NULL) ? ENOMEM : EOK;
 	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI RH function.\n");
-	instance->rh_fun->ops = &rh_ops;
-	instance->rh_fun->driver_data = &instance->rh;
+	ddf_fun_set_ops(instance->rh_fun, &rh_ops);
+	ddf_fun_data_implant(instance->rh_fun, &instance->rh);
 
 	uintptr_t reg_base = 0;
@@ -190,5 +189,5 @@
 	CHECK_RET_DEST_FREE_RETURN(ret,
 	    "Failed to get I/O addresses for %" PRIun ": %s.\n",
-	    device->handle, str_error(ret));
+	    ddf_dev_get_handle(device), str_error(ret));
 	usb_log_debug("I/O regs at 0x%p (size %zu), IRQ %d.\n",
 	    (void *) reg_base, reg_size, irq);
Index: uspace/drv/bus/usb/uhcirh/main.c
===================================================================
--- uspace/drv/bus/usb/uhcirh/main.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/uhcirh/main.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -48,5 +48,5 @@
 #define NAME "uhcirh"
 
-static int hc_get_my_registers(const ddf_dev_t *dev,
+static int hc_get_my_registers(ddf_dev_t *dev,
     uintptr_t *io_reg_address, size_t *io_reg_size);
 
@@ -88,5 +88,5 @@
 
 	usb_log_debug2("uhci_rh_dev_add(handle=%" PRIun ")\n",
-	    device->handle);
+	    ddf_dev_get_handle(device));
 
 	uintptr_t io_regs = 0;
@@ -98,6 +98,4 @@
 if (ret != EOK) { \
 	usb_log_error(message); \
-	if (rh) \
-		free(rh); \
 	return ret; \
 } else (void)0
@@ -109,5 +107,5 @@
 	    (void *) io_regs, io_size);
 
-	rh = malloc(sizeof(uhci_root_hub_t));
+	rh = ddf_dev_data_alloc(device, sizeof(uhci_root_hub_t));
 	ret = (rh == NULL) ? ENOMEM : EOK;
 	CHECK_RET_FREE_RH_RETURN(ret,
@@ -119,7 +117,6 @@
 	    ret, str_error(ret));
 
-	device->driver_data = rh;
 	usb_log_info("Controlling root hub '%s' (%" PRIun ").\n",
-	    device->name, device->handle);
+	    ddf_dev_get_name(device), ddf_dev_get_handle(device));
 	return EOK;
 }
@@ -133,11 +130,9 @@
  */
 int hc_get_my_registers(
-    const ddf_dev_t *dev, uintptr_t *io_reg_address, size_t *io_reg_size)
+    ddf_dev_t *dev, uintptr_t *io_reg_address, size_t *io_reg_size)
 {
-	assert(dev);
-
 	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
-	    IPC_FLAG_BLOCKING);
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE,
+	    ddf_dev_get_handle(dev), IPC_FLAG_BLOCKING);
 	if (!parent_sess)
 		return ENOMEM;
Index: uspace/drv/bus/usb/uhcirh/port.c
===================================================================
--- uspace/drv/bus/usb/uhcirh/port.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/uhcirh/port.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -279,5 +279,5 @@
 	usb_log_info("%s: New device, address %d (handle %" PRIun ").\n",
 	    port->id_string, port->attached_device.address,
-	    port->attached_device.fun->handle);
+	    ddf_fun_get_handle(port->attached_device.fun));
 	return EOK;
 }
Index: uspace/drv/bus/usb/usbflbk/main.c
===================================================================
--- uspace/drv/bus/usb/usbflbk/main.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/usbflbk/main.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -69,5 +69,5 @@
 	    " (node `%s', handle %" PRIun ").\n",
 	    dev->interface_no < 0 ? "device" : "interface",
-	    dev->ddf_dev->name, fun_name, dev->ddf_dev->handle);
+	    ddf_dev_get_name(dev->ddf_dev), fun_name, ddf_dev_get_handle(dev->ddf_dev));
 
 	return EOK;
@@ -85,5 +85,5 @@
 	const int ret = ddf_fun_unbind(ctl_fun);
 	if (ret != EOK) {
-		usb_log_error("Failed to unbind %s.\n", ctl_fun->name);
+		usb_log_error("Failed to unbind %s.\n", ddf_fun_get_name(ctl_fun));
 		return ret;
 	}
Index: uspace/drv/bus/usb/usbhid/generic/hiddev.c
===================================================================
--- uspace/drv/bus/usb/usbhid/generic/hiddev.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/usbhid/generic/hiddev.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -35,4 +35,7 @@
  */
 
+/* XXX Fix this */
+#define _DDF_DATA_IMPLANT
+
 #include <usb/debug.h>
 #include <usb/classes/classes.h>
@@ -81,14 +84,20 @@
 };
 
+/** Return hid_dev_t * for generic HID function node.
+ *
+ * For the generic HID subdriver the 'hid' function has usb_hid_gen_fun_t
+ * as soft state. Through that we can get to the usb_hid_dev_t.
+ */
+static usb_hid_dev_t *fun_hid_dev(ddf_fun_t *fun)
+{
+	return ((usb_hid_gen_fun_t *)ddf_fun_data_get(fun))->hid_dev;
+}
+
 static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun)
 {
 	usb_log_debug2("Generic HID: Get event length (fun: %p, "
-	    "fun->driver_data: %p.\n", fun, fun->driver_data);
-
-	if (fun == NULL || fun->driver_data == NULL) {
-		return 0;
-	}
-
-	const usb_hid_dev_t *hid_dev = fun->driver_data;
+	    "fun->driver_data: %p.\n", fun, ddf_fun_data_get(fun));
+
+	const usb_hid_dev_t *hid_dev = fun_hid_dev(fun);
 
 	usb_log_debug2("hid_dev: %p, Max input report size (%zu).\n",
@@ -103,11 +112,10 @@
 	usb_log_debug2("Generic HID: Get event.\n");
 
-	if (fun == NULL || fun->driver_data == NULL || buffer == NULL
-	    || act_size == NULL || event_nr == NULL) {
+	if (buffer == NULL || act_size == NULL || event_nr == NULL) {
 		usb_log_debug("No function");
 		return EINVAL;
 	}
 
-	const usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
+	const usb_hid_dev_t *hid_dev = fun_hid_dev(fun);
 
 	if (hid_dev->input_report_size > size) {
@@ -132,10 +140,5 @@
 	usb_log_debug("Generic HID: Get report descriptor length.\n");
 
-	if (fun == NULL || fun->driver_data == NULL) {
-		usb_log_debug("No function");
-		return EINVAL;
-	}
-
-	const usb_hid_dev_t *hid_dev = fun->driver_data;
+	const usb_hid_dev_t *hid_dev = fun_hid_dev(fun);
 
 	usb_log_debug2("hid_dev->report_desc_size = %zu\n",
@@ -150,10 +153,5 @@
 	usb_log_debug2("Generic HID: Get report descriptor.\n");
 
-	if (fun == NULL || fun->driver_data == NULL) {
-		usb_log_debug("No function");
-		return EINVAL;
-	}
-
-	const usb_hid_dev_t *hid_dev = fun->driver_data;
+	const usb_hid_dev_t *hid_dev = fun_hid_dev(fun);
 
 	if (hid_dev->report_desc_size > size) {
@@ -183,8 +181,5 @@
 		return;
 	}
-	usb_log_debug2("%s unbound.\n", fun->name);
-	/* We did not allocate this, so leave this alone
-	 * the device would take care of it */
-	fun->driver_data = NULL;
+	usb_log_debug2("%s unbound.\n", ddf_fun_get_name(fun));
 	ddf_fun_destroy(fun);
 }
@@ -192,4 +187,6 @@
 int usb_generic_hid_init(usb_hid_dev_t *hid_dev, void **data)
 {
+	usb_hid_gen_fun_t *hid_fun;
+
 	if (hid_dev == NULL) {
 		return EINVAL;
@@ -205,8 +202,8 @@
 	}
 
-	/* This is nasty, both device and this function have the same
-	 * driver data, thus destruction causes to double free */
-	fun->driver_data = hid_dev;
-	fun->ops = &usb_generic_hid_ops;
+	/* Create softstate */
+	hid_fun = ddf_fun_data_alloc(fun, sizeof(usb_hid_gen_fun_t));
+	hid_fun->hid_dev = hid_dev;
+	ddf_fun_set_ops(fun, &usb_generic_hid_ops);
 
 	int rc = ddf_fun_bind(fun);
@@ -214,10 +211,10 @@
 		usb_log_error("Could not bind DDF function: %s.\n",
 		    str_error(rc));
-		fun->driver_data = NULL;
 		ddf_fun_destroy(fun);
 		return rc;
 	}
 
-	usb_log_debug("HID function created. Handle: %" PRIun "\n", fun->handle);
+	usb_log_debug("HID function created. Handle: %" PRIun "\n",
+	    ddf_fun_get_handle(fun));
 	*data = fun;
 
Index: uspace/drv/bus/usb/usbhid/generic/hiddev.h
===================================================================
--- uspace/drv/bus/usb/usbhid/generic/hiddev.h	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/usbhid/generic/hiddev.h	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -47,5 +47,8 @@
 const char *HID_GENERIC_CLASS_NAME;
 
-
+/** The USB HID generic 'hid' function softstate */
+typedef struct {
+	struct usb_hid_dev *hid_dev;
+} usb_hid_gen_fun_t;
 
 int usb_generic_hid_init(struct usb_hid_dev *hid_dev, void **data);
Index: uspace/drv/bus/usb/usbhid/kbd/kbddev.c
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/kbddev.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/usbhid/kbd/kbddev.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -34,4 +34,7 @@
  * USB HID keyboard device structure and API.
  */
+
+/* XXX Fix this */
+#define _DDF_DATA_IMPLANT
 
 #include <errno.h>
@@ -162,12 +165,6 @@
     ipc_callid_t icallid, ipc_call_t *icall)
 {
-	if (fun == NULL || fun->driver_data == NULL) {
-		usb_log_error("%s: Missing parameter.\n", __FUNCTION__);
-		async_answer_0(icallid, EINVAL);
-		return;
-	}
-
 	const sysarg_t method = IPC_GET_IMETHOD(*icall);
-	usb_kbd_t *kbd_dev = fun->driver_data;
+	usb_kbd_t *kbd_dev = ddf_fun_data_get(fun);
 
 	switch (method) {
@@ -501,6 +498,6 @@
 	/* Store the initialized HID device and HID ops
 	 * to the DDF function. */
-	fun->ops = &kbdops;
-	fun->driver_data = kbd_dev;
+	ddf_fun_set_ops(fun, &kbdops);
+	ddf_fun_data_implant(fun, kbd_dev);
 
 	int rc = ddf_fun_bind(fun);
@@ -508,5 +505,4 @@
 		usb_log_error("Could not bind DDF function: %s.\n",
 		    str_error(rc));
-		fun->driver_data = NULL; /* We did not allocate this. */
 		ddf_fun_destroy(fun);
 		return rc;
@@ -514,5 +510,5 @@
 
 	usb_log_debug("%s function created. Handle: %" PRIun "\n",
-	    HID_KBD_FUN_NAME, fun->handle);
+	    HID_KBD_FUN_NAME, ddf_fun_get_handle(fun));
 
 	usb_log_debug("Adding DDF function to category %s...\n",
@@ -524,10 +520,9 @@
 		    HID_KBD_CLASS_NAME, str_error(rc));
 		if (ddf_fun_unbind(fun) == EOK) {
-			fun->driver_data = NULL; /* We did not allocate this. */
 			ddf_fun_destroy(fun);
 		} else {
 			usb_log_error(
 			    "Failed to unbind `%s', will not destroy.\n",
-			    fun->name);
+			    ddf_fun_get_name(fun));
 		}
 		return rc;
@@ -757,12 +752,11 @@
 		if (ddf_fun_unbind(kbd_dev->fun) != EOK) {
 			usb_log_warning("Failed to unbind %s.\n",
-			    kbd_dev->fun->name);
+			    ddf_fun_get_name(kbd_dev->fun));
 		} else {
-			usb_log_debug2("%s unbound.\n", kbd_dev->fun->name);
-			kbd_dev->fun->driver_data = NULL;
+			usb_log_debug2("%s unbound.\n",
+			    ddf_fun_get_name(kbd_dev->fun));
 			ddf_fun_destroy(kbd_dev->fun);
 		}
 	}
-	free(kbd_dev);
 }
 
Index: uspace/drv/bus/usb/usbhid/main.c
===================================================================
--- uspace/drv/bus/usb/usbhid/main.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/usbhid/main.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -103,5 +103,5 @@
 	if (rc != EOK) {
 		usb_log_error("Failed to start polling fibril for `%s'.\n",
-		    dev->ddf_dev->name);
+		    ddf_dev_get_name(dev->ddf_dev));
 		usb_hid_deinit(hid_dev);
 		return rc;
@@ -109,5 +109,6 @@
 	hid_dev->running = true;
 
-	usb_log_info("HID device `%s' ready to use.\n", dev->ddf_dev->name);
+	usb_log_info("HID device `%s' ready to use.\n",
+	    ddf_dev_get_name(dev->ddf_dev));
 
 	return EOK;
@@ -149,5 +150,5 @@
 
 	usb_hid_deinit(hid_dev);
-	usb_log_debug2("%s destruction complete.\n", dev->ddf_dev->name);
+	usb_log_debug2("%s destruction complete.\n", ddf_dev_get_name(dev->ddf_dev));
 	return EOK;
 }
Index: uspace/drv/bus/usb/usbhid/mouse/mousedev.c
===================================================================
--- uspace/drv/bus/usb/usbhid/mouse/mousedev.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/usbhid/mouse/mousedev.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -34,4 +34,7 @@
  * USB Mouse driver API.
  */
+
+/* XXX Fix this */
+#define _DDF_DATA_IMPLANT
 
 #include <usb/debug.h>
@@ -115,5 +118,5 @@
     ipc_callid_t icallid, ipc_call_t *icall)
 {
-	usb_mouse_t *mouse_dev = fun->driver_data;
+	usb_mouse_t *mouse_dev = ddf_fun_data_get(fun);
 
 	if (mouse_dev == NULL) {
@@ -123,5 +126,5 @@
 	}
 
-	usb_log_debug("%s: fun->name: %s\n", __FUNCTION__, fun->name);
+	usb_log_debug("%s: fun->name: %s\n", __FUNCTION__, ddf_fun_get_name(fun));
 	usb_log_debug("%s: mouse_sess: %p\n",
 	    __FUNCTION__, mouse_dev->mouse_sess);
@@ -133,9 +136,9 @@
 			mouse_dev->mouse_sess = sess;
 			usb_log_debug("Console session to %s set ok (%p).\n",
-			    fun->name, sess);
+			    ddf_fun_get_name(fun), sess);
 			async_answer_0(icallid, EOK);
 		} else {
 			usb_log_error("Console session to %s already set.\n",
-			    fun->name);
+			    ddf_fun_get_name(fun));
 			async_answer_0(icallid, ELIMIT);
 			async_hangup(sess);
@@ -249,9 +252,8 @@
 if (fun) { \
 	if (ddf_fun_unbind((fun)) == EOK) { \
-		(fun)->driver_data = NULL; \
 		ddf_fun_destroy((fun)); \
 	} else { \
 		usb_log_error("Could not unbind function `%s', it " \
-		    "will not be destroyed.\n", (fun)->name); \
+		    "will not be destroyed.\n", ddf_fun_get_name(fun)); \
 	} \
 } else (void)0
@@ -272,12 +274,11 @@
 	}
 
-	fun->ops = &ops;
-	fun->driver_data = mouse;
+	ddf_fun_set_ops(fun, &ops);
+	ddf_fun_data_implant(fun, mouse);
 
 	int rc = ddf_fun_bind(fun);
 	if (rc != EOK) {
 		usb_log_error("Could not bind DDF function `%s': %s.\n",
-		    fun->name, str_error(rc));
-		fun->driver_data = NULL;
+		    ddf_fun_get_name(fun), str_error(rc));
 		ddf_fun_destroy(fun);
 		return rc;
@@ -285,5 +286,5 @@
 
 	usb_log_debug("Adding DDF function `%s' to category %s...\n",
-	    fun->name, HID_MOUSE_CATEGORY);
+	    ddf_fun_get_name(fun), HID_MOUSE_CATEGORY);
 	rc = ddf_fun_add_to_category(fun, HID_MOUSE_CATEGORY);
 	if (rc != EOK) {
@@ -419,5 +420,4 @@
 
 	free(mouse_dev->buttons);
-	free(mouse_dev);
 }
 
Index: uspace/drv/bus/usb/usbhid/multimedia/multimedia.c
===================================================================
--- uspace/drv/bus/usb/usbhid/multimedia/multimedia.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/usbhid/multimedia/multimedia.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -86,10 +86,6 @@
 {
 	usb_log_debug(NAME " default_connection_handler()\n");
-	if (fun == NULL || fun->driver_data == NULL) {
-		async_answer_0(icallid, EINVAL);
-		return;
-	}
-
-	usb_multimedia_t *multim_dev = fun->driver_data;
+
+	usb_multimedia_t *multim_dev = ddf_fun_data_get(fun);
 
 	async_sess_t *sess =
@@ -172,5 +168,5 @@
 	}
 
-	fun->ops = &multimedia_ops;
+	ddf_fun_set_ops(fun, &multimedia_ops);
 
 	usb_multimedia_t *multim_dev =
@@ -194,5 +190,5 @@
 
 	usb_log_debug(NAME " function created (handle: %" PRIun ").\n",
-	    fun->handle);
+	    ddf_fun_get_handle(fun));
 
 	rc = ddf_fun_add_to_category(fun, "keyboard");
@@ -203,5 +199,5 @@
 		if (ddf_fun_unbind(fun) != EOK) {
 			usb_log_error("Failed to unbind %s, won't destroy.\n",
-			    fun->name);
+			    ddf_fun_get_name(fun));
 		} else {
 			ddf_fun_destroy(fun);
@@ -220,21 +216,18 @@
 {
 	ddf_fun_t *fun = data;
-	if (fun != NULL && fun->driver_data != NULL) {
-		usb_multimedia_t *multim_dev = fun->driver_data;
-		/* Hangup session to the console */
-		if (multim_dev->console_sess)
-			async_hangup(multim_dev->console_sess);
-		if (ddf_fun_unbind(fun) != EOK) {
-			usb_log_error("Failed to unbind %s, won't destroy.\n",
-			    fun->name);
-		} else {
-			usb_log_debug2("%s unbound.\n", fun->name);
-			/* This frees multim_dev too as it was stored in
-			 * fun->data */
-			ddf_fun_destroy(fun);
-		}
+
+	usb_multimedia_t *multim_dev = ddf_fun_data_get(fun);
+
+	/* Hangup session to the console */
+	if (multim_dev->console_sess)
+		async_hangup(multim_dev->console_sess);
+	if (ddf_fun_unbind(fun) != EOK) {
+		usb_log_error("Failed to unbind %s, won't destroy.\n",
+		    ddf_fun_get_name(fun));
 	} else {
-		usb_log_error(
-		    "Failed to deinit multimedia subdriver, data missing.\n");
+		usb_log_debug2("%s unbound.\n", ddf_fun_get_name(fun));
+		/* This frees multim_dev too as it was stored in
+		 * fun->data */
+		ddf_fun_destroy(fun);
 	}
 }
@@ -244,9 +237,9 @@
 	// TODO: checks
 	ddf_fun_t *fun = data;
-	if (hid_dev == NULL || fun == NULL || fun->driver_data == NULL) {
+	if (hid_dev == NULL) {
 		return false;
 	}
 
-	usb_multimedia_t *multim_dev = fun->driver_data;
+	usb_multimedia_t *multim_dev = ddf_fun_data_get(fun);
 
 	usb_hid_report_path_t *path = usb_hid_report_path();
Index: uspace/drv/bus/usb/usbhub/port.c
===================================================================
--- uspace/drv/bus/usb/usbhub/port.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/usbhub/port.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -436,6 +436,7 @@
 		usb_log_info("Detected new device on `%s' (port %zu), "
 		    "address %d (handle %" PRIun ").\n",
-		    data->hub->usb_device->ddf_dev->name,
-		    data->port->port_number, new_address, child_fun->handle);
+		    ddf_dev_get_name(data->hub->usb_device->ddf_dev),
+		    data->port->port_number, new_address,
+		    ddf_fun_get_handle(child_fun));
 	} else {
 		usb_log_error("Failed registering device on port %zu: %s.\n",
Index: uspace/drv/bus/usb/usbhub/usbhub.c
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/usbhub/usbhub.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -160,5 +160,5 @@
 	hub_dev->running = true;
 	usb_log_info("Controlling hub '%s' (%zu ports).\n",
-	    hub_dev->usb_device->ddf_dev->name, hub_dev->port_count);
+	    ddf_dev_get_name(hub_dev->usb_device->ddf_dev), hub_dev->port_count);
 
 	usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
Index: uspace/drv/bus/usb/usbmast/main.c
===================================================================
--- uspace/drv/bus/usb/usbmast/main.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/usbmast/main.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -160,5 +160,5 @@
 	mdev->usb_dev = dev;
 
-	usb_log_info("Initializing mass storage `%s'.\n", dev->ddf_dev->name);
+	usb_log_info("Initializing mass storage `%s'.\n", ddf_dev_get_name(dev->ddf_dev));
 	usb_log_debug("Bulk in endpoint: %d [%zuB].\n",
 	    dev->pipes[BULK_IN_EP].pipe.endpoint_no,
@@ -245,5 +245,5 @@
 
 	/* Set up a connection handler. */
-	fun->conn_handler = usbmast_bd_connection;
+	ddf_fun_set_conn_handler(fun, usbmast_bd_connection);
 
 	usb_log_debug("Inquire...\n");
@@ -252,5 +252,5 @@
 	if (rc != EOK) {
 		usb_log_warning("Failed to inquire device `%s': %s.\n",
-		    mdev->ddf_dev->name, str_error(rc));
+		    ddf_dev_get_name(mdev->ddf_dev), str_error(rc));
 		rc = EIO;
 		goto error;
@@ -259,5 +259,5 @@
 	usb_log_info("Mass storage `%s' LUN %u: " \
 	    "%s by %s rev. %s is %s (%s).\n",
-	    mdev->ddf_dev->name,
+	    ddf_dev_get_name(mdev->ddf_dev),
 	    lun,
 	    inquiry.product,
@@ -272,5 +272,5 @@
 	if (rc != EOK) {
 		usb_log_warning("Failed to read capacity, device `%s': %s.\n",
-		    mdev->ddf_dev->name, str_error(rc));
+		    ddf_dev_get_name(mdev->ddf_dev), str_error(rc));
 		rc = EIO;
 		goto error;
@@ -310,5 +310,5 @@
 	usbmast_fun_t *mfun;
 
-	mfun = (usbmast_fun_t *) ((ddf_fun_t *)arg)->driver_data;
+	mfun = (usbmast_fun_t *) ddf_fun_data_get((ddf_fun_t *)arg);
 	bd_conn(iid, icall, &mfun->bds);
 }
Index: uspace/drv/bus/usb/usbmast/scsi_ms.c
===================================================================
--- uspace/drv/bus/usb/usbmast/scsi_ms.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/usbmast/scsi_ms.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -88,5 +88,5 @@
 		if (rc != EOK) {
 			usb_log_error("Inquiry transport failed, device %s: %s.\n",
-			   mfun->mdev->ddf_dev->name, str_error(rc));
+			   ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));
 			return rc;
 		}
@@ -96,5 +96,5 @@
 
 		usb_log_error("SCSI command failed, device %s.\n",
-		    mfun->mdev->ddf_dev->name);
+		    ddf_dev_get_name(mfun->mdev->ddf_dev));
 
 		rc = usbmast_request_sense(mfun, &sense_buf, sizeof(sense_buf));
@@ -147,5 +147,5 @@
 	if (rc != EOK) {
 		usb_log_error("Inquiry transport failed, device %s: %s.\n",
-		   mfun->mdev->ddf_dev->name, str_error(rc));
+		   ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));
 		return rc;
 	}
@@ -153,5 +153,5 @@
 	if (cmd.status != CMDS_GOOD) {
 		usb_log_error("Inquiry command failed, device %s.\n",
-		   mfun->mdev->ddf_dev->name);
+		   ddf_dev_get_name(mfun->mdev->ddf_dev));
 		return EIO;
 	}
@@ -215,5 +215,5 @@
         if (rc != EOK || cmd.status != CMDS_GOOD) {
 		usb_log_error("Request Sense failed, device %s: %s.\n",
-		   mfun->mdev->ddf_dev->name, str_error(rc));
+		   ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));
 		return rc;
 	}
@@ -257,5 +257,5 @@
         if (rc != EOK) {
 		usb_log_error("Read Capacity (10) transport failed, device %s: %s.\n",
-		   mfun->mdev->ddf_dev->name, str_error(rc));
+		   ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));
 		return rc;
 	}
@@ -263,5 +263,5 @@
 	if (cmd.status != CMDS_GOOD) {
 		usb_log_error("Read Capacity (10) command failed, device %s.\n",
-		   mfun->mdev->ddf_dev->name);
+		   ddf_dev_get_name(mfun->mdev->ddf_dev));
 		return EIO;
 	}
@@ -314,5 +314,5 @@
         if (rc != EOK) {
 		usb_log_error("Read (10) transport failed, device %s: %s.\n",
-		   mfun->mdev->ddf_dev->name, str_error(rc));
+		   ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));
 		return rc;
 	}
@@ -320,5 +320,5 @@
 	if (cmd.status != CMDS_GOOD) {
 		usb_log_error("Read (10) command failed, device %s.\n",
-		   mfun->mdev->ddf_dev->name);
+		   ddf_dev_get_name(mfun->mdev->ddf_dev));
 		return EIO;
 	}
@@ -370,5 +370,5 @@
         if (rc != EOK) {
 		usb_log_error("Write (10) transport failed, device %s: %s.\n",
-		   mfun->mdev->ddf_dev->name, str_error(rc));
+		   ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));
 		return rc;
 	}
@@ -376,5 +376,5 @@
 	if (cmd.status != CMDS_GOOD) {
 		usb_log_error("Write (10) command failed, device %s.\n",
-		   mfun->mdev->ddf_dev->name);
+		   ddf_dev_get_name(mfun->mdev->ddf_dev));
 		return EIO;
 	}
Index: uspace/drv/bus/usb/usbmid/explore.c
===================================================================
--- uspace/drv/bus/usb/usbmid/explore.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/usbmid/explore.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -172,5 +172,5 @@
 		return false;
 	}
-	usb_mid->ctl_fun->ops = &mid_device_ops;
+	ddf_fun_set_ops(usb_mid->ctl_fun, &mid_device_ops);
 
 	/* Bind control function. */
Index: uspace/drv/bus/usb/usbmid/main.c
===================================================================
--- uspace/drv/bus/usb/usbmid/main.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/usbmid/main.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -51,5 +51,5 @@
 static int usbmid_device_add(usb_device_t *dev)
 {
-	usb_log_info("Taking care of new MID `%s'.\n", dev->ddf_dev->name);
+	usb_log_info("Taking care of new MID `%s'.\n", ddf_dev_get_name(dev->ddf_dev));
 
 	const bool accept = usbmid_explore_device(dev);
@@ -127,5 +127,5 @@
 	assert(usb_mid);
 
-	usb_log_info("USB MID gone: `%s'.\n", dev->ddf_dev->name);
+	usb_log_info("USB MID gone: `%s'.\n", ddf_dev_get_name(dev->ddf_dev));
 
 	/* Remove ctl function */
Index: uspace/drv/bus/usb/usbmid/usbmid.c
===================================================================
--- uspace/drv/bus/usb/usbmid/usbmid.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/usbmid/usbmid.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -30,4 +30,8 @@
  * @{
  */
+
+/* XXX Fix this */
+#define _DDF_DATA_IMPLANT
+
 /**
  * @file
@@ -47,7 +51,5 @@
 static int usb_iface_get_interface_impl(ddf_fun_t *fun, int *iface_no)
 {
-	assert(fun);
-
-	usbmid_interface_t *iface = fun->driver_data;
+	usbmid_interface_t *iface = ddf_fun_data_get(fun);
 	assert(iface);
 
@@ -123,10 +125,24 @@
 	}
 
+	match_id_list_t match_ids;
+	init_match_ids(&match_ids);
+
 	rc = usb_device_create_match_ids_from_interface(device_descriptor,
-	    interface_descriptor, &child->match_ids);
+	    interface_descriptor, &match_ids);
 	if (rc != EOK) {
 		ddf_fun_destroy(child);
 		return rc;
 	}
+
+	list_foreach(match_ids.ids, link) {
+		match_id_t *match_id = list_get_instance(link, match_id_t, link);
+		rc = ddf_fun_add_match_id(child, match_id->id, match_id->score);
+		if (rc != EOK) {
+			clean_match_ids(&match_ids);
+			ddf_fun_destroy(child);
+			return rc;
+		}
+	}
+	clean_match_ids(&match_ids);
 
 	rc = ddf_fun_bind(child);
@@ -138,6 +154,6 @@
 
 	iface->fun = child;
-	child->driver_data = iface;
-	child->ops = &child_device_ops;
+	ddf_fun_data_implant(child, iface);
+	ddf_fun_set_ops(child, &child_device_ops);
 
 	return EOK;
Index: uspace/drv/bus/usb/vhc/conndev.c
===================================================================
--- uspace/drv/bus/usb/vhc/conndev.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/vhc/conndev.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -94,5 +94,5 @@
     ipc_call_t *icall)
 {
-	vhc_data_t *vhc = fun->dev->driver_data;
+	vhc_data_t *vhc = ddf_dev_data_get(ddf_fun_get_dev(fun));
 	
 	async_sess_t *callback =
@@ -125,5 +125,5 @@
 void on_client_close(ddf_fun_t *fun)
 {
-	vhc_data_t *vhc = fun->dev->driver_data;
+	vhc_data_t *vhc = ddf_dev_data_get(ddf_fun_get_dev(fun));
 
 	if (plugged_device_handle != 0) {
Index: uspace/drv/bus/usb/vhc/connhost.c
===================================================================
--- uspace/drv/bus/usb/vhc/connhost.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/vhc/connhost.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -42,5 +42,5 @@
 
 #define GET_VHC_DATA(fun) \
-	((vhc_data_t *)fun->dev->driver_data)
+	((vhc_data_t *)ddf_dev_data_get(ddf_fun_get_dev(fun)))
 #define VHC_DATA(vhc, fun) \
 	vhc_data_t *vhc = GET_VHC_DATA(fun); assert(vhc->magic == 0xdeadbeef)
@@ -483,5 +483,5 @@
 	VHC_DATA(vhc, root_hub_fun);
 
-	*handle = vhc->hc_fun->handle;
+	*handle = ddf_fun_get_handle(vhc->hc_fun);
 
 	return EOK;
@@ -492,5 +492,5 @@
 	VHC_DATA(vhc, root_hub_fun);
 
-	devman_handle_t handle = root_hub_fun->handle;
+	devman_handle_t handle = ddf_fun_get_handle(root_hub_fun);
 
 	usb_log_debug("tell_address_rh(handle=%" PRIun ")\n", handle);
Index: uspace/drv/bus/usb/vhc/hub.c
===================================================================
--- uspace/drv/bus/usb/vhc/hub.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/vhc/hub.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -100,5 +100,6 @@
 	async_sess_t *sess;
 	do {
-		sess = devman_device_connect(EXCHANGE_SERIALIZE, hc_dev->handle, 0);
+		sess = devman_device_connect(EXCHANGE_SERIALIZE,
+		    ddf_fun_get_handle(hc_dev), 0);
 	} while (!sess);
 	async_hangup(sess);
@@ -107,5 +108,5 @@
 
 	usb_hc_connection_t hc_conn;
-	usb_hc_connection_initialize(&hc_conn, hc_dev->handle);
+	usb_hc_connection_initialize(&hc_conn, ddf_fun_get_handle(hc_dev));
 
 	rc = usb_hc_connection_open(&hc_conn);
@@ -113,5 +114,5 @@
 
 	ddf_fun_t *hub_dev;
-	rc = usb_hc_new_device_wrapper(hc_dev->dev, &hc_conn, USB_SPEED_FULL,
+	rc = usb_hc_new_device_wrapper(ddf_fun_get_dev(hc_dev), &hc_conn, USB_SPEED_FULL,
 	    pretend_port_rest, NULL, NULL, &rh_ops, hc_dev, &hub_dev);
 	if (rc != EOK) {
@@ -123,5 +124,5 @@
 
 	usb_log_info("Created root hub function (handle %zu).\n",
-	    (size_t) hub_dev->handle);
+	    (size_t) ddf_fun_get_handle(hub_dev));
 
 	return 0;
Index: uspace/drv/bus/usb/vhc/main.c
===================================================================
--- uspace/drv/bus/usb/vhc/main.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/bus/usb/vhc/main.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -67,5 +67,5 @@
 	}
 
-	vhc_data_t *data = malloc(sizeof(vhc_data_t));
+	vhc_data_t *data = ddf_dev_data_alloc(dev, sizeof(vhc_data_t));
 	if (data == NULL) {
 		usb_log_fatal("Failed to allocate memory.\n");
@@ -89,11 +89,9 @@
 	}
 
-	hc->ops = &vhc_ops;
+	ddf_fun_set_ops(hc, &vhc_ops);
 	list_initialize(&data->devices);
 	fibril_mutex_initialize(&data->guard);
 	data->hub = &virtual_hub_device;
 	data->hc_fun = hc;
-
-	dev->driver_data = data;
 
 	rc = ddf_fun_bind(hc);
@@ -116,7 +114,5 @@
 
 	usb_log_info("Virtual USB host controller ready (dev %zu, hc %zu).\n",
-	    (size_t) dev->handle, (size_t) hc->handle);
-
-
+	    (size_t) ddf_dev_get_handle(dev), (size_t) ddf_fun_get_handle(hc));
 
 	rc = vhc_virtdev_plug_hub(data, data->hub, NULL);
Index: uspace/drv/char/i8042/i8042.c
===================================================================
--- uspace/drv/char/i8042/i8042.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/char/i8042/i8042.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -39,5 +39,4 @@
  */
 
-#include <devman.h>
 #include <device/hw_res.h>
 #include <ddi.h>
@@ -140,4 +139,10 @@
 };
 
+/** Get i8042 soft state from device node. */
+static i8042_t *dev_i8042(ddf_dev_t *dev)
+{
+	return ddf_dev_data_get(dev);
+}
+
 /** Wait until it is safe to write to the device. */
 static void wait_ready(i8042_t *dev)
@@ -159,8 +164,5 @@
     ipc_call_t *call)
 {
-	if ((!dev) || (!dev->driver_data))
-		return;
-	
-	i8042_t *controller = dev->driver_data;
+	i8042_t *controller = dev_i8042(dev);
 	
 	const uint8_t status = IPC_GET_ARG1(*call);
@@ -188,40 +190,49 @@
     int irq_mouse, ddf_dev_t *ddf_dev)
 {
-	assert(ddf_dev);
-	assert(dev);
-	
-	if (reg_size < sizeof(i8042_regs_t))
-		return EINVAL;
-	
-	if (pio_enable(regs, sizeof(i8042_regs_t), (void **) &dev->regs) != 0)
-		return -1;
+	const size_t range_count = sizeof(i8042_ranges) /
+	    sizeof(irq_pio_range_t);
+	irq_pio_range_t ranges[range_count];
+	const size_t cmd_count = sizeof(i8042_cmds) / sizeof(irq_cmd_t);
+	irq_cmd_t cmds[cmd_count];
+
+	int rc;
+	bool kbd_bound = false;
+	bool aux_bound = false;
+
+	dev->kbd_fun = NULL;
+	dev->aux_fun = NULL;
+	
+	if (reg_size < sizeof(i8042_regs_t)) {
+		rc = EINVAL;
+		goto error;
+	}
+	
+	if (pio_enable(regs, sizeof(i8042_regs_t), (void **) &dev->regs) != 0) {
+		rc = EIO;
+		goto error;
+	}
 	
 	dev->kbd_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2a");
-	if (!dev->kbd_fun)
-		return ENOMEM;
-	
-	int ret = ddf_fun_add_match_id(dev->kbd_fun, "char/xtkbd", 90);
-	if (ret != EOK) {
-		ddf_fun_destroy(dev->kbd_fun);
-		return ret;
-	}
+	if (dev->kbd_fun == NULL) {
+		rc = ENOMEM;
+		goto error;
+	};
+	
+	rc = ddf_fun_add_match_id(dev->kbd_fun, "char/xtkbd", 90);
+	if (rc != EOK)
+		goto error;
 	
 	dev->aux_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2b");
-	if (!dev->aux_fun) {
-		ddf_fun_destroy(dev->kbd_fun);
-		return ENOMEM;
-	}
-	
-	ret = ddf_fun_add_match_id(dev->aux_fun, "char/ps2mouse", 90);
-	if (ret != EOK) {
-		ddf_fun_destroy(dev->kbd_fun);
-		ddf_fun_destroy(dev->aux_fun);
-		return ret;
-	}
-	
-	dev->kbd_fun->ops = &ops;
-	dev->aux_fun->ops = &ops;
-	dev->kbd_fun->driver_data = dev;
-	dev->aux_fun->driver_data = dev;
+	if (dev->aux_fun == NULL) {
+		rc = ENOMEM;
+		goto error;
+	}
+	
+	rc = ddf_fun_add_match_id(dev->aux_fun, "char/ps2mouse", 90);
+	if (rc != EOK)
+		goto error;
+	
+	ddf_fun_set_ops(dev->kbd_fun, &ops);
+	ddf_fun_set_ops(dev->aux_fun, &ops);
 	
 	buffer_init(&dev->kbd_buffer, dev->kbd_data, BUFFER_SIZE);
@@ -229,11 +240,19 @@
 	fibril_mutex_initialize(&dev->write_guard);
 	
-	ret = ddf_fun_bind(dev->kbd_fun);
-	CHECK_RET_DESTROY(ret, "Failed to bind keyboard function: %s.",
-	    str_error(ret));
-	
-	ret = ddf_fun_bind(dev->aux_fun);
-	CHECK_RET_DESTROY(ret, "Failed to bind mouse function: %s.",
-	    str_error(ret));
+	rc = ddf_fun_bind(dev->kbd_fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed to bind keyboard function: %s.",
+		    ddf_fun_get_name(dev->kbd_fun));
+		goto error;
+	}
+	kbd_bound = true;
+	
+	rc = ddf_fun_bind(dev->aux_fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed to bind aux function: %s.",
+		    ddf_fun_get_name(dev->aux_fun));
+		goto error;
+	}
+	aux_bound = true;
 	
 	/* Disable kbd and aux */
@@ -247,12 +266,7 @@
 		(void) pio_read_8(&dev->regs->data);
 
-	const size_t range_count = sizeof(i8042_ranges) /
-	    sizeof(irq_pio_range_t);
-	irq_pio_range_t ranges[range_count];
 	memcpy(ranges, i8042_ranges, sizeof(i8042_ranges));
 	ranges[0].base = (uintptr_t) regs;
 
-	const size_t cmd_count = sizeof(i8042_cmds) / sizeof(irq_cmd_t);
-	irq_cmd_t cmds[cmd_count];
 	memcpy(cmds, i8042_cmds, sizeof(i8042_cmds));
 	cmds[0].addr = (void *) &(((i8042_regs_t *) regs)->status);
@@ -266,25 +280,31 @@
 	};
 	
-	ret = register_interrupt_handler(ddf_dev, irq_kbd, i8042_irq_handler,
+	rc = register_interrupt_handler(ddf_dev, irq_kbd, i8042_irq_handler,
 	    &irq_code);
-	CHECK_RET_UNBIND_DESTROY(ret, "Failed set handler for kbd: %s.",
-	    str_error(ret));
-	
-	ret = register_interrupt_handler(ddf_dev, irq_mouse, i8042_irq_handler,
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed set handler for kbd: %s.",
+		    ddf_dev_get_name(ddf_dev));
+		goto error;
+	}
+	
+	rc = register_interrupt_handler(ddf_dev, irq_mouse, i8042_irq_handler,
 	    &irq_code);
-	CHECK_RET_UNBIND_DESTROY(ret, "Failed set handler for mouse: %s.",
-	    str_error(ret));
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed set handler for mouse: %s.",
+		    ddf_dev_get_name(ddf_dev));
+		goto error;
+	}
 	
 	/* Enable interrupts */
-	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, ddf_dev->handle,
-	    IPC_FLAG_BLOCKING);
-	ret = parent_sess ? EOK : ENOMEM;
-	CHECK_RET_UNBIND_DESTROY(ret, "Failed to create parent connection.");
+	async_sess_t *parent_sess = ddf_dev_parent_sess_get(ddf_dev);
+	assert(parent_sess != NULL);
 	
 	const bool enabled = hw_res_enable_interrupt(parent_sess);
-	async_hangup(parent_sess);
-	ret = enabled ? EOK : EIO;
-	CHECK_RET_UNBIND_DESTROY(ret, "Failed to enable interrupts: %s.");
+	if (!enabled) {
+		log_msg(LVL_ERROR, "Failed to enable interrupts: %s.",
+		    ddf_dev_get_name(ddf_dev));
+		rc = EIO;
+		goto error;
+	}
 	
 	/* Enable port interrupts. */
@@ -296,4 +316,15 @@
 	
 	return EOK;
+error:
+	if (kbd_bound)
+		ddf_fun_unbind(dev->kbd_fun);
+	if (aux_bound)
+		ddf_fun_unbind(dev->aux_fun);
+	if (dev->kbd_fun != NULL)
+		ddf_fun_destroy(dev->kbd_fun);
+	if (dev->aux_fun != NULL)
+		ddf_fun_destroy(dev->aux_fun);
+
+	return rc;
 }
 
@@ -315,8 +346,5 @@
 static int i8042_write(ddf_fun_t *fun, char *buffer, size_t size)
 {
-	assert(fun);
-	assert(fun->driver_data);
-	
-	i8042_t *controller = fun->driver_data;
+	i8042_t *controller = dev_i8042(ddf_fun_get_dev(fun));
 	fibril_mutex_lock(&controller->write_guard);
 	
@@ -347,8 +375,5 @@
 static int i8042_read(ddf_fun_t *fun, char *data, size_t size)
 {
-	assert(fun);
-	assert(fun->driver_data);
-	
-	i8042_t *controller = fun->driver_data;
+	i8042_t *controller = dev_i8042(ddf_fun_get_dev(fun));
 	buffer_t *buffer = (fun == controller->aux_fun) ?
 	    &controller->aux_buffer : &controller->kbd_buffer;
Index: uspace/drv/char/i8042/main.c
===================================================================
--- uspace/drv/char/i8042/main.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/char/i8042/main.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -37,5 +37,4 @@
 #include <libarch/inttypes.h>
 #include <ddf/driver.h>
-#include <devman.h>
 #include <device/hw_res_parsed.h>
 #include <errno.h>
@@ -64,13 +63,12 @@
  *
  */
-static int get_my_registers(const ddf_dev_t *dev, uintptr_t *io_reg_address,
+static int get_my_registers(ddf_dev_t *dev, uintptr_t *io_reg_address,
     size_t *io_reg_size, int *kbd_irq, int *mouse_irq)
 {
 	assert(dev);
 	
-	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
-	    IPC_FLAG_BLOCKING);
-	if (!parent_sess)
+	async_sess_t *parent_sess = ddf_dev_parent_sess_create(
+	    dev, EXCHANGE_SERIALIZE);
+	if (parent_sess == NULL)
 		return ENOMEM;
 	
@@ -78,5 +76,4 @@
 	hw_res_list_parsed_init(&hw_resources);
 	const int ret = hw_res_get_list_parsed(parent_sess, &hw_resources, 0);
-	async_hangup(parent_sess);
 	if (ret != EOK)
 		return ret;
@@ -136,5 +133,5 @@
 	
 	ddf_msg(LVL_NOTE, "Controlling '%s' (%" PRIun ").",
-	    device->name, device->handle);
+	    ddf_dev_get_name(device), ddf_dev_get_handle(device));
 	return EOK;
 }
Index: uspace/drv/char/ns8250/ns8250.c
===================================================================
--- uspace/drv/char/ns8250/ns8250.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/char/ns8250/ns8250.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -58,7 +58,5 @@
 #include <ops/char_dev.h>
 
-#include <devman.h>
 #include <ns.h>
-#include <ipc/devman.h>
 #include <ipc/services.h>
 #include <ipc/irc.h>
@@ -127,10 +125,4 @@
 #define	NS8250_MSR_SIGNALS	(NS8250_MSR_CTS | NS8250_MSR_DSR \
     | NS8250_MSR_RI | NS8250_MSR_DCD)
-
-/** Obtain soft-state structure from function node */
-#define NS8250(fnode) ((ns8250_t *) ((fnode)->dev->driver_data))
-
-/** Obtain soft-state structure from device node */
-#define NS8250_FROM_DEV(dnode) ((ns8250_t *) ((dnode)->driver_data))
 
 /** The number of bits of one data unit send by the serial port. */
@@ -187,4 +179,16 @@
 } ns8250_t;
 
+/** Obtain soft-state structure from device node */
+static ns8250_t *dev_ns8250(ddf_dev_t *dev)
+{
+	return ddf_dev_data_get(dev);
+}
+
+/** Obtain soft-state structure from function node */
+static ns8250_t *fun_ns8250(ddf_fun_t *fun)
+{
+	return dev_ns8250(ddf_fun_get_dev(fun));
+}
+
 /** Find out if there is some incomming data available on the serial port.
  *
@@ -241,5 +245,5 @@
 static int ns8250_read(ddf_fun_t *fun, char *buf, size_t count)
 {
-	ns8250_t *ns = NS8250(fun);
+	ns8250_t *ns = fun_ns8250(fun);
 	int ret = 0;
 	
@@ -279,5 +283,5 @@
 static int ns8250_write(ddf_fun_t *fun, char *buf, size_t count)
 {
-	ns8250_t *ns = NS8250(fun);
+	ns8250_t *ns = fun_ns8250(fun);
 	size_t idx;
 	
@@ -317,8 +321,4 @@
 static void ns8250_dev_cleanup(ns8250_t *ns)
 {
-	if (ns->dev->parent_sess) {
-		async_hangup(ns->dev->parent_sess);
-		ns->dev->parent_sess = NULL;
-	}
 }
 
@@ -330,5 +330,5 @@
 static bool ns8250_pio_enable(ns8250_t *ns)
 {
-	ddf_msg(LVL_DEBUG, "ns8250_pio_enable %s", ns->dev->name);
+	ddf_msg(LVL_DEBUG, "ns8250_pio_enable %s", ddf_dev_get_name(ns->dev));
 	
 	/* Gain control over port's registers. */
@@ -336,5 +336,5 @@
 	    (void **) &ns->port)) {
 		ddf_msg(LVL_ERROR, "Cannot map the port %#" PRIx32
-		    " for device %s.", ns->io_addr, ns->dev->name);
+		    " for device %s.", ns->io_addr, ddf_dev_get_name(ns->dev));
 		return false;
 	}
@@ -352,5 +352,5 @@
 static bool ns8250_dev_probe(ns8250_t *ns)
 {
-	ddf_msg(LVL_DEBUG, "ns8250_dev_probe %s", ns->dev->name);
+	ddf_msg(LVL_DEBUG, "ns8250_dev_probe %s", ddf_dev_get_name(ns->dev));
 	
 	bool res = true;
@@ -372,5 +372,5 @@
 	if (!res) {
 		ddf_msg(LVL_DEBUG, "Device %s is not present.",
-		    ns->dev->name);
+		    ddf_dev_get_name(ns->dev));
 	}
 	
@@ -385,7 +385,8 @@
 static int ns8250_dev_initialize(ns8250_t *ns)
 {
-	ddf_msg(LVL_DEBUG, "ns8250_dev_initialize %s", ns->dev->name);
-	
+	async_sess_t *parent_sess;
 	int ret = EOK;
+	
+	ddf_msg(LVL_DEBUG, "ns8250_dev_initialize %s", ddf_dev_get_name(ns->dev));
 	
 	hw_resource_list_t hw_resources;
@@ -393,9 +394,8 @@
 	
 	/* Connect to the parent's driver. */
-	ns->dev->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
-	    ns->dev->handle, IPC_FLAG_BLOCKING);
-	if (!ns->dev->parent_sess) {
+	parent_sess = ddf_dev_parent_sess_create(ns->dev, EXCHANGE_SERIALIZE);
+	if (parent_sess == NULL) {
 		ddf_msg(LVL_ERROR, "Failed to connect to parent driver of "
-		    "device %s.", ns->dev->name);
+		    "device %s.", ddf_dev_get_name(ns->dev));
 		ret = ENOENT;
 		goto failed;
@@ -403,8 +403,8 @@
 	
 	/* Get hw resources. */
-	ret = hw_res_get_resource_list(ns->dev->parent_sess, &hw_resources);
+	ret = hw_res_get_resource_list(parent_sess, &hw_resources);
 	if (ret != EOK) {
 		ddf_msg(LVL_ERROR, "Failed to get HW resources for device "
-		    "%s.", ns->dev->name);
+		    "%s.", ddf_dev_get_name(ns->dev));
 		goto failed;
 	}
@@ -422,5 +422,5 @@
 			irq = true;
 			ddf_msg(LVL_NOTE, "Device %s was asigned irq = 0x%x.",
-			    ns->dev->name, ns->irq);
+			    ddf_dev_get_name(ns->dev), ns->irq);
 			break;
 			
@@ -429,5 +429,5 @@
 			if (res->res.io_range.size < REG_COUNT) {
 				ddf_msg(LVL_ERROR, "I/O range assigned to "
-				    "device %s is too small.", ns->dev->name);
+				    "device %s is too small.", ddf_dev_get_name(ns->dev));
 				ret = ELIMIT;
 				goto failed;
@@ -435,5 +435,5 @@
 			ioport = true;
 			ddf_msg(LVL_NOTE, "Device %s was asigned I/O address = "
-			    "0x%x.", ns->dev->name, ns->io_addr);
+			    "0x%x.", ddf_dev_get_name(ns->dev), ns->io_addr);
     			break;
 			
@@ -445,5 +445,5 @@
 	if (!irq || !ioport) {
 		ddf_msg(LVL_ERROR, "Missing HW resource(s) for device %s.",
-		    ns->dev->name);
+		    ddf_dev_get_name(ns->dev));
 		ret = ENOENT;
 		goto failed;
@@ -613,4 +613,7 @@
 	*parity = ((val >> NS8250_LCR_PARITY) & 7);
 	
+	/* Silence warnings */
+	*word_length = 0;
+
 	switch (val & 3) {
 	case WORD_LENGTH_5:
@@ -755,10 +758,10 @@
 				if (!buf_push_back(&ns->input_buffer, val)) {
 					ddf_msg(LVL_WARN, "Buffer overflow on "
-					    "%s.", ns->dev->name);
+					    "%s.", ddf_dev_get_name(ns->dev));
 					break;
 				} else {
 					ddf_msg(LVL_DEBUG2, "Character %c saved "
 					    "to the buffer of %s.",
-					    val, ns->dev->name);
+					    val, ddf_dev_get_name(ns->dev));
 					if (buf_was_empty)
 						fibril_condvar_broadcast(&ns->input_buffer_available);
@@ -782,5 +785,5 @@
     ipc_call_t *icall)
 {
-	ns8250_t *ns = NS8250_FROM_DEV(dev);
+	ns8250_t *ns = dev_ns8250(dev);
 
 	uint8_t iir = pio_read_8(&ns->regs->iid);
@@ -788,5 +791,5 @@
 		uint8_t lsr = pio_read_8(&ns->regs->lsr);
 		if (lsr & NS8250_LSR_OE) {
-			ddf_msg(LVL_WARN, "Overrun error on %s", ns->dev->name);
+			ddf_msg(LVL_WARN, "Overrun error on %s", ddf_dev_get_name(ns->dev));
 		}
 	}
@@ -828,5 +831,5 @@
 	
 	ddf_msg(LVL_DEBUG, "ns8250_dev_add %s (handle = %d)",
-	    dev->name, (int) dev->handle);
+	    ddf_dev_get_name(dev), (int) ddf_dev_get_handle(dev));
 	
 	/* Allocate soft-state for the device */
@@ -883,5 +886,5 @@
 	
 	/* Set device operations. */
-	fun->ops = &ns8250_dev_ops;
+	ddf_fun_set_ops(fun, &ns8250_dev_ops);
 	rc = ddf_fun_bind(fun);
 	if (rc != EOK) {
@@ -895,5 +898,5 @@
 	
 	ddf_msg(LVL_NOTE, "Device %s successfully initialized.",
-	    dev->name);
+	    ddf_dev_get_name(dev));
 	
 	return EOK;
@@ -908,5 +911,5 @@
 static int ns8250_dev_remove(ddf_dev_t *dev)
 {
-	ns8250_t *ns = NS8250_FROM_DEV(dev);
+	ns8250_t *ns = dev_ns8250(dev);
 	int rc;
 	
@@ -942,5 +945,5 @@
 static int ns8250_open(ddf_fun_t *fun)
 {
-	ns8250_t *ns = NS8250(fun);
+	ns8250_t *ns = fun_ns8250(fun);
 	int res;
 	
@@ -968,5 +971,5 @@
 static void ns8250_close(ddf_fun_t *fun)
 {
-	ns8250_t *data = (ns8250_t *) fun->dev->driver_data;
+	ns8250_t *data = fun_ns8250(fun);
 	
 	fibril_mutex_lock(&data->mutex);
@@ -993,5 +996,5 @@
     unsigned int *word_length, unsigned int* stop_bits)
 {
-	ns8250_t *data = (ns8250_t *) dev->driver_data;
+	ns8250_t *data = dev_ns8250(dev);
 	ns8250_regs_t *regs = data->regs;
 	
@@ -1024,5 +1027,5 @@
 	    stop_bits);
 	
-	ns8250_t *data = (ns8250_t *) dev->driver_data;
+	ns8250_t *data = dev_ns8250(dev);
 	ns8250_regs_t *regs = data->regs;
 	int ret;
@@ -1053,5 +1056,5 @@
 	switch (method) {
 	case SERIAL_GET_COM_PROPS:
-		ns8250_get_props(fun->dev, &baud_rate, &parity, &word_length,
+		ns8250_get_props(ddf_fun_get_dev(fun), &baud_rate, &parity, &word_length,
 		    &stop_bits);
 		async_answer_4(callid, EOK, baud_rate, parity, word_length,
@@ -1064,5 +1067,5 @@
 		word_length = IPC_GET_ARG3(*call);
 		stop_bits = IPC_GET_ARG4(*call);
-		ret = ns8250_set_props(fun->dev, baud_rate, parity, word_length,
+		ret = ns8250_set_props(ddf_fun_get_dev(fun), baud_rate, parity, word_length,
 		    stop_bits);
 		async_answer_0(callid, ret);
Index: uspace/drv/char/ps2mouse/main.c
===================================================================
--- uspace/drv/char/ps2mouse/main.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/char/ps2mouse/main.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -98,5 +98,5 @@
 
 	ddf_msg(LVL_NOTE, "Controlling '%s' (%" PRIun ").",
-	    device->name, device->handle);
+	    ddf_dev_get_name(device), ddf_dev_get_handle(device));
 	return EOK;
 }
Index: uspace/drv/char/ps2mouse/ps2mouse.c
===================================================================
--- uspace/drv/char/ps2mouse/ps2mouse.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/char/ps2mouse/ps2mouse.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -35,5 +35,4 @@
 #include <bool.h>
 #include <errno.h>
-#include <devman.h>
 #include <ddf/log.h>
 #include <io/keycode.h>
@@ -114,9 +113,6 @@
 int ps2_mouse_init(ps2_mouse_t *mouse, ddf_dev_t *dev)
 {
-	assert(mouse);
-	assert(dev);
 	mouse->client_sess = NULL;
-	mouse->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
-	    dev->handle, IPC_FLAG_BLOCKING);
+	mouse->parent_sess = ddf_dev_parent_sess_create(dev, EXCHANGE_SERIALIZE);
 	if (!mouse->parent_sess)
 		return ENOMEM;
@@ -124,14 +120,10 @@
 	mouse->mouse_fun = ddf_fun_create(dev, fun_exposed, "mouse");
 	if (!mouse->mouse_fun) {
-		async_hangup(mouse->parent_sess);
-		return ENOMEM;
-	}
-	mouse->mouse_fun->ops = &mouse_ops;
-	mouse->mouse_fun->driver_data = mouse;
+		return ENOMEM;
+	}
+	ddf_fun_set_ops(mouse->mouse_fun, &mouse_ops);
 
 	int ret = ddf_fun_bind(mouse->mouse_fun);
 	if (ret != EOK) {
-		async_hangup(mouse->parent_sess);
-		mouse->mouse_fun->driver_data = NULL;
 		ddf_fun_destroy(mouse->mouse_fun);
 		return ENOMEM;
@@ -140,7 +132,5 @@
 	ret = ddf_fun_add_to_category(mouse->mouse_fun, "mouse");
 	if (ret != EOK) {
-		async_hangup(mouse->parent_sess);
 		ddf_fun_unbind(mouse->mouse_fun);
-		mouse->mouse_fun->driver_data = NULL;
 		ddf_fun_destroy(mouse->mouse_fun);
 		return ENOMEM;
@@ -161,7 +151,5 @@
 		ddf_msg(LVL_ERROR, "Failed to enable data reporting.");
 		async_exchange_end(exch);
-		async_hangup(mouse->parent_sess);
 		ddf_fun_unbind(mouse->mouse_fun);
-		mouse->mouse_fun->driver_data = NULL;
 		ddf_fun_destroy(mouse->mouse_fun);
 		return EIO;
@@ -173,7 +161,5 @@
 		ddf_msg(LVL_ERROR, "Failed to confirm data reporting: %hhx.",
 		    report);
-		async_hangup(mouse->parent_sess);
 		ddf_fun_unbind(mouse->mouse_fun);
-		mouse->mouse_fun->driver_data = NULL;
 		ddf_fun_destroy(mouse->mouse_fun);
 		return EIO;
@@ -182,7 +168,5 @@
 	mouse->polling_fibril = fibril_create(polling_f, mouse);
 	if (!mouse->polling_fibril) {
-		async_hangup(mouse->parent_sess);
 		ddf_fun_unbind(mouse->mouse_fun);
-		mouse->mouse_fun->driver_data = NULL;
 		ddf_fun_destroy(mouse->mouse_fun);
 		return ENOMEM;
@@ -368,12 +352,6 @@
     ipc_callid_t icallid, ipc_call_t *icall)
 {
-	if (fun == NULL || fun->driver_data == NULL) {
-		ddf_msg(LVL_ERROR, "%s: Missing parameter.", __FUNCTION__);
-		async_answer_0(icallid, EINVAL);
-		return;
-	}
-
 	const sysarg_t method = IPC_GET_IMETHOD(*icall);
-	ps2_mouse_t *mouse = fun->driver_data;
+	ps2_mouse_t *mouse = ddf_dev_data_get(ddf_fun_get_dev(fun));
 
 	switch (method) {
Index: uspace/drv/char/xtkbd/main.c
===================================================================
--- uspace/drv/char/xtkbd/main.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/char/xtkbd/main.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -98,5 +98,5 @@
 
 	ddf_msg(LVL_NOTE, "Controlling '%s' (%" PRIun ").",
-	    device->name, device->handle);
+	    ddf_dev_get_name(device), ddf_dev_get_handle(device));
 	return EOK;
 }
Index: uspace/drv/char/xtkbd/xtkbd.c
===================================================================
--- uspace/drv/char/xtkbd/xtkbd.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/char/xtkbd/xtkbd.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -34,5 +34,4 @@
 
 #include <errno.h>
-#include <devman.h>
 #include <ddf/log.h>
 #include <io/keycode.h>
@@ -207,6 +206,5 @@
 	assert(dev);
 	kbd->client_sess = NULL;
-	kbd->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
-	    dev->handle, IPC_FLAG_BLOCKING);
+	kbd->parent_sess = ddf_dev_parent_sess_create(dev, EXCHANGE_SERIALIZE);
 	if (!kbd->parent_sess)
 		return ENOMEM;
@@ -214,14 +212,10 @@
 	kbd->kbd_fun = ddf_fun_create(dev, fun_exposed, "kbd");
 	if (!kbd->kbd_fun) {
-		async_hangup(kbd->parent_sess);
-		return ENOMEM;
-	}
-	kbd->kbd_fun->ops = &kbd_ops;
-	kbd->kbd_fun->driver_data = kbd;
+		return ENOMEM;
+	}
+	ddf_fun_set_ops(kbd->kbd_fun, &kbd_ops);
 
 	int ret = ddf_fun_bind(kbd->kbd_fun);
 	if (ret != EOK) {
-		async_hangup(kbd->parent_sess);
-		kbd->kbd_fun->driver_data = NULL;
 		ddf_fun_destroy(kbd->kbd_fun);
 		return ENOMEM;
@@ -230,7 +224,5 @@
 	ret = ddf_fun_add_to_category(kbd->kbd_fun, "keyboard");
 	if (ret != EOK) {
-		async_hangup(kbd->parent_sess);
 		ddf_fun_unbind(kbd->kbd_fun);
-		kbd->kbd_fun->driver_data = NULL;
 		ddf_fun_destroy(kbd->kbd_fun);
 		return ENOMEM;
@@ -239,7 +231,5 @@
 	kbd->polling_fibril = fibril_create(polling, kbd);
 	if (!kbd->polling_fibril) {
-		async_hangup(kbd->parent_sess);
 		ddf_fun_unbind(kbd->kbd_fun);
-		kbd->kbd_fun->driver_data = NULL;
 		ddf_fun_destroy(kbd->kbd_fun);
 		return ENOMEM;
@@ -319,12 +309,6 @@
     ipc_callid_t icallid, ipc_call_t *icall)
 {
-	if (fun == NULL || fun->driver_data == NULL) {
-		ddf_msg(LVL_ERROR, "%s: Missing parameter.", __FUNCTION__);
-		async_answer_0(icallid, EINVAL);
-		return;
-	}
-
 	const sysarg_t method = IPC_GET_IMETHOD(*icall);
-	xt_kbd_t *kbd = fun->driver_data;
+	xt_kbd_t *kbd = ddf_dev_data_get(ddf_fun_get_dev(fun));
 
 	switch (method) {
Index: uspace/drv/fb/kfb/port.c
===================================================================
--- uspace/drv/fb/kfb/port.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/fb/kfb/port.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -344,5 +344,5 @@
 		return ENOMEM;
 	}
-	fun_vs->ops = &graph_vsl_device_ops;
+	ddf_fun_set_ops(fun_vs, &graph_vsl_device_ops);
 
 	visualizer_t *vs = ddf_fun_data_alloc(fun_vs, sizeof(visualizer_t));
@@ -380,5 +380,5 @@
 	}
 
-	vs->reg_svc_handle = fun_vs->handle;
+	vs->reg_svc_handle = ddf_fun_get_handle(fun_vs);
 	ddf_fun_add_to_category(fun_vs, "visualizer");
 
Index: uspace/drv/infrastructure/root/root.c
===================================================================
--- uspace/drv/infrastructure/root/root.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/infrastructure/root/root.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -204,5 +204,5 @@
 {
 	ddf_msg(LVL_DEBUG, "root_dev_add, device handle=%" PRIun,
-	    dev->handle);
+	    ddf_dev_get_handle(dev));
 
 	/*
Index: uspace/drv/infrastructure/rootmac/rootmac.c
===================================================================
--- uspace/drv/infrastructure/rootmac/rootmac.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/infrastructure/rootmac/rootmac.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -44,8 +44,4 @@
 #define NAME  "rootmac"
 
-/** Obtain function soft-state from DDF function node */
-#define ROOTMAC_FUN(fnode) \
-	((rootmac_fun_t *) (fnode)->driver_data)
-
 typedef struct {
 	hw_resource_list_t hw_resources;
@@ -80,11 +76,17 @@
 static ddf_dev_ops_t rootmac_fun_ops;
 
+/** Obtain function soft-state from DDF function node */
+static rootmac_fun_t *rootmac_fun(ddf_fun_t *fnode)
+{
+	return ddf_fun_data_get(fnode);
+}
+
 static bool rootmac_add_fun(ddf_dev_t *dev, const char *name,
-    const char *str_match_id, rootmac_fun_t *fun)
+    const char *str_match_id, rootmac_fun_t *fun_proto)
 {
 	ddf_msg(LVL_DEBUG, "Adding new function '%s'.", name);
 	
 	ddf_fun_t *fnode = NULL;
-	match_id_t *match_id = NULL;
+	int rc;
 	
 	/* Create new device. */
@@ -93,17 +95,14 @@
 		goto failure;
 	
-	fnode->driver_data = fun;
+	rootmac_fun_t *fun = ddf_fun_data_alloc(fnode, sizeof(rootmac_fun_t));
+	*fun = *fun_proto;
 	
-	/* Initialize match id list */
-	match_id = create_match_id();
-	if (match_id == NULL)
+	/* Add match ID */
+	rc = ddf_fun_add_match_id(fnode, str_match_id, 100);
+	if (rc != EOK)
 		goto failure;
 	
-	match_id->id = str_match_id;
-	match_id->score = 100;
-	add_match_id(&fnode->match_ids, match_id);
-	
 	/* Set provided operations to the device. */
-	fnode->ops = &rootmac_fun_ops;
+	ddf_fun_set_ops(fnode, &rootmac_fun_ops);
 	
 	/* Register function. */
@@ -116,7 +115,4 @@
 	
 failure:
-	if (match_id != NULL)
-		match_id->id = NULL;
-	
 	if (fnode != NULL)
 		ddf_fun_destroy(fnode);
@@ -162,5 +158,5 @@
 static hw_resource_list_t *rootmac_get_resources(ddf_fun_t *fnode)
 {
-	rootmac_fun_t *fun = ROOTMAC_FUN(fnode);
+	rootmac_fun_t *fun = rootmac_fun(fnode);
 	assert(fun != NULL);
 	
Index: uspace/drv/infrastructure/rootpc/rootpc.c
===================================================================
--- uspace/drv/infrastructure/rootpc/rootpc.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/infrastructure/rootpc/rootpc.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -53,7 +53,4 @@
 
 #define NAME "rootpc"
-
-/** Obtain function soft-state from DDF function node */
-#define ROOTPC_FUN(fnode) ((rootpc_fun_t *) (fnode)->driver_data)
 
 typedef struct rootpc_fun {
@@ -101,7 +98,13 @@
 };
 
+/** Obtain function soft-state from DDF function node */
+static rootpc_fun_t *rootpc_fun(ddf_fun_t *fnode)
+{
+	return ddf_fun_data_get(fnode);
+}
+
 static hw_resource_list_t *rootpc_get_resources(ddf_fun_t *fnode)
 {
-	rootpc_fun_t *fun = ROOTPC_FUN(fnode);
+	rootpc_fun_t *fun = rootpc_fun(fnode);
 	
 	assert(fun != NULL);
@@ -126,10 +129,10 @@
 static bool
 rootpc_add_fun(ddf_dev_t *dev, const char *name, const char *str_match_id,
-    rootpc_fun_t *fun)
+    rootpc_fun_t *fun_proto)
 {
 	ddf_msg(LVL_DEBUG, "Adding new function '%s'.", name);
 	
 	ddf_fun_t *fnode = NULL;
-	match_id_t *match_id = NULL;
+	int rc;
 	
 	/* Create new device. */
@@ -138,17 +141,14 @@
 		goto failure;
 	
-	fnode->driver_data = fun;
-	
-	/* Initialize match id list */
-	match_id = create_match_id();
-	if (match_id == NULL)
+	rootpc_fun_t *fun = ddf_fun_data_alloc(fnode, sizeof(rootpc_fun_t));
+	*fun = *fun_proto;
+	
+	/* Add match ID */
+	rc = ddf_fun_add_match_id(fnode, str_match_id, 100);
+	if (rc != EOK)
 		goto failure;
 	
-	match_id->id = str_match_id;
-	match_id->score = 100;
-	add_match_id(&fnode->match_ids, match_id);
-	
 	/* Set provided operations to the device. */
-	fnode->ops = &rootpc_fun_ops;
+	ddf_fun_set_ops(fnode, &rootpc_fun_ops);
 	
 	/* Register function. */
@@ -161,7 +161,4 @@
 	
 failure:
-	if (match_id != NULL)
-		match_id->id = NULL;
-	
 	if (fnode != NULL)
 		ddf_fun_destroy(fnode);
@@ -186,5 +183,5 @@
 {
 	ddf_msg(LVL_DEBUG, "rootpc_dev_add, device handle = %d",
-	    (int)dev->handle);
+	    (int)ddf_dev_get_handle(dev));
 	
 	/* Register functions. */
Index: uspace/drv/infrastructure/rootvirt/rootvirt.c
===================================================================
--- uspace/drv/infrastructure/rootvirt/rootvirt.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/infrastructure/rootvirt/rootvirt.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -151,5 +151,5 @@
 {
 	int rc;
-	const char *name = rvfun->fun->name;
+	const char *name = ddf_fun_get_name(rvfun->fun);
 
 	ddf_msg(LVL_DEBUG, "rootvirt_fun_remove('%s')", name);
@@ -183,5 +183,5 @@
 	}
 
-	ddf_msg(LVL_DEBUG, "dev_add(handle=%d)", (int)dev->handle);
+	ddf_msg(LVL_DEBUG, "dev_add(handle=%d)", (int)ddf_dev_get_handle(dev));
 
 	rootvirt = ddf_dev_data_alloc(dev, sizeof(rootvirt_t));
@@ -207,5 +207,5 @@
 static int rootvirt_dev_remove(ddf_dev_t *dev)
 {
-	rootvirt_t *rootvirt = (rootvirt_t *)dev->driver_data;
+	rootvirt_t *rootvirt = (rootvirt_t *)ddf_dev_data_get(dev);
 	int rc;
 
Index: uspace/drv/nic/e1k/e1k.c
===================================================================
--- uspace/drv/nic/e1k/e1k.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/nic/e1k/e1k.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -32,4 +32,7 @@
  *
  */
+
+/* XXX Fix this */
+#define _DDF_DATA_IMPLANT
 
 #include <assert.h>
@@ -71,11 +74,19 @@
 	((e1000_t *) nic_get_specific(nic))
 
-/** device_t* -> nic_driver_data_t* cast */
+/** ddf_fun_t * -> nic_driver_data_t* cast */
+#define NIC_DATA_FUN(fun) \
+	((nic_t *) ddf_fun_data_get(fun))
+
+/** ddf_dev_t * -> nic_driver_data_t* cast */
 #define NIC_DATA_DEV(dev) \
-	((nic_t *) ((dev)->driver_data))
-
-/** device_t* -> e1000_t* cast */
+	((nic_t *) ddf_dev_data_get(dev))
+
+/** ddf_dev_t * -> e1000_t* cast */
 #define DRIVER_DATA_DEV(dev) \
 	(DRIVER_DATA_NIC(NIC_DATA_DEV(dev)))
+
+/** ddf_fun_t * -> e1000_t* cast */
+#define DRIVER_DATA_FUN(fun) \
+	(DRIVER_DATA_NIC(NIC_DATA_FUN(fun)))
 
 /** Cast pointer to uint64_t
@@ -305,11 +316,7 @@
  *
  */
-static int e1000_get_cable_state(ddf_fun_t *dev, nic_cable_state_t *state)
-{
-	assert(dev);
-	assert(DRIVER_DATA_DEV(dev));
-	assert(state);
-	
-	e1000_t *e1000 = DRIVER_DATA_DEV(dev);
+static int e1000_get_cable_state(ddf_fun_t *fun, nic_cable_state_t *state)
+{
+	e1000_t *e1000 = DRIVER_DATA_FUN(fun);
 	if (E1000_REG_READ(e1000, E1000_STATUS) & (STATUS_LU))
 		*state = NIC_CS_PLUGGED;
@@ -328,8 +335,8 @@
  *
  */
-static int e1000_get_operation_mode(ddf_fun_t *dev, int *speed,
+static int e1000_get_operation_mode(ddf_fun_t *fun, int *speed,
     nic_channel_mode_t *duplex, nic_role_t *role)
 {
-	e1000_t *e1000 = DRIVER_DATA_DEV(dev);
+	e1000_t *e1000 = DRIVER_DATA_FUN(fun);
 	uint32_t status = E1000_REG_READ(e1000, E1000_STATUS);
 	
@@ -376,5 +383,5 @@
  *
  */
-static int e1000_set_operation_mode(ddf_fun_t *dev, int speed,
+static int e1000_set_operation_mode(ddf_fun_t *fun, int speed,
     nic_channel_mode_t duplex, nic_role_t role)
 {
@@ -385,5 +392,5 @@
 		return EINVAL;
 	
-	e1000_t *e1000 = DRIVER_DATA_DEV(dev);
+	e1000_t *e1000 = DRIVER_DATA_FUN(fun);
 	
 	fibril_mutex_lock(&e1000->ctrl_lock);
@@ -424,7 +431,7 @@
  *
  */
-static int e1000_autoneg_enable(ddf_fun_t *dev, uint32_t advertisement)
-{
-	e1000_t *e1000 = DRIVER_DATA_DEV(dev);
+static int e1000_autoneg_enable(ddf_fun_t *fun, uint32_t advertisement)
+{
+	e1000_t *e1000 = DRIVER_DATA_FUN(fun);
 	
 	fibril_mutex_lock(&e1000->ctrl_lock);
@@ -452,7 +459,7 @@
  *
  */
-static int e1000_autoneg_disable(ddf_fun_t *dev)
-{
-	e1000_t *e1000 = DRIVER_DATA_DEV(dev);
+static int e1000_autoneg_disable(ddf_fun_t *fun)
+{
+	e1000_t *e1000 = DRIVER_DATA_FUN(fun);
 	
 	fibril_mutex_lock(&e1000->ctrl_lock);
@@ -491,7 +498,7 @@
  *
  */
-static int e1000_defective_get_mode(ddf_fun_t *device, uint32_t *mode)
-{
-	e1000_t *e1000 = DRIVER_DATA_DEV(device);
+static int e1000_defective_get_mode(ddf_fun_t *fun, uint32_t *mode)
+{
+	e1000_t *e1000 = DRIVER_DATA_FUN(fun);
 	
 	*mode = 0;
@@ -512,7 +519,7 @@
  *
  */
-static int e1000_defective_set_mode(ddf_fun_t *device, uint32_t mode)
-{
-	e1000_t *e1000 = DRIVER_DATA_DEV(device);
+static int e1000_defective_set_mode(ddf_fun_t *fun, uint32_t mode)
+{
+	e1000_t *e1000 = DRIVER_DATA_FUN(fun);
 	int rc = EOK;
 	
@@ -1038,5 +1045,5 @@
  *
  */
-static int e1000_vlan_set_tag(ddf_fun_t *device, uint16_t tag, bool add,
+static int e1000_vlan_set_tag(ddf_fun_t *fun, uint16_t tag, bool add,
     bool strip)
 {
@@ -1052,5 +1059,5 @@
 		return ENOTSUP;
 	
-	e1000_t *e1000 = DRIVER_DATA_DEV(device);
+	e1000_t *e1000 = DRIVER_DATA_FUN(fun);
 	
 	e1000->vlan_tag = tag;
@@ -1855,7 +1862,4 @@
 static e1000_t *e1000_create_dev_data(ddf_dev_t *dev)
 {
-	assert(dev);
-	assert(!dev->driver_data);
-	
 	nic_t *nic = nic_create_and_bind(dev);
 	if (!nic)
@@ -1896,5 +1900,5 @@
 	assert(dev);
 	
-	if (dev->driver_data != NULL)
+	if (ddf_dev_data_get(dev) != NULL)
 		nic_unbind_and_destroy(dev);
 }
@@ -1910,9 +1914,4 @@
 	
 	e1000_delete_dev_data(dev);
-	
-	if (dev->parent_sess != NULL) {
-		async_hangup(dev->parent_sess);
-		dev->parent_sess = NULL;
-	}
 }
 
@@ -1931,8 +1930,4 @@
     const hw_res_list_parsed_t *hw_resources)
 {
-	assert(dev != NULL);
-	assert(hw_resources != NULL);
-	assert(dev->driver_data != NULL);
-	
 	e1000_t *e1000 = DRIVER_DATA_DEV(dev);
 	
@@ -2003,5 +1998,5 @@
 	
 	uint16_t device_id;
-	rc = pci_config_space_read_16(dev->parent_sess, PCI_DEVICE_ID,
+	rc = pci_config_space_read_16(ddf_dev_parent_sess_get(dev), PCI_DEVICE_ID,
 	    &device_id);
 	if (rc != EOK) {
@@ -2121,5 +2116,5 @@
 	
 	/* Device initialization */
-	nic_t *nic = dev->driver_data;
+	nic_t *nic = ddf_dev_data_get(dev);
 	e1000_t *e1000 = DRIVER_DATA_NIC(nic);
 	
@@ -2147,6 +2142,6 @@
 		goto err_tx_structure;
 	nic_set_ddf_fun(nic, fun);
-	fun->ops = &e1000_dev_ops;
-	fun->driver_data = nic;
+	ddf_fun_set_ops(fun, &e1000_dev_ops);
+	ddf_fun_data_implant(fun, nic);
 	
 	rc = e1000_register_int_handler(nic);
@@ -2278,7 +2273,7 @@
  * @return Negative error code otherwise
  */
-static int e1000_set_addr(ddf_fun_t *dev, const nic_address_t *addr)
-{
-	nic_t *nic = NIC_DATA_DEV(dev);
+static int e1000_set_addr(ddf_fun_t *fun, const nic_address_t *addr)
+{
+	nic_t *nic = NIC_DATA_FUN(fun);
 	e1000_t *e1000 = DRIVER_DATA_NIC(nic);
 	
Index: uspace/drv/nic/ne2k/ne2k.c
===================================================================
--- uspace/drv/nic/ne2k/ne2k.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/nic/ne2k/ne2k.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -38,4 +38,7 @@
  */
 
+/* XXX Fix this */
+#define _DDF_DATA_IMPLANT
+
 #include <stdio.h>
 #include <errno.h>
@@ -61,5 +64,5 @@
 #define IRQ_GET_TSR(call)  ((int) IPC_GET_ARG3(call))
 
-#define DRIVER_DATA(dev) ((nic_t *) ((dev)->driver_data))
+#define DRIVER_DATA(dev) ((nic_t *) ddf_dev_data_get(dev))
 #define NE2K(device) ((ne2k_t *) nic_get_specific(DRIVER_DATA(device)))
 
@@ -169,5 +172,5 @@
 static void ne2k_dev_cleanup(ddf_dev_t *dev)
 {
-	if (dev->driver_data != NULL) {
+	if (ddf_dev_data_get(dev) != NULL) {
 		ne2k_t *ne2k = NE2K(dev);
 		if (ne2k) {
@@ -177,8 +180,4 @@
 		nic_unbind_and_destroy(dev);
 	}
-	if (dev->parent_sess != NULL) {
-		async_hangup(dev->parent_sess);
-		dev->parent_sess = NULL;
-	}
 }
 
@@ -279,5 +278,5 @@
 static int ne2k_set_address(ddf_fun_t *fun, const nic_address_t *address)
 {
-	nic_t *nic_data = DRIVER_DATA(fun);
+	nic_t *nic_data = DRIVER_DATA(ddf_fun_get_dev(fun));
 	int rc = nic_report_address(nic_data, address);
 	if (rc != EOK) {
@@ -410,6 +409,6 @@
 	}
 	nic_set_ddf_fun(nic_data, fun);
-	fun->ops = &ne2k_dev_ops;
-	fun->driver_data = nic_data;
+	ddf_fun_set_ops(fun, &ne2k_dev_ops);
+	ddf_fun_data_implant(fun, nic_data);
 	
 	rc = ddf_fun_bind(fun);
Index: uspace/drv/nic/rtl8139/driver.c
===================================================================
--- uspace/drv/nic/rtl8139/driver.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/nic/rtl8139/driver.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -27,4 +27,7 @@
  */
 
+/* XXX Fix this */
+#define _DDF_DATA_IMPLANT
+
 #include <assert.h>
 #include <errno.h>
@@ -212,13 +215,12 @@
 	rtl8139_regs_lock(rtl8139->io_port);
 
+	async_sess_t *pci_sess =
+		ddf_dev_parent_sess_get(nic_get_ddf_dev(rtl8139->nic_data));
+
 	if (bit_val) {
-		async_sess_t *pci_sess =
-			nic_get_ddf_dev(rtl8139->nic_data)->parent_sess;
 		uint8_t pmen;
 		pci_config_space_read_8(pci_sess, 0x55, &pmen);
 		pci_config_space_write_8(pci_sess, 0x55, pmen | 1 | (1 << 7));
 	} else {
-		async_sess_t *pci_sess =
-			nic_get_ddf_dev(rtl8139->nic_data)->parent_sess;
 		uint8_t pmen;
 		pci_config_space_read_8(pci_sess, 0x55, &pmen);
@@ -1052,11 +1054,6 @@
 	assert(dev);
 
-	if (dev->driver_data)
+	if (ddf_dev_data_get(dev))
 		nic_unbind_and_destroy(dev);
-
-	if (dev->parent_sess != NULL) {
-		async_hangup(dev->parent_sess);
-		dev->parent_sess = NULL;
-	}
 }
 
@@ -1080,22 +1077,22 @@
 
 	if (hw_resources->irqs.count != 1) {
-		ddf_msg(LVL_ERROR, "%s device: unexpected irq count", dev->name);
+		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", dev->name);
+		ddf_msg(LVL_ERROR, "%s device: unexpected io ranges count", ddf_dev_get_name(dev));
 		return EINVAL;
 	}
 
 	rtl8139->irq = hw_resources->irqs.irqs[0];
-	ddf_msg(LVL_DEBUG, "%s device: irq 0x%x assigned", dev->name, rtl8139->irq);
+	ddf_msg(LVL_DEBUG, "%s device: irq 0x%x assigned", ddf_dev_get_name(dev), rtl8139->irq);
 
 	rtl8139->io_addr = IOADDR_TO_PTR(hw_resources->io_ranges.ranges[0].address);
 	if (hw_resources->io_ranges.ranges[0].size < RTL8139_IO_SIZE) {
 		ddf_msg(LVL_ERROR, "i/o range assigned to the device "
-		    "%s is too small.", dev->name);
+		    "%s is too small.", ddf_dev_get_name(dev));
 		return EINVAL;
 	}
-	ddf_msg(LVL_DEBUG, "%s device: i/o addr %p assigned.", dev->name, rtl8139->io_addr);
+	ddf_msg(LVL_DEBUG, "%s device: i/o addr %p assigned.", ddf_dev_get_name(dev), rtl8139->io_addr);
 
 	return EOK;
@@ -1192,5 +1189,5 @@
 static int rtl8139_device_initialize(ddf_dev_t *dev)
 {
-	ddf_msg(LVL_DEBUG, "rtl8139_dev_initialize %s", dev->name);
+	ddf_msg(LVL_DEBUG, "rtl8139_dev_initialize %s", ddf_dev_get_name(dev));
 
 	int ret = EOK;
@@ -1201,5 +1198,5 @@
 	rtl8139_t *rtl8139 = rtl8139_create_dev_data(dev);
 	if (rtl8139 == NULL) {
-		ddf_msg(LVL_ERROR, "Not enough memory for initializing %s.", dev->name);
+		ddf_msg(LVL_ERROR, "Not enough memory for initializing %s.", ddf_dev_get_name(dev));
 		return ENOMEM;
 	}
@@ -1246,5 +1243,5 @@
 static int rtl8139_pio_enable(ddf_dev_t *dev)
 {
-	ddf_msg(LVL_DEBUG, NAME ": rtl8139_pio_enable %s", dev->name);
+	ddf_msg(LVL_DEBUG, NAME ": rtl8139_pio_enable %s", ddf_dev_get_name(dev));
 
 	rtl8139_t *rtl8139 = nic_get_specific(nic_get_from_ddf_dev(dev));
@@ -1253,5 +1250,5 @@
 	if (pio_enable(rtl8139->io_addr, RTL8139_IO_SIZE, &rtl8139->io_port)) {
 		ddf_msg(LVL_ERROR, "Cannot gain the port %lx for device %s.", rtl8139->io_addr,
-		    dev->name);
+		    ddf_dev_get_name(dev));
 		return EADDRNOTAVAIL;
 	}
@@ -1299,5 +1296,6 @@
 
 	assert(dev);
-	ddf_msg(LVL_NOTE, "RTL8139_dev_add %s (handle = %d)", dev->name, dev->handle);
+	ddf_msg(LVL_NOTE, "RTL8139_dev_add %s (handle = %d)",
+	    ddf_dev_get_name(dev), ddf_dev_get_handle(dev));
 
 	/* Init device structure for rtl8139 */
@@ -1340,6 +1338,6 @@
 	}
 	nic_set_ddf_fun(nic_data, fun);
-	fun->ops = &rtl8139_dev_ops;
-	fun->driver_data = nic_data;
+	ddf_fun_set_ops(fun, &rtl8139_dev_ops);
+	ddf_fun_data_implant(fun, nic_data);
 
 	rc = ddf_fun_bind(fun);
@@ -1355,5 +1353,5 @@
 
 	ddf_msg(LVL_NOTE, "The %s device has been successfully initialized.",
-	    dev->name);
+	    ddf_dev_get_name(dev));
 
 	return EOK;
Index: uspace/drv/test/test1/test1.c
===================================================================
--- uspace/drv/test/test1/test1.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/test/test1/test1.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -145,13 +145,16 @@
 	ddf_fun_t *fun_a;
 	test1_t *test1;
-	int rc;
-
+	const char *dev_name;
+	int rc;
+
+	dev_name = ddf_dev_get_name(dev);
 	ddf_msg(LVL_DEBUG, "dev_add(name=\"%s\", handle=%d)",
-	    dev->name, (int) dev->handle);
+	    dev_name, (int) ddf_dev_get_handle(dev));
 
 	test1 = ddf_dev_data_alloc(dev, sizeof(test1_t));
 	if (test1 == NULL) {
 		ddf_msg(LVL_ERROR, "Failed allocating soft state.\n");
-		return ENOMEM;
+		rc = ENOMEM;
+		goto error;
 	}
 
@@ -159,5 +162,6 @@
 	if (fun_a == NULL) {
 		ddf_msg(LVL_ERROR, "Failed creating function 'a'.");
-		return ENOMEM;
+		rc = ENOMEM;
+		goto error;
 	}
 
@@ -168,13 +172,13 @@
 		ddf_msg(LVL_ERROR, "Failed binding function 'a'.");
 		ddf_fun_destroy(fun_a);
-		return rc;
+		goto error;
 	}
 
 	ddf_fun_add_to_category(fun_a, "virtual");
 
-	if (str_cmp(dev->name, "null") == 0) {
-		fun_a->ops = &char_device_ops;
+	if (str_cmp(dev_name, "null") == 0) {
+		ddf_fun_set_ops(fun_a,  &char_device_ops);
 		ddf_fun_add_to_category(fun_a, "virt-null");
-	} else if (str_cmp(dev->name, "test1") == 0) {
+	} else if (str_cmp(dev_name, "test1") == 0) {
 		(void) register_fun_verbose(dev,
 		    "cloning myself ;-)", "clone",
@@ -183,5 +187,5 @@
 		    "cloning myself twice ;-)", "clone",
 		    "virtual&test1", 10, EEXISTS, NULL);
-	} else if (str_cmp(dev->name, "clone") == 0) {
+	} else if (str_cmp(dev_name, "clone") == 0) {
 		(void) register_fun_verbose(dev,
 		    "run by the same task", "child",
@@ -189,7 +193,8 @@
 	}
 
-	ddf_msg(LVL_DEBUG, "Device `%s' accepted.", dev->name);
-
-	return EOK;
+	ddf_msg(LVL_DEBUG, "Device `%s' accepted.", dev_name);
+	return EOK;
+error:
+	return rc;
 }
 
@@ -232,5 +237,5 @@
 static int test1_dev_remove(ddf_dev_t *dev)
 {
-	test1_t *test1 = (test1_t *)dev->driver_data;
+	test1_t *test1 = (test1_t *)ddf_dev_data_get(dev);
 	int rc;
 
@@ -260,5 +265,5 @@
 static int test1_dev_gone(ddf_dev_t *dev)
 {
-	test1_t *test1 = (test1_t *)dev->driver_data;
+	test1_t *test1 = (test1_t *)ddf_dev_data_get(dev);
 	int rc;
 
Index: uspace/drv/test/test2/test2.c
===================================================================
--- uspace/drv/test/test2/test2.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/test/test2/test2.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -196,7 +196,8 @@
 {
 	test2_t *test2;
+	const char *dev_name = ddf_dev_get_name(dev);
 
 	ddf_msg(LVL_DEBUG, "test2_dev_add(name=\"%s\", handle=%d)",
-	    dev->name, (int) dev->handle);
+	    dev_name, (int) ddf_dev_get_handle(dev));
 
 	test2 = ddf_dev_data_alloc(dev, sizeof(test2_t));
@@ -208,5 +209,5 @@
 	test2->dev = dev;
 
-	if (str_cmp(dev->name, "child") != 0) {
+	if (str_cmp(dev_name, "child") != 0) {
 		fid_t postpone = fibril_create(plug_unplug, test2);
 		if (postpone == 0) {
@@ -225,5 +226,5 @@
 static int test2_dev_remove(ddf_dev_t *dev)
 {
-	test2_t *test2 = (test2_t *)dev->driver_data;
+	test2_t *test2 = (test2_t *)ddf_dev_data_get(dev);
 	int rc;
 
@@ -259,5 +260,5 @@
 static int test2_dev_gone(ddf_dev_t *dev)
 {
-	test2_t *test2 = (test2_t *)dev->driver_data;
+	test2_t *test2 = (test2_t *)ddf_dev_data_get(dev);
 	int rc;
 
Index: uspace/drv/test/test3/test3.c
===================================================================
--- uspace/drv/test/test3/test3.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/drv/test/test3/test3.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -133,5 +133,5 @@
 
 	ddf_msg(LVL_DEBUG, "dev_add(name=\"%s\", handle=%d)",
-	    dev->name, (int) dev->handle);
+	    ddf_dev_get_name(dev), (int) ddf_dev_get_handle(dev));
 
 	test3 = ddf_dev_data_alloc(dev, sizeof(test3_t));
@@ -155,5 +155,5 @@
 static int test3_dev_remove(ddf_dev_t *dev)
 {
-	test3_t *test3 = (test3_t *)dev->driver_data;
+	test3_t *test3 = (test3_t *)ddf_dev_data_get(dev);
 	char *fun_name;
 	int rc;
Index: uspace/lib/drv/generic/driver.c
===================================================================
--- uspace/lib/drv/generic/driver.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/lib/drv/generic/driver.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -36,4 +36,6 @@
 /** @file
  */
+
+#define _DDF_DATA_IMPLANT
 
 #include <assert.h>
@@ -58,4 +60,5 @@
 #include "ddf/driver.h"
 #include "ddf/interrupt.h"
+#include "private/driver.h"
 
 /** Driver structure */
@@ -523,4 +526,6 @@
 static void delete_device(ddf_dev_t *dev)
 {
+	if (dev->parent_sess)
+		async_hangup(dev->parent_sess);
 	if (dev->driver_data != NULL)
 		free(dev->driver_data);
@@ -597,4 +602,96 @@
 }
 
+/** Implant foreign driver-specific device data.
+ *
+ * XXX This is used to transition USB to new interface. Do not use
+ * in new code. Use of this function must be removed.
+ */
+void ddf_fun_data_implant(ddf_fun_t *fun, void *data)
+{
+	assert(fun->driver_data == NULL);
+	fun->driver_data = data;
+}
+
+/** Return driver-specific device data. */
+void *ddf_dev_data_get(ddf_dev_t *dev)
+{
+	return dev->driver_data;
+}
+
+/** Get device handle. */
+devman_handle_t ddf_dev_get_handle(ddf_dev_t *dev)
+{
+	return dev->handle;
+}
+
+/** Return device name.
+ *
+ * @param dev	Device
+ * @return	Device name. Valid as long as @a dev is valid.
+ */
+const char *ddf_dev_get_name(ddf_dev_t *dev)
+{
+	return dev->name;
+}
+
+/** Create session with the parent function.
+ *
+ * The session will be automatically closed when @a dev is destroyed.
+ *
+ * @param dev	Device
+ * @param mgmt	Exchange management style
+ * @return	New session or NULL if session could not be created
+ */
+async_sess_t *ddf_dev_parent_sess_create(ddf_dev_t *dev, exch_mgmt_t mgmt)
+{
+	assert(dev->parent_sess == NULL);
+	dev->parent_sess = devman_parent_device_connect(mgmt, dev->handle,
+	    IPC_FLAG_BLOCKING);
+
+	return dev->parent_sess;
+}
+
+/** Return existing session with the parent function.
+ *
+ * @param dev	Device
+ * @return	Existing session or NULL if there is no session
+ */
+async_sess_t *ddf_dev_parent_sess_get(ddf_dev_t *dev)
+{
+	return dev->parent_sess;
+}
+
+/** Set function name (if it was not specified when node was created.)
+ *
+ * @param dev	Device whose name has not been set yet
+ * @param name	Name, will be copied
+ * @return	EOK on success, ENOMEM if out of memory
+ */
+int ddf_fun_set_name(ddf_fun_t *dev, const char *name)
+{
+	assert(dev->name == NULL);
+
+	dev->name = str_dup(name);
+	if (dev->name == NULL)
+		return ENOENT;
+
+	return EOK;
+}
+
+/** Get device to which function belongs. */
+ddf_dev_t *ddf_fun_get_dev(ddf_fun_t *fun)
+{
+	return fun->dev;
+}
+
+/** Get function handle.
+ *
+ * XXX USB uses this, but its use should be eliminated.
+ */
+devman_handle_t ddf_fun_get_handle(ddf_fun_t *fun)
+{
+	return fun->handle;
+}
+
 /** Create a DDF function node.
  *
@@ -608,5 +705,7 @@
  * This function should only fail if there is not enough free memory.
  * Specifically, this function succeeds even if @a dev already has
- * a (bound) function with the same name.
+ * a (bound) function with the same name. @a name can be NULL in which
+ * case the caller will set the name later using ddf_fun_set_name().
+ * He must do this before binding the function.
  *
  * Type: A function of type fun_inner indicates that DDF should attempt
@@ -616,5 +715,5 @@
  * @param dev		Device to which we are adding function
  * @param ftype		Type of function (fun_inner or fun_exposed)
- * @param name		Name of function
+ * @param name		Name of function or NULL
  *
  * @return		New function or @c NULL if memory is not available
@@ -633,8 +732,10 @@
 	fun->ftype = ftype;
 	
-	fun->name = str_dup(name);
-	if (fun->name == NULL) {
-		delete_function(fun);
-		return NULL;
+	if (name != NULL) {
+		fun->name = str_dup(name);
+		if (fun->name == NULL) {
+			delete_function(fun);
+			return NULL;
+		}
 	}
 	
@@ -654,4 +755,20 @@
 	fun->driver_data = data;
 	return data;
+}
+
+/** Return driver-specific function data. */
+void *ddf_fun_data_get(ddf_fun_t *fun)
+{
+	return fun->driver_data;
+}
+
+/** Return function name.
+ *
+ * @param fun	Function
+ * @return	Function name. Valid as long as @a fun is valid.
+ */
+const char *ddf_fun_get_name(ddf_fun_t *fun)
+{
+	return fun->name;
 }
 
@@ -805,4 +922,21 @@
 	add_match_id(&fun->match_ids, match_id);
 	return EOK;
+}
+
+/** Set function ops. */
+void ddf_fun_set_ops(ddf_fun_t *fun, ddf_dev_ops_t *dev_ops)
+{
+	assert(fun->conn_handler == NULL);
+	fun->ops = dev_ops;
+}
+
+/** Set user-defined connection handler.
+ *
+ * This allows handling connections the non-devman way.
+ */
+void ddf_fun_set_conn_handler(ddf_fun_t *fun, async_client_conn_t conn)
+{
+	assert(fun->ops == NULL);
+	fun->conn_handler = conn;
 }
 
Index: uspace/lib/drv/generic/interrupt.c
===================================================================
--- uspace/lib/drv/generic/interrupt.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/lib/drv/generic/interrupt.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -41,4 +41,5 @@
 
 #include "ddf/interrupt.h"
+#include "private/driver.h"
 
 static void driver_irq_handler(ipc_callid_t iid, ipc_call_t *icall);
Index: uspace/lib/drv/generic/private/driver.h
===================================================================
--- uspace/lib/drv/generic/private/driver.h	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
+++ uspace/lib/drv/generic/private/driver.h	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2012 Jiri Svoboda
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef DDF_PRIVATE_DRIVER_H_
+#define DDF_PRIVATE_DRIVER_H_
+
+#include <async.h>
+#include <ipc/devman.h>
+#include <ipc/dev_iface.h>
+#include "dev_iface.h"
+
+/** Device structure */
+struct ddf_dev {
+	/**
+	 * Globally unique device identifier (assigned to the device by the
+	 * device manager).
+	 */
+	devman_handle_t handle;
+	
+	/** Reference count */
+	atomic_t refcnt;
+	
+	/** Session with the parent device driver */
+	async_sess_t *parent_sess;
+	
+	/** Device name */
+	const char *name;
+	
+	/** Driver-specific data associated with this device */
+	void *driver_data;
+	
+	/** Link in the list of devices handled by the driver */
+	link_t link;
+};
+
+/** Function structure */
+struct ddf_fun {
+	/** True if bound to the device manager */
+	bool bound;
+	
+	/** Function indentifier (asigned by device manager) */
+	devman_handle_t handle;
+	
+	/** Reference count */
+	atomic_t refcnt;
+	
+	/** Device which this function belogs to */
+	struct ddf_dev *dev;
+	
+	/** Function type */
+	fun_type_t ftype;
+	
+	/** Function name */
+	const char *name;
+	
+	/** List of device ids for driver matching */
+	match_id_list_t match_ids;
+	
+	/** Driver-specific data associated with this function */
+	void *driver_data;
+	
+	/** Implementation of operations provided by this function */
+	ddf_dev_ops_t *ops;
+	
+	/** Connection handler or @c NULL to use the DDF default handler. */
+	async_client_conn_t conn_handler;
+	
+	/** Link in the list of functions handled by the driver */
+	link_t link;
+};
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/generic/remote_graph_dev.c
===================================================================
--- uspace/lib/drv/generic/remote_graph_dev.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/lib/drv/generic/remote_graph_dev.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -56,10 +56,10 @@
 	graph_dev_ops_t *graph_dev_ops = (graph_dev_ops_t *) ops;
 
-	if (!graph_dev_ops->connect || !fun->driver_data) {
+	if (!graph_dev_ops->connect || !ddf_fun_data_get(fun)) {
 		async_answer_0(callid, ENOTSUP);
 		return;
 	}
 
-	(*graph_dev_ops->connect)(fun->driver_data, callid, call, NULL);
+	(*graph_dev_ops->connect)(ddf_fun_data_get(fun), callid, call, NULL);
 }
 
Index: uspace/lib/drv/include/ddf/driver.h
===================================================================
--- uspace/lib/drv/include/ddf/driver.h	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/lib/drv/include/ddf/driver.h	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -42,10 +42,11 @@
 #include "../dev_iface.h"
 
-typedef struct ddf_dev ddf_dev_t;
-typedef struct ddf_fun ddf_fun_t;
 
 /*
  * Device
  */
+
+typedef struct ddf_dev ddf_dev_t;
+typedef struct ddf_fun ddf_fun_t;
 
 /** Devices operations */
@@ -75,65 +76,8 @@
 
 /** Device structure */
-struct ddf_dev {
-	/**
-	 * Globally unique device identifier (assigned to the device by the
-	 * device manager).
-	 */
-	devman_handle_t handle;
-	
-	/** Reference count */
-	atomic_t refcnt;
-	
-	/**
-	 * Session to the parent device driver (if it is different from this
-	 * driver)
-	 */
-	async_sess_t *parent_sess;
-	
-	/** Device name */
-	const char *name;
-	
-	/** Driver-specific data associated with this device */
-	void *driver_data;
-	
-	/** Link in the list of devices handled by the driver */
-	link_t link;
-};
+struct ddf_dev;
 
 /** Function structure */
-struct ddf_fun {
-	/** True if bound to the device manager */
-	bool bound;
-	
-	/** Function indentifier (asigned by device manager) */
-	devman_handle_t handle;
-	
-	/** Reference count */
-	atomic_t refcnt;
-	
-	/** Device which this function belogs to */
-	ddf_dev_t *dev;
-	
-	/** Function type */
-	fun_type_t ftype;
-	
-	/** Function name */
-	const char *name;
-	
-	/** List of device ids for driver matching */
-	match_id_list_t match_ids;
-	
-	/** Driver-specific data associated with this function */
-	void *driver_data;
-	
-	/** Implementation of operations provided by this function */
-	ddf_dev_ops_t *ops;
-	
-	/** Connection handler or @c NULL to use the DDF default handler. */
-	async_client_conn_t conn_handler;
-	
-	/** Link in the list of functions handled by the driver */
-	link_t link;
-};
+struct ddf_fun;
 
 /*
@@ -167,10 +111,25 @@
 } driver_t;
 
+/** XXX Only to transition USB */
+#ifdef _DDF_DATA_IMPLANT
+extern void ddf_fun_data_implant(ddf_fun_t *, void *);
+#endif
+
 extern int ddf_driver_main(driver_t *);
 
 extern void *ddf_dev_data_alloc(ddf_dev_t *, size_t);
+extern void *ddf_dev_data_get(ddf_dev_t *);
+extern devman_handle_t ddf_dev_get_handle(ddf_dev_t *);
+extern const char *ddf_dev_get_name(ddf_dev_t *);
+extern async_sess_t *ddf_dev_parent_sess_create(ddf_dev_t *, exch_mgmt_t);
+extern async_sess_t *ddf_dev_parent_sess_get(ddf_dev_t *);
 extern ddf_fun_t *ddf_fun_create(ddf_dev_t *, fun_type_t, const char *);
+extern devman_handle_t ddf_fun_get_handle(ddf_fun_t *);
 extern void ddf_fun_destroy(ddf_fun_t *);
 extern void *ddf_fun_data_alloc(ddf_fun_t *, size_t);
+extern void *ddf_fun_data_get(ddf_fun_t *);
+extern const char *ddf_fun_get_name(ddf_fun_t *);
+extern int ddf_fun_set_name(ddf_fun_t *, const char *);
+extern ddf_dev_t *ddf_fun_get_dev(ddf_fun_t *);
 extern int ddf_fun_bind(ddf_fun_t *);
 extern int ddf_fun_unbind(ddf_fun_t *);
@@ -178,5 +137,6 @@
 extern int ddf_fun_offline(ddf_fun_t *);
 extern int ddf_fun_add_match_id(ddf_fun_t *, const char *, int);
-
+extern void ddf_fun_set_ops(ddf_fun_t *, ddf_dev_ops_t *);
+extern void ddf_fun_set_conn_handler(ddf_fun_t *, async_client_conn_t);
 extern int ddf_fun_add_to_category(ddf_fun_t *, const char *);
 
Index: uspace/lib/nic/src/nic_driver.c
===================================================================
--- uspace/lib/nic/src/nic_driver.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/lib/nic/src/nic_driver.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -47,5 +47,4 @@
 #include <sysinfo.h>
 #include <as.h>
-#include <devman.h>
 #include <ddf/interrupt.h>
 #include <ops/nic.h>
@@ -250,12 +249,12 @@
 {
 	ddf_dev_t *dev = nic_data->dev;
+	async_sess_t *parent_sess;
 	
 	/* Connect to the parent's driver. */
-	dev->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
-		dev->handle, IPC_FLAG_BLOCKING);
-	if (dev->parent_sess == NULL)
+	parent_sess = ddf_dev_parent_sess_create(dev, EXCHANGE_SERIALIZE);
+	if (parent_sess == NULL)
 		return EPARTY;
 	
-	return hw_res_get_list_parsed(nic_data->dev->parent_sess, resources, 0);
+	return hw_res_get_list_parsed(parent_sess, resources, 0);
 }
 
@@ -650,19 +649,16 @@
  *
  */
-static nic_t *nic_create(void)
-{
-	nic_t *nic_data = malloc(sizeof(nic_t));
+static nic_t *nic_create(ddf_dev_t *dev)
+{
+	nic_t *nic_data = ddf_dev_data_alloc(dev, sizeof(nic_t));
 	if (nic_data == NULL)
 		return NULL;
 	
 	/* Force zero to all uninitialized fields (e.g. added in future) */
-	bzero(nic_data, sizeof(nic_t));
 	if (nic_rxc_init(&nic_data->rx_control) != EOK) {
-		free(nic_data);
 		return NULL;
 	}
 	
 	if (nic_wol_virtues_init(&nic_data->wol_virtues) != EOK) {
-		free(nic_data);
 		return NULL;
 	}
@@ -705,13 +701,9 @@
 nic_t *nic_create_and_bind(ddf_dev_t *device)
 {
-	assert(device);
-	assert(!device->driver_data);
-	
-	nic_t *nic_data = nic_create();
+	nic_t *nic_data = nic_create(device);
 	if (!nic_data)
 		return NULL;
 	
 	nic_data->dev = device;
-	device->driver_data = nic_data;
 	
 	return nic_data;
@@ -724,11 +716,7 @@
  * @param data
  */
-static void nic_destroy(nic_t *nic_data) {
-	if (nic_data->client_session != NULL) {
-		async_hangup(nic_data->client_session);
-	}
-
+static void nic_destroy(nic_t *nic_data)
+{
 	free(nic_data->specific);
-	free(nic_data);
 }
 
@@ -740,12 +728,7 @@
  * @param device The NIC device structure
  */
-void nic_unbind_and_destroy(ddf_dev_t *device){
-	if (!device)
-		return;
-	if (!device->driver_data)
-		return;
-
-	nic_destroy((nic_t *) device->driver_data);
-	device->driver_data = NULL;
+void nic_unbind_and_destroy(ddf_dev_t *device)
+{
+	nic_destroy(nic_get_from_ddf_dev(device));
 	return;
 }
@@ -983,6 +966,6 @@
 nic_t *nic_get_from_ddf_dev(ddf_dev_t *dev)
 {
-	return (nic_t *) dev->driver_data;
-};
+	return (nic_t *) ddf_dev_data_get(dev);
+}
 
 /** 
@@ -992,6 +975,6 @@
 nic_t *nic_get_from_ddf_fun(ddf_fun_t *fun)
 {
-	return (nic_t *) fun->driver_data;
-};
+	return (nic_t *) ddf_fun_data_get(fun);
+}
 
 /**
Index: uspace/lib/nic/src/nic_impl.c
===================================================================
--- uspace/lib/nic/src/nic_impl.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/lib/nic/src/nic_impl.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -54,5 +54,5 @@
 int nic_get_state_impl(ddf_fun_t *fun, nic_device_state_t *state)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->main_lock);
 	*state = nic_data->state;
@@ -78,5 +78,5 @@
 	}
 
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 
 	fibril_rwlock_write_lock(&nic_data->main_lock);
@@ -170,5 +170,5 @@
 int nic_send_frame_impl(ddf_fun_t *fun, void *data, size_t size)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 
 	fibril_rwlock_read_lock(&nic_data->main_lock);
@@ -192,5 +192,5 @@
 int nic_callback_create_impl(ddf_fun_t *fun)
 {
-	nic_t *nic = (nic_t *) fun->driver_data;
+	nic_t *nic = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_write_lock(&nic->main_lock);
 	
@@ -218,5 +218,5 @@
 {
 	assert(address);
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->main_lock);
 	memcpy(address, &nic_data->mac, sizeof (nic_address_t));
@@ -236,5 +236,5 @@
 int nic_get_stats_impl(ddf_fun_t *fun, nic_device_stats_t *stats)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	assert (stats != NULL);
 	fibril_rwlock_read_lock(&nic_data->stats_lock);
@@ -259,5 +259,5 @@
 	size_t max_count, nic_address_t *addr_list, size_t *addr_count)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->rxc_lock);
 	nic_rxc_unicast_get_mode(&nic_data->rx_control, mode, max_count,
@@ -291,5 +291,5 @@
 	}
 
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_write_lock(&nic_data->rxc_lock);
 	int rc = ENOTSUP;
@@ -326,5 +326,5 @@
 	size_t max_count, nic_address_t *addr_list, size_t *addr_count)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->rxc_lock);
 	nic_rxc_multicast_get_mode(&nic_data->rx_control, mode, max_count,
@@ -358,5 +358,5 @@
 	}
 
-	nic_t *nic_data = (nic_t *) fun->dev->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_write_lock(&nic_data->rxc_lock);
 	int rc = ENOTSUP;
@@ -382,5 +382,5 @@
 int nic_broadcast_get_mode_impl(ddf_fun_t *fun, nic_broadcast_mode_t *mode)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->rxc_lock);
 	nic_rxc_broadcast_get_mode(&nic_data->rx_control, mode);
@@ -402,5 +402,5 @@
 int nic_broadcast_set_mode_impl(ddf_fun_t *fun, nic_broadcast_mode_t mode)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_write_lock(&nic_data->rxc_lock);
 	int rc = ENOTSUP;
@@ -429,5 +429,5 @@
 	size_t max_count, nic_address_t *addr_list, size_t *addr_count)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->rxc_lock);
 	nic_rxc_blocked_sources_get(&nic_data->rx_control,
@@ -452,5 +452,5 @@
 	const nic_address_t *addr_list, size_t addr_count)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_write_lock(&nic_data->rxc_lock);
 	if (nic_data->on_blocked_sources_change) {
@@ -474,5 +474,5 @@
 int nic_vlan_get_mask_impl(ddf_fun_t *fun, nic_vlan_mask_t *mask)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->rxc_lock);
 	int rc = nic_rxc_vlan_get_mask(&nic_data->rx_control, mask);
@@ -492,5 +492,5 @@
 int nic_vlan_set_mask_impl(ddf_fun_t *fun, const nic_vlan_mask_t *mask)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_write_lock(&nic_data->rxc_lock);
 	int rc = nic_rxc_vlan_set_mask(&nic_data->rx_control, mask);
@@ -520,5 +520,5 @@
 	const void *data, size_t length, nic_wv_id_t *new_id)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	if (nic_data->on_wol_virtue_add == NULL
 		|| nic_data->on_wol_virtue_remove == NULL) {
@@ -594,5 +594,5 @@
 int nic_wol_virtue_remove_impl(ddf_fun_t *fun, nic_wv_id_t id)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	if (nic_data->on_wol_virtue_add == NULL
 		|| nic_data->on_wol_virtue_remove == NULL) {
@@ -631,5 +631,5 @@
 	nic_wv_type_t *type, size_t max_length, void *data, size_t *length)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->wv_lock);
 	const nic_wol_virtue_t *virtue =
@@ -669,5 +669,5 @@
 	size_t max_count, nic_wv_id_t *id_list, size_t *id_count)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->wv_lock);
 	int rc = nic_wol_virtues_list(&nic_data->wol_virtues, type,
@@ -689,5 +689,5 @@
 int nic_wol_virtue_get_caps_impl(ddf_fun_t *fun, nic_wv_type_t type, int *count)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->wv_lock);
 	*count = nic_data->wol_virtues.caps_max[type]
@@ -712,5 +712,5 @@
 	nic_poll_mode_t *mode, struct timeval *period)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->main_lock);
 	*mode = nic_data->poll_mode;
@@ -735,5 +735,5 @@
 	nic_poll_mode_t mode, const struct timeval *period)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	/* If the driver does not implement the poll mode change handler it cannot
 	 * switch off interrupts and this is not supported. */
@@ -783,5 +783,5 @@
  */
 int nic_poll_now_impl(ddf_fun_t *fun) {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->main_lock);
 	if (nic_data->poll_mode != NIC_POLL_ON_DEMAND) {
Index: uspace/lib/usb/include/usb/hc.h
===================================================================
--- uspace/lib/usb/include/usb/hc.h	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/lib/usb/include/usb/hc.h	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -77,6 +77,5 @@
 }
 
-int usb_hc_connection_initialize_from_device(usb_hc_connection_t *,
-    const ddf_dev_t *);
+int usb_hc_connection_initialize_from_device(usb_hc_connection_t *, ddf_dev_t *);
 
 void usb_hc_connection_deinitialize(usb_hc_connection_t *);
Index: uspace/lib/usb/src/ddfiface.c
===================================================================
--- uspace/lib/usb/src/ddfiface.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/lib/usb/src/ddfiface.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -68,5 +68,5 @@
 {
 	assert(fun);
-	return usb_get_hc_by_handle(fun->handle, handle);
+	return usb_get_hc_by_handle(ddf_fun_get_handle(fun), handle);
 }
 
@@ -82,5 +82,5 @@
 
 	if (handle != NULL) {
-		*handle = fun->handle;
+		*handle = ddf_fun_get_handle(fun);
 	}
 
@@ -99,5 +99,5 @@
 {
 	assert(fun);
-	return usb_get_address_by_handle(fun->handle, address);
+	return usb_get_address_by_handle(ddf_fun_get_handle(fun), address);
 }
 
@@ -116,7 +116,5 @@
     usb_address_t *address)
 {
-	assert(fun);
-	assert(fun->driver_data);
-	const usb_hub_attached_device_t *device = fun->driver_data;
+	const usb_hub_attached_device_t *device = ddf_fun_data_get(fun);
 	assert(device->fun == fun);
 	if (address)
Index: uspace/lib/usb/src/hc.c
===================================================================
--- uspace/lib/usb/src/hc.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/lib/usb/src/hc.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -115,14 +115,11 @@
  */
 int usb_hc_connection_initialize_from_device(usb_hc_connection_t *connection,
-    const ddf_dev_t *device)
-{
-	assert(connection);
-
-	if (device == NULL) {
+    ddf_dev_t *device)
+{
+	if (device == NULL)
 		return EBADMEM;
-	}
 
 	devman_handle_t hc_handle;
-	const int rc = usb_get_hc_by_handle(device->handle, &hc_handle);
+	const int rc = usb_get_hc_by_handle(ddf_dev_get_handle(device), &hc_handle);
 	if (rc == EOK) {
 		usb_hc_connection_initialize(connection, hc_handle);
Index: uspace/lib/usbdev/src/devdrv.c
===================================================================
--- uspace/lib/usbdev/src/devdrv.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/lib/usbdev/src/devdrv.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -105,5 +105,5 @@
 	if (dev == NULL) {
 		usb_log_error("USB device `%s' structure allocation failed.\n",
-		    gen_dev->name);
+		    ddf_dev_get_name(gen_dev));
 		return ENOMEM;
 	}
@@ -114,5 +114,5 @@
 	if (rc != EOK) {
 		usb_log_error("USB device `%s' init failed (%s): %s.\n",
-		    gen_dev->name, err_msg, str_error(rc));
+		    ddf_dev_get_name(gen_dev), err_msg, str_error(rc));
 		return rc;
 	}
@@ -139,5 +139,5 @@
 		return ENOTSUP;
 	/* Just tell the driver to stop whatever it is doing */
-	usb_device_t *usb_dev = gen_dev->driver_data;
+	usb_device_t *usb_dev = ddf_dev_data_get(gen_dev);
 	const int ret = driver->ops->device_rem(usb_dev);
 	if (ret != EOK)
@@ -160,5 +160,5 @@
 	if (driver->ops->device_gone == NULL)
 		return ENOTSUP;
-	usb_device_t *usb_dev = gen_dev->driver_data;
+	usb_device_t *usb_dev = ddf_dev_data_get(gen_dev);
 	const int ret = driver->ops->device_gone(usb_dev);
 	if (ret == EOK)
@@ -415,5 +415,5 @@
 	usb_address_t address;
 
-	int rc = usb_get_info_by_handle(ddf_dev->handle,
+	int rc = usb_get_info_by_handle(ddf_dev_get_handle(ddf_dev),
 	    &hc_handle, &address, &usb_dev->interface_no);
 	if (rc != EOK) {
Index: uspace/lib/usbdev/src/devpoll.c
===================================================================
--- uspace/lib/usbdev/src/devpoll.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/lib/usbdev/src/devpoll.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -80,5 +80,5 @@
 		usb_log_debug("Poll%p: started polling of `%s' - " \
 		    "interface %d (%s,%d,%d), %zuB/%zu.\n",
-		    data, data->dev->ddf_dev->name,
+		    data, ddf_dev_get_name(data->dev->ddf_dev),
 		    (int) mapping->interface->interface_number,
 		    usb_str_class(mapping->interface->interface_class),
@@ -159,8 +159,10 @@
 		if (failed) {
 			usb_log_error("Polling of device `%s' terminated: "
-			    "recurring failures.\n", data->dev->ddf_dev->name);
+			    "recurring failures.\n", ddf_dev_get_name(
+			    data->dev->ddf_dev));
 		} else {
 			usb_log_debug("Polling of device `%s' terminated: "
-			    "driver request.\n", data->dev->ddf_dev->name);
+			    "driver request.\n", ddf_dev_get_name(
+			    data->dev->ddf_dev));
 		}
 	}
Index: uspace/lib/usbdev/src/hub.c
===================================================================
--- uspace/lib/usbdev/src/hub.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/lib/usbdev/src/hub.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -63,5 +63,5 @@
 		return EBADMEM;
 	return usb_hc_bind_address(connection,
-	    attached_device->address, attached_device->fun->handle);
+	    attached_device->address, ddf_fun_get_handle(attached_device->fun));
 }
 
@@ -287,7 +287,4 @@
 	rc = usb_hub_register_device(hc_conn, &new_device);
 	if (rc != EOK) {
-		/* We know nothing about that data. */
-		if (new_dev_data)
-			child_fun->driver_data = NULL;
 		/* The child function is already created. */
 		ddf_fun_destroy(child_fun);
Index: uspace/lib/usbdev/src/recognise.c
===================================================================
--- uspace/lib/usbdev/src/recognise.c	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/lib/usbdev/src/recognise.c	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -33,4 +33,7 @@
  * Functions for recognition of attached devices.
  */
+
+/** XXX Fix this */
+#define _DDF_DATA_IMPLANT
 
 #include <sys/types.h>
@@ -352,9 +355,10 @@
 	
 	if (dev_ops != NULL)
-		child->ops = dev_ops;
+		ddf_fun_set_ops(child, dev_ops);
 	else
-		child->ops = &child_ops;
-	
-	child->driver_data = dev_data;
+		ddf_fun_set_ops(child, &child_ops);
+	
+	ddf_fun_data_implant(child, dev_data);
+	
 	/*
 	 * Store the attached device in fun
@@ -373,7 +377,20 @@
 	}
 	
-	rc = usb_device_create_match_ids(ctrl_pipe, &child->match_ids);
+	match_id_list_t match_ids;
+	init_match_ids(&match_ids);
+	rc = usb_device_create_match_ids(ctrl_pipe, &match_ids);
 	if (rc != EOK)
 		goto failure;
+	
+	list_foreach(match_ids.ids, id_link) {
+		match_id_t *match_id = list_get_instance(id_link, match_id_t, link);
+		rc = ddf_fun_add_match_id(child, match_id->id, match_id->score);
+		if (rc != EOK) {
+			clean_match_ids(&match_ids);
+			goto failure;
+		}
+	}
+	
+	clean_match_ids(&match_ids);
 	
 	rc = ddf_fun_bind(child);
@@ -386,8 +403,4 @@
 failure:
 	if (child != NULL) {
-		/* We know nothing about the data if it came from outside. */
-		if (dev_data)
-			child->driver_data = NULL;
-		
 		/* This takes care of match_id deallocation as well. */
 		ddf_fun_destroy(child);
Index: uspace/lib/usbhost/include/usb/host/hcd.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/hcd.h	(revision 831257700e85d4f86746c23bc9174ea3e33e4bb6)
+++ uspace/lib/usbhost/include/usb/host/hcd.h	(revision 1d5a5405546f3f0a0cab965cb3a4339c902e5e26)
@@ -98,8 +98,7 @@
  * @return pointer cast to hcd_t*.
  */
-static inline hcd_t * fun_to_hcd(const ddf_fun_t *fun)
+static inline hcd_t *fun_to_hcd(ddf_fun_t *fun)
 {
-	assert(fun);
-	return fun->driver_data;
+	return ddf_fun_data_get(fun);
 }
 
