source: trunk/src/wnaspi32/cdio.cpp@ 8706

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

os2cdrom.dmd rewrite

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