treewide: Move device_tree to commonlib
[coreboot2.git] / payloads / coreinfo / pci_module.c
blobff01770868d58ea4d829d70e903f1cd4f0f9109a
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <arch/io.h>
4 #include <pci.h>
5 #include <libpayload.h>
6 #include "coreinfo.h"
8 #if CONFIG(MODULE_PCI)
10 struct pci_devices {
11 pcidev_t device;
12 unsigned int id;
15 #define MAX_PCI_DEVICES 64
16 static struct pci_devices devices[MAX_PCI_DEVICES];
17 static int devices_index;
19 /* Number of entries to show in the list */
20 #define MENU_VISIBLE 16
22 static int menu_selected = 0;
23 static int menu_first = 0;
25 static void swap(struct pci_devices *a, struct pci_devices *b)
27 struct pci_devices tmp;
29 tmp.device = a->device;
30 tmp.id = a->id;
32 a->device = b->device;
33 a->id = b->id;
35 b->device = tmp.device;
36 b->id = tmp.id;
39 static int partition(struct pci_devices *list, int len)
41 pcidev_t val = list[len / 2].device;
42 int index = 0;
43 int i;
45 swap(&list[len / 2], &list[len - 1]);
47 for (i = 0; i < len - 1; i++) {
48 if (list[i].device < val) {
49 swap(&list[i], &list[index]);
50 index++;
54 swap(&list[index], &list[len - 1]);
56 return index;
59 static void quicksort(struct pci_devices *list, int len)
61 int index;
63 if (len <= 1)
64 return;
66 index = partition(list, len);
68 quicksort(list, index);
69 quicksort(&(list[index]), len - index);
72 static void show_config_space(WINDOW *win, int row, int col, int index)
74 unsigned char cspace[256];
75 pcidev_t dev;
76 int i, x, y;
78 dev = devices[index].device;
80 for (i = 0; i < 256; i ++)
81 cspace[i] = pci_read_config8(dev, i);
83 for (y = 0; y < 16; y++) {
84 for (x = 0; x < 16; x++)
85 mvwprintw(win, row + y, col + (x * 3), "%2.2X ",
86 cspace[(y * 16) + x]);
90 static int pci_module_redraw(WINDOW *win)
92 unsigned int bus, slot, func;
93 int i;
95 print_module_title(win, "PCI Device List");
97 for (i = 0; i < MENU_VISIBLE; i++) {
98 int item = menu_first + i;
100 /* Draw a blank space. */
101 if (item >= devices_index) {
102 wattrset(win, COLOR_PAIR(2));
103 mvwprintw(win, 2 + i, 1, " ");
104 continue;
107 bus = PCI_BUS(devices[item].device);
108 slot = PCI_SLOT(devices[item].device);
109 func = PCI_FUNC(devices[item].device);
111 if (item == menu_selected)
112 wattrset(win, COLOR_PAIR(3) | A_BOLD);
113 else
114 wattrset(win, COLOR_PAIR(2));
116 mvwprintw(win, 2 + i, 1, "%X:%2.2X.%2.2X %04X:%04X ",
117 bus, slot, func,
118 devices[item].id & 0xffff,
119 (devices[item].id >> 16) & 0xffff);
121 wattrset(win, COLOR_PAIR(2));
123 if (i == 0) {
124 if (item != 0)
125 mvwaddch(win, 2 + i, 19, ACS_UARROW);
127 if (i == MENU_VISIBLE - 1) {
128 if ((item + 1) < devices_index)
129 mvwaddch(win, 2 + i, 19, ACS_DARROW);
133 wattrset(win, COLOR_PAIR(2));
135 for (i = 0; i < 16; i++)
136 mvwprintw(win, 2, 26 + (i * 3), "%2.2X ", i);
138 wmove(win, 3, 25);
140 for (i = 0; i < 48; i++)
141 waddch(win, (i == 0) ? ACS_ULCORNER : ACS_HLINE);
143 for (i = 0; i < 16; i++) {
144 mvwprintw(win, 4 + i, 23, "%2.2X", i * 16);
145 wmove(win, 4 + i, 25);
146 waddch(win, ACS_VLINE);
149 show_config_space(win, 4, 26, menu_selected);
151 return 0;
154 static void ci_pci_scan_bus(int bus)
156 int slot, func;
157 unsigned int val;
158 unsigned char hdr;
160 for (slot = 0; slot < 0x20; slot++) {
161 for (func = 0; func < 8; func++) {
162 pcidev_t dev = PCI_DEV(bus, slot, func);
164 val = pci_read_config32(dev, REG_VENDOR_ID);
166 /* Nobody home. */
167 if (val == 0xffffffff || val == 0x00000000 ||
168 val == 0x0000ffff || val == 0xffff0000) {
170 /* If function 0 is not present, no need
171 * to test other functions. */
172 if (func == 0)
173 func = 8;
174 continue;
177 /* FIXME: Remove this arbitrary limitation. */
178 if (devices_index >= MAX_PCI_DEVICES)
179 return;
181 devices[devices_index].device =
182 PCI_DEV(bus, slot, func);
184 devices[devices_index++].id = val;
186 /* If this is a bridge, then follow it. */
187 hdr = pci_read_config8(dev, REG_HEADER_TYPE);
189 if ((func == 0) && !(hdr & HEADER_TYPE_MULTIFUNCTION))
190 func = 8;
192 hdr &= ~HEADER_TYPE_MULTIFUNCTION;
193 if (hdr == HEADER_TYPE_BRIDGE ||
194 hdr == HEADER_TYPE_CARDBUS) {
195 unsigned int busses;
197 busses = pci_read_config32(dev, REG_PRIMARY_BUS);
199 ci_pci_scan_bus((busses >> 8) & 0xff);
205 quicksort(devices, devices_index);
208 static int pci_module_handle(int key)
210 int ret = 0;
212 switch (key) {
213 case KEY_DOWN:
214 if (menu_selected + 1 < devices_index) {
215 menu_selected++;
216 ret = 1;
218 break;
219 case KEY_UP:
220 if (menu_selected > 0) {
221 menu_selected--;
222 ret = 1;
224 break;
227 if (!ret)
228 return ret;
230 if (menu_selected < menu_first)
231 menu_first = menu_selected;
232 else if (menu_selected >= menu_first + MENU_VISIBLE) {
233 menu_first = menu_selected - (MENU_VISIBLE - 1);
234 if (menu_first < 0)
235 menu_first = 0;
238 return ret;
241 static int pci_module_init(void)
243 ci_pci_scan_bus(0);
244 return 0;
247 struct coreinfo_module pci_module = {
248 .name = "PCI",
249 .init = pci_module_init,
250 .redraw = pci_module_redraw,
251 .handle = pci_module_handle,
254 #else
256 struct coreinfo_module pci_module = {
259 #endif