Порты ATA

Тема в разделе "WASM.ELECTRONICS", создана пользователем Asvald, 1 мар 2007.

  1. Asvald

    Asvald New Member

    Публикаций:
    0
    Регистрация:
    18 сен 2006
    Сообщения:
    58
    Скачал себе спецификацию команд ATA/ATAPI Command Set с www.t13.org. В ней все входные данные для команд описываются в виде:
    Код (Text):
    1. Word
    2.  00h Feature ...
    3.  01h Count   ...
    4.  02h LBA      ...
    5.  03h         ...
    6.  04h         ...
    7.  05h Device  ...
    А куда эти ворды писать, в какие порты, я так и не понял. Объясните кто знает.
     
  2. lukash

    lukash New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2006
    Сообщения:
    142
  3. Asvald

    Asvald New Member

    Публикаций:
    0
    Регистрация:
    18 сен 2006
    Сообщения:
    58
    Из статей "ATA для дZенствующих" я понял что все порты(кроме 1F0/170) 8 битные, как тогда в них записывать слова, последовательно по байту? Куда записывать 28-битный адрес сектора я понял, а куда писать 48-битный при LBA48? И отличается ли еще как-то LBA48 от LBA28 помимо разрядности адреса?
     
  4. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    Asvald
    Да отличается. Вопервых способом адрессации. Во вторых расхождения в командах есть, правда незначительно.
    Почитай на томже сайте там и про LBA48 расписано.
    Там чтобы записать вторые 24 нужно установить верхнии биты 28-25 в 111b (пишу по памяти могу путать).
     
  5. Asvald

    Asvald New Member

    Публикаций:
    0
    Регистрация:
    18 сен 2006
    Сообщения:
    58
    В некоторых источниках(например у Кулакова) пишется, что при чтении из порта 1F7h сбрасывается IRQ14, но не написано когда оно восстанавливается или это нужно делать вручную через порт 0A1h? У меня что-то никак не получается: прерывание генерируется только после первого чтения сектора через команду 20h, при дальнейших выполнениях этой команды(20h) данные с диска читаются, но IRQ14 не возникает.
     
  6. Asvald

    Asvald New Member

    Публикаций:
    0
    Регистрация:
    18 сен 2006
    Сообщения:
    58
    Код моей процедуры.

    Код (Text):
    1. Prim_base_port = 1F0h
    2. Sec_base_port = 170h
    3. Prim_base_alter_reg =3f6h
    4. Primary   = 0
    5. Secondary = 1F0h-170h
    6. ATA_StateReg = 7h
    7. ATA_CommandReg = 7h
    8. ATA_DeviceReg  = 6h
    9. ATA_BSY        = 80h
    10. ATA_DRDY       = 40h
    11. ATA_LBAHighReg =5h
    12. ATA_LBAMidReg  =4h
    13. ATA_LBALowReg  =3h
    14. ATA_CountReg   =2h
    15. ATA_FeatureReg =1h
    16. ATA_AlterStateReg =3f6h-376h
    17. ATA_WAIT_FOR_COMMAND   equ 20h,24h
    18. ATA_NO_WAIT_FOR_COMAND equ 30h
    19.  
    20.  
    21.  
    22. ;Посылает команды ATA устройствам
    23. ;Вход: ebx[15:0]  -  Count      1F2/172
    24. ;      ebx[31:16] -  Feature    1F1/171
    25. ;      edi[31:0]  -  LBA[31:0]  1F3,1F4,1F5/173,174,175
    26. ;      esi[31:16]  -  LBA[47:32]
    27. ;      ecx[15:8] -  Device     1F6/176
    28. ;      ecx[7:0] -  Command    1F7/177
    29. ;      esi[15:0] - канал Primary/Secondary
    30. ;      ecx[32]  - Если 0- Завершение команды произойдет по прерыванию
    31. ;                    1- Завершение команды ожидать не нужно, сразу вернуть управление
    32.  
    33. proc ATA_SendCommand
    34. mov dx,Prim_base_port
    35. sub dx,si   ;Выбор канала ATA
    36.  
    37.  
    38. add dx,ATA_StateReg   ;Ждем освобождения канала, если канал свободен, то BSY=0
    39. @@:           ;а если занят,то BSY=1
    40. in al,dx
    41. test al,ATA_BSY
    42. jnz @b
    43.  
    44.  
    45. mov eax,ecx ;Выбираем устройство на канале и ждем, когда
    46.         ;оно будет готово к приему команды(DRDY=0)
    47. shr eax,8      ;AL=Device
    48. sub dx,ATA_StateReg-ATA_DeviceReg
    49. out dx, al
    50.  
    51. add  dx,ATA_StateReg-ATA_DeviceReg
    52. @@:      ;Ждем, DRDY=1 и BSY=0
    53. in   al,dx
    54. test al,ATA_BSY      ;BSY=1?
    55. jnz  @b
    56. test al,ATA_DRDY     ;DRDY=1?
    57. jz   @b
    58.  
    59.  
    60. ;Загружаем LBA в следующей последовательности
    61. ;The host shall transmit bits 47:40 to the LBA High register.
    62. ;The host shall transmit bits 39:32 to the LBA Mid register.
    63. ;The host shall transmit bits 31:24 to the LBA Low register.
    64. ;The host shall transmit bits 23:16 to the LBA High register.
    65. ;The host shall transmit bits 15:8 to the LBA Mid register.
    66. ;The host shall transmit bits 7:0 to the LBA Low register.
    67.  
    68.  
    69. mov eax,esi
    70. shr eax,16       ;AH=LBA[47:40] AL=LBA[39:32]
    71. sub dx,ATA_StateReg-ATA_LBAHighReg
    72. xchg ah,al
    73. out dx,al
    74. sub dx,ATA_LBAHighReg-ATA_LBAMidReg
    75. xchg ah,al
    76. out dx,al
    77.  
    78. mov eax,edi
    79. push eax
    80. shr eax,16      ;AH=LBA[31:24] AL=LBA[23:16]
    81. sub dx,ATA_LBAMidReg-ATA_LBALowReg
    82. xchg ah,al
    83. out dx,al
    84. add dx,ATA_LBAHighReg-ATA_LBALowReg
    85. xchg ah,al
    86. out dx,al
    87.  
    88. pop eax          ;AH=LBA[15:8] AL=LBA[7:0]
    89. sub dx,ATA_LBAHighReg-ATA_LBAMidReg
    90. xchg ah,al
    91. out dx,al
    92. sub dx,ATA_LBAMidReg-ATA_LBALowReg
    93. xchg ah,al
    94. out dx,al
    95.  
    96. sub dx,ATA_LBALowReg-ATA_CountReg   ;записываем Count и Feature
    97. mov eax,ebx
    98. out dx,al
    99. xchg ah,al
    100. out dx,al
    101. ;shr ebx,16
    102. ;sub dx,ATA_CountReg-ATA_FeatureReg
    103. ;out dx,bl
    104. ;out dx,bh
    105.  
    106. test ecx,10000h
    107. jnz @f
    108. pop ebp
    109. mov eax,[esp]
    110. add esp,4   ;Очищаем стек
    111. mov [at_caller],eax
    112. mov [Wait_Flag],1
    113.  
    114. @@:
    115. mov eax,ecx ;Посылаем команду Al=Command
    116. add dx,ATA_CommandReg-ATA_CountReg
    117. out dx,al
    118.  
    119.  
    120. test ecx, 10000h
    121. jz @f
    122. retrn
    123.  
    124. @@:
    125.  
    126. ;Здесь произойдет прерывание 0Eh(14) сигнализирующее о том,
    127. ;что ATA устройство отработало и готово передавать или получать данные
    128. jmp $ ;Уходим в бесконечный цикл, но здесь должно быть перекючение на другую задачу
    129. retrn
    130. Wait_Flag dd 0 ;Флаг сигнализирующий о том, ожидается ли завершение операции
    131. at_caller dd 0 ;Адрес вызвавшего кода
     
  7. Asvald

    Asvald New Member

    Публикаций:
    0
    Регистрация:
    18 сен 2006
    Сообщения:
    58
    Все разобрался, проблема была в обработчике irq14, в котором я некорректно сбрасывал бит в ISR, поэтому все последующие irq14 были запрещены.
     
  8. afybc

    afybc New Member

    Публикаций:
    0
    Регистрация:
    30 июн 2006
    Сообщения:
    73
    Вопрос: процедура чтения секторов написанная для ATA-4 будет ли корректно работать с последующими версиями?
     
  9. Vov4ick

    Vov4ick Владимир

    Публикаций:
    0
    Регистрация:
    8 окт 2006
    Сообщения:
    581
    Адрес:
    МО
    Да, будет. Всё развитие IBM PC обеспесивает совместимость с предыдущими моделями.
     
  10. afybc

    afybc New Member

    Публикаций:
    0
    Регистрация:
    30 июн 2006
    Сообщения:
    73
    Спасибо за внимание. Еще пара вопросов.
    Вопрос №2:
    На какие порты проецируются "Data Port", "Alternate Status register-Device Control register"?
    Для остальных вроде нашёл:
    Код (Text):
    1. BASE                  = 0x1F0
    2. DATA_REG              = BASE + 0
    3. FEATURES_REG          = BASE + 0x1
    4. ERROR_REG             = BASE + 0x1
    5. SECTCOUNT_REG         = BASE + 0x2
    6. SECTNUM_REG           = BASE + 0x3
    7. CHIGH_REG             = BASE + 0x4
    8. CLOW_REG              = BASE + 0x5
    9. DEVICEHEAD_REG        = BASE + 0x6
    10. COMMAND_REG           = BASE + 0x7
    11. STATUS_REG            = BASE + 0x7
    Вопрос №3:
    В винде для первичного канала указан диапазон ввода/вывода 0x1F0-0x1F7 и 0x3F6. Так вот какой регистр отображается в 0x3F6?
     
  11. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Код (Text):
    1. #define HDD_PORT_DR_1   0x1F0 // Регистр данных. Только для PIO, младший байт
    2. #define HDD_PORT_DR_2   0x1F1 // Регистр данных. Только для PIO, старший байт, только запись
    3. #define HDD_PORT_ER     0x1F1 // Регистр ошибки. Только чтение. Содержит информацию при (SR & HDD_REG_SR_ERR) > 0
    4. #define HDD_PORT_FT     0x1F1 // Регистр свойств. Формат зависит от команды, только запись
    5. #define HDD_PORT_SC     0x1F2 // Количество секторов, если 0, то читается 256 секторов
    6. #define HDD_PORT_SN     0x1F3 // CHS: номер сектора, LBA: 0-7 биты
    7. #define HDD_PORT_CL     0x1F4 // CHS: номер циллиндра, младший байт, LBA: 8-15 биты
    8. #define HDD_PORT_CH     0x1F5 // CHS: номер циллиндра, старший байт, LBA: 16-23 биты
    9. #define HDD_PORT_DH     0x1F6 // Биты 0-3: CHS: номер головки, LBA: 24-27 биты. Бит 4: номер устройства. Бит 6: 0 - CHS, 1 - LBA
    10. #define HDD_PORT_SR     0x1F7 // Регистр состояния, только чтение
    11. #define HDD_PORT_CR     0x1F7 // Коммандный регистр, только запись
    12. #define HDD_PORT_AC     0x3F6 // Альтернативный регистр состояния, только чтение
     
  12. afybc

    afybc New Member

    Публикаций:
    0
    Регистрация:
    30 июн 2006
    Сообщения:
    73
    Пытаюсь прочитать первый сектор в ring0 и вылетает BSOD. Может кто подскажет что я делаю не так?
    Код (Text):
    1. include '%fasminc%\win32a.inc'
    2. format PE GUI
    3. entry DriverEntry
    4.  
    5.  
    6. BASE                  = 0x1F0
    7. DATA_REG              = BASE + 0
    8. FEATURES_REG          = BASE + 0x1
    9. ERROR_REG             = BASE + 0x1
    10. SECCOUNT_REG          = BASE + 0x2
    11. SECNUM_REG            = BASE + 0x3
    12. CHIGH_REG             = BASE + 0x4
    13. CLOW_REG              = BASE + 0x5
    14. DEVICEHEAD_REG        = BASE + 0x6
    15. COMMAND_REG           = BASE + 0x7
    16. STATUS_REG            = BASE + 0x7
    17. DEVICECTRL_REG        = 0x3F6
    18. ALTSTATUS_REG         = 0x3F6
    19.  
    20. ATA_READSECTOR        = 0x20
    21.  
    22. STATUS_ERR            = 0x1
    23. STATUS_DRQ            = 0x8
    24. STATUS_DRDY           = 0x40
    25. STATUS_BSY            = 0x80
    26.  
    27. DEVICEHEAD_DEV        = 0x10
    28.  
    29.  
    30.  
    31. ;___________________________________________________________________________________________
    32. section '.code' code readable writeable executable
    33.  
    34.   proc DriverEntry        pDriverObject,pusRegistryPath
    35.  
    36.  
    37.     mov         dx, DEVICECTRL_REG      ;|
    38.     mov         al, 0x2                 ;| - запрет прерываний
    39.     out         dx, al                  ;|
    40.  
    41.     mov         dx, STATUS_REG          ;|
    42.   @@:                                   ;|
    43.     in          al, dx                  ;|
    44.     test        al, STATUS_BSY          ;| - ожидание BSY=0 и DRQ=0
    45.     jnz         @b                      ;|
    46.     test        al, STATUS_DRQ          ;|
    47.     jnz         @b                      ;|
    48.  
    49.     mov         dx, DEVICEHEAD_REG      ;|
    50.     in          al, dx                  ;| - выбор Device0
    51.     and         al, not DEVICEHEAD_DEV  ;|
    52.     out         dx, al                  ;|
    53.  
    54.     mov         dx, STATUS_REG          ;|
    55.   @@:                                   ;|
    56.     in          al, dx                  ;|
    57.     test        al, STATUS_BSY          ;| - ожидание BSY=0 и DRQ=0
    58.     jnz         @b                      ;|
    59.     test        al, STATUS_DRQ          ;|
    60.     jnz         @b                      ;|
    61.  
    62.     mov         dx, SECCOUNT_REG        ;|
    63.     mov         al, 1                   ;| - количество секторов
    64.     out         dx, al                  ;|
    65.  
    66.     mov         dx, SECNUM_REG          ;|
    67.     mov         al, 1                   ;| - LBA [0..7]
    68.     out         dx, al                  ;|
    69.  
    70.     mov         dx, CLOW_REG            ;|
    71.     xor         al, al                  ;| - LBA [8..15]
    72.     out         dx, al                  ;|
    73.  
    74.     mov         dx, CHIGH_REG           ;|
    75.     xor         al, al                  ;| - LBA [17..23]
    76.     out         dx, al                  ;|
    77.  
    78.     mov         dx, DEVICEHEAD_REG      ;|
    79.     mov         al, 0x40                ;|
    80.     out         dx, al                  ;|
    81.  
    82.     mov         dx, STATUS_REG          ;|
    83.   @@:                                   ;|
    84.     in          al, dx                  ;|
    85.     test        al, STATUS_BSY          ;| - ожидание BSY=0 и DRQ=0
    86.     jnz         @b                      ;|
    87.     test        al, STATUS_DRQ          ;|
    88.     jnz         @b                      ;|
    89.  
    90.     mov         dx, COMMAND_REG         ;|
    91.     mov         al, ATA_READSECTOR      ;|
    92.     out         dx, al                  ;|
    93.  
    94.     mov         dx, ALTSTATUS_REG       ;|
    95.     in          al, dx                  ;|
    96.  
    97.     mov         dx, STATUS_REG          ;|
    98.   @@:                                   ;|
    99.     in          al, dx                  ;|
    100.     test        al, STATUS_BSY          ;| - ожидание BSY=0 и DRQ=1
    101.     jnz         @b                      ;|
    102.     test        al, STATUS_DRQ          ;|
    103.     jz         @b                       ;|
    104.  
    105.     mov         dx, DATA_REG            ;|
    106.     mov         edi, buffer             ;|
    107.     mov         ecx, 256                ;| - чтение данных
    108.     cld                                 ;|
    109.     rep insw                            ;|
    110.  
    111.     mov         dx, ALTSTATUS_REG       ;|
    112.     in          al, dx                  ;|
    113.  
    114.     mov         dx, STATUS_REG          ;|
    115.     in          al, dx                  ;|
    116.  
    117.     xor         eax,eax
    118.     not         eax
    119.     ret
    120.   endp
    121. ;___________________________________________________________________________________________
    122.  
    123. section '.data' data readable writeable
    124.   buffer rw 256
     
  13. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Код (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. }
     
  14. afybc

    afybc New Member

    Публикаций:
    0
    Регистрация:
    30 июн 2006
    Сообщения:
    73
    Спасибо за пример, но у меня под рукой нет DDK.. =(
     
  15. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Разве здесь нужен DDK?
    Все макросы и функции мои :P