4 #include "wine/windef16.h"
5 #include "wine/winaspi.h"
7 #include "debugtools.h"
8 #include "miscemu.h" /* DOSMEM_* */
12 DEFAULT_DEBUG_CHANNEL(aspi
);
14 static HINSTANCE hWNASPI32
= INVALID_HANDLE_VALUE
;
15 static DWORD (__cdecl
*pSendASPI32Command
) (LPSRB
) = NULL
;
18 DOSASPI_PostProc( SRB_ExecSCSICmd
*lpPRB
)
24 memcpy(&ptrSRB
,lpPRB
->SenseArea
+ lpPRB
->SRB_SenseLen
,sizeof(DWORD
));
25 TRACE("Copying data back to DOS client at 0x%8lx\n",ptrSRB
);
26 lpSRB16
= DOSMEM_MapRealToLinear(ptrSRB
);
27 lpSRB16
->cmd
.SRB_TargStat
= lpPRB
->SRB_TargStat
;
28 lpSRB16
->cmd
.SRB_HaStat
= lpPRB
->SRB_HaStat
;
29 memcpy(lpSRB16
->cmd
.CDBByte
+ lpSRB16
->cmd
.SRB_CDBLen
,lpPRB
->SenseArea
,lpSRB16
->cmd
.SRB_SenseLen
);
32 if( lpPRB
->SRB_Status
== SS_SECURITY_VIOLATION
)
34 /* SS_SECURITY_VIOLATION isn't defined in DOS ASPI */
35 TRACE("Returning SS_NO_DEVICE for SS_SECURITY_VIOLATION\n");
36 lpPRB
->SRB_Status
= SS_NO_DEVICE
;
39 lpSRB16
->cmd
.SRB_Status
= lpPRB
->SRB_Status
;
40 TRACE("SRB_Status = 0x%x\n", lpPRB
->SRB_Status
);
42 HeapFree(GetProcessHeap(),0,lpPRB
);
44 if( (lpSRB16
->cmd
.SRB_Flags
& SRB_POSTING
) && lpSRB16
->cmd
.SRB_PostProc
)
47 /* The stack should look like this on entry to proc
48 * NOTE: the SDK draws the following diagram bass akwards, use this one
49 * to avoid being confused. Remember, the act of pushing something on
50 * an intel stack involves decreasing the stack pointer by the size of
51 * the data, and then copying the data at the new SP.
53 /***************************
54 * ... Other crap that is already on the stack ...
55 * Segment of SRB Pointer <- SP+6
56 * Offset of SRB Pointer <- SP+4
57 * Segment of return address <- SP+2
58 * Offset of return address <- SP+0
60 /* FIXME: I am about 99% sure what is here is correct,
61 * but this code has never been tested (and probably
62 * won't be either until someone finds a DOS program
63 * that actually uses a Post Routine) */
66 memset(&ctx
, 0, sizeof(ctx
));
67 /* CS:IP is routine to call */
68 ctx
.SegCs
= SELECTOROF(lpSRB16
->cmd
.SRB_PostProc
);
69 ctx
.Eip
= OFFSETOF(lpSRB16
->cmd
.SRB_PostProc
);
70 /* DPMI_CallRMProc will push the pointer to the stack
71 * it is given (in this case &ptrSRB) with length
72 * 2*sizeof(WORD), that is, it copies the the contents
73 * of ptrSRB onto the stack, and decs sp by 2*sizeof(WORD).
74 * After doing that, it pushes the return address
75 * onto the stack (so we don't need to worry about that)
76 * So the stack should be okay for the PostProc
78 if(DPMI_CallRMProc(&ctx
, (LPWORD
)&ptrSRB
, 2, FALSE
))
80 TRACE("DPMI_CallRMProc returned nonzero (error) status\n");
82 } /* if ((SRB_Flags&SRB_POSTING) && SRB_PostProc) */
86 DWORD
ASPI_SendASPIDOSCommand(DWORD ptrSRB
)
88 PSRB_ExecSCSICmd lpPRB
;
90 union tagSRB16
* lpSRB16
;
92 lpSRB16
= DOSMEM_MapRealToLinear(ptrSRB
);
95 switch( lpSRB16
->common
.SRB_Cmd
)
98 TRACE("SC_HA_INQUIRY\n");
99 /* Format is identical in this case */
100 retval
= (*pSendASPI32Command
)((LPSRB
)lpSRB16
);
102 case SC_GET_DEV_TYPE
:
103 TRACE("SC_GET_DEV_TYPE\n");
104 /* Format is identical in this case */
105 retval
= (*pSendASPI32Command
)((LPSRB
)lpSRB16
);
107 case SC_EXEC_SCSI_CMD
:
108 TRACE("SC_EXEC_SCSI_CMD\n");
109 TRACE("Copying data from DOS client at 0x%8lx\n",ptrSRB
);
110 lpPRB
= HeapAlloc(GetProcessHeap(),0,sizeof(SRB
)+lpSRB16
->cmd
.SRB_SenseLen
+sizeof(DWORD
));
111 #define srb_dos_to_w32(name) \
112 lpPRB->SRB_##name = lpSRB16->cmd.SRB_##name
115 srb_dos_to_w32(Status
);
116 srb_dos_to_w32(HaId
);
117 srb_dos_to_w32(BufLen
);
118 srb_dos_to_w32(SenseLen
);
119 srb_dos_to_w32(CDBLen
);
120 srb_dos_to_w32(Target
);
122 #undef srb_dos_to_w32
124 /* Allow certain flags to go on to WNASPI32, we also need
125 * to make sure SRB_POSTING is enabled */
126 lpPRB
->SRB_Flags
= SRB_POSTING
| (lpSRB16
->cmd
.SRB_Flags
&(SRB_DIR_IN
|SRB_DIR_OUT
|SRB_ENABLE_RESIDUAL_COUNT
));
128 /* Pointer to data buffer */
129 lpPRB
->SRB_BufPointer
= DOSMEM_MapRealToLinear(lpSRB16
->cmd
.SRB_BufPointer
);
131 memcpy(&lpPRB
->CDBByte
[0],&lpSRB16
->cmd
.CDBByte
[0],lpSRB16
->cmd
.SRB_CDBLen
);
133 /* Set post proc to our post proc */
134 lpPRB
->SRB_PostProc
= &DOSASPI_PostProc
;
136 /* Stick the DWORD after all the sense info */
137 memcpy(lpPRB
->SenseArea
+ lpPRB
->SRB_SenseLen
,&ptrSRB
,sizeof(DWORD
));
138 retval
= (*pSendASPI32Command
)((LPSRB
)lpPRB
);
141 TRACE("SC_ABORT_SRB\n");
142 /* Would need some sort of table of active shit */
145 TRACE("SC_RESET_DEV\n");
148 TRACE("Unkown command code\n");
152 TRACE("Returning %lx\n", retval
);
156 void WINAPI
ASPI_DOS_func(CONTEXT86
*context
)
158 WORD
*stack
= CTX_SEG_OFF_TO_LIN(context
, context
->SegSs
, context
->Esp
);
159 DWORD ptrSRB
= *(DWORD
*)&stack
[2];
161 ASPI_SendASPIDOSCommand(ptrSRB
);
163 /* simulate a normal RETF sequence as required by DPMI CallRMProcFar */
164 context
->Eip
= *(stack
++);
165 context
->SegCs
= *(stack
++);
166 context
->Esp
+= 2*sizeof(WORD
);
170 /* returns the address of a real mode callback to ASPI_DOS_func() */
171 void ASPI_DOS_HandleInt(CONTEXT86
*context
)
173 FARPROC16
*p
= (FARPROC16
*)CTX_SEG_OFF_TO_LIN(context
, context
->SegDs
, context
->Edx
);
174 TRACE("DOS ASPI opening\n");
175 if ((CX_reg(context
) == 4) || (CX_reg(context
) == 5))
177 if( hWNASPI32
== INVALID_HANDLE_VALUE
)
179 TRACE("Loading WNASPI32\n");
180 hWNASPI32
= LoadLibraryExA("WNASPI32", 0, 0);
183 if( hWNASPI32
== INVALID_HANDLE_VALUE
)
185 ERR("Error loading WNASPI32\n");
189 /* Get SendASPI32Command by Ordinal 2 */
190 /* Cast to correct argument/return types */
191 pSendASPI32Command
= (DWORD (*)(LPSRB
))GetProcAddress(hWNASPI32
, (LPBYTE
)2);
192 if( !pSendASPI32Command
)
194 ERR("Error getting ordinal 2 from WNASPI32\n");
198 *p
= DPMI_AllocInternalRMCB(ASPI_DOS_func
);
199 TRACE("allocated real mode proc %p\n", *p
);
200 AX_reg(context
) = CX_reg(context
);
205 /* Return some error... General Failure sounds okay */
206 AX_reg(context
) = ERROR_GEN_FAILURE
;