16 |
#include <pthread.h> |
#include <pthread.h> |
17 |
|
|
18 |
#include "ptask.h" |
#include "ptask.h" |
19 |
#include "mips64.h" |
#include "cpu.h" |
20 |
|
#include "vm.h" |
21 |
#include "dynamips.h" |
#include "dynamips.h" |
22 |
#include "memory.h" |
#include "memory.h" |
23 |
#include "device.h" |
#include "device.h" |
54 |
vm_instance_t *vm; |
vm_instance_t *vm; |
55 |
u_int irq; |
u_int irq; |
56 |
|
|
57 |
|
/* Register offset divisor */ |
58 |
|
u_int reg_div; |
59 |
|
|
60 |
/* Periodic task to trigger DUART IRQ */ |
/* Periodic task to trigger DUART IRQ */ |
61 |
ptask_id_t tid; |
ptask_id_t tid; |
62 |
|
|
109 |
/* |
/* |
110 |
* dev_ns16552_access() |
* dev_ns16552_access() |
111 |
*/ |
*/ |
112 |
void *dev_ns16552_access(cpu_mips_t *cpu,struct vdevice *dev,m_uint32_t offset, |
void *dev_ns16552_access(cpu_gen_t *cpu,struct vdevice *dev,m_uint32_t offset, |
113 |
u_int op_size,u_int op_type,m_uint64_t *data) |
u_int op_size,u_int op_type,m_uint64_t *data) |
114 |
{ |
{ |
115 |
struct ns16552_data *d = dev->priv_data; |
struct ns16552_data *d = dev->priv_data; |
121 |
|
|
122 |
#if DEBUG_ACCESS |
#if DEBUG_ACCESS |
123 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
124 |
cpu_log(cpu,"NS16552","read from 0x%x, pc=0x%llx, ra=0x%llx\n", |
cpu_log(cpu,"NS16552","read from 0x%x, pc=0x%llx\n", |
125 |
offset,cpu->pc,cpu->gpr[MIPS_GPR_RA]); |
offset,cpu_get_pc(cpu)); |
126 |
} else { |
} else { |
127 |
cpu_log(cpu,"NS16552","write to 0x%x, value=0x%llx, pc=0x%llx\n", |
cpu_log(cpu,"NS16552","write to 0x%x, value=0x%llx, pc=0x%llx\n", |
128 |
offset,*data,cpu->pc); |
offset,*data,cpu_get_pc(cpu)); |
129 |
} |
} |
130 |
#endif |
#endif |
131 |
|
|
132 |
if (offset >= 0x40) |
offset >>= d->reg_div; |
133 |
|
|
134 |
|
if (offset >= 0x08) |
135 |
channel = 1; |
channel = 1; |
136 |
|
|
137 |
switch(offset) { |
switch(offset) { |
138 |
/* Receiver Buffer Reg. (RBR) / Transmitting Holding Reg. (THR) */ |
/* Receiver Buffer Reg. (RBR) / Transmitting Holding Reg. (THR) */ |
139 |
case 0x00: |
case 0x00: |
140 |
case 0x40: |
case 0x08: |
141 |
if (op_type == MTS_WRITE) { |
if (op_type == MTS_WRITE) { |
142 |
vtty_put_char(d->channel[channel].vtty,(char)*data); |
vtty_put_char(d->channel[channel].vtty,(char)*data); |
143 |
|
|
151 |
break; |
break; |
152 |
|
|
153 |
/* Interrupt Enable Register (IER) */ |
/* Interrupt Enable Register (IER) */ |
154 |
case 0x08: |
case 0x01: |
155 |
case 0x48: |
case 0x09: |
156 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
157 |
*data = d->channel[channel].ier; |
*data = d->channel[channel].ier; |
158 |
} else { |
} else { |
166 |
break; |
break; |
167 |
|
|
168 |
/* Interrupt Ident Register (IIR) */ |
/* Interrupt Ident Register (IIR) */ |
169 |
case 0x10: |
case 0x02: |
170 |
vm_clear_irq(d->vm,d->irq); |
vm_clear_irq(d->vm,d->irq); |
171 |
case 0x50: |
case 0x0A: |
172 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
173 |
odata = IIR_NPENDING; |
odata = IIR_NPENDING; |
174 |
|
|
186 |
break; |
break; |
187 |
|
|
188 |
/* Line Status Register (LSR) */ |
/* Line Status Register (LSR) */ |
189 |
case 0x28: |
case 0x05: |
190 |
case 0x68: |
case 0x0D: |
191 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
192 |
odata = 0; |
odata = 0; |
193 |
|
|
203 |
default: |
default: |
204 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
205 |
cpu_log(cpu,"NS16552","read from addr 0x%x, pc=0x%llx (size=%u)\n", |
cpu_log(cpu,"NS16552","read from addr 0x%x, pc=0x%llx (size=%u)\n", |
206 |
offset,cpu->pc,op_size); |
offset,cpu_get_pc(cpu),op_size); |
207 |
} else { |
} else { |
208 |
cpu_log(cpu,"NS16552","write to addr 0x%x, value=0x%llx, " |
cpu_log(cpu, |
209 |
"pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size); |
"NS16552","write to addr 0x%x, value=0x%llx, " |
210 |
|
"pc=0x%llx (size=%u)\n", |
211 |
|
offset,*data,cpu_get_pc(cpu),op_size); |
212 |
} |
} |
213 |
#endif |
#endif |
214 |
} |
} |
236 |
|
|
237 |
/* Create a NS16552 device */ |
/* Create a NS16552 device */ |
238 |
int dev_ns16552_init(vm_instance_t *vm,m_uint64_t paddr,m_uint32_t len, |
int dev_ns16552_init(vm_instance_t *vm,m_uint64_t paddr,m_uint32_t len, |
239 |
u_int irq,vtty_t *vtty_portA,vtty_t *vtty_portB) |
u_int reg_div,u_int irq,vtty_t *vtty_A,vtty_t *vtty_B) |
240 |
{ |
{ |
241 |
struct ns16552_data *d; |
struct ns16552_data *d; |
242 |
|
|
249 |
memset(d,0,sizeof(*d)); |
memset(d,0,sizeof(*d)); |
250 |
d->vm = vm; |
d->vm = vm; |
251 |
d->irq = irq; |
d->irq = irq; |
252 |
d->channel[0].vtty = vtty_portA; |
d->reg_div = reg_div; |
253 |
d->channel[1].vtty = vtty_portB; |
d->channel[0].vtty = vtty_A; |
254 |
|
d->channel[1].vtty = vtty_B; |
255 |
|
|
256 |
vm_object_init(&d->vm_obj); |
vm_object_init(&d->vm_obj); |
257 |
d->vm_obj.name = "ns16552"; |
d->vm_obj.name = "ns16552"; |
266 |
d->dev.handler = dev_ns16552_access; |
d->dev.handler = dev_ns16552_access; |
267 |
d->dev.priv_data = d; |
d->dev.priv_data = d; |
268 |
|
|
269 |
vtty_portA->priv_data = d; |
vtty_A->priv_data = d; |
270 |
vtty_portB->priv_data = d; |
vtty_B->priv_data = d; |
271 |
vtty_portA->read_notifier = tty_con_input; |
vtty_A->read_notifier = tty_con_input; |
272 |
vtty_portB->read_notifier = tty_aux_input; |
vtty_B->read_notifier = tty_aux_input; |
273 |
|
|
274 |
/* Trigger periodically a dummy IRQ to flush buffers */ |
/* Trigger periodically a dummy IRQ to flush buffers */ |
275 |
d->tid = ptask_add((ptask_callback)tty_trigger_dummy_irq,d,NULL); |
d->tid = ptask_add((ptask_callback)tty_trigger_dummy_irq,d,NULL); |