Annotation of embedaddon/pciutils/lib/proc.c, revision 1.1.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>