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

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

unix.superglobalmegacorp.com

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