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

📄 hp100.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
  hp100_stop_interface( dev );   hp100_hwinit( dev );  hp100_start_interface( dev ); /* sets mac modes, enables interrupts */  return 0;}/* The close function is called when the interface is to be brought down */static int hp100_close( struct device *dev ){  int ioaddr = dev->base_addr;  struct hp100_private *lp = (struct hp100_private *)dev->priv;#ifdef HP100_DEBUG_B  hp100_outw( 0x4205, TRACE );  printk("hp100: %s: close\n", dev->name);#endif  hp100_page( PERFORMANCE );  hp100_outw( 0xfefe, IRQ_MASK );    /* mask off all IRQs */  hp100_stop_interface( dev );  if ( lp->lan_type == HP100_LAN_100 )     lp->hub_status=hp100_login_to_vg_hub( dev, FALSE );  dev->tbusy = 1;  dev->start = 0;  free_irq( dev->irq, dev );#ifdef HP100_DEBUG  printk( "hp100: %s: close LSW = 0x%x\n", dev->name, hp100_inw(OPTION_LSW) );#endif  MOD_DEC_USE_COUNT;  return 0;}/* * Configure the PDL Rx rings and LAN  */static void hp100_init_pdls( struct device *dev ){  struct hp100_private *lp = (struct hp100_private *)dev->priv;  hp100_ring_t         *ringptr;  u_int                *pageptr;  int                  i;#ifdef HP100_DEBUG_B  int ioaddr = dev->base_addr;#endif#ifdef HP100_DEBUG_B  hp100_outw( 0x4206, TRACE );  printk("hp100: %s: init pdls\n", dev->name);#endif  if(0==lp->page_vaddr_algn)    printk("hp100: %s: Warning: lp->page_vaddr_algn not initialised!\n",dev->name);  else    {      /* pageptr shall point into the DMA accessible memory region  */      /* we use this pointer to status the upper limit of allocated */      /* memory in the allocated page. */      /* note: align the pointers to the pci cache line size */      memset(lp->page_vaddr_algn, 0, MAX_RINGSIZE); /* Zero  Rx/Tx ring page */      pageptr=lp->page_vaddr_algn;						      lp->rxrcommit =0;      ringptr = lp->rxrhead = lp-> rxrtail = &(lp->rxring[0]);            /* Initialise Rx Ring */      for (i=MAX_RX_PDL-1; i>=0; i--)        {          lp->rxring[i].next = ringptr;          ringptr=&(lp->rxring[i]);          pageptr+=hp100_init_rxpdl(dev, ringptr, pageptr);        }            /* Initialise Tx Ring */      lp->txrcommit = 0;      ringptr = lp->txrhead = lp->txrtail = &(lp->txring[0]);      for (i=MAX_TX_PDL-1; i>=0; i--)        {          lp->txring[i].next = ringptr;          ringptr=&(lp->txring[i]);          pageptr+=hp100_init_txpdl(dev, ringptr, pageptr);        }    }}/* These functions "format" the entries in the pdl structure   *//* They return how much memory the fragments need.            */static int hp100_init_rxpdl( struct device *dev, register hp100_ring_t *ringptr, register u32 *pdlptr ){  /* pdlptr is starting address for this pdl */  if( 0!=( ((unsigned)pdlptr) & 0xf) )    printk("hp100: %s: Init rxpdl: Unaligned pdlptr 0x%x.\n",dev->name,(unsigned)pdlptr);  ringptr->pdl       = pdlptr+1;   ringptr->pdl_paddr = virt_to_bus(pdlptr+1);  ringptr->skb       = (void *) NULL;   /*    * Write address and length of first PDL Fragment (which is used for   * storing the RX-Header   * We use the 4 bytes _before_ the PDH in the pdl memory area to    * store this information. (PDH is at offset 0x04)   */  /* Note that pdlptr+1 and not pdlptr is the pointer to the PDH */  *(pdlptr+2) =(u_int) virt_to_bus(pdlptr);  /* Address Frag 1 */   *(pdlptr+3) = 4;                           /* Length  Frag 1 */  return( ( ((MAX_RX_FRAG*2+2)+3) /4)*4 );}static int hp100_init_txpdl( struct device *dev, register hp100_ring_t *ringptr, register u32 *pdlptr ){  if( 0!=( ((unsigned)pdlptr) & 0xf) )    printk("hp100: %s: Init txpdl: Unaligned pdlptr 0x%x.\n",dev->name,(unsigned) pdlptr);  ringptr->pdl       = pdlptr; /* +1; */    ringptr->pdl_paddr = virt_to_bus(pdlptr); /* +1 */  ringptr->skb = (void *) NULL;    return((((MAX_TX_FRAG*2+2)+3)/4)*4);}/* * hp100_build_rx_pdl allocates an skb_buff of maximum size plus two bytes  * for possible odd word alignment rounding up to next dword and set PDL * address for fragment#2  * Returns: 0 if unable to allocate skb_buff *          1 if successful */int hp100_build_rx_pdl( hp100_ring_t *ringptr, struct device *dev ){#ifdef HP100_DEBUG_B  int ioaddr = dev->base_addr;#endif#ifdef HP100_DEBUG_BM  u_int *p;#endif#ifdef HP100_DEBUG_B  hp100_outw( 0x4207, TRACE );  printk("hp100: %s: build rx pdl\n", dev->name);#endif  /* Allocate skb buffer of maximum size */  /* Note: This depends on the alloc_skb functions allocating more    * space than requested, i.e. aligning to 16bytes */  ringptr->skb = dev_alloc_skb( ((MAX_ETHER_SIZE+2+3)/4)*4 );		  if(NULL!=ringptr->skb)    {      /*        * Reserve 2 bytes at the head of the buffer to land the IP header       * on a long word boundary (According to the Network Driver section       * in the Linux KHG, this should help to increase performance.)       */      skb_reserve(ringptr->skb, 2);      ringptr->skb->dev=dev;       ringptr->skb->data=(u_char *)skb_put(ringptr->skb, MAX_ETHER_SIZE );						      /* ringptr->pdl points to the beginning of the PDL, i.e. the PDH */      /* Note: 1st Fragment is used for the 4 byte packet status       * (receive header). Its PDL entries are set up by init_rxpdl. So        * here we only have to set up the PDL fragment entries for the data       * part. Those 4 bytes will be stored in the DMA memory region        * directly before the PDL.        */#ifdef HP100_DEBUG_BM      printk("hp100: %s: build_rx_pdl: PDH@0x%x, skb->data (len %d) at 0x%x\n",      	     dev->name,	     (u_int) ringptr->pdl,	     ((MAX_ETHER_SIZE+2+3)/4)*4,	     (unsigned int) ringptr->skb->data);#endif      ringptr->pdl[0] = 0x00020000;                          /* Write PDH */      ringptr->pdl[3] = ((u_int)virt_to_bus(ringptr->skb->data));       ringptr->pdl[4] = MAX_ETHER_SIZE;                 /* Length of Data */						#ifdef HP100_DEBUG_BM      for(p=(ringptr->pdl); p<(ringptr->pdl+5); p++)        printk("hp100: %s: Adr 0x%.8x = 0x%.8x\n",dev->name,(u_int) p,(u_int) *p );#endif      return(1);    }  /* else: */  /* alloc_skb failed (no memory) -> still can receive the header   * fragment into PDL memory. make PDL safe by clearing msgptr and   * making the PDL only 1 fragment (i.e. the 4 byte packet status)   */#ifdef HP100_DEBUG_BM  printk("hp100: %s: build_rx_pdl: PDH@0x%x, No space for skb.\n",  	 dev->name,	 (u_int) ringptr->pdl);#endif  ringptr->pdl[0]=0x00010000;   /* PDH: Count=1 Fragment */  return(0);}/* *  hp100_rxfill - attempt to fill the Rx Ring will empty skb's * * Makes assumption that skb's are always contiguous memory areas and * therefore PDLs contain only 2 physical fragments. * -  While the number of Rx PDLs with buffers is less than maximum *      a.  Get a maximum packet size skb *      b.  Put the physical address of the buffer into the PDL. *      c.  Output physical address of PDL to adapter. */static void hp100_rxfill( struct device *dev ){  int ioaddr=dev->base_addr;   struct hp100_private  *lp      = (struct hp100_private *)dev->priv;  hp100_ring_t    *ringptr;#ifdef HP100_DEBUG_B  hp100_outw( 0x4208, TRACE );  printk("hp100: %s: rxfill\n",dev->name);#endif		  hp100_page( PERFORMANCE );  while (lp->rxrcommit < MAX_RX_PDL)    {      /*      ** Attempt to get a buffer and build a Rx PDL.      */      ringptr = lp->rxrtail;      if (0 == hp100_build_rx_pdl( ringptr, dev ))        {          return;      /* None available, return */        }            /* Hand this PDL over to the card */      /* Note: This needs performance page selected! */#ifdef HP100_DEBUG_BM      printk("hp100: %s: rxfill: Hand to card: pdl #%d @0x%x phys:0x%x, buffer: 0x%x\n",      	     dev->name,             lp->rxrcommit,             (u_int)ringptr->pdl,             (u_int)ringptr->pdl_paddr,             (u_int)ringptr->pdl[3]);#endif      hp100_outl( (u32)ringptr->pdl_paddr, RX_PDA);             lp->rxrcommit += 1;      lp->rxrtail = ringptr->next;    }}/* * BM_shutdown - shutdown bus mastering and leave chip in reset state */static void hp100_BM_shutdown( struct device *dev ){  int ioaddr = dev->base_addr;  struct hp100_private *lp = (struct hp100_private *)dev->priv;  unsigned long time;#ifdef HP100_DEBUG_B  hp100_outw( 0x4209, TRACE );  printk("hp100: %s: bm shutdown\n",dev->name);#endif  hp100_page( PERFORMANCE );  hp100_outw( 0xfefe, IRQ_MASK ); /* mask off all ints */  hp100_outw( 0xffff, IRQ_STATUS ); /* Ack all ints */  /* Ensure Interrupts are off */  hp100_outw( HP100_INT_EN | HP100_RESET_LB , OPTION_LSW );  /* Disable all MAC activity */  hp100_page( MAC_CTRL );  hp100_andb( ~(HP100_RX_EN | HP100_TX_EN), MAC_CFG_1 );  /* stop rx/tx */  /* If cascade MMU is not already in reset */  if (0 != (hp100_inw(OPTION_LSW)&HP100_HW_RST) )    {      /* Wait 1.3ms (10Mb max packet time) to ensure MAC is idle so       * MMU pointers will not be reset out from underneath       */      hp100_page( MAC_CTRL );      for(time=0; time<5000; time++)        {          if( (hp100_inb(MAC_CFG_1)&(HP100_TX_IDLE|HP100_RX_IDLE))==              (HP100_TX_IDLE|HP100_RX_IDLE) ) break;        }            /* Shutdown algorithm depends on the generation of Cascade */      if( lp->chip==HP100_CHIPID_LASSEN )        { /* ETR shutdown/reset */          /* Disable Busmaster mode and wait for bit to go to zero. */          hp100_page(HW_MAP);          hp100_andb( ~HP100_BM_MASTER, BM );          /* 100 ms timeout */          for(time=0; time<32000; time++)            {              if ( 0 == (hp100_inb( BM ) & HP100_BM_MASTER) ) break;            }        }      else        { /* Shasta or Rainier Shutdown/Reset */          /* To ensure all bus master inloading activity has ceased,           * wait for no Rx PDAs or no Rx packets on card.            */          hp100_page( PERFORMANCE );          /* 100 ms timeout */          for(time=0; time<10000; time++)            {              /* RX_PDL: PDLs not executed. */              /* RX_PKT_CNT: RX'd packets on card. */              if ( (hp100_inb( RX_PDL ) == 0) &&                   (hp100_inb( RX_PKT_CNT ) == 0) ) break;            }                    if(time>=10000)            printk("hp100: %s: BM shutdown error.\n", dev->name);                    /* To ensure all bus master outloading activity has ceased,           * wait until the Tx PDA count goes to zero or no more Tx space           * available in the Tx region of the card.            */          /* 100 ms timeout */          for(time=0; time<10000; time++) {            if ( (0 == hp100_inb( TX_PKT_CNT )) &&                 (0 != (hp100_inb( TX_MEM_FREE )&HP100_AUTO_COMPARE))) break;          }                     /* Disable Busmaster mode */          hp100_page(HW_MAP);          hp100_andb( ~HP100_BM_MASTER, BM );        } /* end of shutdown procedure for non-etr parts */  						      hp100_cascade_reset( dev, TRUE );    }  hp100_page( PERFORMANCE );  /* hp100_outw( HP100_BM_READ | HP100_BM_WRITE | HP100_RESET_HB, OPTION_LSW ); */  /* Busmaster mode should be shut down now. */}/*  *  transmit functions *//* tx function for busmaster mode */static int hp100_start_xmit_bm( struct sk_buff *skb, struct device *dev ){  unsigned long flags;  int i, ok_flag;  int ioaddr = dev->base_addr;  struct hp100_private *lp = (struct hp100_private *)dev->priv;  hp100_ring_t *ringptr;#ifdef HP100_DEBUG_B  hp100_outw( 0x4210, TRACE );  printk("hp100: %s: start_xmit_bm\n",dev->name);#endif  if ( skb==NULL )    {#ifndef LINUX_2_1      dev_tint( dev );#endif      return 0;    }	  if ( skb->len <= 0 ) return 0;	  /* Get Tx ring tail pointer */  if( lp->txrtail->next==lp->txrhead )    {      /* No memory. */#ifdef HP100_DEBUG      printk("hp100: %s: start_xmit_bm: No TX PDL available.\n", dev->name);#endif      /* not waited long enough since last tx? */      if ( jiffies - dev->trans_start < HZ ) return -EAGAIN;      if ( lp->lan_type < 0 ) /* no LAN type detected yet? */	{	  hp100_stop_interface( dev );	  if ( ( lp->lan_type = hp100_sense_lan( dev ) ) < 0 )	    {	      printk( "hp100: %s: no connection found - check wire\n", dev->name );	      hp100_start_interface( dev );  /* 10Mb/s RX pkts maybe handled */	      return -EIO;	    }	  if ( lp->lan_type == HP100_LAN_100 )	    lp->hub_status = hp100_login_to_vg_hub( dev, FALSE ); /* relogin */	  hp100_start_interface( dev );	}				      if ( lp->lan_type == HP100_LAN_100 && lp->hub_status < 0 )	/* we have a 100Mb/s adapter but it isn't connected to hub */	{	  printk( "hp100: %s: login to 100Mb/s hub retry\n", dev->name );

⌨️ 快捷键说明

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