summaryrefslogtreecommitdiffstats
path: root/sw-old/z80/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'sw-old/z80/kernel')
-rw-r--r--sw-old/z80/kernel/crt0.s103
-rw-r--r--sw-old/z80/kernel/fs/fd.c255
-rw-r--r--sw-old/z80/kernel/fs/fs.c236
-rw-r--r--sw-old/z80/kernel/include/devices.h15
-rw-r--r--sw-old/z80/kernel/include/errno.h35
-rw-r--r--sw-old/z80/kernel/include/fs/dev.h29
-rw-r--r--sw-old/z80/kernel/include/fs/dirent.h17
-rw-r--r--sw-old/z80/kernel/include/fs/fd.h102
-rw-r--r--sw-old/z80/kernel/include/fs/fdop.h140
-rw-r--r--sw-old/z80/kernel/include/fs/fs.h63
-rw-r--r--sw-old/z80/kernel/include/fs/iter.h17
-rw-r--r--sw-old/z80/kernel/include/fs/users.h21
-rw-r--r--sw-old/z80/kernel/include/memory.h50
-rw-r--r--sw-old/z80/kernel/include/process.h43
-rw-r--r--sw-old/z80/kernel/include/sio.h43
-rw-r--r--sw-old/z80/kernel/include/stat.h24
-rw-r--r--sw-old/z80/kernel/include/types.h62
-rw-r--r--sw-old/z80/kernel/kernel.c7
-rw-r--r--sw-old/z80/kernel/makefile53
-rw-r--r--sw-old/z80/kernel/memory.c94
-rw-r--r--sw-old/z80/kernel/process.c58
21 files changed, 1467 insertions, 0 deletions
diff --git a/sw-old/z80/kernel/crt0.s b/sw-old/z80/kernel/crt0.s
new file mode 100644
index 0000000..00c7da1
--- /dev/null
+++ b/sw-old/z80/kernel/crt0.s
@@ -0,0 +1,103 @@
+;--------------------------------------------------------------------------
+; crt0.s - Generic crt0.s for a Z80
+;
+; Copyright (C) 2000, Michael Hope
+;
+; This library 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, or (at your option) any
+; later version.
+;
+; This library 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 library; see the file COPYING. If not, write to the
+; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+; MA 02110-1301, USA.
+;
+; As a special exception, if you link this library with other files,
+; some of which are compiled with SDCC, to produce an executable,
+; this library does not by itself cause the resulting executable to
+; be covered by the GNU General Public License. This exception does
+; not however invalidate any other reasons why the executable file
+; might be covered by the GNU General Public License.
+;--------------------------------------------------------------------------
+
+ .module crt0
+ .globl _kmain
+
+ .area _HEADER (ABS)
+ ;; Reset vector
+ .org 0
+ jp init
+
+ .org 0x08
+ reti
+ .org 0x10
+ reti
+ .org 0x18
+ reti
+ .org 0x20
+ reti
+ .org 0x28
+ reti
+ .org 0x30
+ reti
+ .org 0x38
+ reti
+
+ .org 0x100
+init:
+ ;; Set stack pointer directly above top of memory.
+ ld sp,#0xFFFF
+
+ ;; Initialise global variables
+ call gsinit
+ call _kmain
+ jp _exit
+
+ ;; Ordering of segments for the linker.
+ .area _HOME
+ .area _CODE
+ .area _INITIALIZER
+ .area _GSINIT
+ .area _GSFINAL
+
+ .area _DATA
+ .area _INITIALIZED
+ .area _BSEG
+ .area _BSS
+ .area _HEAP
+
+ .area _CODE
+
+__clock::
+ ld a,#2
+ rst 0x08
+ ret
+
+_exit::
+ ;; Exit - special code to the emulator
+ ld a,#0
+ rst 0x08
+1$:
+ halt
+ jr 1$
+
+ .area _GSINIT
+gsinit::
+ ; ld bc, #l__INITIALIZER
+ ld a, b
+ or a, c
+ jr Z, gsinit_next
+ ; ld de, #s__INITIALIZED
+ ; ld hl, #s__INITIALIZER
+ ldir
+gsinit_next:
+
+ .area _GSFINAL
+ ret
+
diff --git a/sw-old/z80/kernel/fs/fd.c b/sw-old/z80/kernel/fs/fd.c
new file mode 100644
index 0000000..96603ad
--- /dev/null
+++ b/sw-old/z80/kernel/fs/fd.c
@@ -0,0 +1,255 @@
+#include "fs/fd.h"
+#include "fs/fdop.h"
+#include "fs/fs.h"
+
+/* from fd.h */
+struct file_desc fd_table[FD_TABLE_SIZE];
+struct uint8_t fd_bmap[FD_TABLE_SIZE / 8];
+
+/* File descriptors implementation */
+
+int8_t open(const char *path, uint8_t flags)
+{
+ // TODO
+ return 0;
+}
+
+size_t ls(int8_t fd, struct dirent *buf, uint8_t all)
+{
+ // TODO
+ return 0;
+}
+
+size_t find(int8_t fd, struct dirent *buf, const char *name)
+{
+ // TODO
+ return 0;
+}
+
+int8_t mkdir(int8_t fd, const char *name)
+{
+ // TODO
+ return 0;
+}
+
+int8_t touch(int8_t fd, const char *name)
+{
+ // TODO
+ return 0;
+}
+
+int8_t ln(int8_t fd, const char *name)
+{
+ // TODO
+ return 0;
+}
+
+int8_t seek(int8_t fd, fsize_t pos)
+{
+ // TODO
+ return 0;
+}
+
+size_t readline(int8_t fd, char *buf, char term)
+{
+ // TODO
+ return 0;
+}
+
+int8_t print(int8_t fd, const char *str)
+{
+ // TODO
+ return 0;
+}
+
+size_t read(int8_t fd, void *buf, size_t n)
+{
+ // TODO
+ return 0;
+}
+
+int8_t write(int8_t fd, const void *buf, size_t n)
+{
+ // TODO
+ return 0;
+}
+
+void close(int8_t fd)
+{
+ // TODO
+ return 0;
+}
+
+/* Set of file descriptors operations */
+/* Determines if to use the serial interface or the address space */
+
+/* Address space section */
+
+/* File functions */
+
+size_t as_readline(inode_t inode, fsize_t seek, char *buf, char term)
+{
+ // TODO
+ return 0;
+}
+
+size_t as_print(inode_t inode, fsize_t seek, const char *str)
+{
+ // TODO
+ return 0;
+}
+
+size_t as_append(inode_t inode, fsize_t *seek_ptr, const char *str)
+{
+ // TODO
+ return 0;
+}
+
+size_t as_read(inode_t inode, fsize_t seek, void *buf, size_t n)
+{
+ // TODO
+ return 0;
+}
+
+size_t as_write(inode_t inode, fsize_t seek, const void *buf, size_t n)
+{
+ // TODO
+ return 0;
+}
+
+size_t as_bin_append(inode_t inode, fsize_t *seek_ptr, const void *buf, size_t
+n)
+{
+ // TODO
+ return 0;
+}
+
+/* Directory functions */
+
+size_t as_ls(inode_t inode, struct dirent *buf, uint8_t all)
+{
+ // TODO
+ return 0;
+}
+
+size_t as_find(inode_t inode, struct dirent *buf, const char *name)
+{
+ // TODO
+ return 0;
+}
+
+int8_t as_mkdir(inode_t inode, const char *name)
+{
+ // TODO
+ return 0;
+}
+
+int8_t as_rmdir(inode_t inode, const char *name)
+{
+ // TODO
+ return 0;
+}
+
+int8_t as_touch(inode_t inode, const char *name)
+{
+ // TODO
+ return 0;
+}
+
+int8_t as_rm(inode_t inode, const char *name)
+{
+ // TODO
+ return 0;
+}
+
+int8_t as_ln(inode_t inode, const char *path, const char *name)
+{
+ // TODO
+ return 0;
+}
+
+/* Serial Space section */
+/* Warning, it doesn't switch to the right driver */
+
+/* File functions */
+
+size_t ss_readline(inode_t inode, fsize_t seek, char *buf, char term)
+{
+ // TODO
+ return 0;
+}
+
+size_t ss_print(inode_t inode, fsize_t seek, const char *str)
+{
+ // TODO
+ return 0;
+}
+
+size_t ss_append(inode_t inode, fsize_t *seek_ptr, const char *str)
+{
+ // TODO
+ return 0;
+}
+
+size_t ss_read(inode_t inode, fsize_t seek, void *buf, size_t n)
+{
+ // TODO
+ return 0;
+}
+
+size_t ss_write(inode_t inode, fsize_t seek, const void *buf, size_t n)
+{
+ // TODO
+ return 0;
+}
+
+size_t ss_bin_append(inode_t inode, fsize_t *seek_ptr, const void *buf, size_t
+n)
+{
+ // TODO
+ return 0;
+}
+
+/* Directory functions */
+
+size_t ss_ls(inode_t inode, struct dirent *buf, uint8_t all)
+{
+ // TODO
+ return 0;
+}
+
+size_t ss_find(inode_t inode, struct dirent *buf, const char *name)
+{
+ // TODO
+ return 0;
+}
+
+int8_t ss_mkdir(inode_t inode, const char *name)
+{
+ // TODO
+ return 0;
+}
+
+int8_t ss_rmdir(inode_t inode, const char *name)
+{
+ // TODO
+ return 0;
+}
+
+int8_t ss_touch(inode_t inode, const char *name)
+{
+ // TODO
+ return 0;
+}
+
+int8_t ss_rm(inode_t inode, const char *name)
+{
+ // TODO
+ return 0;
+}
+
+int8_t ss_ln(inode_t, const char *path, const char *name)
+{
+ // TODO
+ return 0;
+}
diff --git a/sw-old/z80/kernel/fs/fs.c b/sw-old/z80/kernel/fs/fs.c
new file mode 100644
index 0000000..584f934
--- /dev/null
+++ b/sw-old/z80/kernel/fs/fs.c
@@ -0,0 +1,236 @@
+#include "fs/fs.h"
+#include "fs/users.h"
+#include "fs/dev.h"
+
+/* from users.h */
+struct fs_user c_user;
+
+/* from inode.h */
+inode_t c_inode;
+
+struct fs_dev devices[FS_MOUNT_LIMIT];
+
+/* filesystem basic implementation */
+
+devsize_t fs_block(blk_t block)
+{
+ // TODO
+ return 0;
+}
+
+devsize_t fs_inode(struct fs_inode *buf)
+{
+ struct fs_superblock * sb;
+ devsize_t seek;
+
+ if (FS_USE_ROM(c_inode))
+ {
+ seek = FS_ROM_SPACE;
+ sb = (struct fs_superblock*) seek;
+
+ } else {
+
+ seek = 0;
+
+ if (c_inode.dev > 0x7)
+ panic("Invalid device"); // TODO, still to implement
+
+ sb = &devices[c_inode.dev].superblock;
+ }
+
+ if (c_inode.inode >= sb->imap_size)
+ {
+ // TODO, set errno
+ return 0; // inode doesn't exist
+ }
+
+ seek += sizeof(struct fs_superblock) +
+ sizeof(struct fs_inode) * c_inode.inode;
+
+ if (FS_USE_ROM(c_inode))
+ *buf = *(struct fs_inode*)seek;
+ else
+ {
+ /* set sio port */
+ sio_port = devices[c_inode.dev].port_no;
+ sio_seek = seek;
+
+ if (sio_read((void *)buf, INODE_META_SIZE) < INODE_META_SIZE)
+ {
+ // TODO, set errno
+ return 0; // cannot read to device
+ }
+ }
+
+ return seek + INODE_META_SIZE;
+}
+
+/* from fd.h */
+int8_t __fd_new()
+{
+ int8_t fd;
+ for (int8_t = 0; i < FD_TABLE_SIZE / 8; i++)
+ {
+ for (uint8_t bit = 0x80, j = 0; bit > 0; bit >>= 1, j++)
+ {
+ if (!(bit & fd_bmap[i]))
+ return i * 8 + j;
+ }
+ }
+
+ return -1;
+}
+
+/* from fd.h */
+int8_t __open_c_inode(uint8_t flags)
+{
+ /* read meta data */
+ struct fs_inode inode;
+
+ /* init file_desc buffer */
+ struct file_desc desc = {c_inode, 0};
+
+ desc.begin = fs_inode(&inode);
+
+ /* bind operations */
+
+ if (flags & OPEN_DIR)
+ {
+ /* dir handler */
+
+ if (inode.type == INODE_TYPE_DIR)
+ {
+ /* bind dir functions */
+ if (FS_USE_ROM(c_inode))
+ /* bind address space functions */
+ FD_BIND_AS_DIR(desc.opers)
+ else
+ /* bind serial space functions */
+ FD_BIND_SS_DIR(desc.opers)
+
+ } else {
+
+ // TODO, set errno
+ return -1; // not a directory
+ }
+
+ } else if (flags & OPEN_LINK) {
+
+ /* link handler */
+
+ if (inode.type == INODE_TYPE_LINK)
+ {
+ if (FS_USE_ROM(c_inode))
+ FD_BIND_AS_FILE(desc.opers, flags)
+ else
+ FD_BIND_SS_FILE(desc.opers, flags)
+
+ if (flags & OPEN_ERASE)
+ /* empty file content */
+ __inode_empty(desc.begin);
+
+ } else {
+
+ // TODO, set errno
+ return -1; // not a link
+ }
+
+ } else {
+
+ /* file */
+
+ if (inode.type == INODE_TYPE_FILE)
+ ; // do nothing
+ else if (inode.type == INODE_TYPE_SPECIAL) {
+
+ // TODO, bind special callbacks
+
+ } else {
+
+ // TODO, set errno
+ return -1;
+ }
+
+ /* bind operations */
+
+ if (FS_USE_ROM(c_inode))
+ {
+ if (flags & OPEN_BIN)
+ FD_BIND_AS_BINFILE(desc.opers, flags)
+ else
+ FD_BIND_AS_FILE(desc.opers, flags)
+
+ } else {
+
+ if (flags & OPEN_BIN)
+ FD_BIND_SS_BINFILE(desc.opers, flags)
+ else
+ FD_BIND_SS_FILE(desc.opers, flags)
+ }
+ }
+
+ /* find a free fd space */
+
+ int8_t fd = __fd_new();
+
+ if (fd < 0)
+ {
+ // TODO, set errno, fd not available
+
+ } else
+ fd_table[fd] = desc; // copy buffer into the table
+
+ return fd;
+}
+
+inode_t fs_rec_path(const char *path);
+
+inode_t fs_parse_path(const char *path)
+{
+ inode_t ino, cwd = c_inode;
+
+ switch (path[0])
+ {
+ case '0':
+ FS_INODE_NULL(ino)
+ return ino;
+
+ case '/':
+ FS_INODE_ROOT(ino)
+ c_inode = ino; // set cwd to root
+ path++;
+ break;
+
+ case '~':
+
+ if (path[1] = '/')
+ {
+ c_inode.dev = FS_DEV_ROM;
+ c_inode.inode = c_user.home; // set cwd to home
+ path += 2;
+ }
+
+ break;
+ }
+
+ ino = fs_rec_path(path);
+ c_inode = cwd;
+ return ino;
+}
+
+inode_t fs_rec_path(const char *path)
+{
+ devsize_t inode = fs_inode(c_inode.inode);
+ inode_t rel;
+
+ if (!inode) // if not exists
+ {
+ FS_INODE_NULL(rel)
+ return rel;
+ }
+
+ // TODO, check if dir or file
+ // TODO, if dir, find name
+ // TODO, set fs_cwd to new inode
+ // TODO, recall fs_rec_path
+}
diff --git a/sw-old/z80/kernel/include/devices.h b/sw-old/z80/kernel/include/devices.h
new file mode 100644
index 0000000..a846f9b
--- /dev/null
+++ b/sw-old/z80/kernel/include/devices.h
@@ -0,0 +1,15 @@
+#ifndef __DEVICES_H__
+#define __DEVICES_H__
+
+#define ADDR_DEV_ROM_L 0x0000
+#define ADDR_DEV_ROM_H 0x2000
+
+#define ADDR_DEV_USART 0x4000
+#define ADDR_DEV_CTC 0x4100
+#define ADDR_DEV_PIO 0x4200
+
+#define ADDR_DEV_MMU
+
+#define ADDR_DEV_RAM 0x8000
+
+#endif
diff --git a/sw-old/z80/kernel/include/errno.h b/sw-old/z80/kernel/include/errno.h
new file mode 100644
index 0000000..7632269
--- /dev/null
+++ b/sw-old/z80/kernel/include/errno.h
@@ -0,0 +1,35 @@
+#ifndef ERRNO_H
+#define ERRNO_H
+
+extern int errno;
+
+#define EPERM 1 /* Operation not permitted */
+#define ENOENT 2 /* No such file or directory */
+#define ESRCH 3 /* No such process */
+#define EINTR 4 /* Interrupted system call */
+#define EIO 5 /* Input/output error */
+#define ENXIO 6 /* Device not configured */
+#define E2BIG 7 /* Argument list too long */
+#define ENOEXEC 8 /* Exec format error */
+#define EBADF 9 /* Bad file descriptor */
+#define ECHILD 10 /* No child processes */
+#define EDEADLK 11 /* Resource deadlock avoided */
+
+#define ENOMEM 12 /* Cannot allocate memory */
+#define EACCES 13 /* Permission denied */
+#define EFAULT 14 /* Bad address */
+
+#define ENOTBLK 15 /* Block device required */
+#define EBUSY 16 /* Device busy */
+#define EEXIST 17 /* File exists */
+
+#define EXDEV 18 /* Cross-device link */
+#define ENODEV 19 /* Operation not supported by device */
+#define ENOTDIR 20 /* Not a directory */
+#define EISDIR 21 /* Is a directory */
+#define EINVAL 22 /* Invalid argument */
+#define ENFILE 23 /* Too many open files in system */
+#define EMFILE 24 /* Too many open files */
+#define ENOTTY 25 /* Inappropriate ioctl for device */
+
+#endif
diff --git a/sw-old/z80/kernel/include/fs/dev.h b/sw-old/z80/kernel/include/fs/dev.h
new file mode 100644
index 0000000..8e550f3
--- /dev/null
+++ b/sw-old/z80/kernel/include/fs/dev.h
@@ -0,0 +1,29 @@
+#ifndef DEV_H
+#define DEV_H
+
+#include "types.h"
+
+#define FS_MOUNT_LIMIT 16
+
+struct fs_superblock
+{
+ uint8_t magic; // identifier
+
+ size_t blk_size; // size of a single block
+ size_t imap_size; // quantity of inodes
+ size_t dmap_size; // quantity of blocks
+};
+
+struct fs_dev
+{
+ uint enabled :1; // in use
+ uint port_no :3; // serial port number
+ uint :4;
+ inode_t inode; // dir mounted
+ struct fs_superblock superblock; // block informations
+};
+
+/* list of devices */
+extern struct fs_dev devices[FS_MOUNT_LIMIT];
+
+#endif
diff --git a/sw-old/z80/kernel/include/fs/dirent.h b/sw-old/z80/kernel/include/fs/dirent.h
new file mode 100644
index 0000000..2fd224a
--- /dev/null
+++ b/sw-old/z80/kernel/include/fs/dirent.h
@@ -0,0 +1,17 @@
+#ifndef __DIRENT_H__
+#define __DIRENT_H__
+
+#include "types.h"
+
+struct dirent
+{
+ ino_t inode; // inode referred
+ uint8_t name_size; // size of the name
+ char name[]; // name of the referred inode
+};
+
+/* if inode is FS_INO_NULL, then the dirent is a memory leak */
+/* Warning: dirent leaks are generated by rm or rmdir operations */
+/* Filesystem must be periodically checked and cleaned */
+
+#endif // __DIRENT_H__
diff --git a/sw-old/z80/kernel/include/fs/fd.h b/sw-old/z80/kernel/include/fs/fd.h
new file mode 100644
index 0000000..d2fea2a
--- /dev/null
+++ b/sw-old/z80/kernel/include/fs/fd.h
@@ -0,0 +1,102 @@
+#ifndef __FD_H__
+#define __FD_H__
+
+#include "types.h"
+
+#define FD_MAX 32
+
+#define OPEN_READ 0x1
+#define OPEN_WRITE 0x2
+#define OPEN_BIN 0x4
+#define OPEN_APPEND 0x8
+#define OPEN_ERASE 0x10
+#define OPEN_DIR 0x20
+#define OPEN_LINK 0x40
+
+#define LS_ALL 0x1
+
+/* declare dirent, not include */
+#ifndef __DIRENT_H__
+struct dirent;
+#endif
+
+/* set of operations callback for fd */
+struct fd_operations
+{
+ size_t (*readline)(inode_t, fsize_t, char *, char term);
+ size_t (*print)(inode_t, fsize_t, const char *);
+ size_t (*append)(inode_t, fsize_t*, const char *);
+
+ size_t (*read)(inode_t, fsize_t, void *, size_t);
+ size_t (*write)(inode_t, fsize_t, const void *, size_t);
+ size_t (*bin_append)(inode_t, fsize_t*, const void *, size_t);
+
+ size_t (*ls)(inode_t, struct dirent *, uint8_t);
+ size_t (*find)(inode_t, struct dirent *, const char *);
+ int8_t (*mkdir)(inode_t, const char *);
+ int8_t (*rmdir)(inode_t, const char *);
+ int8_t (*touch)(inode_t, const char *);
+ int8_t (*rm)(inode_t, const char *);
+ int8_t (*ln)(inode_t, const char *, const char *);
+
+ int8_t (*special)(inode_t, void *, size_t);
+};
+
+/* file descriptor */
+struct file_desc
+{
+ inode_t inode; // inode pointed
+ fsize_t seek; // virtual seek
+ devsize_t begin; // beginning of blocks
+ struct fd_operations opers; // bound operations
+};
+
+/* bitmap of used file descriptors */
+extern struct uint8_t fd_bmap[FD_TABLE_SIZE / 8];
+
+/* table of file descriptors */
+extern struct file_desc fd_table[FD_TABLE_SIZE];
+
+/* returns a free file descriptor */
+int8_t __fd_new();
+
+/* opens a file streaming of the cwd */
+int8_t __open_c_inode(uint8_t flags);
+
+/* opens a file streaming by a path */
+int8_t open(const char *path, uint8_t flags);
+
+/* list content of directory */
+size_t ls(int8_t fd, struct dirent *buf, uint8_t all);
+
+/* find name through the directory entries */
+size_t find(int8_t fd, struct dirent *buf, const char *name);
+
+/* creates a new directory inside fd with the specified name */
+int8_t mkdir(int8_t fd, const char *name);
+
+/* creates a new file inside fd with the specified name */
+int8_t touch(int8_t fd, const char *name);
+
+/* creates a new symlink inside fd with the specified name */
+int8_t ln(int8_t fd, const char *name);
+
+/* change virtual seek position of the fd */
+int8_t seek(int8_t fd, fsize_t pos);
+
+/* reads a string from the fd until the terminator is reached */
+size_t readline(int8_t fd, char *buf, char term);
+
+/* writes a string into the fd */
+int8_t print(int8_t fd, const char *str);
+
+/* reads n bytes from the fd */
+size_t read(int8_t fd, void *buf, size_t n);
+
+/* writes n bytes into the fd */
+int8_t write(int8_t fd, const void *buf, size_t n);
+
+/* frees fd space */
+void close(int8_t fd);
+
+#endif // __FD_H__
diff --git a/sw-old/z80/kernel/include/fs/fdop.h b/sw-old/z80/kernel/include/fs/fdop.h
new file mode 100644
index 0000000..d4b1b77
--- /dev/null
+++ b/sw-old/z80/kernel/include/fs/fdop.h
@@ -0,0 +1,140 @@
+#ifndef __FDOP_H__
+#define __FDOP_H__
+
+#include "types.h"
+
+#ifndef __DIRENT_H__
+struct dirent;
+#endif
+
+/* macro for direct binding */
+
+#define FD_BIND_AS_DIR(oper) { \
+ oper.ls = &as_ls; \
+ oper.find = &as_find; \
+ oper.mkdir = &as_mkdir; \
+ oper.rmdir = &as_rmdir; \
+ oper.touch = &as_touch; \
+ oper.rm = &as_rm; \
+ oper.ln = &as_ln; \
+ }
+
+#define FD_BIND_SS_DIR(oper) { \
+ oper.ls = &ss_ls; \
+ oper.find = &ss_find; \
+ oper.mkdir = &ss_mkdir; \
+ oper.rmdir = &ss_rmdir; \
+ oper.touch = &ss_touch; \
+ oper.rm = &ss_rm; \
+ oper.ln = &ss_ln; \
+ }
+
+#define FD_BIND_AS_FILE(opers, flags) { \
+ if (flags & OPEN_READ) \
+ opers.readline = as_readline; \
+ if (flags & OPEN_APPEND) \
+ opers.append = as_append; \
+ else if (flags & OPEN_WRITE) \
+ opers.print = as_print; \
+ }
+
+#define FD_BIND_SS_FILE(opers, flags) { \
+ if (flags & OPEN_READ) \
+ opers.readline = ss_readline; \
+ if (flags & OPEN_APPEND) \
+ opers.append = ss_append; \
+ else if (flags & OPEN_WRITE) \
+ opers.print = ss_print; \
+ }
+
+#define FD_BIND_AS_BINFILE(opers, flags) { \
+ if (flags & OPEN_READ) \
+ opers.read = as_read; \
+ if (flags & OPEN_APPEND) \
+ opers.bin_append = as_bin_append; \
+ else if (flags & OPEN_WRITE) \
+ opers.write = as_write; \
+ }
+
+#define FD_BIND_SS_BINFILE(opers, flags) { \
+ if (flags & OPEN_READ) \
+ opers.read = ss_read; \
+ if (flags & OPEN_APPEND) \
+ opers.bin_append = ss_bin_append; \
+ else if (flags & OPEN_WRITE) \
+ opers.write = ss_write; \
+ }
+
+/* Set of file descriptors operations */
+/* Determines if to use the serial interface or the address space */
+
+/* Address space section */
+
+/* File functions */
+
+size_t as_readline(inode_t inode, fsize_t seek, char *buf, char term);
+
+size_t as_print(inode_t inode, fsize_t seek, const char *str);
+
+size_t as_append(inode_t inode, fsize_t *seek_ptr, const char *str);
+
+
+size_t as_read(inode_t inode, fsize_t seek, void *buf, size_t n);
+
+size_t as_write(inode_t inode, fsize_t seek, const void *buf, size_t n);
+
+size_t as_bin_append(inode_t inode, fsize_t *seek_ptr, const void *buf, size_t
+n);
+
+/* Directory functions */
+
+size_t as_ls(inode_t inode, struct dirent *buf, uint8_t all);
+
+size_t as_find(inode_t inode, struct dirent *buf, const char *name);
+
+int8_t as_mkdir(inode_t inode, const char *name);
+
+int8_t as_rmdir(inode_t inode, const char *name);
+
+int8_t as_touch(inode_t inode, const char *name);
+
+int8_t as_rm(inode_t inode, const char *name);
+
+int8_t as_ln(inode_t inode, const char *path, const char *name);
+
+/* Serial Space section */
+/* Warning, it doesn't switch to the right driver */
+
+/* File functions */
+
+size_t ss_readline(inode_t inode, fsize_t seek, char *buf, char term);
+
+size_t ss_print(inode_t inode, fsize_t seek, const char *str);
+
+size_t ss_append(inode_t inode, fsize_t *seek_ptr, const char *str);
+
+
+size_t ss_read(inode_t inode, fsize_t seek, void *buf, size_t n);
+
+size_t ss_write(inode_t inode, fsize_t seek, const void *buf, size_t n);
+
+size_t ss_bin_append(inode_t inode, fsize_t *seek_ptr, const void *buf, size_t
+n);
+
+/* Directory functions */
+
+size_t ss_ls(inode_t inode, struct dirent *buf, uint8_t all);
+
+size_t ss_find(inode_t inode, struct dirent *buf, const char *name);
+
+int8_t ss_mkdir(inode_t inode, const char *name);
+
+int8_t ss_rmdir(inode_t inode, const char *name);
+
+int8_t ss_touch(inode_t inode, const char *name);
+
+int8_t ss_rm(inode_t inode, const char *name);
+
+int8_t ss_ln(inode_t, const char *path, const char *name);
+
+#endif // __FDOP_H__
diff --git a/sw-old/z80/kernel/include/fs/fs.h b/sw-old/z80/kernel/include/fs/fs.h
new file mode 100644
index 0000000..ad20adb
--- /dev/null
+++ b/sw-old/z80/kernel/include/fs/fs.h
@@ -0,0 +1,63 @@
+#ifndef __FS_H__
+#define __FS_H__
+
+#include "types.h"
+
+#define FS_OFFSET 0x1000
+
+#define FS_BLOCKS_SIZE 512
+#define FS_BLOCKS_N 8
+#define FS_BLOCKS_IND 6
+
+#define INODE_TYPE_FILE 0x0
+#define INODE_TYPE_DIR 0x1
+#define INODE_TYPE_SLINK 0x2
+#define INODE_TYPE_SPECIAL 0x3
+
+#define INODE_META_SIZE 8
+
+/* inode basic structure */
+struct fs_inode
+{
+ /* inode meta data */
+
+ uint mode :3; // chmod
+ uint uid :3; // chown
+ uint type :2; // file, dir, sym-link, special
+
+ time_t ctime; // creation time
+
+ uint24_t size; // inode size
+
+ /* data storage informations */
+ /* it doesn't allocate memory, virtual size FS_BLOCKS_N */
+ blk_t blocks[];
+};
+
+#define FS_DEV_ROM 0x7f /* 01111111 */
+#define FS_DEV_NULL 0x80 /* 10000000 */
+
+#define FS_ROM_SPACE 0x2000 // second rom
+
+#define FS_INO_ROOT 0x0 // first inode
+
+#define FS_INODE_ROOT(inode) {inode.dev = 0xff; inode.inode = 0x0}
+#define FS_INODE_NULL(inode) {inode.dev = 0x80; inode.inode = 0x0}
+
+#define FS_USE_ROM(inode) {inode.dev == 0x7f}
+
+/* get block seek in current device */
+devsize_t fs_block(blk_t block);
+
+/* get common inode seek in current device */
+/* c_inode must be set first */
+/* returns seek at the beginning of blocks field */
+devsize_t fs_inode(struct fs_inode *buf);
+
+/* common inode for syscalls */
+extern inode_t c_inode;
+
+/* parse a path, absolute or relative to c_inode */
+inode_t fs_parse_path(const char *path);
+
+#endif // __FS_H__
diff --git a/sw-old/z80/kernel/include/fs/iter.h b/sw-old/z80/kernel/include/fs/iter.h
new file mode 100644
index 0000000..41f011d
--- /dev/null
+++ b/sw-old/z80/kernel/include/fs/iter.h
@@ -0,0 +1,17 @@
+#ifndef __ITER_H__
+#define __ITER_H__
+
+struct inode_iter
+{
+ devsize_t dev_seek; /* seek position in the volume */
+ devsize_t blk_end; /* end of the block */
+
+ int16_t blk_index; /* index of the block */
+
+ int8_t blk_level; /* recursion level, indirect blocks */
+
+ fsize_t fseek; /* virtual seek in the file */
+ fsize_t size; /* file size */
+};
+
+#endif // __ITER_H__
diff --git a/sw-old/z80/kernel/include/fs/users.h b/sw-old/z80/kernel/include/fs/users.h
new file mode 100644
index 0000000..83980e5
--- /dev/null
+++ b/sw-old/z80/kernel/include/fs/users.h
@@ -0,0 +1,21 @@
+#ifndef USERS_H
+#define USERS_H
+
+#include "types.h"
+
+#define USERS_MAX 8
+#define USER_ROOT 0
+
+/* current user in use */
+extern struct fs_user c_user;
+
+struct fs_user
+{
+ char name[32];
+ ino_t home;
+ uint8_t perm; // TODO, permissions
+};
+
+/* all users are in rom device */
+
+#endif
diff --git a/sw-old/z80/kernel/include/memory.h b/sw-old/z80/kernel/include/memory.h
new file mode 100644
index 0000000..67c4b88
--- /dev/null
+++ b/sw-old/z80/kernel/include/memory.h
@@ -0,0 +1,50 @@
+#ifndef __MEMORY_H__
+#define __MEMORY_H__
+
+#include "types.h"
+#include "devices.h"
+
+/* maximum number of pages on the system */
+#define PAGES_MAX_COUNT 32
+#define PAGE_SIZE 1000
+
+/* in our system there are only 16 pages since only 64KB can be addressed
+ * to optimize the memory management in ROM and RAM only pages from this set
+ * shall be used
+ */
+// ROM
+#define ADDR_PAGE_0 0x0000
+#define ADDR_PAGE_1 0x1000
+#define ADDR_PAGE_2 0x2000
+#define ADDR_PAGE_3 0x3000
+// IOSPACE
+#define ADDR_PAGE_4 0x4000
+#define ADDR_PAGE_5 0x5000
+#define ADDR_PAGE_6 0x6000
+#define ADDR_PAGE_7 0x7000
+// RAM
+#define ADDR_PAGE_8 0x8000
+#define ADDR_PAGE_9 0x9000
+#define ADDR_PAGE_10 0xA000
+#define ADDR_PAGE_11 0xB000
+#define ADDR_PAGE_12 0xC000
+#define ADDR_PAGE_13 0xD000
+#define ADDR_PAGE_14 0xE000
+#define ADDR_PAGE_15 0xF000
+
+#define ADDR_PAGE_FIRST ADDR_PAGE_8
+#define ADDR_PAGE_LAST ADDR_PAGE_15
+
+struct page
+{
+ pid_t pid; // process owner of the page (0 if free)
+ uint16_t addr; // physical address
+};
+
+int mmu_write_table(void);
+
+int page_new(void);
+int page_map(int page, int pid, uint16_t addr);
+int page_unmap(int page);
+
+#endif // __MEMORY_H__
diff --git a/sw-old/z80/kernel/include/process.h b/sw-old/z80/kernel/include/process.h
new file mode 100644
index 0000000..3b0c843
--- /dev/null
+++ b/sw-old/z80/kernel/include/process.h
@@ -0,0 +1,43 @@
+#ifndef __PROCESS_H__
+#define __PROCESS_H__
+
+#include "types.h"
+#include "memory.h"
+
+ /* maximum number of processes (i.e. pages in ram)
+ * since each program can use only one page in ram
+ */
+#define PROC_COUNT 2
+
+/* the pid is defined with a single byte (pid_t is uint8_t), because of that
+ * there cannot be more than 255 processes open at the same time. this is a
+ * limitation but for our purposes is more than enough
+ */
+#define PID_COUNT_MAX 255
+
+struct executable
+{
+ void *text;
+ size_t text_size;
+ void *bss;
+ size_t bss_size;
+};
+
+struct process
+{
+ uint blocked :1; // process is waiting for hardware or locked
+ uint running :1; // pid is used
+ uint pages; // number of pages used by the process
+ struct page page[4]; // pages used by the process
+};
+
+pid_t newpid(void);
+
+int fork(void);
+int exec(char *path, char *args);
+int spawn(char *path, char *args);
+
+pid_t getpid(void);
+int kill(pid_t pid);
+
+#endif // __PROCESS_H__
diff --git a/sw-old/z80/kernel/include/sio.h b/sw-old/z80/kernel/include/sio.h
new file mode 100644
index 0000000..276b99c
--- /dev/null
+++ b/sw-old/z80/kernel/include/sio.h
@@ -0,0 +1,43 @@
+#ifndef __SIO_H__
+#define __SIO_H__
+
+#include "types.h"
+
+#define SIO_PORT_0 0x0
+#define SIO_PORT_1 0x1
+#define SIO_PORT_2 0x2
+#define SIO_PORT_3 0x3
+#define SIO_PORT_4 0x4
+#define SIO_PORT_5 0x5
+#define SIO_PORT_6 0x6
+#define SIO_PORT_7 0x7
+
+/* current port in use */
+extern uint8_t sio_port;
+
+/* current seek in the device */
+extern devsize_t sio_seek;
+
+struct dev_buffer
+{
+ // TODO, bytes needed to the device buffer interface
+};
+
+/* points to the buffers mapped in the I/O space */
+/* to be defined precisely in assembly */
+extern volatile struct dev_buffer sio_buffers[8];
+
+/* initialize serial interface */
+void sio_init();
+
+/* syscall: read one byte from the current device */
+uint8_t sio_recv();
+/* syscall: write one byte into the current device */
+void sio_send(uint8_t value);
+
+/* read n bytes from the current port */
+size_t sio_read(void *buffer, size_t n);
+/* write n bytes into the current port */
+int8_t sio_write(const void *buffer, size_t n);
+
+#endif // __SIO_H__
diff --git a/sw-old/z80/kernel/include/stat.h b/sw-old/z80/kernel/include/stat.h
new file mode 100644
index 0000000..44c0f63
--- /dev/null
+++ b/sw-old/z80/kernel/include/stat.h
@@ -0,0 +1,24 @@
+#ifndef __STAT_H__
+#define __STAT_H__
+
+#include "types.h"
+
+struct stat
+{
+ inode_t inode; /* inode reference */
+
+ uint mode :3; /* mode */
+ uint uid :3; /* owner id */
+ uint type :2; /* file, dir or link */
+
+ devsize_t size; /* file size */
+
+ size_t blk_size; /* single block size */
+ size_t blk_used; /* blocks used by the file */
+
+ time_t ctime; /* creation time */
+}
+
+struct stat * stat(const char *path, struct stat *buffer);
+
+#endif // __STAT_H__
diff --git a/sw-old/z80/kernel/include/types.h b/sw-old/z80/kernel/include/types.h
new file mode 100644
index 0000000..c6e620b
--- /dev/null
+++ b/sw-old/z80/kernel/include/types.h
@@ -0,0 +1,62 @@
+#ifndef __TYPES_H__
+#define __TYPES_H__
+
+/* only types from primitive types are defined in this file */
+
+typedef volatile unsigned char register_t;
+
+typedef unsigned int uint;
+
+typedef char int8_t;
+typedef unsigned char uint8_t;
+typedef int int16_t;
+typedef unsigned int uint16_t;
+typedef long int int32_t;
+typedef unsigned long int uint32_t;
+
+typedef uint16_t size_t;
+typedef int16_t ssize_t;
+
+typedef uint8_t pid_t;
+typedef uint16_t ino_t;
+
+typedef uint8_t dev_t;
+typedef uint32_t devsize_t;
+typedef uint8_t fd_t;
+typedef uint16_t blk_t;
+typedef uint8_t user_t;
+
+typedef struct {
+ uint8_t member[3];
+
+} uint24_t;
+
+typedef uint32_t fsize_t;
+
+typedef struct
+{
+ dev_t dev; // device id, global in the fs
+ ino_t inode; // inode id relative to the volume
+
+} inode_t;
+
+typedef struct time_s
+{
+ struct
+ {
+ uint minutes :6;
+ uint hour :5;
+
+ } time;
+
+ struct
+ {
+ uint day :5;
+ uint month :4;
+ uint year :12;
+
+ } date;
+
+} time_t;
+
+#endif
diff --git a/sw-old/z80/kernel/kernel.c b/sw-old/z80/kernel/kernel.c
new file mode 100644
index 0000000..3d5aeb6
--- /dev/null
+++ b/sw-old/z80/kernel/kernel.c
@@ -0,0 +1,7 @@
+#include "types.h"
+#include "usart.h"
+
+void kmain(void)
+{
+ usart_init(USART_BAUDRATE_9600, USART_PARITY_EVEN, USART_STOP_BITS_1);
+}
diff --git a/sw-old/z80/kernel/makefile b/sw-old/z80/kernel/makefile
new file mode 100644
index 0000000..be8eed4
--- /dev/null
+++ b/sw-old/z80/kernel/makefile
@@ -0,0 +1,53 @@
+####
+# source code settings
+#
+OSNAME := helvetiOS
+
+CSOURCES := $(wildcard *.c) \
+ $(wildcard drivers/*.c)
+
+OBJECTS := $(patsubst %.c,build/%.rel,$(CSOURCES))
+HEXFILE := build/$(OSNAME).hex
+BINARY := build/$(OSNAME).bin
+
+###
+# compiler settings
+
+CC := sdcc
+
+CFLAGS := -mz80 \
+ -I include \
+ -I include/drivers \
+ -I libc/include \
+ --opt-code-size \
+ -DDEBUG
+
+LDFLAGS := -mz80 --no-std-crt0 build/crt0.rel \
+ --std-c89 -pedantic \
+ --code-loc 0x0800 --data-loc 0x8000
+
+.PHONY: dirs dis clean
+all: $(BINARY)
+
+# build binary
+$(BINARY): $(OBJECTS) dirs
+ $(CC) $(LDFLAGS) $(OBJECTS) -o $(HEXFILE)
+ makebin -s 16384 $(HEXFILE) $(BINARY)
+
+$(OBJECTS): build/%.rel : %.c $(CSOURCES) dirs build/crt0.rel
+ @printf "\n"
+ $(CC) $(CFLAGS) -c $< -o $@
+
+build/crt0.rel: crt0.s
+ sdasz80 -o $<
+ @mv crt0.rel build
+
+dirs:
+ mkdir -p build build/kernel build/libc build/kernel/drivers
+
+dis: $(BINARY)
+ dz80 -b -n $<
+
+clean:
+ - rm -rd build/*
+ - rm crt0.rel
diff --git a/sw-old/z80/kernel/memory.c b/sw-old/z80/kernel/memory.c
new file mode 100644
index 0000000..1b2cc76
--- /dev/null
+++ b/sw-old/z80/kernel/memory.c
@@ -0,0 +1,94 @@
+#include "memory.h"
+
+static struct page pages_table[PAGES_MAX_COUNT];
+
+int mmu_write_table(void)
+{
+ int i;
+
+ for (i = 0; i < PAGES_MAX_COUNT; i++) {
+ if (pages_table[i].pid != 0) {
+ // write to mmu table
+ }
+ }
+
+ return 0;
+}
+
+int page_new(void)
+{
+ int i, used;
+ uint16_t addr;
+
+ for (addr = ADDR_PAGE_FIRST; addr < ADDR_PAGE_LAST; addr += PAGE_SIZE) {
+ used = 0;
+
+ for (i = 0; i < PAGES_MAX_COUNT; i++) {
+ if (pages_table[i].addr == addr) {
+ used = 1;
+ break;
+ }
+ }
+
+ if (!used)
+ return i;
+ }
+
+ return -1;
+}
+
+int page_map(int page, int pid, uint16_t addr)
+{
+ if (page >= PAGES_MAX_COUNT)
+ return -1;
+
+ if (pages_table[page].pid != 0)
+ return -2;
+
+ pages_table[page].addr = addr;
+ pages_table[page].pid = pid;
+
+ return 0;
+}
+
+int page_unmap(int page)
+{
+ if (page >= PAGES_MAX_COUNT)
+ return -1;
+
+ if (pages_table[page].pid == 0)
+ return -2;
+
+ pages_table[page].pid = 0;
+ pages_table[page].addr = 0;
+ return 0;
+}
+
+/* k_malloc manager */
+/*
+struct k_buf_entry k_buf_table[K_BUF_MAX_COUNT];
+
+struct k_buf k_buffers[K_BUF_MAX_COUNT];
+
+void * k_malloc()
+{
+ for (uint8_t i = 0; i < K_BUF_TABLE_COUNT; i++)
+ {
+ for (uint8_t bit = 0x80, j = 0; j < 8; bit >>= 1, j++)
+ {
+ if (bit & k_buf_table[i])
+ {
+ k_buf_table[i] |= bit;
+ return &k_buffers[8 * i + j];
+ }
+ }
+ }
+}
+
+void k_free(void * ptr)
+{
+ uint8_t index = (ptr - &k_buffers[0]) / K_BUF_SIZE;
+
+ if (index < K_BUF_MAX_COUNT)
+ k_buf_table[index / 8] ^= 0x80 >> index % 8;
+}*/
diff --git a/sw-old/z80/kernel/process.c b/sw-old/z80/kernel/process.c
new file mode 100644
index 0000000..7d8db89
--- /dev/null
+++ b/sw-old/z80/kernel/process.c
@@ -0,0 +1,58 @@
+#include "process.h"
+
+static struct process proc_table[PID_COUNT_MAX];
+static struct process *current_proc;
+
+pid_t newpid(void)
+{
+ int i;
+ static pid_t last_pid = 0;
+
+ for (i = 0; i < PID_COUNT_MAX; i++, last_pid++) {
+ if (last_pid == PID_COUNT_MAX) {
+ last_pid = 0;
+ continue;
+ }
+
+ if (!proc_table[last_pid].running)
+ break;
+ }
+
+ if (i >= PID_COUNT_MAX)
+ return 0;
+
+ return last_pid;
+}
+
+int fork(void)
+{
+ int i, p;
+ pid_t child_pid = newpid();
+
+ if (child_pid == 0)
+ return -1;
+
+
+ for (i = 0; i < current_proc->pages; i++) {
+ p = page_new();
+
+ if (p == -1) {
+ return -2;
+ }
+
+ // TODO: use memcpy()
+ // SDCC does not allow assignemnts of structs
+
+ // proc_table[child_pid].page[i] = p;
+ }
+}
+
+int exec(char *path, char *args)
+{
+
+}
+
+int spawn(char *path, char *args)
+{
+
+}