]> git.ipfire.org Git - thirdparty/pciutils.git/blob - lib/nbsd-libpci.c
Fix symbol versioning of pci_init()
[thirdparty/pciutils.git] / lib / nbsd-libpci.c
1 /*
2 * The PCI Library -- NetBSD libpci access
3 * (based on FreeBSD /dev/pci access)
4 *
5 * Copyright (c) 1999 Jari Kirma <kirma@cs.hut.fi>
6 * Copyright (c) 2002 Quentin Garnier <cube@cubidou.net>
7 * Copyright (c) 2002 Martin Mares <mj@ucw.cz>
8 *
9 * Can be freely distributed and used under the terms of the GNU GPL.
10 */
11
12 /*
13 * Read functionality of this driver is briefly tested, and seems
14 * to supply basic information correctly, but I promise no more.
15 */
16
17 #include <fcntl.h>
18 #include <string.h>
19 #include <unistd.h>
20
21 #include <pci.h>
22
23 #include "internal.h"
24
25 static void
26 nbsd_config(struct pci_access *a)
27 {
28 pci_define_param(a, "nbsd.path", PCI_PATH_NBSD_DEVICE, "Path to the NetBSD PCI device");
29 }
30
31 static int
32 nbsd_detect(struct pci_access *a)
33 {
34 char *name = pci_get_param(a, "nbsd.path");
35
36 if (access(name, R_OK))
37 {
38 a->warning("Cannot open %s", name);
39 return 0;
40 }
41
42 if (!access(name, W_OK))
43 a->writeable = O_RDWR;
44 a->debug("...using %s", name);
45 return 1;
46 }
47
48 static void
49 nbsd_init(struct pci_access *a)
50 {
51 char *name = pci_get_param(a, "nbsd.path");
52 int mode = a->writeable ? O_RDWR : O_RDONLY;
53
54 a->fd = open(name, mode, 0);
55 if (a->fd < 0)
56 a->error("nbsd_init: %s open failed", name);
57 }
58
59 static void
60 nbsd_cleanup(struct pci_access *a)
61 {
62 close(a->fd);
63 }
64
65 static int
66 nbsd_read(struct pci_dev *d, int pos, byte *buf, int len)
67 {
68 pcireg_t val;
69 int shift;
70
71 if (!(len == 1 || len == 2 || len == 4))
72 return pci_generic_block_read(d, pos, buf, len);
73
74 if (pos >= 4096)
75 return 0;
76
77 shift = 8*(pos % 4);
78 pos &= ~3;
79
80 if (pcibus_conf_read(d->access->fd, d->bus, d->dev, d->func, pos, &val) < 0)
81 d->access->error("nbsd_read: pci_bus_conf_read() failed");
82
83 switch (len)
84 {
85 case 1:
86 *buf = val >> shift;
87 break;
88 case 2:
89 *(u16*)buf = cpu_to_le16(val >> shift);
90 break;
91 case 4:
92 *(u32*)buf = cpu_to_le32(val);
93 break;
94 }
95 return 1;
96 }
97
98 static int
99 nbsd_write(struct pci_dev *d, int pos, byte *buf, int len)
100 {
101 pcireg_t val = 0;
102 int shift;
103
104 if (!(len == 1 || len == 2 || len == 4))
105 return pci_generic_block_write(d, pos, buf, len);
106
107 if (pos >= 256)
108 return 0;
109
110 /*
111 * BEWARE: NetBSD seems to support only 32-bit access, so we have
112 * to emulate byte and word writes by read-modify-write, possibly
113 * causing troubles.
114 */
115
116 shift = 8*(pos % 4);
117 pos &= ~3;
118 if (len != 4)
119 {
120 if (pcibus_conf_read(d->access->fd, d->bus, d->dev, d->func, pos, &val) < 0)
121 d->access->error("nbsd_write: pci_bus_conf_read() failed");
122 }
123
124 switch (len)
125 {
126 case 1:
127 val = (val & ~(0xff << shift)) | (buf[0] << shift);
128 break;
129 case 2:
130 val = (val & ~(0xffff << shift)) | (le16_to_cpu(*(u16*)buf) << shift);
131 break;
132 case 4:
133 val = le32_to_cpu(*(u32*)buf);
134 break;
135 }
136
137 if (pcibus_conf_write(d->access->fd, d->bus, d->dev, d->func, pos, val) < 0)
138 d->access->error("nbsd_write: pci_bus_conf_write() failed");
139
140 return 1;
141 }
142
143 struct pci_methods pm_nbsd_libpci = {
144 "nbsd-libpci",
145 "NetBSD libpci",
146 nbsd_config,
147 nbsd_detect,
148 nbsd_init,
149 nbsd_cleanup,
150 pci_generic_scan,
151 pci_generic_fill_info,
152 nbsd_read,
153 nbsd_write,
154 NULL, /* read_vpd */
155 NULL, /* dev_init */
156 NULL /* dev_cleanup */
157 };