A more generic way of passing caps to user-space drivers.
[barrelfish] / lib / driverkit / map_devices.c
1 /**
2  * \brief Memory management helper functions for device drivers.
3  */
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <assert.h>
7
8 #include <barrelfish/barrelfish.h>
9 #include <barrelfish/capabilities.h>
10
11 #include <driverkit/driverkit.h>
12
13 #define UNBITS_GENPA(bits) (((genpaddr_t)1) << (bits))
14
15 /**
16  * \brief Maps device register with the capabilities provided by the
17  * argcn slot.
18  *
19  * The function is used mostly as a helper to map registers by programs
20  * that were spawned by Kaluga.
21  *
22  * \param[in] address The base of the device region you want to map.
23  * \param[in] size The size of the region.
24  * \param[out] return_address The virtual memory base address where the region
25  * was mapped at.
26  *
27  * \retval SYS_ERR_OK Mapping was succesful.
28  */
29 errval_t map_device_register(lpaddr_t address, size_t size, lvaddr_t **return_address)
30 {
31     //debug_printf("%s:%d: address=0x%x size=%u\n", __FUNCTION__, __LINE__, address, size);
32
33     struct capref argcn = {
34         .cnode = cnode_root,
35         .slot = 10
36     };
37     //debug_cspace(argcn);
38
39     size_t bits = 8; // TODO(gz): How do I figure this value out on the fly?
40     struct capref device_cap_iter = {
41         .cnode = build_cnoderef(argcn, bits),
42         .slot = 0
43     };
44     //walk_cspace(build_cnoderef(argcn, bits), 0);
45
46
47     for (size_t i = 0; i<4; i++) {
48         struct frame_identity fid;
49         errval_t err = invoke_frame_identify(device_cap_iter, &fid);
50         if (err_is_fail(err)) {
51             DEBUG_ERR(err, "Failure in invoke_frame_identify");
52             return err;
53         }
54         assert(err_is_ok(err));
55         if (address >= fid.base &&
56                 (address + size) <= (fid.base + UNBITS_GENPA(fid.bits))) {
57             err = vspace_map_one_frame_attr((void **)return_address, size,
58                                             device_cap_iter, VREGION_FLAGS_READ_WRITE_NOCACHE,
59                                             NULL, NULL);
60             if (err_is_fail(err)) {
61                 DEBUG_ERR(err, "Failure in vspace_map_one_frame_attr.\n");
62             }
63             return err;
64         }
65
66         device_cap_iter.slot += 1;
67     }
68
69     return DRIVERKIT_NO_CAP_FOUND;
70 }