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

📄 network.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  network.c: An 82596 ethernet driver for rtems-bsd. * *  $Id: network.c,v 1.7 2002/11/01 21:50:47 joel Exp $ */#define KERNEL/*  *  Selectively define to debug the network driver. If you define any of these *  you must run with polled console I/O. */ /* #define DBG_ADD_CMD#define DBG_WAIT#define DBG_SEND#define DBG_MEM#define DBG_SELFTEST_CMD#define DBG_DUMP_CMD#define DBG_RESET#define DBG_ATTACH#define DBG_START#define DBG_INIT#define DBG_STOP#define DBG_RX#define DBG_ISR#define DBG_IOCTL#define DBG_STAT#define DBG_PACKETS*//* * Default number of buffer descriptors and buffer sizes. */#define RX_BUF_COUNT   15#define TX_BUF_COUNT   4#define TX_BD_PER_BUF  4#define RBUF_SIZE  1520#define UTI_596_ETH_MIN_SIZE  60#define INET_ADDR_MAX_BUF_SIZE (sizeof "255.255.255.255")/* * RTEMS events */#define INTERRUPT_EVENT         RTEMS_EVENT_1#define START_TRANSMIT_EVENT    RTEMS_EVENT_2#define NIC_RESET_EVENT         RTEMS_EVENT_3#include <bsp.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <rtems/error.h>#include <rtems/rtems_bsdnet.h>#include <sys/param.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/sockio.h>#include <sys/types.h>#include <net/if.h>#include <netinet/in.h>#include <netinet/if_ether.h>#include <arpa/inet.h>#include "uti596.h"/* If we are running interrupt driven I/O no debug output is printed */#if CD2401_POLLED_IO == 1   #define printk(arglist) printk arglist;#else   #define printk(arglist)#endif#define UTI_596_ASSERT( condition, str )  if (!( condition ) ) { printk((str)) }/* Types of PORT commands */#define UTI596_RESET_PORT_FUNCTION	  	0#define UTI596_SELFTEST_PORT_FUNCTION 	1#define UTI596_SCP_PORT_FUNCTION      	2#define UTI596_DUMP_PORT_FUNCTION     	3/* Types of waiting for commands */#define UTI596_NO_WAIT									0#define UTI596_WAIT_FOR_CU_ACCEPT				1#define UTI596_WAIT_FOR_INITIALIZATION	2#define UTI596_WAIT_FOR_STAT_C					3/* Device dependent data structure */static uti596_softc_ uti596_softc;/* Globals */int count_rx = 0;static int scbStatus;static rtems_status_code sc;static i596_cmd *pIsrCmd;static i596_rfd *pIsrRfd;/* * Initial 596 configuration */char uti596initSetup[] = {  0x0E,   /* Byte 0: length, prefetch off ( no RBD's ) */  0xC8,   /* Byte 1: fifo to 8, monitor off */  0x40,   /* Byte 2: don't save bad frames ( was save= 80, use intel's 40 )*/  0x2E,   /* Byte 3: No source address insertion, 8 byte preamble */  0x00,   /* Byte 4: priority and backoff defaults */  0x60,   /* Byte 5: interframe spacing */  0x00,   /* Byte 6: slot time LSB */  0xf2,   /* Byte 7: slot time and retries */  0x0C,   /* Byte 8: not promisc, enable bcast, tx no crs, crc inserted 32bit, 802.3 framing */  0x08,   /* Byte 9: collision detect */  0x40,   /* Byte 10: minimum frame length */  0xfb,   /* Byte 11: tried C8 same as byte 1 in bits 6-7, else ignored*/  0x00,   /* Byte 12: disable full duplex */  0x3f    /* Byte 13: no multi IA, backoff enabled */};/* Local Routines */static unsigned long word_swap ( unsigned long );static void * malloc_16byte_aligned ( void **, void ** adjusted_pointer, size_t );RTEMS_INLINE_ROUTINE void uti596_writePortFunction ( volatile void *, unsigned long );RTEMS_INLINE_ROUTINE void uti596_portReset( void );static unsigned long uti596_portSelfTest( i596_selftest * );static int uti596_portDump ( i596_dump_result * );static int uti596_wait ( uti596_softc_ *, unsigned8 );static int uti596_issueCA ( uti596_softc_ *, unsigned8 );static void uti596_addCmd ( i596_cmd * );static void uti596_addPolledCmd ( i596_cmd * );static void uti596_CU_dump ( i596_dump_result * );static void uti596_dump_scb ( void );static int uti596_setScpAndScb ( uti596_softc_ * );static int uti596_diagnose ( void );static int uti596_configure ( uti596_softc_ * );static int uti596_IAsetup ( uti596_softc_ * );static int uti596_initTBD ( uti596_softc_ * );static int uti596_initRFA ( int );static void uti596_initMem ( uti596_softc_ * );static void uti596_initialize ( uti596_softc_ * );static void uti596_initialize_hardware ( uti596_softc_ * );static void uti596_reset_hardware ( uti596_softc_ *);static void uti596_reset ( void );static void uti596_clearListStatus ( i596_rfd * );static i596_rfd * uti596_dequeue ( i596_rfd ** );static void uti596_append ( i596_rfd ** , i596_rfd * );static void uti596_supplyFD ( i596_rfd * );static void send_packet ( struct ifnet *, struct mbuf * );/* Required RTEMS network driver functions and tasks (plus reset daemon) */static void uti596_start ( struct ifnet * );void uti596_init ( void * );void uti596_stop ( uti596_softc_ * );void uti596_txDaemon ( void * );void uti596_rxDaemon ( void * );void uti596_resetDaemon( void * );rtems_isr uti596_DynamicInterruptHandler ( rtems_vector_number );static int uti596_ioctl ( struct ifnet *, int, caddr_t );void uti596_stats ( uti596_softc_ * );#ifdef DBG_PACKETSstatic void dumpQ( void );static void show_buffers( void );static void show_queues( void );static void print_eth  ( unsigned char * );static void print_hdr  ( unsigned char * );static void print_pkt  ( unsigned char * );static void print_echo ( unsigned char * );#endif/* *  word_swap * *  Return a 32 bit value, swapping the upper and lower words first. * *  Input parameters: *    val - 32 bit value to swap * *  Output parameters: NONE * *  Return value: *    Input value with upper and lower 16-bit words swapped */static unsigned long word_swap(  unsigned long val){  return (((val >> 16)&(0x0000ffff)) | ((val << 16)&(0xffff0000)));}/* *  malloc_16byte_aligned * *  Allocate a block of a least nbytes aligned on a 16-byte boundary. *  Clients are responsible to store both the real address and the adjusted *  address. The real address must be used to free the block. * *  Input parameters: *    real_pointer - pointer to a void * pointer in which to store the starting *                   address of the block. Required for free. *    adjusted_pointer - pointer to a void * pointer in which to store the *                       starting address of the block rounded up to the next *                       16 byte boundary. *    nbytes - number of bytes of storage requested * *  Output parameters: *    real_pointer - starting address of the block. *    adjusted_pointer - starting address of the block rounded up to the next *                       16 byte boundary. * *  Return value: *    starting address of the block rounded up to the next 16 byte boundary. *    NULL if no storage was allocated. */static void * malloc_16byte_aligned(  void ** real_pointer,  void ** adjusted_pointer,  size_t nbytes){  *real_pointer = malloc( nbytes + 0xF, 0, M_NOWAIT );  *adjusted_pointer = (void *)(((unsigned long)*real_pointer + 0xF ) & 0xFFFFFFF0 );  return *adjusted_pointer;}/* *  uti596_scp_alloc * *  Allocate a new scp, possibly freeing a previously allocated one. * *  Input parameters: *    sc - pointer to the global uti596_softc in which to store pointers *         to the newly allocated block. * *  Output parameters: NONE * *  Return value: *    Pointer to the newly allocated, 16-byte aligned scp. */static i596_scp * uti596_scp_alloc(  uti596_softc_ * sc){  if( sc->base_scp != NULL ) {    #ifdef DBG_MEM    printk(("uti596_scp_alloc: Already have an SCP at %p\n", sc->base_scp))    #endif    return sc->pScp;  }      /* allocate enough memory for the Scp block to be aligned on 16 byte boundary */  malloc_16byte_aligned( (void *)&(sc->base_scp), (void *)&(sc->pScp), sizeof( i596_scp ) );  					  #ifdef DBG_MEM  printk(("uti596_scp_alloc: Scp base address is %p\n", sc->base_scp))  printk(("uti596_scp_alloc: Scp aligned address is : %p\n",sc->pScp))  #endif  return sc->pScp;}/* *  uti596_writePortFunction *   *  Write the command into the PORT. *   *  Input parameters: *    addr - 16-byte aligned address to write into the PORT. *    cmd - 4-bit cmd to write into the PORT * *  Output parameters: NONE * *  Return value: NONE *     *  The Motorola manual swapped the high and low registers. */RTEMS_INLINE_ROUTINE void uti596_writePortFunction(  volatile void * addr,  unsigned long cmd){  i82596->port_lower = (unsigned short)(((unsigned long)addr & 0xFFF0) | cmd);  i82596->port_upper = (unsigned short)(((unsigned long)addr >> 16 ) & 0xFFFF);}/* *  uti596_portReset *  *  Issue a port Reset to the uti596 *  *  Input parameters: NONE * *  Output parameters: NONE * *  Return value: NONE */RTEMS_INLINE_ROUTINE void uti596_portReset( void ){  uti596_writePortFunction( NULL, UTI596_RESET_PORT_FUNCTION );}/* *  uti596_portSelfTest * *  Perform a self-test. Wait for up to 1 second for the test to *  complete. Normally, the test should complete in a very short time, *  so busy waiting is not  an issue. * *  Input parameters: *    stp - pointer to a 16-byte aligned uti596_selftest structure. * *  Output parameters: NONE * *  Return value: *    32-bit result field if successful, -1 otherwise. */static unsigned long uti596_portSelfTest(  i596_selftest * stp){  rtems_interval ticks_per_second, start_ticks, end_ticks;    stp->results = 0xFFFFFFFF;  uti596_writePortFunction( stp, UTI596_SELFTEST_PORT_FUNCTION );  rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second);	rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_ticks);	end_ticks = start_ticks + ticks_per_second;		  do {    if( stp->results != 0xFFFFFFFF )      break;		else			rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_ticks);	} while (start_ticks <= end_ticks);  if (start_ticks > end_ticks ) {    #ifdef DBG_SELFTEST_CMD    printk(("uti596_selftest: Timed out\n" ))		#endif		return -1;  }  else {    #ifdef DBG_SELFTEST_CMD    printk(("uti596_selftest: Succeeded with signature = 0x%08x, result = 0x%08x\n",      			 stp->signature,             stp->results))		#endif		return stp->results;	}}  /* *  uti596_portDump * *  Perform a dump Wait for up to 1 second for the test to *  complete. Normally, the test should complete in a very short time, *  so busy waiting is not an issue. * *  Input parameters: *    dp - pointer to a 16-byte aligned uti596_dump structure. * *  Output parameters: NONE * *  Return value: *    16-bit dump_status field if successful, -1 otherwise. */static int uti596_portDump(  i596_dump_result * dp){  rtems_interval ticks_per_second, start_ticks, end_ticks;    dp->dump_status = 0;  uti596_writePortFunction( dp, UTI596_DUMP_PORT_FUNCTION );  rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second);	rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_ticks);	end_ticks = start_ticks + ticks_per_second;		  do {    if( dp->dump_status != 0xA006 )      break;		else			rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_ticks);	} while (start_ticks <= end_ticks);  if (start_ticks > end_ticks ) {    #ifdef DBG_DUMP_CMD    printk(("uti596_dump: Timed out with dump at 0x%08x\n", (unsigned long)dp ))		#endif		return -1;  }  else {    #ifdef DBG_DUMP_CMD    printk(("uti596_dump: Succeeded with dump at = 0x%08x\n", (unsigned long)dp ))		#endif		return dp->dump_status;	}}/* *  uti596_wait * *  Wait for a certain condition. *   *  Input parameters: *    sc - pointer to the uti596_softc struct *    wait_type - UTI596_NO_WAIT *    						UTI596_WAIT *                UTI596_WAIT_FOR_CU_ACCEPT *                UTI596_WAIT_FOR_INITIALIZATION *                UTI596_WAIT_FOR_STAT_C * *  Output parameters: NONE * *  Return value: *    0 if successful, -1 otherwise. */static int uti596_wait(  uti596_softc_ *sc,  unsigned8 waitType){  rtems_interval ticks_per_second, start_ticks, end_ticks;  rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second);	rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_ticks);	end_ticks = start_ticks + ticks_per_second;  switch( waitType ) {      case UTI596_NO_WAIT:      return 0;    case UTI596_WAIT_FOR_CU_ACCEPT:		  do {			  if (sc->scb.command == 0)				  break;			  else				  rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_ticks);					  } while (start_ticks <= end_ticks);		  		  if( (sc->scb.command != 0) || (start_ticks > end_ticks) ) {			  printf("i82596 timed out with status %x, cmd %x.\n",               sc->scb.status,  sc->scb.command);        return -1;      }      else        return 0;     case UTI596_WAIT_FOR_INITIALIZATION:		  do {		    if( !sc->iscp.busy )		      break;				else					rtems_clock_get(RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start_ticks);			} while (start_ticks <= end_ticks);		  if (start_ticks > end_ticks ) {		    #ifdef DBG_WAIT		    printk(("uti596_setScpAndScb: Timed out\n"  ))				#endif				return -1;		  }		  else {

⌨️ 快捷键说明

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