#ifndef _TG3_H
#define _TG3_H

/** @file
 *
 * Broadcom NetXtreme I (BCM57xx / tg3) driver
 *
 */

FILE_LICENCE ( GPL2_OR_LATER );

#include <stdint.h>
#include <ipxe/if_ether.h>

/* PCI vendor / device IDs ------------------------------------------------- */

#define TG3_VENDOR_ID   0x14e4

/* BCM57xx device IDs present in Intel Macs and common hardware */
#define TG3_DEV_5751    0x1677
#define TG3_DEV_5751M   0x167d
#define TG3_DEV_5754    0x167a
#define TG3_DEV_5754M   0x1672
#define TG3_DEV_5755    0x167b
#define TG3_DEV_5755M   0x169c
#define TG3_DEV_5756M   0x1674
#define TG3_DEV_5761    0x1680
#define TG3_DEV_5761E   0x1681
#define TG3_DEV_5761S   0x1688
#define TG3_DEV_5761SE  0x1689
#define TG3_DEV_5764    0x1684  /* MacBook, MacBook Pro */
#define TG3_DEV_5784    0x1698
#define TG3_DEV_5787    0x169b
#define TG3_DEV_5787M   0x1693  /* MacBook */
#define TG3_DEV_5906    0x1712
#define TG3_DEV_5906M   0x1713
#define TG3_DEV_57780   0x16b4  /* MacBook Pro, iMac */
#define TG3_DEV_57781   0x16b7  /* Mac mini */
#define TG3_DEV_57785   0x16b5  /* MacBook Pro */
#define TG3_DEV_57788   0x16b6  /* iMac */
#define TG3_DEV_57762   0x1682
#define TG3_DEV_57766   0x1686

/* Mailboxes (MMIO 0x0200-0x02ff) ------------------------------------------ */

#define TG3_MBOX_INT_0          0x0200
#define TG3_MBOX_RCV_RET_CON_0 0x0220  /* RX return consumer index */
#define TG3_MBOX_RCV_STD_PROD  0x0268  /* RX std producer index    */
#define TG3_MBOX_SND_PROD_0    0x0280  /* TX host producer index   */

/* MAC registers (0x0400-0x05ff) ------------------------------------------- */

#define TG3_MAC_MODE            0x0400
#define  MAC_MODE_TDE_ENABLE     0x00020000
#define  MAC_MODE_RDE_ENABLE     0x00040000
#define  MAC_MODE_FHDE_ENABLE    0x00080000
#define  MAC_MODE_RXSTAT_ENABLE  0x00000020
#define  MAC_MODE_RXSTAT_CLEAR   0x00000040
#define  MAC_MODE_TXSTAT_ENABLE  0x00000100
#define  MAC_MODE_TXSTAT_CLEAR   0x00000200

#define TG3_MAC_STATUS          0x0404
#define  MAC_STATUS_LNKSTATE_CHANGED 0x00001000
#define  MAC_STATUS_MI_COMPLETION    0x00400000

#define TG3_MAC_ADDR_0_HI       0x0410
#define TG3_MAC_ADDR_0_LO       0x0414

#define TG3_MAC_HASH_0          0x041c  /* 8 consecutive dwords → hash[0..7] */

#define TG3_TX_MODE             0x043c
#define  TX_MODE_ENABLE          0x00000001

#define TG3_TX_STATUS           0x0440

#define TG3_TX_LENGTHS          0x0444
#define  TX_LENGTHS_DFL          0x00002620  /* slot=0x20, IPG=0x26 */

/* MII/PHY (0x044c-0x045b) ------------------------------------------------- */

#define TG3_MI_COM              0x044c
#define  MI_COM_CMD_READ         0x00000000
#define  MI_COM_CMD_WRITE        0x04000000
#define  MI_COM_START            0x20000000
#define  MI_COM_BUSY             0x20000000
#define  MI_COM_PHY_ADDR_SHIFT   23
#define  MI_COM_REG_ADDR_SHIFT   18
#define  MI_COM_DATA_MASK        0x0000ffff

#define TG3_MI_MODE             0x0454
#define  MI_MODE_500KHZ_CONST    0x00000030

/* RX mode (0x0500-0x050f) ------------------------------------------------- */

#define TG3_RX_MODE             0x0500
#define  RX_MODE_ENABLE          0x00000001
#define  RX_MODE_KEEP_VLAN_TAG   0x00000200

#define TG3_RX_STATUS           0x0504

/* Send path subsystems (0x1000-0x1fff) ------------------------------------- */

#define TG3_SNDBDC_MODE         0x1000
#define  SNDBDC_MODE_ENABLE      0x00000001

#define TG3_SNDBDS_MODE         0x1400
#define  SNDBDS_MODE_ENABLE      0x00000001

#define TG3_SNDDATA_MODE        0x1800
#define  SNDDATA_MODE_ENABLE     0x00000001

#define TG3_SNDBDI_MODE         0x1c00
#define  SNDBDI_MODE_ENABLE      0x00000001

/* Receive BD producer (0x2400-0x2fff) ------------------------------------- */

#define TG3_RCVBDI_MODE         0x2400
#define  RCVBDI_MODE_ENABLE      0x00000001

#define TG3_STD_RCV_RING_INFO   0x2450  /* 2 qwords: base addr, len/flags */

#define TG3_RCVDBDI_MODE        0x2c00
#define  RCVDBDI_MODE_ENABLE     0x00000001

/* Receive data completion (0x3400) ---------------------------------------- */

#define TG3_RCVCC_MODE          0x3400
#define  RCVCC_MODE_ENABLE       0x00000001

/* Send BD completion (0x4000) ---------------------------------------------- */

#define TG3_SBDC_MODE           0x4000
#define  SBDC_MODE_ENABLE        0x00000001

/* Receive BD completion (0x4400) ------------------------------------------ */

#define TG3_RBDC_MODE           0x4400
#define  RBDC_MODE_ENABLE        0x00000001

/* Read DMA (0x4800) / Write DMA (0x4c00) ----------------------------------- */

#define TG3_RDMA_MODE           0x4800
#define  RDMA_MODE_ENABLE        0x00000001
#define  RDMA_MODE_FIFO_LONG_BURST 0x00000300

#define TG3_WDMA_MODE           0x4c00
#define  WDMA_MODE_ENABLE        0x00000001

/* Host coalescing (0x5000-0x50ff) ----------------------------------------- */

#define TG3_HOSTCC_MODE         0x5000
#define  HOSTCC_MODE_ENABLE      0x00000001
#define  HOSTCC_MODE_NOW         0x00000002

#define TG3_HOSTCC_RXCOL_TICKS  0x5008
#define TG3_HOSTCC_TXCOL_TICKS  0x500c
#define TG3_HOSTCC_RXMAX_FRAMES 0x5010
#define TG3_HOSTCC_TXMAX_FRAMES 0x5014
#define TG3_HOSTCC_STATBLK_HI   0x5034
#define TG3_HOSTCC_STATBLK_LO   0x5038

/* Memory arbiter (0x5800) ------------------------------------------------- */

#define TG3_MEM_ARB_MODE        0x5800
#define  MEM_ARB_MODE_ENABLE     0x00000001

/* Buffer manager (0x5c00-0x5cff) ------------------------------------------ */

#define TG3_BUFMGR_MODE         0x5c00
#define  BUFMGR_MODE_ENABLE      0x00000001
#define  BUFMGR_MODE_ATTN_ENABLE 0x00000004

#define TG3_BUFMGR_MB_POOL_ADDR 0x5c08
#define TG3_BUFMGR_MB_POOL_SIZE 0x5c0c

/* GRC (0x6800-0x68ff) ----------------------------------------------------- */

#define TG3_GRC_MODE            0x6800
#define TG3_GRC_MISC_CFG        0x6804
#define  GRC_MISC_CFG_CORECLK_RESET 0x00000001  /* chip reset trigger */
#define  GRC_MODE_BSWAP_NONBD   0x00000004
#define  GRC_MODE_WSWAP_NONBD   0x00000010
#define  GRC_MODE_BSWAP_DATA    0x00000020
#define  GRC_MODE_NO_TX_PHDR_CSUM 0x00100000
#define  GRC_MODE_NO_RX_PHDR_CSUM 0x00400000

#define TG3_GRC_LOCAL_CTRL      0x6808

/* NIC SRAM window (0x6900-0x6907) ----------------------------------------- */

#define TG3_NIC_SRAM_WIN_BASE   0x6900
#define TG3_NIC_SRAM_WIN_DATA   0x6904

/* NIC SRAM internal addresses --------------------------------------------- */

#define TG3_NIC_SRAM_SEND_RCB   0x0100  /* TX ring control block   */
#define TG3_NIC_SRAM_RCV_RET_RCB 0x0200 /* RX return ring ctrl blk */

/* PCI config-space mirrors (read via indirect when needed) ---------------- */

#define TG3_PCISTATE            0x0070
#define TG3_MISC_HOST_CTRL      0x0068
#define  MISC_HOST_CTRL_MASK_INT 0x00000001
#define  MISC_HOST_CTRL_BYTE_SWAP 0x00000004
#define  MISC_HOST_CTRL_WORD_SWAP 0x00000002

/* Ring sizes and limits --------------------------------------------------- */

#define TG3_TX_RING_SIZE        64
#define TG3_RX_STD_RING_SIZE    64
#define TG3_RX_RET_RING_SIZE    64
#define TG3_RX_STD_MAX_SIZE     1536

/* MII standard registers -------------------------------------------------- */

#define MII_BMCR        0x00
#define  BMCR_RESET      0x8000
#define  BMCR_ANENABLE   0x1000
#define  BMCR_ANRESTART  0x0200

#define MII_BMSR        0x01
#define  BMSR_LSTATUS    0x0004
#define  BMSR_ANEGCOMPLETE 0x0020

#define MII_PHYSID1     0x02

#define MII_ADVERTISE   0x04
#define  ADVERTISE_ALL   0x01e0  /* 10/100 half+full */
#define  ADVERTISE_PAUSE_CAP 0x0400
#define  ADVERTISE_CSMA  0x0001

#define MII_CTRL1000    0x09
#define  ADVERTISE_1000FULL 0x0200
#define  ADVERTISE_1000HALF 0x0100

/* Buffer manager NIC-SRAM addresses for a 1 MB internal SRAM -------------- */

#define TG3_MBUF_POOL_ADDR      0x00008000
#define TG3_MBUF_POOL_SIZE      0x00018000

/* BCM5906 has only 64 KB SRAM; pool starts after the RCB area ------------- */
#define TG3_MBUF_POOL_ADDR_5906 0x00000300  /* after SEND/RCV RCBs          */
#define TG3_MBUF_POOL_SIZE_5906 0x0000fc00  /* rest of 64 KB SRAM           */

/* NVRAM registers (0x7000-0x7027) ----------------------------------------- */

#define TG3_NVRAM_CMD           0x7000
#define  NVRAM_CMD_RESET         0x00000001
#define  NVRAM_CMD_GO            0x00000020
#define  NVRAM_CMD_DONE          0x00000008
#define  NVRAM_CMD_RD            0x00000000  /* read (no WR bit set)         */
#define  NVRAM_CMD_FIRST         0x00000080
#define  NVRAM_CMD_LAST          0x00000040

#define TG3_NVRAM_ADDR          0x700c
#define TG3_NVRAM_RDDATA        0x7010
#define TG3_NVRAM_ACCESS        0x7024
#define  NVRAM_ACCESS_ENABLE     0x00000001

/* NVRAM offset for MAC address (6 bytes, big-endian) ----------------------- */
#define TG3_NVRAM_MAC_ADDR_OFF  0x7c

/* Firmware / ASF mailboxes in NIC SRAM ------------------------------------- */

#define TG3_NIC_SRAM_FW_DRV_STATE_MBOX  0x0b04
#define  DRV_STATE_START                  0xf0000001
#define  DRV_STATE_UNLOAD                 0xf0000002

/* Descriptor structures --------------------------------------------------- */

/** TX buffer descriptor (send BD) */
struct tg3_tx_bd {
	uint32_t addr_hi;   /* high 32 bits of buffer DMA address */
	uint32_t addr_lo;   /* low  32 bits of buffer DMA address */
	uint32_t len_flags; /* [31:16]=length, [15:0]=flags       */
	uint32_t vlan_tag;  /* unused by driver; must be zero     */
} __attribute__ (( packed ));

/** TX BD flags */
#define TG3_TX_BD_FLAG_END      0x0001  /* last BD in packet       */
#define TG3_TX_BD_FLAG_IP_CSUM  0x0002
#define TG3_TX_BD_FLAG_TCP_CSUM 0x0004
#define TG3_TX_BD_FLAG_VLAN     0x0040
#define TG3_TX_BD_FLAG_NO_CRC   0x0080
#define TG3_TX_BD_LEN_SHIFT     16

/** RX buffer descriptor (standard producer BD) */
struct tg3_rx_bd {
	uint32_t addr_hi;
	uint32_t addr_lo;
	uint32_t idx_len;   /* [31:16]=opaque index, [15:0]=buffer length */
	uint32_t flags;
	uint32_t reserved[3];
	uint32_t opaque;    /* returned in RX return BD */
} __attribute__ (( packed ));

/** RX return descriptor */
struct tg3_rx_ret_bd {
	uint32_t addr_hi;     /* unused in return */
	uint32_t addr_lo;     /* unused in return */
	uint32_t idx_len;     /* [31:16]=std-ring-idx, [15:0]=frame length */
	uint32_t flags;       /* status flags */
	uint32_t ip_csum;
	uint32_t err_vlan;
	uint16_t reserved;
	uint16_t opaque;      /* matches opaque from producer BD */
} __attribute__ (( packed ));

/** RX return BD flags */
#define TG3_RX_RET_FLAG_ERROR   0x00000400

/**
 * Hardware status block (written by NIC via DMA after each coalescing event).
 * The host reads TX consumer and RX return consumer indices from here.
 */
struct tg3_status_block {
	uint32_t status;        /* SD_STATUS_UPDATED etc. */
	uint32_t status_tag;
	uint16_t rx_jumbo_consumer;
	uint16_t rx_mini_consumer;
	struct {
		uint16_t rx_consumer; /* RX return ring consumer */
		uint16_t tx_consumer; /* TX ring consumer        */
	} idx[1];               /* one queue is enough for boot */
} __attribute__ (( packed ));

#define TG3_STATBLK_SZ  sizeof ( struct tg3_status_block )
#define TG3_STATBLK_ALIGN 64

/** Private device state */
struct tg3_nic {
	/** MMIO base (BAR 0) */
	void *regs;
	/** PCI device */
	struct pci_device *pci;
	/** PCI device ID (used for per-chip quirks) */
	uint16_t chip_id;

	/** TX ring (in DMA memory) */
	struct tg3_tx_bd *tx_ring;
	/** TX producer index (next slot to fill) */
	unsigned int tx_prod;
	/** TX consumer index (last freed by NIC) */
	unsigned int tx_cons;
	/** TX I/O buffers in flight */
	struct io_buffer *tx_iobuf[TG3_TX_RING_SIZE];

	/** RX standard producer ring */
	struct tg3_rx_bd *rx_std;
	/** RX return ring */
	struct tg3_rx_ret_bd *rx_ret;
	/** RX standard producer index */
	unsigned int rx_std_prod;
	/** RX return consumer index */
	unsigned int rx_ret_cons;
	/** RX I/O buffers (one per std-ring slot) */
	struct io_buffer *rx_iobuf[TG3_RX_STD_RING_SIZE];

	/** DMA status block (NIC writes consumer indices here) */
	struct tg3_status_block *status_block;

	/** PHY address on MII bus */
	unsigned int phy_addr;
};

#endif /* _TG3_H */
