Blame view
drivers/macintosh/via-macii.c
14.1 KB
b24413180
|
1 |
// SPDX-License-Identifier: GPL-2.0 |
1da177e4c
|
2 3 4 5 6 7 8 9 10 11 12 13 14 |
/* * 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> |
47fd20606
|
15 |
* - Big overhaul, should actually work now. |
d0c2c269a
|
16 |
* 2006-12-31 Finn Thain - Another overhaul. |
d95fd5fce
|
17 18 19 20 21 22 23 24 |
* * 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/ |
1da177e4c
|
25 |
*/ |
47fd20606
|
26 |
|
1da177e4c
|
27 28 29 30 31 |
#include <stdarg.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/kernel.h> #include <linux/delay.h> |
1da177e4c
|
32 33 34 35 36 |
#include <linux/adb.h> #include <linux/interrupt.h> #include <linux/init.h> #include <asm/macintosh.h> #include <asm/macints.h> |
1da177e4c
|
37 |
#include <asm/mac_via.h> |
1da177e4c
|
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
static volatile unsigned char *via; /* VIA registers - spaced 0x200 bytes apart */ #define RS 0x200 /* skip between registers */ #define B 0 /* B-side data */ #define A RS /* A-side data */ #define DIRB (2*RS) /* B-side direction (1=output) */ #define DIRA (3*RS) /* A-side direction (1=output) */ #define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */ #define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */ #define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */ #define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */ #define T2CL (8*RS) /* Timer 2 ctr/latch (low 8 bits) */ #define T2CH (9*RS) /* Timer 2 counter (high 8 bits) */ #define SR (10*RS) /* Shift register */ #define ACR (11*RS) /* Auxiliary control register */ #define PCR (12*RS) /* Peripheral control register */ #define IFR (13*RS) /* Interrupt flag register */ #define IER (14*RS) /* Interrupt enable register */ #define ANH (15*RS) /* A-side data, no handshake */ /* Bits in B data register: all active low */ |
d95fd5fce
|
61 |
#define CTLR_IRQ 0x08 /* Controller rcv status (input) */ |
1da177e4c
|
62 63 64 65 66 67 68 69 70 71 72 |
#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 */ |
1da177e4c
|
73 74 75 76 77 78 |
/* 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 */ |
f93bfeb55
|
79 80 81 |
/* ADB command byte structure */ #define ADDR_MASK 0xF0 #define CMD_MASK 0x0F |
b4d76c28e
|
82 83 |
#define OP_MASK 0x0C #define TALK 0x0C |
f93bfeb55
|
84 |
|
47fd20606
|
85 |
static int macii_init_via(void); |
1da177e4c
|
86 |
static void macii_start(void); |
7d12e780e
|
87 |
static irqreturn_t macii_interrupt(int irq, void *arg); |
1da177e4c
|
88 89 90 91 92 93 94 95 96 97 98 |
static void macii_queue_poll(void); static int macii_probe(void); static int macii_init(void); static int macii_send_request(struct adb_request *req, int sync); static int macii_write(struct adb_request *req); static int macii_autopoll(int devs); static void macii_poll(void); static int macii_reset_bus(void); struct adb_driver via_macii_driver = { |
3a52f6f98
|
99 100 101 102 103 104 105 |
.name = "Mac II", .probe = macii_probe, .init = macii_init, .send_request = macii_send_request, .autopoll = macii_autopoll, .poll = macii_poll, .reset_bus = macii_reset_bus, |
1da177e4c
|
106 107 108 109 110 111 |
}; static enum macii_state { idle, sending, reading, |
1da177e4c
|
112 |
} macii_state; |
d95fd5fce
|
113 114 115 |
static struct adb_request *current_req; /* first request struct in the queue */ static struct adb_request *last_req; /* last request struct in the queue */ static unsigned char reply_buf[16]; /* storage for autopolled replies */ |
eb4da4cec
|
116 |
static unsigned char *reply_ptr; /* next byte in reply_buf or req->reply */ |
f87a16257
|
117 |
static bool reading_reply; /* store reply in reply_buf else req->reply */ |
d95fd5fce
|
118 119 120 |
static int data_index; /* index of the next byte to send from req->data */ static int reply_len; /* number of bytes received in reply_buf or req->reply */ static int status; /* VIA's ADB status bits captured upon interrupt */ |
b4d76c28e
|
121 122 |
static bool bus_timeout; /* no data was sent by the device */ static bool srq_asserted; /* have to poll for the device that asserted it */ |
f93bfeb55
|
123 |
static u8 last_cmd; /* the most recent command byte transmitted */ |
b4d76c28e
|
124 |
static u8 last_talk_cmd; /* the most recent Talk command byte transmitted */ |
f93bfeb55
|
125 |
static u8 last_poll_cmd; /* the most recent Talk R0 command byte transmitted */ |
5c0c15a19
|
126 |
static unsigned int autopoll_devs; /* bits set are device addresses to poll */ |
d95fd5fce
|
127 |
|
1da177e4c
|
128 129 130 |
/* Check for MacII style ADB */ static int macii_probe(void) { |
47fd20606
|
131 132 |
if (macintosh_config->adb_type != MAC_ADB_II) return -ENODEV; |
1da177e4c
|
133 134 |
via = via1; |
351e5ad32
|
135 136 |
pr_info("adb: Mac II ADB Driver v1.0 for Unified ADB "); |
1da177e4c
|
137 138 139 140 |
return 0; } /* Initialize the driver */ |
3327e58a0
|
141 |
static int macii_init(void) |
1da177e4c
|
142 143 144 |
{ unsigned long flags; int err; |
47fd20606
|
145 |
|
1da177e4c
|
146 |
local_irq_save(flags); |
47fd20606
|
147 |
|
1da177e4c
|
148 |
err = macii_init_via(); |
47fd20606
|
149 150 |
if (err) goto out; |
1da177e4c
|
151 |
|
5a2394534
|
152 |
err = request_irq(IRQ_MAC_ADB, macii_interrupt, 0, "ADB", |
1da177e4c
|
153 |
macii_interrupt); |
47fd20606
|
154 155 |
if (err) goto out; |
1da177e4c
|
156 157 |
macii_state = idle; |
d95fd5fce
|
158 |
out: |
1da177e4c
|
159 |
local_irq_restore(flags); |
d95fd5fce
|
160 |
return err; |
1da177e4c
|
161 |
} |
47fd20606
|
162 |
/* initialize the hardware */ |
1da177e4c
|
163 164 165 |
static int macii_init_via(void) { unsigned char x; |
d95fd5fce
|
166 167 |
/* We want CTLR_IRQ as input and ST_EVEN | ST_ODD as output lines. */ via[DIRB] = (via[DIRB] | ST_EVEN | ST_ODD) & ~CTLR_IRQ; |
1da177e4c
|
168 169 170 |
/* Set up state: idle */ via[B] |= ST_IDLE; |
1da177e4c
|
171 172 173 174 175 176 177 178 179 |
/* Shift register on input */ via[ACR] = (via[ACR] & ~SR_CTRL) | SR_EXT; /* Wipe any pending data and int */ x = via[SR]; return 0; } |
d95fd5fce
|
180 |
/* Send an ADB poll (Talk Register 0 command prepended to the request queue) */ |
1da177e4c
|
181 182 |
static void macii_queue_poll(void) { |
1da177e4c
|
183 |
static struct adb_request req; |
f93bfeb55
|
184 185 |
unsigned char poll_command; unsigned int poll_addr; |
1da177e4c
|
186 |
|
f93bfeb55
|
187 188 189 190 191 |
/* 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. */ |
47fd20606
|
192 193 |
if (!autopoll_devs) return; |
1da177e4c
|
194 |
|
f93bfeb55
|
195 196 197 198 199 200 201 202 203 204 205 206 207 |
/* 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))) { unsigned int higher_devs; higher_devs = autopoll_devs & -(1 << (poll_addr + 1)); poll_addr = ffs(higher_devs ? higher_devs : autopoll_devs) - 1; } |
1da177e4c
|
208 |
|
f93bfeb55
|
209 210 211 212 213 214 215 216 217 218 |
/* Send a Talk Register 0 command */ poll_command = ADB_READREG(poll_addr, 0); /* No need to repeat this Talk command. The transceiver will do that * as long as it is idle. */ if (poll_command == last_cmd) return; adb_request(&req, NULL, ADBREQ_NOSEND, 1, poll_command); |
1da177e4c
|
219 |
|
d95fd5fce
|
220 221 222 223 |
req.sent = 0; req.complete = 0; req.reply_len = 0; req.next = current_req; |
1da177e4c
|
224 |
|
f93bfeb55
|
225 |
if (WARN_ON(current_req)) { |
d95fd5fce
|
226 |
current_req = &req; |
1da177e4c
|
227 |
} else { |
d95fd5fce
|
228 229 |
current_req = &req; last_req = &req; |
1da177e4c
|
230 |
} |
1da177e4c
|
231 232 233 234 235 |
} /* Send an ADB request; if sync, poll out the reply 'till it's done */ static int macii_send_request(struct adb_request *req, int sync) { |
d95fd5fce
|
236 |
int err; |
1da177e4c
|
237 |
|
d95fd5fce
|
238 |
err = macii_write(req); |
5ce6185c2
|
239 240 |
if (err) return err; |
d95fd5fce
|
241 |
|
5ce6185c2
|
242 |
if (sync) |
5f93d7081
|
243 |
while (!req->complete) |
d95fd5fce
|
244 |
macii_poll(); |
d95fd5fce
|
245 |
|
5ce6185c2
|
246 |
return 0; |
1da177e4c
|
247 |
} |
d95fd5fce
|
248 |
/* Send an ADB request (append to request queue) */ |
1da177e4c
|
249 250 |
static int macii_write(struct adb_request *req) { |
5ce6185c2
|
251 |
unsigned long flags; |
1da177e4c
|
252 253 254 255 |
if (req->nbytes < 2 || req->data[0] != ADB_PACKET || req->nbytes > 15) { req->complete = 1; return -EINVAL; } |
47fd20606
|
256 |
|
a5d361fc2
|
257 |
req->next = NULL; |
1da177e4c
|
258 259 260 |
req->sent = 0; req->complete = 0; req->reply_len = 0; |
5ce6185c2
|
261 |
local_irq_save(flags); |
1da177e4c
|
262 263 264 265 266 267 |
if (current_req != NULL) { last_req->next = req; last_req = req; } else { current_req = req; last_req = req; |
47fd20606
|
268 269 |
if (macii_state == idle) macii_start(); |
1da177e4c
|
270 |
} |
5ce6185c2
|
271 272 |
local_irq_restore(flags); |
1da177e4c
|
273 274 275 276 277 278 |
return 0; } /* Start auto-polling */ static int macii_autopoll(int devs) { |
d95fd5fce
|
279 |
unsigned long flags; |
d95fd5fce
|
280 |
|
59ea38f6b
|
281 |
local_irq_save(flags); |
d95fd5fce
|
282 |
/* bit 1 == device 1, and so on. */ |
5c0c15a19
|
283 |
autopoll_devs = (unsigned int)devs & 0xFFFE; |
d95fd5fce
|
284 |
|
f93bfeb55
|
285 286 287 288 |
if (!current_req) { macii_queue_poll(); if (current_req && macii_state == idle) macii_start(); |
d95fd5fce
|
289 290 291 |
} local_irq_restore(flags); |
d95fd5fce
|
292 |
|
f93bfeb55
|
293 |
return 0; |
1da177e4c
|
294 295 296 297 298 |
} /* Prod the chip without interrupts */ static void macii_poll(void) { |
d95fd5fce
|
299 |
macii_interrupt(0, NULL); |
1da177e4c
|
300 301 302 303 304 |
} /* Reset the bus */ static int macii_reset_bus(void) { |
046ace825
|
305 |
struct adb_request req; |
47fd20606
|
306 |
|
1da177e4c
|
307 |
/* Command = 0, Address = ignored */ |
b52dce873
|
308 309 |
adb_request(&req, NULL, ADBREQ_NOSEND, 1, ADB_BUSRESET); macii_send_request(&req, 1); |
1da177e4c
|
310 |
|
d95fd5fce
|
311 312 |
/* Don't want any more requests during the Global Reset low time. */ udelay(3000); |
1da177e4c
|
313 314 315 316 317 318 |
return 0; } /* Start sending ADB packet */ static void macii_start(void) { |
1da177e4c
|
319 320 321 |
struct adb_request *req; req = current_req; |
1da177e4c
|
322 |
|
d95fd5fce
|
323 324 325 |
/* 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. |
1da177e4c
|
326 |
*/ |
1da177e4c
|
327 |
|
1da177e4c
|
328 329 330 331 332 333 334 335 336 |
/* 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; |
b4d76c28e
|
337 338 339 |
bus_timeout = false; srq_asserted = false; |
1da177e4c
|
340 341 342 |
} /* |
d95fd5fce
|
343 344 345 346 |
* 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. |
1da177e4c
|
347 |
* |
b4d76c28e
|
348 349 350 351 352 353 354 355 356 357 358 |
* 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 |
1da177e4c
|
359 |
*/ |
7d12e780e
|
360 |
static irqreturn_t macii_interrupt(int irq, void *arg) |
1da177e4c
|
361 |
{ |
d95fd5fce
|
362 |
int x; |
1da177e4c
|
363 |
struct adb_request *req; |
5ce6185c2
|
364 365 366 |
unsigned long flags; local_irq_save(flags); |
1da177e4c
|
367 |
|
d95fd5fce
|
368 369 370 371 |
if (!arg) { /* Clear the SR IRQ flag when polling. */ if (via[IFR] & SR_INT) via[IFR] = SR_INT; |
5ce6185c2
|
372 373 |
else { local_irq_restore(flags); |
d95fd5fce
|
374 |
return IRQ_NONE; |
5ce6185c2
|
375 |
} |
1da177e4c
|
376 |
} |
47fd20606
|
377 |
status = via[B] & (ST_MASK | CTLR_IRQ); |
1da177e4c
|
378 379 |
switch (macii_state) { |
47fd20606
|
380 |
case idle: |
b4d76c28e
|
381 382 383 |
WARN_ON((status & ST_MASK) != ST_IDLE); reply_ptr = reply_buf; |
f87a16257
|
384 |
reading_reply = false; |
b4d76c28e
|
385 386 387 |
bus_timeout = false; srq_asserted = false; |
d95fd5fce
|
388 |
|
47fd20606
|
389 |
x = via[SR]; |
1da177e4c
|
390 |
|
b4d76c28e
|
391 392 393 |
if (!(status & CTLR_IRQ)) { /* /CTLR_IRQ asserted in idle state means we must * read an autopoll reply from the transceiver buffer. |
47fd20606
|
394 |
*/ |
47fd20606
|
395 396 397 |
macii_state = reading; *reply_ptr = x; reply_len = 1; |
b4d76c28e
|
398 399 |
} else { /* bus timeout */ |
b4d76c28e
|
400 |
reply_len = 0; |
b16b67689
|
401 |
break; |
47fd20606
|
402 |
} |
1da177e4c
|
403 |
|
47fd20606
|
404 405 406 |
/* set ADB state = even for first data byte */ via[B] = (via[B] & ~ST_MASK) | ST_EVEN; break; |
1da177e4c
|
407 |
|
47fd20606
|
408 409 |
case sending: req = current_req; |
b4d76c28e
|
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 |
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; |
f87a16257
|
431 |
reading_reply = false; |
b4d76c28e
|
432 433 434 435 436 437 438 439 |
reply_ptr = reply_buf; *reply_ptr = last_talk_cmd; reply_len = 1; /* reset to shift in */ via[ACR] &= ~SR_OUT; x = via[SR]; } else if (data_index >= req->nbytes) { |
47fd20606
|
440 |
req->sent = 1; |
d95fd5fce
|
441 |
|
47fd20606
|
442 |
if (req->reply_expected) { |
b4d76c28e
|
443 |
macii_state = reading; |
f87a16257
|
444 |
reading_reply = true; |
b4d76c28e
|
445 446 447 448 449 450 |
reply_ptr = req->reply; *reply_ptr = req->data[1]; reply_len = 1; via[ACR] &= ~SR_OUT; x = via[SR]; |
624cf5b53
|
451 452 |
} else if ((req->data[1] & OP_MASK) == TALK) { macii_state = reading; |
f87a16257
|
453 |
reading_reply = false; |
624cf5b53
|
454 455 456 457 458 459 460 461 462 463 464 |
reply_ptr = reply_buf; *reply_ptr = req->data[1]; reply_len = 1; via[ACR] &= ~SR_OUT; x = via[SR]; req->complete = 1; current_req = req->next; if (req->done) (*req->done)(req); |
1da177e4c
|
465 |
} else { |
b4d76c28e
|
466 |
macii_state = idle; |
47fd20606
|
467 468 469 470 |
req->complete = 1; current_req = req->next; if (req->done) (*req->done)(req); |
b4d76c28e
|
471 |
break; |
1da177e4c
|
472 |
} |
47fd20606
|
473 474 |
} else { via[SR] = req->data[data_index++]; |
b4d76c28e
|
475 |
} |
1da177e4c
|
476 |
|
b4d76c28e
|
477 478 479 480 481 482 |
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; |
47fd20606
|
483 484 |
} break; |
1da177e4c
|
485 |
|
47fd20606
|
486 487 488 489 |
case reading: x = via[SR]; WARN_ON((status & ST_MASK) == ST_CMD || (status & ST_MASK) == ST_IDLE); |
47fd20606
|
490 |
if (!(status & CTLR_IRQ)) { |
b4d76c28e
|
491 492 493 494 495 |
if (status == ST_EVEN && reply_len == 1) { bus_timeout = true; } else if (status == ST_ODD && reply_len == 2) { srq_asserted = true; } else { |
b16b67689
|
496 497 498 499 500 501 502 503 504 505 506 507 508 509 |
macii_state = idle; if (bus_timeout) reply_len = 0; if (reading_reply) { struct adb_request *req = current_req; req->reply_len = reply_len; req->complete = 1; current_req = req->next; if (req->done) (*req->done)(req); |
624cf5b53
|
510 511 512 |
} else if (reply_len && autopoll_devs && reply_buf[0] == last_poll_cmd) { adb_input(reply_buf, reply_len, 1); |
b16b67689
|
513 514 |
} break; |
47fd20606
|
515 516 |
} } |
1da177e4c
|
517 |
|
b16b67689
|
518 |
if (reply_len < ARRAY_SIZE(reply_buf)) { |
47fd20606
|
519 520 521 522 |
reply_ptr++; *reply_ptr = x; reply_len++; } |
1da177e4c
|
523 |
|
47fd20606
|
524 525 526 |
/* invert state bits, toggle ODD/EVEN */ via[B] ^= ST_MASK; break; |
1da177e4c
|
527 |
|
b16b67689
|
528 529 530 |
default: break; } |
47fd20606
|
531 |
|
b16b67689
|
532 |
if (macii_state == idle) { |
f93bfeb55
|
533 |
if (!current_req) |
47fd20606
|
534 535 536 537 |
macii_queue_poll(); if (current_req) macii_start(); |
47fd20606
|
538 |
|
b16b67689
|
539 540 541 |
if (macii_state == idle) { via[ACR] &= ~SR_OUT; x = via[SR]; |
47fd20606
|
542 |
via[B] = (via[B] & ~ST_MASK) | ST_IDLE; |
b16b67689
|
543 |
} |
1da177e4c
|
544 |
} |
d95fd5fce
|
545 |
|
5ce6185c2
|
546 |
local_irq_restore(flags); |
1da177e4c
|
547 548 |
return IRQ_HANDLED; } |