change floppy.js to prototypical definition5~

This commit is contained in:
Fabian 2014-05-06 06:17:28 +02:00
parent 6ce08cfe02
commit c5fd846319

View file

@ -3,26 +3,34 @@
/** @constructor */
function FloppyController(dev, fda_image, fdb_image)
{
var
io = dev.io,
pic = dev.pic,
dma = dev.dma,
bytes_expecting = 0,
receiving_command = new Uint8Array(10),
receiving_index = 0,
next_command,
this.io = dev.io;
this.pic = dev.pic;
this.dma = dev.dma;
response_data = new Uint8Array(10),
response_index = 0,
response_length = 0,
this.bytes_expecting = 0;
this.receiving_command = new Uint8Array(10);
this.receiving_index = 0;
this.next_command = null;
floppy_size,
this.response_data = new Uint8Array(10);
this.response_index = 0;
this.response_length = 0;
/** @const */
byte_per_sector = 512;
this.floppy_size = 0;
this.buffer = fda_image;
this.fda_image = fda_image;
this.fdb_image = fdb_image;
this.status_reg0 = 0;
this.status_reg1 = 0;
this.status_reg2 = 0;
this.drive = 0;
this.last_cylinder = 0;
this.last_head = 0;
this.last_sector = 1;
if(!fda_image)
{
@ -30,7 +38,7 @@ function FloppyController(dev, fda_image, fdb_image)
return;
}
floppy_size = fda_image.byteLength;
this.floppy_size = fda_image.byteLength;
var floppy_types = {
160 : { type: 1, tracks: 40, sectors: 8 , heads: 1 },
@ -49,9 +57,9 @@ function FloppyController(dev, fda_image, fdb_image)
var number_of_cylinders,
sectors_per_track,
number_of_heads,
floppy_type = floppy_types[floppy_size >> 10];
floppy_type = floppy_types[this.floppy_size >> 10];
if(floppy_type && (floppy_size & 0x3FF) === 0)
if(floppy_type && (this.floppy_size & 0x3FF) === 0)
{
this.type = floppy_type.type;
@ -64,320 +72,316 @@ function FloppyController(dev, fda_image, fdb_image)
throw "Unknown floppy size: " + h(fda_image.byteLength);
}
var status_reg0 = 0,
status_reg1 = 0,
status_reg2 = 0,
drive = 0;
this.sectors_per_track = sectors_per_track;
this.number_of_heads = number_of_heads;
this.number_of_cylinders = number_of_cylinders;
var last_cylinder = 0,
last_head = 0,
last_sector = 1;
this.io.register_read(0x3F0, this.port3F0_read, this);
this.io.register_read(0x3F2, this.port3F2_read, this);
this.io.register_read(0x3F4, this.port3F4_read, this);
this.io.register_read(0x3F5, this.port3F5_read, this);
this.io.register_read(0x3F7, this.port3F7_read, this);
io.register_read(0x3F0, port3F0_read);
io.register_read(0x3F4, port3F4_read);
io.register_read(0x3F5, port3F5_read);
io.register_read(0x3F7, port3F7_read);
this.io.register_write(0x3F2, this.port3F2_write, this);
this.io.register_write(0x3F5, this.port3F5_write, this);
io.register_write(0x3F5, port3F5_write);
}
function port3F0_read()
FloppyController.prototype.port3F0_read = function()
{
dbg_log("3F0 read", LOG_DISK);
return 0;
};
FloppyController.prototype.port3F4_read = function()
{
dbg_log("3F4 read", LOG_DISK);
var return_byte = 0x80;
if(this.response_index < this.response_length)
{
dbg_log("3F0 read", LOG_DISK);
return 0;
};
function port3F4_read()
{
dbg_log("3F4 read", LOG_DISK);
var return_byte = 0x80;
if(response_index < response_length)
{
return_byte |= 0x40 | 0x10;
}
if((dor & 8) === 0)
{
return_byte |= 0x20;
}
return return_byte;
};
function port3F7_read()
{
dbg_log("3F7 read", LOG_DISK);
return 0x00;
return_byte |= 0x40 | 0x10;
}
function port3F5_read()
if((dor & 8) === 0)
{
if(response_index < response_length)
{
dbg_log("3F5 read: " + response_data[response_index], LOG_DISK);
return response_data[response_index++];
}
else
{
dbg_log("3F5 read, empty", LOG_DISK);
return 0xFF;
}
};
return_byte |= 0x20;
}
function port3F5_write(reg_byte)
return return_byte;
};
FloppyController.prototype.port3F7_read = function()
{
dbg_log("3F7 read", LOG_DISK);
return 0x00;
}
FloppyController.prototype.port3F5_read = function()
{
if(this.response_index < this.response_length)
{
dbg_log("3F5 write " + h(reg_byte), LOG_DISK);
dbg_log("3F5 read: " + this.response_data[this.response_index], LOG_DISK);
return this.response_data[this.response_index++];
}
else
{
dbg_log("3F5 read, empty", LOG_DISK);
return 0xFF;
}
};
if(bytes_expecting > 0)
FloppyController.prototype.port3F5_write = function(reg_byte)
{
dbg_log("3F5 write " + h(reg_byte), LOG_DISK);
if(this.bytes_expecting > 0)
{
this.receiving_command[this.receiving_index++] = reg_byte;
this.bytes_expecting--;
if(this.bytes_expecting === 0)
{
receiving_command[receiving_index++] = reg_byte;
bytes_expecting--;
if(bytes_expecting === 0)
if(DEBUG)
{
if(DEBUG)
{
var log = "3F5 command received: ";
for(var i = 0; i < receiving_index; i++)
log += h(receiving_command[i]) + " ";
dbg_log(log, LOG_DISK);
}
next_command(receiving_command);
}
}
else
{
switch(reg_byte)
{
// TODO
//case 2:
//next_command = read_complete_track;
//bytes_expecting = 8;
//break;
case 0x03:
next_command = fix_drive_data;
bytes_expecting = 2;
break;
case 0x04:
next_command = check_drive_status;
bytes_expecting = 1;
break;
case 0x05:
case 0xC5:
next_command = function(args) { do_sector(true, args); };
bytes_expecting = 8;
break;
case 0xE6:
next_command = function(args) { do_sector(false, args); };
bytes_expecting = 8;
break;
case 0x07:
next_command = calibrate;
bytes_expecting = 1;
break;
case 0x08:
check_interrupt_status();
break;
case 0x4A:
next_command = read_sector_id;
bytes_expecting = 1;
break;
case 0x0F:
bytes_expecting = 2;
next_command = seek;
break;
case 0x0E:
// dump regs
dbg_log("dump registers", LOG_DISK);
response_data[0] = 0x80;
response_index = 0;
response_length = 1;
bytes_expecting = 0;
break;
default:
if(DEBUG) throw "unimpl floppy command call " + h(reg_byte);
var log = "3F5 command received: ";
for(var i = 0; i < this.receiving_index; i++)
log += h(this.receiving_command[i]) + " ";
dbg_log(log, LOG_DISK);
}
receiving_index = 0;
}
};
// this should actually be write-only ... but people read it anyway
var dor = 0;
function port3F2_read()
{
dbg_log("read 3F2: DOR", LOG_DISK);
return dor;
}
io.register_read(0x3F2, port3F2_read);
function port3F2_write(value)
{
if((value & 4) === 4 && (dor & 4) === 0)
{
// reset
pic.push_irq(6);
}
dbg_log("start motors: " + h(value >> 4), LOG_DISK);
dbg_log("enable dma: " + !!(value & 8), LOG_DISK);
dbg_log("reset fdc: " + !!(value & 4), LOG_DISK);
dbg_log("drive select: " + (value & 3), LOG_DISK);
dbg_log("DOR = " + h(value), LOG_DISK);
dor = value;
}
io.register_write(0x3F2, port3F2_write);
function check_drive_status(args)
{
dbg_log("check drive status", LOG_DISK);
response_index = 0;
response_length = 1;
response_data[0] = 1 << 5;
}
function seek(args)
{
dbg_log("seek", LOG_DISK);
last_cylinder = args[1];
last_head = args[0] >> 2 & 1;
if(dor & 8)
{
pic.push_irq(6);
this.next_command.call(this, this.receiving_command);
}
}
function calibrate(args)
else
{
dbg_log("floppy calibrate", LOG_DISK);
if(dor & 8)
switch(reg_byte)
{
pic.push_irq(6);
// TODO
//case 2:
//this.next_command = read_complete_track;
//this.bytes_expecting = 8;
//break;
case 0x03:
this.next_command = this.fix_drive_data;
this.bytes_expecting = 2;
break;
case 0x04:
this.next_command = this.check_drive_status;
this.bytes_expecting = 1;
break;
case 0x05:
case 0xC5:
this.next_command = function(args) { this.do_sector(true, args); };
this.bytes_expecting = 8;
break;
case 0xE6:
this.next_command = function(args) { this.do_sector(false, args); };
this.bytes_expecting = 8;
break;
case 0x07:
this.next_command = this.calibrate;
this.bytes_expecting = 1;
break;
case 0x08:
this.check_interrupt_status();
break;
case 0x4A:
this.next_command = this.read_sector_id;
this.bytes_expecting = 1;
break;
case 0x0F:
this.bytes_expecting = 2;
this.next_command = this.seek;
break;
case 0x0E:
// dump regs
dbg_log("dump registers", LOG_DISK);
this.response_data[0] = 0x80;
this.response_index = 0;
this.response_length = 1;
this.bytes_expecting = 0;
break;
default:
if(DEBUG) throw "unimpl floppy command call " + h(reg_byte);
}
this.receiving_index = 0;
}
};
// this should actually be write-only ... but people read it anyway
var dor = 0;
FloppyController.prototype.port3F2_read = function()
{
dbg_log("read 3F2: DOR", LOG_DISK);
return dor;
}
FloppyController.prototype.port3F2_write = function(value)
{
if((value & 4) === 4 && (dor & 4) === 0)
{
// reset
this.pic.push_irq(6);
}
function check_interrupt_status()
{
// do not trigger an interrupt here
dbg_log("floppy check interrupt status", LOG_DISK);
dbg_log("start motors: " + h(value >> 4), LOG_DISK);
dbg_log("enable dma: " + !!(value & 8), LOG_DISK);
dbg_log("reset fdc: " + !!(value & 4), LOG_DISK);
dbg_log("drive select: " + (value & 3), LOG_DISK);
dbg_log("DOR = " + h(value), LOG_DISK);
response_index = 0;
response_length = 2;
dor = value;
response_data[0] = 1 << 5;
response_data[1] = last_cylinder;
}
}
function do_sector(is_write, args)
{
var head = args[2],
cylinder = args[1],
sector = args[3],
sector_size = 128 << args[4],
read_count = args[5] - args[3] + 1,
FloppyController.prototype.check_drive_status = function(args)
{
dbg_log("check drive status", LOG_DISK);
read_offset = ((head + number_of_heads * cylinder) * sectors_per_track + sector - 1) * sector_size;
dbg_log("Floppy Read", LOG_DISK);
dbg_log("from " + h(read_offset) + " length " + h(read_count * sector_size), LOG_DISK);
dbg_log(cylinder + " / " + head + " / " + sector, LOG_DISK);
this.response_index = 0;
this.response_length = 1;
this.response_data[0] = 1 << 5;
}
if(!args[4])
{
dbg_log("FDC: sector count is zero, use data length instead", LOG_DISK);
}
FloppyController.prototype.seek = function(args)
{
dbg_log("seek", LOG_DISK);
if(is_write)
{
dma.do_write(fda_image, read_offset, read_count * sector_size, 2, done);
}
else
{
dma.do_read(fda_image, read_offset, read_count * sector_size, 2, done);
}
function done(error)
{
if(error)
{
// TODO: Set appropriate bits
return;
}
sector++;
if(sector > sectors_per_track)
{
sector = 1;
head++;
if(head >= number_of_heads)
{
head = 0;
cylinder++;
}
}
last_cylinder = cylinder;
last_head = head;
last_sector = sector;
response_index = 0;
response_length = 7;
response_data[0] = head << 2 | 0x20;
response_data[1] = 0;
response_data[2] = 0;
response_data[3] = cylinder;
response_data[4] = head;
response_data[5] = sector;
response_data[6] = args[4];
if(dor & 8)
{
pic.push_irq(6);
}
}
}
this.last_cylinder = args[1];
this.last_head = args[0] >> 2 & 1;
function fix_drive_data(args)
if(dor & 8)
{
dbg_log("floppy fix drive data " + args, LOG_DISK);
}
function read_sector_id(args)
{
dbg_log("floppy read sector id " + args, LOG_DISK);
response_index = 0;
response_length = 7;
response_data[0] = 0;
response_data[1] = 0;
response_data[2] = 0;
response_data[3] = 0;
response_data[4] = 0;
response_data[5] = 0;
response_data[6] = 0;
if(dor & 8)
{
pic.push_irq(6);
}
this.pic.push_irq(6);
}
}
FloppyController.prototype.calibrate = function(args)
{
dbg_log("floppy calibrate", LOG_DISK);
if(dor & 8)
{
this.pic.push_irq(6);
}
}
FloppyController.prototype.check_interrupt_status = function()
{
// do not trigger an interrupt here
dbg_log("floppy check interrupt status", LOG_DISK);
this.response_index = 0;
this.response_length = 2;
this.response_data[0] = 1 << 5;
this.response_data[1] = this.last_cylinder;
}
FloppyController.prototype.do_sector = function(is_write, args)
{
var head = args[2],
cylinder = args[1],
sector = args[3],
sector_size = 128 << args[4],
read_count = args[5] - args[3] + 1,
read_offset = ((head + this.number_of_heads * cylinder) * this.sectors_per_track + sector - 1) * sector_size;
dbg_log("Floppy Read", LOG_DISK);
dbg_log("from " + h(read_offset) + " length " + h(read_count * sector_size), LOG_DISK);
dbg_log(cylinder + " / " + head + " / " + sector, LOG_DISK);
if(!args[4])
{
dbg_log("FDC: sector count is zero, use data length instead", LOG_DISK);
}
if(is_write)
{
this.dma.do_write(this.fda_image, read_offset, read_count * sector_size, 2, this.done.bind(this, args, cylinder, head, sector));
}
else
{
this.dma.do_read(this.fda_image, read_offset, read_count * sector_size, 2, this.done.bind(this, args, cylinder, head, sector));
}
};
FloppyController.prototype.done = function(cylinder, args, head, sector, error)
{
if(error)
{
// TODO: Set appropriate bits
return;
}
sector++;
if(sector > this.sectors_per_track)
{
sector = 1;
head++;
if(head >= this.number_of_heads)
{
head = 0;
cylinder++;
}
}
this.last_cylinder = cylinder;
this.last_head = head;
this.last_sector = sector;
this.response_index = 0;
this.response_length = 7;
this.response_data[0] = head << 2 | 0x20;
this.response_data[1] = 0;
this.response_data[2] = 0;
this.response_data[3] = cylinder;
this.response_data[4] = head;
this.response_data[5] = sector;
this.response_data[6] = args[4];
if(dor & 8)
{
this.pic.push_irq(6);
}
}
FloppyController.prototype.fix_drive_data = function(args)
{
dbg_log("floppy fix drive data " + args, LOG_DISK);
}
FloppyController.prototype.read_sector_id = function(args)
{
dbg_log("floppy read sector id " + args, LOG_DISK);
this.response_index = 0;
this.response_length = 7;
this.response_data[0] = 0;
this.response_data[1] = 0;
this.response_data[2] = 0;
this.response_data[3] = 0;
this.response_data[4] = 0;
this.response_data[5] = 0;
this.response_data[6] = 0;
if(dor & 8)
{
this.pic.push_irq(6);
}
}