⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scc.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
#ifndef lintstatic char *sccsid = "@(#)scc.c	4.8      (ULTRIX)  1/22/91";#endif	lint/************************************************************************ *									* *			Copyright (c) 1988,89 by			* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any	other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or	reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************ */* * scc.c * * SCC SLU console driver * * Modification history * * 21-Jan-1991 - Randall Brown *	Modified use of tc_isolate_memerr() to now use tc_memerr_status *	struct. * * 06-Dec-1990 - Randall Brown  *	Added the call to tc_isolate_memerr() in the dma_xerror routine to *	log error information about the memory error. * * 06-Nov-1990 - pgt *      Added disabling of baud rate generator before time constants are *      set. Fixed the setting of breaks. Modify dma interrupt routines *      to do appropriate masking. Fixed handling of Speed Indicate. *	Did general clean-up.  *  * 13-Sep-90 Joe Szczypek *	Added new TURBOchannel console ROM support.  osconsole environment *	variable now returns 1 slot number if serial line, else 2 slot number *	if graphics.  Use this to determine how to do setup.  Note that new *	ROMs do not support multiple outputs... * * 7-Sept-1990 - pgt  *	Enabled modem control and break interrupts. Also fixed sccparam *	and added macros to handle enabling and disabling of modem and *	interrupts. * * 16-Aug-1990 - Randall Brown *	Enable use of mouse and keyboard ports. * * 20-Feb-1990 - pgt (Philip Gapuz Te) * 	created file. * */#include "../machine/pte.h"#include "../h/param.h"#include "../h/systm.h"#include "../h/ioctl.h"#include "../h/tty.h"#include "../h/dir.h"#include "../h/user.h"#include "../h/proc.h"#include "../h/map.h"#include "../h/buf.h"#include "../h/vm.h"#include "../h/conf.h"#include "../h/file.h"#include "../h/uio.h"#include "../h/kernel.h"#include "../h/devio.h"#include "../../machine/common/cpuconf.h"#include "../h/exec.h"#include "../h/kmalloc.h"#include "../h/sys_tpath.h"#include "../io/uba/ubavar.h"	/* auto-config headers */#include "../machine/cpu.h"#include "../io/tc/ioasic.h"#include "../io/tc/sccreg.h"#include "../io/tc/slu.h"#include "../io/tc/vsxxx.h"#include "../io/tc/xcons.h"#include "../io/tc/tc.h"struct	tty scc_tty[NSCCLINE];   /* tty structure */struct  slu slu;  struct  scc_softc *sccsc;	/* software controller struct for scc */u_char	sccmodem[NSCCLINE];	/* keeps track of modem state */int     scc_cbaud[NSCCLINE];     /* baud rate integer flag */int     scc_brk[4];             /* break condition */struct	timeval scctimestamp[NSCCLINE];char	sccsoftCAR;char	sccdefaultCAR;int	scc_cnt = NSCCLINE;int	sccprobe(), sccattach(), scc_dma_rint();int	scc_dsr_check(), scc_tty_drop(), scc_cd_drop(); /* Modem */u_short	sccstd[] = { 0 };struct uba_device *sccinfo[1];struct uba_driver sccdriver = { sccprobe, 0, sccattach, 0, sccstd, "scc", 				  sccinfo };struct scc_softc scc_softc[1]; int	sccstart(), scc_dma_xint(), sccbaudrate();int	ttrstrt();int     sccspeedi(); scc_half_speed();/* * Graphics device driver entry points. * Used to call graphics device driver as needed. */extern	(*vs_gdopen)();extern	(*vs_gdclose)();extern	(*vs_gdread)();extern	(*vs_gdwrite)();extern	(*vs_gdselect)();extern	(*vs_gdkint)();extern	(*vs_gdioctl)();extern	(*vs_gdstop)();extern int (*v_consgetc)();extern int (*v_consputc)();extern int prom_getenv();#define GRAPHIC_DEV 0x2 /* pick up from pm header file later */#define LINEMASK	0x03		/* line unit mask */int scc_other[4] = { 3, 2, 1, 0 };/* ioasic register bits */u_long scc_xdma_en[4] = { 0, 0, SSR_COMM1_XEN, SSR_COMM2_XEN};u_long scc_rdma_en[4] = { 0, 0, SSR_COMM1_REN, SSR_COMM2_REN};u_long scc_xint[4] = { 0, 0, SIR_COMM1_XINT, SIR_COMM2_XINT };u_long scc_rint[4] = { 0, 0, SIR_COMM1_RINT, SIR_COMM2_RINT };u_long scc_xerror[4] = { 0, 0, SIR_COMM1_XERROR, SIR_COMM2_XERROR };u_long scc_rerror[4] = { 0, 0, SIR_COMM1_RERROR, SIR_COMM2_RERROR };/* * Baud Rate Support * * When the baud rate on the right is specified, the line parameter register * is setup with the appropriate bits as specified in the left column. */#define BAUD_UNSUPPORTED 0	/* Device does not provide this baud rate */#define BAUD_SUPPORTED   1	/* Device does provide this baud rate     *//* * The SCC manual provides a formula to compute the time constants for a * specified baudrate. For B110 and B134.5, the formula does not yield * whole integers. Thus, the chip baudrate in these two cases is very close * but not equal to the specified baudrate. */struct baud_support scc_speeds[] = {    {0,	                 0, 	                 BAUD_UNSUPPORTED}, /* B0    */    {SCC_WR12_B50_LO,    SCC_WR13_B50_HI,	 BAUD_SUPPORTED},   /* B50   */    {SCC_WR12_B75_LO,    SCC_WR13_B75_HI,	 BAUD_SUPPORTED},   /* B75   */    {SCC_WR12_B110_LO,   SCC_WR13_B110_HI,	 BAUD_SUPPORTED},   /* B110  */    {SCC_WR12_B134_5_LO, SCC_WR13_B134_5_HI,     BAUD_SUPPORTED},   /* B134  */    {SCC_WR12_B150_LO,   SCC_WR13_B150_HI,	 BAUD_SUPPORTED},   /* B150  */    {SCC_WR12_B200_LO,   SCC_WR13_B200_HI,	 BAUD_SUPPORTED},   /* B200  */    {SCC_WR12_B300_LO,   SCC_WR13_B300_HI,	 BAUD_SUPPORTED},   /* B300  */    {SCC_WR12_B600_LO,   SCC_WR13_B600_HI,	 BAUD_SUPPORTED},   /* B600  */    {SCC_WR12_B1200_LO,  SCC_WR13_B1200_HI,	 BAUD_SUPPORTED},   /* B1200 */    {SCC_WR12_B1800_LO,  SCC_WR13_B1800_HI,	 BAUD_SUPPORTED},   /* B1800 */    {SCC_WR12_B2400_LO,  SCC_WR13_B2400_HI,	 BAUD_SUPPORTED},   /* B2400 */    {SCC_WR12_B4800_LO,  SCC_WR13_B4800_HI,	 BAUD_SUPPORTED},   /* B4800 */    {SCC_WR12_B9600_LO,  SCC_WR13_B9600_HI,	 BAUD_SUPPORTED},   /* B9600 */    {SCC_WR12_B19200_LO, SCC_WR13_B19200_HI,     BAUD_SUPPORTED},   /* EXTA  */    {SCC_WR12_B38400_LO, SCC_WR13_B38400_HI,     BAUD_SUPPORTED},   /* EXTB  */};extern int 	consDev;#define SCC0_B_BASE (PHYS_TO_K1(0x1c100000))#define SCC0_A_BASE (PHYS_TO_K1(0x1c100008))#define SCC1_B_BASE (PHYS_TO_K1(0x1c180000))#define SCC1_A_BASE (PHYS_TO_K1(0x1c180008))#define SCC_READ(rsp, reg, val)   { \	     (rsp)->SCC_CMD = ((u_short)(reg))<<8; \	     (val) = (((rsp)->SCC_CMD)>>8)&0xff; \		 DELAY(10);\	     }#define SCC_WRITE(rsp, reg, val)  { \	     (rsp)->SCC_CMD = ((u_short)(reg))<<8; \	     (rsp)->SCC_CMD = ((u_short)(val))<<8; \		 DELAY(10);\	     }/* these macros can only set or clear one bit at a time */#define SCC_MSET(unit, bit) { \	     sccsc->sc_saved_regs[(unit)].wr5 |= (bit); \	     SCC_WRITE(sccsc->sc_regs[(unit)], SCC_WR5, \		       sccsc->sc_saved_regs[(unit)].wr5); \             }#define SCC_MCLR(unit, bit)   { \	     sccsc->sc_saved_regs[(unit)].wr5 &= ~(bit); \	     SCC_WRITE(sccsc->sc_regs[(unit)], SCC_WR5, \		       sccsc->sc_saved_regs[(unit)].wr5); \             }#define SCC_MTEST(unit, bit)  (((sccsc->sc_regs[(unit)]->SCC_CMD)>>8)&(bit))/* DTR makes use of the DTR of channel A, controlled by WR5 */#define SCC_SET_DTR(unit)   SCC_MSET(scc_other[(unit)], SCC_WR5_DTR)#define SCC_CLR_DTR(unit)   SCC_MCLR(scc_other[(unit)], SCC_WR5_DTR)#define SCC_SET_RTS(unit)   SCC_MSET(scc_other[(unit)], SCC_WR5_RTS)#define SCC_CLR_RTS(unit)   SCC_MCLR(scc_other[(unit)], SCC_WR5_RTS)#define	SCC_SET_SS(unit)    SCC_MSET((unit), SCC_WR5_RTS)#define	SCC_CLR_SS(unit)    SCC_MCLR((unit), SCC_WR5_RTS)#define SCC_SET_BRK(unit)   SCC_MSET((unit), SCC_WR5_BRK)#define SCC_CLR_BRK(unit)   SCC_MCLR((unit), SCC_WR5_BRK)#define SCC_DSR(unit)   SCC_MTEST(scc_other[(unit)], SCC_RR0_SYNC)#define SCC_CTS(unit)   SCC_MTEST((unit), SCC_RR0_CTS)#define SCC_DCD(unit)   SCC_MTEST((unit), SCC_RR0_DCD)#define SCC_SI(unit)	SCC_MTEST(scc_other[(unit)], SCC_RR0_CTS)#define SCC_RI(unit)	SCC_MTEST(scc_other[(unit)], SCC_RR0_DCD)#define SCC_XMIT(unit)  (SCC_DSR(scc_other[(unit)]) && SCC_CTS((unit)) && SCC_DCD((unit)))#define SCC_DTR(unit) ((sccsc->sc_saved_regs[scc_other[(unit)]].wr5)&SCC_WR5_DTR)#define SCC_RTS(unit) ((sccsc->sc_saved_regs[scc_other[(unit)]].wr5)&SCC_WR5_RTS)#define SCC_MODEM_ON(unit)  { \	SCC_WRITE(sccsc->sc_regs[scc_other[(unit)]], SCC_WR15, SCC_WR15_SYNC_IE); \	sccsc->sc_regs[scc_other[(unit)]]->SCC_CMD = SCC_WR0_RESET_EXT_INT<<8; \	sccsc->sc_regs[scc_other[(unit)]]->SCC_CMD = SCC_WR0_RESET_EXT_INT<<8; \	SCC_WRITE(sccsc->sc_regs[(unit)], SCC_WR15, (SCC_WR15_CTS_IE|SCC_WR15_DCD_IE|SCC_WR15_BREAK_IE)); \        sccsc->sc_regs[(unit)]->SCC_CMD = SCC_WR0_RESET_EXT_INT<<8; \	sccsc->sc_regs[(unit)]->SCC_CMD = SCC_WR0_RESET_EXT_INT<<8; \    }#define SCC_MODEM_OFF(unit)  { \	SCC_WRITE(sccsc->sc_regs[scc_other[(unit)]], SCC_WR15, 0x00); \	sccsc->sc_regs[scc_other[(unit)]]->SCC_CMD = SCC_WR0_RESET_EXT_INT<<8; \	sccsc->sc_regs[scc_other[(unit)]]->SCC_CMD = SCC_WR0_RESET_EXT_INT<<8; \	SCC_WRITE(sccsc->sc_regs[(unit)], SCC_WR15, SCC_WR15_BREAK_IE); \	sccsc->sc_regs[(unit)]->SCC_CMD = SCC_WR0_RESET_EXT_INT<<8; \	sccsc->sc_regs[(unit)]->SCC_CMD = SCC_WR0_RESET_EXT_INT<<8; \    }#define SCC_INT_ON(unit) { \	if ((unit) == 0 || (unit) == 1) { \	    sccsc->sc_saved_regs[(unit)].wr1 &= ~SCC_WR1_RINT; \	    sccsc->sc_saved_regs[(unit)].wr1 |= SCC_WR1_RINT_ALL; \	    SCC_WRITE(sccsc->sc_regs[(unit)], SCC_WR1, sccsc->sc_saved_regs[(unit)].wr1); \        } else { \	    sccsc->sc_saved_regs[scc_other[(unit)]].wr1 |= SCC_WR1_EXT_IE; \	    SCC_WRITE(sccsc->sc_regs[scc_other[(unit)]], SCC_WR1, sccsc->sc_saved_regs[scc_other[(unit)]].wr1); \	    sccsc->sc_saved_regs[(unit)].wr1 &= ~SCC_WR1_RINT; \	    sccsc->sc_saved_regs[(unit)].wr1 |= (SCC_WR1_RINT_SPC| SCC_WR1_EXT_IE| SCC_WR1_WDMA_EN); \	    SCC_WRITE(sccsc->sc_regs[(unit)], SCC_WR1, sccsc->sc_saved_regs[(unit)].wr1); \        } \    }#define PRINT_SIGNALS() { cprintf("Modem signals: "); \	if (SCC_DSR(2)) cprintf(" DSR2 "); \	if (SCC_CTS(2)) cprintf(" CTS2 "); \	if (SCC_DCD(2)) cprintf(" CD2 "); \	if (SCC_SI(2)) cprintf(" SI2 "); \	if (SCC_RI(2)) cprintf(" RI2 "); \	if (SCC_DSR(3)) cprintf(" DSR3 "); \	if (SCC_CTS(3)) cprintf(" CTS3 "); \	if (SCC_DCD(3)) cprintf(" CD3 "); \	if (SCC_SI(3)) cprintf(" SI3 "); \	if (SCC_RI(3)) cprintf(" RI3 "); \	cprintf("\n"); }#define PRINT_SIR(sir) { \	    if ((sir) & SIR_COMM1_RINT)  cprintf("R1 "); \	    if ((sir) & SIR_COMM2_RINT)  cprintf("R2 "); \	    if ((sir) & SIR_COMM1_XINT)  cprintf("X1 "); \	    if ((sir) & SIR_COMM2_XINT)  cprintf("X2 "); \	    }#define PRINT_SSR(line) { \	    if ((*(u_int *)(0xbc040100)) & scc_rdma_en[(line)]) \	      cprintf("SSR: RDMA Enabled: %d\n", (line)); \	    }sccprobe(reg)     int reg;{    /* the intialization is done through scc_cons_init, so     * if we have gotten this far we are alive so return a 1     */    return(1);}sccattach(){    register struct scc_softc *sc = sccsc;    register int i;    register struct scc_reg *rsp, *rsp0;    register struct scc_saved_reg *ssp, *ssp0;    sccsoftCAR = 0xff;    sccdefaultCAR = 0xff;    scc_init(2);    if (consDev == GRAPHIC_DEV)        scc_init(3);    for (i = 2; i < 4; i++) {	SCC_CLR_DTR(i);          /* clear modem control signals */	SCC_CLR_RTS(i);	SCC_CLR_SS(i);/* * pgt: can not use IOC_CLR(reg, mask) to clear system interrupt register bits  * because bits may change between the time the register value is saved and  * the time it is written back with the mask. See ioasic.h for definition. */	IOC_WR(IOC_SIR, ~scc_rint[i]);	IOC_WR(IOC_SIR, ~scc_xerror[i]);	IOC_WR(IOC_SIR, ~scc_rerror[i]);	/* set rdma ptr, enable rdma */	sc->ioc_regs[i]->RDMA_REG = (u_long)(svtophy(sc->rbuf[i][sc->rflag[i]]				     + SCC_HALF_PAGE - SCC_WORD) << 3);	IOC_SET(IOC_SSR, scc_rdma_en[i]);    }}/* * scc_init() sets the SCC modes */scc_init(unit)     register int unit;{    register struct scc_softc *sc = sccsc;    register struct scc_reg *rsp, *rsp0;    register struct scc_saved_reg *ssp, *ssp0;    register int line = unit;        rsp = sc->sc_regs[line];    ssp = &sc->sc_saved_regs[line];        /*     * set modes:     *   WR9   force hardware reset     *   WR4   line 1: odd parity, one stop bit, x16 clock     *         lines 0, 2, 3: ~no parity, one stop bit, x16 clock     *   WR1   ~W/DMA: DMA request, receive; parity is special condition     *   WR2   interrupt vector 0x00     *   WR3   8 bits/char     *   WR5   8 bits/char     *   WR9   interrupt disabled 0x00     *   WR10  NRZ     *   WR11  tx & rx clocks = brgen, TRxC input, RTxC ~no xtal     *   WR12  low time constant     *   WR13  hi time constant     *         baud rate: line 0 or 1: 4800 baud     *                    line 2 or 3: 9600 baud     *   WR14  brgen source = pclk     *         line 2 or 3: channel B: ~DTR/REQ: request function, transmit     *                      channel A: ~DTR/REQ: ~DTR function     */    if (line == 0 || line == 1) {	SCC_WRITE(rsp, SCC_WR9, SCC_WR9_RESETA);            } else {        SCC_WRITE(rsp, SCC_WR9, SCC_WR9_RESETB);            }/* rpbfix : do we need to delay this long ???? */    DELAY(20);    if (line == 1 )  {              /* odd parity for mouse */         ssp->wr4 = ( SCC_WR4_PENABLE | SCC_WR4_ONESB | SCC_WR4_CLOCK16);	SCC_WRITE(rsp, SCC_WR4, ssp->wr4);    } else {                        /* no parity for mouse and comm. ports */        ssp->wr4 = (SCC_WR4_ONESB | SCC_WR4_CLOCK16);	SCC_WRITE(rsp, SCC_WR4, ssp->wr4);    }    ssp->wr1 = (SCC_WR1_DMA_REQ | SCC_WR1_WDMA_RX | SCC_WR1_PSPC);    SCC_WRITE(rsp, SCC_WR1, ssp->wr1);    SCC_WRITE(rsp, SCC_WR2, 0xf0);     /* interrupt vector 0x00 */    ssp->wr3 = SCC_WR3_RBITS8;    SCC_WRITE(rsp, SCC_WR3, ssp->wr3);    ssp->wr5 = SCC_WR5_TBITS8;    SCC_WRITE(rsp, SCC_WR5, ssp->wr5);     SCC_WRITE(rsp, SCC_WR9, 0x00);     /*  WR9 interrupt disabled */    SCC_WRITE(rsp, SCC_WR10, SCC_WR10_NRZ);     /*      * TRxC pin should be an input because we can not allow output from      * the TRxC pin for asynchronous communication. See SCC manual.      */    SCC_WRITE(rsp, SCC_WR11, SCC_WR11_TxC_BRGEN | SCC_WR11_RxC_BRGEN);	          if (line == 0 || line == 1) {  /* keyboard or mouse 4800 BPS */        SCC_WRITE(rsp, SCC_WR12, SCC_WR12_B4800_LO);	SCC_WRITE(rsp, SCC_WR13, SCC_WR13_B4800_HI);    } else {                       /* 9600 BPS */        SCC_WRITE(rsp, SCC_WR12, SCC_WR12_B9600_LO);	SCC_WRITE(rsp, SCC_WR13, SCC_WR13_B9600_HI);    }     if (line == 0 || line == 1) {  /* channel A - keyboard or mouse */        ssp->wr14 = SCC_WR14_BRGEN_PCLK;	SCC_WRITE(rsp, SCC_WR14, ssp->wr14);    } else {         /*	 * Communication ports 1 & 2 use the A channels of the mouse and	 * keyboard respectively. Since the ~DTR/REQ bit selects DTR when it	 * is zero, no need to do anything here.	 */	ssp->wr14 = (SCC_WR14_BRGEN_PCLK | SCC_WR14_REQ);	SCC_WRITE(rsp, SCC_WR14, ssp->wr14);    }    SCC_WRITE(rsp, SCC_WR9, SCC_WR9_MIE);}scc_cons_init(){    extern int (*vcons_init[])();    extern int rex_base;    int i;    register struct scc_reg *rsp;    register struct scc_softc *sc;    register struct scc_saved_reg *ssp;    int scc_mouse_init(), scc_mouse_putc(), scc_mouse_getc();    int scc_kbd_init(), scc_kbd_putc(), scc_kbd_getc(), scc_putc();    sccsc = &scc_softc[0];        sc = sccsc;    sc->sc_regs[0] = (struct scc_reg *)SCC1_A_BASE;    sc->sc_regs[1] = (struct scc_reg *)SCC0_A_BASE;    sc->sc_regs[2] = (struct scc_reg *)SCC0_B_BASE;    sc->sc_regs[3] = (struct scc_reg *)SCC1_B_BASE;    sc->ioc_regs[2] = (struct ioc_reg *)IOC_COMM1_DMA_BASE;    sc->ioc_regs[3] = (struct ioc_reg *)IOC_COMM2_DMA_BASE;    for (i = 2; i < 4; i++) {        KM_ALLOC(sc->tbuf[i], char *, SCC_PAGE_SIZE, KM_DEVBUF, KM_CLEAR);	KM_ALLOC(sc->rbuf[i][0], char *, SCC_PAGE_SIZE, KM_DEVBUF, (KM_CLEAR | KM_NOCACHE));	KM_ALLOC(sc->rbuf[i][1], char *, SCC_PAGE_SIZE, KM_DEVBUF, (KM_CLEAR | KM_NOCACHE));	sc->rflag[i] = 0;    }    /*     *     * Query the prom. The prom can be set such that the user      * could use either the alternate tty or the graphics console.     * You get the graphics console if the first bit is set in     * osconsole.  The user sets the console variable

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -