/[gxemul]/upstream/0.3.1/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

Contents of /upstream/0.3.1/devices/dev_pckbc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (show annotations)
Mon Oct 8 16:17:52 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 17896 byte(s)
0.3.1
1 /*
2 * Copyright (C) 2003-2005 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 * $Id: dev_pckbc.c,v 1.37 2005/02/22 06:26:10 debug Exp $
29 *
30 * Standard 8042 PC keyboard controller, and a 8242WB PS2 keyboard/mouse
31 * controller.
32 *
33 *
34 * TODO: Finish the rewrite for 8242.
35 */
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 #include "console.h"
42 #include "cpu.h"
43 #include "devices.h"
44 #include "machine.h"
45 #include "memory.h"
46 #include "misc.h"
47
48 #include "kbdreg.h"
49
50
51 /* #define PCKBC_DEBUG */
52
53
54 #define MAX_8042_QUEUELEN 256
55
56 #define PC_DATA 0
57 #define PC_CMD 0
58 #define PC_STATUS 1
59
60 #define PS2_TXBUF 0
61 #define PS2_RXBUF 1
62 #define PS2_CONTROL 2
63 #define PS2_STATUS 3
64
65 #define PS2 100
66
67 #define PCKBC_TICKSHIFT 14
68
69 struct pckbc_data {
70 int console_handle;
71 int in_use;
72 int any_command_used;
73
74 int reg[DEV_PCKBC_LENGTH];
75 int keyboard_irqnr;
76 int mouse_irqnr;
77 int type;
78
79 /* TODO: one of these for each port? */
80 int clocksignal;
81 int rx_int_enable;
82 int tx_int_enable;
83
84 int keyscanning_enabled;
85 int state;
86 int cmdbyte;
87 int last_scancode;
88
89 unsigned key_queue[2][MAX_8042_QUEUELEN];
90 int head[2], tail[2];
91 };
92
93 #define STATE_NORMAL 0
94 #define STATE_LDCMDBYTE 1
95 #define STATE_RDCMDBYTE 2
96 #define STATE_WAITING_FOR_TRANSLTABLE 3
97
98
99 /*
100 * pckbc_add_code():
101 *
102 * Adds a byte to the data queue.
103 */
104 void pckbc_add_code(struct pckbc_data *d, int code, int port)
105 {
106 /* Add at the head, read at the tail: */
107 d->head[port] = (d->head[port]+1) % MAX_8042_QUEUELEN;
108 if (d->head[port] == d->tail[port])
109 fatal("[ pckbc: queue overrun, port %i! ]\n", port);
110
111 d->key_queue[port][d->head[port]] = code;
112 }
113
114
115 /*
116 * pckbc_get_code():
117 *
118 * Reads a byte from a data queue.
119 */
120 int pckbc_get_code(struct pckbc_data *d, int port)
121 {
122 if (d->head[port] == d->tail[port])
123 fatal("[ pckbc: queue empty, port %i! ]\n", port);
124
125 d->tail[port] = (d->tail[port]+1) % MAX_8042_QUEUELEN;
126 return d->key_queue[port][d->tail[port]];
127 }
128
129
130 /*
131 * ascii_to_scancodes():
132 *
133 * Conversion from ASCII codes to default (US) keyboard scancodes.
134 * (See http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html)
135 */
136 static void ascii_to_pc_scancodes(int a, struct pckbc_data *d)
137 {
138 int p = 0; /* port */
139 int shift = 0, ctrl = 0;
140
141 if (a >= 'A' && a <= 'Z') { a += 32; shift = 1; }
142 if ((a >= 1 && a <= 26) && (a!='\n' && a!='\t' && a!='\b' && a!='\r'))
143 { a += 96; ctrl = 1; }
144
145 if (shift)
146 pckbc_add_code(d, 0x2a, p);
147 else
148 pckbc_add_code(d, 0x2a + 0x80, p);
149
150 if (ctrl)
151 pckbc_add_code(d, 0x1d, p);
152
153 /*
154 * TODO: Release for all of these?
155 */
156
157 if (a==27) pckbc_add_code(d, 0x01, p);
158
159 if (a=='1') pckbc_add_code(d, 0x02, p);
160 if (a=='2') pckbc_add_code(d, 0x03, p);
161 if (a=='3') pckbc_add_code(d, 0x04, p);
162 if (a=='4') pckbc_add_code(d, 0x05, p);
163 if (a=='5') pckbc_add_code(d, 0x06, p);
164 if (a=='6') pckbc_add_code(d, 0x07, p);
165 if (a=='7') pckbc_add_code(d, 0x08, p);
166 if (a=='8') pckbc_add_code(d, 0x09, p);
167 if (a=='9') pckbc_add_code(d, 0x0a, p);
168 if (a=='0') pckbc_add_code(d, 0x0b, p);
169 if (a=='-') pckbc_add_code(d, 0x0c, p);
170 if (a=='=') pckbc_add_code(d, 0x0d, p);
171
172 if (a=='!') { pckbc_add_code(d, 0x2a, p);
173 pckbc_add_code(d, 0x02, p); }
174 if (a=='@') { pckbc_add_code(d, 0x2a, p);
175 pckbc_add_code(d, 0x03, p); }
176 if (a=='#') { pckbc_add_code(d, 0x2a, p);
177 pckbc_add_code(d, 0x04, p); }
178 if (a=='$') { pckbc_add_code(d, 0x2a, p);
179 pckbc_add_code(d, 0x05, p); }
180 if (a=='%') { pckbc_add_code(d, 0x2a, p);
181 pckbc_add_code(d, 0x06, p); }
182 if (a=='^') { pckbc_add_code(d, 0x2a, p);
183 pckbc_add_code(d, 0x07, p); }
184 if (a=='&') { pckbc_add_code(d, 0x2a, p);
185 pckbc_add_code(d, 0x08, p); }
186 if (a=='*') { pckbc_add_code(d, 0x2a, p);
187 pckbc_add_code(d, 0x09, p); }
188 if (a=='(') { pckbc_add_code(d, 0x2a, p);
189 pckbc_add_code(d, 0x0a, p); }
190 if (a==')') { pckbc_add_code(d, 0x2a, p);
191 pckbc_add_code(d, 0x0b, p); }
192 if (a=='_') { pckbc_add_code(d, 0x2a, p);
193 pckbc_add_code(d, 0x0c, p); }
194 if (a=='+') { pckbc_add_code(d, 0x2a, p);
195 pckbc_add_code(d, 0x0d, p); }
196
197 if (a=='\b') pckbc_add_code(d, 0x0e, p);
198
199 if (a=='\t') pckbc_add_code(d, 0x0f, p);
200 if (a=='q') pckbc_add_code(d, 0x10, p);
201 if (a=='w') pckbc_add_code(d, 0x11, p);
202 if (a=='e') pckbc_add_code(d, 0x12, p);
203 if (a=='r') pckbc_add_code(d, 0x13, p);
204 if (a=='t') pckbc_add_code(d, 0x14, p);
205 if (a=='y') pckbc_add_code(d, 0x15, p);
206 if (a=='u') pckbc_add_code(d, 0x16, p);
207 if (a=='i') pckbc_add_code(d, 0x17, p);
208 if (a=='o') pckbc_add_code(d, 0x18, p);
209 if (a=='p') pckbc_add_code(d, 0x19, p);
210
211 if (a=='[') pckbc_add_code(d, 0x1a, p);
212 if (a=='{') { pckbc_add_code(d, 0x2a, p);
213 pckbc_add_code(d, 0x1a, p); }
214 if (a==']') pckbc_add_code(d, 0x1b, p);
215 if (a=='}') { pckbc_add_code(d, 0x2a, p);
216 pckbc_add_code(d, 0x1b, p); }
217
218 if (a=='\n' || a=='\r') pckbc_add_code(d, 0x1c, p);
219
220 if (a=='a') pckbc_add_code(d, 0x1e, p);
221 if (a=='s') pckbc_add_code(d, 0x1f, p);
222 if (a=='d') pckbc_add_code(d, 0x20, p);
223 if (a=='f') pckbc_add_code(d, 0x21, p);
224 if (a=='g') pckbc_add_code(d, 0x22, p);
225 if (a=='h') pckbc_add_code(d, 0x23, p);
226 if (a=='j') pckbc_add_code(d, 0x24, p);
227 if (a=='k') pckbc_add_code(d, 0x25, p);
228 if (a=='l') pckbc_add_code(d, 0x26, p);
229
230 if (a==';') pckbc_add_code(d, 0x27, p);
231 if (a==':') { pckbc_add_code(d, 0x2a, p);
232 pckbc_add_code(d, 0x27, p); }
233 if (a=='\'') pckbc_add_code(d, 0x28, p);
234 if (a=='"') { pckbc_add_code(d, 0x2a, p);
235 pckbc_add_code(d, 0x28, p); }
236 if (a=='~') pckbc_add_code(d, 0x29, p);
237
238 if (a=='\\') pckbc_add_code(d, 0x2b, p);
239 if (a=='|') { pckbc_add_code(d, 0x2a, p);
240 pckbc_add_code(d, 0x2b, p); }
241
242 if (a=='z') pckbc_add_code(d, 0x2c, p);
243 if (a=='x') pckbc_add_code(d, 0x2d, p);
244 if (a=='c') pckbc_add_code(d, 0x2e, p);
245 if (a=='v') pckbc_add_code(d, 0x2f, p);
246 if (a=='b') pckbc_add_code(d, 0x30, p);
247 if (a=='n') pckbc_add_code(d, 0x31, p);
248 if (a=='m') pckbc_add_code(d, 0x32, p);
249
250 if (a==',') pckbc_add_code(d, 0x33, p);
251 if (a=='<') { pckbc_add_code(d, 0x2a, p);
252 pckbc_add_code(d, 0x33, p); }
253 if (a=='.') pckbc_add_code(d, 0x34, p);
254 if (a=='>') { pckbc_add_code(d, 0x2a, p);
255 pckbc_add_code(d, 0x34, p); }
256 if (a=='/') pckbc_add_code(d, 0x35, p);
257 if (a=='?') { pckbc_add_code(d, 0x2a, p);
258 pckbc_add_code(d, 0x35, p); }
259
260 if (a==' ') pckbc_add_code(d, 0x39, p);
261
262 /* Release ctrl: */
263 if (ctrl)
264 pckbc_add_code(d, 0x1d + 0x80, p);
265 }
266
267
268 /*
269 * dev_pckbc_tick():
270 */
271 void dev_pckbc_tick(struct cpu *cpu, void *extra)
272 {
273 struct pckbc_data *d = extra;
274 int port_nr;
275 int ch;
276
277 if (d->in_use && d->any_command_used &&
278 console_charavail(d->console_handle)) {
279 ch = console_readchar(d->console_handle);
280 if (ch >= 0)
281 ascii_to_pc_scancodes(ch, d);
282 }
283
284 /* TODO: mouse movements? */
285
286 for (port_nr=0; port_nr<2; port_nr++) {
287 /* Cause receive interrupt,
288 if there's something in the receive buffer: */
289 if (d->head[port_nr] != d->tail[port_nr] && d->rx_int_enable) {
290 cpu_interrupt(cpu, port_nr==0? d->keyboard_irqnr
291 : d->mouse_irqnr);
292 } else {
293 cpu_interrupt_ack(cpu, port_nr==0? d->keyboard_irqnr
294 : d->mouse_irqnr);
295 }
296 }
297 }
298
299
300 /*
301 * dev_pckbc_command():
302 */
303 static void dev_pckbc_command(struct pckbc_data *d, int port_nr)
304 {
305 int cmd = d->reg[PC_CMD];
306
307 d->any_command_used = 1;
308
309 if (d->type == PCKBC_8242)
310 cmd = d->reg[PS2_TXBUF];
311
312 if (d->state == STATE_WAITING_FOR_TRANSLTABLE) {
313 debug("[ pckbc: switching to translation table 0x%02x ]\n",
314 cmd);
315 pckbc_add_code(d, KBR_ACK, port_nr);
316 d->state = STATE_NORMAL;
317 return;
318 }
319
320 switch (cmd) {
321 case 0x00:
322 pckbc_add_code(d, KBR_ACK, port_nr);
323 break;
324 case KBC_MODEIND: /* Set LEDs */
325 /* Just ACK, no LEDs are actually set. */
326 pckbc_add_code(d, KBR_ACK, port_nr);
327 break;
328 case KBC_SETTABLE:
329 pckbc_add_code(d, KBR_ACK, port_nr);
330 d->state = STATE_WAITING_FOR_TRANSLTABLE;
331 break;
332 case KBC_ENABLE:
333 d->keyscanning_enabled = 1;
334 pckbc_add_code(d, KBR_ACK, port_nr);
335 break;
336 case KBC_DISABLE:
337 d->keyscanning_enabled = 0;
338 pckbc_add_code(d, KBR_ACK, port_nr);
339 break;
340 case KBC_SETDEFAULT:
341 pckbc_add_code(d, KBR_ACK, port_nr);
342 break;
343 case KBC_RESET:
344 pckbc_add_code(d, KBR_ACK, port_nr);
345 pckbc_add_code(d, KBR_RSTDONE, port_nr);
346 break;
347 default:
348 fatal("[ pckbc: UNIMPLEMENTED command 0x%02x ]\n", cmd);
349 }
350 }
351
352
353 /*
354 * dev_pckbc_access():
355 */
356 int dev_pckbc_access(struct cpu *cpu, struct memory *mem,
357 uint64_t relative_addr, unsigned char *data, size_t len,
358 int writeflag, void *extra)
359 {
360 uint64_t idata = 0, odata = 0;
361 int i, port_nr = 0;
362 struct pckbc_data *d = extra;
363
364 idata = memory_readmax64(cpu, data, len);
365
366 #ifdef PCKBC_DEBUG
367 if (writeflag == MEM_WRITE)
368 fatal("[ pckbc: write to addr 0x%x: 0x%x ]\n",
369 (int)relative_addr, (int)idata);
370 else
371 fatal("[ pckbc: read from addr 0x%x ]\n",
372 (int)relative_addr);
373 #endif
374
375 /* For JAZZ-based machines: */
376 if (relative_addr >= 0x60)
377 relative_addr -= 0x60;
378
379 /* 8242 PS2-style: */
380 if (d->type == PCKBC_8242) {
381 /* when using 8-byte alignment... */
382 relative_addr /= sizeof(uint64_t);
383 /* port_nr = 0 for keyboard, 1 for mouse */
384 port_nr = (relative_addr >> 2);
385 relative_addr &= 3;
386 relative_addr += PS2;
387 } else {
388 /* The relative_addr is either 0 or 1,
389 but some machines use longer registers than one byte
390 each, so this will make things simpler for us: */
391 if (relative_addr)
392 relative_addr = 1;
393 }
394
395 switch (relative_addr) {
396
397 /*
398 * 8042 (PC):
399 */
400
401 case 0: /* data */
402 if (writeflag==MEM_READ) {
403 if (d->state == STATE_RDCMDBYTE) {
404 odata = d->cmdbyte;
405 d->state = STATE_NORMAL;
406 } else {
407 if (d->head[0] != d->tail[0]) {
408 odata = pckbc_get_code(d, 0);
409 d->last_scancode = odata;
410 } else {
411 odata = d->last_scancode;
412 d->last_scancode |= 0x80;
413 }
414 }
415 debug("[ pckbc: read from DATA: 0x%02x ]\n", odata);
416 } else {
417 debug("[ pckbc: write to DATA:");
418 for (i=0; i<len; i++)
419 debug(" %02x", data[i]);
420 debug(" ]\n");
421
422 if (d->state == STATE_LDCMDBYTE) {
423 d->cmdbyte = idata;
424 d->rx_int_enable = d->cmdbyte &
425 (KC8_KENABLE | KC8_MENABLE) ? 1 : 0;
426 d->state = STATE_NORMAL;
427 } else {
428 d->reg[relative_addr] = idata;
429 dev_pckbc_command(d, port_nr);
430 }
431 }
432 break;
433 case 1: /* control */
434 if (writeflag==MEM_READ) {
435 dev_pckbc_tick(cpu, d);
436
437 odata = 0;
438
439 /* "Data in buffer" bit */
440 if (d->head[0] != d->tail[0] ||
441 d->state == STATE_RDCMDBYTE)
442 odata |= KBS_DIB;
443 /* odata |= KBS_OCMD; */
444 /* debug("[ pckbc: read from CTL status port: "
445 "0x%02x ]\n", (int)odata); */
446 } else {
447 debug("[ pckbc: write to CTL:");
448 for (i=0; i<len; i++)
449 debug(" %02x", data[i]);
450 debug(" ]\n");
451 d->reg[relative_addr] = idata;
452
453 switch (idata) {
454 case K_RDCMDBYTE:
455 d->state = STATE_RDCMDBYTE;
456 break;
457 case K_LDCMDBYTE:
458 d->state = STATE_LDCMDBYTE;
459 break;
460 case 0xa9: /* test auxiliary port */
461 debug("[ pckbc: CONTROL 0xa9, TODO ]\n");
462 break;
463 case 0xaa: /* keyboard self-test */
464 pckbc_add_code(d, 0x55, port_nr);
465 break;
466 case 0xd4: /* write to auxiliary port */
467 debug("[ pckbc: CONTROL 0xd4, TODO ]\n");
468 break;
469 default:
470 fatal("[ pckbc: unknown CONTROL 0x%x ]\n",
471 idata);
472 d->state = STATE_NORMAL;
473 }
474 }
475 break;
476
477 /*
478 * 8242 (PS2):
479 */
480
481 /*
482 * BIG TODO: The following should be rewritten to use dev_pckbc_command()
483 * etc, like the 8042 code above does.
484 */
485
486 case PS2 + PS2_TXBUF:
487 if (writeflag==MEM_READ) {
488 odata = random() & 0xff;
489 debug("[ pckbc: read from port %i, PS2_TXBUF: "
490 "0x%x ]\n", port_nr, (int)odata);
491 } else {
492 debug("[ pckbc: write to port %i, PS2_TXBUF: "
493 "0x%llx ]\n", port_nr, (long long)idata);
494
495 /* Handle keyboard commands: */
496 switch (idata) {
497 /* These are incorrect, the second byte of
498 commands should be treated better: */
499 case 0x00: /* second byte of 0xed,
500 SGI-IP32's prom */
501 pckbc_add_code(d, 0x03, port_nr);/* ack (?) */
502 break;
503 case 0x14: /* second byte of 0xfc,
504 SGI-IP32's prom */
505 case 0x28: /* second byte of 0xf3,
506 SGI-IP32's prom */
507 case 0x76: /* third byte of 0xfc,
508 SGI-IP32's prom */
509 case 0x03: /* second byte of
510 ATKBD_CMD_GSCANSET (?) */
511 case 0x04:
512 pckbc_add_code(d, 0x03, port_nr);/* ? */
513 break;
514
515 /* Command bytes: */
516 case 0xf0: /* ATKBD_CMD_GSCANSET (?) */
517 pckbc_add_code(d, 0x03, port_nr);/* ? */
518 break;
519 case 0xf2: /* Get keyboard ID */
520 /* The keyboard should generate 2
521 status bytes. */
522 pckbc_add_code(d, 0xab, port_nr);
523 pckbc_add_code(d, 0x83, port_nr);
524 break;
525 case 0xed: /* "ATKBD_CMD_SETLEDS",
526 takes 1 byte arg */
527 case 0xf3: /* "PSMOUSE_CMD_SETRATE",
528 takes 1 byte arg */
529 case 0xf4: /* "ATKBD_CMD_ENABLE" (or
530 PSMOUSE_CMD_ENABLE), no args */
531 case 0xf5: /* "ATKBD_CMD_RESET_DIS" (keyboard,
532 according to Linux sources) */
533 case 0xf6: /* "PSMOUSE_CMD_RESET_DIS" (mouse,
534 according to Linux sources) */
535 /* TODO: what does this do? */
536 pckbc_add_code(d, 0xfa, port_nr);/* ack (?) */
537 break;
538 case 0xfa: /* "ATKBD_CMD_SETALL_MBR" (linux) */
539 pckbc_add_code(d, 0xfa, port_nr);/* ack (?) */
540 break;
541 case 0xfc: /* ? */
542 pckbc_add_code(d, 0xfa, port_nr);/* ack (?) */
543 break;
544 case 0xff: /* Keyboard reset */
545 /* The keyboard should generate 2
546 status bytes. */
547 pckbc_add_code(d, 0xfa, port_nr);/* ack (?) */
548 pckbc_add_code(d, 0xaa, port_nr);
549 /* battery ok (?) */
550 break;
551 default:
552 debug("[ pckbc: UNIMPLEMENTED keyboard command"
553 " 0x%02x (port %i) ]\n", (int)idata,
554 port_nr);
555 }
556 }
557 break;
558
559 case PS2 + PS2_RXBUF:
560 if (writeflag==MEM_READ) {
561 /* TODO: What should be returned if no data
562 is available? */
563 odata = random() & 0xff;
564 if (d->head[port_nr] != d->tail[port_nr])
565 odata = pckbc_get_code(d, port_nr);
566 debug("[ pckbc: read from port %i, PS2_RXBUF: "
567 "0x%02x ]\n", port_nr, (int)odata);
568 } else {
569 debug("[ pckbc: write to port %i, PS2_RXBUF: "
570 "0x%llx ]\n", port_nr, (long long)idata);
571 }
572 break;
573
574 case PS2 + PS2_CONTROL:
575 if (writeflag==MEM_READ) {
576 debug("[ pckbc: read from port %i, PS2_CONTROL"
577 " ]\n", port_nr);
578 } else {
579 debug("[ pckbc: write to port %i, PS2_CONTROL:"
580 " 0x%llx ]\n", port_nr, (long long)idata);
581 d->clocksignal = (idata & 0x10) ? 1 : 0;
582 d->rx_int_enable = (idata & 0x08) ? 1 : 0;
583 d->tx_int_enable = (idata & 0x04) ? 1 : 0;
584 }
585 break;
586
587 case PS2 + PS2_STATUS:
588 if (writeflag==MEM_READ) {
589 /* 0x08 = transmit buffer empty */
590 odata = d->clocksignal + 0x08;
591
592 if (d->head[port_nr] != d->tail[port_nr]) {
593 /* 0x10 = receicer data available (?) */
594 odata |= 0x10;
595 }
596
597 debug("[ pckbc: read from port %i, PS2_STATUS: "
598 "0x%llx ]\n", port_nr, (long long)odata);
599 } else {
600 debug("[ pckbc: write to port %i, PS2_STATUS: "
601 "0x%llx ]\n", port_nr, (long long)idata);
602 }
603 break;
604
605 default:
606 if (writeflag==MEM_READ) {
607 debug("[ pckbc: read from unimplemented reg %i ]\n",
608 (int)relative_addr);
609 odata = d->reg[relative_addr];
610 } else {
611 debug("[ pckbc: write to unimplemented reg %i:",
612 (int)relative_addr);
613 for (i=0; i<len; i++)
614 debug(" %02x", data[i]);
615 debug(" ]\n");
616 d->reg[relative_addr] = idata;
617 }
618 }
619
620 if (writeflag == MEM_READ)
621 memory_writemax64(cpu, data, len, odata);
622
623 dev_pckbc_tick(cpu, d);
624
625 return 1;
626 }
627
628
629 /*
630 * dev_pckbc_init():
631 *
632 * Type should be PCKBC_8042 or PCKBC_8242.
633 */
634 int dev_pckbc_init(struct machine *machine, struct memory *mem,
635 uint64_t baseaddr, int type, int keyboard_irqnr, int mouse_irqnr,
636 int in_use)
637 {
638 struct pckbc_data *d;
639 int len = DEV_PCKBC_LENGTH;
640
641 d = malloc(sizeof(struct pckbc_data));
642 if (d == NULL) {
643 fprintf(stderr, "out of memory\n");
644 exit(1);
645 }
646 memset(d, 0, sizeof(struct pckbc_data));
647
648 if (type == PCKBC_JAZZ) {
649 type = PCKBC_8042;
650 len = DEV_PCKBC_LENGTH + 0x60;
651 }
652
653 d->type = type;
654 d->keyboard_irqnr = keyboard_irqnr;
655 d->mouse_irqnr = mouse_irqnr;
656 d->in_use = in_use;
657 d->console_handle = console_start_slave_inputonly(machine, "pckbc");
658
659 memory_device_register(mem, "pckbc", baseaddr,
660 len, dev_pckbc_access, d, MEM_DEFAULT, NULL);
661 machine_add_tickfunction(machine, dev_pckbc_tick, d, PCKBC_TICKSHIFT);
662
663 return d->console_handle;
664 }
665

  ViewVC Help
Powered by ViewVC 1.1.26