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
;
63 ERR(aspi
, "Error opening device %s, error '%s'\n", device_str
, strerror(save_error
));
65 ERR(aspi
, "Error opening device %s, error %d\n", device_str
, save_error
);
70 /* device is now open */
71 curr
= HeapAlloc( SystemHeap
, 0, sizeof(ASPI_DEVICE_INFO
) );
73 curr
->hostId
= prb
->SRB_HaId
;
74 curr
->target
= prb
->SRB_Target
;
75 curr
->lun
= prb
->SRB_Lun
;
77 /* insert new record at beginning of open device list */
78 curr
->next
= ASPI_open_devices
;
79 ASPI_open_devices
= curr
;
85 ASPI_DebugPrintCmd32(SRB_ExecSCSICmd32
*prb
)
90 dbg_decl_str(aspi
, 512);
92 switch (prb
->CDBByte
[0]) {
95 TRACE(aspi
, "\tEVPD: %d\n", prb
->CDBByte
[1] & 1);
96 TRACE(aspi
, "\tLUN: %d\n", (prb
->CDBByte
[1] & 0xc) >> 1);
97 TRACE(aspi
, "\tPAGE CODE: %d\n", prb
->CDBByte
[2]);
98 TRACE(aspi
, "\tALLOCATION LENGTH: %d\n", prb
->CDBByte
[4]);
99 TRACE(aspi
, "\tCONTROL: %d\n", prb
->CDBByte
[5]);
103 TRACE(aspi
, "Transfer Length: %d\n", prb
->CDBByte
[4]);
107 TRACE(aspi
, "Host Adapter: %d\n", prb
->SRB_HaId
);
108 TRACE(aspi
, "Flags: %d\n", prb
->SRB_Flags
);
109 if (TARGET_TO_HOST(prb
)) {
110 TRACE(aspi
, "\tData transfer: Target to host. Length checked.\n");
112 else if (HOST_TO_TARGET(prb
)) {
113 TRACE(aspi
, "\tData transfer: Host to target. Length checked.\n");
115 else if (NO_DATA_TRANSFERED(prb
)) {
116 TRACE(aspi
, "\tData transfer: none\n");
119 WARN(aspi
, "\tTransfer by scsi cmd. Length not checked.\n");
122 TRACE(aspi
, "\tResidual byte length reporting %s\n", prb
->SRB_Flags
& 0x4 ? "enabled" : "disabled");
123 TRACE(aspi
, "\tLinking %s\n", prb
->SRB_Flags
& 0x2 ? "enabled" : "disabled");
124 TRACE(aspi
, "\tPosting %s\n", prb
->SRB_Flags
& 0x1 ? "enabled" : "disabled");
125 TRACE(aspi
, "Target: %d\n", prb
->SRB_Target
);
126 TRACE(aspi
, "Lun: %d\n", prb
->SRB_Lun
);
127 TRACE(aspi
, "BufLen: %ld\n", prb
->SRB_BufLen
);
128 TRACE(aspi
, "SenseLen: %d\n", prb
->SRB_SenseLen
);
129 TRACE(aspi
, "BufPtr: %p\n", prb
->SRB_BufPointer
);
130 TRACE(aspi
, "CDB Length: %d\n", prb
->SRB_CDBLen
);
131 TRACE(aspi
, "POST Proc: %lx\n", (DWORD
) prb
->SRB_PostProc
);
132 cdb
= &prb
->CDBByte
[0];
133 cmd
= prb
->CDBByte
[0];
134 for (i
= 0; i
< prb
->SRB_CDBLen
; i
++) {
135 if (i
!= 0) dsprintf(aspi
, ",");
136 dsprintf(aspi
, "%02x", *cdb
++);
138 TRACE(aspi
, "CDB buffer[%s]\n", dbg_str(aspi
));
142 ASPI_PrintSenseArea32(SRB_ExecSCSICmd32
*prb
)
146 dbg_decl_str(aspi
, 512);
148 cdb
= &prb
->CDBByte
[0];
149 for (i
= 0; i
< prb
->SRB_SenseLen
; i
++) {
150 if (i
) dsprintf(aspi
, ",");
151 dsprintf(aspi
, "%02x", *cdb
++);
153 TRACE(aspi
, "SenseArea[%s]\n", dbg_str(aspi
));
157 ASPI_DebugPrintResult32(SRB_ExecSCSICmd32
*prb
)
160 switch (prb
->CDBByte
[0]) {
162 TRACE(aspi
, "Vendor: '%s'\n", prb
->SRB_BufPointer
+ INQUIRY_VENDOR
);
164 case CMD_TEST_UNIT_READY
:
165 ASPI_PrintSenseArea32(prb
);
171 ASPI_ExecScsiCmd32(SRB_ExecSCSICmd32
*lpPRB
)
173 struct sg_header
*sg_hd
, *sg_reply_hdr
;
179 ASPI_DebugPrintCmd32(lpPRB
);
181 fd
= ASPI_OpenDevice32(lpPRB
);
183 ERR(aspi
, "Failed: could not open device. Device permissions !?\n");
184 lpPRB
->SRB_Status
= SS_ERR
;
191 lpPRB
->SRB_Status
= SS_PENDING
;
193 if (!lpPRB
->SRB_CDBLen
) {
194 WARN(aspi
, "Failed: lpPRB->SRB_CDBLen = 0.\n");
195 lpPRB
->SRB_Status
= SS_ERR
;
199 /* build up sg_header + scsi cmd */
200 if (HOST_TO_TARGET(lpPRB
)) {
201 /* send header, command, and then data */
202 in_len
= SCSI_OFF
+ lpPRB
->SRB_CDBLen
+ lpPRB
->SRB_BufLen
;
203 sg_hd
= (struct sg_header
*) malloc(in_len
);
204 memset(sg_hd
, 0, SCSI_OFF
);
205 memcpy(sg_hd
+ 1, &lpPRB
->CDBByte
[0], lpPRB
->SRB_CDBLen
);
206 if (lpPRB
->SRB_BufLen
) {
207 memcpy(((BYTE
*) sg_hd
) + SCSI_OFF
+ lpPRB
->SRB_CDBLen
, lpPRB
->SRB_BufPointer
, lpPRB
->SRB_BufLen
);
211 /* send header and command - no data */
212 in_len
= SCSI_OFF
+ lpPRB
->SRB_CDBLen
;
213 sg_hd
= (struct sg_header
*) malloc(in_len
);
214 memset(sg_hd
, 0, SCSI_OFF
);
215 memcpy(sg_hd
+ 1, &lpPRB
->CDBByte
[0], lpPRB
->SRB_CDBLen
);
218 if (TARGET_TO_HOST(lpPRB
)) {
219 out_len
= SCSI_OFF
+ lpPRB
->SRB_BufLen
;
220 sg_reply_hdr
= (struct sg_header
*) malloc(out_len
);
221 memset(sg_reply_hdr
, 0, SCSI_OFF
);
222 sg_hd
->reply_len
= out_len
;
226 sg_reply_hdr
= (struct sg_header
*) malloc(out_len
);
227 memset(sg_reply_hdr
, 0, SCSI_OFF
);
228 sg_hd
->reply_len
= out_len
;
231 status
= write(fd
, sg_hd
, in_len
);
232 if (status
< 0 || status
!= in_len
) {
233 int save_error
= errno
;
235 WARN(aspi
, "Not enough bytes written to scsi device bytes=%d .. %d\n", in_len
, status
);
237 if (save_error
== ENOMEM
) {
238 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");
241 WARN(aspi
, "error:= '%s'\n", strerror(save_error
));
243 WARN(aspi
, "error:= %d\n", save_error
);
249 status
= read(fd
, sg_reply_hdr
, out_len
);
250 if (status
< 0 || status
!= out_len
) {
251 WARN(aspi
, "not enough bytes read from scsi device%d\n", status
);
255 if (sg_reply_hdr
->result
!= 0) {
256 error_code
= sg_reply_hdr
->result
;
257 WARN(aspi
, "reply header error (%d)\n", sg_reply_hdr
->result
);
261 if (TARGET_TO_HOST(lpPRB
) && lpPRB
->SRB_BufLen
) {
262 memcpy(lpPRB
->SRB_BufPointer
, sg_reply_hdr
+ 1, lpPRB
->SRB_BufLen
);
265 /* copy in sense buffer to amount that is available in client */
266 if (lpPRB
->SRB_SenseLen
) {
267 int sense_len
= lpPRB
->SRB_SenseLen
;
268 if (lpPRB
->SRB_SenseLen
> 16)
270 memcpy(SENSE_BUFFER(lpPRB
), &sg_reply_hdr
->sense_buffer
[0], sense_len
);
274 lpPRB
->SRB_Status
= SS_COMP
;
275 lpPRB
->SRB_HaStat
= HASTAT_OK
;
276 lpPRB
->SRB_TargStat
= STATUS_GOOD
;
280 if (lpPRB
->SRB_PostProc
) {
281 if (ASPI_POSTING(lpPRB
)) {
282 TRACE(aspi
, "Post Routine (%lx) called\n", (DWORD
) lpPRB
->SRB_PostProc
);
283 (*lpPRB
->SRB_PostProc
)(lpPRB
);
286 if (lpPRB
->SRB_Flags
& SRB_EVENT_NOTIFY
) {
287 TRACE(aspi
, "Setting event %04x\n", (HANDLE32
)lpPRB
->SRB_PostProc
);
288 SetEvent((HANDLE32
)lpPRB
->SRB_PostProc
); /* FIXME: correct ? */
293 ASPI_DebugPrintResult32(lpPRB
);
297 if (error_code
== EBUSY
) {
298 lpPRB
->SRB_Status
= SS_ASPI_IS_BUSY
;
299 TRACE(aspi
, "Device busy\n");
302 WARN(aspi
, "Failed\n");
303 lpPRB
->SRB_Status
= SS_ERR
;
306 /* I'm not sure exactly error codes work here
307 * We probably should set lpPRB->SRB_TargStat, SRB_HaStat ?
309 WARN(aspi
, "error_exit\n");
312 return lpPRB
->SRB_Status
;
317 /*******************************************************************
318 * GetASPI32SupportInfo32 [WNASPI32.0]
320 * Checks if the ASPI subsystem is initialized correctly.
324 * HIBYTE of LOWORD: status (SS_COMP or SS_FAILED_INIT)
325 * LOBYTE of LOWORD: # of host adapters.
327 DWORD WINAPI
GetASPI32SupportInfo32()
329 return ((SS_COMP
<< 8) | 1); /* FIXME: get # of host adapters installed */
333 /***********************************************************************
334 * SendASPI32Command32 (WNASPI32.1)
336 DWORD WINAPI
SendASPI32Command32(LPSRB32 lpSRB
)
339 switch (lpSRB
->common
.SRB_Cmd
) {
341 lpSRB
->inquiry
.SRB_Status
= SS_COMP
; /* completed successfully */
342 lpSRB
->inquiry
.HA_Count
= 1; /* not always */
343 lpSRB
->inquiry
.HA_SCSI_ID
= 7; /* not always ID 7 */
344 strcat(lpSRB
->inquiry
.HA_ManagerId
, "ASPI for WIN32"); /* max 15 chars, don't change */
345 strcat(lpSRB
->inquiry
.HA_Identifier
, "Wine host"); /* FIXME: return host adapter name */
346 memset(lpSRB
->inquiry
.HA_Unique
, 0, 16); /* default HA_Unique content */
347 lpSRB
->inquiry
.HA_Unique
[6] = 0x02; /* Maximum Transfer Length (128K, Byte> 4-7) */
348 FIXME(aspi
, "ASPI: Partially implemented SC_HA_INQUIRY for adapter %d.\n", lpSRB
->inquiry
.SRB_HaId
);
350 case SC_GET_DEV_TYPE
:
351 FIXME(aspi
, "Not implemented SC_GET_DEV_TYPE\n");
353 case SC_EXEC_SCSI_CMD
:
354 return ASPI_ExecScsiCmd32(&lpSRB
->cmd
);
357 FIXME(aspi
, "Not implemented SC_RESET_DEV\n");
360 WARN(aspi
, "Unknown command %d\n", lpSRB
->common
.SRB_Cmd
);
362 return SS_INVALID_SRB
;
364 return SS_INVALID_SRB
;
369 /***********************************************************************
370 * GetASPI32DLLVersion32 (WNASPI32.3)
373 DWORD WINAPI
GetASPI32DLLVersion32()