Index: boot/arch/ppc32/Makefile.inc
===================================================================
--- boot/arch/ppc32/Makefile.inc	(revision 81b9d3ed6af6996e5039aa44755f6f7a9b396e2f)
+++ boot/arch/ppc32/Makefile.inc	(revision 84eb4edda850471e7ed12ca3028b9662df14cc3d)
@@ -44,5 +44,4 @@
 RD_DRVS_ESSENTIAL += \
 	platform/mac \
-	bus/adb/cuda_adb \
 	bus/pci/pciintel \
 	bus/usb/ohci \
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 81b9d3ed6af6996e5039aa44755f6f7a9b396e2f)
+++ uspace/Makefile	(revision 84eb4edda850471e7ed12ca3028b9662df14cc3d)
@@ -134,4 +134,5 @@
 	srv/hid/output \
 	srv/hid/remcons \
+	srv/hw/bus/cuda_adb \
 	srv/hw/char/s3c24xx_uart \
 	srv/hw/irc/apic \
@@ -147,5 +148,4 @@
 	drv/block/ata_bd \
 	drv/block/ddisk \
-	drv/bus/adb/cuda_adb \
 	drv/bus/isa \
 	drv/bus/pci/pciintel \
Index: uspace/app/init/init.c
===================================================================
--- uspace/app/init/init.c	(revision 81b9d3ed6af6996e5039aa44755f6f7a9b396e2f)
+++ uspace/app/init/init.c	(revision 84eb4edda850471e7ed12ca3028b9662df14cc3d)
@@ -342,4 +342,5 @@
 	srv_start("/srv/icp-ic");
 	srv_start("/srv/obio");
+	srv_start("/srv/cuda_adb");
 	srv_start("/srv/s3c24xx_uart");
 	srv_start("/srv/s3c24xx_ts");
Index: pace/drv/bus/adb/cuda_adb/Makefile
===================================================================
--- uspace/drv/bus/adb/cuda_adb/Makefile	(revision 81b9d3ed6af6996e5039aa44755f6f7a9b396e2f)
+++ 	(revision )
@@ -1,38 +1,0 @@
-#
-# Copyright (c) 2010 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.
-#
-
-USPACE_PREFIX = ../../../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
-BINARY = cuda_adb
-
-SOURCES = \
-	cuda_adb.c \
-	main.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/bus/adb/cuda_adb/cuda_adb.c
===================================================================
--- uspace/drv/bus/adb/cuda_adb/cuda_adb.c	(revision 81b9d3ed6af6996e5039aa44755f6f7a9b396e2f)
+++ 	(revision )
@@ -1,506 +1,0 @@
-/*
- * Copyright (c) 2010 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 genarch
- * @{
- */
-/** @file VIA-CUDA Apple Desktop Bus driver
- *
- * Note: We should really do a full bus scan at the beginning and resolve
- * address conflicts. Also we should consider the handler ID in r3. Instead
- * we just assume a keyboard at address 2 or 8 and a mouse at address 9.
- */
-
-#include <assert.h>
-#include <ddf/driver.h>
-#include <ddf/log.h>
-#include <ddi.h>
-#include <errno.h>
-#include <ipc/adb.h>
-#include <libarch/ddi.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <sysinfo.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "cuda_adb.h"
-#include "cuda_hw.h"
-
-#define NAME  "cuda_adb"
-
-static void cuda_dev_connection(ipc_callid_t, ipc_call_t *, void *);
-static int cuda_init(cuda_t *);
-static void cuda_irq_handler(ipc_callid_t, ipc_call_t *, void *);
-
-static void cuda_irq_listen(cuda_t *);
-static void cuda_irq_receive(cuda_t *);
-static void cuda_irq_rcv_end(cuda_t *, void *, size_t *);
-static void cuda_irq_send_start(cuda_t *);
-static void cuda_irq_send(cuda_t *);
-
-static void cuda_packet_handle(cuda_t *, uint8_t *, size_t);
-static void cuda_send_start(cuda_t *);
-static void cuda_autopoll_set(cuda_t *, bool);
-
-static void adb_packet_handle(cuda_t *, uint8_t *, size_t, bool);
-
-static irq_pio_range_t cuda_ranges[] = {
-	{
-		.base = 0,
-		.size = sizeof(cuda_regs_t)
-	}
-};
-
-static irq_cmd_t cuda_cmds[] = {
-	{
-		.cmd = CMD_PIO_READ_8,
-		.addr = NULL,
-		.dstarg = 1
-	},
-	{
-		.cmd = CMD_AND,
-		.value = SR_INT,
-		.srcarg = 1,
-		.dstarg = 2
-	},
-	{
-		.cmd = CMD_PREDICATE,
-		.value = 1,
-		.srcarg = 2
-	},
-	{
-		.cmd = CMD_ACCEPT
-	}
-};
-
-
-static irq_code_t cuda_irq_code = {
-	sizeof(cuda_ranges) / sizeof(irq_pio_range_t),
-	cuda_ranges,
-	sizeof(cuda_cmds) / sizeof(irq_cmd_t),
-	cuda_cmds
-};
-
-static int cuda_dev_create(cuda_t *cuda, const char *name, adb_dev_t **rdev)
-{
-	adb_dev_t *dev = NULL;
-	ddf_fun_t *fun;
-	int rc;
-
-	fun = ddf_fun_create(cuda->dev, fun_exposed, name);
-	if (fun == NULL) {
-		ddf_msg(LVL_ERROR, "Failed creating function '%s'.", name);
-		rc = ENOMEM;
-		goto error;
-	}
-
-	dev = ddf_fun_data_alloc(fun, sizeof(adb_dev_t));
-	if (dev == NULL) {
-		ddf_msg(LVL_ERROR, "Failed allocating memory for '%s'.", name);
-		rc = ENOMEM;
-		goto error;
-	}
-
-	dev->fun = fun;
-	list_append(&dev->lcuda, &cuda->devs);
-
-	ddf_fun_set_conn_handler(fun, cuda_dev_connection);
-
-	rc = ddf_fun_bind(fun);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed binding function '%s'.", name);
-		goto error;
-	}
-
-	*rdev = dev;
-	return EOK;
-error:
-	if (fun != NULL)
-		ddf_fun_destroy(fun);
-	return rc;
-}
-
-int cuda_add(cuda_t *cuda, cuda_res_t *res)
-{
-	adb_dev_t *kbd = NULL;
-	adb_dev_t *mouse = NULL;
-	int rc;
-
-	cuda->phys_base = res->base;
-
-	rc = cuda_dev_create(cuda, "kbd", &kbd);
-	if (rc != EOK)
-		goto error;
-
-	rc = cuda_dev_create(cuda, "mouse", &mouse);
-	if (rc != EOK)
-		goto error;
-
-	cuda->addr_dev[2] = kbd;
-	cuda->addr_dev[8] = kbd;
-
-	cuda->addr_dev[9] = mouse;
-
-	rc = cuda_init(cuda);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed initializing CUDA hardware.");
-		return rc;
-	}
-
-	return EOK;
-error:
-	return rc;
-}
-
-int cuda_remove(cuda_t *cuda)
-{
-	return ENOTSUP;
-}
-
-int cuda_gone(cuda_t *cuda)
-{
-	return ENOTSUP;
-}
-
-/** Device connection handler */
-static void cuda_dev_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	adb_dev_t *dev = (adb_dev_t *) ddf_fun_data_get((ddf_fun_t *) arg);
-	ipc_callid_t callid;
-	ipc_call_t call;
-	sysarg_t method;
-
-	/* Answer the IPC_M_CONNECT_ME_TO call. */
-	async_answer_0(iid, EOK);
-
-	while (true) {
-		callid = async_get_call(&call);
-		method = IPC_GET_IMETHOD(call);
-
-		if (!method) {
-			/* The other side has hung up. */
-			async_answer_0(callid, EOK);
-			return;
-		}
-
-		async_sess_t *sess =
-		    async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
-		if (sess != NULL) {
-			dev->client_sess = sess;
-			async_answer_0(callid, EOK);
-		} else {
-			async_answer_0(callid, EINVAL);
-		}
-	}
-}
-
-static int cuda_init(cuda_t *cuda)
-{
-	int rc;
-
-	void *vaddr;
-	rc = pio_enable((void *) cuda->phys_base, sizeof(cuda_regs_t),
-	    &vaddr);
-	if (rc != EOK)
-		return rc;
-
-	cuda->regs = vaddr;
-	cuda->xstate = cx_listen;
-	cuda->bidx = 0;
-	cuda->snd_bytes = 0;
-
-	fibril_mutex_initialize(&cuda->dev_lock);
-
-	/* Disable all interrupts from CUDA. */
-	pio_write_8(&cuda->regs->ier, IER_CLR | ALL_INT);
-
-	cuda_irq_code.ranges[0].base = (uintptr_t) cuda->phys_base;
-	cuda_irq_code.cmds[0].addr = (void *) &((cuda_regs_t *)
-	    cuda->phys_base)->ifr;
-	async_irq_subscribe(10, cuda_irq_handler, cuda, &cuda_irq_code);
-
-	/* Enable SR interrupt. */
-	pio_write_8(&cuda->regs->ier, TIP | TREQ);
-	pio_write_8(&cuda->regs->ier, IER_SET | SR_INT);
-
-	/* Enable ADB autopolling. */
-	cuda_autopoll_set(cuda, true);
-
-	return EOK;
-}
-
-static void cuda_irq_handler(ipc_callid_t iid, ipc_call_t *call, void *arg)
-{
-	uint8_t rbuf[CUDA_RCV_BUF_SIZE];
-	cuda_t *cuda = (cuda_t *)arg;
-	size_t len;
-	bool handle;
-
-	handle = false;
-	len = 0;
-
-	fibril_mutex_lock(&cuda->dev_lock);
-
-	switch (cuda->xstate) {
-	case cx_listen:
-		cuda_irq_listen(cuda);
-		break;
-	case cx_receive:
-		cuda_irq_receive(cuda);
-		break;
-	case cx_rcv_end:
-		cuda_irq_rcv_end(cuda, rbuf, &len);
-		handle = true;
-		break;
-	case cx_send_start:
-		cuda_irq_send_start(cuda);
-		break;
-	case cx_send:
-		cuda_irq_send(cuda);
-		break;
-	}
-
-	/* Lower IFR.SR_INT so that CUDA can generate next int by raising it. */
-	pio_write_8(&cuda->regs->ifr, SR_INT);
-
-	fibril_mutex_unlock(&cuda->dev_lock);
-
-	/* Handle an incoming packet. */
-	if (handle)
-		cuda_packet_handle(cuda, rbuf, len);
-}
-
-/** Interrupt in listen state.
- *
- * Start packet reception.
- *
- * @param cuda CUDA instance
- */
-static void cuda_irq_listen(cuda_t *cuda)
-{
-	uint8_t b = pio_read_8(&cuda->regs->b);
-
-	if ((b & TREQ) != 0) {
-		ddf_msg(LVL_WARN, "cuda_irq_listen: no TREQ?!");
-		return;
-	}
-
-	pio_write_8(&cuda->regs->b, b & ~TIP);
-	cuda->xstate = cx_receive;
-}
-
-/** Interrupt in receive state.
- *
- * Receive next byte of packet.
- *
- * @param cuda CUDA instance
- */
-static void cuda_irq_receive(cuda_t *cuda)
-{
-	uint8_t data = pio_read_8(&cuda->regs->sr);
-	if (cuda->bidx < CUDA_RCV_BUF_SIZE)
-		cuda->rcv_buf[cuda->bidx++] = data;
-
-	uint8_t b = pio_read_8(&cuda->regs->b);
-
-	if ((b & TREQ) == 0) {
-		pio_write_8(&cuda->regs->b, b ^ TACK);
-	} else {
-		pio_write_8(&cuda->regs->b, b | TACK | TIP);
-		cuda->xstate = cx_rcv_end;
-	}
-}
-
-/** Interrupt in rcv_end state.
- *
- * Terminate packet reception. Either go back to listen state or start
- * receiving another packet if CUDA has one for us.
- *
- * @param cuda CUDA instance
- * @param buf Buffer for storing received packet
- * @param len Place to store length of received packet
- */
-static void cuda_irq_rcv_end(cuda_t *cuda, void *buf, size_t *len)
-{
-	uint8_t b = pio_read_8(&cuda->regs->b);
-
-	if ((b & TREQ) == 0) {
-		cuda->xstate = cx_receive;
-		pio_write_8(&cuda->regs->b, b & ~TIP);
-	} else {
-		cuda->xstate = cx_listen;
-		cuda_send_start(cuda);
-	}
-
-	memcpy(buf, cuda->rcv_buf, cuda->bidx);
-	*len = cuda->bidx;
-	cuda->bidx = 0;
-}
-
-/** Interrupt in send_start state.
- *
- * Process result of sending first byte (and send second on success).
- *
- * @param cuda CUDA instance
- */
-static void cuda_irq_send_start(cuda_t *cuda)
-{
-	uint8_t b;
-
-	b = pio_read_8(&cuda->regs->b);
-
-	if ((b & TREQ) == 0) {
-		/* Collision */
-		pio_write_8(&cuda->regs->acr, pio_read_8(&cuda->regs->acr) &
-		    ~SR_OUT);
-		pio_read_8(&cuda->regs->sr);
-		pio_write_8(&cuda->regs->b, pio_read_8(&cuda->regs->b) |
-		    TIP | TACK);
-		cuda->xstate = cx_listen;
-		return;
-	}
-
-	pio_write_8(&cuda->regs->sr, cuda->snd_buf[1]);
-	pio_write_8(&cuda->regs->b, pio_read_8(&cuda->regs->b) ^ TACK);
-	cuda->bidx = 2;
-
-	cuda->xstate = cx_send;
-}
-
-/** Interrupt in send state.
- *
- * Send next byte or terminate transmission.
- *
- * @param cuda CUDA instance
- */
-static void cuda_irq_send(cuda_t *cuda)
-{
-	if (cuda->bidx < cuda->snd_bytes) {
-		/* Send next byte. */
-		pio_write_8(&cuda->regs->sr,
-		    cuda->snd_buf[cuda->bidx++]);
-		pio_write_8(&cuda->regs->b, pio_read_8(&cuda->regs->b) ^ TACK);
-		return;
-	}
-
-	/* End transfer. */
-	cuda->snd_bytes = 0;
-	cuda->bidx = 0;
-
-	pio_write_8(&cuda->regs->acr, pio_read_8(&cuda->regs->acr) & ~SR_OUT);
-	pio_read_8(&cuda->regs->sr);
-	pio_write_8(&cuda->regs->b, pio_read_8(&cuda->regs->b) | TACK | TIP);
-
-	cuda->xstate = cx_listen;
-	/* TODO: Match reply with request. */
-}
-
-static void cuda_packet_handle(cuda_t *cuda, uint8_t *data, size_t len)
-{
-	if (data[0] != PT_ADB)
-		return;
-	if (len < 2)
-		return;
-
-	adb_packet_handle(cuda, data + 2, len - 2, (data[1] & 0x40) != 0);
-}
-
-static void adb_packet_handle(cuda_t *cuda, uint8_t *data, size_t size,
-    bool autopoll)
-{
-	uint8_t dev_addr;
-	uint8_t reg_no;
-	uint16_t reg_val;
-	adb_dev_t *dev;
-	unsigned i;
-
-	dev_addr = data[0] >> 4;
-	reg_no = data[0] & 0x03;
-
-	if (size != 3) {
-		ddf_msg(LVL_WARN, "Unrecognized packet, size=%zu", size);
-		for (i = 0; i < size; ++i) {
-			ddf_msg(LVL_WARN, "  0x%02x", data[i]);
-		}
-		return;
-	}
-
-	if (reg_no != 0) {
-		ddf_msg(LVL_WARN, "Unrecognized packet, size=%zu", size);
-		for (i = 0; i < size; ++i) {
-			ddf_msg(LVL_WARN, "  0x%02x", data[i]);
-		}
-		return;
-	}
-
-	reg_val = ((uint16_t) data[1] << 8) | (uint16_t) data[2];
-
-	ddf_msg(LVL_DEBUG, "Received ADB packet for device address %d",
-	    dev_addr);
-	dev = cuda->addr_dev[dev_addr];
-	if (dev == NULL)
-		return;
-
-	async_exch_t *exch = async_exchange_begin(dev->client_sess);
-	async_msg_1(exch, ADB_REG_NOTIF, reg_val);
-	async_exchange_end(exch);
-}
-
-static void cuda_autopoll_set(cuda_t *cuda, bool enable)
-{
-	cuda->snd_buf[0] = PT_CUDA;
-	cuda->snd_buf[1] = CPT_AUTOPOLL;
-	cuda->snd_buf[2] = enable ? 0x01 : 0x00;
-	cuda->snd_bytes = 3;
-	cuda->bidx = 0;
-
-	cuda_send_start(cuda);
-}
-
-static void cuda_send_start(cuda_t *cuda)
-{
-	assert(cuda->xstate == cx_listen);
-
-	if (cuda->snd_bytes == 0)
-		return;
-
-	/* Check for incoming data. */
-	if ((pio_read_8(&cuda->regs->b) & TREQ) == 0)
-		return;
-
-	pio_write_8(&cuda->regs->acr, pio_read_8(&cuda->regs->acr) | SR_OUT);
-	pio_write_8(&cuda->regs->sr, cuda->snd_buf[0]);
-	pio_write_8(&cuda->regs->b, pio_read_8(&cuda->regs->b) & ~TIP);
-
-	cuda->xstate = cx_send_start;
-}
-
-/** @}
- */
Index: pace/drv/bus/adb/cuda_adb/cuda_adb.h
===================================================================
--- uspace/drv/bus/adb/cuda_adb/cuda_adb.h	(revision 81b9d3ed6af6996e5039aa44755f6f7a9b396e2f)
+++ 	(revision )
@@ -1,96 +1,0 @@
-/*
- * Copyright (c) 2006 Martin Decky
- * Copyright (c) 2010 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 genarch
- * @{
- */
-/** @file
- */
-
-#ifndef CUDA_ADB_H_
-#define CUDA_ADB_H_
-
-#include <adt/list.h>
-#include <async.h>
-#include <ddf/driver.h>
-#include <fibril_synch.h>
-#include <loc.h>
-#include <stdint.h>
-#include "cuda_hw.h"
-
-enum {
-	CUDA_RCV_BUF_SIZE = 5
-};
-
-enum cuda_xfer_state {
-	cx_listen,
-	cx_receive,
-	cx_rcv_end,
-	cx_send_start,
-	cx_send
-};
-
-typedef struct {
-	uintptr_t base;
-	int irq;
-} cuda_res_t;
-
-/** ADB bus device */
-typedef struct {
-	ddf_fun_t *fun;
-	async_sess_t *client_sess;
-	link_t lcuda;
-	struct cuda *cuda;
-} adb_dev_t;
-
-/** CUDA ADB bus */
-typedef struct cude {
-	struct cuda_regs *regs;
-	uintptr_t phys_base;
-	ddf_dev_t *dev;
-
-	uint8_t rcv_buf[CUDA_RCV_BUF_SIZE];
-	uint8_t snd_buf[CUDA_RCV_BUF_SIZE];
-	size_t bidx;
-	size_t snd_bytes;
-	enum cuda_xfer_state xstate;
-	fibril_mutex_t dev_lock;
-
-	list_t devs;
-	adb_dev_t *addr_dev[ADB_MAX_ADDR];
-} cuda_t;
-
-extern int cuda_add(cuda_t *, cuda_res_t *);
-extern int cuda_remove(cuda_t *);
-extern int cuda_gone(cuda_t *);
-
-#endif
-
-/** @}
- */
Index: pace/drv/bus/adb/cuda_adb/cuda_adb.ma
===================================================================
--- uspace/drv/bus/adb/cuda_adb/cuda_adb.ma	(revision 81b9d3ed6af6996e5039aa44755f6f7a9b396e2f)
+++ 	(revision )
@@ -1,1 +1,0 @@
-10 cuda_adb
Index: pace/drv/bus/adb/cuda_adb/cuda_hw.h
===================================================================
--- uspace/drv/bus/adb/cuda_adb/cuda_hw.h	(revision 81b9d3ed6af6996e5039aa44755f6f7a9b396e2f)
+++ 	(revision )
@@ -1,130 +1,0 @@
-/*
- * Copyright (c) 2006 Martin Decky
- * Copyright (c) 2010 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 genarch
- * @{
- */
-/** @file
- */
-
-#ifndef CUDA_HW_H_
-#define CUDA_HW_H_
-
-#include <stdint.h>
-
-typedef struct cuda_regs {
-	uint8_t b;
-	uint8_t pad0[0x1ff];
-
-	uint8_t a;
-	uint8_t pad1[0x1ff];
-
-	uint8_t dirb;
-	uint8_t pad2[0x1ff];
-
-	uint8_t dira;
-	uint8_t pad3[0x1ff];
-
-	uint8_t t1cl;
-	uint8_t pad4[0x1ff];
-
-	uint8_t t1ch;
-	uint8_t pad5[0x1ff];
-
-	uint8_t t1ll;
-	uint8_t pad6[0x1ff];
-
-	uint8_t t1lh;
-	uint8_t pad7[0x1ff];
-
-	uint8_t t2cl;
-	uint8_t pad8[0x1ff];
-
-	uint8_t t2ch;
-	uint8_t pad9[0x1ff];
-
-	uint8_t sr;
-	uint8_t pad10[0x1ff];
-
-	uint8_t acr;
-	uint8_t pad11[0x1ff];
-
-	uint8_t pcr;
-	uint8_t pad12[0x1ff];
-
-	uint8_t ifr;
-	uint8_t pad13[0x1ff];
-
-	uint8_t ier;
-	uint8_t pad14[0x1ff];
-
-	uint8_t anh;
-	uint8_t pad15[0x1ff];
-} cuda_regs_t;
-
-/** B register fields */
-enum {
-	TREQ	= 0x08,
-	TACK	= 0x10,
-	TIP	= 0x20
-};
-
-/** IER register fields */
-enum {
-	IER_CLR	= 0x00,
-	IER_SET	= 0x80,
-
-	SR_INT	= 0x04,
-	ALL_INT	= 0x7f
-};
-
-/** ACR register fields */
-enum {
-	SR_OUT	= 0x10
-};
-
-/** Packet types */
-enum {
-	PT_ADB	= 0x00,
-	PT_CUDA	= 0x01
-};
-
-/** CUDA packet types */
-enum {
-	CPT_AUTOPOLL	= 0x01
-};
-
-enum {
-	ADB_MAX_ADDR	= 16
-};
-
-#endif
-
-/** @}
- */
Index: pace/drv/bus/adb/cuda_adb/main.c
===================================================================
--- uspace/drv/bus/adb/cuda_adb/main.c	(revision 81b9d3ed6af6996e5039aa44755f6f7a9b396e2f)
+++ 	(revision )
@@ -1,162 +1,0 @@
-/*
- * Copyright (c) 2017 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 genarch
- * @{
- */
-/** @file VIA-CUDA Apple Desktop Bus driver
- */
-
-#include <ddf/driver.h>
-#include <ddf/log.h>
-#include <device/hw_res_parsed.h>
-#include <errno.h>
-#include <stdio.h>
-
-#include "cuda_adb.h"
-
-#define NAME  "cuda_adb"
-
-static int cuda_dev_add(ddf_dev_t *dev);
-static int cuda_dev_remove(ddf_dev_t *dev);
-static int cuda_dev_gone(ddf_dev_t *dev);
-static int cuda_fun_online(ddf_fun_t *fun);
-static int cuda_fun_offline(ddf_fun_t *fun);
-
-static driver_ops_t driver_ops = {
-	.dev_add = cuda_dev_add,
-	.dev_remove = cuda_dev_remove,
-	.dev_gone = cuda_dev_gone,
-	.fun_online = cuda_fun_online,
-	.fun_offline = cuda_fun_offline
-};
-
-static driver_t cuda_adb_driver = {
-	.name = NAME,
-	.driver_ops = &driver_ops
-};
-
-static int cuda_get_res(ddf_dev_t *dev, cuda_res_t *res)
-{
-	async_sess_t *parent_sess;
-	hw_res_list_parsed_t hw_res;
-	int rc;
-
-	parent_sess = ddf_dev_parent_sess_create(dev);
-	if (parent_sess == NULL)
-		return ENOMEM;
-
-	hw_res_list_parsed_init(&hw_res);
-	rc = hw_res_get_list_parsed(parent_sess, &hw_res, 0);
-	if (rc != EOK)
-		return rc;
-
-	if (hw_res.io_ranges.count != 1) {
-		rc = EINVAL;
-		goto error;
-	}
-
-	res->base = RNGABS(hw_res.io_ranges.ranges[0]);
-
-	if (hw_res.irqs.count != 1) {
-		rc = EINVAL;
-		goto error;
-	}
-
-	res->irq = hw_res.irqs.irqs[0];
-
-	return EOK;
-error:
-	hw_res_list_parsed_clean(&hw_res);
-	return rc;
-}
-
-static int cuda_dev_add(ddf_dev_t *dev)
-{
-	cuda_t *cuda;
-	cuda_res_t cuda_res;
-	int rc;
-
-        ddf_msg(LVL_DEBUG, "cuda_dev_add(%p)", dev);
-	cuda = ddf_dev_data_alloc(dev, sizeof(cuda_t));
-	if (cuda == NULL) {
-		ddf_msg(LVL_ERROR, "Failed allocating soft state.");
-		return ENOMEM;
-	}
-
-	cuda->dev = dev;
-	list_initialize(&cuda->devs);
-
-	rc = cuda_get_res(dev, &cuda_res);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed getting hardware resource list.\n");
-		return EIO;
-	}
-
-	return cuda_add(cuda, &cuda_res);
-}
-
-static int cuda_dev_remove(ddf_dev_t *dev)
-{
-        cuda_t *cuda = (cuda_t *)ddf_dev_data_get(dev);
-
-        ddf_msg(LVL_DEBUG, "cuda_dev_remove(%p)", dev);
-
-        return cuda_remove(cuda);
-}
-
-static int cuda_dev_gone(ddf_dev_t *dev)
-{
-        cuda_t *cuda = (cuda_t *)ddf_dev_data_get(dev);
-
-        ddf_msg(LVL_DEBUG, "cuda_dev_gone(%p)", dev);
-
-        return cuda_gone(cuda);
-}
-
-static int cuda_fun_online(ddf_fun_t *fun)
-{
-        ddf_msg(LVL_DEBUG, "cuda_fun_online()");
-        return ddf_fun_online(fun);
-}
-
-static int cuda_fun_offline(ddf_fun_t *fun)
-{
-        ddf_msg(LVL_DEBUG, "cuda_fun_offline()");
-        return ddf_fun_offline(fun);
-}
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": VIA-CUDA Apple Desktop Bus driver\n");
-	ddf_log_init(NAME);
-	return ddf_driver_main(&cuda_adb_driver);
-}
-
-/** @}
- */
Index: uspace/drv/platform/mac/mac.c
===================================================================
--- uspace/drv/platform/mac/mac.c	(revision 81b9d3ed6af6996e5039aa44755f6f7a9b396e2f)
+++ uspace/drv/platform/mac/mac.c	(revision 84eb4edda850471e7ed12ca3028b9662df14cc3d)
@@ -1,5 +1,4 @@
 /*
  * Copyright (c) 2011 Martin Decky
- * Copyright (c) 2017 Jiri Svoboda
  * All rights reserved.
  *
@@ -41,7 +40,5 @@
 #include <errno.h>
 #include <ops/hw_res.h>
-#include <ops/pio_window.h>
 #include <stdio.h>
-#include <sysinfo.h>
 
 #define NAME  "mac"
@@ -49,37 +46,5 @@
 typedef struct {
 	hw_resource_list_t hw_resources;
-	pio_window_t pio_window;
 } mac_fun_t;
-
-static hw_resource_t adb_res[] = {
-	{
-		.type = IO_RANGE,
-		.res.io_range = {
-			.address = 0,
-			.size = 0x2000,
-			.relative = true,
-			.endianness = BIG_ENDIAN
-		}
-	},
-	{
-		.type = INTERRUPT,
-		.res.interrupt = {
-			.irq = 0 /* patched at run time */
-		}
-	},
-};
-
-static mac_fun_t adb_data = {
-	.hw_resources = {
-		sizeof(adb_res) / sizeof(adb_res[0]),
-		adb_res
-	},
-	.pio_window = {
-		.io = {
-			.base = 0, /* patched at run time */
-			.size = 0x2000
-		}
-	}
-};
 
 static hw_resource_t pci_conf_regs[] = {
@@ -114,13 +79,7 @@
 
 /** Obtain function soft-state from DDF function node */
-static mac_fun_t *mac_fun(ddf_fun_t *ddf_fun)
+static mac_fun_t *mac_fun(ddf_fun_t *fnode)
 {
-	return ddf_fun_data_get(ddf_fun);
-}
-
-static pio_window_t *mac_get_pio_window(ddf_fun_t *ddf_fun)
-{
-	mac_fun_t *fun = mac_fun(ddf_fun);
-	return &fun->pio_window;
+	return ddf_fun_data_get(fnode);
 }
 
@@ -129,5 +88,4 @@
 {
 	ddf_msg(LVL_DEBUG, "Adding new function '%s'.", name);
-	printf("mac: Adding new function '%s'.\n", name);
 	
 	ddf_fun_t *fnode = NULL;
@@ -156,5 +114,4 @@
 	}
 	
-	printf("mac: Added new function '%s' (str=%s).\n", name, str_match_id);
 	return true;
 	
@@ -178,31 +135,13 @@
 static int mac_dev_add(ddf_dev_t *dev)
 {
-	int rc;
-	uintptr_t cuda_physical;
-	sysarg_t cuda_inr;
 #if 0
 	/* Register functions */
-	if (!mac_add_fun(dev, "pci0", "intel_pci", &pci_data)) {
-		ddf_msg(LVL_ERROR, "Failed to add PCI function for Mac platform.");
-		return EIO;
-	}
+	if (!mac_add_fun(dev, "pci0", "intel_pci", &pci_data))
+		ddf_msg(LVL_ERROR, "Failed to add functions for Mac platform.");
 #else
 	(void)pci_data;
+	(void)mac_add_fun;
 #endif
-	rc = sysinfo_get_value("cuda.address.physical", &cuda_physical);
-	if (rc != EOK)
-		return EIO;
-	rc = sysinfo_get_value("cuda.inr", &cuda_inr);
-	if (rc != EOK)
-		return EIO;
-
-	adb_data.pio_window.io.base = cuda_physical;
-	adb_res[1].res.interrupt.irq = cuda_inr;
-
-	if (!mac_add_fun(dev, "adb", "cuda_adb", &adb_data)) {
-		ddf_msg(LVL_ERROR, "Failed to add ADB function for Mac platform.");
-		return EIO;
-	}
-
+	
 	return EOK;
 }
@@ -234,8 +173,4 @@
 }
 
-static pio_window_ops_t fun_pio_window_ops = {
-        .get_pio_window = &mac_get_pio_window
-};
-
 static hw_res_ops_t fun_hw_res_ops = {
    	.get_resource_list = &mac_get_resources,
@@ -248,5 +183,4 @@
 	ddf_log_init(NAME);
 	mac_fun_ops.interfaces[HW_RES_DEV_IFACE] = &fun_hw_res_ops;
-	mac_fun_ops.interfaces[PIO_WINDOW_DEV_IFACE] = &fun_pio_window_ops;
 	return ddf_driver_main(&mac_driver);
 }
Index: uspace/srv/hid/input/port/adb.c
===================================================================
--- uspace/srv/hid/input/port/adb.c	(revision 81b9d3ed6af6996e5039aa44755f6f7a9b396e2f)
+++ uspace/srv/hid/input/port/adb.c	(revision 84eb4edda850471e7ed12ca3028b9662df14cc3d)
@@ -62,7 +62,7 @@
 	kbd_dev = kdev;
 	
-	const char *dev = "devices/\\hw\\adb\\kbd";
+	const char *dev = "adb/kbd";
 	service_id_t service_id;
-	int rc = loc_service_get_id(dev, &service_id, IPC_FLAG_BLOCKING);
+	int rc = loc_service_get_id(dev, &service_id, 0);
 	if (rc != EOK)
 		return rc;
Index: uspace/srv/hid/input/port/adb_mouse.c
===================================================================
--- uspace/srv/hid/input/port/adb_mouse.c	(revision 81b9d3ed6af6996e5039aa44755f6f7a9b396e2f)
+++ uspace/srv/hid/input/port/adb_mouse.c	(revision 84eb4edda850471e7ed12ca3028b9662df14cc3d)
@@ -75,10 +75,10 @@
 static int adb_port_init(mouse_dev_t *mdev)
 {
-	const char *dev = "devices/\\hw\\adb\\mouse";
+	const char *dev = "adb/mouse";
 	
 	mouse_dev = mdev;
 	
 	service_id_t service_id;
-	int rc = loc_service_get_id(dev, &service_id, IPC_FLAG_BLOCKING);
+	int rc = loc_service_get_id(dev, &service_id, 0);
 	if (rc != EOK)
 		return rc;
Index: uspace/srv/hw/bus/cuda_adb/Makefile
===================================================================
--- uspace/srv/hw/bus/cuda_adb/Makefile	(revision 84eb4edda850471e7ed12ca3028b9662df14cc3d)
+++ uspace/srv/hw/bus/cuda_adb/Makefile	(revision 84eb4edda850471e7ed12ca3028b9662df14cc3d)
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 2010 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.
+#
+
+USPACE_PREFIX = ../../../..
+BINARY = cuda_adb
+
+SOURCES = \
+	cuda_adb.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/hw/bus/cuda_adb/cuda_adb.c
===================================================================
--- uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision 84eb4edda850471e7ed12ca3028b9662df14cc3d)
+++ uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision 84eb4edda850471e7ed12ca3028b9662df14cc3d)
@@ -0,0 +1,498 @@
+/*
+ * Copyright (c) 2010 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 genarch
+ * @{
+ */
+/** @file VIA-CUDA Apple Desktop Bus driver
+ *
+ * Note: We should really do a full bus scan at the beginning and resolve
+ * address conflicts. Also we should consider the handler ID in r3. Instead
+ * we just assume a keyboard at address 2 or 8 and a mouse at address 9.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <ddi.h>
+#include <libarch/ddi.h>
+#include <loc.h>
+#include <sysinfo.h>
+#include <errno.h>
+#include <ipc/adb.h>
+#include <assert.h>
+#include "cuda_adb.h"
+#include "cuda_hw.h"
+
+#define NAME  "cuda_adb"
+
+static void cuda_connection(ipc_callid_t, ipc_call_t *, void *);
+static int cuda_init(cuda_instance_t *);
+static void cuda_irq_handler(ipc_callid_t, ipc_call_t *, void *);
+
+static void cuda_irq_listen(cuda_instance_t *);
+static void cuda_irq_receive(cuda_instance_t *);
+static void cuda_irq_rcv_end(cuda_instance_t *, void *, size_t *);
+static void cuda_irq_send_start(cuda_instance_t *);
+static void cuda_irq_send(cuda_instance_t *);
+
+static void cuda_packet_handle(cuda_instance_t *, uint8_t *, size_t);
+static void cuda_send_start(cuda_instance_t *);
+static void cuda_autopoll_set(cuda_instance_t *, bool);
+
+static void adb_packet_handle(cuda_instance_t *, uint8_t *, size_t, bool);
+
+static irq_pio_range_t cuda_ranges[] = {
+	{
+		.base = 0,
+		.size = sizeof(cuda_t)
+	}
+};
+
+static irq_cmd_t cuda_cmds[] = {
+	{
+		.cmd = CMD_PIO_READ_8,
+		.addr = NULL,
+		.dstarg = 1
+	},
+	{
+		.cmd = CMD_AND,
+		.value = SR_INT,
+		.srcarg = 1,
+		.dstarg = 2
+	},
+	{
+		.cmd = CMD_PREDICATE,
+		.value = 1,
+		.srcarg = 2
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
+
+
+static irq_code_t cuda_irq_code = {
+	sizeof(cuda_ranges) / sizeof(irq_pio_range_t),
+	cuda_ranges,
+	sizeof(cuda_cmds) / sizeof(irq_cmd_t),
+	cuda_cmds
+};
+
+int main(int argc, char *argv[])
+{
+	service_id_t service_id;
+	cuda_instance_t cinst;
+	int rc;
+	int i;
+
+	printf(NAME ": VIA-CUDA Apple Desktop Bus driver\n");
+	
+	for (i = 0; i < ADB_MAX_ADDR; ++i) {
+		cinst.adb_dev[i].client_sess = NULL;
+		cinst.adb_dev[i].service_id = 0;
+	}
+
+	async_set_fallback_port_handler(cuda_connection, &cinst);
+	rc = loc_server_register(NAME);
+	if (rc < 0) {
+		printf(NAME ": Unable to register server.\n");
+		return rc;
+	}
+
+	rc = loc_service_register("adb/kbd", &service_id);
+	if (rc != EOK) {
+		printf(NAME ": Unable to register service %s.\n", "adb/kbd");
+		return rc;
+	}
+
+	cinst.adb_dev[2].service_id = service_id;
+	cinst.adb_dev[8].service_id = service_id;
+
+	rc = loc_service_register("adb/mouse", &service_id);
+	if (rc != EOK) {
+		printf(NAME ": Unable to register service %s.\n", "adb/mouse");
+		return rc;
+	}
+
+	cinst.adb_dev[9].service_id = service_id;
+
+	if (cuda_init(&cinst) < 0) {
+		printf("cuda_init() failed\n");
+		return 1;
+	}
+
+	task_retval(0);
+	async_manager();
+
+	return 0;
+}
+
+/** Character device connection handler */
+static void cuda_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	ipc_callid_t callid;
+	ipc_call_t call;
+	sysarg_t method;
+	service_id_t dsid;
+	cuda_instance_t *cuda = (cuda_instance_t *) arg;
+	int dev_addr, i;
+
+	/* Get the device handle. */
+	dsid = IPC_GET_ARG2(*icall);
+
+	/* Determine which disk device is the client connecting to. */
+	dev_addr = -1;
+	for (i = 0; i < ADB_MAX_ADDR; i++) {
+		if (cuda->adb_dev[i].service_id == dsid)
+			dev_addr = i;
+	}
+
+	if (dev_addr < 0) {
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	/* Answer the IPC_M_CONNECT_ME_TO call. */
+	async_answer_0(iid, EOK);
+
+	while (true) {
+		callid = async_get_call(&call);
+		method = IPC_GET_IMETHOD(call);
+		
+		if (!method) {
+			/* The other side has hung up. */
+			async_answer_0(callid, EOK);
+			return;
+		}
+		
+		async_sess_t *sess =
+		    async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
+		if (sess != NULL) {
+			if (cuda->adb_dev[dev_addr].client_sess == NULL) {
+				cuda->adb_dev[dev_addr].client_sess = sess;
+				
+				/*
+				 * A hack so that we send the data to the session
+				 * regardless of which address the device is on.
+				 */
+				for (i = 0; i < ADB_MAX_ADDR; ++i) {
+					if (cuda->adb_dev[i].service_id == dsid)
+						cuda->adb_dev[i].client_sess = sess;
+				}
+				
+				async_answer_0(callid, EOK);
+			} else
+				async_answer_0(callid, ELIMIT);
+		} else
+			async_answer_0(callid, EINVAL);
+	}
+}
+
+static int cuda_init(cuda_instance_t *cuda)
+{
+	if (sysinfo_get_value("cuda.address.physical", &(cuda->cuda_physical)) != EOK)
+		return -1;
+	
+	void *vaddr;
+	if (pio_enable((void *) cuda->cuda_physical, sizeof(cuda_t), &vaddr) != 0)
+		return -1;
+	
+	cuda->regs = vaddr;
+	cuda->xstate = cx_listen;
+	cuda->bidx = 0;
+	cuda->snd_bytes = 0;
+
+	fibril_mutex_initialize(&cuda->dev_lock);
+
+	/* Disable all interrupts from CUDA. */
+	pio_write_8(&cuda->regs->ier, IER_CLR | ALL_INT);
+
+	cuda_irq_code.ranges[0].base = (uintptr_t) cuda->cuda_physical;
+	cuda_irq_code.cmds[0].addr = (void *) &((cuda_t *) cuda->cuda_physical)->ifr;
+	async_irq_subscribe(10, cuda_irq_handler, cuda, &cuda_irq_code);
+
+	/* Enable SR interrupt. */
+	pio_write_8(&cuda->regs->ier, TIP | TREQ);
+	pio_write_8(&cuda->regs->ier, IER_SET | SR_INT);
+
+	/* Enable ADB autopolling. */
+	cuda_autopoll_set(cuda, true);
+
+	return 0;
+}
+
+static void cuda_irq_handler(ipc_callid_t iid, ipc_call_t *call, void *arg)
+{
+	uint8_t rbuf[CUDA_RCV_BUF_SIZE];
+	cuda_instance_t *cuda = (cuda_instance_t *)arg;
+	size_t len;
+	bool handle;
+
+	handle = false;
+	len = 0;
+
+	fibril_mutex_lock(&cuda->dev_lock);
+
+	switch (cuda->xstate) {
+	case cx_listen:
+		cuda_irq_listen(cuda);
+		break;
+	case cx_receive:
+		cuda_irq_receive(cuda);
+		break;
+	case cx_rcv_end:
+		cuda_irq_rcv_end(cuda, rbuf, &len);
+		handle = true;
+		break;
+	case cx_send_start:
+		cuda_irq_send_start(cuda);
+		break;
+	case cx_send:
+		cuda_irq_send(cuda);
+		break;
+	}
+	
+	/* Lower IFR.SR_INT so that CUDA can generate next int by raising it. */
+	pio_write_8(&cuda->regs->ifr, SR_INT);
+
+	fibril_mutex_unlock(&cuda->dev_lock);
+
+	/* Handle an incoming packet. */
+	if (handle)
+		cuda_packet_handle(cuda, rbuf, len);
+}
+
+/** Interrupt in listen state.
+ *
+ * Start packet reception.
+ *
+ * @param cuda CUDA instance
+ */
+static void cuda_irq_listen(cuda_instance_t *cuda)
+{
+	uint8_t b = pio_read_8(&cuda->regs->b);
+	
+	if ((b & TREQ) != 0) {
+		printf("cuda_irq_listen: no TREQ?!\n");
+		return;
+	}
+	
+	pio_write_8(&cuda->regs->b, b & ~TIP);
+	cuda->xstate = cx_receive;
+}
+
+/** Interrupt in receive state.
+ *
+ * Receive next byte of packet.
+ *
+ * @param cuda CUDA instance
+ */
+static void cuda_irq_receive(cuda_instance_t *cuda)
+{
+	uint8_t data = pio_read_8(&cuda->regs->sr);
+	if (cuda->bidx < CUDA_RCV_BUF_SIZE)
+		cuda->rcv_buf[cuda->bidx++] = data;
+	
+	uint8_t b = pio_read_8(&cuda->regs->b);
+	
+	if ((b & TREQ) == 0) {
+		pio_write_8(&cuda->regs->b, b ^ TACK);
+	} else {
+		pio_write_8(&cuda->regs->b, b | TACK | TIP);
+		cuda->xstate = cx_rcv_end;
+	}
+}
+
+/** Interrupt in rcv_end state.
+ *
+ * Terminate packet reception. Either go back to listen state or start
+ * receiving another packet if CUDA has one for us.
+ *
+ * @param cuda CUDA instance
+ * @param buf Buffer for storing received packet
+ * @param len Place to store length of received packet
+ */
+static void cuda_irq_rcv_end(cuda_instance_t *cuda, void *buf, size_t *len)
+{
+	uint8_t b = pio_read_8(&cuda->regs->b);
+	
+	if ((b & TREQ) == 0) {
+		cuda->xstate = cx_receive;
+		pio_write_8(&cuda->regs->b, b & ~TIP);
+	} else {
+		cuda->xstate = cx_listen;
+		cuda_send_start(cuda);
+	}
+	
+	memcpy(buf, cuda->rcv_buf, cuda->bidx);
+	*len = cuda->bidx;
+	cuda->bidx = 0;
+}
+
+/** Interrupt in send_start state.
+ *
+ * Process result of sending first byte (and send second on success).
+ *
+ * @param cuda CUDA instance
+ */
+static void cuda_irq_send_start(cuda_instance_t *cuda)
+{
+	uint8_t b;
+
+	b = pio_read_8(&cuda->regs->b);
+
+	if ((b & TREQ) == 0) {
+		/* Collision */
+		pio_write_8(&cuda->regs->acr, pio_read_8(&cuda->regs->acr) &
+		    ~SR_OUT);
+		pio_read_8(&cuda->regs->sr);
+		pio_write_8(&cuda->regs->b, pio_read_8(&cuda->regs->b) |
+		    TIP | TACK);
+		cuda->xstate = cx_listen;
+		return;
+	}
+
+	pio_write_8(&cuda->regs->sr, cuda->snd_buf[1]);
+	pio_write_8(&cuda->regs->b, pio_read_8(&cuda->regs->b) ^ TACK);
+	cuda->bidx = 2;
+
+	cuda->xstate = cx_send;
+}
+
+/** Interrupt in send state.
+ *
+ * Send next byte or terminate transmission.
+ *
+ * @param cuda CUDA instance
+ */
+static void cuda_irq_send(cuda_instance_t *cuda)
+{
+	if (cuda->bidx < cuda->snd_bytes) {
+		/* Send next byte. */
+		pio_write_8(&cuda->regs->sr,
+		    cuda->snd_buf[cuda->bidx++]);
+		pio_write_8(&cuda->regs->b, pio_read_8(&cuda->regs->b) ^ TACK);
+		return;
+	}
+
+	/* End transfer. */
+	cuda->snd_bytes = 0;
+	cuda->bidx = 0;
+
+	pio_write_8(&cuda->regs->acr, pio_read_8(&cuda->regs->acr) & ~SR_OUT);
+	pio_read_8(&cuda->regs->sr);
+	pio_write_8(&cuda->regs->b, pio_read_8(&cuda->regs->b) | TACK | TIP);
+
+	cuda->xstate = cx_listen;
+	/* TODO: Match reply with request. */
+}
+
+static void cuda_packet_handle(cuda_instance_t *cuda, uint8_t *data, size_t len)
+{
+	if (data[0] != PT_ADB)
+		return;
+	if (len < 2)
+		return;
+
+	adb_packet_handle(cuda, data + 2, len - 2, (data[1] & 0x40) != 0);
+}
+
+static void adb_packet_handle(cuda_instance_t *cuda, uint8_t *data,
+    size_t size, bool autopoll)
+{
+	uint8_t dev_addr;
+	uint8_t reg_no;
+	uint16_t reg_val;
+	unsigned i;
+
+	dev_addr = data[0] >> 4;
+	reg_no = data[0] & 0x03;
+
+	if (size != 3) {
+		printf("unrecognized packet, size=%zu\n", size);
+		for (i = 0; i < size; ++i) {
+			printf(" 0x%02x", data[i]);
+		}
+		putchar('\n');
+		return;
+	}
+
+	if (reg_no != 0) {
+		printf("unrecognized packet, size=%zu\n", size);
+		for (i = 0; i < size; ++i) {
+			printf(" 0x%02x", data[i]);
+		}
+		putchar('\n');
+		return;
+	}
+
+	reg_val = ((uint16_t) data[1] << 8) | (uint16_t) data[2];
+
+	if (cuda->adb_dev[dev_addr].client_sess == NULL)
+		return;
+
+	async_exch_t *exch =
+	    async_exchange_begin(cuda->adb_dev[dev_addr].client_sess);
+	async_msg_1(exch, ADB_REG_NOTIF, reg_val);
+	async_exchange_end(exch);
+}
+
+static void cuda_autopoll_set(cuda_instance_t *cuda, bool enable)
+{
+	cuda->snd_buf[0] = PT_CUDA;
+	cuda->snd_buf[1] = CPT_AUTOPOLL;
+	cuda->snd_buf[2] = enable ? 0x01 : 0x00;
+	cuda->snd_bytes = 3;
+	cuda->bidx = 0;
+
+	cuda_send_start(cuda);
+}
+
+static void cuda_send_start(cuda_instance_t *cuda)
+{
+	assert(cuda->xstate == cx_listen);
+
+	if (cuda->snd_bytes == 0)
+		return;
+
+	/* Check for incoming data. */
+	if ((pio_read_8(&cuda->regs->b) & TREQ) == 0)
+		return;
+
+	pio_write_8(&cuda->regs->acr, pio_read_8(&cuda->regs->acr) | SR_OUT);
+	pio_write_8(&cuda->regs->sr, cuda->snd_buf[0]);
+	pio_write_8(&cuda->regs->b, pio_read_8(&cuda->regs->b) & ~TIP);
+
+	cuda->xstate = cx_send_start;
+}
+
+/** @}
+ */
Index: uspace/srv/hw/bus/cuda_adb/cuda_adb.h
===================================================================
--- uspace/srv/hw/bus/cuda_adb/cuda_adb.h	(revision 84eb4edda850471e7ed12ca3028b9662df14cc3d)
+++ uspace/srv/hw/bus/cuda_adb/cuda_adb.h	(revision 84eb4edda850471e7ed12ca3028b9662df14cc3d)
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2006 Martin Decky
+ * Copyright (c) 2010 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 genarch
+ * @{
+ */
+/** @file
+ */
+
+#ifndef CUDA_ADB_H_
+#define CUDA_ADB_H_
+
+#include <async.h>
+#include <fibril_synch.h>
+#include <stddef.h>
+#include <stdint.h>
+#include "cuda_hw.h"
+
+enum {
+	CUDA_RCV_BUF_SIZE = 5
+};
+
+enum cuda_xfer_state {
+	cx_listen,
+	cx_receive,
+	cx_rcv_end,
+	cx_send_start,
+	cx_send
+};
+
+typedef struct {
+	service_id_t service_id;
+	async_sess_t *client_sess;
+} adb_dev_t;
+
+typedef struct {
+	struct cuda *regs;
+	uintptr_t cuda_physical;
+
+	uint8_t rcv_buf[CUDA_RCV_BUF_SIZE];
+	uint8_t snd_buf[CUDA_RCV_BUF_SIZE];
+	size_t bidx;
+	size_t snd_bytes;
+	enum cuda_xfer_state xstate;
+	fibril_mutex_t dev_lock;
+
+	adb_dev_t adb_dev[ADB_MAX_ADDR];
+} cuda_instance_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/hw/bus/cuda_adb/cuda_hw.h
===================================================================
--- uspace/srv/hw/bus/cuda_adb/cuda_hw.h	(revision 84eb4edda850471e7ed12ca3028b9662df14cc3d)
+++ uspace/srv/hw/bus/cuda_adb/cuda_hw.h	(revision 84eb4edda850471e7ed12ca3028b9662df14cc3d)
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2006 Martin Decky
+ * Copyright (c) 2010 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 genarch
+ * @{
+ */
+/** @file
+ */
+
+#ifndef CUDA_HW_H_
+#define CUDA_HW_H_
+
+#include <stdint.h>
+
+typedef struct cuda {
+	uint8_t b;
+	uint8_t pad0[0x1ff];
+
+	uint8_t a;
+	uint8_t pad1[0x1ff];
+
+	uint8_t dirb;
+	uint8_t pad2[0x1ff];
+
+	uint8_t dira;
+	uint8_t pad3[0x1ff];
+
+	uint8_t t1cl;
+	uint8_t pad4[0x1ff];
+
+	uint8_t t1ch;
+	uint8_t pad5[0x1ff];
+
+	uint8_t t1ll;
+	uint8_t pad6[0x1ff];
+
+	uint8_t t1lh;
+	uint8_t pad7[0x1ff];
+
+	uint8_t t2cl;
+	uint8_t pad8[0x1ff];
+
+	uint8_t t2ch;
+	uint8_t pad9[0x1ff];
+
+	uint8_t sr;
+	uint8_t pad10[0x1ff];
+
+	uint8_t acr;
+	uint8_t pad11[0x1ff];
+
+	uint8_t pcr;
+	uint8_t pad12[0x1ff];
+
+	uint8_t ifr;
+	uint8_t pad13[0x1ff];
+
+	uint8_t ier;
+	uint8_t pad14[0x1ff];
+
+	uint8_t anh;
+	uint8_t pad15[0x1ff];
+} cuda_t;
+
+/** B register fields */
+enum {
+	TREQ	= 0x08,
+	TACK	= 0x10,
+	TIP	= 0x20
+};
+
+/** IER register fields */
+enum {
+	IER_CLR	= 0x00,
+	IER_SET	= 0x80,
+
+	SR_INT	= 0x04,
+	ALL_INT	= 0x7f
+};
+
+/** ACR register fields */
+enum {
+	SR_OUT	= 0x10
+};
+
+/** Packet types */
+enum {
+	PT_ADB	= 0x00,
+	PT_CUDA	= 0x01
+};
+
+/** CUDA packet types */
+enum {
+	CPT_AUTOPOLL	= 0x01
+};
+
+enum {
+	ADB_MAX_ADDR	= 16
+};
+
+#endif
+
+/** @}
+ */
