]>
Commit | Line | Data |
---|---|---|
168b4f46 MM |
1 | /* |
2 | * The PCI Library -- FreeBSD /dev/pci access | |
3 | * | |
4 | * Copyright (c) 1999 Jari Kirma <kirma@cs.hut.fi> | |
ab12277e | 5 | * Updated in 2003 by Samy Al Bahra <samy@kerneled.com> |
168b4f46 MM |
6 | * |
7 | * Can be freely distributed and used under the terms of the GNU GPL. | |
8 | */ | |
9 | ||
ac9956a8 | 10 | #include <errno.h> |
168b4f46 | 11 | #include <fcntl.h> |
ac9956a8 | 12 | #include <stdio.h> |
168b4f46 MM |
13 | #include <string.h> |
14 | #include <unistd.h> | |
ab12277e | 15 | #include <osreldate.h> |
d1058e9d MM |
16 | #include <stdint.h> |
17 | ||
18 | #ifdef __FreeBSD_kernel_version | |
19 | # ifndef __FreeBSD_version | |
20 | # define __FreeBSD_version __FreeBSD_kernel_version | |
21 | # endif | |
22 | #endif | |
ab12277e | 23 | |
99091df9 | 24 | #if __FreeBSD_version < 430000 && !defined(__DragonFly__) |
ac9956a8 | 25 | # include <pci/pcivar.h> |
ab12277e MM |
26 | # include <pci/pci_ioctl.h> |
27 | #else | |
28 | # include <sys/pciio.h> | |
29 | #endif | |
168b4f46 MM |
30 | |
31 | #include "internal.h" | |
32 | ||
33 | static void | |
34 | fbsd_config(struct pci_access *a) | |
35 | { | |
cb6ee324 | 36 | pci_define_param(a, "fbsd.path", PCI_PATH_FBSD_DEVICE, "Path to the FreeBSD PCI device"); |
168b4f46 MM |
37 | } |
38 | ||
39 | static int | |
40 | fbsd_detect(struct pci_access *a) | |
41 | { | |
cb6ee324 | 42 | char *name = pci_get_param(a, "fbsd.path"); |
168b4f46 MM |
43 | |
44 | if (access(name, R_OK)) | |
45 | { | |
46 | a->warning("Cannot open %s", name); | |
47 | return 0; | |
48 | } | |
49 | a->debug("...using %s", name); | |
50 | return 1; | |
51 | } | |
52 | ||
53 | static void | |
54 | fbsd_init(struct pci_access *a) | |
55 | { | |
cb6ee324 | 56 | char *name = pci_get_param(a, "fbsd.path"); |
168b4f46 MM |
57 | |
58 | a->fd = open(name, O_RDWR, 0); | |
59 | if (a->fd < 0) | |
9c79fcc4 | 60 | a->error("fbsd_init: %s open failed", name); |
168b4f46 MM |
61 | } |
62 | ||
63 | static void | |
64 | fbsd_cleanup(struct pci_access *a) | |
65 | { | |
66 | close(a->fd); | |
67 | } | |
68 | ||
69 | static int | |
70 | fbsd_read(struct pci_dev *d, int pos, byte *buf, int len) | |
71 | { | |
72 | struct pci_io pi; | |
73 | ||
74 | if (!(len == 1 || len == 2 || len == 4)) | |
9c79fcc4 | 75 | return pci_generic_block_read(d, pos, buf, len); |
168b4f46 | 76 | |
09817437 MM |
77 | if (pos >= 256) |
78 | return 0; | |
79 | ||
ac9956a8 MM |
80 | #if __FreeBSD_version >= 700053 |
81 | pi.pi_sel.pc_domain = d->domain; | |
82 | #endif | |
168b4f46 MM |
83 | pi.pi_sel.pc_bus = d->bus; |
84 | pi.pi_sel.pc_dev = d->dev; | |
85 | pi.pi_sel.pc_func = d->func; | |
86 | ||
87 | pi.pi_reg = pos; | |
88 | pi.pi_width = len; | |
94db5c82 | 89 | |
168b4f46 | 90 | if (ioctl(d->access->fd, PCIOCREAD, &pi) < 0) |
ac9956a8 MM |
91 | { |
92 | if (errno == ENODEV) | |
9c79fcc4 | 93 | return 0; |
ac9956a8 MM |
94 | d->access->error("fbsd_read: ioctl(PCIOCREAD) failed: %s", strerror(errno)); |
95 | } | |
94db5c82 | 96 | |
168b4f46 MM |
97 | switch (len) |
98 | { | |
99 | case 1: | |
100 | buf[0] = (u8) pi.pi_data; | |
101 | break; | |
102 | case 2: | |
ac9956a8 | 103 | ((u16 *) buf)[0] = cpu_to_le16((u16) pi.pi_data); |
168b4f46 MM |
104 | break; |
105 | case 4: | |
ac9956a8 | 106 | ((u32 *) buf)[0] = cpu_to_le32((u32) pi.pi_data); |
168b4f46 MM |
107 | break; |
108 | } | |
109 | return 1; | |
110 | } | |
111 | ||
112 | static int | |
113 | fbsd_write(struct pci_dev *d, int pos, byte *buf, int len) | |
114 | { | |
115 | struct pci_io pi; | |
116 | ||
117 | if (!(len == 1 || len == 2 || len == 4)) | |
9c79fcc4 | 118 | return pci_generic_block_write(d, pos, buf, len); |
168b4f46 | 119 | |
09817437 MM |
120 | if (pos >= 256) |
121 | return 0; | |
122 | ||
ac9956a8 MM |
123 | #if __FreeBSD_version >= 700053 |
124 | pi.pi_sel.pc_domain = d->domain; | |
125 | #endif | |
168b4f46 MM |
126 | pi.pi_sel.pc_bus = d->bus; |
127 | pi.pi_sel.pc_dev = d->dev; | |
128 | pi.pi_sel.pc_func = d->func; | |
129 | ||
130 | pi.pi_reg = pos; | |
131 | pi.pi_width = len; | |
94db5c82 | 132 | |
168b4f46 MM |
133 | switch (len) |
134 | { | |
135 | case 1: | |
136 | pi.pi_data = buf[0]; | |
137 | break; | |
138 | case 2: | |
ac9956a8 | 139 | pi.pi_data = le16_to_cpu(((u16 *) buf)[0]); |
168b4f46 MM |
140 | break; |
141 | case 4: | |
ac9956a8 | 142 | pi.pi_data = le32_to_cpu(((u32 *) buf)[0]); |
168b4f46 MM |
143 | break; |
144 | } | |
94db5c82 | 145 | |
168b4f46 MM |
146 | if (ioctl(d->access->fd, PCIOCWRITE, &pi) < 0) |
147 | { | |
ac9956a8 | 148 | if (errno == ENODEV) |
9c79fcc4 | 149 | return 0; |
ac9956a8 | 150 | d->access->error("fbsd_write: ioctl(PCIOCWRITE) failed: %s", strerror(errno)); |
168b4f46 MM |
151 | } |
152 | ||
153 | return 1; | |
154 | } | |
155 | ||
156 | struct pci_methods pm_fbsd_device = { | |
9ff67879 MM |
157 | "fbsd-device", |
158 | "FreeBSD /dev/pci device", | |
168b4f46 MM |
159 | fbsd_config, |
160 | fbsd_detect, | |
161 | fbsd_init, | |
162 | fbsd_cleanup, | |
163 | pci_generic_scan, | |
164 | pci_generic_fill_info, | |
165 | fbsd_read, | |
166 | fbsd_write, | |
52c81519 | 167 | NULL, /* read_vpd */ |
168b4f46 MM |
168 | NULL, /* dev_init */ |
169 | NULL /* dev_cleanup */ | |
170 | }; |