Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Аппаратное обеспечение персонального компьютера

© Александр Фролов, Григорий Фролов
Том 33, М.: Диалог-МИФИ, 1997, 304 стр.

[Назад] [Содеожание] [Дальше]

Команды драйвера CD-ROM

В этом разделе мы расскажем о командах драйвера CD-ROM. Заметим, что в рамках одной команды может выполняться несколько функций. Код функции при этом записывается в расширение загловка запроса.

Инициализация

Команда инициализации вызывается из MS-DOS только один раз.

Ниже мы привели формат заголовка запроса для этой команды:


// ---------------
// Код команды 0
// ---------------
#pragma pack(1)
typedef struct _Init
{
  ReqHdr rh;              
  BYTE   bNumberOfUnits;
  DWORD  lpEndAddress;
  DWORD  lpAddressOfBPB;
  BYTE   bNumberOfBlockDevice;
} Init;

После выполнения команды поля структуры заполняются драйвером следующим образом:

Поле

Описание

rh.wStatus

Слово состояния

bNumberOfUnits

Количество устройств, обслуживаемых драйвером. Равно 0

lpEndAddress

Конечный адрес резидентной порции драйвера в оперативной памяти

lpAddressOfBPB

Указатель на символ = в строке файла CONFIG.SYS, с помощью которой загружен драйвер CD-ROM. Может быть использован для анализа параметров драйвера

bNumberOfBlockDevice

Равно 0

Чтение IOCTL Input

При помощи команды IOCTL Input программа может получить от драйвера самую разную информацию, начиная от адреса заголовка драйвера и заканчивая информацией о дорожках диска.

Формат заголовка запроса:


// ---------------
// Код команды 3
// ---------------
#pragma pack(1)
typedef struct _IOCTL_Input
{             
  ReqHdr rh;
  BYTE   bMediaDescriptor;
  DWORD  lpTransferAddress;
  WORD   wDataSize;
  WORD   wStartSector;
  DWORD  lpVolID;
} IOCTL_Input;

Заполнение полей заголовка запроса:

Поле

Описание

rh.wStatus

После вызова драйвера содержит слово состояния

bMediaDescriptor

Байт описания среды носителя данных

lpTransferAddress

Адрес буфера

wDataSize

Размер буфера

wStartSector

Номер начального сектора

lpVolID

Указатель на идентификатор тома, если при выполнении команды возникла ошибка с кодом 0Fh

Команда IOCTL Input может выполнять много функций. Перед вызовом драйвера вы должны подготовить заголовок функции, указав в одном из его полей код выполняемой функции. Адрес и размер этой структуры необходимо записать в поля lpTransferAddress и wDataSize, соответственно.

Рассмотрим форматы заголовков различных функций, выполняемых в рамках команды IOCTL Input.

Определение адреса заголовка драйвера CD-ROM


// ---------------
// Код функции 0
// ---------------
#pragma pack(1)
typedef struct _RAddr
{             
  BYTE   bFunctionCode;
  DWORD  lpDeviceHeader;
} RAddr;

Поле

Описание

bFunctionCode

Код функции

lpDeviceHeader

Адрес заголовка драйвера CD-ROM

Зная адрес заголовка драйвера, вы можете определить имя драйвера и его атрибуты. Подробности об атрибутах драйверов вы найдете в 18 томе «Библиотеки системного програмиста».

Определение положения головки


// ---------------
// Код функции 1
// ---------------
#pragma pack(1)
typedef struct _HeadLocation
{             
  BYTE   bFunctionCode;
  BYTE   bAddressMode;
  DWORD  lpHeadLocation;
} HeadLocation;

Поле

Описание

bFunctionCode

Код функции

bAddressMode

Режим адресации:

0 – HSG;

1 – Redbook;

2 – 255 – зарезервировано

lpHeadLocation

Положении головки. Значение зависит от режима адресации

Здесь необходимо сделать замечание относительно режимов адресации.

По умолчанию устройство чтения CD-ROM находится в режиме адресации HSG, описанный в стандарте High Sierra. При этом в качестве адреса указывается логический номер блока.

Другой режим адресации описан в стандарте Redbook. В нем адрес представляет собой набор из трех значений: минуты (MIN), секунды (SEC), фреймы (FRAME). Каждое значение занимает один байт, причем в младшем байте хранится значение FRAME, в следующем байте - значение SEC, и в последнем, третьем байте, - значение MIN.

С помощью следующей формулы вы можете преобразовать адрес из формата Redbook в формат HSG:


SECTOR = MIN * 60 * 75 + SEC * 75 + FRAME - 150

Получение информации о звуковых каналах


// ---------------
// Код функции 4
// ---------------
#pragma pack(1)
typedef struct _ChanInfo
{             
  BYTE   bFunctionCode;
  BYTE   bInpChannel0;
  BYTE   bVolControl0;
  BYTE   bInpChannel1;
  BYTE   bVolControl1;
  BYTE   bInpChannel2;
  BYTE   bVolControl2;
  BYTE   bInpChannel3;
  BYTE   bVolControl3;
} ChanInfo;

Поле

Описание

bFunctionCode

Код функции

bInpChannel0

Номер входного канала, присвоенного выходному каналу 0. По умолчанию равно 0

bVolControl0

Уровень громкости для канала 0. По умолчанию равно 0FFh

bInpChannel1

Номер входного канала, присвоенного выходному каналу 1. По умолчанию равно 1

bVolControl1

Уровень громкости для канала 1. По умолчанию равно 0FFh

bInpChannel2

Номер входного канала, присвоенного выходному каналу 2. По умолчанию равно 2

bVolControl2

Уровень громкости для канала 2. По умолчанию равно 0FFh

bInpChannel3

Номер входного канала, присвоенного выходному каналу 3. По умолчанию равно 3

bVolControl3

Уровень громкости для канала 3. По умолчанию равно 0FFh

Чтение данных из устройства


// ---------------
// Код функции 5
// ---------------
#pragma pack(1)
typedef struct _DriveBytes
{             
  BYTE   bFunctionCode;
  BYTE   bNumBytes;
  BYTE   bReadBuff[128];
} DriveBytes;

Поле

Описание

bFunctionCode

Код функции

bNumBytes

Количество байт, которые необходимо прочитать из устройства

bReadBuff

Буфер для чтения размером 128 байт. После выполнения команды в него записывается информация, которая зависит от типа устройства чтения CD-ROM

Определение состояния устройства


// ---------------
// Код функции 6
// ---------------
#pragma pack(1)
typedef struct _DeviceStatus
{             
  BYTE   bFunctionCode;
  DWORD  dwDeviceParameters;
} DeviceStatus;

Поле

Описание

bFunctionCode

Код функции

dwDeviceParameters

32-разрядное слово состояния устройства

Описания отдельных бит слова состояния приведено ниже:

Бит

Описание

0

1 – устройство открыто, в него можно вставлять диск;

0 – устройство закрыто

1

0 – устройство заблокировано, из него нельзя извлечь диск;

1 – устройство разблокировано

2

0 – устройство может работать только в режиме Cooked Reading;

1 – дополнительно может использоваться режим Raw Reading

3

0 – устройстов может только читать компакт-диски;

1 – устройство может читать и записывать компакт-диски

4

0 – устройство может работать только с дорожками, содержащими данные:

1 – дополнительно устройство может проигрывать звуковые дорожки или дорожки с видео

5

0 – устройство не способно работать с чередованием данных;

1 – устройство работает с чередованием данных в стандарте ISO‑9660

6

Зарезервировано

7

0 – предварительная выборка не применяется;

1 – устройство способно выполнять запросы на предварительную выборку

8

0 – устройство не работает со звуковыми каналами;

1 – устройство может работать со звуковыми каналами

9

0 – устройство может работать в режиме адресации HSG;

1 – дополнительно можно использовать режим адресации Redbook

10

Зарезервировано

11

0 – в устройстве находится компакт-диск;

1 – в устройстве нет компакт-диска

12

0 – устрйство не работает с подканалами R-W;

1 – указанные каналы используются

13-31

Зарезервировано и равно нулю

Немного о режимах Cooked и Raw.

По умолчанию устройство чтения CD-ROM работает в режиме Cooked. Этот режим предполагает аппаратную обработку циклической контрольной суммы. Размер блока данных равен 2048 байт.

В режиме Raw драйвер возвращает 2352 байта данных, в которые входят заголовок блока данных и контрольная сумма.

Определение размера сектора


// ---------------
// Код функции 7
// ---------------
#pragma pack(1)
typedef struct _SectorSize
{             
  BYTE   bFunctionCode;
  BYTE   bReadMode;
  DWORD  dwSectorSize;
} SectorSize;

Поле

Описание

bFunctionCode

Код функции

bReadMode

Режим чтения

dwSectorSize

Размер сектора. Для режима Cooked Reading он равен 2048 байт, для режима Raw Reading – 2352 байт

Определение размера тома


// ---------------
// Код функции 8
// ---------------
#pragma pack(1)
typedef struct _VolumeSize
{             
  BYTE   bFunctionCode;
  DWORD  dwVolumeSize;
} VolumeSize;

Поле

Описание

bFunctionCode

Код функции

dwVolumeSize

Размер тома

Функция возвращает адрес дорожки Lead-out, преобразованное в численное значение по следующей формуле:


frame + (sec * 75) + (min * 60 * 75)

Это значение является адресом первого сектора, который располагается за самым последним адресуемым сектором диска.

Проверка замены носителя данных


// ---------------
// Код функции 9
// ---------------
#pragma pack(1)
typedef struct _MediaChange
{             
  BYTE   bFunctionCode;
  BYTE   bMedia;
} MediaChange;

Поле

Описание

bFunctionCode

Код функции

bMedia

1 – носитель не заменялся;

0 – не известно, выполнялась замена носителя данных, или нет;

0FFh – носитель заменялся

Получение информации о компакт-диске


// ---------------
// Код функции 10
// ---------------
#pragma pack(1)
typedef struct _DiskInfo
{
  BYTE   bFunctionCode;
  BYTE   bLowest;
  BYTE   bHighest;
  DWORD  dwTotal;
} DiskInfo;

Поле

Описание

bFunctionCode

Код функции

bLowest

Номер первой дорожки

bHighest

Номер последней дорожки

dwTotal

Адрес дорожки Lead-out

Получение информации о дорожке компакт-диска


// ---------------
// Код функции 11
// ---------------
#pragma pack(1)
typedef struct _TrackInfo
{
  BYTE   bFunctionCode;
  BYTE   bTrack;
  DWORD  dwLoc;
  BYTE   bInfo;
} TrackInfo;

Поле

Описание

bFunctionCode

Код функции

bTrack

Номер дорожки

dwLoc

Первый сектор дорожки

bInfo

Формат дорожки

Старшая тетрада формата дорожки имеет следующий формат:

Значение

Описание

00*0

Два звуковых канала без предискажений

00*1

Два звуковых канала с предискажениями

10*1

Четыре звуковых канала без предискажений

10*0

Четыре звуковых канала с предискажениями

01*0

Дорожка с данными

01*1

Зарезервировано

11**

Зарезервировано

**0*

Копирование дорожки запрещено

**1*

Копирование дорожки разрешено

Состояние бита, отмеченного символом *, значения не имеет.

Младшая тетрада формата дорожки содержит тип режима ADR, описанного в Redbook.

Получение информации о канале Q


// ---------------
// Код функции 12
// ---------------
#pragma pack(1)
typedef struct _QInfo
{
  BYTE   bFunctionCode;
  BYTE   bCtrlAndARD;
  BYTE   bTrackNumb;
  BYTE   bIndex;
  BYTE   bMin;
  BYTE   bSec;
  BYTE   bFrame;
  BYTE   bRunningTime;
  BYTE   bAminOrPmin;
  BYTE   bAsecOrPsec;
  BYTE   bAframeOrPframe;
} QInfo;

Поле

Описание

bFunctionCode

Код функции

bCtrlAndARD

Формат дорожки

bTrackNumb

Номер дорожки

bIndex

Текущее время, которое прошло с начала проигрывания дорожки

bMin

Компонента MIN адреса дорожки

bSec

Компонента SEC адреса дорожки

bFrame

Компонента FRAME адреса дорожки

bRunningTime

Общее время проигрывания диска

bAminOrPmin

Значение AMIN или PMIN

bAsecOrPsec

Значение ASEC или PSEC

bAframeOrPframe

Значение AFRAME или PFRAME

Получение информации о подканале


// ---------------
// Код функции 13
// ---------------
#pragma pack(1)
typedef struct _QInfo
{
  BYTE   bFunctionCode;
  DWORD  dwStartSector;
  DWORD  dwTransferAddress;
  DWORD  dwNumberOfSectors;
} QInfo;

Поле

Описание

bFunctionCode

Код функции

dwStartSector

Адрес начального сектора

dwTransferAddress

Адрес в оперативной памяти, по которому будет скопирована информация из подканала

dwNumberOfSectors

Количество секторов, которые необходимо скопировать

Получение штрих-кода изготовителя компакт-диска


// ---------------
// Код функции 14
// ---------------
#pragma pack(1)
typedef struct _UPCCode
{
  BYTE   bFunctionCode;
  BYTE   bCtrlAndARD;
  BYTE   bUPCCode[7];
  BYTE   bZero;
  BYTE   bAFrame;
} UPCCode;

Поле

Описание

bFunctionCode

Код функции

bCtrlAndARD

Формат дорожек

bUPCCode

Штрих-код

bZero

Равно 0

bAFrame

Значение AFRAME

Сброс входных буферов

Команда освобождает все входные буферы и отменяет все запущенные команды.

Формат заголовка запроса:


// ---------------
// Код команды 7
// ---------------
#pragma pack(1)
typedef struct _Flush
{             
  ReqHdr rh;
} Flush;

Заполнение полей заголовка запроса:

Поле

Описание

rh.wStatus

После вызова драйвера содержит слово состояния

Запись IOCTL Output

При помощи команды IOCTL Output программа может заставить драйвер выполнять различные операции, такие как управление механизмом извлечения компакт-диска.

Формат заголовка запроса:


// ---------------
// Код команды 12
// ---------------
#pragma pack(1)
typedef struct _IOCTL_Output
{             
  ReqHdr rh;
  BYTE   bMediaDescriptor;
  DWORD  lpTransferAddress;
  WORD   wDataSize;
  WORD   wStartSector;
  DWORD  lpVolID;
} IOCTL_Output;       

Заполнение полей заголовка запроса:

Поле

Описание

rh.wStatus

После вызова драйвера содержит слово состояния

bMediaDescriptor

Байт описания среды носителя данных, должен быть равен нулю

lpTransferAddress

Адрес буфера

wDataSize

Размер буфера

wStartSector

Номер начального сектора, должен быть равен нулю

lpVolID

Указатель на идентификатор тома, если при выполнении команды возникла ошибка с кодом 0Fh

Рассмотрим форматы заголовков различных функций, выполняемых в рамках команды IOCTL Output.

Извлечение компакт-диска


// ---------------
// Код функции 0
// ---------------
#pragma pack(1)
typedef struct _EjectDisk
{
  BYTE   bFunctionCode;
} EjectDisk;

Поле

Описание

bFunctionCode

Код функции

Блокирование и разблокирование компакт-диска в устройстве


// ---------------
// Код функции 1
// ---------------
#pragma pack(1)
typedef struct _LockDisk
{
  BYTE   bFunctionCode;
  BYTE   bLock;
} LockDisk;

Поле

Описание

bFunctionCode

Код функции

bLock

1 – блокирование компакт-диска;

0 – разблокирование компакт-диска

Сброс устройства чтения CD-ROM


// ---------------
// Код функции 2
// ---------------
#pragma pack(1)
typedef struct _ResetDrive
{
  BYTE   bFunctionCode;
} ResetDrive;

Поле

Описание

bFunctionCode

Код функции

Управление звуковыми каналами


// ---------------
// Код функции 3
// ---------------
#pragma pack(1)
typedef struct _ChanControl
{             
  BYTE   bFunctionCode;
  BYTE   bInpChannel0;
  BYTE   bVolControl0;
  BYTE   bInpChannel1;
  BYTE   bVolControl1;
  BYTE   bInpChannel2;
  BYTE   bVolControl2;
  BYTE   bInpChannel3;
  BYTE   bVolControl3;
} ChanControl;

Поле

Описание

bFunctionCode

Код функции

bInpChannel0

Номер входного канала, присвоенного выходному каналу 0

bVolControl0

Уровень громкости для канала 0

bInpChannel1

Номер входного канала, присвоенного выходному каналу 1

bVolControl1

Уровень громкости для канала 1

bInpChannel2

Номер входного канала, присвоенного выходному каналу 2

bVolControl2

Уровень громкости для канала 2

bInpChannel3

Номер входного канала, присвоенного выходному каналу 3

bVolControl3

Уровень громкости для канала 3

Запись в устройство управляющей строки


// ---------------
// Код функции 4
// ---------------
#pragma pack(1)
typedef struct _DriveControlBytes
{             
  BYTE bFunctionCode;
  BYTE bWriteBuff[...]; // размер зависит от устройства
} DriveControlBytes;

Поле

Описание

bFunctionCode

Код функции

bWriteBuff

Буфер с управляющими данными, которые будут записаны в устройство чтения CD-ROM. Формат зависит от типа устройства

Закрывание приемного устройства для компакт-диска


// ---------------
// Код функции 5
// ---------------
#pragma pack(1)
typedef struct _CloseTray
{
  BYTE   bFunctionCode;
} CloseTray;

Поле

Описание

bFunctionCode

Код функции

Открывание устройства

Команда открывает устройство чтения CD-ROM, сообщая драйверу о том, что данное устройство будет использовано еще одной программой.

Формат заголовка запроса:


// ---------------
// Код команды 13
// ---------------
#pragma pack(1)
typedef struct _RsumePlay
{             
  ReqHdr rh;
} RsumePlay;

Заполнение полей заголовка запроса:

Поле

Описание

rh.wStatus

После вызова драйвера содержит слово состояния

Закрывание устройства

Команда закрывает устройство чтения CD-ROM, открытое предыдущей командой.

Формат заголовка запроса:


// ---------------
// Код команды 14
// ---------------
#pragma pack(1)
typedef struct _RsumePlay
{             
  ReqHdr rh;
} RsumePlay;

Заполнение полей заголовка запроса:

Поле

Описание

rh.wStatus

После вызова драйвера содержит слово состояния

Чтение длинное

При помощи команды длинного чтения программа может прочитать полное содержимое сектора компакт-диска, включая служебные области сектора.

Формат заголовка запроса:


// ---------------
// Код команды 128
// ---------------
#pragma pack(1)
typedef struct _ReadLong
{             
  ReqHdr rh;
  BYTE   bAddressMode;
  DWORD  lpTransferAddress;
  WORD   wDataSize;
  WORD   wStartSector;
  BYTE   bDataReadMode;
  BYTE   bInterleaveSise;
  BYTE   bInterleaveSkip;
} ReadLong;       

Заполнение полей заголовка запроса:

Поле

Описание

rh.wStatus

После вызова драйвера содержит слово состояния

bAddressMode

Режим адресации:

0 – режим HSG (по умолчанию);

1 – режим Readbook;

2-255 – зарезервировано

lpTransferAddress

Адрес буфера

wDataSize

Размер буфера

wStartSector

Номер начального сектора, должен быть равен нулю

bDataReadMode

Режим чтения данных:

0 – режим Cooked;

1 – режим Raw;

2-255 – зарезервировано

bInterleaveSize

Количество блоков или секторов, которые записаны последовательно друг за другом

bInterleaveSkip

Фактор пропуска при чередовании: количество последовательно расположенных блоков или секторов, которые разделяют фрагменты файла с чередованием

Чтение длинное с предварительной выборкой

Функция аналогична предыдущей, но сразу после вызова она немедленно возвращает управление. Драйвер выполняет подготовительные действия для операции чтения, такие, например, как позиционирование головки, однако операция чтения не выполняется.

Формат заголовка запроса:


// ---------------
// Код команды 130
// ---------------
#pragma pack(1)
typedef struct _ReadLongPrefetch
{             
  ReqHdr rh;
  BYTE   bAddressMode;
  DWORD  lpTransferAddress;
  WORD   wDataSize;
  WORD   wStartSector;
  BYTE   bDataReadMode;
  BYTE   bInterleaveSise;
  BYTE   bInterleaveSkip;
} ReadLongPrefetch;       

Заполнение полей заголовка запроса такое же, как и для предыдущей функции.

Поиск

Команда выполняет позиционирование головки. Она возвращает управление немедленно, не дожидаясь завершения процесса позиционирования.

Формат заголовка запроса:


// ---------------
// Код команды 131
// ---------------
#pragma pack(1)
typedef struct _Seek
{             
  ReqHdr rh;
  BYTE   bAddressMode;
  DWORD  lpTransferAddress;
  WORD   wDataSize;
  WORD   wStartSector;
} Seek;       

Заполнение полей заголовка запроса:

Поле

Описание

rh.wStatus

После вызова драйвера содержит слово состояния

bAddressMode

Режим адресации:

0 – режим HSG (по умолчанию);

1 – режим Readbook;

2-255 – зарезервировано

lpTransferAddress

Адрес буфера

wDataSize

Размер буфера

wStartSector

Номер начального сектора, должен быть равен нулю

Проигрывание звуковой дорожки

Команда запускает проигрывание звуковой дорожки начиная с указанного сектора.

Формат заголовка запроса:


// ---------------
// Код команды 132
// ---------------
#pragma pack(1)
typedef struct _Play
{             
  ReqHdr rh;
  BYTE   bAddressMode;
  WORD   wStartSector;
  WORD   wNumberOfSectors;
} Play;

Заполнение полей заголовка запроса:

Поле

Описание

rh.wStatus

После вызова драйвера содержит слово состояния

bAddressMode

Режим адресации:

0 – режим HSG (по умолчанию);

1 – режим Readbook;

2-255 – зарезервировано

wStartSector

Номер начального сектора

wNumberOfSectors

Количество секторов, которые нужно проиграть

Остановка проигрывания звуковой дорожки

Команда останавливает проигрывание звуковой дорожки.

Формат заголовка запроса:


// ---------------
// Код команды 133
// ---------------
#pragma pack(1)
typedef struct _StopPlay
{             
  ReqHdr rh;
} StopPlay;

Заполнение полей заголовка запроса:

Поле

Описание

rh.wStatus

После вызова драйвера содержит слово состояния

Возобновление проигрывания звуковой дорожки

Команда останавливает проигрывание звуковой дорожки.

Формат заголовка запроса:


// ---------------
// Код команды 136
// ---------------
#pragma pack(1)
typedef struct _RsumePlay
{             
  ReqHdr rh;
} RsumePlay;

Заполнение полей заголовка запроса:

Поле

Описание

rh.wStatus

После вызова драйвера содержит слово состояния


[Назад] [Содеожание] [Дальше]