]>
Commit | Line | Data |
---|---|---|
c4ca3d5a ORL |
1 | /* |
2 | * dev.c | |
3 | * | |
4 | * DSP-BIOS Bridge driver support functions for TI OMAP processors. | |
5 | * | |
6 | * Implementation of Bridge Bridge driver device operations. | |
7 | * | |
8 | * Copyright (C) 2005-2006 Texas Instruments, Inc. | |
9 | * | |
10 | * This package is free software; you can redistribute it and/or modify | |
11 | * it under the terms of the GNU General Public License version 2 as | |
12 | * published by the Free Software Foundation. | |
13 | * | |
14 | * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
15 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
16 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
17 | */ | |
2094f12d | 18 | #include <linux/types.h> |
5fb45dac | 19 | #include <linux/list.h> |
c4ca3d5a ORL |
20 | |
21 | /* ----------------------------------- Host OS */ | |
22 | #include <dspbridge/host_os.h> | |
23 | ||
24 | /* ----------------------------------- DSP/BIOS Bridge */ | |
c4ca3d5a ORL |
25 | #include <dspbridge/dbdefs.h> |
26 | ||
27 | /* ----------------------------------- Trace & Debug */ | |
28 | #include <dspbridge/dbc.h> | |
29 | ||
c4ca3d5a ORL |
30 | /* ----------------------------------- Platform Manager */ |
31 | #include <dspbridge/cod.h> | |
32 | #include <dspbridge/drv.h> | |
33 | #include <dspbridge/proc.h> | |
677f2ded | 34 | #include <dspbridge/dmm.h> |
c4ca3d5a ORL |
35 | |
36 | /* ----------------------------------- Resource Manager */ | |
37 | #include <dspbridge/mgr.h> | |
38 | #include <dspbridge/node.h> | |
39 | ||
40 | /* ----------------------------------- Others */ | |
41 | #include <dspbridge/dspapi.h> /* DSP API version info. */ | |
42 | ||
43 | #include <dspbridge/chnl.h> | |
44 | #include <dspbridge/io.h> | |
45 | #include <dspbridge/msg.h> | |
46 | #include <dspbridge/cmm.h> | |
61a5b769 | 47 | #include <dspbridge/dspdeh.h> |
c4ca3d5a ORL |
48 | |
49 | /* ----------------------------------- This */ | |
50 | #include <dspbridge/dev.h> | |
51 | ||
52 | /* ----------------------------------- Defines, Data Structures, Typedefs */ | |
53 | ||
54 | #define MAKEVERSION(major, minor) (major * 10 + minor) | |
55 | #define BRD_API_VERSION MAKEVERSION(BRD_API_MAJOR_VERSION, \ | |
56 | BRD_API_MINOR_VERSION) | |
57 | ||
58 | /* The Bridge device object: */ | |
59 | struct dev_object { | |
c4ca3d5a ORL |
60 | struct list_head link; /* Link to next dev_object. */ |
61 | u8 dev_type; /* Device Type */ | |
62 | struct cfg_devnode *dev_node_obj; /* Platform specific dev id */ | |
63 | /* Bridge Context Handle */ | |
085467b8 | 64 | struct bridge_dev_context *bridge_context; |
c4ca3d5a ORL |
65 | /* Function interface to Bridge driver. */ |
66 | struct bridge_drv_interface bridge_interface; | |
67 | struct brd_object *lock_owner; /* Client with exclusive access. */ | |
68 | struct cod_manager *cod_mgr; /* Code manager handle. */ | |
085467b8 RS |
69 | struct chnl_mgr *chnl_mgr; /* Channel manager. */ |
70 | struct deh_mgr *deh_mgr; /* DEH manager. */ | |
71 | struct msg_mgr *msg_mgr; /* Message manager. */ | |
121e8f9b | 72 | struct io_mgr *iomgr; /* IO manager (CHNL, msg_ctrl) */ |
085467b8 | 73 | struct cmm_object *cmm_mgr; /* SM memory manager. */ |
677f2ded | 74 | struct dmm_object *dmm_mgr; /* Dynamic memory manager. */ |
c4ca3d5a | 75 | u32 word_size; /* DSP word size: quick access. */ |
085467b8 | 76 | struct drv_object *drv_obj; /* Driver Object */ |
ba44df6f IN |
77 | /* List of Processors attached to this device */ |
78 | struct list_head proc_list; | |
085467b8 | 79 | struct node_mgr *node_mgr; |
c4ca3d5a ORL |
80 | }; |
81 | ||
e8184e6c IGC |
82 | struct drv_ext { |
83 | struct list_head link; | |
84 | char sz_string[MAXREGPATHLENGTH]; | |
85 | }; | |
86 | ||
c4ca3d5a ORL |
87 | /* ----------------------------------- Globals */ |
88 | static u32 refs; /* Module reference count */ | |
89 | ||
90 | /* ----------------------------------- Function Prototypes */ | |
91 | static int fxn_not_implemented(int arg, ...); | |
92 | static int init_cod_mgr(struct dev_object *dev_obj); | |
93 | static void store_interface_fxns(struct bridge_drv_interface *drv_fxns, | |
e6bf74f0 | 94 | struct bridge_drv_interface *intf_fxns); |
c4ca3d5a ORL |
95 | /* |
96 | * ======== dev_brd_write_fxn ======== | |
97 | * Purpose: | |
98 | * Exported function to be used as the COD write function. This function | |
99 | * is passed a handle to a DEV_hObject, then calls the | |
100 | * device's bridge_brd_write() function. | |
101 | */ | |
5e2eae57 | 102 | u32 dev_brd_write_fxn(void *arb, u32 dsp_add, void *host_buf, |
95870a88 | 103 | u32 ul_num_bytes, u32 mem_space) |
c4ca3d5a | 104 | { |
aa09b091 | 105 | struct dev_object *dev_obj = (struct dev_object *)arb; |
c4ca3d5a ORL |
106 | u32 ul_written = 0; |
107 | int status; | |
108 | ||
109 | DBC_REQUIRE(refs > 0); | |
daa89e6c | 110 | DBC_REQUIRE(host_buf != NULL); /* Required of BrdWrite(). */ |
c4ca3d5a ORL |
111 | if (dev_obj) { |
112 | /* Require of BrdWrite() */ | |
085467b8 | 113 | DBC_ASSERT(dev_obj->bridge_context != NULL); |
e17ba7f2 | 114 | status = (*dev_obj->bridge_interface.brd_write) ( |
085467b8 | 115 | dev_obj->bridge_context, host_buf, |
5e2eae57 | 116 | dsp_add, ul_num_bytes, mem_space); |
c4ca3d5a ORL |
117 | /* Special case of getting the address only */ |
118 | if (ul_num_bytes == 0) | |
119 | ul_num_bytes = 1; | |
157990f0 | 120 | if (!status) |
c4ca3d5a ORL |
121 | ul_written = ul_num_bytes; |
122 | ||
123 | } | |
124 | return ul_written; | |
125 | } | |
126 | ||
127 | /* | |
128 | * ======== dev_create_device ======== | |
129 | * Purpose: | |
130 | * Called by the operating system to load the PM Bridge Driver for a | |
131 | * PM board (device). | |
132 | */ | |
e6bf74f0 | 133 | int dev_create_device(struct dev_object **device_obj, |
9d7d0a52 | 134 | const char *driver_file_name, |
c4ca3d5a ORL |
135 | struct cfg_devnode *dev_node_obj) |
136 | { | |
137 | struct cfg_hostres *host_res; | |
c4ca3d5a ORL |
138 | struct bridge_drv_interface *drv_fxns = NULL; |
139 | struct dev_object *dev_obj = NULL; | |
140 | struct chnl_mgrattrs mgr_attrs; | |
141 | struct io_attrs io_mgr_attrs; | |
142 | u32 num_windows; | |
143 | struct drv_object *hdrv_obj = NULL; | |
73b87a91 | 144 | struct drv_data *drv_datap = dev_get_drvdata(bridge); |
c4ca3d5a ORL |
145 | int status = 0; |
146 | DBC_REQUIRE(refs > 0); | |
e436d07d | 147 | DBC_REQUIRE(device_obj != NULL); |
c4ca3d5a ORL |
148 | DBC_REQUIRE(driver_file_name != NULL); |
149 | ||
150 | status = drv_request_bridge_res_dsp((void *)&host_res); | |
151 | ||
51d5e099 | 152 | if (status) { |
c4ca3d5a ORL |
153 | dev_dbg(bridge, "%s: Failed to reserve bridge resources\n", |
154 | __func__); | |
155 | goto leave; | |
156 | } | |
157 | ||
158 | /* Get the Bridge driver interface functions */ | |
159 | bridge_drv_entry(&drv_fxns, driver_file_name); | |
73b87a91 IGC |
160 | |
161 | /* Retrieve the Object handle from the driver data */ | |
162 | if (drv_datap && drv_datap->drv_object) { | |
163 | hdrv_obj = drv_datap->drv_object; | |
164 | } else { | |
c4ca3d5a | 165 | status = -EPERM; |
73b87a91 | 166 | pr_err("%s: Failed to retrieve the object handle\n", __func__); |
c4ca3d5a | 167 | } |
73b87a91 | 168 | |
c4ca3d5a ORL |
169 | /* Create the device object, and pass a handle to the Bridge driver for |
170 | * storage. */ | |
157990f0 | 171 | if (!status) { |
c4ca3d5a ORL |
172 | DBC_ASSERT(drv_fxns); |
173 | dev_obj = kzalloc(sizeof(struct dev_object), GFP_KERNEL); | |
174 | if (dev_obj) { | |
175 | /* Fill out the rest of the Dev Object structure: */ | |
176 | dev_obj->dev_node_obj = dev_node_obj; | |
c4ca3d5a | 177 | dev_obj->cod_mgr = NULL; |
085467b8 RS |
178 | dev_obj->chnl_mgr = NULL; |
179 | dev_obj->deh_mgr = NULL; | |
c4ca3d5a ORL |
180 | dev_obj->lock_owner = NULL; |
181 | dev_obj->word_size = DSPWORDSIZE; | |
085467b8 | 182 | dev_obj->drv_obj = hdrv_obj; |
c4ca3d5a ORL |
183 | dev_obj->dev_type = DSP_UNIT; |
184 | /* Store this Bridge's interface functions, based on its | |
185 | * version. */ | |
186 | store_interface_fxns(drv_fxns, | |
187 | &dev_obj->bridge_interface); | |
188 | ||
189 | /* Call fxn_dev_create() to get the Bridge's device | |
190 | * context handle. */ | |
09f13304 | 191 | status = (dev_obj->bridge_interface.dev_create) |
085467b8 | 192 | (&dev_obj->bridge_context, dev_obj, |
c4ca3d5a ORL |
193 | host_res); |
194 | /* Assert bridge_dev_create()'s ensure clause: */ | |
51d5e099 | 195 | DBC_ASSERT(status |
085467b8 | 196 | || (dev_obj->bridge_context != NULL)); |
c4ca3d5a ORL |
197 | } else { |
198 | status = -ENOMEM; | |
199 | } | |
200 | } | |
201 | /* Attempt to create the COD manager for this device: */ | |
157990f0 | 202 | if (!status) |
c4ca3d5a ORL |
203 | status = init_cod_mgr(dev_obj); |
204 | ||
205 | /* Attempt to create the channel manager for this device: */ | |
157990f0 | 206 | if (!status) { |
c4ca3d5a ORL |
207 | mgr_attrs.max_channels = CHNL_MAXCHANNELS; |
208 | io_mgr_attrs.birq = host_res->birq_registers; | |
209 | io_mgr_attrs.irq_shared = | |
210 | (host_res->birq_attrib & CFG_IRQSHARED); | |
211 | io_mgr_attrs.word_size = DSPWORDSIZE; | |
212 | mgr_attrs.word_size = DSPWORDSIZE; | |
213 | num_windows = host_res->num_mem_windows; | |
214 | if (num_windows) { | |
215 | /* Assume last memory window is for CHNL */ | |
5108de0a RS |
216 | io_mgr_attrs.shm_base = host_res->mem_base[1] + |
217 | host_res->offset_for_monitor; | |
a534f17b | 218 | io_mgr_attrs.sm_length = |
5108de0a RS |
219 | host_res->mem_length[1] - |
220 | host_res->offset_for_monitor; | |
c4ca3d5a ORL |
221 | } else { |
222 | io_mgr_attrs.shm_base = 0; | |
a534f17b | 223 | io_mgr_attrs.sm_length = 0; |
c4ca3d5a ORL |
224 | pr_err("%s: No memory reserved for shared structures\n", |
225 | __func__); | |
226 | } | |
085467b8 | 227 | status = chnl_create(&dev_obj->chnl_mgr, dev_obj, &mgr_attrs); |
c4ca3d5a ORL |
228 | if (status == -ENOSYS) { |
229 | /* It's OK for a device not to have a channel | |
230 | * manager: */ | |
231 | status = 0; | |
232 | } | |
233 | /* Create CMM mgr even if Msg Mgr not impl. */ | |
085467b8 | 234 | status = cmm_create(&dev_obj->cmm_mgr, |
c4ca3d5a ORL |
235 | (struct dev_object *)dev_obj, NULL); |
236 | /* Only create IO manager if we have a channel manager */ | |
085467b8 | 237 | if (!status && dev_obj->chnl_mgr) { |
121e8f9b | 238 | status = io_create(&dev_obj->iomgr, dev_obj, |
c4ca3d5a ORL |
239 | &io_mgr_attrs); |
240 | } | |
241 | /* Only create DEH manager if we have an IO manager */ | |
157990f0 | 242 | if (!status) { |
c4ca3d5a | 243 | /* Instantiate the DEH module */ |
085467b8 | 244 | status = bridge_deh_create(&dev_obj->deh_mgr, dev_obj); |
c4ca3d5a | 245 | } |
677f2ded FC |
246 | /* Create DMM mgr . */ |
247 | status = dmm_create(&dev_obj->dmm_mgr, | |
248 | (struct dev_object *)dev_obj, NULL); | |
c4ca3d5a ORL |
249 | } |
250 | /* Add the new DEV_Object to the global list: */ | |
5fb45dac | 251 | if (!status) |
c4ca3d5a | 252 | status = drv_insert_dev_object(hdrv_obj, dev_obj); |
5fb45dac | 253 | |
c4ca3d5a | 254 | /* Create the Processor List */ |
5fb45dac IN |
255 | if (!status) |
256 | INIT_LIST_HEAD(&dev_obj->proc_list); | |
c4ca3d5a ORL |
257 | leave: |
258 | /* If all went well, return a handle to the dev object; | |
157990f0 ER |
259 | * else, cleanup and return NULL in the OUT parameter. */ |
260 | if (!status) { | |
e436d07d | 261 | *device_obj = dev_obj; |
c4ca3d5a ORL |
262 | } else { |
263 | if (dev_obj) { | |
c4ca3d5a ORL |
264 | if (dev_obj->cod_mgr) |
265 | cod_delete(dev_obj->cod_mgr); | |
677f2ded FC |
266 | if (dev_obj->dmm_mgr) |
267 | dmm_destroy(dev_obj->dmm_mgr); | |
c4ca3d5a ORL |
268 | kfree(dev_obj); |
269 | } | |
270 | ||
e436d07d | 271 | *device_obj = NULL; |
c4ca3d5a ORL |
272 | } |
273 | ||
51d5e099 | 274 | DBC_ENSURE((!status && *device_obj) || (status && !*device_obj)); |
c4ca3d5a ORL |
275 | return status; |
276 | } | |
277 | ||
278 | /* | |
279 | * ======== dev_create2 ======== | |
280 | * Purpose: | |
281 | * After successful loading of the image from api_init_complete2 | |
282 | * (PROC Auto_Start) or proc_load this fxn is called. This creates | |
283 | * the Node Manager and updates the DEV Object. | |
284 | */ | |
285 | int dev_create2(struct dev_object *hdev_obj) | |
286 | { | |
287 | int status = 0; | |
288 | struct dev_object *dev_obj = hdev_obj; | |
289 | ||
290 | DBC_REQUIRE(refs > 0); | |
291 | DBC_REQUIRE(hdev_obj); | |
292 | ||
293 | /* There can be only one Node Manager per DEV object */ | |
085467b8 RS |
294 | DBC_ASSERT(!dev_obj->node_mgr); |
295 | status = node_create_mgr(&dev_obj->node_mgr, hdev_obj); | |
51d5e099 | 296 | if (status) |
085467b8 | 297 | dev_obj->node_mgr = NULL; |
c4ca3d5a | 298 | |
085467b8 RS |
299 | DBC_ENSURE((!status && dev_obj->node_mgr != NULL) |
300 | || (status && dev_obj->node_mgr == NULL)); | |
c4ca3d5a ORL |
301 | return status; |
302 | } | |
303 | ||
304 | /* | |
305 | * ======== dev_destroy2 ======== | |
306 | * Purpose: | |
307 | * Destroys the Node manager for this device. | |
308 | */ | |
309 | int dev_destroy2(struct dev_object *hdev_obj) | |
310 | { | |
311 | int status = 0; | |
312 | struct dev_object *dev_obj = hdev_obj; | |
313 | ||
314 | DBC_REQUIRE(refs > 0); | |
315 | DBC_REQUIRE(hdev_obj); | |
316 | ||
085467b8 RS |
317 | if (dev_obj->node_mgr) { |
318 | if (node_delete_mgr(dev_obj->node_mgr)) | |
c4ca3d5a ORL |
319 | status = -EPERM; |
320 | else | |
085467b8 | 321 | dev_obj->node_mgr = NULL; |
c4ca3d5a ORL |
322 | |
323 | } | |
324 | ||
085467b8 | 325 | DBC_ENSURE((!status && dev_obj->node_mgr == NULL) || status); |
c4ca3d5a ORL |
326 | return status; |
327 | } | |
328 | ||
329 | /* | |
330 | * ======== dev_destroy_device ======== | |
331 | * Purpose: | |
332 | * Destroys the channel manager for this device, if any, calls | |
333 | * bridge_dev_destroy(), and then attempts to unload the Bridge module. | |
334 | */ | |
335 | int dev_destroy_device(struct dev_object *hdev_obj) | |
336 | { | |
337 | int status = 0; | |
338 | struct dev_object *dev_obj = hdev_obj; | |
339 | ||
340 | DBC_REQUIRE(refs > 0); | |
341 | ||
342 | if (hdev_obj) { | |
343 | if (dev_obj->cod_mgr) { | |
344 | cod_delete(dev_obj->cod_mgr); | |
345 | dev_obj->cod_mgr = NULL; | |
346 | } | |
347 | ||
085467b8 RS |
348 | if (dev_obj->node_mgr) { |
349 | node_delete_mgr(dev_obj->node_mgr); | |
350 | dev_obj->node_mgr = NULL; | |
c4ca3d5a ORL |
351 | } |
352 | ||
353 | /* Free the io, channel, and message managers for this board: */ | |
121e8f9b RS |
354 | if (dev_obj->iomgr) { |
355 | io_destroy(dev_obj->iomgr); | |
356 | dev_obj->iomgr = NULL; | |
c4ca3d5a | 357 | } |
085467b8 RS |
358 | if (dev_obj->chnl_mgr) { |
359 | chnl_destroy(dev_obj->chnl_mgr); | |
360 | dev_obj->chnl_mgr = NULL; | |
c4ca3d5a | 361 | } |
085467b8 RS |
362 | if (dev_obj->msg_mgr) { |
363 | msg_delete(dev_obj->msg_mgr); | |
364 | dev_obj->msg_mgr = NULL; | |
c4ca3d5a ORL |
365 | } |
366 | ||
085467b8 | 367 | if (dev_obj->deh_mgr) { |
c4ca3d5a | 368 | /* Uninitialize DEH module. */ |
085467b8 RS |
369 | bridge_deh_destroy(dev_obj->deh_mgr); |
370 | dev_obj->deh_mgr = NULL; | |
c4ca3d5a | 371 | } |
085467b8 RS |
372 | if (dev_obj->cmm_mgr) { |
373 | cmm_destroy(dev_obj->cmm_mgr, true); | |
374 | dev_obj->cmm_mgr = NULL; | |
c4ca3d5a ORL |
375 | } |
376 | ||
677f2ded FC |
377 | if (dev_obj->dmm_mgr) { |
378 | dmm_destroy(dev_obj->dmm_mgr); | |
379 | dev_obj->dmm_mgr = NULL; | |
380 | } | |
381 | ||
c4ca3d5a ORL |
382 | /* Call the driver's bridge_dev_destroy() function: */ |
383 | /* Require of DevDestroy */ | |
085467b8 | 384 | if (dev_obj->bridge_context) { |
09f13304 | 385 | status = (*dev_obj->bridge_interface.dev_destroy) |
085467b8 RS |
386 | (dev_obj->bridge_context); |
387 | dev_obj->bridge_context = NULL; | |
c4ca3d5a ORL |
388 | } else |
389 | status = -EPERM; | |
157990f0 | 390 | if (!status) { |
c4ca3d5a | 391 | /* Remove this DEV_Object from the global list: */ |
085467b8 | 392 | drv_remove_dev_object(dev_obj->drv_obj, dev_obj); |
c4ca3d5a ORL |
393 | /* Free The library * LDR_FreeModule |
394 | * (dev_obj->module_obj); */ | |
395 | /* Free this dev object: */ | |
396 | kfree(dev_obj); | |
397 | dev_obj = NULL; | |
398 | } | |
399 | } else { | |
400 | status = -EFAULT; | |
401 | } | |
402 | ||
403 | return status; | |
404 | } | |
405 | ||
406 | /* | |
407 | * ======== dev_get_chnl_mgr ======== | |
408 | * Purpose: | |
409 | * Retrieve the handle to the channel manager handle created for this | |
410 | * device. | |
411 | */ | |
412 | int dev_get_chnl_mgr(struct dev_object *hdev_obj, | |
e6bf74f0 | 413 | struct chnl_mgr **mgr) |
c4ca3d5a ORL |
414 | { |
415 | int status = 0; | |
416 | struct dev_object *dev_obj = hdev_obj; | |
417 | ||
418 | DBC_REQUIRE(refs > 0); | |
e436d07d | 419 | DBC_REQUIRE(mgr != NULL); |
c4ca3d5a ORL |
420 | |
421 | if (hdev_obj) { | |
085467b8 | 422 | *mgr = dev_obj->chnl_mgr; |
c4ca3d5a | 423 | } else { |
e436d07d | 424 | *mgr = NULL; |
c4ca3d5a ORL |
425 | status = -EFAULT; |
426 | } | |
427 | ||
157990f0 | 428 | DBC_ENSURE(!status || (mgr != NULL && *mgr == NULL)); |
c4ca3d5a ORL |
429 | return status; |
430 | } | |
431 | ||
432 | /* | |
433 | * ======== dev_get_cmm_mgr ======== | |
434 | * Purpose: | |
435 | * Retrieve the handle to the shared memory manager created for this | |
436 | * device. | |
437 | */ | |
438 | int dev_get_cmm_mgr(struct dev_object *hdev_obj, | |
e6bf74f0 | 439 | struct cmm_object **mgr) |
c4ca3d5a ORL |
440 | { |
441 | int status = 0; | |
442 | struct dev_object *dev_obj = hdev_obj; | |
443 | ||
444 | DBC_REQUIRE(refs > 0); | |
e436d07d | 445 | DBC_REQUIRE(mgr != NULL); |
c4ca3d5a ORL |
446 | |
447 | if (hdev_obj) { | |
085467b8 | 448 | *mgr = dev_obj->cmm_mgr; |
c4ca3d5a | 449 | } else { |
e436d07d | 450 | *mgr = NULL; |
c4ca3d5a ORL |
451 | status = -EFAULT; |
452 | } | |
453 | ||
157990f0 | 454 | DBC_ENSURE(!status || (mgr != NULL && *mgr == NULL)); |
c4ca3d5a ORL |
455 | return status; |
456 | } | |
457 | ||
677f2ded FC |
458 | /* |
459 | * ======== dev_get_dmm_mgr ======== | |
460 | * Purpose: | |
461 | * Retrieve the handle to the dynamic memory manager created for this | |
462 | * device. | |
463 | */ | |
464 | int dev_get_dmm_mgr(struct dev_object *hdev_obj, | |
465 | struct dmm_object **mgr) | |
466 | { | |
467 | int status = 0; | |
468 | struct dev_object *dev_obj = hdev_obj; | |
469 | ||
470 | DBC_REQUIRE(refs > 0); | |
471 | DBC_REQUIRE(mgr != NULL); | |
472 | ||
473 | if (hdev_obj) { | |
474 | *mgr = dev_obj->dmm_mgr; | |
475 | } else { | |
476 | *mgr = NULL; | |
477 | status = -EFAULT; | |
478 | } | |
479 | ||
480 | DBC_ENSURE(!status || (mgr != NULL && *mgr == NULL)); | |
481 | return status; | |
482 | } | |
483 | ||
c4ca3d5a ORL |
484 | /* |
485 | * ======== dev_get_cod_mgr ======== | |
486 | * Purpose: | |
487 | * Retrieve the COD manager create for this device. | |
488 | */ | |
489 | int dev_get_cod_mgr(struct dev_object *hdev_obj, | |
e6bf74f0 | 490 | struct cod_manager **cod_mgr) |
c4ca3d5a ORL |
491 | { |
492 | int status = 0; | |
493 | struct dev_object *dev_obj = hdev_obj; | |
494 | ||
495 | DBC_REQUIRE(refs > 0); | |
a5120278 | 496 | DBC_REQUIRE(cod_mgr != NULL); |
c4ca3d5a ORL |
497 | |
498 | if (hdev_obj) { | |
a5120278 | 499 | *cod_mgr = dev_obj->cod_mgr; |
c4ca3d5a | 500 | } else { |
a5120278 | 501 | *cod_mgr = NULL; |
c4ca3d5a ORL |
502 | status = -EFAULT; |
503 | } | |
504 | ||
157990f0 | 505 | DBC_ENSURE(!status || (cod_mgr != NULL && *cod_mgr == NULL)); |
c4ca3d5a ORL |
506 | return status; |
507 | } | |
508 | ||
509 | /* | |
510 | * ========= dev_get_deh_mgr ======== | |
511 | */ | |
512 | int dev_get_deh_mgr(struct dev_object *hdev_obj, | |
e6bf74f0 | 513 | struct deh_mgr **deh_manager) |
c4ca3d5a ORL |
514 | { |
515 | int status = 0; | |
516 | ||
517 | DBC_REQUIRE(refs > 0); | |
a5120278 | 518 | DBC_REQUIRE(deh_manager != NULL); |
c4ca3d5a ORL |
519 | DBC_REQUIRE(hdev_obj); |
520 | if (hdev_obj) { | |
085467b8 | 521 | *deh_manager = hdev_obj->deh_mgr; |
c4ca3d5a | 522 | } else { |
a5120278 | 523 | *deh_manager = NULL; |
c4ca3d5a ORL |
524 | status = -EFAULT; |
525 | } | |
526 | return status; | |
527 | } | |
528 | ||
529 | /* | |
530 | * ======== dev_get_dev_node ======== | |
531 | * Purpose: | |
532 | * Retrieve the platform specific device ID for this device. | |
533 | */ | |
534 | int dev_get_dev_node(struct dev_object *hdev_obj, | |
e6bf74f0 | 535 | struct cfg_devnode **dev_nde) |
c4ca3d5a ORL |
536 | { |
537 | int status = 0; | |
538 | struct dev_object *dev_obj = hdev_obj; | |
539 | ||
540 | DBC_REQUIRE(refs > 0); | |
e436d07d | 541 | DBC_REQUIRE(dev_nde != NULL); |
c4ca3d5a ORL |
542 | |
543 | if (hdev_obj) { | |
e436d07d | 544 | *dev_nde = dev_obj->dev_node_obj; |
c4ca3d5a | 545 | } else { |
e436d07d | 546 | *dev_nde = NULL; |
c4ca3d5a ORL |
547 | status = -EFAULT; |
548 | } | |
549 | ||
157990f0 | 550 | DBC_ENSURE(!status || (dev_nde != NULL && *dev_nde == NULL)); |
c4ca3d5a ORL |
551 | return status; |
552 | } | |
553 | ||
554 | /* | |
555 | * ======== dev_get_first ======== | |
556 | * Purpose: | |
557 | * Retrieve the first Device Object handle from an internal linked list | |
558 | * DEV_OBJECTs maintained by DEV. | |
559 | */ | |
560 | struct dev_object *dev_get_first(void) | |
561 | { | |
562 | struct dev_object *dev_obj = NULL; | |
563 | ||
564 | dev_obj = (struct dev_object *)drv_get_first_dev_object(); | |
565 | ||
566 | return dev_obj; | |
567 | } | |
568 | ||
569 | /* | |
570 | * ======== dev_get_intf_fxns ======== | |
571 | * Purpose: | |
572 | * Retrieve the Bridge interface function structure for the loaded driver. | |
13b18c29 | 573 | * if_fxns != NULL. |
c4ca3d5a ORL |
574 | */ |
575 | int dev_get_intf_fxns(struct dev_object *hdev_obj, | |
e6bf74f0 | 576 | struct bridge_drv_interface **if_fxns) |
c4ca3d5a ORL |
577 | { |
578 | int status = 0; | |
579 | struct dev_object *dev_obj = hdev_obj; | |
580 | ||
581 | DBC_REQUIRE(refs > 0); | |
13b18c29 | 582 | DBC_REQUIRE(if_fxns != NULL); |
c4ca3d5a ORL |
583 | |
584 | if (hdev_obj) { | |
13b18c29 | 585 | *if_fxns = &dev_obj->bridge_interface; |
c4ca3d5a | 586 | } else { |
13b18c29 | 587 | *if_fxns = NULL; |
c4ca3d5a ORL |
588 | status = -EFAULT; |
589 | } | |
590 | ||
157990f0 | 591 | DBC_ENSURE(!status || ((if_fxns != NULL) && (*if_fxns == NULL))); |
c4ca3d5a ORL |
592 | return status; |
593 | } | |
594 | ||
595 | /* | |
596 | * ========= dev_get_io_mgr ======== | |
597 | */ | |
598 | int dev_get_io_mgr(struct dev_object *hdev_obj, | |
e6bf74f0 | 599 | struct io_mgr **io_man) |
c4ca3d5a ORL |
600 | { |
601 | int status = 0; | |
602 | ||
603 | DBC_REQUIRE(refs > 0); | |
e436d07d | 604 | DBC_REQUIRE(io_man != NULL); |
c4ca3d5a ORL |
605 | DBC_REQUIRE(hdev_obj); |
606 | ||
607 | if (hdev_obj) { | |
121e8f9b | 608 | *io_man = hdev_obj->iomgr; |
c4ca3d5a | 609 | } else { |
e436d07d | 610 | *io_man = NULL; |
c4ca3d5a ORL |
611 | status = -EFAULT; |
612 | } | |
613 | ||
614 | return status; | |
615 | } | |
616 | ||
617 | /* | |
618 | * ======== dev_get_next ======== | |
619 | * Purpose: | |
620 | * Retrieve the next Device Object handle from an internal linked list | |
621 | * of DEV_OBJECTs maintained by DEV, after having previously called | |
622 | * dev_get_first() and zero or more dev_get_next | |
623 | */ | |
624 | struct dev_object *dev_get_next(struct dev_object *hdev_obj) | |
625 | { | |
626 | struct dev_object *next_dev_object = NULL; | |
627 | ||
628 | if (hdev_obj) { | |
629 | next_dev_object = (struct dev_object *) | |
630 | drv_get_next_dev_object((u32) hdev_obj); | |
631 | } | |
632 | ||
633 | return next_dev_object; | |
634 | } | |
635 | ||
636 | /* | |
637 | * ========= dev_get_msg_mgr ======== | |
638 | */ | |
e6bf74f0 | 639 | void dev_get_msg_mgr(struct dev_object *hdev_obj, struct msg_mgr **msg_man) |
c4ca3d5a ORL |
640 | { |
641 | DBC_REQUIRE(refs > 0); | |
e436d07d | 642 | DBC_REQUIRE(msg_man != NULL); |
c4ca3d5a ORL |
643 | DBC_REQUIRE(hdev_obj); |
644 | ||
085467b8 | 645 | *msg_man = hdev_obj->msg_mgr; |
c4ca3d5a ORL |
646 | } |
647 | ||
648 | /* | |
649 | * ======== dev_get_node_manager ======== | |
650 | * Purpose: | |
651 | * Retrieve the Node Manager Handle | |
652 | */ | |
653 | int dev_get_node_manager(struct dev_object *hdev_obj, | |
e6bf74f0 | 654 | struct node_mgr **node_man) |
c4ca3d5a ORL |
655 | { |
656 | int status = 0; | |
657 | struct dev_object *dev_obj = hdev_obj; | |
658 | ||
659 | DBC_REQUIRE(refs > 0); | |
daa89e6c | 660 | DBC_REQUIRE(node_man != NULL); |
c4ca3d5a ORL |
661 | |
662 | if (hdev_obj) { | |
085467b8 | 663 | *node_man = dev_obj->node_mgr; |
c4ca3d5a | 664 | } else { |
daa89e6c | 665 | *node_man = NULL; |
c4ca3d5a ORL |
666 | status = -EFAULT; |
667 | } | |
668 | ||
157990f0 | 669 | DBC_ENSURE(!status || (node_man != NULL && *node_man == NULL)); |
c4ca3d5a ORL |
670 | return status; |
671 | } | |
672 | ||
673 | /* | |
674 | * ======== dev_get_symbol ======== | |
675 | */ | |
676 | int dev_get_symbol(struct dev_object *hdev_obj, | |
e6bf74f0 | 677 | const char *str_sym, u32 * pul_value) |
c4ca3d5a ORL |
678 | { |
679 | int status = 0; | |
680 | struct cod_manager *cod_mgr; | |
681 | ||
682 | DBC_REQUIRE(refs > 0); | |
383b8345 | 683 | DBC_REQUIRE(str_sym != NULL && pul_value != NULL); |
c4ca3d5a ORL |
684 | |
685 | if (hdev_obj) { | |
686 | status = dev_get_cod_mgr(hdev_obj, &cod_mgr); | |
687 | if (cod_mgr) | |
383b8345 | 688 | status = cod_get_sym_value(cod_mgr, (char *)str_sym, |
c4ca3d5a ORL |
689 | pul_value); |
690 | else | |
691 | status = -EFAULT; | |
692 | } | |
693 | ||
694 | return status; | |
695 | } | |
696 | ||
697 | /* | |
698 | * ======== dev_get_bridge_context ======== | |
699 | * Purpose: | |
700 | * Retrieve the Bridge Context handle, as returned by the | |
701 | * bridge_dev_create fxn. | |
702 | */ | |
703 | int dev_get_bridge_context(struct dev_object *hdev_obj, | |
e6bf74f0 | 704 | struct bridge_dev_context **phbridge_context) |
c4ca3d5a ORL |
705 | { |
706 | int status = 0; | |
707 | struct dev_object *dev_obj = hdev_obj; | |
708 | ||
709 | DBC_REQUIRE(refs > 0); | |
710 | DBC_REQUIRE(phbridge_context != NULL); | |
711 | ||
712 | if (hdev_obj) { | |
085467b8 | 713 | *phbridge_context = dev_obj->bridge_context; |
c4ca3d5a ORL |
714 | } else { |
715 | *phbridge_context = NULL; | |
716 | status = -EFAULT; | |
717 | } | |
718 | ||
157990f0 | 719 | DBC_ENSURE(!status || ((phbridge_context != NULL) && |
c4ca3d5a ORL |
720 | (*phbridge_context == NULL))); |
721 | return status; | |
722 | } | |
723 | ||
724 | /* | |
725 | * ======== dev_exit ======== | |
726 | * Purpose: | |
727 | * Decrement reference count, and free resources when reference count is | |
728 | * 0. | |
729 | */ | |
730 | void dev_exit(void) | |
731 | { | |
732 | DBC_REQUIRE(refs > 0); | |
733 | ||
734 | refs--; | |
735 | ||
677f2ded | 736 | if (refs == 0) { |
c4ca3d5a | 737 | cmm_exit(); |
677f2ded FC |
738 | dmm_exit(); |
739 | } | |
c4ca3d5a ORL |
740 | |
741 | DBC_ENSURE(refs >= 0); | |
742 | } | |
743 | ||
744 | /* | |
745 | * ======== dev_init ======== | |
746 | * Purpose: | |
747 | * Initialize DEV's private state, keeping a reference count on each call. | |
748 | */ | |
749 | bool dev_init(void) | |
750 | { | |
677f2ded | 751 | bool cmm_ret, dmm_ret, ret = true; |
c4ca3d5a ORL |
752 | |
753 | DBC_REQUIRE(refs >= 0); | |
754 | ||
677f2ded FC |
755 | if (refs == 0) { |
756 | cmm_ret = cmm_init(); | |
757 | dmm_ret = dmm_init(); | |
758 | ||
759 | ret = cmm_ret && dmm_ret; | |
760 | ||
761 | if (!ret) { | |
762 | if (cmm_ret) | |
763 | cmm_exit(); | |
764 | ||
765 | if (dmm_ret) | |
766 | dmm_exit(); | |
767 | ||
768 | } | |
769 | } | |
c4ca3d5a ORL |
770 | |
771 | if (ret) | |
772 | refs++; | |
773 | ||
774 | DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0))); | |
775 | ||
776 | return ret; | |
777 | } | |
778 | ||
779 | /* | |
780 | * ======== dev_notify_clients ======== | |
781 | * Purpose: | |
782 | * Notify all clients of this device of a change in device status. | |
783 | */ | |
ba44df6f | 784 | int dev_notify_clients(struct dev_object *dev_obj, u32 ret) |
c4ca3d5a | 785 | { |
5fb45dac | 786 | struct list_head *curr; |
c4ca3d5a | 787 | |
5fb45dac IN |
788 | /* |
789 | * FIXME: this code needs struct proc_object to have a list_head | |
25985edc | 790 | * at the beginning. If not, this can go horribly wrong. |
5fb45dac IN |
791 | */ |
792 | list_for_each(curr, &dev_obj->proc_list) | |
ba44df6f | 793 | proc_notify_clients((void *)curr, ret); |
c4ca3d5a | 794 | |
5fb45dac | 795 | return 0; |
c4ca3d5a ORL |
796 | } |
797 | ||
798 | /* | |
799 | * ======== dev_remove_device ======== | |
800 | */ | |
801 | int dev_remove_device(struct cfg_devnode *dev_node_obj) | |
802 | { | |
803 | struct dev_object *hdev_obj; /* handle to device object */ | |
804 | int status = 0; | |
e8184e6c IGC |
805 | struct drv_data *drv_datap = dev_get_drvdata(bridge); |
806 | ||
807 | if (!drv_datap) | |
808 | status = -ENODATA; | |
809 | ||
810 | if (!dev_node_obj) | |
811 | status = -EFAULT; | |
c4ca3d5a | 812 | |
25985edc | 813 | /* Retrieve the device object handle originally stored with |
c4ca3d5a | 814 | * the dev_node: */ |
157990f0 | 815 | if (!status) { |
e8184e6c IGC |
816 | /* check the device string and then store dev object */ |
817 | if (!strcmp((char *)((struct drv_ext *)dev_node_obj)->sz_string, | |
818 | "TIOMAP1510")) { | |
819 | hdev_obj = drv_datap->dev_object; | |
820 | /* Destroy the device object. */ | |
821 | status = dev_destroy_device(hdev_obj); | |
822 | } else { | |
823 | status = -EPERM; | |
824 | } | |
c4ca3d5a ORL |
825 | } |
826 | ||
e8184e6c IGC |
827 | if (status) |
828 | pr_err("%s: Failed, status 0x%x\n", __func__, status); | |
829 | ||
c4ca3d5a ORL |
830 | return status; |
831 | } | |
832 | ||
833 | /* | |
834 | * ======== dev_set_chnl_mgr ======== | |
835 | * Purpose: | |
836 | * Set the channel manager for this device. | |
837 | */ | |
838 | int dev_set_chnl_mgr(struct dev_object *hdev_obj, | |
839 | struct chnl_mgr *hmgr) | |
840 | { | |
841 | int status = 0; | |
842 | struct dev_object *dev_obj = hdev_obj; | |
843 | ||
844 | DBC_REQUIRE(refs > 0); | |
845 | ||
846 | if (hdev_obj) | |
085467b8 | 847 | dev_obj->chnl_mgr = hmgr; |
c4ca3d5a ORL |
848 | else |
849 | status = -EFAULT; | |
850 | ||
085467b8 | 851 | DBC_ENSURE(status || (dev_obj->chnl_mgr == hmgr)); |
c4ca3d5a ORL |
852 | return status; |
853 | } | |
854 | ||
855 | /* | |
856 | * ======== dev_set_msg_mgr ======== | |
857 | * Purpose: | |
858 | * Set the message manager for this device. | |
859 | */ | |
860 | void dev_set_msg_mgr(struct dev_object *hdev_obj, struct msg_mgr *hmgr) | |
861 | { | |
862 | DBC_REQUIRE(refs > 0); | |
863 | DBC_REQUIRE(hdev_obj); | |
864 | ||
085467b8 | 865 | hdev_obj->msg_mgr = hmgr; |
c4ca3d5a ORL |
866 | } |
867 | ||
868 | /* | |
869 | * ======== dev_start_device ======== | |
870 | * Purpose: | |
871 | * Initializes the new device with the BRIDGE environment. | |
872 | */ | |
873 | int dev_start_device(struct cfg_devnode *dev_node_obj) | |
874 | { | |
875 | struct dev_object *hdev_obj = NULL; /* handle to 'Bridge Device */ | |
876 | /* Bridge driver filename */ | |
2c36fac4 | 877 | char *bridge_file_name = "UMA"; |
c4ca3d5a ORL |
878 | int status; |
879 | struct mgr_object *hmgr_obj = NULL; | |
a47d4dee | 880 | struct drv_data *drv_datap = dev_get_drvdata(bridge); |
c4ca3d5a ORL |
881 | |
882 | DBC_REQUIRE(refs > 0); | |
883 | ||
884 | /* Given all resources, create a device object. */ | |
885 | status = dev_create_device(&hdev_obj, bridge_file_name, | |
886 | dev_node_obj); | |
157990f0 | 887 | if (!status) { |
c4ca3d5a | 888 | /* Store away the hdev_obj with the DEVNODE */ |
a47d4dee IGC |
889 | if (!drv_datap || !dev_node_obj) { |
890 | status = -EFAULT; | |
891 | pr_err("%s: Failed, status 0x%x\n", __func__, status); | |
892 | } else if (!(strcmp((char *)dev_node_obj, "TIOMAP1510"))) { | |
893 | drv_datap->dev_object = (void *) hdev_obj; | |
894 | } | |
895 | if (!status) { | |
896 | /* Create the Manager Object */ | |
897 | status = mgr_create(&hmgr_obj, dev_node_obj); | |
898 | if (status && !(strcmp((char *)dev_node_obj, | |
899 | "TIOMAP1510"))) { | |
900 | /* Ensure the device extension is NULL */ | |
901 | drv_datap->dev_object = NULL; | |
902 | } | |
903 | } | |
51d5e099 | 904 | if (status) { |
c4ca3d5a ORL |
905 | /* Clean up */ |
906 | dev_destroy_device(hdev_obj); | |
907 | hdev_obj = NULL; | |
908 | } | |
909 | } | |
c4ca3d5a ORL |
910 | |
911 | return status; | |
912 | } | |
913 | ||
914 | /* | |
915 | * ======== fxn_not_implemented ======== | |
916 | * Purpose: | |
917 | * Takes the place of a Bridge Null Function. | |
918 | * Parameters: | |
919 | * Multiple, optional. | |
920 | * Returns: | |
921 | * -ENOSYS: Always. | |
922 | */ | |
923 | static int fxn_not_implemented(int arg, ...) | |
924 | { | |
925 | return -ENOSYS; | |
926 | } | |
927 | ||
928 | /* | |
929 | * ======== init_cod_mgr ======== | |
930 | * Purpose: | |
931 | * Create a COD manager for this device. | |
932 | * Parameters: | |
933 | * dev_obj: Pointer to device object created with | |
934 | * dev_create_device() | |
935 | * Returns: | |
936 | * 0: Success. | |
937 | * -EFAULT: Invalid hdev_obj. | |
938 | * Requires: | |
939 | * Should only be called once by dev_create_device() for a given DevObject. | |
940 | * Ensures: | |
941 | */ | |
942 | static int init_cod_mgr(struct dev_object *dev_obj) | |
943 | { | |
944 | int status = 0; | |
945 | char *sz_dummy_file = "dummy"; | |
946 | ||
947 | DBC_REQUIRE(refs > 0); | |
948 | DBC_REQUIRE(!dev_obj || (dev_obj->cod_mgr == NULL)); | |
949 | ||
5db9e2bf | 950 | status = cod_create(&dev_obj->cod_mgr, sz_dummy_file); |
c4ca3d5a ORL |
951 | |
952 | return status; | |
953 | } | |
954 | ||
955 | /* | |
956 | * ======== dev_insert_proc_object ======== | |
957 | * Purpose: | |
958 | * Insert a ProcObject into the list maintained by DEV. | |
959 | * Parameters: | |
960 | * p_proc_object: Ptr to ProcObject to insert. | |
961 | * dev_obj: Ptr to Dev Object where the list is. | |
aa09b091 | 962 | * already_attached: Ptr to return the bool |
c4ca3d5a ORL |
963 | * Returns: |
964 | * 0: If successful. | |
965 | * Requires: | |
966 | * List Exists | |
967 | * hdev_obj is Valid handle | |
968 | * DEV Initialized | |
aa09b091 | 969 | * already_attached != NULL |
c4ca3d5a ORL |
970 | * proc_obj != 0 |
971 | * Ensures: | |
972 | * 0 and List is not Empty. | |
973 | */ | |
974 | int dev_insert_proc_object(struct dev_object *hdev_obj, | |
e6bf74f0 | 975 | u32 proc_obj, bool *already_attached) |
c4ca3d5a | 976 | { |
c4ca3d5a ORL |
977 | struct dev_object *dev_obj = (struct dev_object *)hdev_obj; |
978 | ||
979 | DBC_REQUIRE(refs > 0); | |
980 | DBC_REQUIRE(dev_obj); | |
981 | DBC_REQUIRE(proc_obj != 0); | |
aa09b091 | 982 | DBC_REQUIRE(already_attached != NULL); |
5fb45dac | 983 | if (!list_empty(&dev_obj->proc_list)) |
aa09b091 | 984 | *already_attached = true; |
c4ca3d5a ORL |
985 | |
986 | /* Add DevObject to tail. */ | |
5fb45dac IN |
987 | /* |
988 | * FIXME: this code needs struct proc_object to have a list_head | |
25985edc | 989 | * at the beginning. If not, this can go horribly wrong. |
5fb45dac IN |
990 | */ |
991 | list_add_tail((struct list_head *)proc_obj, &dev_obj->proc_list); | |
c4ca3d5a | 992 | |
ba44df6f | 993 | return 0; |
c4ca3d5a ORL |
994 | } |
995 | ||
996 | /* | |
997 | * ======== dev_remove_proc_object ======== | |
998 | * Purpose: | |
999 | * Search for and remove a Proc object from the given list maintained | |
1000 | * by the DEV | |
1001 | * Parameters: | |
1002 | * p_proc_object: Ptr to ProcObject to insert. | |
1003 | * dev_obj Ptr to Dev Object where the list is. | |
1004 | * Returns: | |
1005 | * 0: If successful. | |
1006 | * Requires: | |
1007 | * List exists and is not empty | |
1008 | * proc_obj != 0 | |
1009 | * hdev_obj is a valid Dev handle. | |
1010 | * Ensures: | |
1011 | * Details: | |
1012 | * List will be deleted when the DEV is destroyed. | |
1013 | */ | |
1014 | int dev_remove_proc_object(struct dev_object *hdev_obj, u32 proc_obj) | |
1015 | { | |
1016 | int status = -EPERM; | |
1017 | struct list_head *cur_elem; | |
1018 | struct dev_object *dev_obj = (struct dev_object *)hdev_obj; | |
1019 | ||
1020 | DBC_REQUIRE(dev_obj); | |
1021 | DBC_REQUIRE(proc_obj != 0); | |
5fb45dac | 1022 | DBC_REQUIRE(!list_empty(&dev_obj->proc_list)); |
c4ca3d5a ORL |
1023 | |
1024 | /* Search list for dev_obj: */ | |
5fb45dac | 1025 | list_for_each(cur_elem, &dev_obj->proc_list) { |
c4ca3d5a | 1026 | if ((u32) cur_elem == proc_obj) { |
5fb45dac | 1027 | list_del(cur_elem); |
c4ca3d5a ORL |
1028 | status = 0; |
1029 | break; | |
1030 | } | |
1031 | } | |
1032 | ||
1033 | return status; | |
1034 | } | |
1035 | ||
ba44df6f | 1036 | int dev_get_dev_type(struct dev_object *dev_obj, u8 *dev_type) |
c4ca3d5a | 1037 | { |
c4ca3d5a | 1038 | *dev_type = dev_obj->dev_type; |
ba44df6f | 1039 | return 0; |
c4ca3d5a ORL |
1040 | } |
1041 | ||
1042 | /* | |
1043 | * ======== store_interface_fxns ======== | |
1044 | * Purpose: | |
1045 | * Copy the Bridge's interface functions into the device object, | |
1046 | * ensuring that fxn_not_implemented() is set for: | |
1047 | * | |
1048 | * 1. All Bridge function pointers which are NULL; and | |
1049 | * 2. All function slots in the struct dev_object structure which have no | |
1050 | * corresponding slots in the the Bridge's interface, because the Bridge | |
1051 | * is of an *older* version. | |
1052 | * Parameters: | |
1053 | * intf_fxns: Interface fxn Structure of the Bridge's Dev Object. | |
1054 | * drv_fxns: Interface Fxns offered by the Bridge during DEV_Create(). | |
1055 | * Returns: | |
1056 | * Requires: | |
1057 | * Input pointers are valid. | |
1058 | * Bridge driver is *not* written for a newer DSP API. | |
1059 | * Ensures: | |
1060 | * All function pointers in the dev object's fxn interface are not NULL. | |
1061 | */ | |
1062 | static void store_interface_fxns(struct bridge_drv_interface *drv_fxns, | |
e6bf74f0 | 1063 | struct bridge_drv_interface *intf_fxns) |
c4ca3d5a ORL |
1064 | { |
1065 | u32 bridge_version; | |
1066 | ||
1067 | /* Local helper macro: */ | |
1068 | #define STORE_FXN(cast, pfn) \ | |
1069 | (intf_fxns->pfn = ((drv_fxns->pfn != NULL) ? drv_fxns->pfn : \ | |
1070 | (cast)fxn_not_implemented)) | |
1071 | ||
1072 | DBC_REQUIRE(intf_fxns != NULL); | |
1073 | DBC_REQUIRE(drv_fxns != NULL); | |
1074 | DBC_REQUIRE(MAKEVERSION(drv_fxns->brd_api_major_version, | |
1075 | drv_fxns->brd_api_minor_version) <= BRD_API_VERSION); | |
1076 | bridge_version = MAKEVERSION(drv_fxns->brd_api_major_version, | |
1077 | drv_fxns->brd_api_minor_version); | |
1078 | intf_fxns->brd_api_major_version = drv_fxns->brd_api_major_version; | |
1079 | intf_fxns->brd_api_minor_version = drv_fxns->brd_api_minor_version; | |
1080 | /* Install functions up to DSP API version .80 (first alpha): */ | |
1081 | if (bridge_version > 0) { | |
09f13304 RS |
1082 | STORE_FXN(fxn_dev_create, dev_create); |
1083 | STORE_FXN(fxn_dev_destroy, dev_destroy); | |
e17ba7f2 | 1084 | STORE_FXN(fxn_dev_ctrl, dev_cntrl); |
3c882de5 | 1085 | STORE_FXN(fxn_brd_monitor, brd_monitor); |
e17ba7f2 RS |
1086 | STORE_FXN(fxn_brd_start, brd_start); |
1087 | STORE_FXN(fxn_brd_stop, brd_stop); | |
1088 | STORE_FXN(fxn_brd_status, brd_status); | |
3c882de5 | 1089 | STORE_FXN(fxn_brd_read, brd_read); |
e17ba7f2 RS |
1090 | STORE_FXN(fxn_brd_write, brd_write); |
1091 | STORE_FXN(fxn_brd_setstate, brd_set_state); | |
3c882de5 RS |
1092 | STORE_FXN(fxn_brd_memcopy, brd_mem_copy); |
1093 | STORE_FXN(fxn_brd_memwrite, brd_mem_write); | |
1094 | STORE_FXN(fxn_brd_memmap, brd_mem_map); | |
1095 | STORE_FXN(fxn_brd_memunmap, brd_mem_un_map); | |
e17ba7f2 RS |
1096 | STORE_FXN(fxn_chnl_create, chnl_create); |
1097 | STORE_FXN(fxn_chnl_destroy, chnl_destroy); | |
1098 | STORE_FXN(fxn_chnl_open, chnl_open); | |
1099 | STORE_FXN(fxn_chnl_close, chnl_close); | |
1100 | STORE_FXN(fxn_chnl_addioreq, chnl_add_io_req); | |
1101 | STORE_FXN(fxn_chnl_getioc, chnl_get_ioc); | |
1102 | STORE_FXN(fxn_chnl_cancelio, chnl_cancel_io); | |
1103 | STORE_FXN(fxn_chnl_flushio, chnl_flush_io); | |
1104 | STORE_FXN(fxn_chnl_getinfo, chnl_get_info); | |
1105 | STORE_FXN(fxn_chnl_getmgrinfo, chnl_get_mgr_info); | |
1106 | STORE_FXN(fxn_chnl_idle, chnl_idle); | |
1107 | STORE_FXN(fxn_chnl_registernotify, chnl_register_notify); | |
09f13304 RS |
1108 | STORE_FXN(fxn_io_create, io_create); |
1109 | STORE_FXN(fxn_io_destroy, io_destroy); | |
1110 | STORE_FXN(fxn_io_onloaded, io_on_loaded); | |
1111 | STORE_FXN(fxn_io_getprocload, io_get_proc_load); | |
1112 | STORE_FXN(fxn_msg_create, msg_create); | |
1113 | STORE_FXN(fxn_msg_createqueue, msg_create_queue); | |
1114 | STORE_FXN(fxn_msg_delete, msg_delete); | |
1115 | STORE_FXN(fxn_msg_deletequeue, msg_delete_queue); | |
1116 | STORE_FXN(fxn_msg_get, msg_get); | |
1117 | STORE_FXN(fxn_msg_put, msg_put); | |
1118 | STORE_FXN(fxn_msg_registernotify, msg_register_notify); | |
1119 | STORE_FXN(fxn_msg_setqueueid, msg_set_queue_id); | |
c4ca3d5a ORL |
1120 | } |
1121 | /* Add code for any additional functions in newerBridge versions here */ | |
1122 | /* Ensure postcondition: */ | |
09f13304 RS |
1123 | DBC_ENSURE(intf_fxns->dev_create != NULL); |
1124 | DBC_ENSURE(intf_fxns->dev_destroy != NULL); | |
e17ba7f2 | 1125 | DBC_ENSURE(intf_fxns->dev_cntrl != NULL); |
3c882de5 | 1126 | DBC_ENSURE(intf_fxns->brd_monitor != NULL); |
e17ba7f2 RS |
1127 | DBC_ENSURE(intf_fxns->brd_start != NULL); |
1128 | DBC_ENSURE(intf_fxns->brd_stop != NULL); | |
1129 | DBC_ENSURE(intf_fxns->brd_status != NULL); | |
3c882de5 | 1130 | DBC_ENSURE(intf_fxns->brd_read != NULL); |
e17ba7f2 RS |
1131 | DBC_ENSURE(intf_fxns->brd_write != NULL); |
1132 | DBC_ENSURE(intf_fxns->chnl_create != NULL); | |
1133 | DBC_ENSURE(intf_fxns->chnl_destroy != NULL); | |
1134 | DBC_ENSURE(intf_fxns->chnl_open != NULL); | |
1135 | DBC_ENSURE(intf_fxns->chnl_close != NULL); | |
1136 | DBC_ENSURE(intf_fxns->chnl_add_io_req != NULL); | |
1137 | DBC_ENSURE(intf_fxns->chnl_get_ioc != NULL); | |
1138 | DBC_ENSURE(intf_fxns->chnl_cancel_io != NULL); | |
1139 | DBC_ENSURE(intf_fxns->chnl_flush_io != NULL); | |
1140 | DBC_ENSURE(intf_fxns->chnl_get_info != NULL); | |
1141 | DBC_ENSURE(intf_fxns->chnl_get_mgr_info != NULL); | |
1142 | DBC_ENSURE(intf_fxns->chnl_idle != NULL); | |
1143 | DBC_ENSURE(intf_fxns->chnl_register_notify != NULL); | |
09f13304 RS |
1144 | DBC_ENSURE(intf_fxns->io_create != NULL); |
1145 | DBC_ENSURE(intf_fxns->io_destroy != NULL); | |
1146 | DBC_ENSURE(intf_fxns->io_on_loaded != NULL); | |
1147 | DBC_ENSURE(intf_fxns->io_get_proc_load != NULL); | |
1148 | DBC_ENSURE(intf_fxns->msg_set_queue_id != NULL); | |
c4ca3d5a ORL |
1149 | |
1150 | #undef STORE_FXN | |
1151 | } |