errors acpi ACPI_ERR_ {
failure NO_MCFG_TABLE "No MCFG Table found.",
failure INVALID_PATH_NAME "Invalid ACPI path name.",
+ failure INVALID_HANDLE "Invalid ACPI handle.",
+ failure NO_CHILD_BRIDGE "No matching child bridge found.",
failure GET_RESOURCES "Failed to execute _CRT method.",
failure SET_IRQ "Failed to set IRQ for device.",
failure NO_MADT_TABLE "No APIC found in ACPI.",
-- would not find its headers.
commonLinkFlags arch =
- [ Str "-nostdlib", NStr "-L", makeAbs $ NoDep BuildTree arch "/lib/" ]
- ++ [ Str "-Wl,--start-group" ]
- ++ (map makeAbs (optLibs (options arch)))
- ++ (map makeAbs (extraLink arch))
- ++ [
+ [ Str "-nostdlib", NStr "-L", makeAbs $ NoDep BuildTree arch "/lib/" ] ++
+ [ Str "-Wl,--start-group" ]
+-- The following line seems to add libbarrelfish as an dependency which
+--
+-- ++ (map makeAbs (optLibs (options arch)))
+-- ++ (map makeAbs (extraLink arch))
+ ++
+ [
Str "-Wl,--end-group",
-- Enable the following flags for ld debugging
-- Str "-Wl,-verbose=2",
++ (compileCFLAGS arch)
++ [ Str "\"" ]
- envCC arch = [ NStr "CC=" , Str (RuleDefs.compiler $ options arch) ]
+ envCC arch =
+ [ NStr "CC=\"" ]
+ ++ [Str (RuleDefs.compiler $ options arch)]
+ ++ [ Str "\"" ]
convertArch arch = case arch of
"x86_64" -> "x86_64-unknown-none"
Target arch "configure"
]
),
+
-- run configure
Rule ( [
-- this is tricky as configure produces Makefile in .
Str "sed -i.orig s/HAVE_OBSTACK_VPRINTF/HAVE_OBSTACK_VPRINTF_nope/g",
Out arch "config.h"
]
- ++
- (map toDep (optLibs (options arch)))
- ++
- (map toDep (extraLink arch))
+-- ++
+-- (map toDep (optLibs (options arch)))
+-- ++
+-- (map toDep (extraLink arch))
),
-- run make
Rule ( [
-- ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
--
-- Hakefile for /platforms/
---
+--
--------------------------------------------------------------------------
-let bin_rcce_lu = [ "/sbin/" ++ f | f <- [
+let bin_rcce_lu = [ "/sbin/" ++ f | f <- [
"rcce_lu_A1",
"rcce_lu_A2",
"rcce_lu_A4",
"rcce_lu_A32",
"rcce_lu_A64" ]]
- bin_rcce_bt = [ "/sbin/" ++ f | f <- [
+ bin_rcce_bt = [ "/sbin/" ++ f | f <- [
"rcce_bt_A1",
"rcce_bt_A4",
"rcce_bt_A9",
tests_common = [ "/sbin/" ++ f | f <- [
"fputest",
- "fread_test",
- "fscanf_test",
"hellotest",
"idctest",
"memtest",
"testerror",
"yield_test" ] ]
- tests_x86 = [ "/sbin/" ++ f | f <- [
+ tests_x86 = [ "/sbin/" ++ f | f <- [
"tests/luatest",
"tests/numatest" ] ] ++ tests_common
- tests_x86_64 = [ "/sbin/" ++ f | f <- [
+ tests_x86_64 = [ "/sbin/" ++ f | f <- [
"arrakis_hellotest",
+ "fread_test",
+ "fscanf_test",
"ata_rw28_test",
"bomp_cpu_bound",
"bomp_cpu_bound_progress",
"xcorecap",
"xcorecapserv" ] ] ++ tests_x86
- tests_x86_32 = tests_x86
+ tests_x86_32 = [ "/sbin/" ++ f | f <- [
+ "fread_test",
+ "fscanf_test"
+ ] ] ++ tests_x86
tests_k1om = [ "/sbin/" ++ f | f <- [
"tests/dma_test",
"tests/xeon_phi_test",
"tests/xphi_nameservice_test" ] ] ++ tests_x86
- bench_common = [ "/sbin/" ++ f | f <- [
+ bench_common = [ "/sbin/" ++ f | f <- [
"channel_cost_bench",
"flounder_stubs_buffer_bench",
"flounder_stubs_empty_bench",
"flounder_stubs_payload_bench",
"xcorecapbench" ]]
- bench_x86 = [ "/sbin/" ++ f | f <- [
+ bench_x86 = [ "/sbin/" ++ f | f <- [
"multihop_latency_bench",
"net_openport_test",
"perfmontest",
"ump_send",
"ump_throughput" ]]
- bench_x86_64 = bench_x86 ++ bin_rcce_bt ++ bin_rcce_lu ++
- [ "/sbin/" ++ f | f <- [
+ bench_x86_64 = bench_x86 ++ bin_rcce_bt ++ bin_rcce_lu ++
+ [ "/sbin/" ++ f | f <- [
"ahci_bench",
"apicdrift_bench",
"benchmarks/bomp_mm",
bench_x86_32 = bench_x86 ++ bin_rcce_bt ++ bin_rcce_lu
- bench_k1om = [ "/sbin/" ++ f | f <- [
+ bench_k1om = [ "/sbin/" ++ f | f <- [
"benchmarks/bomp_mm",
"benchmarks/dma_bench",
"benchmarks/xomp_share",
"benchmarks/xphi_xump_bench" ] ] ++ bench_x86
-- Default list of modules to build/install for all enabled architectures
- modules_common = [ "/sbin/" ++ f | f <- [
+ modules_common = [ "/sbin/" ++ f | f <- [
"init",
"chips",
"skb",
"/sshd_ramfs.cpio.gz" ]
-- x86_64-specific modules to build by default
- -- this should shrink as targets are ported and move into the generic list above
- modules_x86_64 = [ "/sbin/" ++ f | f <- [
+ -- this should shrink as targets are ported and move into the generic list above
+ modules_x86_64 = [ "/sbin/" ++ f | f <- [
"elver",
"cpu",
"acpi",
"xeon_phi",
"xeon_phi_mgr"
]] ++ modules_common
-
+
-- the following are broken in the newidc system
- modules_x86_64_broken = [ "/sbin/" ++ f | f <- [
+ modules_x86_64_broken = [ "/sbin/" ++ f | f <- [
"barriers",
"ipi_bench",
"ring_barriers",
"ssf_bcast",
"lamport_bcast" ]]
-
+
-- x86-32-specific module to build by default
- modules_x86_32 = [ "/sbin/" ++ f | f <- [
+ modules_x86_32 = [ "/sbin/" ++ f | f <- [
"cpu",
"lpc_kbd",
"serial",
--
-- Rules to build assorted platforms
--
-
+
platform "X86_64_Basic" [ "x86_64" ]
([ ("x86_64", f) | f <- modules_x86_64 ]
++
platform "PandaboardES" [ "armv7" ]
([ ("armv7", f) | f <- pandaModules ] ++ [ ("root", "/pandaboard_image") ])
"Standard Pandaboard ES build image and modules",
-
+
platform "ARMv8-GEM5" [ "armv8" ]
([ ("armv8", f) | f <- armv8_gem5Modules ] ++ [ ("root", "/armv8_gem5_image") ])
"GEM5 emulator for ARM Cortex-A series multicore processors",
--
-- Rules to build assorted boot images
--
-
+
-- Build the default PandaBoard boot image
Rule ([ In SrcTree "tools" "/tools/arm_molly/build_pandaboard_image.sh",
- Str "--srcdir", NoDep SrcTree "root" "/.",
- Str "--builddir", NoDep BuildTree "root" "/.",
+ Str "--srcdir", NoDep SrcTree "root" "/.",
+ Str "--builddir", NoDep BuildTree "root" "/.",
Str "--arch armv7-a",
Str "--menu", In SrcTree "tools" "/hake/menu.lst.pandaboard",
Str "--baseaddr", Str "0x82001000",
-- Build the (old) PandaBoard Cortex-M3 image
Rule ([ In SrcTree "tools" "/tools/arm_molly/build_pandaboard_image.sh",
- Str "--srcdir", NoDep SrcTree "root" "/.",
+ Str "--srcdir", NoDep SrcTree "root" "/.",
Str "--builddir", NoDep BuildTree "root" "/.",
Str "--arch armv7-m",
Str "--menu", In SrcTree "tools" "/hake/menu.lst.armv7-m",
-- Build the ARMv7 GEM5 simulation image
Rule ([ In SrcTree "tools" "/tools/arm_molly/build_pandaboard_image.sh",
- Str "--srcdir", NoDep SrcTree "root" "/.",
- Str "--builddir", NoDep BuildTree "root" "/.",
+ Str "--srcdir", NoDep SrcTree "root" "/.",
+ Str "--builddir", NoDep BuildTree "root" "/.",
Str "--arch armv7-a",
Str "--menu", In SrcTree "tools" "/hake/menu.lst.arm_gem5_mc",
Str "--baseaddr", Str "0x100000",
-- Build the ARMv8 GEM5 simulation image
Rule ([ In SrcTree "tools" "/tools/arm_molly/build_pandaboard_image.sh",
- Str "--srcdir", NoDep SrcTree "root" "/.",
- Str "--builddir", NoDep BuildTree "root" "/.",
+ Str "--srcdir", NoDep SrcTree "root" "/.",
+ Str "--builddir", NoDep BuildTree "root" "/.",
Str "--arch armv8-a",
Str "--menu", In SrcTree "tools" "/hake/menu.lst.armv8_gem5",
Str "--baseaddr", Str "0x100000",
Rules [ copyFile SrcTree "root" ("/hake/menu.lst." ++ p)
"root" ("/platforms/x86/menu.lst." ++ p)
| p <- [ "x86_32", "x86_64", "k1om" ] ],
-
+
-- Convenient functions for running GEM5
boot "gem5_armv8" [ "armv8" ] [
Str Config.gem5,
Str "--menu", In BuildTree "root" "/platforms/x86/menu.lst.x86_64",
Str "--arch", Str "x86_64" ]
"Boot QEMU in 64-bit x86 mode emulating a PC",
-
+
boot "qemu_x86_32" [ "x86_32" ] [
In SrcTree "tools" "/tools/qemu-wrapper.sh",
Str "--menu", In BuildTree "root" "/platforms/x86/menu.lst.x86_32",
Str "--arch", Str "x86_64",
Str "--debug", In SrcTree "tools" "/tools/debug.gdb" ]
"Boot QEMU under GDB in 64-bit x86 mode emulating a PC",
-
+
boot "qemu_x86_32_debug" [ "x86_32" ] [
In SrcTree "tools" "/tools/qemu-wrapper.sh",
Str "--menu", In BuildTree "root" "/platforms/x86/menu.lst.x86_32",
if machine.name == "sbrinz1" or machine.name == "sbrinz2" \
or machine.name == "tomme1" or machine.name == "tomme2" \
- or is_babybel == 1 :
+ or machine.name == "appenzeller" or is_babybel == 1 :
# PCI allocation broken, use BIOS plan
m.add_module("%s/sbin/pci" % a, ["auto",
"skb_bridge_program=bridge_bios"] + machine.get_pci_args())
--- /dev/null
+##########################################################################
+# Copyright (c) 2011, ETH Zurich.
+# All rights reserved.
+#
+# This file is distributed under the terms in the attached LICENSE file.
+# If you do not find this file, copies can be found by writing to:
+# ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+##########################################################################
+import datetime
+import re
+import tests
+from common import TestCommon
+from results import PassFailResult
+
+#IRQTEST_TIMEOUT = datetime.timedelta(minutes=5)
+
+@tests.add_test
+class IRQTest(TestCommon):
+ '''PCI IRQ test'''
+ name = "irqtest"
+
+ def get_machine_irqtest_args(self, machine):
+ '''For a given machine, return the paramaters passed to irqtest.
+ It should contain of the e1000 PCI device id, and if there are multiple
+ cards, also the PCI function.'''
+ mn = machine.get_machine_name()
+ if mn.startswith("sbrinz"):
+ return ["deviceid=0x1079", "function=0"]
+ elif mn == "gruyere":
+ return ["deviceid=0x1076"]
+ elif mn == "appenzeller":
+ return ["deviceid=0x10d3"]
+ elif mn.startswith("nos"):
+ return ["deviceid=0x107d"]
+ elif mn.startswith("tomme"):
+ return ["deviceid=0x10a7", "function=0"]
+ else:
+ raise Exception("Machine %s not supported" % mn)
+
+
+ def get_modules(self, build, machine):
+ modules = super(IRQTest, self).get_modules(build, machine)
+ modules.add_module("irqtest",
+ ["core=%d" % machine.get_coreids()[1]] + self.get_machine_irqtest_args(machine))
+ return modules
+
+ def is_finished(self, line):
+ return line.startswith("TEST ")
+
+ def process_data(self, testdir, rawiter):
+ for line in rawiter:
+ if line.startswith("TEST SUCCESS"):
+ return PassFailResult(True)
+ return PassFailResult(False)
except TimeoutError as e:
if self.boot_phase:
if self.boot_attempts < MAX_BOOT_ATTEMPTS:
- yield BOOT_TIMEOUT_LINE_RETRY
+ yield '[Error: boot timed out, retry]\n'
self.reboot(machine)
continue
else:
- yield BOOT_TIMEOUT_LINE_FAIL
+ yield '[Error: boot timed out, retry limit reached]\n'
else:
- yield TEST_TIMEOUT_LINE
+ yield '[Error: test timed out]\n'
debug.verbose("timeout encountered in collect_data");
self.has_timeout = True
if self.is_done :
#include "intel_vtd.h"
#include <trace/trace.h>
+#define PCI_LNK_DEV_STRING "PNP0C0F"
+#define METHOD_NAME__DIS "_DIS"
+
struct pci_resources {
uint8_t minbus, maxbus;
lpaddr_t minmem, maxmem;
char prtbuf[2048];
ACPI_BUFFER bufobj = {.Length = sizeof(prtbuf), .Pointer = prtbuf};
+ char namebuf[256];
+ ACPI_BUFFER namebufobj = {.Length = sizeof(namebuf), .Pointer = namebuf};
+
+ as = AcpiGetName(handle, ACPI_FULL_PATHNAME, &namebufobj);
+ if (ACPI_FAILURE(as)) {
+ ACPI_DEBUG("No name found: %s\n", AcpiFormatException(as));
+ namebuf[0] = 0;
+ } else {
+ assert(namebufobj.Pointer == namebuf);
+ }
+
/* do we have an interrupt routing table? */
as = AcpiGetIrqRoutingTable(handle, &bufobj);
if (ACPI_FAILURE(as)) {
- ACPI_DEBUG("No IRQ routing table found: %s\n", AcpiFormatException(as));
+ ACPI_DEBUG("No PCI IRQ routing table for (%s) bus %"PRIu8": %s\n", namebuf, bus, AcpiFormatException(as));
return;
}
- //printf("PCI IRQ routing table:\n");
+ ACPI_DEBUG("PCI IRQ routing table for (%s) bus %"PRIu8":\n", namebuf, bus);
ACPI_PCI_ROUTING_TABLE *prt = bufobj.Pointer;
for (; prt->Length; prt = (void *)prt + prt->Length) {
uint16_t device = (prt->Address >> 16) & 0xffff;
}
}
-void acpi_get_irqtable_device(ACPI_HANDLE parent,
+errval_t acpi_get_irqtable_device(ACPI_HANDLE parent,
acpi_pci_address_t device, ACPI_HANDLE *child, uint8_t bus)
{
-/* char b[128]; */
-/* ACPI_BUFFER buf = { .Length = 128, .Pointer = b }; */
-/* ACPI_STATUS s; */
*child = NULL;
if(parent == NULL) {
- return;
+ return ACPI_ERR_INVALID_PATH_NAME;
}
-/* s = AcpiGetName(parent, ACPI_FULL_PATHNAME, &buf); */
-/* assert(ACPI_SUCCESS(s)); */
-/* printf("Parent: %s\n", b); */
-
+ // For each children of parent
for(;;) {
ACPI_STATUS as =
AcpiGetNextObject(ACPI_TYPE_DEVICE, parent, *child, child);
if(as == AE_NOT_FOUND || *child == NULL) {
- return;
+ break; //Goto error out
}
if(ACPI_FAILURE(as)) {
- ACPI_DEBUG("Error looking up ACPI children\n");
+ ACPI_DEBUG("Error looking up ACPI children.\n");
abort();
}
-/* s = AcpiGetName(*child, ACPI_FULL_PATHNAME, &buf); */
-/* if(ACPI_FAILURE(s)) { */
-/* printf("Name lookup failure: %d\n", s); */
-/* } else { */
-/* printf("Current: %s\n", b); */
-/* } */
-
- /* look for a _ADR node, which tells us the bridge's configuration space */
+ // look for a _ADR node, which tells us the bridge's configuration space
ACPI_INTEGER addr;
as = acpi_eval_integer(*child, "_ADR", &addr);
if (ACPI_FAILURE(as)) {
+ ACPI_DEBUG("No _ADR method found !?!.\n");
continue;
}
if(device.device == bridgeaddr.device
&& device.function == bridgeaddr.function) {
-/* printf("Found corresponding ACPI bridge device!\n"); */
get_irq_routing(*child, bus);
+ return SYS_ERR_OK;
}
}
+
+ // Error output
+ char namebuf[128];
+ ACPI_BUFFER buf = { .Length = sizeof(namebuf), .Pointer = namebuf };
+ ACPI_STATUS s;
+ s = AcpiGetName(parent, ACPI_FULL_PATHNAME, &buf);
+ assert(ACPI_SUCCESS(s));
+ // LH: It seems this is not a fatal condition, but I am really not sure.
+ ACPI_DEBUG("acpi_service: No matching child bridge found. Parent '%s'. Child %"PRIu8
+ ", %"PRIu8", %"PRIu8" \n", namebuf, bus, device.device, device.function);
+ return ACPI_ERR_NO_CHILD_BRIDGE;
+}
+
+static ACPI_STATUS add_pci_lnk_device(ACPI_HANDLE handle, UINT32 level,
+ void *context, void **retval)
+{
+ ACPI_STATUS as;
+ char namebuf[128];
+ ACPI_BUFFER bufobj = {.Length = sizeof(namebuf), .Pointer = namebuf};
+
+ /* get the node's name */
+ as = AcpiGetName(handle, ACPI_FULL_PATHNAME, &bufobj);
+ if (ACPI_FAILURE(as)) {
+ ACPI_DEBUG("Cannot resolve name of PCI Link device\n");
+ return as;
+ }
+ assert(bufobj.Pointer == namebuf);
+ ACPI_DEBUG("Discovered PCI Link device (%s). Disabling\n", namebuf);
+ as = AcpiEvaluateObject(handle, METHOD_NAME__DIS, NULL, NULL);
+ if (ACPI_FAILURE(as)) {
+ ACPI_DEBUG("Cannot execute _DIS of PCI Link device (%s)\n", namebuf);
+ return as;
+ }
+
+ return as;
}
+
static ACPI_STATUS add_pci_device(ACPI_HANDLE handle, UINT32 level,
void *context, void **retval)
{
ACPI_DEBUG("Switching to APIC mode...\n");
as = set_apic_mode();
if(ACPI_FAILURE(as)) {
- ACPI_DEBUG("Warning: Could not set system to APIC mode! "
- "Continuing anyway...\n");
+ printf("ACPI: Warning: Could not set system to APIC mode! "
+ "Continuing anyway... status: %s\n", AcpiFormatException(as));
+ } else {
+ printf("ACPI: Switched to APIC mode.\n");
}
/* look for an MCFG table
as = AcpiGetDevices(PCI_ROOT_HID_STRING, add_pci_device, NULL, NULL);
assert(ACPI_SUCCESS(as));
+ ACPI_DEBUG("Walking for PCI Link devices\n");
+ as = AcpiGetDevices(PCI_LNK_DEV_STRING, add_pci_lnk_device, NULL, NULL);
+ assert(ACPI_SUCCESS(as));
+
//ACPI_DEBUG("Programming PCI BARs and bridge windows\n");
//pci_program_bridges();
//ACPI_DEBUG("PCI programming completed\n");
static void read_irq_table(struct acpi_binding* b, char* pathname,
acpi_pci_address_t addr, uint8_t bus)
{
- ACPI_DEBUG("read_irq_table: %s\n", pathname);
+ ACPI_DEBUG("read_irq_table: (parent)%s, (%"PRIu8",%"PRIu8",%"PRIu8"), %"PRIu8"\n",
+ pathname == NULL ? "NULL" : pathname, addr.bus, addr.device, addr.function, bus);
errval_t err;
ACPI_STATUS as;
as = AcpiGetHandle(NULL, pathname, &handle);
if (ACPI_SUCCESS(as)) {
ACPI_HANDLE child;
- acpi_get_irqtable_device(handle, addr, &child, bus);
-
- char name[128];
- get_path_name(child, name, 128);
- ACPI_DEBUG("Sending back path name: %s\n", name);
-
- err = b->tx_vtbl.read_irq_table_response(b, NOP_CONT, SYS_ERR_OK, name);
- assert(err_is_ok(err));
+ err = acpi_get_irqtable_device(handle, addr, &child, bus);
+
+ if(err_is_fail(err)){
+ ACPI_DEBUG("get_irq_table failed.\n");
+ err = b->tx_vtbl.read_irq_table_response(b, NOP_CONT, err, NULL);
+ assert(err_is_ok(err));
+ } else {
+ char name[128];
+ get_path_name(child, name, 128);
+ ACPI_DEBUG("Sending back path name: %s\n", name);
+
+ err = b->tx_vtbl.read_irq_table_response(b, NOP_CONT, SYS_ERR_OK, name);
+ assert(err_is_ok(err));
+ }
}
else {
ACPI_DEBUG("Unknown ACPI Handle for path: %s\n", pathname);
int init_acpi(void);
ACPI_STATUS acpi_eval_integer(ACPI_HANDLE handle, char *name, ACPI_INTEGER *ret);
-void acpi_get_irqtable_device(ACPI_HANDLE parent, acpi_pci_address_t device,
+errval_t acpi_get_irqtable_device(ACPI_HANDLE parent, acpi_pci_address_t device,
ACPI_HANDLE *child, uint8_t bus);
void video_init(void);
void buttons_init(void);
struct find_cap_result_msg_st *msg_st = (struct find_cap_result_msg_st*)e;
err = intermon_capops_find_cap_result__tx(b, NOP_CONT, msg_st->result, msg_st->st);
+
+ if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+ DEBUG_CAPOPS("%s: got FLOUNDER_ERR_TX_BUSY; requeueing msg.\n", __FUNCTION__);
+ struct intermon_state *inter_st = (struct intermon_state *)b->st;
+ // requeue send request at front and return
+ err = intermon_enqueue_send_at_front(b, &inter_st->queue, b->waitset,
+ (struct msg_queue_elem *)e);
+ GOTO_IF_ERR(err, handle_err);
+ return;
+ }
+
+handle_err:
if (err_is_fail(err)) {
USER_PANIC_ERR(err, "failed to send find_cap_result message");
}
struct find_descendants_result_msg_st *msg_st;
msg_st = (struct find_descendants_result_msg_st*)e;
err = intermon_capops_find_descendants_result__tx(b, NOP_CONT, msg_st->status, msg_st->st);
+
+ if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+ DEBUG_CAPOPS("%s: got FLOUNDER_ERR_TX_BUSY; requeueing msg.\n", __FUNCTION__);
+ struct intermon_state *inter_st = (struct intermon_state *)b->st;
+ // requeue send request at front and return
+ err = intermon_enqueue_send_at_front(b, &inter_st->queue, b->waitset,
+ (struct msg_queue_elem *)e);
+ GOTO_IF_ERR(err, handle_err);
+ return;
+ }
+
+handle_err:
free(msg_st);
if (err_is_fail(err)) {
USER_PANIC_ERR(err, "could not send find_descendants_result");
struct owner_updated_msg_st *msg_st = (struct owner_updated_msg_st*)e;
err = intermon_capops_owner_updated__tx(b, NOP_CONT, msg_st->st);
+
+ if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+ DEBUG_CAPOPS("%s: got FLOUNDER_ERR_TX_BUSY; requeueing msg.\n", __FUNCTION__);
+ struct intermon_state *inter_st = (struct intermon_state *)b->st;
+ // requeue send request at front and return
+ err = intermon_enqueue_send_at_front(b, &inter_st->queue, b->waitset,
+ (struct msg_queue_elem *)e);
+ GOTO_IF_ERR(err, handle_err);
+ return;
+ }
+
+handle_err:
if (err_is_fail(err)) {
USER_PANIC_ERR(err, "failed to send owner_updated message");
}
err = intermon_capops_recv_copy_result__tx(b, NOP_CONT, msg_st->status,
msg_st->capaddr, msg_st->vbits,
msg_st->slot, msg_st->st);
+
+ if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+ DEBUG_CAPOPS("%s: got FLOUNDER_ERR_TX_BUSY; requeueing msg.\n", __FUNCTION__);
+ struct intermon_state *inter_st = (struct intermon_state *)b->st;
+ // requeue send request at front and return
+ err = intermon_enqueue_send_at_front(b, &inter_st->queue, b->waitset,
+ (struct msg_queue_elem *)e);
+ GOTO_IF_ERR(err, handle_err);
+ return;
+ }
+
+handle_err:
PANIC_IF_ERR(err, "failed to send recv_copy_result");
free(msg_st);
}
err = intermon_capops_recv_copy__tx(b, NOP_CONT, msg_st->caprep,
msg_st->owner_relations, msg_st->st);
+ if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+ DEBUG_CAPOPS("%s: got FLOUNDER_ERR_TX_BUSY; requeueing msg.\n", __FUNCTION__);
+ struct intermon_state *inter_st = (struct intermon_state *)b->st;
+ // requeue send request at front and return
+ err = intermon_enqueue_send_at_front(b, &inter_st->queue, b->waitset,
+ (struct msg_queue_elem *)e);
+ GOTO_IF_ERR(err, handle_err);
+ return;
+ }
+
+handle_err:
if (err_is_fail(err)) {
// send failed, report result
rpc_st->recv_handler(err, 0, 0, 0, rpc_st);
err = intermon_capops_request_copy__tx(b, NOP_CONT, msg_st->dest,
msg_st->caprep,
(lvaddr_t)msg_st->st);
+
+ if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+ DEBUG_CAPOPS("%s: got FLOUNDER_ERR_TX_BUSY; requeueing msg.\n", __FUNCTION__);
+ struct intermon_state *inter_st = (struct intermon_state *)b->st;
+ // requeue send request at front and return
+ err = intermon_enqueue_send_at_front(b, &inter_st->queue, b->waitset,
+ (struct msg_queue_elem *)e);
+ GOTO_IF_ERR(err, handle_err);
+ return;
+ }
+
+handle_err:
if (err_is_fail(err)) {
assert(msg_st->st);
struct cap_copy_rpc_st *rpc_st = (struct cap_copy_rpc_st*)msg_st->st;
errval_t err;
struct delete_remote_result_msg_st *msg_st = (struct delete_remote_result_msg_st*)e;
err = intermon_capops_delete_remote_result__tx(b, NOP_CONT, msg_st->status, msg_st->st);
+
+ if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+ DEBUG_CAPOPS("%s: got FLOUNDER_ERR_TX_BUSY; requeueing msg.\n", __FUNCTION__);
+ struct intermon_state *inter_st = (struct intermon_state *)b->st;
+ // requeue send request at front and return
+ err = intermon_enqueue_send_at_front(b, &inter_st->queue, b->waitset,
+ (struct msg_queue_elem *)e);
+ GOTO_IF_ERR(err, handle_err);
+ return;
+ }
+
+handle_err:
PANIC_IF_ERR(err, "failed to send delete_remote_result msg");
free(msg_st);
}
{
errval_t err;
struct move_request_msg_st *msg_st = (struct move_request_msg_st*)e;
- err = intermon_capops_move_request__tx(b, NOP_CONT, msg_st->caprep, msg_st->relations, (lvaddr_t)msg_st->st);
+ err = intermon_capops_move_request__tx(b, NOP_CONT, msg_st->caprep,
+ msg_st->relations, (lvaddr_t)msg_st->st);
+
+ if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+ DEBUG_CAPOPS("%s: got FLOUNDER_ERR_TX_BUSY; requeueing msg.\n", __FUNCTION__);
+ struct intermon_state *inter_st = (struct intermon_state *)b->st;
+ // requeue send request at front and return
+ err = intermon_enqueue_send_at_front(b, &inter_st->queue, b->waitset,
+ (struct msg_queue_elem *)e);
+ GOTO_IF_ERR(err, handle_err);
+ return;
+ }
+
+handle_err:
if (err_is_fail(err)) {
struct cap_move_rpc_st *rpc_st = (struct cap_move_rpc_st*)msg_st->st;
if (rpc_st->result_handler) {
errval_t err;
struct move_result_msg_st *msg_st = (struct move_result_msg_st*)e;
err = intermon_capops_move_result__tx(b, NOP_CONT, msg_st->status, msg_st->st);
+
+ if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+ DEBUG_CAPOPS("%s: got FLOUNDER_ERR_TX_BUSY; requeueing msg.\n", __FUNCTION__);
+ struct intermon_state *inter_st = (struct intermon_state *)b->st;
+ // requeue send request at front and return
+ err = intermon_enqueue_send_at_front(b, &inter_st->queue, b->waitset,
+ (struct msg_queue_elem *)e);
+ GOTO_IF_ERR(err, handle_err);
+ return;
+ }
+
+handle_err:
if (err_is_fail(err)) {
USER_PANIC_ERR(err, "failed to send move_result");
}
capability_to_caprep(&st->rawcap, &caprep);
err = intermon_capops_retrieve_request__tx(b, NOP_CONT, caprep, (lvaddr_t)st);
+
+ if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+ DEBUG_CAPOPS("%s: got FLOUNDER_ERR_TX_BUSY; requeueing msg.\n", __FUNCTION__);
+ struct intermon_state *inter_st = (struct intermon_state *)b->st;
+ // requeue send request at front and return
+ err = intermon_enqueue_send_at_front(b, &inter_st->queue, b->waitset,
+ (struct msg_queue_elem *)e);
+ }
+
GOTO_IF_ERR(err, report_error);
return;
err = intermon_capops_retrieve_result__tx(b, NOP_CONT, st->status,
st->relations, st->st);
+
+ if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+ DEBUG_CAPOPS("%s: got FLOUNDER_ERR_TX_BUSY; requeueing msg.\n", __FUNCTION__);
+ struct intermon_state *inter_st = (struct intermon_state *)b->st;
+ // requeue send request at front and return
+ err = intermon_enqueue_send_at_front(b, &inter_st->queue, b->waitset,
+ (struct msg_queue_elem *)e);
+ GOTO_IF_ERR(err, handle_err);
+ return;
+ }
+
+handle_err:
PANIC_IF_ERR(err, "sending retrieve result");
free(st);
}
struct requested_retype_st *req_st = (struct requested_retype_st*)e;
err = intermon_capops_retype_response__tx(b, NOP_CONT, req_st->status,
req_st->request_st);
+
+ if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+ DEBUG_CAPOPS("%s: got FLOUNDER_ERR_TX_BUSY; requeueing msg.\n", __FUNCTION__);
+ struct intermon_state *inter_st = (struct intermon_state *)b->st;
+ // requeue send request at front and return
+ err = intermon_enqueue_send_at_front(b, &inter_st->queue, b->waitset,
+ (struct msg_queue_elem *)e);
+ GOTO_IF_ERR(err, handle_err);
+ return;
+ }
+
+handle_err:
PANIC_IF_ERR(err, "sending retype result message");
free(req_st);
}
req_st->check.count,
(lvaddr_t)req_st);
+
+ if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+ DEBUG_CAPOPS("%s: got FLOUNDER_ERR_TX_BUSY; requeueing msg.\n", __FUNCTION__);
+ struct intermon_state *inter_st = (struct intermon_state *)b->st;
+ // requeue send request at front and return
+ err = intermon_enqueue_send_at_front(b, &inter_st->queue, b->waitset,
+ (struct msg_queue_elem *)e);
+ GOTO_IF_ERR(err, handle_err);
+ return;
+ }
+
+handle_err:
if (err_is_fail(err)) {
retype_result__rx(err, req_st);
}
errval_t err;
struct revoke_slave_st *rvk_st = (struct revoke_slave_st*)e;
err = intermon_capops_revoke_ready__tx(b, NOP_CONT, rvk_st->st);
+
+ if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+ DEBUG_CAPOPS("%s: got FLOUNDER_ERR_TX_BUSY; requeueing msg.\n", __FUNCTION__);
+ struct intermon_state *inter_st = (struct intermon_state *)b->st;
+ // requeue send request at front and return
+ err = intermon_enqueue_send_at_front(b, &inter_st->queue, b->waitset,
+ (struct msg_queue_elem *)e);
+ GOTO_IF_ERR(err, handle_err);
+ return;
+ }
+
+handle_err:
PANIC_IF_ERR(err, "sending revoke_ready");
}
errval_t err;
struct revoke_slave_st *rvk_st = (struct revoke_slave_st*)e;
err = intermon_capops_revoke_done__tx(b, NOP_CONT, rvk_st->st);
+
+ if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+ DEBUG_CAPOPS("%s: got FLOUNDER_ERR_TX_BUSY; requeueing msg.\n", __FUNCTION__);
+ struct intermon_state *inter_st = (struct intermon_state *)b->st;
+ // requeue send request at front and return
+ err = intermon_enqueue_send_at_front(b, &inter_st->queue, b->waitset,
+ (struct msg_queue_elem *)e);
+ GOTO_IF_ERR(err, handle_err);
+ return;
+ }
+
+handle_err:
PANIC_IF_ERR(err, "sending revoke_done");
remove_slave_from_list(rvk_st);
free(rvk_st);
//ACPI_HANDLE child;
char* child = NULL;
errval_t error_code;
- PCI_DEBUG("get irq table for (%hhu,%hhu,%hhu)\n", (*busnum) + 1,
+ PCI_DEBUG("get irq table for (%hhu,%hhu,%hhu)\n", (*busnum) + 2,
addr.device, addr.function);
struct acpi_rpc_client* cl = get_acpi_rpc_client();
// XXX: why do we have two different types for the same thing?
.device = addr.device,
.function = addr.function,
};
- cl->vtbl.read_irq_table(cl, handle, xaddr, (*busnum) + 1,
+ errval_t err = cl->vtbl.read_irq_table(cl, handle, xaddr, (*busnum) + 2,
&error_code, &child);
- if (err_is_fail(error_code)) {
+ if (err_is_ok(err) && error_code == ACPI_ERR_NO_CHILD_BRIDGE){
+ PCI_DEBUG("No corresponding ACPI entry for bridge found\n");
+ } else if (err_is_fail(err) || err_is_fail(error_code)) {
DEBUG_ERR(error_code, "Reading IRQs failed");
- assert(!"Check ACPI code");
}
// Increase by 2 to leave room for SR-IOV
}
}
+ if(hdr_type.fmt == pci_hdr0_cardbus) {
+ printf("PCI: WARNING: Found cardbus bridge.\n");
+ }
// is this a multi-function device?
if (addr.function == 0 && !hdr_type.multi) {
break;
--- /dev/null
+--------------------------------------------------------------------------
+-- Copyright (c) 2007-2009, ETH Zurich.
+-- All rights reserved.
+--
+-- This file is distributed under the terms in the attached LICENSE file.
+-- If you do not find this file, copies can be found by writing to:
+-- ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+--
+-- Hakefile for /usr/tests/irqtest
+--
+--------------------------------------------------------------------------
+
+[ build application { target = "irqtest",
+ cFiles = [ "irqtest.c", "e1000n_helpers.c", "e1000n_hwinit.c" ],
+ addLibraries = libDeps [ "pci" ],
+ mackerelDevices = [ "e1000" ]
+ }
+]
--- /dev/null
+/*
+ * Copyright (c) 2008, ETH Zurich. All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#ifndef E1000_H__
+#define E1000_H__
+
+#include <barrelfish/barrelfish.h>
+#include <pci/pci.h>
+
+#include <dev/e1000_dev.h> /* auto generated by Mackerel */
+#include "e1000n_desc.h"
+#include "irqtest_debug.h"
+
+#define DRIVER_STRING "e1000: "
+
+/**
+ * Default message print format.
+ */
+#define E1000_PRINT(fmt, ...) printf(DRIVER_STRING fmt, ##__VA_ARGS__)
+#define E1000_PRINT_ERROR(fmt, ...) fprintf(stderr, DRIVER_STRING fmt, ##__VA_ARGS__)
+
+#define E1000_USE_LEGACY_DESC 1
+/*
+ * Global constants
+ */
+#define MAC_ADDRESS_LEN 6
+
+
+/*
+ * e1000 (e1000) device family id's.
+ */
+#define E1000_DEVICE_82542 0x1000
+#define E1000_DEVICE_82543GC_FIBER 0x1001
+#define E1000_DEVICE_82543GC_COPPER 0x1004
+#define E1000_DEVICE_82544EI_COPPER 0x1008
+#define E1000_DEVICE_82544EI_FIBER 0x1009
+#define E1000_DEVICE_82544GC_COPPER 0x100C
+#define E1000_DEVICE_82544GC_LOM 0x100D
+#define E1000_DEVICE_82540EM 0x100E
+#define E1000_DEVICE_82540EM_LOM 0x1015
+#define E1000_DEVICE_82540EP_LOM 0x1016
+#define E1000_DEVICE_82540EP 0x1017
+#define E1000_DEVICE_82540EP_LP 0x101E
+#define E1000_DEVICE_82545EM_COPPER 0x100F
+#define E1000_DEVICE_82545EM_FIBER 0x1011
+#define E1000_DEVICE_82545GM_COPPER 0x1026
+#define E1000_DEVICE_82545GM_FIBER 0x1027
+#define E1000_DEVICE_82545GM_SERDES 0x1028
+#define E1000_DEVICE_82546EB_COPPER 0x1010
+#define E1000_DEVICE_82546EB_FIBER 0x1012
+#define E1000_DEVICE_82546EB_QUAD_COPPER 0x101D
+#define E1000_DEVICE_82541EI 0x1013
+#define E1000_DEVICE_82541EI_MOBILE 0x1018
+#define E1000_DEVICE_82541ER_LOM 0x1014
+#define E1000_DEVICE_82541ER 0x1078
+#define E1000_DEVICE_82547GI 0x1075
+#define E1000_DEVICE_82541GI 0x1076
+#define E1000_DEVICE_82541GI_MOBILE 0x1077
+#define E1000_DEVICE_82541GI_LF 0x107C
+#define E1000_DEVICE_82546GB_COPPER 0x1079
+#define E1000_DEVICE_82546GB_FIBER 0x107A
+#define E1000_DEVICE_82546GB_SERDES 0x107B
+#define E1000_DEVICE_82546GB_PCIE 0x108A
+#define E1000_DEVICE_82546GB_QUAD_COPPER 0x1099
+#define E1000_DEVICE_82563EB 0x1096
+#define E1000_DEVICE_82547EI 0x1019
+#define E1000_DEVICE_82547EI_MOBILE 0x101A
+#define E1000_DEVICE_82571EB_COPPER 0x105E
+#define E1000_DEVICE_82571EB_FIBER 0x105F
+#define E1000_DEVICE_82571EB_SERDES 0x1060
+#define E1000_DEVICE_82571EB_QUAD_COPPER 0x10A4
+#define E1000_DEVICE_82571EB_QUAD_FIBER 0x10A5
+#define E1000_DEVICE_82571EB_QUAD_COPPER_LOWPROFILE 0x10BC
+#define E1000_DEVICE_82571EB_SERDES_DUAL 0x10D9
+#define E1000_DEVICE_82571EB_SERDES_QUAD 0x10DA
+#define E1000_DEVICE_82572EI_COPPER 0x107D
+#define E1000_DEVICE_82572EI_FIBER 0x107E
+#define E1000_DEVICE_82572EI_SERDES 0x107F
+#define E1000_DEVICE_82572EI 0x10B9
+#define E1000_DEVICE_82573E 0x108B
+#define E1000_DEVICE_82573E_IAMT 0x108C
+#define E1000_DEVICE_82573L 0x109A
+#define E1000_DEVICE_82574L 0x10D3
+#define E1000_DEVICE_82575EB 0x10A7 // TODO(gz): This cards needs more work
+#define E1000_DEVICE_82576EG 0x10C9 // TODO(gz): This cards needs more work
+#define E1000_DEVICE_I210 0x1533
+#define E1000_DEVICE_I350_EEPROM_LESS 0x151F
+#define E1000_DEVICE_I350_COPPER 0x1521
+#define E1000_DEVICE_I350_FIBER 0x1522
+#define E1000_DEVICE_I350_BACKPANE 0x1523
+#define E1000_DEVICE_I350_SGMII 0x1524
+#define E1000_DEVICE_I350_DUMMY 0x10A6
+#define E1000_DEVICE_82546GB_QUAD_COPPER_KSP3 0x10B5
+
+
+/**
+ * Group definitions for cards that share specification and quirks.
+ *
+ * e1000_82542 should be split into:
+ * e1000_82542_rev_2_1 and e1000_82542_rev_2_2.
+ * This can be figured out reading the PCI bus.
+ */
+typedef enum {
+ e1000_undefined = 0,
+ e1000_82542, /* revision 2.1 and 2.2 merged */
+ e1000_82543,
+ e1000_82544,
+ e1000_82540,
+ e1000_82545,
+ e1000_82545_rev_3,
+ e1000_82546,
+ e1000_82546_rev_3,
+ e1000_82541,
+ e1000_82541_rev_2,
+ e1000_82547,
+ e1000_82547_rev_2,
+ e1000_82563,
+ e1000_82571,
+ e1000_82572,
+ e1000_82573,
+ e1000_82574,
+ e1000_82575,
+ e1000_82576,
+ e1000_I210,
+ e1000_I350,
+ e1000_num_macs
+} e1000_mac_type_t;
+
+
+/**
+ * Hardware supported buffer sizes.
+ */
+typedef enum {
+ bsize_256 = 256,
+ bsize_512 = 512,
+ bsize_1024 = 1024,
+ bsize_2048 = 2048,
+ bsize_4096 = 4096,
+ bsize_8192 = 8192,
+ bsize_16384 = 16384
+} e1000_rx_bsize_t;
+
+/**
+ * Media types.
+ */
+typedef enum {
+ e1000_media_type_undefined,
+ e1000_media_type_fiber,
+ e1000_media_type_copper,
+ e1000_media_type_serdes,
+ e1000_num_media_types
+} e1000_media_type_t;
+
+
+
+/**
+ * Internal device info.
+ */
+typedef struct {
+ e1000_t *device;
+ uint32_t device_id;
+ e1000_media_type_t media_type;
+ e1000_mac_type_t mac_type;
+ e1000_rx_bsize_t rx_bsize;
+ bool tbi_combaility;
+} e1000_device_t ;
+
+
+e1000_mac_type_t e1000_get_mac_type(uint32_t vendor, uint32_t device_id);
+bool e1000_supported_device(uint32_t vendor, uint32_t device_id);
+bool e1000_link_up_led_status(e1000_device_t *dev);
+bool e1000_check_link_up(e1000_device_t *dev);
+bool e1000_auto_negotiate_link(e1000_device_t *dev);
+void *alloc_map_frame(vregion_flags_t attr, size_t size, struct capref *retcap);
+void e1000_hwinit(e1000_device_t *device, struct device_mem *bar_info,
+ int nr_allocated_bars,
+ volatile struct tx_desc **transmit_ring,
+ volatile union rx_desc **receive_ring,
+ int receive_buffers, int transmit_buffers,
+ uint8_t *macaddr,
+ bool user_macaddr, bool use_interrupt);
+
+
+/*****************************************************************
+ * On the i82541xx GPI_SP2 and GPI_SP3 are merged into one register
+ * value of bits.
+ *
+ ****************************************************************/
+static inline uint8_t i82541xx_get_icr_gpi_sdp(e1000_t *dev)
+{
+ e1000_intreg_t intreg = e1000_icr_rawrd(dev);
+ uint8_t sdp2 = e1000_intreg_gpi_sdp2_extract(intreg);
+ uint8_t sdp3 = e1000_intreg_gpi_sdp3_extract(intreg);
+ uint8_t sdp = sdp2 | (sdp3 << 1);
+
+ return sdp;
+}
+
+
+/*****************************************************************
+ * Barrelfish has no delay. We do it like this instead.
+ ****************************************************************/
+
+#include <barrelfish/sys_debug.h>
+
+#if 0
+/* apparently this does not work... getting usertrap #13 */
+extern cycles_t tscperms;
+
+static inline void usec_delay(unsigned int ms)
+{
+ if (tscperms == 0) {
+ errval_t err = sys_debug_get_tsc_per_ms(&tscperms);
+ assert(err_is_ok(err));
+ }
+ cycles_t end = (cycles_t)ms * tscperms + rdtsc();
+ while(rdtsc() < end) {
+ thread_yield();
+ }
+
+}
+#else
+static inline void usec_delay(unsigned int count)
+{
+ while(count--) {
+ __asm__ __volatile__("inb $0x80, %b0" :: "a"(0));
+ }
+}
+#endif
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2008, ETH Zurich. All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#ifndef __E1000_DESC_H__
+#define __E1000_DESC_H__
+
+typedef union {
+ uint16_t vlan;
+ struct {
+ uint16_t vlan :12;
+ uint16_t cfi :1;
+ uint16_t pri :3;
+ } __attribute__((packed)) bits;
+} __attribute__((packed)) vlan_tag_t;
+
+
+union rx_desc {
+ uint64_t raw[2] __attribute__((packed));
+ struct {
+ uint64_t buffer_address;
+ struct {
+ uint16_t length;
+ uint16_t checksum; /* reserved on: 82544GC/EI */
+ struct {
+ unsigned int dd :1;
+ unsigned int eop :1;
+ unsigned int ixsm :1;
+ unsigned int vp :1;
+ unsigned int udpcs :1; /* reserved on: 8254x */
+ unsigned int tcpcs :1;
+ unsigned int ipcs :1;
+ unsigned int pif :1;
+ } __attribute__ ((packed)) status;
+
+ union {
+ uint8_t errors;
+ struct {
+ uint8_t ce :1;
+ uint8_t seq :1; /* reserved on: 82541xx, 82547GI/EI, and 82540EP/EM only. */
+ uint8_t res0 :1; /* reserved on: 8254x */
+ uint8_t cxe :1; /* 82544GC/EI only */
+ uint8_t tcpe :1;
+ uint8_t ipe :1;
+ uint8_t rxe :1;
+ } __attribute__ ((packed)) bits;
+ } __attribute__ ((packed)) errors;
+
+ vlan_tag_t vlan;
+
+ } __attribute__ ((packed)) info;
+
+ } __attribute__ ((packed)) rx_read_format;
+
+} __attribute__ ((packed));
+
+
+struct tx_desc {
+ uint64_t buffer_address;
+ union {
+ uint64_t raw;
+ struct {
+ uint16_t data_len;
+ uint8_t cso;
+ union {
+ uint8_t raw;
+ struct {
+ uint8_t eop :1;
+ uint8_t ifcs :1;
+ uint8_t ic :1;
+ uint8_t rs :1;
+ uint8_t rsv :1;
+ uint8_t dext :1;
+ uint8_t vle :1;
+ uint8_t ide :1;
+ } __attribute__ ((packed)) d;
+ } __attribute__ ((packed)) cmd;
+ union {
+ uint8_t raw;
+ struct {
+ uint8_t dd :1;
+ uint8_t ec :1;
+ uint8_t lc :1;
+ uint8_t res :5;
+ } __attribute__ ((packed)) d;
+ } __attribute__ ((packed)) stat_rsv;
+ uint8_t css;
+ uint16_t special;
+ } __attribute__ ((packed)) legacy;
+
+ struct {
+ uint64_t data_len :20;
+ uint64_t dtype :4;
+ union {
+ uint8_t raw;
+ struct {
+ uint8_t eop :1;
+ uint8_t ifcs :1;
+ uint8_t tse :1;
+ uint8_t rs :1;
+ uint8_t rsv :1;
+ uint8_t dext :1;
+ uint8_t vle :1;
+ uint8_t ide :1;
+ } __attribute__ ((packed)) d;
+ } __attribute__ ((packed)) dcmd;
+
+ union {
+ uint8_t raw;
+ struct {
+ uint8_t dd :1;
+ uint8_t res :7;
+ } __attribute__ ((packed)) d;
+ } __attribute__ ((packed)) stat_rsv;
+
+ union {
+ uint8_t raw;
+ struct {
+ uint8_t ixsm : 1;
+ uint8_t txsm : 1;
+ uint8_t res : 6;
+ } __attribute__ ((packed)) d;
+ } __attribute__ ((packed)) popts;
+
+ vlan_tag_t vlan;
+
+ } __attribute__ ((packed)) extended_tcpip;
+ } __attribute__ ((packed)) ctrl;
+} __attribute__ ((packed));
+
+/*
+ * TCP/IP Context Descriptor Layout
+ *
+ * Provides access to enhanced checksum offload facility
+ * available in the Ethernet controllerfor TCP and UDP packets.
+ */
+union context_desc {
+ uint64_t raw;
+ struct {
+ uint8_t ipcss;
+ uint8_t ipcso;
+ uint16_t ipcse;
+ uint8_t tucss;
+ uint8_t tucso;
+ uint16_t tucse;
+ struct {
+ uint32_t paylen :20;
+ uint32_t dtype :4;
+ } __attribute__ ((packed)) pd;
+
+ union {
+ uint8_t raw;
+ struct {
+ uint8_t tcp :1;
+ uint8_t ip :1;
+ uint8_t tse :1;
+ uint8_t rs :1;
+ uint8_t rsv :1;
+ uint8_t dext :1;
+ uint8_t snap :1;
+ uint8_t ide :1;
+ } __attribute__ ((packed)) d;
+ } __attribute__ ((packed)) tucmd;
+
+ union {
+ uint8_t raw;
+ struct {
+ uint8_t dd :1;
+ uint8_t res :7;
+ } __attribute__ ((packed)) d;
+ } __attribute__ ((packed)) stat_rsv;
+
+ uint8_t hdrlen;
+ uint16_t mss;
+
+ } __attribute__ ((packed)) d;
+} __attribute__ ((packed));
+
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2008, ETH Zurich. All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+/*
+ * e1000_helpers.c
+ *
+ * Created on: Feb 14, 2013
+ * Author: mao
+ */
+#include "e1000n.h"
+#include "irqtest_debug.h"
+
+/*****************************************************************
+ *
+ *
+ ****************************************************************/
+e1000_mac_type_t e1000_get_mac_type(uint32_t vendor, uint32_t device_id)
+{
+ if (vendor == PCI_VENDOR_INTEL) {
+
+ switch (device_id) {
+ case E1000_DEVICE_82542:
+ return e1000_82542;
+ case E1000_DEVICE_82543GC_FIBER:
+ case E1000_DEVICE_82543GC_COPPER:
+ return e1000_82543;
+ case E1000_DEVICE_82544EI_COPPER:
+ case E1000_DEVICE_82544EI_FIBER:
+ case E1000_DEVICE_82544GC_COPPER:
+ case E1000_DEVICE_82544GC_LOM:
+ return e1000_82544;
+ case E1000_DEVICE_82540EM:
+ case E1000_DEVICE_82540EM_LOM:
+ case E1000_DEVICE_82540EP:
+ case E1000_DEVICE_82540EP_LOM:
+ case E1000_DEVICE_82540EP_LP:
+ return e1000_82540;
+ case E1000_DEVICE_82545EM_COPPER:
+ case E1000_DEVICE_82545EM_FIBER:
+ return e1000_82545;
+ case E1000_DEVICE_82545GM_COPPER:
+ case E1000_DEVICE_82545GM_FIBER:
+ case E1000_DEVICE_82545GM_SERDES:
+ return e1000_82545_rev_3;
+ case E1000_DEVICE_82546EB_COPPER:
+ case E1000_DEVICE_82546EB_FIBER:
+ case E1000_DEVICE_82546EB_QUAD_COPPER:
+ return e1000_82546;
+ case E1000_DEVICE_82546GB_COPPER:
+ case E1000_DEVICE_82546GB_FIBER:
+ case E1000_DEVICE_82546GB_SERDES:
+ case E1000_DEVICE_82546GB_PCIE:
+ case E1000_DEVICE_82546GB_QUAD_COPPER:
+ case E1000_DEVICE_82546GB_QUAD_COPPER_KSP3:
+ return e1000_82546_rev_3;
+ case E1000_DEVICE_82541EI:
+ case E1000_DEVICE_82541EI_MOBILE:
+ case E1000_DEVICE_82541ER_LOM:
+ return e1000_82541;
+ case E1000_DEVICE_82541ER:
+ case E1000_DEVICE_82541GI:
+ case E1000_DEVICE_82541GI_LF:
+ case E1000_DEVICE_82541GI_MOBILE:
+ return e1000_82541_rev_2;
+ case E1000_DEVICE_82547EI:
+ case E1000_DEVICE_82547EI_MOBILE:
+ return e1000_82547;
+ case E1000_DEVICE_82547GI:
+ return e1000_82547_rev_2;
+ case E1000_DEVICE_82563EB:
+ return e1000_82563;
+ case E1000_DEVICE_82571EB_COPPER:
+ case E1000_DEVICE_82571EB_FIBER:
+ case E1000_DEVICE_82571EB_SERDES:
+ case E1000_DEVICE_82571EB_SERDES_DUAL:
+ case E1000_DEVICE_82571EB_SERDES_QUAD:
+ case E1000_DEVICE_82571EB_QUAD_COPPER:
+ case E1000_DEVICE_82571EB_QUAD_FIBER:
+ case E1000_DEVICE_82571EB_QUAD_COPPER_LOWPROFILE:
+ return e1000_82571;
+ case E1000_DEVICE_82572EI_COPPER:
+ case E1000_DEVICE_82572EI_FIBER:
+ case E1000_DEVICE_82572EI_SERDES:
+ case E1000_DEVICE_82572EI:
+ return e1000_82572;
+ case E1000_DEVICE_82573E:
+ case E1000_DEVICE_82573E_IAMT:
+ case E1000_DEVICE_82573L:
+ return e1000_82573;
+ case E1000_DEVICE_82574L:
+ return e1000_82574;
+ case E1000_DEVICE_82575EB:
+ return e1000_82575;
+ case E1000_DEVICE_82576EG:
+ return e1000_82576;
+ case E1000_DEVICE_I210:
+ return e1000_I210;
+ case E1000_DEVICE_I350_EEPROM_LESS:
+ case E1000_DEVICE_I350_COPPER:
+ case E1000_DEVICE_I350_FIBER:
+ case E1000_DEVICE_I350_BACKPANE:
+ case E1000_DEVICE_I350_SGMII:
+ case E1000_DEVICE_I350_DUMMY:
+ return e1000_I350;
+ default:
+ IRQ_DEBUG("Unsupported device: vendor: 0x%x, device id: 0x%x\n", PCI_VENDOR_INTEL, device_id);
+ return e1000_undefined;
+ }
+ }
+
+ return e1000_undefined;
+}
+
+
+/*****************************************************************
+ * allocate a single frame, mapping it into our vspace with given
+ * attributes
+ ****************************************************************/
+void *alloc_map_frame(vregion_flags_t attr, size_t size, struct capref *retcap)
+{
+ struct capref frame;
+ errval_t err;
+ void *va;
+
+ err = frame_alloc(&frame, size, NULL);
+ if (err_is_fail(err)) {
+ IRQ_DEBUG("ERROR: frame_alloc failed.\n");
+ return NULL;
+ }
+
+ err = vspace_map_one_frame_attr(&va, size, frame, attr, NULL, NULL);
+
+ if (err_is_fail(err)) {
+ IRQ_DEBUG("Error: vspace_map_one_frame failed\n");
+ return NULL;
+ }
+
+ if (retcap != NULL) {
+ *retcap = frame;
+ }
+
+ return va;
+}
+
+cycles_t tscperms;
+
+
+
+
--- /dev/null
+/*
+ * Copyright (c) 2008, ETH Zurich. All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+/*
+ * e1000_hwinit.c
+ *
+ * Created on: Feb 12, 2013
+ * Author: mao
+ *
+ * Much referencing has been done against iPXE - Open Source Boot Firmware
+ * and the Linux kernel.
+ */
+#include "e1000n.h"
+#include "e1000n_hwinit.h"
+
+
+/*****************************************************************
+ * PHY
+ *
+ ****************************************************************/
+/*****************************************************************
+ * Writes a value to a PHY register
+ *
+ *****************************************************************/
+/* TODO */
+
+/***************************************************************************
+ * Is EEPROM NVM or FLASH.
+ *
+ * Returns true if EEPROM is of NVM type, else false.
+ *
+ ****************************************************************************/
+static bool e1000_is_onboard_nvm_eeprom(e1000_device_t *dev)
+{
+ if (dev->mac_type == e1000_82573) {
+ e1000_eecd_t eecd = e1000_eecd_rd(dev->device);
+ /* Isolate bits 15 & 16 */
+ uint8_t eecd_flash = ((eecd >> 15) & 0x03);
+
+ /* If both bits are set, device is Flash type */
+ if (eecd_flash == 0x03) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/*****************************************************************
+ * Read e1000 EEPROM.
+ *
+ * TODO: Fix semaphore support and eeprom release on devices that
+ * need this.
+ *
+ * dev - device to read eeprom from.
+ * offset - eeprom offset.
+ * data - returns data read.
+ * Returns: 0 on success, 1 on timeout and 2 if no eeprom.
+ ****************************************************************/
+static errval_t e1000_read_eeprom(e1000_device_t *dev, uint64_t offset,
+ uint16_t *data)
+{
+ int timeout = 1000;
+
+ /* Make shore there are no direct access requests on
+ * devices that support this.
+ */
+ if (dev->mac_type != e1000_82544) {
+ e1000_eecd_ee_req_wrf(dev->device, 1);
+ }
+
+ if (dev->mac_type != e1000_I210) {
+ while (!e1000_eecd_ee_gnt_rdf(dev->device)) {
+ usec_delay(1000);
+ }
+ }
+
+ /* EEPROM present */
+ // TODO(gz): Why does e1000 82574 have ee_pres == 0?
+ if (e1000_eecd_ee_pres_rdf(dev->device) ||
+ dev->mac_type == e1000_82574) {
+ e1000_eerd_ms_t eerd_ms = 0;
+ e1000_eerd_nm_t eerd_nm = 0;
+
+ switch (dev->mac_type) {
+ case e1000_82571:
+ case e1000_82572:
+ case e1000_82573:
+ case e1000_82574:
+ case e1000_82575:
+ case e1000_I210:
+ case e1000_I350:
+ /* These devices have SPI or Microwire EEPROMs */
+ eerd_ms = e1000_eerd_ms_start_insert(eerd_ms, 1);
+ eerd_ms = e1000_eerd_ms_addr_insert(eerd_ms, offset);
+ e1000_eerd_ms_wr(dev->device, eerd_ms);
+
+ while (e1000_eerd_ms_done_rdf(dev->device) == 0 && 0 < timeout--) {
+ usec_delay(1000);
+ }
+
+ *data = e1000_eerd_ms_data_rdf(dev->device);
+ break;
+ default:
+ /* These devices have standard EEPROMs */
+ eerd_nm = e1000_eerd_nm_start_insert(eerd_nm, 1);
+ eerd_nm = e1000_eerd_nm_addr_insert(eerd_nm, offset);
+ e1000_eerd_nm_wr(dev->device, eerd_nm);
+
+ while (e1000_eerd_ms_done_rdf(dev->device) == 0 && 0 < timeout--) {
+ usec_delay(1000);
+ }
+
+ *data = e1000_eerd_nm_data_rdf(dev->device);
+ break;
+ }
+ } else {
+ IRQ_DEBUG("No EEPROM pressent.\n");
+ e1000_eecd_ee_req_wrf(dev->device, 0);
+ return -1;
+ }
+
+ if (timeout) {
+ e1000_eecd_ee_req_wrf(dev->device, 0);
+ return 0; /* Success */
+ }
+
+ IRQ_DEBUG("EEPROM read timed out\n");
+
+ e1000_eecd_ee_req_wrf(dev->device, 0);
+ return 1;
+}
+
+/*****************************************************************
+ * Check for EEPROM Auto Read bit done.
+ *
+ ****************************************************************/
+static errval_t e1000_get_auto_rd_done(e1000_device_t *dev)
+{
+ uint16_t data;
+ errval_t err;
+
+ err = e1000_read_eeprom(dev, 0, &data);
+
+ /* PHY configuration from NVM just starts after EECD_AUTO_RD sets to high.
+ * Need to wait for PHY configuration completion before accessing NVM
+ * and PHY. */
+ if (dev->mac_type == e1000_82573) {
+ usec_delay(2500);
+ }
+
+ return err;
+}
+
+/******************************************************************************
+ * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the
+ * second function of dual function devices
+ *
+ *****************************************************************************/
+static errval_t e1000_read_mac_addr(e1000_device_t *dev, uint8_t *mac_addr)
+{
+ uint16_t offset;
+ uint16_t eeprom_data, i;
+ e1000_status_t status;
+
+ for (i = 0; i < MAC_ADDRESS_LEN; i += 2) {
+ offset = i >> 1;
+ if (e1000_read_eeprom(dev, offset, &eeprom_data) != 0) {
+ return 1;
+ }
+ mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF);
+ mac_addr[i + 1] = (uint8_t) (eeprom_data >> 8);
+ }
+
+ switch (dev->mac_type) {
+ default:
+ break;
+ case e1000_82546:
+ case e1000_82546_rev_3:
+ case e1000_82571:
+ /* test LAN ID to see if we need to modify the MAC from EEPROM */
+ status = e1000_status_rd(dev->device);
+ if (e1000_status_func_id_extract(status) == e1000_lan_b) {
+ mac_addr[5] ^= e1000_lan_b_mask;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+/*****************************************************************
+ * Reset the device and disable interrupts.
+ *
+ ****************************************************************/
+static int e1000_reset(e1000_device_t *dev)
+{
+ errval_t err = 0;
+ int timeout;
+
+ /* disable interrupts */
+ if (dev->mac_type == e1000_I350) {
+ e1000_eimc_wr(dev->device, 0xffffffff);
+ } else {
+ e1000_imc_rawwr(dev->device, 0xffffffff);
+ }
+
+ /* disable receive and transmit */
+ e1000_rctl_rawwr(dev->device, 0);
+ e1000_tctl_rawwr(dev->device, 0);
+
+ /* Delay to allow outstanding PCI transactions to complete before
+ * reseting the device */
+ usec_delay(1000);
+
+ /* Exit from GIO management mode */
+ if (dev->mac_type == e1000_82571 || dev->mac_type == e1000_82563
+ || dev->mac_type == e1000_82573) {
+ IRQ_DEBUG("Disabling GIO management.\n");
+
+ e1000_ctrl_gio_md_wrf(dev->device, 1);
+
+ timeout = 1000;
+ do {
+ usec_delay(10);
+ } while (e1000_ctrl_gio_md_rdf(dev->device) && 0 < timeout--);
+
+ if (timeout <= 0) {
+ IRQ_DEBUG("Error: Failed to disable GIO management.\n");
+ // return -1;
+ }
+ }
+
+ if (dev->mac_type == e1000_I350) {
+ IRQ_DEBUG("Disabling GIO management.\n");
+ e1000_ctrl_gio_md_wrf(dev->device, 1);
+ timeout = 1000;
+ do {
+ usec_delay(10);
+ } while (e1000_status_I350_gio_mes_rdf(dev->device) && 0 < timeout--);
+
+ if (timeout <= 0) {
+ IRQ_DEBUG("Error: Failed to disable GIO management.\n");
+ }
+ }
+
+ /* Must reset PHY before reseting the MAC */
+ if (dev->mac_type == e1000_82541 || dev->mac_type == e1000_82547) {
+ e1000_ctrl_phy_rst_wrf(dev->device, 1);
+ }
+
+ /* Must acquire MDIO ownership before MAC reset
+ * Ownership defaults to firmware after a reset */
+ if (dev->mac_type == e1000_82573) {
+ timeout = 1000;
+ do {
+ e1000_extcnf_ctrl_mdio_swown_wrf(dev->device, 1);
+ usec_delay(200);
+ } while (e1000_extcnf_ctrl_mdio_swown_rdf(dev->device) == 0
+ && 0 < timeout--);
+ }
+
+ IRQ_DEBUG("Resetting device.\n");
+
+ switch (dev->mac_type) {
+ case e1000_82545_rev_3:
+ case e1000_82546_rev_3:
+ /* Reset is performed on a shadow of the control register
+ * Where is this mentioned?
+ */
+ e1000_ctrldup_rst_wrf(dev->device, 1);
+ break;
+ case e1000_82540:
+ case e1000_82541:
+ case e1000_82541_rev_2:
+ case e1000_82544:
+ case e1000_82545:
+ case e1000_82546:
+ /* These controllers can't ack the 64-bit write when issuing the
+ * reset, so use IO-mapping as a workaround to issue the reset
+ * We don't support IO-mapped writing yet */
+ case e1000_I350:
+ e1000_ctrl_rst_wrf(dev->device, 1);
+ usec_delay(3000);
+ timeout = 1000;
+ timeout = 1000;
+ do {
+ usec_delay(10);
+ } while (e1000_ctrl_rst_rdf(dev->device) != 0 && 0 < timeout--);
+
+ if (timeout <= 0 || !e1000_status_pf_rst_done_rdf(dev->device)) {
+ IRQ_DEBUG("Error: Failed to reset device.\n");
+ }
+ break;
+ default:
+ e1000_ctrl_rst_wrf(dev->device, 1);
+
+ /* Wait for reset to clear */
+ timeout = 1000;
+ do {
+ usec_delay(10);
+ } while (e1000_ctrl_rst_rdf(dev->device) != 0 && 0 < timeout--);
+
+ if (timeout <= 0) {
+ IRQ_DEBUG("Error: Failed to reset device.\n");
+ }
+ break;
+ }
+
+
+ /* After MAC reset, force reload of EEPROM to restore power-on settings to
+ * device. Later controllers reload the EEPROM automatically, so just wait
+ * for reload to complete.
+ */
+ switch (dev->mac_type) {
+ case e1000_82542:
+ case e1000_82543:
+ case e1000_82544:
+ e1000_ctrlext_ee_rst_wrf(dev->device, 1);
+ /* Wait for EEPROM reload */
+ usec_delay(2000);
+ break;
+ case e1000_82541:
+ case e1000_82541_rev_2:
+ case e1000_82547:
+ case e1000_82547_rev_2:
+ /* Wait for EEPROM reload */
+ usec_delay(20000);
+ break;
+ case e1000_82573:
+ if (e1000_is_onboard_nvm_eeprom(dev) == false) {
+ usec_delay(100);
+ e1000_ctrlext_ee_rst_wrf(dev->device, 1);
+ }
+ err = e1000_get_auto_rd_done(dev);
+ break;
+ case e1000_I350:
+ timeout = 1000;
+ while(!e1000_eec_auto_rd_rdf(dev->device) && timeout--) {
+ usec_delay(100);
+ }
+ if (timeout <= 0) {
+ IRQ_DEBUG("Error: Autoloading of the EEPROM failed.\n");
+ }
+ usec_delay(3000);
+ break;
+ default:
+ err = e1000_get_auto_rd_done(dev);
+
+ break;
+ }
+
+ if (err) {
+ IRQ_DEBUG("Auto read by HW from EEPROM did not complete.\n");
+ }
+
+ /* Disable HW ARPs on ASF enabled adapters */
+ if (dev->mac_type >= e1000_82540 && dev->mac_type <= e1000_82547_rev_2) {
+ e1000_manc_arp_req_en_wrf(dev->device, 0);
+ }
+
+ if (dev->mac_type == e1000_82541 || dev->mac_type == e1000_82547) {
+ /* Configure activity LED after PHY reset */
+ e1000_ledctl_t ledctl;
+
+ // TODO:
+// e1000_phy_init_script(dev);
+
+ /* I guess this is not realy needed to setup card LEDs */
+ ledctl = e1000_ledctl_rd(dev->device);
+ ledctl &= IGP_ACTIVITY_LED_MASK;
+ ledctl = e1000_ledctl_led0_mode_insert(ledctl, 0x2);
+ ledctl = e1000_ledctl_led3_mode_insert(ledctl, 0x3);
+ e1000_ledctl_wr(dev->device, ledctl);
+ }
+
+ /* disable interrupts */
+ if (dev->mac_type == e1000_I350) {
+ e1000_eimc_wr(dev->device, 0xffffffff);
+ } else {
+ e1000_imc_rawwr(dev->device, 0xffffffff);
+ }
+
+ /* clear any pending interrupts */
+ e1000_icr_rd(dev->device);
+
+ debug_printf("Reset done..\n");
+
+ return 0;
+}
+
+/*****************************************************************
+ * Get media type.
+ *
+ ****************************************************************/
+static void e1000_set_media_type(e1000_device_t *dev)
+{
+ e1000_status_t status;
+
+ if (dev->mac_type != e1000_82543) {
+ dev->tbi_combaility = false;
+ }
+
+ switch (dev->device_id) {
+ case E1000_DEVICE_82545GM_SERDES:
+ case E1000_DEVICE_82546GB_SERDES:
+ case E1000_DEVICE_82571EB_SERDES:
+ case E1000_DEVICE_82571EB_SERDES_DUAL:
+ case E1000_DEVICE_82571EB_SERDES_QUAD:
+ case E1000_DEVICE_82572EI_SERDES:
+ dev->media_type = e1000_media_type_serdes;
+ break;
+ default:
+ switch (dev->mac_type) {
+ /*
+ * According to: 1.3.7 Additional Ethernet Controller Features
+ */
+ case e1000_82546:
+ case e1000_82545:
+ dev->media_type = e1000_media_type_serdes;
+ break;
+ case e1000_82542:
+ dev->media_type = e1000_media_type_fiber;
+ break;
+ case e1000_82573:
+ /* The STATUS.tbimode bit is reserved or reused for the this
+ * device.
+ */
+ dev->media_type = e1000_media_type_copper;
+ break;
+ default:
+ status = e1000_status_rd(dev->device);
+ if (e1000_status_tbimode_extract(status)) {
+ dev->media_type = e1000_media_type_fiber;
+ dev->tbi_combaility = false;
+ } else {
+ dev->media_type = e1000_media_type_copper;
+ }
+ break;
+ }
+ break;
+ }
+}
+
+/*****************************************************************
+ * Check link connection status.
+ *
+ ****************************************************************/
+bool e1000_check_link_up(e1000_device_t *dev)
+{
+ e1000_status_t status = e1000_status_rd(dev->device);
+
+ if (e1000_status_lu_extract(status)) {
+ return true;
+ }
+
+ return false;
+}
+
+/*****************************************************************
+ * Setup link auto-negotiation.
+ *
+ ****************************************************************/
+bool e1000_auto_negotiate_link(e1000_device_t *dev)
+{
+ bool link_up = false;
+
+ e1000_ctrlext_t ctrlext = e1000_ctrlext_rd(dev->device);
+ if (e1000_ctrlext_link_mode_extract(ctrlext) == e1000_serdes) {
+ IRQ_DEBUG("Auto-negotiation: serdes mode");
+ int timeout = 4000;
+ e1000_txcw_ane_wrf(dev->device, 1);
+ e1000_ctrl_lrst_wrf(dev->device, 1);
+
+ while (e1000_rxcw_anc_rdf(dev->device) == 0 && 0 < timeout--) {
+ usec_delay(10);
+ }
+
+ if (timeout > 0) {
+ link_up = true;
+ }
+
+ if (!link_up) {
+ e1000_txcw_ane_wrf(dev->device, 0);
+ }
+ } else {
+ int timeout = 4000;
+
+ // XXX: find out which cards really need this?
+ if (dev->mac_type < e1000_82571) {
+ e1000_ctrl_asde_wrf(dev->device, 1);
+ }
+
+ if (dev->mac_type == e1000_I350) {
+ e1000_ctrl_slu_wrf(dev->device, 1);
+ e1000_ctrl_frcspd_wrf(dev->device, 0);
+ e1000_ctrl_frcdplx_wrf(dev->device, 0);
+ }
+
+ while (e1000_check_link_up(dev) == false && 0 < timeout--) {
+ usec_delay(10);
+ }
+
+ link_up = e1000_check_link_up(dev);
+ }
+
+ IRQ_DEBUG("Auto-negotiate link status: %s\n", e1000_check_link_up(dev) ? "link-up" : "link-down");
+ return link_up;
+}
+
+/*****************************************************************
+ * Set RX buffer size and enable receive unit.
+ *
+ ****************************************************************/
+static void e1000_set_rxbsize(e1000_device_t *dev, e1000_rx_bsize_t rx_bsize)
+{
+ uint8_t bsize;
+ uint8_t bsex;
+ e1000_rctl_t rctl;
+
+ switch (rx_bsize) {
+ case bsize_16384:
+ bsize = 0x1;
+ bsex = 1;
+ break;
+ case bsize_8192:
+ bsize = 0x2;
+ bsex = 1;
+ break;
+ case bsize_4096:
+ bsize = 0x3;
+ bsex = 1;
+ break;
+ case bsize_2048:
+ bsize = 0x0;
+ bsex = 0;
+ break;
+ case bsize_1024:
+ bsize = 0x1;
+ bsex = 0;
+ break;
+ case bsize_512:
+ bsize = 0x2;
+ bsex = 0;
+ break;
+ case bsize_256:
+ default:
+ bsize = 0x3;
+ bsex = 0;
+ break;
+ }
+
+ rctl = e1000_rctl_rd(dev->device);
+ rctl = e1000_rctl_bsize_insert(rctl, bsize);
+ rctl = e1000_rctl_bsex_insert(rctl, bsex);
+ rctl = e1000_rctl_bam_insert(rctl, 1);
+ e1000_rctl_wr(dev->device, rctl);
+
+ e1000_rctl_en_wrf(dev->device, 1);
+}
+
+/*****************************************************************
+ * Set serial interface mode.
+ *
+ ****************************************************************/
+static void e1000_set_serial_interface_mode(e1000_device_t *dev)
+{
+ e1000_ctrlext_t ctrlext = e1000_ctrlext_rd(dev->device);
+
+ if (dev->mac_type == e1000_82544) {
+ assert(!"XXX: How do we set these ones up?");
+ return;
+ }
+
+ if (dev->mac_type == e1000_82573) {
+ ctrlext = e1000_ctrlext_link_mode_insert(ctrlext, e1000_l82573);
+ }
+ else if (dev->media_type == e1000_media_type_serdes) {
+ ctrlext = e1000_ctrlext_link_mode_insert(ctrlext, e1000_serdes);
+ }
+ else {
+ ctrlext = e1000_ctrlext_link_mode_insert(ctrlext, e1000_glci);
+ }
+ /* write serial interface mode */
+ e1000_ctrlext_wr(dev->device, ctrlext);
+}
+
+/*****************************************************************
+ * Set Transmit Inter Packet Gap (TIPG)
+ *
+ ****************************************************************/
+static void e1000_set_tipg(e1000_device_t *dev)
+{
+ e1000_tipg_t tipg = 0;
+
+ if ((dev->mac_type <= e1000_82547_rev_2)
+ && (dev->media_type == e1000_media_type_fiber
+ || dev->media_type == e1000_media_type_serdes)) {
+ tipg = e1000_tipg_ipgt_insert(tipg, DEFAULT_825XX_TIPG_IPGT_FIBER);
+ } else {
+ tipg = e1000_tipg_ipgt_insert(tipg, DEFAULT_825XX_TIPG_IPGT_COPPER);
+ }
+
+ switch (dev->mac_type) {
+ case e1000_82542:
+ tipg = e1000_tipg_ipgt_insert(tipg, DEFAULT_825XX_TIPG_IPGT);
+ tipg = e1000_tipg_ipgr1_insert(tipg, DEFAULT_82542_TIPG_IPGR1);
+ tipg = e1000_tipg_ipgr2_insert(tipg, DEFAULT_82542_TIPG_IPGR2);
+ break;
+ case e1000_82575:
+ case e1000_82576:
+ case e1000_I210:
+ case e1000_I350:
+ tipg = e1000_tipg_ipgr1_insert(tipg, DEFAULT_82575_TIPG_IPGR1);
+ tipg = e1000_tipg_ipgr2_insert(tipg, DEFAULT_82575_TIPG_IPGR2);
+ break;
+ default:
+ tipg = e1000_tipg_ipgr1_insert(tipg, DEFAULT_82543_TIPG_IPGR1);
+ tipg = e1000_tipg_ipgr2_insert(tipg, DEFAULT_82543_TIPG_IPGR2);
+ break;
+ }
+
+ e1000_tipg_wr(dev->device, tipg);
+}
+
+/*****************************************************************
+ * Configure card transmit
+ *
+ ****************************************************************/
+static void e1000_configure_tx(e1000_device_t *dev)
+{
+ // TODO: configure_tx
+ if (dev->mac_type >= e1000_82571 && dev->mac_type < e1000_82575) {
+ /* Reset delay timers after every interrupt */
+ e1000_ctrlext_int_tca_wrf(dev->device, 1);
+ }
+
+ /* Set Transmit Inter-Packet Gap (TIPG)*/
+ e1000_set_tipg(dev);
+}
+
+/*****************************************************************
+ * Configure device receive
+ *
+ ****************************************************************/
+static void e1000_configure_rx(e1000_device_t *dev)
+{
+ /* set buffer size and enable receive unit */
+ e1000_set_rxbsize(dev, dev->rx_bsize);
+}
+
+/*****************************************************************
+ * Initialize the hardware
+ *
+ ****************************************************************/
+void e1000_hwinit(e1000_device_t *dev, struct device_mem *bar_info,
+ int nr_allocated_bars, volatile struct tx_desc **transmit_ring,
+ volatile union rx_desc **receive_ring, int receive_buffers,
+ int transmit_buffers, uint8_t *mac_addr,
+ bool user_mac_addr, bool use_interrupt)
+{
+ struct frame_identity frameid = { .base = 0, .bits = 0 };
+ struct capref frame;
+ errval_t err;
+
+ IRQ_DEBUG("Initializing network device.\n");
+
+ if (nr_allocated_bars < 1) {
+ E1000_PRINT_ERROR("Error: Not enough PCI bars allocated. Can not initialize network device.\n");
+ exit(1);
+ }
+
+ err = map_device(&bar_info[0]);
+ if (err_is_fail(err)) {
+ E1000_PRINT_ERROR("Error: map_device failed. Can not initialize network device.\n");
+ exit(err);
+ }
+
+ e1000_initialize(dev->device, (void *) bar_info[0].vaddr);
+
+ /*
+ * XXX: This is a check if we are using legacy descriptors and virtual functions
+ * are enabled to display an error message and abort execution.
+ */
+ if (dev->mac_type == e1000_I350 && E1000_USE_LEGACY_DESC) {
+ if(e1000_txswc_loopback_en_rdf(dev->device)
+ || e1000_status_I350_vfe_rdf(dev->device)
+ || e1000_txswc_macas_rdf(dev->device)
+ || e1000_txswc_vlanas_rdf(dev->device)) {
+ debug_printf("ERROR: legacy descriptors used with Advanced Features!\n");
+ exit(1);
+ };
+
+ }
+
+ IRQ_DEBUG("Setting media type.\n");
+ e1000_set_media_type(dev);
+
+ err = e1000_reset(dev);
+ if (err) {
+ IRQ_DEBUG("Error during e1000_reset! Exiting.");
+ exit(1);
+ }
+
+ IRQ_DEBUG("Deasserting PHY reset.\n");
+ e1000_ctrl_phy_rst_wrf(dev->device, 0);
+
+ IRQ_DEBUG("Setting serial interface mode.\n");
+ e1000_set_serial_interface_mode(dev);
+
+ IRQ_DEBUG("Auto negotiating link.\n");
+ if (!e1000_auto_negotiate_link(dev)) {
+ IRQ_DEBUG("Auto negotiating link failed, force link-up in driver.\n");
+ e1000_ctrl_slu_wrf(dev->device, 0x1);
+ //set full-duplex
+ e1000_ctrl_fd_wrf(dev->device, 0x1);
+ e1000_ctrl_speed_wrf(dev->device, e1000_status_speed_rdf(dev->device));
+ }
+
+ if (dev->mac_type == e1000_I350) {
+ e1000_ctrl_rfce_wrf(dev->device, 0);
+ e1000_ctrl_tfce_wrf(dev->device, 0);
+ }
+ /* set flow control */
+ e1000_fcal_wr(dev->device, 0);
+ e1000_fcah_wr(dev->device, 0);
+ e1000_fct_wr(dev->device, 0);
+
+ /* initialize statistic counters */
+ for (int i = 0; i < e1000_statsregs_length; i++) {
+ e1000_statsregs_rd(dev->device, i);
+ }
+
+ /* --------------------- MAC address setup --------------------- */
+ IRQ_DEBUG("Setting up MAC address.\n");
+
+ /* is a valid MAC already present? */
+ /* This will always return false due to hardware/software reset */
+ bool mac_present = e1000_rah_av_rdf(dev->device, 0);
+
+ if (user_mac_addr || !mac_present) {
+ uint16_t mac_word0, mac_word1, mac_word2;
+ e1000_rah_t rah = 0;
+
+ if (user_mac_addr == false)
+ /* read MAC from EEPROM */
+ {
+ e1000_read_mac_addr(dev, mac_addr);
+ }
+
+ mac_word0 = (((uint16_t) mac_addr[1]) << 8) | mac_addr[0];
+ mac_word1 = (((uint16_t) mac_addr[3]) << 8) | mac_addr[2];
+ mac_word2 = (((uint16_t) mac_addr[5]) << 8) | mac_addr[4];
+
+ if (user_mac_addr == false && mac_word0 == 0 && mac_word1 == 0
+ && mac_word2 == 0) {
+ E1000_PRINT_ERROR("Error: Failed to read MAC address from EEPROM.\n");
+ E1000_PRINT_ERROR("Try setting it manually. Use -h for help.\n");
+ exit(1);
+ }
+
+ /* program card's address with MAC */
+ e1000_rah_wr(dev->device, 0, 0);
+ e1000_ral_wr(dev->device, 0, (mac_word0 | ((mac_word1) << 16)));
+ rah = e1000_rah_rah_insert(rah, mac_word2);
+ rah = e1000_rah_av_insert(rah, 1);
+ e1000_rah_wr(dev->device, 0, rah);
+ }
+
+ /* cache MAC for stack to see */
+ uint64_t mac_hi = e1000_rah_rah_rdf(dev->device, 0);
+ uint64_t mac = e1000_ral_rd(dev->device, 0) + (mac_hi << 32);
+ mac_addr[0] = mac & 0xff;
+ mac_addr[1] = (mac >> 8) & 0xff;
+ mac_addr[2] = (mac >> 16) & 0xff;
+ mac_addr[3] = (mac >> 24) & 0xff;
+ mac_addr[4] = (mac >> 32) & 0xff;
+ mac_addr[5] = (mac >> 40) & 0xff;
+
+ IRQ_DEBUG("MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
+
+ /* clear all other filers (clear high-to-low (13.4.3)) */
+ for (int i = 1; i < e1000_ral_length; i++) {
+ e1000_rah_wr(dev->device, i, 0);
+ e1000_ral_wr(dev->device, i, 0);
+ }
+
+ /* clear MTA table */
+ for (int i = 0; i < e1000_mta_length; i++) {
+ e1000_mta_wr(dev->device, i, 0);
+ }
+
+ /* --------------------- receive setup --------------------- */
+ /* receive descriptor control */
+ if (dev->mac_type == e1000_82575
+ || dev->mac_type == e1000_82576
+ || dev->mac_type == e1000_I210) {
+ e1000_rxdctl_82575_t rxdctl = 0;
+
+ rxdctl = e1000_rxdctl_82575_enable_insert(rxdctl, 1);
+ rxdctl = e1000_rxdctl_82575_wthresh_insert(rxdctl, 1);
+ e1000_rxdctl_82575_wr(dev->device, 0, rxdctl);
+ } else if (dev->mac_type != e1000_I350) {
+ e1000_rxdctl_t rxdctl = 0;
+
+ rxdctl = e1000_rxdctl_gran_insert(rxdctl, 1);
+ rxdctl = e1000_rxdctl_wthresh_insert(rxdctl, 1);
+ e1000_rxdctl_wr(dev->device, 0, rxdctl);
+
+ e1000_rfctl_exsten_wrf(dev->device, 0);
+ }
+
+ /* Allocate and map frame for receive ring */
+ *receive_ring = alloc_map_frame(VREGION_FLAGS_READ_WRITE_NOCACHE,
+ sizeof(union rx_desc) * receive_buffers, &frame);
+
+ if (*receive_ring == NULL) {
+ E1000_PRINT_ERROR("Error: Failed to allocate map frame.\n");
+ exit(1);
+ }
+
+ err = invoke_frame_identify(frame, &frameid);
+ if (err_is_fail(err)) {
+ E1000_PRINT_ERROR("Error: Failed to invoke frame identify.\n");
+ exit(1);
+ }
+
+ if (dev->mac_type == e1000_I350) {
+ /* If VLANs are not used, software should clear VFE. */
+ e1000_rctl_vfe_wrf(dev->device, 0);
+
+ /* Set up the MTA (Multicast Table Array) by software. This means
+ * zeroing all entries initially and adding in entries as requested. */
+ for (int i = 0; i < 128; ++i) {
+ e1000_mta_wr(dev->device, i, 0);
+ }
+
+ /* Software should program RDLEN[n] register only when queue is disabled */
+ e1000_rdbal_I350_wr(dev->device, 0, frameid.base & 0xffffffff);
+ e1000_rdbah_I350_wr(dev->device, 0, (frameid.base >> 32) & 0xffffffff);
+ e1000_rdlen_I350_len_wrf(dev->device, 0, (receive_buffers / 8));
+
+ /* Initialize receive head and tail pointers */
+ e1000_rdh_I350_wr(dev->device, 0, 0);
+ e1000_rdt_I350_wr(dev->device, 0, 0);
+
+ /* Program SRRCTL of the queue according to the size of the buffers,
+ * the required header handling and the drop policy. */
+ e1000_srrctl_t srrctl = 0;
+ srrctl = e1000_srrctl_bsizeheader_insert(srrctl, 0);
+ e1000_srrctl_wr(dev->device, 0, srrctl);
+
+ /* Enable the queue by setting RXDCTL.ENABLE. In the case of queue zero,
+ * the enable bit is set by default - so the ring parameters should be
+ * set before RCTL.RXEN is set. */
+ e1000_rxdctl_I350_t rxdctl = 0;
+ rxdctl = e1000_rxdctl_I350_enable_insert(rxdctl, 1);
+ rxdctl = e1000_rxdctl_I350_wthresh_insert(rxdctl, 1);
+ e1000_rxdctl_I350_wr(dev->device, 0, rxdctl);
+
+ /* Poll the RXDCTL register until the ENABLE bit is set. The tail should
+ * not be bumped before this bit was read as one. */
+ uint16_t timeout = 1000;
+ while(!e1000_rxdctl_I350_enable_rdf(dev->device, 0) && timeout--) {
+ usec_delay(10);
+ }
+ if (timeout <= 0) {
+ IRQ_DEBUG("ERROR: failed to enable the RX queue\n");
+ }
+
+ } else {
+ /* tell card where receive ring is */
+ e1000_rdbal_wr(dev->device, 0, frameid.base & 0xffffffff);
+ e1000_rdbah_wr(dev->device, 0, (frameid.base >> 32) & 0xffffffff);
+ e1000_rdlen_len_wrf(dev->device, 0, (receive_buffers / 8));
+
+ /* Initialize receive head and tail pointers */
+ e1000_rdh_wr(dev->device, 0, 0);
+ e1000_rdt_wr(dev->device, 0, 0);
+ }
+ e1000_configure_rx(dev);
+
+
+ /* --------------------- transmit setup --------------------- */
+ if (dev->mac_type == e1000_82575
+ || dev->mac_type == e1000_82576
+ || dev->mac_type == e1000_I210) {
+ e1000_txdctl_82575_t txdctl = 0;
+ txdctl = e1000_txdctl_82575_enable_insert(txdctl, 1);
+ txdctl = e1000_txdctl_82575_priority_insert(txdctl, 1);
+ e1000_txdctl_82575_wr(dev->device, 0, txdctl);
+ } else if (dev->mac_type != e1000_I350){
+ e1000_txdctl_t txdctl = 0;
+ txdctl = e1000_txdctl_gran_insert(txdctl, 1);
+ e1000_txdctl_wr(dev->device, 0, txdctl);
+ }
+
+ /* allocate and map frame for transmit ring */
+ *transmit_ring = alloc_map_frame(VREGION_FLAGS_READ_WRITE_NOCACHE,
+ sizeof(struct tx_desc) * transmit_buffers, &frame);
+
+ if (*transmit_ring == NULL) {
+ E1000_PRINT_ERROR("Error: Failed to allocate map frame.\n");
+ exit(1);
+ }
+
+ err = invoke_frame_identify(frame, &frameid);
+ if (err_is_fail(err)) {
+ E1000_PRINT_ERROR("Error: Failed to invoke frame identify.\n");
+ exit(1);
+ }
+
+ if (dev->mac_type == e1000_I350) {
+ /* Software should program TDLEN[n] register only when queue is disabled */
+ e1000_tdbal_I350_wr(dev->device, 0, frameid.base & 0xffffffff);
+ e1000_tdbah_I350_wr(dev->device, 0, frameid.base >> 32);
+ e1000_tdlen_I350_len_wrf(dev->device, 0, (transmit_buffers / 8));
+ e1000_tdh_I350_wr(dev->device, 0, 0);
+ e1000_tdt_I350_wr(dev->device, 0, 0);
+
+ /* Program the TXDCTL register with the desired TX descriptor write
+ * back policy. Suggested values are:
+ — WTHRESH = 1b
+ — All other fields 0b.
+ */
+ e1000_txdctl_I350_t txdctl = 0;
+ txdctl = e1000_txdctl_I350_priority_insert(txdctl, 1);
+ txdctl = e1000_txdctl_I350_wthresh_insert(txdctl, 1);
+ e1000_txdctl_I350_wr(dev->device, 0, txdctl);
+
+ /* If needed, set the TDWBAL/TWDBAH to enable head write back */
+ e1000_tdwbal_wr(dev->device, 0, 0);
+ e1000_tdwbah_wr(dev->device, 0, 0);
+
+ /* Enable the queue using TXDCTL.ENABLE (queue zero is enabled by default). */
+ e1000_txdctl_I350_enable_wrf(dev->device, 0, 1);
+
+ /* Poll the TXDCTL register until the ENABLE bit is set. */
+ uint16_t timeout = 1000;
+ while(!e1000_txdctl_I350_enable_rdf(dev->device, 0) && timeout--) {
+ usec_delay(10);
+ }
+ if (timeout <= 0) {
+ IRQ_DEBUG("ERROR: failed to enable the TX queue\n");
+ }
+
+ } else {
+ /* tell card about our transmit ring */
+ e1000_tdbal_wr(dev->device, 0, frameid.base & 0xffffffff);
+ e1000_tdbah_wr(dev->device, 0, frameid.base >> 32);
+ e1000_tdlen_len_wrf(dev->device, 0, (transmit_buffers / 8));
+ e1000_tdh_wr(dev->device, 0, 0);
+ e1000_tdt_wr(dev->device, 0, 0);
+ }
+ e1000_configure_tx(dev);
+
+ /* enable transmit */
+
+ e1000_tctl_t tctl = 0;
+ if (dev->mac_type == e1000_I350) {
+ tctl = e1000_tctl_ct_insert(tctl, 0xf);
+ } else {
+ tctl = e1000_tctl_ct_insert(tctl, 0x10);
+ }
+ tctl = e1000_tctl_en_insert(tctl, 1);
+ tctl = e1000_tctl_psp_insert(tctl, 1);
+ tctl = e1000_tctl_bst_insert(tctl, 0x40);
+ e1000_tctl_wr(dev->device, tctl);
+
+ /* Enable interrupts */
+ if (use_interrupt) {
+
+ /* Enable interrupt throttling rate.
+ *
+ * The optimal performance setting for this register is very system and
+ * configuration specific. A initial suggested range is 651-5580 (28Bh - 15CCh).
+ * The value 0 will disable interrupt throttling
+ */
+ if (dev->mac_type == e1000_82575
+ || dev->mac_type == e1000_82576
+ || dev->mac_type == e1000_I210
+ || dev->mac_type == e1000_I350) {
+ e1000_eitr_interval_wrf(dev->device, 0, 5580);
+ //e1000_eitr_interval_wrf(dev->device, 0, 10);
+ }
+ else {
+ e1000_itr_interval_wrf(dev->device, 5580);
+ //e1000_itr_interval_wrf(dev->device, 10);
+ }
+
+ e1000_intreg_t intreg = 0;
+
+ intreg = e1000_intreg_lsc_insert(intreg, 1);
+ intreg = e1000_intreg_rxt0_insert(intreg, 1);
+
+ intreg = e1000_intreg_txqe_insert(intreg, 1);
+ intreg = e1000_intreg_txdw_insert(intreg, 1);
+ e1000_ims_wr(dev->device, intreg);
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2008, ETH Zurich. All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+/*
+ * e1000_hw.h
+ *
+ * Created on: Feb 13, 2013
+ * Author: mao
+ */
+
+#ifndef E1000_HWINIT_H_
+#define E1000_HWINIT_H_
+
+
+/* Default values for the transmit IPG register */
+#define DEFAULT_825XX_TIPG_IPGT 10
+#define DEFAULT_825XX_TIPG_IPGT_FIBER 9
+#define DEFAULT_825XX_TIPG_IPGT_COPPER 8
+#define DEFAULT_82544_TIPG_IPGT_FIBER 6
+#define DEFAULT_82544_TIPG_IPGT_COPPER 8
+
+#define DEFAULT_82575_TIPG_IPGR1 8
+#define DEFAULT_82542_TIPG_IPGR1 2
+#define DEFAULT_82543_TIPG_IPGR1 10
+
+#define DEFAULT_82575_TIPG_IPGR2 7
+#define DEFAULT_82542_TIPG_IPGR2 10
+#define DEFAULT_82543_TIPG_IPGR2 10
+
+#define IGP_ACTIVITY_LED_MASK 0xFFFFF0FF
+
+#endif /* E1000_HW_H_ */
--- /dev/null
+/**
+ * \file
+ * \brief A simple test for checking if lpc_timer works
+ * It tests periodic timers implemented by timer library.
+ * test_A: When no arguments are given, then timer_test will run test_A
+ * which starts two periodic timers and stops them after 100 callbacks
+ * from each of them.
+ *
+ * test_B: When there are command line arguments given, then timer_test
+ * will run test_B. This test registers three periodic timer and stops
+ * when 100 callbacks are received from all three timers.
+ *
+ * It is advised to run both test_A and test_B at same time. It can be
+ * done by inserting following lines into the menu.lst
+ * module /x86_64/sbin/lpc_timer core=1
+ * module /x86_64/sbin/timer_test core=2
+ * module /x86_64/sbin/timer_test core=3 B
+ *
+ */
+
+/*
+ * Copyright (c) 2007, 2008, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/nameservice_client.h>
+#include <barrelfish/waitset.h>
+#include <pci/pci.h>
+#include "irqtest_debug.h"
+#include "e1000n.h"
+#include "stdint.h"
+
+/*****************************************************************
+ * Local states:
+ *****************************************************************/
+static uint32_t class = PCI_CLASS_ETHERNET;
+static uint32_t subclass = PCI_DONT_CARE;
+static uint32_t bus = PCI_DONT_CARE;
+static uint32_t device = PCI_DONT_CARE;
+static uint32_t function = PCI_DONT_CARE;
+//static uint32_t deviceid = 0x1079; //sbrinz1/2
+static uint32_t deviceid = 0x107d; //appenzeller
+static uint32_t vendor = PCI_VENDOR_INTEL;
+static uint32_t program_interface = PCI_DONT_CARE;
+static e1000_mac_type_t mac_type = e1000_undefined;
+
+/*****************************************************************
+ * Local states:
+ *****************************************************************/
+static uint64_t minbase = -1;
+static uint64_t maxbase = -1;
+
+/*****************************************************************
+ * e1000 states:
+ *****************************************************************/
+static e1000_t e1000;
+static e1000_device_t e1000_device;
+static bool e1000_initialized = false;
+static uint8_t mac_address[MAC_ADDRESS_LEN]; /* buffers the card's MAC address upon card reset */
+
+/*****************************************************************
+ * Receive and transmit
+ *****************************************************************/
+static e1000_rx_bsize_t receive_buffer_size = bsize_16384;
+static volatile struct tx_desc *transmit_ring;
+
+//receive
+static volatile union rx_desc *receive_ring;
+
+
+//static uint32_t receive_bufptr = 0;
+
+static void **receive_opaque = NULL;
+
+
+#define DRIVER_RECEIVE_BUFFERS (1024 * 8)
+#define DRIVER_TRANSMIT_BUFFERS (1024 * 8)
+
+#define PACKET_SIZE_LIMIT 1073741824 /* 1 Gigabyte */
+
+
+
+
+
+
+
+static void setup_internal_memory(void)
+{
+ receive_opaque = calloc(sizeof(void *), DRIVER_RECEIVE_BUFFERS);
+ assert(receive_opaque != NULL );
+}
+
+
+
+
+static void e1000_init_fn(struct device_mem *bar_info, int nr_allocated_bars)
+{
+ IRQ_DEBUG("Starting hardware initialization.\n");
+ e1000_hwinit(&e1000_device, bar_info, nr_allocated_bars, &transmit_ring,
+ &receive_ring, DRIVER_RECEIVE_BUFFERS, DRIVER_TRANSMIT_BUFFERS,
+ mac_address, false, 1);
+
+ // Disable interrupt throttling
+ e1000_itr_interval_wrf(e1000_device.device, 0);
+ e1000_eitr_interval_wrf(e1000_device.device, 0, 0);
+
+ e1000_initialized = true;
+ IRQ_DEBUG("Hardware initialization complete.\n");
+
+ setup_internal_memory();
+
+}
+
+/*****************************************************************
+ * e1000 interrupt handler
+ *
+ ****************************************************************/
+static int64_t interrupt_counter = 0;
+static int64_t int_trigger_counter = 0;
+static void e1000_interrupt_handler_fn(void *arg)
+{
+ /* Read interrupt cause, this also acknowledges the interrupt */
+ e1000_intreg_t icr = e1000_icr_rd(e1000_device.device);
+
+ printf("#### interrupt handler called: %"PRIi64"\n", interrupt_counter);
+ ++interrupt_counter;
+
+ if (e1000_intreg_rxt0_extract(icr) == 0) {
+ return;
+ }
+}
+
+static void e1000_reregister_handler(void *arg)
+{
+ errval_t err;
+ printf("%s:%s:%d:\n", __FILE__, __FUNCTION__, __LINE__);
+ err = pci_reregister_irq_for_device(
+ class, subclass, program_interface,
+ vendor, deviceid, bus, device, function,
+ e1000_interrupt_handler_fn, NULL,
+ e1000_reregister_handler, NULL);
+ if (err_is_fail(err)) {
+ DEBUG_ERR(err, "pci_reregister_irq_for_device");
+ }
+
+ return;
+}
+
+
+int main(int argc, char **argv)
+{
+ errval_t err;
+
+ /** Parse command line arguments. */
+ IRQ_DEBUG("irq test started.\n");
+
+ IRQ_DEBUG("argc = %d\n", argc);
+
+
+
+ for (int i = 1; i < argc; i++) {
+ IRQ_DEBUG("arg %d = %s\n", i, argv[i]);
+ if (strcmp(argv[i], "auto") == 0) {
+ continue;
+ }
+ if (strncmp(argv[i], "affinitymin=", strlen("affinitymin=")) == 0) {
+ minbase = atol(argv[i] + strlen("affinitymin="));
+ IRQ_DEBUG("minbase = %lu\n", minbase);
+ } else if (strncmp(argv[i], "affinitymax=", strlen("affinitymax="))
+ == 0) {
+ maxbase = atol(argv[i] + strlen("affinitymax="));
+ IRQ_DEBUG("maxbase = %lu\n", maxbase);
+ } else if(strncmp(argv[i],"bus=",strlen("bus=")-1)==0) {
+ bus = atol(argv[i] + strlen("bus="));
+ IRQ_DEBUG("bus = %ul\n", bus);
+ } else if (strncmp(argv[i], "device=", strlen("device=")) == 0) {
+ device = atol(argv[i] + strlen("device="));
+ IRQ_DEBUG("device = %ul\n", device);
+ } else if (strncmp(argv[i], "function=", strlen("function=")) == 0) {
+ function = atol(argv[i] + strlen("function="));
+ IRQ_DEBUG("function = %u\n", function);
+ } else if (strncmp(argv[i], "deviceid=", strlen("deviceid=")) == 0) {
+ deviceid = strtoul(argv[i] + strlen("deviceid="), NULL, 0);
+ IRQ_DEBUG("deviceid = %u\n", deviceid);
+ } else if (strcmp(argv[i], "-h") == 0 ||
+ strcmp(argv[i], "--help") == 0) {
+ //exit_help(argv[0]);
+ } else {
+ IRQ_DEBUG("Parsed Kaluga device address %s.\n", argv[i]);
+ }
+ } // end for :
+
+ if ((minbase != -1) && (maxbase != -1)) {
+ IRQ_DEBUG("set memory affinity [%lx, %lx]\n", minbase, maxbase);
+ ram_set_affinity(minbase, maxbase);
+ }
+
+
+ IRQ_DEBUG("Starting standalone driver.\n");
+
+ /* Check if forced device id and vendor is known to be supported. */
+ mac_type = e1000_get_mac_type(vendor, deviceid);
+ if(mac_type == e1000_undefined){
+ IRQ_DEBUG("WARNING: Passed deviceid unknown.\n");
+ }
+
+
+ /* Setup known device info */
+ e1000_device.device = &e1000;
+ e1000_device.mac_type = mac_type;
+ e1000_device.device_id = deviceid;
+ if (e1000_device.mac_type == e1000_82575
+ || e1000_device.mac_type == e1000_82576
+ || e1000_device.mac_type == e1000_I210
+ || e1000_device.mac_type == e1000_I350) {
+ // These cards do not have a bsex reg entry
+ // therefore, we can't use 16384 buffer size.
+ // If we use smaller buffers than 2048 bytes the
+ // eop bit on received packets might not be set in case the package
+ // is biger than the receive buffer size and we don't handle these
+ // cases currently.
+ e1000_device.rx_bsize = bsize_2048;
+ } else {
+ e1000_device.rx_bsize = receive_buffer_size;
+ }
+ e1000_device.media_type = e1000_media_type_undefined;
+
+
+ IRQ_DEBUG("Connecting to PCI.\n");
+
+ err = pci_client_connect();
+ assert(err_is_ok(err));
+
+ err = pci_register_driver_movable_irq(e1000_init_fn, class, subclass, program_interface,
+ vendor, deviceid, bus, device, function,
+ e1000_interrupt_handler_fn, NULL,
+ e1000_reregister_handler,
+ NULL);
+ IRQ_DEBUG("########### Driver with interrupts ###########\n");
+
+
+ if (err_is_fail(err)) {
+ E1000_PRINT_ERROR("Error: %u, pci_register_driver failed\n", (unsigned int)err);
+ exit(err);
+ }
+
+ IRQ_DEBUG("Registered driver.\n");
+
+ IRQ_DEBUG("#### starting dispatch loop.\n");
+ uint64_t ticks_per_msec, current_tick;
+ uint64_t last_int_trigger_ticks = 0;
+ sys_debug_get_tsc_per_ms(&ticks_per_msec);
+ IRQ_DEBUG("Ticks per msec: %"PRIu64".\n", ticks_per_msec);
+ assert(err_is_ok(err));
+
+ while(true){
+ err = event_dispatch_non_block(get_default_waitset());
+ if(!err_is_ok(err) && err != LIB_ERR_NO_EVENT) {
+ IRQ_DEBUG("Error in event_dispatch_non_block, returned %s\n",
+ err_getstring(err));
+ }
+
+ if(int_trigger_counter >= 20){
+ if(abs(int_trigger_counter - interrupt_counter) < 3){
+ printf("triggerred: %"PRIi64" and received %"PRIi64" interrupts. (+-2 is okay).\n",
+ int_trigger_counter, interrupt_counter);
+ printf("TEST SUCCESS\n");
+ }
+ else {
+ printf("triggerred: %"PRIi64" and received %"PRIi64" interrupts. (+-2 is okay).\n",
+ int_trigger_counter, interrupt_counter);
+ printf("TEST FAILURE\n");
+ }
+ exit(0);
+ }
+ if(e1000_initialized){
+ current_tick = rdtsc();
+ if(last_int_trigger_ticks + ticks_per_msec*100 < current_tick){
+ last_int_trigger_ticks = current_tick;
+ IRQ_DEBUG("Creating Link change interrupt...\n");
+
+ // Cause an (artificial) interrupt
+ e1000_intreg_t ics = 0;
+ ics = e1000_intreg_lsc_insert(ics, 1);
+ e1000_ics_wr(e1000_device.device, ics);
+ int_trigger_counter++;
+ }
+ }
+ }
+
+ return 1;
+}
--- /dev/null
+/*
+ * Copyright (c) 2008, ETH Zurich. All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#ifndef __IRQTEST_DEBUG_H__
+#define __IRQTEST_DEBUG_H__
+
+/*****************************************************************
+ * Debug printer:
+ *****************************************************************/
+#define IRQTEST_DEBUG 1
+
+#if defined(IRQTEST_DEBUG) || defined(GLOBAL_DEBUG)
+#define IRQ_DEBUG(fmt, ...) printf("irq test: " fmt, ##__VA_ARGS__)
+#else
+#define IRQ_DEBUG(fmt, ...) ((void)0)
+#endif
+
+#endif // __IRQTEST_DEBUG_H__
"modify_flags.c", "nkmtest.c",
"vspace_dump.c" ],
addLibraries = [ "cap_predicates" ],
- architectures = [ "x86_64" ]
+ architectures = [ "x86_64", "k1om" ]
},
build application { target = "nkmtest_all",
cFiles = [ "main.c",