コード例 #1
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);
}
コード例 #2
0
ファイル: prom_starcat.c プロジェクト: apprisi/illumos-gate
/*
 * 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);
	}
}
コード例 #3
0
ファイル: prom_mem.c プロジェクト: openbios/openboot
/*
 * 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);
}
コード例 #4
0
ファイル: prom_path.c プロジェクト: openbios/openboot
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 */
}
コード例 #5
0
ファイル: prom_starcat.c プロジェクト: apprisi/illumos-gate
/*
 * Given the portid of the IOB to which the tunnel should be moved and the type
 * of move that should be performed, ask OBP to switch the IOSRAM tunnel from
 * its current host IOB to a new location.  If the move type is 0, OBP will
 * coordinate the change with SMS and will copy data from the current location
 * to the new location.  If the move type is 1, OBP will simply mark the new
 * location valid and start using it, without doing any data copying and without
 * communicating with SMS.  Return 0 on success, non-zero on failure.
 */
int
prom_starcat_switch_tunnel(uint_t portid, uint_t msgtype)
{
	static uint8_t	warned = 0;
	cell_t		ci[6];
	int		rv;

	/*
	 * Make sure we have the necessary support in OBP.
	 */
	if (prom_test(switch_tunnel_cmd) == 0) {
		ci[0] = p1275_ptr2cell(switch_tunnel_cmd); /* name */
	} else {
		if (!warned) {
			warned = 1;
			prom_printf(
			    "Warning: No prom support for switch-tunnel!\n");
		}
		return (-1);
	}

	/*
	 * Set up the arguments and call into OBP.
	 */
	ci[1] = (cell_t)2;				/* #argument cells */
	ci[2] = (cell_t)1;				/* #result cells */
	ci[3] = p1275_uint2cell(portid);
	ci[4] = p1275_uint2cell(msgtype);

	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
	 * failure and non-zero on success for this interface.
	 */
	if (rv != 0) {
		return (rv);
	} else if (p1275_cell2int(ci[5]) == 0)	{
		return (-1);
	} else {
		return (0);
	}
}
コード例 #6
0
ファイル: prom_alloc.c プロジェクト: andreiw/polaris
/*
 * 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);
}
コード例 #7
0
ファイル: prom_serengeti.c プロジェクト: andreiw/polaris
int
prom_serengeti_detach_board(uint_t node, uint_t board)
{
	cell_t ci[6];
	int rv;

	ci[0] = p1275_ptr2cell("SUNW,Serengeti,remove-board");	/* name */
	ci[1] = (cell_t)2;				/* #argument cells */
	ci[2] = (cell_t)1;				/* #result cells */
	ci[3] = p1275_uint2cell(board);
	ci[4] = p1275_uint2cell(node);

	promif_preprom();
	rv = p1275_cif_handler(&ci);
	promif_postprom();

	if (rv != 0)
		return (rv);
	if (p1275_cell2int(ci[5]) != 0)			/* Res1: Catch result */
		return (-1);

	return (0);
}
コード例 #8
0
ファイル: prom_alloc.c プロジェクト: andreiw/polaris
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();
}
コード例 #9
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 */
}
コード例 #10
0
ファイル: prom_io.c プロジェクト: apprisi/illumos-gate
int
prom_seek(int fd, unsigned long long 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_uint2cell((uint_t)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 */

	promif_preprom();
	(void) p1275_cif_handler(&ci);
	promif_postprom();

	return (p1275_cell2int(ci[6]));		/* Res1: actual */
}
コード例 #11
0
ファイル: prom_io.c プロジェクト: apprisi/illumos-gate
int
prom_close(int fd)
{
	cell_t ci[4];
	promif_owrap_t *ow;

	ci[0] = p1275_ptr2cell("close");	/* Service name */
	ci[1] = (cell_t)1;			/* #argument cells */
	ci[2] = (cell_t)0;			/* #result cells */
	ci[3] = p1275_uint2cell((uint_t)fd);	/* Arg1: ihandle */

	ow = promif_preout();
	promif_preprom();
	(void) p1275_cif_handler(&ci);
	promif_postprom();
	promif_postout(ow);

	return (0);
}
コード例 #12
0
ファイル: prom_io.c プロジェクト: apprisi/illumos-gate
/*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 */
}
コード例 #13
0
ファイル: prom_serengeti.c プロジェクト: andreiw/polaris
/*
 * 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);
}
コード例 #14
0
ファイル: prom_io.c プロジェクト: apprisi/illumos-gate
/*ARGSUSED3*/
ssize_t
prom_write(ihandle_t fd, caddr_t buf, size_t len, uint_t startblk, char devtype)
{
	cell_t ci[7];
	promif_owrap_t *ow;
	ssize_t rlen;

#ifdef PROM_32BIT_ADDRS
	caddr_t obuf = NULL;
	static char smallbuf[256];

	ASSERT(buf);
#endif

	/*
	 * If the callback address is set, attempt to redirect
	 * console output back into kernel terminal emulator.
	 */
	if (promif_redirect != NULL && fd == prom_stdout_ihandle()) {
		ow = promif_preout();
		rlen = promif_redirect(promif_redirect_arg, (uchar_t *)buf,
		    len);
		promif_postout(ow);
		return (rlen);
	}

#ifdef PROM_32BIT_ADDRS
	if ((uintptr_t)buf > (uint32_t)-1) {
		/*
		 * This is a hack for kernel message output.
		 * By avoiding calls to promplat_alloc (and
		 * using smallbuf instead) when memory is low
		 * we can print shortish kernel messages without
		 * deadlocking. smallbuf should be at least as
		 * large as the automatic buffer in
		 * prom_printf.c:_doprint()'s stack frame.
		 * promplat_alloc() can block on a mutex and so
		 * is called here before calling promif_preprom().
		 */
		if (len > sizeof (smallbuf)) {
			obuf = buf;
			buf = promplat_alloc(len);
			if (buf == NULL) {
				return (-1);
			}
			promplat_bcopy(obuf, buf, len);
		}
	}
#endif

	/*
	 * Normally we'd call promif_preprom() just before
	 * calling into the prom (to enforce single-threaded
	 * access) but here we need to call it before accessing
	 * smallbuf, since smallbuf is statically allocated and
	 * hence can only be accessed by one thread at a time.
	 */
	ow = promif_preout();
	promif_preprom();

#ifdef PROM_32BIT_ADDRS
	if ((uintptr_t)buf > (uint32_t)-1) {
		/*
		 * If buf is small enough, use smallbuf
		 * instead of promplat_alloc() (see above)
		 * smallbuf is static, so single thread
		 * access to it by using it only after
		 * promif_preprom()
		 */
		if (len <= sizeof (smallbuf)) {
			promplat_bcopy(buf, smallbuf, len);
			buf = smallbuf;
		}
	}
#endif

	ci[0] = p1275_ptr2cell("write");	/* Service name */
	ci[1] = (cell_t)3;			/* #argument cells */
	ci[2] = (cell_t)1;			/* #result cells */
	ci[3] = p1275_uint2cell((uint_t)fd);	/* Arg1: ihandle */
	ci[4] = p1275_ptr2cell(buf);		/* Arg2: buffer addr */
	ci[5] = p1275_size2cell(len);		/* Arg3: buffer len */
	ci[6] = (cell_t)-1;			/* Res1: Prime result */

	(void) p1275_cif_handler(&ci);
	rlen = p1275_cell2size(ci[6]);		/* Res1: actual len */

	promif_postprom();
	promif_postout(ow);

#ifdef PROM_32BIT_ADDRS
	if (obuf != NULL)
		promplat_free(buf, len);
#endif

	return (rlen);
}
コード例 #15
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);
}
コード例 #16
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);
}