dev_pckbc.cc Source File

Back to the index.

dev_pckbc.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2003-2018 Anders Gavare. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *
28  * COMMENT: 8042 PC keyboard controller (+ 8242WB Keyboard/Mouse controller)
29  *
30  * This module includes emulation of the 8048 keyboard chip too.
31  *
32  * Quick source of good info: http://my.execpc.com/~geezer/osd/kbd/kbd.txt
33  *
34  * Some scancode listings for various types:
35  * http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html
36  * http://www.computer-engineering.org/ps2keyboard/scancodes3.html
37  * https://www.win.tue.nl/~aeb/linux/kbd/scancodes-10.html#scancodesets
38  * http://nixdoc.net/man-pages/irix/man7/pckeyboard.7.html
39  */
40 
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 
45 #include "console.h"
46 #include "cpu.h"
47 #include "devices.h"
48 #include "machine.h"
49 #include "memory.h"
50 #include "misc.h"
51 
52 #include "thirdparty/kbdreg.h"
53 
54 
55 // #define PCKBC_DEBUG
56 // #define debug fatal
57 
58 
59 // Should be 256 to emulate a real 8042? Having a larger value allows
60 // pasting of larger text chunks which is useful in the emulator.
61 // #define MAX_8042_QUEUELEN 256
62 #define MAX_8042_QUEUELEN 32768
63 
64 #define PC_DATA 0
65 #define PC_CMD 0
66 #define PC_STATUS 1
67 
68 #define PS2_TXBUF 0
69 #define PS2_RXBUF 1
70 #define PS2_CONTROL 2
71 #define PS2_CONTROL_TXINTEN (1 << 2)
72 #define PS2_CONTROL_RXINTEN (1 << 3)
73 #define PS2_STATUS 3
74 #define PS2_STATUS_TXEMPTY (1 << 3)
75 #define PS2_STATUS_RXFULL (1 << 4)
76 
77 #define PS2 100 // internal offset
78 
79 #define PCKBC_TICKSHIFT 15
80 
81 
82 struct pckbc_data {
84  int in_use;
85 
87 
91  int type;
93 
94  /* TODO: one of these for each port? */
96  int rx_int_enable[2];
97  int tx_int_enable[2];
98 
101  int state[2];
102  int cmdbyte;
105 
107  int head[2], tail[2];
108 
109  int mouse_x;
110  int mouse_y;
112 };
113 
114 #define STATE_NORMAL 0
115 #define STATE_LDCMDBYTE 1
116 #define STATE_RDCMDBYTE 2
117 #define STATE_WAITING_FOR_TRANSLTABLE 3
118 #define STATE_WAITING_FOR_RATE 4
119 #define STATE_WAITING_FOR_ONEKEY_MB 5
120 #define STATE_WAITING_FOR_AUX 6
121 #define STATE_WAITING_FOR_AUX_OUT 7
122 #define STATE_LDOUTPUT 8
123 #define STATE_RDOUTPUT 9
124 
125 
126 /*
127  * pckbc_add_code():
128  *
129  * Adds a byte to the data queue.
130  */
131 void pckbc_add_code(struct pckbc_data *d, int code, int port)
132 {
133  /* Add at the head, read at the tail: */
134  d->head[port] = (d->head[port]+1) % MAX_8042_QUEUELEN;
135  if (d->head[port] == d->tail[port])
136  fatal("[ pckbc: queue overrun, port %i! ]\n", port);
137 
138  d->key_queue[port][d->head[port]] = code;
139 }
140 
141 
142 /*
143  * pckbc_get_code():
144  *
145  * Reads a byte from a data queue.
146  */
147 int pckbc_get_code(struct pckbc_data *d, int port)
148 {
149  if (d->head[port] == d->tail[port])
150  fatal("[ pckbc: queue empty, port %i! ]\n", port);
151  else
152  d->tail[port] = (d->tail[port]+1) % MAX_8042_QUEUELEN;
153 
154  return d->key_queue[port][d->tail[port]];
155 }
156 
157 
158 /*
159  * ascii_to_scancodes_type1():
160  *
161  * Conversion from ASCII codes to default (US) keyboard scancodes.
162  */
163 static void ascii_to_pc_scancodes_type1(int a, struct pckbc_data *d)
164 {
165  int old_head;
166  int p = 0; /* port */
167  int shift = 0, ctrl = 0;
168 
169  if (a >= 'A' && a <= 'Z') { a += 32; shift = 1; }
170  if ((a >= 1 && a <= 26) && (a!='\n' && a!='\t' && a!='\b' && a!='\r'))
171  { a += 96; ctrl = 1; }
172 
173  if (a=='!') { a = '1'; shift = 1; }
174  if (a=='@') { a = '2'; shift = 1; }
175  if (a=='#') { a = '3'; shift = 1; }
176  if (a=='$') { a = '4'; shift = 1; }
177  if (a=='%') { a = '5'; shift = 1; }
178  if (a=='^') { a = '6'; shift = 1; }
179  if (a=='&') { a = '7'; shift = 1; }
180  if (a=='*') { a = '8'; shift = 1; }
181  if (a=='(') { a = '9'; shift = 1; }
182  if (a==')') { a = '0'; shift = 1; }
183  if (a=='_') { a = '-'; shift = 1; }
184  if (a=='+') { a = '='; shift = 1; }
185  if (a=='{') { a = '['; shift = 1; }
186  if (a=='}') { a = ']'; shift = 1; }
187  if (a==':') { a = ';'; shift = 1; }
188  if (a=='"') { a = '\''; shift = 1; }
189  if (a=='|') { a = '\\'; shift = 1; }
190  if (a=='<') { a = ','; shift = 1; }
191  if (a=='>') { a = '.'; shift = 1; }
192  if (a=='?') { a = '/'; shift = 1; }
193  if (a=='~') { a = '`'; shift = 1; }
194 
195  if (shift)
196  pckbc_add_code(d, 0x2a, p);
197  else
198  pckbc_add_code(d, 0x2a + 0x80, p);
199 
200  if (ctrl)
201  pckbc_add_code(d, 0x1d, p);
202 
203  /*
204  * Note: The ugly hack used to add release codes for all of these
205  * keys is as follows: we remember how much of the kbd buf that
206  * is in use here, before we add any scancode. After we've added
207  * one or more scancodes (ie an optional shift + another key)
208  * then we duplicate the last scancode | 0x80 _if_ the kbd buf
209  * was altered.
210  */
211 
212  old_head = d->head[p];
213 
214  if (a==27) pckbc_add_code(d, 0x01, p);
215 
216  if (a=='1') pckbc_add_code(d, 0x02, p);
217  if (a=='2') pckbc_add_code(d, 0x03, p);
218  if (a=='3') pckbc_add_code(d, 0x04, p);
219  if (a=='4') pckbc_add_code(d, 0x05, p);
220  if (a=='5') pckbc_add_code(d, 0x06, p);
221  if (a=='6') pckbc_add_code(d, 0x07, p);
222  if (a=='7') pckbc_add_code(d, 0x08, p);
223  if (a=='8') pckbc_add_code(d, 0x09, p);
224  if (a=='9') pckbc_add_code(d, 0x0a, p);
225  if (a=='0') pckbc_add_code(d, 0x0b, p);
226  if (a=='-') pckbc_add_code(d, 0x0c, p);
227  if (a=='=') pckbc_add_code(d, 0x0d, p);
228 
229  if (a=='!') { pckbc_add_code(d, 0x2a, p);
230  pckbc_add_code(d, 0x02, p); }
231  if (a=='@') { pckbc_add_code(d, 0x2a, p);
232  pckbc_add_code(d, 0x03, p); }
233  if (a=='#') { pckbc_add_code(d, 0x2a, p);
234  pckbc_add_code(d, 0x04, p); }
235  if (a=='$') { pckbc_add_code(d, 0x2a, p);
236  pckbc_add_code(d, 0x05, p); }
237  if (a=='%') { pckbc_add_code(d, 0x2a, p);
238  pckbc_add_code(d, 0x06, p); }
239  if (a=='^') { pckbc_add_code(d, 0x2a, p);
240  pckbc_add_code(d, 0x07, p); }
241  if (a=='&') { pckbc_add_code(d, 0x2a, p);
242  pckbc_add_code(d, 0x08, p); }
243  if (a=='*') { pckbc_add_code(d, 0x2a, p);
244  pckbc_add_code(d, 0x09, p); }
245  if (a=='(') { pckbc_add_code(d, 0x2a, p);
246  pckbc_add_code(d, 0x0a, p); }
247 
248  if (a=='\b') pckbc_add_code(d, 0x0e, p);
249 
250  if (a=='\t') pckbc_add_code(d, 0x0f, p);
251  if (a=='q') pckbc_add_code(d, 0x10, p);
252  if (a=='w') pckbc_add_code(d, 0x11, p);
253  if (a=='e') pckbc_add_code(d, 0x12, p);
254  if (a=='r') pckbc_add_code(d, 0x13, p);
255  if (a=='t') pckbc_add_code(d, 0x14, p);
256  if (a=='y') pckbc_add_code(d, 0x15, p);
257  if (a=='u') pckbc_add_code(d, 0x16, p);
258  if (a=='i') pckbc_add_code(d, 0x17, p);
259  if (a=='o') pckbc_add_code(d, 0x18, p);
260  if (a=='p') pckbc_add_code(d, 0x19, p);
261 
262  if (a=='[') pckbc_add_code(d, 0x1a, p);
263  if (a==']') pckbc_add_code(d, 0x1b, p);
264 
265  if (a=='\n' || a=='\r') pckbc_add_code(d, 0x1c, p);
266 
267  if (a=='a') pckbc_add_code(d, 0x1e, p);
268  if (a=='s') pckbc_add_code(d, 0x1f, p);
269  if (a=='d') pckbc_add_code(d, 0x20, p);
270  if (a=='f') pckbc_add_code(d, 0x21, p);
271  if (a=='g') pckbc_add_code(d, 0x22, p);
272  if (a=='h') pckbc_add_code(d, 0x23, p);
273  if (a=='j') pckbc_add_code(d, 0x24, p);
274  if (a=='k') pckbc_add_code(d, 0x25, p);
275  if (a=='l') pckbc_add_code(d, 0x26, p);
276 
277  if (a==';') pckbc_add_code(d, 0x27, p);
278  if (a=='\'') pckbc_add_code(d, 0x28, p);
279  if (a=='`') pckbc_add_code(d, 0x29, p);
280  if (a=='\\') pckbc_add_code(d, 0x2b, p);
281 
282  if (a=='z') pckbc_add_code(d, 0x2c, p);
283  if (a=='x') pckbc_add_code(d, 0x2d, p);
284  if (a=='c') pckbc_add_code(d, 0x2e, p);
285  if (a=='v') pckbc_add_code(d, 0x2f, p);
286  if (a=='b') pckbc_add_code(d, 0x30, p);
287  if (a=='n') pckbc_add_code(d, 0x31, p);
288  if (a=='m') pckbc_add_code(d, 0x32, p);
289 
290  if (a==',') pckbc_add_code(d, 0x33, p);
291  if (a=='.') pckbc_add_code(d, 0x34, p);
292  if (a=='/') pckbc_add_code(d, 0x35, p);
293 
294  if (a==' ') pckbc_add_code(d, 0x39, p);
295 
296  /* Add release code, if a key was pressed: */
297  if (d->head[p] != old_head) {
298  int code = d->key_queue[p][d->head[p]] | 0x80;
299  pckbc_add_code(d, code, p);
300  }
301 
302  /* Release ctrl: */
303  if (ctrl)
304  pckbc_add_code(d, 0x1d + 0x80, p);
305 }
306 
307 
308 /*
309  * ascii_to_scancodes_type2():
310  *
311  * Conversion from ASCII codes to default (US) keyboard scancodes.
312  */
313 static void ascii_to_pc_scancodes_type2(int a, struct pckbc_data *d)
314 {
315  int old_head;
316  int p = 0; /* port */
317  int shift = 0, ctrl = 0;
318 
319  if (a >= 'A' && a <= 'Z') { a += 32; shift = 1; }
320  if ((a >= 1 && a <= 26) && (a!='\n' && a!='\t' && a!='\b' && a!='\r'))
321  { a += 96; ctrl = 1; }
322  if (a=='!') { a = '1'; shift = 1; }
323  if (a=='@') { a = '2'; shift = 1; }
324  if (a=='#') { a = '3'; shift = 1; }
325  if (a=='$') { a = '4'; shift = 1; }
326  if (a=='%') { a = '5'; shift = 1; }
327  if (a=='^') { a = '6'; shift = 1; }
328  if (a=='&') { a = '7'; shift = 1; }
329  if (a=='*') { a = '8'; shift = 1; }
330  if (a=='(') { a = '9'; shift = 1; }
331  if (a==')') { a = '0'; shift = 1; }
332  if (a=='_') { a = '-'; shift = 1; }
333  if (a=='+') { a = '='; shift = 1; }
334  if (a=='{') { a = '['; shift = 1; }
335  if (a=='}') { a = ']'; shift = 1; }
336  if (a==':') { a = ';'; shift = 1; }
337  if (a=='"') { a = '\''; shift = 1; }
338  if (a=='|') { a = '\\'; shift = 1; }
339  if (a=='<') { a = ','; shift = 1; }
340  if (a=='>') { a = '.'; shift = 1; }
341  if (a=='?') { a = '/'; shift = 1; }
342  if (a=='~') { a = '`'; shift = 1; }
343 
344  if (shift)
345  pckbc_add_code(d, 0x12, p);
346  if (ctrl)
347  pckbc_add_code(d, 0x14, p);
348 
349  /*
350  * Note: The ugly hack used to add release codes for all of these
351  * keys is as follows: we remember how much of the kbd buf that
352  * is in use here, before we add any scancode. After we've added
353  * one or more scancodes (ie an optional shift + another key)
354  * then we add 0xf0 + the last scancode _if_ the kbd buf was altered.
355  */
356 
357  old_head = d->head[p];
358 
359  if (a==27) pckbc_add_code(d, 0x76, p);
360 
361  if (a=='1') pckbc_add_code(d, 0x16, p);
362  if (a=='2') pckbc_add_code(d, 0x1e, p);
363  if (a=='3') pckbc_add_code(d, 0x26, p);
364  if (a=='4') pckbc_add_code(d, 0x25, p);
365  if (a=='5') pckbc_add_code(d, 0x2e, p);
366  if (a=='6') pckbc_add_code(d, 0x36, p);
367  if (a=='7') pckbc_add_code(d, 0x3d, p);
368  if (a=='8') pckbc_add_code(d, 0x3e, p);
369  if (a=='9') pckbc_add_code(d, 0x46, p);
370  if (a=='0') pckbc_add_code(d, 0x45, p);
371  if (a=='-') pckbc_add_code(d, 0x4e, p);
372  if (a=='=') pckbc_add_code(d, 0x55, p);
373 
374  if (a=='\b') pckbc_add_code(d, 0x66, p);
375 
376  if (a=='\t') pckbc_add_code(d, 0x0d, p);
377  if (a=='q') pckbc_add_code(d, 0x15, p);
378  if (a=='w') pckbc_add_code(d, 0x1d, p);
379  if (a=='e') pckbc_add_code(d, 0x24, p);
380  if (a=='r') pckbc_add_code(d, 0x2d, p);
381  if (a=='t') pckbc_add_code(d, 0x2c, p);
382  if (a=='y') pckbc_add_code(d, 0x35, p);
383  if (a=='u') pckbc_add_code(d, 0x3c, p);
384  if (a=='i') pckbc_add_code(d, 0x43, p);
385  if (a=='o') pckbc_add_code(d, 0x44, p);
386  if (a=='p') pckbc_add_code(d, 0x4d, p);
387 
388  if (a=='[') pckbc_add_code(d, 0x54, p);
389  if (a==']') pckbc_add_code(d, 0x5b, p);
390 
391  if (a=='\n' || a=='\r') pckbc_add_code(d, 0x5a, p);
392 
393  if (a=='a') pckbc_add_code(d, 0x1c, p);
394  if (a=='s') pckbc_add_code(d, 0x1b, p);
395  if (a=='d') pckbc_add_code(d, 0x23, p);
396  if (a=='f') pckbc_add_code(d, 0x2b, p);
397  if (a=='g') pckbc_add_code(d, 0x34, p);
398  if (a=='h') pckbc_add_code(d, 0x33, p);
399  if (a=='j') pckbc_add_code(d, 0x3b, p);
400  if (a=='k') pckbc_add_code(d, 0x42, p);
401  if (a=='l') pckbc_add_code(d, 0x4b, p);
402 
403  if (a==';') pckbc_add_code(d, 0x4c, p);
404  if (a=='\'') pckbc_add_code(d, 0x52, p);
405  if (a=='`') pckbc_add_code(d, 0x0e, p); // ?
406  if (a=='\\') pckbc_add_code(d, 0x5d, p); // 0x5c?
407 
408  if (a=='z') pckbc_add_code(d, 0x1a, p);
409  if (a=='x') pckbc_add_code(d, 0x22, p);
410  if (a=='c') pckbc_add_code(d, 0x21, p);
411  if (a=='v') pckbc_add_code(d, 0x2a, p);
412  if (a=='b') pckbc_add_code(d, 0x32, p);
413  if (a=='n') pckbc_add_code(d, 0x31, p);
414  if (a=='m') pckbc_add_code(d, 0x3a, p);
415 
416  if (a==',') pckbc_add_code(d, 0x41, p);
417  if (a=='.') pckbc_add_code(d, 0x49, p);
418  if (a=='/') pckbc_add_code(d, 0x4a, p);
419 
420  if (a==' ') pckbc_add_code(d, 0x29, p);
421 
422  /* Add release code, if a key was pressed: */
423  if (d->head[p] != old_head) {
424  int code = d->key_queue[p][d->head[p]];
425  pckbc_add_code(d, 0xf0, p);
426  pckbc_add_code(d, code, p);
427  }
428 
429  /* Release shift and ctrl: */
430  if (shift) {
431  pckbc_add_code(d, 0xf0, p);
432  pckbc_add_code(d, 0x12, p);
433  }
434  if (ctrl) {
435  pckbc_add_code(d, 0xf0, p);
436  pckbc_add_code(d, 0x14, p);
437  }
438 }
439 
440 
441 /*
442  * ascii_to_scancodes_type3():
443  *
444  * Conversion from ASCII codes to default (US) keyboard scancodes.
445  */
446 static void ascii_to_pc_scancodes_type3(int a, struct pckbc_data *d)
447 {
448  int old_head;
449  int p = 0; /* port */
450  int shift = 0, ctrl = 0;
451 
452  if (a >= 'A' && a <= 'Z') { a += 32; shift = 1; }
453  if ((a >= 1 && a <= 26) && (a!='\n' && a!='\t' && a!='\b' && a!='\r'))
454  { a += 96; ctrl = 1; }
455  if (a=='!') { a = '1'; shift = 1; }
456  if (a=='@') { a = '2'; shift = 1; }
457  if (a=='#') { a = '3'; shift = 1; }
458  if (a=='$') { a = '4'; shift = 1; }
459  if (a=='%') { a = '5'; shift = 1; }
460  if (a=='^') { a = '6'; shift = 1; }
461  if (a=='&') { a = '7'; shift = 1; }
462  if (a=='*') { a = '8'; shift = 1; }
463  if (a=='(') { a = '9'; shift = 1; }
464  if (a==')') { a = '0'; shift = 1; }
465  if (a=='_') { a = '-'; shift = 1; }
466  if (a=='+') { a = '='; shift = 1; }
467  if (a=='{') { a = '['; shift = 1; }
468  if (a=='}') { a = ']'; shift = 1; }
469  if (a==':') { a = ';'; shift = 1; }
470  if (a=='"') { a = '\''; shift = 1; }
471  if (a=='|') { a = '\\'; shift = 1; }
472  if (a=='<') { a = ','; shift = 1; }
473  if (a=='>') { a = '.'; shift = 1; }
474  if (a=='?') { a = '/'; shift = 1; }
475  if (a=='~') { a = '`'; shift = 1; }
476 
477  if (shift)
478  pckbc_add_code(d, 0x12, p);
479  if (ctrl)
480  pckbc_add_code(d, 0x11, p);
481 
482  /*
483  * Note: The ugly hack used to add release codes for all of these
484  * keys is as follows: we remember how much of the kbd buf that
485  * is in use here, before we add any scancode. After we've added
486  * one or more scancodes (ie an optional shift + another key)
487  * then we add 0xf0 + the last scancode _if_ the kbd buf was altered.
488  */
489 
490  old_head = d->head[p];
491 
492  if (a==27) pckbc_add_code(d, 0x08, p);
493 
494  if (a=='1') pckbc_add_code(d, 0x16, p);
495  if (a=='2') pckbc_add_code(d, 0x1e, p);
496  if (a=='3') pckbc_add_code(d, 0x26, p);
497  if (a=='4') pckbc_add_code(d, 0x25, p);
498  if (a=='5') pckbc_add_code(d, 0x2e, p);
499  if (a=='6') pckbc_add_code(d, 0x36, p);
500  if (a=='7') pckbc_add_code(d, 0x3d, p);
501  if (a=='8') pckbc_add_code(d, 0x3e, p);
502  if (a=='9') pckbc_add_code(d, 0x46, p);
503  if (a=='0') pckbc_add_code(d, 0x45, p);
504  if (a=='-') pckbc_add_code(d, 0x4e, p);
505  if (a=='=') pckbc_add_code(d, 0x55, p);
506 
507  if (a=='\b') pckbc_add_code(d, 0x66, p);
508 
509  if (a=='\t') pckbc_add_code(d, 0x0d, p);
510  if (a=='q') pckbc_add_code(d, 0x15, p);
511  if (a=='w') pckbc_add_code(d, 0x1d, p);
512  if (a=='e') pckbc_add_code(d, 0x24, p);
513  if (a=='r') pckbc_add_code(d, 0x2d, p);
514  if (a=='t') pckbc_add_code(d, 0x2c, p);
515  if (a=='y') pckbc_add_code(d, 0x35, p);
516  if (a=='u') pckbc_add_code(d, 0x3c, p);
517  if (a=='i') pckbc_add_code(d, 0x43, p);
518  if (a=='o') pckbc_add_code(d, 0x44, p);
519  if (a=='p') pckbc_add_code(d, 0x4d, p);
520 
521  if (a=='[') pckbc_add_code(d, 0x54, p);
522  if (a==']') pckbc_add_code(d, 0x5b, p);
523 
524  if (a=='\n' || a=='\r') pckbc_add_code(d, 0x5a, p);
525 
526  if (a=='a') pckbc_add_code(d, 0x1c, p);
527  if (a=='s') pckbc_add_code(d, 0x1b, p);
528  if (a=='d') pckbc_add_code(d, 0x23, p);
529  if (a=='f') pckbc_add_code(d, 0x2b, p);
530  if (a=='g') pckbc_add_code(d, 0x34, p);
531  if (a=='h') pckbc_add_code(d, 0x33, p);
532  if (a=='j') pckbc_add_code(d, 0x3b, p);
533  if (a=='k') pckbc_add_code(d, 0x42, p);
534  if (a=='l') pckbc_add_code(d, 0x4b, p);
535 
536  if (a==';') pckbc_add_code(d, 0x4c, p);
537  if (a=='\'') pckbc_add_code(d, 0x52, p);
538  if (a=='`') pckbc_add_code(d, 0x0e, p); // ?
539  if (a=='\\') pckbc_add_code(d, 0x5d, p); // 0x5c?
540 
541  if (a=='z') pckbc_add_code(d, 0x1a, p);
542  if (a=='x') pckbc_add_code(d, 0x22, p);
543  if (a=='c') pckbc_add_code(d, 0x21, p);
544  if (a=='v') pckbc_add_code(d, 0x2a, p);
545  if (a=='b') pckbc_add_code(d, 0x32, p);
546  if (a=='n') pckbc_add_code(d, 0x31, p);
547  if (a=='m') pckbc_add_code(d, 0x3a, p);
548 
549  if (a==',') pckbc_add_code(d, 0x41, p);
550  if (a=='.') pckbc_add_code(d, 0x49, p);
551  if (a=='/') pckbc_add_code(d, 0x4a, p);
552 
553  if (a==' ') pckbc_add_code(d, 0x29, p);
554 
555  /* Add release code, if a key was pressed: */
556  if (d->head[p] != old_head) {
557  int code = d->key_queue[p][d->head[p]];
558  pckbc_add_code(d, 0xf0, p);
559  pckbc_add_code(d, code, p);
560  }
561 
562  /* Release shift and ctrl: */
563  if (shift) {
564  pckbc_add_code(d, 0xf0, p);
565  pckbc_add_code(d, 0x12, p);
566  }
567  if (ctrl) {
568  pckbc_add_code(d, 0xf0, p);
569  pckbc_add_code(d, 0x11, p);
570  }
571 }
572 
573 
575 {
576  bool ints_enabled = true;
577 
578  // if (d->cmdbyte & KC8_KDISABLE)
579  // ints_enabled = false;
580 
581  for (int port_nr = 0; port_nr < 2; port_nr++) {
582  /*
583  * Cause receive interrupt, if there's something in the
584  * receive buffer: (Otherwise deassert the interrupt.)
585  */
586  if (d->head[port_nr] != d->tail[port_nr] && ints_enabled && d->rx_int_enable[port_nr]) {
587  if (!d->currently_asserted[port_nr]) {
588  // fatal("[ pckbc: interrupt port %i ]\n", port_nr);
589  if (port_nr == 0)
591  else
593  }
594 
595  d->currently_asserted[port_nr] = 1;
596  } else {
597  if (d->currently_asserted[port_nr]) {
598  // fatal("[ pckbc: DEASSERT interrupt port %i ]\n", port_nr);
599  if (port_nr == 0)
601  else
603  }
604 
605  d->currently_asserted[port_nr] = 0;
606  }
607  }
608 }
609 
610 
612 {
613  struct pckbc_data *d = (struct pckbc_data *) extra;
614  int ch;
615 
616  // Keyboard input:
617  if (d->in_use) {
618  while (console_charavail(d->console_handle)) {
620  if (ch >= 0) {
621  switch (d->translation_table) {
622  case 1: ascii_to_pc_scancodes_type1(ch, d);
623  break;
624  case 2: ascii_to_pc_scancodes_type2(ch, d);
625  break;
626  case 3: ascii_to_pc_scancodes_type3(ch, d);
627  break;
628  default:fatal("[ pckbc: unimplemented translation table type %i ]\n",
629  d->translation_table);
630  }
631  }
632  }
633  }
634 
635  // Mouse input:
636  /* Don't do mouse updates if we're running in serial console mode: */
637  if (cpu->machine->x11_md.in_use && d->state[1] == STATE_NORMAL && d->scanning_enabled[1]) {
638  int mouse_x, mouse_y, mouse_buttons, mouse_fb_nr;
639  console_getmouse(&mouse_x, &mouse_y, &mouse_buttons, &mouse_fb_nr);
640 
641  int xdelta = mouse_x - d->mouse_x;
642  int ydelta = d->mouse_y - mouse_y; // note: inverted
643 
644  const int m = 100;
645 
646  if (xdelta > m)
647  xdelta = m;
648  if (xdelta < -m)
649  xdelta = -m;
650  if (ydelta > m)
651  ydelta = m;
652  if (ydelta < -m)
653  ydelta = -m;
654 
655  /* Only send update if there is an actual diff. */
656  if (xdelta != 0 || ydelta != 0 || d->mouse_buttons != mouse_buttons) {
657  d->mouse_x = mouse_x;
658  d->mouse_y = mouse_y;
660 
661  // See "The default protocol" at
662  // https://www.win.tue.nl/~aeb/linux/kbd/scancodes-13.html
663  uint8_t b1 = 0x08;
664  uint8_t b2 = xdelta;
665  uint8_t b3 = ydelta;
666 
667  b1 |= (mouse_buttons & 4) >> 2; // Left
668  b1 |= (mouse_buttons & 2) << 1; // Middle
669  b1 |= (mouse_buttons & 1) << 1; // Right
670  b1 |= ((xdelta >> 8) & 1) << 4;
671  b1 |= ((ydelta >> 8) & 1) << 5;
672 
673  // printf("x=%i y=%i b1=%02x %02x %02x\n", xdelta, ydelta, b1,b2,b3);
674 
675  pckbc_add_code(d, b1, 1);
676  pckbc_add_code(d, b2, 1);
677  pckbc_add_code(d, b3, 1);
678  }
679  }
680 
682 }
683 
684 
685 /*
686  * dev_pckbc_command():
687  *
688  * Handle commands to the 8048 in the emulated keyboard.
689  */
690 static void dev_pckbc_command(struct pckbc_data *d, int port_nr)
691 {
692  int cmd = d->type == PCKBC_8242 ? d->reg[PS2_TXBUF] : d->reg[PC_CMD];
693 
694 #if 0
695  // Mouse port debugging:
696  if (port_nr == 1)
697  fatal("[ pckbc: (port %i) command 0x%02x ]\n", port_nr, cmd);
698 #endif
699 
700  if (d->state[port_nr] == STATE_WAITING_FOR_TRANSLTABLE) {
701  debug("[ pckbc: (port %i) switching to translation table "
702  "0x%02x ]\n", port_nr, cmd);
703 
704  switch (cmd) {
705  case 0: // TODO. "Writing 0xf0 followed by 0 queries the mode,
706  // resulting in a scancode byte 43, 41 or 3f from the
707  // keyboard." according to
708  // https://www.win.tue.nl/~aeb/linux/kbd/scancodes-10.html#scancodesets
709  fatal("[ pckbc: TODO: return current translation table ]\n");
710  break;
711  case 1: // Fall-through.
712  case 2: // Fall-through.
713  case 3: d->translation_table = cmd;
714  break;
715  default:fatal("[ pckbc: (port %i) translation table "
716  "0x%02x is NOT YET IMPLEMENTED ]\n",
717  port_nr, cmd);
718  }
719 
720  // Hack for OpenBSD/cats and NetBSD/cats:
721  if (d->type != PCKBC_8242) {
722  fatal("[ pckbc: TODO: hack for non-8242. figure out how to deal with this ]\n");
723  d->translation_table = 1;
724  }
725 
726  pckbc_add_code(d, KBR_ACK, port_nr);
727  d->state[port_nr] = STATE_NORMAL;
728  return;
729  }
730 
731  if (d->state[port_nr] == STATE_WAITING_FOR_RATE) {
732  debug("[ pckbc: (port %i) received Typematic/Sample Rate data: "
733  "0x%02x ]\n", port_nr, cmd);
734  pckbc_add_code(d, KBR_ACK, port_nr);
735  d->state[port_nr] = STATE_NORMAL;
736  return;
737  }
738 
739  if (d->state[port_nr] == STATE_WAITING_FOR_ONEKEY_MB) {
740  debug("[ pckbc: (port %i) received One-key make/break data: "
741  "0x%02x ]\n", port_nr, cmd);
742  pckbc_add_code(d, KBR_ACK, port_nr);
743  d->state[port_nr] = STATE_NORMAL;
744  return;
745  }
746 
747  if (d->state[port_nr] == STATE_WAITING_FOR_AUX) {
748  debug("[ pckbc: (port %i) received aux data: "
749  "0x%02x ]\n", port_nr, cmd);
750  /* Echo back. */
751  pckbc_add_code(d, cmd, port_nr);
752  d->state[port_nr] = STATE_NORMAL;
753  return;
754  }
755 
756  if (d->state[port_nr] == STATE_WAITING_FOR_AUX_OUT) {
757  debug("[ pckbc: (port %i) received aux out data: "
758  "0x%02x ]\n", port_nr, cmd);
759  /* Echo back. */
760  pckbc_add_code(d, cmd, port_nr);
761  d->state[port_nr] = STATE_NORMAL;
762  return;
763  }
764 
765  switch (cmd) {
766 
767  case 0x00:
768  /*
769  * TODO: What does this do? This is possibly due to an
770  * error in the handling of some other command code.
771  */
772  pckbc_add_code(d, KBR_ACK, port_nr);
773  break;
774 
775  case KBC_MODEIND: /* Set LEDs */
776  /* Just ACK, no LEDs are actually set. */
777  pckbc_add_code(d, KBR_ACK, port_nr);
778  break;
779 
780  case KBC_ECHO:
781  pckbc_add_code(d, KBR_ECHO, port_nr);
782  break;
783 
784  case KBC_SETTABLE:
785  pckbc_add_code(d, KBR_ACK, port_nr);
786  d->state[port_nr] = STATE_WAITING_FOR_TRANSLTABLE;
787  break;
788 
789  case KBC_ENABLE:
790  d->scanning_enabled[port_nr] = 1;
791  pckbc_add_code(d, KBR_ACK, port_nr);
792  break;
793 
794  case KBC_DISABLE:
795  d->scanning_enabled[port_nr] = 0;
796  pckbc_add_code(d, KBR_ACK, port_nr);
797  break;
798 
799  case KBC_SETDEFAULT:
800  pckbc_add_code(d, KBR_ACK, port_nr);
801  break;
802 
803  case KBC_GETID:
804  /* Get keyboard/mouse ID. NOTE/TODO: Ugly hardcoded answer. */
805  pckbc_add_code(d, KBR_ACK, port_nr);
806 
807  if (port_nr == 0) {
808  // Keyboard:
809  pckbc_add_code(d, 0xab, port_nr);
810  pckbc_add_code(d, 0x41, port_nr);
811  } else {
812  // Mouse:
813  pckbc_add_code(d, 0x00, port_nr);
814  pckbc_add_code(d, 0x00, port_nr);
815  }
816  break;
817 
818  case KBC_TYPEMATIC:
819  /*
820  * Keyboard: Set typematic (auto-repeat) delay/speed.
821  * PS/2 mouse: Set sample ratre.
822  */
823  pckbc_add_code(d, KBR_ACK, port_nr);
824  d->state[port_nr] = STATE_WAITING_FOR_RATE;
825  break;
826 
827  case KBC_ALLKEYS_TMB:
828  /* "Make all keys typematic/make/break" */
829  pckbc_add_code(d, KBR_ACK, port_nr);
830  break;
831 
832  case KBC_ONEKEY_MB:
833  /* "Make one key typematic/make/break" */
834  pckbc_add_code(d, KBR_ACK, port_nr);
835  d->state[port_nr] = STATE_WAITING_FOR_ONEKEY_MB;
836  break;
837 
838  case KBC_RESET:
839  pckbc_add_code(d, KBR_ACK, port_nr);
840  pckbc_add_code(d, KBR_RSTDONE, port_nr);
841 
842  if (port_nr == 1) {
843  // Mouse (based on NetBSD's pckbport/pms.c) sends
844  // mouse ID after RSTDONE:
845  pckbc_add_code(d, 0x00, port_nr);
846  }
847 
848  /*
849  * Disable interrupts during reset, or Linux 2.6
850  * prints warnings about spurious interrupts.
851  */
852  // d->rx_int_enable = 0;
853  d->scanning_enabled[port_nr] = 0;
854  break;
855 
856  default:
857  pckbc_add_code(d, KBR_RESEND, port_nr); // Error
858  fatal("[ pckbc: UNIMPLEMENTED command"
859  " 0x%02x (port %i) ]\n", cmd, port_nr);
860  }
861 }
862 
863 
865 {
866  struct pckbc_data *d = (struct pckbc_data *) extra;
867  uint64_t idata = 0, odata = 0;
868  int port_nr = 0;
869  size_t i;
870 
871  if (writeflag == MEM_WRITE)
872  idata = memory_readmax64(cpu, data, len);
873 
874 #ifdef PCKBC_DEBUG
875  if (writeflag == MEM_WRITE)
876  fatal("[ pckbc: write to addr 0x%x: 0x%x ]\n",
877  (int)relative_addr, (int)idata);
878  else
879  fatal("[ pckbc: read from addr 0x%x ]\n",
880  (int)relative_addr);
881 #endif
882 
883  /* For JAZZ-based machines: */
884  if (relative_addr >= 0x60) {
885  relative_addr -= 0x60;
886  if (relative_addr != 0)
887  relative_addr = 1;
888  } else if (d->type == PCKBC_8242) {
889  /* 8242 PS2-style: */
890  /* when using 8-byte alignment... */
891  relative_addr /= sizeof(uint64_t);
892  /* port_nr = 0 for keyboard, 1 for mouse */
893  port_nr = (relative_addr >> 2);
894  relative_addr &= 3;
895  relative_addr += PS2;
896  } else if (d->pc_style_flag) {
897  /* PC-style: */
898  if (relative_addr != 0 && relative_addr != 4) {
899  /* TODO (port 0x61) */
900  odata = 0x21;
901 {
902 static int x = 0;
903 x++;
904 if (x&1)
905  odata ^= 0x10;
906 }
907  if (writeflag == MEM_READ)
908  memory_writemax64(cpu, data, len, odata);
909  return 1;
910  }
911  if (relative_addr != 0)
912  relative_addr = 1;
913  } else {
914  /* Others... Non-Jazz ARC-based machines etc. */
915  if (relative_addr != 0)
916  relative_addr = 1;
917  }
918 
919  switch (relative_addr) {
920 
921  /*
922  * 8042 (PC):
923  */
924 
925  case 0: /* data */
926  if (writeflag==MEM_READ) {
927  switch (d->state[port_nr]) {
928  case STATE_RDCMDBYTE:
929  odata = d->cmdbyte;
930  d->state[port_nr] = STATE_NORMAL;
931  break;
932  case STATE_RDOUTPUT:
933  odata = d->output_byte;
934  d->state[port_nr] = STATE_NORMAL;
935  break;
936  default:if (d->head[0] != d->tail[0]) {
937  odata = pckbc_get_code(d, 0);
938  d->last_scancode = odata;
939  } else {
940  odata = d->last_scancode;
941  d->last_scancode |= 0x80;
942  }
943  }
944  /* debug("[ pckbc: read from DATA: 0x%02x ]\n",
945  (int)odata); */
946  } else {
947  if (port_nr == 1) {
948  fatal("[ pckbc: write to DATA:");
949  for (i=0; i<len; i++)
950  fatal(" %02x", data[i]);
951  fatal(" ]\n");
952  }
953 
954  switch (d->state[port_nr]) {
955  case STATE_LDCMDBYTE:
956  d->cmdbyte = idata;
957  d->rx_int_enable[port_nr] = d->cmdbyte &
958  (KC8_KENABLE | KC8_MENABLE) ? 1 : 0;
959  d->state[port_nr] = STATE_NORMAL;
960  break;
961  case STATE_LDOUTPUT:
962  d->output_byte = idata;
963  d->state[port_nr] = STATE_NORMAL;
964  break;
965  default:d->reg[relative_addr] = idata;
966  dev_pckbc_command(d, port_nr);
967  }
968  }
969  break;
970  case 1: /* control */
971  if (writeflag==MEM_READ) {
972  odata = 0;
973 
974  /* "Data in buffer" bit */
975  if (d->head[0] != d->tail[0] ||
976  d->state[port_nr] == STATE_RDCMDBYTE ||
977  d->state[port_nr] == STATE_RDOUTPUT)
978  odata |= KBS_DIB;
979 
980  if (d->state[port_nr] == STATE_RDCMDBYTE)
981  odata |= KBS_OCMD;
982 
983  odata |= KBS_NOSEC;
984  /* debug("[ pckbc: read from CTL status port: "
985  "0x%02x ]\n", (int)odata); */
986  } else {
987  debug("[ pckbc: write to CTL:");
988  for (i=0; i<len; i++)
989  debug(" %02x", data[i]);
990  debug(" ]\n");
991  d->reg[relative_addr] = idata;
992 
993  switch (idata) {
994  case 0x10:
995  case 0x11:
996  /* TODO: For now, don't print warnings about
997  these. NetBSD sends these. */
998  break;
999  case K_RDCMDBYTE:
1000  d->state[port_nr] = STATE_RDCMDBYTE;
1001  break;
1002  case K_LDCMDBYTE:
1003  d->state[port_nr] = STATE_LDCMDBYTE;
1004  break;
1005  case 0xa7:
1006  d->cmdbyte |= KC8_MDISABLE;
1007  break;
1008  case 0xa8:
1009  d->cmdbyte &= ~KC8_MDISABLE;
1010  break;
1011  case 0xa9: /* test auxiliary port */
1012  debug("[ pckbc: CONTROL 0xa9, TODO ]\n");
1013  break;
1014  case 0xaa: /* keyboard self-test */
1015  pckbc_add_code(d, 0x55, port_nr);
1016  break;
1017  case 0xab: /* keyboard interface self-test */
1018  pckbc_add_code(d, 0x00, port_nr);
1019  break;
1020  case 0xad:
1021  d->cmdbyte |= KC8_KDISABLE;
1022  break;
1023  case 0xae:
1024  d->cmdbyte &= ~KC8_KDISABLE;
1025  break;
1026  case 0xd0:
1027  d->state[port_nr] = STATE_RDOUTPUT;
1028  break;
1029  case 0xd1:
1030  d->state[port_nr] = STATE_LDOUTPUT;
1031  break;
1032  case 0xd3: /* write to auxiliary device
1033  output buffer */
1034  debug("[ pckbc: CONTROL 0xd3, TODO ]\n");
1035  d->state[port_nr] = STATE_WAITING_FOR_AUX_OUT;
1036  break;
1037  case 0xd4: /* write to auxiliary port */
1038  debug("[ pckbc: CONTROL 0xd4, TODO ]\n");
1039  d->state[port_nr] = STATE_WAITING_FOR_AUX;
1040  break;
1041  default:
1042  fatal("[ pckbc: unknown CONTROL 0x%x ]\n",
1043  (int)idata);
1044  d->state[port_nr] = STATE_NORMAL;
1045  }
1046  }
1047  break;
1048 
1049  /*
1050  * 8242 (PS2):
1051  */
1052 
1053  case PS2 + PS2_TXBUF:
1054  if (writeflag==MEM_READ) {
1055  odata = random() & 0xff;
1056  debug("[ pckbc: read from port %i, PS2_TXBUF: "
1057  "0x%x ]\n", port_nr, (int)odata);
1058  } else {
1059  debug("[ pckbc: write to port %i, PS2_TXBUF: "
1060  "0x%llx ]\n", port_nr, (long long)idata);
1061 
1062  /* Handle keyboard commands: */
1063  d->reg[PS2_TXBUF] = idata;
1064  dev_pckbc_command(d, port_nr);
1065  }
1066  break;
1067 
1068  case PS2 + PS2_RXBUF:
1069  if (writeflag==MEM_READ) {
1070  /* TODO: What should be returned if no data
1071  is available? */
1072  odata = 0;
1073  if (d->head[port_nr] != d->tail[port_nr])
1074  odata = pckbc_get_code(d, port_nr);
1075  debug("[ pckbc: read from port %i, PS2_RXBUF: "
1076  "0x%02x ]\n", port_nr, (int)odata);
1077  } else {
1078  debug("[ pckbc: write to port %i, PS2_RXBUF: "
1079  "0x%llx ]\n", port_nr, (long long)idata);
1080  }
1081  break;
1082 
1083  case PS2 + PS2_CONTROL:
1084  if (writeflag==MEM_READ) {
1085  debug("[ pckbc: read from port %i, PS2_CONTROL"
1086  " ]\n", port_nr);
1087  } else {
1088  debug("[ pckbc: write to port %i, PS2_CONTROL:"
1089  " 0x%llx ]\n", port_nr, (long long)idata);
1090  d->clocksignal = (idata & 0x10) ? 1 : 0;
1091  d->rx_int_enable[port_nr] = (idata & PS2_CONTROL_RXINTEN) ? 1 : 0;
1092  d->tx_int_enable[port_nr] = (idata & PS2_CONTROL_TXINTEN) ? 1 : 0;
1093 
1094  // HACK/TODO: NetBSD/sgimips' X11 seems to work when
1095  // interrupts are enabled, but it seems to not turn
1096  // them on. Having this here makes it work, but it not
1097  // the correct solution.
1098  if (port_nr == 1) {
1099  d->rx_int_enable[port_nr] = 1;
1100  }
1101  }
1102  break;
1103 
1104  case PS2 + PS2_STATUS:
1105  if (writeflag==MEM_READ) {
1106  odata = d->clocksignal + PS2_STATUS_TXEMPTY;
1107 
1108  if (d->head[port_nr] != d->tail[port_nr]) {
1109  /* receiced data available */
1110  odata |= PS2_STATUS_RXFULL;
1111  }
1112 
1113  //debug("[ pckbc: read from port %i, PS2_STATUS: "
1114  // "0x%llx ]\n", port_nr, (long long)odata);
1115  } else {
1116  debug("[ pckbc: write to port %i, PS2_STATUS: "
1117  "0x%llx ]\n", port_nr, (long long)idata);
1118  }
1119  break;
1120 
1121  default:
1122  if (writeflag==MEM_READ) {
1123  debug("[ pckbc: read from unimplemented reg %i ]\n",
1124  (int)relative_addr);
1125  odata = d->reg[relative_addr % DEV_PCKBC_LENGTH];
1126  } else {
1127  debug("[ pckbc: write to unimplemented reg %i:",
1128  (int)relative_addr);
1129  for (i=0; i<len; i++)
1130  debug(" %02x", data[i]);
1131  debug(" ]\n");
1132  d->reg[relative_addr % DEV_PCKBC_LENGTH] = idata;
1133  }
1134  }
1135 
1136  /* SGI? TODO: fix */
1137 #if 0
1138  if (len == 8)
1139  odata |= (odata << 8) | (odata << 16) | (odata << 24) |
1140  (odata << 32) | (odata << 40) | (odata << 48) |
1141  (odata << 56);
1142 #endif
1143  if (writeflag == MEM_READ)
1144  memory_writemax64(cpu, data, len, odata);
1145 
1147 
1148  return 1;
1149 }
1150 
1151 
1152 /*
1153  * dev_pckbc_init():
1154  *
1155  * Type should be PCKBC_8042 or PCKBC_8242.
1156  */
1157 int dev_pckbc_init(struct machine *machine, struct memory *mem,
1158  uint64_t baseaddr, int type, char *keyboard_irqpath,
1159  char *mouse_irqpath, int in_use, int pc_style_flag)
1160 {
1161  struct pckbc_data *d;
1162  int len = DEV_PCKBC_LENGTH;
1163 
1164  CHECK_ALLOCATION(d = (struct pckbc_data *) malloc(sizeof(struct pckbc_data)));
1165  memset(d, 0, sizeof(struct pckbc_data));
1166 
1167  d->translation_table = 2;
1168 
1169  if (type == PCKBC_8242) {
1170  len = 0x40;
1171  d->translation_table = 3;
1172  }
1173 
1174  if (type == PCKBC_JAZZ) {
1175  type = PCKBC_8042;
1176  len = DEV_PCKBC_LENGTH + 0x60;
1177  }
1178 
1179  INTERRUPT_CONNECT(keyboard_irqpath, d->irq_keyboard);
1180  INTERRUPT_CONNECT(mouse_irqpath, d->irq_mouse);
1181 
1182  d->type = type;
1183  d->in_use = in_use;
1185  d->rx_int_enable[0] = 1;
1186  d->rx_int_enable[1] = 0;
1187  d->output_byte = 0x02; /* A20 enable on PCs */
1188 
1189  // Default is ENABLE keyboard but DISABLE mouse port:
1190  d->scanning_enabled[0] = 1;
1191  d->scanning_enabled[1] = 0;
1192 
1194  machine, "pckbc", d->in_use);
1195 
1196  memory_device_register(mem, "pckbc", baseaddr,
1197  len, dev_pckbc_access, d, DM_DEFAULT, NULL);
1198  machine_add_tickfunction(machine, dev_pckbc_tick, d,
1199  PCKBC_TICKSHIFT);
1200 
1201  return d->console_handle;
1202 }
1203 
data
u_short data
Definition: siireg.h:79
pckbc_data::mouse_y
int mouse_y
Definition: dev_pckbc.cc:110
pckbc_data::irq_mouse
struct interrupt irq_mouse
Definition: dev_pckbc.cc:89
STATE_RDCMDBYTE
#define STATE_RDCMDBYTE
Definition: dev_pckbc.cc:116
INTERRUPT_CONNECT
#define INTERRUPT_CONNECT(name, istruct)
Definition: interrupt.h:77
PS2_RXBUF
#define PS2_RXBUF
Definition: dev_pckbc.cc:69
PS2_TXBUF
#define PS2_TXBUF
Definition: dev_pckbc.cc:68
INTERRUPT_ASSERT
#define INTERRUPT_ASSERT(istruct)
Definition: interrupt.h:74
DEVICE_TICK
DEVICE_TICK(pckbc)
Definition: dev_pckbc.cc:611
pckbc_data::tx_int_enable
int tx_int_enable[2]
Definition: dev_pckbc.cc:97
memory
Definition: memory.h:75
KC8_KENABLE
#define KC8_KENABLE
Definition: kbdreg.h:64
debug
#define debug
Definition: dev_adb.cc:57
PCKBC_8042
#define PCKBC_8042
Definition: devices.h:320
KBC_DISABLE
#define KBC_DISABLE
Definition: kbdreg.h:73
PS2_CONTROL_TXINTEN
#define PS2_CONTROL_TXINTEN
Definition: dev_pckbc.cc:71
kbdreg.h
pckbc_data::pc_style_flag
int pc_style_flag
Definition: dev_pckbc.cc:92
STATE_RDOUTPUT
#define STATE_RDOUTPUT
Definition: dev_pckbc.cc:123
STATE_WAITING_FOR_RATE
#define STATE_WAITING_FOR_RATE
Definition: dev_pckbc.cc:118
KBC_TYPEMATIC
#define KBC_TYPEMATIC
Definition: kbdreg.h:75
pckbc_data::console_handle
int console_handle
Definition: dev_pckbc.cc:83
console_getmouse
void console_getmouse(int *x, int *y, int *buttons, int *fb_nr)
Definition: console.cc:497
memory_device_register
void memory_device_register(struct memory *mem, const char *, uint64_t baseaddr, uint64_t len, int(*f)(struct cpu *, struct memory *, uint64_t, unsigned char *, size_t, int, void *), void *extra, int flags, unsigned char *dyntrans_data)
Definition: memory.cc:339
STATE_WAITING_FOR_AUX
#define STATE_WAITING_FOR_AUX
Definition: dev_pckbc.cc:120
MEM_READ
#define MEM_READ
Definition: memory.h:116
console_start_slave_inputonly
int console_start_slave_inputonly(struct machine *machine, const char *consolename, int use_for_input)
Definition: console.cc:714
pckbc_add_code
void pckbc_add_code(struct pckbc_data *d, int code, int port)
Definition: dev_pckbc.cc:131
DM_DEFAULT
#define DM_DEFAULT
Definition: memory.h:130
KBC_SETTABLE
#define KBC_SETTABLE
Definition: kbdreg.h:77
console.h
console_charavail
int console_charavail(int handle)
Definition: console.cc:336
KBC_RESET
#define KBC_RESET
Definition: kbdreg.h:68
PS2_CONTROL
#define PS2_CONTROL
Definition: dev_pckbc.cc:70
pckbc_data::rx_int_enable
int rx_int_enable[2]
Definition: dev_pckbc.cc:96
cmd
Definition: debugger_cmds.cc:1189
MEM_WRITE
#define MEM_WRITE
Definition: memory.h:117
STATE_LDOUTPUT
#define STATE_LDOUTPUT
Definition: dev_pckbc.cc:122
MAX_8042_QUEUELEN
#define MAX_8042_QUEUELEN
Definition: dev_pckbc.cc:62
pckbc_data::tail
int tail[2]
Definition: dev_pckbc.cc:107
STATE_LDCMDBYTE
#define STATE_LDCMDBYTE
Definition: dev_pckbc.cc:115
PS2_STATUS_TXEMPTY
#define PS2_STATUS_TXEMPTY
Definition: dev_pckbc.cc:74
KBC_MODEIND
#define KBC_MODEIND
Definition: kbdreg.h:79
machine_add_tickfunction
void machine_add_tickfunction(struct machine *machine, void(*func)(struct cpu *, void *), void *extra, int clockshift)
Definition: machine.cc:280
pckbc_data::output_byte
int output_byte
Definition: dev_pckbc.cc:103
pckbc_reassert_interrupts
void pckbc_reassert_interrupts(struct pckbc_data *d)
Definition: dev_pckbc.cc:574
STATE_WAITING_FOR_AUX_OUT
#define STATE_WAITING_FOR_AUX_OUT
Definition: dev_pckbc.cc:121
pckbc_data::cmdbyte
int cmdbyte
Definition: dev_pckbc.cc:102
fatal
void fatal(const char *fmt,...)
Definition: main.cc:152
x11_md::in_use
int in_use
Definition: machine.h:82
pckbc_data::irq_keyboard
struct interrupt irq_keyboard
Definition: dev_pckbc.cc:88
misc.h
KC8_KDISABLE
#define KC8_KDISABLE
Definition: kbdreg.h:60
memory_readmax64
uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
Definition: memory.cc:55
machine.h
machine
Definition: machine.h:97
console_readchar
int console_readchar(int handle)
Definition: console.cc:385
KBR_ECHO
#define KBR_ECHO
Definition: kbdreg.h:89
pckbc_data::in_use
int in_use
Definition: dev_pckbc.cc:84
KBR_RESEND
#define KBR_RESEND
Definition: kbdreg.h:83
KBS_NOSEC
#define KBS_NOSEC
Definition: kbdreg.h:46
machine::x11_md
struct x11_md x11_md
Definition: machine.h:179
PCKBC_JAZZ
#define PCKBC_JAZZ
Definition: devices.h:322
KBR_RSTDONE
#define KBR_RSTDONE
Definition: kbdreg.h:88
cpu.h
STATE_WAITING_FOR_TRANSLTABLE
#define STATE_WAITING_FOR_TRANSLTABLE
Definition: dev_pckbc.cc:117
PS2_STATUS
#define PS2_STATUS
Definition: dev_pckbc.cc:73
pckbc_data::translation_table
int translation_table
Definition: dev_pckbc.cc:100
KBC_SETDEFAULT
#define KBC_SETDEFAULT
Definition: kbdreg.h:72
PS2
#define PS2
Definition: dev_pckbc.cc:77
STATE_WAITING_FOR_ONEKEY_MB
#define STATE_WAITING_FOR_ONEKEY_MB
Definition: dev_pckbc.cc:119
K_LDCMDBYTE
#define K_LDCMDBYTE
Definition: kbdreg.h:56
pckbc_data::currently_asserted
int currently_asserted[2]
Definition: dev_pckbc.cc:90
dev_pckbc_init
int dev_pckbc_init(struct machine *machine, struct memory *mem, uint64_t baseaddr, int type, char *keyboard_irqpath, char *mouse_irqpath, int in_use, int pc_style_flag)
Definition: dev_pckbc.cc:1157
PCKBC_TICKSHIFT
#define PCKBC_TICKSHIFT
Definition: dev_pckbc.cc:79
cpu::machine
struct machine * machine
Definition: cpu.h:328
KBS_OCMD
#define KBS_OCMD
Definition: kbdreg.h:45
KBC_ONEKEY_MB
#define KBC_ONEKEY_MB
Definition: kbdreg.h:70
pckbc_data::head
int head[2]
Definition: dev_pckbc.cc:107
pckbc_data::mouse_x
int mouse_x
Definition: dev_pckbc.cc:109
KBC_ENABLE
#define KBC_ENABLE
Definition: kbdreg.h:74
PS2_STATUS_RXFULL
#define PS2_STATUS_RXFULL
Definition: dev_pckbc.cc:75
K_RDCMDBYTE
#define K_RDCMDBYTE
Definition: kbdreg.h:55
INTERRUPT_DEASSERT
#define INTERRUPT_DEASSERT(istruct)
Definition: interrupt.h:75
DEVICE_ACCESS
DEVICE_ACCESS(pckbc)
Definition: dev_pckbc.cc:864
KBR_ACK
#define KBR_ACK
Definition: kbdreg.h:84
pckbc_data
Definition: dev_pckbc.cc:82
PC_CMD
#define PC_CMD
Definition: dev_pckbc.cc:65
pckbc_data::last_scancode
int last_scancode
Definition: dev_pckbc.cc:104
pckbc_data::scanning_enabled
int scanning_enabled[2]
Definition: dev_pckbc.cc:99
KBC_ALLKEYS_TMB
#define KBC_ALLKEYS_TMB
Definition: kbdreg.h:71
pckbc_data::state
int state[2]
Definition: dev_pckbc.cc:101
interrupt
Definition: interrupt.h:36
pckbc_data::mouse_buttons
int mouse_buttons
Definition: dev_pckbc.cc:111
memory_writemax64
void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len, uint64_t data)
Definition: memory.cc:89
PS2_CONTROL_RXINTEN
#define PS2_CONTROL_RXINTEN
Definition: dev_pckbc.cc:72
pckbc_data::reg
int reg[DEV_PCKBC_LENGTH]
Definition: dev_pckbc.cc:86
DEV_PCKBC_LENGTH
#define DEV_PCKBC_LENGTH
Definition: devices.h:319
devices.h
PCKBC_8242
#define PCKBC_8242
Definition: devices.h:321
cpu
Definition: cpu.h:326
KC8_MENABLE
#define KC8_MENABLE
Definition: kbdreg.h:63
STATE_NORMAL
#define STATE_NORMAL
Definition: dev_pckbc.cc:114
pckbc_get_code
int pckbc_get_code(struct pckbc_data *d, int port)
Definition: dev_pckbc.cc:147
KBC_ECHO
#define KBC_ECHO
Definition: kbdreg.h:78
KC8_MDISABLE
#define KC8_MDISABLE
Definition: kbdreg.h:59
pckbc_data::clocksignal
int clocksignal
Definition: dev_pckbc.cc:95
memory.h
pckbc_data::type
int type
Definition: dev_pckbc.cc:91
KBC_GETID
#define KBC_GETID
Definition: kbdreg.h:76
dev_pckbc_access
int dev_pckbc_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr, unsigned char *data, size_t len, int writeflag, void *)
pckbc_data::key_queue
unsigned key_queue[2][MAX_8042_QUEUELEN]
Definition: dev_pckbc.cc:106
KBS_DIB
#define KBS_DIB
Definition: kbdreg.h:42
CHECK_ALLOCATION
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239

Generated on Tue Mar 24 2020 14:04:48 for GXemul by doxygen 1.8.17