source: trunk/src/kernel32/oslibcdio.cpp@ 22018

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

Ported & extended QueryDosDeviceA/W; implemented IOCTL_SCSI_GET_CAPABILITIES; don't fail CDIO init if media not present

File size: 11.0 KB
Line 
1/*
2 * OS2CDROM.DMD interface for sending SCSI commands
3 *
4 * Based on example code by:
5 * (c) 2001 S&T Systemtechnik GmbH
6 *
7 * erzeugt: 15.02.01 R.Ihle
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12
13#define INCL_NOPMAPI
14#define INCL_DOSDEVICES
15#define INCL_DOSDEVIOCTL
16#define INCL_DOSFILEMGR
17#define INCL_DOSMISC
18#include <os2wrap.h>
19
20#include "cdioctl.h"
21
22#include <stdio.h>
23#include <string.h>
24#include <malloc.h>
25
26#include "oslibCdIo.h"
27#include <win32type.h>
28
29
30//needed for high memory support check
31DWORD SYSTEM OSLibDosDevIOCtl( DWORD hFile, DWORD dwCat, DWORD dwFunc,
32 PVOID pParm, DWORD dwParmMaxLen, DWORD *pdwParmLen,
33 PVOID pData, DWORD dwDataMaxLen, DWORD *pdwDataLen);
34
35static BOOL fDisableCDIo = FALSE;
36
37//----------------------------------------------------------------------//
38// Open drive //
39//----------------------------------------------------------------------//
40void WIN32API DisableCDIo()
41{
42 fDisableCDIo = TRUE;
43}
44
45//----------------------------------------------------------------------//
46// Initialize CD/DVD drive access //
47//----------------------------------------------------------------------//
48
49BOOL OSLibCdIoInitialize(void)
50{
51 ULONG ulAction, ulFeatures;
52 int fResult = 0;
53 HFILE hDev;
54
55 if(fDisableCDIo) {
56 return FALSE;
57 }
58
59 if( DosOpen("CD-ROM2$", &hDev, &ulAction, 0, FILE_NORMAL,
60 OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
61 OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE |
62 OPEN_FLAGS_FAIL_ON_ERROR, NULL) == 0 )
63 {
64 fResult = DosDevIOCtl(hDev, IOCTL_CDROMDISK2, CDROMDISK2_FEATURES,
65 NULL, 0, NULL, &ulFeatures, sizeof(ulFeatures), NULL) == 0 &&
66 (ulFeatures & FEATURE_EXECMD_SUPPORT);
67
68 DosClose(hDev);
69 }
70
71 return fResult;
72}
73
74
75//----------------------------------------------------------------------//
76// Unload ASPI manager //
77//----------------------------------------------------------------------//
78
79BOOL OSLibCdIoTerminate(void)
80{
81 return 1;
82}
83
84
85//----------------------------------------------------------------------//
86// Open drive //
87//----------------------------------------------------------------------//
88
89BOOL OSLibCdIoIsSupported(HFILE hDisk)
90{
91 ULONG ulAction, ulCDSig;
92
93 ulCDSig = ('C') | ('D' << 8) | ('9' << 16) | ('9' << 24);
94
95 if(OSLibCdIoInitialize() == FALSE) {
96 return FALSE;
97 }
98
99 if(hDisk == 0) {//no media present; return success here as the DosDevIOCtl will fail
100 return TRUE;
101 }
102
103 if(DosDevIOCtl(hDisk, IOCTL_CDROMDISK, CDROMDISK_GETDRIVER, &ulCDSig, sizeof(ulCDSig), NULL,
104 &ulCDSig, sizeof(ulCDSig), NULL) == 0 &&
105 ulCDSig == (('C') | ('D' << 8) | ('0' << 16) | ('1' << 24)) )
106 {
107 return TRUE;
108 }
109 return FALSE;
110}
111
112
113//----------------------------------------------------------------------//
114// Send command to drive //
115//----------------------------------------------------------------------//
116
117BOOL OSLibCdIoSendCommand(HCDIO hCdIo, CDIO_CMD_BUFFER *pCmdBuf, void *pData, unsigned cbData)
118{
119 struct ExecCmd Param;
120 ULONG ulDummy, ParmLen, DataLen;
121
122 if( !pData || !cbData )
123 {
124 ulDummy = 0; pData = &ulDummy; cbData = sizeof(ulDummy);
125 }
126
127 Param.ID_code = 'C' | ('D'<<8) | ('0'<<16) | ('1'<<24);
128 Param.data_length = (USHORT)cbData;
129 Param.cmd_length = pCmdBuf->cbCDB;
130 Param.flags = (USHORT)
131 (( pCmdBuf->flDirection & 1 ) ? EX_DIRECTION_IN : 0);
132 memcpy(Param.cmd_buffer, pCmdBuf->arCDB, sizeof(Param.cmd_buffer));
133
134
135 ParmLen = sizeof(Param);
136 DataLen = cbData;
137 return OSLibDosDevIOCtl((HFILE)hCdIo, IOCTL_CDROMDISK, CDROMDISK_EXECMD,
138 &Param, ParmLen, &ParmLen, pData, cbData, &DataLen) == 0;
139}
140
141
142//----------------------------------------------------------------------//
143// Load / Eject disk //
144//----------------------------------------------------------------------//
145
146BOOL OSLibCdIoLoadEjectDisk(HCDIO hCdIo, int fLoad)
147{
148 CDIO_CMD_BUFFER CmdBuf;
149
150 memset(&CmdBuf, 0, sizeof(CmdBuf));
151 CmdBuf.flDirection = CMDDIR_OUTPUT;
152 CmdBuf.cbCDB = 6;
153 CmdBuf.arCDB[0] = 0x1b; // START STOP UNIT command
154 CmdBuf.arCDB[4] = (unsigned char)(( fLoad ) ? 0x03 : 0x02);
155 // Bit 1: 0:Start/Stop, 1:Load/Eject
156 // Bit 0: 0:Stop/Eject, 1:Start/Load
157 return OSLibCdIoSendCommand(hCdIo, &CmdBuf, NULL, 0);
158}
159
160
161//----------------------------------------------------------------------//
162// Test drive readyness //
163//----------------------------------------------------------------------//
164
165BOOL OSLibCdIoUnitReady(HCDIO hCdIo)
166{
167 CDIO_CMD_BUFFER CmdBuf;
168
169 memset(&CmdBuf, 0, sizeof(CmdBuf));
170 CmdBuf.flDirection = CMDDIR_OUTPUT;
171 CmdBuf.cbCDB = 6;
172// CmdBuf.arCDB[0] = 0x00; // TEST UNIT READY command
173
174 return OSLibCdIoSendCommand(hCdIo, &CmdBuf, NULL, 0);
175}
176
177
178//----------------------------------------------------------------------//
179// Reset drive //
180//----------------------------------------------------------------------//
181
182BOOL OSLibCdIoResetUnit(HCDIO hCdIo)
183{
184 CDIO_CMD_BUFFER CmdBuf;
185
186 memset(&CmdBuf, 0, sizeof(CmdBuf));
187 CmdBuf.flDirection = CMDDIR_OUTPUT;
188 CmdBuf.cbCDB = 6;
189 CmdBuf.arCDB[0] = 0x01; // REZERO command
190
191 return OSLibCdIoSendCommand(hCdIo, &CmdBuf, NULL, 0);
192}
193
194
195//----------------------------------------------------------------------//
196// Query information about drive //
197//----------------------------------------------------------------------//
198
199BOOL OSLibCdIoInquiry(HCDIO hCdIo, unsigned uPageCode, void *pData, unsigned cbData)
200{
201 CDIO_CMD_BUFFER CmdBuf;
202
203 if( cbData > 255 ) cbData = 255;
204
205 memset(&CmdBuf, 0, sizeof(CmdBuf));
206 CmdBuf.flDirection = CMDDIR_INPUT;
207 CmdBuf.cbCDB = 6;
208 CmdBuf.arCDB[0] = 0x12; // INQUIRY CAPACITY command
209 CmdBuf.arCDB[4] = (unsigned char)cbData;
210
211 if( uPageCode )
212 {
213 CmdBuf.arCDB[1] = 1; // enable vital product data
214 CmdBuf.arCDB[2] = (unsigned char)uPageCode;
215 }
216
217 return OSLibCdIoSendCommand(hCdIo, &CmdBuf, pData, cbData);
218}
219
220
221//----------------------------------------------------------------------//
222// Query sense information //
223//----------------------------------------------------------------------//
224
225BOOL OSLibCdIoRequestSense(HCDIO hCdIo, void *pData, unsigned cbData)
226{
227 CDIO_CMD_BUFFER CmdBuf;
228
229 if( cbData > 255 ) cbData = 255;
230
231 memset(&CmdBuf, 0, sizeof(CmdBuf));
232 CmdBuf.flDirection = CMDDIR_INPUT;
233 CmdBuf.cbCDB = 6;
234 CmdBuf.arCDB[0] = 0x03; // REQUEST SENSE command
235 CmdBuf.arCDB[4] = (unsigned char)cbData;
236
237 return OSLibCdIoSendCommand(hCdIo, &CmdBuf, pData, cbData);
238}
239
240
241//----------------------------------------------------------------------//
242// Query disc capacity //
243//----------------------------------------------------------------------//
244
245BOOL OSLibCdIoQueryCapacity(HCDIO hCdIo, unsigned *pctBlocks, unsigned *pcbBlock)
246{
247 CDIO_CMD_BUFFER CmdBuf;
248 unsigned arResult[2];
249
250 memset(&CmdBuf, 0, sizeof(CmdBuf));
251 CmdBuf.flDirection = CMDDIR_INPUT;
252 CmdBuf.cbCDB = 10;
253 CmdBuf.arCDB[0] = 0x25; // READ CAPACITY command
254
255 if( OSLibCdIoSendCommand(hCdIo, &CmdBuf, arResult, sizeof(arResult)) )
256 {
257 *pctBlocks = (arResult[0] << 24) |
258 ((arResult[0] & 0x0000ff00) << 8) |
259 ((arResult[0] & 0x00ff0000) >> 8) |
260 (arResult[0] >> 24);
261
262 *pcbBlock = (arResult[1] << 24) |
263 ((arResult[1] & 0x0000ff00) << 8) |
264 ((arResult[1] & 0x00ff0000) >> 8) |
265 (arResult[1] >> 24);
266
267 return 1;
268 }
269
270 return 0;
271}
272
273
274//----------------------------------------------------------------------//
275// Read data //
276//----------------------------------------------------------------------//
277
278BOOL OSLibCdIoReadBlock(HCDIO hCdIo, unsigned uLBA, void *pData, unsigned cbData)
279{
280 CDIO_CMD_BUFFER CmdBuf;
281
282 memset(&CmdBuf, 0, sizeof(CmdBuf));
283 CmdBuf.flDirection = CMDDIR_INPUT;
284 CmdBuf.cbCDB = 10;
285// CmdBuf.arCDB[0] = 0x3e; // READ LONG command MODE SELECT ???
286// CmdBuf.arCDB[1] = 0x02; // Bit 1: perform ECC
287
288 CmdBuf.arCDB[0] = 0x28; // READ command
289 CmdBuf.arCDB[2] = (unsigned char)(uLBA >> 24);
290 CmdBuf.arCDB[3] = (unsigned char)(uLBA >> 16);
291 CmdBuf.arCDB[4] = (unsigned char)(uLBA >> 8);
292 CmdBuf.arCDB[5] = (unsigned char)(uLBA);
293 CmdBuf.arCDB[7] = 0;
294 CmdBuf.arCDB[8] = 1;
295
296 return ( cbData > 2047 ) ? OSLibCdIoSendCommand(hCdIo, &CmdBuf, pData, cbData) : 0;
297}
298
299
300//----------------------------------------------------------------------//
301// Query bit mask of all CD drives //
302//----------------------------------------------------------------------//
303
304ULONG OSLibCdIoQueryDriveList(void)
305{
306 BIOSPARAMETERBLOCK BPB;
307 HFILE hDev;
308 struct DrvInfo CDInfo;
309 ULONG ulAction, ulParam, uDriveMap = 0;
310
311 if( DosOpen("CD-ROM2$", &hDev, &ulAction, 0, FILE_NORMAL,
312 OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
313 OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE |
314 OPEN_FLAGS_FAIL_ON_ERROR, NULL) == 0 )
315 {
316 if( DosDevIOCtl(hDev, IOCTL_CDROMDISK2, CDROMDISK2_DRVINFO,
317 NULL, 0, NULL, &CDInfo, sizeof(CDInfo), NULL) == 0 )
318 {
319 // Workaround for Warp4/FP14 kernel bug ...
320 ulParam = CDInfo.usFirstDrvNo << 8;
321 while( CDInfo.usFirstDrvNo <= ('Z' - 'A') &&
322 DosDevIOCtl((HFILE)-1, IOCTL_DISK, DSK_GETDEVICEPARAMS,
323 &ulParam, 2, NULL, &BPB, sizeof(BPB), NULL) == 0 &&
324 BPB.bDeviceType != DEVTYPE_UNKNOWN )
325 {
326 ulParam = ++CDInfo.usFirstDrvNo;
327 }
328
329 if( CDInfo.usFirstDrvNo > ('Z' - 'A') ) CDInfo.usDrvCount = 0;
330
331 while( CDInfo.usDrvCount-- )
332 uDriveMap |= 1 << (CDInfo.usFirstDrvNo + CDInfo.usDrvCount);
333 }
334
335 DosClose(hDev);
336 }
337
338 return uDriveMap;
339}
340
341
342//----------------------------------------------------------------------//
343// Query fully qualified path name of a given file //
344//----------------------------------------------------------------------//
345
346BOOL OSLibCdIoQueryFullName(char *pchPartName, char *pchFullName, unsigned cbFullName)
347{
348 APIRET rc;
349
350 DosError(FERR_DISABLEHARDERR);
351 rc = DosQueryPathInfo(pchPartName, FIL_QUERYFULLNAME, pchFullName, cbFullName);
352 DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
353
354 return rc == 0;
355}
356
357
358//----------------------------------------------------------------------//
359// Read volume label //
360//----------------------------------------------------------------------//
361BOOL OSLibCdIoQueryVolumeLabel(char chDrive, char *pchLabel, unsigned cbLabel)
362{
363 FSINFO FsInfo;
364
365 memset(pchLabel, '\0', cbLabel);
366 if( cbLabel && DosQueryFSInfo((chDrive & 0x5f) - 'A' + 1,
367 FSIL_VOLSER, &FsInfo, sizeof(FsInfo)) == 0 )
368 {
369 strncpy(pchLabel, FsInfo.vol.szVolLabel, cbLabel);
370 pchLabel[cbLabel-1] = '\0';
371 return 1;
372 }
373
374 return 0;
375}
376
377
Note: See TracBrowser for help on using the repository browser.