cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

via-cuda.c (19795B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Device driver for the Cuda and Egret system controllers found on PowerMacs
      4 * and 68k Macs.
      5 *
      6 * The Cuda or Egret is a 6805 microcontroller interfaced to the 6522 VIA.
      7 * This MCU controls system power, Parameter RAM, Real Time Clock and the
      8 * Apple Desktop Bus (ADB) that connects to the keyboard and mouse.
      9 *
     10 * Copyright (C) 1996 Paul Mackerras.
     11 */
     12#include <linux/stdarg.h>
     13#include <linux/types.h>
     14#include <linux/errno.h>
     15#include <linux/kernel.h>
     16#include <linux/delay.h>
     17#include <linux/adb.h>
     18#include <linux/cuda.h>
     19#include <linux/spinlock.h>
     20#include <linux/interrupt.h>
     21#include <linux/of_address.h>
     22#include <linux/of_irq.h>
     23
     24#ifdef CONFIG_PPC
     25#include <asm/machdep.h>
     26#include <asm/pmac_feature.h>
     27#else
     28#include <asm/macintosh.h>
     29#include <asm/macints.h>
     30#include <asm/mac_via.h>
     31#endif
     32#include <asm/io.h>
     33#include <linux/init.h>
     34
     35static volatile unsigned char __iomem *via;
     36static DEFINE_SPINLOCK(cuda_lock);
     37
     38/* VIA registers - spaced 0x200 bytes apart */
     39#define RS		0x200		/* skip between registers */
     40#define B		0		/* B-side data */
     41#define A		RS		/* A-side data */
     42#define DIRB		(2*RS)		/* B-side direction (1=output) */
     43#define DIRA		(3*RS)		/* A-side direction (1=output) */
     44#define T1CL		(4*RS)		/* Timer 1 ctr/latch (low 8 bits) */
     45#define T1CH		(5*RS)		/* Timer 1 counter (high 8 bits) */
     46#define T1LL		(6*RS)		/* Timer 1 latch (low 8 bits) */
     47#define T1LH		(7*RS)		/* Timer 1 latch (high 8 bits) */
     48#define T2CL		(8*RS)		/* Timer 2 ctr/latch (low 8 bits) */
     49#define T2CH		(9*RS)		/* Timer 2 counter (high 8 bits) */
     50#define SR		(10*RS)		/* Shift register */
     51#define ACR		(11*RS)		/* Auxiliary control register */
     52#define PCR		(12*RS)		/* Peripheral control register */
     53#define IFR		(13*RS)		/* Interrupt flag register */
     54#define IER		(14*RS)		/* Interrupt enable register */
     55#define ANH		(15*RS)		/* A-side data, no handshake */
     56
     57/*
     58 * When the Cuda design replaced the Egret, some signal names and
     59 * logic sense changed. They all serve the same purposes, however.
     60 *
     61 *   VIA pin       |  Egret pin
     62 * ----------------+------------------------------------------
     63 *   PB3 (input)   |  Transceiver session   (active low)
     64 *   PB4 (output)  |  VIA full              (active high)
     65 *   PB5 (output)  |  System session        (active high)
     66 *
     67 *   VIA pin       |  Cuda pin
     68 * ----------------+------------------------------------------
     69 *   PB3 (input)   |  Transfer request      (active low)
     70 *   PB4 (output)  |  Byte acknowledge      (active low)
     71 *   PB5 (output)  |  Transfer in progress  (active low)
     72 */
     73
     74/* Bits in Port B data register */
     75#define TREQ		0x08		/* Transfer request */
     76#define TACK		0x10		/* Transfer acknowledge */
     77#define TIP		0x20		/* Transfer in progress */
     78
     79/* Bits in ACR */
     80#define SR_CTRL		0x1c		/* Shift register control bits */
     81#define SR_EXT		0x0c		/* Shift on external clock */
     82#define SR_OUT		0x10		/* Shift out if 1 */
     83
     84/* Bits in IFR and IER */
     85#define IER_SET		0x80		/* set bits in IER */
     86#define IER_CLR		0		/* clear bits in IER */
     87#define SR_INT		0x04		/* Shift register full/empty */
     88
     89/* Duration of byte acknowledgement pulse (us) */
     90#define EGRET_TACK_ASSERTED_DELAY	300
     91#define EGRET_TACK_NEGATED_DELAY	400
     92
     93/* Interval from interrupt to start of session (us) */
     94#define EGRET_SESSION_DELAY		450
     95
     96#ifdef CONFIG_PPC
     97#define mcu_is_egret	false
     98#else
     99static bool mcu_is_egret;
    100#endif
    101
    102static inline bool TREQ_asserted(u8 portb)
    103{
    104	return !(portb & TREQ);
    105}
    106
    107static inline void assert_TIP(void)
    108{
    109	if (mcu_is_egret) {
    110		udelay(EGRET_SESSION_DELAY);
    111		out_8(&via[B], in_8(&via[B]) | TIP);
    112	} else
    113		out_8(&via[B], in_8(&via[B]) & ~TIP);
    114}
    115
    116static inline void assert_TIP_and_TACK(void)
    117{
    118	if (mcu_is_egret) {
    119		udelay(EGRET_SESSION_DELAY);
    120		out_8(&via[B], in_8(&via[B]) | TIP | TACK);
    121	} else
    122		out_8(&via[B], in_8(&via[B]) & ~(TIP | TACK));
    123}
    124
    125static inline void assert_TACK(void)
    126{
    127	if (mcu_is_egret) {
    128		udelay(EGRET_TACK_NEGATED_DELAY);
    129		out_8(&via[B], in_8(&via[B]) | TACK);
    130	} else
    131		out_8(&via[B], in_8(&via[B]) & ~TACK);
    132}
    133
    134static inline void toggle_TACK(void)
    135{
    136	out_8(&via[B], in_8(&via[B]) ^ TACK);
    137}
    138
    139static inline void negate_TACK(void)
    140{
    141	if (mcu_is_egret) {
    142		udelay(EGRET_TACK_ASSERTED_DELAY);
    143		out_8(&via[B], in_8(&via[B]) & ~TACK);
    144	} else
    145		out_8(&via[B], in_8(&via[B]) | TACK);
    146}
    147
    148static inline void negate_TIP_and_TACK(void)
    149{
    150	if (mcu_is_egret) {
    151		udelay(EGRET_TACK_ASSERTED_DELAY);
    152		out_8(&via[B], in_8(&via[B]) & ~(TIP | TACK));
    153	} else
    154		out_8(&via[B], in_8(&via[B]) | TIP | TACK);
    155}
    156
    157static enum cuda_state {
    158    idle,
    159    sent_first_byte,
    160    sending,
    161    reading,
    162    read_done,
    163    awaiting_reply
    164} cuda_state;
    165
    166static struct adb_request *current_req;
    167static struct adb_request *last_req;
    168static unsigned char cuda_rbuf[16];
    169static unsigned char *reply_ptr;
    170static int reading_reply;
    171static int data_index;
    172static int cuda_irq;
    173#ifdef CONFIG_PPC
    174static struct device_node *vias;
    175#endif
    176static int cuda_fully_inited;
    177
    178#ifdef CONFIG_ADB
    179static int cuda_probe(void);
    180static int cuda_send_request(struct adb_request *req, int sync);
    181static int cuda_adb_autopoll(int devs);
    182static int cuda_reset_adb_bus(void);
    183#endif /* CONFIG_ADB */
    184
    185static int cuda_init_via(void);
    186static void cuda_start(void);
    187static irqreturn_t cuda_interrupt(int irq, void *arg);
    188static void cuda_input(unsigned char *buf, int nb);
    189void cuda_poll(void);
    190static int cuda_write(struct adb_request *req);
    191
    192int cuda_request(struct adb_request *req,
    193		 void (*done)(struct adb_request *), int nbytes, ...);
    194
    195#ifdef CONFIG_ADB
    196struct adb_driver via_cuda_driver = {
    197	.name         = "CUDA",
    198	.probe        = cuda_probe,
    199	.send_request = cuda_send_request,
    200	.autopoll     = cuda_adb_autopoll,
    201	.poll         = cuda_poll,
    202	.reset_bus    = cuda_reset_adb_bus,
    203};
    204#endif /* CONFIG_ADB */
    205
    206#ifdef CONFIG_MAC
    207int __init find_via_cuda(void)
    208{
    209    struct adb_request req;
    210    int err;
    211
    212    if (macintosh_config->adb_type != MAC_ADB_CUDA &&
    213        macintosh_config->adb_type != MAC_ADB_EGRET)
    214	return 0;
    215
    216    via = via1;
    217    cuda_state = idle;
    218    mcu_is_egret = macintosh_config->adb_type == MAC_ADB_EGRET;
    219
    220    err = cuda_init_via();
    221    if (err) {
    222	printk(KERN_ERR "cuda_init_via() failed\n");
    223	via = NULL;
    224	return 0;
    225    }
    226
    227    /* enable autopoll */
    228    cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1);
    229    while (!req.complete)
    230	cuda_poll();
    231
    232    return 1;
    233}
    234#else
    235int __init find_via_cuda(void)
    236{
    237    struct adb_request req;
    238    phys_addr_t taddr;
    239    const u32 *reg;
    240    int err;
    241
    242    if (vias)
    243	return 1;
    244    vias = of_find_node_by_name(NULL, "via-cuda");
    245    if (!vias)
    246	return 0;
    247
    248    reg = of_get_property(vias, "reg", NULL);
    249    if (reg == NULL) {
    250	    printk(KERN_ERR "via-cuda: No \"reg\" property !\n");
    251	    goto fail;
    252    }
    253    taddr = of_translate_address(vias, reg);
    254    if (taddr == 0) {
    255	    printk(KERN_ERR "via-cuda: Can't translate address !\n");
    256	    goto fail;
    257    }
    258    via = ioremap(taddr, 0x2000);
    259    if (via == NULL) {
    260	    printk(KERN_ERR "via-cuda: Can't map address !\n");
    261	    goto fail;
    262    }
    263
    264    cuda_state = idle;
    265    sys_ctrler = SYS_CTRLER_CUDA;
    266
    267    err = cuda_init_via();
    268    if (err) {
    269	printk(KERN_ERR "cuda_init_via() failed\n");
    270	via = NULL;
    271	return 0;
    272    }
    273
    274    /* Clear and enable interrupts, but only on PPC. On 68K it's done  */
    275    /* for us by the main VIA driver in arch/m68k/mac/via.c        */
    276
    277    out_8(&via[IFR], 0x7f);	/* clear interrupts by writing 1s */
    278    out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */
    279
    280    /* enable autopoll */
    281    cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1);
    282    while (!req.complete)
    283	cuda_poll();
    284
    285    return 1;
    286
    287 fail:
    288    of_node_put(vias);
    289    vias = NULL;
    290    return 0;
    291}
    292#endif /* !defined CONFIG_MAC */
    293
    294static int __init via_cuda_start(void)
    295{
    296    if (via == NULL)
    297	return -ENODEV;
    298
    299#ifdef CONFIG_MAC
    300    cuda_irq = IRQ_MAC_ADB;
    301#else
    302    cuda_irq = irq_of_parse_and_map(vias, 0);
    303    if (!cuda_irq) {
    304	printk(KERN_ERR "via-cuda: can't map interrupts for %pOF\n",
    305	       vias);
    306	return -ENODEV;
    307    }
    308#endif
    309
    310    if (request_irq(cuda_irq, cuda_interrupt, 0, "ADB", cuda_interrupt)) {
    311	printk(KERN_ERR "via-cuda: can't request irq %d\n", cuda_irq);
    312	return -EAGAIN;
    313    }
    314
    315    pr_info("Macintosh Cuda and Egret driver.\n");
    316
    317    cuda_fully_inited = 1;
    318    return 0;
    319}
    320
    321device_initcall(via_cuda_start);
    322
    323#ifdef CONFIG_ADB
    324static int
    325cuda_probe(void)
    326{
    327#ifdef CONFIG_PPC
    328    if (sys_ctrler != SYS_CTRLER_CUDA)
    329	return -ENODEV;
    330#else
    331    if (macintosh_config->adb_type != MAC_ADB_CUDA &&
    332        macintosh_config->adb_type != MAC_ADB_EGRET)
    333	return -ENODEV;
    334#endif
    335    if (via == NULL)
    336	return -ENODEV;
    337    return 0;
    338}
    339#endif /* CONFIG_ADB */
    340
    341static int __init sync_egret(void)
    342{
    343	if (TREQ_asserted(in_8(&via[B]))) {
    344		/* Complete the inbound transfer */
    345		assert_TIP_and_TACK();
    346		while (1) {
    347			negate_TACK();
    348			mdelay(1);
    349			(void)in_8(&via[SR]);
    350			assert_TACK();
    351			if (!TREQ_asserted(in_8(&via[B])))
    352				break;
    353		}
    354		negate_TIP_and_TACK();
    355	} else if (in_8(&via[B]) & TIP) {
    356		/* Terminate the outbound transfer */
    357		negate_TACK();
    358		assert_TACK();
    359		mdelay(1);
    360		negate_TIP_and_TACK();
    361	}
    362	/* Clear shift register interrupt */
    363	if (in_8(&via[IFR]) & SR_INT)
    364		(void)in_8(&via[SR]);
    365	return 0;
    366}
    367
    368#define WAIT_FOR(cond, what)					\
    369    do {                                                        \
    370    	int x;							\
    371	for (x = 1000; !(cond); --x) {				\
    372	    if (x == 0) {					\
    373		pr_err("Timeout waiting for " what "\n");	\
    374		return -ENXIO;					\
    375	    }							\
    376	    udelay(100);					\
    377	}							\
    378    } while (0)
    379
    380static int
    381__init cuda_init_via(void)
    382{
    383#ifdef CONFIG_PPC
    384    out_8(&via[IER], 0x7f);					/* disable interrupts from VIA */
    385    (void)in_8(&via[IER]);
    386#else
    387    out_8(&via[IER], SR_INT);					/* disable SR interrupt from VIA */
    388#endif
    389
    390    out_8(&via[DIRB], (in_8(&via[DIRB]) | TACK | TIP) & ~TREQ);	/* TACK & TIP out */
    391    out_8(&via[ACR], (in_8(&via[ACR]) & ~SR_CTRL) | SR_EXT);	/* SR data in */
    392    (void)in_8(&via[SR]);					/* clear any left-over data */
    393
    394    if (mcu_is_egret)
    395	return sync_egret();
    396
    397    negate_TIP_and_TACK();
    398
    399    /* delay 4ms and then clear any pending interrupt */
    400    mdelay(4);
    401    (void)in_8(&via[SR]);
    402    out_8(&via[IFR], SR_INT);
    403
    404    /* sync with the CUDA - assert TACK without TIP */
    405    assert_TACK();
    406
    407    /* wait for the CUDA to assert TREQ in response */
    408    WAIT_FOR(TREQ_asserted(in_8(&via[B])), "CUDA response to sync");
    409
    410    /* wait for the interrupt and then clear it */
    411    WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (2)");
    412    (void)in_8(&via[SR]);
    413    out_8(&via[IFR], SR_INT);
    414
    415    /* finish the sync by negating TACK */
    416    negate_TACK();
    417
    418    /* wait for the CUDA to negate TREQ and the corresponding interrupt */
    419    WAIT_FOR(!TREQ_asserted(in_8(&via[B])), "CUDA response to sync (3)");
    420    WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (4)");
    421    (void)in_8(&via[SR]);
    422    out_8(&via[IFR], SR_INT);
    423
    424    return 0;
    425}
    426
    427#ifdef CONFIG_ADB
    428/* Send an ADB command */
    429static int
    430cuda_send_request(struct adb_request *req, int sync)
    431{
    432    int i;
    433
    434    if ((via == NULL) || !cuda_fully_inited) {
    435	req->complete = 1;
    436	return -ENXIO;
    437    }
    438  
    439    req->reply_expected = 1;
    440
    441    i = cuda_write(req);
    442    if (i)
    443	return i;
    444
    445    if (sync) {
    446	while (!req->complete)
    447	    cuda_poll();
    448    }
    449    return 0;
    450}
    451
    452
    453/* Enable/disable autopolling */
    454static int
    455cuda_adb_autopoll(int devs)
    456{
    457    struct adb_request req;
    458
    459    if ((via == NULL) || !cuda_fully_inited)
    460	return -ENXIO;
    461
    462    cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, (devs? 1: 0));
    463    while (!req.complete)
    464	cuda_poll();
    465    return 0;
    466}
    467
    468/* Reset adb bus - how do we do this?? */
    469static int
    470cuda_reset_adb_bus(void)
    471{
    472    struct adb_request req;
    473
    474    if ((via == NULL) || !cuda_fully_inited)
    475	return -ENXIO;
    476
    477    cuda_request(&req, NULL, 2, ADB_PACKET, 0);		/* maybe? */
    478    while (!req.complete)
    479	cuda_poll();
    480    return 0;
    481}
    482#endif /* CONFIG_ADB */
    483
    484/* Construct and send a cuda request */
    485int
    486cuda_request(struct adb_request *req, void (*done)(struct adb_request *),
    487	     int nbytes, ...)
    488{
    489    va_list list;
    490    int i;
    491
    492    if (via == NULL) {
    493	req->complete = 1;
    494	return -ENXIO;
    495    }
    496
    497    req->nbytes = nbytes;
    498    req->done = done;
    499    va_start(list, nbytes);
    500    for (i = 0; i < nbytes; ++i)
    501	req->data[i] = va_arg(list, int);
    502    va_end(list);
    503    req->reply_expected = 1;
    504    return cuda_write(req);
    505}
    506EXPORT_SYMBOL(cuda_request);
    507
    508static int
    509cuda_write(struct adb_request *req)
    510{
    511    unsigned long flags;
    512
    513    if (req->nbytes < 2 || req->data[0] > CUDA_PACKET) {
    514	req->complete = 1;
    515	return -EINVAL;
    516    }
    517    req->next = NULL;
    518    req->sent = 0;
    519    req->complete = 0;
    520    req->reply_len = 0;
    521
    522    spin_lock_irqsave(&cuda_lock, flags);
    523    if (current_req) {
    524	last_req->next = req;
    525	last_req = req;
    526    } else {
    527	current_req = req;
    528	last_req = req;
    529	if (cuda_state == idle)
    530	    cuda_start();
    531    }
    532    spin_unlock_irqrestore(&cuda_lock, flags);
    533
    534    return 0;
    535}
    536
    537static void
    538cuda_start(void)
    539{
    540    /* assert cuda_state == idle */
    541    if (current_req == NULL)
    542	return;
    543    data_index = 0;
    544    if (TREQ_asserted(in_8(&via[B])))
    545	return;			/* a byte is coming in from the CUDA */
    546
    547    /* set the shift register to shift out and send a byte */
    548    out_8(&via[ACR], in_8(&via[ACR]) | SR_OUT);
    549    out_8(&via[SR], current_req->data[data_index++]);
    550    if (mcu_is_egret)
    551	assert_TIP_and_TACK();
    552    else
    553	assert_TIP();
    554    cuda_state = sent_first_byte;
    555}
    556
    557void
    558cuda_poll(void)
    559{
    560	cuda_interrupt(0, NULL);
    561}
    562EXPORT_SYMBOL(cuda_poll);
    563
    564#define ARRAY_FULL(a, p)	((p) - (a) == ARRAY_SIZE(a))
    565
    566static irqreturn_t
    567cuda_interrupt(int irq, void *arg)
    568{
    569    unsigned long flags;
    570    u8 status;
    571    struct adb_request *req = NULL;
    572    unsigned char ibuf[16];
    573    int ibuf_len = 0;
    574    int complete = 0;
    575    bool full;
    576    
    577    spin_lock_irqsave(&cuda_lock, flags);
    578
    579    /* On powermacs, this handler is registered for the VIA IRQ. But they use
    580     * just the shift register IRQ -- other VIA interrupt sources are disabled.
    581     * On m68k macs, the VIA IRQ sources are dispatched individually. Unless
    582     * we are polling, the shift register IRQ flag has already been cleared.
    583     */
    584
    585#ifdef CONFIG_MAC
    586    if (!arg)
    587#endif
    588    {
    589        if ((in_8(&via[IFR]) & SR_INT) == 0) {
    590            spin_unlock_irqrestore(&cuda_lock, flags);
    591            return IRQ_NONE;
    592        } else {
    593            out_8(&via[IFR], SR_INT);
    594        }
    595    }
    596
    597    status = in_8(&via[B]) & (TIP | TACK | TREQ);
    598
    599    switch (cuda_state) {
    600    case idle:
    601	/* System controller has unsolicited data for us */
    602	(void)in_8(&via[SR]);
    603idle_state:
    604	assert_TIP();
    605	cuda_state = reading;
    606	reply_ptr = cuda_rbuf;
    607	reading_reply = 0;
    608	break;
    609
    610    case awaiting_reply:
    611	/* System controller has reply data for us */
    612	(void)in_8(&via[SR]);
    613	assert_TIP();
    614	cuda_state = reading;
    615	reply_ptr = current_req->reply;
    616	reading_reply = 1;
    617	break;
    618
    619    case sent_first_byte:
    620	if (TREQ_asserted(status)) {
    621	    /* collision */
    622	    out_8(&via[ACR], in_8(&via[ACR]) & ~SR_OUT);
    623	    (void)in_8(&via[SR]);
    624	    negate_TIP_and_TACK();
    625	    cuda_state = idle;
    626	    /* Egret does not raise an "aborted" interrupt */
    627	    if (mcu_is_egret)
    628		goto idle_state;
    629	} else {
    630	    out_8(&via[SR], current_req->data[data_index++]);
    631	    toggle_TACK();
    632	    if (mcu_is_egret)
    633		assert_TACK();
    634	    cuda_state = sending;
    635	}
    636	break;
    637
    638    case sending:
    639	req = current_req;
    640	if (data_index >= req->nbytes) {
    641	    out_8(&via[ACR], in_8(&via[ACR]) & ~SR_OUT);
    642	    (void)in_8(&via[SR]);
    643	    negate_TIP_and_TACK();
    644	    req->sent = 1;
    645	    if (req->reply_expected) {
    646		cuda_state = awaiting_reply;
    647	    } else {
    648		current_req = req->next;
    649		complete = 1;
    650		/* not sure about this */
    651		cuda_state = idle;
    652		cuda_start();
    653	    }
    654	} else {
    655	    out_8(&via[SR], req->data[data_index++]);
    656	    toggle_TACK();
    657	    if (mcu_is_egret)
    658		assert_TACK();
    659	}
    660	break;
    661
    662    case reading:
    663	full = reading_reply ? ARRAY_FULL(current_req->reply, reply_ptr)
    664	                     : ARRAY_FULL(cuda_rbuf, reply_ptr);
    665	if (full)
    666	    (void)in_8(&via[SR]);
    667	else
    668	    *reply_ptr++ = in_8(&via[SR]);
    669	if (!TREQ_asserted(status) || full) {
    670	    if (mcu_is_egret)
    671		assert_TACK();
    672	    /* that's all folks */
    673	    negate_TIP_and_TACK();
    674	    cuda_state = read_done;
    675	    /* Egret does not raise a "read done" interrupt */
    676	    if (mcu_is_egret)
    677		goto read_done_state;
    678	} else {
    679	    toggle_TACK();
    680	    if (mcu_is_egret)
    681		negate_TACK();
    682	}
    683	break;
    684
    685    case read_done:
    686	(void)in_8(&via[SR]);
    687read_done_state:
    688	if (reading_reply) {
    689	    req = current_req;
    690	    req->reply_len = reply_ptr - req->reply;
    691	    if (req->data[0] == ADB_PACKET) {
    692		/* Have to adjust the reply from ADB commands */
    693		if (req->reply_len <= 2 || (req->reply[1] & 2) != 0) {
    694		    /* the 0x2 bit indicates no response */
    695		    req->reply_len = 0;
    696		} else {
    697		    /* leave just the command and result bytes in the reply */
    698		    req->reply_len -= 2;
    699		    memmove(req->reply, req->reply + 2, req->reply_len);
    700		}
    701	    }
    702	    current_req = req->next;
    703	    complete = 1;
    704	    reading_reply = 0;
    705	} else {
    706	    /* This is tricky. We must break the spinlock to call
    707	     * cuda_input. However, doing so means we might get
    708	     * re-entered from another CPU getting an interrupt
    709	     * or calling cuda_poll(). I ended up using the stack
    710	     * (it's only for 16 bytes) and moving the actual
    711	     * call to cuda_input to outside of the lock.
    712	     */
    713	    ibuf_len = reply_ptr - cuda_rbuf;
    714	    memcpy(ibuf, cuda_rbuf, ibuf_len);
    715	}
    716	reply_ptr = cuda_rbuf;
    717	cuda_state = idle;
    718	cuda_start();
    719	if (cuda_state == idle && TREQ_asserted(in_8(&via[B]))) {
    720	    assert_TIP();
    721	    cuda_state = reading;
    722	}
    723	break;
    724
    725    default:
    726	pr_err("cuda_interrupt: unknown cuda_state %d?\n", cuda_state);
    727    }
    728    spin_unlock_irqrestore(&cuda_lock, flags);
    729    if (complete && req) {
    730    	void (*done)(struct adb_request *) = req->done;
    731    	mb();
    732    	req->complete = 1;
    733    	/* Here, we assume that if the request has a done member, the
    734    	 * struct request will survive to setting req->complete to 1
    735    	 */
    736    	if (done)
    737		(*done)(req);
    738    }
    739    if (ibuf_len)
    740	cuda_input(ibuf, ibuf_len);
    741    return IRQ_HANDLED;
    742}
    743
    744static void
    745cuda_input(unsigned char *buf, int nb)
    746{
    747    switch (buf[0]) {
    748    case ADB_PACKET:
    749#ifdef CONFIG_XMON
    750	if (nb == 5 && buf[2] == 0x2c) {
    751	    extern int xmon_wants_key, xmon_adb_keycode;
    752	    if (xmon_wants_key) {
    753		xmon_adb_keycode = buf[3];
    754		return;
    755	    }
    756	}
    757#endif /* CONFIG_XMON */
    758#ifdef CONFIG_ADB
    759	adb_input(buf+2, nb-2, buf[1] & 0x40);
    760#endif /* CONFIG_ADB */
    761	break;
    762
    763    case TIMER_PACKET:
    764	/* Egret sends these periodically. Might be useful as a 'heartbeat'
    765	 * to trigger a recovery for the VIA shift register errata.
    766	 */
    767	break;
    768
    769    default:
    770	print_hex_dump(KERN_INFO, "cuda_input: ", DUMP_PREFIX_NONE, 32, 1,
    771	               buf, nb, false);
    772    }
    773}
    774
    775/* Offset between Unix time (1970-based) and Mac time (1904-based) */
    776#define RTC_OFFSET	2082844800
    777
    778time64_t cuda_get_time(void)
    779{
    780	struct adb_request req;
    781	u32 now;
    782
    783	if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0)
    784		return 0;
    785	while (!req.complete)
    786		cuda_poll();
    787	if (req.reply_len != 7)
    788		pr_err("%s: got %d byte reply\n", __func__, req.reply_len);
    789	now = (req.reply[3] << 24) + (req.reply[4] << 16) +
    790	      (req.reply[5] << 8) + req.reply[6];
    791	return (time64_t)now - RTC_OFFSET;
    792}
    793
    794int cuda_set_rtc_time(struct rtc_time *tm)
    795{
    796	u32 now;
    797	struct adb_request req;
    798
    799	now = lower_32_bits(rtc_tm_to_time64(tm) + RTC_OFFSET);
    800	if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME,
    801	                 now >> 24, now >> 16, now >> 8, now) < 0)
    802		return -ENXIO;
    803	while (!req.complete)
    804		cuda_poll();
    805	if ((req.reply_len != 3) && (req.reply_len != 7))
    806		pr_err("%s: got %d byte reply\n", __func__, req.reply_len);
    807	return 0;
    808}