xref: /titanic_51/usr/src/uts/sparc/os/polled_io.c (revision 827029ebaa965d6bf71a101c482dd796bfc673b8)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5fea9cb91Slq150181  * Common Development and Distribution License (the "License").
6fea9cb91Slq150181  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*827029ebSJames Marks - Sun Microsystems  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * This code sets up the callbacks(vx_handlers) so that the firmware may call
287c478bd9Sstevel@tonic-gate  * into the kernel for console input and/or output while in the debugger.
297c478bd9Sstevel@tonic-gate  * The callbacks that execute in debug mode must be careful to not
307c478bd9Sstevel@tonic-gate  * allocate memory, access mutexes, etc. because most kernel services are
317c478bd9Sstevel@tonic-gate  * not available during this mode.
327c478bd9Sstevel@tonic-gate  *
337c478bd9Sstevel@tonic-gate  * This code, and the underlying code that supports the polled input, is very
347c478bd9Sstevel@tonic-gate  * hard to debug.  In order to get the code to execute, polled input must
357c478bd9Sstevel@tonic-gate  * provide input to the debugger.  If anything goes wrong with the code, then
367c478bd9Sstevel@tonic-gate  * it is hard to debug the debugger.  If there are any problems to debug,
377c478bd9Sstevel@tonic-gate  * the following is useful:
387c478bd9Sstevel@tonic-gate  *
397c478bd9Sstevel@tonic-gate  * set the polled_debug variable in /etc/system
407c478bd9Sstevel@tonic-gate  *	set polled_debug=1
417c478bd9Sstevel@tonic-gate  *
427c478bd9Sstevel@tonic-gate  * This variable will register the callbacks but will not throw the switch
437c478bd9Sstevel@tonic-gate  * in the firmware.  The callbacks can be executed by hand from the firmware.
447c478bd9Sstevel@tonic-gate  * Boot the system and drop down to the firmware.
457c478bd9Sstevel@tonic-gate  *
467c478bd9Sstevel@tonic-gate  *	ok " /os-io" select-dev
477c478bd9Sstevel@tonic-gate  *
487c478bd9Sstevel@tonic-gate  * The following will cause the polled_give_input to execute:
497c478bd9Sstevel@tonic-gate  *	ok take
507c478bd9Sstevel@tonic-gate  *
517c478bd9Sstevel@tonic-gate  * The following will cause the polled_take_input to execute:
527c478bd9Sstevel@tonic-gate  *	ok give
537c478bd9Sstevel@tonic-gate  *
547c478bd9Sstevel@tonic-gate  * The following will cause polled_read to execute:
557c478bd9Sstevel@tonic-gate  *	ok read
567c478bd9Sstevel@tonic-gate  */
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
597c478bd9Sstevel@tonic-gate #include <v9/sys/prom_isa.h>
607c478bd9Sstevel@tonic-gate #include <sys/devops.h>
617c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
627c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
637c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
647c478bd9Sstevel@tonic-gate #include <sys/promif.h>
657c478bd9Sstevel@tonic-gate #include <sys/note.h>
667c478bd9Sstevel@tonic-gate #include <sys/consdev.h>
677c478bd9Sstevel@tonic-gate #include <sys/polled_io.h>
687c478bd9Sstevel@tonic-gate #include <sys/kdi.h>
69*827029ebSJames Marks - Sun Microsystems #ifdef sun4v
70*827029ebSJames Marks - Sun Microsystems #include <sys/ldoms.h>
71*827029ebSJames Marks - Sun Microsystems #endif
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate /*
747c478bd9Sstevel@tonic-gate  * Internal Functions
757c478bd9Sstevel@tonic-gate  */
767c478bd9Sstevel@tonic-gate static void	polled_give_input(cell_t *cif);
777c478bd9Sstevel@tonic-gate static void	polled_read(cell_t *cif);
787c478bd9Sstevel@tonic-gate static void	polled_take_input(cell_t *cif);
79fea9cb91Slq150181 
807c478bd9Sstevel@tonic-gate static void	polled_write(cell_t *cif);
817c478bd9Sstevel@tonic-gate static void	polled_io_register(cons_polledio_t *,
827c478bd9Sstevel@tonic-gate 			polled_io_console_type_t, int);
837c478bd9Sstevel@tonic-gate static int	polled_io_take_console(polled_io_console_type_t, int);
847c478bd9Sstevel@tonic-gate static int	polled_io_release_console(polled_io_console_type_t, int);
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate /*
877c478bd9Sstevel@tonic-gate  * State information regarding the input/output device
887c478bd9Sstevel@tonic-gate  */
897c478bd9Sstevel@tonic-gate static polled_device_t	polled_input_device;
907c478bd9Sstevel@tonic-gate static polled_device_t	polled_output_device;
917c478bd9Sstevel@tonic-gate static int polled_vx_handlers_init = 0;
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate extern void	add_vx_handler(char *name, int flag, void (*func)(cell_t *));
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate /*
967c478bd9Sstevel@tonic-gate  * This is a useful flag for debugging the entry points.   This flag
977c478bd9Sstevel@tonic-gate  * allows us to exercise the entry points from the firmware without
987c478bd9Sstevel@tonic-gate  * switching the firmware's notion of the input device.
997c478bd9Sstevel@tonic-gate  */
1007c478bd9Sstevel@tonic-gate int	polled_debug = 0;
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate /*
1037c478bd9Sstevel@tonic-gate  * This routine is called to initialize polled I/O.  We insert our entry
1047c478bd9Sstevel@tonic-gate  * points so that the firmware will call into this code
1057c478bd9Sstevel@tonic-gate  * when the switch is thrown in polled_io_take_console().
1067c478bd9Sstevel@tonic-gate  */
1077c478bd9Sstevel@tonic-gate void
1087c478bd9Sstevel@tonic-gate polled_io_init(void)
1097c478bd9Sstevel@tonic-gate {
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate 	/*
1127c478bd9Sstevel@tonic-gate 	 * Only do the initialization once
1137c478bd9Sstevel@tonic-gate 	 */
1147c478bd9Sstevel@tonic-gate 	if (polled_vx_handlers_init != 0)
1157c478bd9Sstevel@tonic-gate 		return;
116*827029ebSJames Marks - Sun Microsystems #ifdef sun4v
117*827029ebSJames Marks - Sun Microsystems 	if (!domaining_enabled()) {
118*827029ebSJames Marks - Sun Microsystems #endif
1197c478bd9Sstevel@tonic-gate 	/*
1207c478bd9Sstevel@tonic-gate 	 * Add the vx_handlers for the different functions that
1217c478bd9Sstevel@tonic-gate 	 * need to be accessed from firmware.
1227c478bd9Sstevel@tonic-gate 	 */
1237c478bd9Sstevel@tonic-gate 	add_vx_handler("enter-input", 1, polled_give_input);
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	add_vx_handler("read", 1, polled_read);
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	add_vx_handler("exit-input", 1, polled_take_input);
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 	add_vx_handler("write", 1, polled_write);
130*827029ebSJames Marks - Sun Microsystems #ifdef sun4v
131*827029ebSJames Marks - Sun Microsystems 	}
132*827029ebSJames Marks - Sun Microsystems #endif
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	/*
1357c478bd9Sstevel@tonic-gate 	 * Initialize lock to protect multiple thread access to the
1367c478bd9Sstevel@tonic-gate 	 * polled_input_device structure.  This does not protect
1377c478bd9Sstevel@tonic-gate 	 * us from access in debug mode.
1387c478bd9Sstevel@tonic-gate 	 */
1397c478bd9Sstevel@tonic-gate 	mutex_init(&polled_input_device.polled_device_lock,
1407c478bd9Sstevel@tonic-gate 	    NULL, MUTEX_DRIVER, NULL);
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 	/*
1437c478bd9Sstevel@tonic-gate 	 * Initialize lock to protect multiple thread access to the
1447c478bd9Sstevel@tonic-gate 	 * polled_output_device structure.  This does not protect
1457c478bd9Sstevel@tonic-gate 	 * us from access in debug mode.
1467c478bd9Sstevel@tonic-gate 	 */
1477c478bd9Sstevel@tonic-gate 	mutex_init(&polled_output_device.polled_device_lock,
1487c478bd9Sstevel@tonic-gate 	    NULL, MUTEX_DRIVER, NULL);
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 	polled_vx_handlers_init = 1;
1517c478bd9Sstevel@tonic-gate }
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate /*
1547c478bd9Sstevel@tonic-gate  * Register a device for input or output.  The polled_io structure
1557c478bd9Sstevel@tonic-gate  * will be filled in with the callbacks that are appropriate for
1567c478bd9Sstevel@tonic-gate  * that device.
1577c478bd9Sstevel@tonic-gate  */
1587c478bd9Sstevel@tonic-gate int
1597c478bd9Sstevel@tonic-gate polled_io_register_callbacks(
1607c478bd9Sstevel@tonic-gate cons_polledio_t			*polled_io,
1617c478bd9Sstevel@tonic-gate int				flags
1627c478bd9Sstevel@tonic-gate )
1637c478bd9Sstevel@tonic-gate {
1647c478bd9Sstevel@tonic-gate 	/*
1657c478bd9Sstevel@tonic-gate 	 * If the input structure entries aren't filled in, then register this
1667c478bd9Sstevel@tonic-gate 	 * structure as an input device.
1677c478bd9Sstevel@tonic-gate 	 */
1687c478bd9Sstevel@tonic-gate 	if ((polled_io->cons_polledio_getchar != NULL) &&
1697c478bd9Sstevel@tonic-gate 	    (polled_io->cons_polledio_ischar != NULL)) {
1707c478bd9Sstevel@tonic-gate 
171*827029ebSJames Marks - Sun Microsystems 		polled_io_register(polled_io, POLLED_IO_CONSOLE_INPUT, flags);
1727c478bd9Sstevel@tonic-gate 	}
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate 	/*
1757c478bd9Sstevel@tonic-gate 	 * If the output structure entries aren't filled in, then register this
1767c478bd9Sstevel@tonic-gate 	 * structure as an output device.
1777c478bd9Sstevel@tonic-gate 	 */
1787c478bd9Sstevel@tonic-gate 	if (polled_io->cons_polledio_putchar != NULL) {
1797c478bd9Sstevel@tonic-gate 
180*827029ebSJames Marks - Sun Microsystems 		polled_io_register(polled_io, POLLED_IO_CONSOLE_OUTPUT, flags);
1817c478bd9Sstevel@tonic-gate 	}
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate 	cons_polledio = polled_io;
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
1867c478bd9Sstevel@tonic-gate }
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate /*
189fea9cb91Slq150181  * Sends string through the polled output interfaces when the
190fea9cb91Slq150181  * system is panicing.
1917c478bd9Sstevel@tonic-gate  */
1927c478bd9Sstevel@tonic-gate void
193fea9cb91Slq150181 polled_io_cons_write(uchar_t *text, size_t len)
1947c478bd9Sstevel@tonic-gate {
195fea9cb91Slq150181 	cons_polledio_t *pio = polled_output_device.polled_io;
196fea9cb91Slq150181 	int i;
1977c478bd9Sstevel@tonic-gate 
198fea9cb91Slq150181 	for (i = 0; i < len; i++)
199fea9cb91Slq150181 		pio->cons_polledio_putchar(
200fea9cb91Slq150181 		    pio->cons_polledio_argument, text[i]);
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate /*
2047c478bd9Sstevel@tonic-gate  * Generic internal routine for registering a polled input or output device.
2057c478bd9Sstevel@tonic-gate  */
2067c478bd9Sstevel@tonic-gate /* ARGSUSED */
2077c478bd9Sstevel@tonic-gate static void
2087c478bd9Sstevel@tonic-gate polled_io_register(
2097c478bd9Sstevel@tonic-gate cons_polledio_t			*polled_io,
2107c478bd9Sstevel@tonic-gate polled_io_console_type_t	type,
2117c478bd9Sstevel@tonic-gate int				flags
2127c478bd9Sstevel@tonic-gate )
2137c478bd9Sstevel@tonic-gate {
2147c478bd9Sstevel@tonic-gate 	switch (type) {
2157c478bd9Sstevel@tonic-gate 	case POLLED_IO_CONSOLE_INPUT:
2167c478bd9Sstevel@tonic-gate 		/*
2177c478bd9Sstevel@tonic-gate 		 * Grab the device lock, because we are going to access
2187c478bd9Sstevel@tonic-gate 		 * protected structure entries.  We do this before the
2197c478bd9Sstevel@tonic-gate 		 * POLLED_IO_CONSOLE_OPEN_INPUT so that we serialize
2207c478bd9Sstevel@tonic-gate 		 * registration.
2217c478bd9Sstevel@tonic-gate 		 */
2227c478bd9Sstevel@tonic-gate 		mutex_enter(&polled_input_device.polled_device_lock);
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 		/*
2257c478bd9Sstevel@tonic-gate 		 * Save the polled_io pointers so that we can access
2267c478bd9Sstevel@tonic-gate 		 * them later.
2277c478bd9Sstevel@tonic-gate 		 */
2287c478bd9Sstevel@tonic-gate 		polled_input_device.polled_io = polled_io;
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 		mutex_exit(&polled_input_device.polled_device_lock);
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 		if (!polled_debug) {
2347c478bd9Sstevel@tonic-gate 			/*
2357c478bd9Sstevel@tonic-gate 			 * Tell the generic console framework to
2367c478bd9Sstevel@tonic-gate 			 * repoint firmware's stdin to this keyboard device.
2377c478bd9Sstevel@tonic-gate 			 */
2387c478bd9Sstevel@tonic-gate 			(void) polled_io_take_console(type, 0);
2397c478bd9Sstevel@tonic-gate 		}
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 		break;
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	case POLLED_IO_CONSOLE_OUTPUT:
2447c478bd9Sstevel@tonic-gate 		/*
2457c478bd9Sstevel@tonic-gate 		 * Grab the device lock, because we are going to access
2467c478bd9Sstevel@tonic-gate 		 * protected structure entries. We do this before the
2477c478bd9Sstevel@tonic-gate 		 * POLLED_IO_CONSOLE_OPEN_OUTPUT so that we serialize
2487c478bd9Sstevel@tonic-gate 		 * registration.
2497c478bd9Sstevel@tonic-gate 		 */
2507c478bd9Sstevel@tonic-gate 		mutex_enter(&polled_output_device.polled_device_lock);
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 		/*
2537c478bd9Sstevel@tonic-gate 		 * Save the polled_io pointers so that we can access
2547c478bd9Sstevel@tonic-gate 		 * them later.
2557c478bd9Sstevel@tonic-gate 		 */
256fea9cb91Slq150181 		polled_output_device.polled_io = polled_io;
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 		mutex_exit(&polled_output_device.polled_device_lock);
2597c478bd9Sstevel@tonic-gate 
260fea9cb91Slq150181 		if (!polled_debug) {
261fea9cb91Slq150181 			/*
262fea9cb91Slq150181 			 * Tell the generic console framework to
263fea9cb91Slq150181 			 * repoint firmware's stdout to the framebuffer.
264fea9cb91Slq150181 			 */
265fea9cb91Slq150181 			(void) polled_io_take_console(type, 0);
2667c478bd9Sstevel@tonic-gate 		}
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 		break;
2697c478bd9Sstevel@tonic-gate 	}
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate /*
2737c478bd9Sstevel@tonic-gate  * This is the routine that is called to throw the switch from the
2747c478bd9Sstevel@tonic-gate  * firmware's ownership of stdout/stdin to the kernel.
2757c478bd9Sstevel@tonic-gate  */
2767c478bd9Sstevel@tonic-gate /* ARGSUSED */
2777c478bd9Sstevel@tonic-gate static int
2787c478bd9Sstevel@tonic-gate polled_io_take_console(
2797c478bd9Sstevel@tonic-gate polled_io_console_type_t	type,
2807c478bd9Sstevel@tonic-gate int				flags
2817c478bd9Sstevel@tonic-gate )
2827c478bd9Sstevel@tonic-gate {
2837c478bd9Sstevel@tonic-gate 
284*827029ebSJames Marks - Sun Microsystems #ifdef sun4v
285*827029ebSJames Marks - Sun Microsystems 	if (domaining_enabled())
286*827029ebSJames Marks - Sun Microsystems 		return (DDI_SUCCESS);
287*827029ebSJames Marks - Sun Microsystems #endif
288*827029ebSJames Marks - Sun Microsystems 
2897c478bd9Sstevel@tonic-gate 	switch (type) {
2907c478bd9Sstevel@tonic-gate 	case POLLED_IO_CONSOLE_INPUT:
2917c478bd9Sstevel@tonic-gate 		/*
2927c478bd9Sstevel@tonic-gate 		 * Call into firmware to switch to the kernel I/O handling.
2937c478bd9Sstevel@tonic-gate 		 * We will save the old value of stdin so that we can
2947c478bd9Sstevel@tonic-gate 		 * restore it if the device is released.
2957c478bd9Sstevel@tonic-gate 		 */
2967c478bd9Sstevel@tonic-gate #ifdef DEBUG_OBP
2977c478bd9Sstevel@tonic-gate 		/*
2987c478bd9Sstevel@tonic-gate 		 * This code is useful to trace through
2997c478bd9Sstevel@tonic-gate 		 * what the prom is doing
3007c478bd9Sstevel@tonic-gate 		 */
3017c478bd9Sstevel@tonic-gate 		prom_interpret(
3027c478bd9Sstevel@tonic-gate 		    "stdin @ swap ! trace-on \" /os-io\" input trace-off",
3037c478bd9Sstevel@tonic-gate 		    (uintptr_t)&polled_input_device.polled_old_handle,
3047c478bd9Sstevel@tonic-gate 		    0, 0, 0, 0);
3057c478bd9Sstevel@tonic-gate #endif
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 		prom_interpret(
3087c478bd9Sstevel@tonic-gate 		    "stdin @ swap ! \" /os-io\" open-dev stdin !",
3097c478bd9Sstevel@tonic-gate 		    (uintptr_t)&polled_input_device.polled_old_handle,
3107c478bd9Sstevel@tonic-gate 		    0, 0, 0, 0);
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 		break;
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	case POLLED_IO_CONSOLE_OUTPUT:
3157c478bd9Sstevel@tonic-gate 		/*
3167c478bd9Sstevel@tonic-gate 		 * Call into firmware to switch to the kernel I/O handling.
3177c478bd9Sstevel@tonic-gate 		 * We will save the old value of stdout so that we can
3187c478bd9Sstevel@tonic-gate 		 * restore it if the device is released.
3197c478bd9Sstevel@tonic-gate 		 */
320*827029ebSJames Marks - Sun Microsystems 		prom_interpret("stdout @ swap ! \" /os-io\" open-dev stdout !",
3217c478bd9Sstevel@tonic-gate 		    (uintptr_t)&polled_output_device.polled_old_handle,
3227c478bd9Sstevel@tonic-gate 		    0, 0, 0, 0);
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 		break;
3257c478bd9Sstevel@tonic-gate 	}
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
3287c478bd9Sstevel@tonic-gate }
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate /*
3317c478bd9Sstevel@tonic-gate  * This is the routine that the firmware calls to save any state information
3327c478bd9Sstevel@tonic-gate  * before using the input device.  This routine, and all of the
3337c478bd9Sstevel@tonic-gate  * routines that it calls, are responsible for saving any state
3347c478bd9Sstevel@tonic-gate  * information so that it can be restored when debug mode is over.
3357c478bd9Sstevel@tonic-gate  *
3367c478bd9Sstevel@tonic-gate  * WARNING: This routine runs in debug mode.
3377c478bd9Sstevel@tonic-gate  */
3387c478bd9Sstevel@tonic-gate static void
3397c478bd9Sstevel@tonic-gate polled_give_input(cell_t *cif)
3407c478bd9Sstevel@tonic-gate {
3417c478bd9Sstevel@tonic-gate 	cons_polledio_t		*polled_io;
3427c478bd9Sstevel@tonic-gate 	uint_t			out_args;
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 	/*
3457c478bd9Sstevel@tonic-gate 	 * Calculate the offset of the return arguments
3467c478bd9Sstevel@tonic-gate 	 */
347*827029ebSJames Marks - Sun Microsystems 	out_args = CIF_MIN_SIZE + p1275_cell2uint(cif[CIF_NUMBER_IN_ARGS]);
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 	/*
3507c478bd9Sstevel@tonic-gate 	 * There is one argument being passed back to firmware.
3517c478bd9Sstevel@tonic-gate 	 */
3527c478bd9Sstevel@tonic-gate 	cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
3537c478bd9Sstevel@tonic-gate 	cif[out_args] = p1275_uint2cell(CIF_SUCCESS);
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 	/*
3567c478bd9Sstevel@tonic-gate 	 * We check to see if there is an
3577c478bd9Sstevel@tonic-gate 	 * input device that has been registered.
3587c478bd9Sstevel@tonic-gate 	 */
3597c478bd9Sstevel@tonic-gate 	polled_io = polled_input_device.polled_io;
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	if (polled_io == NULL) {
3627c478bd9Sstevel@tonic-gate 		return;
3637c478bd9Sstevel@tonic-gate 	}
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 	/*
3667c478bd9Sstevel@tonic-gate 	 * Call down to the lower layers to save the state.
3677c478bd9Sstevel@tonic-gate 	 */
368*827029ebSJames Marks - Sun Microsystems 	polled_io->cons_polledio_enter(polled_io->cons_polledio_argument);
3697c478bd9Sstevel@tonic-gate }
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate /*
3727c478bd9Sstevel@tonic-gate  * This is the routine that the firmware calls
3737c478bd9Sstevel@tonic-gate  * when it wants to read a character.
3747c478bd9Sstevel@tonic-gate  * We will call to the lower layers to see if there is any input data
3757c478bd9Sstevel@tonic-gate  * available.
3767c478bd9Sstevel@tonic-gate  *
3777c478bd9Sstevel@tonic-gate  * WARNING: This routine runs in debug mode.
3787c478bd9Sstevel@tonic-gate  */
3797c478bd9Sstevel@tonic-gate static void
3807c478bd9Sstevel@tonic-gate polled_read(cell_t *cif)
3817c478bd9Sstevel@tonic-gate {
3827c478bd9Sstevel@tonic-gate 	uint_t				actual;
3837c478bd9Sstevel@tonic-gate 	cons_polledio_t			*polled_io;
3847c478bd9Sstevel@tonic-gate 	uint_t				in_args;
3857c478bd9Sstevel@tonic-gate 	uint_t				out_args;
3867c478bd9Sstevel@tonic-gate 	uchar_t				*buffer;
3877c478bd9Sstevel@tonic-gate 	uint_t				buflen;
3887c478bd9Sstevel@tonic-gate 	uchar_t				key;
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 	/*
3917c478bd9Sstevel@tonic-gate 	 * The number of arguments passed in by the firmware
3927c478bd9Sstevel@tonic-gate 	 */
3937c478bd9Sstevel@tonic-gate 	in_args = p1275_cell2uint(cif[CIF_NUMBER_IN_ARGS]);
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate 	/*
3967c478bd9Sstevel@tonic-gate 	 * Calculate the location of the first out arg.  This location is
3977c478bd9Sstevel@tonic-gate 	 * CIF_MIN_SIZE plus the in argument locations.
3987c478bd9Sstevel@tonic-gate 	 */
3997c478bd9Sstevel@tonic-gate 	out_args = CIF_MIN_SIZE + in_args;
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	/*
4027c478bd9Sstevel@tonic-gate 	 * The firmware should pass in a pointer to a buffer, and the
4037c478bd9Sstevel@tonic-gate 	 * number of characters it expects or expects to write.
4047c478bd9Sstevel@tonic-gate 	 * If 2 arguments are not passed in, then return an error.
4057c478bd9Sstevel@tonic-gate 	 */
4067c478bd9Sstevel@tonic-gate 	if (in_args != 2) {
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate 		/*
4097c478bd9Sstevel@tonic-gate 		 * Tell firmware how many arguments we are passing back.
4107c478bd9Sstevel@tonic-gate 		 */
4117c478bd9Sstevel@tonic-gate 		cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 		/*
4147c478bd9Sstevel@tonic-gate 		 * Tell the firmware that we cannot give it any characters.
4157c478bd9Sstevel@tonic-gate 		 */
4167c478bd9Sstevel@tonic-gate 		cif[out_args] = p1275_uint2cell(CIF_FAILURE);
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 		return;
4197c478bd9Sstevel@tonic-gate 	}
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 	/*
4227c478bd9Sstevel@tonic-gate 	 * Get the address of where to copy the characters into.
4237c478bd9Sstevel@tonic-gate 	 */
4241a70ae91Smathue 	buffer = (uchar_t *)(uintptr_t)p1275_cell2uint(cif[CIF_MIN_SIZE+0]);
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 	/*
4277c478bd9Sstevel@tonic-gate 	 * Get the length of the buffer that we can copy characters into.
4287c478bd9Sstevel@tonic-gate 	 */
4297c478bd9Sstevel@tonic-gate 	buflen = p1275_cell2uint(cif[CIF_MIN_SIZE+1]);
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 	/*
4327c478bd9Sstevel@tonic-gate 	 * Make sure there is enough room in the buffer to copy the
4337c478bd9Sstevel@tonic-gate 	 * characters into.
4347c478bd9Sstevel@tonic-gate 	 */
4357c478bd9Sstevel@tonic-gate 	if (buflen == 0) {
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 		/*
4387c478bd9Sstevel@tonic-gate 		 * Tell the OBP that we cannot give it any characters.
4397c478bd9Sstevel@tonic-gate 		 */
4407c478bd9Sstevel@tonic-gate 		cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 		/*
4437c478bd9Sstevel@tonic-gate 		 * Tell the firmware that we cannot give it any characters.
4447c478bd9Sstevel@tonic-gate 		 */
4457c478bd9Sstevel@tonic-gate 		cif[out_args] = p1275_uint2cell(CIF_FAILURE);
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 		return;
4487c478bd9Sstevel@tonic-gate 	}
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate 	/*
4517c478bd9Sstevel@tonic-gate 	 * Pass back whether or not the operation was a success or
4527c478bd9Sstevel@tonic-gate 	 * failure plus the actual number of bytes in the buffer.
4537c478bd9Sstevel@tonic-gate 	 * Tell firmware how many arguments we are passing back.
4547c478bd9Sstevel@tonic-gate 	 */
4557c478bd9Sstevel@tonic-gate 	cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)2);
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 	/*
4587c478bd9Sstevel@tonic-gate 	 * Initialize the cif to be "no characters"
4597c478bd9Sstevel@tonic-gate 	 */
4607c478bd9Sstevel@tonic-gate 	cif[out_args+0] = p1275_uint2cell(CIF_SUCCESS);
4617c478bd9Sstevel@tonic-gate 	cif[out_args+1] = p1275_uint2cell(CIF_NO_CHARACTERS);
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 	/*
4647c478bd9Sstevel@tonic-gate 	 * We check to see if there is an
4657c478bd9Sstevel@tonic-gate 	 * input device that has been registered.
4667c478bd9Sstevel@tonic-gate 	 */
4677c478bd9Sstevel@tonic-gate 	polled_io = polled_input_device.polled_io;
4687c478bd9Sstevel@tonic-gate 
469fea9cb91Slq150181 	if (polled_io == NULL ||
470fea9cb91Slq150181 	    polled_io->cons_polledio_ischar == NULL) {
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate 		/*
4737c478bd9Sstevel@tonic-gate 		 * The cif structure is already set up to return
4747c478bd9Sstevel@tonic-gate 		 * no characters.
4757c478bd9Sstevel@tonic-gate 		 */
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 		return;
4787c478bd9Sstevel@tonic-gate 	}
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 	actual = 0;
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate 	/*
4837c478bd9Sstevel@tonic-gate 	 * Obtain the characters
4847c478bd9Sstevel@tonic-gate 	 */
4857c478bd9Sstevel@tonic-gate 	while (polled_io->cons_polledio_ischar(
4867c478bd9Sstevel@tonic-gate 	    polled_io->cons_polledio_argument) == B_TRUE) {
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 		/*
4897c478bd9Sstevel@tonic-gate 		 * Make sure that we don't overrun the buffer.
4907c478bd9Sstevel@tonic-gate 		 */
4917c478bd9Sstevel@tonic-gate 		if (actual == buflen) {
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate 			break;
4947c478bd9Sstevel@tonic-gate 		}
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 		/*
4977c478bd9Sstevel@tonic-gate 		 * Call down to the device to copy the input data into the
4987c478bd9Sstevel@tonic-gate 		 * buffer.
4997c478bd9Sstevel@tonic-gate 		 */
5007c478bd9Sstevel@tonic-gate 		key = polled_io->cons_polledio_getchar(
5017c478bd9Sstevel@tonic-gate 		    polled_io->cons_polledio_argument);
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate 		*(buffer + actual) = key;
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 		actual++;
5067c478bd9Sstevel@tonic-gate 	}
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate 	/*
5097c478bd9Sstevel@tonic-gate 	 * There is a special return code when there is no data.
5107c478bd9Sstevel@tonic-gate 	 */
5117c478bd9Sstevel@tonic-gate 	if (actual == 0) {
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate 		/*
5147c478bd9Sstevel@tonic-gate 		 * The cif structure is already set up to return
5157c478bd9Sstevel@tonic-gate 		 * no characters.
5167c478bd9Sstevel@tonic-gate 		 */
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 		return;
5197c478bd9Sstevel@tonic-gate 	}
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 	/*
5227c478bd9Sstevel@tonic-gate 	 * Tell firmware how many characters we are sending it.
5237c478bd9Sstevel@tonic-gate 	 */
5247c478bd9Sstevel@tonic-gate 	cif[out_args+0] = p1275_uint2cell((uint_t)CIF_SUCCESS);
5257c478bd9Sstevel@tonic-gate 	cif[out_args+1] = p1275_uint2cell((uint_t)actual);
5267c478bd9Sstevel@tonic-gate }
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate /*
5297c478bd9Sstevel@tonic-gate  * This is the routine that firmware calls when it is giving up control of the
5307c478bd9Sstevel@tonic-gate  * input device.  This routine, and the lower layer routines that it calls,
5317c478bd9Sstevel@tonic-gate  * are responsible for restoring the controller state to the state it was
5327c478bd9Sstevel@tonic-gate  * in before firmware took control.
5337c478bd9Sstevel@tonic-gate  *
5347c478bd9Sstevel@tonic-gate  * WARNING: This routine runs in debug mode.
5357c478bd9Sstevel@tonic-gate  */
5367c478bd9Sstevel@tonic-gate static void
5377c478bd9Sstevel@tonic-gate polled_take_input(cell_t *cif)
5387c478bd9Sstevel@tonic-gate {
5397c478bd9Sstevel@tonic-gate 	cons_polledio_t		*polled_io;
5407c478bd9Sstevel@tonic-gate 	uint_t			out_args;
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate 	/*
5437c478bd9Sstevel@tonic-gate 	 * Calculate the offset of the return arguments
5447c478bd9Sstevel@tonic-gate 	 */
545*827029ebSJames Marks - Sun Microsystems 	out_args = CIF_MIN_SIZE + p1275_cell2uint(cif[CIF_NUMBER_IN_ARGS]);
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 	/*
5487c478bd9Sstevel@tonic-gate 	 * There is one argument being passed back to firmware.
5497c478bd9Sstevel@tonic-gate 	 */
5507c478bd9Sstevel@tonic-gate 	cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
5517c478bd9Sstevel@tonic-gate 	cif[out_args] = p1275_uint2cell(CIF_SUCCESS);
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	/*
5547c478bd9Sstevel@tonic-gate 	 * We check the pointer to see if there is an
5557c478bd9Sstevel@tonic-gate 	 * input device that has been registered.
5567c478bd9Sstevel@tonic-gate 	 */
5577c478bd9Sstevel@tonic-gate 	polled_io = polled_input_device.polled_io;
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate 	if (polled_io == NULL) {
5607c478bd9Sstevel@tonic-gate 		return;
5617c478bd9Sstevel@tonic-gate 	}
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 	/*
5647c478bd9Sstevel@tonic-gate 	 * Call down to the lower layers to save the state.
5657c478bd9Sstevel@tonic-gate 	 */
566*827029ebSJames Marks - Sun Microsystems 	polled_io->cons_polledio_exit(polled_io->cons_polledio_argument);
5677c478bd9Sstevel@tonic-gate }
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate /*
5707c478bd9Sstevel@tonic-gate  * This is the routine that the firmware calls when
5717c478bd9Sstevel@tonic-gate  * it wants to write a character.
5727c478bd9Sstevel@tonic-gate  *
5737c478bd9Sstevel@tonic-gate  * WARNING: This routine runs in debug mode.
5747c478bd9Sstevel@tonic-gate  */
5757c478bd9Sstevel@tonic-gate static void
5767c478bd9Sstevel@tonic-gate polled_write(cell_t *cif)
5777c478bd9Sstevel@tonic-gate {
5787c478bd9Sstevel@tonic-gate 	cons_polledio_t			*polled_io;
5797c478bd9Sstevel@tonic-gate 	uint_t				in_args;
5807c478bd9Sstevel@tonic-gate 	uint_t				out_args;
5817c478bd9Sstevel@tonic-gate 	uchar_t				*buffer;
5827c478bd9Sstevel@tonic-gate 	uint_t				buflen;
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 	/*
5857c478bd9Sstevel@tonic-gate 	 * The number of arguments passed in by the firmware
5867c478bd9Sstevel@tonic-gate 	 */
5877c478bd9Sstevel@tonic-gate 	in_args = p1275_cell2uint(cif[CIF_NUMBER_IN_ARGS]);
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate 	/*
5907c478bd9Sstevel@tonic-gate 	 * Calculate the location of the first out arg.  This location is
5917c478bd9Sstevel@tonic-gate 	 * CIF_MIN_SIZE (name + no. in args + no. out args) plus the
5927c478bd9Sstevel@tonic-gate 	 * in argument locations.
5937c478bd9Sstevel@tonic-gate 	 */
5947c478bd9Sstevel@tonic-gate 	out_args = CIF_MIN_SIZE + in_args;
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 	/*
5977c478bd9Sstevel@tonic-gate 	 * The firmware should pass in a pointer to a buffer, and the
5987c478bd9Sstevel@tonic-gate 	 * number of characters it expects or expects to write.
5997c478bd9Sstevel@tonic-gate 	 * If 2 arguments are not passed in, then return an error.
6007c478bd9Sstevel@tonic-gate 	 */
6017c478bd9Sstevel@tonic-gate 	if (in_args != 2) {
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate 		/*
6047c478bd9Sstevel@tonic-gate 		 * Tell firmware how many arguments we are passing back.
6057c478bd9Sstevel@tonic-gate 		 */
6067c478bd9Sstevel@tonic-gate 		cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate 		/*
6107c478bd9Sstevel@tonic-gate 		 * Tell the firmware that we cannot give it any characters.
6117c478bd9Sstevel@tonic-gate 		 */
6127c478bd9Sstevel@tonic-gate 		cif[out_args] = p1275_uint2cell(CIF_FAILURE);
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate 		return;
6157c478bd9Sstevel@tonic-gate 	}
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 	/*
6187c478bd9Sstevel@tonic-gate 	 * Get the address of where to copy the characters into.
6197c478bd9Sstevel@tonic-gate 	 */
6201a70ae91Smathue 	buffer = (uchar_t *)(uintptr_t)p1275_cell2uint(cif[CIF_MIN_SIZE+0]);
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate 	/*
6237c478bd9Sstevel@tonic-gate 	 * Get the length of the buffer that we can copy characters into.
6247c478bd9Sstevel@tonic-gate 	 */
6257c478bd9Sstevel@tonic-gate 	buflen = p1275_cell2uint(cif[CIF_MIN_SIZE+1]);
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 	/*
6287c478bd9Sstevel@tonic-gate 	 * Make sure there is enough room in the buffer to copy the
6297c478bd9Sstevel@tonic-gate 	 * characters into.
6307c478bd9Sstevel@tonic-gate 	 */
6317c478bd9Sstevel@tonic-gate 	if (buflen == 0) {
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate 		/*
6347c478bd9Sstevel@tonic-gate 		 * Tell the OBP that we cannot give it any characters.
6357c478bd9Sstevel@tonic-gate 		 */
6367c478bd9Sstevel@tonic-gate 		cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
6377c478bd9Sstevel@tonic-gate 
6387c478bd9Sstevel@tonic-gate 		/*
6397c478bd9Sstevel@tonic-gate 		 * Tell the firmware that we cannot give it any characters.
6407c478bd9Sstevel@tonic-gate 		 */
6417c478bd9Sstevel@tonic-gate 		cif[out_args] = p1275_uint2cell(CIF_FAILURE);
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate 		return;
6447c478bd9Sstevel@tonic-gate 	}
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 	/*
6487c478bd9Sstevel@tonic-gate 	 * Tell the firmware how many arguments we are passing back.
6497c478bd9Sstevel@tonic-gate 	 */
6507c478bd9Sstevel@tonic-gate 	cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)2);
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate 	/*
6537c478bd9Sstevel@tonic-gate 	 * Initialize the cif to success
6547c478bd9Sstevel@tonic-gate 	 */
6557c478bd9Sstevel@tonic-gate 	cif[out_args+0] = p1275_uint2cell(CIF_SUCCESS);
6567c478bd9Sstevel@tonic-gate 	cif[out_args+1] = p1275_uint2cell(0);
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 	/*
6597c478bd9Sstevel@tonic-gate 	 * We check the pointer to see if there is an
6607c478bd9Sstevel@tonic-gate 	 * input device that has been registered.
6617c478bd9Sstevel@tonic-gate 	 */
6627c478bd9Sstevel@tonic-gate 	polled_io = polled_output_device.polled_io;
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 	if (polled_io == NULL) {
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate 		/*
6677c478bd9Sstevel@tonic-gate 		 * The cif is already initialized
6687c478bd9Sstevel@tonic-gate 		 */
6697c478bd9Sstevel@tonic-gate 		return;
6707c478bd9Sstevel@tonic-gate 	}
6717c478bd9Sstevel@tonic-gate 
672fea9cb91Slq150181 	polled_io_cons_write(buffer, (size_t)buflen);
6737c478bd9Sstevel@tonic-gate 
6747c478bd9Sstevel@tonic-gate 	/*
6757c478bd9Sstevel@tonic-gate 	 * Tell the firmware how many characters we are sending it.
6767c478bd9Sstevel@tonic-gate 	 */
6777c478bd9Sstevel@tonic-gate 	cif[out_args+0] = p1275_uint2cell((uint_t)CIF_SUCCESS);
6787c478bd9Sstevel@tonic-gate 	cif[out_args+1] = p1275_uint2cell((uint_t)buflen);
6797c478bd9Sstevel@tonic-gate }
680