- Slightly reworked include files (less messy, more straightforward).
- Moved DOS ASPI functionality to msdos/dosaspi.c.
- Got rid using PROFILE to get SCSI info from wine.conf.
- Read scsi info from /proc/scsi/scsi.
- Added setting of a reasonable timeout when opening a SCSI device (5
  minutes, defined in winescsi.h).
- ExecScsiCommand now ALWAYS posts, even on error (which is the correct
  behavior).

diff --git a/Makefile.in b/Makefile.in
index 3eef1b4..9bb7b41 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -37,7 +37,6 @@
 	dlls/mouse \
 	dlls/mpr \
 	dlls/ntdll \
-	dlls/winaspi \
 	files \
 	graphics \
 	graphics/enhmetafiledrv \
@@ -114,7 +113,6 @@
 	dlls/mouse/mouse.o \
 	dlls/mpr/mpr.o \
 	dlls/ntdll/ntdll.o \
-	dlls/winaspi/winaspi.o \
 	files/files.o \
 	graphics/graphics.o \
 	graphics/enhmetafiledrv/enhmetafiledrv.o \
diff --git a/configure b/configure
index ab5252c..e696ef3 100755
--- a/configure
+++ b/configure
@@ -6231,7 +6231,6 @@
 dlls/winmm/wineoss/Makefile
 dlls/winsock/Makefile
 dlls/winspool/Makefile
-dlls/wnaspi32/Makefile
 documentation/Makefile
 documentation/wine.conf.man
 documentation/wine.man
@@ -6447,7 +6446,6 @@
 dlls/winmm/wineoss/Makefile
 dlls/winsock/Makefile
 dlls/winspool/Makefile
-dlls/wnaspi32/Makefile
 documentation/Makefile
 documentation/wine.conf.man
 documentation/wine.man
diff --git a/configure.in b/configure.in
index fa08d8f..adde21a 100644
--- a/configure.in
+++ b/configure.in
@@ -993,7 +993,6 @@
 dlls/winmm/wineoss/Makefile
 dlls/winsock/Makefile
 dlls/winspool/Makefile
-dlls/wnaspi32/Makefile
 documentation/Makefile
 documentation/wine.conf.man
 documentation/wine.man
diff --git a/dlls/Makefile.in b/dlls/Makefile.in
index 9cc7500..3cb7a35 100644
--- a/dlls/Makefile.in
+++ b/dlls/Makefile.in
@@ -35,10 +35,11 @@
 	version/libversion.@LIBEXT@ \
 	win32s/libw32skrnl.@LIBEXT@ \
 	win87em/libwin87em.@LIBEXT@ \
+	winaspi/libwnaspi32.@LIBEXT@ \
 	windebug/libwindebug.@LIBEXT@ \
 	wing/libwing.@LIBEXT@ \
-	winmm/libwinmm.@LIBEXT@ \
 	winmm/joystick/libjoystick.drv.@LIBEXT@ \
+	winmm/libwinmm.@LIBEXT@ \
 	winmm/mcianim/libmcianim.drv.@LIBEXT@ \
 	winmm/mciavi/libmciavi.drv.@LIBEXT@ \
 	winmm/mcicda/libmcicda.drv.@LIBEXT@ \
@@ -48,8 +49,7 @@
 	winmm/wavemap/libmsacm.drv.@LIBEXT@ \
 	winmm/wineoss/libwineoss.drv.@LIBEXT@ \
 	winsock/libwsock32.@LIBEXT@ \
-	winspool/libwinspool.@LIBEXT@ \
-	wnaspi32/libwnaspi32.@LIBEXT@
+	winspool/libwinspool.@LIBEXT@
 
 # extra names for dlls containing multiple spec files
 EXTRADLLNAMES = \
@@ -72,6 +72,7 @@
 	ver \
 	w32sys \
 	win32s16 \
+	winaspi \
 	winsock
 
 @MAKE_RULES@
@@ -212,8 +213,8 @@
 libwinspool.@LIBEXT@: winspool/libwinspool.@LIBEXT@
 	$(RM) $@ && $(LN_S) winspool/libwinspool.@LIBEXT@ $@
 
-libwnaspi32.@LIBEXT@: wnaspi32/libwnaspi32.@LIBEXT@
-	$(RM) $@ && $(LN_S) wnaspi32/libwnaspi32.@LIBEXT@ $@
+libwnaspi32.@LIBEXT@ libwinaspi.@LIBEXT@: winaspi/libwnaspi32.@LIBEXT@
+	$(RM) $@ && $(LN_S) winaspi/libwnaspi32.@LIBEXT@ $@
 
 libwsock32.@LIBEXT@ libwinsock.@LIBEXT@: winsock/libwsock32.@LIBEXT@
 	$(RM) $@ && $(LN_S) winsock/libwsock32.@LIBEXT@ $@
diff --git a/dlls/winaspi/.cvsignore b/dlls/winaspi/.cvsignore
index 227d839..0fb2dc0 100644
--- a/dlls/winaspi/.cvsignore
+++ b/dlls/winaspi/.cvsignore
@@ -1,3 +1,4 @@
-Makefile
 *.spec.c
 *.spec.glue.s
+Makefile
+libwnaspi32.so.1.0
diff --git a/dlls/winaspi/Makefile.in b/dlls/winaspi/Makefile.in
index c4c9c6a..0039878 100644
--- a/dlls/winaspi/Makefile.in
+++ b/dlls/winaspi/Makefile.in
@@ -1,17 +1,18 @@
-DEFS      = @DLLFLAGS@ -D__WINE__
 TOPSRCDIR = @top_srcdir@
 TOPOBJDIR = ../..
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
-MODULE    = winaspi
+MODULE    = wnaspi32
+SOVERSION = 1.0
+ALTNAMES  = winaspi
 
-SPEC_SRCS = winaspi.spec
+SPEC_SRCS = wnaspi32.spec winaspi.spec
 
 C_SRCS = \
-	winaspi16.c
+	aspi.c \
+	winaspi16.c \
+	winaspi32.c
 
-all: $(MODULE).o
-
-@MAKE_RULES@
+@MAKE_DLL_RULES@
 
 ### Dependencies:
diff --git a/dlls/winaspi/aspi.c b/dlls/winaspi/aspi.c
new file mode 100644
index 0000000..dae42fa
--- /dev/null
+++ b/dlls/winaspi/aspi.c
@@ -0,0 +1,347 @@
+/**************************************************************************
+ASPI routines
+(C) 2000 David Elliott <dfe@netnitco.net>
+Licensed under the WINE (X11) license
+*/
+
+/* These routines are to be called from either WNASPI32 or WINASPI */
+
+/* FIXME:
+ * - Registry format is stupid for now.. fix that later
+ * - No way to override automatic /proc detection, maybe provide an
+ *   HKEY_LOCAL_MACHINE\Software\Wine\Wine\Scsi regkey
+ * - Somewhat debating an #ifdef linux... technically all this code will
+ *   run on another UNIX.. it will fail nicely.
+ * - Please add support for mapping multiple channels on host adapters to
+ *   aspi controllers, e-mail me if you need help.
+ */
+
+/*
+Registry format is currently:
+HKEY_DYN_DATA
+	WineScsi
+		(default)=number of host adapters
+		hHHcCCtTTdDD=linux device name
+*/
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "debugtools.h"
+#include "winreg.h"
+#include "winerror.h"
+#include "winescsi.h"
+#include "file.h"
+
+DEFAULT_DEBUG_CHANNEL(aspi);
+
+/* Internal function prototypes */
+static void
+SCSI_GetProcinfo();
+
+/* Exported functions */
+void
+SCSI_Init()
+{
+	/* For now we just call SCSI_GetProcinfo */
+	SCSI_GetProcinfo();
+}
+
+int
+ASPI_GetNumControllers()
+{
+	HKEY hkeyScsi;
+	DWORD type = REG_DWORD;
+	DWORD num_ha = 0;
+	DWORD cbData = sizeof(num_ha);
+
+	if( RegOpenKeyExA(HKEY_DYN_DATA, KEYNAME_SCSI, 0, KEY_ALL_ACCESS, &hkeyScsi ) != ERROR_SUCCESS )
+	{
+		ERR("Could not open HEKY_DYN_DATA\\%s\n",KEYNAME_SCSI);
+		return 0;
+	}
+
+	if( RegQueryValueExA(hkeyScsi, NULL, NULL, &type, (LPBYTE)&num_ha, &cbData ) != ERROR_SUCCESS )
+	{
+		ERR("Could not query value HEKY_DYN_DATA\\%s\n",KEYNAME_SCSI);
+		num_ha=0;
+	}
+	RegCloseKey(hkeyScsi);
+	FIXME("Please fix to return number of controllers\n");
+	TRACE("Returning %ld host adapters\n", num_ha );
+	return num_ha;
+}
+
+BOOL
+SCSI_GetDeviceName( int h, int c, int t, int d, LPSTR devstr, LPDWORD lpcbData )
+{
+
+	char idstr[20];
+	HKEY hkeyScsi;
+	DWORD type;
+
+	if( RegOpenKeyExA(HKEY_DYN_DATA, KEYNAME_SCSI, 0, KEY_ALL_ACCESS, &hkeyScsi ) != ERROR_SUCCESS )
+	{
+		ERR("Could not open HEKY_DYN_DATA\\%s\n",KEYNAME_SCSI);
+		return FALSE;
+	}
+
+
+	sprintf(idstr, "h%02dc%02dt%02dd%02d", h, c, t, d);
+
+	if( RegQueryValueExA(hkeyScsi, idstr, NULL, &type, devstr, lpcbData) != ERROR_SUCCESS )
+	{
+		WARN("Could not query value HKEY_DYN_DATA\\%s\\%s\n",KEYNAME_SCSI, idstr);
+		RegCloseKey(hkeyScsi);
+		return FALSE;
+	}
+	RegCloseKey(hkeyScsi);
+
+	TRACE("scsi %s: Device name: %s\n",idstr,devstr);
+	return TRUE;
+}
+
+/* SCSI_GetHCforController
+ * RETURNS
+ * 	HIWORD: Host Adapter
+ * 	LOWORD: Channel
+ */
+DWORD
+ASPI_GetHCforController( int controller )
+{
+	DWORD retval;
+	FIXME("Please fix to map each channel of each host adapter to the proper ASPI controller number!\n");
+	retval = (controller << 16);
+	return retval;
+};
+
+int
+SCSI_OpenDevice( int h, int c, int t, int d )
+{
+	char devstr[20];
+	DWORD cbData = 20;
+	int fd = -1;
+
+	if(!SCSI_GetDeviceName( h, c, t, d, devstr, &cbData ))
+	{
+		WARN("Could not get device name for h%02dc%02dt%02dd%02d\n", h, c, t, d);
+		return -1;
+	}
+
+	TRACE("Opening device %s mode O_RDWR\n",devstr);
+	fd = open(devstr, O_RDWR);
+
+	if( fd < 0 )
+	{
+		TRACE("open failed\n");
+		FILE_SetDosError(); /* SetLastError() to errno */
+		TRACE("GetLastError: %ld\n", GetLastError());
+	}
+	return fd;
+}
+
+int
+SCSI_LinuxSetTimeout( int fd, int timeout )
+{
+	int retval;
+	TRACE("Setting timeout to %d jiffies\n", timeout);
+	retval=ioctl(fd,SG_SET_TIMEOUT,&timeout);
+	if(retval)
+	{
+		WARN("Could not set timeout errno=%d!\n",errno);
+	}
+	return retval;
+	
+}
+
+/* This function takes care of the write/read to the linux sg device.
+ * It returns TRUE or FALSE and uses FILE_SetDosError() to convert
+ * UNIX errno to Windows GetLastError().  The reason for that is that
+ * several programs will check that error and we might as well set
+ * it here.  We also return the value of the read call in
+ * lpcbBytesReturned.
+ */
+BOOL /* NOTE: This function SHOULD BLOCK */
+SCSI_LinuxDeviceIo( int fd,
+		struct sg_header * lpInBuffer, DWORD cbInBuffer,
+		struct sg_header * lpOutBuffer, DWORD cbOutBuffer,
+		LPDWORD lpcbBytesReturned )
+{
+	DWORD dwBytes;
+	DWORD save_error;
+
+	TRACE("Writing to Liunx sg device\n");
+	dwBytes = write( fd, lpInBuffer, cbInBuffer );
+	if( dwBytes != cbInBuffer )
+	{
+		FILE_SetDosError();
+		save_error = GetLastError();
+		WARN("Not enough bytes written to scsi device. bytes=%ld .. %ld\n", cbInBuffer, dwBytes );
+		if( save_error == ERROR_NOT_ENOUGH_MEMORY )
+			MESSAGE("Your Linux kernel was not able to handle the amount of data sent to the scsi device.  Try recompiling with a larger SG_BIG_BUFF value (kernel 2.0.x sg.h");
+		WARN("error= %ld\n", save_error );
+		*lpcbBytesReturned = 0;
+		return FALSE;
+	}
+	
+	TRACE("Reading reply from Linux sg device\n");
+	*lpcbBytesReturned = read( fd, lpOutBuffer, cbOutBuffer );
+	if( *lpcbBytesReturned != cbOutBuffer )
+	{
+		FILE_SetDosError();
+		save_error = GetLastError();
+		WARN("Not enough bytes read from scsi device. bytes=%ld .. %ld\n", cbOutBuffer, *lpcbBytesReturned);
+		WARN("error= %ld\n", save_error );
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/* Internal functions */
+struct LinuxProcScsiDevice
+{
+	int host;
+	int channel;
+	int target;
+	int lun;
+	char vendor[9];
+	char model[17];
+	char rev[5];
+	char type[33];
+	int ansirev;
+};
+
+static int
+SCSI_getprocentry( FILE * procfile, struct LinuxProcScsiDevice * dev )
+{
+	int result;
+	result = fscanf( procfile,
+		"Host: scsi%d Channel: %d Id: %d Lun: %d\n",
+		&dev->host,
+		&dev->channel,
+		&dev->target,
+		&dev->lun );
+	if( result == EOF )
+		return EOF;
+	if( result != 4 )
+		return 0;
+	result = fscanf( procfile,
+		"  Vendor: %8c Model: %16c Rev: %4c\n",
+		dev->vendor,
+		dev->model,
+		dev->rev );
+	if( result != 3 )
+		return 0;
+
+	result = fscanf( procfile,
+		"  Type:   %32c ANSI SCSI revision: %d\n",
+		dev->type,
+		&dev->ansirev );
+	if( result != 2 )
+		return 0;
+	/* Since we fscanf with %XXc instead of %s.. put a NULL at end */
+	dev->vendor[8] = 0;
+	dev->model[16] = 0;
+	dev->rev[4] = 0;
+	dev->type[32] = 0;
+
+	return 1;
+}
+
+static void
+SCSI_printprocentry( const struct LinuxProcScsiDevice * dev )
+{
+	TRACE( "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
+		dev->host,
+		dev->channel,
+		dev->target,
+		dev->lun );
+	TRACE( "  Vendor: %s Model: %s Rev: %s\n",
+		dev->vendor,
+		dev->model,
+		dev->rev );
+	TRACE( "  Type:   %s ANSI SCSI revision: %02d\n",
+		dev->type,
+		dev->ansirev );
+}
+
+static void
+SCSI_GetProcinfo()
+/* I'll admit, this function is somewhat of a mess... it was originally
+ * designed to make some sort of linked list then I realized that
+ * HKEY_DYN_DATA would be a lot less messy
+ */
+{
+	FILE * procfile = NULL;
+
+	int result = 0;
+
+	struct LinuxProcScsiDevice dev;
+
+	char idstr[20];
+	char devstr[20];
+
+	int devnum=0;
+	int num_ha = 0;
+
+	HKEY hkeyScsi;
+	DWORD disposition;
+
+	procfile = fopen( "/proc/scsi/scsi", "r" );
+	if( !procfile )
+	{
+		ERR("Could not open /proc/scsi/scsi\n");
+		return;
+	}
+
+	result = fscanf( procfile, "Attached devices: \n");
+	if( result != 0 )
+	{
+		ERR("Incorrect /proc/scsi/scsi format");
+		return;
+	}
+
+	if( RegCreateKeyExA(HKEY_DYN_DATA, KEYNAME_SCSI, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyScsi, &disposition ) != ERROR_SUCCESS )
+	{
+		ERR("Could not create HEKY_DYN_DATA\\%s\n",KEYNAME_SCSI);
+		return;
+	}
+
+	/* Read info for one device */
+	while( (result = SCSI_getprocentry(procfile, &dev)) > 0 )
+	{
+		/* Add to registry */
+
+		sprintf(idstr, "h%02dc%02dt%02dd%02d", dev.host, dev.channel, dev.target, dev.lun);
+		sprintf(devstr, "/dev/sg%c", 'a'+devnum);
+		if( RegSetValueExA(hkeyScsi, idstr, 0, REG_SZ, devstr, strlen(devstr)+1 ) != ERROR_SUCCESS )
+		{
+			ERR("Could not set value HEKY_DYN_DATA\\%s\\%s\n",KEYNAME_SCSI, idstr);
+		}
+
+		/* Debug output */
+		SCSI_printprocentry( &dev );
+
+		/* FIXME: We *REALLY* need number of controllers.. not ha */
+		/* num of hostadapters is highest ha + 1 */
+		if( dev.host >= num_ha )
+			num_ha = dev.host+1;
+		devnum++;
+	} /* while(1) */
+	if( result != EOF )
+	{
+		ERR("Incorrect /proc/scsi/scsi format");
+	}
+	fclose( procfile );
+	if( RegSetValueExA(hkeyScsi, NULL, 0, REG_DWORD, (LPBYTE)&num_ha, sizeof(num_ha) ) != ERROR_SUCCESS )
+	{
+		ERR("Could not set value HEKY_DYN_DATA\\%s\n",KEYNAME_SCSI);
+	}
+	RegCloseKey(hkeyScsi);
+	return;
+}
+
diff --git a/dlls/winaspi/winaspi16.c b/dlls/winaspi/winaspi16.c
index 48f1d43..7bbae1f 100644
--- a/dlls/winaspi/winaspi16.c
+++ b/dlls/winaspi/winaspi16.c
@@ -12,7 +12,9 @@
 
 #include "winbase.h"
 #include "aspi.h"
+#include "winescsi.h"
 #include "winaspi.h"
+#include "winescsi.h"
 #include "options.h"
 #include "heap.h"
 #include "debugtools.h"
@@ -520,33 +522,3 @@
 #endif
 }
 
-
-void WINAPI ASPI_DOS_func(CONTEXT86 *context)
-{
-	WORD *stack = CTX_SEG_OFF_TO_LIN(context, SS_reg(context), ESP_reg(context));
-	DWORD ptrSRB = *(DWORD *)&stack[2];
-
-	ASPI_SendASPICommand(ptrSRB, ASPI_DOS);
-
-	/* simulate a normal RETF sequence as required by DPMI CallRMProcFar */
-	EIP_reg(context) = *(stack++);
-	CS_reg(context)  = *(stack++);
-	ESP_reg(context) += 2*sizeof(WORD);
-}
-
-
-/* returns the address of a real mode callback to ASPI_DOS_func() */
-void ASPI_DOS_HandleInt(CONTEXT86 *context)
-{
-#ifdef linux
-	FARPROC16 *p = (FARPROC16 *)CTX_SEG_OFF_TO_LIN(context, DS_reg(context), EDX_reg(context));
-	if ((CX_reg(context) == 4) || (CX_reg(context) == 5))
-	{
-	*p = DPMI_AllocInternalRMCB(ASPI_DOS_func);
-	TRACE("allocated real mode proc %p\n", *p);
-	    AX_reg(context) = CX_reg(context);
-	}
-	else
-#endif
-	SET_CFLAG(context);
-}
diff --git a/dlls/wnaspi32/winaspi32.c b/dlls/winaspi/winaspi32.c
similarity index 99%
rename from dlls/wnaspi32/winaspi32.c
rename to dlls/winaspi/winaspi32.c
index ec226df..f5243de 100644
--- a/dlls/wnaspi32/winaspi32.c
+++ b/dlls/winaspi/winaspi32.c
@@ -12,6 +12,7 @@
 #include "winbase.h"
 #include "aspi.h"
 #include "wnaspi32.h"
+#include "winescsi.h"
 #include "options.h"
 #include "heap.h"
 #include "debugtools.h"
diff --git a/dlls/winaspi/winescsi.h b/dlls/winaspi/winescsi.h
new file mode 100644
index 0000000..f2fa449
--- /dev/null
+++ b/dlls/winaspi/winescsi.h
@@ -0,0 +1,101 @@
+#ifndef __WINESCSI_H__
+#define __WINESCSI_H__
+
+#ifdef linux
+/* Copy of info from 2.2.x kernel */
+#define SG_MAX_SENSE 16   /* too little, unlikely to change in 2.2.x */
+
+struct sg_header
+{
+    int pack_len;    /* [o] reply_len (ie useless), ignored as input */
+    int reply_len;   /* [i] max length of expected reply (inc. sg_header) */
+    int pack_id;     /* [io] id number of packet (use ints >= 0) */
+    int result;      /* [o] 0==ok, else (+ve) Unix errno (best ignored) */
+    unsigned int twelve_byte:1; 
+        /* [i] Force 12 byte command length for group 6 & 7 commands  */
+    unsigned int target_status:5;   /* [o] scsi status from target */
+    unsigned int host_status:8;     /* [o] host status (see "DID" codes) */
+    unsigned int driver_status:8;   /* [o] driver status+suggestion */
+    unsigned int other_flags:10;    /* unused */
+    unsigned char sense_buffer[SG_MAX_SENSE]; /* [o] Output in 3 cases:
+           when target_status is CHECK_CONDITION or 
+           when target_status is COMMAND_TERMINATED or
+           when (driver_status & DRIVER_SENSE) is true. */
+};      /* This structure is 36 bytes long on i386 */
+
+#define SCSI_OFF sizeof(struct sg_header)
+
+#define SG_SET_TIMEOUT	0x2201
+#define SG_GET_TIMEOUT	0x2202
+#define SCSI_DEFAULT_TIMEOUT 6000*5 /* 5 minutes */
+#endif
+
+
+/* RegKey used for SCSI info under HKEY_DYN_DATA */
+#define KEYNAME_SCSI "WineScsi"
+
+/* Function prototypes from dlls/wnaspi32/aspi.c */
+void
+SCSI_Init();
+
+int
+ASPI_GetNumControllers();
+
+int
+SCSI_OpenDevice( int h, int c, int t, int d );
+
+int
+SCSI_LinuxSetTimeout( int fd, int timeout );
+
+BOOL
+SCSI_LinuxDeviceIo( int fd,
+		struct sg_header * lpvInBuffer, DWORD cbInBuffer,
+		struct sg_header * lpvOutBuffer, DWORD cbOutBuffer,
+		LPDWORD lpcbBytesReturned );
+
+BOOL
+SCSI_GetDeviceName(int h, int c, int t, int d, LPSTR devstr, LPDWORD lpcbData);
+
+DWORD
+ASPI_GetHCforController( int controller );
+
+/*** This is where we throw some miscellaneous crap ***/
+
+#define ASPI_POSTING(prb) (prb->SRB_Flags & 0x1)
+
+/* WNASPI32/WINASPI defs */
+#define HOST_TO_TARGET(prb) (((prb->SRB_Flags>>3) & 0x3) == 0x2)
+#define TARGET_TO_HOST(prb) (((prb->SRB_Flags>>3) & 0x3) == 0x1)
+#define NO_DATA_TRANSFERED(prb) (((prb->SRB_Flags>>3) & 0x3) == 0x3)
+
+
+#define INQUIRY_VENDOR          8
+
+#define MUSTEK_SCSI_AREA_AND_WINDOWS 0x04
+#define MUSTEK_SCSI_READ_SCANNED_DATA 0x08
+#define MUSTEK_SCSI_GET_IMAGE_STATUS 0x0f
+#define MUSTEK_SCSI_ADF_AND_BACKTRACE 0x10
+#define MUSTEK_SCSI_CCD_DISTANCE 0x11
+#define MUSTEK_SCSI_START_STOP 0x1b
+
+
+#define INQURIY_CMDLEN 6
+#define INQURIY_REPLY_LEN 96
+#define INQUIRY_VENDOR 8
+
+#define SENSE_BUFFER(prb) (&prb->CDBByte[prb->SRB_CDBLen])
+
+/* Just a container for seeing what devices are open */
+struct ASPI_DEVICE_INFO {
+    struct ASPI_DEVICE_INFO *   next;
+    int                         fd;
+    int                         hostId;
+    int                         target;
+    int                         lun;
+};
+
+typedef struct ASPI_DEVICE_INFO ASPI_DEVICE_INFO;
+
+/*** End Miscellaneous crap ***/
+
+#endif /* #ifndef __WINESCSI_H */
diff --git a/dlls/wnaspi32/wnaspi32.spec b/dlls/winaspi/wnaspi32.spec
similarity index 100%
rename from dlls/wnaspi32/wnaspi32.spec
rename to dlls/winaspi/wnaspi32.spec
diff --git a/dlls/wnaspi32/.cvsignore b/dlls/wnaspi32/.cvsignore
deleted file mode 100644
index 490a329..0000000
--- a/dlls/wnaspi32/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-*.spec.c
-Makefile
-libwnaspi32.so.1.0
diff --git a/dlls/wnaspi32/Makefile.in b/dlls/wnaspi32/Makefile.in
deleted file mode 100644
index bbbb5f9..0000000
--- a/dlls/wnaspi32/Makefile.in
+++ /dev/null
@@ -1,15 +0,0 @@
-TOPSRCDIR = @top_srcdir@
-TOPOBJDIR = ../..
-SRCDIR    = @srcdir@
-VPATH     = @srcdir@
-MODULE    = wnaspi32
-SOVERSION = 1.0
-
-SPEC_SRCS = wnaspi32.spec
-
-C_SRCS = \
-	winaspi32.c
-
-@MAKE_DLL_RULES@
-
-### Dependencies:
diff --git a/include/aspi.h b/include/aspi.h
index 8a005e8..2e7cd22 100644
--- a/include/aspi.h
+++ b/include/aspi.h
@@ -1,4 +1,4 @@
-/* ASPI definitions used for both WNASPI16 and WNASPI32 */
+/* ASPI definitions used for both WINASPI and WNASPI32 */
 
 #ifndef __WINE_ASPI_H
 #define __WINE_ASPI_H
@@ -6,33 +6,75 @@
 #include "windef.h"
 
 #include "pshpack1.h"
-
-#define SS_PENDING      0x00
-#define SS_COMP         0x01
-#define SS_ABORTED      0x02
-#define SS_ERR          0x04
-#define SS_INVALID_HA   0x81
-#define SS_INVALID_SRB  0xe0
-#define SS_OLD_MANAGE   0xe1
-#define SS_ILLEGAL_MODE 0xe2
-#define SS_NO_ASPI      0xe3
-#define SS_FAILED_INIT  0xe4
-#define SS_ASPI_IS_BUSY 0xe5
-#define SS_BUFFER_TO_BIG        0xe6
-
-#define SC_HA_INQUIRY           0x00
-#define SC_GET_DEV_TYPE         0x01
-#define SC_EXEC_SCSI_CMD        0x02
-#define SC_ABORT_SRB            0x03
-#define SC_RESET_DEV            0x04
+#ifdef __cplusplus
+extern "C" {
+#endif /* #ifdef __cplusplus */
 
 
-/* Host adapter status codes */
-#define HASTAT_OK               0x00
-#define HASTAT_SEL_TO           0x11
-#define HASTAT_DO_DU            0x12
-#define HASTAT_BUS_FREE         0x13
-#define HASTAT_PHASE_ERR        0x14
+/* Stuff in BOTH spec */
+
+/* SCSI Miscellaneous Stuff */
+#define SENSE_LEN			14
+#define SRB_DIR_SCSI			0x00
+#define SRB_POSTING			0x01
+#define SRB_ENABLE_RESIDUAL_COUNT	0x04
+#define SRB_DIR_IN			0x08
+#define SRB_DIR_OUT			0x10
+
+/* ASPI Command Definitions */
+#define SC_HA_INQUIRY			0x00
+#define SC_GET_DEV_TYPE			0x01
+#define SC_EXEC_SCSI_CMD		0x02
+#define SC_ABORT_SRB			0x03
+#define SC_RESET_DEV			0x04
+#define SC_SET_HA_PARMS			0x05
+#define SC_GET_DISK_INFO		0x06
+
+/* SRB status codes */
+#define SS_PENDING			0x00
+#define SS_COMP				0x01
+#define SS_ABORTED			0x02
+#define SS_ABORT_FAIL			0x03
+#define SS_ERR				0x04
+
+#define SS_INVALID_CMD			0x80
+#define SS_INVALID_HA			0x81
+#define SS_NO_DEVICE			0x82
+
+#define SS_INVALID_SRB			0xE0
+#define SS_OLD_MANAGER			0xE1
+#define SS_BUFFER_ALIGN			0xE1 // Win32
+#define SS_ILLEGAL_MODE			0xE2
+#define SS_NO_ASPI			0xE3
+#define SS_FAILED_INIT			0xE4
+#define SS_ASPI_IS_BUSY			0xE5
+#define SS_BUFFER_TO_BIG		0xE6
+#define SS_MISMATCHED_COMPONENTS	0xE7 // DLLs/EXE version mismatch
+#define SS_NO_ADAPTERS			0xE8
+#define SS_INSUFFICIENT_RESOURCES	0xE9
+#define SS_ASPI_IS_SHUTDOWN		0xEA
+#define SS_BAD_INSTALL			0xEB
+
+
+/* Host status codes */
+#define HASTAT_OK			0x00
+#define HASTAT_SEL_TO			0x11
+#define HASTAT_DO_DU			0x12
+#define HASTAT_BUS_FREE			0x13
+#define HASTAT_PHASE_ERR		0x14
+
+#define HASTAT_TIMEOUT			0x09
+#define HASTAT_COMMAND_TIMEOUT		0x0B
+#define HASTAT_MESSAGE_REJECT		0x0D
+#define HASTAT_BUS_RESET		0x0E
+#define HASTAT_PARITY_ERROR		0x0F
+#define HASTAT_REQUEST_SENSE_FAILED	0x10
+
+
+
+
+
+/*********** OLD ****************/
 
 /* Target status codes */
 #define STATUS_GOOD             0x00
@@ -40,42 +82,13 @@
 #define STATUS_BUSY             0x08
 #define STATUS_RESCONF          0x18
 
-#ifdef linux
-
-/* This is a duplicate of the sg_header from /usr/src/linux/include/scsi/sg.h
- * kernel 2.0.30
- * This will probably break at some point, but for those who don't have
- * kernels installed, I think this should still work.
- *
- */
-
-struct sg_header
- {
-  int pack_len;    /* length of incoming packet <4096 (including header) */
-  int reply_len;   /* maximum length <4096 of expected reply */
-  int pack_id;     /* id number of packet */
-  int result;      /* 0==ok, otherwise refer to errno codes */
-  unsigned int twelve_byte:1; /* Force 12 byte command length for group 6 & 7
-commands  */
-  unsigned int target_status:5;   /* [o] scsi status from target */
-  unsigned int host_status:8;     /* [o] host status (see "DID" codes) */
-  unsigned int driver_status:8;   /* [o] driver status+suggestion */
-  unsigned int other_flags:10;    /* unused */
-  unsigned char sense_buffer[16]; /* used only by reads */
-  /* command follows then data for command */
- };
-
-#define SCSI_OFF sizeof(struct sg_header)
-#endif
-
 #define ASPI_POSTING(prb) (prb->SRB_Flags & 0x1)
 
+/* WNASPI32/WINASPI defs */
 #define HOST_TO_TARGET(prb) (((prb->SRB_Flags>>3) & 0x3) == 0x2)
 #define TARGET_TO_HOST(prb) (((prb->SRB_Flags>>3) & 0x3) == 0x1)
 #define NO_DATA_TRANSFERED(prb) (((prb->SRB_Flags>>3) & 0x3) == 0x3)
 
-#define SRB_ENABLE_RESIDUAL_COUNT 0x4
-#define SRB_EVENT_NOTIFY 0x40 /* Enable ASPI event notification */
 
 #define INQUIRY_VENDOR          8
 
@@ -107,18 +120,9 @@
 
 #define SENSE_BUFFER(prb) (&prb->CDBByte[prb->SRB_CDBLen])
 
-
-/* Just a container for seeing what devices are open */
-struct ASPI_DEVICE_INFO {
-    struct ASPI_DEVICE_INFO *   next;
-    int                         fd;
-    int                         hostId;
-    int                         target;
-    int                         lun;
-};
-
-typedef struct ASPI_DEVICE_INFO ASPI_DEVICE_INFO;
-
+#ifdef __cplusplus
+}
+#endif /* #ifdef __cplusplus */
 #include "poppack.h"
 
 #endif
diff --git a/include/winaspi.h b/include/winaspi.h
index 0be982e..4d79c4c 100644
--- a/include/winaspi.h
+++ b/include/winaspi.h
@@ -1,16 +1,31 @@
-#ifndef __WINE_WINASPI_H
-#define __WINE_WINASPI_H
+/**************************************************************************
+ * WINE winaspi.h
+ * This file should be source compatible with the Adaptec winaspi.h
+ * All DOS ASPI structures are the same as WINASPI
+ */
 
-#include "windef.h"
+/* If __WINE__ is not defined, extra typedefs are defined to be
+ * source compatible with the regular winaspi.h.
+ */
+#ifndef __WINASPI_H__
+#define __WINASPI_H__
+
+#define FAR
+/* Include base aspi defs */
+#include "aspi.h"
 
 #include "pshpack1.h"
+#ifdef __cplusplus
+extern "C" {
+#endif /* #ifdef __cplusplus */
 
+/* WINE SCSI Stuff */
 #define ASPI_DOS        1
 #define ASPI_WIN16      2
 
-typedef union SRB16 * LPSRB16;
+/* SRB HA_INQUIRY */
 
-typedef struct tagSRB_HaInquiry16 {
+struct tagSRB16_HaInquiry {
   BYTE	SRB_Cmd;
   BYTE	SRB_Status;
   BYTE	SRB_HaId;
@@ -23,9 +38,22 @@
   BYTE	HA_Identifier[16];
   BYTE	HA_Unique[16];
   BYTE	HA_ExtBuffer[4];
-} SRB_HaInquiry16 WINE_PACKED;
+} WINE_PACKED;
 
-typedef struct tagSRB_ExecSCSICmd16 {
+struct tagSRB16_GDEVBlock {
+  BYTE        SRB_Cmd;            /* ASPI command code = SC_GET_DEV_TYPE */
+  BYTE        SRB_Status;         /* ASPI command status byte */
+  BYTE        SRB_HaId;           /* ASPI host adapter number */
+  BYTE        SRB_Flags;          /* ASPI request flags */
+  DWORD       SRB_Hdr_Rsvd;       /* Reserved, MUST = 0 */
+  BYTE        SRB_Target;         /* Target's SCSI ID */
+  BYTE        SRB_Lun;            /* Target's LUN number */
+  BYTE        SRB_DeviceType;     /* Target's peripheral device type */
+} WINE_PACKED;
+
+
+
+struct tagSRB16_ExecSCSICmd {
   BYTE        SRB_Cmd;                /* ASPI command code	      (W)  */
   BYTE        SRB_Status;             /* ASPI command status byte     (R)  */
   BYTE        SRB_HaId;               /* ASPI host adapter number     (W)  */
@@ -47,18 +75,18 @@
    * BYTE        CDBByte[6];             * SCSI CDB                    (W) *
    * BYTE        SenseArea6[SENSE_LEN];  * Request Sense buffer 	(R) *
    */
-} SRB_ExecSCSICmd16 WINE_PACKED;
+} WINE_PACKED;
 
-typedef struct tagSRB_Abort16 {
+struct tagSRB16_Abort {
   BYTE        SRB_Cmd;            /* ASPI command code = SC_ABORT_SRB */
   BYTE        SRB_Status;         /* ASPI command status byte */
   BYTE        SRB_HaId;           /* ASPI host adapter number */
   BYTE        SRB_Flags;          /* ASPI request flags */
   DWORD       SRB_Hdr_Rsvd;       /* Reserved, MUST = 0 */
-  LPSRB16     SRB_ToAbort;        /* Pointer to SRB to abort */
-} SRB_Abort16 WINE_PACKED;
+  SEGPTR      SRB_ToAbort;        /* Pointer to SRB to abort */
+} WINE_PACKED;
 
-typedef struct tagSRB_BusDeviceReset16 {
+struct tagSRB16_BusDeviceReset {
   BYTE        SRB_Cmd;            /* ASPI command code = SC_RESET_DEV */
   BYTE        SRB_Status;         /* ASPI command status byte */
   BYTE        SRB_HaId;           /* ASPI host adapter number */
@@ -69,35 +97,79 @@
   BYTE        SRB_ResetRsvd1[14]; /* Reserved, MUST = 0 */
   BYTE        SRB_HaStat;         /* Host Adapter Status */
   BYTE        SRB_TargStat;       /* Target Status */
-  SEGPTR      SRB_PostProc;       /* Post routine */
+  FARPROC16   SRB_PostProc;       /* Post routine */
   BYTE        SRB_ResetRsvd2[34]; /* Reserved, MUST = 0 */
-} SRB_BusDeviceReset16 WINE_PACKED;
+} WINE_PACKED;
 
-typedef struct tagSRB_GDEVBlock16 {
-  BYTE        SRB_Cmd;            /* ASPI command code = SC_GET_DEV_TYPE */
+struct tagSRB16_Common {
+  BYTE        SRB_Cmd;            /* ASPI command code = SC_ABORT_SRB */
   BYTE        SRB_Status;         /* ASPI command status byte */
   BYTE        SRB_HaId;           /* ASPI host adapter number */
   BYTE        SRB_Flags;          /* ASPI request flags */
   DWORD       SRB_Hdr_Rsvd;       /* Reserved, MUST = 0 */
-  BYTE        SRB_Target;         /* Target's SCSI ID */
-  BYTE        SRB_Lun;            /* Target's LUN number */
-  BYTE        SRB_DeviceType;     /* Target's peripheral device type */
-} SRB_GDEVBlock16 WINE_PACKED;
+} WINE_PACKED;
 
-typedef struct tagSRB_Common16 {
-  BYTE	SRB_Cmd;
-} SRB_Common16;
-
-union SRB16 {
-  SRB_Common16		common;
-  SRB_HaInquiry16	inquiry;
-  SRB_ExecSCSICmd16	cmd;
-  SRB_Abort16		abort;
-  SRB_BusDeviceReset16	reset;
-  SRB_GDEVBlock16	devtype;
+union tagSRB16 {
+  struct tagSRB16_Common common;
+  struct tagSRB16_HaInquiry inquiry;
+  struct tagSRB16_ExecSCSICmd cmd;
+  struct tagSRB16_Abort abort;
+  struct tagSRB16_BusDeviceReset reset;
+  struct tagSRB16_GDEVBlock devtype;
 };
 
-typedef union SRB16 SRB16;
+#ifndef __WINE__
+/* These typedefs would conflict with WNASPI32 typedefs, but
+ * would make it easier to port WINASPI source to WINE */
+typedef struct tagSRB16_HaInquiry
+SRB_HAInquiry, *PSRB_HAInquiry, FAR *LPSRB_HAInquiry;
+
+typedef struct tagSRB16_GDEVBlock
+SRB_GDEVBlock, *PSRB_GDEVBlock, FAR *LPSRB_GDEVBlock;
+
+typedef struct tagSRB16_ExecSCSICmd
+SRB_ExecSCSICmd, *PSRB_ExecSCSICmd, FAR *LPSRB_ExecSCSICmd;
+
+typedef struct tagSRB16_Abort
+SRB_Abort, *PSRB_Abort, FAR *LPSRB_Abort;
+
+typedef struct tagSRB16_BusDeviceReset
+SRB_BusDeviceReset, *PSRB_BusDeviceReset, FAR *LPSRB_BusDeviceReset;
+
+typedef struct tagSRB16_Common
+SRB_Common, *PSRB_Common, FAR *LPSRB_Common;
+
+typedef union tagSRB16 SRB, FAR *LPSRB;
+
+extern WORD FAR PASCAL SendASPICommand( LPSRB );
+extern WORD FAR PASCAL GetASPISupportInfo( VOID );
+
+#endif
+
+/* These are the typedefs for WINE */
+typedef struct tagSRB16_HaInquiry
+SRB_HAInquiry16, *PSRB_HAInquiry16, FAR *LPSRB_HAInquiry16;
+
+typedef struct tagSRB16_GDEVBlock
+SRB_GDEVBlock16, *PSRB_GDEVBlock16, FAR *LPSRB_GDEVBlock16;
+
+typedef struct tagSRB16_ExecSCSICmd
+SRB_ExecSCSICmd16, *PSRB_ExecSCSICmd16, FAR *LPSRB_ExecSCSICmd16;
+
+typedef struct tagSRB16_Abort
+SRB_Abort16, *PSRB_Abort16, FAR *LPSRB_Abort16;
+
+typedef struct tagSRB16_BusDeviceReset
+SRB_BusDeviceReset16, *PSRB_BusDeviceReset16, FAR *LPSRB_BusDeviceReset16;
+
+typedef struct tagSRB16_Common
+SRB_Common16, *PSRB_Common16, FAR *LPSRB_Common16;
+
+typedef union tagSRB16 SRB16, FAR *LPSRB16;
+
+#ifdef __cplusplus
+}
+#endif /* #ifdef __cplusplus */
 
 #include "poppack.h"
 
diff --git a/include/wnaspi32.h b/include/wnaspi32.h
index 8945d30..c5fc1c6 100644
--- a/include/wnaspi32.h
+++ b/include/wnaspi32.h
@@ -1,17 +1,39 @@
-#ifndef __WINE_WNASPI32_H
-#define __WINE_WNASPI32_H
+#ifndef __WNASPI32_H__
+#define __WNASPI32_H__
 
-#include "windef.h"
+#define FAR
+/* This file should be 100% source compatible according to MSes docs and
+ * Adaptecs docs */
+/* Include base aspi defs */
+#include "aspi.h"
 
 #include "pshpack1.h"
+#ifdef __cplusplus
+extern "C" {
+#endif /* #ifdef __cplusplus */
 
-typedef union SRB * LPSRB;
+/* Additional definitions */
+/* SCSI Miscellaneous Stuff */
+#define SRB_EVENT_NOTIFY		0x40
+#define RESIDUAL_COUNT_SUPPORTED	0x02
+#define MAX_SRB_TIMEOUT			1080001u
+#define DEFAULT_SRB_TIMEOUT		1080001u
 
-#define SS_INVALID_CMD 0x80
-#define SS_INVALID_HA 0x81
-#define SS_NO_DEVICE 0x82
+/* These are defined by MS but not adaptec */
+#define SRB_DATA_SG_LIST		0x02
+#define WM_ASPIPOST			0x4D42
 
-typedef struct tagSRB_HaInquiry {
+
+/* ASPI Command Definitions */
+#define SC_RESCAN_SCSI_BUS		0x07
+#define SC_GETSET_TIMEOUTS		0x08
+
+/* SRB Status.. MS defined */
+#define SS_SECURITY_VIOLATION		0xE2 // Replaces SS_INVALID_MODE
+/*** END DEFS */
+
+/* SRB - HOST ADAPTER INQUIRY - SC_HA_INQUIRY */
+struct tagSRB32_HaInquiry {
  BYTE  SRB_Cmd;                 /* ASPI command code = SC_HA_INQUIRY */
  BYTE  SRB_Status;              /* ASPI command status byte */
  BYTE  SRB_HaId;                /* ASPI host adapter number */
@@ -23,9 +45,23 @@
  BYTE  HA_Identifier[16];       /* String describing the host adapter */
  BYTE  HA_Unique[16];           /* Host Adapter Unique parameters */
  WORD  HA_Rsvd1;
-} SRB_HaInquiry WINE_PACKED;
+} WINE_PACKED;
 
-typedef struct tagSRB_ExecSCSICmd {
+/* SRB - GET DEVICE TYPE - SC_GET_DEV_TYPE */
+struct tagSRB32_GDEVBlock {
+ BYTE  SRB_Cmd;                 /* ASPI command code = SC_GET_DEV_TYPE */
+ BYTE  SRB_Status;              /* ASPI command status byte */
+ BYTE  SRB_HaId;                /* ASPI host adapter number */
+ BYTE  SRB_Flags;               /* Reserved */
+ DWORD  SRB_Hdr_Rsvd;           /* Reserved */
+ BYTE  SRB_Target;              /* Target's SCSI ID */
+ BYTE  SRB_Lun;                 /* Target's LUN number */
+ BYTE  SRB_DeviceType;          /* Target's peripheral device type */
+ BYTE  SRB_Rsvd1;
+} WINE_PACKED;
+
+/* SRB - EXECUTE SCSI COMMAND - SC_EXEC_SCSI_CMD */
+struct tagSRB32_ExecSCSICmd {
   BYTE        SRB_Cmd;            /* ASPI command code = SC_EXEC_SCSI_CMD */
   BYTE        SRB_Status;         /* ASPI command status byte */
   BYTE        SRB_HaId;           /* ASPI host adapter number */
@@ -45,18 +81,20 @@
   BYTE        SRB_Rsvd3[16];      /* Reserved for expansion */
   BYTE        CDBByte[16];        /* SCSI CDB */
   BYTE        SenseArea[0];       /* Request sense buffer - var length */
-} SRB_ExecSCSICmd WINE_PACKED;
+} WINE_PACKED;
 
-typedef struct tagSRB_Abort {
+/* SRB - ABORT AN ARB - SC_ABORT_SRB */
+struct tagSRB32_Abort {
   BYTE        SRB_Cmd;            /* ASPI command code = SC_ABORT_SRB */
   BYTE        SRB_Status;         /* ASPI command status byte */
   BYTE        SRB_HaId;           /* ASPI host adapter number */
   BYTE        SRB_Flags;          /* Reserved */
   DWORD       SRB_Hdr_Rsvd;       /* Reserved, MUST = 0 */
-  LPSRB     SRB_ToAbort;        /* Pointer to SRB to abort */
-} SRB_Abort WINE_PACKED;
+  VOID        FAR *SRB_ToAbort;   /* Pointer to SRB to abort */
+} WINE_PACKED;
 
-typedef struct tagSRB_BusDeviceReset {
+/* SRB - BUS DEVICE RESET - SC_RESET_DEV */
+struct tagSRB32_BusDeviceReset {
  BYTE         SRB_Cmd;                  /* ASPI command code = SC_RESET_DEV */
  BYTE         SRB_Status;               /* ASPI command status byte */
  BYTE         SRB_HaId;                 /* ASPI host adapter number */
@@ -70,35 +108,68 @@
  void         (*SRB_PostProc)();        /* Post routine */
  void         *SRB_Rsvd2;               /* Reserved */
  BYTE         SRB_Rsvd3[32];            /* Reserved */
-} SRB_BusDeviceReset WINE_PACKED;
+} WINE_PACKED;
 
-typedef struct tagSRB_GDEVBlock {
- BYTE  SRB_Cmd;                 /* ASPI command code = SC_GET_DEV_TYPE */
- BYTE  SRB_Status;              /* ASPI command status byte */
- BYTE  SRB_HaId;                /* ASPI host adapter number */
- BYTE  SRB_Flags;               /* Reserved */
- DWORD  SRB_Hdr_Rsvd;           /* Reserved */
- BYTE  SRB_Target;              /* Target's SCSI ID */
- BYTE  SRB_Lun;                 /* Target's LUN number */
- BYTE  SRB_DeviceType;          /* Target's peripheral device type */
- BYTE  SRB_Rsvd1;
-} SRB_GDEVBlock WINE_PACKED;
+/* SRB - GET DISK INFORMATION - SC_GET_DISK_INFO */
+struct tagSRB32_GetDiskInfo {
+ BYTE         SRB_Cmd;                  /* ASPI command code = SC_RESET_DEV */
+ BYTE         SRB_Status;               /* ASPI command status byte */
+ BYTE         SRB_HaId;                 /* ASPI host adapter number */
+ BYTE         SRB_Flags;                /* Reserved */
+ DWORD        SRB_Hdr_Rsvd;             /* Reserved */
+ BYTE         SRB_Target;               /* Target's SCSI ID */
+ BYTE         SRB_Lun;                  /* Target's LUN number */
+ BYTE         SRB_DriveFlags;           /* Driver flags */
+ BYTE         SRB_Int13HDriveInfo;      /* Host Adapter Status */
+ BYTE         SRB_Heads;                /* Preferred number of heads trans */
+ BYTE         SRB_Sectors;              /* Preferred number of sectors trans */
+ BYTE         SRB_Rsvd1[10];            /* Reserved */
+} WINE_PACKED;
 
-typedef struct tagSRB_Common {
-  BYTE  SRB_Cmd;
-} SRB_Common;
+/* SRB header */
+struct tagSRB32_Header {
+ BYTE         SRB_Cmd;                  /* ASPI command code = SC_RESET_DEV */
+ BYTE         SRB_Status;               /* ASPI command status byte */
+ BYTE         SRB_HaId;                 /* ASPI host adapter number */
+ BYTE         SRB_Flags;                /* Reserved */
+ DWORD        SRB_Hdr_Rsvd;             /* Reserved */
+} WINE_PACKED;
 
-union SRB {
-  SRB_Common          common;
-  SRB_HaInquiry       inquiry;
-  SRB_ExecSCSICmd     cmd;
-  SRB_Abort           abort;
-  SRB_BusDeviceReset  reset;
-  SRB_GDEVBlock       devtype;
+union tagSRB32 {
+  struct tagSRB32_Header          common;
+  struct tagSRB32_HaInquiry       inquiry;
+  struct tagSRB32_ExecSCSICmd     cmd;
+  struct tagSRB32_Abort           abort;
+  struct tagSRB32_BusDeviceReset  reset;
+  struct tagSRB32_GDEVBlock       devtype;
 };
 
-typedef union SRB SRB;
+/* Typedefs */
+#define typedefSRB(name) \
+typedef struct tagSRB32_##name \
+SRB_##name##, *PSRB_##name
+typedefSRB(HaInquiry);
+typedefSRB(GDEVBlock);
+typedefSRB(ExecSCSICmd);
+typedefSRB(Abort);
+typedefSRB(BusDeviceReset);
+typedefSRB(GetDiskInfo);
+typedefSRB(Header);
+#undef typedefSRB
 
+typedef union tagSRB32 SRB, *PSRB, *LPSRB;
+
+/* Prototypes */
+extern DWORD __cdecl
+SendASPI32Command (PSRB);
+extern DWORD WINAPI
+GetASPI32SupportInfo (void);
+extern DWORD WINAPI
+GetASPI32DLLVersion(void);
+
+#ifdef __cplusplus
+}
+#endif /* #ifdef __cplusplus */
 #include "poppack.h"
 
-#endif /* __WINE_WNASPI32_H */
+#endif /* __WNASPI32_H__ */
diff --git a/msdos/Makefile.in b/msdos/Makefile.in
index bc1cae5..e1a2a0f 100644
--- a/msdos/Makefile.in
+++ b/msdos/Makefile.in
@@ -7,6 +7,7 @@
 
 C_SRCS = \
 	devices.c \
+	dosaspi.c \
 	dosconf.c \
 	dosmem.c \
 	dpmi.c \
diff --git a/msdos/dosaspi.c b/msdos/dosaspi.c
new file mode 100644
index 0000000..fdf12a5
--- /dev/null
+++ b/msdos/dosaspi.c
@@ -0,0 +1,209 @@
+#include "config.h"
+
+#include "winbase.h"
+#include "winaspi.h"
+#include "wnaspi32.h"
+#include "heap.h"
+#include "debugtools.h"
+#include "selectors.h"
+#include "miscemu.h" /* DOSMEM_* */
+#include "callback.h"
+#include "winerror.h"
+
+DEFAULT_DEBUG_CHANNEL(aspi)
+
+static HINSTANCE hWNASPI32 = INVALID_HANDLE_VALUE;
+static DWORD (__cdecl *pSendASPI32Command) (LPSRB) = NULL;
+
+static void
+DOSASPI_PostProc( SRB_ExecSCSICmd *lpPRB )
+{
+	DWORD ptrSRB;
+	LPSRB16 lpSRB16;
+
+
+	memcpy(&ptrSRB,(LPBYTE)(lpPRB+1)+lpPRB->SRB_SenseLen,sizeof(DWORD));
+	TRACE("Copying data back to DOS client at 0x%8lx\n",ptrSRB);
+	lpSRB16 = DOSMEM_MapRealToLinear(ptrSRB);
+	lpSRB16->cmd.SRB_TargStat = lpPRB->SRB_TargStat;
+	lpSRB16->cmd.SRB_HaStat = lpPRB->SRB_HaStat;
+	memcpy((LPBYTE)(lpSRB16+1)+lpSRB16->cmd.SRB_CDBLen,&lpPRB->SenseArea[0],lpSRB16->cmd.SRB_SenseLen);
+
+	/* Now do posting */
+	if( lpPRB->SRB_Status == SS_SECURITY_VIOLATION )
+	{
+		/* SS_SECURITY_VIOLATION isn't defined in DOS ASPI */
+		TRACE("Returning SS_NO_DEVICE for SS_SECURITY_VIOLATION\n");
+		lpPRB->SRB_Status = SS_NO_DEVICE;
+	}
+
+	lpSRB16->cmd.SRB_Status = lpPRB->SRB_Status;
+	TRACE("SRB_Status = 0x%x\n", lpPRB->SRB_Status);
+
+	HeapFree(GetProcessHeap(),0,lpPRB);
+
+	if( (lpSRB16->cmd.SRB_Flags & SRB_POSTING) && lpSRB16->cmd.SRB_PostProc )
+	{
+		CONTEXT86 ctx;
+/* The stack should look like this on entry to proc
+ * NOTE: the SDK draws the following diagram bass akwards, use this one
+ * to avoid being confused.  Remember, the act of pushing something on
+ * an intel stack involves decreasing the stack pointer by the size of
+ * the data, and then copying the data at the new SP.
+ */
+/***************************
+ * ... Other crap that is already on the stack ...
+ * Segment of SRB Pointer		<- SP+6
+ * Offset of SRB Pointer		<- SP+4
+ * Segment of return address		<- SP+2
+ * Offset of return address		<- SP+0
+ */ 
+		/* FIXME: I am about 99% sure what is here is correct,
+		 * but this code has never been tested (and probably
+		 * won't be either until someone finds a DOS program
+		 * that actually uses a Post Routine) */
+
+		/* Zero everything */
+		memset(&ctx, 0, sizeof(ctx));
+		/* CS:IP is routine to call */
+		CS_reg(&ctx) = SELECTOROF(lpSRB16->cmd.SRB_PostProc);
+		EIP_reg(&ctx) = OFFSETOF(lpSRB16->cmd.SRB_PostProc);
+		/* DPMI_CallRMProc will push the pointer to the stack
+		 * it is given (in this case &ptrSRB) with length
+		 * 2*sizeof(WORD), that is, it copies the the contents
+		 * of ptrSRB onto the stack, and decs sp by 2*sizeof(WORD).
+		 * After doing that, it pushes the return address
+		 * onto the stack (so we don't need to worry about that)
+		 * So the stack should be okay for the PostProc
+		 */
+		if(DPMI_CallRMProc(&ctx, (LPWORD)&ptrSRB, 2, FALSE))
+		{
+			TRACE("DPMI_CallRMProc returned nonzero (error) status\n");
+		}
+	} /* if ((SRB_Flags&SRB_POSTING) && SRB_PostProc) */
+}
+
+static 
+DWORD ASPI_SendASPIDOSCommand(DWORD ptrSRB)
+{
+	PSRB_ExecSCSICmd lpPRB;
+	DWORD retval;
+	union tagSRB16 * lpSRB16;
+
+	lpSRB16 = DOSMEM_MapRealToLinear(ptrSRB);
+
+	retval = SS_ERR;
+	switch( lpSRB16->common.SRB_Cmd )
+	{
+	case SC_HA_INQUIRY:
+		TRACE("SC_HA_INQUIRY\n");
+		/* Format is identical in this case */
+		retval = (*pSendASPI32Command)((LPSRB)lpSRB16);
+		break;
+	case SC_GET_DEV_TYPE:
+		TRACE("SC_GET_DEV_TYPE\n");
+		/* Format is identical in this case */
+		retval = (*pSendASPI32Command)((LPSRB)lpSRB16);
+		break;
+	case SC_EXEC_SCSI_CMD:
+		TRACE("SC_EXEC_SCSI_CMD\n");
+		TRACE("Copying data from DOS client at 0x%8lx\n",ptrSRB);
+		lpPRB = HeapAlloc(GetProcessHeap(),0,sizeof(SRB)+lpSRB16->cmd.SRB_SenseLen+sizeof(DWORD));
+#define srb_dos_to_w32(name) \
+		lpPRB->SRB_##name = lpSRB16->cmd.SRB_##name
+
+		srb_dos_to_w32(Cmd);
+		srb_dos_to_w32(Status);
+		srb_dos_to_w32(HaId);
+		srb_dos_to_w32(BufLen);
+		srb_dos_to_w32(SenseLen);
+		srb_dos_to_w32(CDBLen);
+		srb_dos_to_w32(Target);
+		srb_dos_to_w32(Lun);
+#undef srb_dos_to_w32
+
+		/* Allow certain flags to go on to WNASPI32, we also need
+		 * to make sure SRB_POSTING is enabled */
+		lpPRB->SRB_Flags = SRB_POSTING | (lpSRB16->cmd.SRB_Flags&(SRB_DIR_IN|SRB_DIR_OUT|SRB_ENABLE_RESIDUAL_COUNT));
+
+		/* Pointer to data buffer */
+		lpPRB->SRB_BufPointer = DOSMEM_MapRealToLinear(lpSRB16->cmd.SRB_BufPointer);
+		/* Copy CDB in */
+		memcpy(&lpPRB->CDBByte[0],&lpSRB16->cmd.CDBByte[0],lpSRB16->cmd.SRB_CDBLen);
+
+		/* Set post proc to our post proc */
+		lpPRB->SRB_PostProc = &DOSASPI_PostProc;
+
+		/* Stick the DWORD after all the sense info */
+		memcpy((LPBYTE)(lpPRB+1)+lpPRB->SRB_SenseLen,&ptrSRB,sizeof(DWORD));
+		retval = (*pSendASPI32Command)((LPSRB)lpPRB);
+		break;
+	case SC_ABORT_SRB:
+		TRACE("SC_ABORT_SRB\n");
+		/* Would need some sort of table of active shit */
+		break;
+	case SC_RESET_DEV:
+		TRACE("SC_RESET_DEV\n");
+		break;
+	default:
+		TRACE("Unkown command code\n");
+		break;
+	}
+
+	TRACE("Returning %lx\n", retval );
+	return retval;
+}
+
+void WINAPI ASPI_DOS_func(CONTEXT86 *context)
+{
+	WORD *stack = CTX_SEG_OFF_TO_LIN(context, SS_reg(context), ESP_reg(context));
+	DWORD ptrSRB = *(DWORD *)&stack[2];
+
+	ASPI_SendASPIDOSCommand(ptrSRB);
+
+	/* simulate a normal RETF sequence as required by DPMI CallRMProcFar */
+	EIP_reg(context) = *(stack++);
+	CS_reg(context)  = *(stack++);
+	ESP_reg(context) += 2*sizeof(WORD);
+}
+
+
+/* returns the address of a real mode callback to ASPI_DOS_func() */
+void ASPI_DOS_HandleInt(CONTEXT86 *context)
+{
+	FARPROC16 *p = (FARPROC16 *)CTX_SEG_OFF_TO_LIN(context, DS_reg(context), EDX_reg(context));
+	TRACE("DOS ASPI opening\n");
+	if ((CX_reg(context) == 4) || (CX_reg(context) == 5))
+	{
+		if( hWNASPI32 == INVALID_HANDLE_VALUE )
+		{
+			TRACE("Loading WNASPI32\n");
+			hWNASPI32 = LoadLibraryExA("WNASPI32", NULL, 0);
+		}
+
+		if( hWNASPI32 == INVALID_HANDLE_VALUE )
+		{
+			ERR("Error loading WNASPI32\n");
+			goto error_exit;
+		}
+
+		/* Get SendASPI32Command by Ordinal 2 */
+		/* Cast to correct argument/return types */
+		pSendASPI32Command = (DWORD (*)(LPSRB))GetProcAddress(hWNASPI32, (LPBYTE)2);
+		if( !pSendASPI32Command )
+		{
+			ERR("Error getting ordinal 2 from WNASPI32\n");
+			goto error_exit;
+		}
+
+		*p = DPMI_AllocInternalRMCB(ASPI_DOS_func);
+		TRACE("allocated real mode proc %p\n", *p);
+		AX_reg(context) = CX_reg(context);
+
+		return;
+	}
+error_exit:
+	/* Return some error... General Failure sounds okay */
+	AX_reg(context) = ERROR_GEN_FAILURE;
+	SET_CFLAG(context);
+}