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

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

PD:bugfixes

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