/[gxemul]/trunk/src/devices/dev_pckbc.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/src/devices/dev_pckbc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 6 by dpavlin, Mon Oct 8 16:18:11 2007 UTC revision 30 by dpavlin, Mon Oct 8 16:20:40 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2003-2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2003-2006  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *     *  
27   *   *
28   *  $Id: dev_pckbc.c,v 1.45 2005/06/02 15:42:49 debug Exp $   *  $Id: dev_pckbc.c,v 1.69 2006/07/25 18:58:02 debug Exp $
29   *     *  
30   *  Standard 8042 PC keyboard controller (and a 8242WB PS2 keyboard/mouse   *  Standard 8042 PC keyboard controller (and a 8242WB PS2 keyboard/mouse
31   *  controller), including the 8048 keyboard chip.   *  controller), including the 8048 keyboard chip.
32   *   *
33     *  Quick source of good info: http://my.execpc.com/~geezer/osd/kbd/kbd.txt
34   *   *
35   *  TODO: Finish the rewrite for 8242.   *
36     *  TODOs:
37     *      Finish the rewrite for 8242.
38   */   */
39    
40  #include <stdio.h>  #include <stdio.h>
# Line 49  Line 52 
52    
53    
54  /*  #define PCKBC_DEBUG  */  /*  #define PCKBC_DEBUG  */
55    /*  #define debug fatal  */
56    
57    
58  #define MAX_8042_QUEUELEN       256  #define MAX_8042_QUEUELEN       256
# Line 64  Line 68 
68    
69  #define PS2     100  #define PS2     100
70    
71  #define PCKBC_TICKSHIFT         14  #define PCKBC_TICKSHIFT         15
72    
73  struct pckbc_data {  struct pckbc_data {
74          int             console_handle;          int             console_handle;
# Line 73  struct pckbc_data { Line 77  struct pckbc_data {
77          int             reg[DEV_PCKBC_LENGTH];          int             reg[DEV_PCKBC_LENGTH];
78          int             keyboard_irqnr;          int             keyboard_irqnr;
79          int             mouse_irqnr;          int             mouse_irqnr;
80            int             currently_asserted[2];
81          int             type;          int             type;
82          int             pc_style_flag;          int             pc_style_flag;
83    
# Line 82  struct pckbc_data { Line 87  struct pckbc_data {
87          int             tx_int_enable;          int             tx_int_enable;
88    
89          int             keyscanning_enabled;          int             keyscanning_enabled;
90            int             translation_table;
91          int             state;          int             state;
92          int             cmdbyte;          int             cmdbyte;
93          int             output_byte;          int             output_byte;
# Line 95  struct pckbc_data { Line 101  struct pckbc_data {
101  #define STATE_LDCMDBYTE                 1  #define STATE_LDCMDBYTE                 1
102  #define STATE_RDCMDBYTE                 2  #define STATE_RDCMDBYTE                 2
103  #define STATE_WAITING_FOR_TRANSLTABLE   3  #define STATE_WAITING_FOR_TRANSLTABLE   3
104  #define STATE_LDOUTPUT                  4  #define STATE_WAITING_FOR_RATE          4
105  #define STATE_RDOUTPUT                  5  #define STATE_WAITING_FOR_ONEKEY_MB     5
106    #define STATE_WAITING_FOR_AUX           6
107    #define STATE_WAITING_FOR_AUX_OUT       7
108    #define STATE_LDOUTPUT                  8
109    #define STATE_RDOUTPUT                  9
110    
111    
112  /*  /*
# Line 131  int pckbc_get_code(struct pckbc_data *d, Line 141  int pckbc_get_code(struct pckbc_data *d,
141    
142    
143  /*  /*
144   *  ascii_to_scancodes():   *  ascii_to_scancodes_type3():
145     *
146     *  Conversion from ASCII codes to default (US) keyboard scancodes.
147     *  (See http://www.computer-engineering.org/ps2keyboard/scancodes3.html)
148     */
149    static void ascii_to_pc_scancodes_type3(int a, struct pckbc_data *d)
150    {
151            int old_head;
152            int p = 0;      /*  port  */
153            int shift = 0, ctrl = 0;
154    
155            if (a >= 'A' && a <= 'Z') { a += 32; shift = 1; }
156            if ((a >= 1 && a <= 26) && (a!='\n' && a!='\t' && a!='\b' && a!='\r'))
157                    { a += 96; ctrl = 1; }
158            if (a=='!')  {  a = '1'; shift = 1; }
159            if (a=='@')  {  a = '2'; shift = 1; }
160            if (a=='#')  {  a = '3'; shift = 1; }
161            if (a=='$')  {  a = '4'; shift = 1; }
162            if (a=='%')  {  a = '5'; shift = 1; }
163            if (a=='^')  {  a = '6'; shift = 1; }
164            if (a=='&')  {  a = '7'; shift = 1; }
165            if (a=='*')  {  a = '8'; shift = 1; }
166            if (a=='(')  {  a = '9'; shift = 1; }
167            if (a==')')  {  a = '0'; shift = 1; }
168            if (a=='_')  {  a = '-'; shift = 1; }
169            if (a=='+')  {  a = '='; shift = 1; }
170            if (a=='{')  {  a = '['; shift = 1; }
171            if (a=='}')  {  a = ']'; shift = 1; }
172            if (a==':')  {  a = ';'; shift = 1; }
173            if (a=='"')  {  a = '\''; shift = 1; }
174            if (a=='|')  {  a = '\\'; shift = 1; }
175            if (a=='<')  {  a = ','; shift = 1; }
176            if (a=='>')  {  a = '.'; shift = 1; }
177            if (a=='?')  {  a = '/'; shift = 1; }
178    
179            if (shift)
180                    pckbc_add_code(d, 0x12, p);
181            if (ctrl)
182                    pckbc_add_code(d, 0x11, p);
183    
184            /*
185             *  Note: The ugly hack used to add release codes for all of these
186             *  keys is as follows:  we remember how much of the kbd buf that
187             *  is in use here, before we add any scancode. After we've added
188             *  one or more scancodes (ie an optional shift + another key)
189             *  then we add 0xf0 + the last scancode _if_ the kbd buf was altered.
190             */
191    
192            old_head = d->head[p];
193    
194            if (a==27)      pckbc_add_code(d, 0x08, p);
195    
196            if (a=='1')     pckbc_add_code(d, 0x16, p);
197            if (a=='2')     pckbc_add_code(d, 0x1e, p);
198            if (a=='3')     pckbc_add_code(d, 0x26, p);
199            if (a=='4')     pckbc_add_code(d, 0x25, p);
200            if (a=='5')     pckbc_add_code(d, 0x2e, p);
201            if (a=='6')     pckbc_add_code(d, 0x36, p);
202            if (a=='7')     pckbc_add_code(d, 0x3d, p);
203            if (a=='8')     pckbc_add_code(d, 0x3e, p);
204            if (a=='9')     pckbc_add_code(d, 0x46, p);
205            if (a=='0')     pckbc_add_code(d, 0x45, p);
206            if (a=='-')     pckbc_add_code(d, 0x4e, p);
207            if (a=='=')     pckbc_add_code(d, 0x55, p);
208    
209            if (a=='\b')    pckbc_add_code(d, 0x29, p);
210    
211            if (a=='\t')    pckbc_add_code(d, 0x0d, p);
212            if (a=='q')     pckbc_add_code(d, 0x15, p);
213            if (a=='w')     pckbc_add_code(d, 0x1d, p);
214            if (a=='e')     pckbc_add_code(d, 0x24, p);
215            if (a=='r')     pckbc_add_code(d, 0x2d, p);
216            if (a=='t')     pckbc_add_code(d, 0x2c, p);
217            if (a=='y')     pckbc_add_code(d, 0x35, p);
218            if (a=='u')     pckbc_add_code(d, 0x3c, p);
219            if (a=='i')     pckbc_add_code(d, 0x43, p);
220            if (a=='o')     pckbc_add_code(d, 0x44, p);
221            if (a=='p')     pckbc_add_code(d, 0x4d, p);
222    
223            if (a=='[')     pckbc_add_code(d, 0x54, p);
224            if (a==']')     pckbc_add_code(d, 0x5b, p);
225    
226            if (a=='\n' || a=='\r') pckbc_add_code(d, 0x5a, p);
227    
228            if (a=='a')     pckbc_add_code(d, 0x1c, p);
229            if (a=='s')     pckbc_add_code(d, 0x1b, p);
230            if (a=='d')     pckbc_add_code(d, 0x23, p);
231            if (a=='f')     pckbc_add_code(d, 0x2b, p);
232            if (a=='g')     pckbc_add_code(d, 0x34, p);
233            if (a=='h')     pckbc_add_code(d, 0x33, p);
234            if (a=='j')     pckbc_add_code(d, 0x3b, p);
235            if (a=='k')     pckbc_add_code(d, 0x42, p);
236            if (a=='l')     pckbc_add_code(d, 0x4b, p);
237    
238            if (a==';')     pckbc_add_code(d, 0x4c, p);
239            if (a=='\'')    pckbc_add_code(d, 0x52, p);
240    /*      if (a=='~')     pckbc_add_code(d, 0x29, p);  ?  */
241            if (a=='\\')    pckbc_add_code(d, 0x5c, p);
242    
243            if (a=='z')     pckbc_add_code(d, 0x1a, p);
244            if (a=='x')     pckbc_add_code(d, 0x22, p);
245            if (a=='c')     pckbc_add_code(d, 0x21, p);
246            if (a=='v')     pckbc_add_code(d, 0x2a, p);
247            if (a=='b')     pckbc_add_code(d, 0x32, p);
248            if (a=='n')     pckbc_add_code(d, 0x31, p);
249            if (a=='m')     pckbc_add_code(d, 0x3a, p);
250    
251            if (a==',')     pckbc_add_code(d, 0x41, p);
252            if (a=='.')     pckbc_add_code(d, 0x49, p);
253            if (a=='/')     pckbc_add_code(d, 0x4a, p);
254    
255            if (a==' ')     pckbc_add_code(d, 0x29, p);
256    
257            /*  Add release code, if a key was pressed:  */
258            if (d->head[p] != old_head) {
259                    int code = d->key_queue[p][d->head[p]];
260                    pckbc_add_code(d, 0xf0, p);
261                    pckbc_add_code(d, code, p);
262            }
263    
264            /*  Release shift and ctrl:  */
265            if (shift) {
266                    pckbc_add_code(d, 0xf0, p);
267                    pckbc_add_code(d, 0x12, p);
268            }
269            if (ctrl) {
270                    pckbc_add_code(d, 0xf0, p);
271                    pckbc_add_code(d, 0x11, p);
272            }
273    }
274    
275    
276    /*
277     *  ascii_to_scancodes_type2():
278   *   *
279   *  Conversion from ASCII codes to default (US) keyboard scancodes.   *  Conversion from ASCII codes to default (US) keyboard scancodes.
280   *  (See http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html)   *  (See http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html)
281     *
282     *  NOTE/TODO: This seems to be type 2, not type 1.
283   */   */
284  static void ascii_to_pc_scancodes(int a, struct pckbc_data *d)  static void ascii_to_pc_scancodes_type2(int a, struct pckbc_data *d)
285  {  {
286          int old_head;          int old_head;
287          int p = 0;      /*  port  */          int p = 0;      /*  port  */
288          int shift = 0, ctrl = 0;          int shift = 0, ctrl = 0;
289    
290            if (d->translation_table == 3) {
291                    ascii_to_pc_scancodes_type3(a, d);
292                    return;
293            }
294    
295            if (d->translation_table != 2) {
296                    fatal("[ ascii_to_pc_scancodes: unimplemented type! ]\n");
297                    return;
298            }
299    
300          if (a >= 'A' && a <= 'Z') { a += 32; shift = 1; }          if (a >= 'A' && a <= 'Z') { a += 32; shift = 1; }
301          if ((a >= 1 && a <= 26) && (a!='\n' && a!='\t' && a!='\b' && a!='\r'))          if ((a >= 1 && a <= 26) && (a!='\n' && a!='\t' && a!='\b' && a!='\r'))
302                  { a += 96; ctrl = 1; }                  { a += 96; ctrl = 1; }
303    
304            if (a=='!')  {  a = '1'; shift = 1; }
305            if (a=='@')  {  a = '2'; shift = 1; }
306            if (a=='#')  {  a = '3'; shift = 1; }
307            if (a=='$')  {  a = '4'; shift = 1; }
308            if (a=='%')  {  a = '5'; shift = 1; }
309            if (a=='^')  {  a = '6'; shift = 1; }
310            if (a=='&')  {  a = '7'; shift = 1; }
311            if (a=='*')  {  a = '8'; shift = 1; }
312            if (a=='(')  {  a = '9'; shift = 1; }
313            if (a==')')  {  a = '0'; shift = 1; }
314            if (a=='_')  {  a = '-'; shift = 1; }
315            if (a=='+')  {  a = '='; shift = 1; }
316            if (a=='{')  {  a = '['; shift = 1; }
317            if (a=='}')  {  a = ']'; shift = 1; }
318            if (a==':')  {  a = ';'; shift = 1; }
319            if (a=='"')  {  a = '\''; shift = 1; }
320            if (a=='|')  {  a = '\\'; shift = 1; }
321            if (a=='<')  {  a = ','; shift = 1; }
322            if (a=='>')  {  a = '.'; shift = 1; }
323            if (a=='?')  {  a = '/'; shift = 1; }
324            if (a=='~')  {  a = '`'; shift = 1; }
325    
326          if (shift)          if (shift)
327                  pckbc_add_code(d, 0x2a, p);                  pckbc_add_code(d, 0x2a, p);
328          else          else
# Line 198  static void ascii_to_pc_scancodes(int a, Line 375  static void ascii_to_pc_scancodes(int a,
375                          pckbc_add_code(d, 0x09, p); }                          pckbc_add_code(d, 0x09, p); }
376          if (a=='(')  {  pckbc_add_code(d, 0x2a, p);          if (a=='(')  {  pckbc_add_code(d, 0x2a, p);
377                          pckbc_add_code(d, 0x0a, p); }                          pckbc_add_code(d, 0x0a, p); }
         if (a==')')  {  pckbc_add_code(d, 0x2a, p);  
                         pckbc_add_code(d, 0x0b, p); }  
         if (a=='_')  {  pckbc_add_code(d, 0x2a, p);  
                         pckbc_add_code(d, 0x0c, p); }  
         if (a=='+')  {  pckbc_add_code(d, 0x2a, p);  
                         pckbc_add_code(d, 0x0d, p); }  
378    
379          if (a=='\b')    pckbc_add_code(d, 0x0e, p);          if (a=='\b')    pckbc_add_code(d, 0x0e, p);
380    
# Line 220  static void ascii_to_pc_scancodes(int a, Line 391  static void ascii_to_pc_scancodes(int a,
391          if (a=='p')     pckbc_add_code(d, 0x19, p);          if (a=='p')     pckbc_add_code(d, 0x19, p);
392    
393          if (a=='[')     pckbc_add_code(d, 0x1a, p);          if (a=='[')     pckbc_add_code(d, 0x1a, p);
         if (a=='{')  {  pckbc_add_code(d, 0x2a, p);  
                         pckbc_add_code(d, 0x1a, p); }  
394          if (a==']')     pckbc_add_code(d, 0x1b, p);          if (a==']')     pckbc_add_code(d, 0x1b, p);
         if (a=='}')  {  pckbc_add_code(d, 0x2a, p);  
                         pckbc_add_code(d, 0x1b, p); }  
395    
396          if (a=='\n' || a=='\r') pckbc_add_code(d, 0x1c, p);          if (a=='\n' || a=='\r') pckbc_add_code(d, 0x1c, p);
397    
# Line 239  static void ascii_to_pc_scancodes(int a, Line 406  static void ascii_to_pc_scancodes(int a,
406          if (a=='l')     pckbc_add_code(d, 0x26, p);          if (a=='l')     pckbc_add_code(d, 0x26, p);
407    
408          if (a==';')     pckbc_add_code(d, 0x27, p);          if (a==';')     pckbc_add_code(d, 0x27, p);
         if (a==':')  {  pckbc_add_code(d, 0x2a, p);  
                         pckbc_add_code(d, 0x27, p); }  
409          if (a=='\'')    pckbc_add_code(d, 0x28, p);          if (a=='\'')    pckbc_add_code(d, 0x28, p);
410          if (a=='"')  {  pckbc_add_code(d, 0x2a, p);          if (a=='`')     pckbc_add_code(d, 0x29, p);
                         pckbc_add_code(d, 0x28, p); }  
         if (a=='~')     pckbc_add_code(d, 0x29, p);  
   
411          if (a=='\\')    pckbc_add_code(d, 0x2b, p);          if (a=='\\')    pckbc_add_code(d, 0x2b, p);
         if (a=='|')  {  pckbc_add_code(d, 0x2a, p);  
                         pckbc_add_code(d, 0x2b, p); }  
412    
413          if (a=='z')     pckbc_add_code(d, 0x2c, p);          if (a=='z')     pckbc_add_code(d, 0x2c, p);
414          if (a=='x')     pckbc_add_code(d, 0x2d, p);          if (a=='x')     pckbc_add_code(d, 0x2d, p);
# Line 259  static void ascii_to_pc_scancodes(int a, Line 419  static void ascii_to_pc_scancodes(int a,
419          if (a=='m')     pckbc_add_code(d, 0x32, p);          if (a=='m')     pckbc_add_code(d, 0x32, p);
420    
421          if (a==',')     pckbc_add_code(d, 0x33, p);          if (a==',')     pckbc_add_code(d, 0x33, p);
         if (a=='<')  {  pckbc_add_code(d, 0x2a, p);  
                         pckbc_add_code(d, 0x33, p); }  
422          if (a=='.')     pckbc_add_code(d, 0x34, p);          if (a=='.')     pckbc_add_code(d, 0x34, p);
         if (a=='>')  {  pckbc_add_code(d, 0x2a, p);  
                         pckbc_add_code(d, 0x34, p); }  
423          if (a=='/')     pckbc_add_code(d, 0x35, p);          if (a=='/')     pckbc_add_code(d, 0x35, p);
         if (a=='?')  {  pckbc_add_code(d, 0x2a, p);  
                         pckbc_add_code(d, 0x35, p); }  
424    
425          if (a==' ')     pckbc_add_code(d, 0x39, p);          if (a==' ')     pckbc_add_code(d, 0x39, p);
426    
# Line 293  void dev_pckbc_tick(struct cpu *cpu, voi Line 447  void dev_pckbc_tick(struct cpu *cpu, voi
447          if (d->in_use && console_charavail(d->console_handle)) {          if (d->in_use && console_charavail(d->console_handle)) {
448                  ch = console_readchar(d->console_handle);                  ch = console_readchar(d->console_handle);
449                  if (ch >= 0)                  if (ch >= 0)
450                          ascii_to_pc_scancodes(ch, d);                          ascii_to_pc_scancodes_type2(ch, d);
451          }          }
452    
453          ints_enabled = d->rx_int_enable;          ints_enabled = d->rx_int_enable;
# Line 306  void dev_pckbc_tick(struct cpu *cpu, voi Line 460  void dev_pckbc_tick(struct cpu *cpu, voi
460          for (port_nr=0; port_nr<2; port_nr++) {          for (port_nr=0; port_nr<2; port_nr++) {
461                  /*  Cause receive interrupt, if there's something in the                  /*  Cause receive interrupt, if there's something in the
462                      receive buffer: (Otherwise deassert the interrupt.)  */                      receive buffer: (Otherwise deassert the interrupt.)  */
463                    int irq = port_nr==0? d->keyboard_irqnr : d->mouse_irqnr;
464    
465                  if (d->head[port_nr] != d->tail[port_nr] && ints_enabled) {                  if (d->head[port_nr] != d->tail[port_nr] && ints_enabled) {
466                          cpu_interrupt(cpu, port_nr==0? d->keyboard_irqnr                          debug("[ pckbc: interrupt port %i ]\n", port_nr);
467                              : d->mouse_irqnr);                          cpu_interrupt(cpu, irq);
468                            d->currently_asserted[port_nr] = 1;
469                  } else {                  } else {
470                          cpu_interrupt_ack(cpu, port_nr==0? d->keyboard_irqnr                          if (d->currently_asserted[port_nr])
471                              : d->mouse_irqnr);                                  cpu_interrupt_ack(cpu, irq);
472                            d->currently_asserted[port_nr] = 0;
473                  }                  }
474          }          }
475  }  }
# Line 330  static void dev_pckbc_command(struct pck Line 488  static void dev_pckbc_command(struct pck
488                  cmd = d->reg[PS2_TXBUF];                  cmd = d->reg[PS2_TXBUF];
489    
490          if (d->state == STATE_WAITING_FOR_TRANSLTABLE) {          if (d->state == STATE_WAITING_FOR_TRANSLTABLE) {
491                  debug("[ pckbc: switching to translation table 0x%02x ]\n",                  debug("[ pckbc: (port %i) switching to translation table "
492                      cmd);                      "0x%02x ]\n", port_nr, cmd);
493                    switch (cmd) {
494                    case 2:
495                    case 3: d->translation_table = cmd;
496                            break;
497                    default:fatal("[ pckbc: (port %i) translation table "
498                                "0x%02x is NOT YET IMPLEMENTED ]\n",
499                                port_nr, cmd);
500                    }
501                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
502                  d->state = STATE_NORMAL;                  d->state = STATE_NORMAL;
503                  return;                  return;
504          }          }
505    
506            if (d->state == STATE_WAITING_FOR_RATE) {
507                    debug("[ pckbc: (port %i) received Typematic Rate data: "
508                        "0x%02x ]\n", port_nr, cmd);
509                    pckbc_add_code(d, KBR_ACK, port_nr);
510                    d->state = STATE_NORMAL;
511                    return;
512            }
513    
514            if (d->state == STATE_WAITING_FOR_ONEKEY_MB) {
515                    debug("[ pckbc: (port %i) received One-key make/break data: "
516                        "0x%02x ]\n", port_nr, cmd);
517                    pckbc_add_code(d, KBR_ACK, port_nr);
518                    d->state = STATE_NORMAL;
519                    return;
520            }
521    
522            if (d->state == STATE_WAITING_FOR_AUX) {
523                    debug("[ pckbc: (port %i) received aux data: "
524                        "0x%02x ]\n", port_nr, cmd);
525                    /*  Echo back.  */
526                    pckbc_add_code(d, cmd, port_nr);
527                    d->state = STATE_NORMAL;
528                    return;
529            }
530    
531            if (d->state == STATE_WAITING_FOR_AUX_OUT) {
532                    debug("[ pckbc: (port %i) received aux out data: "
533                        "0x%02x ]\n", port_nr, cmd);
534                    /*  Echo back.  */
535                    pckbc_add_code(d, cmd, port_nr);
536                    d->state = STATE_NORMAL;
537                    return;
538            }
539    
540          switch (cmd) {          switch (cmd) {
541    
542          case 0x00:          case 0x00:
543                    /*
544                     *  TODO: What does this do? This is possibly due to an
545                     *  error in the handling of some other command code.
546                     */
547                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
548                  break;                  break;
549    
550          case KBC_MODEIND:       /*  Set LEDs  */          case KBC_MODEIND:       /*  Set LEDs  */
551                  /*  Just ACK, no LEDs are actually set.  */                  /*  Just ACK, no LEDs are actually set.  */
552                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
553                  break;                  break;
554    
555          case KBC_SETTABLE:          case KBC_SETTABLE:
556                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
557                  d->state = STATE_WAITING_FOR_TRANSLTABLE;                  d->state = STATE_WAITING_FOR_TRANSLTABLE;
558                  break;                  break;
559    
560          case KBC_ENABLE:          case KBC_ENABLE:
561                  d->keyscanning_enabled = 1;                  d->keyscanning_enabled = 1;
562                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
563                  break;                  break;
564    
565          case KBC_DISABLE:          case KBC_DISABLE:
566                  d->keyscanning_enabled = 0;                  d->keyscanning_enabled = 0;
567                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
568                  break;                  break;
569    
570          case KBC_SETDEFAULT:          case KBC_SETDEFAULT:
571                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
572                  break;                  break;
573    
574            case KBC_GETID:
575                    /*  Get keyboard ID.  NOTE/TODO: Ugly hardcoded answer.  */
576                    pckbc_add_code(d, KBR_ACK, port_nr);
577                    pckbc_add_code(d, 0xab, port_nr);
578                    pckbc_add_code(d, 0x41, port_nr);
579                    break;
580    
581            case KBC_TYPEMATIC:
582                    /*  Set typematic (auto-repeat) delay/speed:  */
583                    pckbc_add_code(d, KBR_ACK, port_nr);
584                    d->state = STATE_WAITING_FOR_RATE;
585                    break;
586    
587            case KBC_ALLKEYS_TMB:
588                    /*  "Make all keys typematic/make/break"  */
589                    pckbc_add_code(d, KBR_ACK, port_nr);
590                    break;
591    
592            case KBC_ONEKEY_MB:
593                    /*  "Make one key typematic/make/break"  */
594                    pckbc_add_code(d, KBR_ACK, port_nr);
595                    d->state = STATE_WAITING_FOR_ONEKEY_MB;
596                    break;
597    
598          case KBC_RESET:          case KBC_RESET:
599                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
600                  pckbc_add_code(d, KBR_RSTDONE, port_nr);                  pckbc_add_code(d, KBR_RSTDONE, port_nr);
601                    /*
602                     *  Disable interrupts during reset, or Linux 2.6
603                     *  prints warnings about spurious interrupts.
604                     */
605                    d->rx_int_enable = 0;
606                  break;                  break;
607    
608          default:          default:
609                  fatal("[ pckbc: UNIMPLEMENTED 8048 command 0x%02x ]\n", cmd);                  fatal("[ pckbc: (port %i) UNIMPLEMENTED 8048 command"
610                        " 0x%02x ]\n", port_nr, cmd);
611                    exit(1);
612          }          }
613  }  }
614    
615    
616  /*  DEVICE_ACCESS(pckbc)
  *  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 *extra)  
617  {  {
618          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
619          int i, port_nr = 0;          int port_nr = 0;
620            size_t i;
621          struct pckbc_data *d = extra;          struct pckbc_data *d = extra;
622    
623          idata = memory_readmax64(cpu, data, len);          if (writeflag == MEM_WRITE)
624                    idata = memory_readmax64(cpu, data, len);
625    
626  #ifdef PCKBC_DEBUG  #ifdef PCKBC_DEBUG
627          if (writeflag == MEM_WRITE)          if (writeflag == MEM_WRITE)
# Line 454  if (x&1) Line 694  if (x&1)
694                                  }                                  }
695                          }                          }
696                          /*  debug("[ pckbc: read from DATA: 0x%02x ]\n",                          /*  debug("[ pckbc: read from DATA: 0x%02x ]\n",
697                              odata);  */                              (int)odata);  */
698                  } else {                  } else {
699                          debug("[ pckbc: write to DATA:");                          debug("[ pckbc: write to DATA:");
700                          for (i=0; i<len; i++)                          for (i=0; i<len; i++)
# Line 503  if (x&1) Line 743  if (x&1)
743                          d->reg[relative_addr] = idata;                          d->reg[relative_addr] = idata;
744    
745                          switch (idata) {                          switch (idata) {
746                            case 0x10:
747                            case 0x11:
748                                    /*  TODO: For now, don't print warnings about
749                                        these. NetBSD sends these.  */
750                                    break;
751                          case K_RDCMDBYTE:                          case K_RDCMDBYTE:
752                                  d->state = STATE_RDCMDBYTE;                                  d->state = STATE_RDCMDBYTE;
753                                  break;                                  break;
# Line 521  if (x&1) Line 766  if (x&1)
766                          case 0xaa:      /*  keyboard self-test  */                          case 0xaa:      /*  keyboard self-test  */
767                                  pckbc_add_code(d, 0x55, port_nr);                                  pckbc_add_code(d, 0x55, port_nr);
768                                  break;                                  break;
769                            case 0xab:      /*  keyboard interface self-test  */
770                                    pckbc_add_code(d, 0x00, port_nr);
771                                    break;
772                          case 0xad:                          case 0xad:
773                                  d->cmdbyte |= KC8_KDISABLE;                                  d->cmdbyte |= KC8_KDISABLE;
774                                  break;                                  break;
# Line 533  if (x&1) Line 781  if (x&1)
781                          case 0xd1:                          case 0xd1:
782                                  d->state = STATE_LDOUTPUT;                                  d->state = STATE_LDOUTPUT;
783                                  break;                                  break;
784                            case 0xd3:      /*  write to auxiliary device
785                                                output buffer  */
786                                    debug("[ pckbc: CONTROL 0xd3, TODO ]\n");
787                                    d->state = STATE_WAITING_FOR_AUX_OUT;
788                                    break;
789                          case 0xd4:      /*  write to auxiliary port  */                          case 0xd4:      /*  write to auxiliary port  */
790                                  debug("[ pckbc: CONTROL 0xd4, TODO ]\n");                                  debug("[ pckbc: CONTROL 0xd4, TODO ]\n");
791                                    d->state = STATE_WAITING_FOR_AUX;
792                                  break;                                  break;
793                          default:                          default:
794                                  fatal("[ pckbc: unknown CONTROL 0x%x ]\n",                                  fatal("[ pckbc: unknown CONTROL 0x%x ]\n",
795                                      idata);                                      (int)idata);
796                                  d->state = STATE_NORMAL;                                  d->state = STATE_NORMAL;
797                          }                          }
798                  }                  }
# Line 548  if (x&1) Line 802  if (x&1)
802           *  8242 (PS2):           *  8242 (PS2):
803           */           */
804    
 /*  
  *  BIG TODO: The following should be rewritten to use dev_pckbc_command()  
  *  etc, like the 8042 code above does.  
  */  
   
805          case PS2 + PS2_TXBUF:          case PS2 + PS2_TXBUF:
806                  if (writeflag==MEM_READ) {                  if (writeflag==MEM_READ) {
807                          odata = random() & 0xff;                          odata = random() & 0xff;
# Line 563  if (x&1) Line 812  if (x&1)
812                              "0x%llx ]\n", port_nr, (long long)idata);                              "0x%llx ]\n", port_nr, (long long)idata);
813    
814                          /*  Handle keyboard commands:  */                          /*  Handle keyboard commands:  */
815                          switch (idata) {                          d->reg[PS2_TXBUF] = idata;
816                          /*  These are incorrect, the second byte of                          dev_pckbc_command(d, port_nr);
                             commands should be treated better:  */  
                         case 0x00:      /*  second byte of 0xed,  
                                             SGI-IP32's prom  */  
                                 pckbc_add_code(d, 0x03, port_nr);/*  ack  (?) */  
                                 break;  
                         case 0x14:      /*  second byte of 0xfc,  
                                             SGI-IP32's prom  */  
                         case 0x28:      /*  second byte of 0xf3,  
                                             SGI-IP32's prom  */  
                         case 0x76:      /*  third byte of 0xfc,  
                                             SGI-IP32's prom  */  
                         case 0x03:      /*  second byte of  
                                             ATKBD_CMD_GSCANSET (?)  */  
                         case 0x04:  
                                 pckbc_add_code(d, 0x03, port_nr);/*  ?  */  
                                 break;  
   
                         /*  Command bytes:  */  
                         case 0xf0:      /*  ATKBD_CMD_GSCANSET (?)  */  
                                 pckbc_add_code(d, 0x03, port_nr);/*  ?  */  
                                 break;  
                         case 0xf2:      /*  Get keyboard ID  */  
                                 /*  The keyboard should generate 2  
                                     status bytes.  */  
                                 pckbc_add_code(d, 0xab, port_nr);  
                                 pckbc_add_code(d, 0x83, port_nr);  
                                 break;  
                         case 0xed:      /*  "ATKBD_CMD_SETLEDS",  
                                             takes 1 byte arg  */  
                         case 0xf3:      /*  "PSMOUSE_CMD_SETRATE",  
                                             takes 1 byte arg  */  
                         case 0xf4:      /*  "ATKBD_CMD_ENABLE" (or  
                                             PSMOUSE_CMD_ENABLE), no args  */  
                         case 0xf5:      /*  "ATKBD_CMD_RESET_DIS" (keyboard,  
                                             according to Linux sources)  */  
                         case 0xf6:      /*  "PSMOUSE_CMD_RESET_DIS" (mouse,  
                                             according to Linux sources)  */  
                                 /*  TODO: what does this do?  */  
                                 pckbc_add_code(d, 0xfa, port_nr);/*  ack  (?) */  
                                 break;  
                         case 0xfa:      /*  "ATKBD_CMD_SETALL_MBR" (linux)  */  
                                 pckbc_add_code(d, 0xfa, port_nr);/*  ack  (?) */  
                                 break;  
                         case 0xfc:      /*  ?  */  
                                 pckbc_add_code(d, 0xfa, port_nr);/*  ack  (?) */  
                                 break;  
                         case 0xff:      /*  Keyboard reset  */  
                                 /*  The keyboard should generate 2  
                                     status bytes.  */  
                                 pckbc_add_code(d, 0xfa, port_nr);/*  ack  (?) */  
                                 pckbc_add_code(d, 0xaa, port_nr);  
                                         /*  battery ok (?)  */  
                                 break;  
                         default:  
                                 debug("[ pckbc: UNIMPLEMENTED keyboard command"  
                                     " 0x%02x (port %i) ]\n", (int)idata,  
                                     port_nr);  
                         }  
817                  }                  }
818                  break;                  break;
819    
# Line 687  if (x&1) Line 878  if (x&1)
878                  }                  }
879          }          }
880    
881            /*  SGI? TODO: fix  */
882            if (len == 8)
883                    odata |= (odata << 8) | (odata << 16) | (odata << 24) |
884                        (odata << 32) | (odata << 40) | (odata << 48) |
885                        (odata << 56);
886    
887          if (writeflag == MEM_READ)          if (writeflag == MEM_READ)
888                  memory_writemax64(cpu, data, len, odata);                  memory_writemax64(cpu, data, len, odata);
889    
# Line 715  int dev_pckbc_init(struct machine *machi Line 912  int dev_pckbc_init(struct machine *machi
912          }          }
913          memset(d, 0, sizeof(struct pckbc_data));          memset(d, 0, sizeof(struct pckbc_data));
914    
915            if (type == PCKBC_8242)
916                    len = 0x18;
917    
918          if (type == PCKBC_JAZZ) {          if (type == PCKBC_JAZZ) {
919                  type = PCKBC_8042;                  type = PCKBC_8042;
920                  len = DEV_PCKBC_LENGTH + 0x60;                  len = DEV_PCKBC_LENGTH + 0x60;
921          }          }
922    
923          d->type           = type;          d->type              = type;
924          d->keyboard_irqnr = keyboard_irqnr;          d->keyboard_irqnr    = keyboard_irqnr;
925          d->mouse_irqnr    = mouse_irqnr;          d->mouse_irqnr       = mouse_irqnr;
926          d->in_use         = in_use;          d->in_use            = in_use;
927          d->pc_style_flag  = pc_style_flag;          d->pc_style_flag     = pc_style_flag;
928          d->console_handle = console_start_slave_inputonly(machine, "pckbc");          d->translation_table = 2;
929          d->rx_int_enable  = 1;          d->rx_int_enable     = 1;
930          d->output_byte    = 0x02;       /*  A20 enable on PCs  */          d->output_byte       = 0x02;    /*  A20 enable on PCs  */
931    
932            d->console_handle = console_start_slave_inputonly(
933                machine, "pckbc", d->in_use);
934    
935          memory_device_register(mem, "pckbc", baseaddr,          memory_device_register(mem, "pckbc", baseaddr,
936              len, dev_pckbc_access, d, MEM_DEFAULT, NULL);              len, dev_pckbc_access, d, DM_DEFAULT, NULL);
937          machine_add_tickfunction(machine, dev_pckbc_tick, d, PCKBC_TICKSHIFT);          machine_add_tickfunction(machine, dev_pckbc_tick, d,
938                PCKBC_TICKSHIFT, 0.0);
939    
940          return d->console_handle;          return d->console_handle;
941  }  }

Legend:
Removed from v.6  
changed lines
  Added in v.30

  ViewVC Help
Powered by ViewVC 1.1.26