📄 if_sn.c
字号:
#ifdef SN_DEBUG if (SN_DEBUG_TX && SN_DEBUG_VERBOSE) logMsg ("sn: Tx: reclaimed TXD=%x\n", (int)pTXD, 0, 0, 0, 0, 0);#endif /* SN_DEBUG */ } else /* ERROR! */ { pDrvCtrl->TxErrs++; /* bump our counter */ pDrvCtrl->pDev->cr = TXP; /* restart transmitter */ break; } /* Advance to the next TXD. */ pTXD = pTXD->pLink; /* Update the reclaim pointer for next time. */ pDrvCtrl->pTXDReclaim = pTXD; /* invalidate the cache for this TXD */ CACHE_DMA_INVALIDATE (&pTXD->status, sizeof (pTXD->status)); } }/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * SECTION: Receive related routines *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*//****************************************************************************** snRxPktReady - indicates a received packet is ready for processing*/LOCAL BOOL snRxPktReady (pDrvCtrl) DRV_CTRL *pDrvCtrl; { RX_DESC *pRXD; pRXD = pDrvCtrl->pRXDNext; CACHE_DMA_INVALIDATE (pRXD, RX_DESC_SIZ); if (pRXD->in_use == NOT_IN_USE) /* if not yet filled */ return (FALSE); return (TRUE); }/********************************************************************************* snRxPktProcess - process one received packet**/LOCAL STATUS snRxPktProcess (pDrvCtrl) DRV_CTRL *pDrvCtrl; { RX_DESC *pRXD; /* ptr to a packet descriptor */ struct ether_header *pPktHdr; /* ptr to packet header */ u_char *pData; /* ptr to packet data */ MBUF *pMbuf; /* ptr to mbuf structs */ SONIC *pDev; /* ptr to the device regs */ int len; int ndx; /* index into RRA desc array */ int status; /* return status */ u_short ether_type; /* safe copy of packet type */ int spl; /* The current RX_DESC will already have been made cache coherent * by the snRxPktReady() routine. There is no need to do it here. */ pRXD = pDrvCtrl->pRXDNext; /* get ptr to the desc */ len = (pRXD->byte_count & UMASK) - 4; /* get pkt length - FCS */ pPktHdr = (struct ether_header *) /* get ptr to pkt header */ (((pRXD->pkt_ptr1 & UMASK) << 16) | (pRXD->pkt_ptr0 & UMASK)); pPktHdr = (struct ether_header *) CACHE_DMA_PHYS_TO_VIRT (pPktHdr); /* Do some sanity checks on the RXD info */ if ( (len < 60) || (len > 1514) || (pPktHdr == NULL) || (!(pRXD->status & PRX)) || (pRXD->link == RX_EOL) || (pRXD->link == NULL) ) { logMsg ("sn: Fatal error. Receive structures invalid.\n",0,0,0,0,0,0); taskSuspend (0); return (ERROR); } pDrvCtrl->sn_if.if_ipackets++; /* bump statistic */ /* advance our mgmt variable */ pDrvCtrl->pRXDNext = (RX_DESC *) CACHE_DMA_PHYS_TO_VIRT (pRXD->link);#ifdef SN_DEBUG if (SN_DEBUG_RX && SN_DEBUG_VERBOSE) logMsg ("sn: Rx: packet addr=0x%x, len=0x%x, pRXD=0x%x\n", (int)pPktHdr, len, (int)pRXD, 0, 0, 0); if (SN_DEBUG_TRACE) { logMsg ("sn: Rx: packet type 0x%x from %s", pPktHdr->ether_type, (int)ether_sprintf (&pPktHdr->ether_shost), 0, 0, 0, 0); logMsg (" to %s\n", (int) ether_sprintf (&pPktHdr->ether_dhost), 0, 0, 0, 0, 0); }#endif /* SN_DEBUG */ CACHE_DMA_INVALIDATE (pPktHdr, len); /* call input hook if any */ if (etherInputHookRtn != NULL) { if ((* etherInputHookRtn) (&pDrvCtrl->sn_if, (char *)pPktHdr, len)) return (OK); } /* Subtract size of enet header from packet length. */ len -= 14; /* Set pData to begining of packet data. */ pData = (u_char *)pPktHdr; pData += 14; /* save the packet type, since build_cluster modifies the packet header */ ether_type = pPktHdr->ether_type; /* convert packet data into mbufs */ spl = splnet (); pMbuf = copy_to_mbufs (pData, len, 0, (IFNET *) &pDrvCtrl->sn_if); splx (spl); /* We are now done with the packet descriptor and the packet data. * First we manage the packet buffer mechanisms, then we manage * the packet descriptor mechanisms. */ { /* done with packet buffer */ if (pRXD->status & LPKT) /* if last pkt in this buffer */ { /* form index to RRA descriptor this packet associates with */ ndx = (((pRXD->seq_no & 0x0000ff00) >> 8) + 1) % NUM_RRA_DESC; pDev = pDrvCtrl->pDev; pDev->rwp = (unsigned long)(&((RRA_DESC *)pDrvCtrl->RSA)[ndx]) & UMASK; if (pDev->isr & RBE) /* deal with RBE condition */ pDev->isr = RBE; /* clear the RBE condition */ } } { /* done with the desc */ pRXD->in_use = NOT_IN_USE; /* Set NOT_IN_USE */ pRXD->link = RX_EOL; /* Last one */ /* Link into list */ pDrvCtrl->pRXDLast->link = (RX_DESC *) CACHE_DMA_VIRT_TO_PHYS (pRXD); pDrvCtrl->pRXDLast = pRXD; /* update our mgmt variable */ } if (pMbuf == NULL) { logMsg ("sn: out of mbufs\n",0,0,0,0,0,0); pDrvCtrl->sn_if.if_ierrors++; /* bump error statistic */ status = ERROR; } else { /* give the packet to the appropriate protocol */ spl = splnet ();#ifdef BSD43_DRIVER do_protocol_with_type (ether_type, pMbuf, &pDrvCtrl->sn_ac, len);#else do_protocol (pPktHdr, pMbuf, &pDrvCtrl->sn_ac, len);#endif splx (spl); status = OK; } return (status); }/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * SECTION: Interrupt driven routines, and primary event handler *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*//********************************************************************************* snIntr - device interrupt handler** This routine is called at interrupt level in response to an interrupt from* the device.** Only the "received packet" interrupt event is acknowledged and serviced* in this routine. Some of the exception conditions are handled elsewhere.*/LOCAL void snIntr (int unit) { DRV_CTRL *pDrvCtrl; /* ptr to driver ctrl struct */ SONIC *pDev; /* ptr to the device regs */ pDrvCtrl = & drvCtrl [unit]; pDev = pDrvCtrl->pDev; if ((pDev->isr & pDev->imr) & TCEN) { if (pDrvCtrl->timerIntHandler) { pDev->cr = STP; pDev->isr = TCEN; (*pDrvCtrl->timerIntHandler)(); pDev->wt0 = pDrvCtrl->ticks & 0xffff; pDev->wt1 = pDrvCtrl->ticks >> 16; pDev->cr = ST; } } if ((pDev->isr & pDev->imr) & (PKTRX | TXDN | TXER)) { /* disable further interrupts (except timer and bus retry enable). */ pDev->imr = (pDrvCtrl->imr &= BREN | TCEN); (void) netJobAdd ( /* queue netTask job */ (FUNCPTR)snEventHandler, unit, 0,0,0,0 ); } /* Handle bus retry interrupt. */ if (pDev->isr & BR) pDev->isr = BR; sysEnetIntAck (unit); /* do system int ack */ }/********************************************************************************* snEventHandler - device event handler, a netTask job*/LOCAL void snEventHandler (int unit) { DRV_CTRL *pDrvCtrl; SONIC *pDev; /* ptr to the device regs */ int loops;#ifdef SN_DEBUG if (SN_DEBUG_EVENT) logMsg ("sn: event handler enter\n", 0, 0, 0, 0, 0, 0);#endif /* SN_DEBUG */ /* Give up the spl semaphore. We don't need it yet, even though the * netTask thinks we do. */ splx (0); pDrvCtrl = & drvCtrl [unit]; pDev = pDrvCtrl->pDev; loops = 0; /* Loop, processing events */ while ( pDev->isr & (PKTRX | TXDN | TXER) ) { /* Process received packets */ if (pDev->isr & PKTRX) { while (snRxPktReady (pDrvCtrl)) /* packets ready? */ { pDev->isr = PKTRX; /* clear this interrupt */ snRxPktProcess (pDrvCtrl); } } /* Process transmitter events */ if ( pDev->isr & (TXDN | TXER) ) { pDev->isr = (TXDN | TXER); /* clear these interrupts */ snTxReclaim (pDrvCtrl); } loops++; } /* Take the spl semaphore before we return to the main loop of the * netTask. This is done because the spl semaphore is assumed to be * owned by netTask after this routine returns. */ (void) splnet (); /* Enable the interrupts */ pDev->imr = (pDrvCtrl->imr |= PKTRX | TXDN | TXER);#ifdef SN_DEBUG if (SN_DEBUG_EVENT) logMsg ("sn: event handler exit %d\n", loops, 0, 0, 0, 0, 0);#endif /* SN_DEBUG */ }/********************************************************************************* snClkEnable - enable the SONIC timer interrupt** This routine enables the SONIC timer to give a periodic interrupt.* The <unit> parameter selects the SONIC device. The <ticksPerSecond>* parameter specifies the number of interrupts to generate per second.* When an interrupt occurs, the function in <intHandler> is called.** NOTE:* The SONIC clock interrupt is dependent on the SONIC interface being* configured and enabled. For this reason, this interrupt is unsuitable* for use as the main system clock. It is suitable for use as an auxiliary* clock source for boards that have no other source of clock.** RETURNS: N/A** SEE ALSO: snClkDisable()** NOMANUAL*/void snClkEnable ( int unit, /* unit number */ int ticksPerSecond, /* interrupt frequency */ FUNCPTR intHandler /* interrupt handler */ ) { DRV_CTRL *pDrvCtrl; SONIC *pDev; int key; pDrvCtrl = & drvCtrl [ unit ]; pDev = pDrvCtrl->pDev; key = intLock (); pDrvCtrl->timerIntHandler = intHandler; pDrvCtrl->ticks = 5000000 / ticksPerSecond; pDrvCtrl->imr |= TCEN; if (pDev) { pDev->cr = STP; pDev->wt0 = pDrvCtrl->ticks & 0xffff; pDev->wt1 = pDrvCtrl->ticks >> 16; pDev->imr = pDrvCtrl->imr; pDev->cr = ST; } intUnlock (key); }/********************************************************************************* snClkDisable - disable the SONIC timer interrupt** This routine disables the SONIC timer interrupt. The <unit> parameter* selects the SONIC device.** RETURNS: N/A** SEE ALSO: snClkEnable()** NOMANUAL*/void snClkDisable ( int unit /* unit number */ ) { DRV_CTRL *pDrvCtrl; SONIC *pDev; int key; pDrvCtrl = & drvCtrl [ unit ]; pDev = pDrvCtrl->pDev; if (pDev) { key = intLock (); pDev->imr = (pDrvCtrl->imr &= ~TCEN); pDev->cr = STP; intUnlock (key); } }/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * SECTION: NOTES *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*//* END OF FILE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -