FreeBSD/Linux Kernel Cross Reference
sys/chips/dtop_hdw.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,1992 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: dtop_hdw.c,v $
29 * Revision 2.9 93/05/15 19:39:04 mrt
30 * machparam.h -> machspl.h
31 *
32 * Revision 2.8 93/05/10 20:07:34 rvb
33 * Fixed types.
34 * [93/05/06 09:59:47 af]
35 *
36 * Revision 2.7 93/03/26 17:58:31 mrt
37 * Rid of dev_t.
38 * [93/03/19 af]
39 *
40 * Revision 2.6 93/02/01 09:55:33 danner
41 * Made all printfs conditional
42 * [93/01/25 danner]
43 *
44 * Revision 2.5 93/01/14 17:15:48 danner
45 * Prototyped handler.
46 * [93/01/14 danner]
47 *
48 * Now that we know how to be heard on the bus, added bell
49 * and .. leds. From jtp@hut.fi.
50 * [92/12/14 af]
51 * Proper spl typing.
52 * [92/11/30 af]
53 *
54 * Revision 2.4 92/05/22 15:47:43 jfriedl
55 * Poll every 16usecs, as per specs.
56 * [92/05/20 22:41:35 af]
57 *
58 * Revision 2.2.1.1 92/05/04 11:19:55 af
59 * Fixed interrupt routine & spls.
60 * Since t_addr is now used to check for presence of
61 * a given line, make sure it is non-zero.
62 * [92/05/04 af]
63 *
64 * Revision 2.2 92/03/02 18:32:29 rpd
65 * Created, from DEC specs.
66 * [92/01/19 af]
67 *
68 */
69 /*
70 * File: dtop_hdw.c
71 * Author: Alessandro Forin, Carnegie Mellon University
72 * Date: 1/92
73 *
74 * Hardware-level operations for the Desktop serial line
75 * bus (i2c aka ACCESS).
76 */
77
78 #include <dtop.h>
79 #if NDTOP > 0
80 #include <bm.h>
81 #include <platforms.h>
82
83 #include <machine/machspl.h> /* spl definitions */
84 #include <mach/std_types.h>
85 #include <device/io_req.h>
86 #include <device/tty.h>
87
88 #include <chips/busses.h>
89 #include <chips/serial_defs.h>
90 #include <chips/screen_defs.h>
91 #include <chips/lk201.h>
92 #include <mips/PMAX/tc.h>
93
94 #include <chips/dtop.h>
95
96 #define DTOP_MAX_POLL 0x7fff /* about half a sec */
97
98 #ifdef MAXINE
99
100 typedef volatile unsigned int *data_reg_t; /* uC */
101 #define DTOP_GET_BYTE(data) (((*(data)) >> 8) & 0xff)
102 #define DTOP_PUT_BYTE(data,c) { *(data) = (c) << 8; }
103
104 typedef volatile unsigned int *poll_reg_t; /* SIR */
105 #define DTOP_RX_AVAIL(poll) (*(poll) & 1)
106 #define DTOP_TX_AVAIL(poll) (*(poll) & 2)
107
108 #else
109
110 define how to get/put DTOP packets on this box
111
112 #endif
113
114 /*
115 * Driver status
116 */
117
118 struct dtop_softc {
119 data_reg_t data;
120 poll_reg_t poll;
121 char polling_mode;
122 char probed_once;
123 short bad_pkts;
124
125 struct dtop_ds {
126 int (*handler)(dtop_device_t,
127 dtop_message_t,
128 int,
129 unsigned char);
130 dtop_device status;
131 } device[(DTOP_ADDR_DEFAULT - DTOP_ADDR_FIRST) >> 1];
132
133 # define DTOP_DEVICE_NO(address) (((address)-DTOP_ADDR_FIRST)>>1)
134
135 } dtop_softc_data[NDTOP];
136
137 typedef struct dtop_softc *dtop_softc_t;
138
139 dtop_softc_t dtop_softc[NDTOP];
140
141 /*
142 * Definition of the driver for the auto-configuration program.
143 */
144
145 int dtop_probe(), dtop_intr();
146 static void dtop_attach();
147
148 vm_offset_t dtop_std[NDTOP] = { 0 };
149 struct bus_device *dtop_info[NDTOP];
150 struct bus_driver dtop_driver =
151 { dtop_probe, 0, dtop_attach, 0, dtop_std, "dtop", dtop_info,};
152
153
154 int dtop_print_debug = 0;
155
156 /*
157 * Adapt/Probe/Attach functions
158 */
159
160 set_dtop_address( dtopunit, poll_reg)
161 data_reg_t poll_reg;
162 {
163 int i;
164
165 extern int dtop_probe(), dtop_param(), dtop_start(),
166 dtop_putc(), dtop_getc(),
167 dtop_pollc(), dtop_mctl(), dtop_softCAR();
168
169 dtop_std[dtopunit] = (vm_offset_t)poll_reg;
170
171 /* Do this here */
172 console_probe = dtop_probe;
173 console_param = dtop_param;
174 console_start = dtop_start;
175 console_putc = dtop_putc;
176 console_getc = dtop_getc;
177 console_pollc = dtop_pollc;
178 console_mctl = dtop_mctl;
179 console_softCAR = dtop_softCAR;
180
181 }
182
183 dtop_probe( data_reg, ui)
184 data_reg_t data_reg;
185 struct bus_device *ui;
186 {
187 int dtopunit = ui->unit, i;
188 dtop_softc_t dtop;
189
190 dtop = &dtop_softc_data[dtopunit];
191 dtop_softc[dtopunit] = dtop;
192
193 dtop->poll = (poll_reg_t)dtop_std[dtopunit];
194 dtop->data = data_reg;
195
196 for (i = 0; i < DTOP_MAX_DEVICES; i++)
197 dtop->device[i].handler = dtop_null_device_handler;
198
199 /* a lot more needed here, fornow: */
200 dtop->device[DTOP_DEVICE_NO(0x6a)].handler = dtop_locator_handler;
201 dtop->device[DTOP_DEVICE_NO(0x6a)].status.locator.type =
202 DEV_MOUSE;
203 dtop->device[DTOP_DEVICE_NO(0x6a)].status.locator.relative =
204 1;
205 dtop->device[DTOP_DEVICE_NO(0x6a)].status.locator.button_code[0] =
206 KEY_LEFT_BUTTON;
207 dtop->device[DTOP_DEVICE_NO(0x6a)].status.locator.button_code[1] =
208 KEY_RIGHT_BUTTON;
209 dtop->device[DTOP_DEVICE_NO(0x6a)].status.locator.button_code[2] =
210 KEY_MIDDLE_BUTTON;
211 dtop->device[DTOP_DEVICE_NO(0x6a)].status.locator.n_coords =
212 2;
213
214 dtop->device[DTOP_DEVICE_NO(0x6c)].handler = dtop_keyboard_handler;
215 dtop->device[DTOP_DEVICE_NO(0x6c)].status.keyboard.poll_frequency =
216 (hz * 5) / 100; /* x0.01 secs */
217 dtop->device[DTOP_DEVICE_NO(0x6c)].status.keyboard.bell_volume =
218 DTOP_CLICK_VOLUME_MAX;
219
220 return 1;
221 }
222
223 static void
224 dtop_attach(ui)
225 struct bus_device *ui;
226 {
227 int i;
228
229 /* Initialize all the console ttys */
230 for (i = 0; i < 4; i++)
231 ttychars(console_tty[i]);
232 /* Mark keyboard and mouse present */
233 for (i = 0; i < 2; i++)
234 console_tty[i]->t_addr = (char*)1;
235 }
236
237 /*
238 * Polled I/O (debugger)
239 */
240 dtop_pollc(unit, on)
241 boolean_t on;
242 {
243 dtop_softc_t dtop;
244
245 dtop = dtop_softc[unit];
246 if (on) {
247 dtop->polling_mode++;
248 #if NBM > 0
249 screen_on_off(unit, TRUE);
250 #endif NBM > 0
251 } else
252 dtop->polling_mode--;
253 }
254
255 /*
256 * Interrupt routine
257 */
258 dtop_intr (unit, spllevel, recvd)
259 spl_t spllevel;
260 boolean_t recvd;
261 {
262
263 if (recvd) {
264 dtop_message msg;
265 int devno;
266 dtop_softc_t dtop;
267
268 ssaver_bump(unit);
269
270 #ifdef mips
271 splx(spllevel);
272 #endif
273
274 dtop = dtop_softc[unit];
275 if (dtop_get_packet(dtop, &msg) < 0) {
276 if (dtop_print_debug)
277 printf("%s", "dtop: overrun (or stray)\n");
278 return;
279 }
280
281 devno = DTOP_DEVICE_NO(msg.src_address);
282 if (devno < 0 || devno > 15) return; /* sanity */
283
284 (void) (*dtop->device[devno].handler)
285 (&dtop->device[devno].status, &msg,
286 DTOP_EVENT_RECEIVE_PACKET, 0);
287
288 } else {
289 /* fornow xmit is not intr based */
290 (*tc_enable_interrupt)( dtop_info[unit]->adaptor, FALSE, TRUE);
291 }
292 }
293
294 boolean_t
295 dtop_start(tp)
296 struct tty *tp;
297 {
298 register int line, temp;
299
300 /* no, we do not need a char out first */
301 return FALSE;
302 }
303
304 dtop_w_test(n, a,b,c,d,e,f,g,h)
305 {
306 int *p = (int*)0xbc2a0000;
307
308 if (n <= 0) return;
309
310 a <<= 8; *p = a;
311 if (--n == 0) goto out;
312 delay(20);
313 b <<= 8; *p = b;
314 if (--n == 0) goto out;
315 delay(20);
316 c <<= 8; *p = c;
317 if (--n == 0) goto out;
318 delay(20);
319 d <<= 8; *p = d;
320 if (--n == 0) goto out;
321 delay(20);
322 e <<= 8; *p = e;
323 if (--n == 0) goto out;
324 delay(20);
325 f <<= 8; *p = f;
326 if (--n == 0) goto out;
327 delay(20);
328 g <<= 8; *p = g;
329 if (--n == 0) goto out;
330 delay(20);
331 h <<= 8; *p = h;
332 out:
333 delay(10000);
334 {
335 int buf[100];
336
337 delay(20);
338 a = *p;
339 buf[0] = a;
340 c = 1;
341 for (n = 0; n < 100; n++) {
342 delay(20);
343 b = *p;
344 if (b != a) {
345 buf[c++] = b;
346 b = a;
347 }
348 }
349 for (n = 0; n < c; n++)
350 db_printf("%x ", ((buf[n])>>8)&0xff);
351 }
352 return c;
353 }
354
355 /*
356 * Take a packet off dtop interface
357 * A packet MUST be there, this is not checked for.
358 */
359 #define DTOP_ESC_CHAR 0xf8
360 dtop_escape(c)
361 {
362 /* I donno much about this stuff.. */
363 switch (c) {
364 case 0xe8: return 0xf8;
365 case 0xe9: return 0xf9;
366 case 0xea: return 0xfa;
367 case 0xeb: return 0xfb;
368 default: /* printf("{esc %x}", c); */
369 return c;
370 }
371 }
372
373 dtop_get_packet(dtop, pkt)
374 dtop_softc_t dtop;
375 dtop_message_t pkt;
376 {
377 register poll_reg_t poll;
378 register data_reg_t data;
379 register int max, i, len;
380 register unsigned char c;
381
382 poll = dtop->poll;
383 data = dtop->data;
384
385 /*
386 * The interface does not handle us the first byte,
387 * which is our address and cannot ever be anything
388 * else but 0x50. This is a good thing, it makes
389 * the average packet exactly one word long, too.
390 */
391 pkt->src_address = DTOP_GET_BYTE(data);
392
393 for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++)
394 delay(16);
395 if (max == DTOP_MAX_POLL) goto bad;
396 pkt->code.bits = DTOP_GET_BYTE(data);
397
398 /*
399 * Now get data and checksum
400 */
401 len = pkt->code.val.len + 1;
402 c = 0;
403 for (i = 0; i < len; i++) {
404
405 again: for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++)
406 delay(16);
407 if (max == DTOP_MAX_POLL) goto bad;
408 if (c == DTOP_ESC_CHAR) {
409 c = dtop_escape(DTOP_GET_BYTE(data) & 0xff);
410 } else {
411 c = DTOP_GET_BYTE(data);
412 if (c == DTOP_ESC_CHAR)
413 goto again;
414 }
415
416 pkt->body[i] = c;
417 }
418 return len;
419 bad:
420 dtop->bad_pkts++;
421 return -1;
422 }
423
424 /* Conversely... */
425 dtop_put_packet(dtop, pkt)
426 dtop_softc_t dtop;
427 dtop_message_t pkt;
428 {
429 register int i, max;
430 register unsigned char *cp;
431 register unsigned int spl;
432 register unsigned char c;
433
434 spl = spltty();
435 pkt->src_address = pkt->dest_address;
436 i = 0;
437 cp = (unsigned char *)&pkt->src_address;
438 while (i < pkt->code.val.len + 2) {
439 for (max = 0; max < DTOP_MAX_POLL && !DTOP_TX_AVAIL(dtop->poll);
440 max++);
441 if (max == DTOP_MAX_POLL)
442 goto bad;
443 DTOP_PUT_BYTE(dtop->data, *cp);
444 cp++;
445 i++;
446 }
447 for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(dtop->poll); max++)
448 delay(16);
449 if (max == DTOP_MAX_POLL)
450 goto bad;
451 c = DTOP_GET_BYTE(dtop->data);
452 if (c == DTOP_ESC_CHAR) {
453 for (max = 0; (max < DTOP_MAX_POLL)
454 && !DTOP_RX_AVAIL(dtop->poll); max++)
455 delay(16);
456 if (max == DTOP_MAX_POLL)
457 goto bad;
458 c = DTOP_GET_BYTE(dtop->data);
459 }
460 splx(spl);
461 switch (c) {
462 case 0xfb: /* XMT, ok */
463 break;
464 default:
465 return 0;
466 }
467 return 1;
468 bad:
469 splx(spl);
470 return 0;
471 }
472
473
474 /*
475 * Get a char from a specific DTOP line
476 * [this is only used for console&screen purposes]
477 */
478 dtop_getc( unit, line, wait, raw )
479 boolean_t wait;
480 boolean_t raw;
481 {
482 register int c;
483 dtop_softc_t dtop;
484
485 dtop = dtop_softc[unit];
486 again:
487 c = -1;
488
489 /*
490 * Try rconsole first
491 */
492 if (rcline && line == SCREEN_LINE_KEYBOARD) {
493 c = scc_getc( 0, rcline, FALSE, raw);
494 if (c != -1) return c;
495 }
496
497 /*
498 * Now check keyboard
499 */
500 if (DTOP_RX_AVAIL(dtop->poll)) {
501
502 dtop_message msg;
503 struct dtop_ds *ds;
504
505 if (dtop_get_packet(dtop, &msg) >= 0) {
506
507 ds = &dtop->device[DTOP_DEVICE_NO(msg.src_address)];
508 if (ds->handler == dtop_keyboard_handler) {
509
510 c = dtop_keyboard_handler(
511 &ds->status, &msg,
512 DTOP_EVENT_RECEIVE_PACKET, -1);
513
514 if (c > 0) return c;
515
516 c = -1;
517 }
518 }
519 }
520
521 if (wait && (c == -1)) {
522 delay(100);
523 goto again;
524 }
525
526 return c;
527 }
528
529 /*
530 * Put a char on a specific DTOP line
531 */
532 dtop_putc( unit, line, c )
533 {
534 if (rcline && line == rcline) {
535 scc_putc(0, rcline, c);
536 }
537 /* dprintf("%c", c); */
538 }
539
540 dtop_param(tp, line)
541 struct tty *tp;
542 {
543 if (tp->t_ispeed == 0)
544 ttymodem(tp, 0);
545 else
546 /* called too early to invoke ttymodem, sigh */
547 tp->t_state |= TS_CARR_ON;
548 }
549
550 /*
551 * Modem control functions, we don't need 'em
552 */
553 dtop_mctl(dev, bits, how)
554 int dev;
555 int bits, how;
556 {
557 return 0;
558 }
559
560 dtop_softCAR(unit, line, on)
561 {
562 }
563
564 /* Some keyboard specific stuff, probably belongs elsewhere */
565
566 dtop_kbd_probe(unit)
567 {
568 if (dtop_std[unit]) {
569 lk201_probe(unit);
570 return 1;
571 }
572 return 0;
573 }
574
575 io_return_t
576 dtop_set_status(unit, flavor, status, status_count)
577 int unit;
578 int flavor;
579 dev_status_t status;
580 unsigned int status_count;
581 {
582 dtop_device_t dev;
583
584 dev = &dtop_softc[unit]->device[DTOP_DEVICE_NO(0x6c)].status;
585
586 switch (flavor) {
587 case LK201_SEND_CMD: {
588 register lk201_cmd_t *cmd = (lk201_cmd_t *)status;
589 unsigned int cnt;
590
591 if ((status_count < (sizeof(*cmd)/sizeof(int))) ||
592 ((cnt = cmd->len) > 2))
593 return D_INVALID_SIZE;
594 switch (cmd->command) {
595 case LK_CMD_ENB_BELL:
596 cmd->params[0] ^= 0x7;
597 if (dtop_print_debug)
598 printf("LK_CMD_ENB_BELL %d\n", cmd->params[0]);
599 dev->keyboard.bell_volume = cmd->params[0] & 0x7;
600 break;
601 case LK_CMD_DIS_BELL:
602 dev->keyboard.bell_volume = 0;
603 break;
604 case LK_CMD_BELL:
605 dtop_ring_bell(unit);
606 break;
607 case LK_CMD_LEDS_ON:
608 cmd->params[0] &= ~0x80;
609 if (dtop_print_debug)
610 printf("LK_CMD_LEDS_ON %d %x\n",
611 cmd->params[0], cmd->params[0]);
612 dev->keyboard.led_status |= cmd->params[0];
613 dtop_leds(unit, dev->keyboard.led_status);
614 break;
615 case LK_CMD_LEDS_OFF:
616 cmd->params[0] &= ~0x80;
617 dev->keyboard.led_status &= ~cmd->params[0];
618 dtop_leds(unit, dev->keyboard.led_status);
619 break;
620 case LK_CMD_ENB_KEYCLK:
621 case LK_CMD_DIS_KEYCLK:
622 case LK_CMD_SOUND_CLK:
623 case LK_CMD_DIS_CTLCLK:
624 case LK_CMD_ENB_CTLCLK:
625 break;
626 default:
627 break;
628 }
629 break;
630 }
631 default:
632 break;
633 }
634 return lk201_set_status(unit, flavor, status, status_count);
635 }
636
637 dtop_kbd_reset(unit)
638 {
639 return lk201_reset(unit);
640 }
641
642 #define DTOP_BITS(p, len) (((p) << 7) | (len))
643
644 dtop_ring_bell(unit)
645 {
646 dtop_message msg;
647 dtop_device_t dev;
648 int vol;
649
650 dev = &dtop_softc[unit]->device[DTOP_DEVICE_NO(0x6c)].status;
651 vol = dev->keyboard.bell_volume;
652
653 if (dtop_print_debug)
654 printf("dtop_ring_bell: %d\n", vol);
655 msg.dest_address = DTOP_ADDR_KBD;
656 msg.code.bits = DTOP_BITS(1, 2);
657 msg.body[0] = DTOP_KMSG_BELL;
658 msg.body[1] = vol;
659 if (!dtop_put_packet(dtop_softc[unit], &msg)) {
660 if (dtop_print_debug)
661 printf("dtop_ring_bell: dtop_put_packet failed\n");
662 return -1;
663 }
664 return 0;
665 }
666
667 dtop_leds(unit, mask)
668 {
669 dtop_message msg;
670
671 if (dtop_print_debug)
672 printf("dtop_leds %x\n", mask);
673 msg.dest_address = DTOP_ADDR_KBD;
674 msg.code.bits = DTOP_BITS(1, 2);
675 msg.body[0] = DTOP_KMSG_LED;
676 msg.body[1] = mask;
677 if (!dtop_put_packet(dtop_softc[unit], &msg)) {
678 if (dtop_print_debug)
679 printf("dtop_leds: dtop_put_packet failed\n");
680 return -1;
681 }
682 return 0;
683 }
684
685
686
687 #endif NDTOP > 0
Cache object: 8bc22fde7e38988d79047b8684352412
|