dev_clmpcc.cc Source File

Back to the index.

dev_clmpcc.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007-2014 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: Cirrus Logic 4-Channel Communications Controller (CD2400/CD2401)
29  *
30  * Used by OpenBSD/mvme88k.
31  *
32  * Works so far:
33  * TX/RX interrupts (happy case).
34  *
35  * TODO:
36  * Multiple channels
37  * DMA?
38  */
39 
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 
44 #include "console.h"
45 #include "cpu.h"
46 #include "device.h"
47 #include "emul.h"
48 #include "interrupt.h"
49 #include "machine.h"
50 #include "memory.h"
51 #include "misc.h"
52 
54 #include "thirdparty/clmpccreg.h"
55 
56 
57 #define debug fatal
58 
59 #define CLMPCC_LEN 0x200
60 #define DEV_CLMPCC_TICK_SHIFT 16
61 
62 struct clmpcc_data {
63  unsigned char reg[CLMPCC_LEN];
64 
66 
67  /* Interrupt pins on the PCC2 controller: */
68  struct interrupt irq_scc_rxe;
69  struct interrupt irq_scc_m;
70  struct interrupt irq_scc_tx;
71  struct interrupt irq_scc_rx;
72 };
73 
74 
75 static void reassert_interrupts(struct clmpcc_data *d)
76 {
77  int rxintr = 0;
78 
80  rxintr = 1;
81 
82  if (rxintr)
84  else
86 
87  /* TODO: Hack/experiment for now... */
88  if ((d->reg[CLMPCC_REG_IER] & 3) != 0)
90  else
92 }
93 
94 
95 DEVICE_TICK(clmpcc)
96 {
97  struct clmpcc_data *d = (struct clmpcc_data *) extra;
98  reassert_interrupts(d);
99 }
100 
101 
103 {
104  struct clmpcc_data *d = (struct clmpcc_data *) extra;
105  uint64_t idata = 0, odata = 0;
106 
107  if (writeflag == MEM_WRITE) {
108  idata = memory_readmax64(cpu, data, len);
109  d->reg[relative_addr] = idata;
110  }
111 
112  if (writeflag == MEM_READ)
113  odata = d->reg[relative_addr];
114 
115  switch (relative_addr) {
116 
117  case 0: /* Used by OpenBSD/mvme88k when probing... */
118  break;
119 
120  case CLMPCC_REG_TPR: /* Timer Period Register */
121  break;
122 
123  case CLMPCC_REG_CAR: /* Channel Access Register */
124  /* debug("[ clmpcc: selecting channel %i ]\n",
125  (int) idata); */
126  break;
127 
128  case CLMPCC_REG_CCR: /* Channel Command Register: */
129  odata = 0;
130  break;
131 
132  case CLMPCC_REG_CMR: /* Channel Mode Register */
133  case CLMPCC_REG_COR1: /* Channel Option Register #1 */
134  case CLMPCC_REG_COR2: /* Channel Option Register #2 */
135  case CLMPCC_REG_COR3: /* Channel Option Register #3 */
136  case CLMPCC_REG_COR4: /* Channel Option Register #4 */
137  case CLMPCC_REG_COR5: /* Channel Option Register #5 */
138  case CLMPCC_REG_COR6: /* Channel Option Register #6 */
139  case CLMPCC_REG_COR7: /* Channel Option Register #7 */
140  case CLMPCC_REG_SCHR1: /* Special Character Register #1 */
141  case CLMPCC_REG_SCHR2: /* Special Character Register #2 */
142  case CLMPCC_REG_SCHR3: /* Special Character Register #3 */
143  case CLMPCC_REG_SCHR4: /* Special Character Register #4 */
144  case CLMPCC_REG_SCRl: /* Special Character Range (low) */
145  case CLMPCC_REG_SCRh: /* Special Character Range (high) */
146  case CLMPCC_REG_LNXT: /* LNext Character */
147  break;
148 
149  case CLMPCC_REG_STCR: /* Special Transmit Command Register */
150  if (writeflag == MEM_WRITE) {
151  if (idata == 0x0b) {
152  if (d->reg[CLMPCC_REG_CAR] == 0)
154  d->reg[CLMPCC_REG_SCHR3]);
155  else
156  fatal("[ clmpcc: TODO: transmit "
157  "to channel, CAR!=0 ]\n");
158 
159  /* Command done: */
160  d->reg[CLMPCC_REG_STCR] = 0x00;
161  } else {
162  fatal("clmpcc: unimplemented STCR byte "
163  "0x%02x\n", (int) idata);
164  exit(1);
165  }
166  }
167  break;
168 
169  case CLMPCC_REG_RBPR: /* Receive Baud Rate Period Register */
170  case CLMPCC_REG_TBPR: /* Transmit Baud Rate Period Register */
171  case CLMPCC_REG_RCOR: /* Receive Clock Options Register */
172  case CLMPCC_REG_TCOR: /* Transmit Clock Options Register */
173  break;
174 
175  case CLMPCC_REG_MSVR_RTS:/* Modem Signal Value Register, RTS */
176  case CLMPCC_REG_MSVR_DTR:/* Modem Signal Value Register, DTR */
177  break;
178 
179  case CLMPCC_REG_RTPRl: /* Receive Timeout Period Register (low) */
180  case CLMPCC_REG_RTPRh: /* Receive Timeout Period Register (high) */
181  break;
182 
183  case CLMPCC_REG_IER: /* Interrupt Enable Register */
184  case CLMPCC_REG_LIVR: /* Local Interrupt Vector Register */
185  case CLMPCC_REG_RPILR: /* Rx Priority Interrupt Level Register */
186  case CLMPCC_REG_TPILR: /* Tx Priority Interrupt Level Register */
187  case CLMPCC_REG_MPILR: /* Modem Priority Interrupt Level Register */
188  reassert_interrupts(d);
189  break;
190 
191  case CLMPCC_REG_RISRl: /* Receive Interrupt Status Reg (low) */
192  odata = 0x00;
193  break;
194 
195  case CLMPCC_REG_TIR: /* Transmit Interrupt Register */
196  odata = 0x40; /* see openbsd's cl_txintr */
197  break;
198 
199  case CLMPCC_REG_RIR: /* Rx Interrupt Register */
200  odata = 0x00;
202  odata = 0xc0;
203  break;
204 
205  case CLMPCC_REG_LICR: /* Local Interrupt Status Register */
206  odata = 0; /* channel nr << 2 */
207  break;
208 
209  case CLMPCC_REG_RFOC: /* Rx FIFO Output Count */
210  odata = 0;
212  odata = 1;
213  break;
214 
215  case CLMPCC_REG_TFTC: /* Tx FIFO Transfer Count */
216  /*
217  * 0x1f is low enough to allow OpenBSD/mvme88k's ramdisk
218  * kernel to run (bsd.rd), but not the default kernel (bsd).
219  * Lowering it to 0x0f seems to work.
220  */
221  odata = 0x0f;
222  break;
223 
224  case CLMPCC_REG_TEOIR: /* Tx End of Interrupt Register */
225  /* TODO: Do something more realistic? */
227  break;
228 
229  case CLMPCC_REG_REOIR: /* Rx End of Interrupt Register */
230  /* TODO: Do something more realistic? */
232  break;
233 
234  case CLMPCC_REG_TDR:
235  if (writeflag == MEM_WRITE) {
236  if (d->reg[CLMPCC_REG_CAR] == 0)
237  console_putchar(d->console_handle, idata);
238  else
239  fatal("[ clmpcc: TODO: transmit "
240  "to channel, CAR!=0 ]\n");
241  } else {
242  odata = console_readchar(d->console_handle);
243  }
244  break;
245 
246  default:if (writeflag == MEM_READ)
247  fatal("[ clmpcc: unimplemented READ from offset 0x%x ]"
248  "\n", (int)relative_addr);
249  else
250  fatal("[ clmpcc: unimplemented WRITE to offset 0x%x: "
251  "0x%x ]\n", (int)relative_addr, (int)idata);
252  exit(1);
253  }
254 
255  if (writeflag == MEM_READ)
256  memory_writemax64(cpu, data, len, odata);
257 
258  return 1;
259 }
260 
261 
262 DEVINIT(clmpcc)
263 {
264  struct clmpcc_data *d;
265  char tmpstr[100];
266 
267  CHECK_ALLOCATION(d = (struct clmpcc_data *) malloc(sizeof(struct clmpcc_data)));
268  memset(d, 0, sizeof(struct clmpcc_data));
269 
270  d->console_handle =
273 
274  /*
275  * Connect to the PCC2's interrupt pins:
276  *
277  * The supplied interrupt_path is something like
278  * "machine[0].cpu[0].pcc2".
279  *
280  * We want to use "machine[0].cpu[0].pcc2.x", where x is
281  * 0xc, 0xd, 0xe, and 0xf (PCC2V_SCC_xxx).
282  */
283  snprintf(tmpstr, sizeof(tmpstr), "%s.%i",
285  INTERRUPT_CONNECT(tmpstr, d->irq_scc_rxe);
286  snprintf(tmpstr, sizeof(tmpstr), "%s.%i",
288  INTERRUPT_CONNECT(tmpstr, d->irq_scc_m);
289  snprintf(tmpstr, sizeof(tmpstr), "%s.%i",
291  INTERRUPT_CONNECT(tmpstr, d->irq_scc_tx);
292  snprintf(tmpstr, sizeof(tmpstr), "%s.%i",
294  INTERRUPT_CONNECT(tmpstr, d->irq_scc_rx);
295 
297  devinit->addr, CLMPCC_LEN, dev_clmpcc_access, (void *)d,
298  DM_DEFAULT, NULL);
299 
301  dev_clmpcc_tick, d, DEV_CLMPCC_TICK_SHIFT);
302 
303  /*
304  * NOTE: Ugly cast into a pointer, because this is a convenient way
305  * to return the console handle to code in src/machines/.
306  */
307  devinit->return_ptr = (void *)(size_t)d->console_handle;
308 
309  return 1;
310 }
311 
CLMPCC_REG_TIR
#define CLMPCC_REG_TIR
Definition: clmpccreg.h:120
data
u_short data
Definition: siireg.h:79
CLMPCC_REG_LNXT
#define CLMPCC_REG_LNXT
Definition: clmpccreg.h:81
CLMPCC_REG_TDR
#define CLMPCC_REG_TDR
Definition: clmpccreg.h:123
CLMPCC_REG_MSVR_RTS
#define CLMPCC_REG_MSVR_RTS
Definition: clmpccreg.h:99
CLMPCC_REG_CCR
#define CLMPCC_REG_CCR
Definition: clmpccreg.h:95
console_putchar
void console_putchar(int handle, int ch)
Definition: console.cc:410
INTERRUPT_CONNECT
#define INTERRUPT_CONNECT(name, istruct)
Definition: interrupt.h:77
CLMPCC_REG_SCHR4
#define CLMPCC_REG_SCHR4
Definition: clmpccreg.h:78
CLMPCC_REG_CAR
#define CLMPCC_REG_CAR
Definition: clmpccreg.h:64
INTERRUPT_ASSERT
#define INTERRUPT_ASSERT(istruct)
Definition: interrupt.h:74
CLMPCC_REG_TPILR
#define CLMPCC_REG_TPILR
Definition: clmpccreg.h:119
clmpcc_data::irq_scc_rx
struct interrupt irq_scc_rx
Definition: dev_clmpcc.cc:71
clmpccreg.h
CLMPCC_REG_RPILR
#define CLMPCC_REG_RPILR
Definition: clmpccreg.h:109
devinit::addr
uint64_t addr
Definition: device.h:46
memory_device_register
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
MEM_READ
#define MEM_READ
Definition: memory.h:116
CLMPCC_REG_COR2
#define CLMPCC_REG_COR2
Definition: clmpccreg.h:69
DM_DEFAULT
#define DM_DEFAULT
Definition: memory.h:130
devinit::machine
struct machine * machine
Definition: device.h:41
console.h
console_charavail
int console_charavail(int handle)
Definition: console.cc:347
DEVICE_ACCESS
DEVICE_ACCESS(clmpcc)
Definition: dev_clmpcc.cc:102
device.h
CLMPCC_REG_COR6
#define CLMPCC_REG_COR6
Definition: clmpccreg.h:73
MEM_WRITE
#define MEM_WRITE
Definition: memory.h:117
machine_add_tickfunction
void machine_add_tickfunction(struct machine *machine, void(*func)(struct cpu *, void *), void *extra, int clockshift)
Definition: machine.cc:280
CLMPCC_REG_LICR
#define CLMPCC_REG_LICR
Definition: clmpccreg.h:105
CLMPCC_REG_TCOR
#define CLMPCC_REG_TCOR
Definition: clmpccreg.h:92
PCC2V_SCC_RXE
#define PCC2V_SCC_RXE
Definition: mvme_pcctworeg.h:80
devinit::interrupt_path
char * interrupt_path
Definition: device.h:50
CLMPCC_REG_RTPRl
#define CLMPCC_REG_RTPRl
Definition: clmpccreg.h:164
interrupt.h
fatal
void fatal(const char *fmt,...)
Definition: main.cc:152
PCC2V_SCC_M
#define PCC2V_SCC_M
Definition: mvme_pcctworeg.h:81
CLMPCC_REG_SCHR3
#define CLMPCC_REG_SCHR3
Definition: clmpccreg.h:77
clmpcc_data::reg
unsigned char reg[CLMPCC_LEN]
Definition: dev_clmpcc.cc:63
PCC2V_SCC_RX
#define PCC2V_SCC_RX
Definition: mvme_pcctworeg.h:83
CLMPCC_REG_REOIR
#define CLMPCC_REG_REOIR
Definition: clmpccreg.h:116
misc.h
memory_readmax64
uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
Definition: memory.cc:55
machine.h
CLMPCC_REG_RTPRh
#define CLMPCC_REG_RTPRh
Definition: clmpccreg.h:165
console_readchar
int console_readchar(int handle)
Definition: console.cc:390
CLMPCC_REG_COR5
#define CLMPCC_REG_COR5
Definition: clmpccreg.h:72
CLMPCC_REG_RBPR
#define CLMPCC_REG_RBPR
Definition: clmpccreg.h:89
devinit::name
char * name
Definition: device.h:43
CLMPCC_REG_COR7
#define CLMPCC_REG_COR7
Definition: clmpccreg.h:74
emul.h
CLMPCC_REG_COR3
#define CLMPCC_REG_COR3
Definition: clmpccreg.h:70
CLMPCC_REG_LIVR
#define CLMPCC_REG_LIVR
Definition: clmpccreg.h:103
clmpcc_data::irq_scc_tx
struct interrupt irq_scc_tx
Definition: dev_clmpcc.cc:70
CLMPCC_REG_SCRl
#define CLMPCC_REG_SCRl
Definition: clmpccreg.h:79
devinit
Definition: device.h:40
console_start_slave
int console_start_slave(struct machine *machine, const char *consolename, int use_for_input)
Definition: console.cc:673
CLMPCC_REG_RIR
#define CLMPCC_REG_RIR
Definition: clmpccreg.h:110
cpu.h
DEVICE_TICK
DEVICE_TICK(clmpcc)
Definition: dev_clmpcc.cc:95
clmpcc_data::irq_scc_m
struct interrupt irq_scc_m
Definition: dev_clmpcc.cc:69
machine::memory
struct memory * memory
Definition: machine.h:126
clmpcc_data::irq_scc_rxe
struct interrupt irq_scc_rxe
Definition: dev_clmpcc.cc:68
clmpcc_data::console_handle
int console_handle
Definition: dev_clmpcc.cc:65
devinit::return_ptr
void * return_ptr
Definition: device.h:56
CLMPCC_REG_IER
#define CLMPCC_REG_IER
Definition: clmpccreg.h:104
CLMPCC_REG_MSVR_DTR
#define CLMPCC_REG_MSVR_DTR
Definition: clmpccreg.h:100
CLMPCC_LEN
#define CLMPCC_LEN
Definition: dev_clmpcc.cc:59
DEV_CLMPCC_TICK_SHIFT
#define DEV_CLMPCC_TICK_SHIFT
Definition: dev_clmpcc.cc:60
CLMPCC_REG_SCRh
#define CLMPCC_REG_SCRh
Definition: clmpccreg.h:80
CLMPCC_REG_COR1
#define CLMPCC_REG_COR1
Definition: clmpccreg.h:68
CLMPCC_REG_STCR
#define CLMPCC_REG_STCR
Definition: clmpccreg.h:96
INTERRUPT_DEASSERT
#define INTERRUPT_DEASSERT(istruct)
Definition: interrupt.h:75
clmpcc_data
Definition: dev_clmpcc.cc:62
interrupt
Definition: interrupt.h:36
devinit::name2
char * name2
Definition: device.h:44
mvme_pcctworeg.h
PCC2V_SCC_TX
#define PCC2V_SCC_TX
Definition: mvme_pcctworeg.h:82
CLMPCC_REG_CMR
#define CLMPCC_REG_CMR
Definition: clmpccreg.h:67
memory_writemax64
void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len, uint64_t data)
Definition: memory.cc:89
CLMPCC_REG_TFTC
#define CLMPCC_REG_TFTC
Definition: clmpccreg.h:122
CLMPCC_REG_TEOIR
#define CLMPCC_REG_TEOIR
Definition: clmpccreg.h:124
cpu
Definition: cpu.h:326
CLMPCC_REG_RISRl
#define CLMPCC_REG_RISRl
Definition: clmpccreg.h:112
CLMPCC_REG_SCHR1
#define CLMPCC_REG_SCHR1
Definition: clmpccreg.h:75
CLMPCC_REG_SCHR2
#define CLMPCC_REG_SCHR2
Definition: clmpccreg.h:76
DEVINIT
DEVINIT(clmpcc)
Definition: dev_clmpcc.cc:262
CLMPCC_REG_COR4
#define CLMPCC_REG_COR4
Definition: clmpccreg.h:71
devinit::in_use
int in_use
Definition: device.h:52
memory.h
CLMPCC_REG_TBPR
#define CLMPCC_REG_TBPR
Definition: clmpccreg.h:91
CLMPCC_REG_RCOR
#define CLMPCC_REG_RCOR
Definition: clmpccreg.h:90
CLMPCC_REG_RFOC
#define CLMPCC_REG_RFOC
Definition: clmpccreg.h:114
CLMPCC_REG_TPR
#define CLMPCC_REG_TPR
Definition: clmpccreg.h:162
CLMPCC_REG_MPILR
#define CLMPCC_REG_MPILR
Definition: clmpccreg.h:127
CHECK_ALLOCATION
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239

Generated on Tue Aug 25 2020 19:25:06 for GXemul by doxygen 1.8.18