dev_z8530.cc Source File

Back to the index.

dev_z8530.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004-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: Zilog Z8530 "zs" serial controller
29  *
30  * Features:
31  * o) Two channels, 0 = "channel B", 1 = "channel A".
32  * Normally, only channel B is in use.
33  *
34  * This is a work in progress... TODOs include:
35  * o) Implement more of the register set.
36  * o) Verify that it works with other guest OSes than NetBSD and OpenBSD.
37  * o) Implement 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 "interrupt.h"
48 #include "machine.h"
49 #include "memory.h"
50 #include "misc.h"
51 
52 #include "thirdparty/z8530reg.h"
53 
54 
55 /* #define debug fatal */
56 
57 #define ZS_TICK_SHIFT 14
58 #define ZS_N_REGS 16
59 #define ZS_N_CHANNELS 2
60 #define DEV_Z8530_LENGTH 4
61 
62 struct z8530_data {
63  struct interrupt irq;
65  int addr_mult;
66 
71 };
72 
73 
74 /*
75  * check_incoming():
76  *
77  * Sets the RX interrupt flag for ports B and A, if something there is input
78  * available on port 0 or 1, respectively.
79  */
80 static void check_incoming(struct cpu *cpu, struct z8530_data *d)
81 {
82  if (console_charavail(d->console_handle[0])) {
83  d->rr[1][3] |= ZSRR3_IP_B_RX;
84  d->rr[0][0] |= ZSRR0_RX_READY;
85  }
86  if (console_charavail(d->console_handle[1])) {
87  d->rr[1][3] |= ZSRR3_IP_A_RX;
88  d->rr[1][0] |= ZSRR0_RX_READY;
89  }
90 }
91 
92 
94 {
95  /* Generate transmit and receive interrupts at regular intervals. */
96  struct z8530_data *d = (struct z8530_data *) extra;
97  int asserted = 0;
98 
99  if (d->rr[1][3] & ZSRR3_IP_B_TX && d->wr[0][1] & ZSWR1_TIE)
100  asserted = 1;
101  if (d->rr[1][3] & ZSRR3_IP_A_TX && d->wr[1][1] & ZSWR1_TIE)
102  asserted = 1;
103 
104  d->rr[1][3] &= ~(ZSRR3_IP_B_RX | ZSRR3_IP_A_RX);
105  if (!asserted)
106  check_incoming(cpu, d);
107 
108  if (d->rr[1][3] & ZSRR3_IP_B_RX && (d->wr[0][1]&0x18) != ZSWR1_RIE_NONE)
109  asserted = 1;
110  if (d->rr[1][3] & ZSRR3_IP_A_RX && (d->wr[1][1]&0x18) != ZSWR1_RIE_NONE)
111  asserted = 1;
112 
113  if (!(d->wr[1][9] & ZSWR9_MASTER_IE))
114  asserted = 0;
115 
116  if (asserted)
117  INTERRUPT_ASSERT(d->irq);
118 
119  if (d->irq_asserted && !asserted)
121 
122  d->irq_asserted = asserted;
123 }
124 
125 
127 {
128  struct z8530_data *d = (struct z8530_data *) extra;
129  uint64_t idata = 0, odata = 0;
130  int port_nr;
131 
132  if (writeflag == MEM_WRITE)
133  idata = memory_readmax64(cpu, data, len);
134 
135  /* Both ports are always ready to transmit: */
136  d->rr[0][0] |= ZSRR0_TX_READY | ZSRR0_DCD | ZSRR0_CTS;
137  d->rr[1][0] |= ZSRR0_TX_READY | ZSRR0_DCD | ZSRR0_CTS;
138 
139  relative_addr /= d->addr_mult;
140 
141  port_nr = (relative_addr / 2) % ZS_N_CHANNELS;
142  relative_addr &= 1;
143 
144  if (relative_addr == 0) {
145  /* Register access: */
146  if (writeflag == MEM_READ) {
147  odata = d->rr[port_nr][d->reg_select[port_nr]];
148  debug("[ z8530: read from port %i reg %2i: "
149  "0x%02x ]\n", port_nr, d->reg_select[
150  port_nr], (int)odata);
151  d->reg_select[port_nr] = 0;
152  } else {
153  if (d->reg_select[port_nr] == 0) {
154  if (idata < 16)
155  d->reg_select[port_nr] = idata & 15;
156  else
157  d->reg_select[port_nr] = idata & 7;
158  switch (idata & 0xf8) {
159  case ZSWR0_CLR_INTR: /* Interrupt ack: */
160  d->rr[1][3] = 0;
161  break;
162  }
163  } else {
164  d->wr[port_nr][d->reg_select[port_nr]] = idata;
165  switch (d->reg_select[port_nr]) {
166  default:debug("[ z8530: write to port %i reg "
167  "%2i: 0x%02x ]\n", port_nr, d->
168  reg_select[port_nr], (int)idata);
169  }
170  d->reg_select[port_nr] = 0;
171  }
172  }
173  } else {
174  /* Data access: */
175  if (writeflag == MEM_READ) {
176  int x = console_readchar(d->console_handle[port_nr]);
177  d->rr[port_nr][0] &= ~ZSRR0_RX_READY;
178  odata = x < 0? 0 : x;
179  } else {
180  idata &= 255;
181  if (idata != 0)
182  console_putchar(d->console_handle[port_nr],
183  idata);
184  if (1 /* d->wr[port_nr][1] & ZSWR1_TIE */) {
185  if (port_nr == 0)
186  d->rr[1][3] |= ZSRR3_IP_B_TX;
187  else
188  d->rr[1][3] |= ZSRR3_IP_A_TX;
189  }
190  }
191  }
192 
193  if (writeflag == MEM_READ)
194  memory_writemax64(cpu, data, len, odata);
195 
196  dev_z8530_tick(cpu, extra);
197 
198  return 1;
199 }
200 
201 
202 DEVINIT(z8530)
203 {
204  struct z8530_data *d;
205  char tmp[100];
206 
207  CHECK_ALLOCATION(d = (struct z8530_data *) malloc(sizeof(struct z8530_data)));
208  memset(d, 0, sizeof(struct z8530_data));
209 
211 
213 
214  snprintf(tmp, sizeof(tmp), "%s [ch-b]", devinit->name);
216  devinit->in_use);
217  snprintf(tmp, sizeof(tmp), "%s [ch-a]", devinit->name);
219 
220  if (devinit->name2 != NULL && devinit->name2[0])
221  snprintf(tmp, sizeof(tmp), "%s [%s]", devinit->name,
222  devinit->name2);
223  else
224  snprintf(tmp, sizeof(tmp), "%s", devinit->name);
225 
227  DEV_Z8530_LENGTH * d->addr_mult, dev_z8530_access, d, DM_DEFAULT,
228  NULL);
229 
230  machine_add_tickfunction(devinit->machine, dev_z8530_tick, d,
231  ZS_TICK_SHIFT);
232 
233  devinit->return_ptr = (void *)(size_t) d->console_handle[0];
234 
235  return 1;
236 }
237 
console_handle
Definition: console.cc:106
data
u_short data
Definition: siireg.h:79
console_putchar
void console_putchar(int handle, int ch)
Definition: console.cc:410
INTERRUPT_CONNECT
#define INTERRUPT_CONNECT(name, istruct)
Definition: interrupt.h:77
INTERRUPT_ASSERT
#define INTERRUPT_ASSERT(istruct)
Definition: interrupt.h:74
z8530_data::rr
uint8_t rr[ZS_N_CHANNELS][ZS_N_REGS]
Definition: dev_z8530.cc:69
z8530_data::wr
uint8_t wr[ZS_N_CHANNELS][ZS_N_REGS]
Definition: dev_z8530.cc:70
z8530_data::console_handle
int console_handle[ZS_N_CHANNELS]
Definition: dev_z8530.cc:67
z8530_data::addr_mult
int addr_mult
Definition: dev_z8530.cc:65
z8530reg.h
debug
#define debug
Definition: dev_adb.cc:57
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
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
ZS_TICK_SHIFT
#define ZS_TICK_SHIFT
Definition: dev_z8530.cc:57
z8530_data::reg_select
int reg_select[ZS_N_CHANNELS]
Definition: dev_z8530.cc:68
device.h
z8530_data::irq_asserted
int irq_asserted
Definition: dev_z8530.cc:64
MEM_WRITE
#define MEM_WRITE
Definition: memory.h:117
ZS_N_REGS
#define ZS_N_REGS
Definition: dev_z8530.cc:58
ZSRR3_IP_A_RX
#define ZSRR3_IP_A_RX
Definition: z8530reg.h:420
ZSRR3_IP_B_TX
#define ZSRR3_IP_B_TX
Definition: z8530reg.h:424
machine_add_tickfunction
void machine_add_tickfunction(struct machine *machine, void(*func)(struct cpu *, void *), void *extra, int clockshift)
Definition: machine.cc:280
DEVICE_ACCESS
DEVICE_ACCESS(z8530)
Definition: dev_z8530.cc:126
ZSRR0_RX_READY
#define ZSRR0_RX_READY
Definition: z8530reg.h:395
devinit::interrupt_path
char * interrupt_path
Definition: device.h:50
ZSWR1_RIE_NONE
#define ZSWR1_RIE_NONE
Definition: z8530reg.h:158
interrupt.h
misc.h
memory_readmax64
uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
Definition: memory.cc:55
machine.h
ZSRR3_IP_A_TX
#define ZSRR3_IP_A_TX
Definition: z8530reg.h:421
console_readchar
int console_readchar(int handle)
Definition: console.cc:390
devinit::name
char * name
Definition: device.h:43
ZS_N_CHANNELS
#define ZS_N_CHANNELS
Definition: dev_z8530.cc:59
DEVICE_TICK
DEVICE_TICK(z8530)
Definition: dev_z8530.cc:93
ZSWR9_MASTER_IE
#define ZSWR9_MASTER_IE
Definition: z8530reg.h:273
z8530_data
Definition: dev_z8530.cc:62
ZSWR0_CLR_INTR
#define ZSWR0_CLR_INTR
Definition: z8530reg.h:141
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
cpu.h
ZSWR1_TIE
#define ZSWR1_TIE
Definition: z8530reg.h:164
machine::memory
struct memory * memory
Definition: machine.h:126
devinit::return_ptr
void * return_ptr
Definition: device.h:56
ZSRR0_CTS
#define ZSRR0_CTS
Definition: z8530reg.h:390
ZSRR0_DCD
#define ZSRR0_DCD
Definition: z8530reg.h:392
ZSRR3_IP_B_RX
#define ZSRR3_IP_B_RX
Definition: z8530reg.h:423
INTERRUPT_DEASSERT
#define INTERRUPT_DEASSERT(istruct)
Definition: interrupt.h:75
DEVINIT
DEVINIT(z8530)
Definition: dev_z8530.cc:202
interrupt
Definition: interrupt.h:36
devinit::name2
char * name2
Definition: device.h:44
memory_writemax64
void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len, uint64_t data)
Definition: memory.cc:89
cpu
Definition: cpu.h:326
ZSRR0_TX_READY
#define ZSRR0_TX_READY
Definition: z8530reg.h:393
DEV_Z8530_LENGTH
#define DEV_Z8530_LENGTH
Definition: dev_z8530.cc:60
devinit::in_use
int in_use
Definition: device.h:52
devinit::addr_mult
int addr_mult
Definition: device.h:53
memory.h
z8530_data::irq
struct interrupt irq
Definition: dev_z8530.cc:63
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