Subversion Repositories Kolibri OS

Rev

Rev 9139 | Rev 9141 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 9139 Rev 9140
Line 23... Line 23...
23
AHCI_DEV_PM     = 3
23
AHCI_DEV_PM     = 3
24
AHCI_DEV_SATAPI = 4
24
AHCI_DEV_SATAPI = 4
Line 25... Line 25...
25
 
25
 
26
; ATA commands
26
; ATA commands
-
 
27
ATA_IDENTIFY        = 0xEC
Line 27... Line 28...
27
ATA_IDENTIFY    = 0xEC
28
ATA_CMD_READ_DMA_EX = 0x25
28
 
29
 
29
; ATA constants
30
; ATA constants
Line 161... Line 162...
161
    fb            dd ? ; FIS base
162
    fb            dd ? ; FIS base
162
    ctba_arr      rd 32 ; ctba_arr[0] = clb[0].ctba, ... and so on.
163
    ctba_arr      rd 32 ; ctba_arr[0] = clb[0].ctba, ... and so on.
163
    port          dd ? ; address of correspoding HBA_PORT structure
164
    port          dd ? ; address of correspoding HBA_PORT structure
164
    portno        dd ? ; port index, 0..31
165
    portno        dd ? ; port index, 0..31
165
    drive_type    db ? ; drive type
166
    drive_type    db ? ; drive type
-
 
167
    sector_count  dq ? ; number of sectors
166
ends
168
ends
Line 167... Line 169...
167
 
169
 
168
; Register FIS – Host to Device
170
; Register FIS – Host to Device
169
struct FIS_REG_H2D
171
struct FIS_REG_H2D
Line 308... Line 310...
308
; --------------------------------------------------
310
; --------------------------------------------------
309
uglobal
311
uglobal
310
align 4
312
align 4
311
        ahci_controller AHCI_DATA
313
        ahci_controller AHCI_DATA
312
        port_data_arr   rb (sizeof.PORT_DATA*AHCI_MAX_PORTS)
314
        port_data_arr   rb (sizeof.PORT_DATA*AHCI_MAX_PORTS)
-
 
315
        ahci_mutex      MUTEX
-
 
316
endg
-
 
317
 
-
 
318
iglobal
-
 
319
align 4
-
 
320
ahci_callbacks:
-
 
321
    dd  ahci_callbacks.end - ahci_callbacks
-
 
322
    dd  0   ; no close function
-
 
323
    dd  0   ; no closemedia function
-
 
324
    dd  ahci_querymedia
-
 
325
    dd  ahci_read
-
 
326
    dd  0;ahci_write
-
 
327
    dd  0   ; no flush function
-
 
328
    dd  0   ; use default cache size
-
 
329
.end:
-
 
330
hd_name db 'hd', 0, 0, 0
-
 
331
hd_counter dd 0
313
endg
332
endg
Line 314... Line 333...
314
 
333
 
315
; -----------------------------------------------------------------------
334
; -----------------------------------------------------------------------
316
; detect ahci controller and initialize
335
; detect ahci controller and initialize
317
align 4
336
align 4
-
 
337
ahci_init:
-
 
338
        mov     ecx, ahci_mutex
-
 
339
        call    mutex_init
318
ahci_init:
340
 
319
        mov     ecx, ahci_controller
341
        mov     ecx, ahci_controller
320
        mov     esi, pcidev_list
342
        mov     esi, pcidev_list
321
.find_ahci_ctr:
343
.find_ahci_ctr:
322
        mov     esi, [esi + PCIDEV.fd]
344
        mov     esi, [esi + PCIDEV.fd]
Line 431... Line 453...
431
        ; calculate irq line
453
        ; calculate irq line
432
        ; ahciHBA->ghc |= AHCI_GHC_IE;
454
        ; ahciHBA->ghc |= AHCI_GHC_IE;
433
        ; IDT::RegisterInterruptHandler(irq, InterruptHandler);
455
        ; IDT::RegisterInterruptHandler(irq, InterruptHandler);
434
        ; ahciHBA->is = 0xffffffff;
456
        ; ahciHBA->is = 0xffffffff;
Line -... Line 457...
-
 
457
 
435
 
458
        mov     [hd_counter], 0
436
        xor     ebx, ebx
459
        xor     ebx, ebx
437
.detect_drives:
460
.detect_drives:
438
        cmp     ebx, AHCI_MAX_PORTS
461
        cmp     ebx, AHCI_MAX_PORTS
Line 536... Line 559...
536
 
559
 
Line 537... Line 560...
537
        DEBUGF  1, "K: AHCI: found drive on port %u: TYPE = %u\n", ebx, [ecx + PORT_DATA.drive_type]
560
        DEBUGF  1, "K: AHCI: found drive on port %u: TYPE = %u\n", ebx, [ecx + PORT_DATA.drive_type]
Line -... Line 561...
-
 
561
 
-
 
562
        stdcall ahci_port_identify, ecx
-
 
563
 
-
 
564
        cmp     [ecx + PORT_DATA.drive_type], AHCI_DEV_SATA
-
 
565
        jne     .after_add_disk ; skip adding disk code
-
 
566
        ; register disk in system:
-
 
567
        push    ecx edx
-
 
568
        mov     eax, [hd_counter]
-
 
569
        xor     edx, edx
-
 
570
        mov     ecx, 10
-
 
571
        div     ecx ; eax = hd_counter / 10, edx = hd_counter % 10
-
 
572
        test    eax, eax
-
 
573
        jz      .concat_one
-
 
574
        add     al, '0'
-
 
575
        mov     byte [hd_name + 2], al
-
 
576
        add     dl, '0'
-
 
577
        mov     byte [hd_name + 3], dl
-
 
578
        jmp     .endif1
-
 
579
.concat_one:
-
 
580
        add     dl, '0'
-
 
581
        mov     byte [hd_name + 2], dl
-
 
582
.endif1:
-
 
583
        pop     edx ecx
-
 
584
 
-
 
585
        DEBUGF  1, "adding '%s'\n", hd_name
-
 
586
 
-
 
587
        stdcall disk_add, ahci_callbacks, hd_name, ecx, 0
-
 
588
        test    eax, eax
-
 
589
        jz      .disk_add_fail
-
 
590
        stdcall disk_media_changed, eax, 1 ; system will scan for partitions on disk
-
 
591
        jmp     .after_add_disk
-
 
592
 
-
 
593
.disk_add_fail:
538
 
594
        DEBUGF  1, "Failed to add disk\n"
539
        stdcall ahci_port_identify, ecx
595
.after_add_disk:
540
 
596
 
Line 572... Line 628...
572
 
628
 
573
        cmp     eax, -1
629
        cmp     eax, -1
Line 574... Line 630...
574
        jne      .cmdslot_found
630
        jne      .cmdslot_found
-
 
631
 
Line 575... Line 632...
575
 
632
        DEBUGF  1, "No free cmdslot on port %u\n", [esi + PORT_DATA.portno]
576
        DEBUGF  1, "No free cmdslot on port %u\n", [esi + PORT_DATA.portno]
633
        jmp     .ret
577
 
634
 
Line 664... Line 721...
664
.ret:
721
.ret:
665
        popad
722
        popad
666
        ret
723
        ret
667
endp
724
endp
Line -... Line 725...
-
 
725
 
-
 
726
proc ahci_querymedia stdcall, pdata, mediainfo
-
 
727
        push    ecx edx
-
 
728
        mov     eax, [mediainfo]
-
 
729
        mov     edx, [pdata]
-
 
730
        mov     [eax + DISKMEDIAINFO.Flags], 0
-
 
731
        mov     [eax + DISKMEDIAINFO.SectorSize], 512
-
 
732
        mov     ecx, dword[edx + PORT_DATA.sector_count]
-
 
733
        mov     dword [eax + DISKMEDIAINFO.Capacity], ecx
-
 
734
        mov     ecx, dword[edx + PORT_DATA.sector_count + 4]
-
 
735
        mov     dword [eax + DISKMEDIAINFO.Capacity + 4], ecx
-
 
736
        pop     edx ecx
-
 
737
        xor     eax, eax
-
 
738
        ret
-
 
739
endp
-
 
740
 
-
 
741
; Read sectors
-
 
742
; return value: 0 = success, otherwise = error
-
 
743
proc ahci_read stdcall pdata: dword, buffer: dword, startsector: qword, numsectors_ptr:dword
-
 
744
        locals
-
 
745
            cmdslot dd ?
-
 
746
            cmdheader dd ?
-
 
747
            cmdtable  dd ?
-
 
748
            numsectors dd ?
-
 
749
            buffer_pos dd ?
-
 
750
            buffer_length dd ?
-
 
751
        endl
-
 
752
 
-
 
753
        pushad
-
 
754
 
-
 
755
        mov     ecx, ahci_mutex
-
 
756
        call    mutex_lock
-
 
757
 
-
 
758
;         xor     ecx, ecx
-
 
759
;         mov     esi, [buffer]
-
 
760
; .print_data:
-
 
761
;         cmp     ecx, 512
-
 
762
;         jae     .end_print_data
-
 
763
 
-
 
764
;         mov     al, byte [esi + ecx]
-
 
765
;         mov     byte [tmpstr], al
-
 
766
;         mov     byte [tmpstr + 1], 0
-
 
767
;         DEBUGF  1, "0x%x(%s) ", al:1, tmpstr
-
 
768
 
-
 
769
;         inc     ecx
-
 
770
;         jmp     .print_data
-
 
771
; .end_print_data:
-
 
772
;         DEBUGF  1, "\n"
-
 
773
 
-
 
774
        mov     eax, [numsectors_ptr]
-
 
775
        mov     eax, [eax]
-
 
776
        mov     [numsectors], eax
-
 
777
 
-
 
778
        DEBUGF  1, "  ahci_read: buffer = 0x%x, startsector = 0x%x:%x, numsectors = %u\n", [buffer], [startsector], [startsector + 4], eax
-
 
779
 
-
 
780
        mov     esi, [pdata] ; esi - address of PORT_DATA struct of port
-
 
781
        mov     edi, [esi + PORT_DATA.port] ; edi - address of HBA_PORT struct of port
-
 
782
        mov     eax, edi
-
 
783
        call    ahci_find_cmdslot
-
 
784
        cmp     eax, -1
-
 
785
        jne      .cmdslot_found
-
 
786
 
-
 
787
        DEBUGF  1, "No free cmdslot on port %u\n", [esi + PORT_DATA.portno]
-
 
788
        jmp     .ret
-
 
789
 
-
 
790
.cmdslot_found:
-
 
791
        mov     [cmdslot], eax
-
 
792
        ; DEBUGF  1, "Found free cmdslot %u on port %u\n", [cmdslot], [esi + PORT_DATA.portno]
-
 
793
 
-
 
794
        shl     eax, BSF sizeof.HBA_CMD_HDR
-
 
795
        add     eax, [esi + PORT_DATA.clb]
-
 
796
        mov     [cmdheader], eax ; address of virtual mapping of command header
-
 
797
        mov     eax, [cmdslot]
-
 
798
        mov     eax, [esi + eax*4 + PORT_DATA.ctba_arr]
-
 
799
        mov     [cmdtable], eax ; address of virtual mapping of command table of command header
-
 
800
 
-
 
801
        mov     eax, [cmdheader]
-
 
802
        and     [eax + HBA_CMD_HDR.flags1], not 0x1F ; zero out lower 5 bits, they will be used for cfl
-
 
803
        or      [eax + HBA_CMD_HDR.flags1], (sizeof.FIS_REG_H2D / 4) ; set command fis length in dwords
-
 
804
        movzx   bx, [eax + HBA_CMD_HDR.flags1]
-
 
805
        btr     bx, 6 ; flag W = 0
-
 
806
        mov     [eax + HBA_CMD_HDR.flags1], bl
-
 
807
        movzx   bx, [eax + HBA_CMD_HDR.flags2]
-
 
808
        btr     bx, 2 ; flag C = 0
-
 
809
        mov     [eax + HBA_CMD_HDR.flags2], bl
-
 
810
 
-
 
811
        mov     ebx, [numsectors]
-
 
812
        shl     ebx, 9 ; *= 512
-
 
813
        mov     [buffer_length], ebx
-
 
814
        dec     ebx
-
 
815
        shr     ebx, 12 ; /= 4096
-
 
816
        inc     ebx
-
 
817
        mov     [eax + HBA_CMD_HDR.prdtl], bx
-
 
818
        ;DEBUGF  1, "  prdtl = %u\n", [eax + HBA_CMD_HDR.prdtl]:2
-
 
819
        
-
 
820
        ; zero out the command table with its prdt entries
-
 
821
        dec     ebx
-
 
822
        shl     ebx, BSF sizeof.HBA_PRDT_ENTRY
-
 
823
        add     ebx, sizeof.HBA_CMD_TBL
-
 
824
        stdcall _memset, [cmdtable], 0, ebx
-
 
825
        
-
 
826
        DEBUGF  1, "  prdtl = %u\n", [eax + HBA_CMD_HDR.prdtl]:2
-
 
827
        ;jmp     .ret
-
 
828
 
-
 
829
        xor     ecx, ecx
-
 
830
        movzx   edx, [eax + HBA_CMD_HDR.prdtl]
-
 
831
        dec     edx
-
 
832
        mov     eax, [buffer]
-
 
833
        mov     [buffer_pos], eax
-
 
834
 
-
 
835
.prdt_fill:
-
 
836
        cmp     ecx, edx
-
 
837
        jae     .prdt_fill_end
-
 
838
 
-
 
839
        mov     ebx, [buffer_pos]
-
 
840
        and     ebx, 0xFFF
-
 
841
        call    get_pg_addr ; eax = phys addr 
-
 
842
        add     eax, ebx
-
 
843
        DEBUGF  1, "  PHYS = 0x%x\n", eax
-
 
844
        mov     ebx, ecx
-
 
845
        shl     ebx, BSF sizeof.HBA_PRDT_ENTRY
-
 
846
        add     ebx, [cmdtable]
-
 
847
        add     ebx, HBA_CMD_TBL.prdt_entry ; now ebx - address of ecx'th prdt_entry
-
 
848
 
-
 
849
        mov     [ebx + HBA_PRDT_ENTRY.dba], eax
-
 
850
        mov     [ebx + HBA_PRDT_ENTRY.dbau], 0
-
 
851
        and     [ebx + HBA_PRDT_ENTRY.flags], not 0x3FFFFF ; zero out lower 22 bits, they used for byte count
-
 
852
        or      [ebx + HBA_PRDT_ENTRY.flags], 4096 - 1 ; reason why -1 see in spec on this field
-
 
853
        ; or      [eax + HBA_CMD_TBL.prdt_entry + HBA_PRDT_ENTRY.flags], 1 shl 31 ; enable interrupt on completion
-
 
854
 
-
 
855
        add     [buffer_pos], 4096
-
 
856
        sub     [buffer_length], 4096
-
 
857
 
-
 
858
        inc     ecx
-
 
859
        jmp     .prdt_fill
-
 
860
.prdt_fill_end:
-
 
861
 
-
 
862
        mov     ebx, [buffer_pos]
-
 
863
        and     ebx, 0xFFF
-
 
864
        call    get_pg_addr ; eax = phys addr 
-
 
865
        add     eax, ebx
-
 
866
        DEBUGF  1, "  PHYS. = 0x%x\n", eax
-
 
867
        mov     ebx, ecx
-
 
868
        shl     ebx, BSF sizeof.HBA_PRDT_ENTRY
-
 
869
        add     ebx, [cmdtable]
-
 
870
        add     ebx, HBA_CMD_TBL.prdt_entry ; now ebx - address of ecx'th prdt_entry
-
 
871
        mov     [ebx + HBA_PRDT_ENTRY.dba], eax
-
 
872
        mov     [ebx + HBA_PRDT_ENTRY.dbau], 0
-
 
873
        and     [ebx + HBA_PRDT_ENTRY.flags], not 0x3FFFFF ; zero out lower 22 bits, they used for byte count
-
 
874
        mov     eax, [buffer_length]
-
 
875
        dec     eax
-
 
876
        DEBUGF  1, " DBC = %u\n", eax
-
 
877
        or      [ebx + HBA_PRDT_ENTRY.flags], eax ; reason why -1 see in spec on this field
-
 
878
        ; or      [eax + HBA_CMD_TBL.prdt_entry + HBA_PRDT_ENTRY.flags], 1 shl 31 ; enable interrupt on completion
-
 
879
 
-
 
880
        mov     eax, [cmdtable]
-
 
881
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.fis_type], FIS_TYPE_REG_H2D
-
 
882
        movzx   ebx, byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.flags]
-
 
883
        bts     ebx, bit_AHCI_H2D_FLAG_CMD ; Set Command bit in H2D FIS.
-
 
884
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.flags], bl
-
 
885
 
-
 
886
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.command], ATA_CMD_READ_DMA_EX
-
 
887
 
-
 
888
        mov     ebx, dword [startsector]
-
 
889
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.lba0], bl
-
 
890
        shr     ebx, 8
-
 
891
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.lba1], bl
-
 
892
        shr     ebx, 8
-
 
893
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.lba2], bl
-
 
894
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.device], 1 shl 6 ; LBA mode
-
 
895
        shr     ebx, 8
-
 
896
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.lba3], bl
-
 
897
        mov     ebx, dword [startsector + 4]
-
 
898
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.lba4], bl
-
 
899
        shr     ebx, 8
-
 
900
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.lba5], bl
-
 
901
 
-
 
902
        mov     ebx, [numsectors]
-
 
903
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.countl], bl
-
 
904
        shr     ebx, 8
-
 
905
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.counth], bl
-
 
906
 
-
 
907
        ; Wait on previous command to complete, before issuing new command.
-
 
908
        stdcall ahci_port_wait, edi, AHCI_PORT_TIMEOUT
-
 
909
 
-
 
910
        mov     eax, [cmdslot]
-
 
911
        bts     [edi + HBA_PORT.command_issue], eax ; Issue the command
-
 
912
 
-
 
913
        ; Wait for command completion
-
 
914
        stdcall ahci_port_cmd_wait, edi, eax;, AHCI_PORT_CMD_TIMEOUT
-
 
915
 
-
 
916
        DEBUGF  1, "sata_error register = 0x%x\n", [edi + HBA_PORT.sata_error]
-
 
917
 
-
 
918
        DEBUGF  1, "reading completed\n"
-
 
919
 
-
 
920
        xor     ecx, ecx
-
 
921
        mov     esi, [buffer]
-
 
922
.print_data:
-
 
923
        cmp     ecx, 512
-
 
924
        jae     .end_print_data
-
 
925
 
-
 
926
        mov     al, byte [esi + ecx]
-
 
927
        mov     byte [tmpstr], al
-
 
928
        mov     byte [tmpstr + 1], 0
-
 
929
        DEBUGF  1, "0x%x(%s) ", al:1, tmpstr
-
 
930
 
-
 
931
        inc     ecx
-
 
932
        jmp     .print_data
-
 
933
.end_print_data:
-
 
934
        DEBUGF  1, "\n"
-
 
935
 
-
 
936
.ret:
-
 
937
        mov     ecx, ahci_mutex
-
 
938
        call    mutex_unlock
-
 
939
 
-
 
940
        popad
-
 
941
        xor     eax, eax
-
 
942
        ret
-
 
943
endp
Line 668... Line 944...
668
 
944
tmpstr    rb 16
669
 
945
 
670
; Start command engine
946
; Start command engine
671
; in: eax - address of HBA_PORT structure
947
; in: eax - address of HBA_PORT structure