📄 dp83815.c
字号:
DP_REG16_WRITE(DP_TBTSCR, 0x0866); /* suppress heartbeat */ DP_REG32_WRITE(DP_MIBC, 0x0000); /* don't freeze MIB counters */ dp_cfg_val = (DP_CFG_PESEL | /* parity error detect */ DP_CFG_ANEG_SEL_ALL_XD | /* negotiate 10/100 full/half */ DP_CFG_PAUSE_ADV | /* pause capable */ DP_CFG_PINT_ACEN | /* phy intr auto clear */ 0x00040000); /* phy config */ DP_REG32_WRITE(DP_CFG, dp_cfg_val | DP_CFG_PHY_RST); microsleep(500); DP_REG32_WRITE(DP_CFG, dp_cfg_val); /*-------------------------------------------------------------------*/ /* Wait for auto-negotiation to finish. */ /*-------------------------------------------------------------------*/ for (timeout = 10000; timeout; --timeout) { if (DP_REG32_READ(DP_CFG) & DP_CFG_ANEG_DN) break; microsleep(500); } if (timeout == 0) return -1; /*-------------------------------------------------------------------*/ /* Read negotiation status. */ /*-------------------------------------------------------------------*/ phy_status = DP_REG16_READ(DP_PHYSTS); /*-------------------------------------------------------------------*/ /* Set flag if full duplex is enabled. */ /*-------------------------------------------------------------------*/ FullDuplex = phy_status & DP_PHYSTS_FDX; /*-------------------------------------------------------------------*/ /* Display the interface status. */ /*-------------------------------------------------------------------*/ printf("dp83815: speed=%s duplex=%s link=%s\n", (phy_status & DP_PHYSTS_SPEED_10) ? "10" : "100", FullDuplex ? "full" : "half", (phy_status & DP_PHYSTS_LNK_VALID) ? "up" : "down"); return 0;}/***********************************************************************//* ni_init: Initialize the Ethernet hardware *//* *//***********************************************************************/static int ni_init(void){ tmLibdevErr_t tm_err; PnP pnp; ui16 pci_cfgcmd; BufDescType *bd_ptr; ui32 temp; /*-------------------------------------------------------------------*/ /* See if the device exists. */ /*-------------------------------------------------------------------*/ tm_err = PnPOpen(DP83815_VENDOR_ID, DP83815_DEVICE_ID, 0, &pnp); if (tm_err != TMLIBDEV_OK) { printf("dp83815: PnPOpen failed %08X\n", tm_err); return -1; } /*-------------------------------------------------------------------*/ /* Get I/O base address. */ /*-------------------------------------------------------------------*/ PnPGetBaseAddress(pnp, 0, &IoAddress); /*-------------------------------------------------------------------*/ /* Enable bus-mastering. */ /*-------------------------------------------------------------------*/ PnPConfigRead16(pnp, 4, &pci_cfgcmd); pci_cfgcmd |= 0x04; PnPConfigWrite16(pnp, 4, pci_cfgcmd); /*-------------------------------------------------------------------*/ /* Disable power management. */ /*-------------------------------------------------------------------*/ PnPConfigWrite32(pnp, 0x44, 0); /*-------------------------------------------------------------------*/ /* Get the Ethernet address. */ /*-------------------------------------------------------------------*/ if (get_eth_addr(OurAddress.byte)) return -1; printf("dp83815: MAC Address = "); printEth(OurAddress.byte); putchar('\n'); /*-------------------------------------------------------------------*/ /* Reset the device. */ /*-------------------------------------------------------------------*/ if (dev_reset()) { printf("dp83815: Device Reset failed\n"); return -1; } /*-------------------------------------------------------------------*/ /* Set the Ethernet address in hardware. */ /*-------------------------------------------------------------------*/ set_eth_addr(OurAddress.byte); /*-------------------------------------------------------------------*/ /* Install and enable ISR. */ /*-------------------------------------------------------------------*/ tm_err = PnPSetHandler(pnp, &ni_isr, TW_INTS_HND_AMD_PNA, 0); if (tm_err != TMLIBDEV_OK) { printf("dp83815: PnPSetHandler() error status = %08X\n", tm_err); return -1; } /*-------------------------------------------------------------------*/ /* Allocate memory for the receive and transmit buffer descriptors. */ /*-------------------------------------------------------------------*/ BufDesc = _cache_malloc(sizeof(BufDescType) * (NUM_RX_BDS + NUM_TX_BDS), -1); if (BufDesc == NULL) return -1; /*-------------------------------------------------------------------*/ /* Initialize the receive buffer descriptors as a ring. */ /*-------------------------------------------------------------------*/ RxFillBD = RxNextBD = bd_ptr = &BufDesc[BEG_RX_BD]; for (; bd_ptr < &BufDesc[END_RX_BD]; ++bd_ptr) { bd_ptr->link = htopl((ui32)(bd_ptr + 1)); bd_ptr->cmdsts = 0; bd_ptr->bufptr = 0; } bd_ptr->link = htopl((ui32)RxFillBD); bd_ptr->cmdsts = 0; bd_ptr->bufptr = 0; _cache_copyback(RxFillBD, sizeof(BufDescType) * NUM_RX_BDS); fill_rx_ring(); /*-------------------------------------------------------------------*/ /* Initialize the transmit buffer descriptors as a ring. */ /*-------------------------------------------------------------------*/ TxFreeBD = TxNextBD = bd_ptr = &BufDesc[BEG_TX_BD]; for (; bd_ptr < &BufDesc[END_TX_BD]; ++bd_ptr) { bd_ptr->link = htopl((ui32)(bd_ptr + 1)); bd_ptr->cmdsts = 0; bd_ptr->bufptr = 0; } bd_ptr->link = htopl((ui32)TxFreeBD); bd_ptr->cmdsts = 0; bd_ptr->bufptr = 0; _cache_copyback(TxFreeBD, sizeof(BufDescType) * NUM_TX_BDS); /*-------------------------------------------------------------------*/ /* Assign initial receive and transmit buffer descriptor pointers. */ /*-------------------------------------------------------------------*/ DP_REG32_WRITE(DP_RXDP, RxNextBD); DP_REG32_WRITE(DP_TXDP, TxNextBD); /*-------------------------------------------------------------------*/ /* Setup phy capabilities. */ /*-------------------------------------------------------------------*/ while (phy_setup()) printf("dp83815: Warning PHY setup did not complete. Check cable.\n"); /*-------------------------------------------------------------------*/ /* Setup transmit control. */ /*-------------------------------------------------------------------*/ temp = DP_TXCFG_DRTH_SET(48) | DP_TXCFG_FLTH_SET(16) | DP_TXCFG_MXDMA_32 | DP_TXCFG_ATP; if (FullDuplex) temp |= DP_TXCFG_CSI | DP_TXCFG_HBI; DP_REG32_WRITE(DP_TXCFG, temp); /*-------------------------------------------------------------------*/ /* Setup receive control. */ /*-------------------------------------------------------------------*/ temp = DP_RXCFG_DRTH_SET(8) | DP_RXCFG_MXDMA_32; if (FullDuplex) temp |= DP_RXCFG_ATX; DP_REG32_WRITE(DP_RXCFG, temp); /*-------------------------------------------------------------------*/ /* Receive perfect match and broadcast packets. */ /*-------------------------------------------------------------------*/ DP_REG32_WRITE(DP_RFCR, 0); DP_REG32_WRITE(DP_RFCR, (DP_RFCR_AAB | /* all broadcast pkts */ DP_RFCR_APM | /* perfect match pkts */ DP_RFCR_RFEN)); /*-------------------------------------------------------------------*/ /* Turn on device interrupts. */ /*-------------------------------------------------------------------*/ DP_REG32_WRITE(DP_IMR, (DP_INT_RXOK | DP_INT_MIB | DP_INT_RTABT | DP_INT_RMABT | DP_INT_SSERR | DP_INT_PHY | DP_INT_TXERR | DP_INT_RXERR | DP_INT_TXOK)); DP_REG32_WRITE(DP_IER, DP_IER_IE); /*-------------------------------------------------------------------*/ /* Activate the receiver. */ /*-------------------------------------------------------------------*/ DP_REG32_WRITE(DP_CR, DP_CR_TXE | DP_CR_RXE); /*-------------------------------------------------------------------*/ /* We appear to be semi-functional. */ /*-------------------------------------------------------------------*/ return 0;}/***********************************************************************//* transmit: Add a buffer to transmitter's output queue *//* *//* Inputs: buf = pointer to outbound buffer *//* hwa = pointer to destination hardware address *//* *//***********************************************************************/static void transmit(NetBuf *buf, void *hwa){ int i; FRAME *frame; char *eth_hwa = hwa; /*-------------------------------------------------------------------*/ /* Convert to Ethernet frame pointer and add Ethernet header length. */ /*-------------------------------------------------------------------*/ buf->ip_pkt -= ETH_HDR_LEN; buf->length += ETH_HDR_LEN; /*-------------------------------------------------------------------*/ /* Check for over-long frames. */ /*-------------------------------------------------------------------*/ assert(buf->length <= 1514); /*-------------------------------------------------------------------*/ /* Convert "length" to just length of first data region. */ /*-------------------------------------------------------------------*/ buf->length -= (buf->app_len + buf->app_len2); /*-------------------------------------------------------------------*/ /* Build Ethernet header immediately in front of IP packet. */ /*-------------------------------------------------------------------*/ frame = (FRAME *)buf->ip_pkt; for (i = 0; i < ETH_ALEN; ++i) frame->daddr.byte[i] = eth_hwa[i]; frame->saddr.word1 = OurAddress.word1; frame->saddr.word2 = OurAddress.word2; frame->saddr.word3 = OurAddress.word3; frame->type = buf->type; /*-------------------------------------------------------------------*/ /* Add buffer to end of outbound list. */ /*-------------------------------------------------------------------*/ buf->next = NULL; if (TxMsgQHead == NULL) TxMsgQHead = buf; else TxMsgQTail->next = buf; TxMsgQTail = buf; /*-------------------------------------------------------------------*/ /* Add to transmit decriptor ring, if there is room. */ /*-------------------------------------------------------------------*/ if ((NUM_TX_BDS - NumBusyTxBds) > TxMsgQHead->order) fill_tx_ring();}/***********************************************************************//* broadcast: Add a buffer to output queue using broadcast address *//* *//* Input: buf = pointer to outbound buffer *//* *//***********************************************************************/static void broadcast(NetBuf *buf){ transmit(buf, "\xFF\xFF\xFF\xFF\xFF\xFF");}/***********************************************************************//* free_tx_bufs: Reclaim buffer's that have already been transmitted *//* *//***********************************************************************/static void free_tx_bufs(void){ NetBuf *buf; ui32 status; static int num_bds_nframe; /*-------------------------------------------------------------------*/ /* Free up some buffer descriptors if possible. */ /*-------------------------------------------------------------------*/ for (;;) { /*-----------------------------------------------------------------*/ /* Break if all previously assigned buffers have been recovered. */ /*-----------------------------------------------------------------*/ if (NumBusyTxBds == 0) break; /*-----------------------------------------------------------------*/ /* Invalidate any stale descriptor data in cache. */ /*-----------------------------------------------------------------*/ _cache_invalidate(TxFreeBD, sizeof(BufDescType)); /*-----------------------------------------------------------------*/ /* Break upon reaching a buffer yet to be transmitted. */ /*-----------------------------------------------------------------*/ status = ptohl(TxFreeBD->cmdsts); if (status & DP_DESC_CMDSTS_OWN) break; /*-----------------------------------------------------------------*/ /* Count number of buffer descriptors used by frame. */ /*-----------------------------------------------------------------*/ ++num_bds_nframe; /*-----------------------------------------------------------------*/ /* Advance TxFreeBD to next buffer descriptor in transmit ring. */ /*-----------------------------------------------------------------*/ if (TxFreeBD == &BufDesc[END_TX_BD]) TxFreeBD = &BufDesc[BEG_TX_BD]; else ++TxFreeBD; /*-----------------------------------------------------------------*/ /* Check if this is the last descriptor in the frame. */ /*-----------------------------------------------------------------*/ if ((status & DP_DESC_CMDSTS_MORE) == 0) { /*---------------------------------------------------------------*/ /* Adjust the number of busy buffer descriptors and reset count. */ /*---------------------------------------------------------------*/ NumBusyTxBds -= num_bds_nframe; num_bds_nframe = 0; /*---------------------------------------------------------------*/ /* Record packet transmission and check for errors. */ /*---------------------------------------------------------------*/ ++dp83815Ni.opkts; if (status & DP_DESC_CMDSTS_TX_ERRORS) ++dp83815Ni.oerrs; /*---------------------------------------------------------------*/ /* Return buffer to TargetTCP's buffer manager. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -