[PATCH] update adb driver

Paul Mackerras (paulus@samba.org)
Mon, 31 Mar 2003 08:55:55 +1000 (EST)


This patch updates the ADB (Apple desktop bus) driver used on macs and
powermacs. The main change, from Ben Herrenschmidt, is that handlers
are called without a lock held now. It also adds a way for userland
to obtain some information about individual ADB devices from the
driver.

Please apply.

Paul.

diff -urN linux-2.5/drivers/macintosh/adb.c linuxppc-2.5/drivers/macintosh/adb.c
--- linux-2.5/drivers/macintosh/adb.c 2003-03-21 19:48:22.000000000 +1100
+++ linuxppc-2.5/drivers/macintosh/adb.c 2003-03-21 20:06:37.000000000 +1100
@@ -102,6 +102,7 @@
void (*handler)(unsigned char *, int, struct pt_regs *, int);
int original_address;
int handler_id;
+ int busy;
} adb_handler[16];

/*
@@ -134,7 +135,7 @@
{
if (current->pid && adb_probe_task_pid &&
adb_probe_task_pid == current->pid) {
- current->state = TASK_UNINTERRUPTIBLE;
+ set_task_state(current, TASK_UNINTERRUPTIBLE);
schedule_timeout(1 + ms * HZ / 1000);
} else
mdelay(ms);
@@ -249,7 +250,7 @@
strcpy(current->comm, "kadbprobe");

sigfillset(&blocked);
- sigprocmask(SIG_BLOCK, &blocked, NULL);
+ sigprocmask(SIG_BLOCK, &blocked, NULL);
flush_signals(current);

printk(KERN_INFO "adb: starting probe task...\n");
@@ -550,12 +551,17 @@
down(&adb_handler_sem);
write_lock_irq(&adb_handler_lock);
if (adb_handler[index].handler) {
+ while(adb_handler[index].busy) {
+ write_unlock_irq(&adb_handler_lock);
+ yield();
+ write_lock_irq(&adb_handler_lock);
+ }
ret = 0;
adb_handler[index].handler = 0;
}
write_unlock_irq(&adb_handler_lock);
up(&adb_handler_sem);
- return 0;
+ return ret;
}

void
@@ -563,6 +569,8 @@
{
int i, id;
static int dump_adb_input = 0;
+ unsigned long flags;
+
void (*handler)(unsigned char *, int, struct pt_regs *, int);

/* We skip keystrokes and mouse moves when the sleep process
@@ -578,11 +586,17 @@
printk(" %x", buf[i]);
printk(", id = %d\n", id);
}
- read_lock(&adb_handler_lock);
+ write_lock_irqsave(&adb_handler_lock, flags);
handler = adb_handler[id].handler;
- if (handler != 0)
+ if (handler != NULL)
+ adb_handler[id].busy = 1;
+ write_unlock_irqrestore(&adb_handler_lock, flags);
+ if (handler != NULL) {
(*handler)(buf, nb, regs, autopoll);
- read_unlock(&adb_handler_lock);
+ wmb();
+ adb_handler[id].busy = 0;
+ }
+
}

/* Try to change handler to new_id. Will return 1 if successful. */
@@ -671,6 +685,29 @@
spin_unlock_irqrestore(&state->lock, flags);
}

+static int
+do_adb_query(struct adb_request *req)
+{
+ int ret = -EINVAL;
+
+ switch(req->data[1])
+ {
+ case ADB_QUERY_GETDEVINFO:
+ if (req->nbytes < 3)
+ break;
+ down(&adb_handler_sem);
+ req->reply[0] = adb_handler[req->data[2]].original_address;
+ req->reply[1] = adb_handler[req->data[2]].handler_id;
+ up(&adb_handler_sem);
+ req->complete = 1;
+ req->reply_len = 2;
+ adb_write_done(req);
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
static int adb_open(struct inode *inode, struct file *file)
{
struct adbdev_state *state;
@@ -806,24 +843,32 @@

/* If a probe is in progress or we are sleeping, wait for it to complete */
down(&adb_probe_mutex);
- up(&adb_probe_mutex);

+ /* Queries are special requests sent to the ADB driver itself */
+ if (req->data[0] == ADB_QUERY) {
+ if (count > 1)
+ ret = do_adb_query(req);
+ else
+ ret = -EINVAL;
+ up(&adb_probe_mutex);
+ }
/* Special case for ADB_BUSRESET request, all others are sent to
the controller */
- if ((req->data[0] == ADB_PACKET)&&(count > 1)
+ else if ((req->data[0] == ADB_PACKET)&&(count > 1)
&&(req->data[1] == ADB_BUSRESET)) {
ret = do_adb_reset_bus();
+ up(&adb_probe_mutex);
atomic_dec(&state->n_pending);
if (ret == 0)
ret = count;
goto out;
} else {
req->reply_expected = ((req->data[1] & 0xc) == 0xc);
-
if (adb_controller && adb_controller->send_request)
ret = adb_controller->send_request(req, 0);
else
ret = -ENXIO;
+ up(&adb_probe_mutex);
}

if (ret != 0) {
diff -urN linux-2.5/drivers/macintosh/macio-adb.c linuxppc-2.5/drivers/macintosh/macio-adb.c
--- linux-2.5/drivers/macintosh/macio-adb.c 2002-10-13 15:00:41.000000000 +1000
+++ linuxppc-2.5/drivers/macintosh/macio-adb.c 2002-11-22 23:15:30.000000000 +1100
@@ -8,6 +8,7 @@
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
+#include <linux/interrupt.h>
#include <asm/prom.h>
#include <linux/adb.h>
#include <asm/io.h>
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/