Subversion Repositories Kolibri OS

Rev

Rev 3534 | Rev 4700 | 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: 3539 $
  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. .hdreadcache:
  41. ;    cmp   dword [esi+4],0       ; empty
  42. ;    je    .nohdcache
  43.         cmp     [esi], eax      ; correct sector
  44.         je      .yeshdcache
  45. .nohdcache:
  46.         add     esi, 8
  47.         inc     edi
  48.         dec     ecx
  49.         jnz     .hdreadcache
  50.         call    find_empty_slot_CD_cache ; ret in edi
  51.  
  52.         push    edi
  53.         push    eax
  54.         call    cd_calculate_cache_2
  55.         shl     edi, 11
  56.         add     edi, eax
  57.         mov     [CDDataBuf_pointer], edi
  58.         pop     eax
  59.         pop     edi
  60.  
  61.         call    ReadCDWRetr_1
  62.         cmp     [DevErrorCode], 0
  63.         jne     .exit
  64.  
  65.         mov     [CDDataBuf_pointer], ebx
  66.         call    cd_calculate_cache_1
  67.         lea     esi, [edi*8+esi]
  68.         mov     [esi], eax      ; sector number
  69. ;    mov   dword [esi+4],1       ; hd read - mark as same as in hd
  70. .yeshdcache:
  71.         mov     esi, edi
  72.         shl     esi, 11;9
  73.         push    eax
  74.         call    cd_calculate_cache_2
  75.         add     esi, eax
  76.         pop     eax
  77.         mov     edi, ebx;[CDDataBuf_pointer]
  78.         mov     ecx, 512;/4
  79.         cld
  80.         rep movsd               ; move data
  81. .exit:
  82.         popad
  83.         ret
  84.  
  85. ReadCDWRetr_1:
  86.         pushad
  87.  
  88. ; Цикл, пока команда не выполнена успешно или не
  89. ; исчерпано количество попыток
  90.         mov     ECX, MaxRetr
  91. @@NextRetr:
  92. ; Подать команду
  93. ;*************************************************
  94. ;*      ПОЛНОЕ ЧТЕНИЕ СЕКТОРА КОМПАКТ-ДИСКА      *
  95. ;* Считываются данные пользователя, информация   *
  96. ;* субканала и контрольная информация            *
  97. ;* Входные параметры передаются через глобальные *
  98. ;* перменные:                                    *
  99. ;* ChannelNumber - номер канала;                 *
  100. ;* DiskNumber - номер диска на канале;           *
  101. ;* CDSectorAddress - адрес считываемого сектора. *
  102. ;* Данные считывается в массив CDDataBuf.        *
  103. ;*************************************************
  104. ;ReadCD:
  105.         push    ecx
  106. ;        pusha
  107. ; Задать размер сектора
  108. ;        mov       [CDBlockSize],2048 ;2352
  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. ;        mov   eax,[CDSectorAddress]
  123. ;        mov   [PacketCommand+2],eax
  124. ; Задать количество считываемых секторов
  125.         mov     [PacketCommand+8], byte 1
  126. ; Задать считывание данных в полном объеме
  127. ;        mov     [PacketCommand+9],byte 0xF8
  128. ; Подать команду
  129.         call    SendPacketDatCommand
  130.         pop     ecx
  131. ;        ret
  132.  
  133. ;        cmp       [DevErrorCode],0
  134.         test    eax, eax
  135.         jz      @@End_4
  136.  
  137.         or      ecx, ecx        ;{SPraid.simba} (for cd load)
  138.         jz      @@End_4
  139.         dec     ecx
  140.  
  141.         cmp     [timer_ticks_enable], 0
  142.         jne     @f
  143.         mov     eax, NoTickWaitTime
  144. .wait:
  145.         dec     eax
  146. ;        test  eax,eax
  147.         jz      @@NextRetr
  148.         jmp     .wait
  149. @@:
  150. ; Задержка на 2,5 секунды
  151. ;       mov     EAX,[timer_ticks]
  152. ;       add     EAX,50  ;250
  153. ;@@Wait:
  154. ;       call    change_task
  155. ;       cmp     EAX,[timer_ticks]
  156. ;       ja      @@Wait
  157.         loop    @@NextRetr
  158. @@End_4:
  159.         mov     dword [DevErrorCode], eax
  160.         popad
  161.         ret
  162.  
  163.  
  164. ; Универсальные процедуры, обеспечивающие выполнение
  165. ;             пакетных команд в режиме PIO
  166.  
  167. ; Максимально допустимое время ожидания реакции
  168. ; устройства на пакетную команду (в тиках)
  169.  
  170. MaxCDWaitTime equ 1000 ;200 ;10 секунд
  171. uglobal
  172. ; Область памяти для формирования пакетной команды
  173. PacketCommand:
  174.                  rb 12  ;DB 12 DUP (?)
  175. ; Область памяти для приема данных от дисковода
  176. ;CDDataBuf       DB 4096 DUP (0)
  177. ; Размер принимаемого блока данных в байтах
  178. ;CDBlockSize     DW ?
  179. ; Адрес считываемого сектора данных
  180. CDSectorAddress:
  181.                  DD ?
  182. ; Время начала очередной операции с диском
  183. TickCounter_1 DD 0
  184. ; Время начала ожидания готовности устройства
  185. WURStartTime DD 0
  186. ; указатель буфера для считывания
  187. CDDataBuf_pointer dd 0
  188. endg
  189. ;****************************************************
  190. ;*    ПОСЛАТЬ УСТРОЙСТВУ ATAPI ПАКЕТНУЮ КОМАНДУ,    *
  191. ;* ПРЕДУСМАТРИВАЮЩУЮ ПЕРЕДАЧУ ОДНОГО СЕКТОРА ДАННЫХ *
  192. ;*     РАЗМЕРОМ 2048 БАЙТ ОТ УСТРОЙСТВА К ХОСТУ     *
  193. ;* Входные параметры передаются через глобальные    *
  194. ;* перменные:                                       *
  195. ;* ChannelNumber - номер канала;                    *
  196. ;* DiskNumber - номер диска на канале;              *
  197. ;* PacketCommand - 12-байтный командный пакет;      *
  198. ;* CDBlockSize - размер принимаемого блока данных.  *
  199. ; return eax DevErrorCode
  200. ;****************************************************
  201. SendPacketDatCommand:
  202.         xor     eax, eax
  203. ;        mov    byte [DevErrorCode],al
  204. ; Задать режим CHS
  205.         mov     byte [ATAAddressMode], al
  206. ; Послать ATA-команду передачи пакетной команды
  207.         mov     byte [ATAFeatures], al
  208.         mov     byte [ATASectorCount], al
  209.         mov     byte [ATASectorNumber], al
  210.         ; Загрузить размер передаваемого блока
  211.         mov     [ATAHead], al
  212. ;        mov     AX,[CDBlockSize]
  213.         mov     [ATACylinder], CDBlockSize
  214.         mov     [ATACommand], 0A0h
  215.         call    SendCommandToHDD_1
  216.         test    eax, eax
  217. ;        cmp     [DevErrorCode],0 ;проверить код ошибки
  218.         jnz     @@End_8    ;закончить, сохранив код ошибки
  219.  
  220. ; Ожидание готовности дисковода к приему
  221. ; пакетной команды
  222.         mov     DX, [ATABasePortAddr]
  223.         add     DX, 7    ;порт 1х7h
  224.         mov     ecx, NoTickWaitTime
  225. @@WaitDevice0:
  226.         cmp     [timer_ticks_enable], 0
  227.         jne     @f
  228.         dec     ecx
  229. ;        test    ecx,ecx
  230.         jz      @@Err1_1
  231.         jmp     .test
  232. @@:
  233.         call    change_task
  234.         ; Проверить время выполнения команды
  235.         mov     EAX, [timer_ticks]
  236.         sub     EAX, [TickCounter_1]
  237.         cmp     EAX, BSYWaitTime
  238.         ja      @@Err1_1   ;ошибка тайм-аута
  239.         ; Проверить готовность
  240. .test:
  241.         in      AL, DX
  242.         test    AL, 80h  ;состояние сигнала BSY
  243.         jnz     @@WaitDevice0
  244.         test    AL, 1    ;состояние сигнала ERR
  245.         jnz     @@Err6
  246.         test    AL, 08h  ;состояние сигнала DRQ
  247.         jz      @@WaitDevice0
  248. ; Послать пакетную команду
  249.         cli
  250.         mov     DX, [ATABasePortAddr]
  251.         mov     AX, [PacketCommand]
  252.         out     DX, AX
  253.         mov     AX, [PacketCommand+2]
  254.         out     DX, AX
  255.         mov     AX, [PacketCommand+4]
  256.         out     DX, AX
  257.         mov     AX, [PacketCommand+6]
  258.         out     DX, AX
  259.         mov     AX, [PacketCommand+8]
  260.         out     DX, AX
  261.         mov     AX, [PacketCommand+10]
  262.         out     DX, AX
  263.         sti
  264. ; Ожидание готовности данных
  265.         mov     DX, [ATABasePortAddr]
  266.         add     DX, 7  ;порт 1х7h
  267.         mov     ecx, NoTickWaitTime
  268. @@WaitDevice1:
  269.         cmp     [timer_ticks_enable], 0
  270.         jne     @f
  271.         dec     ecx
  272. ;        test    ecx,ecx
  273.         jz      @@Err1_1
  274.         jmp     .test_1
  275. @@:
  276.         call    change_task
  277.         ; Проверить время выполнения команды
  278.         mov     EAX, [timer_ticks]
  279.         sub     EAX, [TickCounter_1]
  280.         cmp     EAX, MaxCDWaitTime
  281.         ja      @@Err1_1   ;ошибка тайм-аута
  282.         ; Проверить готовность
  283. .test_1:
  284.         in      AL, DX
  285.         test    AL, 80h  ;состояние сигнала BSY
  286.         jnz     @@WaitDevice1
  287.         test    AL, 1    ;состояние сигнала ERR
  288.         jnz     @@Err6_temp
  289.         test    AL, 08h  ;состояние сигнала DRQ
  290.         jz      @@WaitDevice1
  291. ; Принять блок данных от контроллера
  292.         mov     EDI, [CDDataBuf_pointer];0x7000  ;CDDataBuf
  293.         ; Загрузить адрес регистра данных контроллера
  294.         mov     DX, [ATABasePortAddr];порт 1x0h
  295.         ; Загрузить в счетчик размер блока в байтах
  296.         xor     ecx, ecx
  297.         mov     CX, CDBlockSize
  298.         ; Вычислить размер блока в 16-разрядных словах
  299.         shr     CX, 1;разделить размер блока на 2
  300.         ; Принять блок данных
  301.         cli
  302.         cld
  303.         rep insw
  304.         sti
  305. ; Успешное завершение приема данных
  306. @@End_8:
  307.         xor     eax, eax
  308.         ret
  309.  
  310. ; Записать код ошибки
  311. @@Err1_1:
  312.         xor     eax, eax
  313.         inc     eax
  314.         ret
  315. ;        mov     [DevErrorCode],1
  316. ;       ret
  317. @@Err6_temp:
  318.         mov     eax, 7
  319.         ret
  320. ;        mov     [DevErrorCode],7
  321. ;       ret
  322. @@Err6:
  323.         mov     eax, 6
  324.         ret
  325. ;        mov     [DevErrorCode],6
  326. ;@@End_8:
  327. ;        ret
  328.  
  329.  
  330.  
  331. ;***********************************************
  332. ;*  ПОСЛАТЬ УСТРОЙСТВУ ATAPI ПАКЕТНУЮ КОМАНДУ, *
  333. ;*     НЕ ПРЕДУСМАТРИВАЮЩУЮ ПЕРЕДАЧИ ДАННЫХ    *
  334. ;* Входные параметры передаются через          *
  335. ;* глобальные перменные:                       *
  336. ;* ChannelNumber - номер канала;               *
  337. ;* DiskNumber - номер диска на канале;         *
  338. ;* PacketCommand - 12-байтный командный пакет. *
  339. ;***********************************************
  340. SendPacketNoDatCommand:
  341.         pushad
  342.         xor     eax, eax
  343. ;        mov     byte [DevErrorCode],al
  344. ; Задать режим CHS
  345.         mov     byte [ATAAddressMode], al
  346. ; Послать ATA-команду передачи пакетной команды
  347.         mov     byte [ATAFeatures], al
  348.         mov     byte [ATASectorCount], al
  349.         mov     byte [ATASectorNumber], al
  350.         mov     word [ATACylinder], ax
  351.         mov     byte [ATAHead], al
  352.         mov     [ATACommand], 0A0h
  353.         call    SendCommandToHDD_1
  354. ;        cmp     [DevErrorCode],0 ;проверить код ошибки
  355.         test    eax, eax
  356.         jnz     @@End_9  ;закончить, сохранив код ошибки
  357. ; Ожидание готовности дисковода к приему
  358. ; пакетной команды
  359.         mov     DX, [ATABasePortAddr]
  360.         add     DX, 7  ;порт 1х7h
  361. @@WaitDevice0_1:
  362.         call    change_task
  363.         ; Проверить время ожидания
  364.         mov     EAX, [timer_ticks]
  365.         sub     EAX, [TickCounter_1]
  366.         cmp     EAX, BSYWaitTime
  367.         ja      @@Err1_3   ;ошибка тайм-аута
  368.         ; Проверить готовность
  369.         in      AL, DX
  370.         test    AL, 80h  ;состояние сигнала BSY
  371.         jnz     @@WaitDevice0_1
  372.         test    AL, 1    ;состояние сигнала ERR
  373.         jnz     @@Err6_1
  374.         test    AL, 08h  ;состояние сигнала DRQ
  375.         jz      @@WaitDevice0_1
  376. ; Послать пакетную команду
  377. ;        cli
  378.         mov     DX, [ATABasePortAddr]
  379.         mov     AX, word [PacketCommand]
  380.         out     DX, AX
  381.         mov     AX, word [PacketCommand+2]
  382.         out     DX, AX
  383.         mov     AX, word [PacketCommand+4]
  384.         out     DX, AX
  385.         mov     AX, word [PacketCommand+6]
  386.         out     DX, AX
  387.         mov     AX, word [PacketCommand+8]
  388.         out     DX, AX
  389.         mov     AX, word [PacketCommand+10]
  390.         out     DX, AX
  391. ;        sti
  392.         cmp     [ignore_CD_eject_wait], 1
  393.         je      @@clear_DEC
  394. ; Ожидание подтверждения приема команды
  395.         mov     DX, [ATABasePortAddr]
  396.         add     DX, 7  ;порт 1х7h
  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, 80h  ;состояние сигнала BSY
  407.         jnz     @@WaitDevice1_1
  408.         test    AL, 1    ;состояние сигнала ERR
  409.         jnz     @@Err6_1
  410.         test    AL, 40h  ;состояние сигнала DRDY
  411.         jz      @@WaitDevice1_1
  412. @@clear_DEC:
  413.         and     [DevErrorCode], 0
  414.         popad
  415.         ret
  416. ; Записать код ошибки
  417. @@Err1_3:
  418.         xor     eax, eax
  419.         inc     eax
  420.         jmp     @@End_9
  421. @@Err6_1:
  422.         mov     eax, 6
  423. @@End_9:
  424.         mov     [DevErrorCode], eax
  425.         popad
  426.         ret
  427.  
  428. ;****************************************************
  429. ;*          ПОСЛАТЬ КОМАНДУ ЗАДАННОМУ ДИСКУ         *
  430. ;* Входные параметры передаются через глобальные    *
  431. ;* переменные:                                      *
  432. ;* ChannelNumber - номер канала (1 или 2);          *
  433. ;* DiskNumber - номер диска (0 или 1);              *
  434. ;* ATAFeatures - "особенности";                     *
  435. ;* ATASectorCount - количество секторов;            *
  436. ;* ATASectorNumber - номер начального сектора;      *
  437. ;* ATACylinder - номер начального цилиндра;         *
  438. ;* ATAHead - номер начальной головки;               *
  439. ;* ATAAddressMode - режим адресации (0-CHS, 1-LBA); *
  440. ;* ATACommand - код команды.                        *
  441. ;* После успешного выполнения функции:              *
  442. ;* в ATABasePortAddr - базовый адрес HDD;           *
  443. ;* в DevErrorCode - ноль.                           *
  444. ;* При возникновении ошибки в DevErrorCode будет    *
  445. ;* возвращен код ошибки в eax                       *
  446. ;****************************************************
  447. SendCommandToHDD_1:
  448. ;        pushad
  449. ;        mov    [DevErrorCode],0        not need
  450. ; Проверить значение кода режима
  451.         cmp     [ATAAddressMode], 1
  452.         ja      @@Err2_4
  453. ; Проверить корректность номера канала
  454.         mov     BX, [ChannelNumber]
  455.         cmp     BX, 1
  456.         jb      @@Err3_4
  457.         cmp     BX, 2
  458.         ja      @@Err3_4
  459. ; Установить базовый адрес
  460.         dec     BX
  461.         shl     BX, 1
  462.         movzx   ebx, bx
  463.         mov     AX, [ebx+StandardATABases]
  464.         mov     [ATABasePortAddr], AX
  465. ; Ожидание готовности HDD к приему команды
  466.         ; Выбрать нужный диск
  467.         mov     DX, [ATABasePortAddr]
  468.         add     DX, 6   ;адрес регистра головок
  469.         mov     AL, [DiskNumber]
  470.         cmp     AL, 1   ;проверить номера диска
  471.         ja      @@Err4_4
  472.         shl     AL, 4
  473.         or      AL, 10100000b
  474.         out     DX, AL
  475.         ; Ожидать, пока диск не будет готов
  476.         inc     DX
  477.         mov     eax, [timer_ticks]
  478.         mov     [TickCounter_1], eax
  479.         mov     ecx, NoTickWaitTime
  480. @@WaitHDReady_2:
  481.         cmp     [timer_ticks_enable], 0
  482.         jne     @f
  483.         dec     ecx
  484. ;        test   ecx,ecx
  485.         jz      @@Err1_4
  486.         jmp     .test
  487. @@:
  488.         call    change_task
  489.         ; Проверить время ожидания
  490.         mov     eax, [timer_ticks]
  491.         sub     eax, [TickCounter_1]
  492.         cmp     eax, BSYWaitTime;300    ;ожидать 3 сек.
  493.         ja      @@Err1_4   ;ошибка тайм-аута
  494.         ; Прочитать регистр состояния
  495. .test:
  496.         in      AL, DX
  497.         ; Проверить состояние сигнала BSY
  498.         test    AL, 80h
  499.         jnz     @@WaitHDReady_2
  500.         ; Проверить состояние сигнала DRQ
  501.         test    AL, 08h
  502.         jnz     @@WaitHDReady_2
  503.  
  504. ; Загрузить команду в регистры контроллера
  505.         cli
  506.         mov     DX, [ATABasePortAddr]
  507.         inc     DX      ;регистр "особенностей"
  508.         mov     AL, [ATAFeatures]
  509.         out     DX, AL
  510.         inc     DX      ;счетчик секторов
  511.         mov     AL, [ATASectorCount]
  512.         out     DX, AL
  513.         inc     DX      ;регистр номера сектора
  514.         mov     AL, [ATASectorNumber]
  515.         out     DX, AL
  516.         inc     DX      ;номер цилиндра (младший байт)
  517.         mov     AX, [ATACylinder]
  518.         out     DX, AL
  519.         inc     DX      ;номер цилиндра (старший байт)
  520.         mov     AL, AH
  521.         out     DX, AL
  522.         inc     DX      ;номер головки/номер диска
  523.         mov     AL, [DiskNumber]
  524.         shl     AL, 4
  525.         cmp     [ATAHead], 0Fh;проверить номер головки
  526.         ja      @@Err5_4
  527.         or      AL, [ATAHead]
  528.         or      AL, 10100000b
  529.         mov     AH, [ATAAddressMode]
  530.         shl     AH, 6
  531.         or      AL, AH
  532.         out     DX, AL
  533. ; Послать команду
  534.         mov     AL, [ATACommand]
  535.         inc     DX      ;регистр команд
  536.         out     DX, AL
  537.         sti
  538. ; Сбросить признак ошибки
  539. ;        mov     [DevErrorCode],0
  540. @@End_10:
  541.         xor     eax, eax
  542.         ret
  543. ; Записать код ошибки
  544. @@Err1_4:
  545.         xor     eax, eax
  546.         inc     eax
  547. ;        mov     [DevErrorCode],1
  548.         ret
  549. @@Err2_4:
  550.         mov     eax, 2
  551. ;        mov     [DevErrorCode],2
  552.         ret
  553. @@Err3_4:
  554.         mov     eax, 3
  555. ;        mov     [DevErrorCode],3
  556.         ret
  557. @@Err4_4:
  558.         mov     eax, 4
  559. ;        mov     [DevErrorCode],4
  560.         ret
  561. @@Err5_4:
  562.         mov     eax, 5
  563. ;        mov     [DevErrorCode],5
  564. ; Завершение работы программы
  565.         ret
  566. ;        sti
  567. ;        popad
  568.  
  569. ;*************************************************
  570. ;*    ОЖИДАНИЕ ГОТОВНОСТИ УСТРОЙСТВА К РАБОТЕ    *
  571. ;* Входные параметры передаются через глобальные *
  572. ;* перменные:                                    *
  573. ;* ChannelNumber - номер канала;                 *
  574. ;* DiskNumber - номер диска на канале.           *
  575. ;*************************************************
  576. WaitUnitReady:
  577.         pusha
  578. ; Запомнить время начала операции
  579.         mov     EAX, [timer_ticks]
  580.         mov     [WURStartTime], EAX
  581. ; Очистить буфер пакетной команды
  582.         call    clear_packet_buffer
  583. ; Сформировать команду TEST UNIT READY
  584.         mov     [PacketCommand], word 00h
  585. ; ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ УСТРОЙСТВА
  586.         mov     ecx, NoTickWaitTime
  587. @@SendCommand:
  588.         ; Подать команду проверки готовности
  589.         call    SendPacketNoDatCommand
  590.         cmp     [timer_ticks_enable], 0
  591.         jne     @f
  592.         cmp     [DevErrorCode], 0
  593.         je      @@End_11
  594.         dec     ecx
  595. ;        cmp     ecx,0
  596.         jz      .Error
  597.         jmp     @@SendCommand
  598. @@:
  599.         call    change_task
  600.         ; Проверить код ошибки
  601.         cmp     [DevErrorCode], 0
  602.         je      @@End_11
  603.         ; Проверить время ожидания готовности
  604.         mov     EAX, [timer_ticks]
  605.         sub     EAX, [WURStartTime]
  606.         cmp     EAX, MaxCDWaitTime
  607.         jb      @@SendCommand
  608. .Error:
  609.         ; Ошибка тайм-аута
  610.         mov     [DevErrorCode], 1
  611. @@End_11:
  612.         popa
  613.         ret
  614.  
  615. ;*************************************************
  616. ;*            ЗАПРЕТИТЬ СМЕНУ ДИСКА              *
  617. ;* Входные параметры передаются через глобальные *
  618. ;* перменные:                                    *
  619. ;* ChannelNumber - номер канала;                 *
  620. ;* DiskNumber - номер диска на канале.           *
  621. ;*************************************************
  622. prevent_medium_removal:
  623.         pusha
  624. ; Очистить буфер пакетной команды
  625.         call    clear_packet_buffer
  626. ; Задать код команды
  627.         mov     [PacketCommand], byte 0x1E
  628. ; Задать код запрета
  629.         mov     [PacketCommand+4], byte 11b
  630. ; Подать команду
  631.         call    SendPacketNoDatCommand
  632.         mov     eax, ATAPI_IDE0_lock
  633.         add     eax, [cdpos]
  634.         dec     eax
  635.         mov     [eax], byte 1
  636.         popa
  637.         ret
  638.  
  639. ;*************************************************
  640. ;*            РАЗРЕШИТЬ СМЕНУ ДИСКА              *
  641. ;* Входные параметры передаются через глобальные *
  642. ;* перменные:                                    *
  643. ;* ChannelNumber - номер канала;                 *
  644. ;* DiskNumber - номер диска на канале.           *
  645. ;*************************************************
  646. allow_medium_removal:
  647.         pusha
  648. ; Очистить буфер пакетной команды
  649.         call    clear_packet_buffer
  650. ; Задать код команды
  651.         mov     [PacketCommand], byte 0x1E
  652. ; Задать код запрета
  653.         mov     [PacketCommand+4], byte 00b
  654. ; Подать команду
  655.         call    SendPacketNoDatCommand
  656.         mov     eax, ATAPI_IDE0_lock
  657.         add     eax, [cdpos]
  658.         dec     eax
  659.         mov     [eax], byte 0
  660.         popa
  661.         ret
  662.  
  663. ;*************************************************
  664. ;*         ЗАГРУЗИТЬ НОСИТЕЛЬ В ДИСКОВОД         *
  665. ;* Входные параметры передаются через глобальные *
  666. ;* перменные:                                    *
  667. ;* ChannelNumber - номер канала;                 *
  668. ;* DiskNumber - номер диска на канале.           *
  669. ;*************************************************
  670. LoadMedium:
  671.         pusha
  672. ; Очистить буфер пакетной команды
  673.         call    clear_packet_buffer
  674. ; Сформировать команду START/STOP UNIT
  675.         ; Задать код команды
  676.         mov     [PacketCommand], word 1Bh
  677.         ; Задать операцию загрузки носителя
  678.         mov     [PacketCommand+4], word 00000011b
  679. ; Подать команду
  680.         call    SendPacketNoDatCommand
  681.         popa
  682.         ret
  683.  
  684. ;*************************************************
  685. ;*         ИЗВЛЕЧЬ НОСИТЕЛЬ ИЗ ДИСКОВОДА         *
  686. ;* Входные параметры передаются через глобальные *
  687. ;* перменные:                                    *
  688. ;* ChannelNumber - номер канала;                 *
  689. ;* DiskNumber - номер диска на канале.           *
  690. ;*************************************************
  691. EjectMedium:
  692.         pusha
  693. ; Очистить буфер пакетной команды
  694.         call    clear_packet_buffer
  695. ; Сформировать команду START/STOP UNIT
  696.         ; Задать код команды
  697.         mov     [PacketCommand], word 1Bh
  698.         ; Задать операцию извлечения носителя
  699.         mov     [PacketCommand+4], word 00000010b
  700. ; Подать команду
  701.         call    SendPacketNoDatCommand
  702.         popa
  703.         ret
  704.  
  705. ;*************************************************
  706. ;* Проверить событие нажатия кнопки извлечения   *
  707. ;*                     диска                     *
  708. ;* Входные параметры передаются через глобальные *
  709. ;* переменные:                                   *
  710. ;* ChannelNumber - номер канала;                 *
  711. ;* DiskNumber - номер диска на канале.           *
  712. ;*************************************************
  713. proc check_ATAPI_device_event_has_work?
  714.         mov     eax, [timer_ticks]
  715.         sub     eax, [timer_ATAPI_check]
  716.         cmp     eax, 100
  717.         jb      .no
  718. .yes:
  719.         xor     eax, eax
  720.         inc     eax
  721.         ret
  722. .no:
  723.         xor     eax, eax
  724.         ret
  725. endp
  726.  
  727. align 4
  728. check_ATAPI_device_event:
  729.         pusha
  730.         mov     eax, [timer_ticks]
  731.         sub     eax, [timer_ATAPI_check]
  732.         cmp     eax, 100
  733.         jb      .end_1
  734.         mov     al, [DRIVE_DATA+1]
  735.         and     al, 11b
  736.         cmp     al, 10b
  737.         jz      .ide3
  738. .ide2_1:
  739.         mov     al, [DRIVE_DATA+1]
  740.         and     al, 1100b
  741.         cmp     al, 1000b
  742.         jz      .ide2
  743. .ide1_1:
  744.         mov     al, [DRIVE_DATA+1]
  745.         and     al, 110000b
  746.         cmp     al, 100000b
  747.         jz      .ide1
  748. .ide0_1:
  749.         mov     al, [DRIVE_DATA+1]
  750.         and     al, 11000000b
  751.         cmp     al, 10000000b
  752.         jz      .ide0
  753. .end:
  754.  
  755.         sti
  756.         mov     eax, [timer_ticks]
  757.         mov     [timer_ATAPI_check], eax
  758. .end_1:
  759.         popa
  760.         ret
  761.  
  762. .ide3:
  763.         cli
  764.         cmp     [ATAPI_IDE3_lock], 1
  765.         jne     .ide2_1
  766.         cmp     [IDE_Channel_2], 0
  767.         jne     .ide1_1
  768.         cmp     [cd_status], 0
  769.         jne     .end
  770.         mov     [IDE_Channel_2], 1
  771.         call    reserve_ok2
  772.         mov     [ChannelNumber], 2
  773.         mov     [DiskNumber], 1
  774.         mov     [cdpos], 4
  775.         call    GetEvent_StatusNotification
  776.         cmp     [CDDataBuf+4], byte 1
  777.         je      .eject_ide3
  778.         call    syscall_cdaudio.free
  779.         jmp     .ide2_1
  780. .eject_ide3:
  781.         call    .eject
  782.         call    syscall_cdaudio.free
  783.         jmp     .ide2_1
  784.  
  785. .ide2:
  786.         cli
  787.         cmp     [ATAPI_IDE2_lock], 1
  788.         jne     .ide1_1
  789.         cmp     [IDE_Channel_2], 0
  790.         jne     .ide1_1
  791.         cmp     [cd_status], 0
  792.         jne     .end
  793.         mov     [IDE_Channel_2], 1
  794.         call    reserve_ok2
  795.         mov     [ChannelNumber], 2
  796.         mov     [DiskNumber], 0
  797.         mov     [cdpos], 3
  798.         call    GetEvent_StatusNotification
  799.         cmp     [CDDataBuf+4], byte 1
  800.         je      .eject_ide2
  801.         call    syscall_cdaudio.free
  802.         jmp     .ide1_1
  803. .eject_ide2:
  804.         call    .eject
  805.         call    syscall_cdaudio.free
  806.         jmp     .ide1_1
  807.  
  808. .ide1:
  809.         cli
  810.         cmp     [ATAPI_IDE1_lock], 1
  811.         jne     .ide0_1
  812.         cmp     [IDE_Channel_1], 0
  813.         jne     .end
  814.         cmp     [cd_status], 0
  815.         jne     .end
  816.         mov     [IDE_Channel_1], 1
  817.         call    reserve_ok2
  818.         mov     [ChannelNumber], 1
  819.         mov     [DiskNumber], 1
  820.         mov     [cdpos], 2
  821.         call    GetEvent_StatusNotification
  822.         cmp     [CDDataBuf+4], byte 1
  823.         je      .eject_ide1
  824.         call    syscall_cdaudio.free
  825.         jmp     .ide0_1
  826. .eject_ide1:
  827.         call    .eject
  828.         call    syscall_cdaudio.free
  829.         jmp     .ide0_1
  830.  
  831. .ide0:
  832.         cli
  833.         cmp     [ATAPI_IDE0_lock], 1
  834.         jne     .end
  835.         cmp     [IDE_Channel_1], 0
  836.         jne     .end
  837.         cmp     [cd_status], 0
  838.         jne     .end
  839.         mov     [IDE_Channel_1], 1
  840.         call    reserve_ok2
  841.         mov     [ChannelNumber], 1
  842.         mov     [DiskNumber], 0
  843.         mov     [cdpos], 1
  844.         call    GetEvent_StatusNotification
  845.         cmp     [CDDataBuf+4], byte 1
  846.         je      .eject_ide0
  847.         call    syscall_cdaudio.free
  848.         jmp     .end
  849. .eject_ide0:
  850.         call    .eject
  851.         call    syscall_cdaudio.free
  852.         jmp     .end
  853.  
  854. .eject:
  855.         call    clear_CD_cache
  856.         call    allow_medium_removal
  857.         mov     [ignore_CD_eject_wait], 1
  858.         call    EjectMedium
  859.         mov     [ignore_CD_eject_wait], 0
  860.         ret
  861. iglobal
  862. timer_ATAPI_check dd 0
  863. ATAPI_IDE0_lock db 0
  864. ATAPI_IDE1_lock db 0
  865. ATAPI_IDE2_lock db 0
  866. ATAPI_IDE3_lock db 0
  867. ignore_CD_eject_wait db 0
  868. endg
  869. ;*************************************************
  870. ;* Получить сообщение о событии или состоянии    *
  871. ;*                  устройства                   *
  872. ;* Входные параметры передаются через глобальные *
  873. ;* переменные:                                   *
  874. ;* ChannelNumber - номер канала;                 *
  875. ;* DiskNumber - номер диска на канале.           *
  876. ;*************************************************
  877. GetEvent_StatusNotification:
  878.         pusha
  879.         mov     [CDDataBuf_pointer], CDDataBuf
  880. ; Очистить буфер пакетной команды
  881.         call    clear_packet_buffer
  882. ; Задать код команды
  883.         mov     [PacketCommand], byte 4Ah
  884.         mov     [PacketCommand+1], byte 00000001b
  885. ; Задать запрос класса сообщений
  886.         mov     [PacketCommand+4], byte 00010000b
  887. ; Размер выделенной области
  888.         mov     [PacketCommand+7], byte 8h
  889.         mov     [PacketCommand+8], byte 0h
  890. ; Подать команду
  891.         call    SendPacketDatCommand
  892.         popa
  893.         ret
  894.  
  895. ;*************************************************
  896. ; прочитать информацию из TOC
  897. ;* Входные параметры передаются через глобальные *
  898. ;* переменные:                                   *
  899. ;* ChannelNumber - номер канала;                 *
  900. ;* DiskNumber - номер диска на канале.           *
  901. ;*************************************************
  902. Read_TOC:
  903.         pusha
  904.         mov     [CDDataBuf_pointer], CDDataBuf
  905. ; Очистить буфер пакетной команды
  906.         call    clear_packet_buffer
  907. ; Сформировать пакетную команду для считывания
  908. ; сектора данных
  909.         mov     [PacketCommand], byte 0x43
  910.         ; Задать формат
  911.         mov     [PacketCommand+2], byte 1
  912. ; Размер выделенной области
  913.         mov     [PacketCommand+7], byte 0xFF
  914.         mov     [PacketCommand+8], byte 0h
  915. ; Подать команду
  916.         call    SendPacketDatCommand
  917.         popa
  918.         ret
  919.  
  920. ;*************************************************
  921. ;* ОПРЕДЕЛИТЬ ОБЩЕЕ КОЛИЧЕСТВО СЕКТОРОВ НА ДИСКЕ *
  922. ;* Входные параметры передаются через глобальные *
  923. ;* переменные:                                   *
  924. ;* ChannelNumber - номер канала;                 *
  925. ;* DiskNumber - номер диска на канале.           *
  926. ;*************************************************
  927. ;ReadCapacity:
  928. ;       pusha
  929. ;; Очистить буфер пакетной команды
  930. ;       call  clear_packet_buffer
  931. ;; Задать размер буфера в байтах
  932. ;       mov     [CDBlockSize],8
  933. ;; Сформировать команду READ CAPACITY
  934. ;       mov     [PacketCommand],word 25h
  935. ;; Подать команду
  936. ;       call    SendPacketDatCommand
  937. ;       popa
  938. ;       ret
  939.  
  940. clear_packet_buffer:
  941. ; Очистить буфер пакетной команды
  942.         and     [PacketCommand], dword 0
  943.         and     [PacketCommand+4], dword 0
  944.         and     [PacketCommand+8], dword 0
  945.         ret
  946.