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