- 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/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);
+}