📄 lan91c111.c
字号:
}
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 + -