Page 1 of 3

Cannot read blocks using AHCI

Posted: Sun Jan 21, 2024 2:48 pm
by WinExperements
Hi! So i managed to write the AHCI driver, and now when my driver trying to read the first sector of disk the ci is keeps set to 1. I tested to run this driver on real hardware since i know that it doesn't corrupt anything, and i noticed that the hard drive activity LED is starts active when the driver trying to read the sector and never go off. I think that i miss something or misunderstud about something in AHCI, i tried to debug it by myself, but no results, still the same. Here is my code:

Code: Select all

#include <output.h>
#include <debug.h>
#include <pci/driver.h> // PCI
#include <pci/registry.h>
#include <mm/alloc.h>
#include <arch/mmu.h>
#include <arch.h>

#define HBA_PxIS_TFES   (1 << 30)
#define ATA_CMD_READ_DMA_EX 0x25
#define ATA_CMD_WRITE_DMA_EX    0x35
#define HBA_PxCMD_CR    (1 << 15)
#define HBA_PxCMD_FR    (1 << 14)
#define HBA_PxCMD_FRE   (1 << 4)
#define HBA_PxCMD_SUD   (1 << 1)
#define HBA_PxCMD_ST    (1 << 0)
#define ATA_DEV_BUSY 0x80
#define ATA_DEV_DRQ 0x08

__attribute__((section(".modname"))) char *name = "ahci";

static int ctrl_id = 0;

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 tagFIS_REG_H2D
{
    // int32_t 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
 
    // int32_t 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
 
    // int32_t 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
 
    // int32_t 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
 
    // int32_t 4
    uint8_t    rsv1[4];    // Reserved
} FIS_REG_H2D;

typedef struct tagFIS_REG_D2H
{
    // int32_t 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

    // int32_t 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

    // int32_t 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

    // int32_t 3
    uint8_t    countl;      // Count register, 7:0
    uint8_t    counth;      // Count register, 15:8
    uint8_t    rsv3[2];     // Reserved

    // int32_t 4
    uint8_t    rsv4[4];     // Reserved
} FIS_REG_D2H;

typedef struct tagFIS_DATA
{
    // int32_t 0
    uint8_t    fis_type;   // FIS_TYPE_DATA
 
    uint8_t    pmport:4;   // Port multiplier
    uint8_t    rsv0:4;     // Reserved
 
    uint8_t    rsv1[2];    // Reserved
 
    // int32_t 1 ~ N
    uint32_t   data[1];    // Payload
} FIS_DATA;

typedef volatile struct tagHBA_PORT
{
    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 tagHBA_MEM
{
    // 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 struct tagHBA_PRDT_ENTRY
{
    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;

typedef struct tagHBA_CMD_HEADER
{
    // 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
} __attribute__((packed)) HBA_CMD_HEADER;

struct sata_info {
	void *clb;
	void *fb;
	void *ctba[32];
	HBA_PORT *port;
	HBA_MEM *abar;
};

#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_SATAPI 4
#define AHCI_DEV_SEMB 2
#define AHCI_DEV_PM 3
#define HBA_PORT_DET_PRESENT 3
#define HBA_PORT_IPM_ACTIVE 1

static HBA_MEM *ctrl_data;
static PciBar *bar;

static int find_cmdslot(HBA_PORT *port,HBA_MEM *abar);
static uint8_t read_sata(struct sata_info *pdata, uint32_t startl, uint32_t starth, uint32_t count,char *buf);

static void PciVisit(unsigned int bus, unsigned int dev, unsigned int func)
{
    unsigned int id = PCI_MAKE_ID(bus, dev, func);

    PciDeviceInfo info;
    info.vendorId = PciRead16(id, PCI_CONFIG_VENDOR_ID);
    if (info.vendorId == 0xffff)
    {
        return;
    }

    info.deviceId = PciRead16(id, PCI_CONFIG_DEVICE_ID);
    info.progIntf = PciRead8(id, PCI_CONFIG_PROG_INTF);
    info.subclass = PciRead8(id, PCI_CONFIG_SUBCLASS);
    info.classCode = PciRead8(id, PCI_CONFIG_CLASS_CODE);
    if (((info.classCode << 8) | info.subclass) == PCI_STORAGE_SATA) {
            kprintf("found\r\n");
        int addr = PciRead32(id,PCI_CONFIG_BAR5);
	    PciWrite16(id,PCI_CONFIG_COMMAND,PciRead16(id,PCI_CONFIG_COMMAND) | 0x0002 | 0x0004);
	    ctrl_data = (HBA_MEM *)(addr & ~0xf);
        // Map the space
        int pages = (sizeof(HBA_MEM))+1;
        for (int page = 0; page < pages; page++) {
            int align = page*4096;
            arch_mmu_mapPage(NULL,addr+align,addr+align,7);
        }
        ctrl_id = id;
	kprintf("AHCI controller PCI dump: \n");
	PciBar *ba = kmalloc(sizeof(PciBar));
	memset(ba,0,sizeof(PciBar));
	for (int i = 0; i < 5; i++) {
		PciGetBar(ba,id,i);
		kprintf("BAR%d dump: \n",i);
		kprintf("Address 0x%x\n",ba->u.address);
		kprintf("Size: 0x%x\n",ba->size);
		kprintf("Flags: 0x%x\n",ba->flags);
	}
    }
}

static int check_type(HBA_PORT *port) {
	uint16_t ssts = port->ssts;
	uint8_t ipm = (ssts >> 8) & 0x0F;
	uint8_t det = ssts & 0x0F;
	if (det != HBA_PORT_DET_PRESENT) {
		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;
}

void start_cmd(HBA_PORT *port)
{
    // Set FRE (bit4) and ST (bit0)
    // Wait until CR (bit15) is cleared
    while (port->cmd & HBA_PxCMD_CR)
        ;
    port->cmd |= HBA_PxCMD_FRE;
    port->cmd |= HBA_PxCMD_ST;
}

// Stop command engine
void stop_cmd(HBA_PORT *port)
{
    // Clear ST (bit0)
    port->cmd &= ~HBA_PxCMD_ST;
    port->cmd &= ~HBA_PxCMD_FRE;
    // Wait until FR (bit14), CR (bit15) are cleared
    while(1)
    {
        //printk("cmd: %d\n", port->cmd);
        if (port->cmd & HBA_PxCMD_FR)
            continue;
        if (port->cmd & HBA_PxCMD_CR)
            continue;
        break;
    }
}


// Our hell begins here
static void rebase_port(HBA_PORT *port, int portno,struct sata_info *info) {
	kprintf("ahci: %s: entered\n",__func__);
	info->abar->ghc = (uint32_t ) (1 << 31);
	info->abar->ghc = (uint32_t ) (1 << 0);
	info->abar->ghc = (uint32_t) (1 << 31);
	info->abar->ghc = (uint32_t) (1 << 1);
	stop_cmd(port);
	port->cmd = port->cmd & 0xffff7fff; //Bit 15
    	port->cmd = port->cmd & 0xffffbfff; //Bit 14
    	port->cmd = port->cmd & 0xfffffffe; //Bit 0
    	port->cmd = port->cmd & 0xfffffff7; //Bit 4
	void *mapped_clb = kmalloc(4096);
	memset(mapped_clb,0,4096);
	port->clb = arch_mmu_getPhysical(mapped_clb);
	port->clbu = 0;
	info->clb = mapped_clb;
	void *mapped_fb = kmalloc(4096);
	memset(mapped_fb,0,4096);
	port->fb = arch_mmu_getPhysical(mapped_fb);
	port->fbu = 0;
	info->fb = mapped_fb;
	port->serr = 1; //For each implemented port, clear the PxSERR register, by writing 1 to each implemented location
    	port->is = 0; //
    	port->ie = 1;
	kprintf("ahci: %s: writing something to cmdheader\n",__func__);
	HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER*)(mapped_clb);
	for (int i = 0; i < 32; i++) {
		 cmdheader[i].prdtl = 8;
		 void *ctba_buf = kmalloc(4096);
		 memset(ctba_buf,0,4096);
		 info->ctba[i] = ctba_buf;
		 cmdheader[i].ctba = arch_mmu_getPhysical(ctba_buf);
		 cmdheader[i].ctbau = 0;
	}
	info->port = port;
	while(port->cmd & HBA_PxCMD_CR);
	start_cmd(port);
	port->is = 0;
    	port->ie = 0xffffffff;
	kprintf("Port %d rebase done\n",portno);
}

static void module_main() {
    kprintf("Finding AHCI controller in PCI base...");
    void *a = arch_mmu_getAspace();
    arch_mmu_switch(arch_mmu_getKernelSpace());
    // Scan each BUS to find the SATA controller
    for (unsigned int bus = 0; bus < 256; ++bus)
    {
        for (unsigned int dev = 0; dev < 32; ++dev)
        {
            unsigned int baseId = PCI_MAKE_ID(bus, dev, 0);
            uint8_t headerType = PciRead8(baseId, PCI_CONFIG_HEADER_TYPE);
            unsigned int funcCount = headerType & PCI_TYPE_MULTIFUNC ? 8 : 1;

            for (unsigned int func = 0; func < funcCount; ++func)
            {
                PciVisit(bus, dev, func);
            }
        }
    }
    if (ctrl_id == 0) {
        kprintf("not found\r\n");
        return;
    }
    int pi = ctrl_data->pi;
    int i =0;
    struct sata_info *sata = NULL;
    if (!(ctrl_data->bohc & 2)) {
            //kprintf("Requesting ownership for port %d\r\n",i);
            ctrl_data->bohc = (ctrl_data->bohc &~8) | 2;
            int endtime = clock_getUptimeMsec()+100;
            while((ctrl_data->bohc & 1) && clock_getUptimeMsec() < endtime);
            if ((ctrl_data->bohc & 1)) {
                //kprintf("BIOS! It's MY drive, i'll get it force!\r\n");
                ctrl_data->bohc = 2;
                ctrl_data->bohc |= 8;
            } else {
                //kprintf("Thank you, BIOS for the permission!\r\n");
            }
        } else {
            kprintf("Oh! The firmware is automatically switch the drive into OS mode, i like this!\r\n");
        }
        if (!(ctrl_data->ghc & 0x80000000)) {
            kprintf("Switching AHCI to AHCI mode\n");
        }
        arch_sti();
    while(i < 32) {
	if (pi & 1) {
        HBA_PORT* port = (HBA_PORT*)&ctrl_data->ports[i];
		int type = check_type(port);
		if (type == AHCI_DEV_SATA) {
			kprintf("Found hard drive on port %d\r\n",i);
			kprintf("Port CLB: 0x%x, CLBU: 0x%x\r\n",port->clb,port->clbu);
			sata = kmalloc(sizeof(struct sata_info *));
			memset(sata,0,sizeof(struct sata_info *));
			kprintf("Rebasing port\n");
			sata->abar = ctrl_data;
			rebase_port(port,i,sata);
		} else if (type == AHCI_DEV_SATAPI) {
           		 kprintf("Found CDROM drive on port %d\r\n",i);
        	} else {
            		pi >>= 1;
			i++;
			continue;
        	}
	if (type == AHCI_DEV_SATA) {
        	kprintf("Reading first sector\n");
        	char *sector = kmalloc(512);
        	int ret = read_sata(sata,0,0,1,sector);
        	kprintf("Readed, return of read_sata: %d\n",ret);
        	kfree(sector);
	}
	}
	pi >>= 1;
	i++;
    }
   arch_mmu_switch(a);
    kprintf("AHCI driver done\n");
}
static int find_cmdslot(HBA_PORT *port,HBA_MEM *abar) {
    uint32_t slots = (port->sact | port->ci);
    int cmdslots = (abar -> cap & 0x0f00) >> 8;
    for (int i=0; i<cmdslots; i++)
    {
        if ((slots&1) == 0)
            return i;
        slots >>= 1;
    }
    return -1;
}
static uint8_t read_sata(struct sata_info *pdata, uint32_t startl, uint32_t starth, uint32_t count,char *buf) {
	pdata->port->is = (uint32_t) -1;
     int spin = 0; // Spin lock timeout counter
    int slot = find_cmdslot(pdata->port,pdata->abar);
    //uint64_t buf_phys = (uint64_t)buf - KERN_VMBASE;
    uint64_t buf_phys = arch_mmu_getPhysical(buf);
    //printf("%x\n", buf_phys);
    if (slot == -1)
        return 0;

    //HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER*) (KERN_VMBASE + port->clb);
    HBA_CMD_HEADER* cmdheader = (HBA_CMD_HEADER*) pdata->clb;
    cmdheader += slot;
    cmdheader->cfl = sizeof(FIS_REG_H2D)/sizeof(uint32_t); // Command FIS size
    cmdheader->w = 0;       // Read device
    cmdheader->prdtl = (uint16_t)((count-1)>>4) + 1;    // PRDT entries count

    HBA_CMD_TBL *cmdtbl = (HBA_CMD_TBL*) pdata->ctba[slot];
    //HBA_CMD_TBL *cmdtbl = (HBA_CMD_TBL*)(KERN_VMBASE + cmdheader->ctba);
    //memset(cmdtbl, 0, sizeof(HBA_CMD_TBL) +
    //    (cmdheader->prdtl-1)*sizeof(HBA_PRDT_ENTRY));

    int i;
    // 8K bytes (16 sectors) per PRDT
    for (i=0; i<cmdheader->prdtl-1; i++)
    {
        cmdtbl->prdt_entry[i].dba = (uint32_t)buf_phys;
        //cmdtbl->prdt_entry[i].dbau = (uint32_t) ( ( (buf_phys) >> 32) & 0xffffffff);
        cmdtbl->prdt_entry[i].dbc = 8*1024; // 8K bytes
        cmdtbl->prdt_entry[i].i = 1;
        buf += 4*1024;  // 4K words
        count -= 16;    // 16 sectors
    }
    // Last entry
    cmdtbl->prdt_entry[i].dba = (uint32_t) (buf_phys & 0xffffffff);
    //cmdtbl->prdt_entry[i].dbau = (uint32_t) ( (buf_phys >> 32) & 0xffffffff);
    kprintf("dba & dbau: 0x%x 0x%x\n", cmdtbl ->prdt_entry[i].dba, cmdtbl -> prdt_entry[i].dbau);
    cmdtbl->prdt_entry[i].dbc = count<<9;   // 512 bytes per sector
    cmdtbl->prdt_entry[i].i = 1;

    // Setup command
    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_t)startl;
    cmdfis->lba1 = (uint8_t)(startl>>8);
    cmdfis->lba2 = (uint8_t)(startl>>16);
    cmdfis->device = 1<<6;  // LBA mode

    cmdfis->lba3 = (uint8_t)(startl>>24);
    cmdfis->lba4 = (uint8_t)starth;
    cmdfis->lba5 = (uint8_t)(starth>>8);

    cmdfis->countl = (count & 0xff);
    cmdfis->counth = (count >> 8);

    // The below loop waits until the port is no longer busy before issuing a new command
    kprintf("Waiting for port is not longer be a busy");
    while ((pdata->port->tfd & (ATA_DEV_BUSY | ATA_DEV_DRQ)) && spin < 1000000)
    {
        spin++;
    }
    if (spin == 1000000)
    {
        //printk("Port is hung\n");
        return 0;
    }
    kprintf("ok. Issue command...");

    pdata->port->ci = 1; // Issue command
    kprintf("ok\n");
    kprintf("PORT INFO: %x %d %d\n", pdata->port, pdata->port->ci, pdata->port->tfd);
    kprintf("Slot: %d, ci: %d, mask: %d\n",slot,pdata->port->ci,1<<slot);

    // Wait for completion
    while (1)
    {
        //kprintf("Reading disk...\n");
        // In some longer duration reads, it may be helpful to spin on the DPS bit
        // in the PxIS port field as well (1 << 5)
        //kprintf("value: %d\n", (pdata->port -> ci & (1<<slot) )  );
        if ((pdata->port->ci & (1<<slot)) == 0)
            break;
        if (pdata->port->is & HBA_PxIS_TFES)   // Task file error
        {
            //printk("Read disk error\n");
            return 0;
        }
        //kprintf("IS: %d\n",pdata->port->is);
    }

    // Check again
    if (pdata->port->is & HBA_PxIS_TFES)
    {
        //printk("Read disk error\n");
        return 0;
    }

    return 1;
}

Re: Cannot read blocks using AHCI

Posted: Sun Jan 21, 2024 3:37 pm
by Octocontrabass
WinExperements wrote:I tested to run this driver on real hardware
Did you test it in a virtual machine?
WinExperements wrote:

Code: Select all

    // 8K bytes (16 sectors) per PRDT
Why 8kiB? The maximum is 4MiB.

Re: Cannot read blocks using AHCI

Posted: Sun Jan 21, 2024 3:45 pm
by WinExperements
Octocontrabass wrote: Did you test it in a virtual machine?
Yes i do, and still the same, the ci never cleans
Octocontrabass wrote: Why 8kiB? The maximum is 4MiB.
I seen this size in many other realization, yes maybe this is wrong, so i need to increase it up to 4MB?

Re: Cannot read blocks using AHCI

Posted: Sun Jan 21, 2024 3:58 pm
by Octocontrabass
WinExperements wrote:Yes i do, and still the same, the ci never cleans
You can use QEMU's trace log to debug it. Try "-trace enable=ahci_*" or something along those lines.
WinExperements wrote:I seen this size in many other realization, yes maybe this is wrong, so i need to increase it up to 4MB?
The maximum is 4MiB, but the size you can use depends on physical memory fragmentation.

Re: Cannot read blocks using AHCI

Posted: Sun Jan 21, 2024 4:25 pm
by WinExperements
So i runned the qemu with trice command, and when the read begins it's stops at

Code: Select all

ahci_port_read ahci(0x559e9712e3b0)[0]: port read [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_read_32 ahci(0x559e9712e3b0): mem read @ 0x118: 0x00000006
ahci_mem_read ahci(0x559e9712e3b0): read4 @ 0x118: 0x0000000000000006
ahci_mem_write ahci(0x559e9712e3b0): write4 @ 0x118: 0x0000000000000016
ahci_port_write ahci(0x559e9712e3b0)[0]: port write [reg:PxCMD] @ 0x18: 0x00000016
ahci_trigger_irq ahci(0x559e9712e3b0)[0]: trigger irq +DHRS (0x00000001); irqstat: 0x00000000 --> 0x00000001; effective: 0x00000001
ahci_check_irq ahci(0x559e9712e3b0): check irq 0x00000000 --> 0x00000001
ahci_irq_raise ahci(0x559e9712e3b0): raise irq
And after that i get continuesly interrupts with number 0x2b, what i should do with this IRQ?

EDIT: I see about IRQ in wiki, so i will try to do what saying in the wiki

Re: Cannot read blocks using AHCI

Posted: Mon Jan 22, 2024 5:26 am
by WinExperements
Hello again! So i fixed the issue, the problem is in the struct sata_info allocation.

So i have new question: what i am doing wrong in the AHCI port rebase code? I ask this because i got this messages in QEMU when trying to read the first sector:

Code: Select all

ahci_port_write ahci(0x55e524dd3eb0)[0]: port write [reg:PxCI] @ 0x38: 0x00000001
ahci_start_dma ahci(0x55e524dd3eb0)[0]: start dma
ahci_populate_sglist ahci(0x55e524dd3eb0)[0]
ahci_populate_sglist_no_prdtl ahci(0x55e524dd3eb0)[0]: no sg list given by guest: 0x0005
ahci_dma_prepare_buf_fail ahci(0x55e524dd3eb0)[0]: sglist population failed

And i think that i doesn't allocate something for the list or something else

Re: Cannot read blocks using AHCI

Posted: Mon Jan 22, 2024 11:06 am
by Octocontrabass
QEMU logs that error when PRDTL is zero.

It looks like PRDTL is set correctly in the code you've posted, but you've made changes since that post, so maybe one of those changes broke something.

Re: Cannot read blocks using AHCI

Posted: Mon Jan 22, 2024 11:58 am
by WinExperements
Octocontrabass wrote:but you've made changes since that post, so maybe one of those changes broke something.
I added some functions to register the devices in devfs:

Code: Select all

void blockNoToLBA(uint32_t blockNo, uint32_t blockSize, uint32_t* startl, uint32_t* starth) {
    // Calculate the LBA (Logical Block Address) based on block number and block size
    uint32_t lba = blockNo * (blockSize / 512);

    // Break down LBA into startl and starth
    *startl = lba & 0xFFFFFFFF;
    *starth = (lba >> 32) & 0xFFFFFFFF;
}

static void ahci_vdev_readBlock(vfs_node_t *node,int blockNo,int how, void *buf) {
    // Convert blockNo to the startl and starth
    int blocks = how / 512;
    if (blocks == 0) {
        blocks = 1;
    }
    uint32_t startl,starth;
    blockNoToLBA(blockNo,512,&startl,&starth);
    read_sata((struct sata_info *)node->device,startl,starth,blocks,buf);
}

void registerDev(struct sata_info *inf) {
    dev_t *dev = kmalloc(sizeof(dev_t));
    memset(dev,0,sizeof(dev));
    dev->name = strdup("sat0");
    dev->readBlock = ahci_vdev_readBlock;
    dev->buffer_sizeMax = 512;
    dev->device = inf;
    dev->type = DEVFS_TYPE_BLOCK;
    dev_add(dev);
}
Also removed the * in kmalloc and memset parameters for struct sata_info inside the module_main
The dev_add will trigger to read the MBR partiton sheme from drive, but the problems begins when the driver reads first sector inside the module_main

EDIT: Works in QEMU, but the byte order isn't correct, also the driver hungs when tryed to read fisrt sector in VirtualBox and on real hardware the read returns with port hung error

Re: Cannot read blocks using AHCI

Posted: Mon Jan 22, 2024 2:52 pm
by Octocontrabass
WinExperements wrote:EDIT: Works in QEMU, but the byte order isn't correct,
Check your buffer alignment. AHCI requires at least 2-byte alignment. Also, what does QEMU's trace log say?

Re: Cannot read blocks using AHCI

Posted: Tue Jan 23, 2024 9:41 am
by WinExperements
Octocontrabass wrote: Check your buffer alignment. AHCI requires at least 2-byte alignment
what buffer? Data buffer?
Octocontrabass wrote: Also, what does QEMU's trace log say?
Here is full log from AHCI when driver boots:

Code: Select all

ahci_reset ahci(0x55f3905f0080): HBA reset
ahci_reset_port ahci(0x55f3905f0080)[0]: reset port
ahci_set_signature ahci(0x55f3905f0080)[0]: set signature sector:0x01 nsector:0x01 lcyl:0x00 hcyl:0x00 (cumulatively: 0x00000101)
ahci_reset_port ahci(0x55f3905f0080)[1]: reset port
ahci_reset_port ahci(0x55f3905f0080)[2]: reset port
ahci_reset_port ahci(0x55f3905f0080)[3]: reset port
ahci_reset_port ahci(0x55f3905f0080)[4]: reset port
ahci_reset_port ahci(0x55f3905f0080)[5]: reset port
ahci_mem_write_host ahci(0x55f3905f0080) write4 [reg:GHC] @ 0x4: 0x0000000000000001
ahci_mem_write ahci(0x55f3905f0080): write4 @ 0x4: 0x0000000080000000
ahci_check_irq ahci(0x55f3905f0080): check irq 0x00000000 --> 0x00000000
ahci_irq_lower ahci(0x55f3905f0080): lower irq
ahci_mem_write_host ahci(0x55f3905f0080) write4 [reg:GHC] @ 0x4: 0x0000000080000000
ahci_mem_write ahci(0x55f3905f0080): write4 @ 0x4: 0x0000000000000002
ahci_check_irq ahci(0x55f3905f0080): check irq 0x00000000 --> 0x00000000
ahci_irq_lower ahci(0x55f3905f0080): lower irq
ahci_mem_write_host ahci(0x55f3905f0080) write4 [reg:GHC] @ 0x4: 0x0000000000000002
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x118: 0x00000006
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x118: 0x0000000000000006
ahci_mem_write ahci(0x55f3905f0080): write4 @ 0x118: 0x0000000000000006
ahci_port_write ahci(0x55f3905f0080)[0]: port write [reg:PxCMD] @ 0x18: 0x00000006
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x118: 0x00000006
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x118: 0x0000000000000006
ahci_mem_write ahci(0x55f3905f0080): write4 @ 0x118: 0x0000000000000006
ahci_port_write ahci(0x55f3905f0080)[0]: port write [reg:PxCMD] @ 0x18: 0x00000006
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x118: 0x00000006
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x118: 0x0000000000000006
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x118: 0x00000006
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x118: 0x0000000000000006
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x118: 0x00000006
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x118: 0x0000000000000006
ahci_mem_write ahci(0x55f3905f0080): write4 @ 0x118: 0x0000000000000006
ahci_port_write ahci(0x55f3905f0080)[0]: port write [reg:PxCMD] @ 0x18: 0x00000006
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x118: 0x00000006
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x118: 0x0000000000000006
ahci_mem_write ahci(0x55f3905f0080): write4 @ 0x118: 0x0000000000000006
ahci_port_write ahci(0x55f3905f0080)[0]: port write [reg:PxCMD] @ 0x18: 0x00000006
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x118: 0x00000006
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x118: 0x0000000000000006
ahci_mem_write ahci(0x55f3905f0080): write4 @ 0x118: 0x0000000000000006
ahci_port_write ahci(0x55f3905f0080)[0]: port write [reg:PxCMD] @ 0x18: 0x00000006
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x118: 0x00000006
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x118: 0x0000000000000006
ahci_mem_write ahci(0x55f3905f0080): write4 @ 0x118: 0x0000000000000006
ahci_port_write ahci(0x55f3905f0080)[0]: port write [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_write ahci(0x55f3905f0080): write4 @ 0x100: 0x0000000001505004
ahci_port_write ahci(0x55f3905f0080)[0]: port write [reg:PxCLB] @ 0x0: 0x01505004
ahci_mem_write ahci(0x55f3905f0080): write4 @ 0x104: 0x0000000000000000
ahci_port_write ahci(0x55f3905f0080)[0]: port write [reg:PxCLBU] @ 0x4: 0x00000000
ahci_mem_write ahci(0x55f3905f0080): write4 @ 0x108: 0x0000000001507004
ahci_port_write ahci(0x55f3905f0080)[0]: port write [reg:PxFB] @ 0x8: 0x01507004
ahci_mem_write ahci(0x55f3905f0080): write4 @ 0x10c: 0x0000000000000000
ahci_port_write ahci(0x55f3905f0080)[0]: port write [reg:PxFBU] @ 0xc: 0x00000000
ahci_mem_write ahci(0x55f3905f0080): write4 @ 0x130: 0x0000000000000001
ahci_port_write ahci(0x55f3905f0080)[0]: port write [reg:PxSERR] @ 0x30: 0x00000001
ahci_mem_write ahci(0x55f3905f0080): write4 @ 0x110: 0x0000000000000000
ahci_port_write ahci(0x55f3905f0080)[0]: port write [reg:PxIS] @ 0x10: 0x00000000
ahci_check_irq ahci(0x55f3905f0080): check irq 0x00000000 --> 0x00000000
ahci_irq_lower ahci(0x55f3905f0080): lower irq
ahci_mem_write ahci(0x55f3905f0080): write4 @ 0x114: 0x0000000000000001
ahci_port_write ahci(0x55f3905f0080)[0]: port write [reg:PXIE] @ 0x14: 0x00000001
ahci_check_irq ahci(0x55f3905f0080): check irq 0x00000000 --> 0x00000000
ahci_irq_lower ahci(0x55f3905f0080): lower irq
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x118: 0x00000006
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x118: 0x0000000000000006
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x118: 0x00000006
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x118: 0x0000000000000006
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x118: 0x00000006
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x118: 0x0000000000000006
ahci_mem_write ahci(0x55f3905f0080): write4 @ 0x118: 0x0000000000000016
ahci_port_write ahci(0x55f3905f0080)[0]: port write [reg:PxCMD] @ 0x18: 0x00000016
ahci_trigger_irq ahci(0x55f3905f0080)[0]: trigger irq +DHRS (0x00000001); irqstat: 0x00000000 --> 0x00000001; effective: 0x00000001
ahci_check_irq ahci(0x55f3905f0080): check irq 0x00000000 --> 0x00000001
ahci_irq_raise ahci(0x55f3905f0080): raise irq
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxCMD] @ 0x18: 0x00004016
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x118: 0x00004016
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x118: 0x0000000000004016
ahci_mem_write ahci(0x55f3905f0080): write4 @ 0x118: 0x0000000000004017
ahci_port_write ahci(0x55f3905f0080)[0]: port write [reg:PxCMD] @ 0x18: 0x00004017
ahci_mem_write ahci(0x55f3905f0080): write4 @ 0x110: 0x0000000000000000
ahci_port_write ahci(0x55f3905f0080)[0]: port write [reg:PxIS] @ 0x10: 0x00000000
ahci_check_irq ahci(0x55f3905f0080): check irq 0x00000001 --> 0x00000001
ahci_irq_raise ahci(0x55f3905f0080): raise irq
ahci_mem_write ahci(0x55f3905f0080): write4 @ 0x114: 0x00000000ffffffff
ahci_port_write ahci(0x55f3905f0080)[0]: port write [reg:PXIE] @ 0x14: 0xffffffff
ahci_check_irq ahci(0x55f3905f0080): check irq 0x00000001 --> 0x00000001
ahci_irq_raise ahci(0x55f3905f0080): raise irq
ahci_mem_write ahci(0x55f3905f0080): write4 @ 0x110: 0x00000000ffffffff
ahci_port_write ahci(0x55f3905f0080)[0]: port write [reg:PxIS] @ 0x10: 0xffffffff
ahci_check_irq ahci(0x55f3905f0080): check irq 0x00000001 --> 0x00000000
ahci_irq_lower ahci(0x55f3905f0080): lower irq
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxSACT] @ 0x34: 0x00000000
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x134: 0x00000000
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x134: 0x0000000000000000
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxCI] @ 0x38: 0x00000000
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x138: 0x00000000
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x138: 0x0000000000000000
ahci_mem_read_32_host ahci(0x55f3905f0080): mem read [reg:CAP] @ 0x0: 0xc0141f05
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x0: 0xc0141f05
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x0: 0x00000000c0141f05
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxTFD] @ 0x20: 0x00000130
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x120: 0x00000130
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x120: 0x0000000000000130
ahci_mem_write ahci(0x55f3905f0080): write4 @ 0x138: 0x0000000000000001
ahci_port_write ahci(0x55f3905f0080)[0]: port write [reg:PxCI] @ 0x38: 0x00000001
ahci_start_dma ahci(0x55f3905f0080)[0]: start dma
ahci_populate_sglist ahci(0x55f3905f0080)[0]
ahci_dma_prepare_buf ahci(0x55f3905f0080)[0]: prepare buf limit=512 prepared=512
ahci_cmd_done ahci(0x55f3905f0080)[0]: cmd done
ahci_trigger_irq ahci(0x55f3905f0080)[0]: trigger irq +DHRS (0x00000001); irqstat: 0x00000000 --> 0x00000001; effective: 0x00000001
ahci_check_irq ahci(0x55f3905f0080): check irq 0x00000000 --> 0x00000001
ahci_irq_raise ahci(0x55f3905f0080): raise irq
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxTFD] @ 0x20: 0x00000050
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x120: 0x00000050
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x120: 0x0000000000000050
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxCI] @ 0x38: 0x00000000
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x138: 0x00000000
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x138: 0x0000000000000000
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxCI] @ 0x38: 0x00000000
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x138: 0x00000000
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x138: 0x0000000000000000
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxCI] @ 0x38: 0x00000000
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x138: 0x00000000
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x138: 0x0000000000000000
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxIS] @ 0x10: 0x00000001
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x110: 0x00000001
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x110: 0x0000000000000001
ahci_mem_write ahci(0x55f3905f0080): write4 @ 0x110: 0x00000000ffffffff
ahci_port_write ahci(0x55f3905f0080)[0]: port write [reg:PxIS] @ 0x10: 0xffffffff
ahci_check_irq ahci(0x55f3905f0080): check irq 0x00000001 --> 0x00000000
ahci_irq_lower ahci(0x55f3905f0080): lower irq
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxSACT] @ 0x34: 0x00000000
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x134: 0x00000000
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x134: 0x0000000000000000
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxCI] @ 0x38: 0x00000000
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x138: 0x00000000
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x138: 0x0000000000000000
ahci_mem_read_32_host ahci(0x55f3905f0080): mem read [reg:CAP] @ 0x0: 0xc0141f05
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x0: 0xc0141f05
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x0: 0x00000000c0141f05
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxTFD] @ 0x20: 0x00000050
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x120: 0x00000050
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x120: 0x0000000000000050
ahci_mem_write ahci(0x55f3905f0080): write4 @ 0x138: 0x0000000000000001
ahci_port_write ahci(0x55f3905f0080)[0]: port write [reg:PxCI] @ 0x38: 0x00000001
ahci_start_dma ahci(0x55f3905f0080)[0]: start dma
ahci_populate_sglist ahci(0x55f3905f0080)[0]
ahci_dma_prepare_buf ahci(0x55f3905f0080)[0]: prepare buf limit=512 prepared=512
ahci_cmd_done ahci(0x55f3905f0080)[0]: cmd done
ahci_trigger_irq ahci(0x55f3905f0080)[0]: trigger irq +DHRS (0x00000001); irqstat: 0x00000000 --> 0x00000001; effective: 0x00000001
ahci_check_irq ahci(0x55f3905f0080): check irq 0x00000000 --> 0x00000001
ahci_irq_raise ahci(0x55f3905f0080): raise irq
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxTFD] @ 0x20: 0x00000050
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x120: 0x00000050
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x120: 0x0000000000000050
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxCI] @ 0x38: 0x00000000
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x138: 0x00000000
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x138: 0x0000000000000000
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxCI] @ 0x38: 0x00000000
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x138: 0x00000000
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x138: 0x0000000000000000
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxCI] @ 0x38: 0x00000000
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x138: 0x00000000
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x138: 0x0000000000000000
ahci_port_read ahci(0x55f3905f0080)[0]: port read [reg:PxIS] @ 0x10: 0x00000001
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x110: 0x00000001
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x110: 0x0000000000000001
ahci_port_read ahci(0x55f3905f0080)[1]: port read [reg:PxSSTS] @ 0x28: 0x00000000
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x1a8: 0x00000000
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x1a8: 0x0000000000000000
ahci_port_read ahci(0x55f3905f0080)[2]: port read [reg:PxSSTS] @ 0x28: 0x00000000
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x228: 0x00000000
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x228: 0x0000000000000000
ahci_port_read ahci(0x55f3905f0080)[3]: port read [reg:PxSSTS] @ 0x28: 0x00000000
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x2a8: 0x00000000
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x2a8: 0x0000000000000000
ahci_port_read ahci(0x55f3905f0080)[4]: port read [reg:PxSSTS] @ 0x28: 0x00000000
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x328: 0x00000000
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x328: 0x0000000000000000
ahci_port_read ahci(0x55f3905f0080)[5]: port read [reg:PxSSTS] @ 0x28: 0x00000000
ahci_mem_read_32 ahci(0x55f3905f0080): mem read @ 0x3a8: 0x00000000
ahci_mem_read ahci(0x55f3905f0080): read4 @ 0x3a8: 0x0000000000000000


Re: Cannot read blocks using AHCI

Posted: Tue Jan 23, 2024 1:36 pm
by Octocontrabass
WinExperements wrote:what buffer? Data buffer?
The data buffer referenced by the PRDT.
WinExperements wrote:

Code: Select all

ahci_port_write ahci(0x55f3905f0080)[0]: port write [reg:PxCLB] @ 0x0: 0x01505004
PxCLB requires a 1kiB-aligned address. The address you're using is not correctly aligned.

Re: Cannot read blocks using AHCI

Posted: Tue Jan 23, 2024 3:49 pm
by WinExperements
So yeah i read the wiki again and aligned the addresses to 1KiB and to 256 bytes, but new issue showed, the CI is never cleared from port. Here is my changes in code:

Code: Select all

void* align_addr(void* address,int al) {
    uintptr_t addr = (uintptr_t)address;
    uintptr_t aligned_addr = (addr + al - 1) & ~al - 1;
    return (void*)aligned_addr;
}

In read_sata:
buf_phys = (uint64_t)align_addr(buf_phys,1024);

in rebase_port:
void *mapped_clb = kmalloc(4096);
memset(mapped_clb,0,4096);
port->clb = align_addr(arch_mmu_getPhysical(mapped_clb),1024);
port->clbu = 0;
void *mapped_fb = kmalloc(4096);
	memset(mapped_fb,0,4096);
	port->fb = align_addr(arch_mmu_getPhysical(mapped_fb),256);
	port->fbu = 0;
	info->fb = mapped_fb;
HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER*)(mapped_clb);
	for (int i = 0; i < 32; i++) {
		 cmdheader[i].prdtl = 8;
		 void *ctba_buf = kmalloc(4096);
		 memset(ctba_buf,0,4096);
		 info->ctba[i] = ctba_buf;
         void *phys = arch_mmu_getPhysical(ctba_buf);
		 cmdheader[i].ctba = align_addr(phys,1024); // OSDEV wiki says that the address must 128 byte aligned.
		 cmdheader[i].ctbau = 0;
	}
QEMU trace:

Code: Select all

ahci_reset ahci(0x5654c171d650): HBA reset
ahci_reset_port ahci(0x5654c171d650)[0]: reset port
ahci_set_signature ahci(0x5654c171d650)[0]: set signature sector:0x01 nsector:0x01 lcyl:0x00 hcyl:0x00 (cumulatively: 0x00000101)
ahci_reset_port ahci(0x5654c171d650)[1]: reset port
ahci_reset_port ahci(0x5654c171d650)[2]: reset port
ahci_reset_port ahci(0x5654c171d650)[3]: reset port
ahci_reset_port ahci(0x5654c171d650)[4]: reset port
ahci_reset_port ahci(0x5654c171d650)[5]: reset port
ahci_mem_write_host ahci(0x5654c171d650) write4 [reg:GHC] @ 0x4: 0x0000000000000001
ahci_mem_write ahci(0x5654c171d650): write4 @ 0x4: 0x0000000080000000
ahci_check_irq ahci(0x5654c171d650): check irq 0x00000000 --> 0x00000000
ahci_irq_lower ahci(0x5654c171d650): lower irq
ahci_mem_write_host ahci(0x5654c171d650) write4 [reg:GHC] @ 0x4: 0x0000000080000000
ahci_mem_write ahci(0x5654c171d650): write4 @ 0x4: 0x0000000000000002
ahci_check_irq ahci(0x5654c171d650): check irq 0x00000000 --> 0x00000000
ahci_irq_lower ahci(0x5654c171d650): lower irq
ahci_mem_write_host ahci(0x5654c171d650) write4 [reg:GHC] @ 0x4: 0x0000000000000002
ahci_port_read ahci(0x5654c171d650)[0]: port read [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x118: 0x00000006
ahci_mem_read ahci(0x5654c171d650): read4 @ 0x118: 0x0000000000000006
ahci_mem_write ahci(0x5654c171d650): write4 @ 0x118: 0x0000000000000006
ahci_port_write ahci(0x5654c171d650)[0]: port write [reg:PxCMD] @ 0x18: 0x00000006
ahci_port_read ahci(0x5654c171d650)[0]: port read [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x118: 0x00000006
ahci_mem_read ahci(0x5654c171d650): read4 @ 0x118: 0x0000000000000006
ahci_mem_write ahci(0x5654c171d650): write4 @ 0x118: 0x0000000000000006
ahci_port_write ahci(0x5654c171d650)[0]: port write [reg:PxCMD] @ 0x18: 0x00000006
ahci_port_read ahci(0x5654c171d650)[0]: port read [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x118: 0x00000006
ahci_mem_read ahci(0x5654c171d650): read4 @ 0x118: 0x0000000000000006
ahci_port_read ahci(0x5654c171d650)[0]: port read [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x118: 0x00000006
ahci_mem_read ahci(0x5654c171d650): read4 @ 0x118: 0x0000000000000006
ahci_port_read ahci(0x5654c171d650)[0]: port read [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x118: 0x00000006
ahci_mem_read ahci(0x5654c171d650): read4 @ 0x118: 0x0000000000000006
ahci_mem_write ahci(0x5654c171d650): write4 @ 0x118: 0x0000000000000006
ahci_port_write ahci(0x5654c171d650)[0]: port write [reg:PxCMD] @ 0x18: 0x00000006
ahci_port_read ahci(0x5654c171d650)[0]: port read [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x118: 0x00000006
ahci_mem_read ahci(0x5654c171d650): read4 @ 0x118: 0x0000000000000006
ahci_mem_write ahci(0x5654c171d650): write4 @ 0x118: 0x0000000000000006
ahci_port_write ahci(0x5654c171d650)[0]: port write [reg:PxCMD] @ 0x18: 0x00000006
ahci_port_read ahci(0x5654c171d650)[0]: port read [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x118: 0x00000006
ahci_mem_read ahci(0x5654c171d650): read4 @ 0x118: 0x0000000000000006
ahci_mem_write ahci(0x5654c171d650): write4 @ 0x118: 0x0000000000000006
ahci_port_write ahci(0x5654c171d650)[0]: port write [reg:PxCMD] @ 0x18: 0x00000006
ahci_port_read ahci(0x5654c171d650)[0]: port read [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x118: 0x00000006
ahci_mem_read ahci(0x5654c171d650): read4 @ 0x118: 0x0000000000000006
ahci_mem_write ahci(0x5654c171d650): write4 @ 0x118: 0x0000000000000006
ahci_port_write ahci(0x5654c171d650)[0]: port write [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_write ahci(0x5654c171d650): write4 @ 0x100: 0x0000000001035002
ahci_port_write ahci(0x5654c171d650)[0]: port write [reg:PxCLB] @ 0x0: 0x01035002
ahci_mem_write ahci(0x5654c171d650): write4 @ 0x104: 0x0000000000000000
ahci_port_write ahci(0x5654c171d650)[0]: port write [reg:PxCLBU] @ 0x4: 0x00000000
ahci_mem_write ahci(0x5654c171d650): write4 @ 0x108: 0x0000000001037002
ahci_port_write ahci(0x5654c171d650)[0]: port write [reg:PxFB] @ 0x8: 0x01037002
ahci_mem_write ahci(0x5654c171d650): write4 @ 0x10c: 0x0000000000000000
ahci_port_write ahci(0x5654c171d650)[0]: port write [reg:PxFBU] @ 0xc: 0x00000000
ahci_mem_write ahci(0x5654c171d650): write4 @ 0x130: 0x0000000000000001
ahci_port_write ahci(0x5654c171d650)[0]: port write [reg:PxSERR] @ 0x30: 0x00000001
ahci_mem_write ahci(0x5654c171d650): write4 @ 0x110: 0x0000000000000000
ahci_port_write ahci(0x5654c171d650)[0]: port write [reg:PxIS] @ 0x10: 0x00000000
ahci_check_irq ahci(0x5654c171d650): check irq 0x00000000 --> 0x00000000
ahci_irq_lower ahci(0x5654c171d650): lower irq
ahci_mem_write ahci(0x5654c171d650): write4 @ 0x114: 0x0000000000000001
ahci_port_write ahci(0x5654c171d650)[0]: port write [reg:PXIE] @ 0x14: 0x00000001
ahci_check_irq ahci(0x5654c171d650): check irq 0x00000000 --> 0x00000000
ahci_irq_lower ahci(0x5654c171d650): lower irq
ahci_port_read ahci(0x5654c171d650)[0]: port read [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x118: 0x00000006
ahci_mem_read ahci(0x5654c171d650): read4 @ 0x118: 0x0000000000000006
ahci_port_read ahci(0x5654c171d650)[0]: port read [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x118: 0x00000006
ahci_mem_read ahci(0x5654c171d650): read4 @ 0x118: 0x0000000000000006
ahci_port_read ahci(0x5654c171d650)[0]: port read [reg:PxCMD] @ 0x18: 0x00000006
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x118: 0x00000006
ahci_mem_read ahci(0x5654c171d650): read4 @ 0x118: 0x0000000000000006
ahci_mem_write ahci(0x5654c171d650): write4 @ 0x118: 0x0000000000000016
ahci_port_write ahci(0x5654c171d650)[0]: port write [reg:PxCMD] @ 0x18: 0x00000016
ahci_trigger_irq ahci(0x5654c171d650)[0]: trigger irq +DHRS (0x00000001); irqstat: 0x00000000 --> 0x00000001; effective: 0x00000001
ahci_check_irq ahci(0x5654c171d650): check irq 0x00000000 --> 0x00000001
ahci_irq_raise ahci(0x5654c171d650): raise irq
ahci_port_read ahci(0x5654c171d650)[0]: port read [reg:PxCMD] @ 0x18: 0x00004016
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x118: 0x00004016
ahci_mem_read ahci(0x5654c171d650): read4 @ 0x118: 0x0000000000004016
ahci_mem_write ahci(0x5654c171d650): write4 @ 0x118: 0x0000000000004017
ahci_port_write ahci(0x5654c171d650)[0]: port write [reg:PxCMD] @ 0x18: 0x00004017
ahci_mem_write ahci(0x5654c171d650): write4 @ 0x110: 0x0000000000000000
ahci_port_write ahci(0x5654c171d650)[0]: port write [reg:PxIS] @ 0x10: 0x00000000
ahci_check_irq ahci(0x5654c171d650): check irq 0x00000001 --> 0x00000001
ahci_irq_raise ahci(0x5654c171d650): raise irq
ahci_mem_write ahci(0x5654c171d650): write4 @ 0x114: 0x00000000ffffffff
ahci_port_write ahci(0x5654c171d650)[0]: port write [reg:PXIE] @ 0x14: 0xffffffff
ahci_check_irq ahci(0x5654c171d650): check irq 0x00000001 --> 0x00000001
ahci_irq_raise ahci(0x5654c171d650): raise irq
ahci_mem_write ahci(0x5654c171d650): write4 @ 0x110: 0x00000000ffffffff
ahci_port_write ahci(0x5654c171d650)[0]: port write [reg:PxIS] @ 0x10: 0xffffffff
ahci_check_irq ahci(0x5654c171d650): check irq 0x00000001 --> 0x00000000
ahci_irq_lower ahci(0x5654c171d650): lower irq
ahci_port_read ahci(0x5654c171d650)[0]: port read [reg:PxSACT] @ 0x34: 0x00000000
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x134: 0x00000000
ahci_mem_read ahci(0x5654c171d650): read4 @ 0x134: 0x0000000000000000
ahci_port_read ahci(0x5654c171d650)[0]: port read [reg:PxCI] @ 0x38: 0x00000000
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x138: 0x00000000
ahci_mem_read ahci(0x5654c171d650): read4 @ 0x138: 0x0000000000000000
ahci_mem_read_32_host ahci(0x5654c171d650): mem read [reg:CAP] @ 0x0: 0xc0141f05
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x0: 0xc0141f05
ahci_mem_read ahci(0x5654c171d650): read4 @ 0x0: 0x00000000c0141f05
ahci_port_read ahci(0x5654c171d650)[0]: port read [reg:PxTFD] @ 0x20: 0x00000130
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x120: 0x00000130
ahci_mem_read ahci(0x5654c171d650): read4 @ 0x120: 0x0000000000000130
ahci_mem_write ahci(0x5654c171d650): write4 @ 0x138: 0x0000000000000001
ahci_port_write ahci(0x5654c171d650)[0]: port write [reg:PxCI] @ 0x38: 0x00000001
ahci_port_read ahci(0x5654c171d650)[0]: port read [reg:PxTFD] @ 0x20: 0x00000130
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x120: 0x00000130
ahci_mem_read ahci(0x5654c171d650): read4 @ 0x120: 0x0000000000000130
ahci_port_read ahci(0x5654c171d650)[0]: port read [reg:PxCI] @ 0x38: 0x00000001
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x138: 0x00000001
ahci_mem_read ahci(0x5654c171d650): read4 @ 0x138: 0x0000000000000001
ahci_port_read ahci(0x5654c171d650)[0]: port read [reg:PxCI] @ 0x38: 0x00000001
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x138: 0x00000001
ahci_mem_read ahci(0x5654c171d650): read4 @ 0x138: 0x0000000000000001
ahci_port_read ahci(0x5654c171d650)[0]: port read [reg:PxCI] @ 0x38: 0x00000001
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x138: 0x00000001
ahci_mem_read ahci(0x5654c171d650): read4 @ 0x138: 0x0000000000000001
ahci_port_read ahci(0x5654c171d650)[0]: port read [reg:PxIS] @ 0x10: 0x00000000
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x110: 0x00000000
ahci_mem_read ahci(0x5654c171d650): read4 @ 0x110: 0x0000000000000000
ahci_port_read ahci(0x5654c171d650)[0]: port read [reg:PxCI] @ 0x38: 0x00000001
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x138: 0x00000001
ahci_mem_read ahci(0x5654c171d650): read4 @ 0x138: 0x0000000000000001
ahci_port_read ahci(0x5654c171d650)[0]: port read [reg:PxIS] @ 0x10: 0x00000000
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x110: 0x00000000
ahci_mem_read ahci(0x5654c171d650): read4 @ 0x110: 0x0000000000000000
ahci_port_read ahci(0x5654c171d650)[0]: port read [reg:PxCI] @ 0x38: 0x00000001
ahci_mem_read_32 ahci(0x5654c171d650): mem read @ 0x138: 0x00000001
*repeats forever*
Did i miss something again?

Re: Cannot read blocks using AHCI

Posted: Tue Jan 23, 2024 4:34 pm
by Octocontrabass
WinExperements wrote:

Code: Select all

ahci_port_write ahci(0x5654c171d650)[0]: port write [reg:PxCLB] @ 0x0: 0x01035002
That's still not aligned correctly.

Re: Cannot read blocks using AHCI

Posted: Wed Jan 24, 2024 7:02 am
by WinExperements
i am fixed the align function, now address to CLB is 0x1035400 and for FB is 0x01037100, but still the same issue. The CI never cleans, the trace log isn't changed except the addresses loaded into PxCLB and PxFB. What i do wrong again? The interrupt handlers currently not registred for the interrupt line. on real hardware the port always reports busy state, after writing the command into the header and before the driver issue the command

Re: Cannot read blocks using AHCI

Posted: Wed Jan 24, 2024 9:10 pm
by Octocontrabass
Are the virtual addresses aligned too?