Initial revision
[opensuse:hwinfo.git] / doc / index.html
1 <html>
2 <head>
3 <title>Automatic Hardware Probing</title>
4 </head>
5
6 <body>
7 <h1>Automatic Hardware Probing</h1>
8
9 Author: Steffen Winterfeldt <a href="snwint@suse.de">snwint@suse.de</a><p>
10
11 Current version (9 Aug 1999): 0.7.1<p>
12
13 Everything related to this project can be found in <code>~snwint/hd</code>
14
15 <h2>Contents</h2>
16
17 <ul>
18   <a href="#intro">Introduction</a><br>
19   <a href="#general">General Considerations</a><br>
20   <a href="#tech">Technical Specification</a><br>
21   <ul>
22     <a href="#intend">Intended Functionality</a><br>
23     <a href="#pstruc">Program Structure</a><br>
24     <a href="#works">Working Parts</a><br>
25     <a href="#nexts">Next Steps</a><br>
26   </ul>
27   <a href="#detail">Technical Details &amp; Documentation</a><br>
28   <ul>
29     <a href="#idr">Internal Data Representation</a><br>
30     <a href="#dspecs">Database Specification</a><br>
31     <ul>
32       <a href="#pciids">PCI ID/vendor Entries</a><br>
33       <a href="#eisaids">EISA ID/vendor Entries</a><br>
34       <a href="#busids">Bus Entries</a><br>
35       <a href="#classids">Class/Subclass Entries</a><br>
36       <a href="#compatids">ISA-PnP Compatible Device Entries</a><br>
37       <a href="#csids">Assigning a Class/Subclass to a Device</a><br>
38       <a href="#modids">Assigning a Device Driver to a Device</a><br>
39     </ul>
40     <a href="#hwcats">Hardware Categories</a><br>
41     <ul>
42       <a href="#mmem">Main Memory</a><br>
43       <a href="#monitor">Monitor</a><br>
44       <a href="#pnpcards">ISA-PnP Cards</a><br>
45       <a href="#pcicards">PCI Cards</a><br>
46     </ul>
47   </ul>
48   <a href="#ref">References &amp; Sources</a><br>
49 </ul>
50
51 <h2><a name=intro>Introduction</a></h2>
52
53 Autoprobing should be able to identify (nearly) all installed hardware. This
54 poses more or less difficulties depending on the kind of hardware being
55 probed. The main problems are caused by non-PnP ISA cards and devices
56 attached to serial and parallel interfaces. Not to mention vendor specific
57 interfaces.
58
59 <h2><a name=general>General Considerations</a></h2>
60
61 <ul>
62   PCI cards<br><ul>
63     Information about PCI cards can be easily read from /proc/bus/pci.
64     /proc/bus/pci/devices has a list of all the PCI devices and
65     /proc/bus/pci/xy/ab.c has detailed info about individual devices.
66     (These files contain the PCI configuration space header.)<p>
67
68     Data in the config space include device/vendor ids, device class ids
69     and resources used by that device. Note: there are no <em>strings</em>
70     of any kind (e.g. device <em>names</em>).<p>
71
72     Note that only the first 64 bytes of config space (256 bytes total) are
73     available to non-root users.
74   </ul><br>
75
76   Plug and Play ISA cards<br><ul>
77     PnP cards have an onboard configuration space that contains information
78     about the needed (and configured) resources as well as some data
79     characterizing the device. Unlike PCI there is no data assigning
80     the device to a device class. So you cannot automatically recognize a
81     card as, e.g., a SCSI controller.<p>
82
83     It is, however, possible that the config data contains a 'compatible
84     device' tag. This tag is a vendor/device id pair. In cards I have seen
85     so far this feature was used to point to 'PNPxxxx' devices. The
86     special 'PNP' vendor was actually reserved by Microsoft to allow
87     standard drivers to be used (and to classify old ISA cards). For
88     example, 'PNP80d6' is a NE2000 compatible network adapter. The complete
89     list is available at Microsofts web site. (Note that this very list
90     is referenced to as 'compatible device id list' in the Plug and Play
91     ISA Specification, Version 1.0a.)
92   </ul><br>
93
94   non-PnP ('legacy') ISA cards<br><ul>
95     Detecting old ISA cards can basically be done in two ways: either
96     probing the interface directly (which basically comes down to
97     trying to load a bunch of modules). The other way is to check the BIOS ROM
98     for installed hardware. As most cards come with their own BIOS routines,
99     this <em>might</em> work in a lot of cases. The advantage would be to
100     avoid lockups by the more or less erratic module loading procedure.
101   </ul><br>
102
103   ISA/VLB Graphics Cards<br><ul>
104     Aside from the above mentioned BIOS ROM scanning, there is the SuperProbe
105     tool. Another source of information would be the VESA interface that all
106     but the <em>very</em> old boards support. Via VESA calls we can get an id
107     string, the graphics card memory size and, in case of VESA >=2.0 the address
108     of a frame buffer (if supported).<p>
109
110     To avoid problems, calling the VESA interface should be added to
111     <code>syslinux</code>, too (see Monitor, below).
112   </ul><br>
113
114   Monitors<br><ul>
115     Most modern monitors can provide configuration data via the DDC
116     (Display Data Channel). As XFree86 does currently not support reading
117     this info, the only practicable way is to use an existing VESA call
118     to access this data.<p>
119
120     This is best done, <em>before</em> Linux has started, so it comes down
121     to modify the boot manager. In this case <code>syslinux</code>.
122     The config data can be transfered via the kernel command line.
123   </ul><br>
124
125   Mice/Modems (Serial Devices)<br><ul>
126     There exists a Plug and Play COM Device Specification that allows
127     those devices to return some config data. The ids used have the same
128     format as the ISA-PnP ids (that is, are actually EISA ids).<p>
129
130     For Modems not conforming to this spec, we would have to issue some
131     AT commands. The Lothar Project does exactly this.<p>
132
133     For Mice, there is apparently a <em>very</em> rudimentary identification
134     process that allows more or less to <em>detect</em> the presence of a
135     mouse. To distinguish between the various mouse protocols it might be
136     necessary to <em>move</em> the mouse (to see which data interpretation
137     makes sense).
138   </ul><br>
139
140   Printer (Parallel Devices)<br><ul>
141     As you might guess, there is a Plug and Play Parallel Port Devices Spec
142     as well.<p>
143
144     Namely printer are reported to conform to it. The kernel already has
145     support for it. The info is available in /proc/parport.
146   </ul><br>
147
148   PS/2 Mice<br><ul>
149     I suppose they will all work with the standard PS/2 driver. This might
150     not be the case with support for all the special features they might
151     have (wheels, extra buttons, whatever).
152   </ul><br>
153
154   Other System Components<br><ul>
155     Floppy: check /proc/devices? Scan output of dmesg?
156   </ul><br>
157
158   Storage Devices<br><ul>
159     As long as they are attached to SCSI or IDE there should be no problem
160     identifying these. Information can be found in /proc/scsi, /proc/ide.<p>
161
162     A list of CD-ROM devices can be found in /proc/sys/dev/cdrom/info.<p>
163
164     Partition info is in /proc/partitions.
165   </ul>
166 </ul>
167
168 <h2><a name=tech>Technical Specification</a></h2>
169
170 Current (preliminary) project name: <code>hd</code>.<p>
171
172 It consists of a hardware detect library (<code>libhd.a</code>) and a
173 simple test application (<code>hw</code>) that dumps all hardware info
174 to <code>stdout</code>.<p>
175
176 <h3><a name=intend>Intended Functionality</a></h3>
177
178 All functionality will be packed into one library (<code>libhd.a</code>)
179 that must be linked to the application. As for now I do not plan to make a
180 shared version.<p>
181
182 Probing may be done on different 'levels' (or 'depths'). That is you can do
183 a 'save' probe looking for hardware that can be probed for without risking
184 to lock up the system and a 'thorough' probe that will try to find as many
185 devices as possible.<p>
186
187 The results are passed as a linear list of hardware components. Sufficient
188 data to assign e.g. hard discs to their interfaces will be provided,
189 however.<p>
190
191 The hardware data will contain information about errors that occurred during
192 the probing and data indicating the source of information (e.g. ports read
193 from /proc/ioports etc.).<p>
194
195 To work around lock-ups it will be possible to specify which hardware
196 component should not be probed. For this the library will provide a string
197 identifying the following probing step. (And write it to stderr.)<p>
198
199 <h3><a name=pstruc>Program Structure</a></h3>
200
201 The probing code consists of several independent modules. The results are
202 reported back and collected as a linear list of hardware components. Each
203 module is <em>completely</em> responsible for the probing process i.e. there
204 is no 'meta' interface telling them how to do it. Although the probing
205 process man be restricted (according to the probing levels mentioned
206 above).<p>
207
208 The modules should be designed as not to interfere with the probing of
209 others.<p>
210
211 The library uses an external data file containing configuration information.
212 It does, however, not <em>rely</em> on it being present. Reported results
213 might be less accurate, however.<p>
214
215 This data file can be used to associate a hardware component with
216 a device driver.<p>
217
218 <h3><a name=works>Working Parts</a></h3>
219
220 <ul>
221   Main Memory<br><ul>
222     Reports the actual amount of physical memory (e.g 128MB).
223   </ul><br>
224
225   Monitor<br><ul>
226     Reads the EDID (Extended Display ID) record via DDC (Display Data
227     Channel).<p>
228
229     Unfortunately is reading via DDC graphics card specific (XFree86 4.0
230     intends to implement an interface) but there is a VBE 2.0 (VESA BIOS
231     Extension) call that does exactly that.<p>
232     
233     So I modified <code>syslinux</code> to do the VBE call and report
234     the result on kernel command line, e.g.:<br>
235     monitor=IVM1901241B3FEFA940A94AA94FA959<p>
236
237     This implies of course that this works only during installation.
238   </ul><br>
239
240   ISA-PnP Cards<br><ul>
241     This code is based on <code>pnpdump</code> from the
242     <a href="http://www.roestock.demon.co.uk/isapnptools/">
243     ISA Plug and Play Tools</a>.<p>
244
245     Reads the configuration of all installed ISA-PnP cards. Some cards might
246     not have been configured already. Those will have no valid resources (i/o ports,
247     irqs etc.) assigned. But the required resources are reported.<p>
248     
249     It would be not particularly tricky to implement the resource assignment
250     and activation of those cards (thus bypassing <code>isapnp</code>). But
251     I think that this exceeds the scope of this project.<p>
252     
253     ISA-PnP is a rather strange 'standard'. See the 'Technical Details &amp;
254     Documentation' section below.
255   </ul><br>
256
257   PCI Cards<br><ul>
258     This code is <em>not</em> based on <code>pciutils</code>. The code
259     basically reads /proc/bus/pci. The format of the data structures found there
260     is defined in /usr/include/linux/pci.h.
261   </ul>
262 </ul>
263
264 <h3><a name=nexts>Next Steps</a></h3>
265
266 <ul>
267   document everything implemented so far<br>
268   mouse (particular serial mouse) detection<br>
269   ISA/VLB graphics cards<br>
270   PCMCIA<br>
271   other ISA cards<br>
272   obscure stuff (scanning the BIOS ROM for info)<br>
273 </ul>
274
275 I have started to collect info on mouse detection (There exists actually a
276 PnP-COM devices spec). ISA graphics cards detection will probably be based
277 on <code>SuperProbe</code>.<p>
278
279 Detection of other ISA cards (e.g. SCSI, network) must probably be done by
280 trial and error module loading or BIOS ROM analyzing.
281
282 <h2><a name=detail>Technical Details &amp; Documentation</a></h2>
283
284 <h3><a name=idr>Internal Data Representation</a></h3>
285
286 As already mentioned, PCI uses a rather general approach describing devices.
287 Hence I use internally an extension of the PCI data structures. To minimize
288 work, the codes are compatible to PCI codes but some extensions are added.
289 This should not lead to future incompatibilities, as the extension is done
290 by choosing codes <em>outside</em> the range of PCI values (e.g. PCI classes
291 are 8-bit unsigned values and the class extensions start at 0x100).<p>
292
293 The data structure holding the device info looks currently like this:
294
295 <pre>
296 typedef struct struct_hw_t {
297   int idx;              // used to number the entries
298   unsigned bus, slot, func;
299   unsigned base_class, sub_class, prog_if;
300   unsigned dev, vend, sub_dev, sub_vend, rev;
301   unsigned compat_dev, compat_vend;
302
303   res_t res;            // device resources
304   unsigned ext_flags;   // device class specific info
305   void* ext;            // dto
306
307   // ... (heavily varying stuff)
308 } hw_t;
309 </pre>
310
311 Note that there is no field to hold the name of a device driver (module).
312 Instead, it exists a lookup function that can retrieve the module info
313 from the external database. An example for an entry with device driver
314 info is the <a href="metcalf_samp.html#elsa">ELSA QuickStep 1000</a> entry.<p>
315
316 The only non-intuitive change to PCI is that the <code>bus</code> member
317 does specify the <em>type</em> of the bus (PCI knows several <em>PCI</em>
318 busses, that are numbered (and connected via bridges)).<p>
319
320 Here is a sample hardware entry to illustrate this:
321
322 <pre>
323 10: PCI 04.2: 0c03 USB Controller
324   Vendor: 8086 "Intel"
325   Device: 7112 "82371AB/EB PIIX4 USB Controller"
326   Revision: 0x01
327   I/O Ports: 0xd400-??? (rw)
328 </pre>
329
330 The format of the first line is
331 <pre>
332 idx: bus slot.func: ((base_class*0x100) + sub_class) class_name
333 </pre>
334
335 Each vendor and device entry is preceded by the id and followed by
336 the name string. The name strings come mainly from the external data base
337 although ISA-PnP cards may provide some of their own.<p>
338
339 NOTE: subdevice ids are <em>not</em> required to be unique across different
340 devices. That is, different devices <em>may</em> use the same subdevice ids<p>
341
342 <a href="metcalf_samp.html">This is a complete hardware listing</a>.<p>
343
344 <a href="krieger_samp.html">And here is another</a>.
345
346 <h3><a name=dspecs>Database Specification</a></h3>
347
348 <code>libhd.a</code> uses an external database to read config info
349 and text strings (for fancy outputs) from. This database is actually
350 a textfile with a format derived from the PCI id list used by
351 <code>pciutils</code>.<p>
352
353 <a href="file:/home/alex/snwint/hd/hd/id_list">Here</a> is the full database
354 currently in use. <p>
355
356 <h4><a name=pciids>PCI id/vendor entries</a></h4>
357
358 Here an example:
359 <pre>
360 10DE    Nvidia Corp
361         0008    NV1 EDGE 3D Accelerator
362         0009    NV1 EDGE 3D Multimedia
363         0020    Riva 128 TNT GUI+3D Accelerator
364                 02001043        V3400 TNT
365                 05501092        Viper V550
366 </pre>
367
368 The format is:
369 <pre>
370 vendor_id  vendor_name
371 \tdevice_id  device_name
372 \t\t((subdevice_id << 16) + vendor_id) subdevice_name
373 </pre>
374
375 Tabs <em>must not</em> be replaced by spaces. The number of other spaces
376 (e.g. <em>after</em> the id values) is arbitrary.
377
378 <h4><a name=eisaids>EISA id/vendor entries</a></h4>
379
380 First an example:
381
382 <pre>
383 CTL     Creative Technology Ltd.
384         009e    Creative SB AWE64 Gold
385                 CTL0044 AWE64 Gold 16-bit Audio (SB16 compatible)
386                 CTL7002 Programmable Game Port
387 </pre>
388
389 <pre>
390 vendor_id  vendor_name
391 \tdevice_id  device_name
392 \t\tvendor_idsubdevice_id subdevice_name
393 </pre>
394
395 The format is exactly the same as a PCI entry, except that an EISA vendor
396 id consists of 3 uppercase letters.<p>
397
398 Again, none of the tabs may be replaced by spaces.
399
400 <h4><a name=subids>PCI/EISA Subdevice Entries</a></h4>
401
402 Instead of specifying a subdevice as an entry belonging to a device you
403 can specify a 'dedicated' subdevice entry as follows:
404
405 <pre>
406 S CTL   Creative Technology Ltd.
407         0023    AWE64 Gold Wavetable MIDI (AWE32 compatible)
408 </pre>
409
410 The format:
411 <pre>
412 S vendor_id  vendor_name
413 \tsubdevice_id  device_name
414 </pre>
415
416 The same format can be used for PCI devices.<p>
417
418 The main purpose for having 'dedicated' subdevice entries is that they are
419 not associated (unlike the 'normal' subdevices) with device ids. For
420 example, the 'Viper V550' entry in the example is only valid as a subdevice
421 of a Riva TNT device. The 'Viper 550' subdevice/vendor pair 05501092 will
422 <em>not</em> be recognized if it appears as a subdevice of a different
423 device.<p>
424
425 Although this behavior is pretty sensible, there are cases where this
426 might not be what you actually want. As an example look at the wavetable
427 subdevice above. It <em>may</em> be useful to recognize a wavetable device
428 even if its not on a AWE64 card (but on another SB compatible card).<p>
429
430 Anyway, the usefulness of this kind of entries <em>is</em> questionable.<p>
431
432 <h4><a name=busids>Bus Entries</a></h4>
433
434 Example:
435 <pre>
436 B 04  PCI
437 </pre>
438
439 The format:
440 <pre>
441 B bus_id  bus_name
442 </pre>
443
444 <h4><a name=classids>Class/Subclass Entries</a></h4>
445
446 Example:
447 <pre>
448 C 02  Network controller
449         0000  Ethernet controller
450         0001  Token ring network controller
451 </pre>
452
453 The format:
454 <pre>
455 C class_id  class_name
456 \tsubclass_id subclass_name
457 </pre>
458
459 Again, watch out for tabs.
460
461 <h4><a name=compatids>ISA-PnP Compatible Device Entries</a></h4>
462
463 The format follows (is identical to) the EISA entry format. What makes
464 these to compatible device entries is the special vendor 'PNP'.
465
466 Example:
467 <pre>
468 PNP     PnP
469         80d6.0200       NE2000 Compatible
470         b02f    Joystick/Game port
471 </pre>
472
473 The <code>.0200</code> is explained below.
474
475 <h4><a name=csids>Assigning a Class/Subclass to a Device</a></h4>
476
477 As mentioned in the ISA-PnP sections, ISA-PnP does not provide information
478 about the device class or subclass (to use the PCI terminology). Therefore
479 you can add this information in the database by adding a <code>.class</code>
480 to the device ids, as seen in the NE2000 example above 
481 (with <code>class = base_class*0x100 + sub_class</code>).<p>
482
483 This works currently only for EISA ids.
484
485 Note that this info is used to assign an unknown ISA-PnP device it's proper
486 device class <em>if</em> the card has a 'compatible to' entry <em>and</em> there has been a
487 device class associated with this compatible device. For example, the
488 AXE2201 card from the <a href="metcalf_samp.html#ether">listing</a> is recognized
489 as an Ethernet controller, because it has a 'compatible to PNP80d6' entry
490 <em>and</em> PNP80d6 is tagged as a (Ethernet-)network card as demonstrated
491 in the above example.
492
493 <h4><a name=modids>Assigning a Device Driver to a Device</a></h4>
494
495 You can associate a device driver to a device or subdevice in the following
496 way:
497
498 <pre>
499 ELS     ELSA International
500         0133.10300      [isdn] ELSA QuickStep 1000
501 </pre>
502
503 If a (sub)device name starts with <code>[driver_name]</code>, the text
504 between the brackets is assumed to be some driver info. The text is stored
505 internally and can be retrieved if needed.<p>
506
507 Note: this text is not analyzed or processed in any way.<p>
508
509 <a href="metcalf_samp.html#elsa">Here is an example</a>.
510
511 <h3><a name=hwcats>Hardware Categories</a></h3>
512
513 <h4><a name=mmem>Main Memory</a></h4>
514
515 I do a <code>stat</code> on <code>/proc/kcore</code> which is one
516 page more than the actual memory. The memory seems to be reduced by SCSI
517 device drivers. (And possibly others that need DMA?) The actual value
518 reported will be caculated on the assumption that the memory configuration
519 is done at least in 256k steps (e.g. 255.75MB are reported as 256MB).<p>
520
521 <a href="memory_samp.html">This is a sample main memory entry</a>.
522
523 <h4><a name=monitor>Monitor</a></h4>
524
525 The VBE call used is function 0x4f15 of int 0x10. The returned EDID record has a size of
526 128 bytes and only the relevant parts are reported on the kernel command
527 line. <a href="edid.html">This is a sample EDID record</a>. (Note the byte
528 order which is big endian!)<p>
529
530 Although the record <em>might</em> provide the monitor name explicitly it
531 seems not to be done in practice. So identification is done using the 4 byte
532 manufacturer ID code (which is actually an EISA ID code that is used
533 as the ISA-PnP ID code as well). The encoding of this ID is rather strange
534 and decoding results in something like <code>IVM1901</code> where
535 <code>IVM</code> identifies the manufacturer and <code>1901</code>
536 is an product ID.<p>
537
538 This manufacturer ID is given in the first 7 bytes of the
539 <code>monitor=</code> parameter (see above for an example).<p>
540
541 I found only one source of manufacturer ID codes besides the W9x *.inf files
542 and that is
543 <a href="http://www.cs.cmu.edu/afs/cs.cmu.edu/user/ralf/pub/WWW/files.html">
544 Ralf Brown's Interrupt List</a>. But I haven't looked for a more
545 comprehensive source so far.
546
547 Finally, note that it is not necessary to rely completely on the monitor ID
548 as the EDID record itself contains timing and geometry information.<p>
549
550 <a href="monitor_samp.html">This is a sample monitor entry</a>.
551
552 <h4><a name=pnpcards>ISA-PnP Cards</a></h4>
553
554 One of the tricky parts of ISA-PnP is that the communication port (well,
555 <em>one</em> of them) has no fixed location but may be within the range of
556 0x203-0x3ff. That is because (according to the specs) they could not
557 name a single(!) unused fixed port address!?<p>
558
559 The application using <code>libhd.a</code> should therefore provide some
560 means of <em>storing</em> this value somewhere. <code>pnpdump</code>
561 puts it into <code>/etc/isapnp.conf</code> where <code>isapnp</code>
562 can read it from. <code>libhd.a</code> uses
563 <code>/etc/isapnp.conf</code> as well (if it exists) to find out the
564 value. If this file is missing, the standard method for finding an appropriate
565 port is carried out.<p>
566
567 And this is the very reason why the ISA-PnP interface itself gets listed as a
568 hardware device (see the examples below): it occupies 3 i/o ports: two fixed
569 write only ports and one relocatable read only port.<p>
570
571 An ISA-PnP card may have more than one logical device. The practical reason
572 for that may be seen in the last example below (an AWE64 sound card). Links
573 are provided to relate these logical devices to the ISA-PnP card (marked as
574 'belongs to device:').<p>
575
576 ISA-PnP provides also a 'compatibility' tag (see the examples). If you are wondering
577 what <code>PNP80D6</code> or <code>PNPB02F</code> are, look at
578 <a href="file:/home/alex/snwint/hd/PnP/devids.txt">devids.txt</a>.<p>
579
580 Note: not all card resources <em>must</em> be listed in the ISA-PnP data
581 (AWE64 being an (infamous) example). This is only required for all cards
582 that have to be configured by the BIOS because they participate in the BOOT
583 process.<p>
584
585 The BIOS may or may not choose to configure individual cards. So it is possible
586 for a card to have no valid resources assigned. Such cards will of course
587 not work until they have been properly initialized.<p>
588
589 A fairly complete documentation of Plug and Play is available from
590 <a href="http://www.microsoft.com/hwdev/respec/pnpspecs.htm">Microsoft</a>.
591 Or, locally and in Postscript form, from
592 <a href="file:/home/alex/snwint/hd/PnP/">here</a>.<p>
593
594 <a href="isapnp_samp.html">Here are some sample ISA-PnP entries</a>.<br>
595
596 <h4><a name=pcicards>PCI Cards</a></h4>
597
598 I just read all information out of <code>/proc/bus/pci</code>.<p>
599
600 It is apparently somewhat tricky to get the <em>range</em> of i/o and
601 memory ranges (reading the base addresses is trivial).<p>
602
603 PCI configuration data reflect a pretty general approach to describing
604 devices. A card occupies a <code>slot</code> on a <code>bus</code>.
605 On every card there may be several subdevices (PCI-ish
606 <code>functions</code>).<p>
607
608 Every <code>function</code> has its own configuration space. It gets
609 assigned a <code>class</code>, a <code>subclass</code> and an
610 <code>interface type</code> (e.g.: Storage Device -> IDE Controller ->
611 Generic IDE).<p>
612
613 To identify the devices, each <code>function</code> has a <code>vendor
614 id</code>, a <code>device id</code>, a <code>subvendor id</code>,
615 <code>a subdevice id</code> and a <code>revision number</code>. (See
616 see example below.))<p>
617
618 To associate these numbers to human-readable texts a extern database is
619 necessary. A large collection of PCI ids is available
620 <a href="http://home.hyperlink.net.au/~chart/download/vendors.txt"> here </a>.
621 The database format <code>libhd.a</code> uses, is closely modeled after
622 this one.<p>
623
624 <a href="pci_samp.html">Here are some sample PCI entries</a>.<br>
625
626 <h2><a name=ref>References &amp; Sources</a></h2>
627
628 This section is missing. For the curious, a text file with some links is
629 <a href="file:/home/alex/snwint/hd/info">here</a>.
630 </body>
631 </html>
632