2 Copyright (C) 2004-2010, The AROS Development Team.
6 #include <exec/memory.h>
16 #include <aros/debug.h>
18 // it's supposed to become a shared library one day ...
20 // current implementation:
21 // on pciids_Open(), the file is read in memory, then
22 // an index is built (in computeVendorIndexes()), as an array
23 // of couples (vendor_id, offset)
24 // where offset is the offset where the vendor stuff begins
25 // in the memory file. This array is ascending sorted by vendor_id,
26 // so a binary search can be done to retrieve the vendor offset
27 // given its id. This search is done in getVendorIndex().
28 // All the stringification functions first call this search func,
29 // then parse the memory:
30 // 1234 VendorName (so: s[0] = hex digit, s[4] == ' ', s[6+] == name)
31 // <tab>1234 DeviceName (same with a tab on linestart)
32 // todo: subvendor/subdevice parsing
33 // todo: proper memory reallocation, currently the index is fixed
36 static STRPTR mem
= NULL
;
37 static ULONG memsize
= 0;
45 static struct vendor_cell
*vendor_index
= NULL
;
46 static ULONG vi_allocated
= 0;
47 static UWORD vi_number
= 0;
49 static LONG
skip_line(const char *buffer
, LONG size
, LONG pos
)
54 if (*buffer
++ == '\n')
64 static LONG
copy_until_eol(STRPTR m
, ULONG msize
, LONG pos
, STRPTR buf
,
70 while ((pos
< msize
) && (j
< bufsize
- 1) && (*m
!= '\n'))
78 static BOOL
computeVendorIndexes(const char *buffer
, LONG size
)
83 vendor_index
= (struct vendor_cell
*)AllocVec(vi_allocated
* sizeof(struct vendor_cell
), MEMF_ANY
);
84 if (NULL
== vendor_index
)
92 // don't use isxdigit, beware of uppercase letter
93 if ((isdigit(buffer
[i
]) || (buffer
[i
] >= 'a' && buffer
[i
] <= 'f'))
94 && (i
+ 4 < size
) && (buffer
[i
+ 4] == ' '))
96 if (sscanf(buffer
+ i
, "%hx", &(vendor_index
[j
].vendorID
)) != 1)
98 vendor_index
[j
].offset
= i
;
99 //bug("%ld: %x => %ld\n", j, vendor_index[j].vendorID, vendor_index[j].offset);
101 if (j
>= vi_allocated
)
103 bug("[pcitool] pciids.c:computeVendorIndexes: vendor_index overflow\n");
104 FreeVec(vendor_index
);
109 i
= skip_line(buffer
, size
, i
);
115 static LONG
getVendorIndex(UWORD vendorID
)
118 LONG upper
= vi_number
;
120 if (!mem
|| !vendor_index
)
123 while (upper
!= lower
)
127 vid
= vendor_index
[(upper
+ lower
) / 2].vendorID
;
129 return vendor_index
[(upper
+ lower
) / 2].offset
;
131 lower
= (upper
+ lower
) / 2 + 1;
133 upper
= (upper
+ lower
) / 2;
138 static LONG
getDeviceIndex(LONG vendorIndex
, UWORD deviceID
)
140 LONG i
= vendorIndex
;
145 i
= skip_line(mem
, memsize
, i
); // skip vendor
146 while ((i
< memsize
) && ((mem
[i
] == '\t') || (mem
[i
] == '#')))
152 if ((i
+ 6 < memsize
) && (mem
[i
+ 5] == ' ')
153 && (sscanf(mem
+ i
+ 1, "%hx", &did
) == 1) && (did
== deviceID
))
158 i
= skip_line(mem
, memsize
, i
);
163 static LONG
getSubDeviceIndex(LONG deviceIndex
, UWORD subVendorID
, UWORD subDeviceID
)
165 LONG i
= deviceIndex
;
170 i
= skip_line(mem
, memsize
, i
);
171 while ((i
< memsize
) && ((mem
[i
] == '\t') || (mem
[i
] == '#')))
173 UWORD subvid
, subdid
;
175 if ((mem
[i
] != '#') && (i
+ 1 < memsize
) && (mem
[i
+1] == '\t'))
177 if ((i
+ 11 < memsize
)
178 && (mem
[i
+ 6] == ' ')
179 && (sscanf(mem
+ i
, "%hx", &subvid
) == 1)
180 && (subvid
== subVendorID
)
181 && (mem
[i
+ 11] == ' ')
182 && (sscanf(mem
+ i
+ 7, "%hx", &subdid
) == 1)
183 && (subdid
== subDeviceID
))
188 i
= skip_line(mem
, memsize
, i
);
193 void pciids_Open(void)
198 fh
= Open("DEVS:pci.ids", MODE_OLDFILE
);
202 Seek(fh
, 0, OFFSET_END
);
203 size
= Seek(fh
, 0, OFFSET_CURRENT
);
207 memsize
= (ULONG
)size
;
208 Seek(fh
, 0, OFFSET_BEGINNING
);
210 mem
= (STRPTR
)AllocVec(memsize
, MEMF_ANY
);
214 if (Read(fh
, mem
, memsize
) != size
)
217 if (!computeVendorIndexes(mem
, memsize
))
234 void pciids_Close(void)
238 FreeVec(vendor_index
);
249 STRPTR
pciids_GetVendorName(UWORD vendorID
, STRPTR buf
, ULONG bufsize
)
251 LONG i
= getVendorIndex(vendorID
);
257 copy_until_eol(mem
, memsize
, i
+ 6, buf
, bufsize
);
262 STRPTR
pciids_GetDeviceName(UWORD vendorID
, UWORD deviceID
, STRPTR buf
,
265 LONG i
= getVendorIndex(vendorID
);
268 if (i
< 0) // unknown vendor
271 i
= getDeviceIndex(i
, deviceID
);
272 if (i
< 0) // unknown device
275 copy_until_eol(mem
, memsize
, i
+ 7, buf
, bufsize
);
279 STRPTR
pciids_GetSubDeviceName(UWORD vendorID
, UWORD deviceID
, UWORD subVendorID
,
280 UWORD subDeviceID
, STRPTR buf
, ULONG bufsize
)
288 if ((0 == subVendorID
) && (0 == subDeviceID
))
291 i
= getVendorIndex(vendorID
);
292 if (i
< 0) // unknown vendor
295 i
= getDeviceIndex(i
, deviceID
);
296 if (i
< 0) // unknown device
299 j
= getVendorIndex(subVendorID
);
300 if (j
< 0) // unknown subvendor
303 copied
= copy_until_eol(mem
, memsize
, j
+ 6, buf
, bufsize
);
305 if (copied
+ 4 < bufsize
)
307 strcpy(buf
+ copied
, " : ");
309 i
= getSubDeviceIndex(i
, subVendorID
, subDeviceID
);
310 if (i
< 0) // unknown subdevice
312 if (bufsize
- copied
- 3 > 6)
313 sprintf(buf
+ copied
+ 3, "0x%04x", subDeviceID
);
317 copy_until_eol(mem
, memsize
, i
+ 13, buf
+ copied
+ 3,
318 bufsize
- copied
- 3);