1 #include <exec/types.h>
10 #include <aros/debug.h>
12 // it's supposed to become a shared library one day ...
14 // current implementation:
15 // on pciids_Open(), the file is read in memory, then
16 // an index is built (in computeVendorIndexes()), as an array
17 // of couples (vendor_id, offset)
18 // where offset is the offset where the vendor stuff begins
19 // in the memory file. This array is ascending sorted by vendor_id,
20 // so a binary search can be done to retrieve the vendor offset
21 // given its id. This search is done in getVendorIndex().
22 // All the stringification functions first call this search func,
23 // then parse the memory:
24 // 1234 VendorName (so: s[0] = hex digit, s[4] == ' ', s[6+] == name)
25 // <tab>1234 DeviceName (same with a tab on linestart)
26 // todo: subvendor/subdevice parsing
27 // todo: proper memory reallocation, currently the index is fixed
28 // to 2000 vendors (around 1700 exist on 2004-02-08)
30 static STRPTR mem
= NULL
;
31 static ULONG memsize
= 0;
39 static struct vendor_cell
*vendor_index
= NULL
;
40 static ULONG vi_allocated
= 0;
41 static UWORD vi_number
= 0;
43 static LONG
skip_line(const char *buffer
, LONG size
, LONG pos
)
48 if (*buffer
++ == '\n')
58 static LONG
copy_until_eol(STRPTR m
, ULONG msize
, LONG pos
, STRPTR buf
,
64 while ((pos
< msize
) && (j
< bufsize
- 1) && (*m
!= '\n'))
72 static BOOL
computeVendorIndexes(const char *buffer
, LONG size
)
77 vendor_index
= AllocVec(vi_allocated
* sizeof(struct vendor_cell
), MEMF_ANY
);
78 if (NULL
== vendor_index
)
86 // dont use isxdigit, beware of uppercase letter
87 if ((isdigit(buffer
[i
]) || (buffer
[i
] >= 'a' && buffer
[i
] <= 'f'))
88 && (i
+ 4 < size
) && (buffer
[i
+ 4] == ' '))
90 if (sscanf(buffer
+ i
, "%hx", &(vendor_index
[j
].vendorID
)) != 1)
92 vendor_index
[j
].offset
= i
;
93 //bug("%ld: %x => %ld\n", j, vendor_index[j].vendorID, vendor_index[j].offset);
97 bug("[pcitool] pciids.c:computeVendorIndexes: vendor_index overflow\n");
98 FreeVec(vendor_index
);
103 i
= skip_line(buffer
, size
, i
);
109 static LONG
getVendorIndex(UWORD vendorID
)
112 LONG upper
= vi_number
;
114 if (!mem
|| !vendor_index
)
117 while (upper
!= lower
)
121 vid
= vendor_index
[(upper
+ lower
) / 2].vendorID
;
123 return vendor_index
[(upper
+ lower
) / 2].offset
;
125 lower
= (upper
+ lower
) / 2 + 1;
127 upper
= (upper
+ lower
) / 2;
132 static LONG
getDeviceIndex(LONG vendorIndex
, UWORD deviceID
)
134 LONG i
= vendorIndex
;
139 i
= skip_line(mem
, memsize
, i
); // skip vendor
140 while ((i
< memsize
) && ((mem
[i
] == '\t') || (mem
[i
] == '#')))
146 if ((i
+ 6 < memsize
) && (mem
[i
+ 5] == ' ')
147 && (sscanf(mem
+ i
+ 1, "%hx", &did
) == 1) && (did
== deviceID
))
152 i
= skip_line(mem
, memsize
, i
);
157 static LONG
getSubDeviceIndex(LONG deviceIndex
, UWORD subVendorID
, UWORD subDeviceID
)
159 LONG i
= deviceIndex
;
164 i
= skip_line(mem
, memsize
, i
);
165 while ((i
< memsize
) && ((mem
[i
] == '\t') || (mem
[i
] == '#')))
167 UWORD subvid
, subdid
;
169 if ((mem
[i
] != '#') && (i
+ 1 < memsize
) && (mem
[i
+1] == '\t'))
171 if ((i
+ 11 < memsize
)
172 && (mem
[i
+ 6] == ' ')
173 && (sscanf(mem
+ i
, "%hx", &subvid
) == 1)
174 && (subvid
== subVendorID
)
175 && (mem
[i
+ 11] == ' ')
176 && (sscanf(mem
+ i
+ 7, "%hx", &subdid
) == 1)
177 && (subdid
== subDeviceID
))
182 i
= skip_line(mem
, memsize
, i
);
187 void pciids_Open(void)
192 fh
= Open("DEVS:pci.ids", MODE_OLDFILE
);
196 Seek(fh
, 0, OFFSET_END
);
197 size
= Seek(fh
, 0, OFFSET_CURRENT
);
201 memsize
= (ULONG
)size
;
202 Seek(fh
, 0, OFFSET_BEGINNING
);
204 mem
= AllocVec(memsize
, MEMF_ANY
);
208 if (Read(fh
, mem
, memsize
) != size
)
211 if (!computeVendorIndexes(mem
, memsize
))
228 void pciids_Close(void)
232 FreeVec(vendor_index
);
243 STRPTR
pciids_GetVendorName(UWORD vendorID
, STRPTR buf
, ULONG bufsize
)
245 LONG i
= getVendorIndex(vendorID
);
251 copy_until_eol(mem
, memsize
, i
+ 6, buf
, bufsize
);
256 STRPTR
pciids_GetDeviceName(UWORD vendorID
, UWORD deviceID
, STRPTR buf
,
259 LONG i
= getVendorIndex(vendorID
);
262 if (i
< 0) // unknown vendor
265 i
= getDeviceIndex(i
, deviceID
);
266 if (i
< 0) // unknown device
269 copy_until_eol(mem
, memsize
, i
+ 7, buf
, bufsize
);
273 STRPTR
pciids_GetSubDeviceName(UWORD vendorID
, UWORD deviceID
, UWORD subVendorID
,
274 UWORD subDeviceID
, STRPTR buf
, ULONG bufsize
)
282 if ((0 == subVendorID
) && (0 == subDeviceID
))
285 i
= getVendorIndex(vendorID
);
286 if (i
< 0) // unknown vendor
289 i
= getDeviceIndex(i
, deviceID
);
290 if (i
< 0) // unknown device
293 j
= getVendorIndex(subVendorID
);
294 if (j
< 0) // unknown subvendor
297 copied
= copy_until_eol(mem
, memsize
, j
+ 6, buf
, bufsize
);
299 if (copied
+ 4 < bufsize
)
301 strcpy(buf
+ copied
, " : ");
303 i
= getSubDeviceIndex(i
, subVendorID
, subDeviceID
);
304 if (i
< 0) // unknown subdevice
306 if (bufsize
- copied
- 3 > 6)
307 sprintf(buf
+ copied
+ 3, "0x%04x", subDeviceID
);
311 copy_until_eol(mem
, memsize
, i
+ 13, buf
+ copied
+ 3,
312 bufsize
- copied
- 3);