-
Not sure what your background is, but if you have never written a device driver before I can tell you from first hand experience that you definitely could. Have you ever written drivers or kernels before? Anyway, thanks a lot for helping me out here. I feel a lot less confused now, so I will go ahead and try this out and post back if I hit a snag. Much appreciated.
-
At any rate, I am still having issues, perhaps I am still doing it wrong:
Code:
#define secPerTrk 0x3F //= 63
#define maxHeadNm 0xFE //= 254
#define intATACmd 0x91 //= initialize ata command
unsigned long val;
unsigned long res;
// read, then write
pci_read_config_dword(&pci,BAR5+0x90,&i);
val=(i&0xFF00FFFF) + (secPerTrk<<16);
pci_write_config_dword(&pci, BAR5+0x90, val);
res=(i>>16) & 0xff;
//print
printf(0x0F,3,10,"res: 0x%x, val: 0x%x", res, val);
Output:
Quote:
res: 0x0, val: 0x3F0000
Shouldn't *res* be the same as *val*, and shouldn't val = 0x003F0000?
-
The value of res depends on the value of i, which depends on what came in from your read_config. Apparently the original value of your bit_field was 0. (If you had done
Code:
res=(val>>16) & 0xff;
I would expect res to be the same secPerTrk, i.e., 0x3F.
And val is 0x003F0000. (Leading zeroes don't print unless you do something fancy. Granted you're using an outre version of printf, but %x by default doesn't pad zeroes.)
-
still having trouble understanding this. I tried mapping the memory to a pointer, but I am sure I am using it wrong as it keeps causing a double-fault:
Code:
unsigned char* pBar5;
unsigned int* pTFR0;
pBar5 = (unsigned char*)mapreg(BAR5, BAR5Sze); //map bar5
pTFR0 = (unsigned int*)(pBar5+0x90); //map offset to pointer
//initialize ata
*pTFR0 = (pTFR0&0xFF00FFFF) + (secPerTrk<<16); //write to memory
pci_read_config_dword(&pci,pBar5[0x90],&i); //read offset to i
res=(i>>16) & 0xff; //shift and mask
printf("res: 0x%x", res);
thanks in advance
-
If you plan to mask off what is pointed to by pTFR0, you would use (*pTFR0&0xFF00FFFF).
Also pBar5[0x90] corresponds to *(pBar5+0x90), in other words the contents of your 0x90, not the pointer itself, which I'm pretty sure you were using before. (In other words: pBar5[0x90] is a character while pBar5+0x90 is a pointer.)
-
I am not able to test this now, but if I:
Code:
unsigned char* pBar5;
unsigned int* pTFR0;
pBar5 = (unsigned char*)mapreg(BAR5, BAR5Sze); //map bar5
pTFR0 = (unsigned int*)(pBar5+0x90); //map offset to pointer
//initialize ata
*pTFR0 = (*pTFR0&0xFF00FFFF) + (secPerTrk<<16); //write to memory
pci_read_config_dword(&pci,pBar5+0x90,&i); //read offset to i
res=(i>>16) & 0xff; //shift and mask
printf("res: 0x%x", res);
that should work and if not then it is a problem with my mapping?
-
The read_config thing is at least consistent with what you had before that appeared to give you an answer, so that's probably right. And the *pTFR0 is what you wanted.
-
I tried this:
Code:
unsigned char* pBar5;
unsigned int* pTFR0;
// Map the memory
pBar5 = (unsigned char*)mapReg(BAR5, BAR5Sze);
pTFR0 = (unsigned int*)(pBar5+0x90); //map offset to pointer
//initialize ata
*pTFR0 = (*pTFR0&0xFF00FFFF) + (secPerTrk<<16); //write to memory
pci_read_config_dword(&pci,(unsigned)(pBar5+0x90),&i); //read offset to i
res=(i>>16) & 0xff; //shift and mask
printf(0x0f,3,10,"res: 0x%x", res);
And it double-faults the CPU. I think what is happening is that I am trying to map an address to a part of memory that I am not allowed to access as it is not apart of my kernels address space. So is there a way to access a memory address without mapping it? If so, how?
-
to pick back up on our discussion about bitfields, suppose I have this dilema:
I must use outb and inb to read from an IO address at 0x9804, this address contains four 8bit registers totaling 32bits wide. How would I access bitfield 23:16 for both read and write; knowing I can only read and write 8 bits at a time?
-
That depends on the specifics of how you can read and write 8 bits at a time.
Is your IO address byte-based? If so, then with your address at 0x9804 the bitfield you want is 0x9805, and we're done. However, if you can only access aligned addresses, then you'll have to think. OTOH, if you can only read and write 8 bits at a time, I would be somewhat surprised to be restricted to an alignment.
So the question is: can you read/write to address 0x9805?
-
oh, your right, I am sure it must be aligned by doing ~3, just as I was doing with the pci config registers. I'll try though, brb.
EDIT:
I tried it and it returned the right value, but how would I align as I think I must.
-
Well, but wait. 0x9805 & ~3 is 0x9804. Can you do inb (or whatever your "read eight bits at a time" function is) on address 0x9805 (no ~3 stuff), or does it have to be aligned to a 32-bit boundary (which is what the ~3 is doing for you)?
-
I think it must be aligned to a 32 bit boundary because each new base address starts with 0x00 as an offset and this one has two 32 bit boundaries one at offset 0x00 and the other at 0x04, then like I said the next base address starts with an offset of 0x00. I could show you the data sheet if you want.
There are a total of 6 base addresses 5 of which are I/O addresses. The address I am after is the first base address (I/O) and it starts at 9800 with two offsets (0x00 and 0x04) each containing 32 bits, then the next base address (I/O) starts at 9C00 with one offset (0x00) containing 32 bits.
EDIT: found out they are standard byte-aligned.
-
By "returned the right value", you mean you have a BYTE with the correct eight bits in it? If so, then that part's done. Or do you have an int, with the proper bits in 23..16? And then outb is probably the same way.
As I said, if you can access just the eight bits at address 0x9805, then do so. Somewhere on your data sheet it should say whether those base addresses are the only places you can start or if you can get single bytes (or maybe the function that you're using has documentation). I don't know enough about PCI to be able to tell you. If you must start at 0x9804, then you'll need to read eight bits, throw them away, and then read the next eight bits.
Edit: If they are byte-aligned, then address 0x9805 should be a perfectly cromulent address to read from/write to.
-
here is the data sheet: http://gkernel.sourceforge.net/specs...095-B2.pdf.bz2
here is what I tried that returned what was written:
Code:
//let base = 9800
unsigned char i;
outb(base+0x05, 0x3F);
i=inb(base+0x05);
return: 0x3F
my inb and outb are just inline asm to work with asm instructions inb and outb as normal. If I am to start at 9804 and throw away bytes how would I do that, in a loop counting down from 8? /me confused