Annotation of nono/vm/goldfish_tty.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: //
                      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"
1.1.1.2 ! root       43: #include "mpu.h"
1.1       root       44: #include "scheduler.h"
                     45: 
                     46: // コンストラクタ
                     47: GFTTYDevice::GFTTYDevice()
                     48:        : inherited(OBJ_GFTTY)
                     49: {
                     50: }
                     51: 
                     52: // デストラクタ
                     53: GFTTYDevice::~GFTTYDevice()
                     54: {
                     55:        if ((bool)hostcom) {
                     56:                hostcom->SetRxCallback(NULL);
                     57:        }
                     58: }
                     59: 
                     60: bool
                     61: GFTTYDevice::Create()
                     62: {
                     63:        // 対応するホストドライバを作成
                     64:        hostcom.reset(new HostCOMDevice(this, "HostCOM"));
                     65:        if ((bool)hostcom == false) {
                     66:                return false;
                     67:        }
                     68:        hostcom->SetRxCallback(ToDeviceCallback(&GFTTYDevice::HostRxCallback));
                     69: 
                     70:        return true;
                     71: }
                     72: 
                     73: void
                     74: GFTTYDevice::SetLogLevel(int loglevel_)
                     75: {
                     76:        inherited::SetLogLevel(loglevel_);
                     77: 
                     78:        assert((bool)hostcom);
                     79:        hostcom->SetLogLevel(loglevel_);
                     80: }
                     81: 
                     82: // 初期化
                     83: bool
                     84: GFTTYDevice::Init()
                     85: {
                     86:        if (inherited::Init() == false) {
                     87:                return false;
                     88:        }
                     89: 
                     90:        mainbus = GetMainbusDevice();
                     91: 
                     92:        gfpic = GetGFPICDevice(1);
                     93:        gfpic->RegistIRQ(32, "GFTTY", this);
                     94: 
                     95:        scheduler->ConnectMessage(MessageID::HOSTCOM_RX, this,
                     96:                ToMessageCallback(&GFTTYDevice::RxMessage));
                     97:        return true;
                     98: }
                     99: 
                    100: // 電源オン/リセット
                    101: void
                    102: GFTTYDevice::ResetHard(bool poweron)
                    103: {
                    104:        rxq.clear();
                    105:        intr_enable = false;
                    106:        ChangeInterrupt();
                    107: }
                    108: 
                    109: busdata
1.1.1.2 ! root      110: GFTTYDevice::ReadPort(uint32 offset)
1.1       root      111: {
                    112:        busdata data;
                    113: 
                    114:        switch (offset) {
                    115:         case BYTES_READY:
1.1.1.2 ! root      116:                data = GetREADY();
        !           117:                putlog(2, "BYTES_READY -> $%08x", data.Data());
1.1       root      118:                break;
                    119: 
                    120:         case VERSION:
1.1.1.2 ! root      121:                data = GFTTYVersion;
1.1       root      122:                putlog(2, "VERSION -> $%08x", data.Data());
                    123:                break;
                    124: 
                    125:         default:
1.1.1.2 ! root      126:                putlog(1, "Read $%08x.L", mpu->GetPaddr());
1.1       root      127:                data.SetBusErr();
                    128:                break;
                    129:        }
                    130: 
1.1.1.2 ! root      131:        data |= BusData::Size4;
1.1       root      132:        return data;
                    133: }
                    134: 
                    135: busdata
1.1.1.2 ! root      136: GFTTYDevice::WritePort(uint32 offset, uint32 data)
1.1       root      137: {
                    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:
1.1.1.2 ! root      161:                putlog(1, "Write $%08x.L", mpu->GetPaddr());
1.1       root      162:                r.SetBusErr();
                    163:                break;
                    164:        }
1.1.1.2 ! root      165: 
        !           166:        r |= BusData::Size4;
1.1       root      167:        return r;
                    168: }
                    169: 
                    170: busdata
1.1.1.2 ! root      171: GFTTYDevice::PeekPort(uint32 offset)
        !           172: {
        !           173:        switch (offset) {
        !           174:         case BYTES_READY:
        !           175:                return GetREADY();
        !           176:         case VERSION:
        !           177:                return GFTTYVersion;
        !           178:         default:
        !           179:                return BusData::BusErr;
        !           180:        }
        !           181: }
        !           182: 
        !           183: // 着信しているバイト数を返す。
        !           184: uint32
        !           185: GFTTYDevice::GetREADY() const
1.1       root      186: {
1.1.1.2 ! root      187:        return rxq.size();
1.1       root      188: }
                    189: 
                    190: void
                    191: GFTTYDevice::Command(uint32 cmd)
                    192: {
                    193:        switch (cmd) {
                    194:         case CMD_INT_DISABLE:
                    195:                putlog(1, "CMD_INT_DISABLE");
                    196:                intr_enable = false;
                    197:                ChangeInterrupt();
                    198:                break;
                    199: 
                    200:         case CMD_INT_ENABLE:
                    201:                putlog(1, "CMD_INT_ENABLE");
                    202:                intr_enable = true;
                    203:                ChangeInterrupt();
                    204:                break;
                    205: 
                    206:         case CMD_WRITE_BUFFER:
                    207:         {
                    208:                // ゲストからの書き込み
                    209:                putlog(1, "CMD_WRITE_BUFFER($%08x, $%08x)", dma_ptr, dma_len);
                    210:                uint32 addr = dma_ptr;
                    211:                uint32 end = addr + dma_len;
                    212:                for (; addr < end; addr++) {
1.1.1.2 ! root      213:                        busdata data = mainbus->HVRead1(addr);
1.1       root      214:                        if (data.IsBusErr()) {
                    215:                                putlog(1, "WRITE_BUFFER: BusError at $%08x", addr);
                    216:                                break;
                    217:                        }
                    218:                        hostcom->Tx(data);
                    219:                }
                    220:                break;
                    221:         }
                    222: 
                    223:         case CMD_READ_BUFFER:
                    224:         {
                    225:                // ゲストからの読み込み (ゲスト空間へ書き出し)
                    226:                putlog(1, "CMD_READ_BUFFER($%08x, $%08x)", dma_ptr, dma_len);
                    227:                uint32 addr = dma_ptr;
                    228:                uint32 len = std::min(dma_len, (uint32)rxq.size());
                    229:                for (uint32 end = addr + len; addr < end; addr++) {
                    230:                        uint32 data = rxq.front();
                    231:                        rxq.pop_front();
1.1.1.2 ! root      232:                        busdata bd = mainbus->HVWrite1(addr, data);
1.1       root      233:                        if (bd.IsBusErr()) {
                    234:                                putlog(1, "READ_BUFFER: BusError at $%08x", addr);
                    235:                                break;
                    236:                        }
                    237:                }
                    238:                ChangeInterrupt();
                    239:                break;
                    240:         }
                    241: 
                    242:         default:
                    243:                putlog(1, "Unknown command $%08x", cmd);
                    244:                break;
                    245:        }
                    246: }
                    247: 
                    248: void
                    249: GFTTYDevice::ChangeInterrupt()
                    250: {
                    251:        bool irq = (intr_enable && rxq.empty() == false);
                    252:        gfpic->ChangeINT(this, irq);
                    253: }
                    254: 
                    255: // ホストスレッドからの受信通知
                    256: // (HostCOM スレッドで呼ばれる)
                    257: void
                    258: GFTTYDevice::HostRxCallback()
                    259: {
                    260:        scheduler->SendMessage(MessageID::HOSTCOM_RX);
                    261: }
                    262: 
                    263: // ホストシリアルからの1バイト(以上)受信メッセージ
                    264: // (VM スレッドで呼ばれる)
                    265: void
                    266: GFTTYDevice::RxMessage(MessageID msgid, uint32 arg)
                    267: {
                    268:        bool recv = false;
                    269: 
                    270:        for (;;) {
                    271:                uint32 data = hostcom->Rx();
                    272:                if ((int32)data < 0) {
                    273:                        break;
                    274:                }
                    275:                rxq.push_back(data);
                    276:                recv = true;
                    277:        }
                    278: 
                    279:        if (recv) {
                    280:                ChangeInterrupt();
                    281:        }
                    282: }

unix.superglobalmegacorp.com

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