static void ieee_value_to_sym(cell_t *cif) { u_int nargs, nresults; u_long value; u_int offset; char *name = symbol; extern u_long value_to_name(uintptr_t value, char *symbol); nargs = p1275_cell2uint(cif[1]); nresults = p1275_cell2uint(cif[2]); if (nresults == 0) return; /* No room for results. Just return. */ /* * If there are no arguments, fall through and return "not found". * Otherwise, try to translate the value to a symbol-name/offset. */ *name = (char)0; offset = (u_int)-1; if (nargs != 0) { value = p1275_cell2uintptr(cif[3]); /* argument 0 */ offset = value_to_name(value, name); } /* * Stuff the results in the argument array and set the * nresults element to the number of results actually returned * in the argument array. (It's a maximum of 2). * * cif[0]: service name ( Pointer to service name ) * cif[1]: nargs ( number of argument cells) * cif[2]: nresults ( number of result cells) * cif[3]: argument{0} ( First argument cell ) * ... * cif[3 + nargs]: result{0} ( First result cell ) * ... */ /* * Treat this as an integer, so we sign-extend -1, offsets * are always postive, -1 indicates not found. */ cif[3 + nargs] = p1275_int2cell((int)offset); if (nresults > 1) { cif[3 + nargs + 1] = p1275_ptr2cell(name); cif[2] = p1275_int2cell(2); /* there are 2 results */ } else { cif[2] = p1275_int2cell(1); /* there is 1 result */ } }
static void ieee_sym_to_value(cell_t *cif) { int error = -1; uintptr_t symvalue = 0; unsigned int nargs, nresults; char *symname; extern int name_to_value(char *name, uintptr_t *value); nargs = p1275_cell2uint(cif[1]); nresults = p1275_cell2uint(cif[2]); if (nresults == 0) return; /* No room for results. Just return. */ /* * If there are no arguments, fall through and return an error. * Otherwise, try to translate the symbol name arg to a value. */ if (nargs != 0) { symname = p1275_cell2ptr(cif[3]); /* argument 0 */ error = name_to_value(symname, &symvalue); } /* * Stuff the results in the argument array and set the * nresults element to the number of results actually returned * in the argument array. (It's a maximum of 2). * * cif[0]: service name ( Pointer to service name ) * cif[1]: nargs ( number of argument cells) * cif[2]: nresults ( number of result cells) * cif[3]: argument{0} ( First argument cell ) * ... * cif[3 + nargs]: result{0} ( First result cell ) * ... */ cif[3 + nargs] = p1275_int2cell(error); if (nresults > 1) { cif[3 + nargs + 1] = p1275_uintptr2cell(symvalue); cif[2] = p1275_int2cell(2); /* there are 2 results */ } else { cif[2] = p1275_int2cell(1); /* there is 1 result */ } }
int promif_asr_list_keys_len(void *p) { cell_t *ci = (cell_t *)p; ci[3] = p1275_int2cell(-1); return (-1); }
int prom_asr_disable(char *keystr, int keystr_len, char *reason, int reason_len) { int rv; cell_t ci[5]; ci[0] = p1275_ptr2cell("SUNW,asr-disable"); /* Service name */ ci[1] = (cell_t)4; /* #argument cells */ ci[2] = (cell_t)0; /* #return cells */ ci[3] = p1275_ptr2cell(keystr); /* Arg1: key address */ ci[3] = p1275_int2cell(keystr_len); /* Arg2: key len */ ci[3] = p1275_ptr2cell(reason); /* Arg1: reason address */ ci[3] = p1275_int2cell(reason_len); /* Arg2: reason len */ promif_preprom(); rv = p1275_cif_handler(&ci); promif_postprom(); return (rv); }
/* * Read the date using "set-time" method in rtc node * For values 00 - 68, write 2000-2068, and for 69-99, * write 1969-1999 */ static int todds1307_prom_setdate(struct rtc_t *rtc) { int year; cell_t ci[12]; year = rtc->rtc_year; if ((year < 0) || (year > 99)) return (DDI_FAILURE); if (year <= 68) year = rtc->rtc_year + 2000; else year = rtc->rtc_year + 1900; ci[0] = p1275_ptr2cell("call-method"); /* Service name */ ci[1] = 8; /* # of arguments */ ci[2] = 0; /* # of result cells */ ci[3] = p1275_ptr2cell("set-time"); ci[4] = p1275_ihandle2cell(todds1307_ihandle); ci[5] = p1275_int2cell(year); ci[6] = p1275_int2cell(rtc->rtc_mon); ci[7] = p1275_int2cell(rtc->rtc_dom); ci[8] = p1275_int2cell(rtc->rtc_hrs); ci[9] = p1275_int2cell(rtc->rtc_min); ci[10] = p1275_int2cell(rtc->rtc_sec); promif_preprom(); (void) p1275_cif_handler(&ci); promif_postprom(); return (DDI_SUCCESS); }
int promif_get_sun4v_api_version(void *p) { cell_t *ci = (cell_t *)p; uint64_t api_group; uint64_t major; uint64_t minor; uint64_t status; ASSERT(ci[1] == 1); ASSERT(ci[2] == 3); api_group = (uint64_t)p1275_cell2int(ci[3]); status = hv_api_get_version(api_group, &major, &minor); ci[4] = p1275_int2cell(status); ci[5] = p1275_int2cell(major); ci[6] = p1275_int2cell(minor); return ((status == H_EOK) ? 0 : -1); }
int promif_set_sun4v_api_version(void *p) { cell_t *ci = (cell_t *)p; uint64_t api_group; uint64_t major; uint64_t minor; uint64_t status; uint64_t supported_minor; ASSERT(ci[1] == 3); ASSERT(ci[2] == 2); api_group = (uint64_t)p1275_cell2int(ci[3]); major = (uint64_t)p1275_cell2int(ci[4]); minor = (uint64_t)p1275_cell2int(ci[5]); status = hv_api_set_version(api_group, major, minor, &supported_minor); ci[6] = p1275_int2cell(status); ci[7] = p1275_int2cell(supported_minor); return ((status == H_EOK) ? 0 : -1); }
int prom_setprop(pnode_t nodeid, caddr_t name, caddr_t value, int len) { cell_t ci[8]; #ifdef PROM_32BIT_ADDRS caddr_t ovalue = NULL; if ((uintptr_t)value > (uint32_t)-1) { ovalue = value; value = promplat_alloc(len); if (value == NULL) { return (-1); } promplat_bcopy(ovalue, value, len); } #endif prom_setprop_enter(); promif_preprom(); ci[0] = p1275_ptr2cell("setprop"); /* Service name */ ci[1] = (cell_t)4; /* #argument cells */ ci[2] = (cell_t)1; /* #result cells */ ci[3] = p1275_phandle2cell((phandle_t)nodeid); /* Arg1: phandle */ ci[4] = p1275_ptr2cell(name); /* Arg2: property name */ ci[5] = p1275_ptr2cell(value); /* Arg3: New value ptr */ ci[6] = p1275_int2cell(len); /* Arg4: New value len */ ci[7] = (cell_t)-1; /* Res1: Prime result */ (void) p1275_cif_handler(&ci); promif_postprom(); prom_setprop_exit(); #ifdef PROM_32BIT_ADDRS if (ovalue != NULL) promplat_free(value, len); #endif return (p1275_cell2int(ci[7])); /* Res1: Actual new size */ }
int prom_bounded_getprop(pnode_t nodeid, caddr_t name, caddr_t value, int len) { cell_t ci[8]; ci[0] = p1275_ptr2cell("getprop"); /* Service name */ ci[1] = (cell_t)4; /* #argument cells */ ci[2] = (cell_t)1; /* #result cells */ ci[3] = p1275_phandle2cell((phandle_t)nodeid); /* Arg1: package */ ci[4] = p1275_ptr2cell(name); /* Arg2: property name */ ci[5] = p1275_ptr2cell(value); /* Arg3: buffer address */ ci[6] = p1275_int2cell(len); /* Arg4: buffer length */ ci[7] = (cell_t)-1; /* Res1: Prime result */ promif_preprom(); (void) p1275_cif_handler(&ci); promif_postprom(); return (p1275_cell2int(ci[7])); /* Res1: Returned length */ }
/* * This service converts the given physical address into a text string, * representing the name of the field-replacable part for the given * physical address. In other words, it tells the kernel which ecache * module got the (un)correctable ECC error. */ int prom_serengeti_get_ecacheunum(int cpuid, unsigned long long physaddr, char *buf, uint_t buflen, int *ustrlen) { cell_t ci[12]; int rv; ihandle_t imemory = prom_memory_ihandle(); *ustrlen = -1; if ((imemory == (ihandle_t)-1)) return (-1); if (prom_test_method("SUNW,Serengeti,get-ecache-unum", prom_getphandle(imemory)) != 0) return (-1); ci[0] = p1275_ptr2cell("call-method"); /* Service name */ ci[1] = (cell_t)7; /* #argument cells */ ci[2] = (cell_t)2; /* #result cells */ ci[3] = p1275_ptr2cell("SUNW,Serengeti,get-ecache-unum"); /* Arg1: Method name */ ci[4] = p1275_ihandle2cell(imemory); /* Arg2: mem. ihandle */ ci[5] = p1275_uint2cell(buflen); /* Arg3: buflen */ ci[6] = p1275_ptr2cell(buf); /* Arg4: buf */ ci[7] = p1275_ull2cell_high(physaddr); /* Arg5: physhi */ ci[8] = p1275_ull2cell_low(physaddr); /* Arg6: physlo */ ci[9] = p1275_int2cell(cpuid); /* Arg7: cpuid */ ci[10] = (cell_t)-1; /* ret1: catch result */ ci[11] = (cell_t)-1; /* ret2: length */ promif_preprom(); rv = p1275_cif_handler(&ci); promif_postprom(); if (rv != 0) return (rv); if (p1275_cell2int(ci[10]) != 0) /* Res1: catch result */ return (-1); /* "SUNW,Serengeti,get-ecache-unum" failed */ *ustrlen = p1275_cell2uint(ci[11]); /* Res2: unum str length */ return (0); }