dev_dc7085.cc Source File

Back to the index.

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

Generated on Fri Dec 7 2018 19:52:23 for GXemul by doxygen 1.8.13