enet: Map device registers

This commit is contained in:
Jan Schär 2022-05-18 17:45:24 +02:00
parent 9edba91b34
commit 6a2b1f61bf
8 changed files with 128 additions and 79 deletions

View File

@ -5,6 +5,7 @@
bootdriver /armv8/sbin/boot_armv8_generic
cpudriver /armv8/sbin/cpu_imx8x
module /armv8/sbin/init
module /armv8/sbin/enet
module /armv8/sbin/hello echoclient
module /armv8/sbin/memeater
module /armv8/sbin/mallocator

View File

@ -99,7 +99,7 @@ static inline bool capref_is_null(struct capref capref)
/* well-known cnodes */
extern struct cnoderef cnode_root, cnode_task, cnode_base, cnode_super,
cnode_page, cnode_module;
cnode_page, cnode_module, cnode_arg;
/* well-known capabilities */
extern struct capref cap_root, cap_monitorep, cap_irq, cap_io, cap_dispatcher,

View File

@ -126,6 +126,7 @@
#define CPTR_PHYADDRCN_BASE ROOTCN_SLOT_ADDR(ROOTCN_SLOT_PACN)
#define CPTR_MODULECN_BASE ROOTCN_SLOT_ADDR(ROOTCN_SLOT_MODULECN)
#define CPTR_PAGECN_BASE ROOTCN_SLOT_ADDR(ROOTCN_SLOT_PAGECN)
#define CPTR_ARGCN_BASE ROOTCN_SLOT_ADDR(ROOTCN_SLOT_ARGCN)
/**
* Memory region types.

View File

@ -43,6 +43,7 @@ struct spawninfo {
struct cnoderef cspace_l2_cnode_slot_alloc_2; // < A third L2 Node for the slot allocator to use.
struct cnoderef cspace_l2_cnode_base_pagecn; // < Each slot holds a BASE_PAGE_SIZEd RAM capability.
struct cnoderef cspace_l2_cnode_pagecn; // < Contains capabilites to the pagetable
struct cnoderef cspace_l2_cnode_argcn; // < Contains argument capabilites
// these capabilites are all stored in the taskcn cnode
struct capref cspace_cap_selfep; // < Endpoint to itself. You can get this capability by retyping the dispatcher capability to ObjType_EndPointLMP.

View File

@ -45,6 +45,11 @@ struct cnoderef cnode_root = ROOT_CNODE_INIT;
.cnode = CPTR_MODULECN_BASE, \
.level = CNODE_TYPE_OTHER, }
#define ARG_CNODE_INIT { \
.croot = CPTR_ROOTCN, \
.cnode = CPTR_ARGCN_BASE, \
.level = CNODE_TYPE_OTHER, }
/// Task CNode
struct cnoderef cnode_task = TASK_CNODE_INIT;
@ -68,6 +73,9 @@ struct cnoderef cnode_page = PAGE_CNODE_INIT;
/// Module CNode
struct cnoderef cnode_module = MODULE_CNODE_INIT;
/// Arg CNode
struct cnoderef cnode_arg = ARG_CNODE_INIT;
struct capref cap_mmstrings = {
.cnode = MODULE_CNODE_INIT,
.slot = 0
@ -85,6 +93,12 @@ struct capref cap_irq = {
.slot = TASKCN_SLOT_IRQ
};
/// Capability for Device Frame
struct capref cap_io = {
.cnode = TASK_CNODE_INIT,
.slot = TASKCN_SLOT_DEV
};
/// Capability for endpoint to self
struct capref cap_selfep = {
.cnode = TASK_CNODE_INIT,
@ -724,14 +738,14 @@ errval_t frame_create(struct capref dest, size_t bytes, size_t *retbytes)
/**
* \brief Create a dispatcher capability and store it in the slot pointed to
* by 'dest'
*
* This function requires that dest refers to an existing but empty slot. It
*
* This function requires that dest refers to an existing but empty slot. It
* allocates a new RAM cap, retypes it to one of type ObjType_Dispatcher and
* stores it at the slot pointed to by the capref struct 'dest'. The intermediate
* ram cap is then destroyed.
*
* \param dest location to place new dispatcher cap
*
*
* \return Either SYS_ERR_OK if no error occured or an error
* indicating what went wrong otherwise.
*/

View File

@ -14,6 +14,8 @@
#include <spawn/multiboot.h>
#include <spawn/argv.h>
#include <maps/imx8x_map.h>
extern struct bootinfo *bi;
extern coreid_t my_core_id;
extern struct aos_urpc urpc_to_bsp;
@ -500,6 +502,26 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si,
if (err_is_fail(err)) return err_push(err, LIB_ERR_CAP_COPY_FAIL);
si->init_chan.remote_cap = NULL_CAP;
// Set up capability arguments. This would ideally be passed somehow as an argument to spawn instead.
size_t arg0_base = 0;
size_t arg0_size = 0;
if (strcmp(argv[0], "enet") == 0) {
arg0_base = IMX8X_ENET_BASE;
arg0_size = IMX8X_ENET_SIZE;
}
si->cspace_l2_cnode_argcn = NULL_CNODE;
if (arg0_base != 0) {
err = cnode_create_foreign_l2(si->cspace_l1_cnode_cap, ROOTCN_SLOT_ARGCN, &si->cspace_l2_cnode_argcn);
if (err_is_fail(err)) return err;
struct capref arg0_cap = {
.cnode = si->cspace_l2_cnode_argcn,
.slot = 0
};
err = cap_retype(arg0_cap, cap_io, (arg0_base - IMX8X_START_DEV_RANGE), ObjType_DevFrame, arg0_size, 1);
if (err_is_fail(err)) return err_push(err, LIB_ERR_CAP_RETYPE);
}
// - Setup the child's vspace
// afeer: create level 0 page table
// the l0 page table is in the first slot (PAGECN_SLOT_VROOT) of the pagecn cnode.

View File

@ -12,7 +12,7 @@
let
-- Default list of modules to build/install
modules_common = [ "/sbin/" ++ f | f <- [ "init", "hello", "memeater", "mallocator", "stackoverflow", "echoserver"
modules_common = [ "/sbin/" ++ f | f <- [ "init", "hello", "memeater", "mallocator", "stackoverflow", "echoserver", "enet"
] ]
in
[

View File

@ -22,6 +22,7 @@
#include <aos/deferred.h>
#include <driverkit/driverkit.h>
#include <dev/imx8x/enet_dev.h>
#include <maps/imx8x_map.h>
#include <netutil/etharp.h>
@ -32,19 +33,19 @@
static errval_t enet_write_mdio(struct enet_driver_state* st, int8_t phyaddr,
int8_t regaddr, int16_t data)
{
// Some protocol ...
enet_mmfr_t reg = 0;
reg = enet_mmfr_pa_insert(reg, phyaddr);
reg = enet_mmfr_ra_insert(reg, regaddr);
reg = enet_mmfr_data_insert(reg, data);
reg = enet_mmfr_st_insert(reg, 0x1);
reg = enet_mmfr_ta_insert(reg, 0x2);
reg = enet_mmfr_data_insert(reg, data);
reg = enet_mmfr_st_insert(reg, 0x1);
reg = enet_mmfr_ta_insert(reg, 0x2);
// 1 is write 2 is read
reg = enet_mmfr_op_insert(reg, 0x1);
reg = enet_mmfr_op_insert(reg, 0x1);
ENET_DEBUG("Write MDIO: write cmd %lx \n", reg);
enet_mmfr_wr(st->d, reg);
@ -57,7 +58,7 @@ static errval_t enet_write_mdio(struct enet_driver_state* st, int8_t phyaddr,
return ENET_ERR_MDIO_WRITE;
}
}
enet_eir_mii_wrf(st->d, 0x1);
return SYS_ERR_OK;
}
@ -65,20 +66,20 @@ static errval_t enet_write_mdio(struct enet_driver_state* st, int8_t phyaddr,
static errval_t enet_read_mdio(struct enet_driver_state* st, int8_t phyaddr,
int8_t regaddr, int16_t *data)
{
// Some protocol ...
enet_eir_mii_wrf(st->d, 0x1);
enet_mmfr_t reg = 0;
reg = enet_mmfr_pa_insert(reg, phyaddr);
reg = enet_mmfr_ra_insert(reg, regaddr);
reg = enet_mmfr_st_insert(reg, 0x1);
reg = enet_mmfr_ta_insert(reg, 0x2);
reg = enet_mmfr_st_insert(reg, 0x1);
reg = enet_mmfr_ta_insert(reg, 0x2);
// 1 is write 2 is read
reg = enet_mmfr_op_insert(reg, 0x2);
reg = enet_mmfr_op_insert(reg, 0x2);
enet_mmfr_wr(st->d, reg);
ENET_DEBUG("Read MDIO: read cmd %lx \n", reg);
uint16_t tries = 1000;
@ -89,34 +90,34 @@ static errval_t enet_read_mdio(struct enet_driver_state* st, int8_t phyaddr,
return ENET_ERR_MDIO_WRITE;
}
}
enet_eir_mii_wrf(st->d, 0x1);
*data = enet_mmfr_data_rdf(st->d);
return SYS_ERR_OK;
}
static errval_t enet_get_phy_id(struct enet_driver_state* st)
{
errval_t err;
int16_t data;
int16_t data;
uint32_t phy_id;
// get phy ID1
err = enet_read_mdio(st, PHY_ID, 0x2, &data);
if (err_is_fail(err)) {
return err;
}
}
phy_id = data << 16;
// get phy ID2
err = enet_read_mdio(st, PHY_ID, 0x3, &data);
if (err_is_fail(err)) {
return err;
}
}
phy_id |= data;
st->phy_id = phy_id;
st->phy_id = phy_id;
return err;
}
@ -135,21 +136,21 @@ static errval_t enet_reset_phy(struct enet_driver_state* st)
err = enet_write_mdio(st, PHY_ID, PHY_RESET_CMD, PHY_RESET);
if (err_is_fail(err)) {
return err;
}
}
int16_t data;
err = enet_read_mdio(st, PHY_ID, PHY_RESET_CMD, &data);
if (err_is_fail(err)) {
return err;
}
}
int timeout = 500;
while ((data & PHY_RESET) && timeout > 0) {
err = enet_read_mdio(st, PHY_ID, PHY_RESET_CMD, &data);
if (err_is_fail(err)) {
return err;
}
}
barrelfish_usleep(1000);
timeout--;
}
@ -171,19 +172,19 @@ static errval_t enet_setup_autoneg(struct enet_driver_state* st)
err = enet_read_mdio(st, PHY_ID, 0x1, &status);
if (err_is_fail(err)) {
return err;
}
}
// READ autoneg status
err = enet_read_mdio(st, PHY_ID, PHY_AUTONEG_CMD, &autoneg);
if (err_is_fail(err)) {
return err;
}
}
// Read BASIC contorl register
err = enet_read_mdio(st, PHY_ID, PHY_RESET_CMD, &status);
if (err_is_fail(err)) {
return err;
}
}
return SYS_ERR_OK;
}
@ -207,19 +208,19 @@ static errval_t enet_restart_autoneg(struct enet_driver_state* st)
barrelfish_usleep(1000);
//barrelfish_usleep(1000);
err = enet_write_mdio(st, PHY_ID, PHY_AUTONEG_CMD,
err = enet_write_mdio(st, PHY_ID, PHY_AUTONEG_CMD,
AUTONEG_100FULL | AUTONEG_100HALF | AUTONEG_10FULL |
AUTONEG_10HALF | AUTONEG_PSB_802_3);
if (err_is_fail(err)) {
return err;
}
err = enet_write_mdio(st, PHY_ID, PHY_RESET_CMD,
err = enet_write_mdio(st, PHY_ID, PHY_RESET_CMD,
AUTONEG_ENABLE | AUTONEG_RESTART);
if (err_is_fail(err)) {
return err;
}
return SYS_ERR_OK;
}
@ -230,13 +231,13 @@ static errval_t enet_init_phy(struct enet_driver_state* st)
err = enet_get_phy_id(st);
if (err_is_fail(err)) {
return err;
}
}
err = enet_reset_phy(st);
if (err_is_fail(err)) {
return err;
}
}
// board_phy_config in uboot driver. Don't know what
// this actually does ...
err = enet_write_mdio(st, PHY_ID, 0x1d, 0x1f);
@ -255,7 +256,7 @@ static errval_t enet_init_phy(struct enet_driver_state* st)
err = enet_setup_autoneg(st);
if (err_is_fail(err)) {
return err;
}
}
return SYS_ERR_OK;
}
@ -284,21 +285,21 @@ static void enet_parse_link(struct enet_driver_state* st)
err = enet_read_mdio(st, PHY_ID, PHY_STATUS_CMD, &mii_reg);
assert(err_is_ok(err));
if (status < 0) {
if (status < 0) {
debug_printf("ENET not capable of 1G \n");
return;
} else {
err = enet_read_mdio(st, PHY_ID, PHY_CTRL1000_CMD, &status);
assert(err_is_ok(err));
if (status == 0) {
int16_t lpa, lpa2;
int16_t lpa, lpa2;
err = enet_read_mdio(st, PHY_ID, PHY_AUTONEG_CMD, &lpa);
assert(err_is_ok(err));
err = enet_read_mdio(st, PHY_ID, PHY_LPA_CMD, &lpa2);
assert(err_is_ok(err));
lpa &= lpa2;
if (lpa & (PHY_LPA_100FULL | PHY_LPA_100HALF)) {
if (lpa & PHY_LPA_100FULL) {
@ -325,7 +326,7 @@ static errval_t enet_phy_startup(struct enet_driver_state* st)
debug_printf("LINK already UP\n");
return SYS_ERR_OK;
}
if (!(mii_reg & PHY_STATUS_ANEG_COMP)) {
debug_printf("[enet] Starting autonegotiation \n");
@ -334,16 +335,16 @@ static errval_t enet_phy_startup(struct enet_driver_state* st)
assert(err_is_ok(err));
barrelfish_usleep(1000);
}
ENET_DEBUG("Autonegotation done\n");
}
enet_parse_link(st);
return SYS_ERR_OK;
}
// bool promiscous for promiscous mode.
// bool promiscous for promiscous mode.
// This will also set it so that all multicast packets will also be received!
/*
static void enet_init_multicast_filt(struct enet_driver_state* st, bool promisc)
@ -354,7 +355,7 @@ static void enet_init_multicast_filt(struct enet_driver_state* st, bool promisc)
}
enet_rcr_prom_wrf(st->d, 0);
// TODO Catching all multicast packets for now
enet_gaur_wr(st->d, 0xFFFFFFFF);
enet_galr_wr(st->d, 0xFFFFFFFF);
@ -368,18 +369,18 @@ static void enet_init_multicast_filt(struct enet_driver_state* st, bool promisc)
unsigned char data = ((uint8_t*) &st->mac)[i];
for (int bit = 0; bit < 8; bit++, data >>= 1) {
crc = (crc >> 1) ^ (((crc ^ data) & 1) ? ENET_CRC32_POLY : 0);
crc = (crc >> 1) ^ (((crc ^ data) & 1) ? ENET_CRC32_POLY : 0);
}
hash = (crc >> (32 - ENET_HASH_BITS)) & 0x3f;
hash = (crc >> (32 - ENET_HASH_BITS)) & 0x3f;
if (hash > 31) {
hash_high |= 1 << (hash - 32);
} else {
hash_low |= 1 << hash;
}
}
}
enet_gaur_gaddr_wrf(st->d, hash_high);
enet_galr_gaddr_wrf(st->d, hash_low);
#endif
@ -395,12 +396,12 @@ static void enet_read_mac(struct enet_driver_state* st)
uint64_t mac = (lower << 16) | upper;
ENET_DEBUG("MAC %lx \n", mac);
st->mac = mac;
st->mac = mac;
}
static void enet_write_mac(struct enet_driver_state* st)
{
uint64_t lower = st->mac >> 16;
uint32_t upper = st->mac & 0xFFFF;
@ -412,7 +413,7 @@ static errval_t enet_reset(struct enet_driver_state* st)
{
// reset device
ENET_DEBUG("Reset device\n");
uint64_t ecr = enet_ecr_rd(st->d);
enet_ecr_wr(st->d, ecr | 0x1);
int timeout = 500;
@ -424,7 +425,7 @@ static errval_t enet_reset(struct enet_driver_state* st)
if (timeout <= 0) {
return ENET_ERR_DEV_RESET;
}
return SYS_ERR_OK;
}
@ -436,8 +437,8 @@ static void enet_reg_setup(struct enet_driver_state* st)
// Clear outstanding interrupts
ENET_DEBUG("Clear outstanding interrupts\n");
enet_eir_wr(st->d, 0xFFFFFFFF);
uint64_t reg;
uint64_t reg;
// TODO see if other fields are required, not in dump
reg = enet_rcr_rd(st->d);
reg = enet_rcr_loop_insert(reg, 0x0);
@ -446,7 +447,7 @@ static void enet_reg_setup(struct enet_driver_state* st)
reg = enet_rcr_fce_insert(reg, 0x1);
reg = enet_rcr_max_fl_insert(reg, 1522);
//reg = enet_rcr_prom_insert(reg, 1);
enet_rcr_wr(st->d, reg);
enet_rcr_wr(st->d, reg);
}
static errval_t enet_open(struct enet_driver_state *st)
@ -468,10 +469,10 @@ static errval_t enet_open(struct enet_driver_state *st)
err = enet_phy_startup(st);
if (err_is_fail(err)) {
return err;
}
}
uint8_t speed = enet_ecr_speed_rdf(st->d);
if (!speed) {
enet_rcr_rmii_10t_wrf(st->d, 0x0);
}
@ -493,7 +494,7 @@ static errval_t enet_init(struct enet_driver_state* st)
enet_reg_setup(st);
uint64_t reg;
uint64_t reg;
// Set MII speed, do not drop preamble and set hold time to 10ns
reg = enet_mscr_rd(st->d);
reg = enet_mscr_mii_speed_insert(reg, 0x18);
@ -536,10 +537,10 @@ static errval_t enet_probe(struct enet_driver_state* st)
if (err_is_fail(err)) {
return err;
}
enet_reg_setup(st);
uint64_t reg;
uint64_t reg;
// Set MII speed, do not drop preamble and set hold time to 10ns
reg = enet_mscr_rd(st->d);
reg = enet_mscr_mii_speed_insert(reg, 0x18);
@ -550,7 +551,7 @@ static errval_t enet_probe(struct enet_driver_state* st)
if (err_is_fail(err)) {
debug_printf("Failed PHY reset\n");
return err;
}
}
// Write back mac again
ENET_DEBUG("Reset MAC\n");
@ -558,7 +559,7 @@ static errval_t enet_probe(struct enet_driver_state* st)
enet_write_mac(st);
enet_read_mac(st);
// TODO checked dump until here!
// TODO checked dump until here!
return SYS_ERR_OK;
}
@ -567,13 +568,22 @@ int main(int argc, char *argv[]) {
errval_t err;
debug_printf("Enet driver started \n");
struct enet_driver_state * st = (struct enet_driver_state*)
calloc(1, sizeof(struct enet_driver_state));
struct enet_driver_state * st = (struct enet_driver_state*)
calloc(1, sizeof(struct enet_driver_state));
assert(st != NULL);
/* TODO Net Project: get the capability to the register region
/* Net Project: get the capability to the register region
* and then map it so it is accessible.
* TODO set st->d_vaddr to the memory mapped register region */
* set st->d_vaddr to the memory mapped register region */
struct capref cap_arg0 = {
.cnode = cnode_arg,
.slot = 0
};
err = paging_map_frame_attr(get_current_paging_state(),
(void **) &st->d_vaddr, IMX8X_ENET_SIZE,
cap_arg0, VREGION_FLAGS_READ_WRITE_NOCACHE);
if (err_is_fail(err)) return err;
if ((void *)st->d_vaddr == NULL) {
USER_PANIC("ENET: No register region mapped \n");
}
@ -598,9 +608,9 @@ int main(int argc, char *argv[]) {
}
debug_printf("Enet driver init done \n");
debug_printf("Creating devqs \n");
err = enet_rx_queue_create(&st->rxq, st->d);
if (err_is_fail(err)) {
debug_printf("Failed creating RX devq \n");
@ -609,7 +619,7 @@ int main(int argc, char *argv[]) {
err = enet_tx_queue_create(&st->txq, st->d);
if (err_is_fail(err)) {
debug_printf("Failed creating RX devq \n");
debug_printf("Failed creating TX devq \n");
return err;
}