|
|
1.1 root 1: //
2: // nono
1.1.1.3 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
7: #include "upd7201.h"
1.1.1.5 ! root 8: #include "interrupt.h"
1.1 root 9:
10: // コンストラクタ
11: uPD7201Device::uPD7201Device()
12: {
1.1.1.5 ! root 13: monitor_size = nnSize(48, 22);
1.1 root 14: cr.chan[0].id = 0;
15: cr.chan[0].name = "A";
16: cr.chan[1].id = 1;
17: cr.chan[1].name = "B";
18:
19: cr.chan[0].desc = NULL;
20: cr.chan[1].desc = NULL;
21: }
22:
23: // デストラクタ
24: uPD7201Device::~uPD7201Device()
25: {
26: }
27:
28: // リセット
29: // どのタイミングで呼ばれるかは上位による
30: void
31: uPD7201Device::Reset()
32: {
33: putlog(2, "リセット");
34:
35: // CR2A はチップリセットで bit6 以外を '0' に
36: cr.cr2a &= ~0xbf;
37:
38: // チャンネルリセット
39: ResetChannel(&cr.chan[0]);
40: ResetChannel(&cr.chan[1]);
41: }
42:
43: // チャンネルリセット
44: void
45: uPD7201Device::ResetChannel(struct SIO::channel *chan)
46: {
1.1.1.5 ! root 47: putlog(2, "Channel %s Reset", chan->name);
1.1 root 48:
1.1.1.5 ! root 49: // CR0 b2-0 (PTR)
1.1 root 50: chan->ptr = 0;
51:
52: // CR1 b0,1,3,4,7
53: chan->cr1 &= ~(SIO::CR1_WAIT_EN | SIO::CR1_RXINT |
54: SIO::CR1_TXINT_EN | SIO::CR1_ESINT_EN);
1.1.1.5 ! root 55: chan->all_or_first = false;
1.1 root 56:
57: // CR3 b0-7
58: chan->cr3 = 0;
59:
60: // CR5 b1,2,3,4,7
61: chan->cr5 &= ~(SIO::CR5_DTR | SIO::CR5_SENDBREAK | SIO::CR5_TX_EN |
62: SIO::CR5_CRC16 | SIO::CR5_RTS);
63:
64: // SR0 は b0,1 が '0'、b2,6 が '1'、残りは不定
65: chan->sr0 &= ~(SIO::SR0_INTPEND | SIO::SR0_RXAVAIL);
66: chan->sr0 |= (SIO::SR0_TXUNDER | SIO::SR0_TXEMPTY);
67:
68: // SR1 は b4-7 が '0'
69: chan->sr1 &= ~(SIO::SR1_ENDOFFRAME | SIO::SR1_CRCERROR |
70: SIO::SR1_RXOVERRUN | SIO::SR1_PARITYERROR);
71:
1.1.1.5 ! root 72: // 内部状態をリセット
1.1 root 73: chan->es_ratched = false;
1.1.1.5 ! root 74: chan->reset_txint_pend = true;
1.1 root 75:
76: // 受信バッファをクリア
77: memset(chan->rxbuf, 0, sizeof(chan->rxbuf));
78: chan->rxlen = 0;
79: }
80:
81: // 制御ポートの読み込み
82: uint8
83: uPD7201Device::ReadCtrl(struct SIO::channel *chan)
84: {
85: uint8 data;
86:
87: switch (chan->ptr) {
88: case 0: // SR0
1.1.1.5 ! root 89: data = chan->sr0;
1.1 root 90: putlog(2, "SR%d%s -> $%02x", chan->ptr, chan->name, data);
91: // アクセス後は SR0 へ戻す
92: chan->ptr = 0;
93: break;
94:
95: case 1: // SR1
1.1.1.5 ! root 96: data = chan->sr1;
1.1 root 97: putlog(2, "SR%d%s -> $%02x", chan->ptr, chan->name, data);
98: // アクセス後は SR0 へ戻す
99: chan->ptr = 0;
100: break;
101:
102: case 2:
103: // SR2B はベクタの読み出し
104: if (chan->id == 1) {
105: data = cr.vector;
106: putlog(2, "SR%d%s -> $%02x", chan->ptr, chan->name, data);
107: // アクセス後は SR0 へ戻す
108: chan->ptr = 0;
109: break;
110: }
111:
112: // SR2A はない
113: FALLTHROUGH;
114:
115: default:
116: putlog(0, "未実装レジスタ読み込み SR%d%s",
117: chan->ptr, chan->name);
118: // SR0 へ戻る?
119: chan->ptr = 0;
120: return 0xff;
121: }
122: return data;
123: }
124:
125: // 制御ポートの書き込み
126: void
127: uPD7201Device::WriteCtrl(struct SIO::channel *chan, uint32 data)
128: {
1.1.1.5 ! root 129: // CR0 はコマンドかまたは次にアクセスするレジスタを指定する。
! 130: // CR0 以外のレジスタをアクセスすると、次のアクセスは CR0 に戻る。
1.1 root 131:
1.1.1.5 ! root 132: if (chan->ptr == 0) {
! 133: WriteCR0(chan, data);
! 134: } else {
! 135: switch (chan->ptr) {
! 136: case 1:
! 137: WriteCR1(chan, data);
1.1 root 138: break;
1.1.1.5 ! root 139: case 2:
! 140: WriteCR2(chan, data);
1.1 root 141: break;
1.1.1.5 ! root 142: case 3:
! 143: WriteCR3(chan, data);
1.1 root 144: break;
1.1.1.5 ! root 145: case 4:
! 146: WriteCR4(chan, data);
1.1 root 147: break;
1.1.1.5 ! root 148: case 5:
! 149: WriteCR5(chan, data);
1.1 root 150: break;
1.1.1.5 ! root 151: case 6:
! 152: WriteCR6(chan, data);
1.1 root 153: break;
1.1.1.5 ! root 154: case 7:
! 155: WriteCR7(chan, data);
1.1 root 156: break;
157: default:
1.1.1.5 ! root 158: putlog(0, "未実装レジスタ書き込み CR%d%s <- $%02x",
! 159: chan->ptr, chan->name, data);
! 160: break;
1.1 root 161: }
162: // アクセス後は CR0 へ戻す
163: chan->ptr = 0;
164: }
165: }
166:
1.1.1.2 root 167: // 制御ポートの Peek
168: uint8
169: uPD7201Device::PeekCtrl(const struct SIO::channel *chan) const
170: {
171: switch (chan->ptr) {
172: case 0: // SR0
1.1.1.5 ! root 173: return chan->sr0;
1.1.1.2 root 174:
175: case 1: // SR1
1.1.1.5 ! root 176: return chan->sr1;
1.1.1.2 root 177:
178: case 2: // SR2
179: // SR2A はない。SR2B はベクタの読み出し
180: if (chan->id == 1) {
181: return cr.vector;
182: }
183: FALLTHROUGH;
184:
185: default:
186: // 未調査
187: return 0xff;
188: }
189: }
190:
1.1.1.5 ! root 191: // CR0 への書き込み
! 192: void
! 193: uPD7201Device::WriteCR0(struct SIO::channel *chan, uint32 data)
1.1.1.2 root 194: {
1.1.1.5 ! root 195: uint cmd;
1.1.1.2 root 196:
1.1.1.5 ! root 197: // XXX b7,b6 は未対応。
! 198: // b5,b4,b3 がコマンド。
! 199: // b2,b1,b0 が次にアクセスするレジスタ(chan->ptr)の切り替え。
! 200: chan->cr0 = data;
! 201: chan->ptr = (chan->cr0 & SIO::CR0_PTR);
! 202:
! 203: cmd = (chan->cr0 & SIO::CR0_CMD) >> 3;
! 204: if (cmd == 0) {
! 205: // コマンド0 ならレジスタ切り替え
! 206: putlog(3, "CR0%s <- $%02x (ptr=%d)", chan->name, data, chan->ptr);
! 207: } else {
! 208: // 0 以外ならコマンド発行
! 209: putlog(2, "CR0%s <- $%02x", chan->name, data);
! 210: }
! 211: switch (cmd) {
! 212: case 0: // No operation
! 213: break;
! 214: case 1: // Send Abort
! 215: if (chan->mode == SIO::Mode::HDLC) {
! 216: putlog(0, "CR0: Send Abort 未実装");
! 217: } else {
! 218: // XXX Send Abort コマンドは「HDLC モードのみ有効」と書いて
! 219: // あるがそれ以外の時にどうなるか不明。
! 220: putlog(0, "CR0: 未定義コマンド %d", cmd);
! 221: }
! 222: break;
! 223: case 2: // Reset External/Status Interrupt
! 224: putlog(3, "CR0%s: Reset E/S Interrupt", chan->name);
! 225: chan->es_ratched = false;
! 226: break;
! 227: case 3: // Channel Reset
! 228: ResetChannel(chan);
! 229: break;
! 230: case 4: // Enable Interrupt On Next Receive Character
! 231: putlog(0, "CR0: 未実装コマンド %d", cmd);
! 232: break;
! 233: case 5: // Reset Transmitter Interrupt/DMA Pending
! 234: putlog(1, "CR0%s: Reset Tx Int/DMA Pending", chan->name);
! 235: chan->reset_txint_pend = false;
! 236: ChangeInterrupt();
! 237: break;
! 238: case 6: // Error Reset
! 239: case 7: // End of Interrupt
! 240: putlog(0, "CR0: 未実装コマンド %d", cmd);
! 241: break;
! 242: default:
! 243: __unreachable();
1.1.1.2 root 244: }
245: }
246:
1.1.1.5 ! root 247: // CR1 への書き込み
! 248: void
! 249: uPD7201Device::WriteCR1(struct SIO::channel *chan, uint32 data)
1.1.1.2 root 250: {
1.1.1.5 ! root 251: putlog(2, "CR%d%s <- $%02x", chan->ptr, chan->name, data);
! 252:
! 253: chan->cr1 = data;
! 254:
! 255: // RXINT モードで all_or_first の値(初期値)を用意。
! 256: // DISABLE なら(使わないのでどっちでもいいはずだけど一応) false にしとく。
! 257: // FIRSTCHAR なら初期状態が true。ALL_* なら常時 true。
! 258: chan->all_or_first = ((chan->cr1 & SIO::CR1_RXINT) != SIO::RXINT_DISABLE);
1.1.1.2 root 259: }
260:
1.1.1.5 ! root 261: // CR2 への書き込み
! 262: void
! 263: uPD7201Device::WriteCR2(struct SIO::channel *chan, uint32 data)
! 264: {
! 265: if (chan->id == 0) { // CR2A
! 266: putlog(2, "CR2A <- $%02x 書き込み(b7,b2-0未実装)", data);
! 267: cr.cr2a = data;
! 268: } else { // CR2B
! 269: putlog(2, "CR2B <- $%02x (Set vector)", data);
! 270: cr.vector = data;
! 271: }
! 272: }
! 273:
! 274: // CR3 への書き込み
! 275: void
! 276: uPD7201Device::WriteCR3(struct SIO::channel *chan, uint32 data)
! 277: {
! 278: chan->cr3 = data;
! 279:
! 280: putlog(2, "CR%d%s <- $%02x", chan->ptr, chan->name, data);
! 281: putlog(1, "Channel %s RX %s, %dbits",
! 282: chan->name,
! 283: (chan->cr3 & SIO::CR3_RX_EN) ? "Enable" : "Disable",
! 284: bits_per_char[(chan->cr3 & SIO::CR3_RXBITS) >> 6]);
! 285: }
! 286:
! 287: // CR4 への書き込み
! 288: void
! 289: uPD7201Device::WriteCR4(struct SIO::channel *chan, uint32 data)
! 290: {
! 291: chan->cr4 = data;
! 292: putlog(2, "CR%d%s <- $%02x", chan->ptr, chan->name, data);
! 293: uint8 stopbits = (chan->cr4 & SIO::CR4_STOPBITS);
! 294: uint8 syncmode = (chan->cr4 & SIO::CR4_SYNCMODE);
! 295:
! 296: // モード分け、優先順位は分からない
! 297: if (stopbits == SIO::SYNC_MODE) {
! 298: if (syncmode == SIO::SYNC_HDLC) {
! 299: chan->mode = SIO::Mode::HDLC;
! 300: putlog(2, "Channel %s HDLC Mode", chan->name);
! 301: } else {
! 302: chan->mode = SIO::Mode::SYNC;
! 303: const char *sm[] = { "8bit", "16bit", "HDLC?", "Ext" };
! 304: putlog(2, "Channel %s Sync (%s) Mode",
! 305: chan->name, sm[syncmode >> 4]);
! 306: }
! 307: } else {
! 308: chan->mode = SIO::Mode::ASYNC;
! 309: const char *cm[] = { "x1", "x16", "x32", "x64" };
! 310: const char *sm[] = { "?", "1", "1.5", "2" };
! 311: putlog(2, "Channel %s Async (%s clock, stopbit %s) Mode",
! 312: chan->name,
! 313: cm[(chan->cr4 & SIO::CR4_CLKRATE) >> 6],
! 314: sm[stopbits >> 2]);
! 315: }
! 316: }
! 317:
! 318: // CR5 への書き込み
! 319: void
! 320: uPD7201Device::WriteCR5(struct SIO::channel *chan, uint32 data)
! 321: {
! 322: chan->cr5 = data;
! 323:
! 324: putlog(2, "CR%d%s <- $%02x", chan->ptr, chan->name, data);
! 325: putlog(1, "Channel %s TX %s, %dbits",
! 326: chan->name,
! 327: (chan->cr5 & SIO::CR5_TX_EN) ? "Enable" : "Disable",
! 328: bits_per_char[(chan->cr5 & SIO::CR5_TXBITS) >> 5]);
! 329: }
! 330:
! 331: // CR6 への書き込み
! 332: void
! 333: uPD7201Device::WriteCR6(struct SIO::channel *chan, uint32 data)
! 334: {
! 335: chan->cr6 = data;
! 336:
! 337: putlog(0, "CR6%s <- $%02x 書き込み(未実装)", chan->name, data);
! 338: }
! 339:
! 340: // CR7 への書き込み
! 341: void
! 342: uPD7201Device::WriteCR7(struct SIO::channel *chan, uint32 data)
! 343: {
! 344: chan->cr7 = data;
! 345:
! 346: putlog(0, "CR7%s <- $%02x 書き込み(未実装)", chan->name, data);
! 347: }
1.1.1.2 root 348:
1.1 root 349: // データポートの読み込み
350: uint8
1.1.1.2 root 351: uPD7201Device::ReadData(struct SIO::channel *chan)
1.1 root 352: {
353: uint8 data;
354:
355: if (chan->rxlen > 0) {
356: data = chan->rxbuf[0];
1.1.1.5 ! root 357: putlog(3, "Ch%s Data -> $%02x", chan->name, data);
1.1 root 358: chan->rxlen--;
1.1.1.5 ! root 359: if (chan->rxlen == 0) {
! 360: // 取り出して空になった
! 361: chan->sr0 &= ~SIO::SR0_RXAVAIL;
! 362: ChangeInterrupt();
! 363: } else {
! 364: // 少ないので毎回前詰めしちゃえ
1.1 root 365: memmove(chan->rxbuf + 1, chan->rxbuf, chan->rxlen);
366: }
367: } else {
368: // XXX 何が読めるか
369: data = 0xff;
1.1.1.5 ! root 370: putlog(3, "Ch%s Data -> $%02x (Empty)", chan->name, data);
1.1 root 371: }
372:
373: return data;
374: }
375:
376: // データポートの書き込み
377: void
378: uPD7201Device::WriteData(struct SIO::channel *chan, uint32 data)
379: {
380: char charbuf[4];
381:
382: if (isprint((int)data)) {
383: snprintf(charbuf, sizeof(charbuf), "'%c'", data);
384: } else {
385: charbuf[0] = '\0';
386: }
1.1.1.5 ! root 387: putlog(3, "Ch%s Data <- $%02x %s", chan->name, data, charbuf);
1.1 root 388:
389: // 1文字送信
390:
391: // 今のところ内部バッファがなく常に送信できるので
392: // 必ず Tx Buffer Empty が発生する。
393: chan->sr0 |= SIO::SR0_TXEMPTY;
394:
1.1.1.5 ! root 395: // 割り込み状態を変える
! 396: ChangeInterrupt();
1.1 root 397: }
398:
1.1.1.2 root 399: // データポートの Peek
400: uint8
401: uPD7201Device::PeekData(const struct SIO::channel *chan) const
402: {
403: if (chan->rxlen > 0) {
404: // 受信バッファにデータがあれば先頭バイトが見える
405: return chan->rxbuf[0];
406: } else {
407: // 空の時は?
408: return 0xff;
409: }
410: }
411:
1.1.1.3 root 412: // TX/RX の bits/char のレジスタ値を実際の bits/char の値に変換する。
1.1 root 413: /* static */
414: const int
415: uPD7201Device::bits_per_char[] = { 5, 7, 6, 8 };
416:
417: // 1バイト受信する。
418: // 受理されれば true を返す。
419: bool
420: uPD7201Device::Rx(int ch, uint32 data)
421: {
422: struct SIO::channel *chan = &cr.chan[ch];
423:
424: // Rx Enable でなければ受け取らない?
425: if ((chan->cr3 & SIO::CR3_RX_EN) == 0) {
426: return false;
427: }
428:
1.1.1.5 ! root 429: // 1バイトでもあれば有効
! 430: chan->sr0 |= SIO::SR0_RXAVAIL;
! 431:
1.1 root 432: // バッファが一杯なら Rx Overrun Error
433: if (chan->rxlen == sizeof(chan->rxbuf)) {
434: putlog(2, "Rx Overrun");
435: chan->sr1 |= SIO::SR1_RXOVERRUN;
1.1.1.5 ! root 436: // XXX special Rx condition interrupt occurs
1.1 root 437: return false;
438: }
439:
440: // 受信
441: chan->rxbuf[chan->rxlen++] = data;
442:
1.1.1.5 ! root 443: // 割り込み状態を変更
! 444: ChangeInterrupt();
! 445:
! 446: return true;
! 447: }
! 448:
! 449: // 割り込み状態を変更
! 450: void
! 451: uPD7201Device::ChangeInterrupt()
! 452: {
! 453: uint int_asserted = 0;
! 454:
! 455: for (int ch = 0; ch < 2; ch++) {
! 456: struct SIO::channel *chan = &cr.chan[ch];
! 457:
! 458: // Rx
! 459: bool rx_avail = (chan->rxlen > 0) && chan->all_or_first;
! 460: // Special Rx
! 461: bool special = false; // XXX not yet
! 462:
! 463: bool rx_enable = (chan->cr3 & SIO::CR3_RX_EN);
! 464: bool rx_int = (rx_enable && (rx_avail || special));
! 465:
! 466: // FirstChar モードなら1文字受信割り込み後にフラグを下ろす
! 467: // (Rx 割り込み用の変数 rx_int が確定したここで行う)
! 468: if ((chan->cr1 & SIO::CR1_RXINT) == SIO::RXINT_FIRSTCHAR) {
! 469: chan->all_or_first = false;
1.1 root 470: }
1.1.1.5 ! root 471:
! 472: // XXX E/S not yet
! 473:
! 474: // Tx
! 475: bool tx_empty = (chan->sr0 & SIO::SR0_TXEMPTY);
! 476: bool tx_enable = (chan->cr1 & SIO::CR1_TXINT_EN);
! 477: // reset_txint_pend は通常 true、コマンド発行で false に落ちる。
! 478: // XXX INT DMA Mode はよく分からんのでスルー
! 479: bool tx_int = (tx_empty && tx_enable && chan->reset_txint_pend);
! 480:
! 481: // 4つの要因の合成
! 482: chan->int_asserted = 0;
! 483: chan->int_asserted |= tx_int ? SIO::INTR_TX : 0;
! 484: chan->int_asserted |= rx_int ? SIO::INTR_RX : 0;
! 485:
! 486: // 両方のチャンネル分を合成
! 487: int_asserted |= chan->int_asserted;
1.1 root 488: }
489:
1.1.1.5 ! root 490: gInterrupt->ChangeINT(this, int_asserted);
1.1 root 491: }
492:
493: // モニター
1.1.1.4 root 494: void
495: uPD7201Device::MonitorUpdate(TextScreen& monitor)
1.1 root 496: {
1.1.1.5 ! root 497: int y;
! 498:
1.1 root 499: monitor.Clear();
500: for (int i = 0; i < 2; i++) {
501: int x = 0;
1.1.1.5 ! root 502: y = i * 10;
1.1.1.4 root 503: MonitorUpdateCh(monitor, i, x, y);
1.1 root 504: }
1.1.1.5 ! root 505:
! 506: // CR2A
! 507: uint cr2a = cr.cr2a;
! 508: y = 20;
! 509: monitor.Print(0, y, "CR2A:$%02x", cr2a);
! 510: if ((cr2a & 0x80)) {
! 511: monitor.Print(9, y, TA::On, "SYNC");
! 512: } else {
! 513: monitor.Print(9, y, "RTSB");
! 514: }
! 515: monitor.Print(14, y, "----");
! 516: monitor.Print(19, y, TA::OnOff((cr2a & 0x20)), "Vect");
! 517: if ((cr2a & 0x18) == 0x10) {
! 518: monitor.Print(24, y, "IM=V4-V2");
! 519: } else {
! 520: monitor.Print(24, y, "IM=V2-V0");
! 521: }
! 522: // bit2 (Priority Select) は bit0 が 0 の時だけ意味があるようだ
! 523: if ((cr2a & 0x01) == 0) {
! 524: if ((cr2a & 0x04)) {
! 525: monitor.Print(34, y, "RxTx");
! 526: } else {
! 527: monitor.Print(34, y, "A->B");
! 528: }
! 529: }
! 530: // bit1,0 はよく分からん
! 531: monitor.Print(39, y, "INT/DMA=%d", (cr2a & 0x3));
! 532: y++;
! 533:
! 534: // CR2B
! 535: monitor.Print(0, y, "CR2B:$%02x", cr.vector);
1.1 root 536: }
537:
538: // モニター (1チャンネル)
539: void
1.1.1.4 root 540: uPD7201Device::MonitorUpdateCh(TextScreen& monitor,
541: int ch, int xbase, int ybase)
1.1 root 542: {
543: struct SIO::channel *chan = &cr.chan[ch];
544: uint cr0;
545: uint cr1;
546: uint cr3;
547: uint cr4;
548: uint cr5;
549: uint sr0;
550: uint sr1;
551: uint rxlen;
552: int x;
553: int y;
554:
1.1.1.5 ! root 555: cr0 = (chan->cr0 & ~SIO::CR0_PTR) | chan->ptr;
1.1 root 556: cr1 = chan->cr1;
557: cr3 = chan->cr3;
558: cr4 = chan->cr4;
559: cr5 = chan->cr5;
560: sr0 = chan->sr0;
561: sr1 = chan->sr1;
562: rxlen = chan->rxlen;
563:
564: // 0 1 2 3 4 5 6
565: // 012345678901234567890123456789012345678901234567890123456789012345
566: // 0123 0123 0123 0123 0123 0123 0123 0123
1.1.1.5 ! root 567: // CR0: $xx CRC=x CMD=x PTR=x
! 568: // CR1: $xx WE 0 WR RXInt=x 0 TXEn ESEn
! 569: // RXBuf: 0 --- --- --- Intr: Rx Sp Tx ES
1.1 root 570:
571: x = xbase;
572: y = ybase;
573: monitor.Print(x, y++, "Channel %s: %s", chan->name, chan->desc);
1.1.1.5 ! root 574: monitor.Print(x, y++, "CR0: $%02x", cr0);
! 575: monitor.Print(x, y++, "CR1: $%02x", cr1);
! 576: monitor.Print(x, y++, "CR3: $%02x", cr3);
! 577: monitor.Print(x, y++, "CR4: $%02x", cr4);
! 578: monitor.Print(x, y++, "CR5: $%02x", cr5);
! 579: monitor.Print(x, y++, "SR0: $%02x", sr0);
! 580: monitor.Print(x, y++, "SR1: $%02x", sr1);
! 581: monitor.Print(x, y, "RXbuf: %d", rxlen);
1.1 root 582: int i;
583: for (i = 0; i < rxlen; i++) {
1.1.1.5 ! root 584: monitor.Print(x + 9 + i * 4, y, "$%02x", chan->rxbuf[i]);
1.1 root 585: }
586: for (; i < sizeof(chan->rxbuf); i++) {
1.1.1.5 ! root 587: monitor.Print(x + 9 + i * 4, y, "---");
1.1 root 588: }
1.1.1.5 ! root 589: // 内部割り込み状態
! 590: monitor.Print(31, y, "Intr:");
! 591: monitor.Print(37, y, TA::OnOff(chan->int_asserted & SIO::INTR_RX), "Rx");
! 592: monitor.Print(40, y, TA::OnOff(chan->int_asserted & SIO::INTR_SP), "SP");
! 593: monitor.Print(43, y, TA::OnOff(chan->int_asserted & SIO::INTR_TX), "Tx");
! 594: monitor.Print(46, y, TA::OnOff(chan->int_asserted & SIO::INTR_ES), "ES");
1.1 root 595:
596: y = ybase + 1;
597: x = xbase;
598: // CR0
599: monitor.Print(x + 9, y, "CRC=%d", (cr0 >> 6));
600: static const char * const cmd_str[] = {
601: // 0123456789012345
602: "No operation",
603: "Send Abort",
604: "Reset E/S Int",
605: "Channel Reset",
606: "Enable IntNextCh",
607: "Reset TxIntPend",
608: "Error Reset",
609: "End of Interrupt",
610: };
611: uint cmd = (cr0 >> 3) & 7;
612: monitor.Print(x + 19, y, "CMD=%d(%s)", cmd, cmd_str[cmd]);
613: monitor.Print(x + 43, y, "PTR=%d", (cr0 & 7));
614: y++;
615:
616: // CR1
617: static const char * const cr1_str[] = {
618: "WaEn", "----", "WaRx", "", "", "----", "TxIE", "ESEn"
619: };
1.1.1.4 root 620: MonitorReg(monitor, x + 9, y, cr1, cr1_str);
1.1.1.5 ! root 621: static const char * const rxint_str[] = {
! 622: // 2345678
! 623: "=SpOnly",
! 624: "=AllChr",
! 625: "=1stChr",
! 626: "Disable",
! 627: };
! 628: monitor.Print(x + 24, y, "RI%s", rxint_str[(cr1 >> 3) & 3]);
1.1 root 629: y++;
630:
631: // CR3
632: static const char * const cr3_str[] = {
633: "", "", "AuEn", "----", "----", "----", "----", "RXEn"
634: };
1.1.1.4 root 635: MonitorReg(monitor, x + 9, y, cr3, cr3_str);
1.1 root 636: monitor.Print(x + 9, y, "RXbits=%d", 5 + ((cr3 >> 6) & 3));
637: y++;
638:
639: // CR4
640: static const char * const cr4_str[] = {
641: "", "", "", "", "", "", "PaEv", "PaEn"
642: };
1.1.1.4 root 643: MonitorReg(monitor, x + 9, y, cr4, cr4_str);
1.1 root 644:
645: static const char * const clkrate_str[] = {
646: "1", "16", "32", "64"
647: };
648: monitor.Print(x + 9, y, "Rate=x%s", clkrate_str[(cr4 >> 6) & 3]);
649: static const char * const syncmode_str[] = {
650: "Mono", "Bi", "HDLC", "Ext"
651: };
652: monitor.Print(x + 19, y, "Sync=%s", syncmode_str[(cr4 >> 4) & 3]);
653: static const char * const stopbit_str[] = {
654: "Sync", "1", "1.5", "2"
655: };
656: monitor.Print(x + 29, y, "Stop=%s", stopbit_str[(cr4 >> 2) & 3]);
657: y++;
658:
659: // CR5
660: static const char * const cr5_str[] = {
661: "DTR", "", "", "SBrk", "TXEn", "CRC", "!RTS", "TCEn"
662: };
1.1.1.4 root 663: MonitorReg(monitor, x + 9, y, cr5, cr5_str);
1.1 root 664: monitor.Print(x + 14, y, "TXbits=%d", 5 + ((cr5 >> 5) & 3));
665: y++;
666:
667: // SR0
668: static const char * const sr0_str[] = {
669: "BrAb", "TxUn", "CTS", "SYNC", "DCD", "TxEm", "IntP", "RxAv"
670: };
1.1.1.4 root 671: MonitorReg(monitor, x + 9, y, sr0, sr0_str);
1.1.1.5 ! root 672: // SR0 の bit1 (Interrupt Pending) は SR0A のみ。SR0B では 0。
! 673: if (ch == 1) {
! 674: monitor.Print(39, y, "----");
! 675: }
1.1 root 676: y++;
677:
678: // SR1
679: static const char * const sr1_str[] = {
680: "EOF", "CRCE", "RxOv", "PaEr", "", "", "", "Sent"
681: };
1.1.1.4 root 682: MonitorReg(monitor, x + 9, y, sr1, sr1_str);
1.1 root 683: monitor.Print(x + 29, y, "ResidueCode=%d", (sr1 >> 1) & 7);
684: y++;
685: }
686:
687: // レジスタをビットごとに表示する。MonitorUpdate の下請け。
688: void
1.1.1.4 root 689: uPD7201Device::MonitorReg(TextScreen& monitor,
690: int x, int y, uint32 reg, const char * const *names)
1.1 root 691: {
692: for (int i = 0; i < 8; i++) {
693: if (strcmp(names[i], "----") == 0) {
1.1.1.3 root 694: monitor.Puts(x + i * 5, y, TA::Disable, names[i]);
1.1 root 695: } else {
696: bool b = reg & (1 << (7 - i));
1.1.1.3 root 697: monitor.Puts(x + i * 5, y, TA::OnOff(b), names[i]);
1.1 root 698: }
699: }
700: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.