/[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 4 by dpavlin, Mon Oct 8 16:18:00 2007 UTC revision 22 by dpavlin, Mon Oct 8 16:19:37 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.37 2005/02/22 06:26:10 debug Exp $   *  $Id: dev_pckbc.c,v 1.64 2006/01/01 13:17:16 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.   *  controller), including the 8048 keyboard chip.
32   *   *
33   *   *
34   *  TODO: Finish the rewrite for 8242.   *  TODO: Finish the rewrite for 8242.
# Line 49  Line 49 
49    
50    
51  /*  #define PCKBC_DEBUG  */  /*  #define PCKBC_DEBUG  */
52    /*  #define debug fatal  */
53    
54    
55  #define MAX_8042_QUEUELEN       256  #define MAX_8042_QUEUELEN       256
# Line 64  Line 65 
65    
66  #define PS2     100  #define PS2     100
67    
68  #define PCKBC_TICKSHIFT         14  #define PCKBC_TICKSHIFT         15
69    
70  struct pckbc_data {  struct pckbc_data {
71          int             console_handle;          int             console_handle;
72          int             in_use;          int             in_use;
         int             any_command_used;  
73    
74          int             reg[DEV_PCKBC_LENGTH];          int             reg[DEV_PCKBC_LENGTH];
75          int             keyboard_irqnr;          int             keyboard_irqnr;
76          int             mouse_irqnr;          int             mouse_irqnr;
77            int             currently_asserted[2];
78          int             type;          int             type;
79            int             pc_style_flag;
80    
81          /*  TODO: one of these for each port?  */          /*  TODO: one of these for each port?  */
82          int             clocksignal;          int             clocksignal;
# Line 82  struct pckbc_data { Line 84  struct pckbc_data {
84          int             tx_int_enable;          int             tx_int_enable;
85    
86          int             keyscanning_enabled;          int             keyscanning_enabled;
87            int             translation_table;
88          int             state;          int             state;
89          int             cmdbyte;          int             cmdbyte;
90            int             output_byte;
91          int             last_scancode;          int             last_scancode;
92    
93          unsigned        key_queue[2][MAX_8042_QUEUELEN];          unsigned        key_queue[2][MAX_8042_QUEUELEN];
# Line 94  struct pckbc_data { Line 98  struct pckbc_data {
98  #define STATE_LDCMDBYTE                 1  #define STATE_LDCMDBYTE                 1
99  #define STATE_RDCMDBYTE                 2  #define STATE_RDCMDBYTE                 2
100  #define STATE_WAITING_FOR_TRANSLTABLE   3  #define STATE_WAITING_FOR_TRANSLTABLE   3
101    #define STATE_WAITING_FOR_F3            4
102    #define STATE_WAITING_FOR_FC            5
103    #define STATE_WAITING_FOR_AUX           6
104    #define STATE_WAITING_FOR_AUX_OUT       7
105    #define STATE_LDOUTPUT                  8
106    #define STATE_RDOUTPUT                  9
107    
108    
109  /*  /*
# Line 121  int pckbc_get_code(struct pckbc_data *d, Line 131  int pckbc_get_code(struct pckbc_data *d,
131  {  {
132          if (d->head[port] == d->tail[port])          if (d->head[port] == d->tail[port])
133                  fatal("[ pckbc: queue empty, port %i! ]\n", port);                  fatal("[ pckbc: queue empty, port %i! ]\n", port);
134            else
135          d->tail[port] = (d->tail[port]+1) % MAX_8042_QUEUELEN;                  d->tail[port] = (d->tail[port]+1) % MAX_8042_QUEUELEN;
136          return d->key_queue[port][d->tail[port]];          return d->key_queue[port][d->tail[port]];
137  }  }
138    
139    
140  /*  /*
141   *  ascii_to_scancodes():   *  ascii_to_scancodes_type3():
142     *
143     *  Conversion from ASCII codes to default (US) keyboard scancodes.
144     *  (See http://www.computer-engineering.org/ps2keyboard/scancodes3.html)
145     */
146    static void ascii_to_pc_scancodes_type3(int a, struct pckbc_data *d)
147    {
148            int old_head;
149            int p = 0;      /*  port  */
150            int shift = 0, ctrl = 0;
151    
152            if (a >= 'A' && a <= 'Z') { a += 32; shift = 1; }
153            if ((a >= 1 && a <= 26) && (a!='\n' && a!='\t' && a!='\b' && a!='\r'))
154                    { a += 96; ctrl = 1; }
155            if (a=='!')  {  a = '1'; shift = 1; }
156            if (a=='@')  {  a = '2'; shift = 1; }
157            if (a=='#')  {  a = '3'; shift = 1; }
158            if (a=='$')  {  a = '4'; shift = 1; }
159            if (a=='%')  {  a = '5'; shift = 1; }
160            if (a=='^')  {  a = '6'; shift = 1; }
161            if (a=='&')  {  a = '7'; shift = 1; }
162            if (a=='*')  {  a = '8'; shift = 1; }
163            if (a=='(')  {  a = '9'; shift = 1; }
164            if (a==')')  {  a = '0'; shift = 1; }
165            if (a=='_')  {  a = '-'; shift = 1; }
166            if (a=='+')  {  a = '='; shift = 1; }
167            if (a=='{')  {  a = '['; 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    
176            if (shift)
177                    pckbc_add_code(d, 0x12, p);
178            if (ctrl)
179                    pckbc_add_code(d, 0x11, p);
180    
181            /*
182             *  Note: The ugly hack used to add release codes for all of these
183             *  keys is as follows:  we remember how much of the kbd buf that
184             *  is in use here, before we add any scancode. After we've added
185             *  one or more scancodes (ie an optional shift + another key)
186             *  then we add 0xf0 + the last scancode _if_ the kbd buf was altered.
187             */
188    
189            old_head = d->head[p];
190    
191            if (a==27)      pckbc_add_code(d, 0x08, p);
192    
193            if (a=='1')     pckbc_add_code(d, 0x16, p);
194            if (a=='2')     pckbc_add_code(d, 0x1e, p);
195            if (a=='3')     pckbc_add_code(d, 0x26, p);
196            if (a=='4')     pckbc_add_code(d, 0x25, p);
197            if (a=='5')     pckbc_add_code(d, 0x2e, p);
198            if (a=='6')     pckbc_add_code(d, 0x36, p);
199            if (a=='7')     pckbc_add_code(d, 0x3d, p);
200            if (a=='8')     pckbc_add_code(d, 0x3e, p);
201            if (a=='9')     pckbc_add_code(d, 0x46, p);
202            if (a=='0')     pckbc_add_code(d, 0x45, p);
203            if (a=='-')     pckbc_add_code(d, 0x4e, p);
204            if (a=='=')     pckbc_add_code(d, 0x55, p);
205    
206            if (a=='\b')    pckbc_add_code(d, 0x29, p);
207    
208            if (a=='\t')    pckbc_add_code(d, 0x0d, p);
209            if (a=='q')     pckbc_add_code(d, 0x15, p);
210            if (a=='w')     pckbc_add_code(d, 0x1d, p);
211            if (a=='e')     pckbc_add_code(d, 0x24, p);
212            if (a=='r')     pckbc_add_code(d, 0x2d, p);
213            if (a=='t')     pckbc_add_code(d, 0x2c, p);
214            if (a=='y')     pckbc_add_code(d, 0x35, p);
215            if (a=='u')     pckbc_add_code(d, 0x3c, p);
216            if (a=='i')     pckbc_add_code(d, 0x43, p);
217            if (a=='o')     pckbc_add_code(d, 0x44, p);
218            if (a=='p')     pckbc_add_code(d, 0x4d, p);
219    
220            if (a=='[')     pckbc_add_code(d, 0x54, p);
221            if (a==']')     pckbc_add_code(d, 0x5b, p);
222    
223            if (a=='\n' || a=='\r') pckbc_add_code(d, 0x5a, p);
224    
225            if (a=='a')     pckbc_add_code(d, 0x1c, p);
226            if (a=='s')     pckbc_add_code(d, 0x1b, p);
227            if (a=='d')     pckbc_add_code(d, 0x23, p);
228            if (a=='f')     pckbc_add_code(d, 0x2b, p);
229            if (a=='g')     pckbc_add_code(d, 0x34, p);
230            if (a=='h')     pckbc_add_code(d, 0x33, p);
231            if (a=='j')     pckbc_add_code(d, 0x3b, p);
232            if (a=='k')     pckbc_add_code(d, 0x42, p);
233            if (a=='l')     pckbc_add_code(d, 0x4b, p);
234    
235            if (a==';')     pckbc_add_code(d, 0x4c, p);
236            if (a=='\'')    pckbc_add_code(d, 0x52, p);
237    /*      if (a=='~')     pckbc_add_code(d, 0x29, p);  ?  */
238            if (a=='\\')    pckbc_add_code(d, 0x5c, p);
239    
240            if (a=='z')     pckbc_add_code(d, 0x1a, p);
241            if (a=='x')     pckbc_add_code(d, 0x22, p);
242            if (a=='c')     pckbc_add_code(d, 0x21, p);
243            if (a=='v')     pckbc_add_code(d, 0x2a, p);
244            if (a=='b')     pckbc_add_code(d, 0x32, p);
245            if (a=='n')     pckbc_add_code(d, 0x31, p);
246            if (a=='m')     pckbc_add_code(d, 0x3a, p);
247    
248            if (a==',')     pckbc_add_code(d, 0x41, p);
249            if (a=='.')     pckbc_add_code(d, 0x49, p);
250            if (a=='/')     pckbc_add_code(d, 0x4a, p);
251    
252            if (a==' ')     pckbc_add_code(d, 0x29, p);
253    
254            /*  Add release code, if a key was pressed:  */
255            if (d->head[p] != old_head) {
256                    int code = d->key_queue[p][d->head[p]];
257                    pckbc_add_code(d, 0xf0, p);
258                    pckbc_add_code(d, code, p);
259            }
260    
261            /*  Release shift and ctrl:  */
262            if (shift) {
263                    pckbc_add_code(d, 0xf0, p);
264                    pckbc_add_code(d, 0x12, p);
265            }
266            if (ctrl) {
267                    pckbc_add_code(d, 0xf0, p);
268                    pckbc_add_code(d, 0x11, p);
269            }
270    }
271    
272    
273    /*
274     *  ascii_to_scancodes_type2():
275   *   *
276   *  Conversion from ASCII codes to default (US) keyboard scancodes.   *  Conversion from ASCII codes to default (US) keyboard scancodes.
277   *  (See http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html)   *  (See http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html)
278     *
279     *  NOTE/TODO: This seems to be type 2, not type 1.
280   */   */
281  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)
282  {  {
283            int old_head;
284          int p = 0;      /*  port  */          int p = 0;      /*  port  */
285          int shift = 0, ctrl = 0;          int shift = 0, ctrl = 0;
286    
287            if (d->translation_table == 3) {
288                    ascii_to_pc_scancodes_type3(a, d);
289                    return;
290            }
291    
292            if (d->translation_table != 2) {
293                    fatal("[ ascii_to_pc_scancodes: unimplemented type! ]\n");
294                    return;
295            }
296    
297          if (a >= 'A' && a <= 'Z') { a += 32; shift = 1; }          if (a >= 'A' && a <= 'Z') { a += 32; shift = 1; }
298          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'))
299                  { a += 96; ctrl = 1; }                  { a += 96; ctrl = 1; }
300    
301            if (a=='!')  {  a = '1'; shift = 1; }
302            if (a=='@')  {  a = '2'; shift = 1; }
303            if (a=='#')  {  a = '3'; shift = 1; }
304            if (a=='$')  {  a = '4'; shift = 1; }
305            if (a=='%')  {  a = '5'; shift = 1; }
306            if (a=='^')  {  a = '6'; shift = 1; }
307            if (a=='&')  {  a = '7'; shift = 1; }
308            if (a=='*')  {  a = '8'; shift = 1; }
309            if (a=='(')  {  a = '9'; shift = 1; }
310            if (a==')')  {  a = '0'; shift = 1; }
311            if (a=='_')  {  a = '-'; shift = 1; }
312            if (a=='+')  {  a = '='; shift = 1; }
313            if (a=='{')  {  a = '['; 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    
323          if (shift)          if (shift)
324                  pckbc_add_code(d, 0x2a, p);                  pckbc_add_code(d, 0x2a, p);
325          else          else
# Line 151  static void ascii_to_pc_scancodes(int a, Line 329  static void ascii_to_pc_scancodes(int a,
329                  pckbc_add_code(d, 0x1d, p);                  pckbc_add_code(d, 0x1d, p);
330    
331          /*          /*
332           *  TODO: Release for all of these?           *  Note: The ugly hack used to add release codes for all of these
333             *  keys is as follows:  we remember how much of the kbd buf that
334             *  is in use here, before we add any scancode. After we've added
335             *  one or more scancodes (ie an optional shift + another key)
336             *  then we duplicate the last scancode | 0x80 _if_ the kbd buf
337             *  was altered.
338           */           */
339    
340            old_head = d->head[p];
341    
342          if (a==27)      pckbc_add_code(d, 0x01, p);          if (a==27)      pckbc_add_code(d, 0x01, p);
343    
344          if (a=='1')     pckbc_add_code(d, 0x02, p);          if (a=='1')     pckbc_add_code(d, 0x02, p);
# Line 187  static void ascii_to_pc_scancodes(int a, Line 372  static void ascii_to_pc_scancodes(int a,
372                          pckbc_add_code(d, 0x09, p); }                          pckbc_add_code(d, 0x09, p); }
373          if (a=='(')  {  pckbc_add_code(d, 0x2a, p);          if (a=='(')  {  pckbc_add_code(d, 0x2a, p);
374                          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); }  
375    
376          if (a=='\b')    pckbc_add_code(d, 0x0e, p);          if (a=='\b')    pckbc_add_code(d, 0x0e, p);
377    
# Line 209  static void ascii_to_pc_scancodes(int a, Line 388  static void ascii_to_pc_scancodes(int a,
388          if (a=='p')     pckbc_add_code(d, 0x19, p);          if (a=='p')     pckbc_add_code(d, 0x19, p);
389    
390          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); }  
391          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); }  
392    
393          if (a=='\n' || a=='\r') pckbc_add_code(d, 0x1c, p);          if (a=='\n' || a=='\r') pckbc_add_code(d, 0x1c, p);
394    
# Line 228  static void ascii_to_pc_scancodes(int a, Line 403  static void ascii_to_pc_scancodes(int a,
403          if (a=='l')     pckbc_add_code(d, 0x26, p);          if (a=='l')     pckbc_add_code(d, 0x26, p);
404    
405          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); }  
406          if (a=='\'')    pckbc_add_code(d, 0x28, p);          if (a=='\'')    pckbc_add_code(d, 0x28, p);
407          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);  
   
408          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); }  
409    
410          if (a=='z')     pckbc_add_code(d, 0x2c, p);          if (a=='z')     pckbc_add_code(d, 0x2c, p);
411          if (a=='x')     pckbc_add_code(d, 0x2d, p);          if (a=='x')     pckbc_add_code(d, 0x2d, p);
# Line 248  static void ascii_to_pc_scancodes(int a, Line 416  static void ascii_to_pc_scancodes(int a,
416          if (a=='m')     pckbc_add_code(d, 0x32, p);          if (a=='m')     pckbc_add_code(d, 0x32, p);
417    
418          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); }  
419          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); }  
420          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); }  
421    
422          if (a==' ')     pckbc_add_code(d, 0x39, p);          if (a==' ')     pckbc_add_code(d, 0x39, p);
423    
424            /*  Add release code, if a key was pressed:  */
425            if (d->head[p] != old_head) {
426                    int code = d->key_queue[p][d->head[p]] | 0x80;
427                    pckbc_add_code(d, code, p);
428            }
429    
430          /*  Release ctrl:  */          /*  Release ctrl:  */
431          if (ctrl)          if (ctrl)
432                  pckbc_add_code(d, 0x1d + 0x80, p);                  pckbc_add_code(d, 0x1d + 0x80, p);
# Line 271  static void ascii_to_pc_scancodes(int a, Line 439  static void ascii_to_pc_scancodes(int a,
439  void dev_pckbc_tick(struct cpu *cpu, void *extra)  void dev_pckbc_tick(struct cpu *cpu, void *extra)
440  {  {
441          struct pckbc_data *d = extra;          struct pckbc_data *d = extra;
442          int port_nr;          int port_nr, ch, ints_enabled;
         int ch;  
443    
444          if (d->in_use && d->any_command_used &&          if (d->in_use && console_charavail(d->console_handle)) {
             console_charavail(d->console_handle)) {  
445                  ch = console_readchar(d->console_handle);                  ch = console_readchar(d->console_handle);
446                  if (ch >= 0)                  if (ch >= 0)
447                          ascii_to_pc_scancodes(ch, d);                          ascii_to_pc_scancodes_type2(ch, d);
448          }          }
449    
450            ints_enabled = d->rx_int_enable;
451    
452          /*  TODO: mouse movements?  */          /*  TODO: mouse movements?  */
453    
454            if (d->cmdbyte & KC8_KDISABLE)
455                    ints_enabled = 0;
456    
457          for (port_nr=0; port_nr<2; port_nr++) {          for (port_nr=0; port_nr<2; port_nr++) {
458                  /*  Cause receive interrupt,                  /*  Cause receive interrupt, if there's something in the
459                      if there's something in the receive buffer:  */                      receive buffer: (Otherwise deassert the interrupt.)  */
460                  if (d->head[port_nr] != d->tail[port_nr] && d->rx_int_enable) {                  if (d->head[port_nr] != d->tail[port_nr] && ints_enabled) {
461                            debug("[ pckbc: interrupt port %i ]\n", port_nr);
462                          cpu_interrupt(cpu, port_nr==0? d->keyboard_irqnr                          cpu_interrupt(cpu, port_nr==0? d->keyboard_irqnr
463                              : d->mouse_irqnr);                              : d->mouse_irqnr);
464                            d->currently_asserted[port_nr] = 1;
465                  } else {                  } else {
466                          cpu_interrupt_ack(cpu, port_nr==0? d->keyboard_irqnr                          if (d->currently_asserted[port_nr])
467                              : d->mouse_irqnr);                                  cpu_interrupt_ack(cpu, port_nr==0?
468                                        d->keyboard_irqnr : d->mouse_irqnr);
469                            d->currently_asserted[port_nr] = 0;
470                  }                  }
471          }          }
472  }  }
# Line 299  void dev_pckbc_tick(struct cpu *cpu, voi Line 474  void dev_pckbc_tick(struct cpu *cpu, voi
474    
475  /*  /*
476   *  dev_pckbc_command():   *  dev_pckbc_command():
477     *
478     *  Handle commands to the 8048 in the emulated keyboard.
479   */   */
480  static void dev_pckbc_command(struct pckbc_data *d, int port_nr)  static void dev_pckbc_command(struct pckbc_data *d, int port_nr)
481  {  {
482          int cmd = d->reg[PC_CMD];          int cmd = d->reg[PC_CMD];
483    
         d->any_command_used = 1;  
   
484          if (d->type == PCKBC_8242)          if (d->type == PCKBC_8242)
485                  cmd = d->reg[PS2_TXBUF];                  cmd = d->reg[PS2_TXBUF];
486    
487          if (d->state == STATE_WAITING_FOR_TRANSLTABLE) {          if (d->state == STATE_WAITING_FOR_TRANSLTABLE) {
488                  debug("[ pckbc: switching to translation table 0x%02x ]\n",                  debug("[ pckbc: (port %i) switching to translation table "
489                      cmd);                      "0x%02x ]\n", port_nr, cmd);
490                    switch (cmd) {
491                    case 2:
492                    case 3: d->translation_table = cmd;
493                            break;
494                    default:fatal("[ pckbc: (port %i) translation table "
495                                "0x%02x is NOT YET IMPLEMENTED ]\n",
496                                port_nr, cmd);
497                    }
498                    pckbc_add_code(d, KBR_ACK, port_nr);
499                    d->state = STATE_NORMAL;
500                    return;
501            }
502    
503            if (d->state == STATE_WAITING_FOR_F3) {
504                    debug("[ pckbc: (port %i) received '0xf3' data: "
505                        "0x%02x ]\n", port_nr, cmd);
506                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
507                  d->state = STATE_NORMAL;                  d->state = STATE_NORMAL;
508                  return;                  return;
509          }          }
510    
511            if (d->state == STATE_WAITING_FOR_FC) {
512                    debug("[ pckbc: (port %i) received '0xfc' data: "
513                        "0x%02x ]\n", port_nr, cmd);
514                    pckbc_add_code(d, KBR_ACK, port_nr);
515                    d->state = STATE_NORMAL;
516                    return;
517            }
518    
519            if (d->state == STATE_WAITING_FOR_AUX) {
520                    debug("[ pckbc: (port %i) received aux data: "
521                        "0x%02x ]\n", port_nr, cmd);
522                    /*  Echo back.  */
523                    pckbc_add_code(d, cmd, port_nr);
524                    d->state = STATE_NORMAL;
525                    return;
526            }
527    
528            if (d->state == STATE_WAITING_FOR_AUX_OUT) {
529                    debug("[ pckbc: (port %i) received aux out data: "
530                        "0x%02x ]\n", port_nr, cmd);
531                    /*  Echo back.  */
532                    pckbc_add_code(d, cmd, port_nr);
533                    d->state = STATE_NORMAL;
534                    return;
535            }
536    
537          switch (cmd) {          switch (cmd) {
538          case 0x00:          case 0x00:
539                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
# Line 340  static void dev_pckbc_command(struct pck Line 557  static void dev_pckbc_command(struct pck
557          case KBC_SETDEFAULT:          case KBC_SETDEFAULT:
558                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
559                  break;                  break;
560            case 0xf3:
561                    pckbc_add_code(d, KBR_ACK, port_nr);
562                    d->state = STATE_WAITING_FOR_F3;
563                    break;
564            case 0xfa:      /*  Just ack?  */
565                    pckbc_add_code(d, KBR_ACK, port_nr);
566                    break;
567            case 0xfc:
568                    pckbc_add_code(d, KBR_ACK, port_nr);
569                    d->state = STATE_WAITING_FOR_FC;
570                    break;
571          case KBC_RESET:          case KBC_RESET:
572                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
573                  pckbc_add_code(d, KBR_RSTDONE, port_nr);                  pckbc_add_code(d, KBR_RSTDONE, port_nr);
574                  break;                  break;
575          default:          default:
576                  fatal("[ pckbc: UNIMPLEMENTED command 0x%02x ]\n", cmd);                  fatal("[ pckbc: (port %i) UNIMPLEMENTED 8048 command"
577                        " 0x%02x ]\n", port_nr, cmd);
578          }          }
579  }  }
580    
# Line 353  static void dev_pckbc_command(struct pck Line 582  static void dev_pckbc_command(struct pck
582  /*  /*
583   *  dev_pckbc_access():   *  dev_pckbc_access():
584   */   */
585  int dev_pckbc_access(struct cpu *cpu, struct memory *mem,  DEVICE_ACCESS(pckbc)
         uint64_t relative_addr, unsigned char *data, size_t len,  
         int writeflag, void *extra)  
586  {  {
587          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
588          int i, port_nr = 0;          int port_nr = 0;
589            size_t i;
590          struct pckbc_data *d = extra;          struct pckbc_data *d = extra;
591    
592          idata = memory_readmax64(cpu, data, len);          if (writeflag == MEM_WRITE)
593                    idata = memory_readmax64(cpu, data, len);
594    
595  #ifdef PCKBC_DEBUG  #ifdef PCKBC_DEBUG
596          if (writeflag == MEM_WRITE)          if (writeflag == MEM_WRITE)
# Line 373  int dev_pckbc_access(struct cpu *cpu, st Line 602  int dev_pckbc_access(struct cpu *cpu, st
602  #endif  #endif
603    
604          /*  For JAZZ-based machines:  */          /*  For JAZZ-based machines:  */
605          if (relative_addr >= 0x60)          if (relative_addr >= 0x60) {
606                  relative_addr -= 0x60;                  relative_addr -= 0x60;
607                    if (relative_addr != 0)
608          /*  8242 PS2-style:  */                          relative_addr = 1;
609          if (d->type == PCKBC_8242) {          } else if (d->type == PCKBC_8242) {
610                    /*  8242 PS2-style:  */
611                  /*  when using 8-byte alignment...  */                  /*  when using 8-byte alignment...  */
612                  relative_addr /= sizeof(uint64_t);                  relative_addr /= sizeof(uint64_t);
613                  /*  port_nr = 0 for keyboard, 1 for mouse  */                  /*  port_nr = 0 for keyboard, 1 for mouse  */
614                  port_nr = (relative_addr >> 2);                  port_nr = (relative_addr >> 2);
615                  relative_addr &= 3;                  relative_addr &= 3;
616                  relative_addr += PS2;                  relative_addr += PS2;
617            } else if (d->pc_style_flag) {
618                    /*  PC-style:  */
619                    if (relative_addr != 0 && relative_addr != 4) {
620                            /*  TODO (port 0x61)  */
621                            odata = 0x21;
622    {
623    static int x = 0;
624    x++;
625    if (x&1)
626                            odata ^= 0x10;
627    }
628                            if (writeflag == MEM_READ)
629                                    memory_writemax64(cpu, data, len, odata);
630                            return 0;
631                    }
632                    if (relative_addr != 0)
633                            relative_addr = 1;
634          } else {          } else {
635                  /*  The relative_addr is either 0 or 1,                  /*  Others... Non-Jazz ARC-based machines etc.  */
636                      but some machines use longer registers than one byte                  if (relative_addr != 0)
                     each, so this will make things simpler for us:  */  
                 if (relative_addr)  
637                          relative_addr = 1;                          relative_addr = 1;
638          }          }
639    
# Line 400  int dev_pckbc_access(struct cpu *cpu, st Line 645  int dev_pckbc_access(struct cpu *cpu, st
645    
646          case 0:         /*  data  */          case 0:         /*  data  */
647                  if (writeflag==MEM_READ) {                  if (writeflag==MEM_READ) {
648                          if (d->state == STATE_RDCMDBYTE) {                          switch (d->state) {
649                            case STATE_RDCMDBYTE:
650                                  odata = d->cmdbyte;                                  odata = d->cmdbyte;
651                                  d->state = STATE_NORMAL;                                  d->state = STATE_NORMAL;
652                          } else {                                  break;
653                                  if (d->head[0] != d->tail[0]) {                          case STATE_RDOUTPUT:
654                                    odata = d->output_byte;
655                                    d->state = STATE_NORMAL;
656                                    break;
657                            default:if (d->head[0] != d->tail[0]) {
658                                          odata = pckbc_get_code(d, 0);                                          odata = pckbc_get_code(d, 0);
659                                          d->last_scancode = odata;                                          d->last_scancode = odata;
660                                  } else {                                  } else {
# Line 412  int dev_pckbc_access(struct cpu *cpu, st Line 662  int dev_pckbc_access(struct cpu *cpu, st
662                                          d->last_scancode |= 0x80;                                          d->last_scancode |= 0x80;
663                                  }                                  }
664                          }                          }
665                          debug("[ pckbc: read from DATA: 0x%02x ]\n", odata);                          /*  debug("[ pckbc: read from DATA: 0x%02x ]\n",
666                                (int)odata);  */
667                  } else {                  } else {
668                          debug("[ pckbc: write to DATA:");                          debug("[ pckbc: write to DATA:");
669                          for (i=0; i<len; i++)                          for (i=0; i<len; i++)
670                                  debug(" %02x", data[i]);                                  debug(" %02x", data[i]);
671                          debug(" ]\n");                          debug(" ]\n");
672    
673                          if (d->state == STATE_LDCMDBYTE) {                          switch (d->state) {
674                            case STATE_LDCMDBYTE:
675                                  d->cmdbyte = idata;                                  d->cmdbyte = idata;
676                                  d->rx_int_enable = d->cmdbyte &                                  d->rx_int_enable = d->cmdbyte &
677                                      (KC8_KENABLE | KC8_MENABLE) ? 1 : 0;                                      (KC8_KENABLE | KC8_MENABLE) ? 1 : 0;
678                                  d->state = STATE_NORMAL;                                  d->state = STATE_NORMAL;
679                          } else {                                  break;
680                                  d->reg[relative_addr] = idata;                          case STATE_LDOUTPUT:
681                                    d->output_byte = idata;
682                                    d->state = STATE_NORMAL;
683                                    break;
684                            default:d->reg[relative_addr] = idata;
685                                  dev_pckbc_command(d, port_nr);                                  dev_pckbc_command(d, port_nr);
686                          }                          }
687                  }                  }
# Line 438  int dev_pckbc_access(struct cpu *cpu, st Line 694  int dev_pckbc_access(struct cpu *cpu, st
694    
695                          /*  "Data in buffer" bit  */                          /*  "Data in buffer" bit  */
696                          if (d->head[0] != d->tail[0] ||                          if (d->head[0] != d->tail[0] ||
697                              d->state == STATE_RDCMDBYTE)                              d->state == STATE_RDCMDBYTE ||
698                                d->state == STATE_RDOUTPUT)
699                                  odata |= KBS_DIB;                                  odata |= KBS_DIB;
700                          /*  odata |= KBS_OCMD;  */  
701                            if (d->state == STATE_RDCMDBYTE)
702                                    odata |= KBS_OCMD;
703    
704                            odata |= KBS_NOSEC;
705                          /*  debug("[ pckbc: read from CTL status port: "                          /*  debug("[ pckbc: read from CTL status port: "
706                              "0x%02x ]\n", (int)odata);  */                              "0x%02x ]\n", (int)odata);  */
707                  } else {                  } else {
# Line 451  int dev_pckbc_access(struct cpu *cpu, st Line 712  int dev_pckbc_access(struct cpu *cpu, st
712                          d->reg[relative_addr] = idata;                          d->reg[relative_addr] = idata;
713    
714                          switch (idata) {                          switch (idata) {
715                            case 0x10:
716                            case 0x11:
717                                    /*  TODO: For now, don't print warnings about
718                                        these. NetBSD sends these.  */
719                                    break;
720                          case K_RDCMDBYTE:                          case K_RDCMDBYTE:
721                                  d->state = STATE_RDCMDBYTE;                                  d->state = STATE_RDCMDBYTE;
722                                  break;                                  break;
723                          case K_LDCMDBYTE:                          case K_LDCMDBYTE:
724                                  d->state = STATE_LDCMDBYTE;                                  d->state = STATE_LDCMDBYTE;
725                                  break;                                  break;
726                            case 0xa7:
727                                    d->cmdbyte |= KC8_MDISABLE;
728                                    break;
729                            case 0xa8:
730                                    d->cmdbyte &= ~KC8_MDISABLE;
731                                    break;
732                          case 0xa9:      /*  test auxiliary port  */                          case 0xa9:      /*  test auxiliary port  */
733                                  debug("[ pckbc: CONTROL 0xa9, TODO ]\n");                                  debug("[ pckbc: CONTROL 0xa9, TODO ]\n");
734                                  break;                                  break;
735                          case 0xaa:      /*  keyboard self-test  */                          case 0xaa:      /*  keyboard self-test  */
736                                  pckbc_add_code(d, 0x55, port_nr);                                  pckbc_add_code(d, 0x55, port_nr);
737                                  break;                                  break;
738                            case 0xab:      /*  keyboard interface self-test  */
739                                    pckbc_add_code(d, 0x00, port_nr);
740                                    break;
741                            case 0xad:
742                                    d->cmdbyte |= KC8_KDISABLE;
743                                    break;
744                            case 0xae:
745                                    d->cmdbyte &= ~KC8_KDISABLE;
746                                    break;
747                            case 0xd0:
748                                    d->state = STATE_RDOUTPUT;
749                                    break;
750                            case 0xd1:
751                                    d->state = STATE_LDOUTPUT;
752                                    break;
753                            case 0xd3:      /*  write to auxiliary device
754                                                output buffer  */
755                                    debug("[ pckbc: CONTROL 0xd3, TODO ]\n");
756                                    d->state = STATE_WAITING_FOR_AUX_OUT;
757                                    break;
758                          case 0xd4:      /*  write to auxiliary port  */                          case 0xd4:      /*  write to auxiliary port  */
759                                  debug("[ pckbc: CONTROL 0xd4, TODO ]\n");                                  debug("[ pckbc: CONTROL 0xd4, TODO ]\n");
760                                    d->state = STATE_WAITING_FOR_AUX;
761                                  break;                                  break;
762                          default:                          default:
763                                  fatal("[ pckbc: unknown CONTROL 0x%x ]\n",                                  fatal("[ pckbc: unknown CONTROL 0x%x ]\n",
764                                      idata);                                      (int)idata);
765                                  d->state = STATE_NORMAL;                                  d->state = STATE_NORMAL;
766                          }                          }
767                  }                  }
# Line 478  int dev_pckbc_access(struct cpu *cpu, st Line 771  int dev_pckbc_access(struct cpu *cpu, st
771           *  8242 (PS2):           *  8242 (PS2):
772           */           */
773    
 /*  
  *  BIG TODO: The following should be rewritten to use dev_pckbc_command()  
  *  etc, like the 8042 code above does.  
  */  
   
774          case PS2 + PS2_TXBUF:          case PS2 + PS2_TXBUF:
775                  if (writeflag==MEM_READ) {                  if (writeflag==MEM_READ) {
776                          odata = random() & 0xff;                          odata = random() & 0xff;
# Line 493  int dev_pckbc_access(struct cpu *cpu, st Line 781  int dev_pckbc_access(struct cpu *cpu, st
781                              "0x%llx ]\n", port_nr, (long long)idata);                              "0x%llx ]\n", port_nr, (long long)idata);
782    
783                          /*  Handle keyboard commands:  */                          /*  Handle keyboard commands:  */
784                          switch (idata) {                          d->reg[PS2_TXBUF] = idata;
785                          /*  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);  
                         }  
786                  }                  }
787                  break;                  break;
788    
# Line 617  int dev_pckbc_access(struct cpu *cpu, st Line 847  int dev_pckbc_access(struct cpu *cpu, st
847                  }                  }
848          }          }
849    
850            /*  SGI? TODO: fix  */
851            if (len == 8)
852                    odata |= (odata << 8) | (odata << 16) | (odata << 24) |
853                        (odata << 32) | (odata << 40) | (odata << 48) |
854                        (odata << 56);
855    
856          if (writeflag == MEM_READ)          if (writeflag == MEM_READ)
857                  memory_writemax64(cpu, data, len, odata);                  memory_writemax64(cpu, data, len, odata);
858    
# Line 633  int dev_pckbc_access(struct cpu *cpu, st Line 869  int dev_pckbc_access(struct cpu *cpu, st
869   */   */
870  int dev_pckbc_init(struct machine *machine, struct memory *mem,  int dev_pckbc_init(struct machine *machine, struct memory *mem,
871          uint64_t baseaddr, int type, int keyboard_irqnr, int mouse_irqnr,          uint64_t baseaddr, int type, int keyboard_irqnr, int mouse_irqnr,
872          int in_use)          int in_use, int pc_style_flag)
873  {  {
874          struct pckbc_data *d;          struct pckbc_data *d;
875          int len = DEV_PCKBC_LENGTH;          int len = DEV_PCKBC_LENGTH;
# Line 645  int dev_pckbc_init(struct machine *machi Line 881  int dev_pckbc_init(struct machine *machi
881          }          }
882          memset(d, 0, sizeof(struct pckbc_data));          memset(d, 0, sizeof(struct pckbc_data));
883    
884            if (type == PCKBC_8242)
885                    len = 0x18;
886    
887          if (type == PCKBC_JAZZ) {          if (type == PCKBC_JAZZ) {
888                  type = PCKBC_8042;                  type = PCKBC_8042;
889                  len = DEV_PCKBC_LENGTH + 0x60;                  len = DEV_PCKBC_LENGTH + 0x60;
890          }          }
891    
892          d->type           = type;          d->type              = type;
893          d->keyboard_irqnr = keyboard_irqnr;          d->keyboard_irqnr    = keyboard_irqnr;
894          d->mouse_irqnr    = mouse_irqnr;          d->mouse_irqnr       = mouse_irqnr;
895          d->in_use         = in_use;          d->in_use            = in_use;
896          d->console_handle = console_start_slave_inputonly(machine, "pckbc");          d->pc_style_flag     = pc_style_flag;
897            d->translation_table = 2;
898            d->rx_int_enable     = 1;
899            d->output_byte       = 0x02;    /*  A20 enable on PCs  */
900    
901            d->console_handle = console_start_slave_inputonly(
902                machine, "pckbc", d->in_use);
903    
904          memory_device_register(mem, "pckbc", baseaddr,          memory_device_register(mem, "pckbc", baseaddr,
905              len, dev_pckbc_access, d, MEM_DEFAULT, NULL);              len, dev_pckbc_access, d, DM_DEFAULT, NULL);
906          machine_add_tickfunction(machine, dev_pckbc_tick, d, PCKBC_TICKSHIFT);          machine_add_tickfunction(machine, dev_pckbc_tick, d, PCKBC_TICKSHIFT);
907    
908          return d->console_handle;          return d->console_handle;

Legend:
Removed from v.4  
changed lines
  Added in v.22

  ViewVC Help
Powered by ViewVC 1.1.26