OSDev.org https://forum.osdev.org/ |
|
AHCI can't read and write blocks https://forum.osdev.org/viewtopic.php?f=1&t=56313 |
Page 1 of 2 |
Author: | prcups [ Thu Jun 09, 2022 10:27 pm ] |
Post subject: | AHCI can't read and write blocks |
I try to use AHCI to visit my sata disk in my os. I can find port 0, rebase the hba memory correctly. I had set port 0's command issue to (1 << slot), waiting the device to respond but not. ci keeps 1, sig keeps 0x101, is and serr keep 0, sstr keeps 0x113 and tfd keeps 0x50. I am confused about it. My code: ahci.h: Code: #ifndef AHCI_H #define AHCI_H #include <bits/stdint-uintn.h> #include <stdbool.h> #define FIS_DEV_BITS uint16_t #define HBA_PxCMD_ST 0x0001 #define HBA_PxCMD_FRE 0x0010 #define HBA_PxCMD_FR 0x4000 #define HBA_PxCMD_CR 0x8000 #define HBA_PxIS_TFES (1 << 30) #define ATA_DEV_BUSY 0x80 #define ATA_DEV_DRQ 0x08 #define ATA_CMD_READ_DMA_EX 0x25 #define ATA_CMD_WRITE_DMA_EX 0x35 #define SATA_SIG_ATA 0x00000101 // SATA drive #define SATA_SIG_ATAPI 0xEB140101 // SATAPI drive #define SATA_SIG_SEMB 0xC33C0101 // Enclosure management bridge #define SATA_SIG_PM 0x96690101 // Port multiplier #define AHCI_DEV_NULL 0 #define AHCI_DEV_SATA 1 #define AHCI_DEV_SEMB 2 #define AHCI_DEV_PM 3 #define AHCI_DEV_SATAPI 4 #define HBA_PORT_IPM_ACTIVE 1 #define HBA_PORT_DET_PRESENT 3 typedef enum { FIS_TYPE_REG_H2D = 0x27, // Register FIS - host to device FIS_TYPE_REG_D2H = 0x34, // Register FIS - device to host FIS_TYPE_DMA_ACT = 0x39, // DMA activate FIS - device to host FIS_TYPE_DMA_SETUP = 0x41, // DMA setup FIS - bidirectional FIS_TYPE_DATA = 0x46, // Data FIS - bidirectional FIS_TYPE_BIST = 0x58, // BIST activate FIS - bidirectional FIS_TYPE_PIO_SETUP = 0x5F, // PIO setup FIS - device to host FIS_TYPE_DEV_BITS = 0xA1, // Set device bits FIS - device to host } FIS_TYPE; typedef struct { // DWORD 0 uint8_t fis_type; // FIS_TYPE_REG_H2D uint8_t pmport:4; // Port multiplier uint8_t rsv0:3; // Reserved uint8_t c:1; // 1: Command, 0: Control uint8_t command; // Command register uint8_t featurel; // Feature register, 7:0 // DWORD 1 uint8_t lba0; // LBA low register, 7:0 uint8_t lba1; // LBA mid register, 15:8 uint8_t lba2; // LBA high register, 23:16 uint8_t device; // Device register // DWORD 2 uint8_t lba3; // LBA register, 31:24 uint8_t lba4; // LBA register, 39:32 uint8_t lba5; // LBA register, 47:40 uint8_t featureh; // Feature register, 15:8 // DWORD 3 uint8_t countl; // Count register, 7:0 uint8_t counth; // Count register, 15:8 uint8_t icc; // Isochronous command completion uint8_t control; // Control register // DWORD 4 uint8_t rsv1[4]; // Reserved } FIS_REG_H2D; typedef struct { // DWORD 0 uint8_t fis_type; // FIS_TYPE_REG_D2H uint8_t pmport:4; // Port multiplier uint8_t rsv0:2; // Reserved uint8_t i:1; // Interrupt bit uint8_t rsv1:1; // Reserved uint8_t status; // Status register uint8_t error; // Error register // DWORD 1 uint8_t lba0; // LBA low register, 7:0 uint8_t lba1; // LBA mid register, 15:8 uint8_t lba2; // LBA high register, 23:16 uint8_t device; // Device register // DWORD 2 uint8_t lba3; // LBA register, 31:24 uint8_t lba4; // LBA register, 39:32 uint8_t lba5; // LBA register, 47:40 uint8_t rsv2; // Reserved // DWORD 3 uint8_t countl; // Count register, 7:0 uint8_t counth; // Count register, 15:8 uint8_t rsv3[2]; // Reserved // DWORD 4 uint8_t rsv4[4]; // Reserved } FIS_REG_D2H; typedef struct { // DWORD 0 uint8_t fis_type; // FIS_TYPE_DATA uint8_t pmport:4; // Port multiplier uint8_t rsv0:4; // Reserved uint8_t rsv1[2]; // Reserved // DWORD 1 ~ N uint32_t data[1]; // Payload } FIS_DATA; typedef struct { // DWORD 0 uint8_t fis_type; // FIS_TYPE_PIO_SETUP uint8_t pmport:4; // Port multiplier uint8_t rsv0:1; // Reserved uint8_t d:1; // Data transfer direction, 1 - device to host uint8_t i:1; // Interrupt bit uint8_t rsv1:1; uint8_t status; // Status register uint8_t error; // Error register // DWORD 1 uint8_t lba0; // LBA low register, 7:0 uint8_t lba1; // LBA mid register, 15:8 uint8_t lba2; // LBA high register, 23:16 uint8_t device; // Device register // DWORD 2 uint8_t lba3; // LBA register, 31:24 uint8_t lba4; // LBA register, 39:32 uint8_t lba5; // LBA register, 47:40 uint8_t rsv2; // Reserved // DWORD 3 uint8_t countl; // Count register, 7:0 uint8_t counth; // Count register, 15:8 uint8_t rsv3; // Reserved uint8_t e_status; // New value of status register // DWORD 4 uint16_t tc; // Transfer count uint8_t rsv4[2]; // Reserved } FIS_PIO_SETUP; typedef struct { // DWORD 0 uint8_t fis_type; // FIS_TYPE_DMA_SETUP uint8_t pmport:4; // Port multiplier uint8_t rsv0:1; // Reserved uint8_t d:1; // Data transfer direction, 1 - device to host uint8_t i:1; // Interrupt bit uint8_t a:1; // Auto-activate. Specifies if DMA Activate FIS is needed uint8_t rsved[2]; // Reserved //DWORD 1&2 uint64_t DMAbufferID; // DMA Buffer Identifier. Used to Identify DMA buffer in host memory. // SATA Spec says host specific and not in Spec. Trying AHCI spec might work. //DWORD 3 uint32_t rsvd; //More reserved //DWORD 4 uint32_t DMAbufOffset; //Byte offset into buffer. First 2 bits must be 0 //DWORD 5 uint32_t TransferCount; //Number of bytes to transfer. Bit 0 must be 0 //DWORD 6 uint32_t resvd; //Reserved } FIS_DMA_SETUP; typedef volatile struct { uint32_t clb; // 0x00, command list base address, 1K-byte aligned uint32_t clbu; // 0x04, command list base address upper 32 bits uint32_t fb; // 0x08, FIS base address, 256-byte aligned uint32_t fbu; // 0x0C, FIS base address upper 32 bits uint32_t is; // 0x10, interrupt status uint32_t ie; // 0x14, interrupt enable uint32_t cmd; // 0x18, command and status uint32_t rsv0; // 0x1C, Reserved uint32_t tfd; // 0x20, task file data uint32_t sig; // 0x24, signature uint32_t ssts; // 0x28, SATA status (SCR0:SStatus) uint32_t sctl; // 0x2C, SATA control (SCR2:SControl) uint32_t serr; // 0x30, SATA error (SCR1:SError) uint32_t sact; // 0x34, SATA active (SCR3:SActive) uint32_t ci; // 0x38, command issue uint32_t sntf; // 0x3C, SATA notification (SCR4:SNotification) uint32_t fbs; // 0x40, FIS-based switch control uint32_t rsv1[11]; // 0x44 ~ 0x6F, Reserved uint32_t vendor[4]; // 0x70 ~ 0x7F, vendor specific } HBA_PORT; typedef volatile struct { // 0x00 - 0x2B, Generic Host Control uint32_t cap; // 0x00, Host capability uint32_t ghc; // 0x04, Global host control uint32_t is; // 0x08, Interrupt status uint32_t pi; // 0x0C, Port implemented uint32_t vs; // 0x10, Version uint32_t ccc_ctl; // 0x14, Command completion coalescing control uint32_t ccc_pts; // 0x18, Command completion coalescing ports uint32_t em_loc; // 0x1C, Enclosure management location uint32_t em_ctl; // 0x20, Enclosure management control uint32_t cap2; // 0x24, Host capabilities extended uint32_t bohc; // 0x28, BIOS/OS handoff control and status // 0x2C - 0x9F, Reserved uint8_t rsv[0xA0-0x2C]; // 0xA0 - 0xFF, Vendor specific registers uint8_t vendor[0x100-0xA0]; // 0x100 - 0x10FF, Port control registers HBA_PORT ports[1]; // 1 ~ 32 } HBA_MEM; // typedef volatile struct // { // // 0x00 // FIS_DMA_SETUP dsfis; // DMA Setup FIS // uint8_t pad0[4]; // // // 0x20 // FIS_PIO_SETUP psfis; // PIO Setup FIS // uint8_t pad1[12]; // // // 0x40 // FIS_REG_D2H rfis; // Register – Device to Host FIS // uint8_t pad2[4]; // // // 0x58 // FIS_DEV_BITS sdbfis; // Set Device Bit FIS // // // 0x60 // uint8_t ufis[64]; // // // 0xA0 // uint8_t rsv[0x100-0xA0]; // } HBA_FIS; typedef struct { // DW0 uint8_t cfl:5; // Command FIS length in DWORDS, 2 ~ 16 uint8_t a:1; // ATAPI uint8_t w:1; // Write, 1: H2D, 0: D2H uint8_t p:1; // Prefetchable uint8_t r:1; // Reset uint8_t b:1; // BIST uint8_t c:1; // Clear busy upon R_OK uint8_t rsv0:1; // Reserved uint8_t pmp:4; // Port multiplier port uint16_t prdtl; // Physical region descriptor table length in entries // DW1 volatile uint32_t prdbc; // Physical region descriptor byte count transferred // DW2, 3 uint32_t ctba; // Command table descriptor base address uint32_t ctbau; // Command table descriptor base address upper 32 bits // DW4 - 7 uint32_t rsv1[4]; // Reserved } HBA_CMD_HEADER; typedef struct { uint32_t dba; // Data base address uint32_t dbau; // Data base address upper 32 bits uint32_t rsv0; // Reserved // DW3 uint32_t dbc:22; // Byte count, 4M max uint32_t rsv1:9; // Reserved uint32_t i:1; // Interrupt on completion } HBA_PRDT_ENTRY; typedef struct tagHBA_CMD_TBL { // 0x00 uint8_t cfis[64]; // Command FIS // 0x40 uint8_t acmd[16]; // ATAPI command, 12 or 16 bytes // 0x50 uint8_t rsv[48]; // Reserved // 0x80 HBA_PRDT_ENTRY prdt_entry[1]; // Physical region descriptor table entries, 0 ~ 65535 } HBA_CMD_TBL; void start_cmd(); void stop_cmd(); void ahci_init(uint64 base); int read_port(uint32 startl, uint32 starth, uint32 count, uint64 buf); int write_port(uint32 startl, uint32 starth, uint32 count, uint64 buf); int find_cmdslot(); void rebase_port(); void start_cmd(); void stop_cmd(); void probe_port(HBA_MEM *abar_temp); #endif ahci.c Code: #include "kernel/include/xtos.h"
#include "kernel/include/ahci.h" static HBA_MEM *abar; static int portno = -1; #define PORT (abar -> ports + portno) #define AHCI_BASE (uint64) abar void ahci_init(uint64 ahci_base) { probe_port((HBA_MEM *) ahci_base); } // /* // Code Reference : OSDEV // */ // void handler_ahci_routine() // { // printf("AHCI INTERRUPT HANDLER\n"); // if (abar->ports[0].is & HBA_PxIS_TFES) // printf("Read disk error\n"); // printf("\n TFD=[%d]", ((HBA_PORT *) &abar->ports[0])->tfd); // printf("\nSSTS =[%d]", ((HBA_PORT *) &abar->ports[0])->ssts); // printf("\nIE=[%d]", ((HBA_PORT *) &abar->ports[0])->ie); // printf("\nSERR%d", ((HBA_PORT *) &abar->ports[0])->serr); // printf("\nIS%d", ((HBA_PORT *) &abar->ports[0])->is); // abar->ports[0].is = 0xffff; // while (1) // ; // } /* Code Reference : OSDEV */ int read_port(uint32 startl, uint32 starth, uint32 count, uint64 buf) { PORT->is = 0xffff; // Clear pending interrupt bits int slot = find_cmdslot(PORT); if (slot == -1) return -1; HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER*)(PORT->clb | DMWIN_MASK); cmdheader += slot; cmdheader->cfl = sizeof(FIS_REG_H2D) / sizeof(uint32); // Command FIS size cmdheader->w = 0; // Read from device cmdheader->c = 1; // Read from device cmdheader->p = 1; // Read from device cmdheader->prdtl = (uint16) ((count - 1) >> 4) + 1; // PRDT entries count HBA_CMD_TBL *cmdtbl = (HBA_CMD_TBL*)(cmdheader->ctba | DMWIN_MASK); int i = 0; for (i = 0; i < cmdheader->prdtl - 1; i++) { cmdtbl->prdt_entry[i].dba = (uint32) (buf & 0xFFFFFFFF); cmdtbl->prdt_entry[i].dbau = (uint32) ((buf >> 32) & 0xFFFFFFFF); cmdtbl->prdt_entry[i].dbc = 8 * 1024 - 1; // 8K bytes cmdtbl->prdt_entry[i].i = 0; buf += 4 * 1024; // 4K words count -= 16; // 16 sectors } cmdtbl->prdt_entry[i].dba = (uint32) (buf & 0xFFFFFFFF); cmdtbl->prdt_entry[i].dbau = (uint32) ((buf >> 32) & 0xFFFFFFFF); cmdtbl->prdt_entry[i].dbc = count << 9; // 512 bytes per sector cmdtbl->prdt_entry[i].i = 0; FIS_REG_H2D *cmdfis = (FIS_REG_H2D*) (&cmdtbl->cfis); cmdfis->fis_type = FIS_TYPE_REG_H2D; cmdfis->c = 1; // Command cmdfis->command = ATA_CMD_READ_DMA_EX; cmdfis->lba0 = (uint8) startl; cmdfis->lba1 = (uint8) (startl >> 8); cmdfis->lba2 = (uint8) (startl >> 16); cmdfis->device = 1 << 6; // LBA mode cmdfis->lba3 = (uint8) (startl >> 24); cmdfis->lba4 = (uint8) starth; cmdfis->lba5 = (uint8) (starth >> 8); cmdfis->countl = count & 0xff; cmdfis->counth = count >> 8; int spin = 0; while ((PORT->tfd & (ATA_DEV_BUSY | ATA_DEV_DRQ)) && spin < 1000000) { spin++; } if (spin == 1000000) { printf("Port is hung\n"); return -1; } PORT->ci = (1 << slot); printf("0x%x 0x%x\n", PORT->ci, PORT->is); while (1) { if ((PORT->ci & (1 << slot)) == 0) break; if (PORT->is & HBA_PxIS_TFES) { // Task file error printf("Read disk error\n"); return -1; } } if (PORT->is & HBA_PxIS_TFES) { printf("Read disk error\n"); return -1; } while (PORT->ci != 0) { printf("Read disk error\n"); } return 0; } /* Code Reference : OSDEV */ int write_port(uint32 startl, uint32 starth, uint32 count, uint64 buf) { PORT->is = 0xffff; // Clear pending interrupt bits int slot = find_cmdslot(PORT); if (slot == -1) return -1; HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER*)(PORT->clb | DMWIN_MASK); cmdheader += slot; cmdheader->cfl = sizeof(FIS_REG_H2D) / sizeof(uint32); // Command FIS size cmdheader->w = 1; // Read from device cmdheader->c = 1; // Read from device cmdheader->p = 1; // Read from device cmdheader->prdtl = (uint16) ((count - 1) >> 4) + 1; // PRDT entries count HBA_CMD_TBL *cmdtbl = (HBA_CMD_TBL*)(cmdheader->ctba | DMWIN_MASK); int i = 0; for (i = 0; i < cmdheader->prdtl - 1; i++) { cmdtbl->prdt_entry[i].dba = (uint32) (buf & 0xFFFFFFFF); cmdtbl->prdt_entry[i].dbau = (uint32) ((buf >> 32) & 0xFFFFFFFF); cmdtbl->prdt_entry[i].dbc = 8 * 1024 - 1; // 8K bytes cmdtbl->prdt_entry[i].i = 0; buf += 4 * 1024; // 4K words count -= 16; // 16 sectors } cmdtbl->prdt_entry[i].dba = (uint32) (buf & 0xFFFFFFFF); cmdtbl->prdt_entry[i].dbau = (uint32) ((buf >> 32) & 0xFFFFFFFF); cmdtbl->prdt_entry[i].dbc = count << 9; // 512 bytes per sector cmdtbl->prdt_entry[i].i = 0; FIS_REG_H2D *cmdfis = (FIS_REG_H2D*) (&cmdtbl->cfis); cmdfis->fis_type = FIS_TYPE_REG_H2D; cmdfis->c = 1; // Command cmdfis->command = ATA_CMD_WRITE_DMA_EX; cmdfis->lba0 = (uint8) startl; cmdfis->lba1 = (uint8) (startl >> 8); cmdfis->lba2 = (uint8) (startl >> 16); cmdfis->device = 1 << 6; // LBA mode cmdfis->lba3 = (uint8) (startl >> 24); cmdfis->lba4 = (uint8) starth; cmdfis->lba5 = (uint8) (starth >> 8); cmdfis->countl = count & 0xff; cmdfis->counth = count >> 8; int spin = 0; while ((PORT->tfd & (ATA_DEV_BUSY | ATA_DEV_DRQ)) && spin < 1000000) { spin++; } if (spin == 1000000) { printf("Port is hung\n"); return -1; } PORT->ci = (1 << slot); while (1) { // In some longer duration reads, it may be helpful to spin on the DPS bit // in the PxIS port field as well (1 << 5) if ((PORT->ci & (1 << slot)) == 0) break; if (PORT->is & HBA_PxIS_TFES) { // Task file error printf("Read disk error\n"); return -1; } } if (PORT->is & HBA_PxIS_TFES) { printf("Read disk error\n"); return -1; } while (PORT->ci != 0) { printf("Read disk error\n"); } return 0; } // To setup command fing a free command list slot int find_cmdslot() { uint32 slots = (PORT->sact | PORT->ci); int num_of_slots = (abar->cap & 0x0f00) >> 8; // Bit 8-12 int i; for (i = 0; i < num_of_slots; i++) { if ((slots & 1) == 0) { // printf("[slot=%d]", i); // if(i==0) return i; // break; } slots >>= 1; } printf("Cannot find free command list entry\n"); return -1; } // Check device type static int check_type(HBA_PORT * port) { uint32 ssts = port->ssts; uint8 ipm = (ssts >> 8) & 0x0F; uint8 det = ssts & 0x0F; //printf ("\n ipm %d det %d sig %d", ipm, det, PORT->sig); if (det != HBA_PORT_DET_PRESENT) // Check drive status return AHCI_DEV_NULL; if (ipm != HBA_PORT_IPM_ACTIVE) return AHCI_DEV_NULL; switch (port->sig) { case SATA_SIG_ATAPI: return AHCI_DEV_SATAPI; case SATA_SIG_SEMB: return AHCI_DEV_SEMB; case SATA_SIG_PM: return AHCI_DEV_PM; default: return AHCI_DEV_SATA; } return 0; } /* Code Reference : OSDEV */ void rebase_port() { stop_cmd(PORT); // Stop command engine // Command list offset: 1K*portno // Command list entry size = 32 // Command list entry maxim count = 32 // Command list maxim size = 32*32 = 1K per port PORT->clb = AHCI_BASE + (portno<<10); PORT->clbu = 0; memset((void*)((PORT->clb) | DMWIN_MASK) , 0, 1024); // FIS offset: 32K+256*portno // FIS entry size = 256 bytes per port PORT->fb = AHCI_BASE + (32<<10) + (portno<<8); PORT->fbu = 0; memset((void*)((PORT->fb) | DMWIN_MASK), 0, 256); // Command table offset: 40K + 8K*portno // Command table size = 256*32 = 8K per port HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER*)((PORT->clb) | DMWIN_MASK); for (int i=0; i<32; i++) { cmdheader[i].prdtl = 8; // 8 prdt entries per command table // 256 bytes per command table, 64+16+48+16*8 // Command table offset: 40K + 8K*portno + cmdheader_index*256 cmdheader[i].ctba = AHCI_BASE + (40<<10) + (portno<<13) + (i<<8); cmdheader[i].ctbau = 0; memset((void*)(cmdheader[i].ctba | DMWIN_MASK) , 0, 256); } start_cmd(PORT); // Start command engine } // Start command engine void start_cmd() { // Wait until CR (bit15) is cleared while (PORT->cmd & HBA_PxCMD_CR) ; // Set FRE (bit4) and ST (bit0) PORT->cmd |= HBA_PxCMD_FRE; PORT->cmd |= HBA_PxCMD_ST; } // Stop command engine void stop_cmd() { // Clear ST (bit0) PORT->cmd &= ~HBA_PxCMD_ST; // Clear FRE (bit4) PORT->cmd &= ~HBA_PxCMD_FRE; // Wait until FR (bit14), CR (bit15) are cleared while(1) { if (PORT->cmd & HBA_PxCMD_FR) continue; if (PORT->cmd & HBA_PxCMD_CR) continue; break; } } /* Code Reference : OSDEV */ void probe_port(HBA_MEM *abar_temp) { printf("Inside probe_port\n"); // Search disk in impelemented ports uint32 pi = abar_temp->pi; int i = 0; while (i < 32) { if (pi & 1) { int dt = check_type((HBA_PORT *) &abar_temp->ports[i]); if (dt == AHCI_DEV_SATA) { printf("\nSATA drive found at port %d\n", i); abar = abar_temp; portno = i; rebase_port(); printf("DONE AHCI INITIALISATION :: PORT REBASE\n"); return; } else if (dt == AHCI_DEV_SATAPI) { printf("\nSATAPI drive found at port %d\n", i); } else if (dt == AHCI_DEV_SEMB) { printf("\nSEMB drive found at port %d\n", i); } else if (dt == AHCI_DEV_PM) { printf("\nPM drive found at port %d\n", i); } else { printf("\nNo drive found at port %d\n", i); } } pi >>= 1; i++; } printf("probe_port complete\n"); } |
Author: | Octocontrabass [ Tue Jun 14, 2022 10:32 am ] |
Post subject: | Re: AHCI can't read and write blocks |
Does your OS use paging? The example code on the wiki makes no distinction between physical and virtual address, and the AHCI HBA can only access physical addresses. |
Author: | prcups [ Wed Jun 22, 2022 7:15 pm ] |
Post subject: | Re: AHCI can't read and write blocks |
Octocontrabass wrote: Does your OS use paging? The example code on the wiki makes no distinction between physical and virtual address, and the AHCI HBA can only access physical addresses. I use efi application to start and didn't write any code about paging. |
Author: | iansjack [ Thu Jun 23, 2022 5:39 am ] |
Post subject: | Re: AHCI can't read and write blocks |
Is your code 32-bit or 64-bit? |
Author: | prcups [ Thu Jun 23, 2022 6:58 am ] |
Post subject: | Re: AHCI can't read and write blocks |
iansjack wrote: Is your code 32-bit or 64-bit? 64 bit |
Author: | iansjack [ Thu Jun 23, 2022 7:27 am ] |
Post subject: | Re: AHCI can't read and write blocks |
Then you are using paging. UEFI will have set up a simple page table for you. |
Author: | prcups [ Thu Jun 23, 2022 10:39 am ] |
Post subject: | Re: AHCI can't read and write blocks |
iansjack wrote: Then you are using paging. UEFI will have set up a simple page table for you. Does the default paging affect ahci's work?I think that the virtual address is equal to the real address, so the ahci controller will visit proper registers. |
Author: | iansjack [ Thu Jun 23, 2022 2:59 pm ] |
Post subject: | Re: AHCI can't read and write blocks |
I’m not sure of the answer to that (although I’m sure someone will provide it), but I would expect UEFI to only map those pages it uses. So I would not expect it to map the ahci controller address space. |
Author: | Octocontrabass [ Thu Jun 23, 2022 6:52 pm ] |
Post subject: | Re: AHCI can't read and write blocks |
UEFI page tables are only guaranteed to identity map addresses listed in the UEFI memory map. Did you call ExitBootServices()? You need to do that before accessing the AHCI controller. Is GHC.AE (bit 31) set to 1? The controller won't work correctly if GHC.AE is 0. In stop_cmd(), you are not waiting for PxCMD.CR to clear before you clear PxCMD.FRE. You must wait for PxCMD.CR to be 0 before you can set PxCMD.FRE to 0. What is DMWIN_MASK? |
Author: | prcups [ Thu Jun 23, 2022 9:06 pm ] |
Post subject: | Re: AHCI can't read and write blocks |
Octocontrabass wrote: UEFI page tables are only guaranteed to identity map addresses listed in the UEFI memory map. Did you call ExitBootServices()? You need to do that before accessing the AHCI controller. Is GHC.AE (bit 31) set to 1? The controller won't work correctly if GHC.AE is 0. In stop_cmd(), you are not waiting for PxCMD.CR to clear before you clear PxCMD.FRE. You must wait for PxCMD.CR to be 0 before you can set PxCMD.FRE to 0. What is DMWIN_MASK? I called ExitBootServices. GHC.AE is set to 1. I added while (PORT->cmd & HBA_PxCMD_CR); just now but not make sense. DMWIN_MASK is set to 0 now because I don't need it any more. I have put my code on github: https://github.com/prcups/xtos-x86-clone.git |
Author: | Octocontrabass [ Fri Jun 24, 2022 8:38 pm ] |
Post subject: | Re: AHCI can't read and write blocks |
You should detect the AHCI controller instead of hardcoding its address. In the example code on the wiki, AHCI_BASE refers to a chunk of free memory used by the AHCI driver. It is not ABAR. In a real driver, you should assign memory dynamically instead of using a fixed address. |
Author: | prcups [ Sat Jun 25, 2022 6:39 am ] |
Post subject: | Re: AHCI can't read and write blocks |
Octocontrabass wrote: You should detect the AHCI controller instead of hardcoding its address. In the example code on the wiki, AHCI_BASE refers to a chunk of free memory used by the AHCI driver. It is not ABAR. In a real driver, you should assign memory dynamically instead of using a fixed address. I know in the end I have to enumerate pci devices to find the correct sata controller. Now I just use pci base address from ACPI and bus/device/function id found at qemu and uefi for test. The address of abar is sata controller's pci base address offset 9 (bar 5). |
Author: | Octocontrabass [ Sat Jun 25, 2022 3:28 pm ] |
Post subject: | Re: AHCI can't read and write blocks |
Does it work when AHCI_BASE points to RAM instead of ABAR? |
Author: | prcups [ Sun Jun 26, 2022 7:00 am ] |
Post subject: | Re: AHCI can't read and write blocks |
Octocontrabass wrote: Does it work when AHCI_BASE points to RAM instead of ABAR? Same as before. I create a memory area and transfer its address to AHCI_BASE. Nothing changed. |
Author: | Octocontrabass [ Sun Jun 26, 2022 4:22 pm ] |
Post subject: | Re: AHCI can't read and write blocks |
Really? It successfully reads the disk when I do that. Where are you allocating this memory area? Have you tried using debug tracing? For example, try adding "-d trace:handle_cmd_*" to your QEMU command line. There's a list of available trace events here. |
Page 1 of 2 | All times are UTC - 6 hours |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |