Index: uspace/drv/audio/hdaudio/hdaudio.c
===================================================================
--- uspace/drv/audio/hdaudio/hdaudio.c	(revision 646849b3f81f70632a7c09814cd3044cd829bde3)
+++ uspace/drv/audio/hdaudio/hdaudio.c	(revision 60744cba3754acca8b3f05999d839bd617742de8)
@@ -58,5 +58,5 @@
 static errno_t hda_fun_offline(ddf_fun_t *fun);
 
-static void hdaudio_interrupt(ipc_call_t *, ddf_dev_t *);
+static void hdaudio_interrupt(ipc_call_t *, void *);
 
 static driver_ops_t driver_ops = {
@@ -266,5 +266,5 @@
 	cap_irq_handle_t irq_cap;
 	rc = register_interrupt_handler(dev, res.irqs.irqs[0],
-	    hdaudio_interrupt, &irq_code, &irq_cap);
+	    hdaudio_interrupt, (void *)hda, &irq_code, &irq_cap);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed registering interrupt handler: %s",
@@ -377,7 +377,12 @@
 }
 
-static void hdaudio_interrupt(ipc_call_t *icall, ddf_dev_t *dev)
-{
-	hda_t *hda = (hda_t *)ddf_dev_data_get(dev);
+/** HD Audio interrupt handler.
+ *
+ * @param icall IRQ event notification
+ * @param arg Argument (hda_t *)
+ */
+static void hdaudio_interrupt(ipc_call_t *icall, void *arg)
+{
+	hda_t *hda = (hda_t *)arg;
 
 	if (0)
Index: uspace/drv/audio/sb16/main.c
===================================================================
--- uspace/drv/audio/sb16/main.c	(revision 646849b3f81f70632a7c09814cd3044cd829bde3)
+++ uspace/drv/audio/sb16/main.c	(revision 60744cba3754acca8b3f05999d839bd617742de8)
@@ -76,7 +76,12 @@
 }
 
-static void irq_handler(ipc_call_t *call, ddf_dev_t *dev)
-{
-	sb16_t *sb16_dev = ddf_dev_data_get(dev);
+/** SB16 IRQ handler.
+ *
+ * @param call IRQ event notification
+ * @param arg Argument (sb16_t *)
+ */
+static void irq_handler(ipc_call_t *call, void *arg)
+{
+	sb16_t *sb16_dev = (sb16_t *)arg;
 	sb16_interrupt(sb16_dev);
 }
@@ -124,5 +129,5 @@
 
 	rc = register_interrupt_handler(device, irq, irq_handler,
-	    &irq_code, &irq_cap);
+	    (void *)soft_state, &irq_code, &irq_cap);
 	if (rc != EOK) {
 		ddf_log_error("Failed to register irq handler: %s.",
Index: uspace/drv/block/ahci/ahci.c
===================================================================
--- uspace/drv/block/ahci/ahci.c	(revision 646849b3f81f70632a7c09814cd3044cd829bde3)
+++ uspace/drv/block/ahci/ahci.c	(revision 60744cba3754acca8b3f05999d839bd617742de8)
@@ -162,10 +162,4 @@
 }
 
-/** 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.
  *
@@ -891,10 +885,9 @@
  *
  * @param icall The IPC call structure.
- * @param dev   DDF device structure.
- *
- */
-static void ahci_interrupt(ipc_call_t *icall, ddf_dev_t *dev)
-{
-	ahci_dev_t *ahci = dev_ahci_dev(dev);
+ * @param arg   Argument (ahci_dev_t *)
+ */
+static void ahci_interrupt(ipc_call_t *icall, void *arg)
+{
+	ahci_dev_t *ahci = (ahci_dev_t *)arg;
 	unsigned int port = ipc_get_arg1(icall);
 	ahci_port_is_t pxis = ipc_get_arg2(icall);
@@ -1186,5 +1179,6 @@
 	cap_irq_handle_t irq_cap;
 	errno_t rc = register_interrupt_handler(dev,
-	    hw_res_parsed.irqs.irqs[0], ahci_interrupt, &ct, &irq_cap);
+	    hw_res_parsed.irqs.irqs[0], ahci_interrupt, (void *)ahci, &ct,
+	    &irq_cap);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed registering interrupt handler.");
Index: uspace/drv/block/ddisk/ddisk.c
===================================================================
--- uspace/drv/block/ddisk/ddisk.c	(revision 646849b3f81f70632a7c09814cd3044cd829bde3)
+++ uspace/drv/block/ddisk/ddisk.c	(revision 60744cba3754acca8b3f05999d839bd617742de8)
@@ -64,5 +64,5 @@
 static void ddisk_bd_connection(ipc_call_t *, void *);
 
-static void ddisk_irq_handler(ipc_call_t *, ddf_dev_t *);
+static void ddisk_irq_handler(ipc_call_t *, void *);
 
 static driver_ops_t driver_ops = {
@@ -176,10 +176,15 @@
 };
 
-void ddisk_irq_handler(ipc_call_t *icall, ddf_dev_t *dev)
+/** Ddisk IRQ handler.
+ *
+ * @param icall IRQ event notification
+ * @param arg Argument (ddisk_t *)
+ */
+void ddisk_irq_handler(ipc_call_t *icall, void *arg)
 {
 	ddf_msg(LVL_DEBUG, "ddisk_irq_handler(), status=%" PRIx32,
 	    (uint32_t) ipc_get_arg1(icall));
 
-	ddisk_t *ddisk = (ddisk_t *) ddf_dev_data_get(dev);
+	ddisk_t *ddisk = (ddisk_t *)arg;
 
 	fibril_mutex_lock(&ddisk->lock);
@@ -512,5 +517,5 @@
 	ddisk_irq_commands[3].addr = (void *) &res_phys->command;
 	rc = register_interrupt_handler(dev, ddisk->ddisk_res.irq,
-	    ddisk_irq_handler, &ddisk_irq_code, &ddisk->irq_cap);
+	    ddisk_irq_handler, (void *)ddisk, &ddisk_irq_code, &ddisk->irq_cap);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed to register interrupt handler.");
Index: uspace/drv/block/isa-ide/isa-ide.c
===================================================================
--- uspace/drv/block/isa-ide/isa-ide.c	(revision 646849b3f81f70632a7c09814cd3044cd829bde3)
+++ uspace/drv/block/isa-ide/isa-ide.c	(revision 60744cba3754acca8b3f05999d839bd617742de8)
@@ -59,5 +59,5 @@
 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_irq_handler(ipc_call_t *, void *);
 
 static void isa_ide_write_data_16(void *, uint16_t *, size_t);
@@ -256,5 +256,5 @@
 
 	ddf_msg(LVL_NOTE, "IRQ %d", chan->irq);
-	rc = register_interrupt_handler_arg(chan->ctrl->dev, chan->irq,
+	rc = register_interrupt_handler(chan->ctrl->dev, chan->irq,
 	    isa_ide_irq_handler, (void *)chan, &irq_code, &chan->ihandle);
 	if (rc != EOK) {
@@ -291,9 +291,9 @@
  *
  * @param call Call data
- * @param dev Device that caused the interrupt
- */
-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
+ * @param arg Argument (isa_ide_channel_t *)
+ */
+static void isa_ide_irq_handler(ipc_call_t *call, void *arg)
+{
+	isa_ide_channel_t *chan = (isa_ide_channel_t *)arg;
 	uint8_t status;
 	async_sess_t *parent_sess;
Index: uspace/drv/block/virtio-blk/virtio-blk.c
===================================================================
--- uspace/drv/block/virtio-blk/virtio-blk.c	(revision 646849b3f81f70632a7c09814cd3044cd829bde3)
+++ uspace/drv/block/virtio-blk/virtio-blk.c	(revision 60744cba3754acca8b3f05999d839bd617742de8)
@@ -73,7 +73,12 @@
 };
 
-static void virtio_blk_irq_handler(ipc_call_t *icall, ddf_dev_t *dev)
-{
-	virtio_blk_t *virtio_blk = (virtio_blk_t *) ddf_dev_data_get(dev);
+/** VirtIO block IRQ handler.
+ *
+ * @param icall IRQ event notification
+ * @param arg Argument (virtio_blk_t *)
+ */
+static void virtio_blk_irq_handler(ipc_call_t *icall, void *arg)
+{
+	virtio_blk_t *virtio_blk = (virtio_blk_t *)arg;
 	virtio_dev_t *vdev = &virtio_blk->virtio_dev;
 
@@ -145,5 +150,6 @@
 
 	return register_interrupt_handler(dev, virtio_blk->irq,
-	    virtio_blk_irq_handler, &irq_code, &virtio_blk->irq_handle);
+	    virtio_blk_irq_handler, (void *)virtio_blk, &irq_code,
+	    &virtio_blk->irq_handle);
 }
 
Index: uspace/drv/char/i8042/i8042.c
===================================================================
--- uspace/drv/char/i8042/i8042.c	(revision 646849b3f81f70632a7c09814cd3044cd829bde3)
+++ uspace/drv/char/i8042/i8042.c	(revision 60744cba3754acca8b3f05999d839bd617742de8)
@@ -123,11 +123,10 @@
  * Write new data to the corresponding buffer.
  *
- * @param call pointerr to call data.
- * @param dev  Device that caued the interrupt.
- *
- */
-static void i8042_irq_handler(ipc_call_t *call, ddf_dev_t *dev)
-{
-	i8042_t *controller = ddf_dev_data_get(dev);
+ * @param call Pointer to call data.
+ * @param arg  Argument (i8042_t *)
+ */
+static void i8042_irq_handler(ipc_call_t *call, void *arg)
+{
+	i8042_t *controller = (i8042_t *)arg;
 	errno_t rc;
 
@@ -147,5 +146,5 @@
 	fibril_condvar_broadcast(&port->buf_cv);
 
-	async_sess_t *parent_sess = ddf_dev_parent_sess_get(dev);
+	async_sess_t *parent_sess = ddf_dev_parent_sess_get(controller->dev);
 	hw_res_clear_interrupt(parent_sess, port->irq);
 }
@@ -178,4 +177,6 @@
 	bool aux_bound = false;
 
+	dev->dev = ddf_dev;
+
 	if (regs->size < sizeof(i8042_regs_t)) {
 		rc = EINVAL;
@@ -288,5 +289,5 @@
 	cap_irq_handle_t kbd_ihandle;
 	rc = register_interrupt_handler(ddf_dev, irq_kbd,
-	    i8042_irq_handler, &irq_code, &kbd_ihandle);
+	    i8042_irq_handler, (void *)dev, &irq_code, &kbd_ihandle);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed set handler for kbd: %s.",
@@ -297,5 +298,5 @@
 	cap_irq_handle_t mouse_ihandle;
 	rc = register_interrupt_handler(ddf_dev, irq_mouse,
-	    i8042_irq_handler, &irq_code, &mouse_ihandle);
+	    i8042_irq_handler, (void *)dev, &irq_code, &mouse_ihandle);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed set handler for mouse: %s.",
Index: uspace/drv/char/i8042/i8042.h
===================================================================
--- uspace/drv/char/i8042/i8042.h	(revision 646849b3f81f70632a7c09814cd3044cd829bde3)
+++ uspace/drv/char/i8042/i8042.h	(revision 60744cba3754acca8b3f05999d839bd617742de8)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2021 Jiri Svoboda
+ * Copyright (c) 2024 Jiri Svoboda
  * Copyright (c) 2006 Josef Cejka
  * Copyright (c) 2011 Jan Vesely
@@ -82,4 +82,6 @@
 /** i8042 Controller. */
 typedef struct i8042 {
+	/** DDF device */
+	ddf_dev_t *dev;
 	/** I/O registers. */
 	i8042_regs_t *regs;
Index: uspace/drv/char/ns8250/ns8250.c
===================================================================
--- uspace/drv/char/ns8250/ns8250.c	(revision 646849b3f81f70632a7c09814cd3044cd829bde3)
+++ uspace/drv/char/ns8250/ns8250.c	(revision 60744cba3754acca8b3f05999d839bd617742de8)
@@ -783,10 +783,10 @@
  * data and reading the line status register.
  *
- * @param dev The serial port device.
- *
- */
-static inline void ns8250_interrupt_handler(ipc_call_t *icall, ddf_dev_t *dev)
-{
-	ns8250_t *ns = dev_ns8250(dev);
+ * @pram icall IRQ event notificatoin
+ * @param arg Argument (ns8250_t *)
+ */
+static inline void ns8250_interrupt_handler(ipc_call_t *icall, void *arg)
+{
+	ns8250_t *ns = (ns8250_t *)arg;
 	uint8_t iir = pio_read_8(&ns->regs->iid);
 	if ((iir & NS8250_IID_CAUSE_MASK) == NS8250_IID_CAUSE_RXSTATUS) {
@@ -809,5 +809,5 @@
 {
 	return register_interrupt_handler(ns->dev, ns->irq,
-	    ns8250_interrupt_handler, NULL, ihandle);
+	    ns8250_interrupt_handler, (void *)ns, NULL, ihandle);
 }
 
Index: uspace/drv/char/pl050/pl050.c
===================================================================
--- uspace/drv/char/pl050/pl050.c	(revision 646849b3f81f70632a7c09814cd3044cd829bde3)
+++ uspace/drv/char/pl050/pl050.c	(revision 60744cba3754acca8b3f05999d839bd617742de8)
@@ -143,7 +143,12 @@
 }
 
-static void pl050_interrupt(ipc_call_t *call, ddf_dev_t *dev)
-{
-	pl050_t *pl050 = (pl050_t *)ddf_dev_data_get(dev);
+/** PL050 interrupt handler
+ *
+ * @param call IRQ event notification
+ * @param arg Argument (pl050_t *)
+ */
+static void pl050_interrupt(ipc_call_t *call, void *arg)
+{
+	pl050_t *pl050 = (pl050_t *)arg;
 	size_t nidx;
 
@@ -220,5 +225,6 @@
 	cap_irq_handle_t ihandle;
 	rc = register_interrupt_handler(pl050->dev,
-	    res.irqs.irqs[0], pl050_interrupt, &pl050_irq_code, &ihandle);
+	    res.irqs.irqs[0], pl050_interrupt, (void *)pl050, &pl050_irq_code,
+	    &ihandle);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed registering interrupt handler. (%s)",
Index: uspace/drv/nic/e1k/e1k.c
===================================================================
--- uspace/drv/nic/e1k/e1k.c	(revision 646849b3f81f70632a7c09814cd3044cd829bde3)
+++ uspace/drv/nic/e1k/e1k.c	(revision 60744cba3754acca8b3f05999d839bd617742de8)
@@ -1244,12 +1244,11 @@
  *
  * @param icall IPC call structure
- * @param dev   E1000 device
- *
- */
-static void e1000_interrupt_handler(ipc_call_t *icall,
-    ddf_dev_t *dev)
+ * @param arg   Argument (nic_t *)
+ *
+ */
+static void e1000_interrupt_handler(ipc_call_t *icall, void *arg)
 {
 	uint32_t icr = (uint32_t) ipc_get_arg2(icall);
-	nic_t *nic = NIC_DATA_DEV(dev);
+	nic_t *nic = (nic_t *)arg;
 	e1000_t *e1000 = DRIVER_DATA_NIC(nic);
 
@@ -1283,5 +1282,5 @@
 
 	errno_t rc = register_interrupt_handler(nic_get_ddf_dev(nic), e1000->irq,
-	    e1000_interrupt_handler, &e1000_irq_code, handle);
+	    e1000_interrupt_handler, (void *)nic, &e1000_irq_code, handle);
 
 	fibril_mutex_unlock(&irq_reg_mutex);
Index: uspace/drv/nic/ne2k/ne2k.c
===================================================================
--- uspace/drv/nic/ne2k/ne2k.c	(revision 646849b3f81f70632a7c09814cd3044cd829bde3)
+++ uspace/drv/nic/ne2k/ne2k.c	(revision 60744cba3754acca8b3f05999d839bd617742de8)
@@ -121,5 +121,5 @@
 };
 
-static void ne2k_interrupt_handler(ipc_call_t *, ddf_dev_t *);
+static void ne2k_interrupt_handler(ipc_call_t *, void *);
 
 static errno_t ne2k_register_interrupt(nic_t *nic_data,
@@ -161,5 +161,6 @@
 
 	return register_interrupt_handler(nic_get_ddf_dev(nic_data),
-	    ne2k->irq, ne2k_interrupt_handler, &ne2k->code, handle);
+	    ne2k->irq, ne2k_interrupt_handler, (void *)nic_data, &ne2k->code,
+	    handle);
 }
 
@@ -237,7 +238,12 @@
 }
 
-void ne2k_interrupt_handler(ipc_call_t *call, ddf_dev_t *dev)
-{
-	nic_t *nic_data = DRIVER_DATA(dev);
+/** NE2K interrupt handler
+ *
+ * @param call IRQ event notification
+ * @param arg Argument (nic_t *)
+ */
+void ne2k_interrupt_handler(ipc_call_t *call, void *arg)
+{
+	nic_t *nic_data = (nic_t *)arg;
 	ne2k_interrupt(nic_data, IRQ_GET_ISR(*call), IRQ_GET_TSR(*call));
 }
Index: uspace/drv/nic/rtl8139/driver.c
===================================================================
--- uspace/drv/nic/rtl8139/driver.c	(revision 646849b3f81f70632a7c09814cd3044cd829bde3)
+++ uspace/drv/nic/rtl8139/driver.c	(revision 60744cba3754acca8b3f05999d839bd617742de8)
@@ -819,14 +819,11 @@
  *
  * @param icall  The IPC call structure
- * @param dev    The rtl8139 device
- *
- */
-static void rtl8139_interrupt_handler(ipc_call_t *icall, ddf_dev_t *dev)
-{
-	assert(dev);
-	assert(icall);
-
+ * @param arg    Argument (nic_t *)
+ *
+ */
+static void rtl8139_interrupt_handler(ipc_call_t *icall, void *arg)
+{
 	uint16_t isr = (uint16_t) ipc_get_arg2(icall);
-	nic_t *nic_data = nic_get_from_ddf_dev(dev);
+	nic_t *nic_data = (nic_t *)arg;
 	rtl8139_t *rtl8139 = nic_get_specific(nic_data);
 
@@ -861,5 +858,6 @@
 	rtl8139_irq_code.cmds[3].addr = rtl8139->io_addr + IMR;
 	errno_t rc = register_interrupt_handler(nic_get_ddf_dev(nic_data),
-	    rtl8139->irq, rtl8139_interrupt_handler, &rtl8139_irq_code, handle);
+	    rtl8139->irq, rtl8139_interrupt_handler, (void *)nic_data,
+	    &rtl8139_irq_code, handle);
 
 	RTL8139_IRQ_STRUCT_UNLOCK();
Index: uspace/drv/nic/rtl8169/driver.c
===================================================================
--- uspace/drv/nic/rtl8169/driver.c	(revision 646849b3f81f70632a7c09814cd3044cd829bde3)
+++ uspace/drv/nic/rtl8169/driver.c	(revision 60744cba3754acca8b3f05999d839bd617742de8)
@@ -74,5 +74,5 @@
 static errno_t rtl8169_on_stopped(nic_t *nic_data);
 static void rtl8169_send_frame(nic_t *nic_data, void *data, size_t size);
-static void rtl8169_irq_handler(ipc_call_t *icall, ddf_dev_t *dev);
+static void rtl8169_irq_handler(ipc_call_t *icall, void *);
 static inline errno_t rtl8169_register_int_handler(nic_t *nic_data,
     cap_irq_handle_t *handle);
@@ -372,5 +372,6 @@
 	rtl8169_irq_code.cmds[3].addr = rtl8169->regs + IMR;
 	errno_t rc = register_interrupt_handler(nic_get_ddf_dev(nic_data),
-	    rtl8169->irq, rtl8169_irq_handler, &rtl8169_irq_code, handle);
+	    rtl8169->irq, rtl8169_irq_handler, (void *)rtl8169,
+	    &rtl8169_irq_code, handle);
 
 	return rc;
@@ -1033,12 +1034,13 @@
 }
 
-static void rtl8169_irq_handler(ipc_call_t *icall, ddf_dev_t *dev)
-{
-	assert(dev);
-	assert(icall);
-
+/** RTL8169 IRQ handler.
+ *
+ * @param icall IRQ event notification
+ * @param arg Argument (rtl8169_t *)
+ */
+static void rtl8169_irq_handler(ipc_call_t *icall, void *arg)
+{
 	uint16_t isr = (uint16_t) ipc_get_arg2(icall) & INT_KNOWN;
-	nic_t *nic_data = nic_get_from_ddf_dev(dev);
-	rtl8169_t *rtl8169 = nic_get_specific(nic_data);
+	rtl8169_t *rtl8169 = (rtl8169_t *)arg;
 
 	ddf_msg(LVL_DEBUG, "rtl8169_irq_handler(): isr=0x%04x", isr);
@@ -1050,5 +1052,5 @@
 		/* Packet underrun or link change */
 		if (isr & INT_PUN) {
-			rtl8169_link_change(dev);
+			rtl8169_link_change(rtl8169->dev);
 			pio_write_16(rtl8169->regs + ISR, INT_PUN);
 		}
@@ -1056,5 +1058,5 @@
 		/* Transmit notification */
 		if (isr & (INT_TER | INT_TOK | INT_TDU)) {
-			rtl8169_transmit_done(dev);
+			rtl8169_transmit_done(rtl8169->dev);
 			pio_write_16(rtl8169->regs + ISR, (INT_TER | INT_TOK | INT_TDU));
 		}
@@ -1072,5 +1074,5 @@
 
 		if (isr & (INT_RER | INT_ROK)) {
-			rtl8169_receive_done(dev);
+			rtl8169_receive_done(rtl8169->dev);
 			pio_write_16(rtl8169->regs + ISR, (INT_RER | INT_ROK));
 		}
Index: uspace/drv/nic/virtio-net/virtio-net.c
===================================================================
--- uspace/drv/nic/virtio-net/virtio-net.c	(revision 646849b3f81f70632a7c09814cd3044cd829bde3)
+++ uspace/drv/nic/virtio-net/virtio-net.c	(revision 60744cba3754acca8b3f05999d839bd617742de8)
@@ -70,7 +70,12 @@
 };
 
-static void virtio_net_irq_handler(ipc_call_t *icall, ddf_dev_t *dev)
-{
-	nic_t *nic = ddf_dev_data_get(dev);
+/** VirtIO net IRQ handler.
+ *
+ * @param icall IRQ event notification
+ * @param arg Argument (nic_t *)
+ */
+static void virtio_net_irq_handler(ipc_call_t *icall, void *arg)
+{
+	nic_t *nic = (nic_t *)arg;
 	virtio_net_t *virtio_net = nic_get_specific(nic);
 	virtio_dev_t *vdev = &virtio_net->virtio_dev;
@@ -164,5 +169,6 @@
 
 	return register_interrupt_handler(dev, virtio_net->irq,
-	    virtio_net_irq_handler, &irq_code, &virtio_net->irq_handle);
+	    virtio_net_irq_handler, (void *)nic, &irq_code,
+	    &virtio_net->irq_handle);
 }
 
