1 /* 2 * Memory and resource allocation utility functions. 3 * 4 * Copyright (C) 2018, 2019, 2023 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #include <l4/io/io.h> 23 #include <l4/re/env.h> 24 #include <l4/re/c/mem_alloc.h> 25 #include <l4/re/c/util/cap_alloc.h> 26 #include <l4/util/util.h> 27 #include <l4/vbus/vbus.h> 28 29 #include "memory.h" 30 31 32 33 int get_device(char const *hid, l4io_device_handle_t *dh, l4io_resource_handle_t *rh) 34 { 35 return l4io_lookup_device(hid, dh, 0, rh); 36 } 37 38 int get_irq(char const *hid, l4_uint32_t *start, l4_uint32_t *end) 39 { 40 l4io_device_handle_t dh; 41 l4io_resource_handle_t rh; 42 l4io_resource_t res; 43 int result; 44 45 result = get_device(hid, &dh, &rh); 46 47 if (result < 0) 48 return result; 49 50 result = get_resource(dh, &res, L4VBUS_RESOURCE_IRQ); 51 52 if (result) 53 return result; 54 55 *start = res.start; 56 *end = res.end; 57 58 return result; 59 } 60 61 int get_resource(l4io_device_handle_t dh, l4io_resource_t *res, 62 enum l4vbus_resource_type_t type) 63 { 64 int current = 0, result = 0; 65 l4_cap_idx_t vbus = l4re_env_get_cap("vbus"); 66 67 do 68 { 69 result = l4vbus_get_resource(vbus, dh, current, res); 70 current++; 71 } 72 while ((!result) && (res->type != type)); 73 74 return result; 75 } 76 77 int get_memory(char const *hid, l4_addr_t *start, l4_addr_t *end) 78 { 79 l4_addr_t phys_start, phys_end; 80 81 return get_memory_complete(hid, start, end, &phys_start, &phys_end); 82 } 83 84 int get_memory_complete(char const *hid, l4_addr_t *start, l4_addr_t *end, 85 l4_addr_t *phys_start, l4_addr_t *phys_end) 86 { 87 l4io_device_handle_t dh; 88 l4io_resource_handle_t rh; 89 l4io_resource_t res; 90 int result; 91 92 result = get_device(hid, &dh, &rh); 93 94 if (result < 0) 95 return result; 96 97 result = get_resource(dh, &res, L4VBUS_RESOURCE_MEM); 98 99 if (result) 100 return result; 101 102 result = l4io_request_iomem(res.start, res.end - res.start + 1, 103 L4IO_MEM_NONCACHED, start); 104 105 if (result) 106 return result; 107 108 *end = *start + (res.end - res.start + 1); 109 *phys_start = res.start; 110 *phys_end = res.end; 111 112 return 0; 113 } 114 115 static int _find_resource(l4vbus_device_handle_t device, 116 l4vbus_resource_t *resource, 117 enum l4vbus_resource_type_t type, 118 l4vbus_device_t info) 119 { 120 l4_cap_idx_t vbus = l4re_env_get_cap("vbus"); 121 122 for (unsigned int i = 0; i < info.num_resources; i++) 123 { 124 int result = l4vbus_get_resource(vbus, device, i, resource); 125 126 if (!result && (resource->type == type)) 127 return 1; 128 } 129 130 return 0; 131 } 132 133 int find_resource(l4vbus_device_handle_t *device, l4vbus_resource_t *resource, 134 enum l4vbus_resource_type_t type) 135 { 136 l4_cap_idx_t vbus = l4re_env_get_cap("vbus"); 137 l4vbus_device_t info; 138 139 /* Search within devices only, not within the top-level of the bus itself. */ 140 141 while (!l4vbus_get_next_device(vbus, L4VBUS_ROOT_BUS, device, 142 L4VBUS_MAX_DEPTH, &info)) 143 { 144 if (_find_resource(*device, resource, type, info)) 145 return 1; 146 } 147 148 return 0; 149 }