                         MSCDEX   ver. 2.20
                            / part one /

This document (Document Number: 000080010-100-O00-1186) describes the 
CD-ROM hardware-dependent device driver and its interface with
MSCDEX.EXE, the MS-DOS CD-ROM Extensions resident program.
Differences between CD-ROM drives and hard- or floppy-disk drives
account for the differences in this device driver specification from
the normal MS-DOS block and character device driver specification.
The chapters on device drivers in the MS-DOS Programmer's Reference
Manual (MS-PRM) provide more information.

The MS-DOS operating system reads CONFIG.SYS and installs the device. 
MSCDEX.EXE performs an open system call on the device driver name in
order to communicate with it and uses an IOCTL call to ask the device 
driver for the address of its device header. From the device header
address, MSCDEX.EXE locates the device driver's interrupt and
strategy routines. After that, all requests the device driver
receives come directly from MSCDEX.EXE, not MS-DOS. To avoid
reentrancy problems and allow MSCDEX to monitor all media changes,
all other applications that wish to communicate directly with CD-ROM
device drivers should do so through the Send Device Driver Request
INT 2Fh function 10h. MSCDEX.EXE interfaces with MS-DOS so that
normal requests for I/O with files on a CD-ROM drive down to the
MS-DOS INT 21h service layer will work just as they would for a
normal MS-DOS device.

Installation

The device driver will be installed in the same way as any other
device with an entry in CONFIG.SYS. The syntax is:

DEVICE=<filename> /D:<device_name> /N:<number of drives>

The following are examples:

DEVICE=HITACHI.SYS /D:MSCD001 /D:MSCD002
DEVICE=SONY.SYS /D:MSCD003 /N:2

The arguments will be the character device names that will be used on 
the command line when starting MSCDEX.EXE so that it can find and
communicate with the device driver.

A device driver may support one or more physical drives or logical
disks. This may be done by having multiple device headers in the
device driver file (in which case it will be necessary to have more
than one device_name on the command line - one for each device
header; see the HITACHI.SYS example above) or through the use of
subunits. Each disk handled by a device driver that supports multiple 
disks using subunits is addressed by the subunit field of the request 
header when a request is made for that disk. A device driver that
supports more than one disk can share code and data instead of
requiring separate device drivers for each disk. A "jukebox" CD-ROM
system would be an example of a CD-ROM device that might wish to
support more than one drive or a disk pack using a single device
driver.

Device drivers that use multiple subunits should use the optional
switch /n:<number of drives> to say how many drives are present. If
not present, the default number of drives is 1. If the driver can
tell how many drives are installed without a command line switch,
then this argument is not necessary. Unless there are special
considerations, it is better practice to support multiple drives
using subunits than to have multiple device headers in the same
device driver file.
Device header

The device header is an extension to what is described in the
MS-PRM.

DevHdrDD-1; Ptr to next driver in file or -1 if last driver
DW?; Device attributes
DW?; Device strategy entry point
DW?; Device interrupt entry point
DB8 dup (?); Character device name field
DW0; Reserved
DB0; Drive letter
DB?; Number of units

The following are the device attributes for MSCDEX.EXE device
drivers:

Bit 151       - Character device
Bit 141       - IOCTL supported
Bit 130       - Output 'till  busy
Bit 120       - Reserved
Bit 111       - OPEN/CLOSE/RM supported
Bit 10-40       - Reserved
Bit 30       - Dev is CLOCK
Bit 20       - Dev is NUL
Bit 10       - Dev is STO
Bit 00       - Dev is STI

MSCDEX.EXE device drivers will be character devices that understand
IOCTL calls and handle OPEN/CLOSE/RM calls.

The drive letter field is a read-only field for the device driver and 
is initialized to 0. The field is for MSCDEX.EXE to use when it
assigns the device driver to a drive letter (A = 1, B = 2...Z = 26).
It should never be modified by the device driver. For drivers that
support more than one unit, the drive letter will indicate the first
unit, and each successive unit is assigned the next higher drive
letter. For example, if the device driver has four units defined
(0-3), it requires four drive letters. The position of the driver in
the list of all drivers determines which units correspond to which
drive letters. If driver ALPHA is the first driver in the device
list, and it defines 4 units (0-3), they will be A, B, C, and D. If
BETA is the second driver and defines three units (0-2), they will be 
E, F, and G, and so on. The theoretical limit to the number of drive
letters is 63, but it should be noted that the device installation
code will not allow the installation of a device if it would result
in a drive letter > 'Z' (5Ah). All block device drivers present in
the standard resident BIOS will be placed ahead of installable device 
drivers in the list.

NOTE: It is important that one set lastdrive=<letter> in CONFIG.SYS
to accommodate the additional drive letters that CD-ROM device
drivers will require.

The number-of-units field is set by the device driver to the number
of disks that are supported. Normal character devices do not support
more than one unit and MS-DOS does not expect a character device to
handle more than one unit or have a nonzero subunit value in the
request header. Since these device drivers are not called by MS-DOS
directly, this is not a problem. Nonetheless, the number of units
returned by the device driver in the number-of-units field during the 
INIT call must be 0, since MS-DOS makes the INIT call and does not
expect a nonzero value for a character device. MSCDEX.EXE will never
see what is returned anyway, and relies on the number-of-units field
in the device header.

The signature field is necessary for MSCDEX confirmation that the
device driver is a valid cd-rom device driver and consists of the 4
bytes 'MSCD' followed by two ascii digits for the version which is
'00' at present.



Sample device header:

HsgDrvDD-1; Pointer to next device
DW0c800h; Device attributes
DWSTRATEGY; Pointer to device strategy routine
DWDEVINT ; Pointer to device interrupt routine
DB'MSCD003 '; 8-byte character device name field
DW0; Reserved (must be zero)
DB0; Drive letter (must be zero)
DB1; Number of units supported (one or more)

As with other MS-DOS device drivers, the code originates at offset 0, 
not 100H. The first device header will be at offset 0 of the code
segment. The pointer to the next driver is a double word field
(offset/segment) that is the address of the next device driver in the 
list, or -1 if the device header is the only one or the last in the
list. The strategy and interrupt entry points are word fields and
must be offsets into the same segment as the device header. The
device driver is expected to overwrite the name(s) in each of its one 
or more device headers with the <device_name> command line arguments
during its initialization.

MSCDEX.EXE will call the device driver in the following manner:
1. MSCDEX.EXE makes a far call to the strategy entry.
2. MSCDEX.EXE passes device driver information in a request header to 
the strategy routine.
3. MSCDEX.EXE makes a far call to the interrupt entry.

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.

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

Status
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)

Bit 15, the error bit, is set by the device driver if an error is
detected or if an invalid request is made to the driver. The low 8
bits indicate the error code.

Bit 9, the busy bit, should be set by the device driver when the
drive is in audio play mode. Device drivers should fail all requests
to the physical device that require head movement when the device is
playing and return the request with this bit and the error bit set
and an error code. Requests that would not interrupt audio play may
return without error but will also have this bit set when the drive
is in audio play mode. Play mode can be terminated prematurely with a 
reset or STOP AUDIO request and a new request can be made at that
point. Monitoring this bit in each successive request, an Audio
Q-Channel Info IOCTL for example, will tell when play mode is
complete.

Bit 8, the done bit, is set by the device driver when the operation
is finished.  Error codes are the following:

0  Write-protect violation1Unknown unit
2Drive not ready3Unknown command
4CRC error5Bad drive request structure length
6Seek error7Unknown media
8Sector not found9Printer out of paper
AWrite faultBRead fault
CGeneral failureDReserved
EReservedFInvalid disk change

Command code field
The following values are valid command codes:

*0INIT
1MEDIA CHECK (block devices)
2BUILD BPB (block devices)
*3IOCTL INPUT
4INPUT (read)
5NONDESTRUCTIVE INPUT NO WAIT
6INPUT STATUS
*7INPUT FLUSH
8OUTPUT (write)
9OUTPUT WITH VERIFY
10OUTPUT STATUS
#11OUTPUT FLUSH
*12IOCTL OUTPUT
*13DEVICE OPEN
*14DEVICE CLOSE
15REMOVABLE MEDIA (block devices)
16OUTPUT UNTIL BUSY
*128READ LONG(NEW) 
129Reserved
*130READ LONG PREFETCH(NEW)
*131SEEK(NEW)
+132PLAY AUDIO(NEW)
+133STOP AUDIO(NEW)
#134WRITE LONG(NEW) 
#135WRITE LONG VERIFY(NEW) 
+136RESUME AUDIO(NEW)

* Supported by a basic CD-ROM device driver (required)
+ Supported by an extended CD-ROM device driver
# Supported by erasable CD-ROM device drivers for authoring systems

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 writing.

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.
INIT

Command code = 0
ES:BX = INIT

INITDB13 dup (0); Request header
DB0; Number of units (must be 0)
DD?; End address
DD?; Ptr to BPB array
DB0; Block device number
________________

This call is made only once, when the device is installed. INIT and a 
single IOCTL call for the device header address are the only device
driver calls that come directly from MS-DOS. Because the INIT
function is called from MS-DOS, the number of units returned is 0, as 
for normal MS-DOS character devices. MSCDEX.EXE will get the number
of units supported from the device header.

The device must return the END ADDRESS, which is a DWORD pointer to
the end of the portion of the device driver to remain resident. Code
and data following the pointer is used for initialization and then
discarded. If there are multiple device drivers in a single file, the 
ending address returned by the last INIT call will be the one that
MS-DOS uses, but it is recommended that all the device drivers in the 
file return the same address. The code to remain resident for all the 
devices in a single file should be grouped together low in memory
with the initialization code for all devices following it in memory.

The pointer to BPB array points to the character after the "=" on the 
line in CONFIG.SYS that caused this device driver to be loaded. This
data is read-only and allows the device driver to scan the invocation 
line for parameters. This line is terminated by a carriage return or
a line feed.
During initialization, the device driver must set the device name
field in the device header to the argument provided on the invocation 
line in CONFIG.SYS. The device driver must also check that the
device_name command line argument is a legal 8-character filename and 
pad it out to 8 characters with spaces (20H) when copying it to the
device name field.

The block device number and number of units are both 0 for character
devices.

READ (IOCTL Input)

Command code = 3
ES:BX = IOCTLI
________________

IOCTLIDB13 dup (0); Request header
DB0; Media descriptor byte from BPB
DD?; Transfer address
DW?; Number of bytes to transfer
DW0; Starting sector number 
DD0; DWORD ptr to requested vol 
; ID if error 0FH
________________

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

The transfer address points to a control block that is used to
communicate with the device driver. The first byte of the control
block determines the request that is being made. If the command code
is reserved or the function not supported, then the device driver
will return the error code for Unknown Command. If, for some reason,
the device driver is not able to process the request at that time, it 
will return the error code for Drive Not Ready.

CodeNumber of bytes to transferFunction

05Return Address of Device Header
16Location of Head
2?Reserved
3?Error Statistics
49Audio Channel Info
5130Read Drive Bytes
65Device Status
74Return Sector Size
85Return Volume Size
92Media Changed
107Audio Disk Info
117Audio Track Info
1211Audio Q-Channel Info
1313Audio Sub-Channel Info
1411UPC Code
1511Audio Status Info
16-255?Reserved

- Return Address of Device Header
________________

RaddrDB0; Control block code
DD?; Address of device header
________________

The device driver will fill the 4-byte field with the address of its
device header. This is used by MSCDEX.EXE to locate the device
driver's strategy and interrupt routines.

- Location of Head
________________

LocHeadDB1; Control block code
DB?; Addressing mode
DD?; Location of drive head
________________

The device driver will return a 4-byte address that indicates where
the head is located. The value will be interpreted based on the
addressing mode. (See function READ LONG for more information about
addressing modes.)

NOTE: the drive could provide this information by monitoring the
Q-channel on the disk.

- Error Statistics
________________

ErrStatDB3; Control block code
DBN dup (?); Error statistics
________________

The format of the Error Statistics is not yet defined.




- Audio Channel Info
________________

AudInfoDB4; Control block code
DB?; Input channel (0, 1, 2, or 3) for output channel 0
DB?; Volume control (0 - 0xff) for output channel 0
DB?; Input channel (0, 1, 2, or 3) for output channel 1
DB?; Volume control (0 - 0xff) for output channel 1
DB?; Input channel (0, 1, 2, or 3) for output channel 2
DB?; Volume control (0 - 0xff) for output channel 2
DB?; Input channel (0, 1, 2, or 3) for output channel 3
DB?; Volume control (0 - 0xff) for output channel 3
________________

This function returns the present settings of the audio channel
control set with the Audio Channel Control Ioctl Write function. The
default settings for the audio channel control are for each input
channel to be assigned to its corresponding output channel (0 to 0, 1 
to 1, etc.) and for the volume control on each channel is set at
0xff.

- Read Drive Bytes
________________

DrvBytesDB5; Control block code
DB?; Number bytes read
DB128 dup (?); Read buffer
________________

Data returned from the CD-ROM drive itself can be read using this
function. The number-bytes-read field returns the length of the
number of bytes read, which will not exceed 128 per call. If more
than this needs to be returned, the call will be repeated until the
number returned is less than 128.

The function and content of these bytes are entirely device and
device driver dependent. This function is provided to allow access to 
device-specific features that are not addressed under any other
portion of the device driver spec.

- Device Status
________________

DevStatDB6; Control block code
DD?; Device parameters
________________

The device driver will return a 32-bit value. Bit 0 is the least
significant bit. The bits are interpreted as follows:

Bit 00Door closed
1Door open
Bit 10Door locked
1Door unlocked
Bit 20Supports only cooked reading
1Supports cooked and raw reading
Bit 30Read only
1Read/write
Bit 40Data read only
1Data read and plays audio/video tracks
Bit 50No interleaving
1Supports ISO-9660 interleaving using interleave size 
and skip factor
Bit 60Reserved
Bit 70No prefetching
1Supports prefetching requests
Bit 80No audio channel manipulation
1Supports audio channel manipulation
Bit 90Supports HSG addressing mode
1Supports HSG and Red Book addressing modes
Bit 100Reserved
Bit 110Disc is present in drive
1No disc is present in drive
Bit 120Doesn't support R-W sub-channels
1Supports R-W sub-channels
Bit 13-310Reserved (all 0)

- Return  Sector Size
________________

SectSizeDB7; Control block code
DB?; Read mode
DW?; Sector size
________________

The device driver will return the sector size of the device given the 
read mode provided. In the case of CD-ROM, the value returned for
cooked is 2048, and the return value  for raw is 2352.

- Return  Volume Size
________________

VolSizeDB8; Control block code
DD?; Volume size
________________

The device driver will return the number of sectors on the device.
The size returned is the address of the lead-out track in the TOC
converted to a binary value according to FRAME + (SEC * 75) + (MIN *
60 * 75). A disc with a lead out track starting at 31:14.63 would
return a volume size of 140613. The address of the lead-out track is
assumed to point to the first sector following the last addressable
sector recorded on the disc.

- Media Changed
________________

MedChngDB9; Control block code
DB?; Media byte
________________

The normal media check function (command code 1) is not performed on
character devices and contains additional semantics that are not
needed for CD-ROM device drivers. This is why there is an IOCTL
request for this function.

When the device driver receives a call to see if the media has
changed on that subunit, it will return one of the following values:

1Media not changed
0Don't know if changed
-1 (0FFh)Media changed

If the driver can assure that the media has not been changed (through 
a door-lock or other interlock mechanism), performance is enhanced
because MSCDEX.EXE does not need to reread the VTOC and invalidate
in-memory buffers for each directory access. For drives that do not
report if the media has changed, CD-ROM device drivers can utilize
the same solution that has been applied to floppy disks. In some
floppy-disk device drivers, if the MEDIA CHECK occurs within 2
seconds of a floppy-disk access, the driver reports "Media not
changed." It is highly recommended though that drives be able to
detect and report media changes.

If the drive can enforce a door lock mechanism so that the device
driver is notified when the door lock has been unlocked or the device 
driver is requested to do so by MSCDEX.EXE, then to improve
performance, the driver could return that the media has not changed
without bothering to communicate with the physical device.

If the media has not been changed, MSCDEX.EXE will proceed with the
disk access. If the value returned is "Don't know," or "Media
changed," then MSCDEX.EXE will check to see if the disk has changed.
It will  continue if it has not, and reinitialize what it knows about 
the disk if it has.

It is not necessary for the device driver to do anything for the
volume ID when the media has changed.

- Audio Disk Info
________________

DiskInfoDB10; Control block code
DB?; Lowest track number
DB?; Highest track number
DD?; Starting point of the lead-out track
________________

This function returns TOC (Table of Contents) information from the
Q-Channel in the lead-in track indicating what the first and last
track numbers are and the Red Book address for the lead-out track
(PMIN/PSEC/PFRAME when POINT = A2). The first and last track numbers
are binary values and not BCD. It is recommended that the information 
for Audio Disk Info and Audio Track Info should be read by the drive
when the disc is initialized and made accessible to the driver so
that when these functions are called, the drive or driver do not have 
to interrupt audio play to read them from the TOC. If the TOC is not
made available to the driver and the driver must obtain the
information itself from the lead-in track, the driver should read and 
and attempt to cache the disk and track information during the Audio
Disk Info command and invalidate this information only if the media
changes.
