jslinux/Serial.js

144 lines
3.5 KiB
JavaScript

/*
Fabrix - An annotated version of the original JSLinux which is Copyright (c) 2011 Fabrice Bellard
Serial Controller Emulator
*/
function Serial(Ng, mem8_loc, kh, lh) {
this.divider = 0;
this.rbr = 0;
this.ier = 0;
this.iir = 0x01;
this.lcr = 0;
this.mcr;
this.lsr = 0x40 | 0x20;
this.msr = 0;
this.scr = 0;
this.set_irq_func = kh;
this.write_func = lh;
this.receive_fifo = "";
Ng.register_ioport_write(0x3f8, 8, 1, this.ioport_write.bind(this));
Ng.register_ioport_read(0x3f8, 8, 1, this.ioport_read.bind(this));
}
Serial.prototype.update_irq = function() {
if ((this.lsr & 0x01) && (this.ier & 0x01)) {
this.iir = 0x04;
} else if ((this.lsr & 0x20) && (this.ier & 0x02)) {
this.iir = 0x02;
} else {
this.iir = 0x01;
}
if (this.iir != 0x01) {
this.set_irq_func(1);
} else {
this.set_irq_func(0);
}
};
Serial.prototype.ioport_write = function(mem8_loc, x) {
mem8_loc &= 7;
switch (mem8_loc) {
default:
case 0:
if (this.lcr & 0x80) {
this.divider = (this.divider & 0xff00) | x;
} else {
this.lsr &= ~0x20;
this.update_irq();
this.write_func(String.fromCharCode(x));
this.lsr |= 0x20;
this.lsr |= 0x40;
this.update_irq();
}
break;
case 1:
if (this.lcr & 0x80) {
this.divider = (this.divider & 0x00ff) | (x << 8);
} else {
this.ier = x;
this.update_irq();
}
break;
case 2:
break;
case 3:
this.lcr = x;
break;
case 4:
this.mcr = x;
break;
case 5:
break;
case 6:
this.msr = x;
break;
case 7:
this.scr = x;
break;
}
};
Serial.prototype.ioport_read = function(mem8_loc) {
var Pg;
mem8_loc &= 7;
switch (mem8_loc) {
default:
case 0:
if (this.lcr & 0x80) {
Pg = this.divider & 0xff;
} else {
Pg = this.rbr;
this.lsr &= ~(0x01 | 0x10);
this.update_irq();
this.send_char_from_fifo();
}
break;
case 1:
if (this.lcr & 0x80) {
Pg = (this.divider >> 8) & 0xff;
} else {
Pg = this.ier;
}
break;
case 2:
Pg = this.iir;
break;
case 3:
Pg = this.lcr;
break;
case 4:
Pg = this.mcr;
break;
case 5:
Pg = this.lsr;
break;
case 6:
Pg = this.msr;
break;
case 7:
Pg = this.scr;
break;
}
return Pg;
};
Serial.prototype.send_break = function() {
this.rbr = 0;
this.lsr |= 0x10 | 0x01;
this.update_irq();
};
Serial.prototype.send_char = function(mh) {
this.rbr = mh;
this.lsr |= 0x01;
this.update_irq();
};
Serial.prototype.send_char_from_fifo = function() {
var nh;
nh = this.receive_fifo;
if (nh != "" && !(this.lsr & 0x01)) {
this.send_char(nh.charCodeAt(0));
this.receive_fifo = nh.substr(1, nh.length - 1);
}
};
Serial.prototype.send_chars = function(na) {
this.receive_fifo += na;
this.send_char_from_fifo();
};