/*	
 *	clipeth.h
 *
 *	P/ECE USB Ethernet (DIX Ethernet Ver2.0)
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2005 Naoyuki Sawa
 *
 *	* Tue Aug 23 04:43:00 JST 2005 Naoyuki Sawa
 *	- 1st リリース。
 */
#ifndef __CLIP_ETH_H__
#define __CLIP_ETH_H__

/*****************************************************************************
 *	
 *****************************************************************************/

/*  ==================[ DIX Ethernet Ver2.0 ﾌﾚｰﾑ構造 ]====================
 *
 *           |<---- NDISﾐﾆﾎﾟｰﾄﾄﾞﾗｲﾊﾞが扱う部分 (60-1514 byte) ---->|
 *           |                                                     |
 *  +--------+-------------+-------------+--------+----------------+-----+
 *  | 8 byte |    6 byte   |    6 byte   | 2 byte |  46-1500 byte  |4byte|
 *  +--------+-------------+-------------+--------+----------------+-----+
 *  |        |宛て先       |送信元       |        |                |     |
 *  |ﾌﾟﾘｱﾝﾌﾞﾙ|Ethernetｱﾄﾞﾚｽ|Ethernetｱﾄﾞﾚｽ|ﾌﾚｰﾑﾀｲﾌﾟ|      ﾃﾞｰﾀ      | FCS |
 *  +--------+-------------+-------------+--------+----------------+-----+
 *       A                                                            A
 *       |                                                            |
 *       +- NICﾊｰﾄﾞｳｪｱが付加/除去するので､ﾄﾞﾗｲﾊﾞｿﾌﾄｳｪｱでは考慮しない -+
 */

/****************************************************************************
 *	
 ****************************************************************************/

#define ETHERNET_PRODUCT_ID	(PCE_PRODUCT_ID+0x16)	/* 重複禁止!! */

/* 無効アドレス
 * * "Null Address"の名称は、Token-Ring用語から借用しました。[http://www.techfest.com/networking/lan/token.htm] (2005/08/26)
 *   -----------------------------------------------------------------------------------------------------------------------
 *   2.6.4 Null Address
 *     The Individual Address x'00 00 00 00 00 00' is known as a "Null Address".
 *     No station shall be assigned the Null Address and frames addressed to the Null Address are not expected to be copied.
 *   -----------------------------------------------------------------------------------------------------------------------
 */
extern const unsigned char ethernet_null_address[6];		/* 00-00-00-00-00-00 */

/* ブロードキャストアドレス */
extern const unsigned char ethernet_broadcast_address[6];	/* FF-FF-FF-FF-FF-FF */

/****************************************************************************
 *	
 ****************************************************************************/

typedef struct _ETHERNETCLIENT ETHERNETCLIENT;

/* ETHERNETCLIENT.recv : 受信完了コールバックのプロトタイプ */
typedef void ETHERNETRECV(ETHERNETCLIENT* client,
	const unsigned char* address/*[6]*/,	/* 送信元Ethernetアドレス       (       6バイト) */
	const unsigned char* data/*[length]*/,	/* Ethernetフレームのデータ部分 (46..1500バイト) */
	int length);				/* Ethernetフレームのデータ長   (46..1500      ) */

/* ETHERNETCLIENT.conf : 設定変更コールバックのプロトタイプ */
typedef void ETHERNETCONF(ETHERNETCLIENT* client);

/* クライアント登録用の構造体 */
/*typedef*/ struct _ETHERNETCLIENT {

	/*--------------------------------------------------------------------------------------*
	 *	ethernet_open()を呼び出す前に、アプリケーションにて設定しておくフィールド。	*
	 *	ethernet_open()を呼び出した後は、変更してはいけない。				*
	 *--------------------------------------------------------------------------------------*/

	int type;		/* フレームタイプ  (0x0600..0xffff) */
	ETHERNETRECV* recv;	/* 受信完了コールバック (NULL:無し) */
	ETHERNETCONF* conf;	/* 設定変更コールバック (NULL:無し) */

	/*--------------------------------------------------------------------------------------*
	 *	Ethernetドライバが、内部で使用するフィールド。					*
	 *	アプリケーションは、以下のフィールドにアクセスしてはいけない。			*
	 *--------------------------------------------------------------------------------------*/

	LIST_ENTRY list_entry;	/* クライアントリスト */

} /*ETHERNETCLIENT*/;

/****************************************************************************
 *	
 ****************************************************************************/

/* USB Ethernetを開始します。
 * [in]
 *	txque_capacity	送信キューの許容量。
 *			//最大のEthernetフレームを1つ格納するために必要なキューの許容量は、(sizeof(int)+1514)です。
 *			//txque_capacityに(sizeof(int)+1514)未満を指定した場合は、(sizeof(int)+1514)へ切り上げて確保します。
 *			//↓2005/09/16 create_queue()が暗黙でsizeof(int)を加算するよう仕様変更したことに追従しました。
 *			最大のEthernetフレームを1つ格納するために必要なキューの許容量は、1514です。
 *			txque_capacityに1514未満を指定した場合は、1514へ切り上げて確保します。
 * [note]
 *	* ethernet_start()を呼び出したアプリケーションは、終了前に必ず、ethernet_stop()を呼び出してください。
 *	  ethernet_stop()を呼び出さずにアプリケーションを終了すると、P/ECEシステムが異常動作を起こします。
 *	* ethernet_open()を呼び出してクライアントを登録する前に、必ず、ethernet_start()を呼び出してください。
 * [interrupt]
 *	通常処理	割り込み許可状態での呼び出し	○
 *	通常処理	割り込み禁止状態での呼び出し	○
 *	割り込み処理	割り込み禁止状態での呼び出し	×
 */
void ethernet_start(int txque_capacity);

/* USB Ethernetを停止します。
 * [note]
 *	* ethernet_stop()は、常に安全に呼び出し可能です。
 *	  ethernet_start()を呼び出していなくても、いつでも、何回でも、ethernet_stop()を呼び出して構いません。
 *	* ethernet_stop()を呼び出すと、登録されているクライアントは、自動的にすべて登録解除されます。
 *	  ethernet_stop()を呼び出す前に、個々のクライアントを、明示的に登録解除する必要はありません。
 *	  また、ethernet_stop()を呼び出した後に、ethernet_close()を呼び出してはいけません。
 * [interrupt]
 *	通常処理	割り込み許可状態での呼び出し	○
 *	通常処理	割り込み禁止状態での呼び出し	○
 *	割り込み処理	割り込み禁止状態での呼び出し	×
 */
void ethernet_stop();

/* 特定のフレームタイプを処理する、クライアントを登録します。
 * [in]
 *	client		呼び出し側にて確保した、クライアント登録用の構造体。
 *			各フィールドを、あらかじめ適切に初期化しておいてください。
 * [note]
 *	* フレームタイプの値は、0x0600以上と定められています。(DIX Ethernet Ver2.0仕様)
 *	  ETHERNETCLIENT.typeに、0x0600未満の値を指定して呼び出すと、エラー終了します。
 *	* 同じフレームタイプを処理するクライアントを、同時に二つ以上登録しようとすると、エラー終了します。
 *	* クライアント登録用の構造体は、Ethernetドライバ内部のリストにリンクされます。
 *	  ethernet_close()を呼び出して登録解除するまで、構造体を開放してはいけません。
 * [interrupt]
 *	通常処理	割り込み許可状態での呼び出し	○
 *	通常処理	割り込み禁止状態での呼び出し	○
 *	割り込み処理	割り込み禁止状態での呼び出し	△　可能だが、推奨しない
 */
void ethernet_open(ETHERNETCLIENT* client);

/* 登録済みクライアントを、登録解除します。
 * [in]
 *	client		登録済みクライアントの構造体。
 * [note]
 *	* 未登録のクライアントを登録解除しようとすると、エラー終了します。
 * [interrupt]
 *	通常処理	割り込み許可状態での呼び出し	○
 *	通常処理	割り込み禁止状態での呼び出し	○
 *	割り込み処理	割り込み禁止状態での呼び出し	△　可能だが、推奨しない
 */
void ethernet_close(ETHERNETCLIENT* client);

/* Ethernetフレームを送信します。
 * [in]
 *	client		登録済みクライアントの構造体。
 *	address		宛て先Ethernetアドレス。      (      6バイト)
 *	data		Ethernetフレームのデータ部分。(0..1500バイト)
 *	length		Ethernetフレームのデータ長。  (0..1500      )
 * [out]
 *	戻り値		成功ならば、データ長(length引数の値)をそのまま返します。(0、または、正数)
 *			送信キューがいっぱいで送信できない場合、負数を返します。
 * [note]
 *	* Ethernetの最大フレーム長は、1514以下(データ長は1500以下)です。
 *	  1500バイトを超えるデータを送信しようとすると、エラー終了します。
 *	* Ethernetの最小フレーム長は、60以上(データ長は46以上)です。
 *	  データ長に46未満の値を指定した場合、自動的に最小データ長までパディングして送出します。
 *	  呼び出し側にて、明示的なパディングを行う必要はありません。
 * [interrupt]
 *	通常処理	割り込み許可状態での呼び出し	○
 *	通常処理	割り込み禁止状態での呼び出し	○
 *	割り込み処理	割り込み禁止状態での呼び出し	○
 */
int ethernet_send(ETHERNETCLIENT* client, const unsigned char* address/*[6]*/, const void* data/*[length]*/, int length);

/* Ethernetアドレスを設定します。(内部使用)
 * [in]
 *	address		Ethernetアドレス。
 * [note]
 *	* P/ECE側のEthernetアドレスは、PC側デバイスドライバから、VendorRequestにて自動的に設定されます。
 *	  この関数は、基本的に、VendorRequestからのみ利用します。
 *	  アプリケーションプログラムや、上位プロトコルドライバが直接利用することは、通常、無いはずです。
 * [interrupt]
 *	通常処理	割り込み許可状態での呼び出し	○
 *	通常処理	割り込み禁止状態での呼び出し	○
 *	割り込み処理	割り込み禁止状態での呼び出し	○
 */
void ethernet_set_address(const unsigned char* address/*[6]*/);

/* Ethernetアドレスを取得します。
 * [in]
 *	address		Ethernetアドレスを受け取る、6バイトのバッファ。
 * [note]
 *	* P/ECE側のEthernetアドレスは、PC側デバイスドライバから、VendorRequestにて自動的に設定されます。
 *	  ethernet_start()直後は、初期化タイムラグにより、まだVendorRequestが発行されていません。
 *	  ethernet_start()直後は、正しいEthernetアドレスが得られないことに注意してください。
 *	* PC側デバイスドライバの停止・再開により、任意のタイミングでEthernetアドレスが再設定されます。
 *	  P/ECE側のEthernetアドレスは固定でなく、任意のタイミングで変化するものと考えてください。
 * [interrupt]
 *	通常処理	割り込み許可状態での呼び出し	○
 *	通常処理	割り込み禁止状態での呼び出し	○
 *	割り込み処理	割り込み禁止状態での呼び出し	○
 */
void ethernet_get_address(unsigned char* address/*[6]*/);

/* USB Ethernetの状態を取得します。
 * [in]
 *	stat		結果を格納するETHERNETSTAT構造体へのポインタ。
 * [interrupt]
 *	通常処理	割り込み許可状態での呼び出し	○
 *	通常処理	割り込み禁止状態での呼び出し	○
 *	割り込み処理	割り込み禁止状態での呼び出し	○
 */
typedef struct _ETHERNETSTAT {
	int reset;	/* バスリセット回数 */
	int rxok;	/* 受信成功したフレーム数 */
	int rxerr;	/* 受信エラーのフレーム数 */
	int txok;	/* 送信成功したフレーム数 */
	int txerr;	/* 送信エラーのフレーム数 (ethernet_send()の送信オーバーラン回数です) */
} ETHERNETSTAT;
void ethernet_stat(ETHERNETSTAT* stat);

#endif /*__CLIP_ETH_H__*/
