|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2023 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: //
8: // Nereid イーサネット (RTL8019AS)
9: //
10:
11: #pragma once
12:
13: #include "ethernet.h"
14: #include "event.h"
15: #include "hostnet.h"
16: #include "message.h"
17:
18: class InterruptDevice;
19:
20: struct RTL8019
21: {
22: // レジスタアドレスは $0-$f までの16個 x Page 0-3 の4ページなので、
23: // ここでのレジスタ番号は全部リニアに並べて表現する。
24: // Page0 はほとんどが Read/Write でレジスタが異なるが、
25: // それについてはここでは区別せず、Read/Write のコード中で使い分ける。
26:
27: // Page0 R(/W)
28: static const uint32 CR = 0x00; // RW: Command Register
29: static const uint32 CLDA0 = 0x01; // R-: Current Local DMA Address Regs
30: static const uint32 CLDA1 = 0x02; // R-: Current Local DMA Address Regs
31: static const uint32 BNRY = 0x03; // RW: Boundary Register
32: static const uint32 TSR = 0x04; // R-: Transmit Status Register
33: static const uint32 NCR = 0x05; // R-: Number of Collisions Register
34: static const uint32 FIFO = 0x06; // R-: First In First Out Register
35: static const uint32 ISR = 0x07; // RW: Interrupt Status Register
36: static const uint32 CRDA0 = 0x08; // R-: Current Remote DMA Address Regs
37: static const uint32 CRDA1 = 0x09; // R-: Current Remote DMA Address Regs
38: static const uint32 ID0 = 0x0a; // R-: 8019ID0
39: static const uint32 ID1 = 0x0b; // R-: 8019ID1
40: static const uint32 RSR = 0x0c; // R-: Receive Configuration Register
41: static const uint32 CNTR0 = 0x0d; // R-: Frame Align.Error Tally Counter
42: static const uint32 CNTR1 = 0x0e; // R-: CRC Error Tally Counter Reg.
43: static const uint32 CNTR2 = 0x0f; // R-: Missed Pakcet Tally Counter Reg.
44:
45: // Page0 W
46: static const uint32 PSTART = 0x01; // -W: Page Start Register
47: static const uint32 PSTOP = 0x02; // -W: Page Stop Register
48: static const uint32 TPSR = 0x04; // -W: Transmit Page Start Register
49: static const uint32 TBCR0 = 0x05; // -W: Transmit Byte Counter Registers
50: static const uint32 TBCR1 = 0x06; // -W: Transmit Byte Counter Registers
51: static const uint32 RSAR0 = 0x08; // -W: Remote Start Address Regs
52: static const uint32 RSAR1 = 0x09; // -W: Remote Start Address Regs
53: static const uint32 RBCR0 = 0x0a; // -W: Remote Byte Count Registers
54: static const uint32 RBCR1 = 0x0b; // -W: Remote Byte Count Registers
55: static const uint32 RCR = 0x0c; // -W: Receive Configuration Register
56: static const uint32 TCR = 0x0d; // -W: Transmit Configuration Register
57: static const uint32 DCR = 0x0e; // -W: Data Configuration Register
58: static const uint32 IMR = 0x0f; // -W: Interrupt Mask Register
59:
60: // Page 1 R/W
61: static const uint32 CR_1 = 0x10;
62: static const uint32 PAR0 = 0x11; // RW: Physical Address Registers
63: static const uint32 PAR1 = 0x12; // RW: Physical Address Registers
64: static const uint32 PAR2 = 0x13; // RW: Physical Address Registers
65: static const uint32 PAR3 = 0x14; // RW: Physical Address Registers
66: static const uint32 PAR4 = 0x15; // RW: Physical Address Registers
67: static const uint32 PAR5 = 0x16; // RW: Physical Address Registers
68: static const uint32 CURR = 0x17; // RW: Current Page Register
69: static const uint32 MAR0 = 0x18; // RW: Multicast Address Registers
70: static const uint32 MAR1 = 0x19; // RW: Multicast Address Registers
71: static const uint32 MAR2 = 0x1a; // RW: Multicast Address Registers
72: static const uint32 MAR3 = 0x1b; // RW: Multicast Address Registers
73: static const uint32 MAR4 = 0x1c; // RW: Multicast Address Registers
74: static const uint32 MAR5 = 0x1d; // RW: Multicast Address Registers
75: static const uint32 MAR6 = 0x1e; // RW: Multicast Address Registers
76: static const uint32 MAR7 = 0x1f; // RW: Multicast Address Registers
77:
78: // Page2 R
79: static const uint32 CR_2 = 0x20;
80: static const uint32 PSTART_2= 0x21;
81: static const uint32 PSTOP_2 = 0x22;
82: static const uint32 TPSR_2 = 0x24;
83: static const uint32 RCR_2 = 0x2c;
84: static const uint32 TCR_2 = 0x2d;
85: static const uint32 DCR_2 = 0x2e;
86: static const uint32 IMR_2 = 0x2f;
87:
88: // Page3 R/W
89: static const uint32 CR_3 = 0x30;
90: static const uint32 CR9346 = 0x31; // RW: 9346 Command Register
91: static const uint32 BPAGE = 0x32; // RW: BROM Page Register
92: static const uint32 CONFIG0 = 0x33; // R-: RTL8019AS Config. Register 0
93: static const uint32 CONFIG1 = 0x34; // RW: RTL8019AS Config. Register 1
94: static const uint32 CONFIG2 = 0x35; // RW: RTL8019AS Config. Register 2
95: static const uint32 CONFIG3 = 0x36; // RW: RTL8019AS Config. Register 3
96: static const uint32 TEST = 0x37; // -W:
97: static const uint32 CSNSAV = 0x38; // R-: CSN Save Register (For PnP)
98: static const uint32 HLTCLK = 0x39; // -W: Halt Clock Register
99: static const uint32 INTR = 0x3b; // R-: Interrupt Register
100: static const uint32 FMWP = 0x3c; // -W: Flush Memory Write Protect Reg.
101: static const uint32 CONFIG4 = 0x3d; // R-: RTL8019AS Config. Register 4
102:
103: // 7 6 5 4 3 2 1 0
104: // +-----+-----+-----+-----+-----+-----+-----+-----+
105: // CR | PS | RD | TXP | STA | STP |
106: // +-----+-----+-----+-----+-----+-----+-----+-----+
107: static const uint32 CR_RD_READ = 0x08;
108: static const uint32 CR_RD_WRITE = 0x10;
109: static const uint32 CR_RD_SEND = 0x18;
110: static const uint32 CR_TXP = 0x04;
111: static const uint32 CR_STA = 0x02;
112: static const uint32 CR_STP = 0x01;
113:
114: // 7 6 5 4 3 2 1 0
115: // +-----+-----+-----+-----+-----+-----+-----+-----+
116: // TSR | OWC | CDH | 0 | CRS | ABT | COL | 1 | PTX |
117: // +-----+-----+-----+-----+-----+-----+-----+-----+
118: static const uint32 TSR_OWC = 0x80; // Out of Window Collision
119: static const uint32 TSR_CDH = 0x40; // CD Heartbeat
120: static const uint32 TSR_CRS = 0x10; // Carrier Sense lost bit
121: static const uint32 TSR_ABT = 0x08; // Abort TX due to excessive coll.
122: static const uint32 TSR_COL = 0x04; // TX collied with other station
123: static const uint32 TSR_PTX = 0x01; // TX completes with no errors
124:
125: // 7 6 5 4 3 2 1 0
126: // +-----+-----+-----+-----+-----+-----+-----+-----+
127: // ISR | RST | RDC | CNT | OVW | TXE | RXE | PTX | PRX |
128: // +-----+-----+-----+-----+-----+-----+-----+-----+
129: static const uint32 ISR_RST = 0x80; // Enter reset state
130: static const uint32 ISR_RDC = 0x40; // Remote DMA operation completed
131: static const uint32 ISR_CNT = 0x20; //
132: static const uint32 ISR_OVW = 0x10; // RX buffer overflow
133: static const uint32 ISR_TXE = 0x08; // TX Error
134: static const uint32 ISR_RXE = 0x04; // RX Error
135: static const uint32 ISR_PTX = 0x02; // Packet transmitted with no errors
136: static const uint32 ISR_PRX = 0x01; // Packet received with no errors
137:
138: // 7 6 5 4 3 2 1 0
139: // +-----+-----+-----+-----+-----+-----+-----+-----+
140: // RSR | DFR | DIS | PHY | MPA | 0 | FAE | CRC | PRX |
141: // +-----+-----+-----+-----+-----+-----+-----+-----+
142: static const uint32 RSR_DFR = 0x80; // Deffering
143: static const uint32 RSR_DIS = 0x40; // Receiver Disabled
144: static const uint32 RSR_PHY = 0x20; // Recv'd packet is multi/broadcast
145: static const uint32 RSR_MPA = 0x10; // Missed Packet
146: static const uint32 RSR_FAE = 0x04; // Frame Alignment Error
147: static const uint32 RSR_CRC = 0x02; // CRC Error
148: static const uint32 RSR_PRX = 0x01; // Packet received with no errors
149:
150: // 7 6 5 4 3 2 1 0
151: // +-----+-----+-----+-----+-----+-----+-----+-----+
152: // RCR | 1 | 1 | MON | PRO | AM | AB | AR | SEP |
153: // +-----+-----+-----+-----+-----+-----+-----+-----+
154: static const uint32 RCR_MON = 0x20; // Monitor mode
155: static const uint32 RCR_PRO = 0x10; // Promisc.
156: static const uint32 RCR_AM = 0x08; // Accept multicast dest address
157: static const uint32 RCR_AB = 0x04; // Accept broadcast dest address
158: static const uint32 RCR_AR = 0x02; // Accept <64bytes
159: static const uint32 RCR_SEP = 0x01; // Accept packet with recv errors
160:
161: // 7 6 5 4 3 2 1 0
162: // +-----+-----+-----+-----+-----+-----+-----+-----+
163: // TCR | 1 | 1 | 1 |OFST | ATD | LB | CRC |
164: // +-----+-----+-----+-----+-----+-----+-----+-----+
165: static const uint32 TCR_OFST = 0x10; // Collision Offset Enable
166: static const uint32 TCR_ATD = 0x08; // Auto Transmit Disable
167: static const uint32 TCR_LB_MASK = 0x06; // Loopback mode
168: static const uint32 TCR_CRC = 0x01; // Don't append CRC
169:
170: // 7 6 5 4 3 2 1 0
171: // +-----+-----+-----+-----+-----+-----+-----+-----+
172: // DCR | 1 | FT | ARM | LS | LAS | BOS | WTS |
173: // +-----+-----+-----+-----+-----+-----+-----+-----+
174: static const uint32 DCR_FT_MASK = 0x60; // FIFO threshold
175: static const uint32 DCR_ARM = 0x10; // Auto initialize Remote
176: static const uint32 DCR_LS = 0x08; // Loopback Select
177: static const uint32 DCR_LAS = 0x04; // (32bit DMA not supported by NIC)
178: static const uint32 DCR_BOS = 0x02; // Byte Order Select (Not Impl?)
179: static const uint32 DCR_WTS = 0x01; // Word Transfer Select
180:
181: // 7 6 5 4 3 2 1 0
182: // +-----+-----+-----+-----+-----+-----+-----+-----+
183: // 9346CR | EEM | not used |EECS |EESK |EEDI |EEDO |
184: // +-----+-----+-----+-----+-----+-----+-----+-----+
185: static const uint32 CR9346_EEM_MASK = 0xc0; // RTL8019AS operating mode
186:
187: // 7 6 5 4 3 2 1 0
188: // +-----+-----+-----+-----+-----+-----+-----+-----+
189: // CONFIG0 | VERID | AUI |PNPJP| JP | BNC | 0 | 0 |
190: // +-----+-----+-----+-----+-----+-----+-----+-----+
191: static const uint32 CONFIG0_VERID_MASK = 0xc0;
192: static const uint32 CONFIG0_AUI = 0x20;
193: static const uint32 CONFIG0_PNPJP = 0x10;
194: static const uint32 CONFIG0_JP = 0x08;
195: static const uint32 CONFIG0_BNC = 0x04;
196:
197: // 7 6 5 4 3 2 1 0
198: // +-----+-----+-----+-----+-----+-----+-----+-----+
199: // CONFIG1 |IRQEN| IRQS | IOS |
200: // +-----+-----+-----+-----+-----+-----+-----+-----+
201: static const uint32 CONFIG1_IRQEN = 0x80;
202: static const uint32 CONFIG1_IRQS_MASK = 0x70;
203: static const uint32 CONFIG1_IOS_MASK = 0x0f;
204:
205: // 7 6 5 4 3 2 1 0
206: // +-----+-----+-----+-----+-----+-----+-----+-----+
207: // CONFIG2 | PL |BSELB| BS |
208: // +-----+-----+-----+-----+-----+-----+-----+-----+
209: static const uint32 CONFIG2_PL_MASK = 0xc0;
210: static const uint32 CONFIG2_BSELB = 0x20;
211: static const uint32 CONFIG2_BS = 0x1f;
212:
213: // 7 6 5 4 3 2 1 0
214: // +-----+-----+-----+-----+-----+-----+-----+-----+
215: // CONFIG3 | PNP |FUDUP|LEDS1|LEDS0| 0 |SLEEP|PWRDN|ACTB |
216: // +-----+-----+-----+-----+-----+-----+-----+-----+
217: static const uint32 CONFIG3_PNP = 0x80;
218: static const uint32 CONFIG3_FUDUP = 0x40;
219: static const uint32 CONFIG3_LEDS1 = 0x20;
220: static const uint32 CONFIG3_LEDS0 = 0x10;
221: static const uint32 CONFIG3_SLEEP = 0x04;
222: static const uint32 CONFIG3_PWRDN = 0x02;
223: static const uint32 CONFIG3_ACTB = 0x01;
224:
225: // 7 6 5 4 3 2 1 0
226: // +-----+-----+-----+-----+-----+-----+-----+-----+
227: // CONFIG4 | - | - | - | - | - | - | - |IOMS |
228: // +-----+-----+-----+-----+-----+-----+-----+-----+
229: static const uint32 CONFIG4_IOMS = 0x01;
230:
231: // メディアタイプ (CONFIG2)
232: enum {
233: MediaType_10BaseT_Auto = 0,
234: MediaType_10BaseT = 1,
235: MediaType_10Base5 = 2,
236: MediaType_10Base2 = 3,
237: };
238: };
239:
1.1.1.5 ! root 240: class RTL8019ASDevice : public EthernetDevice, public IHWAddrFilter
1.1 root 241: {
242: using inherited = EthernetDevice;
243:
244: // 動作状態 (数値比較も行うことに注意)
245: enum class State {
246: Normal = 0, // 送受信可能
247: Stop = 1, // STP
248: StopInProgress = 2, // STP へ移行中 (処理中の送受信のみ継続)
249: };
250:
251: // DMA 状態?
252: enum class DMAMode {
253: NotAllowed = 0,
254: RemoteRead = 1,
255: RemoteWrite = 2,
256: SendPacket = 3,
257: Complete = 4,
258: };
259:
260: public:
1.1.1.3 root 261: RTL8019ASDevice(uint n_, int vector_);
1.1.1.2 root 262: ~RTL8019ASDevice() override;
1.1 root 263:
264: bool Init() override;
265: void ResetHard(bool poweron) override;
266:
1.1.1.3 root 267: busdata Read(busaddr addr) override;
268: busdata Write(busaddr addr, uint32 data) override;
269: busdata Peek1(uint32 addr) override;
1.1 root 270:
1.1.1.2 root 271: busdata InterruptAcknowledge();
1.1 root 272:
1.1.1.5 ! root 273: int HWAddrFilter(const MacAddr& dstaddr) const override;
! 274:
1.1 root 275: private:
276: static inline uint32 Decoder(uint32 addr);
277:
278: uint32 ReadReg(uint32 rn);
279: uint32 ReadDMA8(uint32 a0);
280: uint32 ReadDMA16();
1.1.1.3 root 281: void WriteReg(uint32 rn, uint32 data);
1.1 root 282: void WriteCR(uint32 data);
283: void WritePSTART(uint32 data);
284: void WritePSTOP(uint32 data);
285: void WriteBNRY(uint32 data);
286: void WriteTPSR(uint32 data);
287: void WriteTBCR0(uint32 data);
288: void WriteTBCR1(uint32 data);
289: void WriteISR(uint32 data);
290: void WriteRSAR0(uint32 data);
291: void WriteRSAR1(uint32 data);
292: void WriteRBCR0(uint32 data);
293: void WriteRBCR1(uint32 data);
294: void WriteRCR(uint32 data);
295: void WriteTCR(uint32 data);
296: void WriteDCR(uint32 data);
297: void WriteIMR(uint32 data);
1.1.1.3 root 298: void WritePAR(uint n, uint32 data);
1.1 root 299: void WriteCURR(uint32 data);
1.1.1.3 root 300: void WriteMAR(uint n, uint32 data);
1.1 root 301: void Write9346CR(uint32 data);
302: void WriteCONFIG0(uint32 data);
303: void WriteCONFIG1(uint32 data);
304: void WriteCONFIG2(uint32 data);
305: void WriteCONFIG3(uint32 data);
306: void WriteDMA8(uint32 data);
307: void WriteDMA16(uint32 data);
308: uint32 PeekReg(uint32 rn) const;
309: uint32 PeekCR() const;
310: uint32 PeekCLDA() const;
311: uint32 PeekBNRY() const;
312: uint32 PeekTSR() const;
313: uint32 PeekNCR() const;
314: uint32 PeekFIFO() const;
315: uint32 PeekISR() const;
316: uint32 PeekCRDA() const;
317: uint32 Peek8019ID0() const;
318: uint32 Peek8019ID1() const;
319: uint32 PeekRSR() const;
320: uint32 PeekCNTR(int n) const;
321: uint32 PeekPAR(int n) const;
322: uint32 PeekCURR() const;
323: uint32 PeekMAR(int n) const;
324: uint32 PeekPSTART() const;
325: uint32 PeekPSTOP() const;
326: uint32 PeekTPSR() const;
327: uint32 PeekRCR() const;
328: uint32 PeekTCR() const;
329: uint32 PeekDCR() const;
330: uint32 PeekIMR() const;
331: uint32 Peek9346CR() const;
332: uint32 PeekBPAGE() const;
333: uint32 PeekCONFIG0() const;
334: uint32 PeekCONFIG1() const;
335: uint32 PeekCONFIG2() const;
336: uint32 PeekCONFIG3() const;
337: uint32 PeekCONFIG4() const;
338: uint32 PeekCSNSAV() const;
339: uint32 PeekReg39() const;
340: uint32 PeekINTR() const;
341: uint32 PeekDMA(uint32 a0) const;
342:
343: DECLARE_MONITOR_CALLBACK(MonitorUpdate);
344: void MonitorReg(TextScreen&, int, int, uint32, const char * const *names);
345:
346: void Reset();
347: void ChangeInterrupt();
348:
349: // DMA 処理の下請け
350: void ReadDMAlog(uint32 addr, uint32 data, int width);
351: void PostDMA();
352:
353: // 内蔵空間アクセス
354: inline uint32 ReadPROM(uint32 addr) const;
355: inline uint32 ReadRAM(uint32 addr) const;
356: inline void WriteRAM(uint32 addr, uint32 data);
357:
358: // 状態
359: bool IsStopOrInProgress() const;
360: void ChangeState(State newstate);
361:
362: // 送信
363: void Transmit();
364: void TXEvent(Event&);
365: // 受信
1.1.1.2 root 366: void RxMessage(MessageID msgid, uint32 arg);
1.1 root 367: void RXEvent(Event&);
1.1.1.3 root 368: void RXHead();
369: void RXCopy(Event&, uint remain);
1.1 root 370: void RXDone(Event&);
371:
372: void TXLedEvent(Event&);
373: void RXLedEvent(Event&);
374:
375: void IncCounter(int n);
376:
377: // レジスタ名を返す
378: static std::string RegNameR(int rn);
379: static std::string RegNameW(int rn);
380: static const char *GetDMAName(uint32);
381:
382: // 動作状態
383: // ハードウェアリセット(解除?)後、STA が発行されるまではリセット状態。
384: // STP が発行されたら、仕掛りの送受信を終えたところでリセット状態に入る。
385: // リセット状態に入ると ISR:RST が立つ。
386: // このリセット状態をここでは Stop 状態と呼ぶ。
387: State state {};
388: // 送信処理中なら true
389: // (受信処理中の方は rx_packet.length != 0 で判定する)
390: bool tx_in_progress {};
391:
392: // CR: ページ番号 (をあらかじめオフセットしたもの)
393: uint32 pagesel {};
394:
395: // CR_RD: DMA 状態?
396: DMAMode dmamode {};
397:
398: bool cr_sta {};
399:
400: // 割り込みフラグ (bit7 は 0 にすること)
401: uint32 intr_stat {};
402: // 割り込みマスク (bit7 は 0 にすること)
403: uint32 intr_mask {};
404: // 割り込みベクタ (NereidBoardDevice から渡される)
1.1.1.2 root 405: uint32 intr_vector {};
1.1 root 406:
407: uint32 tsr {};
408: uint32 rsr {}; // DIS 以外のビットを保持
409:
410: // RCR: モニタモード
411: bool monitor_mode {};
412: bool promisc_mode {};
413: bool accept_mcast {};
414: bool accept_bcast {};
415: bool accept_short {};
416: bool accept_error {};
417:
418: // TCR
419: uint32 tcr {};
420:
421: // DCR
422: bool word_transfer {};
423: uint32 dcr {}; // それ以外のビット
424:
425: // 折り返しを計算しなくて済むように uint16 にしておく。
426: // またレジスタイメージがバイト単位かページ単位かに関わらず、
427: // すべてバイト単位で統一。
428:
429: uint16 remote_addr {}; // RSAR/CRDA: 現在のアクセス位置
430: uint16 remote_count {}; // RBCR: 残り転送バイト数
431: uint16 remote_start_addr {}; // DMA 開始時の位置 (ログ用)
432: uint16 remote_start_count {}; // DMA 開始時の残り転送バイト数 (ログ用)
433:
434: uint16 transmit_page_start_addr {}; // TPSR
435: uint16 transmit_byte_count {}; // TBCR
436:
437: uint16 pstart_addr {}; // PSTART
438: uint16 pstop_addr {}; // PSTOP
439: uint16 boundary_addr {}; // BNRY
440: uint16 current_page_addr {}; // CURR: 受信開始位置
441: uint16 local_addr {}; // CLDA: 書き込み位置
442: uint16 next_page_addr {}; // 次パケットの受信開始位置
443:
1.1.1.5 ! root 444: MacAddr par {};
! 445: uint64 mar {};
1.1 root 446: std::array<uint8, 3> error_counter {};
447:
448: // 9346CR
449: bool config_write_enable {};
450:
451: // CONFIG
452: uint32 verid {};
453: bool irq_enable {};
454: uint32 mediatype {};
455: bool brom_force_disable {};
456: uint32 config3 {};
457:
458: // バッファ (16KB 固定)
459: std::array<uint8, 16384> buffer {};
460:
461: // PROM (実質 16 バイト)
462: std::array<uint8, 16> prom {};
463:
464: NetPacket tx_packet {};
465: NetPacket rx_packet {};
466:
467: // LED (true で点灯)
468: bool tx_led {};
469: bool rx_led {};
470:
1.1.1.4 root 471: Monitor *monitor {};
1.1 root 472:
473: Event tx_event { this };
474: Event rx_event { this };
475: Event txled_event { this };
476: Event rxled_event { this };
477:
478: InterruptDevice *interrupt {};
479:
480: static const char * const regnames[];
481: };
482:
483: static inline RTL8019ASDevice *GetRTL8019ASDevice(int n) {
484: return Object::GetObject<RTL8019ASDevice>(OBJ_ETHERNET(n));
485: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.