Hi guys,
I tried to stay out of this thread, but curiosity kept getting the best of me.
natiiix, might I suggest a few things to do to improve your situation?
First, biting the hand that feeds you usually leaves you really hungry. Therefore, please be a little more respectful and you will find that we, the members of this forum, are eager to help.
So, let's start with a few things to see what it wrong with your code.
natiiix wrote:There is nothing being written to the buf buffer.
How do you know? If you zero the buffer, then call your code, what does the buffer still look like? zero's? Try filling it with 0xAA 0x55 or some other random value to be sure the code isn't just clearing out the buffer.
natiiix wrote:I use the port index from probe_port() as HBA_MEM*->ports[index], is that the correct way to do it?
Who knows? What does
probe_port() do?
natiiix wrote:note:
phystovirt() converts physical memory address to a virtual one and
virttophys() does the exact opposite, the rest of the functions used are from
Wiki.
May I suggest that you remove any code that uses virtual addressing, for two reasons. First, if you use all physical addressing, you will eliminate your paging/virtual memory manager as a culprit. Second, if this code is in your kernel space, you should not be using virtual addressing anyway. If the address to your buffer will be passed as a virtual address, you can change that to physical at the top of the code and then use all physical addressing from there on(, at least for a beginner working on his/her OS).
Code: Select all
BOOL read(HBA_PORT *port, DWORD startl, DWORD starth, DWORD count, WORD *buf)
{
port->is = (DWORD)-1; // Clear pending interrupt bits
First, print (writeline()) the value of
port and see what it is. Better yet, let us know what it is. If the bottom four bits are not zero, there is a problem. In fact, if the bottom 8 to 12 bits are not zero, there most likely is a problem. Second, is your
HBA_PORT structure (class) byte padded or machine word padded? i.e. if the compiler pads each member, this will drastically change the hardware access you think you are reading from/writing to.
Also, if your paging manager isn't allowing a memory access to 0xF0404000 for example, your code could be generating a page fault and you don't even know about it, unless your paging manager handles page faults. Does the current paging mechanism, for this code, allow access to addresses in the 0xF0404000 range?
Code: Select all
int spin = 0; // Spin lock timeout counter
int slot = find_cmdslot(port);
term::writeline((size_t)slot, 16);
if (slot == -1)
{
For debugging purposes, print something here. Maybe your code isn't finding a slot and you don't know about it because all you do is return FALSE.
Code: Select all
return FALSE;
}
HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER*)phystovirt(port->clb);
What does port->clb contain? Have you initialized it to have a value yet?
Second, why get the virtual address?
I think this is your problem. You get the virtual address from (of?) port->clb and expect cmdheader to be the virtual address. Then every time you read or write using the cmdheader pointer, you expect it to use virtual addressing. However, when you use the port pointer, you expect it to use physical addressing. Does this code use virtual addressing or physical addressing, and if so, how does it know where
port is as a virtual address or where
cmdheader is as a physical address?
Code: Select all
term::writeline((size_t)cmdheader, 16);
What does this print? Is cmdheader paragraph aligned? Byte aligned?
Be careful here with pointer addition. This may or may not be what you think it is.
Code: Select all
cmdheader->cfl = sizeof(FIS_REG_H2D)/sizeof(DWORD); // Command FIS size
cmdheader->w = 0; // Read from device
cmdheader->prdtl = (WORD)((count-1)>>4) + 1; // PRDT entries count
Without going and looking myself, does
cmdheader use bitfields? If it does, does your compiler handle bitfields as expected by this code? Bitfields are specific to the compiler being used and are not standard.
Code: Select all
HBA_CMD_TBL *cmdtbl = (HBA_CMD_TBL*)phystovirt(cmdheader->ctba);
memset(cmdtbl, 0, sizeof(HBA_CMD_TBL) + (cmdheader->prdtl-1)*sizeof(HBA_PRDT_ENTRY));
Again, you get the virtual address to (of?) cmdheader->ctba and pass this to your memset() function? Does memset() use virtual or physical addressing?
Code: Select all
// 8K bytes (16 sectors) per PRDT
for (int i = 0; i < cmdheader->prdtl-1; i++)
(snip remaining code)
Check for those things I mention, giving us details of the results. We need something to go on to help you find the problem. Just giving us code, especially code that you have copied from somewhere else, does not help us at all, which helps you even less.
Print the value of
port and let us know what you get. Eliminate the virtual addressing. For now, if you must use virtual addressing, set up a physical temporary buffer, using physical addressing to get your code to work. Then modify it to use virtual addressing later.
I hope this helps, rather than feeding the fire that is burning in this thread.
Ben
P.S. Since you obviously don't think you need to go and read the specifications, how about a book that describes this in more detail? In Part 4 of my book, Chapters 12 through 14 explain in detail how to detect, initialize, and use the AHCI.
http://www.fysnet.net/media_storage_devices.htm