PCI Address Spaces - osdev

I have a question about the PCI. The PCI has three address spaces; PCI I/O, PCI Memory and PCI Configuration space. Where are they each physically located? In the PCI controller? Or in the devices? Is any of them part of the system RAM?

For physical plug-in PCI cards it is always on the device. The device has to announce what it is (configuration space), and keeps it local state independent of the host machine (I/O and memory space)
PCI is however often abused as just the mechanism for configuration, and there are many devices that do not actually talk over a PCI interface but only fake it - PCI express cards always shows up as a PCI device, but the magical 33MHz bus that would have been put between them has magically disappeared.
With pretty much everything integrated in the chipset these days, the majority of PCI devices are such fakes. However, they still uphold everything that PCI dictates it to be. For instance, an embedded graphics on your northbridge will use the system RAM, but for all the ram that the graphics device uses, the computer will tell the operating system that same ram doesn't exist.
As far as the OS will see, the device always comes with it's own memory.

I would like to add some comments about it.
All of PCI devices have a PCI Configuration space as a BAR0. You can find information about PCI devices in the space. It is located on the device.
And about PCI I/O, PCI Memory, you can put the memory space into both of them. It is depends on your S/W scheme. If your pci device want to access to their host memory data, you can put the memory space into your PCI controller. (ex, tx packet buffer in the network driver).

Related

net.ipv4 kernel variables affect on DPDK ports

Sorry beforehand if this question is trivial or even if the answer is the question.
Our devices have an application that employees DPDK to use its NICs.
As part of the device setup some init done, part of it is settings kernel variables net.ipv4.tcp_keepalive_intvl, tcp_max_syn_backlog, net.ipv4.conf.all.log_martians and etc
Do these kind of variables have any affect our ports under DPDK control?
Probably not, as DPDK is user space NICs, but I am not confident enough to assert it
As long as you have NIC which are listed in driver/net/ there are not much PMD devices which rely net.ipv4 other than TAP/TUN. So if it is physical NIC one would not be affected.
[EDIT-1]
only Physcial NIC with userspace PMD (not tap representations) can be guaranteed to be not be affected like e1000, ixgbe, i40e, ice, fm10k etc are not affected. PMD like AF_PACKET/AF_XDP are also not affected while TAP/PCAP goes through linux stack

C/C++ How to get the usb subsystem path for a USB libudev hidraw device?

I'm using libudev in C/C++ with the hidraw subsystem to enumerate and communicate with custom HID devices - working well. My devices are assigned specific usb plugs and they are "hot swappable" - I need to know which plug is connected to each hidraw device. Is there a correspondence between the usb and the hidraw subsystems and how to get the usb path which details the interface route (like: /dev/bus/usb/002/001 and not the hidraw path) for each device from its hidraw device pointer?
i think with hidraw device pointer you mean the device nodes like /dev/hidraw0 or similar
Hidraw uses a dynamic major number, meaning that udev should be relied
on to create hidraw device nodes. Udev will typically create the
device nodes directly under /dev (eg: /dev/hidraw0). As this location
is distribution- and udev rule-dependent, applications should use
libudev to locate hidraw devices attached to the system. There is a
tutorial on libudev with a working example at:
http://www.signal11.us/oss/udev/
linux has two species of device nodes, one created by device drivers i.e. /dev/sdb for a mass storage device and raw device nodes like /dev/bus/usb/BBB/DDD where BBB is the bus number and DDD is the device number, that are created by the kernel directly :
USB Device Issues
USB devices usually have two kinds of device nodes associated with
them.
The first kind is created by device-specific drivers (e.g.,
usb_storage/sd_mod or usblp) in the kernel. For example, a USB mass
storage device would be /dev/sdb, and a USB printer would be
/dev/usb/lp0. These device nodes exist only when the device-specific
driver is loaded.
The second kind of device nodes (/dev/bus/usb/BBB/DDD, where BBB is
the bus number and DDD is the device number) are created even if the
device doesn't have a kernel driver. By using these "raw" USB device
nodes, an application can exchange arbitrary USB packets with the
device, i.e., bypass the possibly-existing kernel driver.
source : http://www.linuxfromscratch.org/blfs/view/7.10/postlfs/devices.html
you want to establish a link between the kernel module device node ( i.e. /dev/hidraw0 ) and the corresponding raw device node ( i.e /dev/bus/usb/BBB/DDD )
you can get the bus address (BBB and DDD ) from the device node using sudo udevadm info -a -p $(sudo udevadm info -q path -n /dev/hidraw0) ( ATTRS{busnum}=="BBB" and ATTRS{devnum}=="DDD" in the output ) however this is a bit ugly
in Find bus number and device number with device file symlink is code using libudev to get bus number BBB and device number DDD for a specific device node in /dev/ i.e. /dev/hidraw0 it uses udev_device_get_sysattr_value(dev, "devnum")); to get DDD in /dev/bus/usb/BBB/DDD and udev_device_get_sysattr_value(dev, busnum")); to get BBB
you can also get BBB and DDD from sysfs ( /sys/devices/ ... ) :
/sys/devices/pci0000:00/0000:00:12.2/usb2/2-5/2-5.4$ ls 2-5.4:1.0
bDeviceSubClass configuration idProduct remove authorized
bmAttributes descriptors idVendor serial
avoid_reset_quirk bMaxPacketSize0 dev manufacturer
speed bcdDevice bMaxPower devnum
maxchild subsystem bConfigurationValue bNumConfigurations devpath
power uevent bDeviceClass bNumInterfaces driver
product urbnum bDeviceProtocol busnum
ep_00
quirks version
source : http://www.signal11.us/oss/udev/
to get the sysfs path of your device ( the /sys/devices/pci0000:00/0000:00:12.2/usb2/2-5/2-5.4 above ) use sudo udevadm info -q path -n /dev/hidraw0
( https://unix.stackexchange.com/questions/344784/how-to-map-sys-bus-usb-devices-to-dev-video )
Hope it's helpful but IIRC, you cannot reliably (with port# being same between insert events) enumerate individual ports on hubs that are connected downstream from a main USB controller point. I think that was one of the reasons we started seeing lots and lots of USB controllers on MB's after USB came out; because when chaining everything off downstream hubs, besides negatively affecting bandwidth, also caused problems with persistent software numbering issues.
I believe when a device is plugged into a USB port directly connected to a USB controller, you can reliably get the same exact port# it's connected to. But when doing that from a downstream multi-port USB hub connected upstream to a USB port from a USB controller, the actual port# on the USB hub does not get passed upstream or even if it does, it is not a predictable port# between insertions/power-resets in the same hub port.

Direct access PCI serial port

Hello i have an application built some times ago in C++.
It is used to control an appliance via serial port.
I remember the guy that developed it saying that his software is directly accessing the serial port (directly accessing the memory).
Since PCs with serial ports are becoming rare these days, would the software still directly access the serial port if i used a PCI extension serial port?
Thanks
That depends a bit on how much backward-compatible driver support your PCIe serial port has.
If it provides direct I/O-space mapping of a (possibly virtual) 16550 UART's registers, you will need to change the "base address" in the software but then it might work. If the drivers do not, then it's not going to work.
The first four standard serial ports have the following base addresses and interrupts associated with them:
| base IRQ
-----------------
COM1 | 0x3f8 IRQ4
COM2 | 0x2f8 IRQ3
COM3 | 0x3e8 n/a
COM4 | 0x2e8 n/a
The software should probably be rewritten to use more high-level access to the port.
I believe that the vast majority of local bus serial port cards emulate a 16x50 RS-232 UART. Unless you intend to use some special card, such as those expensive multiport cards used for managing modem banks, it would probably be fine.
USB/RS-232 converters are a different story altogether - in general they will not work with software that accesses the serial port directly, as their driver only provides access via the OS serial port subsystem. Even if their driver somehow manages to emulate a proper local bus UART, those converters often have different behavior w.r.t. signal timing that might lead to issues with software that does unusual things with the serial port. For example, I have had issues with attaching IR remote control receivers to some USB/RS-232 converters. Using a converter that supports USB 2.0 helps somewhat, but it is still far from the real thing.
You should also keep in mind that if your application is designed for an older OS, newer versions of that operating system might not allow direct access to serial ports anymore.
If all else fails, you might still be able to improve the situation by using a virtual machine. For example, VirtualBox allows the guest OS to access the host serial ports, emulating a 16550A UART. This might allow you to work around a driver or an OS that does not support or allow direct access to a serial port.
I searched around i found some PCI cards that map their serial ports to the memory.
I will try one of those.
Thank you all.
I have another solution.
PCs are coming with mostly usb ports.
so you can use any usb to serial port converter. it is very cheap and works fine.

Send zeroes and ones to the USB data pins?

Am trying to figure how can I make some software and USB hardware.
Let's put the hardware thing aside for now. For software, how can I send data to a USB port?
C++ / Java or any other language (prefer to be working on Linux).
USB ports are not like "dumb" RS-232 serial ports. It's a bus, that requires quite complicated handling, all driven by the host (the computer, typically). Very low-level operations such as "sending ones and zeros" to the data pins are more or less impossible.
The easiest way to program USB from user-space in Linux is probably to use libusb.
On the client (your custom USB hardware) end, either look for a system featuring a built-in USB controller, or a software stack. I don't think writing your own software stack is feasible, since you (no offense) don't seem to be quite at that level regarding your knowledge of USB.
V-USB is a software USB stack for Atmel's AVR microcontrollers, for instance.
As others have pointed out you have to write a driver for the USB device.
Another option is to communicate with the device using a serial protocol over USB, then your hardware needs an USB to serial chip. The best answer regarding USB over serial is in the question How to get C++ to perform I/O from a USB Port like a Serial Port by Mike DeSimone
If you want to bitbang I/O using USB, then you can connect a FTDI chip like the FT232 (which is used in many USB to serial cables) to the USB port.
On the PC you can use libFTDI to bitbang the I/O pins of the FTDI chip.
I think this is the easiest way for controlling I/O pins using USB.
An alternative to serial port emulation is USB HID (Human Input Device), which is supported on Linux out of the box. You'd use the "HIDAPI" to communicate with your device.
A usb port is just a serial port. Therefore, the first place that you want to look is writing a sofware to handle serial port communication.
Be aware that the OS may assign a different port number to the device whenever it's connected.

Control of sd-card pins in Linux

Is it possible to control SD card reader register pins from Linux via C/C++ ? I have seen people doing it for pcmcia. But never with sd.
Use lspci to list the devices on your motherboard. From that you can find the hardware driver. If it doesn't already have the capability, you can add ioctl calls to the driver to read and write registers.