From c5fd8463195d0bcf7e2da2e80f3fab5c106540c8 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 6 May 2014 06:17:28 +0200 Subject: [PATCH] change floppy.js to prototypical definition5~ --- src/floppy.js | 606 +++++++++++++++++++++++++------------------------- 1 file changed, 305 insertions(+), 301 deletions(-) diff --git a/src/floppy.js b/src/floppy.js index 161b45c2..bba5a900 100644 --- a/src/floppy.js +++ b/src/floppy.js @@ -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); } }