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

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

bugfixes

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