patch-2.2.18 linux/arch/m68k/mac/adb-bus.c
Next file: linux/arch/m68k/mac/adb-misc.c
Previous file: linux/arch/m68k/mac/Makefile
Back to the patch index
Back to the overall index
- Lines: 1078
- Date:
Fri Oct 13 23:30:47 2000
- Orig file:
v2.2.17/arch/m68k/mac/adb-bus.c
- Orig date:
Fri Apr 21 12:45:46 2000
diff -u --new-file --recursive --exclude-from /usr/src/exclude v2.2.17/arch/m68k/mac/adb-bus.c linux/arch/m68k/mac/adb-bus.c
@@ -11,6 +11,28 @@
* - Guido Koerber's session with a logic analyzer
*
* MSch (1/98) Integrated start of IIsi driver by Robert Thompson
+ *
+ * 1999-05-30 (JMT) - Added support for reading/writing the PRAM clock.
+ * We really need to clean up the reply_expected usage
+ * in here so that the special cases in adb_interrupt
+ * for faking replies can be removed.
+ *
+ * 1999-06-10 (JMT) - Wedged in some IOP support. This is really getting
+ * messy...
+ *
+ * 1999-06-11 (JMT) - IOP support sort of working. Autopolling of the
+ * keyboard works but if we transmit and get a timeout
+ * we'll get bombarded with timeout message from the
+ * IOP and I don't know how to make them stop. Thus
+ * I have disabled transmission until I can figure out
+ * how to handle the timeouts properly.
+ * 1999-06-12 (JMT) - Rewrote IOP support to match changes in IOP
+ * architecture. Also discovered that you need to send
+ * a sensible reply to an autopoll packet or else the
+ * keyboard will stop sending packets. I chose to send
+ * back what we received, as that was what we were
+ * essentially doing before the IOP rewrite and it
+ * seemed to work.
*/
#include <stdarg.h>
@@ -22,7 +44,6 @@
#include <linux/sched.h>
#include <linux/malloc.h>
#include <linux/mm.h>
-#include "via6522.h"
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -32,7 +53,9 @@
#include <asm/setup.h>
#include <asm/macintosh.h>
#include <asm/macints.h>
-
+#include <asm/mac_via.h>
+#include <asm/mac_iop.h>
+#include <asm/adb_iop.h>
#define MACII /* For now - will be a switch */
@@ -51,11 +74,7 @@
/* Bits in ACR */
#define SR_CTRL 0x1c /* Shift register control bits */
-#ifdef USE_ORIG
-#define SR_EXT 0x1c /* Shift on external clock */
-#else
#define SR_EXT 0x0c /* Shift on external clock */
-#endif
#define SR_OUT 0x10 /* Shift out if 1 */
/* Bits in IFR and IER */
@@ -68,6 +87,17 @@
/* JRT */
#define ADB_DELAY 150
+#ifdef DEBUG_ADB_INTS
+static int nclock, ndata;
+#endif
+
+static int need_poll = 0;
+static int command_byte = 0;
+static int last_reply = 0;
+static int last_active = 0;
+
+static struct adb_request *retry_req;
+
static struct adb_handler {
void (*handler)(unsigned char *, int, struct pt_regs *);
} adb_handler[16];
@@ -100,14 +130,23 @@
int in_keybinit = 1;
static void adb_start(void);
-extern void adb_interrupt(int irq, void *arg, struct pt_regs *regs);
-extern void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs);
-extern void adb_clock_interrupt(int irq, void *arg, struct pt_regs *regs);
-extern void adb_data_interrupt(int irq, void *arg, struct pt_regs *regs);
+static void adb_interrupt(int irq, void *arg, struct pt_regs *regs);
+static void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs);
+static void adb_pm_interrupt(int irq, void *arg, struct pt_regs *regs);
+#ifdef DEBUG_ADB_INTS
+static void adb_clock_interrupt(int irq, void *arg, struct pt_regs *regs);
+static void adb_data_interrupt(int irq, void *arg, struct pt_regs *regs);
+#endif
static void adb_input(unsigned char *buf, int nb, struct pt_regs *regs);
+static void adb_iop_receive(struct iop_msg *, struct pt_regs *);
+static void adb_hw_setup_macII(void);
static void adb_hw_setup_IIsi(void);
static void adb_hw_setup_cuda(void);
+static void adb_hw_setup_iop(void);
+static void adb_hw_setup_pm(void);
+
+void adb_retransmit(int);
/*
* debug level 10 required for ADB logging (should be && debug_adb, ideally)
@@ -149,7 +188,6 @@
void adb_bus_init(void)
{
unsigned long flags;
- unsigned char c, i;
save_flags(flags);
cli();
@@ -162,122 +200,47 @@
{
case MAC_ADB_II:
- printk("adb: MacII style keyboard/mouse driver.\n");
- /* Set the lines up. We want TREQ as input TACK|TIP as output */
- via_write(via1, vDirB, ((via_read(via1,vDirB)|TACK|TIP)&~TREQ));
- /*
- * Docs suggest TREQ should be output - that seems nuts
- * BSD agrees here :-)
- * Setup vPCR ??
- */
-
-#ifdef USE_ORIG
- /* Lower the bus signals (MacII is active low it seems ???) */
- via_write(via1, vBufB, via_read(via1, vBufB)&~TACK);
-#else
- /* Corresponding state: idle (clear state bits) */
- via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE);
- last_status = (via_read(via1, vBufB)&~ST_MASK);
-#endif
- /* Shift register on input */
- c=via_read(via1, vACR);
- c&=~SR_CTRL; /* Clear shift register bits */
- c|=SR_EXT; /* Shift on external clock; out or in? */
- via_write(via1, vACR, c);
- /* Wipe any pending data and int */
- via_read(via1, vSR);
-
- /* This is interrupts on enable SR for keyboard */
- via_write(via1, vIER, IER_SET|SR_INT);
- /* This clears the interrupt bit */
- via_write(via1, vIFR, SR_INT);
-
- /*
- * Ok we probably ;) have a ready to use adb bus. Its also
- * hopefully idle (Im assuming the mac didnt leave a half
- * complete transaction on booting us).
- */
-
+ printk(KERN_INFO "adb: MacII style keyboard/mouse driver.\n");
+ adb_hw_setup_macII();
request_irq(IRQ_MAC_ADB, adb_interrupt, IRQ_FLG_LOCK,
"adb interrupt", adb_interrupt);
adb_state = idle;
break;
- /*
- * Unsupported; but later code doesn't notice !!
- */
- case MAC_ADB_CUDA:
- printk("adb: CUDA interface.\n");
-#if 0
- /* don't know what to set up here ... */
- adb_state = idle;
- /* Set the lines up. We want TREQ as input TACK|TIP as output */
- via_write(via1, vDirB, ((via_read(via1,vDirB)|TACK|TIP)&~TREQ));
-#endif
- adb_hw_setup_cuda();
- adb_state = idle;
- request_irq(IRQ_MAC_ADB, adb_cuda_interrupt, IRQ_FLG_LOCK,
- "adb CUDA interrupt", adb_cuda_interrupt);
- break;
case MAC_ADB_IISI:
printk("adb: Using IIsi hardware.\n");
- printk("\tDEBUG_JRT\n");
- /* Set the lines up. We want TREQ as input TACK|TIP as output */
- via_write(via1, vDirB, ((via_read(via1,vDirB)|TACK|TIP)&~TREQ));
-
- /*
- * MSch: I'm pretty sure the setup is mildly wrong
- * for the IIsi.
- */
- /* Initial state: idle (clear state bits) */
- via_write(via1, vBufB, (via_read(via1, vBufB) & ~(TIP|TACK)) );
- last_status = (via_read(via1, vBufB)&~ST_MASK);
- /* Shift register on input */
- c=via_read(via1, vACR);
- c&=~SR_CTRL; /* Clear shift register bits */
- c|=SR_EXT; /* Shift on external clock; out or in? */
- via_write(via1, vACR, c);
- /* Wipe any pending data and int */
- via_read(via1, vSR);
-
- /* This is interrupts on enable SR for keyboard */
- via_write(via1, vIER, IER_SET|SR_INT);
- /* This clears the interrupt bit */
- via_write(via1, vIFR, SR_INT);
-
- /* get those pesky clock ticks we missed while booting */
- for ( i = 0; i < 60; i++) {
- udelay(ADB_DELAY);
- adb_hw_setup_IIsi();
- udelay(ADB_DELAY);
- if (via_read(via1, vBufB) & TREQ)
- break;
- }
- if (i == 60)
- printk("adb_IIsi: maybe bus jammed ??\n");
-
- /*
- * Ok we probably ;) have a ready to use adb bus. Its also
- */
+ adb_hw_setup_IIsi();
request_irq(IRQ_MAC_ADB, adb_cuda_interrupt, IRQ_FLG_LOCK,
"adb interrupt", adb_cuda_interrupt);
adb_state = idle;
break;
+ case MAC_ADB_CUDA:
+ printk(KERN_INFO "adb: CUDA interface.\n");
+
+ adb_hw_setup_cuda();
+ request_irq(IRQ_MAC_ADB, adb_cuda_interrupt, IRQ_FLG_LOCK,
+ "adb CUDA interrupt", adb_cuda_interrupt);
+ adb_state = idle;
+ break;
+ case MAC_ADB_IOP:
+ printk("adb: using IOP for ADB...good luck.\n");
+ iop_listen(ADB_IOP, ADB_CHAN, adb_iop_receive, "ADB");
+ adb_hw_setup_iop();
+ adb_state = idle;
+ break;
+ case MAC_ADB_PB1:
+ case MAC_ADB_PB2:
+ printk("adb: using PowerManager for ADB... you are doomed.\n");
+ adb_hw_setup_pm();
+ request_irq(IRQ_MAC_ADB, adb_pm_interrupt, IRQ_FLG_LOCK,
+ "adb PowerManager interrupt", adb_pm_interrupt);
+ adb_state = idle;
+ break;
default:
printk("adb: Unknown hardware interface.\n");
- nosupp:
- printk("adb: Interface unsupported.\n");
restore_flags(flags);
return;
}
- /*
- * XXX: interrupt only registered if supported HW !!
- * -> unsupported HW will just time out on keyb_init!
- */
-#if 0
- request_irq(IRQ_MAC_ADB, adb_interrupt, IRQ_FLG_LOCK,
- "adb interrupt", adb_interrupt);
-#endif
#ifdef DEBUG_ADB_INTS
request_irq(IRQ_MAC_ADB_CL, adb_clock_interrupt, IRQ_FLG_LOCK,
"adb clock interrupt", adb_clock_interrupt);
@@ -289,6 +252,100 @@
restore_flags(flags);
}
+/* Set up IOP ADB */
+
+void adb_hw_setup_iop(void)
+{
+#if 0
+ volatile struct adb_request req;
+#endif
+
+ printk("adb-iop: hardware setup in progress.\n");
+
+#if 0
+ adb_request((struct adb_request *) &req, NULL,
+ 2, ADB_PACKET, AIF_RESET);
+ while (!req.complete);
+#endif
+
+ printk("adb-iop: hardware setup done!\n");
+}
+
+/* Strip the adb message out of an IOP message */
+
+static void adb_from_iopmsg(struct iop_msg *src, struct adb_iopmsg *dst,
+ int is_reply)
+{
+ if (is_reply) {
+ memcpy(dst, &src->reply[0], sizeof(struct adb_iopmsg));
+ } else {
+ memcpy(dst, &src->message[0], sizeof(struct adb_iopmsg));
+ }
+}
+
+/*
+ * Receive an ADB message from the IOP.
+ *
+ * This will be called in two cases:
+ *
+ * 1. A message has been successfully sent to the IOP.
+ * 4. An unsolicited message was received from the IOP.
+ */
+
+void adb_iop_receive(struct iop_msg *msg, struct pt_regs *regs)
+{
+ struct adb_iopmsg amsg;
+ struct adb_request *req;
+ unsigned char packet[16];
+ int i;
+
+ req = current_req;
+
+ if (msg->status == IOP_MSGSTATUS_COMPLETE) {
+ if (req->reply_expected) {
+ adb_from_iopmsg(msg, &amsg, 1);
+ req->reply_len = amsg.count + 1;
+ req->reply[0] = ADB_PACKET;
+ for (i = 0 ; i < sizeof(amsg.data) ; i++) {
+ req->reply[i+1] = amsg.data[i];
+ }
+ }
+ req->complete = 1;
+ current_req = req->next;
+ if (req->done) (*req->done)(req);
+ adb_state = idle;
+ } else if (msg->status == IOP_MSGSTATUS_UNSOL) {
+ adb_from_iopmsg(msg, &amsg, 0);
+ if (amsg.flags & ADB_IOP_TIMEOUT) { /* timeout */
+ printk("adb_iop_receive: timeout, retransmitting to %d\n", last_active);
+ if (last_active == -1)
+ last_active = (amsg.cmd&0xf0)>>4;
+ if (current_req) {
+ adb_start();
+ } else {
+ adb_retransmit(last_active);
+ }
+ } else {
+ /* fake a CUDA-format packet */
+ packet[0] = ADB_PACKET; /* packet type */
+ packet[1] = 0; /* ???? */
+ packet[2] = amsg.cmd; /* command byte */
+ i = 0;
+ while (i < amsg.count) {
+ packet[i+3] = amsg.data[i];
+ i++;
+ }
+ adb_input(packet, amsg.count + 3, regs);
+ memcpy(&msg->reply[0], &msg->message[0], IOP_MSG_LEN);
+ }
+ iop_complete_message(msg);
+ adb_state = idle;
+ } else {
+ printk("adb_iop_receive: unknown IOP message state %d.\n",
+ msg->status);
+ }
+}
+
void adb_hw_setup_cuda(void)
{
int x;
@@ -398,20 +455,45 @@
printk("\nCUDA: HW Setup done!\n");
}
-void adb_hw_setup_IIsi(void)
+static void adb_hw_setup_macII(void)
+{
+ /* Set the lines up. We want TREQ as input TACK|TIP as output */
+ via_write(via1, vDirB, ((via_read(via1,vDirB)|TACK|TIP)&~TREQ));
+ /*
+ * Docs suggest TREQ should be output - that seems nuts
+ * BSD agrees here :-)
+ * Setup vPCR ??
+ */
+
+ /* Set up state: idle */
+ via_write(via1, vBufB, via_read(via1, vBufB) | ST_IDLE);
+ last_status = (via_read(via1, vBufB)&~ST_MASK);
+
+ /* Shift register on input */
+ via_write(via1, vACR, (via_read(via1, vACR) & ~SR_CTRL) | SR_EXT);
+ /* Wipe any pending data and int */
+ via_read(via1, vSR);
+
+ /* This is interrupts on enable SR for keyboard */
+ via_write(via1, vIER, IER_SET|SR_INT);
+ /* This clears the interrupt bit */
+ via_write(via1, vIFR, SR_INT);
+}
+
+static void adb_IIsi_cleanup(void)
{
int dummy;
long poll_timeout;
- printk("adb_IIsi: cleanup!\n");
+ printk(KERN_DEBUG "adb_IIsi: cleanup!\n");
/* ??? */
udelay(ADB_DELAY);
- /* disable SR int. */
- via_write(via1, vIER, IER_CLR|SR_INT);
/* set SR to shift in */
via_write(via1, vACR, via_read(via1, vACR ) & ~SR_OUT);
+ /* disable SR int. */
+ via_write(via1, vIER, IER_CLR|SR_INT);
/* this is required, especially on faster machines */
udelay(ADB_DELAY);
@@ -454,6 +536,44 @@
via_write(via1, vIER, IER_SET|SR_INT);
}
+static void adb_hw_setup_IIsi(void)
+{
+ int i;
+
+ /* Set the lines up. We want TREQ as input TACK|TIP as output */
+ via_write(via1, vDirB, (via_read(via1,vDirB)|TACK|TIP) & ~TREQ);
+
+ /* Shift register on input */
+ via_write(via1, vACR, (via_read(via1, vACR) & ~SR_CTRL) | SR_EXT);
+ /* Wipe any pending data and int */
+ via_read(via1, vSR);
+
+ /* This is interrupts on enable SR for keyboard */
+ via_write(via1, vIER, IER_SET|SR_INT);
+
+ /* Set initial state: idle */
+ via_write(via1, vBufB, via_read(via1, vBufB) & ~ST_IDLE);
+ last_status = (via_read(via1, vBufB)&~ST_MASK);
+
+ /* This clears the interrupt bit */
+ via_write(via1, vIFR, SR_INT);
+
+ /* get those pesky clock ticks we missed while booting */
+ for ( i = 0; i < 60; i++) {
+ udelay(ADB_DELAY);
+ adb_IIsi_cleanup();
+ udelay(ADB_DELAY);
+ if (via_read(via1, vBufB) & TREQ)
+ break;
+ }
+ if (i == 60)
+ printk("adb_IIsi: maybe bus jammed ??\n");
+}
+
+static void adb_hw_setup_pm(void)
+{
+}
+
#define WAIT_FOR(cond, what) \
do { \
for (x = 1000; !(cond); --x) { \
@@ -477,7 +597,7 @@
* here depending on hardware type ...
*/
int adb_request(struct adb_request *req, void (*done)(struct adb_request *),
- int nbytes, ...)
+ int nbytes, ...)
{
va_list list;
int i, start;
@@ -488,6 +608,9 @@
* skip first byte if not CUDA
*/
if (macintosh_config->adb_type == MAC_ADB_II) {
+/*
+ (macintosh_config->adb_type == MAC_ADB_IOP)) {
+*/
start = va_arg(list, int);
nbytes--;
}
@@ -599,7 +722,7 @@
r.reply_expected=0;
r.done=NULL;
r.sent=0;
- r.got_reply=0;
+ r.complete=0;
r.reply_len=0;
save_flags(flags);
cli();
@@ -636,7 +759,7 @@
rt.reply_expected = 0;
rt.done = NULL;
rt.sent = 0;
- rt.got_reply = 0;
+ rt.complete = 0;
rt.reply_len = 0;
rt.next = NULL;
@@ -674,7 +797,7 @@
req->next = 0;
req->sent = 0;
- req->got_reply = 0;
+ req->complete = 0;
req->reply_len = 0;
save_flags(flags);
cli();
@@ -696,14 +819,92 @@
return 0;
}
-static int nclock, ndata;
+/*
+ * Start sending an ADB packet, IOP style
+ *
+ * There isn't much to do other than hand the packet over to the IOP
+ * after encapsulating it in an adb_iopmsg.
+ */
-static int need_poll = 0;
-static int command_byte = 0;
-static int last_reply = 0;
-static int last_active = 0;
+static void adb_start_iop(void)
+{
+ unsigned long flags;
+ struct adb_request *req;
+ struct adb_iopmsg amsg;
+ int reply_expected,i,nb;
-static struct adb_request *retry_req;
+ /* get the packet to send */
+ req = current_req;
+
+ /* TODO: re-enable transmits when timeout handling is fixed */
+
+ req->sent = 1;
+ req->complete = 1;
+ if (req->done) (*req->done)(req);
+ return;
+
+ /* assert adb_state == idle */
+ if (adb_state != idle) {
+ printk("adb-iop: adb_start_iop called while driver busy (%p %x)!\n",
+ req, adb_state);
+ return;
+ }
+
+ if (req->data[0] != ADB_PACKET) {
+ printk("abb-iop: attempt to send non-ADB packet through IOP\n");
+ return;
+ }
+
+ if (req == 0) return;
+ save_flags(flags);
+ cli();
+
+ /* Always expecting a reply could be fatal since it could clog */
+ /* the receive channel, not to mention it won't reset the adb */
+ /* state back to idle since adb_iop_receive won't be called. */
+ /* It's best to play it safe; if we aren't sure then don't */
+ /* set reply_expected; it won't work right but at least it */
+ /* won't clog the ADB subsystem. */
+
+ if ((req->data[1] & 0x0C) == AIF_TALK) {
+ reply_expected = 1;
+ } else {
+ reply_expected = 0;
+ }
+
+ /* The IOP appears to take MacII-style packets, not CUDA packets */
+
+ nb = req->nbytes - 2;
+ if (nb > sizeof(amsg.data)) nb = sizeof(amsg.data);
+
+ printk("adb-iop: sending packet, %d bytes:", nb);
+
+ amsg.flags = ADB_IOP_EXPLICIT;
+ amsg.cmd = req->data[1];
+ amsg.count = nb;
+
+ printk(" %02X", (uint) amsg.cmd);
+
+ i = 0;
+ while(i < nb) {
+ amsg.data[i] = req->data[i+2];
+ printk(" %02X", (uint) amsg.data[i]);
+ i++;
+ }
+ printk("\n");
+
+ /* Now send it. The IOP manager will call */
+ /* adb_iop_receive when the reply comes */
+ /* or when the send is completed if no */
+ /* reply is expected. */
+
+ iop_send_message(ADB_IOP, ADB_CHAN, req,
+ sizeof(amsg), (__u8 *) &amsg, adb_iop_receive);
+
+ adb_state = sending;
+
+ restore_flags(flags);
+}
/*
* Start sending ADB packet
@@ -713,10 +914,15 @@
unsigned long flags;
struct adb_request *req;
+ if (macintosh_config->adb_type == MAC_ADB_IOP) {
+ adb_start_iop();
+ return;
+ }
+
/*
* We get here on three 'sane' conditions:
* 1) called from send_adb_request, if adb_state == idle
- * 2) called from within adb_interrupt, if adb_state == idle
+ * 2) called from within adb_interrupt, if ade_state == idle
* (after receiving, or after sending a LISTEN)
* 3) called from within adb_interrupt, if adb_state == sending
* and no reply is expected (immediate next command).
@@ -741,8 +947,10 @@
printk("adb_start: request %p ", req);
#endif
+#ifdef DEBUG_ADB_INTS
nclock = 0;
ndata = 0;
+#endif
/*
* IRQ signaled ?? (means ADB controller wants to send, or might
@@ -926,6 +1134,7 @@
restore_flags(flags);
}
+#ifdef DEBUG_ADB_INTS
/*
* Debugging gimmicks
*/
@@ -938,6 +1147,7 @@
{
ndata++;
}
+#endif
/*
* The notorious ADB interrupt handler - does all of the protocol handling,
@@ -1345,7 +1555,7 @@
/* XXX: fake ADB header? */
req->reply[0] = req->reply[1] = req->reply[2] = 0xFF;
req->reply_len = 3;
- req->got_reply = 1;
+ req->complete = 1;
current_req = req->next;
if (req->done)
(*req->done)(req);
@@ -1413,7 +1623,7 @@
/* invert state bits, toggle ODD/EVEN */
x = via_read(via1, vBufB);
via_write(via1, vBufB,
- (x&~ST_MASK)|~(x&ST_MASK));
+ (x&~ST_MASK)|(~(x&ST_MASK) & ST_MASK));
}
}
break;
@@ -1632,7 +1842,7 @@
/* invert state bits, toggle ODD/EVEN */
x = via_read(via1, vBufB);
via_write(via1, vBufB,
- (x&~ST_MASK)|~(x&ST_MASK));
+ (x&~ST_MASK)|(~(x&ST_MASK) & ST_MASK));
#endif
/* adjust packet length */
reply_len--;
@@ -1655,7 +1865,7 @@
/* invert state bits, toggle ODD/EVEN */
x = via_read(via1, vBufB);
via_write(via1, vBufB,
- (x&~ST_MASK)|~(x&ST_MASK));
+ (x&~ST_MASK)|(~(x&ST_MASK) & ST_MASK));
}
}
}
@@ -1672,7 +1882,7 @@
{
req = current_req;
req->reply_len = reply_ptr - req->reply;
- req->got_reply = 1;
+ req->complete = 1;
current_req = req->next;
if (req->done)
(*req->done)(req);
@@ -1824,14 +2034,6 @@
udelay(150);
via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
}
- else if(macintosh_config->adb_type==MAC_ADB_II)
- {
- if (status != TREQ)
- printk("adb_macII: state=idle status=%x want=%x\n",
- status, TREQ);
- x = via_read(via1, vSR);
- via_write(via1, vBufB, via_read(via1, vBufB)&~(TIP|TACK));
- }
adb_state = reading;
reply_ptr = cuda_rbuf;
reply_len = 0;
@@ -1949,9 +2151,7 @@
/* delay */
udelay(ADB_DELAY);
/* set the shift register to shift out and send a byte */
-#if 0
via_write(via1, vACR, via_read(via1, vACR) | SR_OUT);
-#endif
via_write(via1, vSR, current_req->data[1]);
/* signal 'byte ready' */
via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
@@ -1959,17 +2159,6 @@
adb_state = sending;
}
}
- else if(macintosh_config->adb_type==MAC_ADB_II)
- {
- if(status!=TIP+SR_OUT)
- printk("adb_macII: state=send_first_byte status=%x want=%x\n",
- status, TIP+SR_OUT);
- via_write(via1, vSR, current_req->data[1]);
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
- data_index=2;
- adb_state = sending;
- }
break;
case sending:
@@ -1997,21 +2186,13 @@
/* delay */
udelay(ADB_DELAY);
/* set the shift register to shift in */
- via_write(via1, vACR, via_read(via1, vACR)|SR_OUT);
+ via_write(via1, vACR, via_read(via1, vACR) & ~SR_OUT);
/* clear SR int. */
x = via_read(via1, vSR);
/* set ADB state 'idle' (end of frame) */
via_write(via1, vBufB,
via_read(via1,vBufB) & ~(TACK|TIP));
}
- else if(macintosh_config->adb_type==MAC_ADB_II)
- {
- via_write(via1, vACR,
- via_read(via1, vACR) & ~SR_OUT);
- x=via_read(via1, vSR);
- via_write(via1, vBufB,
- via_read(via1, vBufB)|TACK|TIP);
- }
req->sent = 1;
if (req->reply_expected)
{
@@ -2019,10 +2200,11 @@
* maybe fake a reply here on Listen ??
* Otherwise, a Listen hangs on success
* CUDA+IIsi: only ADB Talk considered
- * RTC/PRAM read (0x1 0x3) to follow.
*/
if ( (req->data[0] == 0x0) && ((req->data[1]&0xc) == 0xc) )
adb_state = awaiting_reply;
+ else if ((req->data[0] == 0x1) && (req->data[1] == 0x3) )
+ adb_state = awaiting_reply;
else {
/*
* Reply expected, but none
@@ -2036,7 +2218,7 @@
/* XXX: fake ADB header? */
req->reply[0] = req->reply[1] = req->reply[2] = 0xFF;
req->reply_len = 3;
- req->got_reply = 1;
+ req->complete = 1;
current_req = req->next;
if (req->done)
(*req->done)(req);
@@ -2088,12 +2270,6 @@
/* signal 'byte ready' */
via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
}
- else if(macintosh_config->adb_type==MAC_ADB_II)
- {
- via_write(via1, vSR, req->data[data_index++]);
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
- }
}
break;
@@ -2169,24 +2345,6 @@
Handshake anyway?? */
}
}
- if(macintosh_config->adb_type==MAC_ADB_II)
- {
- if( status == TIP)
- {
- via_write(via1, vBufB,
- via_read(via1, vBufB)|TACK|TIP);
- adb_state = read_done;
- }
- else
- {
-#if (ADBDEBUG & ADBDEBUG_STATUS)
- if(status!=TIP+TREQ)
- printk("macII_adb: state=reading status=%x\n", status);
-#endif
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
- }
- }
/* fall through for IIsi on end of frame */
if (macintosh_config->adb_type != MAC_ADB_IISI
|| adb_state != read_done)
@@ -2203,7 +2361,7 @@
{
req = current_req;
req->reply_len = reply_ptr - req->reply;
- req->got_reply = 1;
+ req->complete = 1;
current_req = req->next;
if (req->done)
(*req->done)(req);
@@ -2247,31 +2405,38 @@
}
+static void adb_pm_interrupt(int irq, void *arg, struct pt_regs *regs)
+{
+ printk("adb_pm_interrupt called!\n");
+}
+
/*
* The 'reply delivery' routine; determines which device sent the
* request and calls the appropriate handler.
* Reply data are expected in CUDA format (again, argh...) so we need
* to fake this in the interrupt handler for MacII.
+ *
+ * Note! The PowerPC code now expects data in ADB format, and
+ * has their CUDA handler throw non-ADB packets on the floor. We
+ * are going to sync with them. It is only a matter of time.
+ *
* Only one handler per device ID is currently possible.
* XXX: is the ID field here representing the default or real ID?
*/
static void adb_input(unsigned char *buf, int nb, struct pt_regs *regs)
{
- int i, id;
+ int id;
switch (buf[0])
{
case ADB_PACKET:
/* what's in buf[1] ?? */
+ /* according to via-cuda.c, buf[1] should tell
+ us whether to autopoll or not */
id = buf[2] >> 4;
-#if 0
- xmon_printf("adb packet: ");
- for (i = 0; i < nb; ++i)
- xmon_printf(" %x", buf[i]);
- xmon_printf(", id = %d\n", id);
-#endif
#if (ADBDEBUG & ADBDEBUG_INPUT)
if (console_loglevel == 10) {
+ int i;
printk("adb_input: adb packet ");
for (i = 0; i < nb; ++i)
printk(" %x", buf[i]);
@@ -2287,6 +2452,7 @@
default:
#if (ADBDEBUG & ADBDEBUG_INPUT)
if (console_loglevel == 10) {
+ int i;
printk("adb_input: data from via (%d bytes):", nb);
for (i = 0; i < nb; ++i)
printk(" %.2x", buf[i]);
@@ -2338,7 +2504,7 @@
add_wait_queue(&adb_wait, &wait);
current->state = TASK_INTERRUPTIBLE;
- while (!state->req.got_reply) {
+ while (!state->req.complete) {
if (file->f_flags & O_NONBLOCK) {
ret = -EAGAIN;
break;
@@ -2358,9 +2524,9 @@
static void adb_write_done(struct adb_request *req)
{
- if (!req->got_reply) {
+ if (!req->complete) {
req->reply_len = 0;
- req->got_reply = 1;
+ req->complete = 1;
}
wake_up_interruptible(&adb_wait);
}
@@ -2371,7 +2537,7 @@
static int adb_open(struct inode *inode, struct file *file)
{
- int adb_type, adb_subtype;
+ int adb_subtype;
struct adbdev_state *state;
if (MINOR(inode->i_rdev) > ADB_MAX_MINOR)
@@ -2401,28 +2567,29 @@
return 0;
}
-static void adb_release(struct inode *inode, struct file *file)
+static int adb_release(struct inode *inode, struct file *file)
{
struct adbdev_state *state = file->private_data;
if (state) {
+ int ret;
+
file->private_data = NULL;
- if (state->req.reply_expected && !state->req.got_reply)
- if (adb_wait_reply(state, file))
- return;
+ if (state->req.reply_expected && !state->req.complete)
+ if ((ret = adb_wait_reply(state, file)))
+ return ret;
kfree(state);
}
- return;
+ return 0;
}
-static int adb_lseek(struct inode *inode, struct file *file,
- off_t offset, int origin)
+static loff_t adb_lseek(struct file *file, loff_t offset, int origin)
{
return -ESPIPE;
}
-static int adb_read(struct inode *inode, struct file *file,
- char *buf, int count)
+static ssize_t adb_read(struct file *file, char *buf,
+ size_t count, loff_t *offset)
{
int ret;
struct adbdev_state *state = file->private_data;
@@ -2449,8 +2616,8 @@
return ret;
}
-static int adb_write(struct inode *inode, struct file *file,
- const char *buf, int count)
+static ssize_t adb_write(struct file *file, const char *buf,
+ size_t count, loff_t *offset)
{
int ret, i;
struct adbdev_state *state = file->private_data;
@@ -2461,7 +2628,7 @@
if (ret)
return ret;
- if (state->req.reply_expected && !state->req.got_reply) {
+ if (state->req.reply_expected && !state->req.complete) {
/* A previous request is still being processed.
Wait for it to finish. */
ret = adb_wait_reply(state, file);
@@ -2471,7 +2638,7 @@
state->req.nbytes = count;
state->req.done = adb_write_done;
- state->req.got_reply = 0;
+ state->req.complete = 0;
copy_from_user(state->req.data, buf, count);
#if 0
switch (adb_hardware) {
@@ -2508,7 +2675,12 @@
NULL, /* no mmap */
adb_open,
NULL, /* flush */
- adb_release
+ adb_release,
+ NULL, /* fsync */
+ NULL, /* fasync */
+ NULL, /* check_media_change */
+ NULL, /* revalidate */
+ NULL /* lock */
};
int adbdev_register(int subtype, struct file_operations *fops)
@@ -2537,7 +2709,6 @@
printk(KERN_ERR "adb: unable to get major %d\n", ADB_MAJOR);
}
-
#if 0 /* old ADB device */
/*
@@ -2566,7 +2737,7 @@
add_wait_queue(&adb_wait, &wait);
current->state = TASK_INTERRUPTIBLE;
- while (!state->req.got_reply) {
+ while (!state->req.complete) {
if (file->f_flags & O_NONBLOCK) {
ret = -EAGAIN;
break;
@@ -2586,9 +2757,9 @@
static void adb_write_done(struct adb_request *req)
{
- if (!req->got_reply) {
+ if (!req->complete) {
req->reply_len = 0;
- req->got_reply = 1;
+ req->complete = 1;
}
wake_up_interruptible(&adb_wait);
}
@@ -2611,7 +2782,7 @@
if (state) {
file->private_data = NULL;
- if (state->req.reply_expected && !state->req.got_reply)
+ if (state->req.reply_expected && !state->req.complete)
if (adb_wait_reply(state, file))
return;
kfree(state);
@@ -2619,14 +2790,13 @@
return;
}
-static int adb_lseek(struct inode *inode, struct file *file,
- off_t offset, int origin)
+static int adb_lseek(struct file *file, loff_t offset, int origin)
{
return -ESPIPE;
}
-static int adb_read(struct inode *inode, struct file *file,
- char *buf, int count)
+static int adb_read(struct file *file, char *buf, size_t count,
+ loff_t *offset)
{
int ret;
struct adbdev_state *state = file->private_data;
@@ -2653,8 +2823,8 @@
return ret;
}
-static int adb_write(struct inode *inode, struct file *file,
- const char *buf, int count)
+static int adb_write(struct file *file, const char *buf,
+ size_t count, loff_t *offset)
{
int ret;
struct adbdev_state *state = file->private_data;
@@ -2665,7 +2835,7 @@
if (ret)
return ret;
- if (state->req.reply_expected && !state->req.got_reply) {
+ if (state->req.reply_expected && !state->req.complete) {
/* A previous request is still being processed.
Wait for it to finish. */
ret = adb_wait_reply(state, file);
@@ -2677,7 +2847,7 @@
state->req.done = adb_write_done;
memcpy_fromfs(state->req.data, buf, count);
state->req.reply_expected = 1;
- state->req.got_reply = 0;
+ state->req.complete = 0;
adb_send_request(&state->req);
return count;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)