From: Tomas BURBA <tburba@stud.ktu.lt>
Subject: Re: How to detect if you can read from CDROM Drive - if a CD is inserted ?
Date: Sunday, August 22, 1999 12:48 PM

Philipp Schweighardt wrote:
> My enviroment:
> - C program compiled with WatCom C Ver. 11.0b.
> - runs under DOS 6.22 using a dos extender (DOS32A - 100% compatible
> to DOS4GW).

  Indeed, I use BC++ 3.1 and no extenders, but the following may help
you. I'm working on similar problem.


> I know how to detect if a drive is a cdrom, but I dont know how to
> detect prior to access of the cdrom whether a cd is inserted to it or
> not

  First, I get available CD-ROM drive letters (for insurance too):

INT 2F - CD-ROM - INSTALLATION CHECK
        AX = 1500h
        BX = 0000h
Return: BX = number of CD-ROM drive letters used
        CX = starting drive letter (0=A:)
Notes:  this installation check DOES NOT follow the format used by
          other software
        this installation check conflicts with the DOS 4.00 GRAPHICS.COM
          installation check
BUG:    this function may return an incorrect starting drive letter when
          INTERLNK is installed

  Second, I determine device driver header addresses:

INT 2F - CD-ROM - GET DRIVE DEVICE LIST    
        AX = 1501h    
        ES:BX -> buffer to hold drive letter list (5 bytes per drive
                 letter)
Return: buffer filled, for each drive letter
          BYTE  subunit number in driver
          DWORD address of device driver header (see #0987)
Note:   reportedly returns AX=0000h and an invalid address under
        Windows95

  Device driver name can be found in its header, at offset 000Ah (eight
characters, blank-padded). So, I copy these eight chars to temporary
ASCIIZ buffer and open the driver as file (INT 21h, AH=3Dh or
int open(char *path, int access) from io.h).
  All further operations can be done via driver's IOCTL, using the
handle which we just got:

INT 21 - CD-ROM device driver - IOCTL INPUT
        AX = 4402h
        BX = file handle referencing character device for CD-ROM driver
        CX = number of bytes to read
        DS:DX -> control block (see #0793)
Return: CF clear if successful
            AX = number of bytes actually read
        CF set on error
            AX = error code (01h,05h,06h,0Dh) (see #1020 at
                 AH=59h/BX=0000h)
Note:   the data returned depends on the first byte of the control
          block; the remainder of the control block is filled by
          the driver

(Table 0792)
Values for CD-ROM data being requested:
 00h    device driver header address
 01h    drive head location
 02h    reserved
 03h    error statistics
 04h    audio channel info
 05h    raw drive bytes (uninterpreted and device-specific)
 06h    device status
 07h    sector size
 08h    volume size
 09h    media change status
 0Ah    audio disk info
 0Bh    audio track info
 0Ch    audio Q-Channel info
 0Dh    audio sub-channel info
 0Eh    UPC code
 0Fh    audio status info

Format of CD-ROM control block:
Offset  Size    Description     (Table 0793)
 00h    BYTE    data being requested (see #0792)
---function 00h---
 01h    DWORD   device driver header address (see also AH=52h,#0987)
---function 01h---
 01h    BYTE    addressing mode
                00h HSG
                01h Red Book
 02h    DWORD   current location of drive's head
                logical sector number in HSG mode
                frame/second/minute/unused in Red Book mode
                (HSG sector = minute * 4500 + second * 75 + frame - 150)
---function 03h---
 01h  N BYTEs   undefined as of 5 Aug 88 specification
---function 04h---
 01h    BYTE    input channel (0-3) for output channel 0
 02h    BYTE    volume for output channel 0
 03h    BYTE    input channel (0-3) for output channel 1
 04h    BYTE    volume for output channel 1
 05h    BYTE    input channel (0-3) for output channel 2
 06h    BYTE    volume for output channel 2
 07h    BYTE    input channel (0-3) for output channel 3
 08h    BYTE    volume for output channel 3
Notes:  output channels 0 and 1 are left and right, 2 and 3 are left
          prime and right prime; a volume of 00h is off
        the default setting is for each input channel to be assigned
          to the same-numbered output channel at full (FFh) volume
---function 05h---
 01h    BYTE    number of bytes read
 02h 128 BYTEs  buffer for drive bytes
---function 06h---
 01h    DWORD   device parameters (see #0794)
---function 07h---
 01h    BYTE    read mode
                00h cooked
                01h raw
 02h    WORD    sector size in bytes
---function 08h---
 01h    DWORD   volume size in sectors
---function 09h---
 01h    BYTE    media change status
                00h don't know
                01h media unchanged
                FFh media has been changed
---function 0Ah---
 01h    BYTE    lowest audio track number
 02h    BYTE    highest audio track number
 03h    DWORD   start address of lead-out track (Red Book format)
--function 0Bh---
 01h    BYTE    track number (set by caller)
 02h    DWORD   starting point of track (Red Book format)
 06h    BYTE    track control info
                bits 15,14,12: track type (notice: bits not contiguous!)
                        000 two audio channels, no pre-emphasis
                        001 two audio channels with pre-emphasis
                        010 data track
                        100 four audio channels, no pre-emphasis
                        101 four audio channels with pre-emphasis
                        other reserved
                bit 13: digital copy permitted
---function 0Ch---
 01h    BYTE    CONTROL and ADR byte (as received from drive)
 02h    BYTE    track number
 03h    BYTE    point or index
 04h    BYTE    minute  \
 05h    BYTE    second   > running time within track
 06h    BYTE    frame   /
 07h    BYTE    zero
 08h    BYTE    "AMIN" or "PMIN"     \
 09h    BYTE    "ASEC" or "PSEC"      > running time on disk
 0Ah    BYTE    "AFRAME" or "PFRAME" /
---function 0Dh---
 01h    DWORD   starting frame address (Red Book format)
 05h    DWORD   transfer address
 09h    DWORD   number of sectors to read
Note:   copies 96 bytes of sub-channel info per sector into buffer
---function 0Eh---
 01h    BYTE    CONTROL and ADR byte
 02h  7 BYTEs   UPC/EAN code (13 BCD digits,low-order nybble of last 
                byte is 0)
 09h    BYTE    zero
 0Ah    BYTE    "AFRAME"
---function 0Fh---
 ??? documentation not yet available
 01h    WORD    pause status (0000h not paused, 0001h paused)
 03h    DWORD   audio play start address
 07h    DWORD   ??? audio play length or end address

Bitfields for CD-ROM device parameters:
Bit(s)  Description     (Table 0794)
 0      door open
 1      door unlocked
 2      supports raw reading in addition to cooked
 3      writable
 4      can play audio/video tracks
 5      supports interleaving
 6      reserved
 7      supports prefetch requests
 8      supports audio channel control
 9      supports Red Book addressing in addition to HSG
 10     audio is playing
 11     no disk in drive
 12     supports R-W subchannels

  So, to check if media is present, you'll have to issue fn 06 and look
to the result bit 11 in control block.
  I currently tried only fn 01 and 04 -- works fine.


> I am to avoid dos system messages like ABORT, RETRY, ... !!!

  As far as I remember, while copying from defective CD, I always got
message NOT from DOS, but from device driver itself:

  CDR101: Not ready reading drive E:
  Abort, Retry, Ignore, Fail?

  But I suppose that this message can be suppressed as DOS critical
error messages too, via specifying your own INT 24h handler.
For example,

  #pragma argsused
  int handler();
  {
      hardretn(_DI);  /* return DOS error code to app */
  }

  .
  .
  .

  harderr(&handler);

  Experiment.
-- 
   Tomas (IRC: Pacifist  ICQ: 36743324)
   ANSI C & ASM, x86 / 8051 