source: mainline/uspace/app/pci/pci.c@ 7acd787

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 7acd787 was 7acd787, checked in by Jiri Svoboda <jiri@…>, 6 years ago

Utility for listing PCI devices

Currently all information presented can also be gathered from devctl -v,
although 'pci' prints it in a nice compact format. Ability to print
more information, including information not available from devctl,
can be added later.

  • Property mode set to 100644
File size: 5.8 KB
Line 
1/*
2 * Copyright (c) 2019 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup pci
30 * @{
31 */
32
33/**
34 * @file
35 * @brief Tool for listing PCI devices.
36 */
37
38#include <devman.h>
39#include <errno.h>
40#include <io/table.h>
41#include <loc.h>
42#include <pci.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <str.h>
46
47#define NAME "mkext4"
48
49#define MAX_NAME_LENGTH 1024
50
51static void syntax_print(void);
52static errno_t pci_list(void);
53static errno_t pci_list_bridge(const char *);
54static errno_t pci_list_bridge_id(service_id_t);
55
56int main(int argc, char **argv)
57{
58 errno_t rc;
59 const char *bridge = NULL;
60
61 --argc;
62 ++argv;
63
64 while (argc > 0 && argv[0][0] == '-') {
65 if (str_cmp(argv[0], "--bridge") == 0) {
66 --argc;
67 ++argv;
68 if (argc < 1) {
69 printf("Option argument missing.\n");
70 return 1;
71 }
72
73 bridge = argv[0];
74 --argc;
75 ++argv;
76 } else {
77 syntax_print();
78 return 1;
79 }
80 }
81
82 if (argc != 0) {
83 syntax_print();
84 return 1;
85 }
86
87 if (bridge != NULL)
88 rc = pci_list_bridge(bridge);
89 else
90 rc = pci_list();
91
92 if (rc != EOK)
93 return 1;
94
95 return 0;
96}
97
98static void syntax_print(void)
99{
100 printf("syntax: pci [<options>]\n");
101 printf("options:\n"
102 "\t--bridge <svc-name> Only devices under host bridge <svc-name>\n");
103}
104
105/** List PCI devices. */
106static errno_t pci_list(void)
107{
108 errno_t rc;
109 category_id_t pci_cat_id;
110 service_id_t *svc_ids = NULL;
111 size_t svc_cnt;
112 size_t i;
113
114 rc = loc_category_get_id("pci", &pci_cat_id, 0);
115 if (rc != EOK) {
116 printf("Error getting 'pci' category ID.\n");
117 goto error;
118 }
119
120 rc = loc_category_get_svcs(pci_cat_id, &svc_ids, &svc_cnt);
121 if (rc != EOK) {
122 printf("Error getting list of PCI services.\n");
123 goto error;
124 }
125
126 for (i = 0; i < svc_cnt; i++) {
127 if (i > 0)
128 putchar('\n');
129
130 rc = pci_list_bridge_id(svc_ids[i]);
131 if (rc != EOK)
132 goto error;
133 }
134
135 free(svc_ids);
136 return EOK;
137error:
138 if (svc_ids != NULL)
139 free(svc_ids);
140 return rc;
141}
142
143/** List PCI devices under a host bridge specified by name.
144 *
145 * @param svc_name PCI service name
146 * @return EOK on success or an error code
147 */
148static errno_t pci_list_bridge(const char *svc_name)
149{
150 errno_t rc;
151 service_id_t svc_id;
152
153 rc = loc_service_get_id(svc_name, &svc_id, 0);
154 if (rc != EOK) {
155 printf("Error looking up host bridge '%s'.\n", svc_name);
156 return rc;
157 }
158
159 return pci_list_bridge_id(svc_id);
160}
161
162/** List PCI devices under a host bridge specified by ID.
163 *
164 * @param svc_id PCI service ID
165 * @return EOK on success or an error code
166 */
167static errno_t pci_list_bridge_id(service_id_t svc_id)
168{
169 errno_t rc;
170 devman_handle_t *dev_ids = NULL;
171 size_t dev_cnt;
172 pci_dev_info_t dev_info;
173 size_t i;
174 pci_t *pci = NULL;
175 char *svc_name = NULL;
176 char *drv_name = NULL;
177 table_t *table = NULL;
178
179 drv_name = malloc(MAX_NAME_LENGTH);
180 if (drv_name == NULL) {
181 printf("Out of memory.\n");
182 rc = ENOMEM;
183 goto error;
184 }
185
186 rc = table_create(&table);
187 if (rc != EOK) {
188 printf("Out of memory.\n");
189 rc = ENOMEM;
190 goto error;
191 }
192
193 table_header_row(table);
194 table_printf(table, "Address\t" "Type\t" "Driver\n");
195
196 rc = loc_service_get_name(svc_id, &svc_name);
197 if (rc != EOK) {
198 printf("Error getting service name.\n");
199 goto error;
200 }
201
202 rc = pci_open(svc_id, &pci);
203 if (rc != EOK) {
204 printf("Error opening PCI service '%s'.\n", svc_name);
205 goto error;
206 }
207
208 rc = pci_get_devices(pci, &dev_ids, &dev_cnt);
209 if (rc != EOK) {
210 printf("Error getting PCI device list.\n");
211 goto error;
212 }
213
214 for (i = 0; i < dev_cnt; i++) {
215 rc = pci_dev_get_info(pci, dev_ids[i], &dev_info);
216 if (rc != EOK) {
217 printf("Error getting PCI device info.\n");
218 goto error;
219 }
220
221 rc = devman_fun_get_driver_name(dev_info.dev_handle,
222 drv_name, MAX_NAME_LENGTH);
223 if (rc != EOK && rc != EINVAL) {
224 printf("Error getting driver name.\n");
225 goto error;
226 }
227
228 if (rc == EINVAL)
229 drv_name[0] = '\0';
230
231 table_printf(table, "%02x.%02x.%x\t" "%04x:%04x\t"
232 "%s\n", dev_info.bus_num, dev_info.dev_num,
233 dev_info.fn_num, dev_info.vendor_id,
234 dev_info.device_id, drv_name);
235 }
236
237 printf("Device listing for host bridge %s:\n\n", svc_name);
238 rc = table_print_out(table, stdout);
239 if (rc != EOK) {
240 printf("Error printing table.\n");
241 goto error;
242 }
243
244 table_destroy(table);
245 table = NULL;
246 free(dev_ids);
247 dev_ids = NULL;
248 pci_close(pci);
249 pci = NULL;
250 free(svc_name);
251 svc_name = NULL;
252
253 free(drv_name);
254 return EOK;
255error:
256 if (drv_name != NULL)
257 free(drv_name);
258 if (table != NULL)
259 table_destroy(table);
260 if (pci != NULL)
261 pci_close(pci);
262 if (svc_name != NULL)
263 free(svc_name);
264 if (dev_ids != NULL)
265 free(dev_ids);
266 return rc;
267}
268
269/**
270 * @}
271 */
Note: See TracBrowser for help on using the repository browser.