This patch for libpciaccess goes in lockstep with the previous patches I sent for hurd.
--- src/hurd_pci.c | 125 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 98 insertions(+), 27 deletions(-) diff --git a/src/hurd_pci.c b/src/hurd_pci.c index ada7af8..ff14285 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" @@ -302,26 +305,74 @@ pci_device_hurd_destroy(struct pci_device *dev) mach_port_deallocate (mach_task_self (), d->device_port); } +static struct dirent * +simple_readdir(mach_port_t port, uint32_t *first_entry) +{ + struct dirent *e; + 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; + e = (struct dirent *)(data+4); + return e; +} + +static struct dirent * +readdir_wrapper(DIR *dir, mach_port_t port, uint32_t *count) +{ + if (dir) { + return readdir(dir); + } else { + return simple_readdir(port, count); + } +} + +static int +closedir_wrapper(DIR *dir) +{ + if (dir) { + return closedir(dir); + } + return 0; +} + /* 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 pci_port, 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; + DIR *dir = NULL; + struct dirent *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) { + dir = opendir(parent); + if (!dir) + return errno; + } else { + 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 = readdir_wrapper(dir, 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 +382,7 @@ enum_devices(const char *parent, int domain, errno = 0; ret = strtol(entry->d_name, 0, 16); if (errno) { - closedir(dir); + closedir_wrapper(dir); return errno; } @@ -353,14 +404,14 @@ enum_devices(const char *parent, int domain, func = ret; break; default: - if (closedir(dir) < 0) + if (closedir_wrapper(dir) < 0) return errno; return -1; } - err = enum_devices(path, domain, bus, dev, func, lev+1); + err = enum_devices(pci_port, cwd_port, path, domain, bus, dev, func, lev+1); if (err && err != EPERM && err != EACCES) { - if (closedir(dir) < 0) + if (closedir_wrapper(dir) < 0) return errno; return err; } @@ -370,12 +421,22 @@ 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, - entry->d_name); - device_port = file_name_lookup(server, 0, 0); + if (pci_port == MACH_PORT_NULL) { + snprintf(server, NAME_MAX, "%s/%04x/%02x/%02x/%01u/%s", + _SERVERS_BUS_PCI, domain, bus, dev, func, + entry->d_name); + device_port = file_name_lookup(server, 0, 0); + } else { + snprintf(server, NAME_MAX, "./%04x/%02x/%02x/%01u/%s", + domain, bus, dev, func, + entry->d_name); + device_port = file_name_lookup_under(pci_port, server, O_RDWR, 0); + mach_print("pciaccess(hurd): Found "); + mach_print(server); + mach_print("\n"); + } if (device_port == MACH_PORT_NULL) { - closedir(dir); + closedir_wrapper(dir); return errno; } @@ -383,12 +444,12 @@ enum_devices(const char *parent, int domain, err = pciclient_cfg_read(device_port, PCI_VENDOR_ID, (char*)®, &toread); if (err) { - if (closedir(dir) < 0) + if (closedir_wrapper(dir) < 0) return errno; return err; } if (toread != sizeof(reg)) { - if (closedir(dir) < 0) + if (closedir_wrapper(dir) < 0) return errno; return -1; } @@ -396,7 +457,7 @@ enum_devices(const char *parent, int domain, devices = realloc(pci_sys->devices, (pci_sys->num_devices + 1) * sizeof(struct pci_device_private)); if (!devices) { - if (closedir(dir) < 0) + if (closedir_wrapper(dir) < 0) return errno; return ENOMEM; } @@ -415,12 +476,12 @@ enum_devices(const char *parent, int domain, err = pciclient_cfg_read(device_port, PCI_CLASS, (char*)®, &toread); if (err) { - if (closedir(dir) < 0) + if (closedir_wrapper(dir) < 0) return errno; return err; } if (toread != sizeof(reg)) { - if (closedir(dir) < 0) + if (closedir_wrapper(dir) < 0) return errno; return -1; } @@ -432,12 +493,12 @@ 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) + if (closedir_wrapper(dir) < 0) return errno; return err; } if (toread != sizeof(reg)) { - if (closedir(dir) < 0) + if (closedir_wrapper(dir) < 0) return errno; return -1; } @@ -452,7 +513,7 @@ enum_devices(const char *parent, int domain, } } - if (closedir(dir) < 0) + if (closedir_wrapper(dir) < 0) return errno; return 0; @@ -489,6 +550,8 @@ pci_system_hurd_create(void) { int err; struct pci_system_hurd *pci_sys_hurd; + mach_port_t device_master; + mach_port_t root, pci_server_port = MACH_PORT_NULL; if (&netfs_server_name && netfs_server_name && !strcmp(netfs_server_name, "pci-arbiter")) { @@ -513,7 +576,15 @@ 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 (! get_privileged_ports (NULL, &device_master) && (device_master != MACH_PORT_NULL)) { + device_open (device_master, D_READ|D_WRITE, "pci", &pci_server_port); + root = file_name_lookup_under (pci_server_port, ".", O_DIRECTORY | O_RDWR | O_EXEC, 0); + err = enum_devices(pci_server_port, root, ".", -1, -1, -1, -1, LEVEL_DOMAIN); + } else { + err = enum_devices(MACH_PORT_NULL, MACH_PORT_NULL, _SERVERS_BUS_PCI, -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 */ -- 2.30.0