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