Annotation of nono/vm/v68kio.cpp, revision 1.1

1.1     ! root        1: //
        !             2: // nono
        !             3: // Copyright (C) 2024 nono project
        !             4: // Licensed under nono-license.txt
        !             5: //
        !             6: 
        !             7: //
        !             8: // virt68k の I/O 空間担当
        !             9: //
        !            10: 
        !            11: // メモリマップ。
        !            12: // NetBSD/virt68k は $ff00'0000 以降が I/O 空間で、デバイス配置は
        !            13: // ブートローダ (実質 BIOS) からカーネルにパラメータとして渡される。
        !            14: // 各デバイスの先頭番地こそ自由だが、同種のデバイスが連続する場合
        !            15: // 配置間隔がデバイスによって異なっておりその長さはハードコードのようだ。
        !            16: // GF* は 0x1000 番地ずつ、VirtIO は 0x200 番地ずつとなっている。
        !            17: //
        !            18: // メモリマップはこんな感じにする。
        !            19: //
        !            20: // $ff00'0000-$ff00'ffff PROM
        !            21: // $ff01'xxxx            Goldfish Interrupt(PIC) #1..#6
        !            22: // $ff01'1000-$ff01'1fff  Lv1
        !            23: // $ff01'2000-$ff01'2fff  Lv2
        !            24: // $ff01'3000-$ff01'3fff  Lv3
        !            25: // $ff01'4000-$ff01'4fff  Lv4
        !            26: // $ff01'5000-$ff01'5fff  Lv5
        !            27: // $ff01'6000-$ff01'6fff  Lv6
        !            28: // $ff02'xxxx            Goldfish RTC+Timer
        !            29: // $ff02'0000-$ff02'0fff  Timer
        !            30: // $ff02'1000-$ff02'1fff  RTC
        !            31: // $ff03'0000-$ff03'0fff Goldfish TTY
        !            32: // $ff04'0000-$ff04'0fff Qemu Virtual System Controller
        !            33: // $ff07'xxxx            VirtIO
        !            34: //
        !            35: // VirtIO は間隔が違うので最後に置く。
        !            36: // ここは 1スロット $200 で、最大 127個まで置けるようだ。
        !            37: // デバイスが存在しないスロットはバスエラーではなく、DEVICE_ID = INVALID
        !            38: // で応答しなければならない。
        !            39: //
        !            40: // $ff07'0000-$ff07'01ff  VirtIO(00)
        !            41: // $ff07'0200-$ff07'03ff  VirtIO(01)
        !            42: //  :
        !            43: // $ff07'fe00-$ff07'ffff  VirtIO(7f)
        !            44: 
        !            45: #include "v68kio.h"
        !            46: #include "config.h"
        !            47: #include "goldfish_pic.h"
        !            48: #include "goldfish_rtc.h"
        !            49: #include "goldfish_timer.h"
        !            50: #include "goldfish_tty.h"
        !            51: #include "mainbus.h"
        !            52: #include "qemusysctlr.h"
        !            53: #include "romemu_virt68k.h"
        !            54: #include "virtio_base.h"
        !            55: #include "virtio_block.h"
        !            56: #include "virtio_net.h"
        !            57: #include "vm.h"
        !            58: 
        !            59: // コンストラクタ
        !            60: V68kIODevice::V68kIODevice()
        !            61:        : inherited(OBJ_V68KIO)
        !            62: {
        !            63:        NEWDV(PROM, new Virt68kROMEmuDevice());
        !            64:        NEWDV(GFPIC1, new GFPICDevice(1));
        !            65:        NEWDV(GFPIC2, new GFPICDevice(2));
        !            66:        NEWDV(GFPIC3, new GFPICDevice(3));
        !            67:        NEWDV(GFPIC4, new GFPICDevice(4));
        !            68:        NEWDV(GFPIC5, new GFPICDevice(5));
        !            69:        NEWDV(GFPIC6, new GFPICDevice(6));
        !            70:        NEWDV(GFRTC, new GFRTCDevice());                                // required by GFTimer
        !            71:        NEWDV(GFTimer, new GFTimerDevice());
        !            72:        NEWDV(GFTTY, new GFTTYDevice());
        !            73:        NEWDV(QemuSysCtlr, new QemuSysCtlrDevice());
        !            74:        NEWDV(VirtIONone, new VirtIONoneDevice());
        !            75: 
        !            76:        buserr = GetBusErrDevice();
        !            77: 
        !            78:        // まず全域をバスエラーで埋める。
        !            79:        for (int i = 0; i < table.size(); i++) {
        !            80:                table[i] = buserr;
        !            81:        }
        !            82: 
        !            83:        // 少ないので手動で埋めていく。
        !            84:        for (int i = 0; i < 0x10; i++) {
        !            85:                table[i] = pPROM.get();
        !            86:        }
        !            87:        table[0x11] = pGFPIC1.get();
        !            88:        table[0x12] = pGFPIC2.get();
        !            89:        table[0x13] = pGFPIC3.get();
        !            90:        table[0x14] = pGFPIC4.get();
        !            91:        table[0x15] = pGFPIC5.get();
        !            92:        table[0x16] = pGFPIC6.get();
        !            93:        table[0x20] = pGFTimer.get();
        !            94:        table[0x21] = pGFRTC.get();
        !            95:        table[0x30] = pGFTTY.get();
        !            96:        table[0x40] = pQemuSysCtlr.get();
        !            97: 
        !            98:        // VirtIO 用は、設定によるので後で代入する。
        !            99:        // ここはバスエラーではない。
        !           100:        for (int i = 0; i < viotable.size(); i++) {
        !           101:                viotable[i] = pVirtIONone.get();
        !           102:        }
        !           103: }
        !           104: 
        !           105: // デストラクタ
        !           106: V68kIODevice::~V68kIODevice()
        !           107: {
        !           108: }
        !           109: 
        !           110: // 動的なコンストラクション
        !           111: bool
        !           112: V68kIODevice::Create()
        !           113: {
        !           114:        int slot;
        !           115: 
        !           116:        // (QEMU virt68k の?)
        !           117:        // virtio はスロットによって割り込み先を固定してあるようだ。
        !           118:        // スロット  0 .. 31 は PIC2(Lv2) の IRQ1..32、
        !           119:        // スロット 32 .. 63 は PIC3(Lv3) の IRQ1..32、
        !           120:        // スロット 64 .. 95 は PIC4(Lv4) の IRQ1..32、
        !           121:        // スロット 96 ..127 は PIC5(Lv5) の IRQ1..32 となる。
        !           122:        //
        !           123:        // Block、Net はとりあえず先例にならって Lv5 につなぐことにしてみる。
        !           124:        slot = 96;
        !           125: 
        !           126:        // Net
        !           127:        if (true) {
        !           128:                pVirtIO[slot].reset(new VirtIONetDevice(slot));
        !           129:                if ((bool)pVirtIO[slot] == false) {
        !           130:                        return false;
        !           131:                }
        !           132:                viotable[slot] = pVirtIO[slot].get();
        !           133:                slot++;
        !           134:        }
        !           135: 
        !           136:        // Block (とりあえず8個まで)
        !           137:        for (int id = 0; id < 8; id++) {
        !           138:                const std::string key = string_format("virtio-block%d-image", id);
        !           139:                const ConfigItem& item = gConfig->Find(key);
        !           140:                const std::string& image = item.AsString();
        !           141: 
        !           142:                // 空ならデバイスなし
        !           143:                if (image.empty()) {
        !           144:                        // 未接続部分のパラメータは減らしておくか。
        !           145:                        // --show-config するとさすがに無駄に多くて邪魔なので。
        !           146:                        gConfig->Delete(string_format("virtio-block%d-writeignore", id));
        !           147:                        continue;
        !           148:                }
        !           149: 
        !           150:                pVirtIO[slot].reset(new VirtIOBlockDevice(slot, id));
        !           151:                if ((bool)pVirtIO[slot] == false) {
        !           152:                        item.Err();     // ?
        !           153:                        return false;
        !           154:                }
        !           155:                viotable[slot] = pVirtIO[slot].get();
        !           156:                slot++;
        !           157:        }
        !           158: 
        !           159:        return true;
        !           160: }
        !           161: 
        !           162: bool
        !           163: V68kIODevice::Init()
        !           164: {
        !           165:        if (inherited::Init() == false) {
        !           166:                return false;
        !           167:        }
        !           168: 
        !           169:        return true;
        !           170: }
        !           171: 
        !           172: inline IODevice *
        !           173: V68kIODevice::SearchDevice(uint32 addr) const
        !           174: {
        !           175:        if (__predict_true(addr < 0xff07'0000)) {
        !           176:                // FF0X'X000
        !           177:                uint32 idx = (addr >> 12) & 0x7f;
        !           178:                return table[idx];
        !           179:        } else if (__predict_true(addr < 0xff08'0000)) {
        !           180:                // FF07'XX00
        !           181:                uint32 idx = (addr >> 9) & 0x7f;
        !           182:                return viotable[idx];
        !           183:        } else {
        !           184:                return buserr;
        !           185:        }
        !           186: }
        !           187: 
        !           188: busdata
        !           189: V68kIODevice::Read8(uint32 addr)
        !           190: {
        !           191:        IODevice *d = SearchDevice(addr);
        !           192:        return d->Read8(addr);
        !           193: }
        !           194: 
        !           195: busdata
        !           196: V68kIODevice::Read16(uint32 addr)
        !           197: {
        !           198:        IODevice *d = SearchDevice(addr);
        !           199:        return d->Read16(addr);
        !           200: }
        !           201: 
        !           202: busdata
        !           203: V68kIODevice::Read32(uint32 addr)
        !           204: {
        !           205:        IODevice *d = SearchDevice(addr);
        !           206:        return d->Read32(addr);
        !           207: }
        !           208: 
        !           209: busdata
        !           210: V68kIODevice::Write8(uint32 addr, uint32 data)
        !           211: {
        !           212:        IODevice *d = SearchDevice(addr);
        !           213:        return d->Write8(addr, data);
        !           214: }
        !           215: 
        !           216: busdata
        !           217: V68kIODevice::Write16(uint32 addr, uint32 data)
        !           218: {
        !           219:        IODevice *d = SearchDevice(addr);
        !           220:        return d->Write16(addr, data);
        !           221: }
        !           222: 
        !           223: busdata
        !           224: V68kIODevice::Write32(uint32 addr, uint32 data)
        !           225: {
        !           226:        IODevice *d = SearchDevice(addr);
        !           227:        return d->Write32(addr, data);
        !           228: }
        !           229: 
        !           230: busdata
        !           231: V68kIODevice::Peek8(uint32 addr)
        !           232: {
        !           233:        IODevice *d = SearchDevice(addr);
        !           234:        return d->Peek8(addr);
        !           235: }
        !           236: 
        !           237: bool
        !           238: V68kIODevice::Poke8(uint32 addr, uint32 data)
        !           239: {
        !           240:        IODevice *d = SearchDevice(addr);
        !           241:        return d->Poke8(addr, data);
        !           242: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.