xref: /netbsd/sys/arch/alpha/alpha/promcons.c (revision bf9ec67e)
1 /* $NetBSD: promcons.c,v 1.19 2002/03/17 19:40:26 atatat Exp $ */
2 
3 /*
4  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
5  * All rights reserved.
6  *
7  * Author: Chris G. Demetriou
8  *
9  * Permission to use, copy, modify and distribute this software and
10  * its documentation is hereby granted, provided that both the copyright
11  * notice and this permission notice appear in all copies of the
12  * software, derivative works or modified versions, and any portions
13  * thereof, and that both notices appear in supporting documentation.
14  *
15  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
17  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18  *
19  * Carnegie Mellon requests users of this software to return to
20  *
21  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
22  *  School of Computer Science
23  *  Carnegie Mellon University
24  *  Pittsburgh PA 15213-3890
25  *
26  * any improvements or extensions that they make and grant Carnegie the
27  * rights to redistribute these changes.
28  */
29 
30 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
31 
32 __KERNEL_RCSID(0, "$NetBSD: promcons.c,v 1.19 2002/03/17 19:40:26 atatat Exp $");
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/ioctl.h>
37 #include <sys/select.h>
38 #include <sys/tty.h>
39 #include <sys/proc.h>
40 #include <sys/user.h>
41 #include <sys/file.h>
42 #include <sys/uio.h>
43 #include <sys/kernel.h>
44 #include <sys/syslog.h>
45 #include <sys/types.h>
46 #include <sys/device.h>
47 
48 #include <uvm/uvm_extern.h>
49 
50 #include <machine/conf.h>
51 #include <machine/prom.h>
52 
53 #ifdef _PMAP_MAY_USE_PROM_CONSOLE
54 
55 #define	PROM_POLL_HZ	50
56 
57 static struct  tty *prom_tty[1];
58 static int polltime;
59 
60 void	promstart(struct tty *);
61 void	promtimeout(void *);
62 int	promparam(struct tty *, struct termios *);
63 
64 struct callout prom_ch = CALLOUT_INITIALIZER;
65 
66 int
67 promopen(dev_t dev, int flag, int mode, struct proc *p)
68 {
69 	int unit = minor(dev);
70 	struct tty *tp;
71 	int s;
72 	int error = 0, setuptimeout = 0;
73 
74 	if (!pmap_uses_prom_console() || unit >= 1)
75 		return ENXIO;
76 
77 	s = spltty();
78 
79 	if (!prom_tty[unit]) {
80 		tp = prom_tty[unit] = ttymalloc();
81 		tty_attach(tp);
82 	} else
83 		tp = prom_tty[unit];
84 
85 	tp->t_oproc = promstart;
86 	tp->t_param = promparam;
87 	tp->t_dev = dev;
88 	if ((tp->t_state & TS_ISOPEN) == 0) {
89 		tp->t_state |= TS_CARR_ON;
90 		ttychars(tp);
91 		tp->t_iflag = TTYDEF_IFLAG;
92 		tp->t_oflag = TTYDEF_OFLAG;
93 		tp->t_cflag = TTYDEF_CFLAG|CLOCAL;
94 		tp->t_lflag = TTYDEF_LFLAG;
95 		tp->t_ispeed = tp->t_ospeed = 9600;
96 		ttsetwater(tp);
97 
98 		setuptimeout = 1;
99 	} else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) {
100 		splx(s);
101 		return EBUSY;
102 	}
103 
104 	splx(s);
105 
106 	error = (*tp->t_linesw->l_open)(dev, tp);
107 	if (error == 0 && setuptimeout) {
108 		polltime = hz / PROM_POLL_HZ;
109 		if (polltime < 1)
110 			polltime = 1;
111 		callout_reset(&prom_ch, polltime, promtimeout, tp);
112 	}
113 	return error;
114 }
115 
116 int
117 promclose(dev_t dev, int flag, int mode, struct proc *p)
118 {
119 	int unit = minor(dev);
120 	struct tty *tp = prom_tty[unit];
121 
122 	callout_stop(&prom_ch);
123 	(*tp->t_linesw->l_close)(tp, flag);
124 	ttyclose(tp);
125 	return 0;
126 }
127 
128 int
129 promread(dev_t dev, struct uio *uio, int flag)
130 {
131 	struct tty *tp = prom_tty[minor(dev)];
132 
133 	return ((*tp->t_linesw->l_read)(tp, uio, flag));
134 }
135 
136 int
137 promwrite(dev_t dev, struct uio *uio, int flag)
138 {
139 	struct tty *tp = prom_tty[minor(dev)];
140 
141 	return ((*tp->t_linesw->l_write)(tp, uio, flag));
142 }
143 
144 int
145 prompoll(dev, events, p)
146 	dev_t dev;
147 	int events;
148 	struct proc *p;
149 {
150 	struct tty *tp = prom_tty[minor(dev)];
151 
152 	return ((*tp->t_linesw->l_poll)(tp, events, p));
153 }
154 
155 int
156 promioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
157 {
158 	int unit = minor(dev);
159 	struct tty *tp = prom_tty[unit];
160 	int error;
161 
162 	error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p);
163 	if (error != EPASSTHROUGH)
164 		return error;
165 	return ttioctl(tp, cmd, data, flag, p);
166 }
167 
168 int
169 promparam(struct tty *tp, struct termios *t)
170 {
171 
172 	return 0;
173 }
174 
175 void
176 promstart(struct tty *tp)
177 {
178 	int s;
179 
180 	s = spltty();
181 	if (tp->t_state & (TS_TTSTOP | TS_BUSY))
182 		goto out;
183 	if (tp->t_outq.c_cc <= tp->t_lowat) {
184 		if (tp->t_state & TS_ASLEEP) {
185 			tp->t_state &= ~TS_ASLEEP;
186 			wakeup((caddr_t)&tp->t_outq);
187 		}
188 		selwakeup(&tp->t_wsel);
189 	}
190 	tp->t_state |= TS_BUSY;
191 	while (tp->t_outq.c_cc != 0)
192 		promcnputc(tp->t_dev, getc(&tp->t_outq));
193 	tp->t_state &= ~TS_BUSY;
194 out:
195 	splx(s);
196 }
197 
198 /*
199  * Stop output on a line.
200  */
201 void
202 promstop(struct tty *tp, int flag)
203 {
204 	int s;
205 
206 	s = spltty();
207 	if (tp->t_state & TS_BUSY)
208 		if ((tp->t_state & TS_TTSTOP) == 0)
209 			tp->t_state |= TS_FLUSH;
210 	splx(s);
211 }
212 
213 void
214 promtimeout(void *v)
215 {
216 	struct tty *tp = v;
217 	u_char c;
218 
219 	while (promcnlookc(tp->t_dev, &c)) {
220 		if (tp->t_state & TS_ISOPEN)
221 			(*tp->t_linesw->l_rint)(c, tp);
222 	}
223 	callout_reset(&prom_ch, polltime, promtimeout, tp);
224 }
225 
226 struct tty *
227 promtty(dev_t dev)
228 {
229 
230 	if (minor(dev) != 0)
231 		panic("promtty: bogus");
232 
233 	return prom_tty[0];
234 }
235 
236 #endif /* _PMAP_MAY_USE_PROM_CONSOLE */
237