Запись дисков CD-R/RW в Linux. Часть 1::Журнал СА 11.2004
www.samag.ru
     
Поиск   
              
 www.samag.ru    Web  0 товаров , сумма 0 руб.
E-mail
Пароль  
 Запомнить меня
Регистрация | Забыли пароль?
Журнал "Системный администратор"
Журнал «БИТ»
Наука и технологии
Подписка
Где купить
Авторам
Рекламодателям
Архив номеров
Контакты
   

  Опросы
  Статьи

Электронный документооборот  

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

Область применения технологий электронной подписи с каждым годом расширяется. Все больше задач

 Читать далее...

Рынок труда  

Системные администраторы по-прежнему востребованы и незаменимы

Системные администраторы, практически, есть везде. Порой их не видно и не слышно,

 Читать далее...

Учебные центры  

Карьерные мечты нужно воплощать! А мы поможем

Школа Bell Integrator открывает свои двери для всех, кто хочет освоить перспективную

 Читать далее...

Гость номера  

Дмитрий Галов: «Нельзя сказать, что люди становятся доверчивее, скорее эволюционирует ландшафт киберугроз»

Использование мобильных устройств растет. А вместе с ними быстро растет количество мобильных

 Читать далее...

Прошу слова  

Твердая рука в бархатной перчатке: принципы soft skills

Лауреат Нобелевской премии, специалист по рынку труда, профессор Лондонской школы экономики Кристофер

 Читать далее...

1001 и 1 книга  
19.03.2018г.
Просмотров: 9896
Комментарии: 0
Потоковая обработка данных

 Читать далее...

19.03.2018г.
Просмотров: 8108
Комментарии: 0
Релевантный поиск с использованием Elasticsearch и Solr

 Читать далее...

19.03.2018г.
Просмотров: 8210
Комментарии: 0
Конкурентное программирование на SCALA

 Читать далее...

19.03.2018г.
Просмотров: 5196
Комментарии: 0
Машинное обучение с использованием библиотеки Н2О

 Читать далее...

12.03.2018г.
Просмотров: 5877
Комментарии: 0
Особенности киберпреступлений в России: инструменты нападения и защита информации

 Читать далее...

Друзья сайта  

 Запись дисков CD-R/RW в Linux. Часть 1

Архив номеров / 2004 / Выпуск №11 (24) / Запись дисков CD-R/RW в Linux. Часть 1

Рубрика: Администрирование /  Оборудование

ВЛАДИМИР МЕШКОВ

Запись дисков CD-R/RW в Linux

Часть 1

В данной статье рассматриваются примеры использования мультимедийных команд стандарта SCSI (SCSI Multimedia Commands–4, MMC-4) для записи на лазерные диски CD-R/RW различной информации – музыкальных треков и данных.

В первой части статьи рассматриваются вопросы организации хранения данных на компакт-диске, порядок использования SCSI Generic-драйвера для доступа к устройству чтения/записи компакт-дисков, определения параметров конфигурации устройства и управления режимами работы устройства

Работоспособность всех примеров программ была проверена для ОС Linux, ядро 2.4.27. Модель привода для чтения и записи компакт-дисков – TEAC CD-W524E Rev 1.0E. Привод подключен как Secondary Master, в ядре включены поддержка SCSI Generic-драйвера и режим SCSI-эмуляции для ATAPI-устройств (SCSI host adapter emulation for IDE ATAPI devices).

Физический формат данных на компакт-диске

Данные, записанные на компакт-диск, представляют собой последовательность малых кадров, small frame.

1 synchronization

pattern

(24 + 3 bits)

1 byte

of Sub-channel data

(14 + 3 bits)

12 bytes

of main

channel data

(12 x (14 + 3) bits)

4 bytes

of CIRC code

(4 x (14 + 3) bits)

12 bytes

of main

channel data

(12 x (14 + 3) bits)

4 bytes

of CIRC code

(4 x (14 + 3) bits)

588 bits

Рисунок 1. Формат малого кадра

Малый кадр содержит:

  • 3 байта кода синхронизации;
  • 1 байт данных субканала;
  • 24 байта данных основного канала (две группы по 12 байт);
  • 8 байт помехоустойчивого корректирующего кода CIRC, Cross Interleaved Read-Solomon Code (две группы по 4 байта).

Общая длина данных малого кадра составляет 36 байт.

При записи на компакт-диск данные субканала, основного канала и CIRC кодируются 14-разрядными EFM-кодом (Eight to Fourteen Modulation). Дополнительно к каждому полю добавляются три связывающих бита. Итоговый размер малого кадра, записанного на компакт-диск, равен 588 бит (рис.1). 98 последовательно расположенных малых кадров образуют кадр (Frame), или сектор, минимально адресуемую единицу данных на компакт-диске. Один кадр содержит 24 x 98 = 2352 байт данных основного канала и 98 байт субканала. Эти 98 байт в свою очередь делятся на 2 байта синхронизации и 96 байт данных. Каждый байт данных субканала размечен на битовые позиции, и, таким образом, субканал делится еще на 8 субканалов.

7

6

5

4

3

2

1

0

P

Q

R

S

T

U

V

W

Рисунок 2. Формат байта данных субканала

В одном кадре для каждого из этих субканалов содержится по 96 бит (12 байт) информации.

Из всех имеющихся в наличии субканалов основную информационную нагрузку несет Q-субканал. В нем содержится адресная информация кадра, информация о логической структуре компакт-диска, идентификационная информация диска или музыкального трека. Рассмотрим формат данных Q-субканала. Q-субканал содержит:

  • 2 бита синхронизации (S0, S1);
  • 4 бита поля управления (Control Field);
  • 4 бита идентификатора режима данных Q-субканала (ADR);
  • 72 бита (9 байт) данных (DATA-Q);
  • 16 контрольной суммы полей управления, режима данных и поля данных (CRC).

Поле Control Field определяет тип информации, которая находится в основном канале кадра. Это поле может принимать следующие значения:

  • 00x0b – 2 аудиоканала без предыскажения;
  • 00x1b – 2 аудиоканала, предыскажения 50/15 мкс;
  • 10x0b – 4 аудиоканала без предыскажений;
  • 10x1b – 4 аудиоканала, предыскажения 50/15 мкс;
  • 01x0b – трек данных, непрерывный режим записи (Disk-at-once, DAO);
  • 01x1b – трек данных, инкрементный режим записи (Track-at-once (TAO), Session-at-once (SAO));
  • 11xxb – зарезервировано.

Поле режима данных Q-субканала ADR определяет формат данных Q-субканала. Подробное описание форматов данных Q-субканала находится в спецификации SCSI MMC-4 ([1]), п. 4.2.4.4 «Q Sub-channel».

Блок данных основного канала предназначен для хранения информации – аудио или данных. У компакт-дисков, используемых для хранения аудио-информации, все 2352 байт блока основного канала заняты аудиоданными. Для хранения данных используется 6 основных форматов блока основного канала. Наиболее широкое применение получили три формата:

  • режим данных 1, Yellow Book Mode 1;
  • форма 1 режима данных 2, CD-ROM XA Mode 2 Form 1;
  • форма 2 режима данных 2, CD-ROM XA Mode 2 Form 2.

Блок основного канала, содержащий данные, начинается с поля синхронизации Data Block Sync Pattern длиной 12 байт (рис. 3). За полем синхронизации находится заголовок блока Header данных длиной 4 байт. Заголовок блока содержит координаты блока данных в формате MSF (Minute/Second/Frame) и байт формата записи данных Data Mode. Значение формата блока содержат биты 0-1 байта Data Mode.

0

1

2

3

4

5

6

7

8

9

10

11

0x00

0xFF

0xFF

0xFF

0xFF

0xFF

0xFF

0xFF

0xFF

0xFF

0xFF

0x00

Рисунок 3. Структура поля синхронизации Data Block Sync Pattern

Формат данных Mode 1 представлен в таблице 1, форматы данных Mode 2 Form 1 и Mode 2 Form 2 – в таблицах 2 и 3.

Таблица 1. Mode 1 data format

Byte Offset

Field Length

Content

0

12

Data Block Sync pattern, поле синхронизации

12

3

Block MSF address (BCD), адрес блока в формате MSF

15

1

Data mode = 01, режим данных

16

2048

User data, данные пользователя

2064

4

CRC (P = (X16+X15+X2+X1)*(X16+X2+X+1)) Bytes 0 - 2063

2068

8

Zero fill

2046

172

P parity symbols

2248

104

Q parity symbols

Таблица 2. Mode 2 Form 1 data format

Byte Offset

Field Length

Content

0

12

Data Block Sync pattern, поле синхронизации

12

3

Block MSF address (BCD), адрес блока в формате MSF

15

1

Data mode = 2, режим данных

16

4

Sub-header, first copy, подзаголовок (первая копия)

20

4

Sub-header, second copy, подзаголовок (вторая копия)

24

2048

User data, данные пользователя

2072

4

CRC (P = (X16+X15+X2+X1)*(X16+X2+X+1)) Bytes 16 - 2071

2076

172

P parity symbols

2248

104

Q parity symbols

Таблица 3. Mode 2 Form 2 data format

Byte Offset

Field Length

Content

0

12

Data Block Sync pattern, поле синхронизации

12

3

Block MSF address (BCD), адрес блока в формате MSF

15

1

Data mode = 2, режим данных

16

4

Sub-header, first copy, подзаголовок (первая копия)

20

4

Sub-header, second copy, подзаголовок (вторая копия)

24

2324

User data, данные пользователя

2348

4

Optional CRC Bytes 16 - 2347

Пространство CD-ROM делится на три области (рис. 4):

  • Lead-In Area, входная область диска.
  • User Data Area, область данных пользователя, или область программ.
  • Lead-Out Area, выходная область диска.

Lead-in Area

User Data Area

Lead-out Area

Рисунок 4. Общая структура CD-ROM

Lead-In-область предназначена для хранения информации об организации данных на компакт-диске. Q-субканал Lead-In-области содержит таблицу содержания диска, Table Of Contents (TOC). В TOC хранится информация о сессиях и стартовых адресах треков. Пример чтения и описания формата Q-субканала Lead-In-области (TOC) приведен в [5].

В User Data Area находятся треки с данными пользователя. Минимальное число треков, которое может быть записано на компакт-диск, равно 1. Максимальное число треков на диске равно 99. Треки нумеруются начиная с единицы.

Совокупность всех трех областей – Lead-In, User Data, Lead-Out – называется сессией. Любой CD-ROM, содержащий информацию, имеет минимум одну сессию. Максимальное число сессий зависит от используемого типа компакт-диска. Нумерация сессий начинается с единицы.

Lead-In

User Data

Lead-Out

 

 

Session 1

Session 2

….

Session X-1

 

 

 

 

 

Lead-In

User Data

Lead-Out

 

 

 

 

 

 

Logical Track

N

Logical Track

N+1

Logical Track

N+K-1

 

 

 

K Logical Tracks

 

Рисунок 5. Общая структура многосессионного компакт-диска

Lead-In-область первой сессии является Lead-In-областью всего диска. Lead-Out-область последней сессии является Lead-Out-областью диска. В User Data-области любой сессии находятся треки с данными.

Диски CD-R и CD-RW содержат две дополнительные области перед первой Lead-In-областью компакт-диска – Power Calibration Area (PCA) и Program Memory Area (PMA).

Рисунок 6. Структура CD-R и CD-RW диска

Рисунок 6. Структура CD-R и CD-RW диска

The Power Calibration Area, PCA – область калибровки мощности пишущего лазера. Область присутствует только на CD-R и CD-RW дисках. В свою очередь, PCA делится на две области – тестовую область (test area) и область счетчика (count area).

Тестовая область содержит 100 калибровочных участков. Область счетчика используется для учета количества использованных калибровочных участков. Для калибровки мощности пишущего лазера используется последовательность команд READ DISK INFORMATION/SEND OPC INFORMATION (см. [1]).

The Program Memory Area, PMA – область памяти программ. Область присутствует только на CD-R и CD-RW дисках и предназначена для учета использования User Data-области носителя. Q-субканал области PMA используется в качестве временной TOC при записи треков в инкрементном режиме – Track-at-once (TAO), Session-at-once (SAO). При записи диска в режиме Disk-at-once (DAO) данные в PMA не записываются.

SCSI Generic-драйвер. Общие сведения

SCSI Generic-драйвер (далее sg-драйвер) входит в состав ядра Linux и позволяет приложению пользователя посылать SCSI-команды устройству при условии, что устройство эти команды понимает. Доступ к sg-драйверу выполняется через специальные файлы устройства, которые находятся в каталоге /dev. Список некоторых файлов можно получить при помощи команды:

# ls -l /dev/sg[01]

crw-------  1 root  root  21, 0 Apr 13 /dev/sg0

crw-------  1 root  root  21, 1 Apr 13 /dev/sg1

Каждый файл соответствует одному подключенному SCSI-устройству.

Обращение к SCSI-устройству через sg-драйвер выполняется при помощи системного вызова ioctl следующим образом:

    ioctl(sg_fd, SG_IO, struct sg_io_hdr *)

Первый параметр sg_fd – это дескриптор файла sg-устройства /dev/sg*, открытого при помощи системного вызова open( ). Третий параметр – структура следующего типа:

typedef struct sg_io_hdr

{

    int interface_id; /*"S" for SCSI generic (required) */

    int dxfer_direction; /* data transfer direction  */

    unsigned char cmd_len; /* SCSI command length ( <= 16 bytes) */

    unsigned char mx_sb_len; /* max length to write to sbp */

    unsigned short iovec_count; /* 0 implies no scatter gather */

    unsigned int dxfer_len; /* byte count of data transfer */

    void * dxferp; /* points to data transfer memory or scatter gather list */

    unsigned char * cmdp; /* points to command to perform */

    unsigned char * sbp; /* points to sense_buffer memory */

    unsigned int timeout; /* MAX_UINT->no timeout (unit: millisec) */

    unsigned int flags; /* 0 -> default, see SG_FLAG... */

    int pack_id; /* unused internally (normally) */

    void * usr_ptr; /* unused internally */

    unsigned char status; /* scsi status */

    unsigned char masked_status; /* shifted, masked scsi status */

    unsigned char msg_status; /* messaging level data (optional) */

    unsigned char sb_len_wr; /* byte count actually written to sbp */

    unsigned short host_status; /* errors from host adapter */

    unsigned short driver_status; /* errors from software driver */

    int resid; /* dxfer_len - actual_transferred */

    unsigned int duration; /* time taken by cmd (unit: millisec) */

    unsigned int info; /* auxiliary information */

} sg_io_hdr_t; /* 64 bytes long (on i386) */

Данная структура определена в файле . Назначение основных полей структуры:

  • interface_id – это поле должно содержать литеру «S»;
  • dxfer_direction – направление передачи данных. Поле может принимать следующие значения (см. ):
  • #define SG_DXFER_NONE (-1) – нет обмена данными;
  • #define SG_DXFER_TO_DEV (-2) – передача данных устройству;
  • #define SG_DXFER_FROM_DEV (-3) – прием данных от устройства.
  • cmdp – указатель на командный пакет, посылаемый устройству;
  • cmd_len – размер командного пакета. Если для ATAPI-устройств размер командного пакета фиксирован и равен 12 байт, то для SCSI-устройств размер пакета может принимать значения 6, 10, 12 и 16 байт;
  • sbp – указатель на буфер SENSE DATA (данные о состоянии устройства после выполнения команды, [1, 5]);
  • mx_sb_len – максимальный размер буфера SENSE DATA;
  • sb_len_wr – реальный размер данных, сохраненных в буфере SENSE DATA;
  • dxferp – указатель на буфер для данных, принимаемых от устройства или передаваемых устройству;
  • dxfer_len – размер передаваемых/принимаемых данных;
  • iovec_count – если это поле равно 0, то буфер для данных представляет собой простой линейный массив байт, и поле dxferp – указатель на этот массив. В противном случае dxferp указывает на массив структур типа:

typedef struct sg_iovec {

void * iov_base; /* starting address */

size_t iov_len;  /* length in bytes */

} sg_iovec_t,

а поле iovec_count – число структур в этом массиве.

Подробная информация о sg-драйвере приведена в SCSI-Generic-HOWTO [4].

Рассмотрим порядок использования sg-драйвера на примере чтения PMA (Program Memory Area) CD-R/RW диска. Для чтения PMA устройству необходимо послать команду READ TOC/PMA/ATIP. Формат этой команды описан в [1], пример использования был рассмотрен в [5]. Для чтения PMA поле Format должно содержать значение 0011b. В ответ на команду READ TOC/PMA/ATIP устройство вернет блок данных следующего формата:

READ TOC/PMA/ATIP response data (Format = 0011b)

Bit

Byte

7

6

5

4

3

2

1

0

0

(MSB)

PMA Data Length

1

 

(LSB)

2

Reserved

3

Reserved

 

 

 

0

Reserved

1

ADR

CONTROL

2

TNO

3

POINT

4

Min

5

Sec

6

Frame

7

Zero

8

PMIN

9

PSEC

10

PFRAME

Рисунок 7. Формат данных PMA, Format Field = 0011b

Поле PMA Data Length содержит размер данных PMA, при этом длина самого поля (2 байта) не учитывается. Назначение каждого байта дескриптора PMA определяется значением поля ADR:

Таблица 4

ADR

Поле

Значение поля

 

1

TNO

0

 

POINT

Номер трека в BCD-коде

 

MIN,SEC,FRAME

Координаты конца трека

 

PMIN,PSEC,PFRAME

Координаты начала трека

 

2

TNO

0

 

POINT

0

 

MIN,SEC,FRAME

Идентификатор диска (6 цифр в BCD-коде)

 

PMIN

0

 

PSEC

Формат сессии:

00 - CDDA, CD-ROM,

10 - CD-I, 20 - CD-ROM-XA

 
 

PFRAME

0

 

Заголовочные файлы:

#include

#include

#include

#include

#include

#include

#include

#define SG_DEV "/dev/sg0" // имя файла устройства

// Макрос для пересчета координат сектора из MSF формата в LBA

#define MSF2LBA(Min, Sec, Frame) (((Min * 60 + Sec) * 75 + Frame) - 150)

int sg_fd; // файловый дескриптор

Следующая структура описывает формат данных PMA, представленный на рис. 7:

typedef struct {

        __u8 rez;       // reserved

        __u8 ctrl :4;    // Control

        __u8 adr :4;    // ADR

        __u8 tno;       // TNO (always 0)

        __u8 point;     // POINT

        __u8 min;       // AMIN

        __u8 sec;       // ASEC

        __u8 frame;     // AFRAME

        __u8 zero;      // 0

        __u8 pmin;      // PMIN

        __u8 psec;      // PSEC

        __u8 pframe;    // PFRAME

} __attribute__ ((packed)) pma_t;

Обмен данными с sg-драйвером выполняет функция send_cmd(). Параметры функции:

  • cmd – указатель на командный пакет;
  • cmdlen – длина командного пакета;
  • direction – направление передачи данных;
  • data – указатель на блок памяти для данных, передаваемых устройству или принимаемых от устройства. Если обмен данными не предусмотрен, этот параметр содержит значение NULL;
  • datalen – размер блока данных, на который указывает data. Если data == NULL, то datalen == 0
  • timeout – значения time-out.

int send_cmd(__u8 *cmd, __u8 cmdlen, unsigned int direction, __u8 *data, __u32 datalen, unsigned int timeout)

{

    int k = 0;

    sg_io_hdr_t io_hdr;

/* В sense_buffer будет сохранена информация о состоянии устройства после выполнения команды */

    __u8 sense_buffer[32];

/* Формируем запрос к sg-драйверу – заполняем поля структуры sg_io_hdr_t необходимыми значениями */

    memset(&io_hdr, 0, sizeof(sg_io_hdr_t));

    io_hdr.interface_id = "S";

    io_hdr.cmd_len = cmdlen; // длина команды

    io_hdr.mx_sb_len = sizeof(sense_buffer);

    io_hdr.dxfer_direction = direction; // направление передачи данных

    io_hdr.dxfer_len = datalen; // размер данных

    io_hdr.dxferp = data; // указатель на блок данных

    io_hdr.cmdp = cmd; // указатель на командный пакет

    io_hdr.sbp = sense_buffer;

    io_hdr.timeout = timeout;

/* Посылаем устройству команду */

    if(ioctl(sg_fd, SG_IO, &io_hdr) < 0) {

           perror("SG_IO ioctl");

           return -1;

    }

/* Отобразим содержимое sense_buffer, если при выполнении команды произошла ошибка. Это позволит установить причину ошибки */

    if((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) {

           if (io_hdr.sb_len_wr > 0) {

                 printf("Sense data: ");

                 for (k = 0; k < io_hdr.sb_len_wr; ++k) {

                        if ((k > 0) && (0 == (k % 10))) printf("   ");

                        printf("0x%02x ", sense_buffer[k]);

                 }

                 printf(" ");

           }

           if(io_hdr.masked_status)

                 printf("SCSI status=0x%x ", io_hdr.status);

           if(io_hdr.host_status)

                 printf("Host_status=0x%x ", io_hdr.host_status);

           if(io_hdr.driver_status)

                 printf("Driver_status=0x%x ", io_hdr.driver_status);

           return -1;

    }

    return 0;

}

Проверку готовности устройства к приему команды выполняет функция test_unit_ready():

int test_unit_ready()

{

    __u8 testCmdBlk[6];

    /* Prepare TEST UNIT command */

    memset(testCmdBlk, 0, 6);

    if(send_cmd(testCmdBlk, 6, SG_DXFER_NONE, NULL, 0, 20000) < 0) {

           printf("Unit not ready ");

           return -1;

    }

    return 0;

}

Чтение PMA выполняет функция read_pma():

int read_pma()

{

    int i, k;

    __u8 read_pma_cmd[10];

    __u8 *pma_data_buff; // здесь будут сохранены результаты чтения PMA

    __u16 buff_size = 0xFFFF; // размер блока памяти для хранения считываемых данных

    __u16 pma_data_length = 0; // реальная длина записей PMA

    __u32 lba;

    int pma_entries = 0; // число записей PMA

    pma_t *pma;

/* Проверяем готовность устройства к приему команды */

    if(test_unit_ready() < 0) exit(-1);

    pma_data_buff = (__u8 *)malloc(buff_size);

    memset(pma_data_buff, 0, buff_size);

/* Формируем командный пакет */

    memset(read_pma_cmd, 0, 10);

    read_pma_cmd[0] = 0x43; // код команды READ_TOC/PMA/ATIP

    read_pma_cmd[2] = 3; // поле Format Field = 011b, читаем PMA

    read_pma_cmd[7] = 0xFF;

    read_pma_cmd[8] = 0xFF;

/* Посылаем устройству команду */

    if(send_cmd(read_pma_cmd, 10, SG_DXFER_FROM_DEV, pma_data_buff, buff_size, 20000) < 0) return -1;

/* Считываем длину записей PMA. Размер поля PMA Data Length (2 байта) не учитывается */

    memcpy(&pma_data_length, pma_data_buff, 2);

    pma_data_length = __swab16(pma_data_length);

    printf("PMA data length - %d ", pma_data_length);

/* Определяем число записей PMA */

    pma_entries = (pma_data_length - 2)/11;

    printf("PMA entries - %d ", pma_entries);

/* Размер данных PMA точно известен и равен pma_data_length. Выделяем блок памяти для данных PMA и копируем их туда

 * из pma_data_buff. После этого можно освободить блок памяти, на который указывает pma_data_buff

 */

    pma = (pma_t *)malloc(pma_data_length);

    memset((void *)pma, 0, pma_data_length);

    memcpy((void *)pma, pma_data_buff + 4, pma_data_length);

    free(pma_data_buff);

/* Отображаем данные PMA */

    printf("Entry ADR CTRL Point Zero Min Sec Frame PMin Psec PFrame LBA ");

    for(i = 0; i < pma_entries; i++) {

           printf("%d ", i);

           printf("%X ", (pma + i)->adr);

           printf("%X ", (pma + i)->ctrl);

           printf("%X ", (pma + i)->point);

           printf("%d ", (pma + i)->zero);

           printf("%d ", (pma + i)->min);

           printf("%d ", (pma + i)->sec);

           printf("%d ", (pma + i)->frame);

           printf("%d ", (pma + i)->pmin);

           printf("%d ", (pma + i)->psec);

           printf("%d ", (pma + i)->pframe);

           lba = MSF2LBA((pma + i)->pmin, (pma + i)->psec, (pma + i)->pframe);

           if((pma + i)->adr != 1) printf("--- ");

           else printf("%u ", lba);

    }

    free(pma);

    return 0;

}

Вызов функции read_pma() для чтения данных PMA выполняется из главной функции:

Открываем файл устройства. Обратите внимание на режим открытия – чтение/запись. Если устройство открыто в режиме «Только чтение» (O_RDONLY), то оно воспринимает команды (см. [4]):

  • INQUIRY
  • TEST UNIT READY
  • REQUEST SENSE
  • READ CAPACITY
  • READ BUFFER
  • READ(6) (10) and (12)
  • MODE SENSE(6) and (10)

int main()

{

    if((sg_fd = open(SG_DEV, O_RDWR)) < 0) {

           perror("open");

           return -1;

    }

/*  Считываем PMA */

    if(read_pma() < 0) printf("Cannot read PMA ");

    close(sg_fd);

    return 0;

}

Полный текст данной программы находится в файле SG/read_pma.c.

Устанавливаем в устройство диск CD-RW, на котором записано 3 аудиотрека, и запускаем программу на выполнение. Результаты работы программы:

PMA data length - 46

PMA entries - 4

Entry      ADR      CTRL      Point      Zero      Min      Sec      Frame      PMin      Psec      PFrame            LBA

0            2      0      0      0      54      88      82      0      0      0            ---

1            1      0      1      0      5      3      16      0      2      0            0

2            1      0      2      0      8      28      58      5      5      16            22741

3            1      0      3      0      12      30      21      8      30      58            38158

Для анализа полученных результатов воспользуемся таблицей 4.

Запись

Значение

0

Поля MIN/SEC/FRAME содержат идентификатор диска в BCD-коде. Поле PSEC содержит формат сессии.

В нашем примере это значение равно 0 – CD-DA, аудиодиск.

1-3

Поле POINT содержит номер трека, поля PMIN/PSEC/PFRAME содержат координаты начала трека, MIN/SEC/FRAME – координаты конца трека. Хорошо видно, что пауза между треками составляет

2 секунды.

Свойства, профили и страницы режимов устройства

Свойства и профили устройства

Прежде чем послать устройству какую-либо команду, надо убедиться в том, что устройство способно эту команду выполнить. Для этого необходимо установить, какие именно команды поддерживает устройство. Набор команд, поддерживаемых устройством, называется свойством (Features).

Одно устройство может поддерживать несколько свойств. Базовый набор свойств устройства называется профилем (Profile). Перечень всех существующих свойств и профилей приведен в спецификации SCSI MMC-4, п. 5 «Features and Profiles for Multi-Media Device».

GET CONFIGURATION response data format

Bit

Byte

7

6

5

4

3

2

1

0

0-7

Feature Header

8-n

 

Рисунок 8. Формат блока данных, возвращаемого по команде GET CONFIGURATION

Feature Header

Bit

Byte

7

6

5

4

3

2

1

0

0

(MSB)

Data Length

 

(LSB)

1

2

3

4

Reserved

5

Reserved

6

(MSB)

Current Profile

(LSB)

                   

Рисунок 9. Формат заголовка свойства

Поле Data Length содержит размер считанных данных, следующих за эти полем, в поле Current Profile находится значение текущего профиля устройства. Если свойство не поддерживается устройством, то команда GET CONFIGU-RATION вернет только заголовок свойства, и поле Data Length будет содержать значение 4 (2 поля Reserved по одному байту каждое + 2 байта поля Current Profile).

Bit

Byte

7

6

5

4

3

2

1

0

0

(MSB)

Feature Code

(LSB)

1

2

Reserved

Version

Persistent

Current

3

Additional Length

4-n

Feature Dependent Data

Рисунок 10. Общий формат дескриптора свойства

Назначение полей дескриптора свойства:

  • Feature Code – код свойства. Каждое свойство имеет свой уникальный код. Список всех кодов приведен в спецификации [1], п. 5.3 «Feature Definitions».
  • Persistent – если этот бит установлен в 0, то данное свойство может менять текущий статус. Если бит равен 1, то свойство всегда активно.
  • Current – если бит установлен в 1, то данное свойство активно, т.е. устройство поддерживает набор команд, определенный этим свойством.
  • Feature Dependent Data – данные, специфичные для указанного свойства.

Назначение полей командного пакета:

  • RT – определяет тип данных, возвращаемых устройством. Поле может принимать следующие значения:
  • 00b – устройство возвращает заголовок свойства и дескрипторы всех свойств, поддерживаемых устройством, даже если свойство не является активным.
  • 01b – устройство возвращает заголовок свойства и дескрипторы активных свойств устройства (у которых бит Current установлен в единицу).
  • 10b – устройство возвращает заголовок и дескриптор свойства, номер которого задан в поле Starting Feature Number. Если запрашиваемое свойство не поддерживается устройством, возвращается только заголовок свойства Feature Header (рис. 9).
  • 11b – зарезервировано.
  • Allocation Length – размер памяти, выделенной для данных.

GET CONFIGURATION CDB

Bit

Byte

7

6

5

4

3

2

1

0

0

OPERATION CODE  (46h)

1

Reserved

RT

2

(MSB)

Starting Feature Number

(LSB)

3

4

Reserved

5

Reserved

6

Reserved

7

(MSB)

Allocation Length

(LSB)

8

9

Control

Рисунок 11. Формат команды GET CONFIGURATION

Рассмотрим пример. Необходимо выяснить, может ли устройство выполнить запись треков на компакт-диск в режиме TAO. Для этого надо установить, обладает ли устройство свойством «СD Track at Once». Код этого свойства равен 0x002D (см. [1]).

Bit

Byte

7

6

5

4

3

2

1

0

0

(MSB)

Feature Code = 002Dh

(LSB)

1

2

Reserved

Version = 2h

Persistent

Current

3

Additional Length = 04h

4

Resvd

BUF

Resvd

R-W Raw

R-W Pack

Test Write

CD-RW

R-W Sub-code

5

Reserved

6

(MSB)

Data Type Supported

(LSB)

Рисунок 12. Формат дескриптора свойства «СD Track at Once»

Устройство способно выполнить запись трека на компакт-диск в режиме TAO в том случае, если бит CD-RW установлен в единицу.

Рассмотрим функцию, выполняющую проверку наличия у устройства свойства «СD Track at Once» и значение бита CD-RW. Функция принимает один параметр – код свойства. Полный текст программы приведен в файле SG/get_conf.c.

int get_conf(__u16 f_num)

{

    __u8 get_conf_cmd[10];

    __u8 data_buff[16]; // результаты чтения

    __u32 data_length = 0; // реальная длина данных

    __u16 current_prof = 0; // значение текущего профиля

    __u16 f_code = 0; // код свойства

/* Ждем готовность устройства */

    if(test_unit_ready() < 0) exit(-1);

/* Формируем командный пакет */

    memset(data_buff, 0, 16);

    memset(get_conf_cmd, 0, 10);

    get_conf_cmd[0] = 0x46; // код команды GET CONFIGURATION

    get_conf_cmd[1] = 2; // RT= 10b

    get_conf_cmd[8] = 16;

/* В поле Starting Feature Number заносим код свойства */

    f_num = __swab16(f_num);

    memcpy((get_conf_cmd + 2), (void *)&f_num, 2);

/* Посылаем устройству команду */

    if(send_cmd(get_conf_cmd, 10, SG_DXFER_FROM_DEV, data_buff, 16, 20000) < 0) return -1;

/* Определяем длину считанных данных */

    memcpy((void *)&data_length, data_buff, 4);

    data_length = __swab32(data_length);

    printf(" Feature data length - %u ", data_length);

/* Если длина считанных данных равна 4, то запрашиваемое свойство не поддерживается */

    if(data_length == 4) return -1;

/* Определяем значение текущего профиля */

    memcpy((void *)&current_prof, data_buff + 6, 2);

    current_prof = __swab16(current_prof);

    printf("Current profile - 0x%.4X ", current_prof);

/* Код свойства, значение должно совпадать с параметром f_num */

    memcpy((void *)&f_code, (data_buff + 8), 2);

    f_code = __swab16(f_code);

    printf("Feature Code - 0x%.4X ", f_code);

    printf("Byte 4: 0x%X ", data_buff[12]);

/* Проверяем значение бита CD-RW. Если бит установлен в единицу – запрашиваемое свойство устройством поддерживается */

    if(data_buff[12] & 0x02) printf("Feature CD TAO support ");

    else return -1;

    return 0;

}

Устанавливаем в привод CD-RW диск и запускаем программу на выполнение. Результаты работы:

Feature data length - 12

Current profile - 0x000A

Feature Code - 0x002D

Byte 4: 0x6

Feature CD TAO support

Текущий профиль устройства – CD-RW, см. п. 5.4.10 «Profile 000Ah: CD-RW» спецификации SCSI MMC-4 ([1]). Список свойств, соответствующих данному профилю, приведен в этом же пункте, в таблице 192 «Mandatory Feature for CD-RW». Свойство «CD Track at Once» входит в их число.

Теперь установим в привод диск CD-ROM и опять запустим программу на выполнение. Результаты работы программы:

Feature data length - 12

Current profile - 0x0008

Feature Code - 0x002D

Byte 4: 0x6

Feature CD TAO support

Свойство «CD Track at Once» приводом поддерживается, но текущий профиль – 0x0008, CD-ROM – не позволяет это свойство применять. Список свойств, соответствующих профилю «CD-ROM», приведен в таблице 188 «Mandatory Feature for CD-ROM», п. 5.4.8 спецификации SCSI MMC-4 ([1]).

Страницы режимов

Для установки или определения параметров работы устройства используются страницы режимов (Mode Page). Каждая страница режима характеризуется кодовым номером, длиной и набором параметров. В таблице 5 приведен список кодов некоторых страниц режимов. Полный перечень находится в спецификации SCSI MMC-4, п. 7.1.3 «Mode Pages».

Таблица 5

Код страницы

Назначение страницы

0x01

Параметры режима коррекции ошибок чтения/записи

0x05

Параметры режима записи

0x0D

Параметры CD-дисковода

0x0E

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

0x1A

Параметры энергопотребления

0x1C

Управление сообщениями о сбоях и неисправностях

0x1D

time-out и защита

Прием и передача страниц осуществляется при помощи списка параметров режима Mode Parameter List. Список страниц начинается с заголовка (Mode Parameter Header), за которым могут следовать одна или несколько страниц режимов (рис. 13).

Mode Parameter List

Bit

Byte

7

6

5

4

3

2

1

0

0-7

Mode Parameter Header

8-n

Mode Page(s)

Рисунок 13. Формат списка Mode Parameter List

Mode Parameters Header

Bit

Byte

7

6

5

4

3

2

1

0

0

(MSB)

Mode Data Length

(LSB)

1

2

Reserved

3

Reserved

4

Reserved

5

Reserved

6

(MSB)

 

(LSB)

Рисунок 14. Формат заголовка списка страниц (Mode Parameter Header)

Поле Mode Data Length содержит размер блока данных, следующего сразу за этим полем, т.е. 6 оставшихся байт заголовка плюс длину запрашиваемой страницы. Если страница передается устройству, то значение поля Mode Data Length не используется (зарезервировано).

Страница параметров режима записи

Рассмотрим подробнее, что из себя представляет страница режима, на примере страницы параметров режима записи, Write Parameters Mode Page.

Write Parameters Page

Bit

Byte

7

6

5

4

3

2

1

0

0

PS

Reserved

Page Code (05h)

1

Page Length (32h or 36h)

2

Reserved

BUFE

LS_V

Test Write

Write Type

3

Multi-session

FP

Copy

Track Mode

4

Reserved

Data Block Type

5

Link Size

6

Reserved

7

Reserved

Initiator Application Code

8

Session Format

9

Reserved

10

(MSB)

Packet Size

 

(LSB)

11

12

13

14

(MSB)

Audio Pause Length

(LSB)

15

16

(MSB)

...

Media Catalog Number

...

(LSB)

17

……

30

31

32

(MSB)

...

International Standard Recording Code

...

(LSB)

33

……

46

47

48

Sub-header Byte 0

49

Sub-header Byte 1

50

Sub-header Byte 2

51

Sub-header Byte 3

52-55

Vendor Specific

Рисунок 15. Формат страницы параметров режима записи

Назначение полей:

  • Page Code – код страницы, содержит значение 0x05.
  • Page Length – размер страницы в байтах.
  • Write Type – используемый режим записи:
    • 01 – Track-at-once (TAO);
    • 02 – Session-at-once (SAO);
    • 03 – RAW.
  • Test Write – режим имитации записи данных на носитель. Бит имеет значение только для режимов TAO и SAO.
  • Track Mode – содержит значение поля управления Control Field Q-субканала при ADR = 1 (см. «Физический формат данных на компакт-диске»). В данной статье будет использовано только два значения этого поля:
    • 0 – аудио-трек;
    • 4 – трек данных.
  • Multi-session – показывает, как закрытие текущей сессии влияет на открытие следующей:
    • 00b – указатель B0 отсутствует в TOC, открытие новой сессии запрещено ([3, 5]);
    • 01b – указатель B0 содержит значение FF:FF:FF, открытие новой сессии запрещено;
    • 11b – открытие новой сессии разрешено. Указатель B0 содержит координаты начала следующей области программ.
  • Data Block Type – определяет тип блока данных и его размер. Перечень всех значений этого поля находится в таблице 619 «Data Block Type Codes» спецификации MMC-4. В данной статье будет использовано только два значения:
    • 0 – блок «сырых» данных размером 2352 байт (блок аудиоданных);
    • 8 – блок данных размером 2048 байт, формат блока данных Mode 1.
  • Session Format – формат сессии. Это значение записывается в поле PSEC указателя A0 таблицы содержания диска TOC. Поле может принимать следующие значения:
    • 00h – диск CD-DA или CD-ROM
    • 01h – диск CD-I
    • 20h – диск CD-ROM XA

В поле Sub-Header устройству передается информация для заполнения подзаголовка сектора при записи на диск данных в формате Mode 2 Form 1/2 (см. табл. 2 и 3).

Во второй части статьи будут рассмотрены примеры программ, выполняющих запись на компакт-диск CD-R/RW различной информации, музыкальных треков и данных.

Литература, ссылки:

  1. Спецификация SCSI Multimedia Commands-4 (SCSI MMC-4), http://www.t10.org/ftp/t10/drafts/mmc4/mmc4r03d.pdf
  2. Спецификация SCSI-3 Multimedia Commands, http://www.t10.org/ftp/t10/drafts/mmc/mmc-r10a.pdf
  3. Specification for ATAPI DVD Devices, ftp.seagate.com/sff/INF-8090.pdf
  4. SCSI-Generic-HOWTO, http://www.linux.org/docs/ldp/howto/SCSI-Generic-HOWTO/index.html
  5. Мешков В. Пакетные команды интерфейса ATAPI. – Журнал «Системный администратор», № 9(22), сентябрь 2004 г. – 70-84 с.

Комментарии отсутствуют

Добавить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

               Copyright © Системный администратор

Яндекс.Метрика
Tel.: (499) 277-12-41
Fax: (499) 277-12-45
E-mail: sa@samag.ru