static int fm_eth_tx_port_parameter_init(struct fm_eth *fm_eth) { struct fm_port_global_pram *pram; u32 pram_page_offset; void *tx_bd_ring_base; struct fm_port_bd *txbd; struct fm_port_qd *txqd; struct fm_bmi_tx_port *bmi_tx_port = fm_eth->tx_port; int i; /* alloc global parameter ram at MURAM */ pram = (struct fm_port_global_pram *)fm_muram_alloc(fm_eth->fm_index, FM_PRAM_SIZE, FM_PRAM_ALIGN); fm_eth->tx_pram = pram; /* parameter page offset to MURAM */ pram_page_offset = (u32)pram - fm_muram_base(fm_eth->fm_index); /* enable global mode- snooping data buffers and BDs */ pram->mode = PRAM_MODE_GLOBAL; /* init the Tx queue descriptor pionter */ pram->txqd_ptr = pram_page_offset + 0x40; /* alloc Tx buffer descriptors from main memory */ tx_bd_ring_base = malloc(sizeof(struct fm_port_bd) * TX_BD_RING_SIZE); if (!tx_bd_ring_base) return 0; memset(tx_bd_ring_base, 0, sizeof(struct fm_port_bd) * TX_BD_RING_SIZE); /* save it to fm_eth */ fm_eth->tx_bd_ring = tx_bd_ring_base; fm_eth->cur_txbd = tx_bd_ring_base; /* init Tx BDs ring */ txbd = (struct fm_port_bd *)tx_bd_ring_base; for (i = 0; i < TX_BD_RING_SIZE; i++) { txbd->status = TxBD_LAST; txbd->len = 0; txbd->buf_ptr_hi = 0; txbd->buf_ptr_lo = 0; } /* set the Tx queue decriptor */ txqd = &pram->txqd; muram_writew(&txqd->bd_ring_base_hi, 0); txqd->bd_ring_base_lo = (u32)tx_bd_ring_base; muram_writew(&txqd->bd_ring_size, sizeof(struct fm_port_bd) * TX_BD_RING_SIZE); muram_writew(&txqd->offset_in, 0); muram_writew(&txqd->offset_out, 0); /* set IM parameter ram pointer to Tx Confirmation Frame Queue ID */ out_be32(&bmi_tx_port->fmbm_tcfqid, pram_page_offset); return 1; }
static int fm_eth_send(struct eth_device *dev, void *buf, int len) { struct fm_eth *fm_eth; struct fm_port_global_pram *pram; struct fm_port_bd *txbd, *txbd_base; u16 offset_in; int i; fm_eth = (struct fm_eth *)dev->priv; pram = fm_eth->tx_pram; txbd = fm_eth->cur_txbd; /* find one empty TxBD */ for (i = 0; muram_readw(&txbd->status) & TxBD_READY; i++) { udelay(100); if (i > 0x1000) { printf("%s: Tx buffer not ready, txbd->status = 0x%x\n", dev->name, muram_readw(&txbd->status)); return 0; } } /* setup TxBD */ muram_writew(&txbd->buf_ptr_hi, (u16)upper_32_bits(virt_to_phys(buf))); out_be32(&txbd->buf_ptr_lo, lower_32_bits(virt_to_phys(buf))); muram_writew(&txbd->len, len); sync(); muram_writew(&txbd->status, TxBD_READY | TxBD_LAST); sync(); /* update TxQD, let RISC to send the packet */ offset_in = muram_readw(&pram->txqd.offset_in); offset_in += sizeof(struct fm_port_bd); if (offset_in >= muram_readw(&pram->txqd.bd_ring_size)) offset_in = 0; muram_writew(&pram->txqd.offset_in, offset_in); sync(); /* wait for buffer to be transmitted */ for (i = 0; muram_readw(&txbd->status) & TxBD_READY; i++) { udelay(100); if (i > 0x10000) { printf("%s: Tx error, txbd->status = 0x%x\n", dev->name, muram_readw(&txbd->status)); return 0; } } /* advance the TxBD */ txbd++; txbd_base = (struct fm_port_bd *)fm_eth->tx_bd_ring; if (txbd >= (txbd_base + TX_BD_RING_SIZE)) txbd = txbd_base; /* update current txbd */ fm_eth->cur_txbd = (void *)txbd; return 1; }
static int fm_eth_recv(struct eth_device *dev) { struct fm_eth *fm_eth; struct fm_port_global_pram *pram; struct fm_port_bd *rxbd, *rxbd_base; u16 status, len; u32 buf_lo, buf_hi; u8 *data; u16 offset_out; int ret = 1; fm_eth = (struct fm_eth *)dev->priv; pram = fm_eth->rx_pram; rxbd = fm_eth->cur_rxbd; status = muram_readw(&rxbd->status); while (!(status & RxBD_EMPTY)) { if (!(status & RxBD_ERROR)) { buf_hi = muram_readw(&rxbd->buf_ptr_hi); buf_lo = in_be32(&rxbd->buf_ptr_lo); data = (u8 *)((ulong)(buf_hi << 16) << 16 | buf_lo); len = muram_readw(&rxbd->len); net_process_received_packet(data, len); } else { printf("%s: Rx error\n", dev->name); ret = 0; } /* clear the RxBDs */ muram_writew(&rxbd->status, RxBD_EMPTY); muram_writew(&rxbd->len, 0); sync(); /* advance RxBD */ rxbd++; rxbd_base = (struct fm_port_bd *)fm_eth->rx_bd_ring; if (rxbd >= (rxbd_base + RX_BD_RING_SIZE)) rxbd = rxbd_base; /* read next status */ status = muram_readw(&rxbd->status); /* update RxQD */ offset_out = muram_readw(&pram->rxqd.offset_out); offset_out += sizeof(struct fm_port_bd); if (offset_out >= muram_readw(&pram->rxqd.bd_ring_size)) offset_out = 0; muram_writew(&pram->rxqd.offset_out, offset_out); sync(); } fm_eth->cur_rxbd = (void *)rxbd; return ret; }
static int fm_eth_recv(struct eth_device *dev) { struct fm_eth *fm_eth; struct fm_port_global_pram *pram; struct fm_port_bd *rxbd, *rxbd_base; u16 status, len; u8 *data; u16 offset_out; fm_eth = (struct fm_eth *)dev->priv; pram = fm_eth->rx_pram; rxbd = fm_eth->cur_rxbd; status = rxbd->status; while (!(status & RxBD_EMPTY)) { if (!(status & RxBD_ERROR)) { data = (u8 *)rxbd->buf_ptr_lo; len = rxbd->len; NetReceive(data, len); } else { printf("%s: Rx error\n", dev->name); return 0; } /* clear the RxBDs */ rxbd->status = RxBD_EMPTY; rxbd->len = 0; sync(); /* advance RxBD */ rxbd++; rxbd_base = (struct fm_port_bd *)fm_eth->rx_bd_ring; if (rxbd >= (rxbd_base + RX_BD_RING_SIZE)) rxbd = rxbd_base; /* read next status */ status = rxbd->status; /* update RxQD */ offset_out = muram_readw(&pram->rxqd.offset_out); offset_out += sizeof(struct fm_port_bd); if (offset_out >= muram_readw(&pram->rxqd.bd_ring_size)) offset_out = 0; muram_writew(&pram->rxqd.offset_out, offset_out); sync(); } fm_eth->cur_rxbd = (void *)rxbd; return 1; }
static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth) { struct fm_port_global_pram *pram; u32 pram_page_offset; void *rx_bd_ring_base; void *rx_buf_pool; struct fm_port_bd *rxbd; struct fm_port_qd *rxqd; struct fm_bmi_rx_port *bmi_rx_port = fm_eth->rx_port; int i; /* alloc global parameter ram at MURAM */ pram = (struct fm_port_global_pram *)fm_muram_alloc(fm_eth->fm_index, FM_PRAM_SIZE, FM_PRAM_ALIGN); fm_eth->rx_pram = pram; /* parameter page offset to MURAM */ pram_page_offset = (u32)pram - fm_muram_base(fm_eth->fm_index); /* enable global mode- snooping data buffers and BDs */ pram->mode = PRAM_MODE_GLOBAL; /* init the Rx queue descriptor pionter */ pram->rxqd_ptr = pram_page_offset + 0x20; /* set the max receive buffer length, power of 2 */ muram_writew(&pram->mrblr, MAX_RXBUF_LOG2); /* alloc Rx buffer descriptors from main memory */ rx_bd_ring_base = malloc(sizeof(struct fm_port_bd) * RX_BD_RING_SIZE); if (!rx_bd_ring_base) return 0; memset(rx_bd_ring_base, 0, sizeof(struct fm_port_bd) * RX_BD_RING_SIZE); /* alloc Rx buffer from main memory */ rx_buf_pool = malloc(MAX_RXBUF_LEN * RX_BD_RING_SIZE); if (!rx_buf_pool) return 0; memset(rx_buf_pool, 0, MAX_RXBUF_LEN * RX_BD_RING_SIZE); /* save them to fm_eth */ fm_eth->rx_bd_ring = rx_bd_ring_base; fm_eth->cur_rxbd = rx_bd_ring_base; fm_eth->rx_buf = rx_buf_pool; /* init Rx BDs ring */ rxbd = (struct fm_port_bd *)rx_bd_ring_base; for (i = 0; i < RX_BD_RING_SIZE; i++) { rxbd->status = RxBD_EMPTY; rxbd->len = 0; rxbd->buf_ptr_hi = 0; rxbd->buf_ptr_lo = (u32)rx_buf_pool + i * MAX_RXBUF_LEN; rxbd++; } /* set the Rx queue descriptor */ rxqd = &pram->rxqd; muram_writew(&rxqd->gen, 0); muram_writew(&rxqd->bd_ring_base_hi, 0); rxqd->bd_ring_base_lo = (u32)rx_bd_ring_base; muram_writew(&rxqd->bd_ring_size, sizeof(struct fm_port_bd) * RX_BD_RING_SIZE); muram_writew(&rxqd->offset_in, 0); muram_writew(&rxqd->offset_out, 0); /* set IM parameter ram pointer to Rx Frame Queue ID */ out_be32(&bmi_rx_port->fmbm_rfqid, pram_page_offset); return 1; }
static int fm_eth_tx_port_parameter_init(struct fm_eth *fm_eth) { struct fm_port_global_pram *pram; u32 pram_page_offset; void *tx_bd_ring_base; u32 bd_ring_base_lo, bd_ring_base_hi; struct fm_port_bd *txbd; struct fm_port_qd *txqd; struct fm_bmi_tx_port *bmi_tx_port = fm_eth->tx_port; int i; /* alloc global parameter ram at MURAM */ pram = (struct fm_port_global_pram *)fm_muram_alloc(fm_eth->fm_index, FM_PRAM_SIZE, FM_PRAM_ALIGN); if (!pram) { printf("%s: No muram for Tx global parameter\n", __func__); return -ENOMEM; } fm_eth->tx_pram = pram; /* parameter page offset to MURAM */ pram_page_offset = (void *)pram - fm_muram_base(fm_eth->fm_index); /* enable global mode- snooping data buffers and BDs */ out_be32(&pram->mode, PRAM_MODE_GLOBAL); /* init the Tx queue descriptor pionter */ out_be32(&pram->txqd_ptr, pram_page_offset + 0x40); /* alloc Tx buffer descriptors from main memory */ tx_bd_ring_base = malloc(sizeof(struct fm_port_bd) * TX_BD_RING_SIZE); if (!tx_bd_ring_base) return -ENOMEM; memset(tx_bd_ring_base, 0, sizeof(struct fm_port_bd) * TX_BD_RING_SIZE); /* save it to fm_eth */ fm_eth->tx_bd_ring = tx_bd_ring_base; fm_eth->cur_txbd = tx_bd_ring_base; /* init Tx BDs ring */ txbd = (struct fm_port_bd *)tx_bd_ring_base; for (i = 0; i < TX_BD_RING_SIZE; i++) { muram_writew(&txbd->status, TxBD_LAST); muram_writew(&txbd->len, 0); muram_writew(&txbd->buf_ptr_hi, 0); out_be32(&txbd->buf_ptr_lo, 0); txbd++; } /* set the Tx queue decriptor */ txqd = &pram->txqd; bd_ring_base_hi = upper_32_bits(virt_to_phys(tx_bd_ring_base)); bd_ring_base_lo = lower_32_bits(virt_to_phys(tx_bd_ring_base)); muram_writew(&txqd->bd_ring_base_hi, (u16)bd_ring_base_hi); out_be32(&txqd->bd_ring_base_lo, bd_ring_base_lo); muram_writew(&txqd->bd_ring_size, sizeof(struct fm_port_bd) * TX_BD_RING_SIZE); muram_writew(&txqd->offset_in, 0); muram_writew(&txqd->offset_out, 0); /* set IM parameter ram pointer to Tx Confirmation Frame Queue ID */ out_be32(&bmi_tx_port->fmbm_tcfqid, pram_page_offset); return 0; }
static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth) { struct fm_port_global_pram *pram; u32 pram_page_offset; void *rx_bd_ring_base; void *rx_buf_pool; u32 bd_ring_base_lo, bd_ring_base_hi; u32 buf_lo, buf_hi; struct fm_port_bd *rxbd; struct fm_port_qd *rxqd; struct fm_bmi_rx_port *bmi_rx_port = fm_eth->rx_port; int i; /* alloc global parameter ram at MURAM */ pram = (struct fm_port_global_pram *)fm_muram_alloc(fm_eth->fm_index, FM_PRAM_SIZE, FM_PRAM_ALIGN); if (!pram) { printf("%s: No muram for Rx global parameter\n", __func__); return -ENOMEM; } fm_eth->rx_pram = pram; /* parameter page offset to MURAM */ pram_page_offset = (void *)pram - fm_muram_base(fm_eth->fm_index); /* enable global mode- snooping data buffers and BDs */ out_be32(&pram->mode, PRAM_MODE_GLOBAL); /* init the Rx queue descriptor pionter */ out_be32(&pram->rxqd_ptr, pram_page_offset + 0x20); /* set the max receive buffer length, power of 2 */ muram_writew(&pram->mrblr, MAX_RXBUF_LOG2); /* alloc Rx buffer descriptors from main memory */ rx_bd_ring_base = malloc(sizeof(struct fm_port_bd) * RX_BD_RING_SIZE); if (!rx_bd_ring_base) return -ENOMEM; memset(rx_bd_ring_base, 0, sizeof(struct fm_port_bd) * RX_BD_RING_SIZE); /* alloc Rx buffer from main memory */ rx_buf_pool = malloc(MAX_RXBUF_LEN * RX_BD_RING_SIZE); if (!rx_buf_pool) return -ENOMEM; memset(rx_buf_pool, 0, MAX_RXBUF_LEN * RX_BD_RING_SIZE); debug("%s: rx_buf_pool = %p\n", __func__, rx_buf_pool); /* save them to fm_eth */ fm_eth->rx_bd_ring = rx_bd_ring_base; fm_eth->cur_rxbd = rx_bd_ring_base; fm_eth->rx_buf = rx_buf_pool; /* init Rx BDs ring */ rxbd = (struct fm_port_bd *)rx_bd_ring_base; for (i = 0; i < RX_BD_RING_SIZE; i++) { muram_writew(&rxbd->status, RxBD_EMPTY); muram_writew(&rxbd->len, 0); buf_hi = upper_32_bits(virt_to_phys(rx_buf_pool + i * MAX_RXBUF_LEN)); buf_lo = lower_32_bits(virt_to_phys(rx_buf_pool + i * MAX_RXBUF_LEN)); muram_writew(&rxbd->buf_ptr_hi, (u16)buf_hi); out_be32(&rxbd->buf_ptr_lo, buf_lo); rxbd++; } /* set the Rx queue descriptor */ rxqd = &pram->rxqd; muram_writew(&rxqd->gen, 0); bd_ring_base_hi = upper_32_bits(virt_to_phys(rx_bd_ring_base)); bd_ring_base_lo = lower_32_bits(virt_to_phys(rx_bd_ring_base)); muram_writew(&rxqd->bd_ring_base_hi, (u16)bd_ring_base_hi); out_be32(&rxqd->bd_ring_base_lo, bd_ring_base_lo); muram_writew(&rxqd->bd_ring_size, sizeof(struct fm_port_bd) * RX_BD_RING_SIZE); muram_writew(&rxqd->offset_in, 0); muram_writew(&rxqd->offset_out, 0); /* set IM parameter ram pointer to Rx Frame Queue ID */ out_be32(&bmi_rx_port->fmbm_rfqid, pram_page_offset); return 0; }