Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 31 Jan 1997 21:36:21 +0100
From:      se@freebsd.org (Stefan Esser)
To:        hackers@freebsd.org
Subject:   PCI LKM: How to find object file from PCI ID ...
Message-ID:  <19970131213621.EQ13588@x14.mi.uni-koeln.de>

next in thread | raw e-mail | index | archive | help
Hi all!


I've been thinking about the best way to have a user-land program
determine, whether any of the object files in the /lkm directory
might be appropriate for some PCI device, for which no driver 
exists in the kernel.

I test-implemented all of them, and found that all approaches that
relie on some text being present in the object file as a string or
as part of a symbol require this information to be inlined verbatim
(i.e. you can't just reference a macro like NCR_810_ID, since it is
only defined regarding its numeric contents).


Possibilities:

1) Have a config file that contains PCI ID to LKM mappings.
2) Put the PCI IDs as character strings into the LKM binary.
3) Create symbols with names that allow to derive PCI IDs supported.
4) Put an array of PCI IDs into the LKM under a well known name.


Examples:

1) File containing lines like:

D 00011000 ncr.o
D 000f1000 ncr.o
D 802910ec if_ed.o

   [ The "D" denotes a PCI Device ID, while "C" would match a 
     PCI Class, and "S" a Subvendor ID. ]

2) Create (symbolic) links that contain the PCI ID and point to the
   LKM file:

/dev/pci/d_00011000 -> ../ncr.o
/dev/pci/d_000f1000 -> ../ncr.o
/dev/pci/d_802910ec -> ../if_ed.o

3) Include a string into the binary, for example:

static const char pciids [] = "\nPCI_D 00011000 000f1000\n";

4) Define a character variable, of which only the name is significant:

static char pci_d_00011000;
static char pci_d_000f1000;

5) Build an array of integers under a known name:

static const int pci_d_ids [] = { 0x00011000, 0x000f1000 };


Advantages:

1) Trivial implementation, no driver changes required.
   Fast lookup from a script possible, for highest flexibility.

2) Trivial implementation, extremely fast lookup, high flexibility.
   Similar to 1), but uses file names as keys to directly access the
   LKM required.

3) Easy to implement and to use (just a "strings | grep").

4) Easy to implement and to use, but requires system command "nm"
   instead of "strings".

5) The only one not worried about the details of the representation
   of the number (i.e. operating on a number instead of a string).

3+4+5) do not require any steps beyond copying the LKM into the
target directory for making it available to the PCI LKM loader.


Disadvantages:

1) File must be maintained on driver updates (but this could be
   automated to happen in the install target of the LKM's Makefile
   or the package "description" of a LKM distributed as binary).

2) Lots of file names are to be created, since a single driver may
   support devices with up to 10 distinct PCI IDs.
   Inconsistencies are possible, if a LKM is replaced by one for a
   different (set of) PCI device(s), but the old PCI IDs still point
   to the LKM name (this could be avoided by using hard links).

3) Requires an action to be performed on each file in the LKM 
   directory, which is significantly slower than a grep on a file.
   False hits are possible, but can be minimized by choosing a good
   lead in string for each line.
   The character array increases the kernel space requirement of the 
   driver.

4) Same as 3), with "nm" being slower and possibly not available on
   a system (if it is not at all used for software development).

5) Can't be done in a simple shell script. (Ok, you could make this
   a shell script calling the debugger to extract symbol information :)
   A C program is required to extract the symbol table with reasonable
   performance.

3+4+5) Could take advantage of cacheing information retrieved on boot
time in file, and then the advantages of 1) could be provided :)


Conclusions:

I'm not going to choose either of these for the time being, but would 
like to receive some feedback from interested parties.

Since USB uses very similar device IDs and will require loading and
unloading of LKMs whenever a device is connected or deconnected (USB
supports hot-pluggable devices !), I would like to find a solution 
that applies to USB, too. It is for that reason, that I consider the
real and CPU times required to identify the LKM ...


My prefered solution would be 1), currently, since only a low number of
PCI drivers exist. The file of PCI IDs could be automatically maintained 
by each drivers install target in the Makefile.

Solution 2) also has its advantages. But it requires the creation of
a new directory (under /lkm to allow for hard links to point there).
It does not differ from 1) that much, actually ...

3+4+5) put all the information into the LKM binary, and need no further
steps to be performed, besides moving the LKM in an agreed-upon directory.
I do not like the overhead of looking into some 30 files, which easily
might become 3 times as many, if more drivers are made available as LKM.
If a file is created from the 


Any further ideas ?

Regards, STefan



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19970131213621.EQ13588>