OSDev Wiki
Advertisement
;****************************************************
;*                 ПОИСК HDD и CD                   *
;****************************************************
OS_BASE         equ 0
IDEBasesPorts   equ OS_BASE+6F00h
IDEMaxConroller equ    4
IDEMaxCanals    equ    8
;Таблица портов имеет следующий формат
;канал 0
;канал 1
;канал 2
;..
;канал 7
; * кажый канал это два порта 
;   Базовый адрес портов команд  
;   Базовый адрес порта контроля именно порта, а не блока.
 
; Всего 8 каналов 8*2*2=32Байта
IDEBusMaster equ IDEBasesPorts+20h 
; Всего 4 вхождения по 4 байта.

IDEBusIRQ equ IDEBasesPorts+ 30h
; Всего 4 байта.
IDEHDD_CD equ IDEBasesPorts+34h 
;4Байта 00b нет устройства 01b есть жесткий диск 10b есть Сидиром 11b рерв. 8  Каналов по два диска
IDELBA48 equ IDEBasesPorts+38h
;2 Байта 0 нет поддержки 1 есть поддержка и так 8 Каналов по два диска
 
FindHDD:
; Стандартные
        xor     eax, eax
        mov     ecx, 100h
        mov     edi, IDEBasesPorts
        rep     stosb
; Поиск контролеров и четение из них базовых портов
        call    FindBasesPorts
        mov     ecx, IDEMaxCanals-1
           
.Loop:
        mov     ah, cl 
        xor     al, al         ; al = 0
        call    TestDisks
        mov     ah, cl
        mov     al, 1          ; al = 1
        call    TestDisks

        dec     ecx
        cmp     ecx, dword -1
        jne     .Loop
        ret
;***********************
; Функция для проверки существования диска.
; ah - канал
; al - диск мастер 0 слейв 1
; 
buf    dw 256 dup 0
TestDisks:
        pushad
        and     al, 1

        movzx   esi, ah
        movzx   edi, al

         
        mov     dx, word [IDEBasesPorts+esi*4]  ; базовый порт команд
        test    dx, dx                          ; dx == 0 ?
        jz      .end                            ; прыгаем, если dx == 0

        shl     esi, 1
        add     esi, edi
        shl     esi, 1
            
        shl     al, 4
        
        add     dx, 6                           ;+6 Device         
        out     dx, al
        
        xor     al, al                          ; al = 0
        dec     dx                              ;+5
        out     dx, al
        dec     dx                              ;+4
        out     dx, al
        dec     dx                              ;+3
        out     dx, al
        dec     dx                              ;+2
        out     dx, al
       
        add     dx, 5		                ;+7 Command
        mov     al, 90h				; EXECUTE DEVICE DIAGNOSTIC
        out     dx, al
       
        mov     ecx, 0FFFFh
.loop:
        out     0EBh, al                        ; задержка
        in      al, dx                          ;+7 Status
        test    al, 80h                         ;BSY  
        jz     .ok1
        loop    .loop

.timeout:
        ; время вышло - устройства нет
        mov    eax, 3
       
        mov    ecx, esi
        shl    eax, cl   
        
        not    eax
        and    dword [IDEHDD_CD], eax
        
        sub    dx, 7                            ;+0
        jmp    .reset
        
.ok1:
        sub    dx, 6                            ;+1
        in     al, dx
        add    dx, 6                            ;+7

        cmp    edi, 1
        je     .label1
        cmp    al, 1
        je     .label2
        sub    dx, 7                            ;+0
        jmp    .other1

.label1:
        cmp    al, 1
        je     .label2
        cmp    al, 80h
        je     .label2
        sub    dx, 7                            ;+0
        jmp    .other1
       
.label2:
        dec    dx                               ;+6
        dec    dx                               ;+5
        in     al, dx
        mov    bl, al
        shl    ebx, 8
        dec    dx                               ;+4
        in     al, dx
        mov    bl, al
        shl    ebx, 8
        dec    dx                               ;+3
        in     al, dx
        mov    bl, al
        shl    ebx, 8
        dec    dx                               ;+2
        in     al, dx
        mov    bl, al
        sub    dx,2                             ;+0
        
        cmp    ebx, 000000101h                  ; жесткий диск
        jne    .cd
        mov    eax, 1
        mov    ecx, esi
        shl    eax, cl   
        or     dword [IDEHDD_CD], eax
        jmp    .indef
        
.cd:
        cmp    ebx, 0EB140101h                  ; сидиром
        jne    .other1
        mov    eax, 2
        mov    ecx, esi
        shl    eax, cl   
       
        or     dword [IDEHDD_CD], eax
        jmp    .reset

.other1: 
        mov    eax, 3
        
        mov    ecx, esi
        shl    eax, cl   
        not    eax
        and    dword [IDEHDD_CD], eax

.reset:
        add     dx, 6                    ;+6
        mov     eax, edi
        shl     al, 4
        out     dx, al
         
        mov     al, 0
        dec     dx                       ;+5
        out     dx, al                    
        dec     dx                       ;+4
        out     dx, al 
        dec     dx                       ;+3
        out     dx, al
        dec     dx                       ;+2
        out     dx, al
        
        add     dx, 5			 ;+7 Command
        mov     al, 08h			 ; Device RESET
        out     dx, al
        
        mov     ecx, 0FFFFh

.loop2:
        out    0EBh, al                  ; задержка

        in     al, dx                    ;+7 Status
        test   al, 80h                   ;BSY  
        jz    .ok2
        loop    .loop2

.timeout2:
        ; время вышло - устройства нет
        mov    eax, 2
        
        mov    ecx, esi
        shl    eax, cl   
        not    eax
        and    dword [IDEHDD_CD], eax
      
        sub    dx, 7                     ;+0
        jmp    .end

.ok2:
        sub    dx, 6                     ;+1
        in     al, dx
        add    dx, 6                     ;+7

        cmp    edi, 1
        je     .label3
        cmp    al, 1
        je     .label4
        sub    dx, 7                     ;+0
        jmp    .other2

.label3:
        cmp    al, 1
        je     .label4
        cmp    al, 80h
        je     .label4
        sub    dx, 7                     ;+0
        jmp    .other2
        
.label4:
        dec    dx                        ;+6
        dec    dx                        ;+5
        in     al, dx
        mov    bl, al
        shl    ebx, 8
        dec    dx                        ;+4
        in     al, dx
        mov    bl, al
        shl    ebx, 8
        dec    dx                        ;+3
        in     al, dx
        mov    bl, al
        shl    ebx, 8
        dec    dx                        ;+2
        in     al, dx
        mov    bl, al
        sub    dx, 2                     ;+0

.cd2:
        cmp    ebx, 0EB140101h       ; сидиром
        jne    .other2
        mov    eax, 2
        mov    ecx, esi
        shl    eax, cl   
        or     dword [IDEHDD_CD], eax
        jmp    .indef

.other2:
        mov    eax, 3
        mov    ecx, esi
        shl    eax, cl   
        not    eax
        and    dword [IDEHDD_CD], eax
        
.indef:
        add    dx, 6     ;+6 command
        mov    eax, edi
        shl    al, 4
        out    dx, al
        inc    dx        ;+7 command
           
        mov    eax, dword [IDEHDD_CD]
        mov    ecx, esi
        shr    eax, cl   
        and    al,  3

        cmp    al, 0
        je     .end
        cmp    al, 1
        jne    .cd3
        mov    al, 0ECh  ; IDENTIFY DEVICE
        out    dx,al
        jmp    .read
.cd3:
        cmp    al, 2
        jne    .end
        mov    al, 0A1h   ; IDENTIFY PACKET DEVICE
        out    dx,al
        
.read:
        mov    ecx, 0FFFFh

.loop3:
        dec    ecx
        jz     .timeout3  
        out    0EBh, AL        ; задержка
 
        in     al, dx          ;+7 Status
        test   al, 80h         ; состояние сигнала BSY
        jnz    .loop3
        test   al, 08h         ; состояние сигнала DRQ
        jz     .loop3
        jmp    .ok3

        .timeout3:
        mov    eax, 3
        
        mov    ecx, esi
        shl    eax, cl   
        not    eax
        and    dword [IDEHDD_CD], eax         
       
        sub    dx, 7           ;+0 
        jmp    .end
        
.ok3:
        xchg    edi, eax
        mov     edi, buf       ;offset buf
        sub     dx, 7          ;+0 регистр данных
        mov     cx, 256        ;число считываемых слов
        rep     insw           ;принять блок данных
        xchg    edi, eax

        mov     ecx, 255
        mov     ax, word [buf] 

.loop4:      ; проверяем на муссор вернулись одинаковые слова
        mov    bx, word [buf + ecx*2]
        cmp    ax,bx
        jne    .ok4

.equ:
        loop .loop4

.error: 
        mov    eax, 3
        
        mov    ecx, esi
        shl    eax, cl   
        not    eax
        and    dword [IDEHDD_CD],eax         
       
        sub    dx, 7      ;+0           
        jmp    .end
        
.ok4:
        ; Все проверки пройдены
        ; LBA48
        mov    ax, word[buf+86*2]
        shr    ax, 10
        and    ax, 1
        mov    ecx, esi
        shr    ecx, 1
        shl    eax, cl   
        or     [IDELBA48],ax
            
.end:
        popad
        ret

Addr_PCI  DD  0            ; Адресс PCI устройства
;**********************
;Функция читает один регистр из конфигурационного пространства устройства 
;по адресу Addr и заносит его в EAX.  
;**********************
ReadPCIRegistr: 
        mov    eax, [Addr_PCI]    ; 
        and    eax, 0FFFFFFFCh    ; Проверяем Addr в начале должен быть два 00
        or     eax, 80000000h     ; 31 бит обязан быть единицей.
        mov    dx, 0CF8h
        out    dx, EAX            ; Устанавливаем адрес
        mov    dx, 0CFCh
        in     eax, DX            ; Читаем регистр
        push   eax           
        xor    eax, eax           ; Сбрасываем адрес
        mov    dx, 0CF8h          ; Чтобы не было претензий.
        out    dx, eax            ;
        pop    eax
        ret
 
;*********************************
; Функция для поиска устройства по его классу
; EAX -его базовый класс.
; На выходи адрес если нет то -1
;***********************************
FindPCIDevice3: 
        push   ebx
        push   ecx
        push   edx

        mov    ebx, eax           ; Сохраняем

        mov    ecx, [Addr_PCI]    ; Счетчик он же адрес
        and    ecx, 0FFFFFFFCh    ; Проверяем Addr в начале должен быть два 00
        or     ecx, 80000000h     ; 31 бит обязан быть единицей.

.Label1:
        and    ecx, 0FFFFFF00h    ; Выравниваем
        mov    eax, ecx
        mov    dx, 0CF8h
        out    dx, eax            ; Устанавливаем адрес
        mov    dx, 0CFCh
        in     eax, dx            ; Читаем регистр
        cmp    eax, 0FFFFFFFFh    ; Не существующее устройство.
        je     .Label2
        add    ecx, 08            ; Наш Регистр
        mov    eax, ecx
        mov    dx, 0CF8h
        out    dx, eax            ; Устанавливаем адрес
        mov    dx, 0CFCh
        in     eax, dx            ; Читаем регистр
        shr    eax, 24            ; Base Class Code  
        cmp    eax, ebx
        je     .Label3            ; Ура: нашли!
 
.Label2:
        add    ecx, 256
                       ; Нужно бы добавить проверку на то, есть функции или нет.
        cmp    ecx, 80FFFF00h    ; Максимум 256 шин.             
        jne    .Label1
        mov    ecx, 0FFFFFFFFh   ; Не нашли 

.Label3:
        xor    eax, eax          ; Сбрасываем адрес
        mov    dx, 0CF8h         ; Чтобы не было претензий.
        out    dx, eax           ;
 
        and    ecx, 0FFFFFF00h   ; Сбрасываем индекс регистра
        mov    [Addr_PCI], ECX
        cmp    ecx, 0FFFFFF00h
        jne    .exit
        mov    ecx, 0FFFFFFFFh   ; Не нашли 

.exit:
        mov    eax, ecx
        pop    edx
        pop    ecx
        pop    ebx
        ret

;**********************************************
;*    ПОИСК КОНТРОЛЕРОВ и ЧЕТЕНИЕ ИХ ПОРТОВ
;*    IDEBasesPorts - базовые порты
FindBasesPorts:
        push   eax
        push   esi               ;
        push   edi               ; 
        
        xor    esi, esi
        xor    edi, edi
         
        mov    eax, 00           ;
        mov    [Addr_PCI], eax   ; B0:D0:F0
.Next:
        mov    eax, 01           ; Base Class Code =01 накопитель
        call   FindPCIDevice3
        cmp    eax, 0FFFFFFFFh
        je     .end
        add    [Addr_PCI], 8
        call   ReadPCIRegistr
        and    eax, 0FFFF0000h   ; Class Code 
        cmp    eax, 001010000h   ; IDE, SATA маскирующийся под IDE 
        je     .IDE 
        cmp    eax, 001040000h   ; RAID,SATA маскирующийся под RAID 
        jne    .NotIDE         
.IDE:
        add    [Addr_PCI], 8     ;  8+8=10h
        call   ReadPCIRegistr 
        and    eax, 0FFFCh       ; зануляем лишнее
        cmp    eax, 0
        jne    .native1
        mov    eax, 01F0h
.native1:
        mov    [IDEBasesPorts+esi], ax

        add    [Addr_PCI], 4     ;  8+8+4=14h
        call   ReadPCIRegistr 
        and    eax, 0FFFCh       ; зануляем лишнее
        cmp    eax, 0
        jne    .native2
        mov    eax, 03F4h
.native2:
        add    ax, 2             ; Порт контроля+2
        mov    [IDEBasesPorts+esi+2], ax
        
.last:
        add    esi, 4

        mov    byte [Addr_PCI], 18h  ;  14h+4=18h
        call   ReadPCIRegistr 
        and    eax, 0FFFCh           ; обнуляем лишнее
        cmp    eax, 0
        jne    .native3
        mov    eax, 0170h
.native3:
        mov    [IDEBasesPorts+esi], ax
 
        mov    byte [Addr_PCI],1Ch   ;  18h+4=1Ch
        call   ReadPCIRegistr 
        and    eax, 0FFFCh           ; зануляем лишнее
        cmp    eax, 0
        jne    .native4
        mov    eax, 0374h
.native4:
        add    ax, 2                 ; Порт контроля+2
        mov    [IDEBasesPorts+esi+2], ax
 
.MasterBus:
        add    esi, 4 
        mov    byte [Addr_PCI], 20h  ;  1Ch+4=20h
        call   ReadPCIRegistr 
        and    eax, 0FFFCh           ; зануляем лишнее Bus Master
        mov    [IDEBusMaster+edi*2], eax

        add    [Addr_PCI], 1Ch       ;  1Ch+20h=3Ch
        call   ReadPCIRegistr 
        and    eax, 0FFh             ; зануляем лишнее Interrupt Line (IRQ)
        mov    byte [IDEBusIRQ+edi], al
 
        inc    edi
.NotIDE:
        and    [Addr_PCI], 0FFFFFF00h
        add    [Addr_PCI], 100h
        cmp    esi, IDEMaxCanals*4            ; 8*4=20h 
        jne    .Next

        pop    edi
        pop    esi
        pop    eax
        ret
Advertisement