]> mj.ucw.cz Git - pciutils.git/commitdiff
New back-end for AmigaOS on PowerPC
authorMartin Mares <mj@ucw.cz>
Mon, 8 Jan 2024 22:29:44 +0000 (23:29 +0100)
committerMartin Mares <mj@ucw.cz>
Mon, 8 Jan 2024 22:29:44 +0000 (23:29 +0100)
Contributed by Olrick Lefebvre <olrick.lefebvre@olrick.fr>

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

diff --git a/README b/README
index 04e9348f5b5a601b31bce336e016d4f13d42dced..955bd7f8819a7dc99b34eb924c56d871de4c1467 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 a89ac14e42cb9a1354a6d445d7123b7df3e4070c..bacdbc5aa087e09cc9a48bb75113830acaf1eaca 100644 (file)
@@ -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 (file)
index 0000000..6d80bd3
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ *     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
+
+#if defined KDEBUG
+       #if defined __AMIGAOS4__
+               #include <proto/exec.h>
+       #endif
+#endif
+#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"
+
+
+// Debug macros
+/////////////////////////////////////////////////////////////////////////
+
+#define __PRIV_log(lvl, fmt, ...) fprintf(stderr, "[" lvl "] (%s:%d: errno: %s) " fmt "\n", __FILE__, __LINE__, clean_errno(), __VA_ARGS__)
+
+#ifndef DEBUG
+       #define dbg_print(M, ...)
+#else
+       #if defined KDEBUG && defined __AMIGAOS4__
+               #define __PRIV_debug(fmt, ...) IExec->DebugPrintF("DEBUG %s:%d: "fmt"\n", __FILE__, __LINE__, __VA_ARGS__)
+               #undef __PRIV_log
+               #define __PRIV_log(lvl, fmt, ...) IExec->DebugPrintF("[" lvl "] (%s:%d: errno: %s) " fmt "\n", __FILE__, __LINE__, clean_errno(), __VA_ARGS__)
+       #else
+               #define __PRIV_debug(fmt, ...) fprintf(stderr, "DEBUG %s:%d: "fmt"\n", __FILE__, __LINE__, __VA_ARGS__)
+       #endif
+       #define dbg_print(...) __PRIV_debug(__VA_ARGS__, 0)
+#endif
+
+
+#define clean_errno() (errno == 0 ? "None" : strerror(errno))
+
+#define log_err(...) __PRIV_log("ERROR", __VA_ARGS__, 0)
+#define log_warn(...) __PRIV_log("WARN", __VA_ARGS__, 0)
+#define log_info(...) __PRIV_log("INFO", __VA_ARGS__, 0)
+
+#define check(A, ...) if(!(A)) { log_err(__VA_ARGS__); errno=0; goto on_error; }
+#define sentinel(...)  { log_err(__VA_ARGS__); errno=0; goto on_error; }
+#define check_mem(A) check((A), "Out of memory.")
+#define check_debug(A, ...) if(!(A)) { debug(__VA_ARGS__); errno=0; goto on_error; }
+
+
+// AmigaOS access support
+/////////////////////////////////////////////////////////////////////////
+
+#define PCIACCESS_TAG 0xc0ffeeee
+typedef struct _PCIAccess {
+       ULONG tag; // 0xc0ffeeee
+       struct ExpansionBase *expansion;
+       struct PCIIFace *ipci;
+} PCIAccess;
+
+
+static void aos_close_pci_interface(struct pci_access *a)
+{
+       PCIAccess *pci;
+
+       if(NULL != a)
+       {
+               pci = (PCIAccess *)a->backend_data;
+               if(NULL != pci)
+               {
+                       if(NULL != pci->expansion)
+                       {
+                               if(NULL != 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;
+
+       check(NULL != a, "Null pci_access");
+
+       if(NULL != a->backend_data)
+       {   
+               pci = (PCIAccess *)(a->backend_data);
+               check(PCIACCESS_TAG == pci->tag, "pci_access.backend_data already used by alien code");
+       }
+       else
+       {
+               pci     = pci_malloc(a, sizeof(PCIAccess));
+               a->backend_data = pci;
+               pci->tag = PCIACCESS_TAG;
+               pci->expansion = (struct ExpansionBase *)IExec->OpenLibrary("expansion.library", 0);
+               check(NULL != pci->expansion, "Unable to open expansion.library");
+
+               pci->ipci = (struct PCIIFace *)IExec->GetInterface((struct Library *)pci->expansion, "pci", 1, TAG_DONE);
+               check(NULL != pci->ipci, "Unable to obtain pci interface");
+       }
+
+       return TRUE;
+
+
+on_error:
+       aos_close_pci_interface(a);
+       return FALSE;
+}
+
+
+static int aos_expansion_detect(struct pci_access *a)
+{
+       struct PCIDevice *device = NULL;
+       PCIAccess *pci;
+
+       check(TRUE == aos_open_pci_interface(a), "AmigaOS Expansion PCI interface cannot be accessed.");
+       pci = a->backend_data;
+
+       // Try to read PCI first device
+       device = pci->ipci->FindDeviceTags(FDT_Index, 0);
+       check(NULL != device, "AmigaOS Expansion PCI interface cannot find any device");
+       
+       pci->ipci->FreeDevice(device);
+       
+       return TRUE;
+
+on_error:
+       aos_close_pci_interface(a);
+       return FALSE;
+}
+
+
+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);
+}
+
+/*
+#define BYTE_LEN 1
+#define WORD_LEN 2
+#define LONG_LEN 4
+*/
+
+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;
+
+       check(NULL != a, "Null pci_access");
+       pci = a->backend_data;
+       check((NULL != pci) && (PCIACCESS_TAG == pci->tag), "PCIData struct not available");
+
+       // 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(NULL != device)
+       {
+               d = pci_alloc_dev(a);
+               check_mem(d);
+               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);
+       }
+
+on_error:
+       if((NULL != device) && (NULL != pci))
+       {
+               pci->ipci->FreeDevice(device);
+       }
+
+       return;
+}
+
+
+static int aos_expansion_read(struct pci_dev *d, int pos, byte *buf, int len)
+{
+       byte *ptr = buf;
+       int i;
+
+       check(NULL != d, "Null pci_dev");
+       if(NULL != d->backend_data)
+       {
+               for(i = 0; i < len; i++)
+               {
+                       // byte by byte to avoid endianness troubles
+                       *ptr = ((struct PCIDevice *)(d->backend_data))->ReadConfigByte(pos + i);
+                       ptr++;
+               }
+       }
+
+       return TRUE;
+
+on_error:
+       return FALSE;
+}
+
+
+static int aos_expansion_write(struct pci_dev *d, int pos, byte *buf, int len)
+{
+       byte *ptr = buf;
+       int i;
+
+       check(NULL != d, "Null pci_dev");
+       if(NULL != d->backend_data)
+       {
+               for(i = 0; i < len; i++)
+               {
+                       // byte by byte to avoid endianness troubles
+                       ((struct PCIDevice *)(d->backend_data))->WriteConfigByte(pos + i, *ptr);
+                       ptr++;
+               }
+       }
+
+       return TRUE;
+
+on_error:
+       return FALSE;
+}
+
+
+static void aos_expansion_init_dev(struct pci_dev *d)
+{
+       if(NULL != d)
+       {
+               d->backend_data = NULL; // struct PCIDevice * to be obtained
+       }
+}
+
+static void aos_expansion_cleanup_dev(struct pci_dev *d)
+{
+       PCIAccess *pci;
+
+       if((NULL != d) && (NULL != d->backend_data) && (NULL != d->access) && (NULL != 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, // scan,
+  pci_generic_fill_info, // fill_info,
+  aos_expansion_read, // read,
+  aos_expansion_write, // write,
+  NULL, // read_vpd,
+  aos_expansion_init_dev, // init_dev,
+  aos_expansion_cleanup_dev     // cleanup_dev,
+};
index 158cc0a71bd9bc5552c244c35ca1633e0198a51c..8385daa061954c220c9dd85185f4f496eda18242 100755 (executable)
@@ -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
index 347668163f7a9f9a0b6d75227022b19f5a4ae3b8..9c805d39882031dc5d10d7b9c75f0bf41d03fbba 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,30 @@ 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)
+{
+       char last_char;
+       int len = strlen(PCI_PATH_IDS_DIR);
+
+       if(0 == len) // empty path
+       {
+         pci_set_name_list_path(a, PCI_IDS, 0);
+       }
+       else
+       {
+               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 00ac401ec5a3e07d3165b391d59b7ec9d01dd0c1..ba07d26a7087afb7a71c5a94706087a0dcafc2e5 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 03b4c41694ff03d4302f6564336d4e6757f43162..77abdafb8d36bb69a27547cc1fc6bee5a6d65f12 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 750203573f006dd1b088a00e0ec4f788ece2ee15..5695c30a05900856546230ea9f21e25e2d819da1 100644 (file)
@@ -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