diff options
author | Martin Mares <mj@ucw.cz> | 2024-02-23 14:56:39 +0100 |
---|---|---|
committer | Martin Mares <mj@ucw.cz> | 2024-02-23 14:56:39 +0100 |
commit | 3f13452c5b2388271edf11cfdc5713633b561e69 (patch) | |
tree | 0fe28f864098c128a591449f8f39307f0c1995bd | |
parent | 3b35571588efef33489d3bb6e4436dc7581596be (diff) | |
parent | 7ec6e3ec76eda8964f96a3393b09ae3d6eb2fef0 (diff) | |
download | pciutils-3f13452c5b2388271edf11cfdc5713633b561e69.tar.gz |
Merge branch 'amiga'
-rw-r--r-- | README | 1 | ||||
-rw-r--r-- | lib/Makefile | 4 | ||||
-rw-r--r-- | lib/aos-expansion.c | 237 | ||||
-rwxr-xr-x | lib/configure | 8 | ||||
-rw-r--r-- | lib/init.c | 24 | ||||
-rw-r--r-- | lib/internal.h | 7 | ||||
-rw-r--r-- | lib/pci.h | 1 | ||||
-rw-r--r-- | lib/sysdep.h | 4 | ||||
-rw-r--r-- | pcilib.man | 3 |
9 files changed, 288 insertions, 1 deletions
@@ -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 26ea170..de976ed 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -89,6 +89,10 @@ endif endif 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..3e11f47 --- /dev/null +++ b/lib/aos-expansion.c @@ -0,0 +1,237 @@ +/* + * 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: pciutils " PCILIB_VERSION " (" PCILIB_DATE_AMIGAOS ") 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 = 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 9064166..3df057a 100755 --- a/lib/configure +++ b/lib/configure @@ -216,6 +216,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 @@ -354,4 +361,5 @@ else fi echo >>$c "#define PCILIB_VERSION \"$VERSION\"" +echo >>$c "#define PCILIB_DATE_AMIGAOS \"`echo $DATE | sed 's/\(....\)-\(..\)-\(..\)/\3.\2.\1/'`\"" sed '/"/{s/^#define \([^ ]*\) "\(.*\)"$/\1=\2/;p;d;};s/^#define \(.*\)/\1=1/' <$c >>$m @@ -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 64836b9..549f94c 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 @@ -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 a11080a..40e1407 100644 --- a/lib/sysdep.h +++ b/lib/sysdep.h @@ -93,6 +93,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 @@ -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 |