CDSRCS = start.c
C1SRCS = version.c filesys.c devio.c kdata.c
C1SRCS += inode.c tty.c
+C2SRCS = syscall_proc.c process.c malloc.c
+C2SRCS += simple.c single.c bank16k.c bank16k_low.c bank32k.c bankfixed.c flat.c
#
-# Keep all of the syscalls in C2SRCS
+# Usually we map sysalls into CODE2 but they can be overlaid
+#
+CS1SRCS = syscall_fs.c
+CS2SRCS = syscall_fs2.c
+CS3SRCS = syscall_fs3.c
+CS4SRCS = syscall_other.c
+CS5SRCS = syscall_exec$(BITS).c
#
-C2SRCS = syscall_proc.c syscall_fs.c
-C2SRCS += syscall_fs2.c syscall_other.c syscall_exec$(BITS).c process.c malloc.c
-C2SRCS += simple.c single.c bank16k.c bank16k_low.c bank32k.c bankfixed.c flat.c
#
# Drop some bits into CODE3 so the 6502 banks fit nicely. May well
# need to do this on Z80 as well
C1OBJS = $(C1SRCS:.c=$(BINEXT))
C2OBJS = $(C2SRCS:.c=$(BINEXT))
C3OBJS = $(C3SRCS:.c=$(BINEXT))
+
+CS1OBJS = $(CS1SRCS:.c=$(BINEXT))
+CS2OBJS = $(CS2SRCS:.c=$(BINEXT))
+CS3OBJS = $(CS3SRCS:.c=$(BINEXT))
+CS4OBJS = $(CS4SRCS:.c=$(BINEXT))
+CS5OBJS = $(CS5SRCS:.c=$(BINEXT))
+
CFONTOBJS = $(CFONTSRCS:.c=$(BINEXT))
CVIDEOOBJS = $(CVIDEOSRCS:.c=$(BINEXT))
AOBJS = $(ASRCS:$(ASMEXT)=$(BINEXT))
-CSRCS = $(CDSRCS) $(C1SRCS) $(C2SRCS) $(C3SRCS) $(CFONTSRCS) $(CVIDEOSRCS)
-COBJS = $(CDOBJS) $(C1OBJS) $(C2OBJS) $(C3OBJS) $(CFONTOBJS) $(CVIDEOOBJS)
+CSSRCS = $(CS1SRCS) $(CS2SRCS) $(CS3SRCS) $(CS4SRCS) $(CS5SRCS)
+CSOBJS = $(CS1OBJS) $(CS2OBJS) $(CS3OBJS) $(CS4OBJS) $(CS5OBJS)
+
+CSRCS = $(CDSRCS) $(C1SRCS) $(C2SRCS) $(C3SRCS) $(CFONTSRCS) $(CVIDEOSRCS) $(CSSRCS)
+COBJS = $(CDOBJS) $(C1OBJS) $(C2OBJS) $(C3OBJS) $(CFONTOBJS) $(CVIDEOOBJS) $(CSOBJS)
OBJS = $(COBJS) $(AOBJS)
$(CVIDEOOBJS): %$(BINEXT): %.c
$(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_VIDEO) $<
+$(CS1OBJS): %$(BINEXT): %.c
+ $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SYS1) $<
+
+$(CS2OBJS): %$(BINEXT): %.c
+ $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SYS2) $<
+
+$(CS3OBJS): %$(BINEXT): %.c
+ $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SYS3) $<
+
+$(CS4OBJS): %$(BINEXT): %.c
+ $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SYS4) $<
+
+$(CS5OBJS): %$(BINEXT): %.c
+ $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SYS5) $<
+
$(AOBJS): %$(BINEXT): %$(ASMEXT)
$(CROSS_AS) $(ASOPTS) -o $*$(BINEXT) $<
export CROSS_CC_SEG3=-mcode-section=.text2 -mfar-code-page=2
export CROSS_CC_SEGDISC=-mcode-section=.discard -mdata-section=.discard -mfar-code-page=3
export CROSS_CC_VIDEO=-mcode-section=.video -mdata-section=.videodata -mfar-code-page=4
+export CROSS_CC_SYS1=-mcode-section=.text2 -mfar-code-page=2
+export CROSS_CC_SYS2=-mcode-section=.text2 -mfar-code-page=2
+export CROSS_CC_SYS3=-mcode-section=.text2 -mfar-code-page=2
+export CROSS_CC_SYS4=-mcode-section=.text2 -mfar-code-page=2
+export CROSS_CC_SYS5=-mcode-section=.text2 -mfar-code-page=2
export ASOPTS=
export ASMEXT = .s
export BINEXT = .o
export CROSS_CC_SEGDISC=--codeseg DISCARD --constseg DISCARD
export CROSS_CC_FONT=--constseg FONT
export CROSS_CC_VIDEO=--codeseg VIDEO
+export CROSS_CC_SYS1=--codeseg CODE2
+export CROSS_CC_SYS2=--codeseg CODE2
+export CROSS_CC_SYS3=--codeseg CODE2
+export CROSS_CC_SYS4=--codeseg CODE2
+export CROSS_CC_SYS5=--codeseg CODE2
export ASOPTS=-plosff
export ASMEXT = .s
export BINEXT = .rel
../devio.o ../filesys.o ../process.o ../inode.o ../syscall_fs.o \
../syscall_proc.o ../syscall_other.o ../mm.o ../swap.o \
../tty.o ../devsys.o ../usermem.o ../syscall_fs2.o ../syscall_exec16.o \
- devtty.o libc.o ../vt.o
+ devtty.o libc.o ../vt.o ../syscall_fs3.o
../tools/decb-image <../fuzix.bin fuzix.img
# Repack the high 4K where the loader wants it
dd if=fuzix.img of=fuzix.tmp bs=1024 skip=60
../devio.o ../filesys.o ../process.o ../inode.o ../syscall_fs.o \
../syscall_proc.o ../syscall_other.o ../mm.o ../bank16k.o ../swap.o \
../tty.o ../devsys.o ../usermem.o ../syscall_fs2.o ../syscall_exec16.o \
+ ../syscall_fs3.o \
../usermem_std-6809.o devtty.o libc.o ../vt.o usermem_gime.o video.o \
videoll.o
../devio.o ../filesys.o ../process.o ../inode.o ../syscall_fs.o \
../syscall_proc.o ../syscall_other.o ../mm.o ../swap.o \
../tty.o ../devsys.o ../usermem.o ../syscall_fs2.o ../syscall_exec16.o \
+ ../syscall_fs3.o \
devlpr.o devtty.o libc.o ../vt.o video.o ../font8x8.o \
devide.o blkdev.o ide.o devide_discard.o mbr.o \
devsd.o devsd_discard.o spi.o devscsi.o devscsi_discard.o \
/* Banks as reported to user space */
#define CONFIG_BANKS 1
+#define PTABSIZE 8
#define TICKSPERSEC 100 /* Ticks per second */
#define PROGBASE 0x0000 /* also data base */
#define PROGLOAD 0x0100
-#define PROGTOP 0x6000 /* Top of program, base of U_DATA */
+#define PROGTOP 0x7E00 /* Top of program, base of U_DATA */
#define PROC_SIZE 32 /* Memory needed per process */
#define SWAP_SIZE 0x40 /* 32K in blocks (we actually don't need the low 256) */
#define SWAPBASE 0x0000 /* We swap the lot in one, include the */
#define SWAPTOP 0x8000 /* vectors so its a round number of sectors */
-#define MAX_SWAPS 64 /* The full drive would actually be 170! */
+#define MAX_SWAPS PTABSIZE /* The full drive would actually be 170! */
#define swap_map(x) ((uint8_t *)(x)) /* Simple zero based mapping */
#define BOOT_TTY (512 + 1)/* Set this to default device for stdio, stderr */
-; 2013-12-18 William R Sowerbutts
-
- .module crt0
-
; Ordering of segments for the linker.
; WRS: Note we list all our segments here, even though
; we don't use them all, because their ordering is set
; when they are first seen.
+ .area _CODE6 ; overlaid by 3 4 5 (which are smaller)
.area _CODE
.area _CODE2
.area _CONST
.area _DISCARD
.area _UDATA
+ .module crt0
+
+
; imported symbols
.globl _fuzix_main
.globl init_early
-mwxuy
-i fuzix.ihx
+-b _CODE=0xC000
-b _DISCARD=0x5000
--b _UDATA=0x6000
--b _CODE=0x6300
+-b _UDATA=0x7E00
+-b _CODE6=0x8000
+-b _CODE3=0x8000
+-b _CODE4=0x8000
+-b _CODE5=0x8000
+-b _CODE7=0x8000
-l z80
platform-micropack/crt0.rel
platform-micropack/commonmem.rel
syscall_exec16.rel
syscall_fs.rel
syscall_fs2.rel
+syscall_fs3.rel
syscall_proc.rel
syscall_other.rel
tty.rel
; UZI mnemonics for memory addresses etc
-U_DATA .equ 0x6000 ; (this is struct u_data from kernel.h)
+U_DATA .equ 0x8200 ; (this is struct u_data from kernel.h)
U_DATA__TOTALSIZE .equ 0x300 ; 256+256+256 bytes.
Z80_TYPE .equ 0
# Use RST8 for call preamble
#
CROSS_CCOPTS += --peep-file $(ROOT_DIR)/cpu-z80/rst8.peep
-
+export CROSS_CC_SYS1=--codeseg CODE3
+export CROSS_CC_SYS2=--codeseg CODE4
+export CROSS_CC_SYS3=--codeseg CODE5
+export CROSS_CC_SYS4=--codeseg CODE6
+export CROSS_CC_SYS5=--codeseg CODE7
syscall_exec16.rel
syscall_fs.rel
syscall_fs2.rel
+syscall_fs3.rel
syscall_proc.rel
syscall_other.rel
mm.rel
syscall_exec16.rel
syscall_fs.rel
syscall_fs2.rel
+syscall_fs3.rel
syscall_proc.rel
syscall_other.rel
mm.rel
syscall_exec16.rel
syscall_fs.rel
syscall_fs2.rel
+syscall_fs3.rel
syscall_proc.rel
syscall_other.rel
tty.rel
syscall_exec16.rel
syscall_fs.rel
syscall_fs2.rel
+syscall_fs3.rel
syscall_proc.rel
syscall_other.rel
tty.rel
syscall_fs.rel
syscall_proc.rel
syscall_fs2.rel
+syscall_fs3.rel
syscall_other.rel
mm.rel
swap.rel
syscall_exec16.rel
syscall_fs.rel
syscall_fs2.rel
+syscall_fs3.rel
syscall_proc.rel
syscall_other.rel
tty.rel
syscall_exec16.rel
syscall_fs.rel
syscall_fs2.rel
+syscall_fs3.rel
syscall_proc.rel
syscall_other.rel
tty.rel
syscall_exec16.rel
syscall_fs.rel
syscall_fs2.rel
+syscall_fs3.rel
syscall_proc.rel
syscall_other.rel
tty.rel
syscall_exec16.rel
syscall_fs.rel
syscall_fs2.rel
+syscall_fs3.rel
syscall_proc.rel
syscall_other.rel
tty.rel
syscall_exec16.rel
syscall_fs.rel
syscall_fs2.rel
+syscall_fs3.rel
syscall_proc.rel
syscall_other.rel
tty.rel
syscall_exec16.rel
syscall_fs.rel
syscall_fs2.rel
+syscall_fs3.rel
syscall_proc.rel
syscall_other.rel
tty.rel
syscall_exec16.rel
syscall_fs.rel
syscall_fs2.rel
+syscall_fs3.rel
syscall_proc.rel
syscall_other.rel
tty.rel
syscall_exec16.rel
syscall_fs.rel
syscall_fs2.rel
+syscall_fs3.rel
syscall_proc.rel
syscall_other.rel
tty.rel
syscall_exec16.rel
syscall_fs.rel
syscall_fs2.rel
+syscall_fs3.rel
syscall_proc.rel
syscall_other.rel
tty.rel
syscall_fs.rel
syscall_proc.rel
syscall_fs2.rel
+syscall_fs3.rel
syscall_other.rel
mm.rel
swap.rel
syscall_exec16.rel
syscall_fs.rel
syscall_fs2.rel
+syscall_fs3.rel
syscall_proc.rel
syscall_other.rel
tty.rel
#undef dev
#undef buf
-
-/*******************************************
-open (name, flag, mode) Function 1
-char *name;
-int16_t flag;
-int16_t mode;
-********************************************/
-#define name (char *)udata.u_argn
-#define flag (uint16_t)udata.u_argn1
-#define mode (uint16_t)udata.u_argn2
-
-arg_t _open(void)
-{
- int8_t uindex;
- int8_t oftindex;
- staticfast inoptr ino;
- int16_t perm;
- staticfast inoptr parent;
- char fname[FILENAME_LEN + 1];
- int trunc;
- int r;
- int w;
- int j;
-
- parent = NULLINODE;
-
- trunc = flag & O_TRUNC;
- r = (flag + 1) & 1;
- w = (flag + 1) & 2;
-
- if (O_ACCMODE(flag) == 3 || (flag & O_BADBITS)) {
- udata.u_error = EINVAL;
- return (-1);
- }
- if ((uindex = uf_alloc()) == -1)
- return (-1);
-
- if ((oftindex = oft_alloc()) == -1)
- goto nooft;
-
- ino = n_open(name, &parent);
- if (ino) {
- i_deref(parent);
- /* O_EXCL test */
- if ((flag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) {
- udata.u_error = EEXIST;
- goto idrop;
- }
- } else {
- /* The n_open failed */
- if (udata.u_error == EFAULT)
- goto cantopen;
- /* New file */
- if (!(flag & O_CREAT)) {
- udata.u_error = ENOENT;
- goto cantopen;
- }
- filename(name, fname);
- /* newfile drops parent for us */
- if (parent && (ino = newfile(parent, fname))) {
- ino->c_node.i_mode =
- (F_REG | (mode & MODE_MASK & ~udata.u_mask));
- setftime(ino, A_TIME | M_TIME | C_TIME);
- wr_inode(ino);
- } else {
- udata.u_error = ENFILE; /* FIXME, should be set in newfile
- not bodged to a guessed code */
- goto cantopen;
- }
- }
- /* Book our slot in case we block opening a device */
- of_tab[oftindex].o_inode = ino;
-
- perm = getperm(ino);
- if ((r && !(perm & OTH_RD)) || (w && !(perm & OTH_WR))) {
- udata.u_error = EACCES;
- goto cantopen;
- }
- if (w) {
- if (getmode(ino) == F_DIR ) {
- udata.u_error = EISDIR;
- goto cantopen;
- }
- if (ino->c_flags & CRDONLY) {
- udata.u_error = EROFS;
- goto cantopen;
- }
- }
-
- if (isdevice(ino)) {
- inoptr *iptr = &of_tab[oftindex].o_inode;
- /* d_open may block and thus ino may become invalid as may
- parent (but we don't need it again). It may also be changed
- by the call to dev_openi */
-
- if (dev_openi(iptr, flag) != 0)
- goto cantopen;
-
- /* May have changed */
- /* get the static pointer back in case it changed via dev
- usage or just because we blocked */
- ino = *iptr;
- }
-
- if (trunc && getmode(ino) == F_REG) {
- if (f_trunc(ino))
- goto idrop;
- for (j = 0; j < OFTSIZE; ++j)
- /* Arguably should fix at read/write */
- if (of_tab[j].o_inode == ino)
- of_tab[j].o_ptr = 0;
- }
-
- udata.u_files[uindex] = oftindex;
-
- of_tab[oftindex].o_ptr = 0;
- of_tab[oftindex].o_access = flag; /* Save the low bits only */
- if (flag & O_CLOEXEC)
- udata.u_cloexec |= (1 << oftindex);
- /* FIXME: ATIME ? */
-
-/*
- * Sleep process if no writer or reader
- */
- if (getmode(ino) == F_PIPE && of_tab[oftindex].o_refs == 1
- && !(flag & O_NDELAY))
- psleep(ino);
-
- /* From the moment of the psleep ino is invalid */
-
- return (uindex);
- idrop:
- i_deref(ino);
- cantopen:
- oft_deref(oftindex); /* This will call i_deref() */
- nooft:
- udata.u_files[uindex] = NO_FILE;
- return (-1);
-}
-
-#undef name
-#undef flag
-#undef mode
-
-
-
-/*******************************************
-link (name1, name2) Function 5
-char *name1;
-char *name2;
-********************************************/
-#define name1 (char *)udata.u_argn
-#define name2 (char *)udata.u_argn1
-
-arg_t _link(void)
-{
- inoptr ino;
- inoptr ino2;
- inoptr parent2;
- char fname[FILENAME_LEN + 1];
-
- if (!(ino = n_open(name1, NULLINOPTR)))
- return (-1);
-
- if (getmode(ino) == F_DIR && esuper())
- goto nogood;
-
- if (ino->c_node.i_nlink == 0xFFFF) {
- udata.u_error = EMLINK;
- goto nogood;
- }
-
- /* Make sure file2 doesn't exist, and get its parent */
- if ((ino2 = n_open(name2, &parent2)) != NULL) {
- i_deref(ino2);
- i_deref(parent2);
- udata.u_error = EEXIST;
- goto nogood;
- }
-
- if (!parent2)
- goto nogood;
-
- if (ino->c_dev != parent2->c_dev) {
- i_deref(parent2);
- udata.u_error = EXDEV;
- goto nogood;
- }
-
- filename(name2, fname);
-
- if (!ch_link(parent2, "", fname, ino)) {
- i_deref(parent2);
- goto nogood;
- }
-
- /* Update the link count. */
- ++ino->c_node.i_nlink;
- wr_inode(ino);
- setftime(ino, C_TIME);
-
- i_deref(parent2);
- i_deref(ino);
- return 0;
-
- nogood:
- i_deref(ino);
- return -1;
-}
-
-#undef name1
-#undef name2
-
-
-/*******************************************
- fcntl (fd, request, data) Function 47
- int fd;
- int request;
- char *data;
- ********************************************/
-#define fd (int)udata.u_argn
-#define request (int)udata.u_argn1
-#define data (int)udata.u_argn2
-
-arg_t _fcntl(void)
-{
- uint8_t *acc;
- int newd;
-
- if (getinode(fd) == NULLINODE)
- return (-1);
-
- acc = &of_tab[udata.u_files[fd]].o_access;
- switch (request) {
- case F_SETFL:
- *acc =
- (*acc & ~(O_APPEND | O_NDELAY)) | (data &
- (O_APPEND |
- O_NDELAY));
- return 0;
- case F_GETFL:
- return data;
- case F_GETFD:
- return udata.u_cloexec & (1 << fd) ? O_CLOEXEC : 0;
- case F_SETFD:
- if (data & O_CLOEXEC)
- udata.u_cloexec |= (1 << fd);
- else
- udata.u_cloexec &= (1 << fd);
- return 0;
- case F_DUPFD:
- if ((newd = uf_alloc_n(data)) == -1)
- return (-1);
- udata.u_files[newd] = udata.u_files[fd];
- ++of_tab[udata.u_files[fd]].o_refs;
- return 0;
- default:
- udata.u_error = EINVAL;
- return -1;
- }
-}
-
-#undef fd
-#undef request
-#undef data
-
-/*******************************************
-uname (buf, len) Function 54
-char *buf;
-uint16_t len;
-
-We pass a set of \0 terminated strings, don't bother
-with node name. Rest is up to the libc.
-********************************************/
-
-#define buf (char *)udata.u_argn
-#define len (uint16_t)udata.u_argn1
-
-arg_t _uname(void)
-{
- uint16_t size = sizeof(sysinfo) + uname_len;
- if (size > len)
- size = len;
- sysinfo.memk = procmem;
- sysinfo.usedk = pagemap_mem_used();
- sysinfo.nproc = PTABSIZE;
- sysinfo.ticks = ticks_per_dsecond * 10;
- sysinfo.loadavg[0] = loadavg[0].average;
- sysinfo.loadavg[1] = loadavg[1].average;
- sysinfo.loadavg[2] = loadavg[2].average;
- uput(&sysinfo, buf, size);
- return size;
-}
-
-#undef buf
-
-/**************************************
-flock(fd, lockop) Function 60
-int file;
-int lockop;
-
-Perform locking upon a file.
-**************************************/
-
-#define file (uint16_t)udata.u_argn
-#define lockop (uint16_t)udata.u_argn1
-
-arg_t _flock(void)
-{
- inoptr ino;
- struct oft *o;
- staticfast uint8_t c;
- staticfast uint8_t lock;
- staticfast int self;
-
- lock = lockop & ~LOCK_NB;
- self = 0;
-
- if (lock > LOCK_UN) {
- udata.u_error = EINVAL;
- return -1;
- }
-
- if ((ino = getinode(file)) == NULLINODE)
- return -1;
- o = &of_tab[udata.u_files[file]];
-
- c = ino->c_flags & CFLOCK;
-
- /* Upgrades and downgrades. Check if we are in fact doing a no-op */
- if (o->o_access & O_FLOCK) {
- self = 1;
- /* Shared or exclusive to shared can't block and is easy */
- if (lock == LOCK_SH) {
- if (c == CFLEX)
- c = 1;
- goto done;
- }
- /* Exclusive to exclusive - no op */
- if (c == CFLEX && lock == LOCK_EX)
- return 0;
- /* Shared to exclusive - handle via the loop */
- }
-
-
- /* Unlock - drop the locks, mark us not a lock holder. Doesn't block */
- if (lockop == LOCK_UN) {
- o->o_access &= ~O_FLOCK;
- deflock(o);
- return 0;
- }
-
- do {
- /* Exclusive lock must have no holders */
- if (c == self && lock == LOCK_EX) {
- c = CFLEX;
- goto done;
- }
- if (c < CFMAX) {
- c++;
- goto done;
- }
- if (c == CFMAX) {
- udata.u_error = ENOLCK;
- return -1;
- }
- /* LOCK_NB is defined as O_NDELAY... */
- if (psleep_flags(&ino->c_flags, (lockop & LOCK_NB)))
- return -1;
- /* locks will hopefully have changed .. */
- c = ino->c_flags & CFLOCK;
- } while (1);
-
-done:
- if (o->o_access & O_FLOCK)
- deflock(o);
- ino->c_flags &= ~CFLOCK;
- ino->c_flags |= c;
- o->o_access |= O_FLOCK;
- wakeup(&ino->c_flags);
- return 0;
-}
-
-
-#undef file
-#undef lockop
--- /dev/null
+#include <kernel.h>
+#include <version.h>
+#include <kdata.h>
+#include <printf.h>
+
+
+/*******************************************
+open (name, flag, mode) Function 1
+char *name;
+int16_t flag;
+int16_t mode;
+********************************************/
+#define name (char *)udata.u_argn
+#define flag (uint16_t)udata.u_argn1
+#define mode (uint16_t)udata.u_argn2
+
+arg_t _open(void)
+{
+ int8_t uindex;
+ int8_t oftindex;
+ staticfast inoptr ino;
+ int16_t perm;
+ staticfast inoptr parent;
+ char fname[FILENAME_LEN + 1];
+ int trunc;
+ int r;
+ int w;
+ int j;
+
+ parent = NULLINODE;
+
+ trunc = flag & O_TRUNC;
+ r = (flag + 1) & 1;
+ w = (flag + 1) & 2;
+
+ if (O_ACCMODE(flag) == 3 || (flag & O_BADBITS)) {
+ udata.u_error = EINVAL;
+ return (-1);
+ }
+ if ((uindex = uf_alloc()) == -1)
+ return (-1);
+
+ if ((oftindex = oft_alloc()) == -1)
+ goto nooft;
+
+ ino = n_open(name, &parent);
+ if (ino) {
+ i_deref(parent);
+ /* O_EXCL test */
+ if ((flag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) {
+ udata.u_error = EEXIST;
+ goto idrop;
+ }
+ } else {
+ /* The n_open failed */
+ if (udata.u_error == EFAULT)
+ goto cantopen;
+ /* New file */
+ if (!(flag & O_CREAT)) {
+ udata.u_error = ENOENT;
+ goto cantopen;
+ }
+ filename(name, fname);
+ /* newfile drops parent for us */
+ if (parent && (ino = newfile(parent, fname))) {
+ ino->c_node.i_mode =
+ (F_REG | (mode & MODE_MASK & ~udata.u_mask));
+ setftime(ino, A_TIME | M_TIME | C_TIME);
+ wr_inode(ino);
+ } else {
+ udata.u_error = ENFILE; /* FIXME, should be set in newfile
+ not bodged to a guessed code */
+ goto cantopen;
+ }
+ }
+ /* Book our slot in case we block opening a device */
+ of_tab[oftindex].o_inode = ino;
+
+ perm = getperm(ino);
+ if ((r && !(perm & OTH_RD)) || (w && !(perm & OTH_WR))) {
+ udata.u_error = EACCES;
+ goto cantopen;
+ }
+ if (w) {
+ if (getmode(ino) == F_DIR ) {
+ udata.u_error = EISDIR;
+ goto cantopen;
+ }
+ if (ino->c_flags & CRDONLY) {
+ udata.u_error = EROFS;
+ goto cantopen;
+ }
+ }
+
+ if (isdevice(ino)) {
+ inoptr *iptr = &of_tab[oftindex].o_inode;
+ /* d_open may block and thus ino may become invalid as may
+ parent (but we don't need it again). It may also be changed
+ by the call to dev_openi */
+
+ if (dev_openi(iptr, flag) != 0)
+ goto cantopen;
+
+ /* May have changed */
+ /* get the static pointer back in case it changed via dev
+ usage or just because we blocked */
+ ino = *iptr;
+ }
+
+ if (trunc && getmode(ino) == F_REG) {
+ if (f_trunc(ino))
+ goto idrop;
+ for (j = 0; j < OFTSIZE; ++j)
+ /* Arguably should fix at read/write */
+ if (of_tab[j].o_inode == ino)
+ of_tab[j].o_ptr = 0;
+ }
+
+ udata.u_files[uindex] = oftindex;
+
+ of_tab[oftindex].o_ptr = 0;
+ of_tab[oftindex].o_access = flag; /* Save the low bits only */
+ if (flag & O_CLOEXEC)
+ udata.u_cloexec |= (1 << oftindex);
+ /* FIXME: ATIME ? */
+
+/*
+ * Sleep process if no writer or reader
+ */
+ if (getmode(ino) == F_PIPE && of_tab[oftindex].o_refs == 1
+ && !(flag & O_NDELAY))
+ psleep(ino);
+
+ /* From the moment of the psleep ino is invalid */
+
+ return (uindex);
+ idrop:
+ i_deref(ino);
+ cantopen:
+ oft_deref(oftindex); /* This will call i_deref() */
+ nooft:
+ udata.u_files[uindex] = NO_FILE;
+ return (-1);
+}
+
+#undef name
+#undef flag
+#undef mode
+
+
+
+/*******************************************
+link (name1, name2) Function 5
+char *name1;
+char *name2;
+********************************************/
+#define name1 (char *)udata.u_argn
+#define name2 (char *)udata.u_argn1
+
+arg_t _link(void)
+{
+ inoptr ino;
+ inoptr ino2;
+ inoptr parent2;
+ char fname[FILENAME_LEN + 1];
+
+ if (!(ino = n_open(name1, NULLINOPTR)))
+ return (-1);
+
+ if (getmode(ino) == F_DIR && esuper())
+ goto nogood;
+
+ if (ino->c_node.i_nlink == 0xFFFF) {
+ udata.u_error = EMLINK;
+ goto nogood;
+ }
+
+ /* Make sure file2 doesn't exist, and get its parent */
+ if ((ino2 = n_open(name2, &parent2)) != NULL) {
+ i_deref(ino2);
+ i_deref(parent2);
+ udata.u_error = EEXIST;
+ goto nogood;
+ }
+
+ if (!parent2)
+ goto nogood;
+
+ if (ino->c_dev != parent2->c_dev) {
+ i_deref(parent2);
+ udata.u_error = EXDEV;
+ goto nogood;
+ }
+
+ filename(name2, fname);
+
+ if (!ch_link(parent2, "", fname, ino)) {
+ i_deref(parent2);
+ goto nogood;
+ }
+
+ /* Update the link count. */
+ ++ino->c_node.i_nlink;
+ wr_inode(ino);
+ setftime(ino, C_TIME);
+
+ i_deref(parent2);
+ i_deref(ino);
+ return 0;
+
+ nogood:
+ i_deref(ino);
+ return -1;
+}
+
+#undef name1
+#undef name2
+
+
+/*******************************************
+ fcntl (fd, request, data) Function 47
+ int fd;
+ int request;
+ char *data;
+ ********************************************/
+#define fd (int)udata.u_argn
+#define request (int)udata.u_argn1
+#define data (int)udata.u_argn2
+
+arg_t _fcntl(void)
+{
+ uint8_t *acc;
+ int newd;
+
+ if (getinode(fd) == NULLINODE)
+ return (-1);
+
+ acc = &of_tab[udata.u_files[fd]].o_access;
+ switch (request) {
+ case F_SETFL:
+ *acc =
+ (*acc & ~(O_APPEND | O_NDELAY)) | (data &
+ (O_APPEND |
+ O_NDELAY));
+ return 0;
+ case F_GETFL:
+ return data;
+ case F_GETFD:
+ return udata.u_cloexec & (1 << fd) ? O_CLOEXEC : 0;
+ case F_SETFD:
+ if (data & O_CLOEXEC)
+ udata.u_cloexec |= (1 << fd);
+ else
+ udata.u_cloexec &= (1 << fd);
+ return 0;
+ case F_DUPFD:
+ if ((newd = uf_alloc_n(data)) == -1)
+ return (-1);
+ udata.u_files[newd] = udata.u_files[fd];
+ ++of_tab[udata.u_files[fd]].o_refs;
+ return 0;
+ default:
+ udata.u_error = EINVAL;
+ return -1;
+ }
+}
+
+#undef fd
+#undef request
+#undef data
+
+/*******************************************
+uname (buf, len) Function 54
+char *buf;
+uint16_t len;
+
+We pass a set of \0 terminated strings, don't bother
+with node name. Rest is up to the libc.
+********************************************/
+
+#define buf (char *)udata.u_argn
+#define len (uint16_t)udata.u_argn1
+
+arg_t _uname(void)
+{
+ uint16_t size = sizeof(sysinfo) + uname_len;
+ if (size > len)
+ size = len;
+ sysinfo.memk = procmem;
+ sysinfo.usedk = pagemap_mem_used();
+ sysinfo.nproc = PTABSIZE;
+ sysinfo.ticks = ticks_per_dsecond * 10;
+ sysinfo.loadavg[0] = loadavg[0].average;
+ sysinfo.loadavg[1] = loadavg[1].average;
+ sysinfo.loadavg[2] = loadavg[2].average;
+ uput(&sysinfo, buf, size);
+ return size;
+}
+
+#undef buf
+
+/**************************************
+flock(fd, lockop) Function 60
+int file;
+int lockop;
+
+Perform locking upon a file.
+**************************************/
+
+#define file (uint16_t)udata.u_argn
+#define lockop (uint16_t)udata.u_argn1
+
+arg_t _flock(void)
+{
+ inoptr ino;
+ struct oft *o;
+ staticfast uint8_t c;
+ staticfast uint8_t lock;
+ staticfast int self;
+
+ lock = lockop & ~LOCK_NB;
+ self = 0;
+
+ if (lock > LOCK_UN) {
+ udata.u_error = EINVAL;
+ return -1;
+ }
+
+ if ((ino = getinode(file)) == NULLINODE)
+ return -1;
+ o = &of_tab[udata.u_files[file]];
+
+ c = ino->c_flags & CFLOCK;
+
+ /* Upgrades and downgrades. Check if we are in fact doing a no-op */
+ if (o->o_access & O_FLOCK) {
+ self = 1;
+ /* Shared or exclusive to shared can't block and is easy */
+ if (lock == LOCK_SH) {
+ if (c == CFLEX)
+ c = 1;
+ goto done;
+ }
+ /* Exclusive to exclusive - no op */
+ if (c == CFLEX && lock == LOCK_EX)
+ return 0;
+ /* Shared to exclusive - handle via the loop */
+ }
+
+
+ /* Unlock - drop the locks, mark us not a lock holder. Doesn't block */
+ if (lockop == LOCK_UN) {
+ o->o_access &= ~O_FLOCK;
+ deflock(o);
+ return 0;
+ }
+
+ do {
+ /* Exclusive lock must have no holders */
+ if (c == self && lock == LOCK_EX) {
+ c = CFLEX;
+ goto done;
+ }
+ if (c < CFMAX) {
+ c++;
+ goto done;
+ }
+ if (c == CFMAX) {
+ udata.u_error = ENOLCK;
+ return -1;
+ }
+ /* LOCK_NB is defined as O_NDELAY... */
+ if (psleep_flags(&ino->c_flags, (lockop & LOCK_NB)))
+ return -1;
+ /* locks will hopefully have changed .. */
+ c = ino->c_flags & CFLOCK;
+ } while (1);
+
+done:
+ if (o->o_access & O_FLOCK)
+ deflock(o);
+ ino->c_flags &= ~CFLOCK;
+ ino->c_flags |= c;
+ o->o_access |= O_FLOCK;
+ wakeup(&ino->c_flags);
+ return 0;
+}
+
+
+#undef file
+#undef lockop
struct socket *s = sock_get(d, NULL);
int ret;
+ /* FIXME: will need _read redone for banked syscalls */
if (s == NULL)
return -1;
ret = _read();
#undef DEBUG /* UNdefine to delete debug code sequences */
+/*
+ * On some 8bit systems it makes a huge difference if we avoid all the
+ * t-> pointer dereferences at link time, so for a single tty we abuse
+ * the preprocessor slightly
+ */
+
/*
* Minimal Terminal Interface
*
int tty_inproc(uint8_t minor, unsigned char c)
{
unsigned char oc;
- struct tty *t;
- struct s_queue *q = &ttyinq[minor];
int canon;
uint8_t wr;
+ struct tty *t = &ttydata[minor];
+ struct s_queue *q = &ttyinq[minor];
- t = &ttydata[minor];
canon = t->termios.c_lflag & ICANON;
if (t->termios.c_iflag & ISTRIP)