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

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: inline IODevice *
                    174: V68kIODevice::SearchDevice(uint32 addr) const
                    175: {
                    176:        if (__predict_true(addr < 0xff07'0000)) {
                    177:                // FF0X'X000
                    178:                uint32 idx = (addr >> 12) & 0x7f;
                    179:                return table[idx];
                    180:        } else if (__predict_true(addr < 0xff08'0000)) {
                    181:                // FF07'XX00
                    182:                uint32 idx = (addr >> 9) & 0x7f;
                    183:                return viotable[idx];
                    184:        } else {
                    185:                return buserr;
                    186:        }
                    187: }
                    188: 
                    189: busdata
1.1.1.2   root      190: V68kIODevice::Read(busaddr addr)
1.1       root      191: {
1.1.1.2   root      192:        IODevice *d = SearchDevice(addr.Addr());
                    193:        return d->Read(addr);
1.1       root      194: }
                    195: 
                    196: busdata
1.1.1.2   root      197: V68kIODevice::Write(busaddr addr, uint32 data)
1.1       root      198: {
1.1.1.2   root      199:        IODevice *d = SearchDevice(addr.Addr());
                    200:        return d->Write(addr, data);
1.1       root      201: }
                    202: 
                    203: busdata
1.1.1.2   root      204: V68kIODevice::Peek1(uint32 addr)
1.1       root      205: {
                    206:        IODevice *d = SearchDevice(addr);
1.1.1.2   root      207:        return d->Peek1(addr);
1.1       root      208: }
                    209: 
                    210: bool
1.1.1.2   root      211: V68kIODevice::Poke1(uint32 addr, uint32 data)
1.1       root      212: {
                    213:        IODevice *d = SearchDevice(addr);
1.1.1.2   root      214:        return d->Poke1(addr, data);
1.1       root      215: }

unix.superglobalmegacorp.com

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