1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-09-30 07:55:01 +00:00

Stubs in just enough of the 5380 to get a Mac Plus too boot.

This commit is contained in:
Thomas Harte 2019-08-11 20:55:20 -04:00
parent 949c1e1668
commit a90a74a512
3 changed files with 122 additions and 53 deletions

View File

@ -8,11 +8,80 @@
#include "ncr5380.hpp"
#include "../../Outputs/Log.hpp"
using namespace NCR::NCR5380;
void NCR5380::write(int address, uint8_t value) {
switch(address & 7) {
case 0:
LOG("[SCSI] Set current SCSI bus state to " << PADHEX(2) << value);
break;
case 1:
LOG("[SCSI] Initiator command register set: " << PADHEX(2) << value);
break;
case 2:
LOG("[SCSI] Set mode: " << PADHEX(2) << value);
mode_ = value;
break;
case 3:
LOG("[SCSI] Set target command: " << PADHEX(2) << value);
break;
case 4:
LOG("[SCSI] Set select enabled: " << PADHEX(2) << value);
break;
case 5:
LOG("[SCSI] Start DMA send: " << PADHEX(2) << value);
break;
case 6:
LOG("[SCSI] Start DMA target receive: " << PADHEX(2) << value);
break;
case 7:
LOG("[SCSI] Start DMA initiator receive: " << PADHEX(2) << value);
break;
}
}
uint8_t NCR5380::read(int address) {
switch(address & 7) {
case 0:
LOG("[SCSI] Get current SCSI bus state");
return 0xff;
case 1:
LOG("[SCSI] Initiator command register get");
return 0xff;
case 2:
LOG("[SCSI] Get mode");
return mode_;
case 3:
LOG("[SCSI] Get target command");
return 0xff;
case 4:
LOG("[SCSI] Get current bus state");
return 0xff;
case 5:
LOG("[SCSI] Get bus and status");
return 0x03;
case 6:
LOG("[SCSI] Get input data");
return 0xff;
case 7:
LOG("[SCSI] Reset parity/interrupt");
return 0xff;
}
return 0;
}

View File

@ -24,6 +24,9 @@ class NCR5380 {
/*! Reads from @c address. */
uint8_t read(int address);
private:
uint8_t mode_ = 0xff;
};
}

View File

@ -29,6 +29,7 @@
//#define LOG_TRACE
#include "../../../Components/5380/ncr5380.hpp"
#include "../../../Components/6522/6522.hpp"
#include "../../../Components/8530/z8530.hpp"
#include "../../../Components/DiskII/IWM.hpp"
@ -183,8 +184,6 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
uint16_t *memory_base = nullptr;
HalfCycles delay;
switch(memory_map_[word_address >> 16]) {
case BusDevice::SCSI:
printf("SCSI\n");
default: assert(false);
case BusDevice::Unassigned:
@ -234,6 +233,35 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
}
} return delay;
case BusDevice::SCSI: {
const int register_address = word_address >> 2; // TODO: this is a guess.
// Even accesses = read; odd = write.
if(*cycle.address & 1) {
// Odd access => this is a write. Data will be in the upper byte.
if(cycle.operation & Microcycle::Read) {
scsi_.write(register_address, 0xff);
} else {
if(cycle.operation & Microcycle::SelectWord) {
scsi_.write(register_address, cycle.value->halves.high);
} else {
scsi_.write(register_address, cycle.value->halves.low);
}
}
} else {
// Even access => this is a read.
if(cycle.operation & Microcycle::Read) {
const auto result = scsi_.read(register_address);
if(cycle.operation & Microcycle::SelectWord) {
// Data is loaded on the top part of the bus only.
cycle.value->full = (result << 8) | 0xff;
} else {
cycle.value->halves.low = result;
}
}
}
} return delay;
case BusDevice::SCCReadResetPhase: {
// Any word access here adjusts phase.
if(cycle.operation & Microcycle::SelectWord) {
@ -350,7 +378,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
case Model::Mac128k:
case Model::Mac512k:
case Model::Mac512ke:
populate_memory_map([rom_is_overlay] (std::function<void(int target, BusDevice device)> map_to) {
populate_memory_map(0, [rom_is_overlay] (std::function<void(int target, BusDevice device)> map_to) {
// Addresses up to $80 0000 aren't affected by this bit.
if(rom_is_overlay) {
// Up to $60 0000 mirrors of the ROM alternate with unassigned areas every $10 0000 byes.
@ -367,7 +395,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
break;
case Model::MacPlus:
populate_memory_map([rom_is_overlay] (std::function<void(int target, BusDevice device)> map_to) {
populate_memory_map(0, [rom_is_overlay] (std::function<void(int target, BusDevice device)> map_to) {
// Addresses up to $80 0000 aren't affected by this bit.
if(rom_is_overlay) {
for(int c = 0; c < 0x580000; c += 0x20000) {
@ -674,6 +702,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
VIAPortHandler via_port_handler_;
Zilog::SCC::z8530 scc_;
NCR::NCR5380::NCR5380 scsi_;
HalfCycles via_clock_;
HalfCycles real_time_clock_;
@ -704,60 +733,28 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
BusDevice memory_map_[128];
void setup_memory_map() {
// Apply the power-up memory map, i.e. assume that ROM_is_overlay_ = true.
// Apply the power-up memory map, i.e. assume that ROM_is_overlay_ = true;
// start by calling into set_rom_is_overlay to seed everything up to $800000.
set_rom_is_overlay(true);
using Model = Analyser::Static::Macintosh::Target::Model;
switch(model) {
default: assert(false);
case Model::Mac128k:
case Model::Mac512k:
case Model::Mac512ke:
populate_memory_map([] (std::function<void(int target, BusDevice device)> map_to) {
// Up to $60 0000 mirrors of the ROM alternate with unassigned areas every $10 0000 byes.
for(int c = 0; c < 0x600000; c += 0x100000) {
map_to(c + 0x100000, (c & 0x100000) ? BusDevice::Unassigned : BusDevice::ROM);
}
map_to(0x800000, BusDevice::RAM);
map_to(0x900000, BusDevice::Unassigned);
map_to(0xa00000, BusDevice::SCCReadResetPhase);
map_to(0xb00000, BusDevice::Unassigned);
map_to(0xc00000, BusDevice::SCCWrite);
map_to(0xd00000, BusDevice::Unassigned);
map_to(0xe00000, BusDevice::IWM);
map_to(0xe80000, BusDevice::Unassigned);
map_to(0xf00000, BusDevice::VIA);
map_to(0xf80000, BusDevice::PhaseRead);
map_to(0x1000000, BusDevice::Unassigned);
});
break;
case Model::MacPlus:
populate_memory_map([] (std::function<void(int target, BusDevice device)> map_to) {
for(int c = 0; c < 0x580000; c += 0x20000) {
map_to(c + 0x20000, ((c & 0x100000) || (c & 0x20000)) ? BusDevice::Unassigned : BusDevice::ROM);
}
map_to(0x600000, BusDevice::SCSI);
map_to(0x800000, BusDevice::RAM);
map_to(0x900000, BusDevice::Unassigned);
map_to(0xa00000, BusDevice::SCCReadResetPhase);
map_to(0xb00000, BusDevice::Unassigned);
map_to(0xc00000, BusDevice::SCCWrite);
map_to(0xd00000, BusDevice::Unassigned);
map_to(0xe00000, BusDevice::IWM);
map_to(0xe80000, BusDevice::Unassigned);
map_to(0xf00000, BusDevice::VIA);
map_to(0xf80000, BusDevice::PhaseRead);
map_to(0x1000000, BusDevice::Unassigned);
});
break;
}
populate_memory_map(0x800000, [] (std::function<void(int target, BusDevice device)> map_to) {
map_to(0x900000, BusDevice::Unassigned);
map_to(0xa00000, BusDevice::SCCReadResetPhase);
map_to(0xb00000, BusDevice::Unassigned);
map_to(0xc00000, BusDevice::SCCWrite);
map_to(0xd00000, BusDevice::Unassigned);
map_to(0xe00000, BusDevice::IWM);
map_to(0xe80000, BusDevice::Unassigned);
map_to(0xf00000, BusDevice::VIA);
map_to(0xf80000, BusDevice::PhaseRead);
map_to(0x1000000, BusDevice::Unassigned);
});
}
void populate_memory_map(std::function<void(std::function<void(int, BusDevice)>)> populator) {
void populate_memory_map(int start_address, std::function<void(std::function<void(int, BusDevice)>)> populator) {
// Define semantics for below; map_to will write from the current cursor position
// to the supplied 24-bit address, setting a particular mapped device.
int segment = 0;
int segment = start_address >> 17;
auto map_to = [&segment, this](int address, BusDevice device) {
for(; segment < address >> 17; ++segment) {
this->memory_map_[segment] = device;