tests
This commit is contained in:
183
kern.c
183
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 <stdio.h>
|
||||
@@ -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;
|
||||
|
||||
13
kern.h
13
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
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user