source: trunk/src/wnaspi32/winaspi32.cpp@ 5120

Last change on this file since 5120 was 4801, checked in by sandervl, 25 years ago

some minor fixes

File size: 13.4 KB
Line 
1/* $Id: winaspi32.cpp,v 1.12 2000-12-16 15:42:42 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 if(aspi->access(FALSE)) //'non-blocking' call
331 {
332 bNumDrv = aspi->getNumHosts();
333 brc = SS_COMP;
334 rc = RegOpenKeyA ( HKEY_LOCAL_MACHINE,
335 "Software\\ODIN\\ASPIROUT",
336 &hkeyDrvInfo);
337 if(ERROR_SUCCESS==rc)
338 {
339 dwData = bNumDrv;
340 RegSetValueExA( hkeyDrvInfo,
341 "NumAdapers",
342 NULL,
343 REG_DWORD,
344 (LPBYTE)&dwData,
345 sizeof(DWORD));
346 RegCloseKey( hkeyDrvInfo);
347 }
348 aspi->release();
349 }
350 else
351 {
352 // Driver is used by other process/thread
353 // so try get value form registry
354
355 brc = SS_FAILED_INIT;
356 rc = RegOpenKeyA ( HKEY_LOCAL_MACHINE,
357 "Software\\ODIN\\ASPIROUT",
358 &hkeyDrvInfo);
359
360 if(ERROR_SUCCESS!=rc)
361 return ((SS_FAILED_INIT << 8) | bNumDrv);
362
363 dwSize = sizeof(DWORD);
364 rc = RegQueryValueExA( hkeyDrvInfo,
365 "NumAdapers",
366 NULL,
367 &dwType,
368 (BYTE*)&dwData,
369 &dwSize);
370
371 RegCloseKey( hkeyDrvInfo);
372
373 if( (ERROR_SUCCESS==rc) &&
374 (REG_DWORD != dwType) )
375 {
376 bNumDrv = 0xFF & dwData;
377 brc = SS_COMP;
378 }
379 }
380
381 return ((brc << 8) | bNumDrv); /* FIXME: get # of host adapters installed */
382}
383
384/***********************************************************************
385 * SendASPI32Command32 (WNASPI32.1)
386 */
387DWORD CDECL SendASPI32Command(LPSRB lpSRB)
388{
389 DWORD dwRC;
390 ULONG ulParam, ulReturn;
391 BYTE bRC;
392 LONG rc;
393
394 if(NULL==lpSRB)
395 return SS_INVALID_SRB; // Not sure what to return here but that is an error
396
397 dprintf(("SendASPI32Command %x %d", lpSRB, lpSRB->common.SRB_Cmd));
398
399 // test first for a valid command
400 if( (SC_HA_INQUIRY!=lpSRB->common.SRB_Cmd) &&
401 (SC_GET_DEV_TYPE!=lpSRB->common.SRB_Cmd) &&
402 (SC_EXEC_SCSI_CMD!=lpSRB->common.SRB_Cmd) &&
403 (SC_ABORT_SRB!=lpSRB->common.SRB_Cmd) &&
404 (SC_RESET_DEV!=lpSRB->common.SRB_Cmd) )
405 {
406 dprintf(("Invalid command!"));
407 return SS_INVALID_SRB; // shoud be invalid command
408 }
409
410 dwRC = SS_ERR;
411
412 if(aspi->access(TRUE)) // Block if a SRB is pending
413 {
414 switch (lpSRB->common.SRB_Cmd)
415 {
416 case SC_HA_INQUIRY:
417 aspi->HA_inquiry(lpSRB->inquiry.SRB_HaId);
418 memset(lpSRB,0,sizeof(SRB_HaInquiry));
419 memcpy( lpSRB,
420 &aspi->SRBlock,
421 sizeof(SRB_HaInquiry)-4 );
422 // FIXME: I'dont know why in OS/2->ha_unique are filled with 0
423 // Hackmode ON ======
424 lpSRB->inquiry.HA_Unique[6] = 0x01; // transfer only 64KB
425 lpSRB->inquiry.HA_Unique[3] = 0x10; // 16 devices.
426 // HackMode OFF =====
427 dwRC = aspi->SRBlock.status;
428 break;
429
430 case SC_GET_DEV_TYPE:
431 rc=aspi->getDeviceType(lpSRB->devtype.SRB_HaId,lpSRB->devtype.SRB_Target, lpSRB->devtype.SRB_Lun);
432 dwRC = lpSRB->devtype.SRB_Status = aspi->SRBlock.status;
433 lpSRB->devtype.SRB_DeviceType = aspi->SRBlock.u.dev.devtype;
434 break;
435
436 case SC_EXEC_SCSI_CMD:
437 dwRC = ASPI_ExecScsiCmd( aspi, &lpSRB->cmd);
438 break;
439
440 case SC_ABORT_SRB:
441 dwRC = SS_INVALID_SRB; // We don't do async ASPI so no way to abort
442 break;
443
444 case SC_RESET_DEV:
445 aspi->resetDevice(lpSRB->reset.SRB_HaId,lpSRB->reset.SRB_Target, lpSRB->reset.SRB_Lun);
446 lpSRB->reset.SRB_Status = aspi->SRBlock.status;
447 lpSRB->reset.SRB_Flags = aspi->SRBlock.flags;
448 lpSRB->reset.SRB_Hdr_Rsvd = 0;
449 memset( lpSRB->reset.SRB_Rsvd1,
450 0,
451 12 );
452 lpSRB->reset.SRB_HaStat = aspi->SRBlock.u.res.ha_status; /* Host Adapter Status */
453 lpSRB->reset.SRB_TargStat = aspi->SRBlock.u.res.target_status; /* Target Status */
454 lpSRB->reset.SRB_PostProc = NULL; /* Post routine */
455 lpSRB->reset.SRB_Rsvd2 = NULL; /* Reserved */
456 memset( lpSRB->reset.SRB_Rsvd3,
457 0,
458 32); /* Reserved */
459 dwRC = aspi->SRBlock.status;
460 break;
461
462 } // end switch (lpSRB->common.SRB_Cmd)
463
464 aspi->release();
465 }
466 else
467 {
468 dprintf(("Unable to access aspi!!"));
469 dwRC = SS_NO_ASPI;
470 }
471
472 return dwRC;
473}
474
475/***********************************************************************
476 * GetASPI32DLLVersion32 (WNASPI32.3)
477 */
478DWORD WINAPI GetASPI32DLLVersion()
479{
480 return (DWORD)1;
481}
482
Note: See TracBrowser for help on using the repository browser.