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