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 routine that firmware calls when it is giving up control of the * input device. This routine, and the lower layer routines that it calls, * are responsible for restoring the controller state to the state it was * in before firmware took control. * * WARNING: This routine runs in debug mode. */ static void polled_take_input(cell_t *cif) { cons_polledio_t *polled_io; uint_t out_args; /* * Calculate the offset of the return arguments */ out_args = CIF_MIN_SIZE + p1275_cell2uint(cif[CIF_NUMBER_IN_ARGS]); /* * There is one argument being passed back to firmware. */ cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1); cif[out_args] = p1275_uint2cell(CIF_SUCCESS); /* * We check the pointer to see if there is an * input device that has been registered. */ polled_io = polled_input_device.polled_io; if (polled_io == NULL) { return; } /* * Call down to the lower layers to save the state. */ polled_io->cons_polledio_exit(polled_io->cons_polledio_argument); }
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 */ } }
u_int prom_gettime(void) { cell_t ci[4]; ci[0] = p1275_ptr2cell("milliseconds"); /* Service name */ ci[1] = (cell_t)0; /* #argument cells */ ci[2] = (cell_t)1; /* #return cells */ promif_preprom(); (void) p1275_cif_handler(&ci); promif_postprom(); return (p1275_cell2uint(ci[3])); /* Res0: time in ms. */ }
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 */ }
/* * 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); }
/* * This is the routine that the firmware calls when * it wants to write a character. * * WARNING: This routine runs in debug mode. */ static void polled_write(cell_t *cif) { cons_polledio_t *polled_io; uint_t in_args; uint_t out_args; uchar_t *buffer; uint_t buflen; /* * The number of arguments passed in by the firmware */ in_args = p1275_cell2uint(cif[CIF_NUMBER_IN_ARGS]); /* * Calculate the location of the first out arg. This location is * CIF_MIN_SIZE (name + no. in args + no. out args) plus the * in argument locations. */ out_args = CIF_MIN_SIZE + in_args; /* * The firmware should pass in a pointer to a buffer, and the * number of characters it expects or expects to write. * If 2 arguments are not passed in, then return an error. */ if (in_args != 2) { /* * Tell firmware how many arguments we are passing back. */ cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1); /* * Tell the firmware that we cannot give it any characters. */ cif[out_args] = p1275_uint2cell(CIF_FAILURE); return; } /* * Get the address of where to copy the characters into. */ buffer = (uchar_t *)(uintptr_t)p1275_cell2uint(cif[CIF_MIN_SIZE+0]); /* * Get the length of the buffer that we can copy characters into. */ buflen = p1275_cell2uint(cif[CIF_MIN_SIZE+1]); /* * Make sure there is enough room in the buffer to copy the * characters into. */ if (buflen == 0) { /* * Tell the OBP that we cannot give it any characters. */ cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1); /* * Tell the firmware that we cannot give it any characters. */ cif[out_args] = p1275_uint2cell(CIF_FAILURE); return; } /* * Tell the firmware how many arguments we are passing back. */ cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)2); /* * Initialize the cif to success */ cif[out_args+0] = p1275_uint2cell(CIF_SUCCESS); cif[out_args+1] = p1275_uint2cell(0); /* * We check the pointer to see if there is an * input device that has been registered. */ polled_io = polled_output_device.polled_io; if (polled_io == NULL) { /* * The cif is already initialized */ return; } polled_io_cons_write(buffer, (size_t)buflen); /* * Tell the firmware how many characters we are sending it. */ cif[out_args+0] = p1275_uint2cell((uint_t)CIF_SUCCESS); cif[out_args+1] = p1275_uint2cell((uint_t)buflen); }
/* * This is the routine that the firmware calls * when it wants to read a character. * We will call to the lower layers to see if there is any input data * available. * * WARNING: This routine runs in debug mode. */ static void polled_read(cell_t *cif) { uint_t actual; cons_polledio_t *polled_io; uint_t in_args; uint_t out_args; uchar_t *buffer; uint_t buflen; uchar_t key; /* * The number of arguments passed in by the firmware */ in_args = p1275_cell2uint(cif[CIF_NUMBER_IN_ARGS]); /* * Calculate the location of the first out arg. This location is * CIF_MIN_SIZE plus the in argument locations. */ out_args = CIF_MIN_SIZE + in_args; /* * The firmware should pass in a pointer to a buffer, and the * number of characters it expects or expects to write. * If 2 arguments are not passed in, then return an error. */ if (in_args != 2) { /* * Tell firmware how many arguments we are passing back. */ cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1); /* * Tell the firmware that we cannot give it any characters. */ cif[out_args] = p1275_uint2cell(CIF_FAILURE); return; } /* * Get the address of where to copy the characters into. */ buffer = (uchar_t *)(uintptr_t)p1275_cell2uint(cif[CIF_MIN_SIZE+0]); /* * Get the length of the buffer that we can copy characters into. */ buflen = p1275_cell2uint(cif[CIF_MIN_SIZE+1]); /* * Make sure there is enough room in the buffer to copy the * characters into. */ if (buflen == 0) { /* * Tell the OBP that we cannot give it any characters. */ cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1); /* * Tell the firmware that we cannot give it any characters. */ cif[out_args] = p1275_uint2cell(CIF_FAILURE); return; } /* * Pass back whether or not the operation was a success or * failure plus the actual number of bytes in the buffer. * Tell firmware how many arguments we are passing back. */ cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)2); /* * Initialize the cif to be "no characters" */ cif[out_args+0] = p1275_uint2cell(CIF_SUCCESS); cif[out_args+1] = p1275_uint2cell(CIF_NO_CHARACTERS); /* * We check to see if there is an * input device that has been registered. */ polled_io = polled_input_device.polled_io; if (polled_io == NULL || polled_io->cons_polledio_ischar == NULL) { /* * The cif structure is already set up to return * no characters. */ return; } actual = 0; /* * Obtain the characters */ while (polled_io->cons_polledio_ischar( polled_io->cons_polledio_argument) == B_TRUE) { /* * Make sure that we don't overrun the buffer. */ if (actual == buflen) { break; } /* * Call down to the device to copy the input data into the * buffer. */ key = polled_io->cons_polledio_getchar( polled_io->cons_polledio_argument); *(buffer + actual) = key; actual++; } /* * There is a special return code when there is no data. */ if (actual == 0) { /* * The cif structure is already set up to return * no characters. */ return; } /* * Tell firmware how many characters we are sending it. */ cif[out_args+0] = p1275_uint2cell((uint_t)CIF_SUCCESS); cif[out_args+1] = p1275_uint2cell((uint_t)actual); }