/* Copyright 1990,1991,1992 Eric R. Smith. All rights reserved. */ /* * XBIOS replacement routines */ #include "mint.h" extern int tosvers; /* from main.c */ #define XBIOS_MAX 0x80 Func xbios_tab[XBIOS_MAX]; /* initially all zeros */ short xbios_max = XBIOS_MAX; /* NOTE: has_bconmap is initialized in main.c */ int has_bconmap; /* flag: set if running under a version * of TOS which supports Bconmap */ /* * Supexec() presents a lot of problems for us: for example, the user * may be calling the kernel, or may be changing interrupt vectors * unexpectedly. So we play some dirty tricks here: the function * call is treated like a signal handler, and we take advantage * of the fact that no context switches will take place while * in supervisor mode. ASSUMPTION: the user will not choose to * switch back to user mode, or if s/he does it will be as part * of a longjmp(). * * BUG: if the user function switches to user mode, then back to * supervisor mode and returns, then the returned value may be * inaccurate (this happens if two programs make Supexec calls * at the same time). */ static long (*usrcall) P_((long,long,long,long,long)); static long usrret; static long usrarg1, usrarg2, usrarg3, usrarg4, usrarg5; static void do_usrcall P_((void)); static void do_usrcall() { usrret = (*usrcall)(usrarg1, usrarg2, usrarg3, usrarg4, usrarg5); } long supexec(funcptr, arg1, arg2, arg3, arg4, arg5) Func funcptr; long arg1, arg2, arg3, arg4, arg5; { short savesr; CONTEXT *syscall = &curproc->ctxt[SYSCALL]; /* set things up so that "signal 0" will be handled by calling the user's * function. */ usrcall = funcptr; usrarg1 = arg1; usrarg2 = arg2; usrarg3 = arg3; usrarg4 = arg4; usrarg5 = arg5; curproc->sighandle[0] = (long)do_usrcall; savesr = syscall->sr; /* save old super/user mode flag */ syscall->sr |= 0x2000; /* set supervisor mode */ handle_sig(0); /* actually call out to the user function */ syscall->sr = savesr; /* do_usrcall saves the user's return value in usrret */ return usrret; } /* * midiws: we have to replace this, because it's possible that the process' * view of what the MIDI port is has been changed by Fforce or Fmidipipe */ long midiws(cnt, buf) int cnt; const char *buf; { FILEPTR *f; long towrite = cnt+1; f = curproc->handle[-5]; /* MIDI output handle */ if (!f) return EIHNDL; if (is_terminal(f)) { while (cnt >= 0) { tty_putchar(f, (long)*buf, RAW); buf++; cnt--; } return towrite; } return (*f->dev->write)(f, buf, towrite); } /* * Modem control things: these are replaced because we handle * Bconmap ourselves */ /* mapin: utility routine, does a Bconmap and keeps track * so we call the kernel only when necessary; call this * only if has_bconmap is "true". * Returns: 0 on failure, 1 on success. */ int curbconmap; int mapin(dev) int dev; { int r; if (dev == curbconmap) return 1; r = Bconmap(dev); if (r) { curbconmap = dev; return 1; } return 0; } long uiorec(dev) int dev; { TRACE("Iorec(%d)", dev); if (dev == 0 && has_bconmap) mapin(curproc->bconmap); return (long)Iorec(dev); } long rsconf(baud, flow, uc, rs, ts, sc) int baud, flow, uc, rs, ts, sc; { TRACE("Rsconf(%d,%d,%d,%d,%d,%d)", baud, flow, uc, rs, ts, sc); if (has_bconmap) mapin(curproc->bconmap); return Rsconf(baud, flow, uc, rs, ts, sc); } long bconmap(dev) int dev; { int old = curproc->bconmap; TRACE("Bconmap(%d)", dev); if (has_bconmap) { if (dev == -1) return old; if (dev == -2) return Bconmap(-2); if (mapin(dev) == 0) { DEBUG("Bconmap: mapin failed"); return 0; } if (set_auxhandle(curproc, dev) == 0) { DEBUG("Bconmap: Couldn't change AUX:"); return 0; } curproc->bconmap = dev; return old; } return EINVFN; /* no Bconmap available */ } void init_xbios() { curbconmap = (has_bconmap) ? Bconmap(-1) : 1; xbios_tab[0x0c] = midiws; xbios_tab[0x0e] = uiorec; xbios_tab[0x0f] = rsconf; xbios_tab[0x26] = supexec; xbios_tab[0x2c] = bconmap; }