]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/ia64/ia64/ssc.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / ia64 / ia64 / ssc.c
1 /*-
2  * Copyright (c) 2000 Doug Rabson
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  *      $FreeBSD$
27  */
28 #include <sys/param.h>
29 #include <sys/bus.h>
30 #include <sys/conf.h>
31 #include <sys/cons.h>
32 #include <sys/kernel.h>
33 #include <sys/lock.h>
34 #include <sys/module.h>
35 #include <sys/mutex.h>
36 #include <sys/priv.h>
37 #include <sys/proc.h>
38 #include <sys/systm.h>
39 #include <sys/tty.h>
40 #include <machine/md_var.h>
41
42 #include <vm/vm.h>
43 #include <vm/vm_param.h>
44 #include <vm/vm_kern.h>
45 #include <vm/vm_page.h>
46 #include <vm/vm_map.h>
47 #include <vm/vm_object.h>
48 #include <vm/vm_extern.h>
49 #include <vm/vm_pageout.h>
50 #include <vm/vm_pager.h>
51
52 #define SSC_GETCHAR                     21
53 #define SSC_PUTCHAR                     31
54
55 #define SSC_POLL_HZ     50
56
57 static  d_open_t        ssc_open;
58 static  d_close_t       ssc_close;
59
60 static struct cdevsw ssc_cdevsw = {
61         .d_version =    D_VERSION,
62         .d_open =       ssc_open,
63         .d_close =      ssc_close,
64         .d_name =       "ssc",
65         .d_flags =      D_TTY | D_NEEDGIANT,
66 };
67
68 static struct tty *ssc_tp = NULL;
69 static int polltime;
70 static struct callout_handle ssc_timeouthandle
71         = CALLOUT_HANDLE_INITIALIZER(&ssc_timeouthandle);
72
73 static void     ssc_start(struct tty *);
74 static void     ssc_timeout(void *);
75 static int      ssc_param(struct tty *, struct termios *);
76 static void     ssc_stop(struct tty *, int);
77
78 static u_int64_t
79 ssc(u_int64_t in0, u_int64_t in1, u_int64_t in2, u_int64_t in3, int which)
80 {
81         register u_int64_t ret0 __asm("r8");
82
83         __asm __volatile("mov r15=%1\n\t"
84                          "break 0x80001"
85                          : "=r"(ret0)
86                          : "r"(which), "r"(in0), "r"(in1), "r"(in2), "r"(in3));
87         return ret0;
88 }
89
90 static void
91 ssc_cnprobe(struct consdev *cp)
92 {
93         sprintf(cp->cn_name, "ssccons");
94         cp->cn_pri = CN_INTERNAL;
95 }
96
97 static void
98 ssc_cninit(struct consdev *cp)
99 {
100 }
101
102 static void
103 ssc_cnterm(struct consdev *cp)
104 {
105 }
106
107 static void
108 ssc_cnattach(void *arg)
109 {
110         make_dev(&ssc_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "ssccons");
111         ssc_tp = ttyalloc();
112 }
113
114 SYSINIT(ssc_cnattach, SI_SUB_DRIVERS, SI_ORDER_ANY, ssc_cnattach, 0);
115
116 static void
117 ssc_cnputc(struct consdev *cp, int c)
118 {
119         ssc(c, 0, 0, 0, SSC_PUTCHAR);
120 }
121
122 static int
123 ssc_cngetc(struct consdev *cp)
124 {
125     int c;
126     c = ssc(0, 0, 0, 0, SSC_GETCHAR);
127     if (!c)
128             return -1;
129     return c;
130 }
131
132 static int
133 ssc_open(struct cdev *dev, int flag, int mode, struct thread *td)
134 {
135         struct tty *tp;
136         int s;
137         int error = 0, setuptimeout = 0;
138  
139         tp = dev->si_tty = ssc_tp;
140
141         s = spltty();
142         tp->t_oproc = ssc_start;
143         tp->t_param = ssc_param;
144         tp->t_stop = ssc_stop;
145         tp->t_dev = dev;
146         if ((tp->t_state & TS_ISOPEN) == 0) {
147                 tp->t_state |= TS_CARR_ON;
148                 ttyconsolemode(tp, 0);
149
150                 setuptimeout = 1;
151         } else if ((tp->t_state & TS_XCLUDE) &&
152             priv_check(td, PRIV_TTY_EXCLUSIVE)) {
153                 splx(s);
154                 return EBUSY;
155         }
156
157         splx(s);
158
159         error = ttyld_open(tp, dev);
160
161         if (error == 0 && setuptimeout) {
162                 polltime = hz / SSC_POLL_HZ;
163                 if (polltime < 1)
164                         polltime = 1;
165                 ssc_timeouthandle = timeout(ssc_timeout, tp, polltime);
166         }
167         return error;
168 }
169  
170 static int
171 ssc_close(struct cdev *dev, int flag, int mode, struct thread *td)
172 {
173         int unit = minor(dev);
174         struct tty *tp = ssc_tp;
175
176         if (unit != 0)
177                 return ENXIO;
178
179         untimeout(ssc_timeout, tp, ssc_timeouthandle);
180         ttyld_close(tp, flag);
181         tty_close(tp);
182         return 0;
183 }
184  
185 static int
186 ssc_param(struct tty *tp, struct termios *t)
187 {
188
189         return 0;
190 }
191
192 static void
193 ssc_start(struct tty *tp)
194 {
195         int s;
196
197         s = spltty();
198
199         if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
200                 ttwwakeup(tp);
201                 splx(s);
202                 return;
203         }
204
205         tp->t_state |= TS_BUSY;
206         while (tp->t_outq.c_cc != 0)
207                 ssc_cnputc(NULL, getc(&tp->t_outq));
208         tp->t_state &= ~TS_BUSY;
209
210         ttwwakeup(tp);
211         splx(s);
212 }
213
214 /*
215  * Stop output on a line.
216  */
217 static void
218 ssc_stop(struct tty *tp, int flag)
219 {
220         int s;
221
222         s = spltty();
223         if (tp->t_state & TS_BUSY)
224                 if ((tp->t_state & TS_TTSTOP) == 0)
225                         tp->t_state |= TS_FLUSH;
226         splx(s);
227 }
228
229 static void
230 ssc_timeout(void *v)
231 {
232         struct tty *tp = v;
233         int c;
234
235         while ((c = ssc_cngetc(NULL)) != -1) {
236                 if (tp->t_state & TS_ISOPEN)
237                         ttyld_rint(tp, c);
238         }
239         ssc_timeouthandle = timeout(ssc_timeout, tp, polltime);
240 }
241
242 CONSOLE_DRIVER(ssc);