⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ns8390.c

📁 Coldfire MCF5282 DBug bootloader
💻 C
📖 第 1 页 / 共 2 页
字号:

	/* stop the nic */
	NS8390_WR_CR(ns8390, 0
		| NS8390_CR_PAGE0
		| NS8390_CR_RD_AB
		| NS8390_CR_STP
		) ;
}

/********************************************************************/
static int
ns8390_send (NIF *nif,
	HWA_ADDR_P	eth_dest,
	HWA_ADDR_P	eth_src,
	uint16		eth_type,
	NBUF		*pNbuf)
{
	/*
	 * This routine transmits one frame.  This routine only accepts
	 * 6-byte Ethernet addresses.
	 */
	int mod_data_length, index;
	NS8390 *ns8390;
	uint8 old_ipl;

	ns8390 = nif->nic;

	/*
	 * The format of an Ethernet frame looks like:
	 *
	 *   00 01 02 03 04 05
	 *  +--+--+--+--+--+--+
	 *  |  |  |  |  |  |  | destination ethernet address
	 *  +--+--+--+--+--+--+
	 *   06 07 08 09 0A 0B
	 *  +--+--+--+--+--+--+
	 *  |  |  |  |  |  |  | source ethernet address
	 *  +--+--+--+--+--+--+
	 *   0C 0D
	 *  +--+--+
	 *  |  |  | type (IP = 0x0800)
	 *  +--+--+
	 *   0E 0F ...
	 *  +--+--+--+--+--+--+
	 *  |  |  |  |  |  |  | data (min of 46 octets, max of 1500)
	 *  +--+--+--+--+--+--+
	 *
	 *  +--+--+--+--+
	 *  |  |  |  |  | 32-bit CRC (generated by hardware)
	 *  +--+--+--+--+
	 *
	 * NOTE:  The NS8390 takes care of pre-amble, and is programmed
	 * to generate the 32-bit CRC.
	 *
	 * NOTE:  The minimum size of data transmitted in an ethernet
	 * frame is 46 octets (bytes).
	 */

	/*
	 * Check for valid length of data.
	 */
	if ((pNbuf->length > nif->mtu) || (pNbuf->length <= 0))
	{
		return 0;
	}
	mod_data_length = pNbuf->length;
	if (mod_data_length < ETH_MIN_SIZE)
		mod_data_length = ETH_MIN_SIZE;
#if (defined(NS8390_16BIT))
	if (mod_data_length & 0x0001)
		++mod_data_length;	/* make it align to 16 bits */
#endif

	/*
	 * During the course of loading a frame into the NS8390, we
	 * can not have interrupts occur, especially those from the
	 * NS8390 receiver!
	 */
	old_ipl = asm_set_ipl(6);

	/*
	 * Load starting address and length into the DMA registers.
	 */
	set_dma_write_at (ns8390,(DEFAULT_TPSR << 8), mod_data_length+14);

	/*
	 * Write destination ethernet address.
	 */
#if (defined(NS8390_8BIT))
	NS8390_WR_DATA8(ns8390, eth_dest[0]);
	NS8390_WR_DATA8(ns8390, eth_dest[1]);
	NS8390_WR_DATA8(ns8390, eth_dest[2]);
	NS8390_WR_DATA8(ns8390, eth_dest[3]);
	NS8390_WR_DATA8(ns8390, eth_dest[4]);
	NS8390_WR_DATA8(ns8390, eth_dest[5]);
#elif (defined(NS8390_16BIT))
	NS8390_WR_DATA16(ns8390, *((uint16 *)&eth_dest[0]));
	NS8390_WR_DATA16(ns8390, *((uint16 *)&eth_dest[2]));
	NS8390_WR_DATA16(ns8390, *((uint16 *)&eth_dest[4]));
#else
#error
#endif

	/*
	 * Write source ethernet address.
	 */
#if (defined(NS8390_8BIT))
	NS8390_WR_DATA8(ns8390, eth_src[0]);
	NS8390_WR_DATA8(ns8390, eth_src[1]);
	NS8390_WR_DATA8(ns8390, eth_src[2]);
	NS8390_WR_DATA8(ns8390, eth_src[3]);
	NS8390_WR_DATA8(ns8390, eth_src[4]);
	NS8390_WR_DATA8(ns8390, eth_src[5]);
#elif (defined(NS8390_16BIT))
	NS8390_WR_DATA16(ns8390, *((uint16 *)&eth_src[0]));
	NS8390_WR_DATA16(ns8390, *((uint16 *)&eth_src[2]));
	NS8390_WR_DATA16(ns8390, *((uint16 *)&eth_src[4]));
#else
#error
#endif

	/*
	 * Write frame type.
	 */
#if (defined(NS8390_8BIT))
	NS8390_WR_DATA8(ns8390, ((eth_type & 0x0000FF00) >> 8));
	NS8390_WR_DATA8(ns8390, (eth_type & 0x000000FF));
#elif (defined(NS8390_16BIT))
	NS8390_WR_DATA16(ns8390, eth_type);
#else
#error
#endif


	/*
	 * Write the data.
	 */
#if (defined(NS8390_8BIT))
	for (index = 0; index < pNbuf->length; ++index)
	{
		NS8390_WR_DATA8(ns8390, pNbuf->data[ETH_HDR_SIZE + index]);
	}
	for (index = pNbuf->length; index < ETH_MIN_SIZE; ++index)
	{
		NS8390_WR_DATA8(ns8390, 0);
	}
#elif (defined(NS8390_16BIT))
	for (index = 0; (index + 1) < pNbuf->length; index += 2)
	{
		NS8390_WR_DATA16(ns8390, *((uint16 *)&pNbuf->data[ETH_HDR_SIZE + index]));
	}
	if (pNbuf->length & 0x0001)
	{
		/* odd number of bytes to transmit */
		NS8390_WR_DATA16(ns8390, (pNbuf->data[ETH_HDR_SIZE + pNbuf->length - 1]<<8));
		++pNbuf->length;	/* for zero pad below */
	}
	for (index = pNbuf->length; index < ETH_MIN_SIZE; index += 2)
	{
		NS8390_WR_DATA16(ns8390, 0);
	}
#else
#error
#endif

	/*
	 * Load Transmit Start Pointer Register and Transmit Byte Count
	 * Registers.
	 */
	NS8390_WR_P0_TPSR(ns8390, DEFAULT_TPSR);
	NS8390_WR_P0_TBCR0(ns8390, ((mod_data_length + 14) & 0x000000FF));
	NS8390_WR_P0_TBCR1(ns8390,
		(((mod_data_length + 14) & 0x0000FF00) >> 8));

	/*
	 * Turn the transmitter on!  We're done!
	 */
	NS8390_WR_CR(ns8390, 0
		| NS8390_CR_PAGE0
		| NS8390_CR_STA
		| NS8390_CR_TXP
		| NS8390_CR_RD_AB
		) ;

	/* Free the network buffer */
	nif->tx_free(pNbuf);

	/* We can allow interrupts again */
	asm_set_ipl(old_ipl);

	return TRUE;
}

/********************************************************************/
static void
ns8390_receive (NS8390 *ns8390, NIF *nif)
{
	/*
	 * This command pulls one frame from the card.
	 */
	int index, current, receive_status, np_pointer, a,b, receive_count;
	eth_frame_hdr *ethframe;
	NBUF *pNbuf;

	/* Prepare to read from the local buffer memory */
	current = nif->next_receive;
	set_dma_read_at (ns8390, current, 4);

	/*
	 * Read the Status bytes and Ethernet frame from the
	 * local buffer memory.  The DMA hardware automatically
	 * increments the DMA pointers.
	 */
#if (defined(NS8390_8BIT))
	receive_status = NS8390_RD_DATA8(ns8390) & 0x00FF;
	np_pointer = NS8390_RD_DATA8(ns8390) & 0x00FF;
	a = (NS8390_DATAPORT(ns8390) & 0x00FF);
	b = (NS8390_DATAPORT(ns8390) & 0x00FF);
	receive_count = ((b << 8) | a);
#elif (defined(NS8390_16BIT))
	a = NS8390_RD_DATA16(ns8390);
	b = NS8390_RD_DATA16(ns8390);

#if (defined(NS8390_ENDIAN_BIG))
	receive_status = (a & 0x00FF);
	np_pointer = ((a & 0xFF00)>>8);
	receive_count = (((b & 0x00FF) << 8) | ((b&0xFF00)>>8));
#elif (defined(NS8390_ENDIAN_LITTLE))
	np_pointer = (a & 0x00FF);
	receive_status = ((a & 0xFF00)>>8);
	receive_count = (((b & 0x00FF) << 8) | ((b&0xFF00)>>8));
#else
#error "ENDIAN"
#endif

#else
#error
#endif

	/* Record next packet pointer and adjust circular queue */
	nif->next_receive = (np_pointer << 8);
	if ((np_pointer-1) <= DEFAULT_PSTART)
		NS8390_WR_P0_BNRY(ns8390, DEFAULT_PSTOP-1);
	else
		NS8390_WR_P0_BNRY(ns8390, np_pointer-1);

	/* This frame has errors! */
	if ((receive_status & NS8390_RSR_PRX) != NS8390_RSR_PRX)
	{
		++nif->f_rx_err;
		return;
	}

	/* Process the frame */
	set_dma_read_at(ns8390, current+4, 6 + 6 + 2);

	/* Obtain system RAM buffer for the frame */
	if ((pNbuf = nif->rx_alloc()) == NULL)
		return;

	ethframe = (eth_frame_hdr *)&pNbuf->data[ETH_HDR_OFFSET];

	/* Read the frame from the local buffer */
#if (defined(NS8390_8BIT))
	ethframe->dest[0] = NS8390_RD_DATA8(ns8390);
	ethframe->dest[1] = NS8390_RD_DATA8(ns8390);
	ethframe->dest[2] = NS8390_RD_DATA8(ns8390);
	ethframe->dest[3] = NS8390_RD_DATA8(ns8390);
	ethframe->dest[4] = NS8390_RD_DATA8(ns8390);
	ethframe->dest[5] = NS8390_RD_DATA8(ns8390);

	ethframe->src[0] = NS8390_RD_DATA8(ns8390);
	ethframe->src[1] = NS8390_RD_DATA8(ns8390);
	ethframe->src[2] = NS8390_RD_DATA8(ns8390);
	ethframe->src[3] = NS8390_RD_DATA8(ns8390);
	ethframe->src[4] = NS8390_RD_DATA8(ns8390);
	ethframe->src[5] = NS8390_RD_DATA8(ns8390);

	a = (NS8390_RD_DATA8(ns8390) & 0x00FF);
	b = (NS8390_RD_DATA8(ns8390) & 0x00FF);
	ethframe->type = (uint16)((a << 8) | b);
#elif (defined(NS8390_16BIT))
	*(uint16 *)&ethframe->dest[0] = NS8390_RD_DATA16(ns8390);
	*(uint16 *)&ethframe->dest[2] = NS8390_RD_DATA16(ns8390);
	*(uint16 *)&ethframe->dest[4] = NS8390_RD_DATA16(ns8390);

	*(uint16 *)&ethframe->src[0] = NS8390_RD_DATA16(ns8390);
	*(uint16 *)&ethframe->src[2] = NS8390_RD_DATA16(ns8390);
	*(uint16 *)&ethframe->src[4] = NS8390_RD_DATA16(ns8390);

	ethframe->type = NS8390_RD_DATA16(ns8390);
#else
#error
#endif

	if (!nif_protocol_exist(nif,ethframe->type))
	{
		nif->rx_free(pNbuf);
		return;
	}

	pNbuf->length = receive_count - (4 + 6 + 6 + 2);
	set_dma_read_at(ns8390, current+18, pNbuf->length);

#if (defined(NS8390_8BIT))
	for (index = 0; index < pNbuf->length; ++index)
	{
		ethframe->data[index] = NS8390_RD_DATA8(ns8390);
	}
#elif (defined(NS8390_16BIT))
	for (index = 0; index < pNbuf->length; index += 2)
	{
		*(uint16 *)&ethframe->data[index] = NS8390_RD_DATA16(ns8390);
	}
#else
#error
#endif

	/* Call the appriopriate handler */
	nif_protocol_handler(nif, ethframe->type,pNbuf);

	/****************************************************************
	 Higher level protocols must save off the data if they need to 
	 keep it around for processing.
	*****************************************************************/
	nif->rx_free(pNbuf);
}

/********************************************************************/
int
ns8390_handler (NS8390 *ns8390, NIF *nif)
{
	/* This is the Interrupt Service Routine for the NS 8390 */
	int isr;

	NS8390_WR_CR(ns8390, 0
		| NS8390_CR_PAGE0
		| NS8390_CR_RD_AB
		| NS8390_CR_STA
		) ;

	/* Verify part has interrupts pending */
	isr = NS8390_RD_P0_ISR(ns8390) & 0x00FF;
	if (!isr) 
	{
		return FALSE;
	}

	/* Check the source of interrupts, and handle it */
	if (isr & NS8390_ISR_PRX)
	{
		/* Ack as soon as possible so more RX IRQs recognized */
		NS8390_WR_P0_ISR(ns8390, NS8390_ISR_PRX);
		ns8390_receive(ns8390, nif);
		++nif->f_rx;
	}
	if (isr & NS8390_ISR_PTX)
	{
		NS8390_WR_P0_ISR(ns8390, NS8390_ISR_PTX);
		++nif->f_tx;
	}
	if (isr & NS8390_ISR_RXE)
	{
		printf("NS8390 RXE Receiver Error\n");
		/* ns8390_receive(ns8390, nif); */
		NS8390_WR_P0_ISR(ns8390, NS8390_ISR_RXE);
	}
	if (isr & NS8390_ISR_TXE)
	{
		printf("NS8390 TXE Transmitter Error\n");
		NS8390_WR_P0_ISR(ns8390, NS8390_ISR_TXE);
		++nif->f_tx_err;
	}
	if (isr & NS8390_ISR_OVW)
	{
		printf("NS8390 OVW Buffer Overflow\n");
		NS8390_WR_P0_ISR(ns8390, NS8390_ISR_OVW);
		++nif->f_rx_err;
	}
	if (isr & NS8390_ISR_CNT)
	{
		printf("NS8390 CNT\n");
		NS8390_WR_P0_ISR(ns8390, NS8390_ISR_CNT);
	}
	if (isr & NS8390_ISR_RDC)
	{
		NS8390_WR_P0_ISR(ns8390, NS8390_ISR_RDC);
	}

	return TRUE;
}
/********************************************************************/
int
ns8390_init (NIF *nif, void *base, int vector)
{
	nif_init(nif, "ns8390");
	nif->nic = base;
	nif->vector = vector;

	read_eth_addr(nif->nic,&nif->hwa[0]);
	nif->hwa_size = 6;
	nif->mtu = 1500;
	nif->reset = ns8390_reset;
	nif->start = ns8390_start;
	nif->stop = ns8390_stop;
	nif->send = ns8390_send;
	nif->receive = (void *)&ns8390_receive;
	nif->rx_alloc = nbuf_rx_allocate;
	nif->tx_alloc = nbuf_tx_allocate;
	nif->rx_free = nbuf_rx_release;
	nif->tx_free = nbuf_tx_release;
	return TRUE;
}
/********************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -