📄 mpc85xx.c
字号:
if ((ext->tx_addr_table = malloc (ext->num_tx_descriptors * sizeof(uint32_t))) == NULL) { nic_slogf (_SLOGC_NETWORK, _SLOG_ERROR, "malloc at \"%s\":%d: %s\n", __FILE__, __LINE__, strerror(errno)); return (errno); }#endif return (EOK);}/****************************************************************************//* *//****************************************************************************/static int mpc_init_list (mpc85xx_t *ext){ mpc_bd_t *bd; int i; net_iov_t *iov; npkt_t *npkt; /* initialize the receive ring */ if ((npkt = mpc_alloc_npkt(ext, MPC_MTU_SIZE, ext->num_rx_descriptors)) == NULL) { errno = ENOBUFS; return -1; } for (i = 0, bd = (mpc_bd_t *) ext->rx_bd; i < ext->num_rx_descriptors; i++, bd++) { if (i == ext->num_rx_descriptors - 1) { bd->status = (RXBD_W | RXBD_E | RXBD_I); /* Wrap indicator */ } else { bd->status = (RXBD_E | RXBD_I); } ext->rx_pktq[i] = npkt; npkt = npkt->next; ext->rx_pktq[i]->next = NULL; // ext->rx_pktq[i]->flags = (_NPKT_UP | MPC_KEEP_PACKET); iov = TAILQ_FIRST(&(ext->rx_pktq[i]->buffers))->net_iov; bd->buffer = iov->iov_phys; bd->length = 0; } ext->rx_cidx = 0; #if 0 /* let's also initialize the freeq */ if ((npkt = mpc_alloc_npkt(ext, MPC_MTU_SIZE, ext->num_rx_descriptors)) == NULL) { errno = ENOBUFS; return -1; } _mutex_lock (&ext->rx_free_pkt_q_mutex); ext->rx_free_pkt_q = npkt; ext->num_rx_free = ext->num_rx_descriptors; _mutex_unlock (&ext->rx_free_pkt_q_mutex);#endif /* setup the tx_addr_table */ for (i = 0; i < ext->num_tx_descriptors; i++) { ext->tx_bd[i].status = 0;#if 0 if (i == ext->num_tx_descriptors - 1) { ext->tx_bd [i].status = TXBD_W; /* Wrap */ } if ((ext->tx_addr_table[i] = vtophys ((void *) &ext->tx_bd[i])) == -1) { errno = ENOBUFS; return (-1); }#endif } ext->tx_bd[ext->num_tx_descriptors - 1].status = TXBD_W; ext->tx_pidx = ext->tx_cidx = 0; return (EOK);}/****************************************************************************//* *//****************************************************************************/static void read_phys_addr (mpc85xx_t *ext){ uint32_t *base = ext->reg; uint32_t addr [2]; addr [0] = *(base + MPC_MACSTNADDR1); addr [1] = *(base + MPC_MACSTNADDR2); if (ext->cfg.verbose) { nic_slogf (_SLOGC_NETWORK, _SLOG_INFO, "MAC addr1 %08x - addr2 %08x", addr [0], addr [1]); }}/****************************************************************************//* *//****************************************************************************/static void set_phys_addr (mpc85xx_t *ext){ uint32_t *base = ext->reg; union { uint32_t addr [2]; uint8_t caddr [8]; } tab; int i, j; memset ((char *) tab.caddr, 0, 8); for (i = 0, j = 5; i < 6; i++, j--) { tab.caddr [i] = ext->cfg.current_address [j]; } *(base + MPC_MACSTNADDR1) = tab.addr [0]; *(base + MPC_MACSTNADDR2) = tab.addr [1];}/****************************************************************************//* *//****************************************************************************/void mpc_reset (mpc85xx_t *ext){ uint32_t *base = ext->reg; uint32_t status; int timeout = MPC_TIMEOUT; /* Graceful transmit stop and wait for completion. */ *(base + MPC_DMACTRL) |= DMACTRL_GTS; timeout = MPC_TIMEOUT; do { nanospin_ns (10); if (! --timeout) break; status = *(base + MPC_IEVENT); } while ((status & IEVENT_GTSC) != IEVENT_GTSC); if (! timeout) { nic_slogf (_SLOGC_NETWORK, _SLOG_ERROR, "DMA GTS stop failed"); } /* Disable Rx and Tx */ *(base + MPC_MACCFG1) &= ~(MACCFG1_TXEN | MACCFG1_RXEN); /* Wait for 9.6KBytes worth of data (worst case ~ 8ms) */ delay (9); /* Graceful receive stop and wait for completion. */ *(base + MPC_DMACTRL) |= DMACTRL_GRS; timeout = MPC_TIMEOUT; do { nanospin_ns (10); if (! --timeout) break; status = *(base + MPC_IEVENT); } while ((status & IEVENT_GRSC) != IEVENT_GRSC); if (!timeout) { nic_slogf (_SLOGC_NETWORK, _SLOG_ERROR, "DMA GRS stop failed"); } *(base + MPC_IEVENT) = (IEVENT_GTSC | IEVENT_GRSC); *(base + MPC_MACCFG1) = MACCFG1_SFT_RESET; nanospin_ns (1000); *(base + MPC_MACCFG1) &= ~MACCFG1_SFT_RESET;}/****************************************************************************//* *//****************************************************************************/static int mpc_config (mpc85xx_t *ext){ nic_config_t *cfg = &ext->cfg; nic_ethernet_stats_t *estats = &ext->stats.un.estats; nic_stats_t *gstats = &ext->stats; uint32_t *base = ext->reg; /* nic ethernet default params */ cfg->media = NIC_MEDIA_802_3; cfg->mac_length = ETH_MAC_LEN; if (cfg->mtu == 0 || cfg->mtu > ETH_MAX_PKT_LEN ) { cfg->mtu = ETH_MAX_PKT_LEN; } cfg->mru = cfg->mtu; gstats->media = cfg->media; estats->valid_stats = NIC_ETHER_STAT_INTERNAL_TX_ERRORS | NIC_ETHER_STAT_INTERNAL_RX_ERRORS | NIC_ETHER_STAT_TX_DEFERRED | NIC_ETHER_STAT_XCOLL_ABORTED | NIC_ETHER_STAT_LATE_COLLISIONS | NIC_ETHER_STAT_SINGLE_COLLISIONS | NIC_ETHER_STAT_MULTI_COLLISIONS | NIC_ETHER_STAT_TOTAL_COLLISION_FRAMES | NIC_ETHER_STAT_ALIGN_ERRORS | NIC_ETHER_STAT_FCS_ERRORS | NIC_ETHER_STAT_JABBER_DETECTED | NIC_ETHER_STAT_OVERSIZED_PACKETS | NIC_ETHER_STAT_SHORT_PACKETS | NIC_ETHER_STAT_LENGTH_FIELD_OUTRANGE | NIC_ETHER_STAT_LENGTH_FIELD_MISMATCH | NIC_ETHER_STAT_EXCESSIVE_DEFERRALS; if (ext->num_rx_descriptors <= 0) { ext->num_rx_descriptors = DEFAULT_NUM_RX_DESCRIPTORS; } if (ext->num_tx_descriptors <= 0) { ext->num_tx_descriptors = DEFAULT_NUM_TX_DESCRIPTORS; } if (cfg->media_rate != -1) { ext->data_rate = (cfg->media_rate / 1000); } else { ext->data_rate = 0; } if (mpc_init_memory (ext) != EOK) { return (-1); } if (mpc_init_list (ext) != EOK) { return (-1); } mpc_reset (ext); /* get out physical address */ if (nic_get_syspage_mac (cfg->permanent_address) == -1) { nic_slogf (_SLOGC_NETWORK, _SLOG_ERROR, "devn-mpc85xx: MAC address not found in system page");// read_phys_addr (ext); } /* set up our address */ /* check for command line override */ if (memcmp (cfg->current_address, "\0\0\0\0\0\0", 6) == 0) { nic_slogf (_SLOGC_NETWORK, _SLOG_ERROR, "You must specify a MAC address"); return (-1); } set_phys_addr (ext); read_phys_addr (ext); *(base + MPC_TBASE) = vtophys ((void *) ext->tx_bd); *(base + MPC_RBASE) = vtophys ((void *) ext->rx_bd); *(base + MPC_MACCFG2) = (MACCFG2_IF_MODE_BYT | MACCFG2_PAD_CRC | (cfg->duplex ? MACCFG2_FDX : 0) | MACCFG2_PRE_LEN(7)); *(base + MPC_ECNTRL) = (ECNTRL_CLRCNT | ECNTRL_STEN | ECNTRL_AUTOZ); *(base + MPC_MRBLR) = MPC_MTU_SIZE; *(base + MPC_DMACTRL) |= (DMACTRL_WWR | DMACTRL_TBDSEN | DMACTRL_TDSEN /*| DMACTRL_WOP*/); /* Suprisingly enough, when performing loopback tests, the polled mode is FASTER than the * wait mode for smaller packets */ *(base + MPC_DMACTRL) &= ~(DMACTRL_WOP); *(base + MPC_FIFO_TX_THR) = ext->fifo; *(base + MPC_FIFO_TX_STARVE) = ext->fifo_starve; *(base + MPC_FIFO_TX_STARVE_SHUTOFF) = ext->fifo_starve_shutoff;#if 1 /* ask chip put 64bytes in L2 cache */ *(base + MPC_ATTR) = 0x40c0; *(base + MPC_ATTRELI) = 0x00400000;#else *(base + MPC_ATTR) = 0x000000c0;#endif *(base + MPC_IADDR0) = 0x0; *(base + MPC_IADDR1) = 0x0; *(base + MPC_IADDR2) = 0x0; *(base + MPC_IADDR3) = 0x0; *(base + MPC_IADDR4) = 0x0; *(base + MPC_IADDR5) = 0x0; *(base + MPC_IADDR6) = 0x0; *(base + MPC_IADDR7) = 0x0; *(base + MPC_GADDR0) = 0x0; *(base + MPC_GADDR1) = 0x0; *(base + MPC_GADDR2) = 0x0; *(base + MPC_GADDR3) = 0x0; *(base + MPC_GADDR4) = 0x0; *(base + MPC_GADDR5) = 0x0; *(base + MPC_GADDR6) = 0x0; *(base + MPC_GADDR7) = 0x0; *(base + MPC_CAR1) = 0xffffffff; *(base + MPC_CAR2) = 0xffffffff; *(base + MPC_CAM1) = 0x0; *(base + MPC_CAM2) = 0x0; if (cfg->flags & NIC_FLAG_PROMISCUOUS) { *(base + MPC_RCTRL) = RCTRL_PROM; } *(base + MPC_IMASK) = (IMASK_TXE | IMASK_TXB | IMASK_TXF | IMASK_RXBO | IMASK_RXFO | IMASK_BABR | IMASK_BSY | IMASK_EBERR); *(base + MPC_TSTAT) = TSTAT_THLT; *(base + MPC_RSTAT) = RSTAT_QHLT; *(base + MPC_DMACTRL) &= ~(DMACTRL_GRS | DMACTRL_GTS); *(base + MPC_MACCFG1) = (MACCFG1_RXEN | MACCFG1_TXEN | ext->flowctl_flag | ext->loopback); mpc_init_phy (ext, (cfg->media_rate == - 1) ? 0 : cfg->media_rate); return (EOK);}/****************************************************************************//* *//****************************************************************************/int mpc_register_device (mpc85xx_t *ext, io_net_self_t *ion, void *dll_hdl){ nic_config_t *cfg = &ext->cfg; pthread_attr_t pattr; pthread_mutexattr_t mattr; struct sched_param param; struct sigevent event; uint16_t lan; int ret, err = 0; ext->ion = ion; ext->dll_hdl = dll_hdl; if ((ext->chid = ChannelCreate (_NTO_CHF_DISCONNECT | _NTO_CHF_UNBLOCK)) < 0) { nic_slogf (_SLOGC_NETWORK, _SLOG_ERROR, "ChannelCreate at \"%s\":%d: %s\n", __FILE__, __LINE__, strerror(errno)); goto error; } err++; if ((ext->coid = ConnectAttach (0, 0, ext->chid, _NTO_SIDE_CHANNEL, 0)) < 0) { nic_slogf( _SLOGC_NETWORK, _SLOG_ERROR, "devn-mpc85xx: Unable to ConnectAtttach" ); goto error; } err++;#if 0 if (cache_init(0, &ext->cachectl, NULL) == -1) { nic_slogf (_SLOGC_NETWORK, _SLOG_ERROR, "devn-mpc85xx: cache_init() failed"); goto error; } err++;#endif /* we need a valid connection id before calling mpc_config */ if (mpc_config (ext) != EOK) { nic_slogf ( _SLOGC_NETWORK, _SLOG_ERROR, "devn-mpc85xx: mpc_config error" ); goto error; } pthread_mutexattr_init (&mattr); if (pthread_mutex_init (&ext->tx_mutex, &mattr) != EOK) { nic_slogf (_SLOGC_NETWORK, _SLOG_ERROR, "devn-mpc85xx: Unable to initialize TX mutex"); goto error; } err++; if (pthread_mutex_init (&ext->rx_free_pkt_q_mutex, &mattr) != EOK) { nic_slogf (_SLOGC_NETWORK, _SLOG_ERROR, "devn-mpc85xx: Unable to initialize RX Free Queue mutex"); goto error; } err++; mpc_entry.func_hdl = (void *) ext; mpc_entry.top_type = cfg->uptype; if (cfg->lan != -1) { mpc_entry.flags |= _REG_ENDPOINT_ARG; lan = cfg->lan; } if (ion_register (dll_hdl, &mpc_entry, &ext->reg_hdl, &ext->cell, &lan) < 0) { nic_slogf (_SLOGC_NETWORK, _SLOG_ERROR, "ion_register at \"%s\":%d: %s\n", __FILE__, __LINE__, strerror(errno)); goto error; } cfg->lan = lan; if (ext->ion->devctl (ext->reg_hdl, DCMD_IO_NET_VERSION, &ext->version, sizeof (ext->version), NULL)) { ext->version = 0; } if (ext->ion->devctl (ext->reg_hdl, DCMD_IO_NET_STATIC, &ext->io_static, sizeof(ext->io_static), NULL)) { ext->io_static = 0; } if (!ext->max_pkts) { ext->max_pkts = MPC_DEFAULT_MAX_PACKETS; } pthread_attr_init (&pattr); pthread_attr_setschedpolicy (&pattr, SCHED_RR);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -