/* setup_x_magic: * To make sure that things will go on working properly even if a few * bits of code don't know about mode-X screens, we do special magic * inside the bank switch functions to emulate a linear image surface. * Whenever someone tries to access the screen directly, these routines * copy the planar image into a temporary buffer, let the client write * there, and then automatically refresh the screen with the updated * graphics. Very slow, but it makes 100% sure that everything will work. */ static void setup_x_magic(BITMAP *b) { #ifdef ALLEGRO_DOS /* DOS buffer has to go in conventional memory */ int seg = __dpmi_allocate_dos_memory((b->w+15)/16, &magic_sel); if (seg > 0) _x_magic_buffer_addr = seg*16; else _x_magic_buffer_addr = 0; #else /* other platforms can put the buffer wherever they like */ _x_magic_buffer_addr = (unsigned long)_AL_MALLOC(b->w); #endif _x_magic_screen_addr = 0; _x_magic_screen_width = 0; LOCK_VARIABLE(_x_magic_buffer_addr); LOCK_VARIABLE(_x_magic_screen_addr); LOCK_VARIABLE(_x_magic_screen_width); LOCK_FUNCTION(_x_bank_switch); b->write_bank = b->read_bank = _x_bank_switch; }
int emm_init(void) { /* TODO: check EMM presence */ /* allocate 1 para for page map array */ rmseg = __dpmi_allocate_dos_memory(1, &rmsel); if (rmseg == -1) return -1; __dpmi_get_segment_base_address(rmsel, &rmaddr); return 0; }
/* * 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); }
dma_buffer *dma_allocate(unsigned int channel, unsigned int size) { int parsize = (size + 15) >> 4; /* size in paragraphs */ int par = 0; /* Real-mode paragraph */ int selector = 0; /* Protected-mode selector */ int mask = channel <= 3 ? 0xfff : 0x1fff; /* Alignment mask in para. */ int allocsize = parsize; /* Allocated size in paragraphs */ int count; /* Try count */ int bound = 0; /* Nearest bound address */ int maxsize; /* Maximal possible block size */ dma_buffer *buffer = NULL; __dpmi_meminfo buff_info, struct_info; if (!dma_initialize()) return NULL; /* Loop until we'll get a properly aligned memory block */ for (count = 8; count; count--) { int resize = (selector != 0); /* Try first to resize (possibly previously) allocated block */ if (resize) { maxsize = (bound + parsize) - par; if (maxsize > parsize * 2) maxsize = parsize * 2; if (maxsize == allocsize) resize = 0; else { allocsize = maxsize; /* BUG WARNING: there is an error in dpmi.h DJGPP 2.01 library: the order of "selector" and "alloc size" should be reversed */ if (__dpmi_resize_dos_memory(allocsize, selector, &maxsize) != 0) resize = 0; } } if (!resize) { if (selector) __dpmi_free_dos_memory(selector), selector = 0; par = __dpmi_allocate_dos_memory(allocsize, &selector); } if ((par == 0) || (par == -1)) goto exit; /* If memory block contains a properly aligned portion, quit loop */ bound = (par + mask + 1) & ~mask; if (par + parsize <= bound) break; if (bound + parsize <= par + allocsize) { par = bound; break; } } if (!count) { __dpmi_free_dos_memory(selector); goto exit; } buffer = malloc(sizeof(dma_buffer)); buffer->linear = (void *)(__djgpp_conventional_base + bound * 16); buffer->physical = bound * 16; buffer->size = parsize * 16; buffer->selector = selector; buffer->channel = channel; buff_info.address = buffer->physical; buff_info.size = buffer->size; /* Don't pay attention to return code since under plain DOS it often returns error (at least under HIMEM/CWSDPMI and EMM386/DPMI) */ __dpmi_lock_linear_region(&buff_info); /* Lock the DMA buffer control structure as well */ struct_info.address = __djgpp_base_address + (unsigned long)buffer; struct_info.size = sizeof(dma_buffer); if (__dpmi_lock_linear_region(&struct_info)) { __dpmi_unlock_linear_region(&buff_info); __dpmi_free_dos_memory(selector); free(buffer); buffer = NULL; goto exit; } exit: if (buffer) __buffer_count++; else if (--__buffer_count == 0) dma_finalize(); return buffer; }