10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51253Slq150181 * Common Development and Distribution License (the "License").
61253Slq150181 * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*7416SJames.Marks@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate * This code sets up the callbacks(vx_handlers) so that the firmware may call
280Sstevel@tonic-gate * into the kernel for console input and/or output while in the debugger.
290Sstevel@tonic-gate * The callbacks that execute in debug mode must be careful to not
300Sstevel@tonic-gate * allocate memory, access mutexes, etc. because most kernel services are
310Sstevel@tonic-gate * not available during this mode.
320Sstevel@tonic-gate *
330Sstevel@tonic-gate * This code, and the underlying code that supports the polled input, is very
340Sstevel@tonic-gate * hard to debug. In order to get the code to execute, polled input must
350Sstevel@tonic-gate * provide input to the debugger. If anything goes wrong with the code, then
360Sstevel@tonic-gate * it is hard to debug the debugger. If there are any problems to debug,
370Sstevel@tonic-gate * the following is useful:
380Sstevel@tonic-gate *
390Sstevel@tonic-gate * set the polled_debug variable in /etc/system
400Sstevel@tonic-gate * set polled_debug=1
410Sstevel@tonic-gate *
420Sstevel@tonic-gate * This variable will register the callbacks but will not throw the switch
430Sstevel@tonic-gate * in the firmware. The callbacks can be executed by hand from the firmware.
440Sstevel@tonic-gate * Boot the system and drop down to the firmware.
450Sstevel@tonic-gate *
460Sstevel@tonic-gate * ok " /os-io" select-dev
470Sstevel@tonic-gate *
480Sstevel@tonic-gate * The following will cause the polled_give_input to execute:
490Sstevel@tonic-gate * ok take
500Sstevel@tonic-gate *
510Sstevel@tonic-gate * The following will cause the polled_take_input to execute:
520Sstevel@tonic-gate * ok give
530Sstevel@tonic-gate *
540Sstevel@tonic-gate * The following will cause polled_read to execute:
550Sstevel@tonic-gate * ok read
560Sstevel@tonic-gate */
570Sstevel@tonic-gate
580Sstevel@tonic-gate #include <sys/stropts.h>
590Sstevel@tonic-gate #include <v9/sys/prom_isa.h>
600Sstevel@tonic-gate #include <sys/devops.h>
610Sstevel@tonic-gate #include <sys/modctl.h>
620Sstevel@tonic-gate #include <sys/ddi.h>
630Sstevel@tonic-gate #include <sys/sunddi.h>
640Sstevel@tonic-gate #include <sys/promif.h>
650Sstevel@tonic-gate #include <sys/note.h>
660Sstevel@tonic-gate #include <sys/consdev.h>
670Sstevel@tonic-gate #include <sys/polled_io.h>
680Sstevel@tonic-gate #include <sys/kdi.h>
69*7416SJames.Marks@Sun.COM #ifdef sun4v
70*7416SJames.Marks@Sun.COM #include <sys/ldoms.h>
71*7416SJames.Marks@Sun.COM #endif
720Sstevel@tonic-gate
730Sstevel@tonic-gate /*
740Sstevel@tonic-gate * Internal Functions
750Sstevel@tonic-gate */
760Sstevel@tonic-gate static void polled_give_input(cell_t *cif);
770Sstevel@tonic-gate static void polled_read(cell_t *cif);
780Sstevel@tonic-gate static void polled_take_input(cell_t *cif);
791253Slq150181
800Sstevel@tonic-gate static void polled_write(cell_t *cif);
810Sstevel@tonic-gate static void polled_io_register(cons_polledio_t *,
820Sstevel@tonic-gate polled_io_console_type_t, int);
830Sstevel@tonic-gate static int polled_io_take_console(polled_io_console_type_t, int);
840Sstevel@tonic-gate static int polled_io_release_console(polled_io_console_type_t, int);
850Sstevel@tonic-gate
860Sstevel@tonic-gate /*
870Sstevel@tonic-gate * State information regarding the input/output device
880Sstevel@tonic-gate */
890Sstevel@tonic-gate static polled_device_t polled_input_device;
900Sstevel@tonic-gate static polled_device_t polled_output_device;
910Sstevel@tonic-gate static int polled_vx_handlers_init = 0;
920Sstevel@tonic-gate
930Sstevel@tonic-gate extern void add_vx_handler(char *name, int flag, void (*func)(cell_t *));
940Sstevel@tonic-gate
950Sstevel@tonic-gate /*
960Sstevel@tonic-gate * This is a useful flag for debugging the entry points. This flag
970Sstevel@tonic-gate * allows us to exercise the entry points from the firmware without
980Sstevel@tonic-gate * switching the firmware's notion of the input device.
990Sstevel@tonic-gate */
1000Sstevel@tonic-gate int polled_debug = 0;
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate /*
1030Sstevel@tonic-gate * This routine is called to initialize polled I/O. We insert our entry
1040Sstevel@tonic-gate * points so that the firmware will call into this code
1050Sstevel@tonic-gate * when the switch is thrown in polled_io_take_console().
1060Sstevel@tonic-gate */
1070Sstevel@tonic-gate void
polled_io_init(void)1080Sstevel@tonic-gate polled_io_init(void)
1090Sstevel@tonic-gate {
1100Sstevel@tonic-gate
1110Sstevel@tonic-gate /*
1120Sstevel@tonic-gate * Only do the initialization once
1130Sstevel@tonic-gate */
1140Sstevel@tonic-gate if (polled_vx_handlers_init != 0)
1150Sstevel@tonic-gate return;
116*7416SJames.Marks@Sun.COM #ifdef sun4v
117*7416SJames.Marks@Sun.COM if (!domaining_enabled()) {
118*7416SJames.Marks@Sun.COM #endif
1190Sstevel@tonic-gate /*
1200Sstevel@tonic-gate * Add the vx_handlers for the different functions that
1210Sstevel@tonic-gate * need to be accessed from firmware.
1220Sstevel@tonic-gate */
1230Sstevel@tonic-gate add_vx_handler("enter-input", 1, polled_give_input);
1240Sstevel@tonic-gate
1250Sstevel@tonic-gate add_vx_handler("read", 1, polled_read);
1260Sstevel@tonic-gate
1270Sstevel@tonic-gate add_vx_handler("exit-input", 1, polled_take_input);
1280Sstevel@tonic-gate
1290Sstevel@tonic-gate add_vx_handler("write", 1, polled_write);
130*7416SJames.Marks@Sun.COM #ifdef sun4v
131*7416SJames.Marks@Sun.COM }
132*7416SJames.Marks@Sun.COM #endif
1330Sstevel@tonic-gate
1340Sstevel@tonic-gate /*
1350Sstevel@tonic-gate * Initialize lock to protect multiple thread access to the
1360Sstevel@tonic-gate * polled_input_device structure. This does not protect
1370Sstevel@tonic-gate * us from access in debug mode.
1380Sstevel@tonic-gate */
1390Sstevel@tonic-gate mutex_init(&polled_input_device.polled_device_lock,
140*7416SJames.Marks@Sun.COM NULL, MUTEX_DRIVER, NULL);
1410Sstevel@tonic-gate
1420Sstevel@tonic-gate /*
1430Sstevel@tonic-gate * Initialize lock to protect multiple thread access to the
1440Sstevel@tonic-gate * polled_output_device structure. This does not protect
1450Sstevel@tonic-gate * us from access in debug mode.
1460Sstevel@tonic-gate */
1470Sstevel@tonic-gate mutex_init(&polled_output_device.polled_device_lock,
148*7416SJames.Marks@Sun.COM NULL, MUTEX_DRIVER, NULL);
1490Sstevel@tonic-gate
1500Sstevel@tonic-gate polled_vx_handlers_init = 1;
1510Sstevel@tonic-gate }
1520Sstevel@tonic-gate
1530Sstevel@tonic-gate /*
1540Sstevel@tonic-gate * Register a device for input or output. The polled_io structure
1550Sstevel@tonic-gate * will be filled in with the callbacks that are appropriate for
1560Sstevel@tonic-gate * that device.
1570Sstevel@tonic-gate */
1580Sstevel@tonic-gate int
polled_io_register_callbacks(cons_polledio_t * polled_io,int flags)1590Sstevel@tonic-gate polled_io_register_callbacks(
1600Sstevel@tonic-gate cons_polledio_t *polled_io,
1610Sstevel@tonic-gate int flags
1620Sstevel@tonic-gate )
1630Sstevel@tonic-gate {
1640Sstevel@tonic-gate /*
1650Sstevel@tonic-gate * If the input structure entries aren't filled in, then register this
1660Sstevel@tonic-gate * structure as an input device.
1670Sstevel@tonic-gate */
1680Sstevel@tonic-gate if ((polled_io->cons_polledio_getchar != NULL) &&
169*7416SJames.Marks@Sun.COM (polled_io->cons_polledio_ischar != NULL)) {
1700Sstevel@tonic-gate
171*7416SJames.Marks@Sun.COM polled_io_register(polled_io, POLLED_IO_CONSOLE_INPUT, flags);
1720Sstevel@tonic-gate }
1730Sstevel@tonic-gate
1740Sstevel@tonic-gate /*
1750Sstevel@tonic-gate * If the output structure entries aren't filled in, then register this
1760Sstevel@tonic-gate * structure as an output device.
1770Sstevel@tonic-gate */
1780Sstevel@tonic-gate if (polled_io->cons_polledio_putchar != NULL) {
1790Sstevel@tonic-gate
180*7416SJames.Marks@Sun.COM polled_io_register(polled_io, POLLED_IO_CONSOLE_OUTPUT, flags);
1810Sstevel@tonic-gate }
1820Sstevel@tonic-gate
1830Sstevel@tonic-gate cons_polledio = polled_io;
1840Sstevel@tonic-gate
1850Sstevel@tonic-gate return (DDI_SUCCESS);
1860Sstevel@tonic-gate }
1870Sstevel@tonic-gate
1880Sstevel@tonic-gate /*
1891253Slq150181 * Sends string through the polled output interfaces when the
1901253Slq150181 * system is panicing.
1910Sstevel@tonic-gate */
1920Sstevel@tonic-gate void
polled_io_cons_write(uchar_t * text,size_t len)1931253Slq150181 polled_io_cons_write(uchar_t *text, size_t len)
1940Sstevel@tonic-gate {
1951253Slq150181 cons_polledio_t *pio = polled_output_device.polled_io;
1961253Slq150181 int i;
1970Sstevel@tonic-gate
1981253Slq150181 for (i = 0; i < len; i++)
1991253Slq150181 pio->cons_polledio_putchar(
2001253Slq150181 pio->cons_polledio_argument, text[i]);
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate /*
2040Sstevel@tonic-gate * Generic internal routine for registering a polled input or output device.
2050Sstevel@tonic-gate */
2060Sstevel@tonic-gate /* ARGSUSED */
2070Sstevel@tonic-gate static void
polled_io_register(cons_polledio_t * polled_io,polled_io_console_type_t type,int flags)2080Sstevel@tonic-gate polled_io_register(
2090Sstevel@tonic-gate cons_polledio_t *polled_io,
2100Sstevel@tonic-gate polled_io_console_type_t type,
2110Sstevel@tonic-gate int flags
2120Sstevel@tonic-gate )
2130Sstevel@tonic-gate {
2140Sstevel@tonic-gate switch (type) {
2150Sstevel@tonic-gate case POLLED_IO_CONSOLE_INPUT:
2160Sstevel@tonic-gate /*
2170Sstevel@tonic-gate * Grab the device lock, because we are going to access
2180Sstevel@tonic-gate * protected structure entries. We do this before the
2190Sstevel@tonic-gate * POLLED_IO_CONSOLE_OPEN_INPUT so that we serialize
2200Sstevel@tonic-gate * registration.
2210Sstevel@tonic-gate */
2220Sstevel@tonic-gate mutex_enter(&polled_input_device.polled_device_lock);
2230Sstevel@tonic-gate
2240Sstevel@tonic-gate /*
2250Sstevel@tonic-gate * Save the polled_io pointers so that we can access
2260Sstevel@tonic-gate * them later.
2270Sstevel@tonic-gate */
2280Sstevel@tonic-gate polled_input_device.polled_io = polled_io;
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate mutex_exit(&polled_input_device.polled_device_lock);
2310Sstevel@tonic-gate
2320Sstevel@tonic-gate
2330Sstevel@tonic-gate if (!polled_debug) {
2340Sstevel@tonic-gate /*
2350Sstevel@tonic-gate * Tell the generic console framework to
2360Sstevel@tonic-gate * repoint firmware's stdin to this keyboard device.
2370Sstevel@tonic-gate */
2380Sstevel@tonic-gate (void) polled_io_take_console(type, 0);
2390Sstevel@tonic-gate }
2400Sstevel@tonic-gate
2410Sstevel@tonic-gate break;
2420Sstevel@tonic-gate
2430Sstevel@tonic-gate case POLLED_IO_CONSOLE_OUTPUT:
2440Sstevel@tonic-gate /*
2450Sstevel@tonic-gate * Grab the device lock, because we are going to access
2460Sstevel@tonic-gate * protected structure entries. We do this before the
2470Sstevel@tonic-gate * POLLED_IO_CONSOLE_OPEN_OUTPUT so that we serialize
2480Sstevel@tonic-gate * registration.
2490Sstevel@tonic-gate */
2500Sstevel@tonic-gate mutex_enter(&polled_output_device.polled_device_lock);
2510Sstevel@tonic-gate
2520Sstevel@tonic-gate /*
2530Sstevel@tonic-gate * Save the polled_io pointers so that we can access
2540Sstevel@tonic-gate * them later.
2550Sstevel@tonic-gate */
2561253Slq150181 polled_output_device.polled_io = polled_io;
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate mutex_exit(&polled_output_device.polled_device_lock);
2590Sstevel@tonic-gate
2601253Slq150181 if (!polled_debug) {
2611253Slq150181 /*
2621253Slq150181 * Tell the generic console framework to
2631253Slq150181 * repoint firmware's stdout to the framebuffer.
2641253Slq150181 */
2651253Slq150181 (void) polled_io_take_console(type, 0);
2661253Slq150181 }
2670Sstevel@tonic-gate
2680Sstevel@tonic-gate break;
2690Sstevel@tonic-gate }
2700Sstevel@tonic-gate }
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate /*
2730Sstevel@tonic-gate * This is the routine that is called to throw the switch from the
2740Sstevel@tonic-gate * firmware's ownership of stdout/stdin to the kernel.
2750Sstevel@tonic-gate */
2760Sstevel@tonic-gate /* ARGSUSED */
2770Sstevel@tonic-gate static int
polled_io_take_console(polled_io_console_type_t type,int flags)2780Sstevel@tonic-gate polled_io_take_console(
2790Sstevel@tonic-gate polled_io_console_type_t type,
2800Sstevel@tonic-gate int flags
2810Sstevel@tonic-gate )
2820Sstevel@tonic-gate {
2830Sstevel@tonic-gate
284*7416SJames.Marks@Sun.COM #ifdef sun4v
285*7416SJames.Marks@Sun.COM if (domaining_enabled())
286*7416SJames.Marks@Sun.COM return (DDI_SUCCESS);
287*7416SJames.Marks@Sun.COM #endif
288*7416SJames.Marks@Sun.COM
2890Sstevel@tonic-gate switch (type) {
2900Sstevel@tonic-gate case POLLED_IO_CONSOLE_INPUT:
2910Sstevel@tonic-gate /*
2920Sstevel@tonic-gate * Call into firmware to switch to the kernel I/O handling.
2930Sstevel@tonic-gate * We will save the old value of stdin so that we can
2940Sstevel@tonic-gate * restore it if the device is released.
2950Sstevel@tonic-gate */
2960Sstevel@tonic-gate #ifdef DEBUG_OBP
2970Sstevel@tonic-gate /*
2980Sstevel@tonic-gate * This code is useful to trace through
2990Sstevel@tonic-gate * what the prom is doing
3000Sstevel@tonic-gate */
3010Sstevel@tonic-gate prom_interpret(
302*7416SJames.Marks@Sun.COM "stdin @ swap ! trace-on \" /os-io\" input trace-off",
303*7416SJames.Marks@Sun.COM (uintptr_t)&polled_input_device.polled_old_handle,
304*7416SJames.Marks@Sun.COM 0, 0, 0, 0);
3050Sstevel@tonic-gate #endif
3060Sstevel@tonic-gate
3070Sstevel@tonic-gate prom_interpret(
308*7416SJames.Marks@Sun.COM "stdin @ swap ! \" /os-io\" open-dev stdin !",
309*7416SJames.Marks@Sun.COM (uintptr_t)&polled_input_device.polled_old_handle,
310*7416SJames.Marks@Sun.COM 0, 0, 0, 0);
3110Sstevel@tonic-gate
3120Sstevel@tonic-gate break;
3130Sstevel@tonic-gate
3140Sstevel@tonic-gate case POLLED_IO_CONSOLE_OUTPUT:
3150Sstevel@tonic-gate /*
3160Sstevel@tonic-gate * Call into firmware to switch to the kernel I/O handling.
3170Sstevel@tonic-gate * We will save the old value of stdout so that we can
3180Sstevel@tonic-gate * restore it if the device is released.
3190Sstevel@tonic-gate */
320*7416SJames.Marks@Sun.COM prom_interpret("stdout @ swap ! \" /os-io\" open-dev stdout !",
321*7416SJames.Marks@Sun.COM (uintptr_t)&polled_output_device.polled_old_handle,
322*7416SJames.Marks@Sun.COM 0, 0, 0, 0);
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate break;
3250Sstevel@tonic-gate }
3260Sstevel@tonic-gate
3270Sstevel@tonic-gate return (DDI_SUCCESS);
3280Sstevel@tonic-gate }
3290Sstevel@tonic-gate
3300Sstevel@tonic-gate /*
3310Sstevel@tonic-gate * This is the routine that the firmware calls to save any state information
3320Sstevel@tonic-gate * before using the input device. This routine, and all of the
3330Sstevel@tonic-gate * routines that it calls, are responsible for saving any state
3340Sstevel@tonic-gate * information so that it can be restored when debug mode is over.
3350Sstevel@tonic-gate *
3360Sstevel@tonic-gate * WARNING: This routine runs in debug mode.
3370Sstevel@tonic-gate */
3380Sstevel@tonic-gate static void
polled_give_input(cell_t * cif)3390Sstevel@tonic-gate polled_give_input(cell_t *cif)
3400Sstevel@tonic-gate {
3410Sstevel@tonic-gate cons_polledio_t *polled_io;
3420Sstevel@tonic-gate uint_t out_args;
3430Sstevel@tonic-gate
3440Sstevel@tonic-gate /*
3450Sstevel@tonic-gate * Calculate the offset of the return arguments
3460Sstevel@tonic-gate */
347*7416SJames.Marks@Sun.COM out_args = CIF_MIN_SIZE + p1275_cell2uint(cif[CIF_NUMBER_IN_ARGS]);
3480Sstevel@tonic-gate
3490Sstevel@tonic-gate /*
3500Sstevel@tonic-gate * There is one argument being passed back to firmware.
3510Sstevel@tonic-gate */
3520Sstevel@tonic-gate cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
3530Sstevel@tonic-gate cif[out_args] = p1275_uint2cell(CIF_SUCCESS);
3540Sstevel@tonic-gate
3550Sstevel@tonic-gate /*
3560Sstevel@tonic-gate * We check to see if there is an
3570Sstevel@tonic-gate * input device that has been registered.
3580Sstevel@tonic-gate */
3590Sstevel@tonic-gate polled_io = polled_input_device.polled_io;
3600Sstevel@tonic-gate
3610Sstevel@tonic-gate if (polled_io == NULL) {
3620Sstevel@tonic-gate return;
3630Sstevel@tonic-gate }
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate /*
3660Sstevel@tonic-gate * Call down to the lower layers to save the state.
3670Sstevel@tonic-gate */
368*7416SJames.Marks@Sun.COM polled_io->cons_polledio_enter(polled_io->cons_polledio_argument);
3690Sstevel@tonic-gate }
3700Sstevel@tonic-gate
3710Sstevel@tonic-gate /*
3720Sstevel@tonic-gate * This is the routine that the firmware calls
3730Sstevel@tonic-gate * when it wants to read a character.
3740Sstevel@tonic-gate * We will call to the lower layers to see if there is any input data
3750Sstevel@tonic-gate * available.
3760Sstevel@tonic-gate *
3770Sstevel@tonic-gate * WARNING: This routine runs in debug mode.
3780Sstevel@tonic-gate */
3790Sstevel@tonic-gate static void
polled_read(cell_t * cif)3800Sstevel@tonic-gate polled_read(cell_t *cif)
3810Sstevel@tonic-gate {
3820Sstevel@tonic-gate uint_t actual;
3830Sstevel@tonic-gate cons_polledio_t *polled_io;
3840Sstevel@tonic-gate uint_t in_args;
3850Sstevel@tonic-gate uint_t out_args;
3860Sstevel@tonic-gate uchar_t *buffer;
3870Sstevel@tonic-gate uint_t buflen;
3880Sstevel@tonic-gate uchar_t key;
3890Sstevel@tonic-gate
3900Sstevel@tonic-gate /*
3910Sstevel@tonic-gate * The number of arguments passed in by the firmware
3920Sstevel@tonic-gate */
3930Sstevel@tonic-gate in_args = p1275_cell2uint(cif[CIF_NUMBER_IN_ARGS]);
3940Sstevel@tonic-gate
3950Sstevel@tonic-gate /*
3960Sstevel@tonic-gate * Calculate the location of the first out arg. This location is
3970Sstevel@tonic-gate * CIF_MIN_SIZE plus the in argument locations.
3980Sstevel@tonic-gate */
3990Sstevel@tonic-gate out_args = CIF_MIN_SIZE + in_args;
4000Sstevel@tonic-gate
4010Sstevel@tonic-gate /*
4020Sstevel@tonic-gate * The firmware should pass in a pointer to a buffer, and the
4030Sstevel@tonic-gate * number of characters it expects or expects to write.
4040Sstevel@tonic-gate * If 2 arguments are not passed in, then return an error.
4050Sstevel@tonic-gate */
4060Sstevel@tonic-gate if (in_args != 2) {
4070Sstevel@tonic-gate
4080Sstevel@tonic-gate /*
4090Sstevel@tonic-gate * Tell firmware how many arguments we are passing back.
4100Sstevel@tonic-gate */
4110Sstevel@tonic-gate cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
4120Sstevel@tonic-gate
4130Sstevel@tonic-gate /*
4140Sstevel@tonic-gate * Tell the firmware that we cannot give it any characters.
4150Sstevel@tonic-gate */
4160Sstevel@tonic-gate cif[out_args] = p1275_uint2cell(CIF_FAILURE);
4170Sstevel@tonic-gate
4180Sstevel@tonic-gate return;
4190Sstevel@tonic-gate }
4200Sstevel@tonic-gate
4210Sstevel@tonic-gate /*
4220Sstevel@tonic-gate * Get the address of where to copy the characters into.
4230Sstevel@tonic-gate */
4241009Smathue buffer = (uchar_t *)(uintptr_t)p1275_cell2uint(cif[CIF_MIN_SIZE+0]);
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate /*
4270Sstevel@tonic-gate * Get the length of the buffer that we can copy characters into.
4280Sstevel@tonic-gate */
4290Sstevel@tonic-gate buflen = p1275_cell2uint(cif[CIF_MIN_SIZE+1]);
4300Sstevel@tonic-gate
4310Sstevel@tonic-gate /*
4320Sstevel@tonic-gate * Make sure there is enough room in the buffer to copy the
4330Sstevel@tonic-gate * characters into.
4340Sstevel@tonic-gate */
4350Sstevel@tonic-gate if (buflen == 0) {
4360Sstevel@tonic-gate
4370Sstevel@tonic-gate /*
4380Sstevel@tonic-gate * Tell the OBP that we cannot give it any characters.
4390Sstevel@tonic-gate */
4400Sstevel@tonic-gate cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
4410Sstevel@tonic-gate
4420Sstevel@tonic-gate /*
4430Sstevel@tonic-gate * Tell the firmware that we cannot give it any characters.
4440Sstevel@tonic-gate */
4450Sstevel@tonic-gate cif[out_args] = p1275_uint2cell(CIF_FAILURE);
4460Sstevel@tonic-gate
4470Sstevel@tonic-gate return;
4480Sstevel@tonic-gate }
4490Sstevel@tonic-gate
4500Sstevel@tonic-gate /*
4510Sstevel@tonic-gate * Pass back whether or not the operation was a success or
4520Sstevel@tonic-gate * failure plus the actual number of bytes in the buffer.
4530Sstevel@tonic-gate * Tell firmware how many arguments we are passing back.
4540Sstevel@tonic-gate */
4550Sstevel@tonic-gate cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)2);
4560Sstevel@tonic-gate
4570Sstevel@tonic-gate /*
4580Sstevel@tonic-gate * Initialize the cif to be "no characters"
4590Sstevel@tonic-gate */
4600Sstevel@tonic-gate cif[out_args+0] = p1275_uint2cell(CIF_SUCCESS);
4610Sstevel@tonic-gate cif[out_args+1] = p1275_uint2cell(CIF_NO_CHARACTERS);
4620Sstevel@tonic-gate
4630Sstevel@tonic-gate /*
4640Sstevel@tonic-gate * We check to see if there is an
4650Sstevel@tonic-gate * input device that has been registered.
4660Sstevel@tonic-gate */
4670Sstevel@tonic-gate polled_io = polled_input_device.polled_io;
4680Sstevel@tonic-gate
4691253Slq150181 if (polled_io == NULL ||
4701253Slq150181 polled_io->cons_polledio_ischar == NULL) {
4710Sstevel@tonic-gate
4720Sstevel@tonic-gate /*
4730Sstevel@tonic-gate * The cif structure is already set up to return
4740Sstevel@tonic-gate * no characters.
4750Sstevel@tonic-gate */
4760Sstevel@tonic-gate
4770Sstevel@tonic-gate return;
4780Sstevel@tonic-gate }
4790Sstevel@tonic-gate
4800Sstevel@tonic-gate actual = 0;
4810Sstevel@tonic-gate
4820Sstevel@tonic-gate /*
4830Sstevel@tonic-gate * Obtain the characters
4840Sstevel@tonic-gate */
4850Sstevel@tonic-gate while (polled_io->cons_polledio_ischar(
486*7416SJames.Marks@Sun.COM polled_io->cons_polledio_argument) == B_TRUE) {
4870Sstevel@tonic-gate
4880Sstevel@tonic-gate /*
4890Sstevel@tonic-gate * Make sure that we don't overrun the buffer.
4900Sstevel@tonic-gate */
4910Sstevel@tonic-gate if (actual == buflen) {
4920Sstevel@tonic-gate
4930Sstevel@tonic-gate break;
4940Sstevel@tonic-gate }
4950Sstevel@tonic-gate
4960Sstevel@tonic-gate /*
4970Sstevel@tonic-gate * Call down to the device to copy the input data into the
4980Sstevel@tonic-gate * buffer.
4990Sstevel@tonic-gate */
5000Sstevel@tonic-gate key = polled_io->cons_polledio_getchar(
501*7416SJames.Marks@Sun.COM polled_io->cons_polledio_argument);
5020Sstevel@tonic-gate
5030Sstevel@tonic-gate *(buffer + actual) = key;
5040Sstevel@tonic-gate
5050Sstevel@tonic-gate actual++;
5060Sstevel@tonic-gate }
5070Sstevel@tonic-gate
5080Sstevel@tonic-gate /*
5090Sstevel@tonic-gate * There is a special return code when there is no data.
5100Sstevel@tonic-gate */
5110Sstevel@tonic-gate if (actual == 0) {
5120Sstevel@tonic-gate
5130Sstevel@tonic-gate /*
5140Sstevel@tonic-gate * The cif structure is already set up to return
5150Sstevel@tonic-gate * no characters.
5160Sstevel@tonic-gate */
5170Sstevel@tonic-gate
5180Sstevel@tonic-gate return;
5190Sstevel@tonic-gate }
5200Sstevel@tonic-gate
5210Sstevel@tonic-gate /*
5220Sstevel@tonic-gate * Tell firmware how many characters we are sending it.
5230Sstevel@tonic-gate */
5240Sstevel@tonic-gate cif[out_args+0] = p1275_uint2cell((uint_t)CIF_SUCCESS);
5250Sstevel@tonic-gate cif[out_args+1] = p1275_uint2cell((uint_t)actual);
5260Sstevel@tonic-gate }
5270Sstevel@tonic-gate
5280Sstevel@tonic-gate /*
5290Sstevel@tonic-gate * This is the routine that firmware calls when it is giving up control of the
5300Sstevel@tonic-gate * input device. This routine, and the lower layer routines that it calls,
5310Sstevel@tonic-gate * are responsible for restoring the controller state to the state it was
5320Sstevel@tonic-gate * in before firmware took control.
5330Sstevel@tonic-gate *
5340Sstevel@tonic-gate * WARNING: This routine runs in debug mode.
5350Sstevel@tonic-gate */
5360Sstevel@tonic-gate static void
polled_take_input(cell_t * cif)5370Sstevel@tonic-gate polled_take_input(cell_t *cif)
5380Sstevel@tonic-gate {
5390Sstevel@tonic-gate cons_polledio_t *polled_io;
5400Sstevel@tonic-gate uint_t out_args;
5410Sstevel@tonic-gate
5420Sstevel@tonic-gate /*
5430Sstevel@tonic-gate * Calculate the offset of the return arguments
5440Sstevel@tonic-gate */
545*7416SJames.Marks@Sun.COM out_args = CIF_MIN_SIZE + p1275_cell2uint(cif[CIF_NUMBER_IN_ARGS]);
5460Sstevel@tonic-gate
5470Sstevel@tonic-gate /*
5480Sstevel@tonic-gate * There is one argument being passed back to firmware.
5490Sstevel@tonic-gate */
5500Sstevel@tonic-gate cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
5510Sstevel@tonic-gate cif[out_args] = p1275_uint2cell(CIF_SUCCESS);
5520Sstevel@tonic-gate
5530Sstevel@tonic-gate /*
5540Sstevel@tonic-gate * We check the pointer to see if there is an
5550Sstevel@tonic-gate * input device that has been registered.
5560Sstevel@tonic-gate */
5570Sstevel@tonic-gate polled_io = polled_input_device.polled_io;
5580Sstevel@tonic-gate
5590Sstevel@tonic-gate if (polled_io == NULL) {
5600Sstevel@tonic-gate return;
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate
5630Sstevel@tonic-gate /*
5640Sstevel@tonic-gate * Call down to the lower layers to save the state.
5650Sstevel@tonic-gate */
566*7416SJames.Marks@Sun.COM polled_io->cons_polledio_exit(polled_io->cons_polledio_argument);
5670Sstevel@tonic-gate }
5680Sstevel@tonic-gate
5690Sstevel@tonic-gate /*
5700Sstevel@tonic-gate * This is the routine that the firmware calls when
5710Sstevel@tonic-gate * it wants to write a character.
5720Sstevel@tonic-gate *
5730Sstevel@tonic-gate * WARNING: This routine runs in debug mode.
5740Sstevel@tonic-gate */
5750Sstevel@tonic-gate static void
polled_write(cell_t * cif)5760Sstevel@tonic-gate polled_write(cell_t *cif)
5770Sstevel@tonic-gate {
5780Sstevel@tonic-gate cons_polledio_t *polled_io;
5790Sstevel@tonic-gate uint_t in_args;
5800Sstevel@tonic-gate uint_t out_args;
5810Sstevel@tonic-gate uchar_t *buffer;
5820Sstevel@tonic-gate uint_t buflen;
5830Sstevel@tonic-gate
5840Sstevel@tonic-gate /*
5850Sstevel@tonic-gate * The number of arguments passed in by the firmware
5860Sstevel@tonic-gate */
5870Sstevel@tonic-gate in_args = p1275_cell2uint(cif[CIF_NUMBER_IN_ARGS]);
5880Sstevel@tonic-gate
5890Sstevel@tonic-gate /*
5900Sstevel@tonic-gate * Calculate the location of the first out arg. This location is
5910Sstevel@tonic-gate * CIF_MIN_SIZE (name + no. in args + no. out args) plus the
5920Sstevel@tonic-gate * in argument locations.
5930Sstevel@tonic-gate */
5940Sstevel@tonic-gate out_args = CIF_MIN_SIZE + in_args;
5950Sstevel@tonic-gate
5960Sstevel@tonic-gate /*
5970Sstevel@tonic-gate * The firmware should pass in a pointer to a buffer, and the
5980Sstevel@tonic-gate * number of characters it expects or expects to write.
5990Sstevel@tonic-gate * If 2 arguments are not passed in, then return an error.
6000Sstevel@tonic-gate */
6010Sstevel@tonic-gate if (in_args != 2) {
6020Sstevel@tonic-gate
6030Sstevel@tonic-gate /*
6040Sstevel@tonic-gate * Tell firmware how many arguments we are passing back.
6050Sstevel@tonic-gate */
6060Sstevel@tonic-gate cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
6070Sstevel@tonic-gate
6080Sstevel@tonic-gate
6090Sstevel@tonic-gate /*
6100Sstevel@tonic-gate * Tell the firmware that we cannot give it any characters.
6110Sstevel@tonic-gate */
6120Sstevel@tonic-gate cif[out_args] = p1275_uint2cell(CIF_FAILURE);
6130Sstevel@tonic-gate
6140Sstevel@tonic-gate return;
6150Sstevel@tonic-gate }
6160Sstevel@tonic-gate
6170Sstevel@tonic-gate /*
6180Sstevel@tonic-gate * Get the address of where to copy the characters into.
6190Sstevel@tonic-gate */
6201009Smathue buffer = (uchar_t *)(uintptr_t)p1275_cell2uint(cif[CIF_MIN_SIZE+0]);
6210Sstevel@tonic-gate
6220Sstevel@tonic-gate /*
6230Sstevel@tonic-gate * Get the length of the buffer that we can copy characters into.
6240Sstevel@tonic-gate */
6250Sstevel@tonic-gate buflen = p1275_cell2uint(cif[CIF_MIN_SIZE+1]);
6260Sstevel@tonic-gate
6270Sstevel@tonic-gate /*
6280Sstevel@tonic-gate * Make sure there is enough room in the buffer to copy the
6290Sstevel@tonic-gate * characters into.
6300Sstevel@tonic-gate */
6310Sstevel@tonic-gate if (buflen == 0) {
6320Sstevel@tonic-gate
6330Sstevel@tonic-gate /*
6340Sstevel@tonic-gate * Tell the OBP that we cannot give it any characters.
6350Sstevel@tonic-gate */
6360Sstevel@tonic-gate cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
6370Sstevel@tonic-gate
6380Sstevel@tonic-gate /*
6390Sstevel@tonic-gate * Tell the firmware that we cannot give it any characters.
6400Sstevel@tonic-gate */
6410Sstevel@tonic-gate cif[out_args] = p1275_uint2cell(CIF_FAILURE);
6420Sstevel@tonic-gate
6430Sstevel@tonic-gate return;
6440Sstevel@tonic-gate }
6450Sstevel@tonic-gate
6460Sstevel@tonic-gate
6470Sstevel@tonic-gate /*
6480Sstevel@tonic-gate * Tell the firmware how many arguments we are passing back.
6490Sstevel@tonic-gate */
6500Sstevel@tonic-gate cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)2);
6510Sstevel@tonic-gate
6520Sstevel@tonic-gate /*
6530Sstevel@tonic-gate * Initialize the cif to success
6540Sstevel@tonic-gate */
6550Sstevel@tonic-gate cif[out_args+0] = p1275_uint2cell(CIF_SUCCESS);
6560Sstevel@tonic-gate cif[out_args+1] = p1275_uint2cell(0);
6570Sstevel@tonic-gate
6580Sstevel@tonic-gate /*
6590Sstevel@tonic-gate * We check the pointer to see if there is an
6600Sstevel@tonic-gate * input device that has been registered.
6610Sstevel@tonic-gate */
6620Sstevel@tonic-gate polled_io = polled_output_device.polled_io;
6630Sstevel@tonic-gate
6640Sstevel@tonic-gate if (polled_io == NULL) {
6650Sstevel@tonic-gate
6660Sstevel@tonic-gate /*
6670Sstevel@tonic-gate * The cif is already initialized
6680Sstevel@tonic-gate */
6690Sstevel@tonic-gate return;
6700Sstevel@tonic-gate }
6710Sstevel@tonic-gate
6721253Slq150181 polled_io_cons_write(buffer, (size_t)buflen);
6730Sstevel@tonic-gate
6740Sstevel@tonic-gate /*
6750Sstevel@tonic-gate * Tell the firmware how many characters we are sending it.
6760Sstevel@tonic-gate */
6770Sstevel@tonic-gate cif[out_args+0] = p1275_uint2cell((uint_t)CIF_SUCCESS);
6780Sstevel@tonic-gate cif[out_args+1] = p1275_uint2cell((uint_t)buflen);
6790Sstevel@tonic-gate }
680