|
|
nono 1.7.0
//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//
//
// PEDEC
//
// IODevice
// |
// +-- InterruptDevice (割り込みコントローラの共通部)
// |
// +-- M680x0Interrupt (m68k 割り込みコントローラの共通部)
// | |
// | +-- X68030Interrupt (X68030 の割り込みコントローラ)
// | +-- LunaInterrupt (LUNA-I の割り込みコントローラ)
// |
// | +-------------+
// +--| PEDECDevice | (X68030 の Lv1 担当コントローラ)
// | +-------------+
// |
// +-- SysCtlrDevice (LUNA-88K の割り込みコントローラ)
#include "pedec.h"
#include "fdc.h"
#include "fdd.h"
#include "mainapp.h"
#include "spc.h"
// コンストラクタ
PEDECDevice::PEDECDevice()
: inherited(OBJ_PEDEC)
{
}
// デストラクタ
PEDECDevice::~PEDECDevice()
{
}
// 初期化
bool
PEDECDevice::Init()
{
interrupt = GetInterruptDevice();
// 検索順
RegistINT(IntmapSPC, "SPC", GetSPCDevice());
RegistINT(IntmapFDC, "FDC", GetFDCDevice());
RegistINT(IntmapHDD, "HDD", NULL);
RegistINT(IntmapPRT, "PRT", NULL);
// FDD は4本を共有しているのでいろいろ特別扱い。
RegistINT(IntmapFDD0, "FDD0", gMainApp.FindObject<FDDDevice>(OBJ_FDD(0)));
RegistINT(IntmapFDD1, "FDD1", gMainApp.FindObject<FDDDevice>(OBJ_FDD(1)));
RegistINT(IntmapFDD2, "FDD2", gMainApp.FindObject<FDDDevice>(OBJ_FDD(2)));
RegistINT(IntmapFDD3, "FDD3", gMainApp.FindObject<FDDDevice>(OBJ_FDD(3)));
// 名前表示用
RegistINT(IntmapFDD, "FDD", NULL);
// 表示順
disp_list = {
IntmapSPC,
IntmapFDC,
IntmapFDD,
IntmapHDD,
IntmapPRT,
};
return true;
}
// リセット
void
PEDECDevice::ResetHard(bool poweron)
{
inherited::ResetHard(poweron);
intmap_enable = IntmapSPC;
ChangeInterrupt();
// XXX vector
}
busdata
PEDECDevice::ReadPort(uint32 offset)
{
busdata data;
switch (offset) {
case 0: // $E9C001 割り込みステータス
data = GetStat();
break;
case 1: // $E9C003 割り込みベクタ
// 書き込み専用
data = 0xff;
break;
default:
data = 0xff;
break;
}
// XXX wait?
data |= BusData::Size1;
return data;
}
busdata
PEDECDevice::WritePort(uint32 offset, uint32 data)
{
switch (offset) {
case 0: // $E9C001 割り込みマスク
intmap_enable = IntmapSPC;
intmap_enable |= (data & 0x08) ? IntmapHDD : 0;
intmap_enable |= (data & 0x04) ? IntmapFDC : 0;
intmap_enable |= (data & 0x02) ? IntmapFDD : 0;
intmap_enable |= (data & 0x01) ? IntmapPRT : 0;
putlog(1, "Set Interrupt Mask HDD=%u FDC=%u FDD=%u PRT=%u",
((intmap_enable & IntmapHDD) ? 1 : 0),
((intmap_enable & IntmapFDC) ? 1 : 0),
((intmap_enable & IntmapFDD) ? 1 : 0),
((intmap_enable & IntmapPRT) ? 1 : 0));
break;
case 1: // $E9C003 割り込みベクタ
vector = data & 0xfc;
putlog(1, "Set Interrupt Vector $%02x", vector);
break;
default:
break;
}
// XXX wait?
busdata r = BusData::Size1;
return r;
}
busdata
PEDECDevice::PeekPort(uint32 offset)
{
switch (offset) {
case 0:
return GetStat();
case 1:
// 書き込み専用
return 0xff;
default:
return 0xff;
}
}
bool
PEDECDevice::PokePort(uint32 offset, uint32 data)
{
return false;
}
void
PEDECDevice::MonitorScreen(TextScreen& screen, uint intr_level, int y)
{
for (uint32 map : disp_list) {
int clz = __builtin_clz(map);
screen.Puts(4, y, TA::OnOff(intmap_status & map), GetIntName(map));
if (intr_level >= 1 || (intmap_enable & map) == 0) {
screen.Puts(11, y, "Mask");
}
uint64 cnt = counter[clz];
if (__predict_false(map == IntmapFDD)) {
// FDD は4つの和
cnt += counter[clz + 1] + counter[clz + 2] + counter[clz + 3];
}
screen.Print(15, y, "%26s", format_number(cnt).c_str());
y++;
}
}
// 割り込みステータスレジスタの値を取得。
// (Peek からも呼ばれるので副作用を持たせてはいけない)
uint32
PEDECDevice::GetStat() const
{
uint32 data = 0;
data |= (intmap_status & IntmapFDC) ? 0x80 : 0;
data |= (intmap_status & IntmapFDD) ? 0x40 : 0;
data |= (intmap_status & IntmapPRT) ? 0x20 : 0;
data |= (intmap_status & IntmapHDD) ? 0x10 : 0;
data |= (intmap_enable & IntmapHDD) ? 0x08 : 0;
data |= (intmap_enable & IntmapFDC) ? 0x04 : 0;
data |= (intmap_enable & IntmapFDD) ? 0x02 : 0;
data |= (intmap_enable & IntmapPRT) ? 0x01 : 0;
return data;
}
// 割り込み信号線の状態を変える
void
PEDECDevice::ChangeInterrupt()
{
#if 0 // こんなログ出したいかも
// ログ表示のためだけ
if ((intmap_enable & IntmapFDC)) {
putlog(1, "FDC からの割り込み要求");
} else {
putlog(2, "FDC からの割り込み要求(マスク)");
}
#endif
uint32 stat = (intmap_status & intmap_enable);
interrupt->ChangeINT(this, stat);
}
// 割り込みアクノリッジ
busdata
PEDECDevice::InterruptAcknowledge(int lv)
{
uint32 stat = (intmap_status & intmap_enable);
// SPC と I/O コントローラ担当の4本どっちが優先かは分からないので
// SPC を優先しておくのでいいだろう。
if ((stat & IntmapSPC)) {
// XXX PEDEC のベクタに影響されるか?
return 0x6c;
}
if ((stat & IntmapFDC)) {
return vector + 0;
} else if ((stat & IntmapFDD)) {
return vector + 1;
} else {
return BusData::BusErr;
}
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.