diff --git a/hake/menu.lst.armv8_imx8x b/hake/menu.lst.armv8_imx8x index 3cd2895..04edcd0 100644 --- a/hake/menu.lst.armv8_imx8x +++ b/hake/menu.lst.armv8_imx8x @@ -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 diff --git a/include/aos/caddr.h b/include/aos/caddr.h index 3c36ff3..10449a0 100644 --- a/include/aos/caddr.h +++ b/include/aos/caddr.h @@ -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, diff --git a/include/barrelfish_kpi/init.h b/include/barrelfish_kpi/init.h index 5d2ce14..88b2fbc 100644 --- a/include/barrelfish_kpi/init.h +++ b/include/barrelfish_kpi/init.h @@ -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. diff --git a/include/spawn/spawn.h b/include/spawn/spawn.h index 4e3208f..8258421 100644 --- a/include/spawn/spawn.h +++ b/include/spawn/spawn.h @@ -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. diff --git a/lib/aos/capabilities.c b/lib/aos/capabilities.c index 14a5bcd..83ed621 100644 --- a/lib/aos/capabilities.c +++ b/lib/aos/capabilities.c @@ -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. */ diff --git a/lib/spawn/spawn.c b/lib/spawn/spawn.c index 1c8d0db..8727794 100644 --- a/lib/spawn/spawn.c +++ b/lib/spawn/spawn.c @@ -14,6 +14,8 @@ #include #include +#include + 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. diff --git a/platforms/Hakefile b/platforms/Hakefile index 92f54a6..88fadb7 100644 --- a/platforms/Hakefile +++ b/platforms/Hakefile @@ -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 [ diff --git a/usr/drivers/enet/enet_module.c b/usr/drivers/enet/enet_module.c index 80a3022..8518207 100644 --- a/usr/drivers/enet/enet_module.c +++ b/usr/drivers/enet/enet_module.c @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -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; }