Hey guys, me again. :)
So, my device is working great now that I can access the GPIO pins via userspace (using iotools w/ Tom Sylla's help) and can power on the device. However, I'd like to be able to toggle the power on via a kernel driver as well, but I'm having trouble accessing the same memory range from kernelspace.
For example:
iotools io_read8 0xA00
Will return the state of the first 5 GPIO pins. I see that iotools calls iopl() to be able to access this location from userspace.
When I try to do the same thing in the kernel:
unsigned short b; unsigned short* ptr = (unsigned short*)(0xA00);
if(access_ok(VERIFY_READ, ptr, 8)) { get_user(b, ptr);
...I immediately get a segfault. From what I've read and seen in other example code, I believe I'm doing this right. However, I may be making some wrong assumptions. I was just curious if anyone would be able to shed some light on the subject--perhaps I'm missing some virtual memory offset functions or similar...
On Thu, Apr 14, 2011 at 7:13 PM, Jeremy Moles cubicool@gmail.com wrote:
Hey guys, me again. :)
So, my device is working great now that I can access the GPIO pins via userspace (using iotools w/ Tom Sylla's help) and can power on the device. However, I'd like to be able to toggle the power on via a kernel driver as well, but I'm having trouble accessing the same memory range from kernelspace.
For example:
iotools io_read8 0xA00
Will return the state of the first 5 GPIO pins. I see that iotools calls iopl() to be able to access this location from userspace.
When I try to do the same thing in the kernel:
unsigned short b; unsigned short* ptr = (unsigned short*)(0xA00);
if(access_ok(VERIFY_READ, ptr, 8)) { get_user(b, ptr);
...I immediately get a segfault. From what I've read and seen in other example code, I believe I'm doing this right. However, I may be making some wrong assumptions. I was just curious if anyone would be able to shed some light on the subject--perhaps I'm missing some virtual memory offset functions or similar...
Hello! I'm not a C programmer, I just make use of its strengths and some of its weaknesses. That being stated, why don't you explain more about what you're trying to achieve without of course releasing anything considered a trade secret.
For example are you using the uncommitted GPIO lines to access a feature on your device? And is your device returning something back to your board? Come to that, what is your device doing? That's the big thing I am curious about, again without doing that above.
For what I do with Linux, I am interested in making use of your ideas, but again there is that limitation. Also is this being done on a board that was built by your shop, or did it start out life as a reference platform.
----- Gregg C Levine gregg.drwho8@gmail.com "This signature fought the Time Wars, time and again."
Jeremy Moles wrote:
working great now .. via userspace
..
However, I'd like to be able to toggle the power on via a kernel driver as well,
Why?
but I'm having trouble accessing the same memory range from kernelspace.
For example:
iotools io_read8 0xA00
io_read8 is not a memory access, it is an I/O access. x86 has two different address spaces on the bus, and different instructions to access them.
The superio is not memory mapped..
When I try to do the same thing in the kernel:
unsigned short b; unsigned short* ptr = (unsigned short*)(0xA00);
if(access_ok(VERIFY_READ, ptr, 8)) { get_user(b, ptr);
...I immediately get a segfault.
..so that's not the way to reach it. Last time I did this I used inb() and outb(). Remember to use barriers as neccessary and also make sure that request_region() succeeds before you touch any hardware.
The proper way to implement GPIO support is btw to write a gpio class driver for it. There are lots of gpio drivers already in the kernel. I would actually not be surprised if your chip is already supported by one of them, and if not one could probably be extended easily. The GPIO drivers are exposed to userspace via sysfs.
Again; why does your other kernel driver need to deal with this GPIO? This smells like a questionable design decision was made somewhere in the chain. Better fix that sooner than later in that case..
//Peter
On Fri, 2011-04-15 at 02:07 +0200, Peter Stuge wrote:
Jeremy Moles wrote:
working great now .. via userspace
..
However, I'd like to be able to toggle the power on via a kernel driver as well,
Why?
but I'm having trouble accessing the same memory range from kernelspace.
For example:
iotools io_read8 0xA00
io_read8 is not a memory access, it is an I/O access. x86 has two different address spaces on the bus, and different instructions to access them.
The superio is not memory mapped..
When I try to do the same thing in the kernel:
unsigned short b; unsigned short* ptr = (unsigned short*)(0xA00);
if(access_ok(VERIFY_READ, ptr, 8)) { get_user(b, ptr);
...I immediately get a segfault.
..so that's not the way to reach it. Last time I did this I used inb() and outb(). Remember to use barriers as neccessary and also make sure that request_region() succeeds before you touch any hardware.
The proper way to implement GPIO support is btw to write a gpio class driver for it. There are lots of gpio drivers already in the kernel. I would actually not be surprised if your chip is already supported by one of them, and if not one could probably be extended easily. The GPIO drivers are exposed to userspace via sysfs.
Again; why does your other kernel driver need to deal with this GPIO? This smells like a questionable design decision was made somewhere in the chain. Better fix that sooner than later in that case..
It's really just an exercise to see whether it can be done or not. I thought it might be interesting to continue to experiment with the hardware a bit more. The real code to control the device is just a bash script using iotools.
However, using inb() doesn't change anything; it still panics the kernel immediately. There must be some kernel setup I'm mising... oh well.
//Peter