Class: Zemu::Config::BlockDrive
- Inherits:
-
BusDevice
- Object
- Zemu::ConfigObject
- BusDevice
- Zemu::Config::BlockDrive
- Defined in:
- lib/zemu/config.rb
Overview
Block drive object
Represents a device with a sequence of sectors of a fixed size, which can be accessed via IO instructions as an IDE drive.
Constant Summary collapse
- DRIVE_MODE_READ =
Mode for reading drive.
0x01- DRIVE_MODE_WRITE =
Mode for writing drive.
0x02- DRIVE_MODE_UNINIT =
Uninitialised drive mode.
0x00
Instance Method Summary collapse
-
#blocks ⇒ Object
Array of sectors of this drive.
-
#functions ⇒ Object
Defines FFI API which will be available to the instance wrapper if this IO device is used.
-
#get_sector ⇒ Object
Get a sector number from the four LBA registers.
-
#initialize ⇒ BlockDrive
constructor
Constructor.
-
#initialize_from(file) ⇒ Object
Set file to initialize from.
-
#io_read(port) ⇒ Object
IO bus read handler.
-
#io_write(port, value) ⇒ Object
IO bus write handler.
-
#load_sector ⇒ Object
Load sector data pointed to by LBA registers.
-
#params ⇒ Object
Valid parameters for a BlockDrive, along with those defined in [Zemu::Config::BusDevice].
-
#read_byte(sector, offset) ⇒ Object
Read a byte at the given offset in a sector.
-
#write_current_sector ⇒ Object
Write sector data to the sector currently pointed to by the LBA registers.
Methods inherited from BusDevice
#clock, #interrupt, #interrupt?, #mem_read, #mem_write, #memory, #nmi, #nmi?, #when_setup
Methods inherited from Zemu::ConfigObject
Constructor Details
#initialize ⇒ BlockDrive
Constructor.
Takes a block in which the parameters of the block drive can be initialized.
All parameters can be set within this block. They become readonly as soon as the block completes.
Constructor raises RangeError if a file is provided for initialization and it is of the wrong size.
490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 |
# File 'lib/zemu/config.rb', line 490 def initialize @initialize_from = nil super # Initialize from provided file if applicable. unless @initialize_from.nil? # Check file size. file_size = File.size(@initialize_from) if (file_size != num_sectors * sector_size) raise RangeError, "Initialization file for Zemu::Config::BlockDrive '#{name}' is of wrong size." end end @lba_0 = 0 @lba_1 = 0 @lba_2 = 0 @lba_3 = 0 @drive_mode = DRIVE_MODE_UNINIT @drive_status = 0b01000000 @sector_offset = 0 @sector_data = [] end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class Zemu::ConfigObject
Instance Method Details
#blocks ⇒ Object
Array of sectors of this drive.
612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 |
# File 'lib/zemu/config.rb', line 612 def blocks b = [] if @initialize_from.nil? num_sectors.times do this_block = [] sector_size.times do this_block << 0 end b << this_block end return b end File.open(@initialize_from, "rb") do |f| num_sectors.times do this_block = f.read(sector_size) b << this_block.unpack("C" * sector_size) end end b end |
#functions ⇒ Object
Defines FFI API which will be available to the instance wrapper if this IO device is used.
657 658 659 660 |
# File 'lib/zemu/config.rb', line 657 def functions [ ] end |
#get_sector ⇒ Object
Get a sector number from the four LBA registers.
540 541 542 543 544 545 546 547 548 |
# File 'lib/zemu/config.rb', line 540 def get_sector() sector = 0 sector |= @lba_0 sector |= @lba_1 << 8 sector |= @lba_2 << 16 sector |= @lba_3 << 24 sector end |
#initialize_from(file) ⇒ Object
Set file to initialize from.
637 638 639 |
# File 'lib/zemu/config.rb', line 637 def initialize_from(file) @initialize_from = file end |
#io_read(port) ⇒ Object
IO bus read handler.
Handles read access via the IO bus to this device.
Returns the value read, or nil if the port does not correspond to this device.
523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 |
# File 'lib/zemu/config.rb', line 523 def io_read(port) if port == base_port b = @sector_data.shift() if @sector_data.empty? @drive_status = 0b01000000 end return b elsif port == (base_port + 7) return @drive_status end nil end |
#io_write(port, value) ⇒ Object
IO bus write handler.
Handles write access via the IO bus to this device.
576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 |
# File 'lib/zemu/config.rb', line 576 def io_write(port, value) if port == base_port if @drive_mode == DRIVE_MODE_WRITE @sector_data << value if @sector_data.size >= sector_size write_current_sector() @drive_status = 0b01000000 end end elsif port == (base_port + 3) @lba_0 = (value & 0xff) elsif port == (base_port + 4) @lba_1 = (value & 0xff) elsif port == (base_port + 5) @lba_2 = (value & 0xff) elsif port == (base_port + 6) @lba_3 = (value & 0x1f) elsif port == (base_port + 7) # Read command. if value == 0x20 load_sector() @drive_mode = DRIVE_MODE_READ @drive_status = 0b00001000 # Write command. elsif value == 0x30 @sector_data = [] @drive_mode = DRIVE_MODE_WRITE @drive_status = 0b00001000 end end end |
#load_sector ⇒ Object
Load sector data pointed to by LBA registers.
561 562 563 564 565 566 567 568 |
# File 'lib/zemu/config.rb', line 561 def load_sector() file_offset = get_sector() * sector_size File.open(@initialize_from, "rb") do |f| f.seek(file_offset) s = f.read(sector_size) @sector_data = s.unpack("C" * sector_size) end end |
#params ⇒ Object
Valid parameters for a BlockDrive, along with those defined in [Zemu::Config::BusDevice].
664 665 666 |
# File 'lib/zemu/config.rb', line 664 def params super + %w(base_port sector_size num_sectors) end |
#read_byte(sector, offset) ⇒ Object
Read a byte at the given offset in a sector.
Returns the byte read from the file.
647 648 649 650 651 652 653 654 |
# File 'lib/zemu/config.rb', line 647 def read_byte(sector, offset) file_offset = (sector * sector_size) + offset File.open(@initialize_from, "rb") do |f| f.seek(file_offset) s = f.read(1) return s.unpack("C")[0] end end |
#write_current_sector ⇒ Object
Write sector data to the sector currently pointed to by the LBA registers.
552 553 554 555 556 557 558 |
# File 'lib/zemu/config.rb', line 552 def write_current_sector() file_offset = get_sector() * sector_size File.open(@initialize_from, "r+b") do |f| f.seek(file_offset) f.write(@sector_data.pack("C" * sector_size)) end end |