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
polled_io_init(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
polled_io_register_callbacks(cons_polledio_t * polled_io,int flags)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
polled_io_unregister_callbacks(cons_polledio_t * polled_io,int flags)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
polled_io_fini()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
polled_io_register(cons_polledio_t * polled_io,polled_io_console_type_t type,int flags)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
polled_io_unregister(polled_io_console_type_t type,int flags)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
polled_io_take_console(polled_io_console_type_t type,int flags)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
polled_io_release_console(polled_io_console_type_t type,int flags)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
polled_give_input(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
polled_take_input(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
polled_give_output()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
polled_take_output(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