dpdk + ixgbe adater _ hw 通过pci_map_resource 读写dma寄存器 + 总线地址 + dma读写地址
一般驱动
https://www.cnblogs.com/codestack/p/12906441.html
static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev = alloc_etherdev_mq(sizeof(struct ixgbe_adapter), indices); // 分配net_device和ixgbe_adapter,发送队列数为MAX_TX_QUEUE if (!netdev) { err = -ENOMEM; goto err_alloc_etherdev; } SET_NETDEV_DEV(netdev, &pdev->dev); adapter = netdev_priv(netdev);// 得到ixgbe_adapter的指针 adapter->netdev = netdev; adapter->pdev = pdev; hw = &adapter->hw;// 得到ixgbe_hw的指针 hw->back = adapter; adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); // 将BAR0中的总线地址映射成内存地址,赋给hw->hw_addr,允许网卡驱动通过hw->hw_addr访问网卡的BAR0对应的Memory空间 hw->hw_addr = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); adapter->io_addr = hw->hw_addr;
dpdk
IXGBE_WRITE_REG
#define IXGBE_PCI_REG_WRITE(reg, value) \ rte_write32((rte_cpu_to_le_32(value)), reg)
eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) { struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); eth_dev->dev_ops = &ixgbe_eth_dev_ops; eth_dev->rx_pkt_burst = &ixgbe_recv_pkts; eth_dev->tx_pkt_burst = &ixgbe_xmit_pkts; eth_dev->tx_pkt_prepare = &ixgbe_prep_pkts; hw->device_id = pci_dev->id.device_id; hw->vendor_id = pci_dev->id.vendor_id; hw->hw_addr = (void *)pci_dev->mem_resource[0].addr; } int __attribute__((cold)) ixgbe_dev_rx_init(struct rte_eth_dev *dev) { struct ixgbe_adapter *adapter = dev->data->dev_private; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); ... for (i = 0; i < dev->data->nb_rx_queues; i++) { rxq = dev->data->rx_queues[i]; ... bus_addr = rxq->rx_ring_phys_addr; /* desc数组的总线地址 */ /* 将desc数组的总线地址写入网卡寄存器 * RDBAL(RX Descriptor Base Address Low) * RDBAH(RX Descriptor Base Address High) * RDLEN(RX Descriptor Length) * RDH(RX Descriptor Head) * RDT(RX Descriptor Tail) * #define IXGBE_RDBAL(_i) (((_i) < 64) ? (0x01000 + ((_i) * 0x40)) : \ * (0x0D000 + (((_i) - 64) * 0x40))) * #define IXGBE_RDBAH(_i) (((_i) < 64) ? (0x01004 + ((_i) * 0x40)) : \ * (0x0D004 + (((_i) - 64) * 0x40))) * #define IXGBE_RDLEN(_i) (((_i) < 64) ? (0x01008 + ((_i) * 0x40)) : \ * (0x0D008 + (((_i) - 64) * 0x40))) * #define IXGBE_RDH(_i) (((_i) < 64) ? (0x01010 + ((_i) * 0x40)) : \ * (0x0D010 + (((_i) - 64) * 0x40))) * #define IXGBE_RDT(_i) (((_i) < 64) ? (0x01018 + ((_i) * 0x40)) : \ * (0x0D018 + (((_i) - 64) * 0x40))) */ IXGBE_WRITE_REG(hw, IXGBE_RDBAL(rxq->reg_idx), (uint32_t)(bus_addr & 0x00000000ffffffffULL)); IXGBE_WRITE_REG(hw, IXGBE_RDBAH(rxq->reg_idx), (uint32_t)(bus_addr >> 32)); IXGBE_WRITE_REG(hw, IXGBE_RDLEN(rxq->reg_idx), rxq->nb_rx_desc * sizeof(union ixgbe_adv_rx_desc)); /* desc数组的长度 */ IXGBE_WRITE_REG(hw, IXGBE_RDH(rxq->reg_idx), 0); /* 写RDH为0 */ IXGBE_WRITE_REG(hw, IXGBE_RDT(rxq->reg_idx), 0); /* 写RDT为0 */ ... } ... }
ixgbe_dev_rx_queue_setup
rz = rte_eth_dma_zone_reserve(dev, "rx_ring", queue_idx,
RX_RING_SZ, IXGBE_ALIGN, socket_id)
rxq->rx_ring_phys_addr = rz->iova;
rxq->rx_ring = (union ixgbe_adv_rx_desc *) rz->addr;
static inline rte_iova_t
rte_mbuf_data_iova_default(const struct rte_mbuf *mb)
{
return mb->buf_iova + RTE_PKTMBUF_HEADROOM;
}
__rte_deprecated
static inline phys_addr_t
rte_mbuf_data_dma_addr_default(const struct rte_mbuf *mb)
{
return rte_mbuf_data_iova_default(mb);
}
nmb = rte_mbuf_raw_alloc(rxq->mb_pool);
dma_addr =rte_cpu_to_le_64(rte_mbuf_data_dma_addr_default(nmb)); /* 得到新mbuf的总线地址 */
rxdp->read.hdr_addr = 0; /* 清零新mbuf对应的desc的DD,后续网卡会读desc */
rxdp->read.pkt_addr = dma_addr