summaryrefslogtreecommitdiff
path: root/chips/scc_8530_hdw.c
diff options
context:
space:
mode:
Diffstat (limited to 'chips/scc_8530_hdw.c')
-rw-r--r--chips/scc_8530_hdw.c1145
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 68c6e9d..0000000
--- 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