From ed5da6c063bca878c17b9b26079c16ca5056aae2 Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Sat, 23 May 2026 14:23:25 +0200 Subject: [PATCH] tests --- kern.c | 183 ++++++++++++++++++++++++--------------------------------- kern.h | 13 ++-- 2 files changed, 83 insertions(+), 113 deletions(-) diff --git a/kern.c b/kern.c index 7ea5e52..3d3aa77 100644 --- a/kern.c +++ b/kern.c @@ -1,19 +1,9 @@ /* - * kern.c - C-side experimental NetWare/DOS request wrapper + * kern.c - C-side experimental NetWare/DOS request wrappers * - * 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 Net_Call_C(unsigned int 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 Net_Call_C_Dump(void); + * kern_wasm.asm remains the production/reference implementation. + * These C functions are test wrappers so we can inspect register setup and + * slowly port proven pieces from ASM to C. */ #include @@ -28,7 +18,6 @@ #define KERN_C_CALL #endif - typedef struct { unsigned int in_ax; unsigned int in_bx; @@ -55,37 +44,64 @@ typedef struct { NET_CALL_C_DEBUG Net_Call_C_Last; +static void net_call_c_clear(void) +{ + memset(&Net_Call_C_Last, 0, sizeof(Net_Call_C_Last)); +} + +static void net_call_c_save_in(union REGS *r, struct SREGS *s, + void *req, void *repl) +{ + Net_Call_C_Last.in_ax = r->x.ax; + Net_Call_C_Last.in_bx = r->x.bx; + Net_Call_C_Last.in_cx = r->x.cx; + Net_Call_C_Last.in_dx = r->x.dx; + Net_Call_C_Last.in_si = r->x.si; + Net_Call_C_Last.in_di = r->x.di; + Net_Call_C_Last.in_ds = s->ds; + Net_Call_C_Last.in_es = s->es; + Net_Call_C_Last.req_ptr = req; + Net_Call_C_Last.repl_ptr = repl; +} + +static void net_call_c_save_out(union REGS *r, unsigned int returned_ax) +{ + Net_Call_C_Last.out_ax = returned_ax; + Net_Call_C_Last.out_bx = r->x.bx; + Net_Call_C_Last.out_cx = r->x.cx; + Net_Call_C_Last.out_dx = r->x.dx; + Net_Call_C_Last.out_si = r->x.si; + Net_Call_C_Last.out_di = r->x.di; + Net_Call_C_Last.out_flags = r->x.cflag; + Net_Call_C_Last.rc = returned_ax & 0x00ff; +} + /* - * 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. + * C equivalent of kern_wasm.asm Net_Call: + * AX = func + * DS:SI = request + * ES:DI = reply + * int 21h + * return AL only, because kern_wasm.asm clears AH before return. */ int KERN_C_CALL Net_Call_C(unsigned int 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_C_CALL Net_Call_CX(unsigned int ax, unsigned int bx, - unsigned int cx, unsigned int dx, - void *req, void *repl) + unsigned int cx, unsigned int dx, + void *req, void *repl) { union REGS inregs; union REGS outregs; struct SREGS segregs; + unsigned int ret_ax; 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)); + net_call_c_clear(); inregs.x.ax = ax; inregs.x.bx = bx; @@ -97,69 +113,45 @@ int KERN_C_CALL Net_Call_CX(unsigned int ax, unsigned int bx, 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; + net_call_c_save_in(&inregs, &segregs, req, 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; - /* kern_wasm.asm clears AH before returning, so return AL only. */ - Net_Call_C_Last.rc = outregs.x.ax & 0x00ff; + ret_ax = outregs.x.ax & 0x00ff; /* match ASM Net_Call return */ - return Net_Call_C_Last.rc; + net_call_c_save_out(&outregs, ret_ax); + + return (int)ret_ax; } /* - * Experimental Client32/VLM-style AH=F2 raw request wrapper. - * - * This mirrors the official Novell FLAG.EXE wrapper shape seen in disassembly: - * DX = connection / connection reference - * ES:DI = reply buffer - * CX = caller supplied size/count - * DS:SI = request buffer + * Experimental Novell Client/VLM AH=F2 wrapper derived from official FLAG.EXE + * disassembly: * AH = F2h * AL = NCP function, e.g. 57h for NCP 87 - * int 21h - * - * Return convention mirrors Novell wrapper and old kern.asm Net_Call: -int KERN_C_CALL Net_Call_F2_C(UI function, UI req_len, UI repl_len, - void *req, void *repl) + * CX = request length + * DX = reply buffer length + * DS:SI = request buffer + * ES:DI = reply buffer + */ +int KERN_C_CALL Net_Call_F2_C(unsigned int function, + unsigned int req_len, + unsigned int repl_len, + void *req, + void *repl) { union REGS inregs; union REGS outregs; struct SREGS segregs; - UI ret_ax; + unsigned int ret_ax; 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)); + net_call_c_clear(); - /* - * Official FLAG.EXE wrapper shape: - * AH = F2h - * AL = NCP function, e.g. 57h for NCP 87 - * CX = request length - * DX = reply buffer length - * DS:SI = request buffer - * ES:DI = reply buffer - */ inregs.h.ah = 0xF2; - inregs.h.al = (uint8)(function & 0xff); + inregs.h.al = (unsigned char)(function & 0xff); inregs.x.cx = req_len; inregs.x.dx = repl_len; inregs.x.si = FP_OFF(req); @@ -167,37 +159,26 @@ int KERN_C_CALL Net_Call_F2_C(UI function, UI req_len, UI repl_len, 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; + net_call_c_save_in(&inregs, &segregs, req, repl); int86x(0x21, &inregs, &outregs, &segregs); - ret_ax = outregs.x.ax; - ret_ax &= 0x00ff; + /* + * Novell wrapper behavior: + * xor ah,ah + * or al,al + * if al != 0: ah=89h + * Return AL only for C caller, but keep 89xx in debug out_ax. + */ + ret_ax = outregs.x.ax & 0x00ff; if (ret_ax) ret_ax |= 0x8900; - Net_Call_C_Last.out_ax = ret_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 = ret_ax & 0x00ff; + net_call_c_save_out(&outregs, ret_ax); - return Net_Call_C_Last.rc; + return (int)(ret_ax & 0x00ff); } - void KERN_C_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", @@ -221,15 +202,7 @@ void KERN_C_CALL Net_Call_C_Dump(void) 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_C_CALL Net_Call_C_GetDebug(UI idx) +unsigned int KERN_C_CALL Net_Call_C_GetDebug(unsigned int idx) { switch (idx) { case 0: return Net_Call_C_Last.in_ax; diff --git a/kern.h b/kern.h index d391b4f..f6eae43 100644 --- a/kern.h +++ b/kern.h @@ -14,19 +14,16 @@ 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); 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 int KERN_CALL Net_Call_F2_C(UI function, UI req_len, UI repl_len, - void *req, void *repl); -extern void KERN_CALL Net_Call_C_Dump(void); -extern UI KERN_CALL Net_Call_C_GetDebug(UI idx); -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 int KERN_CALL Net_Call_F2_C(UI function, UI req_len, UI repl_len, + 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 -