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

📄 l1.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* $Id$ * * This file is subject to the terms and conditions of the GNU General Public * License.  See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. * Copyright (C) 2000 by Colin Ngam *//* In general, this file is organized in a hierarchy from lower-level * to higher-level layers, as follows: * *	UART routines *	Bedrock/L1 "PPP-like" protocol implementation *	System controller "message" interface (allows multiplexing *		of various kinds of requests and responses with *		console I/O) *	Console interfaces (there are two): *	  (1) "elscuart", used in the IP35prom and (maybe) some *		debugging situations elsewhere, and *	  (2) "l1_cons", the glue that allows the L1 to act *		as the system console for the stdio libraries * * Routines making use of the system controller "message"-style interface * can be found in l1_command.c.  Their names are leftover from early SN0,  * when the "module system controller" (msc) was known as the "entry level * system controller" (elsc).  The names and signatures of those functions  * remain unchanged in order to keep the SN0 -> SN1 system controller * changes fairly localized. */#include <linux/types.h>#include <linux/config.h>#include <linux/slab.h>#include <asm/sn/sgi.h>#include <asm/sn/iograph.h>#include <asm/sn/invent.h>#include <asm/sn/hcl.h>#include <asm/sn/hcl_util.h>#include <asm/sn/labelcl.h>#include <asm/sn/eeprom.h>#include <asm/sn/ksys/i2c.h>#include <asm/sn/cmn_err.h>#include <asm/sn/router.h>#include <asm/sn/module.h>#include <asm/sn/ksys/l1.h>#include <asm/sn/nodepda.h>#include <asm/sn/clksupport.h>#include <asm/sn/sn1/uart16550.h>#if defined(EEPROM_DEBUG)#define db_printf(x) printk x#else#define db_printf(x)#endif// From irix/kern/sys/SN/SN1/bdrkhspecregs.h#define    HSPEC_UART_0              0x00000080    /* UART Registers         *//********************************************************************* * Hardware-level (UART) driver routines. *//* macros for reading/writing registers */#define LD(x)		(*(volatile uint64_t *)(x))#define SD(x, v)        (LD(x) = (uint64_t) (v))/* location of uart receive/xmit data register */#define L1_UART_BASE(n)	((ulong)REMOTE_HSPEC_ADDR((n), HSPEC_UART_0))#define LOCAL_HUB	LOCAL_HUB_ADDR#define ADDR_L1_REG(n, r)	\    (L1_UART_BASE(n) | ( (r) << 3 ))#define READ_L1_UART_REG(n, r) \    ( LD(ADDR_L1_REG((n), (r))) )#define WRITE_L1_UART_REG(n, r, v) \    ( SD(ADDR_L1_REG((n), (r)), (v)) )/* Avoid conflicts with symmon...*/#define CONS_HW_LOCK(x)#define CONS_HW_UNLOCK(x)#define L1_CONS_HW_LOCK(sc)	CONS_HW_LOCK(sc->uart == BRL1_LOCALUART)#define L1_CONS_HW_UNLOCK(sc)	CONS_HW_UNLOCK(sc->uart == BRL1_LOCALUART)#if DEBUGstatic int debuglock_ospl; /* For CONS_HW_LOCK macro */#endif/* UART-related #defines */#define UART_BAUD_RATE		57600#define UART_FIFO_DEPTH		16#define UART_DELAY_SPAN		10#define UART_PUTC_TIMEOUT	50000#define UART_INIT_TIMEOUT	100000/* error codes */#define UART_SUCCESS		  0#define UART_TIMEOUT		(-1)#define UART_LINK		(-2)#define UART_NO_CHAR		(-3)#define UART_VECTOR		(-4)#ifdef BRINGUP#define UART_DELAY(x)	{ int i; i = x * 1000; while (--i); }#else#define UART_DELAY(x)	us_delay(x)#endif/* *	Some macros for handling Endian-ness */#ifdef	LITTLE_ENDIAN#define COPY_INT_TO_BUFFER(_b, _i, _n)		\	{					\		_b[_i++] = (_n >> 24) & 0xff;	\		_b[_i++] = (_n >> 16) & 0xff;	\		_b[_i++] = (_n >>  8) & 0xff;	\		_b[_i++] =  _n        & 0xff;	\	}#define COPY_BUFFER_TO_INT(_b, _i, _n)		\	{					\		_n  = (_b[_i++] << 24) & 0xff;	\		_n |= (_b[_i++] << 16) & 0xff;	\		_n |= (_b[_i++] <<  8) & 0xff;	\		_n |=  _b[_i++]        & 0xff;	\	}#define COPY_BUFFER_TO_BUFFER(_b, _i, _bn)	\	{					\	    char *_xyz = (char *)_bn;		\	    _xyz[3] = _b[_i++];			\	    _xyz[2] = _b[_i++];			\	    _xyz[1] = _b[_i++];			\	    _xyz[0] = _b[_i++];			\	}#else	/* BIG_ENDIAN */#define COPY_INT_TO_BUFFER(_b, _i, _n)			\	{						\		bcopy((char *)&_n, _b, sizeof(_n));	\		_i += sizeof(_n);			\	}#define COPY_BUFFER_TO_INT(_b, _i, _n)			\	{						\		bcopy(&_b[_i], &_n, sizeof(_n));	\		_i += sizeof(_n);			\	}#define COPY_BUFFER_TO_BUFFER(_b, _i, _bn)		\	{						\            bcopy(&(_b[_i]), _bn, sizeof(int));		\            _i += sizeof(int);				\	}#endif	/* LITTLE_ENDIAN */int atomicAddInt(int *int_ptr, int value);int atomicClearInt(int *int_ptr, int value);void kmem_free(void *where, int size);#define BCOPY(x,y,z)	memcpy(y,x,z)extern char *bcopy(const char * src, char * dest, int count);int get_L1_baud(void){    return UART_BAUD_RATE;}/* uart driver functions */static voiduart_delay( rtc_time_t delay_span ){    UART_DELAY( delay_span );}#define UART_PUTC_READY(n)	(READ_L1_UART_REG((n), REG_LSR) & LSR_XHRE)static intuart_putc( l1sc_t *sc ) {#ifdef BRINGUP    /* need a delay to avoid dropping chars */    UART_DELAY(57);#endif    WRITE_L1_UART_REG( sc->nasid, REG_DAT,		       sc->send[sc->sent] );    return UART_SUCCESS;}static intuart_getc( l1sc_t *sc ){    u_char lsr_reg = 0;    nasid_t nasid = sc->nasid;    if( (lsr_reg = READ_L1_UART_REG( nasid, REG_LSR )) & 	(LSR_RCA | LSR_PARERR | LSR_FRMERR) )     {	if( lsr_reg & LSR_RCA ) 	    return( (u_char)READ_L1_UART_REG( nasid, REG_DAT ) );	else if( lsr_reg & (LSR_PARERR | LSR_FRMERR) ) {	    return UART_LINK;	}    }    return UART_NO_CHAR;}#define PROM_SER_CLK_SPEED	12000000#define PROM_SER_DIVISOR(x)	(PROM_SER_CLK_SPEED / ((x) * 16))static voiduart_init( l1sc_t *sc, int baud ){    rtc_time_t expire;    int clkdiv;    nasid_t nasid;    clkdiv = PROM_SER_DIVISOR(baud);    expire = rtc_time() + UART_INIT_TIMEOUT;    nasid = sc->nasid;        /* make sure the transmit FIFO is empty */    while( !(READ_L1_UART_REG( nasid, REG_LSR ) & LSR_XSRE) ) {	uart_delay( UART_DELAY_SPAN );	if( rtc_time() > expire ) {	    break;	}    }    L1_CONS_HW_LOCK( sc );    WRITE_L1_UART_REG( nasid, REG_LCR, LCR_DLAB );	uart_delay( UART_DELAY_SPAN );    WRITE_L1_UART_REG( nasid, REG_DLH, (clkdiv >> 8) & 0xff );	uart_delay( UART_DELAY_SPAN );    WRITE_L1_UART_REG( nasid, REG_DLL, clkdiv & 0xff );	uart_delay( UART_DELAY_SPAN );    /* set operating parameters and set DLAB to 0 */    WRITE_L1_UART_REG( nasid, REG_LCR, LCR_BITS8 | LCR_STOP1 );	uart_delay( UART_DELAY_SPAN );    WRITE_L1_UART_REG( nasid, REG_MCR, MCR_RTS | MCR_AFE );	uart_delay( UART_DELAY_SPAN );    /* disable interrupts */    WRITE_L1_UART_REG( nasid, REG_ICR, 0x0 );	uart_delay( UART_DELAY_SPAN );    /* enable FIFO mode and reset both FIFOs */    WRITE_L1_UART_REG( nasid, REG_FCR, FCR_FIFOEN );	uart_delay( UART_DELAY_SPAN );    WRITE_L1_UART_REG( nasid, REG_FCR,	FCR_FIFOEN | FCR_RxFIFO | FCR_TxFIFO );    L1_CONS_HW_UNLOCK( sc );}static voiduart_intr_enable( l1sc_t *sc, u_char mask ){    u_char lcr_reg, icr_reg;    nasid_t nasid = sc->nasid;    L1_CONS_HW_LOCK(sc);    /* make sure that the DLAB bit in the LCR register is 0     */    lcr_reg = READ_L1_UART_REG( nasid, REG_LCR );    lcr_reg &= ~(LCR_DLAB);    WRITE_L1_UART_REG( nasid, REG_LCR, lcr_reg );    /* enable indicated interrupts     */    icr_reg = READ_L1_UART_REG( nasid, REG_ICR );    icr_reg |= mask;    WRITE_L1_UART_REG( nasid, REG_ICR, icr_reg /*(ICR_RIEN | ICR_TIEN)*/ );    L1_CONS_HW_UNLOCK(sc);}static voiduart_intr_disable( l1sc_t *sc, u_char mask ){    u_char lcr_reg, icr_reg;    nasid_t nasid = sc->nasid;    L1_CONS_HW_LOCK(sc);    /* make sure that the DLAB bit in the LCR register is 0     */    lcr_reg = READ_L1_UART_REG( nasid, REG_LCR );    lcr_reg &= ~(LCR_DLAB);    WRITE_L1_UART_REG( nasid, REG_LCR, lcr_reg );    /* enable indicated interrupts     */    icr_reg = READ_L1_UART_REG( nasid, REG_ICR );    icr_reg &= mask;    WRITE_L1_UART_REG( nasid, REG_ICR, icr_reg /*(ICR_RIEN | ICR_TIEN)*/ );    L1_CONS_HW_UNLOCK(sc);}#define uart_enable_xmit_intr(sc) \	uart_intr_enable((sc), ICR_TIEN)#define uart_disable_xmit_intr(sc) \        uart_intr_disable((sc), ~(ICR_TIEN))#define uart_enable_recv_intr(sc) \        uart_intr_enable((sc), ICR_RIEN)#define uart_disable_recv_intr(sc) \        uart_intr_disable((sc), ~(ICR_RIEN))/********************************************************************* * Routines for accessing a remote (router) UART */#define READ_RTR_L1_UART_REG(p, n, r, v)		\    {							\	if( vector_read_node( (p), (n), 0,		\			      RR_JBUS1(r), (v) ) ) {	\	    return UART_VECTOR;				\	}						\    }#define WRITE_RTR_L1_UART_REG(p, n, r, v)		\    {							\	if( vector_write_node( (p), (n), 0,		\			       RR_JBUS1(r), (v) ) ) {	\	    return UART_VECTOR;				\	}						\    }#ifdef SABLE#define RTR_UART_PUTC_TIMEOUT	0#define RTR_UART_DELAY_SPAN	0#define RTR_UART_INIT_TIMEOUT	0#else#define RTR_UART_PUTC_TIMEOUT	UART_PUTC_TIMEOUT*10#define RTR_UART_DELAY_SPAN	UART_DELAY_SPAN#define RTR_UART_INIT_TIMEOUT	UART_INIT_TIMEOUT*10#endifstatic intrtr_uart_putc( l1sc_t *sc ){    uint64_t regval, c;    nasid_t nasid = sc->nasid;    net_vec_t path = sc->uart;    rtc_time_t expire = rtc_time() + RTR_UART_PUTC_TIMEOUT;        c = (sc->send[sc->sent] & 0xffULL);        while( 1 )     {        /* Check for "tx hold reg empty" bit. */	READ_RTR_L1_UART_REG( path, nasid, REG_LSR, &regval );	if( regval & LSR_XHRE )	{	    WRITE_RTR_L1_UART_REG( path, nasid, REG_DAT, c );	    return UART_SUCCESS;	}	if( rtc_time() >= expire ) 	{	    return UART_TIMEOUT;	}	uart_delay( RTR_UART_DELAY_SPAN );    }}static intrtr_uart_getc( l1sc_t *sc ){    uint64_t regval;    nasid_t nasid = sc->nasid;    net_vec_t path = sc->uart;    READ_RTR_L1_UART_REG( path, nasid, REG_LSR, &regval );    if( regval & (LSR_RCA | LSR_PARERR | LSR_FRMERR) )    {	if( regval & LSR_RCA )	{	    READ_RTR_L1_UART_REG( path, nasid, REG_DAT, &regval );	    return( (int)regval );	}	else	{	    return UART_LINK;	}    }    return UART_NO_CHAR;}static intrtr_uart_init( l1sc_t *sc, int baud ){    rtc_time_t expire;    int clkdiv;    nasid_t nasid;    net_vec_t path;    uint64_t regval;    clkdiv = PROM_SER_DIVISOR(baud);    expire = rtc_time() + RTR_UART_INIT_TIMEOUT;    nasid = sc->nasid;    path = sc->uart;    /* make sure the transmit FIFO is empty */    while(1) {	READ_RTR_L1_UART_REG( path, nasid, REG_LSR, &regval );	if( regval & LSR_XSRE ) {	    break;	}	if( rtc_time() > expire ) {	    break;	}	uart_delay( RTR_UART_DELAY_SPAN );    }    WRITE_RTR_L1_UART_REG( path, nasid, REG_LCR, LCR_DLAB  );	uart_delay( UART_DELAY_SPAN );    WRITE_RTR_L1_UART_REG( path, nasid, REG_DLH, (clkdiv >> 8) & 0xff  );	uart_delay( UART_DELAY_SPAN );    WRITE_RTR_L1_UART_REG( path, nasid, REG_DLL, clkdiv & 0xff  );	uart_delay( UART_DELAY_SPAN );    /* set operating parameters and set DLAB to 0 */    WRITE_RTR_L1_UART_REG( path, nasid, REG_LCR, LCR_BITS8 | LCR_STOP1  );	uart_delay( UART_DELAY_SPAN );    WRITE_RTR_L1_UART_REG( path, nasid, REG_MCR, MCR_RTS | MCR_AFE  );	uart_delay( UART_DELAY_SPAN );    /* disable interrupts */    WRITE_RTR_L1_UART_REG( path, nasid, REG_ICR, 0x0  );	uart_delay( UART_DELAY_SPAN );    /* enable FIFO mode and reset both FIFOs */    WRITE_RTR_L1_UART_REG( path, nasid, REG_FCR, FCR_FIFOEN  );	uart_delay( UART_DELAY_SPAN );    WRITE_RTR_L1_UART_REG( path, nasid, REG_FCR,	FCR_FIFOEN | FCR_RxFIFO | FCR_TxFIFO );    return 0;}    	/********************************************************************* * locking macros  */#define L1SC_SEND_LOCK(l,pl)						\     { if( (l)->uart == BRL1_LOCALUART )				\	 (pl) = mutex_spinlock_spl( &((l)->send_lock), spl7 ); }#define L1SC_SEND_UNLOCK(l,pl)				\     { if( (l)->uart == BRL1_LOCALUART )		\	 mutex_spinunlock( &((l)->send_lock), (pl)); }#define L1SC_RECV_LOCK(l,pl)						\     { if( (l)->uart == BRL1_LOCALUART )				\	 (pl) = mutex_spinlock_spl( &((l)->recv_lock), spl7 ); }

⌨️ 快捷键说明

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