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