/*
 *  TINET (TCP/IP Protocol Stack)
 * 
 *  Copyright (C) 2001-2009 by Dep. of Computer Science and Engineering
 *                   Tomakomai National College of Technology, JAPAN
 *
 *  上記著作権者は，以下の (1)〜(4) の条件か，Free Software Foundation 
 *  によって公表されている GNU General Public License の Version 2 に記
 *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
 *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
 *  利用と呼ぶ）することを無償で許諾する．
 *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
 *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
 *      スコード中に含まれていること．
 *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
 *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
 *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
 *      の無保証規定を掲載すること．
 *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
 *      用できない形で再配布する場合には，次の条件を満たすこと．
 *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
 *        作権表示，この利用条件および下記の無保証規定を掲載すること．
 *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
 *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
 *
 *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
 *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
 *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
 *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
 * 
 *  @(#) $Id: if_v850ec.c,v 1.5 2009/12/24 05:46:31 abe Exp abe $
 */

/*
 * Copyright (c) 1995, David Greenman
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice unmodified, this list of conditions, and the following
 *    disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD: src/sys/i386/isa/if_ed.c,v 1.148.2.4 1999/09/25 13:08:18 nyan Exp $
 */

#ifdef TARGET_KERNEL_ASP

#define CAST(type, val)		((type)(val))

#include <kernel.h>
#include <sil.h>
#include <t_syslog.h>
#include "kernel_cfg.h"
#include "target_config.h"

#endif	/* of #ifdef TARGET_KERNEL_ASP */

#ifdef TARGET_KERNEL_JSP

#include <s_services.h>
#include <t_services.h>
#include "kernel_id.h"

#endif	/* of #ifdef TARGET_KERNEL_JSP */

#include <tinet_defs.h>
#include <tinet_config.h>

#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_arp.h>
#include <net/net.h>
#include <net/net_timer.h>
#include <net/net_count.h>
#include <net/net_buf.h>

#include "if_v850ecreg.h"
#include <string.h>

#ifdef _MSC_VER
#include <stdlib.h>
#endif

/*
 *  ネットワークインタフェースに依存するソフトウェア情報 
 */

typedef struct t_v850ec_softc {
	bool_t tx_empty;
	T_V850EC_DESC *tx_write;
	T_V850EC_DESC *rx_read;
} T_V850EC_SOFTC;

/*
 *  ネットワークインタフェースのソフトウェア情報
 */

/* ネットワークインタフェースに依存するソフトウェア情報 */

static T_V850EC_SOFTC v850ec_softc;

#if defined(__ghs__)
#pragma ghs section bss=".eth_memory"
#elif !defined(_MSC_VER)
#pragma	section	data	"eth_memory"	begin
#endif
uint8_t rx_buffer[IF_V850EC_BUF_PAGE_COUNT][(int)&((T_NET_BUF *)0)->buf + IF_V850EC_RXBUF_PAGE_SIZE];
uint8_t tx_buffer[IF_V850EC_BUF_PAGE_COUNT][IF_V850EC_RXBUF_PAGE_SIZE];
T_V850EC_DESC rx_desc[IF_V850EC_BUF_PAGE_COUNT + 1];
T_V850EC_DESC tx_desc[IF_V850EC_BUF_PAGE_COUNT + 1];
#if defined(__ghs__)
#pragma ghs section bss=default
#elif !defined(_MSC_VER)
#pragma	section	data	"eth_memory"	end
#endif

/* ネットワークインタフェースに依存しないソフトウェア情報 */

T_IF_SOFTC if_softc = {
	{0,},					/* ネットワークインタフェースのアドレス	*/
	0,					/* 送信タイムアウト			*/
	&v850ec_softc,				/* ディバイス依存のソフトウェア情報	*/
	SEM_IF_V850EC_SBUF_READY,			/* 送信セマフォ			*/
	SEM_IF_V850EC_RBUF_READY,			/* 受信セマフォ			*/

#ifdef SUPPORT_INET6

	IF_MADDR_INIT,				/* マルチキャストアドレスリスト	*/

#endif	/* of #ifdef SUPPORT_INET6 */
};

/*
 *  局所変数
 */

static void v850ec_pio_readmem (T_V850EC_SOFTC *sc, uint32_t src, uint8_t *dst, uint16_t amount);
static T_NET_BUF *v850ec_get_frame (T_V850EC_SOFTC *sc, uint32_t ring, uint16_t len);
static void v850ec_xmit (T_IF_SOFTC *ic);
static void v850ec_stop (T_V850EC_SOFTC *sc);
static void v850ec_init_sub (T_IF_SOFTC *ic);
static void v850ec_setrcr (T_IF_SOFTC *ic);

#ifdef SUPPORT_INET6

static uint32_t ds_crc (uint8_t *addr);
static void ds_getmcaf (T_IF_SOFTC *ic, uint32_t *mcaf);

/*
 *  ds_crc -- イーサネットアドレスの CRC を計算する。
 */

#define POLYNOMIAL	0x04c11db6

static uint32_t
ds_crc (uint8_t *addr)
{
	uint32_t	crc = ULONG_C(0xffffffff);
	int_t		carry, len, bit;
	uint8_t		byte;

	for (len = ETHER_ADDR_LEN; len -- > 0; ) {
		byte = *addr ++;
		for (bit = 8; bit -- > 0; ) {
			carry   = ((crc & ULONG_C(0x80000000)) ? 1 : 0) ^ (byte & UINT_C(0x01));
			crc   <<= 1;
			byte   >>= 1;
			if (carry)
				crc = (crc ^ POLYNOMIAL) | carry;
		}
	}
	return crc;
}

#undef POLYNOMIAL

/*
 *  ds_getmcaf -- マルチキャストアドレスのリストからマルチキャストアドレス
 *                フィルタを計算する。
 */

static void
ds_getmcaf (T_IF_SOFTC *ic, uint32_t *mcaf)
{
	uint32_t	count, index;
	uint8_t		*af = (uint8_t*)mcaf;

	mcaf[0] = mcaf[1] = 0;

	for (count = MAX_IF_MADDR_CNT; count -- > 0; ) {
		index = ds_crc(ic->maddrs[count].lladdr) >> 26;
		af[index >> 3] |= 1 << (index & 7);
	}
}

/*
 * v850ec_setrcr -- 受信構成レジスタ (RCR) を設定する。
 */

static void
v850ec_setrcr (T_IF_SOFTC *ic)
{
	T_V850EC_SOFTC	*sc = ic->sc;
}

/*
 * v850ec_addmulti -- マルチキャストアドレスを追加する。
 */

ER
v850ec_addmulti (T_IF_SOFTC *ic)
{
	v850ec_setrcr(ic);
	return E_OK;
}

#endif	/* of #ifdef SUPPORT_INET6 */

/*
 *  v850ec_stop -- ed ネットワークインタフェースを停止する。
 *
 *    注意: NIC 割り込み禁止状態で呼び出すこと。
 */

static void
v850ec_stop (T_V850EC_SOFTC *sc)
{
	/* 送受信DMA動作停止 */
	sil_wrw_mem(TRANSCTL, sil_rew_mem(TRANSCTL) & ~(TRANSCTL_TXEN | TRANSCTL_RXEN));

	/* FIFO部送受信停止 */
	sil_wrw_mem(MFFCONT, sil_rew_mem(MFFCONT) & ~(MFFCONT_RXEN | MFFCONT_TXEN));

	/* MAC部受信停止 */
	sil_wrw_mem(MACC1, sil_rew_mem(MACC1) & ~(MACC1_SRXEN));
}

/*
 *  v850ec_init_sub -- ed ネットワークインタフェースの初期化
 *
 *    注意: NIC 割り込み禁止状態で呼び出すこと。
 */

static void
v850ec_init_sub (T_IF_SOFTC *ic)
{
	uint32_t dummy;

	/* イーサネット・コントローラの動作を許可 */
	sil_wrb_mem(MIICTL, sil_reb_mem(MIICTL) | MIICTL_MIIEN);

	/* MAC部動作モード設定 */
	sil_wrw_mem(MACC1, MACC1_CRCEN | MACC1_PADEN | MACC1_FULLD);
	sil_wrw_mem(MACC2, 0);

	/* MAC部ソフトウエア・リセット */
	sil_wrw_mem(MACC2, sil_rew_mem(MACC2) | MACC2_MCRST | MACC2_RFRST | MACC2_TFRST);

	/* シリアル・マネジメント・インタフェース・ブロックのソフトウエア・リセット */
	sil_wrw_mem(MIIC, MIIC_MIRST);

	/* MII動作モード設定 */
	sil_wrw_mem(MIIC, MIIC_CLKS_50MHZ);

	/* MAC部各種レジスタ設定 */
	sil_wrw_mem(IPGT, 0x00000013);
	sil_wrw_mem(IPGR, 0x00000E13);
	sil_wrw_mem(CLRT, 0x0000380F);
	sil_wrw_mem(LMAX, 0x00000600);
	sil_wrw_mem(LSA1, (ic->ifaddr.lladdr[0] << 8) | ic->ifaddr.lladdr[1]);
	sil_wrw_mem(LSA2, (ic->ifaddr.lladdr[2] << 24) | (ic->ifaddr.lladdr[3] << 16)
		| (ic->ifaddr.lladdr[4] << 8) | ic->ifaddr.lladdr[5]);
	sil_wrw_mem(VLTP, 0x00000000);
	sil_wrw_mem(AFR, AFR_ABC);
	sil_wrw_mem(HT1, 0x00000000);
	sil_wrw_mem(HT2, 0x00000000);
	sil_wrw_mem(CAM1, 0x00000000);
	sil_wrw_mem(CAM2, 0x00000000);

	/* 統計カウンタ・クリア */
	sil_wrw_mem(CAR1, 0x00000000);
	sil_wrw_mem(CAR2, 0x00000000);
	sil_wrw_mem(RBYT, 0x00000000);
	sil_wrw_mem(RPKT, 0x00000000);
	sil_wrw_mem(RFCS, 0x00000000);
	sil_wrw_mem(RMCA, 0x00000000);
	sil_wrw_mem(RBCA, 0x00000000);
	sil_wrw_mem(RXCF, 0x00000000);
	sil_wrw_mem(RXPF, 0x00000000);
	sil_wrw_mem(RXUO, 0x00000000);
	sil_wrw_mem(RALN, 0x00000000);
	sil_wrw_mem(RFLR, 0x00000000);
	sil_wrw_mem(RCDE, 0x00000000);
	sil_wrw_mem(RFCR, 0x00000000);
	sil_wrw_mem(RUND, 0x00000000);
	sil_wrw_mem(ROVR, 0x00000000);
	sil_wrw_mem(RFRG, 0x00000000);
	sil_wrw_mem(RJBR, 0x00000000);
	sil_wrw_mem(R64,  0x00000000);
	sil_wrw_mem(R127, 0x00000000);
	sil_wrw_mem(R255, 0x00000000);
	sil_wrw_mem(R511, 0x00000000);
	sil_wrw_mem(R1K,  0x00000000);
	sil_wrw_mem(RMAX, 0x00000000);
	sil_wrw_mem(RVBT, 0x00000000);
	sil_wrw_mem(TBYT, 0x00000000);
	sil_wrw_mem(TPKT, 0x00000000);
	sil_wrw_mem(TFCS, 0x00000000);
	sil_wrw_mem(TMCA, 0x00000000);
	sil_wrw_mem(TBCA, 0x00000000);
	sil_wrw_mem(TUCA, 0x00000000);
	sil_wrw_mem(TXPF, 0x00000000);
	sil_wrw_mem(TDFR, 0x00000000);
	sil_wrw_mem(TXDF, 0x00000000);
	sil_wrw_mem(TSCL, 0x00000000);
	sil_wrw_mem(TMCL, 0x00000000);
	sil_wrw_mem(TLCL, 0x00000000);
	sil_wrw_mem(TXCL, 0x00000000);
	sil_wrw_mem(TNCL, 0x00000000);
	sil_wrw_mem(TCSE, 0x00000000);
	sil_wrw_mem(TIME, 0x00000000);

	/* FIFO部ソフトウエア・リセット */
	sil_wrw_mem(RSTCNT, sil_rew_mem(RSTCNT) | RSTCNT_SFTRST);

	/* FIFO部動作モード設定 */
	sil_wrw_mem(MFFCONT, MFFCONT_RXSDMA | MFFCONT_APS | MFFCONT_APL);

	/* FIFO部各種レジスタ設定 */
	sil_wrw_mem(FLOWTHRESH, 0x06000200);
	sil_wrw_mem(PAUSETM, 0x7FFFFFFF);
	sil_wrw_mem(RXERSEL, RXERSEL_RLENE | RXERSEL_VLAN | RXERSEL_USOP
		| RXERSEL_RPCF | RXERSEL_RCFR | RXERSEL_DBNB | RXERSEL_RLOR
		| RXERSEL_RLER | RXERSEL_RCRCE | RXERSEL_RXER | RXERSEL_CEPS
		| RXERSEL_REPS | RXERSEL_PAIG | RXERSEL_TXRX | RXERSEL_DVCF);
	sil_wrw_mem(TXABTCNT, 0x00000000);
	sil_wrw_mem(RXABTCNT, 0x00000000);

	/* FIFO部ステータス割り込み要因クリア */
	dummy = sil_rew_mem(FSTATUS);
	dummy = sil_rew_mem(TXSTATUS);
	dummy = sil_rew_mem(RXSTATUS);

	/* DMA部ソフトウエア・リセット */
	sil_wrw_mem(SFTRST, SFTRST_SFTRST);

	/* 送受信DMA動作停止 */
	sil_wrw_mem(TRANSCTL, sil_rew_mem(TRANSCTL) & ~(TRANSCTL_TXEN | TRANSCTL_RXEN));

	/* DMA転送タイプ設定 */
	sil_wrw_mem(DMACM, DMACM_BURST16);

	/* 受信チェックサム追加機能設定 */
	sil_wrw_mem(TRANSCTL, sil_rew_mem(TRANSCTL) | TRANSCTL_RXCHKSMEN);

	/* DMA部割り込み要因クリア */
	dummy = sil_rew_mem(INTMS);

	/* 割り込みマスク設定 */
	sil_wrw_mem(FSTATUS_MASK, FSTATUS_MASK_TACOF | FSTATUS_MASK_RACOF
		| FSTATUS_MASK_TSUP | FSTATUS_MASK_TFNRTY | FSTATUS_MASK_TFWE
		| FSTATUS_MASK_RFFE | FSTATUS_MASK_RSUP | FSTATUS_MASK_RFWE
		| FSTATUS_MASK_RFOF | FSTATUS_MASK_RFFLW | FSTATUS_MASK_RFZP);
	sil_wrw_mem(TXSTATUS_MASK, TXSTATUS_MASK_TAB | TXSTATUS_MASK_TGNT
		| TXSTATUS_MASK_LCOL | TXSTATUS_MASK_ECOL | TXSTATUS_MASK_TEDFR
		| TXSTATUS_MASK_TDFR | TXSTATUS_MASK_TFLOR | TXSTATUS_MASK_TFLER
		| TXSTATUS_MASK_TCRCE);
	sil_wrw_mem(RXSTATUS_MASK, RXSTATUS_MASK_RLENE | RXSTATUS_MASK_VLAN
		| RXSTATUS_MASK_USOP | RXSTATUS_MASK_RPCF | RXSTATUS_MASK_RCFR
		| RXSTATUS_MASK_DBNB | RXSTATUS_MASK_RLOR | RXSTATUS_MASK_RLER
		| RXSTATUS_MASK_RCRCE | RXSTATUS_MASK_RXER | RXSTATUS_MASK_CEPS
		| RXSTATUS_MASK_REPS | RXSTATUS_MASK_PAIG | RXSTATUS_MASK_TXRX
		| RXSTATUS_MASK_DVCF);
	sil_wrw_mem(INTMS, INTMS_RBEMSK | INTMS_RECMSK | INTMS_RXMSK | INTMS_TBEMSK | INTMS_TECMSK | INTMS_TXMSK);

	/* MAC部受信イネーブル */
	sil_wrw_mem(MACC1, sil_rew_mem(MACC1) | MACC1_SRXEN);

	/* FIFO部送受信イネーブル */
	sil_wrw_mem(MFFCONT, sil_rew_mem(MFFCONT) | MFFCONT_RXEN | MFFCONT_TXEN);

	/* DMA部送受信イネーブル */
	sil_wrw_mem(TRANSCTL, sil_rew_mem(TRANSCTL) | TRANSCTL_RXEN | TRANSCTL_TXEN);
}

/*
 * v850ec_reset -- ed ネットワークインタフェースをリセットする。
 */

void
v850ec_reset (T_IF_SOFTC *ic)
{
#ifdef TARGET_KERNEL_JSP
	IPM	ipm;
#endif

	/* NIC からの割り込みを禁止する。*/
#ifdef TARGET_KERNEL_JSP
	ipm = v850ec_dis_inter();
#endif
#ifdef TARGET_KERNEL_ASP
	syscall(dis_int(INTNO_IF_V850EC_RX));
	syscall(dis_int(INTNO_IF_V850EC_TX));
#endif

	NET_COUNT_ETHER_NIC(net_count_ether_nic[NC_ETHER_NIC_RESETS], 1);
	v850ec_stop(ic->sc);
	v850ec_init_sub(ic);

	/* NIC からの割り込みを許可する。*/
#ifdef TARGET_KERNEL_JSP
	v850ec_ena_inter(ipm);
#endif
#ifdef TARGET_KERNEL_ASP
	syscall(ena_int(INTNO_IF_V850EC_RX));
	syscall(ena_int(INTNO_IF_V850EC_TX));
#endif
}

/*
 *  get_v850ec_softc -- ネットワークインタフェースのソフトウェア情報を返す。
 */

T_IF_SOFTC *
v850ec_get_softc (void)
{
	return &if_softc;
}

/*
 * v850ec_watchdog -- ed ネットワークインタフェースのワッチドッグタイムアウト
 */

void
v850ec_watchdog (T_IF_SOFTC *ic)
{
	v850ec_reset(ic);
}

/*
 * v850ec_probe -- ed ネットワークインタフェースの検出
 */

void
v850ec_probe (T_IF_SOFTC *ic)
{
#ifdef _MSC_VER
	int i;
	for(i = 1; i < 6; i++){
		ic->ifaddr.lladdr[i] = rand();
	}
#endif
}

/*
 * v850ec_init -- ed ネットワークインタフェースの初期化
 */

void
v850ec_init (T_IF_SOFTC *ic)
{
#ifdef TARGET_KERNEL_JSP
	IPM	ipm;
#endif
	T_V850EC_SOFTC *sc = ic->sc;
	T_V850EC_DESC *desc;
	int i;

	/* NIC からの割り込みを禁止する。*/
#ifdef TARGET_KERNEL_JSP
	ipm = v850ec_dis_inter();
#endif
#ifdef TARGET_KERNEL_ASP
	syscall(dis_int(INTNO_IF_V850EC_RX));
	syscall(dis_int(INTNO_IF_V850EC_TX));
#endif

	desc = (T_V850EC_DESC *)tx_desc;
	sc->tx_write = desc;
	for ( i=0 ; i < IF_V850EC_BUF_PAGE_COUNT ; i++ ) {
		*(uint32_t *)desc = 0;
		desc->used = 1;
		desc->addr = (uint8_t *)&tx_buffer[i];
		desc++;
	}
	*(uint32_t *)desc = 0;
	desc->link = 1;
	desc->addr = (uint8_t *)tx_desc;

	desc = (T_V850EC_DESC *)rx_desc;
	sc->rx_read = desc;
	for ( i=0 ; i < IF_V850EC_BUF_PAGE_COUNT ; i++ ) {
		*(uint32_t *)desc = IF_V850EC_RXBUF_PAGE_SIZE;
		desc->addr = (uint8_t *)&rx_buffer[i] + (int)&((T_NET_BUF *)0)->buf;
		desc++;
	}
	*(uint32_t *)desc = 0;
	desc->link = 1;
	desc->addr = (uint8_t *)rx_desc;

	/* v850ec_init 本体を呼び出す。*/
	v850ec_init_sub(ic);

	desc = sc->rx_read;

	if ( (sil_rew_mem(TRANSCTL) & TRANSCTL_RXEN_STA) != TRANSCTL_RXEN_STA ) {
		sil_wrw_mem(RXDP, (uint32_t)desc);
		sil_wrw_mem(ETHMODE, sil_rew_mem(ETHMODE) | ETHMODE_RXS);
	}

	/* NIC からの割り込みを許可する。*/
#ifdef TARGET_KERNEL_JSP
	v850ec_ena_inter(ipm);
#endif
#ifdef TARGET_KERNEL_ASP
	syscall(ena_int(INTNO_IF_V850EC_RX));
	syscall(ena_int(INTNO_IF_V850EC_TX));
#endif
}

/*
 * v850ec_read -- フレームの読み込み
 */

T_NET_BUF *
v850ec_read (T_IF_SOFTC *ic)
{
	T_V850EC_SOFTC *sc = ic->sc;
	T_V850EC_DESC *desc;
	T_NET_BUF *buf;

	desc = sc->rx_read;

	buf = (T_NET_BUF *)((uint8_t *)desc->addr - (int)&((T_NET_BUF *)0)->buf);
	buf->len = desc->size;

	desc++;
	while (desc->link && !desc->last) {
		desc = (T_V850EC_DESC *)desc->addr;
	}
	sc->rx_read = desc;

	*(uint32_t *)desc = IF_V850EC_RXBUF_PAGE_SIZE;

	if ( (sil_rew_mem(TRANSCTL) & TRANSCTL_RXEN_STA) != TRANSCTL_RXEN_STA ) {
		sil_wrw_mem(RXDP, (uint32_t)desc);
		sil_wrw_mem(ETHMODE, sil_rew_mem(ETHMODE) | ETHMODE_RXS);
	}

	return buf;
}

/*
 * v850ec_start -- 送信フレームをバッファリングする。
 */

void
v850ec_start (T_IF_SOFTC *ic, T_NET_BUF *output)
{
	T_V850EC_SOFTC *sc = ic->sc;
	T_V850EC_DESC *desc, *next;
	uint8_t *buf = NULL;

	desc = sc->tx_write;

	if (!desc->used) {
		return;
	}

	buf = (uint8_t *)desc->addr;

	next = desc + 1;
	while (next->link && !next->last) {
		next = (T_V850EC_DESC *)next->addr;
	}
	sc->tx_write = next;

	memcpy(buf, output->buf, output->len);

	*(uint32_t *)desc = output->len;
	desc->last = 1;

	if ( (sil_rew_mem(TRANSCTL) & TRANSCTL_TXEN_STA) != TRANSCTL_TXEN_STA ) {
		sil_wrw_mem(TXDP, (uint32_t)desc);
		sil_wrw_mem(ETHMODE, sil_rew_mem(ETHMODE) | ETHMODE_TXS);
	}
}

/*
 *  V850 Ethernet Controler 受信割り込みハンドラ
 */

void
if_v850ec_rx_handler (void)
{
	T_IF_SOFTC *ic = &if_softc;
	T_V850EC_SOFTC *sc = ic->sc;

	/* 受信割り込み処理 */
	isig_sem(ic->semid_rxb_ready);
}

/*
 *  V850 Ethernet Controler 送信割り込みハンドラ
 */

void
if_v850ec_tx_handler (void)
{
	T_IF_SOFTC *ic = &if_softc;
	T_V850EC_SOFTC *sc = ic->sc;

	/* 送信割り込み処理 */
	isig_sem(ic->semid_txb_ready);
}
