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

📄 network.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 5 页
字号:
/* uti595.c: An 82596 ethernet driver for rtems-bsd. * *  $Id: network.c,v 1.6 2002/11/04 22:17:34 joel Exp $ */void dump_scb(void);void printk_time(void);#ifdef DBG_VERSION#define BREAKPOINT()  asm("   int $3"); #else#define BREAKPOINT()#endif#define KERNEL/*      EII: Oct 16 : Version 0.0*/#define DMA_MODE_CASCADE 0xC0   /* pass thru DREQ->HRQ, DACK<-HLDA only */#define DMA_MASK_REG     0x0A#define DMA_MODE_REG     0x0B#define DMA_ENABLE       0x0#define DMA_DISABLE      0x4   struct i596_rfd *pISR_Rfd;  void show_buffers (void);void show_queues(void);void outbyte(char);void dumpQ(void);#define UTI_596_ASSERT( condition, str ) { if (!( condition ) ) printk(str); }int count_rx = 0;/* static char *version = "uti596.c:v0.0 11/13/97\n"; */#include <bsp.h>#include <stdio.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 <net/if.h>#include <netinet/in.h>#include <netinet/if_ether.h>#include "uti596.h"#include "netexterns.h"#include <asm.h>#include <string.h>/* #include "../misc/utils.h" */static struct uti596_softc uti596_softc;static    int scbStatus;static    struct i596_cmd *pIsrCmd;static    struct i596_rfd *pIsrRfd;/* * Initial 596 configuration */char uti596initSetup[] = {	0x0E,	/* length, prefetch off ( no RBD's ) */	0xC8,	/* fifo to 8, monitor off */	0x40,	/* don't save bad frames ( was save= 80, use intel's 40 )*/	0x2E,	/* No source address insertion, 8 byte preamble */	0x00,	/* priority and backoff defaults */	0x60,	/* interframe spacing */	0x00,	/* slot time LSB */	0xf2,	/* slot time and retries */	0x0C,	/* */	0x08,	/* collision detect */	0x40,	/* minimum frame length */	0xfb,	/* tried C8 same as byte 1 in bits 6-7, else ignored*/	0x00,	0x3f	/*  no multi IA */ };/* *  Externally defined symbols */#define RX_BUF_COUNT     15#define TX_BUF_COUNT     4#define TX_BD_PER_BUF    4#define INTERRUPT_EVENT         RTEMS_EVENT_1#define START_TRANSMIT_EVENT	RTEMS_EVENT_2#define NIC_RESET_EVENT	        RTEMS_EVENT_3#define RBUF_SIZE	1520/* * Local Routines *//* These are extern, and non-inline  for testing purposes */void        uti596addCmd                  (struct i596_cmd *pCmd);void        uti596_initMem                (struct uti596_softc *); void        uti596_init                   (void * );int         uti596initRxBufs              (int num);int         uti596_initRFA                (int num);int         uti596initRxBufs              (int num);static int  uti596_ioctl                  (struct ifnet *, int, caddr_t);rtems_isr   uti596DynamicInterruptHandler (rtems_vector_number);void        uti596_txDaemon               (void *);void        uti596_rxDaemon               (void *);void        uti596_resetDaemon            (void *);void        uti596_stop                   (struct uti596_softc *);static void uti596_start                  (struct ifnet *);void        uti596reset            (void);void         uti596_stats      (struct uti596_softc *);void uti596_initialize_hardware(struct uti596_softc *);void uti596_reset_hardware(struct uti596_softc *);void uti596clearListStatus(struct i596_rfd *);void uti596addPolledCmd(struct i596_cmd *);void uti596supplyFD(struct i596_rfd *);struct i596_rfd * uti596dequeue( struct i596_rfd ** );void uti596append( struct i596_rfd ** , struct i596_rfd * ); #ifdef DEBUG_INITstatic void         print_eth              (unsigned char *);static void         print_hdr              (unsigned char *);static void         print_pkt              (unsigned char *);#endifvoid send_packet(struct ifnet *, struct mbuf *);#define UTI_596_IRQ 5#define UTI_596_ETH_MIN_SIZE 60/* Waits for the command word to clear.  The command word is cleared AFTER the interrupt is * generated. This allows the CPU to issue the next command */#define  UTI_WAIT_COMMAND_ACCEPTED(duration,function)\{   int waitcount = duration; \    while (  uti596_softc.scb.command ) \      if (--waitcount == 0) \	{ \	  printk("%s: i82596 timed out with status %x, cmd %x.\n", function, \                  uti596_softc.scb.status,  uti596_softc.scb.command); \	  break; \    	} \}/*************************************************************************/void uti596_request_reset(void){   rtems_status_code sc;   uti596_softc.nic_reset = 0;   sc = rtems_event_send(uti596_softc.resetDaemonTid, NIC_RESET_EVENT);   if ( sc != RTEMS_SUCCESSFUL )     rtems_panic ("Can't notify resetDaemon: %s\n", rtems_status_text (sc));}static void uti596_maskOn(const rtems_irq_connect_data* irq){  /*   * code should be moved from initialize_hardware   * to this location ?   */  (void) BSP_irq_enable_at_i8259s (irq->name);}static void uti596_maskOff(const rtems_irq_connect_data* irq){  /*   * code should be moved from initialize_hardware   * to this location ?   */  (void) BSP_irq_disable_at_i8259s (irq->name);}static int uti596_isOn(const rtems_irq_connect_data* irq){  return BSP_irq_enabled_at_i8259s (irq->name);}/*********************************************************************** *  Function:   uti596initRFA(int num) ( New ) * *  Description: *              attempts to allocate and initialize ( chain together ) *              the requested number of FD's * *  Algorithm: * ***********************************************************************/int uti596_initRFA(int num){    struct i596_rfd *pRfd;    int i = 0;#ifdef DBG_596    printf ("%s: uti596_initRFA %d.\n", num);#endif    /*      * Initialize the first rfd in the rfa     */    pRfd = (struct i596_rfd *) calloc (1,sizeof (struct i596_rfd));    if ( !pRfd ) {      printf("Can't allocate all buffers: only %d allocated\n", i);      return 0;    }    else {      uti596_softc.countRFD = 1;      uti596_softc.pBeginRFA = uti596_softc.pEndRFA = pRfd;    printf ( "First Rfd allocated is: %p\n", 	     uti596_softc.pBeginRFA);    }    for (i = 1; i < num; i++) {      pRfd = (struct i596_rfd *) calloc (1,sizeof (struct i596_rfd) );      if ( pRfd != NULL ) {	uti596_softc.countRFD++;	uti596_softc.pEndRFA -> next = pRfd; /* link it in   */	  	uti596_softc.pEndRFA         = pRfd; /* move the end */#ifdef DBG_596_RFA	printf("Allocated RFD @ %p\n", pRfd);#endif      }      else {		printf("Can't allocate all buffers: only %d allocated\n", i);	break;      }    } /* end for */        uti596_softc.pEndRFA -> next = I596_NULL;    UTI_596_ASSERT(uti596_softc.countRFD == RX_BUF_COUNT,"INIT:WRONG RFD COUNT\n" );     #ifdef DBG_596_RFA    printf ( "Head of RFA is buffer %p\nEnd of RFA is buffer %p \n", 	     uti596_softc.pBeginRFA, 	     uti596_softc.pEndRFA );#endif    /* initialize the Rfd's */    for ( pRfd = uti596_softc.pBeginRFA;	  pRfd != I596_NULL;	  pRfd = pRfd -> next ) {	        pRfd->cmd = 0x0000;      pRfd->stat = 0x0000;      pRfd->pRbd =  I596_NULL;      pRfd->count = 0;  /* number of bytes in buffer: usually less than size */      pRfd->size = 1532;      /* was 1532;  buffer size ( All RBD ) */      if ( pRfd -> data == NULL )	printf("Can't allocate the RFD data buffer\n");    }    /* mark the last FD */     uti596_softc.pEndRFA -> cmd = CMD_EOL; /* moved jan 13 from before the init stuff */#ifdef DBG_596_RFA    printf ( "Head of RFA is buffer @ %p \n", uti596_softc.pBeginRFA );#endif    uti596_softc.pSavedRfdQueue =       uti596_softc.pEndSavedQueue = I596_NULL;   /* initially empty */        uti596_softc.savedCount = 0;    uti596_softc.nop.cmd.command = CmdNOp; /* initialize the nop command */    return (i); /* the number of allocated buffers */    }/*********************************************************************** *  Function:   uti596supplyFD * *  Description: returns a buffer to the receive frame pool. *               call this with Inetrrupts disabled! * *  Algorithm: * ***********************************************************************/void uti596supplyFD(struct i596_rfd * pRfd ){ struct i596_rfd *pLastRfd; UTI_596_ASSERT(pRfd != I596_NULL, "Supplying NULL RFD!\n"); pRfd -> cmd  = CMD_EOL; pRfd -> pRbd = I596_NULL; pRfd -> next = I596_NULL; pRfd -> stat = 0x0000;      /* clear STAT_C and STAT_B bits */ /*   * Check if the list is empty:  */ if ( uti596_softc.pBeginRFA == I596_NULL ) {     /* Init a list w/ one entry */   uti596_softc.pBeginRFA = uti596_softc.pEndRFA = pRfd;   UTI_596_ASSERT(uti596_softc.countRFD == 0, "Null begin, but non-zero count\n");   if ( uti596_softc.pLastUnkRFD != I596_NULL )     printf("LastUnkRFD is NOT NULL!!\n");   uti596_softc.countRFD = 1;   return; } /*  * Check if the last RFD is used/read by the 596.  */ pLastRfd = uti596_softc.pEndRFA;  if (    pLastRfd != I596_NULL &&       ! (pLastRfd -> stat & ( STAT_C | STAT_B ) )) { /* C = complete, B = busy (prefetched) */      /*     * Not yet too late to add it     */   pLastRfd -> next = pRfd;   pLastRfd -> cmd &= ~CMD_EOL;  /* RESET_EL : reset EL bit to 0  */   uti596_softc.countRFD++;  /* Lets assume we add it successfully 			        If not, the RFD may be used, and may decrement countRFD < 0 !!*/   /*    * Check if the last RFD was used while appending.    */   if ( pLastRfd -> stat & ( STAT_C | STAT_B ) ) { /* completed or was prefetched */     /*       * Either the EL bit of the last rfd has been read by the 82596,      * and it will stop after reception,( true when RESET_EL not reached ) or      * the EL bit was NOT read by the 82596 and it will use the linked      * RFD for the next reception. ( true is RESET_EL was reached )      * So, it is unknown whether or not the linked rfd will be used.      * Therefore, the end of list CANNOT be updated.      */     UTI_596_ASSERT ( uti596_softc.pLastUnkRFD == I596_NULL, "Too many Unk RFD's\n" );     uti596_softc.pLastUnkRFD = pRfd;                   return;   }   else {     /*      * The RFD being added was not touched by the 82596      */     if (uti596_softc.pLastUnkRFD != I596_NULL ) {          uti596append(&uti596_softc.pSavedRfdQueue, pRfd); /* Only here! saved Q */       uti596_softc.pEndSavedQueue = pRfd;       uti596_softc.savedCount++;       uti596_softc.countRFD--;            }     else {       uti596_softc.pEndRFA = pRfd;           /* the RFA has been extended */       if ( ( uti596_softc.scb.status & SCB_STAT_RNR || 	      uti596_softc.scb.status & RU_NO_RESOURCES ) &&	    uti596_softc.countRFD > 1 ) {   /* was == 2 */	 uti596_softc.pBeginRFA -> cmd &= ~CMD_EOL;  /* Ensure that beginRFA is not EOL */	 	 UTI_596_ASSERT(uti596_softc.pEndRFA -> next == I596_NULL, "supply: List buggered\n");	 UTI_596_ASSERT(uti596_softc.pEndRFA -> cmd & CMD_EOL, "supply: No EOL at end.\n");	 UTI_596_ASSERT(uti596_softc.scb.command == 0, "Supply: scb command must be zero\n");#ifdef DBG_START	 printf("Supply FD: starting receiver");#endif	 /* start the receiver */	 UTI_596_ASSERT(uti596_softc.pBeginRFA != I596_NULL, "rx start w/ NULL begin! \n");	 uti596_softc.scb.pRfd = uti596_softc.pBeginRFA;	 uti596_softc.scb.command = RX_START | SCB_STAT_RNR;  /* Don't ack RNR! The receiver should be stopped in this case */	 UTI_596_ASSERT( !(uti596_softc.scb.status & SCB_STAT_FR),"FRAME RECEIVED INT COMING!\n");	 outport_byte(CHAN_ATTN, 0);        }     }     return;        } }  else {   /*     * too late , pLastRfd in use ( or NULL ),     * in either case, EL bit has been read, and RNR condition will occur     */   uti596append( &uti596_softc.pSavedRfdQueue, pRfd); /* save it for RNR */      uti596_softc.pEndSavedQueue = pRfd;                /* reset end of saved queue */     uti596_softc.savedCount++;          return; }}static voiduti596_start (struct ifnet *ifp){	struct uti596_softc *sc = ifp->if_softc;	rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT);	ifp->if_flags |= IFF_OACTIVE;}voiduti596_initialize_hardware(struct uti596_softc *sc){  int boguscnt = 1000;  rtems_status_code status_code;  printf("uti596_initialize_hardware\n");    /* reset the board  */  outport_word( PORT_ADDR, 0 );  outport_word( PORT_ADDR, 0 );  uti596_softc.pScp = (struct i596_scp *) calloc(1,sizeof(struct i596_scp) + 0xf);#ifdef DBG_INIT  printf("initialize_hardware:Scp address initially %p\n", sc->pScp);#endif  sc->pScp = (struct i596_scp *)    ((((int)uti596_softc.pScp) + 0xf) & 0xfffffff0);#ifdef DBG_INIT  printf("initialize_hardware:change scp address to : %p\n",sc->pScp);#endif    /* change the scp address */#ifdef DBG_INIT  printf("Change the SCP address\n");#endif    /*   * Set the DMA mode to enable the 82596 to become a bus-master   */  outport_byte(DMA_MASK_REG,DMA_DISABLE);      /* disable_dma */  outport_byte(DMA_MODE_REG,DMA_MODE_CASCADE); /* set dma mode */  outport_byte(DMA_MASK_REG,DMA_ENABLE);       /* enable dma */  /* reset the board  */  outport_word( PORT_ADDR, 0 );  outport_word( PORT_ADDR, 0 );    outport_word(PORT_ADDR, ((((int)sc->pScp) &  0xffff) | 2 ));  outport_word(PORT_ADDR, (( (int)sc->pScp) >> 16 ) & 0xffff );    /* This is linear mode, LOCK function is disabled  */    sc->pScp->sysbus = 0x00540000;  sc->pScp->iscp   = &sc->iscp;  sc->iscp.scb     = &sc->scb;  sc->iscp.stat    = 0x0001;    sc->pCmdHead     = sc->scb.pCmd = I596_NULL;  #ifdef DBG_596  printf("Starting i82596.\n");#endif    /* Pass the scb address to the 596 */

⌨️ 快捷键说明

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