Index: uspace/drv/bus/isa/isa.c
===================================================================
--- uspace/drv/bus/isa/isa.c	(revision 184f2f8afd2b5e58162ccd6350f9778305850043)
+++ uspace/drv/bus/isa/isa.c	(revision b25970fdaa53055fe44afdf414204a77d77efbf1)
@@ -1,5 +1,5 @@
 /*
+ * Copyright (c) 2018 Jiri Svoboda
  * Copyright (c) 2010 Lenka Trochtova
- * Copyright (c) 2011 Jiri Svoboda
  * Copyright (c) 2011 Jan Vesely
  * All rights reserved.
@@ -697,26 +697,7 @@
 }
 
-static errno_t isa_dev_add(ddf_dev_t *dev)
-{
-	async_sess_t *sess;
+static errno_t isa_read_pci_cfg(isa_bus_t *isa, async_sess_t *sess)
+{
 	errno_t rc;
-
-	ddf_msg(LVL_DEBUG, "isa_dev_add, device handle = %d",
-	    (int) ddf_dev_get_handle(dev));
-
-	isa_bus_t *isa = ddf_dev_data_alloc(dev, sizeof(isa_bus_t));
-	if (isa == NULL)
-		return ENOMEM;
-
-	fibril_mutex_initialize(&isa->mutex);
-	isa->dev = dev;
-	list_initialize(&isa->functions);
-
-	sess = ddf_dev_parent_sess_get(dev);
-	if (sess == NULL) {
-		ddf_msg(LVL_ERROR, "isa_dev_add failed to connect to the "
-		    "parent driver.");
-		return ENOENT;
-	}
 
 	rc = pci_config_space_read_16(sess, PCI_VENDOR_ID, &isa->pci_vendor_id);
@@ -733,4 +714,39 @@
 		return rc;
 
+	return EOK;
+}
+
+static errno_t isa_dev_add(ddf_dev_t *dev)
+{
+	async_sess_t *sess;
+	errno_t rc;
+
+	ddf_msg(LVL_DEBUG, "isa_dev_add, device handle = %d",
+	    (int) ddf_dev_get_handle(dev));
+
+	isa_bus_t *isa = ddf_dev_data_alloc(dev, sizeof(isa_bus_t));
+	if (isa == NULL)
+		return ENOMEM;
+
+	fibril_mutex_initialize(&isa->mutex);
+	isa->dev = dev;
+	list_initialize(&isa->functions);
+
+	sess = ddf_dev_parent_sess_get(dev);
+	if (sess == NULL) {
+		ddf_msg(LVL_ERROR, "isa_dev_add failed to connect to the "
+		    "parent driver.");
+		return ENOENT;
+	}
+
+	rc = isa_read_pci_cfg(isa, sess);
+	if (rc != EOK) {
+		ddf_msg(LVL_NOTE, "Cannot read PCI config. Assuming ISA classic.");
+		isa->pci_vendor_id = 0;
+		isa->pci_device_id = 0;
+		isa->pci_class = BASE_CLASS_BRIDGE;
+		isa->pci_subclass = SUB_CLASS_BRIDGE_ISA;
+	}
+
 	rc = pio_window_get(sess, &isa->pio_win);
 	if (rc != EOK) {
Index: uspace/drv/bus/isa/isa.ma
===================================================================
--- uspace/drv/bus/isa/isa.ma	(revision 184f2f8afd2b5e58162ccd6350f9778305850043)
+++ uspace/drv/bus/isa/isa.ma	(revision b25970fdaa53055fe44afdf414204a77d77efbf1)
@@ -1,2 +1,5 @@
+# Classic ISA
+10 isa
+
 # ISA bridge
 10 pci/class=06&subclass=01
Index: uspace/drv/platform/pc/pc.c
===================================================================
--- uspace/drv/platform/pc/pc.c	(revision 184f2f8afd2b5e58162ccd6350f9778305850043)
+++ uspace/drv/platform/pc/pc.c	(revision b25970fdaa53055fe44afdf414204a77d77efbf1)
@@ -1,3 +1,4 @@
 /*
+ * Copyright (c) 2018 Jiri Svoboda
  * Copyright (c) 2010 Lenka Trochtova
  * All rights reserved.
@@ -93,5 +94,5 @@
 };
 
-static pc_fun_t pci_data = {
+static pc_fun_t sys_data = {
 	.hw_resources = {
 		sizeof(pci_conf_regs) / sizeof(pci_conf_regs[0]),
@@ -151,25 +152,29 @@
 static ddf_dev_ops_t pc_fun_ops;
 
-static bool
-pc_add_fun(ddf_dev_t *dev, const char *name, const char *str_match_id,
-    pc_fun_t *fun_proto)
-{
-	ddf_msg(LVL_DEBUG, "Adding new function '%s'.", name);
-
+static errno_t pc_add_sysbus(ddf_dev_t *dev)
+{
 	ddf_fun_t *fnode = NULL;
 	errno_t rc;
 
+	ddf_msg(LVL_DEBUG, "Adding system bus.");
+
 	/* Create new device. */
-	fnode = ddf_fun_create(dev, fun_inner, name);
-	if (fnode == NULL)
-		goto failure;
+	fnode = ddf_fun_create(dev, fun_inner, "sys");
+	if (fnode == NULL) {
+		rc = ENOMEM;
+		goto error;
+	}
 
 	pc_fun_t *fun = ddf_fun_data_alloc(fnode, sizeof(pc_fun_t));
-	*fun = *fun_proto;
-
-	/* Add match ID */
-	rc = ddf_fun_add_match_id(fnode, str_match_id, 100);
+	*fun = sys_data;
+
+	/* Add match IDs */
+	rc = ddf_fun_add_match_id(fnode, "intel_pci", 100);
 	if (rc != EOK)
-		goto failure;
+		goto error;
+
+	rc = ddf_fun_add_match_id(fnode, "isa", 10);
+	if (rc != EOK)
+		goto error;
 
 	/* Set provided operations to the device. */
@@ -177,23 +182,29 @@
 
 	/* Register function. */
-	if (ddf_fun_bind(fnode) != EOK) {
-		ddf_msg(LVL_ERROR, "Failed binding function %s.", name);
-		goto failure;
-	}
-
-	return true;
-
-failure:
+	rc = ddf_fun_bind(fnode);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding system bus function.");
+		goto error;
+	}
+
+	return EOK;
+
+error:
 	if (fnode != NULL)
 		ddf_fun_destroy(fnode);
 
-	ddf_msg(LVL_ERROR, "Failed adding function '%s'.", name);
-
-	return false;
-}
-
-static bool pc_add_functions(ddf_dev_t *dev)
-{
-	return pc_add_fun(dev, "pci0", "intel_pci", &pci_data);
+	ddf_msg(LVL_ERROR, "Failed adding system bus.");
+	return rc;
+}
+
+static errno_t pc_add_functions(ddf_dev_t *dev)
+{
+	errno_t rc;
+
+	rc = pc_add_sysbus(dev);
+	if (rc != EOK)
+		return rc;
+
+	return EOK;
 }
 
@@ -206,10 +217,14 @@
 static errno_t pc_dev_add(ddf_dev_t *dev)
 {
+	errno_t rc;
+
 	ddf_msg(LVL_DEBUG, "pc_dev_add, device handle = %d",
 	    (int)ddf_dev_get_handle(dev));
 
 	/* Register functions. */
-	if (!pc_add_functions(dev)) {
+	rc = pc_add_functions(dev);
+	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed to add functions for PC platform.");
+		return rc;
 	}
 
Index: uspace/srv/devman/driver.c
===================================================================
--- uspace/srv/devman/driver.c	(revision 184f2f8afd2b5e58162ccd6350f9778305850043)
+++ uspace/srv/devman/driver.c	(revision b25970fdaa53055fe44afdf414204a77d77efbf1)
@@ -1,3 +1,4 @@
 /*
+ * Copyright (c) 2018 Jiri Svoboda
  * Copyright (c) 2010 Lenka Trochtova
  * All rights reserved.
@@ -43,5 +44,9 @@
 #include "devman.h"
 #include "driver.h"
+#include "fun.h"
 #include "match.h"
+#include "main.h"
+
+static errno_t driver_reassign_fibril(void *);
 
 /**
@@ -194,6 +199,5 @@
 }
 
-/** Lookup the best matching driver for the specified device in the list of
- * drivers.
+/** Lookup the next best matching driver for a device.
  *
  * A match between a device and a driver is found if one of the driver's match
@@ -203,4 +207,9 @@
  * of the match between the device and the driver.
  *
+ * If a driver is already assigned to the device (node->drv != NULL),
+ * we look for the next best driver. That is either the next driver with the
+ * same score in the list of drivers, or a driver with the next best score
+ * (greater than zero).
+ *
  * @param drivers_list	The list of drivers, where we look for the driver
  *			suitable for handling the device.
@@ -213,10 +222,41 @@
 	driver_t *best_drv = NULL;
 	int best_score = 0, score = 0;
+	int cur_score;
+	link_t *link;
+	driver_t *drv;
 
 	fibril_mutex_lock(&drivers_list->drivers_mutex);
 
+	if (node->drv != NULL) {
+		cur_score = get_match_score(node->drv, node);
+
+		link = list_next(&drv->drivers, &drivers_list->drivers);
+
+		/*
+		 * Find next driver with score equal to the current.
+		 */
+		while (link != NULL) {
+			drv = list_get_instance(link, driver_t, drivers);
+			score = get_match_score(drv, node);
+			if (score == cur_score) {
+				/* Found it */
+				fibril_mutex_unlock(&drivers_list->drivers_mutex);
+				return drv;
+			}
+
+			link = list_next(link, &drivers_list->drivers);
+		}
+
+		/* There is no driver with the same score */
+	} else {
+		cur_score = INT_MAX;
+	}
+
+	/*
+	 * Find driver with the next best score
+	 */
 	list_foreach(drivers_list->drivers, drivers, driver_t, drv) {
 		score = get_match_score(drv, node);
-		if (score > best_score) {
+		if (score > best_score && score < cur_score) {
 			best_score = score;
 			best_drv = drv;
@@ -225,5 +265,4 @@
 
 	fibril_mutex_unlock(&drivers_list->drivers_mutex);
-
 	return best_drv;
 }
@@ -244,4 +283,6 @@
 
 	dev->drv = drv;
+	dev->passed_to_driver = false;
+	dev->state = DEVICE_NOT_INITIALIZED;
 	list_append(&dev->driver_devices, &drv->devices);
 
@@ -415,4 +456,17 @@
 
 		add_device(driver, dev, tree);
+
+		/* Device probe failed, need to try next best driver */
+		if (dev->state == DEVICE_NOT_PRESENT) {
+			fibril_mutex_lock(&driver->driver_mutex);
+			list_remove(&dev->driver_devices);
+			fibril_mutex_unlock(&driver->driver_mutex);
+			fid_t fid = fibril_create(driver_reassign_fibril, dev);
+			if (fid == 0) {
+				log_msg(LOG_DEFAULT, LVL_ERROR,
+				    "Error creating fibril to assign driver.");
+			}
+			fibril_add_ready(fid);
+		}
 
 		dev_del_ref(dev);
@@ -519,4 +573,6 @@
     dev_tree_t *tree)
 {
+	driver_t *drv;
+
 	assert(dev != NULL);
 	assert(drivers_list != NULL);
@@ -524,7 +580,8 @@
 
 	/*
-	 * Find the driver which is the most suitable for handling this device.
+	 * Find the next best driver for this device.
 	 */
-	driver_t *drv = find_best_match_driver(drivers_list, dev);
+again:
+	drv = find_best_match_driver(drivers_list, dev);
 	if (drv == NULL) {
 		log_msg(LOG_DEFAULT, LVL_ERROR, "No driver found for device `%s'.",
@@ -545,6 +602,11 @@
 
 	/* Notify the driver about the new device. */
-	if (is_running)
+	if (is_running) {
 		add_device(drv, dev, tree);
+
+		/* If the device probe failed, need to try next available driver */
+		if (dev->state == DEVICE_NOT_PRESENT)
+			goto again;
+	}
 
 	fibril_mutex_lock(&drv->driver_mutex);
@@ -781,4 +843,18 @@
 }
 
+/** Try to find next available driver in a separate fibril.
+ *
+ * @param arg Device node (dev_node_t)
+ */
+static errno_t driver_reassign_fibril(void *arg)
+{
+	dev_node_t *dev_node = (dev_node_t *) arg;
+	assign_driver(dev_node, &drivers_list, &device_tree);
+
+	/* Delete one reference we got from the caller. */
+	dev_del_ref(dev_node);
+	return EOK;
+}
+
 /** @}
  */
