ATAPI(IDE) CD

Информация к размышлению

Данный документ никоим образом не является полным описанием стандартного ATAPI-CD. Здесь были собраны только основные данные, необходимые для общего понимания принципов функционирования. Предполагается знание (хотя бы в общих чертах) IDE-интерфейса (стандарт ходил под именем ATA-R4C.*).

Для желающих быстро заполучить исходники для управления CD-ROM могу порекомендовать драйвер VIDE-CDD.SYS. Он проще всего поддается дизассемблированию и содержит достаточно неплохой код. Кроме того, в исходных текстах драйвера CD для Linux содержится много полезной информации, хотя ориентация на "юниксоидный" тип запросов мешает использованию этих текстов для компиляции под MS-DOS.

Соглашения и используемые сокращения.

При указании конкретных адресов подразумевается, что CD является

мастером, адрес контроллера - 170h. Если у Вас используются другие адреса,

вместо 17x необходимо подставить 1Fx, 1E8+x или 168+x.

Тик = 18.2 герца.

Данные  длиной в слово или двойное слово в/из CD идут в формате

co старшим первым байтом ( в отличие от PC, где первый байт - младший).

AP - Atapi пакет, 12 байт передаваемых в CD-Rom. Содержат команду

и основные данные для нее. ВНИМАНИЕ: возможно существуют устройства

c пакетом длиной в 16 байт. Однако, подавляющее большинство

драйверов не анализируют и не поддерживают такой формат.

Для определения размера пакета используется ATA-команда A1h.

AK - Atapi команда

M  - минуты

S  - секунды

F  - номер фрейма (1/75 секунды)

Часто используемые биты региста cостояния (177h):

BSY - бит 80h

DRQ - бит 08h

CHK - бит 01h

I. Определение наличия CD в системе

Для проверки присутствия Atapi-CD устройства необходимо:

1. На нужном шлейфе выбрать требуемое устройство (Master/Slave) в регистре 176h.

2. Проверить отсутствие BSY

3. Если занято - устройства нет.

Далее можно дать команду общего сброса (вывести код 8 в регистр 177h и подождать 1-3 тика), либо попробовать обойтись без этого. Если CD находится в cостоянии нормального ожидания команды, сброс давать не обязательно.

3. В порты 174h и 175h записать нечто, отличающееся от 14EBh.

4. В порт 177h вывести команду ECh и подождать пару тиков.

5. Проверить порт 174h (д.б. = 14h) и порт 175h (д.б. = EBh).

При этом надо учитывать, что в регистрах должна будет установлена ошибка (177h - 51h, 171h - 04h). Это нормально.

Если все условия соблюдены, то можно считать, что на IDE-шлейфе присутствует Atapi устройство. Для уточнения типа устройства можно воспользоваться уже Atapi-командами.

Данный алгоритм может применяться только тогда, когда достоверно известно, что CD до этого не выполнял команд. В противном случае бит BSY может быть установлен. Если необходнимо, проверку регистра состояния можно смягчить, проверяя только наличие самого ATA устройства записью в регистры.

II. Выполнение команд

Для выполнения AK необходимо (работа без прерываний):

1. Выбрать соответствующее устройство (Master/Slave) в порту 176h

2. Дождаться готовности (BSY и DRQ = 0). Драйверы ждут до 10-20 секунд. Если готовности нет - можно попытаться сбросить привод.

3. Установить желательный размер блока в регистрах 174h (мл.)

и 175h (ст. часть) Если команда не возвращает данные, это можно

и не делать. Для DMA-шных обменов в этот момент надо установить

и другие регистры.

4. В 177h записать команду A0h. В ответ на это устройство может установить BSY на время подготовки к приему AP.

5. Дождаться требования данных (DRQ=1 и BSY=0). (обычно ждать не надо - драйв выставляет требование сразу). При этом в регистре 172h два младших бита должны иметь значение 01.

6. В режиме словной пересылки записать в порт 170h 6 слов AP.

7. Дождаться готовности (BSY=0). (В зависимости от типа команды и других обстоятельств, драйв может выполнять команду за время от тысячных долей секунды до десятков секунд (Если, например, плохо читается сектор диска).

8. Проверить бит DRQ и если он установлен, то считать из регистров

174h и 175h длину передаваемого блока.

9. Если длина =0 или бит DRQh в 177h не установлен - п. 11, иначе произвести обмен данными через порт 170h. При этом два младших бита регистра 172h могут принимать значение 00 (при передаче данных в CD) или 02 (при приеме данных из CD).

10.Если команда не закончила обмен (бит BSY=1), то повторить с п 7.

11.После завершения команды два младших бита регистра 172 обычно принимают значение 03, что означает готовность драйва к выдаче статуса завершения команды. При этом можно проанализировать результат завершения команды (регистры 177h и 171h). При ошибках можно использовать ATAPI-функцию 03h для получения более детальной информации.

III. Типы команд

По режимам обмена команды можно разделить на три группы:

а) Управления

Как правило, все данные находятся в AP. В некоторых командах применяется дополнительно пересылаемый блок данных.

Результат можно определить по регистрам ошибок (171h и 177h) или с помощью дополнительной команды получения состояния.

б) Передачи данных

Адресные данные и параметры передачи находятся в AP

Поскольку пишущие CD не рассматриваются (мне они не известны), то блок данных, передаваемых в CD, отсутствует.

Если в команде подразумевается передача данных из CD и

нет ошибок, CD драйв выдает в ответ на команду блок (блоки) данных.

в) Получения информации

Все данные о запросе находятся в AP. В ответ на команду СD выдает блок данных.

IV. ATA команды

У CD есть несколько вспомогательных команд, которые исполняются так же, как и команды обычного IDE-винчестера. При этом назначение регистров совпадает с назначением по ATA.

Вот основные команды:

A0h - Команда передачи AP.

A1h - Идентификация привода. Аналог команды ECh для IDE-винчестера, но формат выходного блока другой (описан в приложении C).

ECh - Воспринимается как ошибка, но в регистрах 174h и 175h устанавливается сигнатура 14EBh - признак Atapi устройства.

08h - Програмный сброс. Выполняет процедуру начальной инициализации.

Также, могут выполняться некоторые команды управления сохранением энергии, установки возможностей и пр. Во многих приводах они воспринимаются как правильные команды, но реально не исполняются или исполняются частично.

V. Команды в ATAPI-пакетах

Первый байт в AP является кодом команды. Это единственный байт, который анализируется всегда. Остальные 11 байт содержат информацию, зависящую от конкретной команды.

---------------------------------------------------------------------- Команда 00h - пустышка, проверяет готовность

Пакет:

db  0

db  11*dup(0)   ; *

Ничего не делает, может применяться для проверки смены диска

ПРИМЕЧАНИЯ:

1) Первая команда после смены диска будет отвергнута с кодом ошибки "смена носителя".

2) Здесь и далее: данные помеченые "*", как правило, не анализируются

CD, но для совместимости должны быть установлены в 0.

Команда

Пакет:

01h - Установить головку на начало диска

db 01h

db 12*dup(0)    ; *

Команда управляющая (практически не используется).

-------

Команда

Пакет:

--------------------------------------------------------------

03h - читать состояние привода

db 03h

db 3*dup(0)     ; *

db Len          ; длина выходного блока

db 7*dup(0)     ; *

На выходе таблица из 12h байт, в которой самыми интересными являются байты 2, 0С и 0D - это три байта кода ошибки последней операции.

-------

Команда

Пакет:

------------------------------------------------------------------

012h - читать строку параметров изготовителя драйва

db 12h

db 0h,0h        ; иногда здесь устанавливаются некие параметры

db 0h           ; *

db Len          ; длина выходной строки

db 7*dup(0)     ; *

Драйв выдает некую строку изготовителя (в формате изготовителя)

Зависит от типа CD-Rom. Иногда применяется в драйверах для проверки соответствия драйвера и устройства.

Структура выходного блока:

0       db      1Fh     - тип устройства (CD = 5)

E0h     - для CD =0

1       db      7Fh     - = 0 (для совм. со SCSI-1)

80h     - поддерживаются сменные носители

2       db      0       - версии ISO, ECMA и ANSI.

3       db      0       - для совместимости со SCSI-2

4       db      ?       - длина оставшегося блока

5       db   2 dup(?)   - резервные

7       db      0       - для совместимости со SCSI-2

8 db 8 dup(?) - строка изготовителя (там бывает 'ATAPI') 10h db 10h dup(?) - название продукции

20h     db 4   dup(?)   - ревизия

Текстовые поля образуют одну строку, разделенную пробелами.

-------

Команда

Пакет:

-------------------------------------------------------------------

01Bh - управление треем и прочее

db 1Bh

db 3*dup(0)     ; *

db Func         ; подфункция

db 7*dup(0)     ; *

Команда управляющая.

Подфункции:

0 - войти в режим Sleep

1 - остановить проигрывание/чтение

2 - выдвинуть трей

3 - закрыть трей

-------

Команда

Пакет:

-------------------------------------------------------------------

01Eh - блокировка трея

db 1Eh

db 3*dup(?)     ; *

db Func         ; подфункция

db 7*dup(?)     ; *

Команда управляющая.

Младший бит Func= 0 - разблокировать трей

= 1 - заблокировать трей

-------

Команда

Пакет:

-------------------------------------------------------------------

025h - получить размер вставленного диска в секторах.

db 25h

db 11*dup(0)    ; *

Команда информационная.

Пользователю в ответ передается блок из 8 байт:

dd Sectors      ; число секторов на текущем диске

dd SectSize     ; размер сектора (как правило, не зависит

; от диска и равен 930h)

Команда

Пакет:

02Bh - Seek

db 2Bh

db 2*dup(0)     ; *

db M,S,F        ; куда позиционироваться

db 6*dup(0)     ; *

Команда управляющая.

Команда

Пакет:

042h - смешанная информация (чтение субканала)

db      42h

db      ScMsf   ; 0/2 - тип выдачи адресов (номер сектора или MSF)

db      FullInfo; вариант запроса (полный/краткий - бит 40h)

db      Func    ; подфункция (только для полного запроса)

db      3*dup(0); *

dw      Length  ; Длина таблицы

db      3*dup(0); *

Команда информационная, выдает блок следующей информации:

00h dw   состояние проигрывания аудио:

00h - неизвестно или не поддерживается

11h - Играет аудио

12h - Аудио стоит

13h - Аудио остановилось на конце

14h - Открыта дверь или ошибка запуска

15h - Прочее

02h dw  длина последующих данных (0 - нет)

04h и далее  присутствует при наличии бита 40h в FullInfo и

зависят от Func

Func не равен 2 или 3

04h db  01h       (формат данных субканала = 1)

05h db  Ctrl/Addr

06h db  TrackNumber

07h db  Point or Index

08h db  0

09h db  3*dup(?) - MSF/SECTOR на диске

0Ch db  0

0Dh db  3*dup(?) - MSF/SECTOR на дорожке

--Подфункция 2-- (Получить UPC код)

04h db  02h       (формат данных субканала = 2)

05h db  3h*dup(?)

08h db 80h - флажок наличия UPC (если нет, то UPC отсутствует) 09h db 0Ch*dup(?) - здесь хранится UPC код (6 цифр в BCD коде)

15h db  3*dup(?)   - Положение чего-то на диске в формате MSF

--Подфункция 3-- (получить ISRC код)

04h db  03h       (формат данных субканала = 2)

05h db  Ctrl/Addr

06h db  TrackNumber  - не всегда используется.

07h db  ?

08h db  80h - флажок присутствия (аналогично функции 02h)

09h db  далее запись ISRC

-------

Команда

Пакет:

---------------------------------------------------------------------

043h - информация о дорожках (READ TOC)

db      43h

db      ScMsf   ; 0/2 - тип выдачи адресов (номер сектора или MSF)

db      4*dup(0); *

db      BegTrk  ; начальная дорожка (от 1, 0 заменяется на 1)

dw      Length  ; Длина таблицы

db      Func    ; варианты выдачи информации (0/40h/80h)

db      2*dup(0); *

Команда информационная, выдает таблицу дорожек. Максимальная длина таблицы 8*64h+4 байт или 64h (100.) дорожек.

Func    = 00h   ; получить обычную таблицу дорожек

= 40h   ; получить таблицу сессий

= 80h   ; получить обычную таблицу в расширенном формате

Общий формат таблицы :

dw      Len             ; длина последующих полей в байтах

db      BegTrk          ; первая дорожка

db      EndTrk          ; последняя дорожка

d?      <track_Def>     ; описание дорожек

Описание дорожек м.б. трех форматов:

1) 5 байт на дорожку (внутренний формат, наружу из CD не выдается): db      Ctrl/Addr       ; тип дорожки и флаги

db         Index         ; индекс дорожки (номер)

db*3    Start         ; адрес начала дорожки

2) 8 байт на дорожку (Func=0h/40h): db      ?

db         Ctrl/Addr         ; тип дорожки и флаги

db         TrackNumber         ; номер дорожки

db         ?

db*4    Start         ; адрес начала дорожки

3) 11 байт на дорожку (Func = 80h): db      Res1

db         Ctrl/Addr       ; тип дорожки

db         Res2

db         Index           ; индекс дорожки

db         Res3

db         Res4

db         Res5

db*4         Start           ; адрес начала дорожки

Ctrl/Addr - тип дорожки(то-же, что и в MSCDEX, но переставлены тетрады):

Ctrl (младшая тетрада, отдельные биты):

01 - есть pre-emphasis

02 - разрешено копирование

04 - дорожка данных

08 - 4 канала (а не 2)

Addr (старшая тетрада, коды):

0 - нет субканала

1 - в субканале закодирована позиция

2 - в субканале закодирован UPC

3 - в субканале закодирован ISRC

прочее - зарезервировано

Самые распространенные коды:

14h - ROM

10h - audio

Index - кодируется в BCD и для обычной дорожки находится в интервале

01-99. Коды A0 и выше имеют специальное значение, они не соответстуют физическим дорожкам на диске, а носят служебный характер - информируют о числе дорожек, начале диска, конце диска и т.п.

Start - в зависимости от запроса, может быть либо номером сектора, либо адресом сектора в формате MSF.

Команда

Пакет:

044h

db

db

db

db

db

dw

db

информация

44h

SL ; ;

0       ;

M,S,F ;

0       ;

Len ;

3*dup(0);

о реальных метках положения (Read HEADER)

бит 2 - что записывать в выходной буфер

(исходный номер сектора или считанный)

*

Номер сектора

*

длина выдаваемой информации

*

Команда информационная, выдает следующую таблицу из 8 байт:

db            SectorType            ; тип формата сектора (data mode)

db            4*dup(0)

db            M,S,F            ; адрес сектора

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

Команда

Пакет:

045h - проигрывать audio в терминах блоков (длина - слово)

db 45h

db 0            ; *

dd StartBlock   ; блок начала проигрывания (-1 - с тек. положения)

db ?

dw Length       ; число блоков

db 3*dup(?)     ; *

Команда управляющая.

Команда

Пакет:

047h - проигрывать audio в стиле MSF

db 47h

db 2*dup(?)     ; *

db M,S,F        ; начало отрезка (FF:FF:FF - текущая позиция)

db M,S,F        ; конец отрезка

db 3*dup(?)     ; *

Команда управляющая.

Команда

Пакет :

04Bh - Start/stop audio

db  4Bh

db  7*dup(0)    ; *

db  Func

db  3*dup(0)    ; *

Команда управляющая.

Младший бит Func= 0 - остановить = 1 - запустить

Команда

Пакет:

04Eh - остановить проигрывание

db 4eh

db 11*dup(?)    ; *

Команда управляющая.

Команда

Пакет:

055h - установить  параметры

db      55h

db      ?       ; бит 1 - сохранять в NVRAM (?)

db      Page    ; требуемая страница параметров

db      4 dup (?)

dw      Length  ; длина таблицы

db      3*dup(0); *

Команда управляющая, коды и формат страниц описан в команде 5Ah.

-------

Команда

Пакет:

--------------------------------------------------------------------

05Ah - получить  параметры

db      5Ah

db      ?

db      Page  - определяет требуемые параметры, состоит из двух

битовых полей:

3Fh - номер требуемой страницы параметров:

01h - параметры исправления ошибок

0Dh - общие параметры

0Eh - аудио-управление

2Ah - параметры устройства (только читается)

3Fh - все странички

C0 - биты типа требуемой страницы:

00 - текущие значения

01 - измененные значения

10 - значения по умолчанию

11 - сохраненные значения

db      4 dup (?)

dw      Length  ; длина таблицы

db      3*dup(0); *

Команда информационная, выдает cоответствующую страничку параметров.

Общий заголовок:

00h     dw              Длина всего блока (без первого слова)

02h     db              Состояние привода

03h     db 5 dup(?);

Заголовок каждой страницы:

08h     db      Номер страницы из запроса

09h     db      Длина страницы

Страница 01 - исправление ошибок

0Ah     db      Параметр исправления ошибок

0Bh     db      Счетчик повторов чтения

Страница 0D - общие параметры

0Ah     db      ?

0Bh     db      Множитель таймера неактивности

0Ch     dw      Число S единиц в M единице для формата MSF (60)

0Eh     dw      Число F единиц в S единице для формата MSF (75)

Страница 0E - аудио параметры

0Ah     db      ?       параметр не исп., но изменяется

0Bh     db      2 dup(?)

0Dh     db      ?    =0 LBA всегда равен номеру сектора,

старший бит указывает правильность следующего

поля

0Eh dw 0 Число логических блоков в секунду для проигрывания. (как-правило не используется)

10h     db      мл. тетрада - биты выходного порта канала 0

11h     db      громкость канала 0

12h     db      мл. тетрада - биты выходного порта канала 1

13h     db      громкость канала 1

14h     db      мл. тетрада - биты выходного порта канала 2

15h     db      громкость канала 2

16h     db      мл. тетрада - биты выходного порта канала 3

17h     db      громкость канала 3

Страница 2Ah - параметры устройства (только чтение)

; биты присутствия/отсутствия функций

0Ch     db      01h - проигрывание аудио

02h - композитный аудио/видео поток

04h - Digital out to port 1

08h - Digital out to port 2

10h - чтение секторов Mode 2 Form 1

20h - -----//-------- Mode 2 Form 2

40h - Чтение многосессионных дисков

80h - ?

0Dh     db      01h - Чтение RedBook через команду Read-CD

02h - Чтение RedBook  "with accurate stream"

04h - Чтение субканала

08h - Поддержка деинтерливинга данных субканала

10h - Поддержка "C2 error pointers"

20h - Поддержка чтения ISRC

40h - Поддержка чтения UPC

80h - ?

0Eh             01h - блокировка носителя

02h - чтение статуса блокировки

04h - Disk prevent jumper present

08h - команда выброса носителя

10h - ?

E0h - Тип загрузчика:

0 - Caddy

1 - Tray

2 - Pop-Up

3 - Reserved

4 - Ченджер с индивидуально

меняемыми дисками

5 - Картридж

6 - Reserved

7 - Reserved

0Fh     db      01h - Раздельная регулировка каналов

02h - Раздельный комутатор каналов

04h - Информация о наличии диска

08h -

10h -

20h -

40h -

80h -

10h     dw      Максимальная скорость обмена в килобайтах

13h     db      Число градаций регулировки громкости

14h     dw      Размер буфера в килобайтах

16h     dw      Текущая скорость обмена

;---------иногда может отсутствовать-------------

18h     db      ?

19h     db      01h - Digital out по фронту/спаду сигнала BCKF

02h - LRCK индицирует левый/правый канал

04h - данные в формате LSB/MSB

08h

10h \  BCKs:     0 - 32

20h  |           1 - 16

40h /            2 - 24

3 - 24 (I^2S)

80h - ?

Длина каждой из стрниц может быть разной. Здесь описаны только те поля, которые более-менее стандартны. Если запрашиваются все странички (код 3Fh), то в выходном блоке будет присутствовать один общий заголовок и последовательно расположенные странички со

своими заголовками.

-------

Команда

Пакет:

---------------------------------------------------------------------

0A5h - проигрывать audio в терминах блоков

db A5h

db 0            ; *

dd StartBlock   ; блок начала проигрывания (-1 - с тек. положения)

dd Length       ; число блоков

db 2*dup(?)     ; *

Команда управляющая.

Команда

Пакет:

0B9h - читать данные

db B9h  ;

db Fmt  ; может быть = 00h годится любой формат

;              08h обычный CD-диск (Желтая книга)

;              10h\  разновидности

;              14h/      Green XA

db 0    ; *

db M,S,F; начало чтения

db M,S,F; конец чтения

db Flg  ; флаги читаемого куска сектора:

; 01h   три

; 02h     неиспользуемых (?)

; 04h           бита

; 08h  EDC/Zero/ECC

; 10h  основное тело сектора (data)

; 20h  описатель адреса сектора (head)

; 40h  данные субканала (sub)

; 80h  начальные синхробайты (sync)

; передаются только те  части секторов, для которых

; установлены биты. Передаваемые части сектора должны идти

; подряд, без пропусков.

db 0    ; всегда д.б. =0, иначе ошибка (?)

db 0    ; *

Команда передачи данные.

Если начало=конец, производится позиционирование на указанную позицию и тест читабельности. В этом случае данные не передаются.

-------

------------------------------------------------------------------

Пакет:

db BEh  ;

db Fmt  ;

dd Sec  ; начало чтения (исп. только 24 бита)

db 0    ; *

              dw ScNum; Число секторов

db Flg  ; флаги читаемого куска сектора (как в B9h)

db 0    ; всегда д.б. =0, иначе ошибка (?)

db 0    ; *

Команда полностью аналогична команде B9, за исключением задания адресов области чтения в терминах секторов.

============================================================================== Приложение A

Коды ошибок ATAPI устройства

(взяты из драйвера CD в Linux'е)

Первый байт

00h

01h

02h

03h

04h

05h

06h

07h

08h

09h

0ah

0bh

0ch

0dh

0eh

0fh

No sense data

Recovered error

Not ready

Medium error

Hardware error

Illegal request

Unit attention

Data protect (reserved) (reserved) (reserved)

Aborted command (reserved) (reserved)

Miscompare (reserved)

Второй и третий байты

0000h                No additional sense information

0011h                Audio play operation in progress

0012h                Audio play operation paused

0013h                Audio play operation successfully completed

0014h                Audio play operation stopped due to error

0015h                No current audio status to return

0200h                No seek complete

0400h                Logical unit not ready - cause not reportable

0401h                Logical unit not ready - in progress (sic) of becoming ready

0402h                Logical unit not ready - initializing command required

0403h                Logical unit not ready - manual intervention required

0600h                No reference position found

0900h                Track following error

0901h                Tracking servo failure

0902h                Focus servo failure

0903h                Spindle servo failure

1100h                Unrecovered read error

1106h                CIRC unrecovered error

1500h                Random positioning error

1501h                Mechanical positioning error

1502h                Positioning error detected by read of medium

1700h                Recovered data with no error correction applied

1701h                Recovered data with retries

1702h                Recovered data with positive head offset

1703h                Recovered data with negative head offset

1704h                Recovered data with retries and/or CIRC applied

1705h                Recovered data using previous sector ID

1800h                Recovered data with error correction applied

1801h                Recovered data with error correction and retries applied

1802h                Recovered data - the data was auto-reallocated

1803h                Recovered data with CIRC

1804h                Recovered data with L-EC

1805h                Recovered data - recommend reassignment

1806h                Recovered data - recommend rewrite

1a00h                Parameter list length error

2000h                Invalid command operation code

2100h                Logical block address out of range

2400h                Invalid field in command packet

2600h                Invalid field in parameter list

2601h                Parameter not supported

2602h                Parameter value invalid

2603h                Threshold parameters not supported

2800h                Not ready to ready transition, medium may have changed

2900h                Power on, reset or bus device reset occurred

2a00h                Parameters changed

2a01h                Mode parameters changed

3000h                Incompatible medium installed

3001h                Cannot read medium - unknown format

3002h                Cannot read medium - incompatible format

3700h                Rounded parameter

3900h                Saving parameters not supported

3a00h                Medium not present

3f00h                ATAPI CD-ROM drive operating conditions have changed

3f01h                Microcode has been changed

3f02h                Changed operating definition

3f03h                Inquiry data has changed

4000h                Diagnostic failure on component (ASCQ)

4400h                Internal ATAPI CD-ROM drive failure

4e00h                Overlapped commands attempted

5300h                Media load or eject failed

5302h                Medium removal prevented

5700h                Unable to recover table of contents

5a00h                Operator request or state change input (unspecified)

5a01h                Operator medium removal request

5b00h                Threshold condition met

5c00h                Status change

6300h                End of user area encountered on this track

6400h                Illegal mode for this track

bf00h                Loss of streaming

-------------------------------------------------------------------------

Приложение B

Некоторые форматы секторов

Аудио диск (красная книга):

audio_sample_bytes

2352

Данные (желтая, mode 1):

sync

12

head

4

data

2048

EDC

4

zero

8

ECC

276

Данные (желтая, mode2):

sync

12

head

4

data

2336

XA данные (зеленая,

mode2 form1):

sync

12

head

4

sub

8

data

2048

EDC

4

ECC

276

XA данные (зеленая,

mode2 form2):

sync

12

head

4

sub

8

data

2324

EDC

4

-------------------------------------------------------------------------

Приложение C

Блок, передаваемый по ATA-команде A1

Смещение

00h                    db   битовое поле:

03h - Длина пакета:   00 - 12 байт

01 - 16 байт

прочее - Reserved

1Ch - ?

60h - CMD DRQ Type:   00 - Микропроцессор

01 - Interrupt

02 - Accelerated

03 - Reserved

80h - Съемное

01h                    db                    1Fh - Тип устройства: 05 - CD-ROM

(остальные типы можно посмотреть

в описании SCSI)

;--тут пропуск---

14h                    dw*0Ah                    Серийный номер

28h                    dw*3                    Что-то от производителя

2Eh                    dw*4                    Версия прошивки

36h                    dw*14h                    Название модели

5Eh                    dw                    Что-то от производителя

60h                    dw                    0

62h                    db                    ????? (0)

63h                    db                    01h - поддержка DMA

02h         -         поддержка LBA

04h         -         устройство может запрещать использование IORDY

08h         -         поддержка IORDY

20h         -         поддержка перекрывающихся операций

40h         -         поддержка Proxy Interrupt

80h         -         поддержка Interleave DMA

66h                db                PIO time (ns)

67h                db                PIO mode

69h                    db                    S/W DMA mode

6Ah                    db                    1 - Поля 6Сh-73h используются

2 - Advanced PIO Support (поля 80h-8Dh используются)

; поля 6Ch - 78h взяты из Interrupt List'а. В большинстве CD не используются

6Ch                    dw                    ???                    logical cylinders in current translation mode

6Eh                    dw                    ???                    logical heads in current translation mode

70h                    dw                    ???                    logical sectors per track in current translation mode

72h                    dw*2                    ???                    current capacity in sectors

76h                    dw                    ???                    multiple-sector count for read/write multiple command

78h                    dw*2                    ???                    total number of user-addressable sectors (LBA mode)

;параметры DMA

7Ch     db                    S/W DMA modes: 1 - 0; 2 - 0,1; 4 -0,1,2; Прочее - нет DMA

7Dh     db                    Текущий режим S/W DMA: 1 - 0, 2 - 1, 4 - 2, прочее - не DMA

7Eh     db                    M/W DMA modes (как в S/W DMA)

7Fh     db                    Текущий режим M/W DMA

80h                    db                    Advanced                    PIO modes:                    4 - PIO 5

                    2 - PIO 4

                    1 - PIO 3

82h                    dw                    Минимальное   время передачи в M/W DMA

84h                dw                Рекомендуемое ---//----//---

86h     dw      Минимальное   время передачи в PIO без F/C

88h     dw      -----//------//-------//----//---  с F/C (IORDY)

8Ah     dw*2    зарезервировано для будущих  PIO-режимов

; эти два поля используются для определениея параметров

; перекрывающегося обмена

8Eh                    dw                    типичное время отпускания шины после команды (ms)

90h                    dw                    ----//-----//-----//-----//----//--- обслуживания (ms)

;

92h     dw      Какой-то номер версии

96h     dw*38h  0

100h    dw*20h  Что-то от производителя

140h    dw*60h  0

 

Приложение D Назначение регистров интерфейса

170h

Регистр данных. Через этот регистр CD обменивается с внешним миром данными. Ввод/вывод только словами.

171h

Чтение - регистр ошибок:

01h - Ошибочная длина

02h - Обнаружен конец носителя

04h - Команда отвергнута (бит совпадает по смыслу с ATA)

08h - Обнаружена смена носителя

F0h - Младшие 4 бита первого байта кодов ошибки

Запись - регистр доп. возможностей (опциональный):

01h - включение обмена по DMA

02h - включение перекрывающихся операций

FDh - зарезервировано

172h

173h

Регистр уточнения причины прерывания:

01h - Тип передачи: 0 - передача данных, 1 - передача AP 02h - направление передачи: 0 - в CD, 1 - из CD

04h - индицирует освобождение шины ATA. (как правило = 0)

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

Сочетания битов 1 и 2 имеют следующий смысл:

0 - Ввод блока данных (в CD)

1 - Ввод Atapi-пакета

2 - Вывод блока данных (из CD)

3 - Выдача состояния завершения команды

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

174h

175h

\Регистры длины пересылки. При записи устанавливается

/желательный размер блока пересылки в байтах. При чтении

возвращается объем, подготовленный для передачи из CD или

требуемый для передачи в CD в следующем цикле обмена.

176h

Регистр выбора устройства

0Fh - Зарезервированы (SAM LUN)

10h - Мастер (0)/ Слэйв (1)

20h - 1

40h - Зарезервировано (0)

80h - 1

177h

Регистр команды (запись) / состояния (чтение)

Биты регистра состояния:

01h - Ошибка выполнения команды

02h - Не используется

04h - Обнаружена скорректированная ошибка чтения

(в большинстве устройств постоянно сброшен)

08h - Устройство требует обмена данными

10h - Устройство запросило прерывание для обслуживания (во многих приводах установлен постоянно)

20h - Усторойство готово к DMA-обмену или

индикация ошибок (зависит от режима и зачастую не

используется)

40h - Устройство закончило выполнение команды

(этот бит лучше не использовать)

80h - Устройство занято.

376h

Регистр управления устройством (мне кажется, он есть не на всех устройствах)

По записи:

01h - 0

02h - Запрет прерываний от устройства

04h - Програмный сброс

08h - 1

F0h - зарезервировано

Примечание: При выполнении обычных ATA (не ATAPI) команд назначение регистров совпадает с их назначением по ATA.

-----------------------------------------------------------------------

Приложение E /*****************************************************************/ /* Пример использования ATAPI-CD команд для проигрывания дисков  */ /* без использования драйвера                                                                                */

/* Приложение к документации по ATAPI-CD                                                */

/* Компилятор: BC 3.1, large model                                                                */

/* Это _крайне_ сырая версия. Т.к. большинство приводов расчитаны*/

/* на работу по прерываниям, существуют определенные проблемы при*/

/* работе без них. Информация о проблемах, возникших с различными*/

/* приводами будет очень ценна для создания версии,    */

/* работоспособной на как можно большем количестве устройств.                */

/*****************************************************************/

#include <stdio.h>

#include <stdlib.h>

#include <dos.h>

#include <conio.h>

typedef unsigned char  byte;

typedef unsigned int   word;

typedef unsigned long dword;

/* описатель IDE-устройства */

typedef struct

int port;                /* базовый порт                                                                */

char irq;                /* номер IRQ 1-15, если отсутствует - 0 */

char ms;                /* 1 - мастер, 0 - слэйв                                */

ATAPos;

/* Если используются другие прерывания

              таблицу надо модифицировать              */

static ATAPos Atp[]=

0x1F0,14,1,

0x1F0,14,0,

0x170,15,1,

0x170,15,0,

0x1E0,10,1,

0x1E0,10,0,

0x168,11,1,

0x168,11,0,

0,0,0;

/* то, что последний раз считалось из 1x7 */

static byte Last1X7=0;

/*static ATAPos *GetDescr(int drvnum)return(Atp+drvnum);*/

void StoreLBAToMSF(long lba, void *msf)

 

byte *msfb=msf;

lba+=150;

*msfb++=lba/(60L*75L);

lba%=(60L*75l);

*msfb++=lba/75L;

*msfb++=lba%75L;

 

word  GetMSBWord(word cd)return(

                           (cd >> 8)|

                                                (cd << 8));

dword GetMSBDword(dword cd)return(

                           ((cd >> 24)&0x000000FFL)|

                           ((cd >>  8)&0x0000FF00L)|

                           ((cd <<  8)&0x00FF0000L)|

                                                ((cd << 24)&0xFF000000L));

/* ждать установки бит */

int WtBitMask(int port, int and, int wt, int sec)

 

long counter;

for(counter=sec*1000L;counter>0;counter--)

              int i;

              i=inportb(port);

              if((port&7)==7)              Last1X7=i;

              if((i&and)==wt) return(0);

              delay(1);

 

return(1);

 

/* произвести сброс */

int ResetDrive(int port)

 

int i;

outportb(port+7,8);                 /* программный сброс */

outportb(port+0x206,0xe); /* аппаратный сброс */

delay(10);

outportb(port+0x206,8);

delay(10);

for(i=0;i<200;i++)

              if((inportb(port+7)&0x88)==0)return(0);

              else delay(10);

return(1);

 

/* найти не более <maxdetect> ATAPI-cd и

записать их описатели в таблицу DrvTbl*/

int FindAtapiCD(int maxdetect, int *DrvTbl)

 

int devnum;

int totaldev=0;

for(devnum=0;(Atp[devnum].port!=0)&&(totaldev<=maxdetect);devnum++)

              register int port=Atp[devnum].port;

              int i;

              /* адрес устройства */

              outportb(port+6,Atp[devnum].ms?0xA0:0xB0);

              delay(1);

              if(inportb(port+7)==0xFF)continue;

              if(inportb(port+7)&0x80)

                      /* м.б. оживится ? */

                      if(ResetDrive(port))continue;

             

              outportb(port+4,0);

              outportb(port+5,0);

              outportb(port+7,0xEC);

              for(i=0;i<20;i++)

                      delay(1);

                      if((inportb(port+4)==0x14)&&

        (inportb(port+5)==0xEB))

                           word devcode;

                           /* есть ATAPI-устройство, анализируем подробнее */

                           delay(1);

                           outportb(port+7,0xA1);

                           for(i=0;i<100;i++)

                        if(inport(port+7)&0x80)delay(1);

                        else goto okcont;

                           goto cont;

                           okcont:

                           delay(10);

                           devcode=inport(port);

                           for(i=0;i<255;i++)inport(port);

                           /* это CD ? */

                           if((devcode&0x1F00)!=0x500)break;

                           /* У него 12 бит в AP ? */

                           if(devcode&1)break;

                           *DrvTbl++=devnum;

                           totaldev++;

                           break;

       

             

              cont:;

 

return(totaldev);

 

/* запретить прерывания - дабы умные cd-драйвера не мешались */

int DsbIrq(int devnum)

 

int inum=Atp[devnum].irq;

int oldst;

if(inum==0)return(0);

if(inum>=8)

              oldst=inportb(0xA1);

              outportb(0xA1,oldst|(1<<(inum-8)));

              return(!(oldst&(1<<(inum-8))));

 

oldst=inportb(0x21);

outportb(0x21,oldst|(1<<(inum)));

return(!(oldst&(1<<(inum))));

 

/* разрешить прерывание от cd - при завершении работы */

void EndIrq(int devnum)

 

int inum=Atp[devnum].irq;

if(inum==0)return;

if(inum>=8)

              outportb(0xA1,

                      inportb(0xA1)&(~(1<<(inum-8))));

 

else

              outportb(0x21,

              inportb(0x21)&(~(1<<inum)));

 

 

/* Выполнить ATAPI-команду:

           drive            - устройство

           dir    - 1 - чтение, 0 - запись данных в CDD

           AP            - буфер с ATAPI-пакетом

           buffer - буфер с данными (NULL, если не нужен)

           bufflen- длина выводимых данных или макс. размер вводимых

на выходе:

           -1           - была ошибка

           прочее - размер пересланного блока (в байтах)

*/

static word PrefIOBlock=0x8000;  /* размер блока пересылки в словах */

static byte DontResetFlg=0;                /* не сбрасывать при неготовности */

int ExecATAPICMD(int drive, int dir, word *AP, word *buffer, word bufflen)

 

int port;

int i;

int readed=0;

int size;

              port=Atp[drive].port;

              /* выберем активное устройство */

              outportb(port+6,Atp[drive].ms?0xA0:0xB0);

              rerd:

              Last1X7=inportb(port+7);

              if(Last1X7&0x88) /* не очень готов - попробуем исправить положение */

                      if(DontResetFlg)return(-1);

                      ResetDrive(port);

                      /* ждем завершения команды сброса */

                      if(WtBitMask(port+7,0x80,0x0,10))return(-1);           /* не готов */

                      goto rerd;

             

              /* установим размер блока */

             

           register word pl;

           if(PrefIOBlock>bufflen)pl=bufflen;

           else                               pl=PrefIOBlock;

           outportb(port+4,pl);

           outportb(port+5,pl>>8);

             

              /* запретим всякие хитрые обмены */

              outportb(port+1,0);

              /* все готово к работе  - приступим к передаче пакета */

              outportb(port+7,0xA0);

              /* ждем готовности не более 3х секунд (можно и меньше) */

              if(WtBitMask(port+7,0x89,8,3))return(-1);

              /* выведем пакетик */

              disable();

              for(i=0;i<6;i++) outport(port,*AP++);

              enable();

              /* точка входа цикла приема блоков */

              GetNextBlk:

              /* здесь ждем до 30 секунд */

              WtBitMask(port+7,0x80,0x00,30);

              /* пакет воспринят, а запрос выполнен -

                      получим размер и направление передачи */

              size=inportb(port+4) | (inportb(port+5)<<8);

              Last1X7=inportb(port+7);

              if(Last1X7&1)return(-1);              /* ошибка выполнения команды */

              if(Last1X7&8) /* нужно что-то пересылать */

                      if(inportb(port+2)&2)

                  /*из CD */

                                  if(dir==1 && buffer != NULL )

                                  /* прочтем предлагаемое */

                                                            while(size>0)

                                            int i=inport(port);

                                            size-=2;

                                            if(bufflen<1)break;

                                            *buffer++=i;

                                            readed+=2;

                                            bufflen-=2;

                                                           

                                           

                                  /* пропустим ненужный остаток */

                                  while((size-=2)>0)inport(port);

                          

                      else

                      /* в CD */

                                  if(dir==0 && buffer!=NULL )

                                                            while(bufflen>0 && size > 0)

                                            if(bufflen<1)break;

                                            outport(port,*buffer++);

                                            bufflen-=2;

                                            readed+=2;

                                            size-=2;

                                                           

                                 

                                  /* добросим остаток нулями */

                                  while((size-=2)>0)outport(port,0);

                          

                      goto GetNextBlk;

             

              /* пересылать больше не нужно - команда завершена */

              Last1X7=inportb(port+7);               if(Last1X7&1)

                      /* были ошибки */                       return(-1);

             

return(readed);

 

/***************************************************************/ /* это тестовый проигрыватель CD */ /* для упрощения интерфейса проигрывает только первые 10 треков*/ /***************************************************************/

/* примитивная спрашивалка строки */

char *AskStr(char *quest)

 

static char str[80];

rtt:

printf(quest);

fflush(stdin);

if(fgets(str,79,stdin)==NULL)exit(1);

return(str);

 

typedef struct

word                Params1;

word                scsi1;

byte                len;

word                dummy2;

byte                Scsi2;

char                Manuf[8];

char                Prod[0x16];

char                Rev[4];

Inf12Blk;

typedef struct

word                bkllen;

byte                state;

byte                undef[9];

byte                flags1, flags2, flags3, flags4;

word                maxspeed;

byte                undef2;

byte                audiosteps;

word                bufsize;

word                curspeed;

word                dummy[10];

Cmd5AInfo;

typedef struct

word                st1;

byte                err0;

byte    dummy1[9];

byte                err1;

byte                err2;

byte                dummy2[4];

Inf3Blk;

typedef struct

byte res1;

byte CA;

byte number;

byte res2;

byte Start[4];

OneTrk0;

typedef struct

word Len;

byte BegTrk;

byte EndTrk;

OneTrk0                Trk[11];

TOC10;

Cmd5AInfo Buf5A2A;

Inf12Blk Info12Buf;

Inf3Blk  Info3Buf;

TOC10                TrkBuf;

/* ATAPI-пакеты для разных запросов */

word ClosePkt[6]=0x1B,0,3,0,0,0;

word EjectPkt[6]=0x1B,0,2,0,0,0;

word Info5A2A[6]=0x5A,0xAA,0,0,0x1C,0;

word Info12[6]=0x12,0,sizeof(Inf12Blk),0,0,0;

word LockPkt[6]=0x1E,0,1,0,0,0;

word UnlockPkt[6]=0x1E,0,0,0,0,0;

word Info3[6]=0x3,0,sizeof(Inf3Blk),0,0,0;

word RdToc[6]=0x243,0,0,1,sizeof(TOC10),0;

word PlaySt[6]=0x47,0,0,-1,255,0;

word ReadSc[6]=0xBE,0,0,0,0,0;

word ReadScM[6]=0xB9,0x0,0x0,0x0,0x0,0;

/* Буфер для чтения секторов */

#define MaxSect 16U

byte Buffer[2352U*MaxSect];

void main(void)

 

int devtbl[8];

int workdrv;

int maxdrv;

int i;

maxdrv=FindAtapiCD(8,devtbl);

printf("Detected %d ATAPI CD-ROM drive(s):\n",maxdrv); if(maxdrv<1)return;

 

int i;

for(i=0;i<maxdrv;i++)

              printf("%1.1d: %3.3Xh:%c (irq %d)\n",i+1,

                           Atp[devtbl[i]].port,

                           Atp[devtbl[i]].ms?'M':'S',

                           Atp[devtbl[i]].irq);

 

if(maxdrv>1)

              do

              workdrv=atoi(AskStr("Select work drive>"));               while((workdrv<1)||(workdrv>maxdrv));               workdrv=devtbl[workdrv-1];

 

else                 AskStr("Press Enter to continue....");

              workdrv=devtbl[0];

 

 

/* рабочий диск выбран */

DsbIrq(workdrv);

redrawscr:

clrscr();

gotoxy(1,15);

cprintf(

" 0-9 - Start play at track X                E - Eject disk\n\r"

" R   - Rescan  track list                C - Close tray\n\r"

" I   - Some drive info                M - Manufacturer Info\n\r"

" L   - Lock tray                U - unlock tray\n\r"

" X   - Error type                W - write CD to disk\n\r"

" Z   - Redraw screen\n\r"

" Esc - quit");

gotoxy(1,22);

cprintf(" Select >");

rein:

gotoxy(10,22);

while(kbhit())getch();

i=getch();

gotoxy(1,23);clreol();

switch(i)

/* треки  - запуск на проигрывание */

case '0':

case '1':

case '2':

case '3':

case '4':

case '5':

case '6':

case '7':

case '8':

case '9':i-='0';

              cprintf("Start playing....");

              PlaySt[1]=TrkBuf.Trk[i].Start[1]<<8;

              PlaySt[2]=TrkBuf.Trk[i].Start[2]|(TrkBuf.Trk[i].Start[3]<<0x8);

              PlaySt[3]=TrkBuf.Trk[i+1].Start[1]|(TrkBuf.Trk[i+1].Start[2]<<0x8);

              PlaySt[4]=TrkBuf.Trk[i+1].Start[3]<<8;

              if(ExecATAPICMD(workdrv,0,PlaySt,NULL,0)!=-1)cprintf("Ok");

              else printf("Fail");

              break;

/* выбросить трей */

case 'E':

case 'e':

              cprintf("Eject disk....");

              if(ExecATAPICMD(workdrv,0,EjectPkt,NULL,0)!=-1)cprintf("Ok");

              else printf("Fail");

              break;

/* втянуть диск */

case 'C':

case 'c':

              cprintf("Close tray....");

              if(ExecATAPICMD(workdrv,0,ClosePkt,NULL,0)!=-1)cprintf("Ok");

              else printf("Fail");

              break;

/* смешанная информация (команда 5A/2A) */

case 'I':

case 'i':

              if(ExecATAPICMD(workdrv,1,Info5A2A,(void*)&Buf5A2A,sizeof(Buf5A2A))>0)

              cprintf("MaxSpd: %d, CurSpd: %d, Buff: %d Kb",

                                  GetMSBWord(Buf5A2A.maxspeed),

                                  GetMSBWord(Buf5A2A.curspeed),

                                  GetMSBWord(Buf5A2A.bufsize));

             

              else cprintf("Fail");

              break;

/* информация от производителя */

case 'M':

case 'm':

              if(ExecATAPICMD(workdrv,1,Info12,(void*)&Info12Buf,sizeof(Info12Buf))>0)

              cprintf("Manuf: [%8.8s], Prod: [%16.16s], Rev: [%4.4s]",

                                  Info12Buf.Manuf,

                                  Info12Buf.Prod,

                                  Info12Buf.Rev);

             

              else cprintf("Fail");

              break;

/* блокировка трея */

case 'l':

case 'L':cprintf("Lock tray....");

              if(ExecATAPICMD(workdrv,0,LockPkt,NULL,0)!=-1)cprintf("Ok");

              else printf("Fail");

              break;

/* разблокировка трея */

case 'u':

case 'U':cprintf("Unlock tray....");

              if(ExecATAPICMD(workdrv,0,UnlockPkt,NULL,0)!=-1)cprintf("Ok");

              else printf("Fail");

              break;

/* расширенная информация об ошибках */

case 'X':

case 'x':

              if(ExecATAPICMD(workdrv,1,Info3,(void*)&Info3Buf,sizeof(Info3Buf))>0)

              cprintf("Err0: %3.3Xh, Err1: %3.3Xh, Err2: %3.3Xh",

                                  Info3Buf.err0,

                                  Info3Buf.err1,

                                  Info3Buf.err2);

             

              else cprintf("Fail");

              break;

/* перечитать список дорожек */

case 'R':

case 'r':

              if(ExecATAPICMD(workdrv,1,RdToc,(void*)&TrkBuf,sizeof(TrkBuf))>0)

                      gotoxy(1,1);

                      cprintf("Num   Ctrl/Addr   TrNum    Start");

                          

                  for(i=0;i<10;i++)

        cprintf("\n\r");

        clreol();

        if(i<TrkBuf.EndTrk)

                                  cprintf("%2.2d    %3.3Xh                 %2.2X                 %2.2d:%2.2d:%2.2d",

                                  i,

                                  TrkBuf.Trk[i].CA,

                                  TrkBuf.Trk[i].number,

                                  TrkBuf.Trk[i].Start[1],

                                  TrkBuf.Trk[i].Start[2],

                                  TrkBuf.Trk[i].Start[3]);

                     

                        

                          

             

              else cprintf("Fail");

              break;

/* чтение секторов на диск (от начала и пока не остановят) */

case 'w':

case 'W':FILE *img;

         word len;

         long CurSector=0;

              while(kbhit())getch();

              img=fopen("CDImage.bin","wb");

              if(img==NULL)cprintf("Can't open save file !");

              cprintf("Copying sectors. Press any key to abort [");

              do

                      cprintf("/");

                      StoreLBAToMSF(CurSector,((byte*)ReadScM)+3);

                      StoreLBAToMSF(CurSector+MaxSect,((byte*)ReadScM)+6);

                      ((byte*)ReadScM)[9]=0x10;

                      len=ExecATAPICMD(workdrv,1,ReadScM,(void*)Buffer,sizeof(Buffer));

                      if(len==0xFFFF) cprintf("]CD read fail");goto ecpy;;

                      if(len==0) cprintf("]CD return zero bytes");goto ecpy;

                      cprintf("%u\\",len);

                      if(fwrite(Buffer,len,1,img)!=1)

                                  cprintf("]Error write to disk");

                                  goto ecpy;

                                                     

                      CurSector+=MaxSect;

              while(!kbhit());

              while(kbhit())getch();

              cprintf("]Copy stopped");

              ecpy:

              cprintf("(%ld)",CurSector);

              fclose(img);

              break;

               

case 'z':

case 'Z':goto redrawscr;

/* выход из програмы */

case 0x1b:goto finch;

case 0: goto rein;

 

goto rein;

finch:

clrscr();

 

#########################################################################

PS/ Изначально этот документ составлялся исключительно для внутреннего использования по причине невозможности найти фирменное описание стандарта на ATAPI-CD.

Поскольку вся информация бралась из дизассемблированных драйверов, исходных текстов Linux'а, отдизассемблированной прошивки ACER665, a также из описания SCSI-пакетов и стандарта на ATAPI, то вполне возможны определенные расхождения со стандартом (в существовании которого я не уверен). Несмотря на это, мне кажется, что даже такое описание представляет определенную ценность.

В данное описание не попала команда специального чтения данных (028h/0A8h) - у меня нет четких данных о ее работе, а также несколько других, которые не используются в драйверах и поддерживаются не всеми приводами. Это касается команд потрекового проигрывания Audio-CD, команд смены диска в многодисковых приводах и т.п.

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

Для любитетлей "подробных описаний" могу порекомендовать стандарт

SCSI-2 (X3T9.2).Там есть большое количество интересной информации, но солидный объем (более 20 тыс. строк или около 1.7 Mb), некоторые отличия SCSI от ATAPI и "замусоренность" лишними деталями усложняют получение нужных сведений.

При необходимости более детального ознакомления с процессом обмена (обмен по DMA, перекрывающиеся команды и т.п.) можно прочитать стандарт на ATAPI устройства (X3T10). Однако, описание конкретных CD команд там отсутствует (есть ссылка на SCSI).

Ревизии:

10.08.1996  - собраны и как-то систематизированы отрывочные данные

19.09.1996  - первый раз отдан на растерзание.

20.12.1996  - добавлено кое-что из ATAPI и сказевого описания.

14.02.1997 - уточнены термины, добавлено описание некоторых битов, регистров и команд.

01.03.1997  - еще одно мелкое исправление терминов.

23.03.1997 - подправлено описание битов, добавлена тестовая программа,

убрано "hex-по умолчанию",

убраны ошибочные сведения о бите 10h в 177h и другие

ошибки в алгоритме выполнения команды.

29.03.1997  - В команде 4B на хвосте пакета был один лишний байт.

Предложения, замечания, ругань и т.п.

просьба направлять по адресу 2:5030/163.44

Константин Норватов (Konstantin Norvatoff, KonNor)

Также, можно попробовать найти меня по адресу: konnor@small.spb.su