aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAgg242 <olrick.lefebvre@olrick.fr>2024-01-22 17:41:47 +0100
committerMartin Mares <mj@ucw.cz>2024-02-17 23:07:57 +0100
commit5b52ae794a6fcf77363a78a42278da8a4feaf225 (patch)
tree1d1aaf1f77acf799c099ae7106910615b67e40df
parenta997ef132d943990cdb65d32a6605b6ff4bfcd79 (diff)
downloadpciutils-5b52ae794a6fcf77363a78a42278da8a4feaf225.tar.gz
New back-end for AmigaOS on PowerPC
-rw-r--r--README1
-rw-r--r--lib/Makefile4
-rw-r--r--lib/aos-expansion.c238
-rwxr-xr-xlib/configure7
-rw-r--r--lib/init.c24
-rw-r--r--lib/internal.h7
-rw-r--r--lib/pci.h1
-rw-r--r--lib/sysdep.h4
-rw-r--r--pcilib.man3
9 files changed, 288 insertions, 1 deletions
diff --git a/README b/README
index 04e9348..955bd7f 100644
--- a/README
+++ b/README
@@ -32,6 +32,7 @@ In runs on the following systems:
Darwin (via IOKit)
DOS/DJGPP (via i386 ports)
SylixOS (via /proc/pci)
+ AmigaOS on PPC (via Expansion library)
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 a89ac14..bacdbc5 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -75,6 +75,10 @@ ifdef PCI_HAVE_PM_WIN32_SYSDBG
OBJS += win32-sysdbg
endif
+ifdef PCI_HAVE_PM_AOS_EXPANSION
+OBJS += aos-expansion
+endif
+
all: $(PCILIB) $(PCILIBPC)
ifeq ($(SHARED),no)
diff --git a/lib/aos-expansion.c b/lib/aos-expansion.c
new file mode 100644
index 0000000..36a4595
--- /dev/null
+++ b/lib/aos-expansion.c
@@ -0,0 +1,238 @@
+/*
+ * The PCI Library -- Configuration Access via AmigaOS 4.x expansion.library
+ *
+ * Copyright (c) 2024 Olrick Lefebvre <olrick.lefebvre@olrick.fr>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL v2+.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#define _GNU_SOURCE
+
+#include <proto/exec.h>
+#include <exec/types.h>
+#include <proto/expansion.h>
+#include <interfaces/expansion.h>
+
+
+// have to undef PCI values to avoid redefine warning
+#undef PCI_BASE_ADDRESS_MEM_MASK
+#undef PCI_BASE_ADDRESS_IO_MASK
+#undef PCI_ROM_ADDRESS_MASK
+#include <expansion/pci.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/unistd.h>
+
+#include "internal.h"
+
+
+// custom Amiga x.y version tag
+#define VERSTAG "\0$VER: lspci 3.10 (02.01.2024) AmigaOS4 port"
+
+
+/*** AmigaOS access support ***/
+
+typedef struct _PCIAccess {
+ struct ExpansionBase *expansion;
+ struct PCIIFace *ipci;
+} PCIAccess;
+
+static void
+aos_close_pci_interface(struct pci_access *a)
+{
+ PCIAccess *pci;
+
+ pci = (PCIAccess *)a->backend_data;
+ if (pci) {
+ if (pci->expansion) {
+ if (pci->ipci) {
+ IExec->DropInterface((struct Interface *)pci->ipci);
+ pci->ipci = NULL;
+ }
+ IExec->CloseLibrary((struct Library *)pci->expansion);
+ pci->expansion = NULL;
+ }
+ pci_mfree(pci);
+ a->backend_data = NULL;
+ }
+}
+
+static BOOL
+aos_open_pci_interface(struct pci_access *a)
+{
+ PCIAccess *pci;
+ BOOL res = FALSE;
+
+ if (NULL == a->backend_data) {
+ pci = pci_malloc(a, sizeof(PCIAccess));
+ a->backend_data = pci;
+ pci->expansion = (struct ExpansionBase *)IExec->OpenLibrary("expansion.library", 0);
+ if(NULL == pci->expansion) {
+ a->warning("Unable to open expansion.library");
+ aos_close_pci_interface(a);
+ } else {
+ pci->ipci = (struct PCIIFace *)IExec->GetInterface((struct Library *)pci->expansion, "pci", 1, TAG_DONE);
+ if(NULL == pci->ipci) {
+ a->warning("Unable to obtain pci interface");
+ aos_close_pci_interface(a);
+ } else {
+ res = TRUE;
+ }
+ }
+ } else {
+ res = TRUE; // already opened
+ }
+
+ return res;
+}
+
+static int
+aos_expansion_detect(struct pci_access *a)
+{
+ int res = FALSE;
+ struct PCIDevice *device = NULL;
+ PCIAccess *pci;
+
+ if(TRUE == aos_open_pci_interface(a)) {
+ pci = a->backend_data;
+
+ // Try to read PCI first device
+ device = pci->ipci->FindDeviceTags(FDT_Index, 0);
+ if(NULL == device) {
+ a->warning("AmigaOS Expansion PCI interface cannot find any device");
+ aos_close_pci_interface(a);
+ } else {
+ pci->ipci->FreeDevice(device);
+ res = TRUE;
+ }
+ }
+
+ return res;
+}
+
+static void
+aos_expansion_init(struct pci_access *a)
+{
+ // to avoid flushing of version tag
+ static STRPTR USED ver = (STRPTR)VERSTAG;
+
+ if (!aos_open_pci_interface(a)) {
+ a->debug("\n");
+ a->error("AmigaOS Expansion PCI interface cannot be accessed.");
+ }
+}
+
+static void
+aos_expansion_cleanup(struct pci_access *a)
+{
+ aos_close_pci_interface(a);
+}
+
+static void
+aos_expansion_scan(struct pci_access *a)
+{
+ struct PCIDevice *device = NULL;
+ PCIAccess *pci = NULL;
+ UBYTE bus_num;
+ UBYTE dev_num;
+ UBYTE fn_num;
+ struct pci_dev *d;
+ int found_devs = 0;
+
+ pci = a->backend_data;
+
+ // X1000 has a bug which left shifts secondary bus by one bit, so we don't scan but get all devices identified by the system
+ device = pci->ipci->FindDeviceTags(FDT_Index, found_devs);
+ while (device) {
+ d = pci_alloc_dev(a);
+ d->domain = 0; // only one domain for AmigaOS
+ device->GetAddress(&bus_num, &dev_num, &fn_num);
+ d->bus = bus_num;
+ d->dev = dev_num;
+ d->func = fn_num;
+ d->backend_data = device;
+ d->vendor_id = device->ReadConfigWord(PCI_VENDOR_ID);
+ d->device_id = device->ReadConfigWord(PCI_DEVICE_ID);
+ d->known_fields = PCI_FILL_IDENT;
+ d->hdrtype = device->ReadConfigByte(PCI_HEADER_TYPE) & ~PCI_HEADER_TYPE_MULTIFUNCTION;
+ pci_link_dev(a, d);
+ a->debug(" Found device %02x:%02x.%d %04x:%04x\n", d->bus, d->dev, d->func, d->vendor_id, d->device_id);
+
+ found_devs++;
+ device = pci->ipci->FindDeviceTags(FDT_Index, found_devs);
+ }
+}
+
+static int
+aos_expansion_read(struct pci_dev *d, int pos, byte *buf, int len)
+{
+ int res = FALSE;
+ byte *ptr = buf;
+ if (d->backend_data) {
+ for (int i = 0; i < len; i++) {
+ // byte by byte to avoid endianness troubles
+ *ptr = ((struct PCIDevice *)(d->backend_data))->ReadConfigByte(pos + i);
+ ptr++;
+ res = TRUE;
+ }
+ }
+
+ return res;
+}
+
+static int
+aos_expansion_write(struct pci_dev *d, int pos, byte *buf, int len)
+{
+ int res = FALSE;
+ byte *ptr = buf;
+
+ if (d->backend_data) {
+ for (int i = 0; i < len; i++) {
+ // byte by byte to avoid endianness troubles
+ ((struct PCIDevice *)(d->backend_data))->WriteConfigByte(pos + i, *ptr);
+ ptr++;
+ res = TRUE;
+ }
+ }
+
+ return res;
+}
+
+static void
+aos_expansion_init_dev(struct pci_dev *d)
+{
+ d->backend_data = NULL; // struct PCIDevice * to be obtained
+}
+
+static void
+aos_expansion_cleanup_dev(struct pci_dev *d)
+{
+ PCIAccess *pci;
+
+ if (d->backend_data && d->access->backend_data) {
+ pci = d->access->backend_data;
+ pci->ipci->FreeDevice((struct PCIDevice *)d->backend_data);
+ d->backend_data = NULL;
+ }
+}
+
+struct pci_methods pm_aos_expansion = {
+ "aos-expansion",
+ "The Expansion.library on AmigaOS 4.x",
+ NULL, // config, called after allocation of pci_access, if assigned
+ aos_expansion_detect, // detect, mandatory because called without check
+ aos_expansion_init, // init, called once access chosen, eventually after detect
+ aos_expansion_cleanup, // cleanup, called at the end
+ aos_expansion_scan,
+ pci_generic_fill_info,
+ aos_expansion_read,
+ aos_expansion_write,
+ NULL, // read_vpd
+ aos_expansion_init_dev,
+ aos_expansion_cleanup_dev,
+};
diff --git a/lib/configure b/lib/configure
index 158cc0a..8385daa 100755
--- a/lib/configure
+++ b/lib/configure
@@ -204,6 +204,13 @@ case $sys in
IDSDIR="/etc/pci"
LIBRESOLV=
;;
+ amigaos)
+ echo_n " aos-expansion"
+ echo >>$c '#define PCI_HAVE_STDINT_H'
+ echo >>$c '#define PCI_HAVE_PM_AOS_EXPANSION'
+ IDSDIR="DEVS:"
+ echo >>$m 'CC=gcc'
+ ;;
*)
echo " Unfortunately, your OS is not supported by the PCI Library"
exit 1
diff --git a/lib/init.c b/lib/init.c
index 3476681..4133890 100644
--- a/lib/init.c
+++ b/lib/init.c
@@ -158,6 +158,11 @@ static struct pci_methods *pci_methods[PCI_ACCESS_MAX] = {
#else
NULL,
#endif
+#if defined(PCI_HAVE_PM_AOS_EXPANSION)
+ &pm_aos_expansion,
+#else
+ NULL,
+#endif
};
// If PCI_ACCESS_AUTO is selected, we probe the access methods in this order
@@ -175,6 +180,7 @@ static int probe_sequence[] = {
PCI_ACCESS_WIN32_CFGMGR32,
PCI_ACCESS_WIN32_KLDBG,
PCI_ACCESS_WIN32_SYSDBG,
+ PCI_ACCESS_AOS_EXPANSION,
// Low-level methods poking the hardware directly
PCI_ACCESS_ECAM,
PCI_ACCESS_I386_TYPE1,
@@ -394,6 +400,24 @@ retry:
pci_set_name_list_path(a, path, 1);
}
}
+
+#elif defined PCI_OS_AMIGAOS
+
+static void
+pci_init_name_list_path(struct pci_access *a)
+{
+ int len = strlen(PCI_PATH_IDS_DIR);
+
+ if (!len)
+ pci_set_name_list_path(a, PCI_IDS, 0);
+ else
+ {
+ char last_char = PCI_PATH_IDS_DIR[len - 1];
+ if (last_char == ':' || last_char == '/') // root or parent char
+ pci_set_name_list_path(a, PCI_PATH_IDS_DIR PCI_IDS, 0);
+ else
+ pci_set_name_list_path(a, PCI_PATH_IDS_DIR "/" PCI_IDS, 0);
+ }
}
#else
diff --git a/lib/internal.h b/lib/internal.h
index 00ac401..ba07d26 100644
--- a/lib/internal.h
+++ b/lib/internal.h
@@ -8,6 +8,9 @@
* SPDX-License-Identifier: GPL-2.0-or-later
*/
+#ifndef _INTERNAL_H
+#define _INTERNAL_H
+
#include "config.h"
#ifdef PCI_SHARED_LIB
@@ -139,4 +142,6 @@ 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_win32_cfgmgr32, pm_win32_kldbg, pm_win32_sysdbg, pm_aos_expansion;
+
+#endif
diff --git a/lib/pci.h b/lib/pci.h
index 03b4c41..77abdaf 100644
--- a/lib/pci.h
+++ b/lib/pci.h
@@ -51,6 +51,7 @@ enum pci_access_type {
PCI_ACCESS_MMIO_TYPE1, /* MMIO ports, type 1 */
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_MAX
};
diff --git a/lib/sysdep.h b/lib/sysdep.h
index 7502035..5695c30 100644
--- a/lib/sysdep.h
+++ b/lib/sysdep.h
@@ -86,6 +86,10 @@ typedef u16 word;
#define BYTE_ORDER LITTLE_ENDIAN
#endif
+#ifdef PCI_OS_AMIGAOS
+ #include <machine/endian.h>
+#endif
+
#if !defined(BYTE_ORDER)
#error "BYTE_ORDER not defined for your platform"
#endif
diff --git a/pcilib.man b/pcilib.man
index c5b3c1a..a78b852 100644
--- a/pcilib.man
+++ b/pcilib.man
@@ -146,6 +146,9 @@ Archived download links of previous WinDbg versions:
https://web.archive.org/web/20110221133326/https://www.microsoft.com/whdc/devtools/debugging/installx86.mspx
.br
https://web.archive.org/web/20110214012715/https://www.microsoft.com/whdc/devtools/debugging/install64bit.mspx
+.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.
.SH PARAMETERS