xref: /illumos-gate/usr/src/uts/sparc/os/polled_io.c (revision 827029eb)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * This code sets up the callbacks(vx_handlers) so that the firmware may call
28  * into the kernel for console input and/or output while in the debugger.
29  * The callbacks that execute in debug mode must be careful to not
30  * allocate memory, access mutexes, etc. because most kernel services are
31  * not available during this mode.
32  *
33  * This code, and the underlying code that supports the polled input, is very
34  * hard to debug.  In order to get the code to execute, polled input must
35  * provide input to the debugger.  If anything goes wrong with the code, then
36  * it is hard to debug the debugger.  If there are any problems to debug,
37  * the following is useful:
38  *
39  * set the polled_debug variable in /etc/system
40  *	set polled_debug=1
41  *
42  * This variable will register the callbacks but will not throw the switch
43  * in the firmware.  The callbacks can be executed by hand from the firmware.
44  * Boot the system and drop down to the firmware.
45  *
46  *	ok " /os-io" select-dev
47  *
48  * The following will cause the polled_give_input to execute:
49  *	ok take
50  *
51  * The following will cause the polled_take_input to execute:
52  *	ok give
53  *
54  * The following will cause polled_read to execute:
55  *	ok read
56  */
57 
58 #include <sys/stropts.h>
59 #include <v9/sys/prom_isa.h>
60 #include <sys/devops.h>
61 #include <sys/modctl.h>
62 #include <sys/ddi.h>
63 #include <sys/sunddi.h>
64 #include <sys/promif.h>
65 #include <sys/note.h>
66 #include <sys/consdev.h>
67 #include <sys/polled_io.h>
68 #include <sys/kdi.h>
69 #ifdef sun4v
70 #include <sys/ldoms.h>
71 #endif
72 
73 /*
74  * Internal Functions
75  */
76 static void	polled_give_input(cell_t *cif);
77 static void	polled_read(cell_t *cif);
78 static void	polled_take_input(cell_t *cif);
79 
80 static void	polled_write(cell_t *cif);
81 static void	polled_io_register(cons_polledio_t *,
82 			polled_io_console_type_t, int);
83 static int	polled_io_take_console(polled_io_console_type_t, int);
84 static int	polled_io_release_console(polled_io_console_type_t, int);
85 
86 /*
87  * State information regarding the input/output device
88  */
89 static polled_device_t	polled_input_device;
90 static polled_device_t	polled_output_device;
91 static int polled_vx_handlers_init = 0;
92 
93 extern void	add_vx_handler(char *name, int flag, void (*func)(cell_t *));
94 
95 /*
96  * This is a useful flag for debugging the entry points.   This flag
97  * allows us to exercise the entry points from the firmware without
98  * switching the firmware's notion of the input device.
99  */
100 int	polled_debug = 0;
101 
102 /*
103  * This routine is called to initialize polled I/O.  We insert our entry
104  * points so that the firmware will call into this code
105  * when the switch is thrown in polled_io_take_console().
106  */
107 void
polled_io_init(void)108 polled_io_init(void)
109 {
110 
111 	/*
112 	 * Only do the initialization once
113 	 */
114 	if (polled_vx_handlers_init != 0)
115 		return;
116 #ifdef sun4v
117 	if (!domaining_enabled()) {
118 #endif
119 	/*
120 	 * Add the vx_handlers for the different functions that
121 	 * need to be accessed from firmware.
122 	 */
123 	add_vx_handler("enter-input", 1, polled_give_input);
124 
125 	add_vx_handler("read", 1, polled_read);
126 
127 	add_vx_handler("exit-input", 1, polled_take_input);
128 
129 	add_vx_handler("write", 1, polled_write);
130 #ifdef sun4v
131 	}
132 #endif
133 
134 	/*
135 	 * Initialize lock to protect multiple thread access to the
136 	 * polled_input_device structure.  This does not protect
137 	 * us from access in debug mode.
138 	 */
139 	mutex_init(&polled_input_device.polled_device_lock,
140 	    NULL, MUTEX_DRIVER, NULL);
141 
142 	/*
143 	 * Initialize lock to protect multiple thread access to the
144 	 * polled_output_device structure.  This does not protect
145 	 * us from access in debug mode.
146 	 */
147 	mutex_init(&polled_output_device.polled_device_lock,
148 	    NULL, MUTEX_DRIVER, NULL);
149 
150 	polled_vx_handlers_init = 1;
151 }
152 
153 /*
154  * Register a device for input or output.  The polled_io structure
155  * will be filled in with the callbacks that are appropriate for
156  * that device.
157  */
158 int
polled_io_register_callbacks(cons_polledio_t * polled_io,int flags)159 polled_io_register_callbacks(
160 cons_polledio_t			*polled_io,
161 int				flags
162 )
163 {
164 	/*
165 	 * If the input structure entries aren't filled in, then register this
166 	 * structure as an input device.
167 	 */
168 	if ((polled_io->cons_polledio_getchar != NULL) &&
169 	    (polled_io->cons_polledio_ischar != NULL)) {
170 
171 		polled_io_register(polled_io, POLLED_IO_CONSOLE_INPUT, flags);
172 	}
173 
174 	/*
175 	 * If the output structure entries aren't filled in, then register this
176 	 * structure as an output device.
177 	 */
178 	if (polled_io->cons_polledio_putchar != NULL) {
179 
180 		polled_io_register(polled_io, POLLED_IO_CONSOLE_OUTPUT, flags);
181 	}
182 
183 	cons_polledio = polled_io;
184 
185 	return (DDI_SUCCESS);
186 }
187 
188 /*
189  * Sends string through the polled output interfaces when the
190  * system is panicing.
191  */
192 void
polled_io_cons_write(uchar_t * text,size_t len)193 polled_io_cons_write(uchar_t *text, size_t len)
194 {
195 	cons_polledio_t *pio = polled_output_device.polled_io;
196 	int i;
197 
198 	for (i = 0; i < len; i++)
199 		pio->cons_polledio_putchar(
200 		    pio->cons_polledio_argument, text[i]);
201 }
202 
203 /*
204  * Generic internal routine for registering a polled input or output device.
205  */
206 /* ARGSUSED */
207 static void
polled_io_register(cons_polledio_t * polled_io,polled_io_console_type_t type,int flags)208 polled_io_register(
209 cons_polledio_t			*polled_io,
210 polled_io_console_type_t	type,
211 int				flags
212 )
213 {
214 	switch (type) {
215 	case POLLED_IO_CONSOLE_INPUT:
216 		/*
217 		 * Grab the device lock, because we are going to access
218 		 * protected structure entries.  We do this before the
219 		 * POLLED_IO_CONSOLE_OPEN_INPUT so that we serialize
220 		 * registration.
221 		 */
222 		mutex_enter(&polled_input_device.polled_device_lock);
223 
224 		/*
225 		 * Save the polled_io pointers so that we can access
226 		 * them later.
227 		 */
228 		polled_input_device.polled_io = polled_io;
229 
230 		mutex_exit(&polled_input_device.polled_device_lock);
231 
232 
233 		if (!polled_debug) {
234 			/*
235 			 * Tell the generic console framework to
236 			 * repoint firmware's stdin to this keyboard device.
237 			 */
238 			(void) polled_io_take_console(type, 0);
239 		}
240 
241 		break;
242 
243 	case POLLED_IO_CONSOLE_OUTPUT:
244 		/*
245 		 * Grab the device lock, because we are going to access
246 		 * protected structure entries. We do this before the
247 		 * POLLED_IO_CONSOLE_OPEN_OUTPUT so that we serialize
248 		 * registration.
249 		 */
250 		mutex_enter(&polled_output_device.polled_device_lock);
251 
252 		/*
253 		 * Save the polled_io pointers so that we can access
254 		 * them later.
255 		 */
256 		polled_output_device.polled_io = polled_io;
257 
258 		mutex_exit(&polled_output_device.polled_device_lock);
259 
260 		if (!polled_debug) {
261 			/*
262 			 * Tell the generic console framework to
263 			 * repoint firmware's stdout to the framebuffer.
264 			 */
265 			(void) polled_io_take_console(type, 0);
266 		}
267 
268 		break;
269 	}
270 }
271 
272 /*
273  * This is the routine that is called to throw the switch from the
274  * firmware's ownership of stdout/stdin to the kernel.
275  */
276 /* ARGSUSED */
277 static int
polled_io_take_console(polled_io_console_type_t type,int flags)278 polled_io_take_console(
279 polled_io_console_type_t	type,
280 int				flags
281 )
282 {
283 
284 #ifdef sun4v
285 	if (domaining_enabled())
286 		return (DDI_SUCCESS);
287 #endif
288 
289 	switch (type) {
290 	case POLLED_IO_CONSOLE_INPUT:
291 		/*
292 		 * Call into firmware to switch to the kernel I/O handling.
293 		 * We will save the old value of stdin so that we can
294 		 * restore it if the device is released.
295 		 */
296 #ifdef DEBUG_OBP
297 		/*
298 		 * This code is useful to trace through
299 		 * what the prom is doing
300 		 */
301 		prom_interpret(
302 		    "stdin @ swap ! trace-on \" /os-io\" input trace-off",
303 		    (uintptr_t)&polled_input_device.polled_old_handle,
304 		    0, 0, 0, 0);
305 #endif
306 
307 		prom_interpret(
308 		    "stdin @ swap ! \" /os-io\" open-dev stdin !",
309 		    (uintptr_t)&polled_input_device.polled_old_handle,
310 		    0, 0, 0, 0);
311 
312 		break;
313 
314 	case POLLED_IO_CONSOLE_OUTPUT:
315 		/*
316 		 * Call into firmware to switch to the kernel I/O handling.
317 		 * We will save the old value of stdout so that we can
318 		 * restore it if the device is released.
319 		 */
320 		prom_interpret("stdout @ swap ! \" /os-io\" open-dev stdout !",
321 		    (uintptr_t)&polled_output_device.polled_old_handle,
322 		    0, 0, 0, 0);
323 
324 		break;
325 	}
326 
327 	return (DDI_SUCCESS);
328 }
329 
330 /*
331  * This is the routine that the firmware calls to save any state information
332  * before using the input device.  This routine, and all of the
333  * routines that it calls, are responsible for saving any state
334  * information so that it can be restored when debug mode is over.
335  *
336  * WARNING: This routine runs in debug mode.
337  */
338 static void
polled_give_input(cell_t * cif)339 polled_give_input(cell_t *cif)
340 {
341 	cons_polledio_t		*polled_io;
342 	uint_t			out_args;
343 
344 	/*
345 	 * Calculate the offset of the return arguments
346 	 */
347 	out_args = CIF_MIN_SIZE + p1275_cell2uint(cif[CIF_NUMBER_IN_ARGS]);
348 
349 	/*
350 	 * There is one argument being passed back to firmware.
351 	 */
352 	cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
353 	cif[out_args] = p1275_uint2cell(CIF_SUCCESS);
354 
355 	/*
356 	 * We check to see if there is an
357 	 * input device that has been registered.
358 	 */
359 	polled_io = polled_input_device.polled_io;
360 
361 	if (polled_io == NULL) {
362 		return;
363 	}
364 
365 	/*
366 	 * Call down to the lower layers to save the state.
367 	 */
368 	polled_io->cons_polledio_enter(polled_io->cons_polledio_argument);
369 }
370 
371 /*
372  * This is the routine that the firmware calls
373  * when it wants to read a character.
374  * We will call to the lower layers to see if there is any input data
375  * available.
376  *
377  * WARNING: This routine runs in debug mode.
378  */
379 static void
polled_read(cell_t * cif)380 polled_read(cell_t *cif)
381 {
382 	uint_t				actual;
383 	cons_polledio_t			*polled_io;
384 	uint_t				in_args;
385 	uint_t				out_args;
386 	uchar_t				*buffer;
387 	uint_t				buflen;
388 	uchar_t				key;
389 
390 	/*
391 	 * The number of arguments passed in by the firmware
392 	 */
393 	in_args = p1275_cell2uint(cif[CIF_NUMBER_IN_ARGS]);
394 
395 	/*
396 	 * Calculate the location of the first out arg.  This location is
397 	 * CIF_MIN_SIZE plus the in argument locations.
398 	 */
399 	out_args = CIF_MIN_SIZE + in_args;
400 
401 	/*
402 	 * The firmware should pass in a pointer to a buffer, and the
403 	 * number of characters it expects or expects to write.
404 	 * If 2 arguments are not passed in, then return an error.
405 	 */
406 	if (in_args != 2) {
407 
408 		/*
409 		 * Tell firmware how many arguments we are passing back.
410 		 */
411 		cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
412 
413 		/*
414 		 * Tell the firmware that we cannot give it any characters.
415 		 */
416 		cif[out_args] = p1275_uint2cell(CIF_FAILURE);
417 
418 		return;
419 	}
420 
421 	/*
422 	 * Get the address of where to copy the characters into.
423 	 */
424 	buffer = (uchar_t *)(uintptr_t)p1275_cell2uint(cif[CIF_MIN_SIZE+0]);
425 
426 	/*
427 	 * Get the length of the buffer that we can copy characters into.
428 	 */
429 	buflen = p1275_cell2uint(cif[CIF_MIN_SIZE+1]);
430 
431 	/*
432 	 * Make sure there is enough room in the buffer to copy the
433 	 * characters into.
434 	 */
435 	if (buflen == 0) {
436 
437 		/*
438 		 * Tell the OBP that we cannot give it any characters.
439 		 */
440 		cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
441 
442 		/*
443 		 * Tell the firmware that we cannot give it any characters.
444 		 */
445 		cif[out_args] = p1275_uint2cell(CIF_FAILURE);
446 
447 		return;
448 	}
449 
450 	/*
451 	 * Pass back whether or not the operation was a success or
452 	 * failure plus the actual number of bytes in the buffer.
453 	 * Tell firmware how many arguments we are passing back.
454 	 */
455 	cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)2);
456 
457 	/*
458 	 * Initialize the cif to be "no characters"
459 	 */
460 	cif[out_args+0] = p1275_uint2cell(CIF_SUCCESS);
461 	cif[out_args+1] = p1275_uint2cell(CIF_NO_CHARACTERS);
462 
463 	/*
464 	 * We check to see if there is an
465 	 * input device that has been registered.
466 	 */
467 	polled_io = polled_input_device.polled_io;
468 
469 	if (polled_io == NULL ||
470 	    polled_io->cons_polledio_ischar == NULL) {
471 
472 		/*
473 		 * The cif structure is already set up to return
474 		 * no characters.
475 		 */
476 
477 		return;
478 	}
479 
480 	actual = 0;
481 
482 	/*
483 	 * Obtain the characters
484 	 */
485 	while (polled_io->cons_polledio_ischar(
486 	    polled_io->cons_polledio_argument) == B_TRUE) {
487 
488 		/*
489 		 * Make sure that we don't overrun the buffer.
490 		 */
491 		if (actual == buflen) {
492 
493 			break;
494 		}
495 
496 		/*
497 		 * Call down to the device to copy the input data into the
498 		 * buffer.
499 		 */
500 		key = polled_io->cons_polledio_getchar(
501 		    polled_io->cons_polledio_argument);
502 
503 		*(buffer + actual) = key;
504 
505 		actual++;
506 	}
507 
508 	/*
509 	 * There is a special return code when there is no data.
510 	 */
511 	if (actual == 0) {
512 
513 		/*
514 		 * The cif structure is already set up to return
515 		 * no characters.
516 		 */
517 
518 		return;
519 	}
520 
521 	/*
522 	 * Tell firmware how many characters we are sending it.
523 	 */
524 	cif[out_args+0] = p1275_uint2cell((uint_t)CIF_SUCCESS);
525 	cif[out_args+1] = p1275_uint2cell((uint_t)actual);
526 }
527 
528 /*
529  * This is the routine that firmware calls when it is giving up control of the
530  * input device.  This routine, and the lower layer routines that it calls,
531  * are responsible for restoring the controller state to the state it was
532  * in before firmware took control.
533  *
534  * WARNING: This routine runs in debug mode.
535  */
536 static void
polled_take_input(cell_t * cif)537 polled_take_input(cell_t *cif)
538 {
539 	cons_polledio_t		*polled_io;
540 	uint_t			out_args;
541 
542 	/*
543 	 * Calculate the offset of the return arguments
544 	 */
545 	out_args = CIF_MIN_SIZE + p1275_cell2uint(cif[CIF_NUMBER_IN_ARGS]);
546 
547 	/*
548 	 * There is one argument being passed back to firmware.
549 	 */
550 	cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
551 	cif[out_args] = p1275_uint2cell(CIF_SUCCESS);
552 
553 	/*
554 	 * We check the pointer to see if there is an
555 	 * input device that has been registered.
556 	 */
557 	polled_io = polled_input_device.polled_io;
558 
559 	if (polled_io == NULL) {
560 		return;
561 	}
562 
563 	/*
564 	 * Call down to the lower layers to save the state.
565 	 */
566 	polled_io->cons_polledio_exit(polled_io->cons_polledio_argument);
567 }
568 
569 /*
570  * This is the routine that the firmware calls when
571  * it wants to write a character.
572  *
573  * WARNING: This routine runs in debug mode.
574  */
575 static void
polled_write(cell_t * cif)576 polled_write(cell_t *cif)
577 {
578 	cons_polledio_t			*polled_io;
579 	uint_t				in_args;
580 	uint_t				out_args;
581 	uchar_t				*buffer;
582 	uint_t				buflen;
583 
584 	/*
585 	 * The number of arguments passed in by the firmware
586 	 */
587 	in_args = p1275_cell2uint(cif[CIF_NUMBER_IN_ARGS]);
588 
589 	/*
590 	 * Calculate the location of the first out arg.  This location is
591 	 * CIF_MIN_SIZE (name + no. in args + no. out args) plus the
592 	 * in argument locations.
593 	 */
594 	out_args = CIF_MIN_SIZE + in_args;
595 
596 	/*
597 	 * The firmware should pass in a pointer to a buffer, and the
598 	 * number of characters it expects or expects to write.
599 	 * If 2 arguments are not passed in, then return an error.
600 	 */
601 	if (in_args != 2) {
602 
603 		/*
604 		 * Tell firmware how many arguments we are passing back.
605 		 */
606 		cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
607 
608 
609 		/*
610 		 * Tell the firmware that we cannot give it any characters.
611 		 */
612 		cif[out_args] = p1275_uint2cell(CIF_FAILURE);
613 
614 		return;
615 	}
616 
617 	/*
618 	 * Get the address of where to copy the characters into.
619 	 */
620 	buffer = (uchar_t *)(uintptr_t)p1275_cell2uint(cif[CIF_MIN_SIZE+0]);
621 
622 	/*
623 	 * Get the length of the buffer that we can copy characters into.
624 	 */
625 	buflen = p1275_cell2uint(cif[CIF_MIN_SIZE+1]);
626 
627 	/*
628 	 * Make sure there is enough room in the buffer to copy the
629 	 * characters into.
630 	 */
631 	if (buflen == 0) {
632 
633 		/*
634 		 * Tell the OBP that we cannot give it any characters.
635 		 */
636 		cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)1);
637 
638 		/*
639 		 * Tell the firmware that we cannot give it any characters.
640 		 */
641 		cif[out_args] = p1275_uint2cell(CIF_FAILURE);
642 
643 		return;
644 	}
645 
646 
647 	/*
648 	 * Tell the firmware how many arguments we are passing back.
649 	 */
650 	cif[CIF_NUMBER_OUT_ARGS] = p1275_uint2cell((uint_t)2);
651 
652 	/*
653 	 * Initialize the cif to success
654 	 */
655 	cif[out_args+0] = p1275_uint2cell(CIF_SUCCESS);
656 	cif[out_args+1] = p1275_uint2cell(0);
657 
658 	/*
659 	 * We check the pointer to see if there is an
660 	 * input device that has been registered.
661 	 */
662 	polled_io = polled_output_device.polled_io;
663 
664 	if (polled_io == NULL) {
665 
666 		/*
667 		 * The cif is already initialized
668 		 */
669 		return;
670 	}
671 
672 	polled_io_cons_write(buffer, (size_t)buflen);
673 
674 	/*
675 	 * Tell the firmware how many characters we are sending it.
676 	 */
677 	cif[out_args+0] = p1275_uint2cell((uint_t)CIF_SUCCESS);
678 	cif[out_args+1] = p1275_uint2cell((uint_t)buflen);
679 }
680