Annotation of nono/vm/v68kio.cpp, revision 1.1.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.