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

📄 lan91c111.c

📁 MIPS下的boottloader yamon 的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
}

static
INT32 dump_status( t_LAN91C111_device *pdevice )
{
	sprintf( msg, " Packets received:               %ld\n\r", pdevice->status.rx_packets ) ;
	PUTS( DEFAULT_PORT, msg ) ;
	sprintf( msg, " Packets transmitted:            %ld\n\r", pdevice->status.tx_packets ) ;
	PUTS( DEFAULT_PORT, msg ) ;
	sprintf( msg, " Bytes received:                 %ld\n\r", pdevice->status.rx_bytes ) ;
	PUTS( DEFAULT_PORT, msg ) ;
	sprintf( msg, " Bytes transmitted:              %ld\n\r", pdevice->status.tx_bytes ) ;
	PUTS( DEFAULT_PORT, msg ) ;
	sprintf( msg, " Receive errors:                 %ld\n\r", pdevice->status.rx_errors ) ;
	PUTS( DEFAULT_PORT, msg ) ;
	sprintf( msg, " Transmit errors:                %ld\n\r", pdevice->status.tx_errors ) ;
	PUTS( DEFAULT_PORT, msg ) ;
	sprintf( msg, " Multicasts received:            %ld\n\r", pdevice->status.multicast ) ;
	PUTS( DEFAULT_PORT, msg ) ;
	sprintf( msg, " Broadcasts received:            %ld\n\r", pdevice->status.broadcast ) ;
	PUTS( DEFAULT_PORT, msg ) ;
	sprintf( msg, " Collisions:                     %ld\n\r", pdevice->status.collisions) ;
	PUTS( DEFAULT_PORT, msg ) ;
}

/************************************************************************
 *      Implementation : Device driver services
 ************************************************************************/

/************************************************************************
 *
 *                          lan91c111_stop
 *  Description :
 *  -------------
 *   This routine stops the SMS LAN controller
 *   by stoping  DMA transfer and resetting the chip.
 *  
 *
 *  Parameters :
 *  ------------
 *
 *  'pdevice',     IN,    reference for this device  context
 *
 *
 *  Return values :
 *  ---------------
 *
 *  'OK'(=0)
 *
 *
 *
 ************************************************************************/
static
INT32 lan91c111_stop( t_LAN91C111_device *pdevice )			   
{
	lan91c111->RCR_0 &= ~RCR_RXEN;
	lan91c111->TCR_0 &= ~TCR_TXEN;
	LAN91C111_state = LAN91C111_DRIVER_IS_STOPPED;
	return( OK );
}

/************************************************************************
 *
 *                          lan91c111_init
 *  Description :
 *  -------------
 *  This service initializes the lan driver and configures
 *  the MAC-address for the 'EN0' LAN interface.
 *  The MAC-address is read during 'init' via the 'syscon' parameter:
 *    -'SYSCON_COM_EN0_MAC_ADDR_ID'.
 *  
 *
 *  Parameters :
 *  ------------
 *
 *  'major',     IN,    major device number
 *  'minor',     IN,    not used
 *  'p_param',   INOUT, not used
 *
 *
 *  Return values :
 *  ---------------
 *
 *  'OK'(=0)
 *
 *
 *
 ************************************************************************/
static
INT32 lan91c111_init(
		  UINT32 major, 		 /* IN: major device number 			*/
		  UINT32 minor, 		 /* IN: minor device number 			*/
		  void	 *p_param ) 	 /* INOUT: device parameter block		*/
{
	t_LAN91C111_device *pdevice;
	INT32 rcode, i;

	/* pointer to device context */
	pdevice = &minor_device[minor];

#if defined(PB1550_CONFIG) || defined(DB1550_CONFIG)
	/* on board CPLD Control/Reset register */
	UINT16 *cpld_control = (UINT16 *)0xAF00000C;

	/* Timings for 396Mhz ONLY */
	*cpld_control |= 0x0f; /* un-reset daughter card */
	*(volatile UINT32 *)0xb4001000 = 0x00010003; /* mem_stcfg0 */
	*(volatile UINT32 *)0xb4001020 = 0x000c00c0; /* mem_stcfg2 */
	*(volatile UINT32 *)0xb4001024 = 0x85E1900D; /* mem_sttime2 */
	asm(" sync");
#endif

	/* reset/init SMC LAN91C111 */
	sys_wait_ms(100);
	select(BANK_0);
	lan91c111->RCR_0 = RCR_SOFTRST;
	lan91c111->RCR_0 = 0x0000;
	sys_wait_ms(100);

	/* check the chip is visible */
	if ((lan91c111->BANK & 0xff00) != 0x3300)
		return (ERROR_LAN_INIT_FAILED);

	/* auto neg. + initialize MII */
	setup_phy_pre();
	/* allocate MAC RX/TX frame buffer space */
	IF_ERROR( (rcode), (allocate_buffers(&minor_device[minor])) )

	/* Reset MAC out of reset and program address */
	IF_ERROR( (rcode), (SYSCON_read( SYSCON_COM_EN0_MAC_ADDR_ID, &(pdevice->PhysicalAddress), sizeof(t_mac_addr))))

	select(BANK_1);
	lan91c111->IA0_1 = pdevice->PhysicalAddress[0];
	lan91c111->IA1_1 = pdevice->PhysicalAddress[1];
	lan91c111->IA2_1 = pdevice->PhysicalAddress[2];
	lan91c111->IA3_1 = pdevice->PhysicalAddress[3];
	lan91c111->IA4_1 = pdevice->PhysicalAddress[4];
	lan91c111->IA5_1 = pdevice->PhysicalAddress[5];

	LAN91C111_state = LAN91C111_DRIVER_IS_STARTED;
	return( OK ) ;
}

/************************************************************************
 *
 *                          lan91c111_open
 *  Description :
 *  -------------
 *  This service registers a mac-layer defined receive-handler in the
 *  LAN-drivers ISR-context to allow for interrupt controlled receive
 *  frame processing in the network stack. No external buffer
 *  administration is required as the protocol-layers are responsible for
 *  handling buffer-allocation and data copy-ing to the allocated buffer
 *  payload area. At return from 'receive' handler, the LAN-drivers
 *  local RX-buffer (packet) is released for re-use. After 'open'
 *  has been called, the LAN-driver's 'read' service will call the
 *  registered receive-handler by any frame reception with direct
 *  reference to the LAN-drivers packet space and no read data will be
 *  delivered in the IO-descriptor.
 *
 *
 *
 *  Parameters :
 *  ------------
 *
 *  'major',     IN,    major device number
 *  'minor',     IN,    not used
 *  'p_param',   IN,    LAN variable of type, t_LAN_IO_desc.
 *
 *
 *  Return values :
 *  ---------------
 *  'OK'(=0)
 *
 *
 *
 ************************************************************************/
static
INT32 lan91c111_open(
		  UINT32 major, 		 /* IN: major device number 			*/
		  UINT32 minor, 		 /* IN: minor device number 			*/
		  t_LAN_OPEN_desc *p_param )   /* IN: receive handler reference */
{
	/* register user defined receive handler */
	usr_receive = p_param->receive ;
	return( OK ) ;
}

/************************************************************************
 *
 *                          lan91c111_read
 *  Description :
 *  -------------
 *  This service polls the specified LAN interface for any received frame.
 *  If any frame has been received, it will be read into the user allocated
 *  variable, *p_param; if none present, completion = 'ERROR_LAN_NO_FRAME'
 *  will be returned.
 *  
 *
 *  Parameters :
 *  ------------
 *
 *  'major',     IN,    major device number
 *  'minor',     IN,    minor device number for multi device drivers
 *  'p_param',   INOUT, LAN variable of type, t_LAN_IO_desc.
 *
 *
 *  Return values :
 *  ---------------
 *
 *  'OK'(=0)
 *  'ERROR_LAN_NO_FRAME':     no frame present on this LAN interface
 *  'ERROR_LAN_COMM_ERROR':   communication error detected
 *
 *
 ************************************************************************/
static
INT32 lan91c111_read(
		  UINT32 major, 		 /* IN: major device number 			*/
		  UINT32 minor, 		 /* IN: minor device number 			*/
		  t_LAN_IO_desc *p_param )	 /* INOUT: LAN frame		   */
{
	t_LAN91C111_device *pdevice ;
	INT32 i, NextRxBuffer;
	UINT16 data, count, status, buffer_len, *read_buff, *dest_buff;
	INT8 control, rx_fifo_no;

	// 0000'4000 - 0000'4FFF   LAN   lan_api.h
	// 0000'A000 - 0000'AFFF   NET   net_api.h
	if ( LAN91C111_state == LAN91C111_DRIVER_IS_STOPPED )
		return( ERROR_LAN_NO_FRAME ) ;

	/* get device context for this minor device */
	pdevice = &minor_device[minor] ;

	select(BANK_2);
	if (!(lan91c111->INTMASKLO_2 & ISR_RX_INT)) return (OK);

	NextRxBuffer = pdevice->NextRxBuffer;
	pdevice->status.rx_packets++;

	/* now a pull packet from memory */
	lan91c111->POINTERS_2 = (PR_RCV | PR_AUTO_INC | PR_READ);
	status = lan91c111->DATA_2;
	count = lan91c111->DATA_2;
	count &= 0x07FF;

	/* FIX!!! if any errors, then release the fifo */
	if( status & (RFS_ALIGNERROR | RFS_BADCRC | RFS_TOOLONG | RFS_TOOSHORT))
	{
		//issue_mmu_command(MMU_CMD_RX_FIFO_RELEASE, MMU_WAIT);
		if (status | RFS_ALIGNERROR) pdevice->status.rx_align_error++;
		if (status | RFS_BADCRC) pdevice->status.rx_badcrc++;
		if (status | RFS_TOOLONG) pdevice->status.rx_toolong++;
		if (status | RFS_TOOSHORT) pdevice->status.rx_tooshort++;
		//continue;
	}

	if (status & RFS_MULTCAST) pdevice->status.multicast++;
	if (status & RFS_BROADCAST) pdevice->status.broadcast++;

	/* buffer len: COUNT - sizeof(status) - sizeof(count) - sizeof(ctrl) */
	buffer_len = (count - 6);

	dest_buff = read_buff = (UINT16 *)KSEG0(pdevice->rx_buffer_addr[NextRxBuffer]);

	/* Read packet data into local buffer */
	for (i = 0; i < ((count-6) >> 1); ++i)
	{
		data = lan91c111->DATA_2;
		data = __SWAP16(data);
		*read_buff++ = data;
	}
	if (status & RFS_ODDFRM)
	{
		*((UINT8 *)read_buff) = lan91c111->DATALO_2;
		++buffer_len;
	}
	control = lan91c111->DATAHI_2;

	/* Release RX memory, ack interrupt */
	issue_mmu_command(MMU_CMD_RX_FIFO_RELEASE, MMU_NOWAIT);
	lan91c111->INTMASKLO_2 |= ISR_RX_INT;

	/* more statistics */
	pdevice->status.rx_bytes += (unsigned long)buffer_len;
	if (buffer_len == 0) /* is this possible ? */
		pdevice->status.rx_zero_length_errors++;

	/* update NextRxBuffer */
	if (++NextRxBuffer == RX_CIRCULAR_BUFFERS)
		NextRxBuffer = 0;
	pdevice->NextRxBuffer = NextRxBuffer;

	/* Now process packet */
	if (usr_receive != NULL)
		(*usr_receive)(buffer_len, ((UINT8*)dest_buff));

	/* FIX!!!! return code ? */
}

/************************************************************************
 *
 *                          lan91c111_write
 *  Description :
 *  -------------
 *  This service requests transmission of a frame on the LAN interface. It is the caller's
 *  responsibility to fill in all information including the destination and source addresses and
 *  the frame type.  The length parameter gives the number of bytes in the ethernet frame.
 *  The routine will not return until the frame has been transmitted or an error has occured.  If
 *  the frame transmits successfully, OK is returned.  If an error occured, a message is sent to
 *  the serial port and the routine returns non-zero.
 *  
 *
 *  Parameters :
 *  ------------
 *
 *  'major',     IN,    major device number
 *  'minor',     IN,    minor device number for multi device drivers
 *  'p_param',   INOUT, LAN variable of type, t_LAN_IO_desc.
 *
 *
 *  Return values :
 *  ---------------
 *
 *  'OK'(=0)
 *  'ERROR_LAN_COMM_ERROR':   communication error detected
 *
 *
 ************************************************************************/
static
INT32 lan91c111_write(
		  UINT32 major, 		 /* IN: major device number 			*/
		  UINT32 minor, 		 /* IN: minor device number 			*/
		  t_LAN_IO_desc *p_param )	 /* OUT: frame to transmit	   */
{
	t_LAN91C111_device *pdevice ;
	INT32 count, i, max_loop = 0;
	INT16 temp, len, status, mask, buffer_len, *write_buff;
	INT8 control, tx_fifo_no, alloc_result;

	if (LAN91C111_state == LAN91C111_DRIVER_IS_STOPPED) return (ERROR_LAN_TXM_ERROR);
	if (!p_param || !p_param->data)  return (ERROR_LAN_TXM_ERROR);

	/* Setup local vars for packet transmission */
	buffer_len = p_param->length;
	DBG0("packet len=%d\n", buffer_len);
	write_buff = (UINT16 *)p_param->data;

	/* get device context for this minor device */
	pdevice = &minor_device[minor] ;

	/* Allocate SMS TX memory buffer */
	if ((alloc_result = allocTx(pdevice)) != OK)
		return (alloc_result);
	alloc_result = lan91c111->PNRHI_2;

	/* Now send the packet !!! */
	lan91c111->PNRLO_2 = alloc_result;
	lan91c111->POINTERS_2 = PR_AUTO_INC;
	lan91c111->DATA_2 = 0;	// status
	lan91c111->DATA_2 = (buffer_len + 6); // len + status + count + ctrl

	for (i=0; i < (buffer_len >> 1); i++)
	{
		lan91c111->DATA_2 = __SWAP16(*write_buff);
		++write_buff;
	}

	if (buffer_len & 0x1)
	{
		lan91c111->DATAHI_2 = *((UINT8 *)write_buff);
		lan91c111->DATALO_2 = CONTROL_BYTE_ODD;
	}
	else
		lan91c111->DATAHI_2 = 0; // no ODD

	/* cheat since only one packet at a time goes out */
	lan91c111->INTMASKLO_2 |= (ISR_TX_INT | ISR_TX_EMPTY_INT);

	issue_mmu_command(MMU_CMD_TX_FIFO_ENQUEUE, MMU_WAIT);

	pdevice->status.tx_bytes += (unsigned long)buffer_len;
	pdevice->status.tx_packets++;

	/* Now wait for transmission to complete or error */
	for (i = 0; i < 1000; ++i)
	{
		status = lan91c111->INTMASKLO_2;
		if (status & (ISR_TX_INT | ISR_TX_EMPTY_INT))
		{
			/* Release TX memory and ACK interrupt */
			issue_mmu_command(MMU_CMD_RELEASE_PACKET, MMU_NOWAIT);
			lan91c111->INTMASKLO_2 |= (ISR_TX_INT | ISR_TX_EMPTY_INT);
		 	txStats(pdevice, lan91c111->EPH_0);
			return (OK);
		}
		sys_wait_ms(1);
	}
	/* TX failed */
	lan91c111_init(0, 0, NULL ) ;
	return( ERROR_LAN_TXM_ERROR ) ;
}

/************************************************************************
 *
 *                          lan91c111_ctrl
 *  Description :
 *  -------------
 *  This service requests special service via 'ctrl'
 *  
 *
 *  Parameters :
 *  ------------
 *
 *  'major',     IN,    major device number
 *  'minor',     IN,    minor device number for multi device drivers
 *  'p_param',   INOUT, LAN variable of type, t_LAN_IO_desc.
 *
 *
 *  Return values :
 *  ---------------
 *
 *  'OK'(=0)
 *
 *
 ************************************************************************/
static
INT32 lan91c111_ctrl(
		  UINT32 major, 		 /* IN: major device number 			*/
		  UINT32 minor, 		 /* IN: minor device number 			*/
		  t_LAN_CTRL_desc *p_param )   /* IN-OUT:						*/
{
	t_LAN91C111_device 		 *pdevice ;

	/* get device context for this minor device */
	pdevice = &minor_device[minor] ;

	switch( p_param->command )
	{
		case LAN_CTRL_DISPLAY_STATISTICS:
			MII_status( pdevice ) ;
			dump_status( pdevice ) ;
			break ;
		case LAN_CTRL_STOP_CONTROLLER:
			lan91c111_stop( pdevice ) ;
			break ;
		case LAN_CTRL_START_CONTROLLER:
			/* re-init driver and controller */
			lan91c111_init( 0, 0, NULL ) ;
			break ;
		default:
			break ;
	}
	return( OK ) ;
}

/************************************************************************
 *      Implementation : Public functions
 ************************************************************************/

/************************************************************************
 *
 *                          lan91c111_install
 *  Description :
 *  -------------
 *
 *  Installs the SMS LAN91C111 device drivers services in 
 *  the IO system at the reserved device slot, found in the
 *  'sysdev.h' file, which defines all major device numbers.
 *
 *  Note:
 *  This service is the only public declared interface function; all
 *  provided device driver services are static declared, but this
 *  function installs the function pointers in the io-system to
 *  enable the provided public driver services.
 *
 *  Parameters :
 *  ------------
 *
 *  -
 *
 *
 *  Return values :
 *  ---------------
 *
 *  'OK'(=0)
 *  'ERROR_IO_ILLEGAL_MAJOR':  Illegal major device number
 *  'ERROR_IO_NO_SPACE':       Device slot already allocated
 *
 ************************************************************************/
INT32 LAN_LAN91C111_install(void)
{
	/* pre-initialize local variables and install device services */
	memset( minor_device, 0, sizeof(minor_device)) ;
	return( IO_install(   SYS_MAJOR_LAN_LAN91C111, /* major device number */
		(t_io_service) lan91c111_init,      /* 'init'  service     */
		(t_io_service) lan91c111_open,      /* 'open'  service     */
		NULL,      /* 'close' service  na */
		(t_io_service) lan91c111_read,      /* 'read'  service     */
		(t_io_service) lan91c111_write,     /* 'write' service     */
		(t_io_service) lan91c111_ctrl ) ) ; /* 'ctrl'  service     */
}

⌨️ 快捷键说明

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