[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH libpciaccess] hurd: device_open the pre-existing pci server
From: |
Damien Zammit |
Subject: |
[PATCH libpciaccess] hurd: device_open the pre-existing pci server |
Date: |
Sun, 7 Mar 2021 09:36:26 +1100 |
This is a revised version of previous patch.
When there is no pci "device" present in the system, the fallback
mechanism to use /servers/bus/pci works.
It also boots from a static arbiter.
---
src/common_init.c | 37 +++++++++++++
src/hurd_pci.c | 138 ++++++++++++++++++++++++++++++----------------
2 files changed, 128 insertions(+), 47 deletions(-)
diff --git a/src/common_init.c b/src/common_init.c
index 1940cff..14f0c6b 100644
--- a/src/common_init.c
+++ b/src/common_init.c
@@ -40,6 +40,40 @@
_pci_hidden struct pci_system * pci_sys;
+static int
+sort_devices(void)
+{
+ int bus, dev, func;
+ struct pci_device_private *sorted;
+ struct pci_device_private *device;
+ struct pci_device_private *tmpdev;
+
+ sorted = calloc(pci_sys->num_devices, sizeof(struct pci_device_private));
+ if (!sorted) {
+ return ENOMEM;
+ }
+
+ tmpdev = sorted;
+
+ for (bus = 0; bus < 256; bus++) {
+ for (dev = 0; dev < 32; dev++) {
+ for (func = 0; func < 8; func++) {
+ device = (struct pci_device_private *)
+ pci_device_find_by_slot(0, bus, dev, func);
+ if (device) {
+ *tmpdev = *device;
+ tmpdev++;
+ }
+ }
+ }
+ }
+ if (pci_sys->devices) {
+ free(pci_sys->devices);
+ pci_sys->devices = sorted;
+ }
+ return 0;
+}
+
/**
* Initialize the PCI subsystem for access.
*
@@ -72,6 +106,9 @@ pci_system_init( void )
#else
# error "Unsupported OS"
#endif
+ if (!err) {
+ err = sort_devices();
+ }
return err;
}
diff --git a/src/hurd_pci.c b/src/hurd_pci.c
index ada7af8..3086b63 100644
--- a/src/hurd_pci.c
+++ b/src/hurd_pci.c
@@ -33,9 +33,12 @@
#include <sys/mman.h>
#include <string.h>
#include <strings.h>
+#include <mach.h>
#include <hurd.h>
#include <hurd/pci.h>
#include <hurd/paths.h>
+#include <hurd/fs.h>
+#include <device/device.h>
#include "x86_pci.h"
#include "pciaccess.h"
@@ -67,6 +70,8 @@ struct pci_system_hurd {
struct pci_system system;
};
+static mach_port_t pci_port;
+
static int
pci_device_hurd_probe(struct pci_device *dev)
{
@@ -295,33 +300,64 @@ pci_device_hurd_read_rom(struct pci_device * dev, void *
buffer)
* Deallocate the port before destroying the device.
*/
static void
-pci_device_hurd_destroy(struct pci_device *dev)
+pci_device_hurd_destroy_device(struct pci_device *dev)
{
struct pci_device_private *d = (struct pci_device_private*) dev;
mach_port_deallocate (mach_task_self (), d->device_port);
}
+static void
+pci_device_hurd_destroy(void)
+{
+ if (pci_port != MACH_PORT_NULL) {
+ device_close (pci_port);
+ }
+}
+
+static struct dirent64 *
+simple_readdir(mach_port_t port, uint32_t *first_entry)
+{
+ char *data;
+ int nentries = 0;
+ vm_size_t size;
+
+ dir_readdir (port, &data, &size, *first_entry, 1, 0, &nentries);
+
+ if (nentries == 0) {
+ return NULL;
+ }
+
+ *first_entry = *first_entry + 1;
+ return (struct dirent64 *)data;
+}
+
/* Walk through the FS tree to see what is allowed for us */
static int
-enum_devices(const char *parent, int domain,
- int bus, int dev, int func, tree_level lev)
+enum_devices(mach_port_t cwd_port, const char *parent, int domain,
+ int bus, int dev, int func, tree_level lev)
{
int err, ret;
- DIR *dir;
- struct dirent *entry;
+ struct dirent64 *entry = NULL;
char path[NAME_MAX];
char server[NAME_MAX];
- uint32_t reg;
+ uint32_t reg, count = 0;
size_t toread;
mach_port_t device_port;
struct pci_device_private *d, *devices;
- dir = opendir(parent);
- if (!dir)
- return errno;
+ if (pci_port == MACH_PORT_NULL) {
+ return EGRATUITOUS;
+ }
+ if (lev > LEVEL_FUNC + 1) {
+ return 0;
+ }
+ cwd_port = file_name_lookup_under (pci_port, parent, O_DIRECTORY | O_RDWR
| O_EXEC, 0);
+ if (cwd_port == MACH_PORT_NULL) {
+ return 0;
+ }
- while ((entry = readdir(dir)) != 0) {
+ while ((entry = simple_readdir(cwd_port, &count)) != NULL) {
snprintf(path, NAME_MAX, "%s/%s", parent, entry->d_name);
if (entry->d_type == DT_DIR) {
if (!strncmp(entry->d_name, ".", NAME_MAX)
@@ -331,7 +367,6 @@ enum_devices(const char *parent, int domain,
errno = 0;
ret = strtol(entry->d_name, 0, 16);
if (errno) {
- closedir(dir);
return errno;
}
@@ -353,16 +388,12 @@ enum_devices(const char *parent, int domain,
func = ret;
break;
default:
- if (closedir(dir) < 0)
- return errno;
- return -1;
+ return 0;
}
- err = enum_devices(path, domain, bus, dev, func, lev+1);
+ err = enum_devices(cwd_port, path, domain, bus, dev, func, lev+1);
if (err && err != EPERM && err != EACCES) {
- if (closedir(dir) < 0)
- return errno;
- return err;
+ return 0;
}
} else {
if (strncmp(entry->d_name, FILE_CONFIG_NAME, NAME_MAX))
@@ -370,34 +401,29 @@ enum_devices(const char *parent, int domain,
continue;
/* We found an available virtual device, add it to our list */
- snprintf(server, NAME_MAX, "%s/%04x/%02x/%02x/%01u/%s",
- _SERVERS_BUS_PCI, domain, bus, dev, func,
+ snprintf(server, NAME_MAX, "./%04x/%02x/%02x/%01u/%s",
+ domain, bus, dev, func,
entry->d_name);
- device_port = file_name_lookup(server, 0, 0);
+ device_port = file_name_lookup_under(pci_port, server, O_RDWR, 0);
if (device_port == MACH_PORT_NULL) {
- closedir(dir);
- return errno;
+ return 0;
}
toread = sizeof(reg);
err = pciclient_cfg_read(device_port, PCI_VENDOR_ID, (char*)®,
&toread);
if (err) {
- if (closedir(dir) < 0)
- return errno;
+ mach_port_deallocate (mach_task_self (), device_port);
return err;
}
if (toread != sizeof(reg)) {
- if (closedir(dir) < 0)
- return errno;
+ mach_port_deallocate (mach_task_self (), device_port);
return -1;
}
devices = realloc(pci_sys->devices, (pci_sys->num_devices + 1)
* sizeof(struct pci_device_private));
if (!devices) {
- if (closedir(dir) < 0)
- return errno;
return ENOMEM;
}
@@ -415,13 +441,11 @@ enum_devices(const char *parent, int domain,
err = pciclient_cfg_read(device_port, PCI_CLASS, (char*)®,
&toread);
if (err) {
- if (closedir(dir) < 0)
- return errno;
+ mach_port_deallocate (mach_task_self (), device_port);
return err;
}
if (toread != sizeof(reg)) {
- if (closedir(dir) < 0)
- return errno;
+ mach_port_deallocate (mach_task_self (), device_port);
return -1;
}
@@ -432,13 +456,11 @@ enum_devices(const char *parent, int domain,
err = pciclient_cfg_read(device_port, PCI_SUB_VENDOR_ID,
(char*)®, &toread);
if (err) {
- if (closedir(dir) < 0)
- return errno;
+ mach_port_deallocate (mach_task_self (), device_port);
return err;
}
if (toread != sizeof(reg)) {
- if (closedir(dir) < 0)
- return errno;
+ mach_port_deallocate (mach_task_self (), device_port);
return -1;
}
@@ -452,15 +474,12 @@ enum_devices(const char *parent, int domain,
}
}
- if (closedir(dir) < 0)
- return errno;
-
return 0;
}
static const struct pci_system_methods hurd_pci_methods = {
- .destroy = pci_system_x86_destroy,
- .destroy_device = pci_device_hurd_destroy,
+ .destroy = pci_device_hurd_destroy,
+ .destroy_device = pci_device_hurd_destroy_device,
.read_rom = pci_device_hurd_read_rom,
.probe = pci_device_hurd_probe,
.map_range = pci_device_x86_map_range,
@@ -489,6 +508,11 @@ pci_system_hurd_create(void)
{
int err;
struct pci_system_hurd *pci_sys_hurd;
+ mach_port_t device_master;
+ mach_port_t root = MACH_PORT_NULL;
+ const char *sbpci = _SERVERS_BUS_PCI;
+ const char *dot = ".";
+ char *rootpath = (char *)dot;
if (&netfs_server_name && netfs_server_name
&& !strcmp(netfs_server_name, "pci-arbiter")) {
@@ -513,12 +537,32 @@ pci_system_hurd_create(void)
pci_sys->methods = &hurd_pci_methods;
pci_sys->num_devices = 0;
- err = enum_devices(_SERVERS_BUS_PCI, -1, -1, -1, -1, LEVEL_DOMAIN);
+
+ if ((err = get_privileged_ports (NULL, &device_master)) || (device_master
== MACH_PORT_NULL)) {
+ pci_system_cleanup();
+ return err;
+ }
+
+ err = device_open (device_master, D_READ|D_WRITE, "pci", &pci_port);
+ if (!err) {
+ root = file_name_lookup_under (pci_port, rootpath, O_DIRECTORY |
O_RDWR | O_EXEC, 0);
+ }
+
+ if (!root) {
+ rootpath = (char *)sbpci;
+ root = file_name_lookup (rootpath, O_RDWR, 0);
+ pci_port = root;
+ }
+
+ if (!root) {
+ pci_system_cleanup();
+ return errno;
+ }
+
+ err = enum_devices (root, rootpath, -1, -1, -1, -1, LEVEL_DOMAIN);
if (err) {
- /* There was an error, but we don't know which devices have been
- * initialized correctly, so call cleanup to free whatever is allocated
*/
- pci_system_cleanup();
- return err;
+ pci_system_cleanup();
+ return err;
}
return 0;
--
2.30.1