1///! AHCI Device helper functions 2#include <barrelfish/barrelfish.h> 3#include <barrelfish/deferred.h> 4 5#include "blk_ahci.h" 6#include "../blk_debug.h" 7 8#include "ahci_dev.h" 9 10size_t ahci_port_offset(uint32_t port) 11{ 12 return 0x100 + port * 0x80; 13} 14 15bool ahci_port_is_idle(ahci_port_t* port) 16{ 17 ahci_port_cmd_t cmd = ahci_port_cmd_rd(port); 18 uint8_t st = ahci_port_cmd_st_extract(cmd); 19 uint8_t cr = ahci_port_cmd_cr_extract(cmd); 20 uint8_t fre = ahci_port_cmd_fre_extract(cmd); 21 22 return st == 0 && cr == 0 && fre == 0; 23} 24 25bool ahci_port_is_ready(ahci_port_t* port) 26{ 27 uint8_t busy = ahci_port_tfd_bsy_rdf(port); 28 uint8_t drq = ahci_port_tfd_drq_rdf(port); 29 return busy == 0 && drq == 0; 30} 31 32bool ahci_port_is_functional(ahci_port_t* port) 33{ 34 uint8_t det = ahci_port_ssts_det_rdf(port); 35 return ahci_port_is_ready(port) && det == 0x3; 36} 37 38bool ahci_port_slot_free(ahci_port_t* port, uint8_t slot) 39{ 40 bool ci_free = (ahci_port_ci_rd(port) & (1<<slot)) == 0; 41 bool sact_free = (ahci_port_sact_rd(port) & (1<<slot)) == 0; 42 return ci_free && sact_free; 43} 44 45void ahci_port_start(ahci_port_t* port) 46{ 47 assert(ahci_port_is_functional(port)); 48 ahci_port_cmd_st_wrf(port, 0x1); 49} 50 51void ahci_port_stop(ahci_port_t* port) 52{ 53 ahci_port_cmd_st_wrf(port, 0); 54 55 ahci_port_cmd_t cmd = ahci_port_cmd_rd(port); 56 while (ahci_port_cmd_cr_extract(cmd) != 0) { 57 // TODO should clear in 500ms 58 } 59 60 ahci_port_cmd_fre_wrf(port, 0); 61 while (ahci_port_cmd_fr_rdf(port) != 0) { 62 // TODO should clear in 500ms 63 } 64} 65 66bool ahci_port_is_running(ahci_port_t* port) 67{ 68 return ahci_port_cmd_st_rdf(port) > 0; 69} 70 71uint32_t ahci_port_probe(ahci_port_t* port) 72{ 73 if (ahci_port_ssts_det_rdf(port) == 0x03) { 74 return ahci_port_sig_rd(port); 75 } 76 77 return 0; 78} 79 80void ahci_hba_reset(ahci_hba_t* controller) 81{ 82 ahci_hba_ghc_t ghc = ahci_hba_ghc_rd(controller); 83 BLK_DEBUG("Resetting HBA (setting ghc = %x)...\n", ghc); 84 ghc = ahci_hba_ghc_hr_insert(ghc, 1); 85 ahci_hba_ghc_wr(controller, ghc); 86 barrelfish_usleep(200000); 87 while (1) { 88 ghc = ahci_hba_ghc_rd(controller); 89 if (ahci_hba_ghc_hr_extract(ghc) == 0) { 90 BLK_DEBUG("reset done\n"); 91 break; 92 } 93 } 94} 95 96void ahci_hba_irq_enable(ahci_hba_t* controller) 97{ 98 BLK_DEBUG("Enabling HBA Interrupts\n"); 99 ahci_hba_ghc_t ghc = ahci_hba_ghc_rd(controller); 100 ghc = ahci_hba_ghc_ie_insert(ghc, 1); 101 ahci_hba_ghc_wr(controller, ghc); 102} 103 104void ahci_hba_irq_disable(ahci_hba_t* controller) 105{ 106 BLK_DEBUG("Disable HBA Interrupts\n"); 107 ahci_hba_ghc_t ghc = ahci_hba_ghc_rd(controller); 108 ghc = ahci_hba_ghc_ie_insert(ghc, 1); 109 ahci_hba_ghc_wr(controller, ghc); 110} 111 112uint32_t ahci_hba_get_num_ports(ahci_hba_t* controller) 113{ 114 return ahci_hba_cap_np_extract(ahci_hba_cap_rd(controller)) + 1; 115} 116 117uint32_t ahci_hba_get_command_slots(ahci_hba_t* controller) 118{ 119 return ahci_hba_cap_ncs_extract(ahci_hba_cap_rd(controller)); 120} 121 122bool ahci_port_is_implemented(ahci_hba_t* controller, size_t port) 123{ 124 return (ahci_hba_pi_rd(controller) & (1 << port)) > 0; 125} 126 127void ahci_port_print_identification(ata_identify_t *id) 128{ 129 char* buf2 = malloc(10*4096); 130 assert(buf2 != NULL); 131 ata_identify_pr(buf2, 10*4096, id); 132 puts(buf2); 133 free(buf2); 134} 135 136errval_t ahci_hba_init(ahci_hba_t* controller) 137{ 138 ahci_hba_reset(controller); 139 140 // Make sure AHCI is enabled: 141 BLK_DEBUG("Setting controller into AHCI mode\n"); 142 ahci_hba_ghc_t ghc = ahci_hba_ghc_rd(controller); 143 ghc = ahci_hba_ghc_ae_insert(ghc, 1); 144 ahci_hba_ghc_wr(controller, ghc); 145 146 ahci_hba_irq_disable(controller); 147 148 return SYS_ERR_OK; 149} 150