Thread: Device Register Access

  1. #1
    Registered User
    Join Date
    Sep 2008
    Posts
    22

    Device Register Access

    Hi. I am seriously confused as to how to access a memory address+offset and bit field. My attempt is below:

    Code:
    #define secPerTrk 0x3F //= 63
    #define maxHeadNm 0xFE //= 254
    #define intATACmd 0x91 //= initialize ata command
    
    //initialize ata
    pci_write_config_dword(&pci, ((BAR5+0x90)>>16), secPerTrk);
    pci_write_config_dword(&pci, ((BAR5+0x94)>>16), maxHeadNm);
    pci_write_config_dword(&pci, ((BAR5+0x94)>>24), intATACmd);
    
    //poll status
    pci_read_config_dword(&pci, (BAR5+0x94), &i);
    
    while(!((i >> 24) & 0x80) == 0) //is busy?
    {
    	delay(10);
    	pci_read_config_dword(&pci, ((BAR5+0x94)>>24), &i);
    }
    
    //ready
    printf(0x0F,3,10,"Device Ready!");
    I am returning Device Ready, but I just don't believe it is working as I do not trust my shifts. Can someone please take a look at my code and tell me what I am doing wrong?

    Thanks

  2. #2
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    Even without knowing what BAR5 is your shifts still look suspect...

    ((BAR5+0x90)>>16)

    if you are adding 0x90, then shifting right 16 bits, you're going to lose the bottom 16 bits... so having added the 0x90 is kinda inconsequential. Unless you're expecting some fancy carry but I doubt it.

  3. #3
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    What nonoob said, plus you should be OR'ing these flags, not adding them.

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    If BAR5 is a memory address and 0x90 and 0x94 are supposed to be offsets, then you would want BAR5[0x90] and BAR5[0x94] -- or if you insist on showing your work *(BAR5+0x90). As it is, you are shifting the pointer 16 or 24 bits, not the contents of the memory.

  5. #5
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    I was looking 'round the weeb... It's a good idea to get the definition of pci_write_config_dword, and understand the arguments. See some examples. The second parameter is usually some low 0xnn thingy. The shifts are probably meant for the third arguments where there are masks and such.

  6. #6
    Registered User
    Join Date
    Sep 2008
    Posts
    22
    I tried mapping the address to a pointer but gcc wouldn't allow me to use the bitwise shift operator on the pointer. I tried:

    Code:
    //vars
    unsigned char* pBar5;
    unsigned int* tfreg0;
    
    //map it
    pBar5 = (unsigned char*)mapreg(BAR5&(~0xf), BAR5Sze);
    
    //set it
    tfreg0 = (unsigned int*)(pBar5+0x90);
    
    //test it
    pci_write_config_dword(&pci, (tfreg0>>24), 0x1234);
    pci_read_config_dword(&pci, (tfreg0>>24), &i);
    
    //print it
    printf("res: 0x%x",((tfreg0>>24)&0xFF)); //should be 0x1234
    My mapreg function works as it returns the right address range, but GCC complains about the bitwise shift operator, so I couldn't test that return. I definitely suspect my shifts, any help?
    Last edited by jacob12; 09-29-2008 at 07:48 PM.

  7. #7
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    What do you think tfreg0>>24 should mean? If you want to access certain bits of the int that tfreg0 points to, then you need masking, not shifting. If you really only want the top eight bits of this address, then I guess that's what you want.

    Edit: I'm deleting this edit because I think I misunderstood your original intent.

    (Is this post confusing yet? I should just stop now.)
    Last edited by tabstop; 09-29-2008 at 07:57 PM.

  8. #8
    Registered User
    Join Date
    Sep 2008
    Posts
    22
    No, I think you are right, can you show me an example?

  9. #9
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    I'm still not clear on what you're trying to do, so I'm going to do everything I can think of:
    The top eight bits (the slowest-changing) of the address is what you've got, intptr>>24.
    The low eight bits (the fastest-changing) of the address is intptr&0xff.
    The top eight bits of the memory pointed to, shifted down, would be (*intptr) >> 24.
    The eight bits at offset 0x90 from a memory address would be charptr[0x90].

  10. #10
    Registered User
    Join Date
    Sep 2008
    Posts
    22
    I'm sorry, I'll just show you what I am after:

    So its BAR5+0x90 to get to the stuff below:

    Address Offset: 90H
    Access Type: Read/Write
    Reset Value: 0x0000_0000

    Bit [31:00]: IDE0 Task File Data (R/W). This bit field defines the IDE0 Task File Data register. This register
    can be accessed as an 8-bit, 16-bit, or 32-bit word, depending upon the PCI bus Byte Enables. The data written
    to this register must be zero-aligned. To access 8-bit Task File Data, the PCI bus Byte Enable for byte 0 must
    be active. To access 16-bit Task File Data, the Byte Enables for byte 1 and byte 0 must be active. To access
    32-bit Task File Data, the Byte Enables for all four bytes must be active.
    • Bit [31:24]: IDE0 Task File Starting Sector Number (R/W). This bit field defines the IDE0 Task File Starting
    Sector Number register. Access to this bit field is permitted only if the PCI bus Byte Enable for byte 3 is active.
    • Bit [23:16]: IDE0 Task File Sector Count (R/W). This bit field defines the IDE0 Task File Sector Count register.
    Access to this bit field is permitted only if the PCI bus Byte Enable for byte 2 is active.
    • Bit [15:08]: IDE0 Task File Features (W). This write-only bit field defines the IDE0 Task File Features register.
    Access to this bit field is permitted only if the PCI bus Byte Enable for byte 1 is active.
    • Bit [15:08]: IDE0 Task File Error (R). This read-only bit field defines the IDE0 Task File Error register. Access
    to this bit field is permitted only if the PCI bus Byte Enable for byte 1 is active.
    I need to read and write bit field 23:16. Hope this helps clear it up.

  11. #11
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    I have failed here -- I can't even find two sources that agree on what data types this pci_whatever_write function takes, let alone what they mean. So unless you pony up that, I can't help you with your arguments.

    I can deal with bitwise access, though: if we manage to get an int variable i whose bits are as above, then we can get the bitfield by doing (i&0xff0000)>>16 (the mask to throw away the other bits, and the shift to move it to the least significant spots). If we have such a variable i, and we want to change just those bits, then we would have to do (i&0xff00ffff) + (newval<<16) -- the first bit keeps the stuff around our bitfield, and the other part stuffs the bitfield in the appropriate place.

  12. #12
    Registered User
    Join Date
    Sep 2008
    Posts
    22
    Sorry man, I wrote that function, here it is:

    Code:
    int pci_read_config_dword (pci_t *pci, unsigned reg,
    		unsigned long *val)
    {
    	outl(PCI_CONFIG_ADDR, 0x80000000L |
    		((unsigned long)pci->bus << 16) |
    		((unsigned)pci->dev << 11) |
    		((unsigned)pci->fn << 8) |
    		(reg & ~3));
    	*val = inl(PCI_CONFIG_DATA+ 0);
    	return 0;
    }
    Do I just:

    Code:
    pci_read_config_dword(&pci,BAR5+0x90,&i);
    result=((i&0xFF000000)>>16);
    And that should read the 23:16 bit field? The entire register is 32 bits.

    Then to write to that field:

    Code:
    value=(i&0xFF00FFFFFF) + (0x3F<<16);
    pci_write_config_dword(&pci, BAR5+0x90, value);
    And that should write 0x3F to bit field 23:16? Thanks
    Last edited by jacob12; 09-29-2008 at 10:25 PM.

  13. #13
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    So, ok, it looks like the second argument would be 0x90/BAR5+0x90/whatever, and the third argument would be the address of a long, like &i the way you have it. Then to read out the bitfield you can do what I have up above.

  14. #14
    Registered User
    Join Date
    Sep 2008
    Posts
    22
    sorry, could you please look at my edits above and just check if I understood you correctly? Thanks in advance.

  15. #15
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    The bitmask should only have four zeroes at the end. You can actually do that in probably less typing and less prone to errors by saying
    Code:
    result = (i>>16) & 0xff;
    that is, shift first and mask second.
    And again, you're off with the other bit mask too -- there are only four F's in the bitfield 0:15, not six.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. DirectInput Device Access (DirectX 10)
    By DarkMasterBosel in forum Game Programming
    Replies: 0
    Last Post: 12-27-2008, 11:41 PM
  2. logical and physical device access
    By pastitprogram in forum Windows Programming
    Replies: 9
    Last Post: 08-05-2008, 03:46 PM
  3. brace-enclosed error
    By jdc18 in forum C++ Programming
    Replies: 53
    Last Post: 05-03-2007, 05:49 PM
  4. Device Driver: sysfs confusion
    By filker0 in forum Linux Programming
    Replies: 0
    Last Post: 12-02-2005, 11:36 AM
  5. Replies: 4
    Last Post: 06-30-2004, 03:11 PM