# HG changeset patch # User Paul Boddie # Date 1709051245 -3600 # Node ID 9c60c22edb25446d728e526520d4fdd1f4d2ec77 # Parent 537d9c4101b02cf8651c7248a60944fb067ff73a Added a test of memory card block-level access. diff -r 537d9c4101b0 -r 9c60c22edb25 conf/landfall-examples/mips-x1600-msc-block.cfg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/conf/landfall-examples/mips-x1600-msc-block.cfg Tue Feb 27 17:27:25 2024 +0100 @@ -0,0 +1,44 @@ +-- vim:set ft=lua: + +local L4 = require("L4"); + +local l = L4.default_loader; + +local io_buses = + { + common = l:new_channel(); + }; + +l:start({ + caps = { + common = io_buses.common:svr(), + icu = L4.Env.icu, + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0), + }, + log = { "IO", "y" }, + l4re_dbg = L4.Dbg.Warn, + }, + "rom/io rom/hw_devices.io rom/mips-x1600-msc-block.io"); + +local block_server = l:new_channel(); + +l:startv({ + caps = { + fsserver = block_server:svr(), + jdb = L4.Env.jdb, -- to set the server name + icu = L4.Env.icu, + vbus = io_buses.common, + }, + log = { "server", "r" }, + }, + -- arguments: MSC channel/device, DMA channel, card index, memory pages + "rom/msc_block_server", "0", "0", "0", "10"); + +l:startv({ + caps = { + fsserver = block_server, + }, + log = { "client", "g" }, + }, + -- arguments: partition number + "rom/msc_block_client", "1"); diff -r 537d9c4101b0 -r 9c60c22edb25 conf/landfall-examples/mips-x1600-msc-block.io --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/conf/landfall-examples/mips-x1600-msc-block.io Tue Feb 27 17:27:25 2024 +0100 @@ -0,0 +1,14 @@ +-- vi:ft=lua +-- configuration file for io + +local hw = Io.system_bus() + +local bus = Io.Vi.System_bus +{ + CPM = wrap(hw:match("x1600-cpm")); + DMA = wrap(hw:match("x1600-dma")); + GPIO = wrap(hw:match("x1600-gpio")); + MSC = wrap(hw:match("x1600-msc")); +} + +Io.add_vbus("common", bus) diff -r 537d9c4101b0 -r 9c60c22edb25 conf/landfall-examples/mips-x1600-msc-block.list --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/conf/landfall-examples/mips-x1600-msc-block.list Tue Feb 27 17:27:25 2024 +0100 @@ -0,0 +1,15 @@ + +modaddr 0x1100000 + +entry mips-x1600-msc-block +bootstrap bootstrap -serial +kernel fiasco -serial_esc +roottask moe rom/mips-x1600-msc-block.cfg +module mips-x1600-msc-block.cfg +module mips-x1600-msc-block.io +module plat-ingenic-x1600/hw_devices.io +module l4re +module io +module ned +module msc_block_client +module msc_block_server diff -r 537d9c4101b0 -r 9c60c22edb25 pkg/landfall-examples/msc_block_client/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/landfall-examples/msc_block_client/Makefile Tue Feb 27 17:27:25 2024 +0100 @@ -0,0 +1,12 @@ +PKGDIR ?= . +L4DIR ?= $(PKGDIR)/../../.. + +TARGET = msc_block_client + +MODE = static + +SRC_CC = msc_block_client.cc + +REQUIRES_LIBS = l4re_c-util libmem libfsclient libipc libstdc++ libsystypes + +include $(L4DIR)/mk/prog.mk diff -r 537d9c4101b0 -r 9c60c22edb25 pkg/landfall-examples/msc_block_client/msc_block_client.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/landfall-examples/msc_block_client/msc_block_client.cc Tue Feb 27 17:27:25 2024 +0100 @@ -0,0 +1,93 @@ +/* + * Test block server access to memory cards. + * + * Copyright (C) 2024 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include +#include +#include + +#include +#include + + + +static int show_sector(file_t *device) +{ + uint8_t sector[512]; + + printf("Seek...\n"); + client_seek(device, 1024, SEEK_SET); + + printf("Read...\n"); + offset_t nread = client_read(device, sector, 512); + int row, col; + + if (!nread) + { + printf("Could not read sector.\n"); + return 1; + } + + for (row = 0; row < 512; row += 16) + { + printf("%04x:", row); + + for (col = 0; col < 16; col++) + printf(" %02x", sector[row + col]); + + printf("\n"); + } + + return 0; +} + + + +int main(int argc, char *argv[]) +{ + if (argc < 1) + { + printf("Need a partition number.\n"); + return 1; + } + + /* Obtain filename and access parameters. */ + + char *filename = argv[1]; + file_t *file; + + file = client_open(filename, O_RDONLY); + + if (!client_opened(file)) + { + printf("Could not obtain file: %s\n", file != NULL ? l4sys_errtostr(file->error) : "(null)"); + return 1; + } + + printf("Opened file: %s\n", filename); + + show_sector(file); + + client_close(file); + printf("End of test.\n"); + return 0; +} + +// vim: tabstop=2 expandtab shiftwidth=2 diff -r 537d9c4101b0 -r 9c60c22edb25 pkg/landfall-examples/msc_block_server/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/landfall-examples/msc_block_server/Makefile Tue Feb 27 17:27:25 2024 +0100 @@ -0,0 +1,16 @@ +PKGDIR ?= . +L4DIR ?= $(PKGDIR)/../../.. + +TARGET = msc_block_server + +MODE = static + +SRC_CC = \ + msc_block_server.cc msc_region_accessor.cc \ + msc_region_opener.cc msc_region_operations.cc + +REQUIRES_LIBS = \ + l4re_c-util libmem libfsserver libresource libipc libstdc++ libsystypes \ + libio libdrivers-cpm libdrivers-dma libdrivers-msc libdevice-util + +include $(L4DIR)/mk/prog.mk diff -r 537d9c4101b0 -r 9c60c22edb25 pkg/landfall-examples/msc_block_server/msc_block_server.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/landfall-examples/msc_block_server/msc_block_server.cc Tue Feb 27 17:27:25 2024 +0100 @@ -0,0 +1,264 @@ +/* + * A dataspace server exposing regions of a MMC/SD card. + * + * Copyright (C) 2020, 2021, 2023, 2024 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "msc_region_opener.h" +#include "msc_region_operations.h" + + + +/* Common configuration. */ + +static l4_cap_idx_t icucap; + + + +/* Device and resource discovery. */ + +static long item_in_range(long start, long end, long index) +{ + if (start < end) + return start + index; + else if (start > end) + return start - index; + else + return start; +} + + + +/* Common functions. */ + +static int init_irq(int num, l4_cap_idx_t irq, l4_uint32_t start, l4_uint32_t end) +{ + /* Create interrupt object. */ + + long err = l4_error(l4_factory_create_irq(l4re_global_env->factory, irq)); + + if (err) + { + printf("Could not create IRQ object: %ld\n", err); + return 1; + } + + /* Bind interrupt objects to IRQ numbers. */ + + err = l4_error(l4_icu_bind(icucap, + item_in_range(start, end, num), + irq)); + + if (err) + { + printf("Could not bind IRQ to the ICU: %ld\n", err); + return 1; + } + + return 0; +} + + + +/* Peripheral resources. */ + +static Cpm_x1600_chip *cpm; +static Dma_x1600_chip *dma; +static Msc_x1600_chip *msc; + +/* Obtain an abstraction for the memory card. */ + +static MscRegionOperations *get_msc_region_operations(int msc_channel_num, + int dma_channel_num, + int card) +{ + l4_addr_t cpm_base = 0, cpm_base_end = 0; + l4_addr_t dma_base = 0, dma_base_end = 0; + l4_addr_t msc_base = 0, msc_base_end = 0; + l4_addr_t msc_phys_base = 0, msc_phys_base_end = 0; + l4_uint32_t dma_irq_start = 0, dma_irq_end = 0; + l4_uint32_t msc_irq_start = 0, msc_irq_end = 0; + + icucap = l4re_env_get_cap("icu"); + + /* Obtain resource details describing I/O memory. */ + + if (get_memory("x1600-cpm", &cpm_base, &cpm_base_end) < 0) + return NULL; + + cpm = new Cpm_x1600_chip(cpm_base); + + if (get_memory("x1600-dma", &dma_base, &dma_base_end) < 0) + return NULL; + + dma = new Dma_x1600_chip(dma_base, dma_base_end, cpm); + + if (get_irq("x1600-dma", &dma_irq_start, &dma_irq_end) < 0) + return NULL; + + l4_cap_idx_t dma_irq = l4re_util_cap_alloc(); + + if (init_irq(0, dma_irq, dma_irq_start, dma_irq_end)) + return NULL; + + dma->enable(); + + if (get_memory_complete("x1600-msc", &msc_base, &msc_base_end, + &msc_phys_base, &msc_phys_base_end) < 0) + return NULL; + + msc = new Msc_x1600_chip(msc_phys_base, msc_base, msc_base_end, cpm); + + if (get_irq("x1600-msc", &msc_irq_start, &msc_irq_end) < 0) + return NULL; + + l4_cap_idx_t msc_irq = l4re_util_cap_alloc(); + + if (init_irq(msc_channel_num, msc_irq, msc_irq_start, msc_irq_end)) + return NULL; + + Dma_x1600_channel *dma_channel = dma->get_channel(dma_channel_num, dma_irq); + Msc_channel *msc_channel = msc->get_channel(msc_channel_num, msc_irq, dma_channel); + + msc_channel->enable(); + + if (card >= msc_channel->num_cards()) + return NULL; + + struct dma_region region; + + if (get_dma_region(512, 12, ®ion)) + return NULL; + + return new MscRegionOperations(msc_channel, card, region); +} + + + +/* Default number of pages for files. */ + +const unsigned int MEMORY_PAGES = 20; + + + +/* Server program. */ + +int main(int argc, char *argv[]) +{ + l4_debugger_set_object_name(l4re_env()->main_thread, "block_server"); + long err; + + /* Introduce concurrency control. */ + + err = ipc_thread_init(); + + if (err) + { + printf("Initialisation error: %s\n", l4sys_errtostr(err)); + return 1; + } + + if (argc < 4) + { + printf("Need a MSC channel/peripheral number, a DMA channel number, " \ + "and a card number.\n\n" \ + "A number of memory pages can be indicated for the use of the " \ + "server.\n\n" \ + "A named capability from the environment can be specified.\n"); + return 1; + } + + int msc_channel_num = atoi(argv[1]); + int dma_channel_num = atoi(argv[2]); + int card = atoi(argv[3]); + + unsigned int memory_pages = MEMORY_PAGES; + + if (argc > 4) + memory_pages = atoi(argv[4]); + + const char *server_name = (argc > 5) ? argv[5] : ENV_FILESYSTEM_SERVER_NAME; + + /* Obtain a DMA space for associating allocated memory with physical + addresses. */ + + l4_cap_idx_t dma_space; + + err = get_dma_space(&dma_space); + + if (err) + { + printf("Could not obtain DMA space: %s\n", l4sys_errtostr(err)); + return 1; + } + + MscRegionOperations *ops = get_msc_region_operations(msc_channel_num, + dma_channel_num, + card); + + if (ops == NULL) + { + printf("Could not access memory card peripheral.\n"); + return 1; + } + + /* Some memory plus infrastructure. */ + + MemoryIncremental mem(memory_pages, PAGE_SIZE, dma_space); + PageQueueShared queue; + Pages pages(&mem, &queue); + ResourceRegistry registry(&pages); + MscRegionOpener opener(®istry, ops); + + /* Register a server associating it with the given object. */ + + ResourceServer server(&opener); + server.bind(server_name); + + printf("Starting server using %d pages...\n", memory_pages); + server.start(); + + return 0; +} + +// vim: tabstop=2 expandtab shiftwidth=2 diff -r 537d9c4101b0 -r 9c60c22edb25 pkg/landfall-examples/msc_block_server/msc_region_accessor.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/landfall-examples/msc_block_server/msc_region_accessor.cc Tue Feb 27 17:27:25 2024 +0100 @@ -0,0 +1,97 @@ +/* + * A memory card region accessor. + * + * Copyright (C) 2021, 2024 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include + +#include + +#include "msc_region_accessor.h" + + + +MscRegionAccessor::MscRegionAccessor(MscRegionOperations *ops, + uint32_t start_block, uint32_t num_blocks, + fileid_t fileid) +: Accessor(fileid), _ops(ops) +{ + // NOTE: Block size assumption employed. + + _start = start_block * 512; + _size = num_blocks * 512; +} + +/* Return the size of the file. */ + +offset_t MscRegionAccessor::get_size() +{ + return _size; +} + +/* Update the size of the file. */ + +void MscRegionAccessor::set_size(offset_t size) +{ + (void) size; +} + +/* Data transfer helper methods. */ + +/* Fill the populated portion of a flexpage. */ + +void MscRegionAccessor::fill_populated(Flexpage *flexpage) +{ + offset_t filepos = flexpage->base_offset; + offset_t populated_size = std::min(flexpage->size, _size - filepos); + + /* Tag the region with file state. */ + + flexpage->region->fill(fileid, filepos); + + /* Fill the region with file content. */ + + _ops->read(flexpage->base_addr, flexpage->base_addr_physical, + _start + filepos, populated_size); + + /* Pad the flexpage with zero. */ + + if (populated_size < flexpage->size) + memset((void *) (flexpage->base_addr + populated_size), 0, + flexpage->size - populated_size); +} + +/* Flush the populated portion of a flexpage. */ + +void MscRegionAccessor::flush_populated(Flexpage *flexpage) +{ + offset_t filepos = flexpage->base_offset; + offset_t populated_size = std::min(flexpage->size, _size - filepos); + + /* Remove the file state tag from the region. */ + + flexpage->region->flush(); + + /* Flush the file content. */ + + _ops->write(flexpage->base_addr, flexpage->base_addr_physical, + _start + filepos, populated_size); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 537d9c4101b0 -r 9c60c22edb25 pkg/landfall-examples/msc_block_server/msc_region_accessor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/landfall-examples/msc_block_server/msc_region_accessor.h Tue Feb 27 17:27:25 2024 +0100 @@ -0,0 +1,57 @@ +/* + * A memory card region accessor. + * + * Copyright (C) 2021, 2024 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + +#include + +#include "msc_region_operations.h" + + + +/* A memory card region accessor, providing flexpages corresponding to the + regions within an exposed memory card region or partition. */ + +class MscRegionAccessor : public Accessor +{ +protected: + MscRegionOperations *_ops; + uint32_t _start; + offset_t _size; + + /* Data transfer helper methods. */ + + virtual void fill_populated(Flexpage *flexpage); + + virtual void flush_populated(Flexpage *flexpage); + +public: + explicit MscRegionAccessor(MscRegionOperations *ops, uint32_t start_block, + uint32_t num_blocks, fileid_t fileid); + + virtual offset_t get_size(); + + virtual void set_size(offset_t size); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 537d9c4101b0 -r 9c60c22edb25 pkg/landfall-examples/msc_block_server/msc_region_opener.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/landfall-examples/msc_block_server/msc_region_opener.cc Tue Feb 27 17:27:25 2024 +0100 @@ -0,0 +1,148 @@ +/* + * An opener for regions of a memory card. + * + * Copyright (C) 2021, 2022, 2024 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include + +#include + +#include "msc_region_accessor.h" +#include "msc_region_opener.h" + + + +MscRegionOpener::~MscRegionOpener() +{ +} + +bool MscRegionOpener::accessing_directory(flags_t flags, fileid_t fileid) +{ + (void) flags; (void) fileid; + return false; +} + +bool MscRegionOpener::accessing_file(flags_t flags, fileid_t fileid) +{ + (void) flags; (void) fileid; + return true; +} + +/* Test if a directory is empty. */ + +bool MscRegionOpener::directory_is_empty(fileid_t fileid) +{ + (void) fileid; + return false; +} + +/* Return a file identifier for the given 'path'. */ + +long MscRegionOpener::get_fileid(const char *path, flags_t flags, fileid_t *fileid) +{ + (void) flags; + + // Convert the path to an integer for use as the file identifier. + + if (!(strlen(path) && isdigit(path[0]))) + return -L4_ENOENT; + + *fileid = atoi(path); + return L4_EOK; +} + +/* Return a new accessor for 'fileid'. */ + +long MscRegionOpener::make_accessor(flags_t flags, fileid_t fileid, + Accessor **accessor) +{ + // NOTE: Not testing for create or write flags. + + (void) flags; + + // Find the given partition and initialise the accessor with the appropriate + // details. + + uint32_t start_block, num_blocks; + + if (_ops->get_partition(fileid, &start_block, &num_blocks)) + return -L4_ENOENT; + + *accessor = new MscRegionAccessor(_ops, start_block, num_blocks, fileid); + return L4_EOK; +} + +/* Return a directory accessor for 'fileid'. + NOTE: Currently unimplemented. */ + +long MscRegionOpener::make_directory_accessor(flags_t flags, fileid_t fileid, + DirectoryAccessor **accessor) +{ + (void) flags; (void) fileid; (void) accessor; + return -L4_EPERM; +} + + + +/* Make a new directory. */ + +long MscRegionOpener::make_directory_object(const char *path, sys_mode_t mode) +{ + (void) path; (void) mode; + return -L4_EPERM; +} + +/* Remove a filesystem object. */ + +long MscRegionOpener::remove_object(fileid_t fileid) +{ + (void) fileid; + return -L4_EPERM; +} + +/* Rename a filesystem object, placing source inside the parent of target. */ + +long MscRegionOpener::rename_object(const char *source, const char *target) +{ + (void) source; (void) target; + return -L4_EPERM; +} + +/* Populate a memory region with statistics metadata for a filesystem object. + NOTE: Currently unimplemented. */ + +long MscRegionOpener::stat_object(const char *path, void *base, offset_t size) +{ + (void) path; (void) base; (void) size; + return -L4_EPERM; +} + +/* Unlink a filesystem object. */ + +long MscRegionOpener::unlink_object(fileid_t parent_fileid, fileid_t fileid) +{ + (void) parent_fileid; (void) fileid; + return -L4_EPERM; +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 537d9c4101b0 -r 9c60c22edb25 pkg/landfall-examples/msc_block_server/msc_region_opener.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/landfall-examples/msc_block_server/msc_region_opener.h Tue Feb 27 17:27:25 2024 +0100 @@ -0,0 +1,79 @@ +/* + * An opener for regions of a memory card. + * + * Copyright (C) 2021, 2022, 2024 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + +#include + +#include "msc_region_operations.h" + + + +/* Support for providing access to memory card regions. */ + +class MscRegionOpener : public OpenerResource +{ +protected: + MscRegionOperations *_ops; + std::mutex _lock; + +public: + explicit MscRegionOpener(ResourceRegistry *registry, MscRegionOperations *ops) + : OpenerResource(registry), _ops(ops) + { + } + + virtual ~MscRegionOpener(); + + /* Convenience methods determining different object types. */ + + virtual bool accessing_directory(flags_t flags, fileid_t fileid); + + virtual bool accessing_file(flags_t flags, fileid_t fileid); + + virtual bool directory_is_empty(fileid_t fileid); + + /* File opening methods. */ + + virtual long get_fileid(const char *path, flags_t flags, fileid_t *fileid); + + virtual long make_accessor(flags_t flags, fileid_t fileid, + Accessor **accessor); + + virtual long make_directory_accessor(flags_t flags, fileid_t fileid, + DirectoryAccessor **accessor); + + /* Filesystem object access and manipulation methods. */ + + virtual long make_directory_object(const char *path, sys_mode_t mode); + + virtual long remove_object(fileid_t fileid); + + virtual long rename_object(const char *source, const char *target); + + virtual long stat_object(const char *path, void *base, offset_t size); + + virtual long unlink_object(fileid_t parent_fileid, fileid_t fileid); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 537d9c4101b0 -r 9c60c22edb25 pkg/landfall-examples/msc_block_server/msc_region_operations.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/landfall-examples/msc_block_server/msc_region_operations.cc Tue Feb 27 17:27:25 2024 +0100 @@ -0,0 +1,106 @@ +/* + * Access to memory cards. + * + * Copyright (C) 2023, 2024 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include +#include + +#include "msc_region_operations.h" + + + +MscRegionOperations::MscRegionOperations(Msc_channel *msc_channel, uint8_t card, + struct dma_region region) +: _msc_channel(msc_channel), _card(card), _region(region) +{ +} + +long MscRegionOperations::read_partition_table(struct partition_table_entry **entry) +{ + l4_cache_inv_data(_region.vaddr, _region.vaddr + _region.size); + + uint32_t transferred = _msc_channel->read(_card, &_region, 0, _region.size); + + if (!transferred) + return -L4_EIO; + + *entry = get_partition_table((uint8_t *) _region.vaddr); + + if (*entry == NULL) + return -L4_EIO; + + return L4_EOK; +} + +/* Public operations. */ + +long MscRegionOperations::get_partition(uint8_t partition, + uint32_t *start_block, + uint32_t *num_blocks) +{ + std::lock_guard guard(_lock); + + // Use the fileid to select the partition. + + if (partition >= 4) + return -L4_ENOENT; + + struct partition_table_entry *entry; + long err = read_partition_table(&entry); + + if (err) + return err; + + if (!entry[partition].num_sectors) + return -L4_ENOENT; + + *start_block = entry[partition].lba_first_sector; + *num_blocks = entry[partition].num_sectors; + + return L4_EOK; +} + +void MscRegionOperations::read(l4_addr_t vaddr, l4re_dma_space_dma_addr_t paddr, + offset_t filepos, offset_t size) +{ + std::lock_guard guard(_lock); + + struct dma_region region; + + // NOTE: Truncating the file position and size. + + region.vaddr = vaddr; + region.paddr = paddr; + region.size = size; + + l4_cache_inv_data(vaddr, vaddr + size); + + _msc_channel->read(_card, ®ion, (uint32_t) filepos, (uint32_t) size); +} + +void MscRegionOperations::write(l4_addr_t vaddr, l4re_dma_space_dma_addr_t paddr, + offset_t filepos, offset_t size) +{ + std::lock_guard guard(_lock); + + // NOTE: To be implemented. + + (void) vaddr; (void) paddr; (void) filepos; (void) size; +} diff -r 537d9c4101b0 -r 9c60c22edb25 pkg/landfall-examples/msc_block_server/msc_region_operations.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/landfall-examples/msc_block_server/msc_region_operations.h Tue Feb 27 17:27:25 2024 +0100 @@ -0,0 +1,59 @@ +/* + * Access to memory cards. + * + * Copyright (C) 2023, 2024 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + +#include +#include +#include +#include + + + +#ifdef __cplusplus + +class MscRegionOperations +{ +protected: + std::mutex _lock; + Msc_channel *_msc_channel; + uint8_t _card; + struct dma_region _region; + +public: + explicit MscRegionOperations(Msc_channel *msc_channel, uint8_t card, + struct dma_region region); + + long get_partition(uint8_t partition, uint32_t *start_block, + uint32_t *num_blocks); + + long read_partition_table(struct partition_table_entry **entry); + + void read(l4_addr_t vaddr, l4re_dma_space_dma_addr_t paddr, offset_t pos, + offset_t size); + + void write(l4_addr_t vaddr, l4re_dma_space_dma_addr_t paddr, offset_t pos, + offset_t size); +}; + +#endif /* __cplusplus */