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