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