--- nono/vm/romemu_x68k.cpp 2026/04/29 17:05:25 1.1.1.3 +++ nono/vm/romemu_x68k.cpp 2026/04/29 17:05:29 1.1.1.4 @@ -8,12 +8,34 @@ // X68030 の ROM30 (SCSI ROM) エミュレーション // +// IODevice +// | +// +- ROMDevice (LoadROM()、ウェイト、マスク等を持つ) +// | +- PROMDevice (LUNA* の PROM) +// | +- IPLROM1Device (X680x0 の IPLROM 後半) +// | +- IPLROM2Device (X680x0 の IPLROM 前半) +// | +- CGROMDevice (X680x0 の CGROM) +// | | +// | +- ROMEmuDevice +// | +- LunaPROMEmuDevice (LUNA PROM エミュレーションの共通部分) +// | | +- Luna1PROMEmuDevice (LUNA-I の PROM エミュレーション) +// | | +- Luna88kPROMEmuDevice (LUNA-88K の PROM エミュレーション) +// | +- NewsROMEmuDevice (NEWS の ROM エミュレーション) +// | | +// | | +----------------+ +// | +-| ROM30EmuDevice | (X68030 の ROM30 エミュレーション) +// | | +----------------+ +// | | +// | +- Virt68kROMEmuDevice (virt-m68k の IPLROM 相当の何か) +// | +// +- PROM0Device (LUNA* のブートページ切り替え用プロキシ) +// +- IPLROM0Device (X680x0 のブートページ切り替え用プロキシ) + #include "romemu_x68k.h" #include "mainbus.h" #include "mainram.h" #include "memorystream.h" #include "mpu680x0.h" -#include "romimg_x68k.h" #include "scsidev.h" #include "spc.h" #include "sram.h" @@ -46,62 +68,62 @@ ROM30EmuDevice::Init() mainbus = GetMainbusDevice(); spc = GetSPCDevice(); - MemoryStreamBE ms(imagebuf.get()); + MemoryStreamBE roms(imagebuf.get()); // fc0000.L 〜 fc001c.L: SCSI ブートアドレス for (int i = 0; i < 8; i++) { - ms.Write32(0x00fc0100); + roms.Write4(0x00fc0100); } // fc0020.L: SCSI 初期化アドレス - ms.Write32(0x00fc0200); + roms.Write4(0x00fc0200); // fc0024.B: マジック - ms.Write32(('S' << 24) | ('C' << 16) | ('S' << 8) | 'I'); - ms.Write16(('I' << 8) | 'N'); - ms.Write8(0); - ms.Write8(0); + roms.Write4(('S' << 24) | ('C' << 16) | ('S' << 8) | 'I'); + roms.Write2(('I' << 8) | 'N'); + roms.Write1(0); + roms.Write1(0); // // SCSI ブート // - ms.SetOffset(0x100); //_SCSIBOOT: - ms.Write16(0x6100); // bsr $fc0200 ; SCSIIOCS 初期化 - ms.Write16(0x0200 - ms.GetOffset()); - ms.Write16(0x2039); // move.l (ROMIO_BOOT),d0 - ms.Write32(ROMIO_BOOT); - ms.Write16(0x6602); // bne _go ; 起動先があればGO + roms.SetOffset(0x100); //_SCSIBOOT: + roms.Write2(0x6100); // bsr $fc0200 ; SCSIIOCS 初期化 + roms.Write2(0x0200 - roms.GetOffset()); + roms.Write2(0x2039); // move.l (ROMIO_BOOT),d0 + roms.Write4(ROMIO_BOOT); + roms.Write2(0x6602); // bne _go ; 起動先があればGO //_bootfail: - ms.Write16(0x4e75); // rts + roms.Write2(0x4e75); // rts //_go: - ms.Write16(0x2040); // move.l d0,a0 ; ジャンプ先を a0 にセット - ms.Write16(0x4ed0); // jmp (a0) ; で、ジャンプ + roms.Write2(0x2040); // move.l d0,a0 ; ジャンプ先を a0 にセット + roms.Write2(0x4ed0); // jmp (a0) ; で、ジャンプ // // SCSIIOCS 初期化 // - ms.SetOffset(0x200); //_SCSIINIT: - ms.Write32(0x323c01f5); // move.w #$01f5,d1 - ms.Write16(0x43f9); // lea.l $00fc0300,a1 - ms.Write32(0x00fc0300); - ms.Write32(0x70804e4f); // IOCS _B_INTVCS + roms.SetOffset(0x200); //_SCSIINIT: + roms.Write4(0x323c01f5); // move.w #$01f5,d1 + roms.Write2(0x43f9); // lea.l $00fc0300,a1 + roms.Write4(0x00fc0300); + roms.Write4(0x70804e4f); // IOCS _B_INTVCS // ; 戻り値(旧アドレス)は破棄 - ms.Write16(0x4e75); // rts + roms.Write2(0x4e75); // rts // // SCSIIOCS エントリ // - ms.SetOffset(0x300); //_SCSIIOCS: - ms.Write16(0x2039); // move.l (ROMIO_SCSI),d0 - ms.Write32(ROMIO_SCSI); - ms.Write16(0x4e75); // rts + roms.SetOffset(0x300); //_SCSIIOCS: + roms.Write2(0x2039); // move.l (ROMIO_SCSI),d0 + roms.Write4(ROMIO_SCSI); + roms.Write2(0x4e75); // rts return true; } -busdata -ROM30EmuDevice::Read32(uint32 addr) +uint64 +ROM30EmuDevice::ReadROMIO(busaddr addr) { // IPLROM2 領域からのロングワードアクセスでだけ謎の I/O 空間が見える。 - if ((mpu->GetPaddr() & 0xfffe0000) == baseaddr) { - switch (addr) { + if ((mpu->GetPPC() & 0xfffe0000) == baseaddr && addr.GetSize() == 4) { + switch (addr.Addr()) { case ROMIO_SCSI: return SCSIIOCS(); @@ -113,7 +135,7 @@ ROM30EmuDevice::Read32(uint32 addr) } } - return inherited::Read32(addr); + return (uint64)-1; } // SRAM で指定された SCSI ID のデバイスからブートブロックを読み込む。 @@ -132,12 +154,12 @@ ROM30EmuDevice::SCSIBoot() const if ((romaddr & 0xffff00) != 0xfc0000) { return 0; } - int id = (romaddr & 0x1f) >> 2; + uint id = (romaddr & 0x1f) >> 2; // ターゲットディスク - SCSITarget *target = spc->GetTarget(id); + SCSITarget *target = spc->GetSCSI()->GetTarget(id); if (target == NULL) { - putlog(1, "%s: SCSI ID %d not found", __func__, id); + putlog(1, "%s: SCSI ID %u not found", __func__, id); return 0; } SCSIDisk *disk = dynamic_cast(target); @@ -157,38 +179,36 @@ ROM30EmuDevice::SCSIBoot() const } else if (sectsize == 2048) { blocksize = sectsize; } else { - putlog(1, "%s: SCSI ID %d: sectsize %d not supported", __func__, + putlog(1, "%s: SCSI ID %u: sectsize %u not supported", __func__, id, sectsize); return 0; } - putlog(2, "%s: SCSI ID %d: sectsize=%d, blocksize=%d", __func__, id, + putlog(2, "%s: SCSI ID %u: sectsize=%u, blocksize=%u", __func__, id, sectsize, blocksize); // +0 ブロック目先頭8バイトのマジックを確認 std::vector block(blocksize); if (disk->Peek(&block[0], 0, 8) == false) { - putlog(1, "%s: SCSI ID %d: Reading magic failed", __func__, id); + putlog(1, "%s: SCSI ID %u: Reading magic failed", __func__, id); return 0; } if (memcmp(&block[0], "X68SCSI1", 8) != 0) { - putlog(1, "%s: SCSI ID %d: invalid magic", __func__, id); + putlog(1, "%s: SCSI ID %u: invalid magic", __func__, id); return 0; } // +1 ブロック目から1ブロックを読んで... if (disk->Peek(&block[0], blocksize, blocksize) == false) { - putlog(1, "%s: SCSI ID %d: Reading boot block failed", __func__, id); + putlog(1, "%s: SCSI ID %u: Reading boot block failed", __func__, id); return 0; } // 先頭バイトが 0x60 (BRA.[BW] 命令の1バイト目) であること if (block[0] != 0x60) { - putlog(1, "%s: SCSI ID %d: no branch instruction", __func__, id); + putlog(1, "%s: SCSI ID %u: no branch instruction", __func__, id); return 0; } // メモリの 0x2000 番地に置く - for (int i = 0; i < blocksize; i++) { - mainram->Write8(0x2000 + i, block[i]); - } + mainram->WriteMem(0x2000, &block[0], blocksize); // D4 にはこの時の SCSI ID が置いてある(のが見えている) reg.D[4] = id; @@ -241,18 +261,18 @@ ROM30EmuDevice::SCSIIOCS() uint32 lun = (d4 >> 16) & 0x0000ffff; \ std::string scsiname = GetSCSICallName(scsicall); \ /* ターゲットディスク */ \ - SCSITarget *target = spc->GetTarget(id); \ + SCSITarget *target = spc->GetSCSI()->GetTarget(id); \ if (target == NULL) { \ - putlog(1, "%s ID%d not found", scsiname.c_str(), id); \ + putlog(1, "%s ID%u not found", scsiname.c_str(), id); \ return -1; \ } \ SCSIDisk *disk __unused = dynamic_cast(target); \ /* ログ表示用 */ \ std::string loghdr; \ if (loglevel >= 1) { \ - loghdr = string_format("%s ID%d", scsiname.c_str(), id); \ + loghdr = string_format("%s ID%u", scsiname.c_str(), id); \ if (lun != 0) { \ - loghdr + string_format(":LUN%d", lun); \ + loghdr + string_format(":LUN%u", lun); \ } \ } \ /*end*/ @@ -262,9 +282,9 @@ ROM30EmuDevice::SCSI_S_INQUIRY(uint32 sc { PRE; - busaddr a1(reg.A[1], busaddr::S); + uint32 a1 = reg.A[1]; uint32 reqlen = reg.D[3]; - putlog(1, "%s a1=$%06x", loghdr.c_str(), a1.Addr()); + putlog(1, "%s a1=$%06x", loghdr.c_str(), a1); std::vector cmdseq(6); cmdseq[0] = SCSI::Command::Inquiry; cmdseq[1] = lun << 5; @@ -282,7 +302,7 @@ ROM30EmuDevice::SCSI_S_INQUIRY(uint32 sc // アロケーションサイズ(reqlen)と結果(cmd->buf)の小さい方まで転送 int len = std::min((int)reqlen, (int)res.size()); for (int i = 0; i < len; i++) { - busdata bd = mainbus->Write8(a1++, res[i]); + busdata bd = mainbus->HVWrite1(a1++, res[i]); if (bd.IsBusErr()) { return -1; } @@ -295,7 +315,7 @@ ROM30EmuDevice::SCSI_S_READEXT(uint32 sc { PRE; - busaddr a1(reg.A[1], busaddr::S); + uint32 a1 = reg.A[1]; uint32 lba = reg.D[2]; uint32 blkcount = reg.D[3]; uint32 blkshift = reg.D[5]; @@ -303,8 +323,8 @@ ROM30EmuDevice::SCSI_S_READEXT(uint32 sc uint32 blkbytes = 0x100 << blkshift; uint32 bytes = blkcount * blkbytes; - putlog(1, "%s a1=$%06x lba=$%08x bytes=%d d5=%d", - loghdr.c_str(), a1.Addr(), lba, bytes, blkshift); + putlog(1, "%s a1=$%06x lba=$%08x bytes=%u d5=%u", + loghdr.c_str(), a1, lba, bytes, blkshift); std::vector cmdseq(10); cmdseq[0] = SCSI::Command::Read10; cmdseq[1] = lun << 5; @@ -326,8 +346,8 @@ ROM30EmuDevice::SCSI_S_READEXT(uint32 sc const std::vector& res = cmd->buf; if (res.size() != bytes) { - putlog(1, "%s res.size=%d mismatch with bytes=%d", - loghdr.c_str(), (int)res.size(), bytes); + putlog(1, "%s res.size=%u mismatch with bytes=%u", + loghdr.c_str(), (uint)res.size(), bytes); // SCSIIOCS ブロックサイズとディスクのセクタサイズが不整合の // 場合、転送は DMAC か SPC のいずれかが打ち切る。 // XXX そのときも何らかのエラーが発生しているはずだが? @@ -337,7 +357,7 @@ ROM30EmuDevice::SCSI_S_READEXT(uint32 sc } for (int i = 0; i < bytes; i++) { - busdata bd = mainbus->Write8(a1++, res[i]); + busdata bd = mainbus->HVWrite1(a1++, res[i]); if (bd.IsBusErr()) { return -1; } @@ -359,8 +379,8 @@ ROM30EmuDevice::SCSI_S_READCAP(uint32 sc { PRE; - busaddr a1(reg.A[1], busaddr::S); - putlog(1, "%s a1=$%06x", loghdr.c_str(), a1.Addr()); + uint32 a1 = reg.A[1]; + putlog(1, "%s a1=$%06x", loghdr.c_str(), a1); std::vector cmdseq(10); cmdseq[0] = SCSI::Command::ReadCapacity; cmdseq[1] = lun << 5; @@ -376,7 +396,7 @@ ROM30EmuDevice::SCSI_S_READCAP(uint32 sc const std::vector& res = cmd->buf; assert(res.size() == 8); for (auto data : res) { - busdata bd = mainbus->Write8(a1++, data); + busdata bd = mainbus->HVWrite1(a1++, data); if (bd.IsBusErr()) { return -1; }