Esempio n. 1
0
/* Open WSS for usage */
boolean wss_open()
{
	__dpmi_meminfo struct_info;

	if (!wss.ok)
		if (!wss_detect())
			return FALSE;

	if (wss.open)
		return FALSE;

	/* Now lock the wss structure in memory */
	struct_info.address = __djgpp_base_address + (unsigned long)&wss;
	struct_info.size = sizeof(wss);
	if (__dpmi_lock_linear_region(&struct_info))
		return FALSE;

	/* Hook the WSS IRQ */
	wss.irq_handle =
	  irq_hook(wss.irq, wss_irq, (long)wss_irq_end - (long)wss_irq);
	if (!wss.irq_handle) {
		__dpmi_unlock_linear_region(&struct_info);
		return FALSE;
	}

	/* Enable the interrupt */
	irq_enable(wss.irq_handle);
	if (wss.irq > 7)
		_irq_enable(2);

	wss.open++;

	return TRUE;
}
Esempio n. 2
0
void
dpmi_lock_memory (void *start, unsigned long num_bytes)
{
  unsigned long base = 0;

  /* Get the linear base address. */
  if (__dpmi_get_segment_base_address (dos_pm_ds, &base) != -1)
    {
      __dpmi_meminfo mem;

      mem.handle  = 0; /* Unused */
      mem.size    = num_bytes;
      mem.address = (unsigned long) ((char *) start + base);
      __dpmi_lock_linear_region (&mem);
    }
}
Esempio n. 3
0
int dma_initialize()
{
	if (!__djgpp_nearptr_enable())
		return 0;

	/* Trick: Avoid re-setting DS selector limit on each memory allocation
	   call */
	__djgpp_selector_limit = 0xffffffff;

	__locked_data.address = __djgpp_base_address + (unsigned long)&dma;
	__locked_data.size = sizeof(dma);
	if (__dpmi_lock_linear_region(&__locked_data))
		return 0;

	return (__initialized = 1);
}
Esempio n. 4
0
void *dos_getmaxlockedmem(int *size)
{
	__dpmi_free_mem_info	meminfo;
	__dpmi_meminfo			info;
	int						working_size;
	void					*working_memory;
	int						last_locked;
	int						extra, 	i, j, allocsize;
	static char				*msg = "Locking data...";
	int						m, n;
	byte					*x;
 
// first lock all the current executing image so the locked count will
// be accurate.  It doesn't hurt to lock the memory multiple times
	last_locked = __djgpp_selector_limit + 1;
	info.size = last_locked - 4096;
	info.address = __djgpp_base_address + 4096;

	if (lockmem)
	{
		if(__dpmi_lock_linear_region(&info))
		{
			Sys_Error ("Lock of current memory at 0x%lx for %ldKb failed!\n",
						info.address, info.size/1024);
		}
	}

	__dpmi_get_free_memory_information(&meminfo);

	if (!win95)		/* Not windows or earlier than Win95 */
	{
		working_size = meminfo.maximum_locked_page_allocation_in_pages * 4096;
	}
	else
	{
		working_size = meminfo.largest_available_free_block_in_bytes -
				LEAVE_FOR_CACHE;
	}

	working_size &= ~0xffff;		/* Round down to 64K */
	working_size += 0x10000;

	do
	{
		working_size -= 0x10000;		/* Decrease 64K and try again */
		working_memory = sbrk(working_size);
	} while (working_memory == (void *)-1);

	extra = 0xfffc - ((unsigned)sbrk(0) & 0xffff);

	if (extra > 0)
	{
		sbrk(extra);
		working_size += extra;
	}

// now grab the memory
	info.address = last_locked + __djgpp_base_address;

	if (!win95)
	{
	    info.size = __djgpp_selector_limit + 1 - last_locked;

		while (info.size > 0 && __dpmi_lock_linear_region(&info))
		{
			info.size -= 0x1000;
			working_size -= 0x1000;
			sbrk(-0x1000);
		}
	}
	else
	{			/* Win95 section */
		j = COM_CheckParm("-winmem");

		if (standard_quake)
			minmem = MINIMUM_WIN_MEMORY;
		else
			minmem = MINIMUM_WIN_MEMORY_LEVELPAK;

		if (j)
		{
			allocsize = ((int)(Q_atoi(com_argv[j+1]))) * 0x100000 +
					LOCKED_FOR_MALLOC;

			if (allocsize < (minmem + LOCKED_FOR_MALLOC))
				allocsize = minmem + LOCKED_FOR_MALLOC;
		}
		else
		{
			allocsize = minmem + LOCKED_FOR_MALLOC;
		}

		if (!lockmem)
		{
		// we won't lock, just sbrk the memory
			info.size = allocsize;
			goto UpdateSbrk;
		}

		// lock the memory down
		write (STDOUT, msg, strlen (msg));

		for (j=allocsize ; j>(minmem + LOCKED_FOR_MALLOC) ;
			 j -= 0x100000)
		{
			info.size = j;
	
			if (!__dpmi_lock_linear_region(&info))
				goto Locked;
	
			write (STDOUT, ".", 1);
		}

	// finally, try with the absolute minimum amount
		for (i=0 ; i<10 ; i++)
		{
			info.size = minmem + LOCKED_FOR_MALLOC;

			if (!__dpmi_lock_linear_region(&info))
				goto Locked;
		}

		Sys_Error ("Can't lock memory; %d Mb lockable RAM required. "
				   "Try shrinking smartdrv.", info.size / 0x100000);

Locked:

UpdateSbrk:

		info.address += info.size;
		info.address -= __djgpp_base_address + 4; // ending point, malloc align
		working_size = info.address - (int)working_memory;
		sbrk(info.address-(int)sbrk(0));		// negative adjustment
	}


	if (lockunlockmem)
	{
		__dpmi_unlock_linear_region (&info);
		printf ("Locked and unlocked %d Mb data\n", working_size / 0x100000);
	}
	else if (lockmem)
	{
		printf ("Locked %d Mb data\n", working_size / 0x100000);
	}
	else
	{
		printf ("Allocated %d Mb data\n", working_size / 0x100000);
	}

// touch all the memory to make sure it's there. The 16-page skip is to
// keep Win 95 from thinking we're trying to page ourselves in (we are
// doing that, of course, but there's no reason we shouldn't)
	x = (byte *)working_memory;

	for (n=0 ; n<4 ; n++)
	{
		for (m=0 ; m<(working_size - 16 * 0x1000) ; m += 4)
		{
			sys_checksum += *(int *)&x[m];
			sys_checksum += *(int *)&x[m + 16 * 0x1000];
		}
	}

// give some of what we locked back for malloc before returning.  Done
// by cheating and passing a negative value to sbrk
	working_size -= LOCKED_FOR_MALLOC;
	sbrk( -(LOCKED_FOR_MALLOC));
	*size = working_size;
	return working_memory;
}
Esempio n. 5
0
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;
}