]> mj.ucw.cz Git - pciutils.git/blob - lib/sylixos-device.c
6bb9958f25964458e7341b13e2e004a5171d347a
[pciutils.git] / lib / sylixos-device.c
1 /*
2  *  The PCI Library -- Direct Configuration access via SylixOS Ports
3  *
4  *  Copyright (c) 2018 YuJian.Gong <gongyujian@acoinfo.com>
5  *
6  *  Can be freely distributed and used under the terms of the GNU GPL.
7  */
8
9 #define _GNU_SOURCE
10 #define  __SYLIXOS_KERNEL
11 #define  __SYLIXOS_PCI_DRV
12 #include <SylixOS.h>
13 #include <stdlib.h>
14 #include <string.h>
15
16 #include "internal.h"
17
18 #define PCI_VENDOR_ID_IS_INVALID(vendor) (((vendor) == 0xffff) || ((vendor) == 0x0000))
19
20 typedef struct {
21     struct pci_access *a;
22     byte *busmap;
23     int bus;
24 } pci_dev_scan;
25
26 static int
27 sylixos_pci_traversal (int (*function)(), void *arg, int min_bus, int max_bus)
28 {
29   int bus, dev, func;
30   u8 header;
31   u16 vendor;
32
33   if (!function || (min_bus < 0) || (max_bus < 0))
34     {
35       return  (PX_ERROR);
36     }
37
38   min_bus = (min_bus > (PCI_MAX_BUS - 1)) ? (PCI_MAX_BUS - 1) : min_bus;
39   max_bus = (max_bus > (PCI_MAX_BUS - 1)) ? (PCI_MAX_BUS - 1) : max_bus;
40
41   for (bus = min_bus; bus <= max_bus; bus++)
42     {
43       for (dev = 0; dev < PCI_MAX_SLOTS; dev++)
44     {
45       for (func = 0; func < PCI_MAX_FUNCTIONS; func++)
46     {
47       pciConfigInWord(bus, dev, func, PCI_VENDOR_ID, &vendor);
48       if (PCI_VENDOR_ID_IS_INVALID(vendor))
49         {
50           if (func == 0)
51             {
52               break;
53             }
54           continue;
55         }
56
57       if (function(bus, dev, func, arg) != ERROR_NONE)
58         {
59           goto  __out;
60         }
61
62       if (func == 0)
63         {
64           pciConfigInByte(bus, dev, func, PCI_HEADER_TYPE, &header);
65           if ((header & PCI_HEADER_MULTI_FUNC) != PCI_HEADER_MULTI_FUNC)
66             {
67               break;
68             }
69         }
70     }
71     }
72     }
73
74 __out:
75   return  (ERROR_NONE);
76 }
77
78 static int
79 pci_dev_list_create (int  bus, int  dev, int  func, void *arg)
80 {
81   pci_dev_scan *f = (pci_dev_scan *)arg;
82   struct pci_dev *d;
83   u32 vd;
84
85   f->busmap[bus] = 1;
86   d = pci_alloc_dev(f->a);
87   d->bus = bus;
88   d->dev = dev;
89   d->func = func;
90
91   vd = pci_read_long(d, PCI_VENDOR_ID);
92   d->vendor_id = vd & 0xffff;
93   d->device_id = vd >> 16U;
94   d->known_fields = PCI_FILL_IDENT;
95   d->hdrtype = pci_read_byte(d, PCI_HEADER_TYPE) & 0x7f;
96   pci_link_dev(f->a, d);
97
98   return  (ERROR_NONE);
99 }
100
101 static void
102 pci_generic_scan_bus_tbl(struct pci_access *a, byte *busmap, int bus)
103 {
104   pci_dev_scan    f;
105
106   f.a = a;
107   f.busmap = busmap;
108   f.bus = bus;
109
110   sylixos_pci_traversal(pci_dev_list_create, &f, bus, PCI_MAX_BUS);
111 }
112
113 static void
114 sylixos_scan(struct pci_access *a)
115 {
116   int se;
117   u8 busmap[256];
118   char *env;
119
120   memset(busmap, 0, sizeof(busmap));
121
122   env = getenv(PCI_SCAN_FUNC);
123   if (!env)
124     {
125       pci_generic_scan_bus(a, busmap, 0);
126       return;
127     }
128
129   se = atoi(env);
130   if (se)
131     {
132       pci_generic_scan_bus_tbl(a, busmap, 0);
133     }
134   else
135     {
136       pci_generic_scan_bus(a, busmap, 0);
137     }
138 }
139
140 static void
141 sylixos_config(struct pci_access *a)
142 {
143   pci_define_param(a, "sylixos.path", PCI_PATH_SYLIXOS_DEVICE, "Path to the SylixOS PCI device");
144 }
145
146 static int
147 sylixos_detect(struct pci_access *a)
148 {
149   char *name = pci_get_param(a, "sylixos.path");
150
151   if (access(name, R_OK))
152     {
153       a->warning("Cannot open %s", name);
154       return 0;
155     }
156
157   a->debug("...using %s", name);
158
159   return 1;
160 }
161
162 static void
163 sylixos_init(struct pci_access *a)
164 {
165   a->fd = -1;
166 }
167
168 static void
169 sylixos_cleanup(struct pci_access *a)
170 {
171     a->fd = -1;
172 }
173
174 static int
175 sylixos_read(struct pci_dev *d, int pos, byte *buf, int len)
176 {
177   int ret = -1;
178   u8  data_byte = -1;
179   u16 data_word = -1;
180   u32 data_dword = -1;
181
182   if (!(len == 1 || len == 2 || len == 4))
183     {
184       return pci_generic_block_read(d, pos, buf, len);
185     }
186
187   if (pos >= 256)
188     {
189       return 0;
190     }
191
192   switch (len)
193     {
194     case 1:
195       ret = pciConfigInByte(d->bus, d->dev, d->func, pos, &data_byte);
196       if (ret != ERROR_NONE)
197         {
198           return  (0);
199         }
200       buf[0] = (u8)data_byte;
201       break;
202
203     case 2:
204       ret = pciConfigInWord(d->bus, d->dev, d->func, pos, &data_word);
205       if (ret != ERROR_NONE)
206         {
207           return  (0);
208         }
209       ((u16 *) buf)[0] = cpu_to_le16(data_word);
210       break;
211
212     case 4:
213       ret = pciConfigInDword(d->bus, d->dev, d->func, pos, &data_dword);
214       if (ret != ERROR_NONE)
215         {
216           return  (0);
217         }
218       ((u32 *) buf)[0] = cpu_to_le32(data_dword);
219       break;
220     }
221
222   return 1;
223 }
224
225 static int
226 sylixos_write(struct pci_dev *d, int pos, byte *buf, int len)
227 {
228   int ret = PX_ERROR;
229   u8 data_byte;
230   u16 data_word;
231   u32 data_dword;
232
233   if (!(len == 1 || len == 2 || len == 4))
234     {
235       return pci_generic_block_write(d, pos, buf, len);
236     }
237
238   if (pos >= 256)
239     {
240       return 0;
241     }
242
243   switch (len)
244     {
245     case 1:
246       data_byte = buf[0];
247       ret = pciConfigOutByte(d->bus, d->dev, d->func, pos, data_byte);
248       if (ret != ERROR_NONE)
249         {
250           return  (0);
251         }
252       break;
253
254     case 2:
255       data_word = le16_to_cpu(((u16 *) buf)[0]);
256       ret = pciConfigOutWord(d->bus, d->dev, d->func, pos, data_word);
257       if (ret != ERROR_NONE)
258         {
259           return  (0);
260         }
261       break;
262
263     case 4:
264       data_dword = le32_to_cpu(((u32 *) buf)[0]);
265       ret = pciConfigOutDword(d->bus, d->dev, d->func, pos, data_dword);
266       if (ret != ERROR_NONE)
267         {
268           return  (0);
269         }
270       break;
271     }
272
273   return 1;
274 }
275
276 struct pci_methods pm_sylixos_device = {
277   "sylixos-device",
278   "SylixOS /proc/pci device",
279   sylixos_config,                                                                           /* config                       */
280   sylixos_detect,
281   sylixos_init,
282   sylixos_cleanup,
283   sylixos_scan,
284   pci_generic_fill_info,
285   sylixos_read,
286   sylixos_write,
287   NULL,                                                                                 /* read_vpd                     */
288   NULL,                                                                                 /* init_dev                     */
289   NULL                                                                                  /* cleanup_dev                  */
290 };