summaryrefslogtreecommitdiffstats
path: root/sys/mips
diff options
context:
space:
mode:
authorjchandra <jchandra@FreeBSD.org>2010-08-28 19:02:51 +0000
committerjchandra <jchandra@FreeBSD.org>2010-08-28 19:02:51 +0000
commit51cf338feecb0df7abaab1235174501fe11e99c0 (patch)
treed32fd3a516d55437304edde06f7d0ea6de27254a /sys/mips
parent8d90bd696f6ffe32185cc58c210e1cb2b6b40466 (diff)
downloadFreeBSD-src-51cf338feecb0df7abaab1235174501fe11e99c0.zip
FreeBSD-src-51cf338feecb0df7abaab1235174501fe11e99c0.tar.gz
New driver nlge for XLR/XLS Network Accelerator. This will support the XGMAC
and XAUI 10G interfaces in addition RGMII/SGMII 1G interfaces. This driver is work in progress. board.c and board.h expanded to include more info. Only one of rge and nlge can be enabled at a time, rge will be deprecated when nlge stabilizes. Submitted by: Sriram Gorti <srgorti at netlogicmicro com>
Diffstat (limited to 'sys/mips')
-rw-r--r--sys/mips/rmi/board.c456
-rw-r--r--sys/mips/rmi/board.h68
-rw-r--r--sys/mips/rmi/dev/nlge/if_nlge.c2444
-rw-r--r--sys/mips/rmi/dev/nlge/if_nlge.h1180
-rw-r--r--sys/mips/rmi/files.xlr1
-rw-r--r--sys/mips/rmi/iodi.c46
6 files changed, 4069 insertions, 126 deletions
diff --git a/sys/mips/rmi/board.c b/sys/mips/rmi/board.c
index ab55e05..ac36755 100644
--- a/sys/mips/rmi/board.c
+++ b/sys/mips/rmi/board.c
@@ -78,13 +78,12 @@ static int xls_rxstn_to_txstn_map[128] = {
[120 ... 127] = TX_STN_SAE
};
-struct stn_cc *xlr_core_cc_configs[] = {&cc_table_cpu_0, &cc_table_cpu_1,
- &cc_table_cpu_2, &cc_table_cpu_3,
- &cc_table_cpu_4, &cc_table_cpu_5,
-&cc_table_cpu_6, &cc_table_cpu_7};
+struct stn_cc *xlr_core_cc_configs[] = { &cc_table_cpu_0, &cc_table_cpu_1,
+ &cc_table_cpu_2, &cc_table_cpu_3, &cc_table_cpu_4, &cc_table_cpu_5,
+ &cc_table_cpu_6, &cc_table_cpu_7};
-struct stn_cc *xls_core_cc_configs[] = {&xls_cc_table_cpu_0, &xls_cc_table_cpu_1,
-&xls_cc_table_cpu_2, &xls_cc_table_cpu_3};
+struct stn_cc *xls_core_cc_configs[] = { &xls_cc_table_cpu_0, &xls_cc_table_cpu_1,
+ &xls_cc_table_cpu_2, &xls_cc_table_cpu_3 };
struct xlr_board_info xlr_board_info;
@@ -98,6 +97,174 @@ xlr_pcmcia_present(void)
return ((resetconf & 0x4000) != 0);
}
+static void
+xlr_board_specific_overrides(struct xlr_board_info* board)
+{
+ struct xlr_gmac_block_t *blk1, *blk2;
+
+ blk1 = &board->gmac_block[1];
+ blk2 = &board->gmac_block[2];
+
+ switch (xlr_boot1_info.board_major_version) {
+ case RMI_XLR_BOARD_ARIZONA_I:
+ /* ATX-I has SPI-4, not XGMAC */
+ blk1->type = XLR_SPI4;
+ blk1->enabled = 0; /* nlge does not
+ support SPI-4 */
+ blk2->type = XLR_SPI4;
+ blk2->enabled = 0;
+ break;
+
+ case RMI_XLR_BOARD_ARIZONA_II:
+ /* XGMII_A --> VSC7281, XGMII_B --> VSC7281 */
+ blk1->enabled = 1;
+ blk1->num_ports = 1;
+ blk1->gmac_port[0].valid = 1;
+
+ blk2->enabled = 1;
+ blk2->num_ports = 1;
+ blk2->gmac_port[0].valid = 1;
+ default:
+ break;
+ }
+}
+
+static int
+quad0_xaui(void)
+{
+ xlr_reg_t *gpio_mmio =
+ (unsigned int *)(DEFAULT_XLR_IO_BASE + XLR_IO_GPIO_OFFSET);
+ uint32_t bit24;
+
+ bit24 = (xlr_read_reg(gpio_mmio, 0x15) >> 24) & 0x1;
+ return (bit24);
+}
+
+static int
+quad1_xaui(void)
+{
+ xlr_reg_t *gpio_mmio =
+ (unsigned int *)(DEFAULT_XLR_IO_BASE + XLR_IO_GPIO_OFFSET);
+ uint32_t bit25;
+
+ bit25 = (xlr_read_reg(gpio_mmio, 0x15) >> 25) & 0x1;
+ return (bit25);
+}
+
+static void
+xls_board_specific_overrides(struct xlr_board_info* board)
+{
+ struct xlr_gmac_block_t *blk0, *blk1;
+ int i;
+
+ blk0 = &board->gmac_block[0];
+ blk1 = &board->gmac_block[1];
+
+ switch (xlr_boot1_info.board_major_version) {
+ case RMI_XLR_BOARD_ARIZONA_VI:
+ blk0->mode = XLR_PORT0_RGMII;
+ blk0->gmac_port[0].type = XLR_RGMII;
+ blk0->gmac_port[0].phy_addr = 0;
+ blk0->gmac_port[0].mii_addr = XLR_IO_GMAC_4_OFFSET;
+ /* Because of the Octal PHY, SGMII Quad1 is MII is also bound
+ * to the PHY attached to SGMII0_MDC/MDIO/MDINT. */
+ for (i = 0; i < 4; i++) {
+ blk1->gmac_port[i].mii_addr = XLR_IO_GMAC_0_OFFSET;
+ blk1->gmac_port[i].serdes_addr = XLR_IO_GMAC_0_OFFSET;
+ }
+ blk1->gmac_port[1].mii_addr = XLR_IO_GMAC_0_OFFSET;
+ blk1->gmac_port[2].mii_addr = XLR_IO_GMAC_0_OFFSET;
+ blk1->gmac_port[3].mii_addr = XLR_IO_GMAC_0_OFFSET;
+
+ blk1->gmac_port[1].serdes_addr = XLR_IO_GMAC_0_OFFSET;
+ blk1->gmac_port[2].serdes_addr = XLR_IO_GMAC_0_OFFSET;
+ blk1->gmac_port[3].serdes_addr = XLR_IO_GMAC_0_OFFSET;
+
+ /* RGMII MDIO interrupt is thru NA1 and SGMII MDIO
+ * interrupts for ports in blk1 are from NA0 */
+ blk0->gmac_port[0].mdint_id = 1;
+
+ blk1->gmac_port[0].mdint_id = 0;
+ blk1->gmac_port[1].mdint_id = 0;
+ blk1->gmac_port[2].mdint_id = 0;
+ blk1->gmac_port[3].mdint_id = 0;
+ break;
+
+ case RMI_XLR_BOARD_ARIZONA_VIII:
+ /* There is just one Octal PHY on the board and it is
+ * connected to the MII interface for NA Quad 0. */
+ blk1->gmac_port[0].mii_addr = XLR_IO_GMAC_0_OFFSET;
+ blk1->gmac_port[1].mii_addr = XLR_IO_GMAC_0_OFFSET;
+ blk1->gmac_port[2].mii_addr = XLR_IO_GMAC_0_OFFSET;
+ blk1->gmac_port[3].mii_addr = XLR_IO_GMAC_0_OFFSET;
+
+ /* Board 8.3 (Lite) has XLS108 */
+ if (xlr_boot1_info.board_minor_version == 3) {
+ /* NA0 has 3 ports */
+ blk0->gmac_port[3].valid = 1;
+ blk0->num_ports--;
+ /* NA1 is completely disabled */
+ blk1->enabled = 0;
+ }
+
+ break;
+
+ case RMI_XLR_BOARD_ARIZONA_XI:
+ case RMI_XLR_BOARD_ARIZONA_XII:
+ if (quad0_xaui()) { /* GMAC ports 0-3 are set to XAUI */
+ /* only GMAC0 is active i.e, the 0-th port on this quad.
+ * Disable all the other 7 possible ports. */
+ for (i = 1; i < MAX_NA_PORTS; i++) {
+ memset(&blk0->gmac_port[i], 0,
+ sizeof(blk0->gmac_port[i]));
+ }
+ /* Setup for XAUI on N/w Acc0: gmac0 */
+ blk0->type = XLR_XGMAC;
+ blk0->mode = XLR_XAUI;
+ blk0->num_ports = 1;
+ blk0->gmac_port[0].type = XLR_XAUI;
+ blk1->gmac_port[0].phy_addr = 16;
+ blk0->gmac_port[0].tx_bucket_id = blk0->station_txbase;
+ /* Other addresses etc need not be modified as XAUI_0
+ * shares its addresses with SGMII GMAC_0, which was
+ * set in the caller. */
+ }
+ else {
+ blk0->num_ports = 1; /* only 1 RGMII port */
+ blk0->mode = XLR_PORT0_RGMII;
+ blk0->gmac_port[0].type = XLR_RGMII;
+ blk0->gmac_port[0].phy_addr = 0;
+ blk0->gmac_port[0].mii_addr = XLR_IO_GMAC_0_OFFSET;
+ }
+
+ if (quad1_xaui()) { /* GMAC ports 4-7 are used for XAUI */
+ /* only GMAC4 is active i.e, the 0-th port on this quad.
+ * Disable all the other 7 possible ports. */
+ for (i = 1; i < MAX_NA_PORTS; i++) {
+ memset(&blk1->gmac_port[i], 0,
+ sizeof(blk1->gmac_port[i]));
+ }
+ /* Setup for XAUI on N/w Acc1: gmac4 */
+ blk1->type = XLR_XGMAC;
+ blk1->mode = XLR_XAUI;
+ blk1->num_ports = 1;
+ /* XAUI and SGMII ports share FMN buckets on N/w Acc 1;
+ so, station_txbase, station_rfr need not be
+ patched up. */
+ blk1->gmac_port[0].type = XLR_XAUI;
+ blk1->gmac_port[0].phy_addr = 16;
+ blk1->gmac_port[0].tx_bucket_id = blk1->station_txbase;
+ /* Other addresses etc need not be modified as XAUI_1
+ * shares its addresses with SGMII GMAC_4, which was
+ * set in the caller. */
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
/*
* All our knowledge of chip and board that cannot be detected by probing
* at run-time goes here
@@ -105,6 +272,57 @@ xlr_pcmcia_present(void)
int
xlr_board_info_setup()
{
+ struct xlr_gmac_block_t *blk0, *blk1, *blk2;
+ int i;
+
+ /* This setup code is long'ish because the same base driver
+ * (if_nlge.c) is used for different:
+ * - CPUs (XLR/XLS)
+ * - boards (for each CPU, multiple board configs are possible
+ * and available).
+ *
+ * At the time of writing, there are atleast 12 boards, 4 with XLR
+ * and 8 with XLS. This means that the base driver needs to work with
+ * 12 different configurations, with varying levels of differences.
+ * To accomodate the different configs, the xlr_board_info struct
+ * has various attributes for paramters that could be different.
+ * These attributes are setup here and can be used directly in the
+ * base driver.
+ * It was seen that the setup code is not entirely trivial and
+ * it is possible to organize it in different ways. In the following,
+ * we choose an approach that sacrifices code-compactness/speed for
+ * readability. This is because configuration code executes once
+ * per reboot and hence has a minimal performance impact.
+ * On the other hand, driver debugging/enhancements require
+ * that different engineers can quickly comprehend the setup
+ * sequence. Hence, readability is seen as the key requirement for
+ * this code. It is for the reader to decide how much of this
+ * requirement is met with the current code organization !!
+ *
+ * The initialization is organized thus:
+ *
+ * if (CPU is XLS) {
+ * // initialize per XLS architecture
+ * // default inits (per chip spec)
+ * // board-specific overrides
+ * } else if (CPU is XLR) {
+ * // initialize per XLR architecture
+ * // default inits (per chip spec)
+ * // board-specific overrides
+ * }
+ *
+ * Within each CPU-specific initialization, all the default
+ * initializations are done first. This is followed up with
+ * board specific overrides.
+ */
+
+ /* start with a clean slate */
+ memset(&xlr_board_info, 0, sizeof(xlr_board_info));
+ xlr_board_info.ata = xlr_pcmcia_present();
+
+ blk0 = &xlr_board_info.gmac_block[0];
+ blk1 = &xlr_board_info.gmac_block[1];
+ blk2 = &xlr_board_info.gmac_block[2];
if (xlr_is_xls()) {
xlr_board_info.is_xls = 1;
@@ -113,98 +331,154 @@ xlr_board_info_setup()
/* Board version 8 has NAND flash */
xlr_board_info.cfi =
(xlr_boot1_info.board_major_version != RMI_XLR_BOARD_ARIZONA_VIII);
- xlr_board_info.ata = xlr_pcmcia_present();
xlr_board_info.pci_irq = 0;
xlr_board_info.credit_configs = xls_core_cc_configs;
- xlr_board_info.bucket_sizes = &xls_bucket_sizes;
- xlr_board_info.msgmap = xls_rxstn_to_txstn_map;
- xlr_board_info.gmacports = 8;
-
- /* network block 0 */
- xlr_board_info.gmac_block[0].type = XLR_GMAC;
- xlr_board_info.gmac_block[0].enabled = 0xf;
- xlr_board_info.gmac_block[0].credit_config = &xls_cc_table_gmac0;
- xlr_board_info.gmac_block[0].station_txbase = MSGRNG_STNID_GMACTX0;
- xlr_board_info.gmac_block[0].station_rfr = MSGRNG_STNID_GMACRFR_0;
- if (xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_VI ||
- xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_XI ||
- xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_XII)
- xlr_board_info.gmac_block[0].mode = XLR_PORT0_RGMII;
- else
- xlr_board_info.gmac_block[0].mode = XLR_SGMII;
- xlr_board_info.gmac_block[0].baseaddr = XLR_IO_GMAC_0_OFFSET;
- xlr_board_info.gmac_block[0].baseirq = PIC_GMAC_0_IRQ;
- xlr_board_info.gmac_block[0].baseinst = 0;
-
- /* network block 1 */
- xlr_board_info.gmac_block[1].type = XLR_GMAC;
- xlr_board_info.gmac_block[1].enabled = xlr_is_xls1xx() ? 0 : 0xf;
- if (xlr_is_xls4xx_lite()) {
- xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_GPIO_OFFSET);
- uint32_t tmp;
-
- /* some ports are not enabled on the condor 4xx, figure this
- out from the GPIO fuse bank */
- tmp = xlr_read_reg(mmio, 35);
- if (tmp & (1<<28))
- xlr_board_info.gmac_block[1].enabled &= ~0x8;
- if (tmp & (1<<29))
- xlr_board_info.gmac_block[1].enabled &= ~0x4;
+ xlr_board_info.bucket_sizes = &xls_bucket_sizes;
+ xlr_board_info.msgmap = xls_rxstn_to_txstn_map;
+ xlr_board_info.gmacports = MAX_NA_PORTS;
+
+ /* ---------------- Network Acc 0 ---------------- */
+
+ blk0->type = XLR_GMAC;
+ blk0->enabled = 0xf;
+ blk0->credit_config = &xls_cc_table_gmac0;
+ blk0->station_id = TX_STN_GMAC0;
+ blk0->station_txbase = MSGRNG_STNID_GMACTX0;
+ blk0->station_rfr = MSGRNG_STNID_GMACRFR_0;
+ blk0->mode = XLR_SGMII;
+ blk0->baseaddr = XLR_IO_GMAC_0_OFFSET;
+ blk0->baseirq = PIC_GMAC_0_IRQ;
+ blk0->baseinst = 0;
+
+ /* By default, assume SGMII is setup. But this can change based
+ on board-specific or setting-specific info. */
+ for (i = 0; i < 4; i++) {
+ blk0->gmac_port[i].valid = 1;
+ blk0->gmac_port[i].instance = i + blk0->baseinst;
+ blk0->gmac_port[i].type = XLR_SGMII;
+ blk0->gmac_port[i].phy_addr = i + 16;
+ blk0->gmac_port[i].tx_bucket_id =
+ blk0->station_txbase + i;
+ blk0->gmac_port[i].mdint_id = 0;
+ blk0->num_ports++;
+ blk0->gmac_port[i].base_addr = XLR_IO_GMAC_0_OFFSET + i * 0x1000;
+ blk0->gmac_port[i].mii_addr = XLR_IO_GMAC_0_OFFSET;
+ blk0->gmac_port[i].pcs_addr = XLR_IO_GMAC_0_OFFSET;
+ blk0->gmac_port[i].serdes_addr = XLR_IO_GMAC_0_OFFSET;
}
- xlr_board_info.gmac_block[1].credit_config = &xls_cc_table_gmac1;
- xlr_board_info.gmac_block[1].station_txbase = MSGRNG_STNID_GMAC1_TX0;
- xlr_board_info.gmac_block[1].station_rfr = MSGRNG_STNID_GMAC1_FR_0;
- xlr_board_info.gmac_block[1].mode = XLR_SGMII;
- xlr_board_info.gmac_block[1].baseaddr = XLR_IO_GMAC_4_OFFSET;
- xlr_board_info.gmac_block[1].baseirq = PIC_XGS_0_IRQ;
- xlr_board_info.gmac_block[1].baseinst = 4;
-
- /* network block 2 */
- xlr_board_info.gmac_block[2].enabled = 0; /* disabled on XLS */
- } else {
+
+ /* ---------------- Network Acc 1 ---------------- */
+ blk1->type = XLR_GMAC;
+ blk1->enabled = 0xf;
+ blk1->credit_config = &xls_cc_table_gmac1;
+ blk1->station_id = TX_STN_GMAC1;
+ blk1->station_txbase = MSGRNG_STNID_GMAC1_TX0;
+ blk1->station_rfr = MSGRNG_STNID_GMAC1_FR_0;
+ blk1->mode = XLR_SGMII;
+ blk1->baseaddr = XLR_IO_GMAC_4_OFFSET;
+ blk1->baseirq = PIC_XGS_0_IRQ;
+ blk1->baseinst = 4;
+
+ for (i = 0; i < 4; i++) {
+ blk1->gmac_port[i].valid = 1;
+ blk1->gmac_port[i].instance = i + blk1->baseinst;
+ blk1->gmac_port[i].type = XLR_SGMII;
+ blk1->gmac_port[i].phy_addr = i + 20;
+ blk1->gmac_port[i].tx_bucket_id =
+ blk1->station_txbase + i;
+ blk1->gmac_port[i].mdint_id = 1;
+ blk1->num_ports++;
+ blk1->gmac_port[i].base_addr = XLR_IO_GMAC_4_OFFSET + i * 0x1000;
+ blk1->gmac_port[i].mii_addr = XLR_IO_GMAC_4_OFFSET;
+ blk1->gmac_port[i].pcs_addr = XLR_IO_GMAC_4_OFFSET;
+ blk1->gmac_port[i].serdes_addr = XLR_IO_GMAC_0_OFFSET;
+ }
+
+ /* ---------------- Network Acc 2 ---------------- */
+ xlr_board_info.gmac_block[2].enabled = 0; /* disabled on XLS */
+
+ xls_board_specific_overrides(&xlr_board_info);
+
+ } else { /* XLR */
xlr_board_info.is_xls = 0;
xlr_board_info.nr_cpus = 32;
xlr_board_info.usb = 0;
xlr_board_info.cfi = 1;
- xlr_board_info.ata = xlr_pcmcia_present();
xlr_board_info.pci_irq = 0;
xlr_board_info.credit_configs = xlr_core_cc_configs;
- xlr_board_info.bucket_sizes = &bucket_sizes;
- xlr_board_info.msgmap = xlr_rxstn_to_txstn_map;
- xlr_board_info.gmacports = 4;
-
- /* GMAC0 */
- xlr_board_info.gmac_block[0].type = XLR_GMAC;
- xlr_board_info.gmac_block[0].enabled = 0xf;
- xlr_board_info.gmac_block[0].credit_config = &cc_table_gmac;
- xlr_board_info.gmac_block[0].station_txbase = MSGRNG_STNID_GMACTX0;
- xlr_board_info.gmac_block[0].station_rfr = MSGRNG_STNID_GMACRFR_0;
- xlr_board_info.gmac_block[0].mode = XLR_RGMII;
- xlr_board_info.gmac_block[0].baseaddr = XLR_IO_GMAC_0_OFFSET;
- xlr_board_info.gmac_block[0].baseirq = PIC_GMAC_0_IRQ;
- xlr_board_info.gmac_block[0].baseinst = 0;
-
- /* XGMAC0 */
- xlr_board_info.gmac_block[1].type = XLR_XGMAC;
- xlr_board_info.gmac_block[1].enabled = 1;
- xlr_board_info.gmac_block[1].credit_config = &cc_table_xgs_0;
- xlr_board_info.gmac_block[1].station_txbase = MSGRNG_STNID_XGS0_TX;
- xlr_board_info.gmac_block[1].station_rfr = MSGRNG_STNID_XGS0FR;
- xlr_board_info.gmac_block[1].mode = -1;
- xlr_board_info.gmac_block[1].baseaddr = XLR_IO_XGMAC_0_OFFSET;
- xlr_board_info.gmac_block[1].baseirq = PIC_XGS_0_IRQ;
- xlr_board_info.gmac_block[1].baseinst = 4;
-
- /* XGMAC1 */
- xlr_board_info.gmac_block[2].type = XLR_XGMAC;
- xlr_board_info.gmac_block[2].enabled = 1;
- xlr_board_info.gmac_block[2].credit_config = &cc_table_xgs_1;
- xlr_board_info.gmac_block[2].station_txbase = MSGRNG_STNID_XGS1_TX;
- xlr_board_info.gmac_block[2].station_rfr = MSGRNG_STNID_XGS1FR;
- xlr_board_info.gmac_block[2].mode = -1;
- xlr_board_info.gmac_block[2].baseaddr = XLR_IO_XGMAC_1_OFFSET;
- xlr_board_info.gmac_block[2].baseirq = PIC_XGS_1_IRQ;
- xlr_board_info.gmac_block[2].baseinst = 5;
- }
- return 0;
+ xlr_board_info.bucket_sizes = &bucket_sizes;
+ xlr_board_info.msgmap = xlr_rxstn_to_txstn_map;
+ xlr_board_info.gmacports = 4;
+
+ /* ---------------- GMAC0 ---------------- */
+ blk0->type = XLR_GMAC;
+ blk0->enabled = 0xf;
+ blk0->credit_config = &cc_table_gmac;
+ blk0->station_id = TX_STN_GMAC;
+ blk0->station_txbase = MSGRNG_STNID_GMACTX0;
+ blk0->station_rfr = MSGRNG_STNID_GMACRFR_0;
+ blk0->mode = XLR_RGMII;
+ blk0->baseaddr = XLR_IO_GMAC_0_OFFSET;
+ blk0->baseirq = PIC_GMAC_0_IRQ;
+ blk0->baseinst = 0;
+
+ /* first, do the common/easy stuff for all the ports */
+ for (i = 0; i < 4; i++) {
+ blk0->gmac_port[i].valid = 1;
+ blk0->gmac_port[i].instance = i + blk0->baseinst;
+ blk0->gmac_port[i].type = XLR_RGMII;
+ blk0->gmac_port[i].phy_addr = i;
+ blk0->gmac_port[i].tx_bucket_id =
+ blk0->station_txbase + i;
+ blk0->gmac_port[i].mdint_id = 0;
+ blk0->gmac_port[i].base_addr = XLR_IO_GMAC_0_OFFSET + i * 0x1000;
+ blk0->gmac_port[i].mii_addr = XLR_IO_GMAC_0_OFFSET;
+ /* RGMII ports, no PCS/SERDES */
+ blk0->num_ports++;
+ }
+
+ /* ---------------- XGMAC0 ---------------- */
+ blk1->type = XLR_XGMAC;
+ blk1->mode = XLR_XGMII;
+ blk1->enabled = 0;
+ blk1->credit_config = &cc_table_xgs_0;
+ blk1->station_txbase = MSGRNG_STNID_XGS0_TX;
+ blk1->station_rfr = MSGRNG_STNID_XMAC0RFR;
+ blk1->station_id = TX_STN_XGS_0; /* TBD: is this correct ? */
+ blk1->baseaddr = XLR_IO_XGMAC_0_OFFSET;
+ blk1->baseirq = PIC_XGS_0_IRQ;
+ blk1->baseinst = 4;
+
+ blk1->gmac_port[0].type = XLR_XGMII;
+ blk1->gmac_port[0].instance = 0;
+ blk1->gmac_port[0].phy_addr = 0;
+ blk1->gmac_port[0].base_addr = XLR_IO_XGMAC_0_OFFSET;
+ blk1->gmac_port[0].mii_addr = XLR_IO_XGMAC_0_OFFSET;
+ blk1->gmac_port[0].tx_bucket_id = blk1->station_txbase;
+ blk1->gmac_port[0].mdint_id = 1;
+
+ /* ---------------- XGMAC1 ---------------- */
+ blk2->type = XLR_XGMAC;
+ blk2->mode = XLR_XGMII;
+ blk2->enabled = 0;
+ blk2->credit_config = &cc_table_xgs_1;
+ blk2->station_txbase = MSGRNG_STNID_XGS1_TX;
+ blk2->station_rfr = MSGRNG_STNID_XMAC1RFR;
+ blk2->station_id = TX_STN_XGS_1; /* TBD: is this correct ? */
+ blk2->baseaddr = XLR_IO_XGMAC_1_OFFSET;
+ blk2->baseirq = PIC_XGS_1_IRQ;
+ blk2->baseinst = 5;
+
+ blk2->gmac_port[0].type = XLR_XGMII;
+ blk2->gmac_port[0].instance = 0;
+ blk2->gmac_port[0].phy_addr = 0;
+ blk2->gmac_port[0].base_addr = XLR_IO_XGMAC_1_OFFSET;
+ blk2->gmac_port[0].mii_addr = XLR_IO_XGMAC_1_OFFSET;
+ blk2->gmac_port[0].tx_bucket_id = blk2->station_txbase;
+ blk2->gmac_port[0].mdint_id = 2;
+
+ /* Done with default setup. Now do board-specific tweaks. */
+ xlr_board_specific_overrides(&xlr_board_info);
+ }
+ return 0;
}
diff --git a/sys/mips/rmi/board.h b/sys/mips/rmi/board.h
index a584af5..ed2c045 100644
--- a/sys/mips/rmi/board.h
+++ b/sys/mips/rmi/board.h
@@ -132,41 +132,53 @@ xlr_is_xls4xx_lite(void)
uint32_t chipid = xlr_processor_id();
return (chipid == 0x88 || chipid == 0x8c);
-}
+ }
+
+/* SPI-4 --> 8 ports, 1G MAC --> 4 ports and 10G MAC --> 1 port */
+#define MAX_NA_PORTS 8
/* all our knowledge of chip and board that cannot be detected run-time goes here */
-enum gmac_block_types {
- XLR_GMAC, XLR_XGMAC, XLR_SPI4
-};
-
-enum gmac_block_modes {
- XLR_RGMII, XLR_SGMII, XLR_PORT0_RGMII
-};
+enum gmac_block_types { XLR_GMAC, XLR_XGMAC, XLR_SPI4};
+enum gmac_port_types { XLR_RGMII, XLR_SGMII, XLR_PORT0_RGMII, XLR_XGMII, XLR_XAUI };
struct xlr_board_info {
int is_xls;
int nr_cpus;
- int usb; /* usb enabled ? */
- int cfi; /* NOR flash */
- int ata; /* PCMCIA/compactflash driver */
+ int usb; /* usb enabled ? */
+ int cfi; /* compact flash driver for NOR? */
+ int ata; /* ata driver */
int pci_irq;
- struct stn_cc **credit_configs; /* pointer to Core station credits */
- struct bucket_size *bucket_sizes; /* pointer to Core station
- * bucket */
- int *msgmap; /* mapping of message station to devices */
- int gmacports; /* number of gmac ports on the board */
- struct xlr_gmac_block_t {
- int type; /* see enum gmac_block_types */
- unsigned int enabled; /* mask of ports enabled */
- struct stn_cc *credit_config; /* credit configuration */
- int station_txbase; /* station id for tx */
- int station_rfr;/* free desc bucket */
- int mode; /* see gmac_block_modes */
- uint32_t baseaddr; /* IO base */
- int baseirq; /* first irq for this block, the rest are in
- * sequence */
- int baseinst; /* the first rge unit for this block */
- } gmac_block[3];
+ struct stn_cc **credit_configs; /* pointer to Core station credits */
+ struct bucket_size *bucket_sizes; /* pointer to Core station bucket */
+ int *msgmap; /* mapping of message station to devices */
+ int gmacports; /* number of gmac ports on the board */
+ struct xlr_gmac_block_t { /* refers to the set of GMACs controlled by a
+ network accelarator */
+ int type; /* see enum gmac_block_types */
+ unsigned int enabled; /* mask of ports enabled */
+ struct stn_cc *credit_config; /* credit configuration */
+ int station_id; /* station id for sending msgs */
+ int station_txbase; /* station id for tx */
+ int station_rfr; /* free desc bucket */
+ int mode; /* see gmac_block_modes */
+ uint32_t baseaddr; /* IO base */
+ int baseirq; /* first irq for this block, the rest are in sequence */
+ int baseinst; /* the first rge unit for this block */
+ int num_ports;
+ struct xlr_gmac_port {
+ int valid;
+ int type; /* see enum gmac_port_types */
+ uint32_t instance; /* identifies the GMAC to which
+ this port is bound to. */
+ uint32_t phy_addr;
+ uint32_t base_addr;
+ uint32_t mii_addr;
+ uint32_t pcs_addr;
+ uint32_t serdes_addr;
+ uint32_t tx_bucket_id;
+ uint32_t mdint_id;
+ } gmac_port[MAX_NA_PORTS];
+ } gmac_block [3];
};
extern struct xlr_board_info xlr_board_info;
diff --git a/sys/mips/rmi/dev/nlge/if_nlge.c b/sys/mips/rmi/dev/nlge/if_nlge.c
new file mode 100644
index 0000000..ec476ad
--- /dev/null
+++ b/sys/mips/rmi/dev/nlge/if_nlge.c
@@ -0,0 +1,2444 @@
+/*-
+ * Copyright (c) 2003-2009 RMI Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of RMI Corporation, nor the names of its contributors,
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RMI_BSD */
+
+/*
+ * The XLR device supports upto four 10/100/1000 Ethernet MACs and upto
+ * two 10G Ethernet MACs (of XGMII). Alternatively, each 10G port can used
+ * as a SPI-4 interface, with 8 ports per such interface. The MACs are
+ * encapsulated in another hardware block referred to as network accelerator,
+ * such that there are three instances of these in a XLR. One of them controls
+ * the four 1G RGMII ports while one each of the others controls an XGMII port.
+ * Enabling MACs requires configuring the corresponding network accelerator
+ * and the individual port.
+ * The XLS device supports upto 8 10/100/1000 Ethernet MACs or max 2 10G
+ * Ethernet MACs. The 1G MACs are of SGMII and 10G MACs are of XAUI
+ * interface. These ports are part of two network accelerators.
+ * The nlge driver configures and initializes non-SPI4 Ethernet ports in the
+ * XLR/XLS devices and enables data transfer on them.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_KERNEL_OPTION_HEADERS
+#include "opt_device_polling.h"
+#endif
+
+#include <sys/endian.h>
+#include <sys/systm.h>
+#include <sys/sockio.h>
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/limits.h>
+#include <sys/bus.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+#define __RMAN_RESOURCE_VISIBLE
+#include <sys/rman.h>
+#include <sys/taskqueue.h>
+#include <sys/smp.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/bpf.h>
+#include <net/if_types.h>
+#include <net/if_vlan_var.h>
+
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/uma.h>
+
+#include <machine/reg.h>
+#include <machine/cpu.h>
+#include <machine/mips_opcode.h>
+#include <machine/asm.h>
+#include <machine/cpuregs.h>
+#include <machine/param.h>
+#include <machine/intr_machdep.h>
+#include <machine/clock.h> /* for DELAY */
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <mips/rmi/interrupt.h>
+#include <mips/rmi/msgring.h>
+#include <mips/rmi/iomap.h>
+#include <mips/rmi/debug.h>
+#include <mips/rmi/pic.h>
+#include <mips/rmi/xlrconfig.h>
+#include <mips/rmi/shared_structs.h>
+#include <mips/rmi/board.h>
+#include <mips/rmi/rmi_mips_exts.h>
+#include <mips/rmi/dev/xlr/atx_cpld.h>
+#include <mips/rmi/dev/xlr/xgmac_mdio.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+#include "miidevs.h"
+#include <dev/mii/brgphyreg.h>
+#include "miibus_if.h"
+
+#include <mips/rmi/dev/nlge/if_nlge.h>
+
+MODULE_DEPEND(nlna, nlge, 1, 1, 1);
+MODULE_DEPEND(nlge, ether, 1, 1, 1);
+MODULE_DEPEND(nlge, miibus, 1, 1, 1);
+
+/* Network accelarator entry points */
+static int nlna_probe(device_t);
+static int nlna_attach(device_t);
+static int nlna_detach(device_t);
+static int nlna_suspend(device_t);
+static int nlna_resume(device_t);
+static int nlna_shutdown(device_t);
+
+/* GMAC port entry points */
+static int nlge_probe(device_t);
+static int nlge_attach(device_t);
+static int nlge_detach(device_t);
+static int nlge_suspend(device_t);
+static int nlge_resume(device_t);
+static void nlge_init(void *);
+static int nlge_ioctl(struct ifnet *, u_long, caddr_t);
+static void nlge_start(struct ifnet *);
+static void nlge_rx(struct nlge_softc *sc, vm_paddr_t paddr, int len);
+
+static int nlge_mii_write(struct device *, int, int, int);
+static int nlge_mii_read(struct device *, int, int);
+static void nlge_mac_mii_statchg(device_t);
+static int nlge_mediachange(struct ifnet *ifp);
+static void nlge_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr);
+
+/* Other internal/helper functions */
+static void *get_buf(void);
+static struct mbuf *get_mbuf(void);
+
+static void nlna_add_to_port_set(struct nlge_port_set *pset,
+ struct nlge_softc *sc);
+static void nlna_config_pde(struct nlna_softc *);
+static void nlna_config_parser(struct nlna_softc *);
+static void nlna_config_classifier(struct nlna_softc *);
+static void nlna_config_fifo_spill_area(struct nlna_softc *sc);
+static void nlna_config_common(struct nlna_softc *);
+static void nlna_disable_ports(struct nlna_softc *sc);
+static void nlna_enable_intr(struct nlna_softc *sc);
+static void nlna_disable_intr(struct nlna_softc *sc);
+static void nlna_enable_ports(struct nlna_softc *sc);
+static void nlna_get_all_softc(device_t iodi_dev,
+ struct nlna_softc **sc_vec, uint32_t vec_sz);
+static void nlna_hw_init(struct nlna_softc *sc);
+static int nlna_is_last_active_na(struct nlna_softc *sc);
+static void nlna_media_specific_config(struct nlna_softc *sc);
+static void nlna_reset_ports(struct nlna_softc *sc,
+ struct xlr_gmac_block_t *blk);
+static struct nlna_softc *nlna_sc_init(device_t dev,
+ struct xlr_gmac_block_t *blk);
+static __inline__ int nlna_send_free_desc(struct nlna_softc *nlna,
+ vm_paddr_t addr);
+static void nlna_setup_intr(struct nlna_softc *sc);
+static void nlna_smp_update_pde(void *dummy __unused);
+static void nlna_submit_rx_free_desc(struct nlna_softc *sc,
+ uint32_t n_desc);
+
+static int nlge_gmac_config_speed(struct nlge_softc *, int quick);
+static void nlge_hw_init(struct nlge_softc *sc);
+static int nlge_if_init(struct nlge_softc *sc);
+static void nlge_intr(void *arg);
+static int nlge_irq_init(struct nlge_softc *sc);
+static void nlge_irq_fini(struct nlge_softc *sc);
+static void nlge_media_specific_init(struct nlge_softc *sc);
+static void nlge_mii_init(device_t dev, struct nlge_softc *sc);
+static int nlge_mii_read_internal(xlr_reg_t *mii_base, int phyaddr,
+ int regidx);
+static void nlge_mii_write_internal(xlr_reg_t *mii_base, int phyaddr,
+ int regidx, int regval);
+void nlge_msgring_handler(int bucket, int size, int code,
+ int stid, struct msgrng_msg *msg, void *data);
+static void nlge_port_disable(int id, xlr_reg_t *base, int port_type);
+static void nlge_port_enable(struct nlge_softc *sc);
+static void nlge_read_mac_addr(struct nlge_softc *sc);
+static void nlge_sc_init(struct nlge_softc *sc, device_t dev,
+ struct xlr_gmac_port *port_info);
+static void nlge_set_mac_addr(struct nlge_softc *sc);
+static void nlge_set_port_attribs(struct nlge_softc *,
+ struct xlr_gmac_port *);
+static void nlge_sgmii_init(struct nlge_softc *sc);
+static void nlge_start_locked(struct ifnet *ifp, struct nlge_softc *sc);
+
+static int prepare_fmn_message(struct nlge_softc *sc,
+ struct msgrng_msg *msg, uint32_t *n_entries, struct mbuf *m_head,
+ uint64_t fr_stid, struct nlge_tx_desc **tx_desc);
+
+static void release_mbuf(uint64_t phy_addr);
+static void release_tx_desc(struct msgrng_msg *msg, int rel_buf);
+static int send_fmn_msg_tx(struct nlge_softc *, struct msgrng_msg *,
+ uint32_t n_entries);
+
+//#define DEBUG
+#ifdef DEBUG
+static int mac_debug = 1;
+static int reg_dump = 0;
+#undef PDEBUG
+#define PDEBUG(fmt, args...) \
+ do {\
+ if (mac_debug) {\
+ printf("[%s@%d|%s]: cpu_%d: " fmt, \
+ __FILE__, __LINE__, __FUNCTION__, PCPU_GET(cpuid), ##args);\
+ }\
+ } while(0);
+
+/* Debug/dump functions */
+static void dump_reg(xlr_reg_t *addr, uint32_t offset, char *name);
+static void dump_gmac_registers(struct nlge_softc *);
+static void dump_na_registers(xlr_reg_t *base, int port_id);
+static void dump_mac_stats(struct nlge_softc *sc);
+static void dump_mii_regs(struct nlge_softc *sc) __attribute__((used));
+static void dump_mii_data(struct mii_data *mii) __attribute__((used));
+static void dump_board_info(struct xlr_board_info *);
+static void dump_pcs_regs(struct nlge_softc *sc, int phy);
+
+#else
+#undef PDEBUG
+#define PDEBUG(fmt, args...)
+#define dump_reg(a, o, n) /* nop */
+#define dump_gmac_registers(a) /* nop */
+#define dump_na_registers(a, p) /* nop */
+#define dump_board_info(b) /* nop */
+#define dump_mac_stats(sc) /* nop */
+#define dump_mii_regs(sc) /* nop */
+#define dump_mii_data(mii) /* nop */
+#define dump_pcs_regs(sc, phy) /* nop */
+#endif
+
+/* Wrappers etc. to export the driver entry points. */
+static device_method_t nlna_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, nlna_probe),
+ DEVMETHOD(device_attach, nlna_attach),
+ DEVMETHOD(device_detach, nlna_detach),
+ DEVMETHOD(device_shutdown, nlna_shutdown),
+ DEVMETHOD(device_suspend, nlna_suspend),
+ DEVMETHOD(device_resume, nlna_resume),
+
+ /* bus interface : TBD : what are these for ? */
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_driver_added, bus_generic_driver_added),
+
+ { 0, 0 }
+};
+
+static driver_t nlna_driver = {
+ "nlna",
+ nlna_methods,
+ sizeof(struct nlna_softc)
+};
+
+static devclass_t nlna_devclass;
+
+static device_method_t nlge_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, nlge_probe),
+ DEVMETHOD(device_attach, nlge_attach),
+ DEVMETHOD(device_detach, nlge_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, nlge_suspend),
+ DEVMETHOD(device_resume, nlge_resume),
+
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, nlge_mii_read),
+ DEVMETHOD(miibus_writereg, nlge_mii_write),
+ DEVMETHOD(miibus_statchg, nlge_mac_mii_statchg),
+
+ {0, 0}
+};
+
+static driver_t nlge_driver = {
+ "nlge",
+ nlge_methods,
+ sizeof(struct nlge_softc)
+};
+
+static devclass_t nlge_devclass;
+
+DRIVER_MODULE(nlna, iodi, nlna_driver, nlna_devclass, 0, 0);
+DRIVER_MODULE(nlge, nlna, nlge_driver, nlge_devclass, 0, 0);
+DRIVER_MODULE(miibus, nlge, miibus_driver, miibus_devclass, 0, 0);
+
+static uma_zone_t nl_tx_desc_zone;
+
+/* Function to atomically increment an integer with the given value. */
+static __inline__ unsigned int
+ldadd_wu(unsigned int value, unsigned long *addr)
+{
+ __asm__ __volatile__( ".set push\n"
+ ".set noreorder\n"
+ "move $8, %2\n"
+ "move $9, %3\n"
+ /* "ldaddwu $8, $9\n" */
+ ".word 0x71280011\n"
+ "move %0, $8\n"
+ ".set pop\n"
+ : "=&r"(value), "+m"(*addr)
+ : "0"(value), "r" ((unsigned long)addr)
+ : "$8", "$9");
+ return value;
+}
+
+static __inline__ uint32_t
+xlr_enable_kx(void)
+{
+ uint32_t sr = mips_rd_status();
+
+ mips_wr_status((sr & ~MIPS_SR_INT_IE) | MIPS_SR_KX);
+ return sr;
+}
+
+static int
+nlna_probe(device_t dev)
+{
+ return (BUS_PROBE_DEFAULT);
+}
+
+/*
+ * Add all attached GMAC/XGMAC ports to the device tree. Port
+ * configuration is spread in two regions - common configuration
+ * for all ports in the NA and per-port configuration in MAC-specific
+ * region. This function does the following:
+ * - adds the ports to the device tree
+ * - reset the ports
+ * - do all the common initialization
+ * - invoke bus_generic_attach for per-port configuration
+ * - supply initial free rx descriptors to ports
+ * - initialize s/w data structures
+ * - finally, enable interrupts (only in the last NA).
+ *
+ * For reference, sample address space for common and per-port
+ * registers is given below.
+ *
+ * The address map for RNA0 is: (typical value)
+ *
+ * XLR_IO_BASE +--------------------------------------+ 0xbef0_0000
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * GMAC0 ---> +--------------------------------------+ 0xbef0_c000
+ * | |
+ * | |
+ * (common) -> |......................................| 0xbef0_c400
+ * | |
+ * | (RGMII/SGMII: common registers) |
+ * | |
+ * GMAC1 ---> |--------------------------------------| 0xbef0_d000
+ * | |
+ * | |
+ * (common) -> |......................................| 0xbef0_d400
+ * | |
+ * | (RGMII/SGMII: common registers) |
+ * | |
+ * |......................................|
+ * and so on ....
+ *
+ * Ref: Figure 14-3 and Table 14-1 of XLR PRM
+ */
+static int
+nlna_attach(device_t dev)
+{
+ struct xlr_gmac_block_t *block_info;
+ device_t gmac_dev;
+ struct nlna_softc *sc;
+ int error;
+ int i;
+ int id;
+
+ id = device_get_unit(dev);
+ block_info = device_get_ivars(dev);
+ if (!block_info->enabled) {
+ return 0;
+ }
+
+#ifdef DEBUG
+ dump_board_info(&xlr_board_info);
+#endif
+ block_info->baseaddr += DEFAULT_XLR_IO_BASE;
+
+ /* Initialize nlna state in softc structure */
+ sc = nlna_sc_init(dev, block_info);
+
+ /* Add device's for the ports controlled by this NA. */
+ if (block_info->type == XLR_GMAC) {
+ KASSERT(id < 2, ("No GMACs supported with this network"
+ "accelerator: %d", id));
+ for (i = 0; i < sc->num_ports; i++) {
+ gmac_dev = device_add_child(dev, "nlge", -1);
+ device_set_ivars(gmac_dev, &block_info->gmac_port[i]);
+ }
+ } else if (block_info->type == XLR_XGMAC) {
+ KASSERT(id > 0 && id <= 2, ("No XGMACs supported with this"
+ "network accelerator: %d", id));
+ gmac_dev = device_add_child(dev, "nlge", -1);
+ device_set_ivars(gmac_dev, &block_info->gmac_port[0]);
+ } else if (block_info->type == XLR_SPI4) {
+ /* SPI4 is not supported here */
+ device_printf(dev, "Unsupported: NA with SPI4 type");
+ return (ENOTSUP);
+ }
+
+ nlna_reset_ports(sc, block_info);
+
+ /* Initialize Network Accelarator registers. */
+ nlna_hw_init(sc);
+
+ error = bus_generic_attach(dev);
+ if (error) {
+ device_printf(dev, "failed to attach port(s)\n");
+ goto fail;
+ }
+
+ /* Send out the initial pool of free-descriptors for the rx path */
+ nlna_submit_rx_free_desc(sc, MAX_FRIN_SPILL);
+
+ /* S/w data structure initializations shared by all NA's. */
+ if (nl_tx_desc_zone == NULL) {
+ /* Create a zone for allocating tx descriptors */
+ nl_tx_desc_zone = uma_zcreate("NL Tx Desc",
+ sizeof(struct nlge_tx_desc), NULL, NULL, NULL, NULL,
+ XLR_CACHELINE_SIZE, 0);
+ }
+
+ /* Enable NA interrupts */
+ nlna_setup_intr(sc);
+
+ return (0);
+
+fail:
+ return (error);
+}
+
+static int
+nlna_detach(device_t dev)
+{
+ struct nlna_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (device_is_alive(dev)) {
+ nlna_disable_intr(sc);
+ /* This will make sure that per-port detach is complete
+ * and all traffic on the ports has been stopped. */
+ bus_generic_detach(dev);
+ uma_zdestroy(nl_tx_desc_zone);
+ }
+
+ return (0);
+}
+
+static int
+nlna_suspend(device_t dev)
+{
+
+ return (0);
+}
+
+static int
+nlna_resume(device_t dev)
+{
+
+ return (0);
+}
+
+static int
+nlna_shutdown(device_t dev)
+{
+ return (0);
+}
+
+
+/* GMAC port entry points */
+static int
+nlge_probe(device_t dev)
+{
+ struct nlge_softc *sc;
+ struct xlr_gmac_port *port_info;
+ int index;
+ char *desc[] = { "RGMII", "SGMII", "RGMII/SGMII", "XGMAC", "XAUI",
+ "Unknown"};
+
+ port_info = device_get_ivars(dev);
+ index = (port_info->type < XLR_RGMII || port_info->type > XLR_XAUI) ?
+ 5 : port_info->type;
+ device_set_desc_copy(dev, desc[index]);
+
+ sc = device_get_softc(dev);
+ nlge_sc_init(sc, dev, port_info);
+
+ nlge_port_disable(sc->id, sc->base, sc->port_type);
+
+ return (0);
+}
+
+static int
+nlge_attach(device_t dev)
+{
+ struct nlge_softc *sc;
+ struct nlna_softc *nsc;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ nlge_if_init(sc);
+ nlge_mii_init(dev, sc);
+ error = nlge_irq_init(sc);
+ if (error)
+ return error;
+ nlge_hw_init(sc);
+
+ nsc = (struct nlna_softc *)device_get_softc(device_get_parent(dev));
+ nsc->child_sc[sc->instance] = sc;
+
+ return (0);
+}
+
+static int
+nlge_detach(device_t dev)
+{
+ struct nlge_softc *sc;
+ struct ifnet *ifp;
+
+ sc = device_get_softc(dev);
+ ifp = sc->nlge_if;
+
+ if (device_is_attached(dev)) {
+ ifp->if_drv_flags &= ~(IFF_DRV_OACTIVE | IFF_DRV_RUNNING);
+ nlge_port_disable(sc->id, sc->base, sc->port_type);
+ nlge_irq_fini(sc);
+ ether_ifdetach(ifp);
+ bus_generic_detach(dev);
+ }
+ if (ifp)
+ if_free(ifp);
+
+ return (0);
+}
+
+static int
+nlge_suspend(device_t dev)
+{
+ return (0);
+}
+
+static int
+nlge_resume(device_t dev)
+{
+ return (0);
+}
+
+static void
+nlge_init(void *addr)
+{
+ struct nlge_softc *sc;
+ struct ifnet *ifp;
+
+ sc = (struct nlge_softc *)addr;
+ ifp = sc->nlge_if;
+
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ return;
+
+ nlge_gmac_config_speed(sc, 0);
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ nlge_port_enable(sc);
+
+ if (sc->port_type == XLR_SGMII) {
+ dump_pcs_regs(sc, 27);
+ }
+ dump_gmac_registers(sc);
+ dump_mac_stats(sc);
+}
+
+static int
+nlge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
+{
+ struct mii_data *mii;
+ struct nlge_softc *sc;
+ struct ifreq *ifr;
+ int error;
+
+ sc = ifp->if_softc;
+ error = 0;
+ ifr = (struct ifreq *)data;
+ switch(command) {
+ case SIOCSIFFLAGS:
+ break;
+ case SIOCSIFMEDIA:
+ case SIOCGIFMEDIA:
+ if (sc->mii_bus != NULL) {
+ mii = (struct mii_data *)device_get_softc(sc->mii_bus);
+ error = ifmedia_ioctl(ifp, ifr, &mii->mii_media,
+ command);
+ }
+ break;
+ case SIOCSIFADDR:
+ // intentional fall thru
+ case SIOCSIFMTU:
+ default:
+ error = ether_ioctl(ifp, command, data);
+ break;
+ }
+
+ return (error);
+}
+
+/* This function is called from an interrupt handler */
+void
+nlge_msgring_handler(int bucket, int size, int code, int stid,
+ struct msgrng_msg *msg, void *data)
+{
+ struct nlna_softc *na_sc;
+ struct nlge_softc *sc;
+ struct ifnet *ifp;
+ uint64_t phys_addr;
+ unsigned long addr;
+ uint32_t length;
+ int ctrl;
+ int cpu;
+ int tx_error;
+ int port;
+ int vcpu;
+ int is_p2p;
+
+ cpu = xlr_core_id();
+ vcpu = (cpu << 2) + xlr_thr_id();
+
+ addr = 0;
+ is_p2p = 0;
+ tx_error = 0;
+ length = (msg->msg0 >> 40) & 0x3fff;
+ na_sc = (struct nlna_softc *)data;
+ phys_addr = (uint64_t) (msg->msg0 & 0xffffffffe0ULL);
+ if (length == 0) {
+ ctrl = CTRL_REG_FREE;
+ port = (msg->msg0 >> 54) & 0x0f;
+ is_p2p = (msg->msg0 >> 62) & 0x1;
+ tx_error = (msg->msg0 >> 58) & 0xf;
+ } else {
+ ctrl = CTRL_SNGL;
+ length = length - BYTE_OFFSET - MAC_CRC_LEN;
+ port = msg->msg0 & 0x0f;
+ }
+
+ sc = na_sc->child_sc[port];
+ if (sc == NULL) {
+ printf("Message (of %d len) with softc=NULL on %d port (type=%s)\n",
+ length, port, (ctrl == CTRL_SNGL ? "Pkt rx" :
+ "Freeback for tx packet"));
+ return;
+ }
+
+ if (ctrl == CTRL_REG_FREE || ctrl == CTRL_JUMBO_FREE) {
+ if (is_p2p)
+ release_tx_desc(msg, 1);
+ else {
+ release_mbuf(msg->msg0 & 0xffffffffffULL);
+ }
+ ifp = sc->nlge_if;
+ if (ifp->if_drv_flags & IFF_DRV_OACTIVE){
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ }
+ ldadd_wu(1, (tx_error) ? &ifp->if_oerrors: &ifp->if_opackets);
+ } else if (ctrl == CTRL_SNGL || ctrl == CTRL_START) {
+ /* Rx Packet */
+
+ nlge_rx(sc, phys_addr, length);
+ nlna_submit_rx_free_desc(na_sc, 1); /* return free descr to NA */
+ } else {
+ printf("[%s]: unrecognized ctrl=%d!\n", __FUNCTION__, ctrl);
+ }
+
+}
+
+static void
+nlge_start(struct ifnet *ifp)
+{
+ struct nlge_softc *sc;
+
+ sc = ifp->if_softc;
+ //NLGE_LOCK(sc);
+ nlge_start_locked(ifp, sc);
+ //NLGE_UNLOCK(sc);
+}
+
+static void
+nlge_start_locked(struct ifnet *ifp, struct nlge_softc *sc)
+{
+ struct msgrng_msg msg;
+ struct mbuf *m;
+ struct nlge_tx_desc *tx_desc;
+ uint64_t fr_stid;
+ uint32_t cpu;
+ uint32_t n_entries;
+ uint32_t tid;
+ int ret;
+ int sent;
+
+ cpu = xlr_core_id();
+ tid = xlr_thr_id();
+ fr_stid = (cpu << 3) + tid + 4; /* Each CPU has 8 buckets. */
+
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ return;
+ }
+
+ do {
+ /* Grab a packet off the queue. */
+ IF_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL) {
+ return;
+ }
+
+ tx_desc = NULL;
+ ret = prepare_fmn_message(sc, &msg, &n_entries, m, fr_stid, &tx_desc);
+ if (ret) {
+ goto fail;
+ }
+ sent = send_fmn_msg_tx(sc, &msg, n_entries);
+ if (!sent) {
+ goto fail;
+ }
+ } while(1);
+
+ return;
+
+fail:
+ if (tx_desc != NULL) {
+ uma_zfree(nl_tx_desc_zone, tx_desc);
+ }
+ if (m != NULL) {
+ /*
+ * TBD: It is observed that only when both of the statements
+ * below are not enabled, traffic continues till the end.
+ * Otherwise, the port locks up in the middle and never
+ * recovers from it. The current theory for this behavior
+ * is that the queue is full and the upper layer is neither
+ * able to add to it not invoke nlge_start to drian the
+ * queue. The driver may have to do something in addition
+ * to reset'ing the OACTIVE bit when a trasnmit free-back
+ * is received.
+ */
+ //ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ //IF_PREPEND(&ifp->if_snd, m);
+ m_freem(m);
+ ldadd_wu(1, &ifp->if_iqdrops);
+ }
+ return;
+}
+
+static void
+nlge_rx(struct nlge_softc *sc, vm_paddr_t paddr, int len)
+{
+ struct ifnet *ifp;
+ struct mbuf *m;
+ uint32_t tm, mag, sr;
+
+ sr = xlr_enable_kx();
+ tm = xlr_paddr_lw(paddr - XLR_CACHELINE_SIZE);
+ mag = xlr_paddr_lw(paddr - XLR_CACHELINE_SIZE + sizeof(uint32_t));
+ mips_wr_status(sr);
+
+ m = (struct mbuf *)(intptr_t)tm;
+ if (mag != 0xf00bad) {
+ /* somebody else's packet. Error - FIXME in intialization */
+ printf("cpu %d: *ERROR* Not my packet paddr %llx\n",
+ xlr_core_id(), (uint64_t) paddr);
+ return;
+ }
+
+ ifp = sc->nlge_if;
+ /* align the data */
+ m->m_data += BYTE_OFFSET;
+ m->m_pkthdr.len = m->m_len = len;
+ m->m_pkthdr.rcvif = ifp;
+
+ ldadd_wu(1, &ifp->if_ipackets);
+ (*ifp->if_input)(ifp, m);
+}
+
+static int
+nlge_mii_write(struct device *dev, int phyaddr, int regidx, int regval)
+{
+ struct nlge_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (sc->phy_addr == phyaddr && sc->port_type != XLR_XGMII)
+ nlge_mii_write_internal(sc->mii_base, phyaddr, regidx, regval);
+
+ return (0);
+}
+
+static int
+nlge_mii_read(struct device *dev, int phyaddr, int regidx)
+{
+ struct nlge_softc *sc;
+ int val;
+
+ sc = device_get_softc(dev);
+ val = (sc->phy_addr != phyaddr && sc->port_type != XLR_XGMII) ? (0xffff) :
+ nlge_mii_read_internal(sc->mii_base, phyaddr, regidx);
+
+ return (val);
+}
+
+static void
+nlge_mac_mii_statchg(device_t dev)
+{
+}
+
+static int
+nlge_mediachange(struct ifnet *ifp)
+{
+ return 0;
+}
+
+static void
+nlge_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ struct nlge_softc *sc;
+ struct mii_data *md;
+
+ md = NULL;
+ sc = ifp->if_softc;
+ if (sc->mii_bus)
+ md = device_get_softc(sc->mii_bus);
+
+ ifmr->ifm_status = IFM_AVALID;
+ ifmr->ifm_active = IFM_ETHER;
+
+ if (sc->link == xlr_mac_link_down)
+ return;
+
+ if (md != NULL)
+ ifmr->ifm_active = md->mii_media.ifm_cur->ifm_media;
+ ifmr->ifm_status |= IFM_ACTIVE;
+}
+
+static struct nlna_softc *
+nlna_sc_init(device_t dev, struct xlr_gmac_block_t *blk)
+{
+ struct nlna_softc *sc;
+
+ sc = device_get_softc(dev);
+ memset(sc, 0, sizeof(*sc));
+ sc->nlna_dev = dev;
+ sc->base = (xlr_reg_t *) blk->baseaddr;
+ sc->rfrbucket = blk->station_rfr;
+ sc->station_id = blk->station_id;
+ sc->na_type = blk->type;
+ sc->mac_type = blk->mode;
+ sc->num_ports = blk->num_ports;
+
+ sc->mdio_set.port_vec = sc->mdio_sc;
+ sc->mdio_set.vec_sz = XLR_MAX_MACS;
+
+ return (sc);
+}
+
+/*
+ * Do:
+ * - Initialize common GMAC registers (index range 0x100-0x3ff).
+ */
+static void
+nlna_hw_init(struct nlna_softc *sc)
+{
+
+ /*
+ * It is seen that this is a critical function in bringing up FreeBSD.
+ * When it is not invoked, FreeBSD panics and fails during the
+ * multi-processor init (SI_SUB_SMP of * mi_startup). The key function
+ * in this sequence seems to be platform_prep_smp_launch. */
+ if (register_msgring_handler(sc->station_id, nlge_msgring_handler, sc)) {
+ panic("Couldn't register msgring handler\n");
+ }
+ nlna_config_fifo_spill_area(sc);
+ nlna_config_pde(sc);
+ nlna_config_common(sc);
+ nlna_config_parser(sc);
+ nlna_config_classifier(sc);
+}
+
+/*
+ * Enable interrupts on all the ports controlled by this NA. For now, we
+ * only care about the MII interrupt and this has to be enabled only
+ * on the port id0.
+ *
+ * This function is not in-sync with the regular way of doing things - it
+ * executes only in the context of the last active network accelerator (and
+ * thereby has some ugly accesses in the device tree). Though inelegant, it
+ * is necessary to do it this way as the per-port interrupts can be
+ * setup/enabled only after all the network accelerators have been
+ * initialized.
+ */
+static void
+nlna_setup_intr(struct nlna_softc *sc)
+{
+ struct nlna_softc *na_sc[XLR_MAX_NLNA];
+ struct nlge_port_set *pset;
+ struct xlr_gmac_port *port_info;
+ device_t iodi_dev;
+ int i, j;
+
+ if (!nlna_is_last_active_na(sc))
+ return ;
+
+ /* Collect all nlna softc pointers */
+ memset(na_sc, 0, sizeof(*na_sc) * XLR_MAX_NLNA);
+ iodi_dev = device_get_parent(sc->nlna_dev);
+ nlna_get_all_softc(iodi_dev, na_sc, XLR_MAX_NLNA);
+
+ /* Setup the MDIO interrupt lists. */
+ /*
+ * MDIO interrupts are coarse - a single interrupt line provides
+ * information about one of many possible ports. To figure out the
+ * exact port on which action is to be taken, all of the ports
+ * linked to an MDIO interrupt should be read. To enable this,
+ * ports need to add themselves to port sets.
+ */
+ for (i = 0; i < XLR_MAX_NLNA; i++) {
+ if (na_sc[i] == NULL)
+ continue;
+ for (j = 0; j < na_sc[i]->num_ports; j++) {
+ /* processing j-th port on i-th NA */
+ port_info = device_get_ivars(
+ na_sc[i]->child_sc[j]->nlge_dev);
+ pset = &na_sc[port_info->mdint_id]->mdio_set;
+ nlna_add_to_port_set(pset, na_sc[i]->child_sc[j]);
+ }
+ }
+
+ /* Enable interrupts */
+ for (i = 0; i < XLR_MAX_NLNA; i++) {
+ if (na_sc[i] != NULL && na_sc[i]->na_type != XLR_XGMAC) {
+ nlna_enable_intr(na_sc[i]);
+ }
+ }
+}
+
+static void
+nlna_add_to_port_set(struct nlge_port_set *pset, struct nlge_softc *sc)
+{
+ int i;
+
+ /* step past the non-NULL elements */
+ for (i = 0; i < pset->vec_sz && pset->port_vec[i] != NULL; i++) ;
+ if (i < pset->vec_sz)
+ pset->port_vec[i] = sc;
+ else
+ printf("warning: internal error: out-of-bounds for MDIO array");
+}
+
+static void
+nlna_enable_intr(struct nlna_softc *sc)
+{
+ int i;
+
+ for (i = 0; i < sc->num_ports; i++) {
+ if (sc->child_sc[i]->instance == 0)
+ NLGE_WRITE(sc->child_sc[i]->base, R_INTMASK,
+ (1 << O_INTMASK__MDInt));
+ }
+}
+
+static void
+nlna_disable_intr(struct nlna_softc *sc)
+{
+ int i;
+
+ for (i = 0; i < sc->num_ports; i++) {
+ if (sc->child_sc[i]->instance == 0)
+ NLGE_WRITE(sc->child_sc[i]->base, R_INTMASK, 0);
+ }
+}
+
+static int
+nlna_is_last_active_na(struct nlna_softc *sc)
+{
+ int id;
+
+ id = device_get_unit(sc->nlna_dev);
+ return (id == 2 || xlr_board_info.gmac_block[id + 1].enabled == 0);
+}
+
+static __inline__ int
+nlna_send_free_desc(struct nlna_softc *sc, vm_paddr_t addr)
+{
+ struct msgrng_msg msg;
+ int stid;
+ int code;
+ int i;
+
+ stid = sc->rfrbucket;
+ memset(&msg, 0, sizeof(msg));
+ msg.msg0 = (uint64_t) addr & 0xffffffffe0ULL;
+
+ code = (sc->na_type == XLR_XGMAC) ? MSGRNG_CODE_XGMAC : MSGRNG_CODE_MAC;
+ for (i = 0; i < MAX_MSG_SND_ATTEMPTS; i++) {
+ if (message_send(1, code, stid, &msg) == 0)
+ return (0);
+ }
+ printf("Error: failed to send free desc to station %d\n", stid);
+ return (1);
+}
+
+static void
+nlna_submit_rx_free_desc(struct nlna_softc *sc, uint32_t n_desc)
+{
+ void *ptr;
+ unsigned long msgrng_flags;
+ int i;
+ int ret;
+
+ if (n_desc > 1) {
+ PDEBUG("Sending %d free-in descriptors to station=%d\n", n_desc,
+ sc->rfrbucket);
+ }
+
+ for (i = 0; i < n_desc; i++) {
+ ptr = get_buf();
+ if (!ptr) {
+ ret = -ENOMEM;
+ device_printf(sc->nlna_dev, "Cannot allocate mbuf\n");
+ break;
+ }
+
+ /* Send the free Rx desc to the MAC */
+ msgrng_access_enable(msgrng_flags);
+ ret = nlna_send_free_desc(sc, vtophys(ptr));
+ msgrng_access_disable(msgrng_flags);
+ if (ret) /* no point trying other descriptors after
+ a failure. */
+ break;
+ }
+}
+
+static __inline__ void *
+nlna_config_spill(xlr_reg_t *base, int reg_start_0, int reg_start_1,
+ int reg_size, int size)
+{
+ void *spill;
+ uint64_t phys_addr;
+ uint32_t spill_size;
+
+ spill_size = size;
+ spill = contigmalloc((spill_size + XLR_CACHELINE_SIZE), M_DEVBUF,
+ M_NOWAIT | M_ZERO, 0, 0xffffffff, XLR_CACHELINE_SIZE, 0);
+ if (spill == NULL || ((vm_offset_t) spill & (XLR_CACHELINE_SIZE - 1))) {
+ panic("Unable to allocate memory for spill area!\n");
+ }
+ phys_addr = vtophys(spill);
+ PDEBUG("Allocated spill %d bytes at %llx\n", size, phys_addr);
+ NLGE_WRITE(base, reg_start_0, (phys_addr >> 5) & 0xffffffff);
+ NLGE_WRITE(base, reg_start_1, (phys_addr >> 37) & 0x07);
+ NLGE_WRITE(base, reg_size, spill_size);
+
+ return (spill);
+}
+
+/*
+ * Configure the 6 FIFO's that are used by the network accelarator to
+ * communicate with the rest of the XLx device. 4 of the FIFO's are for
+ * packets from NA --> cpu (called Class FIFO's) and 2 are for feeding
+ * the NA with free descriptors.
+ */
+static void
+nlna_config_fifo_spill_area(struct nlna_softc *sc)
+{
+ sc->frin_spill = nlna_config_spill(sc->base,
+ R_REG_FRIN_SPILL_MEM_START_0,
+ R_REG_FRIN_SPILL_MEM_START_1,
+ R_REG_FRIN_SPILL_MEM_SIZE,
+ MAX_FRIN_SPILL *
+ sizeof(struct fr_desc));
+ sc->frout_spill = nlna_config_spill(sc->base,
+ R_FROUT_SPILL_MEM_START_0,
+ R_FROUT_SPILL_MEM_START_1,
+ R_FROUT_SPILL_MEM_SIZE,
+ MAX_FROUT_SPILL *
+ sizeof(struct fr_desc));
+ sc->class_0_spill = nlna_config_spill(sc->base,
+ R_CLASS0_SPILL_MEM_START_0,
+ R_CLASS0_SPILL_MEM_START_1,
+ R_CLASS0_SPILL_MEM_SIZE,
+ MAX_CLASS_0_SPILL *
+ sizeof(union rx_tx_desc));
+ sc->class_1_spill = nlna_config_spill(sc->base,
+ R_CLASS1_SPILL_MEM_START_0,
+ R_CLASS1_SPILL_MEM_START_1,
+ R_CLASS1_SPILL_MEM_SIZE,
+ MAX_CLASS_1_SPILL *
+ sizeof(union rx_tx_desc));
+ sc->class_2_spill = nlna_config_spill(sc->base,
+ R_CLASS2_SPILL_MEM_START_0,
+ R_CLASS2_SPILL_MEM_START_1,
+ R_CLASS2_SPILL_MEM_SIZE,
+ MAX_CLASS_2_SPILL *
+ sizeof(union rx_tx_desc));
+ sc->class_3_spill = nlna_config_spill(sc->base,
+ R_CLASS3_SPILL_MEM_START_0,
+ R_CLASS3_SPILL_MEM_START_1,
+ R_CLASS3_SPILL_MEM_SIZE,
+ MAX_CLASS_3_SPILL *
+ sizeof(union rx_tx_desc));
+}
+
+/* Set the CPU buckets that receive packets from the NA class FIFOs. */
+static void
+nlna_config_pde(struct nlna_softc *sc)
+{
+ uint64_t bucket_map;
+ uint32_t cpumask;
+ int i, cpu, bucket;
+
+ cpumask = 0x1;
+#ifdef SMP
+ /*
+ * rge may be called before SMP start in a BOOTP/NFSROOT
+ * setup. we will distribute packets to other cpus only when
+ * the SMP is started.
+ */
+ if (smp_started)
+ cpumask = xlr_hw_thread_mask;
+#endif
+
+ bucket_map = 0;
+ for (i = 0; i < 32; i++) {
+ if (cpumask & (1 << i)) {
+ cpu = i;
+ bucket = ((cpu >> 2) << 3);
+ bucket_map |= (1ULL << bucket);
+ }
+ }
+ NLGE_WRITE(sc->base, R_PDE_CLASS_0, (bucket_map & 0xffffffff));
+ NLGE_WRITE(sc->base, R_PDE_CLASS_0 + 1, ((bucket_map >> 32) & 0xffffffff));
+
+ NLGE_WRITE(sc->base, R_PDE_CLASS_1, (bucket_map & 0xffffffff));
+ NLGE_WRITE(sc->base, R_PDE_CLASS_1 + 1, ((bucket_map >> 32) & 0xffffffff));
+
+ NLGE_WRITE(sc->base, R_PDE_CLASS_2, (bucket_map & 0xffffffff));
+ NLGE_WRITE(sc->base, R_PDE_CLASS_2 + 1, ((bucket_map >> 32) & 0xffffffff));
+
+ NLGE_WRITE(sc->base, R_PDE_CLASS_3, (bucket_map & 0xffffffff));
+ NLGE_WRITE(sc->base, R_PDE_CLASS_3 + 1, ((bucket_map >> 32) & 0xffffffff));
+}
+
+static void
+nlna_smp_update_pde(void *dummy __unused)
+{
+ device_t iodi_dev;
+ struct nlna_softc *na_sc[XLR_MAX_NLNA];
+ int i;
+
+ printf("Updating packet distribution for SMP\n");
+
+ iodi_dev = devclass_get_device(devclass_find("iodi"), 0);
+ nlna_get_all_softc(iodi_dev, na_sc, XLR_MAX_NLNA);
+
+ for (i = 0; i < XLR_MAX_NLNA; i++) {
+ if (na_sc[i] == NULL)
+ continue;
+ nlna_disable_ports(na_sc[i]);
+ nlna_config_pde(na_sc[i]);
+ nlna_enable_ports(na_sc[i]);
+ }
+}
+
+SYSINIT(nlna_smp_update_pde, SI_SUB_SMP, SI_ORDER_ANY, nlna_smp_update_pde,
+ NULL);
+
+static void
+nlna_config_parser(struct nlna_softc *sc)
+{
+ /*
+ * Mark it as no classification. The parser extract is gauranteed to
+ * be zero with no classfication
+ */
+ NLGE_WRITE(sc->base, R_L2TYPE_0, 0x00);
+ NLGE_WRITE(sc->base, R_L2TYPE_0, 0x01);
+
+ /* configure the parser : L2 Type is configured in the bootloader */
+ /* extract IP: src, dest protocol */
+ NLGE_WRITE(sc->base, R_L3CTABLE,
+ (9 << 20) | (1 << 19) | (1 << 18) | (0x01 << 16) |
+ (0x0800 << 0));
+ NLGE_WRITE(sc->base, R_L3CTABLE + 1,
+ (12 << 25) | (4 << 21) | (16 << 14) | (4 << 10));
+}
+
+static void
+nlna_config_classifier(struct nlna_softc *sc)
+{
+ int i;
+
+ if (sc->mac_type == XLR_XGMII) { /* TBD: XGMII init sequence */
+ /* xgmac translation table doesn't have sane values on reset */
+ for (i = 0; i < 64; i++)
+ NLGE_WRITE(sc->base, R_TRANSLATETABLE + i, 0x0);
+
+ /*
+ * use upper 7 bits of the parser extract to index the
+ * translate table
+ */
+ NLGE_WRITE(sc->base, R_PARSERCONFIGREG, 0x0);
+ }
+}
+
+/*
+ * Complete a bunch of h/w register initializations that are common for all the
+ * ports controlled by a NA.
+ */
+static void
+nlna_config_common(struct nlna_softc *sc)
+{
+ struct xlr_gmac_block_t *block_info;
+ struct stn_cc *gmac_cc_config;
+ int i, id;
+
+ block_info = device_get_ivars(sc->nlna_dev);
+
+ id = device_get_unit(sc->nlna_dev);
+ gmac_cc_config = block_info->credit_config;
+ for (i = 0; i < MAX_NUM_MSGRNG_STN_CC; i++) {
+ NLGE_WRITE(sc->base, R_CC_CPU0_0 + i,
+ gmac_cc_config->counters[i >> 3][i & 0x07]);
+ }
+
+ NLGE_WRITE(sc->base, R_MSG_TX_THRESHOLD, 3);
+
+ NLGE_WRITE(sc->base, R_DMACR0, 0xffffffff);
+ NLGE_WRITE(sc->base, R_DMACR1, 0xffffffff);
+ NLGE_WRITE(sc->base, R_DMACR2, 0xffffffff);
+ NLGE_WRITE(sc->base, R_DMACR3, 0xffffffff);
+ NLGE_WRITE(sc->base, R_FREEQCARVE, 0);
+
+ nlna_media_specific_config(sc);
+}
+
+static void
+nlna_media_specific_config(struct nlna_softc *sc)
+{
+ struct bucket_size *bucket_sizes;
+
+ bucket_sizes = xlr_board_info.bucket_sizes;
+ switch (sc->mac_type) {
+ case XLR_RGMII:
+ case XLR_SGMII:
+ case XLR_XAUI:
+ NLGE_WRITE(sc->base, R_GMAC_JFR0_BUCKET_SIZE,
+ bucket_sizes->bucket[MSGRNG_STNID_GMACJFR_0]);
+ NLGE_WRITE(sc->base, R_GMAC_RFR0_BUCKET_SIZE,
+ bucket_sizes->bucket[MSGRNG_STNID_GMACRFR_0]);
+ NLGE_WRITE(sc->base, R_GMAC_JFR1_BUCKET_SIZE,
+ bucket_sizes->bucket[MSGRNG_STNID_GMACJFR_1]);
+ NLGE_WRITE(sc->base, R_GMAC_RFR1_BUCKET_SIZE,
+ bucket_sizes->bucket[MSGRNG_STNID_GMACRFR_1]);
+
+ if (sc->mac_type == XLR_XAUI) {
+ NLGE_WRITE(sc->base, R_TXDATAFIFO0, (224 << 16));
+ }
+ break;
+
+ case XLR_XGMII:
+ NLGE_WRITE(sc->base, R_XGS_RFR_BUCKET_SIZE,
+ bucket_sizes->bucket[sc->rfrbucket]);
+
+ default:
+ break;
+ }
+}
+
+static void
+nlna_reset_ports(struct nlna_softc *sc, struct xlr_gmac_block_t *blk)
+{
+ xlr_reg_t *addr;
+ int i;
+ uint32_t rx_ctrl;
+
+ /* Refer Section 13.9.3 in the PRM for the reset sequence */
+
+ for (i = 0; i < sc->num_ports; i++) {
+ uint32_t base = (uint32_t)DEFAULT_XLR_IO_BASE;
+
+ base += blk->gmac_port[i].base_addr;
+ addr = (xlr_reg_t *) base;
+
+ /* 1. Reset RxEnable in MAC_CONFIG */
+ switch (sc->mac_type) {
+ case XLR_RGMII:
+ case XLR_SGMII:
+ NLGE_UPDATE(addr, R_MAC_CONFIG_1, 0,
+ (1 << O_MAC_CONFIG_1__rxen));
+ break;
+ case XLR_XAUI:
+ case XLR_XGMII:
+ NLGE_UPDATE(addr, R_RX_CONTROL, 0,
+ (1 << O_RX_CONTROL__RxEnable));
+ break;
+ default:
+ printf("Error: Unsupported port_type=%d\n",
+ sc->mac_type);
+ }
+
+ /* 1.1 Wait for RxControl.RxHalt to be set */
+ do {
+ rx_ctrl = NLGE_READ(addr, R_RX_CONTROL);
+ } while (!(rx_ctrl & 0x2));
+
+ /* 2. Set the soft reset bit in RxControl */
+ NLGE_UPDATE(addr, R_RX_CONTROL, (1 << O_RX_CONTROL__SoftReset),
+ (1 << O_RX_CONTROL__SoftReset));
+
+ /* 2.1 Wait for RxControl.SoftResetDone to be set */
+ do {
+ rx_ctrl = NLGE_READ(addr, R_RX_CONTROL);
+ } while (!(rx_ctrl & 0x8));
+
+ /* 3. Clear the soft reset bit in RxControl */
+ NLGE_UPDATE(addr, R_RX_CONTROL, 0,
+ (1 << O_RX_CONTROL__SoftReset));
+
+ /* Turn off tx/rx on the port. */
+ NLGE_UPDATE(addr, R_RX_CONTROL, 0,
+ (1 << O_RX_CONTROL__RxEnable));
+ NLGE_UPDATE(addr, R_TX_CONTROL, 0,
+ (1 << O_TX_CONTROL__TxEnable));
+ }
+}
+
+static void
+nlna_disable_ports(struct nlna_softc *sc)
+{
+ struct xlr_gmac_block_t *blk;
+ xlr_reg_t *addr;
+ int i;
+
+ blk = device_get_ivars(sc->nlna_dev);
+ for (i = 0; i < sc->num_ports; i++) {
+ uint32_t base = (uint32_t)DEFAULT_XLR_IO_BASE;
+
+ base += blk->gmac_port[i].base_addr;
+ addr = (xlr_reg_t *) base;
+ nlge_port_disable(i, addr, blk->gmac_port[i].type);
+ }
+}
+
+static void
+nlna_enable_ports(struct nlna_softc *sc)
+{
+ device_t nlge_dev, *devlist;
+ struct nlge_softc *port_sc;
+ int i, numdevs;
+
+ device_get_children(sc->nlna_dev, &devlist, &numdevs);
+ for (i = 0; i < numdevs; i++) {
+ nlge_dev = devlist[i];
+ if (nlge_dev == NULL)
+ continue;
+ port_sc = device_get_softc(nlge_dev);
+ if (port_sc->nlge_if->if_drv_flags & IFF_DRV_RUNNING)
+ nlge_port_enable(port_sc);
+ }
+ free(devlist, M_TEMP);
+}
+
+static void
+nlna_get_all_softc(device_t iodi_dev, struct nlna_softc **sc_vec,
+ uint32_t vec_sz)
+{
+ device_t na_dev;
+ int i;
+
+ for (i = 0; i < vec_sz; i++) {
+ sc_vec[i] = NULL;
+ na_dev = device_find_child(iodi_dev, "nlna", i);
+ if (na_dev != NULL)
+ sc_vec[i] = device_get_softc(na_dev);
+ }
+}
+
+static void
+nlge_port_disable(int id, xlr_reg_t *base, int port_type)
+{
+ uint32_t rd;
+
+ NLGE_UPDATE(base, R_RX_CONTROL, 0x0, 1 << O_RX_CONTROL__RxEnable);
+ do {
+ rd = NLGE_READ(base, R_RX_CONTROL);
+ } while (!(rd & (1 << O_RX_CONTROL__RxHalt)));
+
+ NLGE_UPDATE(base, R_TX_CONTROL, 0, 1 << O_TX_CONTROL__TxEnable);
+ do {
+ rd = NLGE_READ(base, R_TX_CONTROL);
+ } while (!(rd & (1 << O_TX_CONTROL__TxIdle)));
+
+ switch (port_type) {
+ case XLR_RGMII:
+ case XLR_SGMII:
+ NLGE_UPDATE(base, R_MAC_CONFIG_1, 0,
+ ((1 << O_MAC_CONFIG_1__rxen) |
+ (1 << O_MAC_CONFIG_1__txen)));
+ break;
+ case XLR_XGMII:
+ case XLR_XAUI:
+ NLGE_UPDATE(base, R_XGMAC_CONFIG_1, 0,
+ ((1 << O_XGMAC_CONFIG_1__hsttfen) |
+ (1 << O_XGMAC_CONFIG_1__hstrfen)));
+ break;
+ default:
+ panic("Unknown MAC type on port %d\n", id);
+ }
+}
+
+static void
+nlge_port_enable(struct nlge_softc *sc)
+{
+ struct xlr_gmac_port *self;
+ xlr_reg_t *base;
+
+ base = sc->base;
+ self = device_get_ivars(sc->nlge_dev);
+ if (xlr_board_info.is_xls && sc->port_type == XLR_RGMII)
+ NLGE_UPDATE(base, R_RX_CONTROL, (1 << O_RX_CONTROL__RGMII),
+ (1 << O_RX_CONTROL__RGMII));
+
+ NLGE_UPDATE(base, R_RX_CONTROL, (1 << O_RX_CONTROL__RxEnable),
+ (1 << O_RX_CONTROL__RxEnable));
+ NLGE_UPDATE(base, R_TX_CONTROL,
+ (1 << O_TX_CONTROL__TxEnable | RGE_TX_THRESHOLD_BYTES),
+ (1 << O_TX_CONTROL__TxEnable | 0x3fff));
+ switch (sc->port_type) {
+ case XLR_RGMII:
+ case XLR_SGMII:
+ NLGE_UPDATE(base, R_MAC_CONFIG_1,
+ ((1 << O_MAC_CONFIG_1__rxen) | (1 << O_MAC_CONFIG_1__txen)),
+ ((1 << O_MAC_CONFIG_1__rxen) | (1 << O_MAC_CONFIG_1__txen)));
+ break;
+ case XLR_XGMII:
+ case XLR_XAUI:
+ NLGE_UPDATE(base, R_XGMAC_CONFIG_1,
+ ((1 << O_XGMAC_CONFIG_1__hsttfen) | (1 << O_XGMAC_CONFIG_1__hstrfen)),
+ ((1 << O_XGMAC_CONFIG_1__hsttfen) | (1 << O_XGMAC_CONFIG_1__hstrfen)));
+ break;
+ default:
+ panic("Unknown MAC type on port %d\n", sc->id);
+ }
+}
+
+static void
+nlge_sgmii_init(struct nlge_softc *sc)
+{
+ xlr_reg_t *mmio_gpio;
+ int i;
+ int phy;
+
+ if (sc->port_type != XLR_SGMII)
+ return;
+
+ nlge_mii_write_internal(sc->serdes_addr, 26, 0, 0x6DB0);
+ nlge_mii_write_internal(sc->serdes_addr, 26, 1, 0xFFFF);
+ nlge_mii_write_internal(sc->serdes_addr, 26, 2, 0xB6D0);
+ nlge_mii_write_internal(sc->serdes_addr, 26, 3, 0x00FF);
+ nlge_mii_write_internal(sc->serdes_addr, 26, 4, 0x0000);
+ nlge_mii_write_internal(sc->serdes_addr, 26, 5, 0x0000);
+ nlge_mii_write_internal(sc->serdes_addr, 26, 6, 0x0005);
+ nlge_mii_write_internal(sc->serdes_addr, 26, 7, 0x0001);
+ nlge_mii_write_internal(sc->serdes_addr, 26, 8, 0x0000);
+ nlge_mii_write_internal(sc->serdes_addr, 26, 9, 0x0000);
+ nlge_mii_write_internal(sc->serdes_addr, 26,10, 0x0000);
+
+ for(i=0;i<10000000;i++){} /* delay */
+ /* program GPIO values for serdes init parameters */
+ mmio_gpio = (xlr_reg_t *) (DEFAULT_XLR_IO_BASE + XLR_IO_GPIO_OFFSET);
+ mmio_gpio[0x20] = 0x7e6802;
+ mmio_gpio[0x10] = 0x7104;
+ for(i=0;i<100000000;i++){}
+
+ /* enable autoneg - more magic */
+ phy = sc->phy_addr % 4 + 27;
+ nlge_mii_write_internal(sc->pcs_addr, phy, 0, 0x1000);
+ DELAY(100000);
+ nlge_mii_write_internal(sc->pcs_addr, phy, 0, 0x0200);
+ DELAY(100000);
+}
+
+static void
+nlge_intr(void *arg)
+{
+ struct nlge_port_set *pset;
+ struct nlge_softc *sc;
+ struct nlge_softc *port_sc;
+ xlr_reg_t *base;
+ uint32_t intreg;
+ uint32_t intr_status;
+ int i;
+
+ sc = arg;
+ if (sc == NULL) {
+ printf("warning: No port registered for interrupt\n");
+ return;
+ }
+ base = sc->base;
+
+ intreg = NLGE_READ(base, R_INTREG);
+ if (intreg & (1 << O_INTREG__MDInt)) {
+ pset = sc->mdio_pset;
+ if (pset == NULL) {
+ printf("warning: No ports for MDIO interrupt\n");
+ return;
+ }
+ for (i = 0; i < pset->vec_sz; i++) {
+ port_sc = pset->port_vec[i];
+
+ if (port_sc == NULL)
+ continue;
+
+ /* Ack phy interrupt - clear on read*/
+ intr_status = nlge_mii_read_internal(port_sc->mii_base,
+ port_sc->phy_addr, 26);
+ PDEBUG("Phy_%d: int_status=0x%08x\n", port_sc->phy_addr,
+ intr_status);
+
+ if (!(intr_status & 0x8000)) {
+ /* no interrupt for this port */
+ continue;
+ }
+
+ if (intr_status & 0x2410) {
+ /* update link status for port */
+ nlge_gmac_config_speed(port_sc, 0);
+ } else {
+ printf("%s: Unsupported phy interrupt"
+ " (0x%08x)\n",
+ device_get_nameunit(port_sc->nlge_dev),
+ intr_status);
+ }
+ }
+ }
+
+ /* Clear the NA interrupt */
+ xlr_write_reg(base, R_INTREG, 0xffffffff);
+
+ return;
+}
+
+static int
+nlge_irq_init(struct nlge_softc *sc)
+{
+ struct resource irq_res;
+ struct nlna_softc *na_sc;
+ struct xlr_gmac_block_t *block_info;
+ device_t na_dev;
+ int ret;
+ int irq_num;
+
+ na_dev = device_get_parent(sc->nlge_dev);
+ block_info = device_get_ivars(na_dev);
+
+ irq_num = block_info->baseirq + sc->instance;
+ irq_res.__r_i = (struct resource_i *)(intptr_t) (irq_num);
+ ret = bus_setup_intr(sc->nlge_dev, &irq_res, (INTR_FAST |
+ INTR_TYPE_NET | INTR_MPSAFE), NULL, nlge_intr, sc, NULL);
+ if (ret) {
+ nlge_detach(sc->nlge_dev);
+ device_printf(sc->nlge_dev, "couldn't set up irq: error=%d\n",
+ ret);
+ return (ENXIO);
+ }
+ PDEBUG("Setup intr for dev=%s, irq=%d\n",
+ device_get_nameunit(sc->nlge_dev), irq_num);
+
+ if (sc->instance == 0) {
+ na_sc = device_get_softc(na_dev);
+ sc->mdio_pset = &na_sc->mdio_set;
+ }
+ return (0);
+}
+
+static void
+nlge_irq_fini(struct nlge_softc *sc)
+{
+}
+
+static void
+nlge_hw_init(struct nlge_softc *sc)
+{
+ struct xlr_gmac_port *port_info;
+ xlr_reg_t *base;
+
+ base = sc->base;
+ port_info = device_get_ivars(sc->nlge_dev);
+ sc->tx_bucket_id = port_info->tx_bucket_id;
+
+ /* each packet buffer is 1536 bytes */
+ NLGE_WRITE(base, R_DESC_PACK_CTRL,
+ (1 << O_DESC_PACK_CTRL__MaxEntry) |
+ (MAX_FRAME_SIZE << O_DESC_PACK_CTRL__RegularSize));
+ NLGE_WRITE(base, R_STATCTRL, ((1 << O_STATCTRL__Sten) |
+ (1 << O_STATCTRL__ClrCnt)));
+ NLGE_WRITE(base, R_L2ALLOCCTRL, 0xffffffff);
+ NLGE_WRITE(base, R_INTMASK, 0);
+ nlge_set_mac_addr(sc);
+ nlge_media_specific_init(sc);
+}
+
+static void
+nlge_sc_init(struct nlge_softc *sc, device_t dev,
+ struct xlr_gmac_port *port_info)
+{
+ memset(sc, 0, sizeof(*sc));
+ sc->nlge_dev = dev;
+ sc->id = device_get_unit(dev);
+ nlge_set_port_attribs(sc, port_info);
+}
+
+static void
+nlge_media_specific_init(struct nlge_softc *sc)
+{
+ struct mii_data *media;
+ struct bucket_size *bucket_sizes;
+
+ bucket_sizes = xlr_board_info.bucket_sizes;
+ switch (sc->port_type) {
+ case XLR_RGMII:
+ case XLR_SGMII:
+ case XLR_XAUI:
+ NLGE_UPDATE(sc->base, R_DESC_PACK_CTRL,
+ (BYTE_OFFSET << O_DESC_PACK_CTRL__ByteOffset),
+ (W_DESC_PACK_CTRL__ByteOffset <<
+ O_DESC_PACK_CTRL__ByteOffset));
+ NLGE_WRITE(sc->base, R_GMAC_TX0_BUCKET_SIZE + sc->instance,
+ bucket_sizes->bucket[sc->tx_bucket_id]);
+ if (sc->port_type != XLR_XAUI) {
+ nlge_gmac_config_speed(sc, 1);
+ if (sc->mii_bus) {
+ media = (struct mii_data *)device_get_softc(
+ sc->mii_bus);
+ }
+ }
+ break;
+
+ case XLR_XGMII:
+ NLGE_WRITE(sc->base, R_BYTEOFFSET0, 0x2);
+ NLGE_WRITE(sc->base, R_XGMACPADCALIBRATION, 0x30);
+ NLGE_WRITE(sc->base, R_XGS_TX0_BUCKET_SIZE,
+ bucket_sizes->bucket[sc->tx_bucket_id]);
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ * Read the MAC address from the XLR boot registers. All port addresses
+ * are identical except for the lowest octet.
+ */
+static void
+nlge_read_mac_addr(struct nlge_softc *sc)
+{
+ int i, j;
+
+ for (i = 0, j = 40; i < ETHER_ADDR_LEN && j >= 0; i++, j-= 8)
+ sc->dev_addr[i] = (xlr_boot1_info.mac_addr >> j) & 0xff;
+
+ sc->dev_addr[i - 1] += sc->id; /* last octet is port-specific */
+}
+
+/*
+ * Write the MAC address to the XLR MAC port. Also, set the address
+ * masks and MAC filter configuration.
+ */
+static void
+nlge_set_mac_addr(struct nlge_softc *sc)
+{
+ NLGE_WRITE(sc->base, R_MAC_ADDR0,
+ ((sc->dev_addr[5] << 24) | (sc->dev_addr[4] << 16) |
+ (sc->dev_addr[3] << 8) | (sc->dev_addr[2])));
+ NLGE_WRITE(sc->base, R_MAC_ADDR0 + 1,
+ ((sc->dev_addr[1] << 24) | (sc-> dev_addr[0] << 16)));
+
+ NLGE_WRITE(sc->base, R_MAC_ADDR_MASK2, 0xffffffff);
+ NLGE_WRITE(sc->base, R_MAC_ADDR_MASK2 + 1, 0xffffffff);
+ NLGE_WRITE(sc->base, R_MAC_ADDR_MASK3, 0xffffffff);
+ NLGE_WRITE(sc->base, R_MAC_ADDR_MASK3 + 1, 0xffffffff);
+
+ NLGE_WRITE(sc->base, R_MAC_FILTER_CONFIG,
+ (1 << O_MAC_FILTER_CONFIG__BROADCAST_EN) |
+ (1 << O_MAC_FILTER_CONFIG__ALL_MCAST_EN) |
+ (1 << O_MAC_FILTER_CONFIG__MAC_ADDR0_VALID));
+
+ if (sc->port_type == XLR_RGMII || sc->port_type == XLR_SGMII) {
+ NLGE_UPDATE(sc->base, R_IPG_IFG, MAC_B2B_IPG, 0x7f);
+ }
+}
+
+static int
+nlge_if_init(struct nlge_softc *sc)
+{
+ struct ifnet *ifp;
+ device_t dev;
+ int error;
+
+ error = 0;
+ dev = sc->nlge_dev;
+ NLGE_LOCK_INIT(sc, device_get_nameunit(dev));
+
+ ifp = sc->nlge_if = if_alloc(IFT_ETHER);
+ if (ifp == NULL) {
+ device_printf(dev, "can not if_alloc()\n");
+ error = ENOSPC;
+ goto fail;
+ }
+ ifp->if_softc = sc;
+ if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_capabilities = IFCAP_TXCSUM | IFCAP_VLAN_HWTAGGING;
+ ifp->if_capenable = ifp->if_capabilities;
+ ifp->if_ioctl = nlge_ioctl;
+ ifp->if_start = nlge_start;
+ ifp->if_init = nlge_init;
+ ifp->if_hwassist = 0;
+ ifp->if_snd.ifq_drv_maxlen = RGE_TX_Q_SIZE;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
+ IFQ_SET_READY(&ifp->if_snd);
+
+ ifmedia_init(&sc->nlge_mii.mii_media, 0, nlge_mediachange,
+ nlge_mediastatus);
+ ifmedia_add(&sc->nlge_mii.mii_media, IFM_ETHER | IFM_AUTO, 0, NULL);
+ ifmedia_set(&sc->nlge_mii.mii_media, IFM_ETHER | IFM_AUTO);
+ sc->nlge_mii.mii_media.ifm_media = sc->nlge_mii.mii_media.ifm_cur->ifm_media;
+ nlge_read_mac_addr(sc);
+
+ ether_ifattach(ifp, sc->dev_addr);
+
+fail:
+ return (error);
+}
+
+static void
+nlge_mii_init(device_t dev, struct nlge_softc *sc)
+{
+ int error;
+
+ if (sc->port_type != XLR_XAUI && sc->port_type != XLR_XGMII) {
+ NLGE_WRITE(sc->mii_base, R_MII_MGMT_CONFIG, 0x07);
+ }
+ error = mii_phy_probe(dev, &sc->mii_bus, nlge_mediachange, nlge_mediastatus);
+ if (error) {
+ device_printf(dev, "no PHY device found\n");
+ sc->mii_bus = NULL;
+ }
+ if (sc->mii_bus != NULL) {
+ /*
+ * Enable all MDIO interrupts in the phy. RX_ER bit seems to get
+ * set about every 1 sec in GigE mode, ignore it for now...
+ */
+ nlge_mii_write_internal(sc->mii_base, sc->phy_addr, 25,
+ 0xfffffffe);
+ }
+}
+
+/*
+ * Read a PHY register.
+ *
+ * Input parameters:
+ * mii_base - Base address of MII
+ * phyaddr - PHY's address
+ * regidx = index of register to read
+ *
+ * Return value:
+ * value read, or 0 if an error occurred.
+ */
+
+static int
+nlge_mii_read_internal(xlr_reg_t *mii_base, int phyaddr, int regidx)
+{
+ int i, val;
+
+ /* setup the phy reg to be used */
+ NLGE_WRITE(mii_base, R_MII_MGMT_ADDRESS,
+ (phyaddr << 8) | (regidx << 0));
+ /* Issue the read command */
+ NLGE_WRITE(mii_base, R_MII_MGMT_COMMAND,
+ (1 << O_MII_MGMT_COMMAND__rstat));
+
+ /* poll for the read cycle to complete */
+ for (i = 0; i < PHY_STATUS_RETRIES; i++) {
+ if (NLGE_READ(mii_base, R_MII_MGMT_INDICATORS) == 0)
+ break;
+ }
+
+ /* clear the read cycle */
+ NLGE_WRITE(mii_base, R_MII_MGMT_COMMAND, 0);
+
+ if (i == PHY_STATUS_RETRIES) {
+ return (0xffffffff);
+ }
+
+ val = NLGE_READ(mii_base, R_MII_MGMT_STATUS);
+
+ return (val);
+}
+
+/*
+ * Write a value to a PHY register.
+ *
+ * Input parameters:
+ * mii_base - Base address of MII
+ * phyaddr - PHY to use
+ * regidx - register within the PHY
+ * regval - data to write to register
+ *
+ * Return value:
+ * nothing
+ */
+static void
+nlge_mii_write_internal(xlr_reg_t *mii_base, int phyaddr, int regidx,
+ int regval)
+{
+ int i;
+
+ NLGE_WRITE(mii_base, R_MII_MGMT_ADDRESS,
+ (phyaddr << 8) | (regidx << 0));
+
+ /* Write the data which starts the write cycle */
+ NLGE_WRITE(mii_base, R_MII_MGMT_WRITE_DATA, regval);
+
+ /* poll for the write cycle to complete */
+ for (i = 0; i < PHY_STATUS_RETRIES; i++) {
+ if (NLGE_READ(mii_base, R_MII_MGMT_INDICATORS) == 0)
+ break;
+ }
+}
+
+/*
+ * Function to optimize the use of p2d descriptors for the given PDU.
+ * As it is on the fast-path (called during packet transmission), it
+ * described in more detail than the initialization functions.
+ *
+ * Input: mbuf chain (MC), pointer to fmn message
+ * Input constraints: None
+ * Output: FMN message to transmit the data in MC
+ * Return values: 0 - success
+ * 1 - MC cannot be handled (see Limitations below)
+ * 2 - MC cannot be handled presently (maybe worth re-trying)
+ * Other output: Number of entries filled in the FMN message
+ *
+ * Output structure/constraints:
+ * 1. Max 3 p2d's + 1 zero-len (ZL) p2d with virtual address of MC.
+ * 2. 3 p2d's + 1 p2p with max 14 p2d's (ZL p2d not required in this case).
+ * 3. Each p2d points to physically contiguous chunk of data (subject to
+ * entire MC requiring max 17 p2d's).
+ * Limitations:
+ * 1. MC's that require more than 17 p2d's are not handled.
+ * Benefits: MC's that require <= 3 p2d's avoid the overhead of allocating
+ * the p2p structure. Small packets (which typically give low
+ * performance) are expected to have a small MC that takes
+ * advantage of this.
+ */
+static int
+prepare_fmn_message(struct nlge_softc *sc, struct msgrng_msg *fmn_msg,
+ uint32_t *n_entries, struct mbuf *mbuf_chain, uint64_t fb_stn_id,
+ struct nlge_tx_desc **tx_desc)
+{
+ struct mbuf *m;
+ struct nlge_tx_desc *p2p;
+ uint64_t *cur_p2d;
+ vm_offset_t buf;
+ vm_paddr_t paddr;
+ int msg_sz, p2p_sz, is_p2p;
+ int len, frag_sz;
+ /* Num entries per FMN msg is 4 for XLR/XLS */
+ const int FMN_SZ = sizeof(*fmn_msg) / sizeof(uint64_t);
+
+ msg_sz = p2p_sz = is_p2p = 0;
+ p2p = NULL;
+ cur_p2d = &fmn_msg->msg0;
+
+ for (m = mbuf_chain; m != NULL; m = m->m_next) {
+ buf = (vm_offset_t) m->m_data;
+ len = m->m_len;
+
+ while (len) {
+ if (msg_sz == (FMN_SZ - 1)) {
+ p2p = uma_zalloc(nl_tx_desc_zone, M_NOWAIT);
+ if (p2p == NULL)
+ return 2;
+ /*
+ * As we currently use xlr_paddr_lw on a 32-bit
+ * OS, both the pointers are laid out in one
+ * 64-bit location - this makes it easy to
+ * retrieve the pointers when processing the
+ * tx free-back descriptor.
+ */
+ p2p->frag[XLR_MAX_TX_FRAGS] =
+ (((uint64_t) (vm_offset_t) p2p) << 32) |
+ ((vm_offset_t) mbuf_chain);
+ cur_p2d = &p2p->frag[0];
+ is_p2p = 1;
+ } else if (msg_sz == (FMN_SZ - 1 + XLR_MAX_TX_FRAGS)) {
+ uma_zfree(nl_tx_desc_zone, p2p);
+ return 1;
+ }
+ paddr = vtophys(buf);
+ frag_sz = PAGE_SIZE - (buf & PAGE_MASK) ;
+ if (len < frag_sz)
+ frag_sz = len;
+ *cur_p2d++ = (127ULL << 54) | ((uint64_t)frag_sz << 40)
+ | paddr;
+ msg_sz++;
+ if (is_p2p)
+ p2p_sz++;
+ len -= frag_sz;
+ buf += frag_sz;
+ }
+ }
+
+ if (msg_sz > 0) {
+ cur_p2d[-1] |= (1ULL << 63); /* set eop in most-recent p2d */
+ } else {
+ printf("Zero-length mbuf chain ??\n");
+ *n_entries = msg_sz ;
+ return 0;
+ }
+
+ *tx_desc = p2p;
+
+ if (is_p2p) {
+ paddr = vtophys(p2p);
+ fmn_msg->msg3 = (1ULL << 63) | (1ULL << 62) |
+ ((uint64_t)fb_stn_id << 54) |
+ ((uint64_t)(p2p_sz * 8) << 40) | paddr;
+ *n_entries = FMN_SZ;
+ } else {
+ /* zero-len p2d */
+ *cur_p2d = (1ULL << 63) | ((uint64_t)fb_stn_id << 54) |
+ (vm_offset_t) mbuf_chain;
+ *n_entries = msg_sz + 1;
+ }
+
+ return (0);
+}
+
+static int
+send_fmn_msg_tx(struct nlge_softc *sc, struct msgrng_msg *msg,
+ uint32_t n_entries)
+{
+ unsigned long mflags;
+ int ret;
+
+ mflags = 0;
+ msgrng_access_enable(mflags);
+ ret = message_send_retry(n_entries, MSGRNG_CODE_MAC, sc->tx_bucket_id,
+ msg);
+ msgrng_access_disable(mflags);
+ return (!ret);
+}
+
+static void
+release_mbuf(uint64_t phy_addr)
+{
+ struct mbuf *m;
+
+ m = (struct mbuf *)((uint32_t) phy_addr);
+ m_freem(m);
+}
+
+static void
+release_tx_desc(struct msgrng_msg *msg, int rel_buf)
+{
+ vm_paddr_t paddr;
+ uint64_t temp;
+ struct nlge_tx_desc *tx_desc;
+ struct mbuf *m;
+ uint32_t sr;
+
+ paddr = msg->msg0 & 0xffffffffffULL;
+ paddr += (XLR_MAX_TX_FRAGS * sizeof(uint64_t));
+ sr = xlr_enable_kx();
+ temp = xlr_paddr_lw(paddr);
+ mips_wr_status(sr);
+ tx_desc = (struct nlge_tx_desc*)((intptr_t) temp);
+
+ if (rel_buf) {
+ paddr += sizeof(void *);
+ sr = xlr_enable_kx();
+ temp = xlr_paddr_lw(paddr);
+ mips_wr_status(sr);
+ m = (struct mbuf *)((intptr_t) temp);
+ m_freem(m);
+ }
+
+ uma_zfree(nl_tx_desc_zone, tx_desc);
+}
+
+static struct mbuf *
+get_mbuf(void)
+{
+ struct mbuf *m_new;
+
+ if ((m_new = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR)) == NULL)
+ return NULL;
+ m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
+ return (m_new);
+}
+
+static void *
+get_buf(void)
+{
+ struct mbuf *m_new;
+ vm_paddr_t temp1, temp2;
+ unsigned int *md;
+
+ m_new = get_mbuf();
+ if (m_new == NULL)
+ return m_new;
+
+ m_adj(m_new, XLR_CACHELINE_SIZE - ((unsigned int)m_new->m_data & 0x1f));
+ md = (unsigned int *)m_new->m_data;
+ md[0] = (unsigned int)m_new; /* Back Ptr */
+ md[1] = 0xf00bad;
+ m_adj(m_new, XLR_CACHELINE_SIZE);
+
+ temp1 = vtophys((vm_offset_t) m_new->m_data);
+ temp2 = vtophys((vm_offset_t) m_new->m_data + 1536);
+ if ((temp1 + 1536) != temp2)
+ panic("ALLOCED BUFFER IS NOT CONTIGUOUS\n");
+
+ return ((void *)m_new->m_data);
+}
+
+static int
+nlge_gmac_config_speed(struct nlge_softc *sc, int quick)
+{
+ struct mii_data *md;
+ xlr_reg_t *mmio;
+ int bmsr, n_tries, max_tries;
+ int core_ctl[] = { 0x2, 0x1, 0x0, 0x1 };
+ int sgmii_speed[] = { SGMII_SPEED_10,
+ SGMII_SPEED_100,
+ SGMII_SPEED_1000,
+ SGMII_SPEED_100 }; /* default to 100Mbps */
+ char *speed_str[] = { "10",
+ "100",
+ "1000",
+ "unknown, defaulting to 100" };
+ int link_state = LINK_STATE_DOWN;
+
+ if (sc->port_type == XLR_XAUI || sc->port_type == XLR_XGMII)
+ return 0;
+
+ md = NULL;
+ mmio = sc->base;
+ if (sc->mii_base != NULL) {
+ max_tries = (quick == 1) ? 100 : 4000;
+ bmsr = 0;
+ for (n_tries = 0; n_tries < max_tries; n_tries++) {
+ bmsr = nlge_mii_read_internal(sc->mii_base,
+ sc->phy_addr, MII_BMSR);
+ if ((bmsr & BMSR_ACOMP) && (bmsr & BMSR_LINK))
+ break; /* Auto-negotiation is complete
+ and link is up */
+ DELAY(1000);
+ }
+ bmsr &= BMSR_LINK;
+ sc->link = (bmsr == 0) ? xlr_mac_link_down : xlr_mac_link_up;
+ sc->speed = nlge_mii_read_internal(sc->mii_base, sc->phy_addr, 28);
+ sc->speed = (sc->speed >> 3) & 0x03;
+ if (sc->link == xlr_mac_link_up) {
+ link_state = LINK_STATE_UP;
+ nlge_sgmii_init(sc);
+ }
+ if (sc->mii_bus)
+ md = (struct mii_data *)device_get_softc(sc->mii_bus);
+ }
+
+ if (sc->port_type != XLR_RGMII)
+ NLGE_WRITE(mmio, R_INTERFACE_CONTROL, sgmii_speed[sc->speed]);
+ if (sc->speed == xlr_mac_speed_10 || sc->speed == xlr_mac_speed_100 ||
+ sc->speed == xlr_mac_speed_rsvd) {
+ NLGE_WRITE(mmio, R_MAC_CONFIG_2, 0x7117);
+ } else if (sc->speed == xlr_mac_speed_1000) {
+ NLGE_WRITE(mmio, R_MAC_CONFIG_2, 0x7217);
+ if (md != NULL) {
+ ifmedia_set(&md->mii_media, IFM_MAKEWORD(IFM_ETHER,
+ IFM_1000_T, IFM_FDX, md->mii_instance));
+ }
+ }
+ NLGE_WRITE(mmio, R_CORECONTROL, core_ctl[sc->speed]);
+ if_link_state_change(sc->nlge_if, link_state);
+ printf("%s: [%sMbps]\n", device_get_nameunit(sc->nlge_dev),
+ speed_str[sc->speed]);
+
+ return (0);
+}
+
+/*
+ * This function is called for each port that was added to the device tree
+ * and it initializes the following port attributes:
+ * - type
+ * - base (base address to access port-specific registers)
+ * - mii_base
+ * - phy_addr
+ */
+static void
+nlge_set_port_attribs(struct nlge_softc *sc,
+ struct xlr_gmac_port *port_info)
+{
+ sc->instance = port_info->instance % 4; /* TBD: will not work for SPI-4 */
+ sc->port_type = port_info->type;
+ sc->base = (xlr_reg_t *) (port_info->base_addr +
+ (uint32_t)DEFAULT_XLR_IO_BASE);
+ sc->mii_base = (xlr_reg_t *) (port_info->mii_addr +
+ (uint32_t)DEFAULT_XLR_IO_BASE);
+ if (port_info->pcs_addr != 0)
+ sc->pcs_addr = (xlr_reg_t *) (port_info->pcs_addr +
+ (uint32_t)DEFAULT_XLR_IO_BASE);
+ if (port_info->serdes_addr != 0)
+ sc->serdes_addr = (xlr_reg_t *) (port_info->serdes_addr +
+ (uint32_t)DEFAULT_XLR_IO_BASE);
+ sc->phy_addr = port_info->phy_addr;
+
+ PDEBUG("Port%d: base=%p, mii_base=%p, phy_addr=%d\n", sc->id, sc->base,
+ sc->mii_base, sc->phy_addr);
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* Debug dump functions */
+
+#ifdef DEBUG
+
+static void
+dump_reg(xlr_reg_t *base, uint32_t offset, char *name)
+{
+ int val;
+
+ val = NLGE_READ(base, offset);
+ printf("%-30s: 0x%8x 0x%8x\n", name, offset, val);
+}
+
+#define STRINGIFY(x) #x
+
+static void
+dump_na_registers(xlr_reg_t *base_addr, int port_id)
+{
+ PDEBUG("Register dump for NA (of port=%d)\n", port_id);
+ dump_reg(base_addr, R_PARSERCONFIGREG, STRINGIFY(R_PARSERCONFIGREG));
+ PDEBUG("Tx bucket sizes\n");
+ dump_reg(base_addr, R_GMAC_JFR0_BUCKET_SIZE,
+ STRINGIFY(R_GMAC_JFR0_BUCKET_SIZE));
+ dump_reg(base_addr, R_GMAC_RFR0_BUCKET_SIZE,
+ STRINGIFY(R_GMAC_RFR0_BUCKET_SIZE));
+ dump_reg(base_addr, R_GMAC_TX0_BUCKET_SIZE,
+ STRINGIFY(R_GMAC_TX0_BUCKET_SIZE));
+ dump_reg(base_addr, R_GMAC_TX1_BUCKET_SIZE,
+ STRINGIFY(R_GMAC_TX1_BUCKET_SIZE));
+ dump_reg(base_addr, R_GMAC_TX2_BUCKET_SIZE,
+ STRINGIFY(R_GMAC_TX2_BUCKET_SIZE));
+ dump_reg(base_addr, R_GMAC_TX3_BUCKET_SIZE,
+ STRINGIFY(R_GMAC_TX3_BUCKET_SIZE));
+ dump_reg(base_addr, R_GMAC_JFR1_BUCKET_SIZE,
+ STRINGIFY(R_GMAC_JFR1_BUCKET_SIZE));
+ dump_reg(base_addr, R_GMAC_RFR1_BUCKET_SIZE,
+ STRINGIFY(R_GMAC_RFR1_BUCKET_SIZE));
+ dump_reg(base_addr, R_TXDATAFIFO0, STRINGIFY(R_TXDATAFIFO0));
+ dump_reg(base_addr, R_TXDATAFIFO1, STRINGIFY(R_TXDATAFIFO1));
+}
+
+static void
+dump_gmac_registers(struct nlge_softc *sc)
+{
+ xlr_reg_t *base_addr = sc->base;
+ int port_id = sc->instance;
+
+ PDEBUG("Register dump for port=%d\n", port_id);
+ if (sc->port_type == XLR_RGMII || sc->port_type == XLR_SGMII) {
+ dump_reg(base_addr, R_MAC_CONFIG_1, STRINGIFY(R_MAC_CONFIG_1));
+ dump_reg(base_addr, R_MAC_CONFIG_2, STRINGIFY(R_MAC_CONFIG_2));
+ dump_reg(base_addr, R_IPG_IFG, STRINGIFY(R_IPG_IFG));
+ dump_reg(base_addr, R_HALF_DUPLEX, STRINGIFY(R_HALF_DUPLEX));
+ dump_reg(base_addr, R_MAXIMUM_FRAME_LENGTH,
+ STRINGIFY(R_MAXIMUM_FRAME_LENGTH));
+ dump_reg(base_addr, R_TEST, STRINGIFY(R_TEST));
+ dump_reg(base_addr, R_MII_MGMT_CONFIG,
+ STRINGIFY(R_MII_MGMT_CONFIG));
+ dump_reg(base_addr, R_MII_MGMT_COMMAND,
+ STRINGIFY(R_MII_MGMT_COMMAND));
+ dump_reg(base_addr, R_MII_MGMT_ADDRESS,
+ STRINGIFY(R_MII_MGMT_ADDRESS));
+ dump_reg(base_addr, R_MII_MGMT_WRITE_DATA,
+ STRINGIFY(R_MII_MGMT_WRITE_DATA));
+ dump_reg(base_addr, R_MII_MGMT_STATUS,
+ STRINGIFY(R_MII_MGMT_STATUS));
+ dump_reg(base_addr, R_MII_MGMT_INDICATORS,
+ STRINGIFY(R_MII_MGMT_INDICATORS));
+ dump_reg(base_addr, R_INTERFACE_CONTROL,
+ STRINGIFY(R_INTERFACE_CONTROL));
+ dump_reg(base_addr, R_INTERFACE_STATUS,
+ STRINGIFY(R_INTERFACE_STATUS));
+ } else if (sc->port_type == XLR_XAUI || sc->port_type == XLR_XGMII) {
+ dump_reg(base_addr, R_XGMAC_CONFIG_0,
+ STRINGIFY(R_XGMAC_CONFIG_0));
+ dump_reg(base_addr, R_XGMAC_CONFIG_1,
+ STRINGIFY(R_XGMAC_CONFIG_1));
+ dump_reg(base_addr, R_XGMAC_CONFIG_2,
+ STRINGIFY(R_XGMAC_CONFIG_2));
+ dump_reg(base_addr, R_XGMAC_CONFIG_3,
+ STRINGIFY(R_XGMAC_CONFIG_3));
+ dump_reg(base_addr, R_XGMAC_STATION_ADDRESS_LS,
+ STRINGIFY(R_XGMAC_STATION_ADDRESS_LS));
+ dump_reg(base_addr, R_XGMAC_STATION_ADDRESS_MS,
+ STRINGIFY(R_XGMAC_STATION_ADDRESS_MS));
+ dump_reg(base_addr, R_XGMAC_MAX_FRAME_LEN,
+ STRINGIFY(R_XGMAC_MAX_FRAME_LEN));
+ dump_reg(base_addr, R_XGMAC_REV_LEVEL,
+ STRINGIFY(R_XGMAC_REV_LEVEL));
+ dump_reg(base_addr, R_XGMAC_MIIM_COMMAND,
+ STRINGIFY(R_XGMAC_MIIM_COMMAND));
+ dump_reg(base_addr, R_XGMAC_MIIM_FILED,
+ STRINGIFY(R_XGMAC_MIIM_FILED));
+ dump_reg(base_addr, R_XGMAC_MIIM_CONFIG,
+ STRINGIFY(R_XGMAC_MIIM_CONFIG));
+ dump_reg(base_addr, R_XGMAC_MIIM_LINK_FAIL_VECTOR,
+ STRINGIFY(R_XGMAC_MIIM_LINK_FAIL_VECTOR));
+ dump_reg(base_addr, R_XGMAC_MIIM_INDICATOR,
+ STRINGIFY(R_XGMAC_MIIM_INDICATOR));
+ }
+
+ dump_reg(base_addr, R_MAC_ADDR0, STRINGIFY(R_MAC_ADDR0));
+ dump_reg(base_addr, R_MAC_ADDR0 + 1, STRINGIFY(R_MAC_ADDR0+1));
+ dump_reg(base_addr, R_MAC_ADDR1, STRINGIFY(R_MAC_ADDR1));
+ dump_reg(base_addr, R_MAC_ADDR2, STRINGIFY(R_MAC_ADDR2));
+ dump_reg(base_addr, R_MAC_ADDR3, STRINGIFY(R_MAC_ADDR3));
+ dump_reg(base_addr, R_MAC_ADDR_MASK2, STRINGIFY(R_MAC_ADDR_MASK2));
+ dump_reg(base_addr, R_MAC_ADDR_MASK3, STRINGIFY(R_MAC_ADDR_MASK3));
+ dump_reg(base_addr, R_MAC_FILTER_CONFIG, STRINGIFY(R_MAC_FILTER_CONFIG));
+ dump_reg(base_addr, R_TX_CONTROL, STRINGIFY(R_TX_CONTROL));
+ dump_reg(base_addr, R_RX_CONTROL, STRINGIFY(R_RX_CONTROL));
+ dump_reg(base_addr, R_DESC_PACK_CTRL, STRINGIFY(R_DESC_PACK_CTRL));
+ dump_reg(base_addr, R_STATCTRL, STRINGIFY(R_STATCTRL));
+ dump_reg(base_addr, R_L2ALLOCCTRL, STRINGIFY(R_L2ALLOCCTRL));
+ dump_reg(base_addr, R_INTMASK, STRINGIFY(R_INTMASK));
+ dump_reg(base_addr, R_INTREG, STRINGIFY(R_INTREG));
+ dump_reg(base_addr, R_TXRETRY, STRINGIFY(R_TXRETRY));
+ dump_reg(base_addr, R_CORECONTROL, STRINGIFY(R_CORECONTROL));
+ dump_reg(base_addr, R_BYTEOFFSET0, STRINGIFY(R_BYTEOFFSET0));
+ dump_reg(base_addr, R_BYTEOFFSET1, STRINGIFY(R_BYTEOFFSET1));
+ dump_reg(base_addr, R_L2TYPE_0, STRINGIFY(R_L2TYPE_0));
+ dump_na_registers(base_addr, port_id);
+}
+
+static void
+dump_fmn_cpu_credits_for_gmac(struct xlr_board_info *board, int gmac_id)
+{
+ struct stn_cc *cc;
+ int gmac_bucket_ids[] = { 97, 98, 99, 100, 101, 103 };
+ int j, k, r, c;
+ int n_gmac_buckets;
+
+ n_gmac_buckets = sizeof (gmac_bucket_ids) / sizeof (gmac_bucket_ids[0]);
+ for (j = 0; j < 8; j++) { // for each cpu
+ cc = board->credit_configs[j];
+ printf("Credits for Station CPU_%d ---> GMAC buckets (tx path)\n", j);
+ for (k = 0; k < n_gmac_buckets; k++) {
+ r = gmac_bucket_ids[k] / 8;
+ c = gmac_bucket_ids[k] % 8;
+ printf (" --> gmac%d_bucket_%-3d: credits=%d\n", gmac_id,
+ gmac_bucket_ids[k], cc->counters[r][c]);
+ }
+ }
+}
+
+static void
+dump_fmn_gmac_credits(struct xlr_board_info *board, int gmac_id)
+{
+ struct stn_cc *cc;
+ int j, k;
+
+ cc = board->gmac_block[gmac_id].credit_config;
+ printf("Credits for Station: GMAC_%d ---> CPU buckets (rx path)\n", gmac_id);
+ for (j = 0; j < 8; j++) { // for each cpu
+ printf(" ---> cpu_%d\n", j);
+ for (k = 0; k < 8; k++) { // for each bucket in cpu
+ printf(" ---> bucket_%d: credits=%d\n", j * 8 + k,
+ cc->counters[j][k]);
+ }
+ }
+}
+
+static void
+dump_board_info(struct xlr_board_info *board)
+{
+ struct xlr_gmac_block_t *gm;
+ int i, k;
+
+ printf("cpu=%x ", xlr_revision());
+ printf("board_version: major=%llx, minor=%llx\n",
+ xlr_boot1_info.board_major_version,
+ xlr_boot1_info.board_minor_version);
+ printf("is_xls=%d, nr_cpus=%d, usb=%s, cfi=%s, ata=%s\npci_irq=%d,"
+ "gmac_ports=%d\n", board->is_xls, board->nr_cpus,
+ board->usb ? "Yes" : "No", board->cfi ? "Yes": "No",
+ board->ata ? "Yes" : "No", board->pci_irq, board->gmacports);
+ printf("FMN: Core-station bucket sizes\n");
+ for (i = 0; i < 128; i++) {
+ if (i && ((i % 16) == 0))
+ printf("\n");
+ printf ("b[%d] = %d ", i, board->bucket_sizes->bucket[i]);
+ }
+ printf("\n");
+ for (i = 0; i < 3; i++) {
+ gm = &board->gmac_block[i];
+ printf("RNA_%d: type=%d, enabled=%s, mode=%d, station_id=%d,"
+ "station_txbase=%d, station_rfr=%d ", i, gm->type,
+ gm->enabled ? "Yes" : "No", gm->mode, gm->station_id,
+ gm->station_txbase, gm->station_rfr);
+ printf("n_ports=%d, baseaddr=%p, baseirq=%d, baseinst=%d\n",
+ gm->num_ports, (xlr_reg_t *)gm->baseaddr, gm->baseirq,
+ gm->baseinst);
+ }
+ for (k = 0; k < 3; k++) { // for each NA
+ dump_fmn_cpu_credits_for_gmac(board, k);
+ dump_fmn_gmac_credits(board, k);
+ }
+}
+
+static void
+dump_mac_stats(struct nlge_softc *sc)
+{
+ xlr_reg_t *addr;
+ uint32_t pkts_tx, pkts_rx;
+
+ addr = sc->base;
+ pkts_rx = NLGE_READ(sc->base, R_RPKT);
+ pkts_tx = NLGE_READ(sc->base, R_TPKT);
+
+ printf("[nlge_%d mac stats]: pkts_tx=%u, pkts_rx=%u\n", sc->id, pkts_tx,
+ pkts_rx);
+ if (pkts_rx > 0) {
+ uint32_t r;
+
+ /* dump all rx counters. we need this because pkts_rx includes
+ bad packets. */
+ for (r = R_RFCS; r <= R_ROVR; r++)
+ printf("[nlge_%d mac stats]: [0x%x]=%u\n", sc->id, r,
+ NLGE_READ(sc->base, r));
+ }
+ if (pkts_tx > 0) {
+ uint32_t r;
+
+ /* dump all tx counters. might be useful for debugging. */
+ for (r = R_TMCA; r <= R_TFRG; r++) {
+ if ((r == (R_TNCL + 1)) || (r == (R_TNCL + 2)))
+ continue;
+ printf("[nlge_%d mac stats]: [0x%x]=%u\n", sc->id, r,
+ NLGE_READ(sc->base, r));
+ }
+ }
+
+}
+
+static void
+dump_mii_regs(struct nlge_softc *sc)
+{
+ uint32_t mii_regs[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x8, 0x9, 0xa, 0xf, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
+ 0x1c, 0x1d, 0x1e};
+ int i, n_regs;
+
+ if (sc->mii_base == NULL || sc->mii_bus == NULL)
+ return;
+
+ n_regs = sizeof (mii_regs) / sizeof (mii_regs[0]);
+ for (i = 0; i < n_regs; i++) {
+ printf("[mii_0x%x] = %x\n", mii_regs[i],
+ nlge_mii_read_internal(sc->mii_base, sc->phy_addr,
+ mii_regs[i]));
+ }
+}
+
+static void
+dump_ifmedia(struct ifmedia *ifm)
+{
+ printf("ifm_mask=%08x, ifm_media=%08x, cur=%p\n", ifm->ifm_mask,
+ ifm->ifm_media, ifm->ifm_cur);
+ if (ifm->ifm_cur != NULL) {
+ printf("Cur attribs: ifmedia_entry.ifm_media=%08x,"
+ " ifmedia_entry.ifm_data=%08x\n", ifm->ifm_cur->ifm_media,
+ ifm->ifm_cur->ifm_data);
+ }
+}
+
+static void
+dump_mii_data(struct mii_data *mii)
+{
+ dump_ifmedia(&mii->mii_media);
+ printf("ifp=%p, mii_instance=%d, mii_media_status=%08x,"
+ " mii_media_active=%08x\n", mii->mii_ifp, mii->mii_instance,
+ mii->mii_media_status, mii->mii_media_active);
+}
+
+static void
+dump_pcs_regs(struct nlge_softc *sc, int phy)
+{
+ int i, val;
+
+ printf("PCS regs from %p for phy=%d\n", sc->pcs_addr, phy);
+ for (i = 0; i < 18; i++) {
+ if (i == 2 || i == 3 || (i >= 9 && i <= 14))
+ continue;
+ val = nlge_mii_read_internal(sc->pcs_addr, phy, i);
+ printf("PHY:%d pcs[0x%x] is 0x%x\n", phy, i, val);
+ }
+}
+#endif
diff --git a/sys/mips/rmi/dev/nlge/if_nlge.h b/sys/mips/rmi/dev/nlge/if_nlge.h
new file mode 100644
index 0000000..0347071
--- /dev/null
+++ b/sys/mips/rmi/dev/nlge/if_nlge.h
@@ -0,0 +1,1180 @@
+/*-
+ * Copyright (c) 2003-2009 RMI Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of RMI Corporation, nor the names of its contributors,
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * $FreeBSD$
+ *
+ * RMI_BSD
+ */
+
+/* #define MAC_SPLIT_MODE */
+
+#define MAC_SPACING 0x400
+#define XGMAC_SPACING 0x400
+
+/* PE-MCXMAC register and bit field definitions */
+#define R_MAC_CONFIG_1 0x00
+#define O_MAC_CONFIG_1__srst 31
+#define O_MAC_CONFIG_1__simr 30
+#define O_MAC_CONFIG_1__hrrmc 18
+#define W_MAC_CONFIG_1__hrtmc 2
+#define O_MAC_CONFIG_1__hrrfn 16
+#define W_MAC_CONFIG_1__hrtfn 2
+#define O_MAC_CONFIG_1__intlb 8
+#define O_MAC_CONFIG_1__rxfc 5
+#define O_MAC_CONFIG_1__txfc 4
+#define O_MAC_CONFIG_1__srxen 3
+#define O_MAC_CONFIG_1__rxen 2
+#define O_MAC_CONFIG_1__stxen 1
+#define O_MAC_CONFIG_1__txen 0
+#define R_MAC_CONFIG_2 0x01
+#define O_MAC_CONFIG_2__prlen 12
+#define W_MAC_CONFIG_2__prlen 4
+#define O_MAC_CONFIG_2__speed 8
+#define W_MAC_CONFIG_2__speed 2
+#define O_MAC_CONFIG_2__hugen 5
+#define O_MAC_CONFIG_2__flchk 4
+#define O_MAC_CONFIG_2__crce 1
+#define O_MAC_CONFIG_2__fulld 0
+#define R_IPG_IFG 0x02
+#define O_IPG_IFG__ipgr1 24
+#define W_IPG_IFG__ipgr1 7
+#define O_IPG_IFG__ipgr2 16
+#define W_IPG_IFG__ipgr2 7
+#define O_IPG_IFG__mifg 8
+#define W_IPG_IFG__mifg 8
+#define O_IPG_IFG__ipgt 0
+#define W_IPG_IFG__ipgt 7
+#define R_HALF_DUPLEX 0x03
+#define O_HALF_DUPLEX__abebt 24
+#define W_HALF_DUPLEX__abebt 4
+#define O_HALF_DUPLEX__abebe 19
+#define O_HALF_DUPLEX__bpnb 18
+#define O_HALF_DUPLEX__nobo 17
+#define O_HALF_DUPLEX__edxsdfr 16
+#define O_HALF_DUPLEX__retry 12
+#define W_HALF_DUPLEX__retry 4
+#define O_HALF_DUPLEX__lcol 0
+#define W_HALF_DUPLEX__lcol 10
+#define R_MAXIMUM_FRAME_LENGTH 0x04
+#define O_MAXIMUM_FRAME_LENGTH__maxf 0
+#define W_MAXIMUM_FRAME_LENGTH__maxf 16
+#define R_TEST 0x07
+#define O_TEST__mbof 3
+#define O_TEST__rthdf 2
+#define O_TEST__tpause 1
+#define O_TEST__sstct 0
+#define R_MII_MGMT_CONFIG 0x08
+#define O_MII_MGMT_CONFIG__scinc 5
+#define O_MII_MGMT_CONFIG__spre 4
+#define O_MII_MGMT_CONFIG__clks 3
+#define W_MII_MGMT_CONFIG__clks 3
+#define R_MII_MGMT_COMMAND 0x09
+#define O_MII_MGMT_COMMAND__scan 1
+#define O_MII_MGMT_COMMAND__rstat 0
+#define R_MII_MGMT_ADDRESS 0x0A
+#define O_MII_MGMT_ADDRESS__fiad 8
+#define W_MII_MGMT_ADDRESS__fiad 5
+#define O_MII_MGMT_ADDRESS__fgad 5
+#define W_MII_MGMT_ADDRESS__fgad 0
+#define R_MII_MGMT_WRITE_DATA 0x0B
+#define O_MII_MGMT_WRITE_DATA__ctld 0
+#define W_MII_MGMT_WRITE_DATA__ctld 16
+#define R_MII_MGMT_STATUS 0x0C
+#define R_MII_MGMT_INDICATORS 0x0D
+#define O_MII_MGMT_INDICATORS__nvalid 2
+#define O_MII_MGMT_INDICATORS__scan 1
+#define O_MII_MGMT_INDICATORS__busy 0
+#define R_INTERFACE_CONTROL 0x0E
+#define O_INTERFACE_CONTROL__hrstint 31
+#define O_INTERFACE_CONTROL__tbimode 27
+#define O_INTERFACE_CONTROL__ghdmode 26
+#define O_INTERFACE_CONTROL__lhdmode 25
+#define O_INTERFACE_CONTROL__phymod 24
+#define O_INTERFACE_CONTROL__hrrmi 23
+#define O_INTERFACE_CONTROL__rspd 16
+#define O_INTERFACE_CONTROL__hr100 15
+#define O_INTERFACE_CONTROL__frcq 10
+#define O_INTERFACE_CONTROL__nocfr 9
+#define O_INTERFACE_CONTROL__dlfct 8
+#define O_INTERFACE_CONTROL__enjab 0
+#define R_INTERFACE_STATUS 0x0F
+#define O_INTERFACE_STATUS__xsdfr 9
+#define O_INTERFACE_STATUS__ssrr 8
+#define W_INTERFACE_STATUS__ssrr 5
+#define O_INTERFACE_STATUS__miilf 3
+#define O_INTERFACE_STATUS__locar 2
+#define O_INTERFACE_STATUS__sqerr 1
+#define O_INTERFACE_STATUS__jabber 0
+#define R_STATION_ADDRESS_LS 0x10
+#define R_STATION_ADDRESS_MS 0x11
+
+/* A-XGMAC register and bit field definitions */
+#define R_XGMAC_CONFIG_0 0x00
+#define O_XGMAC_CONFIG_0__hstmacrst 31
+#define O_XGMAC_CONFIG_0__hstrstrctl 23
+#define O_XGMAC_CONFIG_0__hstrstrfn 22
+#define O_XGMAC_CONFIG_0__hstrsttctl 18
+#define O_XGMAC_CONFIG_0__hstrsttfn 17
+#define O_XGMAC_CONFIG_0__hstrstmiim 16
+#define O_XGMAC_CONFIG_0__hstloopback 8
+#define R_XGMAC_CONFIG_1 0x01
+#define O_XGMAC_CONFIG_1__hsttctlen 31
+#define O_XGMAC_CONFIG_1__hsttfen 30
+#define O_XGMAC_CONFIG_1__hstrctlen 29
+#define O_XGMAC_CONFIG_1__hstrfen 28
+#define O_XGMAC_CONFIG_1__tfen 26
+#define O_XGMAC_CONFIG_1__rfen 24
+#define O_XGMAC_CONFIG_1__hstrctlshrtp 12
+#define O_XGMAC_CONFIG_1__hstdlyfcstx 10
+#define W_XGMAC_CONFIG_1__hstdlyfcstx 2
+#define O_XGMAC_CONFIG_1__hstdlyfcsrx 8
+#define W_XGMAC_CONFIG_1__hstdlyfcsrx 2
+#define O_XGMAC_CONFIG_1__hstppen 7
+#define O_XGMAC_CONFIG_1__hstbytswp 6
+#define O_XGMAC_CONFIG_1__hstdrplt64 5
+#define O_XGMAC_CONFIG_1__hstprmscrx 4
+#define O_XGMAC_CONFIG_1__hstlenchk 3
+#define O_XGMAC_CONFIG_1__hstgenfcs 2
+#define O_XGMAC_CONFIG_1__hstpadmode 0
+#define W_XGMAC_CONFIG_1__hstpadmode 2
+#define R_XGMAC_CONFIG_2 0x02
+#define O_XGMAC_CONFIG_2__hsttctlfrcp 31
+#define O_XGMAC_CONFIG_2__hstmlnkflth 27
+#define O_XGMAC_CONFIG_2__hstalnkflth 26
+#define O_XGMAC_CONFIG_2__rflnkflt 24
+#define W_XGMAC_CONFIG_2__rflnkflt 2
+#define O_XGMAC_CONFIG_2__hstipgextmod 16
+#define W_XGMAC_CONFIG_2__hstipgextmod 5
+#define O_XGMAC_CONFIG_2__hstrctlfrcp 15
+#define O_XGMAC_CONFIG_2__hstipgexten 5
+#define O_XGMAC_CONFIG_2__hstmipgext 0
+#define W_XGMAC_CONFIG_2__hstmipgext 5
+#define R_XGMAC_CONFIG_3 0x03
+#define O_XGMAC_CONFIG_3__hstfltrfrm 31
+#define W_XGMAC_CONFIG_3__hstfltrfrm 16
+#define O_XGMAC_CONFIG_3__hstfltrfrmdc 15
+#define W_XGMAC_CONFIG_3__hstfltrfrmdc 16
+#define R_XGMAC_STATION_ADDRESS_LS 0x04
+#define O_XGMAC_STATION_ADDRESS_LS__hstmacadr0 0
+#define W_XGMAC_STATION_ADDRESS_LS__hstmacadr0 32
+#define R_XGMAC_STATION_ADDRESS_MS 0x05
+#define R_XGMAC_MAX_FRAME_LEN 0x08
+#define O_XGMAC_MAX_FRAME_LEN__hstmxfrmwctx 16
+#define W_XGMAC_MAX_FRAME_LEN__hstmxfrmwctx 14
+#define O_XGMAC_MAX_FRAME_LEN__hstmxfrmbcrx 0
+#define W_XGMAC_MAX_FRAME_LEN__hstmxfrmbcrx 16
+#define R_XGMAC_REV_LEVEL 0x0B
+#define O_XGMAC_REV_LEVEL__revlvl 0
+#define W_XGMAC_REV_LEVEL__revlvl 15
+#define R_XGMAC_MIIM_COMMAND 0x10
+#define O_XGMAC_MIIM_COMMAND__hstldcmd 3
+#define O_XGMAC_MIIM_COMMAND__hstmiimcmd 0
+#define W_XGMAC_MIIM_COMMAND__hstmiimcmd 3
+#define R_XGMAC_MIIM_FILED 0x11
+#define O_XGMAC_MIIM_FILED__hststfield 30
+#define W_XGMAC_MIIM_FILED__hststfield 2
+#define O_XGMAC_MIIM_FILED__hstopfield 28
+#define W_XGMAC_MIIM_FILED__hstopfield 2
+#define O_XGMAC_MIIM_FILED__hstphyadx 23
+#define W_XGMAC_MIIM_FILED__hstphyadx 5
+#define O_XGMAC_MIIM_FILED__hstregadx 18
+#define W_XGMAC_MIIM_FILED__hstregadx 5
+#define O_XGMAC_MIIM_FILED__hsttafield 16
+#define W_XGMAC_MIIM_FILED__hsttafield 2
+#define O_XGMAC_MIIM_FILED__miimrddat 0
+#define W_XGMAC_MIIM_FILED__miimrddat 16
+#define R_XGMAC_MIIM_CONFIG 0x12
+#define O_XGMAC_MIIM_CONFIG__hstnopram 7
+#define O_XGMAC_MIIM_CONFIG__hstclkdiv 0
+#define W_XGMAC_MIIM_CONFIG__hstclkdiv 7
+#define R_XGMAC_MIIM_LINK_FAIL_VECTOR 0x13
+#define O_XGMAC_MIIM_LINK_FAIL_VECTOR__miimlfvec 0
+#define W_XGMAC_MIIM_LINK_FAIL_VECTOR__miimlfvec 32
+#define R_XGMAC_MIIM_INDICATOR 0x14
+#define O_XGMAC_MIIM_INDICATOR__miimphylf 4
+#define O_XGMAC_MIIM_INDICATOR__miimmoncplt 3
+#define O_XGMAC_MIIM_INDICATOR__miimmonvld 2
+#define O_XGMAC_MIIM_INDICATOR__miimmon 1
+#define O_XGMAC_MIIM_INDICATOR__miimbusy 0
+
+/* GMAC stats registers */
+#define R_RBYT 0x27
+#define R_RPKT 0x28
+#define R_RFCS 0x29
+#define R_RMCA 0x2A
+#define R_RBCA 0x2B
+#define R_RXCF 0x2C
+#define R_RXPF 0x2D
+#define R_RXUO 0x2E
+#define R_RALN 0x2F
+#define R_RFLR 0x30
+#define R_RCDE 0x31
+#define R_RCSE 0x32
+#define R_RUND 0x33
+#define R_ROVR 0x34
+#define R_TBYT 0x38
+#define R_TPKT 0x39
+#define R_TMCA 0x3A
+#define R_TBCA 0x3B
+#define R_TXPF 0x3C
+#define R_TDFR 0x3D
+#define R_TEDF 0x3E
+#define R_TSCL 0x3F
+#define R_TMCL 0x40
+#define R_TLCL 0x41
+#define R_TXCL 0x42
+#define R_TNCL 0x43
+#define R_TJBR 0x46
+#define R_TFCS 0x47
+#define R_TXCF 0x48
+#define R_TOVR 0x49
+#define R_TUND 0x4A
+#define R_TFRG 0x4B
+
+/* Glue logic register and bit field definitions */
+#define R_MAC_ADDR0 0x50
+#define R_MAC_ADDR1 0x52
+#define R_MAC_ADDR2 0x54
+#define R_MAC_ADDR3 0x56
+#define R_MAC_ADDR_MASK2 0x58
+#define R_MAC_ADDR_MASK3 0x5A
+#define R_MAC_FILTER_CONFIG 0x5C
+#define O_MAC_FILTER_CONFIG__BROADCAST_EN 10
+#define O_MAC_FILTER_CONFIG__PAUSE_FRAME_EN 9
+#define O_MAC_FILTER_CONFIG__ALL_MCAST_EN 8
+#define O_MAC_FILTER_CONFIG__ALL_UCAST_EN 7
+#define O_MAC_FILTER_CONFIG__HASH_MCAST_EN 6
+#define O_MAC_FILTER_CONFIG__HASH_UCAST_EN 5
+#define O_MAC_FILTER_CONFIG__ADDR_MATCH_DISC 4
+#define O_MAC_FILTER_CONFIG__MAC_ADDR3_VALID 3
+#define O_MAC_FILTER_CONFIG__MAC_ADDR2_VALID 2
+#define O_MAC_FILTER_CONFIG__MAC_ADDR1_VALID 1
+#define O_MAC_FILTER_CONFIG__MAC_ADDR0_VALID 0
+#define R_HASH_TABLE_VECTOR 0x30
+#define R_TX_CONTROL 0x0A0
+#define O_TX_CONTROL__Tx15Halt 31
+#define O_TX_CONTROL__Tx14Halt 30
+#define O_TX_CONTROL__Tx13Halt 29
+#define O_TX_CONTROL__Tx12Halt 28
+#define O_TX_CONTROL__Tx11Halt 27
+#define O_TX_CONTROL__Tx10Halt 26
+#define O_TX_CONTROL__Tx9Halt 25
+#define O_TX_CONTROL__Tx8Halt 24
+#define O_TX_CONTROL__Tx7Halt 23
+#define O_TX_CONTROL__Tx6Halt 22
+#define O_TX_CONTROL__Tx5Halt 21
+#define O_TX_CONTROL__Tx4Halt 20
+#define O_TX_CONTROL__Tx3Halt 19
+#define O_TX_CONTROL__Tx2Halt 18
+#define O_TX_CONTROL__Tx1Halt 17
+#define O_TX_CONTROL__Tx0Halt 16
+#define O_TX_CONTROL__TxIdle 15
+#define O_TX_CONTROL__TxEnable 14
+#define O_TX_CONTROL__TxThreshold 0
+#define W_TX_CONTROL__TxThreshold 14
+#define R_RX_CONTROL 0x0A1
+#define O_RX_CONTROL__RGMII 10
+#define O_RX_CONTROL__SoftReset 2
+#define O_RX_CONTROL__RxHalt 1
+#define O_RX_CONTROL__RxEnable 0
+#define R_DESC_PACK_CTRL 0x0A2
+#define O_DESC_PACK_CTRL__ByteOffset 17
+#define W_DESC_PACK_CTRL__ByteOffset 3
+#define O_DESC_PACK_CTRL__PrePadEnable 16
+#define O_DESC_PACK_CTRL__MaxEntry 14
+#define W_DESC_PACK_CTRL__MaxEntry 2
+#define O_DESC_PACK_CTRL__RegularSize 0
+#define W_DESC_PACK_CTRL__RegularSize 14
+#define R_STATCTRL 0x0A3
+#define O_STATCTRL__OverFlowEn 4
+#define O_STATCTRL__GIG 3
+#define O_STATCTRL__Sten 2
+#define O_STATCTRL__ClrCnt 1
+#define O_STATCTRL__AutoZ 0
+#define R_L2ALLOCCTRL 0x0A4
+#define O_L2ALLOCCTRL__TxL2Allocate 9
+#define W_L2ALLOCCTRL__TxL2Allocate 9
+#define O_L2ALLOCCTRL__RxL2Allocate 0
+#define W_L2ALLOCCTRL__RxL2Allocate 9
+#define R_INTMASK 0x0A5
+#define O_INTMASK__Spi4TxError 28
+#define O_INTMASK__Spi4RxError 27
+#define O_INTMASK__RGMIIHalfDupCollision 27
+#define O_INTMASK__Abort 26
+#define O_INTMASK__Underrun 25
+#define O_INTMASK__DiscardPacket 24
+#define O_INTMASK__AsyncFifoFull 23
+#define O_INTMASK__TagFull 22
+#define O_INTMASK__Class3Full 21
+#define O_INTMASK__C3EarlyFull 20
+#define O_INTMASK__Class2Full 19
+#define O_INTMASK__C2EarlyFull 18
+#define O_INTMASK__Class1Full 17
+#define O_INTMASK__C1EarlyFull 16
+#define O_INTMASK__Class0Full 15
+#define O_INTMASK__C0EarlyFull 14
+#define O_INTMASK__RxDataFull 13
+#define O_INTMASK__RxEarlyFull 12
+#define O_INTMASK__RFreeEmpty 9
+#define O_INTMASK__RFEarlyEmpty 8
+#define O_INTMASK__P2PSpillEcc 7
+#define O_INTMASK__FreeDescFull 5
+#define O_INTMASK__FreeEarlyFull 4
+#define O_INTMASK__TxFetchError 3
+#define O_INTMASK__StatCarry 2
+#define O_INTMASK__MDInt 1
+#define O_INTMASK__TxIllegal 0
+#define R_INTREG 0x0A6
+#define O_INTREG__Spi4TxError 28
+#define O_INTREG__Spi4RxError 27
+#define O_INTREG__RGMIIHalfDupCollision 27
+#define O_INTREG__Abort 26
+#define O_INTREG__Underrun 25
+#define O_INTREG__DiscardPacket 24
+#define O_INTREG__AsyncFifoFull 23
+#define O_INTREG__TagFull 22
+#define O_INTREG__Class3Full 21
+#define O_INTREG__C3EarlyFull 20
+#define O_INTREG__Class2Full 19
+#define O_INTREG__C2EarlyFull 18
+#define O_INTREG__Class1Full 17
+#define O_INTREG__C1EarlyFull 16
+#define O_INTREG__Class0Full 15
+#define O_INTREG__C0EarlyFull 14
+#define O_INTREG__RxDataFull 13
+#define O_INTREG__RxEarlyFull 12
+#define O_INTREG__RFreeEmpty 9
+#define O_INTREG__RFEarlyEmpty 8
+#define O_INTREG__P2PSpillEcc 7
+#define O_INTREG__FreeDescFull 5
+#define O_INTREG__FreeEarlyFull 4
+#define O_INTREG__TxFetchError 3
+#define O_INTREG__StatCarry 2
+#define O_INTREG__MDInt 1
+#define O_INTREG__TxIllegal 0
+#define R_TXRETRY 0x0A7
+#define O_TXRETRY__CollisionRetry 6
+#define O_TXRETRY__BusErrorRetry 5
+#define O_TXRETRY__UnderRunRetry 4
+#define O_TXRETRY__Retries 0
+#define W_TXRETRY__Retries 4
+#define R_CORECONTROL 0x0A8
+#define O_CORECONTROL__ErrorThread 4
+#define W_CORECONTROL__ErrorThread 7
+#define O_CORECONTROL__Shutdown 2
+#define O_CORECONTROL__Speed 0
+#define W_CORECONTROL__Speed 2
+#define R_BYTEOFFSET0 0x0A9
+#define R_BYTEOFFSET1 0x0AA
+#define R_L2TYPE_0 0x0F0
+#define O_L2TYPE__ExtraHdrProtoSize 26
+#define W_L2TYPE__ExtraHdrProtoSize 5
+#define O_L2TYPE__ExtraHdrProtoOffset 20
+#define W_L2TYPE__ExtraHdrProtoOffset 6
+#define O_L2TYPE__ExtraHeaderSize 14
+#define W_L2TYPE__ExtraHeaderSize 6
+#define O_L2TYPE__ProtoOffset 8
+#define W_L2TYPE__ProtoOffset 6
+#define O_L2TYPE__L2HdrOffset 2
+#define W_L2TYPE__L2HdrOffset 6
+#define O_L2TYPE__L2Proto 0
+#define W_L2TYPE__L2Proto 2
+#define R_L2TYPE_1 0xF0
+#define R_L2TYPE_2 0xF0
+#define R_L2TYPE_3 0xF0
+#define R_PARSERCONFIGREG 0x100
+#define O_PARSERCONFIGREG__CRCHashPoly 8
+#define W_PARSERCONFIGREG__CRCHashPoly 7
+#define O_PARSERCONFIGREG__PrePadOffset 4
+#define W_PARSERCONFIGREG__PrePadOffset 4
+#define O_PARSERCONFIGREG__UseCAM 2
+#define O_PARSERCONFIGREG__UseHASH 1
+#define O_PARSERCONFIGREG__UseProto 0
+#define R_L3CTABLE 0x140
+#define O_L3CTABLE__Offset0 25
+#define W_L3CTABLE__Offset0 7
+#define O_L3CTABLE__Len0 21
+#define W_L3CTABLE__Len0 4
+#define O_L3CTABLE__Offset1 14
+#define W_L3CTABLE__Offset1 7
+#define O_L3CTABLE__Len1 10
+#define W_L3CTABLE__Len1 4
+#define O_L3CTABLE__Offset2 4
+#define W_L3CTABLE__Offset2 6
+#define O_L3CTABLE__Len2 0
+#define W_L3CTABLE__Len2 4
+#define O_L3CTABLE__L3HdrOffset 26
+#define W_L3CTABLE__L3HdrOffset 6
+#define O_L3CTABLE__L4ProtoOffset 20
+#define W_L3CTABLE__L4ProtoOffset 6
+#define O_L3CTABLE__IPChksumCompute 19
+#define O_L3CTABLE__L4Classify 18
+#define O_L3CTABLE__L2Proto 16
+#define W_L3CTABLE__L2Proto 2
+#define O_L3CTABLE__L3ProtoKey 0
+#define W_L3CTABLE__L3ProtoKey 16
+#define R_L4CTABLE 0x160
+#define O_L4CTABLE__Offset0 21
+#define W_L4CTABLE__Offset0 6
+#define O_L4CTABLE__Len0 17
+#define W_L4CTABLE__Len0 4
+#define O_L4CTABLE__Offset1 11
+#define W_L4CTABLE__Offset1 6
+#define O_L4CTABLE__Len1 7
+#define W_L4CTABLE__Len1 4
+#define O_L4CTABLE__TCPChksumEnable 0
+#define R_CAM4X128TABLE 0x172
+#define O_CAM4X128TABLE__ClassId 7
+#define W_CAM4X128TABLE__ClassId 2
+#define O_CAM4X128TABLE__BucketId 1
+#define W_CAM4X128TABLE__BucketId 6
+#define O_CAM4X128TABLE__UseBucket 0
+#define R_CAM4X128KEY 0x180
+#define R_TRANSLATETABLE 0x1A0
+#define R_DMACR0 0x200
+#define O_DMACR0__Data0WrMaxCr 27
+#define W_DMACR0__Data0WrMaxCr 3
+#define O_DMACR0__Data0RdMaxCr 24
+#define W_DMACR0__Data0RdMaxCr 3
+#define O_DMACR0__Data1WrMaxCr 21
+#define W_DMACR0__Data1WrMaxCr 3
+#define O_DMACR0__Data1RdMaxCr 18
+#define W_DMACR0__Data1RdMaxCr 3
+#define O_DMACR0__Data2WrMaxCr 15
+#define W_DMACR0__Data2WrMaxCr 3
+#define O_DMACR0__Data2RdMaxCr 12
+#define W_DMACR0__Data2RdMaxCr 3
+#define O_DMACR0__Data3WrMaxCr 9
+#define W_DMACR0__Data3WrMaxCr 3
+#define O_DMACR0__Data3RdMaxCr 6
+#define W_DMACR0__Data3RdMaxCr 3
+#define O_DMACR0__Data4WrMaxCr 3
+#define W_DMACR0__Data4WrMaxCr 3
+#define O_DMACR0__Data4RdMaxCr 0
+#define W_DMACR0__Data4RdMaxCr 3
+#define R_DMACR1 0x201
+#define O_DMACR1__Data5WrMaxCr 27
+#define W_DMACR1__Data5WrMaxCr 3
+#define O_DMACR1__Data5RdMaxCr 24
+#define W_DMACR1__Data5RdMaxCr 3
+#define O_DMACR1__Data6WrMaxCr 21
+#define W_DMACR1__Data6WrMaxCr 3
+#define O_DMACR1__Data6RdMaxCr 18
+#define W_DMACR1__Data6RdMaxCr 3
+#define O_DMACR1__Data7WrMaxCr 15
+#define W_DMACR1__Data7WrMaxCr 3
+#define O_DMACR1__Data7RdMaxCr 12
+#define W_DMACR1__Data7RdMaxCr 3
+#define O_DMACR1__Data8WrMaxCr 9
+#define W_DMACR1__Data8WrMaxCr 3
+#define O_DMACR1__Data8RdMaxCr 6
+#define W_DMACR1__Data8RdMaxCr 3
+#define O_DMACR1__Data9WrMaxCr 3
+#define W_DMACR1__Data9WrMaxCr 3
+#define O_DMACR1__Data9RdMaxCr 0
+#define W_DMACR1__Data9RdMaxCr 3
+#define R_DMACR2 0x202
+#define O_DMACR2__Data10WrMaxCr 27
+#define W_DMACR2__Data10WrMaxCr 3
+#define O_DMACR2__Data10RdMaxCr 24
+#define W_DMACR2__Data10RdMaxCr 3
+#define O_DMACR2__Data11WrMaxCr 21
+#define W_DMACR2__Data11WrMaxCr 3
+#define O_DMACR2__Data11RdMaxCr 18
+#define W_DMACR2__Data11RdMaxCr 3
+#define O_DMACR2__Data12WrMaxCr 15
+#define W_DMACR2__Data12WrMaxCr 3
+#define O_DMACR2__Data12RdMaxCr 12
+#define W_DMACR2__Data12RdMaxCr 3
+#define O_DMACR2__Data13WrMaxCr 9
+#define W_DMACR2__Data13WrMaxCr 3
+#define O_DMACR2__Data13RdMaxCr 6
+#define W_DMACR2__Data13RdMaxCr 3
+#define O_DMACR2__Data14WrMaxCr 3
+#define W_DMACR2__Data14WrMaxCr 3
+#define O_DMACR2__Data14RdMaxCr 0
+#define W_DMACR2__Data14RdMaxCr 3
+#define R_DMACR3 0x203
+#define O_DMACR3__Data15WrMaxCr 27
+#define W_DMACR3__Data15WrMaxCr 3
+#define O_DMACR3__Data15RdMaxCr 24
+#define W_DMACR3__Data15RdMaxCr 3
+#define O_DMACR3__SpClassWrMaxCr 21
+#define W_DMACR3__SpClassWrMaxCr 3
+#define O_DMACR3__SpClassRdMaxCr 18
+#define W_DMACR3__SpClassRdMaxCr 3
+#define O_DMACR3__JumFrInWrMaxCr 15
+#define W_DMACR3__JumFrInWrMaxCr 3
+#define O_DMACR3__JumFrInRdMaxCr 12
+#define W_DMACR3__JumFrInRdMaxCr 3
+#define O_DMACR3__RegFrInWrMaxCr 9
+#define W_DMACR3__RegFrInWrMaxCr 3
+#define O_DMACR3__RegFrInRdMaxCr 6
+#define W_DMACR3__RegFrInRdMaxCr 3
+#define O_DMACR3__FrOutWrMaxCr 3
+#define W_DMACR3__FrOutWrMaxCr 3
+#define O_DMACR3__FrOutRdMaxCr 0
+#define W_DMACR3__FrOutRdMaxCr 3
+#define R_REG_FRIN_SPILL_MEM_START_0 0x204
+#define O_REG_FRIN_SPILL_MEM_START_0__RegFrInSpillMemStart0 0
+#define W_REG_FRIN_SPILL_MEM_START_0__RegFrInSpillMemStart0 32
+#define R_REG_FRIN_SPILL_MEM_START_1 0x205
+#define O_REG_FRIN_SPILL_MEM_START_1__RegFrInSpillMemStart1 0
+#define W_REG_FRIN_SPILL_MEM_START_1__RegFrInSpillMemStart1 3
+#define R_REG_FRIN_SPILL_MEM_SIZE 0x206
+#define O_REG_FRIN_SPILL_MEM_SIZE__RegFrInSpillMemSize 0
+#define W_REG_FRIN_SPILL_MEM_SIZE__RegFrInSpillMemSize 32
+#define R_FROUT_SPILL_MEM_START_0 0x207
+#define O_FROUT_SPILL_MEM_START_0__FrOutSpillMemStart0 0
+#define W_FROUT_SPILL_MEM_START_0__FrOutSpillMemStart0 32
+#define R_FROUT_SPILL_MEM_START_1 0x208
+#define O_FROUT_SPILL_MEM_START_1__FrOutSpillMemStart1 0
+#define W_FROUT_SPILL_MEM_START_1__FrOutSpillMemStart1 3
+#define R_FROUT_SPILL_MEM_SIZE 0x209
+#define O_FROUT_SPILL_MEM_SIZE__FrOutSpillMemSize 0
+#define W_FROUT_SPILL_MEM_SIZE__FrOutSpillMemSize 32
+#define R_CLASS0_SPILL_MEM_START_0 0x20A
+#define O_CLASS0_SPILL_MEM_START_0__Class0SpillMemStart0 0
+#define W_CLASS0_SPILL_MEM_START_0__Class0SpillMemStart0 32
+#define R_CLASS0_SPILL_MEM_START_1 0x20B
+#define O_CLASS0_SPILL_MEM_START_1__Class0SpillMemStart1 0
+#define W_CLASS0_SPILL_MEM_START_1__Class0SpillMemStart1 3
+#define R_CLASS0_SPILL_MEM_SIZE 0x20C
+#define O_CLASS0_SPILL_MEM_SIZE__Class0SpillMemSize 0
+#define W_CLASS0_SPILL_MEM_SIZE__Class0SpillMemSize 32
+#define R_JUMFRIN_SPILL_MEM_START_0 0x20D
+#define O_JUMFRIN_SPILL_MEM_START_0__JumFrInSpillMemStar0 0
+#define W_JUMFRIN_SPILL_MEM_START_0__JumFrInSpillMemStar0 32
+#define R_JUMFRIN_SPILL_MEM_START_1 0x20E
+#define O_JUMFRIN_SPILL_MEM_START_1__JumFrInSpillMemStart1 0
+#define W_JUMFRIN_SPILL_MEM_START_1__JumFrInSpillMemStart1 3
+#define R_JUMFRIN_SPILL_MEM_SIZE 0x20F
+#define O_JUMFRIN_SPILL_MEM_SIZE__JumFrInSpillMemSize 0
+#define W_JUMFRIN_SPILL_MEM_SIZE__JumFrInSpillMemSize 32
+#define R_CLASS1_SPILL_MEM_START_0 0x210
+#define O_CLASS1_SPILL_MEM_START_0__Class1SpillMemStart0 0
+#define W_CLASS1_SPILL_MEM_START_0__Class1SpillMemStart0 32
+#define R_CLASS1_SPILL_MEM_START_1 0x211
+#define O_CLASS1_SPILL_MEM_START_1__Class1SpillMemStart1 0
+#define W_CLASS1_SPILL_MEM_START_1__Class1SpillMemStart1 3
+#define R_CLASS1_SPILL_MEM_SIZE 0x212
+#define O_CLASS1_SPILL_MEM_SIZE__Class1SpillMemSize 0
+#define W_CLASS1_SPILL_MEM_SIZE__Class1SpillMemSize 32
+#define R_CLASS2_SPILL_MEM_START_0 0x213
+#define O_CLASS2_SPILL_MEM_START_0__Class2SpillMemStart0 0
+#define W_CLASS2_SPILL_MEM_START_0__Class2SpillMemStart0 32
+#define R_CLASS2_SPILL_MEM_START_1 0x214
+#define O_CLASS2_SPILL_MEM_START_1__Class2SpillMemStart1 0
+#define W_CLASS2_SPILL_MEM_START_1__Class2SpillMemStart1 3
+#define R_CLASS2_SPILL_MEM_SIZE 0x215
+#define O_CLASS2_SPILL_MEM_SIZE__Class2SpillMemSize 0
+#define W_CLASS2_SPILL_MEM_SIZE__Class2SpillMemSize 32
+#define R_CLASS3_SPILL_MEM_START_0 0x216
+#define O_CLASS3_SPILL_MEM_START_0__Class3SpillMemStart0 0
+#define W_CLASS3_SPILL_MEM_START_0__Class3SpillMemStart0 32
+#define R_CLASS3_SPILL_MEM_START_1 0x217
+#define O_CLASS3_SPILL_MEM_START_1__Class3SpillMemStart1 0
+#define W_CLASS3_SPILL_MEM_START_1__Class3SpillMemStart1 3
+#define R_CLASS3_SPILL_MEM_SIZE 0x218
+#define O_CLASS3_SPILL_MEM_SIZE__Class3SpillMemSize 0
+#define W_CLASS3_SPILL_MEM_SIZE__Class3SpillMemSize 32
+#define R_REG_FRIN1_SPILL_MEM_START_0 0x219
+#define R_REG_FRIN1_SPILL_MEM_START_1 0x21a
+#define R_REG_FRIN1_SPILL_MEM_SIZE 0x21b
+#define R_SPIHNGY0 0x219
+#define O_SPIHNGY0__EG_HNGY_THRESH_0 24
+#define W_SPIHNGY0__EG_HNGY_THRESH_0 7
+#define O_SPIHNGY0__EG_HNGY_THRESH_1 16
+#define W_SPIHNGY0__EG_HNGY_THRESH_1 7
+#define O_SPIHNGY0__EG_HNGY_THRESH_2 8
+#define W_SPIHNGY0__EG_HNGY_THRESH_2 7
+#define O_SPIHNGY0__EG_HNGY_THRESH_3 0
+#define W_SPIHNGY0__EG_HNGY_THRESH_3 7
+#define R_SPIHNGY1 0x21A
+#define O_SPIHNGY1__EG_HNGY_THRESH_4 24
+#define W_SPIHNGY1__EG_HNGY_THRESH_4 7
+#define O_SPIHNGY1__EG_HNGY_THRESH_5 16
+#define W_SPIHNGY1__EG_HNGY_THRESH_5 7
+#define O_SPIHNGY1__EG_HNGY_THRESH_6 8
+#define W_SPIHNGY1__EG_HNGY_THRESH_6 7
+#define O_SPIHNGY1__EG_HNGY_THRESH_7 0
+#define W_SPIHNGY1__EG_HNGY_THRESH_7 7
+#define R_SPIHNGY2 0x21B
+#define O_SPIHNGY2__EG_HNGY_THRESH_8 24
+#define W_SPIHNGY2__EG_HNGY_THRESH_8 7
+#define O_SPIHNGY2__EG_HNGY_THRESH_9 16
+#define W_SPIHNGY2__EG_HNGY_THRESH_9 7
+#define O_SPIHNGY2__EG_HNGY_THRESH_10 8
+#define W_SPIHNGY2__EG_HNGY_THRESH_10 7
+#define O_SPIHNGY2__EG_HNGY_THRESH_11 0
+#define W_SPIHNGY2__EG_HNGY_THRESH_11 7
+#define R_SPIHNGY3 0x21C
+#define O_SPIHNGY3__EG_HNGY_THRESH_12 24
+#define W_SPIHNGY3__EG_HNGY_THRESH_12 7
+#define O_SPIHNGY3__EG_HNGY_THRESH_13 16
+#define W_SPIHNGY3__EG_HNGY_THRESH_13 7
+#define O_SPIHNGY3__EG_HNGY_THRESH_14 8
+#define W_SPIHNGY3__EG_HNGY_THRESH_14 7
+#define O_SPIHNGY3__EG_HNGY_THRESH_15 0
+#define W_SPIHNGY3__EG_HNGY_THRESH_15 7
+#define R_SPISTRV0 0x21D
+#define O_SPISTRV0__EG_STRV_THRESH_0 24
+#define W_SPISTRV0__EG_STRV_THRESH_0 7
+#define O_SPISTRV0__EG_STRV_THRESH_1 16
+#define W_SPISTRV0__EG_STRV_THRESH_1 7
+#define O_SPISTRV0__EG_STRV_THRESH_2 8
+#define W_SPISTRV0__EG_STRV_THRESH_2 7
+#define O_SPISTRV0__EG_STRV_THRESH_3 0
+#define W_SPISTRV0__EG_STRV_THRESH_3 7
+#define R_SPISTRV1 0x21E
+#define O_SPISTRV1__EG_STRV_THRESH_4 24
+#define W_SPISTRV1__EG_STRV_THRESH_4 7
+#define O_SPISTRV1__EG_STRV_THRESH_5 16
+#define W_SPISTRV1__EG_STRV_THRESH_5 7
+#define O_SPISTRV1__EG_STRV_THRESH_6 8
+#define W_SPISTRV1__EG_STRV_THRESH_6 7
+#define O_SPISTRV1__EG_STRV_THRESH_7 0
+#define W_SPISTRV1__EG_STRV_THRESH_7 7
+#define R_SPISTRV2 0x21F
+#define O_SPISTRV2__EG_STRV_THRESH_8 24
+#define W_SPISTRV2__EG_STRV_THRESH_8 7
+#define O_SPISTRV2__EG_STRV_THRESH_9 16
+#define W_SPISTRV2__EG_STRV_THRESH_9 7
+#define O_SPISTRV2__EG_STRV_THRESH_10 8
+#define W_SPISTRV2__EG_STRV_THRESH_10 7
+#define O_SPISTRV2__EG_STRV_THRESH_11 0
+#define W_SPISTRV2__EG_STRV_THRESH_11 7
+#define R_SPISTRV3 0x220
+#define O_SPISTRV3__EG_STRV_THRESH_12 24
+#define W_SPISTRV3__EG_STRV_THRESH_12 7
+#define O_SPISTRV3__EG_STRV_THRESH_13 16
+#define W_SPISTRV3__EG_STRV_THRESH_13 7
+#define O_SPISTRV3__EG_STRV_THRESH_14 8
+#define W_SPISTRV3__EG_STRV_THRESH_14 7
+#define O_SPISTRV3__EG_STRV_THRESH_15 0
+#define W_SPISTRV3__EG_STRV_THRESH_15 7
+#define R_TXDATAFIFO0 0x221
+#define O_TXDATAFIFO0__Tx0DataFifoStart 24
+#define W_TXDATAFIFO0__Tx0DataFifoStart 7
+#define O_TXDATAFIFO0__Tx0DataFifoSize 16
+#define W_TXDATAFIFO0__Tx0DataFifoSize 7
+#define O_TXDATAFIFO0__Tx1DataFifoStart 8
+#define W_TXDATAFIFO0__Tx1DataFifoStart 7
+#define O_TXDATAFIFO0__Tx1DataFifoSize 0
+#define W_TXDATAFIFO0__Tx1DataFifoSize 7
+#define R_TXDATAFIFO1 0x222
+#define O_TXDATAFIFO1__Tx2DataFifoStart 24
+#define W_TXDATAFIFO1__Tx2DataFifoStart 7
+#define O_TXDATAFIFO1__Tx2DataFifoSize 16
+#define W_TXDATAFIFO1__Tx2DataFifoSize 7
+#define O_TXDATAFIFO1__Tx3DataFifoStart 8
+#define W_TXDATAFIFO1__Tx3DataFifoStart 7
+#define O_TXDATAFIFO1__Tx3DataFifoSize 0
+#define W_TXDATAFIFO1__Tx3DataFifoSize 7
+#define R_TXDATAFIFO2 0x223
+#define O_TXDATAFIFO2__Tx4DataFifoStart 24
+#define W_TXDATAFIFO2__Tx4DataFifoStart 7
+#define O_TXDATAFIFO2__Tx4DataFifoSize 16
+#define W_TXDATAFIFO2__Tx4DataFifoSize 7
+#define O_TXDATAFIFO2__Tx5DataFifoStart 8
+#define W_TXDATAFIFO2__Tx5DataFifoStart 7
+#define O_TXDATAFIFO2__Tx5DataFifoSize 0
+#define W_TXDATAFIFO2__Tx5DataFifoSize 7
+#define R_TXDATAFIFO3 0x224
+#define O_TXDATAFIFO3__Tx6DataFifoStart 24
+#define W_TXDATAFIFO3__Tx6DataFifoStart 7
+#define O_TXDATAFIFO3__Tx6DataFifoSize 16
+#define W_TXDATAFIFO3__Tx6DataFifoSize 7
+#define O_TXDATAFIFO3__Tx7DataFifoStart 8
+#define W_TXDATAFIFO3__Tx7DataFifoStart 7
+#define O_TXDATAFIFO3__Tx7DataFifoSize 0
+#define W_TXDATAFIFO3__Tx7DataFifoSize 7
+#define R_TXDATAFIFO4 0x225
+#define O_TXDATAFIFO4__Tx8DataFifoStart 24
+#define W_TXDATAFIFO4__Tx8DataFifoStart 7
+#define O_TXDATAFIFO4__Tx8DataFifoSize 16
+#define W_TXDATAFIFO4__Tx8DataFifoSize 7
+#define O_TXDATAFIFO4__Tx9DataFifoStart 8
+#define W_TXDATAFIFO4__Tx9DataFifoStart 7
+#define O_TXDATAFIFO4__Tx9DataFifoSize 0
+#define W_TXDATAFIFO4__Tx9DataFifoSize 7
+#define R_TXDATAFIFO5 0x226
+#define O_TXDATAFIFO5__Tx10DataFifoStart 24
+#define W_TXDATAFIFO5__Tx10DataFifoStart 7
+#define O_TXDATAFIFO5__Tx10DataFifoSize 16
+#define W_TXDATAFIFO5__Tx10DataFifoSize 7
+#define O_TXDATAFIFO5__Tx11DataFifoStart 8
+#define W_TXDATAFIFO5__Tx11DataFifoStart 7
+#define O_TXDATAFIFO5__Tx11DataFifoSize 0
+#define W_TXDATAFIFO5__Tx11DataFifoSize 7
+#define R_TXDATAFIFO6 0x227
+#define O_TXDATAFIFO6__Tx12DataFifoStart 24
+#define W_TXDATAFIFO6__Tx12DataFifoStart 7
+#define O_TXDATAFIFO6__Tx12DataFifoSize 16
+#define W_TXDATAFIFO6__Tx12DataFifoSize 7
+#define O_TXDATAFIFO6__Tx13DataFifoStart 8
+#define W_TXDATAFIFO6__Tx13DataFifoStart 7
+#define O_TXDATAFIFO6__Tx13DataFifoSize 0
+#define W_TXDATAFIFO6__Tx13DataFifoSize 7
+#define R_TXDATAFIFO7 0x228
+#define O_TXDATAFIFO7__Tx14DataFifoStart 24
+#define W_TXDATAFIFO7__Tx14DataFifoStart 7
+#define O_TXDATAFIFO7__Tx14DataFifoSize 16
+#define W_TXDATAFIFO7__Tx14DataFifoSize 7
+#define O_TXDATAFIFO7__Tx15DataFifoStart 8
+#define W_TXDATAFIFO7__Tx15DataFifoStart 7
+#define O_TXDATAFIFO7__Tx15DataFifoSize 0
+#define W_TXDATAFIFO7__Tx15DataFifoSize 7
+#define R_RXDATAFIFO0 0x229
+#define O_RXDATAFIFO0__Rx0DataFifoStart 24
+#define W_RXDATAFIFO0__Rx0DataFifoStart 7
+#define O_RXDATAFIFO0__Rx0DataFifoSize 16
+#define W_RXDATAFIFO0__Rx0DataFifoSize 7
+#define O_RXDATAFIFO0__Rx1DataFifoStart 8
+#define W_RXDATAFIFO0__Rx1DataFifoStart 7
+#define O_RXDATAFIFO0__Rx1DataFifoSize 0
+#define W_RXDATAFIFO0__Rx1DataFifoSize 7
+#define R_RXDATAFIFO1 0x22A
+#define O_RXDATAFIFO1__Rx2DataFifoStart 24
+#define W_RXDATAFIFO1__Rx2DataFifoStart 7
+#define O_RXDATAFIFO1__Rx2DataFifoSize 16
+#define W_RXDATAFIFO1__Rx2DataFifoSize 7
+#define O_RXDATAFIFO1__Rx3DataFifoStart 8
+#define W_RXDATAFIFO1__Rx3DataFifoStart 7
+#define O_RXDATAFIFO1__Rx3DataFifoSize 0
+#define W_RXDATAFIFO1__Rx3DataFifoSize 7
+#define R_RXDATAFIFO2 0x22B
+#define O_RXDATAFIFO2__Rx4DataFifoStart 24
+#define W_RXDATAFIFO2__Rx4DataFifoStart 7
+#define O_RXDATAFIFO2__Rx4DataFifoSize 16
+#define W_RXDATAFIFO2__Rx4DataFifoSize 7
+#define O_RXDATAFIFO2__Rx5DataFifoStart 8
+#define W_RXDATAFIFO2__Rx5DataFifoStart 7
+#define O_RXDATAFIFO2__Rx5DataFifoSize 0
+#define W_RXDATAFIFO2__Rx5DataFifoSize 7
+#define R_RXDATAFIFO3 0x22C
+#define O_RXDATAFIFO3__Rx6DataFifoStart 24
+#define W_RXDATAFIFO3__Rx6DataFifoStart 7
+#define O_RXDATAFIFO3__Rx6DataFifoSize 16
+#define W_RXDATAFIFO3__Rx6DataFifoSize 7
+#define O_RXDATAFIFO3__Rx7DataFifoStart 8
+#define W_RXDATAFIFO3__Rx7DataFifoStart 7
+#define O_RXDATAFIFO3__Rx7DataFifoSize 0
+#define W_RXDATAFIFO3__Rx7DataFifoSize 7
+#define R_RXDATAFIFO4 0x22D
+#define O_RXDATAFIFO4__Rx8DataFifoStart 24
+#define W_RXDATAFIFO4__Rx8DataFifoStart 7
+#define O_RXDATAFIFO4__Rx8DataFifoSize 16
+#define W_RXDATAFIFO4__Rx8DataFifoSize 7
+#define O_RXDATAFIFO4__Rx9DataFifoStart 8
+#define W_RXDATAFIFO4__Rx9DataFifoStart 7
+#define O_RXDATAFIFO4__Rx9DataFifoSize 0
+#define W_RXDATAFIFO4__Rx9DataFifoSize 7
+#define R_RXDATAFIFO5 0x22E
+#define O_RXDATAFIFO5__Rx10DataFifoStart 24
+#define W_RXDATAFIFO5__Rx10DataFifoStart 7
+#define O_RXDATAFIFO5__Rx10DataFifoSize 16
+#define W_RXDATAFIFO5__Rx10DataFifoSize 7
+#define O_RXDATAFIFO5__Rx11DataFifoStart 8
+#define W_RXDATAFIFO5__Rx11DataFifoStart 7
+#define O_RXDATAFIFO5__Rx11DataFifoSize 0
+#define W_RXDATAFIFO5__Rx11DataFifoSize 7
+#define R_RXDATAFIFO6 0x22F
+#define O_RXDATAFIFO6__Rx12DataFifoStart 24
+#define W_RXDATAFIFO6__Rx12DataFifoStart 7
+#define O_RXDATAFIFO6__Rx12DataFifoSize 16
+#define W_RXDATAFIFO6__Rx12DataFifoSize 7
+#define O_RXDATAFIFO6__Rx13DataFifoStart 8
+#define W_RXDATAFIFO6__Rx13DataFifoStart 7
+#define O_RXDATAFIFO6__Rx13DataFifoSize 0
+#define W_RXDATAFIFO6__Rx13DataFifoSize 7
+#define R_RXDATAFIFO7 0x230
+#define O_RXDATAFIFO7__Rx14DataFifoStart 24
+#define W_RXDATAFIFO7__Rx14DataFifoStart 7
+#define O_RXDATAFIFO7__Rx14DataFifoSize 16
+#define W_RXDATAFIFO7__Rx14DataFifoSize 7
+#define O_RXDATAFIFO7__Rx15DataFifoStart 8
+#define W_RXDATAFIFO7__Rx15DataFifoStart 7
+#define O_RXDATAFIFO7__Rx15DataFifoSize 0
+#define W_RXDATAFIFO7__Rx15DataFifoSize 7
+#define R_XGMACPADCALIBRATION 0x231
+#define R_FREEQCARVE 0x233
+#define R_SPI4STATICDELAY0 0x240
+#define O_SPI4STATICDELAY0__DataLine7 28
+#define W_SPI4STATICDELAY0__DataLine7 4
+#define O_SPI4STATICDELAY0__DataLine6 24
+#define W_SPI4STATICDELAY0__DataLine6 4
+#define O_SPI4STATICDELAY0__DataLine5 20
+#define W_SPI4STATICDELAY0__DataLine5 4
+#define O_SPI4STATICDELAY0__DataLine4 16
+#define W_SPI4STATICDELAY0__DataLine4 4
+#define O_SPI4STATICDELAY0__DataLine3 12
+#define W_SPI4STATICDELAY0__DataLine3 4
+#define O_SPI4STATICDELAY0__DataLine2 8
+#define W_SPI4STATICDELAY0__DataLine2 4
+#define O_SPI4STATICDELAY0__DataLine1 4
+#define W_SPI4STATICDELAY0__DataLine1 4
+#define O_SPI4STATICDELAY0__DataLine0 0
+#define W_SPI4STATICDELAY0__DataLine0 4
+#define R_SPI4STATICDELAY1 0x241
+#define O_SPI4STATICDELAY1__DataLine15 28
+#define W_SPI4STATICDELAY1__DataLine15 4
+#define O_SPI4STATICDELAY1__DataLine14 24
+#define W_SPI4STATICDELAY1__DataLine14 4
+#define O_SPI4STATICDELAY1__DataLine13 20
+#define W_SPI4STATICDELAY1__DataLine13 4
+#define O_SPI4STATICDELAY1__DataLine12 16
+#define W_SPI4STATICDELAY1__DataLine12 4
+#define O_SPI4STATICDELAY1__DataLine11 12
+#define W_SPI4STATICDELAY1__DataLine11 4
+#define O_SPI4STATICDELAY1__DataLine10 8
+#define W_SPI4STATICDELAY1__DataLine10 4
+#define O_SPI4STATICDELAY1__DataLine9 4
+#define W_SPI4STATICDELAY1__DataLine9 4
+#define O_SPI4STATICDELAY1__DataLine8 0
+#define W_SPI4STATICDELAY1__DataLine8 4
+#define R_SPI4STATICDELAY2 0x242
+#define O_SPI4STATICDELAY0__TxStat1 8
+#define W_SPI4STATICDELAY0__TxStat1 4
+#define O_SPI4STATICDELAY0__TxStat0 4
+#define W_SPI4STATICDELAY0__TxStat0 4
+#define O_SPI4STATICDELAY0__RxControl 0
+#define W_SPI4STATICDELAY0__RxControl 4
+#define R_SPI4CONTROL 0x243
+#define O_SPI4CONTROL__StaticDelay 2
+#define O_SPI4CONTROL__LVDS_LVTTL 1
+#define O_SPI4CONTROL__SPI4Enable 0
+#define R_CLASSWATERMARKS 0x244
+#define O_CLASSWATERMARKS__Class0Watermark 24
+#define W_CLASSWATERMARKS__Class0Watermark 5
+#define O_CLASSWATERMARKS__Class1Watermark 16
+#define W_CLASSWATERMARKS__Class1Watermark 5
+#define O_CLASSWATERMARKS__Class3Watermark 0
+#define W_CLASSWATERMARKS__Class3Watermark 5
+#define R_RXWATERMARKS1 0x245
+#define O_RXWATERMARKS__Rx0DataWatermark 24
+#define W_RXWATERMARKS__Rx0DataWatermark 7
+#define O_RXWATERMARKS__Rx1DataWatermark 16
+#define W_RXWATERMARKS__Rx1DataWatermark 7
+#define O_RXWATERMARKS__Rx3DataWatermark 0
+#define W_RXWATERMARKS__Rx3DataWatermark 7
+#define R_RXWATERMARKS2 0x246
+#define O_RXWATERMARKS__Rx4DataWatermark 24
+#define W_RXWATERMARKS__Rx4DataWatermark 7
+#define O_RXWATERMARKS__Rx5DataWatermark 16
+#define W_RXWATERMARKS__Rx5DataWatermark 7
+#define O_RXWATERMARKS__Rx6DataWatermark 8
+#define W_RXWATERMARKS__Rx6DataWatermark 7
+#define O_RXWATERMARKS__Rx7DataWatermark 0
+#define W_RXWATERMARKS__Rx7DataWatermark 7
+#define R_RXWATERMARKS3 0x247
+#define O_RXWATERMARKS__Rx8DataWatermark 24
+#define W_RXWATERMARKS__Rx8DataWatermark 7
+#define O_RXWATERMARKS__Rx9DataWatermark 16
+#define W_RXWATERMARKS__Rx9DataWatermark 7
+#define O_RXWATERMARKS__Rx10DataWatermark 8
+#define W_RXWATERMARKS__Rx10DataWatermark 7
+#define O_RXWATERMARKS__Rx11DataWatermark 0
+#define W_RXWATERMARKS__Rx11DataWatermark 7
+#define R_RXWATERMARKS4 0x248
+#define O_RXWATERMARKS__Rx12DataWatermark 24
+#define W_RXWATERMARKS__Rx12DataWatermark 7
+#define O_RXWATERMARKS__Rx13DataWatermark 16
+#define W_RXWATERMARKS__Rx13DataWatermark 7
+#define O_RXWATERMARKS__Rx14DataWatermark 8
+#define W_RXWATERMARKS__Rx14DataWatermark 7
+#define O_RXWATERMARKS__Rx15DataWatermark 0
+#define W_RXWATERMARKS__Rx15DataWatermark 7
+#define R_FREEWATERMARKS 0x249
+#define O_FREEWATERMARKS__FreeOutWatermark 16
+#define W_FREEWATERMARKS__FreeOutWatermark 16
+#define O_FREEWATERMARKS__JumFrWatermark 8
+#define W_FREEWATERMARKS__JumFrWatermark 7
+#define O_FREEWATERMARKS__RegFrWatermark 0
+#define W_FREEWATERMARKS__RegFrWatermark 7
+#define R_EGRESSFIFOCARVINGSLOTS 0x24a
+
+#define CTRL_RES0 0
+#define CTRL_RES1 1
+#define CTRL_REG_FREE 2
+#define CTRL_JUMBO_FREE 3
+#define CTRL_CONT 4
+#define CTRL_EOP 5
+#define CTRL_START 6
+#define CTRL_SNGL 7
+
+#define CTRL_B0_NOT_EOP 0
+#define CTRL_B0_EOP 1
+
+#define R_ROUND_ROBIN_TABLE 0
+#define R_PDE_CLASS_0 0x300
+#define R_PDE_CLASS_1 0x302
+#define R_PDE_CLASS_2 0x304
+#define R_PDE_CLASS_3 0x306
+
+#define R_MSG_TX_THRESHOLD 0x308
+
+#define R_GMAC_JFR0_BUCKET_SIZE 0x320
+#define R_GMAC_RFR0_BUCKET_SIZE 0x321
+#define R_GMAC_TX0_BUCKET_SIZE 0x322
+#define R_GMAC_TX1_BUCKET_SIZE 0x323
+#define R_GMAC_TX2_BUCKET_SIZE 0x324
+#define R_GMAC_TX3_BUCKET_SIZE 0x325
+#define R_GMAC_JFR1_BUCKET_SIZE 0x326
+#define R_GMAC_RFR1_BUCKET_SIZE 0x327
+
+#define R_XGS_TX0_BUCKET_SIZE 0x320
+#define R_XGS_TX1_BUCKET_SIZE 0x321
+#define R_XGS_TX2_BUCKET_SIZE 0x322
+#define R_XGS_TX3_BUCKET_SIZE 0x323
+#define R_XGS_TX4_BUCKET_SIZE 0x324
+#define R_XGS_TX5_BUCKET_SIZE 0x325
+#define R_XGS_TX6_BUCKET_SIZE 0x326
+#define R_XGS_TX7_BUCKET_SIZE 0x327
+#define R_XGS_TX8_BUCKET_SIZE 0x328
+#define R_XGS_TX9_BUCKET_SIZE 0x329
+#define R_XGS_TX10_BUCKET_SIZE 0x32A
+#define R_XGS_TX11_BUCKET_SIZE 0x32B
+#define R_XGS_TX12_BUCKET_SIZE 0x32C
+#define R_XGS_TX13_BUCKET_SIZE 0x32D
+#define R_XGS_TX14_BUCKET_SIZE 0x32E
+#define R_XGS_TX15_BUCKET_SIZE 0x32F
+#define R_XGS_JFR_BUCKET_SIZE 0x330
+#define R_XGS_RFR_BUCKET_SIZE 0x331
+
+#define R_CC_CPU0_0 0x380
+#define R_CC_CPU1_0 0x388
+#define R_CC_CPU2_0 0x390
+#define R_CC_CPU3_0 0x398
+#define R_CC_CPU4_0 0x3a0
+#define R_CC_CPU5_0 0x3a8
+#define R_CC_CPU6_0 0x3b0
+#define R_CC_CPU7_0 0x3b8
+
+#define XLR_GMAC_BLK_SZ (XLR_IO_GMAC_1_OFFSET - \
+ XLR_IO_GMAC_0_OFFSET)
+
+/* Constants used for configuring the devices */
+
+#define RGE_TX_THRESHOLD 1024
+#define RGE_TX_Q_SIZE 1024
+
+#define MAC_B2B_IPG 88
+
+/* frame sizes need to be cacheline aligned */
+#define MAX_FRAME_SIZE 1536
+#define MAX_FRAME_SIZE_JUMBO 9216
+#define RGE_TX_THRESHOLD_BYTES ETHER_MAX_LEN
+
+#define MAC_SKB_BACK_PTR_SIZE SMP_CACHE_BYTES
+#define MAC_PREPAD 0
+#define BYTE_OFFSET 2
+#define XLR_RX_BUF_SIZE (MAX_FRAME_SIZE + BYTE_OFFSET + \
+ MAC_PREPAD + MAC_SKB_BACK_PTR_SIZE + SMP_CACHE_BYTES)
+#define MAC_CRC_LEN 4
+#define MAX_NUM_MSGRNG_STN_CC 128
+#define MAX_MSG_SND_ATTEMPTS 100 /* 13 stns x 4 entry msg/stn +
+ headroom */
+
+#define MAC_FRIN_TO_BE_SENT_THRESHOLD 16
+
+#define MAX_NUM_DESC_SPILL 1024
+#define MAX_FRIN_SPILL (MAX_NUM_DESC_SPILL << 2)
+#define MAX_FROUT_SPILL (MAX_NUM_DESC_SPILL << 2)
+#define MAX_CLASS_0_SPILL (MAX_NUM_DESC_SPILL << 2)
+#define MAX_CLASS_1_SPILL (MAX_NUM_DESC_SPILL << 2)
+#define MAX_CLASS_2_SPILL (MAX_NUM_DESC_SPILL << 2)
+#define MAX_CLASS_3_SPILL (MAX_NUM_DESC_SPILL << 2)
+
+#define XLR_MAX_CORE 8
+
+#define XLR_MAX_NLNA 3
+#define XLR_MAX_MACS 8
+#define XLR_MAX_TX_FRAGS 14
+#define MAX_P2D_DESC_PER_PORT 512
+
+#define PHY_STATUS_RETRIES 25000
+
+
+/* Structs representing hardware data structures */
+struct size_1_desc {
+ uint64_t entry0;
+};
+
+struct size_2_desc {
+ uint64_t entry0;
+ uint64_t entry1;
+};
+
+struct size_3_desc {
+ uint64_t entry0;
+ uint64_t entry1;
+ uint64_t entry2;
+};
+
+struct size_4_desc {
+ uint64_t entry0;
+ uint64_t entry1;
+ uint64_t entry2;
+ uint64_t entry3;
+};
+
+struct fr_desc {
+ struct size_1_desc d1;
+};
+
+union rx_tx_desc {
+ struct size_2_desc d2;
+ /* struct size_3_desc d3; */
+ /* struct size_4_desc d4; */
+};
+
+
+extern unsigned char xlr_base_mac_addr[];
+
+/* Driver data structures and enums */
+
+typedef enum {
+ xlr_mac_speed_10, xlr_mac_speed_100,
+ xlr_mac_speed_1000, xlr_mac_speed_rsvd
+} xlr_mac_speed_t;
+
+typedef enum {
+ xlr_mac_duplex_auto, xlr_mac_duplex_half,
+ xlr_mac_duplex_full
+} xlr_mac_duplex_t;
+
+typedef enum {
+ xlr_mac_link_down,
+ xlr_mac_link_up,
+} xlr_mac_link_t;
+
+typedef enum {
+ xlr_mac_fc_auto, xlr_mac_fc_disabled, xlr_mac_fc_frame,
+ xlr_mac_fc_collision, xlr_mac_fc_carrier
+} xlr_mac_fc_t;
+
+enum {
+ SGMII_SPEED_10 = 0x00000000,
+ SGMII_SPEED_100 = 0x02000000,
+ SGMII_SPEED_1000 = 0x04000000,
+};
+
+struct nlge_softc;
+
+/*
+ * A data-structure to hold a set of related ports. The "sense" in which they
+ * are related is defined by the user of this data-structure.
+ *
+ * One example: a set of ports that are controlled thru a single MDIO line.
+ */
+struct nlge_port_set {
+ struct nlge_softc **port_vec;
+ uint32_t vec_sz;
+};
+
+/*
+ * nlna_softc has Network Accelerator (NA) attributes that are necessary to
+ * configure the h/w registers of this block. All the commmon configuration
+ * for a set of GMAC ports controlled by an NA is done from here.
+ */
+struct nlna_softc {
+ device_t nlna_dev;
+
+ uint32_t num_ports;
+ int na_type;
+ int mac_type;
+ xlr_reg_t *base;
+
+ struct fr_desc *frin_spill;
+ struct fr_desc *frout_spill;
+ union rx_tx_desc *class_0_spill;
+ union rx_tx_desc *class_1_spill;
+ union rx_tx_desc *class_2_spill;
+ union rx_tx_desc *class_3_spill;
+ uint32_t rfrbucket;
+ uint32_t station_id;
+
+ struct nlge_softc *child_sc[XLR_MAX_MACS];
+
+ /*
+ * Set of ports controlled/configured by the MII line
+ * of this network accelerator.
+ */
+ struct nlge_port_set mdio_set;
+ struct nlge_softc *mdio_sc[XLR_MAX_MACS];
+};
+
+struct nlge_softc {
+ struct ifnet *nlge_if; /* should be first member - cf.
+ mii.c:miibus_attach() */
+ struct mii_data nlge_mii;
+ struct nlge_port_set *mdio_pset;
+ device_t nlge_dev;
+ device_t mii_bus;
+ xlr_reg_t *base;
+ xlr_reg_t *mii_base;
+ xlr_reg_t *pcs_addr;
+ xlr_reg_t *serdes_addr;
+ int port_type;
+ xlr_mac_speed_t speed;
+ xlr_mac_duplex_t duplex;
+ xlr_mac_link_t link;
+ xlr_mac_fc_t flow_ctrl;
+ uint32_t id;
+ uint32_t instance;
+ uint32_t phy_addr;
+ uint32_t tx_bucket_id;
+ uint8_t dev_addr[ETHER_ADDR_LEN];
+ struct mtx sc_lock;
+};
+
+
+struct nlge_tx_desc {
+ uint64_t frag[XLR_MAX_TX_FRAGS + 2];
+};
+
+#define MAX_TX_RING_SIZE (XLR_MAX_MACS * MAX_P2D_DESC_PER_PORT *\
+ sizeof(struct p2d_tx_desc))
+
+#define NLGE_WRITE(base, off, val) xlr_write_reg(base, off, val)
+#define NLGE_READ(base, off) xlr_read_reg(base, off)
+#define NLGE_UPDATE(base, off, val, mask) \
+ do { \
+ uint32_t rd_val, wrt_val; \
+ rd_val = NLGE_READ(base, off); \
+ wrt_val = (rd_val & ~mask) | (val & mask); \
+ NLGE_WRITE(base, off, wrt_val); \
+ } while (0)
+
+#define NLGE_LOCK_INIT(_sc, _name) \
+ mtx_init(&(_sc)->sc_lock, _name, MTX_NETWORK_LOCK, MTX_DEF)
+#define NLGE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_lock)
+#define NLGE_LOCK(_sc) mtx_lock(&(_sc)->sc_lock)
+#define NLGE_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_lock)
+#define NLGE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_lock, MA_OWNED)
+
diff --git a/sys/mips/rmi/files.xlr b/sys/mips/rmi/files.xlr
index ace8442..e96fc43 100644
--- a/sys/mips/rmi/files.xlr
+++ b/sys/mips/rmi/files.xlr
@@ -21,6 +21,7 @@ mips/rmi/bus_space_rmi_pci.c standard
mips/rmi/dev/sec/rmisec.c optional rmisec
mips/rmi/dev/sec/rmilib.c optional rmisec
mips/rmi/dev/xlr/rge.c optional rge
+mips/rmi/dev/nlge/if_nlge.c optional nlge
dev/iicbus/xlr_rtc.c optional xlr_rtc
dev/iicbus/xlr_temperature.c optional xlr_temperature
dev/iicbus/xlr_eeprom.c optional xlr_eeprom
diff --git a/sys/mips/rmi/iodi.c b/sys/mips/rmi/iodi.c
index fc18732..be68564 100644
--- a/sys/mips/rmi/iodi.c
+++ b/sys/mips/rmi/iodi.c
@@ -108,13 +108,14 @@ iodi_setup_intr(device_t dev, device_t child,
struct resource *ires, int flags, driver_filter_t * filt,
driver_intr_t *intr, void *arg, void **cookiep)
{
+ const char *name = device_get_name(child);
- if (strcmp(device_get_name(child), "uart") == 0) {
+ if (strcmp(name, "uart") == 0) {
/* FIXME uart 1? */
cpu_establish_hardintr("uart", filt, intr, arg,
PIC_UART_0_IRQ, flags, cookiep);
pic_setup_intr(PIC_IRT_UART_0_INDEX, PIC_UART_0_IRQ, 0x1, 0);
- } else if (strcmp(device_get_name(child), "rge") == 0) {
+ } else if (strcmp(name, "rge") == 0 || strcmp(name, "nlge") == 0) {
int irq;
/* This is a hack to pass in the irq */
@@ -122,16 +123,15 @@ iodi_setup_intr(device_t dev, device_t child,
cpu_establish_hardintr("rge", filt, intr, arg, irq, flags,
cookiep);
pic_setup_intr(irq - PIC_IRQ_BASE, irq, 0x1, 0);
- } else if (strcmp(device_get_name(child), "ehci") == 0) {
+ } else if (strcmp(name, "ehci") == 0) {
cpu_establish_hardintr("ehci", filt, intr, arg, PIC_USB_IRQ, flags,
cookiep);
pic_setup_intr(PIC_USB_IRQ - PIC_IRQ_BASE, PIC_USB_IRQ, 0x1, 0);
- } else if (strcmp(device_get_name(child), "ata") == 0) {
+ } else if (strcmp(name, "ata") == 0) {
xlr_establish_intr("ata", filt, intr, arg, PIC_PCMCIA_IRQ, flags,
cookiep, bridge_pcmcia_ack);
pic_setup_intr(PIC_PCMCIA_IRQ - PIC_IRQ_BASE, PIC_PCMCIA_IRQ, 0x1, 0);
}
-
return (0);
}
@@ -194,6 +194,7 @@ iodi_activate_resource(device_t bus, device_t child, int type, int rid,
/* prototypes */
static int iodi_probe(device_t);
static int iodi_attach(device_t);
+static int iodi_detach(device_t);
static void iodi_identify(driver_t *, device_t);
int
@@ -213,6 +214,7 @@ int
iodi_attach(device_t dev)
{
device_t tmpd;
+ int i;
/*
* Attach each devices
@@ -268,17 +270,47 @@ iodi_attach(device_t dev)
tmpd = device_add_child(dev, "rge", 5);
device_set_ivars(tmpd, &xlr_board_info.gmac_block[1]);
#endif
- } else
- device_printf(dev, "Unknown type of gmac 1\n");
+ } else
+ device_printf(dev, "Unknown type of gmac 1\n");
+ }
+
+ /* This is to add the new GMAC driver. The above adds the old driver,
+ which has been retained for now as the new driver is stabilized.
+ The new driver is enabled with "option nlge". Make sure that only
+ one of rge or nlge is enabled in the conf file. */
+ for (i = 0; i < 3; i++) {
+ if (xlr_board_info.gmac_block[i].enabled == 0)
+ continue;
+ tmpd = device_add_child(dev, "nlna", i);
+ device_set_ivars(tmpd, &xlr_board_info.gmac_block[i]);
}
bus_generic_probe(dev);
bus_generic_attach(dev);
return 0;
}
+int
+iodi_detach(device_t dev)
+{
+ device_t nlna_dev;
+ int error, i, ret;
+
+ error = 0;
+ ret = 0;
+ for (i = 0; i < 3; i++) {
+ nlna_dev = device_find_child(dev, "nlna", i);
+ if (nlna_dev != NULL)
+ error = bus_generic_detach(nlna_dev);
+ if (error)
+ ret = error;
+ }
+ return ret;
+}
+
static device_method_t iodi_methods[] = {
DEVMETHOD(device_probe, iodi_probe),
DEVMETHOD(device_attach, iodi_attach),
+ DEVMETHOD(device_detach, iodi_detach),
DEVMETHOD(device_identify, iodi_identify),
DEVMETHOD(bus_alloc_resource, iodi_alloc_resource),
DEVMETHOD(bus_activate_resource, iodi_activate_resource),
OpenPOWER on IntegriCloud