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 |