diff --git a/CMakeLists.txt b/CMakeLists.txt index ce128c4..18f965d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,7 @@ if(MARS_NWE_BUILD_DOSUTILS) find_package(OpenWatcom REQUIRED) set(DOSUTILS_C_SOURCES + kern.c net.c tools.c netcall.c diff --git a/kern.c b/kern.c new file mode 100644 index 0000000..0f9959f --- /dev/null +++ b/kern.c @@ -0,0 +1,182 @@ +/* + * kern.c - C-side experimental NetWare/DOS request wrapper + * + * This does NOT replace kern.asm. It adds separate functions so we can test + * register/segment handling and inspect the last call from DOS DEBUG or from + * a small debug command later. + * + * Existing assembler function stays: + * int Net_Call(unsigned int func, void *req, void *repl); + * + * New test functions: + * int KERN_CALL Net_Call_C(UI ax, void *req, void *repl); + * int Net_Call_CX(unsigned int ax, unsigned int bx, + * unsigned int cx, unsigned int dx, + * void *req, void *repl); + * void KERN_CALL Net_Call_C_Dump(void); + */ + +#include +#include +#include + +#include "net.h" + +#if defined(__WATCOMC__) +#define KERN_CALL _Cdecl +#else +#define KERN_CALL +#endif + +typedef struct { + unsigned int in_ax; + unsigned int in_bx; + unsigned int in_cx; + unsigned int in_dx; + unsigned int in_si; + unsigned int in_di; + unsigned int in_ds; + unsigned int in_es; + + unsigned int out_ax; + unsigned int out_bx; + unsigned int out_cx; + unsigned int out_dx; + unsigned int out_si; + unsigned int out_di; + unsigned int out_flags; + + void far *req_ptr; + void far *repl_ptr; + + int rc; +} NET_CALL_C_DEBUG; + +NET_CALL_C_DEBUG Net_Call_C_Last; + +/* + * Same call shape as kern.asm Net_Call, but implemented in C. + * + * This is meant for OLD known-working calls first: + * Net_Call_C(0xE200, ...) + * Net_Call_C(0xE300, ...) + * + * Do not use it blindly for NCP87 yet; the previous F257 test hung through + * the old wrapper, so we will first test old calls and register layout. + */ +int KERN_CALL Net_Call_C(UI ax, void *req, void *repl) +{ + return Net_Call_CX(ax, 0, 0, 0, req, repl); +} + +/* + * Extended variant with BX/CX/DX settable. This lets us experiment without + * changing kern.asm every time. + */ +int KERN_CALL Net_Call_CX(UI ax, UI bx, + UI cx, UI dx, + void *req, void *repl) +{ + union REGS inregs; + union REGS outregs; + struct SREGS segregs; + + memset(&inregs, 0, sizeof(inregs)); + memset(&outregs, 0, sizeof(outregs)); + memset(&segregs, 0, sizeof(segregs)); + memset(&Net_Call_C_Last, 0, sizeof(Net_Call_C_Last)); + + inregs.x.ax = ax; + inregs.x.bx = bx; + inregs.x.cx = cx; + inregs.x.dx = dx; + + inregs.x.si = FP_OFF(req); + inregs.x.di = FP_OFF(repl); + segregs.ds = FP_SEG(req); + segregs.es = FP_SEG(repl); + + Net_Call_C_Last.in_ax = inregs.x.ax; + Net_Call_C_Last.in_bx = inregs.x.bx; + Net_Call_C_Last.in_cx = inregs.x.cx; + Net_Call_C_Last.in_dx = inregs.x.dx; + Net_Call_C_Last.in_si = inregs.x.si; + Net_Call_C_Last.in_di = inregs.x.di; + Net_Call_C_Last.in_ds = segregs.ds; + Net_Call_C_Last.in_es = segregs.es; + Net_Call_C_Last.req_ptr = req; + Net_Call_C_Last.repl_ptr = repl; + + int86x(0x21, &inregs, &outregs, &segregs); + + Net_Call_C_Last.out_ax = outregs.x.ax; + Net_Call_C_Last.out_bx = outregs.x.bx; + Net_Call_C_Last.out_cx = outregs.x.cx; + Net_Call_C_Last.out_dx = outregs.x.dx; + Net_Call_C_Last.out_si = outregs.x.si; + Net_Call_C_Last.out_di = outregs.x.di; + Net_Call_C_Last.out_flags = outregs.x.cflag; + Net_Call_C_Last.rc = outregs.x.ax; + + return outregs.x.ax; +} + +/* + * Text dump for quick testing. Later we can expose this through DEBUG.EXE + * as "debug netcall" or similar. + */ +void KERN_CALL Net_Call_C_Dump(void) +{ + fprintf(stdout, "NETCALLC in : AX=%04X BX=%04X CX=%04X DX=%04X DS:SI=%04X:%04X ES:DI=%04X:%04X\n", + Net_Call_C_Last.in_ax, + Net_Call_C_Last.in_bx, + Net_Call_C_Last.in_cx, + Net_Call_C_Last.in_dx, + Net_Call_C_Last.in_ds, + Net_Call_C_Last.in_si, + Net_Call_C_Last.in_es, + Net_Call_C_Last.in_di); + + fprintf(stdout, "NETCALLC out: AX=%04X BX=%04X CX=%04X DX=%04X SI=%04X DI=%04X CF=%04X RC=%d\n", + Net_Call_C_Last.out_ax, + Net_Call_C_Last.out_bx, + Net_Call_C_Last.out_cx, + Net_Call_C_Last.out_dx, + Net_Call_C_Last.out_si, + Net_Call_C_Last.out_di, + Net_Call_C_Last.out_flags, + Net_Call_C_Last.rc); +} + +/* + * Optional helper for DEBUG-style commands that do not want formatted output. + * idx: + * 0 in_ax 1 in_bx 2 in_cx 3 in_dx + * 4 in_ds 5 in_si 6 in_es 7 in_di + * 8 out_ax 9 out_bx 10 out_cx 11 out_dx + * 12 out_si 13 out_di 14 out_flags 15 rc + */ +UI KERN_CALL Net_Call_C_GetDebug(UI idx) +{ + switch (idx) { + case 0: return Net_Call_C_Last.in_ax; + case 1: return Net_Call_C_Last.in_bx; + case 2: return Net_Call_C_Last.in_cx; + case 3: return Net_Call_C_Last.in_dx; + case 4: return Net_Call_C_Last.in_ds; + case 5: return Net_Call_C_Last.in_si; + case 6: return Net_Call_C_Last.in_es; + case 7: return Net_Call_C_Last.in_di; + case 8: return Net_Call_C_Last.out_ax; + case 9: return Net_Call_C_Last.out_bx; + case 10: return Net_Call_C_Last.out_cx; + case 11: return Net_Call_C_Last.out_dx; + case 12: return Net_Call_C_Last.out_si; + case 13: return Net_Call_C_Last.out_di; + case 14: return Net_Call_C_Last.out_flags; + case 15: return (unsigned int)Net_Call_C_Last.rc; + } + return 0xffff; +} + +#undef KERN_CALL diff --git a/kern.h b/kern.h index 780557a..56281b5 100644 --- a/kern.h +++ b/kern.h @@ -14,6 +14,15 @@ extern void esr_routine(ECB *ecb); extern void KERN_CALL xmemmove(void *ziel, void *quelle, UI anz); extern int KERN_CALL Net_Call(UI func, void *req, void *repl); +/* kern.c experimental C port / debug wrapper. + * These keep kern_wasm.asm Net_Call() untouched and are used for tests. + */ +extern int KERN_CALL Net_Call_C(UI func, void *req, void *repl); +extern int KERN_CALL Net_Call_CX(UI func, UI bx, UI cx, UI dx, + void *req, void *repl); +extern void KERN_CALL Net_Call_C_Dump(void); +extern UI KERN_CALL Net_Call_C_GetDebug(UI idx); + #undef KERN_CALL