]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/io/pci/v2_0/tests/pci1.c
Initial revision
[karo-tx-redboot.git] / packages / io / pci / v2_0 / tests / pci1.c
1 //==========================================================================
2 //
3 //        pci1.c
4 //
5 //        Test PCI library API
6 //
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.
12 //
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.
16 //
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
20 // for more details.
21 //
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.
25 //
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.
32 //
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.
35 //
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####
42 //
43 // Author(s):     jskov
44 // Contributors:  jskov
45 // Date:          1999-03-17
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
50 //                  them).
51 //####DESCRIPTIONEND####
52
53 #include <pkgconf/system.h>
54
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
58
59 // Package requirements
60 #if defined(CYGPKG_IO_PCI) && defined(CYGPKG_KERNEL) && defined(CYGPKG_ISOINFRA)
61
62 #include <pkgconf/kernel.h>
63 #include <pkgconf/io_pci.h>
64 #include <cyg/io/pci.h>
65 #include <cyg/hal/hal_arch.h>
66 #include <string.h>
67
68 // Package option requirements
69 #if defined(CYGFUN_KERNEL_API_C) && defined(CYG_PCI_PRESENT)
70
71 #include <cyg/kernel/kapi.h>
72
73 // If the target has limited memory resources, undef the below to
74 // avoid inclusion of the big PCI code tables.
75 //
76 // The header file is created from http://www.yourvote.com/pci
77 // maintained by Jim Boemler (jboemler@halcyon.com).
78 //
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
82
83 #ifdef USE_PCI_CODE_LIST
84 #include "pcihdr.h"
85 #endif
86
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
92
93 unsigned char stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
94 cyg_thread thread_data;
95 cyg_handle_t thread_handle;
96
97 void pci_scan( void );
98
99 cyg_bool
100 pci_api_test(int dummy)
101 {
102     cyg_pci_device dev_info;
103     cyg_pci_device_id devid = CYG_PCI_NULL_DEVID;
104     cyg_bool ret;
105     CYG_PCI_ADDRESS64 mem_base = 0;
106     CYG_PCI_ADDRESS32 io_base = 0;
107     CYG_ADDRWORD vec;
108     cyg_uint8 var_uint8;
109     cyg_uint16 var_uint16;
110     cyg_uint32 var_uint32;
111
112
113     // Always return...
114     if (dummy)
115         return true;
116
117     CYG_TEST_FAIL_FINISH("Not reached");
118
119     // PCI library API
120     cyg_pci_init();
121
122     cyg_pci_get_device_info (devid, &dev_info);
123     cyg_pci_set_device_info (devid, &dev_info);
124
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);
128
129     ret |= cyg_pci_configure_device(&dev_info);
130
131     cyg_pci_set_memory_base(mem_base);
132     cyg_pci_set_io_base(io_base);
133
134     ret |= cyg_pci_allocate_memory(&dev_info, 0, &mem_base);
135     ret |= cyg_pci_allocate_io(&dev_info, 0, &io_base);
136
137     ret |= cyg_pci_translate_interrupt(&dev_info, &vec);
138
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);
142
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);
146
147     return ret;
148 }
149
150 void
151 pci_test( void )
152 {
153     cyg_pci_device dev_info;
154     cyg_pci_device_id devid;
155     CYG_ADDRWORD irq;
156     int i;
157 #ifdef USE_PCI_CODE_LIST
158     cyg_bool no_match = false;
159     cyg_uint16 vendor, device;
160     cyg_uint8  bc, sc, pi;
161     PCI_VENTABLE* vtbl;
162     PCI_DEVTABLE* dtbl;
163     PCI_CLASSCODETABLE* ctbl;
164 #endif
165
166     pci_api_test(1);
167
168     cyg_pci_init();
169
170     diag_printf( "========== Finding and configuring devices\n" );
171
172     if (cyg_pci_find_next(CYG_PCI_NULL_DEVID, &devid)) {
173         do {
174             // Get device info
175             cyg_pci_get_device_info(devid, &dev_info);
176
177
178             // Print stuff
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));
182
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");
186             }
187
188             // Configure the device
189             if (cyg_pci_configure_device(&dev_info)) {
190                 diag_printf(" Device configuration succeeded\n");
191 #ifdef ENABLE_PCI_DEVICES
192                 {
193                     cyg_uint16 cmd;
194
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);
202                 }
203                 diag_printf(" **** Device IO and MEM access enabled\n");
204 #endif
205             } else {
206                 diag_printf(" Device configuration failed");
207                 if (dev_info.command & CYG_PCI_CFG_COMMAND_ACTIVE)
208                     diag_printf(" - device already enabled\n");
209                 else
210                     diag_printf(" - resource problem\n");
211             }
212
213             diag_printf(" Vendor    0x%04x", dev_info.vendor);
214 #ifdef USE_PCI_CODE_LIST
215             vendor = dev_info.vendor;
216             vtbl = PciVenTable;
217             for (i = 0; i < PCI_VENTABLE_LEN; i++, vtbl++)
218                 if (vendor == vtbl->VenId) 
219                     break;
220
221             if (i < PCI_VENTABLE_LEN) {
222                 diag_printf(" [%s][%s]", vtbl->VenShort, vtbl->VenFull);
223             } else {
224                 diag_printf(" [UNKNOWN]");
225                 no_match = true;
226             }
227 #endif
228             diag_printf("\n Device    0x%04x", dev_info.device);
229 #ifdef USE_PCI_CODE_LIST
230             device = dev_info.device;
231             dtbl = PciDevTable;
232             for (i = 0; i < PCI_DEVTABLE_LEN; i++, dtbl++)
233                 if (vendor == dtbl->VenId && device == dtbl->DevId) 
234                     break;
235
236             if (i < PCI_DEVTABLE_LEN) {
237                 diag_printf(" [%s][%s]", dtbl->Chip, dtbl->ChipDesc);
238             } else {
239                 diag_printf(" [UNKNOWN]");
240                 no_match = true;
241             }
242 #endif
243
244             diag_printf("\n Command   0x%04x, Status 0x%04x\n",
245                         dev_info.command, dev_info.status);
246
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)
257                     break;
258
259             if (i < PCI_CLASSCODETABLE_LEN) {
260                 diag_printf(" [%s][%s][%s]", ctbl->BaseDesc,
261                             ctbl->SubDesc, ctbl->ProgDesc);
262             } else {
263                 diag_printf(" [UNKNOWN]");
264                 no_match = true;
265             }
266 #endif
267             diag_printf("\n Header 0x%02x\n", dev_info.header_type);
268
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);
272
273
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]);
278             }
279             
280             if (cyg_pci_translate_interrupt(&dev_info, &irq))
281                 diag_printf(" Wired to HAL vector %d\n", irq);
282             else
283                 diag_printf(" Does not generate interrupts.\n");
284
285         } while (cyg_pci_find_next(devid, &devid));
286
287
288 #ifdef USE_PCI_CODE_LIST
289         diag_printf("\nStrings in [] are from the PCI Code List at http://www.yourvote.com/pci\n");
290         if (no_match) {
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");
294         }
295 #endif
296     } else {
297         diag_printf("No PCI devices found.");
298     }
299
300     pci_scan();
301
302     CYG_TEST_PASS_FINISH("pci1 test OK");
303 }
304
305 void
306 pci_scan( void )
307 {
308     cyg_pci_device dev_info;
309     cyg_pci_device_id devid;
310     CYG_ADDRWORD irq;
311     int i;
312 #ifdef USE_PCI_CODE_LIST
313     cyg_bool no_match = false;
314     cyg_uint16 vendor, device;
315     cyg_uint8  bc, sc, pi;
316     PCI_VENTABLE* vtbl;
317     PCI_DEVTABLE* dtbl;
318     PCI_CLASSCODETABLE* ctbl;
319 #endif
320
321     diag_printf( "========== Scanning initialized devices\n" );
322
323     if (cyg_pci_find_next(CYG_PCI_NULL_DEVID, &devid)) {
324         do {
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 ) );
328
329             // Get device info
330             cyg_pci_get_device_info(devid, &dev_info);
331
332             // Print stuff
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));
336
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");
340             }
341
342             diag_printf(" Vendor    0x%04x", dev_info.vendor);
343 #ifdef USE_PCI_CODE_LIST
344             vendor = dev_info.vendor;
345             vtbl = PciVenTable;
346             for (i = 0; i < PCI_VENTABLE_LEN; i++, vtbl++)
347                 if (vendor == vtbl->VenId) 
348                     break;
349
350             if (i < PCI_VENTABLE_LEN) {
351                 diag_printf(" [%s][%s]", vtbl->VenShort, vtbl->VenFull);
352             } else {
353                 diag_printf(" [UNKNOWN]");
354                 no_match = true;
355             }
356 #endif
357             diag_printf("\n Device    0x%04x", dev_info.device);
358 #ifdef USE_PCI_CODE_LIST
359             device = dev_info.device;
360             dtbl = PciDevTable;
361             for (i = 0; i < PCI_DEVTABLE_LEN; i++, dtbl++)
362                 if (vendor == dtbl->VenId && device == dtbl->DevId) 
363                     break;
364
365             if (i < PCI_DEVTABLE_LEN) {
366                 diag_printf(" [%s][%s]", dtbl->Chip, dtbl->ChipDesc);
367             } else {
368                 diag_printf(" [UNKNOWN]");
369                 no_match = true;
370             }
371 #endif
372
373             diag_printf("\n Command   0x%04x, Status 0x%04x\n",
374                         dev_info.command, dev_info.status);
375
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)
386                     break;
387
388             if (i < PCI_CLASSCODETABLE_LEN) {
389                 diag_printf(" [%s][%s][%s]", ctbl->BaseDesc,
390                             ctbl->SubDesc, ctbl->ProgDesc);
391             } else {
392                 diag_printf(" [UNKNOWN]");
393                 no_match = true;
394             }
395 #endif
396             diag_printf("\n Header 0x%02x\n", dev_info.header_type);
397
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);
401
402
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]);
407             }
408             
409             if (cyg_pci_translate_interrupt(&dev_info, &irq))
410                 diag_printf(" Wired to HAL vector %d\n", irq);
411             else
412                 diag_printf(" Does not generate interrupts.\n");
413
414         } while (cyg_pci_find_next(devid, &devid));
415     } else {
416         diag_printf("No PCI devices found.");
417     }
418 }
419
420 void
421 cyg_start(void)
422 {
423     CYG_TEST_INIT();
424     cyg_thread_create(10,                   // Priority - just a number
425                       (cyg_thread_entry_t*)pci_test,         // entry
426                       0,                    // 
427                       "pci_thread",     // Name
428                       &stack[0],            // Stack
429                       CYGNUM_HAL_STACK_SIZE_TYPICAL,           // Size
430                       &thread_handle,       // Handle
431                       &thread_data          // Thread data structure
432         );
433     cyg_thread_resume(thread_handle);
434     cyg_scheduler_start();
435 }
436
437 #else // CYGFUN_KERNEL_API_C && CYG_PCI_PRESENT
438 #define N_A_MSG "Needs kernel C API & PCI platform support"
439 #endif
440
441 #else // CYGPKG_IO_PCI && CYGPKG_KERNEL
442 #define N_A_MSG "Needs IO/PCI, ISOINFRA, and Kernel"
443 #endif
444
445 #ifdef N_A_MSG
446 void
447 cyg_start( void )
448 {
449     CYG_TEST_INIT();
450     CYG_TEST_NA( N_A_MSG);
451 }
452 #endif // N_A_MSG
453
454 // EOF pci1.c