From 51cf338feecb0df7abaab1235174501fe11e99c0 Mon Sep 17 00:00:00 2001 From: jchandra Date: Sat, 28 Aug 2010 19:02:51 +0000 Subject: 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 --- sys/mips/rmi/board.c | 456 ++++++-- sys/mips/rmi/board.h | 68 +- sys/mips/rmi/dev/nlge/if_nlge.c | 2444 +++++++++++++++++++++++++++++++++++++++ sys/mips/rmi/dev/nlge/if_nlge.h | 1180 +++++++++++++++++++ sys/mips/rmi/files.xlr | 1 + sys/mips/rmi/iodi.c | 46 +- 6 files changed, 4069 insertions(+), 126 deletions(-) create mode 100644 sys/mips/rmi/dev/nlge/if_nlge.c create mode 100644 sys/mips/rmi/dev/nlge/if_nlge.h (limited to 'sys/mips') 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 +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_KERNEL_OPTION_HEADERS +#include "opt_device_polling.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define __RMAN_RESOURCE_VISIBLE +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include /* for DELAY */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "miidevs.h" +#include +#include "miibus_if.h" + +#include + +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), -- cgit v1.1