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:

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,
                &param, 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,
                &param, 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:


댓글

이 블로그의 인기 게시물

토렌트: < 왕좌의 게임 > 시즌 1 ~ 시즌 8 완결편 마그넷

토렌트: NGC < 코스모스 > 우리말 더빙 전편(1편~13편) 마그넷

토렌트: < 스타워즈 > Ep.1 ~ Ep.6 마그넷