First version
[3rdparty/ote_partner/tlk.git] / app / pcitests / pci_tests.c
1 /*
2  * Copyright (c) 2009 Corey Tabaka
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 #include <app.h>
24 #include <debug.h>
25 #include <stdint.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <compiler.h>
30 #include <platform.h>
31 #include <dev/pci.h>
32
33 #if defined(WITH_LIB_CONSOLE)
34 #include <lib/console.h>
35
36 /*
37  * enumerates pci devices
38  */
39 static void pci_list(void)
40 {
41         pci_location_t state;
42         uint16_t device_id, vendor_id;
43         uint8_t header_type;
44         int busses = 0, devices = 0, lines = 0, devfn, ret;
45         char c;
46         
47         printf("Scanning...\n");
48         
49         for (state.bus = 0; state.bus <= pci_get_last_bus(); state.bus++) {
50                 busses++;
51                 
52                 for (devfn = 0; devfn < 256; devfn++) {
53                         state.dev_fn = devfn;
54                         
55                         ret = pci_read_config_half(&state, PCI_CONFIG_VENDOR_ID, &vendor_id);
56                         if (ret != _PCI_SUCCESSFUL) goto error;
57                         
58                         ret = pci_read_config_half(&state, PCI_CONFIG_DEVICE_ID, &device_id);
59                         if (ret != _PCI_SUCCESSFUL) goto error;
60                         
61                         ret = pci_read_config_byte(&state, PCI_CONFIG_HEADER_TYPE, &header_type);
62                         if (ret != _PCI_SUCCESSFUL) goto error;
63                         
64                         if (vendor_id != 0xffff) {
65                                 printf("%02x:%02x vendor_id=%04x device_id=%04x, header_type=%02x\n", state.bus, state.dev_fn,
66                                                 vendor_id, device_id, header_type);
67                                 devices++;
68                                 lines++;
69                         }
70                         
71                         if (~header_type & PCI_HEADER_TYPE_MULTI_FN) {
72                                 // this is not a multi-function device, so advance to the next device
73                                 devfn |= 7;
74                         }
75                         
76                         if (lines == 23) {
77                                 printf("... press any key to continue, q to quit ...");
78                                 while(getc(&c) < 0);
79                                 printf("\n");
80                                 lines = 0;
81                                 
82                                 if (c == 'q' || c == 'Q') goto quit;
83                         }
84                 }
85         }
86
87         printf("... done. Scanned %d busses, %d device/functions\n", busses, devices);
88 quit:
89         return;
90         
91 error:
92         printf("Error while reading PCI config space: %02x\n", ret);
93 }
94
95 /*
96  * a somewhat fugly pci config space examine/modify command. this should probably
97  * be broken up a bit.
98  */
99 static int pci_config(int argc, const cmd_args *argv)
100 {
101         pci_location_t loc;
102         pci_config_t config;
103         uint32_t offset;
104         unsigned int i;
105         int ret;
106         
107         if (argc < 5) {
108                 return -1;
109         }
110         
111         if (!strcmp(argv[2].str, "dump")) {
112                 loc.bus = atoui(argv[3].str);
113                 loc.dev_fn = atoui(argv[4].str);
114                 
115                 for (i=0; i < sizeof(pci_config_t); i++) {
116                         ret = pci_read_config_byte(&loc, i, (uint8_t *) &config + i);
117                         if (ret != _PCI_SUCCESSFUL) goto error;
118                 }
119                 
120                 printf("Device at %02x:%02x vendor id=%04x device id=%04x\n", loc.bus,
121                         loc.dev_fn, config.vendor_id, config.device_id);
122                 printf("command=%04x status=%04x pi=%02x sub cls=%02x base cls=%02x\n",
123                         config.command, config.status, config.program_interface,
124                         config.sub_class, config.base_class);
125                 
126                 for (i=0; i < 6; i+=2) {
127                         printf("bar%d=%08x  bar%d=%08x\n", i, config.base_addresses[i],
128                                 i+1, config.base_addresses[i+1]);
129                 }
130         } else if (!strcmp(argv[2].str, "rb") || !strcmp(argv[2].str, "rh") || !strcmp(argv[2].str, "rw")) {
131                 if (argc != 6) {
132                         return -1;
133                 }
134                 
135                 loc.bus = atoui(argv[3].str);
136                 loc.dev_fn = atoui(argv[4].str);
137                 offset = atoui(argv[5].str);
138                 
139                 switch (argv[2].str[1]) {
140                         case 'b': {
141                                 uint8_t value;
142                                 ret = pci_read_config_byte(&loc, offset, &value);
143                                 if (ret != _PCI_SUCCESSFUL) goto error;
144                                 
145                                 printf("byte at device %02x:%02x config offset %04x: %02x\n", loc.bus, loc.dev_fn, offset, value);
146                         }
147                         break;
148                         
149                         case 'h': {
150                                 uint16_t value;
151                                 ret = pci_read_config_half(&loc, offset, &value);
152                                 if (ret != _PCI_SUCCESSFUL) goto error;
153                                 
154                                 printf("half at device %02x:%02x config offset %04x: %04x\n", loc.bus, loc.dev_fn, offset, value);
155                         }
156                         break;
157                         
158                         case 'w': {
159                                 uint32_t value;
160                                 ret = pci_read_config_word(&loc, offset, &value);
161                                 if (ret != _PCI_SUCCESSFUL) goto error;
162                                 
163                                 printf("word at device %02x:%02x config offset %04x: %08x\n", loc.bus, loc.dev_fn, offset, value);
164                         }
165                         break;
166                 }
167         } else if (!strcmp(argv[2].str, "mb") || !strcmp(argv[2].str, "mh") || !strcmp(argv[2].str, "mw")) {
168                 if (argc != 7) {
169                         return -1;
170                 }
171                 
172                 loc.bus = atoui(argv[3].str);
173                 loc.dev_fn = atoui(argv[4].str);
174                 offset = atoui(argv[5].str);
175                 
176                 switch (argv[2].str[1]) {
177                         case 'b': {
178                                 uint8_t value = atoui(argv[6].str);
179                                 ret = pci_write_config_byte(&loc, offset, value);
180                                 if (ret != _PCI_SUCCESSFUL) goto error;
181                                 
182                                 printf("byte to device %02x:%02x config offset %04x: %02x\n", loc.bus, loc.dev_fn, offset, value);
183                         }
184                         break;
185                         
186                         case 'h': {
187                                 uint16_t value = atoui(argv[6].str);
188                                 ret = pci_write_config_half(&loc, offset, value);
189                                 if (ret != _PCI_SUCCESSFUL) goto error;
190                                 
191                                 printf("half to device %02x:%02x config offset %04x: %04x\n", loc.bus, loc.dev_fn, offset, value);
192                         }
193                         break;
194                         
195                         case 'w': {
196                                 uint32_t value = atoui(argv[6].str);
197                                 ret = pci_write_config_word(&loc, offset, value);
198                                 if (ret != _PCI_SUCCESSFUL) goto error;
199                                 
200                                 printf("word to device %02x:%02x config offset %04x: %08x\n", loc.bus, loc.dev_fn, offset, value);
201                         }
202                         break;
203                 }
204         } else {
205                 return -1;
206         }
207         
208         return 0;
209
210 error:
211         printf("Error while reading PCI config space: %02x\n", ret);
212         return -2;
213 }
214
215 static int pci_cmd(int argc, const cmd_args *argv)
216 {
217         if (argc < 2) {
218                 printf("pci commands:\n");
219 usage:
220                 printf("%s list\n", argv[0].str);
221                 printf("%s config dump <bus> <devfn>\n", argv[0].str);
222                 printf("%s config <rb|rh|rw> <bus> <devfn> <offset>\n", argv[0].str);
223                 printf("%s config <mb|mh|mw> <bus> <devfn> <offset> <value>\n", argv[0].str);
224                 goto out;
225         }
226         
227         if (!strcmp(argv[1].str, "list")) {
228                 pci_list();
229         } else if (!strcmp(argv[1].str, "config")) {
230                 if (pci_config(argc, argv)) {
231                         goto usage;
232                 }
233         } else {
234                 goto usage;
235         }
236
237 out:
238         return 0;
239 }
240
241 STATIC_COMMAND_START
242 { "pci", "pci toolbox", &pci_cmd },
243 STATIC_COMMAND_END(pcitests);
244
245 #endif
246
247 APP_START(pcitests)
248 APP_END
249