2 * The PCI Library -- Direct Configuration access via SylixOS Ports
4 * Copyright (c) 2018 YuJian.Gong <gongyujian@acoinfo.com>
6 * Can be freely distributed and used under the terms of the GNU GPL.
10 #define __SYLIXOS_KERNEL
11 #define __SYLIXOS_PCI_DRV
18 #define PCI_VENDOR_ID_IS_INVALID(vendor) (((vendor) == 0xffff) || ((vendor) == 0x0000))
27 sylixos_pci_traversal (int (*function)(), void *arg, int min_bus, int max_bus)
33 if (!function || (min_bus < 0) || (max_bus < 0))
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;
41 for (bus = min_bus; bus <= max_bus; bus++)
43 for (dev = 0; dev < PCI_MAX_SLOTS; dev++)
45 for (func = 0; func < PCI_MAX_FUNCTIONS; func++)
47 pciConfigInWord(bus, dev, func, PCI_VENDOR_ID, &vendor);
48 if (PCI_VENDOR_ID_IS_INVALID(vendor))
57 if (function(bus, dev, func, arg) != ERROR_NONE)
64 pciConfigInByte(bus, dev, func, PCI_HEADER_TYPE, &header);
65 if ((header & PCI_HEADER_MULTI_FUNC) != PCI_HEADER_MULTI_FUNC)
79 pci_dev_list_create (int bus, int dev, int func, void *arg)
81 pci_dev_scan *f = (pci_dev_scan *)arg;
86 d = pci_alloc_dev(f->a);
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);
102 pci_generic_scan_bus_tbl(struct pci_access *a, byte *busmap, int bus)
110 sylixos_pci_traversal(pci_dev_list_create, &f, bus, PCI_MAX_BUS);
114 sylixos_scan(struct pci_access *a)
120 memset(busmap, 0, sizeof(busmap));
122 env = getenv(PCI_SCAN_FUNC);
125 pci_generic_scan_bus(a, busmap, 0);
132 pci_generic_scan_bus_tbl(a, busmap, 0);
136 pci_generic_scan_bus(a, busmap, 0);
141 sylixos_config(struct pci_access *a)
143 pci_define_param(a, "sylixos.path", PCI_PATH_SYLIXOS_DEVICE, "Path to the SylixOS PCI device");
147 sylixos_detect(struct pci_access *a)
149 char *name = pci_get_param(a, "sylixos.path");
151 if (access(name, R_OK))
153 a->warning("Cannot open %s", name);
157 a->debug("...using %s", name);
163 sylixos_init(struct pci_access *a)
169 sylixos_cleanup(struct pci_access *a)
175 sylixos_read(struct pci_dev *d, int pos, byte *buf, int len)
182 if (!(len == 1 || len == 2 || len == 4))
184 return pci_generic_block_read(d, pos, buf, len);
195 ret = pciConfigInByte(d->bus, d->dev, d->func, pos, &data_byte);
196 if (ret != ERROR_NONE)
200 buf[0] = (u8)data_byte;
204 ret = pciConfigInWord(d->bus, d->dev, d->func, pos, &data_word);
205 if (ret != ERROR_NONE)
209 ((u16 *) buf)[0] = cpu_to_le16(data_word);
213 ret = pciConfigInDword(d->bus, d->dev, d->func, pos, &data_dword);
214 if (ret != ERROR_NONE)
218 ((u32 *) buf)[0] = cpu_to_le32(data_dword);
226 sylixos_write(struct pci_dev *d, int pos, byte *buf, int len)
233 if (!(len == 1 || len == 2 || len == 4))
235 return pci_generic_block_write(d, pos, buf, len);
247 ret = pciConfigOutByte(d->bus, d->dev, d->func, pos, data_byte);
248 if (ret != ERROR_NONE)
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)
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)
276 struct pci_methods pm_sylixos_device = {
278 "SylixOS /proc/pci device",
279 sylixos_config, /* config */
284 pci_generic_fill_info,
289 NULL /* cleanup_dev */