2 * The PCI Library -- Configuration Access via /proc/bus/pci
4 * Copyright (c) 1997--1999 Martin Mares <mj@ucw.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
16 #include <sys/types.h>
21 * We'd like to use pread/pwrite for configuration space accesses, but
22 * unfortunately it isn't simple at all since all libc's until glibc 2.1
26 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ > 0
27 /* glibc 2.1 or newer -> pread/pwrite supported automatically */
29 #elif defined(i386) && defined(__GLIBC__)
30 /* glibc 2.0 on i386 -> call syscalls directly */
31 #include <asm/unistd.h>
32 #include <syscall-list.h>
36 static int pread(unsigned int fd
, void *buf
, size_t size
, loff_t where
)
37 { return syscall(SYS_pread
, fd
, buf
, size
, where
); }
39 #define SYS_pwrite 181
41 static int pwrite(unsigned int fd
, void *buf
, size_t size
, loff_t where
)
42 { return syscall(SYS_pwrite
, fd
, buf
, size
, where
); }
45 /* old libc on i386 -> call syscalls directly the old way */
46 #include <asm/unistd.h>
47 static _syscall5(int, pread
, unsigned int, fd
, void *, buf
, size_t, size
, u32
, where_lo
, u32
, where_hi
);
48 static _syscall5(int, pwrite
, unsigned int, fd
, void *, buf
, size_t, size
, u32
, where_lo
, u32
, where_hi
);
49 static int do_read(struct pci_dev
*d UNUSED
, int fd
, void *buf
, size_t size
, int where
) { return pread(fd
, buf
, size
, where
, 0); }
50 static int do_write(struct pci_dev
*d UNUSED
, int fd
, void *buf
, size_t size
, int where
) { return pwrite(fd
, buf
, size
, where
, 0); }
54 /* In all other cases we use lseek/read/write instead to be safe */
55 #define make_rw_glue(op) \
56 static int do_##op(struct pci_dev *d, int fd, void *buf, size_t size, int where) \
58 struct pci_access *a = d->access; \
60 if (a->fd_pos != where && lseek(fd, where, SEEK_SET) < 0) \
62 r = op(fd, buf, size); \
66 a->fd_pos = where + r; \
75 #define do_read(d,f,b,l,p) pread(f,b,l,p)
76 #define do_write(d,f,b,l,p) pwrite(f,b,l,p)
80 proc_config(struct pci_access
*a
)
82 a
->method_params
[PCI_ACCESS_PROC_BUS_PCI
] = PATH_PROC_BUS_PCI
;
86 proc_detect(struct pci_access
*a
)
88 char *name
= a
->method_params
[PCI_ACCESS_PROC_BUS_PCI
];
90 if (access(name
, R_OK
))
92 a
->warning("Cannot open %s", name
);
95 a
->debug("...using %s", name
);
100 proc_init(struct pci_access
*a
)
106 proc_cleanup(struct pci_access
*a
)
116 proc_scan(struct pci_access
*a
)
121 if (snprintf(buf
, sizeof(buf
), "%s/devices", a
->method_params
[PCI_ACCESS_PROC_BUS_PCI
]) == sizeof(buf
))
122 a
->error("File name too long");
125 a
->error("Cannot open %s", buf
);
126 while (fgets(buf
, sizeof(buf
)-1, f
))
128 struct pci_dev
*d
= pci_alloc_dev(a
);
129 unsigned int dfn
, vend
, cnt
, known
;
132 #ifdef HAVE_LONG_ADDRESS
133 "%x %x %x %llx %llx %llx %llx %llx %llx %llx %llx %llx %llx %llx %llx %llx %llx",
135 "%x %x %x %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx",
154 if (cnt
!= 9 && cnt
!= 10 && cnt
!= 17)
155 a
->error("proc: parse error (read only %d items)", cnt
);
157 d
->dev
= PCI_SLOT(dfn
& 0xff);
158 d
->func
= PCI_FUNC(dfn
& 0xff);
159 d
->vendor_id
= vend
>> 16U;
160 d
->device_id
= vend
& 0xffff;
161 d
->hdrtype
= pci_read_byte(d
, PCI_HEADER_TYPE
);
162 known
= PCI_FILL_IDENT
;
165 known
|= PCI_FILL_IRQ
| PCI_FILL_BASES
;
167 known
|= PCI_FILL_ROM_BASE
;
169 known
|= PCI_FILL_SIZES
;
171 d
->known_fields
= known
;
178 proc_setup(struct pci_dev
*d
, int rw
)
180 struct pci_access
*a
= d
->access
;
182 if (a
->cached_dev
!= d
|| a
->fd_rw
< rw
)
187 if (snprintf(buf
, sizeof(buf
), "%s/%02x/%02x.%d", a
->method_params
[PCI_ACCESS_PROC_BUS_PCI
],
188 d
->bus
, d
->dev
, d
->func
) == sizeof(buf
))
189 a
->error("File name too long");
190 a
->fd_rw
= a
->writeable
|| rw
;
191 a
->fd
= open(buf
, a
->fd_rw
? O_RDWR
: O_RDONLY
);
193 a
->warning("Cannot open %s", buf
);
201 proc_read(struct pci_dev
*d
, int pos
, byte
*buf
, int len
)
203 int fd
= proc_setup(d
, 0);
208 res
= do_read(d
, fd
, buf
, len
, pos
);
211 d
->access
->warning("proc_read: read failed: %s", strerror(errno
));
216 d
->access
->warning("proc_read: tried to read %d bytes at %d, but got only %d", len
, pos
, res
);
223 proc_write(struct pci_dev
*d
, int pos
, byte
*buf
, int len
)
225 int fd
= proc_setup(d
, 1);
230 res
= do_write(d
, fd
, buf
, len
, pos
);
233 d
->access
->warning("proc_write: write failed: %s", strerror(errno
));
238 d
->access
->warning("proc_write: tried to write %d bytes at %d, but got only %d", len
, pos
, res
);
245 proc_cleanup_dev(struct pci_dev
*d
)
247 if (d
->access
->cached_dev
== d
)
248 d
->access
->cached_dev
= NULL
;
251 struct pci_methods pm_linux_proc
= {
258 pci_generic_fill_info
,