Subversion Repositories Kolibri OS

Rev

Rev 4700 | Rev 5363 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 4734 $
  9.  
  10. ;-----------------------------------------------------------------------------
  11. ;**********************************************************
  12. ;  Непосредственная работа с устройством СD (ATAPI)
  13. ;**********************************************************
  14. ; Автор части исходного текста Кулаков Владимир Геннадьевич
  15. ; Адаптация, доработка и разработка Mario79,<Lrz>
  16.  
  17. ; Максимальное количество повторений операции чтения
  18. MaxRetr equ 10
  19. ; Предельное время ожидания готовности к приему команды
  20. ; (в тиках)
  21. BSYWaitTime equ 1000  ;2
  22. NoTickWaitTime equ 0xfffff
  23. CDBlockSize equ 2048
  24. ;********************************************
  25. ;*        ЧТЕНИЕ СЕКТОРА С ПОВТОРАМИ        *
  26. ;* Многократное повторение чтения при сбоях *
  27. ;********************************************
  28. ReadCDWRetr:
  29. ;-----------------------------------------------------------
  30. ; input  : eax = block to read
  31. ;          ebx = destination
  32. ;-----------------------------------------------------------
  33.         pushad
  34.         mov     eax, [CDSectorAddress]
  35.         mov     ebx, [CDDataBuf_pointer]
  36.         call    cd_calculate_cache
  37.         xor     edi, edi
  38.         add     esi, 8
  39.         inc     edi
  40. ;--------------------------------------
  41. align 4
  42. .hdreadcache:
  43.         cmp     [esi], eax      ; correct sector
  44.         je      .yeshdcache
  45.  
  46.         add     esi, 8
  47.         inc     edi
  48.         dec     ecx
  49.         jnz     .hdreadcache
  50.  
  51.         call    find_empty_slot_CD_cache ; ret in edi
  52.  
  53.         push    edi
  54.         push    eax
  55.         call    cd_calculate_cache_2
  56.         shl     edi, 11
  57.         add     edi, eax
  58.         mov     [CDDataBuf_pointer], edi
  59.         pop     eax
  60.         pop     edi
  61.  
  62.         call    ReadCDWRetr_1
  63.         cmp     [DevErrorCode], 0
  64.         jne     .exit
  65.  
  66.         mov     [CDDataBuf_pointer], ebx
  67.         call    cd_calculate_cache_1
  68.         lea     esi, [edi*8+esi]
  69.         mov     [esi], eax      ; sector number
  70. ;--------------------------------------
  71. .yeshdcache:
  72.         mov     esi, edi
  73.         shl     esi, 11 ;9
  74.         push    eax
  75.         call    cd_calculate_cache_2
  76.         add     esi, eax
  77.         pop     eax
  78.         mov     edi, ebx ;[CDDataBuf_pointer]
  79.         mov     ecx, 512 ;/4
  80.         cld
  81.         rep movsd               ; move data
  82. ;--------------------------------------
  83. .exit:
  84.         popad
  85.         ret
  86. ;-----------------------------------------------------------------------------
  87. ReadCDWRetr_1:
  88.         pushad
  89. ; Цикл, пока команда не выполнена успешно или не
  90. ; исчерпано количество попыток
  91.         mov     ecx, MaxRetr
  92. ;--------------------------------------
  93. align 4
  94. @@NextRetr:
  95. ; Подать команду
  96. ;*************************************************
  97. ;*      ПОЛНОЕ ЧТЕНИЕ СЕКТОРА КОМПАКТ-ДИСКА      *
  98. ;* Считываются данные пользователя, информация   *
  99. ;* субканала и контрольная информация            *
  100. ;* Входные параметры передаются через глобальные *
  101. ;* перменные:                                    *
  102. ;* ChannelNumber - номер канала;                 *
  103. ;* DiskNumber - номер диска на канале;           *
  104. ;* CDSectorAddress - адрес считываемого сектора. *
  105. ;* Данные считывается в массив CDDataBuf.        *
  106. ;*************************************************
  107. ;ReadCD:
  108.         push    ecx
  109. ; Очистить буфер пакетной команды
  110.         call    clear_packet_buffer
  111. ; Сформировать пакетную команду для считывания
  112. ; сектора данных
  113. ; Задать код команды Read CD
  114.         mov     [PacketCommand], byte 0x28 ;0xBE
  115. ; Задать адрес сектора
  116.         mov     ax, word [CDSectorAddress+2]
  117.         xchg    al, ah
  118.         mov     word [PacketCommand+2], ax
  119.         mov     ax, word [CDSectorAddress]
  120.         xchg    al, ah
  121.         mov     word [PacketCommand+4], ax
  122. ; Задать количество считываемых секторов
  123.         mov     [PacketCommand+8], byte 1
  124. ; Подать команду
  125.         call    SendPacketDatCommand
  126.         pop     ecx
  127.  
  128.         test    eax, eax
  129.         jz      @@End_4
  130.  
  131.         or      ecx, ecx        ;{SPraid.simba} (for cd load)
  132.         jz      @@End_4
  133.  
  134.         dec     ecx
  135.  
  136.         cmp     [timer_ticks_enable], 0
  137.         jne     @f
  138.  
  139.         mov     eax, NoTickWaitTime
  140. ;--------------------------------------
  141. align 4
  142. .wait:
  143.         dec     eax
  144.         jz      @@NextRetr
  145.  
  146.         jmp     .wait
  147. ;--------------------------------------
  148. align 4
  149. @@:
  150.         loop    @@NextRetr
  151. ;--------------------------------------
  152. @@End_4:
  153.         mov     dword [DevErrorCode], eax
  154.         popad
  155.         ret
  156. ;-----------------------------------------------------------------------------
  157. ; Универсальные процедуры, обеспечивающие выполнение
  158. ;             пакетных команд в режиме PIO
  159. ; Максимально допустимое время ожидания реакции
  160. ; устройства на пакетную команду (в тиках)
  161. ;-----------------------------------------------------------------------------
  162. MaxCDWaitTime equ 1000 ;200 ;10 секунд
  163. uglobal
  164. ; Область памяти для формирования пакетной команды
  165. PacketCommand:
  166.                  rb 12  ;DB 12 DUP (?)
  167. ; Адрес считываемого сектора данных
  168. CDSectorAddress:   dd ?
  169. ; Время начала очередной операции с диском
  170. TickCounter_1     dd 0
  171. ; Время начала ожидания готовности устройства
  172. WURStartTime      dd 0
  173. ; указатель буфера для считывания
  174. CDDataBuf_pointer dd 0
  175. endg
  176. ;-----------------------------------------------------------------------------
  177. ;****************************************************
  178. ;*    ПОСЛАТЬ УСТРОЙСТВУ ATAPI ПАКЕТНУЮ КОМАНДУ,    *
  179. ;* ПРЕДУСМАТРИВАЮЩУЮ ПЕРЕДАЧУ ОДНОГО СЕКТОРА ДАННЫХ *
  180. ;*     РАЗМЕРОМ 2048 БАЙТ ОТ УСТРОЙСТВА К ХОСТУ     *
  181. ;* Входные параметры передаются через глобальные    *
  182. ;* перменные:                                       *
  183. ;* ChannelNumber - номер канала;                    *
  184. ;* DiskNumber - номер диска на канале;              *
  185. ;* PacketCommand - 12-байтный командный пакет;      *
  186. ;* CDBlockSize - размер принимаемого блока данных.  *
  187. ; return eax DevErrorCode
  188. ;****************************************************
  189. SendPacketDatCommand:
  190.         xor     eax, eax
  191. ; Задать режим CHS
  192.         mov     byte [ATAAddressMode], al
  193. ; Послать ATA-команду передачи пакетной команды
  194.         mov     byte [ATAFeatures], al
  195.         mov     byte [ATASectorCount], al
  196.         mov     byte [ATASectorNumber], al
  197.         ; Загрузить размер передаваемого блока
  198.         mov     [ATAHead], al
  199.         mov     [ATACylinder], CDBlockSize
  200.         mov     [ATACommand], 0xA0
  201.         call    SendCommandToHDD_1
  202.         test    eax, eax
  203.         jnz     @@End_8    ;закончить, сохранив код ошибки
  204. ; Ожидание готовности дисковода к приему
  205. ; пакетной команды
  206.         mov     dx, [ATABasePortAddr]
  207.         add     dx, 7    ;порт 1х7h
  208.         mov     ecx, NoTickWaitTime
  209. ;--------------------------------------
  210. align 4
  211. @@WaitDevice0:
  212.         cmp     [timer_ticks_enable], 0
  213.         jne     @f
  214.  
  215.         dec     ecx
  216.         jz      @@Err1_1
  217.  
  218.         jmp     .test
  219. ;--------------------------------------
  220. align 4
  221. @@:
  222.         call    change_task
  223.         ; Проверить время выполнения команды
  224.         mov     eax, [timer_ticks]
  225.         sub     eax, [TickCounter_1]
  226.         cmp     eax, BSYWaitTime
  227.         ja      @@Err1_1   ;ошибка тайм-аута
  228.         ; Проверить готовность
  229. ;--------------------------------------
  230. align 4
  231. .test:
  232.         in      al, dx
  233.         test    al, 0x80  ;состояние сигнала BSY
  234.         jnz     @@WaitDevice0
  235.  
  236.         test    al, 1    ;состояние сигнала ERR
  237.         jnz     @@Err6
  238.  
  239.         test    al, 0x8  ;состояние сигнала DRQ
  240.         jz      @@WaitDevice0
  241. ; Послать пакетную команду
  242.         cli
  243.         mov     dx, [ATABasePortAddr]
  244.         mov     ax, [PacketCommand]
  245.         out     dx, ax
  246.         mov     ax, [PacketCommand+2]
  247.         out     dx, ax
  248.         mov     ax, [PacketCommand+4]
  249.         out     dx, ax
  250.         mov     ax, [PacketCommand+6]
  251.         out     dx, ax
  252.         mov     ax, [PacketCommand+8]
  253.         out     dx, ax
  254.         mov     ax, [PacketCommand+10]
  255.         out     dx, ax
  256.         sti
  257. ; Ожидание готовности данных
  258.         mov     dx, [ATABasePortAddr]
  259.         add     dx, 7  ;порт 1х7h
  260.         mov     ecx, NoTickWaitTime
  261. ;--------------------------------------
  262. align 4
  263. @@WaitDevice1:
  264.         cmp     [timer_ticks_enable], 0
  265.         jne     @f
  266.  
  267.         dec     ecx
  268.         jz      @@Err1_1
  269.  
  270.         jmp     .test_1
  271. ;--------------------------------------
  272. align 4
  273. @@:
  274.         call    change_task
  275.         ; Проверить время выполнения команды
  276.         mov     eax, [timer_ticks]
  277.         sub     eax, [TickCounter_1]
  278.         cmp     eax, MaxCDWaitTime
  279.         ja      @@Err1_1   ;ошибка тайм-аута
  280.         ; Проверить готовность
  281. ;--------------------------------------
  282. align 4
  283. .test_1:
  284.         in      al, dx
  285.         test    al, 0x80  ;состояние сигнала BSY
  286.         jnz     @@WaitDevice1
  287.  
  288.         test    al, 1    ;состояние сигнала ERR
  289.         jnz     @@Err6_temp
  290.  
  291.         test    al, 0x8  ;состояние сигнала DRQ
  292.         jz      @@WaitDevice1
  293. ; Принять блок данных от контроллера
  294.         mov     edi, [CDDataBuf_pointer]
  295.         ; Загрузить адрес регистра данных контроллера
  296.         mov     dx, [ATABasePortAddr]
  297.         ; Загрузить в счетчик размер блока в байтах
  298.         xor     ecx, ecx
  299.         mov     cx, CDBlockSize
  300.         ; Вычислить размер блока в 16-разрядных словах
  301.         shr     cx, 1 ;разделить размер блока на 2
  302.         ; Принять блок данных
  303.         cli
  304.         cld
  305.         rep insw
  306.         sti
  307. ;--------------------------------------
  308. ; Успешное завершение приема данных
  309. @@End_8:
  310.         xor     eax, eax
  311.         ret
  312. ;--------------------------------------
  313. ; Записать код ошибки
  314. @@Err1_1:
  315.         xor     eax, eax
  316.         inc     eax
  317.         ret
  318. ;--------------------------------------
  319. @@Err6_temp:
  320.         mov     eax, 7
  321.         ret
  322. ;--------------------------------------
  323. @@Err6:
  324.         mov     eax, 6
  325.         ret
  326. ;-----------------------------------------------------------------------------
  327. ;***********************************************
  328. ;*  ПОСЛАТЬ УСТРОЙСТВУ ATAPI ПАКЕТНУЮ КОМАНДУ, *
  329. ;*     НЕ ПРЕДУСМАТРИВАЮЩУЮ ПЕРЕДАЧИ ДАННЫХ    *
  330. ;* Входные параметры передаются через          *
  331. ;* глобальные перменные:                       *
  332. ;* ChannelNumber - номер канала;               *
  333. ;* DiskNumber - номер диска на канале;         *
  334. ;* PacketCommand - 12-байтный командный пакет. *
  335. ;***********************************************
  336. SendPacketNoDatCommand:
  337.         pushad
  338.         xor     eax, eax
  339. ; Задать режим CHS
  340.         mov     byte [ATAAddressMode], al
  341. ; Послать ATA-команду передачи пакетной команды
  342.         mov     byte [ATAFeatures], al
  343.         mov     byte [ATASectorCount], al
  344.         mov     byte [ATASectorNumber], al
  345.         mov     word [ATACylinder], ax
  346.         mov     byte [ATAHead], al
  347.         mov     [ATACommand], 0xA0
  348.         call    SendCommandToHDD_1
  349.         test    eax, eax
  350.         jnz     @@End_9  ;закончить, сохранив код ошибки
  351. ; Ожидание готовности дисковода к приему
  352. ; пакетной команды
  353.         mov     dx, [ATABasePortAddr]
  354.         add     dx, 7  ;порт 1х7h
  355. ;--------------------------------------
  356. align 4
  357. @@WaitDevice0_1:
  358.         call    change_task
  359.         ; Проверить время ожидания
  360.         mov     eax, [timer_ticks]
  361.         sub     eax, [TickCounter_1]
  362.         cmp     eax, BSYWaitTime
  363.         ja      @@Err1_3   ;ошибка тайм-аута
  364.         ; Проверить готовность
  365.         in      al, dx
  366.         test    al, 0x80  ;состояние сигнала BSY
  367.         jnz     @@WaitDevice0_1
  368.  
  369.         test    al, 1    ;состояние сигнала ERR
  370.         jnz     @@Err6_1
  371.  
  372.         test    al, 0x8  ;состояние сигнала DRQ
  373.         jz      @@WaitDevice0_1
  374. ; Послать пакетную команду
  375. ;        cli
  376.         mov     dx, [ATABasePortAddr]
  377.         mov     ax, word [PacketCommand]
  378.         out     dx, ax
  379.         mov     ax, word [PacketCommand+2]
  380.         out     dx, ax
  381.         mov     ax, word [PacketCommand+4]
  382.         out     dx, ax
  383.         mov     ax, word [PacketCommand+6]
  384.         out     dx, ax
  385.         mov     ax, word [PacketCommand+8]
  386.         out     dx, ax
  387.         mov     ax, word [PacketCommand+10]
  388.         out     dx, ax
  389. ;        sti
  390.         cmp     [ignore_CD_eject_wait], 1
  391.         je      @@clear_DEC
  392. ; Ожидание подтверждения приема команды
  393.         mov     dx, [ATABasePortAddr]
  394.         add     dx, 7  ;порт 1х7h
  395. ;--------------------------------------
  396. align 4
  397. @@WaitDevice1_1:
  398.         call    change_task
  399.         ; Проверить время выполнения команды
  400.         mov     eax, [timer_ticks]
  401.         sub     eax, [TickCounter_1]
  402.         cmp     eax, MaxCDWaitTime
  403.         ja      @@Err1_3   ;ошибка тайм-аута
  404.         ; Ожидать освобождения устройства
  405.         in      al, dx
  406.         test    al, 0x80  ;состояние сигнала BSY
  407.         jnz     @@WaitDevice1_1
  408.  
  409.         test    al, 1    ;состояние сигнала ERR
  410.         jnz     @@Err6_1
  411.  
  412.         test    al, 0x40  ;состояние сигнала DRDY
  413.         jz      @@WaitDevice1_1
  414. ;--------------------------------------
  415. @@clear_DEC:
  416.         and     [DevErrorCode], 0
  417.         popad
  418.         ret
  419. ;--------------------------------------
  420. ; Записать код ошибки
  421. @@Err1_3:
  422.         xor     eax, eax
  423.         inc     eax
  424.         jmp     @@End_9
  425. ;--------------------------------------
  426. @@Err6_1:
  427.         mov     eax, 6
  428. ;--------------------------------------
  429. @@End_9:
  430.         mov     [DevErrorCode], eax
  431.         popad
  432.         ret
  433. ;-----------------------------------------------------------------------------
  434. ;****************************************************
  435. ;*          ПОСЛАТЬ КОМАНДУ ЗАДАННОМУ ДИСКУ         *
  436. ;* Входные параметры передаются через глобальные    *
  437. ;* переменные:                                      *
  438. ;* ChannelNumber - номер канала (1 или 2);          *
  439. ;* DiskNumber - номер диска (0 или 1);              *
  440. ;* ATAFeatures - "особенности";                     *
  441. ;* ATASectorCount - количество секторов;            *
  442. ;* ATASectorNumber - номер начального сектора;      *
  443. ;* ATACylinder - номер начального цилиндра;         *
  444. ;* ATAHead - номер начальной головки;               *
  445. ;* ATAAddressMode - режим адресации (0-CHS, 1-LBA); *
  446. ;* ATACommand - код команды.                        *
  447. ;* После успешного выполнения функции:              *
  448. ;* в ATABasePortAddr - базовый адрес HDD;           *
  449. ;* в DevErrorCode - ноль.                           *
  450. ;* При возникновении ошибки в DevErrorCode будет    *
  451. ;* возвращен код ошибки в eax                       *
  452. ;****************************************************
  453. SendCommandToHDD_1:
  454. ; Проверить значение кода режима
  455.         cmp     [ATAAddressMode], 1
  456.         ja      @@Err2_4
  457. ; Проверить корректность номера канала
  458.         mov     bx, [ChannelNumber]
  459.         cmp     bx, 1
  460.         jb      @@Err3_4
  461.  
  462.         cmp     bx, 2
  463.         ja      @@Err3_4
  464. ; Установить базовый адрес
  465.         dec     bx
  466.         shl     ebx, 2
  467.         movzx   ebx, bx
  468.         mov     eax, [cdpos]
  469.         dec     eax
  470.         shr     eax, 2
  471.         imul    eax, sizeof.IDE_DATA
  472.         add     eax, IDE_controller_1
  473.         add     eax, ebx
  474.         mov     ax, [eax+IDE_DATA.BAR0_val]
  475.         mov     [ATABasePortAddr], ax
  476. ; Ожидание готовности HDD к приему команды
  477.         ; Выбрать нужный диск
  478.         mov     dx, [ATABasePortAddr]
  479.         add     dx, 6   ;адрес регистра головок
  480.         mov     al, [DiskNumber]
  481.         cmp     al, 1   ;проверить номера диска
  482.         ja      @@Err4_4
  483.  
  484.         shl     al, 4
  485.         or      al, 10100000b
  486.         out     dx, al
  487.         ; Ожидать, пока диск не будет готов
  488.         inc     dx
  489.         mov     eax, [timer_ticks]
  490.         mov     [TickCounter_1], eax
  491.         mov     ecx, NoTickWaitTime
  492. ;--------------------------------------
  493. align 4
  494. @@WaitHDReady_2:
  495.         cmp     [timer_ticks_enable], 0
  496.         jne     @f
  497.  
  498.         dec     ecx
  499.         jz      @@Err1_4
  500.  
  501.         jmp     .test
  502. ;--------------------------------------
  503. align 4
  504. @@:
  505.         call    change_task
  506.         ; Проверить время ожидания
  507.         mov     eax, [timer_ticks]
  508.         sub     eax, [TickCounter_1]
  509.         cmp     eax, BSYWaitTime ;300    ;ожидать 3 сек.
  510.         ja      @@Err1_4   ;ошибка тайм-аута
  511. ;--------------------------------------
  512. align 4
  513. .test:
  514.         in      al, dx ; Прочитать регистр состояния
  515.         ; Проверить состояние сигнала BSY
  516.         test    al, 0x80
  517.         jnz     @@WaitHDReady_2
  518.         ; Проверить состояние сигнала DRQ
  519.         test    al, 0x8
  520.         jnz     @@WaitHDReady_2
  521. ; Загрузить команду в регистры контроллера
  522.         cli
  523.         mov     dx, [ATABasePortAddr]
  524.         inc     dx      ;регистр "особенностей"
  525.         mov     al, [ATAFeatures]
  526.         out     dx, al
  527.         inc     dx      ;счетчик секторов
  528.         mov     al, [ATASectorCount]
  529.         out     dx, al
  530.         inc     dx      ;регистр номера сектора
  531.         mov     al, [ATASectorNumber]
  532.         out     dx, al
  533.         inc     dx      ;номер цилиндра (младший байт)
  534.         mov     ax, [ATACylinder]
  535.         out     dx, al
  536.         inc     dx      ;номер цилиндра (старший байт)
  537.         mov     al, ah
  538.         out     dx, al
  539.         inc     dx      ;номер головки/номер диска
  540.         mov     al, [DiskNumber]
  541.         shl     al, 4
  542.         cmp     [ATAHead], 0xF ;проверить номер головки
  543.         ja      @@Err5_4
  544.  
  545.         or      al, [ATAHead]
  546.         or      al, 10100000b
  547.         mov     ah, [ATAAddressMode]
  548.         shl     ah, 6
  549.         or      al, ah
  550.         out     dx, al
  551. ; Послать команду
  552.         mov     al, [ATACommand]
  553.         inc     dx      ;регистр команд
  554.         out     dx, al
  555.         sti
  556. ;--------------------------------------
  557. @@End_10:
  558.         xor     eax, eax
  559.         ret
  560. ;--------------------------------------
  561. ; Записать код ошибки
  562. @@Err1_4:
  563.         xor     eax, eax
  564.         inc     eax
  565.         ret
  566. ;--------------------------------------
  567. @@Err2_4:
  568.         mov     eax, 2
  569.         ret
  570. ;--------------------------------------
  571. @@Err3_4:
  572.         mov     eax, 3
  573.         ret
  574. ;--------------------------------------
  575. @@Err4_4:
  576.         mov     eax, 4
  577.         ret
  578. ;--------------------------------------
  579. @@Err5_4:
  580.         mov     eax, 5
  581.         ret
  582. ;-----------------------------------------------------------------------------
  583. ;*************************************************
  584. ;*    ОЖИДАНИЕ ГОТОВНОСТИ УСТРОЙСТВА К РАБОТЕ    *
  585. ;* Входные параметры передаются через глобальные *
  586. ;* перменные:                                    *
  587. ;* ChannelNumber - номер канала;                 *
  588. ;* DiskNumber - номер диска на канале.           *
  589. ;*************************************************
  590. WaitUnitReady:
  591.         pusha
  592. ; Запомнить время начала операции
  593.         mov     eax, [timer_ticks]
  594.         mov     [WURStartTime], eax
  595. ; Очистить буфер пакетной команды
  596.         call    clear_packet_buffer
  597. ; Сформировать команду TEST UNIT READY
  598.         mov     [PacketCommand], word 0
  599. ; ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ УСТРОЙСТВА
  600.         mov     ecx, NoTickWaitTime
  601. ;--------------------------------------
  602. align 4
  603. @@SendCommand:
  604.         ; Подать команду проверки готовности
  605.         call    SendPacketNoDatCommand
  606.         cmp     [timer_ticks_enable], 0
  607.         jne     @f
  608.  
  609.         cmp     [DevErrorCode], 0
  610.         je      @@End_11
  611.  
  612.         dec     ecx
  613.         jz      .Error
  614.  
  615.         jmp     @@SendCommand
  616. ;--------------------------------------
  617. align 4
  618. @@:
  619.         call    change_task
  620.         ; Проверить код ошибки
  621.         cmp     [DevErrorCode], 0
  622.         je      @@End_11
  623.         ; Проверить время ожидания готовности
  624.         mov     eax, [timer_ticks]
  625.         sub     eax, [WURStartTime]
  626.         cmp     eax, MaxCDWaitTime
  627.         jb      @@SendCommand
  628. ;--------------------------------------
  629. .Error:
  630.         ; Ошибка тайм-аута
  631.         mov     [DevErrorCode], 1
  632. ;--------------------------------------
  633. @@End_11:
  634.         popa
  635.         ret
  636. ;-----------------------------------------------------------------------------
  637. ;*************************************************
  638. ;*            ЗАПРЕТИТЬ СМЕНУ ДИСКА              *
  639. ;* Входные параметры передаются через глобальные *
  640. ;* перменные:                                    *
  641. ;* ChannelNumber - номер канала;                 *
  642. ;* DiskNumber - номер диска на канале.           *
  643. ;*************************************************
  644. prevent_medium_removal:
  645.         pusha
  646. ; Очистить буфер пакетной команды
  647.         call    clear_packet_buffer
  648. ; Задать код команды
  649.         mov     [PacketCommand], byte 0x1E
  650. ; Задать код запрета
  651.         mov     [PacketCommand+4], byte 11b
  652. ; Подать команду
  653.         call    SendPacketNoDatCommand
  654.         mov     eax, ATAPI_IDE0_lock
  655.         add     eax, [cdpos]
  656.         dec     eax
  657.         mov     [eax], byte 1
  658.         popa
  659.         ret
  660. ;-----------------------------------------------------------------------------
  661. ;*************************************************
  662. ;*            РАЗРЕШИТЬ СМЕНУ ДИСКА              *
  663. ;* Входные параметры передаются через глобальные *
  664. ;* перменные:                                    *
  665. ;* ChannelNumber - номер канала;                 *
  666. ;* DiskNumber - номер диска на канале.           *
  667. ;*************************************************
  668. allow_medium_removal:
  669.         pusha
  670. ; Очистить буфер пакетной команды
  671.         call    clear_packet_buffer
  672. ; Задать код команды
  673.         mov     [PacketCommand], byte 0x1E
  674. ; Задать код запрета
  675.         mov     [PacketCommand+4], byte 0
  676. ; Подать команду
  677.         call    SendPacketNoDatCommand
  678.         mov     eax, ATAPI_IDE0_lock
  679.         add     eax, [cdpos]
  680.         dec     eax
  681.         mov     [eax], byte 0
  682.         popa
  683.         ret
  684. ;-----------------------------------------------------------------------------
  685. ;*************************************************
  686. ;*         ЗАГРУЗИТЬ НОСИТЕЛЬ В ДИСКОВОД         *
  687. ;* Входные параметры передаются через глобальные *
  688. ;* перменные:                                    *
  689. ;* ChannelNumber - номер канала;                 *
  690. ;* DiskNumber - номер диска на канале.           *
  691. ;*************************************************
  692. LoadMedium:
  693.         pusha
  694. ; Очистить буфер пакетной команды
  695.         call    clear_packet_buffer
  696. ; Сформировать команду START/STOP UNIT
  697.         ; Задать код команды
  698.         mov     [PacketCommand], word 0x1B
  699.         ; Задать операцию загрузки носителя
  700.         mov     [PacketCommand+4], word 00000011b
  701. ; Подать команду
  702.         call    SendPacketNoDatCommand
  703.         popa
  704.         ret
  705. ;-----------------------------------------------------------------------------
  706. ;*************************************************
  707. ;*         ИЗВЛЕЧЬ НОСИТЕЛЬ ИЗ ДИСКОВОДА         *
  708. ;* Входные параметры передаются через глобальные *
  709. ;* перменные:                                    *
  710. ;* ChannelNumber - номер канала;                 *
  711. ;* DiskNumber - номер диска на канале.           *
  712. ;*************************************************
  713. EjectMedium:
  714.         pusha
  715. ; Очистить буфер пакетной команды
  716.         call    clear_packet_buffer
  717. ; Сформировать команду START/STOP UNIT
  718.         ; Задать код команды
  719.         mov     [PacketCommand], word 0x1B
  720.         ; Задать операцию извлечения носителя
  721.         mov     [PacketCommand+4], word 00000010b
  722. ; Подать команду
  723.         call    SendPacketNoDatCommand
  724.         popa
  725.         ret
  726. ;-----------------------------------------------------------------------------
  727. ;*************************************************
  728. ;* Проверить событие нажатия кнопки извлечения   *
  729. ;*                     диска                     *
  730. ;* Входные параметры передаются через глобальные *
  731. ;* переменные:                                   *
  732. ;* ChannelNumber - номер канала;                 *
  733. ;* DiskNumber - номер диска на канале.           *
  734. ;*************************************************
  735. proc check_ATAPI_device_event_has_work?
  736.         mov     eax, [timer_ticks]
  737.         sub     eax, [timer_ATAPI_check]
  738.         cmp     eax, 100
  739.         jb      .no
  740.  
  741.         xor     eax, eax
  742.         inc     eax
  743.         ret
  744. ;--------------------------------------
  745. .no:
  746.         xor     eax, eax
  747.         ret
  748. endp
  749. ;-----------------------------------------------------------------------------
  750. align 4
  751. check_ATAPI_device_event:
  752.         pusha
  753.         mov     eax, [timer_ticks]
  754.         sub     eax, [timer_ATAPI_check]
  755.         cmp     eax, 100
  756.         jb      .end_1
  757.  
  758.         pushfd
  759.         mov     al, [DRIVE_DATA+1]
  760.         and     al, 11b
  761.         cmp     al, 10b
  762.         jz      .ide3
  763. ;--------------------------------------
  764. .ide2_1:
  765.         mov     al, [DRIVE_DATA+1]
  766.         and     al, 1100b
  767.         cmp     al, 1000b
  768.         jz      .ide2
  769. ;--------------------------------------
  770. .ide1_1:
  771.         mov     al, [DRIVE_DATA+1]
  772.         and     al, 110000b
  773.         cmp     al, 100000b
  774.         jz      .ide1
  775. ;--------------------------------------
  776. .ide0_1:
  777.         mov     al, [DRIVE_DATA+1]
  778.         and     al, 11000000b
  779.         cmp     al, 10000000b
  780.         jz      .ide0
  781. ;--------------------------------------
  782. .ide7_1:
  783.         mov     al, [DRIVE_DATA+6]
  784.         and     al, 11b
  785.         cmp     al, 10b
  786.         jz      .ide7
  787. ;--------------------------------------
  788. .ide6_1:
  789.         mov     al, [DRIVE_DATA+6]
  790.         and     al, 1100b
  791.         cmp     al, 1000b
  792.         jz      .ide6
  793. ;--------------------------------------
  794. .ide5_1:
  795.         mov     al, [DRIVE_DATA+6]
  796.         and     al, 110000b
  797.         cmp     al, 100000b
  798.         jz      .ide5
  799. ;--------------------------------------
  800. .ide4_1:
  801.         mov     al, [DRIVE_DATA+6]
  802.         and     al, 11000000b
  803.         cmp     al, 10000000b
  804.         jz      .ide4
  805. ;--------------------------------------
  806. .ide11_1:
  807.         mov     al, [DRIVE_DATA+11]
  808.         and     al, 11b
  809.         cmp     al, 10b
  810.         jz      .ide11
  811. ;--------------------------------------
  812. .ide10_1:
  813.         mov     al, [DRIVE_DATA+11]
  814.         and     al, 1100b
  815.         cmp     al, 1000b
  816.         jz      .ide10
  817. ;--------------------------------------
  818. .ide9_1:
  819.         mov     al, [DRIVE_DATA+11]
  820.         and     al, 110000b
  821.         cmp     al, 100000b
  822.         jz      .ide9
  823. ;--------------------------------------
  824. .ide8_1:
  825.         mov     al, [DRIVE_DATA+11]
  826.         and     al, 11000000b
  827.         cmp     al, 10000000b
  828.         jz      .ide8
  829. ;--------------------------------------
  830. .end:
  831.         popfd
  832.         mov     eax, [timer_ticks]
  833.         mov     [timer_ATAPI_check], eax
  834. ;--------------------------------------
  835. .end_1:
  836.         popa
  837.         ret
  838. ;-----------------------------------------------------------------------------
  839. .ide3:
  840.         cli
  841.         cmp     [ATAPI_IDE3_lock], 1
  842.         jne     .ide2_1
  843.  
  844.         cmp     [cd_status], 0
  845.         jne     .end
  846.  
  847.         mov     ecx, ide_channel2_mutex
  848.         call    mutex_lock
  849.         call    reserve_ok2
  850.         mov     [ChannelNumber], 2
  851.         mov     [DiskNumber], 1
  852.         mov     [cdpos], 4
  853.         call    GetEvent_StatusNotification
  854.         cmp     [CDDataBuf+4], byte 1
  855.         jne     @f
  856.  
  857.         call    .eject
  858. ;--------------------------------------
  859. @@:
  860.         call    syscall_cdaudio.free
  861.         jmp     .ide2_1
  862. ;-----------------------------------------------------------------------------
  863. .ide2:
  864.         cli
  865.         cmp     [ATAPI_IDE2_lock], 1
  866.         jne     .ide1_1
  867.  
  868.         cmp     [cd_status], 0
  869.         jne     .end
  870.  
  871.         mov     ecx, ide_channel2_mutex
  872.         call    mutex_lock
  873.         call    reserve_ok2
  874.         mov     [ChannelNumber], 2
  875.         mov     [DiskNumber], 0
  876.         mov     [cdpos], 3
  877.         call    GetEvent_StatusNotification
  878.         cmp     [CDDataBuf+4], byte 1
  879.         jne     @f
  880.  
  881.         call    .eject
  882. ;--------------------------------------
  883. @@:
  884.         call    syscall_cdaudio.free
  885.         jmp     .ide1_1
  886. ;-----------------------------------------------------------------------------
  887. .ide1:
  888.         cli
  889.         cmp     [ATAPI_IDE1_lock], 1
  890.         jne     .ide0_1
  891.  
  892.         cmp     [cd_status], 0
  893.         jne     .end
  894.  
  895.         mov     ecx, ide_channel1_mutex
  896.         call    mutex_lock
  897.         call    reserve_ok2
  898.         mov     [ChannelNumber], 1
  899.         mov     [DiskNumber], 1
  900.         mov     [cdpos], 2
  901.         call    GetEvent_StatusNotification
  902.         cmp     [CDDataBuf+4], byte 1
  903.         jne     @f
  904.  
  905.         call    .eject
  906. ;--------------------------------------
  907. @@:
  908.         call    syscall_cdaudio.free
  909.         jmp     .ide0_1
  910. ;-----------------------------------------------------------------------------
  911. .ide0:
  912.         cli
  913.         cmp     [ATAPI_IDE0_lock], 1
  914.         jne     .ide7_1
  915.  
  916.         cmp     [cd_status], 0
  917.         jne     .end
  918.  
  919.         mov     ecx, ide_channel1_mutex
  920.         call    mutex_lock
  921.         call    reserve_ok2
  922.         mov     [ChannelNumber], 1
  923.         mov     [DiskNumber], 0
  924.         mov     [cdpos], 1
  925.         call    GetEvent_StatusNotification
  926.         cmp     [CDDataBuf+4], byte 1
  927.         jne     @f
  928.  
  929.         call    .eject
  930. ;--------------------------------------
  931. @@:
  932.         call    syscall_cdaudio.free
  933.         jmp     .ide7_1
  934. ;-----------------------------------------------------------------------------
  935. .ide7:
  936.         cli
  937.         cmp     [ATAPI_IDE7_lock], 1
  938.         jne     .ide6_1
  939.  
  940.         cmp     [cd_status], 0
  941.         jne     .end
  942.  
  943.         mov     ecx, ide_channel4_mutex
  944.         call    mutex_lock
  945.         call    reserve_ok2
  946.         mov     [ChannelNumber], 2
  947.         mov     [DiskNumber], 1
  948.         mov     [cdpos], 8
  949.         call    GetEvent_StatusNotification
  950.         cmp     [CDDataBuf+4], byte 1
  951.         jne     @f
  952.  
  953.         call    .eject
  954. ;--------------------------------------
  955. @@:
  956.         call    syscall_cdaudio.free
  957.         jmp     .ide6_1
  958. ;-----------------------------------------------------------------------------
  959. .ide6:
  960.         cli
  961.         cmp     [ATAPI_IDE6_lock], 1
  962.         jne     .ide5_1
  963.  
  964.         cmp     [cd_status], 0
  965.         jne     .end
  966.  
  967.         mov     ecx, ide_channel4_mutex
  968.         call    mutex_lock
  969.         call    reserve_ok2
  970.         mov     [ChannelNumber], 2
  971.         mov     [DiskNumber], 0
  972.         mov     [cdpos], 7
  973.         call    GetEvent_StatusNotification
  974.         cmp     [CDDataBuf+4], byte 1
  975.         jne     @f
  976.  
  977.         call    .eject
  978. ;--------------------------------------
  979. @@:
  980.         call    syscall_cdaudio.free
  981.         jmp     .ide5_1
  982. ;-----------------------------------------------------------------------------
  983. .ide5:
  984.         cli
  985.         cmp     [ATAPI_IDE5_lock], 1
  986.         jne     .ide4_1
  987.  
  988.         cmp     [cd_status], 0
  989.         jne     .end
  990.  
  991.         mov     ecx, ide_channel3_mutex
  992.         call    mutex_lock
  993.         call    reserve_ok2
  994.         mov     [ChannelNumber], 1
  995.         mov     [DiskNumber], 1
  996.         mov     [cdpos], 6
  997.         call    GetEvent_StatusNotification
  998.         cmp     [CDDataBuf+4], byte 1
  999.         jne     @f
  1000.  
  1001.         call    .eject
  1002. ;--------------------------------------
  1003. @@:
  1004.         call    syscall_cdaudio.free
  1005.         jmp     .ide4_1
  1006. ;-----------------------------------------------------------------------------
  1007. .ide4:
  1008.         cli
  1009.         cmp     [ATAPI_IDE4_lock], 1
  1010.         jne     .ide11_1
  1011.  
  1012.         cmp     [cd_status], 0
  1013.         jne     .end
  1014.  
  1015.         mov     ecx, ide_channel3_mutex
  1016.         call    mutex_lock
  1017.         call    reserve_ok2
  1018.         mov     [ChannelNumber], 1
  1019.         mov     [DiskNumber], 0
  1020.         mov     [cdpos], 5
  1021.         call    GetEvent_StatusNotification
  1022.         cmp     [CDDataBuf+4], byte 1
  1023.         jne     @f
  1024.  
  1025.         call    .eject
  1026. ;--------------------------------------
  1027. @@:
  1028.         call    syscall_cdaudio.free
  1029.         jmp     .ide11_1
  1030. ;-----------------------------------------------------------------------------
  1031. .ide11:
  1032.         cli
  1033.         cmp     [ATAPI_IDE11_lock], 1
  1034.         jne     .ide10_1
  1035.  
  1036.         cmp     [cd_status], 0
  1037.         jne     .end
  1038.  
  1039.         mov     ecx, ide_channel6_mutex
  1040.         call    mutex_lock
  1041.         call    reserve_ok2
  1042.         mov     [ChannelNumber], 2
  1043.         mov     [DiskNumber], 1
  1044.         mov     [cdpos], 12
  1045.         call    GetEvent_StatusNotification
  1046.         cmp     [CDDataBuf+4], byte 1
  1047.         jne     @f
  1048.  
  1049.         call    .eject
  1050. ;--------------------------------------
  1051. @@:
  1052.         call    syscall_cdaudio.free
  1053.         jmp     .ide10_1
  1054. ;-----------------------------------------------------------------------------
  1055. .ide10:
  1056.         cli
  1057.         cmp     [ATAPI_IDE10_lock], 1
  1058.         jne     .ide9_1
  1059.  
  1060.         cmp     [cd_status], 0
  1061.         jne     .end
  1062.  
  1063.         mov     ecx, ide_channel6_mutex
  1064.         call    mutex_lock
  1065.         call    reserve_ok2
  1066.         mov     [ChannelNumber], 2
  1067.         mov     [DiskNumber], 0
  1068.         mov     [cdpos], 11
  1069.         call    GetEvent_StatusNotification
  1070.         cmp     [CDDataBuf+4], byte 1
  1071.         jne     @f
  1072.  
  1073.         call    .eject
  1074. ;--------------------------------------
  1075. @@:
  1076.         call    syscall_cdaudio.free
  1077.         jmp     .ide9_1
  1078. ;-----------------------------------------------------------------------------
  1079. .ide9:
  1080.         cli
  1081.         cmp     [ATAPI_IDE9_lock], 1
  1082.         jne     .ide8_1
  1083.  
  1084.         cmp     [cd_status], 0
  1085.         jne     .end
  1086.  
  1087.         mov     ecx, ide_channel5_mutex
  1088.         call    mutex_lock
  1089.         call    reserve_ok2
  1090.         mov     [ChannelNumber], 1
  1091.         mov     [DiskNumber], 1
  1092.         mov     [cdpos], 10
  1093.         call    GetEvent_StatusNotification
  1094.         cmp     [CDDataBuf+4], byte 1
  1095.         jne     @f
  1096.  
  1097.         call    .eject
  1098. ;--------------------------------------
  1099. @@:
  1100.         call    syscall_cdaudio.free
  1101.         jmp     .ide8_1
  1102. ;-----------------------------------------------------------------------------
  1103. .ide8:
  1104.         cli
  1105.         cmp     [ATAPI_IDE8_lock], 1
  1106.         jne     .end
  1107.  
  1108.         cmp     [cd_status], 0
  1109.         jne     .end
  1110.  
  1111.         mov     ecx, ide_channel5_mutex
  1112.         call    mutex_lock
  1113.         call    reserve_ok2
  1114.         mov     [ChannelNumber], 1
  1115.         mov     [DiskNumber], 0
  1116.         mov     [cdpos], 9
  1117.         call    GetEvent_StatusNotification
  1118.         cmp     [CDDataBuf+4], byte 1
  1119.         jne     @f
  1120.  
  1121.         call    .eject
  1122. ;--------------------------------------
  1123. @@:
  1124.         call    syscall_cdaudio.free
  1125.         jmp     .end
  1126. ;-----------------------------------------------------------------------------
  1127. .eject:
  1128.         call    clear_CD_cache
  1129.         call    allow_medium_removal
  1130.         mov     [ignore_CD_eject_wait], 1
  1131.         call    EjectMedium
  1132.         mov     [ignore_CD_eject_wait], 0
  1133.         ret
  1134. ;-----------------------------------------------------------------------------
  1135. iglobal
  1136. timer_ATAPI_check dd 0
  1137. ATAPI_IDE0_lock db 0
  1138. ATAPI_IDE1_lock db 0
  1139. ATAPI_IDE2_lock db 0
  1140. ATAPI_IDE3_lock db 0
  1141. ATAPI_IDE4_lock db 0
  1142. ATAPI_IDE5_lock db 0
  1143. ATAPI_IDE6_lock db 0
  1144. ATAPI_IDE7_lock db 0
  1145. ATAPI_IDE8_lock db 0
  1146. ATAPI_IDE9_lock db 0
  1147. ATAPI_IDE10_lock db 0
  1148. ATAPI_IDE11_lock db 0
  1149. ignore_CD_eject_wait db 0
  1150. endg
  1151. ;-----------------------------------------------------------------------------
  1152. ;*************************************************
  1153. ;* Получить сообщение о событии или состоянии    *
  1154. ;*                  устройства                   *
  1155. ;* Входные параметры передаются через глобальные *
  1156. ;* переменные:                                   *
  1157. ;* ChannelNumber - номер канала;                 *
  1158. ;* DiskNumber - номер диска на канале.           *
  1159. ;*************************************************
  1160. GetEvent_StatusNotification:
  1161.         pusha
  1162.         mov     [CDDataBuf_pointer], CDDataBuf
  1163. ; Очистить буфер пакетной команды
  1164.         call    clear_packet_buffer
  1165. ; Задать код команды
  1166.         mov     [PacketCommand], byte 4Ah
  1167.         mov     [PacketCommand+1], byte 00000001b
  1168. ; Задать запрос класса сообщений
  1169.         mov     [PacketCommand+4], byte 00010000b
  1170. ; Размер выделенной области
  1171.         mov     [PacketCommand+7], byte 8h
  1172.         mov     [PacketCommand+8], byte 0h
  1173. ; Подать команду
  1174.         call    SendPacketDatCommand
  1175.         popa
  1176.         ret
  1177. ;-----------------------------------------------------------------------------
  1178. ;*************************************************
  1179. ; прочитать информацию из TOC
  1180. ;* Входные параметры передаются через глобальные *
  1181. ;* переменные:                                   *
  1182. ;* ChannelNumber - номер канала;                 *
  1183. ;* DiskNumber - номер диска на канале.           *
  1184. ;*************************************************
  1185. Read_TOC:
  1186.         pusha
  1187.         mov     [CDDataBuf_pointer], CDDataBuf
  1188. ; Очистить буфер пакетной команды
  1189.         call    clear_packet_buffer
  1190. ; Сформировать пакетную команду для считывания
  1191. ; сектора данных
  1192.         mov     [PacketCommand], byte 0x43
  1193.         ; Задать формат
  1194.         mov     [PacketCommand+2], byte 1
  1195. ; Размер выделенной области
  1196.         mov     [PacketCommand+7], byte 0xFF
  1197.         mov     [PacketCommand+8], byte 0h
  1198. ; Подать команду
  1199.         call    SendPacketDatCommand
  1200.         popa
  1201.         ret
  1202. ;-----------------------------------------------------------------------------
  1203. ;*************************************************
  1204. ;* ОПРЕДЕЛИТЬ ОБЩЕЕ КОЛИЧЕСТВО СЕКТОРОВ НА ДИСКЕ *
  1205. ;* Входные параметры передаются через глобальные *
  1206. ;* переменные:                                   *
  1207. ;* ChannelNumber - номер канала;                 *
  1208. ;* DiskNumber - номер диска на канале.           *
  1209. ;*************************************************
  1210. ;ReadCapacity:
  1211. ;       pusha
  1212. ;; Очистить буфер пакетной команды
  1213. ;       call  clear_packet_buffer
  1214. ;; Задать размер буфера в байтах
  1215. ;       mov     [CDBlockSize],8
  1216. ;; Сформировать команду READ CAPACITY
  1217. ;       mov     [PacketCommand],word 25h
  1218. ;; Подать команду
  1219. ;       call    SendPacketDatCommand
  1220. ;       popa
  1221. ;       ret
  1222. ;-----------------------------------------------------------------------------
  1223. clear_packet_buffer:
  1224. ; Очистить буфер пакетной команды
  1225.         and     [PacketCommand], dword 0
  1226.         and     [PacketCommand+4], dword 0
  1227.         and     [PacketCommand+8], dword 0
  1228.         ret
  1229. ;-----------------------------------------------------------------------------
  1230.