Hello, For the Paraflasher project I would like to setup a function to automatically detect the presence of the PC's parallel ports and their base addresses. This way it doesn't need to be hard-coded into the program. I was thinking of using /proc/ioports to do this but I am not really sure how to do this in C. Here is what I am thinking:
1. First use grep -c paraport /proc/ioports to check if we have multiple parallel ports and maybe setup loop for it. 2. Then grep paraport /proc/ioports again to get the base address of each parallel port detected. This is where I am stuck. I just need to turn the first 4 characters (base address) into a variable. Can anyone help???
On Sat, Dec 6, 2008 at 10:22 AM, Joseph Smith joe@settoplinux.org wrote:
Hello, For the Paraflasher project I would like to setup a function to automatically detect the presence of the PC's parallel ports and their base addresses. This way it doesn't need to be hard-coded into the program. I was thinking of using /proc/ioports to do this but I am not really sure how to do this in C. Here is what I am thinking:
- First use grep -c paraport /proc/ioports to check if we have multiple
parallel ports and maybe setup loop for it. 2. Then grep paraport /proc/ioports again to get the base address of each parallel port detected. This is where I am stuck. I just need to turn the first 4 characters (base address) into a variable. Can anyone help???
There must be a way to do this in C. Maybe do some digging around in the kernel's include files?
-Corey
you're making it too hard. :-)
If you do this: awk '/rtc/{print $1}'
you get a line like this: cat /proc/ioports | awk '/rtc/{print $1}' 0070-0071
OK, but you just want the first four digits, right? Well, strtoul will do this for you, so: port = strtoul(string, 0, 16);
it will stop at the '-', which is not hex. Problem solved.
But how do I get this into a program?
paraflash `awk '/rtc/{print $1}'`
First arg will be the port addresses.
Instead of 'rtc', use whatever your parallel port name is.
Did you want more than one? Here's another example: [rminnich@xcpu2 coreboot-v3]$ echo `cat /proc/ioports | awk '/ahci/{print $1}' ` 1c20-1c3f 1c40-1c43 1c44-1c47 1c48-1c4f 1c50-1c57 [rminnich@xcpu2 coreboot-v3]$
So your program will see a sequence of arguments, one for each parallel port.
You don't have to do it exactly this way, but this is why we have all these fiddly little tools, so you can put things together without having to write lots of code.
If you don't want users to see this commnand, use popen(3).
thanks
ron
On Sat, 6 Dec 2008 09:49:32 -0800, "ron minnich" rminnich@gmail.com wrote:
you're making it too hard. :-)
If you do this: awk '/rtc/{print $1}'
you get a line like this: cat /proc/ioports | awk '/rtc/{print $1}' 0070-0071
OK, but you just want the first four digits, right? Well, strtoul will do this for you, so: port = strtoul(string, 0, 16);
it will stop at the '-', which is not hex. Problem solved.
But how do I get this into a program?
paraflash `awk '/rtc/{print $1}'`
First arg will be the port addresses.
Instead of 'rtc', use whatever your parallel port name is.
Did you want more than one? Here's another example: [rminnich@xcpu2 coreboot-v3]$ echo `cat /proc/ioports | awk '/ahci/{print $1}' ` 1c20-1c3f 1c40-1c43 1c44-1c47 1c48-1c4f 1c50-1c57 [rminnich@xcpu2 coreboot-v3]$
So your program will see a sequence of arguments, one for each parallel port.
You don't have to do it exactly this way, but this is why we have all these fiddly little tools, so you can put things together without having to write lots of code.
If you don't want users to see this commnand, use popen(3).
Awsome, that is exacly what I was looking for, thanks Ron.
On Sat, 06 Dec 2008 13:07:06 -0500, Joseph Smith joe@settoplinux.org wrote:
On Sat, 6 Dec 2008 09:49:32 -0800, "ron minnich" rminnich@gmail.com wrote:
you're making it too hard. :-)
If you do this: awk '/rtc/{print $1}'
you get a line like this: cat /proc/ioports | awk '/rtc/{print $1}' 0070-0071
OK, but you just want the first four digits, right? Well, strtoul will do this for you, so: port = strtoul(string, 0, 16);
it will stop at the '-', which is not hex. Problem solved.
But how do I get this into a program?
paraflash `awk '/rtc/{print $1}'`
First arg will be the port addresses.
Instead of 'rtc', use whatever your parallel port name is.
Did you want more than one? Here's another example: [rminnich@xcpu2 coreboot-v3]$ echo `cat /proc/ioports | awk
'/ahci/{print
$1}' ` 1c20-1c3f 1c40-1c43 1c44-1c47 1c48-1c4f 1c50-1c57 [rminnich@xcpu2 coreboot-v3]$
So your program will see a sequence of arguments, one for each parallel port.
You don't have to do it exactly this way, but this is why we have all these fiddly little tools, so you can put things together without having to write lots of code.
If you don't want users to see this commnand, use popen(3).
So, to get the command into the program wouldn't I use system() ?
Something like: base_addrs = system("cat /proc/ioports | awk '/paraport*{print $1}'");
para1_base_addr = strtoul(base_addrs, 0, 16);
This should get the firsts parallel ports base address, right? What if I want to get the base address of the second parallel port, can I use strtoul() to skip to the next string after the whitespace?
On Sat, 06 Dec 2008 13:51:28 -0500, Joseph Smith joe@settoplinux.org wrote:
On Sat, 06 Dec 2008 13:07:06 -0500, Joseph Smith joe@settoplinux.org wrote:
On Sat, 6 Dec 2008 09:49:32 -0800, "ron minnich" rminnich@gmail.com wrote:
you're making it too hard. :-)
If you do this: awk '/rtc/{print $1}'
you get a line like this: cat /proc/ioports | awk '/rtc/{print $1}' 0070-0071
OK, but you just want the first four digits, right? Well, strtoul will do this for you, so: port = strtoul(string, 0, 16);
it will stop at the '-', which is not hex. Problem solved.
But how do I get this into a program?
paraflash `awk '/rtc/{print $1}'`
First arg will be the port addresses.
Instead of 'rtc', use whatever your parallel port name is.
Did you want more than one? Here's another example: [rminnich@xcpu2 coreboot-v3]$ echo `cat /proc/ioports | awk
'/ahci/{print
$1}' ` 1c20-1c3f 1c40-1c43 1c44-1c47 1c48-1c4f 1c50-1c57 [rminnich@xcpu2 coreboot-v3]$
So your program will see a sequence of arguments, one for each parallel port.
You don't have to do it exactly this way, but this is why we have all these fiddly little tools, so you can put things together without having to write lots of code.
If you don't want users to see this commnand, use popen(3).
So, to get the command into the program wouldn't I use system() ?
Something like: base_addrs = system("cat /proc/ioports | awk '/paraport*{print $1}'");
para1_base_addr = strtoul(base_addrs, 0, 16);
This should get the firsts parallel ports base address, right? What if I want to get the base address of the second parallel port, can I use strtoul() to skip to the next set of char after the whitespace?
I think I got it:
unsigned long * next; para1_base_addr = strtoul(base_addrs, &next, 16); para2_base_addr = strtoul(next, &next, 16); para3_base_addr = strtoul(next, 0, 16);
right?
system() doesn't give you a pipe to read from.
ron
On Sat, 6 Dec 2008 11:51:10 -0800, "ron minnich" rminnich@gmail.com wrote:
But how do I get this into a program?
paraflash `awk '/rtc/{print $1}'`
base_addrs = system("cat /proc/ioports | awk '/paraport*{print $1}'");
system() doesn't give you a pipe to read from.
Hmm. I guess I am a little confused then how I am supposed to call the bash one-liner from with in the program?
Sorry, I am just trying to understand.
hey, have some fun!
FILE *f; f = popen("date", "r");
fgets(f, data, sizeof(data)); printf(data);
Any sh command in place of "date" will do.
ron
On Sat, Dec 06, 2008 at 10:22:44AM -0500, Joseph Smith wrote:
Hello, For the Paraflasher project I would like to setup a function to automatically detect the presence of the PC's parallel ports and their base addresses. This way it doesn't need to be hard-coded into the program. I was thinking of using /proc/ioports to do this but I am not really sure how to do this in C. Here is what I am thinking:
- First use grep -c paraport /proc/ioports to check if we have multiple
parallel ports and maybe setup loop for it. 2. Then grep paraport /proc/ioports again to get the base address of each parallel port detected. This is where I am stuck. I just need to turn the first 4 characters (base address) into a variable. Can anyone help???
Would an environment variable be ok? Sed/awk should be able to do that for you.
Thanks, Ward.
Joseph Smith wrote:
For the Paraflasher project I would like to setup a function to automatically detect the presence of the PC's parallel ports and their base addresses.
..
I was thinking of using /proc/ioports to do this
I'm afraid you can't win this one.
If the kernel knows about the ports (ie. if they are listed in /proc/ioports) then it's because there is already a driver in the kernel which is responsible for driving the hardware - and your /userspace program should not interfere.
If there is no driver loaded, there will be no entry in /proc/ioports so you won't know which ports to use.
There are two ways to do this while still playing nicely;
1. Interface with the kernel parport driver. This may not work, I'm not sure if parport offers a userspace API, and if it does I don't know if it offers functionality suitable for bitbanging the port.
2. Make the user specify an IO port (you can give suggestions, 0x3bc 0x378 and 0x278 are the common ones) and check that this port is NOT listed in /proc/ioports.
but I am not really sure how to do this in C.
If you know another language better then just use that. :) It doesn't matter for flashrom, I want potential future plugin stuff to use IPC so that hardware drivers can be written in any language.
In C, I would suggest fopen("/proc/ioports","r"), while(fgets()), then using strstr() to find lines with "parport" and finally sscanf() to convert the string into an uint16_t variable.
Don't forget error checking and corner cases, make sure that you have actually read a full line before letting the loop start over.
//Peter
Joseph Smith wrote:
Hello, For the Paraflasher project I would like to setup a function to automatically detect the presence of the PC's parallel ports and their base addresses. This way it doesn't need to be hard-coded into the program. I was thinking of using /proc/ioports to do this but I am not really sure how to do this in C. Here is what I am thinking:
- First use grep -c paraport /proc/ioports to check if we have multiple
parallel ports and maybe setup loop for it. 2. Then grep paraport /proc/ioports again to get the base address of each parallel port detected. This is where I am stuck. I just need to turn the first 4 characters (base address) into a variable. Can anyone help???
Check out http://people.redhat.com/twaugh/parport/html/parportguide.html
It has some information on how to use /dev/partportX for your purposes.
Stefan
On Sat, 06 Dec 2008 23:32:26 +0100, Stefan Reinauer stepan@coresystems.de wrote:
Joseph Smith wrote:
Hello, For the Paraflasher project I would like to setup a function to automatically detect the presence of the PC's parallel ports and their
base
addresses. This way it doesn't need to be hard-coded into the program. I was thinking of using /proc/ioports to do this but I am not really sure
how
to do this in C. Here is what I am thinking:
- First use grep -c paraport /proc/ioports to check if we have multiple
parallel ports and maybe setup loop for it. 2. Then grep paraport /proc/ioports again to get the base address of
each
parallel port detected. This is where I am stuck. I just need to turn
the
first 4 characters (base address) into a variable. Can anyone help???
Hmm after some research it looks like for every parallel port Linux (kernel 2.4 and up) detects it creates /proc/sys/dev/parport/parport* (0,1,2,3, and so on) directory. Within this directory there is a base-addr file.
cat /proc/sys/dev/parport/parport0/base-addr 888 1912 Then turn the first number into hex (888 => 0x378)
Wala, we have our base address :-)
So, For multi ports I think I just need a shell command that will count how many parport* directories found in /proc/sys/dev/parport/, any ideas?
On Sat, Dec 6, 2008 at 9:52 PM, Joseph Smith joe@settoplinux.org wrote:
cat /proc/sys/dev/parport/parport0/base-addr 888 1912 Then turn the first number into hex (888 => 0x378)
boy do I feel dumb! I forgot entirely about that.
But why not use Stefan's idea of /dev/parportX?
Why do all this other work?
ron
On Sat, 6 Dec 2008 22:53:04 -0800, "ron minnich" rminnich@gmail.com wrote:
On Sat, Dec 6, 2008 at 9:52 PM, Joseph Smith joe@settoplinux.org wrote:
cat /proc/sys/dev/parport/parport0/base-addr 888 1912 Then turn the first number into hex (888 => 0x378)
boy do I feel dumb! I forgot entirely about that.
But why not use Stefan's idea of /dev/parportX?
Why do all this other work?
From everything I have read, there are two main ways to get control over
the parallel port.
One way is to use /dev/parportX. The /dev/parportX method is a higher level driver. I'm still looking into this to see if it will be better. I think Stefan was referring to the parport_find_base() function which wouldn't work for me. For that you input a base address and it returns the corresponding parallel port.
The other method is directly controlling the I/O. It is a lower level driver directly accessing the hardware. It is supposed to be faster, which will be good for flashing. It is also very simple, using outb and inb. This is the method I prefer. But it seems in all the examples I have looked at the the base address is statically defined. That is what I am trying to do is automate that.
On Sat, 6 Dec 2008 22:53:04 -0800, "ron minnich" rminnich@gmail.com wrote:
On Sat, Dec 6, 2008 at 9:52 PM, Joseph Smith joe@settoplinux.org wrote:
cat /proc/sys/dev/parport/parport0/base-addr 888 1912 Then turn the first number into hex (888 => 0x378)
boy do I feel dumb! I forgot entirely about that.
But why not use Stefan's idea of /dev/parportX?
Why do all this other work?
From everything I have read, there are two main ways to get control over
the parallel port.
One way is to use /dev/parportX. The /dev/parportX method is a higher level driver. I'm still looking into this to see if it will be better. I think Stefan was referring to the parport_find_base() function which wouldn't work for me. For that you input a base address and it returns the corresponding parallel port.
The other method is directly controlling the I/O. It is a lower level driver directly accessing the hardware. It is supposed to be faster, which will be good for flashing. It is also very simple, using outb and inb. This is the method I prefer. But it seems in all the examples I have looked at the the base address is statically defined. That is what I am trying to do is automate that.