docs: Use sphinx and start to bash the documents into a coherent form
authorAlan Cox <alan@linux.intel.com>
Thu, 11 Apr 2019 23:35:35 +0000 (00:35 +0100)
committerAlan Cox <alan@linux.intel.com>
Thu, 11 Apr 2019 23:35:35 +0000 (00:35 +0100)
Yes they need major surgery on the formatting.

docs/65C816.md [new file with mode: 0644]
docs/BankedZ80.md [new file with mode: 0644]
docs/DiskFormats.md [new file with mode: 0644]
docs/ExternalBuffers.md [new file with mode: 0644]
docs/M68000.md [new file with mode: 0644]
docs/Makefile [new file with mode: 0644]
docs/Platforms.md [new file with mode: 0644]
docs/Tickless.md [new file with mode: 0644]
docs/Z80Thunked.md [new file with mode: 0644]
docs/build-filesystem-ng.md [new file with mode: 0644]
docs/conf.py [new file with mode: 0644]

diff --git a/docs/65C816.md b/docs/65C816.md
new file mode 100644 (file)
index 0000000..4db0556
--- /dev/null
@@ -0,0 +1,314 @@
+# 65C816 Systems
+
+## Introduction
+
+The 65C816 target for FUZIX provides a single implementation of the core
+code required to support FUZIX on typical configurations of these
+processors.
+
+Providing your platform fits the basic structure anticipated only small
+amounts of non driver platform code are required. The main work is laying
+out the memory map.
+
+The port shares an ABI with the 6502 target, although processes can use the
+additional features with certain limitations imposed by the CPU
+architecture.
+
+
+## Limitations of The Port
+
+-      CC65 currently has no floating point support. This needs someone to
+write an open source library to unpack/pack IEEE float and do basic maths
+operations upon it.
+
+-      There are architectural differences between the 6502/65C02/65C816
+that cannot be hidden. In particular the 65C816 requires that the processor
+stack and zero page reside in bank 0, while the 6502/65C02 places them at
+the bottom of the current bank.
+
+-      The 65C816 supports separate 64K code and data spaces. This is not
+yet supported. In theory with the right kernel magic multiple code banks are
+supportable.
+
+-      Relocation of loaded executables is not yet supported.
+
+-      Swapping is not yet supported.
+
+-      cc65 does not know how to generate 65C816 optimized code. For the
+kernel in particular it would be a good project for someone to teach ANSI
+pcc or ACK how to generate suitable 65c816 code.
+
+-      No proper support for exceptions such as abort yet.
+
+
+## Reference Platform
+
+The reference platform for development and testing is v65c816. This is a
+simple software 65C816 simulation of a platform with basic I/O devices and
+8MB of RAM from address 0, with a 256 byte I/O window at $FE00 and a simple
+simulated framebuffer.
+
+We require 512 bytes (ZP and CPU stack) for each process in memory at the
+same time. Thus with 512K RAM we have 7 processes in memory (and bank 0 holds
+the rest), so we need 3.5K for DP/ZP spaces.
+
+With 8MB of RAM that rises to 63.5K which requires that the kernel moves to
+another bank. In practice it's quite hard to use 8MB of RAM for processes on
+a 65C816 as that amounts to 128 processes which for such a slow processor is
+unlikely to be a practical workload.
+
+There are two reference kernels: v65c816 for the reference platform places
+the kernel in bank 0, along with the CPU stack and direct page (zero page)
+for each process. This model should be directly usable for smaller systems
+up to about 512K RAM.
+
+For larger systems v65c816-big shows how to develop a platform where you
+only place stacks and direct pages in bank 0. In the reference kernel the
+kernel code lives in bank 1 and the kernel data in bank 2.
+
+
+## Execution Environment
+
+Userspace applications are loaded at the load address indicated in their
+header providing they fit within the available memory. Thus even though we
+don't yet support relocations a binary linked at $2000 can be loaded on a
+system with userspace from $0200-$FE00 as it will fit with space below.
+
+Applications are entered in 65C816 mode in a8i8 form. DP and S are set to
+suitable memory spaces and S is at the top of a 256 byte stack that cc65
+uses only for call/return paths and briefly when doing work. On entry the
+registers are defined as follows
+
+       X:      high byte of load address
+       Y:      zero page base (will be used with relocating)
+       A:      currently zero (undefined)
+
+The C stack top holds argc, argv, and the environment (see
+Library/libs/crt0_6502.s).
+
+The application memory is arranged with the code at the bottom, then any
+writeable data then bss (variables initialized to 0). Above that is space
+and at the top of the available user memory is the C language stack, a
+construct maintained entirely by cc65. The stack expands down and sbrk()
+allows the data to expand upwards.
+
+System calls are made by calling [$00FE] (which should not be assumed to be
+the same as $FE in zero page). At the moment this is hard coded but does
+need to end up in the relocation system for 6502 platforms where those bytes
+are not usable. Calls should be made in a8i8 mode, and the return from them
+will likewise be a8i8.
+
+System calls are made like normal C calls and the syscall interface pulls
+the arguments off the application C stack as if it was a function call. This
+also means that the compiler knows that zp:0 is the C stack pointer, and
+this is also hardcoded until we get relocations.
+
+System call state is returned in XY and the error code if any is in A.
+If there is no error then A is zero.
+
+At any point the binary that is being executed may be swapped out and at
+some point swapped back in from storage and resumed. When it is resumed it
+may well be allocated a different bank, different S and different DP.
+
+An application must not
+
+- Assume that DP is $0000 in your current bank, or that the CPU stack is $0100
+  in your current bank. On 65C816 this will not be true even if it is true on
+  the 6502 itself.
+
+- Save or restore DP, B or S itself
+
+- Do any long operations (rtl etc) or use mvn/mvp (as we might move bank mid
+  mvn/mvp)
+
+- Compute addresses based upon S or DP. They may not remain valid. It
+  is ok to do things like LDA 6,S but not to do TSX LDA 6,X. Treat S as if
+  it was a stack that lives in its own memory space not accessible elsewhere
+
+cc65 (as of the latest version) handles these rules correctly. Older cc65
+assumes ZP is at $0000 but the C library has a workaround to replace the
+problem routine with its own. The C library also contains a less than pretty
+implementation of longjmp that does the right thing.
+
+## Signal Handling
+
+Signals are particularly tricky in the 6502/65C816 world as the C stack is a
+software construction. In order to isolate the kernel from the complexities
+of what each compiler does a signal is handled by pushing a system specific
+save area followed by the signal number and the vector to invoke. Rather
+than returning via that vector the kernel calls [load_address + $20] which
+is a pointer to a helper routine in user space (again see crt0_6502.s).
+
+When the signal handler completes the helper is expected to restore the C
+state and return. The platform specific handler provided by the kernel will
+then restore state and return to the interrupted point.
+
+
+## Porting To A New Platform
+
+It is easiest to start with a copy of the v65c816 platform.
+
+config.h holds the system configuration as seen from C. kernel.def holds the
+configuration in a form the assembler can use. Always remember to change
+both when a symbol is present in both places.
+
+Start with config.h. The only things you should need to change are
+
+
+MAX_MAPS: The number of user processes that we can have loaded at once. This
+is normally 1 per 64K of memory minus one for the kernel (3 for 256K 7 for
+512K, 15 for 1MB).
+
+STACK_BANKOFF: This specifies where in bank 0 to begin allocation of the
+zero pages and direct pages for each process. This can be adjusted to suit
+the memory map and the number of pages (two per process in memory) required
+
+TICKSPERSEC:  Number of timer interrupt events per second. If you can
+configure this then 10/second is ideal.
+
+The rest should not need touching for a typical setup.
+
+kernel.def contains another copy of STACK_BANKOFF that should be set the
+same.
+
+The following other values might need touching
+
+KERNEL_BANK    -       the bank number of the kernel
+KERNEL_FAR     -       the 24bit base of the kernel
+
+The low level platform code lives in v65.s and crt0.s. crt0.s is the setup
+code that runs before the C environment and kernel. It is responsible for
+things like wiping the BSS and setting the stack pointers. This will need
+rewriting for whatever boot loader and boot you are using.
+
+v65.s contains the platform specific routines.
+
+_trap_monitor: jumps to a monitor program if present, otherwise halts the
+system. It is used on a detected crash to help debug. One option is to load
+a debugger into the top bank and drop MAX_MAPS by 1 when debugging
+
+_trap_reboot: if possible causes a reboot, if not halts the system
+
+__hard_di:
+__hard_ei:
+__hard_irqrestore:
+
+These are low level wrappers for the interrupt masking. They can be copied
+from the reference port unless you need to implemnt 'soft' IRQ disabling to
+get better handling of things like serial interrupts.
+
+init_early:
+
+This is called from crt0 and in our example case we use it to place the
+exception vectors in the correct addresses
+
+init_hardware:
+
+This does any early hardware setup. Interrupts are off so things like timers
+
+kernel.def contains another copy of STACK_BANKOFF that should be set the
+same.
+
+The following other values might need touching
+
+KERNEL_BANK    -       the bank number of the kernel
+KERNEL_FAR     -       the 24bit base of the kernel
+
+
+The low level platform code lives in v65.s and crt0.s. crt0.s is the setup
+code that runs before the C environment and kernel. It is responsible for
+things like wiping the BSS and setting the stack pointers. This will need
+rewriting for whatever boot loader and boot you are using.
+
+v65.s contains the platform specific routines.
+
+_trap_monitor: jumps to a monitor program if present, otherwise halts the
+system. It is used on a detected crash to help debug. One option is to load
+a debugger into the top bank and drop MAX_MAPS by 1 when debugging
+
+_trap_reboot: if possible causes a reboot, if not halts the system
+
+__hard_di:
+__hard_ei:
+__hard_irqrestore:
+
+These are low level wrappers for the interrupt masking. They can be copied
+from the reference port unless you need to implement 'soft' IRQ disabling to
+get better handling of things like serial interrupts.
+
+init_early:
+
+This is called from crt0 and in our example case we use it to place the
+exception vectors in the correct addresses
+
+init_hardware:
+
+This does any early hardware setup. Interrupts are off so things like timers
+can be enabled ready, memory sized etc.
+
+_program_vectors:
+
+On some architectures this copies vectors between banks. For the 65C816 this
+isn't needed so can be an rts
+
+outchar:
+
+This routine should print the contents of the A to whatever is a good debug
+port to use. It must not corrupt X or Y. This is used to output debugging
+messages and crash messages from assembler code for debug.
+
+The file also contains examples of block read/write code for a disk driver.
+
+
+### C Files
+
+main.c: This holds routines used in the set up and general running of the
+platform.
+
+platform_idle: is called in a tight loop when there is no process to run. If
+the platform is entirely IRQ driven it could sleep to save power, but with
+systems that have polled serial it is usually best to keep polling the
+serial to get the best responsiveness and least dropped characters.
+
+do_beep: is only used if you enable VT as opposed to serial ports and should
+make the beep noise for control-G.
+
+pagemap_init/map_init should not need touching for a 65c816 port
+
+platform_param: is called with each string on the boot line that is not
+known by the core code. The platform can claim a string by returning 1, and
+then do whatever setup is required for this.
+
+devtty.c provides a very simple example serial port driver for the console
+port and on the v65c816 platform a simple video driver.
+
+devhd.c provides a very simple example block device.
+
+devices.c provides the tables and helper functions that bind all the devices
+and the kernel core together. The table can be altered to suit the needs of
+the system. device_init() is a hook to initialize/probe any devices during
+system startup.
+
+
+## Large Systems
+
+Once the amount of memory rises above 512K it becomes trickier to find a
+space for all of the ZP and DP blocks that are in use. In addition the
+number of buffers and inode cache entries required for lots of processes
+puts further pressure on allocations.
+
+A large configuration would therefore want to place the ZP/DP buffers in
+bank 0, maybe along with tty buffers to use up space if needed. The kernel
+can in theory run split I/D across banks 1 and 2, which would allow enough
+space for networking and a lot of buffers. Such a configuration could
+support up to 8MB without the core code changing. Beyond that point there
+are assumptions in lowlevel-65c816.s that you can take the user page number
+shift it left and add it to a base to get an offset. This breaks once you
+pass 128 banks (8MB). In addition once you hit 128 processes you run out of
+bank 0 memory to hold their DP/stack.
+
+Moving the kernel also of course requires updating the exception vectors to
+jump into the right bank, and their return paths to do the right thing.
+
+For an example see platform-v65c816-big.
+
diff --git a/docs/BankedZ80.md b/docs/BankedZ80.md
new file mode 100644 (file)
index 0000000..cce7fec
--- /dev/null
@@ -0,0 +1,388 @@
+# Banked Z80 Systems
+
+## Introduction
+
+Z80 based systems were typically built with a fixed common memory space at
+the top of the address space and multiple banks below that threshold. For
+such machines Fuzix provides all the basic management and switching support
+code needed.
+
+This approach can also be useful for machines with more complicated memory
+paging arrangements such as multiple 16K pages and while less efficient in
+memory usage is a convenient way to bring the system up initially.
+
+## Reference Platform
+
+The reference platform for this document is the SBCv2 platform which is a
+fairly simple banked system and has been heavily commented. The Microbee platform
+Kernel/platform-ubee may also be useful. This platform shows both the
+use of standard banking code, the vt interface for systems with a real
+keyboard and display built in, and how to handle screen maps.
+
+
+For Z180 platforms please see the Z180 documentation instead. As the Z180
+has a standardised MMU the port is even easier.
+
+## Configuration Files
+
+Your platform needs a minimum of the following files
+
+- Makefile
+- kernel.def
+- config.h
+- target.mk
+
+The recommended approach is to copy these from an existing port and then
+edit them as neccessary.
+
+For an initial banked memory platform edit config.h and change the following
+parameters
+
+CONFIG_RTC: set this if you have a real time clock which can provide a
+current seconds value when read. Fuzix uses this to lock the system clock
+against a time source even when interrupt disables may cause missed ticks.
+
+CONFIG_VT: this and the corresponding VT_ paramemters should be set if you
+have a display console. If you have a serial port you can use that - and it is
+usually a lot easier to bring the platform up on the serial port first.
+
+TICKSPERSEC: set this to the number of ticks per second your timer interrupt
+provides. It should be a multiple of 10. If you have only fast timers you
+can use a counter in your interrupt handler and only invoke the Fuzix
+interrupts when needed.
+
+FIXME: BANKS
+
+PROGBASE: this is the base address of programs. On all normal Z80 systems
+this will be zero.
+
+PROGLOAD: is the load address of programs. Like CP/M Fuzix uses 0x0100 in
+order to leave the exception vectors free.
+
+PROGTOP: needs to be set to 768 bytes below the common memory base. The
+bytes above this are used by the kernel to store per process data
+
+PROC_SIZE: the number of KB required per process. This will usually be the
+size of the bank region
+
+Delete any swap configuration if your machine has enough banks to hold the
+kernel and 3 processes. If you have less you may need to implement swap from
+the beginning.
+
+To begin with set BOOT_TTY to (512 + 1), set NUM_DEV_TTY to 1 and implement
+just the serial port for bring up.
+
+kernel.def is the matching assembly language definition file.
+
+U_DATA_STASH: should normally match PROGTOP in config.h. It needs to be 512
+bytes of space within the program bank. In theory it could be elsewhere but
+for CP/M emulation it is better to keep the low memory available to the
+user.
+
+PROGBASE and PROGLOAD: these should match config.h
+
+Z80_TYPE: Should be set to 0 for a CMOS Z80, or 1 for an NMOS Z80. If you
+are unsure set the value to 1. This will then compile in workarounds for the
+hardware bugs in the NMOS Z80 processor.
+
+CONFIG_SWAP: should be undefined for now
+
+NBUFS: should match NBUFS in the kernel.
+
+## Memory Map
+
+### Kernel Map
+
+The initial segment the kernel runs from plus common memory is laid out in
+the following order:
+
+Vectors: Low 0x100 bytes. Except for the needed RST instructions the rest of
+this space can be used and some platforms even load the kernel lower. For
+CP/M platforms however 0x100 makes an easy base and means the kernel can be
+loaded as a .COM file and initially even debugged under DDT.
+
+Code: Two banks of code starting at 0x100 and continuing upwards along with
+constants
+
+Data: Mostly zero. This holds the various static variables and data used by
+the kernel, along with arrays for process, file system and the like.
+
+Buffers: This is the final part of the main kernel image. It holds the
+initial buffers for the disk cache.
+
+Discard: Code/Data that is executed only during bring up. This is discarded
+at the point the init user process load begins and the space is reclaimed as
+disk cache buffers. The buffer space reclain continues up until the base of
+the kernel common area.
+
+Common: This holds code and data that must remain mapped at all times,
+including bank switching code, functions that copy memory to user banks and
+the data transfer routines for disk I/O. If you are familiar with CP/M 3
+common memory the approach is similar except that less needs to be in
+common space. The common space for the banked model starts with 768 bytes of
+udata and stack. This holds data specific to the current process that can be
+swapped out with that process, and which is only needed when that process is
+running.
+
+### User Map
+
+The user space memory map is in the following order
+
+Vectors: Low 0x100 bytes. On most platforms this space is available to use
+except for the system call (RST 38h) and interrupt vectors. It should only
+be used by the CP/M emulator for portability reasons.
+
+Code: The binary of the executing process is loaded at 0x100 and executed
+from that address.
+
+Data: This follows the code and consists of the initialized data of the
+current process.
+
+BSS: Zeroed space. It begins at the size specified in the executable header
+but can be extended via the brk() and sbrk() system calls.
+
+Space: Unclaimed space between the top of the BSS and the bottom of the
+stack. This space should not be accessed by a process.
+
+Stack: From the current stack pointer up to the top of the user process
+memory. On entry this holds arguments and environment. It is used for the
+process stack throughout execution.
+
+Save Area: The top 768 bytes of the per process memory map hold a saved copy
+of the udata when that process is not executing.
+
+Above this is the common area of the kernel map.
+
+### Dealing With Awkward Common Sizes
+
+Most systems (particularly those aimed at MP/M) have a common area of 16K or more.
+For these platforms the user process space is limited to the size of the
+non-common area and the kernel non-common area may continue into common space,
+with the 'common' as the kernel sees it set much higher. No special handling of
+this is needed, just set Fuzix up as if the common memory was somewhere higher
+up.
+
+The first problem case is where the common memory is too small. In these cases
+place the common data in the real common and if need be copy the remaining
+common code (read only) into the top of each bank at boot time so that whatever
+bank is selected the common code is present.
+
+The second case covers systems such as the Cromenco where there is no common
+memory as such. These platforms have their own different Z80 support
+framework. See 'Z80 Special Cases' for more information.
+
+The final case is systems with a 32K/32K split such as the Microbee and
+TRS80 model 4. If both the 32K banks can be switched then it can be treated
+the same way as systems like the Cromemco with the advantage that you get
+large processes in memory but at significant complexity cost. If you can
+only switch the lower bank or there is not enough memory for multiple
+processes at a time using both banks then you can implement a system with
+only 32K of user space and banking. This prevents a small number of tools
+such as dc and fsh (Bourne shell with line editing) from being run but not
+much else.
+
+## Standard Files
+
+There are two standard files that are needed for the system and provided by
+generic code for all banked Z80 boxes. The commonmem.s and tricks.s files
+include standard support code and should just include the library versions
+of the code provided. Some of this code is quite complex and tricky.
+
+## Low Level Assembly Functions
+
+These can be found in the file sbcv2.s,ubee.s, and similar functions can be found
+in other banked ports to give more examples (eg trs80, mtx, z80pack).
+
+The assembly level functions are invoked by the low level support code for
+the processor. This can be read at lowlevel-z80.s and the files it includes.
+
+Note that SDCC starts all C symbols with a hidden _ so that other assembly
+labels are not visible in the C namespace.
+
+### Start up code
+
+The first code linked is crt0.s. This can be customized per platform in
+order to do the initial setup needed. It is handy to link it to 0x0100 and
+execute from this address as it can then be executed from CP/M during bring
+up.
+
+The start up code needs to disable interrupts, and set up a valid stack
+pointer. Once this is done it invokes init_early for any platform specific
+early initialization.
+
+After this returns it needs to relocate common and discard memory. When the
+kernel is built the image is packed for size with the common and discard placed
+over the zero data area. This makes the image smaller and also allows it to
+load in situations where it must take some action before using the higher
+memory.
+
+The crt0 code needs to copy this code to the correct location and
+then wipe the data segment. Some platforms may want to do early checks here
+(for example before wiping out CP/M) so they can return nicely to the boot
+environment when an error occurs.
+
+After copying the banks into place and zeroing memory the startup should set
+the stack to kstack_top (in the common space) if it did not already do so,
+and then call init_hardware to do early hardware initialization. Finally it
+invokes_fuzix_main which enters the C environment and never returns.
+
+platform-z80pack provides an example of a fairly minimal crt0.s
+
+### The following should be placed in common memory (.area _COMMONMEM)
+
+_platform_monitor: called when something bad happens. This can either spin
+or can invoke a monitor if one is loaded. If a monitor is not present in ROM
+then one option is to reserve another bank for a monitor/debugger and switch
+bank. Another option is to write the memory image to disk.
+
+_platform_reboot: called when the user shuts down and exits Fuzix. This
+ideally will switch the memory map back and invoke any boot rom. On some
+platforms this is not possible so it may just need to spin. If the boot rom
+clears the screen then add a delay or keyboard wait before rebooting.
+
+_program_vectors: this is called from C when a bank is being set up. It is
+responsible for setting up the entry points in the low memory space. It is
+also invoked with the parameter NULL during boot to initialize the vectors
+in the kernel space. For most platforms this should be identical.
+
+platform_interrupt_all: is invoked at the start of the kernel interrupt
+handler being called. It provides a hook for any special processing but can
+normally just be a ret instruction.
+
+map_kernel: set the bank mapping up so that the kernel is mapped into
+memory. This routine should save and restore any registers it uses.
+
+map_process: map the process whose bank number is in (HL), or if NULL map
+the kernel. This function may corrupt HL and AF but no other registers.
+
+map_process_a: map the process whose bank number is in the A register. This
+should corrupt no other registers except AF. Usually it can be implemented
+as part of map_process.
+
+map_process_always: map the current process. This must not corrupt any
+registers. On most platforms it can be implemented as
+
+       push af
+       push hl
+       ld hl,#U_DATA__U_PAGE
+       call _map_process
+       pop hl
+       pop af
+       ret
+
+but in some cases there may be more efficient methods to do this.
+
+map_save_kernel: saves a copy of the current mapping and map the kernel.
+If any additional banking is being done within the kernel (such as video or ROM
+overlay) it should correctly record the state. This may mean that map_process and
+friends need to record the state they have set up, especially if the bank
+registers are write only. Take care to save the state after mapping the
+kernel or into common space that will always be accessible.
+
+map_restore: restore the mapping saved in the map_save call. Because systems
+with no real common have no banked data memory to store the maps safely it
+is guaranteed that the map_restore will be called with the kernel bank
+mapped.
+
+outchar: this is used by asm debug routines and it should output the
+character in A to whatever port is being used for debug. For a machine with
+serial ports this may well be the serial console itself.
+
+### The following routine must be in code (.area _CODE) memory space.
+
+init_early: this function is invoked during the initial boot up of the
+system before any C code is executed and before the common and disard is
+setup and available. This routine should only do whatever must be done
+before the memory is set up properly.
+
+### The following routine may be in code or discard (.area _DISCARD) memory space.
+
+init_hardware: is invoked before the C entry. It is responsible for setting
+the memory size in Kb of the system and placing it in _ramsize, as well as
+placing the memory size ignoring the kernel in _procmem. For a banked system
+the total memory is normally the size of the real non common area multipled
+by the number of banks plus the size of the common, and the size of process
+memory is 64K less. init_hardware should also invoke _program_vectors with a
+argument on the stack of 0.
+
+## Low Level Data
+
+### Data in buffers (.area _BUFFERS)
+
+The following block is required to create the buffer space the Kernel will
+ensure is place at the end of the kernel image proper
+
+       .globl _bufpool
+       .area _BUFFERS
+_bufpool:
+       .ds BUFSIZE * NBUFS
+
+### Data in common memory
+
+_kernel_flag:
+       .db 1
+
+## C Level Platform Interface
+
+### Functions that may not be in the discard segment
+
+void platform_idle(void) : This function is invoked whenever there is no
+work to run. On a purely interrupt driven machine it can invoke halt
+instructions or other power saving. On a polling machine it normally saves
+the interrupt state, disables interrupts and does a keyboard poll before
+restoring the interrupt state and returning. This causes the serial ports to
+be polled at high speed when idle which gives a far better feel.
+
+uint8_t platform_rtc_secs(void) : If CONFIG_RTC was set this routine will be
+called by the kernel in order to keep a lock between the system time and
+real time. The other clock fields do not matter.
+
+void platform_interrupt(void) : This function is invoked from the low level
+interrupt entry code. It is responsible for handling the results of any
+interrupt events and should also ensure timer_interrupt() is invoked ten
+times per second. This code can also handle polling devices.
+
+void platform_discard(void) : This is called just before init is executed.
+It is able to grow the buffer space (see platform-ubee for an example) or
+otherwise reuse memory removed from discard.
+
+bool validdev(uint16_t dev) : Checks whether a device code is valid. This
+function needs to live in the same file as the device table and can be
+copied as-is from another port.
+
+kputchar(char c): Write a character to the system console. This normally
+invokes tty_putc in the terminal interface but can directly map to a debug
+port if preferred. Unlike tty_putc this should be blocking and not require
+interrupts.
+
+### Functions that may be in the discard segment
+
+void map_init(void) : This can be a null function on a banked system
+
+void pagemap_init(void); This function sets up the page map. For a banked
+system this consists of calling pagemap_add() with an 8bit non zero constant
+to represent each bank. In many cases this can be the actual value to write
+to a bank register. In more complex systems it may be a lookup table index.
+This value is the value passed by poiner to map_process and in A to map_process_a.
+
+uint8_t platform_param(char *p) : Called with each string on the boot
+command line. If a string is recognized as an option return 1 and act upon
+it, otherwise 0. This method is invoked after device_init but before we
+mount the root file system. It is therefore allowed to modify the device
+tables.
+
+void device_init(void) : This is invoked after interrupts are enabled and
+allows device probing and setup to occur before we mount the root file
+system. It is called after the kernel serial (tty) interfaces are invoked so
+the console needs to work before this is called.
+
+### Tables
+
+struct devsw dev_tab[] : This table holds the functions to call for device
+driver operations. Each device major number has open, close, read, write and
+ioctl (control) methods. Not all of the methods are mandatory and the kernel
+provides helper methods - no_open, no_close, no_rdwr, no_ioctl for them.
+Also provided is nxio_open which is the open method for a device that is not
+present in the system.
+
+See the device section on how to fill this in and write device drivers.
diff --git a/docs/DiskFormats.md b/docs/DiskFormats.md
new file mode 100644 (file)
index 0000000..7b5fd96
--- /dev/null
@@ -0,0 +1,67 @@
+# Proposed Fuzix Standard Floppy Disk Formats
+
+## 8" Drives
+
+- Single Density
+26 sectors per track, 128 bytes per sector soft skew
+of 6. IBM 3740 format, standard CP/M format. May be hard
+sectored. Usually 77 tracks. Defacto world wide standard
+for 8" single density.
+
+- Duble Density
+  16 sectors per track, 512 bytes per sector,  skewed at format
+  time. (Cromemco and others).
+
+## 5.25" Drives
+
+These may be 35, 40, 77 or 80 track. Doublestep may be needed.
+
+- Single Density
+  18 sectors per track, 128 bytes per sector, skewed at format
+  time or do we do  9 / 256 ?.
+
+- Double Density
+  10 sectors per track, 512 bytes per sector, skewed at format
+  time. Must also support 9 sectors/track (IBM PC format).
+
+- High Density
+  15 sectors per track, 512 bytes per sector, skewed at format
+  time. (IBM PC format).
+
+## 3.5" Drives
+
+- Double Density
+  As 5.25"
+
+- High Density
+  18 sectors per track, 512 bytes per sector, skewed at format
+  time. (IBM PC format)
+
+- EHD
+  18 sectors per track, 512 bytes per sector, skewed at format
+  time. (IBM PC format)
+
+## 3" Drives
+
+These may be 40 or 80 track, single or double sided. Single sided disks are
+flippable. They are all double density.
+
+- Double Density
+  9 sectors per track, 512 bytes/sector, skewed at format time.
+  (Amstrad format).
+
+Flippable media can either me treated as one file system (only readable properly
+on a double sided drive), or two. Double step may be needed
+
+## General Rules
+
+Systems should support physical media formats used by other common OS on their
+platform, even if not auto-detected. Floppy media should not be partitioned.
+Logical sector order is sector/side/track. In other words blocks are ordered on
+track 0 side 0, then track 0 side 1, then track 1 side 0 and so forth.
+
+Platforms that mix 40 and 80 track media should support double step if possible.
+
+Some platforms have their own way of doing things so will need a different
+private formatting default. They should if possible also support something
+standard. This affects Apple and Commodore mostly.
diff --git a/docs/ExternalBuffers.md b/docs/ExternalBuffers.md
new file mode 100644 (file)
index 0000000..ab9a44c
--- /dev/null
@@ -0,0 +1,39 @@
+# External Buffers
+
+If your platform requires you to place the buffer cache outside of the kernel
+address space (or you want to for other reasons) then you need to provide the
+following functionality and define CONFIG_BLKBUF_EXTERNAL.
+
+    void blktok(void *kaddr, struct blkbuf *buf, uint16_t off, uint16_t len)
+
+    Copy the section of the buffer from offset off, for len bytes into the kernel
+    addres space beginning at kaddr.
+
+    void blkfromk(void *kaddr, struct blkbuf *buf, uint16_t off, uint16_t len)
+
+    Copy from kaddr into the section of the buffer from offset off, for len bytes.
+
+    void blktou(void *uaddr, struct blkbuf *buf, uint16_t off, uint16_t len)
+
+    Copy the section of the buffer from offset off, for len bytes into the current
+    user address space starting at uaddr.
+
+    void blkfromu(void *uaddr, struct blkbuf *buf, uint16_t off, uint16_t len)
+
+    Copy from uaddr in the current user address space into the section of the
+    buffer from offset off, for len bytes.
+
+    void blkzero(struct blkbuf *buf)
+
+    Fill the given buffer data with zero bytes
+
+    void *blkptr(struct blkbuf *buf, uint16_t offset, uint16_t len)
+
+    Return a pointer to a temporary copy of the data in buf from offset to offset
+    + len. The copy is lost on further calls. The largest value of len required is
+    currently about 64 bytes.
+
+The buffers have a private __bf_data field which is native platform sized
+pointer. This is entirely free for the user of your buffer cache manager
+and should be filled in at initialization time using whatever scheme you
+prefer (eg address within the block buffer bank).
diff --git a/docs/M68000.md b/docs/M68000.md
new file mode 100644 (file)
index 0000000..d58ea80
--- /dev/null
@@ -0,0 +1,115 @@
+# Motorola 68000
+
+## System Calls
+
+The syscall API is as follows
+
+trap #12
+
+The trap number is chosen to avoid other traps we might want to use for
+emulating things like TOS or CP/M 68K.
+
+Arguments are placed as follows
+
+    D0.W - call number
+    D1.L - argument 1
+    A0.L - argument 2
+    A1.L - argument 3
+    A2.L - argument 4
+
+All system calls except fork (and in future possibly things like vfork)
+save all registers except A0/A1/D0/D1. This matches the GCC ABI and avoids
+too much stack pushing and popping. Four argument C callers need to save and
+restore A2 first.
+
+System calls are 32bit integer, 32bit pointer.
+
+On return:
+
+    D1.W is the error code if present or 0 if not.
+    D0.L and A0.L hold the return code
+    A1.L is destroyed.
+
+Fork is special. The performance tricks for general syscalls mean that
+fork() cannot restore all the registers. The kernel interface restores only
+A5. A5 is chosen because it is used for the GOT on PIC binaries and without
+A5 being kernel restored a signal just as a fork completes could make a nasty
+mess. A5 is also used in kernel for the udata pointer.
+
+Fork returns the same way as other calls.
+
+To deal with all of this the fork wrapper in libc saves and restores the
+other expected registers (all but A0/A1/D0/D1) so the trick is invisible to
+normal C code.
+
+
+## Signal Handling And VDSO
+
+The kernel injects a short code block in the header space of the binary that is
+not available otherwise. At the moment this consists of two entry points
+
+0: trap and rts to make a system call. Not currently used as it appears
+we don't need to change trap.
+4: signal unwind code
+
+The block is executed in user mode.
+
+The internal behaviour of the signal handler is not defined to be ABI but
+the following are guaranteed.
+
+On entry to a signal handler the stack frame looks like a C call and holds
+(low to high)
+
+       Address of signal unwind code
+       Signal number
+       Pointer to copy of trap frame for hardware exceptions only
+               (This is CPU specific so be careful!)
+       Pointer to save of A0-A1/D0-D1 in MOVEM order with CCR above
+       [Undefined]
+       [A0-A1/D0-D1]
+       [CCR]
+       [Undefined]
+       Return address
+
+A program is permitted to
+
+- longjmp out discarding the frame
+- modify the saved A0-A1/D0-D1 and CCR (eg for emulation)
+- directly set A2-A6/D2-D7 and have them passed back to the code 
+  that caused the event. In other words you can set all registers.
+
+The only portable property is the signal number.
+
+## Executables
+
+Executables are currently loaded using the ucLinux flat binary format. The
+format has some serious problems so this may change.
+
+Only flat binaries with standard relocations are currently supported. Although
+the core kernel is designed to handle PIC the loader does not yet do GOT
+relocations.
+
+Compressed binaries are not supported, nor is executing from ROM.
+
+The 'stack' space is also the sbrk space (akin to Minix). At the moment
+malloc also uses this but that will change.
+
+Binaries with GOTPIC will in future be executed re-entrantly so must be
+clean and contain no data relocations. Other binaries should also have the
+text clean as since we do memory swapping it will be possible to share the
+code across forks (avoiding some of the copying due to MMUless).
+
+Currently binaries are loaded as a single linear block with code, data and
+bss in order then stack. This is *not* guaranteed.
+
+The following binfmt_flat things want fixing ideally
+
+- No field to identify target OS and CPU
+- No field to identify any platform features wanted
+- Relocations are very inefficiently stored
+- Multiple segments cannot be loaded into different places (eg as AmigaOS can)
+- Shared libraries including GOT accesses to private data
+
+so the loader and format are likely to change once the platform develops
+further
+
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644 (file)
index 0000000..c889497
--- /dev/null
@@ -0,0 +1,20 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build-3
+SPHINXPROJ    = Fuzix
+SOURCEDIR     = .
+BUILDDIR      = tmp_build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+       @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+       @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
\ No newline at end of file
diff --git a/docs/Platforms.md b/docs/Platforms.md
new file mode 100644 (file)
index 0000000..691e95c
--- /dev/null
@@ -0,0 +1,299 @@
+# Supported Platforms
+
+## Classic Systems
+
+### Amstrad NC100 and NC200
+
+This requires an Amstrad NC system with PCMCIA memory card. On the NC100 the
+OS is booted from the memory card image and the filesystem is kept upon the
+memory card as well. The NC200 also supports the floppy disk drive.
+
+Supported Features
+- Keyboard
+- Screen
+- Serial port
+- PCMCIA memory card
+- Floppy disk (NC200 only)
+- RTC (in test)
+- Sound (only experimentally)
+
+Unsupported
+- Ranger serial floppy disk drive
+- Related clones (some may work but the 1.44MB drive used by certain units
+  may need additioanl work)
+
+Tested On 0.2
+- NC100: No
+- NC200: Yes, real system
+
+### Dragon 32 / 64 / Tandy COCO2
+
+There are three different ports to differing configurations of this system
+
+The first port is the coco2cart port. This requires a 64K Dragon or 64K Tandy COCO
+with a Cloud 9 compatible IDE or COCOSD cartridge and Fuzix installed on the cartridge and disk.
+Fuzix boots from cartridge, loads the rest of itself into memory and runs in
+single process at a time mode. Due to lack of resources this port is quite
+minimally featured but has some space for further improvement.
+
+The second port is the dragon32-nx port. This supports the Dragon 32/64 or
+Tandy COCO with at least 32K of memory and with Tormod's Spinx cartridge
+giving 512K of banked RAM and an SD card slot. This port offers a full
+featured Fuzix but with userspace limited to 32K per application. On 6809
+this is not a big problem in general.
+
+The third port is the dragon32-mooh port. This supports the Dragon 32/64
+with Tormod's MOOH cartridge. This cartridge offers flexible memory
+management much like that of the Tandy COCO3 and the port makes full use of
+this.
+
+Supported Features
+- Keyboard
+- Video (only text mode on coco2cart)
+- Serial Port (Dragon only)
+- SD or IDE interface
+- MPI (not coco2cart)
+- Drivewire
+- 9128 CRT (not coco2cart)
+- Floppy disk (not coco2cart)
+- Printer
+
+Tested On 0.2
+- COCO2 with SDC: Yes - real system
+- Dragon32 with NX: Yes - real system
+- COCO2 with IDE: Yes - emulation
+
+### Pentagon 1024K
+
+A Russian clone of the Sinclair Spectrum with extensions. Early versions of
+the 1024K Pentagon are a bit different, but probably work with the Scorpion
+port.
+
+Older Pentagon systems do not support mapping RAM into the low 16K so are
+not currently supported.
+
+Supported Features
+- Keyboard
+- Video
+- NemoIDE
+- Joystick (Kempston or Fuller or both)
+- Kempston Mouse
+
+Not Supported
+- BetaDisk
+
+### Scorpion 256K
+
+A Russian clone of the Sinclair Spectrum with extensions, but not quite the
+same ones as the Pentagon.
+
+Supported Features
+- Keyboard
+- Video
+- NemoIDE
+- Joystick (Kempston or Fuller or both)
+- Kempston Mouse
+
+Not Supported
+- BetaDisk
+- SMUC
+
+### Sinclair ZX Spectrum 128K / +2 with DivIDE or DivMMC
+
+There are several ports for versions of the Sinclair systems and their
+clones. This port supports the 128K spectrum and the gray +2 with 128K of
+RAM and a DivIDE or DivMMC adapter. It will also run on the black +2 and the
++3 systems but they have their own port.
+
+Program size is limited to 32K per process due to the limited memory mapping
+capabilities of the platform.
+
+Supported Features
+- Keyboard
+- Video
+- DivIDE
+- DivMMC
+- Joystick (Kempston or Fuller or both)
+- Kempston Mouse
+
+### Sinclair ZX Spectrum +2 (black) / +3
+
+This port supports the later CP/M capable +2 and +3 systems. A suitable hard
+disk adapter is needed not just floppy drives. Unlike the 128K systems full
+size processes can be run.
+
+Supported Features
+- Keyboard
+- Video
+- DivIDE
+- ZXMMC
+- Floppy Drive
+- Joystick (Kempston or Fuller or both)
+- Kempston Mouse
+
+### Sinclair / Timex TC2068 / TS2068
+
+Variants of the Spectrum systems for the US market and also in Argentia,
+Portugal and Poland. At a software level it is not compatible with the
+Sinclair systems but the hardware is except for some extensions. On this
+platform Fuzix needs to be a cartridge.
+
+Supported Features
+- Keyboard
+- Video (including extended Timex modes)
+- DivIDE (via twister, must be set not to boot)
+- Joysticks
+
+Not Supported
+- AY-3-8912 Sound
+
+### Tandy COCO3
+
+The Tandy COCO3 is supported by its own kernel as it differs in many ways
+from the earlier systems.
+
+Supported Features
+- Keyboard
+- Video
+- Drivewire
+- COCOSDC
+- COCO on a chip SDC
+- Glennside style IDE
+- Printer
+
+Not supported
+- COCO3 timer/FIR based serial
+
+### Tandy TRS80 Model I or III / LNW-80 / Video Genie / Dick Smith System 80 / PMZ 80
+
+The classic TRS80 systems and various clones thereof. These systems are not
+usable in Fuzix without add on memory banking cards. The current kernel
+supports either the Alpha SuperMem (or compatibles) or the Selector add in.
+Adding support for other mappers should not be too difficult.
+
+For the Video Genie style systems the S100 based expansion unit and a
+suitable S100 banked memory card can emulate the Alpha SuperMem behaviour
+sufficiently or an new mapper could be added.
+
+Program sizes are limited to 32K by the mappers.
+
+Supported Features (Tandy style)
+- Keyboard
+- Video (Not LNW80 extensions)
+- Floppy Disk
+- Printer
+- RS232 Interface (26-1145 or similar)
+- Hard Disk (26-1132 or modern clones)
+- Lower Case Kit (26-1104 or simple mod)
+- Percom Doubler
+- Holmes style speed up board (anything using port 254 bit 0)
+- RTC (only for clock sync right now)
+- Lo-tech IDE CF
+- Alpha Joystick
+
+Supported Features (Video Genie style)
+- Keyboard
+- Video
+- Lower case (built in or add in)
+- X-4010 Expansion
+- EG3014 / X-4020 Expansion
+- EG3016 Printer
+- EG3020 RS232
+- EG3022 S100 Adapter (but no card drivers)
+- Percom doubler
+- Tandy style RTC
+- Lo-tech IDE CF
+- In theory most things for the TRS80 via the convertor cable.
+- Alpha Joystick
+
+Unsupported
+- LNW80 extended video modes
+- Sound cards
+- Tandy doubler
+- Using Video Genie style printer or serial on TRS80 and vice versa
+
+Tested On 0.2:
+- Yes, emulation only
+
+### TRS80 Model 4/4D/4P with 128K+ RAM
+
+The first TRS80 that can in theory run Fuzix out of the box as supplied.
+128K of RAM is required. A 64K machine cannot run Fuzix.
+
+Program size is limited to 32K per application due to the limits of the
+memory banking.
+
+Supported
+- Keyboard
+- Video
+- Floppy Disk
+- Hard Disk
+- Huffman style banked memory on port 0x94
+- Alpha Joystick
+
+Not Supported
+- Alpha Technologies SuperMem
+- Anitek HyperMem
+- XLR8R
+
+Tested On 0.2:
+- Yes, emulation only. Some problems to resulve on actual hardware.
+
+## Retrobrew And RC2014 Systems
+
+These are modern systems designed to be home built using classic 8bit
+processors, or in some cases early 32bit ones such as the 68000. There are
+two main groups of systems. The Retrobrew (formerly N8VEM) designs generally use
+an ECB bus. The RC2014 systems are mostly a simpler to build design based
+upon a minimalist Z80 bus with their origins in Grant Searle's homebrew CP/M
+systems. There is increasingly an overlap between the two communities so the
+divides are not always clear.
+
+For more information on RC2014 see https://rc2014.co.uk. For more information on
+Retrobrew systems see http://www.retrobrewcomputers.org.
+
+### Easy-Z80
+
+Easy-Z80 is an RC2014 compatible system with onboard SIO, CTC, ROM and RAM
+and including memory banking.
+
+Supported Features
+- Dual SIO serial ports
+- CTC for timers and baud rate setting
+- Some RC2014 add in cards
+
+The Easy-Z80 supports Z80 interrupt mode 2, and any add in cards with
+interrupt support need to be wired for IM2 support.
+
+Tested on 0.2
+- No
+
+### LiNC80 SBC1
+
+The LiNC80 is a single board computer kit that includes Z80 SIO, CTC and PIO
+as well as having optional bank switched RAM and ROM. The port requires you
+have wired yourself up at least one extra 16K RAM RAM bank expansion.
+
+Supported Features
+- SIO/2 serial ports
+- CTC for SIO and clock
+- PIO for SD card interface
+- Compact Flash card
+
+Tested on 0.2
+- No
+
+### N8VEM (now Retrobrew) Mark IV SBC
+
+A Z180 based SBC with optional ECB bus interface.
+
+Supported Features
+- RS232 serial port
+- RS422 serial port
+- IDE/CF adapter
+- SD card interface
+- Onboard RTC
+- Optional PropIO V2 adapter
+
+Tested on 0.2
+- Yes, real system
diff --git a/docs/Tickless.md b/docs/Tickless.md
new file mode 100644 (file)
index 0000000..21be3da
--- /dev/null
@@ -0,0 +1,71 @@
+# Tickless Kernel Support
+
+This chapter describes how to configure a kernel for a system which has no
+available timer tick. Such systems can be made to function but will not be
+able to provide particularly fair time sharing or deal with a process spinning
+in user space very well.
+
+A clock reference is required and interrupt driven I/O is recommended.
+
+
+## Configuration
+
+To configure such a system
+
+    #define CONFIG_NO_CLOCK
+
+Provide a function
+
+    void sync_clock(void)
+    {
+       static uint8_t depth;
+       irqflags_t irq = di();
+       if (!depth++) {
+               Read Timer
+               Call timer_interrupt the correct number of times to
+                       advance
+               Poll any non interrupt devices like serial
+               depth--;
+       }
+       irqrestore(irq);
+    }
+
+Also provide a function
+
+    void update_sync_clock(void)
+    {
+    }
+
+This is called with interrupts off when the kernel changes its time base. If
+you are using the kernel ticks as a timebase for sync_clock you can adjust
+your own timing here. If you are doing your timing entirely via internal
+variables this function can probably be empty.
+
+Finally ensure your platform_idle routine calls sync_clock(). This ensures
+that when idle the time progresses as expected, events happen, sleeps wake and
+alarms go off.
+
+## Functional Limitations
+
+The timing values for process time used will be rather more inaccurate.
+
+Uptime will be pretty meaningless for CPU load.
+
+Task switching will only occur when a process makes a system call after
+exceeding its time quantum, when it sleeps, on process exit, or when a
+signal is delivered. The last one is done to ensure that actions such as
+hitting ^C have a reasonable chance of working correctly even when a process
+is stuck in userspace.
+
+If you have an RTC and your RTC is fast to access you can also consider calling
+sync_clock() on keyboard interrupts. That will normally allow an interactive
+user to regain control of the system in all cases. If the RTC is slow (for
+example a bitbanged SPI) then it is likely to be too expensive to do so.
+
+On some systems it's relatively easy to retrofit a periodic interrupt handler.
+A spare serial port can be used as a timing generator, or an interrupt driven
+serial port with control lines and interrupts for them (eg a 16x50) can have
+one of the control signals wired to something like a PIC generating a 10Hz
+square wave, without interfering with the other use of the port.
+
+Such an approach is preferable.
diff --git a/docs/Z80Thunked.md b/docs/Z80Thunked.md
new file mode 100644 (file)
index 0000000..b953280
--- /dev/null
@@ -0,0 +1,274 @@
+# Z80 Special Cases
+
+## Z80 Systems With a 32K Split
+
+There are two classes of system that fit this category. Those with a 32K
+fixed bank and those with two 32K pages. For the fixed bank case see the
+description of banked Z80 systems. Almost all base Fuzix apps will run in 32K.
+
+If you have two switchable 32K banks then the banking requires some special
+handling. The conventional Fuzix model is that you have a common space which
+holds writable stacks that are used as you transition between modes. When
+you are executing with a pair of 32K banks however you don't have enough
+room to make that model work nicely.
+
+There are two ways a 32K split can be handled. Firstly it is possible to
+treat it as a single bank model. In this case the high (or low) 32K stays
+pinned and the other 32K chunks become one kernel space and the rest are
+process spaces. For a 128K system this is probably the better model unless
+it has very fast swap. The TRS80 model 4 uses this model in part for the
+lack of memory reason and also because the banking rules are quite awkward.
+
+The second approach is to actually do 32K/32K banking. In this model there
+are some signifcant changes to behaviour.
+
+Memory is laid out as
+
+       32K low bank:
+               Kernel code (not data or bss so we can make kernel/user
+               copies easier). Not stacks
+               User space + stubs in low 256 bytes
+
+       32K high bank:
+               Kernel code/data/stacks/udata
+               User space + udata stash
+
+## Entry and Exit
+
+System calls are wrapped with an entry function that switches the
+upper 32K to the kernel upper space and on return switches back to the user
+32K matching the 32K upper at the time of return. Remember you might be
+swapped out while asleep in the kernel! The page number is returned in A
+to help. The stub is responsible for stack switching and must save the old
+sp in U_DATA__U_SYSCALL_SP.
+
+Interrupt entry is expected to do full register saves, map the
+upper 32K and enter the kernel platform code. On return it needs to set the
+lower 32K to match the upper 32K.  The page number is returned in A to help.
+The stub is responsible for stack switching and saving the old stack
+in istack_switched_sp.
+
+Remember you can also take an interrupt in kernel mode in which case the map
+is already present and you need to return to the kernel (A will be 0)
+
+The platform syscall wrapper is responsible for saving IX and loading BC DE HL IX
+with the syscall arguments 1-4 and A with the syscall number. This is needed
+as the user stack may be inaccessible once the entry function switches the
+high bank. The wrapper needs to be in the low 256 bytes.
+
+The return from a system call is as follows
+
+       A = page to map high
+       DE = retval
+       H = signal (or 0)
+       L = errno
+       BC = signal vector
+
+The wrapper must implement the following logic
+
+       map page A high
+       if H then
+               push hl
+               push de
+               push signal number
+               push a return helper
+               push bc
+               ret
+       helper:
+               pop de  ; discard signal
+               pop de
+               pop hl
+               ld h,0
+       endif
+       ld bc,0
+       pop ix  ; we saved it on entry remember
+       ret
+
+Execve is also via a helper. The caller must provide a low memory function.
+Note that the function is called with the user sp set, so may have no valid
+stack on execution until the high page map completes.
+
+    _platform_doexec:
+       map high user page (passed in A)
+       ei
+       jp (hl)
+
+
+The return from an interrupt is as follows (so the handler must save
+HL/DE/AF). The wrapped code will save IX/IY/alt-regs/BC.
+
+       HL = signal vector
+       A = page
+       E = signal
+
+The wrapper must implement the following logic
+
+       map page A high (0 = kernel)
+       switch stacks back
+       if E then
+               push signal number
+               push return helper
+               jp (hl)         
+       helper:
+               pop hl  ; discard signal
+       endif
+       pop hl          ; assuming the wrapper pushed them as af/de/hl
+       pop de
+       pop af
+       ei
+       ret             ; not reti
+
+
+
+## Function Changes
+
+The standard lowlevel-z80 and z80 usermem functions are not used.
+The alternative lowlevel-z80-thunked handlers are used instead.
+
+There is no conventional map_kernel, map_process, map_process_always
+or map_process_a. Instead the routines provided are
+
+       map_kernel_low  -       maps the low kernel pages. Stack must be
+                               high.
+
+       map_user_low    -       map the current user page back into low
+                               memory
+
+       map_page_low    -       map a given page in the low 32K for user
+                               access. Stack must be high.
+
+       map_restore_low -       restore the map from map_save_low
+
+       map_save_low    -       save the old low mapping and switch to
+                               kernel
+
+This is necessary because high page switches have to be inlined as there is
+no easy watch to do stack switches.
+
+The user copy methods must be placed in the upper 32K. They map the needed
+bank into the low 32K and copy taking care of any wraps to flip the low
+32K around as needed.
+
+Device drivers cannot simply map user space because there is no common stack
+space. Instead they too must handle mapping the 32K bank, and the corner
+case of a transfer splitting a block.
+
+To help with this the following are provided
+
+       map_user_low    HL = user address BC = length
+                       DE = kaddr (optional)
+                       IX = page ptr
+
+       returns Z and HL = address to write/read, BC = length
+       returns NZ for 'would split', 
+               HL = address, BC = length before split, DE = kaddr
+               HL' = user address of second, BC' = length of second,
+               DE' = kaddr of second
+               (The ' values are intended to be fed to a second call)
+
+
+Drivers can then decide whether to handle the split or to double buffer the
+odd time it happens.
+
+For example
+
+       ; HL = user address BC = length
+       ; DE = kernel destination
+
+       call map_user_low       ; Map what we can
+       jr z, copy_in_one       ; Single map
+       ldir
+       exx
+       call map_user_low       ; second map cannot split length doesn't matter
+    copy_in_one:
+       ldir
+       jp map_kernel_low
+
+With inir/otir it's a shade more complex
+
+
+    sectors_in:
+       ld b,#2
+    sector_loop:
+       push hl
+       ; 256bytes from disk to user
+       ; HL = user
+       ; BC = length
+       ld bc,#256
+       call map_user_low       ; Map what we can DE data is junk...
+       jr z, copy_in_one       ; Single map
+       ld b,c
+       ld c,port
+       inir
+       exx
+       call map_user_low       ; second map cannot split length doesn't matter
+    copy_in_one:
+       ld b,c
+       ld c,port
+       inir
+       pop hl
+       inc h
+       djnz sector_loop
+       jp map_kernel_low
+
+Swapping is expected to use the functionality above but with
+the map_swap helpers. As swap is aligned in 512 byte chunks from
+0 the splitting case goes away and this looks like other multi-bank
+swap arrangements.
+
+The MMU hooks are not supported in this model.
+
+
+It's possible to use this model with other banking arrangements, eg with a
+16K banked system in order to maximise kernel memory available. However
+because the whole space is flipped to a kernel space this adds the same
+overhead as a conventional single bank arrangement in order to copy the
+udata.
+
+
+## Systems with 64K switching via ROM helper
+
+These systems use the same basic interfaces except that
+
+- The helper must switch the whole address space
+
+- map_page_low and map_kernel_low don't do anything but remember the
+  selected page
+
+- The rom must provide a routine to copy the initial common code from the
+  starting bank to other banks
+
+- The entry code as with 32K ends up doing something like
+
+       ld (switch_sp),sp
+       di                              ; if syscall
+       ld sp, kstack                   ; one for syscall one for irq
+       ld a,kernel
+       out (x),a                       ; kernel map
+       ei                              ; if syscall
+       ; Switches to the same code in the other bank and the kstack
+       call helper
+       di                              ; if syscall
+       out (x),a                       ; user page in A
+       ; back on other stack - this means we can't push/pop over these
+       ; boundaries so we may need to save alt regs or ix/iy and use them
+       ; for the stubs
+       ; A BC DE HL tell us what to do
+
+       ...
+
+- Use the 64K via ROM functions.
+
+
+The final case is systems without a common memory where you can write
+through pages or where the shared memory has awkward side effects (eg a
+Nascom). This is basically the above example but with RAM based helpers written
+through into the top of each bank which implement the functions specified.
+Take care that you use a private all bank stack for them or that they
+block interrupts.
+
+For all these cases task switching is done single bank style. The kernel
+helpers in tricks.s save/restore a common udata. The actual switch may cause
+temporary banks switches to shuffle udata but does not cause any visible
+ones.
+
diff --git a/docs/build-filesystem-ng.md b/docs/build-filesystem-ng.md
new file mode 100644 (file)
index 0000000..8cd69e8
--- /dev/null
@@ -0,0 +1,373 @@
+# Packaging/Disk Image Build System for FUZIX
+
+## Overview
+
+build-filesystem-ng is designed as a replacement for build-filesystem. If
+accepted, it will be renamed and the old files retired.
+
+build-filesystem-ng is a script for creating a FUZIX disk image. It has some of
+the attributes of a package manager. The original motivation for its development
+was to move away from the monolithic build-filesystem script. Using
+build-filesystem-ng, each application or group of files can be described by a
+separate package file which can be created and maintained in a distributed way.
+
+build-filesystem-ng makes it easy to identify target-specific and
+platform-specific files/file-sets in order to create a tailored disk image.
+
+
+## Operation
+
+When build-filesystem-ng is executed, it performs these steps in sequence:
+
+* Search the Standalone and Application trees for package files. Package files
+  are recognised by name. It's OK to have multiple package files with the same
+  name.
+* Determine whether each package is enabled or disabled.
+* Re-order the package list, if necessary, to resolve declared dependencies of
+  enabled packages.
+* Generate a FUZIX disk image containing all of the elements (files,
+  directories, nodes etc.) specified in the enabled packages
+
+
+## Package Files
+
+A package file is plain ASCII, typically hand-generated.
+
+Each package file contains zero or more package definitions. Each package
+definition is followed by zero or more attributes and then by zero or more
+commands. A package definition is simply the name of the package. Package names
+must be unique.
+
+
+## Example
+
+Here are 3 (cut-down) package files.
+
+Standalone/filesystem-src/fuzix-basefs.pkg
+````
+package  basefs
+
+d 0755 /
+d 0755 /usr
+d 0755 /dev
+d 0755 /usr/share
+
+f 0644 /usr/lib/liberror.txt            ../../Library/libs/liberror.txt
+
+n 20666 512 /dev/tty   
+````
+
+Applications/util/fuzix-util.pkg
+````
+package  util
+
+f 0755 /bin/banner      banner
+f 0755 /bin/basename    basename
+f 0755 /bin/man         man
+f 0644 /usr/man/man1/man.1    man.1
+
+package  z80-util
+if-cpu  z80
+
+f 0755 /bin/patchcpm    patchcpm
+
+````
+
+Applications/rpilot-1.4.2/fuzix-rpilot.pkg
+````
+package  rpilot
+if-file  rpilot
+
+f 0755 /usr/bin/rpilot                     rpilot
+l      /usr/bin/rpilot                     /usr/bin/pilot
+f 0644 /usr/man/man1/rpilot.1              doc/rpilot.1
+d 0755 /usr/doc/rpilot
+
+````
+
+The format is line-based and uses \# as the comment-to-end-of-line character.
+
+The definition of a package extends from the "package" keyword until the next
+"package" keyword or until the end of the file. Thus, a file can contain
+multiple package definitions.
+
+The "package" keyword is followed by zero or more lines of attributes and then
+by zero or more lines of commands. Within a line, keywords/attributes/commands
+are space-separated from their arguments.
+
+The following commands are (currently) defined:
+
+* d - create and set permissions on a directory. The directory must be created
+  leaf by leaf.
+* n - create and set properties on a node.
+* f - copy and set permissions on a file. The destination directory must
+  exist. The source and destination file names are specified independently. The
+  source file is specified relative to the location of the package file (so
+  fuzix-basefs.pkg needs to ../ its way to liberror.txt but fuzix-util.pkg can
+  reference banner in the cwd).
+* l - link from existing file to new file. The full path of both files must
+  be specified. The destination directory must exist.
+* r - remove an existing file. The full path of the file must be specified.
+* (a rename can be synthesised by a l followed by a r)
+
+The following attributes are shown in the examples:
+
+* if-file - this is used in optional packages. It checks for the existence of the
+  named file. If the named file is not found, the package is disabled. This
+  provides a simple method to omit groups of files from applications that have not
+  been built.
+* if-cpu - this is used to disable a package if its content is only applicable to
+  a particular target.
+
+
+## Enabling and disabling packages
+
+Consider the following use-cases:
+
+1. Build a disk image containing everything that's available
+2. Build a disk image containing everything that is suitable for a specific target processor
+3. Build a disk image containing a specific package or set of packages
+4. Build a disk image omitting a specific package or set of packages
+
+The first use-case is trivial; it is the default behaviour of the script. A
+well-written package file will include the "if-file" attribute and so all
+packages that have been built will be included in the disk image.
+
+The remaining three use-cases require the use of a "meta-package". A
+meta-package is disabled by default (and therefore will not form part of
+"everything that's available" in the previous example). One single meta-package
+can be enabled at the command-line.
+
+The second use-case can be achieved using a package file like this:
+
+````
+# My custom setup
+package  mysys09
+disable-pkg  mysys09
+
+set-cpu  6809
+````
+
+Which is applied like this:
+
+````
+./build-filesystem-ng -x -f fuzixfs.dsk -p mysys09
+````
+
+The attribute disable-pkg is used to disable the package by default. The
+package is enabled by the -p command-line argument.
+
+The attribute set-cpu provides a value that is tested by if-cpu (fuzix-util.pkg
+above provides an example). The if-cpu test will fail (package will be disabled)
+if a set-cpu attribute is found in an enabled package _and_ the arguments to
+if-cpu and set-cpu mis-match (therefore, in the absence of a set-cpu attribute,
+the if-cpu test will always pass; package will remain enabled).
+
+There is also an attribute pair if-platform/set-platform. They work in the same
+way as if-cpu/set-cpu.
+
+Notes:
+
+* The order in which package files are found/processed does not affect the
+  decision-making
+* The implementation is intended to cope will real use-cases. You can surely
+  compose pathological cases that are mutually contradictory.
+
+The last two use-cases take opposite approaches to the same problem. One says
+"start with nothing and add a specific set of package", the other says "start
+with everything and remove a specific set of packages". Here is a package file
+for the "start with nothing" approach:
+
+````
+# A specific set of packages for my system
+package  mysys-nothing
+disable-pkg  mysys-nothing ALL
+enable-pkg basefs games V7-games adventure
+````
+
+As before, it is selected using the -p command-line parameter.
+
+This example introduces:
+
+* The special/reserved package name ALL which is used to disable every package
+* The idea that disable-pkg actually accepts a _list_ of packages
+* The attribute enable-pkg which is used to specify a list of packages to enable
+
+
+Notes:
+
+* You can only use ALL with disable-pkg
+* You should only used ALL once, in the package specified at the command-line
+* The _order_ of the enable-pkg, disable-pkg attributes has no effect on the
+  behaviour of ALL; it has the effect of disabling every package (except the one
+  that contains it) before any enable-pkg attributes are considered.
+
+Finally, here is a package file for the "start with everything" approach:
+
+````
+# An educational system. No games (boo!)
+package  mysys-all
+disable-pkg  mysys-all games V7-games adventure
+````
+As before, it is selected using the -p command-line parameter.
+
+
+Each package referred to on the enable-pkg/disable-pkg list could itself be a
+meta-package. The design of the meta-package depends upon whether you are using
+the "start with everything" or the "start with nothing" approach. For example,
+consider these two package definitions (conveniently stored in a single file):
+
+````
+# All the games
+package  allgames
+disable-pkg allgames
+enable-pkg  games V7-games adventure
+
+# None of the games
+package no-allgames
+disable-pkg no-allgames games V7-games adventure
+````
+
+And then the earlier examples would become:
+
+````
+# A specific set of packages for my system
+package  mysys
+disable-pkg  mysys ALL
+enable-pkg basefs allgames
+````
+and:
+
+````
+# An educational system. No games (boo!)
+package  mysys
+disable-pkg  mysys
+enable-pkg no-allgames    # enable it so it can disable packages!
+````
+
+Package files can be "nested" to arbitrary depth in this way.
+
+Notes:
+
+* The idea of including a "positive" and "negative" meta-package in a single
+  file is a convenient way of leaving your options open
+* The "no-" prefix to the package name has no significance to build-filesystem-ng
+  but might be considered a useful working-practise.
+
+Implementation detail: package enabling/disabling is a 6-stage process:
+
+* Apply defaults: enable any package unless it is self-disabled
+* Apply -p: enable a package referenced on the command-line
+* Apply ALL if found: disable all packages except its containing package
+* For all enabled packages, process any enable-pkg statements. Iterate until stable
+* For all enabled packages, process any disable-pkg statements except self-disable (no iteration is required here)
+* For all enabled packages, process any if-file if-cpu if-platform attributes (may result in packages being disabled)
+
+Once the attributes have been processed, each enabled package is expected to be
+able to be processed to completion without errors. Errors are fatal.
+
+
+## Building Small Disk Images
+
+Here are some techniques for building small disk images.
+
+* Create a meta-package, use ALL to disable everything
+* Refactor existing packages (within a single package file) into a minimal
+  and a full-blown file set (see fuzix-util.pkg for an example of this) and
+  then pull in the minimal parts
+* Use r (remove) in the meta-package file to tactically trim away files you
+  can do without
+
+
+See Standalone/filesystem-src/fuzix-mini.pkg for an example.
+
+## Building Custom Disk Images
+
+Here are some techniques for building custom disk images.
+
+* Create a meta-package
+* Use the techniques elsewhere to customise the package list, if required
+* There is no command to _rename_ a file, but you can synthesise a rename by
+  a link followed by remove of the original file.
+* You cannot overwrite a file (for example, to replace /etc/inittab with
+  a version customised for your system) but you can synthesise an overwrite
+  by a remove followed by a copy of the new file
+
+Here is an example of these techniues:
+
+````
+# Custom package for my system
+package deluxe
+disable-pkg deluxe
+# synthesise rename of /etc/init
+l /etc/inittab /etc/inittab.orig
+r /etc/inittab
+
+# replace it with a version that starts up 2 terminals
+f 0644 /etc/inittab   my_inittab
+````
+
+One 'gotcha' with this technique is that there is (currently) no control over
+the order in which package files are processed, except that those in Standalone/
+are processed before those in Applications/. See require-pkg in the 'futures'
+section below.
+
+
+## Futures
+
+This section is a list of anticipated but not-yet-implemented changes.
+Mail me with other requirements.
+
+1. Dependencies, using new attribute require-pkg. -- A simple iterative solver
+will put them in the right order. Currently, all packages have an implicit
+dependency on fuzix-basefs.pkg and it is "luck" that it gets processed first.
+
+2. Add Kernel/platform to search list
+
+and some more attributes, then a package can be found there like this (Kernel/platform/fuzix.pkg):
+
+````
+# This is a platform-specific file found through the Kernel/platform link
+package  multicomp09
+set-cpu  6809
+set-platform  multicomp09
+set-endian  big
+set-geometry  256   65535
+````
+
+3. allow enable-pkg disable-pkg to be repeated within a package file:
+concatenate their argument lists. Currently ignore all but the last instance in
+any packaged file.
+
+
+## Implementation
+
+build-filesystem-ng is a PERL script which runs on the host system and invokes
+the FUZIX mkfs, ucp and fsk executables.
+
+Each of the (currently-defined) commands maps to one or more ucp commands. A
+correct-by-construction ucp script is generated (ucp-temp.txt) and applied to
+the ucp executable.
+
+The r(emove) command does not remove an entry from the ucp-temp.txt - it generates
+a new (rm) entry in ucp-temp.txt.
+
+
+## Restrictions and error-handling
+
+Within a package file, # is treated as a comment character, with no escape. Text
+from '#' to the end of the line is discarded.
+
+Whitespace acts as a separator. Excess whitespace is ignored and discarded.
+
+There is no accommodation for file-names that include whitespace or quotes or
+slashes or anything weird.
+
+Attempts to multiply-define a directory/node/file generate an error, referenced
+back to the source directory/file/line (ucp allows a file to be redefined but I
+do not).
+
+build-filesystem-ng processes all package files to completion, reporting all
+errors. If this process is successful it goes on to apply the ucp script. An
+error in the execution of the ucp script represents a bug in
+build-filesystem-ng.
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644 (file)
index 0000000..e1640fc
--- /dev/null
@@ -0,0 +1,166 @@
+# -*- coding: utf-8 -*-
+#
+# Configuration file for the Sphinx documentation builder.
+#
+# This file does only contain a selection of the most common options. For a
+# full list see the documentation:
+# http://www.sphinx-doc.org/en/master/config
+
+# -- Path setup --------------------------------------------------------------
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+# import os
+# import sys
+# sys.path.insert(0, os.path.abspath('.'))
+
+
+# -- Project information -----------------------------------------------------
+
+project = 'Fuzix'
+copyright = '2019, Alan Cox'
+author = 'Alan Cox'
+
+# The short X.Y version
+version = '0.3'
+# The full version, including alpha/beta/rc tags
+release = '0.3-rc1'
+
+
+# -- General configuration ---------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#
+# needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+    'sphinx.ext.todo',
+    'sphinx.ext.ifconfig',
+    'sphinx.ext.githubpages',
+    'recommonmark'
+]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['tmp_templates']
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+#
+source_suffix = ['.rst', '.md']
+
+# The master toctree document.
+master_doc = 'index'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = None
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This pattern also affects html_static_path and html_extra_path .
+exclude_patterns = ['tmp_build', 'Thumbs.db', '.DS_Store']
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+
+# -- Options for HTML output -------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+#
+html_theme = 'alabaster'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#
+# html_theme_options = {}
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['tmp_static']
+
+# Custom sidebar templates, must be a dictionary that maps document names
+# to template names.
+#
+# The default sidebars (for documents that don't match any pattern) are
+# defined by theme itself.  Builtin themes are using these templates by
+# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
+# 'searchbox.html']``.
+#
+# html_sidebars = {}
+
+
+# -- Options for HTMLHelp output ---------------------------------------------
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'Fuzixdoc'
+
+
+# -- Options for LaTeX output ------------------------------------------------
+
+latex_elements = {
+    # The paper size ('letterpaper' or 'a4paper').
+    #
+    # 'papersize': 'letterpaper',
+
+    # The font size ('10pt', '11pt' or '12pt').
+    #
+    # 'pointsize': '10pt',
+
+    # Additional stuff for the LaTeX preamble.
+    #
+    # 'preamble': '',
+
+    # Latex figure (float) alignment
+    #
+    # 'figure_align': 'htbp',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+#  author, documentclass [howto, manual, or own class]).
+latex_documents = [
+    (master_doc, 'Fuzix.tex', 'Fuzix Documentation',
+     'Alan Cox', 'manual'),
+]
+
+
+# -- Options for manual page output ------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    (master_doc, 'fuzix', 'Fuzix Documentation',
+     [author], 1)
+]
+
+
+# -- Options for Texinfo output ----------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+    (master_doc, 'Fuzix', 'Fuzix Documentation',
+     author, 'Fuzix', 'One line description of project.',
+     'Miscellaneous'),
+]
+
+
+# -- Extension configuration -------------------------------------------------
+
+# -- Options for todo extension ----------------------------------------------
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = True