1 /*
2 * Mach Operating System
3 * Copyright (c) 1993-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 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: scc_8530_hdw.c,v $
29 * Revision 2.15 93/11/17 16:13:30 dbg
30 * Import kern/time_out.h for 'hz'.
31 * [93/06/11 dbg]
32 *
33 * Revision 2.14 93/08/05 16:50:01 mrt
34 * Quick workaround for bad cabling on Flamingo. Tzk tzk...
35 * [93/08/05 af]
36 *
37 * Revision 2.13 93/05/30 21:07:25 rvb
38 * Handle CTS transitions, for modem CTS/RTS flow control.
39 * [93/05/29 09:45:48 af]
40 *
41 * Revision 2.12 93/05/20 19:32:56 rvb
42 * Added first (working) cut at true modem support, but I have
43 * a bad cable and needs finessing.
44 * Also, 3max+ support, from John Wroclawski (jtw@lcs.mit.edu).
45 * [93/05/08 af]
46 *
47 * Revision 2.11 93/05/17 17:10:46 rvb
48 * include machparam.h -> machspl.h
49 *
50 * Revision 2.10 93/05/10 20:08:37 rvb
51 * Fixed types.
52 * [93/05/06 10:01:41 af]
53 *
54 * Revision 2.9 93/03/26 17:58:01 mrt
55 * No minor()s, no dev_t.
56 * [93/03/18 af]
57 *
58 * Revision 2.8 93/03/09 10:52:21 danner
59 * GCC quiet.
60 * [93/03/07 13:29:58 af]
61 *
62 * Post-debugging lint.
63 * [93/03/05 af]
64 *
65 * Revision 2.7 93/02/05 08:05:17 danner
66 * Flamingo, full_modem and isa_console per-line.
67 * [93/02/04 af]
68 *
69 * Revision 2.6 93/01/14 17:21:44 danner
70 * static/extern cleanups.
71 * [93/01/14 danner]
72 *
73 * Proper spl typing.
74 * [92/11/30 af]
75 *
76 * Revision 2.5 92/05/05 10:04:59 danner
77 * Fixed how the interrupt routine plays with priorities.
78 * Ask for buffering on all lines.
79 * [92/05/04 11:15:43 af]
80 *
81 * Fixed for more than just rconsole-ing. Two bugs: the chip
82 * needs one char out to generate the xmit-empty (so it really
83 * is a xmit-done) interrupt, and the t_addr game was not played
84 * properly.
85 * Tested both on maxine and the two serial lines kmin has.
86 * [92/04/14 11:47:26 af]
87 *
88 * Revision 2.4 92/02/19 16:46:10 elf
89 * Uhmm, lotsa changes. Basically, got channel B working
90 * and made it possible to use it as rconsole line.
91 * Missing modem bitsies only.
92 * A joint Terri&Sandro feature presentation.
93 * [92/02/10 17:03:08 af]
94 *
95 * Revision 2.3 91/08/28 11:09:53 jsb
96 * Fixed scc_scan to actually check the tp->state each time,
97 * we are not notified when the MI code brutally zeroes it
98 * on close and so we cannot update our software CARrier.
99 * [91/08/27 16:18:05 af]
100 *
101 * Revision 2.2 91/08/24 11:52:54 af
102 * Created, from the Zilog specs:
103 * "Z8530 SCC Serial Communications Controller, Product Specification"
104 * in the "1983/84 Components Data Book" pp 409-429, September 1983
105 * Zilog, Campbell, CA 95008
106 * [91/06/28 af]
107 *
108 */
109 /*
110 * File: scc_8530_hdw.c
111 * Author: Alessandro Forin, Carnegie Mellon University
112 * Date: 6/91
113 *
114 * Hardware-level operations for the SCC Serial Line Driver
115 */
116
117 #include <scc.h>
118 #if NSCC > 0
119 #include <bm.h>
120 #include <platforms.h>
121
122 #include <mach_kdb.h>
123
124 #include <machine/machspl.h> /* spl definitions */
125 #include <mach/std_types.h>
126 #include <kern/time_out.h> /* hz */
127 #include <device/io_req.h>
128 #include <device/tty.h>
129
130 #include <chips/busses.h>
131 #include <chips/serial_defs.h>
132 #include <chips/screen_defs.h>
133
134 /* Alignment and padding */
135 #if defined(DECSTATION)
136 /*
137 * 3min's padding
138 */
139 typedef struct {
140 char pad0;
141 volatile unsigned char datum;
142 char pad1[2];
143 } scc_padded1_register_t;
144
145 #define scc_register_t scc_padded1_register_t
146 #endif
147
148 #if defined(FLAMINGO)
149 typedef struct {
150 volatile unsigned int datum;
151 unsigned int pad1;
152 } scc_padded1_register_t;
153
154 #define scc_register_t scc_padded1_register_t
155
156 #define scc_set_datum(d,v) (d) = (volatile unsigned int) (v) << 8, wbflush()
157 #define scc_get_datum(d,v) (v) = ((d) >> 8) & 0xff
158
159 #endif
160
161 #include <chips/scc_8530.h> /* needs the above defs */
162
163 #define private static
164 #define public
165
166 /*
167 * Forward decls
168 */
169 private void check_car( struct tty *, boolean_t );
170
171 /*
172 * On the 3min keyboard and mouse come in on channels A
173 * of the two units. The MI code expects them at 'lines'
174 * 0 and 1, respectively. So we map here back and forth.
175 * Note also the MI code believes unit 0 has four lines.
176 */
177
178 #define SCC_KBDUNIT 1
179 #define SCC_PTRUNIT 0
180
181 void mi_to_scc(
182 int *unitp,
183 int *linep)
184 {
185 /* only play games on MI 'unit' 0 */
186 if (*unitp) {
187 /* e.g. by mapping the first four lines specially */
188 *unitp++;
189 return;
190 }
191
192 /* always get unit=0 (console) and line = 0|1 */
193 if (*linep == SCREEN_LINE_KEYBOARD) {
194 *unitp = SCC_KBDUNIT;
195 *linep = SCC_CHANNEL_A;
196 } else if (*linep == SCREEN_LINE_POINTER) {
197 *unitp = SCC_PTRUNIT;
198 *linep = SCC_CHANNEL_A;
199 } else {
200 *unitp = (*linep & 1);
201 *linep = SCC_CHANNEL_B;
202 }
203 /* line 0 is channel B, line 1 is channel A */
204 }
205
206 #define NSCC_LINE 2 /* 2 ttys per chip */
207
208 /* only care for mapping to ttyno */
209 int scc_to_mi(
210 int sccunit,
211 int sccline)
212 {
213 if (sccunit > 1)
214 return (sccunit * NSCC_LINE + sccline);
215 /* only for console (first pair of SCCs): */
216 if (sccline == SCC_CHANNEL_A)
217 return ((!sccunit) & 1);
218 return 2+sccunit;
219 }
220
221
222 /*
223 * Driver status
224 */
225 struct scc_softc {
226 scc_regmap_t *regs;
227
228 /* software copy of some write regs, for reg |= */
229 struct softreg {
230 unsigned char wr1;
231 unsigned char wr4;
232 unsigned char wr5;
233 unsigned char wr14;
234 } softr[2]; /* per channel */
235
236 unsigned char last_rr0[2]; /* for modem signals */
237 unsigned short fake; /* missing rs232 bits, channel A */
238 char polling_mode;
239 char softCAR, osoftCAR;
240 char probed_once;
241
242 boolean_t full_modem;
243 boolean_t isa_console;
244
245 } scc_softc_data[NSCC];
246
247 typedef struct scc_softc *scc_softc_t;
248
249 scc_softc_t scc_softc[NSCC];
250
251 void scc_softCAR(
252 int unit,
253 int line,
254 int on)
255 {
256 mi_to_scc(&unit, &line);
257 if (on)
258 scc_softc[unit]->softCAR |= 1<<line;
259 else
260 scc_softc[unit]->softCAR &= ~(1 << line);
261 }
262
263
264 /*
265 * BRG formula is:
266 * ClockFrequency
267 * BRGconstant = --------------------------- - 2
268 * 2 * BaudRate * ClockDivider
269 */
270 /* Speed selections with Pclk=7.3728Mhz, clock x16 */
271 static
272 short scc_speeds[] =
273 /* 0 50 75 110 134.5 150 200 300 600 1200 1800 2400 */
274 { 0, 4606, 3070, 2093, 1711, 1534, 1150, 766, 382, 190, 126, 94,
275
276 /* 4800 9600 19.2k 38.4k */
277 46, 22, 10, 4};
278
279 /*
280 * Definition of the driver for the auto-configuration program.
281 */
282
283 boolean_t scc_probe(
284 vm_offset_t address,
285 struct bus_device *ui);
286
287 static void
288 scc_attach(
289 register struct bus_device *ui);
290
291 vm_offset_t scc_std[NSCC] = { 0 };
292 struct bus_device *scc_info[NSCC];
293 struct bus_driver scc_driver =
294 { scc_probe, 0, scc_attach, 0, scc_std, "scc", scc_info,};
295
296 /*
297 * Adapt/Probe/Attach functions
298 */
299 boolean_t scc_uses_modem_control = FALSE;/* patch this with adb */
300
301 void scc_param(
302 struct tty *tp,
303 int line); /* forward */
304 void scc_start(
305 struct tty *tp);
306
307 void scc_putc(
308 int unit,
309 int line,
310 int c);
311
312 int scc_getc(
313 int unit,
314 int line,
315 boolean_t wait,
316 boolean_t raw);
317
318 void scc_pollc(
319 int unit,
320 boolean_t on);
321
322 int scc_mctl(
323 int dev,
324 int bits,
325 int how);
326
327 void scc_set_modem_control(
328 scc_softc_t scc,
329 boolean_t on);
330
331 void scc_modem_intr(
332 scc_softc_t scc,
333 int chan,
334 int unit);
335
336 /*
337 * Set up console to point to SCC.
338 */
339 void set_scc_address(
340 int sccunit,
341 vm_offset_t regs,
342 boolean_t has_modem,
343 boolean_t isa_console)
344 {
345 scc_std[sccunit] = regs;
346 scc_softc_data[sccunit].full_modem = has_modem & scc_uses_modem_control;
347 scc_softc_data[sccunit].isa_console = isa_console;
348
349 /* Do this here */
350 console_probe = scc_probe;
351 console_param = scc_param;
352 console_start = scc_start;
353 console_putc = scc_putc;
354 console_getc = scc_getc;
355 console_pollc = scc_pollc;
356 console_mctl = scc_mctl;
357 console_softCAR = scc_softCAR;
358
359 }
360
361 boolean_t scc_probe(
362 vm_offset_t address,
363 struct bus_device *ui)
364 {
365 int sccunit = ui->unit;
366 scc_softc_t scc;
367 register int val;
368 register scc_regmap_t *regs;
369
370 regs = (scc_regmap_t *)scc_std[sccunit];
371 if (regs == 0)
372 return 0;
373
374 /*
375 * See if we are here
376 */
377 if (check_memory(regs, 0)) {
378 /* no rides today */
379 return 0;
380 }
381
382 scc = &scc_softc_data[sccunit];
383
384 if (scc->probed_once++){
385 return 1;
386 }
387 /*
388 * Chip once-only initialization
389 *
390 * NOTE: The wiring we assume is the one on the 3min:
391 *
392 * out A-TxD --> TxD keybd or mouse
393 * in A-RxD --> RxD keybd or mouse
394 * out A-DTR~ --> DTR comm
395 * out A-RTS~ --> RTS comm
396 * in A-CTS~ --> SI comm
397 * in A-DCD~ --> RI comm
398 * in A-SYNCH~--> DSR comm
399 * out B-TxD --> TxD comm
400 * in B-RxD --> RxD comm
401 * in B-RxC --> TRxCB comm
402 * in B-TxC --> RTxCB comm
403 * out B-RTS~ --> SS comm
404 * in B-CTS~ --> CTS comm
405 * in B-DCD~ --> CD comm
406 */
407
408 scc_softc[sccunit] = scc;
409 scc->regs = regs;
410
411 scc->fake = 1<<SCC_CHANNEL_A;
412
413 {
414 register int i;
415 /* We need this in scc_start only, hence the funny
416 value: we need it non-zero and we want to avoid
417 too much overhead in getting to (scc,regs,line) */
418 for (i = 0; i < NSCC_LINE; i++) {
419 register struct tty *tp;
420
421 tp = console_tty[scc_to_mi(sccunit,i)];
422 tp->t_addr = (char*)(0x80000000L + (sccunit<<1) + (i&1));
423 /* do min buffering */
424 tp->t_state |= TS_MIN;
425 }
426 }
427
428 /* make sure reg pointer is in known state */
429 scc_init_reg(regs, SCC_CHANNEL_A);
430 scc_init_reg(regs, SCC_CHANNEL_B);
431
432 /* reset chip, fully */
433 scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_HW_RESET);
434 delay(50000);/*enough ? */
435 scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR9, 0);
436
437 /* program the interrupt vector */
438 scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR2, 0xf0);
439 scc_write_reg(regs, SCC_CHANNEL_B, SCC_WR2, 0xf0);
440 scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_VIS);
441
442 /* most of the init is in scc_param() */
443
444 /* timing base defaults */
445 scc->softr[SCC_CHANNEL_A].wr4 = SCC_WR4_CLK_x16;
446 scc->softr[SCC_CHANNEL_B].wr4 = SCC_WR4_CLK_x16;
447
448 /* enable DTR, RTS and dont SS */
449 #if 0
450 /* According to one book I have this signal (pin 23, "SS")
451 is "specified by the provider", meaning the EIA-232-D
452 standard does not define what it is. Better leave
453 it alone */
454 scc->softr[SCC_CHANNEL_B].wr5 = SCC_WR5_RTS;
455 #else
456 scc->softr[SCC_CHANNEL_B].wr5 = 0;
457 #endif
458 scc->softr[SCC_CHANNEL_A].wr5 = SCC_WR5_RTS | SCC_WR5_DTR;
459
460 /* baud rates */
461 val = SCC_WR14_BAUDR_ENABLE|SCC_WR14_BAUDR_SRC;
462 scc->softr[SCC_CHANNEL_B].wr14 = val;
463 scc->softr[SCC_CHANNEL_A].wr14 = val;
464
465 /* interrupt conditions */
466 val = SCC_WR1_RXI_ALL_CHAR | SCC_WR1_PARITY_IE |
467 SCC_WR1_EXT_IE | SCC_WR1_TX_IE;
468 scc->softr[SCC_CHANNEL_A].wr1 = val;
469 scc->softr[SCC_CHANNEL_B].wr1 = val;
470
471 scc_read_reg_zero(regs, SCC_CHANNEL_A, scc->last_rr0[SCC_CHANNEL_A]);
472 scc_read_reg_zero(regs, SCC_CHANNEL_B, scc->last_rr0[SCC_CHANNEL_B]);
473
474 /*
475 * After probing, any line that should be active
476 * (keybd,mouse,rcline) is activated via scc_param().
477 */
478
479 scc_set_modem_control(scc, scc->full_modem);
480
481 #if defined(KMIN) || defined (FLAMINGO) || defined(KN03)
482 /*
483 * Crock: MI code knows of unit 0 as console, we need
484 * unit 1 as well since the keyboard is there
485 * This is acceptable on maxine, which has to call its
486 * only one chip unit 1 so that rconsole is happy.
487 */
488 if (sccunit == 0) {
489 struct bus_device d;
490 d = *ui;
491 d.unit = 1;
492 scc_probe(address, &d);
493 }
494 #endif
495 return 1;
496 }
497
498 boolean_t scc_timer_started = FALSE;
499
500 void scc_scan(void); /* forward */
501
502 static void
503 scc_attach(
504 register struct bus_device *ui)
505 {
506 int sccunit = ui->unit;
507 extern int tty_inq_size;
508 int i;
509
510 /* We only have 4 ttys, but always at 9600
511 * Give em a lot of room (plus dma..)
512 */
513 tty_inq_size = 4096;
514 if (!scc_timer_started) {
515 /* do all of them, before we call scc_scan() */
516 /* harmless if done already */
517 for (i = 0; i < NSCC*NSCC_LINE; i++)
518 ttychars(console_tty[i]);
519
520 scc_timer_started = TRUE;
521 scc_scan();
522 }
523
524 #if NBM > 0
525 if (SCREEN_ISA_CONSOLE() && scc_softc[sccunit]->isa_console) {
526 printf("\n sl0: ");
527 if (sccunit && rcline == 3) printf("( rconsole )");
528
529 if (sccunit == SCC_KBDUNIT) {
530 printf("\n sl1: "); lk201_attach(0, sccunit >> 1);
531 } else if (sccunit == SCC_PTRUNIT) {
532 printf("\n sl1: "); mouse_attach(0, sccunit >> 1);
533 }
534 } else
535 #endif /* NBM > 0 */
536 {
537 printf("%s", (sccunit == 1) ?
538 "\n sl0: ( alternate console )\n sl1:" :
539 "\n sl0:\n sl1:");
540 }
541 }
542
543 /*
544 * Would you like to make a phone call ?
545 */
546 void
547 scc_set_modem_control(
548 scc_softc_t scc,
549 boolean_t on)
550 {
551 if (on)
552 /* your problem if the hardware then is broke */
553 scc->fake = 0;
554 else
555 scc->fake = 3;
556 scc->full_modem = on;
557 /* user should do an scc_param() ifchanged */
558 }
559
560 /*
561 * Polled I/O (debugger)
562 */
563 void
564 scc_pollc(
565 int unit,
566 boolean_t on)
567 {
568 scc_softc_t scc;
569 int line = SCREEN_LINE_KEYBOARD,
570 sccunit = unit;
571
572 mi_to_scc(&sccunit, &line);
573
574 scc = scc_softc[sccunit];
575 if (on) {
576 scc->polling_mode++;
577 #if NBM > 0
578 screen_on_off(unit, TRUE);
579 #endif /* NBM > 0 */
580 } else
581 scc->polling_mode--;
582 }
583
584 /*
585 * Interrupt routine
586 */
587 int scc_intr_count;
588
589 void scc_intr(
590 int unit,
591 spl_t spllevel)
592 {
593 scc_softc_t scc = scc_softc[unit];
594 register scc_regmap_t *regs = scc->regs;
595 register int rr1, rr2;
596 register int c;
597
598 scc_intr_count++;
599
600 #if mips
601 splx(spllevel); /* lower priority */
602 #endif
603
604 while (1) {
605
606 scc_read_reg(regs, SCC_CHANNEL_B, SCC_RR2, rr2);
607
608 rr2 = SCC_RR2_STATUS(rr2);
609
610 /* are we done yet ? */
611 if (rr2 == 6) { /* strange, distinguished value */
612 register int rr3;
613 scc_read_reg(regs, SCC_CHANNEL_A, SCC_RR3, rr3);
614 if (rr3 == 0)
615 return;
616 }
617
618 if ((rr2 == SCC_RR2_A_XMIT_DONE) || (rr2 == SCC_RR2_B_XMIT_DONE)) {
619
620 register chan = (rr2 == SCC_RR2_A_XMIT_DONE) ?
621 SCC_CHANNEL_A : SCC_CHANNEL_B;
622
623 scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
624 c = cons_simple_tint(scc_to_mi(unit,chan), FALSE);
625
626 if (c == -1) {
627 /* no more data for this line */
628
629 scc_read_reg(regs, chan, SCC_RR15, c);
630 c &= ~SCC_WR15_TX_UNDERRUN_IE;
631 scc_write_reg(regs, chan, SCC_WR15, c);
632
633 c = scc->softr[chan].wr1 & ~SCC_WR1_TX_IE;
634 scc_write_reg(regs, chan, SCC_WR1, c);
635 scc->softr[chan].wr1 = c;
636
637 c = cons_simple_tint(scc_to_mi(unit,chan), TRUE);
638 if (c != -1)
639 /* funny race, scc_start has been called already */
640 scc_write_data(regs, chan, c);
641 } else {
642 scc_write_data(regs, chan, c);
643 /* and leave it enabled */
644 }
645 }
646
647 else if (rr2 == SCC_RR2_A_RECV_DONE) {
648
649 scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
650 if (scc->polling_mode)
651 continue;
652
653 scc_read_data(regs, SCC_CHANNEL_A, c);
654 rr1 = scc_to_mi(unit,SCC_CHANNEL_A);
655 cons_simple_rint (rr1, rr1, c, 0);
656 }
657
658 else if (rr2 == SCC_RR2_B_RECV_DONE) {
659
660 scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
661 if (scc->polling_mode)
662 continue;
663
664 scc_read_data(regs, SCC_CHANNEL_B, c);
665 rr1 = scc_to_mi(unit,SCC_CHANNEL_B);
666 cons_simple_rint (rr1, rr1, c, 0);
667 }
668
669 else if ((rr2 == SCC_RR2_A_EXT_STATUS) || (rr2 == SCC_RR2_B_EXT_STATUS)) {
670 int chan = (rr2 == SCC_RR2_A_EXT_STATUS) ?
671 SCC_CHANNEL_A : SCC_CHANNEL_B;
672 scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_EXT_IP);
673 scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
674 scc_modem_intr(scc, chan, unit);
675 }
676
677 else if ((rr2 == SCC_RR2_A_RECV_SPECIAL) || (rr2 == SCC_RR2_B_RECV_SPECIAL)) {
678 register int chan = (rr2 == SCC_RR2_A_RECV_SPECIAL) ?
679 SCC_CHANNEL_A : SCC_CHANNEL_B;
680
681 scc_read_reg(regs, chan, SCC_RR1, rr1);
682 if (rr1 & (SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN | SCC_RR1_FRAME_ERR)) {
683 int err;
684 /* map to CONS_ERR_xxx MI error codes */
685 err = ((rr1 & SCC_RR1_PARITY_ERR)<<8) |
686 ((rr1 & SCC_RR1_RX_OVERRUN)<<9) |
687 ((rr1 & SCC_RR1_FRAME_ERR)<<7);
688 scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_ERROR);
689 rr1 = scc_to_mi(unit,chan);
690 cons_simple_rint(rr1, rr1, 0, err);
691 }
692 scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
693 }
694
695 }
696
697 }
698
699 void
700 scc_start(
701 struct tty *tp)
702 {
703 register scc_regmap_t *regs;
704 register int chan, temp;
705 register struct softreg *sr;
706
707 temp = (natural_t)tp->t_addr;
708 chan = (temp & 1); /* channel */
709 temp = (temp >> 1)&0xff;/* sccunit */
710 regs = scc_softc[temp]->regs;
711 sr = &scc_softc[temp]->softr[chan];
712
713 scc_read_reg(regs, chan, SCC_RR15, temp);
714 temp |= SCC_WR15_TX_UNDERRUN_IE;
715 scc_write_reg(regs, chan, SCC_WR15, temp);
716
717 temp = sr->wr1 | SCC_WR1_TX_IE;
718 scc_write_reg(regs, chan, SCC_WR1, temp);
719 sr->wr1 = temp;
720
721 /* but we need a first char out or no cookie */
722 scc_read_reg(regs, chan, SCC_RR0, temp);
723 if (temp & SCC_RR0_TX_EMPTY)
724 {
725 register char c;
726
727 c = getc(&tp->t_outq);
728 scc_write_data(regs, chan, c);
729 }
730 }
731
732 /*
733 * Get a char from a specific SCC line
734 * [this is only used for console&screen purposes]
735 */
736 int scc_getc(
737 int unit,
738 int line,
739 boolean_t wait,
740 boolean_t raw)
741 {
742 scc_softc_t scc;
743 register scc_regmap_t *regs;
744 unsigned char c;
745 int value, mi_line, rcvalue, from_line;
746
747 mi_line = line;
748 mi_to_scc(&unit, &line);
749
750 scc = scc_softc[unit];
751 regs = scc->regs;
752
753 /*
754 * wait till something available
755 *
756 * NOTE: we know! that rcline==3
757 */
758 if (rcline) rcline = 3;
759 again:
760 rcvalue = 0;
761 while (1) {
762 scc_read_reg_zero(regs, line, value);
763 if (rcline && (mi_line == SCREEN_LINE_KEYBOARD)) {
764 scc_read_reg_zero(regs, SCC_CHANNEL_B, rcvalue);
765 value |= rcvalue;
766 }
767 if (((value & SCC_RR0_RX_AVAIL) == 0) && wait)
768 delay(10);
769 else
770 break;
771 }
772
773 /*
774 * if nothing found return -1
775 */
776 from_line = (rcvalue & SCC_RR0_RX_AVAIL) ? SCC_CHANNEL_B : line;
777
778 if (value & SCC_RR0_RX_AVAIL) {
779 scc_read_reg(regs, from_line, SCC_RR1, value);
780 scc_read_data(regs, from_line, c);
781 } else {
782 /* splx(s);*/
783 return -1;
784 }
785
786 /*
787 * bad chars not ok
788 */
789 if (value&(SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN | SCC_RR1_FRAME_ERR)) {
790 /* scc_state(unit,from_line); */
791 scc_write_reg(regs, from_line, SCC_RR0, SCC_RESET_ERROR);
792 if (wait) {
793 scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
794 goto again;
795 }
796 }
797 scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
798 /* splx(s);*/
799
800
801 #if NBM > 0
802 if ((mi_line == SCREEN_LINE_KEYBOARD) && (from_line == SCC_CHANNEL_A) &&
803 !raw && SCREEN_ISA_CONSOLE() && scc->isa_console)
804 return lk201_rint(SCREEN_CONS_UNIT(), c, wait, scc->polling_mode);
805 else
806 #endif /* NBM > 0 */
807 return c;
808 }
809
810 /*
811 * Put a char on a specific SCC line
812 */
813 void scc_putc(
814 int unit,
815 int line,
816 int c)
817 {
818 scc_softc_t scc;
819 register scc_regmap_t *regs;
820 spl_t s = spltty();
821 register int value;
822
823 mi_to_scc(&unit, &line);
824
825 scc = scc_softc[unit];
826 regs = scc->regs;
827
828 do {
829 scc_read_reg(regs, line, SCC_RR0, value);
830 if (value & SCC_RR0_TX_EMPTY)
831 break;
832 delay(100);
833 } while (1);
834
835 scc_write_data(regs, line, c);
836 /* wait for it to swallow the char ? */
837
838 splx(s);
839 }
840
841 void scc_param(
842 struct tty *tp,
843 int line)
844 {
845 scc_regmap_t *regs;
846 int value, sccline, unit;
847 struct softreg *sr;
848 scc_softc_t scc;
849
850 line = tp->t_dev;
851 /* MI code wants us to handle 4 lines on unit 0 */
852 unit = (line < 4) ? 0 : (line / NSCC_LINE);
853 sccline = line;
854 mi_to_scc(&unit, &sccline);
855
856 if ((scc = scc_softc[unit]) == 0) return; /* sanity */
857 regs = scc->regs;
858
859 sr = &scc->softr[sccline];
860
861 /*
862 * Do not let user fool around with kbd&mouse
863 */
864 #if NBM > 0
865 if (screen_captures(line)) {
866 tp->t_ispeed = tp->t_ospeed = B4800;
867 tp->t_flags |= TF_LITOUT;
868 }
869 #endif /* NBM > 0 */
870
871 if (tp->t_ispeed == 0) {
872 (void) scc_mctl(tp->t_dev, TM_HUP, DMSET); /* hang up line */
873 return;
874 }
875
876 /* reset line */
877 value = (sccline == SCC_CHANNEL_A) ? SCC_WR9_RESET_CHA_A : SCC_WR9_RESET_CHA_B;
878 scc_write_reg(regs, sccline, SCC_WR9, value);
879 delay(25);
880
881 /* stop bits, normally 1 */
882 value = sr->wr4 & 0xf0;
883 value |= (tp->t_ispeed == B110) ? SCC_WR4_2_STOP : SCC_WR4_1_STOP;
884
885 /* .. and parity */
886 if ((tp->t_flags & (TF_ODDP | TF_EVENP)) == TF_ODDP)
887 value |= SCC_WR4_PARITY_ENABLE;
888
889 /* set it now, remember it must be first after reset */
890 sr->wr4 = value;
891 scc_write_reg(regs, sccline, SCC_WR4, value);
892
893 /* vector again */
894 scc_write_reg(regs, sccline, SCC_WR2, 0xf0);
895
896 /* we only do 8 bits per char */
897 value = SCC_WR3_RX_8_BITS;
898 scc_write_reg(regs, sccline, SCC_WR3, value);
899
900 /* clear break, keep rts dtr */
901 value = sr->wr5 & (SCC_WR5_DTR|SCC_WR5_RTS);
902 value |= SCC_WR5_TX_8_BITS;
903 sr->wr5 = value;
904 scc_write_reg(regs, sccline, SCC_WR5, value);
905 /* some are on the other channel, which might
906 never be used (e.g. maxine has only one line) */
907 {
908 register int otherline = (sccline+1)&1;
909
910 scc_write_reg(regs, otherline, SCC_WR5, scc->softr[otherline].wr5);
911 }
912
913 scc_write_reg(regs, sccline, SCC_WR6, 0);
914 scc_write_reg(regs, sccline, SCC_WR7, 0);
915
916 scc_write_reg(regs, sccline, SCC_WR9, SCC_WR9_VIS);
917
918 scc_write_reg(regs, sccline, SCC_WR10, 0);
919
920 /* clock config */
921 value = SCC_WR11_RCLK_BAUDR | SCC_WR11_XTLK_BAUDR |
922 SCC_WR11_TRc_OUT | SCC_WR11_TRcOUT_BAUDR;
923 scc_write_reg(regs, sccline, SCC_WR11, value);
924
925 value = scc_speeds[tp->t_ispeed];
926 scc_set_timing_base(regs,sccline,value);
927
928 value = sr->wr14;
929 scc_write_reg(regs, sccline, SCC_WR14, value);
930
931 #if FLAMINGO
932 if (unit != 1)
933 #else
934 if (1)
935 #endif
936 {
937 /* Chan-A: CTS==SI DCD==RI DSR=SYNCH */
938 value = SCC_WR15_CTS_IE | SCC_WR15_DCD_IE | SCC_WR15_SYNCHUNT_IE;
939 scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR15, value);
940
941 /* Chan-B: CTS==CTS DCD==DCD */
942 value = SCC_WR15_BREAK_IE | SCC_WR15_CTS_IE | SCC_WR15_DCD_IE;
943 scc_write_reg(regs, SCC_CHANNEL_B, SCC_WR15, value);
944 } else {
945 /* Here if modem bits are floating noise, keep quiet */
946 value = SCC_WR15_BREAK_IE;
947 scc_write_reg(regs, sccline, SCC_WR15, value);
948 }
949
950 /* and now the enables */
951 value = SCC_WR3_RX_8_BITS | SCC_WR3_RX_ENABLE;
952 scc_write_reg(regs, sccline, SCC_WR3, value);
953
954 value = sr->wr5 | SCC_WR5_TX_ENABLE;
955 sr->wr5 = value;
956 scc_write_reg(regs, sccline, SCC_WR5, value);
957
958 /* master inter enable */
959 scc_write_reg(regs,sccline,SCC_WR9,SCC_WR9_MASTER_IE|SCC_WR9_VIS);
960
961 scc_write_reg(regs, sccline, SCC_WR1, sr->wr1);
962
963 }
964
965 /*
966 * Modem control functions
967 */
968 int
969 scc_mctl(
970 int dev,
971 int bits,
972 int how)
973 {
974 register scc_regmap_t *regs;
975 struct softreg *sra, *srb, *sr;
976 int unit, sccline;
977 int b = 0;
978 spl_t s;
979 scc_softc_t scc;
980
981 /* MI code wants us to handle 4 lines on unit 0 */
982 unit = (dev < 4) ? 0 : (dev / NSCC_LINE);
983 sccline = dev;
984 mi_to_scc(&unit, &sccline);
985
986 if ((scc = scc_softc[unit]) == 0) return 0; /* sanity */
987 regs = scc->regs;
988
989 sr = &scc->softr[sccline];
990 sra = &scc->softr[SCC_CHANNEL_A];
991 srb = &scc->softr[SCC_CHANNEL_B];
992
993 if (bits == TM_HUP) { /* close line (internal) */
994 bits = TM_DTR | TM_RTS;
995 how = DMBIC;
996 /* xxx interrupts too ?? */
997 }
998
999 if (bits & TM_BRK) {
1000 switch (how) {
1001 case DMSET:
1002 case DMBIS:
1003 sr->wr5 |= SCC_WR5_SEND_BREAK;
1004 break;
1005 case DMBIC:
1006 sr->wr5 &= ~SCC_WR5_SEND_BREAK;
1007 break;
1008 default:
1009 goto dontbrk;
1010 }
1011 s = spltty();
1012 scc_write_reg(regs, sccline, SCC_WR5, sr->wr5);
1013 splx(s);
1014 dontbrk:
1015 b |= (sr->wr5 & SCC_WR5_SEND_BREAK) ? TM_BRK : 0;
1016 }
1017
1018 /* no modem support on channel A */
1019 if (sccline == SCC_CHANNEL_A)
1020 return (b | TM_LE | TM_DTR | TM_CTS | TM_CAR | TM_DSR);
1021
1022 sra = &scc->softr[SCC_CHANNEL_A];
1023 srb = &scc->softr[SCC_CHANNEL_B];
1024
1025 #if 0
1026 /* do I need to do something on this ? */
1027 if (bits & TM_LE) { /* line enable */
1028 }
1029 #endif
1030
1031 if (bits & (TM_DTR|TM_RTS)) { /* data terminal ready, request to send */
1032 register int w = 0;
1033
1034 if (bits & TM_DTR) w |= SCC_WR5_DTR;
1035 if (bits & TM_RTS) w |= SCC_WR5_RTS;
1036
1037 switch (how) {
1038 case DMSET:
1039 case DMBIS:
1040 sra->wr5 |= w;
1041 break;
1042 case DMBIC:
1043 sra->wr5 &= ~w;
1044 break;
1045 default:
1046 goto dontdtr;
1047 }
1048 s = spltty();
1049 scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR5, sra->wr5);
1050 splx(s);
1051 dontdtr:
1052 b |= (sra->wr5 & w) ? (bits & (TM_DTR|TM_RTS)) : 0;
1053 }
1054
1055 s = spltty();
1056
1057 #if 0
1058 /* Unsupported */
1059 if (bits & TM_ST) { /* secondary transmit */
1060 }
1061 if (bits & TM_SR) { /* secondary receive */
1062 }
1063 #endif
1064
1065 if (bits & TM_CTS) { /* clear to send */
1066 register int value;
1067 scc_read_reg(regs, SCC_CHANNEL_B, SCC_RR0, value);
1068 b |= (value & SCC_RR0_CTS) ? TM_CTS : 0;
1069 }
1070
1071 if (bits & TM_CAR) { /* carrier detect */
1072 register int value;
1073 scc_read_reg(regs, SCC_CHANNEL_B, SCC_RR0, value);
1074 b |= (value & SCC_RR0_DCD) ? TM_CAR : 0;
1075 }
1076
1077 if (bits & TM_RNG) { /* ring */
1078 register int value;
1079 scc_read_reg(regs, SCC_CHANNEL_A, SCC_RR0, value);
1080 b |= (value & SCC_RR0_DCD) ? TM_RNG : 0;
1081 }
1082
1083 if (bits & TM_DSR) { /* data set ready */
1084 register int value;
1085 scc_read_reg(regs, SCC_CHANNEL_A, SCC_RR0, value);
1086 b |= (value & SCC_RR0_SYNCH) ? TM_DSR : 0;
1087 }
1088
1089 splx(s);
1090
1091 return b;
1092 }
1093
1094 #define debug 0
1095
1096 void
1097 scc_modem_intr(
1098 scc_softc_t scc,
1099 int chan,
1100 int unit)
1101 {
1102 register int value, changed;
1103
1104 scc_read_reg_zero(scc->regs, chan, value);
1105
1106 /* See what changed */
1107 changed = value ^ scc->last_rr0[chan];
1108 scc->last_rr0[chan] = value;
1109
1110 #if debug
1111 printf("sccmodem: chan %c now %x, changed %x : ",
1112 (chan == SCC_CHANNEL_B) ? 'B' : 'A',
1113 value, changed);
1114 #endif
1115
1116 if (chan == SCC_CHANNEL_A) {
1117 if (changed & SCC_RR0_CTS) {
1118 /* Speed indicator, ignore XXX */
1119 #if debug
1120 printf("%s-speed ", (value & SCC_RR0_CTS) ? "Full" : "Half");
1121 #endif
1122 }
1123 if (changed & SCC_RR0_DCD) {
1124 /* Ring indicator */
1125 #if debug
1126 printf("Ring ");
1127 #endif
1128 }
1129 if (changed & SCC_RR0_SYNCH) {
1130 /* Data Set Ready */
1131 #if debug
1132 printf("DSR ");
1133 #endif
1134 /* If modem went down then CD will also go down,
1135 or it did already.
1136 If modem came up then we have to wait for CD
1137 anyways before enabling the line.
1138 Either way, nothing to do here */
1139 }
1140 } else {
1141 if (changed & SCC_RR0_CTS) {
1142 /* Clear To Send */
1143 #if debug
1144 printf("CTS ");
1145 #endif
1146 tty_cts(console_tty[scc_to_mi(unit,chan)],
1147 value & SCC_RR0_CTS);
1148 }
1149 if (changed & SCC_RR0_DCD) {
1150 #if debug
1151 printf("CD ");
1152 #endif
1153 check_car(console_tty[scc_to_mi(unit,chan)],
1154 value & SCC_RR0_DCD);
1155 }
1156 }
1157 #if debug
1158 printf(".\n");
1159 #endif
1160 }
1161
1162 private void check_car(
1163 register struct tty *tp,
1164 boolean_t car)
1165 {
1166 if (car) {
1167 #if notyet
1168 /* cancel modem timeout if need to */
1169 if (car & (SCC_MSR_CD2 | SCC_MSR_CD3))
1170 untimeout(scc_hup, (vm_offset_t)tp);
1171 #endif
1172
1173 /* I think this belongs in the MI code */
1174 if (tp->t_state & TS_WOPEN)
1175 tp->t_state |= TS_ISOPEN;
1176 /* carrier present */
1177 if ((tp->t_state & TS_CARR_ON) == 0)
1178 (void)ttymodem(tp, 1);
1179 } else if ((tp->t_state&TS_CARR_ON) && ttymodem(tp, 0) == 0)
1180 scc_mctl( tp->t_dev, TM_DTR, DMBIC);
1181 }
1182
1183 /*
1184 * Periodically look at the CD signals:
1185 * they do generate interrupts but we
1186 * must fake them on channel A. We might
1187 * also fake them on channel B.
1188 */
1189 void scc_scan(void)
1190 {
1191 register i;
1192 spl_t s = spltty();
1193
1194 for (i = 0; i < NSCC; i++) {
1195 register scc_softc_t scc;
1196 register int car;
1197 register struct tty **tpp;
1198
1199 scc = scc_softc[i];
1200 if (scc == 0)
1201 continue;
1202 car = scc->softCAR | scc->fake;
1203
1204 tpp = &console_tty[i * NSCC_LINE];
1205
1206 while (car) {
1207 if (car & 1)
1208 check_car(*tpp, 1);
1209 tpp++;
1210 car = car>>1;
1211 }
1212
1213 }
1214 splx(s);
1215 timeout(scc_scan, (vm_offset_t)0, 5*hz);
1216 }
1217
1218
1219 #if debug
1220 scc_rr0(unit,chan)
1221 {
1222 int val;
1223 scc_read_reg_zero(scc_softc[unit]->regs, chan, val);
1224 return val;
1225 }
1226
1227 scc_rreg(unit,chan,n)
1228 {
1229 int val;
1230 scc_read_reg(scc_softc[unit]->regs, chan, n, val);
1231 return val;
1232 }
1233
1234 scc_wreg(unit,chan,n,val)
1235 {
1236 scc_write_reg(scc_softc[unit]->regs, chan, n, val);
1237 }
1238
1239 scc_state(unit,soft)
1240 {
1241 int rr0, rr1, rr3, rr12, rr13, rr15;
1242
1243 rr0 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR0);
1244 rr1 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR1);
1245 rr3 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR3);
1246 rr12 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR12);
1247 rr13 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR13);
1248 rr15 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR15);
1249 printf("{%d intr, A: R0 %x R1 %x R3 %x baudr %x R15 %x}\n",
1250 scc_intr_count, rr0, rr1, rr3,
1251 (rr13 << 8) | rr12, rr15);
1252
1253 rr0 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR0);
1254 rr1 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR1);
1255 rr3 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR2);
1256 rr12 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR12);
1257 rr13 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR13);
1258 rr15 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR15);
1259 printf("{B: R0 %x R1 %x R2 %x baudr %x R15 %x}\n",
1260 rr0, rr1, rr3,
1261 (rr13 << 8) | rr12, rr15);
1262
1263 if (soft) {
1264 struct softreg *sr;
1265 sr = scc_softc[unit]->softr;
1266 printf("{B: W1 %x W4 %x W5 %x W14 %x}",
1267 sr->wr1, sr->wr4, sr->wr5, sr->wr14);
1268 sr++;
1269 printf("{A: W1 %x W4 %x W5 %x W14 %x}\n",
1270 sr->wr1, sr->wr4, sr->wr5, sr->wr14);
1271 }
1272 }
1273
1274 #endif
1275
1276 #endif /* NSCC > 0 */
Cache object: 91831ce37330f305140308cf270934cc
|