11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Device driver for the IIsi-style ADB on some Mac LC and II-class machines 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Based on via-cuda.c and via-macii.c, as well as the original 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * adb-bus.c, which in turn is somewhat influenced by (but uses no 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * code from) the NetBSD HWDIRECT ADB code. Original IIsi driver work 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * was done by Robert Thompson and integrated into the old style 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * driver by Michael Schmitz. 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Original sources (c) Alan Cox, Paul Mackerras, and others. 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Rewritten for Unified ADB by David Huggins-Daines <dhd@debian.org> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7/13/2000- extensive changes by Andrew McPherson <andrew@macduff.dhs.org> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Works about 30% of the time now. 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/adb.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/cuda.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/macintosh.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/macints.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/mac_via.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic volatile unsigned char *via; 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* VIA registers - spaced 0x200 bytes apart - only the ones we actually use */ 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RS 0x200 /* skip between registers */ 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define B 0 /* B-side data */ 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define A RS /* A-side data */ 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DIRB (2*RS) /* B-side direction (1=output) */ 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DIRA (3*RS) /* A-side direction (1=output) */ 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SR (10*RS) /* Shift register */ 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACR (11*RS) /* Auxiliary control register */ 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IFR (13*RS) /* Interrupt flag register */ 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IER (14*RS) /* Interrupt enable register */ 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Bits in B data register: all active low */ 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TREQ 0x08 /* Transfer request (input) */ 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TACK 0x10 /* Transfer acknowledge (output) */ 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TIP 0x20 /* Transfer in progress (output) */ 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ST_MASK 0x30 /* mask for selecting ADB state bits */ 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Bits in ACR */ 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SR_CTRL 0x1c /* Shift register control bits */ 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SR_EXT 0x0c /* Shift on external clock */ 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SR_OUT 0x10 /* Shift out if 1 */ 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Bits in IFR and IER */ 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IER_SET 0x80 /* set bits in IER */ 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IER_CLR 0 /* clear bits in IER */ 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SR_INT 0x04 /* Shift register full/empty */ 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SR_DATA 0x08 /* Shift register data */ 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SR_CLOCK 0x10 /* Shift register clock */ 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ADB_DELAY 150 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef DEBUG_MACIISI_ADB 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 64872758563d7f132d25fc06857bd19df06c5c70c7Olaf Heringstatic struct adb_request* current_req; 65872758563d7f132d25fc06857bd19df06c5c70c7Olaf Heringstatic struct adb_request* last_req; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned char maciisi_rbuf[16]; 67872758563d7f132d25fc06857bd19df06c5c70c7Olaf Heringstatic unsigned char *reply_ptr; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int data_index; 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int reading_reply; 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int reply_len; 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tmp; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int need_sync; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic enum maciisi_state { 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds idle, 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sending, 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reading, 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} maciisi_state; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int maciisi_probe(void); 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int maciisi_init(void); 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int maciisi_send_request(struct adb_request* req, int sync); 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void maciisi_sync(struct adb_request *req); 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int maciisi_write(struct adb_request* req); 857d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t maciisi_interrupt(int irq, void* arg); 867d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void maciisi_input(unsigned char *buf, int nb); 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int maciisi_init_via(void); 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void maciisi_poll(void); 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int maciisi_start(void); 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct adb_driver via_maciisi_driver = { 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Mac IIsi", 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maciisi_probe, 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maciisi_init, 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maciisi_send_request, 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NULL, /* maciisi_adb_autopoll, */ 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maciisi_poll, 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NULL /* maciisi_reset_adb_bus */ 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmaciisi_probe(void) 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (macintosh_config->adb_type != MAC_ADB_IISI) 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via = via1; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmaciisi_init(void) 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (via == NULL) 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((err = maciisi_init_via())) { 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "maciisi_init: maciisi_init_via() failed, code %d\n", err); 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via = NULL; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1255a2394534b160ce18f9a705cf9de40e77648f8a2Geert Uytterhoeven if (request_irq(IRQ_MAC_ADB, maciisi_interrupt, 0, "ADB", 1265a2394534b160ce18f9a705cf9de40e77648f8a2Geert Uytterhoeven maciisi_interrupt)) { 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "maciisi_init: can't get irq %d\n", IRQ_MAC_ADB); 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EAGAIN; 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("adb: Mac IIsi driver v0.2 for Unified ADB.\n"); 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Flush data from the ADB controller */ 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmaciisi_stfu(void) 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status = via[B] & (TIP|TREQ); 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & TREQ) { 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_MACIISI_ADB 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk (KERN_DEBUG "maciisi_stfu called with TREQ high!\n"); 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(ADB_DELAY); 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[ACR] &= ~SR_OUT; 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[IER] = IER_CLR | SR_INT; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(ADB_DELAY); 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = via[B] & (TIP|TREQ); 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(status & TREQ)) 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[B] |= TIP; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while(1) 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int poll_timeout = ADB_DELAY * 5; 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Poll for SR interrupt */ 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (!(via[IFR] & SR_INT) && poll_timeout-- > 0) 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = via[B] & (TIP|TREQ); 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = via[SR]; /* Clear shift register */ 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_MACIISI_ADB 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "maciisi_stfu: status %x timeout %d data %x\n", 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status, poll_timeout, tmp); 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(via[B] & TREQ) 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ACK on-off */ 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[B] |= TACK; 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(ADB_DELAY); 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[B] &= ~TACK; 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* end frame */ 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[B] &= ~TIP; 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(ADB_DELAY); 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[IER] = IER_SET | SR_INT; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* All specifically VIA-related initialization goes here */ 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmaciisi_init_via(void) 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set the lines up. We want TREQ as input TACK|TIP as output */ 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[DIRB] = (via[DIRB] | TACK | TIP) & ~TREQ; 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Shift register on input */ 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[ACR] = (via[ACR] & ~SR_CTRL) | SR_EXT; 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_MACIISI_ADB 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "maciisi_init_via: initial status %x\n", via[B] & (TIP|TREQ)); 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Wipe any pending data and int */ 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = via[SR]; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Enable keyboard interrupts */ 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[IER] = IER_SET | SR_INT; 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set initial state: idle */ 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[B] &= ~(TACK|TIP); 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Clear interrupt bit */ 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[IFR] = SR_INT; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for(i = 0; i < 60; i++) { 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(ADB_DELAY); 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maciisi_stfu(); 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(ADB_DELAY); 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(via[B] & TREQ) 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i == 60) 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "maciisi_init_via: bus jam?\n"); 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maciisi_state = idle; 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds need_sync = 0; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Send a request, possibly waiting for a reply */ 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmaciisi_send_request(struct adb_request* req, int sync) 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_MACIISI_ADB 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static int dump_packet = 0; 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (via == NULL) { 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req->complete = 1; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENXIO; 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_MACIISI_ADB 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dump_packet) { 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "maciisi_send_request:"); 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < req->nbytes; i++) { 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" %.2x", req->data[i]); 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" sync %d\n", sync); 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req->reply_expected = 1; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = maciisi_write(req); 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i) 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Normally, if a packet requires syncing, that happens at the end of 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * maciisi_send_request. But if the transfer fails, it will be restarted 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * by maciisi_interrupt(). We use need_sync to tell maciisi_interrupt 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * when to sync a packet that it sends out. 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Suggestions on a better way to do this are welcome. 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(i == -EBUSY && sync) 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds need_sync = 1; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds need_sync = 0; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return i; 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(sync) 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maciisi_sync(req); 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Poll the ADB chip until the request completes */ 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void maciisi_sync(struct adb_request *req) 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int count = 0; 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_MACIISI_ADB 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "maciisi_sync called\n"); 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* If for some reason the ADB chip shuts up on us, we want to avoid an endless loop. */ 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (!req->complete && count++ < 50) { 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maciisi_poll(); 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This could be BAD... when the ADB controller doesn't respond 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for this long, it's probably not coming back :-( */ 291dac9ff79a8122b30176e23359bb879b3144d7f1fRoel Kluin if (count > 50) /* Hopefully shouldn't happen */ 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "maciisi_send_request: poll timed out!\n"); 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2953272244c2b1a8f13cec83c04b8245fa7fcb47a27Al Viroint 2963272244c2b1a8f13cec83c04b8245fa7fcb47a27Al Viromaciisi_request(struct adb_request *req, void (*done)(struct adb_request *), 2973272244c2b1a8f13cec83c04b8245fa7fcb47a27Al Viro int nbytes, ...) 2983272244c2b1a8f13cec83c04b8245fa7fcb47a27Al Viro{ 2993272244c2b1a8f13cec83c04b8245fa7fcb47a27Al Viro va_list list; 3003272244c2b1a8f13cec83c04b8245fa7fcb47a27Al Viro int i; 3013272244c2b1a8f13cec83c04b8245fa7fcb47a27Al Viro 3023272244c2b1a8f13cec83c04b8245fa7fcb47a27Al Viro req->nbytes = nbytes; 3033272244c2b1a8f13cec83c04b8245fa7fcb47a27Al Viro req->done = done; 3043272244c2b1a8f13cec83c04b8245fa7fcb47a27Al Viro req->reply_expected = 0; 3053272244c2b1a8f13cec83c04b8245fa7fcb47a27Al Viro va_start(list, nbytes); 3063272244c2b1a8f13cec83c04b8245fa7fcb47a27Al Viro for (i = 0; i < nbytes; i++) 3073272244c2b1a8f13cec83c04b8245fa7fcb47a27Al Viro req->data[i++] = va_arg(list, int); 3083272244c2b1a8f13cec83c04b8245fa7fcb47a27Al Viro va_end(list); 3093272244c2b1a8f13cec83c04b8245fa7fcb47a27Al Viro 3103272244c2b1a8f13cec83c04b8245fa7fcb47a27Al Viro return maciisi_send_request(req, 1); 3113272244c2b1a8f13cec83c04b8245fa7fcb47a27Al Viro} 3123272244c2b1a8f13cec83c04b8245fa7fcb47a27Al Viro 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Enqueue a request, and run the queue if possible */ 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmaciisi_write(struct adb_request* req) 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We will accept CUDA packets - the VIA sends them to us, so 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds it figures that we should be able to send them to it */ 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (req->nbytes < 2 || req->data[0] > CUDA_PACKET) { 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "maciisi_write: packet too small or not an ADB or CUDA packet\n"); 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req->complete = 1; 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 327a5d361fc24b75ea51e219367ee32c64422a2134fAl Viro req->next = NULL; 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req->sent = 0; 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req->complete = 0; 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req->reply_len = 0; 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq_save(flags); 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (current_req) { 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds last_req->next = req; 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds last_req = req; 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_req = req; 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds last_req = req; 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (maciisi_state == idle) 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = maciisi_start(); 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(i != 0) 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq_restore(flags); 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return i; 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_MACIISI_ADB 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "maciisi_write: would start, but state is %d\n", maciisi_state); 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq_restore(flags); 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq_restore(flags); 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmaciisi_start(void) 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adb_request* req; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status; 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_MACIISI_ADB 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = via[B] & (TIP | TREQ); 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "maciisi_start called, state=%d, status=%x, ifr=%x\n", maciisi_state, status, via[IFR]); 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (maciisi_state != idle) { 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* shouldn't happen */ 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "maciisi_start: maciisi_start called when driver busy!\n"); 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req = current_req; 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (req == NULL) 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = via[B] & (TIP|TREQ); 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(status & TREQ)) { 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_MACIISI_ADB 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "maciisi_start: bus busy - aborting\n"); 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Okay, send */ 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_MACIISI_ADB 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "maciisi_start: sending\n"); 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set state to active */ 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[B] |= TIP; 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ACK off */ 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[B] &= ~TACK; 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Delay */ 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(ADB_DELAY); 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Shift out and send */ 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[ACR] |= SR_OUT; 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[SR] = req->data[0]; 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data_index = 1; 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ACK on */ 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[B] |= TACK; 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maciisi_state = sending; 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmaciisi_poll(void) 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq_save(flags); 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (via[IFR] & SR_INT) { 4222850bc273776cbb1b510c5828e9e456dffb50a32Al Viro maciisi_interrupt(0, NULL); 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else /* avoid calling this function too quickly in a loop */ 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(ADB_DELAY); 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq_restore(flags); 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Shift register interrupt - this is *supposed* to mean that the 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds register is either full or empty. In practice, I have no idea what 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds it means :( */ 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic irqreturn_t 4347d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsmaciisi_interrupt(int irq, void* arg) 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status; 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct adb_request *req; 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_MACIISI_ADB 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static int dump_reply = 0; 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq_save(flags); 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = via[B] & (TIP|TREQ); 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_MACIISI_ADB 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "state %d status %x ifr %x\n", maciisi_state, status, via[IFR]); 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(via[IFR] & SR_INT)) { 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Shouldn't happen, we hope */ 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "maciisi_interrupt: called without interrupt flag set\n"); 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq_restore(flags); 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_NONE; 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Clear the interrupt */ 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* via[IFR] = SR_INT; */ 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch_start: 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (maciisi_state) { 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case idle: 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & TIP) 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "maciisi_interrupt: state is idle but TIP asserted!\n"); 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!reading_reply) 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(ADB_DELAY); 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Shift in */ 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[ACR] &= ~SR_OUT; 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Signal start of frame */ 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[B] |= TIP; 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Clear the interrupt (throw this value on the floor, it's useless) */ 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = via[SR]; 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ACK adb chip, high-low */ 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[B] |= TACK; 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(ADB_DELAY); 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[B] &= ~TACK; 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reply_len = 0; 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maciisi_state = reading; 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (reading_reply) { 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reply_ptr = current_req->reply; 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reply_ptr = maciisi_rbuf; 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sending: 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* via[SR]; */ 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set ACK off */ 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[B] &= ~TACK; 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req = current_req; 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(status & TREQ)) { 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* collision */ 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "maciisi_interrupt: send collision\n"); 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set idle and input */ 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[ACR] &= ~SR_OUT; 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = via[SR]; 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[B] &= ~TIP; 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Must re-send */ 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reading_reply = 0; 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reply_len = 0; 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maciisi_state = idle; 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(ADB_DELAY); 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* process this now, because the IFR has been cleared */ 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto switch_start; 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(ADB_DELAY); 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data_index >= req->nbytes) { 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Sent the whole packet, put the bus back in idle state */ 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Shift in, we are about to read a reply (hopefully) */ 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[ACR] &= ~SR_OUT; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = via[SR]; 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* End of frame */ 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[B] &= ~TIP; 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req->sent = 1; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maciisi_state = idle; 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (req->reply_expected) { 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Note: only set this once we've 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds successfully sent the packet */ 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reading_reply = 1; 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_req = req->next; 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (req->done) 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (*req->done)(req); 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Do any queued requests now */ 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = maciisi_start(); 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(i == 0 && need_sync) { 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Packet needs to be synced */ 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maciisi_sync(current_req); 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(i != -EBUSY) 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds need_sync = 0; 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Sending more stuff */ 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Shift out */ 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[ACR] |= SR_OUT; 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Write */ 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[SR] = req->data[data_index++]; 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Signal 'byte ready' */ 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[B] |= TACK; 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case reading: 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Shift in */ 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* via[ACR] &= ~SR_OUT; */ /* Not in 2.2 */ 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (reply_len++ > 16) { 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "maciisi_interrupt: reply too long, aborting read\n"); 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[B] |= TACK; 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(ADB_DELAY); 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[B] &= ~(TACK|TIP); 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maciisi_state = idle; 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = maciisi_start(); 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(i == 0 && need_sync) { 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Packet needs to be synced */ 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maciisi_sync(current_req); 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(i != -EBUSY) 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds need_sync = 0; 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Read data */ 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *reply_ptr++ = via[SR]; 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = via[B] & (TIP|TREQ); 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ACK on/off */ 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[B] |= TACK; 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(ADB_DELAY); 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[B] &= ~TACK; 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(status & TREQ)) 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; /* more stuff to deal with */ 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* end of frame */ 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[B] &= ~TIP; 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = via[SR]; /* That's what happens in 2.2 */ 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(ADB_DELAY); /* Give controller time to recover */ 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* end of packet, deal with it */ 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (reading_reply) { 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req = current_req; 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req->reply_len = reply_ptr - req->reply; 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (req->data[0] == ADB_PACKET) { 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Have to adjust the reply from ADB commands */ 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (req->reply_len <= 2 || (req->reply[1] & 2) != 0) { 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* the 0x2 bit indicates no response */ 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req->reply_len = 0; 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* leave just the command and result bytes in the reply */ 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req->reply_len -= 2; 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memmove(req->reply, req->reply + 2, req->reply_len); 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_MACIISI_ADB 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dump_reply) { 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "maciisi_interrupt: reply is "); 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < req->reply_len; ++i) 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" %.2x", req->reply[i]); 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("\n"); 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req->complete = 1; 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_req = req->next; 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (req->done) 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (*req->done)(req); 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Obviously, we got it */ 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reading_reply = 0; 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 6137d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells maciisi_input(maciisi_rbuf, reply_ptr - maciisi_rbuf); 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maciisi_state = idle; 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = via[B] & (TIP|TREQ); 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(status & TREQ)) { 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Timeout?! More likely, another packet coming in already */ 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_MACIISI_ADB 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "extra data after packet: status %x ifr %x\n", 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status, via[IFR]); 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(ADB_DELAY); 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds via[B] |= TIP; 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maciisi_state = reading; 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reading_reply = 0; 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reply_ptr = maciisi_rbuf; 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Process the packet now */ 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reading_reply = 0; 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto switch_start; 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We used to do this... but the controller might actually have data for us */ 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* maciisi_stfu(); */ 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Do any queued requests now if possible */ 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = maciisi_start(); 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(i == 0 && need_sync) { 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Packet needs to be synced */ 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maciisi_sync(current_req); 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(i != -EBUSY) 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds need_sync = 0; 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("maciisi_interrupt: unknown maciisi_state %d?\n", maciisi_state); 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq_restore(flags); 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_HANDLED; 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 6587d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsmaciisi_input(unsigned char *buf, int nb) 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_MACIISI_ADB 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (buf[0]) { 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ADB_PACKET: 6667d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells adb_input(buf+2, nb-2, buf[1] & 0x40); 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_MACIISI_ADB 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "data from IIsi ADB (%d bytes):", nb); 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < nb; ++i) 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" %.2x", buf[i]); 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("\n"); 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 678