File indexing completed on 2025-05-11 08:24:09
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #include <bsp.h>
0037 #include <rtems/bspIo.h>
0038
0039 #include <boot/ofw.h>
0040 #include <boot/ofwarch.h>
0041 #if 0
0042 #include <boot/printf.h>
0043 #include <boot/asm.h>
0044 #endif
0045 #include <boot/types.h>
0046 #include <string.h>
0047 #include <asm.h>
0048
0049 #define RED(i) (((i) >> 5) & ((1 << 3) - 1))
0050 #define GREEN(i) (((i) >> 3) & ((1 << 2) - 1))
0051 #define BLUE(i) ((i) & ((1 << 3) - 1))
0052 #define CLIP(i) ((i) <= 255 ? (i) : 255)
0053
0054 uintptr_t ofw_cif;
0055
0056 phandle ofw_chosen;
0057 ihandle ofw_stdout;
0058 ihandle ofw_stdin;
0059
0060 phandle ofw_root;
0061 ihandle ofw_mmu;
0062 ihandle ofw_memory_prop;
0063 phandle ofw_memory;
0064
0065 void ofw_init(void)
0066 {
0067 ofw_chosen = ofw_find_device("/chosen");
0068 if (ofw_chosen == -1)
0069 halt();
0070
0071 if (ofw_get_property(ofw_chosen, "stdout", &ofw_stdout,
0072 sizeof(ofw_stdout)) <= 0)
0073 ofw_stdout = 0;
0074
0075 if (ofw_get_property(ofw_chosen, "stdin", &ofw_stdin,
0076 sizeof(ofw_stdin)) <= 0)
0077 ofw_stdin = 0;
0078
0079 ofw_root = ofw_find_device("/");
0080 if (ofw_root == -1) {
0081 printk("\r\nError: Unable to find / device, halted.\r\n");
0082 halt();
0083 }
0084
0085 if (ofw_get_property(ofw_chosen, "mmu", &ofw_mmu,
0086 sizeof(ofw_mmu)) <= 0) {
0087 printk("\r\nError: Unable to get mmu property, halted.\r\n");
0088 halt();
0089 }
0090 if (ofw_get_property(ofw_chosen, "memory", &ofw_memory_prop,
0091 sizeof(ofw_memory_prop)) <= 0) {
0092 printk("\r\nError: Unable to get memory property, halted.\r\n");
0093 halt();
0094 }
0095
0096 ofw_memory = ofw_find_device("/memory");
0097 if (ofw_memory == -1) {
0098 printk("\r\nError: Unable to find /memory device, halted.\r\n");
0099 halt();
0100 }
0101 }
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115 unsigned long
0116 ofw_call(const char *service, const int nargs, const int nret, ofw_arg_t *rets,
0117 ...)
0118 {
0119 va_list list;
0120 ofw_args_t args;
0121 int i;
0122
0123 args.service = (ofw_arg_t) service;
0124 args.nargs = nargs;
0125 args.nret = nret;
0126
0127 va_start(list, rets);
0128 for (i = 0; i < nargs; i++)
0129 args.args[i] = va_arg(list, ofw_arg_t);
0130 va_end(list);
0131
0132 for (i = 0; i < nret; i++)
0133 args.args[i + nargs] = 0;
0134
0135 (void) ofw(&args);
0136
0137 for (i = 1; i < nret; i++)
0138 rets[i - 1] = args.args[i + nargs];
0139
0140 return args.args[nargs];
0141 }
0142
0143 phandle ofw_find_device(const char *name)
0144 {
0145 return ofw_call("finddevice", 1, 1, NULL, name);
0146 }
0147
0148 int ofw_get_property(const phandle device, const char *name, void *buf,
0149 const int buflen)
0150 {
0151 return ofw_call("getprop", 4, 1, NULL, device, name, buf, buflen);
0152 }
0153
0154 int ofw_get_proplen(const phandle device, const char *name)
0155 {
0156 return ofw_call("getproplen", 2, 1, NULL, device, name);
0157 }
0158
0159 int ofw_next_property(const phandle device, char *previous, char *buf)
0160 {
0161 return ofw_call("nextprop", 3, 1, NULL, device, previous, buf);
0162 }
0163
0164 int ofw_package_to_path(const phandle device, char *buf, const int buflen)
0165 {
0166 return ofw_call("package-to-path", 3, 1, NULL, device, buf, buflen);
0167 }
0168
0169 unsigned int ofw_get_address_cells(const phandle device)
0170 {
0171 unsigned int ret = 1;
0172
0173 if (ofw_get_property(device, "#address-cells", &ret, sizeof(ret)) <= 0)
0174 if (ofw_get_property(ofw_root, "#address-cells", &ret,
0175 sizeof(ret)) <= 0)
0176 ret = OFW_ADDRESS_CELLS;
0177
0178 return ret;
0179 }
0180
0181 unsigned int ofw_get_size_cells(const phandle device)
0182 {
0183 unsigned int ret;
0184
0185 if (ofw_get_property(device, "#size-cells", &ret, sizeof(ret)) <= 0)
0186 if (ofw_get_property(ofw_root, "#size-cells", &ret,
0187 sizeof(ret)) <= 0)
0188 ret = OFW_SIZE_CELLS;
0189
0190 return ret;
0191 }
0192
0193 phandle ofw_get_child_node(const phandle node)
0194 {
0195 return ofw_call("child", 1, 1, NULL, node);
0196 }
0197
0198 phandle ofw_get_peer_node(const phandle node)
0199 {
0200 return ofw_call("peer", 1, 1, NULL, node);
0201 }
0202
0203 static ihandle ofw_open(const char *name)
0204 {
0205 return ofw_call("open", 1, 1, NULL, name);
0206 }
0207
0208
0209 void ofw_write(const char *str, const int len)
0210 {
0211 if (ofw_stdout == 0)
0212 return;
0213
0214 ofw_call("write", 3, 1, NULL, ofw_stdout, str, len);
0215 }
0216
0217 void ofw_read(void *str, const int len)
0218 {
0219 if (ofw_stdin == 0)
0220 return;
0221
0222 ofw_call("read", 3, 1, NULL, ofw_stdin, str, len);
0223 }
0224
0225 void *ofw_translate(const void *virt)
0226 {
0227 ofw_arg_t result[4];
0228 int shift;
0229
0230 if (ofw_call("call-method", 4, 5, result, "translate", ofw_mmu,
0231 virt, 0) != 0) {
0232 printk("Error: MMU method translate() failed, halting.\n");
0233 halt();
0234 }
0235
0236 if (ofw_translate_failed(result[0]))
0237 return NULL;
0238
0239 if (sizeof(unative_t) == 8)
0240 shift = 32;
0241 else
0242 shift = 0;
0243
0244 return (void *) ((result[2] << shift) | result[3]);
0245 }
0246
0247 void *ofw_claim_virt(const void *virt, const unsigned int len)
0248 {
0249 ofw_arg_t retaddr;
0250
0251 if (ofw_call("call-method", 5, 2, &retaddr, "claim", ofw_mmu, 0, len,
0252 virt) != 0) {
0253 printk("Error: MMU method claim() failed, halting.\n");
0254 halt();
0255 }
0256
0257 return (void *) retaddr;
0258 }
0259
0260 static void *ofw_claim_phys_internal(const void *phys, const unsigned int len, const unsigned int alignment)
0261 {
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274 if (sizeof(unative_t) == 8) {
0275 ofw_arg_t retaddr[2];
0276 int shift = 32;
0277
0278 if (ofw_call("call-method", 6, 3, retaddr, "claim",
0279 ofw_memory_prop, alignment, len, ((uintptr_t) phys) >> shift,
0280 ((uintptr_t) phys) & ((uint32_t) -1)) != 0) {
0281 printk("Error: memory method claim() failed, halting.\n");
0282 halt();
0283 }
0284
0285 return (void *) ((retaddr[0] << shift) | retaddr[1]);
0286 } else {
0287 ofw_arg_t retaddr[1];
0288
0289 if (ofw_call("call-method", 5, 2, retaddr, "claim",
0290 ofw_memory_prop, alignment, len, (uintptr_t) phys) != 0) {
0291 printk("Error: memory method claim() failed, halting.\n");
0292 halt();
0293 }
0294
0295 return (void *) retaddr[0];
0296 }
0297 }
0298
0299 void *ofw_claim_phys(const void *phys, const unsigned int len)
0300 {
0301 return ofw_claim_phys_internal(phys, len, 0);
0302 }
0303
0304 void *ofw_claim_phys_any(const unsigned int len, const unsigned int alignment)
0305 {
0306 return ofw_claim_phys_internal(NULL, len, alignment);
0307 }
0308
0309 int ofw_map(const void *phys, const void *virt, const unsigned int size, const int mode)
0310 {
0311 uintptr_t phys_hi, phys_lo;
0312
0313 if (sizeof(unative_t) == 8) {
0314 int shift = 32;
0315 phys_hi = (uintptr_t) phys >> shift;
0316 phys_lo = (uintptr_t) phys & 0xffffffff;
0317 } else {
0318 phys_hi = 0;
0319 phys_lo = (uintptr_t) phys;
0320 }
0321
0322 return ofw_call("call-method", 7, 1, NULL, "map", ofw_mmu, mode, size,
0323 virt, phys_hi, phys_lo);
0324 }
0325
0326
0327
0328
0329
0330
0331
0332 int ofw_memmap(memmap_t *map)
0333 {
0334 unsigned int ac = ofw_get_address_cells(ofw_memory) /
0335 (sizeof(uintptr_t) / sizeof(uint32_t));
0336 unsigned int sc = ofw_get_size_cells(ofw_memory) /
0337 (sizeof(uintptr_t) / sizeof(uint32_t));
0338
0339 uintptr_t buf[((ac + sc) * MEMMAP_MAX_RECORDS)];
0340 int ret = ofw_get_property(ofw_memory, "reg", buf, sizeof(buf));
0341 if (ret <= 0)
0342 return false;
0343
0344 int pos;
0345 map->total = 0;
0346 map->count = 0;
0347 for (pos = 0; (pos < ret / sizeof(uintptr_t)) &&
0348 (map->count < MEMMAP_MAX_RECORDS); pos += ac + sc) {
0349 void *start = (void *) (buf[pos + ac - 1]);
0350 unsigned int size = buf[pos + ac + sc - 1];
0351
0352
0353
0354
0355
0356
0357
0358
0359 if ((map->count > 0) && (map->zones[map->count - 1].start +
0360 map->zones[map->count - 1].size < start))
0361 break;
0362
0363 if (size > 0) {
0364 map->zones[map->count].start = start;
0365 map->zones[map->count].size = size;
0366 map->count++;
0367 map->total += size;
0368 }
0369 }
0370
0371 return true;
0372 }
0373
0374 static void ofw_setup_screen(phandle handle)
0375 {
0376
0377 char device_type[OFW_TREE_PROPERTY_MAX_VALUELEN];
0378 if (ofw_get_property(handle, "device_type", device_type, OFW_TREE_PROPERTY_MAX_VALUELEN) <= 0)
0379 return;
0380
0381 device_type[OFW_TREE_PROPERTY_MAX_VALUELEN - 1] = '\0';
0382 if (strcmp(device_type, "display") != 0)
0383 return;
0384
0385
0386 uint32_t depth;
0387 if (ofw_get_property(handle, "depth", &depth, sizeof(uint32_t)) <= 0)
0388 depth = 0;
0389
0390
0391 static char path[OFW_TREE_PATH_MAX_LEN + 1];
0392 size_t len = ofw_package_to_path(handle, path, OFW_TREE_PATH_MAX_LEN);
0393 if (len == -1)
0394 return;
0395
0396 path[len] = '\0';
0397
0398
0399 ihandle screen = ofw_open(path);
0400 if (screen == -1)
0401 return;
0402
0403 if (depth == 8) {
0404
0405 unsigned int i;
0406 for (i = 0; i < 256; i++) {
0407 ofw_call("call-method", 6, 1, NULL, "color!", screen,
0408 255 - i, CLIP(BLUE(i) * 37), GREEN(i) * 85, CLIP(RED(i) * 37));
0409 }
0410 }
0411 }
0412
0413 static void ofw_setup_screens_internal(phandle current)
0414 {
0415 while ((current != 0) && (current != -1)) {
0416 ofw_setup_screen(current);
0417
0418
0419
0420
0421 phandle child = ofw_get_child_node(current);
0422 if ((child != 0) && (child != -1))
0423 ofw_setup_screens_internal(child);
0424
0425
0426
0427
0428
0429
0430
0431
0432 phandle peer = ofw_get_peer_node(current);
0433 if ((peer != 0) && (peer != -1)) {
0434 current = peer;
0435
0436
0437
0438 continue;
0439 }
0440
0441
0442
0443
0444 break;
0445 }
0446 }
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456 void ofw_setup_screens(void)
0457 {
0458 ofw_setup_screens_internal(ofw_root);
0459 }
0460
0461 void ofw_quiesce(void)
0462 {
0463 ofw_call("quiesce", 0, 0, NULL);
0464 }