|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990,1989 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: dz_hdw.c
28: * Author: Alessandro Forin, Carnegie Mellon University
29: * Date: 9/90
30: *
31: * Hardware-level operations for the DZ Serial Line Driver
32: */
33:
34: #include <dz_.h>
35: #if NDZ_ > 0
36: #include <bm.h>
37: #include <platforms.h>
38:
39: #include <mach_kdb.h>
40:
41: #include <machine/machspl.h> /* spl definitions */
42: #include <device/io_req.h>
43: #include <device/tty.h>
44:
45: #include <chips/busses.h>
46: #include <chips/screen_defs.h>
47: #include <chips/serial_defs.h>
48:
49: #include <chips/dz_7085.h>
50:
51:
52: #ifdef DECSTATION
53: #include <mips/mips_cpu.h>
54: #include <mips/PMAX/kn01.h>
55: #define DZ_REGS_DEFAULT (vm_offset_t)PHYS_TO_K1SEG(KN01_SYS_DZ)
56: #define PAD(n) char n[6];
57: #endif /*DECSTATION*/
58:
59: #ifdef VAXSTATION
60: #define DZ_REGS_DEFAULT 0
61: #define wbflush()
62: #define check_memory(addr,dow) ((dow) ? wbadaddr(addr,4) : badaddr(addr,4))
63: #define PAD(n) char n[2];
64: #endif /*VAXSTATION*/
65:
66: #ifndef PAD
67: #define PAD(n)
68: #endif
69:
70: typedef struct {
71: volatile unsigned short dz_csr; /* Control and Status */
72: PAD(pad0)
73: volatile unsigned short dz_rbuf; /* Rcv buffer (RONLY) */
74: PAD(pad1)
75: volatile unsigned short dz_tcr; /* Xmt control (R/W)*/
76: PAD(pad2)
77: volatile unsigned short dz_tbuf; /* Xmt buffer (WONLY)*/
78: # define dz_lpr dz_rbuf /* Line parameters (WONLY)*/
79: # define dz_msr dz_tbuf /* Modem status (RONLY)*/
80: PAD(pad3)
81: } dz_padded_regmap_t;
82:
83:
84: /* this is ok both for rcv (char) and xmt (csr) */
85: #define LINEOF(x) (((x) >> 8) & 0x3)
86:
87: /*
88: * Driver status
89: */
90: struct dz7085_softc {
91: dz_padded_regmap_t *regs;
92: unsigned short breaks;
93: unsigned short fake; /* missing rs232 bits */
94: int polling_mode;
95: unsigned short prev_msr;
96: char softCAR;
97: } dz7085_softc_data[NDZ_];
98:
99: typedef struct dz7085_softc *dz7085_softc_t;
100:
101: dz7085_softc_t dz7085_softc[NDZ_];
102:
103: static void check_car();
104: static void check_ring();
105:
106: dz7085_softCAR(unit, line, on)
107: {
108: if (on)
109: dz7085_softc[unit]->softCAR |= 1<<line;
110: else
111: dz7085_softc[unit]->softCAR &= ~(1 << line);
112: }
113:
114: static
115: short dz7085_speeds[] =
116: { 0, DZ_LPAR_50, DZ_LPAR_75, DZ_LPAR_110, DZ_LPAR_134_5, DZ_LPAR_150,
117: 0, DZ_LPAR_300, DZ_LPAR_600, DZ_LPAR_1200, DZ_LPAR_1800, DZ_LPAR_2400,
118: DZ_LPAR_4800, DZ_LPAR_9600, DZ_LPAR_MAX_SPEED, 0 };
119:
120:
121: /*
122: * Definition of the driver for the auto-configuration program.
123: */
124:
125: int dz7085_probe(), dz7085_intr();
126: static void dz7085_attach();
127:
128: vm_offset_t dz7085_std[NDZ_] = { DZ_REGS_DEFAULT, };
129: struct bus_device *dz7085_info[NDZ_];
130: struct bus_driver dz_driver =
131: { dz7085_probe, 0, dz7085_attach, 0, dz7085_std, "dz", dz7085_info,};
132:
133: /*
134: * Adapt/Probe/Attach functions
135: */
136:
137: static boolean_t dz7085_full_modem = FALSE;
138: boolean_t dz7085_uses_modem_control = FALSE;/* patch this with adb */
139:
140: set_dz_address( unit, regs, has_modem)
141: vm_offset_t regs;
142: boolean_t has_modem;
143: {
144: extern int dz7085_probe(), dz7085_param(), dz7085_start(),
145: dz7085_putc(), dz7085_getc(),
146: dz7085_pollc(), dz7085_mctl(), dz7085_softCAR();
147:
148: dz7085_std[unit] = regs;
149: dz7085_full_modem = has_modem & dz7085_uses_modem_control;
150:
151: /* Do this here */
152: console_probe = dz7085_probe;
153: console_param = dz7085_param;
154: console_start = dz7085_start;
155: console_putc = dz7085_putc;
156: console_getc = dz7085_getc;
157: console_pollc = dz7085_pollc;
158: console_mctl = dz7085_mctl;
159: console_softCAR = dz7085_softCAR;
160:
161: }
162:
163: dz7085_probe( xxx, ui)
164: struct bus_device *ui;
165: {
166: int unit = ui->unit;
167: dz7085_softc_t sc;
168: register int cntr;
169: register dz_padded_regmap_t *regs;
170:
171: static int probed_once = 0;
172:
173: regs = (dz_padded_regmap_t *)dz7085_std[unit]; /* like the old days! */
174: if (regs == 0)
175: return 0;
176: /*
177: * If this is not there we are toast
178: */
179: if (check_memory(regs, 0))
180: return 0;
181:
182: if (probed_once++)
183: return 1;
184:
185: sc = &dz7085_softc_data[unit];
186: dz7085_softc[unit] = sc;
187: sc->regs = regs;
188:
189: for (cntr = unit*NDZ_LINE; cntr < NDZ_LINE*(unit+1); cntr++) {
190: console_tty[cntr]->t_addr = (char*)regs;
191: console_tty[cntr]->t_state |= TS_MIN;
192: }
193:
194: /* pmaxen et al. lack many modem bits */
195: dz7085_set_modem_control(sc, dz7085_full_modem);
196:
197: regs->dz_tcr = 0;/* disable all lines, drop RTS,DTR */
198: return 1;
199: }
200:
201: boolean_t dz7085_timer_started = FALSE;
202:
203: static void
204: dz7085_attach(ui)
205: register struct bus_device *ui;
206: {
207: int unit = ui->unit;
208: extern dz7085_scan();
209: extern int tty_inq_size;
210: int i;
211:
212: /* We only have 4 ttys, but always at 9600
213: * Give em a lot of room
214: */
215: tty_inq_size = 2048;
216: for (i = 0; i < (NDZ_*NDZ_LINE); i++)
217: ttychars(console_tty[i]);
218:
219: if (!dz7085_timer_started) {
220: dz7085_timer_started = TRUE;
221: dz7085_scan();
222: }
223:
224: #if NBM > 0
225: if (SCREEN_ISA_CONSOLE()) {
226: printf("\n sl0: "); lk201_attach(0, unit);
227: printf("\n sl1: "); mouse_attach(0, unit);
228: printf("\n sl2: \n sl3: ");
229: if (rcline == 3) printf("( rconsole )");
230: } else {
231: #endif /*NBM > 0*/
232: printf("\n sl0:\n sl1:\n sl2:\n sl3: ( alternate console )");
233: #if NBM > 0
234: }
235: #endif
236: }
237:
238: /*
239: * Would you like to make a phone call ?
240: */
241: dz7085_set_modem_control(sc, on)
242: dz7085_softc_t sc;
243: boolean_t on;
244: {
245: if (on)
246: /* your problem if the hardware then is broke */
247: sc->fake = 0;
248: else
249: sc->fake = DZ_MSR_CTS3|DZ_MSR_DSR3|DZ_MSR_CD3|
250: DZ_MSR_CTS2|DZ_MSR_CD2;
251: }
252:
253: /*
254: * Polled I/O (debugger)
255: */
256: dz7085_pollc(unit, on)
257: boolean_t on;
258: {
259: dz7085_softc_t sc = dz7085_softc[unit];
260:
261: if (on) {
262: sc->polling_mode++;
263: #if NBM > 0
264: screen_on_off(unit, TRUE);
265: #endif NBM > 0
266: } else
267: sc->polling_mode--;
268: }
269:
270: /*
271: * Interrupt routine
272: */
273: dz_intr(unit,spllevel)
274: spl_t spllevel;
275: {
276: dz7085_softc_t sc = dz7085_softc[unit];
277: register dz_padded_regmap_t *regs = sc->regs;
278: register short csr;
279:
280: csr = regs->dz_csr;
281:
282: if (csr & DZ_CSR_TRDY) {
283: register int c;
284:
285: c = cons_simple_tint(unit*NDZ_LINE + LINEOF(csr), FALSE);
286: if (c == -1) {
287: /* no more data for this line */
288: regs->dz_tcr &= ~(1 << LINEOF(csr));
289: c = cons_simple_tint(unit*NDZ_LINE + LINEOF(csr), TRUE);
290: /* because funny race possible ifnot */
291: }
292: if (c != -1) {
293: regs->dz_tbuf = (c & 0xff) | sc->breaks;
294: /* and leave it enabled */
295: }
296: }
297: if (sc->polling_mode)
298: return;
299:
300: while (regs->dz_csr & DZ_CSR_RDONE) {
301: short c = regs->dz_rbuf;
302: spl_t oldspl;
303:
304: #ifdef DECSTATION
305: oldspl = splhigh();
306: splx(spllevel);
307: #endif /*DECSTATION*/
308: cons_simple_rint(unit*NDZ_LINE+LINEOF(c), LINEOF(c),
309: c&0xff, c&0xff00);
310: #ifdef DECSTATION
311: splx(oldspl);
312: #endif /*DECSTATION*/
313: }
314: }
315:
316: /*
317: * Start transmission on a line
318: */
319: dz7085_start(tp)
320: struct tty *tp;
321: {
322: register dz_padded_regmap_t *regs;
323: register int line;
324:
325: line = tp->t_dev;
326:
327: regs = (dz_padded_regmap_t*)tp->t_addr;
328: regs->dz_tcr |= (1<<(line&3));
329:
330: /* no, we do not need a char out to interrupt */
331: }
332:
333: /*
334: * Get a char from a specific DZ line
335: */
336: dz7085_getc( unit, line, wait, raw )
337: boolean_t wait;
338: boolean_t raw;
339: {
340: dz7085_softc_t sc = dz7085_softc[unit];
341: spl_t s = spltty();
342: register dz_padded_regmap_t *regs = sc->regs;
343: unsigned short c;
344: int rl;
345:
346: again:
347: /*
348: * wait till something in silo
349: */
350: while ((regs->dz_csr & DZ_CSR_RDONE) == 0 && wait)
351: delay(10);
352: c = regs->dz_rbuf;
353:
354: /*
355: * check if right line. For keyboard, rconsole is ok too
356: */
357: rl = LINEOF(c);
358: if (wait && (line != rl) &&
359: !((line == DZ_LINE_KEYBOARD) && rcline == rl))
360: goto again;
361: /*
362: * bad chars not ok
363: */
364: if ((c & (DZ_RBUF_PERR | DZ_RBUF_OERR | DZ_RBUF_FERR)) && wait)
365: goto again;
366:
367: splx(s);
368:
369: /*
370: * if nothing found return -1
371: */
372: if ( ! (c & DZ_RBUF_VALID))
373: return -1;
374:
375: #if NBM > 0
376: if ((rl == DZ_LINE_KEYBOARD) && !raw && SCREEN_ISA_CONSOLE())
377: return lk201_rint(SCREEN_CONS_UNIT(), c, wait, sc->polling_mode);
378: else
379: #endif NBM > 0
380: return c & DZ_RBUF_CHAR;
381: }
382:
383: /*
384: * Put a char on a specific DZ line
385: */
386: dz7085_putc( unit, line, c )
387: {
388: dz7085_softc_t sc = dz7085_softc[unit];
389: register dz_padded_regmap_t *regs = sc->regs;
390: spl_t s = spltty();
391:
392: /*
393: * do not change the break status of other lines
394: */
395: c = (c & 0xff) | sc->breaks;
396:
397: /*
398: * Xmit line info only valid if TRDY,
399: * but never TRDY if no xmit enabled
400: */
401: if ((regs->dz_tcr & DZ_TCR_LNENB) == 0)
402: goto select_it;
403:
404: while ((regs->dz_csr & DZ_CSR_TRDY) == 0)
405: delay(100);
406:
407: /*
408: * see if by any chance we are already on the right line
409: */
410: if (LINEOF(regs->dz_csr) == line)
411: regs->dz_tbuf = c;
412: else {
413: unsigned short tcr;
414: select_it:
415: tcr = regs->dz_tcr;
416: regs->dz_tcr = (1 << line) | (tcr & 0xff00);
417: wbflush();
418:
419: do
420: delay(2);
421: while ((regs->dz_csr & DZ_CSR_TRDY) == 0 ||
422: (LINEOF(regs->dz_csr) != line));
423:
424: regs->dz_tbuf = c;
425: wbflush();
426:
427: /* restore previous settings */
428: regs->dz_tcr = tcr;
429: }
430:
431: splx(s);
432: }
433:
434:
435: dz7085_param(tp, line)
436: register struct tty *tp;
437: register int line;
438: {
439: register dz_padded_regmap_t *regs;
440: register int lpr;
441:
442: line = tp->t_dev;
443: regs = dz7085_softc[line/NDZ_LINE]->regs;
444:
445: /*
446: * Do not let user fool around with kbd&mouse
447: */
448: #if NBM > 0
449: if (screen_captures(line)) {
450: tp->t_ispeed = tp->t_ospeed = B4800;
451: tp->t_flags |= TF_LITOUT;
452: }
453: #endif NBM > 0
454: regs->dz_csr = DZ_CSR_MSE|DZ_CSR_RIE|DZ_CSR_TIE;
455: if (tp->t_ispeed == 0) {
456: (void) (*console_mctl)(tp->t_dev, TM_HUP, DMSET); /* hang up line */
457: return;
458: }
459: /* 19200/38400 here */
460: lpr = dz7085_speeds[tp->t_ispeed] | (line&DZ_LPAR_LINE) | DZ_LPAR_ENABLE;
461: lpr |= DZ_LPAR_8BITS;
462:
463: if ((tp->t_flags & (TF_ODDP|TF_EVENP)) == TF_ODDP)
464: lpr |= DZ_LPAR_ODD_PAR;
465:
466: if (tp->t_ispeed == B110)
467: lpr |= DZ_LPAR_STOP;
468: regs->dz_lpr = lpr;
469: }
470:
471: /*
472: * This is a total mess: not only are bits spread out in
473: * various registers, but we have to fake some for pmaxen.
474: */
475: dz7085_mctl(dev, bits, how)
476: int dev;
477: int bits, how;
478: {
479: register dz_padded_regmap_t *regs;
480: register int unit;
481: register int tcr, msr, brk, n_tcr, n_brk;
482: int b;
483: spl_t s;
484: dz7085_softc_t sc;
485:
486: unit = dev;
487:
488: /* no modem support on lines 0 & 1 */
489: /* XXX break on 0&1 */
490: if ((unit & 2) == 0)
491: return TM_LE|TM_DTR|TM_CTS|TM_CAR|TM_DSR;
492:
493: b = 1 ^ (unit & 1); /* line 2 ? */
494:
495: sc = dz7085_softc[unit>>2];
496: regs = sc->regs;
497: s = spltty();
498:
499: tcr = ((regs->dz_tcr | (sc->fake>>4)) & 0xf00) >> (8 + b*2);
500: brk = (sc->breaks >> (8 + (unit&3))) & 1; /* THE break bit */
501:
502: n_tcr = (bits & (TM_RTS|TM_DTR)) >> 1;
503: n_brk = (bits & TM_BRK) >> 9;
504:
505: /* break transitions, must 'send' a char out */
506: bits = (brk ^ n_brk) & 1;
507:
508: switch (how) {
509: case DMSET:
510: tcr = n_tcr;
511: brk = n_brk;
512: break;
513:
514: case DMBIS:
515: tcr |= n_tcr;
516: brk |= n_brk;
517: break;
518:
519: case DMBIC:
520: tcr &= ~n_tcr;
521: brk = 0;
522: break;
523:
524: case DMGET:
525: msr = ((regs->dz_msr|sc->fake) & 0xf0f) >> (b*8);
526: (void) splx(s);
527: return (tcr<<1)|/* DTR, RTS */
528: ((msr&1)<<5)|/* CTS */
529: ((msr&2)<<7)|/* DSR */
530: ((msr&0xc)<<4)|/* CD, RNG */
531: (brk << 9)|/* BRK */
532: TM_LE;
533: }
534: n_tcr = (regs->dz_tcr & ~(3 << (8 + b*2))) |
535: (tcr << (8 + b*2));
536:
537: regs->dz_tcr = n_tcr;
538: sc->fake = (sc->fake & 0xf0f) | (n_tcr<<4&0xf000);
539:
540: sc->breaks = (sc->breaks & ~(1 << (8 + (unit&3)))) |
541: (brk << (8 + (unit&3)));
542: if(bits) (*console_putc)( unit>>2, unit&3, 0);/* force break, now */
543: (void) splx(s);
544: return 0;/* useless to compute it */
545: }
546:
547: /*
548: * Periodically look at the CD signals:
549: * they do not generate interrupts.
550: */
551: dz7085_scan()
552: {
553: register i;
554: register dz_padded_regmap_t *regs;
555: register msr;
556: register struct tty *tp;
557:
558: for (i = 0; i < NDZ_; i++) {
559: dz7085_softc_t sc = dz7085_softc[i];
560: register int temp;
561:
562: if (sc == 0)
563: continue;
564: regs = sc->regs;
565:
566: tp = console_tty[i * NDZ_LINE];
567:
568: msr = regs->dz_msr | (sc->fake & 0xf0f);
569: if (temp = sc->softCAR) {
570: if (temp & 0x4)
571: msr |= DZ_MSR_CD2 | DZ_MSR_CTS2;
572: if (temp & 0x8)
573: msr |= DZ_MSR_CD3 | DZ_MSR_CTS3;
574: }
575:
576: /* Lines 0 and 1 have carrier on by definition */
577: /* [horrid casts cuz compiler stupid] */
578: check_car((char*)tp + 0*sizeof(struct tty), 1);
579: check_car((char*)tp + 1*sizeof(struct tty), 1);
580: check_car((char*)tp + 2*sizeof(struct tty), msr & DZ_MSR_CD2);
581: check_car((char*)tp + 3*sizeof(struct tty), msr & DZ_MSR_CD3);
582:
583: /* nothing else to do if no msr transitions */
584: if ((temp = sc->prev_msr) == msr)
585: continue;
586: else
587: sc->prev_msr = msr;
588:
589: /* see if we have an incoming call */
590: #define RING (DZ_MSR_RI2|DZ_MSR_RI3)
591: if ((msr & RING) != (temp & RING)) {
592: /*printf("%s %x->%x\n", "ET Phone RI", temp & RING, msr & RING);*/
593: check_ring((char*)tp + 2*sizeof(struct tty),
594: msr & DZ_MSR_RI2, temp & DZ_MSR_RI2);
595: check_ring((char*)tp + 3*sizeof(struct tty),
596: msr & DZ_MSR_RI3, temp & DZ_MSR_RI3);
597: }
598: #undef RING
599: /* see if we must do flow-control */
600: if ((msr ^ temp) & DZ_MSR_CTS2) {
601: tty_cts((char*)tp + 2*sizeof(struct tty),
602: msr & DZ_MSR_CTS2);
603: }
604: if ((msr ^ temp) & DZ_MSR_CTS3) {
605: tty_cts((char*)tp + 3*sizeof(struct tty),
606: msr & DZ_MSR_CTS3);
607: }
608: }
609: timeout(dz7085_scan, (vm_offset_t)0, 2*hz);
610: }
611:
612: static dz7085_hup(tp)
613: register struct tty *tp;
614: {
615: (*console_mctl)(tp->t_dev, TM_DTR, DMBIC);
616: }
617:
618: static void check_car(tp, car)
619: register struct tty *tp;
620: {
621: if (car) {
622: /* cancel modem timeout if need to */
623: if (car & (DZ_MSR_CD2|DZ_MSR_CD3))
624: untimeout(dz7085_hup, (vm_offset_t)tp);
625:
626: /* I think this belongs in the MI code */
627: if (tp->t_state & TS_WOPEN)
628: tp->t_state |= TS_ISOPEN;
629: /* carrier present */
630: if ((tp->t_state & TS_CARR_ON) == 0)
631: (void)ttymodem(tp, 1);
632: } else if ((tp->t_state&TS_CARR_ON) && ttymodem(tp, 0) == 0)
633: (*console_mctl)( tp->t_dev, TM_DTR, DMBIC);
634: }
635:
636: int dz7085_ring_timeout = 60; /* seconds, patchable */
637:
638: static void check_ring(tp, ring, oring)
639: register struct tty *tp;
640: {
641: if (ring == oring)
642: return;
643: if (ring) {
644: (*console_mctl)( tp->t_dev, TM_DTR, DMBIS);
645: /* give it ample time to find the right carrier */
646: timeout(dz7085_hup, (vm_offset_t)tp, dz7085_ring_timeout*hz);
647: }
648: }
649: #endif NDZ_ > 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.