Subversion Repositories Kolibri OS

Rev

Rev 3539 | Rev 4734 | 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: 3742 $
  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.         mov     ecx, ide_channel2_mutex
  772.         call    mutex_lock
  773.         call    reserve_ok2
  774.         mov     [ChannelNumber], 2
  775.         mov     [DiskNumber], 1
  776.         mov     [cdpos], 4
  777.         call    GetEvent_StatusNotification
  778.         cmp     [CDDataBuf+4], byte 1
  779.         je      .eject_ide3
  780.         call    syscall_cdaudio.free
  781.         jmp     .ide2_1
  782. .eject_ide3:
  783.         call    .eject
  784.         call    syscall_cdaudio.free
  785.         jmp     .ide2_1
  786.  
  787. .ide2:
  788.         cli
  789.         cmp     [ATAPI_IDE2_lock], 1
  790.         jne     .ide1_1
  791.         cmp     [IDE_Channel_2], 0
  792.         jne     .ide1_1
  793.         cmp     [cd_status], 0
  794.         jne     .end
  795.         mov     [IDE_Channel_2], 1
  796.         mov     ecx, ide_channel2_mutex
  797.         call    mutex_lock
  798.         call    reserve_ok2
  799.         mov     [ChannelNumber], 2
  800.         mov     [DiskNumber], 0
  801.         mov     [cdpos], 3
  802.         call    GetEvent_StatusNotification
  803.         cmp     [CDDataBuf+4], byte 1
  804.         je      .eject_ide2
  805.         call    syscall_cdaudio.free
  806.         jmp     .ide1_1
  807. .eject_ide2:
  808.         call    .eject
  809.         call    syscall_cdaudio.free
  810.         jmp     .ide1_1
  811.  
  812. .ide1:
  813.         cli
  814.         cmp     [ATAPI_IDE1_lock], 1
  815.         jne     .ide0_1
  816.         cmp     [IDE_Channel_1], 0
  817.         jne     .end
  818.         cmp     [cd_status], 0
  819.         jne     .end
  820.         mov     [IDE_Channel_1], 1
  821.         mov     ecx, ide_channel1_mutex
  822.         call    mutex_lock
  823.         call    reserve_ok2
  824.         mov     [ChannelNumber], 1
  825.         mov     [DiskNumber], 1
  826.         mov     [cdpos], 2
  827.         call    GetEvent_StatusNotification
  828.         cmp     [CDDataBuf+4], byte 1
  829.         je      .eject_ide1
  830.         call    syscall_cdaudio.free
  831.         jmp     .ide0_1
  832. .eject_ide1:
  833.         call    .eject
  834.         call    syscall_cdaudio.free
  835.         jmp     .ide0_1
  836.  
  837. .ide0:
  838.         cli
  839.         cmp     [ATAPI_IDE0_lock], 1
  840.         jne     .end
  841.         cmp     [IDE_Channel_1], 0
  842.         jne     .end
  843.         cmp     [cd_status], 0
  844.         jne     .end
  845.         mov     [IDE_Channel_1], 1
  846.         mov     ecx, ide_channel1_mutex
  847.         call    mutex_lock
  848.         call    reserve_ok2
  849.         mov     [ChannelNumber], 1
  850.         mov     [DiskNumber], 0
  851.         mov     [cdpos], 1
  852.         call    GetEvent_StatusNotification
  853.         cmp     [CDDataBuf+4], byte 1
  854.         je      .eject_ide0
  855.         call    syscall_cdaudio.free
  856.         jmp     .end
  857. .eject_ide0:
  858.         call    .eject
  859.         call    syscall_cdaudio.free
  860.         jmp     .end
  861.  
  862. .eject:
  863.         call    clear_CD_cache
  864.         call    allow_medium_removal
  865.         mov     [ignore_CD_eject_wait], 1
  866.         call    EjectMedium
  867.         mov     [ignore_CD_eject_wait], 0
  868.         ret
  869. iglobal
  870. timer_ATAPI_check dd 0
  871. ATAPI_IDE0_lock db 0
  872. ATAPI_IDE1_lock db 0
  873. ATAPI_IDE2_lock db 0
  874. ATAPI_IDE3_lock db 0
  875. ignore_CD_eject_wait db 0
  876. endg
  877. ;*************************************************
  878. ;* Получить сообщение о событии или состоянии    *
  879. ;*                  устройства                   *
  880. ;* Входные параметры передаются через глобальные *
  881. ;* переменные:                                   *
  882. ;* ChannelNumber - номер канала;                 *
  883. ;* DiskNumber - номер диска на канале.           *
  884. ;*************************************************
  885. GetEvent_StatusNotification:
  886.         pusha
  887.         mov     [CDDataBuf_pointer], CDDataBuf
  888. ; Очистить буфер пакетной команды
  889.         call    clear_packet_buffer
  890. ; Задать код команды
  891.         mov     [PacketCommand], byte 4Ah
  892.         mov     [PacketCommand+1], byte 00000001b
  893. ; Задать запрос класса сообщений
  894.         mov     [PacketCommand+4], byte 00010000b
  895. ; Размер выделенной области
  896.         mov     [PacketCommand+7], byte 8h
  897.         mov     [PacketCommand+8], byte 0h
  898. ; Подать команду
  899.         call    SendPacketDatCommand
  900.         popa
  901.         ret
  902.  
  903. ;*************************************************
  904. ; прочитать информацию из TOC
  905. ;* Входные параметры передаются через глобальные *
  906. ;* переменные:                                   *
  907. ;* ChannelNumber - номер канала;                 *
  908. ;* DiskNumber - номер диска на канале.           *
  909. ;*************************************************
  910. Read_TOC:
  911.         pusha
  912.         mov     [CDDataBuf_pointer], CDDataBuf
  913. ; Очистить буфер пакетной команды
  914.         call    clear_packet_buffer
  915. ; Сформировать пакетную команду для считывания
  916. ; сектора данных
  917.         mov     [PacketCommand], byte 0x43
  918.         ; Задать формат
  919.         mov     [PacketCommand+2], byte 1
  920. ; Размер выделенной области
  921.         mov     [PacketCommand+7], byte 0xFF
  922.         mov     [PacketCommand+8], byte 0h
  923. ; Подать команду
  924.         call    SendPacketDatCommand
  925.         popa
  926.         ret
  927.  
  928. ;*************************************************
  929. ;* ОПРЕДЕЛИТЬ ОБЩЕЕ КОЛИЧЕСТВО СЕКТОРОВ НА ДИСКЕ *
  930. ;* Входные параметры передаются через глобальные *
  931. ;* переменные:                                   *
  932. ;* ChannelNumber - номер канала;                 *
  933. ;* DiskNumber - номер диска на канале.           *
  934. ;*************************************************
  935. ;ReadCapacity:
  936. ;       pusha
  937. ;; Очистить буфер пакетной команды
  938. ;       call  clear_packet_buffer
  939. ;; Задать размер буфера в байтах
  940. ;       mov     [CDBlockSize],8
  941. ;; Сформировать команду READ CAPACITY
  942. ;       mov     [PacketCommand],word 25h
  943. ;; Подать команду
  944. ;       call    SendPacketDatCommand
  945. ;       popa
  946. ;       ret
  947.  
  948. clear_packet_buffer:
  949. ; Очистить буфер пакетной команды
  950.         and     [PacketCommand], dword 0
  951.         and     [PacketCommand+4], dword 0
  952.         and     [PacketCommand+8], dword 0
  953.         ret
  954.