/[gxemul]/trunk/src/devices/dev_8253.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 /trunk/src/devices/dev_8253.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 30 - (show annotations)
Mon Oct 8 16:20:40 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 6086 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1325 2006/08/15 15:38:37 debug Exp $
20060723	More Transputer instructions (pfix, nfix, opr, mint, ldl, ldlp,
		eqc, rev, ajw, stl, stlf, sthf, sub, ldnl, ldnlp, ldpi, move,
		wcnt, add, bcnt).
		Adding more SPARC instructions (andcc, addcc, bl, rdpr).
		Progress on the igsfb framebuffer used by NetBSD/netwinder.
		Enabling 8-bit fills in dev_fb.
		NetBSD/netwinder 3.0.1 can now run from a disk image :-)
20060724	Cleanup/performance fix for 64-bit virtual translation table
		updates (by removing the "timestamp" stuff). A full NetBSD/pmax
		3.0.1 install for R4400 has dropped from 667 seconds to 584 :)
		Fixing the igsfb "almost vga" color (it is 24-bit, not 18-bit).
		Adding some MIPS instruction combinations (3*lw, and 3*addu).
		The 8048 keyboard now turns off interrupt enable between the
		KBR_ACK and the KBR_RSTDONE, to work better with Linux 2.6.
		Not causing PPC DEC interrupts if PPC_NO_DEC is set for a
		specific CPU; NetBSD/bebox gets slightly further than before.
		Adding some more SPARC instructions: branches, udiv.
20060725	Refreshing dev_pckbc.c a little.
		Cleanups for the SH emulation mode, and adding the first
		"compact" (16-bit) instructions: various simple movs, nop,
		shll, stc, or, ldc.
20060726	Adding dummy "pcn" (AMD PCnet NIC) PCI glue.
20060727	Various cleanups; removing stuff from cpu.h, such as
		running_translated (not really meaningful anymore), and
		page flags (breaking into the debugger clears all translations
		anyway).
		Minor MIPS instruction combination updates.
20060807	Expanding the 3*sw and 3*lw MIPS instruction combinations to
		work with 2* and 4* too, resulting in a minor performance gain.
		Implementing a usleep hack for the RM52xx/MIPS32/MIPS64 "wait"
		instruction (when emulating 1 cpu).
20060808	Experimenting with some more MIPS instruction combinations.
		Implementing support for showing a (hardcoded 12x22) text
		cursor in igsfb.
20060809	Simplifying the NetBSD/evbmips (Malta) install instructions
		somewhat (by using a NetBSD/pmax ramdisk install kernel).
20060812	Experimenting more with the MIPS 'wait' instruction.
		PCI configuration register writes can now be handled, which
		allow PCI IDE controllers to work with NetBSD/Malta 3.0.1 and
		NetBSD/cobalt 3.0.1. (Previously only NetBSD 2.1 worked.)
20060813	Updating dev_gt.c based on numbers from Alec Voropay, to enable
		Linux 2.6 to use PCI on Malta.
		Continuing on Algor interrupt stuff.
20060814	Adding support for routing ISA interrupts to two different
		interrupts, making it possible to run NetBSD/algor :-)
20060814-15	Testing for the release.

==============  RELEASE 0.4.2  ==============


1 /*
2 * Copyright (C) 2005-2006 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_8253.c,v 1.14 2006/07/24 19:08:17 debug Exp $
29 *
30 * Intel 8253/8254 Programmable Interval Timer
31 *
32 * TODO: The timers don't really count down. Fix this when there is a generic
33 * clock framework; also split counter[] into reset value and current value.
34 */
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 #include "cpu.h"
41 #include "device.h"
42 #include "devices.h"
43 #include "emul.h"
44 #include "machine.h"
45 #include "memory.h"
46 #include "misc.h"
47
48 #include "i8253reg.h"
49
50
51 /* #define debug fatal */
52
53 #define DEV_8253_LENGTH 4
54 #define TICK_SHIFT 14
55
56
57 struct pit8253_data {
58 int in_use;
59
60 int irq0_nr;
61 int counter_select;
62 uint8_t mode_byte;
63
64 int mode[3];
65 int counter[3];
66 };
67
68
69 DEVICE_TICK(8253)
70 {
71 struct pit8253_data *d = (struct pit8253_data *) extra;
72
73 if (!d->in_use)
74 return;
75
76 switch (d->mode[0] & 0x0e) {
77
78 case I8253_TIMER_INTTC:
79 /* TODO: Correct frequency! */
80 cpu_interrupt(cpu, d->irq0_nr);
81 break;
82
83 case I8253_TIMER_RATEGEN:
84 break;
85
86 default:fatal("[ 8253: unimplemented mode 0x%x ]\n", d->mode[0] & 0x0e);
87 exit(1);
88 }
89 }
90
91
92 DEVICE_ACCESS(8253)
93 {
94 struct pit8253_data *d = (struct pit8253_data *) extra;
95 uint64_t idata = 0, odata = 0;
96
97 if (writeflag == MEM_WRITE)
98 idata = memory_readmax64(cpu, data, len);
99
100 d->in_use = 1;
101
102 /* TODO: ack somewhere else */
103 cpu_interrupt_ack(cpu, d->irq0_nr);
104
105 switch (relative_addr) {
106
107 case I8253_TIMER_CNTR0:
108 case I8253_TIMER_CNTR1:
109 case I8253_TIMER_CNTR2:
110 if (writeflag == MEM_WRITE) {
111 switch (d->mode_byte & 0x30) {
112 case I8253_TIMER_LSB:
113 case I8253_TIMER_16BIT:
114 d->counter[relative_addr] &= 0xff00;
115 d->counter[relative_addr] |= (idata & 0xff);
116 break;
117 case I8253_TIMER_MSB:
118 d->counter[relative_addr] &= 0x00ff;
119 d->counter[relative_addr] |= ((idata&0xff)<<8);
120 debug("[ 8253: counter %i set to %i (%i Hz) "
121 "]\n", relative_addr, d->counter[
122 relative_addr], (int)(I8253_TIMER_FREQ /
123 (float)d->counter[relative_addr] + 0.5));
124 break;
125 default:fatal("[ 8253: huh? writing to counter"
126 " %i but neither from msb nor lsb? ]\n",
127 relative_addr);
128 }
129 } else {
130 switch (d->mode_byte & 0x30) {
131 case I8253_TIMER_LSB:
132 case I8253_TIMER_16BIT:
133 odata = d->counter[relative_addr] & 0xff;
134 break;
135 case I8253_TIMER_MSB:
136 odata = (d->counter[relative_addr] >> 8) & 0xff;
137 break;
138 default:fatal("[ 8253: huh? reading from counter"
139 " %i but neither from msb nor lsb? ]\n",
140 relative_addr);
141 }
142 }
143
144 /* Switch from LSB to MSB, if accessing as 16-bit word: */
145 if ((d->mode_byte & 0x30) == I8253_TIMER_16BIT)
146 d->mode_byte &= ~I8253_TIMER_LSB;
147
148 break;
149
150 case I8253_TIMER_MODE:
151 if (writeflag == MEM_WRITE) {
152 d->mode_byte = idata;
153
154 d->counter_select = idata >> 6;
155 if (d->counter_select > 2) {
156 debug("[ 8253: attempt to select counter 3,"
157 " which doesn't exist. ]\n");
158 d->counter_select = 0;
159 }
160
161 d->mode[d->counter_select] = idata & 0x0e;
162
163 debug("[ 8253: select=%i mode=0x%x ",
164 d->counter_select, d->mode[d->counter_select]);
165 if (idata & 0x30) {
166 switch (idata & 0x30) {
167 case I8253_TIMER_LSB:
168 debug("LSB ");
169 break;
170 case I8253_TIMER_16BIT:
171 debug("LSB+");
172 case I8253_TIMER_MSB:
173 debug("MSB ");
174 }
175 }
176 debug("]\n");
177
178 if (idata & I8253_TIMER_BCD) {
179 fatal("[ 8253: BCD not yet implemented ]\n");
180 exit(1);
181 }
182 } else {
183 debug("[ 8253: read; can this actually happen? ]\n");
184 odata = d->mode_byte;
185 }
186 break;
187
188 default:if (writeflag == MEM_WRITE) {
189 fatal("[ 8253: unimplemented write to address 0x%x"
190 " data=0x%02x ]\n", (int)relative_addr, (int)idata);
191 } else {
192 fatal("[ 8253: unimplemented read from address 0x%x "
193 "]\n", (int)relative_addr);
194 }
195 exit(1);
196 }
197
198 if (writeflag == MEM_READ)
199 memory_writemax64(cpu, data, len, odata);
200
201 return 1;
202 }
203
204
205 DEVINIT(8253)
206 {
207 struct pit8253_data *d = malloc(sizeof(struct pit8253_data));
208
209 if (d == NULL) {
210 fprintf(stderr, "out of memory\n");
211 exit(1);
212 }
213 memset(d, 0, sizeof(struct pit8253_data));
214 d->irq0_nr = devinit->irq_nr;
215 d->in_use = devinit->in_use;
216
217 /* Don't cause interrupt, by default. */
218 d->mode[0] = I8253_TIMER_RATEGEN;
219 d->mode[1] = I8253_TIMER_RATEGEN;
220 d->mode[2] = I8253_TIMER_RATEGEN;
221
222 memory_device_register(devinit->machine->memory, devinit->name,
223 devinit->addr, DEV_8253_LENGTH, dev_8253_access, (void *)d,
224 DM_DEFAULT, NULL);
225
226 machine_add_tickfunction(devinit->machine, dev_8253_tick,
227 d, TICK_SHIFT, 0.0);
228
229 return 1;
230 }
231

  ViewVC Help
Powered by ViewVC 1.1.26