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

📄 l1.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
				while ( counter > 0 ) {					writeb(*str, (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));					counter--;					str++;				}			}		}		else {#endif	/* USE_SAL_CONSOLE_IO */			nasid_t nasid = get_master_nasid();			int l1_write(l1sc_t *, char *, int, int);			if ( L1_cons_is_inited ) {				if ( NODEPDA(NASID_TO_COMPACT_NODEID(nasid))->module != (module_t *)0 )					return(l1_write(&NODEPDA(NASID_TO_COMPACT_NODEID(nasid))->module->elsc, str, len,#if	defined(SYNC_CONSOLE_WRITE)							1#else							!L1_interrupts_connected#endif									));			}			return(early_l1_serial_out(nasid, str, len, NOT_LOCKED));#if defined(USE_SAL_CONSOLE_IO)		}	}	return((counter <= 0) ? 0 : (len - counter));#endif}/* * These are the 'early' functions - when we need to do things before we have * all the structs setup. */static l1sc_t Early_console;		/* fake l1sc_t */static int Early_console_inited = 0;static voidearly_brl1_init( l1sc_t *sc, nasid_t nasid, net_vec_t uart ){    int i;    brl1_sch_t *subch;    bzero( sc, sizeof( *sc ) );    sc->nasid = nasid;    sc->uart = uart;    sc->getc_f = (uart == BRL1_LOCALHUB_UART ? uart_getc : rtr_uart_getc);    sc->putc_f = (uart == BRL1_LOCALHUB_UART ? uart_putc : rtr_uart_putc);    sc->sol = 1;    subch = sc->subch;    /* initialize L1 subchannels     */    /* assign processor TTY channels */    for( i = 0; i < CPUS_PER_NODE; i++, subch++ ) {	subch->use = BRL1_SUBCH_RSVD;	subch->packet_arrived = ATOMIC_INIT(0);	subch->tx_notify = NULL;	subch->rx_notify = NULL;	subch->iqp = &sc->garbage_q;    }    /* assign system TTY channel (first free subchannel after each     * processor's individual TTY channel has been assigned)     */    subch->use = BRL1_SUBCH_RSVD;    subch->packet_arrived = ATOMIC_INIT(0);    subch->tx_notify = NULL;    subch->rx_notify = NULL;    if( sc->uart == BRL1_LOCALHUB_UART ) {	static sc_cq_t x_iqp;	subch->iqp = &x_iqp;	ASSERT( subch->iqp );	cq_init( subch->iqp );    }    else {	/* we shouldn't be getting console input from remote UARTs */	subch->iqp = &sc->garbage_q;    }    subch++; i++;    /* "reserved" subchannels (0x05-0x0F); for now, throw away     * incoming packets     */    for( ; i < 0x10; i++, subch++ ) {	subch->use = BRL1_SUBCH_FREE;	subch->packet_arrived = ATOMIC_INIT(0);	subch->tx_notify = NULL;	subch->rx_notify = NULL;	subch->iqp = &sc->garbage_q;    }    /* remaining subchannels are free */    for( ; i < BRL1_NUM_SUBCHANS; i++, subch++ ) {	subch->use = BRL1_SUBCH_FREE;	subch->packet_arrived = ATOMIC_INIT(0);	subch->tx_notify = NULL;	subch->rx_notify = NULL;	subch->iqp = &sc->garbage_q;    }}static inline l1sc_t *early_sc_init(nasid_t nasid){	/* This is for early I/O */	if ( Early_console_inited == 0 ) {    		early_brl1_init(&Early_console, nasid,  BRL1_LOCALHUB_UART);		Early_console_inited = 1;	}	return(&Early_console);}#define PUTCHAR(ch) \    { \        while( (!(READ_L1_UART_REG( nasid, REG_LSR ) & LSR_XHRE)) || \                (!(READ_L1_UART_REG( nasid, REG_MSR ) & MSR_CTS)) ); \        WRITE_L1_UART_REG( nasid, REG_DAT, (ch) ); \    }static intearly_l1_serial_out( nasid_t nasid, char *str, int len, int lock_state ){	int ret, sent = 0;	char *msg = str;	static int early_l1_send( nasid_t nasid, char *str, int len, int lock_state );	while ( sent < len ) {		ret = early_l1_send(nasid, msg, len - sent, lock_state);		sent += ret;		msg += ret;	}	return(len);}static inline intearly_l1_send( nasid_t nasid, char *str, int len, int lock_state ){    int sent;    char crc_char;    unsigned short crc = INIT_CRC;    if( len > (BRL1_QSIZE - 1) )	len = (BRL1_QSIZE - 1);    sent = len;    if ( lock_state == NOT_LOCKED )    	lock_console(nasid);    PUTCHAR( BRL1_FLAG_CH );    PUTCHAR( BRL1_EVENT | SC_CONS_SYSTEM );    crc = crc16_calc( crc, (BRL1_EVENT | SC_CONS_SYSTEM) );    while( len ) {	if( (*str == BRL1_FLAG_CH) || (*str == BRL1_ESC_CH) ) {	    PUTCHAR( BRL1_ESC_CH );	    PUTCHAR( (*str) ^ BRL1_XOR_CH );	}	else {	    PUTCHAR( *str );	}		crc = crc16_calc( crc, *str );	str++; len--;    }        crc ^= 0xffff;    crc_char = crc & 0xff;    if( (crc_char == BRL1_ESC_CH) || (crc_char == BRL1_FLAG_CH) ) {	crc_char ^= BRL1_XOR_CH;	PUTCHAR( BRL1_ESC_CH );    }    PUTCHAR( crc_char );    crc_char = (crc >> 8) & 0xff;    if( (crc_char == BRL1_ESC_CH) || (crc_char == BRL1_FLAG_CH) ) {	crc_char ^= BRL1_XOR_CH;	PUTCHAR( BRL1_ESC_CH );    }    PUTCHAR( crc_char );    PUTCHAR( BRL1_FLAG_CH );    if ( lock_state == NOT_LOCKED )    	unlock_console(nasid);    return sent;}/********************************************************************* * l1_cons functions * * These allow the L1 to act as the system console.  They're intended * to abstract away most of the br/l1 internal details from the * _L1_cons_* functions (in the prom-- see "l1_console.c") and * l1_* functions (in the kernel-- see "sio_l1.c") that they support. * */static intl1_poll( l1sc_t *sc, int mode ){    int ret;    /* in case this gets called before the l1sc_t structure for the module_t     * struct for this node is initialized (i.e., if we're called with a     * zero l1sc_t pointer)...     */    if( !sc ) {	return 0;    }    if( atomic_read(&sc->subch[SC_CONS_SYSTEM].packet_arrived) ) {	return 1;    }    ret = brl1_receive( sc, mode );    if ( (ret != BRL1_VALID) && (ret != BRL1_NO_MESSAGE) && (ret != BRL1_PROTOCOL) && (ret != BRL1_CRC) )	L1_collectibles[L1C_REC_STALLS] = ret;    if( atomic_read(&sc->subch[SC_CONS_SYSTEM].packet_arrived) ) {	return 1;    }    return 0;}/* pull a character off of the system console queue (if one is available) */static intl1_getc( l1sc_t *sc, int mode ){    unsigned long pl = 0;    int c;    brl1_sch_t *subch = &(sc->subch[SC_CONS_SYSTEM]);    sc_cq_t *q = subch->iqp;    if( !l1_poll( sc, mode ) ) {	return 0;    }    SUBCH_DATA_LOCK( subch, pl );    if( cq_empty( q ) ) {	atomic_set(&subch->packet_arrived, 0);	SUBCH_DATA_UNLOCK( subch, pl );	return 0;    }    cq_rem( q, c );    if( cq_empty( q ) )	atomic_set(&subch->packet_arrived, 0);    SUBCH_DATA_UNLOCK( subch, pl );    return c;}/* * Write a message to the L1 on the system console subchannel. * * Danger: don't use a non-zero value for the wait parameter unless you're * someone important (like a kernel error message). */intl1_write( l1sc_t *sc, char *msg, int len, int wait ){	int sent = 0, ret = 0;	if ( wait ) {		while ( sent < len ) {			ret = brl1_send( sc, msg, len - sent, (SC_CONS_SYSTEM | BRL1_EVENT), wait );			sent += ret;			msg += ret;		}		ret = len;	}	else {		ret = brl1_send( sc, msg, len, (SC_CONS_SYSTEM | BRL1_EVENT), wait );	}	return(ret);}/* initialize the system console subchannel */voidl1_init(void){	/* All we do now is remember that we have been called */	L1_cons_is_inited = 1;}/********************************************************************* * The following functions and definitions implement the "message"- * style interface to the L1 system controller. * * Note that throughout this file, "sc" generally stands for "system * controller", while "subchannels" tend to be represented by * variables with names like subch or ch. * */#ifdef L1_DEBUG#define L1_DBG_PRF(x) printf x#else#define L1_DBG_PRF(x)#endif/* * sc_data_ready is called to signal threads that are blocked on l1 input. */voidsc_data_ready( int dummy0, void *dummy1, struct pt_regs *dummy2, l1sc_t *sc, int ch ){    unsigned long pl = 0;    brl1_sch_t *subch = &(sc->subch[ch]);    SUBCH_DATA_LOCK( subch, pl );    sv_signal( &(subch->arrive_sv) );    SUBCH_DATA_UNLOCK( subch, pl );}/* sc_open reserves a subchannel to send a request to the L1 (the * L1's response will arrive on the same channel).  The number * returned by sc_open is the system controller subchannel * acquired. */intsc_open( l1sc_t *sc, uint target ){    /* The kernel version implements a locking scheme to arbitrate     * subchannel assignment.     */    int ch;    unsigned long pl = 0;    brl1_sch_t *subch;    SUBCH_LOCK( sc, pl );    /* Look for a free subchannel. Subchannels 0-15 are reserved     * for other purposes.     */    for( subch = &(sc->subch[BRL1_CMD_SUBCH]), ch = BRL1_CMD_SUBCH; 			ch < BRL1_NUM_SUBCHANS; subch++, ch++ ) {        if( subch->use == BRL1_SUBCH_FREE )            break;    }    if( ch == BRL1_NUM_SUBCHANS ) {        /* there were no subchannels available! */        SUBCH_UNLOCK( sc, pl );        return SC_NSUBCH;    }    subch->use = BRL1_SUBCH_RSVD;    SUBCH_UNLOCK( sc, pl );    atomic_set(&subch->packet_arrived, 0);    subch->target = target;    spin_lock_init( &(subch->data_lock) );    sv_init( &(subch->arrive_sv), &(subch->data_lock), SV_MON_SPIN | SV_ORDER_FIFO /* | SV_INTS */);    subch->tx_notify = NULL;    subch->rx_notify = sc_data_ready;    subch->iqp = snia_kmem_zalloc_node( sizeof(sc_cq_t), KM_NOSLEEP,				   NASID_TO_COMPACT_NODEID(sc->nasid) );    ASSERT( subch->iqp );    cq_init( subch->iqp );    return ch;}/* sc_close frees a Bedrock<->L1 subchannel. */intsc_close( l1sc_t *sc, int ch ){    unsigned long pl = 0;    brl1_sch_t *subch;    SUBCH_LOCK( sc, pl );    subch = &(sc->subch[ch]);    if( subch->use != BRL1_SUBCH_RSVD ) {        /* we're trying to close a subchannel that's not open */	SUBCH_UNLOCK( sc, pl );        return SC_NOPEN;    }    atomic_set(&subch->packet_arrived, 0);    subch->use = BRL1_SUBCH_FREE;    sv_broadcast( &(subch->arrive_sv) );    sv_destroy( &(subch->arrive_sv) );    spin_lock_destroy( &(subch->data_lock) );    ASSERT( subch->iqp && (subch->iqp != &sc->garbage_q) );    snia_kmem_free( subch->iqp, sizeof(sc_cq_t) );    subch->iqp = &sc->garbage_q;    subch->tx_notify = NULL;    subch->rx_notify = brl1_discard_packet;    SUBCH_UNLOCK( sc, pl );    return SC_SUCCESS;}/* sc_construct_msg builds a bedrock-to-L1 request in the supplied * buffer.  Returns the length of the message.  The * safest course when passing a buffer to be filled in is to use * BRL1_QSIZE as the buffer size. * * Command arguments are passed as type/argument pairs, i.e., to * pass the number 5 as an argument to an L1 command, call * sc_construct_msg as follows: * *    char msg[BRL1_QSIZE]; *    msg_len = sc_construct_msg( msg, *				  BRL1_QSIZE, *				  target_component, *                                L1_ADDR_TASK_BOGUSTASK, *                                L1_BOGUSTASK_REQ_BOGUSREQ, *                                2, *                                L1_ARG_INT, 5 ); * * To pass an additional ASCII argument, you'd do the following: * *    char *str; *    ... str points to a null-terminated ascii string ... *    msg_len = sc_construct_msg( msg, *                                BRL1_QSIZE, *				  target_component, *                                L1_ADDR_TASK_BOGUSTASK, *                                L1_BOGUSTASK_REQ_BOGUSREQ, *                                4, *                                L1_ARG_INT, 5, *                                L1_ARG_ASCII, str ); * * Finally, arbitrary data of unknown type is passed using the argtype * code L1_ARG_UNKNOWN, a data length, and a buffer pointer, e.g. * *    msg_len = sc_construct_msg( msg, *                                BRL1_QSIZE, *				  target_component, *                                L1_ADDR_TASK_BOGUSTASK, *                                L1_BOGUSTASK_REQ_BOGUSREQ, *                                3, *                                L1_ARG_UNKNOWN, 32, bufptr ); * * ...passes 32 bytes of data starting at bufptr.  Note that no string or * "unknown"-type argument should be long enough to overflow the message * buffer. * * To construct a message for an L1 command that requires no arguments, * you'd use the following: * *    msg_len = sc_construct_msg( msg, *                                BRL1_QSIZE, *				  target_component, *                                L1_ADDR_TASK_BOGUSTASK, *                                L1_BOGUSTASK_REQ_BOGUSREQ, *                                0 ); * * The final 0 means "no varargs".  Notice that this parameter is used to hold * the number of additional arguments to sc_construct_msg, _not_ the actual * number of arguments used by the L1 command (so 2 per L1_ARG_[INT,ASCII] * type argument, and 3 per L1_ARG_UNKOWN type argument).  A call to construct * an L1 command which required three integer arguments and two arguments of * some arbitrary (unknown) type would pass 12 as the value for this parameter. * * ENDIANNESS WARNING: The following code does a lot of copying back-and-forth * between byte arrays and four-byte big-endian integers.  Depending on the * system controller connection and endianness of future architectures, some * rewriting might be necessary. */intsc_construct_msg( l1sc_t  *sc,		/* system controller struct */		  int	   ch,           /* subchannel for this message */		  char    *msg,          /* message buffer */		  int      msg_len,      /* size of message buffer */                  l1addr_t addr_task,    /* target system controller task

⌨️ 快捷键说明

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