summaryrefslogtreecommitdiffstats
path: root/sys/mips/cavium
diff options
context:
space:
mode:
authorjmallett <jmallett@FreeBSD.org>2010-07-20 19:25:11 +0000
committerjmallett <jmallett@FreeBSD.org>2010-07-20 19:25:11 +0000
commit3dc9275fe39c5d0fd860c4acac1ab1658a583004 (patch)
tree675a78e54a65a0fe4e3ea52b10a630f886aa4ffc /sys/mips/cavium
parentfd28c2f49567cb0767fe5a65f64d034603b1a775 (diff)
downloadFreeBSD-src-3dc9275fe39c5d0fd860c4acac1ab1658a583004.zip
FreeBSD-src-3dc9275fe39c5d0fd860c4acac1ab1658a583004.tar.gz
Update the port of FreeBSD to Cavium Octeon to use the Cavium Simple Executive
library: o) Increase inline unit / large function growth limits for MIPS to accommodate the needs of the Simple Executive, which uses a shocking amount of inlining. o) Remove TARGET_OCTEON and use CPU_CNMIPS to do things required by cnMIPS and the Octeon SoC. o) Add OCTEON_VENDOR_LANNER to use Lanner's allocation of vendor-specific board numbers, specifically to support the MR320. o) Add OCTEON_BOARD_CAPK_0100ND to hard-wire configuration for the CAPK-0100nd, which improperly uses an evaluation board's board number and breaks board detection at runtime. This board is sold by Portwell as the CAM-0100. o) Add support for the RTC available on some Octeon boards. o) Add support for the Octeon PCI bus. Note that rman_[sg]et_virtual for IO ports can not work unless building for n64. o) Clean up the CompactFlash driver to use Simple Executive macros and structures where possible (it would be advisable to use the Simple Executive API to set the PIO mode, too, but that is not done presently.) Also use structures from FreeBSD's ATA layer rather than structures copied from Linux. o) Print available Octeon SoC features on boot. o) Add support for the Octeon timecounter. o) Use the Simple Executive's routines rather than local copies for doing reads and writes to 64-bit addresses and use its macros for various device addresses rather than using local copies. o) Rename octeon_board_real to octeon_is_simulation to reduce differences with Cavium-provided code originally written for Linux. Also make it use the same simplified test that the Simple Executive and Linux both use rather than our complex one. o) Add support for the Octeon CIU, which is the main interrupt unit, as a bus to use normal interrupt allocation and setup routines. o) Use the Simple Executive's bootmem facility to allocate physical memory for the kernel, rather than assuming we know which addresses we can steal. NB: This may reduce the amount of RAM the kernel reports you as having if you are leaving large temporary allocations made by U-Boot allocated when starting FreeBSD. o) Add a port of the Cavium-provided Ethernet driver for Linux. This changes Ethernet interface naming from rgmxN to octeN. The new driver has vast improvements over the old one, both in performance and functionality, but does still have some features which have not been ported entirely and there may be unimplemented code that can be hit in everyday use. I will make every effort to correct those as they are reported. o) Support loading the kernel on non-contiguous cores. o) Add very conservative support for harvesting randomness from the Octeon random number device. o) Turn SMP on by default. o) Clean up the style of the Octeon kernel configurations a little and make them compile with -march=octeon. o) Add support for the Lanner MR320 and the CAPK-0100nd to the Simple Executive. o) Modify the Simple Executive to build on FreeBSD and to build without executive-config.h or cvmx-config.h. In the future we may want to revert part of these changes and supply executive-config.h and cvmx-config.h and access to the options contained in those files via kernel configuration files. o) Modify the Simple Executive USB routines to support getting and setting of the USB PID.
Diffstat (limited to 'sys/mips/cavium')
-rw-r--r--sys/mips/cavium/ciu.c359
-rw-r--r--sys/mips/cavium/cvmx_config.h194
-rw-r--r--sys/mips/cavium/dev/rgmii/octeon_fau.h220
-rw-r--r--sys/mips/cavium/dev/rgmii/octeon_fpa.c230
-rw-r--r--sys/mips/cavium/dev/rgmii/octeon_fpa.h259
-rw-r--r--sys/mips/cavium/dev/rgmii/octeon_ipd.c148
-rw-r--r--sys/mips/cavium/dev/rgmii/octeon_ipd.h204
-rw-r--r--sys/mips/cavium/dev/rgmii/octeon_pip.h219
-rw-r--r--sys/mips/cavium/dev/rgmii/octeon_pko.c378
-rw-r--r--sys/mips/cavium/dev/rgmii/octeon_pko.h332
-rw-r--r--sys/mips/cavium/dev/rgmii/octeon_rgmx.c2328
-rw-r--r--sys/mips/cavium/dev/rgmii/octeon_rgmx.h630
-rw-r--r--sys/mips/cavium/driveid.h298
-rw-r--r--sys/mips/cavium/files.octeon151
-rw-r--r--sys/mips/cavium/obio.c70
-rw-r--r--sys/mips/cavium/octe/cavium-ethernet.h94
-rw-r--r--sys/mips/cavium/octe/ethernet-common.c278
-rw-r--r--sys/mips/cavium/octe/ethernet-common.h52
-rw-r--r--sys/mips/cavium/octe/ethernet-defines.h101
-rw-r--r--sys/mips/cavium/octe/ethernet-headers.h43
-rw-r--r--sys/mips/cavium/octe/ethernet-mdio.c138
-rw-r--r--sys/mips/cavium/octe/ethernet-mdio.h40
-rw-r--r--sys/mips/cavium/octe/ethernet-mem.c207
-rw-r--r--sys/mips/cavium/octe/ethernet-mem.h33
-rw-r--r--sys/mips/cavium/octe/ethernet-rgmii.c359
-rw-r--r--sys/mips/cavium/octe/ethernet-rx.c410
-rw-r--r--sys/mips/cavium/octe/ethernet-rx.h37
-rw-r--r--sys/mips/cavium/octe/ethernet-sgmii.c135
-rw-r--r--sys/mips/cavium/octe/ethernet-spi.c309
-rw-r--r--sys/mips/cavium/octe/ethernet-tx.c398
-rw-r--r--sys/mips/cavium/octe/ethernet-tx.h34
-rw-r--r--sys/mips/cavium/octe/ethernet-util.h84
-rw-r--r--sys/mips/cavium/octe/ethernet-xaui.c134
-rw-r--r--sys/mips/cavium/octe/ethernet.c536
-rw-r--r--sys/mips/cavium/octe/octe.c515
-rw-r--r--sys/mips/cavium/octe/octebus.c123
-rw-r--r--sys/mips/cavium/octe/octebusvar.h41
-rw-r--r--sys/mips/cavium/octe/wrapper-cvmx-includes.h50
-rw-r--r--sys/mips/cavium/octeon_ds1337.c213
-rw-r--r--sys/mips/cavium/octeon_ebt3000_cf.c36
-rw-r--r--sys/mips/cavium/octeon_ebt3000_cf.h75
-rw-r--r--sys/mips/cavium/octeon_machdep.c701
-rw-r--r--sys/mips/cavium/octeon_mp.c39
-rw-r--r--sys/mips/cavium/octeon_pcmap_regs.h608
-rw-r--r--sys/mips/cavium/octeon_rnd.c137
-rw-r--r--sys/mips/cavium/octeon_rtc.c130
-rw-r--r--sys/mips/cavium/octopci.c402
-rw-r--r--sys/mips/cavium/octopci_bus_space.c583
-rw-r--r--sys/mips/cavium/octopcireg.h105
-rw-r--r--sys/mips/cavium/octopcivar.h35
-rw-r--r--sys/mips/cavium/std.octeon13
-rw-r--r--sys/mips/cavium/uart_bus_octeonusart.c9
-rw-r--r--sys/mips/cavium/uart_cpu_octeonusart.c23
-rw-r--r--sys/mips/cavium/uart_dev_oct16550.c19
54 files changed, 6683 insertions, 6506 deletions
diff --git a/sys/mips/cavium/ciu.c b/sys/mips/cavium/ciu.c
new file mode 100644
index 0000000..ee1dd4d
--- /dev/null
+++ b/sys/mips/cavium/ciu.c
@@ -0,0 +1,359 @@
+/*-
+ * Copyright (c) 2010 Juli Mallett <jmallett@FreeBSD.org>
+ * 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.
+ *
+ * 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$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/interrupt.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+
+#include <contrib/octeon-sdk/cvmx.h>
+#include <contrib/octeon-sdk/cvmx-interrupt.h>
+
+/*
+ * This bus sits between devices/buses and nexus and handles CIU interrupts
+ * and passes everything else through. It should really be a nexus subclass
+ * or something, but for now this will be sufficient.
+ */
+
+#define CIU_IRQ_HARD (0)
+
+#define CIU_IRQ_EN0_BEGIN CVMX_IRQ_WORKQ0
+#define CIU_IRQ_EN0_END CVMX_IRQ_BOOTDMA
+#define CIU_IRQ_EN0_COUNT ((CIU_IRQ_EN0_END - CIU_IRQ_EN0_BEGIN) + 1)
+
+#define CIU_IRQ_EN1_BEGIN CVMX_IRQ_WDOG0
+#define CIU_IRQ_EN1_END CVMX_IRQ_WDOG15
+#define CIU_IRQ_EN1_COUNT ((CIU_IRQ_EN1_END - CIU_IRQ_EN1_BEGIN) + 1)
+
+struct ciu_softc {
+ struct rman irq_rman;
+ struct resource *ciu_irq;
+};
+
+static mips_intrcnt_t ciu_en0_intrcnt[CIU_IRQ_EN0_COUNT];
+static mips_intrcnt_t ciu_en1_intrcnt[CIU_IRQ_EN1_COUNT];
+
+static struct intr_event *ciu_en0_intr_events[CIU_IRQ_EN0_COUNT];
+static struct intr_event *ciu_en1_intr_events[CIU_IRQ_EN1_COUNT];
+
+static int ciu_probe(device_t);
+static int ciu_attach(device_t);
+static struct resource *ciu_alloc_resource(device_t, device_t, int, int *,
+ u_long, u_long, u_long, u_int);
+static int ciu_setup_intr(device_t, device_t, struct resource *,
+ int, driver_filter_t *, driver_intr_t *,
+ void *, void **);
+static void ciu_hinted_child(device_t, const char *, int);
+
+static void ciu_en0_intr_mask(void *);
+static void ciu_en0_intr_unmask(void *);
+
+static void ciu_en1_intr_mask(void *);
+static void ciu_en1_intr_unmask(void *);
+
+static int ciu_intr(void *);
+
+static int
+ciu_probe(device_t dev)
+{
+ if (device_get_unit(dev) != 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "Cavium Octeon Central Interrupt Unit");
+ return (0);
+}
+
+static int
+ciu_attach(device_t dev)
+{
+ char name[MAXCOMLEN + 1];
+ struct ciu_softc *sc;
+ unsigned i;
+ int error;
+ int rid;
+
+ sc = device_get_softc(dev);
+
+ rid = 0;
+ sc->ciu_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, CIU_IRQ_HARD,
+ CIU_IRQ_HARD, 1, RF_ACTIVE);
+ if (sc->ciu_irq == NULL) {
+ device_printf(dev, "could not allocate irq%d\n", CIU_IRQ_HARD);
+ return (ENXIO);
+ }
+
+ error = bus_setup_intr(dev, sc->ciu_irq, INTR_TYPE_MISC, ciu_intr,
+ NULL, sc, NULL);
+ if (error != 0) {
+ device_printf(dev, "bus_setup_intr failed: %d\n", error);
+ return (error);
+ }
+
+ sc->irq_rman.rm_type = RMAN_ARRAY;
+ sc->irq_rman.rm_descr = "CIU IRQ";
+
+ error = rman_init(&sc->irq_rman);
+ if (error != 0)
+ return (error);
+
+ /*
+ * We have two contiguous IRQ regions, use a single rman.
+ */
+ error = rman_manage_region(&sc->irq_rman, CIU_IRQ_EN0_BEGIN,
+ CIU_IRQ_EN1_END);
+ if (error != 0)
+ return (error);
+
+ for (i = 0; i < CIU_IRQ_EN0_COUNT; i++) {
+ snprintf(name, sizeof name, "int%d:", i + CIU_IRQ_EN0_BEGIN);
+ ciu_en0_intrcnt[i] = mips_intrcnt_create(name);
+ }
+
+ for (i = 0; i < CIU_IRQ_EN1_COUNT; i++) {
+ snprintf(name, sizeof name, "int%d:", i + CIU_IRQ_EN1_BEGIN);
+ ciu_en1_intrcnt[i] = mips_intrcnt_create(name);
+ }
+
+ bus_generic_probe(dev);
+ bus_generic_attach(dev);
+
+ return (0);
+}
+
+static struct resource *
+ciu_alloc_resource(device_t bus, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct resource *res;
+ struct ciu_softc *sc;
+
+ sc = device_get_softc(bus);
+
+ switch (type) {
+ case SYS_RES_IRQ:
+ break;
+ default:
+ return (bus_alloc_resource(device_get_parent(bus), type, rid,
+ start, end, count, flags));
+ }
+
+ /*
+ * One interrupt at a time for now.
+ */
+ if (start != end)
+ return (NULL);
+
+ res = rman_reserve_resource(&sc->irq_rman, start, end, count, flags,
+ child);
+ if (res != NULL)
+ return (res);
+
+ return (NULL);
+}
+
+static int
+ciu_setup_intr(device_t bus, device_t child, struct resource *res, int flags,
+ driver_filter_t *filter, driver_intr_t *intr, void *arg,
+ void **cookiep)
+{
+ struct intr_event *event, **eventp;
+ void (*mask_func)(void *);
+ void (*unmask_func)(void *);
+ mips_intrcnt_t intrcnt;
+ int error;
+ int irq;
+
+ irq = rman_get_start(res);
+ if (irq <= CIU_IRQ_EN0_END) {
+ eventp = &ciu_en0_intr_events[irq - CIU_IRQ_EN0_BEGIN];
+ intrcnt = ciu_en0_intrcnt[irq - CIU_IRQ_EN0_BEGIN];
+ mask_func = ciu_en0_intr_mask;
+ unmask_func = ciu_en0_intr_unmask;
+ } else {
+ eventp = &ciu_en1_intr_events[irq - CIU_IRQ_EN1_BEGIN];
+ intrcnt = ciu_en1_intrcnt[irq - CIU_IRQ_EN1_BEGIN];
+ mask_func = ciu_en1_intr_mask;
+ unmask_func = ciu_en1_intr_unmask;
+ }
+
+ if ((event = *eventp) == NULL) {
+ error = intr_event_create(eventp, (void *)(uintptr_t)irq, 0,
+ irq, mask_func, unmask_func, NULL, NULL, "int%d", irq);
+ if (error != 0)
+ return (error);
+
+ event = *eventp;
+
+ unmask_func((void *)(uintptr_t)irq);
+ }
+
+ intr_event_add_handler(event, device_get_nameunit(child),
+ filter, intr, arg, intr_priority(flags), flags, cookiep);
+
+ mips_intrcnt_setname(intrcnt, event->ie_fullname);
+
+ return (0);
+}
+
+static void
+ciu_hinted_child(device_t bus, const char *dname, int dunit)
+{
+ BUS_ADD_CHILD(bus, 0, dname, dunit);
+}
+
+static void
+ciu_en0_intr_mask(void *arg)
+{
+ uint64_t mask;
+ int irq;
+
+ irq = (uintptr_t)arg;
+ mask = cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2));
+ mask &= ~(1ull << (irq - CIU_IRQ_EN0_BEGIN));
+ cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2), mask);
+}
+
+static void
+ciu_en0_intr_unmask(void *arg)
+{
+ uint64_t mask;
+ int irq;
+
+ irq = (uintptr_t)arg;
+ mask = cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2));
+ mask |= 1ull << (irq - CIU_IRQ_EN0_BEGIN);
+ cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2), mask);
+}
+
+static void
+ciu_en1_intr_mask(void *arg)
+{
+ uint64_t mask;
+ int irq;
+
+ irq = (uintptr_t)arg;
+ mask = cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num()*2));
+ mask &= ~(1ull << (irq - CIU_IRQ_EN1_BEGIN));
+ cvmx_write_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num()*2), mask);
+}
+
+static void
+ciu_en1_intr_unmask(void *arg)
+{
+ uint64_t mask;
+ int irq;
+
+ irq = (uintptr_t)arg;
+ mask = cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num()*2));
+ mask |= 1ull << (irq - CIU_IRQ_EN1_BEGIN);
+ cvmx_write_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num()*2), mask);
+}
+
+static int
+ciu_intr(void *arg)
+{
+ struct ciu_softc *sc;
+ uint64_t en0_sum, en1_sum;
+ uint64_t en0_mask, en1_mask;
+ int irq_index;
+ int error;
+
+ sc = arg;
+ (void)sc;
+
+ en0_sum = cvmx_read_csr(CVMX_CIU_INTX_SUM0(cvmx_get_core_num()*2));
+ en1_sum = cvmx_read_csr(CVMX_CIU_INT_SUM1);
+
+ en0_mask = cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2));
+ en1_mask = cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num()*2));
+
+ en0_sum &= en0_mask;
+ en1_sum &= en1_mask;
+
+ if (en0_sum == 0 && en1_sum == 0)
+ return (FILTER_STRAY);
+
+ irq_index = 0;
+ for (irq_index = 0; en0_sum != 0; irq_index++, en0_sum >>= 1) {
+ if ((en0_sum & 1) == 0)
+ continue;
+
+ mips_intrcnt_inc(ciu_en0_intrcnt[irq_index]);
+
+ error = intr_event_handle(ciu_en0_intr_events[irq_index], NULL);
+ if (error != 0)
+ printf("%s: stray en0 irq%d\n", __func__, irq_index);
+ }
+
+ irq_index = 0;
+ for (irq_index = 0; en1_sum != 0; irq_index++, en1_sum >>= 1) {
+ if ((en1_sum & 1) == 0)
+ continue;
+
+ mips_intrcnt_inc(ciu_en1_intrcnt[irq_index]);
+
+ error = intr_event_handle(ciu_en1_intr_events[irq_index], NULL);
+ if (error != 0)
+ printf("%s: stray en1 irq%d\n", __func__, irq_index);
+ }
+
+ return (FILTER_HANDLED);
+}
+
+static device_method_t ciu_methods[] = {
+ DEVMETHOD(device_probe, ciu_probe),
+ DEVMETHOD(device_attach, ciu_attach),
+
+ DEVMETHOD(bus_alloc_resource, ciu_alloc_resource),
+ DEVMETHOD(bus_activate_resource,bus_generic_activate_resource),
+ DEVMETHOD(bus_setup_intr, ciu_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+
+ DEVMETHOD(bus_add_child, bus_generic_add_child),
+ DEVMETHOD(bus_hinted_child, ciu_hinted_child),
+
+ { 0, 0 }
+};
+
+static driver_t ciu_driver = {
+ "ciu",
+ ciu_methods,
+ sizeof(struct ciu_softc),
+};
+static devclass_t ciu_devclass;
+DRIVER_MODULE(ciu, nexus, ciu_driver, ciu_devclass, 0, 0);
diff --git a/sys/mips/cavium/cvmx_config.h b/sys/mips/cavium/cvmx_config.h
new file mode 100644
index 0000000..7dd2c63
--- /dev/null
+++ b/sys/mips/cavium/cvmx_config.h
@@ -0,0 +1,194 @@
+/***********************license start***************
+ * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
+ * reserved.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * 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.
+ *
+ * * Neither the name of Cavium Networks nor the names of
+ * its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written
+ * permission.
+ *
+ * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+ * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
+ * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
+ * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
+ * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
+ * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
+ * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
+ * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
+ * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT
+ * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+ *
+ *
+ * For any questions regarding licensing please contact marketing@caviumnetworks.com
+ *
+ ***********************license end**************************************/
+/* $FreeBSD$ */
+
+#ifndef _CVMX_CONFIG_H
+#define _CVMX_CONFIG_H
+
+#include "opt_cvmx.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/pmap.h>
+#include <machine/stdarg.h>
+
+#define asm __asm
+
+#define CVMX_DONT_INCLUDE_CONFIG
+
+/* Define to enable the use of simple executive packet output functions.
+** For packet I/O setup enable the helper functions below.
+*/
+#define CVMX_ENABLE_PKO_FUNCTIONS
+
+/* Define to enable the use of simple executive helper functions. These
+** include many harware setup functions. See cvmx-helper.[ch] for
+** details.
+*/
+#define CVMX_ENABLE_HELPER_FUNCTIONS
+
+/* CVMX_HELPER_FIRST_MBUFF_SKIP is the number of bytes to reserve before
+** the beginning of the packet. If necessary, override the default
+** here. See the IPD section of the hardware manual for MBUFF SKIP
+** details.*/
+#define CVMX_HELPER_FIRST_MBUFF_SKIP 184
+
+/* CVMX_HELPER_NOT_FIRST_MBUFF_SKIP is the number of bytes to reserve in each
+** chained packet element. If necessary, override the default here */
+#define CVMX_HELPER_NOT_FIRST_MBUFF_SKIP 0
+
+/* CVMX_HELPER_ENABLE_BACK_PRESSURE controls whether back pressure is enabled
+** for all input ports. This controls if IPD sends backpressure to all ports if
+** Octeon's FPA pools don't have enough packet or work queue entries. Even when
+** this is off, it is still possible to get backpressure from individual
+** hardware ports. When configuring backpressure, also check
+** CVMX_HELPER_DISABLE_*_BACKPRESSURE below. If necessary, override the default
+** here */
+#define CVMX_HELPER_ENABLE_BACK_PRESSURE 1
+
+/* CVMX_HELPER_ENABLE_IPD controls if the IPD is enabled in the helper
+** function. Once it is enabled the hardware starts accepting packets. You
+** might want to skip the IPD enable if configuration changes are need
+** from the default helper setup. If necessary, override the default here */
+#define CVMX_HELPER_ENABLE_IPD 1
+
+/* CVMX_HELPER_INPUT_TAG_TYPE selects the type of tag that the IPD assigns
+** to incoming packets. */
+#define CVMX_HELPER_INPUT_TAG_TYPE CVMX_POW_TAG_TYPE_ORDERED
+
+/* The following select which fields are used by the PIP to generate
+** the tag on INPUT
+** 0: don't include
+** 1: include */
+#define CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP 0
+#define CVMX_HELPER_INPUT_TAG_IPV6_DST_IP 0
+#define CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT 0
+#define CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT 0
+#define CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER 0
+#define CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP 0
+#define CVMX_HELPER_INPUT_TAG_IPV4_DST_IP 0
+#define CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT 0
+#define CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT 0
+#define CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL 0
+#define CVMX_HELPER_INPUT_TAG_INPUT_PORT 1
+
+/* Select skip mode for input ports */
+#define CVMX_HELPER_INPUT_PORT_SKIP_MODE CVMX_PIP_PORT_CFG_MODE_SKIPL2
+
+/* Define the number of queues per output port */
+#define CVMX_HELPER_PKO_QUEUES_PER_PORT_INTERFACE0 1
+#define CVMX_HELPER_PKO_QUEUES_PER_PORT_INTERFACE1 1
+
+/* Configure PKO to use per-core queues (PKO lockless operation).
+** Please see the related SDK documentation for PKO that illustrates
+** how to enable and configure this option. */
+//#define CVMX_ENABLE_PKO_LOCKLESS_OPERATION 1
+//#define CVMX_HELPER_PKO_MAX_PORTS_INTERFACE0 8
+//#define CVMX_HELPER_PKO_MAX_PORTS_INTERFACE1 8
+
+/* Force backpressure to be disabled. This overrides all other
+** backpressure configuration */
+#define CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE 1
+
+/* Disable the SPI4000's processing of backpressure packets and backpressure
+** generation. When this is 1, the SPI4000 will not stop sending packets when
+** receiving backpressure. It will also not generate backpressure packets when
+** its internal FIFOs are full. */
+#define CVMX_HELPER_DISABLE_SPI4000_BACKPRESSURE 1
+
+/* CVMX_HELPER_SPI_TIMEOUT is used to determine how long the SPI initialization
+** routines wait for SPI training. You can override the value using
+** executive-config.h if necessary */
+#define CVMX_HELPER_SPI_TIMEOUT 10
+
+/* Select the number of low latency memory ports (interfaces) that
+** will be configured. Valid values are 1 and 2.
+*/
+#define CVMX_LLM_CONFIG_NUM_PORTS 2
+
+/* Enable the fix for PKI-100 errata ("Size field is 8 too large in WQE and next
+** pointers"). If CVMX_ENABLE_LEN_M8_FIX is set to 0, the fix for this errata will
+** not be enabled.
+** 0: Fix is not enabled
+** 1: Fix is enabled, if supported by hardware
+*/
+#define CVMX_ENABLE_LEN_M8_FIX 1
+
+#if defined(CVMX_ENABLE_HELPER_FUNCTIONS) && !defined(CVMX_ENABLE_PKO_FUNCTIONS)
+#define CVMX_ENABLE_PKO_FUNCTIONS
+#endif
+
+/************************* Config Specific Defines ************************/
+#define CVMX_LLM_NUM_PORTS 1
+#define CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 1 /**< PKO queues per port for interface 0 (ports 0-15) */
+#define CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 1 /**< PKO queues per port for interface 1 (ports 16-31) */
+#define CVMX_PKO_MAX_PORTS_INTERFACE0 CVMX_HELPER_PKO_MAX_PORTS_INTERFACE0 /**< Limit on the number of PKO ports enabled for interface 0 */
+#define CVMX_PKO_MAX_PORTS_INTERFACE1 CVMX_HELPER_PKO_MAX_PORTS_INTERFACE1 /**< Limit on the number of PKO ports enabled for interface 1 */
+#define CVMX_PKO_QUEUES_PER_PORT_PCI 1 /**< PKO queues per port for PCI (ports 32-35) */
+#define CVMX_PKO_QUEUES_PER_PORT_LOOP 1 /**< PKO queues per port for Loop devices (ports 36-39) */
+
+/************************* FPA allocation *********************************/
+/* Pool sizes in bytes, must be multiple of a cache line */
+#define CVMX_FPA_POOL_0_SIZE (15 * CVMX_CACHE_LINE_SIZE)
+#define CVMX_FPA_POOL_1_SIZE (1 * CVMX_CACHE_LINE_SIZE)
+#define CVMX_FPA_POOL_2_SIZE (8 * CVMX_CACHE_LINE_SIZE)
+#define CVMX_FPA_POOL_3_SIZE (0 * CVMX_CACHE_LINE_SIZE)
+#define CVMX_FPA_POOL_4_SIZE (0 * CVMX_CACHE_LINE_SIZE)
+#define CVMX_FPA_POOL_5_SIZE (0 * CVMX_CACHE_LINE_SIZE)
+#define CVMX_FPA_POOL_6_SIZE (0 * CVMX_CACHE_LINE_SIZE)
+#define CVMX_FPA_POOL_7_SIZE (0 * CVMX_CACHE_LINE_SIZE)
+
+/* Pools in use */
+#define CVMX_FPA_PACKET_POOL (0) /**< Packet buffers */
+#define CVMX_FPA_PACKET_POOL_SIZE CVMX_FPA_POOL_0_SIZE
+#define CVMX_FPA_WQE_POOL (1) /**< Work queue entrys */
+#define CVMX_FPA_WQE_POOL_SIZE CVMX_FPA_POOL_1_SIZE
+#define CVMX_FPA_OUTPUT_BUFFER_POOL (2) /**< PKO queue command buffers */
+#define CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE CVMX_FPA_POOL_2_SIZE
+
+/************************* FAU allocation ********************************/
+#define CVMX_FAU_REG_END 2048
+
+#define CVMX_SCR_SCRATCH 0
+
+#endif /* !_CVMX_CONFIG_H */
diff --git a/sys/mips/cavium/dev/rgmii/octeon_fau.h b/sys/mips/cavium/dev/rgmii/octeon_fau.h
deleted file mode 100644
index acf5132..0000000
--- a/sys/mips/cavium/dev/rgmii/octeon_fau.h
+++ /dev/null
@@ -1,220 +0,0 @@
-/***********************license start***************
- * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
- * reserved.
- *
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * 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.
- *
- * * Neither the name of Cavium Networks nor the names of
- * its contributors may be used to endorse or promote products
- * derived from this software without specific prior written
- * permission.
- *
- * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
- * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
- * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
- * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
- * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
- * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
- * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
- * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
- * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT
- * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
- *
- *
- * For any questions regarding licensing please contact marketing@caviumnetworks.com
- *
- ***********************license end**************************************/
-
-/* $FreeBSD$ */
-
-/*------------------------------------------------------------------
- * octeon_fau.h Fetch & Add Unit
- *
- *------------------------------------------------------------------
- */
-
-
-#ifndef ___OCTEON_FAU__H___
-#define ___OCTEON_FAU__H___
-
-
-
-
-typedef enum {
- OCTEON_FAU_OP_SIZE_8 = 0,
- OCTEON_FAU_OP_SIZE_16 = 1,
- OCTEON_FAU_OP_SIZE_32 = 2,
- OCTEON_FAU_OP_SIZE_64 = 3
-} octeon_fau_op_size_t;
-
-
-
-#define OCTEON_FAU_LOAD_IO_ADDRESS octeon_build_io_address(0x1e, 0)
-#define OCTEON_FAU_BITS_SCRADDR 63,56
-#define OCTEON_FAU_BITS_LEN 55,48
-#define OCTEON_FAU_BITS_INEVAL 35,14
-#define OCTEON_FAU_BITS_TAGWAIT 13,13
-#define OCTEON_FAU_BITS_NOADD 13,13
-#define OCTEON_FAU_BITS_SIZE 12,11
-#define OCTEON_FAU_BITS_REGISTER 10,0
-
-#define OCTEON_FAU_REG_64_ADDR(x) ((x <<3) + OCTEON_FAU_REG_64_START)
-typedef enum
-{
- OCTEON_FAU_REG_64_START = 0,
- OCTEON_FAU_REG_OQ_ADDR_INDEX = OCTEON_FAU_REG_64_ADDR(0),
- OCTEON_FAU_REG_OQ_ADDR_END = OCTEON_FAU_REG_64_ADDR(31),
- OCTEON_FAU_REG_64_END = OCTEON_FAU_REG_64_ADDR(39),
-} octeon_fau_reg_64_t;
-
-#define OCTEON_FAU_REG_32_ADDR(x) ((x <<2) + OCTEON_FAU_REG_32_START)
-typedef enum
-{
- OCTEON_FAU_REG_32_START = OCTEON_FAU_REG_64_END,
- OCTEON_FAU_REG_32_END = OCTEON_FAU_REG_32_ADDR(0),
-} octeon_fau_reg_32_t;
-
-
-
-/*
- * octeon_fau_atomic_address
- *
- * Builds a I/O address for accessing the FAU
- *
- * @param tagwait Should the atomic add wait for the current tag switch
- * operation to complete.
- * - 0 = Don't wait
- * - 1 = Wait for tag switch to complete
- * @param reg FAU atomic register to access. 0 <= reg < 4096.
- * - Step by 2 for 16 bit access.
- * - Step by 4 for 32 bit access.
- * - Step by 8 for 64 bit access.
- * @param value Signed value to add.
- * Note: When performing 32 and 64 bit access, only the low
- * 22 bits are available.
- * @return Address to read from for atomic update
- */
-static inline uint64_t octeon_fau_atomic_address (uint64_t tagwait, uint64_t reg,
- int64_t value)
-{
- return (OCTEON_ADD_IO_SEG(OCTEON_FAU_LOAD_IO_ADDRESS) |
- octeon_build_bits(OCTEON_FAU_BITS_INEVAL, value) |
- octeon_build_bits(OCTEON_FAU_BITS_TAGWAIT, tagwait) |
- octeon_build_bits(OCTEON_FAU_BITS_REGISTER, reg));
-}
-
-
-/*
- * octeon_fau_store_address
- *
- * Builds a store I/O address for writing to the FAU
- *
- * noadd 0 = Store value is atomically added to the current value
- * 1 = Store value is atomically written over the current value
- * reg FAU atomic register to access. 0 <= reg < 4096.
- * - Step by 2 for 16 bit access.
- * - Step by 4 for 32 bit access.
- * - Step by 8 for 64 bit access.
- * Returns Address to store for atomic update
- */
-static inline uint64_t octeon_fau_store_address (uint64_t noadd, uint64_t reg)
-{
- return (OCTEON_ADD_IO_SEG(OCTEON_FAU_LOAD_IO_ADDRESS) |
- octeon_build_bits(OCTEON_FAU_BITS_NOADD, noadd) |
- octeon_build_bits(OCTEON_FAU_BITS_REGISTER, reg));
-}
-
-
-/*
- * octeon_fau_atomic_add32
- *
- * Perform an atomic 32 bit add
- *
- * @param reg FAU atomic register to access. 0 <= reg < 4096.
- * - Step by 4 for 32 bit access.
- * @param value Signed value to add.
- */
-static inline void octeon_fau_atomic_add32 (octeon_fau_reg_32_t reg, int32_t value)
-{
- oct_write32(octeon_fau_store_address(0, reg), value);
-}
-
-/*
- * octeon_fau_fetch_and_add
- *
- * reg FAU atomic register to access. 0 <= reg < 4096.
- * - Step by 8 for 64 bit access.
- * value Signed value to add.
- * Note: Only the low 22 bits are available.
- * returns Value of the register before the update
- */
-static inline int64_t octeon_fau_fetch_and_add64 (octeon_fau_reg_64_t reg,
- int64_t val64)
-{
-
- return (oct_read64(octeon_fau_atomic_address(0, reg, val64)));
-}
-
-/*
- * octeon_fau_fetch_and_add32
- *
- * reg FAU atomic register to access. 0 <= reg < 4096.
- * - Step by 8 for 64 bit access.
- * value Signed value to add.
- * Note: Only the low 22 bits are available.
- * returns Value of the register before the update
- */
-static inline int32_t octeon_fau_fetch_and_add32 (octeon_fau_reg_64_t reg,
- int32_t val32)
-{
- return (oct_read32(octeon_fau_atomic_address(0, reg, val32)));
-}
-
-/*
- * octeon_fau_atomic_write32
- *
- * Perform an atomic 32 bit write
- *
- * @param reg FAU atomic register to access. 0 <= reg < 4096.
- * - Step by 4 for 32 bit access.
- * @param value Signed value to write.
- */
-static inline void octeon_fau_atomic_write32(octeon_fau_reg_32_t reg, int32_t value)
-{
- oct_write32(octeon_fau_store_address(1, reg), value);
-}
-
-
-/*
- * octeon_fau_atomic_write64
- *
- * Perform an atomic 32 bit write
- *
- * reg FAU atomic register to access. 0 <= reg < 4096.
- * - Step by 8 for 64 bit access.
- * value Signed value to write.
- */
-static inline void octeon_fau_atomic_write64 (octeon_fau_reg_64_t reg, int64_t value)
-{
- oct_write64(octeon_fau_store_address(1, reg), value);
-}
-
-
-static inline void octeon_fau_atomic_add64 (octeon_fau_reg_64_t reg, int64_t value)
-{
- oct_write64_int64(octeon_fau_store_address(0, reg), value);
-}
-
-
-#endif /* ___OCTEON_FAU__H___ */
diff --git a/sys/mips/cavium/dev/rgmii/octeon_fpa.c b/sys/mips/cavium/dev/rgmii/octeon_fpa.c
deleted file mode 100644
index 3e43a88..0000000
--- a/sys/mips/cavium/dev/rgmii/octeon_fpa.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/***********************license start***************
- * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
- * reserved.
- *
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * 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.
- *
- * * Neither the name of Cavium Networks nor the names of
- * its contributors may be used to endorse or promote products
- * derived from this software without specific prior written
- * permission.
- *
- * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
- * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
- * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
- * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
- * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
- * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
- * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
- * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
- * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT
- * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
- *
- *
- * For any questions regarding licensing please contact marketing@caviumnetworks.com
- *
- ***********************license end**************************************/
-
-/*------------------------------------------------------------------
- * octeon_fpa.c Free Pool Allocator
- *
- *------------------------------------------------------------------
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <vm/vm.h>
-#include <vm/pmap.h>
-
-
-#include <mips/cavium/octeon_pcmap_regs.h>
-#include "octeon_fpa.h"
-
-
-#define FPA_DEBUG 1
-
-/*
- * octeon_dump_fpa
- *
- */
-void octeon_dump_fpa (void)
-{
- int i;
- octeon_fpa_ctl_status_t status;
- octeon_fpa_queue_available_t q_avail;
-
- status.word64 = oct_read64(OCTEON_FPA_CTL_STATUS);
- if (!status.bits.enb) {
- printf("\n FPA Disabled");
- /*
- * No dumping if disabled
- */
- return;
- }
- printf(" FPA Ctrl-Status-reg 0x%llX := 0x%llX EN %X M1_E %X M0_E %X\n",
- OCTEON_FPA_CTL_STATUS, (unsigned long long)status.word64,
- status.bits.enb, status.bits.mem1_err, status.bits.mem0_err);
- for (i = 0; i < OCTEON_FPA_QUEUES; i++) {
- printf(" Pool: %d\n", i);
-
- q_avail.word64 = oct_read64((OCTEON_FPA_QUEUE_AVAILABLE + (i)*8ull));
- printf(" Avail-reg 0x%llX := Size: 0x%X\n",
- (OCTEON_FPA_QUEUE_AVAILABLE + (i)*8ull), q_avail.bits.queue_size);
- }
-}
-
-void octeon_dump_fpa_pool (u_int pool)
-{
- octeon_fpa_ctl_status_t status;
- octeon_fpa_queue_available_t q_avail;
-
- status.word64 = oct_read64(OCTEON_FPA_CTL_STATUS);
- if (!status.bits.enb) {
- printf("\n FPA Disabled");
- /*
- * No dumping if disabled
- */
- return;
- }
- printf(" FPA Ctrl-Status-reg 0x%llX := 0x%llX EN %X M1_E %X M0_E %X\n",
- OCTEON_FPA_CTL_STATUS, (unsigned long long)status.word64,
- status.bits.enb, status.bits.mem1_err, status.bits.mem0_err);
- q_avail.word64 = oct_read64((OCTEON_FPA_QUEUE_AVAILABLE + (pool)*8ull));
- printf(" FPA Pool: %u Avail-reg 0x%llX := Size: 0x%X\n", pool,
- (OCTEON_FPA_QUEUE_AVAILABLE + (pool)*8ull), q_avail.bits.queue_size);
-}
-
-
-u_int octeon_fpa_pool_size (u_int pool)
-{
- octeon_fpa_queue_available_t q_avail;
- u_int size = 0;
-
- if (pool < 7) {
- q_avail.word64 = oct_read64((OCTEON_FPA_QUEUE_AVAILABLE + (pool)*8ull));
- size = q_avail.bits.queue_size;
- }
- return (size);
-}
-
-
-/*
- * octeon_enable_fpa
- *
- * configure fpa with defaults and then mark it enabled.
- */
-void octeon_enable_fpa (void)
-{
- int i;
- octeon_fpa_ctl_status_t status;
- octeon_fpa_fpf_marks_t marks;
-
- for (i = 0; i < OCTEON_FPA_QUEUES; i++) {
- marks.word64 = oct_read64((OCTEON_FPA_FPF_MARKS + (i)*8ull));
-
- marks.bits.fpf_wr = 0xe0;
- oct_write64((OCTEON_FPA_FPF_MARKS + (i)*8ull), marks.word64);
- }
-
- /* Enforce a 10 cycle delay between config and enable */
- octeon_wait(10);
-
- status.word64 = 0;
- status.bits.enb = 1;
- oct_write64(OCTEON_FPA_CTL_STATUS, status.word64);
-}
-
-
-#define FPA_DEBUG_TERSE 1
-
-/*
- * octeon_fpa_fill_pool_mem
- *
- * Fill the specified FPA pool with elem_num number of
- * elements of size elem_size_words * 8
- */
-void octeon_fpa_fill_pool_mem (u_int pool, u_int elem_size_words, u_int elem_num)
-{
- void *memory;
- u_int bytes, elem_size_bytes;
- u_int block_size;
-
-#ifdef FPA_DEBUG
- u_int elems = elem_num;
- printf(" FPA fill: Pool %u elem_size_words %u Num: %u\n", pool, elem_size_words, elem_num);
-#endif
- elem_size_bytes = elem_size_words * sizeof(uint64_t);
- block_size = OCTEON_ALIGN(elem_size_bytes);
-
-// block_size = ((elem_size_bytes / OCTEON_FPA_POOL_ALIGNMENT) + 1) * OCTEON_FPA_POOL_ALIGNMENT;
-
- bytes = (elem_num * block_size);
-
-#ifdef FPA_DEBUG
- printf(" elem_size_bytes = words * 8 = %u; block_size %u\n", elem_size_bytes, block_size);
-#endif
-
-
-#ifdef FPA_DEBUG
- int block = 0;
-
- printf(" %% Filling Pool %u with %u blocks of %u bytes %u words\n",
- pool, elem_num, elem_size_bytes, elem_size_words);
-#endif
-
-// memory = malloc(bytes, M_DEVBUF, M_NOWAIT | M_ZERO);
- memory = contigmalloc(bytes, M_DEVBUF, M_NOWAIT | M_ZERO,
- 0, 0x20000000,
- OCTEON_FPA_POOL_ALIGNMENT, 0);
-
- if (memory == NULL) {
- printf(" %% FPA pool %u could not be filled with %u bytes\n",
- pool, bytes);
- return;
- }
-
- /*
- * Forward Align allocated mem to needed alignment. Don't worry about growth, we
- * already preallocated extra
- */
-#ifdef FPA_DEBUG
- printf(" %% Huge MemBlock %p Bytes %u\n", memory, bytes);
-#endif
-
- memory = (void *) OCTEON_ALIGN(memory);
-
-#ifdef FPA_DEBUG_TERSE
- printf("FPA fill: %u Count: %u SizeBytes: %u SizeBytesAligned: %u 1st: %p = %p\n",
- pool, elem_num, elem_size_bytes, block_size, memory,
- (void *)(intptr_t)OCTEON_PTR2PHYS(memory));
-#endif
-
-// memory = (void *) ((((u_int) memory / OCTEON_FPA_POOL_ALIGNMENT) + 1) * OCTEON_FPA_POOL_ALIGNMENT);
-
- while (elem_num--) {
-#ifdef FPA_DEBUG
- if (((elems - elem_num) < 4) || (elem_num < 4))
- printf(" %% Block %d: %p Phys %p Bytes %u\n", block, memory,
- (void *)(intptr_t)OCTEON_PTR2PHYS(memory), elem_size_bytes);
- block++;
-#endif
- octeon_fpa_free(memory, pool, 0);
- memory = (void *) (((u_long) memory) + block_size);
- }
-}
-
diff --git a/sys/mips/cavium/dev/rgmii/octeon_fpa.h b/sys/mips/cavium/dev/rgmii/octeon_fpa.h
deleted file mode 100644
index 33d273b..0000000
--- a/sys/mips/cavium/dev/rgmii/octeon_fpa.h
+++ /dev/null
@@ -1,259 +0,0 @@
-/***********************license start***************
- * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
- * reserved.
- *
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * 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.
- *
- * * Neither the name of Cavium Networks nor the names of
- * its contributors may be used to endorse or promote products
- * derived from this software without specific prior written
- * permission.
- *
- * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
- * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
- * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
- * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
- * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
- * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
- * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
- * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
- * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT
- * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
- *
- *
- * For any questions regarding licensing please contact marketing@caviumnetworks.com
- *
- ***********************license end**************************************/
-
-/* $FreeBSD$ */
-
-/*------------------------------------------------------------------
- * octeon_fpa.h Free Pool Allocator
- *
- *------------------------------------------------------------------
- */
-
-
-#ifndef ___OCTEON_FPA__H___
-#define ___OCTEON_FPA__H___
-
-
-#define OCTEON_FPA_FPA_OUTPUT_BUFFER_POOL 2 /* Same in octeon_rgmx.h */
-
-
-/*
- * OCTEON_FPA_FPF_MARKS = FPA's Queue Free Page FIFO Read Write Marks
- *
- * The high and low watermark register that determines when we write and
- * read free pages from L2C for Queue.
- */
-typedef union {
- uint64_t word64;
- struct {
- uint64_t reserved : 42; /* Must be zero */
- uint64_t fpf_wr : 11; /* Write Hi Water mark */
- uint64_t fpf_rd : 11; /* Read Lo Water mark */
- } bits;
-} octeon_fpa_fpf_marks_t;
-
-
-/*
- * OCTEON_FPA_CTL_STATUS = FPA's Control/Status Register
- *
- * The FPA's interrupt enable register.
- * - Use with the CVMX_FPA_CTL_STATUS CSR.
- */
-typedef union {
- uint64_t word64;
- struct {
- uint64_t reserved : 49; /* Must be zero */
- uint64_t enb : 1; /* Enable */
- uint64_t mem1_err : 7; /* ECC flip 1 */
- uint64_t mem0_err : 7; /* ECC flip 0 */
- } bits;
-} octeon_fpa_ctl_status_t;
-
-
-/*
- * OCTEON_FPA_FPF_SIZE = FPA's Queue N Free Page FIFO Size
- *
- * The number of page pointers that will be kept local to the FPA for
- * this Queue. FPA Queues are assigned in order from Queue 0 to
- * Queue 7, though only Queue 0 through Queue x can be used.
- * The sum of the 8 (0-7)OCTEON_FPA_FPF#_SIZE registers must be limited to 2048.
- * - Use with the CVMX_FPA_FPF0_SIZE CSR.
- */
-typedef union {
- uint64_t word64;
- struct {
- uint64_t reserved : 52; /* Must be zero */
- /*
- * The number of entries assigned in the FPA FIFO (used to hold
- * page-pointers) for this Queue.
- * The value of this register must divisable by 2, and the FPA will
- * ignore bit [0] of this register.
- * The total of the FPF_SIZ field of the 8 (0-7)OCTEON_FPA_FPF#_MARKS
- * registers must not exceed 2048.
- * After writing this field the FPA will need 10 core clock cycles
- * to be ready for operation. The assignment of location in
- * the FPA FIFO must start with Queue 0, then 1, 2, etc.
- * The number of useable entries will be FPF_SIZ-2.
- */
- uint64_t fpf_siz : 12;
- } bits;
-} octeon_fpa_fpf_size_t;
-
-/*
- *OCTEON_FPA_INT_ENB = FPA's Interrupt Enable
- *
- * The FPA's interrupt enable register.
- * - Use with the CVMX_FPA_INT_ENB CSR.
- */
-typedef union {
- uint64_t word64;
- struct {
- uint64_t reserved : 60; /* Must be zero */
- uint64_t fed1_dbe : 1; /* Int iff bit3 Int-Sum set */
- uint64_t fed1_sbe : 1; /* Int iff bit2 Int-Sum set */
- uint64_t fed0_dbe : 1; /* Int iff bit1 Int-Sum set */
- uint64_t fed0_sbe : 1; /* Int iff bit0 Int-Sum set */
- } bits;
-} octeon_fpa_int_enb_t;
-
-/**
- *OCTEON_FPA_INT_SUM = FPA's Interrupt Summary Register
- *
- * Contains the diffrent interrupt summary bits of the FPA.
- * - Use with the CVMX_FPA_INT_SUM CSR.
- */
-typedef union {
- uint64_t word64;
- struct {
- uint64_t reserved : 60; /**< Must be zero */
- uint64_t fed1_dbe : 1;
- uint64_t fed1_sbe : 1;
- uint64_t fed0_dbe : 1;
- uint64_t fed0_sbe : 1;
- } bits;
-} octeon_fpa_int_sum_t;
-
-
-/*
- *OCTEON_FPA_QUEUE_PAGES_AVAILABLE = FPA's Queue 0-7 Free Page Available Register
- *
- * The number of page pointers that are available in the FPA and local DRAM.
- * - Use with the CVMX_FPA_QUEX_AVAILABLE(0..7) CSR.
- */
-typedef union {
- uint64_t word64;
- struct {
- uint64_t reserved : 38; /* Must be zero */
- uint64_t queue_size : 26; /* free pages available */
- } bits;
-} octeon_fpa_queue_available_t;
-
-
-/*
- *OCTEON_FPA_QUEUE_PAGE_INDEX
- *
- */
-typedef union {
- uint64_t word64;
- struct {
- uint64_t reserved : 39; /* Must be zero */
- uint64_t page_index : 25; /* page_index */
- } bits;
-} octeon_fpa_queue_page_index_t;
-
-
-#define OCTEON_DID_FPA 5ULL
-
-#define OCTEON_FPA_POOL_ALIGNMENT (OCTEON_CACHE_LINE_SIZE)
-
-
-/*
- * Externs
- */
-extern void octeon_dump_fpa(void);
-extern void octeon_dump_fpa_pool(u_int pool);
-extern u_int octeon_fpa_pool_size(u_int pool);
-extern void octeon_enable_fpa(void);
-extern void octeon_fpa_fill_pool_mem(u_int pool,
- u_int block_size_words,
- u_int block_num);
-
-/*
- * octeon_fpa_free
- *
- * Free a mem-block to FPA pool.
- *
- * Takes away this 'buffer' from SW and passes it to FPA for management.
- *
- * pool is FPA pool num, ptr is block ptr, num_cache_lines is number of
- * cache lines to invalidate (not written back).
- */
-static inline void octeon_fpa_free (void *ptr, u_int pool,
- u_int num_cache_lines)
-{
- octeon_addr_t free_ptr;
-
- free_ptr.word64 = (uint64_t)OCTEON_PTR2PHYS(ptr);
-
- free_ptr.sfilldidspace.didspace = OCTEON_ADDR_DIDSPACE(
- OCTEON_ADDR_FULL_DID(OCTEON_DID_FPA, pool));
-
- /*
- * Do not 'sync'
- * asm volatile ("sync\n");
- */
- oct_write64(free_ptr.word64, num_cache_lines);
-}
-
-
-
-/*
- * octeon_fpa_alloc
- *
- * Allocate a new block from the FPA
- *
- * Buffer passes away from FPA management to SW control
- */
-static inline void *octeon_fpa_alloc (u_int pool)
-{
- uint64_t address;
-
- address = oct_read64(OCTEON_ADDR_DID(OCTEON_ADDR_FULL_DID(OCTEON_DID_FPA,
- pool)));
- if (address) {
-
-/*
- * 32 bit FPA pointers only
- */
- /*
- * We only use 32 bit pointers at this time
- */
-/*XXX mips64 issue */
- return ((void *) MIPS_PHYS_TO_KSEG0(address & 0xffffffff));
- }
- return (NULL);
-}
-
-static inline uint64_t octeon_fpa_alloc_phys (u_int pool)
-{
-
- return (oct_read64(OCTEON_ADDR_DID(OCTEON_ADDR_FULL_DID(OCTEON_DID_FPA,
- pool))));
-}
-
-#endif /* ___OCTEON_FPA__H___ */
diff --git a/sys/mips/cavium/dev/rgmii/octeon_ipd.c b/sys/mips/cavium/dev/rgmii/octeon_ipd.c
deleted file mode 100644
index 8757a10..0000000
--- a/sys/mips/cavium/dev/rgmii/octeon_ipd.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/***********************license start***************
- * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
- * reserved.
- *
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * 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.
- *
- * * Neither the name of Cavium Networks nor the names of
- * its contributors may be used to endorse or promote products
- * derived from this software without specific prior written
- * permission.
- *
- * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
- * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
- * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
- * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
- * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
- * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
- * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
- * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
- * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT
- * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
- *
- *
- * For any questions regarding licensing please contact marketing@caviumnetworks.com
- *
- ***********************license end**************************************/
-
-/*------------------------------------------------------------------
- * octeon_ipd.c Input Packet Unit
- *
- *------------------------------------------------------------------
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-
-#include <mips/cavium/octeon_pcmap_regs.h>
-#include "octeon_ipd.h"
-
-/*
- * octeon_ipd_enable
- *
- * enable ipd
- */
-void octeon_ipd_enable (void)
-{
- octeon_ipd_ctl_status_t octeon_ipd_reg;
-
- octeon_ipd_reg.word64 = oct_read64(OCTEON_IPD_CTL_STATUS);
- octeon_ipd_reg.bits.ipd_en = 1;
- oct_write64(OCTEON_IPD_CTL_STATUS, octeon_ipd_reg.word64);
-}
-
-
-/*
- * octeon_ipd_disable
- *
- * disable ipd
- */
-void octeon_ipd_disable (void)
-{
- octeon_ipd_ctl_status_t octeon_ipd_reg;
-
- octeon_ipd_reg.word64 = oct_read64(OCTEON_IPD_CTL_STATUS);
- octeon_ipd_reg.bits.ipd_en = 0;
- oct_write64(OCTEON_IPD_CTL_STATUS, octeon_ipd_reg.word64);
-}
-
-
-/*
- * octeon_ipd_config
- *
- * Configure IPD
- *
- * mbuff_size Packets buffer size in 8 byte words
- * first_mbuff_skip
- * Number of 8 byte words to skip in the first buffer
- * not_first_mbuff_skip
- * Number of 8 byte words to skip in each following buffer
- * first_back Must be same as first_mbuff_skip / Cache_Line_size
- * second_back
- * Must be same as not_first_mbuff_skip / Cache_Line_Size
- * wqe_fpa_pool
- * FPA pool to get work entries from
- * cache_mode
- * back_pres_enable_flag
- * Enable or disable port back pressure
- */
-void octeon_ipd_config (u_int mbuff_size,
- u_int first_mbuff_skip,
- u_int not_first_mbuff_skip,
- u_int first_back,
- u_int second_back,
- u_int wqe_fpa_pool,
- octeon_ipd_mode_t cache_mode,
- u_int back_pres_enable_flag)
-{
- octeon_ipd_mbuff_first_skip_t first_skip;
- octeon_ipd_mbuff_not_first_skip_t not_first_skip;
- octeon_ipd_mbuff_size_t size;
- octeon_ipd_first_next_ptr_back_t first_back_struct;
- octeon_ipd_second_next_ptr_back_t second_back_struct;
- octeon_ipd_wqe_fpa_pool_t wqe_pool;
- octeon_ipd_ctl_status_t octeon_ipd_ctl_reg;
-
- first_skip.word64 = 0;
- first_skip.bits.skip_sz = first_mbuff_skip;
- oct_write64(OCTEON_IPD_1ST_MBUFF_SKIP, first_skip.word64);
-
- not_first_skip.word64 = 0;
- not_first_skip.bits.skip_sz = not_first_mbuff_skip;
- oct_write64(OCTEON_IPD_NOT_1ST_MBUFF_SKIP, not_first_skip.word64);
-
- size.word64 = 0;
- size.bits.mb_size = mbuff_size;
- oct_write64(OCTEON_IPD_PACKET_MBUFF_SIZE, size.word64);
-
- first_back_struct.word64 = 0;
- first_back_struct.bits.back = first_back;
- oct_write64(OCTEON_IPD_1ST_NEXT_PTR_BACK, first_back_struct.word64);
-
- second_back_struct.word64 = 0;
- second_back_struct.bits.back = second_back;
- oct_write64(OCTEON_IPD_2ND_NEXT_PTR_BACK, second_back_struct.word64);
-
- wqe_pool.word64 = 0;
- wqe_pool.bits.wqe_pool = wqe_fpa_pool;
- oct_write64(OCTEON_IPD_WQE_FPA_QUEUE, wqe_pool.word64);
-
- octeon_ipd_ctl_reg.word64 = 0;
- octeon_ipd_ctl_reg.bits.opc_mode = cache_mode;
- octeon_ipd_ctl_reg.bits.pbp_en = back_pres_enable_flag;
- oct_write64(OCTEON_IPD_CTL_STATUS, octeon_ipd_ctl_reg.word64);
-}
diff --git a/sys/mips/cavium/dev/rgmii/octeon_ipd.h b/sys/mips/cavium/dev/rgmii/octeon_ipd.h
deleted file mode 100644
index aabfaae..0000000
--- a/sys/mips/cavium/dev/rgmii/octeon_ipd.h
+++ /dev/null
@@ -1,204 +0,0 @@
-/***********************license start***************
- * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
- * reserved.
- *
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * 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.
- *
- * * Neither the name of Cavium Networks nor the names of
- * its contributors may be used to endorse or promote products
- * derived from this software without specific prior written
- * permission.
- *
- * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
- * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
- * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
- * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
- * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
- * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
- * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
- * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
- * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT
- * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
- *
- *
- * For any questions regarding licensing please contact marketing@caviumnetworks.com
- *
- ***********************license end**************************************/
-
-/* $FreeBSD$ */
-
-/*------------------------------------------------------------------
- * octeon_ipd.h Input Packet Unit
- *
- *------------------------------------------------------------------
- */
-
-
-#ifndef ___OCTEON_IPD__H___
-#define ___OCTEON_IPD__H___
-
-
-
-typedef enum {
- OCTEON_IPD_OPC_MODE_STT = 0LL, /* All blocks DRAM, not cached in L2 */
- OCTEON_IPD_OPC_MODE_STF = 1LL, /* All blocks into L2 */
- OCTEON_IPD_OPC_MODE_STF1_STT = 2LL, /* 1st block L2, rest DRAM */
- OCTEON_IPD_OPC_MODE_STF2_STT = 3LL /* 1st, 2nd blocks L2, rest DRAM */
-} octeon_ipd_mode_t;
-
-
-
-
-/*
- * IPD_CTL_STATUS = IPS'd Control Status Register
- * The number of words in a MBUFF used for packet data store.
- */
-typedef union {
- uint64_t word64;
- struct {
- uint64_t reserved : 58; /* Reserved */
- uint64_t pkt_lend : 1; /* Pkt Lil-Endian Writes to L2C */
- uint64_t wqe_lend : 1; /* WQE Lik-Endian Writes to L2C */
- uint64_t pbp_en : 1; /* Enable Back-Pressure */
- octeon_ipd_mode_t opc_mode : 2; /* Pkt data in Mem/L2-cache ? */
- uint64_t ipd_en : 1; /* Enable IPD */
- } bits;
-} octeon_ipd_ctl_status_t;
-
-
-/*
- * IPD_1ST_NEXT_PTR_BACK = IPD First Next Pointer Back Values
- *
- * Contains the Back Field for use in creating the Next Pointer Header
- * for the First MBUF
- */
-typedef union {
- uint64_t word64;
- struct {
- uint64_t reserved : 60; /* Must be zero */
- uint64_t back : 4; /* Used to find head of buffer from the nxt-hdr-ptr. */
- } bits;
-} octeon_ipd_first_next_ptr_back_t;
-
-
-/*
- * IPD_INTERRUPT_ENB = IPD Interrupt Enable Register
- *
- * Used to enable the various interrupting conditions of IPD
- */
-typedef union {
- uint64_t word64;
- struct {
- uint64_t reserved : 59; /* Must be zero */
- uint64_t bp_sub : 1; /* BP subtract is illegal val */
- uint64_t prc_par3 : 1; /* PBM Bits [127:96] Parity Err */
- uint64_t prc_par2 : 1; /* PBM Bits [ 95:64] Parity Err */
- uint64_t prc_par1 : 1; /* PBM Bits [ 63:32] Parity Err */
- uint64_t prc_par0 : 1; /* PBM Bits [ 31:0 ] Parity Err */
- } bits;
-} octeon_ipd_int_enb_t;
-
-
-/*
- * IPD_INTERRUPT_SUM = IPD Interrupt Summary Register
- *
- * Set when an interrupt condition occurs, write '1' to clear.
- */
-typedef union {
- uint64_t word64;
- struct {
- uint64_t reserved : 59; /* Must be zero */
- uint64_t bp_sub : 1; /* BP subtract is illegal val */
- uint64_t prc_par3 : 1; /* PBM Bits [127:96] Parity Err */
- uint64_t prc_par2 : 1; /* PBM Bits [ 95:64] Parity Err */
- uint64_t prc_par1 : 1; /* PBM Bits [ 63:32] Parity Err */
- uint64_t prc_par0 : 1; /* PBM Bits [ 31:0 ] Parity Err */
- } bits;
-} octeon_ipd_int_sum_t;
-
-
-/**
- * IPD_1ST_MBUFF_SKIP = IPD First MBUFF Word Skip Size
- *
- * The number of words that the IPD will skip when writing the first MBUFF.
- */
-typedef union {
- uint64_t word64;
- struct {
- uint64_t reserved : 58; /* Must be zero */
- uint64_t skip_sz : 6; /* 64bit words from the top of */
- /* 1st MBUFF that the IPD will */
- /* store the next-pointer. */
- /* [0..32] && */
- /* (skip_sz + 16) <= IPD_PACKET_MBUFF_SIZE[MB_SIZE]. */
- } bits;
-} octeon_ipd_mbuff_first_skip_t;
-
-
-/*
- * IPD_PACKET_MBUFF_SIZE = IPD's PACKET MUBUF Size In Words
- *
- * The number of words in a MBUFF used for packet data store.
- */
-typedef union {
- uint64_t word64;
- struct {
- uint64_t reserved : 52; /* Must be zero */
- uint64_t mb_size : 12; /* 64bit words in a MBUF. */
- /* Must be [32..2048] */
- /* Is also the size of the FPA's */
- /* Queue-0 Free-Page */
- } bits;
-} octeon_ipd_mbuff_size_t;
-
-
-/*
- * IPD_WQE_FPA_QUEUE = IPD Work-Queue-Entry FPA Page Size
- *
- * Which FPA Queue (0-7) to fetch page-pointers from for WQE's
- */
-typedef union {
- uint64_t word64;
- struct {
- uint64_t reserved : 61; /* Must be zero */
- uint64_t wqe_pool : 3; /* FPA Pool to fetch WQE Page-ptrs */
- } bits;
-} octeon_ipd_wqe_fpa_pool_t;
-
-
-
-
-/* End of Control and Status Register (CSR) definitions */
-
-typedef octeon_ipd_mbuff_first_skip_t octeon_ipd_mbuff_not_first_skip_t;
-typedef octeon_ipd_first_next_ptr_back_t octeon_ipd_second_next_ptr_back_t;
-
-
-/*
- * Externs
- */
-extern void octeon_ipd_enable(void);
-extern void octeon_ipd_disable(void);
-extern void octeon_ipd_config(u_int mbuff_size,
- u_int first_mbuff_skip,
- u_int not_first_mbuff_skip,
- u_int first_back,
- u_int second_back,
- u_int wqe_fpa_pool,
- octeon_ipd_mode_t cache_mode,
- u_int back_pres_enable_flag);
-
-
-
-#endif /* ___OCTEON_IPD__H___ */
diff --git a/sys/mips/cavium/dev/rgmii/octeon_pip.h b/sys/mips/cavium/dev/rgmii/octeon_pip.h
deleted file mode 100644
index a13d244..0000000
--- a/sys/mips/cavium/dev/rgmii/octeon_pip.h
+++ /dev/null
@@ -1,219 +0,0 @@
-/***********************license start***************
- * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
- * reserved.
- *
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * 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.
- *
- * * Neither the name of Cavium Networks nor the names of
- * its contributors may be used to endorse or promote products
- * derived from this software without specific prior written
- * permission.
- *
- * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
- * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
- * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
- * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
- * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
- * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
- * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
- * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
- * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT
- * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
- *
- *
- * For any questions regarding licensing please contact marketing@caviumnetworks.com
- *
- ***********************license end**************************************/
-
-/* $FreeBSD$ */
-
-/*
- * octeon_pip.h Packet Input Processing Block
- *
- */
-
-
-
-#ifndef __OCTEON_PIP_H__
-#define __OCTEON_PIP_H__
-
-/**
- * Enumeration representing the amount of packet processing
- * and validation performed by the input hardware.
- */
-typedef enum
-{
- OCTEON_PIP_PORT_CFG_MODE_NONE = 0ull, /**< Packet input doesn't perform any
- processing of the input packet. */
- OCTEON_PIP_PORT_CFG_MODE_SKIPL2 = 1ull,/**< Full packet processing is performed
- with pointer starting at the L2
- (ethernet MAC) header. */
- OCTEON_PIP_PORT_CFG_MODE_SKIPIP = 2ull /**< Input packets are assumed to be IP.
- Results from non IP packets is
- undefined. Pointers reference the
- beginning of the IP header. */
-} octeon_pip_port_parse_mode_t;
-
-
-
-#define OCTEON_PIP_PRT_CFGX(offset) (0x80011800A0000200ull+((offset)*8))
-#define OCTEON_PIP_PRT_TAGX(offset) (0x80011800A0000400ull+((offset)*8))
-#define OCTEON_PIP_STAT_INB_PKTS(port) (0x80011800A0001A00ull+((port) * 32))
-#define OCTEON_PIP_STAT_INB_ERRS(port) (0x80011800A0001A10ull+((port) * 32))
-
-/*
- * PIP Global Config
- */
-typedef union {
- uint64_t word64;
- struct {
- uint64_t reserved2 : 45; /* Must be zero */
- uint64_t tag_syn : 1; /* Not Include src_crc in TCP..*/
- uint64_t ip6_udp : 1; /* IPv6/UDP checksum is mandatory */
- uint64_t max_l2 : 1; /* Largest L2 frame. 0/1 : 1500/1535 */
- uint64_t reserved1 : 5; /* Must be zero */
- uint64_t raw_shf : 3; /* PCI RAW Packet shift/pad amount */
- uint64_t reserved0 : 5; /* Must be zero */
- uint64_t nip_shf : 3; /* Non-IP shift/pad amount */
- } bits;
-} octeon_pip_gbl_cfg_t;
-
-
-typedef union {
- uint64_t word64;
- struct {
- uint64_t reserved4 : 37; /* Must be zero */
- uint64_t qos : 3; /* Default POW QoS queue */
- uint64_t qos_wat : 4; /* Bitfield to enable QoS watcher */
- /* look up tables. 4 per port. */
- uint64_t reserved3 : 1; /* Must be zero */
- uint64_t spare : 1; /* Must be zero */
- uint64_t qos_diff : 1; /* Use IP diffserv to determine */
- /* the queue in the POW */
- uint64_t qos_vlan : 1; /* Use the VLAN tag to determine */
- /* the queue in the POW */
- uint64_t reserved2 : 3; /* Must be zero */
- uint64_t crc_en : 1; /* Enable HW checksum */
- uint64_t reserved1 : 2; /* Must be zero */
- octeon_pip_port_parse_mode_t mode : 2; /* Raw/Parsed/IP/etc */
- uint64_t reserved0 : 1; /* Must be zero */
- uint64_t skip : 7; /* 8 byte words to skip in the */
- /* beginning of a packet buffer */
- } bits;
-} octeon_pip_port_cfg_t;
-
-
-
-/*
- * Packet input to POW interface. How input packets are tagged for
- * the POW is controlled here.
- */
-typedef union {
- uint64_t word64;
- struct {
- uint64_t reserved : 24; /**< Reserved */
- uint64_t grptagbase : 4; /**< Offset to use when computing group from tag bits
- when GRPTAG is set. Only applies to IP packets.
- (PASS2 only) */
- uint64_t grptagmask : 4; /**< Which bits of the tag to exclude when computing
- group when GRPTAG is set. Only applies to IP packets.
- (PASS2 only) */
- uint64_t grptag : 1; /**< When set, use the lower bit of the tag to compute
- the group in the work queue entry
- GRP = WQE[TAG[3:0]] & ~GRPTAGMASK + GRPTAGBASE.
- Only applies to IP packets. (PASS2 only) */
- uint64_t spare : 1; /**< Spare bit
- (PASS2 only) */
- uint64_t tag_mode : 2; /**< Which tag algorithm to use
- 0 = always use tuple tag algorithm
- 1 = always use mask tag algorithm
- 2 = if packet is IP, use tuple else use mask
- 3 = tuple XOR mask
- (PASS2 only) */
- uint64_t inc_vs : 2; /**< determines the VLAN ID (VID) to be included in
- tuple tag when VLAN stacking is detected
- 0 = do not include VID in tuple tag generation
- 1 = include VID (VLAN0) in hash
- 2 = include VID (VLAN1) in hash
- 3 = include VID ([VLAN0,VLAN1]) in hash
- (PASS2 only) */
- uint64_t inc_vlan : 1; /**< when set, the VLAN ID is included in tuple tag
- when VLAN stacking is not detected
- 0 = do not include VID in tuple tag generation
- 1 = include VID in hash
- (PASS2 only) */
- uint64_t inc_prt_flag : 1; /**< sets whether the port is included in tuple tag */
- uint64_t ip6_dprt_flag : 1; /**< sets whether the TCP/UDP dst port is
- included in tuple tag for IPv6 packets */
- uint64_t ip4_dprt_flag : 1; /**< sets whether the TCP/UDP dst port is
- included in tuple tag for IPv4 */
- uint64_t ip6_sprt_flag : 1; /**< sets whether the TCP/UDP src port is
- included in tuple tag for IPv6 packets */
- uint64_t ip4_sprt_flag : 1; /**< sets whether the TCP/UDP src port is
- included in tuple tag for IPv4 */
- uint64_t ip6_nxth_flag : 1; /**< sets whether ipv6 includes next header in tuple
- tag hash */
- uint64_t ip4_pctl_flag : 1; /**< sets whether ipv4 includes protocol in tuple
- tag hash */
- uint64_t ip6_dst_flag : 1; /**< sets whether ipv6 includes dst address in tuple
- tag hash */
- uint64_t ip4_dst_flag : 1; /**< sets whether ipv4 includes dst address in tuple
- tag hash */
- uint64_t ip6_src_flag : 1; /**< sets whether ipv6 includes src address in tuple
- tag hash */
- uint64_t ip4_src_flag : 1; /**< sets whether ipv4 includes src address in tuple
- tag hash */
- uint64_t tcp6_tag_type : 2; /**< sets the tag_type of a TCP packet (IPv6)
- 0 = ordered tags
- 1 = atomic tags
- 2 = Null tags */
- uint64_t tcp4_tag_type : 2; /**< sets the tag_type of a TCP packet (IPv4)
- 0 = ordered tags
- 1 = atomic tags
- 2 = Null tags */
- uint64_t ip6_tag_type : 2; /**< sets whether IPv6 packet tag type
- 0 = ordered tags
- 1 = atomic tags
- 2 = Null tags */
- uint64_t ip4_tag_type : 2; /**< sets whether IPv4 packet tag type
- 0 = ordered tags
- 1 = atomic tags
- 2 = Null tags */
- uint64_t non_tag_type : 2; /**< sets whether non-IP packet tag type
- 0 = ordered tags
- 1 = atomic tags
- 2 = Null tags */
- uint64_t grp : 4; /* POW group for input pkts */
- } bits;
-} octeon_pip_port_tag_cfg_t;
-
-
-/**
- * Configure an ethernet input port
- *
- * @param port_num Port number to configure
- * @param port_cfg Port hardware configuration
- * @param port_tag_cfg
- * Port POW tagging configuration
- */
-static inline void octeon_pip_config_port(u_int port_num,
- octeon_pip_port_cfg_t port_cfg,
- octeon_pip_port_tag_cfg_t port_tag_cfg)
-{
- oct_write64(OCTEON_PIP_PRT_CFGX(port_num), port_cfg.word64);
- oct_write64(OCTEON_PIP_PRT_TAGX(port_num), port_tag_cfg.word64);
-}
-
-
-#endif /* __OCTEON_PIP_H__ */
diff --git a/sys/mips/cavium/dev/rgmii/octeon_pko.c b/sys/mips/cavium/dev/rgmii/octeon_pko.c
deleted file mode 100644
index e93ef87..0000000
--- a/sys/mips/cavium/dev/rgmii/octeon_pko.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/***********************license start***************
- * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
- * reserved.
- *
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * 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.
- *
- * * Neither the name of Cavium Networks nor the names of
- * its contributors may be used to endorse or promote products
- * derived from this software without specific prior written
- * permission.
- *
- * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
- * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
- * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
- * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
- * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
- * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
- * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
- * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
- * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT
- * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
- *
- *
- * For any questions regarding licensing please contact marketing@caviumnetworks.com
- *
- ***********************license end**************************************/
-
-/*------------------------------------------------------------------
- * octeon_pko.c Packet Output Unit
- *
- *------------------------------------------------------------------
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <vm/vm.h>
-#include <vm/pmap.h>
-
-#include <mips/cavium/octeon_pcmap_regs.h>
-#include "octeon_fau.h"
-#include "octeon_fpa.h"
-#include "octeon_pko.h"
-
-
-/*
- *
- */
-static void octeon_pko_clear_port_counts (u_int port)
-{
- u_int port_num;
- octeon_pko_read_idx_t octeon_pko_idx;
-
- octeon_pko_idx.word64 = 0;
- octeon_pko_idx.bits.idx = port;
- octeon_pko_idx.bits.inc = 0;
- oct_write64(OCTEON_PKO_REG_READ_IDX, octeon_pko_idx.word64);
-
- port_num = port;
- oct_write64(OCTEON_PKO_MEM_COUNT0, port_num);
- port_num = port;
- oct_write64(OCTEON_PKO_MEM_COUNT1, port_num);
-}
-
-/*
- * octeon_pko_init
- *
- */
-void octeon_pko_init (void)
-{
- u_int queue, port;
- octeon_pko_read_idx_t octeon_pko_idx;
- octeon_pko_queue_cfg_t octeon_pko_queue_cfg;
-
- for (port = 0; port < OCTEON_PKO_PORTS_MAX; port++) {
- octeon_pko_clear_port_counts(port);
- }
-
- octeon_pko_idx.word64 = 0;
- octeon_pko_idx.bits.idx = 0;
- octeon_pko_idx.bits.inc = 1;
- oct_write64(OCTEON_PKO_REG_READ_IDX, octeon_pko_idx.word64);
- for (queue = 0; queue < OCTEON_PKO_QUEUES_MAX; queue++) {
-
- octeon_pko_queue_cfg.word64 = 0;
- octeon_pko_queue_cfg.bits.queue = queue;
- octeon_pko_queue_cfg.bits.port = OCTEON_PKO_PORT_ILLEGAL;
- octeon_pko_queue_cfg.bits.buf_ptr = 0;
- oct_write64(OCTEON_PKO_MEM_QUEUE_PTRS, octeon_pko_queue_cfg.word64);
- }
-}
-
-
-/*
- * octeon_pko_enable
- *
- * enable pko
- */
-void octeon_pko_enable (void)
-{
-
- /*
- * PKO enable
- */
- oct_write64(OCTEON_PKO_REG_FLAGS, 3); /* octeon_pko_enable() */
-}
-
-
-/*
- * octeon_pko_disable
- *
- * disable pko
- */
-void octeon_pko_disable (void)
-{
-
- /*
- * PKO disable
- */
- oct_write64(OCTEON_PKO_REG_FLAGS, 0); /* pko_disable() */
-}
-
-/*
- * octeon_pko_config_cmdbuf_global_defaults
- *
- */
-void octeon_pko_config_cmdbuf_global_defaults (u_int cmdbuf_pool,
- u_int cmdbuf_pool_elem_size )
-{
- octeon_pko_pool_cfg_t octeon_pko_pool_config;
-
- octeon_pko_pool_config.word64 = 0;
- octeon_pko_pool_config.bits.pool = cmdbuf_pool;
- octeon_pko_pool_config.bits.size = cmdbuf_pool_elem_size;
- oct_write64(OCTEON_PKO_CMD_BUF, octeon_pko_pool_config.word64);
-}
-
-/*
- * octeon_pko_config_rgmx_ports
- *
- * Configure rgmx pko. Always enables 4 + 4 ports
- */
-void octeon_pko_config_rgmx_ports (void)
-{
- octeon_pko_reg_gmx_port_mode_t octeon_pko_gmx_mode;
-
- octeon_pko_gmx_mode.word64 = 0;
- octeon_pko_gmx_mode.bits.mode0 = 2; /* 16 >> 2 == 4 ports */
- octeon_pko_gmx_mode.bits.mode1 = 2; /* 16 >> 2 == 4 ports */
- oct_write64(OCTEON_PKO_GMX_PORT_MODE, octeon_pko_gmx_mode.word64);
-}
-
-
-/*
- * octeon_pko_config
- *
- * Configure PKO
- *
- */
-void octeon_pko_config (void)
-{
-}
-
-/*
- * octeon_pko_get_port_status
- *
- * Get the status counters for a PKO port.
- *
- * port_num Port number to get statistics for.
- * clear Set to 1 to clear the counters after they are read
- * status Where to put the results.
- */
-void octeon_pko_get_port_status (u_int port, u_int clear,
- octeon_pko_port_status_t *status)
-{
- octeon_word_t packet_num;
- octeon_pko_read_idx_t octeon_pko_idx;
-
- packet_num.word64 = 0;
-
- octeon_pko_idx.word64 = 0;
- octeon_pko_idx.bits.idx = port;
- octeon_pko_idx.bits.inc = 0;
- oct_write64(OCTEON_PKO_REG_READ_IDX, octeon_pko_idx.word64);
-
- packet_num.word64 = oct_read64(OCTEON_PKO_MEM_COUNT0);
- status->packets = packet_num.bits.word32lo;
-
- status->octets = oct_read64(OCTEON_PKO_MEM_COUNT1);
- status->doorbell = oct_read64(OCTEON_PKO_MEM_DEBUG9);
- status->doorbell = (status->doorbell >> 8) & 0xfffff;
- if (clear) {
- octeon_pko_clear_port_counts(port);
- }
-}
-
-static void octeon_pko_doorbell_data_dump(uint64_t port);
-
-static void octeon_pko_doorbell_data_dump (uint64_t port)
-{
- octeon_pko_port_status_t status;
-
- octeon_pko_get_port_status(port, 0, &status);
- printf("\n Port #%lld Pkts %ld Bytes %lld DoorBell %lld",
- (unsigned long long)port, status.packets,
- (unsigned long long)status.octets,
- (unsigned long long)status.doorbell);
-}
-
-/*
- * octeon_pko_show
- *
- * Show the OCTEON_PKO status & configs
- */
-void octeon_pko_show (u_int start_port, u_int end_port)
-{
- u_int queue, queue_max, gmx_int0_ports, gmx_int1_ports;
- u_int port;
- uint64_t val64;
- octeon_pko_port_status_t status;
- octeon_pko_pool_cfg_t octeon_pko_pool_config;
- octeon_pko_read_idx_t octeon_pko_idx;
- octeon_pko_queue_mode_t octeon_pko_queue_mode;
- octeon_pko_reg_gmx_port_mode_t octeon_pko_gmx_mode;
- octeon_pko_crc_ports_enable_t octeon_pko_crc_ports;
- octeon_pko_queue_cfg_t octeon_pko_queue_cfg;
-
- printf("\n\nPKO Status:");
- val64 = oct_read64(OCTEON_PKO_REG_FLAGS);
- if ((val64 & 0x3) != 0x3) {
- printf(" Disabled");
- return;
- } else {
- printf(" Enabled");
- }
- octeon_pko_queue_mode.word64 = oct_read64(OCTEON_PKO_QUEUE_MODE);
- queue_max = (128 >> octeon_pko_queue_mode.bits.mode);
- octeon_pko_gmx_mode.word64 = oct_read64(OCTEON_PKO_GMX_PORT_MODE);
- gmx_int0_ports = (16 >> octeon_pko_gmx_mode.bits.mode0);
- gmx_int1_ports = (16 >> octeon_pko_gmx_mode.bits.mode1);
- octeon_pko_crc_ports.word64 = oct_read64(OCTEON_PKO_REG_CRC_ENABLE);
- printf("\n Total Queues: 0..%d Ports GMX0 %d GMX1 %d CRC 0x%X",
- queue_max - 1, gmx_int0_ports, gmx_int1_ports,
- octeon_pko_crc_ports.bits.crc_ports_mask);
-
- octeon_pko_pool_config.word64 = oct_read64(OCTEON_PKO_CMD_BUF);
- printf("\n CmdBuf Pool: %d CmdBuf Size in Words: %d Bytes: %d",
- octeon_pko_pool_config.bits.pool, octeon_pko_pool_config.bits.size,
- octeon_pko_pool_config.bits.size * 8);
-
- octeon_pko_idx.word64 = 0;
- octeon_pko_idx.bits.idx = 0;
- octeon_pko_idx.bits.inc = 1;
- oct_write64(OCTEON_PKO_REG_READ_IDX, octeon_pko_idx.word64);
- for (queue = 0; queue < queue_max; queue++) {
-
- octeon_pko_queue_cfg.word64 = oct_read64(OCTEON_PKO_MEM_QUEUE_PTRS);
- if (!octeon_pko_queue_cfg.bits.buf_ptr) continue;
- printf("\n Port # %d Queue %3d [%d] BufPtr: 0x%llX Mask: %X%s",
- octeon_pko_queue_cfg.bits.port, octeon_pko_queue_cfg.bits.queue,
- octeon_pko_queue_cfg.bits.index,
- (unsigned long long)octeon_pko_queue_cfg.bits.buf_ptr,
- octeon_pko_queue_cfg.bits.qos_mask,
- (octeon_pko_queue_cfg.bits.tail)? " Last":"");
- }
- printf("\n");
-
- for (port = start_port; port < (end_port + 1); port++) {
-
- octeon_pko_get_port_status(port, 0, &status);
- octeon_pko_doorbell_data_dump(port);
-
- }
-}
-
-
-
-
-/*
- * octeon_pko_config_port
- *
- * Configure a output port and the associated queues for use.
- *
- */
-octeon_pko_status_t octeon_pko_config_port (u_int port,
- u_int base_queue,
- u_int num_queues,
- const u_int priority[],
- u_int pko_output_cmdbuf_fpa_pool,
- octeon_pko_sw_queue_info_t sw_queues[])
-{
- octeon_pko_status_t result_code;
- u_int queue;
- octeon_pko_queue_cfg_t qconfig;
-
- if ((port >= OCTEON_PKO_PORTS_MAX) && (port != OCTEON_PKO_PORT_ILLEGAL)) {
- printf("\n%% Error: octeon_pko_config_port: Invalid port %u", port);
- return (OCTEON_PKO_INVALID_PORT);
- }
-
- if ((base_queue + num_queues) > OCTEON_PKO_QUEUES_MAX) {
- printf("\n%% Error: octeon_pko_config_port: Invalid queue range");
- return (OCTEON_PKO_INVALID_QUEUE);
- }
-
- result_code = OCTEON_PKO_SUCCESS;
-
- for (queue = 0; queue < num_queues; queue++) {
- uint64_t buf_ptr = 0;
-
- qconfig.word64 = 0;
- qconfig.bits.tail = (queue == (num_queues - 1)) ? 1 : 0;
- qconfig.bits.index = queue;
- qconfig.bits.port = port;
- qconfig.bits.queue = base_queue + queue;
-
- /* Convert the priority into an enable bit field. */
- /* Try to space the bits out evenly so the pkts don't get grouped up */
- switch ((int)priority[queue]) {
- case 0: qconfig.bits.qos_mask = 0x00; break;
- case 1: qconfig.bits.qos_mask = 0x01; break;
- case 2: qconfig.bits.qos_mask = 0x11; break;
- case 3: qconfig.bits.qos_mask = 0x49; break;
- case 4: qconfig.bits.qos_mask = 0x55; break;
- case 5: qconfig.bits.qos_mask = 0x57; break;
- case 6: qconfig.bits.qos_mask = 0x77; break;
- case 7: qconfig.bits.qos_mask = 0x7f; break;
- case 8: qconfig.bits.qos_mask = 0xff; break;
- default:
- printf("\n%% Error: octeon_pko_config_port Invalid priority %llu",
- (unsigned long long)priority[queue]);
- qconfig.bits.qos_mask = 0xff;
- result_code = OCTEON_PKO_INVALID_PRIORITY;
- break;
- }
- if (port != OCTEON_PKO_PORT_ILLEGAL) {
-
- buf_ptr = octeon_fpa_alloc_phys(pko_output_cmdbuf_fpa_pool);
- if (!buf_ptr) {
- printf("\n%% Error: octeon_pko_config_port: Unable to allocate");
- return (OCTEON_PKO_NO_MEMORY);
- }
-
- sw_queues[queue].xmit_command_state = (buf_ptr << OCTEON_PKO_INDEX_BITS);
- octeon_spinlock_init(&(sw_queues[queue].lock));
-
-//#define DEBUG_TX
-
-#ifdef DEBUG_TX
- printf(" PKO: port %u pool: %u base+queue %u %u %u buf_ptr: 0x%llX\n",
- port,
- pko_output_cmdbuf_fpa_pool,
- base_queue, queue, base_queue+queue,
- buf_ptr);
-
-#endif
- qconfig.bits.buf_ptr = buf_ptr;
- oct_write64(OCTEON_PKO_MEM_QUEUE_PTRS, qconfig.word64);
-
- }
- }
-
- return (result_code);
-}
-
diff --git a/sys/mips/cavium/dev/rgmii/octeon_pko.h b/sys/mips/cavium/dev/rgmii/octeon_pko.h
deleted file mode 100644
index c6ece8c..0000000
--- a/sys/mips/cavium/dev/rgmii/octeon_pko.h
+++ /dev/null
@@ -1,332 +0,0 @@
-/***********************license start***************
- * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
- * reserved.
- *
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * 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.
- *
- * * Neither the name of Cavium Networks nor the names of
- * its contributors may be used to endorse or promote products
- * derived from this software without specific prior written
- * permission.
- *
- * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
- * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
- * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
- * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
- * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
- * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
- * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
- * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
- * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT
- * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
- *
- *
- * For any questions regarding licensing please contact marketing@caviumnetworks.com
- *
- ***********************license end**************************************/
-
-/* $FreeBSD$ */
-
-/*------------------------------------------------------------------
- * octeon_pko.h Packet Output Block
- *
- *------------------------------------------------------------------
- */
-
-
-#ifndef ___OCTEON_PKO__H___
-#define ___OCTEON_PKO__H___
-
-
-
-/*
- * PKO Command Buffer Register.
- * Specify Pool-# and Size of each entry in Pool. For Output Cmd Buffers.
- */
-typedef union {
- uint64_t word64;
- struct {
- uint64_t unused_mbz : 41; /* Must be zero */
- uint64_t pool : 3; /* FPA Pool to use */
- uint64_t unused_mbz2 : 7; /* Must be zero */
- uint64_t size : 13; /* Size of the pool blocks */
- } bits;
-} octeon_pko_pool_cfg_t;
-
-
-/*
- * PKO GMX Mode Register
- * Specify the # of GMX1 ports and GMX0 ports
- */
-typedef union {
- uint64_t word64;
- struct {
- uint64_t unused_mbz : 58; /* MBZ */
- uint64_t mode1 : 3; /* # GMX1 ports; */
- /* 16 >> MODE1, 0 <= MODE1 <=4 */
- uint64_t mode0 : 3; /* # GMX0 ports; */
- /* 16 >> MODE0, 0 <= MODE0 <=4 */
- } bits;
-} octeon_pko_reg_gmx_port_mode_t;
-
-
-typedef union {
- uint64_t word64;
- struct {
- uint64_t unused_mbz : 62; /* MBZ */
- uint64_t mode : 2; /* Queues Mode */
- } bits;
-} octeon_pko_queue_mode_t;
-
-
-typedef union {
- uint64_t word64;
- struct {
- uint64_t unused_mbz : 32; /* MBZ */
- uint64_t crc_ports_mask : 32; /* CRC Ports Enable mask */
- } bits;
-} octeon_pko_crc_ports_enable_t;
-
-
-
-#define OCTEON_PKO_QUEUES_MAX 128
-#define OCTEON_PKO_PORTS_MAX 36
-#define OCTEON_PKO_PORT_ILLEGAL 63
-
-/* Defines how the PKO command buffer FAU register is used */
-
-#define OCTEON_PKO_INDEX_BITS 12
-#define OCTEON_PKO_INDEX_MASK ((1ull << OCTEON_PKO_INDEX_BITS) - 1)
-
-
-
-typedef enum {
- OCTEON_PKO_SUCCESS,
- OCTEON_PKO_INVALID_PORT,
- OCTEON_PKO_INVALID_QUEUE,
- OCTEON_PKO_INVALID_PRIORITY,
- OCTEON_PKO_NO_MEMORY
-} octeon_pko_status_t;
-
-
-typedef struct {
- long packets;
- uint64_t octets;
- uint64_t doorbell;
-} octeon_pko_port_status_t;
-
-
-typedef union {
- uint64_t word64;
- struct {
- octeon_mips_space_t mem_space : 2; /* Octeon IO_SEG */
- uint64_t unused_mbz :13; /* Must be zero */
- uint64_t is_io : 1; /* Must be one */
- uint64_t did : 8; /* device-ID on non-coherent bus*/
- uint64_t unused_mbz2 : 4; /* Must be zero */
- uint64_t unused_mbz3 :18; /* Must be zero */
- uint64_t port : 6; /* output port */
- uint64_t queue : 9; /* output queue to send */
- uint64_t unused_mbz4 : 3; /* Must be zero */
- } bits;
-} octeon_pko_doorbell_address_t;
-
-/*
- * Structure of the first packet output command word.
- */
-typedef union {
- uint64_t word64;
- struct {
- octeon_fau_op_size_t size1 : 2; /* The size of reg1 operation */
- /* - could be 8, 16, 32, or 64 bits */
- octeon_fau_op_size_t size0 : 2; /* The size of the reg0 operation */
- /* - could be 8, 16, 32, or 64 bits */
- uint64_t subone1 : 1; /* Subtract 1, else sub pkt size */
- uint64_t reg1 :11; /* The register, subtract will be */
- /* done if reg1 is non-zero */
- uint64_t subone0 : 1; /* Subtract 1, else sub pkt size */
- uint64_t reg0 :11; /* The register, subtract will be */
- /* done if reg0 is non-zero */
- uint64_t unused : 2; /* Must be zero */
- uint64_t wqp : 1; /* If rsp, then word3 contains a */
- /* ptr to a work queue entry */
- uint64_t rsp : 1; /* HW will respond when done */
- uint64_t gather : 1; /* If set, the supplied pkt_ptr is */
- /* a ptr to a list of pkt_ptr's */
- uint64_t ipoffp1 : 7; /* Off to IP hdr. For HW checksum */
- uint64_t ignore_i : 1; /* Ignore I bit in all pointers */
- uint64_t dontfree : 1; /* Don't free buffs containing pkt */
- uint64_t segs : 6; /* Number of segs. If gather set, */
- /* also gather list length */
- uint64_t total_bytes :16; /* Includes L2, w/o trailing CRC */
- } bits;
-} octeon_pko_command_word0_t;
-
-
-typedef union {
- void* ptr;
- uint64_t word64;
- struct {
- uint64_t i : 1; /* Invert the "free" pick of the overall pkt. */
- /* For inbound pkts, HW always sets this to 0 */
- uint64_t back : 4; /* Amount to back up to get to buffer start */
- /* in cache lines. This is mostly less than 1 */
- /* complete cache line; so the value is zero */
- uint64_t pool : 3; /* FPA pool that the buffer belongs to */
- uint64_t size :16; /* segment size (bytes) pointed at by addr */
- uint64_t addr :40; /* Ptr to 1st data byte. NOT buffer */
- } bits;
-} octeon_pko_packet_ptr_t;
-
-
-/*
- * Definition of the hardware structure used to configure an
- * output queue.
- */
-typedef union {
- uint64_t word64;
- struct {
- uint64_t unused_mbz : 3; /* Must be zero */
- uint64_t qos_mask : 8; /* Control Mask priority */
- /* across 8 QOS levels */
- uint64_t buf_ptr : 36; /* Command buffer pointer, */
- /* 8 byte-aligned */
- uint64_t tail : 1; /* Set if this queue is the tail */
- /* of the port queue array */
- uint64_t index : 3; /* Index (distance from head) in */
- /* the port queue array */
- uint64_t port : 6; /* Port ID for this queue mapping */
- uint64_t queue : 7; /* Hardware queue number */
- } bits;
-} octeon_pko_queue_cfg_t;
-
-
-typedef union {
- uint64_t word64;
- struct {
- uint64_t unused_mbz : 48;
- uint64_t inc : 8;
- uint64_t idx : 8;
- } bits;
-} octeon_pko_read_idx_t;
-
-
-typedef struct octeon_pko_sw_queue_info_t_
-{
- uint64_t xmit_command_state;
- octeon_spinlock_t lock;
- uint32_t pad[29];
-} octeon_pko_sw_queue_info_t;
-
-
-
-#define OCTEON_DID_PKT 10ULL
-#define OCTEON_DID_PKT_SEND OCTEON_ADDR_FULL_DID(OCTEON_DID_PKT,2ULL)
-
-
-/*
- * Ring the packet output doorbell. This tells the packet
- * output hardware that "len" command words have been added
- * to its pending list. This command includes the required
- * SYNCW before the doorbell ring.
- *
- * @param port Port the packet is for
- * @param queue Queue the packet is for
- * @param len Length of the command in 64 bit words
- */
-extern void octeon_pko_doorbell_data(u_int port);
-
-//#define CORE_0_ONLY 1
-
-static inline void octeon_pko_ring_doorbell (u_int port, u_int queue,
- u_int len)
-{
- octeon_pko_doorbell_address_t ptr;
-
- ptr.word64 = 0;
- ptr.bits.mem_space = OCTEON_IO_SEG;
- ptr.bits.did = OCTEON_DID_PKT_SEND;
- ptr.bits.is_io = 1;
- ptr.bits.port = port;
- ptr.bits.queue = queue;
- OCTEON_SYNCWS;
- oct_write64(ptr.word64, len);
-}
-
-
-
-#define OCTEON_PKO_QUEUES_PER_PORT_INTERFACE0 1
-#define OCTEON_PKO_QUEUES_PER_PORT_INTERFACE1 1
-#define OCTEON_PKO_QUEUES_PER_PORT_PCI 1
-
-/*
- * octeon_pko_get_base_queue
- *
- * For a given port number, return the base pko output queue
- * for the port.
- */
-static inline u_int octeon_pko_get_base_queue (u_int port)
-{
- if (port < 16) {
- return (port * OCTEON_PKO_QUEUES_PER_PORT_INTERFACE0);
- }
- if (port < 32) {
- return (16 * OCTEON_PKO_QUEUES_PER_PORT_INTERFACE0 +
- (port - 16) * OCTEON_PKO_QUEUES_PER_PORT_INTERFACE1);
- }
- return (16 * OCTEON_PKO_QUEUES_PER_PORT_INTERFACE0 +
- 16 * OCTEON_PKO_QUEUES_PER_PORT_INTERFACE1 +
- (port - 32) * OCTEON_PKO_QUEUES_PER_PORT_PCI);
-}
-
-
-/*
- * For a given port number, return the number of pko output queues.
- *
- * @param port Port number
- * @return Number of output queues
- */
-static inline u_int octeon_pko_get_num_queues(u_int port)
-{
- if (port < 16) {
- return (OCTEON_PKO_QUEUES_PER_PORT_INTERFACE0);
- } else if (port<32) {
- return (OCTEON_PKO_QUEUES_PER_PORT_INTERFACE1);
- }
-
- return (OCTEON_PKO_QUEUES_PER_PORT_PCI);
-}
-
-
-
-/*
- * Externs
- */
-extern void octeon_pko_init(void);
-extern void octeon_pko_enable(void);
-extern void octeon_pko_disable(void);
-extern void octeon_pko_show(u_int start_port, u_int end_port);
-extern void octeon_pko_config(void);
-extern void octeon_pko_config_cmdbuf_global_defaults(u_int cmdbuf_pool, u_int elem_size);
-extern void octeon_pko_config_rgmx_ports(void);
-extern void octeon_pko_get_port_status(u_int, u_int, octeon_pko_port_status_t *status);
-extern octeon_pko_status_t octeon_pko_config_port(u_int port,
- u_int base_queue,
- u_int num_queues,
- const u_int priority[],
- u_int pko_output_cmdbuf_fpa_pool,
- octeon_pko_sw_queue_info_t sw_queues[]);
-
-
-#endif /* ___OCTEON_PKO__H___ */
diff --git a/sys/mips/cavium/dev/rgmii/octeon_rgmx.c b/sys/mips/cavium/dev/rgmii/octeon_rgmx.c
deleted file mode 100644
index 5b84af5..0000000
--- a/sys/mips/cavium/dev/rgmii/octeon_rgmx.c
+++ /dev/null
@@ -1,2328 +0,0 @@
-/***********************license start***************
- * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
- * reserved.
- *
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * 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.
- *
- * * Neither the name of Cavium Networks nor the names of
- * its contributors may be used to endorse or promote products
- * derived from this software without specific prior written
- * permission.
- *
- * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
- * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
- * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
- * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
- * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
- * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
- * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
- * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
- * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT
- * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
- *
- *
- * For any questions regarding licensing please contact marketing@caviumnetworks.com
- *
- ***********************license end**************************************/
-
-/*
- * octeon_rgmx.c RGMII Ethernet Interfaces on Octeon
- *
- */
-
-
-/*
- * Driver for the Reduced Gigabit Media Independent Interface (RGMII)
- * present on the Cavium Networks' Octeon chip.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/sysctl.h>
-#include <sys/bus.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/rman.h>
-#include <sys/power.h>
-#include <sys/smp.h>
-#include <sys/time.h>
-#include <sys/timetc.h>
-#include <sys/malloc.h>
-#include <sys/kthread.h>
-#include <sys/socket.h>
-#include <sys/sockio.h>
-#include <sys/mbuf.h>
-#include <sys/taskqueue.h>
-#include <vm/vm.h>
-#include <vm/pmap.h>
-
-#include <net/ethernet.h>
-#include <net/if.h>
-#include <net/if_dl.h>
-#include <net/if_mib.h>
-#include <net/if_media.h>
-#include <net/if_types.h>
-
-#include <netinet/in.h>
-#include <netinet/if_ether.h>
-
-#include <net/bpf.h>
-
-#include <machine/clock.h>
-#include <machine/locore.h>
-#include <machine/md_var.h>
-
-#include <mips/cavium/octeon_pcmap_regs.h>
-
-#include "octeon_fau.h"
-#include "octeon_fpa.h"
-#include "octeon_ipd.h"
-#include "octeon_pko.h"
-#include "octeon_pip.h"
-#include "octeon_rgmx.h"
-
-
-/* The "battleship" boards have 8 ports */
-#define OCTEON_RGMX_NUM_PORTS_MAX 8
-#define NUM_TX_PACKETS 80
-#define NUM_RX_PACKETS 300
-#define MAX_RX_BUFS (NUM_RX_PACKETS) * (OCTEON_RGMX_NUM_PORTS_MAX)
-#define MAX_TX_BUFS (NUM_TX_PACKETS)
-#define OCTEON_RGMX_DEV_NAME "rgmx"
-#define OCTEON_RGMX_MIN_PORT 0
-#define OCTEON_RGMX_MAX_PORT 19
-#define OCTEON_RGMX_OQUEUE_PER_PORT 8
-
-
-#define OCTEON_RGMX_SCHEDULED_ISRS 1 /* Use Scheduled ISRs from kernel tasks */
-
-
-#ifndef POW_MAX_LOOP
-#define POW_MAX_LOOP 0x800
-#endif
-
-
-/*
- * CIU related stuff for enabling POW interrupts
- */
-#define OCTEON_RGMX_CIU_INTX CIU_INT_0
-#define OCTEON_RGMX_CIU_ENX CIU_EN_0
-
-MALLOC_DEFINE(M_RGMII_WQE, "rgmii_wqe", "FPA pool for WQEs");
-
-/* Driver data */
-
-struct rgmx_softc_dev {
- device_t sc_dev; /* Device ID */
- uint64_t link_status;
- struct ifnet *ifp;
- int sc_unit;
-
- u_int port;
- u_int idx;
- u_char ieee[6];
-
- u_short txb_size; /* size of TX buffer, in bytes */
-
- /* Transmission buffer management. */
- u_short txb_free; /* free bytes in TX buffer */
- u_char txb_count; /* number of packets in TX buffer */
- u_char txb_sched; /* number of scheduled packets */
-
- /* Media information. */
- struct ifmedia media; /* used by if_media. */
- u_short mbitmap; /* bitmap for supported media; see bit2media */
- int defmedia; /* default media */
- struct ifqueue tx_pending_queue; /* Queue of mbuf given to PKO currently */
- octeon_pko_sw_queue_info_t *outq_ptr;
-
- struct mtx mtx;
-};
-
-
-/*
- * Device methods
- */
-static int rgmii_probe(device_t);
-static void rgmii_identify(driver_t *, device_t);
-static int rgmii_attach(device_t);
-
-
-
-/*
- * Octeon specific routines
- */
-static int octeon_has_4ports(void);
-static void octeon_config_rgmii_port(u_int port);
-static void octeon_rgmx_config_pip(u_int port);
-static void octeon_line_status_loop(void *);
-static void octeon_rx_loop(void *);
-static void octeon_config_hw_units_post_ports(void);
-static void octeon_config_hw_units_pre_ports(void);
-static void octeon_config_hw_units_port(struct rgmx_softc_dev *sc, u_int port);
-static struct rgmx_softc_dev *get_rgmx_softc(u_int port);
-static void octeon_rgmx_start_port(u_int port);
-static u_int octeon_rgmx_stop_port(u_int port);
-static u_int get_rgmx_port_ordinal(u_int port);
-static void octeon_rgmx_set_mac(u_int port);
-static void octeon_rgmx_init_sc(struct rgmx_softc_dev *sc, device_t dev, u_int port, u_int num_devices);
-static int octeon_rgmx_init_ifnet(struct rgmx_softc_dev *sc);
-static void octeon_rgmx_stop(struct rgmx_softc_dev *sc);
-static void octeon_rgmx_config_speed(u_int port, u_int);
-#ifdef DEBUG_RGMX_DUMP
-static void octeon_dump_rgmx_stats(u_int port);
-static void octeon_dump_pow_stats(void);
-#endif
-#ifdef __not_used__
-static void rgmx_timer_periodic(void);
-#endif
-static void octeon_rgmx_enable_RED_all(int, int);
-
-#ifdef OCTEON_RGMX_SCHEDULED_ISRS
-static void octeon_rgmx_isr_link(void *context, int pending);
-static void octeon_rgmx_isr_rxtx(void *context, int pending);
-static int octeon_rgmx_intr_fast(void *arg);
-#else
-static int octeon_rgmx_intr(void *arg);
-#endif
-
-
-
-
-
-
-
-/* Standard driver entry points. These can be static. */
-static void octeon_rgmx_init (void *);
-//static driver_intr_t rgmx_intr;
-static void octeon_rgmx_config_cam (struct ifnet *);
-static int octeon_rgmx_ioctl (struct ifnet *, u_long, caddr_t);
-static void octeon_rgmx_output_start (struct ifnet *);
-static void octeon_rgmx_output_start_locked (struct ifnet *);
-static int octeon_rgmx_medchange (struct ifnet *);
-static void octeon_rgmx_medstat (struct ifnet *, struct ifmediareq *);
-
-
-/* Mapping between media bitmap (in fe_softc.mbitmap) and ifm_media. */
-static int const bit2media [] = {
- IFM_ETHER | IFM_AUTO,
- IFM_ETHER | IFM_MANUAL,
- IFM_ETHER | IFM_10_T,
- IFM_ETHER | IFM_10_2,
- IFM_ETHER | IFM_10_5,
- IFM_ETHER | IFM_10_FL,
- IFM_ETHER | IFM_10_T,
- /* More can be added here... */
-};
-
-/* Mapping between media bitmap (in fe_softc.mbitmap) and ifm_media. */
-#define MB_HA 0x0001
-#define MB_HM 0x0002
-#define MB_HT 0x0004
-#define MB_H2 0x0008
-#define MB_H5 0x0010
-#define MB_HF 0x0020
-#define MB_FT 0x0040
-
-#define LEBLEN (ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN)
-
-
-static struct rgmx_softc_dev *rgmx_scdev_array[OCTEON_RGMX_NUM_PORTS_MAX] = {NULL};
-static u_int port_array[OCTEON_RGMX_NUM_PORTS_MAX] = {0};
-static u_int num_devices = 0;
-static octeon_pko_sw_queue_info_t output_queues_array[OCTEON_RGMX_NUM_PORTS_MAX * OCTEON_RGMX_OQUEUE_PER_PORT];
-static struct resource *irq_res; /* Interrupt resource. */
-static void *int_handler_tag;
-
-
-#ifdef OCTEON_RGMX_SCHEDULED_ISRS
-
-struct task link_isr_task;
-struct task rxtx_isr_task;
-struct taskqueue *tq; /* private task queue */
-
-#endif
-
-
-
-static u_int get_rgmx_port_ordinal (u_int port)
-{
- u_int idx;
-
- for (idx = 0; idx < OCTEON_RGMX_NUM_PORTS_MAX; idx++) {
- if (port_array[idx] == port) {
- return (idx);
- }
- }
- return (-1);
-}
-
-static struct rgmx_softc_dev *get_rgmx_softc (u_int port)
-{
- u_int idx;
-
- idx = get_rgmx_port_ordinal(port);
- if (idx != -1) {
- return (rgmx_scdev_array[idx]);
- }
- return (NULL);
-}
-
-
-
-static void octeon_rgmx_init_sc (struct rgmx_softc_dev *sc, device_t dev, u_int port, u_int num_devices)
-{
- int ii;
-
- /* No software-controllable media selection. */
- sc->mbitmap = MB_HM;
- sc->defmedia = MB_HM;
-
- sc->sc_dev = dev;
- sc->port = port;
- sc->idx = num_devices;
- sc->link_status = 0;
- sc->sc_unit = num_devices;
- sc->mbitmap = MB_HT;
- sc->defmedia = MB_HT;
- sc->tx_pending_queue.ifq_maxlen = NUM_TX_PACKETS;
- sc->tx_pending_queue.ifq_head = sc->tx_pending_queue.ifq_tail = NULL;
- sc->tx_pending_queue.ifq_len = sc->tx_pending_queue.ifq_drops = 0;
- mtx_init(&sc->tx_pending_queue.ifq_mtx, "if->sc->txpq.ifqmtx", NULL, MTX_DEF);
-
- sc->outq_ptr = &(output_queues_array[num_devices * OCTEON_RGMX_OQUEUE_PER_PORT]);
-
- for (ii = 0; ii < 6; ii++) {
- sc->ieee[ii] = octeon_mac_addr[ii];
- }
- sc->ieee[5] += get_rgmx_port_ordinal(port);
-
-}
-
-static int octeon_rgmx_init_ifnet (struct rgmx_softc_dev *sc)
-{
- struct ifnet *ifp;
-
- ifp = sc->ifp = if_alloc(IFT_ETHER);
- if (NULL == ifp) {
- device_printf(sc->sc_dev, "can not ifalloc for rgmx port\n");
- return (ENOSPC);
- }
- /*
- * Initialize ifnet structure
- */
- ifp->if_softc = sc;
- if_initname(sc->ifp, device_get_name(sc->sc_dev), device_get_unit(sc->sc_dev));
- ifp->if_start = octeon_rgmx_output_start;
- ifp->if_ioctl = octeon_rgmx_ioctl;
- ifp->if_hwassist = CSUM_TCP | CSUM_UDP;
- ifp->if_capabilities = IFCAP_HWCSUM;
- ifp->if_capenable = ifp->if_capabilities;
- ifp->if_init = octeon_rgmx_init;
- ifp->if_linkmib = NULL; // &sc->mibdata;
- ifp->if_linkmiblen = 0; // sizeof (sc->mibdata);
- /*
- * Set fixed interface flags.
- */
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
-// | IFF_NEEDSGIANT;
- if (ifp->if_snd.ifq_maxlen == 0)
- ifp->if_snd.ifq_maxlen = ifqmaxlen;
-
- ifmedia_init(&sc->media, 0, octeon_rgmx_medchange, octeon_rgmx_medstat);
- ifmedia_add(&sc->media, bit2media[0], 0, NULL);
- ifmedia_set(&sc->media, bit2media[0]);
-
- ether_ifattach(sc->ifp, sc->ieee);
-
- return (0);
-}
-
-
-
-/* Driver methods */
-
-
-/* ------------------------------------------------------------------- *
- * rgmii_identify() *
- * ------------------------------------------------------------------- */
-static void rgmii_identify (driver_t *drv, device_t parent)
-{
- BUS_ADD_CHILD(parent, 0, "rgmii", 0);
-}
-
-
-/* ------------------------------------------------------------------- *
- * rgmii_probe() *
- * ------------------------------------------------------------------- */
-static int rgmii_probe (device_t dev)
-{
- if (device_get_unit(dev) != 0)
- panic("can't probe/attach more rgmii devices\n");
-
- device_set_desc(dev, "Octeon RGMII");
- return (0);
-}
-
-
-
-/* ------------------------------------------------------------------- *
- * rgmii_attach() *
- * ------------------------------------------------------------------- */
-static int rgmii_attach (device_t dev)
-{
- struct rgmx_softc_dev *sc;
- device_t child;
- int iface, port, nr_ports, error;
- void *softc;
- int irq_rid;
-
- octeon_config_hw_units_pre_ports();
-
- /* Count interfaces and ports*/
- octeon_gmxx_inf_mode_t iface_mode;
- iface_mode.word64 = 0;
-
- for (iface = 0; iface < 2; iface++) {
- iface_mode.word64 = oct_read64(OCTEON_RGMX_INF_MODE(iface));
-
- /* interface is either disabled or SPI */
- if (!iface_mode.bits.en)
- continue;
- if (octeon_get_chipid() == OCTEON_CN3020_CHIP) {
- nr_ports = 2;
- } else {
- nr_ports = (octeon_has_4ports()) ? 4 : 3;
- if (iface_mode.bits.type ) {
- if (octeon_get_chipid() == OCTEON_CN5020_CHIP)
- nr_ports = 2;
- else
- continue;
- }
- }
-
- oct_write64(OCTEON_RGMX_TX_PRTS(iface), nr_ports);
-
- for (port = iface * 16; port < iface * 16 + nr_ports; port++) {
-
- child = device_add_child(dev, OCTEON_RGMX_DEV_NAME, num_devices);
- if (child == NULL)
- panic("%s: device_add_child() failed\n", __func__);
-
- softc = malloc(sizeof(struct rgmx_softc_dev), M_DEVBUF, M_NOWAIT | M_ZERO);
- if (!softc) {
- panic("%s malloc failed for softc\n", __func__);
- }
- device_set_softc(child, softc);
- device_set_desc(child, "Octeon RGMII");
- sc = device_get_softc(child);
- if (!sc) {
- printf(" No sc\n");
- num_devices++;
- continue;
- }
- port_array[num_devices] = port;
- rgmx_scdev_array[num_devices] = sc;
- RGMX_LOCK_INIT(sc, device_get_nameunit(child));
- octeon_rgmx_init_sc(sc, child, port, num_devices);
- octeon_config_hw_units_port(sc, port);
- if (octeon_rgmx_init_ifnet(sc)) {
- device_printf(dev, " ifinit failed for rgmx port %u\n", port);
- return (ENOSPC);
- }
- num_devices++;
- }
- }
-
- octeon_config_hw_units_post_ports();
-
- irq_rid = 0;
- irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &irq_rid, 0, 0, 1, RF_SHAREABLE | RF_ACTIVE);
- if (irq_res == NULL) {
- device_printf(dev, "failed to allocate irq\n");
- return (ENXIO);
- }
-
-
-#ifdef OCTEON_RGMX_SCHEDULED_ISRS
- /*
- * Single task queues for all child devices. Since POW gives us a unified
- * interrupt based on POW groups, not based on PORTs.
- */
- TASK_INIT(&rxtx_isr_task, 0, octeon_rgmx_isr_rxtx, NULL);
- TASK_INIT(&link_isr_task, 0, octeon_rgmx_isr_link, NULL);
- tq = taskqueue_create_fast("octeon_rgmx_taskq", M_NOWAIT,
- taskqueue_thread_enqueue, &tq);
- taskqueue_start_threads(&tq, 1, PI_NET, "%s taskq", device_get_nameunit(dev));
-
- error = bus_setup_intr(dev, irq_res, INTR_TYPE_NET, octeon_rgmx_intr_fast, NULL,
- NULL, &int_handler_tag);
- if (error != 0) {
- device_printf(dev, "bus_setup_intr returned %d\n", error);
- taskqueue_free(tq);
- tq = NULL;
- return (error);
- }
-
-#else /* OCTEON_RGMX_SCHEDULED_ISRS */
-
- error = bus_setup_intr(dev, irq_res, INTR_TYPE_NET, octeon_rgmx_intr, NULL,
- NULL, &int_handler_tag);
-
- if (error != 0) {
- device_printf(dev, "bus_setup_intr returned %d\n", error);
- tq = NULL;
- return (error);
- }
-
-#endif /* OCTEON_RGMX_SCHEDULED_ISRS */
-
- return (bus_generic_attach(dev));
-}
-
-
-
-
-#define OCTEON_MAX_RGMX_PORT_NUMS 32
-
-
-
-#define OCTEON_POW_RX_GROUP_NUM 0
-#define OCTEON_POW_TX_GROUP_NUM 1 /* If using TX WQE from PKO */
-
-#define OCTEON_POW_RX_GROUP_MASK (1 << OCTEON_POW_RX_GROUP_NUM)
-#define OCTEON_POW_TX_GROUP_MASK (1 << OCTEON_POW_TX_GROUP_NUM)
-#define OCTEON_POW_ALL_OUR_GROUPS_MASK (OCTEON_POW_RX_GROUP_MASK | OCTEON_POW_RX_GROUP_MASK)
-#define OCTEON_POW_ALL_GROUPS_MASK 0xffff
-#define OCTEON_POW_WORKQUEUE_INT (0x8001670000000200ull)
-#define OCTEON_POW_WORKQUEUE_INT_PC (0x8001670000000208ull)
-#define OCTEON_POW_WORKQUEUE_INT_THRESHOLD(group_num) ((0x8001670000000080ull+((group_num)*0x8)))
-#define OCTEON_RGMX_POW_NOS_CNT (0x8001670000000228ull)
-#define OCTEON_POW_INT_CNTR(core) (0x8001670000000100ull+((core)*0x8))
-#define OCTEON_POW_INPT_Q_ALL_QOS (0x8001670000000388ull)
-#define OCTEON_POW_INPT_QOS_GRP(grp) (0x8001670000000340ull + ((grp) * 0x8))
-
-
-
-
-#define NUM_RX_PACKETS_CTL (MAX_RX_BUFS + 3000)
-#define NUM_TX_PACKETS_CTL 40
-
-#define FPA_NOPOOL 0
-
-#define OCTEON_FPA_RX_PACKET_POOL 0
-#define OCTEON_FPA_RX_PACKET_POOL_WORDS 208 /* 2048 bytes */
-#define OCTEON_FPA_RX_PACKET_POOL_ELEM_SIZE (OCTEON_FPA_RX_PACKET_POOL_WORDS)
-#define OCTEON_FPA_RX_PACKET_POOL_ELEMENTS (MAX_RX_BUFS)
-#define OCTEON_RX_MAX_SIZE (OCTEON_FPA_RX_PACKET_POOL_WORDS * sizeof(uint64_t))
-
-#define OCTEON_FPA_WQE_RX_POOL 1
-#define OCTEON_FPA_WQE_RX_WORDS (OCTEON_CACHE_LINE_SIZE/8)
-#define OCTEON_FPA_WQE_RX_POOL_ELEM_SIZE (OCTEON_FPA_WQE_RX_WORDS)
-#define OCTEON_FPA_WQE_RX_POOL_ELEMENTS (NUM_RX_PACKETS_CTL)
-
-#define OCTEON_FPA_TX_PACKET_POOL 2
-#define OCTEON_FPA_TX_PACKET_POOL_WORDS 208 /* 2048 bytes */
-#define OCTEON_FPA_TX_PACKET_POOL_ELEM_SIZE (OCTEON_FPA_TX_PACKET_POOL_WORDS)
-#define OCTEON_FPA_TX_PACKET_POOL_ELEMENTS (MAX_TX_BUFS)
-#define OCTEON_TX_MAX_SIZE (OCTEON_FPA_TX_PACKET_POOL_WORDS * sizeof(uint64_t))
-
-#define OCTEON_FPA_TX_CMDBUF_POOL 3
-#define OCTEON_FPA_TX_CMD_SIZE 2
-#define OCTEON_FPA_TX_CMD_NUM 300
-#define OCTEON_FPA_TX_CMDBUF_POOL_WORDS (OCTEON_FPA_TX_CMD_SIZE * OCTEON_FPA_TX_CMD_NUM)
-#define OCTEON_FPA_TX_CMDBUF_POOL_ELEM_SIZE (OCTEON_FPA_TX_CMDBUF_POOL_WORDS +1)
-#define OCTEON_FPA_TX_CMDBUF_POOL_ELEMENTS (30 * OCTEON_RGMX_NUM_PORTS_MAX)
-
-#define FIRST_PARTICLE_SKIP 0
-#define NOT_FIRST_PARTICLE_SKIP 0
-
-#define ENABLE_BACK_PRESSURE 0
-#define RGMX_MAX_PAK_RECEIVE 5000000
-
-
-#ifdef OCTEON_RGMX_SCHEDULED_ISRS
-
-
-static void octeon_rgmx_isr_link (void *context, int pending)
-{
- octeon_line_status_loop(NULL);
-}
-
-
-static void octeon_rgmx_isr_rxtx (void *context, int pending)
-{
- octeon_rx_loop(NULL);
-}
-
-
-/*********************************************************************
- *
- * Fast Interrupt Service routine
- *
- *********************************************************************/
-
-//#define OCTEON_RGMX_POW_TIME_THR_INTS 1
-
-
-static int octeon_rgmx_intr_fast(void *arg)
-{
-
- int handled_flag = 0;
- uint64_t ciu_summary;
-
- ciu_summary = ciu_get_int_summary(CIU_THIS_CORE, OCTEON_RGMX_CIU_INTX,
- OCTEON_RGMX_CIU_ENX);
-
- if (ciu_summary & CIU_GENTIMER_BITS_ENABLE(CIU_GENTIMER_NUM_1)) {
-
- /*
- * Timer Interrupt for link status checks
- * Acknowledging it will mask it for this cycle.
- */
- ciu_clear_int_summary(CIU_THIS_CORE, OCTEON_RGMX_CIU_INTX,
- OCTEON_RGMX_CIU_ENX,
- CIU_GENTIMER_BITS_ENABLE(CIU_GENTIMER_NUM_1));
-
- taskqueue_enqueue(taskqueue_fast, &link_isr_task);
- handled_flag = 1;
- }
-
- if (ciu_summary & OCTEON_POW_ALL_GROUPS_MASK) {
-#ifndef OCTEON_RGMX_POW_TIME_THR_INTS
- /*
- * When using POW IQ/DSQ size based interrupts, then
- * ack the interrupts right away. So they don't interrupt
- * until the queue size goes to 0 again.
- */
- oct_write64(OCTEON_POW_WORKQUEUE_INT,
- 0x10001 << OCTEON_POW_RX_GROUP_NUM);
-
-#else
- /*
- * We use POW thresholds based interrupt signalled on timer
- * countdown. Acknowledge it now so that it doesn't
- * interrupt us until next countdown to zero.
- */
- oct_write64(OCTEON_POW_WORKQUEUE_INT,
- 0x1 << OCTEON_POW_RX_GROUP_NUM);
-#endif
-
- taskqueue_enqueue(tq, &rxtx_isr_task);
- handled_flag = 1;
- }
-
- return ((handled_flag) ? FILTER_HANDLED : FILTER_STRAY);
-}
-
-
-#else /* ! OCTEON_RGMX_SCHEDULED_ISRS */
-
-
-/*
- * octeon_rgmx_intr
- *
- * This is direct inline isr. Will do all its work and heavy-lifting in interrupt context.
- *
- * Also note that the RGMX_LOCK/UNLOCK code will have to checked/added, since that is new and
- * was not supported with this model.
- */
-static int octeon_rgmx_intr (void *arg)
-{
- int flag = 0;
- uint64_t ciu_summary;
-
- /*
- * read ciu to see if any bits are pow
- */
- while (1) {
- ciu_summary = ciu_get_int_summary(CIU_THIS_CORE, OCTEON_RGMX_CIU_INTX,
- OCTEON_RGMX_CIU_ENX);
-
- if ((ciu_summary & (OCTEON_POW_ALL_GROUPS_MASK | CIU_GENTIMER_BITS_ENABLE(CIU_GENTIMER_NUM_1))) == 0) {
- break;
- }
-
- flag = 1;
-
- if (ciu_summary & OCTEON_POW_ALL_GROUPS_MASK) {
- octeon_rx_loop(NULL);
- /*
- * Acknowledge the interrupt after processing queues.
- */
- oct_write64(OCTEON_POW_WORKQUEUE_INT, OCTEON_POW_RX_GROUP_MASK);
- }
- if (ciu_summary & CIU_GENTIMER_BITS_ENABLE(CIU_GENTIMER_NUM_1)) {
- octeon_line_status_loop(NULL);
- ciu_clear_int_summary(CIU_THIS_CORE, OCTEON_RGMX_CIU_INTX,
- OCTEON_RGMX_CIU_ENX,
- CIU_GENTIMER_BITS_ENABLE(CIU_GENTIMER_NUM_1));
- }
- }
-
- return ((flag) ? FILTER_HANDLED : FILTER_STRAY);
-}
-
-
-#endif /* OCTEON_RGMX_SCHEDULED_ISRS */
-
-
-
-static struct mbuf *octeon_rgmx_build_new_rx_mbuf(struct ifnet *ifp, void *data_start, u_int totlen);
-
-static struct mbuf *octeon_rgmx_build_new_rx_mbuf (struct ifnet *ifp, void *data_start, u_int totlen)
-{
- struct mbuf *m, *m0, *newm;
- caddr_t newdata;
- int len;
-
- if (totlen <= ETHER_HDR_LEN || totlen > LEBLEN - ETHER_CRC_LEN) {
-#ifdef LEDEBUG
- if_printf(ifp, "invalid packet size %d; dropping\n", totlen);
-#endif
- return (NULL);
- }
-
- MGETHDR(m0, M_DONTWAIT, MT_DATA);
- if (m0 == NULL) {
- return (NULL);
- }
-
- /* Initialize packet header info. */
- m0->m_pkthdr.rcvif = ifp;
- m0->m_pkthdr.len = totlen;
- m0->m_pkthdr.csum_flags = CSUM_IP_CHECKED | CSUM_IP_VALID | CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
- m0->m_pkthdr.csum_data = 0xffff;
- len = MHLEN;
- m = m0;
-
- while (totlen > 0) {
- if (totlen >= MINCLSIZE) {
- MCLGET(m, M_DONTWAIT);
- if ((m->m_flags & M_EXT) == 0)
- goto octeon_rgmx_build_new_rx_mbuf_bad;
- len = MCLBYTES;
- }
-
- if (m == m0) {
- newdata = (caddr_t)ALIGN(m->m_data + ETHER_HDR_LEN) - ETHER_HDR_LEN;
- len -= newdata - m->m_data;
- m->m_data = newdata;
- }
-
- /* Set the length of this mbuf. */
- m->m_len = len = min(totlen, len);
- bcopy(data_start, mtod(m, caddr_t), len);
- data_start = (void *) (((u_long) (data_start)) + len);
-
- totlen -= len;
- if (totlen > 0) {
- MGET(newm, M_DONTWAIT, MT_DATA);
- if (newm == 0)
- goto octeon_rgmx_build_new_rx_mbuf_bad;
- len = MLEN;
- m = m->m_next = newm;
- }
- }
-
- return (m0);
-
-octeon_rgmx_build_new_rx_mbuf_bad:
-
- m_freem(m0);
- return (NULL);
-}
-
-
-
-//#define DEBUG_RX 1
-
-static void octeon_rgmx_rx_process_work (octeon_wqe_t *work, u_int port)
-{
- struct rgmx_softc_dev *sc;
- struct ifnet *ifp;
- u_int len;
- void *data_start, *new_data_start;
- struct mbuf *mbuf;
-
-//#define DEBUG_RX_PKT_DUMP 1
-#ifdef DEBUG_RX_PKT_DUMP
- int i; u_char *dc;
-#endif
-
- data_start = octeon_pow_pktptr_to_kbuffer(work->packet_ptr);
-
-//#define DEBUG_RX2
-#ifdef DEBUG_RX2
- printf(" WQE 0x%X: port:%u ", work, port);
- printf(" Grp: %u, %llX Tag: %u %llX type: %u 0x%llx\n",
- work->grp, work->grp, work->tag, work->tag, work->tag_type, work->tag_type);
-#endif
-
- if ((port >= OCTEON_RGMX_MIN_PORT) || (port <= OCTEON_RGMX_MAX_PORT)) {
-
- sc = get_rgmx_softc(port);
-
- if (!sc || !sc->ifp) {
-
- printf(" octeon_rgmx_rx_process_work No sc or sc->ifp - port:%u", port);
- } else {
-
- ifp = sc->ifp;
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
-
- if (!work->word2.bits.rcv_error) {
-
- len = work->len;
-
- /*
- * We cannot pass the same FPA phys-buffer higher up.
- * User space will not be able to use this phys-buffer.
- *
- * Start building a mbuf packet here using data_start & len.
- */
-
- new_data_start = data_start;
- if (!work->word2.bits.not_IP) {
- new_data_start = (void *) (((unsigned long) (new_data_start)) + 14);
- /* mark it as checksum checked */
- } else {
- new_data_start = (void *) (((unsigned long) (new_data_start)) + 8);
- }
-
-#ifdef DEBUG_RX_PKT_DUMP
- dc = new_data_start; printf("In:\n");
- for (i = 0; i < len; i++) { if (!(i % 16)) printf ("\n"); printf(" %02X", dc[i]); }
-#endif
-
- mbuf = octeon_rgmx_build_new_rx_mbuf(ifp, new_data_start, len);
- if (mbuf) {
-// printf(" Passing pkt to ifp: pkt_len: %u len: %u ", mbuf->m_pkthdr.len, mbuf->m_len);
-#ifdef DEBUG_RX_PKT_DUMP
-
- dc = mtod(mbuf, u_char *); printf("\n"); printf("In: ");
- for (i = 0; i < mbuf->m_len; i++) { if (!(i % 16)) printf ("\n"); printf(" %02X", dc[i]); }
-
-#endif
-
- /* Feed the packet to upper layer. */
- (*ifp->if_input)(ifp, mbuf);
- ifp->if_ipackets++;
-
- } else { /* mbuf error */
- if_printf(ifp, "mbuf rx construct error\n");
- printf(" mbuf rx construct error\n");
- ifp->if_ierrors++;
- } /* mbuf error */
-
- } else { /* rcv_error */
- ifp->if_ierrors++;
- } /* rcv_error */
-
- } /* IFF_DRV_RUNNING */
-
- } /* sc && sc->ifp */
-
- } else { /* port number */
- printf(" rgmx_rx:%u bad port\n", port);
- }
-
- octeon_fpa_free(data_start, OCTEON_FPA_RX_PACKET_POOL, 0);
- octeon_fpa_free((void *)work, OCTEON_FPA_WQE_RX_POOL, 0);
-}
-
-
-
-
-/* ------------------------------------------------------------------- *
- * octeon_rx_loop() *
- * ------------------------------------------------------------------- */
-
-
-//#define OCTEON_VISUAL_RGMX 1
-#ifdef OCTEON_VISUAL_RGMX
-static int where0 = 0;
-static int where1 = 0;
-#endif
-
-static void octeon_rx_loop (void *unused)
-{
- u_int core_id;
- uint64_t prev_grp_mask;
- u_int pak_count;
- octeon_wqe_t *work;
-
- core_id = octeon_get_core_num();
- pak_count = 0;
-
- /* Only allow work for our group */
- prev_grp_mask = oct_read64(OCTEON_POW_CORE_GROUP_MASK(core_id));
- oct_write64(OCTEON_POW_CORE_GROUP_MASK(core_id), OCTEON_POW_ALL_GROUPS_MASK);
-
-
-#ifdef OCTEON_VISUAL_RGMX
- octeon_led_run_wheel(&where0, 3);
-#endif
- while(1) {
-
- if (pak_count++ > RGMX_MAX_PAK_RECEIVE) {
- break;
- }
-
- work = octeon_pow_work_request_sync(OCTEON_POW_WAIT);
-
- if (work == NULL) {
- /*
- * No more incoming packets. We can take a break now.
- */
- break;
- }
-
-#ifdef OCTEON_VISUAL_RGMX
- octeon_led_run_wheel(&where1, 4);
-#endif
- octeon_rgmx_rx_process_work(work, work->ipprt);
-
- }
-
- oct_write64(OCTEON_POW_CORE_GROUP_MASK(core_id), prev_grp_mask);
-}
-
-
-static void *octeon_rgmx_write_mbufs_to_fpa_buff (struct rgmx_softc_dev *sc, struct mbuf *m, u_int len)
-{
- struct mbuf *mp;
- void *data_area;
- u_char *write_offset;
-
- /*
- * FIXME
- *
- * Compare len with max FPA-tx-packet size. Or else we will possibly corrupt the next pkt.
- */
-
-
- /*
- * Get an FPA buffer from Xmit-packets FPA pool
- */
- data_area = octeon_fpa_alloc(OCTEON_FPA_TX_PACKET_POOL);
- if (!data_area) {
- /*
- * Fail. No room. No resources.
- */
- return (NULL);
- }
-
- /*
- * Transfer the data from mbuf chain to the transmission buffer.
- */
- write_offset = data_area;
- for (mp = m; mp != 0; mp = mp->m_next) {
- if (mp->m_len) {
- bcopy(mtod(mp, caddr_t), write_offset, mp->m_len);
- write_offset = (u_char *) (((u_long) write_offset) + mp->m_len);
- }
- }
- return (data_area);
-}
-
-
-static u_int octeon_rgmx_pko_xmit_packet (struct rgmx_softc_dev *sc, void *out_buff, u_int len, u_int checksum)
-{
- octeon_pko_command_word0_t pko_cmd;
- octeon_pko_packet_ptr_t pko_pkt_word;
- u_long temp;
- u_short xmit_cmd_index;
- uint64_t *xmit_cmd_ptr;
- uint64_t xmit_cmd_state;
- int queue = 0; // we should randomize queue # based on core num. Using same
- // queue 0 for this port, by all cores on is less efficient.
-
- /*
- * Prepare the PKO buffer and command word.
- * Cmd Buf Word 0
- * No FAU
- * Set #-segs and #-bytes
- */
- pko_cmd.word64 = 0;
- pko_cmd.bits.segs = 1;
- pko_cmd.bits.total_bytes = len;
- if (checksum) {
- pko_cmd.bits.ipoffp1 = ETHER_HDR_LEN + 1; /* IPOffP1 is +1 based. 1 means offset 0 */
- }
-
- /*
- * Build the PKO buffer pointer. PKO Cmd Buf Word 1
- */
- pko_pkt_word.word64 = 0;
- pko_pkt_word.bits.addr = OCTEON_PTR2PHYS(out_buff);
- pko_pkt_word.bits.pool = OCTEON_FPA_TX_PACKET_POOL;
- pko_pkt_word.bits.size = 2048; // dummy. Actual len is above.
-
-#ifdef DEBUG_TX
- printf(" PKO: 0x%llX 0x%llX ", pko_cmd.word64, pko_pkt_word.word64);
-#endif
-
- /*
- * Get the queue command ptr location from the per port per queue, pko info struct.
- */
- octeon_spinlock_lock(&(sc->outq_ptr[queue].lock));
-#ifdef DEBUG_TX
- printf(" xmit: sc->outq_ptr[queue].xmit_command_state: 0x%llX ", sc->outq_ptr[queue].xmit_command_state);
-#endif
- xmit_cmd_state = sc->outq_ptr[queue].xmit_command_state;
- sc->outq_ptr[queue].xmit_command_state = xmit_cmd_state + 2;
-
- temp = (u_long) (xmit_cmd_state >> OCTEON_PKO_INDEX_BITS);
-#ifdef DEBUG_TX
- printf(" temp: 0x%X ", temp);
-#endif
- xmit_cmd_ptr = (uint64_t *) MIPS_PHYS_TO_KSEG0(temp);
- xmit_cmd_index = xmit_cmd_state & OCTEON_PKO_INDEX_MASK;
- xmit_cmd_ptr += xmit_cmd_index;
-
- /*
- * We end the PKO cmd buffer at odd boundary. Towards the end we will have
- * 4 or 3 or 2 or 1 or 0 word remaining. Case of 4, 2, or 0 can never happen.
- * We only care when we have 3 words remaining. In this case we write our 2 words
- * for PKO command and 3rd word as chain for next PKO cmd buffer.
- */
- xmit_cmd_ptr[0] = pko_cmd.word64;
-
- if (xmit_cmd_index < (OCTEON_FPA_TX_CMDBUF_POOL_WORDS - 2)) {
- /*
- * Plenty of space left. Write our 2nd word and worry the next time.
- */
- xmit_cmd_ptr[1] = pko_pkt_word.word64;
-
- } else {
- /*
- * 3 words or less are left. We write our 2nd word now and then put in a chain link
- * to new PKO cmd buf.
- */
- uint64_t phys_cmd_buf = octeon_fpa_alloc_phys(OCTEON_FPA_TX_CMDBUF_POOL);
-
- if (!phys_cmd_buf) {
- /*
- * FPA pool for xmit-buffer-commands is empty.
- */
- sc->outq_ptr[queue].xmit_command_state -= 2;
- octeon_spinlock_unlock(&(sc->outq_ptr[queue].lock));
- return (0);
- }
-
- xmit_cmd_ptr[1] = pko_pkt_word.word64;
- xmit_cmd_ptr[2] = phys_cmd_buf;
-
- sc->outq_ptr[queue].xmit_command_state = (phys_cmd_buf << OCTEON_PKO_INDEX_BITS);
- }
- /*
- * Unlock queue structures.
- */
- octeon_spinlock_unlock(&(sc->outq_ptr[queue].lock));
-
- /*
- * 2 words incremented in PKO. Ring the doorbell.
- */
-#ifdef DEBUG_TX
- printf(" Ringing doorbell: Port %u Queue %u words 2", sc->port, octeon_pko_get_base_queue(sc->port) + queue);
-#endif
- octeon_pko_ring_doorbell(sc->port, octeon_pko_get_base_queue(sc->port) + queue, 2);
-
- return (1);
-}
-
-
-static void octeon_rgmx_xmit_mark_buffers_done(struct rgmx_softc_dev *sc, u_int n);
-
-static void octeon_rgmx_xmit_mark_buffers_done (struct rgmx_softc_dev *sc, u_int n)
-{
- struct mbuf *m;
- u_int i;
-
- for (i = 0; i < n; i++) {
- /*
- * Remove packets in queue. Leaving a lag of 3, to allow for PKO in-flight xmission
- */
- if (_IF_QLEN(&sc->tx_pending_queue) > 4) {
- IF_DEQUEUE(&sc->tx_pending_queue, m);
- if (!m) {
- break; // Queue became empty now. Break out.
- }
- /*
- * Return the mbuf to system.
- */
- m_freem(m);
- }
- }
- if (!i) {
- return; // Nothing removed from queue.
- }
-
- /*
- * The transmitter is no more active.
- * Reset output active flag and watchdog timer.
- */
- sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-}
-
-
-#define OCTEON_RGMX_FLUSH_N_XMIT_MBUFS_EACH_LOOP 5
-#define OCTEON_RGMX_FLUSH_PENDING_MBUFS_MAX 1000
-
-#ifdef __not_used__
-/*
- * octeon_rgmx_output_flush
- *
- * Drop all packets queued at ifnet layer.
- */
-static void octeon_rgmx_output_flush (struct ifnet *ifp)
-{
- struct mbuf *m;
- u_int max_flush = OCTEON_RGMX_FLUSH_PENDING_MBUFS_MAX; /* Arbitrarily high number */
-
- while (max_flush-- && _IF_QLEN(&ifp->if_snd)) {
- /*
- * Get the next mbuf Packet chain to flush.
- */
- IF_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL) {
- /* No more packets to flush */
- break;
- }
- _IF_DROP(&ifp->if_snd);
- m_freem(m);
- ifp->if_oerrors++;
- }
-}
-#endif
-
-/*
- * octeon_rgmx_output_start
- *
- * Start output on interface.
- */
-static void octeon_rgmx_output_start (struct ifnet *ifp)
-{
- struct rgmx_softc_dev *sc = ifp->if_softc;
-
- RGMX_LOCK(sc);
- octeon_rgmx_output_start_locked(ifp);
- RGMX_UNLOCK(sc);
-}
-
-
-
-/*
- * octeon_rgmx_output_start_locked
- *
- * Start output on interface. Assume Driver locked
- */
-static void octeon_rgmx_output_start_locked (struct ifnet *ifp)
-{
- struct rgmx_softc_dev *sc = ifp->if_softc;
- struct mbuf *m;
- u_int len, need_l4_checksum;
- void *out_buff;
-
- /*
- * Take out some of the last queued mbuf's from xmit-pending queue
- */
- octeon_rgmx_xmit_mark_buffers_done(sc, OCTEON_RGMX_FLUSH_N_XMIT_MBUFS_EACH_LOOP);
-
- while (1) {
- /*
- * See if there is room to put another packet in the buffer.
- * We *could* do better job by peeking the send queue to
- * know the length of the next packet. Current version just
- * tests against the worst case (i.e., longest packet). FIXME.
- *
- * When adding the packet-peek feature, don't forget adding a
- * test on txb_count against QUEUEING_MAX.
- * There is a little chance the packet count exceeds
- * the limit. Assume transmission buffer is 8KB (2x8KB
- * configuration) and an application sends a bunch of small
- * (i.e., minimum packet sized) packets rapidly. An 8KB
- * buffer can hold 130 blocks of 62 bytes long...
- */
-
- /*
- * If unable to send more.
- */
- if (_IF_QLEN(&sc->tx_pending_queue) >= MAX_TX_BUFS) {
- printf(" Xmit not possible. NO room %u", _IF_QLEN(&sc->tx_pending_queue));
- goto indicate_active;
- }
-
-
- /*
- * Get the next mbuf chain for a packet to send.
- */
- IF_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL) {
- /* No more packets to send. */
- goto indicate_inactive;
- }
-
- len = m->m_pkthdr.len;
- /*
- * Should never send big packets. If such a packet is passed,
- * it should be a bug of upper layer. We just ignore it.
- * ... Partial (too short) packets, neither.
- */
- if (len < ETHER_HDR_LEN ||
- len > ETHER_MAX_LEN - ETHER_CRC_LEN) {
- /*
- * Fail. Bad packet size. Return the mbuf to system.
- */
- if_printf(ifp,
- "got an out-of-spec packet (%u bytes) to send\n", len);
- m_freem(m);
- goto indicate_active;
- }
-
- /*
- * Copy the mbuf chain into the transmission buffer.
- * txb_* variables are updated as necessary.
- */
- out_buff = octeon_rgmx_write_mbufs_to_fpa_buff(sc, m, len);
- if (!out_buff) {
- /*
- * No FPA physical buf resource.
- * Let's requeue it back. And slow it down for a while.
- */
- IF_PREPEND(&ifp->if_snd, m);
- goto indicate_active;
- }
-
- need_l4_checksum = (m->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP)) ? 1 : 0;
-
- /*
- * put the mbuf onto pending queue
- */
-//#define DEBUG_TX_PKT_DUMP 1
-#ifdef DEBUG_TX_PKT_DUMP
- int ii;
- u_char *dc = out_buff;
-
- printf("\n"); printf("Out: ");
- for (ii = 0; ii < len; ii++) printf(" %X", dc[ii]); printf("\n");
-#endif
-
- ETHER_BPF_MTAP(ifp, m);
-
- IF_ENQUEUE(&sc->tx_pending_queue, m);
-
- /*
- * Pass the mbuf data packet to PKO for xmission.
- */
- octeon_rgmx_pko_xmit_packet(sc, out_buff, len, need_l4_checksum);
-
- ifp->if_opackets++;
- }
-
-indicate_inactive:
- /*
- * We are using the !OACTIVE flag to indicate to
- * the outside world that we can accept an
- * additional packet rather than that the
- * transmitter is _actually_ active. Indeed, the
- * transmitter may be active, but if we haven't
- * filled all the buffers with data then we still
- * want to accept more.
- */
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- return;
-
-
-indicate_active:
- /*
- * The transmitter is active, and there are no room for
- * more outgoing packets in the transmission buffer.
- */
- ifp->if_oerrors++;
-// sc->mibdata.dot3StatsInternalMacTransmitErrors++;
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- return;
-}
-
-
-
-
-/* ------------------------------------------------------------------- *
- * octeon_config_hw_units() *
- * ------------------------------------------------------------------- *
- *
- * Initialize Octeon hardware components. To get the RGMX going.
- *
- */
-static void octeon_config_hw_units_pre_ports (void)
-{
-
- /* Enable FPA */
- octeon_enable_fpa();
-
- /* Enable PKO */
- octeon_pko_enable();
-
- /* Init PKO */
- octeon_pko_init();
-
-
- /* Fill FPA */
-
- /*
- * Input Buffers Pool
- * Pool 0
- */
- octeon_fpa_fill_pool_mem(OCTEON_FPA_RX_PACKET_POOL, OCTEON_FPA_RX_PACKET_POOL_ELEM_SIZE,
- OCTEON_FPA_RX_PACKET_POOL_ELEMENTS);
-
- /*
- * WQE Blocks Pool
- * Pool 1
- */
- octeon_fpa_fill_pool_mem(OCTEON_FPA_WQE_RX_POOL, OCTEON_FPA_WQE_RX_POOL_ELEM_SIZE,
- OCTEON_FPA_WQE_RX_POOL_ELEMENTS);
-
- /*
- * PKO Command Pool
- * Pool 3
- */
- octeon_fpa_fill_pool_mem(OCTEON_FPA_TX_CMDBUF_POOL, OCTEON_FPA_TX_CMDBUF_POOL_ELEM_SIZE,
- OCTEON_FPA_TX_CMDBUF_POOL_ELEMENTS);
-
- /*
- * Output Buffers Pool
- * Pool 2
- */
- octeon_fpa_fill_pool_mem(OCTEON_FPA_TX_PACKET_POOL, OCTEON_FPA_TX_PACKET_POOL_ELEM_SIZE,
- OCTEON_FPA_TX_PACKET_POOL_ELEMENTS);
-
-
-
- octeon_rgmx_enable_RED_all(OCTEON_FPA_RX_PACKET_POOL_ELEMENTS >> 2, OCTEON_FPA_RX_PACKET_POOL_ELEMENTS >> 3);
-
- /* Configure IPD */
- octeon_ipd_config(OCTEON_FPA_RX_PACKET_POOL_WORDS,
- FIRST_PARTICLE_SKIP / 8,
- NOT_FIRST_PARTICLE_SKIP / 8,
- FIRST_PARTICLE_SKIP / 128,
- NOT_FIRST_PARTICLE_SKIP / 128,
- OCTEON_FPA_WQE_RX_POOL,
- OCTEON_IPD_OPC_MODE_STF,
- ENABLE_BACK_PRESSURE);
-
- /*
- * PKO setup Output Command Buffers
- */
- octeon_pko_config_cmdbuf_global_defaults(OCTEON_FPA_TX_CMDBUF_POOL,
- OCTEON_FPA_TX_CMDBUF_POOL_ELEM_SIZE);
-
-}
-
-
-
-static void octeon_config_hw_units_port (struct rgmx_softc_dev *sc, u_int port)
-{
- const u_int priorities[8] = {8,8,8,8,8,8,8,8};
- u_int total_queues, base_queue;
-
- octeon_config_rgmii_port(port);
-
- total_queues = octeon_pko_get_num_queues(port);
- base_queue = octeon_pko_get_base_queue(port);
- /* Packet output configures Queue and Ports */
- octeon_pko_config_port(port, base_queue,
- total_queues,
- priorities,
- OCTEON_FPA_TX_CMDBUF_POOL,
- sc->outq_ptr);
-
- octeon_rgmx_set_mac(port);
-
- /* Setup Port input tagging */
- octeon_rgmx_config_pip(port);
-}
-
-
-typedef union
-{
- uint64_t word64;
- struct
- {
- uint64_t rsvd3 : 35;
- uint64_t enable : 1;
- uint64_t time_thr : 4;
- uint64_t rsvd2 : 1;
- uint64_t ds_thr : 11;
- uint64_t rsvd : 1;
- uint64_t iq_thr : 11;
- } bits;
-} octeon_rgmx_pow_int_threshold_t;
-
-typedef union
-{
- uint64_t word64;
- struct
- {
- uint64_t rsvd : 36;
- uint64_t tc_cnt : 4;
- uint64_t ds_cnt : 12;
- uint64_t iq_cnt : 12;
- } bits;
-} octeon_rgmx_pow_int_cnt_t;
-
-typedef union
-{
- uint64_t word64;
- struct
- {
- uint64_t rsvd3 : 4;
- uint64_t thr_freq : 28; // R/O
- uint64_t rsvd2 : 4;
- uint64_t thr_period : 20;
- uint64_t rsvd : 8;
- } bits;
-} octeon_rgmx_pow_int_pc_t;
-
-
-typedef union
-{
- uint64_t word64;
- struct
- {
- uint64_t rsvd : 52;
- uint64_t nos_cnt : 12;
- } bits;
-} octeon_rgmx_pow_nos_cnt;
-
-
-
-typedef union
-{
- uint64_t word64;
- struct
- {
- uint64_t rsvd : 32;
- uint64_t inb_pkts : 32;
- } bits;
-} octeon_rgmx_pip_inb_pkts;
-
-typedef union
-{
- uint64_t word64;
- struct
- {
- uint64_t rsvd : 48;
- uint64_t inb_errs : 16;
- } bits;
-} octeon_rgmx_pip_inb_errs;
-
-
-
-typedef union
-{
- uint64_t word64;
- struct
- {
- uint64_t rsvd : 32;
- uint64_t iq_cnt : 32;
- } bits;
-} octeon_pow_inpt_q_all_qos;
-
-
-
-typedef union
-{
- uint64_t word64;
- struct
- {
- uint64_t rsvd : 32;
- uint64_t iq_cnt : 32;
- } bits;
-} octeon_pow_inpt_q_grp_qos;
-
-
-static void octeon_config_hw_units_post_ports (void)
-{
-
- octeon_rgmx_pow_int_threshold_t thr;
- octeon_rgmx_pow_int_pc_t intpc;
-
- thr.word64 = 0;
- intpc.word64 = 0;
- intpc.bits.thr_freq = (500 * 1000 * 1000) / (1000 * 16 * 256);
-
-#ifdef OCTEON_RGMX_POW_TIME_THR_INTS
- thr.bits.enable = 1;
- thr.bits.time_thr = 0xf;
- oct_write64(OCTEON_POW_WORKQUEUE_INT_THRESHOLD(OCTEON_POW_RX_GROUP_NUM), thr.word64);
-
- oct_write64(OCTEON_POW_WORKQUEUE_INT_PC, intpc.word64);
-
-#else
- thr.bits.ds_thr = thr.bits.iq_thr = 1; // Only if doing absolute queue-cnt interrupts.
- oct_write64(OCTEON_POW_WORKQUEUE_INT_THRESHOLD(OCTEON_POW_RX_GROUP_NUM), thr.word64);
-#endif
-
- ciu_enable_interrupts(PCPU_GET(cpuid), OCTEON_RGMX_CIU_INTX, OCTEON_RGMX_CIU_ENX,
- (OCTEON_POW_RX_GROUP_MASK |
- CIU_GENTIMER_BITS_ENABLE(CIU_GENTIMER_NUM_1)), CIU_MIPS_IP2);
-
- ciu_clear_int_summary(CIU_THIS_CORE, OCTEON_RGMX_CIU_INTX,
- OCTEON_RGMX_CIU_ENX, CIU_GENTIMER_BITS_ENABLE(CIU_GENTIMER_NUM_1));
-
- octeon_ciu_start_gtimer(CIU_GENTIMER_NUM_1, OCTEON_GENTIMER_PERIODIC,
- OCTEON_GENTIMER_LEN_1SEC);
- /*
- * Enable IPD
- */
- octeon_ipd_enable();
-}
-
-
-
-
-
-static void octeon_rgmx_config_pip (u_int port)
-{
- octeon_pip_gbl_cfg_t pip_config;
- octeon_pip_port_cfg_t pip_port_config;
- octeon_pip_port_tag_cfg_t pip_tag_config;
-
- /*
- * PIP Global config
- */
- pip_config.word64 = 0;
- pip_config.bits.max_l2 = 1;
- oct_write64(OCTEON_PIP_GBL_CFG, pip_config.word64);
-
- /*
- * PIP Port config
- */
- pip_port_config.word64 = 0;
- pip_port_config.bits.mode = OCTEON_PIP_PORT_CFG_MODE_SKIPL2;
- pip_port_config.bits.qos = port & 0x7;
- pip_port_config.bits.crc_en = 1;
-
-
- /*
- * PIP -> POW tags config
- *
- * We don't use any pkt input fields for tag hash, except for Port#
- */
- pip_tag_config.word64 = 0;
-
- pip_tag_config.bits.grptag = 0;
- pip_tag_config.bits.grptagmask = 0xf;
- pip_tag_config.bits.grptagbase = 1;
-
- pip_tag_config.bits.ip6_src_flag = 0;
- pip_tag_config.bits.ip6_dst_flag = 0;
- pip_tag_config.bits.ip6_sprt_flag = 0;
- pip_tag_config.bits.ip6_dprt_flag = 0;
- pip_tag_config.bits.ip6_nxth_flag = 0;
-
- pip_tag_config.bits.ip4_src_flag = 1;
- pip_tag_config.bits.ip4_dst_flag = 1;
- pip_tag_config.bits.ip4_sprt_flag = 1;
- pip_tag_config.bits.ip4_dprt_flag = 1;
- pip_tag_config.bits.ip4_pctl_flag = 1;
-
- pip_tag_config.bits.tcp6_tag_type = 0;
- pip_tag_config.bits.tcp4_tag_type = 0;
- pip_tag_config.bits.ip6_tag_type = 0;
- pip_tag_config.bits.ip4_tag_type = 0;
- pip_tag_config.bits.inc_prt_flag = 1;
- pip_tag_config.bits.non_tag_type = OCTEON_POW_TAG_TYPE_NULL;
- pip_tag_config.bits.grp = OCTEON_POW_RX_GROUP_NUM;
-
- octeon_pip_config_port(port, pip_port_config, pip_tag_config);
-
- oct_write64(OCTEON_POW_CORE_GROUP_MASK(OUR_CORE), OCTEON_POW_ALL_GROUPS_MASK);
-
-}
-
-
-/*
- * octeon_rgmx_stop_port
- *
- */
-static u_int octeon_rgmx_stop_port (u_int port)
-{
- int interface = INTERFACE(port);
- int index = INDEX(port);
- octeon_rgmx_prtx_cfg_t gmx_cfg;
- u_int last_enabled = 0;
-
- gmx_cfg.word64 = oct_read64(OCTEON_RGMX_PRTX_CFG(index, interface));
- last_enabled = (gmx_cfg.bits.en == 1);
- gmx_cfg.bits.en = 0;
- oct_write64(OCTEON_RGMX_PRTX_CFG(index, interface), gmx_cfg.word64);
- return (last_enabled);
-}
-
-static void octeon_rgmx_start_port(u_int port)
-{
- int interface = INTERFACE(port);
- int index = INDEX(port);
- octeon_rgmx_prtx_cfg_t gmx_cfg;
-
- gmx_cfg.word64 = oct_read64(OCTEON_RGMX_PRTX_CFG(index, interface));
- gmx_cfg.bits.en = 1;
- oct_write64(OCTEON_RGMX_PRTX_CFG(index, interface), gmx_cfg.word64);
-}
-
-
-static void octeon_rgmx_stop (struct rgmx_softc_dev *sc)
-{
- octeon_rgmx_stop_port(sc->port);
-
- /* Reset transmitter variables and interface flags. */
- sc->ifp->if_drv_flags &= ~(IFF_DRV_OACTIVE | IFF_DRV_RUNNING);
- sc->txb_count = 0;
- sc->txb_sched = 0;
-}
-
-
-/* Change the media selection. */
-static int octeon_rgmx_medchange (struct ifnet *ifp)
-{
- struct rgmx_softc_dev *sc = ifp->if_softc;
-
-#ifdef DIAGNOSTIC
- /* If_media should not pass any request for a media which this
- interface doesn't support. */
- int b;
-
- for (b = 0; bit2media[b] != 0; b++) {
- if (bit2media[b] == sc->media.ifm_media) break;
- }
- if (((1 << b) & sc->mbitmap) == 0) {
- if_printf(sc->ifp,
- "got an unsupported media request (0x%x)\n",
- sc->media.ifm_media);
- return EINVAL;
- }
-#endif
-
- /* We don't actually change media when the interface is down.
- fe_init() will do the job, instead. Should we also wait
- until the transmission buffer being empty? Changing the
- media when we are sending a frame will cause two garbages
- on wires, one on old media and another on new. FIXME */
- if (sc->ifp->if_flags & IFF_UP) {
- printf(" Media change requested while IF is up\n");
- } else {
- printf(" Media change requested while IF is Down\n");
- }
-
- return 0;
-}
-
-
-static void octeon_rgmx_medstat (struct ifnet *ifp, struct ifmediareq *ifm)
-{
- struct rgmx_softc_dev *sc = ifp->if_softc;
- octeon_rgmx_rxx_rx_inbnd_t link_status;
-
- octeon_rgmx_config_speed(sc->port, 1);
-
- RGMX_LOCK(sc);
-
- ifm->ifm_status = IFM_AVALID;
- ifm->ifm_active = IFM_ETHER;
-
- /*
- * Parse link status.
- */
- link_status.word64 = sc->link_status;
-
- if (!link_status.bits.status) {
- RGMX_UNLOCK(sc);
- return;
- }
-
- ifm->ifm_status |= IFM_ACTIVE;
-
- switch (link_status.bits.speed) {
- case 0:
- ifm->ifm_active |= IFM_10_T;
- break;
- case 1:
- ifm->ifm_active |= IFM_100_TX;
- break;
- case 2:
- ifm->ifm_active |= IFM_1000_T;;
- break;
- default:
- /* Unknown! */
- break;
- }
-
- /*
- * Check duplex.
- */
- if (link_status.bits.duplex == 1)
- ifm->ifm_active |= IFM_FDX;
- else
- ifm->ifm_active |= IFM_HDX;
-
- RGMX_UNLOCK(sc);
-}
-
-static void octeon_rgmx_config_cam(struct ifnet *ifp)
-{
- struct rgmx_softc_dev *sc = ifp->if_softc;
- u_int port = sc->port;
- int index = INDEX(port);
- int iface = INTERFACE(port);
- u_int last_enabled;
- uint64_t adr_ctl;
-
- last_enabled = octeon_rgmx_stop_port(port);
-
- adr_ctl = oct_read64(OCTEON_RGMX_RXX_ADR_CTL(index, iface));
-
- /*
- * Always accept broadcast traffic.
- */
- if ((adr_ctl & OCTEON_RGMX_ADRCTL_ACCEPT_BROADCAST) == 0)
- adr_ctl |= OCTEON_RGMX_ADRCTL_ACCEPT_BROADCAST;
-
- /*
- * Accept all multicast in all multicast mode and in
- * promiscuous mode.
- *
- * XXX Since we don't handle programming the CAM for
- * multicast filtering, always accept all multicast.
- */
- adr_ctl &= ~OCTEON_RGMX_ADRCTL_REJECT_ALL_MULTICAST;
- adr_ctl |= OCTEON_RGMX_ADRCTL_ACCEPT_ALL_MULTICAST;
-
- /*
- * In promiscuous mode, the CAM is shut off, so reject everything.
- * Otherwise, filter using the CAM.
- */
- if ((ifp->if_flags & IFF_PROMISC) != 0) {
- adr_ctl &= ~OCTEON_RGMX_ADRCTL_CAM_MODE_ACCEPT_DMAC;
- adr_ctl |= OCTEON_RGMX_ADRCTL_CAM_MODE_REJECT_DMAC;
- } else {
- adr_ctl &= ~OCTEON_RGMX_ADRCTL_CAM_MODE_REJECT_DMAC;
- adr_ctl |= OCTEON_RGMX_ADRCTL_CAM_MODE_ACCEPT_DMAC;
- }
-
- oct_write64(OCTEON_RGMX_RXX_ADR_CTL(index, iface), adr_ctl);
-
- /*
- * If in promiscuous mode, disable the CAM.
- */
- if ((ifp->if_flags & IFF_PROMISC) != 0)
- oct_write64(OCTEON_RGMX_RXX_ADR_CAM_EN(index, iface), 0);
- else
- oct_write64(OCTEON_RGMX_RXX_ADR_CAM_EN(index, iface), 1);
-
- if (last_enabled) octeon_rgmx_start_port(port);
-}
-
-static int octeon_rgmx_ioctl (struct ifnet * ifp, u_long command, caddr_t data)
-{
- struct rgmx_softc_dev *sc = ifp->if_softc;
- struct ifreq *ifr = (struct ifreq *)data;
- int error = 0;
-
- if (!sc) {
- printf(" octeon_rgmx_ioctl. No sc\n");
- return (0);
- }
- switch (command) {
-
- case SIOCSIFFLAGS:
- /*
- * Switch interface state between "running" and
- * "stopped", reflecting the UP flag.
- */
- if (ifp->if_flags & IFF_UP) {
- /*
- * New state is IFF_UP
- * Restart or Start now, if driver is not running currently.
- */
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
- octeon_rgmx_init(sc);
- }
- octeon_rgmx_config_cam(ifp);
- } else {
- /*
- * New state is IFF_DOWN.
- * Stop & shut it down now, if driver is running currently.
- */
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
- octeon_rgmx_stop(sc);
- }
- }
- break;
-
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- break;
-
- case SIOCSIFMEDIA:
- case SIOCGIFMEDIA:
- /* Let if_media to handle these commands and to call
- us back. */
- error = ifmedia_ioctl(ifp, ifr, &sc->media, command);
- break;
-
- case SIOCSIFCAP:
- {
- int mask;
-
- ifp->if_hwassist &= ~CSUM_TSO;
- ifp->if_capenable &= ~IFCAP_VLAN_HWTAGGING;
- mask = ifr->ifr_reqcap ^ ifp->if_capenable;
- if (mask & IFCAP_HWCSUM) {
- ifp->if_capenable ^= IFCAP_HWCSUM;
- if (ifp->if_capenable & IFCAP_TXCSUM) {
- ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP);
- } else {
- ifp->if_hwassist &= ~(CSUM_TCP | CSUM_UDP);
- }
- }
- }
- break;
-
- default:
- error = ether_ioctl(ifp, command, data);
- break;
- }
-
- return (error);
-}
-
-static void octeon_rgmx_init (void *xsc)
-{
- struct rgmx_softc_dev *sc = xsc;
-
- /* Enable interrupts. */
- /* For RGMX they are already enabled earlier */
-
- /* Enable transmitter and receiver. */
- /* For RGMX they are already enabled earlier */
-
- /* Flush out all HW receive buffers for this interface. */
- /* For RGMX, no means to flush an individual port */
-
- /* Set 'running' flag, because we are now running. */
- sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
-
- /* Set the HW Address filter. aka program Mac-addr & Multicast filters */
- /* For RGMX this was taken care of via set_mac_addr() */
-
- /* Kick start the output */
- /* Hopefully PKO is running and will pick up packets via the timer or receive loop */
-
- /* Set link status. */
- octeon_rgmx_config_speed(sc->port, 1);
-}
-
-
-
-static void octeon_rgmx_config_speed (u_int port, u_int report_link)
-{
- int index = INDEX(port);
- int iface = INTERFACE(port);
- struct rgmx_softc_dev *sc;
- octeon_rgmx_rxx_rx_inbnd_t link_status, old_link_status;
- octeon_rgmx_prtx_cfg_t gmx_cfg;
- uint64_t val64_tx_clk, val64_tx_slot, val64_tx_burst;
- u_int last_enabled;
-
- sc = get_rgmx_softc(port);
- if (!sc) {
- printf(" config_speed didn't find sc int:%u port:%u", iface, port);
- return;
- }
-
- /*
- * Look up interface-port speed params
- */
- link_status.word64 = oct_read64(OCTEON_RGMX_RXX_RX_INBND(index, iface));
-
- RGMX_LOCK(sc);
-
- /*
- * Compre to prev known state. If same then nothing to do.
- */
- if (link_status.word64 == sc->link_status) {
- RGMX_UNLOCK(sc);
- return;
- }
- old_link_status.word64 = sc->link_status;
-
- /*
- * Compare to previous state modulo link status. If only link
- * status is different, we don't need to change media.
- */
- if (old_link_status.bits.duplex != link_status.bits.duplex ||
- old_link_status.bits.speed != link_status.bits.speed) {
- last_enabled = octeon_rgmx_stop_port(port);
-
- gmx_cfg.word64 = oct_read64(OCTEON_RGMX_PRTX_CFG(index, iface));
-
- /*
- * Duplex
- * XXX Set based on link_status.bits.duplex?
- */
- gmx_cfg.bits.duplex = 1;
-
- switch (link_status.bits.speed) {
- case 0: /* 10Mbps */
- gmx_cfg.bits.speed = 0;
- gmx_cfg.bits.slottime = 0;
- val64_tx_clk = 50; val64_tx_slot = 0x40; val64_tx_burst = 0;
- break;
-
- case 1: /* 100Mbps */
- gmx_cfg.bits.speed = 0;
- gmx_cfg.bits.slottime = 0;
- val64_tx_clk = 5; val64_tx_slot = 0x40; val64_tx_burst = 0;
- break;
-
- case 2: /* 1Gbps */
- gmx_cfg.bits.speed = 1;
- gmx_cfg.bits.slottime = 1;
- val64_tx_clk = 1; val64_tx_slot = 0x200; val64_tx_burst = 0x2000;
- break;
-
- case 3: /* ?? */
- default:
- gmx_cfg.bits.speed = 1;
- gmx_cfg.bits.slottime = 1;
- val64_tx_clk = 1; val64_tx_slot = 0x200; val64_tx_burst = 0x2000;
- break;
- }
-
- oct_write64(OCTEON_RGMX_TXX_CLK(index, iface), val64_tx_clk);
- oct_write64(OCTEON_RGMX_TXX_SLOT(index, iface), val64_tx_slot);
- oct_write64(OCTEON_RGMX_TXX_BURST(index, iface), val64_tx_burst);
-
- oct_write64(OCTEON_RGMX_PRTX_CFG(index, iface), gmx_cfg.word64);
-
- if (last_enabled) octeon_rgmx_start_port(port);
- }
-
- /*
- * Now check and possibly change link status.
- */
- if (link_status.bits.status != old_link_status.bits.status) {
- if (report_link) {
- if (link_status.bits.status) {
- if_link_state_change(sc->ifp, LINK_STATE_UP);
- } else {
- if_link_state_change(sc->ifp, LINK_STATE_DOWN);
- }
- }
- }
-
- if (report_link) {
- sc->link_status = link_status.word64;
- } else {
- /*
- * We can't update link status proper since we can't
- * change it in the interface, so keep the old link
- * status intact but note the current speed and duplex
- * settings.
- */
- link_status.bits.status = old_link_status.bits.status;
- sc->link_status = link_status.word64;
- }
-
- RGMX_UNLOCK(sc);
-}
-
-
-
-#ifdef DEBUG_RGMX_DUMP
-static void octeon_dump_rgmx_stats (u_int port)
-{
-
-}
-#endif
-
-#ifdef __not_used__
-static void rgmx_timer_periodic (void)
-{
- u_int port;
- int index;
- struct rgmx_softc_dev *sc;
- struct ifnet *ifp;
-
- for (index = 0; index < OCTEON_RGMX_NUM_PORTS_MAX; index ++) {
-
- port = port_array[index];
- sc = rgmx_scdev_array[index];
-
- /*
- * Skip over ports/slots not in service.
- */
- if ((port < OCTEON_RGMX_MIN_PORT) || (port > OCTEON_RGMX_MAX_PORT)) {
- continue;
- }
- if ((NULL == sc) || (((struct rgmx_softc_dev *)-1) == sc)) {
- continue;
- }
-
- /*
- * Now look for anamolous conditions
- */
- if (sc != get_rgmx_softc(port)) {
- printf(" port %u sc %p not in sync with index: %u\n",
- port, sc, index);
- continue;
- }
-
- if (sc->port != port) {
- printf(" port %u sc %p port-> %u not in sync with index: %u\n",
- port, sc, sc->port, index);
- continue;
- }
-
- ifp = sc->ifp;
- if (ifp == NULL) {
- printf(" port %u sc %p . Bad ifp %p\n", port, sc, ifp);
- continue;
- }
-
- /*
- * Check if packets queued at ifnet layer. Kick start output if we can.
- */
- if (sc->ifp->if_flags & IFF_UP) {
- octeon_rgmx_output_start(ifp);
- } else {
- octeon_rgmx_output_flush(ifp);
- }
-
- /*
- * Check if line status changed ? Adjust ourselves.
- */
- octeon_rgmx_config_speed(port, 1);
- }
-}
-#endif
-
-#ifdef DEBUG_RGMX_DUMP
-static void octeon_dump_pow_stats(void)
-{
- octeon_rgmx_pow_nos_cnt nos_cnt;
- octeon_rgmx_pow_int_pc_t intpc;
- octeon_rgmx_pow_int_threshold_t thr;
- octeon_rgmx_pow_int_cnt_t int_cnt;
- int core = octeon_get_core_num();
- octeon_pow_inpt_q_all_qos inpt_q_all;
- octeon_pow_inpt_q_grp_qos inpt_q_grp;
- octeon_rgmx_pip_inb_pkts pkts;
- octeon_rgmx_pip_inb_errs errs;
- static u_int pkts0 = 0;
- static u_int pkts1 = 0;
- static u_int errs0 = 0;
- static u_int errs1 = 0;
- int i;
-
-
- nos_cnt.word64 = oct_read64(OCTEON_RGMX_POW_NOS_CNT);
- if (nos_cnt.bits.nos_cnt) printf(" *** No sched cnt %u\n", nos_cnt.bits.nos_cnt);
- printf(" \nGroup mask: 0x%llX WorkQueue Int : 0x%llX\n", oct_read64(OCTEON_POW_CORE_GROUP_MASK(OUR_CORE)), oct_read64(OCTEON_POW_WORKQUEUE_INT));
- intpc.word64 = oct_read64(OCTEON_POW_WORKQUEUE_INT_PC);
- printf(" Intr Periodic Cntr: PC %u thr: %u\n", intpc.bits.thr_freq, intpc.bits.thr_period);
- thr.word64 = oct_read64(OCTEON_POW_WORKQUEUE_INT_THRESHOLD(OCTEON_POW_RX_GROUP_NUM));
- printf(" Thresholds iq %u ds %u time %u enable %u\n",
- thr.bits.iq_thr, thr.bits.ds_thr, thr.bits.time_thr, thr.bits.enable);
- int_cnt.word64 = oct_read64(OCTEON_POW_INT_CNTR(core));
- printf(" Int_cnt iq_cnt %u ds_cnt %u tc_cnt %u\n",
- int_cnt.bits.iq_cnt, int_cnt.bits.ds_cnt, int_cnt.bits.tc_cnt);
- pkts.word64 = oct_read64(OCTEON_PIP_STAT_INB_PKTS(16)); pkts0 += pkts.bits.inb_pkts;
- errs.word64 = oct_read64(OCTEON_PIP_STAT_INB_ERRS(16)); errs0 += errs.bits.inb_errs;
- pkts.word64 = oct_read64(OCTEON_PIP_STAT_INB_PKTS(17)); pkts1 += pkts.bits.inb_pkts;
- errs.word64 = oct_read64(OCTEON_PIP_STAT_INB_ERRS(17)); errs1 += errs.bits.inb_errs;
- printf(" PIP inbound pkts(16): %u Errors: %u inbound(17): %u Errors: %u\n", pkts0, errs0, pkts1, errs1);
- inpt_q_all.word64 = oct_read64(OCTEON_POW_INPT_Q_ALL_QOS);
- printf(" All queued pkt in qos Levels: %u -- ", inpt_q_all.bits.iq_cnt);
- for (i = 0 ; i < 7; i++) {
- inpt_q_grp.word64 = oct_read64(OCTEON_POW_INPT_QOS_GRP(i));
- if (inpt_q_grp.bits.iq_cnt) printf(" Grp-%u: %u ", i, inpt_q_grp.bits.iq_cnt);
- }
-}
-#endif
-
-/* ------------------------------------------------------------------- *
- * octeon_line_status_loop() *
- * ------------------------------------------------------------------- */
-static void octeon_line_status_loop (void *unused)
-{
- struct rgmx_softc_dev *sc;
- u_int idx;
-
- for (idx = 0; idx < num_devices; idx++) {
- sc = rgmx_scdev_array[idx];
- if (sc && sc->ifp) {
- if ((sc->ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- octeon_rgmx_config_speed(sc->port, 1);
-
- octeon_rgmx_output_start(sc->ifp);
- }
- }
- }
-
-//#define DEBUG_RGMX_DUMP
-#ifdef DEBUG_RGMX_DUMP
- static int count = 0;
-
- if (++count > 5) {
- count = 0;
-// octeon_dump_fpa_pool(OCTEON_FPA_RX_PACKET_POOL);
-// octeon_dump_fpa_pool(OCTEON_FPA_WQE_RX_POOL);
-// octeon_dump_fpa_pool(OCTEON_FPA_TX_PACKET_POOL);
- octeon_dump_rgmx_stats(16);
- octeon_dump_pow_stats();
- }
-#endif
-}
-
-
-/* ------------------------------------------------------------------- *
- * octeon_rgmx_set_mac *
- * ------------------------------------------------------------------- *
- *
- * octeon_rgmx_set_mac
- *
- * Program the ethernet HW address
- *
- */
-static void octeon_rgmx_set_mac (u_int port)
-{
- struct rgmx_softc_dev *sc;
- u_int iface = INTERFACE(port);
- u_int index = INDEX(port);
- int ii;
- uint64_t mac = 0;
- u_int last_enabled;
-
- sc = get_rgmx_softc(port);
- if (!sc) {
- printf(" octeon_rgmx_set_mac Missing sc. port:%u", port);
- return;
- }
-
- for (ii = 0; ii < 6; ii++) {
- mac = (mac << 8) | (uint64_t)(sc->ieee[ii]);
- }
-
- last_enabled = octeon_rgmx_stop_port(port);
-
- oct_write64(OCTEON_RGMX_SMACX(index, iface), mac);
- oct_write64(OCTEON_RGMX_RXX_ADR_CAM0(index, iface), sc->ieee[0]);
- oct_write64(OCTEON_RGMX_RXX_ADR_CAM1(index, iface), sc->ieee[1]);
- oct_write64(OCTEON_RGMX_RXX_ADR_CAM2(index, iface), sc->ieee[2]);
- oct_write64(OCTEON_RGMX_RXX_ADR_CAM3(index, iface), sc->ieee[3]);
- oct_write64(OCTEON_RGMX_RXX_ADR_CAM4(index, iface), sc->ieee[4]);
- oct_write64(OCTEON_RGMX_RXX_ADR_CAM5(index, iface), sc->ieee[5]);
- oct_write64(OCTEON_RGMX_RXX_ADR_CTL(index, iface),
- OCTEON_RGMX_ADRCTL_ACCEPT_BROADCAST |
- OCTEON_RGMX_ADRCTL_ACCEPT_ALL_MULTICAST |
- OCTEON_RGMX_ADRCTL_CAM_MODE_ACCEPT_DMAC);
- oct_write64(OCTEON_RGMX_RXX_ADR_CAM_EN(index, iface), 1);
- if (last_enabled) octeon_rgmx_start_port(port);
-}
-
-
-/* ------------------------------------------------------------------- *
- * octeon_config_rgmii_port() *
- * ------------------------------------------------------------------- */
-static void octeon_config_rgmii_port (u_int port)
-{
- u_int iface = INTERFACE(port);
- u_int index = INDEX(port);
-
- /*
- * Configure an RGMII port
- */
- octeon_rgmx_prtx_cfg_t gmx_cfg;
-
- /* Enable ASX */
- oct_write64(OCTEON_ASXX_RX_PRT_EN(iface), oct_read64(OCTEON_ASXX_RX_PRT_EN(iface)) | (1<<index));
- oct_write64(OCTEON_ASXX_TX_PRT_EN(iface), oct_read64(OCTEON_ASXX_TX_PRT_EN(iface)) | (1<<index));
-
- /* Enable RGMX */
- gmx_cfg.word64 = oct_read64(OCTEON_RGMX_PRTX_CFG(index, iface));
- gmx_cfg.bits.en = 1;
- oct_write64(OCTEON_RGMX_PRTX_CFG(index, iface), gmx_cfg.word64);
-
- octeon_rgmx_config_speed(port, 0);
-
- oct_write64(OCTEON_RGMX_TXX_THRESH(index, iface), 32);
-
- /*
- * Set hi water mark
- */
- oct_write64(OCTEON_ASXX_TX_HI_WATERX(index, iface), 10);
- if (octeon_get_chipid() == OCTEON_CN5020_CHIP) {
- oct_write64(OCTEON_ASXX_TX_CLK_SETX(index, iface), 16);
- oct_write64(OCTEON_ASXX_RX_CLK_SETX(index, iface), 16);
- } else {
- oct_write64(OCTEON_ASXX_TX_CLK_SETX(index, iface), 24);
- oct_write64(OCTEON_ASXX_RX_CLK_SETX(index, iface), 24);
- }
-}
-
-
-
-static void octeon_rgmx_enable_RED_queue (int queue, int slow_drop, int all_drop)
-{
- octeon_rgmx_ipd_queue_red_marks_t red_marks;
- octeon_rgmx_ipd_red_q_param_t red_param;
-
- if (slow_drop == all_drop) { printf("Bad val in %s", __FUNCTION__); return; }
- red_marks.word64 = 0;
- red_marks.bits.all_drop = all_drop;
- red_marks.bits.slow_drop = slow_drop;
- oct_write64(OCTEON_IPD_QOSX_RED_MARKS(queue), red_marks.word64);
-
- /* Use the actual queue 0 counter, not the average */
- red_param.word64 = 0;
- red_param.bits.prb_con = (255ul << 24) / (slow_drop - all_drop);
- red_param.bits.avg_con = 1;
- red_param.bits.new_con = 255;
- red_param.bits.use_pagecount = 1;
- oct_write64(OCTEON_IPD_RED_Q_PARAM(queue), red_param.word64);
-}
-
-
-static void octeon_rgmx_enable_RED_all (int slow_drop, int all_drop)
-{
-
- int port, queue;
- octeon_ipd_port_bp_page_count_t ipd_bp_page_count;
- octeon_ipd_red_port_enable_t red_port_enable;
-
- /*
- * First remove BP settings
- */
- ipd_bp_page_count.word64 = 0;
- ipd_bp_page_count.bits.bp_enable = 0;
- ipd_bp_page_count.bits.page_count = 100;
-
- for (port = 0; port < OCTEON_RGMX_MAX_PORT; port++) {
- oct_write64(OCTEON_IPD_PORT_BP_PAGE_COUNT(port), ipd_bp_page_count.word64);
- }
-
- /*
- * Enable RED for each individual queue
- */
- for (queue = 0; queue < 8; queue++) {
- octeon_rgmx_enable_RED_queue(queue, slow_drop, all_drop);
- }
-
- oct_write64(OCTEON_IPD_BP_PORT_RED_END, 0);
-
- red_port_enable.word64 = 0;
- red_port_enable.bits.port_enable = 0xfffffffffull;
- red_port_enable.bits.avg_dly = 10000;
- red_port_enable.bits.prb_dly = 10000;
- oct_write64(OCTEON_IPD_RED_PORT_ENABLE, red_port_enable.word64);
-}
-
-
-
-/* ------------------------------------------------------------------- *
- * octeon_has_4ports() *
- * ------------------------------------------------------------------- */
-static int octeon_has_4ports (void)
-{
- u_int chipid;
- int retcode = 1;
-
- chipid = octeon_get_chipid();
-
- switch (chipid) {
- case OCTEON_CN31XX_CHIP:
- case OCTEON_CN30XX_CHIP:
- case OCTEON_CN5020_CHIP:
- retcode = 0;
- break;
-
- default:
- break;
- }
- return (retcode);
-}
-
-
-#ifdef __not_used__
-/*
- * octeon_rgmx_free_intr
- *
- * We have 4 child and one parent device.
- * It's tricky and unexpected that anyone will detach the device that is built'in on
- * the chip.
- * We will not support detachment for now. But keep adding good code that will be used
- * someday.
- */
-static void octeon_rgmx_free_intr (struct rgmx_softc_dev *sc)
-{
- device_t dev = sc->sc_dev;
-
- /*
- * Make sure that sc/dev are the parent Root structs. Not one
- * of the rgmxN childs.
- */
- if (int_handler_tag != NULL) {
- bus_teardown_intr(dev, irq_res, int_handler_tag);
- int_handler_tag = NULL;
- }
-
-#ifdef OCTEON_RGMX_SCHEDULED_ISRS
- if (tq != NULL) {
- taskqueue_drain(tq, &rxtx_isr_task);
- taskqueue_drain(taskqueue_fast, &link_isr_task);
- taskqueue_free(tq);
- tq = NULL;
- }
-#endif
-
-}
-#endif
-
-static device_method_t rgmii_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, rgmii_probe),
- DEVMETHOD(device_identify, rgmii_identify),
- DEVMETHOD(device_attach, rgmii_attach),
- DEVMETHOD(device_detach, bus_generic_detach),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
-
- { 0, 0 }
-};
-
-static driver_t rgmii_driver = {
- "rgmii", rgmii_methods, sizeof(struct rgmx_softc_dev)
-};
-
-static devclass_t rgmii_devclass;
-
-DRIVER_MODULE(rgmii, nexus, rgmii_driver, rgmii_devclass, 0, 0);
diff --git a/sys/mips/cavium/dev/rgmii/octeon_rgmx.h b/sys/mips/cavium/dev/rgmii/octeon_rgmx.h
deleted file mode 100644
index 1939341..0000000
--- a/sys/mips/cavium/dev/rgmii/octeon_rgmx.h
+++ /dev/null
@@ -1,630 +0,0 @@
-/***********************license start***************
- * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
- * reserved.
- *
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * 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.
- *
- * * Neither the name of Cavium Networks nor the names of
- * its contributors may be used to endorse or promote products
- * derived from this software without specific prior written
- * permission.
- *
- * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
- * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
- * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
- * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
- * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
- * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
- * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
- * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
- * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT
- * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
- *
- *
- * For any questions regarding licensing please contact marketing@caviumnetworks.com
- *
- ***********************license end**************************************/
-
-/* $FreeBSD$ */
-
-/*------------------------------------------------------------------
- * octeon_rgmx.h RGMII Ethernet Interfaces
- *
- *------------------------------------------------------------------
- */
-
-
-#ifndef ___OCTEON_RGMX__H___
-#define ___OCTEON_RGMX__H___
-
-
-
-#define OCTEON_FPA_PACKET_POOL 0
-#define OCTEON_FPA_WQE_RX_POOL 1
-#define OCTEON_FPA_OUTPUT_BUFFER_POOL 2
-#define OCTEON_FPA_WQE_POOL_SIZE (1 * OCTEON_CACHE_LINE_SIZE)
-#define OCTEON_FPA_OUTPUT_BUFFER_POOL_SIZE (8 * OCTEON_CACHE_LINE_SIZE)
-#define OCTEON_FPA_PACKET_POOL_SIZE (16 * OCTEON_CACHE_LINE_SIZE)
-
-#define OCTEON_POW_WORK_REQUEST(wait) (0x8001600000000000ull | (wait<<3))
-
-typedef union
-{
- void* ptr;
- uint64_t word64;
- struct
- {
- uint64_t i : 1;
- uint64_t back : 4;
- uint64_t pool : 3;
- uint64_t size :16;
- uint64_t addr :40;
- } bits;
-} octeon_buf_ptr_t;
-
-/**
- * Work queue entry format
- */
-typedef struct
-{
- uint16_t hw_chksum;
- uint8_t unused;
- uint64_t next_ptr : 40;
- uint64_t len :16;
- uint64_t ipprt : 6;
- uint64_t qos : 3;
- uint64_t grp : 4;
- uint64_t tag_type : 3;
- uint64_t tag :32;
- union
- {
- uint64_t word64;
- struct
- {
- uint64_t bufs : 8;
- uint64_t ip_offset : 8;
- uint64_t vlan_valid : 1;
- uint64_t unassigned : 2;
- uint64_t vlan_cfi : 1;
- uint64_t vlan_id :12;
- uint64_t unassigned2 :12;
- uint64_t dec_ipcomp : 1;
- uint64_t tcp_or_udp : 1;
- uint64_t dec_ipsec : 1;
- uint64_t is_v6 : 1;
- uint64_t software : 1;
- uint64_t L4_error : 1;
- uint64_t is_frag : 1;
- uint64_t IP_exc : 1;
- uint64_t is_bcast : 1;
- uint64_t is_mcast : 1;
- uint64_t not_IP : 1;
- uint64_t rcv_error : 1;
- uint64_t err_code : 8;
- } bits;
- struct
- {
- uint64_t bufs : 8;
- uint64_t unused : 8;
- uint64_t vlan_valid : 1;
- uint64_t unassigned : 2;
- uint64_t vlan_cfi : 1;
- uint64_t vlan_id :12;
- uint64_t unassigned2 :16;
- uint64_t software : 1;
- uint64_t unassigned3 : 1;
- uint64_t is_rarp : 1;
- uint64_t is_arp : 1;
- uint64_t is_bcast : 1;
- uint64_t is_mcast : 1;
- uint64_t not_IP : 1;
- uint64_t rcv_error : 1;
- uint64_t err_code : 8;
- } snoip;
- } word2;
- octeon_buf_ptr_t packet_ptr;
- uint8_t packet_data[96];
-} octeon_wqe_t;
-
-typedef union {
- uint64_t word64;
-
- struct {
- uint64_t scraddr : 8; /**< the (64-bit word) location in scratchpad to write to (if len != 0) */
- uint64_t len : 8; /**< the number of words in the response (0 => no response) */
- uint64_t did : 8; /**< the ID of the device on the non-coherent bus */
- uint64_t unused :36;
- uint64_t wait : 1; /**< if set, don't return load response until work is available */
- uint64_t unused2 : 3;
- } bits;
-
-} octeon_pow_iobdma_store_t;
-
-
-/**
- * Wait flag values for pow functions.
- */
-typedef enum
-{
- OCTEON_POW_WAIT = 1,
- OCTEON_POW_NO_WAIT = 0,
-} octeon_pow_wait_t;
-
-
-
-static inline void * phys_to_virt (unsigned long address)
-{
- return (void *)(address + 0x80000000UL);
-}
-
-// decode within DMA space
-typedef enum {
- OCTEON_ADD_WIN_DMA_ADD = 0L, // add store data to the write buffer entry, allocating it if necessary
- OCTEON_ADD_WIN_DMA_SENDMEM = 1L, // send out the write buffer entry to DRAM
- // store data must be normal DRAM memory space address in this case
- OCTEON_ADD_WIN_DMA_SENDDMA = 2L, // send out the write buffer entry as an IOBDMA command
- // see OCTEON_ADD_WIN_DMA_SEND_DEC for data contents
- OCTEON_ADD_WIN_DMA_SENDIO = 3L, // send out the write buffer entry as an IO write
- // store data must be normal IO space address in this case
- OCTEON_ADD_WIN_DMA_SENDSINGLE = 4L, // send out a single-tick command on the NCB bus
- // no write buffer data needed/used
-} octeon_add_win_dma_dec_t;
-
-
-#define OCTEON_OCT_DID_FPA 5ULL
-#define OCTEON_OCT_DID_TAG 12ULL
-#define OCTEON_OCT_DID_TAG_SWTAG OCTEON_ADDR_FULL_DID(OCTEON_OCT_DID_TAG, 0ULL)
-
-
-#define OCTEON_IOBDMA_OFFSET (-3*1024ll)
-#define OCTEON_IOBDMA_SEP 16
-#define OCTEON_IOBDMA_SENDSINGLE (OCTEON_IOBDMA_OFFSET + \
- (OCTEON_ADD_WIN_DMA_SENDSINGLE *\
- OCTEON_IOBDMA_SEP))
-
-static inline void octeon_send_single (uint64_t data)
-{
- oct_write64((uint64_t)(OCTEON_IOBDMA_SENDSINGLE * (long long)8), data);
-}
-
-
-static inline void octeon_pow_work_request_async_nocheck (int scratch_addr,
- octeon_pow_wait_t wait)
-{
- octeon_pow_iobdma_store_t data;
-
- /* scratch_addr must be 8 byte aligned */
- data.bits.scraddr = scratch_addr >> 3;
- data.bits.len = 1;
- data.bits.did = OCTEON_OCT_DID_TAG_SWTAG;
- data.bits.wait = wait;
- octeon_send_single(data.word64);
-}
-
-
-
-/**
- * octeon_gmx_inf_mode
- *
- * GMX_INF_MODE = Interface Mode
- *
- */
-typedef union
-{
- uint64_t word64;
- struct gmxx_inf_mode_s
- {
- uint64_t reserved_3_63 : 61;
- uint64_t p0mii : 1; /**< Port 0 Interface Mode
- 0: Port 0 is RGMII
- 1: Port 0 is MII */
- uint64_t en : 1; /**< Interface Enable */
- uint64_t type : 1; /**< Interface Mode
- 0: RGMII Mode
- 1: Spi4 Mode */
- } bits;
- struct gmxx_inf_mode_cn3020
- {
- uint64_t reserved_2_63 : 62;
- uint64_t en : 1; /**< Interface Enable */
- uint64_t type : 1; /**< Interface Mode
- 0: All three ports are RGMII ports
- 1: prt0 is RGMII, prt1 is GMII, and prt2 is unused */
- } cn3020;
- struct gmxx_inf_mode_s cn30xx;
- struct gmxx_inf_mode_cn3020 cn31xx;
- struct gmxx_inf_mode_cn3020 cn36xx;
- struct gmxx_inf_mode_cn3020 cn38xx;
- struct gmxx_inf_mode_cn3020 cn38xxp2;
- struct gmxx_inf_mode_cn3020 cn56xx;
- struct gmxx_inf_mode_cn3020 cn58xx;
-} octeon_gmxx_inf_mode_t;
-
-
-
-
-typedef union {
- uint64_t word64;
- struct {
- uint64_t reserved : 60; /* Reserved */
- uint64_t slottime : 1; /* Slot Time for Half-Duplex */
- /* operation - 0 = 512 bitimes (10/100Mbs operation) */
- /* - 1 = 4096 bitimes (1000Mbs operation) */
- uint64_t duplex : 1; /* Duplex - 0 = Half Duplex */
- /* (collisions/extentions/bursts) - 1 = Full Duplex */
- uint64_t speed : 1; /* Link Speed - 0 = 10/100Mbs */
- /* operation - 1 = 1000Mbs operation */
- uint64_t en : 1; /* Link Enable */
- } bits;
-} octeon_rgmx_prtx_cfg_t;
-
-
-/*
- * GMX_RX_INBND = RGMX InBand Link Status
- *
- */
-typedef union {
- uint64_t word64;
- struct {
- uint64_t reserved : 60; /* Reserved */
- uint64_t duplex : 1; /* 0 = Half, 1 = Full */
- uint64_t speed : 2; /* Inbound Link Speed */
- /* 00 = 2.5Mhz, 01 = 25Mhz */
- /* 10 = 125MHz, 11 = Reserved */
- uint64_t status : 1; /* Inbound Status Up/Down */
- } bits;
-} octeon_rgmx_rxx_rx_inbnd_t;
-
-
-
-typedef union
-{
- uint64_t word64;
- struct {
- uint64_t all_drop : 32;
- uint64_t slow_drop : 32;
- } bits;
-} octeon_rgmx_ipd_queue_red_marks_t;
-
-
-typedef union
-{
- uint64_t word64;
- struct {
- uint64_t reserved : 15;
- uint64_t use_pagecount : 1;
- uint64_t new_con : 8;
- uint64_t avg_con : 8;
- uint64_t prb_con : 32;
- } bits;
-} octeon_rgmx_ipd_red_q_param_t;
-
-
-
-typedef union
-{
- uint64_t word64;
- struct {
- uint64_t reserved : 46;
- uint64_t bp_enable : 1;
- uint64_t page_count : 17;
- } bits;
-} octeon_ipd_port_bp_page_count_t;
-
-
-typedef union
-{
- uint64_t word64;
- struct {
- uint64_t prb_dly : 14;
- uint64_t avg_dly : 14;
- uint64_t port_enable : 36;
- } bits;
-} octeon_ipd_red_port_enable_t;
-
-
-/**
- * Tag type definitions
- */
-typedef enum
-{
- OCTEON_POW_TAG_TYPE_ORDERED = 0L, /**< Tag ordering is maintained */
- OCTEON_POW_TAG_TYPE_ATOMIC = 1L, /**< Tag ordering is maintained, and at most one PP has the tag */
- OCTEON_POW_TAG_TYPE_NULL = 2L, /**< The work queue entry from the order
- - NEVER tag switch from NULL to NULL */
- OCTEON_POW_TAG_TYPE_NULL_NULL = 3L /**< A tag switch to NULL, and there is no space reserved in POW
- - NEVER tag switch to NULL_NULL
- - NEVER tag switch from NULL_NULL
- - NULL_NULL is entered at the beginning of time and on a deschedule.
- - NULL_NULL can be exited by a new work request. A NULL_SWITCH load can also switch the state to NULL */
-} octeon_pow_tag_type_t ;
-
-/**
- * This structure defines the response to a load/SENDSINGLE to POW (except CSR reads)
- */
-typedef union {
- uint64_t word64;
-
- octeon_wqe_t *wqp;
-
- // response to new work request loads
- struct {
- uint64_t no_work : 1; // set when no new work queue entry was returned
- // If there was de-scheduled work, the HW will definitely
- // return it. When this bit is set, it could mean
- // either mean:
- // - There was no work, or
- // - There was no work that the HW could find. This
- // case can happen, regardless of the wait bit value
- // in the original request, when there is work
- // in the IQ's that is too deep down the list.
- uint64_t unused : 23;
- uint64_t addr : 40; // 36 in O1 -- the work queue pointer
- } s_work;
-
- // response to NULL_RD request loads
- struct {
- uint64_t unused : 62;
- uint64_t state : 2; // of type octeon_pow_tag_type_t
- // state is one of the following:
- // OCTEON_POW_TAG_TYPE_ORDERED
- // OCTEON_POW_TAG_TYPE_ATOMIC
- // OCTEON_POW_TAG_TYPE_NULL
- // OCTEON_POW_TAG_TYPE_NULL_NULL
- } s_null_rd;
-
-} octeon_pow_tag_load_resp_t;
-
-
-/*
- * This structure describes the address to load stuff from POW
- */
-typedef union {
- uint64_t word64;
-
- // address for new work request loads (did<2:0> == 0)
- struct {
- uint64_t mem_region :2;
- uint64_t mbz :13;
- uint64_t is_io : 1; // must be one
- uint64_t did : 8; // the ID of POW -- did<2:0> == 0 in this case
- uint64_t unaddr : 4;
- uint64_t unused :32;
- uint64_t wait : 1; // if set, don't return load response until work is available
- uint64_t mbzl : 3; // must be zero
- } swork; // physical address
-
-
- // address for NULL_RD request (did<2:0> == 4)
- // when this is read, HW attempts to change the state to NULL if it is NULL_NULL
- // (the hardware cannot switch from NULL_NULL to NULL if a POW entry is not available -
- // software may need to recover by finishing another piece of work before a POW
- // entry can ever become available.)
- struct {
- uint64_t mem_region :2;
- uint64_t mbz :13;
- uint64_t is_io : 1; // must be one
- uint64_t did : 8; // the ID of POW -- did<2:0> == 4 in this case
- uint64_t unaddr : 4;
- uint64_t unused :33;
- uint64_t mbzl : 3; // must be zero
- } snull_rd; // physical address
-
- // address for CSR accesses
- struct {
- uint64_t mem_region :2;
- uint64_t mbz :13;
- uint64_t is_io : 1; // must be one
- uint64_t did : 8; // the ID of POW -- did<2:0> == 7 in this case
- uint64_t unaddr : 4;
- uint64_t csraddr:36; // only 36 bits in O1, addr<2:0> must be zero
- } stagcsr; // physical address
-
-} octeon_pow_load_addr_t;
-
-
-static inline void octeon_pow_tag_switch_wait (void)
-{
- uint64_t switch_complete;
-
- do
- {
- OCTEON_CHORD_HEX(&switch_complete);
- } while (!switch_complete);
-
- return;
-}
-
-
-static inline octeon_wqe_t *octeon_pow_work_request_sync_nocheck (octeon_pow_wait_t wait)
-{
- octeon_pow_load_addr_t ptr;
- octeon_pow_tag_load_resp_t result;
-
- ptr.word64 = 0;
- ptr.swork.mem_region = OCTEON_IO_SEG;
- ptr.swork.is_io = 1;
- ptr.swork.did = OCTEON_OCT_DID_TAG_SWTAG;
- ptr.swork.wait = wait;
-
- result.word64 = oct_read64(ptr.word64);
-
- if (result.s_work.no_work || !result.s_work.addr) {
- return NULL;
- }
- return (octeon_wqe_t *) MIPS_PHYS_TO_KSEG0(result.s_work.addr);
-}
-
-static inline octeon_wqe_t *octeon_pow_work_request_sync_nocheck_debug (octeon_pow_wait_t wait)
-{
- octeon_pow_load_addr_t ptr;
- octeon_pow_tag_load_resp_t result;
-
- ptr.word64 = 0;
- ptr.swork.mem_region = OCTEON_IO_SEG;
- ptr.swork.is_io = 1;
- ptr.swork.did = OCTEON_OCT_DID_TAG_SWTAG;
- ptr.swork.wait = wait;
-
- result.word64 = oct_read64(ptr.word64);
-
- printf("WQE Result: 0x%llX No-work %X Addr %llX Ptr: %p\n",
- (unsigned long long)result.word64, result.s_work.no_work,
- (unsigned long long)result.s_work.addr,
- (void *)MIPS_PHYS_TO_KSEG0(result.s_work.addr));
-
- if (result.s_work.no_work || !result.s_work.addr) {
- return NULL;
- }
- return (octeon_wqe_t *) MIPS_PHYS_TO_KSEG0(result.s_work.addr);
-}
-
-static inline octeon_wqe_t *octeon_pow_work_request_sync (octeon_pow_wait_t wait)
-{
- octeon_pow_tag_switch_wait();
- return (octeon_pow_work_request_sync_nocheck(wait));
-}
-
-
-static inline octeon_wqe_t *octeon_pow_work_request_sync_debug (octeon_pow_wait_t wait)
-{
- octeon_pow_tag_switch_wait();
- return (octeon_pow_work_request_sync_nocheck_debug(wait));
-}
-
-
-
-/**
- * Gets result of asynchronous work request. Performs a IOBDMA sync
- * to wait for the response.
- *
- * @param scratch_addr Scratch memory address to get result from
- * Byte address, must be 8 byte aligned.
- * @return Returns the WQE from the scratch register, or NULL if no work was available.
- */
-static inline octeon_wqe_t *octeon_pow_work_response_async(int scratch_addr)
-{
- octeon_pow_tag_load_resp_t result;
-
- OCTEON_SYNCIOBDMA;
- result.word64 = oct_scratch_read64(scratch_addr);
-
- if (result.s_work.no_work) {
- return NULL;
- }
- return (octeon_wqe_t*) MIPS_PHYS_TO_KSEG0(result.s_work.addr);
-}
-
-
-
-/*
- * The address from POW is a physical address. Adjust for back ptr, as well as
- * make it accessible using KSEG0.
- */
-static inline void *octeon_pow_pktptr_to_kbuffer (octeon_buf_ptr_t pkt_ptr)
-{
- return ((void *)MIPS_PHYS_TO_KSEG0(
- ((pkt_ptr.bits.addr >> 7) - pkt_ptr.bits.back) << 7));
-}
-
-#define INTERFACE(port) (port >> 4) /* Ports 0-15 are interface 0, 16-31 are interface 1 */
-#define INDEX(port) (port & 0xf)
-
-
-#define OCTEON_RGMX_PRTX_CFG(index,interface) (0x8001180008000010ull+((index)*2048)+((interface)*0x8000000ull))
-#define OCTEON_RGMX_SMACX(offset,block_id) (0x8001180008000230ull+((offset)*2048)+((block_id)*0x8000000ull))
-#define OCTEON_RGMX_RXX_ADR_CAM0(offset,block_id) (0x8001180008000180ull+((offset)*2048)+((block_id)*0x8000000ull))
-#define OCTEON_RGMX_RXX_ADR_CAM1(offset,block_id) (0x8001180008000188ull+((offset)*2048)+((block_id)*0x8000000ull))
-#define OCTEON_RGMX_RXX_ADR_CAM2(offset,block_id) (0x8001180008000190ull+((offset)*2048)+((block_id)*0x8000000ull))
-#define OCTEON_RGMX_RXX_ADR_CAM3(offset,block_id) (0x8001180008000198ull+((offset)*2048)+((block_id)*0x8000000ull))
-#define OCTEON_RGMX_RXX_ADR_CAM4(offset,block_id) (0x80011800080001A0ull+((offset)*2048)+((block_id)*0x8000000ull))
-#define OCTEON_RGMX_RXX_ADR_CAM5(offset,block_id) (0x80011800080001A8ull+((offset)*2048)+((block_id)*0x8000000ull))
-#define OCTEON_RGMX_RXX_ADR_CTL(offset,block_id) (0x8001180008000100ull+((offset)*2048)+((block_id)*0x8000000ull))
-#define OCTEON_RGMX_RXX_ADR_CAM_EN(offset,block_id) (0x8001180008000108ull+((offset)*2048)+((block_id)*0x8000000ull))
-#define OCTEON_RGMX_INF_MODE(block_id) (0x80011800080007F8ull+((block_id)*0x8000000ull))
-#define OCTEON_RGMX_TX_PRTS(block_id) (0x8001180008000480ull+((block_id)*0x8000000ull))
-#define OCTEON_ASXX_RX_PRT_EN(block_id) (0x80011800B0000000ull+((block_id)*0x8000000ull))
-#define OCTEON_ASXX_TX_PRT_EN(block_id) (0x80011800B0000008ull+((block_id)*0x8000000ull))
-#define OCTEON_RGMX_TXX_THRESH(offset,block_id) (0x8001180008000210ull+((offset)*2048)+((block_id)*0x8000000ull))
-#define OCTEON_ASXX_TX_HI_WATERX(offset,block_id) (0x80011800B0000080ull+((offset)*8)+((block_id)*0x8000000ull))
-#define OCTEON_ASXX_RX_CLK_SETX(offset,block_id) (0x80011800B0000020ull+((offset)*8)+((block_id)*0x8000000ull))
-#define OCTEON_ASXX_TX_CLK_SETX(offset,block_id) (0x80011800B0000048ull+((offset)*8)+((block_id)*0x8000000ull))
-#define OCTEON_RGMX_RXX_RX_INBND(offset,block_id) (0x8001180008000060ull+((offset)*2048)+((block_id)*0x8000000ull))
-#define OCTEON_RGMX_TXX_CLK(offset,block_id) (0x8001180008000208ull+((offset)*2048)+((block_id)*0x8000000ull))
-#define OCTEON_RGMX_TXX_SLOT(offset,block_id) (0x8001180008000220ull+((offset)*2048)+((block_id)*0x8000000ull))
-#define OCTEON_RGMX_TXX_BURST(offset,block_id) (0x8001180008000228ull+((offset)*2048)+((block_id)*0x8000000ull))
-#define OCTEON_PIP_GBL_CTL (0x80011800A0000020ull)
-#define OCTEON_PIP_GBL_CFG (0x80011800A0000028ull)
-#define OCTEON_PIP_PRT_CFGX(offset) (0x80011800A0000200ull+((offset)*8))
-#define OCTEON_PIP_PRT_TAGX(offset) (0x80011800A0000400ull+((offset)*8))
-
-
-
-#define OUR_CORE 0
-#define IP2 0
-#define IP3 1
-#define CIU_TIMERS 4
-#define OCTEON_POW_CORE_GROUP_MASK(core) (0x8001670000000000ull + (8 * core))
-
-#define OCTEON_CIU_INT_EN0(CORE,IP) (0x8001070000000200ull + (IP * 16) + \
- ((CORE) * 32))
-#define OCTEON_CIU_INT_SUM0(CORE,IP) (0x8001070000000000ull + (IP * 8) + \
- ((CORE) * 32))
-#define OCTEON_CIU_TIMX(offset) (0x8001070000000480ull+((offset)*8))
-
-#define OCTEON_POW_WQ_INT_THRX(offset) ((0x8001670000000080ull+((offset)*8)))
-#define OCTEON_POW_WQ_INT_CNTX(offset) ((0x8001670000000100ull+((offset)*8)))
-#define OCTEON_POW_QOS_THRX(offset) ((0x8001670000000180ull+((offset)*8)))
-#define OCTEON_POW_QOS_RNDX(offset) ((0x80016700000001C0ull+((offset)*8)))
-#define OCTEON_POW_WQ_INT_PC (0x8001670000000208ull)
-#define OCTEON_POW_NW_TIM (0x8001670000000210ull)
-#define OCTEON_POW_ECC_ERR (0x8001670000000218ull)
-#define OCTEON_POW_INT_CTL (0x8001670000000220ull)
-#define OCTEON_POW_NOS_CNT (0x8001670000000228ull)
-#define OCTEON_POW_WS_PCX(offset) ((0x8001670000000280ull+((offset)*8)))
-#define OCTEON_POW_WA_PCX(offset) ((0x8001670000000300ull+((offset)*8)))
-#define OCTEON_POW_IQ_CNTX(offset) ((0x8001670000000340ull+((offset)*8)))
-#define OCTEON_POW_WA_COM_PC (0x8001670000000380ull)
-#define OCTEON_POW_IQ_COM_CNT (0x8001670000000388ull)
-#define OCTEON_POW_TS_PC (0x8001670000000390ull)
-#define OCTEON_POW_DS_PC (0x8001670000000398ull)
-#define OCTEON_POW_BIST_STAT (0x80016700000003F8ull)
-
-
-#define OCTEON_POW_WQ_INT (0x8001670000000200ull)
-
-#define OCTEON_IPD_PORT_BP_COUNTERS_PAIRX(offset) (0x80014F00000001B8ull+((offset)*8))
-
-/*
- * Current Counts that triggered interrupt
- */
-#define OCTEON_POW_WQ_INT_CNTX(offset) ((0x8001670000000100ull+((offset)*8)))
-
-
-
-#define OCTEON_RGMX_ADRCTL_CAM_MODE_REJECT_DMAC 0
-#define OCTEON_RGMX_ADRCTL_ACCEPT_BROADCAST 1
-#define OCTEON_RGMX_ADRCTL_REJECT_ALL_MULTICAST 2
-#define OCTEON_RGMX_ADRCTL_ACCEPT_ALL_MULTICAST 4
-#define OCTEON_RGMX_ADRCTL_CAM_MODE_ACCEPT_DMAC 8
-
-
-#define RGMX_LOCK_INIT(_sc, _name) \
- mtx_init(&(_sc)->mtx, _name, MTX_NETWORK_LOCK, MTX_DEF)
-#define RGMX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->mtx)
-#define RGMX_LOCK(_sc) mtx_lock(&(_sc)->mtx)
-#define RGMX_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx)
-#define RGMX_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->mtx, MA_OWNED)
-
-#endif /* ___OCTEON_RGMX__H___ */
diff --git a/sys/mips/cavium/driveid.h b/sys/mips/cavium/driveid.h
deleted file mode 100644
index b4805d9..0000000
--- a/sys/mips/cavium/driveid.h
+++ /dev/null
@@ -1,298 +0,0 @@
-/***********************license start***************
- * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
- * reserved.
- *
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * 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.
- *
- * * Neither the name of Cavium Networks nor the names of
- * its contributors may be used to endorse or promote products
- * derived from this software without specific prior written
- * permission.
- *
- * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
- * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
- * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
- * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
- * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
- * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
- * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
- * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
- * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT
- * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
- *
- *
- * For any questions regarding licensing please contact marketing@caviumnetworks.com
- *
- ***********************license end**************************************/
-
-/* $FreeBSD$ */
-
-/*
- * driveid.h
- *
- */
-
-#ifndef __DRIVEID_H__
-#define __DRIVEID_H__
-
-
-struct hd_driveid {
- unsigned short config; /* lots of obsolete bit flags */
- unsigned short cyls; /* Obsolete, "physical" cyls */
- unsigned short reserved2; /* reserved (word 2) */
- unsigned short heads; /* Obsolete, "physical" heads */
- unsigned short track_bytes; /* unformatted bytes per track */
- unsigned short sector_bytes; /* unformatted bytes per sector */
- unsigned short sectors; /* Obsolete, "physical" sectors per track */
- unsigned short vendor0; /* vendor unique */
- unsigned short vendor1; /* vendor unique */
- unsigned short vendor2; /* Retired vendor unique */
- unsigned char serial_no[20]; /* 0 = not_specified */
- unsigned short buf_type; /* Retired */
- unsigned short buf_size; /* Retired, 512 byte increments
- * 0 = not_specified
- */
- unsigned short ecc_bytes; /* for r/w long cmds; 0 = not_specified */
- unsigned char fw_rev[8]; /* 0 = not_specified */
- unsigned char model[40]; /* 0 = not_specified */
- unsigned char max_multsect; /* 0=not_implemented */
- unsigned char vendor3; /* vendor unique */
- unsigned short dword_io; /* 0=not_implemented; 1=implemented */
- unsigned char vendor4; /* vendor unique */
- unsigned char capability; /* (upper byte of word 49)
- * 3: IORDYsup
- * 2: IORDYsw
- * 1: LBA
- * 0: DMA
- */
- unsigned short reserved50; /* reserved (word 50) */
- unsigned char vendor5; /* Obsolete, vendor unique */
- unsigned char tPIO; /* Obsolete, 0=slow, 1=medium, 2=fast */
- unsigned char vendor6; /* Obsolete, vendor unique */
- unsigned char tDMA; /* Obsolete, 0=slow, 1=medium, 2=fast */
- unsigned short field_valid; /* (word 53)
- * 2: ultra_ok word 88
- * 1: eide_ok words 64-70
- * 0: cur_ok words 54-58
- */
- unsigned short cur_cyls; /* Obsolete, logical cylinders */
- unsigned short cur_heads; /* Obsolete, l heads */
- unsigned short cur_sectors; /* Obsolete, l sectors per track */
- unsigned short cur_capacity0; /* Obsolete, l total sectors on drive */
- unsigned short cur_capacity1; /* Obsolete, (2 words, misaligned int) */
- unsigned char multsect; /* current multiple sector count */
- unsigned char multsect_valid; /* when (bit0==1) multsect is ok */
- unsigned int lba_capacity; /* Obsolete, total number of sectors */
- unsigned short dma_1word; /* Obsolete, single-word dma info */
- unsigned short dma_mword; /* multiple-word dma info */
- unsigned short eide_pio_modes; /* bits 0:mode3 1:mode4 */
- unsigned short eide_dma_min; /* min mword dma cycle time (ns) */
- unsigned short eide_dma_time; /* recommended mword dma cycle time (ns) */
- unsigned short eide_pio; /* min cycle time (ns), no IORDY */
- unsigned short eide_pio_iordy; /* min cycle time (ns), with IORDY */
- unsigned short words69_70[2]; /* reserved words 69-70
- * future command overlap and queuing
- */
- /* HDIO_GET_IDENTITY currently returns only words 0 through 70 */
- unsigned short words71_74[4]; /* reserved words 71-74
- * for IDENTIFY PACKET DEVICE command
- */
- unsigned short queue_depth; /* (word 75)
- * 15:5 reserved
- * 4:0 Maximum queue depth -1
- */
- unsigned short words76_79[4]; /* reserved words 76-79 */
- unsigned short major_rev_num; /* (word 80) */
- unsigned short minor_rev_num; /* (word 81) */
- unsigned short command_set_1; /* (word 82) supported
- * 15: Obsolete
- * 14: NOP command
- * 13: READ_BUFFER
- * 12: WRITE_BUFFER
- * 11: Obsolete
- * 10: Host Protected Area
- * 9: DEVICE Reset
- * 8: SERVICE Interrupt
- * 7: Release Interrupt
- * 6: look-ahead
- * 5: write cache
- * 4: PACKET Command
- * 3: Power Management Feature Set
- * 2: Removable Feature Set
- * 1: Security Feature Set
- * 0: SMART Feature Set
- */
- unsigned short command_set_2; /* (word 83)
- * 15: Shall be ZERO
- * 14: Shall be ONE
- * 13: FLUSH CACHE EXT
- * 12: FLUSH CACHE
- * 11: Device Configuration Overlay
- * 10: 48-bit Address Feature Set
- * 9: Automatic Acoustic Management
- * 8: SET MAX security
- * 7: reserved 1407DT PARTIES
- * 6: SetF sub-command Power-Up
- * 5: Power-Up in Standby Feature Set
- * 4: Removable Media Notification
- * 3: APM Feature Set
- * 2: CFA Feature Set
- * 1: READ/WRITE DMA QUEUED
- * 0: Download MicroCode
- */
- unsigned short cfsse; /* (word 84)
- * cmd set-feature supported extensions
- * 15: Shall be ZERO
- * 14: Shall be ONE
- * 13:6 reserved
- * 5: General Purpose Logging
- * 4: Streaming Feature Set
- * 3: Media Card Pass Through
- * 2: Media Serial Number Valid
- * 1: SMART selt-test supported
- * 0: SMART error logging
- */
- unsigned short cfs_enable_1; /* (word 85)
- * command set-feature enabled
- * 15: Obsolete
- * 14: NOP command
- * 13: READ_BUFFER
- * 12: WRITE_BUFFER
- * 11: Obsolete
- * 10: Host Protected Area
- * 9: DEVICE Reset
- * 8: SERVICE Interrupt
- * 7: Release Interrupt
- * 6: look-ahead
- * 5: write cache
- * 4: PACKET Command
- * 3: Power Management Feature Set
- * 2: Removable Feature Set
- * 1: Security Feature Set
- * 0: SMART Feature Set
- */
- unsigned short cfs_enable_2; /* (word 86)
- * command set-feature enabled
- * 15: Shall be ZERO
- * 14: Shall be ONE
- * 13: FLUSH CACHE EXT
- * 12: FLUSH CACHE
- * 11: Device Configuration Overlay
- * 10: 48-bit Address Feature Set
- * 9: Automatic Acoustic Management
- * 8: SET MAX security
- * 7: reserved 1407DT PARTIES
- * 6: SetF sub-command Power-Up
- * 5: Power-Up in Standby Feature Set
- * 4: Removable Media Notification
- * 3: APM Feature Set
- * 2: CFA Feature Set
- * 1: READ/WRITE DMA QUEUED
- * 0: Download MicroCode
- */
- unsigned short csf_default; /* (word 87)
- * command set-feature default
- * 15: Shall be ZERO
- * 14: Shall be ONE
- * 13:6 reserved
- * 5: General Purpose Logging enabled
- * 4: Valid CONFIGURE STREAM executed
- * 3: Media Card Pass Through enabled
- * 2: Media Serial Number Valid
- * 1: SMART selt-test supported
- * 0: SMART error logging
- */
- unsigned short dma_ultra; /* (word 88) */
- unsigned short trseuc; /* time required for security erase */
- unsigned short trsEuc; /* time required for enhanced erase */
- unsigned short CurAPMvalues; /* current APM values */
- unsigned short mprc; /* master password revision code */
- unsigned short hw_config; /* hardware config (word 93)
- * 15: Shall be ZERO
- * 14: Shall be ONE
- * 13:
- * 12:
- * 11:
- * 10:
- * 9:
- * 8:
- * 7:
- * 6:
- * 5:
- * 4:
- * 3:
- * 2:
- * 1:
- * 0: Shall be ONE
- */
- unsigned short acoustic; /* (word 94)
- * 15:8 Vendor's recommended value
- * 7:0 current value
- */
- unsigned short msrqs; /* min stream request size */
- unsigned short sxfert; /* stream transfer time */
- unsigned short sal; /* stream access latency */
- unsigned int spg; /* stream performance granularity */
- unsigned long long lba_capacity_2;/* 48-bit total number of sectors */
- unsigned short words104_125[22];/* reserved words 104-125 */
- unsigned short last_lun; /* (word 126) */
- unsigned short word127; /* (word 127) Feature Set
- * Removable Media Notification
- * 15:2 reserved
- * 1:0 00 = not supported
- * 01 = supported
- * 10 = reserved
- * 11 = reserved
- */
- unsigned short dlf; /* (word 128)
- * device lock function
- * 15:9 reserved
- * 8 security level 1:max 0:high
- * 7:6 reserved
- * 5 enhanced erase
- * 4 expire
- * 3 frozen
- * 2 locked
- * 1 en/disabled
- * 0 capability
- */
- unsigned short csfo; /* (word 129)
- * current set features options
- * 15:4 reserved
- * 3: auto reassign
- * 2: reverting
- * 1: read-look-ahead
- * 0: write cache
- */
- unsigned short words130_155[26];/* reserved vendor words 130-155 */
- unsigned short word156; /* reserved vendor word 156 */
- unsigned short words157_159[3];/* reserved vendor words 157-159 */
- unsigned short cfa_power; /* (word 160) CFA Power Mode
- * 15 word 160 supported
- * 14 reserved
- * 13
- * 12
- * 11:0
- */
- unsigned short words161_175[15];/* Reserved for CFA */
- unsigned short words176_205[30];/* Current Media Serial Number */
- unsigned short words206_254[49];/* reserved words 206-254 */
- unsigned short integrity_word; /* (word 255)
- * 15:8 Checksum
- * 7:0 Signature
- */
-};
-
-#endif /* __DRIVEID_H__ */
-
diff --git a/sys/mips/cavium/files.octeon1 b/sys/mips/cavium/files.octeon1
index 4cf31f8..48c36cf 100644
--- a/sys/mips/cavium/files.octeon1
+++ b/sys/mips/cavium/files.octeon1
@@ -2,16 +2,59 @@
# Octeon Support Files
#
mips/cavium/asm_octeon.S optional smp
-mips/cavium/dev/rgmii/octeon_fpa.c optional rgmii
-mips/cavium/dev/rgmii/octeon_ipd.c optional rgmii
-mips/cavium/dev/rgmii/octeon_pko.c optional rgmii
-mips/cavium/dev/rgmii/octeon_rgmx.c optional rgmii
+mips/cavium/ciu.c standard
mips/cavium/obio.c optional uart
+mips/cavium/octeon_ds1337.c standard
mips/cavium/octeon_ebt3000_cf.c optional cf
mips/cavium/octeon_machdep.c standard
mips/cavium/octeon_mp.c optional smp
+mips/cavium/octeon_rtc.c standard
mips/cavium/uart_bus_octeonusart.c optional uart
mips/cavium/uart_cpu_octeonusart.c optional uart
mips/cavium/uart_dev_oct16550.c optional uart
mips/mips/intr_machdep.c standard
mips/mips/tick.c standard
+
+mips/cavium/octeon_rnd.c optional random
+
+mips/cavium/octe/ethernet.c optional octe
+mips/cavium/octe/ethernet-common.c optional octe
+mips/cavium/octe/ethernet-mdio.c optional octe
+mips/cavium/octe/ethernet-mem.c optional octe
+mips/cavium/octe/ethernet-rgmii.c optional octe
+mips/cavium/octe/ethernet-rx.c optional octe
+mips/cavium/octe/ethernet-sgmii.c optional octe
+mips/cavium/octe/ethernet-spi.c optional octe
+mips/cavium/octe/ethernet-tx.c optional octe
+mips/cavium/octe/ethernet-xaui.c optional octe
+mips/cavium/octe/octe.c optional octe
+mips/cavium/octe/octebus.c optional octe
+
+mips/cavium/octopci.c optional pci
+mips/cavium/octopci_bus_space.c optional pci
+
+contrib/octeon-sdk/cvmx-cmd-queue.c optional octe
+contrib/octeon-sdk/cvmx-fpa.c optional octe
+contrib/octeon-sdk/cvmx-helper.c optional octe
+contrib/octeon-sdk/cvmx-helper-board.c optional octe
+contrib/octeon-sdk/cvmx-helper-errata.c optional octe
+contrib/octeon-sdk/cvmx-helper-fpa.c optional octe
+contrib/octeon-sdk/cvmx-helper-loop.c optional octe
+contrib/octeon-sdk/cvmx-helper-npi.c optional octe
+contrib/octeon-sdk/cvmx-helper-rgmii.c optional octe
+contrib/octeon-sdk/cvmx-helper-sgmii.c optional octe
+contrib/octeon-sdk/cvmx-helper-spi.c optional octe
+contrib/octeon-sdk/cvmx-helper-util.c optional octe
+contrib/octeon-sdk/cvmx-helper-xaui.c optional octe
+contrib/octeon-sdk/cvmx-pko.c optional octe
+contrib/octeon-sdk/cvmx-spi.c optional octe
+contrib/octeon-sdk/cvmx-spi4000.c optional octe
+contrib/octeon-sdk/cvmx-twsi.c optional octe
+
+# XXX Some files could be excluded in some configurations. Making them
+# optional but on in the default config would seem reasonable.
+contrib/octeon-sdk/cvmx-bootmem.c standard
+contrib/octeon-sdk/cvmx-sysinfo.c standard
+contrib/octeon-sdk/cvmx-thunder.c standard
+contrib/octeon-sdk/cvmx-warn.c standard
+contrib/octeon-sdk/octeon-model.c standard
diff --git a/sys/mips/cavium/obio.c b/sys/mips/cavium/obio.c
index 9ef5b45..f1ceab4 100644
--- a/sys/mips/cavium/obio.c
+++ b/sys/mips/cavium/obio.c
@@ -56,34 +56,42 @@ __FBSDID("$FreeBSD$");
#include <mips/cavium/octeon_pcmap_regs.h>
#include <mips/cavium/obiovar.h>
+#include <contrib/octeon-sdk/cvmx.h>
+#include <contrib/octeon-sdk/cvmx-interrupt.h>
+
extern struct bus_space octeon_uart_tag;
-int obio_probe(device_t);
-int obio_attach(device_t);
+static void obio_identify(driver_t *, device_t);
+static int obio_probe(device_t);
+static int obio_attach(device_t);
-/*
- * We need only one obio. Any other device hanging off of it,
- * shouldn't cause multiple of these to be found.
- */
-static int have_one = 0;
+static void
+obio_identify(driver_t *drv, device_t parent)
+{
+ BUS_ADD_CHILD(parent, 0, "obio", 0);
+}
-int
+static int
obio_probe(device_t dev)
{
- if (!have_one) {
- have_one = 1;
- return 0;
- }
- return (ENXIO);
+ if (device_get_unit(dev) != 0)
+ return (ENXIO);
+ return (0);
}
-int
+static int
obio_attach(device_t dev)
{
struct obio_softc *sc = device_get_softc(dev);
sc->oba_st = mips_bus_space_generic;
- sc->oba_addr = OCTEON_MIO_UART0;
+ /*
+ * XXX
+ * Here and elsewhere using RBR as a base address because it kind of
+ * is, but that feels pretty sloppy. Should consider adding a define
+ * that's more semantic, at least.
+ */
+ sc->oba_addr = CVMX_MIO_UARTX_RBR(0);
sc->oba_size = 0x10000;
sc->oba_rman.rm_type = RMAN_ARRAY;
sc->oba_rman.rm_descr = "OBIO I/O";
@@ -96,10 +104,10 @@ obio_attach(device_t dev)
/*
* This module is intended for UART purposes only and
- * it's IRQ is 0 corresponding to IP2.
+ * manages IRQs for UART0 and UART1.
*/
if (rman_init(&sc->oba_irq_rman) != 0 ||
- rman_manage_region(&sc->oba_irq_rman, 0, 0) != 0)
+ rman_manage_region(&sc->oba_irq_rman, CVMX_IRQ_UART0, CVMX_IRQ_UART1) != 0)
panic("obio_attach: failed to set up IRQ rman");
device_add_child(dev, "uart", 1); /* Setup Uart-1 first. */
@@ -121,6 +129,16 @@ obio_alloc_resource(device_t bus, device_t child, int type, int *rid,
switch (type) {
case SYS_RES_IRQ:
+ switch (device_get_unit(child)) {
+ case 0:
+ start = end = CVMX_IRQ_UART0;
+ break;
+ case 1:
+ start = end = CVMX_IRQ_UART1;
+ break;
+ default:
+ return (NULL);
+ }
rm = &sc->oba_irq_rman;
break;
case SYS_RES_MEMORY:
@@ -128,8 +146,7 @@ obio_alloc_resource(device_t bus, device_t child, int type, int *rid,
case SYS_RES_IOPORT:
rm = &sc->oba_rman;
bt = &octeon_uart_tag;
- bh = device_get_unit(child) ?
- OCTEON_MIO_UART1 : OCTEON_MIO_UART0;
+ bh = CVMX_MIO_UARTX_RBR(device_get_unit(child));
start = bh;
break;
default:
@@ -164,11 +181,14 @@ obio_activate_resource(device_t bus, device_t child, int type, int rid,
return (0);
}
static device_method_t obio_methods[] = {
- DEVMETHOD(device_probe, obio_probe),
- DEVMETHOD(device_attach, obio_attach),
-
- DEVMETHOD(bus_alloc_resource, obio_alloc_resource),
- DEVMETHOD(bus_activate_resource, obio_activate_resource),
+ /* Device methods */
+ DEVMETHOD(device_identify, obio_identify),
+ DEVMETHOD(device_probe, obio_probe),
+ DEVMETHOD(device_attach, obio_attach),
+
+ /* Bus methods */
+ DEVMETHOD(bus_alloc_resource, obio_alloc_resource),
+ DEVMETHOD(bus_activate_resource,obio_activate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
@@ -182,4 +202,4 @@ static driver_t obio_driver = {
};
static devclass_t obio_devclass;
-DRIVER_MODULE(obio, nexus, obio_driver, obio_devclass, 0, 0);
+DRIVER_MODULE(obio, ciu, obio_driver, obio_devclass, 0, 0);
diff --git a/sys/mips/cavium/octe/cavium-ethernet.h b/sys/mips/cavium/octe/cavium-ethernet.h
new file mode 100644
index 0000000..0ab2680
--- /dev/null
+++ b/sys/mips/cavium/octe/cavium-ethernet.h
@@ -0,0 +1,94 @@
+/*************************************************************************
+Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). All rights
+reserved.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export control laws, including the U.S. Export Administration Act and its associated regulations, and may be subject to export or import regulations in other countries.
+
+TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+
+*************************************************************************/
+/* $FreeBSD$ */
+
+/**
+ * @file
+ * External interface for the Cavium Octeon ethernet driver.
+ *
+ * $Id: cavium-ethernet.h 41589 2009-03-19 19:58:58Z cchavva $
+ *
+ */
+#ifndef CAVIUM_ETHERNET_H
+#define CAVIUM_ETHERNET_H
+
+#include <net/if_media.h>
+
+/**
+ * This is the definition of the Ethernet driver's private
+ * driver state stored in ifp->if_softc.
+ */
+typedef struct {
+ /* XXX FreeBSD device softcs must start with an ifnet pointer. */
+ struct ifnet *ifp;
+
+ int port; /* PKO hardware output port */
+ int queue; /* PKO hardware queue for the port */
+ int fau; /* Hardware fetch and add to count outstanding tx buffers */
+ int imode; /* Type of port. This is one of the enums in cvmx_helper_interface_mode_t */
+#if 0
+ struct ifnet_stats stats; /* Device statistics */
+#endif
+ uint64_t link_info; /* Last negotiated link state */
+ void (*poll)(struct ifnet *ifp); /* Called periodically to check link status */
+
+ /*
+ * FreeBSD additions.
+ */
+ device_t dev;
+ device_t miibus;
+
+ int (*open)(struct ifnet *ifp);
+ int (*stop)(struct ifnet *ifp);
+
+ int (*init)(struct ifnet *ifp);
+ void (*uninit)(struct ifnet *ifp);
+
+ uint8_t mac[6];
+ int phy_id;
+
+ struct ifqueue tx_free_queue[16];
+
+ struct ifmedia media;
+ int if_flags;
+
+ struct mtx tx_mtx;
+} cvm_oct_private_t;
+
+
+/**
+ * Free a work queue entry received in a intercept callback.
+ *
+ * @param work_queue_entry
+ * Work queue entry to free
+ * @return Zero on success, Negative on failure.
+ */
+int cvm_oct_free_work(void *work_queue_entry);
+
+#endif
diff --git a/sys/mips/cavium/octe/ethernet-common.c b/sys/mips/cavium/octe/ethernet-common.c
new file mode 100644
index 0000000..2ebbb09
--- /dev/null
+++ b/sys/mips/cavium/octe/ethernet-common.c
@@ -0,0 +1,278 @@
+/*************************************************************************
+Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). All rights
+reserved.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export control laws, including the U.S. Export Administration Act and its associated regulations, and may be subject to export or import regulations in other countries.
+
+TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+
+*************************************************************************/
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+
+#include "wrapper-cvmx-includes.h"
+#include "ethernet-headers.h"
+
+extern int octeon_is_simulation(void);
+extern cvmx_bootinfo_t *octeon_bootinfo;
+extern int pow_send_group;
+extern int always_use_pow;
+extern char pow_send_list[];
+
+
+/**
+ * Get the low level ethernet statistics
+ *
+ * @param dev Device to get the statistics from
+ * @return Pointer to the statistics
+ */
+#if 0
+static struct ifnet_stats *cvm_oct_common_get_stats(struct ifnet *ifp)
+{
+ cvmx_pip_port_status_t rx_status;
+ cvmx_pko_port_status_t tx_status;
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+
+ if (priv->port < CVMX_PIP_NUM_INPUT_PORTS) {
+ if (octeon_is_simulation()) {
+ /* The simulator doesn't support statistics */
+ memset(&rx_status, 0, sizeof(rx_status));
+ memset(&tx_status, 0, sizeof(tx_status));
+ } else {
+ cvmx_pip_get_port_status(priv->port, 1, &rx_status);
+ cvmx_pko_get_port_status(priv->port, 1, &tx_status);
+ }
+
+ priv->stats.rx_packets += rx_status.inb_packets;
+ priv->stats.tx_packets += tx_status.packets;
+ priv->stats.rx_bytes += rx_status.inb_octets;
+ priv->stats.tx_bytes += tx_status.octets;
+ priv->stats.multicast += rx_status.multicast_packets;
+ priv->stats.rx_crc_errors += rx_status.inb_errors;
+ priv->stats.rx_frame_errors += rx_status.fcs_align_err_packets;
+
+ /* The drop counter must be incremented atomically since the RX
+ tasklet also increments it */
+#ifdef CONFIG_64BIT
+ cvmx_atomic_add64_nosync(&priv->stats.rx_dropped, rx_status.dropped_packets);
+#else
+ cvmx_atomic_add32_nosync((int32_t *)&priv->stats.rx_dropped, rx_status.dropped_packets);
+#endif
+ }
+
+ return &priv->stats;
+}
+#endif
+
+
+/**
+ * Set the multicast list. Currently unimplemented.
+ *
+ * @param dev Device to work on
+ */
+void cvm_oct_common_set_multicast_list(struct ifnet *ifp)
+{
+ cvmx_gmxx_prtx_cfg_t gmx_cfg;
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+ int interface = INTERFACE(priv->port);
+ int index = INDEX(priv->port);
+
+ if ((interface < 2) && (cvmx_helper_interface_get_mode(interface) != CVMX_HELPER_INTERFACE_MODE_SPI)) {
+ cvmx_gmxx_rxx_adr_ctl_t control;
+ control.u64 = 0;
+ control.s.bcst = 1; /* Allow broadcast MAC addresses */
+
+ if (/*ifp->mc_list || */(ifp->if_flags&IFF_ALLMULTI) ||
+ (ifp->if_flags & IFF_PROMISC))
+ control.s.mcst = 2; /* Force accept multicast packets */
+ else
+ control.s.mcst = 1; /* Force reject multicat packets */
+
+ if (ifp->if_flags & IFF_PROMISC)
+ control.s.cam_mode = 0; /* Reject matches if promisc. Since CAM is shut off, should accept everything */
+ else
+ control.s.cam_mode = 1; /* Filter packets based on the CAM */
+
+ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64 & ~1ull);
+
+ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CTL(index, interface), control.u64);
+ if (ifp->if_flags&IFF_PROMISC)
+ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM_EN(index, interface), 0);
+ else
+ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM_EN(index, interface), 1);
+
+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
+ }
+}
+
+
+/**
+ * Set the hardware MAC address for a device
+ *
+ * @param dev Device to change the MAC address for
+ * @param addr Address structure to change it too.
+ */
+void cvm_oct_common_set_mac_address(struct ifnet *ifp, const void *addr)
+{
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+ cvmx_gmxx_prtx_cfg_t gmx_cfg;
+ int interface = INTERFACE(priv->port);
+ int index = INDEX(priv->port);
+
+ memcpy(priv->mac, addr, 6);
+
+ if ((interface < 2) && (cvmx_helper_interface_get_mode(interface) != CVMX_HELPER_INTERFACE_MODE_SPI)) {
+ int i;
+ const uint8_t *ptr = addr;
+ uint64_t mac = 0;
+ for (i = 0; i < 6; i++)
+ mac = (mac<<8) | (uint64_t)(ptr[i]);
+
+ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64 & ~1ull);
+
+ cvmx_write_csr(CVMX_GMXX_SMACX(index, interface), mac);
+ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM0(index, interface), ptr[0]);
+ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM1(index, interface), ptr[1]);
+ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM2(index, interface), ptr[2]);
+ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM3(index, interface), ptr[3]);
+ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM4(index, interface), ptr[4]);
+ cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM5(index, interface), ptr[5]);
+ cvm_oct_common_set_multicast_list(ifp);
+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
+ }
+}
+
+
+/**
+ * Change the link MTU. Unimplemented
+ *
+ * @param dev Device to change
+ * @param new_mtu The new MTU
+ * @return Zero on success
+ */
+int cvm_oct_common_change_mtu(struct ifnet *ifp, int new_mtu)
+{
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+ int interface = INTERFACE(priv->port);
+ int index = INDEX(priv->port);
+ int vlan_bytes = 4;
+
+ /* Limit the MTU to make sure the ethernet packets are between 64 bytes
+ and 65535 bytes */
+ if ((new_mtu + 14 + 4 + vlan_bytes < 64) || (new_mtu + 14 + 4 + vlan_bytes > 65392)) {
+ printf("MTU must be between %d and %d.\n", 64-14-4-vlan_bytes, 65392-14-4-vlan_bytes);
+ return -EINVAL;
+ }
+ ifp->if_mtu = new_mtu;
+
+ if ((interface < 2) && (cvmx_helper_interface_get_mode(interface) != CVMX_HELPER_INTERFACE_MODE_SPI)) {
+ int max_packet = new_mtu + 14 + 4 + vlan_bytes; /* Add ethernet header and FCS, and VLAN if configured. */
+
+ if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN58XX)) {
+ /* Signal errors on packets larger than the MTU */
+ cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX(index, interface), max_packet);
+ } else {
+ /* Set the hardware to truncate packets larger than the MTU and
+ smaller the 64 bytes */
+ cvmx_pip_frm_len_chkx_t frm_len_chk;
+ frm_len_chk.u64 = 0;
+ frm_len_chk.s.minlen = 64;
+ frm_len_chk.s.maxlen = max_packet;
+ cvmx_write_csr(CVMX_PIP_FRM_LEN_CHKX(interface), frm_len_chk.u64);
+ }
+ /* Set the hardware to truncate packets larger than the MTU. The
+ jabber register must be set to a multiple of 8 bytes, so round up */
+ cvmx_write_csr(CVMX_GMXX_RXX_JABBER(index, interface), (max_packet + 7) & ~7u);
+ }
+ return 0;
+}
+
+
+/**
+ * Per network device initialization
+ *
+ * @param dev Device to initialize
+ * @return Zero on success
+ */
+int cvm_oct_common_init(struct ifnet *ifp)
+{
+ static int count;
+ char mac[6] = {
+ octeon_bootinfo->mac_addr_base[0],
+ octeon_bootinfo->mac_addr_base[1],
+ octeon_bootinfo->mac_addr_base[2],
+ octeon_bootinfo->mac_addr_base[3],
+ octeon_bootinfo->mac_addr_base[4],
+ octeon_bootinfo->mac_addr_base[5] + count};
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+
+ /* Force the interface to use the POW send if always_use_pow was
+ specified or it is in the pow send list */
+ if ((pow_send_group != -1) && (always_use_pow || strstr(pow_send_list, if_name(ifp))))
+ priv->queue = -1;
+
+ ifp->if_mtu = ETHERMTU;
+
+ count++;
+
+#if 0
+ ifp->get_stats = cvm_oct_common_get_stats;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ ifp->poll_controller = cvm_oct_poll_controller;
+#endif
+#endif
+
+ cvm_oct_mdio_setup_device(ifp);
+
+ cvm_oct_common_set_mac_address(ifp, mac);
+ cvm_oct_common_change_mtu(ifp, ifp->if_mtu);
+
+#if 0
+ /* Zero out stats for port so we won't mistakenly show counters from the
+ bootloader */
+ memset(ifp->get_stats(ifp), 0, sizeof(struct ifnet_stats));
+#endif
+
+ device_attach(priv->dev);
+
+ return 0;
+}
+
+void cvm_oct_common_uninit(struct ifnet *ifp)
+{
+ /* Currently nothing to do */
+}
+
diff --git a/sys/mips/cavium/octe/ethernet-common.h b/sys/mips/cavium/octe/ethernet-common.h
new file mode 100644
index 0000000..ef6e4aa
--- /dev/null
+++ b/sys/mips/cavium/octe/ethernet-common.h
@@ -0,0 +1,52 @@
+/*************************************************************************
+Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). All rights
+reserved.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export control laws, including the U.S. Export Administration Act and its associated regulations, and may be subject to export or import regulations in other countries.
+
+TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+
+*************************************************************************/
+/* $FreeBSD$ */
+
+int cvm_oct_common_init(struct ifnet *ifp);
+void cvm_oct_common_uninit(struct ifnet *ifp);
+
+int cvm_oct_common_change_mtu(struct ifnet *ifp, int new_mtu);
+void cvm_oct_common_set_multicast_list(struct ifnet *ifp);
+void cvm_oct_common_set_mac_address(struct ifnet *ifp, const void *);
+
+int cvm_oct_init_module(device_t);
+void cvm_oct_cleanup_module(void);
+
+/*
+ * XXX/juli
+ * These belong elsewhere but we can't stomach the nested extern.
+ */
+int cvm_oct_rgmii_init(struct ifnet *ifp);
+void cvm_oct_rgmii_uninit(struct ifnet *ifp);
+int cvm_oct_sgmii_init(struct ifnet *ifp);
+void cvm_oct_sgmii_uninit(struct ifnet *ifp);
+int cvm_oct_spi_init(struct ifnet *ifp);
+void cvm_oct_spi_uninit(struct ifnet *ifp);
+int cvm_oct_xaui_init(struct ifnet *ifp);
+void cvm_oct_xaui_uninit(struct ifnet *ifp);
diff --git a/sys/mips/cavium/octe/ethernet-defines.h b/sys/mips/cavium/octe/ethernet-defines.h
new file mode 100644
index 0000000..64babf5
--- /dev/null
+++ b/sys/mips/cavium/octe/ethernet-defines.h
@@ -0,0 +1,101 @@
+/*************************************************************************
+Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). All rights
+reserved.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export control laws, including the U.S. Export Administration Act and its associated regulations, and may be subject to export or import regulations in other countries.
+
+TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+
+*************************************************************************/
+/* $FreeBSD$ */
+
+/*
+ * A few defines are used to control the operation of this driver:
+ * CONFIG_CAVIUM_RESERVE32
+ * This kernel config options controls the amount of memory configured
+ * in a wired TLB entry for all processes to share. If this is set, the
+ * driver will use this memory instead of kernel memory for pools. This
+ * allows 32bit userspace application to access the buffers, but also
+ * requires all received packets to be copied.
+ * CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS
+ * This kernel config option allows the user to control the number of
+ * packet and work queue buffers allocated by the driver. If this is zero,
+ * the driver uses the default from below.
+ * USE_MBUFS_IN_HW
+ * Tells the driver to populate the packet buffers with kernel mbufs.
+ * This allows the driver to receive packets without copying them. It also
+ * means that 32bit userspace can't access the packet buffers.
+ * USE_32BIT_SHARED
+ * This define tells the driver to allocate memory for buffers from the
+ * 32bit sahred region instead of the kernel memory space.
+ * USE_HW_TCPUDP_CHECKSUM
+ * Controls if the Octeon TCP/UDP checksum engine is used for packet
+ * output. If this is zero, the kernel will perform the checksum in
+ * software.
+ * USE_MULTICORE_RECEIVE
+ * Process receive interrupts on multiple cores. This spreads the network
+ * load across the first 8 processors. If ths is zero, only one core
+ * processes incomming packets.
+ * USE_ASYNC_IOBDMA
+ * Use asynchronous IO access to hardware. This uses Octeon's asynchronous
+ * IOBDMAs to issue IO accesses without stalling. Set this to zero
+ * to disable this. Note that IOBDMAs require CVMSEG.
+ */
+#ifndef CONFIG_CAVIUM_RESERVE32
+#define CONFIG_CAVIUM_RESERVE32 0
+#endif
+
+#if CONFIG_CAVIUM_RESERVE32
+ #define USE_32BIT_SHARED 1
+ #define USE_MBUFS_IN_HW 0
+#else
+ #define USE_32BIT_SHARED 0
+ #define USE_MBUFS_IN_HW 1
+#endif
+
+#define INTERRUPT_LIMIT 10000 /* Max interrupts per second per core */
+/*#define INTERRUPT_LIMIT 0 *//* Don't limit the number of interrupts */
+#define USE_HW_TCPUDP_CHECKSUM 1
+#define USE_MULTICORE_RECEIVE 1
+#define USE_RED 1 /* Enable Random Early Dropping under load */
+#if 0
+#define USE_ASYNC_IOBDMA (CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0)
+#else
+#define USE_ASYNC_IOBDMA 0
+#endif
+#define USE_10MBPS_PREAMBLE_WORKAROUND 1 /* Allow SW based preamble removal at 10Mbps to workaround PHYs giving us bad preambles */
+#define DONT_WRITEBACK(x) (x) /* Use this to have all FPA frees also tell the L2 not to write data to memory */
+/*#define DONT_WRITEBACK(x) 0 *//* Use this to not have FPA frees control L2 */
+
+#define MAX_RX_PACKETS 120 /* Maximum number of packets to process per interrupt. */
+#define MAX_OUT_QUEUE_DEPTH 1000
+
+#ifndef SMP
+#undef USE_MULTICORE_RECEIVE
+#define USE_MULTICORE_RECEIVE 0
+#endif
+
+#define IP_PROTOCOL_TCP 6
+#define IP_PROTOCOL_UDP 0x11
+#define FAU_NUM_PACKET_BUFFERS_TO_FREE (CVMX_FAU_REG_END - sizeof(uint32_t))
+#define TOTAL_NUMBER_OF_PORTS (CVMX_PIP_NUM_INPUT_PORTS+1)
+
diff --git a/sys/mips/cavium/octe/ethernet-headers.h b/sys/mips/cavium/octe/ethernet-headers.h
new file mode 100644
index 0000000..ec87c45
--- /dev/null
+++ b/sys/mips/cavium/octe/ethernet-headers.h
@@ -0,0 +1,43 @@
+/*************************************************************************
+Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). All rights
+reserved.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export control laws, including the U.S. Export Administration Act and its associated regulations, and may be subject to export or import regulations in other countries.
+
+TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+
+*************************************************************************/
+/* $FreeBSD$ */
+
+#ifndef __ETHERNET_HEADERS_H__
+#define __ETHERNET_HEADERS_H__
+
+#include "cavium-ethernet.h"
+#include "ethernet-common.h"
+#include "ethernet-defines.h"
+#include "ethernet-mdio.h"
+#include "ethernet-mem.h"
+#include "ethernet-rx.h"
+#include "ethernet-tx.h"
+#include "ethernet-util.h"
+
+#endif
diff --git a/sys/mips/cavium/octe/ethernet-mdio.c b/sys/mips/cavium/octe/ethernet-mdio.c
new file mode 100644
index 0000000..0aff27e
--- /dev/null
+++ b/sys/mips/cavium/octe/ethernet-mdio.c
@@ -0,0 +1,138 @@
+/*************************************************************************
+Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). All rights
+reserved.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export control laws, including the U.S. Export Administration Act and its associated regulations, and may be subject to export or import regulations in other countries.
+
+TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+
+*************************************************************************/
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+
+#include "wrapper-cvmx-includes.h"
+#include "ethernet-headers.h"
+
+struct mtx cvm_oct_mdio_mtx;
+MTX_SYSINIT(cvm_oct_mdio, &cvm_oct_mdio_mtx, "MDIO", MTX_DEF);
+
+/**
+ * Perform an MII read. Called by the generic MII routines
+ *
+ * @param dev Device to perform read for
+ * @param phy_id The MII phy id
+ * @param location Register location to read
+ * @return Result from the read or zero on failure
+ */
+int cvm_oct_mdio_read(struct ifnet *ifp, int phy_id, int location)
+{
+ cvmx_smi_cmd_t smi_cmd;
+ cvmx_smi_rd_dat_t smi_rd;
+
+ MDIO_LOCK();
+ smi_cmd.u64 = 0;
+ smi_cmd.s.phy_op = 1;
+ smi_cmd.s.phy_adr = phy_id;
+ smi_cmd.s.reg_adr = location;
+ cvmx_write_csr(CVMX_SMI_CMD, smi_cmd.u64);
+
+ do {
+#if 0
+ if (!in_interrupt())
+ yield();
+#endif
+ smi_rd.u64 = cvmx_read_csr(CVMX_SMI_RD_DAT);
+ } while (smi_rd.s.pending);
+
+ MDIO_UNLOCK();
+
+ if (smi_rd.s.val)
+ return smi_rd.s.dat;
+ else
+ return 0;
+}
+
+
+/**
+ * Perform an MII write. Called by the generic MII routines
+ *
+ * @param dev Device to perform write for
+ * @param phy_id The MII phy id
+ * @param location Register location to write
+ * @param val Value to write
+ */
+void cvm_oct_mdio_write(struct ifnet *ifp, int phy_id, int location, int val)
+{
+ cvmx_smi_cmd_t smi_cmd;
+ cvmx_smi_wr_dat_t smi_wr;
+
+ MDIO_LOCK();
+ smi_wr.u64 = 0;
+ smi_wr.s.dat = val;
+ cvmx_write_csr(CVMX_SMI_WR_DAT, smi_wr.u64);
+
+ smi_cmd.u64 = 0;
+ smi_cmd.s.phy_op = 0;
+ smi_cmd.s.phy_adr = phy_id;
+ smi_cmd.s.reg_adr = location;
+ cvmx_write_csr(CVMX_SMI_CMD, smi_cmd.u64);
+
+ do {
+#if 0
+ if (!in_interrupt())
+ yield();
+#endif
+ smi_wr.u64 = cvmx_read_csr(CVMX_SMI_WR_DAT);
+ } while (smi_wr.s.pending);
+ MDIO_UNLOCK();
+}
+
+/**
+ * Setup the MDIO device structures
+ *
+ * @param dev Device to setup
+ *
+ * @return Zero on success, negative on failure
+ */
+int cvm_oct_mdio_setup_device(struct ifnet *ifp)
+{
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+
+ priv->phy_id = cvmx_helper_board_get_mii_address(priv->port);
+
+ return 0;
+}
+
diff --git a/sys/mips/cavium/octe/ethernet-mdio.h b/sys/mips/cavium/octe/ethernet-mdio.h
new file mode 100644
index 0000000..c2c4ec6
--- /dev/null
+++ b/sys/mips/cavium/octe/ethernet-mdio.h
@@ -0,0 +1,40 @@
+/*************************************************************************
+Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). All rights
+reserved.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export control laws, including the U.S. Export Administration Act and its associated regulations, and may be subject to export or import regulations in other countries.
+
+TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+
+*************************************************************************/
+/* $FreeBSD$ */
+
+extern struct mtx cvm_oct_mdio_mtx;
+
+#define MDIO_LOCK() mtx_lock(&cvm_oct_mdio_mtx)
+#define MDIO_UNLOCK() mtx_unlock(&cvm_oct_mdio_mtx)
+#define MDIO_TRYLOCK() mtx_trylock(&cvm_oct_mdio_mtx)
+
+int cvm_oct_mdio_read(struct ifnet *ifp, int phy_id, int location);
+void cvm_oct_mdio_write(struct ifnet *ifp, int phy_id, int location, int val);
+int cvm_oct_mdio_setup_device(struct ifnet *ifp);
+
diff --git a/sys/mips/cavium/octe/ethernet-mem.c b/sys/mips/cavium/octe/ethernet-mem.c
new file mode 100644
index 0000000..5d2fa54
--- /dev/null
+++ b/sys/mips/cavium/octe/ethernet-mem.c
@@ -0,0 +1,207 @@
+/*************************************************************************
+Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). All rights
+reserved.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export control laws, including the U.S. Export Administration Act and its associated regulations, and may be subject to export or import regulations in other countries.
+
+TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+
+*************************************************************************/
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+
+#include "wrapper-cvmx-includes.h"
+#include "ethernet-headers.h"
+
+/**
+ * Fill the supplied hardware pool with mbufs
+ *
+ * @param pool Pool to allocate an mbuf for
+ * @param size Size of the buffer needed for the pool
+ * @param elements Number of buffers to allocate
+ */
+static int cvm_oct_fill_hw_mbuf(int pool, int size, int elements)
+{
+ int freed = elements;
+ while (freed) {
+ KASSERT(size <= MCLBYTES - 128, ("mbuf clusters are too small"));
+
+ struct mbuf *m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+ if (__predict_false(m == NULL)) {
+ printf("Failed to allocate mbuf for hardware pool %d\n", pool);
+ break;
+ }
+
+ m->m_data += 128 - (((uintptr_t)m->m_data) & 0x7f);
+ *(struct mbuf **)(m->m_data - sizeof(void *)) = m;
+ cvmx_fpa_free(m->m_data, pool, DONT_WRITEBACK(size/128));
+ freed--;
+ }
+ return (elements - freed);
+}
+
+
+/**
+ * Free the supplied hardware pool of mbufs
+ *
+ * @param pool Pool to allocate an mbuf for
+ * @param size Size of the buffer needed for the pool
+ * @param elements Number of buffers to allocate
+ */
+static void cvm_oct_free_hw_mbuf(int pool, int size, int elements)
+{
+ char *memory;
+
+ do {
+ memory = cvmx_fpa_alloc(pool);
+ if (memory) {
+ struct mbuf *m = *(struct mbuf **)(memory - sizeof(void *));
+ elements--;
+ m_freem(m);
+ }
+ } while (memory);
+
+ if (elements < 0)
+ printf("Warning: Freeing of pool %u had too many mbufs (%d)\n", pool, elements);
+ else if (elements > 0)
+ printf("Warning: Freeing of pool %u is missing %d mbufs\n", pool, elements);
+}
+
+
+/**
+ * This function fills a hardware pool with memory. Depending
+ * on the config defines, this memory might come from the
+ * kernel or global 32bit memory allocated with
+ * cvmx_bootmem_alloc.
+ *
+ * @param pool Pool to populate
+ * @param size Size of each buffer in the pool
+ * @param elements Number of buffers to allocate
+ */
+static int cvm_oct_fill_hw_memory(int pool, int size, int elements)
+{
+ char *memory;
+ int freed = elements;
+
+ if (USE_32BIT_SHARED) {
+#if 0
+ extern uint64_t octeon_reserve32_memory;
+
+ memory = cvmx_bootmem_alloc_range(elements*size, 128, octeon_reserve32_memory,
+ octeon_reserve32_memory + (CONFIG_CAVIUM_RESERVE32<<20) - 1);
+ if (memory == NULL)
+ panic("Unable to allocate %u bytes for FPA pool %d\n", elements*size, pool);
+
+ printf("Memory range %p - %p reserved for hardware\n", memory, memory + elements*size - 1);
+
+ while (freed) {
+ cvmx_fpa_free(memory, pool, 0);
+ memory += size;
+ freed--;
+ }
+#else
+ panic("%s: may need to implement using shared memory.", __func__);
+#endif
+ } else {
+ while (freed) {
+ /* We need to force alignment to 128 bytes here */
+#if 0
+ memory = kmalloc(size + 127, GFP_ATOMIC);
+#else
+ panic("%s: not yet implemented.", __func__);
+#endif
+ if (__predict_false(memory == NULL)) {
+ printf("Unable to allocate %u bytes for FPA pool %d\n", elements*size, pool);
+ break;
+ }
+ memory = (char *)(((unsigned long)memory+127) & -128);
+ cvmx_fpa_free(memory, pool, 0);
+ freed--;
+ }
+ }
+ return (elements - freed);
+}
+
+
+/**
+ * Free memory previously allocated with cvm_oct_fill_hw_memory
+ *
+ * @param pool FPA pool to free
+ * @param size Size of each buffer in the pool
+ * @param elements Number of buffers that should be in the pool
+ */
+static void cvm_oct_free_hw_memory(int pool, int size, int elements)
+{
+ if (USE_32BIT_SHARED) {
+ printf("Warning: 32 shared memory is not freeable\n");
+ } else {
+ char *memory;
+ do {
+ memory = cvmx_fpa_alloc(pool);
+ if (memory) {
+ elements--;
+#if 0
+ kfree(phys_to_virt(cvmx_ptr_to_phys(memory)));
+#else
+ panic("%s: not yet implemented.", __func__);
+#endif
+ }
+ } while (memory);
+
+ if (elements < 0)
+ printf("Freeing of pool %u had too many buffers (%d)\n", pool, elements);
+ else if (elements > 0)
+ printf("Warning: Freeing of pool %u is missing %d buffers\n", pool, elements);
+ }
+}
+
+
+int cvm_oct_mem_fill_fpa(int pool, int size, int elements)
+{
+ int freed;
+ if (USE_MBUFS_IN_HW)
+ freed = cvm_oct_fill_hw_mbuf(pool, size, elements);
+ else
+ freed = cvm_oct_fill_hw_memory(pool, size, elements);
+ return (freed);
+}
+
+void cvm_oct_mem_empty_fpa(int pool, int size, int elements)
+{
+ if (USE_MBUFS_IN_HW)
+ cvm_oct_free_hw_mbuf(pool, size, elements);
+ else
+ cvm_oct_free_hw_memory(pool, size, elements);
+}
+
diff --git a/sys/mips/cavium/octe/ethernet-mem.h b/sys/mips/cavium/octe/ethernet-mem.h
new file mode 100644
index 0000000..d9058d9
--- /dev/null
+++ b/sys/mips/cavium/octe/ethernet-mem.h
@@ -0,0 +1,33 @@
+/*************************************************************************
+Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). All rights
+reserved.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export control laws, including the U.S. Export Administration Act and its associated regulations, and may be subject to export or import regulations in other countries.
+
+TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+
+*************************************************************************/
+/* $FreeBSD$ */
+
+int cvm_oct_mem_fill_fpa(int pool, int size, int elements);
+void cvm_oct_mem_empty_fpa(int pool, int size, int elements);
+
diff --git a/sys/mips/cavium/octe/ethernet-rgmii.c b/sys/mips/cavium/octe/ethernet-rgmii.c
new file mode 100644
index 0000000..d5d704c
--- /dev/null
+++ b/sys/mips/cavium/octe/ethernet-rgmii.c
@@ -0,0 +1,359 @@
+/*************************************************************************
+Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). All rights
+reserved.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export control laws, including the U.S. Export Administration Act and its associated regulations, and may be subject to export or import regulations in other countries.
+
+TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+
+*************************************************************************/
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/rman.h>
+#include <sys/socket.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+
+#include "wrapper-cvmx-includes.h"
+#include "ethernet-headers.h"
+
+#include "octebusvar.h"
+
+extern int octeon_is_simulation(void);
+extern struct ifnet *cvm_oct_device[];
+
+static struct mtx global_register_lock;
+MTX_SYSINIT(global_register_lock, &global_register_lock,
+ "RGMII Global", MTX_SPIN);
+
+static int number_rgmii_ports;
+
+static void cvm_oct_rgmii_poll(struct ifnet *ifp)
+{
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+ cvmx_helper_link_info_t link_info;
+
+ /* Take the global register lock since we are going to touch
+ registers that affect more than one port */
+ mtx_lock_spin(&global_register_lock);
+
+ link_info = cvmx_helper_link_get(priv->port);
+ if (link_info.u64 == priv->link_info) {
+
+ /* If the 10Mbps preamble workaround is supported and we're
+ at 10Mbps we may need to do some special checking */
+ if (USE_10MBPS_PREAMBLE_WORKAROUND && (link_info.s.speed == 10)) {
+
+ /* Read the GMXX_RXX_INT_REG[PCTERR] bit and
+ see if we are getting preamble errors */
+ int interface = INTERFACE(priv->port);
+ int index = INDEX(priv->port);
+ cvmx_gmxx_rxx_int_reg_t gmxx_rxx_int_reg;
+ gmxx_rxx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, interface));
+ if (gmxx_rxx_int_reg.s.pcterr) {
+
+ /* We are getting preamble errors at 10Mbps.
+ Most likely the PHY is giving us packets
+ with mis aligned preambles. In order to get
+ these packets we need to disable preamble
+ checking and do it in software */
+ cvmx_gmxx_rxx_frm_ctl_t gmxx_rxx_frm_ctl;
+ cvmx_ipd_sub_port_fcs_t ipd_sub_port_fcs;
+
+ /* Disable preamble checking */
+ gmxx_rxx_frm_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface));
+ gmxx_rxx_frm_ctl.s.pre_chk = 0;
+ cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface), gmxx_rxx_frm_ctl.u64);
+
+ /* Disable FCS stripping */
+ ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS);
+ ipd_sub_port_fcs.s.port_bit &= 0xffffffffull ^ (1ull<<priv->port);
+ cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64);
+
+ /* Clear any error bits */
+ cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface), gmxx_rxx_int_reg.u64);
+ DEBUGPRINT("%s: Using 10Mbps with software preamble removal\n", if_name(ifp));
+ }
+ }
+ mtx_unlock_spin(&global_register_lock);
+ return;
+ }
+
+ /* If the 10Mbps preamble workaround is allowed we need to on
+ preamble checking, FCS stripping, and clear error bits on
+ every speed change. If errors occur during 10Mbps operation
+ the above code will change this stuff */
+ if (USE_10MBPS_PREAMBLE_WORKAROUND) {
+
+ cvmx_gmxx_rxx_frm_ctl_t gmxx_rxx_frm_ctl;
+ cvmx_ipd_sub_port_fcs_t ipd_sub_port_fcs;
+ cvmx_gmxx_rxx_int_reg_t gmxx_rxx_int_reg;
+ int interface = INTERFACE(priv->port);
+ int index = INDEX(priv->port);
+
+ /* Enable preamble checking */
+ gmxx_rxx_frm_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface));
+ gmxx_rxx_frm_ctl.s.pre_chk = 1;
+ cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface), gmxx_rxx_frm_ctl.u64);
+ /* Enable FCS stripping */
+ ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS);
+ ipd_sub_port_fcs.s.port_bit |= 1ull<<priv->port;
+ cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64);
+ /* Clear any error bits */
+ gmxx_rxx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, interface));
+ cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface), gmxx_rxx_int_reg.u64);
+ }
+
+ link_info = cvmx_helper_link_autoconf(priv->port);
+ priv->link_info = link_info.u64;
+ mtx_unlock_spin(&global_register_lock);
+
+ /* Tell Linux */
+ if (link_info.s.link_up) {
+
+ if_link_state_change(ifp, LINK_STATE_UP);
+ if (priv->queue != -1)
+ DEBUGPRINT("%s: %u Mbps %s duplex, port %2d, queue %2d\n",
+ if_name(ifp), link_info.s.speed,
+ (link_info.s.full_duplex) ? "Full" : "Half",
+ priv->port, priv->queue);
+ else
+ DEBUGPRINT("%s: %u Mbps %s duplex, port %2d, POW\n",
+ if_name(ifp), link_info.s.speed,
+ (link_info.s.full_duplex) ? "Full" : "Half",
+ priv->port);
+ } else {
+
+ if_link_state_change(ifp, LINK_STATE_DOWN);
+ DEBUGPRINT("%s: Link down\n", if_name(ifp));
+ }
+}
+
+
+static int cvm_oct_rgmii_rml_interrupt(void *dev_id)
+{
+ cvmx_npi_rsl_int_blocks_t rsl_int_blocks;
+ int index;
+ int return_status = FILTER_STRAY;
+
+ rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS);
+
+ /* Check and see if this interrupt was caused by the GMX0 block */
+ if (rsl_int_blocks.s.gmx0) {
+
+ int interface = 0;
+ /* Loop through every port of this interface */
+ for (index = 0; index < cvmx_helper_ports_on_interface(interface); index++) {
+
+ /* Read the GMX interrupt status bits */
+ cvmx_gmxx_rxx_int_reg_t gmx_rx_int_reg;
+ gmx_rx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, interface));
+ gmx_rx_int_reg.u64 &= cvmx_read_csr(CVMX_GMXX_RXX_INT_EN(index, interface));
+ /* Poll the port if inband status changed */
+ if (gmx_rx_int_reg.s.phy_dupx || gmx_rx_int_reg.s.phy_link || gmx_rx_int_reg.s.phy_spd) {
+
+ struct ifnet *ifp = cvm_oct_device[cvmx_helper_get_ipd_port(interface, index)];
+ if (ifp)
+ cvm_oct_rgmii_poll(ifp);
+ gmx_rx_int_reg.u64 = 0;
+ gmx_rx_int_reg.s.phy_dupx = 1;
+ gmx_rx_int_reg.s.phy_link = 1;
+ gmx_rx_int_reg.s.phy_spd = 1;
+ cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface), gmx_rx_int_reg.u64);
+ return_status = FILTER_HANDLED;
+ }
+ }
+ }
+
+ /* Check and see if this interrupt was caused by the GMX1 block */
+ if (rsl_int_blocks.s.gmx1) {
+
+ int interface = 1;
+ /* Loop through every port of this interface */
+ for (index = 0; index < cvmx_helper_ports_on_interface(interface); index++) {
+
+ /* Read the GMX interrupt status bits */
+ cvmx_gmxx_rxx_int_reg_t gmx_rx_int_reg;
+ gmx_rx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, interface));
+ gmx_rx_int_reg.u64 &= cvmx_read_csr(CVMX_GMXX_RXX_INT_EN(index, interface));
+ /* Poll the port if inband status changed */
+ if (gmx_rx_int_reg.s.phy_dupx || gmx_rx_int_reg.s.phy_link || gmx_rx_int_reg.s.phy_spd) {
+
+ struct ifnet *ifp = cvm_oct_device[cvmx_helper_get_ipd_port(interface, index)];
+ if (ifp)
+ cvm_oct_rgmii_poll(ifp);
+ gmx_rx_int_reg.u64 = 0;
+ gmx_rx_int_reg.s.phy_dupx = 1;
+ gmx_rx_int_reg.s.phy_link = 1;
+ gmx_rx_int_reg.s.phy_spd = 1;
+ cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface), gmx_rx_int_reg.u64);
+ return_status = FILTER_HANDLED;
+ }
+ }
+ }
+ return return_status;
+}
+
+
+static int cvm_oct_rgmii_open(struct ifnet *ifp)
+{
+ cvmx_gmxx_prtx_cfg_t gmx_cfg;
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+ int interface = INTERFACE(priv->port);
+ int index = INDEX(priv->port);
+ cvmx_helper_link_info_t link_info;
+
+ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
+ gmx_cfg.s.en = 1;
+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
+
+ if (!octeon_is_simulation()) {
+ link_info = cvmx_helper_link_get(priv->port);
+ if (!link_info.s.link_up)
+ if_link_state_change(ifp, LINK_STATE_DOWN);
+ else
+ if_link_state_change(ifp, LINK_STATE_UP);
+ }
+
+ return 0;
+}
+
+static int cvm_oct_rgmii_stop(struct ifnet *ifp)
+{
+ cvmx_gmxx_prtx_cfg_t gmx_cfg;
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+ int interface = INTERFACE(priv->port);
+ int index = INDEX(priv->port);
+
+ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
+ gmx_cfg.s.en = 0;
+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
+ return 0;
+}
+
+int cvm_oct_rgmii_init(struct ifnet *ifp)
+{
+ struct octebus_softc *sc;
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+ int error;
+ int rid;
+
+ cvm_oct_common_init(ifp);
+ priv->open = cvm_oct_rgmii_open;
+ priv->stop = cvm_oct_rgmii_stop;
+ priv->stop(ifp);
+
+ /* Due to GMX errata in CN3XXX series chips, it is necessary to take the
+ link down immediately whne the PHY changes state. In order to do this
+ we call the poll function every time the RGMII inband status changes.
+ This may cause problems if the PHY doesn't implement inband status
+ properly */
+ if (number_rgmii_ports == 0) {
+ sc = device_get_softc(device_get_parent(priv->dev));
+
+ rid = 0;
+ sc->sc_rgmii_irq = bus_alloc_resource(sc->sc_dev, SYS_RES_IRQ,
+ &rid, CVMX_IRQ_RML,
+ CVMX_IRQ_RML, 1,
+ RF_ACTIVE);
+ if (sc->sc_rgmii_irq == NULL) {
+ device_printf(sc->sc_dev, "could not allocate RGMII irq");
+ return ENXIO;
+ }
+
+ error = bus_setup_intr(sc->sc_dev, sc->sc_rgmii_irq,
+ INTR_TYPE_NET | INTR_MPSAFE,
+ cvm_oct_rgmii_rml_interrupt, NULL,
+ &number_rgmii_ports, NULL);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "could not setup RGMII irq");
+ return error;
+ }
+ }
+ number_rgmii_ports++;
+
+ /* Only true RGMII ports need to be polled. In GMII mode, port 0 is really
+ a RGMII port */
+ if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII) && (priv->port == 0)) ||
+ (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {
+
+ if (!octeon_is_simulation()) {
+
+ cvmx_gmxx_rxx_int_en_t gmx_rx_int_en;
+ int interface = INTERFACE(priv->port);
+ int index = INDEX(priv->port);
+
+ /* Enable interrupts on inband status changes for this port */
+ gmx_rx_int_en.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_EN(index, interface));
+ gmx_rx_int_en.s.phy_dupx = 1;
+ gmx_rx_int_en.s.phy_link = 1;
+ gmx_rx_int_en.s.phy_spd = 1;
+ cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface), gmx_rx_int_en.u64);
+ priv->poll = cvm_oct_rgmii_poll;
+ }
+ }
+
+ return 0;
+}
+
+void cvm_oct_rgmii_uninit(struct ifnet *ifp)
+{
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+ cvm_oct_common_uninit(ifp);
+
+ /* Only true RGMII ports need to be polled. In GMII mode, port 0 is really
+ a RGMII port */
+ if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII) && (priv->port == 0)) ||
+ (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {
+
+ if (!octeon_is_simulation()) {
+
+ cvmx_gmxx_rxx_int_en_t gmx_rx_int_en;
+ int interface = INTERFACE(priv->port);
+ int index = INDEX(priv->port);
+
+ /* Disable interrupts on inband status changes for this port */
+ gmx_rx_int_en.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_EN(index, interface));
+ gmx_rx_int_en.s.phy_dupx = 0;
+ gmx_rx_int_en.s.phy_link = 0;
+ gmx_rx_int_en.s.phy_spd = 0;
+ cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface), gmx_rx_int_en.u64);
+ }
+ }
+
+ /* Remove the interrupt handler when the last port is removed */
+ number_rgmii_ports--;
+ if (number_rgmii_ports == 0)
+ panic("%s: need to implement IRQ release.", __func__);
+}
+
diff --git a/sys/mips/cavium/octe/ethernet-rx.c b/sys/mips/cavium/octe/ethernet-rx.c
new file mode 100644
index 0000000..c6cc14c
--- /dev/null
+++ b/sys/mips/cavium/octe/ethernet-rx.c
@@ -0,0 +1,410 @@
+/*************************************************************************
+Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). All rights
+reserved.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export control laws, including the U.S. Export Administration Act and its associated regulations, and may be subject to export or import regulations in other countries.
+
+TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+
+*************************************************************************/
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/smp.h>
+#include <sys/taskqueue.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+
+#include "wrapper-cvmx-includes.h"
+#include "ethernet-headers.h"
+
+extern int pow_receive_group;
+extern struct ifnet *cvm_oct_device[];
+
+static struct task cvm_oct_task;
+static struct taskqueue *cvm_oct_taskq;
+
+/**
+ * Interrupt handler. The interrupt occurs whenever the POW
+ * transitions from 0->1 packets in our group.
+ *
+ * @param cpl
+ * @param dev_id
+ * @param regs
+ * @return
+ */
+int cvm_oct_do_interrupt(void *dev_id)
+{
+ /* Acknowledge the interrupt */
+ if (INTERRUPT_LIMIT)
+ cvmx_write_csr(CVMX_POW_WQ_INT, 1<<pow_receive_group);
+ else
+ cvmx_write_csr(CVMX_POW_WQ_INT, 0x10001<<pow_receive_group);
+ taskqueue_enqueue(cvm_oct_taskq, &cvm_oct_task);
+ return FILTER_HANDLED;
+}
+
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/**
+ * This is called when the kernel needs to manually poll the
+ * device. For Octeon, this is simply calling the interrupt
+ * handler. We actually poll all the devices, not just the
+ * one supplied.
+ *
+ * @param dev Device to poll. Unused
+ */
+void cvm_oct_poll_controller(struct ifnet *ifp)
+{
+ taskqueue_enqueue(cvm_oct_taskq, &cvm_oct_task);
+}
+#endif
+
+/**
+ * This is called on receive errors, and determines if the packet
+ * can be dropped early-on in cvm_oct_tasklet_rx().
+ *
+ * @param work Work queue entry pointing to the packet.
+ * @return Non-zero if the packet can be dropped, zero otherwise.
+ */
+static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work)
+{
+ if ((work->word2.snoip.err_code == 10) && (work->len <= 64)) {
+ /* Ignore length errors on min size packets. Some equipment
+ incorrectly pads packets to 64+4FCS instead of 60+4FCS.
+ Note these packets still get counted as frame errors. */
+ } else
+ if (USE_10MBPS_PREAMBLE_WORKAROUND && ((work->word2.snoip.err_code == 5) || (work->word2.snoip.err_code == 7))) {
+
+ /* We received a packet with either an alignment error or a
+ FCS error. This may be signalling that we are running
+ 10Mbps with GMXX_RXX_FRM_CTL[PRE_CHK} off. If this is the
+ case we need to parse the packet to determine if we can
+ remove a non spec preamble and generate a correct packet */
+ int interface = cvmx_helper_get_interface_num(work->ipprt);
+ int index = cvmx_helper_get_interface_index_num(work->ipprt);
+ cvmx_gmxx_rxx_frm_ctl_t gmxx_rxx_frm_ctl;
+ gmxx_rxx_frm_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface));
+ if (gmxx_rxx_frm_ctl.s.pre_chk == 0) {
+
+ uint8_t *ptr = cvmx_phys_to_ptr(work->packet_ptr.s.addr);
+ int i = 0;
+
+ while (i < work->len-1) {
+ if (*ptr != 0x55)
+ break;
+ ptr++;
+ i++;
+ }
+
+ if (*ptr == 0xd5) {
+ /*
+ DEBUGPRINT("Port %d received 0xd5 preamble\n", work->ipprt);
+ */
+ work->packet_ptr.s.addr += i+1;
+ work->len -= i+5;
+ } else
+ if ((*ptr & 0xf) == 0xd) {
+ /*
+ DEBUGPRINT("Port %d received 0x?d preamble\n", work->ipprt);
+ */
+ work->packet_ptr.s.addr += i;
+ work->len -= i+4;
+ for (i = 0; i < work->len; i++) {
+ *ptr = ((*ptr&0xf0)>>4) | ((*(ptr+1)&0xf)<<4);
+ ptr++;
+ }
+ } else {
+ DEBUGPRINT("Port %d unknown preamble, packet dropped\n", work->ipprt);
+ /*
+ cvmx_helper_dump_packet(work);
+ */
+ cvm_oct_free_work(work);
+ return 1;
+ }
+ }
+ } else {
+ DEBUGPRINT("Port %d receive error code %d, packet dropped\n", work->ipprt, work->word2.snoip.err_code);
+ cvm_oct_free_work(work);
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * Tasklet function that is scheduled on a core when an interrupt occurs.
+ *
+ * @param unused
+ */
+void cvm_oct_tasklet_rx(void *context, int pending)
+{
+ const int coreid = cvmx_get_core_num();
+ uint64_t old_group_mask;
+ uint64_t old_scratch;
+ int rx_count = 0;
+ int number_to_free;
+ int num_freed;
+ int packet_not_copied;
+
+ /* Prefetch cvm_oct_device since we know we need it soon */
+ CVMX_PREFETCH(cvm_oct_device, 0);
+
+ if (USE_ASYNC_IOBDMA) {
+ /* Save scratch in case userspace is using it */
+ CVMX_SYNCIOBDMA;
+ old_scratch = cvmx_scratch_read64(CVMX_SCR_SCRATCH);
+ }
+
+ /* Only allow work for our group (and preserve priorities) */
+ old_group_mask = cvmx_read_csr(CVMX_POW_PP_GRP_MSKX(coreid));
+ cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(coreid),
+ (old_group_mask & ~0xFFFFull) | 1<<pow_receive_group);
+
+ if (USE_ASYNC_IOBDMA)
+ cvmx_pow_work_request_async(CVMX_SCR_SCRATCH, CVMX_POW_NO_WAIT);
+
+ while (1) {
+ struct mbuf *m = NULL;
+ int mbuf_in_hw;
+ cvmx_wqe_t *work;
+
+ if (USE_ASYNC_IOBDMA) {
+ work = cvmx_pow_work_response_async(CVMX_SCR_SCRATCH);
+ } else {
+ if ((INTERRUPT_LIMIT == 0) || (rx_count < MAX_RX_PACKETS))
+ work = cvmx_pow_work_request_sync(CVMX_POW_NO_WAIT);
+ else
+ work = NULL;
+ }
+ CVMX_PREFETCH(work, 0);
+ if (work == NULL)
+ break;
+
+ /* Limit each core to processing MAX_RX_PACKETS packets without a break.
+ This way the RX can't starve the TX task. */
+ if (USE_ASYNC_IOBDMA) {
+
+ if ((INTERRUPT_LIMIT == 0) || (rx_count < MAX_RX_PACKETS))
+ cvmx_pow_work_request_async_nocheck(CVMX_SCR_SCRATCH, CVMX_POW_NO_WAIT);
+ else {
+ cvmx_scratch_write64(CVMX_SCR_SCRATCH, 0x8000000000000000ull);
+ cvmx_pow_tag_sw_null_nocheck();
+ }
+ }
+
+ mbuf_in_hw = USE_MBUFS_IN_HW && work->word2.s.bufs == 1;
+ if ((mbuf_in_hw)) {
+ m = *(struct mbuf **)(cvm_oct_get_buffer_ptr(work->packet_ptr) - sizeof(void *));
+ CVMX_PREFETCH(m, offsetof(struct mbuf, m_data));
+ CVMX_PREFETCH(m, offsetof(struct mbuf, m_pkthdr));
+ }
+ CVMX_PREFETCH(cvm_oct_device[work->ipprt], 0);
+ //CVMX_PREFETCH(m, 0);
+
+
+ rx_count++;
+ /* Immediately throw away all packets with receive errors */
+ if ((work->word2.snoip.rcv_error)) {
+ if (cvm_oct_check_rcv_error(work))
+ continue;
+ }
+
+ /* We can only use the zero copy path if mbufs are in the FPA pool
+ and the packet fits in a single buffer */
+ if ((mbuf_in_hw)) {
+ CVMX_PREFETCH(m->m_data, 0);
+
+ m->m_pkthdr.len = m->m_len = work->len;
+
+ packet_not_copied = 1;
+
+ /*
+ * Adjust the data pointer based on the offset
+ * of the packet within the buffer.
+ */
+ m->m_data += (work->packet_ptr.s.back << 7) + (work->packet_ptr.s.addr & 0x7f);
+ } else {
+
+ /* We have to copy the packet. First allocate an
+ mbuf for it */
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (m == NULL) {
+ DEBUGPRINT("Port %d failed to allocate mbuf, packet dropped\n", work->ipprt);
+ cvm_oct_free_work(work);
+ continue;
+ }
+
+ /* Check if we've received a packet that was entirely
+ stored in the work entry. This is untested */
+ if ((work->word2.s.bufs == 0)) {
+ uint8_t *ptr = work->packet_data;
+
+ if (cvmx_likely(!work->word2.s.not_IP)) {
+ /* The beginning of the packet moves
+ for IP packets */
+ if (work->word2.s.is_v6)
+ ptr += 2;
+ else
+ ptr += 6;
+ }
+ panic("%s: not yet implemented; copy in small packet.", __func__);
+ /* No packet buffers to free */
+ } else {
+ int segments = work->word2.s.bufs;
+ cvmx_buf_ptr_t segment_ptr = work->packet_ptr;
+ int len = work->len;
+
+ while (segments--) {
+ cvmx_buf_ptr_t next_ptr = *(cvmx_buf_ptr_t *)cvmx_phys_to_ptr(segment_ptr.s.addr-8);
+ /* Octeon Errata PKI-100: The segment
+ size is wrong. Until it is fixed,
+ calculate the segment size based on
+ the packet pool buffer size. When
+ it is fixed, the following line
+ should be replaced with this one:
+ int segment_size = segment_ptr.s.size; */
+ int segment_size = CVMX_FPA_PACKET_POOL_SIZE - (segment_ptr.s.addr - (((segment_ptr.s.addr >> 7) - segment_ptr.s.back) << 7));
+ /* Don't copy more than what is left
+ in the packet */
+ if (segment_size > len)
+ segment_size = len;
+ /* Copy the data into the packet */
+ panic("%s: not yet implemented; copy in packet segments.", __func__);
+#if 0
+ memcpy(m_put(m, segment_size), cvmx_phys_to_ptr(segment_ptr.s.addr), segment_size);
+#endif
+ /* Reduce the amount of bytes left
+ to copy */
+ len -= segment_size;
+ segment_ptr = next_ptr;
+ }
+ }
+ packet_not_copied = 0;
+ }
+
+ if (((work->ipprt < TOTAL_NUMBER_OF_PORTS) &&
+ cvm_oct_device[work->ipprt])) {
+ struct ifnet *ifp = cvm_oct_device[work->ipprt];
+
+ /* Only accept packets for devices
+ that are currently up */
+ if ((ifp->if_flags & IFF_UP)) {
+ m->m_pkthdr.rcvif = ifp;
+
+ if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) {
+ if ((work->word2.s.not_IP || work->word2.s.IP_exc || work->word2.s.L4_error))
+ m->m_pkthdr.csum_flags = 0; /* XXX */
+ else {
+ m->m_pkthdr.csum_flags = CSUM_IP_CHECKED | CSUM_IP_VALID | CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
+ m->m_pkthdr.csum_data = 0xffff;
+ }
+ } else {
+ m->m_pkthdr.csum_flags = 0; /* XXX */
+ }
+
+ ifp->if_ipackets++;
+
+ (*ifp->if_input)(ifp, m);
+ } else {
+ /* Drop any packet received for a device that isn't up */
+ /*
+ DEBUGPRINT("%s: Device not up, packet dropped\n",
+ if_name(ifp));
+ */
+ m_freem(m);
+ }
+ } else {
+ /* Drop any packet received for a device that
+ doesn't exist */
+ DEBUGPRINT("Port %d not controlled by Linux, packet dropped\n", work->ipprt);
+ m_freem(m);
+ }
+
+ /* Check to see if the mbuf and work share
+ the same packet buffer */
+ if (USE_MBUFS_IN_HW && (packet_not_copied)) {
+ /* This buffer needs to be replaced, increment
+ the number of buffers we need to free by one */
+ cvmx_fau_atomic_add32(
+ FAU_NUM_PACKET_BUFFERS_TO_FREE, 1);
+
+ cvmx_fpa_free(work, CVMX_FPA_WQE_POOL,
+ DONT_WRITEBACK(1));
+ } else
+ cvm_oct_free_work(work);
+ }
+
+ /* Restore the original POW group mask */
+ cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(coreid), old_group_mask);
+ if (USE_ASYNC_IOBDMA) {
+ /* Restore the scratch area */
+ cvmx_scratch_write64(CVMX_SCR_SCRATCH, old_scratch);
+ }
+
+ if (USE_MBUFS_IN_HW) {
+ /* Refill the packet buffer pool */
+ number_to_free =
+ cvmx_fau_fetch_and_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, 0);
+
+ if (number_to_free > 0) {
+ cvmx_fau_atomic_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE,
+ -number_to_free);
+ num_freed =
+ cvm_oct_mem_fill_fpa(CVMX_FPA_PACKET_POOL,
+ CVMX_FPA_PACKET_POOL_SIZE,
+ number_to_free);
+ if (num_freed != number_to_free) {
+ cvmx_fau_atomic_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE,
+ number_to_free - num_freed);
+ }
+ }
+ }
+}
+
+
+
+void cvm_oct_rx_initialize(void)
+{
+ TASK_INIT(&cvm_oct_task, 0, cvm_oct_tasklet_rx, NULL);
+
+ cvm_oct_taskq = taskqueue_create_fast("oct_rx", M_NOWAIT,
+ taskqueue_thread_enqueue,
+ &cvm_oct_taskq);
+ taskqueue_start_threads(&cvm_oct_taskq, min(mp_ncpus, MAXCPU),
+ PI_NET, "octe taskq");
+}
+
+void cvm_oct_rx_shutdown(void)
+{
+ panic("%s: not yet implemented.", __func__);
+}
+
diff --git a/sys/mips/cavium/octe/ethernet-rx.h b/sys/mips/cavium/octe/ethernet-rx.h
new file mode 100644
index 0000000..735d087
--- /dev/null
+++ b/sys/mips/cavium/octe/ethernet-rx.h
@@ -0,0 +1,37 @@
+/*************************************************************************
+Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). All rights
+reserved.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export control laws, including the U.S. Export Administration Act and its associated regulations, and may be subject to export or import regulations in other countries.
+
+TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+
+*************************************************************************/
+/* $FreeBSD$ */
+
+int cvm_oct_do_interrupt(void *dev_id);
+void cvm_oct_poll_controller(struct ifnet *ifp);
+void cvm_oct_tasklet_rx(void *context, int pending);
+
+void cvm_oct_rx_initialize(void);
+void cvm_oct_rx_shutdown(void);
+
diff --git a/sys/mips/cavium/octe/ethernet-sgmii.c b/sys/mips/cavium/octe/ethernet-sgmii.c
new file mode 100644
index 0000000..69549a1
--- /dev/null
+++ b/sys/mips/cavium/octe/ethernet-sgmii.c
@@ -0,0 +1,135 @@
+/*************************************************************************
+Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). All rights
+reserved.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export control laws, including the U.S. Export Administration Act and its associated regulations, and may be subject to export or import regulations in other countries.
+
+TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+
+*************************************************************************/
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+
+#include "wrapper-cvmx-includes.h"
+#include "ethernet-headers.h"
+
+extern int octeon_is_simulation(void);
+
+static int cvm_oct_sgmii_open(struct ifnet *ifp)
+{
+ cvmx_gmxx_prtx_cfg_t gmx_cfg;
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+ int interface = INTERFACE(priv->port);
+ int index = INDEX(priv->port);
+ cvmx_helper_link_info_t link_info;
+
+ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
+ gmx_cfg.s.en = 1;
+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
+
+ if (!octeon_is_simulation()) {
+ link_info = cvmx_helper_link_get(priv->port);
+ if (!link_info.s.link_up)
+ if_link_state_change(ifp, LINK_STATE_DOWN);
+ else
+ if_link_state_change(ifp, LINK_STATE_UP);
+ }
+
+ return 0;
+}
+
+static int cvm_oct_sgmii_stop(struct ifnet *ifp)
+{
+ cvmx_gmxx_prtx_cfg_t gmx_cfg;
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+ int interface = INTERFACE(priv->port);
+ int index = INDEX(priv->port);
+
+ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
+ gmx_cfg.s.en = 0;
+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
+ return 0;
+}
+
+static void cvm_oct_sgmii_poll(struct ifnet *ifp)
+{
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+ cvmx_helper_link_info_t link_info;
+
+ link_info = cvmx_helper_link_get(priv->port);
+ if (link_info.u64 == priv->link_info)
+ return;
+
+ link_info = cvmx_helper_link_autoconf(priv->port);
+ priv->link_info = link_info.u64;
+
+ /* Tell Linux */
+ if (link_info.s.link_up) {
+
+ if_link_state_change(ifp, LINK_STATE_UP);
+ if (priv->queue != -1)
+ DEBUGPRINT("%s: %u Mbps %s duplex, port %2d, queue %2d\n",
+ if_name(ifp), link_info.s.speed,
+ (link_info.s.full_duplex) ? "Full" : "Half",
+ priv->port, priv->queue);
+ else
+ DEBUGPRINT("%s: %u Mbps %s duplex, port %2d, POW\n",
+ if_name(ifp), link_info.s.speed,
+ (link_info.s.full_duplex) ? "Full" : "Half",
+ priv->port);
+ } else {
+ if_link_state_change(ifp, LINK_STATE_DOWN);
+ DEBUGPRINT("%s: Link down\n", if_name(ifp));
+ }
+}
+
+int cvm_oct_sgmii_init(struct ifnet *ifp)
+{
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+ cvm_oct_common_init(ifp);
+ priv->open = cvm_oct_sgmii_open;
+ priv->stop = cvm_oct_sgmii_stop;
+ priv->stop(ifp);
+ if (!octeon_is_simulation())
+ priv->poll = cvm_oct_sgmii_poll;
+
+ /* FIXME: Need autoneg logic */
+ return 0;
+}
+
+void cvm_oct_sgmii_uninit(struct ifnet *ifp)
+{
+ cvm_oct_common_uninit(ifp);
+}
+
diff --git a/sys/mips/cavium/octe/ethernet-spi.c b/sys/mips/cavium/octe/ethernet-spi.c
new file mode 100644
index 0000000..100f642
--- /dev/null
+++ b/sys/mips/cavium/octe/ethernet-spi.c
@@ -0,0 +1,309 @@
+/*************************************************************************
+Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). All rights
+reserved.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export control laws, including the U.S. Export Administration Act and its associated regulations, and may be subject to export or import regulations in other countries.
+
+TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+
+*************************************************************************/
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/rman.h>
+#include <sys/socket.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+
+#include "wrapper-cvmx-includes.h"
+#include "ethernet-headers.h"
+
+#include "octebusvar.h"
+
+static int number_spi_ports;
+static int need_retrain[2] = {0, 0};
+
+static int cvm_oct_spi_rml_interrupt(void *dev_id)
+{
+ int return_status = FILTER_STRAY;
+ cvmx_npi_rsl_int_blocks_t rsl_int_blocks;
+
+ /* Check and see if this interrupt was caused by the GMX block */
+ rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS);
+ if (rsl_int_blocks.s.spx1) { /* 19 - SPX1_INT_REG & STX1_INT_REG */
+
+ cvmx_spxx_int_reg_t spx_int_reg;
+ cvmx_stxx_int_reg_t stx_int_reg;
+
+ spx_int_reg.u64 = cvmx_read_csr(CVMX_SPXX_INT_REG(1));
+ cvmx_write_csr(CVMX_SPXX_INT_REG(1), spx_int_reg.u64);
+ if (!need_retrain[1]) {
+
+ spx_int_reg.u64 &= cvmx_read_csr(CVMX_SPXX_INT_MSK(1));
+ if (spx_int_reg.s.spf)
+ printf("SPI1: SRX Spi4 interface down\n");
+ if (spx_int_reg.s.calerr)
+ printf("SPI1: SRX Spi4 Calendar table parity error\n");
+ if (spx_int_reg.s.syncerr)
+ printf("SPI1: SRX Consecutive Spi4 DIP4 errors have exceeded SPX_ERR_CTL[ERRCNT]\n");
+ if (spx_int_reg.s.diperr)
+ printf("SPI1: SRX Spi4 DIP4 error\n");
+ if (spx_int_reg.s.tpaovr)
+ printf("SPI1: SRX Selected port has hit TPA overflow\n");
+ if (spx_int_reg.s.rsverr)
+ printf("SPI1: SRX Spi4 reserved control word detected\n");
+ if (spx_int_reg.s.drwnng)
+ printf("SPI1: SRX Spi4 receive FIFO drowning/overflow\n");
+ if (spx_int_reg.s.clserr)
+ printf("SPI1: SRX Spi4 packet closed on non-16B alignment without EOP\n");
+ if (spx_int_reg.s.spiovr)
+ printf("SPI1: SRX Spi4 async FIFO overflow\n");
+ if (spx_int_reg.s.abnorm)
+ printf("SPI1: SRX Abnormal packet termination (ERR bit)\n");
+ if (spx_int_reg.s.prtnxa)
+ printf("SPI1: SRX Port out of range\n");
+ }
+
+ stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(1));
+ cvmx_write_csr(CVMX_STXX_INT_REG(1), stx_int_reg.u64);
+ if (!need_retrain[1]) {
+
+ stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(1));
+ if (stx_int_reg.s.syncerr)
+ printf("SPI1: STX Interface encountered a fatal error\n");
+ if (stx_int_reg.s.frmerr)
+ printf("SPI1: STX FRMCNT has exceeded STX_DIP_CNT[MAXFRM]\n");
+ if (stx_int_reg.s.unxfrm)
+ printf("SPI1: STX Unexpected framing sequence\n");
+ if (stx_int_reg.s.nosync)
+ printf("SPI1: STX ERRCNT has exceeded STX_DIP_CNT[MAXDIP]\n");
+ if (stx_int_reg.s.diperr)
+ printf("SPI1: STX DIP2 error on the Spi4 Status channel\n");
+ if (stx_int_reg.s.datovr)
+ printf("SPI1: STX Spi4 FIFO overflow error\n");
+ if (stx_int_reg.s.ovrbst)
+ printf("SPI1: STX Transmit packet burst too big\n");
+ if (stx_int_reg.s.calpar1)
+ printf("SPI1: STX Calendar Table Parity Error Bank1\n");
+ if (stx_int_reg.s.calpar0)
+ printf("SPI1: STX Calendar Table Parity Error Bank0\n");
+ }
+
+ cvmx_write_csr(CVMX_SPXX_INT_MSK(1), 0);
+ cvmx_write_csr(CVMX_STXX_INT_MSK(1), 0);
+ need_retrain[1] = 1;
+ return_status = FILTER_HANDLED;
+ }
+
+ if (rsl_int_blocks.s.spx0) { /* 18 - SPX0_INT_REG & STX0_INT_REG */
+ cvmx_spxx_int_reg_t spx_int_reg;
+ cvmx_stxx_int_reg_t stx_int_reg;
+
+ spx_int_reg.u64 = cvmx_read_csr(CVMX_SPXX_INT_REG(0));
+ cvmx_write_csr(CVMX_SPXX_INT_REG(0), spx_int_reg.u64);
+ if (!need_retrain[0]) {
+
+ spx_int_reg.u64 &= cvmx_read_csr(CVMX_SPXX_INT_MSK(0));
+ if (spx_int_reg.s.spf)
+ printf("SPI0: SRX Spi4 interface down\n");
+ if (spx_int_reg.s.calerr)
+ printf("SPI0: SRX Spi4 Calendar table parity error\n");
+ if (spx_int_reg.s.syncerr)
+ printf("SPI0: SRX Consecutive Spi4 DIP4 errors have exceeded SPX_ERR_CTL[ERRCNT]\n");
+ if (spx_int_reg.s.diperr)
+ printf("SPI0: SRX Spi4 DIP4 error\n");
+ if (spx_int_reg.s.tpaovr)
+ printf("SPI0: SRX Selected port has hit TPA overflow\n");
+ if (spx_int_reg.s.rsverr)
+ printf("SPI0: SRX Spi4 reserved control word detected\n");
+ if (spx_int_reg.s.drwnng)
+ printf("SPI0: SRX Spi4 receive FIFO drowning/overflow\n");
+ if (spx_int_reg.s.clserr)
+ printf("SPI0: SRX Spi4 packet closed on non-16B alignment without EOP\n");
+ if (spx_int_reg.s.spiovr)
+ printf("SPI0: SRX Spi4 async FIFO overflow\n");
+ if (spx_int_reg.s.abnorm)
+ printf("SPI0: SRX Abnormal packet termination (ERR bit)\n");
+ if (spx_int_reg.s.prtnxa)
+ printf("SPI0: SRX Port out of range\n");
+ }
+
+ stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(0));
+ cvmx_write_csr(CVMX_STXX_INT_REG(0), stx_int_reg.u64);
+ if (!need_retrain[0]) {
+
+ stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(0));
+ if (stx_int_reg.s.syncerr)
+ printf("SPI0: STX Interface encountered a fatal error\n");
+ if (stx_int_reg.s.frmerr)
+ printf("SPI0: STX FRMCNT has exceeded STX_DIP_CNT[MAXFRM]\n");
+ if (stx_int_reg.s.unxfrm)
+ printf("SPI0: STX Unexpected framing sequence\n");
+ if (stx_int_reg.s.nosync)
+ printf("SPI0: STX ERRCNT has exceeded STX_DIP_CNT[MAXDIP]\n");
+ if (stx_int_reg.s.diperr)
+ printf("SPI0: STX DIP2 error on the Spi4 Status channel\n");
+ if (stx_int_reg.s.datovr)
+ printf("SPI0: STX Spi4 FIFO overflow error\n");
+ if (stx_int_reg.s.ovrbst)
+ printf("SPI0: STX Transmit packet burst too big\n");
+ if (stx_int_reg.s.calpar1)
+ printf("SPI0: STX Calendar Table Parity Error Bank1\n");
+ if (stx_int_reg.s.calpar0)
+ printf("SPI0: STX Calendar Table Parity Error Bank0\n");
+ }
+
+ cvmx_write_csr(CVMX_SPXX_INT_MSK(0), 0);
+ cvmx_write_csr(CVMX_STXX_INT_MSK(0), 0);
+ need_retrain[0] = 1;
+ return_status = FILTER_HANDLED;
+ }
+
+ return return_status;
+}
+
+static void cvm_oct_spi_enable_error_reporting(int interface)
+{
+ cvmx_spxx_int_msk_t spxx_int_msk;
+ cvmx_stxx_int_msk_t stxx_int_msk;
+
+ spxx_int_msk.u64 = cvmx_read_csr(CVMX_SPXX_INT_MSK(interface));
+ spxx_int_msk.s.calerr = 1;
+ spxx_int_msk.s.syncerr = 1;
+ spxx_int_msk.s.diperr = 1;
+ spxx_int_msk.s.tpaovr = 1;
+ spxx_int_msk.s.rsverr = 1;
+ spxx_int_msk.s.drwnng = 1;
+ spxx_int_msk.s.clserr = 1;
+ spxx_int_msk.s.spiovr = 1;
+ spxx_int_msk.s.abnorm = 1;
+ spxx_int_msk.s.prtnxa = 1;
+ cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), spxx_int_msk.u64);
+
+ stxx_int_msk.u64 = cvmx_read_csr(CVMX_STXX_INT_MSK(interface));
+ stxx_int_msk.s.frmerr = 1;
+ stxx_int_msk.s.unxfrm = 1;
+ stxx_int_msk.s.nosync = 1;
+ stxx_int_msk.s.diperr = 1;
+ stxx_int_msk.s.datovr = 1;
+ stxx_int_msk.s.ovrbst = 1;
+ stxx_int_msk.s.calpar1 = 1;
+ stxx_int_msk.s.calpar0 = 1;
+ cvmx_write_csr(CVMX_STXX_INT_MSK(interface), stxx_int_msk.u64);
+}
+
+static void cvm_oct_spi_poll(struct ifnet *ifp)
+{
+ static int spi4000_port;
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+ int interface;
+
+ for (interface = 0; interface < 2; interface++) {
+
+ if ((priv->port == interface*16) && need_retrain[interface]) {
+
+ if (cvmx_spi_restart_interface(interface, CVMX_SPI_MODE_DUPLEX, 10) == 0) {
+ need_retrain[interface] = 0;
+ cvm_oct_spi_enable_error_reporting(interface);
+ }
+ }
+
+ /* The SPI4000 TWSI interface is very slow. In order not to
+ bring the system to a crawl, we only poll a single port
+ every second. This means negotiation speed changes
+ take up to 10 seconds, but at least we don't waste
+ absurd amounts of time waiting for TWSI */
+ if (priv->port == spi4000_port) {
+ /* This function does nothing if it is called on an
+ interface without a SPI4000 */
+ cvmx_spi4000_check_speed(interface, priv->port);
+ /* Normal ordering increments. By decrementing
+ we only match once per iteration */
+ spi4000_port--;
+ if (spi4000_port < 0)
+ spi4000_port = 10;
+ }
+ }
+}
+
+
+int cvm_oct_spi_init(struct ifnet *ifp)
+{
+ struct octebus_softc *sc;
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+ int error;
+ int rid;
+
+ if (number_spi_ports == 0) {
+ sc = device_get_softc(device_get_parent(priv->dev));
+
+ rid = 0;
+ sc->sc_spi_irq = bus_alloc_resource(sc->sc_dev, SYS_RES_IRQ,
+ &rid, CVMX_IRQ_RML,
+ CVMX_IRQ_RML, 1,
+ RF_ACTIVE);
+ if (sc->sc_spi_irq == NULL) {
+ device_printf(sc->sc_dev, "could not allocate SPI irq");
+ return ENXIO;
+ }
+
+ error = bus_setup_intr(sc->sc_dev, sc->sc_spi_irq,
+ INTR_TYPE_NET | INTR_MPSAFE,
+ cvm_oct_spi_rml_interrupt, NULL,
+ &number_spi_ports, NULL);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "could not setup SPI irq");
+ return error;
+ }
+ }
+ number_spi_ports++;
+
+ if ((priv->port == 0) || (priv->port == 16)) {
+ cvm_oct_spi_enable_error_reporting(INTERFACE(priv->port));
+ priv->poll = cvm_oct_spi_poll;
+ }
+ cvm_oct_common_init(ifp);
+ return 0;
+}
+
+void cvm_oct_spi_uninit(struct ifnet *ifp)
+{
+ int interface;
+
+ cvm_oct_common_uninit(ifp);
+ number_spi_ports--;
+ if (number_spi_ports == 0) {
+ for (interface = 0; interface < 2; interface++) {
+ cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), 0);
+ cvmx_write_csr(CVMX_STXX_INT_MSK(interface), 0);
+ }
+ panic("%s: IRQ release not yet implemented.", __func__);
+ }
+}
diff --git a/sys/mips/cavium/octe/ethernet-tx.c b/sys/mips/cavium/octe/ethernet-tx.c
new file mode 100644
index 0000000..fc4e273
--- /dev/null
+++ b/sys/mips/cavium/octe/ethernet-tx.c
@@ -0,0 +1,398 @@
+/*************************************************************************
+Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). All rights
+reserved.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export control laws, including the U.S. Export Administration Act and its associated regulations, and may be subject to export or import regulations in other countries.
+
+TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+
+*************************************************************************/
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+
+#include "wrapper-cvmx-includes.h"
+#include "ethernet-headers.h"
+
+/* You can define GET_MBUF_QOS() to override how the mbuf output function
+ determines which output queue is used. The default implementation
+ always uses the base queue for the port. If, for example, you wanted
+ to use the m->priority fieid, define GET_MBUF_QOS as:
+ #define GET_MBUF_QOS(m) ((m)->priority) */
+#ifndef GET_MBUF_QOS
+ #define GET_MBUF_QOS(m) 0
+#endif
+
+extern int pow_send_group;
+
+
+/**
+ * Packet transmit
+ *
+ * @param m Packet to send
+ * @param dev Device info structure
+ * @return Always returns zero
+ */
+int cvm_oct_xmit(struct mbuf *m, struct ifnet *ifp)
+{
+ cvmx_pko_command_word0_t pko_command;
+ cvmx_buf_ptr_t hw_buffer;
+ uint64_t old_scratch;
+ uint64_t old_scratch2;
+ int dropped;
+ int qos;
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+ int32_t in_use;
+ int32_t buffers_to_free;
+ cvmx_wqe_t *work;
+
+ /* Prefetch the private data structure.
+ It is larger that one cache line */
+ CVMX_PREFETCH(priv, 0);
+
+ /* Start off assuming no drop */
+ dropped = 0;
+
+ /* The check on CVMX_PKO_QUEUES_PER_PORT_* is designed to completely
+ remove "qos" in the event neither interface supports multiple queues
+ per port */
+ if ((CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 > 1) ||
+ (CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 > 1)) {
+ qos = GET_MBUF_QOS(m);
+ if (qos <= 0)
+ qos = 0;
+ else if (qos >= cvmx_pko_get_num_queues(priv->port))
+ qos = 0;
+ } else
+ qos = 0;
+
+ if (USE_ASYNC_IOBDMA) {
+ /* Save scratch in case userspace is using it */
+ CVMX_SYNCIOBDMA;
+ old_scratch = cvmx_scratch_read64(CVMX_SCR_SCRATCH);
+ old_scratch2 = cvmx_scratch_read64(CVMX_SCR_SCRATCH+8);
+
+ /* Assume we're going to be able t osend this packet. Fetch and increment
+ the number of pending packets for output */
+ cvmx_fau_async_fetch_and_add32(CVMX_SCR_SCRATCH+8, FAU_NUM_PACKET_BUFFERS_TO_FREE, 0);
+ cvmx_fau_async_fetch_and_add32(CVMX_SCR_SCRATCH, priv->fau+qos*4, 1);
+ }
+
+ /* The CN3XXX series of parts has an errata (GMX-401) which causes the
+ GMX block to hang if a collision occurs towards the end of a
+ <68 byte packet. As a workaround for this, we pad packets to be
+ 68 bytes whenever we are in half duplex mode. We don't handle
+ the case of having a small packet but no room to add the padding.
+ The kernel should always give us at least a cache line */
+ if (__predict_false(m->m_pkthdr.len < 64) && OCTEON_IS_MODEL(OCTEON_CN3XXX)) {
+ cvmx_gmxx_prtx_cfg_t gmx_prt_cfg;
+ int interface = INTERFACE(priv->port);
+ int index = INDEX(priv->port);
+
+ if (interface < 2) {
+ /* We only need to pad packet in half duplex mode */
+ gmx_prt_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
+ if (gmx_prt_cfg.s.duplex == 0) {
+ static uint8_t pad[64];
+
+ if (!m_append(m, sizeof pad - m->m_pkthdr.len, pad))
+ printf("%s: unable to padd small packet.", __func__);
+ }
+ }
+ }
+
+ /*
+ * If the packet is not fragmented.
+ */
+ if (m->m_pkthdr.len == m->m_len) {
+ /* Build the PKO buffer pointer */
+ hw_buffer.u64 = 0;
+ hw_buffer.s.addr = cvmx_ptr_to_phys(m->m_data);
+ hw_buffer.s.pool = 0;
+ hw_buffer.s.size = m->m_len;
+
+ /* Build the PKO command */
+ pko_command.u64 = 0;
+ pko_command.s.segs = 1;
+
+ work = NULL;
+ } else {
+ struct mbuf *n;
+ unsigned segs;
+ uint64_t *gp;
+
+ /*
+ * The packet is fragmented, we need to send a list of segments
+ * in memory we borrow from the WQE pool.
+ */
+ work = cvmx_fpa_alloc(CVMX_FPA_WQE_POOL);
+ gp = (uint64_t *)work;
+
+ segs = 0;
+ for (n = m; n != NULL; n = n->m_next) {
+ if (segs == CVMX_FPA_WQE_POOL_SIZE / sizeof (uint64_t))
+ panic("%s: too many segments in packet; call m_collapse().", __func__);
+
+ /* Build the PKO buffer pointer */
+ hw_buffer.u64 = 0;
+ hw_buffer.s.addr = cvmx_ptr_to_phys(n->m_data);
+ hw_buffer.s.pool = 0;
+ hw_buffer.s.size = n->m_len;
+
+ *gp++ = hw_buffer.u64;
+ segs++;
+ }
+
+ /* Build the PKO buffer gather list pointer */
+ hw_buffer.u64 = 0;
+ hw_buffer.s.addr = cvmx_ptr_to_phys(work);
+ hw_buffer.s.pool = CVMX_FPA_WQE_POOL;
+ hw_buffer.s.size = segs;
+
+ /* Build the PKO command */
+ pko_command.u64 = 0;
+ pko_command.s.segs = segs;
+ pko_command.s.gather = 1;
+ }
+
+ /* Finish building the PKO command */
+ pko_command.s.n2 = 1; /* Don't pollute L2 with the outgoing packet */
+ pko_command.s.dontfree = 1;
+ pko_command.s.reg0 = priv->fau+qos*4;
+ pko_command.s.reg0 = priv->fau+qos*4;
+ pko_command.s.total_bytes = m->m_pkthdr.len;
+ pko_command.s.size0 = CVMX_FAU_OP_SIZE_32;
+ pko_command.s.subone0 = 1;
+
+ /* Check if we can use the hardware checksumming */
+ if (USE_HW_TCPUDP_CHECKSUM &&
+ (m->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP)) != 0) {
+ /* Use hardware checksum calc */
+ pko_command.s.ipoffp1 = ETHER_HDR_LEN + 1;
+ }
+
+ IF_LOCK(&priv->tx_free_queue[qos]);
+ if (USE_ASYNC_IOBDMA) {
+ /* Get the number of mbufs in use by the hardware */
+ CVMX_SYNCIOBDMA;
+ in_use = cvmx_scratch_read64(CVMX_SCR_SCRATCH);
+ buffers_to_free = cvmx_scratch_read64(CVMX_SCR_SCRATCH+8);
+ } else {
+ /* Get the number of mbufs in use by the hardware */
+ in_use = cvmx_fau_fetch_and_add32(priv->fau+qos*4, 1);
+ buffers_to_free = cvmx_fau_fetch_and_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, 0);
+ }
+
+ cvmx_pko_send_packet_prepare(priv->port, priv->queue + qos, CVMX_PKO_LOCK_CMD_QUEUE);
+
+ /* Drop this packet if we have too many already queued to the HW */
+ if (_IF_QFULL(&priv->tx_free_queue[qos])) {
+ dropped = 1;
+ }
+ /* Send the packet to the output queue */
+ else
+ if (__predict_false(cvmx_pko_send_packet_finish(priv->port, priv->queue + qos, pko_command, hw_buffer, CVMX_PKO_LOCK_CMD_QUEUE))) {
+ DEBUGPRINT("%s: Failed to send the packet\n", if_name(ifp));
+ dropped = 1;
+ }
+
+ if (USE_ASYNC_IOBDMA) {
+ /* Restore the scratch area */
+ cvmx_scratch_write64(CVMX_SCR_SCRATCH, old_scratch);
+ cvmx_scratch_write64(CVMX_SCR_SCRATCH+8, old_scratch2);
+ }
+
+ if (__predict_false(dropped)) {
+ m_freem(m);
+ cvmx_fau_atomic_add32(priv->fau+qos*4, -1);
+ ifp->if_oerrors++;
+ } else {
+ /* Put this packet on the queue to be freed later */
+ _IF_ENQUEUE(&priv->tx_free_queue[qos], m);
+ }
+ if (work != NULL)
+ cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, DONT_WRITEBACK(1));
+
+ /* Free mbufs not in use by the hardware */
+ if (_IF_QLEN(&priv->tx_free_queue[qos]) > in_use) {
+ while (_IF_QLEN(&priv->tx_free_queue[qos]) > in_use) {
+ _IF_DEQUEUE(&priv->tx_free_queue[qos], m);
+ m_freem(m);
+ }
+ }
+ IF_UNLOCK(&priv->tx_free_queue[qos]);
+
+ return dropped;
+}
+
+
+/**
+ * Packet transmit to the POW
+ *
+ * @param m Packet to send
+ * @param dev Device info structure
+ * @return Always returns zero
+ */
+int cvm_oct_xmit_pow(struct mbuf *m, struct ifnet *ifp)
+{
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+ char *packet_buffer;
+ char *copy_location;
+
+ /* Get a work queue entry */
+ cvmx_wqe_t *work = cvmx_fpa_alloc(CVMX_FPA_WQE_POOL);
+ if (__predict_false(work == NULL)) {
+ DEBUGPRINT("%s: Failed to allocate a work queue entry\n", if_name(ifp));
+ ifp->if_oerrors++;
+ m_freem(m);
+ return 0;
+ }
+
+ /* Get a packet buffer */
+ packet_buffer = cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL);
+ if (__predict_false(packet_buffer == NULL)) {
+ DEBUGPRINT("%s: Failed to allocate a packet buffer\n",
+ if_name(ifp));
+ cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, DONT_WRITEBACK(1));
+ ifp->if_oerrors++;
+ m_freem(m);
+ return 0;
+ }
+
+ /* Calculate where we need to copy the data to. We need to leave 8 bytes
+ for a next pointer (unused). We also need to include any configure
+ skip. Then we need to align the IP packet src and dest into the same
+ 64bit word. The below calculation may add a little extra, but that
+ doesn't hurt */
+ copy_location = packet_buffer + sizeof(uint64_t);
+ copy_location += ((CVMX_HELPER_FIRST_MBUFF_SKIP+7)&0xfff8) + 6;
+
+ /* We have to copy the packet since whoever processes this packet
+ will free it to a hardware pool. We can't use the trick of
+ counting outstanding packets like in cvm_oct_xmit */
+ m_copydata(m, 0, m->m_pkthdr.len, copy_location);
+
+ /* Fill in some of the work queue fields. We may need to add more
+ if the software at the other end needs them */
+#if 0
+ work->hw_chksum = m->csum;
+#endif
+ work->len = m->m_pkthdr.len;
+ work->ipprt = priv->port;
+ work->qos = priv->port & 0x7;
+ work->grp = pow_send_group;
+ work->tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
+ work->tag = pow_send_group; /* FIXME */
+ work->word2.u64 = 0; /* Default to zero. Sets of zero later are commented out */
+ work->word2.s.bufs = 1;
+ work->packet_ptr.u64 = 0;
+ work->packet_ptr.s.addr = cvmx_ptr_to_phys(copy_location);
+ work->packet_ptr.s.pool = CVMX_FPA_PACKET_POOL;
+ work->packet_ptr.s.size = CVMX_FPA_PACKET_POOL_SIZE;
+ work->packet_ptr.s.back = (copy_location - packet_buffer)>>7;
+
+ panic("%s: POW transmit not quite implemented yet.", __func__);
+#if 0
+ if (m->protocol == htons(ETH_P_IP)) {
+ work->word2.s.ip_offset = 14;
+ #if 0
+ work->word2.s.vlan_valid = 0; /* FIXME */
+ work->word2.s.vlan_cfi = 0; /* FIXME */
+ work->word2.s.vlan_id = 0; /* FIXME */
+ work->word2.s.dec_ipcomp = 0; /* FIXME */
+ #endif
+ work->word2.s.tcp_or_udp = (ip_hdr(m)->protocol == IP_PROTOCOL_TCP) || (ip_hdr(m)->protocol == IP_PROTOCOL_UDP);
+ #if 0
+ work->word2.s.dec_ipsec = 0; /* FIXME */
+ work->word2.s.is_v6 = 0; /* We only support IPv4 right now */
+ work->word2.s.software = 0; /* Hardware would set to zero */
+ work->word2.s.L4_error = 0; /* No error, packet is internal */
+ #endif
+ work->word2.s.is_frag = !((ip_hdr(m)->frag_off == 0) || (ip_hdr(m)->frag_off == 1<<14));
+ #if 0
+ work->word2.s.IP_exc = 0; /* Assume Linux is sending a good packet */
+ #endif
+ work->word2.s.is_bcast = (m->pkt_type == PACKET_BROADCAST);
+ work->word2.s.is_mcast = (m->pkt_type == PACKET_MULTICAST);
+ #if 0
+ work->word2.s.not_IP = 0; /* This is an IP packet */
+ work->word2.s.rcv_error = 0; /* No error, packet is internal */
+ work->word2.s.err_code = 0; /* No error, packet is internal */
+ #endif
+
+ /* When copying the data, include 4 bytes of the ethernet header to
+ align the same way hardware does */
+ memcpy(work->packet_data, m->data + 10, sizeof(work->packet_data));
+ } else {
+ #if 0
+ work->word2.snoip.vlan_valid = 0; /* FIXME */
+ work->word2.snoip.vlan_cfi = 0; /* FIXME */
+ work->word2.snoip.vlan_id = 0; /* FIXME */
+ work->word2.snoip.software = 0; /* Hardware would set to zero */
+ #endif
+ work->word2.snoip.is_rarp = m->protocol == htons(ETH_P_RARP);
+ work->word2.snoip.is_arp = m->protocol == htons(ETH_P_ARP);
+ work->word2.snoip.is_bcast = (m->pkt_type == PACKET_BROADCAST);
+ work->word2.snoip.is_mcast = (m->pkt_type == PACKET_MULTICAST);
+ work->word2.snoip.not_IP = 1; /* IP was done up above */
+ #if 0
+ work->word2.snoip.rcv_error = 0; /* No error, packet is internal */
+ work->word2.snoip.err_code = 0; /* No error, packet is internal */
+ #endif
+ memcpy(work->packet_data, m->data, sizeof(work->packet_data));
+ }
+#endif
+
+ /* Submit the packet to the POW */
+ cvmx_pow_work_submit(work, work->tag, work->tag_type, work->qos, work->grp);
+ ifp->if_opackets++;
+ ifp->if_obytes += m->m_pkthdr.len;
+ m_freem(m);
+ return 0;
+}
+
+
+/**
+ * This function frees all mbufs that are currenty queued for TX.
+ *
+ * @param dev Device being shutdown
+ */
+void cvm_oct_tx_shutdown(struct ifnet *ifp)
+{
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+ int qos;
+
+ for (qos = 0; qos < 16; qos++) {
+ IF_DRAIN(&priv->tx_free_queue[qos]);
+ }
+}
diff --git a/sys/mips/cavium/octe/ethernet-tx.h b/sys/mips/cavium/octe/ethernet-tx.h
new file mode 100644
index 0000000..33c551a
--- /dev/null
+++ b/sys/mips/cavium/octe/ethernet-tx.h
@@ -0,0 +1,34 @@
+/*************************************************************************
+Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). All rights
+reserved.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export control laws, including the U.S. Export Administration Act and its associated regulations, and may be subject to export or import regulations in other countries.
+
+TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+
+*************************************************************************/
+/* $FreeBSD$ */
+
+int cvm_oct_xmit(struct mbuf *m, struct ifnet *ifp);
+int cvm_oct_xmit_pow(struct mbuf *m, struct ifnet *ifp);
+void cvm_oct_tx_shutdown(struct ifnet *ifp);
+
diff --git a/sys/mips/cavium/octe/ethernet-util.h b/sys/mips/cavium/octe/ethernet-util.h
new file mode 100644
index 0000000..37b75bb
--- /dev/null
+++ b/sys/mips/cavium/octe/ethernet-util.h
@@ -0,0 +1,84 @@
+/*************************************************************************
+Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). All rights
+reserved.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export control laws, including the U.S. Export Administration Act and its associated regulations, and may be subject to export or import regulations in other countries.
+
+TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+
+*************************************************************************/
+/* $FreeBSD$ */
+
+#define DEBUGPRINT(format, ...) printf(format, ##__VA_ARGS__)
+
+/**
+ * Given a packet data address, return a pointer to the
+ * beginning of the packet buffer.
+ *
+ * @param packet_ptr Packet data hardware address
+ * @return Packet buffer pointer
+ */
+static inline char *cvm_oct_get_buffer_ptr(cvmx_buf_ptr_t packet_ptr)
+{
+ return cvmx_phys_to_ptr(((packet_ptr.s.addr >> 7) - packet_ptr.s.back) << 7);
+}
+
+
+/**
+ * Given an IPD/PKO port number, return the logical interface it is
+ * on.
+ *
+ * @param ipd_port Port to check
+ *
+ * @return Logical interface
+ */
+static inline int INTERFACE(int ipd_port)
+{
+ if (ipd_port < 32) /* Interface 0 or 1 for RGMII,GMII,SPI, etc */
+ return ipd_port>>4;
+ else if (ipd_port < 36) /* Interface 2 for NPI */
+ return 2;
+ else if (ipd_port < 40) /* Interface 3 for loopback */
+ return 3;
+ else if (ipd_port == 40) /* Non existant interface for POW0 */
+ return 4;
+ else
+ panic("Illegal ipd_port %d passed to INTERFACE\n", ipd_port);
+}
+
+
+/**
+ * Given an IPD/PKO port number, return the port's index on a
+ * logical interface.
+ *
+ * @param ipd_port Port to check
+ *
+ * @return Index into interface port list
+ */
+static inline int INDEX(int ipd_port)
+{
+ if (ipd_port < 32)
+ return ipd_port & 15;
+ else
+ return ipd_port & 3;
+}
+
diff --git a/sys/mips/cavium/octe/ethernet-xaui.c b/sys/mips/cavium/octe/ethernet-xaui.c
new file mode 100644
index 0000000..4eb4be7
--- /dev/null
+++ b/sys/mips/cavium/octe/ethernet-xaui.c
@@ -0,0 +1,134 @@
+/*************************************************************************
+Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). All rights
+reserved.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export control laws, including the U.S. Export Administration Act and its associated regulations, and may be subject to export or import regulations in other countries.
+
+TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+
+*************************************************************************/
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+
+#include "wrapper-cvmx-includes.h"
+#include "ethernet-headers.h"
+
+extern int octeon_is_simulation(void);
+
+static int cvm_oct_xaui_open(struct ifnet *ifp)
+{
+ cvmx_gmxx_prtx_cfg_t gmx_cfg;
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+ int interface = INTERFACE(priv->port);
+ int index = INDEX(priv->port);
+ cvmx_helper_link_info_t link_info;
+
+ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
+ gmx_cfg.s.en = 1;
+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
+
+ if (!octeon_is_simulation()) {
+ link_info = cvmx_helper_link_get(priv->port);
+ if (!link_info.s.link_up)
+ if_link_state_change(ifp, LINK_STATE_DOWN);
+ else
+ if_link_state_change(ifp, LINK_STATE_UP);
+ }
+ return 0;
+}
+
+static int cvm_oct_xaui_stop(struct ifnet *ifp)
+{
+ cvmx_gmxx_prtx_cfg_t gmx_cfg;
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+ int interface = INTERFACE(priv->port);
+ int index = INDEX(priv->port);
+
+ gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
+ gmx_cfg.s.en = 0;
+ cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
+ return 0;
+}
+
+static void cvm_oct_xaui_poll(struct ifnet *ifp)
+{
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+ cvmx_helper_link_info_t link_info;
+
+ link_info = cvmx_helper_link_get(priv->port);
+ if (link_info.u64 == priv->link_info)
+ return;
+
+ link_info = cvmx_helper_link_autoconf(priv->port);
+ priv->link_info = link_info.u64;
+
+ /* Tell Linux */
+ if (link_info.s.link_up) {
+
+ if_link_state_change(ifp, LINK_STATE_UP);
+ if (priv->queue != -1)
+ DEBUGPRINT("%s: %u Mbps %s duplex, port %2d, queue %2d\n",
+ if_name(ifp), link_info.s.speed,
+ (link_info.s.full_duplex) ? "Full" : "Half",
+ priv->port, priv->queue);
+ else
+ DEBUGPRINT("%s: %u Mbps %s duplex, port %2d, POW\n",
+ if_name(ifp), link_info.s.speed,
+ (link_info.s.full_duplex) ? "Full" : "Half",
+ priv->port);
+ } else {
+ if_link_state_change(ifp, LINK_STATE_DOWN);
+ DEBUGPRINT("%s: Link down\n", if_name(ifp));
+ }
+}
+
+
+int cvm_oct_xaui_init(struct ifnet *ifp)
+{
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;
+ cvm_oct_common_init(ifp);
+ priv->open = cvm_oct_xaui_open;
+ priv->stop = cvm_oct_xaui_stop;
+ priv->stop(ifp);
+ if (!octeon_is_simulation())
+ priv->poll = cvm_oct_xaui_poll;
+
+ return 0;
+}
+
+void cvm_oct_xaui_uninit(struct ifnet *ifp)
+{
+ cvm_oct_common_uninit(ifp);
+}
+
diff --git a/sys/mips/cavium/octe/ethernet.c b/sys/mips/cavium/octe/ethernet.c
new file mode 100644
index 0000000..1f7901f
--- /dev/null
+++ b/sys/mips/cavium/octe/ethernet.c
@@ -0,0 +1,536 @@
+/*************************************************************************
+Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). All rights
+reserved.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export control laws, including the U.S. Export Administration Act and its associated regulations, and may be subject to export or import regulations in other countries.
+
+TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+*************************************************************************/
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/rman.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/module.h>
+#include <sys/smp.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_types.h>
+
+#include "wrapper-cvmx-includes.h"
+#include "ethernet-headers.h"
+
+#include "octebusvar.h"
+
+/*
+ * XXX/juli
+ * Convert 0444 to tunables, 0644 to sysctls.
+ */
+#if defined(CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS) && CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS
+int num_packet_buffers = CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS;
+#else
+int num_packet_buffers = 1024;
+#endif
+TUNABLE_INT("hw.octe.num_packet_buffers", &num_packet_buffers);
+/*
+ "\t\tNumber of packet buffers to allocate and store in the\n"
+ "\t\tFPA. By default, 1024 packet buffers are used unless\n"
+ "\t\tCONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS is defined." */
+
+int pow_receive_group = 15;
+TUNABLE_INT("hw.octe.pow_receive_group", &pow_receive_group);
+/*
+ "\t\tPOW group to receive packets from. All ethernet hardware\n"
+ "\t\twill be configured to send incomming packets to this POW\n"
+ "\t\tgroup. Also any other software can submit packets to this\n"
+ "\t\tgroup for the kernel to process." */
+
+int pow_send_group = -1; /* XXX Should be a sysctl. */
+TUNABLE_INT("hw.octe.pow_send_group", &pow_send_group);
+/*
+ "\t\tPOW group to send packets to other software on. This\n"
+ "\t\tcontrols the creation of the virtual device pow0.\n"
+ "\t\talways_use_pow also depends on this value." */
+
+int always_use_pow;
+TUNABLE_INT("hw.octe.always_use_pow", &always_use_pow);
+/*
+ "\t\tWhen set, always send to the pow group. This will cause\n"
+ "\t\tpackets sent to real ethernet devices to be sent to the\n"
+ "\t\tPOW group instead of the hardware. Unless some other\n"
+ "\t\tapplication changes the config, packets will still be\n"
+ "\t\treceived from the low level hardware. Use this option\n"
+ "\t\tto allow a CVMX app to intercept all packets from the\n"
+ "\t\tlinux kernel. You must specify pow_send_group along with\n"
+ "\t\tthis option." */
+
+char pow_send_list[128] = "";
+TUNABLE_STR("hw.octe.pow_send_list", pow_send_list, sizeof pow_send_list);
+/*
+ "\t\tComma separated list of ethernet devices that should use the\n"
+ "\t\tPOW for transmit instead of the actual ethernet hardware. This\n"
+ "\t\tis a per port version of always_use_pow. always_use_pow takes\n"
+ "\t\tprecedence over this list. For example, setting this to\n"
+ "\t\t\"eth2,spi3,spi7\" would cause these three devices to transmit\n"
+ "\t\tusing the pow_send_group." */
+
+
+static int disable_core_queueing = 1;
+TUNABLE_INT("hw.octe.disable_core_queueing", &disable_core_queueing);
+/*
+ "\t\tWhen set the networking core's tx_queue_len is set to zero. This\n"
+ "\t\tallows packets to be sent without lock contention in the packet scheduler\n"
+ "\t\tresulting in some cases in improved throughput.\n" */
+
+extern int octeon_is_simulation(void);
+
+/**
+ * Exported from the kernel so we can determine board information. It is
+ * passed by the bootloader to the kernel.
+ */
+extern cvmx_bootinfo_t *octeon_bootinfo;
+
+/**
+ * Periodic timer to check auto negotiation
+ */
+static struct callout cvm_oct_poll_timer;
+
+/**
+ * Array of every ethernet device owned by this driver indexed by
+ * the ipd input port number.
+ */
+struct ifnet *cvm_oct_device[TOTAL_NUMBER_OF_PORTS];
+
+
+/**
+ * Periodic timer tick for slow management operations
+ *
+ * @param arg Device to check
+ */
+static void cvm_do_timer(void *arg)
+{
+ static int port;
+ if (port < CVMX_PIP_NUM_INPUT_PORTS) {
+ if (cvm_oct_device[port]) {
+ int queues_per_port;
+ int qos;
+ cvm_oct_private_t *priv = (cvm_oct_private_t *)cvm_oct_device[port]->if_softc;
+ if (priv->poll)
+ {
+ /* skip polling if we don't get the lock */
+ if (MDIO_TRYLOCK()) {
+ priv->poll(cvm_oct_device[port]);
+ MDIO_UNLOCK();
+ }
+ }
+
+ queues_per_port = cvmx_pko_get_num_queues(port);
+ /* Drain any pending packets in the free list */
+ for (qos = 0; qos < queues_per_port; qos++) {
+ if (_IF_QLEN(&priv->tx_free_queue[qos]) > 0) {
+ IF_LOCK(&priv->tx_free_queue[qos]);
+ while (_IF_QLEN(&priv->tx_free_queue[qos]) > cvmx_fau_fetch_and_add32(priv->fau+qos*4, 0)) {
+ struct mbuf *m;
+
+ _IF_DEQUEUE(&priv->tx_free_queue[qos], m);
+ m_freem(m);
+ }
+ IF_UNLOCK(&priv->tx_free_queue[qos]);
+
+ /*
+ * XXX locking!
+ */
+ priv->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ }
+ }
+#if 0
+ cvm_oct_device[port]->get_stats(cvm_oct_device[port]);
+#endif
+ }
+ port++;
+ /* Poll the next port in a 50th of a second.
+ This spreads the polling of ports out a little bit */
+ callout_reset(&cvm_oct_poll_timer, hz / 50, cvm_do_timer, NULL);
+ } else {
+ port = 0;
+ /* All ports have been polled. Start the next iteration through
+ the ports in one second */
+ callout_reset(&cvm_oct_poll_timer, hz, cvm_do_timer, NULL);
+ }
+}
+
+
+/**
+ * Configure common hardware for all interfaces
+ */
+static void cvm_oct_configure_common_hw(device_t bus)
+{
+ struct octebus_softc *sc;
+ int error;
+ int rid;
+
+ sc = device_get_softc(bus);
+
+ /* Setup the FPA */
+ cvmx_fpa_enable();
+ cvm_oct_mem_fill_fpa(CVMX_FPA_PACKET_POOL, CVMX_FPA_PACKET_POOL_SIZE, num_packet_buffers);
+ cvm_oct_mem_fill_fpa(CVMX_FPA_WQE_POOL, CVMX_FPA_WQE_POOL_SIZE, num_packet_buffers);
+ if (CVMX_FPA_OUTPUT_BUFFER_POOL != CVMX_FPA_PACKET_POOL)
+ cvm_oct_mem_fill_fpa(CVMX_FPA_OUTPUT_BUFFER_POOL, CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, 128);
+
+ if (USE_RED)
+ cvmx_helper_setup_red(num_packet_buffers/4, num_packet_buffers/8);
+
+ /* Enable the MII interface */
+ if (!octeon_is_simulation())
+ cvmx_write_csr(CVMX_SMI_EN, 1);
+
+ /* Register an IRQ hander for to receive POW interrupts */
+ rid = 0;
+ sc->sc_rx_irq = bus_alloc_resource(bus, SYS_RES_IRQ, &rid,
+ CVMX_IRQ_WORKQ0 + pow_receive_group,
+ CVMX_IRQ_WORKQ0 + pow_receive_group,
+ 1, RF_ACTIVE);
+ if (sc->sc_rx_irq == NULL) {
+ device_printf(bus, "could not allocate workq irq");
+ return;
+ }
+
+ error = bus_setup_intr(bus, sc->sc_rx_irq, INTR_TYPE_NET | INTR_MPSAFE,
+ cvm_oct_do_interrupt, NULL, cvm_oct_device,
+ NULL);
+ if (error != 0) {
+ device_printf(bus, "could not setup workq irq");
+ return;
+ }
+
+
+#ifdef SMP
+ if (USE_MULTICORE_RECEIVE) {
+ critical_enter();
+ {
+ int cpu;
+ for (cpu = 0; cpu < mp_maxid; cpu++) {
+ if (!CPU_ABSENT(cpu) &&
+ (cpu != PCPU_GET(cpuid))) {
+ cvmx_ciu_intx0_t en;
+ en.u64 = cvmx_read_csr(CVMX_CIU_INTX_EN0(cpu*2));
+ en.s.workq |= (1<<pow_receive_group);
+ cvmx_write_csr(CVMX_CIU_INTX_EN0(cpu*2), en.u64);
+ }
+ }
+ }
+ critical_exit();
+ }
+#endif
+}
+
+
+/**
+ * Free a work queue entry received in a intercept callback.
+ *
+ * @param work_queue_entry
+ * Work queue entry to free
+ * @return Zero on success, Negative on failure.
+ */
+int cvm_oct_free_work(void *work_queue_entry)
+{
+ cvmx_wqe_t *work = work_queue_entry;
+
+ int segments = work->word2.s.bufs;
+ cvmx_buf_ptr_t segment_ptr = work->packet_ptr;
+
+ while (segments--) {
+ cvmx_buf_ptr_t next_ptr = *(cvmx_buf_ptr_t *)cvmx_phys_to_ptr(segment_ptr.s.addr-8);
+ if (__predict_false(!segment_ptr.s.i))
+ cvmx_fpa_free(cvm_oct_get_buffer_ptr(segment_ptr), segment_ptr.s.pool, DONT_WRITEBACK(CVMX_FPA_PACKET_POOL_SIZE/128));
+ segment_ptr = next_ptr;
+ }
+ cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, DONT_WRITEBACK(1));
+
+ return 0;
+}
+
+
+/**
+ * Module/ driver initialization. Creates the linux network
+ * devices.
+ *
+ * @return Zero on success
+ */
+int cvm_oct_init_module(device_t bus)
+{
+ device_t dev;
+ int ifnum;
+ int num_interfaces;
+ int interface;
+ int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE;
+ int qos;
+
+ printf("cavium-ethernet: %s\n", OCTEON_SDK_VERSION_STRING);
+
+#if 0
+ cvm_oct_proc_initialize();
+#endif
+ cvm_oct_rx_initialize();
+ cvm_oct_configure_common_hw(bus);
+
+ cvmx_helper_initialize_packet_io_global();
+
+ /* Change the input group for all ports before input is enabled */
+ num_interfaces = cvmx_helper_get_number_of_interfaces();
+ for (interface = 0; interface < num_interfaces; interface++) {
+ int num_ports = cvmx_helper_ports_on_interface(interface);
+ int port;
+
+ for (port = cvmx_helper_get_ipd_port(interface, 0); port < cvmx_helper_get_ipd_port(interface, num_ports); port++) {
+ cvmx_pip_prt_tagx_t pip_prt_tagx;
+ pip_prt_tagx.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(port));
+ pip_prt_tagx.s.grp = pow_receive_group;
+ cvmx_write_csr(CVMX_PIP_PRT_TAGX(port), pip_prt_tagx.u64);
+ }
+ }
+
+ cvmx_helper_ipd_and_packet_input_enable();
+
+ memset(cvm_oct_device, 0, sizeof(cvm_oct_device));
+
+ /* Initialize the FAU used for counting packet buffers that need to be freed */
+ cvmx_fau_atomic_write32(FAU_NUM_PACKET_BUFFERS_TO_FREE, 0);
+
+ if ((pow_send_group != -1)) {
+ struct ifnet *ifp;
+
+ printf("\tConfiguring device for POW only access\n");
+ dev = BUS_ADD_CHILD(bus, 0, "pow", 0);
+ if (dev != NULL)
+ ifp = if_alloc(IFT_ETHER);
+ if (dev != NULL && ifp != NULL) {
+ /* Initialize the device private structure. */
+ cvm_oct_private_t *priv;
+
+ device_probe(dev);
+ priv = device_get_softc(dev);
+ priv->dev = dev;
+ priv->ifp = ifp;
+ priv->init = cvm_oct_common_init;
+ priv->imode = CVMX_HELPER_INTERFACE_MODE_DISABLED;
+ priv->port = CVMX_PIP_NUM_INPUT_PORTS;
+ priv->queue = -1;
+
+ device_set_desc(dev, "Cavium Octeon POW Ethernet\n");
+
+ ifp->if_softc = priv;
+
+ if (priv->init(ifp) < 0) {
+ printf("\t\tFailed to register ethernet device for POW\n");
+ panic("%s: need to free ifp.", __func__);
+ } else {
+ cvm_oct_device[CVMX_PIP_NUM_INPUT_PORTS] = ifp;
+ printf("\t\t%s: POW send group %d, receive group %d\n",
+ if_name(ifp), pow_send_group, pow_receive_group);
+ }
+ } else {
+ printf("\t\tFailed to allocate ethernet device for POW\n");
+ }
+ }
+
+ ifnum = 0;
+ num_interfaces = cvmx_helper_get_number_of_interfaces();
+ for (interface = 0; interface < num_interfaces; interface++) {
+ cvmx_helper_interface_mode_t imode = cvmx_helper_interface_get_mode(interface);
+ int num_ports = cvmx_helper_ports_on_interface(interface);
+ int port;
+
+ for (port = cvmx_helper_get_ipd_port(interface, 0); port < cvmx_helper_get_ipd_port(interface, num_ports); port++) {
+ cvm_oct_private_t *priv;
+ struct ifnet *ifp;
+
+ dev = BUS_ADD_CHILD(bus, 0, "octe", ifnum++);
+ if (dev != NULL)
+ ifp = if_alloc(IFT_ETHER);
+ if (dev == NULL || ifp == NULL) {
+ printf("\t\tFailed to allocate ethernet device for port %d\n", port);
+ continue;
+ }
+ /* XXX/juli set max send q len. */
+#if 0
+ if (disable_core_queueing)
+ ifp->tx_queue_len = 0;
+#endif
+
+ /* Initialize the device private structure. */
+ device_probe(dev);
+ priv = device_get_softc(dev);
+ priv->dev = dev;
+ priv->ifp = ifp;
+ priv->imode = imode;
+ priv->port = port;
+ priv->queue = cvmx_pko_get_base_queue(priv->port);
+ priv->fau = fau - cvmx_pko_get_num_queues(port) * 4;
+ for (qos = 0; qos < cvmx_pko_get_num_queues(port); qos++)
+ cvmx_fau_atomic_write32(priv->fau+qos*4, 0);
+
+ switch (priv->imode) {
+
+ /* These types don't support ports to IPD/PKO */
+ case CVMX_HELPER_INTERFACE_MODE_DISABLED:
+ case CVMX_HELPER_INTERFACE_MODE_PCIE:
+ case CVMX_HELPER_INTERFACE_MODE_PICMG:
+ break;
+
+ case CVMX_HELPER_INTERFACE_MODE_NPI:
+ priv->init = cvm_oct_common_init;
+ priv->uninit = cvm_oct_common_uninit;
+ device_set_desc(dev, "Cavium Octeon NPI Ethernet");
+ break;
+
+ case CVMX_HELPER_INTERFACE_MODE_XAUI:
+ priv->init = cvm_oct_xaui_init;
+ priv->uninit = cvm_oct_xaui_uninit;
+ device_set_desc(dev, "Cavium Octeon XAUI Ethernet");
+ break;
+
+ case CVMX_HELPER_INTERFACE_MODE_LOOP:
+ priv->init = cvm_oct_common_init;
+ priv->uninit = cvm_oct_common_uninit;
+ device_set_desc(dev, "Cavium Octeon LOOP Ethernet");
+ break;
+
+ case CVMX_HELPER_INTERFACE_MODE_SGMII:
+ priv->init = cvm_oct_sgmii_init;
+ priv->uninit = cvm_oct_sgmii_uninit;
+ device_set_desc(dev, "Cavium Octeon SGMII Ethernet");
+ break;
+
+ case CVMX_HELPER_INTERFACE_MODE_SPI:
+ priv->init = cvm_oct_spi_init;
+ priv->uninit = cvm_oct_spi_uninit;
+ device_set_desc(dev, "Cavium Octeon SPI Ethernet");
+ break;
+
+ case CVMX_HELPER_INTERFACE_MODE_RGMII:
+ priv->init = cvm_oct_rgmii_init;
+ priv->uninit = cvm_oct_rgmii_uninit;
+ device_set_desc(dev, "Cavium Octeon RGMII Ethernet");
+ break;
+
+ case CVMX_HELPER_INTERFACE_MODE_GMII:
+ priv->init = cvm_oct_rgmii_init;
+ priv->uninit = cvm_oct_rgmii_uninit;
+ device_set_desc(dev, "Cavium Octeon GMII Ethernet");
+ break;
+ }
+
+ ifp->if_softc = priv;
+
+ if (!priv->init) {
+ panic("%s: unsupported device type, need to free ifp.", __func__);
+ } else
+ if (priv->init(ifp) < 0) {
+ printf("\t\tFailed to register ethernet device for interface %d, port %d\n",
+ interface, priv->port);
+ panic("%s: init failed, need to free ifp.", __func__);
+ } else {
+ cvm_oct_device[priv->port] = ifp;
+ fau -= cvmx_pko_get_num_queues(priv->port) * sizeof(uint32_t);
+ }
+ }
+ }
+
+ if (INTERRUPT_LIMIT) {
+ /* Set the POW timer rate to give an interrupt at most INTERRUPT_LIMIT times per second */
+ cvmx_write_csr(CVMX_POW_WQ_INT_PC, octeon_bootinfo->eclock_hz/(INTERRUPT_LIMIT*16*256)<<8);
+
+ /* Enable POW timer interrupt. It will count when there are packets available */
+ cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), 0x1ful<<24);
+ } else {
+ /* Enable POW interrupt when our port has at least one packet */
+ cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), 0x1001);
+ }
+
+ callout_init(&cvm_oct_poll_timer, CALLOUT_MPSAFE);
+ callout_reset(&cvm_oct_poll_timer, hz, cvm_do_timer, NULL);
+
+ return 0;
+}
+
+
+/**
+ * Module / driver shutdown
+ *
+ * @return Zero on success
+ */
+void cvm_oct_cleanup_module(void)
+{
+ int port;
+
+ /* Disable POW interrupt */
+ cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), 0);
+
+ cvmx_ipd_disable();
+
+#if 0
+ /* Free the interrupt handler */
+ free_irq(8 + pow_receive_group, cvm_oct_device);
+#endif
+
+ callout_stop(&cvm_oct_poll_timer);
+ cvm_oct_rx_shutdown();
+ cvmx_pko_disable();
+
+ /* Free the ethernet devices */
+ for (port = 0; port < TOTAL_NUMBER_OF_PORTS; port++) {
+ if (cvm_oct_device[port]) {
+ cvm_oct_tx_shutdown(cvm_oct_device[port]);
+#if 0
+ unregister_netdev(cvm_oct_device[port]);
+ kfree(cvm_oct_device[port]);
+#else
+ panic("%s: need to detach and free interface.", __func__);
+#endif
+ cvm_oct_device[port] = NULL;
+ }
+ }
+
+ cvmx_pko_shutdown();
+#if 0
+ cvm_oct_proc_shutdown();
+#endif
+
+ cvmx_ipd_free_ptr();
+
+ /* Free the HW pools */
+ cvm_oct_mem_empty_fpa(CVMX_FPA_PACKET_POOL, CVMX_FPA_PACKET_POOL_SIZE, num_packet_buffers);
+ cvm_oct_mem_empty_fpa(CVMX_FPA_WQE_POOL, CVMX_FPA_WQE_POOL_SIZE, num_packet_buffers);
+ if (CVMX_FPA_OUTPUT_BUFFER_POOL != CVMX_FPA_PACKET_POOL)
+ cvm_oct_mem_empty_fpa(CVMX_FPA_OUTPUT_BUFFER_POOL, CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, 128);
+}
diff --git a/sys/mips/cavium/octe/octe.c b/sys/mips/cavium/octe/octe.c
new file mode 100644
index 0000000..312598d
--- /dev/null
+++ b/sys/mips/cavium/octe/octe.c
@@ -0,0 +1,515 @@
+/*-
+ * Copyright (c) 2010 Juli Mallett <jmallett@FreeBSD.org>
+ * 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.
+ *
+ * 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$
+ */
+
+/*
+ * Cavium Octeon Ethernet devices.
+ *
+ * XXX This file should be moved to if_octe.c
+ * XXX The driver may have sufficient locking but we need locking to protect
+ * the interfaces presented here, right?
+ */
+
+#include "opt_inet.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+
+#include <net/bpf.h>
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/if_var.h>
+#include <net/if_vlan_var.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#endif
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include "wrapper-cvmx-includes.h"
+#include "cavium-ethernet.h"
+
+#include "ethernet-common.h"
+#include "ethernet-defines.h"
+#include "ethernet-mdio.h"
+#include "ethernet-tx.h"
+
+#include "miibus_if.h"
+
+#define OCTE_TX_LOCK(priv) mtx_lock(&(priv)->tx_mtx)
+#define OCTE_TX_UNLOCK(priv) mtx_unlock(&(priv)->tx_mtx)
+
+static int octe_probe(device_t);
+static int octe_attach(device_t);
+static int octe_detach(device_t);
+static int octe_shutdown(device_t);
+
+static int octe_miibus_readreg(device_t, int, int);
+static int octe_miibus_writereg(device_t, int, int, int);
+
+static void octe_init(void *);
+static void octe_stop(void *);
+static void octe_start(struct ifnet *);
+
+static int octe_mii_medchange(struct ifnet *);
+static void octe_mii_medstat(struct ifnet *, struct ifmediareq *);
+
+static int octe_medchange(struct ifnet *);
+static void octe_medstat(struct ifnet *, struct ifmediareq *);
+
+static int octe_ioctl(struct ifnet *, u_long, caddr_t);
+
+static device_method_t octe_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, octe_probe),
+ DEVMETHOD(device_attach, octe_attach),
+ DEVMETHOD(device_detach, octe_detach),
+ DEVMETHOD(device_shutdown, octe_shutdown),
+
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, octe_miibus_readreg),
+ DEVMETHOD(miibus_writereg, octe_miibus_writereg),
+
+ { 0, 0 }
+};
+
+static driver_t octe_driver = {
+ "octe",
+ octe_methods,
+ sizeof (cvm_oct_private_t),
+};
+
+static devclass_t octe_devclass;
+
+DRIVER_MODULE(octe, octebus, octe_driver, octe_devclass, 0, 0);
+DRIVER_MODULE(miibus, octe, miibus_driver, miibus_devclass, 0, 0);
+
+static driver_t pow_driver = {
+ "pow",
+ octe_methods,
+ sizeof (cvm_oct_private_t),
+};
+
+static devclass_t pow_devclass;
+
+DRIVER_MODULE(pow, octebus, pow_driver, pow_devclass, 0, 0);
+
+static int
+octe_probe(device_t dev)
+{
+ return (0);
+}
+
+static int
+octe_attach(device_t dev)
+{
+ struct ifnet *ifp;
+ cvm_oct_private_t *priv;
+ unsigned qos;
+ int error;
+
+ priv = device_get_softc(dev);
+ ifp = priv->ifp;
+
+ if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+
+ if (priv->phy_id != -1) {
+ error = mii_phy_probe(dev, &priv->miibus, octe_mii_medchange,
+ octe_mii_medstat);
+ if (error != 0) {
+ device_printf(dev, "missing phy %u\n", priv->phy_id);
+ }
+ }
+
+ if (priv->miibus == NULL) {
+ ifmedia_init(&priv->media, 0, octe_medchange, octe_medstat);
+
+ ifmedia_add(&priv->media, IFM_ETHER | IFM_AUTO, 0, NULL);
+ ifmedia_set(&priv->media, IFM_ETHER | IFM_AUTO);
+ }
+
+ /*
+ * XXX
+ * We don't support programming the multicast filter right now, although it
+ * ought to be easy enough. (Presumably it's just a matter of putting
+ * multicast addresses in the CAM?)
+ */
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | IFF_ALLMULTI;
+ ifp->if_init = octe_init;
+ ifp->if_ioctl = octe_ioctl;
+ ifp->if_start = octe_start;
+
+ priv->if_flags = ifp->if_flags;
+
+ mtx_init(&priv->tx_mtx, ifp->if_xname, "octe tx send queue", MTX_DEF);
+
+ for (qos = 0; qos < 16; qos++) {
+ mtx_init(&priv->tx_free_queue[qos].ifq_mtx, ifp->if_xname, "octe tx free queue", MTX_DEF);
+ IFQ_SET_MAXLEN(&priv->tx_free_queue[qos], MAX_OUT_QUEUE_DEPTH);
+ }
+
+ ether_ifattach(ifp, priv->mac);
+
+ ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
+ ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_HWCSUM;
+ ifp->if_capenable = ifp->if_capabilities;
+ ifp->if_hwassist = CSUM_TCP | CSUM_UDP;
+
+ OCTE_TX_LOCK(priv);
+ IFQ_SET_MAXLEN(&ifp->if_snd, MAX_OUT_QUEUE_DEPTH);
+ ifp->if_snd.ifq_drv_maxlen = MAX_OUT_QUEUE_DEPTH;
+ IFQ_SET_READY(&ifp->if_snd);
+ OCTE_TX_UNLOCK(priv);
+
+ return (0);
+}
+
+static int
+octe_detach(device_t dev)
+{
+ return (0);
+}
+
+static int
+octe_shutdown(device_t dev)
+{
+ return (octe_detach(dev));
+}
+
+static int
+octe_miibus_readreg(device_t dev, int phy, int reg)
+{
+ cvm_oct_private_t *priv;
+
+ priv = device_get_softc(dev);
+
+ if (phy != priv->phy_id)
+ return (0);
+
+ return (cvm_oct_mdio_read(priv->ifp, phy, reg));
+}
+
+static int
+octe_miibus_writereg(device_t dev, int phy, int reg, int val)
+{
+ cvm_oct_private_t *priv;
+
+ priv = device_get_softc(dev);
+
+ KASSERT(phy == priv->phy_id,
+ ("write to phy %u but our phy is %u", phy, priv->phy_id));
+
+ cvm_oct_mdio_write(priv->ifp, phy, reg, val);
+
+ return (0);
+}
+
+static void
+octe_init(void *arg)
+{
+ struct ifnet *ifp;
+ cvm_oct_private_t *priv;
+
+ priv = arg;
+ ifp = priv->ifp;
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ octe_stop(priv);
+
+ if (priv->open != NULL)
+ priv->open(ifp);
+
+ if (((ifp->if_flags ^ priv->if_flags) & (IFF_ALLMULTI | IFF_MULTICAST | IFF_PROMISC)) != 0)
+ cvm_oct_common_set_multicast_list(ifp);
+
+ cvm_oct_common_set_mac_address(ifp, IF_LLADDR(ifp));
+
+ if (priv->poll != NULL)
+ priv->poll(ifp);
+ if (priv->miibus != NULL)
+ mii_mediachg(device_get_softc(priv->miibus));
+
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+}
+
+static void
+octe_stop(void *arg)
+{
+ struct ifnet *ifp;
+ cvm_oct_private_t *priv;
+
+ priv = arg;
+ ifp = priv->ifp;
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ return;
+
+ if (priv->stop != NULL)
+ priv->stop(ifp);
+
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+}
+
+static void
+octe_start(struct ifnet *ifp)
+{
+ cvm_oct_private_t *priv;
+ struct mbuf *m;
+ int error;
+
+ priv = ifp->if_softc;
+
+ if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING)
+ return;
+
+ OCTE_TX_LOCK(priv);
+ while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+
+ OCTE_TX_UNLOCK(priv);
+
+ /*
+ * XXX
+ *
+ * We may not be able to pass the mbuf up to BPF for one of
+ * two very good reasons:
+ * (1) immediately after our inserting it another CPU may be
+ * kind enough to free it for us.
+ * (2) m_collapse gets called on m and we don't get back the
+ * modified pointer.
+ *
+ * We have some options other than an m_dup route:
+ * (1) use a mutex or spinlock to prevent another CPU from
+ * freeing it. We could lock the tx_free_list's lock,
+ * that would make sense.
+ * (2) get back the new mbuf pointer.
+ * (3) do the collapse here.
+ */
+
+ if (priv->queue != -1) {
+ error = cvm_oct_xmit(m, ifp);
+ } else {
+ error = cvm_oct_xmit_pow(m, ifp);
+ }
+
+ if (error != 0) {
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ return;
+ }
+
+ OCTE_TX_LOCK(priv);
+ }
+ OCTE_TX_UNLOCK(priv);
+}
+
+static int
+octe_mii_medchange(struct ifnet *ifp)
+{
+ cvm_oct_private_t *priv;
+ struct mii_data *mii;
+
+ priv = ifp->if_softc;
+ mii = device_get_softc(priv->miibus);
+
+ if (mii->mii_instance) {
+ struct mii_softc *miisc;
+
+ LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
+ mii_phy_reset(miisc);
+ }
+ mii_mediachg(mii);
+
+ return (0);
+}
+
+static void
+octe_mii_medstat(struct ifnet *ifp, struct ifmediareq *ifm)
+{
+ cvm_oct_private_t *priv;
+ struct mii_data *mii;
+
+ priv = ifp->if_softc;
+ mii = device_get_softc(priv->miibus);
+
+ mii_pollstat(mii);
+ ifm->ifm_active = mii->mii_media_active;
+ ifm->ifm_status = mii->mii_media_status;
+}
+
+static int
+octe_medchange(struct ifnet *ifp)
+{
+ return (ENOTSUP);
+}
+
+static void
+octe_medstat(struct ifnet *ifp, struct ifmediareq *ifm)
+{
+ cvm_oct_private_t *priv;
+ cvmx_helper_link_info_t link_info;
+
+ priv = ifp->if_softc;
+
+ ifm->ifm_status = IFM_AVALID;
+ ifm->ifm_active = IFT_ETHER;
+
+ if (priv->poll == NULL)
+ return;
+ priv->poll(ifp);
+
+ link_info.u64 = priv->link_info;
+
+ if (!link_info.s.link_up)
+ return;
+
+ ifm->ifm_status |= IFM_ACTIVE;
+
+ switch (link_info.s.speed) {
+ case 10:
+ ifm->ifm_active |= IFM_10_T;
+ break;
+ case 100:
+ ifm->ifm_active |= IFM_100_TX;
+ break;
+ case 1000:
+ ifm->ifm_active |= IFM_1000_T;
+ break;
+ case 10000:
+ ifm->ifm_active |= IFM_10G_T;
+ break;
+ }
+
+ if (link_info.s.full_duplex)
+ ifm->ifm_active |= IFM_FDX;
+ else
+ ifm->ifm_active |= IFM_HDX;
+}
+
+static int
+octe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+ cvm_oct_private_t *priv;
+ struct mii_data *mii;
+ struct ifreq *ifr;
+#ifdef INET
+ struct ifaddr *ifa;
+#endif
+ int error;
+
+ priv = ifp->if_softc;
+ ifr = (struct ifreq *)data;
+#ifdef INET
+ ifa = (struct ifaddr *)data;
+#endif
+
+ switch (cmd) {
+ case SIOCSIFADDR:
+#ifdef INET
+ /*
+ * Avoid reinitialization unless it's necessary.
+ */
+ if (ifa->ifa_addr->sa_family == AF_INET) {
+ ifp->if_flags |= IFF_UP;
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ octe_init(priv);
+ arp_ifinit(ifp, ifa);
+
+ return (0);
+ }
+#endif
+ error = ether_ioctl(ifp, cmd, data);
+ if (error != 0)
+ return (error);
+ return (0);
+
+ case SIOCSIFFLAGS:
+ if (ifp->if_flags == priv->if_flags)
+ return (0);
+ if ((ifp->if_flags & IFF_UP) != 0) {
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ octe_init(priv);
+ } else {
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ octe_stop(priv);
+ }
+ priv->if_flags = ifp->if_flags;
+ return (0);
+
+ case SIOCSIFCAP:
+ /*
+ * Just change the capabilities in software, currently none
+ * require reprogramming hardware, they just toggle whether we
+ * make use of already-present facilities in software.
+ */
+ ifp->if_capenable = ifr->ifr_reqcap;
+ return (0);
+
+ case SIOCSIFMTU:
+ error = cvm_oct_common_change_mtu(ifp, ifr->ifr_mtu);
+ if (error != 0)
+ return (EINVAL);
+ return (0);
+
+ case SIOCSIFMEDIA:
+ case SIOCGIFMEDIA:
+ if (priv->miibus != NULL) {
+ mii = device_get_softc(priv->miibus);
+ error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
+ if (error != 0)
+ return (error);
+ return (0);
+ }
+ error = ifmedia_ioctl(ifp, ifr, &priv->media, cmd);
+ if (error != 0)
+ return (error);
+ return (0);
+
+ default:
+ error = ether_ioctl(ifp, cmd, data);
+ if (error != 0)
+ return (error);
+ return (0);
+ }
+}
diff --git a/sys/mips/cavium/octe/octebus.c b/sys/mips/cavium/octe/octebus.c
new file mode 100644
index 0000000..ec67cf6
--- /dev/null
+++ b/sys/mips/cavium/octe/octebus.c
@@ -0,0 +1,123 @@
+/*-
+ * Copyright (c) 2010 Juli Mallett <jmallett@FreeBSD.org>
+ * 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.
+ *
+ * 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$
+ */
+
+/*
+ * Cavium Octeon Ethernet pseudo-bus attachment.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+
+#include "ethernet-common.h"
+
+#include "octebusvar.h"
+
+static void octebus_identify(driver_t *drv, device_t parent);
+static int octebus_probe(device_t dev);
+static int octebus_attach(device_t dev);
+static int octebus_detach(device_t dev);
+static int octebus_shutdown(device_t dev);
+
+static device_method_t octebus_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_identify, octebus_identify),
+ DEVMETHOD(device_probe, octebus_probe),
+ DEVMETHOD(device_attach, octebus_attach),
+ DEVMETHOD(device_detach, octebus_detach),
+ DEVMETHOD(device_shutdown, octebus_shutdown),
+
+ /* Bus interface. */
+ DEVMETHOD(bus_add_child, bus_generic_add_child),
+
+ { 0, 0 }
+};
+
+static driver_t octebus_driver = {
+ "octebus",
+ octebus_methods,
+ sizeof (struct octebus_softc),
+};
+
+static devclass_t octebus_devclass;
+
+DRIVER_MODULE(octebus, ciu, octebus_driver, octebus_devclass, 0, 0);
+
+static void
+octebus_identify(driver_t *drv, device_t parent)
+{
+ BUS_ADD_CHILD(parent, 0, "octebus", 0);
+}
+
+static int
+octebus_probe(device_t dev)
+{
+ if (device_get_unit(dev) != 0)
+ return (ENXIO);
+ device_set_desc(dev, "Cavium Octeon Ethernet pseudo-bus");
+ return (0);
+}
+
+static int
+octebus_attach(device_t dev)
+{
+ struct octebus_softc *sc;
+ int rv;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+
+ rv = cvm_oct_init_module(dev);
+ if (rv != 0)
+ return (ENXIO);
+
+ return (0);
+}
+
+static int
+octebus_detach(device_t dev)
+{
+ cvm_oct_cleanup_module();
+ return (0);
+}
+
+static int
+octebus_shutdown(device_t dev)
+{
+ return (octebus_detach(dev));
+}
diff --git a/sys/mips/cavium/octe/octebusvar.h b/sys/mips/cavium/octe/octebusvar.h
new file mode 100644
index 0000000..061c020
--- /dev/null
+++ b/sys/mips/cavium/octe/octebusvar.h
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 2010 Juli Mallett <jmallett@FreeBSD.org>
+ * 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.
+ *
+ * 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$
+ */
+
+#ifndef _CAVIUM_OCTE_OCTEBUSVAR_H_
+#define _CAVIUM_OCTE_OCTEBUSVAR_H_
+
+struct octebus_softc {
+ device_t sc_dev;
+
+ struct resource *sc_rx_irq;
+
+ struct resource *sc_rgmii_irq;
+ struct resource *sc_spi_irq;
+};
+
+#endif /* !_CAVIUM_OCTE_OCTEBUSVAR_H_ */
diff --git a/sys/mips/cavium/octe/wrapper-cvmx-includes.h b/sys/mips/cavium/octe/wrapper-cvmx-includes.h
new file mode 100644
index 0000000..bc69505
--- /dev/null
+++ b/sys/mips/cavium/octe/wrapper-cvmx-includes.h
@@ -0,0 +1,50 @@
+/*************************************************************************
+Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). All rights
+reserved.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export control laws, including the U.S. Export Administration Act and its associated regulations, and may be subject to export or import regulations in other countries.
+
+TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+
+*************************************************************************/
+/* $FreeBSD$ */
+
+#ifndef __WRAPPER_CVMX_INCLUDES_H__
+#define __WRAPPER_CVMX_INCLUDES_H__
+
+#include <contrib/octeon-sdk/cvmx.h>
+#include <contrib/octeon-sdk/cvmx-version.h>
+#include <contrib/octeon-sdk/cvmx-atomic.h>
+#include <contrib/octeon-sdk/cvmx-ciu.h>
+#include <contrib/octeon-sdk/cvmx-pip.h>
+#include <contrib/octeon-sdk/cvmx-ipd.h>
+#include <contrib/octeon-sdk/cvmx-pko.h>
+#include <contrib/octeon-sdk/cvmx-pow.h>
+#include <contrib/octeon-sdk/cvmx-gmx.h>
+#include <contrib/octeon-sdk/cvmx-spi.h>
+#include <contrib/octeon-sdk/cvmx-bootmem.h>
+#include <contrib/octeon-sdk/cvmx-app-init.h>
+#include <contrib/octeon-sdk/cvmx-helper.h>
+#include <contrib/octeon-sdk/cvmx-helper-board.h>
+#include <contrib/octeon-sdk/cvmx-interrupt.h>
+
+#endif
diff --git a/sys/mips/cavium/octeon_ds1337.c b/sys/mips/cavium/octeon_ds1337.c
new file mode 100644
index 0000000..b79d734
--- /dev/null
+++ b/sys/mips/cavium/octeon_ds1337.c
@@ -0,0 +1,213 @@
+/***********************license start***************
+ * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
+ * reserved.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * 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.
+ *
+ * * Neither the name of Cavium Networks nor the names of
+ * its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written
+ * permission.
+ *
+ * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+ * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
+ * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
+ * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
+ * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
+ * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
+ * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
+ * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
+ * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT
+ * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+ *
+ *
+ * For any questions regarding licensing please contact marketing@caviumnetworks.com
+ *
+ ***********************license end**************************************/
+
+
+
+
+
+
+/**
+ * @file
+ *
+ * Interface to the EBH-30xx specific devices
+ *
+ * <hr>$Revision: 41586 $<hr>
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/timespec.h>
+#include <sys/clock.h>
+#include <sys/libkern.h>
+
+#include <contrib/octeon-sdk/cvmx.h>
+#include <contrib/octeon-sdk/cvmx-cn3010-evb-hs5.h>
+#include <contrib/octeon-sdk/cvmx-twsi.h>
+
+#define CT_CHECK(_expr, _msg) \
+ do { \
+ if (_expr) { \
+ cvmx_dprintf("Warning: RTC has invalid %s field\n", (_msg)); \
+ rc = -1; \
+ } \
+ } while(0);
+
+static int validate_ct_struct(struct clocktime *ct)
+{
+ int rc = 0;
+
+ if (!ct)
+ return -1;
+
+ CT_CHECK(ct->sec < 0 || ct->sec > 60, "second"); /* + Leap sec */
+ CT_CHECK(ct->min < 0 || ct->min > 59, "minute");
+ CT_CHECK(ct->hour < 0 || ct->hour > 23, "hour");
+ CT_CHECK(ct->day < 1 || ct->day > 31, "day");
+ CT_CHECK(ct->dow < 0 || ct->dow > 6, "day of week");
+ CT_CHECK(ct->mon < 0 || ct->mon > 11, "month");
+ CT_CHECK(ct->year < 0 || ct->year > 200,"year");
+
+ return rc;
+}
+
+/*
+ * Board-specifc RTC read
+ * Time is expressed in seconds from epoch (Jan 1 1970 at 00:00:00 UTC)
+ * and converted internally to calendar format.
+ */
+uint32_t cvmx_rtc_ds1337_read(void)
+{
+ int i, retry;
+ uint8_t reg[8];
+ uint8_t sec;
+ struct clocktime ct;
+ struct timespec ts;
+
+
+ memset(&reg, 0, sizeof(reg));
+ memset(&ct, 0, sizeof(ct));
+
+ for(retry=0; retry<2; retry++)
+ {
+ /* Lockless read: detects the infrequent roll-over and retries */
+ reg[0] = cvmx_twsi_read8(CVMX_RTC_DS1337_ADDR, 0x0);
+ for(i=1; i<7; i++)
+ reg[i] = cvmx_twsi_read8_cur_addr(CVMX_RTC_DS1337_ADDR);
+
+ sec = cvmx_twsi_read8(CVMX_RTC_DS1337_ADDR, 0x0);
+ if ((sec & 0xf) == (reg[0] & 0xf))
+ break; /* Time did not roll-over, value is correct */
+ }
+
+ ct.sec = bcd2bin(reg[0] & 0x7f);
+ ct.min = bcd2bin(reg[1] & 0x7f);
+ ct.hour = bcd2bin(reg[2] & 0x3f);
+ if ((reg[2] & 0x40) && (reg[2] & 0x20)) /* AM/PM format and is PM time */
+ {
+ ct.hour = (ct.hour + 12) % 24;
+ }
+ ct.dow = (reg[3] & 0x7) - 1; /* Day of week field is 0..6 */
+ ct.day = bcd2bin(reg[4] & 0x3f);
+ ct.mon = bcd2bin(reg[5] & 0x1f) - 1; /* Month field is 0..11 */
+ ct.year = ((reg[5] & 0x80) ? 100 : 0) + bcd2bin(reg[6]);
+
+
+ if (validate_ct_struct(&ct))
+ cvmx_dprintf("Warning: RTC calendar is not configured properly\n");
+
+ if (clock_ct_to_ts(&ct, &ts) != 0) {
+ cvmx_dprintf("Warning: RTC calendar is not configured properly\n");
+ return 0;
+ }
+
+ return ts.tv_sec;
+}
+
+/*
+ * Board-specific RTC write
+ * Time returned is in seconds from epoch (Jan 1 1970 at 00:00:00 UTC)
+ */
+int cvmx_rtc_ds1337_write(uint32_t time)
+{
+ struct clocktime ct;
+ struct timespec ts;
+ int i, rc, retry;
+ uint8_t reg[8];
+ uint8_t sec;
+
+ ts.tv_sec = time;
+ ts.tv_nsec = 0;
+
+ clock_ts_to_ct(&ts, &ct);
+
+ if (validate_ct_struct(&ct))
+ {
+ cvmx_dprintf("Error: RTC was passed wrong calendar values, write failed\n");
+ goto ct_invalid;
+ }
+
+ reg[0] = bin2bcd(ct.sec);
+ reg[1] = bin2bcd(ct.min);
+ reg[2] = bin2bcd(ct.hour); /* Force 0..23 format even if using AM/PM */
+ reg[3] = bin2bcd(ct.dow + 1);
+ reg[4] = bin2bcd(ct.day);
+ reg[5] = bin2bcd(ct.mon + 1);
+ if (ct.year >= 100) /* Set century bit*/
+ {
+ reg[5] |= 0x80;
+ }
+ reg[6] = bin2bcd(ct.year % 100);
+
+ /* Lockless write: detects the infrequent roll-over and retries */
+ for(retry=0; retry<2; retry++)
+ {
+ rc = 0;
+ for(i=0; i<7; i++)
+ {
+ rc |= cvmx_twsi_write8(CVMX_RTC_DS1337_ADDR, i, reg[i]);
+ }
+
+ sec = cvmx_twsi_read8(CVMX_RTC_DS1337_ADDR, 0x0);
+ if ((sec & 0xf) == (reg[0] & 0xf))
+ break; /* Time did not roll-over, value is correct */
+ }
+
+ return (rc ? -1 : 0);
+
+ ct_invalid:
+ return -1;
+}
+
+#ifdef CVMX_RTC_DEBUG
+
+void cvmx_rtc_ds1337_dump_state(void)
+{
+ int i = 0;
+
+ printf("RTC:\n");
+ printf("%d : %02X ", i, cvmx_twsi_read8(CVMX_RTC_DS1337_ADDR, 0x0));
+ for(i=1; i<16; i++) {
+ printf("%02X ", cvmx_twsi_read8_cur_addr(CVMX_RTC_DS1337_ADDR));
+ }
+ printf("\n");
+}
+
+#endif /* CVMX_RTC_DEBUG */
diff --git a/sys/mips/cavium/octeon_ebt3000_cf.c b/sys/mips/cavium/octeon_ebt3000_cf.c
index 4298b75..3ab115f 100644
--- a/sys/mips/cavium/octeon_ebt3000_cf.c
+++ b/sys/mips/cavium/octeon_ebt3000_cf.c
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
#include <sys/bio.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
+#include <sys/ata.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
@@ -65,10 +66,10 @@ __FBSDID("$FreeBSD$");
#include <machine/md_var.h>
#include <machine/cpuregs.h>
-#include "octeon_ebt3000_cf.h"
-#include "driveid.h"
#include <mips/cavium/octeon_pcmap_regs.h>
+#include <contrib/octeon-sdk/cvmx.h>
+
/* ATA Commands */
#define CMD_READ_SECTOR 0x20
#define CMD_WRITE_SECTOR 0x30
@@ -97,10 +98,10 @@ __FBSDID("$FreeBSD$");
#define WAIT_DELAY 1000
#define NR_TRIES 1000
#define SWAP_SHORT(x) ((x << 8) | (x >> 8))
-#define SWAP_LONG(x) (((x << 24) & 0xFF000000) | ((x << 8) & 0x00FF0000) | \
- ((x >> 8) & 0x0000FF00) | ((x << 24) & 0x000000FF) )
#define MODEL_STR_SIZE 40
+/* XXX */
+extern cvmx_bootinfo_t *octeon_bootinfo;
/* Globals */
int bus_width;
@@ -122,7 +123,7 @@ struct cf_priv {
struct drive_param{
union {
char buf[SECTOR_SIZE];
- struct hd_driveid driveid;
+ struct ata_params driveid;
} u;
char model[MODEL_STR_SIZE];
@@ -415,10 +416,11 @@ static int cf_cmd_identify (void)
cf_swap_ascii(drive_param.u.driveid.model, drive_param.model);
drive_param.sector_size = 512; //= SWAP_SHORT (drive_param.u.driveid.sector_bytes);
- drive_param.heads = SWAP_SHORT (drive_param.u.driveid.cur_heads);
- drive_param.tracks = SWAP_SHORT (drive_param.u.driveid.cur_cyls);
- drive_param.sec_track = SWAP_SHORT (drive_param.u.driveid.cur_sectors);
- drive_param.nr_sectors = SWAP_LONG (drive_param.u.driveid.lba_capacity);
+ drive_param.heads = SWAP_SHORT (drive_param.u.driveid.current_heads);
+ drive_param.tracks = SWAP_SHORT (drive_param.u.driveid.current_cylinders);
+ drive_param.sec_track = SWAP_SHORT (drive_param.u.driveid.current_sectors);
+ drive_param.nr_sectors = (uint32_t)SWAP_SHORT (drive_param.u.driveid.lba_size_1) |
+ ((uint32_t)SWAP_SHORT (drive_param.u.driveid.lba_size_2));
return (0);
}
@@ -558,7 +560,7 @@ static void cf_swap_ascii (unsigned char str1[], char str2[])
static int cf_probe (device_t dev)
{
- if (!octeon_board_real()) return 1;
+ if (octeon_is_simulation()) return 1;
if (device_get_unit(dev) != 0) {
panic("can't attach more devices\n");
@@ -583,19 +585,19 @@ static void cf_identify (driver_t *drv, device_t parent)
uint8_t status;
int bus_region;
int count = 0;
- octeon_mio_boot_reg_cfgx_t cfg;
+ cvmx_mio_boot_reg_cfgx_t cfg;
- if (!octeon_board_real())
+ if (octeon_is_simulation())
return;
- base_addr = (void *) MIPS_PHYS_TO_KSEG0(OCTEON_CF_COMMON_BASE_ADDR);
+ base_addr = cvmx_phys_to_ptr(octeon_bootinfo->compact_flash_common_base_addr);
for (bus_region = 0; bus_region < 8; bus_region++)
{
- cfg.word64 = oct_read64(OCTEON_MIO_BOOT_REG_CFGX(bus_region));
- if (cfg.bits.base == OCTEON_CF_COMMON_BASE_ADDR >> 16)
+ cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(bus_region));
+ if (cfg.s.base == octeon_bootinfo->compact_flash_common_base_addr >> 16)
{
- bus_width = (cfg.bits.width) ? 16: 8;
+ bus_width = (cfg.s.width) ? 16: 8;
printf("Compact flash found in bootbus region %d (%d bit).\n", bus_region, bus_width);
break;
}
@@ -664,7 +666,7 @@ static int cf_attach (device_t dev)
{
struct cf_priv *cf_priv;
- if (!octeon_board_real()) return 1;
+ if (octeon_is_simulation()) return 1;
cf_priv = device_get_softc(dev);
cf_priv->dev = dev;
diff --git a/sys/mips/cavium/octeon_ebt3000_cf.h b/sys/mips/cavium/octeon_ebt3000_cf.h
deleted file mode 100644
index 1ce8a8a..0000000
--- a/sys/mips/cavium/octeon_ebt3000_cf.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/***********************license start***************
- * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
- * reserved.
- *
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * 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.
- *
- * * Neither the name of Cavium Networks nor the names of
- * its contributors may be used to endorse or promote products
- * derived from this software without specific prior written
- * permission.
- *
- * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
- * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
- * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
- * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
- * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
- * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
- * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
- * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
- * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT
- * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
- *
- *
- * For any questions regarding licensing please contact marketing@caviumnetworks.com
- *
- ***********************license end**************************************/
-
-/* $FreeBSD$ */
-
-/*
- * octeon_ebt3000_cf.h
- *
- */
-
-
-#ifndef __OCTEON_EBT3000_H__
-#define __OCTEON_EBT3000_H__
-
-
-
-#define OCTEON_CF_COMMON_BASE_ADDR (0x1d000000 | (1 << 11))
-#define OCTEON_MIO_BOOT_REG_CFGX(offset) (0x8001180000000000ull + ((offset) * 8))
-
-
-typedef union
-{
- uint64_t word64;
- struct
- {
- uint64_t reserved : 27; /**< Reserved */
- uint64_t sam : 1; /**< Region 0 SAM */
- uint64_t we_ext : 2; /**< Region 0 write enable count extension */
- uint64_t oe_ext : 2; /**< Region 0 output enable count extension */
- uint64_t en : 1; /**< Region 0 enable */
- uint64_t orbit : 1; /**< No function for region 0 */
- uint64_t ale : 1; /**< Region 0 ALE mode */
- uint64_t width : 1; /**< Region 0 bus width */
- uint64_t size : 12; /**< Region 0 size */
- uint64_t base : 16; /**< Region 0 base address */
- } bits;
-} octeon_mio_boot_reg_cfgx_t;
-
-
-#endif /* __OCTEON_EBT3000_H__ */
diff --git a/sys/mips/cavium/octeon_machdep.c b/sys/mips/cavium/octeon_machdep.c
index d5df4b4..5321a78 100644
--- a/sys/mips/cavium/octeon_machdep.c
+++ b/sys/mips/cavium/octeon_machdep.c
@@ -47,6 +47,8 @@ __FBSDID("$FreeBSD$");
#include <sys/signalvar.h>
#include <sys/sysent.h>
#include <sys/sysproto.h>
+#include <sys/time.h>
+#include <sys/timetc.h>
#include <sys/user.h>
#include <vm/vm.h>
@@ -70,21 +72,60 @@ __FBSDID("$FreeBSD$");
#include <machine/trap.h>
#include <machine/vmparam.h>
+#include <contrib/octeon-sdk/cvmx.h>
+#include <contrib/octeon-sdk/cvmx-bootmem.h>
+#include <contrib/octeon-sdk/cvmx-interrupt.h>
+#include <contrib/octeon-sdk/cvmx-version.h>
+
#if defined(__mips_n64)
#define MAX_APP_DESC_ADDR 0xffffffffafffffff
#else
#define MAX_APP_DESC_ADDR 0xafffffff
#endif
+#define OCTEON_CLOCK_DEFAULT (500 * 1000 * 1000)
+
+struct octeon_feature_description {
+ octeon_feature_t ofd_feature;
+ const char *ofd_string;
+};
+
extern int *edata;
extern int *end;
+static const struct octeon_feature_description octeon_feature_descriptions[] = {
+ { OCTEON_FEATURE_SAAD, "SAAD" },
+ { OCTEON_FEATURE_ZIP, "ZIP" },
+ { OCTEON_FEATURE_CRYPTO, "CRYPTO" },
+ { OCTEON_FEATURE_PCIE, "PCIE" },
+ { OCTEON_FEATURE_KEY_MEMORY, "KEY_MEMORY" },
+ { OCTEON_FEATURE_LED_CONTROLLER, "LED_CONTROLLER" },
+ { OCTEON_FEATURE_TRA, "TRA" },
+ { OCTEON_FEATURE_MGMT_PORT, "MGMT_PORT" },
+ { OCTEON_FEATURE_RAID, "RAID" },
+ { OCTEON_FEATURE_USB, "USB" },
+ { OCTEON_FEATURE_NO_WPTR, "NO_WPTR" },
+ { OCTEON_FEATURE_DFA, "DFA" },
+ { OCTEON_FEATURE_MDIO_CLAUSE_45, "MDIO_CLAUSE_45" },
+ { 0, NULL }
+};
+
uint64_t ciu_get_en_reg_addr_new(int corenum, int intx, int enx, int ciu_ip);
void ciu_dump_interrutps_enabled(int core_num, int intx, int enx, int ciu_ip);
+static uint64_t octeon_get_ticks(void);
+static unsigned octeon_get_timecount(struct timecounter *tc);
+
static void octeon_boot_params_init(register_t ptr);
-static uint64_t ciu_get_intr_sum_reg_addr(int core_num, int intx, int enx);
-static uint64_t ciu_get_intr_en_reg_addr(int core_num, int intx, int enx);
+
+static struct timecounter octeon_timecounter = {
+ octeon_get_timecount, /* get_timecount */
+ 0, /* no poll_pps */
+ 0xffffffffu, /* octeon_mask */
+ 0, /* frequency */
+ "Octeon", /* name */
+ 900, /* quality (adjusted in code) */
+};
void
platform_cpu_init()
@@ -98,7 +139,7 @@ platform_cpu_init()
void
platform_reset(void)
{
- oct_write64(OCTEON_CIU_SOFT_RST, 1);
+ cvmx_write_csr(CVMX_CIU_SOFT_RST, 1);
}
void
@@ -106,7 +147,7 @@ octeon_led_write_char(int char_position, char val)
{
uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8);
- if (!octeon_board_real())
+ if (octeon_is_simulation())
return;
char_position &= 0x7; /* only 8 chars */
@@ -119,7 +160,7 @@ octeon_led_write_char0(char val)
{
uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8);
- if (!octeon_board_real())
+ if (octeon_is_simulation())
return;
oct_write8_x8(ptr, val);
}
@@ -130,7 +171,7 @@ octeon_led_write_hexchar(int char_position, char hexval)
uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8);
char char1, char2;
- if (!octeon_board_real())
+ if (octeon_is_simulation())
return;
char1 = (hexval >> 4) & 0x0f; char1 = (char1 < 10)?char1+'0':char1+'7';
@@ -150,7 +191,7 @@ octeon_led_write_string(const char *str)
uint64_t ptr = (OCTEON_CHAR_LED_BASE_ADDR | 0xf8);
int i;
- if (!octeon_board_real())
+ if (octeon_is_simulation())
return;
for (i=0; i<8; i++, ptr++) {
@@ -158,7 +199,7 @@ octeon_led_write_string(const char *str)
oct_write8_x8(ptr, *str++);
else
oct_write8_x8(ptr, ' ');
- oct_read64(OCTEON_MIO_BOOT_BIST_STAT);
+ (void)cvmx_read_csr(CVMX_MIO_BOOT_BIST_STAT);
}
}
@@ -167,7 +208,7 @@ static char progress[8] = { '-', '/', '|', '\\', '-', '/', '|', '\\'};
void
octeon_led_run_wheel(int *prog_count, int led_position)
{
- if (!octeon_board_real())
+ if (octeon_is_simulation())
return;
octeon_led_write_char(led_position, progress[*prog_count]);
*prog_count += 1;
@@ -183,7 +224,6 @@ octeon_led_write_hex(uint32_t wl)
octeon_led_write_string(nbuf);
}
-
/*
* octeon_debug_symbol
*
@@ -195,23 +235,6 @@ octeon_debug_symbol(void)
{
}
-void
-octeon_ciu_stop_gtimer(int timer)
-{
- oct_write64(OCTEON_CIU_GENTIMER_ADDR(timer), 0ll);
-}
-
-void
-octeon_ciu_start_gtimer(int timer, u_int one_shot, uint64_t time_cycles)
-{
- octeon_ciu_gentimer gentimer;
-
- gentimer.word64 = 0;
- gentimer.bits.one_shot = one_shot;
- gentimer.bits.len = time_cycles - 1;
- oct_write64(OCTEON_CIU_GENTIMER_ADDR(timer), gentimer.word64);
-}
-
/*
* octeon_ciu_reset
*
@@ -220,358 +243,83 @@ octeon_ciu_start_gtimer(int timer, u_int one_shot, uint64_t time_cycles)
void
octeon_ciu_reset(void)
{
+ /* Disable all CIU interrupts by default */
+ cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2), 0);
+ cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2+1), 0);
+ cvmx_write_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num()*2), 0);
+ cvmx_write_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num()*2+1), 0);
- octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_0);
- octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_1);
- octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_2);
- octeon_ciu_stop_gtimer(CIU_GENTIMER_NUM_3);
-
- ciu_disable_intr(CIU_THIS_CORE, CIU_INT_0, CIU_EN_0);
- ciu_disable_intr(CIU_THIS_CORE, CIU_INT_0, CIU_EN_1);
- ciu_disable_intr(CIU_THIS_CORE, CIU_INT_1, CIU_EN_0);
- ciu_disable_intr(CIU_THIS_CORE, CIU_INT_1, CIU_EN_1);
-
- ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_0, CIU_EN_0, 0ll);
- ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_1, CIU_EN_0, 0ll);
- ciu_clear_int_summary(CIU_THIS_CORE, CIU_INT_1, CIU_EN_1, 0ll);
-}
-
-/*
- * mips_disable_interrupt_controllers
- *
- * Disable interrupts in the CPU controller
- */
-void
-mips_disable_interrupt_controls(void)
-{
- /*
- * Disable interrupts in CIU.
- */
- octeon_ciu_reset();
-}
-
-/*
- * ciu_get_intr_sum_reg_addr
- */
-static uint64_t
-ciu_get_intr_sum_reg_addr(int core_num, int intx, int enx)
-{
- uint64_t ciu_intr_sum_reg_addr;
-
- if (enx == CIU_EN_0)
- ciu_intr_sum_reg_addr = OCTEON_CIU_SUMMARY_BASE_ADDR +
- (core_num * 0x10) + (intx * 0x8);
- else
- ciu_intr_sum_reg_addr = OCTEON_CIU_SUMMARY_INT1_ADDR;
-
- return (ciu_intr_sum_reg_addr);
+#ifdef SMP
+ /* Enable the MBOX interrupts. */
+ cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2+1),
+ (1ull << (CVMX_IRQ_MBOX0 - 8)) |
+ (1ull << (CVMX_IRQ_MBOX1 - 8)));
+#endif
}
-
-/*
- * ciu_get_intr_en_reg_addr
- */
-static uint64_t
-ciu_get_intr_en_reg_addr(int core_num, int intx, int enx)
+static void
+octeon_memory_init(void)
{
- uint64_t ciu_intr_reg_addr;
-
- ciu_intr_reg_addr = OCTEON_CIU_ENABLE_BASE_ADDR +
- ((enx == 0) ? 0x0 : 0x8) + (intx * 0x10) + (core_num * 0x20);
- return (ciu_intr_reg_addr);
-}
-
+ vm_paddr_t phys_end;
+ int64_t addr;
+ unsigned i;
+ phys_end = round_page(MIPS_KSEG0_TO_PHYS((vm_offset_t)&end));
+ if (octeon_is_simulation()) {
+ /* Simulator we limit to 96 meg */
+ phys_avail[0] = phys_end;
+ phys_avail[1] = 96 << 20;
-/*
- * ciu_get_intr_reg_addr
- *
- * 200 ---int0,en0 ip2
- * 208 ---int0,en1 ip2 ----> this is wrong... this is watchdog
- *
- * 210 ---int0,en0 ip3 --
- * 218 ---int0,en1 ip3 ----> same here.. .this is watchdog... right?
- *
- * 220 ---int1,en0 ip2
- * 228 ---int1,en1 ip2
- * 230 ---int1,en0 ip3 --
- * 238 ---int1,en1 ip3
- *
- */
-uint64_t
-ciu_get_en_reg_addr_new(int corenum, int intx, int enx, int ciu_ip)
-{
- uint64_t ciu_intr_reg_addr = OCTEON_CIU_ENABLE_BASE_ADDR;
-
- /* XXX kasserts? */
- if (enx < CIU_EN_0 || enx > CIU_EN_1) {
- printf("%s: invalid enx value %d, should be %d or %d\n",
- __func__, enx, CIU_EN_0, CIU_EN_1);
- return 0;
- }
- if (intx < CIU_INT_0 || intx > CIU_INT_1) {
- printf("%s: invalid intx value %d, should be %d or %d\n",
- __func__, enx, CIU_INT_0, CIU_INT_1);
- return 0;
- }
- if (ciu_ip < CIU_MIPS_IP2 || ciu_ip > CIU_MIPS_IP3) {
- printf("%s: invalid ciu_ip value %d, should be %d or %d\n",
- __func__, ciu_ip, CIU_MIPS_IP2, CIU_MIPS_IP3);
- return 0;
+ realmem = physmem = btoc(phys_avail[1] - phys_avail[0]);
+ return;
}
- ciu_intr_reg_addr += (enx * 0x8);
- ciu_intr_reg_addr += (ciu_ip * 0x10);
- ciu_intr_reg_addr += (intx * 0x20);
- return (ciu_intr_reg_addr);
-}
-
-/*
- * ciu_get_int_summary
- */
-uint64_t
-ciu_get_int_summary(int core_num, int intx, int enx)
-{
- uint64_t ciu_intr_sum_reg_addr;
-
- if (core_num == CIU_THIS_CORE)
- core_num = octeon_get_core_num();
- ciu_intr_sum_reg_addr = ciu_get_intr_sum_reg_addr(core_num, intx, enx);
- return (oct_read64(ciu_intr_sum_reg_addr));
-}
-
-//#define DEBUG_CIU 1
-
-#ifdef DEBUG_CIU
-#define DEBUG_CIU_SUM 1
-#define DEBUG_CIU_EN 1
-#endif
-
-
-/*
- * ciu_clear_int_summary
- */
-void
-ciu_clear_int_summary(int core_num, int intx, int enx, uint64_t write_bits)
-{
- uint32_t cpu_status_bits;
- uint64_t ciu_intr_sum_reg_addr;
+ /*
+ * Allocate memory from bootmem 1MB at a time and merge
+ * adjacent entries.
+ */
+ i = 0;
+ while (i < PHYS_AVAIL_ENTRIES) {
+ addr = cvmx_bootmem_phy_alloc(1 << 20, phys_end,
+ ~(vm_paddr_t)0, PAGE_SIZE, 0);
+ if (addr == -1)
+ break;
-//#define DEBUG_CIU_SUM 1
+ physmem += btoc(1 << 20);
-#ifdef DEBUG_CIU_SUM
- uint64_t ciu_intr_sum_bits;
-#endif
+ if (i > 0 && phys_avail[i - 1] == addr) {
+ phys_avail[i - 1] += 1 << 20;
+ continue;
+ }
+ phys_avail[i + 0] = addr;
+ phys_avail[i + 1] = addr + (1 << 20);
- if (core_num == CIU_THIS_CORE) {
- core_num = octeon_get_core_num();
+ i += 2;
}
-#ifdef DEBUG_CIU_SUM
- printf(" CIU: core %u clear sum IntX %u Enx %u Bits: 0x%llX\n",
- core_num, intx, enx, write_bits);
-#endif
-
- cpu_status_bits = intr_disable();
-
- ciu_intr_sum_reg_addr = ciu_get_intr_sum_reg_addr(core_num, intx, enx);
-
-#ifdef DEBUG_CIU_SUM
- ciu_intr_sum_bits = oct_read64(ciu_intr_sum_reg_addr); /* unneeded dummy read */
- printf(" CIU: status: 0x%X reg_addr: 0x%llX Val: 0x%llX -> 0x%llX",
- cpu_status_bits, ciu_intr_sum_reg_addr, ciu_intr_sum_bits,
- ciu_intr_sum_bits | write_bits);
-#endif
-
- oct_write64(ciu_intr_sum_reg_addr, write_bits);
- oct_read64(OCTEON_MIO_BOOT_BIST_STAT); /* Bus Barrier */
-
-#ifdef DEBUG_CIU_SUM
- printf(" Readback: 0x%llX\n\n ", (uint64_t) oct_read64(ciu_intr_sum_reg_addr));
-#endif
-
- intr_restore(cpu_status_bits);
-}
-
-/*
- * ciu_disable_intr
- */
-void
-ciu_disable_intr(int core_num, int intx, int enx)
-{
- uint32_t cpu_status_bits;
- uint64_t ciu_intr_reg_addr;
-
- if (core_num == CIU_THIS_CORE)
- core_num = octeon_get_core_num();
-
- cpu_status_bits = intr_disable();
-
- ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx);
-
- oct_read64(ciu_intr_reg_addr); /* Dummy read */
-
- oct_write64(ciu_intr_reg_addr, 0LL);
- oct_read64(OCTEON_MIO_BOOT_BIST_STAT); /* Bus Barrier */
-
- intr_restore(cpu_status_bits);
-}
-
-void
-ciu_dump_interrutps_enabled(int core_num, int intx, int enx, int ciu_ip)
-{
-
- uint64_t ciu_intr_reg_addr;
- uint64_t ciu_intr_bits;
-
- if (core_num == CIU_THIS_CORE) {
- core_num = octeon_get_core_num();
- }
-
-#ifndef OCTEON_SMP_1
- ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx);
-#else
- ciu_intr_reg_addr = ciu_get_en_reg_addr_new(core_num, intx, enx, ciu_ip);
-#endif
-
- if (!ciu_intr_reg_addr) {
- printf("Bad call to %s\n", __func__);
- while(1);
- return;
- }
-
- ciu_intr_bits = oct_read64(ciu_intr_reg_addr);
- printf(" CIU core %d int: %d en: %d ip: %d Add: %#llx enabled: %#llx SR: %x\n",
- core_num, intx, enx, ciu_ip, (unsigned long long)ciu_intr_reg_addr,
- (unsigned long long)ciu_intr_bits, mips_rd_status());
-}
-
-
-/*
- * ciu_enable_interrupts
- */
-void ciu_enable_interrupts(int core_num, int intx, int enx,
- uint64_t set_these_interrupt_bits, int ciu_ip)
-{
- uint32_t cpu_status_bits;
- uint64_t ciu_intr_reg_addr;
- uint64_t ciu_intr_bits;
-
- if (core_num == CIU_THIS_CORE)
- core_num = octeon_get_core_num();
-
-//#define DEBUG_CIU_EN 1
-
-#ifdef DEBUG_CIU_EN
- printf(" CIU: core %u enabling Intx %u Enx %u IP %d Bits: 0x%llX\n",
- core_num, intx, enx, ciu_ip, set_these_interrupt_bits);
-#endif
-
- cpu_status_bits = intr_disable();
-
-#ifndef OCTEON_SMP_1
- ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx);
-#else
- ciu_intr_reg_addr = ciu_get_en_reg_addr_new(core_num, intx, enx, ciu_ip);
-#endif
-
- if (!ciu_intr_reg_addr) {
- printf("Bad call to %s\n", __func__);
- while(1);
- return; /* XXX */
- }
-
- ciu_intr_bits = oct_read64(ciu_intr_reg_addr);
-
-#ifdef DEBUG_CIU_EN
- printf(" CIU: status: 0x%X reg_addr: 0x%llX Val: 0x%llX -> 0x%llX",
- cpu_status_bits, ciu_intr_reg_addr, ciu_intr_bits, ciu_intr_bits | set_these_interrupt_bits);
-#endif
- ciu_intr_bits |= set_these_interrupt_bits;
- oct_write64(ciu_intr_reg_addr, ciu_intr_bits);
-#ifdef SMP
- mips_wbflush();
-#endif
- oct_read64(OCTEON_MIO_BOOT_BIST_STAT); /* Bus Barrier */
-
-#ifdef DEBUG_CIU_EN
- printf(" Readback: 0x%llX\n\n ",
- (uint64_t)oct_read64(ciu_intr_reg_addr));
-#endif
-
- intr_restore(cpu_status_bits);
-}
-
-unsigned long
-octeon_get_clock_rate(void)
-{
- return octeon_cpu_clock;
-}
-
-static void
-octeon_memory_init(void)
-{
- uint32_t realmem_bytes;
-
- if (octeon_board_real()) {
- realmem_bytes = (octeon_dram - PAGE_SIZE);
- realmem_bytes &= ~(PAGE_SIZE - 1);
- } else {
- /* Simulator we limit to 96 meg */
- realmem_bytes = (96 << 20);
- }
- /* phys_avail regions are in bytes */
- phys_avail[0] = (MIPS_KSEG0_TO_PHYS((vm_offset_t)&end) + PAGE_SIZE) & ~(PAGE_SIZE - 1);
- if (octeon_board_real()) {
- if (realmem_bytes > OCTEON_DRAM_FIRST_256_END)
- phys_avail[1] = OCTEON_DRAM_FIRST_256_END;
- else
- phys_avail[1] = realmem_bytes;
- realmem_bytes -= OCTEON_DRAM_FIRST_256_END;
- realmem_bytes &= ~(PAGE_SIZE - 1);
- } else {
- /* Simulator gets 96Meg period. */
- phys_avail[1] = (96 << 20);
- }
- /*-
- * Octeon Memory looks as follows:
- * PA
- * 0000 0000 to 0x0 0000 0000 0000
- * 0FFF FFFF First 256 MB memory Maps to 0x0 0000 0FFF FFFF
- *
- * 1000 0000 to 0x1 0000 1000 0000
- * 1FFF FFFF Uncached Bu I/O space.converted to 0x1 0000 1FFF FFFF
- *
- * 2FFF FFFF to Cached 0x0 0000 2000 0000
- * FFFF FFFF all dram mem above the first 512M 0x3 FFFF FFFF FFFF
- *
- */
- physmem = btoc(phys_avail[1] - phys_avail[0]);
- if ((octeon_board_real()) &&
- (realmem_bytes > OCTEON_DRAM_FIRST_256_END)) {
- /* take out the upper non-cached 1/2 */
- realmem_bytes -= OCTEON_DRAM_FIRST_256_END;
- realmem_bytes &= ~(PAGE_SIZE - 1);
- /* Now map the rest of the memory */
- phys_avail[2] = 0x20000000;
- phys_avail[3] = ((uint32_t) 0x20000000 + realmem_bytes);
- physmem += btoc(phys_avail[3] - phys_avail[2]);
- }
realmem = physmem;
-
- printf("Total DRAM Size %#X\n", (uint32_t) octeon_dram);
- printf("Bank 0 = %#08lX -> %#08lX\n", (long)phys_avail[0], (long)phys_avail[1]);
- printf("Bank 1 = %#08lX -> %#08lX\n", (long)phys_avail[2], (long)phys_avail[3]);
}
void
platform_start(__register_t a0, __register_t a1, __register_t a2 __unused,
__register_t a3)
{
+ const struct octeon_feature_description *ofd;
uint64_t platform_counter_freq;
+ /*
+ * XXX
+ * octeon_boot_params_init() should be called before anything else,
+ * certainly before any output; we may find out from the boot
+ * descriptor's flags that we're supposed to use the PCI or UART1
+ * consoles rather than UART0. No point doing that reorganization
+ * until we actually intercept UART_DEV_CONSOLE for the UART1 case
+ * and somehow handle the PCI console, which we lack code for
+ * entirely.
+ */
+
/* Initialize pcpu stuff */
mips_pcpu0_init();
mips_timer_early_init(OCTEON_CLOCK_DEFAULT);
@@ -579,6 +327,12 @@ platform_start(__register_t a0, __register_t a1, __register_t a2 __unused,
octeon_ciu_reset();
octeon_boot_params_init(a3);
+ /*
+ * XXX
+ * We can certainly parse command line arguments or U-Boot environment
+ * to determine whether to bootverbose / single user / ... I think
+ * stass has patches to add support for loader things to U-Boot even.
+ */
bootverbose = 1;
/*
@@ -601,16 +355,43 @@ platform_start(__register_t a0, __register_t a1, __register_t a2 __unused,
if (boothowto & RB_KDB)
kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
#endif
- platform_counter_freq = octeon_get_clock_rate();
+ platform_counter_freq = cvmx_sysinfo_get()->cpu_clock_hz;
+
+ octeon_timecounter.tc_frequency = cvmx_sysinfo_get()->cpu_clock_hz;
+ platform_timecounter = &octeon_timecounter;
+
mips_timer_init_params(platform_counter_freq, 0);
+ set_cputicker(octeon_get_ticks, cvmx_sysinfo_get()->cpu_clock_hz, 0);
+
#ifdef SMP
/*
- * Clear any pending IPIs and enable the IPI interrupt.
+ * Clear any pending IPIs.
*/
- oct_write64(OCTEON_CIU_MBOX_CLRX(0), 0xffffffff);
- ciu_enable_interrupts(0, CIU_INT_1, CIU_EN_0, OCTEON_CIU_ENABLE_MBOX_INTR, CIU_MIPS_IP3);
+ cvmx_write_csr(CVMX_CIU_MBOX_CLRX(0), 0xffffffff);
#endif
+
+ printf("Octeon SDK: %s\n", OCTEON_SDK_VERSION_STRING);
+ printf("Available Octeon features:");
+ for (ofd = octeon_feature_descriptions; ofd->ofd_string != NULL; ofd++)
+ if (octeon_has_feature(ofd->ofd_feature))
+ printf(" %s", ofd->ofd_string);
+ printf("\n");
+}
+
+static uint64_t
+octeon_get_ticks(void)
+{
+ uint64_t cvmcount;
+
+ CVMX_MF_CYCLE(cvmcount);
+ return (cvmcount);
+}
+
+static unsigned
+octeon_get_timecount(struct timecounter *tc)
+{
+ return ((unsigned)octeon_get_ticks());
}
/* impSTART: This stuff should move back into the Cavium SDK */
@@ -642,7 +423,6 @@ platform_start(__register_t a0, __register_t a1, __register_t a2 __unused,
#define OCTEON_ARGV_MAX_ARGS (64)
#define OCTOEN_SERIAL_LEN 20
-
typedef struct {
/* Start of block referenced by assembly code - do not change! */
uint32_t desc_version;
@@ -680,168 +460,95 @@ typedef struct {
uint64_t cvmx_desc_vaddr;
} octeon_boot_descriptor_t;
-
-typedef struct {
- uint32_t major_version;
- uint32_t minor_version;
-
- uint64_t stack_top;
- uint64_t heap_base;
- uint64_t heap_end;
- uint64_t desc_vaddr;
-
- uint32_t exception_base_addr;
- uint32_t stack_size;
- uint32_t flags;
- uint32_t core_mask;
- uint32_t dram_size; /**< DRAM size in megabyes */
- uint32_t phy_mem_desc_addr; /**< physical address of free memory descriptor block*/
- uint32_t debugger_flags_base_addr; /**< used to pass flags from app to debugger */
- uint32_t eclock_hz; /**< CPU clock speed, in hz */
- uint32_t dclock_hz; /**< DRAM clock speed, in hz */
- uint32_t spi_clock_hz; /**< SPI4 clock in hz */
- uint16_t board_type;
- uint8_t board_rev_major;
- uint8_t board_rev_minor;
- uint16_t chip_type;
- uint8_t chip_rev_major;
- uint8_t chip_rev_minor;
- char board_serial_number[OCTOEN_SERIAL_LEN];
- uint8_t mac_addr_base[6];
- uint8_t mac_addr_count;
-} cvmx_bootinfo_t;
-
-uint32_t octeon_cpu_clock;
-uint64_t octeon_dram;
-uint32_t octeon_bd_ver = 0, octeon_cvmx_bd_ver = 0, octeon_board_rev_major, octeon_board_rev_minor, octeon_board_type;
-uint8_t octeon_mac_addr[6] = { 0 };
-int octeon_core_mask, octeon_mac_addr_count;
-int octeon_chip_rev_major = 0, octeon_chip_rev_minor = 0, octeon_chip_type = 0;
+cvmx_bootinfo_t *octeon_bootinfo;
static octeon_boot_descriptor_t *app_desc_ptr;
-static cvmx_bootinfo_t *cvmx_desc_ptr;
-
-#define OCTEON_BOARD_TYPE_NONE 0
-#define OCTEON_BOARD_TYPE_SIM 1
-#define OCTEON_BOARD_TYPE_CN3010_EVB_HS5 11
-
-#define OCTEON_CLOCK_MIN (100 * 1000 * 1000)
-#define OCTEON_CLOCK_MAX (800 * 1000 * 1000)
-#define OCTEON_DRAM_DEFAULT (256 * 1024 * 1024)
-#define OCTEON_DRAM_MIN 30
-#define OCTEON_DRAM_MAX 3000
-
int
-octeon_board_real(void)
+octeon_is_simulation(void)
{
- switch (octeon_board_type) {
- case OCTEON_BOARD_TYPE_NONE:
- case OCTEON_BOARD_TYPE_SIM:
- return 0;
- case OCTEON_BOARD_TYPE_CN3010_EVB_HS5:
- /*
- * XXX
- * The CAM-0100 identifies itself as type 11, revision 0.0,
- * despite its being rather real. Disable the revision check
- * for type 11.
- */
+ switch (cvmx_sysinfo_get()->board_type) {
+ case CVMX_BOARD_TYPE_SIM:
return 1;
default:
- if (octeon_board_rev_major == 0)
- return 0;
- return 1;
+ return 0;
}
}
static void
-octeon_process_app_desc_ver_unknown(void)
-{
- printf(" Unknown Boot-Descriptor: Using Defaults\n");
-
- octeon_cpu_clock = OCTEON_CLOCK_DEFAULT;
- octeon_dram = OCTEON_DRAM_DEFAULT;
- octeon_board_rev_major = octeon_board_rev_minor = octeon_board_type = 0;
- octeon_core_mask = 1;
- octeon_chip_type = octeon_chip_rev_major = octeon_chip_rev_minor = 0;
- octeon_mac_addr[0] = 0x00; octeon_mac_addr[1] = 0x0f;
- octeon_mac_addr[2] = 0xb7; octeon_mac_addr[3] = 0x10;
- octeon_mac_addr[4] = 0x09; octeon_mac_addr[5] = 0x06;
- octeon_mac_addr_count = 1;
-}
-
-static int
octeon_process_app_desc_ver_6(void)
{
+ void *phy_mem_desc_ptr;
+
/* XXX Why is 0x00000000ffffffffULL a bad value? */
if (app_desc_ptr->cvmx_desc_vaddr == 0 ||
- app_desc_ptr->cvmx_desc_vaddr == 0xfffffffful) {
- printf ("Bad cvmx_desc_ptr %p\n", cvmx_desc_ptr);
- return 1;
- }
- cvmx_desc_ptr =
+ app_desc_ptr->cvmx_desc_vaddr == 0xfffffffful)
+ panic("Bad octeon_bootinfo %p", octeon_bootinfo);
+
+ octeon_bootinfo =
(cvmx_bootinfo_t *)(intptr_t)app_desc_ptr->cvmx_desc_vaddr;
- cvmx_desc_ptr =
- (cvmx_bootinfo_t *) ((intptr_t)cvmx_desc_ptr | MIPS_KSEG0_START);
- octeon_cvmx_bd_ver = (cvmx_desc_ptr->major_version * 100) +
- cvmx_desc_ptr->minor_version;
- if (cvmx_desc_ptr->major_version != 1) {
- panic("Incompatible CVMX descriptor from bootloader: %d.%d %p\n",
- (int) cvmx_desc_ptr->major_version,
- (int) cvmx_desc_ptr->minor_version, cvmx_desc_ptr);
- }
-
- octeon_core_mask = cvmx_desc_ptr->core_mask;
- octeon_cpu_clock = cvmx_desc_ptr->eclock_hz;
- octeon_board_type = cvmx_desc_ptr->board_type;
- octeon_board_rev_major = cvmx_desc_ptr->board_rev_major;
- octeon_board_rev_minor = cvmx_desc_ptr->board_rev_minor;
- octeon_chip_type = cvmx_desc_ptr->chip_type;
- octeon_chip_rev_major = cvmx_desc_ptr->chip_rev_major;
- octeon_chip_rev_minor = cvmx_desc_ptr->chip_rev_minor;
- octeon_mac_addr[0] = cvmx_desc_ptr->mac_addr_base[0];
- octeon_mac_addr[1] = cvmx_desc_ptr->mac_addr_base[1];
- octeon_mac_addr[2] = cvmx_desc_ptr->mac_addr_base[2];
- octeon_mac_addr[3] = cvmx_desc_ptr->mac_addr_base[3];
- octeon_mac_addr[4] = cvmx_desc_ptr->mac_addr_base[4];
- octeon_mac_addr[5] = cvmx_desc_ptr->mac_addr_base[5];
- octeon_mac_addr_count = cvmx_desc_ptr->mac_addr_count;
-
- if (app_desc_ptr->dram_size > 16*1024*1024)
- octeon_dram = (uint64_t)app_desc_ptr->dram_size;
- else
- octeon_dram = (uint64_t)app_desc_ptr->dram_size << 20;
- return 0;
+ octeon_bootinfo =
+ (cvmx_bootinfo_t *) ((intptr_t)octeon_bootinfo | MIPS_KSEG0_START);
+ if (octeon_bootinfo->major_version != 1)
+ panic("Incompatible CVMX descriptor from bootloader: %d.%d %p",
+ (int) octeon_bootinfo->major_version,
+ (int) octeon_bootinfo->minor_version, octeon_bootinfo);
+
+ phy_mem_desc_ptr =
+ (void *)MIPS_PHYS_TO_KSEG0(octeon_bootinfo->phy_mem_desc_addr);
+ cvmx_sysinfo_minimal_initialize(phy_mem_desc_ptr,
+ octeon_bootinfo->board_type,
+ octeon_bootinfo->board_rev_major,
+ octeon_bootinfo->board_rev_minor,
+ octeon_bootinfo->eclock_hz);
}
static void
octeon_boot_params_init(register_t ptr)
{
- int bad_desc = 1;
-
- if (ptr != 0 && ptr < MAX_APP_DESC_ADDR) {
- app_desc_ptr = (octeon_boot_descriptor_t *)(intptr_t)ptr;
- octeon_bd_ver = app_desc_ptr->desc_version;
- if (app_desc_ptr->desc_version < 6)
- panic("Your boot code is too old to be supported.\n");
- if (app_desc_ptr->desc_version >= 6)
- bad_desc = octeon_process_app_desc_ver_6();
- }
- if (bad_desc)
- octeon_process_app_desc_ver_unknown();
+ if (ptr == 0 || ptr >= MAX_APP_DESC_ADDR)
+ panic("app descriptor passed at invalid address %#jx",
+ (uintmax_t)ptr);
+
+ app_desc_ptr = (octeon_boot_descriptor_t *)(intptr_t)ptr;
+ if (app_desc_ptr->desc_version < 6)
+ panic("Your boot code is too old to be supported.");
+ octeon_process_app_desc_ver_6();
+
+ KASSERT(octeon_bootinfo != NULL, ("octeon_bootinfo should be set"));
+
+ if (cvmx_sysinfo_get()->phy_mem_desc_ptr == NULL)
+ panic("Your boot loader did not supply a memory descriptor.");
+ cvmx_bootmem_init(cvmx_sysinfo_get()->phy_mem_desc_ptr);
printf("Boot Descriptor Ver: %u -> %u/%u",
- octeon_bd_ver, octeon_cvmx_bd_ver/100, octeon_cvmx_bd_ver%100);
- printf(" CPU clock: %uMHz Core Mask: %#x\n", octeon_cpu_clock/1000000, octeon_core_mask);
- printf(" Dram: %u MB", (uint32_t)(octeon_dram >> 20));
+ app_desc_ptr->desc_version, octeon_bootinfo->major_version,
+ octeon_bootinfo->minor_version);
+ printf(" CPU clock: %uMHz Core Mask: %#x\n",
+ cvmx_sysinfo_get()->cpu_clock_hz / 1000000,
+ cvmx_sysinfo_get()->core_mask);
printf(" Board Type: %u Revision: %u/%u\n",
- octeon_board_type, octeon_board_rev_major, octeon_board_rev_minor);
- printf(" Octeon Chip: %u Rev %u/%u",
- octeon_chip_type, octeon_chip_rev_major, octeon_chip_rev_minor);
+ cvmx_sysinfo_get()->board_type,
+ cvmx_sysinfo_get()->board_rev_major,
+ cvmx_sysinfo_get()->board_rev_minor);
printf(" Mac Address %02X.%02X.%02X.%02X.%02X.%02X (%d)\n",
- octeon_mac_addr[0], octeon_mac_addr[1], octeon_mac_addr[2],
- octeon_mac_addr[3], octeon_mac_addr[4], octeon_mac_addr[5],
- octeon_mac_addr_count);
+ octeon_bootinfo->mac_addr_base[0],
+ octeon_bootinfo->mac_addr_base[1],
+ octeon_bootinfo->mac_addr_base[2],
+ octeon_bootinfo->mac_addr_base[3],
+ octeon_bootinfo->mac_addr_base[4],
+ octeon_bootinfo->mac_addr_base[5],
+ octeon_bootinfo->mac_addr_count);
+
+#if defined(OCTEON_BOARD_CAPK_0100ND)
+ if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_CN3010_EVB_HS5)
+ printf("Compiled for CAPK-0100ND, but board type is %s\n",
+ cvmx_board_type_to_string(cvmx_sysinfo_get()->board_type));
+#else
+ printf("Board: %s\n",
+ cvmx_board_type_to_string(cvmx_sysinfo_get()->board_type));
+#endif
+ printf("Model: %s\n", octeon_model_get_string(cvmx_get_proc_id()));
}
/* impEND: This stuff should move back into the Cavium SDK */
diff --git a/sys/mips/cavium/octeon_mp.c b/sys/mips/cavium/octeon_mp.c
index 8ded87e..a0eae2c 100644
--- a/sys/mips/cavium/octeon_mp.c
+++ b/sys/mips/cavium/octeon_mp.c
@@ -31,19 +31,27 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/kernel.h>
+#include <sys/smp.h>
#include <sys/systm.h>
#include <machine/hwfunc.h>
+#include <machine/md_var.h>
#include <machine/smp.h>
#include <mips/cavium/octeon_pcmap_regs.h>
+#include <contrib/octeon-sdk/cvmx.h>
+#include <contrib/octeon-sdk/cvmx-interrupt.h>
+
+/* XXX */
+extern cvmx_bootinfo_t *octeon_bootinfo;
+
unsigned octeon_ap_boot = ~0;
void
platform_ipi_send(int cpuid)
{
- oct_write64(OCTEON_CIU_MBOX_SETX(cpuid), 1);
+ cvmx_write_csr(CVMX_CIU_MBOX_SETX(cpuid), 1);
mips_wbflush();
}
@@ -52,9 +60,9 @@ platform_ipi_clear(void)
{
uint64_t action;
- action = oct_read64(OCTEON_CIU_MBOX_CLRX(PCPU_GET(cpuid)));
+ action = cvmx_read_csr(CVMX_CIU_MBOX_CLRX(PCPU_GET(cpuid)));
KASSERT(action == 1, ("unexpected IPIs: %#jx", (uintmax_t)action));
- oct_write64(OCTEON_CIU_MBOX_CLRX(PCPU_GET(cpuid)), action);
+ cvmx_write_csr(CVMX_CIU_MBOX_CLRX(PCPU_GET(cpuid)), action);
}
int
@@ -66,18 +74,29 @@ platform_ipi_intrnum(void)
void
platform_init_ap(int cpuid)
{
+ unsigned ipi_int_mask, clock_int_mask;
+
/*
* Set the exception base.
*/
mips_wr_ebase(0x80000000 | cpuid);
/*
- * Set up interrupts, clear IPIs and unmask the IPI interrupt.
+ * Clear any pending IPIs.
+ */
+ cvmx_write_csr(CVMX_CIU_MBOX_CLRX(cpuid), 0xffffffff);
+
+ /*
+ * Set up interrupts.
*/
octeon_ciu_reset();
- oct_write64(OCTEON_CIU_MBOX_CLRX(cpuid), 0xffffffff);
- ciu_enable_interrupts(cpuid, CIU_INT_1, CIU_EN_0, OCTEON_CIU_ENABLE_MBOX_INTR, CIU_MIPS_IP3);
+ /*
+ * Unmask the clock and ipi interrupts.
+ */
+ clock_int_mask = hard_int_mask(5);
+ ipi_int_mask = hard_int_mask(platform_ipi_intrnum());
+ set_intr_mask(MIPS_SR_INT_MASK & ~(ipi_int_mask | clock_int_mask));
mips_wbflush();
}
@@ -85,7 +104,13 @@ platform_init_ap(int cpuid)
int
platform_num_processors(void)
{
- return (fls(octeon_core_mask));
+ return (bitcount32(octeon_bootinfo->core_mask));
+}
+
+struct cpu_group *
+platform_smp_topo(void)
+{
+ return (smp_topo_none());
}
int
diff --git a/sys/mips/cavium/octeon_pcmap_regs.h b/sys/mips/cavium/octeon_pcmap_regs.h
index 0ee1a73e..f9ee4df 100644
--- a/sys/mips/cavium/octeon_pcmap_regs.h
+++ b/sys/mips/cavium/octeon_pcmap_regs.h
@@ -46,42 +46,12 @@
#ifndef __OCTEON_PCMAP_REGS_H__
#define __OCTEON_PCMAP_REGS_H__
-#include "opt_cputype.h"
-
-#define OCTEON_CACHE_LINE_SIZE 0x80 /* 128 bytes cache line size */
-#define IS_OCTEON_ALIGNED(p) (!((u_long)(p) & 0x7f))
-#define OCTEON_ALIGN(p) (((u_long)(p) + ((OCTEON_CACHE_LINE_SIZE) - 1)) & ~((OCTEON_CACHE_LINE_SIZE) - 1))
-
#ifndef LOCORE
/*
* Utility inlines & macros
*/
-/* turn the variable name into a string */
-#define OCTEON_TMP_STR(x) OCTEON_TMP_STR2(x)
-#define OCTEON_TMP_STR2(x) #x
-
-#define OCTEON_PREFETCH_PREF0(address, offset) \
- __asm __volatile ( ".set mips64\n" \
- ".set noreorder\n" \
- "pref 0, " OCTEON_TMP_STR(offset) "(%0)\n" \
- ".set reorder\n" \
- ".set mips0\n" \
- : \
- : "r" (address) );
-
-#define OCTEON_PREFETCH(address, offset) OCTEON_PREFETCH_PREF0(address,offset)
-
-#define OCTEON_PREFETCH0(address) OCTEON_PREFETCH(address, 0)
-#define OCTEON_PREFETCH128(address) OCTEON_PREFETCH(address, 128)
-
-#define OCTEON_SYNCIOBDMA __asm __volatile (".word 0x8f" : : :"memory")
-
-#define OCTEON_SYNCW __asm __volatile (".word 0x10f" : : )
-#define OCTEON_SYNCW __asm __volatile (".word 0x10f" : : )
-#define OCTEON_SYNCWS __asm __volatile (".word 0x14f" : : )
-
#if defined(__mips_n64)
#define oct_write64(a, v) (*(volatile uint64_t *)(a) = (uint64_t)(v))
#define oct_write8_x8(a, v) (*(volatile uint8_t *)(a) = (uint8_t)(v))
@@ -305,398 +275,6 @@ static inline void oct_write32 (uint64_t csr_addr, uint32_t val32)
#define oct_readint32(a) ((int32_t)oct_read32((a)))
-#define OCTEON_HW_BASE ((volatile uint64_t *) 0L)
-#define OCTEON_REG_OFFSET (-4 * 1024ll) /* local scratchpad reg base */
-#define OCTEON_SCRATCH_BASE ((volatile uint8_t *)(OCTEON_HW_BASE + \
- OCTEON_REG_OFFSET))
-
-#define OCTEON_SCR_SCRATCH 8
-#define OCTEON_SCRATCH_0 16
-#define OCTEON_SCRATCH_1 24
-#define OCTEON_SCRATCH_2 32
-
-
-
-#define OCTEON_CHORD_HEX(dest_ptr) \
- ({ __asm __volatile( \
- ".set push\n" \
- ".set mips3\n" \
- ".set noreorder\n" \
- ".set noat\n" \
- ".word 0x7c02f03b \n"\
- "nop\n" \
- "nop\n" \
- "nop\n" \
- "nop\n" \
- "sd $2,0(%0)\n" \
- ".set pop" \
- : /* no outputs */ : "r" (dest_ptr) : "$2"); \
- })
-
-static inline uint64_t oct_scratch_read64 (uint64_t address)
-{
- return(*((volatile uint64_t *)(OCTEON_SCRATCH_BASE + address)));
-}
-
-static inline void oct_scratch_write64 (uint64_t address, uint64_t value)
-{
- *((volatile uint64_t *)(OCTEON_SCRATCH_BASE + address)) = value;
-}
-
-
-/*
- * Octeon Address Space Definitions
- */
-typedef enum {
- OCTEON_MIPS_SPACE_XKSEG = 3LL,
- OCTEON_MIPS_SPACE_XKPHYS = 2LL,
- OCTEON_MIPS_SPACE_XSSEG = 1LL,
- OCTEON_MIPS_SPACE_XUSEG = 0LL
-} octeon_mips_space_t;
-
-typedef enum {
- OCTEON_MIPS_XKSEG_SPACE_KSEG0 = 0LL,
- OCTEON_MIPS_XKSEG_SPACE_KSEG1 = 1LL,
- OCTEON_MIPS_XKSEG_SPACE_SSEG = 2LL,
- OCTEON_MIPS_XKSEG_SPACE_KSEG3 = 3LL
-} octeon_mips_xkseg_space_t;
-
-
-/*
-***********************************************************************
- * 32 bit mode alert
- * The kseg0 calc below might fail in xkphys.
- */
-
-/*
- * We limit the allocated device physical blocks to low mem. So use Kseg0
- */
-
-/*
- * Need to go back to kernel to find v->p mappings & vice-versa
- * We are getting non 1-1 mappings.
- * #define OCTEON_PTR2PHYS(addr) ((unsigned long) addr & 0x7fffffff)
- */
-#define OCTEON_PTR2PHYS(addr) octeon_ptr_to_phys(addr)
-
-
-
-/* PTR_SIZE == sizeof(uint32_t) */
-
-#if defined(__mips_n32) || defined(__mips_o32)
-#define mipsx_addr_size uint32_t // u_int64
-#define MIPSX_ADDR_SIZE_KSEGX_BIT_SHIFT 30 // 62
-#define MIPSX_ADDR_SIZE_KSEGX_MASK_REMOVED 0x1fffffff // 0x1fffffff
-#else
-#define mipsx_addr_size uint64_t
-#define MIPSX_ADDR_SIZE_KSEGX_BIT_SHIFT 62
-#define MIPSX_ADDR_SIZE_KSEGX_MASK_REMOVED 0x1fffffffffffffff
-#endif
-
-
-#define octeon_ptr_to_phys(ptr) \
- (((((mipsx_addr_size) ptr) >> MIPSX_ADDR_SIZE_KSEGX_BIT_SHIFT) == 2) ? \
- ((mipsx_addr_size) ptr & MIPSX_ADDR_SIZE_KSEGX_MASK_REMOVED) : \
- (vtophys(ptr)))
-
-#ifdef CODE_FOR_64_BIT_NEEDED
-static inline mipsx_addr_size octeon_ptr_to_phys (void *ptr)
-{
- if ((((mipsx_addr_size) ptr) >> MIPSX_ADDR_SIZE_KSEGX_BIT_SHIFT) == 2) {
- /*
- * KSEG0 based address ?
- */
- return ((mipsx_addr_size) ptr & MIPSX_ADDR_SIZE_KSEGX_MASK_REMOVED);
- } else {
- /*
- * Ask kernel/vm to give us the phys translation.
- */
- return (vtophys(ptr));
- }
-}
-#endif
-
-#define OCTEON_IO_SEG OCTEON_MIPS_SPACE_XKPHYS
-
-
-#define OCTEON_ADD_SEG(segment, add) ((((uint64_t)segment) << 62) | (add))
-
-#define OCTEON_ADD_IO_SEG(add) OCTEON_ADD_SEG(OCTEON_IO_SEG, (add))
-#define OCTEON_ADDR_DID(did) (OCTEON_ADDR_DIDSPACE(did) << 40)
-#define OCTEON_ADDR_DIDSPACE(did) (((OCTEON_IO_SEG) << 22) | ((1ULL) << 8) | (did))
-#define OCTEON_ADDR_FULL_DID(did,subdid) (((did) << 3) | (subdid))
-
-
-#define OCTEON_CIU_PP_RST OCTEON_ADD_IO_SEG(0x0001070000000700ull)
-#define OCTEON_CIU_SOFT_RST OCTEON_ADD_IO_SEG(0x0001070000000740ull)
-#define OCTEON_OCTEON_DID_TAG 12ULL
-
-/*
- * octeon_addr_t
- */
-typedef union {
- uint64_t word64;
-
- struct {
- octeon_mips_space_t R : 2;
- uint64_t offset :62;
- } sva; // mapped or unmapped virtual address
-
- struct {
- uint64_t zeroes :33;
- uint64_t offset :31;
- } suseg; // mapped USEG virtual addresses (typically)
-
- struct {
- uint64_t ones :33;
- octeon_mips_xkseg_space_t sp : 2;
- uint64_t offset :29;
- } sxkseg; // mapped or unmapped virtual address
-
- struct {
- octeon_mips_space_t R :2; // CVMX_MIPS_SPACE_XKPHYS in this case
- uint64_t cca : 3; // ignored by octeon
- uint64_t mbz :10;
- uint64_t pa :49; // physical address
- } sxkphys; // physical address accessed through xkphys unmapped virtual address
-
- struct {
- uint64_t mbz :15;
- uint64_t is_io : 1; // if set, the address is uncached and resides on MCB bus
- uint64_t did : 8; // the hardware ignores this field when is_io==0, else device ID
- uint64_t unaddr: 4; // the hardware ignores <39:36> in Octeon I
- uint64_t offset :36;
- } sphys; // physical address
-
- struct {
- uint64_t zeroes :24; // techically, <47:40> are dont-cares
- uint64_t unaddr: 4; // the hardware ignores <39:36> in Octeon I
- uint64_t offset :36;
- } smem; // physical mem address
-
- struct {
- uint64_t mem_region :2;
- uint64_t mbz :13;
- uint64_t is_io : 1; // 1 in this case
- uint64_t did : 8; // the hardware ignores this field when is_io==0, else device ID
- uint64_t unaddr: 4; // the hardware ignores <39:36> in Octeon I
- uint64_t offset :36;
- } sio; // physical IO address
-
- struct {
- uint64_t didspace : 24;
- uint64_t unused : 40;
- } sfilldidspace;
-
-} octeon_addr_t;
-
-
-typedef union {
- uint64_t word64;
- struct {
- uint32_t word32hi;
- uint32_t word32lo;
- } bits;
-} octeon_word_t;
-
-
-
-
-/*
- * octeon_build_io_address
- *
- * Builds a memory address for I/O based on the Major 5bits and Sub DID 3bits
- */
-static inline uint64_t octeon_build_io_address (uint64_t major_did,
- uint64_t sub_did)
-{
- return ((0x1ull << 48) | (major_did << 43) | (sub_did << 40));
-}
-
-/*
- * octeon_build_mask
- *
- * Builds a bit mask given the required size in bits.
- *
- * @param bits Number of bits in the mask
- * @return The mask
- */
-static inline uint64_t octeon_build_mask (uint64_t bits)
-{
- return ~((~0x0ull) << bits);
-}
-
-/*
- * octeon_build_bits
- *
- * Perform mask and shift to place the supplied value into
- * the supplied bit rage.
- *
- * Example: octeon_build_bits(39,24,value)
- * <pre>
- * 6 5 4 3 3 2 1
- * 3 5 7 9 1 3 5 7 0
- * +-------+-------+-------+-------+-------+-------+-------+------+
- * 000000000000000000000000___________value000000000000000000000000
- * </pre>
- *
- * @param high_bit Highest bit value can occupy (inclusive) 0-63
- * @param low_bit Lowest bit value can occupy inclusive 0-high_bit
- * @param value Value to use
- * @return Value masked and shifted
- */
-static inline uint64_t octeon_build_bits (uint64_t high_bit, uint64_t low_bit,
- uint64_t value)
-{
- return ((value & octeon_build_mask(high_bit - low_bit + 1)) << low_bit);
-}
-
-
-/********************** simple spinlocks ***************/
-typedef struct {
- volatile uint32_t value;
-} octeon_spinlock_t;
-
-// note - macros not expanded in inline ASM, so values hardcoded
-#define OCTEON_SPINLOCK_UNLOCKED_VAL 0
-#define OCTEON_SPINLOCK_LOCKED_VAL 1
-
-/**
- * Initialize a spinlock
- *
- * @param lock Lock to initialize
- */
-static inline void octeon_spinlock_init(octeon_spinlock_t *lock)
-{
- lock->value = OCTEON_SPINLOCK_UNLOCKED_VAL;
-}
-/**
- * Releases lock
- *
- * @param lock pointer to lock structure
- */
-static inline void octeon_spinlock_unlock(octeon_spinlock_t *lock)
-{
- OCTEON_SYNCWS;
-
- lock->value = 0;
- OCTEON_SYNCWS;
-}
-
-/**
- * Gets lock, spins until lock is taken
- *
- * @param lock pointer to lock structure
- */
-static inline void octeon_spinlock_lock(octeon_spinlock_t *lock)
-{
- unsigned int tmp;
- __asm __volatile(
- ".set noreorder \n"
- "1: ll %1, %0 \n"
- " bnez %1, 1b \n"
- " li %1, 1 \n"
- " sc %1, %0 \n"
- " beqz %1, 1b \n"
- " nop \n"
- ".set reorder \n"
- : "+m" (lock->value), "=&r" (tmp )
- :
- : "memory");
-}
-
-/********************** end simple spinlocks ***************/
-
-
-
-/* ------------------------------------------------------------------- *
- * octeon_get_chipid() *
- * ------------------------------------------------------------------- */
-#define OCTEON_CN31XX_CHIP 0x000d0100
-#define OCTEON_CN30XX_CHIP 0x000d0200
-#define OCTEON_CN3020_CHIP 0x000d0112
-#define OCTEON_CN5020_CHIP 0x000d0601
-
-static inline uint32_t octeon_get_chipid(void)
-{
- uint32_t id;
-
- __asm __volatile ("mfc0 %0, $15,0" : "=r" (id));
-
- return (id);
-}
-
-
-static inline uint32_t octeon_get_except_base_reg (void)
-{
- uint32_t tmp;
-
- __asm volatile (
- " .set mips64r2 \n"
- " .set noreorder \n"
- " mfc0 %0, $15, 1 \n"
- " .set reorder \n"
- : "=&r" (tmp) : );
-
- return(tmp);
-}
-
-
-
-
-static inline unsigned int get_coremask (void)
-{
- return(~(oct_read64(OCTEON_CIU_PP_RST)) & 0xffff);
-}
-
-
-static inline uint32_t octeon_get_core_num (void)
-{
-
- return (0x3FF & octeon_get_except_base_reg());
-}
-
-
-static inline uint64_t octeon_get_cycle(void)
-{
-
-/* ABI == 32 */
-
- uint32_t tmp_low, tmp_hi;
-
- __asm __volatile (
- " .set push \n"
- " .set mips64r2 \n"
- " .set noreorder \n"
- " rdhwr %[tmpl], $31 \n"
- " dadd %[tmph], %[tmpl], $0 \n"
- " dsrl %[tmph], 32 \n"
- " dsll %[tmpl], 32 \n"
- " dsrl %[tmpl], 32 \n"
- " .set pop \n"
- : [tmpl] "=&r" (tmp_low), [tmph] "=&r" (tmp_hi) : );
-
- return(((uint64_t)tmp_hi << 32) + tmp_low);
-}
-
-
-/**
- * Wait for the specified number of cycle
- *
- * @param cycles
- */
-static inline void octeon_wait (uint64_t cycles)
-{
- uint64_t done = octeon_get_cycle() + cycles;
-
- while (octeon_get_cycle() < done)
- {
- /* Spin */
- }
-}
-
-
-
/*
* octeon_machdep.c
*
@@ -710,197 +288,13 @@ extern void octeon_reset(void);
extern void octeon_led_write_char0(char val);
extern void octeon_led_run_wheel(int *pos, int led_position);
extern void octeon_debug_symbol(void);
-extern void mips_disable_interrupt_controls(void);
-extern uint32_t octeon_cpu_clock;
-extern uint64_t octeon_dram;
-extern uint32_t octeon_bd_ver, octeon_board_rev_major, octeon_board_rev_minor, octeon_board_type;
-extern uint8_t octeon_mac_addr[6];
-extern int octeon_core_mask, octeon_mac_addr_count, octeon_chip_rev_major, octeon_chip_rev_minor, octeon_chip_type;
-extern void bzero_64(void *str, size_t len);
-extern void bzero_32(void *str, size_t len);
-extern void bzero_16(void *str, size_t len);
-extern void bzero_old(void *str, size_t len);
extern void octeon_ciu_reset(void);
-extern void ciu_disable_intr(int core_num, int intx, int enx);
-extern void ciu_enable_interrupts (int core_num, int intx, int enx, uint64_t set_these_interrupt_bits, int ciu_ip);
-extern void ciu_clear_int_summary(int core_num, int intx, int enx, uint64_t write_bits);
-extern uint64_t ciu_get_int_summary(int core_num, int intx, int enx);
-extern void octeon_ciu_start_gtimer(int timer, u_int one_shot, uint64_t time_cycles);
-extern void octeon_ciu_stop_gtimer(int timer);
-extern int octeon_board_real(void);
-extern unsigned long octeon_get_clock_rate(void);
-
-typedef union {
- uint64_t word64;
- struct {
- uint64_t reserved : 27; /* Not used */
- uint64_t one_shot : 1; /* Oneshot ? */
- uint64_t len : 36; /* len of timer in clock cycles - 1 */
- } bits;
-} octeon_ciu_gentimer;
-
-
-
+extern int octeon_is_simulation(void);
#endif /* LOCORE */
-
-/*
- * R4K Address space definitions
- */
-#define ADRSPC_K0BASE (0x80000000)
-#define ADRSPC_K0SIZE (0x20000000)
-#define ADRSPC_K1BASE (0xA0000000)
-#define ADRSPC_K1SIZE (0x20000000)
-#define ADRSPC_KSBASE (0xC0000000)
-#define ADRSPC_KSSIZE (0x20000000)
-#define ADRSPC_K3BASE (0xE0000000)
-#define ADRSPC_K3SIZE (0x20000000)
-#define ADRSPC_KUBASE (0x00000000)
-#define ADRSPC_KUSIZE (0x80000000)
-#define KSEG_MSB_ADDR 0xFFFFFFFF
-
-
-
-#define OCTEON_CLOCK_DEFAULT (500 * 1000 * 1000)
-
-
-/*
- * Octeon Boot Bus BIST Status
- * Mostly used for dummy read to ensure all prev I/Os are write-complete.
- */
-#define OCTEON_MIO_BOOT_BIST_STAT 0x80011800000000F8ull
-
-/*
- * Octeon UART unit
- */
-#define OCTEON_MIO_UART0 0x8001180000000800ull
-#define OCTEON_MIO_UART1 0x8001180000000C00ull
-#define OCTEON_MIO_UART0_THR 0x8001180000000840ull
-#define OCTEON_MIO_UART1_THR 0x8001180000000C40ull
-#define OCTEON_MIO_UART0_LSR 0x8001180000000828ull
-#define OCTEON_MIO_UART1_LSR 0x8001180000000C28ull
-#define OCTEON_MIO_UART0_RBR 0x8001180000000800ull
-#define OCTEON_MIO_UART1_RBR 0x8001180000000C00ull
-#define OCTEON_MIO_UART0_USR 0x8001180000000938ull
-#define OCTEON_MIO_UART1_USR 0x8001180000000D38ull
-#define OCTEON_MIO_ADDR_HI24 0x800118
-#define OCTEON_MIO_UART_SIZE 0x400ull
-
-
/*
* EBT3000 LED Unit
*/
#define OCTEON_CHAR_LED_BASE_ADDR (0x1d020000 | (0x1ffffffffull << 31))
-#define OCTEON_FPA_QUEUES 8
-
-/*
- * Octeon FPA I/O Registers
- */
-#define OCTEON_FPA_CTL_STATUS 0x8001180028000050ull
-#define OCTEON_FPA_FPF_SIZE 0x8001180028000058ull
-#define OCTEON_FPA_FPF_MARKS 0x8001180028000000ull
-#define OCTEON_FPA_INT_SUMMARY 0x8001180028000040ull
-#define OCTEON_FPA_INT_ENABLE 0x8001180028000048ull
-#define OCTEON_FPA_QUEUE_AVAILABLE 0x8001180028000098ull
-#define OCTEON_FPA_PAGE_INDEX 0x80011800280000f0ull
-
-/*
- * Octeon PKO Unit
- */
-#define OCTEON_PKO_REG_FLAGS 0x8001180050000000ull
-#define OCTEON_PKO_REG_READ_IDX 0x8001180050000008ull
-#define OCTEON_PKO_CMD_BUF 0x8001180050000010ull
-#define OCTEON_PKO_GMX_PORT_MODE 0x8001180050000018ull
-#define OCTEON_PKO_REG_CRC_ENABLE 0x8001180050000020ull
-#define OCTEON_PKO_QUEUE_MODE 0x8001180050000048ull
-#define OCTEON_PKO_MEM_QUEUE_PTRS 0x8001180050001000ull
-#define OCTEON_PKO_MEM_COUNT0 0x8001180050001080ull
-#define OCTEON_PKO_MEM_COUNT1 0x8001180050001088ull
-#define OCTEON_PKO_MEM_DEBUG0 0x8001180050001100ull
-#define OCTEON_PKO_MEM_DEBUG1 0x8001180050001108ull
-#define OCTEON_PKO_MEM_DEBUG2 0x8001180050001110ull
-#define OCTEON_PKO_MEM_DEBUG3 0x8001180050001118ull
-#define OCTEON_PKO_MEM_DEBUG4 0x8001180050001120ull
-#define OCTEON_PKO_MEM_DEBUG5 0x8001180050001128ull
-#define OCTEON_PKO_MEM_DEBUG6 0x8001180050001130ull
-#define OCTEON_PKO_MEM_DEBUG7 0x8001180050001138ull
-#define OCTEON_PKO_MEM_DEBUG8 0x8001180050001140ull
-#define OCTEON_PKO_MEM_DEBUG9 0x8001180050001148ull
-
-
-/*
- * Octeon IPD Unit
- */
-#define OCTEON_IPD_1ST_MBUFF_SKIP 0x80014F0000000000ull
-#define OCTEON_IPD_NOT_1ST_MBUFF_SKIP 0x80014F0000000008ull
-#define OCTEON_IPD_PACKET_MBUFF_SIZE 0x80014F0000000010ull
-#define OCTEON_IPD_1ST_NEXT_PTR_BACK 0x80014F0000000150ull
-#define OCTEON_IPD_2ND_NEXT_PTR_BACK 0x80014F0000000158ull
-#define OCTEON_IPD_WQE_FPA_QUEUE 0x80014F0000000020ull
-#define OCTEON_IPD_CTL_STATUS 0x80014F0000000018ull
-#define OCTEON_IPD_QOSX_RED_MARKS(queue) (0x80014F0000000178ull + ((queue) * 8))
-#define OCTEON_IPD_RED_Q_PARAM(queue) (0x80014F00000002E0ull + ((queue) * 8))
-#define OCTEON_IPD_PORT_BP_PAGE_COUNT(port) (0x80014F0000000028ull + ((port) * 8))
-#define OCTEON_IPD_BP_PORT_RED_END 0x80014F0000000328ull
-#define OCTEON_IPD_RED_PORT_ENABLE 0x80014F00000002D8ull
-
-/*
- * Octeon CIU Unit
- */
-#define OCTEON_CIU_ENABLE_BASE_ADDR 0x8001070000000200ull
-#define OCTEON_CIU_SUMMARY_BASE_ADDR 0x8001070000000000ull
-#define OCTEON_CIU_SUMMARY_INT1_ADDR 0x8001070000000108ull
-
-#define OCTEON_CIU_MBOX_SETX(offset) (0x8001070000000600ull+((offset)*8))
-#define OCTEON_CIU_MBOX_CLRX(offset) (0x8001070000000680ull+((offset)*8))
-#define OCTEON_CIU_ENABLE_MBOX_INTR 0x0000000300000000ull /* bits 32, 33 */
-
-#define CIU_MIPS_IP2 0
-#define CIU_MIPS_IP3 1
-
-#define CIU_INT_0 CIU_MIPS_IP2
-#define CIU_INT_1 CIU_MIPS_IP3
-
-#define CIU_EN_0 0
-#define CIU_EN_1 1
-
-#define CIU_THIS_CORE -1
-
-#define CIU_UART_BITS_UART0 (0x1ull << 34) // Bit 34
-#define CIU_UART_BITS_UART1 (0x1ull << 35) // Bit 35
-#define CIU_GENTIMER_BITS_ENABLE(timer) (0x1ull << (52 + (timer))) // Bit 52..55
-
-#define CIU_GENTIMER_NUM_0 0
-#define CIU_GENTIMER_NUM_1 1
-#define CIU_GENTIMER_NUM_2 2
-#define CIU_GENTIMER_NUM_3 3
-#define OCTEON_GENTIMER_ONESHOT 1
-#define OCTEON_GENTIMER_PERIODIC 0
-
-#define OCTEON_CIU_GENTIMER_ADDR(timer) (0x8001070000000480ull + ((timer) * 0x8))
-
-
-#define OCTEON_GENTIMER_LEN_1MS (0x7a120ull) /* Back of envelope. 500Mhz Octeon */ // FIXME IF WRONG
-#define OCTEON_GENTIMER_LEN_1SEC ((OCTEON_GENTIMER_LEN_1MS) * 1000)
-
-/*
- * Physical Memory Banks
- */
-/* 1st BANK */
-#define OCTEON_DRAM_FIRST_256_START 0x00000000ull
-#define OCTEON_DRAM_FIRST_256_END (0x10000000ull - 1ull)
-#define OCTEON_DRAM_RESERVED_END 0X1FFF000ULL /* 32 Meg Reserved for Mips Kernel MD Ops */
-#define OCTEON_DRAM_FIRST_BANK_SIZE (OCTEON_DRAM_FIRST_256_END - OCTEON_DRAM_FIRST_256_START + 1)
-
-/* 2nd BANK */
-#define OCTEON_DRAM_SECOND_256_START (0x0000000410000000ull)
-#define OCTEON_DRAM_SECOND_256_END (0x0000000420000000ull - 1ull) /* Requires 64 bit paddr */
-#define OCTEON_DRAM_SECOND_BANK_SIZE (OCTEON_DRAM_SECOND_256_END - OCTEON_DRAM_SECOND_256_START + 1ull)
-
-/* 3rd BANK */
-#define OCTEON_DRAM_ABOVE_512_START 0x20000000ull
-#define OCTEON_DRAM_ABOVE_512_END (0x0000000300000000ull - 1ull) /* To be calculated as remaining */
-#define OCTEON_DRAM_THIRD_BANK_SIZE (OCTEON_DRAM_ABOVE_512_END - OCTEON_DRAM_ABOVE_512_START + 1ull)
-
#endif /* !OCTEON_PCMAP_REGS_H__ */
diff --git a/sys/mips/cavium/octeon_rnd.c b/sys/mips/cavium/octeon_rnd.c
new file mode 100644
index 0000000..634a4fa
--- /dev/null
+++ b/sys/mips/cavium/octeon_rnd.c
@@ -0,0 +1,137 @@
+/*-
+ * Copyright (c) 2010 Juli Mallett <jmallett@FreeBSD.org>
+ * 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.
+ *
+ * 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$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/clock.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/random.h>
+
+#include <contrib/octeon-sdk/cvmx.h>
+#include <contrib/octeon-sdk/cvmx-rng.h>
+
+/*
+ * XXX
+ * random_harvest(9) says to call it with no more than 16 bytes, but at least
+ * safe(4) seems to violate that rule.
+ */
+#define OCTEON_RND_WORDS 2
+
+struct octeon_rnd_softc {
+ uint64_t sc_entropy[OCTEON_RND_WORDS];
+ struct callout sc_callout;
+};
+
+static void octeon_rnd_identify(driver_t *drv, device_t parent);
+static int octeon_rnd_attach(device_t dev);
+static int octeon_rnd_probe(device_t dev);
+static int octeon_rnd_detach(device_t dev);
+
+static void octeon_rnd_harvest(void *);
+
+static device_method_t octeon_rnd_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_identify, octeon_rnd_identify),
+ DEVMETHOD(device_probe, octeon_rnd_probe),
+ DEVMETHOD(device_attach, octeon_rnd_attach),
+ DEVMETHOD(device_detach, octeon_rnd_detach),
+
+ { 0, 0 }
+};
+
+static driver_t octeon_rnd_driver = {
+ "rnd",
+ octeon_rnd_methods,
+ sizeof (struct octeon_rnd_softc)
+};
+static devclass_t octeon_rnd_devclass;
+DRIVER_MODULE(rnd, nexus, octeon_rnd_driver, octeon_rnd_devclass, 0, 0);
+
+static void
+octeon_rnd_identify(driver_t *drv, device_t parent)
+{
+ BUS_ADD_CHILD(parent, 0, "rnd", 0);
+}
+
+static int
+octeon_rnd_probe(device_t dev)
+{
+ if (device_get_unit(dev) != 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "Cavium Octeon Random Number Generator");
+ return (0);
+}
+
+static int
+octeon_rnd_attach(device_t dev)
+{
+ struct octeon_rnd_softc *sc;
+
+ sc = device_get_softc(dev);
+ callout_init(&sc->sc_callout, CALLOUT_MPSAFE);
+ callout_reset(&sc->sc_callout, hz * 5, octeon_rnd_harvest, sc);
+
+ cvmx_rng_enable();
+
+ return (0);
+}
+
+static int
+octeon_rnd_detach(device_t dev)
+{
+ struct octeon_rnd_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ callout_stop(&sc->sc_callout);
+
+ return (0);
+}
+
+static void
+octeon_rnd_harvest(void *arg)
+{
+ struct octeon_rnd_softc *sc;
+ unsigned i;
+
+ sc = arg;
+
+ for (i = 0; i < OCTEON_RND_WORDS; i++)
+ sc->sc_entropy[i] = cvmx_rng_get_random64();
+ random_harvest(sc->sc_entropy, sizeof sc->sc_entropy,
+ sizeof sc->sc_entropy * 8, 0, RANDOM_PURE);
+
+ callout_reset(&sc->sc_callout, hz * 5, octeon_rnd_harvest, sc);
+}
diff --git a/sys/mips/cavium/octeon_rtc.c b/sys/mips/cavium/octeon_rtc.c
new file mode 100644
index 0000000..ca2debd
--- /dev/null
+++ b/sys/mips/cavium/octeon_rtc.c
@@ -0,0 +1,130 @@
+/*-
+ * Copyright (c) 2010 Juli Mallett <jmallett@FreeBSD.org>
+ * 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.
+ *
+ * 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$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/clock.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+
+#include <contrib/octeon-sdk/cvmx.h>
+#include <contrib/octeon-sdk/cvmx-rtc.h>
+
+#include "clock_if.h"
+
+static int octeon_rtc_attach(device_t dev);
+static int octeon_rtc_probe(device_t dev);
+
+static int octeon_rtc_settime(device_t dev, struct timespec *ts);
+static int octeon_rtc_gettime(device_t dev, struct timespec *ts);
+
+static device_method_t octeon_rtc_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, octeon_rtc_probe),
+ DEVMETHOD(device_attach, octeon_rtc_attach),
+
+ /* clock interface */
+ DEVMETHOD(clock_gettime, octeon_rtc_gettime),
+ DEVMETHOD(clock_settime, octeon_rtc_settime),
+
+ { 0, 0 }
+};
+
+static driver_t octeon_rtc_driver = {
+ "rtc",
+ octeon_rtc_methods,
+ 0
+};
+static devclass_t octeon_rtc_devclass;
+DRIVER_MODULE(rtc, nexus, octeon_rtc_driver, octeon_rtc_devclass, 0, 0);
+
+static int
+octeon_rtc_probe(device_t dev)
+{
+ cvmx_rtc_options_t supported;
+
+ if (device_get_unit(dev) != 0)
+ return (ENXIO);
+
+ supported = cvmx_rtc_supported();
+ if (supported == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "Cavium Octeon Realtime Clock");
+ return (0);
+}
+
+static int
+octeon_rtc_attach(device_t dev)
+{
+ cvmx_rtc_options_t supported;
+
+ supported = cvmx_rtc_supported();
+ if ((supported & CVMX_RTC_READ) == 0)
+ return (ENXIO);
+
+ clock_register(dev, 1000000);
+ return (0);
+}
+
+static int
+octeon_rtc_settime(device_t dev, struct timespec *ts)
+{
+ cvmx_rtc_options_t supported;
+ uint32_t status;
+
+ supported = cvmx_rtc_supported();
+ if ((supported & CVMX_RTC_WRITE) == 0)
+ return (ENOTSUP);
+
+ status = cvmx_rtc_write(ts->tv_sec);
+ if (status != 0)
+ return (EINVAL);
+
+ return (0);
+}
+
+static int
+octeon_rtc_gettime(device_t dev, struct timespec *ts)
+{
+ uint32_t secs;
+
+ secs = cvmx_rtc_read();
+ if (secs == 0)
+ return (ENOTSUP);
+
+ ts->tv_sec = secs;
+ ts->tv_nsec = 0;
+
+ return (0);
+}
diff --git a/sys/mips/cavium/octopci.c b/sys/mips/cavium/octopci.c
new file mode 100644
index 0000000..0090790
--- /dev/null
+++ b/sys/mips/cavium/octopci.c
@@ -0,0 +1,402 @@
+/*-
+ * Copyright (c) 2010 Juli Mallett <jmallett@FreeBSD.org>
+ * 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.
+ *
+ * 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$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/interrupt.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/pmap.h>
+
+#include <contrib/octeon-sdk/cvmx.h>
+#include <contrib/octeon-sdk/cvmx-interrupt.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include <dev/pci/pcib_private.h>
+
+#include <mips/cavium/octopcireg.h>
+#include <mips/cavium/octopcivar.h>
+
+#include "pcib_if.h"
+
+struct octopci_softc {
+ device_t sc_dev;
+
+ unsigned sc_domain;
+ unsigned sc_bus;
+
+ struct rman sc_io;
+ struct rman sc_mem1;
+};
+
+static void octopci_identify(driver_t *, device_t);
+static int octopci_probe(device_t);
+static int octopci_attach(device_t);
+static int octopci_read_ivar(device_t, device_t, int,
+ uintptr_t *);
+static struct resource *octopci_alloc_resource(device_t, device_t, int, int *,
+ u_long, u_long, u_long, u_int);
+static int octopci_activate_resource(device_t, device_t, int, int,
+ struct resource *);
+static int octopci_maxslots(device_t);
+static uint32_t octopci_read_config(device_t, u_int, u_int, u_int, u_int, int);
+static void octopci_write_config(device_t, u_int, u_int, u_int, u_int,
+ uint32_t, int);
+static int octopci_route_interrupt(device_t, device_t, int);
+
+static uint64_t octopci_cs_addr(unsigned, unsigned, unsigned, unsigned);
+
+static void
+octopci_identify(driver_t *drv, device_t parent)
+{
+ BUS_ADD_CHILD(parent, 0, "pcib", 0);
+}
+
+static int
+octopci_probe(device_t dev)
+{
+ if (device_get_unit(dev) != 0)
+ return (ENXIO);
+ /* XXX Check sysinfo flag. */
+ device_set_desc(dev, "Cavium Octeon PCI bridge");
+ return (0);
+}
+
+static int
+octopci_attach(device_t dev)
+{
+ struct octopci_softc *sc;
+ int error;
+
+ /*
+ * XXX
+ * We currently rely on U-Boot to set up the PCI in host state. We
+ * should properly initialize the PCI bus here.
+ */
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+ sc->sc_domain = 0;
+ sc->sc_bus = 0;
+
+ sc->sc_io.rm_type = RMAN_ARRAY;
+ sc->sc_io.rm_descr = "Cavium Octeon PCI I/O Ports";
+ error = rman_init(&sc->sc_io);
+ if (error != 0)
+ return (error);
+
+ error = rman_manage_region(&sc->sc_io, CVMX_OCT_PCI_IO_BASE,
+ CVMX_OCT_PCI_IO_BASE + CVMX_OCT_PCI_IO_SIZE);
+ if (error != 0)
+ return (error);
+
+ sc->sc_mem1.rm_type = RMAN_ARRAY;
+ sc->sc_mem1.rm_descr = "Cavium Octeon PCI Memory";
+ error = rman_init(&sc->sc_mem1);
+ if (error != 0)
+ return (error);
+
+ error = rman_manage_region(&sc->sc_mem1, CVMX_OCT_PCI_MEM1_BASE,
+ CVMX_OCT_PCI_MEM1_BASE + CVMX_OCT_PCI_MEM1_SIZE);
+ if (error != 0)
+ return (error);
+
+ device_add_child(dev, "pci", 0);
+
+ return (bus_generic_attach(dev));
+}
+
+static int
+octopci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct octopci_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ switch (which) {
+ case PCIB_IVAR_DOMAIN:
+ *result = sc->sc_domain;
+ return (0);
+ case PCIB_IVAR_BUS:
+ *result = sc->sc_bus;
+ return (0);
+
+ }
+ return (ENOENT);
+}
+
+static struct resource *
+octopci_alloc_resource(device_t bus, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct octopci_softc *sc;
+ struct resource *res;
+ struct rman *rm;
+ int error;
+
+ sc = device_get_softc(bus);
+
+ switch (type) {
+ case SYS_RES_IRQ:
+ res = bus_generic_alloc_resource(bus, child, type, rid, start,
+ end, count, flags);
+ if (res != NULL)
+ return (res);
+ return (NULL);
+ case SYS_RES_MEMORY:
+ rm = &sc->sc_mem1;
+ break;
+ case SYS_RES_IOPORT:
+ rm = &sc->sc_io;
+ break;
+ default:
+ return (NULL);
+ }
+
+ res = rman_reserve_resource(rm, start, end, count, flags, child);
+ if (res == NULL)
+ return (NULL);
+
+ rman_set_rid(res, *rid);
+ rman_set_bustag(res, octopci_bus_space);
+
+ switch (type) {
+ case SYS_RES_MEMORY:
+ rman_set_bushandle(res, CVMX_ADDR_DID(CVMX_FULL_DID(CVMX_OCT_DID_PCI, CVMX_OCT_SUBDID_PCI_MEM1)) + rman_get_start(res));
+ break;
+ case SYS_RES_IOPORT:
+ rman_set_bushandle(res, CVMX_ADDR_DID(CVMX_FULL_DID(CVMX_OCT_DID_PCI, CVMX_OCT_SUBDID_PCI_IO)) + rman_get_start(res));
+ /*
+ * XXX
+ * We should just disallow use of io ports on !n64 since without
+ * 64-bit PTEs we can't even do a 32-bit virtual address
+ * mapped to them.
+ */
+#if 0
+ rman_set_virtual(res, (void *)rman_get_bushandle(res));
+#endif
+ break;
+ }
+
+ if ((flags & RF_ACTIVE) != 0) {
+ error = bus_activate_resource(child, type, *rid, res);
+ if (error != 0) {
+ rman_release_resource(res);
+ return (NULL);
+ }
+ }
+
+ return (res);
+}
+
+static int
+octopci_activate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *res)
+{
+ bus_space_handle_t bh;
+ int error;
+
+ switch (type) {
+ case SYS_RES_IRQ:
+ error = bus_generic_activate_resource(bus, child, type, rid,
+ res);
+ if (error != 0)
+ return (error);
+ return (0);
+ case SYS_RES_MEMORY:
+ case SYS_RES_IOPORT:
+ error = bus_space_map(rman_get_bustag(res),
+ rman_get_bushandle(res), rman_get_size(res), 0, &bh);
+ if (error != 0)
+ return (error);
+ rman_set_bushandle(res, bh);
+ break;
+ default:
+ return (ENXIO);
+ }
+
+ error = rman_activate_resource(res);
+ if (error != 0)
+ return (error);
+ return (0);
+}
+
+static int
+octopci_maxslots(device_t dev)
+{
+ return (PCI_SLOTMAX);
+}
+
+static uint32_t
+octopci_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
+ int bytes)
+{
+ struct octopci_softc *sc;
+ uint64_t addr;
+ uint32_t data;
+
+ sc = device_get_softc(dev);
+
+ addr = octopci_cs_addr(bus, slot, func, reg);
+
+ switch (bytes) {
+ case 4:
+ data = le32toh(cvmx_read64_uint32(addr));
+ return (data);
+ case 2:
+ data = le16toh(cvmx_read64_uint16(addr));
+ return (data);
+ case 1:
+ data = cvmx_read64_uint8(addr);
+ return (data);
+ default:
+ return ((uint32_t)-1);
+ }
+}
+
+static void
+octopci_write_config(device_t dev, u_int bus, u_int slot, u_int func,
+ u_int reg, uint32_t data, int bytes)
+{
+ struct octopci_softc *sc;
+ uint64_t addr;
+
+ sc = device_get_softc(dev);
+
+ addr = octopci_cs_addr(bus, slot, func, reg);
+
+ switch (bytes) {
+ case 4:
+ cvmx_write64_uint32(addr, htole32(data));
+ return;
+ case 2:
+ cvmx_write64_uint16(addr, htole16(data));
+ return;
+ case 1:
+ cvmx_write64_uint8(addr, data);
+ return;
+ default:
+ return;
+ }
+}
+
+static int
+octopci_route_interrupt(device_t dev, device_t child, int pin)
+{
+ struct octopci_softc *sc;
+ unsigned bus, slot, func;
+ unsigned irq;
+
+ sc = device_get_softc(dev);
+
+ bus = pci_get_bus(child);
+ slot = pci_get_slot(child);
+ func = pci_get_function(child);
+
+#if defined(OCTEON_VENDOR_LANNER)
+ if (slot < 32) {
+ if (slot == 3 || slot == 9)
+ irq = pin;
+ else
+ irq = pin - 1;
+ return (CVMX_IRQ_PCI_INT0 + (irq & 3));
+ }
+#endif
+
+ irq = slot + pin - 3;
+
+ return (CVMX_IRQ_PCI_INT0 + (irq & 3));
+}
+
+static uint64_t
+octopci_cs_addr(unsigned bus, unsigned slot, unsigned func, unsigned reg)
+{
+ octeon_pci_config_space_address_t pci_addr;
+
+ pci_addr.u64 = 0;
+ pci_addr.s.upper = 2;
+ pci_addr.s.io = 1;
+ pci_addr.s.did = 3;
+ pci_addr.s.subdid = CVMX_OCT_SUBDID_PCI_CFG;
+ pci_addr.s.endian_swap = 1;
+ pci_addr.s.bus = bus;
+ pci_addr.s.dev = slot;
+ pci_addr.s.func = func;
+ pci_addr.s.reg = reg;
+
+ return (pci_addr.u64);
+}
+
+static device_method_t octopci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_identify, octopci_identify),
+ DEVMETHOD(device_probe, octopci_probe),
+ DEVMETHOD(device_attach, octopci_attach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_read_ivar, octopci_read_ivar),
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_alloc_resource, octopci_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource,octopci_activate_resource),
+ DEVMETHOD(bus_deactivate_resource,bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+
+ /* pcib interface */
+ DEVMETHOD(pcib_maxslots, octopci_maxslots),
+ DEVMETHOD(pcib_read_config, octopci_read_config),
+ DEVMETHOD(pcib_write_config, octopci_write_config),
+ DEVMETHOD(pcib_route_interrupt, octopci_route_interrupt),
+
+ {0, 0}
+};
+
+static driver_t octopci_driver = {
+ "pcib",
+ octopci_methods,
+ sizeof(struct octopci_softc),
+};
+static devclass_t octopci_devclass;
+DRIVER_MODULE(octopci, ciu, octopci_driver, octopci_devclass, 0, 0);
diff --git a/sys/mips/cavium/octopci_bus_space.c b/sys/mips/cavium/octopci_bus_space.c
new file mode 100644
index 0000000..870fe32
--- /dev/null
+++ b/sys/mips/cavium/octopci_bus_space.c
@@ -0,0 +1,583 @@
+/* $NetBSD: bus.h,v 1.12 1997/10/01 08:25:15 fvdl Exp $ */
+/*-
+ * $Id: bus.h,v 1.6 2007/08/09 11:23:32 katta Exp $
+ *
+ * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * Copyright (c) 1996 Charles M. Hannum. All rights reserved.
+ * Copyright (c) 1996 Christopher G. Demetriou. 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ *
+ * from: src/sys/alpha/include/bus.h,v 1.5 1999/08/28 00:38:40 peter
+ * $FreeBSD$
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/ktr.h>
+#include <sys/endian.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_extern.h>
+
+#include <machine/bus.h>
+#include <machine/cache.h>
+
+#include <mips/cavium/octopcivar.h>
+
+#include <contrib/octeon-sdk/cvmx.h>
+
+static struct bus_space octopci_space = {
+ /* cookie */
+ (void *) 0,
+
+ /* mapping/unmapping */
+ octopci_bs_map,
+ octopci_bs_unmap,
+ octopci_bs_subregion,
+
+ /* allocation/deallocation */
+ NULL,
+ NULL,
+
+ /* barrier */
+ octopci_bs_barrier,
+
+ /* read (single) */
+ octopci_bs_r_1,
+ octopci_bs_r_2,
+ octopci_bs_r_4,
+ NULL,
+
+ /* read multiple */
+ octopci_bs_rm_1,
+ octopci_bs_rm_2,
+ octopci_bs_rm_4,
+ NULL,
+
+ /* read region */
+ octopci_bs_rr_1,
+ octopci_bs_rr_2,
+ octopci_bs_rr_4,
+ NULL,
+
+ /* write (single) */
+ octopci_bs_w_1,
+ octopci_bs_w_2,
+ octopci_bs_w_4,
+ NULL,
+
+ /* write multiple */
+ octopci_bs_wm_1,
+ octopci_bs_wm_2,
+ octopci_bs_wm_4,
+ NULL,
+
+ /* write region */
+ NULL,
+ octopci_bs_wr_2,
+ octopci_bs_wr_4,
+ NULL,
+
+ /* set multiple */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+
+ /* set region */
+ NULL,
+ octopci_bs_sr_2,
+ octopci_bs_sr_4,
+ NULL,
+
+ /* copy */
+ NULL,
+ octopci_bs_c_2,
+ NULL,
+ NULL,
+
+ /* read (single) stream */
+ octopci_bs_r_1,
+ octopci_bs_r_2,
+ octopci_bs_r_4,
+ NULL,
+
+ /* read multiple stream */
+ octopci_bs_rm_1,
+ octopci_bs_rm_2,
+ octopci_bs_rm_4,
+ NULL,
+
+ /* read region stream */
+ octopci_bs_rr_1,
+ octopci_bs_rr_2,
+ octopci_bs_rr_4,
+ NULL,
+
+ /* write (single) stream */
+ octopci_bs_w_1,
+ octopci_bs_w_2,
+ octopci_bs_w_4,
+ NULL,
+
+ /* write multiple stream */
+ octopci_bs_wm_1,
+ octopci_bs_wm_2,
+ octopci_bs_wm_4,
+ NULL,
+
+ /* write region stream */
+ NULL,
+ octopci_bs_wr_2,
+ octopci_bs_wr_4,
+ NULL,
+};
+
+#define rd8(a) cvmx_read64_uint8(a)
+#define rd16(a) le16toh(cvmx_read64_uint16(a))
+#define rd32(a) le32toh(cvmx_read64_uint32(a))
+#define wr8(a, v) cvmx_write64_uint8(a, v)
+#define wr16(a, v) cvmx_write64_uint16(a, htole16(v))
+#define wr32(a, v) cvmx_write64_uint32(a, htole32(v))
+
+/* octopci bus_space tag */
+bus_space_tag_t octopci_bus_space = &octopci_space;
+
+int
+octopci_bs_map(void *t __unused, bus_addr_t addr,
+ bus_size_t size __unused, int flags __unused,
+ bus_space_handle_t *bshp)
+{
+
+ *bshp = addr;
+ return (0);
+}
+
+void
+octopci_bs_unmap(void *t __unused, bus_space_handle_t bh __unused,
+ bus_size_t size __unused)
+{
+
+ /* Do nothing */
+}
+
+int
+octopci_bs_subregion(void *t __unused, bus_space_handle_t handle __unused,
+ bus_size_t offset __unused, bus_size_t size __unused,
+ bus_space_handle_t *nhandle __unused)
+{
+
+ printf("SUBREGION?!?!?!\n");
+ /* Do nothing */
+ return (0);
+}
+
+uint8_t
+octopci_bs_r_1(void *t, bus_space_handle_t handle,
+ bus_size_t offset)
+{
+
+ return (rd8(handle + offset));
+}
+
+uint16_t
+octopci_bs_r_2(void *t, bus_space_handle_t handle,
+ bus_size_t offset)
+{
+
+ return (rd16(handle + offset));
+}
+
+uint32_t
+octopci_bs_r_4(void *t, bus_space_handle_t handle,
+ bus_size_t offset)
+{
+
+ return (rd32(handle + offset));
+}
+
+
+void
+octopci_bs_rm_1(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, uint8_t *addr, size_t count)
+{
+
+ while (count--)
+ *addr++ = rd8(bsh + offset);
+}
+
+void
+octopci_bs_rm_2(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, uint16_t *addr, size_t count)
+{
+ bus_addr_t baddr = bsh + offset;
+
+ while (count--)
+ *addr++ = rd16(baddr);
+}
+
+void
+octopci_bs_rm_4(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, uint32_t *addr, size_t count)
+{
+ bus_addr_t baddr = bsh + offset;
+
+ while (count--)
+ *addr++ = rd32(baddr);
+}
+
+
+/*
+ * Read `count' 1, 2, 4, or 8 byte quantities from bus space
+ * described by tag/handle and starting at `offset' and copy into
+ * buffer provided.
+ */
+void
+octopci_bs_rr_1(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, uint8_t *addr, size_t count)
+{
+ bus_addr_t baddr = bsh + offset;
+
+ while (count--) {
+ *addr++ = rd8(baddr);
+ baddr += 1;
+ }
+}
+
+void
+octopci_bs_rr_2(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, uint16_t *addr, size_t count)
+{
+ bus_addr_t baddr = bsh + offset;
+
+ while (count--) {
+ *addr++ = rd16(baddr);
+ baddr += 2;
+ }
+}
+
+void
+octopci_bs_rr_4(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, uint32_t *addr, size_t count)
+{
+ bus_addr_t baddr = bsh + offset;
+
+ while (count--) {
+ *addr++ = rd32(baddr);
+ baddr += 4;
+ }
+}
+
+/*
+ * Write the 1, 2, 4, or 8 byte value `value' to bus space
+ * described by tag/handle/offset.
+ */
+void
+octopci_bs_w_1(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, uint8_t value)
+{
+
+ wr8(bsh + offset, value);
+}
+
+void
+octopci_bs_w_2(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, uint16_t value)
+{
+
+ wr16(bsh + offset, value);
+}
+
+void
+octopci_bs_w_4(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, uint32_t value)
+{
+
+ wr32(bsh + offset, value);
+}
+
+/*
+ * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
+ * provided to bus space described by tag/handle/offset.
+ */
+void
+octopci_bs_wm_1(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, const uint8_t *addr, size_t count)
+{
+ bus_addr_t baddr = bsh + offset;
+
+ while (count--)
+ wr8(baddr, *addr++);
+}
+
+void
+octopci_bs_wm_2(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, const uint16_t *addr, size_t count)
+{
+ bus_addr_t baddr = bsh + offset;
+
+ while (count--)
+ wr16(baddr, *addr++);
+}
+
+void
+octopci_bs_wm_4(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, const uint32_t *addr, size_t count)
+{
+ bus_addr_t baddr = bsh + offset;
+
+ while (count--)
+ wr32(baddr, *addr++);
+}
+
+/*
+ * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
+ * to bus space described by tag/handle starting at `offset'.
+ */
+void
+octopci_bs_wr_1(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, const uint8_t *addr, size_t count)
+{
+ bus_addr_t baddr = bsh + offset;
+
+ while (count--) {
+ wr8(baddr, *addr++);
+ baddr += 1;
+ }
+}
+
+void
+octopci_bs_wr_2(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, const uint16_t *addr, size_t count)
+{
+ bus_addr_t baddr = bsh + offset;
+
+ while (count--) {
+ wr16(baddr, *addr++);
+ baddr += 2;
+ }
+}
+
+void
+octopci_bs_wr_4(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, const uint32_t *addr, size_t count)
+{
+ bus_addr_t baddr = bsh + offset;
+
+ while (count--) {
+ wr32(baddr, *addr++);
+ baddr += 4;
+ }
+}
+
+/*
+ * Write the 1, 2, 4, or 8 byte value `val' to bus space described
+ * by tag/handle/offset `count' times.
+ */
+void
+octopci_bs_sm_1(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, uint8_t value, size_t count)
+{
+ bus_addr_t addr = bsh + offset;
+
+ while (count--)
+ wr8(addr, value);
+}
+
+void
+octopci_bs_sm_2(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, uint16_t value, size_t count)
+{
+ bus_addr_t addr = bsh + offset;
+
+ while (count--)
+ wr16(addr, value);
+}
+
+void
+octopci_bs_sm_4(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, uint32_t value, size_t count)
+{
+ bus_addr_t addr = bsh + offset;
+
+ while (count--)
+ wr32(addr, value);
+}
+
+/*
+ * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
+ * by tag/handle starting at `offset'.
+ */
+void
+octopci_bs_sr_1(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, uint8_t value, size_t count)
+{
+ bus_addr_t addr = bsh + offset;
+
+ for (; count != 0; count--, addr++)
+ wr8(addr, value);
+}
+
+void
+octopci_bs_sr_2(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, uint16_t value, size_t count)
+{
+ bus_addr_t addr = bsh + offset;
+
+ for (; count != 0; count--, addr += 2)
+ wr16(addr, value);
+}
+
+void
+octopci_bs_sr_4(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, uint32_t value, size_t count)
+{
+ bus_addr_t addr = bsh + offset;
+
+ for (; count != 0; count--, addr += 4)
+ wr32(addr, value);
+}
+
+/*
+ * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
+ * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
+ */
+void
+octopci_bs_c_1(void *t, bus_space_handle_t bsh1,
+ bus_size_t off1, bus_space_handle_t bsh2,
+ bus_size_t off2, size_t count)
+{
+ bus_addr_t addr1 = bsh1 + off1;
+ bus_addr_t addr2 = bsh2 + off2;
+
+ if (addr1 >= addr2) {
+ /* src after dest: copy forward */
+ for (; count != 0; count--, addr1++, addr2++)
+ wr8(addr2, rd8(addr1));
+ } else {
+ /* dest after src: copy backwards */
+ for (addr1 += (count - 1), addr2 += (count - 1);
+ count != 0; count--, addr1--, addr2--)
+ wr8(addr2, rd8(addr1));
+ }
+}
+
+void
+octopci_bs_c_2(void *t, bus_space_handle_t bsh1,
+ bus_size_t off1, bus_space_handle_t bsh2,
+ bus_size_t off2, size_t count)
+{
+ bus_addr_t addr1 = bsh1 + off1;
+ bus_addr_t addr2 = bsh2 + off2;
+
+ if (addr1 >= addr2) {
+ /* src after dest: copy forward */
+ for (; count != 0; count--, addr1 += 2, addr2 += 2)
+ wr16(addr2, rd16(addr1));
+ } else {
+ /* dest after src: copy backwards */
+ for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
+ count != 0; count--, addr1 -= 2, addr2 -= 2)
+ wr16(addr2, rd16(addr1));
+ }
+}
+
+void
+octopci_bs_c_4(void *t, bus_space_handle_t bsh1,
+ bus_size_t off1, bus_space_handle_t bsh2,
+ bus_size_t off2, size_t count)
+{
+ bus_addr_t addr1 = bsh1 + off1;
+ bus_addr_t addr2 = bsh2 + off2;
+
+ if (addr1 >= addr2) {
+ /* src after dest: copy forward */
+ for (; count != 0; count--, addr1 += 4, addr2 += 4)
+ wr32(addr2, rd32(addr1));
+ } else {
+ /* dest after src: copy backwards */
+ for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
+ count != 0; count--, addr1 -= 4, addr2 -= 4)
+ wr32(addr2, rd32(addr1));
+ }
+}
+
+void
+octopci_bs_barrier(void *t __unused,
+ bus_space_handle_t bsh __unused,
+ bus_size_t offset __unused, bus_size_t len __unused,
+ int flags)
+{
+#if 0
+ if (flags & BUS_SPACE_BARRIER_WRITE)
+ mips_dcache_wbinv_all();
+#endif
+}
diff --git a/sys/mips/cavium/octopcireg.h b/sys/mips/cavium/octopcireg.h
new file mode 100644
index 0000000..23abf1c
--- /dev/null
+++ b/sys/mips/cavium/octopcireg.h
@@ -0,0 +1,105 @@
+/***********************license start************************************
+ * Copyright (c) 2005-2007 Cavium Networks (support@cavium.com). All rights
+ * reserved.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * 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.
+ *
+ * * Neither the name of Cavium Networks nor the names of
+ * its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written
+ * permission.
+ *
+ * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+ * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
+ * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
+ * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
+ * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
+ * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
+ * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
+ * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
+ * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT
+ * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+ *
+ *
+ * For any questions regarding licensing please contact marketing@caviumnetworks.com
+ *
+ ***********************license end**************************************/
+/* $FreeBSD$ */
+
+#ifndef _CAVIUM_OCTOPCIREG_H_
+#define _CAVIUM_OCTOPCIREG_H_
+
+/**
+ * This is the bit decoding used for the Octeon PCI controller addresses for config space
+ */
+typedef union
+{
+ uint64_t u64;
+ uint64_t * u64_ptr;
+ uint32_t * u32_ptr;
+ uint16_t * u16_ptr;
+ uint8_t * u8_ptr;
+ struct
+ {
+ uint64_t upper : 2;
+ uint64_t reserved : 13;
+ uint64_t io : 1;
+ uint64_t did : 5;
+ uint64_t subdid : 3;
+ uint64_t reserved2 : 4;
+ uint64_t endian_swap : 2;
+ uint64_t reserved3 : 10;
+ uint64_t bus : 8;
+ uint64_t dev : 5;
+ uint64_t func : 3;
+ uint64_t reg : 8;
+ } s;
+} octeon_pci_config_space_address_t;
+
+typedef union
+{
+ uint64_t u64;
+ uint32_t * u32_ptr;
+ uint16_t * u16_ptr;
+ uint8_t * u8_ptr;
+ struct
+ {
+ uint64_t upper : 2;
+ uint64_t reserved : 13;
+ uint64_t io : 1;
+ uint64_t did : 5;
+ uint64_t subdid : 3;
+ uint64_t reserved2 : 4;
+ uint64_t endian_swap : 2;
+ uint64_t res1 : 1;
+ uint64_t port : 1;
+ uint64_t addr : 32;
+ } s;
+} octeon_pci_io_space_address_t;
+
+
+#define CVMX_OCT_SUBDID_PCI_CFG 1
+#define CVMX_OCT_SUBDID_PCI_IO 2
+#define CVMX_OCT_SUBDID_PCI_MEM1 3
+#define CVMX_OCT_SUBDID_PCI_MEM2 4
+#define CVMX_OCT_SUBDID_PCI_MEM3 5
+#define CVMX_OCT_SUBDID_PCI_MEM4 6
+
+#define CVMX_OCT_PCI_IO_BASE 0x00001000
+#define CVMX_OCT_PCI_IO_SIZE 0x08000000
+
+#define CVMX_OCT_PCI_MEM1_BASE 0x80000000
+#define CVMX_OCT_PCI_MEM1_SIZE 0x40000000
+
+#endif /* !_CAVIUM_OCTOPCIREG_H_ */
diff --git a/sys/mips/cavium/octopcivar.h b/sys/mips/cavium/octopcivar.h
new file mode 100644
index 0000000..026e45a
--- /dev/null
+++ b/sys/mips/cavium/octopcivar.h
@@ -0,0 +1,35 @@
+/*-
+ * Copyright (c) 2010 Juli Mallett <jmallett@FreeBSD.org>
+ * 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.
+ *
+ * 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$
+ */
+#ifndef _MIPS_CAVIUM_OCTOPCIVAR_H
+#define _MIPS_CAVIUM_OCTOPCIVAR_H
+
+DECLARE_BUS_SPACE_PROTOTYPES(octopci);
+
+extern bus_space_tag_t octopci_bus_space;
+
+#endif /* !_MIPS_CAVIUM_OCTOPCIVAR_H */
diff --git a/sys/mips/cavium/std.octeon1 b/sys/mips/cavium/std.octeon1
index 4e72e4d..3a1f3ed 100644
--- a/sys/mips/cavium/std.octeon1
+++ b/sys/mips/cavium/std.octeon1
@@ -17,6 +17,3 @@ cpu CPU_MIPS4KC
#device clock
#device obio
#device uart
-
-# Kludge
-options TARGET_OCTEON
diff --git a/sys/mips/cavium/uart_bus_octeonusart.c b/sys/mips/cavium/uart_bus_octeonusart.c
index 1adaf1c..c845ae7 100644
--- a/sys/mips/cavium/uart_bus_octeonusart.c
+++ b/sys/mips/cavium/uart_bus_octeonusart.c
@@ -55,6 +55,8 @@ __FBSDID("$FreeBSD$");
#include <mips/cavium/octeon_pcmap_regs.h>
+#include <contrib/octeon-sdk/cvmx.h>
+
#include "uart_if.h"
extern struct uart_class uart_oct16550_class;
@@ -101,7 +103,12 @@ uart_octeon_probe(device_t dev)
sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs);
bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
sc->sc_bas.bst = uart_bus_space_mem;
- if (bus_space_map(sc->sc_bas.bst, OCTEON_MIO_UART0, OCTEON_MIO_UART_SIZE,
+ /*
+ * XXX
+ * RBR isn't really a great base address and it'd be great to not have
+ * a hard-coded 1024.
+ */
+ if (bus_space_map(sc->sc_bas.bst, CVMX_MIO_UARTX_RBR(0), 1024,
0, &sc->sc_bas.bsh) != 0)
return (ENXIO);
return (uart_bus_probe(dev, sc->sc_bas.regshft, 0, 0, unit));
diff --git a/sys/mips/cavium/uart_cpu_octeonusart.c b/sys/mips/cavium/uart_cpu_octeonusart.c
index d2d8f56..c03708e 100644
--- a/sys/mips/cavium/uart_cpu_octeonusart.c
+++ b/sys/mips/cavium/uart_cpu_octeonusart.c
@@ -43,27 +43,11 @@ __FBSDID("$FreeBSD$");
#include <mips/cavium/octeon_pcmap_regs.h>
+#include <contrib/octeon-sdk/cvmx.h>
+
bus_space_tag_t uart_bus_space_io;
bus_space_tag_t uart_bus_space_mem;
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/kernel.h>
-#include <sys/malloc.h>
-#include <sys/ktr.h>
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_extern.h>
-
-#include <machine/bus.h>
-#include <machine/cache.h>
-
/*
* Specailized uart bus space. We present a 1 apart byte oriented
* bus to the outside world, but internally translate to/from the 8-apart
@@ -175,7 +159,8 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di)
*/
di->ops = uart_getops(class);
di->bas.chan = 0;
- if (bus_space_map(di->bas.bst, OCTEON_MIO_UART0, OCTEON_MIO_UART_SIZE,
+ /* XXX */
+ if (bus_space_map(di->bas.bst, CVMX_MIO_UARTX_RBR(0), 1024,
0, &di->bas.bsh) != 0)
return (ENXIO);
di->bas.regshft = 0;
diff --git a/sys/mips/cavium/uart_dev_oct16550.c b/sys/mips/cavium/uart_dev_oct16550.c
index 5c6e11e..b9bfe29 100644
--- a/sys/mips/cavium/uart_dev_oct16550.c
+++ b/sys/mips/cavium/uart_dev_oct16550.c
@@ -72,6 +72,9 @@ __FBSDID("$FreeBSD$");
#include <mips/cavium/octeon_pcmap_regs.h>
+#include <contrib/octeon-sdk/cvmx.h>
+#include <contrib/octeon-sdk/cvmx-interrupt.h>
+
#include "uart_if.h"
/*
@@ -457,13 +460,19 @@ oct16550_bus_attach (struct uart_softc *sc)
uart_setreg(bas, REG_IER, oct16550->ier);
uart_barrier(bas);
- uint32_t status_bits = mips_rd_status();
- mips_wr_status(status_bits & ~MIPS_SR_INT_IE);
/*
* Enable the interrupt in CIU. // UART-x2 @ IP2
*/
- ciu_enable_interrupts(0, CIU_INT_0, CIU_EN_0,
- (!unit) ? CIU_UART_BITS_UART0 : CIU_UART_BITS_UART1, CIU_MIPS_IP2);
+ switch (unit) {
+ case 0:
+ cvmx_interrupt_unmask_irq(CVMX_IRQ_UART0);
+ break;
+ case 1:
+ cvmx_interrupt_unmask_irq(CVMX_IRQ_UART1);
+ break;
+ default:
+ panic("%s: invalid UART %d", __func__, unit);
+ }
return (0);
}
@@ -668,7 +677,7 @@ oct16550_bus_probe (struct uart_softc *sc)
int error;
bas = &sc->sc_bas;
- bas->rclk = uart_oct16550_class.uc_rclk = octeon_cpu_clock;
+ bas->rclk = uart_oct16550_class.uc_rclk = cvmx_sysinfo_get()->cpu_clock_hz;
error = oct16550_probe(bas);
if (error) {
OpenPOWER on IntegriCloud