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