diff options
Diffstat (limited to 'chips/scc_8530_hdw.c')
-rw-r--r-- | chips/scc_8530_hdw.c | 1145 |
1 files changed, 0 insertions, 1145 deletions
diff --git a/chips/scc_8530_hdw.c b/chips/scc_8530_hdw.c deleted file mode 100644 index 68c6e9d2..00000000 --- a/chips/scc_8530_hdw.c +++ /dev/null @@ -1,1145 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1993-1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * File: scc_8530_hdw.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 6/91 - * - * Hardware-level operations for the SCC Serial Line Driver - */ - -#include <scc.h> -#if NSCC > 0 -#include <bm.h> -#include <platforms.h> - -#include <mach_kdb.h> - -#include <machine/machspl.h> /* spl definitions */ -#include <mach/std_types.h> -#include <device/io_req.h> -#include <device/tty.h> - -#include <chips/busses.h> -#include <chips/serial_defs.h> -#include <chips/screen_defs.h> - -/* Alignment and padding */ -#if defined(DECSTATION) -/* - * 3min's padding - */ -typedef struct { - char pad0; - volatile unsigned char datum; - char pad1[2]; -} scc_padded1_register_t; - -#define scc_register_t scc_padded1_register_t -#endif - -#if defined(FLAMINGO) -typedef struct { - volatile unsigned int datum; - unsigned int pad1; -} scc_padded1_register_t; - -#define scc_register_t scc_padded1_register_t - -#define scc_set_datum(d,v) (d) = (volatile unsigned int) (v) << 8, wbflush() -#define scc_get_datum(d,v) (v) = ((d) >> 8) & 0xff - -#endif - -#include <chips/scc_8530.h> /* needs the above defs */ - -#define private static -#define public - -/* - * Forward decls - */ -private check_car( struct tty *, boolean_t ); - -/* - * On the 3min keyboard and mouse come in on channels A - * of the two units. The MI code expects them at 'lines' - * 0 and 1, respectively. So we map here back and forth. - * Note also the MI code believes unit 0 has four lines. - */ - -#define SCC_KBDUNIT 1 -#define SCC_PTRUNIT 0 - -mi_to_scc(unitp, linep) - int *unitp, *linep; -{ - /* only play games on MI 'unit' 0 */ - if (*unitp) { - /* e.g. by mapping the first four lines specially */ - *unitp++; - return; - } - - /* always get unit=0 (console) and line = 0|1 */ - if (*linep == SCREEN_LINE_KEYBOARD) { - *unitp = SCC_KBDUNIT; - *linep = SCC_CHANNEL_A; - } else if (*linep == SCREEN_LINE_POINTER) { - *unitp = SCC_PTRUNIT; - *linep = SCC_CHANNEL_A; - } else { - *unitp = (*linep & 1); - *linep = SCC_CHANNEL_B; - } -/* line 0 is channel B, line 1 is channel A */ -} - -#define NSCC_LINE 2 /* 2 ttys per chip */ - -/* only care for mapping to ttyno */ -scc_to_mi(sccunit, sccline) -{ - if (sccunit > 1) - return (sccunit * NSCC_LINE + sccline); - /* only for console (first pair of SCCs): */ - if (sccline == SCC_CHANNEL_A) - return ((!sccunit) & 1); - return 2+sccunit; -} - - -/* - * Driver status - */ -struct scc_softc { - scc_regmap_t *regs; - - /* software copy of some write regs, for reg |= */ - struct softreg { - unsigned char wr1; - unsigned char wr4; - unsigned char wr5; - unsigned char wr14; - } softr[2]; /* per channel */ - - unsigned char last_rr0[2]; /* for modem signals */ - unsigned short fake; /* missing rs232 bits, channel A */ - char polling_mode; - char softCAR, osoftCAR; - char probed_once; - - boolean_t full_modem; - boolean_t isa_console; - -} scc_softc_data[NSCC]; - -typedef struct scc_softc *scc_softc_t; - -scc_softc_t scc_softc[NSCC]; - -scc_softCAR(unit, line, on) -{ - mi_to_scc(&unit, &line); - if (on) - scc_softc[unit]->softCAR |= 1<<line; - else - scc_softc[unit]->softCAR &= ~(1 << line); -} - - -/* - * BRG formula is: - * ClockFrequency - * BRGconstant = --------------------------- - 2 - * 2 * BaudRate * ClockDivider - */ -/* Speed selections with Pclk=7.3728Mhz, clock x16 */ -static -short scc_speeds[] = - /* 0 50 75 110 134.5 150 200 300 600 1200 1800 2400 */ - { 0, 4606, 3070, 2093, 1711, 1534, 1150, 766, 382, 190, 126, 94, - - /* 4800 9600 19.2k 38.4k */ - 46, 22, 10, 4}; - -/* - * Definition of the driver for the auto-configuration program. - */ - -int scc_probe(), scc_intr(); -static void scc_attach(); - -vm_offset_t scc_std[NSCC] = { 0 }; -struct bus_device *scc_info[NSCC]; -struct bus_driver scc_driver = - { scc_probe, 0, scc_attach, 0, scc_std, "scc", scc_info,}; - -/* - * Adapt/Probe/Attach functions - */ -boolean_t scc_uses_modem_control = FALSE;/* patch this with adb */ - -set_scc_address( - int sccunit, - vm_offset_t regs, - boolean_t has_modem, - boolean_t isa_console) -{ - extern int scc_probe(), scc_param(), scc_start(), - scc_putc(), scc_getc(), - scc_pollc(), scc_mctl(), scc_softCAR(); - - scc_std[sccunit] = regs; - scc_softc_data[sccunit].full_modem = has_modem & scc_uses_modem_control; - scc_softc_data[sccunit].isa_console = isa_console; - - /* Do this here */ - console_probe = scc_probe; - console_param = scc_param; - console_start = scc_start; - console_putc = scc_putc; - console_getc = scc_getc; - console_pollc = scc_pollc; - console_mctl = scc_mctl; - console_softCAR = scc_softCAR; - -} - -scc_probe( - int xxx, - struct bus_device *ui) -{ - int sccunit = ui->unit; - scc_softc_t scc; - register int val; - register scc_regmap_t *regs; - - regs = (scc_regmap_t *)scc_std[sccunit]; - if (regs == 0) - return 0; - - /* - * See if we are here - */ - if (check_memory(regs, 0)) { - /* no rides today */ - return 0; - } - - scc = &scc_softc_data[sccunit]; - - if (scc->probed_once++){ - return 1; - } - /* - * Chip once-only initialization - * - * NOTE: The wiring we assume is the one on the 3min: - * - * out A-TxD --> TxD keybd or mouse - * in A-RxD --> RxD keybd or mouse - * out A-DTR~ --> DTR comm - * out A-RTS~ --> RTS comm - * in A-CTS~ --> SI comm - * in A-DCD~ --> RI comm - * in A-SYNCH~--> DSR comm - * out B-TxD --> TxD comm - * in B-RxD --> RxD comm - * in B-RxC --> TRxCB comm - * in B-TxC --> RTxCB comm - * out B-RTS~ --> SS comm - * in B-CTS~ --> CTS comm - * in B-DCD~ --> CD comm - */ - - scc_softc[sccunit] = scc; - scc->regs = regs; - - scc->fake = 1<<SCC_CHANNEL_A; - - { - register int i; - /* We need this in scc_start only, hence the funny - value: we need it non-zero and we want to avoid - too much overhead in getting to (scc,regs,line) */ - for (i = 0; i < NSCC_LINE; i++) { - register struct tty *tp; - - tp = console_tty[scc_to_mi(sccunit,i)]; - tp->t_addr = (char*)(0x80000000L + (sccunit<<1) + (i&1)); - /* do min buffering */ - tp->t_state |= TS_MIN; - } - } - - /* make sure reg pointer is in known state */ - scc_init_reg(regs, SCC_CHANNEL_A); - scc_init_reg(regs, SCC_CHANNEL_B); - - /* reset chip, fully */ - scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_HW_RESET); - delay(50000);/*enough ? */ - scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR9, 0); - - /* program the interrupt vector */ - scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR2, 0xf0); - scc_write_reg(regs, SCC_CHANNEL_B, SCC_WR2, 0xf0); - scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_VIS); - - /* most of the init is in scc_param() */ - - /* timing base defaults */ - scc->softr[SCC_CHANNEL_A].wr4 = SCC_WR4_CLK_x16; - scc->softr[SCC_CHANNEL_B].wr4 = SCC_WR4_CLK_x16; - - /* enable DTR, RTS and dont SS */ -#if 0 - /* According to one book I have this signal (pin 23, "SS") - is "specified by the provider", meaning the EIA-232-D - standard does not define what it is. Better leave - it alone */ - scc->softr[SCC_CHANNEL_B].wr5 = SCC_WR5_RTS; -#else - scc->softr[SCC_CHANNEL_B].wr5 = 0; -#endif - scc->softr[SCC_CHANNEL_A].wr5 = SCC_WR5_RTS | SCC_WR5_DTR; - - /* baud rates */ - val = SCC_WR14_BAUDR_ENABLE|SCC_WR14_BAUDR_SRC; - scc->softr[SCC_CHANNEL_B].wr14 = val; - scc->softr[SCC_CHANNEL_A].wr14 = val; - - /* interrupt conditions */ - val = SCC_WR1_RXI_ALL_CHAR | SCC_WR1_PARITY_IE | - SCC_WR1_EXT_IE | SCC_WR1_TX_IE; - scc->softr[SCC_CHANNEL_A].wr1 = val; - scc->softr[SCC_CHANNEL_B].wr1 = val; - - scc_read_reg_zero(regs, SCC_CHANNEL_A, scc->last_rr0[SCC_CHANNEL_A]); - scc_read_reg_zero(regs, SCC_CHANNEL_B, scc->last_rr0[SCC_CHANNEL_B]); - - /* - * After probing, any line that should be active - * (keybd,mouse,rcline) is activated via scc_param(). - */ - - scc_set_modem_control(scc, scc->full_modem); - -#if defined(KMIN) || defined (FLAMINGO) || defined(KN03) - /* - * Crock: MI code knows of unit 0 as console, we need - * unit 1 as well since the keyboard is there - * This is acceptable on maxine, which has to call its - * only one chip unit 1 so that rconsole is happy. - */ - if (sccunit == 0) { - struct bus_device d; - d = *ui; - d.unit = 1; - scc_probe( xxx, &d); - } -#endif - return 1; -} - -boolean_t scc_timer_started = FALSE; - -static void -scc_attach( - register struct bus_device *ui) -{ - int sccunit = ui->unit; - extern scc_scan(); - extern int tty_inq_size; - int i; - - /* We only have 4 ttys, but always at 9600 - * Give em a lot of room (plus dma..) - */ - tty_inq_size = 4096; - if (!scc_timer_started) { - /* do all of them, before we call scc_scan() */ - /* harmless if done already */ - for (i = 0; i < NSCC*NSCC_LINE; i++) - ttychars(console_tty[i]); - - scc_timer_started = TRUE; - scc_scan(); - } - -#if NBM > 0 - if (SCREEN_ISA_CONSOLE() && scc_softc[sccunit]->isa_console) { - printf("\n sl0: "); - if (sccunit && rcline == 3) printf("( rconsole )"); - - if (sccunit == SCC_KBDUNIT) { - printf("\n sl1: "); lk201_attach(0, sccunit >> 1); - } else if (sccunit == SCC_PTRUNIT) { - printf("\n sl1: "); mouse_attach(0, sccunit >> 1); - } - } else -#endif /*NBM > 0*/ - { - printf("%s", (sccunit == 1) ? - "\n sl0: ( alternate console )\n sl1:" : - "\n sl0:\n sl1:"); - } -} - -/* - * Would you like to make a phone call ? - */ -scc_set_modem_control( - scc_softc_t scc, - boolean_t on) -{ - if (on) - /* your problem if the hardware then is broke */ - scc->fake = 0; - else - scc->fake = 3; - scc->full_modem = on; - /* user should do an scc_param() ifchanged */ -} - -/* - * Polled I/O (debugger) - */ -scc_pollc( - int unit, - boolean_t on) -{ - scc_softc_t scc; - int line = SCREEN_LINE_KEYBOARD, - sccunit = unit; - - mi_to_scc(&sccunit, &line); - - scc = scc_softc[sccunit]; - if (on) { - scc->polling_mode++; -#if NBM > 0 - screen_on_off(unit, TRUE); -#endif NBM > 0 - } else - scc->polling_mode--; -} - -/* - * Interrupt routine - */ -int scc_intr_count; - -scc_intr( - int unit, - spl_t spllevel) -{ - scc_softc_t scc = scc_softc[unit]; - register scc_regmap_t *regs = scc->regs; - register int rr1, rr2; - register int c; - -scc_intr_count++; - -#if mips - splx(spllevel); /* lower priority */ -#endif - - while (1) { - - scc_read_reg(regs, SCC_CHANNEL_B, SCC_RR2, rr2); - - rr2 = SCC_RR2_STATUS(rr2); - - /* are we done yet ? */ - if (rr2 == 6) { /* strange, distinguished value */ - register int rr3; - scc_read_reg(regs, SCC_CHANNEL_A, SCC_RR3, rr3); - if (rr3 == 0) - return; - } - - if ((rr2 == SCC_RR2_A_XMIT_DONE) || (rr2 == SCC_RR2_B_XMIT_DONE)) { - - register chan = (rr2 == SCC_RR2_A_XMIT_DONE) ? - SCC_CHANNEL_A : SCC_CHANNEL_B; - - scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS); - c = cons_simple_tint(scc_to_mi(unit,chan), FALSE); - - if (c == -1) { - /* no more data for this line */ - - scc_read_reg(regs, chan, SCC_RR15, c); - c &= ~SCC_WR15_TX_UNDERRUN_IE; - scc_write_reg(regs, chan, SCC_WR15, c); - - c = scc->softr[chan].wr1 & ~SCC_WR1_TX_IE; - scc_write_reg(regs, chan, SCC_WR1, c); - scc->softr[chan].wr1 = c; - - c = cons_simple_tint(scc_to_mi(unit,chan), TRUE); - if (c != -1) - /* funny race, scc_start has been called already */ - scc_write_data(regs, chan, c); - } else { - scc_write_data(regs, chan, c); - /* and leave it enabled */ - } - } - - else if (rr2 == SCC_RR2_A_RECV_DONE) { - int err = 0; - - scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS); - if (scc->polling_mode) - continue; - - scc_read_data(regs, SCC_CHANNEL_A, c); - rr1 = scc_to_mi(unit,SCC_CHANNEL_A); - cons_simple_rint (rr1, rr1, c, 0); - } - - else if (rr2 == SCC_RR2_B_RECV_DONE) { - int err = 0; - - scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS); - if (scc->polling_mode) - continue; - - scc_read_data(regs, SCC_CHANNEL_B, c); - rr1 = scc_to_mi(unit,SCC_CHANNEL_B); - cons_simple_rint (rr1, rr1, c, 0); - } - - else if ((rr2 == SCC_RR2_A_EXT_STATUS) || (rr2 == SCC_RR2_B_EXT_STATUS)) { - int chan = (rr2 == SCC_RR2_A_EXT_STATUS) ? - SCC_CHANNEL_A : SCC_CHANNEL_B; - scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_EXT_IP); - scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS); - scc_modem_intr(scc, chan, unit); - } - - else if ((rr2 == SCC_RR2_A_RECV_SPECIAL) || (rr2 == SCC_RR2_B_RECV_SPECIAL)) { - register int chan = (rr2 == SCC_RR2_A_RECV_SPECIAL) ? - SCC_CHANNEL_A : SCC_CHANNEL_B; - - scc_read_reg(regs, chan, SCC_RR1, rr1); - if (rr1 & (SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN | SCC_RR1_FRAME_ERR)) { - int err; - /* map to CONS_ERR_xxx MI error codes */ - err = ((rr1 & SCC_RR1_PARITY_ERR)<<8) | - ((rr1 & SCC_RR1_RX_OVERRUN)<<9) | - ((rr1 & SCC_RR1_FRAME_ERR)<<7); - scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_ERROR); - rr1 = scc_to_mi(unit,chan); - cons_simple_rint(rr1, rr1, 0, err); - } - scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS); - } - - } - -} - -boolean_t -scc_start( - struct tty *tp) -{ - register scc_regmap_t *regs; - register int chan, temp; - register struct softreg *sr; - - temp = (natural_t)tp->t_addr; - chan = (temp & 1); /* channel */ - temp = (temp >> 1)&0xff;/* sccunit */ - regs = scc_softc[temp]->regs; - sr = &scc_softc[temp]->softr[chan]; - - scc_read_reg(regs, chan, SCC_RR15, temp); - temp |= SCC_WR15_TX_UNDERRUN_IE; - scc_write_reg(regs, chan, SCC_WR15, temp); - - temp = sr->wr1 | SCC_WR1_TX_IE; - scc_write_reg(regs, chan, SCC_WR1, temp); - sr->wr1 = temp; - - /* but we need a first char out or no cookie */ - scc_read_reg(regs, chan, SCC_RR0, temp); - if (temp & SCC_RR0_TX_EMPTY) - { - register char c; - - c = getc(&tp->t_outq); - scc_write_data(regs, chan, c); - } -} - -/* - * Get a char from a specific SCC line - * [this is only used for console&screen purposes] - */ -scc_getc( - int unit, - int line, - boolean_t wait, - boolean_t raw) -{ - scc_softc_t scc; - register scc_regmap_t *regs; - unsigned char c; - int value, mi_line, rcvalue, from_line; - - mi_line = line; - mi_to_scc(&unit, &line); - - scc = scc_softc[unit]; - regs = scc->regs; - - /* - * wait till something available - * - * NOTE: we know! that rcline==3 - */ - if (rcline) rcline = 3; -again: - rcvalue = 0; - while (1) { - scc_read_reg_zero(regs, line, value); - if (rcline && (mi_line == SCREEN_LINE_KEYBOARD)) { - scc_read_reg_zero(regs, SCC_CHANNEL_B, rcvalue); - value |= rcvalue; - } - if (((value & SCC_RR0_RX_AVAIL) == 0) && wait) - delay(10); - else - break; - } - - /* - * if nothing found return -1 - */ - from_line = (rcvalue & SCC_RR0_RX_AVAIL) ? SCC_CHANNEL_B : line; - - if (value & SCC_RR0_RX_AVAIL) { - scc_read_reg(regs, from_line, SCC_RR1, value); - scc_read_data(regs, from_line, c); - } else { -/* splx(s);*/ - return -1; - } - - /* - * bad chars not ok - */ - if (value&(SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN | SCC_RR1_FRAME_ERR)) { -/* scc_state(unit,from_line); */ - scc_write_reg(regs, from_line, SCC_RR0, SCC_RESET_ERROR); - if (wait) { - scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS); - goto again; - } - } - scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS); -/* splx(s);*/ - - -#if NBM > 0 - if ((mi_line == SCREEN_LINE_KEYBOARD) && (from_line == SCC_CHANNEL_A) && - !raw && SCREEN_ISA_CONSOLE() && scc->isa_console) - return lk201_rint(SCREEN_CONS_UNIT(), c, wait, scc->polling_mode); - else -#endif NBM > 0 - return c; -} - -/* - * Put a char on a specific SCC line - */ -scc_putc( - int unit, - int line, - int c) -{ - scc_softc_t scc; - register scc_regmap_t *regs; - spl_t s = spltty(); - register int value; - - mi_to_scc(&unit, &line); - - scc = scc_softc[unit]; - regs = scc->regs; - - do { - scc_read_reg(regs, line, SCC_RR0, value); - if (value & SCC_RR0_TX_EMPTY) - break; - delay(100); - } while (1); - - scc_write_data(regs, line, c); -/* wait for it to swallow the char ? */ - - splx(s); -} - -scc_param( - struct tty *tp, - int line) -{ - scc_regmap_t *regs; - int value, sccline, unit; - struct softreg *sr; - scc_softc_t scc; - - line = tp->t_dev; - /* MI code wants us to handle 4 lines on unit 0 */ - unit = (line < 4) ? 0 : (line / NSCC_LINE); - sccline = line; - mi_to_scc(&unit, &sccline); - - if ((scc = scc_softc[unit]) == 0) return; /* sanity */ - regs = scc->regs; - - sr = &scc->softr[sccline]; - - /* - * Do not let user fool around with kbd&mouse - */ -#if NBM > 0 - if (screen_captures(line)) { - tp->t_ispeed = tp->t_ospeed = B4800; - tp->t_flags |= TF_LITOUT; - } -#endif NBM > 0 - - if (tp->t_ispeed == 0) { - (void) scc_mctl(tp->t_dev, TM_HUP, DMSET); /* hang up line */ - return; - } - - /* reset line */ - value = (sccline == SCC_CHANNEL_A) ? SCC_WR9_RESET_CHA_A : SCC_WR9_RESET_CHA_B; - scc_write_reg(regs, sccline, SCC_WR9, value); - delay(25); - - /* stop bits, normally 1 */ - value = sr->wr4 & 0xf0; - value |= (tp->t_ispeed == B110) ? SCC_WR4_2_STOP : SCC_WR4_1_STOP; - - /* .. and parity */ - if ((tp->t_flags & (TF_ODDP | TF_EVENP)) == TF_ODDP) - value |= SCC_WR4_PARITY_ENABLE; - - /* set it now, remember it must be first after reset */ - sr->wr4 = value; - scc_write_reg(regs, sccline, SCC_WR4, value); - - /* vector again */ - scc_write_reg(regs, sccline, SCC_WR2, 0xf0); - - /* we only do 8 bits per char */ - value = SCC_WR3_RX_8_BITS; - scc_write_reg(regs, sccline, SCC_WR3, value); - - /* clear break, keep rts dtr */ - value = sr->wr5 & (SCC_WR5_DTR|SCC_WR5_RTS); - value |= SCC_WR5_TX_8_BITS; - sr->wr5 = value; - scc_write_reg(regs, sccline, SCC_WR5, value); - /* some are on the other channel, which might - never be used (e.g. maxine has only one line) */ - { - register int otherline = (sccline+1)&1; - - scc_write_reg(regs, otherline, SCC_WR5, scc->softr[otherline].wr5); - } - - scc_write_reg(regs, sccline, SCC_WR6, 0); - scc_write_reg(regs, sccline, SCC_WR7, 0); - - scc_write_reg(regs, sccline, SCC_WR9, SCC_WR9_VIS); - - scc_write_reg(regs, sccline, SCC_WR10, 0); - - /* clock config */ - value = SCC_WR11_RCLK_BAUDR | SCC_WR11_XTLK_BAUDR | - SCC_WR11_TRc_OUT | SCC_WR11_TRcOUT_BAUDR; - scc_write_reg(regs, sccline, SCC_WR11, value); - - value = scc_speeds[tp->t_ispeed]; - scc_set_timing_base(regs,sccline,value); - - value = sr->wr14; - scc_write_reg(regs, sccline, SCC_WR14, value); - -#if FLAMINGO - if (unit != 1) -#else - if (1) -#endif - { - /* Chan-A: CTS==SI DCD==RI DSR=SYNCH */ - value = SCC_WR15_CTS_IE | SCC_WR15_DCD_IE | SCC_WR15_SYNCHUNT_IE; - scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR15, value); - - /* Chan-B: CTS==CTS DCD==DCD */ - value = SCC_WR15_BREAK_IE | SCC_WR15_CTS_IE | SCC_WR15_DCD_IE; - scc_write_reg(regs, SCC_CHANNEL_B, SCC_WR15, value); - } else { - /* Here if modem bits are floating noise, keep quiet */ - value = SCC_WR15_BREAK_IE; - scc_write_reg(regs, sccline, SCC_WR15, value); - } - - /* and now the enables */ - value = SCC_WR3_RX_8_BITS | SCC_WR3_RX_ENABLE; - scc_write_reg(regs, sccline, SCC_WR3, value); - - value = sr->wr5 | SCC_WR5_TX_ENABLE; - sr->wr5 = value; - scc_write_reg(regs, sccline, SCC_WR5, value); - - /* master inter enable */ - scc_write_reg(regs,sccline,SCC_WR9,SCC_WR9_MASTER_IE|SCC_WR9_VIS); - - scc_write_reg(regs, sccline, SCC_WR1, sr->wr1); - -} - -/* - * Modem control functions - */ -scc_mctl( - int dev, - int bits, - int how) -{ - register scc_regmap_t *regs; - struct softreg *sra, *srb, *sr; - int unit, sccline; - int b = 0; - spl_t s; - scc_softc_t scc; - - /* MI code wants us to handle 4 lines on unit 0 */ - unit = (dev < 4) ? 0 : (dev / NSCC_LINE); - sccline = dev; - mi_to_scc(&unit, &sccline); - - if ((scc = scc_softc[unit]) == 0) return 0; /* sanity */ - regs = scc->regs; - - sr = &scc->softr[sccline]; - sra = &scc->softr[SCC_CHANNEL_A]; - srb = &scc->softr[SCC_CHANNEL_B]; - - if (bits == TM_HUP) { /* close line (internal) */ - bits = TM_DTR | TM_RTS; - how = DMBIC; - /* xxx interrupts too ?? */ - } - - if (bits & TM_BRK) { - switch (how) { - case DMSET: - case DMBIS: - sr->wr5 |= SCC_WR5_SEND_BREAK; - break; - case DMBIC: - sr->wr5 &= ~SCC_WR5_SEND_BREAK; - break; - default: - goto dontbrk; - } - s = spltty(); - scc_write_reg(regs, sccline, SCC_WR5, sr->wr5); - splx(s); -dontbrk: - b |= (sr->wr5 & SCC_WR5_SEND_BREAK) ? TM_BRK : 0; - } - - /* no modem support on channel A */ - if (sccline == SCC_CHANNEL_A) - return (b | TM_LE | TM_DTR | TM_CTS | TM_CAR | TM_DSR); - - sra = &scc->softr[SCC_CHANNEL_A]; - srb = &scc->softr[SCC_CHANNEL_B]; - -#if 0 - /* do I need to do something on this ? */ - if (bits & TM_LE) { /* line enable */ - } -#endif - - if (bits & (TM_DTR|TM_RTS)) { /* data terminal ready, request to send */ - register int w = 0; - - if (bits & TM_DTR) w |= SCC_WR5_DTR; - if (bits & TM_RTS) w |= SCC_WR5_RTS; - - switch (how) { - case DMSET: - case DMBIS: - sra->wr5 |= w; - break; - case DMBIC: - sra->wr5 &= ~w; - break; - default: - goto dontdtr; - } - s = spltty(); - scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR5, sra->wr5); - splx(s); -dontdtr: - b |= (sra->wr5 & w) ? (bits & (TM_DTR|TM_RTS)) : 0; - } - - s = spltty(); - -#if 0 - /* Unsupported */ - if (bits & TM_ST) { /* secondary transmit */ - } - if (bits & TM_SR) { /* secondary receive */ - } -#endif - - if (bits & TM_CTS) { /* clear to send */ - register int value; - scc_read_reg(regs, SCC_CHANNEL_B, SCC_RR0, value); - b |= (value & SCC_RR0_CTS) ? TM_CTS : 0; - } - - if (bits & TM_CAR) { /* carrier detect */ - register int value; - scc_read_reg(regs, SCC_CHANNEL_B, SCC_RR0, value); - b |= (value & SCC_RR0_DCD) ? TM_CAR : 0; - } - - if (bits & TM_RNG) { /* ring */ - register int value; - scc_read_reg(regs, SCC_CHANNEL_A, SCC_RR0, value); - b |= (value & SCC_RR0_DCD) ? TM_RNG : 0; - } - - if (bits & TM_DSR) { /* data set ready */ - register int value; - scc_read_reg(regs, SCC_CHANNEL_A, SCC_RR0, value); - b |= (value & SCC_RR0_SYNCH) ? TM_DSR : 0; - } - - splx(s); - - return b; -} - -#define debug 0 - -scc_modem_intr( - scc_softc_t scc, - int chan, - int unit) -{ - register int value, changed; - - scc_read_reg_zero(scc->regs, chan, value); - - /* See what changed */ - changed = value ^ scc->last_rr0[chan]; - scc->last_rr0[chan] = value; - -#if debug -printf("sccmodem: chan %c now %x, changed %x : ", - (chan == SCC_CHANNEL_B) ? 'B' : 'A', - value, changed); -#endif - - if (chan == SCC_CHANNEL_A) { - if (changed & SCC_RR0_CTS) { - /* Speed indicator, ignore XXX */ -#if debug -printf("%s-speed ", (value & SCC_RR0_CTS) ? "Full" : "Half"); -#endif - } - if (changed & SCC_RR0_DCD) { - /* Ring indicator */ -#if debug -printf("Ring "); -#endif - } - if (changed & SCC_RR0_SYNCH) { - /* Data Set Ready */ -#if debug -printf("DSR "); -#endif - /* If modem went down then CD will also go down, - or it did already. - If modem came up then we have to wait for CD - anyways before enabling the line. - Either way, nothing to do here */ - } - } else { - if (changed & SCC_RR0_CTS) { - /* Clear To Send */ -#if debug -printf("CTS "); -#endif - tty_cts(console_tty[scc_to_mi(unit,chan)], - value & SCC_RR0_CTS); - } - if (changed & SCC_RR0_DCD) { -#if debug -printf("CD "); -#endif - check_car(console_tty[scc_to_mi(unit,chan)], - value & SCC_RR0_DCD); - } - } -#if debug -printf(".\n"); -#endif -} - -private check_car( - register struct tty *tp, - boolean_t car) - -{ - if (car) { -#if notyet - /* cancel modem timeout if need to */ - if (car & (SCC_MSR_CD2 | SCC_MSR_CD3)) - untimeout(scc_hup, (vm_offset_t)tp); -#endif - - /* I think this belongs in the MI code */ - if (tp->t_state & TS_WOPEN) - tp->t_state |= TS_ISOPEN; - /* carrier present */ - if ((tp->t_state & TS_CARR_ON) == 0) - (void)ttymodem(tp, 1); - } else if ((tp->t_state&TS_CARR_ON) && ttymodem(tp, 0) == 0) - scc_mctl( tp->t_dev, TM_DTR, DMBIC); -} - -/* - * Periodically look at the CD signals: - * they do generate interrupts but we - * must fake them on channel A. We might - * also fake them on channel B. - */ -scc_scan() -{ - register i; - spl_t s = spltty(); - - for (i = 0; i < NSCC; i++) { - register scc_softc_t scc; - register int car; - register struct tty **tpp; - - scc = scc_softc[i]; - if (scc == 0) - continue; - car = scc->softCAR | scc->fake; - - tpp = &console_tty[i * NSCC_LINE]; - - while (car) { - if (car & 1) - check_car(*tpp, 1); - tpp++; - car = car>>1; - } - - } - splx(s); - timeout(scc_scan, (vm_offset_t)0, 5*hz); -} - - -#if debug -scc_rr0(unit,chan) -{ - int val; - scc_read_reg_zero(scc_softc[unit]->regs, chan, val); - return val; -} - -scc_rreg(unit,chan,n) -{ - int val; - scc_read_reg(scc_softc[unit]->regs, chan, n, val); - return val; -} - -scc_wreg(unit,chan,n,val) -{ - scc_write_reg(scc_softc[unit]->regs, chan, n, val); -} - -scc_state(unit,soft) -{ - int rr0, rr1, rr3, rr12, rr13, rr15; - - rr0 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR0); - rr1 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR1); - rr3 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR3); - rr12 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR12); - rr13 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR13); - rr15 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR15); - printf("{%d intr, A: R0 %x R1 %x R3 %x baudr %x R15 %x}\n", - scc_intr_count, rr0, rr1, rr3, - (rr13 << 8) | rr12, rr15); - - rr0 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR0); - rr1 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR1); - rr3 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR2); - rr12 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR12); - rr13 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR13); - rr15 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR15); - printf("{B: R0 %x R1 %x R2 %x baudr %x R15 %x}\n", - rr0, rr1, rr3, - (rr13 << 8) | rr12, rr15); - - if (soft) { - struct softreg *sr; - sr = scc_softc[unit]->softr; - printf("{B: W1 %x W4 %x W5 %x W14 %x}", - sr->wr1, sr->wr4, sr->wr5, sr->wr14); - sr++; - printf("{A: W1 %x W4 %x W5 %x W14 %x}\n", - sr->wr1, sr->wr4, sr->wr5, sr->wr14); - } -} - -#endif - -#endif NSCC > 0 |