xref: /illumos-gate/usr/src/uts/intel/io/polled_io.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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