how to find out which ioports be assigned to my devices - linux

has linux reserved io port numbers for all manufactured devices.
I have devices like intel built-in network card. or another device I have for wifi (usb) from realtek.
On linux repository on github, device drivers use specific io ports to register. And kernel assign those ports to device driver. device drivers normally request for ports using call to request_region function. so for some ethernet device it requests like following
for (id_port = 0x110 ; id_port < 0x200; id_port += 0x10)
{
if (!request_region(id_port, 1, "3c509-control"))
continue;
outb(0x00, id_port);
outb(0xff, id_port);
if (inb(id_port) & 0x01)
break;
else
release_region(id_port, 1);
}
above starts with 0x110 to 0x200, any port can be assigned in this range by kernel to driver and appear in /proc/ioports file means driver is using that io port by the time of success return from request_region.
Question : So my question is has linux assigned io ports to all manufactured devices usable with kernel 5.7 or latest kernel version?
Question : What if I want to write device driver for any device. How can I find the io ports number range to request to. I dont not expect that I have to look into kernel code and find similer driver port range. so How can I find that io port number range. how to achieve this first step required in writing device driver (any device. be it wifi internet device or ethernet device)

Question : So my question is has linux assigned io ports to all manufactured devices usable with kernel 5.7 or latest kernel version?
No.
Question : What if I want to write device driver for any device. How can I find the io ports number range to request to.
You ask the user for it. After all it's the user who set them using jumpers on the ISA card.
Here's a picture of an old Sound Blaster card (taken from Wikipedia, I'm too lazy to rummage around in my basement now). I've highlighted a specific area in the picture:
That jumper header I highlighted: That's the port configuration jumper. As a user you literally connect two of the pins with a jumper connector and that connects a specific address line that comes from the card connectors to the circuitry on the rest of the card. This address line is part of the AT bus port I/O scheme. The user sets this jumper, writes down the number and then tells the driver, which number it was set to. That's how AT style I/O ports.
Or the driver uses one of the well known port numbers for specific hardware (like network controllers) that dates back to the era, where ISA style ports were still are thing. Also there's old ISA-P'n'P where the BIOS and the add-in cards would negotiate the port assignments at power up, before the OS even started. You can read those port numbers with the ISA-P'n'P API provided by the kernel.
We no longer use this kind of hardware in practice! Except for legacy and retro computing purposes.
Over a quarter of century ago, the old AT / ISA bus was superseeded with PCI. Today we use PCIe which, from the point of view of software still looks like PCI. One of the important things about PCI was, that it completely dropped the whole concept of ports.
With ISA what you had were 8 data lines and 16 address lines, plus two read/write enable lines, one for memory mapped I/O and one for port I/O. You can find the details here https://archive.is/3jjZj. But what happens when you're reading from say, port 0x0104, it would physically set the bit pattern of 0x0104 to the address lines on the ISA bus, pull low the read enable line, and then read the voltage level on the data lines. And all of that is implemented as an actual set of instructions of the x86: https://c9x.me/x86/html/file_module_x86_id_139.html
Now look at the PCI bus: There's no longer separate data and address lines. Instead read/write commands would be sent, and everything happens through memory mappings. PCI devices have something called a BAR: a Base Address Register. This is configured by the PCI root complex and assigns the hardware the region of actual physical bus addresses where it appears. The OS has to get those BAR information from the PCI root complex. The driver uses the PCI IDs to have the hardware discovered and the BAR information told to it. It can then do memory reads/writes to talk to the hardware. No I/O ports involved. And that is just the lowest level. USB and Ethernet happen a lot further up. USB is quite abstract, as is Ethernet.
Your other question Looking for driver developer datasheet of Intel(R) Core(TM) i5-2450M CPU # 2.50GHz suggests, that you have some serious misconceptions of what is actually going on. You were asking about USB devices, and Ethernet ports. Neither of those in any way directly interact with this part of the computer.
Your question per se is interesting. But we're also running into a massive XYZ problem here; it's worse than an XY problem; you're asking about X, although you want to solve Y. But Y isn't even the problem you're dealing with in the first place.
You're obviously smart, and curious, and I applaud that. But I have to tell you, that you've to backtrack quite a bit, to clear up some of the misconceptions you have.

Related

IO port register sizing and how device recognise address is for it

I read in a article about that 64k io port each are address assigned to 8bit register and when you combine io port together you get 16 bit,32bit etc. Sorry i am not getting that website in my history now so i cant provide link.
I just not understood what it want to say so i just put the raw form here
So there are mine few points that i want confirmation on as i am confused bcoz as i accidently land on another website they have just another idea.
i) i/o ports are assigned to registers of peripherals. These are of 16bit as there are 64k port and register they are assigned to can be of any size(8,16,32,64bit).
ii)Except for pci related devices io port address number are fixed,but as in device with configuration space register can be assigned io address number using bar any number one want just i should not be used by anyother device.
Que1)When a address come out of processor it goes to motherboard through northbridge/system_agent and it routes it according to address map it has, peripheral device are told to accept i/o range or memory address range on basis of what was configured in bar,but as northbridge is made up of many controller [like memory,graphics,pci etc] but it is who, who has address mapping to route.
queii) according to intel 82815 gmch northbridge page 129 section 4.3
"The processor allows 64K+3 bytes to be addressed within the I/O
space. The GMCH propagates the processor I/O address without any
translation on to the destination bus"
What does this means it only routes mmio and io bar but than how rest of io address(that are not assigned by software or due to i/o bar register) are decided. where should they go how peripheral device know this address it should acccept,if they are just thrown on the bus than how CS pin is decided of particular device

How to set chip select in SPI programming for multipleslaves ? (struct spi_ioc_transfer)

Maybe I am asking the wrong question actually but I am just making my first steps in the embedded world. So I am sorry if the question is somehow stupid.
I am trying to program a software for 9DOF IMU in c++ and linux environment.
As far as I understood the SPI, the SS pin has to be low active in order for a transmission to occur. I have seen multiple reading or writing bytes function examples and all using the struct spi_ioc_transfer but they were all single slave examples and there is no mention about setting or configuring the SS in the code. Also When I check the structre of spi_ioc_transfer there is the cs_change however, how does it know which cs we are dealing with from the beginning ?
The chip select (CS or SS) to use is determined by which device node you open.
To talk to a SPI chip with the Linux spidev driver, you open a device such as /dev/spidev0.1. The numbers in the device node file name refer to the bus and chip select, respectively — in this example it would be the first bus (0) and the second CS (1). If you want to talk to devices on different chip-selects, you have to open different device nodes and do ioctls on the appropriate one.

Linux PCI Driver calls init, but not probe

I'm developing a driver for an FPGA-board connected to my machine via an PCIe expansion slot, and everything works great if the board is powered on prior to the PC. However, if I book up my computer first and then the FPGA board, I get the rather unusual behavior of the device being recognized and loading my module (I see the "init" function called in my syslog), however the "probe" function is never called.
I think this is due to an invalid BAR0. Output from dmesg when I power on the board:
[ 71.287587] pci 0000:3b:00.0: [0ae5:0001] type 00 class 0x000000
[ 71.287613] pci 0000:3b:00.0: reg 0x10: [mem 0x00000000-0x0000ffff]
[ 71.287821] pci 0000:3b:00.0: System wakeup disabled by ACPI
[ 71.328537] my_driver:
[ 71.328537] ****************************************************************
[ 71.328542] my_driver: init debug=2
That first reg should be something like 0xb4000000-0xb400ffff but instead it's coming up as 0. (Like I said, it works perfectly if it's powered on before the computer).
Is there an additional step required to get it to allocate this block? Or somehow to indicate to the kernel that it needs to do this?
The solution wound up being a manual call to pci_assign_resource ( http://lxr.free-electrons.com/source/drivers/pci/setup-res.c#L283 ).
Calling this right before pci_enable_device caused the OS, rather than the BIOS, to allocate the required BAR's and now it all works!
I do still have to manually trigger a PCI bus rescan ( echo 1 > /sys/bus/pci/rescan ).
Your PCI device must be powered up prior to the BIOS PCI enumeration phase.
On enumeration phase, the BIOS tries to read the ID of the PCI devices that might be connected.
If it reads invalid ID (0xfffff) it skips that PCI device.
I don't have a reference, but AFAIK, you have about a second before you must populate the configuration space of the PCI.
Are you sure you register the PCI driver and don't return non-zero from mod_init? Please try to manually bind the device to your driver:
echo -n "0000:3b:00.0" > /sys/bus/pci/drivers/my_driver/bind
Unallocated BAR should not be an issue when loading the driver.
As for the BAR being 0 and HotPlug: find out what is your platform and if and how HotPlug is supported. You need to have the right HotPlug driver in the kernel for this sort of thing to work. BARs are allocated by the kernel (or initially firmware/BIOS) so you can't set them to anything meaningful from the FPGA side - there you can only set the size. Kernel has to do the rescanning and reassignment after device appears. I vaguely recall that there should be some reservation going on during boot, otherwise kernel will not have to space to give to your devices' BAR and it will not reassign the windows on bridges below your device as they can be actively used by other devs. Other option is to just do the BAR programming yourself from the driver. It ain't that hard but you would probably don't want to ship this kind of hacks to customers. Also, even though your device does seem to come up fine, make sure you don't have HP disabled in FW/BIOS.

control Chip Select manually prior to data read in linux?

Hi I have a SPI touch device with 24 keys, each read will return 3 bytes, containing exact all 24 keys status. My hardware is a custom made beaglebone like device, spi0 is able to read its own write by connecting MISO to MOSI.
Everything (wiring, software) is working perfectly matching this guide: http://communistcode.co.uk/blog/blogPost.php?blogPostID=1
Now my touch device is CS active high device, but it requires to drive the chip select to low and back to high before actual read. I don't seems to have control with SPI cs value, I can only either control it within an actual read phase by specifying CS high or low. From my knowledge I have to use another GPIO to emulate the CS.
Question: any way to control cs freely? (i.e. set 0 or 1 by my code directly?)
I have solved this by pinmux the CS pin to a GPIO, and control it manually prior to actual communication.

How would I control the output of the power in USB ports in Linux?

I built a robot from a thin client pc (can run Windows CE or Linux) and two servo motors. I put USB ends on the servo motors, so when they are plugged in to the thin client they continuously run. In Linux, how could I set the amount of current or voltage going from the USB ports to the servo motors? Would I be able to run a shell script to set the power of a certain USB port to slow down a motor or stop one? If this cannot be done through software, what is the easiest way to do this through hardware without having to buy too much?
The USB voltage is fixed at a nominal 5 volts and cannot be controlled.
The behavior of USB devices regarding their current draw is well defined in the USB specifications. USB devices are supposed to draw up to 1 unit load (100mA) unless they have negotiated a higher load from the USB host. It's quite likely that the servo motors that you have are going to need to draw higher currents than that, and wouldn't be able to request it without being a USB device and negotiating with the host.
It's also likely, depending on the servo motor that you are trying to control, that you'll need to either provide a PWM signal or an analogue voltage to control motor position. USB hosts are not intended to provide either of these.
Your best options to drive your motor from your PC are:
Get a dedicated USB controller for your servo motor (if one exists)
Make your own, based on a small microprocessor (eg. using an arduino)
Choose a different port on the PC. If available, PC parallel ports can be controlled to provide control for motor drivers.
The answers here seem to say it is a hardware issue, but I think this is a software issue. ASUS has Ai Charge which more then doubles the volts to charging Apple products from a standard 2.0 usb port.
USB 1.0, 2.0 and 3.0 Specs (All at 5 volts) 4 Wires (2 Data and 2
dedicated power)
Voltage Breakdown: USB 1.0 and USB 2.0 = 0.5A or 500 mA = 2.5 watt
USB 3.0 = 0.9A or 900mA = 4.5 watt Wall wart = 1.5A or 1500 mA = 7.5
watt Ai Charge = 1.2A or 1200mA = 6 watt
Ai Charge works on ASUS and non-ASUS motherboards and is a program you can install in Windows.
Personally I HATE Apple so I want to figure out a way to do this 1.2A usb 2.0 output trick for my netbook while running Linux.
I don't believe it is possible to directly manipulate the USB voltages. They are designed to provide a +5V output at all times unless power is diminised with other hubs.
You might be better served posting this question on http://electronics.stackexchange.com
you need to use PWM to control motors speed, to do that you need a micro controller, PIC18F series supports USB communication, there are plenty of code samples available internet how to use USB in PIC18F series, also you need a transistor array or H-Bridge to control mortors from PIC.
The simplest way to communicate is, program a USB serial in PIC18F micro controller, and when you plug that 18F to your computer, it will detect USB serial port, so you can send the commands to serial port to control speeds.
I dont think its possible, and even if it was, consider this: The USB port is not suposed to power motors because you can burn the USB port. USB is limited to 500mA (or there abouts) and any power device like a motor can potentially require more than that.
Another thing is that servos should be driven with constant voltage, and the speed is controlled by timing impulses on the control wire.
http://en.wikipedia.org/wiki/Pulse-width_modulation
You should use a driver (hardware) to power the motor with an external power source.
This is transistor's purpose, or try with a potentiometer

Resources