1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/stropts.h> 29 #include <sys/devops.h> 30 #include <sys/modctl.h> 31 #include <sys/ddi.h> 32 #include <sys/sunddi.h> 33 #include <sys/promif.h> 34 #include <sys/note.h> 35 #include <sys/consdev.h> 36 #include <sys/polled_io.h> 37 38 /* 39 * consconfig is aware of which devices are the stdin and stout. The 40 * post-attach/pre-detach functions are an extension of consconfig because 41 * they know about the dynamic changes to the stdin device. Neither an 42 * individual driver nor the DDI framework knows what device is really the 43 * stdin. 44 */ 45 /* 46 * Issues: 47 * o There are probably race conditions between vx_handler for "read" 48 * being called by OBP and the update of the polled_input_t 49 * structure. We need to be careful how the structure is updated. 50 * 51 * Solaris/Intel note: While OBP is not in the picture, there are probably 52 * similar issues with kmdb. 53 */ 54 55 #if defined(MAYBE_SOMETIME) 56 static void polled_give_input(void); 57 static void polled_take_input(void); 58 static void polled_give_output(void); 59 static void polled_take_output(void); 60 61 static void polled_io_register(cons_polledio_t *, 62 polled_io_console_type_t, int); 63 64 static void polled_io_unregister(polled_io_console_type_t, int); 65 66 67 /* 68 * Make the registered device become the console for OBP 69 */ 70 static int polled_io_take_console(polled_io_console_type_t, int); 71 72 /* 73 * Restore the old console device for OBP. 74 */ 75 static int polled_io_release_console(polled_io_console_type_t, int); 76 #endif /* MAYBE_SOMETIME */ 77 78 static polled_device_t polled_input_device; 79 static polled_device_t polled_output_device; 80 81 /* 82 * This routine is called to initialize polled I/O. We insert our entry 83 * points so that OBP will call into this code when the switch is thrown 84 * in polled_io_take_console(). 85 */ 86 void 87 polled_io_init(void) 88 { 89 /* 90 * Initialize lock to protect multiple thread access to the 91 * polled_input_device structure. This does not protect 92 * us from access in OBP mode. 93 */ 94 mutex_init(&polled_input_device.polled_device_lock, 95 NULL, MUTEX_DRIVER, NULL); 96 97 /* 98 * Initialize lock to protect multiple thread access to the 99 * polled_output_device structure. This does not protect 100 * us from access in OBP mode. 101 */ 102 mutex_init(&polled_output_device.polled_device_lock, 103 NULL, MUTEX_DRIVER, NULL); 104 } 105 106 /* 107 * Register a device for input or output. The polled_io structure 108 * will be filled in with the callbacks that are appropriate for 109 * that device. 110 */ 111 int 112 polled_io_register_callbacks( 113 cons_polledio_t *polled_io, 114 int flags 115 ) 116 { 117 #if defined(MAYBE_SOMETIME) 118 /* 119 * If the input structure entries are filled in, then register this 120 * structure as an input device. 121 */ 122 if ((polled_io->cons_polledio_getchar != NULL) && 123 (polled_io->cons_polledio_ischar != NULL)) { 124 125 polled_io_register(polled_io, 126 POLLED_IO_CONSOLE_INPUT, flags); 127 } 128 129 /* 130 * If the output structure entries are filled in, then register this 131 * structure as an output device. 132 */ 133 if (polled_io->cons_polledio_putchar != NULL) { 134 135 polled_io_register(polled_io, 136 POLLED_IO_CONSOLE_OUTPUT, flags); 137 } 138 #else 139 _NOTE(ARGUNUSED(flags)) 140 cons_polledio = polled_io; 141 #endif 142 143 return (DDI_SUCCESS); 144 } 145 146 /* 147 * Unregister a device for console input/output. 148 */ 149 int 150 polled_io_unregister_callbacks( 151 cons_polledio_t *polled_io, 152 int flags 153 ) 154 { 155 #if defined(MAYBE_SOMETIME) 156 /* 157 * If polled_io is being used for input, then unregister it. 158 */ 159 if (polled_io == polled_input_device.polled_io) { 160 161 polled_io_unregister( 162 POLLED_IO_CONSOLE_INPUT, flags); 163 } 164 165 /* 166 * If polled_io is being used for output, then unregister it. 167 */ 168 if (polled_io == polled_output_device.polled_io) { 169 170 polled_io_unregister( 171 POLLED_IO_CONSOLE_OUTPUT, flags); 172 } 173 #else 174 _NOTE(ARGUNUSED(polled_io,flags)) 175 #endif /* MAYBE_SOMETIME */ 176 177 return (DDI_SUCCESS); 178 } 179 180 /* 181 * This routine is called when we are done handling polled io. We will 182 * remove all of our handlers and destroy any memory that we have allocated. 183 */ 184 void 185 polled_io_fini() 186 { 187 /* 188 * Destroy the mutexes, we will not need them anymore. 189 */ 190 mutex_destroy(&polled_input_device.polled_device_lock); 191 192 mutex_destroy(&polled_output_device.polled_device_lock); 193 } 194 195 #if defined(MAYBE_SOMETIME) 196 /* 197 * Generic internal routine for registering a polled input or output device. 198 */ 199 /* ARGSUSED */ 200 static void 201 polled_io_register( 202 cons_polledio_t *polled_io, 203 polled_io_console_type_t type, 204 int flags 205 ) 206 { 207 switch (type) { 208 case POLLED_IO_CONSOLE_INPUT: 209 /* 210 * Grab the device lock, because we are going to access 211 * protected structure entries. We do this before the 212 * POLLED_IO_CONSOLE_OPEN_INPUT so that we serialize 213 * registration. 214 */ 215 mutex_enter(&polled_input_device.polled_device_lock); 216 217 /* 218 * Save the polled_io pointers so that we can access 219 * them later. 220 */ 221 polled_input_device.polled_io = polled_io; 222 223 mutex_exit(&polled_input_device.polled_device_lock); 224 225 /* 226 * Tell the generic console framework to 227 * repoint OBP's stdin to this keyboard device. 228 */ 229 (void) polled_io_take_console(type, 0); 230 231 break; 232 233 case POLLED_IO_CONSOLE_OUTPUT: 234 /* 235 * Grab the device lock, because we are going to access 236 * protected structure entries. We do this before the 237 * POLLED_IO_CONSOLE_OPEN_OUTPUT so that we serialize 238 * registration. 239 */ 240 mutex_enter(&polled_output_device.polled_device_lock); 241 242 /* 243 * Save the polled_io pointers so that we can access 244 * them later. 245 */ 246 polled_input_device.polled_io = polled_io; 247 248 mutex_exit(&polled_output_device.polled_device_lock); 249 250 break; 251 } 252 } 253 254 /* 255 * Generic internal routine for unregistering a polled input or output device. 256 */ 257 /* ARGSUSED */ 258 static void 259 polled_io_unregister( 260 polled_io_console_type_t type, 261 int flags 262 ) 263 { 264 switch (type) { 265 case POLLED_IO_CONSOLE_INPUT: 266 /* 267 * Tell the generic console framework to restore OBP's 268 * old stdin pointers. 269 */ 270 (void) polled_io_release_console(type, 0); 271 272 /* 273 * Grab the device lock, because we are going to access 274 * protected structure entries. 275 */ 276 mutex_enter(&polled_input_device.polled_device_lock); 277 278 /* 279 * We are closing the device, so get the value for the op 280 * pointer. We use the polled_io structure to determine if 281 * there is a device registered, so null the dev_ops 282 * structure. 283 */ 284 polled_input_device.polled_io = NULL; 285 286 mutex_exit(&polled_input_device.polled_device_lock); 287 288 break; 289 290 case POLLED_IO_CONSOLE_OUTPUT: 291 /* 292 * Grab the device lock, because we are going to access 293 * protected structure entries. 294 */ 295 mutex_enter(&polled_output_device.polled_device_lock); 296 297 /* 298 * We are closing the device, so get the value for the op 299 * pointer. We use the polled_io structure to determine if 300 * there is a device registered. 301 */ 302 polled_output_device.polled_io = NULL; 303 304 mutex_exit(&polled_output_device.polled_device_lock); 305 306 break; 307 } 308 } 309 310 /* 311 * This is the routine that is called to throw the switch from boot 312 * ownership of stdout/stdin to the kernel. 313 */ 314 /* ARGSUSED */ 315 static int 316 polled_io_take_console( 317 polled_io_console_type_t type, 318 int flags 319 ) 320 { 321 switch (type) { 322 case POLLED_IO_CONSOLE_INPUT: 323 /* 324 * Perhaps this should be where we switch *sysp 325 */ 326 break; 327 328 case POLLED_IO_CONSOLE_OUTPUT: 329 /* 330 * Perhaps this should be where we switch *sysp 331 */ 332 break; 333 } 334 335 return (DDI_SUCCESS); 336 } 337 338 /* 339 * This routine gives control of console input/output back to ???. 340 * 341 * Solaris/Intel has nobody to give it back to. Hope we don't get here! 342 */ 343 /* ARGSUSED */ 344 static int 345 polled_io_release_console( 346 polled_io_console_type_t type, 347 int flags 348 ) 349 { 350 cmn_err(CE_WARN, 351 "polled_io_release_console: nobody to hand console back to"); 352 353 return (DDI_SUCCESS); 354 } 355 356 /* 357 * This is the routine that kmdb calls to save any state information 358 * before using the input device. This routine, and all of the 359 * routines that it calls, are responsible for saving any state 360 * information so that it can be restored when polled mode is over. 361 */ 362 static void 363 polled_give_input(void) 364 { 365 cons_polledio_t *polled_io; 366 367 /* 368 * We check the dev_ops pointer to see if there is an 369 * input device that has been registered. 370 */ 371 polled_io = polled_input_device.polled_io; 372 373 if (polled_io == NULL || polled_io->cons_polledio_enter == NULL) { 374 return; 375 } 376 377 /* 378 * Call down to the lower layers to save the state. 379 */ 380 polled_io->cons_polledio_enter( 381 polled_io->cons_polledio_argument); 382 } 383 384 /* 385 * This is the routine that kmdb calls when it is giving up control of the 386 * input device. This routine, and the lower layer routines that it calls, 387 * are responsible for restoring the controller state to the state it was 388 * in before kmdb took control. 389 */ 390 static void 391 polled_take_input(void) 392 { 393 cons_polledio_t *polled_io; 394 395 /* 396 * We check the dev_ops pointer to see if there is an 397 * input device that has been registered. 398 */ 399 polled_io = polled_input_device.polled_io; 400 401 if (polled_io == NULL || polled_io->cons_polledio_exit == NULL) { 402 return; 403 } 404 405 /* 406 * Call down to the lower layers to save the state. 407 */ 408 polled_io->cons_polledio_exit( 409 polled_io->cons_polledio_argument); 410 } 411 412 /* 413 * This is the routine that kmdb calls to save any state information 414 * before using the output device. This routine, and all of the 415 * routines that it calls, are responsible for saving any state 416 * information so that it can be restored when polled mode is over. 417 */ 418 static void 419 polled_give_output() 420 { 421 cons_polledio_t *polled_io; 422 423 /* 424 * We check the dev_ops pointer to see if there is an 425 * output device that has been registered. 426 */ 427 polled_io = polled_output_device.polled_io; 428 429 if (polled_io == NULL || polled_io->cons_polledio_enter == NULL) { 430 return; 431 } 432 433 /* 434 * Call down to the lower layers to save the state. 435 */ 436 polled_io->cons_polledio_enter( 437 polled_io->cons_polledio_argument); 438 } 439 440 /* 441 * This is the routine that kmdb calls when it is giving up control of the 442 * output device. This routine, and the lower layer routines that it calls, 443 * are responsible for restoring the controller state to the state it was 444 * in before kmdb took control. 445 */ 446 static void 447 polled_take_output(void) 448 { 449 cons_polledio_t *polled_io; 450 451 /* 452 * We check the dev_ops pointer to see if there is an 453 * output device that has been registered. 454 */ 455 polled_io = polled_output_device.polled_io; 456 457 if (polled_io == NULL || polled_io->cons_polledio_exit == NULL) { 458 return; 459 } 460 461 /* 462 * Call down to the lower layers to save the state. 463 */ 464 polled_io->cons_polledio_exit( 465 polled_io->cons_polledio_argument); 466 } 467 #endif /* MAYBE_SOMETIME */ 468