1*c2e0c6b5SAndroid Build Coastguard Worker /*
2*c2e0c6b5SAndroid Build Coastguard Worker * The PCI Library -- Direct Configuration access via SylixOS Ports
3*c2e0c6b5SAndroid Build Coastguard Worker *
4*c2e0c6b5SAndroid Build Coastguard Worker * Copyright (c) 2018 YuJian.Gong <[email protected]>
5*c2e0c6b5SAndroid Build Coastguard Worker *
6*c2e0c6b5SAndroid Build Coastguard Worker * Can be freely distributed and used under the terms of the GNU GPL v2+.
7*c2e0c6b5SAndroid Build Coastguard Worker *
8*c2e0c6b5SAndroid Build Coastguard Worker * SPDX-License-Identifier: GPL-2.0-or-later
9*c2e0c6b5SAndroid Build Coastguard Worker */
10*c2e0c6b5SAndroid Build Coastguard Worker
11*c2e0c6b5SAndroid Build Coastguard Worker #define _GNU_SOURCE
12*c2e0c6b5SAndroid Build Coastguard Worker #define __SYLIXOS_KERNEL
13*c2e0c6b5SAndroid Build Coastguard Worker #define __SYLIXOS_PCI_DRV
14*c2e0c6b5SAndroid Build Coastguard Worker #include <SylixOS.h>
15*c2e0c6b5SAndroid Build Coastguard Worker #include <stdlib.h>
16*c2e0c6b5SAndroid Build Coastguard Worker #include <string.h>
17*c2e0c6b5SAndroid Build Coastguard Worker
18*c2e0c6b5SAndroid Build Coastguard Worker #include "internal.h"
19*c2e0c6b5SAndroid Build Coastguard Worker
20*c2e0c6b5SAndroid Build Coastguard Worker static void
sylixos_scan(struct pci_access * a)21*c2e0c6b5SAndroid Build Coastguard Worker sylixos_scan(struct pci_access *a)
22*c2e0c6b5SAndroid Build Coastguard Worker {
23*c2e0c6b5SAndroid Build Coastguard Worker u8 busmap[256];
24*c2e0c6b5SAndroid Build Coastguard Worker int bus;
25*c2e0c6b5SAndroid Build Coastguard Worker
26*c2e0c6b5SAndroid Build Coastguard Worker memset(busmap, 0, sizeof(busmap));
27*c2e0c6b5SAndroid Build Coastguard Worker
28*c2e0c6b5SAndroid Build Coastguard Worker for (bus = 0; bus < PCI_MAX_BUS; bus++)
29*c2e0c6b5SAndroid Build Coastguard Worker if (!busmap[bus])
30*c2e0c6b5SAndroid Build Coastguard Worker pci_generic_scan_bus(a, busmap, 0, bus);
31*c2e0c6b5SAndroid Build Coastguard Worker }
32*c2e0c6b5SAndroid Build Coastguard Worker
33*c2e0c6b5SAndroid Build Coastguard Worker static void
sylixos_config(struct pci_access * a)34*c2e0c6b5SAndroid Build Coastguard Worker sylixos_config(struct pci_access *a)
35*c2e0c6b5SAndroid Build Coastguard Worker {
36*c2e0c6b5SAndroid Build Coastguard Worker pci_define_param(a, "sylixos.path", PCI_PATH_SYLIXOS_DEVICE, "Path to the SylixOS PCI device");
37*c2e0c6b5SAndroid Build Coastguard Worker }
38*c2e0c6b5SAndroid Build Coastguard Worker
39*c2e0c6b5SAndroid Build Coastguard Worker static int
sylixos_detect(struct pci_access * a)40*c2e0c6b5SAndroid Build Coastguard Worker sylixos_detect(struct pci_access *a)
41*c2e0c6b5SAndroid Build Coastguard Worker {
42*c2e0c6b5SAndroid Build Coastguard Worker char *name = pci_get_param(a, "sylixos.path");
43*c2e0c6b5SAndroid Build Coastguard Worker
44*c2e0c6b5SAndroid Build Coastguard Worker if (access(name, R_OK))
45*c2e0c6b5SAndroid Build Coastguard Worker {
46*c2e0c6b5SAndroid Build Coastguard Worker a->warning("Cannot open %s", name);
47*c2e0c6b5SAndroid Build Coastguard Worker return 0;
48*c2e0c6b5SAndroid Build Coastguard Worker }
49*c2e0c6b5SAndroid Build Coastguard Worker
50*c2e0c6b5SAndroid Build Coastguard Worker a->debug("...using %s", name);
51*c2e0c6b5SAndroid Build Coastguard Worker return 1;
52*c2e0c6b5SAndroid Build Coastguard Worker }
53*c2e0c6b5SAndroid Build Coastguard Worker
54*c2e0c6b5SAndroid Build Coastguard Worker static void
sylixos_init(struct pci_access * a UNUSED)55*c2e0c6b5SAndroid Build Coastguard Worker sylixos_init(struct pci_access *a UNUSED)
56*c2e0c6b5SAndroid Build Coastguard Worker {
57*c2e0c6b5SAndroid Build Coastguard Worker }
58*c2e0c6b5SAndroid Build Coastguard Worker
59*c2e0c6b5SAndroid Build Coastguard Worker static void
sylixos_cleanup(struct pci_access * a UNUSED)60*c2e0c6b5SAndroid Build Coastguard Worker sylixos_cleanup(struct pci_access *a UNUSED)
61*c2e0c6b5SAndroid Build Coastguard Worker {
62*c2e0c6b5SAndroid Build Coastguard Worker }
63*c2e0c6b5SAndroid Build Coastguard Worker
64*c2e0c6b5SAndroid Build Coastguard Worker static int
sylixos_read(struct pci_dev * d,int pos,byte * buf,int len)65*c2e0c6b5SAndroid Build Coastguard Worker sylixos_read(struct pci_dev *d, int pos, byte *buf, int len)
66*c2e0c6b5SAndroid Build Coastguard Worker {
67*c2e0c6b5SAndroid Build Coastguard Worker int ret = -1;
68*c2e0c6b5SAndroid Build Coastguard Worker u8 data_byte = -1;
69*c2e0c6b5SAndroid Build Coastguard Worker u16 data_word = -1;
70*c2e0c6b5SAndroid Build Coastguard Worker u32 data_dword = -1;
71*c2e0c6b5SAndroid Build Coastguard Worker
72*c2e0c6b5SAndroid Build Coastguard Worker if (!(len == 1 || len == 2 || len == 4))
73*c2e0c6b5SAndroid Build Coastguard Worker return pci_generic_block_read(d, pos, buf, len);
74*c2e0c6b5SAndroid Build Coastguard Worker
75*c2e0c6b5SAndroid Build Coastguard Worker if (pos >= 256)
76*c2e0c6b5SAndroid Build Coastguard Worker return 0;
77*c2e0c6b5SAndroid Build Coastguard Worker
78*c2e0c6b5SAndroid Build Coastguard Worker switch (len)
79*c2e0c6b5SAndroid Build Coastguard Worker {
80*c2e0c6b5SAndroid Build Coastguard Worker case 1:
81*c2e0c6b5SAndroid Build Coastguard Worker ret = pciConfigInByte(d->bus, d->dev, d->func, pos, &data_byte);
82*c2e0c6b5SAndroid Build Coastguard Worker if (ret != ERROR_NONE)
83*c2e0c6b5SAndroid Build Coastguard Worker return 0;
84*c2e0c6b5SAndroid Build Coastguard Worker buf[0] = (u8)data_byte;
85*c2e0c6b5SAndroid Build Coastguard Worker break;
86*c2e0c6b5SAndroid Build Coastguard Worker
87*c2e0c6b5SAndroid Build Coastguard Worker case 2:
88*c2e0c6b5SAndroid Build Coastguard Worker ret = pciConfigInWord(d->bus, d->dev, d->func, pos, &data_word);
89*c2e0c6b5SAndroid Build Coastguard Worker if (ret != ERROR_NONE)
90*c2e0c6b5SAndroid Build Coastguard Worker return 0;
91*c2e0c6b5SAndroid Build Coastguard Worker ((u16 *) buf)[0] = cpu_to_le16(data_word);
92*c2e0c6b5SAndroid Build Coastguard Worker break;
93*c2e0c6b5SAndroid Build Coastguard Worker
94*c2e0c6b5SAndroid Build Coastguard Worker case 4:
95*c2e0c6b5SAndroid Build Coastguard Worker ret = pciConfigInDword(d->bus, d->dev, d->func, pos, &data_dword);
96*c2e0c6b5SAndroid Build Coastguard Worker if (ret != ERROR_NONE)
97*c2e0c6b5SAndroid Build Coastguard Worker return 0;
98*c2e0c6b5SAndroid Build Coastguard Worker ((u32 *) buf)[0] = cpu_to_le32(data_dword);
99*c2e0c6b5SAndroid Build Coastguard Worker break;
100*c2e0c6b5SAndroid Build Coastguard Worker }
101*c2e0c6b5SAndroid Build Coastguard Worker
102*c2e0c6b5SAndroid Build Coastguard Worker return 1;
103*c2e0c6b5SAndroid Build Coastguard Worker }
104*c2e0c6b5SAndroid Build Coastguard Worker
105*c2e0c6b5SAndroid Build Coastguard Worker static int
sylixos_write(struct pci_dev * d,int pos,byte * buf,int len)106*c2e0c6b5SAndroid Build Coastguard Worker sylixos_write(struct pci_dev *d, int pos, byte *buf, int len)
107*c2e0c6b5SAndroid Build Coastguard Worker {
108*c2e0c6b5SAndroid Build Coastguard Worker int ret = PX_ERROR;
109*c2e0c6b5SAndroid Build Coastguard Worker u8 data_byte;
110*c2e0c6b5SAndroid Build Coastguard Worker u16 data_word;
111*c2e0c6b5SAndroid Build Coastguard Worker u32 data_dword;
112*c2e0c6b5SAndroid Build Coastguard Worker
113*c2e0c6b5SAndroid Build Coastguard Worker if (!(len == 1 || len == 2 || len == 4))
114*c2e0c6b5SAndroid Build Coastguard Worker return pci_generic_block_write(d, pos, buf, len);
115*c2e0c6b5SAndroid Build Coastguard Worker
116*c2e0c6b5SAndroid Build Coastguard Worker if (pos >= 256)
117*c2e0c6b5SAndroid Build Coastguard Worker return 0;
118*c2e0c6b5SAndroid Build Coastguard Worker
119*c2e0c6b5SAndroid Build Coastguard Worker switch (len)
120*c2e0c6b5SAndroid Build Coastguard Worker {
121*c2e0c6b5SAndroid Build Coastguard Worker case 1:
122*c2e0c6b5SAndroid Build Coastguard Worker data_byte = buf[0];
123*c2e0c6b5SAndroid Build Coastguard Worker ret = pciConfigOutByte(d->bus, d->dev, d->func, pos, data_byte);
124*c2e0c6b5SAndroid Build Coastguard Worker if (ret != ERROR_NONE)
125*c2e0c6b5SAndroid Build Coastguard Worker return 0;
126*c2e0c6b5SAndroid Build Coastguard Worker break;
127*c2e0c6b5SAndroid Build Coastguard Worker
128*c2e0c6b5SAndroid Build Coastguard Worker case 2:
129*c2e0c6b5SAndroid Build Coastguard Worker data_word = le16_to_cpu(((u16 *) buf)[0]);
130*c2e0c6b5SAndroid Build Coastguard Worker ret = pciConfigOutWord(d->bus, d->dev, d->func, pos, data_word);
131*c2e0c6b5SAndroid Build Coastguard Worker if (ret != ERROR_NONE)
132*c2e0c6b5SAndroid Build Coastguard Worker return 0;
133*c2e0c6b5SAndroid Build Coastguard Worker break;
134*c2e0c6b5SAndroid Build Coastguard Worker
135*c2e0c6b5SAndroid Build Coastguard Worker case 4:
136*c2e0c6b5SAndroid Build Coastguard Worker data_dword = le32_to_cpu(((u32 *) buf)[0]);
137*c2e0c6b5SAndroid Build Coastguard Worker ret = pciConfigOutDword(d->bus, d->dev, d->func, pos, data_dword);
138*c2e0c6b5SAndroid Build Coastguard Worker if (ret != ERROR_NONE)
139*c2e0c6b5SAndroid Build Coastguard Worker return 0;
140*c2e0c6b5SAndroid Build Coastguard Worker break;
141*c2e0c6b5SAndroid Build Coastguard Worker }
142*c2e0c6b5SAndroid Build Coastguard Worker
143*c2e0c6b5SAndroid Build Coastguard Worker return 1;
144*c2e0c6b5SAndroid Build Coastguard Worker }
145*c2e0c6b5SAndroid Build Coastguard Worker
146*c2e0c6b5SAndroid Build Coastguard Worker struct pci_methods pm_sylixos_device = {
147*c2e0c6b5SAndroid Build Coastguard Worker .name = "sylixos-device",
148*c2e0c6b5SAndroid Build Coastguard Worker .help = "SylixOS /proc/pci device",
149*c2e0c6b5SAndroid Build Coastguard Worker .config = sylixos_config,
150*c2e0c6b5SAndroid Build Coastguard Worker .detect = sylixos_detect,
151*c2e0c6b5SAndroid Build Coastguard Worker .init = sylixos_init,
152*c2e0c6b5SAndroid Build Coastguard Worker .cleanup = sylixos_cleanup,
153*c2e0c6b5SAndroid Build Coastguard Worker .scan = sylixos_scan,
154*c2e0c6b5SAndroid Build Coastguard Worker .fill_info = pci_generic_fill_info,
155*c2e0c6b5SAndroid Build Coastguard Worker .read = sylixos_read,
156*c2e0c6b5SAndroid Build Coastguard Worker .write = sylixos_write,
157*c2e0c6b5SAndroid Build Coastguard Worker };
158