Attempt uio with devmem. I give up on UIO for now

This commit is contained in:
Ciro Santilli
2017-08-05 23:06:47 +01:00
parent c6edbfddb0
commit 879001563a
4 changed files with 101 additions and 13 deletions

View File

@@ -79,6 +79,7 @@ BR2_PACKAGE_DEVMEM2=y
#
# hexdump /sys/bus/pci/devices/0000:00:05.0/config
#
# and /dev/mem can of course do both reads and writes,
# but setpci provies nice human readable register names, e.g.:
#
# setpci --dumpregs

View File

@@ -60,6 +60,10 @@ Class: pure magic: https://www-s.acm.illinois.edu/sigops/2007/roll_your_own/7.c.
TODO: does it have any side effects? Set in the edu device at:
k->class_id = PCI_CLASS_OTHERS
## Play with registers from the CLI
Use setpci, devmem2 and /sys.
*/
#include <asm/uaccess.h> /* put_user */

View File

@@ -1,19 +1,32 @@
/*
Adapted from: https://yurovsky.github.io/2014/10/10/linux-uio-gpio-interrupt/
TODO get working. Currently I don't understand the behaviour.
modprobe uio_pci_generic
echo '1234 11e9' > /sys/bus/pci/drivers/uio_pci_generic/new_id
/uio_read.out &
TODO how to ACK interrupts? How to ensure that every interrupt gets handled separately?
TODO get working. The problem now is how to generate IRQs to test our IRQ handling:
- a synchronous IRQ needs regwrites to be kicked off, but mmap does not seem to work with this driver
- a custom PCI periodic timer device would also need to be initiazed by some regwrite, otherwise
early interrupts before the OS is setup would crash everything?
TODO write to registers. Currently using /dev/mem and lspci.
Handle interrupts from userland and print a message to stdout.
- Userland driver
- https://stackoverflow.com/questions/15286772/userspace-vs-kernel-space-driver
- https://01.org/linuxgraphics/gfx-docs/drm/driver-api/uio-howto.html
- https://stackoverflow.com/questions/7986260/linux-interrupt-handling-in-user-space
- https://yurovsky.github.io/2014/10/10/linux-uio-gpio-interrupt/
- https://github.com/bmartini/zynq-axis/blob/65a3a448fda1f0ea4977adfba899eb487201853d/dev/axis.c
- https://yurovsky.github.io/2014/10/10/linux-uio-gpio-interrupt/
- http://nairobi-embedded.org/uio_example.html that website has QEMU examples for everything as usual. The example has a kernel-side which creates the memory mappings and is used by the user.
Userland driver stability questions:
- https://stackoverflow.com/questions/8030758/getting-kernel-version-from-linux-kernel-module-at-runtime/45430233#45430233
- https://stackoverflow.com/questions/37098482/how-to-build-a-linux-kernel-module-so-that-it-is-compatible-with-all-kernel-rele/45429681#45429681
- https://liquidat.wordpress.com/2007/07/21/linux-kernel-2623-to-have-stable-userspace-driver-api/
*/
#if 1
/* Adapted from: https://yurovsky.github.io/2014/10/10/linux-uio-gpio-interrupt */
#define _XOPEN_SOURCE 700
#include <fcntl.h> /* open */
#include <stdint.h>
@@ -28,7 +41,6 @@ Handle interrupts from userland and print a message to stdout.
int main(int argc, char **argv)
{
char *dev = "/dev/uio0";
if (argc > 1) {
dev = argv[1];
@@ -58,9 +70,65 @@ int main(int argc, char **argv)
}
nb = read(fd, &info, sizeof(info));
if (nb == sizeof(info)) {
printf("Interrupt #%u\n", info);
printf(__FILE__ " read = %u\n", info);
}
}
close(fd);
exit(EXIT_SUCCESS);
}
#else
/* Ripped from the kernel docs. */
#define _XOPEN_SOURCE 700
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <unistd.h>
int main()
{
int uiofd;
int configfd;
int err;
int i;
unsigned icount;
unsigned char command_high;
uiofd = open("/dev/uio0", O_RDONLY);
if (uiofd < 0) {
perror("uio open:");
return errno;
}
configfd = open("/sys/class/uio/uio0/device/config", O_RDWR);
if (configfd < 0) {
perror("config open:");
return errno;
}
err = pread(configfd, &command_high, 1, 5);
if (err != 1) {
perror("command config read:");
return errno;
}
command_high &= ~0x4;
for(i = 0;; ++i) {
fprintf(stderr, "Interrupts: %d\n", icount);
err = pwrite(configfd, &command_high, 1, 5);
if (err != 1) {
perror("config write:");
break;
}
err = read(uiofd, &icount, 4);
if (err != 4) {
perror("uio read:");
break;
}
}
return errno;
}
#endif

15
rootfs_overlay/uio_read.sh Executable file
View File

@@ -0,0 +1,15 @@
#!/bin/sh
set -ex
modprobe uio_pci_generic
# pci_min device
echo '1234 11e9' > /sys/bus/pci/drivers/uio_pci_generic/new_id
/uio_read.out &
# Helper to observe interrupts.
insmod /irq.ko
base="$(setpci -d 1234:11e9 BASE_ADDRESS_0)"
# Start generating interrupt.
/devmem3.out "0x${base}" w 0x12345678
# Stop generating interrupt.
/devmem3.out "0x$(($base + 4))" w 0x12345678
/devmem3.out "0x${base}" w 0x12345678
/devmem3.out "0x$(($base + 4))" w 0x12345678