Annotation of embedaddon/pciutils/lib/proc.c, revision 1.1
1.1 ! misho 1: /*
! 2: * The PCI Library -- Configuration Access via /proc/bus/pci
! 3: *
! 4: * Copyright (c) 1997--2003 Martin Mares <mj@ucw.cz>
! 5: *
! 6: * Can be freely distributed and used under the terms of the GNU GPL.
! 7: */
! 8:
! 9: #define _GNU_SOURCE
! 10:
! 11: #include <stdio.h>
! 12: #include <string.h>
! 13: #include <unistd.h>
! 14: #include <errno.h>
! 15: #include <fcntl.h>
! 16: #include <sys/types.h>
! 17:
! 18: #include "internal.h"
! 19: #include "pread.h"
! 20:
! 21: static void
! 22: proc_config(struct pci_access *a)
! 23: {
! 24: pci_define_param(a, "proc.path", PCI_PATH_PROC_BUS_PCI, "Path to the procfs bus tree");
! 25: }
! 26:
! 27: static int
! 28: proc_detect(struct pci_access *a)
! 29: {
! 30: char *name = pci_get_param(a, "proc.path");
! 31:
! 32: if (access(name, R_OK))
! 33: {
! 34: a->warning("Cannot open %s", name);
! 35: return 0;
! 36: }
! 37: a->debug("...using %s", name);
! 38: return 1;
! 39: }
! 40:
! 41: static void
! 42: proc_init(struct pci_access *a)
! 43: {
! 44: a->fd = -1;
! 45: }
! 46:
! 47: static void
! 48: proc_cleanup(struct pci_access *a)
! 49: {
! 50: if (a->fd >= 0)
! 51: {
! 52: close(a->fd);
! 53: a->fd = -1;
! 54: }
! 55: }
! 56:
! 57: static void
! 58: proc_scan(struct pci_access *a)
! 59: {
! 60: FILE *f;
! 61: char buf[512];
! 62:
! 63: if (snprintf(buf, sizeof(buf), "%s/devices", pci_get_param(a, "proc.path")) == sizeof(buf))
! 64: a->error("File name too long");
! 65: f = fopen(buf, "r");
! 66: if (!f)
! 67: a->error("Cannot open %s", buf);
! 68: while (fgets(buf, sizeof(buf)-1, f))
! 69: {
! 70: struct pci_dev *d = pci_alloc_dev(a);
! 71: unsigned int dfn, vend, cnt, known;
! 72:
! 73: #define F " " PCIADDR_T_FMT
! 74: cnt = sscanf(buf, "%x %x %x" F F F F F F F F F F F F F F,
! 75: &dfn,
! 76: &vend,
! 77: &d->irq,
! 78: &d->base_addr[0],
! 79: &d->base_addr[1],
! 80: &d->base_addr[2],
! 81: &d->base_addr[3],
! 82: &d->base_addr[4],
! 83: &d->base_addr[5],
! 84: &d->rom_base_addr,
! 85: &d->size[0],
! 86: &d->size[1],
! 87: &d->size[2],
! 88: &d->size[3],
! 89: &d->size[4],
! 90: &d->size[5],
! 91: &d->rom_size);
! 92: #undef F
! 93: if (cnt != 9 && cnt != 10 && cnt != 17)
! 94: a->error("proc: parse error (read only %d items)", cnt);
! 95: d->bus = dfn >> 8U;
! 96: d->dev = PCI_SLOT(dfn & 0xff);
! 97: d->func = PCI_FUNC(dfn & 0xff);
! 98: d->vendor_id = vend >> 16U;
! 99: d->device_id = vend & 0xffff;
! 100: known = 0;
! 101: if (!a->buscentric)
! 102: {
! 103: known |= PCI_FILL_IDENT | PCI_FILL_IRQ | PCI_FILL_BASES;
! 104: if (cnt >= 10)
! 105: known |= PCI_FILL_ROM_BASE;
! 106: if (cnt >= 17)
! 107: known |= PCI_FILL_SIZES;
! 108: }
! 109: d->known_fields = known;
! 110: pci_link_dev(a, d);
! 111: }
! 112: fclose(f);
! 113: }
! 114:
! 115: static int
! 116: proc_setup(struct pci_dev *d, int rw)
! 117: {
! 118: struct pci_access *a = d->access;
! 119:
! 120: if (a->cached_dev != d || a->fd_rw < rw)
! 121: {
! 122: char buf[1024];
! 123: int e;
! 124: if (a->fd >= 0)
! 125: close(a->fd);
! 126: e = snprintf(buf, sizeof(buf), "%s/%02x/%02x.%d",
! 127: pci_get_param(a, "proc.path"),
! 128: d->bus, d->dev, d->func);
! 129: if (e < 0 || e >= (int) sizeof(buf))
! 130: a->error("File name too long");
! 131: a->fd_rw = a->writeable || rw;
! 132: a->fd = open(buf, a->fd_rw ? O_RDWR : O_RDONLY);
! 133: if (a->fd < 0)
! 134: {
! 135: e = snprintf(buf, sizeof(buf), "%s/%04x:%02x/%02x.%d",
! 136: pci_get_param(a, "proc.path"),
! 137: d->domain, d->bus, d->dev, d->func);
! 138: if (e < 0 || e >= (int) sizeof(buf))
! 139: a->error("File name too long");
! 140: a->fd = open(buf, a->fd_rw ? O_RDWR : O_RDONLY);
! 141: }
! 142: if (a->fd < 0)
! 143: a->warning("Cannot open %s", buf);
! 144: a->cached_dev = d;
! 145: a->fd_pos = 0;
! 146: }
! 147: return a->fd;
! 148: }
! 149:
! 150: static int
! 151: proc_read(struct pci_dev *d, int pos, byte *buf, int len)
! 152: {
! 153: int fd = proc_setup(d, 0);
! 154: int res;
! 155:
! 156: if (fd < 0)
! 157: return 0;
! 158: res = do_read(d, fd, buf, len, pos);
! 159: if (res < 0)
! 160: {
! 161: d->access->warning("proc_read: read failed: %s", strerror(errno));
! 162: return 0;
! 163: }
! 164: else if (res != len)
! 165: return 0;
! 166: return 1;
! 167: }
! 168:
! 169: static int
! 170: proc_write(struct pci_dev *d, int pos, byte *buf, int len)
! 171: {
! 172: int fd = proc_setup(d, 1);
! 173: int res;
! 174:
! 175: if (fd < 0)
! 176: return 0;
! 177: res = do_write(d, fd, buf, len, pos);
! 178: if (res < 0)
! 179: {
! 180: d->access->warning("proc_write: write failed: %s", strerror(errno));
! 181: return 0;
! 182: }
! 183: else if (res != len)
! 184: {
! 185: d->access->warning("proc_write: tried to write %d bytes at %d, but only %d succeeded", len, pos, res);
! 186: return 0;
! 187: }
! 188: return 1;
! 189: }
! 190:
! 191: static void
! 192: proc_cleanup_dev(struct pci_dev *d)
! 193: {
! 194: if (d->access->cached_dev == d)
! 195: d->access->cached_dev = NULL;
! 196: }
! 197:
! 198: struct pci_methods pm_linux_proc = {
! 199: "linux-proc",
! 200: "The proc file system on Linux",
! 201: proc_config,
! 202: proc_detect,
! 203: proc_init,
! 204: proc_cleanup,
! 205: proc_scan,
! 206: pci_generic_fill_info,
! 207: proc_read,
! 208: proc_write,
! 209: NULL, /* read_vpd */
! 210: NULL, /* init_dev */
! 211: proc_cleanup_dev
! 212: };
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>