1. Если вы только начинаете программировать на ассемблере и не знаете с чего начать, тогда попробуйте среду разработки ASM Visual IDE
    (c) на правах рекламы
    Скрыть объявление

Чтение сектора используя LBA48

Тема в разделе "WASM.OS.DEVEL", создана пользователем drem1lin, 15 фев 2011.

  1. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    296
    Здравствуйте, в ходе работы надо было произвести сабж, но в буффере постоянно получаются нули. Есть аналогичный код для LBA28, он работает, а 48 нет. Ошибку пока найти не получается, может кто сможет подсказать где косяк. Код основан на книге Кулакова "Программирование дисковых подсистем".
    Вот соответсвенно процедуры посылки команды и чтения сектора:
    Код (Text):
    1. SendCommandToHDDLBA48 proc
    2.     pushad
    3.     debug 88h
    4.     mov eax, ds:[046ch]
    5.     mov ds:[OPERATION_TIMER], eax
    6. ; Проверить корректность номера канала
    7.     mov     BX,ds:[CHANNEL_NUMBER]
    8. ; Установить базовый адрес
    9.     cmp     BX, 1
    10.     db 66h
    11.     jne @@SecondChannel
    12.     mov     word ptr ds:[ATA_BASE_PORT_ADDR],01f0h
    13.     db 66h
    14.     jmp @@PortSelected
    15. @@SecondChannel:
    16.     mov     word ptr ds:[ATA_BASE_PORT_ADDR],0170h
    17. @@PortSelected:
    18. ; Ожидание готовности HDD к приему команды
    19.     ; Выбрать нужный диск
    20.     mov     DX,ds:[ATA_BASE_PORT_ADDR]
    21.     add     DX,6    ;адрес регистра головок
    22.     mov     AL,ds:[DISK_NUMBER]
    23.     shl     AL,4
    24.     or      AL,10100000b
    25.     out     DX,AL
    26.     ; Ожидать, пока диск не будет готов
    27.     inc     DX
    28. @@WaitHDReady:
    29.     ; Проверить время ожидания
    30.     mov     EAX,ds:[046Ch]
    31.     sub     EAX,ds:[OPERATION_TIMER]
    32.     cmp     EAX,BSY_WAIT_TIME
    33.     db 66h
    34.     ja      @@Err1 ;ошибка тайм-аута
    35.     ; Прочитать регистр состояния
    36.     in      AL,DX
    37.     ; Проверить состояние сигнала BSY
    38.     test    AL,80h
    39.     db 66h
    40.     jnz     @@WaitHDReady
    41.     ; Проверить состояние сигнала DRQ
    42.     test    AL,08h
    43.     db 66h
    44.     jnz     @@WaitHDReady
    45.  
    46. ; Загрузить команду в регистры контроллера
    47.     mov     DX,ds:[ATA_BASE_PORT_ADDR]
    48.    
    49.     add     DX,2      ;счетчик секторов   +2
    50.     xor     al, al
    51.     out     DX,AL           ;SECTOR_COUNT 15...8 == 0
    52.     mov     AL,ds:[ATA_SECTOR_COUNT]
    53.     out     DX,AL           ;SECTOR_COUNT 7...0
    54.    
    55.     inc     DX      ;LBA low  +3
    56.     mov     AL,ds:[LBA_24_31]
    57.     out     DX,AL
    58.     mov     AL,ds:[LBA_0_7]
    59.     out     DX,AL
    60.    
    61.     inc     DX      ;LBA mid  +4
    62.     mov     Al,ds:[LBA_32_39]
    63.     out     DX,AL
    64.     mov     AL,ds:[LBA_8_15]
    65.     out     DX,AL
    66.    
    67.     inc     DX      ;LBA high +5
    68.     mov     Al,ds:[LBA_40_47]
    69.     out     DX,AL    
    70.     mov     AL,ds:[LBA_16_23]
    71.     out     DX,AL
    72.  
    73.     inc     DX      ;номер головки/номер диска    +6
    74.     mov     AL,ds:[DISK_NUMBER]
    75.     shl     AL,4
    76.     or      AL,10100000b
    77.     mov     AH,ds:[ATA_ADDRESS_MODE]
    78.     shl     AH,6
    79.     or      AL,AH
    80.     out     DX,AL
    81. ; Послать команду
    82.     mov     AL,byte ptr ds:[ATA_COMMAND]
    83.     inc     DX      ;регистр команд
    84.     out     DX,AL
    85.     mov dword ptr ds:[DEVICE_ERROR_CODE], 0
    86.     db 66h
    87.     jmp @@exit
    88. @@Err1:
    89.     mov dword ptr ds:[DEVICE_ERROR_CODE], 1
    90.  
    91. @@exit:
    92.     debug 89h
    93.     popad
    94.     MyRet
    95. SendCommandToHDDLBA48 endp
    96. ;****************************************************
    97. ; Процедура чтения секторов hdd в режиме LBA48
    98. ;   Вход:   eax - биты 0-31 адреса
    99. ;           dx  - биты 32-47
    100. ;           cx  - Число секторов
    101. ;           edi - адрес буфера приемника
    102. ;           [DISK_NUMBER] - диск primary/slave
    103. ;           [CHANNEL_NUMBER] - канал IDE
    104. ReadHDDSectorLBA48 proc
    105.         pushad
    106.         debug 86h
    107. ; Задать режим LBA
    108.         mov     byte ptr ds:[ATA_ADDRESS_MODE],1
    109. ; Послать команду чтения сектора (с повторами)
    110.         mov     byte ptr ds:[ATA_SECTOR_COUNT],cl
    111.         mov     ds:[LBA_0_7],EAX
    112.         mov     ds:[LBA_32_39], dx
    113.         mov     byte ptr ds:[ATA_COMMAND],24h
    114.         call    large near ptr SendCommandToHDDLBA48
    115.         cmp     dword ptr ds:[DEVICE_ERROR_CODE],0
    116.         db 66h
    117.         jne     @@End    ;закончить, сохранив код ошибки
    118. ; Ожидать готовность данных HDD
    119.         mov     DX,ds:[ATA_BASE_PORT_ADDR]
    120.         add     DX,7     ;адрес регистра состояния
    121. @@WaitCompleet:
    122.         ; Проверить время выполнения команды
    123.         mov     EAX,ds:[046Ch]
    124.         sub     EAX,ds:[OPERATION_TIMER]
    125.         cmp     EAX, MAX_HDD_WAIT_TIME
    126.         db 66h
    127.         ja      @@Error1 ;ошибка тайм-аута
    128.         ; Проверить готовность
    129.         in      AL,DX
    130.         test    AL, 1
    131.         db 66h
    132.         jnz     @@Error2
    133.         test    AL,80h   ;состояние сигнала BSY
    134.         db 66h
    135.         jnz     @@WaitCompleet
    136.         test    AL,08h   ;состояние сигнала DRQ
    137.         db 66h
    138.         jz      @@WaitCompleet
    139. ; Принять сектор
    140.         mov     EDX,ds:[ATA_BASE_PORT_ADDR] ;регистр данных
    141.        
    142.         mov     EAX,256   ;число считываемых слов
    143.         mul     CX
    144.         mov     ECX, EAX
    145.         db 67h
    146.         rep     insw     ;принять блок данных
    147. ; Сбросить признак ошибки
    148.         mov     dword ptr ds:[DEVICE_ERROR_CODE],0
    149.         db 66h
    150.         jmp @@End
    151. ; Записать номер ошибки
    152. @@Error1:
    153.         mov     dword ptr ds:[DEVICE_ERROR_CODE],1 ;ошибка тайм-аута
    154.         db 66h
    155.         jmp  @@End
    156. @@Error2:
    157.         mov     dword ptr ds:[DEVICE_ERROR_CODE],2 ;ошибка
    158. @@End:  
    159.         debug 87h
    160.         popad
    161.         MyRet
    162. ReadHDDSectorLBA48  endp
    Для сравнения также выкладывают код для LBA28:
    Код (Text):
    1. ;****************************************************
    2. ;*          ПОСЛАТЬ КОМАНДУ ЗАДАННОМУ ДИСКУ         *
    3. ;* Входные параметры передаются через глобальные    *
    4. ;* переменные:                                      *
    5. ;* ChannelNumber - номер канала (1 или 2);          *
    6. ;* DiskNumber - номер диска (0 или 1);              *
    7. ;* ATAFeatures - "особенности";                     *
    8. ;* ATASectorCount - количество секторов;            *
    9. ;* ATASectorNumber - номер начального сектора;      *
    10. ;* ATACylinder - номер начального цилиндра;         *
    11. ;* ATAHead - номер начальной головки;               *
    12. ;* ATAAddressMode - режим адресации (0-CHS, 1-LBA); *
    13. ;* ATACommand - код команды.                        *
    14. ;* После успешного выполнения функции:              *
    15. ;* в ATABasePortAddr - базовый адрес HDD;           *
    16. ;* в OpTime - момент начала выполнения команды;     *
    17. ;* в DevErrorCode - ноль.                           *
    18. ;* При возникновении ошибки в DevErrorCode будет    *
    19. ;* возвращен код ошибки.                            *
    20. ;****************************************************
    21. SendCommandToHDD proc
    22.         pushad
    23.         debug 84h
    24.         mov eax, ds:[046ch]
    25.         mov ds:[OPERATION_TIMER], eax
    26. ; Проверить корректность номера канала
    27.         mov     BX,ds:[CHANNEL_NUMBER]
    28. ; Установить базовый адрес
    29.         cmp     BX, 1
    30.         db 66h
    31.         jne @@SecondChannel
    32.         mov     word ptr ds:[ATA_BASE_PORT_ADDR],01f0h
    33.         db 66h
    34.         jmp @@PortSelected
    35. @@SecondChannel:
    36.         mov     word ptr ds:[ATA_BASE_PORT_ADDR],0170h
    37. @@PortSelected:
    38. ; Ожидание готовности HDD к приему команды
    39.         ; Выбрать нужный диск
    40.         mov     DX,ds:[ATA_BASE_PORT_ADDR]
    41.         add     DX,6    ;адрес регистра головок
    42.         mov     AL,ds:[DISK_NUMBER]
    43.         shl     AL,4
    44.         or      AL,10100000b
    45.         out     DX,AL
    46.         ; Ожидать, пока диск не будет готов
    47.         inc     DX
    48. @@WaitHDReady:
    49.         ; Проверить время ожидания
    50.         mov     EAX,ds:[046Ch]
    51.         sub     EAX,ds:[OPERATION_TIMER]
    52.         cmp     EAX,BSY_WAIT_TIME
    53.         db 66h
    54.         ja      @@Err1 ;ошибка тайм-аута
    55.         ; Прочитать регистр состояния
    56.         in      AL,DX
    57.         ; Проверить состояние сигнала BSY
    58.         test    AL,80h
    59.         db 66h
    60.         jnz     @@WaitHDReady
    61.         ; Проверить состояние сигнала DRQ
    62.         test    AL,08h
    63.         db 66h
    64.         jnz     @@WaitHDReady
    65.  
    66. ; Загрузить команду в регистры контроллера
    67.         mov     DX,ds:[ATA_BASE_PORT_ADDR]
    68.         inc     DX      ;регистр "особенностей" +1
    69.         mov     AL,ds:[ATA_FEATURES]
    70.         out     DX,AL
    71.         inc     DX      ;счетчик секторов   +2
    72.         mov     AL,ds:[ATA_SECTOR_COUNT]
    73.         out     DX,AL
    74.         inc     DX      ;регистр номера сектора  +3
    75.         mov     AL,ds:[ATA_SECTOR_NUMBER]
    76.         out     DX,AL
    77.         inc     DX      ;номер цилиндра (младший байт) +4
    78.         mov     AX,ds:[ATA_CYLINDER]
    79.         out     DX,AL
    80.         inc     DX      ;номер цилиндра (старший байт) +5
    81.         mov     AL,AH
    82.         out     DX,AL
    83.         inc     DX      ;номер головки/номер диска    +6
    84.         mov     AL,ds:[DISK_NUMBER]
    85.         shl     AL,4
    86.        
    87.         push    ax
    88.         mov     al, byte ptr ds:[LBA_24_31]
    89.         and     al, 0fh
    90.         mov     byte ptr ds:[ATA_HEAD],al ;LBA_24_27
    91.         pop     ax
    92.        
    93.         or      AL,ds:[ATA_HEAD]
    94.         or      AL,10100000b
    95.         mov     AH,ds:[ATA_ADDRESS_MODE]
    96.         shl     AH,6
    97.         or      AL,AH
    98.         out     DX,AL
    99. ; Послать команду
    100.         mov     AL,byte ptr ds:[ATA_COMMAND]
    101.         inc     DX      ;регистр команд
    102.         out     DX,AL
    103.         mov dword ptr ds:[DEVICE_ERROR_CODE], 0
    104.         db 66h
    105.         jmp @@exit
    106. @@Err1:
    107.         mov dword ptr ds:[DEVICE_ERROR_CODE], 1
    108.         db 66h
    109.         jmp @@exit
    110. @@exit:
    111.         debug 85h
    112.         popad
    113.         MyRet
    114. SendCommandToHDD endp
    115.  
    116. ;*************************************************
    117. ;*  ЧТЕНИЕ СЕКТОРА ЖЕСТКОГО ДИСКА В РЕЖИМЕ LBA   *
    118. ;* Входные параметры передаются через глобальные *
    119. ;* перменные:                                    *
    120. ;* ChannelNumber - номер канала (1 или 2);       *
    121. ;* DiskNumber - номер диска на канале (0 или 1); *
    122. ;* SectorAddress - номер считываемого сектора.   *
    123. ;* Сектор считывается основной сегмент данных,   *
    124. ;* в массив Sector512.                           *
    125. ;*************************************************
    126. ReadHDDSector proc
    127.         pushad
    128.         debug 86h
    129. ; Задать режим LBA
    130.         mov     byte ptr ds:[ATA_ADDRESS_MODE],1
    131. ; Послать команду чтения сектора (с повторами)
    132.         mov     byte ptr ds:[ATA_FEATURES],0
    133.         mov     byte ptr ds:[ATA_SECTOR_COUNT],1
    134.         mov     EAX,0
    135.         mov     ds:[ATA_SECTOR_NUMBER],EAX
    136.         mov     byte ptr ds:[ATA_COMMAND],20h
    137.         call    large near ptr SendCommandToHDD
    138.         cmp     dword ptr ds:[DEVICE_ERROR_CODE],0
    139.         db 66h
    140.         jne     @@End    ;закончить, сохранив код ошибки
    141. ; Ожидать готовность данных HDD
    142.         mov     DX,ds:[ATA_BASE_PORT_ADDR]
    143.         add     DX,7     ;адрес регистра состояния
    144. @@WaitCompleet:
    145.         ; Проверить время выполнения команды
    146.         mov     EAX,ds:[046Ch]
    147.         sub     EAX,ds:[OPERATION_TIMER]
    148.         cmp     EAX, MAX_HDD_WAIT_TIME
    149.         db 66h
    150.         ja      @@Error1 ;ошибка тайм-аута
    151.         ; Проверить готовность
    152.         in      AL,DX
    153.         test    AL,80h   ;состояние сигнала BSY
    154.         db 66h
    155.         jnz     @@WaitCompleet
    156.         test    AL,08h   ;состояние сигнала DRQ
    157.         db 66h
    158.         jz      @@WaitCompleet
    159. ; Принять сектор
    160.         mov     edi, 0fedbb000h
    161.         mov     EDX,ds:[ATA_BASE_PORT_ADDR] ;регистр данных
    162.         mov     ECX,256   ;число считываемых слов
    163.         db 67h
    164.         rep     insw     ;принять блок данных
    165. ; Сбросить признак ошибки
    166.         mov     dword ptr ds:[DEVICE_ERROR_CODE],0
    167.         db 66h
    168.         jmp @@End
    169. ; Записать номер ошибки
    170. @@Error1:
    171.         mov     dword ptr ds:[DEVICE_ERROR_CODE],1 ;ошибка тайм-аута
    172.         db 66h
    173.         jmp  @@End
    174. @@End:  
    175.         debug 87h
    176.         popad
    177.         MyRet
    178. ReadHDDSector   endp
    И еще небольшой вопрос, если я пишу в регистр числа секторов, например, 10, при при считывания я должен сделать insw 10*256 раз?
     
  2. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.399
    Адрес:
    Fryazino
    drem1lin
    Тестируешь на реальной машине или под виртуалкой?
    Просто виртуальные машины хотя и выдавали бит о наличие поддержки 48бит, но на самом деле её не поддерживали.
     
  3. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    296
    На реальной, AIDA бит поодержки показывает. Я разобрался в чем ошибка, там при умножении AX на CX стирается значение DX. а это порт данных. Но пока 2 сектора считать не получается. Пытался 2 раза, в первый раз 18 раз повторился последний байт первого сектора, потом пошел второй сектор и соотвественно 18 байт недокачались. А во второй раз вместо второго сектора туфта было 00 ff повторялися весь сектор. С чем это всвязано не понятно(.
     
  4. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.399
    Адрес:
    Fryazino
    drem1lin
    После чтения 512байт надо подождать 400нс пока DRQ изменится на 0, а после проверять снова статус готовности.
     
  5. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    296
    ТО есть когда встанет бит DRDY?