/* * Called from setup_pkt_inf() in pcpkt.c */ static DWORD setup_pkt_inf_fast (void) { /* Allocate space for asmpkt_inf, temp area, pkt-stub and Tx buffer. */ DWORD rdata_size = PKT_TMP(); size_t stub_size = sizeof(real_stub_array); #if (DOSX) rdata_size += PKT_TMP_SIZE + ETH_MAX + 10; #endif if (rdata_size >= 64*1024UL) { TCP_CONSOLE_MSG (0, ("%s (%u): Development error:\nsize %u too large\n", __FILE__, __LINE__, (unsigned int)rdata_size)); return (0); } if (stub_size < 0xC0) { TCP_CONSOLE_MSG (0, ("%s (%u): Development error:\n\"pkt_stub.h\"" " seems truncated (%d bytes)\n", __FILE__, __LINE__, SIZEOF(real_stub_array))); return (0); } #if (DOSX & DJGPP) { int i, seg, sel; seg = __dpmi_allocate_dos_memory ((rdata_size+15)/16, &sel); if (seg < 0) return (0); _pkt_inf->rm_seg = seg; _pkt_inf->rm_sel = sel; rm_base = (_pkt_inf->rm_seg << 4); for (i = 0; i < (int)rdata_size; i += 4) /* clear area */ POKEL (_pkt_inf->rm_seg, i, 0); } #elif (DOSX & DOS4GW) { WORD seg, sel; seg = dpmi_real_malloc (rdata_size, &sel); if (!seg) return (0); _pkt_inf->rm_seg = seg; _pkt_inf->rm_sel = sel; rm_base = (_pkt_inf->rm_seg) << 4; memset ((void*)rm_base, 0, rdata_size); } #elif (DOSX & PHARLAP) { WORD largest, seg; int i; if (_dx_real_alloc ((rdata_size+15)/16, &seg, &largest) != 0) return (0); _pkt_inf->rm_seg = seg; _pkt_inf->rm_sel = 0; RP_SET (rm_base, 0, _pkt_inf->rm_seg); for (i = 0; i < (int)rdata_size; i += 4) POKEL (_pkt_inf->rm_seg, i, 0); } #elif (DOSX & X32VM) { int i; rm_base = _x32_real_alloc (rdata_size); if (!rm_base) return (0); _pkt_inf->rm_seg = _x32_real_segment (rm_base); _pkt_inf->rm_sel = 0; for (i = 0; i < (int)rdata_size; i += 4) POKEL (_pkt_inf->rm_seg, i, 0); } #elif (DOSX & POWERPAK) { WORD seg, sel; int i; seg = dpmi_real_malloc ((rdata_size+15)/16, &sel); if (!seg) return (0); _pkt_inf->rm_seg = seg; _pkt_inf->rm_sel = sel; RP_SET (rm_base, 0, _pkt_inf->rm_seg); for (i = 0; i < (int)rdata_size; i += 4) POKEL (_pkt_inf->rm_seg, i, 0); } #elif (DOSX == 0) { char _far *buf = _fcalloc (rdata_size, 0); if (!buf) return (0); _pkt_inf->rm_seg = FP_SEG (buf); rm_base = (DWORD) buf; } #else #error Help! #endif pktq_far_init (sizeof(struct pkt_rx_element), RX_BUFS, ASMPKT_INF); _pkt_inf->pkt_queue.num_buf = RX_BUFS; return (rm_base); }
int pkt_test_upcall (void) { #if !defined(NO_RMODE_CALL) int i, max = RX_BUFS + 3; for (i = 0; i < max; i++) { eth_Packet eth; IREGS regs; DWORD linear = 0; memset (®s, 0, sizeof(regs)); memset (ð, 0, sizeof(eth)); eth.head.type = IP4_TYPE; memset (ð.head.destination, 0xFF, 6); memcpy (ð.head.source, _eth_addr, 6); #if (DOSX & (PHARLAP|X32VM)) rmc.eax = 0; rmc.ebx = _pkt_inf->handle; rmc.ecx = ETH_MAX; #endif regs.r_cx = ETH_MAX; regs.r_bx = _pkt_inf->handle; regs.r_ax = 0; regs.r_cs = _pkt_inf->rm_seg; regs.r_ip = PktReceiver; if (DPMI_REAL_CALL(®s)) { linear = SEG_OFS_ADDR (regs.r_es, regs.r_di); printf ("Upcall AX=0: ES:DI %04X:%04X\n", (WORD)regs.r_es, (WORD)regs.r_di); #if (DOSX & DJGPP) if (linear) dosmemput (ð, (WORD)regs.r_cx, linear); #elif (DOSX & (DOS4GW|X32VM)) if (linear) memcpy ((void*)linear, ð, (WORD)regs.r_cx); #elif (DOSX & (PHARLAP|POWERPAK)) if (linear) { RP_SET (linear, regs.r_es, regs.r_di); WriteRealMem (linear, ð, (WORD)regs.r_cx); } #else #error Help me! #endif } if (linear) { regs.r_ss = regs.r_sp = 0; regs.r_ax = 1; regs.r_cs = _pkt_inf->rm_seg; regs.r_ip = PktReceiver; regs.r_ds = regs.r_es; regs.r_si = regs.r_di; if (DPMI_REAL_CALL(®s)) printf ("Upcall AX=1\n"); } printf ("buffers used %d, dropped %lu\n", pkt_buffers_used(), pkt_rx_dropped()); } #endif pkt_dump_real_mem(); return (0); }
static REALPTR _dx_alloc_rmode_wrapper (pmodeHook pmHook, rmodeHook rmHook, int len, int stack_size, ReturnType returnType) { #define DOFS 0x2C /* offset of data section (tiny model) */ #define DSIZE 16 /* sizeof data section at wrapper end */ #define WOFS (DOFS+DSIZE) /* offset of userWrapper code (optional) */ static unsigned char wrapper[] = { 0x16, // 00 push ss 0x06, // 01 push es 0x1E, // 02 push ds 0x0E, // 03 push cs 0x1F, // 04 pop ds ;DS = CS 0xF8, // 05 clc 0xE8,0x33,0, // 06 call userWrapper ;33 relative (3A-8) 0x72,0x1C, // 09 jc short @exit 0x66,0x60, // 0B pushad 0x66,0xFF,0x36,DOFS+12,0, // 0D push taskId ;taskId to call 0x66,0x6A,0, // 12 push 0 ;use default selectors 0xFF,0x36,DOFS+4,0, // 15 push ourCS 0x66,0xFF,0x36,DOFS,0, // 19 push protGlue ;(*protGlue)() 0xFF,0x1E,DOFS+8,0, // 1E call rm2pmAddr 0x83,0xC4,14, // 22 add sp,14 ;discard used stack 0x66,0x61, // 25 popad 0x1F, // 27 @exit:pop ds 0x07, // 28 pop es 0x17, // 29 pop ss 0xCB, // 2A retf 0x90, // 2B nop 0,0,0,0, // +0 protGlue dd ? 0,0,0,0, // +4 ourCS dw ?,? 0,0,0,0, // +8 rm2pmAddr dd ? 0,0,0,0 // +12 taskId dd ? }; // +16 userWrapper: .. FARPTR pmCbuf, fpWrapper; REALPTR rmCbuf, rm2pmAddr, dosReal; USHORT para, paras, left; ULONG cbufSize, i; UINT *stack; assert (sizeof(wrapper) == (DOFS+DSIZE)); if (!pmHook || numWrappers == MAX_WRAPPERS) return (0); _dx_rmlink_get (&rm2pmAddr,&rmCbuf,&cbufSize,&pmCbuf); len += sizeof(wrapper); paras = (len + 15) / 16; para = 0; if (_dx_real_above(paras,¶,&left)) { ULONG temp; if (_dx_cmem_usage(0,0,&temp,&temp)) return (0); if (_dx_real_above(paras,¶,&left)) para = 0; if (_dx_cmem_usage(0,1,&temp,&temp)) { if (para) _dx_real_free (para); return (0); } if (!para) return (0); } for (i = 0; i < MAX_WRAPPERS; i++) if (!_rmcb[i].dosReal) break; *(ULONG*) (wrapper+DOFS+0) = (ULONG)&PmodeGlue; /* pmode helper */ *(ULONG*) (wrapper+DOFS+4) = My_CS(); /* pmode CS */ *(ULONG*) (wrapper+DOFS+8) = (ULONG)rm2pmAddr; /* rm->pm addr */ *(ULONG*) (wrapper+DOFS+12) = i; /* task Id */ wrapper [0x2A] = returnType; /* RETF or IRET */ /* * lock pages used by callback (for 386|VMM, allthough untested) */ FP_SET (fpWrapper,para << 4, SS_DOSMEM); _dx_lock_pgs (fpWrapper, len); _dx_lock_pgsn ((void*)&PmodeGlue, (UINT)&PmGlueEnd - (UINT)&PmodeGlue); RP_SET (dosReal,0,para); FillRealMem (dosReal, 0, len); WriteRealMem (dosReal, &wrapper, sizeof(wrapper)); if (rmHook) WriteRealMem(dosReal+WOFS,(void*)rmHook,len-sizeof(wrapper)); else FillRealMem (dosReal+5,0x90,6); stack_size += sizeof(UINT) + 3; /* add a DWORD for marker */ stack_size &= ~3; /* make number of DWORDs */ stack = malloc (stack_size); if (!stack) return (0); _rmcb [i].dosReal = dosReal; _rmcb [i].callback = pmHook; _rmcb [i].stackStart = stack; _rmcb [i].stackTop = stack + stack_size/sizeof(UINT) - 2; _rmcb [i].stackTop[1] = MARKER; _rmcb [i].marker = MARKER; _dx_lock_pgsn ((void*)stack, stack_size); #if 0 printf ("dosReal %08lX, rm2pmAddr %08lX, len %d, stack %08X\n", dosReal,rm2pmAddr,len,stack); #endif numWrappers++; return (dosReal); }