|
|
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:
1.1.1.6 root 7: //
8: // Ethernet 基本クラス
9: //
10:
1.1.1.10 root 11: #if !defined(SELFTEST)
1.1 root 12: #include "ethernet.h"
1.1.1.7 root 13: #include "config.h"
1.1.1.6 root 14: #include "hostnet.h"
15: #include "scheduler.h"
1.1 root 16:
17: // コンストラクタ
1.1.1.9 root 18: EthernetDevice::EthernetDevice(uint objid_)
1.1.1.8 root 19: : inherited(objid_)
1.1 root 20: {
21: }
22:
23: // デストラクタ
24: EthernetDevice::~EthernetDevice()
25: {
1.1.1.6 root 26: if ((bool)hostnet) {
1.1.1.12! root 27: hostnet->ResetRxCallback();
1.1.1.6 root 28: }
1.1 root 29: }
30:
31: // 動的なコンストラクション
32: bool
33: EthernetDevice::Create()
34: {
1.1.1.12! root 35: // ホストドライバを作成してこのデバイスと紐付ける。
! 36: // ポート名は継承先ごとに Init() で設定している。
1.1.1.8 root 37: int n = GetId() - OBJ_ETHERNET0;
1.1.1.11 root 38: try {
1.1.1.12! root 39: hostnet.reset(new HostNetDevice(this, n, ""));
1.1.1.11 root 40: } catch (...) { }
41: if ((bool)hostnet == false) {
42: warnx("Failed to initialize HostNetDevice(%u) at %s", n, __method__);
43: return false;
44: }
1.1 root 45:
1.1.1.12! root 46: auto func = ToDeviceCallback(&EthernetDevice::HostRxCallback);
! 47: hostnet->SetRxCallback(func, 0);
1.1 root 48:
49: return true;
50: }
51:
1.1.1.6 root 52: // これは Host スレッドから呼ばれる
53: void
1.1.1.12! root 54: EthernetDevice::HostRxCallback(uint32 dummy)
1.1.1.5 root 55: {
1.1.1.6 root 56: // スレッドを超えるためにメッセージを投げる
1.1.1.8 root 57: int n = GetId() - OBJ_ETHERNET0;
58: scheduler->SendMessage(MessageID::HOSTNET_RX(n));
1.1.1.7 root 59: }
60:
61: // 設定ファイルから MAC アドレスを読み込む。
62: // MAC アドレスを保持するデバイスが呼び出すこと。MAC アドレスを保持する
63: // デバイスがイーサネットデバイスとは限らず、例えば LANCE を採用している
64: // 機種ではたいてい ROM か誰かが MAC アドレスを持っている。
65: //
66: // 引数 accept_rom が true なら、設定 ethernet-macaddr=rom を許可する。
67: // これは (お手持ちの実機) ROM イメージが MAC アドレスを保持しているため、
68: // 指定(や生成)不要なケースで指定できる (prom.cpp 参照)。
69: // 引数 accept_rom が false で、設定値に "rom" が指定されるとエラーにする。
70: //
71: // "rom" が指定されて許可されている場合 mac は触らず true を返す。
72: // MAC アドレスが指定されているか自動生成したかで取得できれば mac に格納して
73: // true を返す。それ以外の場合は、エラーメッセージを表示して false を返す。
74: /*static*/ bool
1.1.1.10 root 75: EthernetDevice::GetConfigMacAddr(uint n, MacAddr *mac, bool accept_rom)
1.1.1.7 root 76: {
1.1.1.9 root 77: std::string keyname = string_format("ethernet%u-macaddr", n);
1.1.1.8 root 78: const ConfigItem& item = gConfig->Find(keyname);
1.1.1.7 root 79: const std::string& val = item.AsString();
80:
81: if (val == "rom") {
82: // ROM に書いてあるのを使う。
83: if (accept_rom) {
84: return true;
85: } else {
86: item.Err("\"rom\" cannot be specified in this vmtype");
87: return false;
88: }
89: } else {
90: if (val == "auto") {
91: // 自動生成。
92: // 出来れば生成したのを覚えといて、次からそれを使いたい。
93: if (0) {
94: } else {
95: mac->Generate();
96: }
97: } else {
98: // ユーザ指定
99: if (mac->FromString(val) == false) {
100: item.Err("Invalid MAC address");
101: return false;
102: }
103: }
104: }
105:
106: return true;
1.1.1.5 root 107: }
1.1.1.10 root 108:
109: #endif // !SELFTEST
110:
111: // CRC32 を計算する。
112: //
113: // CRC と言ってもおそらく5つのパラメータによって定まる亜種が多数あるが、
114: // Ethernet で使われる CRC32 はおそらく以下のもの。
115: // 初期値: 0xffffffff
116: // 多項式: 0x04c11db6
117: // RefIn : false
118: // RefOut: false (出力をビットリバースしない)
119: // XorOut: false (出力を XOR しない)
120: //
121: // NetBSD の src/sys/net/if_ethersubr.c にある ether_crc32_be() がこれと同じ。
122: //
123: // その隣にある ether_crc32_le() は
124: // 初期値: 0xffffffff
125: // 多項式: 0xedb88320
126: // RefIn : true
127: // RefOut: false (出力をビットリバースしない)
128: // XorOut: false (出力を XOR しない)
129: // というパラメータだが、RefIn と多項式のビットが反転しているだけなので
130: // 結果をビットリバースすれば同じものになる。
131: //
132: // ちなみに ether_crc32_* の_le, _be はエンディアンではなく、どっち向きに
133: // 処理するかを示しており、名前が紛らわしい。
134: /*static*/ uint32
135: EthernetDevice::CRC32(const uint8 *buf, size_t buflen)
136: {
137: static const uint32 CRC_POLY = 0x04c11db6;
138: uint32 crc;
139: uint32 cy;
140:
141: crc = 0xffffffff;
142: for (size_t i = 0; i < buflen; i++) {
1.1.1.11 root 143: uint32 s = buf[i];
1.1.1.10 root 144: for (size_t j = 0; j < 8; j++) {
145: cy = ((crc & 0x80000000U) ? 0x01 : 0x00) ^ (s & 0x01);
146: crc <<= 1;
147: s >>= 1;
148: if (cy) {
149: crc = (crc ^ CRC_POLY) | cy;
150: }
151: }
152: }
153:
154: return crc;
155: }
156:
157: // MAC アドレスの CRC32 を計算する限定版。
158: // 6バイトが uint64 にリトルエンディアン的に格納されていると分かっている。
159: /*static*/ uint32
160: EthernetDevice::CRC32(const MacAddr& mac)
161: {
162: static const uint32 CRC_POLY = 0x04c11db6;
163: uint32 crc;
164: uint64 s = mac.Get();
165:
166: crc = 0xffffffff;
167: for (size_t i = 0; i < mac.size() * 8; i++) {
1.1.1.11 root 168: uint32 cy = ((crc & 0x80000000U) ? 0x01 : 0x00) ^ (s & 0x01);
1.1.1.10 root 169: crc <<= 1;
170: s >>= 1;
171: if (cy) {
172: crc = (crc ^ CRC_POLY) | cy;
173: }
174: }
175:
176: return crc;
177: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.