1 static char rcsid[] = "$Id: sunkeyboard.c,v 1.5 1996/08/01 02:08:56 paul Exp $";
2
3 /*
4 * This file contains the keyboard driver for SunOS Minix. There are three
5 * groups of functions in this file associated with the three entry points:
6 * - keyboard_intr - the function called when a SIGIO is received
7 * indicating that terminal input is available.
8 * - kb_init - called to initialise keyboard data structures for a
9 * specified terminal line. Also, kb_read is installed as
10 * the function to call to read input from the specified
11 * terminal line.
12 * - wreboot - Shutdown smx. Doesn't really belong in this file.
13 */
14
15 #include "kernel.h"
16 #include <termios.h>
17 #include <minix/callnr.h>
18 #include <minix/com.h>
19 #include "tty.h"
20 #include "proc.h"
21 #include <sun/syscall.h>
22
23 #define KB_IN_BYTES 1024 /* size of keyboard input buffer */
24
25 #define min(x,y) ((x) < (y) ? (x) : (y))
26
27 #define kb_addr(tp) (&kb_lines[tty_line(tp)])
28
29 /*
30 * Keyboard structure, 1 per tty.
31 */
32 struct kb_s {
33 char *ihead; /* next free spot in input buffer */
34 char *itail; /* first used spot in input buffer */
35 int icount; /* # codes in buffer */
36
37 char ibuf[KB_IN_BYTES]; /* input buffer */
38 };
39
40 static struct kb_s kb_lines[NR_CONS];
41
42
43 /*
44 * Local functions
45 */
46 static int hw_read(tty_t *tp, char *buffer, int len);
47 static void input_flush(tty_t *tp);
48
49 static void kb_read(tty_t *tp);
50 static int func_key(tty_t *tp, int scode);
51
52
53 /*===========================================================================*
54 * Functions dealing with the SunOS IO signal *
55 *===========================================================================*/
56
57 /*
58 * Function: keyboard_intr
59 * Parameter: fd - SunOS file descriptor on which input is available
60 *
61 * The function is called when there is input available on the SunOS
62 * descriptor fd, and fd is associated with one of the smx console devices.
63 * keyboard_instr must transfer the input to a terminal buffer, and inform
64 * the terminal driver that new input has arrived. Any terminal input that
65 * won't fit into the keyboard buffer is discarded.
66 *
67 * Maybe the TTY task should transfer input into the buffer (but
68 * it's not awoken until the next clock tick). On the other hand,
69 * the PC MINIX keyboard interrupt handle also puts characters directly
70 * into the buffers of the TTY task.
71 */
72 static void keyboard_intr(int fd)
73 {
74 struct kb_s *kb;
75 tty_t *tp;
76 int line;
77 int num_read, to_read;
78
79 line = (fd - TERMINAL_FD) / 2;
80 if (line < 0 || line >= NR_CONS) {
81 panic("Bad fd supplied to keyboard_intr", fd);
82 }
83
84 tp = &tty_table[line];
85 kb = kb_addr(tp);
86 if (kb->icount < KB_IN_BYTES) {
87 /*
88 * If there is space in the buffer then we go ahead and
89 * try to read from the tty. If the free buffer space
90 * (KB_IN_BYTES - kb->icount) is in one chunk then we
91 * try to fill all of it in a single read. Otherwise
92 * we free the space between head and the end of the
93 * buffer with the first read and, if all of that space
94 * is filled, wrap head around to the beginning of the
95 * buffer and try to fill the free space there.
96 */
97 to_read = min(KB_IN_BYTES - kb->icount,
98 KB_IN_BYTES - (kb->ihead - kb->ibuf));
99 num_read = hw_read(tp, kb->ihead, to_read);
100
101 if (num_read > 0) {
102 tp->tty_events = 1;
103 force_timeout();
104 kb->icount += num_read;
105 kb->ihead += num_read;
106
107 if (kb->ihead == kb->ibuf + KB_IN_BYTES) {
108 kb->ihead = kb->ibuf;
109 if (kb->icount < KB_IN_BYTES) {
110 num_read = hw_read(tp, kb->ihead,
111 KB_IN_BYTES - kb->icount);
112
113 if (num_read > 0) {
114 kb->icount += num_read;
115 kb->ihead += num_read;
116 /*
117 * Read at least 1 byte the first time; ihead
118 * cannot wraparound this time.
119 */
120 }
121 } /* if space in input buffer for a second read */
122 } /* if first read wraps buffer */
123 } /* if first read returns at least one char */
124 } /* if space in input buffer */
125
126 if (kb->icount == KB_IN_BYTES) {
127 /*
128 * If the buffer is full then there may still be data buffered
129 * by SunOS. Flush it to make sure that we get a SIGIO
130 * when the next character gets entered.
131 */
132 input_flush(tp);
133 }
134 }
135
136
137 /*
138 * Function: hw_read
139 * Parameters: tp - terminal to read from
140 * buffer - buffer to read into
141 * len - size of buffer
142 * Returns: value returned by call to SunOS read.
143 *
144 * The terminal input descriptors are the even ones of the terminal
145 * descriptor pair, so the FD to read is simply
146 * TERMINAL_FD + 2 line_number. The smx bootstrap program sets up
147 * these terminal descriptors.
148 */
149 static int hw_read(tty_t *tp, char *buffer, int len)
150 {
151 return SunOS(SYS_read, TERMINAL_FD + tty_line(tp) * 2, buffer, len);
152 }
153
154
155 /*
156 * Function: input_flush
157 * Parameter: tp - terminal to be flushed
158 *
159 * Discard all buffered input for the spcified terminal.
160 */
161 static void input_flush(tty_t *tp)
162 {
163 static char flushbuf[32];
164
165 while (hw_read(tp, flushbuf, sizeof(flushbuf)) > 0) {
166 ;
167 }
168 }
169
170
171 /*===========================================================================*
172 * The keyboard driver functions *
173 *===========================================================================*/
174
175 /*
176 * Function: kb_init
177 * Parameter: tp - terminal whose keyboard driver is to be initialised
178 *
179 * Initialize the keyboard driver for the specified terminal line.
180 */
181 void kb_init(tty_t *tp)
182 {
183 register struct kb_s *kb;
184
185 tp->tty_devread = kb_read; /* Input function. */
186
187 /*
188 * Install kerboard_intr as the handler for input received on the
189 * associated SunOS file descriptor.
190 */
191 sunio_install_handler(TERMINAL_FD + tty_line(tp) * 2, keyboard_intr);
192
193 kb = kb_addr(tp);
194 kb->ihead = kb->itail = kb->ibuf; /* The input buffer is empty */
195 kb->icount = 0;
196 }
197
198
199 /*
200 * Function: kb_read
201 * Parameter: tp - terminal to read input from
202 *
203 * Process characters from the circular keyboard buffer. Characters are
204 * removed from the keyboard buffer one at a time. Each is checked to
205 * see if it is a function key used by the kernel. If so, the character
206 * is actioned and not passed on; otherwise the character is passed on to
207 * in_process().
208 */
209 static void kb_read(tty_t *tp)
210 {
211 struct kb_s *kb;
212 int scode;
213 char ch;
214
215 kb = kb_addr(tp);
216
217 lock();
218 while (kb->icount > 0) {
219 scode = *kb->itail++; /* take one key scan code */
220 if (kb->itail == kb->ibuf + KB_IN_BYTES) kb->itail = kb->ibuf;
221 kb->icount--;
222
223 /*
224 * Is it a function keys used for a debug dump?
225 */
226 if (func_key(tp, scode)) continue;
227
228 /*
229 * It's not a function key. in_process calls lock, so go into it
230 * "unlocked" as otherwise we'll get a recursive lock error.
231 */
232 ch = scode;
233 unlock();
234 (void) in_process(tp, &ch, 1);
235 lock();
236 }
237 unlock();
238 }
239
240
241 /*
242 * Function: func_key
243 * Parameters: tp - terminal line the input was received on
244 * scode - scan code for key received.
245 * Returns: TRUE if scode should be passed on as user input, FALSE if
246 * it has been consumed by the kernel
247 *
248 * Some key-strokes are intercepted by the kernel for its own purposes.
249 * At present two codes are intercepted. Code 0x1f (^_) is used to
250 * cause an emegency panic when the system is not responding (panic
251 * generates various pieces of debugging info). The other code is
252 * MLOGIN_HANGUP, which us sent by mlogin when it is about to exit.
253 */
254 static int func_key(tty_t *tp, int scode)
255 {
256 switch(scode) {
257 case 0x1f: /* ^_, I'm desperate---ignored unless typed on the console */
258 if (tty_line(tp) != 0) return FALSE;
259 panic("TERMINAL PANIC", NO_NUM);
260 break;
261
262 case MLOGIN_HANGUP:
263 hangup(tty_line(tp));
264 break;
265
266 default:
267 return FALSE;
268 }
269 return TRUE;
270 }
271
272
273 /*==========================================================================*
274 * reboot section *
275 *==========================================================================*/
276
277 /*
278 * Function: wreboot
279 * Parameter: how - unused in smx
280 *
281 * Terminates smx by exiting.
282 */
283 void wreboot(int how)
284 {
285 printf("Exiting smx\n");
286 SunOS(SYS_exit, 0);
287 /*NOTREACHED*/
288 }
289
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.