]> git.ipfire.org Git - thirdparty/pciutils.git/blob - lib/obsd-device.c
lib/configure: match all freebsd os's
[thirdparty/pciutils.git] / lib / obsd-device.c
1 /*
2 * The PCI Library -- OpenBSD /dev/pci access
3 *
4 * Adapted from fbsd-device.c by Matthieu Herrb <matthieu.herrb@laas.fr>, 2006
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
9 #include <fcntl.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <errno.h>
13 #include <sys/endian.h>
14 #include <sys/types.h>
15 #include <sys/ioctl.h>
16 #include <sys/pciio.h>
17 #include "internal.h"
18
19 static void
20 obsd_config(struct pci_access *a)
21 {
22 pci_define_param(a, "obsd.path", PCI_PATH_OBSD_DEVICE, "Path to the OpenBSD PCI device");
23 }
24
25 static int
26 obsd_detect(struct pci_access *a)
27 {
28 char *name = pci_get_param(a, "obsd.path");
29
30 if (access(name, R_OK))
31 {
32 a->warning("Cannot open %s", name);
33 return 0;
34 }
35 a->debug("...using %s", name);
36 return 1;
37 }
38
39 static void
40 obsd_init(struct pci_access *a)
41 {
42 char *name = pci_get_param(a, "obsd.path");
43
44 a->fd = open(name, O_RDWR, 0);
45 if (a->fd < 0)
46 a->error("obsd_init: %s open failed", name);
47 }
48
49 static void
50 obsd_cleanup(struct pci_access *a)
51 {
52 close(a->fd);
53 }
54
55 static int
56 obsd_read(struct pci_dev *d, int pos, byte *buf, int len)
57 {
58 struct pci_io pi;
59 union {
60 u_int32_t u32;
61 u_int16_t u16[2];
62 u_int8_t u8[4];
63 } u;
64
65 if (!(len == 1 || len == 2 || len == 4))
66 return pci_generic_block_read(d, pos, buf, len);
67
68 if (pos >= 256)
69 return 0;
70
71 pi.pi_sel.pc_bus = d->bus;
72 pi.pi_sel.pc_dev = d->dev;
73 pi.pi_sel.pc_func = d->func;
74
75 pi.pi_reg = pos - (pos % 4);
76 pi.pi_width = 4;
77
78 if (ioctl(d->access->fd, PCIOCREAD, &pi) < 0) {
79 if (errno == ENXIO)
80 pi.pi_data = 0xffffffff;
81 else
82 d->access->error("obsd_read: ioctl(PCIOCREAD) failed");
83 }
84 u.u32 = pi.pi_data;
85
86 switch (len)
87 {
88 case 1:
89 buf[0] = (u8) u.u8[pos % 4];
90 break;
91 case 2:
92 ((u16 *) buf)[0] = letoh16(u.u16[(pos % 4) / 2]);
93 break;
94 case 4:
95 ((u32 *) buf)[0] = (u32) letoh32(pi.pi_data);
96 break;
97 }
98 return 1;
99 }
100
101 static int
102 obsd_write(struct pci_dev *d, int pos, byte *buf, int len)
103 {
104 struct pci_io pi;
105
106 if (!(len == 1 || len == 2 || len == 4))
107 return pci_generic_block_write(d, pos, buf, len);
108
109 if (pos >= 256)
110 return 0;
111
112 pi.pi_sel.pc_bus = d->bus;
113 pi.pi_sel.pc_dev = d->dev;
114 pi.pi_sel.pc_func = d->func;
115
116 pi.pi_reg = pos;
117 pi.pi_width = len;
118
119 switch (len)
120 {
121 case 1:
122 pi.pi_data = buf[0];
123 break;
124 case 2:
125 pi.pi_data = ((u16 *) buf)[0];
126 break;
127 case 4:
128 pi.pi_data = ((u32 *) buf)[0];
129 break;
130 }
131
132 if (ioctl(d->access->fd, PCIOCWRITE, &pi) < 0)
133 d->access->error("obsd_write: ioctl(PCIOCWRITE) failed");
134
135 return 1;
136 }
137
138 struct pci_methods pm_obsd_device = {
139 "obsd-device",
140 "/dev/pci on OpenBSD",
141 obsd_config,
142 obsd_detect,
143 obsd_init,
144 obsd_cleanup,
145 pci_generic_scan,
146 pci_generic_fill_info,
147 obsd_read,
148 obsd_write,
149 NULL, /* read_vpd */
150 NULL, /* dev_init */
151 NULL /* dev_cleanup */
152 };