__openfirmware long rtas_call(int token, int nargs, int nret, unsigned long *outputs, ...) { va_list list; int i; unsigned long s; struct rtas_args *rtas_args = &(get_paca()->xRtas); PPCDBG(PPCDBG_RTAS, "Entering rtas_call\n"); PPCDBG(PPCDBG_RTAS, "\ttoken = 0x%x\n", token); PPCDBG(PPCDBG_RTAS, "\tnargs = %d\n", nargs); PPCDBG(PPCDBG_RTAS, "\tnret = %d\n", nret); PPCDBG(PPCDBG_RTAS, "\t&outputs = 0x%lx\n", outputs); if (token == RTAS_UNKNOWN_SERVICE) return -1; 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)LONG_LSW(va_arg(list, ulong)); PPCDBG(PPCDBG_RTAS, "\tnarg[%d] = 0x%lx\n", i, rtas_args->args[i]); } va_end(list); for (i = 0; i < nret; ++i) rtas_args->rets[i] = 0; #if 0 /* Gotta do something different here, use global lock for now... */ spin_lock_irqsave(&rtas_args->lock, s); #else spin_lock_irqsave(&rtas.lock, s); #endif PPCDBG(PPCDBG_RTAS, "\tentering rtas with 0x%lx\n", (void *)__pa((unsigned long)rtas_args)); enter_rtas((void *)__pa((unsigned long)rtas_args)); PPCDBG(PPCDBG_RTAS, "\treturned from rtas ...\n"); #if 0 /* Gotta do something different here, use global lock for now... */ spin_unlock_irqrestore(&rtas_args->lock, s); #else spin_unlock_irqrestore(&rtas.lock, s); #endif ifppcdebug(PPCDBG_RTAS) { for(i=0; i < nret ;i++) udbg_printf("\tnret[%d] = 0x%lx\n", i, (ulong)rtas_args->rets[i]); } if (nret > 1 && outputs != NULL) for (i = 0; i < nret-1; ++i) outputs[i] = rtas_args->rets[i+1]; return (ulong)((nret > 0) ? rtas_args->rets[0] : 0); }
void phys_call_rtas(int token, int nargs, int nret, ...) { va_list list; unsigned long offset = reloc_offset(); struct rtas_args *rtas = PTRRELOC(&(get_paca()->xRtas)); int i; rtas->token = token; rtas->nargs = nargs; rtas->nret = nret; rtas->rets = (rtas_arg_t *)PTRRELOC(&(rtas->args[nargs])); va_start(list, nret); for (i = 0; i < nargs; i++) rtas->args[i] = (rtas_arg_t)LONG_LSW(va_arg(list, ulong)); va_end(list); enter_rtas(rtas); }
__openfirmware long rtas_call(int token, int nargs, int nret, unsigned long *outputs, ...) { va_list list; int i, logit = 0; unsigned long flags; struct rtas_args *rtas_args; char * buff_copy = NULL; unsigned long retval; PPCDBG(PPCDBG_RTAS, "Entering rtas_call\n"); PPCDBG(PPCDBG_RTAS, "\ttoken = 0x%x\n", token); PPCDBG(PPCDBG_RTAS, "\tnargs = %d\n", nargs); PPCDBG(PPCDBG_RTAS, "\tnret = %d\n", nret); PPCDBG(PPCDBG_RTAS, "\t&outputs = 0x%lx\n", outputs); if (token == RTAS_UNKNOWN_SERVICE) return -1; spin_lock_irqsave(&rtas.lock, flags); rtas_args = &(get_paca()->xRtas); 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)LONG_LSW(va_arg(list, ulong)); PPCDBG(PPCDBG_RTAS, "\tnarg[%d] = 0x%lx\n", i, rtas_args->args[i]); } va_end(list); for (i = 0; i < nret; ++i) rtas_args->rets[i] = 0; PPCDBG(PPCDBG_RTAS, "\tentering rtas with 0x%lx\n", (void *)__pa((unsigned long)rtas_args)); enter_rtas((void *)__pa((unsigned long)rtas_args)); PPCDBG(PPCDBG_RTAS, "\treturned from rtas ...\n"); /* A -1 return code indicates that the last command couldn't * be completed due to a hardware error. */ if (rtas_args->rets[0] == -1) logit = (__fetch_rtas_last_error() == 0); ifppcdebug(PPCDBG_RTAS) { for(i=0; i < nret ;i++) udbg_printf("\tnret[%d] = 0x%lx\n", i, (ulong)rtas_args->rets[i]); } if (nret > 1 && outputs != NULL) for (i = 0; i < nret-1; ++i) outputs[i] = rtas_args->rets[i+1]; retval = (ulong)((nret > 0) ? rtas_args->rets[0] : 0); /* Log the error in the unlikely case that there was one. */ if (unlikely(logit)) { /* Can't call kmalloc if VM subsystem is not yet up. */ if (slabpages>0) { buff_copy = kmalloc(RTAS_ERROR_LOG_MAX, GFP_ATOMIC); if (buff_copy) { memcpy(buff_copy, rtas_err_buf, RTAS_ERROR_LOG_MAX); } } } spin_unlock_irqrestore(&rtas.lock, flags); if (buff_copy) { log_error(buff_copy, ERR_TYPE_RTAS_LOG, 0); kfree(buff_copy); } return retval; }