diff options
| -rw-r--r-- | CHANGES | 1 | ||||
| -rw-r--r-- | OpenBSD/386/include/fpuctl.h | 76 | ||||
| -rw-r--r-- | OpenBSD/386/include/lib9.h | 491 | ||||
| -rw-r--r-- | emu/OpenBSD/asm-386.S | 111 | ||||
| -rw-r--r-- | emu/OpenBSD/audio.c | 547 | ||||
| -rw-r--r-- | emu/OpenBSD/cmd.c | 213 | ||||
| -rw-r--r-- | emu/OpenBSD/deveia.c | 39 | ||||
| -rw-r--r-- | emu/OpenBSD/devfs.c | 1 | ||||
| -rw-r--r-- | emu/OpenBSD/emu | 106 | ||||
| -rw-r--r-- | emu/OpenBSD/ipif.c | 372 | ||||
| -rw-r--r-- | emu/OpenBSD/mkfile | 45 | ||||
| -rw-r--r-- | emu/OpenBSD/mkfile-OpenBSD | 17 | ||||
| -rw-r--r-- | emu/OpenBSD/os.c | 524 | ||||
| -rw-r--r-- | emu/OpenBSD/rfork_thread.S | 104 | ||||
| -rw-r--r-- | lib9/getcallerpc-OpenBSD-386.S | 7 | ||||
| -rw-r--r-- | libmath/FPcontrol-OpenBSD.c | 78 | ||||
| -rw-r--r-- | libmemdraw/mkfile-OpenBSD | 4 | ||||
| -rw-r--r-- | libmemlayer/mkfile-OpenBSD | 4 | ||||
| -rw-r--r-- | mkfiles/mkfile-OpenBSD-386 | 30 | ||||
| -rw-r--r-- | mkfiles/mkhost-OpenBSD | 19 | ||||
| -rw-r--r-- | tools/styxtest/mkfile-OpenBSD | 0 |
21 files changed, 2789 insertions, 0 deletions
@@ -1,5 +1,6 @@ 20080522 dis/lib/msgio.dis appl/lib/msgio.b - fix incorrect check for 16rFF + add OpenBSD changes from tim@nop.cx (more changes to follow shortly that cause changes elsewhere) 20080416 fix emu/Nt/os.c use of wrong name for null value move win/win-x11a references to emu/*/emu config files from emu/*/mkfile diff --git a/OpenBSD/386/include/fpuctl.h b/OpenBSD/386/include/fpuctl.h new file mode 100644 index 00000000..e7a41cdc --- /dev/null +++ b/OpenBSD/386/include/fpuctl.h @@ -0,0 +1,76 @@ +/* + * 386 fpu support + * Mimic Plan9 floating point support + */ + +static void +setfcr(ulong fcr) +{ + __asm__( "xorb $0x3f, %%al\n\t" + "pushw %%ax\n\t" + "fwait\n\t" + "fldcw (%%esp)\n\t" + "popw %%ax\n\t" + : /* no output */ + : "al" (fcr) + ); +} + +static ulong +getfcr(void) +{ + ulong fcr = 0; + + __asm__( "pushl %%eax\n\t" + "fwait\n\t" + "fstcw (%%esp)\n\t" + "popl %%eax\n\t" + "xorb $0x3f, %%al\n\t" + : "=a" (fcr) + : "eax" (fcr) + ); + return fcr; +} + +static ulong +getfsr(void) +{ + ulong fsr = -1; + + __asm__( "fwait\n\t" + "fstsw (%%eax)\n\t" + "movl (%%eax), %%eax\n\t" + "andl $0xffff, %%eax\n\t" + : "=a" (fsr) + : "eax" (&fsr) + ); + return fsr; +} + +static void +setfsr(ulong fsr) +{ + __asm__("fclex\n\t"); +} + +/* FCR */ +#define FPINEX (1<<5) +#define FPUNFL ((1<<4)|(1<<1)) +#define FPOVFL (1<<3) +#define FPZDIV (1<<2) +#define FPINVAL (1<<0) +#define FPRNR (0<<10) +#define FPRZ (3<<10) +#define FPRPINF (2<<10) +#define FPRNINF (1<<10) +#define FPRMASK (3<<10) +#define FPPEXT (3<<8) +#define FPPSGL (0<<8) +#define FPPDBL (2<<8) +#define FPPMASK (3<<8) +/* FSR */ +#define FPAINEX FPINEX +#define FPAOVFL FPOVFL +#define FPAUNFL FPUNFL +#define FPAZDIV FPZDIV +#define FPAINVAL FPINVAL diff --git a/OpenBSD/386/include/lib9.h b/OpenBSD/386/include/lib9.h new file mode 100644 index 00000000..a0fc2caf --- /dev/null +++ b/OpenBSD/386/include/lib9.h @@ -0,0 +1,491 @@ +/* define _BSD_SOURCE to use ISO C, POSIX, and 4.3BSD things. */ +#ifndef _BSD_SOURCE +#define _BSD_SOURCE +#endif +/* these aren't really needed because OpenBSD does the right thing and makes off_t 64 bits, full stop */ +#define _LARGEFILE64_SOURCE 1 +#define _FILE_OFFSET_BITS 64 +#include <sys/types.h> +#include <sys/stat.h> +#include <stdlib.h> +#include <stdarg.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include "math.h" +#include <fcntl.h> +#include <setjmp.h> +#include <float.h> +#include <time.h> + +#define getwd infgetwd + +#undef isnan +#define round infround +#define fmax inffmax +#define log2 inflog2 + +#ifndef EMU +typedef struct Proc Proc; +#endif + +/* + * math module dtoa + */ +#define __LITTLE_ENDIAN + +#define nil ((void*)0) + +typedef unsigned char uchar; +typedef signed char schar; +//typedef unsigned long ulong; +typedef unsigned short Rune; +typedef long long int vlong; +typedef unsigned long long int uvlong; +typedef unsigned int u32int; +typedef unsigned int mpdigit; /* for /sys/include/mp.h */ +typedef unsigned short u16int; +typedef unsigned char u8int; +typedef unsigned long uintptr; + +#define USED(x) if(x){}else{} +#define SET(x) + +#undef nelem +#define nelem(x) (sizeof(x)/sizeof((x)[0])) +#undef offsetof +#define offsetof(s, m) (ulong)(&(((s*)0)->m)) +#undef assert +#define assert(x) if(x){}else _assert("x") + +/* + * most mem and string routines are declared by ANSI/POSIX files above + */ + +extern char* strecpy(char*, char*, char*); +extern char* strdup(const char*); +extern int cistrncmp(char*, char*, int); +extern int cistrcmp(char*, char*); +extern char* cistrstr(char*, char*); +extern int tokenize(char*, char**, int); + +enum +{ + UTFmax = 3, /* maximum bytes per rune */ + Runesync = 0x80, /* cannot represent part of a UTF sequence (<) */ + Runeself = 0x80, /* rune and UTF sequences are the same (<) */ + Runeerror = 0x80 /* decoding error in UTF */ +}; + +/* + * rune routines + */ +extern int runetochar(char*, Rune*); +extern int chartorune(Rune*, char*); +extern int runelen(long); +extern int runenlen(Rune*, int); +extern int fullrune(char*, int); +extern int utflen(char*); +extern int utfnlen(char*, long); +extern char* utfrune(char*, long); +extern char* utfrrune(char*, long); +extern char* utfutf(char*, char*); +extern char* utfecpy(char*, char*, char*); + +extern Rune* runestrcat(Rune*, Rune*); +extern Rune* runestrchr(Rune*, Rune); +extern int runestrcmp(Rune*, Rune*); +extern Rune* runestrcpy(Rune*, Rune*); +extern Rune* runestrncpy(Rune*, Rune*, long); +extern Rune* runestrecpy(Rune*, Rune*, Rune*); +extern Rune* runestrdup(Rune*); +extern Rune* runestrncat(Rune*, Rune*, long); +extern int runestrncmp(Rune*, Rune*, long); +extern Rune* runestrrchr(Rune*, Rune); +extern long runestrlen(Rune*); +extern Rune* runestrstr(Rune*, Rune*); + +extern Rune tolowerrune(Rune); +extern Rune totitlerune(Rune); +extern Rune toupperrune(Rune); +extern int isalpharune(Rune); +extern int islowerrune(Rune); +extern int isspacerune(Rune); +extern int istitlerune(Rune); +extern int isupperrune(Rune); + +/* + * malloc + */ +extern void* malloc(size_t); +extern void* mallocz(ulong, int); +extern void free(void*); +extern ulong msize(void*); +extern void* calloc(size_t, size_t); +extern void* realloc(void*, size_t); +extern void setmalloctag(void*, ulong); +extern void setrealloctag(void*, ulong); +extern ulong getmalloctag(void*); +extern ulong getrealloctag(void*); +extern void* malloctopoolblock(void*); + +/* + * print routines + */ +typedef struct Fmt Fmt; +struct Fmt{ + uchar runes; /* output buffer is runes or chars? */ + void *start; /* of buffer */ + void *to; /* current place in the buffer */ + void *stop; /* end of the buffer; overwritten if flush fails */ + int (*flush)(Fmt *); /* called when to == stop */ + void *farg; /* to make flush a closure */ + int nfmt; /* num chars formatted so far */ + va_list args; /* args passed to dofmt */ + int r; /* % format Rune */ + int width; + int prec; + ulong flags; +}; + +enum{ + FmtWidth = 1, + FmtLeft = FmtWidth << 1, + FmtPrec = FmtLeft << 1, + FmtSharp = FmtPrec << 1, + FmtSpace = FmtSharp << 1, + FmtSign = FmtSpace << 1, + FmtZero = FmtSign << 1, + FmtUnsigned = FmtZero << 1, + FmtShort = FmtUnsigned << 1, + FmtLong = FmtShort << 1, + FmtVLong = FmtLong << 1, + FmtComma = FmtVLong << 1, + FmtByte = FmtComma << 1, + + FmtFlag = FmtByte << 1 +}; + +extern int print(char*, ...); +extern char* seprint(char*, char*, char*, ...); +extern char* vseprint(char*, char*, char*, va_list); +extern int snprint(char*, int, char*, ...); +extern int vsnprint(char*, int, char*, va_list); +extern char* smprint(char*, ...); +extern char* vsmprint(char*, va_list); +extern int sprint(char*, char*, ...); +extern int fprint(int, char*, ...); +extern int vfprint(int, char*, va_list); + +extern int runesprint(Rune*, char*, ...); +extern int runesnprint(Rune*, int, char*, ...); +extern int runevsnprint(Rune*, int, char*, va_list); +extern Rune* runeseprint(Rune*, Rune*, char*, ...); +extern Rune* runevseprint(Rune*, Rune*, char*, va_list); +extern Rune* runesmprint(char*, ...); +extern Rune* runevsmprint(char*, va_list); + +extern int fmtfdinit(Fmt*, int, char*, int); +extern int fmtfdflush(Fmt*); +extern int fmtstrinit(Fmt*); +extern char* fmtstrflush(Fmt*); +extern int runefmtstrinit(Fmt*); +extern Rune* runefmtstrflush(Fmt*); + +extern int fmtinstall(int, int (*)(Fmt*)); +extern int dofmt(Fmt*, char*); +extern int dorfmt(Fmt*, Rune*); +extern int fmtprint(Fmt*, char*, ...); +extern int fmtvprint(Fmt*, char*, va_list); +extern int fmtrune(Fmt*, int); +extern int fmtstrcpy(Fmt*, char*); +extern int fmtrunestrcpy(Fmt*, Rune*); +/* + * error string for %r + * supplied on per os basis, not part of fmt library + */ +extern int errfmt(Fmt *f); + +/* + * quoted strings + */ +extern char *unquotestrdup(char*); +extern Rune *unquoterunestrdup(Rune*); +extern char *quotestrdup(char*); +extern Rune *quoterunestrdup(Rune*); +extern int quotestrfmt(Fmt*); +extern int quoterunestrfmt(Fmt*); +extern void quotefmtinstall(void); +extern int (*doquote)(int); + +/* + * random number + */ +extern int nrand(int); +extern ulong truerand(void); +extern ulong ntruerand(ulong); + +/* + * math + */ +extern int isNaN(double); +extern int isInf(double, int); +extern double pow(double, double); + +/* + * Time-of-day + */ + +typedef struct Tm Tm; +struct Tm { + int sec; + int min; + int hour; + int mday; + int mon; + int year; + int wday; + int yday; + char zone[4]; + int tzoff; +}; +extern vlong osnsec(void); +#define nsec osnsec + +/* + * one-of-a-kind + */ +extern void _assert(char*); +extern double charstod(int(*)(void*), void*); +extern char* cleanname(char*); +extern double frexp(double, int*); +extern ulong getcallerpc(void*); +extern int getfields(char*, char**, int, int, char*); +extern char* getuser(void); +extern char* getwd(char*, int); +extern double ipow10(int); +extern double ldexp(double, int); +extern double modf(double, double*); +#define pow10 infpow10 +extern double pow10(int); +extern vlong strtoll(const char*, char**, int); +extern uvlong strtoull(const char*, char**, int); +extern void sysfatal(char*, ...); +extern int dec64(uchar*, int, char*, int); +extern int enc64(char*, int, uchar*, int); +extern int dec32(uchar*, int, char*, int); +extern int enc32(char*, int, uchar*, int); +extern int dec16(uchar*, int, char*, int); +extern int enc16(char*, int, uchar*, int); +extern int encodefmt(Fmt*); + +/* + * synchronization + */ +typedef +struct Lock { + ulong val; + int pid; +} Lock; + +extern ulong _tas(ulong*); + +extern void lock(Lock*); +extern void unlock(Lock*); +extern int canlock(Lock*); + +typedef struct QLock QLock; +struct QLock +{ + Lock use; /* to access Qlock structure */ + Proc *head; /* next process waiting for object */ + Proc *tail; /* last process waiting for object */ + int locked; /* flag */ +}; + +extern void qlock(QLock*); +extern void qunlock(QLock*); +extern int canqlock(QLock*); +extern void _qlockinit(ulong (*)(ulong, ulong)); /* called only by the thread library */ + +typedef +struct RWLock +{ + Lock l; /* Lock modify lock */ + QLock x; /* Mutual exclusion lock */ + QLock k; /* Lock for waiting writers */ + int readers; /* Count of readers in lock */ +} RWLock; + +extern int canrlock(RWLock*); +extern int canwlock(RWLock*); +extern void rlock(RWLock*); +extern void runlock(RWLock*); +extern void wlock(RWLock*); +extern void wunlock(RWLock*); + +/* + * network dialing + */ +#define NETPATHLEN 40 + +/* + * system calls + * + */ +#define STATMAX 65535U /* max length of machine-independent stat structure */ +#define DIRMAX (sizeof(Dir)+STATMAX) /* max length of Dir structure */ +#define ERRMAX 128 /* max length of error string */ + +#define MORDER 0x0003 /* mask for bits defining order of mounting */ +#define MREPL 0x0000 /* mount replaces object */ +#define MBEFORE 0x0001 /* mount goes before others in union directory */ +#define MAFTER 0x0002 /* mount goes after others in union directory */ +#define MCREATE 0x0004 /* permit creation in mounted directory */ +#define MCACHE 0x0010 /* cache some data */ +#define MMASK 0x0017 /* all bits on */ + +#define OREAD 0 /* open for read */ +#define OWRITE 1 /* write */ +#define ORDWR 2 /* read and write */ +#define OEXEC 3 /* execute, == read but check execute permission */ +#define OTRUNC 16 /* or'ed in (except for exec), truncate file first */ +#define OCEXEC 32 /* or'ed in, close on exec */ +#define ORCLOSE 64 /* or'ed in, remove on close */ +#define OEXCL 0x1000 /* or'ed in, exclusive use (create only) */ + +#define AEXIST 0 /* accessible: exists */ +#define AEXEC 1 /* execute access */ +#define AWRITE 2 /* write access */ +#define AREAD 4 /* read access */ + +/* bits in Qid.type */ +#define QTDIR 0x80 /* type bit for directories */ +#define QTAPPEND 0x40 /* type bit for append only files */ +#define QTEXCL 0x20 /* type bit for exclusive use files */ +#define QTMOUNT 0x10 /* type bit for mounted channel */ +#define QTAUTH 0x08 /* type bit for authentication file */ +#define QTFILE 0x00 /* plain file */ + +/* bits in Dir.mode */ +#define DMDIR 0x80000000 /* mode bit for directories */ +#define DMAPPEND 0x40000000 /* mode bit for append only files */ +#define DMEXCL 0x20000000 /* mode bit for exclusive use files */ +#define DMMOUNT 0x10000000 /* mode bit for mounted channel */ +#define DMAUTH 0x08000000 /* mode bit for authentication file */ +#define DMREAD 0x4 /* mode bit for read permission */ +#define DMWRITE 0x2 /* mode bit for write permission */ +#define DMEXEC 0x1 /* mode bit for execute permission */ + +typedef +struct Qid +{ + uvlong path; + ulong vers; + uchar type; +} Qid; + +typedef +struct Dir { + /* system-modified data */ + ushort type; /* server type */ + uint dev; /* server subtype */ + /* file data */ + Qid qid; /* unique id from server */ + ulong mode; /* permissions */ + ulong atime; /* last read time */ + ulong mtime; /* last write time */ + vlong length; /* file length */ + char *name; /* last element of path */ + char *uid; /* owner name */ + char *gid; /* group name */ + char *muid; /* last modifier name */ +} Dir; + +extern Dir* dirstat(char*); +extern Dir* dirfstat(int); +extern int dirwstat(char*, Dir*); +extern int dirfwstat(int, Dir*); +extern long dirread(int, Dir**); +extern void nulldir(Dir*); +extern long dirreadall(int, Dir**); + +typedef +struct Waitmsg +{ + int pid; /* of loved one */ + ulong time[3]; /* of loved one & descendants */ + char *msg; +} Waitmsg; + +extern void _exits(char*); + +extern void exits(char*); +extern int create(char*, int, int); +extern int errstr(char*, uint); + +extern void perror(const char*); +extern long readn(int, void*, long); +extern int remove(const char*); +extern void rerrstr(char*, uint); +extern vlong seek(int, vlong, int); +extern int segflush(void*, ulong); +extern void werrstr(char*, ...); + +extern char *argv0; +#define ARGBEGIN for((argv0||(argv0=*argv)),argv++,argc--;\ + argv[0] && argv[0][0]=='-' && argv[0][1];\ + argc--, argv++) {\ + char *_args, *_argt;\ + Rune _argc;\ + _args = &argv[0][1];\ + if(_args[0]=='-' && _args[1]==0){\ + argc--; argv++; break;\ + }\ + _argc = 0;\ + while(*_args && (_args += chartorune(&_argc, _args)))\ + switch(_argc) +#define ARGEND SET(_argt);USED(_argt);USED(_argc); USED(_args);}USED(argv); USED(argc); +#define ARGF() (_argt=_args, _args="",\ + (*_argt? _argt: argv[1]? (argc--, *++argv): 0)) +#define EARGF(x) (_argt=_args, _args="",\ + (*_argt? _argt: argv[1]? (argc--, *++argv): ((x), abort(), (char*)0))) + +#define ARGC() _argc + +/* + * Extensions for Inferno to basic libc.h + */ + +#define setbinmode() + +/* + * Extensions for emu kernel emulation + */ +#ifdef EMU + +/* + * This structure must agree with FPsave and FPrestore asm routines + */ +typedef struct FPU FPU; +struct FPU +{ + uchar env[28]; +}; + +#define KSTACK (32 * 1024) + +static __inline Proc *getup(void) { + Proc *p; + __asm__( "movl %%esp, %%eax\n\t" + : "=a" (p) + ); + return *(Proc **)((unsigned long)p & ~(KSTACK - 1)); +}; + +#define up (getup()) + +typedef sigjmp_buf osjmpbuf; +#define ossetjmp(buf) sigsetjmp(buf, 1) + +#endif diff --git a/emu/OpenBSD/asm-386.S b/emu/OpenBSD/asm-386.S new file mode 100644 index 00000000..f3a3f9cf --- /dev/null +++ b/emu/OpenBSD/asm-386.S @@ -0,0 +1,111 @@ + .file "asm-OpenBSD-386.S" + +#include <sys/syscall.h> +#include <machine/asm.h> + +#include "rfork_thread.S" + +/* + * executeonnewstack(void *tos, void (*tramp)(void *arg), void *arg) + */ + + .type ournewstack,@function + .global executeonnewstack +executeonnewstack: + pushl %ebp + movl %esp, %ebp + pushl %esi + + movl 8(%ebp), %esi /* get tos */ + subl $4, %esi + movl 16(%ebp), %eax + movl %eax, (%esi) /* stash arg on new stack */ + subl $4, %esi + movl 12(%ebp), %eax + movl %eax, (%esi) /* stash tramp on new stack */ + mov %esi, %esp /* swap stacks pronto */ + popl %eax /* recover the tramp address */ + call *%eax /* and jump to it (ho ho) */ + + /* if we return here, tramp didn't do it's job */ + + addl $8, %esp /* clean up for pose value */ + + leal SYS_exit, %eax + int $0x80 + +/* + * unlockandexit(int *key) + * + * NB: the return status may be rubbish if the stack is reused + * between the unlock and the system call, but this should + * not matter since no task is waiting for the result + */ + + .type unlockandexit,@function + .global unlockandexit +unlockandexit: + pushl %ebp + movl %esp, %ebp + + movl 8(%ebp), %esi /* get the key address */ + pushl $0 /* exit status 0 */ + movl $0, %eax /* unlock the stack allocator */ + movl %eax, (%esi) + leal SYS_exit, %eax /* call exit */ + int $0x80 + +/* + * umult(ulong m1, ulong m2, ulong *hi) + */ + + .type umult,@function + .global umult +umult: + pushl %ebp + movl %esp, %ebp + pushl %ebx + + movl 8(%ebp), %eax + movl 12(%ebp), %ebx + mull %ebx + movl 16(%ebp), %ebx + movl %edx, (%ebx) + + popl %ebx + popl %ebp + ret + + .type FPsave,@function + .global FPsave +FPsave: + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %eax + fstenv (%eax) + popl %ebp + ret + + .type FPrestore,@function + .global FPrestore +FPrestore: + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %eax + fldenv (%eax) + popl %ebp + ret + + .type getcallerpc,@function + .global getcallerpc +getcallerpc: + movl 4(%ebp), %eax + ret + + .type _tas,@function + .globl _tas +_tas: + movl $1, %eax + movl 4(%esp), %ecx + xchgl %eax, 0(%ecx) + ret diff --git a/emu/OpenBSD/audio.c b/emu/OpenBSD/audio.c new file mode 100644 index 00000000..4f2de3f6 --- /dev/null +++ b/emu/OpenBSD/audio.c @@ -0,0 +1,547 @@ +#include "dat.h" +#include "fns.h" +#include "error.h" +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/filio.h> +#include "audio.h" +#include <soundcard.h> + +#define Audio_Mic_Val SOUND_MIXER_MIC +#define Audio_Linein_Val SOUND_MIXER_LINE + +#define Audio_Speaker_Val SOUND_MIXER_SPEAKER +#define Audio_Headphone_Val SOUND_MIXER_PHONEOUT +#define Audio_Lineout_Val SOUND_MIXER_VOLUME + +#define Audio_Pcm_Val AFMT_S16_LE +#define Audio_Ulaw_Val AFMT_MU_LAW +#define Audio_Alaw_Val AFMT_A_LAW + +#include "audio-tbls.c" + +#define min(a,b) ((a) < (b) ? (a) : (b)) +static int debug; + +#define AUDIO_FILE_STRING "/dev/dsp" + +enum { + A_Pause, + A_UnPause +}; + +enum { + A_In, + A_Out +}; + +static QLock inlock; +static QLock outlock; + +static int audio_file = -1; /* file in/out */ +static int audio_file_in = -1; /* copy of above when opened O_READ/O_RDWR */ +static int audio_file_out = -1; /* copy of above when opened O_WRITE/O_RDWR */ + +static int audio_swap_flag = 0; /* endian swap */ + +static int audio_in_pause = A_UnPause; + +static Audio_t av; +static int mixerleftvol[32]; +static int mixerrightvol[32]; + +static int audio_enforce(Audio_t*); +static int audio_open(void); +static int audio_pause_in(int, int); +static int audio_flush(int, int); +static int audio_pause_out(int); +static int audio_set_blocking(int); +static int audio_set_info(int, Audio_d*, int); +static void audio_swap_endian(char*, int); + +void +audio_file_init(void) +{ + int i; + static ushort flag = 1; + + audio_swap_flag = *((uchar*)&flag) == 0; /* big-endian? */ + audio_info_init(&av); + for (i = 0; i < 32; i++) + mixerleftvol[i] = mixerrightvol[i] = 100; +} + +void +audio_ctl_init(void) +{ +} + +void +audio_file_open(Chan *c, int omode) +{ + char ebuf[ERRMAX]; + + if (debug) + print("audio_file_open(0x%.8lux, %d)\n", c, omode); + switch(omode){ + case OREAD: + qlock(&inlock); + if(waserror()){ + qunlock(&inlock); + nexterror(); + } + + if(audio_file_in >= 0) + error(Einuse); + if (audio_file < 0) + audio_file = audio_open(); + audio_file_in = audio_file; + poperror(); + qunlock(&inlock); + break; + case OWRITE: + qlock(&outlock); + if(waserror()){ + qunlock(&outlock); + nexterror(); + } + if(audio_file_out >= 0) + error(Einuse); + if (audio_file < 0) + audio_file = audio_open(); + audio_file_out = audio_file; + poperror(); + qunlock(&outlock); + break; + case ORDWR: + qlock(&inlock); + qlock(&outlock); + if(waserror()){ + qunlock(&outlock); + qunlock(&inlock); + nexterror(); + } + if(audio_file_in >= 0 || audio_file_out >= 0) + error(Einuse); + if (audio_file < 0) + audio_file = audio_open(); + audio_file_in = audio_file_out = audio_file; + poperror(); + qunlock(&outlock); + qunlock(&inlock); + break; + } + if (debug) + print("audio_file_open: success\nin %d out %d both %d\n", + audio_file_out, audio_file_in, audio_file); +} + +void +audio_ctl_open(Chan *c, int omode) +{ + USED(c); + USED(omode); +} + +void +audio_file_close(Chan *c) +{ + switch(c->mode){ + case OREAD: + qlock(&inlock); + qlock(&outlock); + if (audio_file_out < 0) { + close(audio_file); + audio_file = -1; + } + qunlock(&outlock); + audio_file_in = -1; + qunlock(&inlock); + break; + case OWRITE: + qlock(&inlock); + qlock(&outlock); + if (audio_file_in < 0) { + close(audio_file); + audio_file = -1; + } + audio_file_out = -1; + qunlock(&outlock); + qunlock(&inlock); + break; + case ORDWR: + qlock(&inlock); + qlock(&outlock); + close(audio_file); + audio_file_in = audio_file_out = audio_file = -1; + qunlock(&outlock); + qunlock(&inlock); + break; + } +} + +void +audio_ctl_close(Chan *c) +{ +} + +long +audio_file_read(Chan *c, void *va, long count, vlong offset) +{ + struct timespec time; + long ba, status, chunk, total; + char *pva = (char *) va; + + qlock(&inlock); + if(waserror()){ + qunlock(&inlock); + nexterror(); + } + + if(audio_file_in < 0) + error(Eperm); + + /* check block alignment */ + ba = av.in.bits * av.in.chan / Bits_Per_Byte; + + if(count % ba) + error(Ebadarg); + + if(! audio_pause_in(audio_file_in, A_UnPause)) + error(Eio); + + total = 0; + while(total < count) { + chunk = count - total; + osenter(); + status = read(audio_file_in, pva + total, chunk); + osleave(); + if(status < 0) + error(Eio); + total += status; + } + + if(total != count) + error(Eio); + + if(audio_swap_flag && av.out.bits == 16) + audio_swap_endian(pva, count); + + poperror(); + qunlock(&inlock); + + return count; +} + +long +audio_file_write(Chan *c, void *va, long count, vlong offset) +{ + struct timespec time; + long status = -1; + long ba, total, chunk, bufsz; + + if (debug > 1) + print("audio_file_write(0x%.8lux, 0x%.8lux, %ld, %uld)\n", + c, va, count, offset); + + qlock(&outlock); + if(waserror()){ + qunlock(&outlock); + nexterror(); + } + + if(audio_file_out < 0) + error(Eperm); + + /* check block alignment */ + ba = av.out.bits * av.out.chan / Bits_Per_Byte; + + if(count % ba) + error(Ebadarg); + + if(audio_swap_flag && av.out.bits == 16) + audio_swap_endian(va, count); + + total = 0; + bufsz = av.out.buf * Audio_Max_Buf / Audio_Max_Val; + + if(bufsz == 0) + error(Ebadarg); + + while(total < count) { + chunk = min(bufsz, count - total); + osenter(); + status = write(audio_file_out, va, chunk); + osleave(); + if(status <= 0) + error(Eio); + total += status; + } + + poperror(); + qunlock(&outlock); + + return count; +} + +static int +audio_open(void) +{ + int fd; + + /* open non-blocking in case someone already has it open */ + /* otherwise we would block until they close! */ + fd = open(AUDIO_FILE_STRING, O_RDWR|O_NONBLOCK); + if(fd < 0) + oserror(); + + /* change device to be blocking */ + if(!audio_set_blocking(fd)) { + if (debug) + print("audio_open: failed to set blocking\n"); + close(fd); + error("cannot set blocking mode"); + } + + if (debug) + print("audio_open: blocking set\n"); + + /* set audio info */ + av.in.flags = ~0; + av.out.flags = 0; + + if(! audio_set_info(fd, &av.in, A_In)) { + close(fd); + error(Ebadarg); + } + + av.in.flags = 0; + + /* tada, we're open, blocking, paused and flushed */ + return fd; +} + +long +audio_ctl_write(Chan *c, void *va, long count, vlong offset) +{ + int fd; + int ff; + Audio_t tmpav = av; + + tmpav.in.flags = 0; + tmpav.out.flags = 0; + + if (!audioparse(va, count, &tmpav)) + error(Ebadarg); + + if (!audio_enforce(&tmpav)) + error(Ebadarg); + + qlock(&inlock); + if (waserror()) { + qunlock(&inlock); + nexterror(); + } + + if (audio_file_in >= 0 && (tmpav.in.flags & AUDIO_MOD_FLAG)) { + if (!audio_pause_in(audio_file_in, A_Pause)) + error(Ebadarg); + if (!audio_flush(audio_file_in, A_In)) + error(Ebadarg); + if (!audio_set_info(audio_file_in, &tmpav.in, A_In)) + error(Ebadarg); + } + poperror(); + qunlock(&inlock); + + qlock(&outlock); + if (waserror()) { + qunlock(&outlock); + nexterror(); + } + if (audio_file_out >= 0 && (tmpav.out.flags & AUDIO_MOD_FLAG)){ + if (!audio_pause_out(audio_file_out)) + error(Ebadarg); + if (!audio_set_info(audio_file_out, &tmpav.out, A_Out)) + error(Ebadarg); + } + poperror(); + qunlock(&outlock); + + tmpav.in.flags = 0; + tmpav.out.flags = 0; + + av = tmpav; + + return count; +} + + + +static int +audio_set_blocking(int fd) +{ + int val; + + if((val = fcntl(fd, F_GETFL, 0)) == -1) + return 0; + + val &= ~O_NONBLOCK; + + if(fcntl(fd, F_SETFL, val) < 0) + return 0; + + return 1; +} + +static int +doioctl(int fd, int ctl, int *info) +{ + int status; + osenter(); + status = ioctl(fd, ctl, info); /* qlock and load general stuff */ + osleave(); + if (status < 0) + print("doioctl(0x%.8lux, 0x%.8lux) failed %d\n", ctl, *info, errno); + return status; +} + +static int +choosefmt(Audio_d *i) +{ + int newbits, newenc; + + newbits = i->bits; + newenc = i->enc; + switch (newenc) { + case Audio_Alaw_Val: + if (newbits == 8) + return AFMT_A_LAW; + break; + case Audio_Ulaw_Val: + if (newbits == 8) + return AFMT_MU_LAW; + break; + case Audio_Pcm_Val: + if (newbits == 8) + return AFMT_U8; + else if (newbits == 16) + return AFMT_S16_LE; + break; + } + return -1; +} + +static int +audio_set_info(int fd, Audio_d *i, int d) +{ + int status; + int unequal_stereo = 0; + + if(fd < 0) + return 0; + + /* fmt */ + if(i->flags & (AUDIO_BITS_FLAG || AUDIO_ENC_FLAG)) { + int oldfmt, newfmt; + oldfmt = AFMT_QUERY; + if (doioctl(fd, SNDCTL_DSP_SETFMT, &oldfmt) < 0) + return 0; + if (debug) + print("audio_set_info: current format 0x%.8lux\n", oldfmt); + newfmt = choosefmt(i); + if (debug) + print("audio_set_info: new format 0x%.8lux\n", newfmt); + if (newfmt == -1 || newfmt != oldfmt && doioctl(fd, SNDCTL_DSP_SETFMT, &newfmt) < 0) + return 0; + } + + /* channels */ + if(i->flags & AUDIO_CHAN_FLAG) { + int channels = i->chan; + if (debug) + print("audio_set_info: new channels %d\n", channels); + if (doioctl(fd, SNDCTL_DSP_CHANNELS, &channels) < 0 + || channels != i->chan) + return 0; + } + + /* sample rate */ + if(i->flags & AUDIO_RATE_FLAG) { + int speed = i->rate; + if (debug) + print("audio_set_info: new speed %d\n", speed); + if (doioctl(fd, SNDCTL_DSP_SPEED, &speed) < 0 || speed != i->rate) + return 0; + } + + /* dev volume */ + if(i->flags & (AUDIO_LEFT_FLAG | AUDIO_VOL_FLAG | AUDIO_RIGHT_FLAG)) { + int val; + if (i->flags & (AUDIO_LEFT_FLAG | AUDIO_VOL_FLAG)) + mixerleftvol[i->dev] = (i->left * 100) / Audio_Max_Val; + if (i->flags & (AUDIO_RIGHT_FLAG | AUDIO_VOL_FLAG)) + mixerrightvol[i->dev] = (i->right * 100) / Audio_Max_Val; + val = mixerleftvol[i->dev] | (mixerrightvol[i->dev] << 8); + doioctl(fd, MIXER_WRITE(i->dev), &val); + } + + if (i->flags & AUDIO_DEV_FLAG) { + } + + return 1; +} + +void +audio_swap_endian(char *p, int n) +{ + int b; + + while (n > 1) { + b = p[0]; + p[0] = p[1]; + p[1] = b; + p += 2; + n -= 2; + } +} + +static int +audio_pause_out(int fd) +{ + USED(fd); + return 1; +} + +static int +audio_pause_in(int fd, int f) +{ + USED(fd); + USED(f); + return 1; +} + +static int +audio_flush(int fd, int d) +{ + int x; + return doioctl(fd, SNDCTL_DSP_SYNC, &x) >= 0; +} + +static int +audio_enforce(Audio_t *t) +{ + if((t->in.enc == Audio_Ulaw_Val || t->in.enc == Audio_Alaw_Val) && + (t->in.rate != 8000 || t->in.chan != 1)) + return 0; + if((t->out.enc == Audio_Ulaw_Val || t->out.enc == Audio_Alaw_Val) && + (t->out.rate != 8000 || t->out.chan != 1)) + return 0; + return 1; +} + +Audio_t* +getaudiodev(void) +{ + return &av; +} diff --git a/emu/OpenBSD/cmd.c b/emu/OpenBSD/cmd.c new file mode 100644 index 00000000..ed4cabab --- /dev/null +++ b/emu/OpenBSD/cmd.c @@ -0,0 +1,213 @@ +#include <sys/types.h> +#include <signal.h> +#include <pwd.h> +#include <sys/resource.h> +#include <sys/wait.h> +#include <fcntl.h> + +#include "dat.h" +#include "fns.h" +#include "error.h" + +enum +{ + Debug = 0 +}; + +/* + * os-specific devcmd support. + * this version should be reasonably portable across Unix systems. + */ +typedef struct Targ Targ; +struct Targ +{ + int fd[3]; /* fd[0] is standard input, fd[1] is standard output, fd[2] is standard error */ + char** args; + char* dir; + int pid; + int wfd; /* child writes errors that occur after the fork or on exec */ + int uid; + int gid; +}; + +extern int gidnobody; +extern int uidnobody; + +static int +childproc(Targ *t) +{ + int i, nfd; + + if(Debug) + print("devcmd: '%s'", t->args[0]); + + nfd = getdtablesize(); + for(i = 0; i < nfd; i++) + if(i != t->fd[0] && i != t->fd[1] && i != t->fd[2] && i != t->wfd) + close(i); + + dup2(t->fd[0], 0); + dup2(t->fd[1], 1); + dup2(t->fd[2], 2); + close(t->fd[0]); + close(t->fd[1]); + close(t->fd[2]); + + /* should have an auth file to do host-specific authorisation? */ + if(t->gid != -1){ + if(setgid(t->gid) < 0 && getegid() == 0){ + fprint(t->wfd, "can't set gid %d: %s", t->gid, strerror(errno)); + _exit(1); + } + } + + if(t->uid != -1){ + if(setuid(t->uid) < 0 && geteuid() == 0){ + fprint(t->wfd, "can't set uid %d: %s", t->uid, strerror(errno)); + _exit(1); + } + } + + if(t->dir != nil && chdir(t->dir) < 0){ + fprint(t->wfd, "can't chdir to %s: %s", t->dir, strerror(errno)); + _exit(1); + } + + signal(SIGPIPE, SIG_DFL); + + execvp(t->args[0], t->args); + if(Debug) + print("execvp: %s\n",strerror(errno)); + fprint(t->wfd, "exec failed: %s", strerror(errno)); + + _exit(1); +} + +void* +oscmd(char **args, int nice, char *dir, int *fd) +{ + Targ *t; + int r, fd0[2], fd1[2], fd2[2], wfd[2], n, pid; + + t = mallocz(sizeof(*t), 1); + if(t == nil) + return nil; + + fd0[0] = fd0[1] = -1; + fd1[0] = fd1[1] = -1; + fd2[0] = fd2[1] = -1; + wfd[0] = wfd[1] = -1; + if(pipe(fd0) < 0 || pipe(fd1) < 0 || pipe(fd2) < 0 || pipe(wfd) < 0) + goto Error; + if(fcntl(wfd[1], F_SETFD, FD_CLOEXEC) < 0) /* close on exec to give end of file on success */ + goto Error; + + t->fd[0] = fd0[0]; + t->fd[1] = fd1[1]; + t->fd[2] = fd2[1]; + t->wfd = wfd[1]; + t->args = args; + t->dir = dir; + t->gid = up->env->gid; + if(t->gid == -1) + t->gid = gidnobody; + t->uid = up->env->uid; + if(t->uid == -1) + t->uid = uidnobody; + + signal(SIGCHLD, SIG_DFL); + switch(pid = fork()) { + case -1: + goto Error; + case 0: + setpgid(0, getpid()); + if(nice) + oslopri(); + childproc(t); + _exit(1); + default: + t->pid = pid; + if(Debug) + print("cmd pid %d\n", t->pid); + break; + } + + close(fd0[0]); + close(fd1[1]); + close(fd2[1]); + close(wfd[1]); + + n = read(wfd[0], up->genbuf, sizeof(up->genbuf)-1); + close(wfd[0]); + if(n > 0){ + close(fd0[1]); + close(fd1[0]); + close(fd2[0]); + free(t); + up->genbuf[n] = 0; + if(Debug) + print("oscmd: bad exec: %q\n", up->genbuf); + error(up->genbuf); + return nil; + } + + fd[0] = fd0[1]; + fd[1] = fd1[0]; + fd[2] = fd2[0]; + return t; + +Error: + r = errno; + if(Debug) + print("oscmd: %q\n",strerror(r)); + close(fd0[0]); + close(fd0[1]); + close(fd1[0]); + close(fd1[1]); + close(fd2[0]); + close(fd2[1]); + close(wfd[0]); + close(wfd[1]); + error(strerror(r)); + return nil; +} + +int +oscmdkill(void *a) +{ + Targ *t = a; + + if(Debug) + print("kill: %d\n", t->pid); + return kill(-t->pid, SIGTERM); +} + +int +oscmdwait(void *a, char *buf, int n) +{ + Targ *t = a; + int s; + + if(waitpid(t->pid, &s, 0) == -1){ + if(Debug) + print("wait error: %d [in %d] %q\n", t->pid, getpid(), strerror(errno)); + return -1; + } + if(WIFEXITED(s)){ + if(WEXITSTATUS(s) == 0) + return snprint(buf, n, "%d 0 0 0 ''", t->pid); + return snprint(buf, n, "%d 0 0 0 'exit: %d'", t->pid, WEXITSTATUS(s)); + } + if(WIFSIGNALED(s)){ + if(WTERMSIG(s) == SIGTERM || WTERMSIG(s) == SIGKILL) + return snprint(buf, n, "%d 0 0 0 killed", t->pid); + return snprint(buf, n, "%d 0 0 0 'signal: %d'", t->pid, WTERMSIG(s)); + } + return snprint(buf, n, "%d 0 0 0 'odd status: 0x%x'", t->pid, s); +} + +void +oscmdfree(void *a) +{ + free(a); +} diff --git a/emu/OpenBSD/deveia.c b/emu/OpenBSD/deveia.c new file mode 100644 index 00000000..2ef622f7 --- /dev/null +++ b/emu/OpenBSD/deveia.c @@ -0,0 +1,39 @@ +/* + * FreeBSD serial port definitions + */ + +static char *sysdev[] = { + "/dev/cuaa0", + "/dev/cuaa1", + "/dev/cuaa2", + "/dev/cuaa3", +}; + +#include <sys/ioctl.h> +#include "deveia-posix.c" +#include "deveia-bsd.c" + + +static struct tcdef_t bps[] = { + {0, B0}, + {50, B50}, + {75, B75}, + {110, B110}, + {134, B134}, + {150, B150}, + {200, B200}, + {300, B300}, + {600, B600}, + {1200, B1200}, + {1800, B1800}, + {2400, B2400}, + {4800, B4800}, + {9600, B9600}, + {19200, B19200}, + {38400, B38400}, + {57600, B57600}, + {115200, B115200}, + {230400, B230400}, + {-1, -1} +}; + diff --git a/emu/OpenBSD/devfs.c b/emu/OpenBSD/devfs.c new file mode 100644 index 00000000..9017c3fc --- /dev/null +++ b/emu/OpenBSD/devfs.c @@ -0,0 +1 @@ +#include "devfs-posix.c" diff --git a/emu/OpenBSD/emu b/emu/OpenBSD/emu new file mode 100644 index 00000000..5130db7c --- /dev/null +++ b/emu/OpenBSD/emu @@ -0,0 +1,106 @@ +dev + root + cons + env + mnt + pipe + prog + prof + srv + dup + ssl + cap + fs + cmd cmd + indir + + draw + pointer + snarf + + ip ipif ipaux + eia + audio audio + mem + +lib + interp + tk + freetype + math + draw + + memlayer + memdraw + keyring + sec + mp + + 9 + +link + +mod + sys + draw + + tk + math + srv srv + keyring + loader + freetype + +port + alloc + cache + chan + dev + dial + dis + discall + env + error + errstr + exception + exportfs + inferno + latin1 + main + parse + pgrp + print + proc + qio + random + sysfile + uqid + +code + +init + emuinit + +root + /dev / + /fd / + /prog / + /net / + /net.alt / + /chan / + /nvfs / + /env / +# /chan +# /dev +# /dis +# /env +# /n +# /net +# /nvfs / +# /prog +# /icons +# /osinit.dis +# /dis/emuinit.dis +# /dis/lib/auth.dis +# /dis/lib/ssl.dis +# /n/local / diff --git a/emu/OpenBSD/ipif.c b/emu/OpenBSD/ipif.c new file mode 100644 index 00000000..853e2e93 --- /dev/null +++ b/emu/OpenBSD/ipif.c @@ -0,0 +1,372 @@ +#include <sys/types.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <net/if.h> +#include <net/if_arp.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <netdb.h> +#include "dat.h" +#include "fns.h" +#include "ip.h" +#include "error.h" +#include <sys/ioctl.h> + +int +so_socket(int type) +{ + int fd, one; + + switch(type) { + default: + error("bad protocol type"); + case S_TCP: + type = SOCK_STREAM; + break; + case S_UDP: + type = SOCK_DGRAM; + break; + } + + fd = socket(AF_INET, type, 0); + if(fd < 0) + oserror(); + if(type == SOCK_DGRAM){ + one = 1; + setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char*)&one, sizeof (one)); + }else{ + one = 1; + setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)); + } + return fd; +} + +int +so_send(int sock, void *va, int len, void *hdr, int hdrlen) +{ + int r; + struct sockaddr sa; + struct sockaddr_in *sin; + char *h = hdr; + + + osenter(); + if(hdr == 0) + r = write(sock, va, len); + else { + memset(&sa, sizeof(sa), 0); + sin = (struct sockaddr_in*)&sa; + sin->sin_family = AF_INET; + switch(hdrlen){ + case OUdphdrlenv4: + memmove(&sin->sin_addr, h, 4); + memmove(&sin->sin_port, h+8, 2); + break; + case OUdphdrlen: + v6tov4((uchar*)&sin->sin_addr, h); + memmove(&sin->sin_port, h+2*IPaddrlen, 2); /* rport */ + break; + default: + v6tov4((uchar*)&sin->sin_addr, h); + memmove(&sin->sin_port, h+3*IPaddrlen, 2); + break; + } + r = sendto(sock, va, len, 0, &sa, sizeof(sa)); + } + osleave(); + return r; +} + +int +so_recv(int sock, void *va, int len, void *hdr, int hdrlen) +{ + int r, l; + struct sockaddr sa; + struct sockaddr_in *sin; + char h[Udphdrlen]; + + + osenter(); + if(hdr == 0) + r = read(sock, va, len); + else { + sin = (struct sockaddr_in*)&sa; + l = sizeof(sa); + r = recvfrom(sock, va, len, 0, &sa, &l); + if(r >= 0) { + memset(h, sizeof h, 0); + switch(hdrlen){ + case OUdphdrlenv4: + memmove(h, &sin->sin_addr, 4); + memmove(h+2*IPv4addrlen, &sin->sin_port, 2); + break; + case OUdphdrlen: + v4tov6(h, (uchar*)&sin->sin_addr); + memmove(h+2*IPaddrlen, &sin->sin_port, 2); + break; + default: + v4tov6(h, (uchar*)&sin->sin_addr); + memmove(h+3*IPaddrlen, &sin->sin_port, 2); + break; + } + + /* alas there's no way to get the local addr/port correctly. Pretend. */ + getsockname(sock, &sa, &l); + switch(hdrlen){ + case OUdphdrlenv4: + memmove(h+IPv4addrlen, &sin->sin_addr, IPv4addrlen); + memmove(h+2*IPv4addrlen+2, &sin->sin_port, 2); + break; + case OUdphdrlen: + v4tov6(h+IPaddrlen, (uchar*)&sin->sin_addr); + memmove(h+2*IPaddrlen+2, &sin->sin_port, 2); + break; + default: + v4tov6(h+IPaddrlen, (uchar*)&sin->sin_addr); + v4tov6(h+2*IPaddrlen, (uchar*)&sin->sin_addr); /* ifcaddr */ + memmove(h+3*IPaddrlen+2, &sin->sin_port, 2); + break; + } + memmove(hdr, h, hdrlen); + } + } + osleave(); + return r; +} + +void +so_close(int sock) +{ + close(sock); +} + +void +so_connect(int fd, unsigned long raddr, unsigned short rport) +{ + int r; + struct sockaddr sa; + struct sockaddr_in *sin; + + memset(&sa, 0, sizeof(sa)); + sin = (struct sockaddr_in*)&sa; + sin->sin_family = AF_INET; + hnputs(&sin->sin_port, rport); + hnputl(&sin->sin_addr.s_addr, raddr); + + osenter(); + r = connect(fd, &sa, sizeof(sa)); + osleave(); + if(r < 0) + oserror(); +} + +void +so_getsockname(int fd, unsigned long *laddr, unsigned short *lport) +{ + int len; + struct sockaddr sa; + struct sockaddr_in *sin; + + + len = sizeof(sa); + if(getsockname(fd, &sa, &len) < 0) + oserror(); + + sin = (struct sockaddr_in*)&sa; + if(sin->sin_family != AF_INET || len != sizeof(*sin)) + error("not AF_INET"); + + *laddr = nhgetl(&sin->sin_addr.s_addr); + *lport = nhgets(&sin->sin_port); +} + +void +so_listen(int fd) +{ + int r; + + osenter(); + r = listen(fd, 5); + osleave(); + if(r < 0) + oserror(); +} + +int +so_accept(int fd, unsigned long *raddr, unsigned short *rport) +{ + int nfd, len; + struct sockaddr sa; + struct sockaddr_in *sin; + + sin = (struct sockaddr_in*)&sa; + + len = sizeof(sa); + osenter(); + nfd = accept(fd, &sa, &len); + osleave(); + if(nfd < 0) + oserror(); + + if(sin->sin_family != AF_INET || len != sizeof(*sin)) + error("not AF_INET"); + + *raddr = nhgetl(&sin->sin_addr.s_addr); + *rport = nhgets(&sin->sin_port); + return nfd; +} + +void +so_bind(int fd, int su, unsigned long addr, unsigned short port) +{ + int i, one; + struct sockaddr sa; + struct sockaddr_in *sin; + + sin = (struct sockaddr_in*)&sa; + + one = 1; + if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0) { + oserrstr(up->genbuf, sizeof(up->genbuf)); + print("setsockopt: %s", up->genbuf); + } + + if(su) { + for(i = 600; i < 1024; i++) { + memset(&sa, 0, sizeof(sa)); + sin->sin_family = AF_INET; + hnputl(&sin->sin_addr.s_addr, addr); + hnputs(&sin->sin_port, i); + + if(bind(fd, &sa, sizeof(sa)) >= 0) + return; + } + oserror(); + } + + memset(&sa, 0, sizeof(sa)); + sin->sin_family = AF_INET; + hnputl(&sin->sin_addr.s_addr, addr); + hnputs(&sin->sin_port, port); + + if(bind(fd, &sa, sizeof(sa)) < 0) + oserror(); +} + +void +so_setsockopt(int fd, int opt, int value) +{ + int r; + struct linger l; + + if(opt == SO_LINGER){ + l.l_onoff = 1; + l.l_linger = (short) value; + osenter(); + r = setsockopt(fd, SOL_SOCKET, opt, (char *)&l, sizeof(l)); + osleave(); + }else + error(Ebadctl); + if(r < 0) + oserror(); +} + +int +so_gethostbyname(char *host, char**hostv, int n) +{ + int i; + char buf[32]; + uchar *p; + struct hostent *hp; + + hp = gethostbyname(host); + if(hp == 0) + return 0; + + for(i = 0; hp->h_addr_list[i] && i < n; i++) { + p = hp->h_addr_list[i]; + snprint(buf, sizeof(buf), "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]); + hostv[i] = strdup(buf); + if(hostv[i] == 0) + break; + } + return i; +} + +int +so_gethostbyaddr(char *addr, char **hostv, int n) +{ + int i; + struct hostent *hp; + unsigned long straddr; + + straddr = inet_addr(addr); + if(straddr == -1) + return 0; + + hp = gethostbyaddr((char *)&straddr, sizeof(straddr), AF_INET); + if(hp == 0) + return 0; + + hostv[0] = strdup(hp->h_name); + if(hostv[0] == 0) + return 0; + for(i = 1; hp->h_aliases[i-1] && i < n; i++) { + hostv[i] = strdup(hp->h_aliases[i-1]); + if(hostv[i] == 0) + break; + } + return i; +} + +int +so_getservbyname(char *service, char *net, char *port) +{ + ushort p; + struct servent *s; + + s = getservbyname(service, net); + if(s == 0) + return -1; + p = s->s_port; + sprint(port, "%d", nhgets(&p)); + return 0; +} + +int +so_hangup(int fd, int linger) +{ + int r; + static struct linger l = {1, 1000}; + + osenter(); + if(linger) + setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&l, sizeof(l)); + r = shutdown(fd, 2); + if(r >= 0) + r = close(fd); + osleave(); + return r; +} + +void +arpadd(char *ipaddr, char *eaddr, int n) +{ + error("arp not implemented"); +} + +int +so_mustbind(int restricted, int port) +{ + return restricted || port != 0; +} + +void +so_keepalive(int fd, int ms) +{ + int on; + + USED(ms); + on = 1; + setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&on, sizeof(on)); +} diff --git a/emu/OpenBSD/mkfile b/emu/OpenBSD/mkfile new file mode 100644 index 00000000..ad4e3155 --- /dev/null +++ b/emu/OpenBSD/mkfile @@ -0,0 +1,45 @@ +<../../mkconfig +SYSTARG=OpenBSD +OBJTYPE=386 + +#Configurable parameters + +CONF=emu #default configuration +CONFLIST=emu +CLEANCONFLIST= + +INSTALLDIR=$ROOT/$SYSTARG/$OBJTYPE/bin #path of directory where kernel is installed + +#end configurable parameters + +<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE #set vars based on target system + +<| $SHELLNAME ../port/mkdevlist $CONF #sets $IP, $DEVS, $PORT, $LIBS + +OBJ=\ + asm-$OBJTYPE.$O\ + os.$O\ + win-x11a.$O\ + $CONF.root.$O\ + lock.$O\ + $DEVS\ + $PORT\ + +HFILES=\ + +CFLAGS='-DROOT="'$ROOT'"' -DEMU -I. -I../port -I$ROOT/$SYSTARG/$OBJTYPE/include -I$ROOT/include -I$ROOT/libinterp $CTHREADFLAGS $CFLAGS $EMUOPTIONS +SYSLIBS= -lm -lX11 -lXext -lossaudio +KERNDATE=`{$NDATE} + +default:V: $O.$CONF + +<../port/portmkfile + +$O.$CONF: $OBJ $CONF.c $CONF.root.h $LIBFILES + $CC $CFLAGS '-DKERNDATE='$KERNDATE $CONF.c + $LD $LDFLAGS -o $target $OBJ $CONF.$O $LIBFILES $SYSLIBS + +install:V: $O.$CONF + cp $O.$CONF $INSTALLDIR/$CONF + +devfs.$O: ../port/devfs-posix.c diff --git a/emu/OpenBSD/mkfile-OpenBSD b/emu/OpenBSD/mkfile-OpenBSD new file mode 100644 index 00000000..d1278ec4 --- /dev/null +++ b/emu/OpenBSD/mkfile-OpenBSD @@ -0,0 +1,17 @@ +# +# architecture-dependent files for OpenBSD +# + +LDFLAGS= + +TARGFILES=devfs-posix.$O\ + deveia-OpenBSD.$O\ + devip.$O\ + ipif-posix.$O\ + os-OpenBSD.$O\ + win-x11.$O\ + srv.$O\ + lock.$O\ + asm-OpenBSD-$OBJTYPE.$O + +SYSLIBS=/usr/X11R6/lib/libX11.a -lm diff --git a/emu/OpenBSD/os.c b/emu/OpenBSD/os.c new file mode 100644 index 00000000..2dd4c4d1 --- /dev/null +++ b/emu/OpenBSD/os.c @@ -0,0 +1,524 @@ +#include "dat.h" +#include "fns.h" +#include "error.h" +#undef getwd +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/param.h> +#include <sys/resource.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <signal.h> +#include <time.h> +#include <termios.h> +#include <sched.h> +#include <pwd.h> +#include <errno.h> +#include <unistd.h> + +enum +{ + DELETE = 0x7F, + NSTACKSPERALLOC = 16, + X11STACK= 256*1024 +}; +char *hosttype = "OpenBSD"; + +int rfork_thread(int, void *, void (*)(void *), void *); + +extern void unlockandexit(int*); +extern void executeonnewstack(void*, void (*f)(void*), void*); +static void *stackalloc(Proc *p, void **tos); +static void stackfreeandexit(void *stack); + +extern int dflag; + +void +pexit(char *msg, int t) +{ + Osenv *e; + Proc *p; + void *kstack; + + lock(&procs.l); + p = up; + if(p->prev) + p->prev->next = p->next; + else + procs.head = p->next; + + if(up->next) + p->next->prev = p->prev; + else + procs.tail = p->prev; + unlock(&procs.l); + + if(0) + print("pexit: %s: %s\n", up->text, msg); + + e = up->env; + if(e != nil) { + closefgrp(e->fgrp); + closepgrp(e->pgrp); + closeegrp(e->egrp); + closesigs(e->sigs); + } + kstack = p->kstack; + free(p->prog); + free(p); + if(kstack != nil) + stackfreeandexit(kstack); +} + +void +trapBUS(int signo, siginfo_t *info, void *context) +{ + if(info) + print("trapBUS: signo: %d code: %d addr: %lx\n", + info->si_signo, info->si_code, info->si_addr); + else + print("trapBUS: no info\n"); + disfault(nil, "Bus error"); +} + +static void +trapUSR1(int signo) +{ + int intwait; + + USED(signo); + + intwait = up->intwait; + up->intwait = 0; /* clear it to let proc continue in osleave */ + + if(up->type != Interp) /* Used to unblock pending I/O */ + return; + if(intwait == 0) /* Not posted so its a sync error */ + disfault(nil, Eintr); /* Should never happen */ +} + +static void +trapUSR2(int signo) +{ + USED(signo); + /* we've done our work of interrupting sigsuspend */ +} + +static void +trapILL(int signo) +{ + disfault(nil, "Illegal instruction"); +} + +static void +trapSEGV(int signo) +{ + disfault(nil, "Segmentation violation"); +} + +static sigset_t initmask; + +static void +setsigs(void) +{ + struct sigaction act; + sigset_t mask; + + memset(&act, 0 , sizeof(act)); + sigemptyset(&initmask); + + signal(SIGPIPE, SIG_IGN); /* prevent signal when devcmd child exits */ + if(signal(SIGTERM, SIG_IGN) != SIG_IGN) + signal(SIGTERM, cleanexit); + + act.sa_handler = trapUSR1; + act.sa_mask = initmask; + sigaction(SIGUSR1, &act, nil); + + act.sa_handler = trapUSR2; + sigaction(SIGUSR2, &act, nil); + sigemptyset(&mask); + sigaddset(&mask, SIGUSR2); + sigaddset(&initmask, SIGUSR2); + sigprocmask(SIG_BLOCK, &mask, NULL); + + /* + * prevent Zombies forming when any process terminates + */ + act.sa_sigaction = 0; + act.sa_flags |= SA_NOCLDWAIT; + if(sigaction(SIGCHLD, &act, nil)) + panic("sigaction SIGCHLD"); + + if(sflag == 0) { + act.sa_sigaction = trapBUS; + act.sa_flags |= SA_SIGINFO; + if(sigaction(SIGBUS, &act, nil)) + panic("sigaction SIGBUS"); + act.sa_handler = trapILL; + if(sigaction(SIGILL, &act, nil)) + panic("sigaction SIGBUS"); + act.sa_handler = trapSEGV; + if(sigaction(SIGSEGV, &act, nil)) + panic("sigaction SIGSEGV"); + if(sigaddset(&initmask, SIGINT) == -1) + panic("sigaddset"); + } + if(sigprocmask(SIG_BLOCK, &initmask, nil)!= 0) + panic("sigprocmask"); +} + +static void +tramp(void *arg) +{ + Proc *p; + + p = arg; + p->pid = p->sigid = getpid(); + sigprocmask(SIG_BLOCK, &initmask, nil); /* in 5.3, rfork_thread doesn't copy from parent, contrary to docs? */ + (*p->func)(p->arg); + pexit("{Tramp}", 0); + _exit(0); +} + +int +kproc(char *name, void (*func)(void*), void *arg, int flags) +{ + Proc *p; + Pgrp *pg; + Fgrp *fg; + Egrp *eg; + int pid; + void *tos; + + p = newproc(); + + if(flags & KPDUPPG) { + pg = up->env->pgrp; + incref(&pg->r); + p->env->pgrp = pg; + } + if(flags & KPDUPFDG) { + fg = up->env->fgrp; + incref(&fg->r); + p->env->fgrp = fg; + } + if(flags & KPDUPENVG) { + eg = up->env->egrp; + incref(&eg->r); + p->env->egrp = eg; + } + + p->env->uid = up->env->uid; + p->env->gid = up->env->gid; + kstrdup(&p->env->user, up->env->user); + + strcpy(p->text, name); + + p->func = func; + p->arg = arg; + + lock(&procs.l); + if(procs.tail != nil) { + p->prev = procs.tail; + procs.tail->next = p; + } + else { + procs.head = p; + p->prev = nil; + } + procs.tail = p; + unlock(&procs.l); + + if(flags & KPX11){ + p->kstack = nil; /* never freed; also up not defined */ + tos = (char*)mallocz(X11STACK, 0) + X11STACK - sizeof(void*); + }else + p->kstack = stackalloc(p, &tos); + pid = rfork_thread(RFPROC|RFMEM|RFNOWAIT, tos, tramp, p); + if(pid < 0) + panic("ourfork"); + + return pid; + +} + +void +oshostintr(Proc *p) +{ + kill(p->sigid, SIGUSR1); +} + +void +osblock(void) +{ + sigset_t mask; + + sigprocmask(SIG_SETMASK, NULL, &mask); + sigdelset(&mask, SIGUSR2); + sigsuspend(&mask); +} + +void +osready(Proc *p) +{ + if(kill(p->sigid, SIGUSR2) < 0) + fprint(2, "emu: osready failed: pid %d: %s\n", p->sigid, strerror(errno)); +} + +void +oslongjmp(void *regs, osjmpbuf env, int val) +{ + USED(regs); + siglongjmp(env, val); +} + +struct termios tinit; + +static void +termset(void) +{ + struct termios t; + + tcgetattr(0, &t); + tinit = t; + t.c_lflag &= ~(ICANON|ECHO|ISIG); + t.c_cc[VMIN] = 1; + t.c_cc[VTIME] = 0; + tcsetattr(0, TCSANOW, &t); +} + +static void +termrestore(void) +{ + tcsetattr(0, TCSANOW, &tinit); +} + +void +cleanexit(int x) +{ + USED(x); + + if(up->intwait) { + up->intwait = 0; + return; + } + + if(dflag == 0) + termrestore(); + + kill(0, SIGKILL); + exit(0); +} + +void +osreboot(char *file, char **argv) +{ + if(dflag == 0) + termrestore(); + execvp(file, argv); + panic("reboot failure"); +} + +int gidnobody= -1, uidnobody= -1; + +void +getnobody() +{ + struct passwd *pwd; + + if(pwd = getpwnam("nobody")) { + uidnobody = pwd->pw_uid; + gidnobody = pwd->pw_gid; + } +} + +void +libinit(char *imod) +{ + struct passwd *pw; + Proc *p; + void *tos; + char sys[64]; + + setsid(); + + gethostname(sys, sizeof(sys)); + kstrdup(&ossysname, sys); + getnobody(); + + if(dflag == 0) + termset(); + + setsigs(); + + p = newproc(); + p->kstack = stackalloc(p, &tos); + + pw = getpwuid(getuid()); + if(pw != nil) + kstrdup(&eve, pw->pw_name); + else + print("cannot getpwuid\n"); + + p->env->uid = getuid(); + p->env->gid = getgid(); + + executeonnewstack(tos, emuinit, imod); +} + +int +readkbd(void) +{ + int n; + char buf[1]; + + n = read(0, buf, sizeof(buf)); + if(n < 0) + print("keyboard close (n=%d, %s)\n", n, strerror(errno)); + if(n <= 0) + pexit("keyboard thread", 0); + + switch(buf[0]) { + case '\r': + buf[0] = '\n'; + break; + case DELETE: + cleanexit(0); + break; + } + return buf[0]; +} + +/* + * Return an abitrary millisecond clock time + */ +long +osmillisec(void) +{ + static long sec0 = 0, usec0; + struct timeval t; + + if(gettimeofday(&t,(struct timezone*)0)<0) + return 0; + if(sec0==0) { + sec0 = t.tv_sec; + usec0 = t.tv_usec; + } + return (t.tv_sec-sec0)*1000+(t.tv_usec-usec0+500)/1000; +} + +int +limbosleep(ulong milsec) +{ + return osmillisleep(milsec); +} + +/* + * Return the time since the epoch in nanoseconds and microseconds + * The epoch is defined at 1 Jan 1970 + */ +vlong +osnsec(void) +{ + struct timeval t; + + gettimeofday(&t, nil); + return (vlong)t.tv_sec*1000000000L + t.tv_usec*1000; +} + +vlong +osusectime(void) +{ + struct timeval t; + + gettimeofday(&t, nil); + return (vlong)t.tv_sec * 1000000 + t.tv_usec; +} + +int +osmillisleep(ulong milsec) +{ + struct timespec time; + + time.tv_sec = milsec / 1000; + time.tv_nsec = (milsec % 1000) * 1000000; + nanosleep(&time, 0); + return 0; +} + +void +osyield(void) +{ + sched_yield(); +} + +void +ospause(void) +{ + for(;;) + pause(); +} + +void +oslopri(void) +{ + setpriority(PRIO_PROCESS, 0, getpriority(PRIO_PROCESS,0)+4); +} + +static struct { + Lock l; + void *free; +} stacklist; + +static void +_stackfree(void *stack) +{ + *((void **)stack) = stacklist.free; + stacklist.free = stack; +} + +static void +stackfreeandexit(void *stack) +{ + lock(&stacklist.l); + _stackfree(stack); + unlockandexit(&stacklist.l.val); +} + +static void * +stackalloc(Proc *p, void **tos) +{ + void *rv; + lock(&stacklist.l); + if (stacklist.free == 0) { + int x; + /* + * obtain some more by using sbrk() + */ + void *more = sbrk(KSTACK * (NSTACKSPERALLOC + 1)); + if (more == 0) + panic("stackalloc: no more stacks"); + /* + * align to KSTACK + */ + more = (void *)((((unsigned long)more) + (KSTACK - 1)) & ~(KSTACK - 1)); + /* + * free all the new stacks onto the freelist + */ + for (x = 0; x < NSTACKSPERALLOC; x++) + _stackfree((char *)more + KSTACK * x); + } + rv = stacklist.free; + stacklist.free = *(void **)rv; + unlock(&stacklist.l); + *tos = rv + KSTACK - sizeof(void*); + *(Proc **)rv = p; + return rv; +} + +int +segflush(void *p, ulong n) +{ + return mprotect(p, n, PROT_EXEC|PROT_READ|PROT_WRITE); +} diff --git a/emu/OpenBSD/rfork_thread.S b/emu/OpenBSD/rfork_thread.S new file mode 100644 index 00000000..bb7cd010 --- /dev/null +++ b/emu/OpenBSD/rfork_thread.S @@ -0,0 +1,104 @@ +/*- + * Copyright (c) 2000 Peter Wemm <peter@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * 8 12 16 20 + * rfork_thread(flags, stack_addr, start_fnc, start_arg); + * + * flags: Flags to rfork system call. See rfork(2). + * stack_addr: Top of stack for thread. + * start_fnc: Address of thread function to call in child. + * start_arg: Argument to pass to the thread function in child. + */ + +ENTRY(rfork_thread) + pushl %ebp + movl %esp, %ebp + pushl %esi + + /* + * Push thread info onto the new thread's stack + */ + movl 12(%ebp), %esi # get stack addr + + subl $4, %esi + movl 20(%ebp), %eax # get start argument + movl %eax, (%esi) + + subl $4, %esi + movl 16(%ebp), %eax # get start thread address + movl %eax, (%esi) + + /* + * Prepare and execute the thread creation syscall + */ + pushl 8(%ebp) + pushl $0 + movl $SYS_rfork, %eax + int $0x80 + jb 2f + + /* + * Check to see if we are in the parent or child + */ + cmpl $0, %edx + jnz 1f + addl $8, %esp + popl %esi + movl %ebp, %esp + popl %ebp + ret + .p2align 2 + + /* + * If we are in the child (new thread), then + * set-up the call to the internal subroutine. If it + * returns, then call __exit. + */ +1: + movl %esi,%esp + popl %eax + call *%eax + addl $4, %esp + + /* + * Exit system call + */ + pushl %eax + pushl $0 + movl $SYS_threxit, %eax + int $0x80 + + /* + * Branch here if the thread creation fails: + */ +2: + addl $8, %esp + popl %esi + movl %ebp, %esp + popl %ebp + PIC_PROLOGUE + jmp PIC_PLT(_C_LABEL(__cerror)) diff --git a/lib9/getcallerpc-OpenBSD-386.S b/lib9/getcallerpc-OpenBSD-386.S new file mode 100644 index 00000000..edf1fd61 --- /dev/null +++ b/lib9/getcallerpc-OpenBSD-386.S @@ -0,0 +1,7 @@ + .file "getcallerpc-OpenBSD-386.S" + + .type getcallerpc,@function + .global getcallerpc +getcallerpc: + movl 4(%ebp), %eax + ret diff --git a/libmath/FPcontrol-OpenBSD.c b/libmath/FPcontrol-OpenBSD.c new file mode 100644 index 00000000..a4419c8f --- /dev/null +++ b/libmath/FPcontrol-OpenBSD.c @@ -0,0 +1,78 @@ +#include "lib9.h" +#include "fpuctl.h" +#include "mathi.h" + +void +FPinit(void) +{ + setfsr(0); /* Clear pending exceptions */ + setfcr(FPPDBL|FPRNR|FPINVAL|FPZDIV|FPUNFL|FPOVFL); +} + +ulong +getFPstatus(void) +{ + ulong fsr = 0, fsr9 = getfsr(); + /* on specific machines, could be table lookup */ + if(fsr9&FPAINEX) fsr |= INEX; + if(fsr9&FPAOVFL) fsr |= OVFL; + if(fsr9&FPAUNFL) fsr |= UNFL; + if(fsr9&FPAZDIV) fsr |= ZDIV; + if(fsr9&FPAINVAL) fsr |= INVAL; + return fsr; +} + +ulong +FPstatus(ulong fsr, ulong mask) +{ + ulong fsr9 = 0; + ulong old = getFPstatus(); + fsr = (fsr&mask) | (old&~mask); + if(fsr&INEX) fsr9 |= FPAINEX; + if(fsr&OVFL) fsr9 |= FPAOVFL; + if(fsr&UNFL) fsr9 |= FPAUNFL; + if(fsr&ZDIV) fsr9 |= FPAZDIV; + if(fsr&INVAL) fsr9 |= FPAINVAL; + setfsr(fsr9); + return(old&mask); +} + +ulong +getFPcontrol(void) +{ + ulong fcr = 0, fcr9 = getfcr(); + switch(fcr9&FPRMASK){ + case FPRNR: fcr = RND_NR; break; + case FPRNINF: fcr = RND_NINF; break; + case FPRPINF: fcr = RND_PINF; break; + case FPRZ: fcr = RND_Z; break; + } + if(fcr9&FPINEX) fcr |= INEX; + if(fcr9&FPOVFL) fcr |= OVFL; + if(fcr9&FPUNFL) fcr |= UNFL; + if(fcr9&FPZDIV) fcr |= ZDIV; + if(fcr9&FPINVAL) fcr |= INVAL; + return fcr; +} + +ulong +FPcontrol(ulong fcr, ulong mask) +{ + ulong fcr9 = FPPDBL; + ulong old = getFPcontrol(); + fcr = (fcr&mask) | (old&~mask); + if(fcr&INEX) fcr9 |= FPINEX; + if(fcr&OVFL) fcr9 |= FPOVFL; + if(fcr&UNFL) fcr9 |= FPUNFL; + if(fcr&ZDIV) fcr9 |= FPZDIV; + if(fcr&INVAL) fcr9 |= FPINVAL; + switch(fcr&RND_MASK){ + case RND_NR: fcr9 |= FPRNR; break; + case RND_NINF: fcr9 |= FPRNINF; break; + case RND_PINF: fcr9 |= FPRPINF; break; + case RND_Z: fcr9 |= FPRZ; break; + } + setfcr(fcr9); + return(old&mask); +} + diff --git a/libmemdraw/mkfile-OpenBSD b/libmemdraw/mkfile-OpenBSD new file mode 100644 index 00000000..f00ef4c1 --- /dev/null +++ b/libmemdraw/mkfile-OpenBSD @@ -0,0 +1,4 @@ +# +# Object files specific for Nt +# +<mkfile-Inferno diff --git a/libmemlayer/mkfile-OpenBSD b/libmemlayer/mkfile-OpenBSD new file mode 100644 index 00000000..d772cd4e --- /dev/null +++ b/libmemlayer/mkfile-OpenBSD @@ -0,0 +1,4 @@ +# +# System dependent objects for Posix model systems +# +SYSFILES=lalloc.$O diff --git a/mkfiles/mkfile-OpenBSD-386 b/mkfiles/mkfile-OpenBSD-386 new file mode 100644 index 00000000..fcbc45b2 --- /dev/null +++ b/mkfiles/mkfile-OpenBSD-386 @@ -0,0 +1,30 @@ +TARGMODEL= Posix +TARGSHTYPE= sh +CPUS= 386 + +O= o +OS= o + +AR= ar +ARFLAGS= ruvs + +AS= cc -c +ASFLAGS= + +CC= cc -c +CFLAGS= -g\ + -O\ + -Wno-deprecated-declarations -Wuninitialized -Wunused -Wreturn-type -Wimplicit\ + -I$ROOT/OpenBSD/386/include\ + -I$ROOT/include\ + -I/usr/X11R6/include\ + -DOPENBSD_386 -fno-stack-protector + +ANSICPP= +LD= cc +LDFLAGS= -L/usr/X11R6/lib + +SYSLIBS= + +YACC= yacc +YFLAGS= -d diff --git a/mkfiles/mkhost-OpenBSD b/mkfiles/mkhost-OpenBSD new file mode 100644 index 00000000..784af9c9 --- /dev/null +++ b/mkfiles/mkhost-OpenBSD @@ -0,0 +1,19 @@ + +# Variables for host system type = OpenBSD + +SHELLTYPE= sh +SHELLNAME= /bin/sh +HOSTMODEL= Posix +OSTARG= os + +DATA2S= data2s +NDATE= ndate +KSIZE= ksize +AWK= awk +CP= cp +ECHO= echo +FALSE= false +MKDIR= mkdir -p +RM= rm -f +RMDIR= rmdir +TRUE= true diff --git a/tools/styxtest/mkfile-OpenBSD b/tools/styxtest/mkfile-OpenBSD new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tools/styxtest/mkfile-OpenBSD |
