CDManager module 3.00 Functional Specification
-----------------------------------------------

Authors: T.G.Roddis, Mike Challis



Contents
--------

 2        Purpose
 4        Product Overview
 5        Concepts and Definitions
 5.1         Definitions
 5.2         Concepts
 6        User Interfaces
 7        Programmer Interfaces
 7.1         The Application Programmer's Interface
 7.1.1          Audio Mode
 7.1.2          Data Mode
 7.1.3          Media changes and error handling
 7.1.4          Addresses
 7.1.5          SWIs
 7.1.6          Star commands
 7.1.7          Errors
 7.1.8          Initialisation and Finalisation
 7.1.9          New drives
 7.2         The Driver Control Interface
 7.2.1          Initialisation and Finalisation
 7.2.2          Service Calls
 7.2.3          SWIs
 7.2.4          Entering Drivers
 7.2.5          Driver entry points
 7.2.6          Error codes returned by drivers
 7.2.7          Notes on driver writing
 

2. Purpose
----------

This document describes the behaviour of CDManager 3.00. CDManager provides
support for the Philips' coloured book standards (including CD-ROM/XA) and
manages CD driver modules. 


4. Product Overview
-------------------

The CDManager provides a set of hardware-independent control and data
access SWIs.

Furthermore, it provides an interface for driver-writers so that client
applications can access a variety of different types of drives transparently.
Drivers must provide a small subset of possible operations with a variety of
optional extra operations. Scope for including extra hardware independent
SWIs to CDManager is provided and a bypass mechanism allowing full use of all
features of the underlying drive exists; drivers should return an error for
any operation they do not support.



5. Concepts and Definitions
---------------------------

5.1 Definitions
---------------

Error numbers are given in this specification relative to the module's error
base; this is indicated by the notation '+n'. This notation is also used when
describing the layout of parameter blocks, and there represents a byte offset
from the start of the block.


5.2 Concepts
------------

The CDManager has a dual responsibility: firstly, it manages the drivers,
providing help in the form of service calls, enforcing a standard interface,
and storing some state as tables so that drivers need not be aware of
high-level abstractions; secondly, it provides a single interface to
client applications wishing to use CDs.



6. User Interfaces
------------------

The end-user should not need to use this module directly. Instead Acorn and
third-parties should provide client applications which have specific
functionalities eg. a CD-DA player or CD-I viewer.



7. Programmer Interfaces
------------------------

Two programmer interfaces are described in the following sections: 7.1
describes the application programmer's interface (the one which CDFS uses);
7.2 describes the interface used by CDManager when communicating with
hardware dependent driver modules.


7.1 The Application Programmer's Interface
------------------------------------------

In order to provide for different coloured book standards, and so that more
standards may be added, CDManager imposes no constraints on the format and
variety of data that might be returned to an application. However, some
things remain true for all applications:

A drive is addressed by its logical drive number. Note that this mapping
is not guaranteed to remain constant over system resets, even if the hardware
configuration remains unchanged; for example, it may be dependent on the
order in which individual drives powered up. However, a method is provided
for checking that a logical drive has a certain physical identity.

Sectors comprise either audio information or data information. Both kinds of
sectors contain information about the 'audio mode', but only data sectors
contain data mode information:


7.1.1 Audio Mode
----------------

This information, stored in sub-channel Q of the sector, describes the type
of information contained within that sector as follows:

      /------------------------------.------------------------------\
      |        C  L  E  A  R         |            S  E  T           |
      |------------------------------+------------------------------|
bit 0 | Audio without pre-emphasis   | Audio with pre-emphasis      |
bit 1 | Digital copy prohibited      | Digital copy permitted       |
bit 2 | Audio track                  | Data track                   |
bit 3 |        ---:      Reserved (currently zero)      :--         |
      \-------------------------------------------------------------/


So that:

    00x0 - audio without pre-emphasis
    00x1 - audio with pre-emphasis
    0x0x - copy prohibited
    0x1x - copy permitted
    01x0 - digital data


7.1.2 Data Mode
---------------

This information, which is held in the header field of each data sector,
describes the type of data in that sector:

    00      Zero sector             
    01      Mode 1
    02      Mode 2  
    other   Reserved


With some drives it may be impracticable to determine whether the data are in
Mode 1 or Mode 2 Form 1, as the user data size is 2048 bytes per sector in
each case.


7.1.3 Media changes and error handling
--------------------------------------

When a disc is changed or inserted for the first time the drive (or driver)
latches a media changed condition. A media change count or 'sequence number'
is stored within CDManager. This count is incremented each time the CD is
changed and clients are expected to call CDMgr_DriveOp with the
GetSequenceNumber reason code to find out what this number is for the disc in
which they are interested. They should then remember this number for future
accesses to that disc.


More formally, calls to CDManager can be classified into three kinds:

  a) Administrative calls that do not require access to a drive; an example
     is CDMgr_Version, which returns the module's version number.

  b) Calls that require access to a drive, but not to a disc; examples are
     calls to lock the drive, or to set the drive's speed or playback volume.

  c) Calls that generally require access to a disc, such as CDMgr_ReadData.


In calls of type (b), the drive is identified by a logical drive number, and
CDManager processes this drive number as follows:

  If no drive of that number is registered with CDManager, the following
  error is returned:

     +10  Drive number not known

  Otherwise the appropriate call is made to the driver which, if the drive is
  not ready for the requested operation, may return one of the following
  errors:

     +0   Disc may have changed
     +1   Drive empty
     +2   Drive becoming ready
     +3   Drive not responding as expected

  If error +0 (Disc may have changed) is returned, CDManager increments the
  current sequence number associated with the drive (see case (c) below) and
  then reissues the driver call.

  In summary, clients of CDManager must be prepared to handle the following
  drive-related errors from calls of type (b):

     +1   Drive empty
     +2   Drive becoming ready
     +3   Drive not responding as expected
     +10  Drive number not known


In calls of type (c), the disc of interest is identified by a logical drive
number together with a sequence number. CDManager maintains a 'current
sequence number' for each registered drive; this is a value that is
incremented whenever the disc is changed in that drive. The logical drive
number and sequence number are processed as follows for type (c) calls:

  If no drive with the given logical drive number is registered with
  CDManager, the following error is returned:

     +10  Drive number not known

  If the given sequence number differs from the current sequence number
  associated with the drive, the following error is returned:

     +0   Disc may have changed

  Otherwise the appropriate call is made to the driver which, if the drive is
  not ready for the requested operation, may return one of the following
  errors:

     +0   Disc may have changed
     +1   Drive empty
     +2   Drive becoming ready
     +3   Drive not responding as expected

  If error +0 (Disc may have changed) is returned, CDManager increments the
  current sequence number associated with the drive; in all error cases, the
  error is then returned to the client.

  In summary, clients of CDManager must be prepared to handle the following
  drive-related errors from calls of type (c):

     +0   Disc may have changed
     +1   Drive empty
     +2   Drive becoming ready
     +3   Drive not responding as expected
     +10  Drive number not known


In more detail, the meanings of these errors are as follows:

 +0   Disc may have changed

    Any disc present in the drive may be different from the one which was
    present when this client last accessed the drive.

 +1   Drive empty

    No disc is accessible in the drive, but it is otherwise available for
    use.

 +2   Drive becoming ready

    At present it is not possible to say whether the drive contains a disc,
    and, if so, whether it may be different from one previously held in
    the drive. However, it is probable that this state of affairs will be
    resolved within the next few seconds (and without manual intervention).

 +3   Drive not responding as expected

    There seems to be some problem with the drive that is unlikely to be
    resolved without manual intervention or software/hardware reset. This
    state includes the "Drive not available" state which arises when a
    registered drive has been powered down.

 +10  Drive number not known

    No drive is registered with this logical drive number.

In some cases, drivers may choose to return more specific errors in place of
+3 (Drive not responding as expected), and so clients will usually treat any
errors in the range +128 to +255 in the same way as +3  (see 7.2.6).


7.1.4 Addresses
---------------

MSF (Minute, Second and Frame) addresses are not supported by SWIs, so there
is a means to convert between MSF and physical sector addresses.


7.1.5 SWIs
----------

Optional functionality is marked [OPTIONAL (n)] in the description below.
If a client application requires the use of optional SWIs, it should first
call CDMgr_GetSupported to determine whether or not the drive and driver can
provide the required functionality: the functionality is present if bit (n)
of the 'supported flags word' is set.

All registers are preserved unless otherwise stated.

By convention, every SWI definition must include at least one reserved bit
which is required to be zero on entry in order to allow for future expansion.
Here, R0 is used for this purpose, and is also used to hold any reason code
for the SWI. Reason codes are assigned sequentially from zero and are placed
in the least significant part of R0, whereas flag bits are assigned from the
most significant bit downwards: all other bits of R0 are reserved, and must
be set to zero.

The SWI chunk base is &4b740.


7.1.5.1 CDMgr_Version (&4b740)  [MANDATORY]
---------------------

On entry:
   R0  =  flags

On exit:
   R0  =  Version number * 100 (eg. 300 for 3.00)
   R1  -> Version string, terminated by NUL

This string is the same as the module help string (PRM p.1-212).

7.1.5.2 CDMgr_GetSupported (&4b741)  [MANDATORY]
--------------------------

On entry:
   R0  =  flags
   R1  =  logical drive number

On exit:
   R0  =  supported bits word:

The word is divided into bits indicating support for a particular function or
set of related functions:-

   bit  0  =  core set of audio operations

      If this bit is set then the CDMgr_AudioOp reason codes PlayTracks,
      PlayFromAddress, Stop, Pause, Resume and AudioStatus are all supported.

   bit  1  =  audio volume

      If this bit is set then the CDMgr_DriveOp reason codes SetVolume and
      GetVolume are supported.

   bit  2  =  audio scan

      If this bit is set then the CDMgr_AudioOp reason codes AudioScanForward
      and AudioScanReverse are supported.

   bit  3  =  Orange Book (multisession) supported

      If this bit is set then the drive and driver support access to
      information stored using the Orange Book standard for multisession and
      hybrid discs (including Photo CDs).

   bit  4  =  motorised drawer

      If this bit is set then the CDMgr_DriveOp reason codes OpenDrawer and
      CloseDrawer are supported.

   bit  5  =  audio data can be read

      If this bit is set then the drive supports the reading of digital audio
      data stored as per Red Book.

   bit  6  =  Mode 2 Form 2 supported

      If this bit is set then the drive supports the reading of Mode 2 Form 2
      data.

   bit  7  =  continuous transfer supported

      If this bit is set then the driver supports the reading of data
      continuously for applications requiring a continuous but less reliable
      stream of data.

   bit  8  =  drive supports raw data reads (see CDMgr_ReadData)

      If this bit is set then the drive is able to return all 2352 bytes
      from any type of sector: for details, see CDMgr_ReadData, reason code
      ReadRawData.

   bit  9  =  drive supports drawer locking mechanism

      If this bit is set then the CDMgr_DriveOp reason codes GetLockedStatus,
      LockDrive and UnlockDrive are supported.

   bit 10  =  drive supports seeking

      If this bit is set then the CDMgr_MiscOp reason code Seek is supported.

   bit 11  =  drive supports sub-channel reads during audio play or scan

      If this bit is set then the CDMgr_MiscOp reason code Address is
      supported.

   bit 12  =  separate left and right audio volume controls are available

      If this bit is set then the CDMgr_DriveOp reason code SetVolume with
      flag bit 31 set (stereo option) is supported.

This SWI can only return the error:

   +10  Drive number not known


7.1.5.3 CDMgr_ReadTOC (&4b742)  [MANDATORY]
---------------------

On entry:
   R0  =  flags:

            bit    Meaning if set

             31  -  return information for each (real) track
             30  -  return information for each session

   R1  =  logical drive number
   R2  =  sequence number
   R3  =  buffer address, or 0 to determine size of buffer required
   R4  =  track (0 for all tracks or the track number required)
   R5  =  session (0 for all sessions or the session required)

On exit:
   If R3 = 0 on entry, R3 = size of buffer required; otherwise:

   R3  =  address of TOC header
   R4  =  address of track information (or 0 if flag bit 31 is clear)
   R5  =  address of session information (or 0 if flag bit 30 is clear)

This call should be made once with R3 = 0 and once again with R3 addressing
a correctly sized buffer.

This returns a variety of different items of information about the disc
stored in the disc's table of contents. It is recommended that any
application needing this data read all that it needs once and then stores the
information in some suitable internal format for future reference. However,
by specifying a required track and/or session, data can be selectively
returned for that track and/or session only.

This SWI can return the following errors:

   +0   Disc may have changed
   +1   Drive empty
   +2   Drive becoming ready
   +3   Drive not responding as expected
   +10  Drive number not known

The TOC header contains the following information:

        1 WORD                      Disc size
        1 WORD                      Disc type
        2 WORDS                     Track range information
        2 WORDS                     Session range information

If flag bit 31 is set, two words of track information are returned for each
track specified by R4, and for the track following: this means that it is
possible to determine the start point and end point of all of the tracks.

If flag bit 30 is set, one word of session information is returned for each
session specified by R5.

This means that the size of buffer required is:

    size in bytes = 24 +                           -  for the TOC header
                    (8 * (no. of tracks + 1)) +    -  for track information
                    (4 * no. of sessions)          -  for session information

Details of the information returned is as follows:

Disc size
---------

This is the number of physical sectors on the disc (ie one greater than the
maximum permitted physical sector address).

There is no way to determine the data size in bytes without scanning the
entire CD-ROM.

Disc Type
---------

This has the value &00 for CD-DA or CD-ROM with first track in Mode 1,
various other values indicate other formats.

Track Range
-----------

The track range describes the first and last tracks on the disc. Track
numbers are continuous throughout the range, but may start at any valid
number.

   +0   WORD   First track number (1-99)
   +4   WORD   Last track number (1-99)

Session Range
-------------

The session range describes the first and last sessions on the disc; for
discs which are not multi-session, these values are always returned as 1.

   +0   WORD   First session number
   +4   WORD   Last session number

Track Information
-----------------

The track information describes the start location and audio mode of each
track on the disc. The TOC also includes a special entry which contains the
address of the start of the last lead-out area on the disc (the first
physical sector after the last track), thus providing information about the
location of the end of the last track.

   +0   WORD   Physical sector address of track start
   +4   WORD   Audio mode

Note that this information is sufficient to determine whether a track is an
audio track or a data track.


Session Information
-------------------

The session information lists the first track on each session.

   +0   WORD   First track number


7.1.5.4 CDMgr_DriveOp (&4b743)  [MANDATORY, but some reason codes OPTIONAL]
---------------------

On entry:
   R0  =  reason code and flags
   R1  =  logical drive number

These are operations on the physical drive(s) and therefore do not need
sequence numbers.


GetSequenceNumber [MANDATORY]
-----------------

On entry:
   R0  =  0 (reason code) and flags
   R1  =  logical drive number

On exit:
   R0  =  current sequence number

This returns the current sequence number for the medium in the drive. See
section '7.1.3 Media Changes'.

This call can return the following errors:

   +1   Drive empty
   +2   Drive becoming ready
   +3   Drive not responding as expected
   +10  Drive number not known


GetPhysicalLocation [MANDATORY]
-------------------

On entry:
   R0  =  1 (reason code) and flags
   R1  =  logical drive number
   R2  -> buffer, or 0 to determine size of buffer required

On exit:
   If R2 = 0 on entry, R2 = size of buffer required; otherwise:

   R2  -> major address string of form 'Slot n', 'Motherboard' etc
   R3  -> interface type string of form 'SCSI' or 'IDE' etc.
   R4  -> minor address string eg. 'Device m LUN n', 'Master' etc
   R5  -> drive type id string eg. 'Acme CD-0123'
   R6  -> firmware version string eg. '3.21'

This call should be made once with R2 = 0 and once again with a correctly
sized buffer. The information is copied to the buffer, and the registers
R2 to R6 set to address the individual strings within it.

All strings are NUL terminated; note, however, that NULL values are never
returned in registers R2 to R6, although the referenced strings may be
empty.

This call can return the following error:

   +10  Drive number not known


DriveStatus [MANDATORY]
-----------

On entry:
   R0  =  2 (reason code) and flags
   R1  =  logical drive number

On exit:
   R0  =  status

Returns status of the drive as follows:

    0   =   Good (drive operable and ready, medium present)
    1   =   Drive empty (Medium not present)
    2   =   In process of becoming ready
    3   =   Not ready (cause not reportable)

This call can return the following error:

   +10  Drive number not known


GetDriveSpeed [MANDATORY]
-------------

On entry:
   R0  =  3 (reason code) and flags:
                   bit 31
                      0  -  return values as percentages of maximum speed
                      1  -  return values as raw transfer rates in Kb/sec
   R1  =  logical drive number

On exit:
   R2  =  current speed of drive
   R3  =  minimum speed of drive
   R4  =  maximum speed of drive

If flag bit 31 = 1, the values are returned as raw transfer rates; note that
these rates are calculated on the assumption that each physical sector
contains 2352 bytes of data, and so represent an ideal transfer rate for
audio data rather than a realistic transfer rate for computer data.

Typical values for a quad-speed drive running at half speed would be:

    R2  =  353
    R3  =  176
    R4  =  706

If flag bit 31 = 0, the values are returned as percentages of the maximum
speed. Since the minimum speed of current CD-ROM drives is always 176 Kb/s,
the ratio of R4 to R3 gives the "performance" of the drive. Typical values
for a quad-speed drive running at half speed would be:

    R2  =  50
    R3  =  25
    R4  = 100

This call can return the following errors:

   +2   Drive becoming ready
   +3   Drive not responding as expected
   +10  Drive number not known


SetDriveSpeed [MANDATORY]
-------------

On entry:
   R0  =  4 (reason code) and flags:
                   bit 31
                      0  -  values are percentages of maximum speed
                      1  -  values are raw transfer rates in Kb/sec
   R1  =  logical drive number
   R2  =  speed desired

On exit:
   R2  =  set speed of drive

The speed desired is given either as a percentage of the maximum speed, or as
an absolute raw transfer rate in Kb/s; see GetDriveSpeed for details.

If the speed requested is less than the slowest speed supported, the drive is
set to its lowest speed; so R0 bit 31 = 0, R2 = 0 will always slow down the
drive as much as possible.

Otherwise, if the drive does not support the speed requested, the speed
selected will be the next slowest drive speed available.

Setting R0 bit 31 = 0, R2 = 100 will always set the drive to its maximum
speed.

The value in R2 on exit gives the speed to which the drive has been set, and
is represented in the same way as the input value.

Note that when converting percentages to raw transfer rates, CDManager will
always round up: eg 40% of 706 = 282.4 is rounded up to 283 Kb/s.

This call can return the following errors:

   +2   Drive becoming ready
   +3   Drive not responding as expected
   +10  Drive number not known


GetVolume [OPTIONAL (1)]
---------

On entry:
   R0  =  5 (reason code) and flags
   R1  =  logical drive number

On exit:
   R2  =  volume left
   R3  =  volume right

This returns the volume as a 16-bit integer; &FFFF represents the maximum
volume, and &0000 represents mute.

This call can return the following errors:

   +2   Drive becoming ready
   +3   Drive not responding as expected
   +4   Operation not supported by driver
   +10  Drive number not known


SetVolume [OPTIONAL (1)]
---------

On entry:
   R0  =  6 (reason code) and flags:
                  bit 31:
                     0 - mono
                     1 - stereo  [OPTIONAL (12)]
   R1  =  logical drive number
   R2  =  volume left (or mono only)
   R3  =  volume right

Only the least significant 16 bits of registers R2 and R3 are examined, with
&FFFF representing maximum volume and &0000 representing mute.

This call can return the following errors:

   +2   Drive becoming ready
   +3   Drive not responding as expected
   +4   Operation not supported by driver
   +10  Drive number not known


OpenDrawer [OPTIONAL (4)]
----------

On entry:
   R0  =  7 (reason code) and flags
   R1  =  logical drive number

This opens the CD-ROM drive drawer or ejects the caddy. If the drive is open
this call does nothing. If the drive is locked then this generates an error.

This call can return the following errors:

   +2   Drive becoming ready
   +3   Drive not responding as expected
   +4   Operation not supported by driver
   +7   Drawer locked
   +10  Drive number not known


CloseDrawer [OPTIONAL (4)]
-----------

On entry:
   R0  =  8 (reason code) and flags
   R1  =  logical drive number

This closes the CD-ROM drive drawer. If the drive is closed this call does
nothing.

This call can return the following errors:

   +2   Drive becoming ready
   +3   Drive not responding as expected
   +4   Operation not supported by driver
   +10  Drive number not known


GetLockedStatus [OPTIONAL (9)]
---------------

On entry:
   R0  =  9 (reason code) and flags
   R1  =  logical drive number

On exit:
   R0  =  1 for drive locked, 0 for unlocked

Careful use of the locked status calls is recommended as other applications
may be using these simultaneously. If the drawer is open, this call will
fault.

This call can return the following errors:

   +1   Drive empty
   +2   Drive becoming ready
   +3   Drive not responding as expected
   +4   Operation not supported by driver
   +10  Drive number not known


LockDrive [OPTIONAL (9)]
---------

On entry:
   R0  =  10 (reason code) and flags
   R1  =  logical drive number

This call prevents the drawer from being opened until an UnlockDrive call is
made.

Careful use of the locked status calls is recommended as other applications
may be using these simultaneously.

This call can return the following errors:

   +2   Drive becoming ready
   +3   Drive not responding as expected
   +4   Operation not supported by driver
   +10  Drive number not known


UnlockDrive [OPTIONAL (9)]
-----------

On entry:
   R0  =  11 (reason code) and flags
   R1  =  logical drive number

No matter how many times the drive is locked it will take only one unlock
call to unlock it.

Careful use of the locked status calls is recommended as other applications
may be using these simultaneously.

This call can return the following errors:

   +2   Drive becoming ready
   +3   Drive not responding as expected
   +4   Operation not supported by driver
   +10  Drive number not known


EnumerateDrives [MANDATORY]
---------------

On entry:
   R0  =  12 (reason code) and flags

On exit:
   R0  =  maximum valid logical drive number, or -1 if none is valid

This call causes CDManager to issue Service_CDNewDrivePoll, R0 = 0, to
request each driver to examine its interface and register any new* drives
that have appeared. After this has completed, the maximum valid logical drive
number is returned as result (note that this value is one less than the
maximum number of drives of which CDManager has been aware, since the first
drive has number zero).

 * If at the time of this call CDManager knows of no drives at all, the
   service call is made with R0 = 1 to force each driver to (re)register
   all of its drives. This ensures that all drives are (re)registered after
   CDManager has been (re)initialised.

This call should not return errors.


BusyTimeOut [MANDATORY]
-----------

On entry:
   R0  =  13 (reason code) and flags
   R1  =  logical drive number

On exit:
   R0  =  timeout (in centiseconds)

This call returns a suitable timeout value for the drive. This is a value
slightly greater than the maximum length of time which the drive is likely to
remain busy (ie inaccessible) during normal operation.


7.1.5.5 CDMgr_ReadData (&4b744)  [MANDATORY, but some options OPTIONAL]
----------------------

On entry:
   R0  =  reason code and flags:
             bit 31:
                0 - transfer will be reliable
                1 - transfer will be in continuous mode (if supported)
   R1  =  logical drive number
   R2  =  sequence number
   R3  =  buffer address in memory
   R4  =  physical sector address
   R5  =  number of physical sectors to transfer
   R6  depends on reason code

On exit:
   R0  depends on reason code

These calls read different data in slightly different ways. There are some
common points, however.

These calls can return the following errors:

   +0   Disc may have changed
   +1   Drive empty
   +2   Drive becoming ready
   +3   Drive not responding as expected
   +4   Operation not supported by driver
   +5   Sector address too large
   +10  Drive number not known


Reliable vs Continuous Transfer
-------------------------------

Reliable transfer is MANDATORY whilst continuous is OPTIONAL (7).

A reliable transfer is one that will retry if the first read of a sector
returns faulty data. If the correct data cannot be read then an error will be
returned.

A continous data transfer will return the data at the first attempt without
retries. The application must be able to tolerate inaccuracies should any
result (eg. due to a dirty or scratched disc).


ReadUserData  [MANDATORY, but some options OPTIONAL]
------------

On entry:
   R0  =  0 (reason code) and flags:
             bit 31:
                0 - transfer will be reliable
                1 - transfer will be in continuous mode (if supported)
   R1  =  logical drive number
   R2  =  sequence number
   R3  =  buffer address
   R4  =  physical sector address
   R5  =  number of physical sectors to transfer
   R6  =  expected sector data type

On exit:
   R0  =  number of bytes transferred

This reads the user data area of one or more physical sectors:

/------.----------.--------------.-----------------------------------------\
| Type | Def'n    | User Data    | Notes                                   |
|======+==========+==============+=========================================+
|   0  | Any Type | Maximum 2352 | Return data without checking type -     |
|      |          |              | terminates on CD-DA / CD-ROM boundaries |
+------+----------+--------------+-----------------------------------------+
|   1  | CD-DA    | 2352         | Return audio data                       |
+------+----------+--------------+-----------------------------------------+
|   2  | Mode 1   | 2048         | Return Yellow Book Mode 1               |
+------+----------+--------------+-----------------------------------------+
|   3  | Mode 2   | 2336         | Return Yellow Book Mode 2               |
+------+----------+--------------+-----------------------------------------+
|   4  | Mode 2   | 2048         | Return Green Book Mode 2 Form 1         |
|      | Form 1   |              |                                         |
+------+----------+--------------+-----------------------------------------+
|   5  | Mode 2   | 2328*        | Return Green Book Mode 2 Form 2         |
|      | Form 2   |              |                                         |
+------+----------+--------------+-----------------------------------------+
|&10000| Mode 1   |              | Return computer data block from Mode 1  |
|      |   or     | 2048         | or Mode 2 Form 1 sector                 |
|      | Mode 2   |              |                                         |
|      | Form 1   |              |                                         |
+------+----------+--------------+-----------------------------------------+
| else |          |              | Reserved                                |
\------'----------'--------------'-----------------------------------------/

   * This consists of 2324 bytes of user data followed by 4 "spare" bytes.

Sector type 1 is OPTIONAL (5), and sector type 5 is OPTIONAL (6).

A buffer will be needed that is the size of

   (no. of sectors transferred * maximum size of sector).

Notes:

The intention is that types 0 to 5 are implemented by the ATAPI READ CD
command (with the same expected sector type), and that type &10000 is
implemented by the ATAPI READ command.

At the time of writing, there seems to be no consensus amongst ATAPI drive
manufacturers as to the precise interpretation of all of these options, with
type 0 being particularly variable.

It is not the intention of this specification to place unnecessary burdens on
driver writers, and with this in mind the following points should be noted:

  Type 0 reads should not be relied upon: some drives may reject audio
  sectors (even when capable of reading them), and others may always return
  2352 bytes.

  Types 1 to 5 will work as specified provided that the sectors to be read
  are, indeed, of the correct type. However, you should not rely on an error
  being generated if sectors of another kind are encountered. (For example,
  some drives will accept Mode 2 Form 1 sectors for type = 2 or 5 reads).

  The behaviour of type &10000 is guaranteed.


ReadRawData  [OPTIONAL (8)]
-----------

On entry:
   R0  =  1 (reason code) and flags:
             bit 31:
                0 - transfer will be reliable
                1 - transfer will be in continuous mode (if supported)
   R1  =  logical drive number
   R2  =  sequence number
   R3  =  buffer address
   R4  =  physical sector address
   R5  =  number of physical sectors to transfer

Reading CD-DA (audio) sectors is OPTIONAL (5), and reading sectors containing
Mode 2 Form 2 data is OPTIONAL (6).

The buffer size should be:

   (number of physical sectors to transfer * 2352).

If the sector is an audio sector it will be read as data (provided that the
drive supports this operation).

In the case of a data sector, all fields including synch, header(s), EDC and
ECC data are returned if this operation is supported.


7.1.5.6 CDMgr_AudioOp (&4b745)  [OPTIONAL (0,1,2)]
---------------------

On entry:
   R0  =  reason code and flags
   R1  =  logical drive number
   R2  =  sequence number
   R3 ... depend on reason code

This SWI deals with audio operations on a CD (but see also GetVolume and
SetVolume reason codes for CDMgr_DriveOp).

The entire SWI is OPTIONAL, but if any audio operations are implemented at
least the following group of reason codes must be supported:

  Core goup (0):
    PlayTracks
    PlayFromAddress
    Stop
    Pause
    Resume
    AudioStatus

Additionally, support for either or both of the following groups of reason
codes may be provided:

  Volume group (1) (in CDMgr_DriveOp):         Scan group (2):
    SetVolume                                    AudioScanForward
    GetVolume                                    AudioScanReverse

The following possible error returns are common to all calls:

   +0   Disc may have changed
   +1   Drive empty
   +2   Drive becoming ready
   +3   Drive not responding as expected
   +4   Operation not supported by driver
   +10  Drive number not known

Additional possible error returns are noted under the individual reason
codes.
  

PlayFromAddress [OPTIONAL (0)]
---------------

On entry:
   R0  =  0 (reason code) and flags
   R1  =  logical drive number
   R2  =  sequence number
   R3  =  starting physical sector address or -1 for current head position
   R4  =  finishing physical sector address

This plays from one address to another. The current head position address
is particularly useful for ending audio scan commands cleanly.

This call can also return the following errors:

   +5   Sector address too large
   +6   Sector mode incompatible with requested operation


PlayTracks [OPTIONAL (0)]
----------

On entry:
   R0  =  1 (reason code) and flags
   R1  =  logical drive number
   R2  =  sequence number
   R3  =  starting track, or -1 to start from first audio track
   R4  =  finishing track, or -1 to play to end of disc

This plays from the starting to the finishing track (inclusive).

If the starting track does not exist or is a data track (or -1 is specified
and the disc contains no audio tracks), then error +11 is returned.

If the finishing track does not exist, or is less than the starting track,
the drive is instructed to play to the end of the disc.

No check is made to see that all tracks specified are audio; the drive will
stop playing as soon as it meets a data track.

This call can also return the following error:

   +11  Track number out of range or is data track


Stop [OPTIONAL (0)]
----

On entry:
   R0  =  2 (reason code) and flags
   R1  =  logical drive number
   R2  =  sequence number

This stops the disc in the drive spinning if an audio operation is in
progress. This is the correct method of terminating an audio scan command.

This call can also return the following error:

   +8   No audio operation in progress


Pause [OPTIONAL (0)]
-----

On entry:
   R0  =  3 (reason code) and flags
   R1  =  logical drive number
   R2  =  sequence number

This pauses the CD-ROM drive, if it was playing or scanning. That is, the
head goes into the 'hold' state in its current position until either the
resume call is made or the hold state time-out limit is reached.

If the disc was already paused this has no effect.

This call can also return the following error:

   +8   No audio operation in progress


Resume [OPTIONAL (0)]
------

On entry:
   R0  =  4 (reason code) and flags
   R1  =  logical drive number
   R2  =  sequence number

This causes the drive to start playing audio from the current head
position during a pause or a scan.

If the disc was already playing this has no effect.

Note: resume always causes the drive to enter play mode, even after a paused
audio scan.

This call can also return the following error:

   +8   No audio operation in progress


AudioScanForward [OPTIONAL (2)]
----------------

On entry:
   R0  =  5 (reason code) and flags
   R1  =  logical drive number
   R2  =  sequence number
   R3  =  starting physical sector address

This scans from the given start address, forwards through the disc until a
play, pause, resume or stop call interrupts or until it reaches the end of
the disc or a data track.

This call can also return the following errors:

   +5   Sector address too large
   +6   Sector mode incompatible with requested operation


AudioScanReverse [OPTIONAL (2)]
----------------

On entry:
   R0  =  6 (reason code) and flags
   R1  =  logical drive number
   R2  =  sequence number
   R3  =  start physical sector address

This scans backwards through the disc until a play, pause, resume or stop
call interrupts or until it reaches the beginning of the disc or a data
track.

This call can also return the following errors:

   +5   Sector address too large
   +6   Sector mode incompatible with requested operation


AudioStatus [OPTIONAL (0)]
-----------

On entry:
   R0  =  7 (reason code) and flags
   R1  =  logical drive number
   R2  =  sequence number

On exit:
   R0  =  audio status:
              0  -  no audio operation in progress
              1  -  audio play or scan in progress
              2  -  audio paused

This returns the current audio status of the drive.


7.1.5.7 CDMgr_ConvertBlockToMSF (&4b746)  [MANDATORY]
-------------------------------

On entry:
   R0  =  flags:
            bit 31:
               0 - return MSF value in three separate registers
               1 - return MSF value in TimeCode packed format
   R1  =  physical sector address

On exit:
   If flag bit 31 = 0:
     R0  =  frames
     R1  =  seconds
     R2  =  minutes

   If flag bit 31 = 1:
     R0  =  MSF in TimeCode packed format

This converts an absolute physical sector address into the corresponding
minutes, seconds and frames address.

There is a one-to-one correspondence and so this is calculated thus:

  frames  = (address plus 150) modulus 75
  seconds = (address plus 150) divided by 75 modulus 60
  minutes = (address plus 150) divided by 4500

For the TimeCode packed format, the following further calculations are made:

  hours = minutes divided by 60
  minutes = minutes modulus 60

and the result is returned in a single word formatted as follows:

    bits

   31 - 26    hours
   25 - 20    minutes
   19 - 14    seconds
   13 -  3    frames
    2 -  0    the binary value '010'

This call can return the following error:

   +12  Value out of range


7.1.5.8 CDMgr_ConvertMSFToBlock (&4b747)  [MANDATORY]
-------------------------------

On entry:
   R0  =  flags:
            bit 31:
               0 - MSF components are supplied in registers R1, R2 and R3
               1 - MSF value is supplied in R1 in TimeCode packed format

   If flag bit 31 = 0:
     R1  =  frames  (must be in the range 0 to 74 inclusive)
     R2  =  seconds (must be in the range 0 to 59 inclusive)
     R3  =  minutes (must be in the range 0 to 99 inclusive)

   If flag bit 31 = 1:
     R1  =  MSF in TimeCode packed format

On exit:
   R0  =  physical sector address

This converts a minutes, seconds and frames address into the corresponding
absolute physical sector address.

There is a one-to-one correspondence and so this is calculated thus:

  address = (minutes * 60 + seconds) * 75 + frames - 150

If flag bit 31 is set, the TimeCode packed format value is examined, and, if
bit 2 is set, an error is returned. Otherwise, the hours, minutes, seconds
and frames components are extracted (see format above) and the minutes value
replaced by (hours * 60) + minutes; each value is then range checked before
converting as above.

This call can return the following errors:

   +12  Value out of range
   +13  Extended TimeCode representation is not supported


7.1.5.9 CDMgr_MiscOp (&4b748)  [MANDATORY, but some reason codes optional]
--------------------

These are miscellaneous operations, combined into one SWI for convenience.

The following possible error returns are common to all calls:

   +0   Disc may have changed
   +1   Drive empty
   +2   Drive becoming ready
   +3   Drive not responding as expected
   +10  Drive number not known

and calls marked OPTIONAL may also return this error:

   +4   Operation not supported by driver

Additional possible error returns are noted under the individual reason
codes.


WhichDisc [MANDATORY]
---------

On entry:
   R0  =  0 (reason code) and flags
   R1  =  logical drive number
   R2  =  sequence number

On exit:
   R0  =  disc number

This call returns a number which is _likely_ to be unique for each disc in
use.


GiveSectorDataMode [MANDATORY]
------------------

On entry:
   R0  =  1 (reason code) and flags
   R1  =  logical drive
   R2  =  sequence number
   R3  =  physical sector address

On exit:
   R0  =  data mode

This call returns the data mode at the given address. Encoding for data
modes is explained above in 7.1.2 and the modes themselves are explained in
section 8.

This call can also return the following errors:

   +5   Sector address too large
   +6   Sector mode incompatible with requested operation


Seek [OPTIONAL (10)]
----

On entry:
   R0  =  2 (reason code) and flags
   R1  =  logical drive number
   R2  =  sequence number
   R3  =  physical sector address

This seeks to the given address and leaves the head in a hold state over that
position. The amount of time for which the head stays in that state is drive
dependent.

This call can also return the following error:

   +5   Sector address too large


Address [OPTIONAL (11)]
-------

On entry:
   R0  =  3 (reason code) and flags
   R1  =  logical drive number
   R2  =  sequence number

On exit:
   R0  =  audio mode (documented in 7.1.1)
   R3  =  absolute physical sector address
   R4  =  relative physical sector address
   R5  =  track number
   R6  =  index number 

When an audio operation is in progress this information relates to the last
sector played. For data reads this information describes either the last
processed sector or the sector at the current head position.


7.1.5.10 CDMgr_CallDeviceDriver (&4b749)  [MANDATORY]
-------------------------------

Recommended registers on entry (nb usage of R1 is obligatory):
   R0  =  reason code and flags:
              reason code:
                    0  -  no data transfer
                    1  -  read (transfer from device to host)
                    2  -  reserved
                    3  -  write (transfer from host to device)
   R1  =  logical drive
   R2  -> data buffer
   R3  =  buffer length
   R4  -> command block
   R5  =  command block length

This call allows the user to bypass the CDManager. Registers R0, and from R2
to R9, are passed to the drive. The recommended register allocation is given
above. 

Values may also be returned in registers R0 and R2 to R9 inclusive.

There is no restriction on the number and type of errors returned, but error
translation will take place, should the error occur in the CDManager
error translation range.


7.1.6 Star commands
-------------------

*CDDevices
----------

This lists all the CD drives known to CDManager in an easy to understand
format with fields titled:

Drive  Vendor     Product            Firmware    Location
  0    SONY       CD-ROM CDU76E-S    1.0c        Motherboard  ATAPI  Device 1


*CDUnlock [<logical drive>]
---------------------------

   This unlocks the drive so that the user may access the disc.
   If no drive number is given, all drives are unlocked.


7.1.7 Errors
------------

The following errors can be returned from the CDManager module:

   +0   Disc may have changed
   +1   Drive empty
   +2   Drive becoming ready
   +3   Drive not responding as expected
   +4   Operation not supported by driver
   +5   Sector address too large
   +6   Sector mode incompatible with requested operation
   +7   Drawer locked
   +8   No audio operation in progress
   +9*
   +10  Drive number not known
   +11  Track number out of range or is data track
   +12  Value out of range
   +13  Extended TimeCode representation is not supported
   +14  Driver not compatible with this version of CDManager

      * +9 (Buffer for TOC is too small) is never returned by CDManager,
          but may be returned to CDManager from a driver.

All these errors are marked as program errors by OR'ing &1b into the top byte
of the error number (see p5a-493 in PRM3).

The error base is &80e200.


7.1.8 Initialisation and Finalisation
-------------------------------------

No special action needs to be taken when CDManager initialises or finalises.


7.1.9 New drives
----------------

With certain kinds of hardware interface, it is possible to switch drives on
and off at will in a live system. CDManager (and hence its clients) will only
become aware of a newly-available drive if the CDMgr_DriveOp EnumerateDrives
SWI is called, and so clients should be prepared to do this if they receive
the error +10 (Drive not known) in response to a CDMgr call.

This is not normally necessary under the desktop since CDFSFiler makes
regular EnumerateDrives calls in order to maintain the correct number of
drive icons on the icon bar. It is also not necessary when access is via
CDFS, since CDFS will request drive enumeration whenever it encounters an
unknown logical drive number.


7.2 The Driver Control Interface
--------------------------------

7.2.1 Initialisation and Finalisation
-------------------------------------

No special action is necessary upon initialisation; instead, the driver can
wait for the Service_CDNewDrivePoll call, at which time it should register
all of its available drives by calling CDMgr_Registration with reason code
Register.

When a driver finalises it *MUST* call CDMgr_Registration with reason code
Deregister for each of its previously registered drives. Failure to do so
may cause the machine to hang if CDManager attempts to call the driver and
instead jumps into the middle of a now random piece of RMA.


7.2.2 Service Calls
-------------------

Service_CDNewDrivePoll  (&b3)
----------------------

   R0  =  reason code and flags:
                reason code:
                      0 - to register any new drives since the previous call
                      1 - to (re)register all known drives
   R1  =  Service_CDNewDrivePoll (service call reason code)

This call is issued by CDManager whenever CDMgr_DriveOp, reason code
EnumerateDrives, is called.

Each driver responds by registering all of its drives (R0 = 1), or just those
that have not been registered previously (R0 = 0); the service call must not
be claimed.

The driver should respond rapidly to this service call, and a strategy should
be adopted that is appropriate to the characteristics and capabilities of the
hardware interface. Some possibilities are:

  If the interface can be interrogated rapidly, then the driver may choose to
  do this at every call in the foreground.

  If interrogation takes some time, the driver may choose to initiate an
  interrogation in the background from time to time - perhaps triggered by
  the arrival of the service call. This means that new drives will not appear
  immediately, but only after a short while.

  If it is unlikely (or impossible) for new drives to become available on the
  interface after initialisation, a single interrogation can be made - either
  during module initialisation, or at the first service call. The results can
  then be cached and used to respond to each subsequent service call.

Note that when CDFSFiler is running, calls to EnumerateDrives are made on a
regular basis, thus ensuring that both the desktop and CDManager maintain an
up-to-date list of the drives currently available.

CDFS itself also calls EnumerateDrives when a request to access an unknown
logical drive is received.


7.2.3 SWIs
----------

CDMgr_Registration (&4b74a)  [MANDATORY]
------------------

On entry:
   R0  =  reason code and flags:
                reason code:
                      0 - to register
                      1 - to deregister
             other bits reserved (should be 0)
   R1  -> driver information block

On exit:
   If R0 = 0 on entry (ie after registration):
     R0  =  version number * 100

   all other registers preserved

This is called by a driver to register a drive in response to the service
call Service_CDNewDrivePoll; drives should not normally be registered under
other circumstances.

A registered drive should not normally be deregistered simply because it has
become unavailable. This is because the logical drive number associated with
a deregistered drive will be reused by CDManager for any new drive that is
registered, thus creating a potentially confusing situation for the user -
particularly if the deregistered drive was only temporarily inaccessible, and
reappears with a different logical drive number after a short time.

However it is imperative that drives are deregistered before the driver
module dies; if not, CDManager will jump to memory with unknown content if
one of its clients refers to the drive in the future.

The format of the driver information block whose contents must remain valid 
and unchanged until the driver deregisters is as follows:

   +0   WORD  =  Entry point
   +4   WORD  =  Driver internal handle
   +8   WORD  =  Flags word:
                    bit 0: 0 - register as a 'C driver'
                           1 - register as an 'Assembler driver'
                    other bits reserved (should be 0)
   +12  WORD  =  Driver special word (see 7.2.4)
   +16  WORD  =  Manager version no. understood * 100
   +20  WORD  =  Supported bits word
   +24  WORD  =  Timeout (in centiseconds)
   +28  WORD  ->  major address string*
   +32  WORD  ->  interface type string*
   +36  WORD  ->  minor address string*
   +40  WORD  ->  drive type id string*
   +44  WORD  ->  firmware version string*

       * These strings are NUL terminated; see SWI DriveOp, reason code
          GetPhysicalLocation for details.

The 'Supported bits word' describes what features the drive supports; see
CDMgr_GetSupported for details.

The 'Timeout' is a value slightly greater than the maximum length of time
which the drive is likely to remain inaccessible during normal operation (eg
when loading the TOC from a freshly inserted disc).


The purpose of the exchange of version numbers between the driver and
CDManager is to allow flexibility for the driver in determining whether it is
able to function correctly with the version of CDManager present at the time
of registration.

Suppose that the driver is designed to operate with any version of CDManager
between vmin and vmax; such a driver might include conditional code to
support new CDManager features which is to be invoked only when the version
number is high enough, and so the driver needs to know to which version of
CDManager it is talking. Registration proceeds as follows:

    The driver registers with 'Manager version no. understood' set equal
    to vmax.

    Suppose CDManager's version is vcurr. If vcurr > vmax, CDManager will
    return an error if it is no longer able to operate in a manner that is
    backwards compatible with version vmax. Otherwise, CDManager registers
    the drive and returns the value vcurr.

    When control returns to the driver, it checks to see that vcurr >= vmin.
    If not, the driver should deregister immediately.

During normal operation, CDManager can alter its behaviour according to the
value of the 'Manager version no. understood' field in the driver information
block, and the driver can modify its behaviour according to the value vcurr
returned from CDMgr_Registration.


Two drives are deemed to be the same if they have the same address for their
driver information blocks, and it is not an error to attempt to register the
same drive twice: the second attempt is simply ignored, leaving the drive
registered just once with CDManager. Similarly, it is not an error to request
deregistration of a drive that is not registered.


This call can return the following error:

   +14  Driver not compatible with this version of CDManager


7.2.4 Entering Drivers
----------------------

The way in which a driver is called from CDManager depends on whether the
driver has registered as a 'C driver' or an 'Assembler driver'. CDManager
includes 'veneer code' which ensures that the appropriate environment is
set up for the call; in either case, the driver is entered in SVC mode.

7.2.4.1 C driver
----------------

The driver information block can be described in C as follows:

typedef _kernel_oserror *(*DriverHandler) (int, int, void *);

typedef struct {
   DriverHandler function;            /* pointer to the C entry function */
   int           driveid;             /* internal drive identification */
   unsigned      flags;               /* Zero for C */
   int         **pw;                  /* The module's private word address */
   int           version_understood;  /* eg 314 for version 3.14 */
   unsigned      supported;
   int           timeout;
   char         *major_address;
   char         *interface_type;
   char         *minor_address;
   char         *drive_type_id;
   char         *firmware_version;
} DriverInformationRec, *DriverInformationPtr;

If the driver registers with function = entry_func and driveid = id, then the
module must contain a function defined as follows:

    _kernel_oserror * entry_func (       /* returns NULL or error pointer */
        int driveid,                     /* internal identifier for drive */
        int opcode,                      /* operation code */
        void *params                     /* address of parameter block */
    );

CDManager will call this function with driveid = id whenever it needs
information about the registered drive; the other parameters (opcode and
params) are described below.

7.2.4.2 Assembler driver
------------------------

The first four words of the driver information block for an Assembler driver
are as follows:

     +0   entrypoint            - entry point address
     +4   driveid               - internal drive identification
     +8   flags                 - 1 for an Assembler driver
     +12  r12                   - value to be put into R12 when the entry
                                  point is called

If the driver registers with entrypoint = Entry_Point, driveid = id and
r12 = wksp, then the module must contain a routine at Entry_Point which meets
the following interface specification:

  On entry:
    R0  =  driveid                       /* internal identifier for drive */
    R1  =  opcode                        /* operation code */
    R2  =  params                        /* address of parameter block */
    R12 =  r12
    R14 =  return address

  On exit:
    R0  =  0                        - if no error
           address of error block   - if error

    Registers R4 to R11 must be preserved across the call.

CDManager will branch-and-link to Entry_Point with R0 = id and R12 = wksp
whenever it needs information about the registered drive; the other register
values (opcode and params) are described below.

7.2.4.3 Entry point parameters
------------------------------

The 'opcode' parameter identifies the reason for the call to the driver; in
many cases there is a direct correspondence between a CDMgr SWI (or one of
its reason codes) and a driver operation.

Other data is passed between CDManager and the driver through a parameter
block, whose address is provided in 'params' when the driver is called. The
format of the parameter block is determined by the opcode.

In the following descriptions, data are given as byte offsets from the start
of the parameter block.


7.2.5 Driver entry points
-------------------------

All driver operation codes can return the following errors:

   +0   Disc may have changed
   +1   Drive empty
   +2   Drive becoming ready
   +3   Drive not responding as expected

and unsupported OPTIONAL operation codes return the error:

   +4   Operation not supported by driver

Other errors recognised by CDManager which may be returned by individual
operation codes are included in the details listed below.
  

7.2.5.1 ReadTOC  (Operation Code 0)  [MANDATORY]
---------------

On entry:
   +0   WORD   buffer for data
   +4   WORD   maximum length of data

This copies the table of contents of the CD to the supplied buffer in the
following format:

   +0   2BYTE   Data length of TOC
   +2   BYTE    First session number
   +3   BYTE    Last session number
   +4   TOC Track descriptor:

      +0   BYTE   Session number
      +1   BYTE   Most significant nybble:  ADR        (see below)
                  Least significant nybble: Audio mode (see 7.1.1)
      +2   BYTE   TNO = 0 (Track No., lead-in track is number zero)
      +3   BYTE   Point** (track no. or additional information identifier)
      +4   BYTE   Min*
      +5   BYTE   Sec*
      +6   BYTE   Frame*
      +7   BYTE   Zero (for Red & Yellow book true and pseudo track entries)
      +8   BYTE   PMin*
      +9   BYTE   PSec*
      +10  BYTE   PFrame*

** Point is encoded in BCD if it represents a track number.

If the buffer is too small, an error is returned after copying as much data
as possible; since the size of the TOC is returned at the start of the
buffer, CDManager can ensure that a large enough buffer is supplied in
another call.

In the following description, (RSVD) indicates a field whose value is not
defined by this specification; however, the driver should copy across the
corresponding value from the TOC.

This specification only defines the contents of track descriptors with
ADR = 1; however, if others are present in the TOC the driver should supply
them to allow for future enhancements.

There is a track descriptor for each genuine track on the CD as follows:

  Session number   -  to which the track belongs
  ADR = 1
  Audio mode       -  determines whether track contains audio or data
  TNO = 0
  Point            -  track number in BCD
  Min   (RSVD)
  Sec   (RSVD)
  Frame (RSVD)
  Zero = 0
  PMin           ) -  these give the start address of the track in MSF
  Psec           )    format; each field is, itself, in binary.
  PFrame         )

Additional error:

   +9   Buffer for TOC is too small


7.2.5.2 ReadCD  (Operation Code 1)  [MANDATORY - but audio reads and raw data
--------------                                   reads are optional.]

On entry:
   +0   WORD   Flags:
                 bit(s)
                  2-4  expected sector type:
                           0   any
                           1   audio (CD-DA)    [OPTIONAL (5)]
                           2   Mode 1
                           3   Mode 2
                           4   Mode 2 Form 1
                           5   Mode 2 Form 2    [OPTIONAL (6)]  
                  31   0 => return user data only
                       1 => return complete physical sector (2352 bytes)
   +4   WORD   Starting physical sector address
   +8   WORD   Transfer length in physical sectors
   +12  WORD   Buffer for data

On exit:
   +0   WORD   Number of bytes transferred

The requested sectors are read into the supplied buffer, but an error is
returned as soon as a sector is encountered that is not of the expected type.

If flag bit 0 = 0, only the user data is transferred; the table below shows
how long this is for the different sector types.

If flag bit 0 = 1, all 2352 bytes of each physical sector are read into
the buffer; this is OPTIONAL (8). The format of the sector depends on its
type as follows:

   1  CD-DA           audio data, as specified in section 8.1
   2  Mode 1          Sync, Header, User data (2048), EDC, Blanks, ECC
   3  Mode 2          Sync, Header, User data (2336)
   4  Mode 2 Form 1   Sync, Header, Subheader, User data (2048), EDC, ECC
   5  Mode 2 Form 2   Sync, Header, Subheader, User data (2328)

where the components are:

               /---------------------.--------------------\
               |  Component          |  Length in bytes   |
               |---------------------+--------------------|
               |  Sync               |        12          |
               |  Header             |         4          |
               |  SubHeader          |         8          |
               |  User data          |     variable       |
               |  EDC                |         4          |
               |  ECC                |       276          |
               \---------------------'--------------------/

Sync:

   +0            &00
   +1 to +10     &FF
   +11           &00

Header:

   +0   BYTE    minutes
   +1   BYTE    seconds
   +2   BYTE    frames
   +3   BYTE    mode (00 = blanks, 01 = Mode 1, 02 = Mode 2)

  The minutes, seconds and frames are given in BCD in the program area and
  lead-out areas.

SubHeader:

  The SubHeader field includes information about the Form of the sector, and
  the format of the user data inside it; it occupies 8 bytes.


ATAPI drives current at the time of writing do not all conform in the same
way to the specification, but every driver is expected to respond correctly
to the following combinations of parameters (if the driver supports the
operation at all):

  Flag bit 0 = 1, type = 0 (ie any):
    The entire contents of each physical sector is returned regardless of its
    type.

  Flag bit 0 = 0, type > 0 (ie other than any):
    If the physical sector encountered is of the requested type, the user
    data as described above is transferred.

The response to other combinations of parameters may vary from drive to
drive.

Note that data reads take precedence over audio play, and so any play
operation in progress must be interrupted if necessary.

Additional errors:

   +5   Sector address too large
   +6   Sector mode incompatible with requested operation


7.2.5.3 Read2048  (Operation Code 2)  [MANDATORY]
----------------

On entry:

   +0   WORD   Flags (reserved - all zero)
   +4   WORD   Starting physical sector address
   +8   WORD   Transfer length in physical sectors
   +12  WORD   Buffer for data

On exit:

   +0   WORD   Number of bytes transferred

The requested sectors - which must all be Mode 1 or Mode 2 Form 1 sectors -
are read into the supplied buffer. Note that data reads take precedence over
audio play, and so any play operation in progress must be interrupted if
necessary.

Additional errors:

   +5   Sector address too large
   +6   Sector mode incompatible with requested operation


7.2.5.4 GiveSectorDataMode  (Operation Code 3)  [MANDATORY]
--------------------------

On entry:

   +0   WORD   Physical sector address to read
   +4   WORD   Buffer for data (8 bytes are required)
   

This returns sector header information in the supplied buffer in the form:

   +0   WORD   Data mode

This operation can not be used on audio tracks.

Additional errors:

   +5   Sector address too large
   +6   Sector mode incompatible with requested operation


7.2.5.5 Address  (Operation Code 4)  [OPTIONAL (11)]
---------------

This returns sub-channel Q information for the current physical sector.

On exit:

   +0   BYTE   reserved (may be non-zero)
   +1   BYTE   [lower 4 bits] audio mode (see 7.1.1)
               [upper 4 bits] reserved (may be non-zero)
   +2   BYTE   track number (1-99)
   +3   BYTE   index number (1-99)
   +4   WORD   physical sector address
   +8   WORD   relative physical sector address (from beginning of track)


7.2.5.6 ReadDiscSize  (Operation Code 5)  [MANDATORY]
--------------------

This returns the number of physical sectors on the disc.

On exit:

   +0   WORD   Disc size in sectors


7.2.5.7 DriveStatus  (Operation Code 6)  [MANDATORY]
-------------------

This call is used to determine whether the drive is ready, and whether the
disc within it has changed since the drive was last accessed. It returns no
data; instead, the drive state is deduced from any error returned.


7.2.5.8 GetDriveSpeed  (Operation Code 7)  [MANDATORY]
---------------------

On exit:

   +0   WORD   current speed of drive
   +4   WORD   minimum speed of drive
   +8   WORD   maximum speed of drive

The values are returned as raw data transfer rates in Kb/sec; for example, a
quad-speed drive running at half speed might return:

    +0  353
    +4  176
    +8  706


7.2.5.9 SetDriveSpeed  (Operation Code 8)  [MANDATORY]
---------------------

On entry:

   +0   WORD   speed desired

On exit:

   +0   WORD   set speed of drive

The speed is given as a raw data transfer rate in Kb/sec.

If the speed is less than the minimum speed that the drive supports, the
drive will reset to its minimum speed. Otherwise, the drive sets its speed to
the nearest value less than or equal to that requested; the value chosen is
returned as result.


7.2.5.10 OpenDrawer  (Operation Code 9)  [OPTIONAL (4)]
-------------------

This opens the CD-ROM drive drawer or ejects the caddy. If the drive is open
this call does nothing.

Additional error:

   +7   Drawer locked


7.2.5.11 CloseDrawer  (Operation Code 10)  [OPTIONAL (4)]
--------------------

This closes the CD-ROM drive drawer. If the drive is closed this call does
nothing.


7.2.5.12 GetLockedStatus  (Operation Code 11)  [OPTIONAL (9)]
------------------------

On exit:

   +0   WORD   1 for drive locked, 0 for unlocked


7.2.5.13 LockDrive  (Operation Code 12)  [OPTIONAL (9)]
------------------

This call prevents the drawer from being opened until an UnlockDrive call is
made.


7.2.5.14 UnlockDrive  (Operation Code 13)  [OPTIONAL (9)]
--------------------

No matter how many times the drive is locked it will take only one unlock
call to unlock it.


7.2.5.15 Seek  (Operation Code 14)  [OPTIONAL (10)]
-------------

On entry:

   +0   WORD   physical sector address to seek to

This seeks to the given address and leaves the head in a hold state over that
position.

Additional error:

   +5   Sector address too large


7.2.5.16 GetVolume  (Operation Code 15)  [OPTIONAL (1)]
------------------

On exit:

   +0   WORD   volume left
   +4   WORD   volume right

This returns the volume as a 16-bit integer representing a logarithmic range
with respect to the binary attenuation values. &FFFF represents the maximum
volume, and &0000 represents mute.

If the value read from the drive is an 8-bit quantity then the driver will
copy down the top byte to the bottom byte to maintain a constant, full range.


7.2.5.17 SetVolume  (Operation Code 16)  [OPTIONAL (1)]
------------------

On entry:

   +0   WORD   volume left
   +4   WORD   volume right

If the drive can only accept 8-bit quantities, the driver truncates the value
and uses only the top 8-bits of the 16-bit quantity.

If the drive does not support separate left and right audio volume controls
[OPTIONAL (12)], then both channels are set to 'volume left'.


7.2.5.18 Play  (Operation Code 17)  [OPTIONAL (0)]
-------------

On entry:

   +0   WORD   starting physical sector address or -1 for current position
   +4   WORD   finishing physical sector address

The drive starts playing audio from the first address to the second.

Additional errors:

   +5   Sector address too large
   +6   Sector mode incompatible with requested operation


7.2.5.19 Stop  (Operation Code 18)  [OPTIONAL (0)]
-------------

This stops the disc in the drive spinning if an audio operation is in
progress.

Additional error:

   +8   No audio operation in progress


7.2.5.20 Pause  (Operation Code 19)  [OPTIONAL (0)]
--------------

This pauses the CD-ROM drive, if it was playing or scanning.

Additional error:

   +8   No audio operation in progress


7.2.5.21 Resume  (Operation Code 20)  [OPTIONAL (0)]
---------------

This causes the drive to start playing audio from the current head position
during a pause or a scan.

Additional error:

   +8   No audio operation in progress


7.2.5.22 AudioScanForward  (Operation Code 21)  [OPTIONAL (2)]
-------------------------

On entry:

   +0   WORD   starting physical sector address

This scans from the given start address, forwards through the disc until a
play, pause, resume or stop call interrupts or until it reaches the end of
the disc or a data track.

Additional errors:

   +5   Sector address too large
   +6   Sector mode incompatible with requested operation


7.2.5.23 AudioScanReverse  (Operation Code 22)  [OPTIONAL (2)]
-------------------------

On entry:

   +0   WORD   starting physical sector address

This scans backwards through the disc until a play, pause, resume or stop
call interrupts or until it reaches the beginning of the disc or a data
track.

Additional errors:

   +5   Sector address too large
   +6   Sector mode incompatible with requested operation


7.2.5.24 AudioStatus  (Operation Code 24)  [OPTIONAL (0)]
--------------------

On exit:
   +0  =  audio status:
              0  -  no audio operation in progress
              1  -  audio play or scan in progress
              2  -  audio paused


7.2.5.25 CallDeviceDriver  (Operation Code 25)  [MANDATORY]
-------------------------

This provides a direct through call. The registers R0, and from R2 to R9,
will map to WORD size locations in the parameter block. The block will always
be 9 words long. No interpretation is placed on the data in this block.

On return from the driver the parameter block should be filled in with the
desired return contents of the registers R0, and from R2 to R9.


7.2.6 Error codes returned by drivers
-------------------------------------

The error codes in the range &80e200: +0 to +127 have meanings assigned by
CDManager, and are treated differently to other errors returned from a
driver. The driver need only return a short-lived pointer to a word
containing the error number. The manager will copy that straight into a
register and will later add the relevant message if it needs to return the
error to a client application.

   +0   Disc may have changed
   +1   Drive empty
   +2   Drive becoming ready
   +3   Drive not responding as expected
   +4   Operation not supported by driver
   +5   Sector address too large
   +6   Sector mode incompatible with requested operation
   +7   Drawer locked
   +8   No audio operation in progress
   +9   Buffer for TOC is too small

Errors in the range &80e200: +128 to +255 are freely available for use by
the driver. CDManager assumes such an error is serious, and passes it
straight up to its client: the driver must supply appropriate error text.


7.2.7 Notes on driver writing
-----------------------------

It is the responsibility of driver writers to iron out any deficiencies in
the drive(s) they intend to support. For instance, in the case of Mode 2 or
'read any kind of data' some drives have shortcomings and return the wrong
amount of data. The driver writer must overcome this, or in the very worst
case generate an error signalling an inability to recover the information
requested. Another example concerns data reads which arrive whilst the drive
is playing audio: if the drive does not itself interrupt the audio play, the
driver must issue an appropriate STOP command before reissuing the data read.