/* * Allocate physical memory, unmapped and possibly aligned. * Returns 0: Success; Non-zero: failure. * Returns *physaddr only if successful. * * This routine is suitable for platforms with 2-cell physical addresses * and a single size cell in the "memory" node. */ int prom_allocate_phys(size_t size, uint32_t align, u_longlong_t *physaddr) { cell_t ci[10]; int32_t rv; ihandle_t imemory = prom_memory_ihandle(); if ((imemory == (ihandle_t)-1)) return (-1); if (align == 0) align = (uint32_t)1; ci[0] = p1275_ptr2cell("call-method"); /* Service name */ ci[1] = (cell_t)4; /* #argument cells */ ci[2] = (cell_t)3; /* #result cells */ ci[3] = p1275_ptr2cell("claim"); /* Arg1: Method name */ ci[4] = p1275_ihandle2cell(imemory); /* Arg2: memory ihandle */ ci[5] = p1275_uint2cell(align); /* Arg3: SA1: align */ ci[6] = p1275_size2cell(size); /* Arg4: SA2: size */ rv = p1275_cif_handler(&ci); if (rv != 0) return (rv); if (p1275_cell2int(ci[7]) != 0) /* Res1: Catch result */ return (-1); *physaddr = p1275_cells2ull(ci[8], ci[9]); /* Res2: SR1: phys.hi ... Res3: SR2: phys.lo */ return (0); }
/* * unmap virt, then map virt to new phys; * see remap definition below */ int prom_remap(size_t size, caddr_t virt, physaddr_t phys) { ihandle_t immu; cell_t ci[8]; int rv; immu = prom_mmu_ihandle(); if (immu == (ihandle_t)-1) return (ERR); ci[0] = p1275_ptr2cell("call-method"); /* Service name */ ci[1] = (cell_t)5; /* #argument cells */ ci[2] = (cell_t)0; /* #result cells */ ci[3] = p1275_ptr2cell("remap"); /* Arg1: Method name */ ci[4] = p1275_ihandle2cell(immu); /* Arg2: memory ihandle */ ci[5] = p1275_size2cell(size); /* remap arg0 */ ci[6] = p1275_ptr2cell(virt); /* remap arg1 */ ci[7] = p1275_ull2cell_low(phys); /* remap arg2 */ promif_preprom(); rv = p1275_cif_handler(ci); promif_postprom(); if (rv) return (rv); /* Service "call-method" failed */ return (0); }
/* * Claim a region of physical memory, unmapped. * Returns 0: Success; Non-zero: failure. * * This routine is suitable for platforms with 2-cell physical addresses * and a single size cell in the "memory" node. */ int prom_claim_phys(size_t size, u_longlong_t physaddr) { cell_t ci[10]; int32_t rv; ihandle_t imemory = prom_memory_ihandle(); if ((imemory == (ihandle_t)-1)) return (-1); ci[0] = p1275_ptr2cell("call-method"); /* Service name */ ci[1] = (cell_t)6; /* #argument cells */ ci[2] = (cell_t)1; /* #result cells */ ci[3] = p1275_ptr2cell("claim"); /* Arg1: Method name */ ci[4] = p1275_ihandle2cell(imemory); /* Arg2: mmu ihandle */ ci[5] = 0; /* Arg3: SA1: align */ ci[6] = p1275_size2cell(size); /* Arg4: SA2: len */ ci[7] = p1275_ull2cell_high(physaddr); /* Arg5: SA3: phys.hi */ ci[8] = p1275_ull2cell_low(physaddr); /* Arg6: SA4: phys.lo */ rv = p1275_cif_handler(&ci); if (rv != 0) return (rv); if (p1275_cell2int(ci[9]) != 0) /* Res1: Catch result */ return (-1); return (0); }
/* * Read the date using "get-time" method in rtc node * PROM returns 1969-1999 when reading 69-99 and * 2000-2068 when reading 00-68 */ static int todds1307_prom_getdate(struct rtc_t *rtc) { int year; cell_t ci[12]; ci[0] = p1275_ptr2cell("call-method"); /* Service name */ ci[1] = 2; /* # of arguments */ ci[2] = 7; /* # of result cells */ ci[3] = p1275_ptr2cell("get-time"); ci[4] = p1275_ihandle2cell(todds1307_ihandle); promif_preprom(); (void) p1275_cif_handler(&ci); promif_postprom(); year = p1275_cell2int(ci[6]); rtc->rtc_mon = p1275_cell2int(ci[7]); rtc->rtc_dom = p1275_cell2int(ci[8]); rtc->rtc_dow = 0; rtc->rtc_hrs = p1275_cell2int(ci[9]); rtc->rtc_min = p1275_cell2int(ci[10]); rtc->rtc_sec = p1275_cell2int(ci[11]); if (year >= 2000) year -= 2000; else year -= 1900; rtc->rtc_year = year; return (DDI_SUCCESS); }
int prom_pathname(char *pathname) { char *from = buffer; char *to = pathname; cell_t ci[7]; if ((to == (char *)0) || (*to == (char)0)) return; (void) prom_strcpy(from, to); *to = (char)0; ci[0] = p1275_ptr2cell("canon"); /* Service name */ ci[1] = (cell_t)3; /* #argument cells */ ci[2] = (cell_t)1; /* #result cells */ ci[3] = p1275_ptr2cell(from); /* Arg1: device specifier */ ci[4] = p1275_ptr2cell(to); /* Arg2: buffer address */ ci[5] = p1275_uint2cell(OBP_MAXPATHLEN); /* Arg3: buffer length */ ci[6] = (cell_t)-1; (void) p1275_cif_handler(&ci); return (p1275_cell2int(ci[6])); /* Res1: length */ }
/* * 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 prom_getprop(pnode_t nodeid, caddr_t name, caddr_t value) { int len, rv; cell_t ci[8]; /* * This function assumes the buffer is large enough to * hold the result, so in 1275 mode, we pass in the length * of the property as the length of the buffer, since we * have no way of knowing the size of the buffer. Pre-1275 * OpenBoot(tm) PROMs did not have a bounded getprop. * * Note that we ignore the "length" result of the service. */ if ((len = prom_getproplen(nodeid, name)) <= 0) return (len); ci[0] = p1275_ptr2cell("getprop"); /* Service name */ ci[1] = (cell_t)4; /* #argument cells */ ci[2] = (cell_t)0; /* #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] = len; /* Arg4: buf len (assumed) */ promif_preprom(); rv = p1275_cif_handler(&ci); promif_postprom(); if (rv != 0) return (-1); return (len); /* Return known length */ }
/* * Get Fcode into supplied buffer. */ int prom_get_fcode(char *str, char *buf) { cell_t ci[6]; int rv; if (prom_test("SUNW,get-fcode") != 0) { return (0); } ci[0] = p1275_ptr2cell("SUNW,get-fcode"); ci[1] = (cell_t)2; /* 2 input args: str + buf */ ci[2] = (cell_t)1; /* 1 output result: true or false */ ci[3] = p1275_ptr2cell(buf); /* Arg#1: buffer to put fcode */ ci[4] = p1275_ptr2cell(str); /* Arg#2: name of drop-in */ ci[5] = (cell_t)0; promif_preprom(); rv = p1275_cif_handler(&ci); promif_postprom(); if (rv == 0) return (p1275_cell2int(ci[5])); return (0); }
/* * This interface allows the client to safely take over the %tba by * the prom's service. The prom will take care of the quiescence of * interrupts and handle any pending soft interrupts. */ void prom_set_traptable(void *tba_addr) { cell_t ci[4]; ci[0] = p1275_ptr2cell("SUNW,set-trap-table"); /* Service name */ ci[1] = (cell_t)1; /* #argument cells */ ci[2] = (cell_t)0; /* #result cells */ ci[3] = p1275_ptr2cell(tba_addr); /* Arg1: tba address */ (void) p1275_cif_handler(&ci); }
/* * Request that OBP write 'len' bytes from the memory indicated by 'buf' into * the IOSRAM chunk associated with 'key', starting at 'offset'. Although there * is a driver that provides this functionality, there are certain cases where * the OS requires access to IOSRAM before the driver is loaded. Return 0 on * success, non-zero on failure. */ int prom_starcat_iosram_write(uint32_t key, uint32_t offset, uint32_t len, caddr_t buf) { static uint8_t warned = 0; cell_t ci[8]; int rv; /* * Make sure we have the necessary support in OBP. */ if (prom_test(iosram_write_cmd) == 0) { ci[0] = p1275_ptr2cell(iosram_write_cmd); /* name */ } else { if (!warned) { warned = 1; prom_printf( "Warning: No prom support for iosram-write!\n"); } return (-1); } /* * Set up the arguments and call into OBP. Note that the argument order * needs to be reversed to accomodate OBP. The order must remain as it * is in the function prototype to maintain intercompatibility with the * IOSRAM driver's equivalent routine. */ ci[1] = (cell_t)4; /* #argument cells */ ci[2] = (cell_t)1; /* #result cells */ ci[3] = p1275_ptr2cell(buf); ci[4] = p1275_uint2cell(len); ci[5] = p1275_uint2cell(offset); ci[6] = p1275_uint2cell(key); promif_preprom(); rv = p1275_cif_handler(&ci); promif_postprom(); /* * p1275_cif_handler will return 0 on success, non-zero on failure. If * it fails, the return cell from OBP is meaningless, because the OBP * client interface probably wasn't even invoked. OBP will return 0 on * success and non-zero on failure for this interface. */ if (rv != 0) { return (rv); } else if (p1275_cell2int(ci[7]) == 0) { return (0); } else { return (-1); } }
/* * Returns 0 on error. Otherwise returns a handle. */ ihandle_t prom_open(char *path) { cell_t ci[5]; ci[0] = p1275_ptr2cell("open"); /* Service name */ ci[1] = (cell_t)1; /* #argument cells */ ci[2] = (cell_t)1; /* #result cells */ ci[3] = p1275_ptr2cell(path); /* Arg1: Pathname */ ci[4] = (cell_t)0; /* Res1: Prime result */ (void) p1275_cif_handler(&ci); return (p1275_cell2ihandle(ci[4])); /* Res1: ihandle */ }
/* * Test for existance of a specific P1275 client interface service */ int prom_test(char *service) { cell_t ci[5]; ci[0] = p1275_ptr2cell("test"); /* Service name */ ci[1] = (cell_t)1; /* #argument cells */ ci[2] = (cell_t)1; /* #result cells */ ci[3] = p1275_ptr2cell(service); /* Arg1: requested svc name */ ci[4] = (cell_t)-1; /* Res1: Prime result */ (void) p1275_cif_handler(&ci); return (p1275_cell2int(ci[4])); /* Res1: missing flag */ }
void prom_free(caddr_t virt, size_t size) { cell_t ci[5]; ci[0] = p1275_ptr2cell("release"); /* Service name */ ci[1] = (cell_t)2; /* #argument cells */ ci[2] = (cell_t)0; /* #result cells */ ci[3] = p1275_ptr2cell(virt); /* Arg1: virt */ ci[4] = p1275_uint2cell(size); /* Arg2: size */ promif_preprom(); (void) p1275_cif_handler(&ci); promif_postprom(); }
void prom_set_symbol_lookup(void *sym2val, void *val2sym) { cell_t ci[5]; ci[0] = p1275_ptr2cell("set-symbol-lookup"); /* Service name */ ci[1] = (cell_t)2; /* #argument cells */ ci[2] = (cell_t)0; /* #return cells */ ci[3] = p1275_ptr2cell(sym2val); /* Arg1: s2v handler */ ci[4] = p1275_ptr2cell(val2sym); /* Arg1: v2s handler */ promif_preprom(); (void) p1275_cif_handler(&ci); promif_postprom(); }
int prom_test_method(char *method, dnode_t node) { cell_t ci[6]; ci[0] = p1275_ptr2cell("test-method"); /* service */ ci[1] = (cell_t)2; /* #argument cells */ ci[2] = (cell_t)1; /* #result cells */ ci[3] = p1275_dnode2cell(node); ci[4] = p1275_ptr2cell(method); ci[5] = (cell_t)-1; (void) p1275_cif_handler(&ci); return (p1275_cell2int(ci[5])); }
uint32_t prom_read(ihandle_t fd, caddr_t buf, uint32_t len) { cell_t ci[7]; ci[0] = p1275_ptr2cell("read"); /* Service name */ ci[1] = (cell_t)3; /* #argument cells */ ci[2] = (cell_t)1; /* #result cells */ ci[3] = p1275_ihandle2cell(fd); /* Arg1: ihandle */ ci[4] = p1275_ptr2cell(buf); /* Arg2: buffer address */ ci[5] = p1275_uint2cell(len); /* Arg3: buffer length */ ci[6] = (cell_t)-1; /* Res1: Prime result */ (void) p1275_cif_handler(&ci); return (p1275_cell2uint(ci[6])); /* Res1: actual length */ }
void * prom_set_callback(void *handler) { cell_t ci[5]; ci[0] = p1275_ptr2cell("set-callback"); /* Service name */ ci[1] = (cell_t)1; /* #argument cells */ ci[2] = (cell_t)1; /* #return cells */ ci[3] = p1275_ptr2cell(handler); /* Arg1: New handler */ ci[4] = (cell_t)-1; /* Res1: Prime result */ promif_preprom(); (void) p1275_cif_handler(&ci); promif_postprom(); return (p1275_cell2ptr(ci[4])); /* Res1: Old handler */ }
int prom_getproplen(pnode_t nodeid, caddr_t name) { cell_t ci[6]; ci[0] = p1275_ptr2cell("getproplen"); /* Service name */ ci[1] = (cell_t)2; /* #argument cells */ ci[2] = (cell_t)1; /* #return cells */ ci[3] = p1275_phandle2cell((phandle_t)nodeid); /* Arg1: package */ ci[4] = p1275_ptr2cell(name); /* Arg2: Property name */ ci[5] = (cell_t)-1; /* Res1: Prime result */ promif_preprom(); (void) p1275_cif_handler(&ci); promif_postprom(); return (p1275_cell2int(ci[5])); /* Res1: Property length */ }
int prom_asr_enable(char *keystr, int keystr_len) { int rv; cell_t ci[5]; ci[0] = p1275_ptr2cell("SUNW,asr-enable"); /* Service name */ ci[1] = (cell_t)2; /* #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 */ promif_preprom(); rv = p1275_cif_handler(&ci); promif_postprom(); return (rv); }
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_asr_export(caddr_t value) { int rv; cell_t ci[5]; ci[0] = p1275_ptr2cell("SUNW,asr-export"); /* Service name */ ci[1] = (cell_t)1; /* #argument cells */ ci[2] = (cell_t)1; /* #return cells */ ci[3] = p1275_ptr2cell(value); /* Arg1: buffer address */ ci[4] = -1; /* Res1: buf len */ promif_preprom(); rv = p1275_cif_handler(&ci); promif_postprom(); if (rv != 0) return (-1); return (p1275_cell2int(ci[4])); /* Res1: buf length */ }
caddr_t prom_nextprop(pnode_t nodeid, caddr_t previous, caddr_t next) { cell_t ci[7]; (void) prom_strcpy(next, ""); /* Prime result, in case call fails */ ci[0] = p1275_ptr2cell("nextprop"); /* Service name */ ci[1] = (cell_t)3; /* #argument cells */ ci[2] = (cell_t)0; /* #result cells */ ci[3] = p1275_phandle2cell((phandle_t)nodeid); /* Arg1: phandle */ ci[4] = p1275_ptr2cell(previous); /* Arg2: addr of prev name */ ci[5] = p1275_ptr2cell(next); /* Arg3: addr of 32 byte buf */ promif_preprom(); (void) p1275_cif_handler(&ci); promif_postprom(); return (next); }
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 */ }
char * prom_serengeti_set_console_input(char *new_value) { cell_t ci[5]; int rv; ci[0] = p1275_ptr2cell("SUNW,set-console-input"); ci[1] = (cell_t)1; /* #argument cells */ ci[2] = (cell_t)1; /* #return cells */ ci[3] = p1275_ptr2cell(new_value); promif_preprom(); rv = p1275_cif_handler(&ci); promif_postprom(); if (rv != 0) return (NULL); return (p1275_cell2ptr(ci[4])); }
/* * Free physical memory (no unmapping is done). * This routine is suitable for platforms with 2-cell physical addresses * with a single size cell. */ void prom_free_phys(size_t size, u_longlong_t physaddr) { cell_t ci[8]; ihandle_t imemory = prom_memory_ihandle(); if ((imemory == (ihandle_t)-1)) return; ci[0] = p1275_ptr2cell("call-method"); /* Service name */ ci[1] = (cell_t)5; /* #argument cells */ ci[2] = (cell_t)0; /* #return cells */ ci[3] = p1275_ptr2cell("release"); /* Arg1: Method name */ ci[4] = p1275_ihandle2cell(imemory); /* Arg2: memory ihandle */ ci[5] = p1275_size2cell(size); /* Arg3: SA1: size */ ci[6] = p1275_ull2cell_high(physaddr); /* Arg4: SA2: phys.hi */ ci[7] = p1275_ull2cell_low(physaddr); /* Arg5: SA3: phys.lo */ (void) p1275_cif_handler(&ci); }
/*ARGSUSED3*/ ssize_t prom_read(ihandle_t fd, caddr_t buf, size_t len, uint_t startblk, char devtype) { cell_t ci[7]; promif_owrap_t *ow; #ifdef PROM_32BIT_ADDRS caddr_t obuf = NULL; if ((uintptr_t)buf > (uint32_t)-1) { obuf = buf; buf = promplat_alloc(len); if (buf == NULL) return (-1); } #endif ow = promif_preout(); promif_preprom(); ci[0] = p1275_ptr2cell("read"); /* Service name */ ci[1] = (cell_t)3; /* #argument cells */ ci[2] = (cell_t)1; /* #result cells */ ci[3] = p1275_size2cell((uint_t)fd); /* Arg1: ihandle */ ci[4] = p1275_ptr2cell(buf); /* Arg2: buffer address */ ci[5] = p1275_uint2cell(len); /* Arg3: buffer length */ ci[6] = (cell_t)-1; /* Res1: Prime result */ (void) p1275_cif_handler(&ci); promif_postprom(); promif_postout(ow); #ifdef PROM_32BIT_ADDRS if (obuf != NULL) { promplat_bcopy(buf, obuf, len); promplat_free(buf, len); } #endif return (p1275_cell2size(ci[6])); /* Res1: actual 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); }
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 */ } }
/* * This is the generic client interface to "claim" memory. * These two routines belong in the common directory. */ caddr_t prom_malloc(caddr_t virt, size_t size, uint_t align) { cell_t ci[7]; int rv; ci[0] = p1275_ptr2cell("claim"); /* Service name */ ci[1] = (cell_t)3; /* #argument cells */ ci[2] = (cell_t)1; /* #result cells */ ci[3] = p1275_ptr2cell(virt); /* Arg1: virt */ ci[4] = p1275_uint2cell(size); /* Arg2: size */ ci[5] = p1275_uint2cell(align); /* Arg3: align */ promif_preprom(); rv = p1275_cif_handler(&ci); promif_postprom(); if (rv == 0) return ((caddr_t)p1275_cell2ptr(ci[6])); /* Res1: base */ return ((caddr_t)-1); }
/* * This interface allows the client to power off the machine. * There's no return from this service. */ void prom_power_off() { cell_t ci[3]; ci[0] = p1275_ptr2cell("SUNW,power-off"); /* Service name */ ci[1] = (cell_t) 0; /* #argument cells */ ci[2] = (cell_t) 0; /* #result cells */ promif_preprom(); (void) p1275_cif_handler(&ci); promif_postprom(); }