scanpci: PCI utility on Solaris

/usr/X11/bin/scanpci

usage:
======

NAME
     scanpci - scan/probe PCI buses

SYNOPSIS
     /usr/X11/bin/scanpci [-v12OfV]

DESCRIPTION
     Scanpci is a utility that can be used to scan PCI buses  and
     report  information  about  the configuration space settings
     for each PCI device.  On most platforms, scanpci can only be
     run by the root user.

OPTIONS
     -v      Print the configuration space information  for  each
             device  in  a  verbose format.  Without this option,
             only a brief description is printed for each device.

     -1      Use PCI config type 1.

     -2      Use PCI config type 2.

     -f      Used in conjunction with the above two options, this
             forces  the  specified configuration type to be used
             for config space access.

     -O      Use the OS's PCI config space  access  mechanism  to
             access the PCI config space (when available).

     -V n    Set the verbosity level to n for  the  internal  PCI
             scanner.  This is primarily for debugging use.

SEE ALSO
     pcitweak(1)

man scanpci for more information.


compile:
========

I donwloaded libpciaccess here without knowing whether there is a better place. The verison i am building is 0.10.3.

configure
make
make install

Reffer to README in the source tree for more compiling information


implementation:
===============

libpciaccess has the similar architecture of libpci in pciutils. Here is the implement of scanpci utility based on libpciaccess:

179 int main( int argc, char ** argv )
180 {
181     struct pci_device_iterator * iter;
182     struct pci_device * dev;
183     int ret;
184
185     ret = pci_system_init();
186     if (ret != 0)
187         err(1, "Couldn't initialize PCI system");
188
189     iter = pci_slot_match_iterator_create( NULL );
190     
191     while ( (dev = pci_device_next( iter )) != NULL ) {
192         print_pci_device( dev, 1 );
193     }
194
195     pci_system_cleanup();
196     return 0;
197 }

OS dependent initialization, including the access methods, is implement in pci_system_init(). For Solaris Operating System, the method is defined as:

137 static const struct pci_system_methods solx_devfs_methods = {
138     .destroy = pci_system_solx_devfs_destroy,
139     .destroy_device = NULL,
140     .read_rom = pci_device_solx_devfs_read_rom,
141     .probe = pci_device_solx_devfs_probe,
142     .map_range = pci_device_solx_devfs_map_range,
143     .unmap_range = pci_device_generic_unmap_range,
144
145     .read = pci_device_solx_devfs_read,
146     .write = pci_device_solx_devfs_write,
147
148     .fill_capabilities = pci_fill_capabilities_generic
149 };

These methods are based on the pci-tools in Solaris kernel. Below is the example if read method:

730 /*
731  * solaris version: Read the configurations space of the devices
732  */
733 static int
734 pci_device_solx_devfs_read( struct pci_device * dev, void * data,
735                              pciaddr_t offset, pciaddr_t size,
736                              pciaddr_t * bytes_read )
737 {
738         pcitool_reg_t cfg_prg;
739         int err = 0;
740         int i = 0;
741
742         cfg_prg.offset = offset;
743         cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_1 + NATIVE_ENDIAN;
744         cfg_prg.bus_no = dev->bus;
745         cfg_prg.dev_no = dev->dev;
746         cfg_prg.func_no = dev->func;
747         cfg_prg.barnum = 0;
748         cfg_prg.user_version = PCITOOL_USER_VERSION;
749         *bytes_read = 0;
750
751         for (i = 0; i < size; i = i + PCITOOL_ACC_ATTR_SIZE(PCITOOL_ACC_ATTR_SIZE_1)) {
752
753                 cfg_prg.offset = offset + i;
754                 if ((err = ioctl(root_fd, PCITOOL_DEVICE_GET_REG,
755                     &cfg_prg)) != 0) {
756                         fprintf(stderr, "read bdf<%x,%x,%x,%llx> config space failure/n",
757                             cfg_prg.bus_no,
758                             cfg_prg.dev_no,
759                             cfg_prg.func_no,
760                             cfg_prg.offset);
761                         fprintf(stderr, "Failure cause = %x/n", err);
762                         break;
763                 }
764
765                 ((uint8_t *)data)[i] = (uint8_t)cfg_prg.data;
766                 /*
767                  * DWORDS Offset or bytes Offset ??
768                  */
769         }
770         *bytes_read = i;
771
772         return (err);
773 }

interface:
==========

(1) pci_device_read_rom( )

 77 /**
 78  * Read a device's expansion ROM.
 79  *
 80  * Reads the device's expansion ROM and stores the data in the memory pointed
 81  * to by /c buffer.  The buffer must be at least /c pci_device::rom_size
 82  * bytes.
 83  *
 84  * /param dev    Device whose expansion ROM is to be read.
 85  * /param buffer Memory in which to store the ROM.
 86  *
 87  * /return
 88  * Zero on success or an /c errno value on failure.
 89  */
 90 int
 91 pci_device_read_rom( struct pci_device * dev, void * buffer )

(2) pci_device_probe( )

102 /**
103  * Probe a PCI device to learn information about the device.
104  *
105  * Probes a PCI device to learn various information about the device.  Before
106  * calling this function, the only public fields in the /c pci_device
107  * structure that have valid values are /c pci_device::domain,
108  * /c pci_device::bus, /c pci_device::dev, and /c pci_device::func.
109  *
110  * /param dev  Device to be probed.
111  *
112  * /return
113  * Zero on succes or an /c errno value on failure.
114  */
115 int
116 pci_device_probe( struct pci_device * dev )

(3) pci_device_map_region( )

127 /**
128  * Map the specified BAR so that it can be accessed by the CPU.
129  *
130  * Maps the specified BAR for acces by the processor.  The pointer to the
131  * mapped region is stored in the /c pci_mem_region::memory pointer for the
132  * BAR.
133  *
134  * /param dev          Device whose memory region is to be mapped.
135  * /param region       Region, on the range [0, 5], that is to be mapped.
136  * /param write_enable Map for writing (non-zero).
137  *
138  * /return
139  * Zero on success or an /c errno value on failure.
140  *
141  * /sa pci_device_map_range, pci_device_unmap_range
142  * /deprecated
143  */
144 int
145 pci_device_map_region(struct pci_device * dev, unsigned region,
146                       int write_enable)

(4) pci_device_unmap_region( )

291 /**
292  * Unmap the specified BAR so that it can no longer be accessed by the CPU.
293  *
294  * Unmaps the specified BAR that was previously mapped via
295  * /c pci_device_map_region.
296  *
297  * /param dev          Device whose memory region is to be mapped.
298  * /param region       Region, on the range [0, 5], that is to be mapped.
299  *
300  * /return
301  * Zero on success or an /c errno value on failure.
302  *
303  * /sa pci_device_map_range, pci_device_unmap_range
304  * /deprecated
305  */
306 int
307 pci_device_unmap_region( struct pci_device * dev, unsigned region )

(5) pci_device_cfg_read( )

413 /**
414  * Read arbitrary bytes from device's PCI config space
415  *
416  * Reads data from the device's PCI configuration space.  As with the system
417  * read command, less data may be returned, without an error, than was
418  * requested.  This is particuarly the case if a non-root user tries to read
419  * beyond the first 64-bytes of configuration space.
420  *
421  * /param dev         Device whose PCI configuration data is to be read.
422  * /param data        Location to store the data
423  * /param offset      Initial byte offset to read
424  * /param size        Total number of bytes to read
425  * /param bytes_read  Location to store the actual number of bytes read.  This
426  *                    pointer may be /c NULL.
427  *
428  * /returns
429  * Zero on success or an errno value on failure.
430  *
431  * /note
432  * Data read from PCI configuartion space using this routine is /b not
433  * byte-swapped to the host's byte order.  PCI configuration data is always
434  * stored in little-endian order, and that is what this routine returns.
435  */
436 int
437 pci_device_cfg_read( struct pci_device * dev, void * data,
438                      pciaddr_t offset, pciaddr_t size,
439                      pciaddr_t * bytes_read )

(6) pci_device_cfg_write( )

500 /**
501  * Write arbitrary bytes to device's PCI config space
502  *
503  * Writess data to the device's PCI configuration space.  As with the system
504  * write command, less data may be written, without an error, than was
505  * requested.
506  *
507  * /param dev         Device whose PCI configuration data is to be written.
508  * /param data        Location of the source data
509  * /param offset      Initial byte offset to write
510  * /param size        Total number of bytes to write
511  * /param bytes_read  Location to store the actual number of bytes written.
512  *                    This pointer may be /c NULL.
513  *
514  * /returns
515  * Zero on success or an errno value on failure.
516  *
517  * /note
518  * Data written to PCI configuartion space using this routine is /b not
519  * byte-swapped from the host's byte order.  PCI configuration data is always
520  * stored in little-endian order, so data written with this routine should be
521  * put in that order in advance.
522  */
523 int
524 pci_device_cfg_write( struct pci_device * dev, const void * data,
525                       pciaddr_t offset, pciaddr_t size,
526                       pciaddr_t * bytes_written )

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值