// SPDX-License-Identifier: GPL-2.0 /* * Device driver for the via ADB on (many) Mac II-class machines * * Based on the original ADB keyboard handler Copyright (c) 1997 Alan Cox * Also derived from code Copyright (C) 1996 Paul Mackerras. * * With various updates provided over the years by Michael Schmitz, * Guideo Koerber and others. * * Rewrite for Unified ADB by Joshua M. Thompson (funaho@jurai.org) * * 1999-08-02 (jmt) - Initial rewrite for Unified ADB. * 2000-03-29 Tony Mantler <tonym@mac.linux-m68k.org> * - Big overhaul, should actually work now. * 2006-12-31 Finn Thain - Another overhaul. * * Suggested reading: * Inside Macintosh, ch. 5 ADB Manager * Guide to the Macinstosh Family Hardware, ch. 8 Apple Desktop Bus * Rockwell R6522 VIA datasheet * * Apple's "ADB Analyzer" bus sniffer is invaluable: * ftp://ftp.apple.com/developer/Tool_Chest/Devices_-_Hardware/Apple_Desktop_Bus/
*/ #include <linux/types.h> #include <linux/errno.h> #include <linux/kernel.h> #include <linux/delay.h> #include <linux/adb.h> #include <linux/interrupt.h> #include <linux/init.h> #include <asm/macintosh.h> #include <asm/macints.h> #include <asm/mac_via.h>
/* Bits in B data register: all active low */ #define CTLR_IRQ 0x08 /* Controller rcv status (input) */ #define ST_MASK 0x30 /* mask for selecting ADB state bits */
/* Bits in ACR */ #define SR_CTRL 0x1c /* Shift register control bits */ #define SR_EXT 0x0c /* Shift on external clock */ #define SR_OUT 0x10 /* Shift out if 1 */
/* Bits in IFR and IER */ #define IER_SET 0x80 /* set bits in IER */ #define IER_CLR 0 /* clear bits in IER */ #define SR_INT 0x04 /* Shift register full/empty */
/* ADB transaction states according to GMHW */ #define ST_CMD 0x00 /* ADB state: command byte */ #define ST_EVEN 0x10 /* ADB state: even data byte */ #define ST_ODD 0x20 /* ADB state: odd data byte */ #define ST_IDLE 0x30 /* ADB state: idle, nothing to send */
staticstruct adb_request *current_req; /* first request struct in the queue */ staticstruct adb_request *last_req; /* last request struct in the queue */ staticunsignedchar reply_buf[16]; /* storage for autopolled replies */ staticunsignedchar *reply_ptr; /* next byte in reply_buf or req->reply */ staticbool reading_reply; /* store reply in reply_buf else req->reply */ staticint data_index; /* index of the next byte to send from req->data */ staticint reply_len; /* number of bytes received in reply_buf or req->reply */ staticint status; /* VIA's ADB status bits captured upon interrupt */ staticbool bus_timeout; /* no data was sent by the device */ staticbool srq_asserted; /* have to poll for the device that asserted it */ static u8 last_cmd; /* the most recent command byte transmitted */ static u8 last_talk_cmd; /* the most recent Talk command byte transmitted */ static u8 last_poll_cmd; /* the most recent Talk R0 command byte transmitted */ staticunsignedint autopoll_devs; /* bits set are device addresses to poll */
/* Check for MacII style ADB */ staticint macii_probe(void)
{ if (macintosh_config->adb_type != MAC_ADB_II) return -ENODEV;
via = via1;
pr_info("adb: Mac II ADB Driver v1.0 for Unified ADB\n"); return 0;
}
/* Initialize the driver */ staticint macii_init(void)
{ int err;
/* Send an ADB poll (Talk Register 0 command prepended to the request queue) */ staticvoid macii_queue_poll(void)
{ staticstruct adb_request req; unsignedchar poll_command; unsignedint poll_addr;
/* This only polls devices in the autopoll list, which assumes that * unprobed devices never assert SRQ. That could happen if a device was * plugged in after the adb bus scan. Unplugging it again will resolve * the problem. This behaviour is similar to MacOS.
*/ if (!autopoll_devs) return;
/* The device most recently polled may not be the best device to poll * right now. Some other device(s) may have signalled SRQ (the active * device won't do that). Or the autopoll list may have been changed. * Try polling the next higher address.
*/
poll_addr = (last_poll_cmd & ADDR_MASK) >> 4; if ((srq_asserted && last_cmd == last_poll_cmd) ||
!(autopoll_devs & (1 << poll_addr))) { unsignedint higher_devs;
/* Now send it. Be careful though, that first byte of the request * is actually ADB_PACKET; the real data begins at index 1! * And req->nbytes is the number of bytes of real data plus one.
*/
/* Output mode */
via[ACR] |= SR_OUT; /* Load data */
via[SR] = req->data[1]; /* set ADB state to 'command' */
via[B] = (via[B] & ~ST_MASK) | ST_CMD;
macii_state = sending;
data_index = 2;
bus_timeout = false;
srq_asserted = false;
}
/* * The notorious ADB interrupt handler - does all of the protocol handling. * Relies on the ADB controller sending and receiving data, thereby * generating shift register interrupts (SR_INT) for us. This means there has * to be activity on the ADB bus. The chip will poll to achieve this. * * The VIA Port B output signalling works as follows. After the ADB transceiver * sees a transition on the PB4 and PB5 lines it will crank over the VIA shift * register which eventually raises the SR_INT interrupt. The PB4/PB5 outputs * are toggled with each byte as the ADB transaction progresses. * * Request with no reply expected (and empty transceiver buffer): * CMD -> IDLE * Request with expected reply packet (or with buffered autopoll packet): * CMD -> EVEN -> ODD -> EVEN -> ... -> IDLE * Unsolicited packet: * IDLE -> EVEN -> ODD -> EVEN -> ... -> IDLE
*/ static irqreturn_t macii_interrupt(int irq, void *arg)
{ int x; struct adb_request *req; unsignedlong flags;
local_irq_save(flags);
if (!arg) { /* Clear the SR IRQ flag when polling. */ if (via[IFR] & SR_INT)
via[IFR] = SR_INT; else {
local_irq_restore(flags); return IRQ_NONE;
}
}
status = via[B] & (ST_MASK | CTLR_IRQ);
switch (macii_state) { case idle:
WARN_ON((status & ST_MASK) != ST_IDLE);
reply_ptr = reply_buf;
reading_reply = false;
bus_timeout = false;
srq_asserted = false;
x = via[SR];
if (!(status & CTLR_IRQ)) { /* /CTLR_IRQ asserted in idle state means we must * read an autopoll reply from the transceiver buffer.
*/
macii_state = reading;
*reply_ptr = x;
reply_len = 1;
} else { /* bus timeout */
reply_len = 0; break;
}
/* set ADB state = even for first data byte */
via[B] = (via[B] & ~ST_MASK) | ST_EVEN; break;
case sending:
req = current_req;
if (status == (ST_CMD | CTLR_IRQ)) { /* /CTLR_IRQ de-asserted after the command byte means * the host can continue with the transaction.
*/
/* Store command byte */
last_cmd = req->data[1]; if ((last_cmd & OP_MASK) == TALK) {
last_talk_cmd = last_cmd; if ((last_cmd & CMD_MASK) == ADB_READREG(0, 0))
last_poll_cmd = last_cmd;
}
}
if (status == ST_CMD) { /* /CTLR_IRQ asserted after the command byte means we * must read an autopoll reply. The first byte was * lost because the shift register was an output.
*/
macii_state = reading;
if ((via[B] & ST_MASK) == ST_CMD) { /* just sent the command byte, set to EVEN */
via[B] = (via[B] & ~ST_MASK) | ST_EVEN;
} else { /* invert state bits, toggle ODD/EVEN */
via[B] ^= ST_MASK;
} break;
case reading:
x = via[SR];
WARN_ON((status & ST_MASK) == ST_CMD ||
(status & ST_MASK) == ST_IDLE);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.