Patrick Georgi | afd4c87 | 2020-05-05 23:43:18 +0200 | [diff] [blame] | 1 | /* ahci.c: dump AHCI registers */ |
Patrick Georgi | ac95903 | 2020-05-05 22:49:26 +0200 | [diff] [blame] | 2 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Iru Cai | 904538b | 2016-06-08 22:39:22 +0800 | [diff] [blame] | 3 | |
| 4 | #include <stdio.h> |
| 5 | #include <stdlib.h> |
| 6 | #include <inttypes.h> |
| 7 | #include "inteltool.h" |
| 8 | |
Iru Cai | 904538b | 2016-06-08 22:39:22 +0800 | [diff] [blame] | 9 | static const char *ghc_regs[] = { |
| 10 | "CAP", "GHC", "IS", "PI", |
| 11 | "VS", "CCC_CTL", "CCC_PORTS", "EM_LOC", |
| 12 | "EM_CTL", "CAP2", "BOHC" |
| 13 | }; |
| 14 | |
| 15 | static const char *port_ctl_regs[] = { |
| 16 | "PxCLB", "PxCLBU", "PxFB", "PxFBU", |
| 17 | "PxIS", "PxIE", "PxCMD", "Reserved", |
| 18 | "PxTFD", "PxSIG", "PxSSTS", "PxSCTL", |
| 19 | "PxSERR", "PxSACT", "PxCI", "PxSNTF", |
| 20 | "PxFBS", "PxDEVSLP", "Reserved" |
| 21 | }; |
| 22 | |
Michael Niewöhner | fe8170f | 2020-03-13 21:18:04 +0100 | [diff] [blame] | 23 | static const io_register_t sunrise_ahci_cfg_registers[] = { |
| 24 | {0x0, 4, "ID"}, |
| 25 | {0x4, 2, "CMD"}, |
| 26 | {0x6, 2, "STS"}, |
| 27 | {0x8, 1, "RID"}, |
| 28 | {0x9, 1, "PI"}, |
| 29 | {0xa, 2, "CC"}, |
| 30 | {0xc, 1, "CLS"}, |
| 31 | {0xd, 1, "MLT"}, |
| 32 | {0xe, 1, "HTYPE"}, |
| 33 | {0x10, 4, "MXTBA"}, |
| 34 | {0x14, 4, "MXPBA"}, |
| 35 | {0x20, 4, "AIDPBA"}, |
| 36 | {0x24, 4, "ABAR"}, |
| 37 | {0x2c, 4, "SS"}, |
| 38 | {0x34, 1, "CAP"}, |
| 39 | {0x3c, 2, "INTR"}, |
| 40 | {0x70, 2, "PID"}, |
| 41 | {0x72, 2, "PC"}, |
| 42 | {0x74, 2, "PMCS"}, |
| 43 | {0x80, 2, "MID"}, |
| 44 | {0x82, 2, "MC"}, |
| 45 | {0x84, 4, "MA"}, |
| 46 | {0x88, 2, "MD"}, |
| 47 | {0x90, 4, "MAP"}, |
| 48 | {0x94, 4, "PCS"}, |
| 49 | {0x9c, 4, "SATAGC"}, |
| 50 | {0xa0, 1, "SIRI"}, |
| 51 | {0xa4, 4, "SIRD"}, |
| 52 | {0xa8, 4, "SATACR0"}, |
| 53 | {0xac, 4, "SATACR1"}, |
| 54 | {0xc0, 4, "SP"}, |
| 55 | {0xd0, 2, "MXID"}, |
| 56 | {0xd2, 2, "MXC"}, |
| 57 | {0xd4, 4, "MXT"}, |
| 58 | {0xd8, 4, "MXP"}, |
| 59 | {0xe0, 4, "BFCS"}, |
| 60 | {0xe4, 4, "BFTD1"}, |
| 61 | {0xe8, 4, "BFTD2"}, |
| 62 | }; |
| 63 | |
| 64 | static const io_register_t sunrise_ahci_sir_registers[] = { |
| 65 | {0x80, 4, "SQUELCH"}, |
| 66 | {0x90, 4, "SATA_MPHY_PG"}, |
| 67 | {0xa4, 4, "OOBRETR"}, |
| 68 | }; |
| 69 | |
Iru Cai | 904538b | 2016-06-08 22:39:22 +0800 | [diff] [blame] | 70 | #define NUM_GHC (sizeof(ghc_regs)/sizeof(ghc_regs[0])) |
| 71 | #define NUM_PORTCTL (sizeof(port_ctl_regs)/sizeof(port_ctl_regs[0])) |
| 72 | |
Nico Huber | c272a87 | 2017-03-31 13:12:49 +0200 | [diff] [blame] | 73 | static void print_port(const uint8_t *const mmio, size_t port) |
| 74 | { |
| 75 | size_t i; |
| 76 | printf("\nPort %zu Control Registers:\n", port); |
| 77 | const uint8_t *const mmio_port = mmio + 0x100 + port * 0x80; |
| 78 | for (i = 0; i < 0x80; i += 4) { |
| 79 | if (i / 4 < NUM_PORTCTL) { |
| 80 | printf("0x%03zx: 0x%08x (%s)\n", |
| 81 | (size_t)(mmio_port - mmio) + i, |
Michael Niewöhner | 10d5221 | 2020-03-13 19:08:21 +0100 | [diff] [blame] | 82 | read32(mmio_port + i), port_ctl_regs[i / 4]); |
| 83 | } else if (read32(mmio_port + i)) { |
Nico Huber | c272a87 | 2017-03-31 13:12:49 +0200 | [diff] [blame] | 84 | printf("0x%03zx: 0x%08x (Reserved)\n", |
Michael Niewöhner | 10d5221 | 2020-03-13 19:08:21 +0100 | [diff] [blame] | 85 | (size_t)(mmio_port - mmio) + i, |
| 86 | read32(mmio_port + i)); |
Nico Huber | c272a87 | 2017-03-31 13:12:49 +0200 | [diff] [blame] | 87 | } |
| 88 | } |
| 89 | } |
| 90 | |
Iru Cai | 904538b | 2016-06-08 22:39:22 +0800 | [diff] [blame] | 91 | int print_ahci(struct pci_dev *ahci) |
| 92 | { |
Michael Niewöhner | 8676c26 | 2020-03-13 21:15:55 +0100 | [diff] [blame] | 93 | size_t ahci_registers_size = 0, i; |
Michael Niewöhner | e6cff0d | 2020-03-13 21:17:21 +0100 | [diff] [blame] | 94 | size_t ahci_cfg_registers_size = 0; |
| 95 | const io_register_t *ahci_cfg_registers; |
| 96 | size_t ahci_sir_offset = 0; |
| 97 | size_t ahci_sir_registers_size = 0; |
| 98 | const io_register_t *ahci_sir_registers; |
Nico Huber | da94e17 | 2017-03-30 17:47:24 +0200 | [diff] [blame] | 99 | |
Iru Cai | 904538b | 2016-06-08 22:39:22 +0800 | [diff] [blame] | 100 | if (!ahci) { |
| 101 | puts("No SATA device found"); |
| 102 | return 0; |
| 103 | } |
| 104 | printf("\n============= AHCI Registers ==============\n\n"); |
Nico Huber | da94e17 | 2017-03-30 17:47:24 +0200 | [diff] [blame] | 105 | |
Michael Niewöhner | 8676c26 | 2020-03-13 21:15:55 +0100 | [diff] [blame] | 106 | switch (ahci->device_id) { |
| 107 | case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_SATA: |
| 108 | case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SATA: |
| 109 | ahci_registers_size = 0x800; |
Michael Niewöhner | fe8170f | 2020-03-13 21:18:04 +0100 | [diff] [blame] | 110 | ahci_sir_offset = 0xa0; |
| 111 | ahci_cfg_registers = sunrise_ahci_cfg_registers; |
| 112 | ahci_cfg_registers_size = ARRAY_SIZE(sunrise_ahci_cfg_registers); |
| 113 | ahci_sir_registers = sunrise_ahci_sir_registers; |
| 114 | ahci_sir_registers_size = ARRAY_SIZE(sunrise_ahci_sir_registers); |
Michael Niewöhner | 8676c26 | 2020-03-13 21:15:55 +0100 | [diff] [blame] | 115 | break; |
| 116 | default: |
| 117 | ahci_registers_size = 0x400; |
| 118 | } |
Nico Huber | da94e17 | 2017-03-30 17:47:24 +0200 | [diff] [blame] | 119 | |
Michael Niewöhner | e6cff0d | 2020-03-13 21:17:21 +0100 | [diff] [blame] | 120 | printf("\n============= AHCI Configuration Registers ==============\n\n"); |
| 121 | for (i = 0; i < ahci_cfg_registers_size; i++) { |
| 122 | switch (ahci_cfg_registers[i].size) { |
| 123 | case 4: |
| 124 | printf("0x%04x: 0x%08x (%s)\n", |
| 125 | ahci_cfg_registers[i].addr, |
| 126 | pci_read_long(ahci, ahci_cfg_registers[i].addr), |
| 127 | ahci_cfg_registers[i].name); |
| 128 | break; |
| 129 | case 2: |
| 130 | printf("0x%04x: 0x%04x (%s)\n", |
| 131 | ahci_cfg_registers[i].addr, |
| 132 | pci_read_word(ahci, ahci_cfg_registers[i].addr), |
| 133 | ahci_cfg_registers[i].name); |
| 134 | break; |
| 135 | case 1: |
| 136 | printf("0x%04x: 0x%02x (%s)\n", |
| 137 | ahci_cfg_registers[i].addr, |
| 138 | pci_read_byte(ahci, ahci_cfg_registers[i].addr), |
| 139 | ahci_cfg_registers[i].name); |
| 140 | break; |
| 141 | } |
| 142 | } |
| 143 | |
| 144 | printf("\n============= SATA Initialization Registers ==============\n\n"); |
| 145 | for (i = 0; i < ahci_sir_registers_size; i++) { |
| 146 | pci_write_byte(ahci, ahci_sir_offset, ahci_sir_registers[i].addr); |
| 147 | switch (ahci_sir_registers[i].size) { |
| 148 | case 4: |
| 149 | printf("0x%02x: 0x%08x (%s)\n", |
| 150 | ahci_sir_registers[i].addr, |
| 151 | pci_read_long(ahci, ahci_sir_offset), |
| 152 | ahci_sir_registers[i].name); |
| 153 | break; |
| 154 | case 2: |
| 155 | printf("0x%02x: 0x%04x (%s)\n", |
| 156 | ahci_sir_registers[i].addr, |
| 157 | pci_read_word(ahci, ahci_sir_offset), |
| 158 | ahci_sir_registers[i].name); |
| 159 | break; |
| 160 | case 1: |
| 161 | printf("0x%02x: 0x%02x (%s)\n", |
| 162 | ahci_sir_registers[i].addr, |
| 163 | pci_read_byte(ahci, ahci_sir_offset), |
| 164 | ahci_sir_registers[i].name); |
| 165 | break; |
| 166 | } |
| 167 | } |
| 168 | |
Michael Niewöhner | 8676c26 | 2020-03-13 21:15:55 +0100 | [diff] [blame] | 169 | const pciaddr_t ahci_phys = ahci->base_addr[5] & ~0x7ULL; |
| 170 | printf("\n============= ABAR ==============\n\n"); |
| 171 | printf("ABAR = 0x%08llx (MEM)\n\n", (unsigned long long)ahci_phys); |
| 172 | const uint8_t *const mmio = map_physical(ahci_phys, ahci_registers_size); |
Iru Cai | 904538b | 2016-06-08 22:39:22 +0800 | [diff] [blame] | 173 | if (mmio == NULL) { |
| 174 | perror("Error mapping MMIO"); |
| 175 | exit(1); |
| 176 | } |
| 177 | |
| 178 | puts("Generic Host Control Registers:"); |
| 179 | for (i = 0; i < 0x100; i += 4) { |
Nico Huber | c272a87 | 2017-03-31 13:12:49 +0200 | [diff] [blame] | 180 | if (i / 4 < NUM_GHC) { |
| 181 | printf("0x%03zx: 0x%08x (%s)\n", |
Michael Niewöhner | 10d5221 | 2020-03-13 19:08:21 +0100 | [diff] [blame] | 182 | i, read32(mmio + i), ghc_regs[i / 4]); |
| 183 | } else if (read32(mmio + i)) { |
| 184 | printf("0x%03zx: 0x%08x (Reserved)\n", i, |
| 185 | read32(mmio + i)); |
Nico Huber | c272a87 | 2017-03-31 13:12:49 +0200 | [diff] [blame] | 186 | } |
Iru Cai | 904538b | 2016-06-08 22:39:22 +0800 | [diff] [blame] | 187 | } |
| 188 | |
Michael Niewöhner | 8676c26 | 2020-03-13 21:15:55 +0100 | [diff] [blame] | 189 | const size_t max_ports = (ahci_registers_size - 0x100) / 0x80; |
Nico Huber | da94e17 | 2017-03-30 17:47:24 +0200 | [diff] [blame] | 190 | for (i = 0; i < max_ports; i++) { |
Michael Niewöhner | 10d5221 | 2020-03-13 19:08:21 +0100 | [diff] [blame] | 191 | if (read32(mmio + 0x0c) & 1 << i) |
Nico Huber | c272a87 | 2017-03-31 13:12:49 +0200 | [diff] [blame] | 192 | print_port(mmio, i); |
Iru Cai | 904538b | 2016-06-08 22:39:22 +0800 | [diff] [blame] | 193 | } |
| 194 | |
Michael Niewöhner | 8676c26 | 2020-03-13 21:15:55 +0100 | [diff] [blame] | 195 | puts("\nOther registers:"); |
| 196 | for (i = 0x500; i < ahci_registers_size; i += 4) { |
Michael Niewöhner | 10d5221 | 2020-03-13 19:08:21 +0100 | [diff] [blame] | 197 | if (read32(mmio + i)) |
| 198 | printf("0x%03zx: 0x%08x\n", i, read32(mmio + i)); |
Nico Huber | da94e17 | 2017-03-30 17:47:24 +0200 | [diff] [blame] | 199 | } |
| 200 | |
Michael Niewöhner | 8676c26 | 2020-03-13 21:15:55 +0100 | [diff] [blame] | 201 | unmap_physical((void *)mmio, ahci_registers_size); |
Iru Cai | 904538b | 2016-06-08 22:39:22 +0800 | [diff] [blame] | 202 | return 0; |
| 203 | } |