25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: dev_ns16550.c,v 1.51 2006/02/18 13:42:39 debug Exp $ |
* $Id: dev_ns16550.c,v 1.55 2006/10/27 13:12:21 debug Exp $ |
29 |
* |
* |
30 |
* NS16550 serial controller. |
* NS16550 serial controller. |
31 |
* |
* |
72 |
}; |
}; |
73 |
|
|
74 |
|
|
75 |
/* |
DEVICE_TICK(ns16550) |
|
* dev_ns16550_tick(): |
|
|
* |
|
|
* This function is called at regular intervals. An interrupt is caused to the |
|
|
* CPU if there is a character available for reading, or if the transmitter |
|
|
* slot is empty (i.e. the ns16550 is ready to transmit). |
|
|
*/ |
|
|
void dev_ns16550_tick(struct cpu *cpu, void *extra) |
|
76 |
{ |
{ |
77 |
|
/* |
78 |
|
* This function is called at regular intervals. An interrupt is |
79 |
|
* asserted if there is a character available for reading, or if the |
80 |
|
* transmitter slot is empty (i.e. the ns16550 is ready to transmit). |
81 |
|
*/ |
82 |
struct ns_data *d = extra; |
struct ns_data *d = extra; |
83 |
|
|
84 |
d->reg[com_iir] &= ~IIR_RXRDY; |
d->reg[com_iir] &= ~IIR_RXRDY; |
89 |
* If interrupts are enabled, and interrupts are pending, then |
* If interrupts are enabled, and interrupts are pending, then |
90 |
* cause a CPU interrupt. |
* cause a CPU interrupt. |
91 |
*/ |
*/ |
92 |
|
|
93 |
if (((d->reg[com_ier] & IER_ETXRDY) && (d->reg[com_iir] & IIR_TXRDY)) || |
if (((d->reg[com_ier] & IER_ETXRDY) && (d->reg[com_iir] & IIR_TXRDY)) || |
94 |
((d->reg[com_ier] & IER_ERXRDY) && (d->reg[com_iir] & IIR_RXRDY))) { |
((d->reg[com_ier] & IER_ERXRDY) && (d->reg[com_iir] & IIR_RXRDY))) { |
95 |
d->reg[com_iir] &= ~IIR_NOPEND; |
d->reg[com_iir] &= ~IIR_NOPEND; |
213 |
d->fcr = idata; |
d->fcr = idata; |
214 |
} else { |
} else { |
215 |
odata = d->reg[com_iir]; |
odata = d->reg[com_iir]; |
216 |
|
if (d->reg[com_iir] & IIR_TXRDY) |
217 |
|
d->reg[com_iir] &= ~IIR_TXRDY; |
218 |
debug("[ ns16550 (%s): read from iir: 0x%02x ]\n", |
debug("[ ns16550 (%s): read from iir: 0x%02x ]\n", |
219 |
d->name, (int)odata); |
d->name, (int)odata); |
220 |
dev_ns16550_tick(cpu, d); |
dev_ns16550_tick(cpu, d); |
288 |
d->reg[com_mcr] = idata; |
d->reg[com_mcr] = idata; |
289 |
debug("[ ns16550 (%s): write to mcr: 0x%02x ]\n", |
debug("[ ns16550 (%s): write to mcr: 0x%02x ]\n", |
290 |
d->name, (int)idata); |
d->name, (int)idata); |
291 |
|
if (!(d->reg[com_iir] & IIR_TXRDY) |
292 |
|
&& (idata & MCR_IENABLE)) |
293 |
|
d->reg[com_iir] |= IIR_TXRDY; |
294 |
|
dev_ns16550_tick(cpu, d); |
295 |
} else { |
} else { |
296 |
odata = d->reg[com_mcr]; |
odata = d->reg[com_mcr]; |
297 |
debug("[ ns16550 (%s): read from mcr: 0x%02x ]\n", |
debug("[ ns16550 (%s): read from mcr: 0x%02x ]\n", |
363 |
DEV_NS16550_LENGTH * d->addrmult, dev_ns16550_access, d, |
DEV_NS16550_LENGTH * d->addrmult, dev_ns16550_access, d, |
364 |
DM_DEFAULT, NULL); |
DM_DEFAULT, NULL); |
365 |
machine_add_tickfunction(devinit->machine, |
machine_add_tickfunction(devinit->machine, |
366 |
dev_ns16550_tick, d, TICK_SHIFT); |
dev_ns16550_tick, d, TICK_SHIFT, 0.0); |
367 |
|
|
368 |
/* |
/* |
369 |
* NOTE: Ugly cast into a pointer, because this is a convenient way |
* NOTE: Ugly cast into a pointer, because this is a convenient way |