aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormcayland-ntx <mark.caveayland@nutanix.com>2025-10-22 00:17:36 +0100
committerGitHub <noreply@github.com>2025-10-22 00:17:36 +0100
commitca9943be5c18ed230f9d4674cc223d1e194f6d23 (patch)
treed62b9562d5d83054dc541c5df628e55fead1d483
parentd7cb436ffb0606fec6ec65e6087fae33e777913a (diff)
downloadlibvfio-user-master.zip
libvfio-user-master.tar.gz
libvfio-user-master.tar.bz2
samples: improve gpio-pci-idio-16 emulation (#821)HEADmaster
Newer kernels implement read register caching for the gpio-pci-idio-16 which means that the pin counter is never incremented, making it impossible to change the input register for testing. Improve the gpio-pci-idio-16 emulation so that the input and output registers match those of the real hardware, and update the logic so that toggling an output line 3 times will toggle the corresponding input line to allow testing individual inputs and outputs. Signed-off-by: Mark Cave-Ayland <mark.caveayland@nutanix.com>
-rw-r--r--samples/gpio-pci-idio-16.c53
1 files changed, 49 insertions, 4 deletions
diff --git a/samples/gpio-pci-idio-16.c b/samples/gpio-pci-idio-16.c
index 6c4e99b..739e242 100644
--- a/samples/gpio-pci-idio-16.c
+++ b/samples/gpio-pci-idio-16.c
@@ -51,17 +51,62 @@ _log(vfu_ctx_t *vfu_ctx UNUSED, UNUSED int level, char const *msg)
fprintf(stderr, "gpio: %s\n", msg);
}
-static int pin;
+static int pin[16];
bool dirty = true;
static ssize_t
bar2_access(vfu_ctx_t *vfu_ctx UNUSED, char * const buf,
size_t count, loff_t offset, const bool is_write)
{
- if (offset == 0 && !is_write)
- buf[0] = pin++ / 3;
+ int i;
+
+ if (is_write) {
+ /* Output registers are 0x0 and 0x4 */
+ switch (offset) {
+ case 0x0:
+ /* Output pins 0-7 */
+ for (i = 0; i < 8; i++) {
+ if (buf[0] & (1 << i)) {
+ pin[i]++;
+ }
+ }
+ break;
+
+ case 0x4:
+ /* Output pins 8-15 */
+ for (i = 0; i < 8; i++) {
+ if (buf[0] & (1 << i)) {
+ pin[i + 8]++;
+ }
+ }
+ break;
+ }
- dirty = true;
+ dirty = true;
+ } else {
+ /* Input registers are 0x1 and 0x5 */
+ switch (offset) {
+ case 0x1:
+ /* Input pins 0-7 */
+ buf[0] = 0;
+ for (i = 0; i < 8; i++) {
+ if ((pin[i] % 3) == 0) {
+ buf[0] |= (1 << i);
+ }
+ }
+ break;
+
+ case 0x5:
+ /* Input pins 8-15 */
+ buf[0] = 0;
+ for (i = 0; i < 8; i++) {
+ if ((pin[i + 8] % 3) == 0) {
+ buf[0] |= (1 << i);
+ }
+ }
+ break;
+ }
+ }
return count;
}