Annotation of nono/vm/goldfish_tty.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: //
                      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:        mainbus = GetMainbusDevice();
                     87: 
                     88:        gfpic = GetGFPICDevice(1);
                     89:        gfpic->RegistIRQ(32, "GFTTY", this);
                     90: 
                     91:        scheduler->ConnectMessage(MessageID::HOSTCOM_RX, this,
                     92:                ToMessageCallback(&GFTTYDevice::RxMessage));
                     93:        return true;
                     94: }
                     95: 
                     96: // 電源オン/リセット
                     97: void
                     98: GFTTYDevice::ResetHard(bool poweron)
                     99: {
                    100:        rxq.clear();
                    101:        intr_enable = false;
                    102:        ChangeInterrupt();
                    103: }
                    104: 
                    105: busdata
1.1.1.2   root      106: GFTTYDevice::ReadPort(uint32 offset)
1.1       root      107: {
                    108:        busdata data;
                    109: 
                    110:        switch (offset) {
                    111:         case BYTES_READY:
1.1.1.2   root      112:                data = GetREADY();
                    113:                putlog(2, "BYTES_READY -> $%08x", data.Data());
1.1       root      114:                break;
                    115: 
                    116:         case VERSION:
1.1.1.2   root      117:                data = GFTTYVersion;
1.1       root      118:                putlog(2, "VERSION -> $%08x", data.Data());
                    119:                break;
                    120: 
                    121:         default:
1.1.1.2   root      122:                putlog(1, "Read $%08x.L", mpu->GetPaddr());
1.1       root      123:                data.SetBusErr();
                    124:                break;
                    125:        }
                    126: 
1.1.1.2   root      127:        data |= BusData::Size4;
1.1       root      128:        return data;
                    129: }
                    130: 
                    131: busdata
1.1.1.2   root      132: GFTTYDevice::WritePort(uint32 offset, uint32 data)
1.1       root      133: {
                    134:        busdata r;
                    135: 
                    136:        switch (offset) {
                    137:         case PUT_CHAR:
                    138:                putlog(2, "PUT_CHAR <- $%02x", data);
                    139:                hostcom->Tx(data);
                    140:                break;
                    141: 
                    142:         case COMMAND:
                    143:                Command(data);
                    144:                break;
                    145: 
                    146:         case DATA_PTR:
                    147:                putlog(2, "DATA_PTR <- $%08x", data);
                    148:                dma_ptr = data;
                    149:                break;
                    150: 
                    151:         case DATA_LEN:
                    152:                putlog(2, "DATA_LEN <- $%08x", data);
                    153:                dma_len = data;
                    154:                break;
                    155: 
                    156:         default:
1.1.1.2   root      157:                putlog(1, "Write $%08x.L", mpu->GetPaddr());
1.1       root      158:                r.SetBusErr();
                    159:                break;
                    160:        }
1.1.1.2   root      161: 
                    162:        r |= BusData::Size4;
1.1       root      163:        return r;
                    164: }
                    165: 
                    166: busdata
1.1.1.2   root      167: GFTTYDevice::PeekPort(uint32 offset)
                    168: {
                    169:        switch (offset) {
                    170:         case BYTES_READY:
                    171:                return GetREADY();
                    172:         case VERSION:
                    173:                return GFTTYVersion;
                    174:         default:
                    175:                return BusData::BusErr;
                    176:        }
                    177: }
                    178: 
                    179: // 着信しているバイト数を返す。
                    180: uint32
                    181: GFTTYDevice::GetREADY() const
1.1       root      182: {
1.1.1.2   root      183:        return rxq.size();
1.1       root      184: }
                    185: 
                    186: void
                    187: GFTTYDevice::Command(uint32 cmd)
                    188: {
                    189:        switch (cmd) {
                    190:         case CMD_INT_DISABLE:
                    191:                putlog(1, "CMD_INT_DISABLE");
                    192:                intr_enable = false;
                    193:                ChangeInterrupt();
                    194:                break;
                    195: 
                    196:         case CMD_INT_ENABLE:
                    197:                putlog(1, "CMD_INT_ENABLE");
                    198:                intr_enable = true;
                    199:                ChangeInterrupt();
                    200:                break;
                    201: 
                    202:         case CMD_WRITE_BUFFER:
                    203:         {
                    204:                // ゲストからの書き込み
                    205:                putlog(1, "CMD_WRITE_BUFFER($%08x, $%08x)", dma_ptr, dma_len);
                    206:                uint32 addr = dma_ptr;
                    207:                uint32 end = addr + dma_len;
                    208:                for (; addr < end; addr++) {
1.1.1.2   root      209:                        busdata data = mainbus->HVRead1(addr);
1.1       root      210:                        if (data.IsBusErr()) {
                    211:                                putlog(1, "WRITE_BUFFER: BusError at $%08x", addr);
                    212:                                break;
                    213:                        }
                    214:                        hostcom->Tx(data);
                    215:                }
                    216:                break;
                    217:         }
                    218: 
                    219:         case CMD_READ_BUFFER:
                    220:         {
                    221:                // ゲストからの読み込み (ゲスト空間へ書き出し)
                    222:                putlog(1, "CMD_READ_BUFFER($%08x, $%08x)", dma_ptr, dma_len);
                    223:                uint32 addr = dma_ptr;
                    224:                uint32 len = std::min(dma_len, (uint32)rxq.size());
                    225:                for (uint32 end = addr + len; addr < end; addr++) {
                    226:                        uint32 data = rxq.front();
                    227:                        rxq.pop_front();
1.1.1.2   root      228:                        busdata bd = mainbus->HVWrite1(addr, data);
1.1       root      229:                        if (bd.IsBusErr()) {
                    230:                                putlog(1, "READ_BUFFER: BusError at $%08x", addr);
                    231:                                break;
                    232:                        }
                    233:                }
                    234:                ChangeInterrupt();
                    235:                break;
                    236:         }
                    237: 
                    238:         default:
                    239:                putlog(1, "Unknown command $%08x", cmd);
                    240:                break;
                    241:        }
                    242: }
                    243: 
                    244: void
                    245: GFTTYDevice::ChangeInterrupt()
                    246: {
                    247:        bool irq = (intr_enable && rxq.empty() == false);
                    248:        gfpic->ChangeINT(this, irq);
                    249: }
                    250: 
                    251: // ホストスレッドからの受信通知
                    252: // (HostCOM スレッドで呼ばれる)
                    253: void
                    254: GFTTYDevice::HostRxCallback()
                    255: {
                    256:        scheduler->SendMessage(MessageID::HOSTCOM_RX);
                    257: }
                    258: 
                    259: // ホストシリアルからの1バイト(以上)受信メッセージ
                    260: // (VM スレッドで呼ばれる)
                    261: void
                    262: GFTTYDevice::RxMessage(MessageID msgid, uint32 arg)
                    263: {
                    264:        bool recv = false;
                    265: 
                    266:        for (;;) {
                    267:                uint32 data = hostcom->Rx();
                    268:                if ((int32)data < 0) {
                    269:                        break;
                    270:                }
                    271:                rxq.push_back(data);
                    272:                recv = true;
                    273:        }
                    274: 
                    275:        if (recv) {
                    276:                ChangeInterrupt();
                    277:        }
                    278: }

unix.superglobalmegacorp.com

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