linux/drivers/macintosh/via-maciisi.c
<<
>>
Prefs
   1/*
   2 * Device driver for the IIsi-style ADB on some Mac LC and II-class machines
   3 *
   4 * Based on via-cuda.c and via-macii.c, as well as the original
   5 * adb-bus.c, which in turn is somewhat influenced by (but uses no
   6 * code from) the NetBSD HWDIRECT ADB code.  Original IIsi driver work
   7 * was done by Robert Thompson and integrated into the old style
   8 * driver by Michael Schmitz.
   9 *
  10 * Original sources (c) Alan Cox, Paul Mackerras, and others.
  11 *
  12 * Rewritten for Unified ADB by David Huggins-Daines <dhd@debian.org>
  13 * 
  14 * 7/13/2000- extensive changes by Andrew McPherson <andrew@macduff.dhs.org>
  15 * Works about 30% of the time now.
  16 */
  17
  18#include <linux/types.h>
  19#include <linux/errno.h>
  20#include <linux/kernel.h>
  21#include <linux/adb.h>
  22#include <linux/cuda.h>
  23#include <linux/delay.h>
  24#include <linux/interrupt.h>
  25#include <asm/macintosh.h>
  26#include <asm/macints.h>
  27#include <asm/mac_via.h>
  28
  29static volatile unsigned char *via;
  30
  31/* VIA registers - spaced 0x200 bytes apart - only the ones we actually use */
  32#define RS              0x200           /* skip between registers */
  33#define B               0               /* B-side data */
  34#define A               RS              /* A-side data */
  35#define DIRB            (2*RS)          /* B-side direction (1=output) */
  36#define DIRA            (3*RS)          /* A-side direction (1=output) */
  37#define SR              (10*RS)         /* Shift register */
  38#define ACR             (11*RS)         /* Auxiliary control register */
  39#define IFR             (13*RS)         /* Interrupt flag register */
  40#define IER             (14*RS)         /* Interrupt enable register */
  41
  42/* Bits in B data register: all active low */
  43#define TREQ            0x08            /* Transfer request (input) */
  44#define TACK            0x10            /* Transfer acknowledge (output) */
  45#define TIP             0x20            /* Transfer in progress (output) */
  46#define ST_MASK         0x30            /* mask for selecting ADB state bits */
  47
  48/* Bits in ACR */
  49#define SR_CTRL         0x1c            /* Shift register control bits */
  50#define SR_EXT          0x0c            /* Shift on external clock */
  51#define SR_OUT          0x10            /* Shift out if 1 */
  52
  53/* Bits in IFR and IER */
  54#define IER_SET         0x80            /* set bits in IER */
  55#define IER_CLR         0               /* clear bits in IER */
  56#define SR_INT          0x04            /* Shift register full/empty */
  57#define SR_DATA         0x08            /* Shift register data */
  58#define SR_CLOCK        0x10            /* Shift register clock */
  59
  60#define ADB_DELAY 150
  61
  62#undef DEBUG_MACIISI_ADB
  63
  64static struct adb_request* current_req;
  65static struct adb_request* last_req;
  66static unsigned char maciisi_rbuf[16];
  67static unsigned char *reply_ptr;
  68static int data_index;
  69static int reading_reply;
  70static int reply_len;
  71static int tmp;
  72static int need_sync;
  73
  74static enum maciisi_state {
  75    idle,
  76    sending,
  77    reading,
  78} maciisi_state;
  79
  80static int maciisi_probe(void);
  81static int maciisi_init(void);
  82static int maciisi_send_request(struct adb_request* req, int sync);
  83static void maciisi_sync(struct adb_request *req);
  84static int maciisi_write(struct adb_request* req);
  85static irqreturn_t maciisi_interrupt(int irq, void* arg);
  86static void maciisi_input(unsigned char *buf, int nb);
  87static int maciisi_init_via(void);
  88static void maciisi_poll(void);
  89static int maciisi_start(void);
  90
  91struct adb_driver via_maciisi_driver = {
  92        "Mac IIsi",
  93        maciisi_probe,
  94        maciisi_init,
  95        maciisi_send_request,
  96        NULL, /* maciisi_adb_autopoll, */
  97        maciisi_poll,
  98        NULL /* maciisi_reset_adb_bus */
  99};
 100
 101static int
 102maciisi_probe(void)
 103{
 104        if (macintosh_config->adb_type != MAC_ADB_IISI)
 105                return -ENODEV;
 106
 107        via = via1;
 108        return 0;
 109}
 110
 111static int
 112maciisi_init(void)
 113{
 114        int err;
 115
 116        if (via == NULL)
 117                return -ENODEV;
 118
 119        if ((err = maciisi_init_via())) {
 120                printk(KERN_ERR "maciisi_init: maciisi_init_via() failed, code %d\n", err);
 121                via = NULL;
 122                return err;
 123        }
 124
 125        if (request_irq(IRQ_MAC_ADB, maciisi_interrupt, 0, "ADB",
 126                        maciisi_interrupt)) {
 127                printk(KERN_ERR "maciisi_init: can't get irq %d\n", IRQ_MAC_ADB);
 128                return -EAGAIN;
 129        }
 130
 131        printk("adb: Mac IIsi driver v0.2 for Unified ADB.\n");
 132        return 0;
 133}
 134
 135/* Flush data from the ADB controller */
 136static void
 137maciisi_stfu(void)
 138{
 139        int status = via[B] & (TIP|TREQ);
 140
 141        if (status & TREQ) {
 142#ifdef DEBUG_MACIISI_ADB
 143                printk (KERN_DEBUG "maciisi_stfu called with TREQ high!\n");
 144#endif
 145                return;
 146        }
 147        
 148        udelay(ADB_DELAY);
 149        via[ACR] &= ~SR_OUT;
 150        via[IER] = IER_CLR | SR_INT;
 151
 152        udelay(ADB_DELAY);
 153
 154        status = via[B] & (TIP|TREQ);
 155
 156        if (!(status & TREQ))
 157        {
 158                via[B] |= TIP;
 159
 160                while(1)
 161                {
 162                        int poll_timeout = ADB_DELAY * 5;
 163                        /* Poll for SR interrupt */
 164                        while (!(via[IFR] & SR_INT) && poll_timeout-- > 0)
 165                                status = via[B] & (TIP|TREQ);
 166
 167                        tmp = via[SR]; /* Clear shift register */
 168#ifdef DEBUG_MACIISI_ADB
 169                        printk(KERN_DEBUG "maciisi_stfu: status %x timeout %d data %x\n",
 170                               status, poll_timeout, tmp);
 171#endif  
 172                        if(via[B] & TREQ)
 173                                break;
 174        
 175                        /* ACK on-off */
 176                        via[B] |= TACK;
 177                        udelay(ADB_DELAY);
 178                        via[B] &= ~TACK;
 179                }
 180
 181                /* end frame */
 182                via[B] &= ~TIP;
 183                udelay(ADB_DELAY);
 184        }
 185
 186        via[IER] = IER_SET | SR_INT;    
 187}
 188
 189/* All specifically VIA-related initialization goes here */
 190static int
 191maciisi_init_via(void)
 192{
 193        int     i;
 194        
 195        /* Set the lines up. We want TREQ as input TACK|TIP as output */
 196        via[DIRB] = (via[DIRB] | TACK | TIP) & ~TREQ;
 197        /* Shift register on input */
 198        via[ACR]  = (via[ACR] & ~SR_CTRL) | SR_EXT;
 199#ifdef DEBUG_MACIISI_ADB
 200        printk(KERN_DEBUG "maciisi_init_via: initial status %x\n", via[B] & (TIP|TREQ));
 201#endif
 202        /* Wipe any pending data and int */
 203        tmp = via[SR];
 204        /* Enable keyboard interrupts */
 205        via[IER] = IER_SET | SR_INT;
 206        /* Set initial state: idle */
 207        via[B] &= ~(TACK|TIP);
 208        /* Clear interrupt bit */
 209        via[IFR] = SR_INT;
 210
 211        for(i = 0; i < 60; i++) {
 212                udelay(ADB_DELAY);
 213                maciisi_stfu();
 214                udelay(ADB_DELAY);
 215                if(via[B] & TREQ)
 216                        break;
 217        }
 218        if (i == 60)
 219                printk(KERN_ERR "maciisi_init_via: bus jam?\n");
 220
 221        maciisi_state = idle;
 222        need_sync = 0;
 223
 224        return 0;
 225}
 226
 227/* Send a request, possibly waiting for a reply */
 228static int
 229maciisi_send_request(struct adb_request* req, int sync)
 230{
 231        int i;
 232
 233#ifdef DEBUG_MACIISI_ADB
 234        static int dump_packet = 0;
 235#endif
 236
 237        if (via == NULL) {
 238                req->complete = 1;
 239                return -ENXIO;
 240        }
 241
 242#ifdef DEBUG_MACIISI_ADB
 243        if (dump_packet) {
 244                printk(KERN_DEBUG "maciisi_send_request:");
 245                for (i = 0; i < req->nbytes; i++) {
 246                        printk(" %.2x", req->data[i]);
 247                }
 248                printk(" sync %d\n", sync);
 249        }
 250#endif
 251
 252        req->reply_expected = 1;
 253        
 254        i = maciisi_write(req);
 255        if (i)
 256        {
 257                /* Normally, if a packet requires syncing, that happens at the end of
 258                 * maciisi_send_request. But if the transfer fails, it will be restarted
 259                 * by maciisi_interrupt(). We use need_sync to tell maciisi_interrupt
 260                 * when to sync a packet that it sends out.
 261                 * 
 262                 * Suggestions on a better way to do this are welcome.
 263                 */
 264                if(i == -EBUSY && sync)
 265                        need_sync = 1;
 266                else
 267                        need_sync = 0;
 268                return i;
 269        }
 270        if(sync)
 271                maciisi_sync(req);
 272        
 273        return 0;
 274}
 275
 276/* Poll the ADB chip until the request completes */
 277static void maciisi_sync(struct adb_request *req)
 278{
 279        int count = 0; 
 280
 281#ifdef DEBUG_MACIISI_ADB
 282        printk(KERN_DEBUG "maciisi_sync called\n");
 283#endif
 284
 285        /* If for some reason the ADB chip shuts up on us, we want to avoid an endless loop. */
 286        while (!req->complete && count++ < 50) {
 287                maciisi_poll();
 288        }
 289        /* This could be BAD... when the ADB controller doesn't respond
 290         * for this long, it's probably not coming back :-( */
 291        if (count > 50) /* Hopefully shouldn't happen */
 292                printk(KERN_ERR "maciisi_send_request: poll timed out!\n");
 293}
 294
 295int
 296maciisi_request(struct adb_request *req, void (*done)(struct adb_request *),
 297            int nbytes, ...)
 298{
 299        va_list list;
 300        int i;
 301
 302        req->nbytes = nbytes;
 303        req->done = done;
 304        req->reply_expected = 0;
 305        va_start(list, nbytes);
 306        for (i = 0; i < nbytes; i++)
 307                req->data[i++] = va_arg(list, int);
 308        va_end(list);
 309
 310        return maciisi_send_request(req, 1);
 311}
 312
 313/* Enqueue a request, and run the queue if possible */
 314static int
 315maciisi_write(struct adb_request* req)
 316{
 317        unsigned long flags;
 318        int i;
 319
 320        /* We will accept CUDA packets - the VIA sends them to us, so
 321           it figures that we should be able to send them to it */
 322        if (req->nbytes < 2 || req->data[0] > CUDA_PACKET) {
 323                printk(KERN_ERR "maciisi_write: packet too small or not an ADB or CUDA packet\n");
 324                req->complete = 1;
 325                return -EINVAL;
 326        }
 327        req->next = NULL;
 328        req->sent = 0;
 329        req->complete = 0;
 330        req->reply_len = 0;
 331        
 332        local_irq_save(flags);
 333
 334        if (current_req) {
 335                last_req->next = req;
 336                last_req = req;
 337        } else {
 338                current_req = req;
 339                last_req = req;
 340        }
 341        if (maciisi_state == idle)
 342        {
 343                i = maciisi_start();
 344                if(i != 0)
 345                {
 346                        local_irq_restore(flags);
 347                        return i;
 348                }
 349        }
 350        else
 351        {
 352#ifdef DEBUG_MACIISI_ADB
 353                printk(KERN_DEBUG "maciisi_write: would start, but state is %d\n", maciisi_state);
 354#endif
 355                local_irq_restore(flags);
 356                return -EBUSY;
 357        }
 358
 359        local_irq_restore(flags);
 360
 361        return 0;
 362}
 363
 364static int
 365maciisi_start(void)
 366{
 367        struct adb_request* req;
 368        int status;
 369
 370#ifdef DEBUG_MACIISI_ADB
 371        status = via[B] & (TIP | TREQ);
 372
 373        printk(KERN_DEBUG "maciisi_start called, state=%d, status=%x, ifr=%x\n", maciisi_state, status, via[IFR]);
 374#endif
 375
 376        if (maciisi_state != idle) {
 377                /* shouldn't happen */
 378                printk(KERN_ERR "maciisi_start: maciisi_start called when driver busy!\n");
 379                return -EBUSY;
 380        }
 381
 382        req = current_req;
 383        if (req == NULL)
 384                return -EINVAL;
 385
 386        status = via[B] & (TIP|TREQ);
 387        if (!(status & TREQ)) {
 388#ifdef DEBUG_MACIISI_ADB
 389                printk(KERN_DEBUG "maciisi_start: bus busy - aborting\n");
 390#endif
 391                return -EBUSY;
 392        }
 393
 394        /* Okay, send */
 395#ifdef DEBUG_MACIISI_ADB
 396        printk(KERN_DEBUG "maciisi_start: sending\n");
 397#endif
 398        /* Set state to active */
 399        via[B] |= TIP;
 400        /* ACK off */
 401        via[B] &= ~TACK;
 402        /* Delay */
 403        udelay(ADB_DELAY);
 404        /* Shift out and send */
 405        via[ACR] |= SR_OUT;
 406        via[SR] = req->data[0];
 407        data_index = 1;
 408        /* ACK on */
 409        via[B] |= TACK;
 410        maciisi_state = sending;
 411
 412        return 0;
 413}
 414
 415void
 416maciisi_poll(void)
 417{
 418        unsigned long flags;
 419
 420        local_irq_save(flags);
 421        if (via[IFR] & SR_INT) {
 422                maciisi_interrupt(0, NULL);
 423        }
 424        else /* avoid calling this function too quickly in a loop */
 425                udelay(ADB_DELAY);
 426
 427        local_irq_restore(flags);
 428}
 429
 430/* Shift register interrupt - this is *supposed* to mean that the
 431   register is either full or empty. In practice, I have no idea what
 432   it means :( */
 433static irqreturn_t
 434maciisi_interrupt(int irq, void* arg)
 435{
 436        int status;
 437        struct adb_request *req;
 438#ifdef DEBUG_MACIISI_ADB
 439        static int dump_reply = 0;
 440#endif
 441        int i;
 442        unsigned long flags;
 443
 444        local_irq_save(flags);
 445
 446        status = via[B] & (TIP|TREQ);
 447#ifdef DEBUG_MACIISI_ADB
 448        printk(KERN_DEBUG "state %d status %x ifr %x\n", maciisi_state, status, via[IFR]);
 449#endif
 450
 451        if (!(via[IFR] & SR_INT)) {
 452                /* Shouldn't happen, we hope */
 453                printk(KERN_ERR "maciisi_interrupt: called without interrupt flag set\n");
 454                local_irq_restore(flags);
 455                return IRQ_NONE;
 456        }
 457
 458        /* Clear the interrupt */
 459        /* via[IFR] = SR_INT; */
 460
 461 switch_start:
 462        switch (maciisi_state) {
 463        case idle:
 464                if (status & TIP)
 465                        printk(KERN_ERR "maciisi_interrupt: state is idle but TIP asserted!\n");
 466
 467                if(!reading_reply)
 468                        udelay(ADB_DELAY);
 469                /* Shift in */
 470                via[ACR] &= ~SR_OUT;
 471                /* Signal start of frame */
 472                via[B] |= TIP;
 473                /* Clear the interrupt (throw this value on the floor, it's useless) */
 474                tmp = via[SR];
 475                /* ACK adb chip, high-low */
 476                via[B] |= TACK;
 477                udelay(ADB_DELAY);
 478                via[B] &= ~TACK;
 479                reply_len = 0;
 480                maciisi_state = reading;
 481                if (reading_reply) {
 482                        reply_ptr = current_req->reply;
 483                } else {
 484                        reply_ptr = maciisi_rbuf;
 485                }
 486                break;
 487
 488        case sending:
 489                /* via[SR]; */
 490                /* Set ACK off */
 491                via[B] &= ~TACK;
 492                req = current_req;
 493
 494                if (!(status & TREQ)) {
 495                        /* collision */
 496                        printk(KERN_ERR "maciisi_interrupt: send collision\n");
 497                        /* Set idle and input */
 498                        via[ACR] &= ~SR_OUT;
 499                        tmp = via[SR];
 500                        via[B] &= ~TIP;
 501                        /* Must re-send */
 502                        reading_reply = 0;
 503                        reply_len = 0;
 504                        maciisi_state = idle;
 505                        udelay(ADB_DELAY);
 506                        /* process this now, because the IFR has been cleared */
 507                        goto switch_start;
 508                }
 509
 510                udelay(ADB_DELAY);
 511
 512                if (data_index >= req->nbytes) {
 513                        /* Sent the whole packet, put the bus back in idle state */
 514                        /* Shift in, we are about to read a reply (hopefully) */
 515                        via[ACR] &= ~SR_OUT;
 516                        tmp = via[SR];
 517                        /* End of frame */
 518                        via[B] &= ~TIP;
 519                        req->sent = 1;
 520                        maciisi_state = idle;
 521                        if (req->reply_expected) {
 522                                /* Note: only set this once we've
 523                                   successfully sent the packet */
 524                                reading_reply = 1;
 525                        } else {
 526                                current_req = req->next;
 527                                if (req->done)
 528                                        (*req->done)(req);
 529                                /* Do any queued requests now */
 530                                i = maciisi_start();
 531                                if(i == 0 && need_sync) {
 532                                        /* Packet needs to be synced */
 533                                        maciisi_sync(current_req);
 534                                }
 535                                if(i != -EBUSY)
 536                                        need_sync = 0;
 537                        }
 538                } else {
 539                        /* Sending more stuff */
 540                        /* Shift out */
 541                        via[ACR] |= SR_OUT;
 542                        /* Write */
 543                        via[SR] = req->data[data_index++];
 544                        /* Signal 'byte ready' */
 545                        via[B] |= TACK;
 546                }
 547                break;
 548
 549        case reading:
 550                /* Shift in */
 551                /* via[ACR] &= ~SR_OUT; */ /* Not in 2.2 */
 552                if (reply_len++ > 16) {
 553                        printk(KERN_ERR "maciisi_interrupt: reply too long, aborting read\n");
 554                        via[B] |= TACK;
 555                        udelay(ADB_DELAY);
 556                        via[B] &= ~(TACK|TIP);
 557                        maciisi_state = idle;
 558                        i = maciisi_start();
 559                        if(i == 0 && need_sync) {
 560                                /* Packet needs to be synced */
 561                                maciisi_sync(current_req);
 562                        }
 563                        if(i != -EBUSY)
 564                                need_sync = 0;
 565                        break;
 566                }
 567                /* Read data */
 568                *reply_ptr++ = via[SR];
 569                status = via[B] & (TIP|TREQ);
 570                /* ACK on/off */
 571                via[B] |= TACK;
 572                udelay(ADB_DELAY);
 573                via[B] &= ~TACK;        
 574                if (!(status & TREQ))
 575                        break; /* more stuff to deal with */
 576                
 577                /* end of frame */
 578                via[B] &= ~TIP;
 579                tmp = via[SR]; /* That's what happens in 2.2 */
 580                udelay(ADB_DELAY); /* Give controller time to recover */
 581
 582                /* end of packet, deal with it */
 583                if (reading_reply) {
 584                        req = current_req;
 585                        req->reply_len = reply_ptr - req->reply;
 586                        if (req->data[0] == ADB_PACKET) {
 587                                /* Have to adjust the reply from ADB commands */
 588                                if (req->reply_len <= 2 || (req->reply[1] & 2) != 0) {
 589                                        /* the 0x2 bit indicates no response */
 590                                        req->reply_len = 0;
 591                                } else {
 592                                        /* leave just the command and result bytes in the reply */
 593                                        req->reply_len -= 2;
 594                                        memmove(req->reply, req->reply + 2, req->reply_len);
 595                                }
 596                        }
 597#ifdef DEBUG_MACIISI_ADB
 598                        if (dump_reply) {
 599                                int i;
 600                                printk(KERN_DEBUG "maciisi_interrupt: reply is ");
 601                                for (i = 0; i < req->reply_len; ++i)
 602                                        printk(" %.2x", req->reply[i]);
 603                                printk("\n");
 604                        }
 605#endif
 606                        req->complete = 1;
 607                        current_req = req->next;
 608                        if (req->done)
 609                                (*req->done)(req);
 610                        /* Obviously, we got it */
 611                        reading_reply = 0;
 612                } else {
 613                        maciisi_input(maciisi_rbuf, reply_ptr - maciisi_rbuf);
 614                }
 615                maciisi_state = idle;
 616                status = via[B] & (TIP|TREQ);
 617                if (!(status & TREQ)) {
 618                        /* Timeout?! More likely, another packet coming in already */
 619#ifdef DEBUG_MACIISI_ADB
 620                        printk(KERN_DEBUG "extra data after packet: status %x ifr %x\n",
 621                               status, via[IFR]);
 622#endif
 623#if 0
 624                        udelay(ADB_DELAY);
 625                        via[B] |= TIP;
 626
 627                        maciisi_state = reading;
 628                        reading_reply = 0;
 629                        reply_ptr = maciisi_rbuf;
 630#else
 631                        /* Process the packet now */
 632                        reading_reply = 0;
 633                        goto switch_start;
 634#endif
 635                        /* We used to do this... but the controller might actually have data for us */
 636                        /* maciisi_stfu(); */
 637                }
 638                else {
 639                        /* Do any queued requests now if possible */
 640                        i = maciisi_start();
 641                        if(i == 0 && need_sync) {
 642                                /* Packet needs to be synced */
 643                                maciisi_sync(current_req);
 644                        }
 645                        if(i != -EBUSY)
 646                                need_sync = 0;
 647                }
 648                break;
 649
 650        default:
 651                printk("maciisi_interrupt: unknown maciisi_state %d?\n", maciisi_state);
 652        }
 653        local_irq_restore(flags);
 654        return IRQ_HANDLED;
 655}
 656
 657static void
 658maciisi_input(unsigned char *buf, int nb)
 659{
 660#ifdef DEBUG_MACIISI_ADB
 661    int i;
 662#endif
 663
 664    switch (buf[0]) {
 665    case ADB_PACKET:
 666            adb_input(buf+2, nb-2, buf[1] & 0x40);
 667            break;
 668    default:
 669#ifdef DEBUG_MACIISI_ADB
 670            printk(KERN_DEBUG "data from IIsi ADB (%d bytes):", nb);
 671            for (i = 0; i < nb; ++i)
 672                    printk(" %.2x", buf[i]);
 673            printk("\n");
 674#endif
 675            break;
 676    }
 677}
 678
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.