]>
Commit | Line | Data |
---|---|---|
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 | ||
19 | static void | |
20 | obsd_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 | ||
25 | static int | |
26 | obsd_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 | ||
39 | static void | |
40 | obsd_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 | ||
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)) | |
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 | ||
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)) | |
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 | ||
138 | struct 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 | }; |