Here is the new DOS ASPI layer, it is now located in msdos/dosaspi.c.
This basically loads up WNASPI32 and translates from DOS ASPI to
WNASPI32 when appropriate.  In the SC_EXEC_SCSI_CMD case it actually
puts the DOS pointer to the original DOS SRB just after the sense info
in the WNASPI32 SRB (that way the PostProc can use it).

I have no clue if this is actually going to work right with the current
WNASPI32 (it should) but it works fine with my heavily hacked with copy
(which I'll send in another RFC for tomorrow).

I still haven't gotten a chance to work on WINASPI, but I think I am
going to be implementing it basically the same way as this (that is,
load up WNASPI32 and translate calls).

-Dave
#include "config.h"

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <memory.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>

#include "winbase.h"
#include "winescsi.h"
#include "winaspi.h"
#include "wnaspi32.h"
#include "options.h"
#include "heap.h"
#include "debugtools.h"
#include "selectors.h"
#include "miscemu.h"
#include "ldt.h"
#include "callback.h"
#include "module.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_COMP;
                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 & 0x1) && lpSRB16->cmd.SRB_PostProc )
        {
                SEGPTR spPRB = MapLS(lpSRB16);
                TRACE("Calling PostProc\n");
                Callbacks->CallASPIPostProc(lpSRB16->cmd.SRB_PostProc, ptrSRB);
                UnMapLS(spPRB);
        }
}

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 */
                pSendASPI32Command = 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:
        AX_reg(context) = 0; // Set Error code to something
        SET_CFLAG(context);
}

Reply via email to