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

📄 l1.c

📁 microwindows移植到S3C44B0的源码
💻 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-2002 Silicon Graphics, Inc.  All rights reserved. *//* 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 interface: *	  "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. */#include <linux/types.h>#include <linux/config.h>#include <linux/slab.h>#include <linux/spinlock.h>#include <linux/delay.h>#include <asm/sn/sgi.h>#include <asm/sn/io.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/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/sn_sal.h>#include <asm/sn/sn_cpuid.h>#include <asm/sn/uart16550.h>#include <asm/sn/simulator.h>#if defined(CONFIG_IA64_SGI_SN2)#define USE_SAL_CONSOLE_IO	1	/* DON'T un-def this for the simulator... */#endif/* Make all console writes atomic */#define SYNC_CONSOLE_WRITE	1/********************************************************************* * 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 */#if defined(CONFIG_IA64_SGI_SN1)#define L1_UART_BASE(n)		((ulong)REMOTE_HSPEC_ADDR((n), 0x00000080))#define LOCK_HUB		REMOTE_HUB_ADDR#elif defined(CONFIG_IA64_SGI_SN2)#define L1_UART_BASE(n)		((ulong)REMOTE_HUB((n), SH_JUNK_BUS_UART0))#define LOCK_HUB		REMOTE_HUBtypedef u64 rtc_time_t;#endif#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)) )/* upper layer interface calling methods */#define SERIAL_INTERRUPT_MODE	0#define SERIAL_POLLED_MODE	1/* 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)#define UART_DELAY(x)		udelay(x)/* Some debug counters */#define L1C_INTERRUPTS		0#define L1C_OUR_R_INTERRUPTS	1#define L1C_OUR_X_INTERRUPTS	2#define L1C_SEND_CALLUPS	3#define L1C_RECEIVE_CALLUPS	4#define L1C_SET_BAUD		5#define L1C_ALREADY_LOCKED	L1C_SET_BAUD#define L1C_R_IRQ		6#define L1C_R_IRQ_RET		7#define L1C_LOCK_TIMEOUTS	8#define L1C_LOCK_COUNTER	9#define L1C_UNLOCK_COUNTER	10#define L1C_REC_STALLS		11#define L1C_CONNECT_CALLS	12#define L1C_SIZE		L1C_CONNECT_CALLS	/* Set to the last one */uint64_t L1_collectibles[L1C_SIZE + 1];/* *	Some macros for handling Endian-ness */#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++];			\	}void snia_kmem_free(void *where, int size);#define ALREADY_LOCKED		1#define NOT_LOCKED		0static int early_l1_serial_out(nasid_t, char *, int, int /* defines above*/ );#define BCOPY(x,y,z)	memcpy(y,x,z)uint8_t L1_interrupts_connected;		/* Non-zero when we are in interrupt mode *//* * Console locking defines and functions. * */uint8_t L1_cons_is_inited = 0;			/* non-zero when console is init'd */nasid_t Master_console_nasid = (nasid_t)-1;extern nasid_t console_nasid;#if defined(CONFIG_IA64_SGI_SN1)u64 ia64_sn_get_console_nasid(void);#endifinline nasid_tget_master_nasid(void){#if defined(CONFIG_IA64_SGI_SN1)	nasid_t nasid = Master_console_nasid;	if ( nasid == (nasid_t)-1 ) {		nasid = (nasid_t)ia64_sn_get_console_nasid();		if ( (nasid < 0) || (nasid >= MAX_NASIDS) ) {			/* Out of bounds, use local */			console_nasid = nasid = get_nasid();		}		else {			/* Got a valid nasid, set the console_nasid */			char xx[100];/* zzzzzz - force nasid to 0 for now */			sprintf(xx, "Master console is set to nasid %d (%d)\n", 0, (int)nasid);nasid = 0;/* end zzzzzz */			xx[99] = (char)0;			early_l1_serial_out(nasid, xx, strlen(xx), NOT_LOCKED);			Master_console_nasid = console_nasid = nasid;		}	}	return(nasid);#else	return((nasid_t)0);#endif	/* CONFIG_IA64_SGI_SN1 */}#if defined(CONFIG_IA64_SGI_SN1)#define HUB_LOCK		16#define PRIMARY_LOCK_TIMEOUT    10000000#define HUB_LOCK_REG(n)         LOCK_HUB(n, MD_PERF_CNT0)#define SET_BITS(reg, bits)     SD(reg, LD(reg) |  (bits))#define CLR_BITS(reg, bits)     SD(reg, LD(reg) & ~(bits))#define TST_BITS(reg, bits)     ((LD(reg) & (bits)) != 0)#define HUB_TEST_AND_SET(n)	LD(LOCK_HUB(n,LB_SCRATCH_REG3_RZ))#define HUB_CLEAR(n)		SD(LOCK_HUB(n,LB_SCRATCH_REG3),0)#define RTC_TIME_MAX		((rtc_time_t) ~0ULL)/* * primary_lock * *   Allows CPU's 0-3  to mutually exclude the hub from one another by *   obtaining a blocking lock.  Does nothing if only one CPU is active. * *   This lock should be held just long enough to set or clear a global *   lock bit.  After a relatively short timeout period, this routine *   figures something is wrong, and steals the lock. It does not set *   any other CPU to "dead". */inline voidprimary_lock(nasid_t nasid){	rtc_time_t          expire;	expire = rtc_time() + PRIMARY_LOCK_TIMEOUT;	while (HUB_TEST_AND_SET(nasid)) {		if (rtc_time() > expire) {			HUB_CLEAR(nasid);		}	}}/* * primary_unlock (internal) * *   Counterpart to primary_lock */inline voidprimary_unlock(nasid_t nasid){	HUB_CLEAR(nasid);}/* * hub_unlock * *   Counterpart to hub_lock_timeout and hub_lock */inline voidhub_unlock(nasid_t nasid, int level){	uint64_t mask = 1ULL << level;	primary_lock(nasid);	CLR_BITS(HUB_LOCK_REG(nasid), mask);	primary_unlock(nasid);}/* * hub_lock_timeout * *   Uses primary_lock to implement multiple lock levels. * *   There are 20 lock levels from 0 to 19 (limited by the number of bits *   in HUB_LOCK_REG).  To prevent deadlock, multiple locks should be *   obtained in order of increasingly higher level, and released in the *   reverse order. * *   A timeout value of 0 may be used for no timeout. * *   Returns 0 if successful, -1 if lock times out. */inline inthub_lock_timeout(nasid_t nasid, int level, rtc_time_t timeout){	uint64_t mask = 1ULL << level;	rtc_time_t expire = (timeout ?  rtc_time() + timeout : RTC_TIME_MAX);	int done    = 0;	while (! done) {		while (TST_BITS(HUB_LOCK_REG(nasid), mask)) {			if (rtc_time() > expire)				return -1;		}		primary_lock(nasid);		if (! TST_BITS(HUB_LOCK_REG(nasid), mask)) {			SET_BITS(HUB_LOCK_REG(nasid), mask);			done = 1;		}		primary_unlock(nasid);	}	return 0;}#define LOCK_TIMEOUT	(0x1500000 * 1) /* 0x1500000 is ~30 sec */voidlock_console(nasid_t nasid){	int ret;	/* If we already have it locked, just return */	L1_collectibles[L1C_LOCK_COUNTER]++;	ret = hub_lock_timeout(nasid, HUB_LOCK, (rtc_time_t)LOCK_TIMEOUT);	if ( ret != 0 ) {		L1_collectibles[L1C_LOCK_TIMEOUTS]++;		/* timeout */		hub_unlock(nasid, HUB_LOCK);		/* If the 2nd lock fails, just pile ahead.... */		hub_lock_timeout(nasid, HUB_LOCK, (rtc_time_t)LOCK_TIMEOUT);		L1_collectibles[L1C_LOCK_TIMEOUTS]++;	}}inline voidunlock_console(nasid_t nasid){	L1_collectibles[L1C_UNLOCK_COUNTER]++;	hub_unlock(nasid, HUB_LOCK);}#else /* SN2 */inline void lock_console(nasid_t n)	{}inline void unlock_console(nasid_t n)	{}#endif	/* CONFIG_IA64_SGI_SN1 */int get_L1_baud(void){    return UART_BAUD_RATE;}/* uart driver functions */static inline 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 ) {    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;	}    }    if ( sc->uart == BRL1_LOCALHUB_UART )	lock_console(nasid);    /* Setup for the proper baud rate */    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 */    /* 8bit, one stop, clear request to send, auto flow control */    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, trigger on 1 */    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 | RxLVL0);    if ( sc->uart == BRL1_LOCALHUB_UART )	unlock_console(nasid);}/* This requires the console lock */#if	defined(CONFIG_IA64_SGI_SN1)static voiduart_intr_enable( l1sc_t *sc, u_char mask ){    u_char lcr_reg, icr_reg;    nasid_t nasid = sc->nasid;    if ( sc->uart == BRL1_LOCALHUB_UART )	lock_console(nasid);    /* 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)*/ );    if ( sc->uart == BRL1_LOCALHUB_UART )	unlock_console(nasid);}/* This requires the console lock */static voiduart_intr_disable( l1sc_t *sc, u_char mask ){    u_char lcr_reg, icr_reg;    nasid_t nasid = sc->nasid;    if ( sc->uart == BRL1_LOCALHUB_UART )	lock_console(nasid);

⌨️ 快捷键说明

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