1 //==========================================================================
5 // Test PCI library API
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
44 // Contributors: jskov
46 // Description: Simple test that:
47 // Checks API (compile time)
48 // Prints out information about found PCI devices.
49 // Allocates resources to devices (but does not enable
51 //####DESCRIPTIONEND####
53 #include <pkgconf/system.h>
55 #include <cyg/infra/diag.h> // diag_printf
56 #include <cyg/infra/testcase.h> // test macros
57 #include <cyg/infra/cyg_ass.h> // assertion macros
59 // Package requirements
60 #if defined(CYGPKG_IO_PCI) && defined(CYGPKG_KERNEL) && defined(CYGPKG_ISOINFRA)
62 #include <pkgconf/kernel.h>
63 #include <pkgconf/io_pci.h>
64 #include <cyg/io/pci.h>
65 #include <cyg/hal/hal_arch.h>
68 // Package option requirements
69 #if defined(CYGFUN_KERNEL_API_C) && defined(CYG_PCI_PRESENT)
71 #include <cyg/kernel/kapi.h>
73 // If the target has limited memory resources, undef the below to
74 // avoid inclusion of the big PCI code tables.
76 // The header file is created from http://www.yourvote.com/pci
77 // maintained by Jim Boemler (jboemler@halcyon.com).
79 // If you have PCI devices not listed in this list, please consider
80 // registering the codes in the database.
81 #define USE_PCI_CODE_LIST
83 #ifdef USE_PCI_CODE_LIST
87 // You may want to use this code to do some simple testing of the
88 // devices on the PCI bus. By enabling the below definition, the
89 // devices will get PCI IO and MEM access activated after configuration
90 // so you can play with IO registers and display/set contents of MEM.
91 #define nENABLE_PCI_DEVICES
93 unsigned char stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
94 cyg_thread thread_data;
95 cyg_handle_t thread_handle;
97 void pci_scan( void );
100 pci_api_test(int dummy)
102 cyg_pci_device dev_info;
103 cyg_pci_device_id devid = CYG_PCI_NULL_DEVID;
105 CYG_PCI_ADDRESS64 mem_base = 0;
106 CYG_PCI_ADDRESS32 io_base = 0;
109 cyg_uint16 var_uint16;
110 cyg_uint32 var_uint32;
117 CYG_TEST_FAIL_FINISH("Not reached");
122 cyg_pci_get_device_info (devid, &dev_info);
123 cyg_pci_set_device_info (devid, &dev_info);
125 ret = cyg_pci_find_device(0, 0, &devid);
126 ret |= cyg_pci_find_class(0, &devid);
127 ret |= cyg_pci_find_next(devid, &devid);
129 ret |= cyg_pci_configure_device(&dev_info);
131 cyg_pci_set_memory_base(mem_base);
132 cyg_pci_set_io_base(io_base);
134 ret |= cyg_pci_allocate_memory(&dev_info, 0, &mem_base);
135 ret |= cyg_pci_allocate_io(&dev_info, 0, &io_base);
137 ret |= cyg_pci_translate_interrupt(&dev_info, &vec);
139 cyg_pci_read_config_uint8(devid, 0, &var_uint8);
140 cyg_pci_read_config_uint16(devid, 0, &var_uint16);
141 cyg_pci_read_config_uint32(devid, 0, &var_uint32);
143 cyg_pci_write_config_uint8(devid, 0, var_uint8);
144 cyg_pci_write_config_uint16(devid, 0, var_uint16);
145 cyg_pci_write_config_uint32(devid, 0, var_uint32);
153 cyg_pci_device dev_info;
154 cyg_pci_device_id devid;
157 #ifdef USE_PCI_CODE_LIST
158 cyg_bool no_match = false;
159 cyg_uint16 vendor, device;
160 cyg_uint8 bc, sc, pi;
163 PCI_CLASSCODETABLE* ctbl;
170 diag_printf( "========== Finding and configuring devices\n" );
172 if (cyg_pci_find_next(CYG_PCI_NULL_DEVID, &devid)) {
175 cyg_pci_get_device_info(devid, &dev_info);
179 diag_printf("Found device on bus %d, devfn 0x%02x:\n",
180 CYG_PCI_DEV_GET_BUS(devid),
181 CYG_PCI_DEV_GET_DEVFN(devid));
183 if (dev_info.command & CYG_PCI_CFG_COMMAND_ACTIVE) {
184 diag_printf(" Note that board is active. Probed"
185 " sizes and CPU addresses invalid!\n");
188 // Configure the device
189 if (cyg_pci_configure_device(&dev_info)) {
190 diag_printf(" Device configuration succeeded\n");
191 #ifdef ENABLE_PCI_DEVICES
195 // Don't use cyg_pci_set_device_info since it clears
196 // some of the fields we want to print out below.
197 cyg_pci_read_config_uint16(dev_info.devid,
198 CYG_PCI_CFG_COMMAND, &cmd);
199 cmd |= CYG_PCI_CFG_COMMAND_IO|CYG_PCI_CFG_COMMAND_MEMORY;
200 cyg_pci_write_config_uint16(dev_info.devid,
201 CYG_PCI_CFG_COMMAND, cmd);
203 diag_printf(" **** Device IO and MEM access enabled\n");
206 diag_printf(" Device configuration failed");
207 if (dev_info.command & CYG_PCI_CFG_COMMAND_ACTIVE)
208 diag_printf(" - device already enabled\n");
210 diag_printf(" - resource problem\n");
213 diag_printf(" Vendor 0x%04x", dev_info.vendor);
214 #ifdef USE_PCI_CODE_LIST
215 vendor = dev_info.vendor;
217 for (i = 0; i < PCI_VENTABLE_LEN; i++, vtbl++)
218 if (vendor == vtbl->VenId)
221 if (i < PCI_VENTABLE_LEN) {
222 diag_printf(" [%s][%s]", vtbl->VenShort, vtbl->VenFull);
224 diag_printf(" [UNKNOWN]");
228 diag_printf("\n Device 0x%04x", dev_info.device);
229 #ifdef USE_PCI_CODE_LIST
230 device = dev_info.device;
232 for (i = 0; i < PCI_DEVTABLE_LEN; i++, dtbl++)
233 if (vendor == dtbl->VenId && device == dtbl->DevId)
236 if (i < PCI_DEVTABLE_LEN) {
237 diag_printf(" [%s][%s]", dtbl->Chip, dtbl->ChipDesc);
239 diag_printf(" [UNKNOWN]");
244 diag_printf("\n Command 0x%04x, Status 0x%04x\n",
245 dev_info.command, dev_info.status);
247 diag_printf(" Class/Rev 0x%08x", dev_info.class_rev);
248 #ifdef USE_PCI_CODE_LIST
249 bc = (dev_info.class_rev >> 24) & 0xff;
250 sc = (dev_info.class_rev >> 16) & 0xff;
251 pi = (dev_info.class_rev >> 8) & 0xff;
252 ctbl = PciClassCodeTable;
253 for (i = 0; i < PCI_CLASSCODETABLE_LEN; i++, ctbl++)
254 if (bc == ctbl->BaseClass
255 && sc == ctbl->SubClass
256 && pi == ctbl->ProgIf)
259 if (i < PCI_CLASSCODETABLE_LEN) {
260 diag_printf(" [%s][%s][%s]", ctbl->BaseDesc,
261 ctbl->SubDesc, ctbl->ProgDesc);
263 diag_printf(" [UNKNOWN]");
267 diag_printf("\n Header 0x%02x\n", dev_info.header_type);
269 diag_printf(" SubVendor 0x%04x, Sub ID 0x%04x\n",
270 dev_info.header.normal.sub_vendor,
271 dev_info.header.normal.sub_id);
274 for(i = 0; i < CYG_PCI_MAX_BAR; i++) {
275 diag_printf(" BAR[%d] 0x%08x /", i, dev_info.base_address[i]);
276 diag_printf(" probed size 0x%08x / CPU addr 0x%08x\n",
277 dev_info.base_size[i], dev_info.base_map[i]);
280 if (cyg_pci_translate_interrupt(&dev_info, &irq))
281 diag_printf(" Wired to HAL vector %d\n", irq);
283 diag_printf(" Does not generate interrupts.\n");
285 } while (cyg_pci_find_next(devid, &devid));
288 #ifdef USE_PCI_CODE_LIST
289 diag_printf("\nStrings in [] are from the PCI Code List at http://www.yourvote.com/pci\n");
291 diag_printf("It seems that some of the device information has not been registered in\n");
292 diag_printf("the PCI Code List. Please consider improving the database by registering\n");
293 diag_printf("the [UNKNOWN] information for your devices. Thanks.\n");
297 diag_printf("No PCI devices found.");
302 CYG_TEST_PASS_FINISH("pci1 test OK");
308 cyg_pci_device dev_info;
309 cyg_pci_device_id devid;
312 #ifdef USE_PCI_CODE_LIST
313 cyg_bool no_match = false;
314 cyg_uint16 vendor, device;
315 cyg_uint8 bc, sc, pi;
318 PCI_CLASSCODETABLE* ctbl;
321 diag_printf( "========== Scanning initialized devices\n" );
323 if (cyg_pci_find_next(CYG_PCI_NULL_DEVID, &devid)) {
325 // Since we are NOT about to configure the device, set the
326 // devinfo record so we don't mistake garbage for data.
327 memset( &dev_info, 0xAAAAAAAAu, sizeof( dev_info ) );
330 cyg_pci_get_device_info(devid, &dev_info);
333 diag_printf("Found device on bus %d, devfn 0x%02x:\n",
334 CYG_PCI_DEV_GET_BUS(devid),
335 CYG_PCI_DEV_GET_DEVFN(devid));
337 if (dev_info.command & CYG_PCI_CFG_COMMAND_ACTIVE) {
338 diag_printf(" Note that board is active. Probed"
339 " sizes and CPU addresses invalid!\n");
342 diag_printf(" Vendor 0x%04x", dev_info.vendor);
343 #ifdef USE_PCI_CODE_LIST
344 vendor = dev_info.vendor;
346 for (i = 0; i < PCI_VENTABLE_LEN; i++, vtbl++)
347 if (vendor == vtbl->VenId)
350 if (i < PCI_VENTABLE_LEN) {
351 diag_printf(" [%s][%s]", vtbl->VenShort, vtbl->VenFull);
353 diag_printf(" [UNKNOWN]");
357 diag_printf("\n Device 0x%04x", dev_info.device);
358 #ifdef USE_PCI_CODE_LIST
359 device = dev_info.device;
361 for (i = 0; i < PCI_DEVTABLE_LEN; i++, dtbl++)
362 if (vendor == dtbl->VenId && device == dtbl->DevId)
365 if (i < PCI_DEVTABLE_LEN) {
366 diag_printf(" [%s][%s]", dtbl->Chip, dtbl->ChipDesc);
368 diag_printf(" [UNKNOWN]");
373 diag_printf("\n Command 0x%04x, Status 0x%04x\n",
374 dev_info.command, dev_info.status);
376 diag_printf(" Class/Rev 0x%08x", dev_info.class_rev);
377 #ifdef USE_PCI_CODE_LIST
378 bc = (dev_info.class_rev >> 24) & 0xff;
379 sc = (dev_info.class_rev >> 16) & 0xff;
380 pi = (dev_info.class_rev >> 8) & 0xff;
381 ctbl = PciClassCodeTable;
382 for (i = 0; i < PCI_CLASSCODETABLE_LEN; i++, ctbl++)
383 if (bc == ctbl->BaseClass
384 && sc == ctbl->SubClass
385 && pi == ctbl->ProgIf)
388 if (i < PCI_CLASSCODETABLE_LEN) {
389 diag_printf(" [%s][%s][%s]", ctbl->BaseDesc,
390 ctbl->SubDesc, ctbl->ProgDesc);
392 diag_printf(" [UNKNOWN]");
396 diag_printf("\n Header 0x%02x\n", dev_info.header_type);
398 diag_printf(" SubVendor 0x%04x, Sub ID 0x%04x\n",
399 dev_info.header.normal.sub_vendor,
400 dev_info.header.normal.sub_id);
403 for(i = 0; i < CYG_PCI_MAX_BAR; i++) {
404 diag_printf(" BAR[%d] 0x%08x /", i, dev_info.base_address[i]);
405 diag_printf(" probed size 0x%08x / CPU addr 0x%08x\n",
406 dev_info.base_size[i], dev_info.base_map[i]);
409 if (cyg_pci_translate_interrupt(&dev_info, &irq))
410 diag_printf(" Wired to HAL vector %d\n", irq);
412 diag_printf(" Does not generate interrupts.\n");
414 } while (cyg_pci_find_next(devid, &devid));
416 diag_printf("No PCI devices found.");
424 cyg_thread_create(10, // Priority - just a number
425 (cyg_thread_entry_t*)pci_test, // entry
427 "pci_thread", // Name
429 CYGNUM_HAL_STACK_SIZE_TYPICAL, // Size
430 &thread_handle, // Handle
431 &thread_data // Thread data structure
433 cyg_thread_resume(thread_handle);
434 cyg_scheduler_start();
437 #else // CYGFUN_KERNEL_API_C && CYG_PCI_PRESENT
438 #define N_A_MSG "Needs kernel C API & PCI platform support"
441 #else // CYGPKG_IO_PCI && CYGPKG_KERNEL
442 #define N_A_MSG "Needs IO/PCI, ISOINFRA, and Kernel"
450 CYG_TEST_NA( N_A_MSG);