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

📄 l1.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	crc = crc16_calc( crc, *msg );	msg++;    }    crc ^= 0xffff;    for( index = 0; index < sizeof(crc); index++ ) {	char crc_char = (char)(crc & 0x00FF);	if( (crc_char == BRL1_ESC_CH) || (crc_char == BRL1_FLAG_CH) ) {	    *send_ptr++ = BRL1_ESC_CH;	    pkt_len++;	    crc_char ^= BRL1_XOR_CH;	}	*send_ptr++ = crc_char;	pkt_len++;	crc >>= 8;    }        *send_ptr++ = BRL1_FLAG_CH;    pkt_len++;    sc->send_len = pkt_len;    sc->sent = 0;    {	int counter = 0;	do {		brl1_send_chars( sc );		if ( counter++ > 0xfffff ) {			char *str = "Looping waiting for uart to clear (2)\n";			early_l1_serial_out(sc->nasid, str, strlen(str), ALREADY_LOCKED);			break;		}	} while( (sc->sent < sc->send_len) && wait );    }    if ( sc->uart == BRL1_LOCALHUB_UART )	unlock_console(sc->nasid);    if( sc->sent == sc->send_len ) {	/* success! release the send buffer and call the callup */#if	!defined(SYNC_CONSOLE_WRITE)	brl1_notif_t callup;#endif	sc->send_in_use = 0;	/* call any upper layer that's asked for notification */#if	defined(XX_SYNC_CONSOLE_WRITE)	/*	 * This is probably not a good idea - since the l1_ write func can be called multiple	 * time within the callup function.	 */	callup = subch->tx_notify;	if( callup && (SUBCH(type_and_subch) == SC_CONS_SYSTEM) ) {		L1_collectibles[L1C_SEND_CALLUPS]++;		(*callup)(sc->subch[SUBCH(type_and_subch)].irq_frame.bf_irq,				sc->subch[SUBCH(type_and_subch)].irq_frame.bf_dev_id,				sc->subch[SUBCH(type_and_subch)].irq_frame.bf_regs, sc, SUBCH(type_and_subch));	}#endif	/* SYNC_CONSOLE_WRITE */    }#if	!defined(SYNC_CONSOLE_WRITE)    else if ( !wait ) {	/* enable low-water interrupts so buffer will be drained */	uart_enable_xmit_intr(sc);    }#endif    L1SC_SEND_UNLOCK(sc, pl);    return len;}/* brl1_send_cont is intended to be called as an interrupt service * routine.  It sends until the UART won't accept any more characters, * or until an error is encountered (in which case we surrender the * send buffer and give up trying to send the packet).  Once the * last character in the packet has been sent, this routine releases * the send buffer and calls any previously-registered "low-water" * output routines. */#if	!defined(SYNC_CONSOLE_WRITE)intbrl1_send_cont( l1sc_t *sc ){    unsigned long pl = 0;    int done = 0;    brl1_notif_t callups[BRL1_NUM_SUBCHANS];    brl1_notif_t *callup;    brl1_sch_t *subch;    int index;    /*     * I'm not sure how I think this is to be handled - whether the lock is held     * over the interrupt - but it seems like it is a bad idea....     */    if ( sc->uart == BRL1_LOCALHUB_UART )	lock_console(sc->nasid);    L1SC_SEND_LOCK(sc, pl);    brl1_send_chars( sc );    done = (sc->sent == sc->send_len);    if( done ) {	sc->send_in_use = 0;#if	!defined(SYNC_CONSOLE_WRITE)	uart_disable_xmit_intr(sc);#endif    }    if ( sc->uart == BRL1_LOCALHUB_UART )	unlock_console(sc->nasid);    /* Release the lock */    L1SC_SEND_UNLOCK(sc, pl);    return 0;}#endif	/* SYNC_CONSOLE_WRITE *//* internal function -- used by brl1_receive to read a character  * from the uart and check whether errors occurred in the process. */static intread_uart( l1sc_t *sc, int *c, int *result ){    *c = sc->getc_f( sc );    /* no character is available */    if( *c == UART_NO_CHAR ) {	*result = BRL1_NO_MESSAGE;	return 0;    }    /* some error in UART */    if( *c < 0 ) {	*result = BRL1_LINK;	return 0;    }    /* everything's fine */    *result = BRL1_VALID;    return 1;}/* * brl1_receive * * This function reads a Bedrock-L1 protocol packet into the l1sc_t * response buffer. * * The operation of this function can be expressed as a finite state * machine: *START STATE			INPUT		TRANSITION==========================================================BRL1_IDLE (reset or error)	flag		BRL1_FLAG				other		BRL1_IDLE@BRL1_FLAG (saw a flag (0x7e))	flag		BRL1_FLAG				escape		BRL1_IDLE@				header byte	BRL1_HDR				other		BRL1_IDLE@BRL1_HDR (saw a type/subch byte)(see below)	BRL1_BODY						BRL1_HDRBRL1_BODY (reading packet body)	flag		BRL1_FLAG				escape		BRL1_ESC				other		BRL1_BODYBRL1_ESC (saw an escape (0x7d))	flag		BRL1_FLAG@				escape		BRL1_IDLE@				other		BRL1_BODY=========================================================="@" denotes an error transition. * The BRL1_HDR state is a transient state which doesn't read input, * but just provides a way in to code which decides to whom an * incoming packet should be directed. * * brl1_receive can be used to poll for input from the L1, or as  * an interrupt service routine.  It reads as much data as is * ready from the junk bus UART and places into the appropriate * input queues according to subchannel.  The header byte is * stripped from console-type data, but is retained for message- * type data (L1 responses).  A length byte will also be * prepended to message-type packets. * * This routine is non-blocking; if the caller needs to block * for input, it must call brl1_receive in a loop. * * brl1_receive returns when there is no more input, the queue * for the current incoming message is full, or there is an * error (parity error, bad header, bad CRC, etc.). */#define STATE_SET(l,s)		((l)->brl1_state = (s))#define STATE_GET(l)		((l)->brl1_state)#define LAST_HDR_SET(l,h)	((l)->brl1_last_hdr = (h))#define LAST_HDR_GET(l)		((l)->brl1_last_hdr)#define VALID_HDR(c)				\    ( SUBCH((c)) <= SC_CONS_SYSTEM		\	? PKT_TYPE((c)) == BRL1_REQUEST		\	: ( PKT_TYPE((c)) == BRL1_RESPONSE ||	\	    PKT_TYPE((c)) == BRL1_EVENT ) )#define IS_TTY_PKT(l)		( SUBCH(LAST_HDR_GET(l)) <= SC_CONS_SYSTEM ? 1 : 0 )intbrl1_receive( l1sc_t *sc, int mode ){    int result;		/* value to be returned by brl1_receive */    int c;		/* most-recently-read character	     	*/    int done;		/* set done to break out of recv loop	*/    unsigned long pl = 0, cpl = 0;    sc_cq_t *q;		/* pointer to queue we're working with	*/    result = BRL1_NO_MESSAGE;    L1SC_RECV_LOCK(sc, cpl);    done = 0;    while( !done )    {	switch( STATE_GET(sc) )	{	  case BRL1_IDLE:	    /* Initial or error state.  Waiting for a flag character             * to resynchronize with the L1.             */	    if( !read_uart( sc, &c, &result ) ) {		/* error reading uart */		done = 1;		continue;	    }	    	    if( c == BRL1_FLAG_CH ) {		/* saw a flag character */		STATE_SET( sc, BRL1_FLAG );		continue;	    }	    break;	    	  case BRL1_FLAG:	    /* One or more flag characters have been read; look for	     * the beginning of a packet (header byte).	     */	    	    if( !read_uart( sc, &c, &result ) ) {		/* error reading uart */		if( c != UART_NO_CHAR )		    STATE_SET( sc, BRL1_IDLE );		done = 1;		continue;	    }	    	    if( c == BRL1_FLAG_CH ) {		/* multiple flags are OK */		continue;	    }	    if( !VALID_HDR( c ) ) {		/* if c isn't a flag it should have been		 * a valid header, so we have an error		 */		result = BRL1_PROTOCOL;		STATE_SET( sc, BRL1_IDLE );		done = 1;		continue;	    }	    /* we have a valid header byte */	    LAST_HDR_SET( sc, c );	    STATE_SET( sc, BRL1_HDR );	    break; 	  case BRL1_HDR:	    /* A header byte has been read. Do some bookkeeping. */	    q = sc->subch[ SUBCH( LAST_HDR_GET(sc) ) ].iqp;	    ASSERT(q);	    	    if( !IS_TTY_PKT(sc) ) {		/* if this is an event or command response rather		 * than console I/O, we need to reserve a couple		 * of extra spaces in the queue for the header		 * byte and a length byte; if we can't, stay in		 * the BRL1_HDR state.		 */		if( cq_room( q ) < 2 ) {		    result = BRL1_FULL_Q;		    done = 1;		    continue;		}		cq_tent_add( q, 0 );			/* reserve length byte */		cq_tent_add( q, LAST_HDR_GET( sc ) );	/* record header byte  */	    }	    STATE_SET( sc, BRL1_BODY );	    break;	  case BRL1_BODY:	    /* A header byte has been read.  We are now attempting	     * to receive the packet body.	     */	    q = sc->subch[ SUBCH( LAST_HDR_GET(sc) ) ].iqp;	    ASSERT(q);	    /* if the queue we want to write into is full, don't read from	     * the uart (this provides backpressure to the L1 side)	     */	    if( cq_tent_full( q ) ) {		result = BRL1_FULL_Q;		done = 1;		continue;	    }	    	    if( !read_uart( sc, &c, &result ) ) {		/* error reading uart */		if( c != UART_NO_CHAR )		    STATE_SET( sc, BRL1_IDLE );		done = 1;		continue;	    }	    if( c == BRL1_ESC_CH ) {		/* prepare to unescape the next character */		STATE_SET( sc, BRL1_ESC );		continue;	    }	    	    if( c == BRL1_FLAG_CH ) {		/* flag signifies the end of a packet */		unsigned short crc;	/* holds the crc as we calculate it */		int i;			/* index variable */		brl1_sch_t *subch;      /* subchannel for received packet */		brl1_notif_t callup;	/* "data ready" callup */		/* whatever else may happen, we've seen a flag and we're		 * starting a new packet		 */		STATE_SET( sc, BRL1_FLAG );		/* if the packet body has less than 2 characters,		 * it can't be a well-formed packet.  Discard it.		 */		if( cq_tent_len( q ) < /* 2 + possible length byte */		    (2 + (IS_TTY_PKT(sc) ? 0 : 1)) )		{		    result = BRL1_PROTOCOL;		    cq_discard_tent( q );		    STATE_SET( sc, BRL1_FLAG );		    done = 1;		    continue;		}				/* check CRC */		/* accumulate CRC, starting with the header byte and		 * ending with the transmitted CRC.  This should		 * result in a known good value.		 */		crc = crc16_calc( INIT_CRC, LAST_HDR_GET(sc) );		for( i = (q->ipos + (IS_TTY_PKT(sc) ? 0 : 2)) % BRL1_QSIZE;		     i != q->tent_next;		     i = (i + 1) % BRL1_QSIZE )		{		    crc = crc16_calc( crc, q->buf[i] );		}		/* verify the caclulated crc against the "good" crc value;		 * if we fail, discard the bad packet and return an error.		 */		if( crc != (unsigned short)GOOD_CRC ) {		    result = BRL1_CRC;		    cq_discard_tent( q );		    STATE_SET( sc, BRL1_FLAG );		    done = 1;		    continue;		}				/* so the crc check was ok.  Now we discard the CRC		 * from the end of the received bytes.		 */		q->tent_next += (BRL1_QSIZE - 2);		q->tent_next %= BRL1_QSIZE;		/* get the subchannel and lock it */		subch = &(sc->subch[SUBCH( LAST_HDR_GET(sc) )]);		SUBCH_DATA_LOCK( subch, pl );				/* if this isn't a console packet, we need to record		 * a length byte		 */		if( !IS_TTY_PKT(sc) ) {		    q->buf[q->ipos] = cq_tent_len( q ) - 1;		}				/* record packet for posterity */		cq_commit_tent( q );		result = BRL1_VALID;		/* notify subchannel owner that there's something		 * on the queue for them		 */		atomic_inc(&(subch->packet_arrived));		callup = subch->rx_notify;		SUBCH_DATA_UNLOCK( subch, pl );		if( callup && (mode == SERIAL_INTERRUPT_MODE) ) {		    L1SC_RECV_UNLOCK( sc, cpl );		    L1_collectibles[L1C_RECEIVE_CALLUPS]++;		    (*callup)( sc->subch[SUBCH(LAST_HDR_GET(sc))].irq_frame.bf_irq,				sc->subch[SUBCH(LAST_HDR_GET(sc))].irq_frame.bf_dev_id,				sc->subch[SUBCH(LAST_HDR_GET(sc))].irq_frame.bf_regs,				sc, SUBCH(LAST_HDR_GET(sc)) );		    L1SC_RECV_LOCK( sc, cpl );		}		continue;	/* go back for more! */	    }	    	    /* none of the special cases applied; we've got a normal	     * body character	     */	    cq_tent_add( q, c );	    break;	  case BRL1_ESC:	    /* saw an escape character.  The next character will need	     * to be unescaped.	     */	    q = sc->subch[ SUBCH( LAST_HDR_GET(sc) ) ].iqp;	    ASSERT(q);	    /* if the queue we want to write into is full, don't read from	     * the uart (this provides backpressure to the L1 side)	     */	    if( cq_tent_full( q ) ) {		result = BRL1_FULL_Q;		done = 1;		continue;	    }	    	    if( !read_uart( sc, &c, &result ) ) {		/* error reading uart */		if( c != UART_NO_CHAR ) {		    cq_discard_tent( q );		    STATE_SET( sc, BRL1_IDLE );		}		done = 1;		continue;	    }	    	    if( c == BRL1_FLAG_CH ) {		/* flag after escape is an error */		STATE_SET( sc, BRL1_FLAG );		cq_discard_tent( q );		result = BRL1_PROTOCOL;		done = 1;		continue;	    }	    if( c == BRL1_ESC_CH ) {		/* two consecutive escapes is an error */		STATE_SET( sc, BRL1_IDLE );		cq_discard_tent( q );		result = BRL1_PROTOCOL;		done = 1;		continue;	    }	    

⌨️ 快捷键说明

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