OS/2 codes: How to control CD-ROM drives
OS/2 provides ioctl commands to control CD-ROM drives and discs. And some commands have been added with new OS2CDROM.DMD. In this article, let's research the ways to control CD-ROM drives and to utilize new commands.
1. Opening or Closing a Tray
The most strange thing of OS/2 ioctl commands are CDROMDISK_CLOSETRAY. It's not possible to issue the command. Because a handle for a disc is required to issue, but there is no way to open a handle for the opened drives.
This is applied to CDROMDISK_EJECTDISK. It's not possible to issue the command if a disc is not in a drive.
To open and/or to close a tray, another way should be used. OS/2 provides general ioctl commands to eject and to load a media for a removable media . Ejecting is used to open a tray. Loading is used to close a tray. These commands can be issued without a handle. Therefore, it's possible to open and to close a tray even if a disc is not in the drive. Codes are like this:
Here, cmd may be 0 for unlocking, 1 for locking, 2 for ejecting and 3 for loading. drive is 0 = A, 1 = B, 2 = C, and so forth. In this case, a handle should be -1 as you see at line 14.
Ejecting and loading may fail according to CD-ROM drives.
2. Getting drive letters for CD-ROM drives
New OS2CDROM.DMD provides a special device, CD-ROM2$. With it, it's possible to get CD-ROM drive letters. It can be called with 0x82 category and 0x60 function. It returns the drive letter of a first CD-ROM drive and the number of the consecutive CD-ROM drives. The way calling it is like this:
IOCTL_CDROMDISK2 is 0x82, CDROMDISK2_DRIVELETTERS is 0x60. data.usDriveCount will be the number of consecutive CD-ROM drives and data.usDriveFirst will be the driver unit, 0 = A, 1 = B, 2 = C, and so forth.
Unless using this command, iterating drive A to drive Z and checking its type to determine if it is a CD-ROM drive should be used.
3. Executing SCSI commands
New OS2CDROM.DMD supports to execute SCSI commands. Such command may be called with 0x08 category and 0x7A function.
The parameter packet is like:
param.auchSign should be always 'CD01', which is not null-terminating string. param.usDataLength is the length of data packet passed to DosDevIOCtl(). param.usCmdLength is the length of the requested SCSI command. param.abCmdBuffer is the buffer of the requested SCSI command. param.usFlags specify a transfer direction and error checking. The following values are available:
If EX_DIRECTION_IN is set, then it will read from a CD-ROM drive. If unset, it will write to a CD-ROM drive. If EX_PLAYING_CHK is set, it will return an error while playing audio. If unset, it will execute a command regardless of playing audio.
Codes to execute SCSI commands look like:
param is the parameter packet, cbDataBuf is the length of data buffer in bytes, cbCmdBuf is the length of command buffer in bytes, usFlags is the flags for transfer direction and error checking, pCmdBuf is the buffer of the SCSI command, hcdio is a handle for a CD-ROM disc opened in DASD mode, pDataBuf is the buffer of data packet.
Using this command, it's possible to perform commands not supported OS/2 ioctl commands. However, this command does not support SCSI SENSE REPLY. For this, maybe ASPI routers such as ASPIROUT.SYS should be used.
4. Conclusion
Opening and/or closing a tray need some tricks. And new OS2CDROM.DMD introduced some useful ioctl commands. New OS2CDROM.DMD supports more than the above. For details, see CD-ROM Device Manger (OS2CDROM.DMD) part of Technical Notes shipped with Convenience Packages.
You can get the implemeneted sources here:
1. Opening or Closing a Tray
The most strange thing of OS/2 ioctl commands are CDROMDISK_CLOSETRAY. It's not possible to issue the command. Because a handle for a disc is required to issue, but there is no way to open a handle for the opened drives.
This is applied to CDROMDISK_EJECTDISK. It's not possible to issue the command if a disc is not in a drive.
To open and/or to close a tray, another way should be used. OS/2 provides general ioctl commands to eject and to load a media for a removable media . Ejecting is used to open a tray. Loading is used to close a tray. These commands can be issued without a handle. Therefore, it's possible to open and to close a tray even if a disc is not in the drive. Codes are like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #pragma pack( 1 ) struct { BYTE bCmdInfo; BYTE bDrive; } param; #pragma pack() ULONG ulParamLen = sizeof( param ); ULONG ulDataLen = 0; param.bCmdInfo = cmd; param.bDrive = drive; DosDevIOCtl(( HFILE )-1, IOCTL_DISK, DSK_UNLOCKEJECTMEDIA, ¶m, ulParamLen, &ulParamLen, NULL, ulDataLen, &ulDataLen ); |
Here, cmd may be 0 for unlocking, 1 for locking, 2 for ejecting and 3 for loading. drive is 0 = A, 1 = B, 2 = C, and so forth. In this case, a handle should be -1 as you see at line 14.
Ejecting and loading may fail according to CD-ROM drives.
2. Getting drive letters for CD-ROM drives
New OS2CDROM.DMD provides a special device, CD-ROM2$. With it, it's possible to get CD-ROM drive letters. It can be called with 0x82 category and 0x60 function. It returns the drive letter of a first CD-ROM drive and the number of the consecutive CD-ROM drives. The way calling it is like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | HFILE hcd2; ULONG ulAction; ULONG ulParamLen = 0; #pragma pack( 1 ) struct { USHORT usDriveCount; USHORT usDriveFirst; } data; #pragma pack() ULONG ulDataLen = sizeof( data ); if( DosOpen(( PSZ )"CD-ROM2$", ( PHFILE )&hcd2, &ulAction, 0, FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW, OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, NULL ) == 0 ) { DosDevIOCtl( hcd2, IOCTL_CDROMDISK2, CDROMDISK2_DRIVELETTERS, NULL, ulParamLen, &ulParamLen, &data, ulDataLen, &ulDataLen ); DosClose( hcd2 ); } |
IOCTL_CDROMDISK2 is 0x82, CDROMDISK2_DRIVELETTERS is 0x60. data.usDriveCount will be the number of consecutive CD-ROM drives and data.usDriveFirst will be the driver unit, 0 = A, 1 = B, 2 = C, and so forth.
Unless using this command, iterating drive A to drive Z and checking its type to determine if it is a CD-ROM drive should be used.
3. Executing SCSI commands
New OS2CDROM.DMD supports to execute SCSI commands. Such command may be called with 0x08 category and 0x7A function.
The parameter packet is like:
1 2 3 4 5 6 7 8 9 10 11 | #pragma pack( 1 ) struct { UCHAR auchSign[ 4 ]; // 'CD01' USHORT usDataLength; // length of the Data Packet USHORT usCmdLength; // length of the Command Buffer USHORT usFlags; // flags BYTE abCmdBuffer[ 16 ]; // Command Buffer for SCSI command } param = { .auchSign = {'C', 'D', '0', '1'}, }; #pragma pack() |
param.auchSign should be always 'CD01', which is not null-terminating string. param.usDataLength is the length of data packet passed to DosDevIOCtl(). param.usCmdLength is the length of the requested SCSI command. param.abCmdBuffer is the buffer of the requested SCSI command. param.usFlags specify a transfer direction and error checking. The following values are available:
1 2 3 4 | /* 0, if transfer data to device, 1, if transfer data from device */ #define EX_DIRECTION_IN 0x0001 /* 0, if don't check playing audio, 1, if device plays audio return error */ #define EX_PLAYING_CHK 0x0002 |
If EX_DIRECTION_IN is set, then it will read from a CD-ROM drive. If unset, it will write to a CD-ROM drive. If EX_PLAYING_CHK is set, it will return an error while playing audio. If unset, it will execute a command regardless of playing audio.
Codes to execute SCSI commands look like:
1 2 3 4 5 6 7 8 9 10 11 12 | ULONG ulParamLen = sizeof( param ); ULONG ulDataLen = cbDataBuf; param.usDataLength = ulDataLen; param.usCmdLength = cbCmdBuf; param.usFlags = usFlags; memcpy( param.abCmdBuffer, pCmdBuf, cbCmdBuf ); DosDevIOCtl(( HFILE )hcdio, IOCTL_CDROMDISK, CDROMDISK_EXECMD, ¶m, ulParamLen, &ulParamLen, pDataBuf, ulDataLen, &ulDataLen ); |
param is the parameter packet, cbDataBuf is the length of data buffer in bytes, cbCmdBuf is the length of command buffer in bytes, usFlags is the flags for transfer direction and error checking, pCmdBuf is the buffer of the SCSI command, hcdio is a handle for a CD-ROM disc opened in DASD mode, pDataBuf is the buffer of data packet.
Using this command, it's possible to perform commands not supported OS/2 ioctl commands. However, this command does not support SCSI SENSE REPLY. For this, maybe ASPI routers such as ASPIROUT.SYS should be used.
4. Conclusion
Opening and/or closing a tray need some tricks. And new OS2CDROM.DMD introduced some useful ioctl commands. New OS2CDROM.DMD supports more than the above. For details, see CD-ROM Device Manger (OS2CDROM.DMD) part of Technical Notes shipped with Convenience Packages.
You can get the implemeneted sources here:
- source: https://github.com/komh/os2codes/blob/master/system/cdio.c
- header: https://github.com/komh/os2codes/blob/master/system/cdio.h
- test: https://github.com/komh/os2codes/blob/master/system/cdio-test.c
댓글
댓글 쓰기