OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [macintosh/] [via-maciisi.c] - Blame information for rev 62

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.