Index: uspace/drv/block/isa-ide/isa-ide.c
===================================================================
--- uspace/drv/block/isa-ide/isa-ide.c	(revision 59c0f478c5ca79154f904083a83642e63b93af6e)
+++ uspace/drv/block/isa-ide/isa-ide.c	(revision 646849b3f81f70632a7c09814cd3044cd829bde3)
@@ -55,9 +55,9 @@
 #include "main.h"
 
-static errno_t isa_ide_init_io(isa_ide_ctrl_t *ctrl);
-static void isa_ide_fini_io(isa_ide_ctrl_t *ctrl);
-static errno_t isa_ide_init_irq(isa_ide_ctrl_t *ctrl);
-static void isa_ide_fini_irq(isa_ide_ctrl_t *ctrl);
-static void isa_ide_irq_handler(ipc_call_t *call, ddf_dev_t *dev);
+static errno_t isa_ide_init_io(isa_ide_channel_t *);
+static void isa_ide_fini_io(isa_ide_channel_t *);
+static errno_t isa_ide_init_irq(isa_ide_channel_t *);
+static void isa_ide_fini_irq(isa_ide_channel_t *);
+static void isa_ide_irq_handler(ipc_call_t *, ddf_dev_t *);
 
 static void isa_ide_write_data_16(void *, uint16_t *, size_t);
@@ -95,6 +95,7 @@
 };
 
-/** Initialize ISA IDE controller. */
-errno_t isa_ide_ctrl_init(isa_ide_ctrl_t *ctrl, isa_ide_hwres_t *res)
+/** Initialize ISA IDE channel. */
+errno_t isa_ide_channel_init(isa_ide_ctrl_t *ctrl, isa_ide_channel_t *chan,
+    unsigned chan_id, isa_ide_hwres_t *res)
 {
 	errno_t rc;
@@ -104,19 +105,27 @@
 	ddf_msg(LVL_DEBUG, "isa_ide_ctrl_init()");
 
-	fibril_mutex_initialize(&ctrl->lock);
-	ctrl->cmd_physical = res->cmd;
-	ctrl->ctl_physical = res->ctl;
-	ctrl->irq = res->irq;
-
-	ddf_msg(LVL_NOTE, "I/O address %p/%p", (void *) ctrl->cmd_physical,
-	    (void *) ctrl->ctl_physical);
+	chan->ctrl = ctrl;
+	chan->chan_id = chan_id;
+	fibril_mutex_initialize(&chan->lock);
+	if (chan_id == 0) {
+		chan->cmd_physical = res->cmd1;
+		chan->ctl_physical = res->ctl1;
+		chan->irq = res->irq1;
+	} else {
+		chan->cmd_physical = res->cmd2;
+		chan->ctl_physical = res->ctl2;
+		chan->irq = res->irq2;
+	}
+
+	ddf_msg(LVL_NOTE, "I/O address %p/%p", (void *) chan->cmd_physical,
+	    (void *) chan->ctl_physical);
 
 	ddf_msg(LVL_DEBUG, "Init I/O");
-	rc = isa_ide_init_io(ctrl);
+	rc = isa_ide_init_io(chan);
 	if (rc != EOK)
 		return rc;
 
 	ddf_msg(LVL_DEBUG, "Init IRQ");
-	rc = isa_ide_init_irq(ctrl);
+	rc = isa_ide_init_irq(chan);
 	if (rc != EOK) {
 		ddf_msg(LVL_NOTE, "init IRQ failed");
@@ -128,6 +137,6 @@
 	ddf_msg(LVL_DEBUG, "isa_ide_ctrl_init(): Initialize IDE channel");
 
-	params.arg = (void *)ctrl;
-	params.have_irq = (ctrl->irq >= 0) ? true : false;
+	params.arg = (void *)chan;
+	params.have_irq = (chan->irq >= 0) ? true : false;
 	params.write_data_16 = isa_ide_write_data_16;
 	params.read_data_16 = isa_ide_read_data_16;
@@ -145,9 +154,9 @@
 	params.msg_error = isa_ide_msg_error;
 
-	rc = ata_channel_create(&params, &ctrl->channel);
+	rc = ata_channel_create(&params, &chan->channel);
 	if (rc != EOK)
 		goto error;
 
-	rc = ata_channel_initialize(ctrl->channel);
+	rc = ata_channel_initialize(chan->channel);
 	if (rc != EOK)
 		goto error;
@@ -157,11 +166,11 @@
 error:
 	if (irq_inited)
-		isa_ide_fini_irq(ctrl);
-	isa_ide_fini_io(ctrl);
+		isa_ide_fini_irq(chan);
+	isa_ide_fini_io(chan);
 	return rc;
 }
 
-/** Remove ISA IDE controller. */
-errno_t isa_ide_ctrl_remove(isa_ide_ctrl_t *ctrl)
+/** Finalize ISA IDE channel. */
+errno_t isa_ide_channel_fini(isa_ide_channel_t *chan)
 {
 	errno_t rc;
@@ -169,73 +178,52 @@
 	ddf_msg(LVL_DEBUG, ": isa_ide_ctrl_remove()");
 
-	fibril_mutex_lock(&ctrl->lock);
-
-	rc = ata_channel_destroy(ctrl->channel);
-	if (rc != EOK) {
-		fibril_mutex_unlock(&ctrl->lock);
-		return rc;
-	}
-
-	isa_ide_fini_irq(ctrl);
-	isa_ide_fini_io(ctrl);
-	fibril_mutex_unlock(&ctrl->lock);
+	fibril_mutex_lock(&chan->lock);
+
+	rc = ata_channel_destroy(chan->channel);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&chan->lock);
+		return rc;
+	}
+
+	isa_ide_fini_irq(chan);
+	isa_ide_fini_io(chan);
+	fibril_mutex_unlock(&chan->lock);
 
 	return EOK;
 }
 
-/** Surprise removal of ISA IDE controller. */
-errno_t isa_ide_ctrl_gone(isa_ide_ctrl_t *ctrl)
-{
-	errno_t rc;
-
-	ddf_msg(LVL_DEBUG, "isa_ide_ctrl_gone()");
-
-	fibril_mutex_lock(&ctrl->lock);
-
-	rc = ata_channel_destroy(ctrl->channel);
-	if (rc != EOK) {
-		fibril_mutex_unlock(&ctrl->lock);
-		return rc;
-	}
-
-	isa_ide_fini_io(ctrl);
-	fibril_mutex_unlock(&ctrl->lock);
-
+/** Enable device I/O. */
+static errno_t isa_ide_init_io(isa_ide_channel_t *chan)
+{
+	errno_t rc;
+	void *vaddr;
+
+	rc = pio_enable((void *) chan->cmd_physical, sizeof(ata_cmd_t), &vaddr);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Cannot initialize device I/O space.");
+		return rc;
+	}
+
+	chan->cmd = vaddr;
+
+	rc = pio_enable((void *) chan->ctl_physical, sizeof(ata_ctl_t), &vaddr);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Cannot initialize device I/O space.");
+		return rc;
+	}
+
+	chan->ctl = vaddr;
 	return EOK;
 }
 
-/** Enable device I/O. */
-static errno_t isa_ide_init_io(isa_ide_ctrl_t *ctrl)
-{
-	errno_t rc;
-	void *vaddr;
-
-	rc = pio_enable((void *) ctrl->cmd_physical, sizeof(ata_cmd_t), &vaddr);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Cannot initialize device I/O space.");
-		return rc;
-	}
-
-	ctrl->cmd = vaddr;
-
-	rc = pio_enable((void *) ctrl->ctl_physical, sizeof(ata_ctl_t), &vaddr);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Cannot initialize device I/O space.");
-		return rc;
-	}
-
-	ctrl->ctl = vaddr;
-	return EOK;
-}
-
 /** Clean up device I/O. */
-static void isa_ide_fini_io(isa_ide_ctrl_t *ctrl)
-{
-	(void) ctrl;
+static void isa_ide_fini_io(isa_ide_channel_t *chan)
+{
+	(void) chan;
 	/* XXX TODO */
 }
 
 /** Initialize IRQ. */
-static errno_t isa_ide_init_irq(isa_ide_ctrl_t *ctrl)
+static errno_t isa_ide_init_irq(isa_ide_channel_t *chan)
 {
 	irq_code_t irq_code;
@@ -244,5 +232,5 @@
 	errno_t rc;
 
-	if (ctrl->irq < 0)
+	if (chan->irq < 0)
 		return EOK;
 
@@ -258,7 +246,7 @@
 
 	memcpy(ranges, &isa_ide_irq_ranges, sizeof(isa_ide_irq_ranges));
-	ranges[0].base = ctrl->cmd_physical;
+	ranges[0].base = chan->cmd_physical;
 	memcpy(cmds, &isa_ide_irq_cmds, sizeof(isa_ide_irq_cmds));
-	cmds[0].addr = &ctrl->cmd->status;
+	cmds[0].addr = &chan->cmd->status;
 
 	irq_code.rangecount = sizeof(isa_ide_irq_ranges) / sizeof(irq_pio_range_t);
@@ -267,7 +255,7 @@
 	irq_code.cmds = cmds;
 
-	ddf_msg(LVL_NOTE, "IRQ %d", ctrl->irq);
-	rc = register_interrupt_handler(ctrl->dev, ctrl->irq, isa_ide_irq_handler,
-	    &irq_code, &ctrl->ihandle);
+	ddf_msg(LVL_NOTE, "IRQ %d", chan->irq);
+	rc = register_interrupt_handler_arg(chan->ctrl->dev, chan->irq,
+	    isa_ide_irq_handler, (void *)chan, &irq_code, &chan->ihandle);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Error registering IRQ.");
@@ -286,16 +274,16 @@
 
 /** Clean up IRQ. */
-static void isa_ide_fini_irq(isa_ide_ctrl_t *ctrl)
+static void isa_ide_fini_irq(isa_ide_channel_t *chan)
 {
 	errno_t rc;
 	async_sess_t *parent_sess;
 
-	parent_sess = ddf_dev_parent_sess_get(ctrl->dev);
-
-	rc = hw_res_disable_interrupt(parent_sess, ctrl->irq);
+	parent_sess = ddf_dev_parent_sess_get(chan->ctrl->dev);
+
+	rc = hw_res_disable_interrupt(parent_sess, chan->irq);
 	if (rc != EOK)
 		ddf_msg(LVL_ERROR, "Error disabling IRQ.");
 
-	(void) unregister_interrupt_handler(ctrl->dev, ctrl->ihandle);
+	(void) unregister_interrupt_handler(chan->ctrl->dev, chan->ihandle);
 }
 
@@ -305,20 +293,20 @@
  * @param dev Device that caused the interrupt
  */
-static void isa_ide_irq_handler(ipc_call_t *call, ddf_dev_t *dev)
-{
-	isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)ddf_dev_data_get(dev);
+static void isa_ide_irq_handler(ipc_call_t *call, ddf_dev_t *xdev)
+{
+	isa_ide_channel_t *chan = (isa_ide_channel_t *)(void *)xdev; // XXX
 	uint8_t status;
 	async_sess_t *parent_sess;
 
 	status = ipc_get_arg1(call);
-	ata_channel_irq(ctrl->channel, status);
-
-	parent_sess = ddf_dev_parent_sess_get(dev);
-	hw_res_clear_interrupt(parent_sess, ctrl->irq);
+	ata_channel_irq(chan->channel, status);
+
+	parent_sess = ddf_dev_parent_sess_get(chan->ctrl->dev);
+	hw_res_clear_interrupt(parent_sess, chan->irq);
 }
 
 /** Write the data register callback handler.
  *
- * @param arg Argument (isa_ide_ctrl_t *)
+ * @param arg Argument (isa_ide_channel_t *)
  * @param data Data
  * @param nwords Number of words to write
@@ -326,14 +314,14 @@
 static void isa_ide_write_data_16(void *arg, uint16_t *data, size_t nwords)
 {
-	isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)arg;
+	isa_ide_channel_t *chan = (isa_ide_channel_t *)arg;
 	size_t i;
 
 	for (i = 0; i < nwords; i++)
-		pio_write_16(&ctrl->cmd->data_port, data[i]);
+		pio_write_16(&chan->cmd->data_port, data[i]);
 }
 
 /** Read the data register callback handler.
  *
- * @param arg Argument (isa_ide_ctrl_t *)
+ * @param arg Argument (isa_ide_channel_t *)
  * @param buf Destination buffer
  * @param nwords Number of words to read
@@ -341,14 +329,14 @@
 static void isa_ide_read_data_16(void *arg, uint16_t *buf, size_t nwords)
 {
-	isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)arg;
+	isa_ide_channel_t *chan = (isa_ide_channel_t *)arg;
 	size_t i;
 
 	for (i = 0; i < nwords; i++)
-		buf[i] = pio_read_16(&ctrl->cmd->data_port);
+		buf[i] = pio_read_16(&chan->cmd->data_port);
 }
 
 /** Write command register callback handler.
  *
- * @param arg Argument (isa_ide_ctrl_t *)
+ * @param arg Argument (isa_ide_channel_t *)
  * @param off Register offset
  * @param value Value to write to command register
@@ -356,12 +344,12 @@
 static void isa_ide_write_cmd_8(void *arg, uint16_t off, uint8_t value)
 {
-	isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)arg;
-
-	pio_write_8(((ioport8_t *)ctrl->cmd) + off, value);
+	isa_ide_channel_t *chan = (isa_ide_channel_t *)arg;
+
+	pio_write_8(((ioport8_t *)chan->cmd) + off, value);
 }
 
 /** Read command register callback handler.
  *
- * @param arg Argument (isa_ide_ctrl_t *)
+ * @param arg Argument (isa_ide_channel_t *)
  * @param off Register offset
  * @return value Value read from command register
@@ -369,12 +357,12 @@
 static uint8_t isa_ide_read_cmd_8(void *arg, uint16_t off)
 {
-	isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)arg;
-
-	return pio_read_8(((ioport8_t *)ctrl->cmd) + off);
+	isa_ide_channel_t *chan = (isa_ide_channel_t *)arg;
+
+	return pio_read_8(((ioport8_t *)chan->cmd) + off);
 }
 
 /** Write control register callback handler.
  *
- * @param arg Argument (isa_ide_ctrl_t *)
+ * @param arg Argument (isa_ide_channel_t *)
  * @param off Register offset
  * @param value Value to write to control register
@@ -382,12 +370,12 @@
 static void isa_ide_write_ctl_8(void *arg, uint16_t off, uint8_t value)
 {
-	isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)arg;
-
-	pio_write_8(((ioport8_t *)ctrl->ctl) + off, value);
+	isa_ide_channel_t *chan = (isa_ide_channel_t *)arg;
+
+	pio_write_8(((ioport8_t *)chan->ctl) + off, value);
 }
 
 /** Read control register callback handler.
  *
- * @param arg Argument (isa_ide_ctrl_t *)
+ * @param arg Argument (isa_ide_channel_t *)
  * @param off Register offset
  * @return value Value read from control register
@@ -395,29 +383,28 @@
 static uint8_t isa_ide_read_ctl_8(void *arg, uint16_t off)
 {
-	isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)arg;
-
-	return pio_read_8(((ioport8_t *)ctrl->ctl) + off);
+	isa_ide_channel_t *chan = (isa_ide_channel_t *)arg;
+
+	return pio_read_8(((ioport8_t *)chan->ctl) + off);
 }
 
 /** Enable IRQ callback handler
  *
- * @param arg Argument (isa_ide_ctrl_t *)
+ * @param arg Argument (isa_ide_channel_t *)
  * @return EOK on success or an error code
  */
 static errno_t isa_ide_irq_enable(void *arg)
 {
-	isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)arg;
+	isa_ide_channel_t *chan = (isa_ide_channel_t *)arg;
 	async_sess_t *parent_sess;
 	errno_t rc;
 
-	ddf_msg(LVL_DEBUG, "Enable IRQ");
-
-	parent_sess = ddf_dev_parent_sess_get(ctrl->dev);
-
-	rc = hw_res_enable_interrupt(parent_sess, ctrl->irq);
+	ddf_msg(LVL_DEBUG, "Enable IRQ %d for channel %u",
+	    chan->irq, chan->chan_id);
+
+	parent_sess = ddf_dev_parent_sess_get(chan->ctrl->dev);
+
+	rc = hw_res_enable_interrupt(parent_sess, chan->irq);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Error enabling IRQ.");
-		(void) unregister_interrupt_handler(ctrl->dev,
-		    ctrl->ihandle);
 		return rc;
 	}
@@ -428,10 +415,10 @@
 /** Disable IRQ callback handler
  *
- * @param arg Argument (isa_ide_ctrl_t *)
+ * @param arg Argument (isa_ide_channel_t *)
  * @return EOK on success or an error code
  */
 static errno_t isa_ide_irq_disable(void *arg)
 {
-	isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)arg;
+	isa_ide_channel_t *chan = (isa_ide_channel_t *)arg;
 	async_sess_t *parent_sess;
 	errno_t rc;
@@ -439,11 +426,9 @@
 	ddf_msg(LVL_DEBUG, "Disable IRQ");
 
-	parent_sess = ddf_dev_parent_sess_get(ctrl->dev);
-
-	rc = hw_res_disable_interrupt(parent_sess, ctrl->irq);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Error enabling IRQ.");
-		(void) unregister_interrupt_handler(ctrl->dev,
-		    ctrl->ihandle);
+	parent_sess = ddf_dev_parent_sess_get(chan->ctrl->dev);
+
+	rc = hw_res_disable_interrupt(parent_sess, chan->irq);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Error disabling IRQ.");
 		return rc;
 	}
@@ -454,5 +439,5 @@
 /** Add ATA device callback handler.
  *
- * @param arg Argument (isa_ide_ctrl_t *)
+ * @param arg Argument (isa_ide_channel_t *)
  * @param idx Device index
  * $param charg Connection handler argument
@@ -461,11 +446,11 @@
 static errno_t isa_ide_add_device(void *arg, unsigned idx, void *charg)
 {
-	isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)arg;
-	return isa_ide_fun_create(ctrl, idx, charg);
+	isa_ide_channel_t *chan = (isa_ide_channel_t *)arg;
+	return isa_ide_fun_create(chan, idx, charg);
 }
 
 /** Remove ATA device callback handler.
  *
- * @param arg Argument (isa_ide_ctrl_t *)
+ * @param arg Argument (isa_ide_channel_t *)
  * @param idx Device index
  * @return EOK on success or an error code
@@ -473,11 +458,11 @@
 static errno_t isa_ide_remove_device(void *arg, unsigned idx)
 {
-	isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)arg;
-	return isa_ide_fun_remove(ctrl, idx);
+	isa_ide_channel_t *chan = (isa_ide_channel_t *)arg;
+	return isa_ide_fun_remove(chan, idx);
 }
 
 /** Debug message callback handler.
  *
- * @param arg Argument (isa_ide_ctrl_t *)
+ * @param arg Argument (isa_ide_channel_t *)
  * @param msg Message
  */
@@ -490,5 +475,5 @@
 /** Notice message callback handler.
  *
- * @param arg Argument (isa_ide_ctrl_t *)
+ * @param arg Argument (isa_ide_channel_t *)
  * @param msg Message
  */
@@ -501,5 +486,5 @@
 /** Warning message callback handler.
  *
- * @param arg Argument (isa_ide_ctrl_t *)
+ * @param arg Argument (isa_ide_channel_t *)
  * @param msg Message
  */
@@ -512,5 +497,5 @@
 /** Error message callback handler.
  *
- * @param arg Argument (isa_ide_ctrl_t *)
+ * @param arg Argument (isa_ide_channel_t *)
  * @param msg Message
  */
Index: uspace/drv/block/isa-ide/isa-ide.h
===================================================================
--- uspace/drv/block/isa-ide/isa-ide.h	(revision 59c0f478c5ca79154f904083a83642e63b93af6e)
+++ uspace/drv/block/isa-ide/isa-ide.h	(revision 646849b3f81f70632a7c09814cd3044cd829bde3)
@@ -47,13 +47,16 @@
 /** ISA IDE hardware resources */
 typedef struct {
-	uintptr_t cmd;	/**< Command block base address. */
-	uintptr_t ctl;	/**< Control block base address. */
-	int irq;	/**< IRQ */
+	uintptr_t cmd1;	/**< Primary channel command block base address. */
+	uintptr_t ctl1;	/**< Primary channel control block base address. */
+	uintptr_t cmd2;	/**< Secondary channel command block base address. */
+	uintptr_t ctl2;	/**< Secondary channel control block base address. */
+	int irq1;	/**< Primary channel IRQ */
+	int irq2;	/**< Secondary channel IRQ */
 } isa_ide_hwres_t;
 
-/** ISA IDE controller */
-typedef struct isa_ide_ctrl {
-	/** DDF device */
-	ddf_dev_t *dev;
+/** ISA IDE channel */
+typedef struct isa_ide_channel {
+	/** Parent controller */
+	struct isa_ide_ctrl *ctrl;
 	/** I/O base address of the command registers */
 	uintptr_t cmd_physical;
@@ -78,6 +81,19 @@
 	ata_channel_t *channel;
 	struct isa_ide_fun *fun[2];
+
+	/** Channel ID */
+	unsigned chan_id;
+} isa_ide_channel_t;
+
+/** ISA IDE controller */
+typedef struct isa_ide_ctrl {
+	/** DDF device */
+	ddf_dev_t *dev;
+
+	/** Primary and secondary channel */
+	isa_ide_channel_t channel[2];
 } isa_ide_ctrl_t;
 
+/** ISA IDE function */
 typedef struct isa_ide_fun {
 	ddf_fun_t *fun;
@@ -85,7 +101,7 @@
 } isa_ide_fun_t;
 
-extern errno_t isa_ide_ctrl_init(isa_ide_ctrl_t *, isa_ide_hwres_t *);
-extern errno_t isa_ide_ctrl_remove(isa_ide_ctrl_t *);
-extern errno_t isa_ide_ctrl_gone(isa_ide_ctrl_t *);
+extern errno_t isa_ide_channel_init(isa_ide_ctrl_t *, isa_ide_channel_t *,
+    unsigned, isa_ide_hwres_t *);
+extern errno_t isa_ide_channel_fini(isa_ide_channel_t *);
 
 #endif
Index: uspace/drv/block/isa-ide/main.c
===================================================================
--- uspace/drv/block/isa-ide/main.c	(revision 59c0f478c5ca79154f904083a83642e63b93af6e)
+++ uspace/drv/block/isa-ide/main.c	(revision 646849b3f81f70632a7c09814cd3044cd829bde3)
@@ -81,5 +81,5 @@
 		return rc;
 
-	if (hw_res.io_ranges.count != 2) {
+	if (hw_res.io_ranges.count != 4) {
 		rc = EINVAL;
 		goto error;
@@ -88,15 +88,29 @@
 	/* I/O ranges */
 
-	addr_range_t *cmd_rng = &hw_res.io_ranges.ranges[0];
-	addr_range_t *ctl_rng = &hw_res.io_ranges.ranges[1];
-	ata_res->cmd = RNGABS(*cmd_rng);
-	ata_res->ctl = RNGABS(*ctl_rng);
-
-	if (RNGSZ(*ctl_rng) < sizeof(ata_ctl_t)) {
-		rc = EINVAL;
-		goto error;
-	}
-
-	if (RNGSZ(*cmd_rng) < sizeof(ata_cmd_t)) {
+	addr_range_t *cmd1_rng = &hw_res.io_ranges.ranges[0];
+	addr_range_t *ctl1_rng = &hw_res.io_ranges.ranges[1];
+	addr_range_t *cmd2_rng = &hw_res.io_ranges.ranges[2];
+	addr_range_t *ctl2_rng = &hw_res.io_ranges.ranges[3];
+	ata_res->cmd1 = RNGABS(*cmd1_rng);
+	ata_res->ctl1 = RNGABS(*ctl1_rng);
+	ata_res->cmd2 = RNGABS(*cmd2_rng);
+	ata_res->ctl2 = RNGABS(*ctl2_rng);
+
+	if (RNGSZ(*ctl1_rng) < sizeof(ata_ctl_t)) {
+		rc = EINVAL;
+		goto error;
+	}
+
+	if (RNGSZ(*cmd1_rng) < sizeof(ata_cmd_t)) {
+		rc = EINVAL;
+		goto error;
+	}
+
+	if (RNGSZ(*ctl2_rng) < sizeof(ata_ctl_t)) {
+		rc = EINVAL;
+		goto error;
+	}
+
+	if (RNGSZ(*cmd2_rng) < sizeof(ata_cmd_t)) {
 		rc = EINVAL;
 		goto error;
@@ -105,7 +119,13 @@
 	/* IRQ */
 	if (hw_res.irqs.count > 0) {
-		ata_res->irq = hw_res.irqs.irqs[0];
+		ata_res->irq1 = hw_res.irqs.irqs[0];
 	} else {
-		ata_res->irq = -1;
+		ata_res->irq1 = -1;
+	}
+
+	if (hw_res.irqs.count > 1) {
+		ata_res->irq2 = hw_res.irqs.irqs[1];
+	} else {
+		ata_res->irq2 = -1;
 	}
 
@@ -142,5 +162,9 @@
 	ctrl->dev = dev;
 
-	rc = isa_ide_ctrl_init(ctrl, &res);
+	rc = isa_ide_channel_init(ctrl, &ctrl->channel[0], 0, &res);
+	if (rc == ENOENT)
+		goto error;
+
+	rc = isa_ide_channel_init(ctrl, &ctrl->channel[1], 1, &res);
 	if (rc == ENOENT)
 		goto error;
@@ -157,9 +181,9 @@
 }
 
-static char *isa_ide_fun_name(unsigned idx)
+static char *isa_ide_fun_name(isa_ide_channel_t *chan, unsigned idx)
 {
 	char *fun_name;
 
-	if (asprintf(&fun_name, "d%u", idx) < 0)
+	if (asprintf(&fun_name, "c%ud%u", chan->chan_id, idx) < 0)
 		return NULL;
 
@@ -167,5 +191,5 @@
 }
 
-errno_t isa_ide_fun_create(isa_ide_ctrl_t *ctrl, unsigned idx, void *charg)
+errno_t isa_ide_fun_create(isa_ide_channel_t *chan, unsigned idx, void *charg)
 {
 	errno_t rc;
@@ -175,5 +199,5 @@
 	bool bound = false;
 
-	fun_name = isa_ide_fun_name(idx);
+	fun_name = isa_ide_fun_name(chan, idx);
 	if (fun_name == NULL) {
 		ddf_msg(LVL_ERROR, "Out of memory.");
@@ -182,5 +206,5 @@
 	}
 
-	fun = ddf_fun_create(ctrl->dev, fun_exposed, fun_name);
+	fun = ddf_fun_create(chan->ctrl->dev, fun_exposed, fun_name);
 	if (fun == NULL) {
 		ddf_msg(LVL_ERROR, "Failed creating DDF function.");
@@ -232,11 +256,11 @@
 }
 
-errno_t isa_ide_fun_remove(isa_ide_ctrl_t *ctrl, unsigned idx)
+errno_t isa_ide_fun_remove(isa_ide_channel_t *chan, unsigned idx)
 {
 	errno_t rc;
 	char *fun_name;
-	isa_ide_fun_t *ifun = ctrl->fun[idx];
-
-	fun_name = isa_ide_fun_name(idx);
+	isa_ide_fun_t *ifun = chan->fun[idx];
+
+	fun_name = isa_ide_fun_name(chan, idx);
 	if (fun_name == NULL) {
 		ddf_msg(LVL_ERROR, "Out of memory.");
@@ -267,11 +291,11 @@
 }
 
-errno_t isa_ide_fun_unbind(isa_ide_ctrl_t *ctrl, unsigned idx)
+errno_t isa_ide_fun_unbind(isa_ide_channel_t *chan, unsigned idx)
 {
 	errno_t rc;
 	char *fun_name;
-	isa_ide_fun_t *ifun = ctrl->fun[idx];
-
-	fun_name = isa_ide_fun_name(idx);
+	isa_ide_fun_t *ifun = chan->fun[idx];
+
+	fun_name = isa_ide_fun_name(chan, idx);
 	if (fun_name == NULL) {
 		ddf_msg(LVL_ERROR, "Out of memory.");
@@ -299,8 +323,17 @@
 {
 	isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)ddf_dev_data_get(dev);
+	errno_t rc;
 
 	ddf_msg(LVL_DEBUG, "isa_ide_dev_remove(%p)", dev);
 
-	return isa_ide_ctrl_remove(ctrl);
+	rc = isa_ide_channel_fini(&ctrl->channel[0]);
+	if (rc != EOK)
+		return rc;
+
+	rc = isa_ide_channel_fini(&ctrl->channel[1]);
+	if (rc != EOK)
+		return rc;
+
+	return EOK;
 }
 
@@ -308,8 +341,17 @@
 {
 	isa_ide_ctrl_t *ctrl = (isa_ide_ctrl_t *)ddf_dev_data_get(dev);
+	errno_t rc;
 
 	ddf_msg(LVL_DEBUG, "isa_ide_dev_gone(%p)", dev);
 
-	return isa_ide_ctrl_gone(ctrl);
+	rc = isa_ide_channel_fini(&ctrl->channel[0]);
+	if (rc != EOK)
+		return rc;
+
+	rc = isa_ide_channel_fini(&ctrl->channel[1]);
+	if (rc != EOK)
+		return rc;
+
+	return EOK;
 }
 
Index: uspace/drv/block/isa-ide/main.h
===================================================================
--- uspace/drv/block/isa-ide/main.h	(revision 59c0f478c5ca79154f904083a83642e63b93af6e)
+++ uspace/drv/block/isa-ide/main.h	(revision 646849b3f81f70632a7c09814cd3044cd829bde3)
@@ -38,7 +38,7 @@
 #include "isa-ide.h"
 
-extern errno_t isa_ide_fun_create(isa_ide_ctrl_t *, unsigned, void *);
-extern errno_t isa_ide_fun_remove(isa_ide_ctrl_t *, unsigned);
-extern errno_t isa_ide_fun_unbind(isa_ide_ctrl_t *, unsigned);
+extern errno_t isa_ide_fun_create(isa_ide_channel_t *, unsigned, void *);
+extern errno_t isa_ide_fun_remove(isa_ide_channel_t *, unsigned);
+extern errno_t isa_ide_fun_unbind(isa_ide_channel_t *, unsigned);
 
 #endif
Index: uspace/drv/bus/isa/isa.c
===================================================================
--- uspace/drv/bus/isa/isa.c	(revision 59c0f478c5ca79154f904083a83642e63b93af6e)
+++ uspace/drv/bus/isa/isa.c	(revision 646849b3f81f70632a7c09814cd3044cd829bde3)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2018 Jiri Svoboda
+ * Copyright (c) 2024 Jiri Svoboda
  * Copyright (c) 2010 Lenka Trochtova
  * Copyright (c) 2011 Jan Vesely
@@ -72,5 +72,5 @@
 #define EBUS_CHILD_FUN_CONF_PATH "/drv/isa/ebus.dev"
 
-#define ISA_MAX_HW_RES 5
+#define ISA_MAX_HW_RES 6
 
 typedef struct {
Index: uspace/drv/bus/isa/isa.dev
===================================================================
--- uspace/drv/bus/isa/isa.dev	(revision 59c0f478c5ca79154f904083a83642e63b93af6e)
+++ uspace/drv/bus/isa/isa.dev	(revision 646849b3f81f70632a7c09814cd3044cd829bde3)
@@ -51,13 +51,10 @@
 	io_range 70 2
 
-ata-c1:
+ide1:
 	match 100 isa/ide
 	io_range 0x1f0 8
 	io_range 0x3f0 8
-	irq 14
-
-ata-c2:
-	match 100 isa/ide
 	io_range 0x170 8
 	io_range 0x370 8
+	irq 14
 	irq 15
