14
var UART_IER_MSI = 0x08;
15
var UART_IER_THRI = 0x02;
16
var UART_IER_RDI = 0x01;
18
var UART_IIR_MSI = 0x00;
19
var UART_IIR_NO_INT = 0x01;
20
var UART_IIR_THRI = 0x02;
21
var UART_IIR_RDI = 0x04;
22
var UART_IIR_RLSI = 0x06;
23
var UART_IIR_CTI = 0x0c;
25
var UART_LSR_DATA_READY = 0x1;
26
var UART_LSR_TX_EMPTY = 0x20;
27
var UART_LSR_TRANSMITTER_EMPTY = 0x40;
36
function UART(cpu, port, bus)
44
this.ints = 1 << UART_IIR_THRI;
48
this.line_control = 0;
51
this.lsr = UART_LSR_TRANSMITTER_EMPTY | UART_LSR_TX_EMPTY;
53
this.fifo_control = 0;
59
this.iir = UART_IIR_NO_INT;
61
this.modem_control = 0;
62
this.modem_status = 0;
64
this.scratch_register = 0;
68
this.input = new ByteQueue(4096);
70
this.current_line = [];
91
dbg_log("Invalid serial port: " + h(port), LOG_SERIAL);
96
this.bus.register("serial" + this.com + "-input", function(data)
98
this.data_received(data);
103
io.register_write(port, this, function(out_byte)
105
this.write_data(out_byte);
106
}, function(out_word)
108
this.write_data(out_word & 0xFF);
109
this.write_data(out_word >> 8);
112
io.register_write(port | 1, this, function(out_byte)
114
if(this.line_control & DLAB)
116
this.baud_rate = this.baud_rate & 0xFF | out_byte << 8;
117
dbg_log("baud rate: " + h(this.baud_rate), LOG_SERIAL);
121
this.ier = out_byte & 0xF;
122
dbg_log("interrupt enable: " + h(out_byte), LOG_SERIAL);
123
this.CheckInterrupt();
127
io.register_read(port, this, function()
129
if(this.line_control & DLAB)
131
return this.baud_rate & 0xFF;
135
var data = this.input.shift();
139
dbg_log("Read input empty", LOG_SERIAL);
143
dbg_log("Read input: " + h(data), LOG_SERIAL);
146
if(this.input.length === 0)
148
this.lsr &= ~UART_LSR_DATA_READY;
149
this.ClearInterrupt(UART_IIR_CTI);
156
io.register_read(port | 1, this, function()
158
if(this.line_control & DLAB)
160
return this.baud_rate >> 8;
164
return this.ier & 0xF;
168
io.register_read(port | 2, this, function()
170
var ret = this.iir & 0xF | 0xC0;
171
dbg_log("read interrupt identification: " + h(this.iir), LOG_SERIAL);
173
if (this.iir == UART_IIR_THRI) {
174
this.ClearInterrupt(UART_IIR_THRI);
179
io.register_write(port | 2, this, function(out_byte)
181
dbg_log("fifo control: " + h(out_byte), LOG_SERIAL);
182
this.fifo_control = out_byte;
185
io.register_read(port | 3, this, function()
187
dbg_log("read line control: " + h(this.line_control), LOG_SERIAL);
188
return this.line_control;
190
io.register_write(port | 3, this, function(out_byte)
192
dbg_log("line control: " + h(out_byte), LOG_SERIAL);
193
this.line_control = out_byte;
197
io.register_read(port | 4, this, function()
199
return this.modem_control;
201
io.register_write(port | 4, this, function(out_byte)
203
dbg_log("modem control: " + h(out_byte), LOG_SERIAL);
204
this.modem_control = out_byte;
207
io.register_read(port | 5, this, function()
209
dbg_log("read line status: " + h(this.lsr), LOG_SERIAL);
212
io.register_write(port | 5, this, function(out_byte)
214
dbg_log("Factory test write", LOG_SERIAL);
217
io.register_read(port | 6, this, function()
219
dbg_log("read modem status: " + h(this.modem_status), LOG_SERIAL);
220
return this.modem_status;
222
io.register_write(port | 6, this, function(out_byte)
224
dbg_log("Unkown register write (base+6)", LOG_SERIAL);
227
io.register_read(port | 7, this, function()
229
return this.scratch_register;
231
io.register_write(port | 7, this, function(out_byte)
233
this.scratch_register = out_byte;
237
UART.prototype.get_state = function()
241
state[0] = this.ints;
242
state[1] = this.baud_rate;
243
state[2] = this.line_control;
245
state[4] = this.fifo_control;
248
state[7] = this.modem_control;
249
state[8] = this.modem_status;
250
state[9] = this.scratch_register;
251
state[10] = this.irq;
256
UART.prototype.set_state = function(state)
258
this.ints = state[0];
259
this.baud_rate = state[1];
260
this.line_control = state[2];
262
this.fifo_control = state[4];
265
this.modem_control = state[7];
266
this.modem_status = state[8];
267
this.scratch_register = state[9];
268
this.irq = state[10];
271
UART.prototype.CheckInterrupt = function() {
272
if ((this.ints & (1 << UART_IIR_CTI)) && (this.ier & UART_IER_RDI)) {
273
this.iir = UART_IIR_CTI;
274
this.cpu.device_raise_irq(this.irq);
276
if ((this.ints & (1 << UART_IIR_THRI)) && (this.ier & UART_IER_THRI)) {
277
this.iir = UART_IIR_THRI;
278
this.cpu.device_raise_irq(this.irq);
280
if ((this.ints & (1 << UART_IIR_MSI)) && (this.ier & UART_IER_MSI)) {
281
this.iir = UART_IIR_MSI;
282
this.cpu.device_raise_irq(this.irq);
284
this.iir = UART_IIR_NO_INT;
285
this.cpu.device_lower_irq(this.irq);
289
UART.prototype.ThrowInterrupt = function(line) {
290
this.ints |= (1 << line);
291
this.CheckInterrupt();
294
UART.prototype.ClearInterrupt = function(line) {
295
this.ints &= ~(1 << line);
296
this.CheckInterrupt();
302
UART.prototype.data_received = function(data)
304
dbg_log("input: " + h(data), LOG_SERIAL);
305
this.input.push(data);
307
this.lsr |= UART_LSR_DATA_READY;
308
this.ThrowInterrupt(UART_IIR_CTI);
311
UART.prototype.write_data = function(out_byte)
313
if(this.line_control & DLAB)
315
this.baud_rate = this.baud_rate & ~0xFF | out_byte;
319
dbg_log("data: " + h(out_byte), LOG_SERIAL);
321
this.ThrowInterrupt(UART_IIR_THRI);
323
if(out_byte === 0xFF)
328
var char = String.fromCharCode(out_byte);
330
this.bus.send("serial" + this.com + "-output-char", char);
332
this.current_line.push(out_byte);
336
const line = String.fromCharCode.apply("", this.current_line).trimRight().replace(/[\x00-\x08\x0b-\x1f\x7f\x80-\xff]/g, "");
337
dbg_log("SERIAL: " + line);
338
this.bus.send("serial" + this.com + "-output-line", String.fromCharCode.apply("", this.current_line));
339
this.current_line = [];