diff options
Diffstat (limited to 'qemu/roms/SLOF/clients/net-snk/oflib/rtas.c')
-rw-r--r-- | qemu/roms/SLOF/clients/net-snk/oflib/rtas.c | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/qemu/roms/SLOF/clients/net-snk/oflib/rtas.c b/qemu/roms/SLOF/clients/net-snk/oflib/rtas.c new file mode 100644 index 000000000..c514c7079 --- /dev/null +++ b/qemu/roms/SLOF/clients/net-snk/oflib/rtas.c @@ -0,0 +1,226 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdint.h> +#include <stdarg.h> +#include <stdio.h> +#include <rtas.h> +#include <of.h> +#include <kernel.h> + +typedef int rtas_arg_t; + +typedef struct { + int token; + int nargs; + int nret; + rtas_arg_t args[16]; + rtas_arg_t *rets; /* Pointer to return values in args[]. */ +} rtas_args_t; + +rtas_args_t rtas_args; + +typedef struct { + void *rtas_start; + void *rtas_entry; + int rtas_size; + phandle_t dev; +} rtas_t; + +extern rtas_t _rtas; +static int instantiate_rtas(void); +void rtas_call_entry(rtas_args_t *, void *, void *); + +int +rtas_token(const char *service) +{ + int token; + int retVal; + if (_rtas.dev == 0) + instantiate_rtas(); + + retVal = of_getprop(_rtas.dev, service, &token, sizeof(token)); + if (retVal == -1) { + token = 0; + } + return token; +} + +int +rtas_call(int token, int nargs, int nret, int *outputs, ...) +{ + va_list list; + int i; + + rtas_args.token = token; + rtas_args.nargs = nargs; + rtas_args.nret = nret; + rtas_args.rets = (rtas_arg_t *) & (rtas_args.args[nargs]); + va_start(list, outputs); + for (i = 0; i < nargs; ++i) { + rtas_args.args[i] = (rtas_arg_t) (va_arg(list, unsigned int)); + } + va_end(list); + + for (i = 0; i < nret; ++i) + rtas_args.rets[i] = 0; + + rtas_call_entry(&rtas_args, _rtas.rtas_start, _rtas.rtas_entry); + if (nret > 0 && outputs != 0) + for (i = 0; i < nret; i++) + outputs[i] = rtas_args.rets[i]; +#if 0 + printf("rtas call %x %x %x args: %x %x %x %x %x %x %x %x\n", + token, nargs, nret, + rtas_args.args[0], + rtas_args.args[1], + rtas_args.args[2], + rtas_args.args[3], + rtas_args.args[4], rtas_args.args[5], outputs[0], outputs[1]); +#endif + return ((nret > 0) ? rtas_args.rets[0] : 0); +} + +rtas_t _rtas; + +static int +instantiate_rtas(void) +{ + long long *rtas_mem_space; + ihandle_t ihandle; + + _rtas.dev = of_finddevice("/rtas"); + if ((long) _rtas.dev < 0) { + printf("\nCould not open /rtas\n"); + return -1; + } + + of_getprop(_rtas.dev, "rtas-size", &_rtas.rtas_size, + sizeof(_rtas.rtas_size)); + + if (_rtas.rtas_size <= 0) { + printf("\nSize of rtas (%x) too small to make sense\n", + _rtas.rtas_size); + return -1; + } + + rtas_mem_space = (long long *) malloc_aligned(_rtas.rtas_size, 0x100); + + if (!rtas_mem_space) { + printf("\nFailed to allocated memory for RTAS\n"); + return -1; + } + + ihandle = of_open("/rtas"); + + if ((long) ihandle < 0) { + printf("Could not open /rtas\n"); + return -1; + } + + if ((long) (_rtas.rtas_entry = of_call_method_3("instantiate-rtas", + ihandle, + p32cast rtas_mem_space)) + > 0) { + _rtas.rtas_start = rtas_mem_space; + } else { + printf("instantiate-rtas failed\n"); + return -1; + } +#if 0 + printf("\ninstantiate-rtas at %x size %x entry %x\n", + _rtas.rtas_start, _rtas.rtas_size, _rtas.rtas_entry); +#endif + return 0; +} + +static int read_pci_config_token = 0; +static int write_pci_config_token = 0; +static int ibm_read_pci_config_token = 0; +static int ibm_write_pci_config_token = 0; +static int get_time_of_day_token = 0; + +void +rtas_init() +{ + int ret; + ret = instantiate_rtas(); + if (ret) + return; + read_pci_config_token = rtas_token("read-pci-config"); + ibm_read_pci_config_token = rtas_token("ibm,read-pci-config"); + write_pci_config_token = rtas_token("write-pci-config"); + ibm_write_pci_config_token = rtas_token("ibm,write-pci-config"); + get_time_of_day_token = rtas_token("get-time-of-day"); +} + + +int +rtas_pci_config_read(long long puid, int size, int bus, int devfn, int offset) +{ + int value[2]; + + if (ibm_read_pci_config_token && puid) { + rtas_call(ibm_read_pci_config_token, 4, 2, value, + bus << 16 | devfn << 8 | offset, + puid >> 32, puid & 0xffffffffULL, size); + } else if (read_pci_config_token) { + rtas_call(read_pci_config_token, 2, 2, value, + bus << 16 | devfn << 8 | offset, size); + } + + return value[1]; +} + +int +rtas_pci_config_write(long long puid, int size, int bus, int devfn, + int offset, int value) +{ + int rc; + + if (ibm_write_pci_config_token && puid) { + rtas_call(ibm_write_pci_config_token, 5, 1, &rc, + bus << 16 | devfn << 8 | offset, + puid >> 32, puid & 0xffffffffULL, size, value); + } else + rtas_call(write_pci_config_token, 3, 1, &rc, + bus << 16 | devfn << 8 | offset, size, value); + + return rc; +} + +int +rtas_get_time_of_day(dtime * get) +{ + int rc = -1; + unsigned int year; + unsigned int month; + unsigned int day; + unsigned int hour; + unsigned int minute; + unsigned int second; + unsigned int nano; + + if (get_time_of_day_token) + rtas_call(get_time_of_day_token, 0, 8, &rc, &year, &month, &day, + &hour, &minute, &second, &nano); + + get->year = year; + get->month = month; + get->day = day; + get->hour = hour; + get->minute = minute; + get->second = second; + get->nano = nano; + + return rc; +} |