From 021d41cfbae6dc6ea8a2dda1382c34d656668ba5 Mon Sep 17 00:00:00 2001 From: GuEe-GUI <2991707448@qq.com> Date: Thu, 28 Nov 2024 14:37:12 +0800 Subject: [PATCH] Port to RT-Thread Smart DM PCI Signed-off-by: GuEe-GUI <2991707448@qq.com> --- README | 1 + lib/Makefile | 4 + lib/configure | 7 ++ lib/init.c | 6 ++ lib/internal.h | 3 +- lib/pci.h | 1 + lib/rt-thread-smart-dm.c | 222 +++++++++++++++++++++++++++++++++++++++ pcilib.man | 12 +++ 8 files changed, 255 insertions(+), 1 deletion(-) create mode 100644 lib/rt-thread-smart-dm.c diff --git a/README b/README index 549d9cd..c4ab994 100644 --- a/README +++ b/README @@ -33,6 +33,7 @@ In runs on the following systems: DOS/DJGPP (via i386 ports) SylixOS (via /proc/pci) AmigaOS on PPC (via Expansion library) + RT-Thread Smart (via /proc/pci) It should be very easy to add support for other systems as well (volunteers wanted; if you want to try that, I'll be very glad to see the patches and diff --git a/lib/Makefile b/lib/Makefile index 8dba53e..3ed5e45 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -95,6 +95,10 @@ ifdef PCI_HAVE_PM_AOS_EXPANSION OBJS += aos-expansion endif +ifdef PCI_HAVE_PM_RT_THREAD_SMART_DM +OBJS += rt-thread-smart-dm +endif + all: $(PCILIB) $(PCILIBPC) ifeq ($(SHARED),no) diff --git a/lib/configure b/lib/configure index a4909e1..4aad925 100755 --- a/lib/configure +++ b/lib/configure @@ -235,6 +235,13 @@ case $sys in IDSDIR="DEVS:" echo >>$m 'CC=gcc' ;; + rt_thread_smart) + echo >>$c '#define PCI_PATH_RT_THREAD_SMART_DM "/proc/pci"' + echo >>$c '#define PCI_HAVE_64BIT_ADDRESS' + echo >>$c '#define PCI_HAVE_PM_RT_THREAD_SMART_DM' + IDSDIR="/etc/pci" + LIBRESOLV= + ;; *) echo " Unfortunately, your OS is not supported by the PCI Library" exit 1 diff --git a/lib/init.c b/lib/init.c index c26720a..b0e5018 100644 --- a/lib/init.c +++ b/lib/init.c @@ -163,6 +163,11 @@ static struct pci_methods *pci_methods[PCI_ACCESS_MAX] = { #else NULL, #endif +#ifdef PCI_HAVE_PM_RT_THREAD_SMART_DM + &pm_rt_thread_smart_dm, +#else + NULL, +#endif }; // If PCI_ACCESS_AUTO is selected, we probe the access methods in this order @@ -181,6 +186,7 @@ static int probe_sequence[] = { PCI_ACCESS_WIN32_KLDBG, PCI_ACCESS_WIN32_SYSDBG, PCI_ACCESS_AOS_EXPANSION, + PCI_ACCESS_RT_THREAD_SMART_DM, // Low-level methods poking the hardware directly PCI_ACCESS_ECAM, PCI_ACCESS_I386_TYPE1, diff --git a/lib/internal.h b/lib/internal.h index 996b80d..43be8d1 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -144,6 +144,7 @@ extern struct pci_methods pm_intel_conf1, pm_intel_conf2, pm_linux_proc, pm_fbsd_device, pm_aix_device, pm_nbsd_libpci, pm_obsd_device, pm_dump, pm_linux_sysfs, pm_darwin, pm_sylixos_device, pm_hurd, pm_mmio_conf1, pm_mmio_conf1_ext, pm_ecam, - pm_win32_cfgmgr32, pm_win32_kldbg, pm_win32_sysdbg, pm_aos_expansion; + pm_win32_cfgmgr32, pm_win32_kldbg, pm_win32_sysdbg, pm_aos_expansion, + pm_rt_thread_smart_dm; #endif diff --git a/lib/pci.h b/lib/pci.h index 58fd5b4..f41bc3c 100644 --- a/lib/pci.h +++ b/lib/pci.h @@ -56,6 +56,7 @@ enum pci_access_type { PCI_ACCESS_MMIO_TYPE1_EXT, /* MMIO ports, type 1 extended */ PCI_ACCESS_ECAM, /* PCIe ECAM via /dev/mem */ PCI_ACCESS_AOS_EXPANSION, /* AmigaOS Expansion library */ + PCI_ACCESS_RT_THREAD_SMART_DM, /* RT-Thread Smart pci */ PCI_ACCESS_MAX }; diff --git a/lib/rt-thread-smart-dm.c b/lib/rt-thread-smart-dm.c new file mode 100644 index 0000000..71c5e0c --- /dev/null +++ b/lib/rt-thread-smart-dm.c @@ -0,0 +1,222 @@ +/* + * The PCI Library -- Direct Configuration access via RT-Thread Smart DM Ports + * + * Copyright (c) 2024 RT-Thread Development Team + * + * Can be freely distributed and used under the terms of the GNU GPL v2+. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" + +static void +rt_thread_smart_dm_config(struct pci_access *a) +{ + pci_define_param(a, "rt-thread-smart-dm.path", PCI_PATH_RT_THREAD_SMART_DM, + "Path to the RT-Thread Smart PCI device"); +} + +static int +rt_thread_smart_dm_detect(struct pci_access *a) +{ + char *name = pci_get_param(a, "rt-thread-smart-dm.path"); + + if (access(name, R_OK)) + { + a->warning("Cannot open %s", name); + return 0; + } + + a->debug("...using %s", name); + return 1; +} + +static void +rt_thread_smart_dm_init(struct pci_access *a) +{ + a->fd = -1; +} + +static void +rt_thread_smart_dm_cleanup(struct pci_access *a UNUSED) +{ + if (a->fd >= 0) + { + close(a->fd); + a->fd = -1; + } +} + +static void +rt_thread_smart_dm_scan(struct pci_access *a) +{ + FILE *f; + char buf[512]; + + if (snprintf(buf, sizeof(buf), "%s/devices", pci_get_param(a, "rt-thread-smart-dm.path")) == sizeof(buf)) + a->error("File name too long"); + + f = fopen(buf, "r"); + if (!f) + a->error("Cannot open %s", buf); + + while (fgets(buf, sizeof(buf)-1, f)) + { + struct pci_dev *d = pci_alloc_dev(a); + unsigned int dfn, vend, cnt, known; + char *driver; + int offset; + +#define F " %016" PCI_U64_FMT_X + cnt = sscanf(buf, "%x %x %x" F F F F F F F F F F F F F F "%n", + &dfn, + &vend, + &d->irq, + &d->base_addr[0], + &d->base_addr[1], + &d->base_addr[2], + &d->base_addr[3], + &d->base_addr[4], + &d->base_addr[5], + &d->rom_base_addr, + &d->size[0], + &d->size[1], + &d->size[2], + &d->size[3], + &d->size[4], + &d->size[5], + &d->rom_size, + &offset); +#undef F + if (cnt != 9 && cnt != 10 && cnt != 17) + a->error("proc: parse error (read only %d items)", cnt); + d->bus = dfn >> 8U; + d->dev = PCI_SLOT(dfn & 0xff); + d->func = PCI_FUNC(dfn & 0xff); + d->vendor_id = vend >> 16U; + d->device_id = vend & 0xffff; + known = 0; + if (!a->buscentric) + { + known |= PCI_FILL_IDENT | PCI_FILL_IRQ | PCI_FILL_BASES; + if (cnt >= 10) + known |= PCI_FILL_ROM_BASE; + if (cnt >= 17) + known |= PCI_FILL_SIZES; + } + if (cnt >= 17) + { + while (buf[offset] && isspace(buf[offset])) + ++offset; + driver = &buf[offset]; + while (buf[offset] && !isspace(buf[offset])) + ++offset; + buf[offset] = '\0'; + if (driver[0]) + { + pci_set_property(d, PCI_FILL_DRIVER, driver); + known |= PCI_FILL_DRIVER; + } + } + d->known_fields = known; + pci_link_dev(a, d); + } + + fclose(f); +} + +static int +rt_thread_smart_dm_setup(struct pci_dev *d, int rw) +{ + struct pci_access *a = d->access; + + if (a->cached_dev != d || a->fd_rw < rw) + { + char buf[1024]; + int e; + if (a->fd >= 0) + close(a->fd); + e = snprintf(buf, sizeof(buf), "%s/%04x:%02x:%02x.%u", + pci_get_param(a, "rt-thread-smart-dm.path"), + d->domain, d->bus, d->dev, d->func); + if (e < 0 || e >= (int) sizeof(buf)) + a->error("File name too long"); + a->fd_rw = a->writeable || rw; + a->fd = open(buf, a->fd_rw ? O_RDWR : O_RDONLY); + if (a->fd < 0) + a->warning("Cannot open %s", buf); + a->cached_dev = d; + } + return a->fd; +} + +static int +rt_thread_smart_dm_read(struct pci_dev *d, int pos, byte *buf, int len) +{ + int fd = rt_thread_smart_dm_setup(d, 0); + int res; + + if (fd < 0) + return 0; + res = pread(fd, buf, len, pos); + if (res < 0) + { + d->access->warning("%s: read failed: %s", __func__, strerror(errno)); + return 0; + } + else if (res != len) + return 0; + return 1; +} + +static int +rt_thread_smart_dm_write(struct pci_dev *d, int pos, byte *buf, int len) +{ + int fd = rt_thread_smart_dm_setup(d, 1); + int res; + + if (fd < 0) + return 0; + res = pwrite(fd, buf, len, pos); + if (res < 0) + { + d->access->warning("%s: write failed: %s", __func__, strerror(errno)); + return 0; + } + else if (res != len) + { + d->access->warning("%s: tried to write %d bytes at %d, but only %d succeeded", __func__, len, pos, res); + return 0; + } + return 1; +} + +static void +rt_thread_smart_dm_cleanup_dev(struct pci_dev *d) +{ + if (d->access->cached_dev == d) + d->access->cached_dev = NULL; +} + +struct pci_methods pm_rt_thread_smart_dm = { + .name = "rt-thread-smart-dm", + .help = "RT-Thrad Smart /proc/pci device", + .config = rt_thread_smart_dm_config, + .detect = rt_thread_smart_dm_detect, + .init = rt_thread_smart_dm_init, + .cleanup = rt_thread_smart_dm_cleanup, + .scan = rt_thread_smart_dm_scan, + .fill_info = pci_generic_fill_info, + .read = rt_thread_smart_dm_read, + .write = rt_thread_smart_dm_write, + .cleanup_dev = rt_thread_smart_dm_cleanup_dev, +}; diff --git a/pcilib.man b/pcilib.man index 3b7bff4..71e1050 100644 --- a/pcilib.man +++ b/pcilib.man @@ -159,6 +159,15 @@ https://web.archive.org/web/20110214012715/https://www.microsoft.com/whdc/devtoo .TP .B aos-expansion Access method used on PowerPC Amiga running OS4+. Access is made through Expansion.library. It offers read and write access to configuration space. +.TP +.B rt-thread-smart +The +.B /proc/pci +filesystem provided by RT-Thread Smart OS. This method requires PCI support +(with the procfs feature enabled) to be available in the driver subsystem, +and the DFS v2-based procfs must be mounted in a rootfs-enabled environment. +It provides access to the standard PCI configuration space, with limited +information available. .SH PARAMETERS @@ -188,6 +197,9 @@ Path to the procfs bus tree. .B sysfs.path Path to the sysfs device tree. .TP +.B rt-thread-smart-dm.path +Path to the rt-thread smart DM procfs device tree. +.TP .B devmem.path Path to the /dev/mem device or path to the \\Device\\PhysicalMemory NT section or name of the platform specific physical address access method. Generally on -- 2.39.5