📄 hdlcint.c
字号:
* DESCRIPTION:
*
* Return TRUE if Buffer Descriptor Status bd_cstatus indicates Receive
* Error; Return FALSE otherwise note Receive Errors are as follows:
*
* 0x80: DPLL Error (DE)
* 0x20: Length Violation (LG)
* 0x10: Non-Octet Aligned (NO)
* 0x8: Rx Abort Sequence (AB)
* 0x4: Rx CRC Error (CR)
* 0x2: Overrun (OV)
* 0x1: Carrier Detect Lost (CD)
*
* EXTERNAL EFFECTS: None
*
* PARAMETERS:
*
* bd_cstatus
*
* RETURNS: TRUE if there was an error and FALSE if there wasn't
*
*-----------------------------------------------------------------------------*/
UHWORD BDRxError(UHWORD bd_cstatus)
{
if (bd_cstatus & BD_RX_ERROR)
return TRUE;
else
return FALSE;
} /* end BDRxError */
/*-----------------------------------------------------------------------------
*
* FUNCTION NAME: LastBD
*
* DESCRIPTION: Return TRUE if Buffer Descriptor with status and control
* register bd_cstatus is last in frame; Return FALSE otherwise.
*
* EXTERNAL EFFECTS: None
*
* PARAMETERS:
*
* bd_cstatus -
*
* RETURNS:
*
*-----------------------------------------------------------------------------*/
UHWORD LastBD(UHWORD bd_cstatus)
{
if (bd_cstatus & 0x0800)
return TRUE;
else
return FALSE;
} /* end LastBD */
/*-----------------------------------------------------------------------------
*
* FUNCTION NAME: BDEmpty
*
* DESCRIPTION:
*
* Return TRUE if Buffer Descriptor Status bd_cstatus is empty. Return
* FALSE otherwise.
*
* EXTERNAL EFFECTS: None
*
* PARAMETERS:
*
* bd_cstatus
*
* RETURNS: TRUE if empty and FALSE if it isn't
*
*-----------------------------------------------------------------------------*/
UHWORD BDEmpty(UHWORD bd_cstatus)
{
if (bd_cstatus & 0x8000)
return TRUE;
else
return FALSE;
} /* end BDEmpty */
/*-----------------------------------------------------------------------------
*
* FUNCTION NAME: ExtIntHandler
*
* DESCRIPTION:
*
* Process External Interrupt (assumes only interrupts from SCC2)
*
* Main Processing Steps:
*
* (1) Save off SCCE for SCC2 (SCC 1 Event Register)
*
* (2) Test input vector against External Interrupt Vector.
*
* (3) Test Interrupt Code in SIU Interrupt Vector Reg (SIVEC) against
* LEVEL 4.
*
* (4) Clear LEVEL 4 Interrupt Level bit in SIPEND.
*
* (5) Request Interrupt Vector Number from CPM Interrupt Vector Reg
* (CIVR).
*
* (6) Test CIVR Interrupt Vector against Vector for SCC2.
*
* (7) Clear SCC2 Event Register
*
* (8) Test SCC2 Event
*
* (9) Clear SCC2 bit CPM Interrupt In-Service Register
*
*
* NOTE: This ISR will only handle ONE RX event. This interrupt happens
* when the last frame of eight is received.
*
* EXTERNAL EFFECTS: interrupt related registers
*
* PARAMETERS:
*
* vector - interrupt vector (address)
*
* RETURNS: NONE
*
*-----------------------------------------------------------------------------*/
void ExtIntHandler(UWORD vector)
{
UWORD sivec_ic;
UWORD scce;
UHWORD index;
/*-----------------------------------------------------------------------*/
/* Shift the byte wide interrupt code down to the least significant byte */
/*-----------------------------------------------------------------------*/
sivec_ic = IMMR->siu_sivec >> 24; /* sivec interrupt code */
/*-----------------------------*/
/* Grab the SCC event register */
/*-----------------------------*/
scce = IMMR->scc_regs[SCC2_REG].scc_scce; /* Save off scce */
/*---------------------------------------------------------------------*/
/* Match input vector against Exteral Interrupt Vector -- 0x500 on PPC */
/*---------------------------------------------------------------------*/
if (vector != EXT_INT_VECTOR)
return;
/*-----------------------------*/
/* Process SIU Interrupt Event */
/*-----------------------------*/
switch(INTERRUPT_LEVEL)
{
case 4:
if(sivec_ic != IC_LEVEL_4)
return;
break;
default:
return; /* INTERRUPT NOT Level 4 */
}
/*----------------------------------------------------------*/
/* Set IACK bit in CIVR to request current interrupt vector */
/*----------------------------------------------------------*/
IMMR->cpmi_civr |= CIVR_IACK;
/*-----------------------------------------------*/
/* Test CPM Interrupt Vector against SCC2 Vector */
/*-----------------------------------------------*/
if ((IMMR->cpmi_civr >> 11) != SCC2_VECTOR)
return;
/*-------------------------------------------*/
/* Clear SCC2 Event Register (by writing 1s) */
/*-------------------------------------------*/
IMMR->scc_regs[SCC2_REG].scc_scce = ALL_ONES;
/*---------------------------------------------------------*/
/* Process SCC HDLC Event if the event flag for RXF is set */
/*---------------------------------------------------------*/
if (scce & HDLC_SCCE_RXF)
{
/*-------------------------------------------------------------------*/
/* Traverse through available Receive Buffers to locate first filled */
/* buffer. */
/*-------------------------------------------------------------------*/
for(index = RxProcIndex; index < NUM_RXBDS; index++)
{
if (!BDEmpty(RxTxBD->RxBD[index].bd_cstatus))
{
/*-------------------------------------------------------------*/
/* Compare the receive buffer with it's corresponding transmit */
/* buffer. */
/*-------------------------------------------------------------*/
if (memcmp(&BufferPool[index],
&BufferPool[index+FIRST_TX_BUF],
(BUFFER_SIZE-2)))
{
RxGood=FALSE; /* they didn't compare */
}
/******************************************************************/
/* I've designed the architecture so that every frame of data */
/* encompasses a buffer descriptor's worth of data. This a very */
/* simple example. Normally there could be several BD's in a */
/* HDLC frame and once a buffer data was processed, the BD could */
/* be released for use. Also, the BDs in this case are linear/in */
/* order in terms of their processing. Normally BD's would not be */
/* guaranteed to be linear so this interrupt code would have to */
/* look for the next BD that wasn't empty and process accordingly.*/
/******************************************************************/
/*----------------------------------------------------------------*/
/* In my example, every BD is the last BD because every frame */
/* holds one buffer per BD. I only include the function "LastBD()"*/
/* so that the user can expand/modify the code to consider */
/* multiple BDs in one frame. */
/*----------------------------------------------------------------*/
if(!LastBD(RxTxBD->RxBD[index].bd_cstatus ))
{
RxTxBD->RxBD[index].bd_cstatus |= 0x8000; /* set empty flag */
/*-------------------------------------*/
/* checking all status bits for errors */
/*-------------------------------------*/
if (BDRxError(RxTxBD->RxBD[index].bd_cstatus ))
RxGood = FALSE;
}
/*-------------------------------------------------------------*/
/* This is the last BD in the chain. Clear all bits but the */
/* Ready bit and Wrap bit. */
/*-------------------------------------------------------------*/
if (index == (NUM_RXBDS-1))
RxTxBD->RxBD[index].bd_cstatus = 0xA000;
/*--------------------------------------------------------------*/
/* Set RX process index to start next BD scan from the BD after */
/* this one */
/*--------------------------------------------------------------*/
RxProcIndex = index+ 1;
}
}
}
else
RxGood = FALSE; /* Expected to see RXF event in SCCE */
/*---------------------------------------------------------------------*/
/* Here's our error loop. Spin here indefinitly if there was an error. */
/*---------------------------------------------------------------------*/
if (RxGood == FALSE)
{
while (1)
FlashEthled(); /* spin here if error is flagged */
}
/*-----------------------------------------------------------------*/
/* Clear CPM Interrupt In-Service Register SCC2 bit (by writing 1) */
/*-----------------------------------------------------------------*/
IMMR->cpmi_cisr |= CISR_SCC2;
} /* end ExtIntHandler */
/*-----------------------------------------------------------------------------
*
* FUNCTION NAME: GetIMMR
*
* DESCRIPTION:
*
* returns in R3, the current value in IMMR register. The IMMR register must
* be accessed in this manner because it is a special purpose register.
*
* EXTERNAL EFFECTS: None
*
* PARAMETERS: none
*
* RETURNS: IMMR value in R3.
*-----------------------------------------------------------------------------*/
GetIMMR()
{
/*--------------------------------------------------------------------*/
/* r3 is the register that the compiler is using for the return value */
/* In other words, r3 is the implicit return value. */
/*--------------------------------------------------------------------*/
#ifdef MetaWare
_ASM(" mfspr %r3,638 "); /* IMMR is spr #638 */
#else
#ifdef Diab
asm(" mfspr r3,638 "); /* IMMR is spr #638 */
#endif
#endif
} /* end GetIMMR */
/*-----------------------------------------------------------------------------
*
* FUNCTION NAME: Ethled
*
* DESCRIPTION:
*
* Turn On/Off Ethernet LED on 821/860 ADS board.
*
* EXTERNAL EFFECTS:
*
* PARAMETERS:
*
* setting - 0 turns off LED; otherwise turn on LED.
*
* RETURNS: NONE
*
*-----------------------------------------------------------------------------*/
void Ethled(UHWORD setting)
{
BCSR *csr;
csr = (BCSR *)(IMMR->memc_br1 & 0xFFFF8000);
if (setting)
csr->bcsr1 &= ~ETHEN; /* turn on LED, active low */
else
csr->bcsr1 |= ETHEN; /* turn off LED, active high */
} /* end Ethled */
/*-----------------------------------------------------------------------------
*
* FUNCTION NAME: FlashEthled
*
* DESCRIPTION: This function flashes the Ethernet LED
*
* EXTERNAL EFFECTS: None
*
* PARAMETERS: none
*
* RETURNS: None
*
*-----------------------------------------------------------------------------*/
void FlashEthled()
{
UBYTE ii;
UWORD jj;
for (ii = 0; ii<20; ii++)
{
Ethled(ii%2); /* Turn on every other time through the loop */
for (jj=0; jj < 100000; jj++); /* Wait */
}
Ethled(0); /* LED off */
} /* end FlashEthled */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -