source: mainline/uspace/lib/device/src/pci.c@ 3a68baa

Last change on this file since 3a68baa was edeee9f, checked in by Jiri Svoboda <jiri@…>, 4 years ago

Fix header guards and doxy groups of stuff moved out of libc

  • Property mode set to 100644
File size: 5.5 KB
Line 
1/*
2 * Copyright (c) 2019 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libdevice
30 * @{
31 */
32/** @file PCI control service API
33 */
34
35#include <abi/ipc/interfaces.h>
36#include <errno.h>
37#include <ipc/devman.h>
38#include <ipc/services.h>
39#include <ipc/pci.h>
40#include <loc.h>
41#include <pci.h>
42#include <stdlib.h>
43#include <types/pci.h>
44
45/** Open PCI service.
46 *
47 * @param svc_id PCI sevice ID
48 * @param rpci Place to store pointer to PCI service object.
49 *
50 * @return EOK on success, ENOMEM if out of memory, EIO if service
51 * cannot be contacted.
52 */
53errno_t pci_open(service_id_t svc_id, pci_t **rpci)
54{
55 pci_t *pci;
56 errno_t rc;
57
58 pci = calloc(1, sizeof(pci_t));
59 if (pci == NULL) {
60 rc = ENOMEM;
61 goto error;
62 }
63
64 pci->sess = loc_service_connect(svc_id, INTERFACE_PCI, 0);
65 if (pci->sess == NULL) {
66 rc = EIO;
67 goto error;
68 }
69
70 *rpci = pci;
71 return EOK;
72error:
73 free(pci);
74 return rc;
75}
76
77/** Close PCI service.
78 *
79 * @param pci PCI service object or @c NULL
80 */
81void pci_close(pci_t *pci)
82{
83 if (pci == NULL)
84 return;
85
86 async_hangup(pci->sess);
87 free(pci);
88}
89
90/** Get list of IDs into a buffer of fixed size.
91 *
92 * @param pci PCI service
93 * @param method IPC method
94 * @param arg1 First argument
95 * @param id_buf Buffer to store IDs
96 * @param buf_size Buffer size
97 * @param act_size Place to store actual size of complete data.
98 *
99 * @return EOK on success or an error code.
100 */
101static errno_t pci_get_ids_once(pci_t *pci, sysarg_t method, sysarg_t arg1,
102 sysarg_t *id_buf, size_t buf_size, size_t *act_size)
103{
104 async_exch_t *exch = async_exchange_begin(pci->sess);
105
106 ipc_call_t answer;
107 aid_t req = async_send_1(exch, method, arg1, &answer);
108 errno_t rc = async_data_read_start(exch, id_buf, buf_size);
109
110 async_exchange_end(exch);
111
112 if (rc != EOK) {
113 async_forget(req);
114 return rc;
115 }
116
117 errno_t retval;
118 async_wait_for(req, &retval);
119
120 if (retval != EOK) {
121 return retval;
122 }
123
124 *act_size = ipc_get_arg1(&answer);
125 return EOK;
126}
127
128/** Get list of IDs.
129 *
130 * Returns an allocated array of service IDs.
131 *
132 * @param pci PCI service
133 * @param method IPC method
134 * @param arg1 IPC argument 1
135 * @param data Place to store pointer to array of IDs
136 * @param count Place to store number of IDs
137 * @return EOK on success or an error code
138 */
139static errno_t pci_get_ids_internal(pci_t *pci, sysarg_t method, sysarg_t arg1,
140 sysarg_t **data, size_t *count)
141{
142 *data = NULL;
143 *count = 0;
144
145 size_t act_size = 0;
146 errno_t rc = pci_get_ids_once(pci, method, arg1, NULL, 0, &act_size);
147 if (rc != EOK)
148 return rc;
149
150 size_t alloc_size = act_size;
151 service_id_t *ids = malloc(alloc_size);
152 if (ids == NULL)
153 return ENOMEM;
154
155 while (true) {
156 rc = pci_get_ids_once(pci, method, arg1, ids, alloc_size,
157 &act_size);
158 if (rc != EOK)
159 return rc;
160
161 if (act_size <= alloc_size)
162 break;
163
164 alloc_size = act_size;
165 service_id_t *tmp = realloc(ids, alloc_size);
166 if (tmp == NULL) {
167 free(ids);
168 return ENOMEM;
169 }
170 ids = tmp;
171 }
172
173 *count = act_size / sizeof(service_id_t);
174 *data = ids;
175 return EOK;
176}
177
178/** Get list of PCI devices as array of devman handles.
179 *
180 * @param pci PCI service
181 * @param data Place to store pointer to array
182 * @param count Place to store length of array (number of entries)
183 *
184 * @return EOK on success or an error code
185 */
186errno_t pci_get_devices(pci_t *pci, devman_handle_t **data, size_t *count)
187{
188 return pci_get_ids_internal(pci, PCI_GET_DEVICES, 0, data, count);
189}
190
191extern errno_t pci_dev_get_info(pci_t *, devman_handle_t, pci_dev_info_t *);
192
193/** Get PCI device information.
194 *
195 * @param pci PCI service
196 * @param dev_handle Device handle
197 * @param info Place to store device information
198 * @return EOK on success or an error code
199 */
200errno_t pci_dev_get_info(pci_t *pci, devman_handle_t dev_handle,
201 pci_dev_info_t *info)
202{
203 async_exch_t *exch;
204 errno_t retval;
205 ipc_call_t answer;
206
207 exch = async_exchange_begin(pci->sess);
208 aid_t req = async_send_1(exch, PCI_DEV_GET_INFO, dev_handle, &answer);
209
210 errno_t rc = async_data_read_start(exch, info, sizeof(pci_dev_info_t));
211 async_exchange_end(exch);
212 if (rc != EOK) {
213 async_forget(req);
214 return EIO;
215 }
216
217 async_wait_for(req, &retval);
218 if (retval != EOK)
219 return EIO;
220
221 return EOK;
222}
223
224/** @}
225 */
Note: See TracBrowser for help on using the repository browser.