In this post I will explain the necessary steps needed to port a ethernet driver from FreeBSD to rtems-libbsd. There are few changes we need to make to be able to compile the driver.
I will be using cpsw ethernet driver for BBB as reference. Follow the below steps
Whenever we edit a header file or c file, we need to add the changes under #if defined __rtems__.
The code on FreeBSD needs to go under the #else part.
1. Copy the driver files from FreeBSD to appropriate destination in rtems-libbsd
I copied it to "freebsd/sys/arm/ti/cpsw"
2. Include the added files in Makefile
"LIB_C_FILES += freebsd/sys/arm/ti/cpsw/if_cpsw.c"
3. Add the following header file for any c file you are including
"#include <machine/rtems-bsd-kernel-space.h>"
4. At this stage, your driver is included for compilation. start compilation
"make clean && make"
5. You will get several errors. You will need to resolve the errors one by one. The errors that come
are dependent on the driver. I will explain some of the common errors.
support these. We need to remove all functions and variables related to sysctl handling.
involves supplying device tree information during boot time using a special configuration file.
RTEMS do not have this support yet, we need to remove those dependencies. Commonly they
are seen in probe and attach functions
c. In attach functions, we may get the phy address from FDT. This phy address is used during
mii_attach. We can give MII_PHY_ANY in mii_attach. It will loop through all the possible
addresses and will find the correct phy.
4. There may some other dependencies on other drivers or some other modules which is defined
FreeBSD but not needed in RTEMS. You can define equivalent functions as per the
requirement. I defined my own functions to read the mac address.
I will be using cpsw ethernet driver for BBB as reference. Follow the below steps
Whenever we edit a header file or c file, we need to add the changes under #if defined __rtems__.
The code on FreeBSD needs to go under the #else part.
STEPS
1. Copy the driver files from FreeBSD to appropriate destination in rtems-libbsd
I copied it to "freebsd/sys/arm/ti/cpsw"
2. Include the added files in Makefile
"LIB_C_FILES += freebsd/sys/arm/ti/cpsw/if_cpsw.c"
3. Add the following header file for any c file you are including
"#include <machine/rtems-bsd-kernel-space.h>"
4. At this stage, your driver is included for compilation. start compilation
"make clean && make"
5. You will get several errors. You will need to resolve the errors one by one. The errors that come
are dependent on the driver. I will explain some of the common errors.
Common Issues
a. Sysctl
The FreeBSD driver usually add sysctls to get stats and adjust variables. RTEMS do notsupport these. We need to remove all functions and variables related to sysctl handling.
b. OFW/FDT
Open Firmware(OFW)/ Flattened Device Tree (FDT) dependency. FreeBSD supports FDTinvolves supplying device tree information during boot time using a special configuration file.
RTEMS do not have this support yet, we need to remove those dependencies. Commonly they
are seen in probe and attach functions
c. In attach functions, we may get the phy address from FDT. This phy address is used during
mii_attach. We can give MII_PHY_ANY in mii_attach. It will loop through all the possible
addresses and will find the correct phy.
4. There may some other dependencies on other drivers or some other modules which is defined
FreeBSD but not needed in RTEMS. You can define equivalent functions as per the
requirement. I defined my own functions to read the mac address.
Simplebus vs nexus
RTEMS has a well defined nexus bus support. It will be the one that will be attaching to root and other drivers will be attaching to this bus. Simplebus interface is not present in RTEMS. Simplebus is usually the bus related to OFW interface. So when we have to port a driver based on simplebus we have two options
1. Port simplebus interface to rtems-libbsd
2. Modify the driver to nexus bus
I took the option to modify the bus to use the nexus bus. For this you need to make the following changes
1. In the DRIVER_MODULE definition, we use nexus instead of simplebus
#ifndef __rtems__
DRIVER_MODULE(cpsw, simplebus, cpsw_driver, cpsw_devclass, 0, 0);
#else
DRIVER_MODULE(cpsw, nexus, cpsw_driver, cpsw_devclass, 0, 0);
#endif
2. Next thing we need to define the resource structure which will inform the driver the base address
to be used for bus handles and irq to be used for the device. The resource should have the
following details the memory map address and the irq and their numbers to be used by the
driver. Cpsw driver starts at 0x4a100000 and have 4 irq's starting at 40.
In the file rtemsbsd/include/bsp/nexus-devices.h
#elif defined(LIBBSP_ARM_BEAGLE_BSP_H)
static const rtems_bsd_device_resource cpsw0_res[] = {
{
.type = RTEMS_BSD_RES_MEMORY,
.start_request = 0,
.start_actual = 0x4a100000 /*Memory map address of the ethernet*/
}, {
.type = RTEMS_BSD_RES_IRQ,
.start_request = 0,
.start_actual = 0x28
},
{
.type = RTEMS_BSD_RES_IRQ,
.start_request = 1,
.start_actual = 0x29
},
{
.type = RTEMS_BSD_RES_IRQ,
.start_request = 2,
.start_actual = 0x2a
},
{
.type = RTEMS_BSD_RES_IRQ,
.start_request = 3,
.start_actual = 0x2b
}
};
3. Define the following macro below the resource structure
RTEMS_BSD_DEFINE_NEXUS_DEVICE(cpsw, 0, RTEMS_ARRAY_SIZE(cpsw0_res),
&cpsw0_res[0]);
This is needed because, we use SYSINIT feature of FreeBSD. With this definition, we will be
automatically loaded during boot time. For more details see libbsd.txt file.
With these changes we moved to nexus bus.
4. You may need to port the phy driver also from FreeBSD. For me I needed smscphy. So I added smscphy.c to rtems-libbsd and included it in compilation.
5. We need to make sure the phy device get attached to miibus. for this we define
SYSINIT_DRIVER_REFERENCE(smscphy, miibus) in the same nexus device file.
With this we should be able to form a proper device tree.
LOG
Below is the log I got. Ignore the Failed to read PHY messages. Since we gave MII_PHY_ANY during attach, it tries different address so we getting failed messages
## Transferring control to RTEMS (at address 80000000) ...
RTEMS Beagleboard: am335x-based
*** LIBBSD INIT 1 TEST ***
RTEMS Shell on /dev/console. Use 'help' to list commands.
[/] # nexus0: <RTEMS Nexus device>
cpsw0: <3-port Switch Ethernet Subsystem> on nexus0
00:00:00 cpsw_attach
cpsw0: device parent is present
cpsw0: CPSW SS Version 1.12 (0)
cpsw0: Initial queue size TX=128 RX=384
cpsw0: MAC HI ce04a578
cpsw0: MAC Low f531
devctl: !system=IFNET subsystem=cpsw0 type=ATTACH
cpsw0: Ethernet address: -2144597976
cpsw0: Failed to read from PHY.
cpsw0: Failed to read from PHY.
cpsw0: Failed to read from PHY.
cpsw0: Failed to read from PHY.
cpsw0: Failed to read from PHY.
cpsw0: Failed to read from PHY.
miibus0: <MII bus> on cpsw0
smscphy0: <SMC LAN8710A 10/100 interface> PHY 0 on miibus0
smscphy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto
devctl: +smscphy0 at phyno=0 oui=0x800f model=0xf rev=0x1 on miibus0
devctl: +miibus0 at on cpsw0
devctl: +cpsw0 at on nexus0
devctl: +nexus0 at on root0
devctl: !system=IFNET subsystem=lo0 type=ATTACH
IRQ defined can be seen using irq command
[/] # irq
-------------------------------------------------------------------------------
INTERRUPT INFORMATION
--------+----------------------------------+---------+------------+------------
VECTOR | INFO | OPTIONS | HANDLER | ARGUMENT
--------+----------------------------------+---------+------------+------------
40 | cpsw0 | UNIQUE | 0x800d8788 | 0x802c5428
41 | cpsw0 | UNIQUE | 0x800d8788 | 0x802c5460
43 | cpsw0 | UNIQUE | 0x800d8788 | 0x802c5498
67 | Clock | UNIQUE | 0x800d7684 | 0x00000000
72 | NS16550 | SHARED | 0x800d945c | 0x00000000
--------+----------------------------------+---------+------------+------------
hi ragu, i am a student from china, and i have some question during porting the driver from freebsd to rtems-libbsd, can you help me? thanks
ReplyDelete