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

📄 rtl_3c59x.c

📁 最新rtlinux内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
      if (vci->drv_flags & EEPROM_8BIT)	base = 0x230;      else if (vci->drv_flags & EEPROM_OFFSET)	base = EEPROM_Read + 0x30;      else	base = EEPROM_Read;      for (i = 0; i < 0x40; i++) {	int timer;		/* This means that we want to read EepromCommand Register and disable writting */	/* Issuing ReadRegister & WriteDisable                                         */	outw(base + i, ioaddr + Wn0EepromCmd);	for (timer = 10; timer >= 0; timer--) {	  /* The read data is available through the EepromData register 162us after  */	  /* the ReadRegister command has been issued                                */	  rtl_delay(162000);	  /* Bit 15th (eepromBusy) of EepromCommand register is a read-only bit asserted   */	  /* during the execution of EEProm commands. Further commans should not be issued */	  /* to the EepromCommand register, nor should data be read from the EepromData    */	  /* register while this bit is true                                               */	  if ((inw(ioaddr + Wn0EepromCmd) & 0x8000) == 0)	    break;	}	/* Save the contents of the 3C90xC NIC's EEPROM     */ 	eeprom[i] = inw(ioaddr + Wn0EepromData);      }    }//EL3WINDOW(0) configuration finished    /* EEPROM can be checksummed in order to assure that reading was OK */    for (i = 0; i < 0x18; i++)      checksum ^= eeprom[i];    checksum = (checksum ^ (checksum >> 8)) & 0xff;    if (checksum != 0x00) {		/* Grrr, needless incompatible change 3Com. */      while (i < 0x21)	checksum ^= eeprom[i++];      checksum = (checksum ^ (checksum >> 8)) & 0xff;    }    if ((checksum != 0x00) && !(vci->drv_flags & IS_TORNADO))      printk(" ***INVALID CHECKSUM %4.4x*** ", checksum);        /* Save HW address into dev_addr (MAC address in format 00:04:75:bd:ea:e7) */    for (i = 0; i < 3; i++)      ((u16 *)private_data.dev_addr)[i] = htons(eeprom[i + 10]);        /* This writes into the StationAddress register the NIC's HW address in order */    /* to define the individual destination address that the NIC responds to when */    /* receiving packets                                                          */    EL3WINDOW(2);    for (i = 0; i < 6; i++)      outb(private_data.dev_addr[i], ioaddr + i);    EL3WINDOW(4);    step = (inb(ioaddr + Wn4_NetDiag) & 0x1e) >> 1;    if (dev && vci->drv_flags & HAS_CB_FNS) {      unsigned long fn_st_addr;			/* Cardbus function status space */      unsigned short n;            fn_st_addr = pci_resource_start (dev, 2);      if (fn_st_addr) {	private_data.cb_fn_base = ioremap(fn_st_addr, 128);	retval = -ENOMEM;	if (!private_data.cb_fn_base)	  goto free_ring;      }      EL3WINDOW(2);            n = inw(ioaddr + Wn2_ResetOptions) & ~0x4010;      if (private_data.drv_flags & INVERT_LED_PWR)	n |= 0x10;      if (private_data.drv_flags & INVERT_MII_PWR)	n |= 0x4000;      outw(n, ioaddr + Wn2_ResetOptions);    }    /* Extract our information from the EEPROM data. */    private_data.info1 = eeprom[13];    private_data.info2 = eeprom[15];    private_data.capabilities = eeprom[16];     if (private_data.info1 & 0x8000){      private_data.full_duplex = 1;      printk(KERN_INFO "Full duplex capable\n");    }    {      unsigned int config;      EL3WINDOW(3);      /* This reads the MediaOptions register which shows what physical media */      /* connections are available in the NIC                                 */      private_data.available_media = inw(ioaddr + Wn3_Options); //Wn3_Options = 8 vp.available_media = 0xa      if ((private_data.available_media & 0xff) == 0)		/* Broken 3c916 */	private_data.available_media = 0x40;      /* This reads the InternalConfig register which provides a way to set */      /* NIC-specific, non-host-related configuration settings              */       config = inl(ioaddr + Wn3_Config); //Wn3_Config = 0      private_data.default_media = XCVR(config);      if (private_data.default_media == XCVR_NWAY)	private_data.has_nway = 1;      private_data.autoselect = AUTOSELECT(config);    }    if (private_data.media_override != 7) {      private_data.if_port = private_data.media_override;    } else      private_data.if_port = private_data.default_media;    if (private_data.if_port == XCVR_MII || private_data.if_port == XCVR_NWAY) {      int phy, phy_idx = 0;      EL3WINDOW(4);      mii_preamble_required++;      mii_preamble_required++;      rtl_3COM905C_mdio_read(24, 1);      for (phy = 0; phy < 32 && phy_idx < 1; phy++) {	int mii_status, phyx;		/*	 * For the 3c905CX we look at index 24 first, because it bogusly	 * reports an external PHY at all indices	 */	if (phy == 0)	  phyx = 24;	else if (phy <= 24)	  phyx = phy - 1;	else	  phyx = phy;	mii_status = rtl_3COM905C_mdio_read(phyx, 1);	if (mii_status  &&  mii_status != 0xffff) {	  private_data.phys[phy_idx++] = phyx;	  	  if ((mii_status & 0x0040) == 0)	    mii_preamble_required++;	}      }		      mii_preamble_required--;      if (phy_idx == 0) {	private_data.phys[0] = 24;      } else {	private_data.advertising = rtl_3COM905C_mdio_read(private_data.phys[0], 4);	if (private_data.full_duplex) {	  /* Only advertise the FD media types. */	  private_data.advertising &= ~0x02A0;	  rtl_3COM905C_mdio_write(private_data.phys[0], 4, private_data.advertising);	}      }    }    if (private_data.capabilities & CapBusMaster) {      private_data.full_bus_master_tx = 1;            private_data.full_bus_master_rx = (private_data.info2 & 1) ? 1 : 2;      private_data.bus_master = 0;		/* AKPM: vortex only */    }    if (private_data.pdev && private_data.enable_wol) {      private_data.pm_state_valid = 1;      rt_pci_save_state(dev, private_data.power_state);      rtl_3COM905C_acpi_set_WOL();    }    vortex_open(dev);  }// if(dev)      return 0; free_ring:  pci_free_consistent(dev, sizeof(struct boom_rx_desc) * RX_RING_SIZE, private_data.rx_ring, private_data.rx_ring_dma);  pci_free_consistent(dev, sizeof(struct boom_tx_desc) * TX_RING_SIZE, private_data.tx_ring, private_data.tx_ring_dma);  return -1; free_region:  if (private_data.must_free_region){    release_region(ioaddr, vci->io_size);    private_data.must_free_region = 0;  }  printk("vortex_probe1 fails.  Returns %d\n", retval);  return -1;}/***************************************************************************************//* ACPI: Advanced Configuration and Power Interface.                                   *//* Set Wake-On-LAN mode and put the board into D3 (power-down) state.                  *//***************************************************************************************/static void rtl_3COM905C_acpi_set_WOL(void){  long ioaddr = private_data.ioaddr;  /* Power up on: 1==Downloaded Filter, 2==Magic Packets, 4==Link Status. */  EL3WINDOW(7);  outw(2, ioaddr + 0x0c);  /* The RxFilter must accept the WOL frames. */  outw(SetRxFilter|RxStation|RxBroadcast, ioaddr + EL3_CMD); //RxMulticast  outw(RxEnable, ioaddr + EL3_CMD);  /* Change the power state to D3; RxEnable doesn't take effect. */  rt_pci_enable_wake(private_data.pdev, 0, 1);  rt_pci_set_power_state(private_data.pdev, 3);}/***************************************************************************************//* This function registers the interrupt handler and reserves memory for buffers which *//* only will be accessed by the card.                                                  *//***************************************************************************************/static int vortex_open(struct pci_dev *dev){  int i;  int retval;    /* Use the now-standard shared IRQ implementation. */  if ((retval = rtl_request_irq(dev->irq, &boomerang_interrupt))) {    printk(KERN_ERR "%s: Could not reserve IRQ %d\n", dev->name, dev->irq);    goto out;  }else    private_data.must_free_irq = 1;  if (private_data.full_bus_master_rx) { /* Boomerang bus master. */    /* RX RING INITIALIZATION */    for (i = 0; i < RX_RING_SIZE; i++) {      unsigned char *skb;      private_data.rx_ring[i].next = cpu_to_le32(private_data.rx_ring_dma + sizeof(struct boom_rx_desc) * (i+1));      private_data.rx_ring[i].status = 0;	/* Clear complete bit. */      private_data.rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ | LAST_FRAG);      skb = rtl_malloc(PKT_BUF_SZ);      private_data.rx_skbuff[i] = skb;      if (skb == NULL)	break;			/* Bad news!  */      private_data.rx_ring[i].addr = cpu_to_le32(pci_map_single(private_data.pdev, skb, PKT_BUF_SZ, PCI_DMA_FROMDEVICE));    }    if (i != RX_RING_SIZE) {      int j;      printk(KERN_EMERG "%s: no memory for rx ring\n", dev->name);      for (j = 0; j < i; j++) {	if (private_data.rx_skbuff[j]) {	  rtl_free(private_data.rx_skbuff[j]);	  private_data.rx_skbuff[j] = 0;	}      }      retval = -ENOMEM;      goto out_free_irq;    }    /* Wrap the ring. */    private_data.rx_ring[i-1].next = cpu_to_le32(private_data.rx_ring_dma);    /* TX RING INITIALIZATION */    for (i = 0; i < TX_RING_SIZE; i++) {      unsigned char *skb;      private_data.tx_ring[i].next = 0;       private_data.tx_ring[i].status = 0;	/* Clear complete bit. */      private_data.tx_ring[i].length = cpu_to_le32(PKT_BUF_SZ | LAST_FRAG);      skb = rtl_malloc(PKT_BUF_SZ);      private_data.tx_skbuff[i] = skb;      if (skb == NULL)	break;			/* Bad news!  */      private_data.tx_ring[i].addr = cpu_to_le32(pci_map_single(private_data.pdev, skb, PKT_BUF_SZ, PCI_DMA_FROMDEVICE));    }        if (i != TX_RING_SIZE) {      int j;      printk(KERN_EMERG "%s: no memory for tx ring\n", dev->name);      for (j = 0; j < i; j++) {	if (private_data.tx_skbuff[j]) {	  rtl_free(private_data.tx_skbuff[j]);	  private_data.tx_skbuff[j] = 0;	}      }      retval = -ENOMEM;      goto out_free_irq;    }    /* Wrap the ring. */    private_data.tx_ring[i-1].next = cpu_to_le32(private_data.tx_ring_dma);  }  vortex_up(dev);  return 0;   out_free_irq:  rtl_free_irq(dev->irq);  out:  return retval;}/***************************************************************************************//* This function is also used to initialise the card. In this function we indicate     *//* which interrupts do we want the card to generate.                                   *//***************************************************************************************/static void vortex_up(struct pci_dev *dev){  long ioaddr = private_data.ioaddr;  unsigned int config;  int i;    private_data.rx_packets = 0;  private_data.rx_frames_for_us = 0;  if (private_data.pdev && private_data.enable_wol) {    rt_pci_set_power_state(dev, 0);	/* Go active */    rt_pci_restore_state(dev, private_data.power_state);  }    /* Before initializing select the active media port. */  EL3WINDOW(3);  config = inl(ioaddr + Wn3_Config);  if (private_data.media_override != 7) {    private_data.if_port = private_data.media_override;  } else if (private_data.autoselect) {    if (private_data.has_nway) {    } else {      /* Find first available media type, starting with 100baseTx. */      private_data.if_port = XCVR_100baseTx;      while (! (private_data.available_media & media_tbl[private_data.if_port].mask))	private_data.if_port = media_tbl[private_data.if_port].next;    }  } else {    private_data.if_port = private_data.default_media;      }  private_data.full_duplex = private_data.force_fd;  config = BFINS(config, private_data.if_port, 20, 4);  outl(config, ioaddr + Wn3_Config);    if (private_data.if_port == XCVR_MII || private_data.if_port == XCVR_NWAY) {    int mii_reg1, mii_reg5;    EL3WINDOW(4);    /* Read BMSR (reg1) only to clear old status. */    mii_reg1 = rtl_3COM905C_mdio_read(private_data.phys[0], 1);    mii_reg5 = rtl_3COM905C_mdio_read(private_data.phys[0], 5);    if (mii_reg5 == 0xffff  ||  mii_reg5 == 0x0000)      ;					/* No MII device or no link partner report */    else if ((mii_reg5 & 0x0100) != 0	/* 100baseTx-FD */	     || (mii_reg5 & 0x00C0) == 0x0040) /* 10T-FD, but not 100-HD */      private_data.full_duplex = 1;    private_data.partner_flow_ctrl = ((mii_reg5 & 0x0400) != 0);    EL3WINDOW(3);  }  private_data.full_duplex = 1;  /* Set the full-duplex bit. */  outw(	((private_data.info1 & 0x8000) || private_data.full_duplex ? 0x20 : 0) |	(private_data.mtu > 1500 ? 0x40 : 0) |	((private_data.full_duplex && private_data.flow_ctrl && private_data.partner_flow_ctrl) ? 0x100 : 0),	ioaddr + Wn3_MAC_Ctrl);    rtl_3COM905C_issue_and_wait(TxReset);  /*   * Don't reset the PHY - that upsets autonegotiation during DHCP operations.   */  rtl_3COM905C_issue_and_wait(RxReset|0x04);    outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);  EL3WINDOW(4);  /* Set the station address and mask in window 2 each time opened. */  EL3WINDOW(2);  for (i = 0; i < 6; i++)    outb(private_data.dev_addr[i], ioaddr + i);  for (; i < 12; i+=2)    outw(0, ioaddr + i);    if (private_data.cb_fn_base) {    unsigned short n = inw(ioaddr + Wn2_ResetOptions) & ~0x4010;    if (private_data.drv_flags & INVERT_LED_PWR)      n |= 0x10;    if (private_data.drv_flags & INVERT_MII_PWR)      n |= 0x4000;    outw(n, ioaddr + Wn2_ResetOptions);  }    if (private_data.if_port == XCVR_10base2)    /* Start the thinnet transceiver. We should really wait 50ms...*/    outw(StartCoax, ioaddr + EL3_CMD);  if (private_data.if_port != XCVR_NWAY) {    EL3WINDOW(4);    outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) |	 media_tbl[private_data.if_port].media_bits, ioaddr + Wn4_Media);

⌨️ 快捷键说明

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