PCI DMA и int76h

Тема в разделе "WASM.ASSEMBLER", создана пользователем kb_Stanley, 27 ноя 2007.

  1. kb_Stanley

    kb_Stanley New Member

    Публикаций:
    0
    Регистрация:
    27 ноя 2007
    Сообщения:
    1
    Добрый день!
    Возникла проблема при написании программы чтения первого сектора жесткого диска в режиме DMA.
    Отправной точкой послужила статья http://www.wasm.ru/print.php?article=atazen02.
    Но мне необходимо было сделать проверку того, что передача закончилась в обработчике прерывания.
    Посадил я этот обработчик на int76h. В результате программа намертво зависает после запуска.
    Вот код:
    Код (Text):
    1. .386
    2.  
    3. ; Создаем таблицу PRDT из одной записи
    4. data segment use16
    5.         PRD_ADDR  dd 0
    6.         PRD_COUNT dw 0
    7.         PRD_FLAG  dw 0
    8.         BUFFER db 512 dup (0),'$'
    9.         Old_Int dw 0,0
    10.         BlockReg dw 0
    11.         CPUtest db 'CPU test',13,10,'$'
    12. data ends
    13.  
    14. ; Базовый адрес регистров контроллера первого канала
    15. BASE equ 1F0h
    16.  
    17. stck segment stack use16
    18.  dw 1024 dup (?)
    19. stck ends
    20.  
    21. code segment use16
    22. assume cs:code,ss:stck,ds:data
    23.  
    24. ;################################################
    25. ;#Процедура определяющая адрес регистров PCI IDE#
    26. ;#с помощью функций PCI BIOS                    #
    27. ;################################################
    28. PCI_DETECT PROC NEAR
    29.  push esi
    30.  push edi
    31.  mov si,0
    32.  mov ecx,010180h
    33. try:
    34.  mov ax,0B103h
    35.  int 1Ah
    36.  jnc next
    37.  add ecx,5
    38.  jmp try
    39. next:
    40.  mov ax,0B10Ah
    41.  mov di,20h
    42.  int 1Ah
    43.  and cx,0FFF0h
    44.  pop edi
    45.  pop esi
    46. ret
    47. PCI_DETECT ENDP
    48.  
    49. ;###################################################
    50. ;Считывание первого сектора ЖД в режиме DMA в буфер#
    51. ;Входные параметры                                 #
    52. ;EDI[31:0] - указатель на PRDT                     #
    53. ;ESI[27:0] - LBA адрес                             #
    54. ;ESI[28] - Устройство (0 - Master, 1 - Slave)      #
    55. ;###################################################
    56. READ_DMA PROC NEAR
    57.     mov dx, BASE + 206h ;Разрешаем прерывания
    58.     mov al, 0
    59.     out dx, al
    60.  
    61.     mov dx, BASE+7 ;Ждем BSY=0
    62. BSY:
    63.     in al, dx
    64.     test al, 80h
    65.     jnz BSY
    66.  
    67.     mov eax, esi ;Выбираем устройство и загружаем старшие разряды адреса
    68.     shr eax, 24
    69.     or  al, 0E0h
    70.     mov dx, BASE+6
    71.     out dx, al
    72.  
    73.     mov dx, BASE+7 ;Ждем BSY=0 и DRDY=1
    74. BSY_DRDY:
    75.     in al, dx
    76.     test al, 80h
    77.     jnz BSY_DRDY
    78.     test al, 40h
    79.     jz BSY_DRDY
    80.  
    81.     mov eax, esi ;Загружаем LBA адрес
    82.     mov dx, BASE+3
    83.     out dx, al    
    84.     shr eax, 8
    85.     inc dx
    86.     out dx, al
    87.     shr eax, 8
    88.     inc dx
    89.     out dx, al
    90.  
    91.     mov dx, BASE+2 ; Количество секторов = 1
    92.     mov al, 1
    93.     out dx, al
    94.  
    95.     call PCI_DETECT ;В CX адрес блока регистров PCI IDE
    96.     mov [BlockReg], cx
    97.  
    98.     call InitIRQ
    99.  
    100.     mov dx,cx ;Указатель на таблицу PRDT
    101.     add dx,4
    102.     mov eax,edi
    103.     out dx,eax
    104.  
    105.     mov dx,cx ;Направление обмена - "в память"
    106.     mov al,8
    107.     out dx,al
    108.  
    109.     mov dx,BASE+7 ;Посылаем команду "READ SECTORS DMA"
    110.     mov al,0C8h
    111.     out dx,al
    112.    
    113.     mov dx,cx ;Разрешаем Bus Mastering (с этого момента начинается обмен)
    114.     mov al,9
    115.     out dx,al
    116.  
    117.     ret
    118. READ_DMA ENDP
    119.  
    120. ;###########################################
    121. ;Инициализация вектора прерываний IRQ14      #
    122. ;###########################################
    123. InitIRQ proc
    124.         push AX
    125.     push BX
    126.     push CX
    127.     push DX
    128.     push ES
    129.     ;считывание старого вектора
    130.     mov AL, 76h
    131.     mov AH, 35h
    132.     int 21h
    133.     mov [Old_Int], BX   ;сохранили старый вектор
    134.     mov [Old_Int+2], ES
    135.     ;устанавливаем новый обработчик прерываний
    136.     mov AL, 76h
    137.     lea DX, IRQ_Int
    138.     mov AH, 25h
    139.     int 21h
    140.     pop ES
    141.     pop DX
    142.     pop CX
    143.     pop BX
    144.     pop AX
    145.     ret
    146. InitIRQ endp
    147.  
    148. ;#################################################
    149. ;Программа обработки прерываний HDD0             # 
    150. ;Когда происходит прерывание проверяется бит AC  #
    151. ;если false, то уходим на стандартный обработчик,#
    152. ;иначе выходим. Данные в буфере             #
    153. ;#################################################
    154. IRQ_Int proc far
    155.         push AX
    156.     push BX
    157.     push CX
    158.     push DX
    159.     push ES
    160.         mov dx,[BlockReg] ;Ждем AC=0 (DMA обмен закончен)
    161.     add dx,2
    162.  
    163.     in al,dx
    164.     test al,1
    165.     jnz exit
    166.    
    167.     mov dx,[BlockReg] ;Запретить Bus Master
    168.     mov al,0
    169.     out dx,al
    170.    
    171.     pop ES
    172.     pop DX
    173.     pop CX
    174.     pop BX
    175.     pop AX
    176.     jmp end_    
    177. exit:   pop ES
    178.     pop DX
    179.     pop CX
    180.     pop BX
    181.     pop AX
    182.     jmp dword ptr [Old_Int]
    183.  
    184. IRQ_Int endp
    185.  
    186. start:
    187.     mov ax,data
    188.     mov ds,ax
    189.  
    190.     mov eax,data
    191.     shl eax,4
    192.     mov edi,eax ;Получаем физический адрес таблицы и загружаем его в EDI
    193.     add eax,8
    194.     mov PRD_ADDR,eax ;Заполняем саму таблицу
    195.     mov PRD_COUNT,512
    196.     mov PRD_FLAG,08000h
    197.     mov esi,0 ;Загрузочный сектор Master-устройства
    198.     call read_dma
    199.  
    200. Wait_:  mov AH, 09h     ;показываем занятость процессора
    201.     lea DX, CPUtest
    202.     int 21h
    203.     jmp Wait_
    204.     ;Теперь в буфере лежит MBR
    205. end_:
    206.  
    207.     ;Восстановление старого вектора
    208.     mov AL, 76h
    209.     mov AH, 25h
    210.     lea DX, dword ptr [Old_Int]
    211.     int 21h
    212.  
    213.     mov ax,4c00h
    214.     int 21h
    215. code ends
    216. end start
    Подскажите, пожалуйста, если есть возможность.
     
  2. _mgf_

    _mgf_ New Member

    Публикаций:
    0
    Регистрация:
    8 ноя 2007
    Сообщения:
    5
    Может быть проблема в том, что когда вызываеться твой обработчик, нет гарантии, что ds указывает на твой сегмент даных. По этому я рекомендую дописать в твоем обработчике в самом начале:
    Код (Text):
    1. push ds
    2. mox ax,data
    3. mov ds,ax
    Ну и в конце не забудь возобновить сегментный регистр ds