📄 ethernet.c
字号:
*
* 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 SCC1)
*
* Main Processing Steps:
** (1) Save off SCCE for SCC1 (SCC1 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 SCC1.
** (7) Clear SCC1 Event Register
** (8) Test SCC1 Event
** (9) Clear SCC1 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[SCC1_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 SCC1 Vector */
/*-----------------------------------------------*/ if ((IMMR->cpmi_civr >> 11) != SCC1_VECTOR)
return;
/*-------------------------------------------*/ /* Clear SCC1 Event Register (by writing 1s) */
/*-------------------------------------------*/ IMMR->scc_regs[SCC1_REG].scc_scce = ALL_ONES;
/*-------------------------------------------------------------*/
/* Process SCC Ethernet Event if the event flag for RXF is set */
/*-------------------------------------------------------------*/
if (scce & 0x0008)
{
/*--------------------------------------------*/
/* Traverse through available Receive Buffers */
/* to locate first filled buffer. */
/*--------------------------------------------*/
while ((!BDEmpty(RxTxBD->RxBD[index].bd_cstatus) &&
(index < NUM_RXBDS)))
{
/*---------------------------------------*/
/* Compare the receive buffer with its */
/* corresponding transmit buffer. */
/*---------------------------------------*/
if (memcmp(&BufferPool[index],
&BufferPool[index+FIRST_TX_BUF],
(BUFFER_SIZE-4)))
{
RxGood=FALSE; /* they didn't compare */
}
/*************************************************************/
/* In this architecture, every frame encompasses a buffer */
/* descriptor's worth of data. This a very simple example. */
/* Normally there could be several BD's in a frame, and once */
/* a data buffer was processed, it could be released for */
/* use. Note also that the BDs in this example are processed */
/* in linear fashion. Typically, BD's would not be */
/* guaranteed to be linear, so more "realistic" interrupt */
/* code would have to search for the next BD that wasn't */
/* empty and process it accordingly. */
/*************************************************************/
/*--------------------------------------------------------*/
/* In this example, EVERY BD is the first and last BD in */
/* frame, because every frame holds one buffer per BD. We */
/* 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;
index++;
}
}
else
RxGood = FALSE; /* Expected to see RXF event in SCCE */
/*-------------------------------------*/
/* Here's our error loop. Spin here */
/* indefinitely if there was an error. */
/*-------------------------------------*/
if (RxGood == FALSE)
{
while (1)
FlashEthled(); /* spin here if error is flagged */
}
/*-----------------------------------------------------------------*/
/* Clear CPM Interrupt In-Service Register SCC1 bit (by writing 1) */
/*-----------------------------------------------------------------*/
IMMR->cpmi_cisr |= CISR_SCC1;
} /* 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 + -