No empty .Rs/.Re
[netbsd-mini2440.git] / sys / dev / cons.c
blob269954e33cf0103c61ce2424a1345e761489eaa7
1 /* $NetBSD: cons.c,v 1.65 2008/01/24 17:32:52 ad Exp $ */
3 /*
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * the Systems Programming Group of the University of Utah Computer
9 * Science Department.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
35 * from: Utah $Hdr: cons.c 1.7 92/01/21$
37 * @(#)cons.c 8.2 (Berkeley) 1/12/94
41 * Copyright (c) 1988 University of Utah.
43 * This code is derived from software contributed to Berkeley by
44 * the Systems Programming Group of the University of Utah Computer
45 * Science Department.
47 * Redistribution and use in source and binary forms, with or without
48 * modification, are permitted provided that the following conditions
49 * are met:
50 * 1. Redistributions of source code must retain the above copyright
51 * notice, this list of conditions and the following disclaimer.
52 * 2. Redistributions in binary form must reproduce the above copyright
53 * notice, this list of conditions and the following disclaimer in the
54 * documentation and/or other materials provided with the distribution.
55 * 3. All advertising materials mentioning features or use of this software
56 * must display the following acknowledgement:
57 * This product includes software developed by the University of
58 * California, Berkeley and its contributors.
59 * 4. Neither the name of the University nor the names of its contributors
60 * may be used to endorse or promote products derived from this software
61 * without specific prior written permission.
63 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
64 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
66 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
67 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
69 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
73 * SUCH DAMAGE.
75 * from: Utah $Hdr: cons.c 1.7 92/01/21$
77 * @(#)cons.c 8.2 (Berkeley) 1/12/94
80 #include <sys/cdefs.h>
81 __KERNEL_RCSID(0, "$NetBSD: cons.c,v 1.65 2008/01/24 17:32:52 ad Exp $");
83 #include <sys/param.h>
84 #include <sys/proc.h>
85 #include <sys/systm.h>
86 #include <sys/buf.h>
87 #include <sys/ioctl.h>
88 #include <sys/poll.h>
89 #include <sys/tty.h>
90 #include <sys/file.h>
91 #include <sys/conf.h>
92 #include <sys/vnode.h>
93 #include <sys/kauth.h>
94 #include <sys/mutex.h>
96 #include <dev/cons.h>
98 dev_type_open(cnopen);
99 dev_type_close(cnclose);
100 dev_type_read(cnread);
101 dev_type_write(cnwrite);
102 dev_type_ioctl(cnioctl);
103 dev_type_poll(cnpoll);
104 dev_type_kqfilter(cnkqfilter);
106 static bool cn_redirect(dev_t *, int, int *);
108 const struct cdevsw cons_cdevsw = {
109 cnopen, cnclose, cnread, cnwrite, cnioctl,
110 nostop, notty, cnpoll, nommap, cnkqfilter, D_TTY
113 struct tty *constty = NULL; /* virtual console output device */
114 struct consdev *cn_tab; /* physical console device info */
115 struct vnode *cn_devvp[2]; /* vnode for underlying device. */
118 cnopen(dev_t dev, int flag, int mode, struct lwp *l)
120 dev_t cndev;
121 int unit, error;
123 unit = minor(dev);
124 if (unit > 1)
125 return ENODEV;
127 if (cn_tab == NULL)
128 return (0);
131 * always open the 'real' console device, so we don't get nailed
132 * later. This follows normal device semantics; they always get
133 * open() calls.
135 cndev = cn_tab->cn_dev;
136 if (cndev == NODEV) {
138 * This is most likely an error in the console attach
139 * code. Panicking looks better than jumping into nowhere
140 * through cdevsw below....
142 panic("cnopen: no console device");
144 if (dev == cndev) {
146 * This causes cnopen() to be called recursively, which
147 * is generally a bad thing. It is often caused when
148 * dev == 0 and cn_dev has not been set, but was probably
149 * initialised to 0.
151 panic("cnopen: cn_tab->cn_dev == dev");
153 if (cn_devvp[unit] != NULLVP)
154 return 0;
155 if ((error = cdevvp(cndev, &cn_devvp[unit])) != 0)
156 printf("cnopen: unable to get vnode reference\n");
157 error = vn_lock(cn_devvp[unit], LK_EXCLUSIVE | LK_RETRY);
158 if (error == 0) {
159 error = VOP_OPEN(cn_devvp[unit], flag, kauth_cred_get());
160 VOP_UNLOCK(cn_devvp[unit], 0);
162 return error;
166 cnclose(dev_t dev, int flag, int mode, struct lwp *l)
168 struct vnode *vp;
169 int unit, error;
171 unit = minor(dev);
173 if (cn_tab == NULL)
174 return (0);
176 vp = cn_devvp[unit];
177 cn_devvp[unit] = NULL;
178 error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
179 if (error == 0) {
180 error = VOP_CLOSE(vp, flag, kauth_cred_get());
181 VOP_UNLOCK(vp, 0);
183 return error;
187 cnread(dev_t dev, struct uio *uio, int flag)
189 int error;
192 * If we would redirect input, punt. This will keep strange
193 * things from happening to people who are using the real
194 * console. Nothing should be using /dev/console for
195 * input (except a shell in single-user mode, but then,
196 * one wouldn't TIOCCONS then).
198 if (!cn_redirect(&dev, 1, &error))
199 return error;
200 return cdev_read(dev, uio, flag);
204 cnwrite(dev_t dev, struct uio *uio, int flag)
206 int error;
208 /* Redirect output, if that's appropriate. */
209 if (!cn_redirect(&dev, 0, &error))
210 return error;
211 return cdev_write(dev, uio, flag);
215 cnioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
217 int error;
219 error = 0;
222 * Superuser can always use this to wrest control of console
223 * output from the "virtual" console.
225 if (cmd == TIOCCONS && constty != NULL) {
226 error = kauth_authorize_generic(l->l_cred,
227 KAUTH_GENERIC_ISSUSER, NULL);
228 if (!error)
229 constty = NULL;
230 return (error);
234 * Redirect the ioctl, if that's appropriate.
235 * Note that strange things can happen, if a program does
236 * ioctls on /dev/console, then the console is redirected
237 * out from under it.
239 if (!cn_redirect(&dev, 0, &error))
240 return error;
241 return cdev_ioctl(dev, cmd, data, flag, l);
244 /*ARGSUSED*/
246 cnpoll(dev_t dev, int events, struct lwp *l)
248 int error;
251 * Redirect the poll, if that's appropriate.
252 * I don't want to think of the possible side effects
253 * of console redirection here.
255 if (!cn_redirect(&dev, 0, &error))
256 return POLLHUP;
257 return cdev_poll(dev, events, l);
260 /*ARGSUSED*/
262 cnkqfilter(dev_t dev, struct knote *kn)
264 int error;
267 * Redirect the kqfilter, if that's appropriate.
268 * I don't want to think of the possible side effects
269 * of console redirection here.
271 if (!cn_redirect(&dev, 0, &error))
272 return error;
273 return cdev_kqfilter(dev, kn);
277 cngetc(void)
279 if (cn_tab == NULL)
280 return (0);
281 return ((*cn_tab->cn_getc)(cn_tab->cn_dev));
285 cngetsn(char *cp, int size)
287 char *lp;
288 int c, len;
290 cnpollc(1);
292 lp = cp;
293 len = 0;
294 for (;;) {
295 c = cngetc();
296 switch (c) {
297 case '\n':
298 case '\r':
299 printf("\n");
300 *lp++ = '\0';
301 cnpollc(0);
302 return (len);
303 case '\b':
304 case '\177':
305 case '#':
306 if (len) {
307 --len;
308 --lp;
309 printf("\b \b");
311 continue;
312 case '@':
313 case 'u'&037: /* CTRL-u */
314 len = 0;
315 lp = cp;
316 printf("\n");
317 continue;
318 default:
319 if (len + 1 >= size || c < ' ') {
320 printf("\007");
321 continue;
323 printf("%c", c);
324 ++len;
325 *lp++ = c;
330 void
331 cnputc(int c)
334 if (cn_tab == NULL)
335 return;
337 if (c) {
338 (*cn_tab->cn_putc)(cn_tab->cn_dev, c);
339 if (c == '\n')
340 (*cn_tab->cn_putc)(cn_tab->cn_dev, '\r');
344 void
345 cnpollc(int on)
347 static int refcount = 0;
349 if (cn_tab == NULL)
350 return;
351 if (!on)
352 --refcount;
353 if (refcount == 0)
354 (*cn_tab->cn_pollc)(cn_tab->cn_dev, on);
355 if (on)
356 ++refcount;
359 void
360 nullcnpollc(dev_t dev, int on)
365 void
366 cnbell(u_int pitch, u_int period, u_int volume)
369 if (cn_tab == NULL || cn_tab->cn_bell == NULL)
370 return;
371 (*cn_tab->cn_bell)(cn_tab->cn_dev, pitch, period, volume);
374 void
375 cnflush(void)
377 if (cn_tab == NULL || cn_tab->cn_flush == NULL)
378 return;
379 (*cn_tab->cn_flush)(cn_tab->cn_dev);
382 void
383 cnhalt(void)
385 if (cn_tab == NULL || cn_tab->cn_halt == NULL)
386 return;
387 (*cn_tab->cn_halt)(cn_tab->cn_dev);
391 * Redirect output, if that's appropriate. If there's no real console,
392 * return ENXIO.
394 * Call with tty_mutex held.
396 static bool
397 cn_redirect(dev_t *devp, int is_read, int *error)
399 dev_t dev = *devp;
401 *error = ENXIO;
402 if (constty != NULL && minor(dev) == 0 &&
403 (cn_tab == NULL || (cn_tab->cn_pri != CN_REMOTE))) {
404 if (is_read) {
405 *error = 0;
406 return false;
408 dev = constty->t_dev;
409 } else if (cn_tab == NULL)
410 return false;
411 else
412 dev = cn_tab->cn_dev;
413 *devp = dev;
414 return true;