Index: rnel/arch/sparc64/include/drivers/z8530.h
===================================================================
--- kernel/arch/sparc64/include/drivers/z8530.h	(revision e7abb0e3396ad17432846b71e804a8fb835dceb8)
+++ 	(revision )
@@ -1,140 +1,0 @@
-/*
- * Copyright (c) 2006 Jakub Jermar
- * 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 sparc64	
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_sparc64_Z8530_H_
-#define KERN_sparc64_Z8530_H_
-
-#include <arch/types.h>
-#include <arch/drivers/kbd.h>
-
-#define Z8530_CHAN_A	4
-#define Z8530_CHAN_B	0
-
-#define WR0	0
-#define WR1	1
-#define WR2	2
-#define WR3	3
-#define WR4	4
-#define WR5	5
-#define WR6	6
-#define WR7	7
-#define WR8	8
-#define WR9	9
-#define WR10	10
-#define WR11	11
-#define WR12	12
-#define WR13	13
-#define WR14	14
-#define WR15	15
-
-#define RR0	0
-#define RR1	1
-#define RR2	2
-#define RR3	3
-#define RR8	8
-#define RR10	10
-#define RR12	12
-#define RR13	13
-#define RR14	14
-#define RR15	15
-
-/* Write Register 0 */
-#define WR0_TX_IP_RST	(0x5<<3)	/** Reset pending TX interrupt. */
-#define WR0_ERR_RST	(0x6<<3)
-
-/* Write Register 1 */
-#define WR1_RID		(0x0<<3)	/** Receive Interrupts Disabled. */
-#define WR1_RIFCSC	(0x1<<3)	/** Receive Interrupt on First Character or Special Condition. */
-#define WR1_IARCSC	(0x2<<3)	/** Interrupt on All Receive Characters or Special Conditions. */
-#define WR1_RISC	(0x3<<3)	/** Receive Interrupt on Special Condition. */
-#define WR1_PISC	(0x1<<2)	/** Parity Is Special Condition. */
-
-/* Write Register 3 */
-#define WR3_RX_ENABLE	(0x1<<0)	/** Rx Enable. */
-#define WR3_RX8BITSCH	(0x3<<6)	/** 8-bits per character. */
-
-/* Write Register 9 */
-#define WR9_MIE		(0x1<<3)	/** Master Interrupt Enable. */
-
-/* Read Register 0 */
-#define RR0_RCA		(0x1<<0)	/** Receive Character Available. */
-
-/** Structure representing the z8530 device. */
-typedef struct {
-	devno_t devno;
-	volatile uint8_t *reg;		/** Memory mapped registers of the z8530. */
-} z8530_t;
-
-static inline void z8530_write(z8530_t *dev, index_t chan, uint8_t reg, uint8_t val)
-{
-	/*
-	 * Registers 8-15 will automatically issue the Point High
-	 * command as their bit 3 is 1.
-	 */
-	dev->reg[WR0+chan] = reg;	/* select register */
-	dev->reg[WR0+chan] = val;	/* write value */
-}
-
-static inline void z8530_write_a(z8530_t *dev, uint8_t reg, uint8_t val)
-{
-	z8530_write(dev, Z8530_CHAN_A, reg, val);
-}
-static inline void z8530_write_b(z8530_t *dev, uint8_t reg, uint8_t val)
-{
-	z8530_write(dev, Z8530_CHAN_B, reg, val);
-}
-
-static inline uint8_t z8530_read(z8530_t *dev, index_t chan, uint8_t reg) 
-{
-	/*
-	 * Registers 8-15 will automatically issue the Point High
-	 * command as their bit 3 is 1.
-	 */
-	dev->reg[WR0+chan] = reg;	/* select register */
-	return dev->reg[WR0+chan];
-}
-
-static inline uint8_t z8530_read_a(z8530_t *dev, uint8_t reg)
-{
-	return z8530_read(dev, Z8530_CHAN_A, reg);
-}
-static inline uint8_t z8530_read_b(z8530_t *dev, uint8_t reg)
-{
-	return z8530_read(dev, Z8530_CHAN_B, reg);
-}
-
-#endif
-
-/** @}
- */
Index: kernel/arch/sparc64/src/console.c
===================================================================
--- kernel/arch/sparc64/src/console.c	(revision e7abb0e3396ad17432846b71e804a8fb835dceb8)
+++ kernel/arch/sparc64/src/console.c	(revision 0f74869b097948cf47305f47d532161682eac285)
@@ -163,14 +163,4 @@
 #endif
 	switch (kbd_type) {
-#ifdef CONFIG_Z8530
-	case KBD_Z8530:
-		z8530_grab();
-		break;
-#endif
-#ifdef CONFIG_NS16550
-	case KBD_NS16550:
-		ns16550_grab();
-		break;
-#endif
 #ifdef CONFIG_SGCN
 	case KBD_SGCN:
@@ -189,14 +179,4 @@
 {
 	switch (kbd_type) {
-#ifdef CONFIG_Z8530
-	case KBD_Z8530:
-		z8530_release();
-		break;
-#endif
-#ifdef CONFIG_NS16550
-	case KBD_NS16550:
-		ns16550_release();
-		break;
-#endif
 #ifdef CONFIG_SGCN
 	case KBD_SGCN:
Index: kernel/arch/sparc64/src/drivers/kbd.c
===================================================================
--- kernel/arch/sparc64/src/drivers/kbd.c	(revision e7abb0e3396ad17432846b71e804a8fb835dceb8)
+++ kernel/arch/sparc64/src/drivers/kbd.c	(revision 0f74869b097948cf47305f47d532161682eac285)
@@ -149,6 +149,7 @@
 #ifdef CONFIG_Z8530
 	case KBD_Z8530:
-		z8530_init(device_assign_devno(),
-		    hw_map(aligned_addr, offset + size) + offset, inr, cir, cir_arg);
+		(void) z8530_init((z8530_t *) hw_map(aligned_addr,
+		    offset + size) + offset, device_assign_devno(), inr, cir,
+		    cir_arg);
 		break;
 #endif
Index: kernel/arch/sparc64/src/drivers/sgcn.c
===================================================================
--- kernel/arch/sparc64/src/drivers/sgcn.c	(revision e7abb0e3396ad17432846b71e804a8fb835dceb8)
+++ kernel/arch/sparc64/src/drivers/sgcn.c	(revision 0f74869b097948cf47305f47d532161682eac285)
@@ -382,11 +382,5 @@
 	
 	if (*in_rdptr_ptr != *in_wrptr_ptr) {
-		if (sgcn_irq.notif_cfg.notify && sgcn_irq.notif_cfg.answerbox) {
-			ipc_irq_send_notif(&sgcn_irq);
-			spinlock_unlock(&sgcn_irq.lock);
-			interrupts_restore(ipl);
-			spinlock_unlock(&sgcn_input_lock);
-			return;
-		}
+		/* XXX: send notification to userspace */
 	}
 	
Index: kernel/genarch/include/kbd/z8530.h
===================================================================
--- kernel/genarch/include/kbd/z8530.h	(revision e7abb0e3396ad17432846b71e804a8fb835dceb8)
+++ kernel/genarch/include/kbd/z8530.h	(revision 0f74869b097948cf47305f47d532161682eac285)
@@ -38,16 +38,87 @@
 #define KERN_Z8530_H_
 
-#include <console/chardev.h>
-#include <ipc/irq.h>
 #include <ddi/irq.h>
+#include <arch/types.h>
 
-extern bool z8530_belongs_to_kernel;
+#define WR0	0
+#define WR1	1
+#define WR2	2
+#define WR3	3
+#define WR4	4
+#define WR5	5
+#define WR6	6
+#define WR7	7
+#define WR8	8
+#define WR9	9
+#define WR10	10
+#define WR11	11
+#define WR12	12
+#define WR13	13
+#define WR14	14
+#define WR15	15
 
-extern void z8530_init(devno_t, uintptr_t, inr_t, cir_t, void *);
-extern void z8530_poll(void);
-extern void z8530_grab(void);
-extern void z8530_release(void);
-extern void z8530_interrupt(void);
-extern char z8530_key_read(chardev_t *);
+#define RR0	0
+#define RR1	1
+#define RR2	2
+#define RR3	3
+#define RR8	8
+#define RR10	10
+#define RR12	12
+#define RR13	13
+#define RR14	14
+#define RR15	15
+
+/** Reset pending TX interrupt. */
+#define WR0_TX_IP_RST	(0x5 << 3)
+#define WR0_ERR_RST	(0x6 << 3)
+
+/** Receive Interrupts Disabled. */
+#define WR1_RID		(0x0 << 3)
+/** Receive Interrupt on First Character or Special Condition. */
+#define WR1_RIFCSC	(0x1 << 3)
+/** Interrupt on All Receive Characters or Special Conditions. */
+#define WR1_IARCSC	(0x2 << 3)
+/** Receive Interrupt on Special Condition. */
+#define WR1_RISC	(0x3 << 3)
+/** Parity Is Special Condition. */
+#define WR1_PISC	(0x1 << 2)
+
+/** Rx Enable. */
+#define WR3_RX_ENABLE	(0x1 << 0)
+/** 8-bits per character. */
+#define WR3_RX8BITSCH	(0x3 << 6)
+
+/** Master Interrupt Enable. */
+#define WR9_MIE		(0x1 << 3)
+
+/** Receive Character Available. */
+#define RR0_RCA		(0x1 << 0)
+
+/** z8530's registers. */
+struct z8530 {
+	union {
+		ioport8_t ctl_b;
+		ioport8_t status_b;
+	} __attribute__ ((packed));
+	uint8_t pad1;
+	ioport8_t data_b;
+	uint8_t pad2;
+	union {
+		ioport8_t ctl_a;
+		ioport8_t status_a;
+	} __attribute__ ((packed));
+	uint8_t pad3;
+	ioport8_t data_a;
+} __attribute__ ((packed));
+typedef struct z8530 z8530_t;
+
+/** Structure representing the z8530 device. */
+typedef struct {
+	devno_t devno;
+	irq_t irq;
+	z8530_t *z8530;
+} z8530_instance_t;
+
+extern bool z8530_init(z8530_t *, devno_t, inr_t, cir_t, void *);
 extern irq_ownership_t z8530_claim(irq_t *);
 extern void z8530_irq_handler(irq_t *);
Index: kernel/genarch/src/kbd/z8530.c
===================================================================
--- kernel/genarch/src/kbd/z8530.c	(revision e7abb0e3396ad17432846b71e804a8fb835dceb8)
+++ kernel/genarch/src/kbd/z8530.c	(revision 0f74869b097948cf47305f47d532161682eac285)
@@ -32,5 +32,5 @@
 /**
  * @file
- * @brief	Zilog 8530 serial port / keyboard driver.
+ * @brief	Zilog 8530 serial port driver.
  */
 
@@ -39,17 +39,31 @@
 #include <genarch/kbd/scanc.h>
 #include <genarch/kbd/scanc_sun.h>
-#include <arch/drivers/z8530.h>
+#include <arch/drivers/kbd.h>
+#include <console/console.h>
+#include <console/chardev.h>
+#include <sysinfo/sysinfo.h>
 #include <ddi/irq.h>
-#include <ipc/irq.h>
-#include <arch/interrupt.h>
-#include <arch/drivers/kbd.h>
-#include <cpu.h>
 #include <arch/asm.h>
-#include <arch.h>
-#include <console/chardev.h>
-#include <console/console.h>
-#include <interrupt.h>
-#include <sysinfo/sysinfo.h>
-#include <print.h>
+#include <mm/slab.h>
+
+static inline void z8530_write(ioport8_t *ctl, uint8_t reg, uint8_t val)
+{
+	/*
+	 * Registers 8-15 will automatically issue the Point High
+	 * command as their bit 3 is 1.
+	 */
+	pio_write_8(ctl, reg);	/* select register */
+	pio_write_8(ctl, val);	/* write value */
+}
+
+static inline uint8_t z8530_read(ioport8_t *ctl, uint8_t reg) 
+{
+	/*
+	 * Registers 8-15 will automatically issue the Point High
+	 * command as their bit 3 is 1.
+	 */
+	pio_write_8(ctl, reg);	/* select register */
+	return pio_read_8(ctl);
+}
 
 /*
@@ -57,7 +71,4 @@
  */
 #define IGNORE_CODE	0x7f		/* all keys up */
-
-static z8530_t z8530;		/**< z8530 device structure. */
-static irq_t z8530_irq;		/**< z8530's IRQ. */ 
 
 static void z8530_suspend(chardev_t *);
@@ -67,13 +78,33 @@
 	.suspend = z8530_suspend,
 	.resume = z8530_resume,
-	.read = z8530_key_read
 };
 
-/** Initialize keyboard and service interrupts using kernel routine. */
-void z8530_grab(void)
+/** Initialize z8530. */
+bool
+z8530_init(z8530_t *dev, devno_t devno, inr_t inr, cir_t cir, void *cir_arg)
 {
-	ipl_t ipl = interrupts_disable();
+	z8530_instance_t *instance;
 
-	(void) z8530_read_a(&z8530, RR8);
+	chardev_initialize("z8530_kbd", &kbrd, &ops);
+	stdin = &kbrd;
+
+	instance = malloc(sizeof(z8530_instance_t), FRAME_ATOMIC);
+	if (!instance)
+		return false;
+
+	instance->devno = devno;
+	instance->z8530 = dev;
+
+	irq_initialize(&instance->irq);
+	instance->irq.devno = devno;
+	instance->irq.inr = inr;
+	instance->irq.claim = z8530_claim;
+	instance->irq.handler = z8530_irq_handler;
+	instance->irq.instance = instance;
+	instance->irq.cir = cir;
+	instance->irq.cir_arg = cir_arg;
+	irq_register(&instance->irq);
+
+	(void) z8530_read(&dev->ctl_a, RR8);
 
 	/*
@@ -81,68 +112,26 @@
 	 * to set FHC UART interrupt state to idle.
 	 */
-	z8530_write_a(&z8530, WR0, WR0_TX_IP_RST);
+	z8530_write(&dev->ctl_a, WR0, WR0_TX_IP_RST);
 
 	/* interrupt on all characters */
-	z8530_write_a(&z8530, WR1, WR1_IARCSC);
+	z8530_write(&dev->ctl_a, WR1, WR1_IARCSC);
 
 	/* 8 bits per character and enable receiver */
-	z8530_write_a(&z8530, WR3, WR3_RX8BITSCH | WR3_RX_ENABLE);
+	z8530_write(&dev->ctl_a, WR3, WR3_RX8BITSCH | WR3_RX_ENABLE);
 	
 	/* Master Interrupt Enable. */
-	z8530_write_a(&z8530, WR9, WR9_MIE);
-	
-	spinlock_lock(&z8530_irq.lock);
-	z8530_irq.notif_cfg.notify = false;
-	spinlock_unlock(&z8530_irq.lock);
-	interrupts_restore(ipl);
-}
+	z8530_write(&dev->ctl_a, WR9, WR9_MIE);
 
-/** Resume the former IPC notification behavior. */
-void z8530_release(void)
-{
-	ipl_t ipl = interrupts_disable();
-	spinlock_lock(&z8530_irq.lock);
-	if (z8530_irq.notif_cfg.answerbox)
-		z8530_irq.notif_cfg.notify = true;
-	spinlock_unlock(&z8530_irq.lock);
-	interrupts_restore(ipl);
-}
-
-/** Initialize z8530. */
-void
-z8530_init(devno_t devno, uintptr_t vaddr, inr_t inr, cir_t cir, void *cir_arg)
-{
-	chardev_initialize("z8530_kbd", &kbrd, &ops);
-	stdin = &kbrd;
-
-	z8530.devno = devno;
-	z8530.reg = (uint8_t *) vaddr;
-
-	irq_initialize(&z8530_irq);
-	z8530_irq.devno = devno;
-	z8530_irq.inr = inr;
-	z8530_irq.claim = z8530_claim;
-	z8530_irq.handler = z8530_irq_handler;
-	z8530_irq.cir = cir;
-	z8530_irq.cir_arg = cir_arg;
-	irq_register(&z8530_irq);
-
+	/*
+	 * This is the necessary evil until the userspace drivers are entirely
+	 * self-sufficient.
+	 */
 	sysinfo_set_item_val("kbd", NULL, true);
 	sysinfo_set_item_val("kbd.type", NULL, KBD_Z8530);
 	sysinfo_set_item_val("kbd.devno", NULL, devno);
 	sysinfo_set_item_val("kbd.inr", NULL, inr);
-	sysinfo_set_item_val("kbd.address.virtual", NULL, vaddr);
+	sysinfo_set_item_val("kbd.address.virtual", NULL, (uintptr_t) dev);
 
-	z8530_grab();
-}
-
-/** Process z8530 interrupt.
- *
- * @param n Interrupt vector.
- * @param istate Interrupted state.
- */
-void z8530_interrupt(void)
-{
-	z8530_poll();
+	return true;
 }
 
@@ -157,33 +146,20 @@
 }
 
-char z8530_key_read(chardev_t *d)
+irq_ownership_t z8530_claim(irq_t *irq)
 {
-	char ch;	
+	z8530_instance_t *instance = irq->instance;
+	z8530_t *dev = instance->z8530;
 
-	while(!(ch = active_read_buff_read())) {
-		uint8_t x;
-		while (!(z8530_read_a(&z8530, RR0) & RR0_RCA))
-			;
-		x = z8530_read_a(&z8530, RR8);
-		if (x != IGNORE_CODE) {
-			if (x & KEY_RELEASE)
-				key_released(x ^ KEY_RELEASE);
-			else
-				active_read_key_pressed(x);
-		}
-	}
-	return ch;
+	return (z8530_read(&dev->ctl_a, RR0) & RR0_RCA);
 }
 
-/** Poll for key press and release events.
- *
- * This function can be used to implement keyboard polling.
- */
-void z8530_poll(void)
+void z8530_irq_handler(irq_t *irq)
 {
+	z8530_instance_t *instance = irq->instance;
+	z8530_t *dev = instance->z8530;
 	uint8_t x;
 
-	while (z8530_read_a(&z8530, RR0) & RR0_RCA) {
-		x = z8530_read_a(&z8530, RR8);
+	if (z8530_read(&dev->ctl_a, RR0) & RR0_RCA) {
+		x = z8530_read(&dev->ctl_a, RR8);
 		if (x != IGNORE_CODE) {
 			if (x & KEY_RELEASE)
@@ -195,17 +171,4 @@
 }
 
-irq_ownership_t z8530_claim(irq_t *irq)
-{
-	return (z8530_read_a(&z8530, RR0) & RR0_RCA);
-}
-
-void z8530_irq_handler(irq_t *irq)
-{
-	if (irq->notif_cfg.notify && irq->notif_cfg.answerbox)
-		ipc_irq_send_notif(irq);
-	else
-		z8530_interrupt();
-}
-
 /** @}
  */
Index: uspace/srv/kbd/port/z8530.c
===================================================================
--- uspace/srv/kbd/port/z8530.c	(revision e7abb0e3396ad17432846b71e804a8fb835dceb8)
+++ uspace/srv/kbd/port/z8530.c	(revision 0f74869b097948cf47305f47d532161682eac285)
@@ -42,17 +42,38 @@
 #include <sys/types.h>
 
-/** Top-half pseudocode for z8530. */
-irq_cmd_t z8530_cmds[] = {
+#define CHAN_A_STATUS	4
+#define CHAN_A_DATA	6
+
+#define RR0_RCA	1
+
+static irq_cmd_t z8530_cmds[] = {
 	{
-		CMD_MEM_READ_1,
-		0,		/**< Address. Will be patched in run-time. */
-		0,		/**< Value. Not used. */
-		1		/**< Arg 1 will contain the result. */
+		.cmd = CMD_PIO_READ_8,
+		.addr = (void *) 0,	/* will be patched in run-time */
+		.dstarg = 1
+	},
+	{
+		.cmd = CMD_BTEST,
+		.value = RR0_RCA,
+		.srcarg = 1,
+		.dstarg = 3
+	},
+	{
+		.cmd = CMD_PREDICATE,
+		.value = 2,
+		.srcarg = 3
+	},
+	{
+		.cmd = CMD_PIO_READ_8,
+		.addr = (void *) 0,	/* will be patched in run-time */
+		.dstarg = 2
+	},
+	{
+		.cmd = CMD_ACCEPT
 	}
 };
-
 	
 irq_code_t z8530_kbd = {
-	1,
+	sizeof(z8530_cmds) / sizeof(irq_cmd_t),
 	z8530_cmds
 };
@@ -63,5 +84,8 @@
 {
 	async_set_interrupt_received(z8530_irq_handler);
-	z8530_cmds[0].addr = (void *) sysinfo_value("kbd.address.virtual") + 6;
+	z8530_cmds[0].addr = (void *) sysinfo_value("kbd.address.virtual") +
+	    CHAN_A_STATUS;
+	z8530_cmds[3].addr = (void *) sysinfo_value("kbd.address.virtual") +
+	    CHAN_A_DATA;
 	ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"),
 	    0, &z8530_kbd);
@@ -71,5 +95,5 @@
 static void z8530_irq_handler(ipc_callid_t iid, ipc_call_t *call)
 {
-	int scan_code = IPC_GET_ARG1(*call);
+	int scan_code = IPC_GET_ARG2(*call);
 	kbd_push_scancode(scan_code);
 }
