📄 if_lnsgi.c
字号:
if ((int) memAdrs == NONE) ls->ls_flags |= LS_MEM_ALLOC_FLAG; ls->bufSize = bufSize; /* if memWidth is NONE (we can copy any byte size/boundaries) and * bufSize is big enough to hold the biggest ethernet frame * we can loan out rmds. On systems that cannot afford to have * big enough RMD's, LANCE will use data-chaining on receive * buffers. Our current implementation of RMD loans does not work * with receive side data-chains. */ if (ls->memWidth == NONE && ls->bufSize == LN_BUFSIZE) { int ix; char *pBuf; ls->canLoanRmds = TRUE; ls->nFree = LN_NUM_RESERVES; if ((pBuf = (char *) malloc ((u_int) (LN_NUM_RESERVES * bufSize))) == NULL) { (void) free (memPool); (void) free ((char *) ls); return (ERROR); } for (ix = 0; ix < LN_NUM_RESERVES; ix++) ls->freeBufs [ix] = (char *) ((int) pBuf + (bufSize * ix)); } else ls->canLoanRmds = FALSE; /* allocate initialization block */ ls->ib = (ln_ib *)memPool; sz = sizeof (ln_ib); /* size of initialization block */ bzero ((char *)ls->ib, (int) sz); /* zero out entire ib */ /* allocate receive message descriptor (RMD) ring structure */ ls->ls_rpo2 = lnRsize; /* remember for lnConfig */ ls->ls_rsize = (1 << lnRsize); /* receive msg descriptor ring size */ /* leave room to adjust low three bits */ ls->ls_rring = (ln_rmd *) ((int)ls->ib + sz); /* of pointer to be 000 */ sz = ((1 << lnRsize) + 1) * sizeof (ln_rmd); bzero ((char *)ls->ls_rring, (int)sz); /* zero out entire RMD ring */ /* allocate receive buffer space */ sz = sz + 2; /* this makes the rx_buffers un-aligned, */ /* but with ether-header prepended, they are */ ls->rmd_ring.r_bufs = (char *)((int)ls->ls_rring + sz); sz = (bufSize << lnRsize); /* room for all the receive buffers */ bzero (ls->rmd_ring.r_bufs, (int)sz);/* zero out entire rbuf area */ /* allocate transmit message descriptor (TMD) ring structure */ ls->ls_tpo2 = lnTsize; /* remember for lnConfig */ ls->ls_tsize = (1 << lnTsize); /* transmit msg descriptor ring size */ sz = sz + 2; /* make ls_tring aligned again */ ls->ls_tring = (ln_tmd *) ((int)ls->rmd_ring.r_bufs + sz); sz = ((1 << lnTsize) + 1) * sizeof (ln_tmd); bzero ((char *)ls->ls_tring, (int)sz); /* zero out entire TMD ring */ /* allocate transmit buffer space */ sz = sz + 2; /* this makes the tx_buffers un-aligned, */ /* but with ether-header prepended, they are */ ls->tmd_ring.t_bufs = (char *)((int)ls->ls_tring + sz); sz = (bufSize << lnTsize); /* room for all the transmit buffers */ bzero (ls->tmd_ring.t_bufs, (int)sz); /* zero out entire tbuf area */ ls_softc [unit] = ls; /* remember address for this unit */ /* initialize device structure */ ls->ivec = ivec; /* interrupt vector */ ls->ilevel = ilevel; /* interrupt level */ ls->devAdrs = (LN_DEVICE *)devAdrs; /* LANCE i/o address */ /* copy the enet address into the softc */ bcopy ((char *) lnsgiEnetAddr, (char *)ls->ls_enaddr, sizeof (ls->ls_enaddr)); ifp = &ls->ls_if; /* attach and enable the LANCE interrupt service routine to vector */ lnChipReset (ls); /* reset LANCE */ (void) intConnect (INUM_TO_IVEC (ivec), lnInt, (int)ls);#ifdef BSD43_DRIVER ether_attach (ifp, unit, "lnsgi", (FUNCPTR) lnInit, (FUNCPTR) lnIoctl, (FUNCPTR) lnOutput, (FUNCPTR) lnReset);#else ether_attach ( ifp, unit, "lnsgi", (FUNCPTR) lnInit, (FUNCPTR) lnIoctl, (FUNCPTR) ether_output, (FUNCPTR) lnReset ); ifp->if_start = (FUNCPTR) lnStartOutput; #endif sysLanIntEnable (ilevel); lnInit (unit); return (OK); }/********************************************************************************* lnReset - reset the interface** Mark interface as inactive & reset the chip*/LOCAL void lnReset ( int unit ) { FAST DRV_CTRL * ls = ls_softc [unit]; ls->ls_if.if_flags &= ~IFF_RUNNING; lnChipReset (ls); /* reset LANCE */ }/********************************************************************************* lnInit -** Initialization of interface; clear recorded pending operations.* Called during driver attach routine at boot time and by interrupt service* routines when fatal errors occur.*/LOCAL int lnInit ( int unit ) { FAST DRV_CTRL * ls = ls_softc [unit]; FAST struct ifnet * ifp = &ls->ls_if; ifp->if_flags &= ~(IFF_UP | IFF_RUNNING | IFF_PROMISC); lnChipReset (ls); /* disable chip during init */ lnConfig (ls); /* reset all ring structures */ ifp->if_flags |= (IFF_UP | IFF_RUNNING); if (ls->ls_flags & LS_PROMISCUOUS_FLAG) ifp->if_flags |= (IFF_PROMISC); lnChipInit (ls); /* on return LANCE is running */#ifdef BSD43_DRIVER lnStartOutput (ls->ls_if.if_unit); /* tell chip about any pending output */#else lnStartOutput (ls);#endif return (0); }/********************************************************************************* lnConfig - fill in initialization block with mode information.** Fill in all fields in the Initialization Block with relevant values.* In addition, fill in all fields in Transmit Message Descriptor ring* and Receive Message Descriptor ring.*/LOCAL void lnConfig ( FAST struct ls_softc *ls ) { FAST ln_rmd *rmd; FAST ln_tmd *tmd; FAST char *buf; FAST ln_ib *ib; FAST int index; int i; rmd = ls->ls_rring; /* receive message descriptor ring */ rmd = (ln_rmd *)(((int)rmd + 7) & ~7); /* low 3 bits must be 000 */ ls->ls_rring = rmd; /* fix softc as well */ sysWbFlush (); buf = ls->rmd_ring.r_bufs; for (i = 0; i < ls->ls_rsize; i++) { /* fill VIP10 dma table entry */ index = RBUF_INDEX + i; pEmap [EMAP_OFFSET(index)] = (u_short) EMAP_VALUE(buf); sysWbFlush (); /* bits 15:00 of buffer address */ rmd->rbuf_ladr = (u_short) LNADDR(index, buf); /* bits 23:16 of buffer address */ rmd->lnRMD1 = (u_short) ((u_int) (LNADDR(index, buf) >> 16) & 0xff); rmd->rbuf_bcnt = -(ls->bufSize);/* neg of buffer byte count */ rmd->rbuf_mcnt = 0; /* no message byte count yet */ rmd->lnRMD1 |= lnrmd1_OWN; /* buffer now owned by LANCE */ sysWbFlush (); /* make sure it gets out */ rmd++; /* step to next message descriptor */ buf += (ls->bufSize); /* step to start of next buffer */ ls->loanRefCnt [i] = (u_char) 0; } ls->ls_rindex = 0; /* LANCE will use at start of ring */ sysWbFlush (); tmd = ls->ls_tring; /* transmit message descriptor ring */ tmd = (ln_tmd *)(((int)tmd + 7) & ~7); /* low 3 bits must be 000 */ ls->ls_tring = tmd; /* fix softc as well */ sysWbFlush (); buf = ls->tmd_ring.t_bufs; for (i = 0; i < ls->ls_tsize; i++) { /* fill VIP10 dma table entry */ index = TBUF_INDEX + i; pEmap [EMAP_OFFSET(index)] = (u_short) EMAP_VALUE(buf); sysWbFlush (); /* bits 15:00 of buffer address */ tmd->tbuf_ladr = (u_short) LNADDR(index, buf); /* bits 23:16 of buffer address */ tmd->lnTMD1 = (u_short) ((u_int) (LNADDR(index, buf) >> 16) & 0xff); tmd->tbuf_bcnt = 0; /* no message byte count yet */ tmd->lnTMD3 = 0; /* no error status yet */ tmd->lnTMD1 |= lntmd1_ENP; /* buffer is end of packet */ tmd->lnTMD1 |= lntmd1_STP; /* buffer is start of packet */ sysWbFlush (); /* make sure it gets out */ tmd++; /* step to next message descriptor */ buf += (ls->bufSize); /* step to start of next buffer */ } ls->ls_tindex = 0; /* LANCE will use at start of ring */ ls->ls_dindex = 0; /* buffer disposal will lag tindex */ sysWbFlush (); ib = ls->ib; /* fill VIP10 dma table entry for initialization block */ index = IBUF_INDEX; pEmap [EMAP_OFFSET(index)] = (u_short) EMAP_VALUE(ib); sysWbFlush (); if (ls->ls_flags & LS_PROMISCUOUS_FLAG) ib->lnIBMode = 0x8000; /* chip will be in promiscuous receive mode */ else ib->lnIBMode = 0; /* chip will be in normal receive mode */ swab ((char *)ls->ls_enaddr, ib->lnIBPadr, 6); /* * Fill VIP10 RMD Desc and Bufs. Two buffers are allocated to accomadate * the crossing page boundries. RMD Desc and buffers should come right * after IB */ index++; pEmap [EMAP_OFFSET(index)] = (u_short) EMAP_VALUE(ls->ls_rring); sysWbFlush (); pEmap [EMAP_OFFSET(index + 1)] = (u_short) (EMAP_VALUE(ls->ls_rring) + 1); sysWbFlush (); ib->lnIBRdraLow = (u_short) LNADDR(index, ls->ls_rring); ib->lnIBRdraHigh = (u_short) ((u_int) (LNADDR(index, ls->ls_rring) >> 16) & 0xff) | (ls->ls_rpo2 << 13); sysWbFlush (); index += 2; pEmap [EMAP_OFFSET(index)] = (u_short) EMAP_VALUE(ls->ls_tring); sysWbFlush (); pEmap [EMAP_OFFSET(index + 1)] = (u_short) (EMAP_VALUE(ls->ls_tring) + 1); sysWbFlush (); ib->lnIBTdraLow = (u_short) LNADDR(index, ls->ls_tring); ib->lnIBTdraHigh = (u_short) ((u_int) (LNADDR(index, ls->ls_tring) >> 16) & 0xff) | (ls->ls_tpo2 << 13); sysWbFlush (); }/********************************************************************************* lnInt - handle controller interrupt** This routine is called at interrupt level in response to an interrupt from* the controller.*/LOCAL void lnInt ( FAST struct ls_softc *ls ) { FAST ln_rmd *rmd; FAST ln_tmd *tmd; FAST int *pDindex; FAST int *pTindex; FAST int *pTsize; FAST ln_tmd *pTring; FAST u_short stat; if (!((stat = lnCsrIntRead (ls, 0)) & lncsr_INTR)) { return; } /* * enable interrupts, clear receive and/or transmit interrupts, * and clear any errors that may be set. */ lnCsrIntWrite (ls, 0, ((stat & (lncsr_BABL | lncsr_CERR | lncsr_MISS | lncsr_MERR | lncsr_RINT | lncsr_TINT | lncsr_IDON)) | lncsr_INEA)); /* * have task level handle csr0 errors; */ if (stat & lncsr_ERR) { lnHandleCsr0Err (ls, stat); } /* have task level handle any input packets */ if ((stat & lncsr_RINT) && (stat & lncsr_RXON)) { if ((rmd = lnGetFullRMD (ls)) != NULL) { /* discard error input ASAP - don't queue it */ if (rmd->lnRMD1 & RMD_ERR) { if (lnsgiLogCount && (ls->ls_if.if_ierrors % lnsgiLogCount) == 0) logMsg ("ln%d lnInt: ERROR rmd1=0x%x mcnt %d\n", ls->ls_if.if_unit, rmd->lnRMD1 & 0xff00, rmd->rbuf_mcnt, 0, 0, 0); ls->ls_if.if_ierrors++; ls->ls_rindex = (ls->ls_rindex + 1) & (ls->ls_rsize - 1); sysWbFlush (); rmd->lnRMD1 &= ~RMD_ERR; LN_RMD_GIVE_TO_LANCE (rmd); sysWbFlush (); } else if ((ls->ls_flags & LS_RCV_HANDLING_FLAG) == 0) { ls->ls_flags |= LS_RCV_HANDLING_FLAG; (void) netJobAdd ((FUNCPTR) lnHandleRecvInt, (int) ls, 0, 0, 0, 0); } } } /* * Did LANCE update any of the TMD's? * If not then don't bother continuing with transmitter stuff */ if (!(stat & lncsr_TINT)) { /* common return path */ return; } pDindex = &ls->ls_dindex; pTindex = &ls->ls_tindex; pTsize = &ls->ls_tsize; pTring = ls->ls_tring; while (*pDindex != *pTindex) { /* disposal has not caught up */ tmd = pTring + *pDindex; cacheClearEntry(tmd, sizeof(ln_tmd)); /* if the buffer is still owned by LANCE, don't touch it */ if (tmd->lnTMD1 & TMD_OWN) break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -