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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 30 - (hide 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 dpavlin 6 /*
2 dpavlin 22 * Copyright (C) 2005-2006 Anders Gavare. All rights reserved.
3 dpavlin 6 *
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 dpavlin 30 * $Id: dev_8253.c,v 1.14 2006/07/24 19:08:17 debug Exp $
29 dpavlin 6 *
30 dpavlin 28 * 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 dpavlin 6 */
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 dpavlin 28 #include "i8253reg.h"
49 dpavlin 6
50 dpavlin 28
51     /* #define debug fatal */
52    
53 dpavlin 6 #define DEV_8253_LENGTH 4
54     #define TICK_SHIFT 14
55    
56    
57     struct pit8253_data {
58 dpavlin 20 int in_use;
59 dpavlin 28
60     int irq0_nr;
61 dpavlin 6 int counter_select;
62 dpavlin 28 uint8_t mode_byte;
63    
64     int mode[3];
65     int counter[3];
66 dpavlin 6 };
67    
68    
69 dpavlin 28 DEVICE_TICK(8253)
70 dpavlin 6 {
71     struct pit8253_data *d = (struct pit8253_data *) extra;
72 dpavlin 20
73     if (!d->in_use)
74     return;
75    
76 dpavlin 28 switch (d->mode[0] & 0x0e) {
77 dpavlin 30
78 dpavlin 28 case I8253_TIMER_INTTC:
79     /* TODO: Correct frequency! */
80     cpu_interrupt(cpu, d->irq0_nr);
81     break;
82 dpavlin 30
83 dpavlin 28 case I8253_TIMER_RATEGEN:
84     break;
85 dpavlin 30
86 dpavlin 28 default:fatal("[ 8253: unimplemented mode 0x%x ]\n", d->mode[0] & 0x0e);
87     exit(1);
88     }
89 dpavlin 6 }
90    
91    
92 dpavlin 22 DEVICE_ACCESS(8253)
93 dpavlin 6 {
94     struct pit8253_data *d = (struct pit8253_data *) extra;
95     uint64_t idata = 0, odata = 0;
96    
97 dpavlin 18 if (writeflag == MEM_WRITE)
98     idata = memory_readmax64(cpu, data, len);
99 dpavlin 6
100 dpavlin 20 d->in_use = 1;
101    
102 dpavlin 6 /* TODO: ack somewhere else */
103 dpavlin 28 cpu_interrupt_ack(cpu, d->irq0_nr);
104 dpavlin 6
105     switch (relative_addr) {
106 dpavlin 28
107     case I8253_TIMER_CNTR0:
108     case I8253_TIMER_CNTR1:
109     case I8253_TIMER_CNTR2:
110 dpavlin 6 if (writeflag == MEM_WRITE) {
111 dpavlin 28 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 dpavlin 6 } else {
130 dpavlin 28 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 dpavlin 6 }
143 dpavlin 28
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 dpavlin 6 break;
149 dpavlin 28
150     case I8253_TIMER_MODE:
151 dpavlin 6 if (writeflag == MEM_WRITE) {
152 dpavlin 28 d->mode_byte = idata;
153    
154 dpavlin 6 d->counter_select = idata >> 6;
155 dpavlin 28 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 dpavlin 6 } else {
183 dpavlin 28 debug("[ 8253: read; can this actually happen? ]\n");
184     odata = d->mode_byte;
185 dpavlin 6 }
186     break;
187 dpavlin 28
188     default:if (writeflag == MEM_WRITE) {
189 dpavlin 6 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 dpavlin 28 exit(1);
196 dpavlin 6 }
197    
198     if (writeflag == MEM_READ)
199     memory_writemax64(cpu, data, len, odata);
200    
201     return 1;
202     }
203    
204    
205 dpavlin 22 DEVINIT(8253)
206 dpavlin 6 {
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 dpavlin 28 d->irq0_nr = devinit->irq_nr;
215 dpavlin 20 d->in_use = devinit->in_use;
216 dpavlin 6
217 dpavlin 28 /* 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 dpavlin 6 memory_device_register(devinit->machine->memory, devinit->name,
223     devinit->addr, DEV_8253_LENGTH, dev_8253_access, (void *)d,
224 dpavlin 20 DM_DEFAULT, NULL);
225 dpavlin 6
226     machine_add_tickfunction(devinit->machine, dev_8253_tick,
227 dpavlin 24 d, TICK_SHIFT, 0.0);
228 dpavlin 6
229     return 1;
230     }
231    

  ViewVC Help
Powered by ViewVC 1.1.26