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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 30 - (show annotations)
Mon Oct 8 16:20:40 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 8791 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) 2003-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_dc7085.c,v 1.56 2006/07/23 14:37:34 debug Exp $
29 *
30 * DC7085 serial controller, used in some DECstation models.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include "console.h"
38 #include "cpu.h"
39 #include "devices.h"
40 #include "machine.h"
41 #include "memory.h"
42 #include "misc.h"
43
44 #include "dc7085.h"
45
46
47 #define DC_TICK_SHIFT 14
48
49 #define MAX_QUEUE_LEN 4096
50
51 struct dc_data {
52 struct dc7085regs regs;
53
54 int console_handle;
55
56 /* For slow_serial_interrupts_hack_for_linux: */
57 int just_transmitted_something;
58
59 unsigned char rx_queue_char[MAX_QUEUE_LEN];
60 char rx_queue_lineno[MAX_QUEUE_LEN];
61 int cur_rx_queue_pos_write;
62 int cur_rx_queue_pos_read;
63
64 int tx_scanner;
65
66 int irqnr;
67 int use_fb;
68
69 struct lk201_data lk201;
70 };
71
72
73 /*
74 * Add a character to the receive queue.
75 */
76 void add_to_rx_queue(void *e, int ch, int line_no)
77 {
78 struct dc_data *d = (struct dc_data *) e;
79 int entries_in_use = d->cur_rx_queue_pos_write -
80 d->cur_rx_queue_pos_read;
81 while (entries_in_use < 0)
82 entries_in_use += MAX_QUEUE_LEN;
83
84 /* Ignore mouse updates, if they come too often: */
85 if (entries_in_use > MAX_QUEUE_LEN/2 && line_no == DCMOUSE_PORT)
86 return;
87
88 d->rx_queue_char[d->cur_rx_queue_pos_write] = ch;
89 d->rx_queue_lineno[d->cur_rx_queue_pos_write] = line_no;
90 d->cur_rx_queue_pos_write ++;
91 if (d->cur_rx_queue_pos_write == MAX_QUEUE_LEN)
92 d->cur_rx_queue_pos_write = 0;
93
94 if (d->cur_rx_queue_pos_write == d->cur_rx_queue_pos_read)
95 fatal("warning: add_to_rx_queue(): rx_queue overrun!\n");
96 }
97
98
99 DEVICE_TICK(dc7085)
100 {
101 /*
102 * If a key is available from the keyboard, add it to the rx queue.
103 * If other bits are set, an interrupt might need to be caused.
104 */
105 struct dc_data *d = extra;
106 int avail;
107
108 if (cpu->machine->slow_serial_interrupts_hack_for_linux) {
109 /*
110 * Special hack to prevent Linux from Oopsing. (This makes
111 * interrupts not come as fast as possible.)
112 */
113 if (d->just_transmitted_something) {
114 d->just_transmitted_something --;
115 return;
116 }
117 }
118
119 d->regs.dc_csr &= ~CSR_RDONE;
120
121 if ((d->regs.dc_csr & CSR_MSE) && !(d->regs.dc_csr & CSR_TRDY)) {
122 int scanner_start = d->tx_scanner;
123
124 /* Loop until we've checked all 4 channels, or some
125 channel was ready to transmit: */
126
127 do {
128 d->tx_scanner = (d->tx_scanner + 1) % 4;
129
130 if (d->regs.dc_tcr & (1 << d->tx_scanner)) {
131 d->regs.dc_csr |= CSR_TRDY;
132 if (d->regs.dc_csr & CSR_TIE)
133 cpu_interrupt(cpu, d->irqnr);
134
135 d->regs.dc_csr &= ~CSR_TX_LINE_NUM;
136 d->regs.dc_csr |= (d->tx_scanner << 8);
137 }
138 } while (!(d->regs.dc_csr & CSR_TRDY) &&
139 d->tx_scanner != scanner_start);
140
141 /* We have to return here. NetBSD can handle both
142 rx and tx interrupts simultaneously, but Ultrix
143 doesn't like that? */
144
145 if (d->regs.dc_csr & CSR_TRDY)
146 return;
147 }
148
149 lk201_tick(&d->lk201);
150
151 avail = d->cur_rx_queue_pos_write != d->cur_rx_queue_pos_read;
152
153 if (avail && (d->regs.dc_csr & CSR_MSE))
154 d->regs.dc_csr |= CSR_RDONE;
155
156 if ((d->regs.dc_csr & CSR_RDONE) && (d->regs.dc_csr & CSR_RIE))
157 cpu_interrupt(cpu, d->irqnr);
158 }
159
160
161 DEVICE_ACCESS(dc7085)
162 {
163 uint64_t idata = 0, odata = 0;
164 size_t i;
165 struct dc_data *d = extra;
166
167 if (writeflag == MEM_WRITE)
168 idata = memory_readmax64(cpu, data, len);
169
170 /* Always clear: */
171 d->regs.dc_csr &= ~CSR_CLR;
172
173 switch (relative_addr) {
174 case 0x00: /* CSR: Control and Status */
175 if (writeflag == MEM_WRITE) {
176 debug("[ dc7085 write to CSR: 0x%04x ]\n", idata);
177 idata &= (CSR_TIE | CSR_RIE | CSR_MSE | CSR_CLR
178 | CSR_MAINT);
179 d->regs.dc_csr &= ~(CSR_TIE | CSR_RIE | CSR_MSE
180 | CSR_CLR | CSR_MAINT);
181 d->regs.dc_csr |= idata;
182 if (!(d->regs.dc_csr & CSR_MSE))
183 d->regs.dc_csr &= ~(CSR_TRDY | CSR_RDONE);
184 goto do_return;
185 } else {
186 /* read: */
187
188 /* fatal("[ dc7085 read from CSR: (csr = 0x%04x) ]\n",
189 d->regs.dc_csr); */
190 odata = d->regs.dc_csr;
191 }
192 break;
193 case 0x08: /* LPR: */
194 if (writeflag == MEM_WRITE) {
195 debug("[ dc7085 write to LPR: 0x%04x ]\n", idata);
196 d->regs.dc_rbuf_lpr = idata;
197 goto do_return;
198 } else {
199 /* read: */
200 int avail = d->cur_rx_queue_pos_write !=
201 d->cur_rx_queue_pos_read;
202 int ch = 0, lineno = 0;
203 /* debug("[ dc7085 read from RBUF: "); */
204 if (avail) {
205 ch = d->rx_queue_char[d->cur_rx_queue_pos_read];
206 lineno = d->rx_queue_lineno[
207 d->cur_rx_queue_pos_read];
208 d->cur_rx_queue_pos_read++;
209 if (d->cur_rx_queue_pos_read == MAX_QUEUE_LEN)
210 d->cur_rx_queue_pos_read = 0;
211 /* if (ch >= ' ' && ch < 127)
212 debug("'%c'", ch);
213 else
214 debug("0x%x", ch);
215 debug(" for lineno %i ", lineno); */
216 } /* else
217 debug("empty ");
218 debug("]\n"); */
219 odata = (avail? RBUF_DVAL:0) |
220 (lineno << RBUF_LINE_NUM_SHIFT) | ch;
221
222 d->regs.dc_csr &= ~CSR_RDONE;
223 cpu_interrupt_ack(cpu, d->irqnr);
224
225 d->just_transmitted_something = 4;
226 }
227 break;
228 case 0x10: /* TCR: */
229 if (writeflag == MEM_WRITE) {
230 /* fatal("[ dc7085 write to TCR: 0x%04x) ]\n",
231 (int)idata); */
232 d->regs.dc_tcr = idata;
233 d->regs.dc_csr &= ~CSR_TRDY;
234 cpu_interrupt_ack(cpu, d->irqnr);
235 goto do_return;
236 } else {
237 /* read: */
238 /* debug("[ dc7085 read from TCR: (tcr = 0x%04x) ]\n",
239 d->regs.dc_tcr); */
240 odata = d->regs.dc_tcr;
241 }
242 break;
243 case 0x18: /* Modem status (R), transmit data (W) */
244 if (writeflag == MEM_WRITE) {
245 int line_no = (d->regs.dc_csr >>
246 RBUF_LINE_NUM_SHIFT) & 0x3;
247 idata &= 0xff;
248
249 lk201_tx_data(&d->lk201, line_no, idata);
250
251 d->regs.dc_csr &= ~CSR_TRDY;
252 cpu_interrupt_ack(cpu, d->irqnr);
253
254 d->just_transmitted_something = 4;
255 } else {
256 /* read: */
257 d->regs.dc_msr_tdr |= MSR_DSR2 | MSR_CD2 |
258 MSR_DSR3 | MSR_CD3;
259 debug("[ dc7085 read from MSR: (msr_tdr = 0x%04x) ]\n",
260 d->regs.dc_msr_tdr);
261 odata = d->regs.dc_msr_tdr;
262 }
263 break;
264 default:
265 if (writeflag==MEM_READ) {
266 debug("[ dc7085 read from 0x%08lx ]\n",
267 (long)relative_addr);
268 } else {
269 debug("[ dc7085 write to 0x%08lx:",
270 (long)relative_addr);
271 for (i=0; i<len; i++)
272 debug(" %02x", data[i]);
273 debug(" ]\n");
274 }
275 }
276
277 if (writeflag == MEM_READ)
278 memory_writemax64(cpu, data, len, odata);
279
280 do_return:
281 dev_dc7085_tick(cpu, extra);
282
283 return 1;
284 }
285
286
287 /*
288 * dev_dc7085_init():
289 *
290 * Initialize a dc7085 serial controller device. use_fb should be non-zero
291 * if a framebuffer device is used. Channel 0 will then be treated as a
292 * DECstation keyboard, instead of a plain serial console.
293 */
294 int dev_dc7085_init(struct machine *machine, struct memory *mem,
295 uint64_t baseaddr, int irq_nr, int use_fb)
296 {
297 struct dc_data *d;
298
299 d = malloc(sizeof(struct dc_data));
300 if (d == NULL) {
301 fprintf(stderr, "out of memory\n");
302 exit(1);
303 }
304 memset(d, 0, sizeof(struct dc_data));
305 d->irqnr = irq_nr;
306 d->use_fb = use_fb;
307
308 d->regs.dc_csr = CSR_TRDY | CSR_MSE;
309 d->regs.dc_tcr = 0x00;
310
311 d->console_handle = console_start_slave(machine, "DC7085", 1);
312
313 lk201_init(&d->lk201, use_fb, add_to_rx_queue, d->console_handle, d);
314
315 memory_device_register(mem, "dc7085", baseaddr, DEV_DC7085_LENGTH,
316 dev_dc7085_access, d, DM_DEFAULT, NULL);
317 machine_add_tickfunction(machine, dev_dc7085_tick, d,
318 DC_TICK_SHIFT, 0.0);
319
320 return d->console_handle;
321 }
322

  ViewVC Help
Powered by ViewVC 1.1.26