diff --git a/kern.h b/kern.h index f7dddea..f6d38a0 100644 --- a/kern.h +++ b/kern.h @@ -13,6 +13,7 @@ extern void asm_esr_routine(void); 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 C32_LoadNios_Probe(UI axfunc, void *outbuf); extern int KERN_CALL Net_Call_VLM_Raw(UI ax, UI bx, UI cx, UI dx, void *req, void *repl, UI p1, UI p2, UI p3); diff --git a/kern_wasm.asm b/kern_wasm.asm index ed9b7cd..61fbe70 100644 --- a/kern_wasm.asm +++ b/kern_wasm.asm @@ -6,7 +6,7 @@ ; Keep kern.asm as the historical TASM source and use this file for the ; reproducible Open Watcom build. -.286 +.386 .model large .data @@ -20,6 +20,7 @@ public _IPXclose_socket public _IPXlisten public _xmemmove public _Net_Call +public _C32_LoadNios_Probe public _Net_Call_VLM_Raw _IPXinit proc far @@ -287,4 +288,61 @@ vlm_raw_done: _Net_Call_VLM_Raw endp +; int C32_LoadNios_Probe(UI axfunc, void *outbuf) +; +; Probe the Client32/NIOS INT 2F entry used by DeveloperNet dninit.asm: +; AX = axfunc, normally D8C1h +; INT 2Fh +; AX = 0000 on success +; ESI and ECX contain Client32/NIOS function pointers/data +; +; outbuf layout, little endian: +; +00 word AX after int 2F +; +02 dword ESI after int 2F +; +06 dword ECX after int 2F +; +0A word BX +; +0C word CX low +; +0E word DX +; +10 word SI low +; +12 word DI low +_C32_LoadNios_Probe proc far + push bp + mov bp, sp + + push ds + push es + push si + push di + + xor ecx, ecx + xor esi, esi + xor ebx, ebx + xor edx, edx + xor edi, edi + + mov ax, [bp+6] + int 2Fh + + les di, dword ptr [bp+8] + + mov es:[di+0], ax + mov dword ptr es:[di+2], esi + mov dword ptr es:[di+6], ecx + mov es:[di+10], bx + mov es:[di+12], cx + mov es:[di+14], dx + mov es:[di+16], si + ; DI currently points at outbuf, so store caller-visible DI is not useful. + mov word ptr es:[di+18], 0 + + pop di + pop si + pop es + pop ds + pop bp + xor ah, ah + ret +_C32_LoadNios_Probe endp + + end diff --git a/nwtests.c b/nwtests.c index be8f8ea..ce68855 100644 --- a/nwtests.c +++ b/nwtests.c @@ -545,9 +545,11 @@ static UI tests_build_nwreq87_path_multi(uint8 *buf, uint8 dhandle, static void tests_wait_key(void) { - fprintf(stdout, "Strike any key when ready . . . "); + fprintf(stdout, "\nStrike any key when ready . . . "); + fflush(stdout); getch(); fprintf(stdout, "\n"); + fflush(stdout); } static int tests_nwreq87vlm_one(char *label, uint8 connid, @@ -1110,7 +1112,6 @@ static int tests_nwreq87vlmfull(void) fprintf(stdout, "drive=%c: connid=%u dhandle=%u flags=%02X\n", 'A' + drive, connid, dhandle, flags); tests_dump_bytes("HDR:", hdr, 9); - tests_wait_key(); tests_build_novell_handle_path(path, dhandle, 0, 0, 1, "LOGIN.EXE", 0, 0); @@ -1128,6 +1129,64 @@ static int tests_nwreq87vlmfull(void) } +static uint16 tests_get_word_lh(uint8 *p) +{ + return (uint16)(p[0] | ((uint16)p[1] << 8)); +} + +static uint32 tests_get_dword_lh2(uint8 *p) +{ + return ((uint32)p[0] | + ((uint32)p[1] << 8) | + ((uint32)p[2] << 16) | + ((uint32)p[3] << 24)); +} + +static int tests_c32type(void) +{ + uint8 out[32]; + int rc; + uint16 ax; + uint32 esi; + uint32 ecx; + uint16 bx; + uint16 cx; + uint16 dx; + uint16 si; + + memset(out, 0, sizeof(out)); + + fprintf(stdout, "TEST Client32/NIOS probe\n"); + fprintf(stdout, "Call INT 2F AX=D8C1 like DeveloperNet dninit.asm\n\n"); + + rc = C32_LoadNios_Probe(0xD8C1, out); + + ax = tests_get_word_lh(out + 0); + esi = tests_get_dword_lh2(out + 2); + ecx = tests_get_dword_lh2(out + 6); + bx = tests_get_word_lh(out + 10); + cx = tests_get_word_lh(out + 12); + dx = tests_get_word_lh(out + 14); + si = tests_get_word_lh(out + 16); + + fprintf(stdout, "C32 probe rc=%04X\n", rc); + fprintf(stdout, "INT2F D8C1 result AX=%04X\n", ax); + fprintf(stdout, "ESI=%08lX ECX=%08lX\n", esi, ecx); + fprintf(stdout, "BX=%04X CX=%04X DX=%04X SI=%04X\n", bx, cx, dx, si); + tests_dump_bytes("RAW:", out, 20); + + if (ax == 0) { + fprintf(stdout, "\nClient32/NIOS entry appears present.\n"); + fprintf(stdout, "Next step: use these values to reproduce C32BEGINUSE/_C32REQUEST.\n"); + } else { + fprintf(stdout, "\nClient32/NIOS D8C1 did not report success.\n"); + fprintf(stdout, "Then VLM/NETX fallback remains the only path.\n"); + } + + return(0); +} + + int func_tests(int argc, char *argv[], int mode) { if (argc >= 2) { @@ -1137,6 +1196,9 @@ int func_tests(int argc, char *argv[], int mode) if (tests_same_arg(argv[1], "E300") || tests_same_arg(argv[1], "NETCALLE300")) return tests_netcall_e300(); + if (tests_same_arg(argv[1], "C32TYPE")) + return tests_c32type(); + if (tests_same_arg(argv[1], "NWREQ87")) return tests_nwreq87(argc, argv);