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