/* * 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); }
/* * 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); }
/* * 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); }
/* * 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); }
/* * 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); }
int prom_close(ihandle_t fd) { cell_t ci[4]; ci[0] = p1275_ptr2cell("close"); /* Service name */ ci[1] = (cell_t)1; /* #argument cells */ ci[2] = (cell_t)0; /* #result cells */ ci[3] = p1275_ihandle2cell(fd); /* Arg1: ihandle */ (void) p1275_cif_handler(&ci); return (0); }
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 */ }
int prom_seek(ihandle_t fd, u_longlong_t offset) { cell_t ci[7]; ci[0] = p1275_ptr2cell("seek"); /* 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_ull2cell_high(offset); /* Arg2: pos.hi */ ci[5] = p1275_ull2cell_low(offset); /* Arg3: pos.lo */ ci[6] = (cell_t)-1; /* Res1: Prime result */ (void) p1275_cif_handler(&ci); return (p1275_cell2int(ci[6])); /* Res1: actual */ }
/* * 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); }
/* * 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); }