2ee01f7974f458ef3f446ddfe91981235d5306e3
* Copyright (c) 1992 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc.
* %sccs.include.redist.c%
* from: $Hdr: scc.c,v 4.300 91/06/09 06:44:53 root Rel41 $ SONY
* @(#)scc.c 7.1 (Berkeley) %G%
* LH8530 SCC (serial communication controller) driver
* NOTE: This driver is available only for news700/1200/1700/3400.
* Any code and mechanism in this module may not be used
* in any form without permissions. COPYRIGHT (C) 1989-
* SONY Corporation, Super Microsystems Group (SMSG),
* Work Station Division, all rights RESERVED.
#include "../include/fix_machine_type.h"
#include "../include/adrsmap.h"
#define VOLATILE volatile
int tty00_is_console
= 0;
char scc_buf
[2][SCC_BUFSIZE
];
register Scc_channel
*scc
= &sccsw
[chan
];
if ((scc
->scc_status
& CHAN_ACTIVE
) == 0) {
scc
->r_dma
.dma_addr
= scc_buf
[chan
];
malloc(SCC_BUFSIZE
, M_DEVBUF
, M_WAITOK
);
scc
->r_dma
.dma_count
= 0;
scc
->scc_status
|= CHAN_ACTIVE
;
VOLATILE
struct scc_reg
*port
= sccsw
[chan
].scc_port
;
temp
= scc_read_reg(chan
, RR12
);
scc_write_reg(chan
, WR12
, PROBE_DATA
);
probe
= scc_read_reg(chan
, RR12
);
scc_write_reg(chan
, WR12
, temp
);
return (probe
== PROBE_DATA
);
VOLATILE
struct scc_reg
*port
= sccsw
[chan
].scc_port
;
if (port
->ctrl
& R0_RxCA
) {
register VOLATILE
struct scc_reg
*port
= sccsw
[chan
].scc_port
;
while ((port
->ctrl
& R0_TxBE
) == 0)
register VOLATILE
struct scc_reg
*port
= sccsw
[chan
].scc_port
;
register VOLATILE u_char
*ctrl
= &sccsw
[chan
].scc_port
->ctrl
;
register VOLATILE u_char
*data
= &sccsw
[chan
].scc_port
->data
;
while ((*ctrl
& R0_TxBE
) == 0) {
*data
= (char)(c
& 0xff);
scc_write_reg(chan
, WR1
, W1_RxINT_ALL
|W1_TxINTE
|W1_EXTINTE
|W1_PARITY
);
register VOLATILE
struct scc_reg
*port
;
register Scc_channel
*scc
= &sccsw
[chan
];
for (i
= 0; i
< N_INITDATA
; i
++) {
scc_write_reg(chan
, WR2
, scc
->scc_vec
& ~0x0f);
This must be bug because scc->scc_param is not initialized yet.
scc_set_param(chan, scc->scc_param);
#define vec_to_scc(vec) ((((vec) - SCCVEC0) >> 3) & 0x000f)
#define vec_to_chan(vec) scc2chan[vec_to_scc(vec)]
int chan
= vec_to_chan(vec
);
Scc_channel
*scc
= &sccsw
[chan
];
register struct scc_reg
*port
= scc
->scc_port
;
if ((scc
->scc_status
& CHAN_ACTIVE
) == 0) {
while (port
->ctrl
& R0_RxCA
) {
if (xputc(c
, SCC_MOUSE
) < 0)
printf("mouse queue overflow\n");
softcall(_ms_helper
, (caddr_t
)0);
if (xputc(c
, SCC_KEYBOARD
) < 0)
printf("keyboard queue overflow\n");
softcall(kb_softint
, (caddr_t
)0);
printf("kb or ms stray intr\n");
int chan
= vec_to_chan(vec
);
register Scc_channel
*scc
= &sccsw
[chan
];
register VOLATILE
struct scc_reg
*port
= scc
->scc_port
;
if ((scc
->scc_status
& CHAN_ACTIVE
) == 0) {
if (scc
->scc_status
& LINE_BREAK
){
scc
->scc_status
&= ~LINE_BREAK
;
while (port
->ctrl
& R0_RxCA
) {
register Scc_channel
*scc
= &sccsw
[chan
];
if ((n
= scc
->r_dma
.dma_count
) > 0) {
scc
->r_dma
.dma_count
= 0;
rsrint(chan
, scc
->r_dma
.dma_addr
, n
);
scc
->scc_status
|= ENABLE
;
register Scc_channel
*scc
= &sccsw
[chan
];
if (scc
->r_dma
.dma_count
>= SCC_BUFSIZE
)
printf("rs%d soft fifo overflow\n", chan
);
scc
->r_dma
.dma_addr
[scc
->r_dma
.dma_count
++] = c
;
if (scc
->scc_status
& ENABLE
|| scc
->r_dma
.dma_count
>= SCC_BUFSIZE
) {
scc
->scc_status
&= ~ENABLE
;
n
= scc
->r_dma
.dma_count
;
scc
->r_dma
.dma_count
= 0;
rsrint(chan
, scc
->r_dma
.dma_addr
, n
);
int chan
= vec_to_chan(vec
);
register Scc_channel
*scc
= &sccsw
[chan
];
register VOLATILE
struct scc_reg
*port
= scc
->scc_port
;
if (scc
->scc_status
& OSTOP
)
scc
->scc_status
&= ~(OACTIVE
|OSTOP
);
if (scc
->scc_status
& OFLUSH
) {
scc
->x_dma
.dma_count
= 0;
scc
->scc_status
&= ~(OACTIVE
|OFLUSH
);
if ((scc
->scc_status
& OACTIVE
) && (scc
->x_dma
.dma_count
> 0)) {
port
->data
= *(scc
->x_dma
.dma_addr
)++;
port
->ctrl
= W0_RES_TxINT
;
scc
->scc_status
&= ~OACTIVE
;
if (scc
->x_dma
.dma_count
== 0)
int chan
= vec_to_chan(vec
);
register Scc_channel
*scc
= &sccsw
[chan
];
register VOLATILE
struct scc_reg
*port
= scc
->scc_port
;
if ((scc
->scc_status
& CHAN_ACTIVE
) == 0) {
scc
->scc_status
|= LINE_BREAK
;
if ((scc
->scc_param
& (DCD
|CTS
|RBREAK
)) != param
) {
scc
->scc_param
= (scc
->scc_param
& ~(DCD
|CTS
|RBREAK
)) | param
;
rssint(chan
, scc
->scc_param
);
int chan
= vec_to_chan(vec
);
register Scc_channel
*scc
= &sccsw
[chan
];
register VOLATILE
struct scc_reg
*port
= scc
->scc_port
;
if ((scc
->scc_status
& CHAN_ACTIVE
) == 0) {
status
= scc_read_reg(chan
, RR1
);
scc
->scc_param
|= FRAMING_ERROR
;
if ((scc
->scc_param
& OVERRUN_ERROR
) == 0) {
scc
->scc_param
|= OVERRUN_ERROR
;
rssint(chan
, scc
->scc_param
);
if (status
& R1_PARITY
) {
scc
->scc_param
|= SCC_PARITY_ERROR
;
while (port
->ctrl
& R0_RxCA
) {
if (scc
->scc_param
& NOCHECK
)
port
->ctrl
= W0_RES_ERROR
;
scc_write_reg(chan
, reg
, data
)
register VOLATILE
struct scc_reg
*port
= sccsw
[chan
].scc_port
;
register VOLATILE
struct scc_reg
*port
= sccsw
[chan
].scc_port
;
{ (char *)SCC_STATUS0
, RIA
, DSRA
},
{ (char *)SCC_STATUS0
, RIB
, DSRB
},
#if !defined(news1200) && !defined(news3200)
{ (char *)SCC_STATUS1
, RIC
, DSRC
},
{ (char *)SCC_STATUS1
, RID
, DSRD
},
{ (char *)SCC_STATUS1
, RIE
, DSRE
},
{ (char *)SCC_STATUS1
, RIF
, DSRF
},
{ (char *)SCC_STATUS2
, RIC
, DSRC
},
{ (char *)SCC_STATUS2
, RID
, DSRD
},
{ (char *)SCC_STATUS2
, RIE
, DSRE
},
{ (char *)SCC_STATUS2
, RIF
, DSRF
}
#endif /* !news1200 && !news3200 */
register struct ri_dsr
*p
;
register int status
, param
;
if ((status
& p
->ri
) == 0)
if ((status
& p
->dsr
) == 0)
* tc = floor(5000000 / 32 / baudrate - 2 + 0.5);
* tc0 = floor(4000000 / 32 / baudrate - 2 + 0.5);
#if defined(news1200) || defined(news3400)
* tc0 = floor(4915200 / 32 / baudrate - 2 + 0.5);
#endif /* news1200 || news3400 */
* tc1 = floor(3686400 / 32 / baudrate - 2 + 0.5);
scc_set_param(chan
, param
)
register Scc_channel
*scc
= &sccsw
[chan
];
register int bit
, baud
, *tc
;
* Baud rate / external clock
if ((baud
= param
& BAUD_RATE
) == EXTB
&& chan
<= SCC_REMOTE1
&&
scc_write_reg(chan
, WR11
, W11_RxC_RTxC
|W11_TxC_TRxC
);
tc
= (chan
<= SCC_REMOTE1
) ? tc0
: tc1
;
scc_write_reg(chan
, WR11
, W11_RxC_BRG
|W11_TxC_BRG
);
scc_write_reg(chan
, WR12
, tc
[baud
] & 0xff);
scc_write_reg(chan
, WR13
, tc
[baud
] >> 8);
* Clock mode / parity / stop bit
switch (param
& STOPBIT
) {
scc_write_reg(chan
, WR4
, bit
);
* Receiver enable / receive character size / auto enable
bit
= (param
& RXE
? W3_RxE
: 0);
switch (param
& CHAR_SIZE
) {
scc_write_reg(chan
, WR3
, bit
);
* Transmitter enable / transmit character size / RTS / DTR / BREAK
bit
= (param
& TXE
? W5_TxE
: 0);
switch (param
& CHAR_SIZE
) {
scc_write_reg(chan
, WR5
, bit
);
register Scc_channel
*scc
= &sccsw
[chan
];
scc
->scc_param
= (scc
->scc_param
& ~(RI
|DSR
)) | get_ri_dsr(chan
);
return (sccsw
[chan
].scc_status
);
scc_set_status(chan
, stat
)
sccsw
[chan
].scc_status
= stat
;
register Scc_channel
*scc
= &sccsw
[chan
];
if (scc
->scc_status
& OACTIVE
)
scc
->scc_status
|= OFLUSH
;
else if (scc
->x_dma
.dma_count
> 0) {
scc
->x_dma
.dma_count
= 0;
register Scc_channel
*scc
= &sccsw
[chan
];
if ((scc
->scc_status
& OACTIVE
) == 0 && scc
->x_dma
.dma_count
> 0) {
scc
->scc_port
->data
= *(scc
->x_dma
.dma_addr
)++;
scc
->scc_status
|= OACTIVE
;
register Scc_channel
*scc
= &sccsw
[chan
];
if (scc
->scc_status
& OACTIVE
)
scc
->scc_status
|= OSTOP
;
scc_write(chan
, buf
, count
)
register Scc_channel
*scc
= &sccsw
[chan
];
scc
->x_dma
.dma_addr
= buf
;
scc
->x_dma
.dma_count
= count
;
scc_error_write(chan
, buf
, count
)
for (i
= 0; i
< count
; i
++)
register Scc_channel
*scc
= &sccsw
[chan
];
while (scc_getc(chan
) != -1)
scc
->scc_status
&= ~CHAN_ACTIVE
;