Annotation of nono/vm/goldfish_tty.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: // 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.