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

📄 l1.c

📁 上传linux-jx2410的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
}intl1_control_in(int offset){	nasid_t nasid = 0; //(get_elsc())->nasid;	return(READ_L1_UART_REG(nasid, offset)); }#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) ); \    }intl1_serial_out( char *str, int len ){    int sent = len;    char crc_char;    unsigned short crc = INIT_CRC;    nasid_t nasid = 0; //(get_elsc())->nasid;    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 );    unlock_console(nasid);    return sent - len;}intl1_serial_in(void){	static int l1_cons_getc( l1sc_t *sc );	return(l1_cons_getc(get_elsc()));}/********************************************************************* * 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_cons_poll( l1sc_t *sc ){    /* 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;    }    brl1_receive( sc );    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_cons_getc( l1sc_t *sc ){    int c;    brl1_sch_t *subch = &(sc->subch[SC_CONS_SYSTEM]);    sc_cq_t *q = subch->iqp;    if( !l1_cons_poll( sc ) ) {	return 0;    }    SUBCH_DATA_LOCK( subch );    if( cq_empty( q ) ) {	atomic_set(&subch->packet_arrived, 0);	SUBCH_DATA_UNLOCK( subch );	return 0;    }    cq_rem( q, c );    if( cq_empty( q ) )	atomic_set(&subch->packet_arrived, 0);    SUBCH_DATA_UNLOCK( subch );    return c;}/* initialize the system console subchannel */voidl1_cons_init( l1sc_t *sc ){    brl1_sch_t *subch = &(sc->subch[SC_CONS_SYSTEM]);    SUBCH_DATA_LOCK( subch );    atomic_set(&subch->packet_arrived, 0);    cq_init( subch->iqp );    SUBCH_DATA_UNLOCK( subch );}/********************************************************************* * 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( l1sc_t *sc, int ch ){    brl1_sch_t *subch = &(sc->subch[ch]);    SUBCH_DATA_LOCK( subch );    sv_signal( &(subch->arrive_sv) );    SUBCH_DATA_UNLOCK( subch );}/* 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;    brl1_sch_t *subch;    SUBCH_LOCK( sc );    /* 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 );        return SC_NSUBCH;    }    subch->use = BRL1_SUBCH_RSVD;    SUBCH_UNLOCK( sc );    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 = 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 ){    brl1_sch_t *subch;    SUBCH_LOCK( sc );    subch = &(sc->subch[ch]);    if( subch->use != BRL1_SUBCH_RSVD ) {        /* we're trying to close a subchannel that's not open */        return SC_NOPEN;    }    atomic_set(&subch->packet_arrived, 0);    subch->use = BRL1_SUBCH_FREE;    SUBCH_DATA_LOCK( subch );    sv_broadcast( &(subch->arrive_sv) );    sv_destroy( &(subch->arrive_sv) );    SUBCH_DATA_UNLOCK( subch );    spin_lock_destroy( &(subch->data_lock) );    ASSERT( subch->iqp && (subch->iqp != &sc->garbage_q) );    kmem_free( subch->iqp, sizeof(sc_cq_t) );    subch->iqp = &sc->garbage_q;    SUBCH_UNLOCK( sc );    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 */                  short    req_code,     /* 16-bit request code */                  int      req_nargs,    /* # of arguments (varargs) passed */                  ... )                 /* any additional parameters */{    uint32_t buf32;   /* 32-bit buffer used to bounce things around */    void *bufptr;       /* used to hold command argument addresses */    va_list al;         /* variable argument list */    int index;          /* current index into msg buffer */    int argno;          /* current position in varargs list */    int l1_argno;       /* running total of arguments to l1 */    int l1_arg_t;       /* argument type/length */    int l1_argno_byte;  /* offset of argument count byte */    index = argno = 0;    /* set up destination address */    if( (msg_len -= sizeof( buf32 )) < 0 )	return -1;    L1_ADDRESS_TO_TASK( &buf32, sc->subch[ch].target, addr_task );    COPY_INT_TO_BUFFER(msg, index, buf32);    /* copy request code */    if( (msg_len -= 2) < 0 )	return( -1 );    msg[index++] = ((req_code >> 8) & 0xff);    msg[index++] = (req_code & 0xff);    if( !req_nargs ) {        return index;    }    /* reserve a byte for the argument count */    if( (msg_len -= 1) < 0 )	return( -1 );    l1_argno_byte = index++;    l1_argno = 0;    /* copy additional arguments */    va_start( al, req_nargs );    while( argno < req_nargs ) {        l1_argno++;        l1_arg_t = va_arg( al, int ); argno++;        switch( l1_arg_t )        {          case L1_ARG_INT:	    if( (msg_len -= (sizeof( buf32 ) + 1)) < 0 )		return( -1 );            msg[index++] = L1_ARG_INT;            buf32 = (unsigned)va_arg( al, int ); argno++;	    COPY_INT_TO_BUFFER(msg, index, buf32);            break;          case L1_ARG_ASCII:            bufptr = va_arg( al, char* ); argno++;	    if( (msg_len -= (strlen( bufptr ) + 2)) < 0 )		return( -1 );            msg[index++] = L1_ARG_ASCII;            strcpy( (char *)&(msg[index]), (char *)bufptr );            index += (strlen( bufptr ) + 1); /* include terminating null */            break;	  case L1_ARG_UNKNOWN:              {                  int arglen;		                    arglen = va_arg( al, int ); argno++;                  bufptr = va_arg( al, void* ); argno++;		  if( (msg_len -= (arglen + 1)) < 0 )		      return( -1 );                  msg[index++] = L1_ARG_UNKNOWN | arglen;                  BCOPY( bufptr, &(msg[index]), arglen  );                  index += arglen;		  break;              }	  	  default: /* unhandled argument type */	    return -1;        }    }    va_end( al );    msg[l1_argno_byte] = l1_argno;    return index;}/* sc_interpret_resp verifies an L1 response to a bedrock request, and * breaks the response data up into the constituent parts.  If the * response message indicates error, or if a mismatch is found in the * expected number and type of arguments, an error is returned.  The * arguments to this function work very much like the arguments to * sc_construct_msg, above, except that L1_ARG_INTs must be followed * by a _pointer_ to an integer that can be filled in by this function. */intsc_interpret_resp( char *resp,          /* buffer received from L1 */                   int   resp_nargs,    /* number of _varargs_ passed in */                   ... ){    uint32_t buf32;   /* 32-bit buffer used to bounce things around */    void *bufptr;       /* used to hold response field addresses */    va_list al;         /* variable argument list */    int index;          /* current index into response buffer */    int argno;          /* current position in varargs list */    int l1_fldno;       /* number of resp fields received from l1 */    int l1_fld_t;       /* field type/length */    index = argno = 0;#if defined(L1_DEBUG)#define DUMP_RESP							  \    {									  \	int ix;								  \        char outbuf[512];						  \        sprintf( outbuf, "sc_interpret_resp error line %d: ", __LINE__ ); \	for( ix = 0; ix < 16; ix++ ) {					  \	    sprintf( &outbuf[strlen(outbuf)], "%x ", resp[ix] );	  \	}								  \	printk( "%s\n", outbuf );					  \    }#else#define DUMP_RESP#endif /* L1_DEBUG */    /* check response code */    COPY_BUFFER_TO_INT(resp, index, buf32);    if( buf32 != L1_RESP_OK ) {	DUMP_RESP;        return buf32;    }    /* get number of response fields */    l1_fldno = resp[index++];    va_start( al, resp_nargs );    /* copy out response fields */    while( argno < resp_nargs ) {        l1_fldno--;        l1_fld_t = va_arg( al, int ); argno++;        switch( l1_fld_t )        {          case L1_ARG_INT:            if( resp[index++] != L1_ARG_INT ) {                /* type mismatch */		va_end( al );		DUMP_RESP;		return -1;            }            bufptr = va_arg( al, int* ); argno++;	    COPY_BUFFER_TO_BUFFER(resp, index, bufptr);            break;          case L1_ARG_ASCII:            if( resp[index++] != L1_ARG_ASCII ) {

⌨️ 快捷键说明

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