xref: /onnv-gate/usr/src/uts/sparc/os/polled_io.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate  * This code sets up the callbacks(vx_handlers) so that the firmware may call
31*0Sstevel@tonic-gate  * into the kernel for console input and/or output while in the debugger.
32*0Sstevel@tonic-gate  * The callbacks that execute in debug mode must be careful to not
33*0Sstevel@tonic-gate  * allocate memory, access mutexes, etc. because most kernel services are
34*0Sstevel@tonic-gate  * not available during this mode.
35*0Sstevel@tonic-gate  *
36*0Sstevel@tonic-gate  * This code, and the underlying code that supports the polled input, is very
37*0Sstevel@tonic-gate  * hard to debug.  In order to get the code to execute, polled input must
38*0Sstevel@tonic-gate  * provide input to the debugger.  If anything goes wrong with the code, then
39*0Sstevel@tonic-gate  * it is hard to debug the debugger.  If there are any problems to debug,
40*0Sstevel@tonic-gate  * the following is useful:
41*0Sstevel@tonic-gate  *
42*0Sstevel@tonic-gate  * set the polled_debug variable in /etc/system
43*0Sstevel@tonic-gate  *	set polled_debug=1
44*0Sstevel@tonic-gate  *
45*0Sstevel@tonic-gate  * This variable will register the callbacks but will not throw the switch
46*0Sstevel@tonic-gate  * in the firmware.  The callbacks can be executed by hand from the firmware.
47*0Sstevel@tonic-gate  * Boot the system and drop down to the firmware.
48*0Sstevel@tonic-gate  *
49*0Sstevel@tonic-gate  *	ok " /os-io" select-dev
50*0Sstevel@tonic-gate  *
51*0Sstevel@tonic-gate  * The following will cause the polled_give_input to execute:
52*0Sstevel@tonic-gate  *	ok take
53*0Sstevel@tonic-gate  *
54*0Sstevel@tonic-gate  * The following will cause the polled_take_input to execute:
55*0Sstevel@tonic-gate  *	ok give
56*0Sstevel@tonic-gate  *
57*0Sstevel@tonic-gate  * The following will cause polled_read to execute:
58*0Sstevel@tonic-gate  *	ok read
59*0Sstevel@tonic-gate  */
60*0Sstevel@tonic-gate 
61*0Sstevel@tonic-gate #include <sys/stropts.h>
62*0Sstevel@tonic-gate #include <v9/sys/prom_isa.h>
63*0Sstevel@tonic-gate #include <sys/devops.h>
64*0Sstevel@tonic-gate #include <sys/modctl.h>
65*0Sstevel@tonic-gate #include <sys/ddi.h>
66*0Sstevel@tonic-gate #include <sys/sunddi.h>
67*0Sstevel@tonic-gate #include <sys/promif.h>
68*0Sstevel@tonic-gate #include <sys/note.h>
69*0Sstevel@tonic-gate #include <sys/consdev.h>
70*0Sstevel@tonic-gate #include <sys/polled_io.h>
71*0Sstevel@tonic-gate #include <sys/kdi.h>
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate /*
74*0Sstevel@tonic-gate  * Internal Functions
75*0Sstevel@tonic-gate  */
76*0Sstevel@tonic-gate static void	polled_give_input(cell_t *cif);
77*0Sstevel@tonic-gate static void	polled_read(cell_t *cif);
78*0Sstevel@tonic-gate static void	polled_take_input(cell_t *cif);
79*0Sstevel@tonic-gate static void	polled_give_output(cell_t *cif);
80*0Sstevel@tonic-gate static void	polled_write(cell_t *cif);
81*0Sstevel@tonic-gate static void	polled_take_output(cell_t *cif);
82*0Sstevel@tonic-gate static void	polled_io_register(cons_polledio_t *,
83*0Sstevel@tonic-gate 			polled_io_console_type_t, int);
84*0Sstevel@tonic-gate static void	polled_io_unregister(polled_io_console_type_t, int);
85*0Sstevel@tonic-gate static int	polled_io_take_console(polled_io_console_type_t, int);
86*0Sstevel@tonic-gate static int	polled_io_release_console(polled_io_console_type_t, int);
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate /*
89*0Sstevel@tonic-gate  * State information regarding the input/output device
90*0Sstevel@tonic-gate  */
91*0Sstevel@tonic-gate static polled_device_t	polled_input_device;
92*0Sstevel@tonic-gate static polled_device_t	polled_output_device;
93*0Sstevel@tonic-gate static int polled_vx_handlers_init = 0;
94*0Sstevel@tonic-gate 
95*0Sstevel@tonic-gate extern void	add_vx_handler(char *name, int flag, void (*func)(cell_t *));
96*0Sstevel@tonic-gate extern void	remove_vx_handler(char *name);
97*0Sstevel@tonic-gate 
98*0Sstevel@tonic-gate /*
99*0Sstevel@tonic-gate  * This is a useful flag for debugging the entry points.   This flag
100*0Sstevel@tonic-gate  * allows us to exercise the entry points from the firmware without
101*0Sstevel@tonic-gate  * switching the firmware's notion of the input device.
102*0Sstevel@tonic-gate  */
103*0Sstevel@tonic-gate int	polled_debug = 0;
104*0Sstevel@tonic-gate 
105*0Sstevel@tonic-gate /*
106*0Sstevel@tonic-gate  * This routine is called to initialize polled I/O.  We insert our entry
107*0Sstevel@tonic-gate  * points so that the firmware will call into this code
108*0Sstevel@tonic-gate  * when the switch is thrown in polled_io_take_console().
109*0Sstevel@tonic-gate  */
110*0Sstevel@tonic-gate void
111*0Sstevel@tonic-gate polled_io_init(void)
112*0Sstevel@tonic-gate {
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate 	/*
115*0Sstevel@tonic-gate 	 * Only do the initialization once
116*0Sstevel@tonic-gate 	 */
117*0Sstevel@tonic-gate 	if (polled_vx_handlers_init != 0)
118*0Sstevel@tonic-gate 		return;
119*0Sstevel@tonic-gate 
120*0Sstevel@tonic-gate 	/*
121*0Sstevel@tonic-gate 	 * Add the vx_handlers for the different functions that
122*0Sstevel@tonic-gate 	 * need to be accessed from firmware.
123*0Sstevel@tonic-gate 	 */
124*0Sstevel@tonic-gate 	add_vx_handler("enter-input", 1, polled_give_input);
125*0Sstevel@tonic-gate 
126*0Sstevel@tonic-gate 	add_vx_handler("read", 1, polled_read);
127*0Sstevel@tonic-gate 
128*0Sstevel@tonic-gate 	add_vx_handler("exit-input", 1, polled_take_input);
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate 	add_vx_handler("give-output", 1, polled_give_output);
131*0Sstevel@tonic-gate 
132*0Sstevel@tonic-gate 	add_vx_handler("write", 1, polled_write);
133*0Sstevel@tonic-gate 
134*0Sstevel@tonic-gate 	add_vx_handler("take-output", 1, polled_take_output);
135*0Sstevel@tonic-gate 
136*0Sstevel@tonic-gate 	/*
137*0Sstevel@tonic-gate 	 * Initialize lock to protect multiple thread access to the
138*0Sstevel@tonic-gate 	 * polled_input_device structure.  This does not protect
139*0Sstevel@tonic-gate 	 * us from access in debug mode.
140*0Sstevel@tonic-gate 	 */
141*0Sstevel@tonic-gate 	mutex_init(&polled_input_device.polled_device_lock,
142*0Sstevel@tonic-gate 		NULL, MUTEX_DRIVER, NULL);
143*0Sstevel@tonic-gate 
144*0Sstevel@tonic-gate 	/*
145*0Sstevel@tonic-gate 	 * Initialize lock to protect multiple thread access to the
146*0Sstevel@tonic-gate 	 * polled_output_device structure.  This does not protect
147*0Sstevel@tonic-gate 	 * us from access in debug mode.
148*0Sstevel@tonic-gate 	 */
149*0Sstevel@tonic-gate 	mutex_init(&polled_output_device.polled_device_lock,
150*0Sstevel@tonic-gate 		NULL, MUTEX_DRIVER, NULL);
151*0Sstevel@tonic-gate 
152*0Sstevel@tonic-gate 	polled_vx_handlers_init = 1;
153*0Sstevel@tonic-gate }
154*0Sstevel@tonic-gate 
155*0Sstevel@tonic-gate /*
156*0Sstevel@tonic-gate  * Register a device for input or output.  The polled_io structure
157*0Sstevel@tonic-gate  * will be filled in with the callbacks that are appropriate for
158*0Sstevel@tonic-gate  * that device.
159*0Sstevel@tonic-gate  */
160*0Sstevel@tonic-gate int
161*0Sstevel@tonic-gate polled_io_register_callbacks(
162*0Sstevel@tonic-gate cons_polledio_t			*polled_io,
163*0Sstevel@tonic-gate int				flags
164*0Sstevel@tonic-gate )
165*0Sstevel@tonic-gate {
166*0Sstevel@tonic-gate 	/*
167*0Sstevel@tonic-gate 	 * If the input structure entries aren't filled in, then register this
168*0Sstevel@tonic-gate 	 * structure as an input device.
169*0Sstevel@tonic-gate 	 */
170*0Sstevel@tonic-gate 	if ((polled_io->cons_polledio_getchar != NULL) &&
171*0Sstevel@tonic-gate 		(polled_io->cons_polledio_ischar != NULL)) {
172*0Sstevel@tonic-gate 
173*0Sstevel@tonic-gate 		polled_io_register(polled_io,
174*0Sstevel@tonic-gate 			POLLED_IO_CONSOLE_INPUT, flags);
175*0Sstevel@tonic-gate 	}
176*0Sstevel@tonic-gate 
177*0Sstevel@tonic-gate 	/*
178*0Sstevel@tonic-gate 	 * If the output structure entries aren't filled in, then register this
179*0Sstevel@tonic-gate 	 * structure as an output device.
180*0Sstevel@tonic-gate 	 */
181*0Sstevel@tonic-gate 	if (polled_io->cons_polledio_putchar != NULL) {
182*0Sstevel@tonic-gate 
183*0Sstevel@tonic-gate 		polled_io_register(polled_io,
184*0Sstevel@tonic-gate 			POLLED_IO_CONSOLE_OUTPUT, flags);
185*0Sstevel@tonic-gate 	}
186*0Sstevel@tonic-gate 
187*0Sstevel@tonic-gate 	cons_polledio = polled_io;
188*0Sstevel@tonic-gate 
189*0Sstevel@tonic-gate 	return (DDI_SUCCESS);
190*0Sstevel@tonic-gate }
191*0Sstevel@tonic-gate 
192*0Sstevel@tonic-gate /*
193*0Sstevel@tonic-gate  * Unregister a device for console input/output.
194*0Sstevel@tonic-gate  */
195*0Sstevel@tonic-gate int
196*0Sstevel@tonic-gate polled_io_unregister_callbacks(
197*0Sstevel@tonic-gate cons_polledio_t			*polled_io,
198*0Sstevel@tonic-gate int				flags
199*0Sstevel@tonic-gate )
200*0Sstevel@tonic-gate {
201*0Sstevel@tonic-gate 	/*
202*0Sstevel@tonic-gate 	 * If polled_io is being used for input, then unregister it.
203*0Sstevel@tonic-gate 	 */
204*0Sstevel@tonic-gate 	if (polled_io == polled_input_device.polled_io) {
205*0Sstevel@tonic-gate 
206*0Sstevel@tonic-gate 		polled_io_unregister(
207*0Sstevel@tonic-gate 			POLLED_IO_CONSOLE_INPUT, flags);
208*0Sstevel@tonic-gate 	}
209*0Sstevel@tonic-gate 
210*0Sstevel@tonic-gate 	/*
211*0Sstevel@tonic-gate 	 * If polled_io is being used for output, then unregister it.
212*0Sstevel@tonic-gate 	 */
213*0Sstevel@tonic-gate 	if (polled_io == polled_output_device.polled_io) {
214*0Sstevel@tonic-gate 
215*0Sstevel@tonic-gate 		polled_io_unregister(
216*0Sstevel@tonic-gate 			POLLED_IO_CONSOLE_OUTPUT, flags);
217*0Sstevel@tonic-gate 	}
218*0Sstevel@tonic-gate 
219*0Sstevel@tonic-gate 	return (DDI_SUCCESS);
220*0Sstevel@tonic-gate }
221*0Sstevel@tonic-gate 
222*0Sstevel@tonic-gate /*
223*0Sstevel@tonic-gate  * This routine is called when we are done handling polled io.  We will
224*0Sstevel@tonic-gate  * remove all of our handlers and destroy any memory that we have allocated.
225*0Sstevel@tonic-gate  */
226*0Sstevel@tonic-gate void
227*0Sstevel@tonic-gate polled_io_fini()
228*0Sstevel@tonic-gate {
229*0Sstevel@tonic-gate 	/*
230*0Sstevel@tonic-gate 	 * Remove the vx_handlers so that our functions will nolonger be
231*0Sstevel@tonic-gate 	 * accessible.
232*0Sstevel@tonic-gate 	 */
233*0Sstevel@tonic-gate 	remove_vx_handler("enter-input");
234*0Sstevel@tonic-gate 
235*0Sstevel@tonic-gate 	remove_vx_handler("read");
236*0Sstevel@tonic-gate 
237*0Sstevel@tonic-gate 	remove_vx_handler("exit-input");
238*0Sstevel@tonic-gate 
239*0Sstevel@tonic-gate 	remove_vx_handler("give-output");
240*0Sstevel@tonic-gate 
241*0Sstevel@tonic-gate 	remove_vx_handler("write");
242*0Sstevel@tonic-gate 
243*0Sstevel@tonic-gate 	remove_vx_handler("take-output");
244*0Sstevel@tonic-gate 
245*0Sstevel@tonic-gate 	/*
246*0Sstevel@tonic-gate 	 * Destroy the mutexes, we will not need them anymore.
247*0Sstevel@tonic-gate 	 */
248*0Sstevel@tonic-gate 	mutex_destroy(&polled_input_device.polled_device_lock);
249*0Sstevel@tonic-gate 
250*0Sstevel@tonic-gate 	mutex_destroy(&polled_output_device.polled_device_lock);
251*0Sstevel@tonic-gate 
252*0Sstevel@tonic-gate 	polled_vx_handlers_init = 0;
253*0Sstevel@tonic-gate }
254*0Sstevel@tonic-gate 
255*0Sstevel@tonic-gate /*
256*0Sstevel@tonic-gate  * Generic internal routine for registering a polled input or output device.
257*0Sstevel@tonic-gate  */
258*0Sstevel@tonic-gate /* ARGSUSED */
259*0Sstevel@tonic-gate static void
260*0Sstevel@tonic-gate polled_io_register(
261*0Sstevel@tonic-gate cons_polledio_t			*polled_io,
262*0Sstevel@tonic-gate polled_io_console_type_t	type,
263*0Sstevel@tonic-gate int				flags
264*0Sstevel@tonic-gate )
265*0Sstevel@tonic-gate {
266*0Sstevel@tonic-gate 	switch (type) {
267*0Sstevel@tonic-gate 	case POLLED_IO_CONSOLE_INPUT:
268*0Sstevel@tonic-gate 		/*
269*0Sstevel@tonic-gate 		 * Grab the device lock, because we are going to access
270*0Sstevel@tonic-gate 		 * protected structure entries.  We do this before the
271*0Sstevel@tonic-gate 		 * POLLED_IO_CONSOLE_OPEN_INPUT so that we serialize
272*0Sstevel@tonic-gate 		 * registration.
273*0Sstevel@tonic-gate 		 */
274*0Sstevel@tonic-gate 		mutex_enter(&polled_input_device.polled_device_lock);
275*0Sstevel@tonic-gate 
276*0Sstevel@tonic-gate 		/*
277*0Sstevel@tonic-gate 		 * Save the polled_io pointers so that we can access
278*0Sstevel@tonic-gate 		 * them later.
279*0Sstevel@tonic-gate 		 */
280*0Sstevel@tonic-gate 		polled_input_device.polled_io = polled_io;
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate 		mutex_exit(&polled_input_device.polled_device_lock);
283*0Sstevel@tonic-gate 
284*0Sstevel@tonic-gate 
285*0Sstevel@tonic-gate 		if (!polled_debug) {
286*0Sstevel@tonic-gate 			/*
287*0Sstevel@tonic-gate 			 * Tell the generic console framework to
288*0Sstevel@tonic-gate 			 * repoint firmware's stdin to this keyboard device.
289*0Sstevel@tonic-gate 			 */
290*0Sstevel@tonic-gate 			(void) polled_io_take_console(type, 0);
291*0Sstevel@tonic-gate 		}
292*0Sstevel@tonic-gate 
293*0Sstevel@tonic-gate 		break;
294*0Sstevel@tonic-gate 
295*0Sstevel@tonic-gate 	case POLLED_IO_CONSOLE_OUTPUT:
296*0Sstevel@tonic-gate 		/*
297*0Sstevel@tonic-gate 		 * Grab the device lock, because we are going to access
298*0Sstevel@tonic-gate 		 * protected structure entries. We do this before the
299*0Sstevel@tonic-gate 		 * POLLED_IO_CONSOLE_OPEN_OUTPUT so that we serialize
300*0Sstevel@tonic-gate 		 * registration.
301*0Sstevel@tonic-gate 		 */
302*0Sstevel@tonic-gate 		mutex_enter(&polled_output_device.polled_device_lock);
303*0Sstevel@tonic-gate 
304*0Sstevel@tonic-gate 		/*
305*0Sstevel@tonic-gate 		 * Save the polled_io pointers so that we can access
306*0Sstevel@tonic-gate 		 * them later.
307*0Sstevel@tonic-gate 		 */
308*0Sstevel@tonic-gate 		polled_input_device.polled_io = polled_io;
309*0Sstevel@tonic-gate 
310*0Sstevel@tonic-gate 		mutex_exit(&polled_output_device.polled_device_lock);
311*0Sstevel@tonic-gate 
312*0Sstevel@tonic-gate 		break;
313*0Sstevel@tonic-gate 	}
314*0Sstevel@tonic-gate }
315*0Sstevel@tonic-gate 
316*0Sstevel@tonic-gate /*
317*0Sstevel@tonic-gate  * Generic internal routine for unregistering a polled input or output device.
318*0Sstevel@tonic-gate  */
319*0Sstevel@tonic-gate /* ARGSUSED */
320*0Sstevel@tonic-gate static void
321*0Sstevel@tonic-gate polled_io_unregister(
322*0Sstevel@tonic-gate polled_io_console_type_t	type,
323*0Sstevel@tonic-gate int				flags
324*0Sstevel@tonic-gate )
325*0Sstevel@tonic-gate {
326*0Sstevel@tonic-gate 	switch (type) {
327*0Sstevel@tonic-gate 	case POLLED_IO_CONSOLE_INPUT:
328*0Sstevel@tonic-gate 		/*
329*0Sstevel@tonic-gate 		 * Tell the generic console framework to restore
330*0Sstevel@tonic-gate 		 * the firmware's old stdin pointers.
331*0Sstevel@tonic-gate 		 */
332*0Sstevel@tonic-gate 		(void) polled_io_release_console(type, 0);
333*0Sstevel@tonic-gate 
334*0Sstevel@tonic-gate 		/*
335*0Sstevel@tonic-gate 		 * Grab the device lock, because we are going to access
336*0Sstevel@tonic-gate 		 * protected structure entries.
337*0Sstevel@tonic-gate 		 */
338*0Sstevel@tonic-gate 		mutex_enter(&polled_input_device.polled_device_lock);
339*0Sstevel@tonic-gate 
340*0Sstevel@tonic-gate 		polled_input_device.polled_io = NULL;
341*0Sstevel@tonic-gate 
342*0Sstevel@tonic-gate 		mutex_exit(&polled_input_device.polled_device_lock);
343*0Sstevel@tonic-gate 
344*0Sstevel@tonic-gate 		break;
345*0Sstevel@tonic-gate 
346*0Sstevel@tonic-gate 	case POLLED_IO_CONSOLE_OUTPUT:
347*0Sstevel@tonic-gate 		/*
348*0Sstevel@tonic-gate 		 * Grab the device lock, because we are going to access
349*0Sstevel@tonic-gate 		 * protected structure entries.
350*0Sstevel@tonic-gate 		 */
351*0Sstevel@tonic-gate 		mutex_enter(&polled_output_device.polled_device_lock);
352*0Sstevel@tonic-gate 
353*0Sstevel@tonic-gate 		polled_output_device.polled_io = NULL;
354*0Sstevel@tonic-gate 
355*0Sstevel@tonic-gate 		mutex_exit(&polled_output_device.polled_device_lock);
356*0Sstevel@tonic-gate 
357*0Sstevel@tonic-gate 		break;
358*0Sstevel@tonic-gate 	}
359*0Sstevel@tonic-gate }
360*0Sstevel@tonic-gate 
361*0Sstevel@tonic-gate /*
362*0Sstevel@tonic-gate  * This is the routine that is called to throw the switch from the
363*0Sstevel@tonic-gate  * firmware's ownership of stdout/stdin to the kernel.
364*0Sstevel@tonic-gate  */
365*0Sstevel@tonic-gate /* ARGSUSED */
366*0Sstevel@tonic-gate static int
367*0Sstevel@tonic-gate polled_io_take_console(
368*0Sstevel@tonic-gate polled_io_console_type_t	type,
369*0Sstevel@tonic-gate int				flags
370*0Sstevel@tonic-gate )
371*0Sstevel@tonic-gate {
372*0Sstevel@tonic-gate 
373*0Sstevel@tonic-gate 	switch (type) {
374*0Sstevel@tonic-gate 	case POLLED_IO_CONSOLE_INPUT:
375*0Sstevel@tonic-gate 		/*
376*0Sstevel@tonic-gate 		 * Call into firmware to switch to the kernel I/O handling.
377*0Sstevel@tonic-gate 		 * We will save the old value of stdin so that we can
378*0Sstevel@tonic-gate 		 * restore it if the device is released.
379*0Sstevel@tonic-gate 		 */
380*0Sstevel@tonic-gate #ifdef DEBUG_OBP
381*0Sstevel@tonic-gate 		/*
382*0Sstevel@tonic-gate 		 * This code is useful to trace through
383*0Sstevel@tonic-gate 		 * what the prom is doing
384*0Sstevel@tonic-gate 		 */
385*0Sstevel@tonic-gate 		prom_interpret(
386*0Sstevel@tonic-gate 			"stdin @ swap ! trace-on \" /os-io\" input trace-off",
387*0Sstevel@tonic-gate 			(uintptr_t)&polled_input_device.polled_old_handle,
388*0Sstevel@tonic-gate 				0, 0, 0, 0);
389*0Sstevel@tonic-gate #endif
390*0Sstevel@tonic-gate 
391*0Sstevel@tonic-gate 		prom_interpret(
392*0Sstevel@tonic-gate 			"stdin @ swap ! \" /os-io\" open-dev stdin !",
393*0Sstevel@tonic-gate 			(uintptr_t)&polled_input_device.polled_old_handle,
394*0Sstevel@tonic-gate 				0, 0, 0, 0);
395*0Sstevel@tonic-gate 
396*0Sstevel@tonic-gate 		break;
397*0Sstevel@tonic-gate 
398*0Sstevel@tonic-gate 	case POLLED_IO_CONSOLE_OUTPUT:
399*0Sstevel@tonic-gate 		/*
400*0Sstevel@tonic-gate 		 * Call into firmware to switch to the kernel I/O handling.
401*0Sstevel@tonic-gate 		 * We will save the old value of stdout so that we can
402*0Sstevel@tonic-gate 		 * restore it if the device is released.
403*0Sstevel@tonic-gate 		 */
404*0Sstevel@tonic-gate 		prom_interpret(
405*0Sstevel@tonic-gate 			"stdout @ swap ! \" /os-io\" output",
406*0Sstevel@tonic-gate 			(uintptr_t)&polled_output_device.polled_old_handle,
407*0Sstevel@tonic-gate 				0, 0, 0, 0);
408*0Sstevel@tonic-gate 
409*0Sstevel@tonic-gate 		break;
410*0Sstevel@tonic-gate 	}
411*0Sstevel@tonic-gate 
412*0Sstevel@tonic-gate 	return (DDI_SUCCESS);
413*0Sstevel@tonic-gate }
414*0Sstevel@tonic-gate 
415*0Sstevel@tonic-gate /*
416*0Sstevel@tonic-gate  * This routine gives control of console input/output back to firmware.
417*0Sstevel@tonic-gate  */
418*0Sstevel@tonic-gate /* ARGSUSED */
419*0Sstevel@tonic-gate static int
420*0Sstevel@tonic-gate polled_io_release_console(
421*0Sstevel@tonic-gate polled_io_console_type_t	type,
422*0Sstevel@tonic-gate int				flags
423*0Sstevel@tonic-gate )
424*0Sstevel@tonic-gate {
425*0Sstevel@tonic-gate 	switch (type) {
426*0Sstevel@tonic-gate 	case POLLED_IO_CONSOLE_INPUT:
427*0Sstevel@tonic-gate 		/*
428*0Sstevel@tonic-gate 		 * Restore the stdin handle
429*0Sstevel@tonic-gate 		 */
430*0Sstevel@tonic-gate 		prom_interpret("to stdin",
431*0Sstevel@tonic-gate 			(uintptr_t)polled_input_device.
432*0Sstevel@tonic-gate 				polled_old_handle,
433*0Sstevel@tonic-gate 				0, 0, 0, 0);
434*0Sstevel@tonic-gate 
435*0Sstevel@tonic-gate 		break;
436*0Sstevel@tonic-gate 
437*0Sstevel@tonic-gate 	case POLLED_IO_CONSOLE_OUTPUT:
438*0Sstevel@tonic-gate 		/*
439*0Sstevel@tonic-gate 		 * Restore the stdout handle
440*0Sstevel@tonic-gate 		 */
441*0Sstevel@tonic-gate 		prom_interpret("to stdout",
442*0Sstevel@tonic-gate 			(uintptr_t)polled_output_device.
443*0Sstevel@tonic-gate 				polled_old_handle,
444*0Sstevel@tonic-gate 				0, 0, 0, 0);
445*0Sstevel@tonic-gate 
446*0Sstevel@tonic-gate 		break;
447*0Sstevel@tonic-gate 	}
448*0Sstevel@tonic-gate 
449*0Sstevel@tonic-gate 	return (DDI_SUCCESS);
450*0Sstevel@tonic-gate }
451*0Sstevel@tonic-gate 
452*0Sstevel@tonic-gate 
453*0Sstevel@tonic-gate /*
454*0Sstevel@tonic-gate  * This is the routine that the firmware calls to save any state information
455*0Sstevel@tonic-gate  * before using the input device.  This routine, and all of the
456*0Sstevel@tonic-gate  * routines that it calls, are responsible for saving any state
457*0Sstevel@tonic-gate  * information so that it can be restored when debug mode is over.
458*0Sstevel@tonic-gate  *
459*0Sstevel@tonic-gate  * WARNING: This routine runs in debug mode.
460*0Sstevel@tonic-gate  */
461*0Sstevel@tonic-gate static void
462*0Sstevel@tonic-gate polled_give_input(cell_t *cif)
463*0Sstevel@tonic-gate {
464*0Sstevel@tonic-gate 	cons_polledio_t		*polled_io;
465*0Sstevel@tonic-gate 	uint_t			out_args;
466*0Sstevel@tonic-gate 
467*0Sstevel@tonic-gate 	/*
468*0Sstevel@tonic-gate 	 * Calculate the offset of the return arguments
469*0Sstevel@tonic-gate 	 */
470*0Sstevel@tonic-gate 	out_args = CIF_MIN_SIZE +
471*0Sstevel@tonic-gate 		p1275_cell2uint(cif[CIF_NUMBER_IN_ARGS]);
472*0Sstevel@tonic-gate 
473*0Sstevel@tonic-gate 	/*
474*0Sstevel@tonic-gate 	 * There is one argument being passed back to firmware.
475*0Sstevel@tonic-gate 	 */
476*0Sstevel@tonic-gate 	cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
477*0Sstevel@tonic-gate 	cif[out_args] = p1275_uint2cell(CIF_SUCCESS);
478*0Sstevel@tonic-gate 
479*0Sstevel@tonic-gate 	/*
480*0Sstevel@tonic-gate 	 * We check to see if there is an
481*0Sstevel@tonic-gate 	 * input device that has been registered.
482*0Sstevel@tonic-gate 	 */
483*0Sstevel@tonic-gate 	polled_io = polled_input_device.polled_io;
484*0Sstevel@tonic-gate 
485*0Sstevel@tonic-gate 	if (polled_io == NULL) {
486*0Sstevel@tonic-gate 		return;
487*0Sstevel@tonic-gate 	}
488*0Sstevel@tonic-gate 
489*0Sstevel@tonic-gate 	/*
490*0Sstevel@tonic-gate 	 * Call down to the lower layers to save the state.
491*0Sstevel@tonic-gate 	 */
492*0Sstevel@tonic-gate 	polled_io->cons_polledio_enter(
493*0Sstevel@tonic-gate 		polled_io->cons_polledio_argument);
494*0Sstevel@tonic-gate }
495*0Sstevel@tonic-gate 
496*0Sstevel@tonic-gate /*
497*0Sstevel@tonic-gate  * This is the routine that the firmware calls
498*0Sstevel@tonic-gate  * when it wants to read a character.
499*0Sstevel@tonic-gate  * We will call to the lower layers to see if there is any input data
500*0Sstevel@tonic-gate  * available.
501*0Sstevel@tonic-gate  *
502*0Sstevel@tonic-gate  * WARNING: This routine runs in debug mode.
503*0Sstevel@tonic-gate  */
504*0Sstevel@tonic-gate static void
505*0Sstevel@tonic-gate polled_read(cell_t *cif)
506*0Sstevel@tonic-gate {
507*0Sstevel@tonic-gate 	uint_t				actual;
508*0Sstevel@tonic-gate 	cons_polledio_t			*polled_io;
509*0Sstevel@tonic-gate 	uint_t				in_args;
510*0Sstevel@tonic-gate 	uint_t				out_args;
511*0Sstevel@tonic-gate 	uchar_t				*buffer;
512*0Sstevel@tonic-gate 	uint_t				buflen;
513*0Sstevel@tonic-gate 	uchar_t				key;
514*0Sstevel@tonic-gate 
515*0Sstevel@tonic-gate 	/*
516*0Sstevel@tonic-gate 	 * The number of arguments passed in by the firmware
517*0Sstevel@tonic-gate 	 */
518*0Sstevel@tonic-gate 	in_args = p1275_cell2uint(cif[CIF_NUMBER_IN_ARGS]);
519*0Sstevel@tonic-gate 
520*0Sstevel@tonic-gate 	/*
521*0Sstevel@tonic-gate 	 * Calculate the location of the first out arg.  This location is
522*0Sstevel@tonic-gate 	 * CIF_MIN_SIZE plus the in argument locations.
523*0Sstevel@tonic-gate 	 */
524*0Sstevel@tonic-gate 	out_args = CIF_MIN_SIZE + in_args;
525*0Sstevel@tonic-gate 
526*0Sstevel@tonic-gate 	/*
527*0Sstevel@tonic-gate 	 * The firmware should pass in a pointer to a buffer, and the
528*0Sstevel@tonic-gate 	 * number of characters it expects or expects to write.
529*0Sstevel@tonic-gate 	 * If 2 arguments are not passed in, then return an error.
530*0Sstevel@tonic-gate 	 */
531*0Sstevel@tonic-gate 	if (in_args != 2) {
532*0Sstevel@tonic-gate 
533*0Sstevel@tonic-gate 		/*
534*0Sstevel@tonic-gate 		 * Tell firmware how many arguments we are passing back.
535*0Sstevel@tonic-gate 		 */
536*0Sstevel@tonic-gate 		cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
537*0Sstevel@tonic-gate 
538*0Sstevel@tonic-gate 		/*
539*0Sstevel@tonic-gate 		 * Tell the firmware that we cannot give it any characters.
540*0Sstevel@tonic-gate 		 */
541*0Sstevel@tonic-gate 		cif[out_args] = p1275_uint2cell(CIF_FAILURE);
542*0Sstevel@tonic-gate 
543*0Sstevel@tonic-gate 		return;
544*0Sstevel@tonic-gate 	}
545*0Sstevel@tonic-gate 
546*0Sstevel@tonic-gate 	/*
547*0Sstevel@tonic-gate 	 * Get the address of where to copy the characters into.
548*0Sstevel@tonic-gate 	 */
549*0Sstevel@tonic-gate 	buffer = (uchar_t *)p1275_cell2uint(cif[CIF_MIN_SIZE+0]);
550*0Sstevel@tonic-gate 
551*0Sstevel@tonic-gate 	/*
552*0Sstevel@tonic-gate 	 * Get the length of the buffer that we can copy characters into.
553*0Sstevel@tonic-gate 	 */
554*0Sstevel@tonic-gate 	buflen = p1275_cell2uint(cif[CIF_MIN_SIZE+1]);
555*0Sstevel@tonic-gate 
556*0Sstevel@tonic-gate 	/*
557*0Sstevel@tonic-gate 	 * Make sure there is enough room in the buffer to copy the
558*0Sstevel@tonic-gate 	 * characters into.
559*0Sstevel@tonic-gate 	 */
560*0Sstevel@tonic-gate 	if (buflen == 0) {
561*0Sstevel@tonic-gate 
562*0Sstevel@tonic-gate 		/*
563*0Sstevel@tonic-gate 		 * Tell the OBP that we cannot give it any characters.
564*0Sstevel@tonic-gate 		 */
565*0Sstevel@tonic-gate 		cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
566*0Sstevel@tonic-gate 
567*0Sstevel@tonic-gate 		/*
568*0Sstevel@tonic-gate 		 * Tell the firmware that we cannot give it any characters.
569*0Sstevel@tonic-gate 		 */
570*0Sstevel@tonic-gate 		cif[out_args] = p1275_uint2cell(CIF_FAILURE);
571*0Sstevel@tonic-gate 
572*0Sstevel@tonic-gate 		return;
573*0Sstevel@tonic-gate 	}
574*0Sstevel@tonic-gate 
575*0Sstevel@tonic-gate 	/*
576*0Sstevel@tonic-gate 	 * Pass back whether or not the operation was a success or
577*0Sstevel@tonic-gate 	 * failure plus the actual number of bytes in the buffer.
578*0Sstevel@tonic-gate 	 * Tell firmware how many arguments we are passing back.
579*0Sstevel@tonic-gate 	 */
580*0Sstevel@tonic-gate 	cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)2);
581*0Sstevel@tonic-gate 
582*0Sstevel@tonic-gate 	/*
583*0Sstevel@tonic-gate 	 * Initialize the cif to be "no characters"
584*0Sstevel@tonic-gate 	 */
585*0Sstevel@tonic-gate 	cif[out_args+0] = p1275_uint2cell(CIF_SUCCESS);
586*0Sstevel@tonic-gate 	cif[out_args+1] = p1275_uint2cell(CIF_NO_CHARACTERS);
587*0Sstevel@tonic-gate 
588*0Sstevel@tonic-gate 	/*
589*0Sstevel@tonic-gate 	 * We check to see if there is an
590*0Sstevel@tonic-gate 	 * input device that has been registered.
591*0Sstevel@tonic-gate 	 */
592*0Sstevel@tonic-gate 	polled_io = polled_input_device.polled_io;
593*0Sstevel@tonic-gate 
594*0Sstevel@tonic-gate 	if (polled_io == NULL) {
595*0Sstevel@tonic-gate 
596*0Sstevel@tonic-gate 		/*
597*0Sstevel@tonic-gate 		 * The cif structure is already set up to return
598*0Sstevel@tonic-gate 		 * no characters.
599*0Sstevel@tonic-gate 		 */
600*0Sstevel@tonic-gate 
601*0Sstevel@tonic-gate 		return;
602*0Sstevel@tonic-gate 	}
603*0Sstevel@tonic-gate 
604*0Sstevel@tonic-gate 	actual = 0;
605*0Sstevel@tonic-gate 
606*0Sstevel@tonic-gate 	/*
607*0Sstevel@tonic-gate 	 * Obtain the characters
608*0Sstevel@tonic-gate 	 */
609*0Sstevel@tonic-gate 	while (polled_io->cons_polledio_ischar(
610*0Sstevel@tonic-gate 		polled_io->cons_polledio_argument) == B_TRUE) {
611*0Sstevel@tonic-gate 
612*0Sstevel@tonic-gate 		/*
613*0Sstevel@tonic-gate 		 * Make sure that we don't overrun the buffer.
614*0Sstevel@tonic-gate 		 */
615*0Sstevel@tonic-gate 		if (actual == buflen) {
616*0Sstevel@tonic-gate 
617*0Sstevel@tonic-gate 			break;
618*0Sstevel@tonic-gate 		}
619*0Sstevel@tonic-gate 
620*0Sstevel@tonic-gate 		/*
621*0Sstevel@tonic-gate 		 * Call down to the device to copy the input data into the
622*0Sstevel@tonic-gate 		 * buffer.
623*0Sstevel@tonic-gate 		 */
624*0Sstevel@tonic-gate 		key = polled_io->cons_polledio_getchar(
625*0Sstevel@tonic-gate 			polled_io->cons_polledio_argument);
626*0Sstevel@tonic-gate 
627*0Sstevel@tonic-gate 		*(buffer + actual) = key;
628*0Sstevel@tonic-gate 
629*0Sstevel@tonic-gate 		actual++;
630*0Sstevel@tonic-gate 	}
631*0Sstevel@tonic-gate 
632*0Sstevel@tonic-gate 	/*
633*0Sstevel@tonic-gate 	 * There is a special return code when there is no data.
634*0Sstevel@tonic-gate 	 */
635*0Sstevel@tonic-gate 	if (actual == 0) {
636*0Sstevel@tonic-gate 
637*0Sstevel@tonic-gate 		/*
638*0Sstevel@tonic-gate 		 * The cif structure is already set up to return
639*0Sstevel@tonic-gate 		 * no characters.
640*0Sstevel@tonic-gate 		 */
641*0Sstevel@tonic-gate 
642*0Sstevel@tonic-gate 		return;
643*0Sstevel@tonic-gate 	}
644*0Sstevel@tonic-gate 
645*0Sstevel@tonic-gate 	/*
646*0Sstevel@tonic-gate 	 * Tell firmware how many characters we are sending it.
647*0Sstevel@tonic-gate 	 */
648*0Sstevel@tonic-gate 	cif[out_args+0] = p1275_uint2cell((uint_t)CIF_SUCCESS);
649*0Sstevel@tonic-gate 	cif[out_args+1] = p1275_uint2cell((uint_t)actual);
650*0Sstevel@tonic-gate }
651*0Sstevel@tonic-gate 
652*0Sstevel@tonic-gate /*
653*0Sstevel@tonic-gate  * This is the routine that firmware calls when it is giving up control of the
654*0Sstevel@tonic-gate  * input device.  This routine, and the lower layer routines that it calls,
655*0Sstevel@tonic-gate  * are responsible for restoring the controller state to the state it was
656*0Sstevel@tonic-gate  * in before firmware took control.
657*0Sstevel@tonic-gate  *
658*0Sstevel@tonic-gate  * WARNING: This routine runs in debug mode.
659*0Sstevel@tonic-gate  */
660*0Sstevel@tonic-gate static void
661*0Sstevel@tonic-gate polled_take_input(cell_t *cif)
662*0Sstevel@tonic-gate {
663*0Sstevel@tonic-gate 	cons_polledio_t		*polled_io;
664*0Sstevel@tonic-gate 	uint_t			out_args;
665*0Sstevel@tonic-gate 
666*0Sstevel@tonic-gate 	/*
667*0Sstevel@tonic-gate 	 * Calculate the offset of the return arguments
668*0Sstevel@tonic-gate 	 */
669*0Sstevel@tonic-gate 	out_args = CIF_MIN_SIZE +
670*0Sstevel@tonic-gate 		p1275_cell2uint(cif[CIF_NUMBER_IN_ARGS]);
671*0Sstevel@tonic-gate 
672*0Sstevel@tonic-gate 	/*
673*0Sstevel@tonic-gate 	 * There is one argument being passed back to firmware.
674*0Sstevel@tonic-gate 	 */
675*0Sstevel@tonic-gate 	cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
676*0Sstevel@tonic-gate 	cif[out_args] = p1275_uint2cell(CIF_SUCCESS);
677*0Sstevel@tonic-gate 
678*0Sstevel@tonic-gate 	/*
679*0Sstevel@tonic-gate 	 * We check the pointer to see if there is an
680*0Sstevel@tonic-gate 	 * input device that has been registered.
681*0Sstevel@tonic-gate 	 */
682*0Sstevel@tonic-gate 	polled_io = polled_input_device.polled_io;
683*0Sstevel@tonic-gate 
684*0Sstevel@tonic-gate 	if (polled_io == NULL) {
685*0Sstevel@tonic-gate 		return;
686*0Sstevel@tonic-gate 	}
687*0Sstevel@tonic-gate 
688*0Sstevel@tonic-gate 	/*
689*0Sstevel@tonic-gate 	 * Call down to the lower layers to save the state.
690*0Sstevel@tonic-gate 	 */
691*0Sstevel@tonic-gate 	polled_io->cons_polledio_exit(
692*0Sstevel@tonic-gate 		polled_io->cons_polledio_argument);
693*0Sstevel@tonic-gate }
694*0Sstevel@tonic-gate 
695*0Sstevel@tonic-gate /*
696*0Sstevel@tonic-gate  * This is the routine that the firmware calls to save any state information
697*0Sstevel@tonic-gate  * before using the output device.  This routine, and all of the
698*0Sstevel@tonic-gate  * routines that it calls, are responsible for saving any state
699*0Sstevel@tonic-gate  * information so that it can be restored when the debug  is over.
700*0Sstevel@tonic-gate  *
701*0Sstevel@tonic-gate  * WARNING:  This routine runs in debug mode.
702*0Sstevel@tonic-gate  */
703*0Sstevel@tonic-gate static void
704*0Sstevel@tonic-gate polled_give_output(cell_t *cif)
705*0Sstevel@tonic-gate {
706*0Sstevel@tonic-gate 	cons_polledio_t		*polled_io;
707*0Sstevel@tonic-gate 
708*0Sstevel@tonic-gate 	uint_t			out_args;
709*0Sstevel@tonic-gate 
710*0Sstevel@tonic-gate 	/*
711*0Sstevel@tonic-gate 	 * Calculate the offset of the return arguments
712*0Sstevel@tonic-gate 	 */
713*0Sstevel@tonic-gate 	out_args = CIF_MIN_SIZE +
714*0Sstevel@tonic-gate 		p1275_cell2uint(cif[CIF_NUMBER_IN_ARGS]);
715*0Sstevel@tonic-gate 
716*0Sstevel@tonic-gate 	/*
717*0Sstevel@tonic-gate 	 * There is one argument being passed back to the firmware .
718*0Sstevel@tonic-gate 	 */
719*0Sstevel@tonic-gate 	cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
720*0Sstevel@tonic-gate 	cif[out_args] = p1275_uint2cell(CIF_SUCCESS);
721*0Sstevel@tonic-gate 
722*0Sstevel@tonic-gate 	/*
723*0Sstevel@tonic-gate 	 * We check to see if there is an
724*0Sstevel@tonic-gate 	 * output device that has been registered.
725*0Sstevel@tonic-gate 	 */
726*0Sstevel@tonic-gate 	polled_io = polled_output_device.polled_io;
727*0Sstevel@tonic-gate 
728*0Sstevel@tonic-gate 	if (polled_io == NULL) {
729*0Sstevel@tonic-gate 		return;
730*0Sstevel@tonic-gate 	}
731*0Sstevel@tonic-gate 
732*0Sstevel@tonic-gate 	/*
733*0Sstevel@tonic-gate 	 * Call down to the lower layers to save the state.
734*0Sstevel@tonic-gate 	 */
735*0Sstevel@tonic-gate 	polled_io->cons_polledio_enter(
736*0Sstevel@tonic-gate 		polled_io->cons_polledio_argument);
737*0Sstevel@tonic-gate }
738*0Sstevel@tonic-gate 
739*0Sstevel@tonic-gate /*
740*0Sstevel@tonic-gate  * This is the routine that the firmware calls when
741*0Sstevel@tonic-gate  * it wants to write a character.
742*0Sstevel@tonic-gate  *
743*0Sstevel@tonic-gate  * WARNING: This routine runs in debug mode.
744*0Sstevel@tonic-gate  */
745*0Sstevel@tonic-gate static void
746*0Sstevel@tonic-gate polled_write(cell_t *cif)
747*0Sstevel@tonic-gate {
748*0Sstevel@tonic-gate 	cons_polledio_t			*polled_io;
749*0Sstevel@tonic-gate 	uint_t				in_args;
750*0Sstevel@tonic-gate 	uint_t				out_args;
751*0Sstevel@tonic-gate 	uchar_t				*buffer;
752*0Sstevel@tonic-gate 	uint_t				buflen;
753*0Sstevel@tonic-gate 	uint_t				i;
754*0Sstevel@tonic-gate 
755*0Sstevel@tonic-gate 	/*
756*0Sstevel@tonic-gate 	 * The number of arguments passed in by the firmware
757*0Sstevel@tonic-gate 	 */
758*0Sstevel@tonic-gate 	in_args = p1275_cell2uint(cif[CIF_NUMBER_IN_ARGS]);
759*0Sstevel@tonic-gate 
760*0Sstevel@tonic-gate 	/*
761*0Sstevel@tonic-gate 	 * Calculate the location of the first out arg.  This location is
762*0Sstevel@tonic-gate 	 * CIF_MIN_SIZE (name + no. in args + no. out args) plus the
763*0Sstevel@tonic-gate 	 * in argument locations.
764*0Sstevel@tonic-gate 	 */
765*0Sstevel@tonic-gate 	out_args = CIF_MIN_SIZE + in_args;
766*0Sstevel@tonic-gate 
767*0Sstevel@tonic-gate 	/*
768*0Sstevel@tonic-gate 	 * The firmware should pass in a pointer to a buffer, and the
769*0Sstevel@tonic-gate 	 * number of characters it expects or expects to write.
770*0Sstevel@tonic-gate 	 * If 2 arguments are not passed in, then return an error.
771*0Sstevel@tonic-gate 	 */
772*0Sstevel@tonic-gate 	if (in_args != 2) {
773*0Sstevel@tonic-gate 
774*0Sstevel@tonic-gate 		/*
775*0Sstevel@tonic-gate 		 * Tell firmware how many arguments we are passing back.
776*0Sstevel@tonic-gate 		 */
777*0Sstevel@tonic-gate 		cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
778*0Sstevel@tonic-gate 
779*0Sstevel@tonic-gate 
780*0Sstevel@tonic-gate 		/*
781*0Sstevel@tonic-gate 		 * Tell the firmware that we cannot give it any characters.
782*0Sstevel@tonic-gate 		 */
783*0Sstevel@tonic-gate 		cif[out_args] = p1275_uint2cell(CIF_FAILURE);
784*0Sstevel@tonic-gate 
785*0Sstevel@tonic-gate 		return;
786*0Sstevel@tonic-gate 	}
787*0Sstevel@tonic-gate 
788*0Sstevel@tonic-gate 	/*
789*0Sstevel@tonic-gate 	 * Get the address of where to copy the characters into.
790*0Sstevel@tonic-gate 	 */
791*0Sstevel@tonic-gate 	buffer = (uchar_t *)p1275_cell2uint(cif[CIF_MIN_SIZE+0]);
792*0Sstevel@tonic-gate 
793*0Sstevel@tonic-gate 	/*
794*0Sstevel@tonic-gate 	 * Get the length of the buffer that we can copy characters into.
795*0Sstevel@tonic-gate 	 */
796*0Sstevel@tonic-gate 	buflen = p1275_cell2uint(cif[CIF_MIN_SIZE+1]);
797*0Sstevel@tonic-gate 
798*0Sstevel@tonic-gate 	/*
799*0Sstevel@tonic-gate 	 * Make sure there is enough room in the buffer to copy the
800*0Sstevel@tonic-gate 	 * characters into.
801*0Sstevel@tonic-gate 	 */
802*0Sstevel@tonic-gate 	if (buflen == 0) {
803*0Sstevel@tonic-gate 
804*0Sstevel@tonic-gate 		/*
805*0Sstevel@tonic-gate 		 * Tell the OBP that we cannot give it any characters.
806*0Sstevel@tonic-gate 		 */
807*0Sstevel@tonic-gate 		cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
808*0Sstevel@tonic-gate 
809*0Sstevel@tonic-gate 		/*
810*0Sstevel@tonic-gate 		 * Tell the firmware that we cannot give it any characters.
811*0Sstevel@tonic-gate 		 */
812*0Sstevel@tonic-gate 		cif[out_args] = p1275_uint2cell(CIF_FAILURE);
813*0Sstevel@tonic-gate 
814*0Sstevel@tonic-gate 		return;
815*0Sstevel@tonic-gate 	}
816*0Sstevel@tonic-gate 
817*0Sstevel@tonic-gate 
818*0Sstevel@tonic-gate 	/*
819*0Sstevel@tonic-gate 	 * Tell the firmware how many arguments we are passing back.
820*0Sstevel@tonic-gate 	 */
821*0Sstevel@tonic-gate 	cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)2);
822*0Sstevel@tonic-gate 
823*0Sstevel@tonic-gate 	/*
824*0Sstevel@tonic-gate 	 * Initialize the cif to success
825*0Sstevel@tonic-gate 	 */
826*0Sstevel@tonic-gate 	cif[out_args+0] = p1275_uint2cell(CIF_SUCCESS);
827*0Sstevel@tonic-gate 	cif[out_args+1] = p1275_uint2cell(0);
828*0Sstevel@tonic-gate 
829*0Sstevel@tonic-gate 	/*
830*0Sstevel@tonic-gate 	 * We check the pointer to see if there is an
831*0Sstevel@tonic-gate 	 * input device that has been registered.
832*0Sstevel@tonic-gate 	 */
833*0Sstevel@tonic-gate 	polled_io = polled_output_device.polled_io;
834*0Sstevel@tonic-gate 
835*0Sstevel@tonic-gate 	if (polled_io == NULL) {
836*0Sstevel@tonic-gate 
837*0Sstevel@tonic-gate 		/*
838*0Sstevel@tonic-gate 		 * The cif is already initialized
839*0Sstevel@tonic-gate 		 */
840*0Sstevel@tonic-gate 		return;
841*0Sstevel@tonic-gate 	}
842*0Sstevel@tonic-gate 
843*0Sstevel@tonic-gate 	for (i = 0; i < buflen; i++) {
844*0Sstevel@tonic-gate 
845*0Sstevel@tonic-gate 		polled_io->cons_polledio_putchar(
846*0Sstevel@tonic-gate 			polled_io->cons_polledio_argument, *(buffer + i));
847*0Sstevel@tonic-gate 	}
848*0Sstevel@tonic-gate 
849*0Sstevel@tonic-gate 	/*
850*0Sstevel@tonic-gate 	 * Tell the firmware how many characters we are sending it.
851*0Sstevel@tonic-gate 	 */
852*0Sstevel@tonic-gate 	cif[out_args+0] = p1275_uint2cell((uint_t)CIF_SUCCESS);
853*0Sstevel@tonic-gate 	cif[out_args+1] = p1275_uint2cell((uint_t)buflen);
854*0Sstevel@tonic-gate }
855*0Sstevel@tonic-gate 
856*0Sstevel@tonic-gate /*
857*0Sstevel@tonic-gate  * This is the routine that the firmware calls
858*0Sstevel@tonic-gate  *  when it is giving up control of the
859*0Sstevel@tonic-gate  * output device.  This routine, and the lower layer routines that it calls,
860*0Sstevel@tonic-gate  * are responsible for restoring the controller state to the state it was
861*0Sstevel@tonic-gate  * in before the firmware took control.
862*0Sstevel@tonic-gate  *
863*0Sstevel@tonic-gate  * WARNING: This routine runs in debug mode.
864*0Sstevel@tonic-gate  */
865*0Sstevel@tonic-gate static void
866*0Sstevel@tonic-gate polled_take_output(cell_t *cif)
867*0Sstevel@tonic-gate {
868*0Sstevel@tonic-gate 	cons_polledio_t		*polled_io;
869*0Sstevel@tonic-gate 	uint_t			out_args;
870*0Sstevel@tonic-gate 
871*0Sstevel@tonic-gate 	/*
872*0Sstevel@tonic-gate 	 * Calculate the offset of the return arguments
873*0Sstevel@tonic-gate 	 */
874*0Sstevel@tonic-gate 	out_args = CIF_MIN_SIZE +
875*0Sstevel@tonic-gate 		p1275_cell2uint(cif[CIF_NUMBER_IN_ARGS]);
876*0Sstevel@tonic-gate 
877*0Sstevel@tonic-gate 	/*
878*0Sstevel@tonic-gate 	 * There is one argument being passed back to the firmware.
879*0Sstevel@tonic-gate 	 */
880*0Sstevel@tonic-gate 	cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
881*0Sstevel@tonic-gate 	cif[out_args] = p1275_uint2cell(CIF_SUCCESS);
882*0Sstevel@tonic-gate 
883*0Sstevel@tonic-gate 	/*
884*0Sstevel@tonic-gate 	 * We check the pointer to see if there is an
885*0Sstevel@tonic-gate 	 * output device that has been registered.
886*0Sstevel@tonic-gate 	 */
887*0Sstevel@tonic-gate 	polled_io = polled_output_device.polled_io;
888*0Sstevel@tonic-gate 
889*0Sstevel@tonic-gate 	if (polled_io == NULL) {
890*0Sstevel@tonic-gate 		return;
891*0Sstevel@tonic-gate 	}
892*0Sstevel@tonic-gate 
893*0Sstevel@tonic-gate 	/*
894*0Sstevel@tonic-gate 	 * Call down to the lower layers to save the state.
895*0Sstevel@tonic-gate 	 */
896*0Sstevel@tonic-gate 	polled_io->cons_polledio_exit(
897*0Sstevel@tonic-gate 		polled_io->cons_polledio_argument);
898*0Sstevel@tonic-gate }
899