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