]> mj.ucw.cz Git - pciutils.git/commitdiff
Merge branch 'amiga'
authorMartin Mares <mj@ucw.cz>
Fri, 23 Feb 2024 13:56:39 +0000 (14:56 +0100)
committerMartin Mares <mj@ucw.cz>
Fri, 23 Feb 2024 13:56:39 +0000 (14:56 +0100)
README
lib/Makefile
lib/aos-expansion.c [new file with mode: 0644]
lib/configure
lib/init.c
lib/internal.h
lib/pci.h
lib/sysdep.h
pcilib.man

diff --git a/README b/README
index fce2f6151abc9df61334d3c7a417c0e4561257ad..ca130b1f6877719441a6c4b89a432d44f2443c34 100644 (file)
--- 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
index 26ea170b40f1202b9cda71f5d80525c900de6742..de976ed5e11c642caf42f77805e36d512e5987a2 100644 (file)
@@ -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 (file)
index 0000000..3e11f47
--- /dev/null
@@ -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,
+};
index 90641663f8736089b8d303a8a8e4b4629a029234..3df057ad8ffebf6878085a5113350e7bd6b9ddaf 100755 (executable)
@@ -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
index 943321b1571aab6dd774297beb602f65053d4bc6..ba1653ea93f582314d0012ad7cca771b0b381003 100644 (file)
@@ -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
index 64836b9b05f6e27b519b95f4e7e3d960d5e7faff..549f94cf0d3d3f9b44d636b7ad369bd63dff173c 100644 (file)
@@ -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
index dbdb02fcfd2d719a008596d43789a83cb75757cc..447118cc37c7fed024b229f699ff2d4887400e64 100644 (file)
--- 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
 };
 
index a11080af96d228dc0a7bf9df5e83ffeeacf16f17..40e1407810b4196cc4a32eb32ebd922acdcf4b06 100644 (file)
@@ -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
index b63ba346ed698d6692534f838884667cb29c43e9..79a1b146e5956e7c07938eeaa415e70a53c86387 100644 (file)
@@ -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