Sync usage with man page.
[netbsd-mini2440.git] / sys / arch / mac68k / dev / scc_8530_hdw.c
blobd2a2d47f9caccd84c392481d81790b3166b7e321
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.
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.
16 * Carnegie Mellon requests users of this software to return to
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
27 * HISTORY
28 * $Log: scc_8530_hdw.c,v $
29 * Revision 2.9 93/03/26 17:58:01 mrt
30 * No minor()s, no dev_t.
31 * [93/03/18 af]
33 * Revision 2.8 93/03/09 10:52:21 danner
34 * GCC quiet.
35 * [93/03/07 13:29:58 af]
37 * Post-debugging lint.
38 * [93/03/05 af]
40 * Revision 2.7 93/02/05 08:05:17 danner
41 * Flamingo, full_modem and isa_console per-line.
42 * [93/02/04 af]
44 * Revision 2.6 93/01/14 17:21:44 danner
45 * static/extern cleanups.
46 * [93/01/14 danner]
48 * Proper spl typing.
49 * [92/11/30 af]
51 * Revision 2.5 92/05/05 10:04:59 danner
52 * Fixed how the interrupt routine plays with priorities.
53 * Ask for buffering on all lines.
54 * [92/05/04 11:15:43 af]
56 * Fixed for more than just rconsole-ing. Two bugs: the chip
57 * needs one char out to generate the xmit-empty (so it really
58 * is a xmit-done) interrupt, and the t_addr game was not played
59 * properly.
60 * Tested both on maxine and the two serial lines kmin has.
61 * [92/04/14 11:47:26 af]
63 * Revision 2.4 92/02/19 16:46:10 elf
64 * Uhmm, lotsa changes. Basically, got channel B working
65 * and made it possible to use it as rconsole line.
66 * Missing modem bitsies only.
67 * A joint Terri&Sandro feature presentation.
68 * [92/02/10 17:03:08 af]
70 * Revision 2.3 91/08/28 11:09:53 jsb
71 * Fixed scc_scan to actually check the tp->state each time,
72 * we are not notified when the MI code brutally zeroes it
73 * on close and so we cannot update our software CARrier.
74 * [91/08/27 16:18:05 af]
76 * Revision 2.2 91/08/24 11:52:54 af
77 * Created, from the Zilog specs:
78 * "Z8530 SCC Serial Communications Controller, Product Specification"
79 * in the "1983/84 Components Data Book" pp 409-429, September 1983
80 * Zilog, Campbell, CA 95008
81 * [91/06/28 af]
84 #ident "$Id: scc_8530_hdw.c,v 1.1 1993/09/29 06:09:27 briggs Exp $"
86 * File: scc_8530_hdw.c
87 * Author: Alessandro Forin, Carnegie Mellon University
88 * Date: 6/91
90 * Hardware-level operations for the SCC Serial Line Driver
93 #include <scc.h>
94 #if NSCC > 0
95 #include <bm.h>
96 #include <platforms.h>
98 #include <mach_kdb.h>
100 #include <machine/machparam.h> /* spl definitions */
101 #include <sys/types.h>
102 #include <mach/std_types.h>
103 #include <device/io_req.h>
104 #include <device/tty.h>
106 #include <chips/busses.h>
107 #include <chips/serial_defs.h>
108 #include <chips/screen_defs.h>
110 /* Alignment and padding */
111 #if defined(DECSTATION)
113 * 3min's padding
115 typedef struct {
116 char pad0;
117 volatile unsigned char datum;
118 char pad1[2];
119 } scc_padded1_register_t;
121 #define scc_register_t scc_padded1_register_t
122 #endif
124 #if defined(FLAMINGO)
125 typedef struct {
126 volatile unsigned int datum;
127 unsigned int pad1;
128 } scc_padded1_register_t;
130 #define scc_register_t scc_padded1_register_t
132 #define scc_set_datum(d,v) (d) = (volatile unsigned int) (v) << 8, wbflush()
133 #define scc_get_datum(d,v) (v) = ((d) >> 8) & 0xff
135 #endif
137 #include <chips/scc_8530.h> /* needs the above defs */
140 * On the 3min keyboard and mouse come in on channels A
141 * of the two units. The MI code expects them at 'lines'
142 * 0 and 1, respectively. So we map here back and forth.
143 * Note also the MI code believes unit 0 has four lines.
146 #define SCC_KBDUNIT 1
147 #define SCC_PTRUNIT 0
149 mi_to_scc(unitp, linep)
150 int *unitp, *linep;
152 /* only play games on MI 'unit' 0 */
153 if (*unitp) {
154 /* e.g. by mapping the first four lines specially */
155 *unitp++;
156 return;
159 /* always get unit=0 (console) and line = 0|1 */
160 if (*linep == SCREEN_LINE_KEYBOARD) {
161 *unitp = SCC_KBDUNIT;
162 *linep = SCC_CHANNEL_A;
163 } else if (*linep == SCREEN_LINE_POINTER) {
164 *unitp = SCC_PTRUNIT;
165 *linep = SCC_CHANNEL_A;
166 } else {
167 *unitp = (*linep & 1);
168 *linep = SCC_CHANNEL_B;
170 /* line 0 is channel B, line 1 is channel A */
173 #define NSCC_LINE 2 /* 2 ttys per chip */
175 /* only care for mapping to ttyno */
176 scc_to_mi(sccunit, sccline)
178 if (sccunit > 1)
179 return (sccunit * NSCC_LINE + sccline);
180 /* only for console (first pair of SCCs): */
181 if (sccline == SCC_CHANNEL_A)
182 return ((!sccunit) & 1);
183 return 2+sccunit;
188 * Driver status
190 struct scc_softc {
191 scc_regmap_t *regs;
193 /* software copy of some write regs, for reg |= */
194 struct softreg {
195 unsigned char wr1;
196 unsigned char wr4;
197 unsigned char wr5;
198 unsigned char wr14;
199 } softr[2]; /* per channel */
201 unsigned short breaks;
202 unsigned short fake; /* missing rs232 bits, channel A */
203 char polling_mode;
204 char softCAR, osoftCAR;
205 char probed_once;
207 boolean_t full_modem;
208 boolean_t isa_console;
210 } scc_softc_data[NSCC];
212 typedef struct scc_softc *scc_softc_t;
214 scc_softc_t scc_softc[NSCC];
216 scc_softCAR(unit, line, on)
218 mi_to_scc(&unit, &line);
219 if (on)
220 scc_softc[unit]->softCAR |= 1<<line;
221 else
222 scc_softc[unit]->softCAR &= ~(1 << line);
227 * BRG formula is:
228 * ClockFrequency
229 * BRGconstant = --------------------------- - 2
230 * 2 * BaudRate * ClockDivider
232 /* Speed selections with Pclk=7.3728Mhz, clock x16 */
233 static
234 short scc_speeds[] =
235 /* 0 50 75 110 134.5 150 200 300 600 1200 1800 2400 */
236 { 0, 4606, 3070, 2093, 1711, 1534, 1150, 766, 382, 190, 126, 94,
238 /* 4800 9600 19.2k 38.4k */
239 46, 22, 10, 4};
242 * Definition of the driver for the auto-configuration program.
245 int scc_probe(), scc_attach(), scc_intr();
247 caddr_t scc_std[NSCC] = { 0 };
248 struct bus_device *scc_info[NSCC];
249 struct bus_driver scc_driver =
250 { scc_probe, 0, scc_attach, 0, scc_std, "scc", scc_info,};
253 * Adapt/Probe/Attach functions
255 boolean_t scc_uses_modem_control = FALSE;/* patch this with adb */
257 set_scc_address( sccunit, regs, has_modem, isa_console)
258 caddr_t regs;
259 boolean_t has_modem;
260 boolean_t isa_console;
262 extern int scc_probe(), scc_param(), scc_start(),
263 scc_putc(), scc_getc(),
264 scc_pollc(), scc_mctl(), scc_softCAR();
266 scc_std[sccunit] = regs;
267 scc_softc_data[sccunit].full_modem = has_modem & scc_uses_modem_control;
268 scc_softc_data[sccunit].isa_console = isa_console;
270 /* Do this here */
271 console_probe = scc_probe;
272 console_param = scc_param;
273 console_start = scc_start;
274 console_putc = scc_putc;
275 console_getc = scc_getc;
276 console_pollc = scc_pollc;
277 console_mctl = scc_mctl;
278 console_softCAR = scc_softCAR;
282 scc_probe( xxx, ui)
283 struct bus_device *ui;
285 int sccunit = ui->unit;
286 scc_softc_t scc;
287 register int val;
288 register scc_regmap_t *regs;
290 regs = (scc_regmap_t *)scc_std[sccunit];
291 if (regs == 0)
292 return 0;
295 * See if we are here
297 if (check_memory(regs, 0)) {
298 /* no rides today */
299 return 0;
302 scc = &scc_softc_data[sccunit];
304 if (scc->probed_once++){
305 return 1;
308 * Chip once-only initialization
310 * NOTE: The wiring we assume is the one on the 3min:
312 * out A-TxD --> TxD keybd or mouse
313 * in A-RxD --> RxD keybd or mouse
314 * out A-DTR~ --> DTR comm
315 * out A-RTS~ --> RTS comm
316 * in A-CTS~ --> SI comm
317 * in A-DCD~ --> RI comm
318 * in A-SYNCH~--> DSR comm
319 * out B-TxD --> TxD comm
320 * in B-RxD --> RxD comm
321 * in B-RxC --> TRxCB comm
322 * in B-TxC --> RTxCB comm
323 * out B-RTS~ --> SS comm
324 * in B-CTS~ --> CTS comm
325 * in B-DCD~ --> CD comm
328 scc_softc[sccunit] = scc;
329 scc->regs = regs;
331 scc->fake = 1<<SCC_CHANNEL_A;
334 register int i;
335 /* We need this in scc_start only, hence the funny
336 value: we need it non-zero and we want to avoid
337 too much overhead in getting to (scc,regs,line) */
338 for (i = 0; i < NSCC_LINE; i++) {
339 register struct tty *tp;
341 tp = console_tty[scc_to_mi(sccunit,i)];
342 tp->t_addr = (char*)(0x80000000L + (sccunit<<1) + (i&1));
343 /* do min buffering */
344 tp->t_state |= TS_MIN;
348 /* make sure reg pointer is in known state */
349 scc_init_reg(regs, SCC_CHANNEL_A);
350 scc_init_reg(regs, SCC_CHANNEL_B);
352 /* reset chip, fully */
353 scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_HW_RESET);
354 delay(50000);/*enough ? */
355 scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR9, 0);
357 /* program the interrupt vector */
358 scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR2, 0xf0);
359 scc_write_reg(regs, SCC_CHANNEL_B, SCC_WR2, 0xf0);
360 scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_VIS);
362 /* most of the init is in scc_param() */
364 /* timing base defaults */
365 scc->softr[SCC_CHANNEL_A].wr4 = SCC_WR4_CLK_x16;
366 scc->softr[SCC_CHANNEL_B].wr4 = SCC_WR4_CLK_x16;
368 /* enable DTR, RTS and SS */
369 scc->softr[SCC_CHANNEL_B].wr5 = SCC_WR5_RTS;
370 scc->softr[SCC_CHANNEL_A].wr5 = SCC_WR5_RTS | SCC_WR5_DTR;
372 /* baud rates */
373 val = SCC_WR14_BAUDR_ENABLE|SCC_WR14_BAUDR_SRC;
374 scc->softr[SCC_CHANNEL_B].wr14 = val;
375 scc->softr[SCC_CHANNEL_A].wr14 = val;
377 /* interrupt conditions */
378 val = SCC_WR1_RXI_ALL_CHAR | SCC_WR1_PARITY_IE |
379 SCC_WR1_EXT_IE | SCC_WR1_TX_IE;
380 scc->softr[SCC_CHANNEL_A].wr1 = val;
381 scc->softr[SCC_CHANNEL_B].wr1 = val;
384 * After probing, any line that should be active
385 * (keybd,mouse,rcline) is activated via scc_param().
388 scc_set_modem_control(scc, scc->full_modem);
390 #if defined(KMIN) || defined (FLAMINGO)
392 * Crock: MI code knows of unit 0 as console, we need
393 * unit 1 as well since the keyboard is there
394 * This is acceptable on maxine, which has to call its
395 * only one chip unit 1 so that rconsole is happy.
397 if (sccunit == 0) {
398 struct bus_device d;
399 d = *ui;
400 d.unit = 1;
401 scc_probe( xxx, &d);
403 #endif
404 return 1;
407 boolean_t scc_timer_started = FALSE;
409 scc_attach(ui)
410 register struct bus_device *ui;
412 int sccunit = ui->unit;
413 extern scc_scan();
414 extern int tty_inq_size;
415 int i;
417 /* We only have 4 ttys, but always at 9600
418 * Give em a lot of room (plus dma..)
420 tty_inq_size = 4096;
421 if (!scc_timer_started) {
422 /* do all of them, before we call scc_scan() */
423 /* harmless if done already */
424 for (i = 0; i < NSCC*NSCC_LINE; i++)
425 ttychars(console_tty[i]);
427 scc_timer_started = TRUE;
428 scc_scan();
431 #if NBM > 0
432 if (SCREEN_ISA_CONSOLE() && scc_softc[sccunit]->isa_console) {
433 printf("\n sl0: ");
434 if (sccunit && rcline == 3) printf("( rconsole )");
436 if (sccunit == SCC_KBDUNIT) {
437 printf("\n sl1: "); lk201_attach(0, sccunit >> 1);
438 } else if (sccunit == SCC_PTRUNIT) {
439 printf("\n sl1: "); mouse_attach(0, sccunit >> 1);
441 } else
442 #endif /*NBM > 0*/
444 printf("%s", (sccunit == 1) ?
445 "\n sl0: ( alternate console )\n sl1:" :
446 "\n sl0:\n sl1:");
451 * Would you like to make a phone call ?
453 scc_set_modem_control(scc, on)
454 scc_softc_t scc;
455 boolean_t on;
457 if (on)
458 /* your problem if the hardware then is broke */
459 scc->fake = 0;
460 else
461 scc->fake = 3;
462 scc->full_modem = on;
463 /* user should do an scc_param() ifchanged */
467 * Polled I/O (debugger)
469 scc_pollc(unit, on)
470 boolean_t on;
472 scc_softc_t scc;
473 int line = SCREEN_LINE_KEYBOARD,
474 sccunit = unit;
476 mi_to_scc(&sccunit, &line);
478 scc = scc_softc[sccunit];
479 if (on) {
480 scc->polling_mode++;
481 #if NBM > 0
482 screen_on_off(unit, TRUE);
483 #endif NBM > 0
484 } else
485 scc->polling_mode--;
489 * Interrupt routine
491 int scc_intr_count;
493 scc_intr(unit,spllevel)
494 spl_t spllevel;
496 scc_softc_t scc = scc_softc[unit];
497 register scc_regmap_t *regs = scc->regs;
498 register int rr1, rr2;
499 register int c;
501 scc_intr_count++;
503 #if mips
504 splx(spllevel); /* lower priority */
505 #endif
507 next_intr:
509 scc_read_reg(regs, SCC_CHANNEL_B, SCC_RR2, rr2);
511 rr2 = SCC_RR2_STATUS(rr2);
513 /* are we done yet ? */
514 if (rr2 == 6) { /* strange, distinguished value */
515 register int rr3;
516 scc_read_reg(regs, SCC_CHANNEL_A, SCC_RR3, rr3);
517 if (rr3 == 0)
518 return;
521 if ((rr2 == SCC_RR2_A_XMIT_DONE) || (rr2 == SCC_RR2_B_XMIT_DONE)) {
523 register chan = (rr2 == SCC_RR2_A_XMIT_DONE) ?
524 SCC_CHANNEL_A : SCC_CHANNEL_B;
526 scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
527 c = cons_simple_tint(scc_to_mi(unit,chan), FALSE);
529 if (c == -1) {
530 /* no more data for this line */
532 scc_read_reg(regs, chan, SCC_RR15, c);
533 c &= ~SCC_WR15_TX_UNDERRUN_IE;
534 scc_write_reg(regs, chan, SCC_WR15, c);
536 c = scc->softr[chan].wr1 & ~SCC_WR1_TX_IE;
537 scc_write_reg(regs, chan, SCC_WR1, c);
538 scc->softr[chan].wr1 = c;
540 c = cons_simple_tint(scc_to_mi(unit,chan), TRUE);
541 if (c != -1)
542 /* funny race, scc_start has been called already */
543 scc_write_data(regs, chan, c);
544 } else {
545 scc_write_data(regs, chan, c);
546 /* and leave it enabled */
550 else if (rr2 == SCC_RR2_A_RECV_DONE) {
551 int err = 0;
553 scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
554 if (scc->polling_mode)
555 goto next_intr;
557 scc_read_data(regs, SCC_CHANNEL_A, c);
558 rr1 = scc_to_mi(unit,SCC_CHANNEL_A);
559 cons_simple_rint (rr1, rr1, c, 0);
562 else if (rr2 == SCC_RR2_B_RECV_DONE) {
563 int err = 0;
565 scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
566 if (scc->polling_mode)
567 goto next_intr;
569 scc_read_data(regs, SCC_CHANNEL_B, c);
570 rr1 = scc_to_mi(unit,SCC_CHANNEL_B);
571 cons_simple_rint (rr1, rr1, c, 0);
574 else if ((rr2 == SCC_RR2_A_EXT_STATUS) || (rr2 == SCC_RR2_B_EXT_STATUS)) {
575 int chan = (rr2 == SCC_RR2_A_EXT_STATUS) ?
576 SCC_CHANNEL_A : SCC_CHANNEL_B;
577 scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_EXT_IP);
578 scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
579 scc_modem_intr(scc, chan);
582 else if ((rr2 == SCC_RR2_A_RECV_SPECIAL) || (rr2 == SCC_RR2_B_RECV_SPECIAL)) {
583 register int chan = (rr2 == SCC_RR2_A_RECV_SPECIAL) ?
584 SCC_CHANNEL_A : SCC_CHANNEL_B;
586 scc_read_reg(regs, chan, SCC_RR1, rr1);
587 if (rr1 & (SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN | SCC_RR1_FRAME_ERR)) {
588 int err;
589 /* map to CONS_ERR_xxx MI error codes */
590 err = ((rr1 & SCC_RR1_PARITY_ERR)<<8) |
591 ((rr1 & SCC_RR1_RX_OVERRUN)<<9) |
592 ((rr1 & SCC_RR1_FRAME_ERR)<<7);
593 scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_ERROR);
594 rr1 = scc_to_mi(unit,chan);
595 cons_simple_rint(rr1, rr1, 0, err);
597 scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
600 goto next_intr;
604 boolean_t
605 scc_start(tp)
606 struct tty *tp;
608 register scc_regmap_t *regs;
609 register int chan, temp;
610 register struct softreg *sr;
612 temp = (natural_t)tp->t_addr;
613 chan = (temp & 1); /* channel */
614 temp = (temp >> 1)&0xff;/* sccunit */
615 regs = scc_softc[temp]->regs;
616 sr = &scc_softc[temp]->softr[chan];
618 scc_read_reg(regs, chan, SCC_RR15, temp);
619 temp |= SCC_WR15_TX_UNDERRUN_IE;
620 scc_write_reg(regs, chan, SCC_WR15, temp);
622 temp = sr->wr1 | SCC_WR1_TX_IE;
623 scc_write_reg(regs, chan, SCC_WR1, temp);
624 sr->wr1 = temp;
626 /* but we need a first char out or no cookie */
627 scc_read_reg(regs, chan, SCC_RR0, temp);
628 if (temp & SCC_RR0_TX_EMPTY)
630 register char c;
632 c = getc(&tp->t_outq);
633 scc_write_data(regs, chan, c);
638 * Get a char from a specific SCC line
639 * [this is only used for console&screen purposes]
641 scc_getc( unit, line, wait, raw )
642 boolean_t wait;
643 boolean_t raw;
645 scc_softc_t scc;
646 register scc_regmap_t *regs;
647 unsigned char c;
648 int value, mi_line, rcvalue, from_line;
650 mi_line = line;
651 mi_to_scc(&unit, &line);
653 scc = scc_softc[unit];
654 regs = scc->regs;
657 * wait till something available
659 * NOTE: we know! that rcline==3
661 if (rcline) rcline = 3;
662 again:
663 rcvalue = 0;
664 while (1) {
665 scc_read_reg_zero(regs, line, value);
666 if (rcline && (mi_line == SCREEN_LINE_KEYBOARD)) {
667 scc_read_reg_zero(regs, SCC_CHANNEL_B, rcvalue);
668 value |= rcvalue;
670 if (((value & SCC_RR0_RX_AVAIL) == 0) && wait)
671 delay(10);
672 else
673 break;
677 * if nothing found return -1
679 from_line = (rcvalue & SCC_RR0_RX_AVAIL) ? SCC_CHANNEL_B : line;
681 if (value & SCC_RR0_RX_AVAIL) {
682 scc_read_reg(regs, from_line, SCC_RR1, value);
683 scc_read_data(regs, from_line, c);
684 } else {
685 /* splx(s);*/
686 return -1;
690 * bad chars not ok
692 if (value&(SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN | SCC_RR1_FRAME_ERR)) {
693 /* scc_state(unit,from_line); */
694 scc_write_reg(regs, from_line, SCC_RR0, SCC_RESET_ERROR);
695 if (wait) {
696 scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
697 goto again;
700 scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
701 /* splx(s);*/
704 #if NBM > 0
705 if ((mi_line == SCREEN_LINE_KEYBOARD) && (from_line == SCC_CHANNEL_A) &&
706 !raw && SCREEN_ISA_CONSOLE() && scc->isa_console)
707 return lk201_rint(SCREEN_CONS_UNIT(), c, wait, scc->polling_mode);
708 else
709 #endif NBM > 0
710 return c;
714 * Put a char on a specific SCC line
716 scc_putc( unit, line, c )
718 scc_softc_t scc;
719 register scc_regmap_t *regs;
720 spl_t s = spltty();
721 register int value;
723 mi_to_scc(&unit, &line);
725 scc = scc_softc[unit];
726 regs = scc->regs;
728 do {
729 scc_read_reg(regs, line, SCC_RR0, value);
730 if (value & SCC_RR0_TX_EMPTY)
731 break;
732 delay(100);
733 } while (1);
735 scc_write_data(regs, line, c);
736 /* wait for it to swallow the char ? */
738 splx(s);
741 scc_param(tp, line)
742 struct tty *tp;
744 scc_regmap_t *regs;
745 int value, sccline, unit;
746 struct softreg *sr;
747 scc_softc_t scc;
749 line = tp->t_dev;
750 /* MI code wants us to handle 4 lines on unit 0 */
751 unit = (line < 4) ? 0 : (line / NSCC_LINE);
752 sccline = line;
753 mi_to_scc(&unit, &sccline);
755 if ((scc = scc_softc[unit]) == 0) return; /* sanity */
756 regs = scc->regs;
758 sr = &scc->softr[sccline];
761 * Do not let user fool around with kbd&mouse
763 #if NBM > 0
764 if (screen_captures(line)) {
765 tp->t_ispeed = tp->t_ospeed = B4800;
766 tp->t_flags |= TF_LITOUT;
768 #endif NBM > 0
770 if (tp->t_ispeed == 0) {
771 (void) scc_mctl(tp->t_dev, TM_HUP, DMSET); /* hang up line */
772 return;
775 /* reset line */
776 value = (sccline == SCC_CHANNEL_A) ? SCC_WR9_RESET_CHA_A : SCC_WR9_RESET_CHA_B;
777 scc_write_reg(regs, sccline, SCC_WR9, value);
778 delay(25);
780 /* stop bits, normally 1 */
781 value = sr->wr4 & 0xf0;
782 value |= (tp->t_ispeed == B110) ? SCC_WR4_2_STOP : SCC_WR4_1_STOP;
783 /* .. and parity */
784 #if 0
785 if ((tp->t_flags & (TF_ODDP | TF_EVENP)) == TF_EVENP)
786 value |= SCC_WR4_EVEN_PARITY;
787 value |= SCC_WR4_PARITY_ENABLE;
788 #else
789 if ((tp->t_flags & (TF_ODDP | TF_EVENP)) == TF_ODDP)
790 value |= SCC_WR4_PARITY_ENABLE;
791 #endif
793 /* set it now, remember it must be first after reset */
794 sr->wr4 = value;
795 scc_write_reg(regs, sccline, SCC_WR4, value);
797 /* vector again */
798 scc_write_reg(regs, sccline, SCC_WR2, 0xf0);
800 /* we only do 8 bits per char */
801 value = SCC_WR3_RX_8_BITS;
802 scc_write_reg(regs, sccline, SCC_WR3, value);
804 /* clear break, keep rts dtr */
805 value = sr->wr5 & (SCC_WR5_DTR|SCC_WR5_RTS);
806 value |= SCC_WR5_TX_8_BITS;
807 sr->wr5 = value;
808 scc_write_reg(regs, sccline, SCC_WR5, value);
810 scc_write_reg(regs, sccline, SCC_WR6, 0);
811 scc_write_reg(regs, sccline, SCC_WR7, 0);
813 scc_write_reg(regs, sccline, SCC_WR9, SCC_WR9_VIS);
815 scc_write_reg(regs, sccline, SCC_WR10, 0);
817 /* clock config */
818 value = SCC_WR11_RCLK_BAUDR | SCC_WR11_XTLK_BAUDR |
819 SCC_WR11_TRc_OUT | SCC_WR11_TRcOUT_BAUDR;
820 scc_write_reg(regs, sccline, SCC_WR11, value);
822 value = scc_speeds[tp->t_ispeed];
823 scc_set_timing_base(regs,sccline,value);
825 value = sr->wr14;
826 scc_write_reg(regs, sccline, SCC_WR14, value);
828 value = (scc->full_modem) ?
829 SCC_WR15_BREAK_IE | SCC_WR15_CTS_IE | SCC_WR15_DCD_IE :
830 SCC_WR15_BREAK_IE;
831 scc_write_reg(regs, sccline, SCC_WR15, value);
833 /* and now the enables */
834 value = SCC_WR3_RX_8_BITS | SCC_WR3_RX_ENABLE;
835 scc_write_reg(regs, sccline, SCC_WR3, value);
837 value = sr->wr5 | SCC_WR5_TX_ENABLE;
838 sr->wr5 = value;
839 scc_write_reg(regs, sccline, SCC_WR5, value);
841 /* master inter enable */
842 scc_write_reg(regs,sccline,SCC_WR9,SCC_WR9_MASTER_IE|SCC_WR9_VIS);
844 scc_write_reg(regs, sccline, SCC_WR1, sr->wr1);
849 * Modem control functions
851 scc_mctl(dev, bits, how)
852 int dev;
853 int bits, how;
855 return 0;
856 #if 0
857 register scc_regmap_t *regs;
858 int unit, sccline;
859 register int tcr, msr, brk, n_tcr, n_brk;
860 int b;
861 spl_t s;
862 scc_softc_t sc;
864 unit = dev;
865 sccline = unit & 3;
866 unit >>= 2;
867 mi_to_scc(&unit, &sccline);
869 /* no modem support on channel A */
870 /* XXX break on 0&1 */
871 if (sccline == SCC_CHANNEL_A)
872 return TM_LE | TM_DTR | TM_CTS | TM_CAR | TM_DSR;
874 scc = scc_softc[unit];
875 regs = scc->regs;
876 s = spltty();
878 ....some other day..
880 tcr = ((regs->scc_tcr | (scc->fake>>4)) & 0xf00) >> (8 + b*2);
881 brk = (scc->breaks >> (8 + (unit&3))) & 1; /* THE break bit */
883 n_tcr = (bits & (TM_RTS | TM_DTR)) >> 1;
884 n_brk = (bits & TM_BRK) >> 9;
886 /* break transitions, must 'send' a char out */
887 bits = (brk ^ n_brk) & 1;
889 switch (how) {
890 case DMSET:
891 tcr = n_tcr;
892 brk = n_brk;
893 break;
895 case DMBIS:
896 tcr |= n_tcr;
897 brk |= n_brk;
898 break;
900 case DMBIC:
901 tcr &= ~n_tcr;
902 brk = 0;
903 break;
905 case DMGET:
906 msr = ((regs->scc_msr | scc->fake) & 0xf0f) >> (b*8);
907 (void) splx(s);
908 return (tcr<<1)|/* DTR, RTS */
909 ((msr&1)<<5)|/* CTS */
910 ((msr&2)<<7)|/* DSR */
911 ((msr&0xc)<<4)|/* CD, RNG */
912 (brk << 9)|/* BRK */
913 TM_LE;
915 n_tcr = (regs->scc_tcr & ~(3 << (8 + b*2))) |
916 (tcr << (8 + b*2));
918 regs->scc_tcr = n_tcr;
919 scc->fake = (scc->fake & 0xf0f) | (n_tcr<<4&0xf000);
921 scc->breaks = (scc->breaks & ~(1 << (8 + (unit&3)))) |
922 (brk << (8 + (unit&3)));
923 if(bits) scc_putc( unit>>2, unit&3, 0);/* force break, now */
924 (void) splx(s);
925 return 0;/* useless to compute it */
926 #endif
929 scc_modem_intr(scc, chan)
931 /* nothing yet */
934 static check_car(
935 register struct tty *tp,
936 boolean_t car)
939 if (car) {
940 #if notyet
941 /* cancel modem timeout if need to */
942 if (car & (SCC_MSR_CD2 | SCC_MSR_CD3))
943 untimeout(scc_hup, (caddr_t)tp);
944 #endif
946 /* I think this belongs in the MI code */
947 if (tp->t_state & TS_WOPEN)
948 tp->t_state |= TS_ISOPEN;
949 /* carrier present */
950 if ((tp->t_state & TS_CARR_ON) == 0)
951 (void)ttymodem(tp, 1);
952 } else if ((tp->t_state&TS_CARR_ON) && ttymodem(tp, 0) == 0)
953 scc_mctl( tp->t_dev, TM_DTR, DMBIC);
957 * Periodically look at the CD signals:
958 * they do generate interrupts but we
959 * must fake them on channel A. We might
960 * also fake them on channel B.
962 scc_scan()
964 register i;
965 spl_t s = spltty();
967 for (i = 0; i < NSCC; i++) {
968 register scc_softc_t scc;
969 register int car;
970 register struct tty **tpp;
972 scc = scc_softc[i];
973 if (scc == 0)
974 continue;
975 car = scc->softCAR | scc->fake;
977 tpp = &console_tty[i * NSCC_LINE];
979 while (car) {
980 if (car & 1)
981 check_car(*tpp, 1);
982 tpp++;
983 car = car>>1;
987 splx(s);
988 timeout(scc_scan, (caddr_t)0, 5*hz);
992 #if 0 /* debug */
993 scc_rreg(unit,chan,n)
995 int val;
996 scc_read_reg(scc_softc[unit]->regs, chan, n, val);
997 return val;
1000 scc_wreg(unit,chan,n,val)
1002 scc_write_reg(scc_softc[unit]->regs, chan, n, val);
1005 scc_state(unit,soft)
1007 printf("{%d intr, A: R0 %x R1 %x R3 %x baudr %x R15 %x}\n",
1008 scc_intr_count,
1009 scc_rreg(unit, 1, SCC_RR0),
1010 scc_rreg(unit, 1, SCC_RR1),
1011 scc_rreg(unit, 1, SCC_RR3),
1012 (scc_rreg(unit, 1, SCC_RR13) << 8) | scc_rreg(unit, 1, SCC_RR12),
1013 scc_rreg(unit, 1, SCC_RR15));
1014 printf("{B: R0 %x R1 %x R2 %x baudr %x R15 %x}\n",
1015 scc_rreg(unit, 1, SCC_RR0),
1016 scc_rreg(unit, 1, SCC_RR1),
1017 scc_rreg(unit, 1, SCC_RR2),
1018 (scc_rreg(unit, 1, SCC_RR13) << 8) | scc_rreg(unit, 1, SCC_RR12),
1019 scc_rreg(unit, 1, SCC_RR15));
1020 if (soft) {
1021 struct softreg *sr;
1022 sr = scc_softc[unit]->softr;
1023 printf("{B: W1 %x W4 %x W5 %x W14 %x}",
1024 sr->wr1, sr->wr4, sr->wr5, sr->wr14);
1025 sr++;
1026 printf("{A: W1 %x W4 %x W5 %x W14 %x}\n",
1027 sr->wr1, sr->wr4, sr->wr5, sr->wr14);
1031 #endif
1033 #endif NSCC > 0