NetBSDでEtherswitch

MarvellのORIONのネットワークドライバは以下にあります。

sys/dev/marvell/if_mvgbe.c

sys/dev/marvell/の下にはごちゃまぜでmarvellのいろいろな機能のチップのコードが入っていて、こういうdevの下のディレクトリはFreeBSDでは見た事なくて斬新です。^ ^;

ターゲットのモジュールはmiiでスイッチの88E6131に接続されているようです。もちろんサポートが無いのでukphyとして認識されます。

![SW2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/7502eb55-b013-5617-64ba-be3eeb7ab04b.png)

88E6131は8ポートのようで、内蔵PHYが3で後はMACだけなのかもしれません
。ターゲットは外付けPHYを2個つけて、あと一つのMACをSOCに接続しているものと思われます。初期のgigaのスイッチなので構成が変則的です。

phy関係は

sys/dev/mii/

にあります。

調べてみると、ここにあるmvphy.cがMarvellのスイッチの88E6060のコードのようです。

一般的なスイッチはPHYと同じインターフェースで、OS側の新しい作り込みが必要ないようになっています。

mdioで32のアドレスについて32のアドレスが読めます。アドレスを0からスキャンしてPHYのIDを確認して対応するPHYのコードをattachします。

88E6060は100の初期のスイッチでFON2201などで使われています。6060は.1qではなくて原始的なスイッチでこの後の6065が.1qになっています。

6060はいろいろなモジュールで使われていましたが、6065はそれほど多く見かけません。これは6065が出来た頃にはすでにgigaのスイッチが出てきていてMarvellが主力をgigaの方にシフトしていたのからかもしれません。

6060と6065はマイナーチェンジのように見えますが、大きく違っていて6065はこれ以降(gigaも含めて)のアーキテクチャの基本となります。

とりあえずこのコードをベースにいじるのが良さそうです。

まずはほんとに88E6131がいるか調べてみます。

```diff
diff --git a/sys/dev/marvell/if_mvgbe.c b/sys/dev/marvell/if_mvgbe.c
index c54c7c446b7..934ee8c1b3f 100644
--- a/sys/dev/marvell/if_mvgbe.c
+++ b/sys/dev/marvell/if_mvgbe.c
@@ -896,6 +896,9 @@ mvgbe_attach(device_t parent, device_t self, void *aux)
        mii->mii_readreg = mvgbec_miibus_readreg;
        mii->mii_writereg = mvgbec_miibus_writereg;
        mii->mii_statchg = mvgbec_miibus_statchg;
+uint16_t pid;
+mvgbec_miibus_readreg(self, 0x10, 3, &pid);
+printf("MORIMORI PID %x\n", pid);
 
        sc->sc_ethercom.ec_mii = mii;
        ifmedia_init(&mii->mii_media, 0, mvgbe_mediachange, mvgbe_mediastatus);
```

実行してみると

```
[   1.0000000] MORIMORI PID 1066
```

Switch Identifier Register
Offset: 0x03 or Decimal 3

|Bits|Field|Type|Description|
|:--|:--|:--|:--|
|15:4|ProductNum|RO|Product Number or identifier.|
|3:0|Rev|RO|Revision Identifier.|

Marvellのオープンソース(dsa)で定義されているPORT_SWITCH_ID_6131_B2のID(0x1066)が返ってくるのでちゃんと接続されてます。

実はこのスイッチFreeBSDではうまく動かすことが出来なかったんで、再度トライしてみたいと思います。

FreeBSDではそもそも古いarmのサポートが壊れていて、現実的に使えなかったし、clangでくそ時間がかかるのであきらめたような記憶があります。

u-bootでネットワークが使えているので、使えるようにできないわけがありません。

6131のmiiのレジスタは以下のようになっています。

|Addr|Type|
|:--|:--|
|0x0c-0x0f|PHY Registor|
|0x10-0x17|Switch Registor|
|0x1b|Grobal Registor|
|0x1c|Grobal Registor 2|

6131にはPHY Polling Unit (PPU)というのが入っていて、PHYの状態を見てるみたいだけど、よく分からないのが上のPHY Registorに出てこない。そもそも内蔵PHYは3つしかないのに4つレジスタがあるのも意味不明。

Marvellのいけてないところは、ちょこちょこ仕様を変えるところ。6131は初期のgigaのスイッチなので、どうもこれ以降の製品と微妙に仕様が違うっぽい。

たとえば6065のPHY Registorは0始まりなのに、6131ではc始まりなってお終わりをfにしたよう。また6065のGrobal RegistorとGrobal Registor2の順番が6131とは逆です。またこれらの後のチップでGrobal Registor1を追加してます。

Switch Registorのダンプ

```
[   1.0000000] MORI SW Reg 0 fd80 7080 7080 6e88 6086 7086 6086 7086
[   1.0000000] MORI SW Reg 1 3 3 3 33 403 403 403 403
[   1.0000000] MORI SW Reg 2 0 0 0 0 0 0 0 0
[   1.0000000] MORI SW Reg 3 1066 1066 1066 1066 1066 1066 1066 1066
[   1.0000000] MORI SW Reg 4 77 77 77 77 74 74 74 77
[   1.0000000] MORI SW Reg 5 0 0 0 0 0 0 0 0
[   1.0000000] MORI SW Reg 6 708 708 708 787 7ef 7df 7bf 708
[   1.0000000] MORI SW Reg 7 1 2 3 1 1 1 1 8
[   1.0000000] MORI SW Reg 8 cf cf cf cf cf cf cf cf
[   1.0000000] MORI SW Reg 9 0 0 0 0 0 0 0 0
[   1.0000000] MORI SW Reg a 3000 3000 3000 3000 3000 3000 3000 3000
[   1.0000000] MORI SW Reg b 1 2 4 8 10 20 40 80
[   1.0000000] MORI SW Reg c 0 0 0 0 0 0 0 0
[   1.0000000] MORI SW Reg d 0 0 0 0 0 0 0 0
[   1.0000000] MORI SW Reg e 0 0 0 0 0 0 0 0
[   1.0000000] MORI SW Reg f 0 0 0 0 0 0 0 0
[   1.0000000] MORI SW Reg 10 0 0 0 0 0 0 0 0
[   1.0000000] MORI SW Reg 11 0 0 0 0 0 0 0 0
[   1.0000000] MORI SW Reg 12 0 0 0 0 0 0 0 0
[   1.0000000] MORI SW Reg 13 0 0 0 0 0 0 0 0
[   1.0000000] MORI SW Reg 14 403 403 403 8403 403 403 403 403
[   1.0000000] MORI SW Reg 15 0 0 0 0 0 0 0 0
[   1.0000000] MORI SW Reg 16 73d 702 702 700 f41 f02 f41 f02
[   1.0000000] MORI SW Reg 17 0 0 0 0 0 0 0 0
[   1.0000000] MORI SW Reg 18 3210 3210 3210 3210 3210 3210 3210 3210
[   1.0000000] MORI SW Reg 19 7654 7654 7654 7654 7654 7654 7654 7654
[   1.0000000] MORI SW Reg 1a 8280 0 250 f00 0 6db1 2863 10c
[   1.0000000] MORI SW Reg 1b 24 0 0 4 0 0 0 0
[   1.0000000] MORI SW Reg 1c 0 0 0 0 0 0 0 0
[   1.0000000] MORI SW Reg 1d c84 c84 c84 c84 c84 c84 c84 c84
[   1.0000000] MORI SW Reg 1e 22 22 22 22 22 22 22 22
[   1.0000000] MORI SW Reg 1f 4444 4444 4444 4444 4444 4444 4444 4444
```

PORTは左から2,1,0,7,5でCPUポートが3のようです。

最初.1qで設定しているのかと思ったのですが、そんな面倒な事しないですよね。普通にPORT BASEでした。

ダンプを見るとPORT BASE VLAN(6)で各ポートがCPUポートへの接続になっているようなので、全ポートにしたところポート間の疎通がとれました。

![PORTVLAN1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/9f51b7e4-84c2-f6e6-a7e2-5eaa2ec8c4c7.png)

から

![PORTVLAN2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/d7430425-649d-5609-b5ed-d5040860a0fe.png)

にしました。

あとはCPUポートとの通信ですが、ポート間の疎通が取れているのでスイッチとしてはCPUポートにもパケットを投げていて、スイッチとSOCの接続設定に問題があると思われます。

この場合いスイッチかSOCかどちらかになりますが、スイッチ側は明らかに初期化されているので、おそらくSOC側の問題の可能性が濃厚です。

このSOCのEthernetはMII,GMII,RGMIIで外部と接続することができます。この接続設定が上手くて規定ないと想像できます。

今はu-bootでネットワークブートしているので、スイッチやインターフェースが初期化されてその副作用で上手くいくことがあります。ローカルのflashから起動された場合は初期化されない可能性もあり、その時はスイッチやインターフェースのレジスタをすべて同じ設定にしたら良いです。

sys/dev/marvell/if_mvgbe.cのmbgbe_init()のMVGBE_PSCの設定を外したとところpingが通りました。めでたしめでたし。

FreeBSDにはetherswitchフレームワークという強力な仕組みがあります。かなり複雑な仕組みなのでNetBSDポートするのは難しいと思われますが、なにか簡単にスイッチを扱える仕組みがあるといいのですが。

STR9102にVitesseのスイッチのVSC7385が付いたモジュールがあります。VSC7385はパラレルかSPIでの制御が可能なようですが、STR9102にはSPIが無いので、I2CなEPROMに固定で設定を入れているようです。