Board index » delphi » Talking to more than one CD-ROM drive in TP6.0

Talking to more than one CD-ROM drive in TP6.0


I didn't see any news follow-up to your posted message in Deja News or
my ISP's on-line news data so I'm gonna give this a shot...

This is from MSCDEX21.DOC that can be found in places on the net...

>CD-ROM Drive Check
>     AX     150Bh
>     BX     Signature word
>     CX     CD-ROM Drive letter (A=0, B=1,...Z=25)
>This function returns whether or not a drive letter is a CD-ROM drive
>supported by MSCDEX. If the extensions are installed, BX will be set to
>ADADh. If the drive letter is supported by MSCDEX, then AX is set to a non-
>zero value. AX is set to zero if the drive is not supported. One must be
>sure to check the signature word to know that MSCDEX is installed and that
>AX has not been modified by another INT 2Fh handler.

One key thing is to check the AX value returned for this call.  You don't.

>MSCDEX will return the number of CD-ROM drive letters in BX and the starting
>drive letter in CX. The first CD-ROM device will be installed at the
>starting drive letter and subsequent drives will be assigned the next
>greater drive letter. A single device driver may be assigned to more than
>one drive letter, such as the case of a device driver that supports multiple
>units. MSCDEX keeps track of which sub-unit a particular drive letter is
>assigned to.

>  This function can be used to determine if MSCDEX is installed by setting
>  BX to zero before executing INT 2Fh. MSCDEX is not installed if BX is
>  still zero on return.

>Also, in a networking environment, one cannot assume that drive letters will
>always be assigned contiguously beginning with the starting drive letter.
>Use function Get CD-ROM drive letters instead.

>Get CD-ROM Drive Device List

>     AX        1501h
>     ES:BX     Transfer address; pointer to buffer to copy drive letter
>               device list

>The buffer must be large enough to hold the device list. By calling function
>Get Number of CD-ROM Drive Letters, one can find out the number of CD-ROM
>drive letters and the buffer size will be a multiple of that. This will be
>an absolute maximum of 26. Each drive letter device entry will consist of
>one byte for the sub-unit followed by 4 bytes for the address of the device
>header assigned to that drive letter. This byte for the sub-unit takes care
>of the problem of distinguishing which unit is assigned to which drive
>letter for device drivers that handle sub-units.
>For example: Suppose there are two installed CD-ROM device drivers, FOO,
>which supports 1 sub-unit, and BAR, which supports two sub-units, on a
>system with 2 floppy drives (A=0 and B=1) and a hard disk (C=2). Then asking
>for the number of CD-ROM drive letters will report that there are 3 drive
>letters used starting at drive letter D=3. ES:BX must point to a buffer that
>is at least 3 * 5 = 15 bytes long. The buffer will be filled as follows:

>ES:BX  = Buffer

>Buffer   DB   0                        ; sub-unit of FOO on drive letter D:
>         DD   <far addr of FOO device header>
>         DB   0                        ; sub-unit of BAR on drive letter E:
>         DD   <far addr of BAR device header>
>         DB   1                        ; sub-unit of BAR on drive letter F:
>         DD   <far addr of BAR device header>

If you do a call to this function (INT 2FH function 1501H) then look at
CD_ROM_LIST_ENTRY cd_dev_list[26];   // saves the list of cd rom drives


typedef struct {
   void far *next_device;
   unsigned dev_attributes;
   void (near *strategy)(void);
   void (near *device_interrupt)(void);
   char char_device_name[8];
   unsigned _res;
   char drive_number;
   char sub_unit_count;
   } HSGDRV;

typedef struct {
   char  letter;
   HSGDRV far *device_header;

then cd_dev_list[iii].device_header->char_device_name will be the
device name of the MSCDEX.EXE /D:MSCD001 /D:MSCD002 line and
cd_dev_list[iii].device_header->drive_number+'A'-1 will be the
drive letter and
cd_dev_list[iii].device_header->drive_number-1 will be the
cd drive number (A=0, B=1, C=2, ...).

As you can tell, I have just been writing my own CD Rom access
functions but in C (sorry not pascal).

I have the trouble that I have two CD Rom drives too, but the added
twists are that one is SCSI and the other is EIDE / ATAPI.  Two
different device drivers are involved, not just one with two
different sub-units, and I am using Win95 drivespace 3
compressed drives--one of which appears between my first
and second CD-Rom drives--J: and L: with K: being a compressed

I was just starting my research for doing IOCTL calls
through MSCDEX when I searched for MSCDEX and IOCTL in
Dja News and found your article.

>Send Device Driver Request

>     AX     1510h
>     CX     CD-ROM drive letter (A=0, B=1, ... Z=25)
>     ES:BX  Address of CD-ROM device driver request header

>This function has been added to simplify communication with CD-ROM drivers
>and help prevent contention between applications that wish to communicate
>with the device driver. It is highly recommended that all applications
>communicate with device drivers through this function request. Applications
>using this function will not have to locate the device driver. The format of
>the request header is specified by the Microsoft MS-DOS CD-ROM Extensions
>Hardware-Dependent Device Driver Specification.

>Request header

>MSCDEX.EXE will call the device's strategy routine with the address of a
>request header in ES:BX. The format of the request header is the same as
>what is described in the MS-PRM.


- Show quoted text -

>ReqHdr    DB   ?         ; Length in bytes of request header
>          DB   ?         ; Subunit code for minor devices
>          DB   ?         ; Command code field
>          DW   ?         ; Status
>          DB   8 dup (?) ; Reserved


>The status word also has the same format as described in the MS-PRM. It is 0
>on entry and is set by the device driver.

>  Bit 15         - Error bit
>  Bit 14-10      - Reserved
>  Bit  9         - Busy
>  Bit  8         - Done
>  Bit  7-0       - Error code (bit 15 on)


- Show quoted text -

>Command Code Field

>The following values are valid command codes:

>    0  INIT
>    1   MEDIA CHECK (block devices)
>    2   BUILD BPB (block devices)
>    4   INPUT (read)
>    8   OUTPUT (write)
>   15   REMOVABLE MEDIA (block devices)
>  128  READ LONG                (NEW)
>  129   Reserved
>  130  READ LONG PREFETCH       (NEW)
>  131  SEEK                     (NEW)
>  132  PLAY AUDIO               (NEW)
>  133  STOP AUDIO               (NEW)
>  134  WRITE LONG               (NEW)
>  135  WRITE LONG VERIFY        (NEW)
>  136  RESUME AUDIO             (NEW)

>Unsupported or illegal commands will set the error bit and return the error
>code for Unknown Command. This includes command codes 1, 2, 4, 5, 6, 8, 9,
>10, 15, 16, and 129; and 11, 134 and 135 for systems that do not support

>If, in the time since the last request to that device driver unit, the media
>has changed, the device driver will return the error code for invalid disk
>change and set the error bit. MSCDEX.EXE will then decide whether to retry
>the request or abort it.

>The minimal CD-ROM device driver will read cooked Mode 1 data sectors using
>HSG addressing mode and return appropriate values for the IOCTL calls. Most
>other features enhance performance or add useful capabilities.


>Command code = 12

>IOCTLO    DB   13 dup (0); Request header
>          DB   0         ; Media descriptor byte from BPB
>          DD   ?         ; Transfer address
>          DW   ?         ; Number of bytes to transfer
>          DW   0         ; Starting sector number
>          DD   0         ; DWORD ptr to requested vol ID if error 0FH

This definition differs from your in that it does not specifically
say that the SEG portion of the pointers are one word and the OFFSET
is the next.  If you got the order wrong for the SEG, OFFSET this
would point your transfer address to some place weird where the
popular value of zero (eject) might happen to be?

With C and C++ and Assembler it is possible to declare the
double words as the far pointers that they are.  When my
program manipulates these locations, I do it via simple
assignments of addr_ptr = &int_var_loc, or
addr_ptr = char_string (which is equivalent to
addr_ptr = &char_string[0].

The advantage of this is that it keeps the program a bit more
readable by other humans and reduces the assembler required to
a minimum, and the "to an extent" non-portable splitting of
addresses into their SEG/OFFSET components.  Since this
software is working with MSCDEX or CDFS on Dos/Win/Win95
it will be fairly non-portable to begin with unless the
functions are translated one to one to Motorola with the
structure definitions largely unchanged.

From what I remember of turbo pascal, there is a cast
operator, and pointer types, and pointer dereferencing.
Probably there can be Far pointers and casting to those
types.  If you have gotten it wrong, then it might be
an idea to re-code your program and declarations to
use pointers and do pointer assignments.

- Show quoted text -

>The media descriptor byte, starting sector number, and volume ID fields are
>all 0.

>The transfer address points to a control block that is


read more »


Re:Talking to more than one CD-ROM drive in TP6.0


You can find MSCDEX21.DOC at

(or similar.. I don't have the exact reference handy ... :-) )

There is an example interface to the MSCDEX API under TP6 at

This unit is NOT for multiple CD-ROM drives; however, there are
only about 2- 3 places in the source where you would need to
make any changes, and these are marked. You will need to refer
to the mscdex21.doc text.

Basically, to control a CD-ROM you need to know which device driver
owns it, and the sub-unit number of the CD-ROM within the driver.
(A single driver can operate multiple CD-ROMS. Alternatively, each
CD-ROM can have its own driver...)

I hope this helps,

Re:Talking to more than one CD-ROM drive in TP6.0

In <>, Chris Rankin <> writes:

Anyone wanting the source code to a unit which can control multiple drives etc
without the in depth driver programming side, just E-Mail me and I'll send
it to you. ...

It's simple, and it's effective. Works with any CD-ROM that is accessed via
MSCDEX. (Even works under OS/2)

Paul L Daniels
Software Development (DOS, OS/2)

Other Threads