📄 mb86960end.c
字号:
mb86960PollStart (pDrvCtrl); break; case EIOCPOLLSTOP: mb86960PollStop (pDrvCtrl); break; case EIOCMULTIADD: error = mb86960MCastAddrAdd (pDrvCtrl, (char *)data); break; case EIOCMULTIDEL: error = mb86960MCastAddrDel (pDrvCtrl, (char *)data); break; case EIOCMULTIGET: error = mb86960MCastAddrGet (pDrvCtrl, (MULTI_TABLE *)data); break; case EIOCGMIB2: if (data == NULL) return (EINVAL); bcopy((char *)&pDrvCtrl->end.mib2Tbl, (char *)data, sizeof(pDrvCtrl->end.mib2Tbl)); break;#if 0 case EIOCGFBUF: if (data == NULL) return (EINVAL); *(int *)data = END_MIN_FBUF; break;#endif default: error = EINVAL; } return (error); }/******************************************************************************** mb86960Reset - reset state initialization for the device** This routine initializes the MB86960 device after a reset / reboot. * of addresses (added with the endAddrAdd() routine) and sets the* device's filter correctly.** RETURNS: N/A.*/LOCAL void mb86960Reset ( MB86960_END_CTRL *pDrvCtrl /* device to be re-configured */ ) { /* Set promiscuous mode if it's asked for. */#if 0 if (END_FLAGS_GET(&pDrvCtrl->end) & IFF_PROMISC) { DRV_LOG (DRV_DEBUG_LOAD, "Setting promiscuous mode on!\n", 1, 2, 3, 4, 5, 6); } else { DRV_LOG (DRV_DEBUG_LOAD, "Setting promiscuous mode off!\n", 1, 2, 3, 4, 5, 6); } /* Set up address filter for multicasting. */ if (END_MULTI_LST_CNT(&pDrvCtrl->end) > 0) { mb86960AddrFilterSet (pDrvCtrl); }#endif /* shutdown device completely */ SYS_OUT_SHORT ((pDrvCtrl->devBaseAddr + NICE_INTRMASK), 0); SYS_OUT_SHORT ((pDrvCtrl->devBaseAddr + NICE_STATUS), 0xffff); return; }/******************************************************************************** mb86960Config - reconfigure the interface under us.** Reconfigure the interface setting promiscuous mode, and changing the* multicast interface list.** RETURNS: N/A.*/LOCAL void mb86960Config ( MB86960_END_CTRL * pDrvCtrl ) { u_short temp; /* scratch pad */ char * pDev = pDrvCtrl->devBaseAddr; /* initial setup of config register 1 */ temp = (DLCR6_DISABLE_DLC | /* resets things */ DLCR6_BIT_6 | /* just do it */ DLCR6_SYS_BUS_16 | /* use 16 bits */ DLCR6_BUF_BUS_16 | /* use 16 bits */ DLCR6_TBS_4KB | /* Tx buf is 4kb */ DLCR6_BS_16KB | /* total buf is 16k */ DLCR7_CNF_NICE | /* normal NICE mode */ DLCR7_PWRDN_OFF | /* normal power mode */ DLCR7_BIT_4 | /* just do it */ DLCR7_REG_BNK_DLC | /* map node ID regs */ DLCR7_ENDIAN_LITTLE ); SYS_OUT_SHORT ((pDev + NICE_CONFIG), temp); /* Mask off all interrupts and clear all event flags. */ SYS_OUT_SHORT ((pDev + NICE_INTRMASK), 0); SYS_OUT_SHORT ((pDev + NICE_STATUS), 0xffff); /* Disable device interrupt at system level and clear any pended. */ SYS_INT_DISABLE (pDrvCtrl); /* The secondary DLC register group is mapped in. Set the node ID. */ SYS_OUT_SHORT ((pDev + NICE_ADDR1), (((u_short *) pDrvCtrl->enetAddr)[0])); SYS_OUT_SHORT ((pDev + NICE_ADDR2), (((u_short *) pDrvCtrl->enetAddr)[1])); SYS_OUT_SHORT ((pDev + NICE_ADDR3), (((u_short *) pDrvCtrl->enetAddr)[2])); /* Change register map. Select buffer memory register group. */ SYS_IN_SHORT ((pDev + NICE_CONFIG), temp); temp &= ~DLCR7_REG_BNK; /* clear bank select bits */ temp |= DLCR7_REG_BNK_HASH; /* add desired bits */ SYS_OUT_SHORT ((pDev + NICE_CONFIG), temp); /* clear all bits in hash table array */ SYS_OUT_SHORT ((pDev + NICE_HASH1), 0); SYS_OUT_SHORT ((pDev + NICE_HASH2), 0); SYS_OUT_SHORT ((pDev + NICE_HASH3), 0); SYS_OUT_SHORT ((pDev + NICE_HASH4), 0); temp &= ~DLCR7_REG_BNK; /* clear bank select bits */ temp |= DLCR7_REG_BNK_BMR; /* add desired bits */ SYS_OUT_SHORT ((pDev + NICE_CONFIG), temp); /* * Setup the receiver and transmitter modes. Note that in * order to enable multicast + hash table, the bit * DLCR5_AF1 must be set. The documentation for the * MB86960 says otherwise but is not correct */ SYS_OUT_SHORT ((pDev + NICE_MODE), (DLCR4_LBC | DLCR5_BIT_2 | DLCR5_AF1)); /* Enable the DLC. */ SYS_IN_SHORT ((pDev + NICE_CONFIG), temp); /* get config reg */ temp &= ~DLCR6_DISABLE_DLC; /* clear the disable bit */ SYS_OUT_SHORT ((pDev + NICE_CONFIG), temp); /* update config reg */ /* set collision control drop packet after 16 collisions */ SYS_OUT_SHORT ((pDev + NICE_TRANSMIT), (BMR11_MASK16 | BMR11_RST_TX16 | BMR11_OPT_16_COLL)); }/********************************************************************************* mb86960PollRcv - routine to receive a packet in polled mode.** This routine is called by a user to try and get a packet from the* device.** RETURNS: OK upon success. EAGAIN is returned when no packet is available.*/LOCAL STATUS mb86960PollRcv ( MB86960_END_CTRL * pDrvCtrl, /* device to be polled */ M_BLK_ID pMblk /* ptr to buffer */ ) { STATUS retCode = OK; MB86960_RX_FRAME * pCluster; int len; if (mb86960RxMore (pDrvCtrl) == FALSE) return (EAGAIN); pCluster = (MB86960_RX_FRAME *) netClusterGet (pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId); if (pCluster == NULL) { DRV_LOG (DRV_DEBUG_POLL_RX, "Cannot loan!\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); return (EAGAIN); } retCode = mb86960PacketGet (pDrvCtrl, pCluster); if (retCode == OK) { len = pCluster->rxHdr.len; pMblk->mBlkHdr.mFlags |= M_PKTHDR; /* set the packet header */ pMblk->mBlkHdr.mLen = len; /* set the data len */ pMblk->mBlkPktHdr.len = len; /* set the total len */ bcopy ((char *)(char *) &pCluster->enetHdr, (char *)pMblk->mBlkHdr.mData, len); netClFree (pDrvCtrl->end.pNetPool, (char*)pCluster); END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1); } else retCode = EAGAIN; DRV_LOG (DRV_DEBUG_POLL_RX, "Received packet\n", 1, 2, 3, 4, 5, 6); return (retCode); }/********************************************************************************* mb86960PollSend - routine to send a packet in polled mode.** This routine is called by a user to try and send a packet on the* device.** RETURNS: OK upon success. EAGAIN if device is busy.*/LOCAL STATUS mb86960PollSend ( MB86960_END_CTRL* pDrvCtrl, /* device to be polled */ M_BLK_ID pMblk /* packet to send */ ) { return (mb86960Send (pDrvCtrl, pMblk)); }/******************************************************************************* mb86960MCastAddrAdd - add a multicast address for the device** This routine adds a multicast address to whatever the driver* is already listening for. It then resets the address filter.** RETURNS: OK or ERROR.*/LOCAL STATUS mb86960MCastAddrAdd ( MB86960_END_CTRL * pDrvCtrl, /* device pointer */ char * pAddress /* new address to add */ ) { int error; if ((error = etherMultiAdd (&pDrvCtrl->end.multiList, pAddress)) == ENETRESET) mb86960AddrFilterSet (pDrvCtrl, pAddress, TRUE); return (OK); }/******************************************************************************* mb86960MCastAddrDel - delete a multicast address for the device** This routine removes a multicast address from whatever the driver* is listening for. It then resets the address filter.** RETURNS: OK or ERROR.*/LOCAL STATUS mb86960MCastAddrDel ( MB86960_END_CTRL * pDrvCtrl, /* device pointer */ char * pAddress /* address to be deleted */ ) { int error; if ((error = etherMultiDel (&pDrvCtrl->end.multiList, (char *)pAddress)) == ENETRESET) mb86960AddrFilterSet (pDrvCtrl, pAddress, FALSE); return (OK); }/******************************************************************************* mb86960MCastAddrGet - get the multicast address list for the device** This routine gets the multicast list of whatever the driver* is already listening for.** RETURNS: OK or ERROR.*/LOCAL STATUS mb86960MCastAddrGet ( MB86960_END_CTRL* pDrvCtrl, /* device pointer */ MULTI_TABLE* pTable /* address table to be filled in */ ) { return (etherMultiGet (&pDrvCtrl->end.multiList, pTable)); }/******************************************************************************** mb86960AddrFilterSet - set the address filter for multicast addresses** This routine goes through all of the multicast addresses on the list* of addresses (added with the MCastAddrAdd() routine) and sets the* device's filter correctly.** NOMANUAL*/LOCAL void mb86960AddrFilterSet ( MB86960_END_CTRL* pDrvCtrl, /* device pointer */ char * pAddr, BOOL bSet ) { UINT16 nRegOffset; UINT16 nBitPosition; UINT16 nBitMask = 0x01; UINT16 index; char * pReg; UINT16 temp; char * pDev = pDrvCtrl->devBaseAddr; UINT16 saveConfig; /* get hash index for the address */ index = mb86960HashIndex (pAddr); nRegOffset = index; nBitPosition= index; /* Find register and bit position */ nBitPosition = nBitPosition & 0x0f; /* 4 LSB bits */ nRegOffset >>= 4; nBitMask <<= nBitPosition; /* Change register map. Select hash memory register group. */ SYS_IN_SHORT ((pDev + NICE_CONFIG), temp); saveConfig = temp; temp &= ~DLCR7_REG_BNK; /* clear bank select bits */ temp |= DLCR7_REG_BNK_HASH; /* select hash table regs */ temp |= DLCR6_DISABLE_DLC; SYS_OUT_SHORT ((pDev + NICE_CONFIG), temp); pReg = pDrvCtrl->devBaseAddr + NICE_HASH1 + nRegOffset*4; /* set the bit in bit array */ nBitMask = MB86960_SWAP_SHORT(nBitMask); SYS_IN_SHORT(pReg, temp); if (bSet == TRUE) { temp |= nBitMask; /* set */ } else { nBitMask = ~nBitMask; /* reset */ temp &= nBitMask; } SYS_OUT_SHORT (pReg, temp); /* restore the configuration register */ SYS_OUT_SHORT ((pDev + NICE_CONFIG), saveConfig); }/********************************************************************************* mb86960HashIndex - compute the hash index for an ethernet address** RETURNS: hash index for an ethernet address.*/LOCAL int mb86960HashIndex ( char * pCp /* pointer to an ethernet address */ ) { char c; u_long crc; int len; int count; crc = 0xffffffff; for (len = 6; --len >= 0;) { c = *pCp++; for (count = 0; count < 8; count++) { if ((c & 0x01) ^ (crc & 0x01)) { crc >>= 1; crc = crc ^ MB86960_CRC_POLY; } else { crc >>= 1; } c >>= 1; } } /* Just want the 6 most significant bits. */ crc = crc >> 26; return (crc); }/********************************************************************************* mb86960Stop - stop the device** This function calls BSP functions to disconnect interrupts and stop* the device from operating in interrupt mode.** RETURNS: OK or ERROR.*/LOCAL STATUS mb86960Stop ( MB86960_END_CTRL * pDrvCtrl /* device to be stopped */ ) { STATUS result = OK; /* stop/disable the device. */ SYS_OUT_SHORT ((pDrvCtrl->devBaseAddr + NICE_INTRMASK), NO_RX_INTRMASK); SYS_INT_DISCONNECT (pDrvCtrl, mb86960Int, (int)pDrvCtrl, &result); if (result == ERROR) { DRV_LOG (DRV_DEBUG_LOAD, "Could not diconnect interrupt!\n", 1, 2, 3, 4, 5, 6); } else { END_FLAGS_CLR (&pDrvCtrl->end, (IFF_UP | IFF_RUNNING)); } return (result); }/******************************************************************************** mb86960Unload - unload a driver from the system** This function first brings down the device, and then frees any* stuff that was allocated by the driver in the load function.** RETURNS: OK or ERROR.*/LOCAL STATUS mb86960Unload ( MB86960_END_CTRL * pDrvCtrl /* device to be unloaded */ ) { END_OBJECT_UNLOAD (&pDrvCtrl->end); return (OK); }/********************************************************************************* mb86960PollStart - start polled mode operations** RETURNS: OK or ERROR.*/LOCAL STATUS mb86960PollStart ( MB86960_END_CTRL * pDrvCtrl /* device to be polled */ ) { int oldLevel; oldLevel = intLock (); /* disable ints during update */ /* turn off interrupts */ SYS_OUT_SHORT ((pDrvCtrl->devBaseAddr + NICE_INTRMASK), 0); intUnlock (oldLevel); /* now mb86960Int won't get confused */ pDrvCtrl->flags |= LS_POLLING; DRV_LOG (DRV_DEBUG_POLL, "STARTED\n", 1, 2, 3, 4, 5, 6); return (OK); }/********************************************************************************* mb86960PollStop - stop polled mode operations** This function terminates polled mode operation. The device returns to* interrupt mode.** The device interrupts are enabled, the current mode flag is switched* to indicate interrupt mode and the device is then reconfigured for* interrupt operation.** RETURNS: OK or ERROR.*/LOCAL STATUS mb86960PollStop ( MB86960_END_CTRL * pDrvCtrl /* device to be changed */ ) { int oldLevel; oldLevel = intLock (); /* disable ints during register updates */ /* Turn the receive interrupts on again. */ SYS_OUT_SHORT ((pDrvCtrl->devBaseAddr + NICE_INTRMASK), NORM_INTRMASK); intUnlock (oldLevel); pDrvCtrl->flags &= ~LS_POLLING; DRV_LOG (DRV_DEBUG_POLL, "STOPPED\n", 1, 2, 3, 4, 5, 6); return (OK); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -