~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/macintosh/via-maciisi.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 #include <linux/types.h>
 15 #include <linux/errno.h>
 16 #include <linux/kernel.h>
 17 #include <linux/sched.h>
 18 #include <linux/adb.h>
 19 #include <linux/cuda.h>
 20 #include <linux/delay.h>
 21 #include <asm/macintosh.h>
 22 #include <asm/macints.h>
 23 #include <asm/machw.h>
 24 #include <asm/mac_via.h>
 25 
 26 static volatile unsigned char *via;
 27 
 28 /* VIA registers - spaced 0x200 bytes apart - only the ones we actually use */
 29 #define RS              0x200           /* skip between registers */
 30 #define B               0               /* B-side data */
 31 #define A               RS              /* A-side data */
 32 #define DIRB            (2*RS)          /* B-side direction (1=output) */
 33 #define DIRA            (3*RS)          /* A-side direction (1=output) */
 34 #define SR              (10*RS)         /* Shift register */
 35 #define ACR             (11*RS)         /* Auxiliary control register */
 36 #define IFR             (13*RS)         /* Interrupt flag register */
 37 #define IER             (14*RS)         /* Interrupt enable register */
 38 
 39 /* Bits in B data register: all active low */
 40 #define TREQ            0x08            /* Transfer request (input) */
 41 #define TACK            0x10            /* Transfer acknowledge (output) */
 42 #define TIP             0x20            /* Transfer in progress (output) */
 43 #define ST_MASK         0x30            /* mask for selecting ADB state bits */
 44 
 45 /* Bits in ACR */
 46 #define SR_CTRL         0x1c            /* Shift register control bits */
 47 #define SR_EXT          0x0c            /* Shift on external clock */
 48 #define SR_OUT          0x10            /* Shift out if 1 */
 49 
 50 /* Bits in IFR and IER */
 51 #define IER_SET         0x80            /* set bits in IER */
 52 #define IER_CLR         0               /* clear bits in IER */
 53 #define SR_INT          0x04            /* Shift register full/empty */
 54 #define SR_DATA         0x08            /* Shift register data */
 55 #define SR_CLOCK        0x10            /* Shift register clock */
 56 
 57 #define ADB_DELAY 150
 58 
 59 static struct adb_request* current_req = NULL;
 60 static struct adb_request* last_req = NULL;
 61 static unsigned char maciisi_rbuf[16];
 62 static unsigned char *reply_ptr = NULL;
 63 static int data_index;
 64 static int reading_reply;
 65 static int reply_len;
 66 
 67 static enum maciisi_state {
 68     idle,
 69     sending,
 70     reading,
 71 } maciisi_state;
 72 
 73 static int maciisi_probe(void);
 74 static int maciisi_init(void);
 75 static int maciisi_send_request(struct adb_request* req, int sync);
 76 static int maciisi_write(struct adb_request* req);
 77 static void maciisi_interrupt(int irq, void* arg, struct pt_regs* regs);
 78 static void maciisi_input(unsigned char *buf, int nb, struct pt_regs *regs);
 79 static int maciisi_init_via(void);
 80 static void maciisi_poll(void);
 81 static void maciisi_start(void);
 82 
 83 struct adb_driver via_maciisi_driver = {
 84         "Mac IIsi",
 85         maciisi_probe,
 86         maciisi_init,
 87         maciisi_send_request,
 88         NULL, /* maciisi_adb_autopoll, */
 89         maciisi_poll,
 90         NULL /* maciisi_reset_adb_bus */
 91 };
 92 
 93 static int
 94 maciisi_probe(void)
 95 {
 96         if (macintosh_config->adb_type != MAC_ADB_IISI)
 97                 return -ENODEV;
 98 
 99         via = via1;
100         return 0;
101 }
102 
103 static int
104 maciisi_init(void)
105 {
106         int err;
107 
108         if (via == NULL)
109                 return -ENODEV;
110 
111         if ((err = maciisi_init_via())) {
112                 printk(KERN_ERR "maciisi_init: maciisi_init_via() failed, code %d\n", err);
113                 via = NULL;
114                 return err;
115         }
116 
117         if (request_irq(IRQ_MAC_ADB, maciisi_interrupt, IRQ_FLG_LOCK, 
118                         "ADB", maciisi_interrupt)) {
119                 printk(KERN_ERR "maciisi_init: can't get irq %d\n", IRQ_MAC_ADB);
120                 return -EAGAIN;
121         }
122 
123         printk("adb: Mac IIsi driver v0.1 for Unified ADB.\n");
124         return 0;
125 }
126 
127 static void
128 maciisi_stfu(void)
129 {
130         int status = via[B] & (TIP|TREQ);
131 
132         if (status & TREQ) {
133                 printk (KERN_DEBUG "maciisi_stfu called with TREQ high!\n");
134                 return;
135         }
136 
137         /* start transfer */
138         via[B] |= TIP;
139         while (!(status & TREQ)) {
140                 int poll_timeout = ADB_DELAY * 5;
141                 /* Poll for SR interrupt */
142                 while (!(via[IFR] & SR_INT) && poll_timeout-- > 0)
143                         status = via[B] & (TIP|TREQ);
144                 via[SR]; /* Clear shift register */
145                 printk(KERN_DEBUG "maciisi_stfu: status %x timeout %d\n",
146                        status, poll_timeout);
147                 
148                 /* ACK on-off */
149                 via[B] |= TACK;
150                 udelay(ADB_DELAY);
151                 via[B] &= ~TACK;
152         }
153         /* end frame */
154         via[B] &= ~TIP;
155 }
156 
157 /* All specifically VIA-related initialization goes here */
158 static int
159 maciisi_init_via(void)
160 {
161         /* Set the lines up. We want TREQ as input TACK|TIP as output */
162         via[DIRB] = (via[DIRB] | TACK | TIP) & ~TREQ;
163         /* Shift register on input */
164         via[ACR]  = (via[ACR] & ~SR_CTRL) | SR_EXT;
165         printk(KERN_DEBUG "maciisi_init_via: initial status %x\n", via[B] & (TIP|TREQ));
166         /* Set initial state: idle */
167         via[B] &= ~(TACK|TIP);
168         /* Wipe any pending data and int */
169         via[SR];
170         if (!(via[B] & TREQ))
171                 maciisi_stfu();
172         via[IER] = IER_SET | SR_INT;
173         maciisi_state = idle;
174         return 0;
175 }
176 
177 /* Send a request, possibly waiting for a reply */
178 static int
179 maciisi_send_request(struct adb_request* req, int sync)
180 {
181         int i;
182         static int dump_packet = 1;
183 
184         if (via == NULL) {
185                 req->complete = 1;
186                 return -ENXIO;
187         }
188 
189         if (dump_packet) {
190                 printk(KERN_DEBUG "maciisi_send_request:");
191                 for (i = 0; i < req->nbytes; i++) {
192                         printk(" %.2x", req->data[i]);
193                 }
194                 printk("\n");
195         }
196         req->reply_expected = 1;
197         
198         i = maciisi_write(req);
199         if (i)
200                 return i;
201         
202         if (sync) {
203                 while (!req->complete) {
204                         maciisi_poll();
205                 }
206         }
207         return 0;
208 }
209 
210 /* Enqueue a request, and run the queue if possible */
211 static int
212 maciisi_write(struct adb_request* req)
213 {
214         unsigned long flags;
215 
216         printk(KERN_DEBUG "maciisi_write called, state=%d ifr=%x\n", maciisi_state, via[IFR]);
217         /* We will accept CUDA packets - the VIA sends them to us, so
218            it figures that we should be able to send them to it */
219         if (req->nbytes < 2 || req->data[0] > CUDA_PACKET) {
220                 printk(KERN_ERR "maciisi_write: packet too small or not an ADB or CUDA packet\n");
221                 req->complete = 1;
222                 return -EINVAL;
223         }
224         req->next = 0;
225         req->sent = 0;
226         req->complete = 0;
227         req->reply_len = 0;
228         save_flags(flags); cli();
229 
230         if (current_req) {
231                 last_req->next = req;
232                 last_req = req;
233         } else {
234                 current_req = req;
235                 last_req = req;
236         }
237         if (maciisi_state == idle)
238                 maciisi_start();
239         else
240                 printk(KERN_DEBUG "maciisi_write: would start, but state is %d\n", maciisi_state);
241 
242         restore_flags(flags);
243         return 0;
244 }
245 
246 static void
247 maciisi_start(void)
248 {
249         struct adb_request* req;
250         int status;
251 
252         printk(KERN_DEBUG "maciisi_start called, state=%d, ifr=%x\n", maciisi_state, via[IFR]);
253         if (maciisi_state != idle) {
254                 /* shouldn't happen */
255                 printk(KERN_ERR "maciisi_start: maciisi_start called when driver busy!\n");
256                 return;
257         }
258 
259         req = current_req;
260         if (req == NULL)
261                 return;
262 
263         status = via[B] & (TIP|TREQ);
264         if (!(status & TREQ)) {
265                 /* Bus is busy, set up for reading */
266                 printk(KERN_DEBUG "maciisi_start: bus busy - aborting\n");
267                 return;
268         }
269 
270         /* Okay, send */
271         printk(KERN_DEBUG "maciisi_start: sending\n");
272         /* Set state to active */
273         via[B] |= TIP;
274         /* ACK off */
275         via[B] &= ~TACK;
276         /* Shift out and send */
277         via[ACR] |= SR_OUT;
278         via[SR] = req->data[0];
279         data_index = 1;
280         /* ACK on */
281         via[B] |= TACK;
282         maciisi_state = sending;
283 }
284 
285 void
286 maciisi_poll(void)
287 {
288         unsigned long flags;
289 
290         save_flags(flags);
291         cli();
292         if (via[IFR] & SR_INT) {
293                 maciisi_interrupt(0, 0, 0);
294         }
295         restore_flags(flags);
296 }
297 
298 /* Shift register interrupt - this is *supposed* to mean that the
299    register is either full or empty. In practice, I have no idea what
300    it means :( */
301 static void
302 maciisi_interrupt(int irq, void* arg, struct pt_regs* regs)
303 {
304         int status;
305         struct adb_request *req;
306         static int dump_reply = 1;
307 
308         if (!(via[IFR] & SR_INT)) {
309                 /* Shouldn't happen, we hope */
310                 printk(KERN_DEBUG "maciisi_interrupt: called without interrupt flag set\n");
311                 return;
312         }
313 
314         status = via[B] & (TIP|TREQ);
315         printk(KERN_DEBUG "state %d status %x ifr %x\n", maciisi_state, status, via[IFR]);
316 
317  switch_start:
318         switch (maciisi_state) {
319         case idle:
320                 printk(KERN_DEBUG "maciisi_interrupt: state=idle, status %x\n", status);
321                 if (status & TIP)
322                         printk(KERN_DEBUG "maciisi_interrupt: state is idle but TIP asserted!\n");
323 
324                 udelay(ADB_DELAY);
325                 /* Shift in */
326                 via[ACR] &= ~SR_OUT;
327                 /* Signal start of frame */
328                 via[B] |= TIP;
329                 /* Clear the interrupt (throw this value on the floor, it's useless) */
330                 via[SR];
331                 /* ACK adb chip, high-low */
332                 via[B] |= TACK;
333                 udelay(ADB_DELAY);
334                 via[B] &= ~TACK;
335                 reply_len = 0;
336                 maciisi_state = reading;
337                 if (reading_reply) {
338                         reply_ptr = current_req->reply;
339                 } else {
340                         printk(KERN_DEBUG "maciisi_interrupt: received unsolicited packet\n");
341                         reply_ptr = maciisi_rbuf;
342                 }
343                 break;
344 
345         case sending:
346                 printk(KERN_DEBUG "maciisi_interrupt: state=sending, status=%x\n", status);
347                 /* Clear interrupt */
348                 via[SR];
349                 /* Set ACK off */
350                 via[B] &= ~TACK;
351                 req = current_req;
352 
353                 if (!(status & TREQ)) {
354                         /* collision */
355                         printk(KERN_DEBUG "maciisi_interrupt: send collision\n");
356                         /* Set idle and input */
357                         via[B] &= ~TIP;
358                         via[ACR] &= ~SR_OUT;
359                         /* Must re-send */
360                         reading_reply = 0;
361                         reply_len = 0;
362                         maciisi_state = idle;
363                         /* process this now, because the IFR has been cleared */
364                         goto switch_start;
365                 }
366 
367                 if (data_index >= req->nbytes) {
368                         /* Sent the whole packet, put the bus back in idle state */
369                         /* Shift in, we are about to read a reply (hopefully) */
370                         via[ACR] &= ~SR_OUT;
371                         /* End of frame */
372                         via[B] &= ~TIP;
373                         req->sent = 1;
374                         maciisi_state = idle;
375                         if (req->reply_expected) {
376                                 /* Note: only set this once we've
377                                    successfully sent the packet */
378                                 reading_reply = 1;
379                         } else {
380                                 current_req = req->next;
381                                 if (req->done)
382                                         (*req->done)(req);
383                         }
384                 } else {
385                         /* Sending more stuff */
386                         /* Shift out */
387                         via[ACR] |= SR_OUT;
388                         /* Delay */
389                         udelay(ADB_DELAY);
390                         /* Write */
391                         via[SR] = req->data[data_index++];
392                         /* Signal 'byte ready' */
393                         via[B] |= TACK;
394                 }
395                 break;
396 
397         case reading:
398                 printk(KERN_DEBUG "maciisi_interrupt: state=reading, status=%x\n", status);
399                 /* Shift in */
400                 via[ACR] &= ~SR_OUT;
401                 if (reply_len++ > 16) {
402                         printk(KERN_ERR "maciisi_interrupt: reply too long, aborting read\n");
403                         via[B] |= TACK;
404                         udelay(ADB_DELAY);
405                         via[B] &= ~(TACK|TIP);
406                         maciisi_state = idle;
407                         maciisi_start();
408                         break;
409                 }
410                 *reply_ptr++ = via[SR];
411                 status = via[B] & (TIP|TREQ);
412                 /* ACK on/off */
413                 via[B] |= TACK;
414                 udelay(ADB_DELAY);
415                 via[B] &= ~TACK;        
416                 if (!(status & TREQ))
417                         break; /* more stuff to deal with */
418                 
419                 /* end of frame */
420                 via[B] &= ~TIP;
421 
422                 /* end of packet, deal with it */
423                 if (reading_reply) {
424                         req = current_req;
425                         req->reply_len = reply_ptr - req->reply;
426                         if (req->data[0] == ADB_PACKET) {
427                                 /* Have to adjust the reply from ADB commands */
428                                 if (req->reply_len <= 2 || (req->reply[1] & 2) != 0) {
429                                         /* the 0x2 bit indicates no response */
430                                         req->reply_len = 0;
431                                 } else {
432                                         /* leave just the command and result bytes in the reply */
433                                         req->reply_len -= 2;
434                                         memmove(req->reply, req->reply + 2, req->reply_len);
435                                 }
436                         }
437                         if (dump_reply) {
438                                 int i;
439                                 printk(KERN_DEBUG "maciisi_interrupt: reply is ");
440                                 for (i = 0; i < req->reply_len; ++i)
441                                         printk(" %.2x", req->reply[i]);
442                                 printk("\n");
443                         }
444                         req->complete = 1;
445                         current_req = req->next;
446                         if (req->done)
447                                 (*req->done)(req);
448                         /* Obviously, we got it */
449                         reading_reply = 0;
450                 } else {
451                         maciisi_input(maciisi_rbuf, reply_ptr - maciisi_rbuf, regs);
452                 }
453                 maciisi_state = idle;
454                 status = via[B] & (TIP|TREQ);
455                 if (!(status & TREQ)) {
456                         /* Timeout?! */
457                         printk(KERN_DEBUG "extra data after packet: status %x ifr %x\n",
458                                status, via[IFR]);
459                         maciisi_stfu();
460                 }
461                 /* Do any queued requests now if possible */
462                 maciisi_start();
463                 break;
464 
465         default:
466                 printk("maciisi_interrupt: unknown maciisi_state %d?\n", maciisi_state);
467         }
468 }
469 
470 static void
471 maciisi_input(unsigned char *buf, int nb, struct pt_regs *regs)
472 {
473     int i;
474 
475     switch (buf[0]) {
476     case ADB_PACKET:
477             adb_input(buf+2, nb-2, regs, buf[1] & 0x40);
478             break;
479     default:
480             printk(KERN_DEBUG "data from IIsi ADB (%d bytes):", nb);
481             for (i = 0; i < nb; ++i)
482                     printk(" %.2x", buf[i]);
483             printk("\n");
484 
485     }
486 }
487 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.