/*
 * ether.c
 *
 * Copyright 2004, Minoru Murashima. All rights reserved.
 * Distributed under the terms of the BSD License.
 *
 * Ethernet controller manager.
 */


#include<sys/user_config.h>
#include<types.h>
#include<lib.h>
#include<device.h>
#include<errno.h>
#include<net/net.h>
#include<net/rt8139.h>
#include<net/ether.h>
#include<net/ip.h>
#include<net/arp.h>


/**************************************************************************
 *
 * 共通
 *
 **************************************************************************/


/* PUBLIC */
ETHER_DEVICE ethDev[ETHER_DEVICE_MAX];
static int etherNum;					/* Eathernet device number. */


/**************************************************************************
 *
 * misc
 *
 **************************************************************************/


/*
 * PUBLIC
 * Search device number from subnet.
 * 送信先がデフォルトゲートウェイなら、IP bufferにゲートウェイIPアドレスを代入する。
 * parameters : destination IP,destination IP buffer
 * return : device number or error number
 */
int searchDevnum(uint ip,uint *buf)
{
	int i;

	for (i = 0; i < etherNum; ++i){
		if ((ip & ethDev[i].netmask) == ethDev[i].subnet){
			*buf = ip;
			return i;
		}
	}

	/* デフォルトゲートウェイへ。 */
	*buf = IP_DEFAULT_GATEWAY;
	for (i = 0; i < etherNum; ++i){
		if ((IP_DEFAULT_GATEWAY & ethDev[i].netmask) == ethDev[i].subnet){
			return i;
		}
	}

	return 0;
}


/*
 * GLOBAL
 * Get source IP address.
 * parameters :
 */
uint32_t getSrcip(uint32_t dstip)
{
	uint32_t tmp;


	return ethDev[searchDevnum(dstip,&tmp)].ip;
}


/**************************************************************************
 *
 * 受信
 *
 **************************************************************************/


/*
 * GLOBAL
 * Receive ether frame.
 * parameters : device number,frame
 * return : 0 or task switch=1
 */
int receiveEther(int num,ETHER_FRAME *frame)
{
/**********************************************************************************
printk("ETHER FRAME type=%x\n"
       "source mac=%d-%d-%d-%d-%d-%d\n"
       "dest   mac=%d-%d-%d-%d-%d-%d\n",
       swapWord(frame->type),
       frame->srcmac[0],frame->srcmac[1],frame->srcmac[2],
       frame->srcmac[3],frame->srcmac[4],frame->srcmac[5],
       frame->dstmac[0],frame->dstmac[1],frame->dstmac[2],
       frame->dstmac[3],frame->dstmac[4],frame->dstmac[5]);
**********************************************************************************/
	/* フレームを各プロトコルに渡す。 */
	switch(swapWord(frame->type))
	{
		case DIX_TYPE_IP:
			return receiveIp((IP_HEADER*)frame->data);
		case DIX_TYPE_ARP:
			return receiveArp(num,(ARP_HEADER*)frame->data);
	}

	return 0;
}



/**************************************************************************
 *
 * 初期化
 *
 **************************************************************************/


//================================== PUBLIC =============================================


// Set ethernet driver infomation.
// return : 0 or error number.
int setEtherDevice(int ethnum, struct ifnet *ifnet, char *mac)
{
	if (ETHER_DEVICE_MAX <= ethnum){
		return -E2BIG;
	}

	ethDev[ethnum].ifnet = ifnet;
	memcpy(ethDev[ethnum].mac, mac, 6);

	/*
	 * IPアドレスの設定。
	 * Note!
	 *  将来変更予定。
	 */
	switch(ethnum){
		case 0:
			ethDev[0].ip = IP_ADDRESS0;
			ethDev[0].netmask = IP_SUBNETMASK0;
			ethDev[0].subnet = IP_ADDRESS0&IP_SUBNETMASK0;
			ethDev[0].mtu = 1500;
			break;
		case 1:
			ethDev[1].ip = IP_ADDRESS1;
			ethDev[1].netmask = IP_SUBNETMASK1;
			ethDev[1].subnet = IP_ADDRESS1&IP_SUBNETMASK1;
			ethDev[1].mtu = 1500;
			break;
	}

	return 0;
}


int initEther()
{
	int rest;


	if((rest=initRt8139(etherNum))>etherNum)etherNum=rest;
	else if(rest<0)return rest;

	/* イーサネットコントローラーがないか、ドライバーがない。 */
	if(etherNum==0)
		printk("No ethernet driver or no ethernet controler!\n");

	return 0;
}
