/*
 * w32util
 *	WINNT utils for dm_bb & other fep tools
 *
 * TODO:
 *
 * $Id: w32util.c,v 1.1 1999/12/13 23:24:04 chrism Exp $
 */


#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "feptypes.h"
#include "DigiKme.h"


static HANDLE w32_get_dev_handle(char *Device)
{
	HANDLE hdev = INVALID_HANDLE_VALUE;

	char DeviceName[32];

	{
		/*
		 * OK, here's what's going on here.  The device name being passed in
		 * to us is either a normal NT style device name, such as DigiDxb5.
		 * Or, most likely it is a Unix style device name like /dev/dm/ram5.
		 * Either way, just scrap off the digit(s) as the end, and use that
		 * to create a DigiDxbN NT style device name.
		*/
		if ( Device[0]=='/' )
		{
			char * pc = &Device[strlen(Device) - 1];
			while (isdigit(*(pc - 1))) pc--;
			sprintf(DeviceName, "\\\\.\\DigiDxb%s", pc);
		}
		else
			sprintf(DeviceName, "\\\\.\\%s", Device);
		printf( "Device %s, DeviceName: %s\n", Device, DeviceName );
	}

	hdev = CreateFile(DeviceName,
				GENERIC_READ | GENERIC_WRITE,
				FILE_SHARE_READ | FILE_SHARE_WRITE,
				NULL,
				CREATE_ALWAYS,
				FILE_ATTRIBUTE_NORMAL,
				NULL);

	return hdev;
}

void *w32_mmap(char *Device)
{
	void *pv = (void *) -1;

	HANDLE hdev = w32_get_dev_handle(Device);
	if (hdev != INVALID_HANDLE_VALUE)
	{
		KME_MAP kmeMap = { 0 };
		BOOL fDevIocltSucceeded = FALSE;
		DWORD cbReturned = 0;

		kmeMap.Flags = KME_FLAG_ADAPTER_MEMORY;

		fDevIocltSucceeded = DeviceIoControl(hdev, (DWORD)IOCTL_KME_MAP,
										&kmeMap, sizeof kmeMap,
										&kmeMap, sizeof kmeMap,
										&cbReturned, NULL);

		if (fDevIocltSucceeded && (cbReturned == sizeof kmeMap))
		{
			pv = kmeMap.pView;
		}

		CloseHandle(hdev);
	}

	return pv;
}

void w32_unmmap(char *Device, void *pv)
{
	HANDLE hdev = w32_get_dev_handle(Device);
	if (hdev != INVALID_HANDLE_VALUE)
	{
		DWORD cbReturned = 0;
		DeviceIoControl(hdev, (DWORD)IOCTL_KME_UNMAP,
			&pv, sizeof pv,
			NULL, 0,
			&cbReturned, NULL);

		CloseHandle(hdev);
	}

	return;
}

void w32_sleep(unsigned long ms)
{
	Sleep(ms);
}

/* getopt.c  (slightly modified by O.Garcia, 12/4/92) */
/* now it accepts either '-' or '/' as switch character */
 
/*
Newsgroups: mod.std.unix
Subject: public domain AT&T getopt source
Date: 3 Nov 85 19:34:15 GMT
 
Here's something you've all been waiting for:  the AT&T public domain source for getopt(3).  It is the code which was given out at the 1985 UNIFORUM conference in Dallas.  I obtained it by electronic mail directly from AT&T.  The people there assure me that it is indeed in the public domain.
*/
 
 
#define ERR(s, c) if(opterr){fprintf(stderr,"%s%s%c\n",argv[0],s,c);} 
 
int    opterr = 1;
int    optind = 1;
int    optopt;
char    *optarg;
 
int w32_getopt(int argc, char **argv, char *opts)
{
  static int sp = 1;
  register int c;
  register char *cp;
 
  if(sp == 1)
      if(optind >= argc ||
        (argv[optind][0] != '-' && argv[optind][0] != '/') 
        || argv[optind][1] == '\0')
        return(EOF);
      else if(strcmp(argv[optind], "--") == 0 ||
      strcmp(argv[optind], "file://") == 0) {
        optind++;
        return(EOF);
      }
  optopt = c = argv[optind][sp];
  if(c == ':' || (cp=strchr(opts, c)) == NULL) {
      ERR(": illegal option -- ", c);
      if(argv[optind][++sp] == '\0') {
        optind++;
        sp = 1;
      }
      return('?');
  }
  if(*++cp == ':') {
      if(argv[optind][sp+1] != '\0')
        optarg = &argv[optind++][sp+1];
      else if(++optind >= argc) {
        ERR(": option requires an argument -- ", c);
        sp = 1;
        return('?');
      } else
        optarg = argv[optind++];
      sp = 1;
  } else {
      if(argv[optind][++sp] == '\0') {
        sp = 1;
        optind++;
      }
      optarg = NULL;
  }
  return(c);
}
