Commit c3bcd6ce authored by David Elliott's avatar David Elliott Committed by Alexandre Julliard

- 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).
parent 5f3b1b0c
......@@ -37,7 +37,6 @@ LIBSUBDIRS = \
dlls/mouse \
dlls/mpr \
dlls/ntdll \
dlls/winaspi \
files \
graphics \
graphics/enhmetafiledrv \
......@@ -114,7 +113,6 @@ LIBOBJS = \
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 \
......
......@@ -6231,7 +6231,6 @@ dlls/winmm/wavemap/Makefile
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/wavemap/Makefile
dlls/winmm/wineoss/Makefile
dlls/winsock/Makefile
dlls/winspool/Makefile
dlls/wnaspi32/Makefile
documentation/Makefile
documentation/wine.conf.man
documentation/wine.man
......
......@@ -993,7 +993,6 @@ dlls/winmm/wavemap/Makefile
dlls/winmm/wineoss/Makefile
dlls/winsock/Makefile
dlls/winspool/Makefile
dlls/wnaspi32/Makefile
documentation/Makefile
documentation/wine.conf.man
documentation/wine.man
......
......@@ -35,10 +35,11 @@ DLLFILES = \
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 @@ DLLFILES = \
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 @@ EXTRADLLNAMES = \
ver \
w32sys \
win32s16 \
winaspi \
winsock
@MAKE_RULES@
......@@ -212,8 +213,8 @@ libwinmm.@LIBEXT@ libmmsystem.@LIBEXT@: winmm/libwinmm.@LIBEXT@
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@ $@
......
Makefile
*.spec.c
*.spec.glue.s
Makefile
libwnaspi32.so.1.0
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:
/**************************************************************************
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;
}
......@@ -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 @@ DWORD WINAPI GetASPIDLLVersion16()
#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);
}
......@@ -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"
......
#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 */
*.spec.c
Makefile
libwnaspi32.so.1.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:
/* 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
/* 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
#ifdef __cplusplus
extern "C" {
#endif /* #ifdef __cplusplus */
/* 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 @@ commands */
#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
#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 @@ typedef struct tagSRB_HaInquiry16 {
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 @@ typedef struct tagSRB_ExecSCSICmd16 {
* 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 @@ typedef struct tagSRB_BusDeviceReset16 {
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"
......
#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 @@ typedef struct tagSRB_HaInquiry {
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 @@ typedef struct tagSRB_ExecSCSICmd {
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 @@ typedef struct tagSRB_BusDeviceReset {
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;
typedef struct tagSRB_Common {
BYTE SRB_Cmd;
} SRB_Common;
union SRB {
SRB_Common common;
SRB_HaInquiry inquiry;
SRB_ExecSCSICmd cmd;
SRB_Abort abort;
SRB_BusDeviceReset reset;
SRB_GDEVBlock devtype;
/* 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;
/* 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 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__ */
......@@ -7,6 +7,7 @@ MODULE = msdos
C_SRCS = \
devices.c \
dosaspi.c \
dosconf.c \
dosmem.c \
dpmi.c \
......
#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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment