Initial import from FreeBSD RELENG_4:
[dragonfly.git] / usr.sbin / pcvt / kbdio / kbdio.y
1 /* Hello emacs, this should be edited in -*- Fundamental -*- mode */
2 %{
3 /*
4  * Copyright (c) 1994 Joerg Wunsch
5  *
6  * All rights reserved.
7  *
8  * This program is free software.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed by Joerg Wunsch
21  * 4. The name of the developer may not be used to endorse or promote
22  *    products derived from this software without specific prior written
23  *    permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
26  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28  * IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36
37 #ident "$FreeBSD: src/usr.sbin/pcvt/kbdio/kbdio.y,v 1.6 1999/09/06 07:39:30 peter Exp $"
38
39 /*
40  * $Log: kbdio.y,v $
41  * Revision 1.2  1994/09/18  19:49:22  j
42  * Refined expr handling; can now set/clear bits.
43  *
44  * Revision 1.1  1994/09/18  12:57:13  j
45  * Initial revision
46  *
47  *
48  */
49
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <math.h>
53 #include <sys/fcntl.h>
54 #include <machine/cpufunc.h>
55 #include <machine/pcvt_ioctl.h>
56
57 #ifdef __NetBSD__
58 #include <machine/pio.h>
59 #endif
60
61 #define KBD_DELAY \
62         { u_char x = inb(0x84); } \
63         { u_char x = inb(0x84); } \
64         { u_char x = inb(0x84); } \
65         { u_char x = inb(0x84); } \
66         { u_char x = inb(0x84); } \
67         { u_char x = inb(0x84); }
68
69 #define YYDEBUG 1
70
71 void yyerror(const char *msg);
72
73 static  void help(int), status(void), data(int), kbd(int), cmdbyte(int),
74         kbc(int), whatMCA(void);
75 static  int kbget(void);
76 %}
77
78 %union {
79         int num;
80 }
81
82 %token          NEWLINE
83 %token          ALL CMD DATA DEFAULTS ECHOC ENABLE EXPR HELP ID LED
84 %token          MAKE ONLY RELEASE RESEND RESET SCAN STATUS TYPEMATIC
85 %token          WHAT
86 %token  <num>   NUM
87
88 %type   <num>   expr opr
89
90 %%
91
92 interpret:      lines ;
93
94 lines:          line
95                 | lines line
96                 ;
97
98 line:           statements NEWLINE
99                 | NEWLINE
100                 | error NEWLINE         { fprintf(stderr, "bing!\n"); }
101                 ;
102
103 statements:     statement
104                 | statements ';' statement
105                 ;
106
107 statement:      '?'                     { help(0); }
108                 | HELP                  { help(0); }
109                 | HELP EXPR             { help(1); }
110                 | STATUS '?'            { status(); }
111                 | WHAT '?'              { whatMCA(); }
112                 | DATA '?'              { data(kbget()); }
113                 | LED '=' NUM           { kbd(0xed); kbd($3); }
114                 | ECHOC                 { kbd(0xee); kbget(); }
115                 | SCAN '=' NUM          { kbd(0xf0); kbd($3);
116                                           if($3 == 0) data(kbget()); }
117                 | SCAN '?'              { kbd(0xf0); kbd(0); data(kbget()); }
118                 | ID '?'                { kbd(0xf2); data(kbget());
119                                           data(kbget()); }
120                 | TYPEMATIC '=' NUM ',' NUM
121                                         { kbd(0xf3);
122                                           if($3 > 1000) $3 = 1000;
123                                           if($5 > 30) $5 = 30;
124                                           if($5 < 2) $5 = 2;
125                                           kbd(
126                                               (int)
127                                                 (8.0 * log(30.0 / (double)$5)
128                                                  / log(2))
129                                               | ((($3 / 250) - 1) * 32)
130                                              );
131                                         }
132                 | ENABLE                { kbd(0xf4); }
133                 | DEFAULTS              { kbd(0xf6); }
134                 | ALL TYPEMATIC         { kbd(0xf7); }
135                 | ALL MAKE RELEASE      { kbd(0xf8); }
136                 | ALL MAKE ONLY         { kbd(0xf9); }
137                 | ALL TYPEMATIC MAKE RELEASE
138                                         { kbd(0xfa); }
139                 | NUM TYPEMATIC         { kbd(0xfb); kbd($1); }
140                 | NUM MAKE RELEASE      { kbd(0xfc); kbd($1); }
141                 | NUM MAKE ONLY         { kbd(0xfd); kbd($1); }
142                 | RESEND                { kbd(0xfe); }
143                 | RESET                 { kbd(0xff); }
144                 | CMD '?'               { kbc(0x20); cmdbyte(kbget()); }
145                 | CMD '=' expr          { kbc(0x60); kbd($3); }
146                 | /* lambda */
147                 ;
148
149 expr:           opr                     { $$ = $1; }
150                 | expr '+' opr          { $$ = $1 | $3; }
151                 | expr '-' opr          { $$ = $1 & ~($3); }
152                 ;
153
154 opr:            NUM                     { $$ = $1; }
155                 | CMD                   { kbc(0x20); $$ = kbget(); }
156                 ;
157
158 %%
159
160 static void
161 help(int topic) {
162         switch(topic) {
163         case 0:
164         printf(
165         "Input consists of lines, containing one or more semicolon-separated\n"
166         "statements. Numbers are implicitly hexadecimal, append a dot for\n"
167         "decimal numbers. Valid statements include:\n"
168         "help [expr];           give help [to expression syntax]\n"
169         "status ?               interpret kbd ctrl status byte\n"
170         "what ?                 check for MCA type 1 or 2 motherboard controller\n"
171         "data ?                 get one byte of data\n"
172         "led = NUM              set kbd LEDs\n"
173         "echo = NUM             echo byte to kbd\n"
174         "scan = NUM; scan ?     set scan code set; return current set\n"
175         "id ?                   get two id bytes\n"
176         "typematic=delay,rate   set typematic delay(ms)&rate(1/s)\n"
177         "enable; defaults       enable kbd; back to defaults\n"
178         "all typematic          make all keys typematic\n"
179         "all make release       make all keys sending make/release\n"
180         "all make only          make all keys sending make only\n"
181         "all typematic make release     make all keys typematic & make/release\n"
182         "NUM typematic          make specific key typematic\n"
183         "NUM make release       make specific key sending make/release\n"
184         "NUM make only          make specific key sending make only\n"
185         "resend; reset          resend last byte from kbd; reset kbd\n"
186         "cmd ?                  fetch kbd ctrl command byte\n"
187         "cmd = expr             set kbd ctrl command byte\n"
188         "\n");
189         break;
190
191         case 1:
192         printf(
193         "Expressions can either consist of a number, possibly followed\n"
194         "by a + or - sign and bit values in numeric or symbolic form.\n"
195         "Symbolic bit values are:\n"
196         "SCCONV IGNPAR CLKLOW OVRINH TEST IRQ\n"
197         "\n");
198         break;
199         }
200 }
201
202 static void
203 status(void) {
204         int c = inb(0x64);
205         if(c&0x80) printf("parity error | ");
206         if(c&0x40) printf("rx timeout | ");
207         if(c&0x20) printf("tx timeout | ");
208         if(c&0x10) printf("kbd released ");
209         else       printf("kbd locked   ");
210         if(c&0x08) printf("| cmd last sent  ");
211         else       printf("| data last sent ");
212         if(c&0x04) printf("| power-on ");
213         else       printf("| test ok  ");
214         if(c&0x02) printf("| ctrl write busy ");
215         else       printf("| ctrl write ok   ");
216         if(c&0x01) printf("| ctrl read ok\n");
217         else       printf("| ctrl read empty\n");
218 }
219
220 /* see: Frank van Gilluwe, "The Undocumented PC", Addison Wesley 1994, pp 273 */
221
222 static void
223 whatMCA(void) {
224         int new, sav;
225         kbc(0x20);              /* get command byte */
226         sav = kbget();          /* sav = command byte */
227         kbc(0x60);              /* set command byte */
228         kbd(sav | 0x40);        /* set keyboard xlate bit */
229         kbc(0x20);              /* get keyboard command */
230         new = kbget();          /* new = command byte */
231         kbc(0x60);              /* set command byte */
232         kbd(sav);               /* restore command byte */
233         if(new & 0xbf)
234                 printf("Hmm - looks like MCA type 1 motherboard controller\n");
235         else
236                 printf("Hmm - looks like MCA type 2 motherboard controller\n");
237 }
238
239 static void
240 kbd(int d) {
241         int i = 100000;
242         while(i && (inb(0x64) & 2)) i--;
243         if(i == 0) { printf("kbd write: timed out\n"); return; }
244         outb(0x60, d);
245 }
246
247 static void
248 kbc(int d) {
249         int i = 100000;
250         while(i && (inb(0x64) & 2)) i--;
251         if(i == 0) { printf("ctrl write: timed out\n"); return; }
252         outb(0x64, d);
253 }
254
255 static int
256 kbget(void) {
257         int i, c;
258         for(;;) {
259                 i = 10000;
260                 while(i && (inb(0x64) & 1) == 0) i--;
261                 if(i == 0) { printf("data read: timed out\n"); return -1; }
262                 KBD_DELAY
263                 c = (unsigned char)inb(0x60);
264                 switch(c) {
265                         case 0: case 0xff:
266                                 printf("got kbd overrun\n"); break;
267                         case 0xaa:
268                                 printf("got self-test OK\n"); break;
269                         case 0xee:
270                                 printf("got ECHO byte\n"); break;
271                         case 0xfa:
272                                 printf("got ACK\n"); break;
273                         case 0xfc:
274                                 printf("got self-test FAIL\n"); break;
275                         case 0xfd:
276                                 printf("got internal failure\n"); break;
277                         case 0xfe:
278                                 printf("got RESEND request\n"); break;
279                         default:
280                                 goto done;
281                 }
282         }
283 done:
284         return c;
285 }
286
287 static void
288 cmdbyte(int d) {
289         if(d&0x40) printf("scan conv ");
290         else       printf("pass thru ");
291         if(d&0x20) printf("| ign parity   ");
292         else       printf("| check parity ");
293         if(d&0x10) printf("| kbd clk low ");
294         else       printf("| enable kbd  ");
295         if(d&0x08) printf("| override kbd inh ");
296         if(d&0x04) printf("| test ok  ");
297         else       printf("| power-on ");
298         if(d&0x01) printf("| irq 1 enable\n");
299         else       printf("| no irq\n");
300 }
301
302 static void
303 data(int d) {
304         if(d < 0) return;
305         printf("data: 0x%02x\n", d);
306 }
307
308 void yyerror(const char *msg) {
309         fprintf(stderr, "yyerror: %s\n", msg);
310 }
311
312 int main(int argc, char **argv) {
313         int fd;
314
315         if(argc > 1) yydebug = 1;
316
317         if((fd = open("/dev/console", O_RDONLY)) < 0)
318                 fd = 0;
319
320         if(ioctl(fd, KDENABIO, 0) < 0) {
321                 perror("ioctl(KDENABIO)");
322                 return 1;
323         }
324         yyparse();
325
326         (void)ioctl(fd, KDDISABIO, 0);
327         return 0;
328 }
329