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