1 /*        $NetBSD: kbd.c,v 1.7 2009/03/18 10:22:27 cegger Exp $       */
2 
3 /*-
4  * Copyright (C) 1995-1997 Gary Thomas (gdt@linuxppc.org)
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by Gary Thomas.
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #if defined(CONS_BE) || defined(CONS_VGA)
34 #include <lib/libsa/stand.h>
35 #include "boot.h"
36 
37 /*
38  * Keyboard handler
39  */
40 #define   L                   0x0001    /* locking function */
41 #define   SHF                 0x0002    /* keyboard shift */
42 #define   ALT                 0x0004    /* alternate shift -- alternate chars */
43 #define   NUM                 0x0008    /* numeric shift  cursors vs. numeric */
44 #define   CTL                 0x0010    /* control shift  -- allows ctl function */
45 #define   CPS                 0x0020    /* caps shift -- swaps case of letter */
46 #define   ASCII               0x0040    /* ascii code for this key */
47 #define   STP                 0x0080    /* stop output */
48 #define   FUNC                0x0100    /* function key */
49 #define   SCROLL              0x0200    /* scroll lock key */
50 
51 #include "pcconstab.US"
52 
53 u_char shfts, ctls, alts, caps, num, stp;
54 
55 #define   KBDATAP             0x60      /* kbd data port */
56 #define   KBSTATUSPORT        0x61      /* kbd status */
57 #define   KBSTATP             0x64      /* kbd status port */
58 #define   KBINRDY             0x01
59 #define   KBOUTRDY  0x02
60 
61 #define   _x__ 0x00  /* Unknown / unmapped */
62 
63 const u_char keycode[] = {
64           _x__, 0x43, 0x41, 0x3F, 0x3D, 0x3B, 0x3C, _x__, /* 0x00-0x07 */
65           _x__, 0x44, 0x42, 0x40, 0x3E, 0x0F, 0x29, _x__, /* 0x08-0x0F */
66           _x__, 0x38, 0x2A, _x__, 0x1D, 0x10, 0x02, _x__, /* 0x10-0x17 */
67           _x__, _x__, 0x2C, 0x1F, 0x1E, 0x11, 0x03, _x__, /* 0x18-0x1F */
68           _x__, 0x2E, 0x2D, 0x20, 0x12, 0x05, 0x04, _x__, /* 0x20-0x27 */
69           _x__, 0x39, 0x2F, 0x21, 0x14, 0x13, 0x06, _x__, /* 0x28-0x2F */
70           _x__, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, _x__, /* 0x30-0x37 */
71           _x__, _x__, 0x32, 0x24, 0x16, 0x08, 0x09, _x__, /* 0x38-0x3F */
72           _x__, 0x33, 0x25, 0x17, 0x18, 0x0B, 0x0A, _x__, /* 0x40-0x47 */
73           _x__, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0C, _x__, /* 0x48-0x4F */
74           _x__, _x__, 0x28, _x__, 0x1A, 0x0D, _x__, _x__, /* 0x50-0x57 */
75           0x3A, 0x36, 0x1C, 0x1B, _x__, 0x2B, _x__, _x__, /* 0x58-0x5F */
76           _x__, _x__, _x__, _x__, _x__, _x__, 0x0E, _x__, /* 0x60-0x67 */
77           _x__, 0x4F, _x__, 0x4B, 0x47, _x__, _x__, _x__, /* 0x68-0x6F */
78           0x52, 0x53, 0x50, 0x4C, 0x4D, 0x48, 0x01, 0x45, /* 0x70-0x77 */
79           _x__, 0x4E, 0x51, 0x4A, _x__, 0x49, 0x46, 0x54, /* 0x78-0x7F */
80 };
81 
82 int
kbd(int noblock)83 kbd(int noblock)
84 {
85           u_char dt, brk, act;
86           int first = 1;
87 
88 loop:
89           if (noblock) {
90                     if ((inb(KBSTATP) & KBINRDY) == 0)
91                               return (-1);
92           } else while ((inb(KBSTATP) & KBINRDY) == 0)
93                     ;
94 
95           dt = inb(KBDATAP);
96 
97           brk = dt & 0x80;    /* brk == 1 on key release */
98           dt = dt & 0x7f;               /* keycode */
99 
100           act = action[dt];
101           if (act & SHF)
102                     shfts = brk ? 0 : 1;
103           if (act & ALT)
104                     alts = brk ? 0 : 1;
105           if (act & NUM) {
106                     if (act & L) {
107                               /* NUM lock */
108                               if (!brk)
109                                         num = !num;
110                     } else {
111                               num = brk ? 0 : 1;
112                     }
113           }
114           if (act & CTL)
115                     ctls = brk ? 0 : 1;
116           if (act & CPS) {
117                     if (act & L) {
118                               /* CAPS lock */
119                               if (!brk)
120                                         caps = !caps;
121                     } else {
122                               caps = brk ? 0 : 1;
123                     }
124           }
125           if (act & STP) {
126                     if (act & L) {
127                               if (!brk)
128                                         stp = !stp;
129                     } else {
130                               stp = brk ? 0 : 1;
131                     }
132           }
133 
134           if ((act & ASCII) && !brk) {
135                     u_char chr;
136 
137                     if (shfts)
138                               chr = shift[dt];
139                     else if (ctls)
140                               chr = ctl[dt];
141                     else
142                               chr = unshift[dt];
143 
144                     if (alts)
145                               chr |= 0x80;
146 
147                     if (caps && (chr >= 'a' && chr <= 'z'))
148                               chr -= 'a' - 'A';
149 #define   CTRL(s) (s & 0x1F)
150                     if ((chr == '\r') || (chr == '\n') ||
151                         (chr == CTRL('A')) || (chr == CTRL('S'))) {
152 
153                               /* Wait for key up */
154                               while (1)
155                               {
156                                         while ((inb(KBSTATP) & KBINRDY) == 0)
157                                                   ;
158                                         dt = inb(KBDATAP);
159                                         if (dt & 0x80) /* key up */ break;
160                               }
161                     }
162                     return (chr);
163           }
164 
165           if (first && brk)
166                     return (0);         /* Ignore initial 'key up' codes */
167           goto loop;
168 }
169 
170 void
kbdreset(void)171 kbdreset(void)
172 {
173           u_char c;
174           int i;
175 
176           /* Send self-test */
177           while (inb(KBSTATP) & KBOUTRDY)
178                     ;
179           outb(KBSTATP, 0xAA);
180           while ((inb(KBSTATP) & KBINRDY) == 0)   /* wait input ready */
181                     ;
182           if ((c = inb(KBDATAP)) != 0x55) {
183                     printf("Keyboard self test failed - result: %x\n", c);
184           }
185           /* Enable interrupts and keyboard controller */
186           while (inb(KBSTATP) & KBOUTRDY)
187                     ;
188           outb(KBSTATP, 0x60);
189           while (inb(KBSTATP) & KBOUTRDY)
190                     ;
191           outb(KBDATAP, 0x45);
192           for (i = 0;  i < 10000;  i++)
193                     ;
194           while (inb(KBSTATP) & KBOUTRDY)
195                     ;
196           outb(KBSTATP, 0xAE);
197 }
198 
199 int
kbd_getc(void)200 kbd_getc(void)
201 {
202           int c;
203           while ((c = kbd(0)) == 0)
204                     ;
205           return (c);
206 }
207 
208 int
kbd_test(void)209 kbd_test(void)
210 {
211           return ((inb(KBSTATP) & KBINRDY) != 0);
212 }
213 #endif /* CONS_BE || CONS_VGA*/
214