source: trunk/src/wnaspi32/aspirout/winaspi32.cpp@ 10366

Last change on this file since 10366 was 8601, checked in by sandervl, 23 years ago

os2cdrom.dmd rewrite

File size: 13.8 KB
Line 
1/* $Id: winaspi32.cpp,v 1.1 2002-06-08 11:42:04 sandervl Exp $ */
2/*
3 * WNASPI routines
4 *
5 * Copyright 1999 Markus Montkowski
6 * Copyright 2000 Przemyslaw Dobrowolski
7 *
8 * Project Odin Software License can be found in LICENSE.TXT
9 *
10 */
11#include <os2win.h>
12#include <stdlib.h>
13#include <sys/types.h>
14#include <sys/stat.h>
15#include <errno.h>
16#include <fcntl.h>
17#include <memory.h>
18
19#include "aspi.h"
20#include "wnaspi32.h"
21#include <winreg.h>
22#include "options.h"
23#include "debugtools.h"
24
25//#include "srbos2.h"
26//#include "odinaspi.h"
27#include "aspilib.h"
28//#include "callback.h"
29
30#ifdef DEBUG
31#define DEBUG_BUFFER
32#endif
33
34DEFAULT_DEBUG_CHANNEL(aspi)
35ODINDEBUGCHANNEL(WNASPI32)
36
37static void
38ASPI_DebugPrintCmd(SRB_ExecSCSICmd *prb)
39{
40 BYTE cmd;
41 int i;
42 BYTE *cdb;
43
44 switch (prb->CDBByte[0]) {
45 case CMD_INQUIRY:
46 TRACE("{\n");
47 TRACE("\tEVPD: %d\n", prb->CDBByte[1] & 1);
48 TRACE("\tLUN: %d\n", (prb->CDBByte[1] & 0xc) >> 1);
49 TRACE("\tPAGE CODE: %d\n", prb->CDBByte[2]);
50 TRACE("\tALLOCATION LENGTH: %d\n", prb->CDBByte[4]);
51 TRACE("\tCONTROL: %d\n", prb->CDBByte[5]);
52 TRACE("}\n");
53 break;
54 case CMD_SCAN_SCAN:
55 TRACE("Transfer Length: %d\n", prb->CDBByte[4]);
56 break;
57 }
58
59 TRACE("Host Adapter: %d\n", prb->SRB_HaId);
60 TRACE("Flags: %d\n", prb->SRB_Flags);
61 if (TARGET_TO_HOST(prb)) {
62 TRACE("\tData transfer: Target to host. Length checked.\n");
63 }
64 else if (HOST_TO_TARGET(prb)) {
65 TRACE("\tData transfer: Host to target. Length checked.\n");
66 }
67 else if (NO_DATA_TRANSFERED(prb)) {
68 TRACE("\tData transfer: none\n");
69 }
70 else {
71 WARN("\tTransfer by scsi cmd. Length not checked.\n");
72 }
73
74 TRACE("\tResidual byte length reporting %s\n", prb->SRB_Flags & 0x4 ? "enabled" : "disabled");
75 TRACE("\tLinking %s\n", prb->SRB_Flags & 0x2 ? "enabled" : "disabled");
76 TRACE("\tPosting %s\n", prb->SRB_Flags & 0x1 ? "enabled" : "disabled");
77 TRACE("Target: %d\n", prb->SRB_Target);
78 TRACE("Lun: %d\n", prb->SRB_Lun);
79 TRACE("BufLen: %ld\n", prb->SRB_BufLen);
80 TRACE("SenseLen: %d\n", prb->SRB_SenseLen);
81 TRACE("BufPtr: %p\n", prb->SRB_BufPointer);
82 TRACE("CDB Length: %d\n", prb->SRB_CDBLen);
83 TRACE("POST Proc: %lx\n", (DWORD) prb->SRB_PostProc);
84 cdb = &prb->CDBByte[0];
85 cmd = prb->CDBByte[0];
86#ifdef DEBUG_BUFFER
87 dprintfNoEOL(("CDB buffer["));
88 for (i = 0; i < prb->SRB_CDBLen; i++) {
89 if (i != 0) dprintfNoEOL((",0x%02x", *cdb++));
90 else dprintfNoEOL(("0x%02x", *cdb++));
91 }
92 dprintfNoEOL(("]\n"));
93#endif
94}
95
96static void
97ASPI_PrintSenseArea(SRB_ExecSCSICmd *prb)
98{
99 int i;
100 BYTE *cdb;
101
102 if (TRACE_ON(aspi))
103 {
104 cdb = &prb->CDBByte[0];
105 DPRINTF("SenseArea[");
106 for (i = 0; i < prb->SRB_SenseLen; i++) {
107 if (i) DPRINTF(",");
108 DPRINTF("%02x", *cdb++);
109 }
110 DPRINTF("]\n");
111 }
112}
113
114static void
115ASPI_DebugPrintResult(SRB_ExecSCSICmd *prb)
116{
117
118 switch (prb->CDBByte[0]) {
119 case CMD_INQUIRY:
120 TRACE("Vendor: '%s'\n", prb->SRB_BufPointer + INQUIRY_VENDOR);
121 break;
122 case CMD_TEST_UNIT_READY:
123 ASPI_PrintSenseArea(prb);
124 break;
125 }
126 dprintf(("Result code: %x", prb->SRB_Status));
127}
128
129
130static WORD ASPI_ExecScsiCmd( scsiObj *aspi, SRB_ExecSCSICmd *lpPRB)
131{
132 int status;
133 int error_code = 0;
134 LONG rc;
135
136 /* FIXME: hackmode */
137#define MAKE_TARGET_TO_HOST(lpPRB) \
138 if (!TARGET_TO_HOST(lpPRB)) { \
139 WARN("program was not sending target_to_host for cmd %x (flags=%x),correcting.\n",lpPRB->CDBByte[0],lpPRB->SRB_Flags); \
140 lpPRB->SRB_Flags |= 8; \
141 }
142#define MAKE_HOST_TO_TARGET(lpPRB) \
143 if (!HOST_TO_TARGET(lpPRB)) { \
144 WARN("program was not sending host_to_target for cmd %x (flags=%x),correcting.\n",lpPRB->CDBByte[0],lpPRB->SRB_Flags); \
145 lpPRB->SRB_Flags |= 0x10; \
146 }
147 switch (lpPRB->CDBByte[0]) {
148 case 0x12: /* INQUIRY */
149 case 0x5a: /* MODE_SENSE_10 */
150 case 0xa4: /* REPORT_KEY (DVD) MMC-2 */
151 case 0xad: /* READ DVD STRUCTURE MMC-2 */
152 MAKE_TARGET_TO_HOST(lpPRB)
153 break;
154 case 0xa3: /* SEND KEY (DVD) MMC-2 */
155 MAKE_HOST_TO_TARGET(lpPRB)
156 break;
157 default:
158 if ((((lpPRB->SRB_Flags & 0x18) == 0x00) ||
159 ((lpPRB->SRB_Flags & 0x18) == 0x18)
160 ) && lpPRB->SRB_BufLen
161 ) {
162 FIXME("command 0x%02x, no data transfer specified, but buflen is %ld!!!\n",lpPRB->CDBByte[0],lpPRB->SRB_BufLen);
163 }
164 break;
165 }
166
167 ASPI_DebugPrintCmd(lpPRB);
168
169 lpPRB->SRB_Status = SS_PENDING;
170
171 if (!lpPRB->SRB_CDBLen)
172 {
173 dprintf(("Failed: lpPRB->SRB_CDBLen = 0."));
174 lpPRB->SRB_Status = SS_ERR;
175 return SS_ERR;
176 }
177
178 if(MaxCDBStatus<lpPRB->SRB_CDBLen)
179 {
180 dprintf(("Failed: lpPRB->SRB_CDBLen > 64."));
181 lpPRB->SRB_Status = SS_ERR;
182 return SS_ERR;
183 }
184
185 if(lpPRB->SRB_BufLen>65536) // Check Max 64k!!
186 {
187 dprintf(("Failed: lpPRB->SRB_BufLen > 65536."));
188 lpPRB->SRB_Status = SS_BUFFER_TO_BIG;
189 return SS_BUFFER_TO_BIG;
190 }
191
192 // copy up to LUN SRBOS2 has no WORD for padding like in WINE
193 memcpy( &aspi->SRBlock,
194 lpPRB,
195 6* sizeof(BYTE) + sizeof(DWORD));
196 aspi->SRBlock.flags |= SRB_Post;
197 aspi->SRBlock.u.cmd.sense_len = lpPRB->SRB_SenseLen;; // length of sense buffer
198 aspi->SRBlock.u.cmd.data_ptr = NULL; // pointer to data buffer
199 aspi->SRBlock.u.cmd.link_ptr = NULL; // pointer to next SRB
200 aspi->SRBlock.u.cmd.data_len = lpPRB->SRB_BufLen;
201 aspi->SRBlock.u.cmd.cdb_len = lpPRB->SRB_CDBLen; // SCSI command length
202 memcpy( &aspi->SRBlock.u.cmd.cdb_st[0],
203 &lpPRB->CDBByte[0],
204 lpPRB->SRB_CDBLen);
205
206 if (HOST_TO_TARGET(lpPRB))
207 {
208 // Write: Copy all Data to Communication Buffer
209 if (lpPRB->SRB_BufLen)
210 {
211 memcpy( aspi->buffer,
212 lpPRB->SRB_BufPointer,
213 lpPRB->SRB_BufLen);
214
215#ifdef DEBUG_BUFFER
216 char *cdb = (char *)lpPRB->SRB_BufPointer;
217 dprintfNoEOL(("Write SRB buffer["));
218 for (int i = 0; i < lpPRB->SRB_BufLen; i++) {
219 if (i != 0) dprintfNoEOL((",0x%02x", *cdb++));
220 else dprintfNoEOL(("0x%02x", *cdb++));
221 }
222 dprintfNoEOL(("]\n"));
223#endif
224 }
225 }
226
227 rc = aspi->SendSRBlock();
228
229 if(!rc)
230 {
231 if( aspi->waitPost())
232 {
233 if (TARGET_TO_HOST(lpPRB))
234 {
235 // Was Read : Copy all Data from Communication Buffer
236 if (lpPRB->SRB_BufLen)
237 {
238 memcpy( lpPRB->SRB_BufPointer,
239 aspi->buffer,
240 lpPRB->SRB_BufLen);
241#ifdef DEBUG_BUFFER
242 char *cdb = (char *)lpPRB->SRB_BufPointer;
243 dprintfNoEOL(("Read SRB buffer["));
244 for (int i = 0; i < lpPRB->SRB_BufLen; i++) {
245 if (i != 0) dprintfNoEOL((",0x%02x", *cdb++));
246 else dprintfNoEOL(("0x%02x", *cdb++));
247 }
248 dprintfNoEOL(("]\n"));
249#endif
250 }
251 }
252
253 if (lpPRB->SRB_SenseLen)
254 {
255 int sense_len = lpPRB->SRB_SenseLen;
256 if (lpPRB->SRB_SenseLen > 32)
257 sense_len = 32;
258 memcpy( SENSE_BUFFER(lpPRB),
259 &aspi->SRBlock.u.cmd.cdb_st[aspi->SRBlock.u.cmd.cdb_len],
260 sense_len);
261 }
262
263#if 0
264 /* FIXME: Should this be != 0 maybe? */
265 if(aspi->SRBlock.u.cmd.target_status == 2 ) {
266 aspi->SRBlock.status = SS_ERR;
267 switch (lpPRB->CDBByte[0]) {
268 case 0xa4: /* REPORT_KEY (DVD) MMC-2 */
269 case 0xa3: /* SEND KEY (DVD) MMC-2 */
270 aspi->SRBlock.status = SS_COMP;
271 aspi->SRBlock.u.cmd.target_status = 0;
272 FIXME("Program wants to do DVD Region switching, but fails (non compliant DVD drive). Ignoring....\n");
273 break;
274 }
275 }
276#endif
277 /* now do posting */
278 if (lpPRB->SRB_PostProc)
279 {
280 if(ASPI_POSTING(lpPRB))
281 {
282 dprintf(("Post Routine (%lx) called\n", (DWORD) lpPRB->SRB_PostProc));
283 (*lpPRB->SRB_PostProc)();
284 }
285 else
286 if (lpPRB->SRB_Flags & SRB_EVENT_NOTIFY)
287 {
288 dprintf(("Setting event %04x\n", (HANDLE)lpPRB->SRB_PostProc));
289 SetEvent((HANDLE)lpPRB->SRB_PostProc); /* FIXME: correct ? */
290 }
291 }
292 }
293 }
294 else
295 lpPRB->SRB_Status = SS_ERR;
296
297 //SvL: Shouldn't this be set before posting?
298 lpPRB->SRB_Status = aspi->SRBlock.status;
299 lpPRB->SRB_HaStat = aspi->SRBlock.u.cmd.ha_status;
300 lpPRB->SRB_TargStat = aspi->SRBlock.u.cmd.target_status;
301
302 ASPI_DebugPrintResult(lpPRB);
303
304 return lpPRB->SRB_Status;
305}
306
307/*******************************************************************
308 * GetASPI32SupportInfo32 [WNASPI32.0]
309 *
310 * Checks if the ASPI subsystem is initialized correctly.
311 *
312 * RETURNS
313 * HIWORD: 0.
314 * HIBYTE of LOWORD: status (SS_COMP or SS_FAILED_INIT)
315 * LOBYTE of LOWORD: # of host adapters.
316 */
317ODINFUNCTION0(DWORD, GetASPI32SupportInfo)
318{
319 LONG rc;
320 BYTE bNumDrv;
321 HKEY hkeyDrvInfo;
322 DWORD dwType;
323 DWORD dwData;
324 DWORD dwSize;
325 ULONG ulParam, ulReturn;
326 BYTE brc;
327
328 bNumDrv = 0;
329
330 // first thing we do is check whether we have a successful ASPI setup
331 if (aspi == NULL)
332 {
333 dprintf(("ASPI was not initialized successfully, return error"));
334 return (SS_FAILED_INIT << 8);
335 }
336
337 if(aspi->access(FALSE)) //'non-blocking' call
338 {
339 bNumDrv = aspi->getNumHosts();
340 brc = SS_COMP;
341 rc = RegOpenKeyA ( HKEY_LOCAL_MACHINE,
342 "Software\\ODIN\\ASPIROUT",
343 &hkeyDrvInfo);
344 if(ERROR_SUCCESS==rc)
345 {
346 dwData = bNumDrv;
347 RegSetValueExA( hkeyDrvInfo,
348 "NumAdapers",
349 NULL,
350 REG_DWORD,
351 (LPBYTE)&dwData,
352 sizeof(DWORD));
353 RegCloseKey( hkeyDrvInfo);
354 }
355 aspi->release();
356 }
357 else
358 {
359 // Driver is used by other process/thread
360 // so try get value form registry
361
362 brc = SS_FAILED_INIT;
363 rc = RegOpenKeyA ( HKEY_LOCAL_MACHINE,
364 "Software\\ODIN\\ASPIROUT",
365 &hkeyDrvInfo);
366
367 if(ERROR_SUCCESS!=rc)
368 return ((SS_FAILED_INIT << 8) | bNumDrv);
369
370 dwSize = sizeof(DWORD);
371 rc = RegQueryValueExA( hkeyDrvInfo,
372 "NumAdapers",
373 NULL,
374 &dwType,
375 (BYTE*)&dwData,
376 &dwSize);
377
378 RegCloseKey( hkeyDrvInfo);
379
380 if( (ERROR_SUCCESS==rc) &&
381 (REG_DWORD != dwType) )
382 {
383 bNumDrv = 0xFF & dwData;
384 brc = SS_COMP;
385 }
386 }
387
388 return ((brc << 8) | bNumDrv); /* FIXME: get # of host adapters installed */
389}
390
391/***********************************************************************
392 * SendASPI32Command32 (WNASPI32.1)
393 */
394DWORD CDECL SendASPI32Command(LPSRB lpSRB)
395{
396 DWORD dwRC;
397 ULONG ulParam, ulReturn;
398 BYTE bRC;
399 LONG rc;
400
401 // first thing we do is check whether we have a successful ASPI setup
402 if (aspi == NULL)
403 {
404 dprintf(("SendASPI32Command: ASPI was not initialized successfully, return error"));
405 return SS_NO_ASPI;
406 }
407
408 if(NULL==lpSRB)
409 return SS_INVALID_SRB; // Not sure what to return here but that is an error
410
411 dprintf(("SendASPI32Command %x %d", lpSRB, lpSRB->common.SRB_Cmd));
412
413 // test first for a valid command
414 if( (SC_HA_INQUIRY!=lpSRB->common.SRB_Cmd) &&
415 (SC_GET_DEV_TYPE!=lpSRB->common.SRB_Cmd) &&
416 (SC_EXEC_SCSI_CMD!=lpSRB->common.SRB_Cmd) &&
417 (SC_ABORT_SRB!=lpSRB->common.SRB_Cmd) &&
418 (SC_RESET_DEV!=lpSRB->common.SRB_Cmd) )
419 {
420 dprintf(("Invalid command!"));
421 return SS_INVALID_SRB; // shoud be invalid command
422 }
423
424 dwRC = SS_ERR;
425
426 if(aspi->access(TRUE)) // Block if a SRB is pending
427 {
428 switch (lpSRB->common.SRB_Cmd)
429 {
430 case SC_HA_INQUIRY:
431 aspi->HA_inquiry(lpSRB->inquiry.SRB_HaId);
432 memset(lpSRB,0,sizeof(SRB_HaInquiry));
433 memcpy( lpSRB,
434 &aspi->SRBlock,
435 sizeof(SRB_HaInquiry)-4 );
436 // FIXME: I'dont know why in OS/2->ha_unique are filled with 0
437 // Hackmode ON ======
438 lpSRB->inquiry.HA_Unique[6] = 0x01; // transfer only 64KB
439 lpSRB->inquiry.HA_Unique[3] = 0x10; // 16 devices.
440 // HackMode OFF =====
441 dwRC = aspi->SRBlock.status;
442 break;
443
444 case SC_GET_DEV_TYPE:
445 rc=aspi->getDeviceType(lpSRB->devtype.SRB_HaId,lpSRB->devtype.SRB_Target, lpSRB->devtype.SRB_Lun);
446 dwRC = lpSRB->devtype.SRB_Status = aspi->SRBlock.status;
447 lpSRB->devtype.SRB_DeviceType = aspi->SRBlock.u.dev.devtype;
448 break;
449
450 case SC_EXEC_SCSI_CMD:
451 dwRC = ASPI_ExecScsiCmd( aspi, &lpSRB->cmd);
452 break;
453
454 case SC_ABORT_SRB:
455 dwRC = SS_INVALID_SRB; // We don't do async ASPI so no way to abort
456 break;
457
458 case SC_RESET_DEV:
459 aspi->resetDevice(lpSRB->reset.SRB_HaId,lpSRB->reset.SRB_Target, lpSRB->reset.SRB_Lun);
460 lpSRB->reset.SRB_Status = aspi->SRBlock.status;
461 lpSRB->reset.SRB_Flags = aspi->SRBlock.flags;
462 lpSRB->reset.SRB_Hdr_Rsvd = 0;
463 memset( lpSRB->reset.SRB_Rsvd1,
464 0,
465 12 );
466 lpSRB->reset.SRB_HaStat = aspi->SRBlock.u.res.ha_status; /* Host Adapter Status */
467 lpSRB->reset.SRB_TargStat = aspi->SRBlock.u.res.target_status; /* Target Status */
468 lpSRB->reset.SRB_PostProc = NULL; /* Post routine */
469 lpSRB->reset.SRB_Rsvd2 = NULL; /* Reserved */
470 memset( lpSRB->reset.SRB_Rsvd3,
471 0,
472 32); /* Reserved */
473 dwRC = aspi->SRBlock.status;
474 break;
475
476 } // end switch (lpSRB->common.SRB_Cmd)
477
478 aspi->release();
479 }
480 else
481 {
482 dprintf(("Unable to access aspi!!"));
483 dwRC = SS_NO_ASPI;
484 }
485
486 return dwRC;
487}
488
489/***********************************************************************
490 * GetASPI32DLLVersion32 (WNASPI32.3)
491 */
492DWORD WINAPI GetASPI32DLLVersion()
493{
494 return (DWORD)1;
495}
496
Note: See TracBrowser for help on using the repository browser.