Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.17-rc2 165 lines 3.8 kB view raw
1/* 2 * Copyright (C) Paul Mackerras 1997. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 */ 9#include <stdarg.h> 10#include <stddef.h> 11#include "string.h" 12#include "stdio.h" 13#include "prom.h" 14 15int (*prom)(void *); 16phandle chosen_handle; 17ihandle stdout; 18 19int call_prom(const char *service, int nargs, int nret, ...) 20{ 21 int i; 22 struct prom_args { 23 const char *service; 24 int nargs; 25 int nret; 26 unsigned int args[12]; 27 } args; 28 va_list list; 29 30 args.service = service; 31 args.nargs = nargs; 32 args.nret = nret; 33 34 va_start(list, nret); 35 for (i = 0; i < nargs; i++) 36 args.args[i] = va_arg(list, unsigned int); 37 va_end(list); 38 39 for (i = 0; i < nret; i++) 40 args.args[nargs+i] = 0; 41 42 if (prom(&args) < 0) 43 return -1; 44 45 return (nret > 0)? args.args[nargs]: 0; 46} 47 48int call_prom_ret(const char *service, int nargs, int nret, 49 unsigned int *rets, ...) 50{ 51 int i; 52 struct prom_args { 53 const char *service; 54 int nargs; 55 int nret; 56 unsigned int args[12]; 57 } args; 58 va_list list; 59 60 args.service = service; 61 args.nargs = nargs; 62 args.nret = nret; 63 64 va_start(list, rets); 65 for (i = 0; i < nargs; i++) 66 args.args[i] = va_arg(list, unsigned int); 67 va_end(list); 68 69 for (i = 0; i < nret; i++) 70 args.args[nargs+i] = 0; 71 72 if (prom(&args) < 0) 73 return -1; 74 75 if (rets != (void *) 0) 76 for (i = 1; i < nret; ++i) 77 rets[i-1] = args.args[nargs+i]; 78 79 return (nret > 0)? args.args[nargs]: 0; 80} 81 82int write(void *handle, void *ptr, int nb) 83{ 84 return call_prom("write", 3, 1, handle, ptr, nb); 85} 86 87/* 88 * Older OF's require that when claiming a specific range of addresses, 89 * we claim the physical space in the /memory node and the virtual 90 * space in the chosen mmu node, and then do a map operation to 91 * map virtual to physical. 92 */ 93static int need_map = -1; 94static ihandle chosen_mmu; 95static phandle memory; 96 97/* returns true if s2 is a prefix of s1 */ 98static int string_match(const char *s1, const char *s2) 99{ 100 for (; *s2; ++s2) 101 if (*s1++ != *s2) 102 return 0; 103 return 1; 104} 105 106static int check_of_version(void) 107{ 108 phandle oprom, chosen; 109 char version[64]; 110 111 oprom = finddevice("/openprom"); 112 if (oprom == (phandle) -1) 113 return 0; 114 if (getprop(oprom, "model", version, sizeof(version)) <= 0) 115 return 0; 116 version[sizeof(version)-1] = 0; 117 printf("OF version = '%s'\r\n", version); 118 if (!string_match(version, "Open Firmware, 1.") 119 && !string_match(version, "FirmWorks,3.")) 120 return 0; 121 chosen = finddevice("/chosen"); 122 if (chosen == (phandle) -1) { 123 chosen = finddevice("/chosen@0"); 124 if (chosen == (phandle) -1) { 125 printf("no chosen\n"); 126 return 0; 127 } 128 } 129 if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) { 130 printf("no mmu\n"); 131 return 0; 132 } 133 memory = (ihandle) call_prom("open", 1, 1, "/memory"); 134 if (memory == (ihandle) -1) { 135 memory = (ihandle) call_prom("open", 1, 1, "/memory@0"); 136 if (memory == (ihandle) -1) { 137 printf("no memory node\n"); 138 return 0; 139 } 140 } 141 printf("old OF detected\r\n"); 142 return 1; 143} 144 145void *claim(unsigned long virt, unsigned long size, unsigned long align) 146{ 147 int ret; 148 unsigned int result; 149 150 if (need_map < 0) 151 need_map = check_of_version(); 152 if (align || !need_map) 153 return (void *) call_prom("claim", 3, 1, virt, size, align); 154 155 ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory, 156 align, size, virt); 157 if (ret != 0 || result == -1) 158 return (void *) -1; 159 ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu, 160 align, size, virt); 161 /* 0x12 == coherent + read/write */ 162 ret = call_prom("call-method", 6, 1, "map", chosen_mmu, 163 0x12, size, virt, virt); 164 return (void *) virt; 165}