53 |
vm_instance_t *vm; |
vm_instance_t *vm; |
54 |
u_int irq; |
u_int irq; |
55 |
|
|
56 |
|
/* Register offset divisor */ |
57 |
|
u_int reg_div; |
58 |
|
|
59 |
/* Periodic task to trigger DUART IRQ */ |
/* Periodic task to trigger DUART IRQ */ |
60 |
ptask_id_t tid; |
ptask_id_t tid; |
61 |
|
|
128 |
} |
} |
129 |
#endif |
#endif |
130 |
|
|
131 |
if (offset >= 0x40) |
offset >>= d->reg_div; |
132 |
|
|
133 |
|
if (offset >= 0x08) |
134 |
channel = 1; |
channel = 1; |
135 |
|
|
136 |
switch(offset) { |
switch(offset) { |
137 |
/* Receiver Buffer Reg. (RBR) / Transmitting Holding Reg. (THR) */ |
/* Receiver Buffer Reg. (RBR) / Transmitting Holding Reg. (THR) */ |
138 |
case 0x00: |
case 0x00: |
139 |
case 0x40: |
case 0x08: |
140 |
if (op_type == MTS_WRITE) { |
if (op_type == MTS_WRITE) { |
141 |
vtty_put_char(d->channel[channel].vtty,(char)*data); |
vtty_put_char(d->channel[channel].vtty,(char)*data); |
142 |
|
|
150 |
break; |
break; |
151 |
|
|
152 |
/* Interrupt Enable Register (IER) */ |
/* Interrupt Enable Register (IER) */ |
153 |
case 0x08: |
case 0x01: |
154 |
case 0x48: |
case 0x09: |
155 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
156 |
*data = d->channel[channel].ier; |
*data = d->channel[channel].ier; |
157 |
} else { |
} else { |
165 |
break; |
break; |
166 |
|
|
167 |
/* Interrupt Ident Register (IIR) */ |
/* Interrupt Ident Register (IIR) */ |
168 |
case 0x10: |
case 0x02: |
169 |
vm_clear_irq(d->vm,d->irq); |
vm_clear_irq(d->vm,d->irq); |
170 |
case 0x50: |
case 0x0A: |
171 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
172 |
odata = IIR_NPENDING; |
odata = IIR_NPENDING; |
173 |
|
|
185 |
break; |
break; |
186 |
|
|
187 |
/* Line Status Register (LSR) */ |
/* Line Status Register (LSR) */ |
188 |
case 0x28: |
case 0x05: |
189 |
case 0x68: |
case 0x0D: |
190 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
191 |
odata = 0; |
odata = 0; |
192 |
|
|
233 |
|
|
234 |
/* Create a NS16552 device */ |
/* Create a NS16552 device */ |
235 |
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, |
236 |
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) |
237 |
{ |
{ |
238 |
struct ns16552_data *d; |
struct ns16552_data *d; |
239 |
|
|
246 |
memset(d,0,sizeof(*d)); |
memset(d,0,sizeof(*d)); |
247 |
d->vm = vm; |
d->vm = vm; |
248 |
d->irq = irq; |
d->irq = irq; |
249 |
d->channel[0].vtty = vtty_portA; |
d->reg_div = reg_div; |
250 |
d->channel[1].vtty = vtty_portB; |
d->channel[0].vtty = vtty_A; |
251 |
|
d->channel[1].vtty = vtty_B; |
252 |
|
|
253 |
vm_object_init(&d->vm_obj); |
vm_object_init(&d->vm_obj); |
254 |
d->vm_obj.name = "ns16552"; |
d->vm_obj.name = "ns16552"; |
263 |
d->dev.handler = dev_ns16552_access; |
d->dev.handler = dev_ns16552_access; |
264 |
d->dev.priv_data = d; |
d->dev.priv_data = d; |
265 |
|
|
266 |
vtty_portA->priv_data = d; |
vtty_A->priv_data = d; |
267 |
vtty_portB->priv_data = d; |
vtty_B->priv_data = d; |
268 |
vtty_portA->read_notifier = tty_con_input; |
vtty_A->read_notifier = tty_con_input; |
269 |
vtty_portB->read_notifier = tty_aux_input; |
vtty_B->read_notifier = tty_aux_input; |
270 |
|
|
271 |
/* Trigger periodically a dummy IRQ to flush buffers */ |
/* Trigger periodically a dummy IRQ to flush buffers */ |
272 |
d->tid = ptask_add((ptask_callback)tty_trigger_dummy_irq,d,NULL); |
d->tid = ptask_add((ptask_callback)tty_trigger_dummy_irq,d,NULL); |