|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.