/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4 - (hide annotations)
Mon Oct 8 16:18:00 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 17896 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.707 2005/04/27 16:37:33 debug Exp $
20050408	Some minor updates to the wdc. Linux now doesn't complain
		anymore if a disk is non-present.
20050409	Various minor fixes (a bintrans bug, and some other things).
		The wdc seems to work with Playstation2 emulation, but there
		is a _long_ annoying delay when disks are detected.
		Fixing a really important bintrans bug (when devices and RAM
		are mixed within 4KB pages), which was triggered with
		NetBSD/playstation2 kernels.
20050410	Adding a dummy dev_ps2_ether (just so that NetBSD doesn't
		complain as much during bootup).
		Symbols starting with '$' are now ignored.
		Renaming dev_ps2_ohci.c to dev_ohci.c, etc.
20050411	Moving the bintrans-cache-isolation check from cpu_mips.c to
		cpu_mips_coproc.c. (I thought this would give a speedup, but
		it's not noticable.)
		Better playstation2 sbus interrupt code.
		Skip ahead many ticks if the count register is read manually.
		(This increases the speed of delay-loops that simply read
		the count register.)
20050412	Updates to the playstation2 timer/interrupt code.
		Some other minor updates.
20050413	NetBSD/cobalt runs from a disk image :-) including userland;
		updating the documentation on how to install NetBSD/cobalt
		using NetBSD/pmax (!).
		Some minor bintrans updates (no real speed improvement) and
		other minor updates (playstation2 now uses the -o options).
20050414	Adding a dummy x86 (and AMD64) mode.
20050415	Adding some (32-bit and 16-bit) x86 instructions.
		Adding some initial support for non-SCSI, non-IDE floppy
		images. (The x86 mode can boot from these, more or less.)
		Moving the devices/ and include/ directories to src/devices/
		and src/include/, respectively.
20050416	Continuing on the x86 stuff. (Adding pc_bios.c and some simple
		support for software interrupts in 16-bit mode.)
20050417	Ripping out most of the x86 instruction decoding stuff, trying
		to rewrite it in a cleaner way.
		Disabling some of the least working CPU families in the
		configure script (sparc, x86, alpha, hppa), so that they are
		not enabled by default.
20050418	Trying to fix the bug which caused problems when turning on
		and off bintrans interactively, by flushing the bintrans cache
		whenever bintrans is manually (re)enabled.
20050419	Adding the 'lswi' ppc instruction.
		Minor updates to the x86 instruction decoding.
20050420	Renaming x86 register name indices from R_xx to X86_R_xx (this
		makes building on Tru64 nicer).
20050422	Adding a check for duplicate MIPS TLB entries on tlbwr/tlbwi.
20050427	Adding screenshots to guestoses.html.
		Some minor fixes and testing for the next release.

==============  RELEASE 0.3.2  ==============


1 dpavlin 4 /*
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