BCM5301XのGEMAC

EthernetのGEMACのTXのディスクリプタのLinuxの定義です。

```c:bcm5301x_amac.c
typedef struct {
        unsigned
                desc_rsrvd_0    : 20,   /* Reserved, must be 0 */
                desc_flags      : 8,    /* Flags, i.e. CRC generation mode */
                desc_eot        : 1,    /* End-of-Table indicator */
                desc_int_comp   : 1,    /* Interrupt on completion */
                desc_eof        : 1,    /* End-of-Frame */
                desc_sof        : 1,    /* Start-of-Frame */
                desc_buf_sz     : 14,   /* Data buffer length (bytes) */
                desc_resrvd_1   : 1,    /* Reserved, must be 0 */
                desc_addr_ext   : 2,    /* AddrExt, not used, must be 0 */
                desc_parity     : 1,    /* Parity bit for even desc parity */
                desc_resrvd_2   : 12;   /* Reserved, must be 0 */
        u64     desc_data_ptr   : 64;   /* Data buffer 64-bit pointer */
} gmac_desc_t;
```

desc_rsrvd_0からdesc_sofまでで32Bit,desc_buf_szからdesc_resrvd_2で32Bitになります。

このようにビットフィールドで書かれたディスクリプタは珍しいです。

他のTulip系のMAC同様に16バイトで1ディスクリプタなのですが、内容はいろいろ違っています。

まずDMA側かHOST側かを示すOWNビットがありません。

バッファポインターは32ビット2本ではなくMIPS SOCの起源が64ビットなので、64ビット1本です。

ディスクリプタのパリティを設定できるようですが、ディセーブルにできるようです。

desc_flagsの内容は定義が見受からず分かりませんが、0だとCRCを付けてくれるみたいです。

TX,RXのディスクリプタの物理アドレスをレジスタに設定するのも64ビットです。

それとディスクリプタのオフセットを指定するPTRレジスタがあります。

LinuxのコードやNetBSDのコードではPTRに物理アドレスを足していますが、必要ありません。これは設定してレジスタを読み出すと上位ビットが消えているので、分かりました。

最初NetBSDの既存コードをいじっていたのですが、受信は出来ていたのですが、送信がときどきDESCPROTOERRになります。いろいろ試したのですが、デバイス側の問題ではなさそうです。NetBSDではifのkpiが7-9間に変更され古い実装の動きがおかしくなったみたいで、c1kのコードをベースに書き換えました。

既存のコードはソフト割り込みなどを使用していて複雑で直せるきがしません。パフォーマンスをよくするために複雑に書いたのかもしれませんが、動かなくなって直せないのでは意味がありません。

このDMAはディスクリプタには書き込みを行わず、ステータスをレジスタに保存してあります。割り込み処理時はこれを元に処理します。

また受信についてはバッファの先頭にステータスやパケット長を付けてくれます。

PTRの仕様を理解するのにてまどったのですが、PTRはRXではディスクリプタリングの最後の次を入れて、TXは送信時に埋めたディスクリプタの次を設定します。

MACは複数あるようですが、一つだけで再実装しました。

既存コードのドライバーはINSTALL用のカーネルのshellでifconfigしてpingで試しました。

作り直したものはある程度動くようになってからはc2kでインストールしたsdをrootfsにしてpingやtcpdumpで確認しました。

既存コードを1週間以上いじっていたのですが、書き直しは3日くらいでできました。とはいえ他のTulip系とはかなり仕様が違い結構苦労しました。

iperf3でテストもしてみました。

```
Connecting to host 10.0.1.38, port 5201
[  5] local 10.0.1.123 port 65534 connected to 10.0.1.38 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.02   sec  20.0 MBytes   165 Mbits/sec    0    491 KBytes       
[  5]   1.02-2.03   sec  20.0 MBytes   166 Mbits/sec    0    864 KBytes       
[  5]   2.03-3.04   sec  20.0 MBytes   166 Mbits/sec    0   1.27 MBytes       
[  5]   3.04-4.05   sec  20.0 MBytes   166 Mbits/sec    0   1.62 MBytes       
[  5]   4.05-5.00   sec  18.8 MBytes   166 Mbits/sec    0   2.03 MBytes       
[  5]   5.00-6.01   sec  20.0 MBytes   165 Mbits/sec    0   2.41 MBytes       
[  5]   6.01-7.03   sec  20.0 MBytes   166 Mbits/sec    0   2.85 MBytes       
[  5]   7.03-8.04   sec  20.0 MBytes   166 Mbits/sec    0   3.32 MBytes       
[  5]   8.04-9.05   sec  20.0 MBytes   166 Mbits/sec    0   3.79 MBytes       
[  5]   9.05-10.06  sec  20.0 MBytes   166 Mbits/sec    0   4.00 MBytes       
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.06  sec   199 MBytes   166 Mbits/sec    0             sender
[  5]   0.00-10.10  sec   199 MBytes   165 Mbits/sec                  receiver
```