(toppers-users 2524) Re: Tinet でバスエラーが発生 (解決)

高橋祥士 staka @ scx.co.jp
2006年 9月 11日 (月) 15:14:58 JST


前略、高橋@システムクリエイトです。

皆さんのご助言のおかげでようやく解決しました。

原因は、SH7616 のイーサネットコントローラは、送受信バッファを16Byteアライメントに
しなければいけないのに、北斗電子のドライバが対応していなかったためでした。
しかしながら、TINETもそれについて考慮されていなかったため、下記のように若干
TINETに手を入れることで解決できました。
できましたらTINETでも対応いただければ速度・フットプリントともに改善できるのでは
と考えていますが、いかがでしょうか?

もなかさん、堀さん、阿部先生、ご助言ありがとうございました。
あらためてお礼申し上げます。

敬具

【現象】
SH7616 のイーサネットコントローラは送受信バッファの先頭は16Byteアライメントで
ないといけないがドライバはそうなっていない。そのため、大量のデータを短時間に
送受信すると固定長メモリ管理が破綻しバスエラーが発生する。
また、TINETも現状では対応できない状態である。

【対策】
TINETが管理するバッファとは別にコントローラが送受信する16Byteアライメントの
バッファを用意するのが本筋だと考えられるが、そうすると TINET の『速度を犠牲に
してもメモリを節約する』という趣旨に反するため、TINETが用意するバッファを16Byte
アライメント調節にできるように若干増やし、送信時はTINETで生成した送信データを
コントローラが使用する位置へコピー、受信時はコントローラが受信したデータをTINET
が扱う位置へコピーすることで解決することとする。
なお、この際 IPヘッダのアドレスが 4Byteアライメントになるように注意する。

実際の変更内容は下記の通り。

1.TINET
 1)新たに送受信バッファアライメントを指定する IF_ETHER_NIC_BUF_16BYTE_ALIGNMENT 
   という定義を設ける。この定義を tinet_nic_defs.h に下記のように追加する。

  #define IF_ETHER_NIC_BUF_16BYTE_ALIGNMENT  /* 送受信バッファは16Byteアライメント */

 2)TINET は送受信バッファのアライメントに関して考慮していない。
  送受信バッファは T_NET_BUF_IF_PDU などで下記のように定義されている。
   typedef struct t_net_buf_if_pdu {
    UB idix;   /* mpfid のインデックス */
    UB unit;   /* インタフェース番号 */
    UH len;   /* データの長さ  */
   #if CPU_NET_ALIGN == 4 && IF_HDR_ALIGN != 4
    UB align[4 - IF_HDR_ALIGN]; <--- ★これを増やす。
   #endif
    UB buf[IF_PDU_SIZE]; /* バッファ本体  */ <--- ★TINETが取り扱う送受信データ
    } T_NET_BUF_IF_PDU;

  アライメントについては IF_HDR_ALIGN を指定することで IPアドレスを4Byte
  アライメント調節にできるようになっているが、送受信バッファについては考慮
  されていない。そこで、align を少し多めに取り、16Byteアライメントでかつ必要
  な大きさのバッファを確保できるようにする。

  実際には、若干トリッキーだが 下記のようにして align の大きさを 14 とする。
  14という値は、16Byteアライメントの領域が確保でき、かつIPヘッダのIPアドレス
  が4Byteアライメントなるようにした値である。

  #if 0 /* 147行目 変更前 */
   #define IF_HDR_ALIGN  2   /* ヘッダのアライン単位 */
  #else /* 変更後 */
   #ifdef IF_ETHER_NIC_BUF_16BYTE_ALIGNMENT
    #define IF_HDR_ALIGN (-10)
   #else
    #define IF_HDR_ALIGN  2   /* ヘッダのアライン単位 */
   #endif
  #endif

2.ドライバ
 北斗電子製 SH7616 用イーサネットドライバである if_she.c は、送受信バッファが
 16Byteアライメントになっていない。(16bitアライメントに勘違い?)
 そのため、下記のように変更した。
 #if 0 /* 440行目 変更前 */
   she_rd_set_buffer(rd, (UB*)(netbuf->buf)-2, 1520);
 #else /* 変更後 */
   she_rd_set_buffer(rd, (UB*)( (UW)netbuf->buf & 0xFFFFFFF0 ), SHE_BUFF_MAX_SIZE);
 #endif

 #if 0 /* 507行目 変更前 */
  memmove(net_buf->buf, net_buf->buf-2, net_buf->len);
 #else /* 変更後 */
  memmove(net_buf->buf, buf, net_buf->len);
 #endif

 #if 0 /* 516行目 変更前 */
  she_rd_set_buffer(&(sc->sc_rd[n]), new_buf->buf-2, new_buf->len);
 #else /* 変更後 */
  she_rd_set_buffer(&(sc->sc_rd[n]), (UB*)( (UW)new_buf->buf & 0xFFFFFFF0 ), new_buf->len);
 #endif

 #if 0 /* 615行目 変更前 */
  memmove(output->buf-2, output->buf, output->len);
 #else /* 変更後 */
  memmove((UB*)( (UW)output->buf & 0xFFFFFFF0 ), output->buf, output->len);
 #endif

 #if 0 /* 625行目 変更前 */
  she_td_set_buffer(td, output->buf-2, ETHER_MIN_LEN-ETHER_CRC_LEN);
 #else /* 変更後 */
  she_td_set_buffer(td, (UB*)( (UW)output->buf & 0xFFFFFFF0 ), ETHER_MIN_LEN-ETHER_CRC_LEN);
 #endif

 #if 0 /* 632行目 変更前 */
  she_td_set_buffer(td, output->buf-2, output->len);
 #else /* 変更後 */
  she_td_set_buffer(td, (UB*)( (UW)output->buf & 0xFFFFFFF0 ), output->len);
 #endif

scscscscscscscscscscscscscscscscscscscscscscscscsc
        高橋祥士 (E-Mail staka @ scx.co.jp)
-------------------------------------------------
    株式会社システムクリエイト
    ホームページ http://www.scx.co.jp
scscscscscscscscscscscscscscscscscscscscscscscscsc