Accessing PCI Memory Mapped Registers in Linux Kernel
Hi, A few days ago, I posted about accessing PCI memory mapped registers. (FYI, the platform I use is 32bit architecture and Linux kernel compiled in 32 bit intel based architecture.) Now, I found that there is a problem to access 16b aligned registers. For example, ------------- struct foo { unsigned int TEST1; unsigned short int a1[256]; } void * regsva; struct foo *test_foo; if ((regsva = ioremap_nocache(dev->base_addr, (16 * 1024))) == NULL) { printk("ioremap() failed\n"); goto fail; } test_foo = (struct foo*)regsva; printk(KERN_DBG "value TEST1: 0x%lx\n", readl(test_foo->TEST1)); printk(KERN_DBG "value 0: 0x%x\n", readw(&test_foo->a1[0]); printk(KERN_DBG "value 1: 0x%x\n", readw(&test_foo->a1[1]); ------------- The above code in PC (intel based 32bit architecture) with the same h/w module shows that value TEST1: 0x8080 value 0: 0x9090 value 1: 0xa0a0 So, that's valid value. (I have datasheet to check if the value is correct or not.) But, when the code is run on our platform (32bit) with the same h/w module, it shows that value TEST1: 0x8080 value 0: 0xFFFF value 1: 0xFFFF Now, if I change the printk as printk(KERN_DBG "value 0: 0x%x\n", readl(&test_foo->a1[0]); printk(KERN_DBG "value 1: 0x%x\n", readl(&test_foo->a1[1]); Then, even PC shows 0xFFFF like this: value 0: 0xFFFFFFFF value 1: 0xFFFFFFFF So, if the read bit is not aligned correctly, it looks it cannot read correctly. OK, then, How can our platform (32 bit) read correctly 16b aligned PCI memory mapped register? (As long as the register is 32 bit, there is no problem.) At least, I would like to understand why the 16 bit registers and 32 bit registers are responding differently. Thanks, Daniel
Hi Daniel......... On Tue, Dec 21, 2010 at 16:04, YOUNGWHAN SONG <breadncup@gmail.com> wrote:
test_foo = (struct foo*)regsva;
I was thinking differently, could it be that casting...as shown above...introduce this behaviour? what if you just point to the address...directly without any "container" such as struct foo?
printk(KERN_DBG "value TEST1: 0x%lx\n", readl(test_foo->TEST1)); printk(KERN_DBG "value 0: 0x%x\n", readw(&test_foo->a1[0]); printk(KERN_DBG "value 1: 0x%x\n", readw(&test_foo->a1[1]);
in the above statement, it means "take the address of a1[0 and read some bytes from that address", right? -- regards, Mulyadi Santosa Freelance Linux trainer and consultant blog: the-hydra.blogspot.com training: mulyaditraining.blogspot.com
Hi Mulyadi, On Tue, Dec 21, 2010 at 9:59 AM, Mulyadi Santosa <mulyadi.santosa@gmail.com>wrote:
Hi Daniel.........
On Tue, Dec 21, 2010 at 16:04, YOUNGWHAN SONG <breadncup@gmail.com> wrote:
test_foo = (struct foo*)regsva;
I was thinking differently, could it be that casting...as shown above...introduce this behaviour? what if you just point to the address...directly without any "container" such as struct foo?
printk(KERN_DBG "value TEST1: 0x%lx\n", readl(test_foo->TEST1));
printk(KERN_DBG "value 0: 0x%x\n", readw(&test_foo->a1[0]); printk(KERN_DBG "value 1: 0x%x\n", readw(&test_foo->a1[1]);
in the above statement, it means "take the address of a1[0 and read some bytes from that address", right?
-- regards,
Mulyadi Santosa Freelance Linux trainer and consultant
blog: the-hydra.blogspot.com training: mulyaditraining.blogspot.com
As we've talked, it looks the code would be ok, but I guess architecture doesn't handle the 16 bit address correctly. Our team will find a way to get through this by modifying the PCI module. Thanks, Mulaydi for this post. Have a great day. Daniel
As we've talked, it looks the code would be ok, but I guess architecture doesn't handle the 16 bit address correctly. Our team will find a way to get through this by modifying the PCI module. Which is the platform/arch you are seeing this problem as opposed to intel(Where the code works?). Remember on Intel, I/O space is separate from main memory. On other platforms(say on ARM) its memory mapped. I suspect the dev->base_addr may not be the same on both platforms. Have you checked it?
-syed
Hi Daniel.. On Wed, Dec 22, 2010 at 08:40, Daniel (Youngwhan) Song <breadncup@gmail.com> wrote:
As we've talked, it looks the code would be ok, but I guess architecture doesn't handle the 16 bit address correctly. Our team will find a way to get through this by modifying the PCI module.
OK, got it...just keep us informed about the progress whenever possible. I am kinda curious about this issue... -- regards, Mulyadi Santosa Freelance Linux trainer and consultant blog: the-hydra.blogspot.com training: mulyaditraining.blogspot.com
participants (4)
-
Daniel (Youngwhan) Song -
Mulyadi Santosa -
Syed Khader -
YOUNGWHAN SONG