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

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

os2cdrom.dmd rewrite

File size: 14.5 KB
Line 
1/* $Id: winaspi32.cpp,v 1.14 2002-06-08 11:42:02 sandervl Exp $ */
2/*
3 * WNASPI routines
4 *
5 * Copyright 1999 Markus Montkowski
6 * Copyright 2000 Przemyslaw Dobrowolski
7 * Copyright 2002 Sander van Leeuwen
8 *
9 * Partly based on WINE code (dlls\winaspi\winaspi32.c)
10 *
11 * Copyright 1997 Bruce Milner
12 * Copyright 1998 Andreas Mohr
13 *
14 * Project Odin Software License can be found in LICENSE.TXT
15 *
16 */
17#include <os2win.h>
18#include <stdlib.h>
19#include <string.h>
20#include <sys/types.h>
21#include <sys/stat.h>
22#include <errno.h>
23#include <fcntl.h>
24#include <memory.h>
25
26#include "aspi.h"
27#include "wnaspi32.h"
28#include "options.h"
29#include "debugtools.h"
30#include "cdio.h"
31
32#ifdef DEBUG
33#define DEBUG_BUFFER
34#endif
35
36
37#ifdef DEBUG
38//*****************************************************************************
39//*****************************************************************************
40static void ASPI_DebugPrintCmd(SRB_ExecSCSICmd *prb)
41{
42 BYTE cmd;
43 int i;
44 BYTE *cdb;
45
46 switch (prb->CDBByte[0]) {
47 case CMD_INQUIRY:
48 TRACE("{\n");
49 TRACE("\tEVPD: %d\n", prb->CDBByte[1] & 1);
50 TRACE("\tLUN: %d\n", (prb->CDBByte[1] & 0xc) >> 1);
51 TRACE("\tPAGE CODE: %d\n", prb->CDBByte[2]);
52 TRACE("\tALLOCATION LENGTH: %d\n", prb->CDBByte[4]);
53 TRACE("\tCONTROL: %d\n", prb->CDBByte[5]);
54 TRACE("}\n");
55 break;
56 case CMD_SCAN_SCAN:
57 TRACE("Transfer Length: %d\n", prb->CDBByte[4]);
58 break;
59 }
60
61 TRACE("Host Adapter: %d\n", prb->SRB_HaId);
62 TRACE("Flags: %d\n", prb->SRB_Flags);
63 if (TARGET_TO_HOST(prb)) {
64 TRACE("\tData transfer: Target to host. Length checked.\n");
65 }
66 else if (HOST_TO_TARGET(prb)) {
67 TRACE("\tData transfer: Host to target. Length checked.\n");
68 }
69 else if (NO_DATA_TRANSFERED(prb)) {
70 TRACE("\tData transfer: none\n");
71 }
72 else {
73 WARN("\tTransfer by scsi cmd. Length not checked.\n");
74 }
75
76 TRACE("\tResidual byte length reporting %s\n", prb->SRB_Flags & 0x4 ? "enabled" : "disabled");
77 TRACE("\tLinking %s\n", prb->SRB_Flags & 0x2 ? "enabled" : "disabled");
78 TRACE("\tPosting %s\n", prb->SRB_Flags & 0x1 ? "enabled" : "disabled");
79 TRACE("Target: %d\n", prb->SRB_Target);
80 TRACE("Lun: %d\n", prb->SRB_Lun);
81 TRACE("BufLen: %ld\n", prb->SRB_BufLen);
82 TRACE("SenseLen: %d\n", prb->SRB_SenseLen);
83 TRACE("BufPtr: %p\n", prb->SRB_BufPointer);
84 TRACE("CDB Length: %d\n", prb->SRB_CDBLen);
85 TRACE("POST Proc: %lx\n", (DWORD) prb->SRB_PostProc);
86 cdb = &prb->CDBByte[0];
87 cmd = prb->CDBByte[0];
88#ifdef DEBUG_BUFFER
89 dprintfNoEOL(("CDB buffer["));
90 for (i = 0; i < prb->SRB_CDBLen; i++) {
91 if (i != 0) dprintfNoEOL((",0x%02x", *cdb++));
92 else dprintfNoEOL(("0x%02x", *cdb++));
93 }
94 dprintfNoEOL(("]\n"));
95#endif
96}
97//*****************************************************************************
98//*****************************************************************************
99static void ASPI_PrintSenseArea(SRB_ExecSCSICmd *prb)
100{
101 int i;
102 BYTE *cdb;
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 ASPI_DebugPrintResult(SRB_ExecSCSICmd *prb)
115{
116
117 switch (prb->CDBByte[0]) {
118 case CMD_INQUIRY:
119 TRACE("Vendor: '%s'\n", prb->SRB_BufPointer + INQUIRY_VENDOR);
120 break;
121 case CMD_TEST_UNIT_READY:
122 ASPI_PrintSenseArea(prb);
123 break;
124 }
125 dprintf(("Result code: %x", prb->SRB_Status));
126}
127#else
128#define ASPI_DebugPrintResult(a)
129#define ASPI_DebugPrintCmd(a)
130#endif
131
132//*****************************************************************************
133// Posting must be done in such a way that as soon as the SRB_Status is set
134// we don't touch the SRB anymore because it could possibly be freed
135// if the app is doing ASPI polling
136//*****************************************************************************
137static DWORD WNASPI32_DoPosting( SRB_ExecSCSICmd *lpPRB, DWORD status )
138{
139 void (* CDECL SRB_PostProc)(SRB_ExecSCSICmd *);
140 BYTE SRB_Flags = lpPRB->SRB_Flags;
141 if( status == SS_PENDING )
142 {
143 dprintf(("Tried posting SS_PENDING\n"));
144 return SS_PENDING;
145 }
146 *((DWORD *)&SRB_PostProc) = (DWORD)lpPRB->SRB_PostProc;
147
148 lpPRB->SRB_Status = status;
149 /* lpPRB is NOT safe, it could be freed in another thread */
150
151 if (SRB_PostProc)
152 {
153 if (SRB_Flags & 0x1)
154 {
155 dprintf(("Post Routine (%lx) called\n", (DWORD) SRB_PostProc));
156 /* Even though lpPRB could have been freed by
157 * the program.. that's unlikely if it planned
158 * to use it in the PostProc
159 */
160 (*SRB_PostProc)(lpPRB);
161 }
162 else if (SRB_Flags & SRB_EVENT_NOTIFY) {
163 dprintf(("Setting event %04x\n", (HANDLE)SRB_PostProc));
164 SetEvent((HANDLE)SRB_PostProc);
165 }
166 }
167 return lpPRB->SRB_Status;
168}
169//*****************************************************************************
170//*****************************************************************************
171static WORD ASPI_ExecScsiCmd(SRB_ExecSCSICmd *lpPRB)
172{
173 int status;
174 int error_code = 0;
175 LONG rc;
176 CDIO_CMD_BUFFER cdiocmd;
177
178 HCDIO hCDIO = OSLibCdIoGetDevice(lpPRB->SRB_HaId, lpPRB->SRB_Target, lpPRB->SRB_Lun);
179 if(hCDIO == -1) {
180 dprintf(("Failed: invalid device %d %d %d", lpPRB->SRB_HaId, lpPRB->SRB_Target, lpPRB->SRB_Lun));
181 return WNASPI32_DoPosting( lpPRB, SS_NO_DEVICE );
182 }
183
184 /* FIXME: hackmode */
185#define MAKE_TARGET_TO_HOST(lpPRB) \
186 if (!TARGET_TO_HOST(lpPRB)) { \
187 dprintf(("program was not sending target_to_host for cmd %x (flags=%x),correcting.\n",lpPRB->CDBByte[0],lpPRB->SRB_Flags)); \
188 lpPRB->SRB_Flags |= SRB_DIR_IN; \
189 }
190#define MAKE_HOST_TO_TARGET(lpPRB) \
191 if (!HOST_TO_TARGET(lpPRB)) { \
192 dprintf(("program was not sending host_to_target for cmd %x (flags=%x),correcting.\n",lpPRB->CDBByte[0],lpPRB->SRB_Flags)); \
193 lpPRB->SRB_Flags |= SRB_DIR_OUT; \
194 }
195 switch (lpPRB->CDBByte[0]) {
196 case 0x12: /* INQUIRY */
197 case 0x5a: /* MODE_SENSE_10 */
198 case 0xa4: /* REPORT_KEY (DVD) MMC-2 */
199 case 0xad: /* READ DVD STRUCTURE MMC-2 */
200 MAKE_TARGET_TO_HOST(lpPRB)
201 break;
202 case 0xa3: /* SEND KEY (DVD) MMC-2 */
203 MAKE_HOST_TO_TARGET(lpPRB)
204 break;
205 default:
206 if ((((lpPRB->SRB_Flags & 0x18) == 0x00) ||
207 ((lpPRB->SRB_Flags & 0x18) == 0x18)
208 ) && lpPRB->SRB_BufLen
209 ) {
210 dprintf(("command 0x%02x, no data transfer specified, but buflen is %ld!!!\n",lpPRB->CDBByte[0],lpPRB->SRB_BufLen));
211 }
212 break;
213 }
214
215 ASPI_DebugPrintCmd(lpPRB);
216
217 lpPRB->SRB_Status = SS_PENDING;
218
219 if (!lpPRB->SRB_CDBLen)
220 {
221 dprintf(("Failed: lpPRB->SRB_CDBLen = 0."));
222 return WNASPI32_DoPosting( lpPRB, SS_INVALID_SRB );
223 }
224
225 if(MAX_CDBLEN < lpPRB->SRB_CDBLen)
226 {
227 dprintf(("Failed: lpPRB->SRB_CDBLen > 64."));
228 return WNASPI32_DoPosting( lpPRB, SS_INVALID_SRB );
229 }
230
231 if(lpPRB->SRB_BufLen > 65536) // Check Max 64k!!
232 {
233 dprintf(("Failed: lpPRB->SRB_BufLen > 65536."));
234 return WNASPI32_DoPosting( lpPRB, SS_BUFFER_TO_BIG );
235 }
236
237 memset(&cdiocmd, 0, sizeof(cdiocmd));
238
239 if(lpPRB->SRB_Flags & SRB_DIR_IN) {
240 cdiocmd.flDirection |= CMDDIR_INPUT;
241 }
242 if(lpPRB->SRB_Flags & SRB_DIR_OUT) {
243 cdiocmd.flDirection |= CMDDIR_OUTPUT;
244 }
245
246 cdiocmd.cbCDB = lpPRB->SRB_CDBLen;
247 memcpy(cdiocmd.arCDB, lpPRB->CDBByte, lpPRB->SRB_CDBLen);
248
249#ifdef DEBUG_BUFFER
250 if(lpPRB->SRB_Flags & SRB_DIR_OUT) {
251 char *cdb = (char *)lpPRB->SRB_BufPointer;
252 dprintfNoEOL(("Write SRB buffer["));
253 for (int i = 0; i < lpPRB->SRB_BufLen; i++) {
254 if (i != 0) dprintfNoEOL((",0x%02x", *cdb++));
255 else dprintfNoEOL(("0x%02x", *cdb++));
256 }
257 dprintfNoEOL(("]\n"));
258 }
259#endif
260
261 lpPRB->SRB_HaStat = HASTAT_OK;
262 lpPRB->SRB_TargStat = HASTAT_OK;
263
264 if(OSLibCdIoSendCommand(hCDIO, &cdiocmd, lpPRB->SRB_BufPointer, lpPRB->SRB_BufLen) == FALSE) {
265 dprintf(("OSLibCdIoSendCommand failed!!"));
266 return WNASPI32_DoPosting( lpPRB, SS_ERR );
267 }
268
269 if(lpPRB->SRB_SenseLen) {
270 if(OSLibCdIoRequestSense(hCDIO, SENSE_BUFFER(lpPRB), lpPRB->SRB_SenseLen) == FALSE) {
271 dprintf(("OSLibCdIoRequestSense failed!!"));
272 return WNASPI32_DoPosting( lpPRB, SS_ERR );
273 }
274 }
275#ifdef DEBUG_BUFFER
276 if(lpPRB->SRB_Flags & SRB_DIR_IN) {
277 char *cdb = (char *)lpPRB->SRB_BufPointer;
278 dprintfNoEOL(("Write SRB buffer["));
279 for (int i = 0; i < lpPRB->SRB_BufLen; i++) {
280 if (i != 0) dprintfNoEOL((",0x%02x", *cdb++));
281 else dprintfNoEOL(("0x%02x", *cdb++));
282 }
283 dprintfNoEOL(("]\n"));
284 }
285#endif
286 ASPI_DebugPrintResult(lpPRB);
287 return WNASPI32_DoPosting( lpPRB, SS_COMP );
288}
289//*****************************************************************************
290// GetASPI32SupportInfo32 [WNASPI32.0]
291//
292// Checks if the ASPI subsystem is initialized correctly.
293//
294// RETURNS
295// HIWORD: 0.
296// HIBYTE of LOWORD: status (SS_COMP or SS_FAILED_INIT)
297// LOBYTE of LOWORD: # of host adapters.
298//*****************************************************************************
299DWORD CDECL GetASPI32SupportInfo()
300{
301 BYTE bNumDrv;
302 BYTE brc;
303
304 bNumDrv = 0;
305
306 // first thing we do is check whether we have a successful ASPI setup
307 if(fASPIAvailable == FALSE)
308 {
309 dprintf(("ASPI was not initialized successfully, return error"));
310 return (SS_FAILED_INIT << 8);
311 }
312
313 bNumDrv = OSLibCdIoGetNumDrives();
314 if (!bNumDrv)
315 return SS_NO_ADAPTERS << 8;
316
317 brc = SS_COMP;
318
319 //pretend there's only one controller
320 return ((brc << 8) | 1);
321}
322//*****************************************************************************
323// SendASPI32Command32 (WNASPI32.1)
324//*****************************************************************************
325DWORD CDECL SendASPI32Command(LPSRB lpSRB)
326{
327 DWORD dwRC;
328 ULONG ulParam, ulReturn;
329 BYTE bRC;
330 LONG rc;
331
332 // first thing we do is check whether we have a successful ASPI setup
333 if(fASPIAvailable == FALSE)
334 {
335 dprintf(("SendASPI32Command: ASPI was not initialized successfully, return error"));
336 return SS_NO_ASPI;
337 }
338
339 if(NULL==lpSRB)
340 return SS_INVALID_SRB; // Not sure what to return here but that is an error
341
342 dprintf(("SendASPI32Command %x %d", lpSRB, lpSRB->common.SRB_Cmd));
343
344 dwRC = SS_ERR;
345
346 switch (lpSRB->common.SRB_Cmd)
347 {
348 case SC_HA_INQUIRY:
349 lpSRB->inquiry.SRB_Status = SS_COMP; /* completed successfully */
350 lpSRB->inquiry.HA_Count = 1;
351 lpSRB->inquiry.HA_SCSI_ID = 7; /* not always ID 7 */
352 strcpy((char *)lpSRB->inquiry.HA_ManagerId, "ASPI for WIN32"); /* max 15 chars, don't change */
353 strcpy((char *)lpSRB->inquiry.HA_Identifier, "Odin host"); /* FIXME: return host adapter name */
354 memset(lpSRB->inquiry.HA_Unique, 0, 16); /* default HA_Unique content */
355 lpSRB->inquiry.HA_Unique[6] = 0x02; /* Maximum Transfer Length (128K, Byte> 4-7) */
356 lpSRB->inquiry.HA_Unique[3] = 0x08; /* Maximum number of SCSI targets */
357 dprintf(("ASPI: Partially implemented SC_HA_INQUIRY for adapter %d.\n", lpSRB->inquiry.SRB_HaId));
358
359 //OS/2 override
360 lpSRB->inquiry.HA_Unique[6] = 0x01; // transfer only 64KB
361 lpSRB->inquiry.HA_Unique[3] = 0x10; // 16 devices.
362
363 dwRC = SS_COMP;
364 break;
365
366 case SC_GET_DEV_TYPE:
367 {
368 dprintf(("SC_GET_DEV_TYPE %d %d %d", lpSRB->devtype.SRB_HaId, lpSRB->devtype.SRB_Target, lpSRB->devtype.SRB_Lun));
369
370 /* FIXME: We should return SS_NO_DEVICE if the device is not configured */
371 /* FIXME: We should return SS_INVALID_HA if HostAdapter!=0 */
372 SRB tmpsrb;
373 char inqbuf[200];
374 DWORD ret;
375
376 memset(&tmpsrb,0,sizeof(tmpsrb));
377
378 /* Copy header */
379 memcpy(&tmpsrb.common,&(lpSRB->common),sizeof(tmpsrb.common));
380
381 tmpsrb.cmd.SRB_Flags |= 8; /* target to host */
382 tmpsrb.cmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
383 tmpsrb.cmd.SRB_Target = lpSRB->devtype.SRB_Target;
384 tmpsrb.cmd.SRB_Lun = lpSRB->devtype.SRB_Lun;
385 tmpsrb.cmd.SRB_BufLen = sizeof(inqbuf);
386 tmpsrb.cmd.SRB_BufPointer = (BYTE *)inqbuf;
387 tmpsrb.cmd.CDBByte[0] = 0x12; /* INQUIRY */
388 /* FIXME: handle lun */
389 tmpsrb.cmd.CDBByte[4] = sizeof(inqbuf);
390 tmpsrb.cmd.SRB_CDBLen = 6;
391
392 ret = ASPI_ExecScsiCmd(&tmpsrb.cmd);
393
394 lpSRB->devtype.SRB_Status = tmpsrb.cmd.SRB_Status;
395 lpSRB->devtype.SRB_DeviceType = inqbuf[0] & 0x1f;
396
397 TRACE("returning devicetype %d for target %d\n", inqbuf[0] & 0x1f, tmpsrb.cmd.SRB_Target);
398
399 if (ret!=SS_PENDING) /* Any error is passed down directly */
400 return ret;
401 /* FIXME: knows that the command is finished already, pass final Status */
402 return tmpsrb.cmd.SRB_Status;
403 }
404
405 case SC_EXEC_SCSI_CMD:
406 dwRC = ASPI_ExecScsiCmd(&lpSRB->cmd);
407 break;
408
409 case SC_ABORT_SRB:
410 dprintf(("SC_ABORT_SRB %d", lpSRB->abort.SRB_HaId));
411 dwRC = SS_INVALID_SRB; // We don't do async ASPI so no way to abort
412 break;
413
414 case SC_RESET_DEV:
415 {
416 HCDIO hCDIO = OSLibCdIoGetDevice(lpSRB->reset.SRB_HaId, lpSRB->reset.SRB_Target, lpSRB->reset.SRB_Lun);
417 if(hCDIO == -1) {
418 return SS_NO_DEVICE;
419 }
420 dprintf(("SC_RESET_DEV %d %d %d", lpSRB->reset.SRB_HaId, lpSRB->reset.SRB_Target, lpSRB->reset.SRB_Lun));
421 OSLibCdIoResetUnit(hCDIO);
422 dwRC = SS_COMP;
423 break;
424 }
425
426 case SC_GET_DISK_INFO:
427 /* here we have to find out the int13 / bios association.
428 * We just say we do not have any.
429 */
430 FIXME("SC_GET_DISK_INFO always return 'int13 unassociated disk'.\n");
431 lpSRB->diskinfo.SRB_DriveFlags = 0; /* disk is not int13 served */
432 return SS_COMP;
433
434 default:
435 dprintf(("Invalid command!"));
436 return SS_INVALID_SRB; // shoud be invalid command
437
438 } // end switch (lpSRB->common.SRB_Cmd)
439
440 dprintf(("SendASPI32Command %x %d done", lpSRB, lpSRB->common.SRB_Cmd));
441 return dwRC;
442}
443//*****************************************************************************
444// GetASPI32DLLVersion32 (WNASPI32.3)
445//*****************************************************************************
446DWORD CDECL GetASPI32DLLVersion()
447{
448 return (DWORD)1;
449}
450//*****************************************************************************
451//*****************************************************************************
452
453
Note: See TracBrowser for help on using the repository browser.