Annotation of nono/vm/goldfish_tty.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: // Goldfish TTY
        !             9: //
        !            10: 
        !            11: // レジスタ仕様は次の通り。
        !            12: //  +$00.L PUT_CHAR            -W: 1バイト出力
        !            13: //  +$04.L BYTES_READY R-: 受信キューにあるバイト数を取得
        !            14: //  +$08.L COMMAND             -W: コマンド
        !            15: //  +$0c.L -
        !            16: //  +$10.L DATA_PTR            -W: DMA 開始アドレス
        !            17: //  +$14.L DATA_LEN            -W: DMA データ長
        !            18: //  +$18.L DATA_PTR_HIGH W: DMA 開始アドレスの上位 32 ビット
        !            19: //  +$1c.L -
        !            20: //  +$20.L VERSION             R-: このデバイスのバージョン ($1)
        !            21: //
        !            22: // コマンドは
        !            23: //  $00 INT_DISABLE
        !            24: //  $01 INT_ENABLE
        !            25: //  $02 WRITE_BUFFER
        !            26: //  $03 READ_BUFFER
        !            27: //
        !            28: // 受信キューにデータがあれば割り込みを上げる。
        !            29: // 受信キューが空になると割り込みを下げる。
        !            30: //
        !            31: // WRITE_BUFFER, READ_BUFFER はたぶんバスマスタ的転送。
        !            32: // 読み出し時 (READ_BUFFER) は、DATA_PTR で指定したアドレスにたぶん最大
        !            33: // DATA_LEN バイトを GFTTY デバイスが書き込む。
        !            34: // 書き込み時 (WRITE_BUFFER) は、DATA_PTR で指定したアドレスから DATA_LEN
        !            35: // バイトを GFTTY デバイスが読み込む。
        !            36: //
        !            37: // nono では DATA_PTR_HIGH は実装しない。
        !            38: 
        !            39: #include "goldfish_tty.h"
        !            40: #include "goldfish_pic.h"
        !            41: #include "hostcom.h"
        !            42: #include "mainbus.h"
        !            43: #include "scheduler.h"
        !            44: 
        !            45: // コンストラクタ
        !            46: GFTTYDevice::GFTTYDevice()
        !            47:        : inherited(OBJ_GFTTY)
        !            48: {
        !            49: }
        !            50: 
        !            51: // デストラクタ
        !            52: GFTTYDevice::~GFTTYDevice()
        !            53: {
        !            54:        if ((bool)hostcom) {
        !            55:                hostcom->SetRxCallback(NULL);
        !            56:        }
        !            57: }
        !            58: 
        !            59: bool
        !            60: GFTTYDevice::Create()
        !            61: {
        !            62:        // 対応するホストドライバを作成
        !            63:        hostcom.reset(new HostCOMDevice(this, "HostCOM"));
        !            64:        if ((bool)hostcom == false) {
        !            65:                return false;
        !            66:        }
        !            67:        hostcom->SetRxCallback(ToDeviceCallback(&GFTTYDevice::HostRxCallback));
        !            68: 
        !            69:        return true;
        !            70: }
        !            71: 
        !            72: void
        !            73: GFTTYDevice::SetLogLevel(int loglevel_)
        !            74: {
        !            75:        inherited::SetLogLevel(loglevel_);
        !            76: 
        !            77:        assert((bool)hostcom);
        !            78:        hostcom->SetLogLevel(loglevel_);
        !            79: }
        !            80: 
        !            81: // 初期化
        !            82: bool
        !            83: GFTTYDevice::Init()
        !            84: {
        !            85:        if (inherited::Init() == false) {
        !            86:                return false;
        !            87:        }
        !            88: 
        !            89:        mainbus = GetMainbusDevice();
        !            90: 
        !            91:        gfpic = GetGFPICDevice(1);
        !            92:        gfpic->RegistIRQ(32, "GFTTY", this);
        !            93: 
        !            94:        scheduler->ConnectMessage(MessageID::HOSTCOM_RX, this,
        !            95:                ToMessageCallback(&GFTTYDevice::RxMessage));
        !            96:        return true;
        !            97: }
        !            98: 
        !            99: // 電源オン/リセット
        !           100: void
        !           101: GFTTYDevice::ResetHard(bool poweron)
        !           102: {
        !           103:        rxq.clear();
        !           104:        intr_enable = false;
        !           105:        ChangeInterrupt();
        !           106: }
        !           107: 
        !           108: busdata
        !           109: GFTTYDevice::Read32(uint32 addr)
        !           110: {
        !           111:        uint32 offset = addr & 0xfff;
        !           112:        busdata data;
        !           113: 
        !           114:        switch (offset) {
        !           115:         case BYTES_READY:
        !           116:                data = rxq.size();
        !           117:                putlog(2, "BYTES_READ -> $%08x", data.Data());
        !           118:                break;
        !           119: 
        !           120:         case VERSION:
        !           121:                data = 1;
        !           122:                putlog(2, "VERSION -> $%08x", data.Data());
        !           123:                break;
        !           124: 
        !           125:         default:
        !           126:                putlog(1, "Read $%08x.L", addr);
        !           127:                data.SetBusErr();
        !           128:                break;
        !           129:        }
        !           130: 
        !           131:        return data;
        !           132: }
        !           133: 
        !           134: busdata
        !           135: GFTTYDevice::Write32(uint32 addr, uint32 data)
        !           136: {
        !           137:        uint32 offset = addr & 0xfff;
        !           138:        busdata r;
        !           139: 
        !           140:        switch (offset) {
        !           141:         case PUT_CHAR:
        !           142:                putlog(2, "PUT_CHAR <- $%02x", data);
        !           143:                hostcom->Tx(data);
        !           144:                break;
        !           145: 
        !           146:         case COMMAND:
        !           147:                Command(data);
        !           148:                break;
        !           149: 
        !           150:         case DATA_PTR:
        !           151:                putlog(2, "DATA_PTR <- $%08x", data);
        !           152:                dma_ptr = data;
        !           153:                break;
        !           154: 
        !           155:         case DATA_LEN:
        !           156:                putlog(2, "DATA_LEN <- $%08x", data);
        !           157:                dma_len = data;
        !           158:                break;
        !           159: 
        !           160:         default:
        !           161:                putlog(1, "Write $%08x.L", addr);
        !           162:                r.SetBusErr();
        !           163:                break;
        !           164:        }
        !           165:        return r;
        !           166: }
        !           167: 
        !           168: busdata
        !           169: GFTTYDevice::Peek8(uint32 addr)
        !           170: {
        !           171:        return busdata::BusErr;
        !           172: }
        !           173: 
        !           174: void
        !           175: GFTTYDevice::Command(uint32 cmd)
        !           176: {
        !           177:        switch (cmd) {
        !           178:         case CMD_INT_DISABLE:
        !           179:                putlog(1, "CMD_INT_DISABLE");
        !           180:                intr_enable = false;
        !           181:                ChangeInterrupt();
        !           182:                break;
        !           183: 
        !           184:         case CMD_INT_ENABLE:
        !           185:                putlog(1, "CMD_INT_ENABLE");
        !           186:                intr_enable = true;
        !           187:                ChangeInterrupt();
        !           188:                break;
        !           189: 
        !           190:         case CMD_WRITE_BUFFER:
        !           191:         {
        !           192:                // ゲストからの書き込み
        !           193:                putlog(1, "CMD_WRITE_BUFFER($%08x, $%08x)", dma_ptr, dma_len);
        !           194:                uint32 addr = dma_ptr;
        !           195:                uint32 end = addr + dma_len;
        !           196:                for (; addr < end; addr++) {
        !           197:                        busdata data = mainbus->HVRead8(addr);
        !           198:                        if (data.IsBusErr()) {
        !           199:                                putlog(1, "WRITE_BUFFER: BusError at $%08x", addr);
        !           200:                                break;
        !           201:                        }
        !           202:                        hostcom->Tx(data);
        !           203:                }
        !           204:                break;
        !           205:         }
        !           206: 
        !           207:         case CMD_READ_BUFFER:
        !           208:         {
        !           209:                // ゲストからの読み込み (ゲスト空間へ書き出し)
        !           210:                putlog(1, "CMD_READ_BUFFER($%08x, $%08x)", dma_ptr, dma_len);
        !           211:                uint32 addr = dma_ptr;
        !           212:                uint32 len = std::min(dma_len, (uint32)rxq.size());
        !           213:                for (uint32 end = addr + len; addr < end; addr++) {
        !           214:                        uint32 data = rxq.front();
        !           215:                        rxq.pop_front();
        !           216:                        busdata bd = mainbus->HVWrite8(addr, data);
        !           217:                        if (bd.IsBusErr()) {
        !           218:                                putlog(1, "READ_BUFFER: BusError at $%08x", addr);
        !           219:                                break;
        !           220:                        }
        !           221:                }
        !           222:                ChangeInterrupt();
        !           223:                break;
        !           224:         }
        !           225: 
        !           226:         default:
        !           227:                putlog(1, "Unknown command $%08x", cmd);
        !           228:                break;
        !           229:        }
        !           230: }
        !           231: 
        !           232: void
        !           233: GFTTYDevice::ChangeInterrupt()
        !           234: {
        !           235:        bool irq = (intr_enable && rxq.empty() == false);
        !           236:        gfpic->ChangeINT(this, irq);
        !           237: }
        !           238: 
        !           239: // ホストスレッドからの受信通知
        !           240: // (HostCOM スレッドで呼ばれる)
        !           241: void
        !           242: GFTTYDevice::HostRxCallback()
        !           243: {
        !           244:        scheduler->SendMessage(MessageID::HOSTCOM_RX);
        !           245: }
        !           246: 
        !           247: // ホストシリアルからの1バイト(以上)受信メッセージ
        !           248: // (VM スレッドで呼ばれる)
        !           249: void
        !           250: GFTTYDevice::RxMessage(MessageID msgid, uint32 arg)
        !           251: {
        !           252:        bool recv = false;
        !           253: 
        !           254:        for (;;) {
        !           255:                uint32 data = hostcom->Rx();
        !           256:                if ((int32)data < 0) {
        !           257:                        break;
        !           258:                }
        !           259:                rxq.push_back(data);
        !           260:                recv = true;
        !           261:        }
        !           262: 
        !           263:        if (recv) {
        !           264:                ChangeInterrupt();
        !           265:        }
        !           266: }

unix.superglobalmegacorp.com

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