Чтение данных CD из программы начальной загрузки

Тема в разделе "WASM.BEGINNERS", создана пользователем l_inc, 27 сен 2006.

  1. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Стоп. Кажется поторопился. В исходнике ни одного in'a, ни одного out'a, даже ни одного int'a. Но хоть есть где покопошиться. Посмотрим...
     
  2. ntcdm

    ntcdm New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2007
    Сообщения:
    247
    посмотри сорсы isolinux - он умеет грузится с CD.
     
  3. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    l_inc
    Я не супер-спец по АТА но кое-что читал, можно попробовать разобраться. Есть несколько вопросов:

    1. Как выполняется код -- из под Win/DOS/голый проц?
    2. Где гарантия, что винчестер работает в PIO -- я думаю, что BIOS настраивает хост-контроллер и контроллер винчестера на максимум, так что это, скорее всего, будет DMA.
     
  4. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Mika0x65
    1. Голый. (P.S. Вы, наверное, не обратили внимания, но Вы в этой теме уже отвечали, зная ответ на этот вопрос. :) Ну... и кроме того в первом посте я писАл.)
    2. Винчестер? Нет. Я указывал координаты (IDE-разъем и Master/Slave) CD-ROM'a, когда пытался с PIO че-нить покрутить.
    Ну а я - просто чайник. Я решил, что можно просто работать по выбранному протоколу, не задумываясь о том на что настроен контроллер.
     
  5. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Mika0x65
    Это зависит от ATA команды:
    Код (Text):
    1. READ MULTIPLE
    2. READ MULTIPLE EXT
    3. READ SECTOR
    4. READ SECTOR EXT
    5. READ BUFFER
    Эти команды PIO.
    Код (Text):
    1. READ BUFFER
    2. READ DMA
    3. READ DMA QUEUED
    4. READ DMA QUEUED EXT
    Соответственно DMA.
     
  6. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Определяет все ATAPI-CD устройства в системе:
    Код (Text):
    1. int FindAtapiCD(int maxdetect, int *DrvTbl)
    2. {
    3. int devnum;
    4. int totaldev=0;
    5. for(devnum=0;(Atp[devnum].port!=0)&&(totaldev<=maxdetect);devnum++){
    6.     register int port=Atp[devnum].port;
    7.     int i;
    8.     /* адрес устройства */
    9.     outportb(port+6,Atp[devnum].ms?0xA0:0xB0);
    10.     delay(1);
    11.     if(inportb(port+7)==0xFF)continue;
    12.     if(inportb(port+7)&0x80){
    13.         /* м.б. оживится ? */
    14.         if(ResetDrive(port))continue;
    15.     }
    16.     outportb(port+4,0);
    17.     outportb(port+5,0);
    18.     outportb(port+7,0xEC);
    19.     for(i=0;i<20;i++){
    20.         delay(1);
    21.         if((inportb(port+4)==0x14)&&
    22.            (inportb(port+5)==0xEB)){
    23.             word devcode;
    24.             /* есть ATAPI-устройство, анализируем подробнее */
    25.             delay(1);
    26.             outportb(port+7,0xA1);
    27.             for(i=0;i<100;i++)
    28.                 if(inport(port+7)&0x80)delay(1);
    29.                 else goto okcont;
    30.             goto cont;
    31.  
    32.             okcont:
    33.             delay(10);
    34.             devcode=inport(port);
    35.             for(i=0;i<255;i++)inport(port);
    36.             /* это CD ? */
    37.             if((devcode&0x1F00)!=0x500)break;
    38.             /* У него 12 бит в AP ? */
    39.             if(devcode&1)break;
    40.             *DrvTbl++=devnum;
    41.             totaldev++;
    42.             break;
    43.            }
    44.     }
    45.     cont:;
    46. }
    47. return(totaldev);
    48. }
    Послать ATAPI комманду.
    Код (Text):
    1. /* Выполнить ATAPI-команду:
    2.      drive  - устройство
    3.      dir    - 1 - чтение, 0 - запись данных в CDD
    4.      AP     - буфер с ATAPI-пакетом
    5.      buffer - буфер с данными (NULL, если не нужен)
    6.      bufflen- длина выводимых данных или макс. размер вводимых
    7. на выходе:
    8.      -1 - была ошибка
    9.      прочее - размер пересланного блока (в байтах)
    10. */
    11. static word PrefIOBlock=0x8000;  /* размер блока пересылки в словах */
    12. static byte DontResetFlg=0; /* не сбрасывать при неготовности */
    13.  
    14. int ExecATAPICMD(int drive, int dir, word *AP, word *buffer, word bufflen)
    15. {
    16. int port;
    17. int i;
    18. int readed=0;
    19. int size;
    20.     port=Atp[drive].port;
    21.     /* выберем активное устройство */
    22.     outportb(port+6,Atp[drive].ms?0xA0:0xB0);
    23.  
    24.     rerd:
    25.  
    26.     Last1X7=inportb(port+7);
    27.     if(Last1X7&0x88){ /* не очень готов - попробуем исправить положение */
    28.         if(DontResetFlg)return(-1);
    29.         ResetDrive(port);
    30.         /* ждем завершения команды сброса */
    31.         if(WtBitMask(port+7,0x80,0x0,10))return(-1);    /* не готов */
    32.         goto rerd;
    33.     }
    34.     /* установим размер блока */
    35.     {
    36.      register word pl;
    37.  
    38.      if(PrefIOBlock>bufflen)pl=bufflen;
    39.      else           pl=PrefIOBlock;
    40.      outportb(port+4,pl);
    41.      outportb(port+5,pl>>8);
    42.     }
    43.     /* запретим всякие хитрые обмены */
    44.     outportb(port+1,0);
    45.     /* все готово к работе  - приступим к передаче пакета */
    46.     outportb(port+7,0xA0);
    47.     /* ждем готовности не более 3х секунд (можно и меньше) */
    48.     if(WtBitMask(port+7,0x89,8,3))return(-1);
    49.     /* выведем пакетик */
    50.     disable();
    51.     for(i=0;i<6;i++) outport(port,*AP++);
    52.     enable();
    53.  
    54.     /* точка входа цикла приема блоков */
    55.     GetNextBlk:
    56.     /* здесь ждем до 30 секунд */
    57.     WtBitMask(port+7,0x80,0x00,30);
    58.     /* пакет воспринят, а запрос выполнен -
    59.         получим размер и направление передачи */
    60.     size=inportb(port+4) | (inportb(port+5)<<8);
    61.     Last1X7=inportb(port+7);
    62.     if(Last1X7&1)return(-1);    /* ошибка выполнения команды */
    63.     if(Last1X7&8){ /* нужно что-то пересылать */
    64.         if(inportb(port+2)&2){
    65.          /*из CD */
    66.                 if(dir==1 && buffer != NULL ){
    67.                 /* прочтем предлагаемое */
    68.                    while(size>0){
    69.                     int i=inport(port);
    70.                     size-=2;
    71.                     if(bufflen<1)break;
    72.                     *buffer++=i;
    73.                     readed+=2;
    74.                     bufflen-=2;
    75.                    }
    76.                 }
    77.                 /* пропустим ненужный остаток */
    78.                 while((size-=2)>0){inport(port);}
    79.         }
    80.         else{
    81.         /* в CD */
    82.             if(dir==0 && buffer!=NULL ){
    83.                    while(bufflen>0 && size > 0){
    84.                     if(bufflen<1)break;
    85.                     outport(port,*buffer++);
    86.                     bufflen-=2;
    87.                     readed+=2;
    88.                     size-=2;
    89.                    }
    90.             }
    91.             /* добросим остаток нулями */
    92.             while((size-=2)>0){outport(port,0);}
    93.         }
    94.         goto GetNextBlk;
    95.     }
    96.     /* пересылать больше не нужно - команда завершена */
    97.     Last1X7=inportb(port+7);
    98.     if(Last1X7&1){
    99.         /* были ошибки */
    100.         return(-1);
    101.     }
    102. return(readed);
    103. }
    Код нагло выдран из "ATAPI(IDE) CD Информация к размышлению."
     
  7. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    n0name
    Т.е. это было правильно, что я начал сразу после загрузки программы с записи в 3F6h (остановка прерываний) и т.д. и никакая предварительная настройка для работы с PIO не нужна?
    Тогда почему же возвращается ошибка?
     
  8. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    n0name
    Да, точно. При чем, DMA команды в стандарте помечены как prohibited для ATAPI устройств.
     
  9. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Хз.
    Вот мой код чтения с HDD:
    Код (Text):
    1. NTSTATUS ReadSector(ULONG dwType, PVOID pBuffer){
    2.     ULONG dwInputType, i;
    3.     USHORT wInput;
    4.  
    5.     if (dwType > READ_TYPE_PIO_END)
    6.         dwInputType = INPUT_TYPE_DMA;
    7.     else
    8.         dwInputType = INPUT_TYPE_PIO;
    9.     _CLI_;
    10.     if (!IsControllerFree(HDD_PORT_SR)){
    11.         DbgPrint("Controller busy for a long time.");
    12.         return STATUS_UNSUCCESSFUL;
    13.     }
    14.     OUT_PORT(HDD_PORT_DH, 0xE0);
    15.     if (!IsDriveCmdReady(HDD_PORT_SR)){
    16.         DbgPrint("Drive does not ready for a long time.");
    17.         return STATUS_UNSUCCESSFUL;
    18.     }
    19.     OUT_PORT(HDD_PORT_SC, 0x01);
    20.     OUT_PORT(HDD_PORT_SN, 0x00);
    21.     OUT_PORT(HDD_PORT_CL, 0x00);
    22.     OUT_PORT(HDD_PORT_CH, 0x00);
    23.     if (dwInputType == INPUT_TYPE_DMA)
    24.         if (!InitDMAChannel())
    25.             return STATUS_UNSUCCESSFUL;
    26.     switch (dwType){
    27.         case READ_TYPE_READSECTOR:
    28.             OUT_PORT(HDD_PORT_CR, HDD_CMD_READSECTOR);
    29.             break;
    30.         case READ_TYPE_READSECTOR_RETRY:
    31.             OUT_PORT(HDD_PORT_CR, HDD_CMD_READSECTOR_RETRY);
    32.             break;
    33.         case READ_TYPE_READMULTIPLE:
    34.             OUT_PORT(HDD_PORT_CR, HDD_CMD_READMULTIPLE);
    35.             break;
    36.     }
    37.     if (dwInputType == INPUT_TYPE_PIO){
    38.         if (!IsDriveExcReady(HDD_PORT_SR)){
    39.             DbgPrint("Drive does not ready to exchange for a long time.");
    40.             return STATUS_UNSUCCESSFUL;
    41.         }
    42.         for (i = 0; i < 256; i++){
    43.             IN_PORTW(HDD_PORT_DR_1, wInput);
    44.             ((PUSHORT)pBuffer)[i] = wInput;
    45.         }
    46.     }
    47.     _STI_;
    48.     return STATUS_SUCCESS;
    49. }
    Работу с DMA вырезал, ибо много и для тебя лишнее.
    К сожалению не работал с ATAPI, читал только про ATA(8).
     
  10. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    l_inc
    М.б. покажешь код полностью? Попробую в эмуляторе запустить.
     
  11. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    n0name
    Я об этом узнал из стандарта ata-atapi-6-3b. Там в 6.4.2 сказано:
     
  12. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Mika0x65
    Да я сам в Bochs'e начал запускать, а то на экране после попытки чтения с CD-ROM'a без эмуляции просто пугающие вещи появляются, а после первой перезагрузки еще и CD-ROM не работает (может из-за того, что дело не доходит до разрешения прерываний). Прикрепил исходник (только за строку db не пинайте :) ), табличку символов (она должна быть в образе на 2-9 секторах) и сам образ для эмулятора.
     
  13. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    Хочешь с оутами - пожалуйста (тоже только ПИО)
     
  14. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Y_Mur
    :)
    Под словами
    я имел в виду остальные исходники. Т.е. я заметил, что система не из одного единственного инклуда состоит, и уже "копошусь" там.
    Еще раз спасибо.
     
  15. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    l_inc
    Посмотрел сейчас образ в Bochs. Он немного отличается от того, что в исходнике... И еще не понятно, зачем нужен такой код:
    Код (Text):
    1. mov dx, 01f7h
    2. m4:
    3.     in al, dx
    4.     test al, 01h
    5.     jz m4
    Попробовал подсунуть на первый канал винчестер -- операция чтения прошла успешно (были установлены DRDY, DRQ & Drive Seek Complete). Точно не уверен (но получается так), что считать данные обычной (непакетной) командой с ATAPI устройства нельзя...
     
  16. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Mika0x65
    Когда пишешь не релиз, а так методом тыка че-то пробуешь, то накапливается куча мягко говоря "неоптимизированного кода". Так вот этот код как-раз проверяет, устанавливается ли бит ERR в порту 01f7h. И если не устанавливается, то происходит зацикливание, но на это можно не рассчитывать, т.к. для CD-ROM он выставляется, а после этого кода я уже получал в ax код ошибки и выводил его. Так вот если бы на экран ничего не выводилось, то произошло зацикливание и ошибки нету. :)
    Дык в этом-то и проблема. :) С винчестером работает, а с CD-ROM'ом - нет, хотя протокол PIO описан, как стандарт для всех ATAPI-устройств.
    И еще интересная подробность:
    скомпилировал код только до вывода строки на экран (все остальное закомментировал и после вывода jmp $ поставил) в тасме и в фасме. В результате бинарники в некоторых местах отличаются (как показывает ида, тасм и фасм некоторые команды различными альтернативными кодами представляют, например xor ax, ax: 33 С0 (TASM) и 31 С0 (FASM)), но Bochs при этом эмулирует только код, скомпилированный в тасме, а при выполнении кода, скомпилированного фасмом, управление каким-то образом передается на второй сектор (а там данные, а не код и т.о. получается illegal instruction DB, если я правильно помню).
     
  17. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Ты немного путаешь транспортный протокол и протокол взаимодействия. PIO -- транспортный протокол, он описывает как данные должны передаваться от устройства к хосту (и обратно), а протокол взаимодействия с ATAPI устройством -- пакетный.

    Попробовал оба (33 и 31) варианта в Bochs 2.3 -- оба работают корректно. Хотя у Bochs бывают заходы...
     
  18. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Mika0x65
    Это я просто различия для xor, как пример привел (на самом деле код различается в довольно многих местах). Что именно неверно (а может и верно: не знаю) эмулируется, я еще не искал. Просто только TASM'e пока компилирую.