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))
36 min_bus
= (min_bus
> (PCI_MAX_BUS
- 1)) ? (PCI_MAX_BUS
- 1) : min_bus
;
37 max_bus
= (max_bus
> (PCI_MAX_BUS
- 1)) ? (PCI_MAX_BUS
- 1) : max_bus
;
39 for (bus
= min_bus
; bus
<= max_bus
; bus
++)
41 for (dev
= 0; dev
< PCI_MAX_SLOTS
; dev
++)
43 for (func
= 0; func
< PCI_MAX_FUNCTIONS
; func
++)
45 pciConfigInWord(bus
, dev
, func
, PCI_VENDOR_ID
, &vendor
);
46 if (PCI_VENDOR_ID_IS_INVALID(vendor
))
53 if (function(bus
, dev
, func
, arg
) != ERROR_NONE
)
58 pciConfigInByte(bus
, dev
, func
, PCI_HEADER_TYPE
, &header
);
59 if ((header
& PCI_HEADER_MULTI_FUNC
) != PCI_HEADER_MULTI_FUNC
)
71 pci_dev_list_create (int bus
, int dev
, int func
, void *arg
)
73 pci_dev_scan
*f
= (pci_dev_scan
*)arg
;
78 d
= pci_alloc_dev(f
->a
);
83 vd
= pci_read_long(d
, PCI_VENDOR_ID
);
84 d
->vendor_id
= vd
& 0xffff;
85 d
->device_id
= vd
>> 16U;
86 d
->known_fields
= PCI_FILL_IDENT
;
87 d
->hdrtype
= pci_read_byte(d
, PCI_HEADER_TYPE
) & 0x7f;
88 pci_link_dev(f
->a
, d
);
94 pci_generic_scan_bus_tbl(struct pci_access
*a
, byte
*busmap
, int bus
)
102 sylixos_pci_traversal(pci_dev_list_create
, &f
, bus
, PCI_MAX_BUS
);
106 sylixos_scan(struct pci_access
*a
)
112 memset(busmap
, 0, sizeof(busmap
));
114 env
= getenv(PCI_SCAN_FUNC
);
117 pci_generic_scan_bus(a
, busmap
, 0);
123 pci_generic_scan_bus_tbl(a
, busmap
, 0);
125 pci_generic_scan_bus(a
, busmap
, 0);
129 sylixos_config(struct pci_access
*a
)
131 pci_define_param(a
, "sylixos.path", PCI_PATH_SYLIXOS_DEVICE
, "Path to the SylixOS PCI device");
135 sylixos_detect(struct pci_access
*a
)
137 char *name
= pci_get_param(a
, "sylixos.path");
139 if (access(name
, R_OK
))
141 a
->warning("Cannot open %s", name
);
145 a
->debug("...using %s", name
);
150 sylixos_init(struct pci_access
*a
)
156 sylixos_cleanup(struct pci_access
*a
)
162 sylixos_read(struct pci_dev
*d
, int pos
, byte
*buf
, int len
)
169 if (!(len
== 1 || len
== 2 || len
== 4))
170 return pci_generic_block_read(d
, pos
, buf
, len
);
178 ret
= pciConfigInByte(d
->bus
, d
->dev
, d
->func
, pos
, &data_byte
);
179 if (ret
!= ERROR_NONE
)
181 buf
[0] = (u8
)data_byte
;
185 ret
= pciConfigInWord(d
->bus
, d
->dev
, d
->func
, pos
, &data_word
);
186 if (ret
!= ERROR_NONE
)
188 ((u16
*) buf
)[0] = cpu_to_le16(data_word
);
192 ret
= pciConfigInDword(d
->bus
, d
->dev
, d
->func
, pos
, &data_dword
);
193 if (ret
!= ERROR_NONE
)
195 ((u32
*) buf
)[0] = cpu_to_le32(data_dword
);
203 sylixos_write(struct pci_dev
*d
, int pos
, byte
*buf
, int len
)
210 if (!(len
== 1 || len
== 2 || len
== 4))
211 return pci_generic_block_write(d
, pos
, buf
, len
);
220 ret
= pciConfigOutByte(d
->bus
, d
->dev
, d
->func
, pos
, data_byte
);
221 if (ret
!= ERROR_NONE
)
226 data_word
= le16_to_cpu(((u16
*) buf
)[0]);
227 ret
= pciConfigOutWord(d
->bus
, d
->dev
, d
->func
, pos
, data_word
);
228 if (ret
!= ERROR_NONE
)
233 data_dword
= le32_to_cpu(((u32
*) buf
)[0]);
234 ret
= pciConfigOutDword(d
->bus
, d
->dev
, d
->func
, pos
, data_dword
);
235 if (ret
!= ERROR_NONE
)
243 struct pci_methods pm_sylixos_device
= {
245 "SylixOS /proc/pci device",
251 pci_generic_fill_info
,
256 NULL
, // no cleanup_dev