FreeBSD Ethernet Manipulation - c

I need a method to perform the following task, suppose if I have a computer with k (k is large) number of Ethernet interfaces. I want to have a method to identify which identifier (em0) is assigned to which physical interface.
The only "easy" method that I came up is to blink the LED light on the physical interface.
For example
etherblink em0
Would flash the link or the activity LED on the physical Ethernet interface that is assigned to em0.
I know on linux there is the ethertool, but that doesn't work with FreeBSD. As well as there is the LED driver on FreeBSD, but that only support limited number of Ethernet modules.
Any ideas? I thought about binding a socket to the interface and write to the socket, but that didn't work.
C or Perl

Tough I have not done this, but, according to FreeBSD handbook, it's possible to bind specific driver node to specific hardware IRQ using kernel configuration hints. See device.hints(5) and FreeBSD network setup to see how to locate each Ethernet device IRQ.

Assume the interface in question is fxp0... run this as root
use strict;
my $intf = "fxp0";
while (1) {
foreach my $state (qw/up down/) {
system("ifconfig $intf $state\n");
sleep 3;
}
}
I assume you won't care about transfering data through the interface while it's blinking...

Sadly I did not find a general solution to this problem, however, from my research (by reading the change log of FreeBSD 8.2, and from the forums) It seems that:
"some cards blink the LEDs on access, so pings could make a repeated pattern.
The LEDs might even go off if the card is downed with ifconfig(8)."
Particularly em and igb interfaces, as stated by:
"The em(4) and igb(4) drivers now support the led(4) interface via /dev/led/emN and
/dev/led/igbN for identification LED control. The following command line makes the
LED blink on em0:[r211241]" (FreeBSD 8.2 Release changelog)
However I do not have the hardware to test this. What I did end up doing was rewritten the Ethernet driver for the interface that I am using to support the LED hardware feature.

Related

RS485 communication not supported using FTDI cable

I'm trying to port a program, which communicates over RS485 half-duplex UART, to Raspberry Pi. Since Pi's built-in UARTs don't support the RS485 standard, I'm using the USB-RS485-WE-1800-BT FTDI cable.
When connected, I can confirm that the cable's FTDI chip shows up in dmesg, the ftdi_sio driver is loaded, and properly exposes the /dev/ttyUSB0 serial terminal to the rest of the system. However, when I attempt to enable RS485 mode from a simple C program:
struct serial_rs485 config = {
.flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND,
.delay_rts_before_send = 0,
.delay_rts_after_send = 0
};
if (ioctl(fd, TIOCSRS485, &config) < 0) {
fprintf(stderr, "ioctl failed (%d): %s\n", errno, strerror(errno));
exit(0);
}
... I get the following error:
ioctl failed (25): Inappropriate ioctl for device
Looking into a schematic, I realized that the FTDI cable internally uses 2 components:
the FT232R chip, which is controlled by the ftdi_sio driver over USB and produces conventional serial output, and
the ZT485EEN chip, which transforms conventional serial comms to RS485.
So, given that FT232R doesn't technically emit RS485, I understand why its driver complains when asked to enable RS485 mode. What it doesn't know, though, is that the second chip takes care of format conversion transparently.
Having researched this topic for a bit and read answers to a similar question, I'm now curious how to proceed. Should I change the request ID in my ioctl() call to something else than TIOCSRS485? Should I remove the ioctl() call entirely? And if I do that, how can RS485 flags and RTS delays be set? Finally, if this means that enabling RS485 mode is not required in this configuration, can the FTDI cable be bypassed entirely by using Raspberry Pi's built-in UARTs combined with a chip like ZT485EEN?
Should I change the request ID in my ioctl() call to something else than TIOCSRS485? Should I remove the ioctl() call entirely?
Removing the ioctl() would be the appropriate thing to do in this case, as the serial converter is handling it entirely for you. As far as you are concerned, it is just a serial port that you read and write to.
And if I do that, how can RS485 flags and RTS delays be set?
You can't set any flags or delay using the FTDI cable. However, since the data that comes out of the cable is already RS485, there's no need to set anything. As long as whatever it is you're talking to is half-duplex(it does not talk at the same time as you do), this isn't an issue, and you can use it just like an RS232 cable. This depends on your specific use-case though. I have never encountered the need to have an RTS delay.
Finally, if this means that enabling RS485 mode is not required in this configuration, can the FTDI cable be bypassed entirely by using Raspberry Pi's built-in UARTs combined with a chip like ZT485EEN?
Sure, you can do that. There are also many different models of RS485 transcievers that you could use; Electronics.SE would the the place to ask for more information on that. You may need to enable RS485 at that point with TIOCSRS485, but that's going to be driver-dependent. I don't know about the Pi, but at least on some Atmel chips that I have used before setting the RS485 mode sets a certain bit in the peripheral on the chip that automatically toggles the RTS pin to enable/disable the RS485 transciever; otherwise, Linux needs to toggle a GPIO in order to set the transciever into the correct state.
Specifically on the FTDI, there are GPIOs that can be set that will turn on/off at appropriate times. One of these is the TXDEN signal, which controls the transciever for you automatically. Others are used for the Tx/Rx LEDs.
There’s no “rs485” mode. Just forget about it and everything will be OK. RS485 is just an electrical standard, and the ZT485 does the electrical translation from logic levels to differential signaling and back. You could use that chip (or any equivalent) directly with the UART pins on the Raspberry PI: those are not RS232 nor RS485, just bare asynchronous logic level UART pins. Your assertion that Raspberry PI “doesn’t support” RS485 is meaningless: it doesn’t support RS232 either, and it’s not supposed to. Those electrical standards require level translation/interface chips, and the “other side” is always the same: logic level asynchronous serial streams and control lines. The only “pitfall” is choosing the proper logic levels (3.3V be 5V - I don’t offhand remember what does RPI support).

Using spi-bitbang driver

I am writing a kernel module to read and write to SPI device (CC1200).
My linux device does not have native SPI, so I am trying to bit-bang the bus.
I found that linux has built-in bitbang code (linux/spi/spi_bitbang.h), but I am confused how to set it up. It needs structs as spi_device and spi_master, each requiring struct device, which requires structs as kobject and many many more, most of them I have no idea what to do with them, and how they are needed for simple bit-banging.
I have looked online for examples, but i found literally none. Not a single use of the included bitbang code, only some references that it is "easy"
I will be very thankful for any help, maybe the bitbang lib is not even the good path. Maybe I can write my own (how to do it efficiently? I have 4 cores, but it is running lots of stuff in the background)
Thanks
Because of the nature of SPI where data is clocked and read by the master there is nothing wrong with the bit banging driver for the master, as the slave should not relay on a stable clock. But of course it depends on the slave device if this will work in practice or not.
If you are using the linux kernel there is no need to implement your own bit-banging driver as there already is one spi-gpio.c
My guess how to get it up and running would be by defining what GPIO pins to use in the devicetree, then the driver would be able to act as any of the other physical layer drivers.
I had a quick glance at drivers/spi/spi-gpio.c source code, and there is even a short user guide how to directly access the GPIO pins inline without using the generic GPIO layer overhead.
/*
* Because the overhead of going through four GPIO procedure calls
* per transferred bit can make performance a problem, this code
* is set up so that you can use it in either of two ways:
*
* - The slow generic way: set up platform_data to hold the GPIO
* numbers used for MISO/MOSI/SCK, and issue procedure calls for
* each of them. This driver can handle several such busses.
*
* - The quicker inlined way: only helps with platform GPIO code
* that inlines operations for constant GPIOs. This can give
* you tight (fast!) inner loops, but each such bus needs a
* new driver. You'll define a new C file, with Makefile and
* Kconfig support; the C code can be a total of six lines:
*
* #define DRIVER_NAME "myboard_spi2"
* #define SPI_MISO_GPIO 119
* #define SPI_MOSI_GPIO 120
* #define SPI_SCK_GPIO 121
* #define SPI_N_CHIPSEL 4
* #include "spi-gpio.c"
*/
PS are you sure your platform does not have spi, all the SoC I have worked with from HiSilicon have had one. I would double check this first
EDIT: It seems they've changed the interface and you can't do this any more in modern kernels from 4.19 and later, for the same reason you can't do it with i2c.
https://forum.openwrt.org/t/i2c-kernel-4-19-i2c-gpio-custom/49213
I will leave this here for now, perhaps it will be useful. I myself am using older kernels for home automation but it's on a private network.
My original answer:
Whilst you can probably get this working by hacking your own kernel module together instead you can investigate spi-gpio-custom, simply load the module and pass the pins you want to use as parameters, you can do everything at run-time and don't need to 'compile-in' the pins you want to use. You can find this module in the OpenWrt project:
https://github.com/openwrt/openwrt/tree/openwrt-19.07/package/kernel/spi-gpio-custom/src
I would expect that to give you some kind of SPI device when initialised that you can write to from user-space. Note that I haven't used this module myself, but some time ago I've used the i2c counterpart which works in similar way.
Alternatively, you could consider introducing an Arduino to talk to your SPI bus then translate the SPI data into something your Linux device understands.
The Nano board will probably do what you need and costs peanuts if you don't want to make up your own board.
Then for the interface, you would then have a few choices: USB, UART, i2c or 1wire even a parallel interface if you have the pins. There is a 1-wire slave library on github for instance: https://github.com/smurfix/owslave.

How to call Linux kernel driver functions from a userspace program?

How can I write a C program (in userspace) to call functions that are part of a kernel driver? If it's not possible to do directly, how else do I do it?
CONTEXT: I am trying to use the PWM pins of my single-board computer (Intel NUC DE3815TYBE) so that I can control fans. A linux driver called pwm_lpss allows control of these pins (driver developed by Intel, source code here). I have verified that this driver is installed by using the lsmod command. Here is the driver information after typing modinfo pwm_lpss:
filename: /lib/modules/3.19.0-25-generic/kernel/drivers/pwm/pwm-lpss.ko
license: GPL v2
author: Mika Westerberg <mika.westerberg#linux.intel.com>
description: PWM driver for Intel LPSS
srcversion: 44AA14AF3E2F96C813770A8
depends:
intree: Y
vermagic: 3.19.0-25-generic SMP mod_unload modversions
signer: Magrathea: Glacier signing key
sig_key: 6A:AA:11:D1:8C:2D:3A:40:B1:B4:DB:E5:BF:8A:D6:56:DD:F5:18:38
sig_hashalgo: sha512
So I know where the driver module is (the pwm-lpss.ko file) and I have the source code which I know has a function in it called pwm_lpss_config() that I'd like to use. How do I call the function from my userspace C program? How would I go about #including it? Or is this not possible to do from userspace?
Unfortunately Intel has provided zero documentation for how to use this driver. I thought drivers normally map their functionality to some user-accessible file. I was able to find some PWM-related files after some digging, but I haven't been able to find a file that looks like it can set PWM duty cycle/frequency.
It's a standard Linux PWM driver, so no special documentation is necessary.
Check the /sys/class/pwm/ directory. (/sys is the interface the kernel provides for access to its data structures. It just looks and acts like a filesystem.) You should have something like /sys/class/pwm/pwmchip0/. Each such directory corresponds to a PWM chip.
The directory will have the following entries. You may need superuser privileges to access these (as you wouldn't want everybody to mess with them):
npwm: Read this to find out how many PWM channels this chip has.
export: Write a channel number (0 to whatever-the-number-in-npwm-1) to make that channel available via this sysfs interface
unexport: Write a channel number to remove the channel from sysfs interface control
Each PWM channel exported to be used via the sysfs interface will show up as a subdirectory named pwmN, where N is the channel number. Here, you can read and write to entries
period: Total period (off + on) in nanoseconds.
duty_cycle: On time in nanoseconds. Must be less than period.
polarity: If the chip supports reversing the signal polarity, you can write inversed here to invert the polarity; normal is the default/normal polarity.
enable: 1 if enabled, 0 if disabled.
When reading or writing to these entries, no special locking is necessary. The kernel will receive all data in one write(), and return all data in one read() operation. When a write() succeeds, the kernel has applied the setting.
some ioctl ? The ioctl() function manipulates the underlying device parameters of special files.
Along the lines
fd = open("/dev/pwm0", O_RDONLY); // put whatever device you've got
if (ioctl(fd, STATUSGET, &status) == -1) // magic constant should be set
....
} else {
....
}

Kernel level memory handling coding

My requirement is to store data in kernel..Data are incoming packets from networks..which may be different in size and have to store for example 250ms duration..and there should be 5 such candidate for which kernel level memory management is required..since packets are coming very fast..my approach is to allocate a large memory say 2mb memory for each such candidate..bez kmalloc and kfree have timing overhead..any help regarding that?
sk_buffs are a generic answer that is network related or as Mike points out a kernel memory cache is even more generic answer to your question. However, I believe you may have put a solution before the question.
The bottle neck with LTE/HSDPA/GSM is the driver and how you get data from the device to the CPU. This depends on how hardware is connected. Are you using SPI, UART, SDHC, USB, PCI?
Also, at least with HSDPA, you need a ppp connection. Isn't LTE the same? Ethernet is not the model to use in this case. Typically you need to emulate a high speed tty. Also, n_gsm supplies a network interface; I am not entirely familiar with this interface, but I suspect that this is to support LTE. This is not well documented. Also, there is the Option USB serial driver, if this is the hardware you are using. An example patch using n_gsm to handle LTE; I believe this patch was reworked into the current n_gsm network support.
You need to tell us more about your hardware.
As already noted within the comments:
struct sk_buff, and it is created for that exact specific purpose
see for example http://www.linuxfoundation.org/collaborate/workgroups/networking/skbuff

Linux device model: Same device but different drivers

I'm customising Linux for an ARM9 Atmel AT91SAM960 board.
In the device file Atmel named all the USART the same atmel_usart. Of course with id enumeration:
static struct platform_device at91sam9260_uart0_device = {
.name = "atmel_usart",
.id = 1,
.dev = { ...}
}
According to the Linux Device model, all these devices (5 UARTS on a SAM9260) would be bind to the driver named atmel_usart.
I don't want to set a TTYS driver on all UARTS which will be registerd. I have several own drivers which serve for different specialised purposes (LON, RS-485 etc.) I want the control which driver does serve a certain USART. So what could I do:
The Atmel device files are unsatisfiable and I can do it better. So I rename (patch) the devices in the device file. However, in case I want a TTYS driver on UART4 I would be in trouble.
I manipulate (patch) the device file,
so that I'm able the access the
structures platform_device. I could
change their names before I would
register them. But as far as I
understood the idea of the Linux Driver Model,
devices should be
registered early during boot-up but the binding to a driver follows .... later.
I could write a driver, which has an
alias name and which would be binded
to a specific bus_Id ->
atmel_usart.4. Can I really?
What solutions else exist. I want to touch a minimal set of Kernel files but I want all the freedom possible?
Addendum what freedom means to me: I can specify at runtime how the UARTS can be used
with the Atmel-Serial driver (ttyS)
with my own drivers
It means also, that changes to the kernel source are minimal.
I built my own line discipline drivers. You can build them as kernel modules and attach them to the UARTs at runtime. No changes to the Linux source are necessary.
Any funny timing or control stuff can be done through ioctl(). Specifically, I implemented a timing-sensitive RS-485 protocol in this way.
When I did this (Linux 2.6.17) there was no dynamic registration mechanism, so I overwrote the existing line disciplines. The Linux code is (was) pretty straightforward, and I was satisfied that this would be a safe thing to do.
Your problem is quite easily solved. The 5 UART devices are presently registered at kernel startup and their function is locked. This is now how it normally works for PCI or USB devices, right? So what you need to do is pull the device registration out of the startup code and register it dynamically. You can even register/unregister as needed.
at91_register_uart() is being called from your board file for every UART that needs registered. at91_add_device_serial() will then platform_device_register all those you what setup. One solution is to let at91_register_uart() be called for all 5 UARTS, but then remove the call to at91_add_device_serial() from your board. You can then make it an exported function that can be called by your loadable drivers. You can even add an argument to it (int) so that instead of looping on all UARTS, you can select which ones to register individually. You can also mirror this function by making one that unregisters the devices.
NOTE: I think you'll need to always leave one UART dedicated as your console, if you are using one that way. You could probably hide that in the exported function by only allowing index 0->3 as in input and then mapping 0->3 to 0-4, skipping the UART that you want to use for console.

Resources