1 /*        $NetBSD: rcons_kern.c,v 1.22 2009/03/14 15:36:20 dsl Exp $ */
2 
3 /*
4  * Copyright (c) 1991, 1993
5  *        The Regents of the University of California.  All rights reserved.
6  *
7  * This software was developed by the Computer Systems Engineering group
8  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9  * contributed to Berkeley.
10  *
11  * All advertising materials mentioning features or use of this software
12  * must display the following acknowledgement:
13  *        This product includes software developed by the University of
14  *        California, Lawrence Berkeley Laboratory.
15  *
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that the following conditions
18  * are met:
19  * 1. Redistributions of source code must retain the above copyright
20  *    notice, this list of conditions and the following disclaimer.
21  * 2. Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in the
23  *    documentation and/or other materials provided with the distribution.
24  * 3. Neither the name of the University nor the names of its contributors
25  *    may be used to endorse or promote products derived from this software
26  *    without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38  * SUCH DAMAGE.
39  *
40  *        @(#)rcons_kern.c    8.1 (Berkeley) 6/11/93
41  */
42 
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: rcons_kern.c,v 1.22 2009/03/14 15:36:20 dsl Exp $");
45 
46 #include <sys/param.h>
47 #include <sys/device.h>
48 #include <sys/kernel.h>
49 #include <sys/systm.h>
50 #include <sys/ioctl.h>
51 #include <sys/tty.h>
52 #include <sys/proc.h>
53 
54 #include <dev/rcons/raster.h>
55 #include <dev/rcons/rcons.h>
56 
57 static void rcons_belltmr(void *);
58 
59 static struct rconsole *mydevicep; /* XXX */
60 static void rcons_output(struct tty *);
61 
62 void
rcons_cnputc(int c)63 rcons_cnputc(int c)
64 {
65           char buf[1];
66           long attr;
67 
68           /* Swap in kernel attribute */
69           attr = mydevicep->rc_attr;
70           mydevicep->rc_attr = mydevicep->rc_kern_attr;
71 
72           if (c == '\n')
73                     rcons_puts(mydevicep, "\r\n", 2);
74           else {
75                     buf[0] = c;
76                     rcons_puts(mydevicep, buf, 1);
77           }
78 
79           /* Swap out kernel attribute */
80           mydevicep->rc_attr = attr;
81 }
82 
83 static void
rcons_output(struct tty * tp)84 rcons_output(struct tty *tp)
85 {
86           int s, n;
87           char buf[OBUFSIZ];
88 
89           s = spltty();
90           if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) {
91                     splx(s);
92                     return;
93           }
94           tp->t_state |= TS_BUSY;
95           splx(s);
96           n = q_to_b(&tp->t_outq, buf, sizeof(buf));
97           rcons_puts(mydevicep, buf, n);
98 
99           s = spltty();
100           tp->t_state &= ~TS_BUSY;
101           /* Come back if there's more to do */
102           if (ttypull(tp)) {
103                     tp->t_state |= TS_TIMEOUT;
104                     callout_schedule(&tp->t_rstrt_ch, 1);
105           }
106           splx(s);
107 }
108 
109 /* Ring the console bell */
110 void
rcons_bell(struct rconsole * rc)111 rcons_bell(struct rconsole *rc)
112 {
113           int i, s;
114 
115           if (rc->rc_bits & FB_VISBELL) {
116                     /* invert the screen twice */
117                     i = ((rc->rc_bits & FB_INVERT) == 0);
118                     rcons_invert(rc, i);
119                     rcons_invert(rc, i ^ 1);
120           }
121 
122           s = splhigh();
123           if (rc->rc_belldepth++) {
124                     if (rc->rc_belldepth > 3)
125                               rc->rc_belldepth = 3;
126                     splx(s);
127           } else {
128                     rc->rc_ringing = 1;
129                     splx(s);
130                     (*rc->rc_bell)(1);
131                     /* XXX Chris doesn't like the following divide */
132                     callout_reset(&rc->rc_belltmr_ch, hz / 10,
133                         rcons_belltmr, rc);
134           }
135 }
136 
137 /* Bell timer service routine */
138 static void
rcons_belltmr(void * p)139 rcons_belltmr(void *p)
140 {
141           struct rconsole *rc = p;
142           int s = splhigh(), i;
143 
144           if (rc->rc_ringing) {
145                     rc->rc_ringing = 0;
146                     i = --rc->rc_belldepth;
147                     splx(s);
148                     (*rc->rc_bell)(0);
149                     if (i != 0)
150                               /* XXX Chris doesn't like the following divide */
151                               callout_reset(&rc->rc_belltmr_ch, hz / 30,
152                                   rcons_belltmr, rc);
153           } else {
154                     rc->rc_ringing = 1;
155                     splx(s);
156                     (*rc->rc_bell)(1);
157                     callout_reset(&rc->rc_belltmr_ch, hz / 10,
158                         rcons_belltmr, rc);
159           }
160 }
161 
162 void
rcons_init(struct rconsole * rc,int clear)163 rcons_init(struct rconsole *rc, int clear)
164 {
165           mydevicep = rc;
166 
167           callout_init(&rc->rc_belltmr_ch, 0);
168 
169           /* Initialize operations set, clear screen and turn cursor on */
170           rcons_init_ops(rc);
171           if (clear) {
172                     rc->rc_col = 0;
173                     rc->rc_row = 0;
174                     rcons_clear2eop(rc);
175           }
176           rcons_cursor(rc);
177 }
178 
179 void
rcons_ttyinit(struct tty * tp)180 rcons_ttyinit(struct tty *tp)
181 {
182           /* XXX this should go away */
183           struct rconsole *rc = mydevicep;
184           struct winsize *ws;
185 
186           if (rc == NULL)
187                     return;
188 
189           /* Let the system know how big the console is */
190           ws = &tp->t_winsize;
191           ws->ws_row = rc->rc_maxrow;
192           ws->ws_col = rc->rc_maxcol;
193           ws->ws_xpixel = rc->rc_width;
194           ws->ws_ypixel = rc->rc_height;
195 
196           /* Initialization done; hook us up */
197           tp->t_oproc = rcons_output;
198           /*tp->t_stop = (void (*)()) nullop;*/
199 }
200