예제 #1
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 */
	}
}
예제 #2
0
/*
 * 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);
}
예제 #3
0
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 */
	}
}
예제 #4
0
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. */
}
예제 #5
0
파일: prom_io.c 프로젝트: openbios/openboot
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 */
}
예제 #6
0
/*
 * 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);
}
예제 #7
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);
}
예제 #8
0
/*
 * 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);
}