1 /****************************************************************************** 2 * Copyright (c) 2004, 2008 IBM Corporation extra()3 * All rights reserved. 4 * This program and the accompanying materials 5 * are made available under the terms of the BSD License 6 * which accompanies this distribution, and is available at 7 * http://www.opensource.org/licenses/bsd-license.php 8 * 9 * Contributors: 10 * IBM Corporation - initial implementation 11 *****************************************************************************/ 12 13 #include <stdint.h> 14 #include <stdarg.h> 15 #include <stdio.h> 16 #include <rtas.h> 17 #include <of.h> 18 #include <kernel.h> 19 20 typedef int rtas_arg_t; 21 22 typedef struct { 23 int token; 24 int nargs; 25 int nret; 26 rtas_arg_t args[16]; 27 rtas_arg_t *rets; /* Pointer to return values in args[]. */ 28 } rtas_args_t; 29 30 rtas_args_t rtas_args; 31 32 typedef struct { 33 void *rtas_start; 34 void *rtas_entry; 35 int rtas_size; 36 phandle_t dev; 37 } rtas_t; 38 39 extern rtas_t _rtas; 40 static int instantiate_rtas(void); 41 void rtas_call_entry(rtas_args_t *, void *, void *); 42 43 int 44 rtas_token(const char *service) 45 { 46 int token; 47 int retVal; 48 if (_rtas.dev == 0) 49 instantiate_rtas(); 50 51 retVal = of_getprop(_rtas.dev, service, &token, sizeof(token)); 52 if (retVal == -1) { 53 token = 0; 54 } 55 return token; 56 } 57 58 int 59 rtas_call(int token, int nargs, int nret, int *outputs, ...) 60 { 61 va_list list; 62 int i; 63 64 rtas_args.token = token; 65 rtas_args.nargs = nargs; 66 rtas_args.nret = nret; 67 rtas_args.rets = (rtas_arg_t *) & (rtas_args.args[nargs]); 68 va_start(list, outputs); 69 for (i = 0; i < nargs; ++i) { 70 rtas_args.args[i] = (rtas_arg_t) (va_arg(list, unsigned int)); 71 } 72 va_end(list); 73 74 for (i = 0; i < nret; ++i) 75 rtas_args.rets[i] = 0; 76 77 rtas_call_entry(&rtas_args, _rtas.rtas_start, _rtas.rtas_entry); 78 if (nret > 0 && outputs != 0) 79 for (i = 0; i < nret; i++) 80 outputs[i] = rtas_args.rets[i]; 81 #if 0 82 printf("rtas call %x %x %x args: %x %x %x %x %x %x %x %x\n", 83 token, nargs, nret, 84 rtas_args.args[0], 85 rtas_args.args[1], 86 rtas_args.args[2], 87 rtas_args.args[3], 88 rtas_args.args[4], rtas_args.args[5], outputs[0], outputs[1]); 89 #endif 90 return ((nret > 0) ? rtas_args.rets[0] : 0); 91 } 92 93 rtas_t _rtas; 94 95 static int 96 instantiate_rtas(void) 97 { 98 long long *rtas_mem_space; 99 ihandle_t ihandle; 100 101 _rtas.dev = of_finddevice("/rtas"); 102 if ((long) _rtas.dev < 0) { 103 printf("\nCould not open /rtas\n"); 104 return -1; 105 } 106 107 of_getprop(_rtas.dev, "rtas-size", &_rtas.rtas_size, 108 sizeof(_rtas.rtas_size)); 109 110 if (_rtas.rtas_size <= 0) { 111 printf("\nSize of rtas (%x) too small to make sense\n", 112 _rtas.rtas_size); 113 return -1; 114 } 115 116 rtas_mem_space = (long long *) malloc_aligned(_rtas.rtas_size, 0x100); 117 118 if (!rtas_mem_space) { 119 printf("\nFailed to allocated memory for RTAS\n"); 120 return -1; 121 } 122 123 ihandle = of_open("/rtas"); 124 125 if ((long) ihandle < 0) { 126 printf("Could not open /rtas\n"); 127 return -1; 128 } 129 130 if ((long) (_rtas.rtas_entry = of_call_method_3("instantiate-rtas", 131 ihandle, 132 p32cast rtas_mem_space)) 133 > 0) { 134 _rtas.rtas_start = rtas_mem_space; 135 } else { 136 printf("instantiate-rtas failed\n"); 137 return -1; 138 } 139 #if 0 140 printf("\ninstantiate-rtas at %x size %x entry %x\n", 141 _rtas.rtas_start, _rtas.rtas_size, _rtas.rtas_entry); 142 #endif 143 return 0; 144 } 145 146 static int read_pci_config_token = 0; 147 static int write_pci_config_token = 0; 148 static int ibm_read_pci_config_token = 0; 149 static int ibm_write_pci_config_token = 0; 150 static int get_time_of_day_token = 0; 151 152 void 153 rtas_init() 154 { 155 int ret; 156 ret = instantiate_rtas(); 157 if (ret) 158 return; 159 read_pci_config_token = rtas_token("read-pci-config"); 160 ibm_read_pci_config_token = rtas_token("ibm,read-pci-config"); 161 write_pci_config_token = rtas_token("write-pci-config"); 162 ibm_write_pci_config_token = rtas_token("ibm,write-pci-config"); 163 get_time_of_day_token = rtas_token("get-time-of-day"); 164 } 165 166 167 int 168 rtas_pci_config_read(long long puid, int size, int bus, int devfn, int offset) 169 { 170 int value[2]; 171 172 if (ibm_read_pci_config_token && puid) { 173 rtas_call(ibm_read_pci_config_token, 4, 2, value, 174 bus << 16 | devfn << 8 | offset, 175 puid >> 32, puid & 0xffffffffULL, size); 176 } else if (read_pci_config_token) { 177 rtas_call(read_pci_config_token, 2, 2, value, 178 bus << 16 | devfn << 8 | offset, size); 179 } 180 181 return value[1]; 182 } 183 184 int 185 rtas_pci_config_write(long long puid, int size, int bus, int devfn, 186 int offset, int value) 187 { 188 int rc; 189 190 if (ibm_write_pci_config_token && puid) { 191 rtas_call(ibm_write_pci_config_token, 5, 1, &rc, 192 bus << 16 | devfn << 8 | offset, 193 puid >> 32, puid & 0xffffffffULL, size, value); 194 } else 195 rtas_call(write_pci_config_token, 3, 1, &rc, 196 bus << 16 | devfn << 8 | offset, size, value); 197 198 return rc; 199 } 200 201 int 202 rtas_get_time_of_day(dtime * get) 203 { 204 int rc = -1; 205 unsigned int year; 206 unsigned int month; 207 unsigned int day; 208 unsigned int hour; 209 unsigned int minute; 210 unsigned int second; 211 unsigned int nano; 212 213 if (get_time_of_day_token) 214 rtas_call(get_time_of_day_token, 0, 8, &rc, &year, &month, &day, 215 &hour, &minute, &second, &nano); 216 217 get->year = year; 218 get->month = month; 219 get->day = day; 220 get->hour = hour; 221 get->minute = minute; 222 get->second = second; 223 get->nano = nano; 224 225 return rc; 226 } 227