16 #include "selectors.h"
22 * 1) Residual byte length reporting not handled
23 * 2) Make this code re-entrant for multithreading
24 * 3) Only linux supported so far
29 ASPI_OpenDevice32(SRB_ExecSCSICmd32
*prb
)
34 ASPI_DEVICE_INFO
*curr
;
36 /* search list of devices to see if we've opened it already.
37 * There is not an explicit open/close in ASPI land, so hopefully
38 * keeping a device open won't be a problem.
41 for (curr
= ASPI_open_devices
; curr
; curr
= curr
->next
) {
42 if (curr
->hostId
== prb
->SRB_HaId
&&
43 curr
->target
== prb
->SRB_Target
&&
44 curr
->lun
== prb
->SRB_Lun
) {
49 /* device wasn't cached, go ahead and open it */
50 sprintf(idstr
, "scsi c%1dt%1dd%1d", prb
->SRB_HaId
, prb
->SRB_Target
, prb
->SRB_Lun
);
52 if (!PROFILE_GetWineIniString(idstr
, "Device", "", device_str
, sizeof(device_str
))) {
53 TRACE(aspi
, "Trying to open unlisted scsi device %s\n", idstr
);
57 TRACE(aspi
, "Opening device %s=%s\n", idstr
, device_str
);
59 fd
= open(device_str
, O_RDWR
);
61 int save_error
= errno
;
62 ERR(aspi
, "Error opening device %s, errno=%d\n", device_str
, save_error
);
66 /* device is now open */
67 curr
= HeapAlloc( SystemHeap
, 0, sizeof(ASPI_DEVICE_INFO
) );
69 curr
->hostId
= prb
->SRB_HaId
;
70 curr
->target
= prb
->SRB_Target
;
71 curr
->lun
= prb
->SRB_Lun
;
73 /* insert new record at beginning of open device list */
74 curr
->next
= ASPI_open_devices
;
75 ASPI_open_devices
= curr
;
81 ASPI_DebugPrintCmd32(SRB_ExecSCSICmd32
*prb
)
86 dbg_decl_str(aspi
, 512);
88 switch (prb
->CDBByte
[0]) {
91 TRACE(aspi
, "\tEVPD: %d\n", prb
->CDBByte
[1] & 1);
92 TRACE(aspi
, "\tLUN: %d\n", (prb
->CDBByte
[1] & 0xc) >> 1);
93 TRACE(aspi
, "\tPAGE CODE: %d\n", prb
->CDBByte
[2]);
94 TRACE(aspi
, "\tALLOCATION LENGTH: %d\n", prb
->CDBByte
[4]);
95 TRACE(aspi
, "\tCONTROL: %d\n", prb
->CDBByte
[5]);
99 TRACE(aspi
, "Transfer Length: %d\n", prb
->CDBByte
[4]);
103 TRACE(aspi
, "Host Adapter: %d\n", prb
->SRB_HaId
);
104 TRACE(aspi
, "Flags: %d\n", prb
->SRB_Flags
);
105 if (TARGET_TO_HOST(prb
)) {
106 TRACE(aspi
, "\tData transfer: Target to host. Length checked.\n");
108 else if (HOST_TO_TARGET(prb
)) {
109 TRACE(aspi
, "\tData transfer: Host to target. Length checked.\n");
111 else if (NO_DATA_TRANSFERED(prb
)) {
112 TRACE(aspi
, "\tData transfer: none\n");
115 WARN(aspi
, "\tTransfer by scsi cmd. Length not checked.\n");
118 TRACE(aspi
, "\tResidual byte length reporting %s\n", prb
->SRB_Flags
& 0x4 ? "enabled" : "disabled");
119 TRACE(aspi
, "\tLinking %s\n", prb
->SRB_Flags
& 0x2 ? "enabled" : "disabled");
120 TRACE(aspi
, "\tPosting %s\n", prb
->SRB_Flags
& 0x1 ? "enabled" : "disabled");
121 TRACE(aspi
, "Target: %d\n", prb
->SRB_Target
);
122 TRACE(aspi
, "Lun: %d\n", prb
->SRB_Lun
);
123 TRACE(aspi
, "BufLen: %ld\n", prb
->SRB_BufLen
);
124 TRACE(aspi
, "SenseLen: %d\n", prb
->SRB_SenseLen
);
125 TRACE(aspi
, "BufPtr: %p\n", prb
->SRB_BufPointer
);
126 TRACE(aspi
, "CDB Length: %d\n", prb
->SRB_CDBLen
);
127 TRACE(aspi
, "POST Proc: %lx\n", (DWORD
) prb
->SRB_PostProc
);
128 cdb
= &prb
->CDBByte
[0];
129 cmd
= prb
->CDBByte
[0];
130 for (i
= 0; i
< prb
->SRB_CDBLen
; i
++) {
131 if (i
!= 0) dsprintf(aspi
, ",");
132 dsprintf(aspi
, "%02x", *cdb
++);
134 TRACE(aspi
, "CDB buffer[%s]\n", dbg_str(aspi
));
138 ASPI_PrintSenseArea32(SRB_ExecSCSICmd32
*prb
)
142 dbg_decl_str(aspi
, 512);
144 cdb
= &prb
->CDBByte
[0];
145 for (i
= 0; i
< prb
->SRB_SenseLen
; i
++) {
146 if (i
) dsprintf(aspi
, ",");
147 dsprintf(aspi
, "%02x", *cdb
++);
149 TRACE(aspi
, "SenseArea[%s]\n", dbg_str(aspi
));
153 ASPI_DebugPrintResult32(SRB_ExecSCSICmd32
*prb
)
156 switch (prb
->CDBByte
[0]) {
158 TRACE(aspi
, "Vendor: '%s'\n", prb
->SRB_BufPointer
+ INQUIRY_VENDOR
);
160 case CMD_TEST_UNIT_READY
:
161 ASPI_PrintSenseArea32(prb
);
167 ASPI_ExecScsiCmd32(SRB_ExecSCSICmd32
*lpPRB
)
169 struct sg_header
*sg_hd
, *sg_reply_hdr
;
175 ASPI_DebugPrintCmd32(lpPRB
);
177 fd
= ASPI_OpenDevice32(lpPRB
);
179 ERR(aspi
, "Failed: could not open device. Device permissions !?\n");
180 lpPRB
->SRB_Status
= SS_ERR
;
187 lpPRB
->SRB_Status
= SS_PENDING
;
189 if (!lpPRB
->SRB_CDBLen
) {
190 WARN(aspi
, "Failed: lpPRB->SRB_CDBLen = 0.\n");
191 lpPRB
->SRB_Status
= SS_ERR
;
195 /* build up sg_header + scsi cmd */
196 if (HOST_TO_TARGET(lpPRB
)) {
197 /* send header, command, and then data */
198 in_len
= SCSI_OFF
+ lpPRB
->SRB_CDBLen
+ lpPRB
->SRB_BufLen
;
199 sg_hd
= (struct sg_header
*) malloc(in_len
);
200 memset(sg_hd
, 0, SCSI_OFF
);
201 memcpy(sg_hd
+ 1, &lpPRB
->CDBByte
[0], lpPRB
->SRB_CDBLen
);
202 if (lpPRB
->SRB_BufLen
) {
203 memcpy(((BYTE
*) sg_hd
) + SCSI_OFF
+ lpPRB
->SRB_CDBLen
, lpPRB
->SRB_BufPointer
, lpPRB
->SRB_BufLen
);
207 /* send header and command - no data */
208 in_len
= SCSI_OFF
+ lpPRB
->SRB_CDBLen
;
209 sg_hd
= (struct sg_header
*) malloc(in_len
);
210 memset(sg_hd
, 0, SCSI_OFF
);
211 memcpy(sg_hd
+ 1, &lpPRB
->CDBByte
[0], lpPRB
->SRB_CDBLen
);
214 if (TARGET_TO_HOST(lpPRB
)) {
215 out_len
= SCSI_OFF
+ lpPRB
->SRB_BufLen
;
216 sg_reply_hdr
= (struct sg_header
*) malloc(out_len
);
217 memset(sg_reply_hdr
, 0, SCSI_OFF
);
218 sg_hd
->reply_len
= out_len
;
222 sg_reply_hdr
= (struct sg_header
*) malloc(out_len
);
223 memset(sg_reply_hdr
, 0, SCSI_OFF
);
224 sg_hd
->reply_len
= out_len
;
227 status
= write(fd
, sg_hd
, in_len
);
228 if (status
< 0 || status
!= in_len
) {
231 WARN(aspi
, "Not enough bytes written to scsi device bytes=%d .. %d\n", in_len
, status
);
233 if (myerror
== ENOMEM
) {
234 MSG("ASPI: Linux generic scsi driver\n You probably need to re-compile your kernel with a larger SG_BIG_BUFF value (sg.h)\n Suggest 130560\n");
236 WARN(aspi
, "errno: = %d\n", myerror
);
241 status
= read(fd
, sg_reply_hdr
, out_len
);
242 if (status
< 0 || status
!= out_len
) {
243 WARN(aspi
, "not enough bytes read from scsi device%d\n", status
);
247 if (sg_reply_hdr
->result
!= 0) {
248 error_code
= sg_reply_hdr
->result
;
249 WARN(aspi
, "reply header error (%d)\n", sg_reply_hdr
->result
);
253 if (TARGET_TO_HOST(lpPRB
) && lpPRB
->SRB_BufLen
) {
254 memcpy(lpPRB
->SRB_BufPointer
, sg_reply_hdr
+ 1, lpPRB
->SRB_BufLen
);
257 /* copy in sense buffer to amount that is available in client */
258 if (lpPRB
->SRB_SenseLen
) {
259 int sense_len
= lpPRB
->SRB_SenseLen
;
260 if (lpPRB
->SRB_SenseLen
> 16)
262 memcpy(SENSE_BUFFER(lpPRB
), &sg_reply_hdr
->sense_buffer
[0], sense_len
);
266 lpPRB
->SRB_Status
= SS_COMP
;
267 lpPRB
->SRB_HaStat
= HASTAT_OK
;
268 lpPRB
->SRB_TargStat
= STATUS_GOOD
;
272 if (lpPRB
->SRB_PostProc
) {
273 if (ASPI_POSTING(lpPRB
)) {
274 TRACE(aspi
, "Post Routine (%lx) called\n", (DWORD
) lpPRB
->SRB_PostProc
);
275 (*lpPRB
->SRB_PostProc
)(lpPRB
);
278 if (lpPRB
->SRB_Flags
& SRB_EVENT_NOTIFY
) {
279 TRACE(aspi
, "Setting event %04x\n", (HANDLE32
)lpPRB
->SRB_PostProc
);
280 SetEvent((HANDLE32
)lpPRB
->SRB_PostProc
); /* FIXME: correct ? */
285 ASPI_DebugPrintResult32(lpPRB
);
289 if (error_code
== EBUSY
) {
290 lpPRB
->SRB_Status
= SS_ASPI_IS_BUSY
;
291 TRACE(aspi
, "Device busy\n");
294 WARN(aspi
, "Failed\n");
295 lpPRB
->SRB_Status
= SS_ERR
;
298 /* I'm not sure exactly error codes work here
299 * We probably should set lpPRB->SRB_TargStat, SRB_HaStat ?
301 WARN(aspi
, "error_exit\n");
304 return lpPRB
->SRB_Status
;
309 /*******************************************************************
310 * GetASPI32SupportInfo32 [WNASPI32.0]
312 * Checks if the ASPI subsystem is initialized correctly.
316 * HIBYTE of LOWORD: status (SS_COMP or SS_FAILED_INIT)
317 * LOBYTE of LOWORD: # of host adapters.
319 DWORD WINAPI
GetASPI32SupportInfo32()
321 return ((SS_COMP
<< 8) | 1); /* FIXME: get # of host adapters installed */
325 /***********************************************************************
326 * SendASPI32Command32 (WNASPI32.1)
328 DWORD WINAPI
SendASPI32Command32(LPSRB32 lpSRB
)
331 switch (lpSRB
->common
.SRB_Cmd
) {
333 lpSRB
->inquiry
.SRB_Status
= SS_COMP
; /* completed successfully */
334 lpSRB
->inquiry
.HA_Count
= 1; /* not always */
335 lpSRB
->inquiry
.HA_SCSI_ID
= 7; /* not always ID 7 */
336 strcat(lpSRB
->inquiry
.HA_ManagerId
, "ASPI for WIN32"); /* max 15 chars, don't change */
337 strcat(lpSRB
->inquiry
.HA_Identifier
, "Wine host"); /* FIXME: return host adapter name */
338 memset(lpSRB
->inquiry
.HA_Unique
, 0, 16); /* default HA_Unique content */
339 lpSRB
->inquiry
.HA_Unique
[6] = 0x02; /* Maximum Transfer Length (128K, Byte> 4-7) */
340 FIXME(aspi
, "ASPI: Partially implemented SC_HA_INQUIRY for adapter %d.\n", lpSRB
->inquiry
.SRB_HaId
);
342 case SC_GET_DEV_TYPE
:
343 FIXME(aspi
, "Not implemented SC_GET_DEV_TYPE\n");
345 case SC_EXEC_SCSI_CMD
:
346 return ASPI_ExecScsiCmd32(&lpSRB
->cmd
);
349 FIXME(aspi
, "Not implemented SC_RESET_DEV\n");
352 WARN(aspi
, "Unknown command %d\n", lpSRB
->common
.SRB_Cmd
);
354 return SS_INVALID_SRB
;
356 return SS_INVALID_SRB
;
361 /***********************************************************************
362 * GetASPI32DLLVersion32 (WNASPI32.3)
365 DWORD WINAPI
GetASPI32DLLVersion32()