From 5b52ae794a6fcf77363a78a42278da8a4feaf225 Mon Sep 17 00:00:00 2001 From: Agg242 Date: Mon, 22 Jan 2024 17:41:47 +0100 Subject: New back-end for AmigaOS on PowerPC --- README | 1 + lib/Makefile | 4 + lib/aos-expansion.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/configure | 7 ++ lib/init.c | 24 ++++++ lib/internal.h | 7 +- lib/pci.h | 1 + lib/sysdep.h | 4 + pcilib.man | 3 + 9 files changed, 288 insertions(+), 1 deletion(-) create mode 100644 lib/aos-expansion.c 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 + * + * 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 +#include +#include +#include + + +// 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 + +#include +#include +#include +#include +#include + +#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 +#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 -- cgit 1.2.3-korg