]> git.ipfire.org Git - thirdparty/pciutils.git/blame - lib/obsd-device.c
fbsd-device: Fix fbsd-device backend on DragonFly BSD.
[thirdparty/pciutils.git] / lib / obsd-device.c
CommitLineData
b6359063
MM
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
19static void
20obsd_config(struct pci_access *a)
21{
cb6ee324 22 pci_define_param(a, "obsd.path", PCI_PATH_OBSD_DEVICE, "Path to the OpenBSD PCI device");
b6359063
MM
23}
24
25static int
26obsd_detect(struct pci_access *a)
27{
cb6ee324 28 char *name = pci_get_param(a, "obsd.path");
b6359063
MM
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
39static void
40obsd_init(struct pci_access *a)
41{
cb6ee324 42 char *name = pci_get_param(a, "obsd.path");
b6359063
MM
43
44 a->fd = open(name, O_RDWR, 0);
45 if (a->fd < 0)
9c79fcc4 46 a->error("obsd_init: %s open failed", name);
b6359063
MM
47}
48
49static void
50obsd_cleanup(struct pci_access *a)
51{
52 close(a->fd);
53}
54
55static int
56obsd_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))
9c79fcc4 66 return pci_generic_block_read(d, pos, buf, len);
b6359063
MM
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;
94db5c82 77
b6359063 78 if (ioctl(d->access->fd, PCIOCREAD, &pi) < 0) {
9c79fcc4 79 if (errno == ENXIO)
b6359063 80 pi.pi_data = 0xffffffff;
9c79fcc4 81 else
b6359063 82 d->access->error("obsd_read: ioctl(PCIOCREAD) failed");
b6359063
MM
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
101static int
102obsd_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))
9c79fcc4 107 return pci_generic_block_write(d, pos, buf, len);
b6359063
MM
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;
94db5c82 118
b6359063
MM
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 }
94db5c82 131
b6359063 132 if (ioctl(d->access->fd, PCIOCWRITE, &pi) < 0)
9c79fcc4 133 d->access->error("obsd_write: ioctl(PCIOCWRITE) failed");
b6359063
MM
134
135 return 1;
136}
137
138struct pci_methods pm_obsd_device = {
9ff67879
MM
139 "obsd-device",
140 "/dev/pci on OpenBSD",
b6359063
MM
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,
52c81519 149 NULL, /* read_vpd */
b6359063
MM
150 NULL, /* dev_init */
151 NULL /* dev_cleanup */
152};