diff options
Diffstat (limited to 'drivers/net')
278 files changed, 18287 insertions, 50416 deletions
diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c index da1a22c1386..ab18343e58e 100644 --- a/drivers/net/3c523.c +++ b/drivers/net/3c523.c @@ -990,7 +990,7 @@ static void elmc_rcv_int(struct net_device *dev) if (skb != NULL) { skb_reserve(skb, 2); /* 16 byte alignment */ skb_put(skb,totlen); - eth_copy_and_sum(skb, (char *) p->base+(unsigned long) rbd->buffer,totlen,0); + skb_copy_to_linear_data(skb, (char *) p->base+(unsigned long) rbd->buffer,totlen); skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); dev->last_rx = jiffies; diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index f26ca331615..6deb20fc7a0 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -324,7 +324,7 @@ static struct vortex_chip_info { {"3c980C Python-T", PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, }, {"3cSOHO100-TX Hurricane", - PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, }, + PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, }, {"3c555 Laptop Hurricane", PCI_USES_MASTER, IS_CYCLONE|EEPROM_8BIT|HAS_HWCKSM, 128, }, {"3c556 Laptop Tornado", diff --git a/drivers/net/7990.c b/drivers/net/7990.c index 0877fc372f4..e89ace109a5 100644 --- a/drivers/net/7990.c +++ b/drivers/net/7990.c @@ -333,9 +333,9 @@ static int lance_rx (struct net_device *dev) skb_reserve (skb, 2); /* 16 byte align */ skb_put (skb, len); /* make room */ - eth_copy_and_sum(skb, + skb_copy_to_linear_data(skb, (unsigned char *)&(ib->rx_buf [lp->rx_new][0]), - len, 0); + len); skb->protocol = eth_type_trans (skb, dev); netif_rx (skb); dev->last_rx = jiffies; diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index e8c9f27817b..807e6992e61 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -107,11 +107,6 @@ MODULE_PARM_DESC (multicast_filter_limit, "8139cp: maximum number of filtered mu #define PFX DRV_NAME ": " -#ifndef TRUE -#define FALSE 0 -#define TRUE (!FALSE) -#endif - #define CP_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ NETIF_MSG_PROBE | \ NETIF_MSG_LINK) @@ -435,20 +430,12 @@ static void cp_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) spin_lock_irqsave(&cp->lock, flags); cp->vlgrp = grp; - cp->cpcmd |= RxVlanOn; - cpw16(CpCmd, cp->cpcmd); - spin_unlock_irqrestore(&cp->lock, flags); -} - -static void cp_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) -{ - struct cp_private *cp = netdev_priv(dev); - unsigned long flags; + if (grp) + cp->cpcmd |= RxVlanOn; + else + cp->cpcmd &= ~RxVlanOn; - spin_lock_irqsave(&cp->lock, flags); - cp->cpcmd &= ~RxVlanOn; cpw16(CpCmd, cp->cpcmd); - vlan_group_set_device(cp->vlgrp, vid, NULL); spin_unlock_irqrestore(&cp->lock, flags); } #endif /* CP_VLAN_TAG_USED */ @@ -669,7 +656,7 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance) if (status & (TxOK | TxErr | TxEmpty | SWInt)) cp_tx(cp); if (status & LinkChg) - mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE); + mii_check_media(&cp->mii_if, netif_msg_link(cp), false); spin_unlock(&cp->lock); @@ -1196,7 +1183,7 @@ static int cp_open (struct net_device *dev) goto err_out_hw; netif_carrier_off(dev); - mii_check_media(&cp->mii_if, netif_msg_link(cp), TRUE); + mii_check_media(&cp->mii_if, netif_msg_link(cp), true); netif_start_queue(dev); return 0; @@ -1812,7 +1799,6 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) void __iomem *regs; resource_size_t pciaddr; unsigned int addr_len, i, pci_using_dac; - u8 pci_rev; #ifndef MODULE static int version_printed; @@ -1820,13 +1806,11 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) printk("%s", version); #endif - pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev < 0x20) { + pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision < 0x20) { dev_err(&pdev->dev, "This (id %04x:%04x rev %02x) is not an 8139C+ compatible chip\n", - pdev->vendor, pdev->device, pci_rev); + pdev->vendor, pdev->device, pdev->revision); dev_err(&pdev->dev, "Try the \"8139too\" driver instead.\n"); return -ENODEV; } @@ -1944,7 +1928,6 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) #if CP_VLAN_TAG_USED dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; dev->vlan_rx_register = cp_vlan_rx_register; - dev->vlan_rx_kill_vid = cp_vlan_rx_kill_vid; #endif if (pci_using_dac) @@ -2059,7 +2042,7 @@ static int cp_resume (struct pci_dev *pdev) spin_lock_irqsave (&cp->lock, flags); - mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE); + mii_check_media(&cp->mii_if, netif_msg_link(cp), false); spin_unlock_irqrestore (&cp->lock, flags); diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index a844b1fe2dc..327eaa7b499 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -931,7 +931,6 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, int i, addr_len, option; void __iomem *ioaddr; static int board_idx = -1; - u8 pci_rev; assert (pdev != NULL); assert (ent != NULL); @@ -949,13 +948,11 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, } #endif - pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); - if (pdev->vendor == PCI_VENDOR_ID_REALTEK && - pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev >= 0x20) { + pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) { dev_info(&pdev->dev, "This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n", - pdev->vendor, pdev->device, pci_rev); + pdev->vendor, pdev->device, pdev->revision); dev_info(&pdev->dev, "Use the \"8139cp\" driver for improved performance and stability.\n"); } @@ -2017,7 +2014,7 @@ no_early_rx: #if RX_BUF_IDX == 3 wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); #else - eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0); + skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); #endif skb_put (skb, pkt_size); diff --git a/drivers/net/8390.h b/drivers/net/8390.h index 414de5bd228..04ddec0f4c6 100644 --- a/drivers/net/8390.h +++ b/drivers/net/8390.h @@ -73,6 +73,9 @@ struct ei_device { u32 *reg_offset; /* Register mapping table */ spinlock_t page_lock; /* Page register locks */ unsigned long priv; /* Private field to store bus IDs etc. */ +#ifdef AX88796_PLATFORM + unsigned char rxcr_base; /* default value for RXCR */ +#endif }; /* The maximum number of 8390 interrupt service routines called per IRQ. */ @@ -86,11 +89,19 @@ struct ei_device { /* Some generic ethernet register configurations. */ #define E8390_TX_IRQ_MASK 0xa /* For register EN0_ISR */ #define E8390_RX_IRQ_MASK 0x5 + +#ifdef AX88796_PLATFORM +#define E8390_RXCONFIG (ei_status.rxcr_base | 0x04) +#define E8390_RXOFF (ei_status.rxcr_base | 0x20) +#else #define E8390_RXCONFIG 0x4 /* EN0_RXCR: broadcasts, no multicast,errors */ #define E8390_RXOFF 0x20 /* EN0_RXCR: Accept no packets */ +#endif + #define E8390_TXCONFIG 0x00 /* EN0_TXCR: Normal transmit mode */ #define E8390_TXOFF 0x02 /* EN0_TXCR: Transmitter off */ + /* Register accessed at EN_CMD, the 8390 base addr. */ #define E8390_STOP 0x01 /* Stop and reset the chip */ #define E8390_START 0x02 /* Start the chip, clear reset */ diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 1798a9f9fb2..d17d64eb706 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -3,10 +3,7 @@ # Network device configuration # -menu "Network device support" - depends on NET - -config NETDEVICES +menuconfig NETDEVICES default y if UML bool "Network device support" ---help--- @@ -28,6 +25,14 @@ config NETDEVICES # that for each of the symbols. if NETDEVICES +config NETDEVICES_MULTIQUEUE + bool "Netdevice multiple hardware queue support" + ---help--- + Say Y here if you want to allow the network stack to use multiple + hardware TX queues on an ethernet device. + + Most people will say N here. + config IFB tristate "Intermediate Functional Block support" depends on NET_CLS_ACT @@ -77,6 +82,16 @@ config BONDING To compile this driver as a module, choose M here: the module will be called bonding. +config MACVLAN + tristate "MAC-VLAN support (EXPERIMENTAL)" + depends on EXPERIMENTAL + ---help--- + This allows one to create virtual interfaces that map packets to + or from specific MAC addresses to a particular interface. + + To compile this driver as a module, choose M here: the module + will be called macvlan. + config EQUALIZER tristate "EQL (serial line load balancing) support" ---help--- @@ -151,11 +166,9 @@ source "drivers/net/phy/Kconfig" # Ethernet # -menu "Ethernet (10 or 100Mbit)" - depends on !UML - -config NET_ETHERNET +menuconfig NET_ETHERNET bool "Ethernet (10 or 100Mbit)" + depends on !UML ---help--- Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common type of Local Area Network (LAN) in universities and companies. @@ -180,9 +193,10 @@ config NET_ETHERNET kernel: saying N will just cause the configurator to skip all the questions about Ethernet network cards. If unsure, say N. +if NET_ETHERNET + config MII tristate "Generic Media Independent Interface device support" - depends on NET_ETHERNET help Most ethernet controllers have MII transceiver either as an external or internal device. It is safe to say Y or M here even if your @@ -190,7 +204,7 @@ config MII config MACB tristate "Atmel MACB support" - depends on NET_ETHERNET && (AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263) + depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263 select MII help The Atmel MACB ethernet interface is found on many AT32 and AT91 @@ -201,9 +215,18 @@ config MACB source "drivers/net/arm/Kconfig" +config AX88796 + tristate "ASIX AX88796 NE2000 clone support" + depends on ARM || MIPS + select CRC32 + select MII + help + AX88796 driver, using platform bus to provide + chip detection and resources + config MACE tristate "MACE (Power Mac ethernet) support" - depends on NET_ETHERNET && PPC_PMAC && PPC32 + depends on PPC_PMAC && PPC32 select CRC32 help Power Macintoshes and clones with Ethernet built-in on the @@ -226,7 +249,7 @@ config MACE_AAUI_PORT config BMAC tristate "BMAC (G3 ethernet) support" - depends on NET_ETHERNET && PPC_PMAC && PPC32 + depends on PPC_PMAC && PPC32 select CRC32 help Say Y for support of BMAC Ethernet interfaces. These are used on G3 @@ -237,7 +260,7 @@ config BMAC config ARIADNE tristate "Ariadne support" - depends on NET_ETHERNET && ZORRO + depends on ZORRO help If you have a Village Tronic Ariadne Ethernet adapter, say Y. Otherwise, say N. @@ -247,7 +270,7 @@ config ARIADNE config A2065 tristate "A2065 support" - depends on NET_ETHERNET && ZORRO + depends on ZORRO select CRC32 help If you have a Commodore A2065 Ethernet adapter, say Y. Otherwise, @@ -258,7 +281,7 @@ config A2065 config HYDRA tristate "Hydra support" - depends on NET_ETHERNET && ZORRO + depends on ZORRO select CRC32 help If you have a Hydra Ethernet adapter, say Y. Otherwise, say N. @@ -268,7 +291,7 @@ config HYDRA config ZORRO8390 tristate "Zorro NS8390-based Ethernet support" - depends on NET_ETHERNET && ZORRO + depends on ZORRO select CRC32 help This driver is for Zorro Ethernet cards using an NS8390-compatible @@ -281,7 +304,7 @@ config ZORRO8390 config APNE tristate "PCMCIA NE2000 support" - depends on NET_ETHERNET && AMIGA_PCMCIA + depends on AMIGA_PCMCIA select CRC32 help If you have a PCMCIA NE2000 compatible adapter, say Y. Otherwise, @@ -292,7 +315,7 @@ config APNE config APOLLO_ELPLUS tristate "Apollo 3c505 support" - depends on NET_ETHERNET && APOLLO + depends on APOLLO help Say Y or M here if your Apollo has a 3Com 3c505 ISA Ethernet card. If you don't have one made for Apollos, you can use one from a PC, @@ -301,7 +324,7 @@ config APOLLO_ELPLUS config MAC8390 bool "Macintosh NS 8390 based ethernet cards" - depends on NET_ETHERNET && MAC + depends on MAC select CRC32 help If you want to include a driver to support Nubus or LC-PDS @@ -311,7 +334,7 @@ config MAC8390 config MAC89x0 tristate "Macintosh CS89x0 based ethernet cards" - depends on NET_ETHERNET && MAC + depends on MAC ---help--- Support for CS89x0 chipset based Ethernet cards. If you have a Nubus or LC-PDS network (Ethernet) card of this type, say Y and @@ -324,7 +347,7 @@ config MAC89x0 config MACSONIC tristate "Macintosh SONIC based ethernet (onboard, NuBus, LC, CS)" - depends on NET_ETHERNET && MAC + depends on MAC ---help--- Support for NatSemi SONIC based Ethernet devices. This includes the onboard Ethernet in many Quadras as well as some LC-PDS, @@ -338,7 +361,7 @@ config MACSONIC config MACMACE bool "Macintosh (AV) onboard MACE ethernet" - depends on NET_ETHERNET && MAC + depends on MAC select CRC32 help Support for the onboard AMD 79C940 MACE Ethernet controller used in @@ -348,7 +371,7 @@ config MACMACE config MVME147_NET tristate "MVME147 (Lance) Ethernet support" - depends on NET_ETHERNET && MVME147 + depends on MVME147 select CRC32 help Support for the on-board Ethernet interface on the Motorola MVME147 @@ -358,7 +381,7 @@ config MVME147_NET config MVME16x_NET tristate "MVME16x Ethernet support" - depends on NET_ETHERNET && MVME16x + depends on MVME16x help This is the driver for the Ethernet interface on the Motorola MVME162, 166, 167, 172 and 177 boards. Say Y here to include the @@ -367,7 +390,7 @@ config MVME16x_NET config BVME6000_NET tristate "BVME6000 Ethernet support" - depends on NET_ETHERNET && BVME6000 + depends on BVME6000 help This is the driver for the Ethernet interface on BVME4000 and BVME6000 VME boards. Say Y here to include the driver for this chip @@ -376,7 +399,7 @@ config BVME6000_NET config ATARILANCE tristate "Atari Lance support" - depends on NET_ETHERNET && ATARI + depends on ATARI help Say Y to include support for several Atari Ethernet adapters based on the AMD Lance chipset: RieblCard (with or without battery), or @@ -384,7 +407,7 @@ config ATARILANCE config ATARI_BIONET tristate "BioNet-100 support" - depends on NET_ETHERNET && ATARI && ATARI_ACSI && BROKEN + depends on ATARI && ATARI_ACSI && BROKEN help Say Y to include support for BioData's BioNet-100 Ethernet adapter for the ACSI port. The driver works (has to work...) with a polled @@ -392,7 +415,7 @@ config ATARI_BIONET config ATARI_PAMSNET tristate "PAMsNet support" - depends on NET_ETHERNET && ATARI && ATARI_ACSI && BROKEN + depends on ATARI && ATARI_ACSI && BROKEN help Say Y to include support for the PAMsNet Ethernet adapter for the ACSI port ("ACSI node"). The driver works (has to work...) with a @@ -400,7 +423,7 @@ config ATARI_PAMSNET config SUN3LANCE tristate "Sun3/Sun3x on-board LANCE support" - depends on NET_ETHERNET && (SUN3 || SUN3X) + depends on SUN3 || SUN3X help Most Sun3 and Sun3x motherboards (including the 3/50, 3/60 and 3/80) featured an AMD Lance 10Mbit Ethernet controller on board; say Y @@ -413,7 +436,7 @@ config SUN3LANCE config SUN3_82586 bool "Sun3 on-board Intel 82586 support" - depends on NET_ETHERNET && SUN3 + depends on SUN3 help This driver enables support for the on-board Intel 82586 based Ethernet adapter found on Sun 3/1xx and 3/2xx motherboards. Note @@ -422,7 +445,7 @@ config SUN3_82586 config HPLANCE bool "HP on-board LANCE support" - depends on NET_ETHERNET && DIO + depends on DIO select CRC32 help If you want to use the builtin "LANCE" Ethernet controller on an @@ -430,21 +453,28 @@ config HPLANCE config LASI_82596 tristate "Lasi ethernet" - depends on NET_ETHERNET && GSC + depends on GSC help Say Y here to support the builtin Intel 82596 ethernet controller found in Hewlett-Packard PA-RISC machines with 10Mbit ethernet. +config SNI_82596 + tristate "SNI RM ethernet" + depends on NET_ETHERNET && SNI_RM + help + Say Y here to support the on-board Intel 82596 ethernet controller + built into SNI RM machines. + config MIPS_JAZZ_SONIC tristate "MIPS JAZZ onboard SONIC Ethernet support" - depends on NET_ETHERNET && MACH_JAZZ + depends on MACH_JAZZ help This is the driver for the onboard card of MIPS Magnum 4000, Acer PICA, Olivetti M700-10 and a few other identical OEM systems. config MIPS_AU1X00_ENET bool "MIPS AU1000 Ethernet support" - depends on NET_ETHERNET && SOC_AU1X00 + depends on SOC_AU1X00 select PHYLIB select CRC32 help @@ -453,11 +483,11 @@ config MIPS_AU1X00_ENET config NET_SB1250_MAC tristate "SB1250 Ethernet support" - depends on NET_ETHERNET && SIBYTE_SB1xxx_SOC + depends on SIBYTE_SB1xxx_SOC config SGI_IOC3_ETH bool "SGI IOC3 Ethernet" - depends on NET_ETHERNET && PCI && SGI_IP27 + depends on PCI && SGI_IP27 select CRC32 select MII help @@ -487,7 +517,7 @@ config SGI_IOC3_ETH_HW_TX_CSUM config MIPS_SIM_NET tristate "MIPS simulator Network device" - depends on NET_ETHERNET && MIPS_SIM + depends on MIPS_SIM help The MIPSNET device is a simple Ethernet network device which is emulated by the MIPS Simulator. @@ -495,11 +525,11 @@ config MIPS_SIM_NET config SGI_O2MACE_ETH tristate "SGI O2 MACE Fast Ethernet support" - depends on NET_ETHERNET && SGI_IP32=y + depends on SGI_IP32=y config STNIC tristate "National DP83902AV support" - depends on NET_ETHERNET && SUPERH + depends on SUPERH select CRC32 help Support for cards based on the National Semiconductor DP83902AV @@ -511,7 +541,7 @@ config STNIC config SUNLANCE tristate "Sun LANCE support" - depends on NET_ETHERNET && SBUS + depends on SBUS select CRC32 help This driver supports the "le" interface present on all 32-bit Sparc @@ -524,7 +554,7 @@ config SUNLANCE config HAPPYMEAL tristate "Sun Happy Meal 10/100baseT support" - depends on NET_ETHERNET && (SBUS || PCI) + depends on SBUS || PCI select CRC32 help This driver supports the "hme" interface present on most Ultra @@ -537,7 +567,7 @@ config HAPPYMEAL config SUNBMAC tristate "Sun BigMAC 10/100baseT support (EXPERIMENTAL)" - depends on NET_ETHERNET && SBUS && EXPERIMENTAL + depends on SBUS && EXPERIMENTAL select CRC32 help This driver supports the "be" interface available as an Sbus option. @@ -548,7 +578,7 @@ config SUNBMAC config SUNQE tristate "Sun QuadEthernet support" - depends on NET_ETHERNET && SBUS + depends on SBUS select CRC32 help This driver supports the "qe" 10baseT Ethernet device, available as @@ -560,7 +590,7 @@ config SUNQE config SUNGEM tristate "Sun GEM support" - depends on NET_ETHERNET && PCI + depends on PCI select CRC32 help Support for the Sun GEM chip, aka Sun GigabitEthernet/P 2.0. See also @@ -568,7 +598,7 @@ config SUNGEM config CASSINI tristate "Sun Cassini support" - depends on NET_ETHERNET && PCI + depends on PCI select CRC32 help Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also @@ -576,7 +606,7 @@ config CASSINI config NET_VENDOR_3COM bool "3COM cards" - depends on NET_ETHERNET && (ISA || EISA || MCA || PCI) + depends on ISA || EISA || MCA || PCI help If you have a network (Ethernet) card belonging to this class, say Y and read the Ethernet-HOWTO, available from @@ -736,7 +766,7 @@ config TYPHOON config LANCE tristate "AMD LANCE and PCnet (AT1500 and NE2100) support" - depends on NET_ETHERNET && ISA && ISA_DMA_API + depends on ISA && ISA_DMA_API help If you have a network (Ethernet) card of this type, say Y and read the Ethernet-HOWTO, available from @@ -748,7 +778,7 @@ config LANCE config NET_VENDOR_SMC bool "Western Digital/SMC cards" - depends on NET_ETHERNET && (ISA || MCA || EISA || MAC) + depends on ISA || MCA || EISA || MAC help If you have a network (Ethernet) card belonging to this class, say Y and read the Ethernet-HOWTO, available from @@ -818,11 +848,27 @@ config ULTRA32 <file:Documentation/networking/net-modules.txt>. The module will be called smc-ultra32. +config SMC9194 + tristate "SMC 9194 support" + depends on NET_VENDOR_SMC && (ISA || MAC && BROKEN) + select CRC32 + ---help--- + This is support for the SMC9xxx based Ethernet cards. Choose this + option if you have a DELL laptop with the docking station, or + another SMC9192/9194 based chipset. Say Y if you want it compiled + into the kernel, and read the file + <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO, + available from <http://www.tldp.org/docs.html#howto>. + + To compile this driver as a module, choose M here and read + <file:Documentation/networking/net-modules.txt>. The module + will be called smc9194. + config SMC91X tristate "SMC 91C9x/91C1xxx support" select CRC32 select MII - depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BFIN) + depends on ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BFIN help This is a driver for SMC's 91x series of Ethernet chipsets, including the SMC91C94 and the SMC91C111. Say Y if you want it @@ -836,26 +882,10 @@ config SMC91X module, say M here and read <file:Documentation/kbuild/modules.txt> as well as <file:Documentation/networking/net-modules.txt>. -config SMC9194 - tristate "SMC 9194 support" - depends on NET_VENDOR_SMC && (ISA || MAC && BROKEN) - select CRC32 - ---help--- - This is support for the SMC9xxx based Ethernet cards. Choose this - option if you have a DELL laptop with the docking station, or - another SMC9192/9194 based chipset. Say Y if you want it compiled - into the kernel, and read the file - <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO, - available from <http://www.tldp.org/docs.html#howto>. - - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module - will be called smc9194. - config NET_NETX tristate "NetX Ethernet support" select MII - depends on NET_ETHERNET && ARCH_NETX + depends on ARCH_NETX help This is support for the Hilscher netX builtin Ethernet ports @@ -865,7 +895,7 @@ config NET_NETX config DM9000 tristate "DM9000 support" - depends on (ARM || MIPS) && NET_ETHERNET + depends on ARM || BLACKFIN || MIPS select CRC32 select MII ---help--- @@ -879,7 +909,7 @@ config SMC911X tristate "SMSC LAN911[5678] support" select CRC32 select MII - depends on NET_ETHERNET && ARCH_PXA + depends on ARCH_PXA help This is a driver for SMSC's LAN911x series of Ethernet chipsets including the new LAN9115, LAN9116, LAN9117, and LAN9118. @@ -893,7 +923,7 @@ config SMC911X config NET_VENDOR_RACAL bool "Racal-Interlan (Micom) NI cards" - depends on NET_ETHERNET && ISA + depends on ISA help If you have a network (Ethernet) card belonging to this class, such as the NI5010, NI5210 or NI6210, say Y and read the Ethernet-HOWTO, @@ -945,7 +975,7 @@ source "drivers/net/tulip/Kconfig" config AT1700 tristate "AT1700/1720 support (EXPERIMENTAL)" - depends on NET_ETHERNET && (ISA || MCA_LEGACY) && EXPERIMENTAL + depends on (ISA || MCA_LEGACY) && EXPERIMENTAL select CRC32 ---help--- If you have a network (Ethernet) card of this type, say Y and read @@ -958,7 +988,7 @@ config AT1700 config DEPCA tristate "DEPCA, DE10x, DE200, DE201, DE202, DE422 support" - depends on NET_ETHERNET && (ISA || EISA || MCA) + depends on ISA || EISA || MCA select CRC32 ---help--- If you have a network (Ethernet) card of this type, say Y and read @@ -972,7 +1002,7 @@ config DEPCA config HP100 tristate "HP 10/100VG PCLAN (ISA, EISA, PCI) support" - depends on NET_ETHERNET && (ISA || EISA || PCI) + depends on ISA || EISA || PCI help If you have a network (Ethernet) card of this type, say Y and read the Ethernet-HOWTO, available from @@ -984,7 +1014,7 @@ config HP100 config NET_ISA bool "Other ISA cards" - depends on NET_ETHERNET && ISA + depends on ISA ---help--- If your network (Ethernet) card hasn't been mentioned yet and its bus system (that's the way the cards talks to the other components @@ -1147,7 +1177,7 @@ config SEEQ8005 config NE2_MCA tristate "NE/2 (ne2000 MCA version) support" - depends on NET_ETHERNET && MCA_LEGACY + depends on MCA_LEGACY select CRC32 help If you have a network (Ethernet) card of this type, say Y and read @@ -1160,7 +1190,7 @@ config NE2_MCA config IBMLANA tristate "IBM LAN Adapter/A support" - depends on NET_ETHERNET && MCA && MCA_LEGACY + depends on MCA && MCA_LEGACY ---help--- This is a Micro Channel Ethernet adapter. You need to set CONFIG_MCA to use this driver. It is both available as an in-kernel @@ -1176,7 +1206,7 @@ config IBMLANA config IBMVETH tristate "IBM LAN Virtual Ethernet support" - depends on NET_ETHERNET && PPC_PSERIES + depends on PPC_PSERIES ---help--- This driver supports virtual ethernet adapters on newer IBM iSeries and pSeries systems. @@ -1187,7 +1217,7 @@ config IBMVETH config IBM_EMAC tristate "PowerPC 4xx on-chip Ethernet support" - depends on 4xx + depends on 4xx && !PPC_MERGE help This driver supports the PowerPC 4xx EMAC family of on-chip Ethernet controllers. @@ -1257,7 +1287,7 @@ config IBM_EMAC_TAH config NET_PCI bool "EISA, VLB, PCI and on board controllers" - depends on NET_ETHERNET && (ISA || EISA || PCI) + depends on ISA || EISA || PCI help This is another class of network cards which attach directly to the bus. If you have one of those, say Y and read the Ethernet-HOWTO, @@ -1313,6 +1343,7 @@ config AMD8111_ETH To compile this driver as a module, choose M here and read <file:Documentation/networking/net-modules.txt>. The module will be called amd8111e. + config AMD8111E_NAPI bool "Enable NAPI support" depends on AMD8111_ETH @@ -1778,7 +1809,7 @@ config SC92031 config NET_POCKET bool "Pocket and portable adapters" - depends on NET_ETHERNET && PARPORT + depends on PARPORT ---help--- Cute little network (Ethernet) devices which attach to the parallel port ("pocket adapters"), commonly used with laptops. If you have @@ -1847,14 +1878,14 @@ config DE620 config SGISEEQ tristate "SGI Seeq ethernet controller support" - depends on NET_ETHERNET && SGI_IP22 + depends on SGI_IP22 help Say Y here if you have an Seeq based Ethernet network card. This is used in many Silicon Graphics machines. config DECLANCE tristate "DEC LANCE ethernet controller support" - depends on NET_ETHERNET && MACH_DECSTATION + depends on MACH_DECSTATION select CRC32 help This driver is for the series of Ethernet controllers produced by @@ -1884,7 +1915,7 @@ config FEC2 config NE_H8300 tristate "NE2000 compatible support for H8/300" - depends on H8300 && NET_ETHERNET + depends on H8300 help Say Y here if you want to use the NE2000 compatible controller on the Renesas H8/300 processor. @@ -1892,7 +1923,7 @@ config NE_H8300 source "drivers/net/fec_8xx/Kconfig" source "drivers/net/fs_enet/Kconfig" -endmenu +endif # NET_ETHERNET # # Gigabit Ethernet @@ -2101,7 +2132,7 @@ config SKGE with better performance and more complete ethtool support. It does not support the link failover and network management - features that "portable" vendor supplied sk98lin driver does. + features available in the hardware. This driver supports adapters based on the original Yukon chipset: Marvell 88E8001, Belkin F5D5005, CNet GigaCard, DLink DGE-530T, @@ -2114,7 +2145,7 @@ config SKGE will be called skge. This is recommended. config SKY2 - tristate "SysKonnect Yukon2 support (EXPERIMENTAL)" + tristate "SysKonnect Yukon2 support" depends on PCI select CRC32 ---help--- @@ -2129,92 +2160,15 @@ config SKY2 To compile this driver as a module, choose M here: the module will be called sky2. This is recommended. -config SK98LIN - tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support (DEPRECATED)" - depends on PCI - ---help--- - Say Y here if you have a Marvell Yukon or SysKonnect SK-98xx/SK-95xx - compliant Gigabit Ethernet Adapter. +config SKY2_DEBUG + bool "Debugging interface" + depends on SKY2 && DEBUG_FS + help + This option adds the ability to dump driver state for debugging. + The file debugfs/sky2/ethX displays the state of the internal + transmit and receive rings. - This driver supports the original Yukon chipset. This driver is - deprecated and will be removed from the kernel in the near future, - it has been replaced by the skge driver. skge is cleaner and - seems to work better. - - This driver does not support the newer Yukon2 chipset. A separate - driver, sky2, is provided to support Yukon2-based adapters. - - The following adapters are supported by this driver: - - 3Com 3C940 Gigabit LOM Ethernet Adapter - - 3Com 3C941 Gigabit LOM Ethernet Adapter - - Allied Telesyn AT-2970LX Gigabit Ethernet Adapter - - Allied Telesyn AT-2970LX/2SC Gigabit Ethernet Adapter - - Allied Telesyn AT-2970SX Gigabit Ethernet Adapter - - Allied Telesyn AT-2970SX/2SC Gigabit Ethernet Adapter - - Allied Telesyn AT-2970TX Gigabit Ethernet Adapter - - Allied Telesyn AT-2970TX/2TX Gigabit Ethernet Adapter - - Allied Telesyn AT-2971SX Gigabit Ethernet Adapter - - Allied Telesyn AT-2971T Gigabit Ethernet Adapter - - Belkin Gigabit Desktop Card 10/100/1000Base-T Adapter, Copper RJ-45 - - EG1032 v2 Instant Gigabit Network Adapter - - EG1064 v2 Instant Gigabit Network Adapter - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Abit) - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Albatron) - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Asus) - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (ECS) - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Epox) - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Foxconn) - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Gigabyte) - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Iwill) - - Marvell 88E8050 Gigabit LOM Ethernet Adapter (Intel) - - Marvell RDK-8001 Adapter - - Marvell RDK-8002 Adapter - - Marvell RDK-8003 Adapter - - Marvell RDK-8004 Adapter - - Marvell RDK-8006 Adapter - - Marvell RDK-8007 Adapter - - Marvell RDK-8008 Adapter - - Marvell RDK-8009 Adapter - - Marvell RDK-8010 Adapter - - Marvell RDK-8011 Adapter - - Marvell RDK-8012 Adapter - - Marvell RDK-8052 Adapter - - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (32 bit) - - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (64 bit) - - N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L) - - SK-9521 10/100/1000Base-T Adapter - - SK-9521 V2.0 10/100/1000Base-T Adapter - - SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T) - - SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter - - SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link) - - SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX) - - SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter - - SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link) - - SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX) - - SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter - - SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link) - - SK-9851 V2.0 Gigabit Ethernet 1000Base-SX Adapter - - SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition) - - SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter - - SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link) - - SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX) - - SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter - - SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) - - SMC EZ Card 1000 (SMC9452TXV.2) - - The adapters support Jumbo Frames. - The dual link adapters support link-failover and dual port features. - Both Marvell Yukon and SysKonnect SK-98xx/SK-95xx adapters support - the scatter-gather functionality with sendfile(). Please refer to - <file:Documentation/networking/sk98lin.txt> for more information about - optional driver parameters. - Questions concerning this driver may be addressed to: - <linux@syskonnect.de> - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read <file:Documentation/kbuild/modules.txt>. The module will - be called sk98lin. This is recommended. + If unsure, say N. config VIA_VELOCITY tristate "VIA Velocity support" @@ -2264,6 +2218,16 @@ config TSI108_ETH To compile this driver as a module, choose M here: the module will be called tsi108_eth. +config GELIC_NET + tristate "PS3 Gigabit Ethernet driver" + depends on PPC_PS3 + help + This driver supports the network device on the PS3 game + console. This driver has built-in support for Ethernet. + + To compile this driver as a module, choose M here: the + module will be called ps3_gelic. + config GIANFAR tristate "Gianfar Ethernet" depends on 85xx || 83xx || PPC_86xx @@ -2280,6 +2244,7 @@ config GFAR_NAPI config UCC_GETH tristate "Freescale QE Gigabit Ethernet" depends on QUICC_ENGINE + select PHYLIB help This driver supports the Gigabit Ethernet mode of the QUICC Engine, which is available on some Freescale SOCs. @@ -2302,7 +2267,7 @@ config UGETH_TX_ON_DEMAND config MV643XX_ETH tristate "MV-643XX Ethernet support" - depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX || MV64360 || MV64X60 || MOMENCO_OCELOT_3 || (PPC_MULTIPLATFORM && PPC32) + depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32) select MII help This driver supports the gigabit Ethernet on the Marvell MV643XX @@ -2837,6 +2802,19 @@ config PPPOATM which can lead to bad results if the ATM peer loses state and changes its encapsulation unilaterally. +config PPPOL2TP + tristate "PPP over L2TP (EXPERIMENTAL)" + depends on EXPERIMENTAL && PPP + help + Support for PPP-over-L2TP socket family. L2TP is a protocol + used by ISPs and enterprises to tunnel PPP traffic over UDP + tunnels. L2TP is replacing PPTP for VPN uses. + + This kernel component handles only L2TP data packets: a + userland daemon handles L2TP the control protocol (tunnel + and session setup). One such daemon is OpenL2TP + (http://openl2tp.sourceforge.net/). + config SLIP tristate "SLIP (serial line) support" ---help--- @@ -2947,8 +2925,6 @@ config NETCONSOLE If you want to log kernel messages over the network, enable this. See <file:Documentation/networking/netconsole.txt> for details. -endif #NETDEVICES - config NETPOLL def_bool NETCONSOLE @@ -2960,4 +2936,4 @@ config NETPOLL_TRAP config NET_POLL_CONTROLLER def_bool NETPOLL -endmenu +endif # NETDEVICES diff --git a/drivers/net/Makefile b/drivers/net/Makefile index a77affa4f6e..c26b8674213 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -60,10 +60,11 @@ obj-$(CONFIG_TIGON3) += tg3.o obj-$(CONFIG_BNX2) += bnx2.o spidernet-y += spider_net.o spider_net_ethtool.o obj-$(CONFIG_SPIDER_NET) += spidernet.o sungem_phy.o +obj-$(CONFIG_GELIC_NET) += ps3_gelic.o +ps3_gelic-objs += ps3_gelic_net.o obj-$(CONFIG_TC35815) += tc35815.o obj-$(CONFIG_SKGE) += skge.o obj-$(CONFIG_SKY2) += sky2.o -obj-$(CONFIG_SK98LIN) += sk98lin/ obj-$(CONFIG_SKFP) += skfp/ obj-$(CONFIG_VIA_RHINE) += via-rhine.o obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o @@ -107,6 +108,7 @@ obj-$(CONFIG_NET_SB1250_MAC) += sb1250-mac.o obj-$(CONFIG_B44) += b44.o obj-$(CONFIG_FORCEDETH) += forcedeth.o obj-$(CONFIG_NE_H8300) += ne-h8300.o +obj-$(CONFIG_AX88796) += ax88796.o obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o @@ -119,12 +121,14 @@ obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o obj-$(CONFIG_PPPOE) += pppox.o pppoe.o +obj-$(CONFIG_PPPOL2TP) += pppox.o pppol2tp.o obj-$(CONFIG_SLIP) += slip.o obj-$(CONFIG_SLHC) += slhc.o obj-$(CONFIG_DUMMY) += dummy.o obj-$(CONFIG_IFB) += ifb.o +obj-$(CONFIG_MACVLAN) += macvlan.o obj-$(CONFIG_DE600) += de600.o obj-$(CONFIG_DE620) += de620.o obj-$(CONFIG_LANCE) += lance.o @@ -157,6 +161,7 @@ obj-$(CONFIG_ELPLUS) += 3c505.o obj-$(CONFIG_AC3200) += ac3200.o 8390.o obj-$(CONFIG_APRICOT) += 82596.o obj-$(CONFIG_LASI_82596) += lasi_82596.o +obj-$(CONFIG_SNI_82596) += sni_82596.o obj-$(CONFIG_MVME16x_NET) += 82596.o obj-$(CONFIG_BVME6000_NET) += 82596.o obj-$(CONFIG_SC92031) += sc92031.o diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index 81d5a374042..a45de6975bf 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -322,9 +322,9 @@ static int lance_rx (struct net_device *dev) skb_reserve (skb, 2); /* 16 byte align */ skb_put (skb, len); /* make room */ - eth_copy_and_sum(skb, + skb_copy_to_linear_data(skb, (unsigned char *)&(ib->rx_buf [lp->rx_new][0]), - len, 0); + len); skb->protocol = eth_type_trans (skb, dev); netif_rx (skb); dev->last_rx = jiffies; diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index 7122b7ba8d6..b78a4e5ceeb 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -159,10 +159,6 @@ static struct pci_device_id acenic_pci_tbl[] = { }; MODULE_DEVICE_TABLE(pci, acenic_pci_tbl); -#ifndef SET_NETDEV_DEV -#define SET_NETDEV_DEV(net, pdev) do{} while(0) -#endif - #define ace_sync_irq(irq) synchronize_irq(irq) #ifndef offset_in_page @@ -480,12 +476,10 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev, #if ACENIC_DO_VLAN dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; dev->vlan_rx_register = ace_vlan_rx_register; - dev->vlan_rx_kill_vid = ace_vlan_rx_kill_vid; #endif - if (1) { - dev->tx_timeout = &ace_watchdog; - dev->watchdog_timeo = 5*HZ; - } + + dev->tx_timeout = &ace_watchdog; + dev->watchdog_timeo = 5*HZ; dev->open = &ace_open; dev->stop = &ace_close; @@ -2283,19 +2277,6 @@ static void ace_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) ace_unmask_irq(dev); local_irq_restore(flags); } - - -static void ace_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) -{ - struct ace_private *ap = netdev_priv(dev); - unsigned long flags; - - local_irq_save(flags); - ace_mask_irq(dev); - vlan_group_set_device(ap->vlgrp, vid, NULL); - ace_unmask_irq(dev); - local_irq_restore(flags); -} #endif /* ACENIC_DO_VLAN */ diff --git a/drivers/net/acenic.h b/drivers/net/acenic.h index 8ca8534d70b..60ed1837fa8 100644 --- a/drivers/net/acenic.h +++ b/drivers/net/acenic.h @@ -787,7 +787,6 @@ static struct net_device_stats *ace_get_stats(struct net_device *dev); static int read_eeprom_byte(struct net_device *dev, unsigned long offset); #if ACENIC_DO_VLAN static void ace_vlan_rx_register(struct net_device *dev, struct vlan_group *grp); -static void ace_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid); #endif #endif /* _ACENIC_H_ */ diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index 675fe918421..a61b2f89fc3 100644 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -155,7 +155,7 @@ This function will write into PHY registers. */ static int amd8111e_write_phy(struct amd8111e_priv* lp,int phy_id, int reg, u32 val) { - unsigned int repeat = REPEAT_CNT + unsigned int repeat = REPEAT_CNT; void __iomem *mmio = lp->mmio; unsigned int reg_val; @@ -1728,15 +1728,8 @@ static void amd8111e_vlan_rx_register(struct net_device *dev, struct vlan_group lp->vlgrp = grp; spin_unlock_irq(&lp->lock); } - -static void amd8111e_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) -{ - struct amd8111e_priv *lp = netdev_priv(dev); - spin_lock_irq(&lp->lock); - vlan_group_set_device(lp->vlgrp, vid, NULL); - spin_unlock_irq(&lp->lock); -} #endif + static int amd8111e_enable_magicpkt(struct amd8111e_priv* lp) { writel( VAL1|MPPLBA, lp->mmio + CMD3); @@ -1996,7 +1989,6 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev, #if AMD8111E_VLAN_TAG_USED dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX ; dev->vlan_rx_register =amd8111e_vlan_rx_register; - dev->vlan_rx_kill_vid = amd8111e_vlan_rx_kill_vid; #endif lp = netdev_priv(dev); @@ -2049,7 +2041,6 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev, #if AMD8111E_VLAN_TAG_USED dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; dev->vlan_rx_register =amd8111e_vlan_rx_register; - dev->vlan_rx_kill_vid = amd8111e_vlan_rx_kill_vid; #endif /* Probe the external PHY */ amd8111e_probe_ext_phy(dev); diff --git a/drivers/net/amd8111e.h b/drivers/net/amd8111e.h index 2007510c4eb..e65080a5994 100644 --- a/drivers/net/amd8111e.h +++ b/drivers/net/amd8111e.h @@ -615,7 +615,7 @@ typedef enum { #define SSTATE 2 /* Assume contoller gets data 10 times the maximum processing time */ -#define REPEAT_CNT 10; +#define REPEAT_CNT 10 /* amd8111e decriptor flag definitions */ typedef enum { diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c index a241ae7855a..bc5a38a6705 100644 --- a/drivers/net/ariadne.c +++ b/drivers/net/ariadne.c @@ -746,7 +746,7 @@ static int ariadne_rx(struct net_device *dev) skb_reserve(skb,2); /* 16 byte align */ skb_put(skb,pkt_len); /* Make room */ - eth_copy_and_sum(skb, (char *)priv->rx_buff[entry], pkt_len,0); + skb_copy_to_linear_data(skb, (char *)priv->rx_buff[entry], pkt_len); skb->protocol=eth_type_trans(skb,dev); #if 0 printk(KERN_DEBUG "RX pkt type 0x%04x from ", diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig index 678e4f48d36..5bf2d33887a 100644 --- a/drivers/net/arm/Kconfig +++ b/drivers/net/arm/Kconfig @@ -4,7 +4,7 @@ # config ARM_AM79C961A bool "ARM EBSA110 AM79C961A support" - depends on NET_ETHERNET && ARM && ARCH_EBSA110 + depends on ARM && ARCH_EBSA110 select CRC32 help If you wish to compile a kernel for the EBSA-110, then you should @@ -12,21 +12,21 @@ config ARM_AM79C961A config ARM_ETHER1 tristate "Acorn Ether1 support" - depends on NET_ETHERNET && ARM && ARCH_ACORN + depends on ARM && ARCH_ACORN help If you have an Acorn system with one of these (AKA25) network cards, you should say Y to this option if you wish to use it with Linux. config ARM_ETHER3 tristate "Acorn/ANT Ether3 support" - depends on NET_ETHERNET && ARM && ARCH_ACORN + depends on ARM && ARCH_ACORN help If you have an Acorn system with one of these network cards, you should say Y to this option if you wish to use it with Linux. config ARM_ETHERH tristate "I-cubed EtherH/ANT EtherM support" - depends on NET_ETHERNET && ARM && ARCH_ACORN + depends on ARM && ARCH_ACORN select CRC32 help If you have an Acorn system with one of these network cards, you @@ -34,7 +34,7 @@ config ARM_ETHERH config ARM_AT91_ETHER tristate "AT91RM9200 Ethernet support" - depends on NET_ETHERNET && ARM && ARCH_AT91RM9200 + depends on ARM && ARCH_AT91RM9200 select MII help If you wish to compile a kernel for the AT91RM9200 and enable @@ -42,7 +42,7 @@ config ARM_AT91_ETHER config EP93XX_ETH tristate "EP93xx Ethernet support" - depends on NET_ETHERNET && ARM && ARCH_EP93XX + depends on ARM && ARCH_EP93XX help This is a driver for the ethernet hardware included in EP93xx CPUs. Say Y if you are building a kernel for EP93xx based devices. diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index 8f0d7ce503c..2143eeb7a2b 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -634,7 +634,7 @@ static void am79c961_poll_controller(struct net_device *dev) { unsigned long flags; local_irq_save(flags); - am79c961_interrupt(dev->irq, dev, NULL); + am79c961_interrupt(dev->irq, dev); local_irq_restore(flags); } #endif diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index 2438c5bff23..f6ece1d43f6 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -258,7 +258,7 @@ static int ep93xx_rx(struct net_device *dev, int *budget) skb_reserve(skb, 2); dma_sync_single(NULL, ep->descs->rdesc[entry].buf_addr, length, DMA_FROM_DEVICE); - eth_copy_and_sum(skb, ep->rx_buf[entry], length, 0); + skb_copy_to_linear_data(skb, ep->rx_buf[entry], length); skb_put(skb, length); skb->protocol = eth_type_trans(skb, dev); diff --git a/drivers/net/atari_pamsnet.c b/drivers/net/atari_pamsnet.c index 54714409a09..f7356374a2e 100644 --- a/drivers/net/atari_pamsnet.c +++ b/drivers/net/atari_pamsnet.c @@ -295,10 +295,7 @@ int if_up = 0; /* Setup the DMA counter */ static void -setup_dma (address, rw_flag, num_blocks) - void *address; - unsigned rw_flag; - int num_blocks; +setup_dma (void *address, unsigned rw_flag, int num_blocks) { WRITEMODE((unsigned) rw_flag | DMA_FDC | SEC_COUNT | REG_ACSI | A1); @@ -317,9 +314,7 @@ setup_dma (address, rw_flag, num_blocks) /* Send the first byte of an command block */ static int -send_first (target, byte) - int target; - unsigned char byte; +send_first (int target, unsigned char byte) { rw = READ; acsi_delay_end(COMMAND_DELAY); @@ -338,10 +333,7 @@ send_first (target, byte) /* Send the rest of an command block */ static int -send_1_5 (lun, command, dma) - int lun; - unsigned char *command; - int dma; +send_1_5 (int lun, unsigned char *command, int dma) { int i, j; @@ -371,8 +363,7 @@ get_status (void) /* Calculate the number of received bytes */ static int -calc_received (start_address) - void *start_address; +calc_received (void *start_address) { return (int)( (((unsigned long)DMAHIGH << 16) | ((unsigned)DMAMID << 8) | DMALOW) @@ -384,8 +375,7 @@ calc_received (start_address) /* start() starts the PAM's DMA adaptor */ static void -start (target) - int target; +start (int target) { send_first(target, START); } @@ -393,8 +383,7 @@ start (target) /* stop() stops the PAM's DMA adaptor and returns a value of zero in case of success */ static int -stop (target) - int target; +stop (int target) { int ret = -1; unsigned char cmd_buffer[5]; @@ -415,8 +404,7 @@ bad: /* testpkt() returns the number of received packets waiting in the queue */ static int -testpkt(target) - int target; +testpkt(int target) { int ret = -1; @@ -431,9 +419,7 @@ bad: /* Please note: The buffer is for internal use only but must be defined! */ static int -inquiry (target, buffer) - int target; - unsigned char *buffer; +inquiry (int target, unsigned char *buffer) { int ret = -1; unsigned char *vbuffer = phys_to_virt((unsigned long)buffer); @@ -468,9 +454,7 @@ bad: */ static HADDR -*read_hw_addr(target, buffer) - int target; - unsigned char *buffer; +*read_hw_addr(int target, unsigned char *buffer) { HADDR *ret = 0; unsigned char cmd_buffer[5]; @@ -491,9 +475,7 @@ bad: } static irqreturn_t -pamsnet_intr(irq, data, fp) - int irq; - void *data; +pamsnet_intr(int irq, void *data) { return IRQ_HANDLED; } @@ -501,9 +483,7 @@ pamsnet_intr(irq, data, fp) /* receivepkt() loads a packet to a given buffer and returns its length */ static int -receivepkt (target, buffer) - int target; - unsigned char *buffer; +receivepkt (int target, unsigned char *buffer) { int ret = -1; unsigned char cmd_buffer[5]; @@ -526,10 +506,7 @@ bad: successfully */ static int -sendpkt (target, buffer, length) - int target; - unsigned char *buffer; - int length; +sendpkt (int target, unsigned char *buffer, int length) { int ret = -1; unsigned char cmd_buffer[5]; @@ -665,7 +642,8 @@ struct net_device * __init pamsnet_probe (int unit) there is non-reboot way to recover if something goes wrong. */ static int -pamsnet_open(struct net_device *dev) { +pamsnet_open(struct net_device *dev) +{ struct net_local *lp = netdev_priv(dev); if (pamsnet_debug > 0) @@ -694,7 +672,8 @@ pamsnet_open(struct net_device *dev) { } static int -pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev) { +pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev) +{ struct net_local *lp = netdev_priv(dev); unsigned long flags; @@ -741,7 +720,8 @@ pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev) { /* We have a good packet(s), get it/them out of the buffers. */ static void -pamsnet_poll_rx(struct net_device *dev) { +pamsnet_poll_rx(struct net_device *dev) +{ struct net_local *lp = netdev_priv(dev); int boguscount; int pkt_len; @@ -816,7 +796,8 @@ pamsnet_poll_rx(struct net_device *dev) { * passes them to the higher layers and restarts the timer. */ static void -pamsnet_tick(unsigned long data) { +pamsnet_tick(unsigned long data) +{ struct net_device *dev = (struct net_device *)data; struct net_local *lp = netdev_priv(dev); @@ -832,7 +813,8 @@ pamsnet_tick(unsigned long data) { /* The inverse routine to pamsnet_open(). */ static int -pamsnet_close(struct net_device *dev) { +pamsnet_close(struct net_device *dev) +{ struct net_local *lp = netdev_priv(dev); if (pamsnet_debug > 0) diff --git a/drivers/net/atl1/atl1.h b/drivers/net/atl1/atl1.h index b1c6034e68f..df4c1a0071a 100644 --- a/drivers/net/atl1/atl1.h +++ b/drivers/net/atl1/atl1.h @@ -210,7 +210,6 @@ struct atl1_hw { u16 phy_spd_default; u16 dev_rev; - u8 revision_id; /* spi flash */ u8 flash_vendor; diff --git a/drivers/net/atl1/atl1_main.c b/drivers/net/atl1/atl1_main.c index 78cf00ff3d3..501919eb7f5 100644 --- a/drivers/net/atl1/atl1_main.c +++ b/drivers/net/atl1/atl1_main.c @@ -118,10 +118,6 @@ static int __devinit atl1_sw_init(struct atl1_adapter *adapter) { struct atl1_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - - /* PCI config space info */ - pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); hw->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE; @@ -634,14 +630,13 @@ static void atl1_intr_tx(struct atl1_adapter *adapter) struct atl1_buffer *buffer_info; u16 sw_tpd_next_to_clean; u16 cmb_tpd_next_to_clean; - u8 update = 0; sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean); cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx); while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) { struct tx_packet_desc *tpd; - update = 1; + tpd = ATL1_TPD_DESC(tpd_ring, sw_tpd_next_to_clean); buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean]; if (buffer_info->dma) { @@ -1229,39 +1224,9 @@ static void atl1_vlan_rx_register(struct net_device *netdev, spin_unlock_irqrestore(&adapter->lock, flags); } -/* FIXME: justify or remove -- CHS */ -static void atl1_vlan_rx_add_vid(struct net_device *netdev, u16 vid) -{ - /* We don't do Vlan filtering */ - return; -} - -/* FIXME: this looks wrong too -- CHS */ -static void atl1_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) -{ - struct atl1_adapter *adapter = netdev_priv(netdev); - unsigned long flags; - - spin_lock_irqsave(&adapter->lock, flags); - /* atl1_irq_disable(adapter); */ - vlan_group_set_device(adapter->vlgrp, vid, NULL); - /* atl1_irq_enable(adapter); */ - spin_unlock_irqrestore(&adapter->lock, flags); - /* We don't do Vlan filtering */ - return; -} - static void atl1_restore_vlan(struct atl1_adapter *adapter) { atl1_vlan_rx_register(adapter->netdev, adapter->vlgrp); - if (adapter->vlgrp) { - u16 vid; - for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { - if (!vlan_group_get_device(adapter->vlgrp, vid)) - continue; - atl1_vlan_rx_add_vid(adapter->netdev, vid); - } - } } static u16 tpd_avail(struct atl1_tpd_ring *tpd_ring) @@ -2203,8 +2168,7 @@ static int __devinit atl1_probe(struct pci_dev *pdev, netdev->poll_controller = atl1_poll_controller; #endif netdev->vlan_rx_register = atl1_vlan_rx_register; - netdev->vlan_rx_add_vid = atl1_vlan_rx_add_vid; - netdev->vlan_rx_kill_vid = atl1_vlan_rx_kill_vid; + netdev->ethtool_ops = &atl1_ethtool_ops; adapter->bd_number = cards_found; adapter->pci_using_64 = pci_using_64; diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index c39ab803c5d..e86b3691765 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -34,7 +34,7 @@ * * */ - +#include <linux/dma-mapping.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/string.h> @@ -1205,8 +1205,8 @@ static int au1000_rx(struct net_device *dev) continue; } skb_reserve(skb, 2); /* 16 byte IP header align */ - eth_copy_and_sum(skb, - (unsigned char *)pDB->vaddr, frmlen, 0); + skb_copy_to_linear_data(skb, + (unsigned char *)pDB->vaddr, frmlen); skb_put(skb, frmlen); skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); /* pass the packet to upper layers */ diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c new file mode 100644 index 00000000000..1d882360b34 --- /dev/null +++ b/drivers/net/ax88796.c @@ -0,0 +1,952 @@ +/* drivers/net/ax88796.c + * + * Copyright 2005,2007 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * Asix AX88796 10/100 Ethernet controller support + * Based on ne.c, by Donald Becker, et-al. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/isapnp.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/timer.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/ethtool.h> +#include <linux/mii.h> + +#include <net/ax88796.h> + +#include <asm/system.h> +#include <asm/io.h> + +static int phy_debug = 0; + +/* Rename the lib8390.c functions to show that they are in this driver */ +#define __ei_open ax_ei_open +#define __ei_close ax_ei_close +#define __ei_poll ax_ei_poll +#define __ei_tx_timeout ax_ei_tx_timeout +#define __ei_interrupt ax_ei_interrupt +#define ____alloc_ei_netdev ax__alloc_ei_netdev +#define __NS8390_init ax_NS8390_init + +/* force unsigned long back to 'void __iomem *' */ +#define ax_convert_addr(_a) ((void __force __iomem *)(_a)) + +#define ei_inb(_a) readb(ax_convert_addr(_a)) +#define ei_outb(_v, _a) writeb(_v, ax_convert_addr(_a)) + +#define ei_inb_p(_a) ei_inb(_a) +#define ei_outb_p(_v, _a) ei_outb(_v, _a) + +/* define EI_SHIFT() to take into account our register offsets */ +#define EI_SHIFT(x) (ei_local->reg_offset[(x)]) + +/* Ensure we have our RCR base value */ +#define AX88796_PLATFORM + +static unsigned char version[] = "ax88796.c: Copyright 2005,2007 Simtec Electronics\n"; + +#include "lib8390.c" + +#define DRV_NAME "ax88796" +#define DRV_VERSION "1.00" + +/* from ne.c */ +#define NE_CMD EI_SHIFT(0x00) +#define NE_RESET EI_SHIFT(0x1f) +#define NE_DATAPORT EI_SHIFT(0x10) + +#define NE1SM_START_PG 0x20 /* First page of TX buffer */ +#define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */ +#define NESM_START_PG 0x40 /* First page of TX buffer */ +#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ + +/* device private data */ + +struct ax_device { + struct timer_list mii_timer; + spinlock_t mii_lock; + struct mii_if_info mii; + + u32 msg_enable; + void __iomem *map2; + struct platform_device *dev; + struct resource *mem; + struct resource *mem2; + struct ax_plat_data *plat; + + unsigned char running; + unsigned char resume_open; + + u32 reg_offsets[0x20]; +}; + +static inline struct ax_device *to_ax_dev(struct net_device *dev) +{ + struct ei_device *ei_local = netdev_priv(dev); + return (struct ax_device *)(ei_local+1); +} + +/* ax_initial_check + * + * do an initial probe for the card to check wether it exists + * and is functional + */ + +static int ax_initial_check(struct net_device *dev) +{ + struct ei_device *ei_local = netdev_priv(dev); + void __iomem *ioaddr = ei_local->mem; + int reg0; + int regd; + + reg0 = ei_inb(ioaddr); + if (reg0 == 0xFF) + return -ENODEV; + + ei_outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD); + regd = ei_inb(ioaddr + 0x0d); + ei_outb(0xff, ioaddr + 0x0d); + ei_outb(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD); + ei_inb(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */ + if (ei_inb(ioaddr + EN0_COUNTER0) != 0) { + ei_outb(reg0, ioaddr); + ei_outb(regd, ioaddr + 0x0d); /* Restore the old values. */ + return -ENODEV; + } + + return 0; +} + +/* Hard reset the card. This used to pause for the same period that a + 8390 reset command required, but that shouldn't be necessary. */ + +static void ax_reset_8390(struct net_device *dev) +{ + struct ei_device *ei_local = netdev_priv(dev); + unsigned long reset_start_time = jiffies; + void __iomem *addr = (void __iomem *)dev->base_addr; + + if (ei_debug > 1) + printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies); + + ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET); + + ei_status.txing = 0; + ei_status.dmaing = 0; + + /* This check _should_not_ be necessary, omit eventually. */ + while ((ei_inb(addr + EN0_ISR) & ENISR_RESET) == 0) { + if (jiffies - reset_start_time > 2*HZ/100) { + printk(KERN_WARNING "%s: %s did not complete.\n", + __FUNCTION__, dev->name); + break; + } + } + + ei_outb(ENISR_RESET, addr + EN0_ISR); /* Ack intr. */ +} + + +static void ax_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, + int ring_page) +{ + struct ei_device *ei_local = netdev_priv(dev); + void __iomem *nic_base = ei_local->mem; + + /* This *shouldn't* happen. If it does, it's the last thing you'll see */ + if (ei_status.dmaing) { + printk(KERN_EMERG "%s: DMAing conflict in %s [DMAstat:%d][irqlock:%d].\n", + dev->name, __FUNCTION__, + ei_status.dmaing, ei_status.irqlock); + return; + } + + ei_status.dmaing |= 0x01; + ei_outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD); + ei_outb(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO); + ei_outb(0, nic_base + EN0_RCNTHI); + ei_outb(0, nic_base + EN0_RSARLO); /* On page boundary */ + ei_outb(ring_page, nic_base + EN0_RSARHI); + ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD); + + if (ei_status.word16) + readsw(nic_base + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1); + else + readsb(nic_base + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)); + + ei_outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ + ei_status.dmaing &= ~0x01; + + le16_to_cpus(&hdr->count); +} + + +/* Block input and output, similar to the Crynwr packet driver. If you + are porting to a new ethercard, look at the packet driver source for hints. + The NEx000 doesn't share the on-board packet memory -- you have to put + the packet out through the "remote DMA" dataport using ei_outb. */ + +static void ax_block_input(struct net_device *dev, int count, + struct sk_buff *skb, int ring_offset) +{ + struct ei_device *ei_local = netdev_priv(dev); + void __iomem *nic_base = ei_local->mem; + char *buf = skb->data; + + if (ei_status.dmaing) { + printk(KERN_EMERG "%s: DMAing conflict in ax_block_input " + "[DMAstat:%d][irqlock:%d].\n", + dev->name, ei_status.dmaing, ei_status.irqlock); + return; + } + + ei_status.dmaing |= 0x01; + + ei_outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD); + ei_outb(count & 0xff, nic_base + EN0_RCNTLO); + ei_outb(count >> 8, nic_base + EN0_RCNTHI); + ei_outb(ring_offset & 0xff, nic_base + EN0_RSARLO); + ei_outb(ring_offset >> 8, nic_base + EN0_RSARHI); + ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD); + + if (ei_status.word16) { + readsw(nic_base + NE_DATAPORT, buf, count >> 1); + if (count & 0x01) + buf[count-1] = ei_inb(nic_base + NE_DATAPORT); + + } else { + readsb(nic_base + NE_DATAPORT, buf, count); + } + + ei_status.dmaing &= ~1; +} + +static void ax_block_output(struct net_device *dev, int count, + const unsigned char *buf, const int start_page) +{ + struct ei_device *ei_local = netdev_priv(dev); + void __iomem *nic_base = ei_local->mem; + unsigned long dma_start; + + /* Round the count up for word writes. Do we need to do this? + What effect will an odd byte count have on the 8390? + I should check someday. */ + + if (ei_status.word16 && (count & 0x01)) + count++; + + /* This *shouldn't* happen. If it does, it's the last thing you'll see */ + if (ei_status.dmaing) { + printk(KERN_EMERG "%s: DMAing conflict in %s." + "[DMAstat:%d][irqlock:%d]\n", + dev->name, __FUNCTION__, + ei_status.dmaing, ei_status.irqlock); + return; + } + + ei_status.dmaing |= 0x01; + /* We should already be in page 0, but to be safe... */ + ei_outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD); + + ei_outb(ENISR_RDC, nic_base + EN0_ISR); + + /* Now the normal output. */ + ei_outb(count & 0xff, nic_base + EN0_RCNTLO); + ei_outb(count >> 8, nic_base + EN0_RCNTHI); + ei_outb(0x00, nic_base + EN0_RSARLO); + ei_outb(start_page, nic_base + EN0_RSARHI); + + ei_outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD); + if (ei_status.word16) { + writesw(nic_base + NE_DATAPORT, buf, count>>1); + } else { + writesb(nic_base + NE_DATAPORT, buf, count); + } + + dma_start = jiffies; + + while ((ei_inb(nic_base + EN0_ISR) & ENISR_RDC) == 0) { + if (jiffies - dma_start > 2*HZ/100) { /* 20ms */ + printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name); + ax_reset_8390(dev); + ax_NS8390_init(dev,1); + break; + } + } + + ei_outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ + ei_status.dmaing &= ~0x01; + return; +} + +/* definitions for accessing MII/EEPROM interface */ + +#define AX_MEMR EI_SHIFT(0x14) +#define AX_MEMR_MDC (1<<0) +#define AX_MEMR_MDIR (1<<1) +#define AX_MEMR_MDI (1<<2) +#define AX_MEMR_MDO (1<<3) +#define AX_MEMR_EECS (1<<4) +#define AX_MEMR_EEI (1<<5) +#define AX_MEMR_EEO (1<<6) +#define AX_MEMR_EECLK (1<<7) + +/* ax_mii_ei_outbits + * + * write the specified set of bits to the phy +*/ + +static void +ax_mii_ei_outbits(struct net_device *dev, unsigned int bits, int len) +{ + struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR; + unsigned int memr; + + /* clock low, data to output mode */ + memr = ei_inb(memr_addr); + memr &= ~(AX_MEMR_MDC | AX_MEMR_MDIR); + ei_outb(memr, memr_addr); + + for (len--; len >= 0; len--) { + if (bits & (1 << len)) + memr |= AX_MEMR_MDO; + else + memr &= ~AX_MEMR_MDO; + + ei_outb(memr, memr_addr); + + /* clock high */ + + ei_outb(memr | AX_MEMR_MDC, memr_addr); + udelay(1); + + /* clock low */ + ei_outb(memr, memr_addr); + } + + /* leaves the clock line low, mdir input */ + memr |= AX_MEMR_MDIR; + ei_outb(memr, (void __iomem *)dev->base_addr + AX_MEMR); +} + +/* ax_phy_ei_inbits + * + * read a specified number of bits from the phy +*/ + +static unsigned int +ax_phy_ei_inbits(struct net_device *dev, int no) +{ + struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR; + unsigned int memr; + unsigned int result = 0; + + /* clock low, data to input mode */ + memr = ei_inb(memr_addr); + memr &= ~AX_MEMR_MDC; + memr |= AX_MEMR_MDIR; + ei_outb(memr, memr_addr); + + for (no--; no >= 0; no--) { + ei_outb(memr | AX_MEMR_MDC, memr_addr); + + udelay(1); + + if (ei_inb(memr_addr) & AX_MEMR_MDI) + result |= (1<<no); + + ei_outb(memr, memr_addr); + } + + return result; +} + +/* ax_phy_issueaddr + * + * use the low level bit shifting routines to send the address + * and command to the specified phy +*/ + +static void +ax_phy_issueaddr(struct net_device *dev, int phy_addr, int reg, int opc) +{ + if (phy_debug) + pr_debug("%s: dev %p, %04x, %04x, %d\n", + __FUNCTION__, dev, phy_addr, reg, opc); + + ax_mii_ei_outbits(dev, 0x3f, 6); /* pre-amble */ + ax_mii_ei_outbits(dev, 1, 2); /* frame-start */ + ax_mii_ei_outbits(dev, opc, 2); /* op code */ + ax_mii_ei_outbits(dev, phy_addr, 5); /* phy address */ + ax_mii_ei_outbits(dev, reg, 5); /* reg address */ +} + +static int +ax_phy_read(struct net_device *dev, int phy_addr, int reg) +{ + struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + unsigned long flags; + unsigned int result; + + spin_lock_irqsave(&ei_local->page_lock, flags); + + ax_phy_issueaddr(dev, phy_addr, reg, 2); + + result = ax_phy_ei_inbits(dev, 17); + result &= ~(3<<16); + + spin_unlock_irqrestore(&ei_local->page_lock, flags); + + if (phy_debug) + pr_debug("%s: %04x.%04x => read %04x\n", __FUNCTION__, + phy_addr, reg, result); + + return result; +} + +static void +ax_phy_write(struct net_device *dev, int phy_addr, int reg, int value) +{ + struct ei_device *ei = (struct ei_device *) netdev_priv(dev); + unsigned long flags; + + printk(KERN_DEBUG "%s: %p, %04x, %04x %04x\n", + __FUNCTION__, dev, phy_addr, reg, value); + + spin_lock_irqsave(&ei->page_lock, flags); + + ax_phy_issueaddr(dev, phy_addr, reg, 1); + ax_mii_ei_outbits(dev, 2, 2); /* send TA */ + ax_mii_ei_outbits(dev, value, 16); + + spin_unlock_irqrestore(&ei->page_lock, flags); +} + +static void ax_mii_expiry(unsigned long data) +{ + struct net_device *dev = (struct net_device *)data; + struct ax_device *ax = to_ax_dev(dev); + unsigned long flags; + + spin_lock_irqsave(&ax->mii_lock, flags); + mii_check_media(&ax->mii, netif_msg_link(ax), 0); + spin_unlock_irqrestore(&ax->mii_lock, flags); + + if (ax->running) { + ax->mii_timer.expires = jiffies + HZ*2; + add_timer(&ax->mii_timer); + } +} + +static int ax_open(struct net_device *dev) +{ + struct ax_device *ax = to_ax_dev(dev); + struct ei_device *ei_local = netdev_priv(dev); + int ret; + + dev_dbg(&ax->dev->dev, "%s: open\n", dev->name); + + ret = request_irq(dev->irq, ax_ei_interrupt, 0, dev->name, dev); + if (ret) + return ret; + + ret = ax_ei_open(dev); + if (ret) + return ret; + + /* turn the phy on (if turned off) */ + + ei_outb(ax->plat->gpoc_val, ei_local->mem + EI_SHIFT(0x17)); + ax->running = 1; + + /* start the MII timer */ + + init_timer(&ax->mii_timer); + + ax->mii_timer.expires = jiffies+1; + ax->mii_timer.data = (unsigned long) dev; + ax->mii_timer.function = ax_mii_expiry; + + add_timer(&ax->mii_timer); + + return 0; +} + +static int ax_close(struct net_device *dev) +{ + struct ax_device *ax = to_ax_dev(dev); + struct ei_device *ei_local = netdev_priv(dev); + + dev_dbg(&ax->dev->dev, "%s: close\n", dev->name); + + /* turn the phy off */ + + ei_outb(ax->plat->gpoc_val | (1<<6), + ei_local->mem + EI_SHIFT(0x17)); + + ax->running = 0; + wmb(); + + del_timer_sync(&ax->mii_timer); + ax_ei_close(dev); + + free_irq(dev->irq, dev); + return 0; +} + +static int ax_ioctl(struct net_device *dev, struct ifreq *req, int cmd) +{ + struct ax_device *ax = to_ax_dev(dev); + unsigned long flags; + int rc; + + if (!netif_running(dev)) + return -EINVAL; + + spin_lock_irqsave(&ax->mii_lock, flags); + rc = generic_mii_ioctl(&ax->mii, if_mii(req), cmd, NULL); + spin_unlock_irqrestore(&ax->mii_lock, flags); + + return rc; +} + +/* ethtool ops */ + +static void ax_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + struct ax_device *ax = to_ax_dev(dev); + + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, ax->dev->name); +} + +static int ax_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct ax_device *ax = to_ax_dev(dev); + unsigned long flags; + + spin_lock_irqsave(&ax->mii_lock, flags); + mii_ethtool_gset(&ax->mii, cmd); + spin_lock_irqsave(&ax->mii_lock, flags); + + return 0; +} + +static int ax_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct ax_device *ax = to_ax_dev(dev); + unsigned long flags; + int rc; + + spin_lock_irqsave(&ax->mii_lock, flags); + rc = mii_ethtool_sset(&ax->mii, cmd); + spin_lock_irqsave(&ax->mii_lock, flags); + + return rc; +} + +static int ax_nway_reset(struct net_device *dev) +{ + struct ax_device *ax = to_ax_dev(dev); + return mii_nway_restart(&ax->mii); +} + +static u32 ax_get_link(struct net_device *dev) +{ + struct ax_device *ax = to_ax_dev(dev); + return mii_link_ok(&ax->mii); +} + +static const struct ethtool_ops ax_ethtool_ops = { + .get_drvinfo = ax_get_drvinfo, + .get_settings = ax_get_settings, + .set_settings = ax_set_settings, + .nway_reset = ax_nway_reset, + .get_link = ax_get_link, + .get_perm_addr = ethtool_op_get_perm_addr, +}; + +/* setup code */ + +static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local) +{ + void __iomem *ioaddr = ei_local->mem; + struct ax_device *ax = to_ax_dev(dev); + + /* Select page 0*/ + ei_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, ioaddr + E8390_CMD); + + /* set to byte access */ + ei_outb(ax->plat->dcr_val & ~1, ioaddr + EN0_DCFG); + ei_outb(ax->plat->gpoc_val, ioaddr + EI_SHIFT(0x17)); +} + +/* ax_init_dev + * + * initialise the specified device, taking care to note the MAC + * address it may already have (if configured), ensure + * the device is ready to be used by lib8390.c and registerd with + * the network layer. + */ + +static int ax_init_dev(struct net_device *dev, int first_init) +{ + struct ei_device *ei_local = netdev_priv(dev); + struct ax_device *ax = to_ax_dev(dev); + void __iomem *ioaddr = ei_local->mem; + unsigned int start_page; + unsigned int stop_page; + int ret; + int i; + + ret = ax_initial_check(dev); + if (ret) + goto err_out; + + /* setup goes here */ + + ax_initial_setup(dev, ei_local); + + /* read the mac from the card prom if we need it */ + + if (first_init && ax->plat->flags & AXFLG_HAS_EEPROM) { + unsigned char SA_prom[32]; + + for(i = 0; i < sizeof(SA_prom); i+=2) { + SA_prom[i] = ei_inb(ioaddr + NE_DATAPORT); + SA_prom[i+1] = ei_inb(ioaddr + NE_DATAPORT); + } + + if (ax->plat->wordlength == 2) + for (i = 0; i < 16; i++) + SA_prom[i] = SA_prom[i+i]; + + memcpy(dev->dev_addr, SA_prom, 6); + } + + if (ax->plat->wordlength == 2) { + /* We must set the 8390 for word mode. */ + ei_outb(ax->plat->dcr_val, ei_local->mem + EN0_DCFG); + start_page = NESM_START_PG; + stop_page = NESM_STOP_PG; + } else { + start_page = NE1SM_START_PG; + stop_page = NE1SM_STOP_PG; + } + + /* load the mac-address from the device if this is the + * first time we've initialised */ + + if (first_init && ax->plat->flags & AXFLG_MAC_FROMDEV) { + ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP, + ei_local->mem + E8390_CMD); /* 0x61 */ + + for (i = 0 ; i < ETHER_ADDR_LEN ; i++) + dev->dev_addr[i] = ei_inb(ioaddr + EN1_PHYS_SHIFT(i)); + } + + ax_reset_8390(dev); + + ei_status.name = "AX88796"; + ei_status.tx_start_page = start_page; + ei_status.stop_page = stop_page; + ei_status.word16 = (ax->plat->wordlength == 2); + ei_status.rx_start_page = start_page + TX_PAGES; + +#ifdef PACKETBUF_MEMSIZE + /* Allow the packet buffer size to be overridden by know-it-alls. */ + ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE; +#endif + + ei_status.reset_8390 = &ax_reset_8390; + ei_status.block_input = &ax_block_input; + ei_status.block_output = &ax_block_output; + ei_status.get_8390_hdr = &ax_get_8390_hdr; + ei_status.priv = 0; + + dev->open = ax_open; + dev->stop = ax_close; + dev->do_ioctl = ax_ioctl; + dev->ethtool_ops = &ax_ethtool_ops; + + ax->msg_enable = NETIF_MSG_LINK; + ax->mii.phy_id_mask = 0x1f; + ax->mii.reg_num_mask = 0x1f; + ax->mii.phy_id = 0x10; /* onboard phy */ + ax->mii.force_media = 0; + ax->mii.full_duplex = 0; + ax->mii.mdio_read = ax_phy_read; + ax->mii.mdio_write = ax_phy_write; + ax->mii.dev = dev; + +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = ax_ei_poll; +#endif + ax_NS8390_init(dev, 0); + + if (first_init) { + printk("AX88796: %dbit, irq %d, %lx, MAC: ", + ei_status.word16 ? 16:8, dev->irq, dev->base_addr); + + for (i = 0; i < ETHER_ADDR_LEN; i++) + printk("%2.2x%c", dev->dev_addr[i], + (i < (ETHER_ADDR_LEN-1) ? ':' : ' ')); + + printk("\n"); + } + + ret = register_netdev(dev); + if (ret) + goto out_irq; + + return 0; + + out_irq: + /* cleanup irq */ + free_irq(dev->irq, dev); + err_out: + return ret; +} + +static int ax_remove(struct platform_device *_dev) +{ + struct net_device *dev = platform_get_drvdata(_dev); + struct ax_device *ax; + + ax = to_ax_dev(dev); + + unregister_netdev(dev); + free_irq(dev->irq, dev); + + iounmap(ei_status.mem); + release_resource(ax->mem); + kfree(ax->mem); + + if (ax->map2) { + iounmap(ax->map2); + release_resource(ax->mem2); + kfree(ax->mem2); + } + + free_netdev(dev); + + return 0; +} + +/* ax_probe + * + * This is the entry point when the platform device system uses to + * notify us of a new device to attach to. Allocate memory, find + * the resources and information passed, and map the necessary registers. +*/ + +static int ax_probe(struct platform_device *pdev) +{ + struct net_device *dev; + struct ax_device *ax; + struct resource *res; + size_t size; + int ret; + + dev = ax__alloc_ei_netdev(sizeof(struct ax_device)); + if (dev == NULL) + return -ENOMEM; + + /* ok, let's setup our device */ + ax = to_ax_dev(dev); + + memset(ax, 0, sizeof(struct ax_device)); + + spin_lock_init(&ax->mii_lock); + + ax->dev = pdev; + ax->plat = pdev->dev.platform_data; + platform_set_drvdata(pdev, dev); + + ei_status.rxcr_base = ax->plat->rcr_val; + + /* find the platform resources */ + + dev->irq = platform_get_irq(pdev, 0); + if (dev->irq < 0) { + dev_err(&pdev->dev, "no IRQ specified\n"); + ret = -ENXIO; + goto exit_mem; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, "no MEM specified\n"); + ret = -ENXIO; + goto exit_mem; + } + + size = (res->end - res->start) + 1; + + /* setup the register offsets from either the platform data + * or by using the size of the resource provided */ + + if (ax->plat->reg_offsets) + ei_status.reg_offset = ax->plat->reg_offsets; + else { + ei_status.reg_offset = ax->reg_offsets; + for (ret = 0; ret < 0x18; ret++) + ax->reg_offsets[ret] = (size / 0x18) * ret; + } + + ax->mem = request_mem_region(res->start, size, pdev->name); + if (ax->mem == NULL) { + dev_err(&pdev->dev, "cannot reserve registers\n"); + ret = -ENXIO; + goto exit_mem; + } + + ei_status.mem = ioremap(res->start, size); + dev->base_addr = (long)ei_status.mem; + + if (ei_status.mem == NULL) { + dev_err(&pdev->dev, "Cannot ioremap area (%08zx,%08zx)\n", + res->start, res->end); + + ret = -ENXIO; + goto exit_req; + } + + /* look for reset area */ + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (res == NULL) { + if (!ax->plat->reg_offsets) { + for (ret = 0; ret < 0x20; ret++) + ax->reg_offsets[ret] = (size / 0x20) * ret; + } + + ax->map2 = NULL; + } else { + size = (res->end - res->start) + 1; + + ax->mem2 = request_mem_region(res->start, size, pdev->name); + if (ax->mem == NULL) { + dev_err(&pdev->dev, "cannot reserve registers\n"); + ret = -ENXIO; + goto exit_mem1; + } + + ax->map2 = ioremap(res->start, size); + if (ax->map2 == NULL) { + dev_err(&pdev->dev, "cannot map reset register"); + ret = -ENXIO; + goto exit_mem2; + } + + ei_status.reg_offset[0x1f] = ax->map2 - ei_status.mem; + } + + /* got resources, now initialise and register device */ + + ret = ax_init_dev(dev, 1); + if (!ret) + return 0; + + if (ax->map2 == NULL) + goto exit_mem1; + + iounmap(ax->map2); + + exit_mem2: + release_resource(ax->mem2); + kfree(ax->mem2); + + exit_mem1: + iounmap(ei_status.mem); + + exit_req: + release_resource(ax->mem); + kfree(ax->mem); + + exit_mem: + free_netdev(dev); + + return ret; +} + +/* suspend and resume */ + +#ifdef CONFIG_PM +static int ax_suspend(struct platform_device *dev, pm_message_t state) +{ + struct net_device *ndev = platform_get_drvdata(dev); + struct ax_device *ax = to_ax_dev(ndev); + + ax->resume_open = ax->running; + + netif_device_detach(ndev); + ax_close(ndev); + + return 0; +} + +static int ax_resume(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct ax_device *ax = to_ax_dev(ndev); + + ax_initial_setup(ndev, netdev_priv(ndev)); + ax_NS8390_init(ndev, ax->resume_open); + netif_device_attach(ndev); + + if (ax->resume_open) + ax_open(ndev); + + return 0; +} + +#else +#define ax_suspend NULL +#define ax_resume NULL +#endif + +static struct platform_driver axdrv = { + .driver = { + .name = "ax88796", + .owner = THIS_MODULE, + }, + .probe = ax_probe, + .remove = ax_remove, + .suspend = ax_suspend, + .resume = ax_resume, +}; + +static int __init axdrv_init(void) +{ + return platform_driver_register(&axdrv); +} + +static void __exit axdrv_exit(void) +{ + platform_driver_unregister(&axdrv); +} + +module_init(axdrv_init); +module_exit(axdrv_exit); + +MODULE_DESCRIPTION("AX88796 10/100 Ethernet platform driver"); +MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 879a2fff474..96fb0ec905a 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -15,6 +15,7 @@ #include <linux/ethtool.h> #include <linux/mii.h> #include <linux/if_ether.h> +#include <linux/if_vlan.h> #include <linux/etherdevice.h> #include <linux/pci.h> #include <linux/delay.h> @@ -68,8 +69,8 @@ (BP)->tx_cons - (BP)->tx_prod - TX_RING_GAP(BP)) #define NEXT_TX(N) (((N) + 1) & (B44_TX_RING_SIZE - 1)) -#define RX_PKT_BUF_SZ (1536 + bp->rx_offset + 64) -#define TX_PKT_BUF_SZ (B44_MAX_MTU + ETH_HLEN + 8) +#define RX_PKT_OFFSET 30 +#define RX_PKT_BUF_SZ (1536 + RX_PKT_OFFSET + 64) /* minimum number of free TX descriptors required to wake up TX process */ #define B44_TX_WAKEUP_THRESH (B44_TX_RING_SIZE / 4) @@ -599,8 +600,7 @@ static void b44_timer(unsigned long __opaque) spin_unlock_irq(&bp->lock); - bp->timer.expires = jiffies + HZ; - add_timer(&bp->timer); + mod_timer(&bp->timer, round_jiffies(jiffies + HZ)); } static void b44_tx(struct b44 *bp) @@ -653,7 +653,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) src_map = &bp->rx_buffers[src_idx]; dest_idx = dest_idx_unmasked & (B44_RX_RING_SIZE - 1); map = &bp->rx_buffers[dest_idx]; - skb = dev_alloc_skb(RX_PKT_BUF_SZ); + skb = netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ); if (skb == NULL) return -ENOMEM; @@ -669,7 +669,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) if (!dma_mapping_error(mapping)) pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE); dev_kfree_skb_any(skb); - skb = __dev_alloc_skb(RX_PKT_BUF_SZ,GFP_DMA); + skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA); if (skb == NULL) return -ENOMEM; mapping = pci_map_single(bp->pdev, skb->data, @@ -684,11 +684,9 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) } } - skb->dev = bp->dev; - skb_reserve(skb, bp->rx_offset); + rh = (struct rx_header *) skb->data; + skb_reserve(skb, RX_PKT_OFFSET); - rh = (struct rx_header *) - (skb->data - bp->rx_offset); rh->len = 0; rh->flags = 0; @@ -698,13 +696,13 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) if (src_map != NULL) src_map->skb = NULL; - ctrl = (DESC_CTRL_LEN & (RX_PKT_BUF_SZ - bp->rx_offset)); + ctrl = (DESC_CTRL_LEN & (RX_PKT_BUF_SZ - RX_PKT_OFFSET)); if (dest_idx == (B44_RX_RING_SIZE - 1)) ctrl |= DESC_CTRL_EOT; dp = &bp->rx_ring[dest_idx]; dp->ctrl = cpu_to_le32(ctrl); - dp->addr = cpu_to_le32((u32) mapping + bp->rx_offset + bp->dma_offset); + dp->addr = cpu_to_le32((u32) mapping + RX_PKT_OFFSET + bp->dma_offset); if (bp->flags & B44_FLAG_RX_RING_HACK) b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma, @@ -783,7 +781,7 @@ static int b44_rx(struct b44 *bp, int budget) PCI_DMA_FROMDEVICE); rh = (struct rx_header *) skb->data; len = le16_to_cpu(rh->len); - if ((len > (RX_PKT_BUF_SZ - bp->rx_offset)) || + if ((len > (RX_PKT_BUF_SZ - RX_PKT_OFFSET)) || (rh->flags & cpu_to_le16(RX_FLAG_ERRORS))) { drop_it: b44_recycle_rx(bp, cons, bp->rx_prod); @@ -815,8 +813,8 @@ static int b44_rx(struct b44 *bp, int budget) pci_unmap_single(bp->pdev, map, skb_size, PCI_DMA_FROMDEVICE); /* Leave out rx_header */ - skb_put(skb, len+bp->rx_offset); - skb_pull(skb,bp->rx_offset); + skb_put(skb, len + RX_PKT_OFFSET); + skb_pull(skb, RX_PKT_OFFSET); } else { struct sk_buff *copy_skb; @@ -828,7 +826,7 @@ static int b44_rx(struct b44 *bp, int budget) skb_reserve(copy_skb, 2); skb_put(copy_skb, len); /* DMA sync done above, copy just the actual packet */ - skb_copy_from_linear_data_offset(skb, bp->rx_offset, + skb_copy_from_linear_data_offset(skb, RX_PKT_OFFSET, copy_skb->data, len); skb = copy_skb; } @@ -969,7 +967,6 @@ static void b44_tx_timeout(struct net_device *dev) static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct b44 *bp = netdev_priv(dev); - struct sk_buff *bounce_skb; int rc = NETDEV_TX_OK; dma_addr_t mapping; u32 len, entry, ctrl; @@ -987,12 +984,13 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev) mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE); if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) { + struct sk_buff *bounce_skb; + /* Chip can't handle DMA to/from >1GB, use bounce buffer */ if (!dma_mapping_error(mapping)) pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE); - bounce_skb = __dev_alloc_skb(TX_PKT_BUF_SZ, - GFP_ATOMIC|GFP_DMA); + bounce_skb = __dev_alloc_skb(len, GFP_ATOMIC | GFP_DMA); if (!bounce_skb) goto err_out; @@ -1001,13 +999,12 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev) if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) { if (!dma_mapping_error(mapping)) pci_unmap_single(bp->pdev, mapping, - len, PCI_DMA_TODEVICE); + len, PCI_DMA_TODEVICE); dev_kfree_skb_any(bounce_skb); goto err_out; } - skb_copy_from_linear_data(skb, skb_put(bounce_skb, len), - skb->len); + skb_copy_from_linear_data(skb, skb_put(bounce_skb, len), len); dev_kfree_skb_any(skb); skb = bounce_skb; } @@ -1396,12 +1393,12 @@ static void b44_init_hw(struct b44 *bp, int reset_kind) bw32(bp, B44_TX_WMARK, 56); /* XXX magic */ if (reset_kind == B44_PARTIAL_RESET) { bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE | - (bp->rx_offset << DMARX_CTRL_ROSHIFT))); + (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT))); } else { bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE); bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset); bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE | - (bp->rx_offset << DMARX_CTRL_ROSHIFT))); + (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT))); bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset); bw32(bp, B44_DMARX_PTR, bp->rx_pending); @@ -2093,11 +2090,6 @@ static int __devinit b44_get_invariants(struct b44 *bp) bp->phy_addr = eeprom[90] & 0x1f; - /* With this, plus the rx_header prepended to the data by the - * hardware, we'll land the ethernet header on a 2-byte boundary. - */ - bp->rx_offset = 30; - bp->imask = IMASK_DEF; bp->core_unit = ssb_core_unit(bp); @@ -2348,11 +2340,11 @@ static int b44_resume(struct pci_dev *pdev) netif_device_attach(bp->dev); spin_unlock_irq(&bp->lock); - bp->timer.expires = jiffies + HZ; - add_timer(&bp->timer); - b44_enable_ints(bp); netif_wake_queue(dev); + + mod_timer(&bp->timer, jiffies + 1); + return 0; } diff --git a/drivers/net/b44.h b/drivers/net/b44.h index 18fc1333662..e537e63f292 100644 --- a/drivers/net/b44.h +++ b/drivers/net/b44.h @@ -443,8 +443,6 @@ struct b44 { #define B44_FLAG_TX_RING_HACK 0x40000000 #define B44_FLAG_WOL_ENABLE 0x80000000 - u32 rx_offset; - u32 msg_enable; struct timer_list timer; diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 88b33c6ddda..d23861c8658 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -54,8 +54,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.5.10" -#define DRV_MODULE_RELDATE "May 1, 2007" +#define DRV_MODULE_VERSION "1.6.2" +#define DRV_MODULE_RELDATE "July 6, 2007" #define RUN_AT(x) (jiffies + (x)) @@ -550,6 +550,9 @@ bnx2_report_fw_link(struct bnx2 *bp) { u32 fw_link_status = 0; + if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) + return; + if (bp->link_up) { u32 bmsr; @@ -601,12 +604,21 @@ bnx2_report_fw_link(struct bnx2 *bp) REG_WR_IND(bp, bp->shmem_base + BNX2_LINK_STATUS, fw_link_status); } +static char * +bnx2_xceiver_str(struct bnx2 *bp) +{ + return ((bp->phy_port == PORT_FIBRE) ? "SerDes" : + ((bp->phy_flags & PHY_SERDES_FLAG) ? "Remote Copper" : + "Copper")); +} + static void bnx2_report_link(struct bnx2 *bp) { if (bp->link_up) { netif_carrier_on(bp->dev); - printk(KERN_INFO PFX "%s NIC Link is Up, ", bp->dev->name); + printk(KERN_INFO PFX "%s NIC %s Link is Up, ", bp->dev->name, + bnx2_xceiver_str(bp)); printk("%d Mbps ", bp->line_speed); @@ -630,7 +642,8 @@ bnx2_report_link(struct bnx2 *bp) } else { netif_carrier_off(bp->dev); - printk(KERN_ERR PFX "%s NIC Link is Down\n", bp->dev->name); + printk(KERN_ERR PFX "%s NIC %s Link is Down\n", bp->dev->name, + bnx2_xceiver_str(bp)); } bnx2_report_fw_link(bp); @@ -1100,6 +1113,9 @@ bnx2_set_link(struct bnx2 *bp) return 0; } + if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) + return 0; + link_up = bp->link_up; bnx2_enable_bmsr1(bp); @@ -1210,12 +1226,74 @@ bnx2_phy_get_pause_adv(struct bnx2 *bp) return adv; } +static int bnx2_fw_sync(struct bnx2 *, u32, int); + static int -bnx2_setup_serdes_phy(struct bnx2 *bp) +bnx2_setup_remote_phy(struct bnx2 *bp, u8 port) +{ + u32 speed_arg = 0, pause_adv; + + pause_adv = bnx2_phy_get_pause_adv(bp); + + if (bp->autoneg & AUTONEG_SPEED) { + speed_arg |= BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG; + if (bp->advertising & ADVERTISED_10baseT_Half) + speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_10HALF; + if (bp->advertising & ADVERTISED_10baseT_Full) + speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_10FULL; + if (bp->advertising & ADVERTISED_100baseT_Half) + speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_100HALF; + if (bp->advertising & ADVERTISED_100baseT_Full) + speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_100FULL; + if (bp->advertising & ADVERTISED_1000baseT_Full) + speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_1GFULL; + if (bp->advertising & ADVERTISED_2500baseX_Full) + speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_2G5FULL; + } else { + if (bp->req_line_speed == SPEED_2500) + speed_arg = BNX2_NETLINK_SET_LINK_SPEED_2G5FULL; + else if (bp->req_line_speed == SPEED_1000) + speed_arg = BNX2_NETLINK_SET_LINK_SPEED_1GFULL; + else if (bp->req_line_speed == SPEED_100) { + if (bp->req_duplex == DUPLEX_FULL) + speed_arg = BNX2_NETLINK_SET_LINK_SPEED_100FULL; + else + speed_arg = BNX2_NETLINK_SET_LINK_SPEED_100HALF; + } else if (bp->req_line_speed == SPEED_10) { + if (bp->req_duplex == DUPLEX_FULL) + speed_arg = BNX2_NETLINK_SET_LINK_SPEED_10FULL; + else + speed_arg = BNX2_NETLINK_SET_LINK_SPEED_10HALF; + } + } + + if (pause_adv & (ADVERTISE_1000XPAUSE | ADVERTISE_PAUSE_CAP)) + speed_arg |= BNX2_NETLINK_SET_LINK_FC_SYM_PAUSE; + if (pause_adv & (ADVERTISE_1000XPSE_ASYM | ADVERTISE_1000XPSE_ASYM)) + speed_arg |= BNX2_NETLINK_SET_LINK_FC_ASYM_PAUSE; + + if (port == PORT_TP) + speed_arg |= BNX2_NETLINK_SET_LINK_PHY_APP_REMOTE | + BNX2_NETLINK_SET_LINK_ETH_AT_WIRESPEED; + + REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB_ARG0, speed_arg); + + spin_unlock_bh(&bp->phy_lock); + bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_CMD_SET_LINK, 0); + spin_lock_bh(&bp->phy_lock); + + return 0; +} + +static int +bnx2_setup_serdes_phy(struct bnx2 *bp, u8 port) { u32 adv, bmcr; u32 new_adv = 0; + if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) + return (bnx2_setup_remote_phy(bp, port)); + if (!(bp->autoneg & AUTONEG_SPEED)) { u32 new_bmcr; int force_link_down = 0; @@ -1323,7 +1401,9 @@ bnx2_setup_serdes_phy(struct bnx2 *bp) } #define ETHTOOL_ALL_FIBRE_SPEED \ - (ADVERTISED_1000baseT_Full) + (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) ? \ + (ADVERTISED_2500baseX_Full | ADVERTISED_1000baseT_Full) :\ + (ADVERTISED_1000baseT_Full) #define ETHTOOL_ALL_COPPER_SPEED \ (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \ @@ -1335,6 +1415,188 @@ bnx2_setup_serdes_phy(struct bnx2 *bp) #define PHY_ALL_1000_SPEED (ADVERTISE_1000HALF | ADVERTISE_1000FULL) +static void +bnx2_set_default_remote_link(struct bnx2 *bp) +{ + u32 link; + + if (bp->phy_port == PORT_TP) + link = REG_RD_IND(bp, bp->shmem_base + BNX2_RPHY_COPPER_LINK); + else + link = REG_RD_IND(bp, bp->shmem_base + BNX2_RPHY_SERDES_LINK); + + if (link & BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG) { + bp->req_line_speed = 0; + bp->autoneg |= AUTONEG_SPEED; + bp->advertising = ADVERTISED_Autoneg; + if (link & BNX2_NETLINK_SET_LINK_SPEED_10HALF) + bp->advertising |= ADVERTISED_10baseT_Half; + if (link & BNX2_NETLINK_SET_LINK_SPEED_10FULL) + bp->advertising |= ADVERTISED_10baseT_Full; + if (link & BNX2_NETLINK_SET_LINK_SPEED_100HALF) + bp->advertising |= ADVERTISED_100baseT_Half; + if (link & BNX2_NETLINK_SET_LINK_SPEED_100FULL) + bp->advertising |= ADVERTISED_100baseT_Full; + if (link & BNX2_NETLINK_SET_LINK_SPEED_1GFULL) + bp->advertising |= ADVERTISED_1000baseT_Full; + if (link & BNX2_NETLINK_SET_LINK_SPEED_2G5FULL) + bp->advertising |= ADVERTISED_2500baseX_Full; + } else { + bp->autoneg = 0; + bp->advertising = 0; + bp->req_duplex = DUPLEX_FULL; + if (link & BNX2_NETLINK_SET_LINK_SPEED_10) { + bp->req_line_speed = SPEED_10; + if (link & BNX2_NETLINK_SET_LINK_SPEED_10HALF) + bp->req_duplex = DUPLEX_HALF; + } + if (link & BNX2_NETLINK_SET_LINK_SPEED_100) { + bp->req_line_speed = SPEED_100; + if (link & BNX2_NETLINK_SET_LINK_SPEED_100HALF) + bp->req_duplex = DUPLEX_HALF; + } + if (link & BNX2_NETLINK_SET_LINK_SPEED_1GFULL) + bp->req_line_speed = SPEED_1000; + if (link & BNX2_NETLINK_SET_LINK_SPEED_2G5FULL) + bp->req_line_speed = SPEED_2500; + } +} + +static void +bnx2_set_default_link(struct bnx2 *bp) +{ + if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) + return bnx2_set_default_remote_link(bp); + + bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL; + bp->req_line_speed = 0; + if (bp->phy_flags & PHY_SERDES_FLAG) { + u32 reg; + + bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg; + + reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG); + reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK; + if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) { + bp->autoneg = 0; + bp->req_line_speed = bp->line_speed = SPEED_1000; + bp->req_duplex = DUPLEX_FULL; + } + } else + bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg; +} + +static void +bnx2_send_heart_beat(struct bnx2 *bp) +{ + u32 msg; + u32 addr; + + spin_lock(&bp->indirect_lock); + msg = (u32) (++bp->fw_drv_pulse_wr_seq & BNX2_DRV_PULSE_SEQ_MASK); + addr = bp->shmem_base + BNX2_DRV_PULSE_MB; + REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, addr); + REG_WR(bp, BNX2_PCICFG_REG_WINDOW, msg); + spin_unlock(&bp->indirect_lock); +} + +static void +bnx2_remote_phy_event(struct bnx2 *bp) +{ + u32 msg; + u8 link_up = bp->link_up; + u8 old_port; + + msg = REG_RD_IND(bp, bp->shmem_base + BNX2_LINK_STATUS); + + if (msg & BNX2_LINK_STATUS_HEART_BEAT_EXPIRED) + bnx2_send_heart_beat(bp); + + msg &= ~BNX2_LINK_STATUS_HEART_BEAT_EXPIRED; + + if ((msg & BNX2_LINK_STATUS_LINK_UP) == BNX2_LINK_STATUS_LINK_DOWN) + bp->link_up = 0; + else { + u32 speed; + + bp->link_up = 1; + speed = msg & BNX2_LINK_STATUS_SPEED_MASK; + bp->duplex = DUPLEX_FULL; + switch (speed) { + case BNX2_LINK_STATUS_10HALF: + bp->duplex = DUPLEX_HALF; + case BNX2_LINK_STATUS_10FULL: + bp->line_speed = SPEED_10; + break; + case BNX2_LINK_STATUS_100HALF: + bp->duplex = DUPLEX_HALF; + case BNX2_LINK_STATUS_100BASE_T4: + case BNX2_LINK_STATUS_100FULL: + bp->line_speed = SPEED_100; + break; + case BNX2_LINK_STATUS_1000HALF: + bp->duplex = DUPLEX_HALF; + case BNX2_LINK_STATUS_1000FULL: + bp->line_speed = SPEED_1000; + break; + case BNX2_LINK_STATUS_2500HALF: + bp->duplex = DUPLEX_HALF; + case BNX2_LINK_STATUS_2500FULL: + bp->line_speed = SPEED_2500; + break; + default: + bp->line_speed = 0; + break; + } + + spin_lock(&bp->phy_lock); + bp->flow_ctrl = 0; + if ((bp->autoneg & (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) != + (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) { + if (bp->duplex == DUPLEX_FULL) + bp->flow_ctrl = bp->req_flow_ctrl; + } else { + if (msg & BNX2_LINK_STATUS_TX_FC_ENABLED) + bp->flow_ctrl |= FLOW_CTRL_TX; + if (msg & BNX2_LINK_STATUS_RX_FC_ENABLED) + bp->flow_ctrl |= FLOW_CTRL_RX; + } + + old_port = bp->phy_port; + if (msg & BNX2_LINK_STATUS_SERDES_LINK) + bp->phy_port = PORT_FIBRE; + else + bp->phy_port = PORT_TP; + + if (old_port != bp->phy_port) + bnx2_set_default_link(bp); + + spin_unlock(&bp->phy_lock); + } + if (bp->link_up != link_up) + bnx2_report_link(bp); + + bnx2_set_mac_link(bp); +} + +static int +bnx2_set_remote_link(struct bnx2 *bp) +{ + u32 evt_code; + + evt_code = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_EVT_CODE_MB); + switch (evt_code) { + case BNX2_FW_EVT_CODE_LINK_EVENT: + bnx2_remote_phy_event(bp); + break; + case BNX2_FW_EVT_CODE_SW_TIMER_EXPIRATION_EVENT: + default: + bnx2_send_heart_beat(bp); + break; + } + return 0; +} + static int bnx2_setup_copper_phy(struct bnx2 *bp) { @@ -1433,13 +1695,13 @@ bnx2_setup_copper_phy(struct bnx2 *bp) } static int -bnx2_setup_phy(struct bnx2 *bp) +bnx2_setup_phy(struct bnx2 *bp, u8 port) { if (bp->loopback == MAC_LOOPBACK) return 0; if (bp->phy_flags & PHY_SERDES_FLAG) { - return (bnx2_setup_serdes_phy(bp)); + return (bnx2_setup_serdes_phy(bp, port)); } else { return (bnx2_setup_copper_phy(bp)); @@ -1659,6 +1921,9 @@ bnx2_init_phy(struct bnx2 *bp) REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK); + if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) + goto setup_phy; + bnx2_read_phy(bp, MII_PHYSID1, &val); bp->phy_id = val << 16; bnx2_read_phy(bp, MII_PHYSID2, &val); @@ -1676,7 +1941,9 @@ bnx2_init_phy(struct bnx2 *bp) rc = bnx2_init_copper_phy(bp); } - bnx2_setup_phy(bp); +setup_phy: + if (!rc) + rc = bnx2_setup_phy(bp, bp->phy_port); return rc; } @@ -1778,6 +2045,15 @@ bnx2_init_5709_context(struct bnx2 *bp) val = BNX2_CTX_COMMAND_ENABLED | BNX2_CTX_COMMAND_MEM_INIT | (1 << 12); val |= (BCM_PAGE_BITS - 8) << 16; REG_WR(bp, BNX2_CTX_COMMAND, val); + for (i = 0; i < 10; i++) { + val = REG_RD(bp, BNX2_CTX_COMMAND); + if (!(val & BNX2_CTX_COMMAND_MEM_INIT)) + break; + udelay(2); + } + if (val & BNX2_CTX_COMMAND_MEM_INIT) + return -EBUSY; + for (i = 0; i < bp->ctx_pages; i++) { int j; @@ -1811,6 +2087,7 @@ bnx2_init_context(struct bnx2 *bp) vcid = 96; while (vcid) { u32 vcid_addr, pcid_addr, offset; + int i; vcid--; @@ -1831,16 +2108,20 @@ bnx2_init_context(struct bnx2 *bp) pcid_addr = vcid_addr; } - REG_WR(bp, BNX2_CTX_VIRT_ADDR, 0x00); - REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr); + for (i = 0; i < (CTX_SIZE / PHY_CTX_SIZE); i++) { + vcid_addr += (i << PHY_CTX_SHIFT); + pcid_addr += (i << PHY_CTX_SHIFT); - /* Zero out the context. */ - for (offset = 0; offset < PHY_CTX_SIZE; offset += 4) { - CTX_WR(bp, 0x00, offset, 0); - } + REG_WR(bp, BNX2_CTX_VIRT_ADDR, 0x00); + REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr); + + /* Zero out the context. */ + for (offset = 0; offset < PHY_CTX_SIZE; offset += 4) + CTX_WR(bp, 0x00, offset, 0); - REG_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr); - REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr); + REG_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr); + REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr); + } } } @@ -1970,6 +2251,9 @@ bnx2_phy_int(struct bnx2 *bp) bnx2_set_link(bp); spin_unlock(&bp->phy_lock); } + if (bnx2_phy_event_is_set(bp, STATUS_ATTN_BITS_TIMER_ABORT)) + bnx2_set_remote_link(bp); + } static void @@ -2283,6 +2567,7 @@ bnx2_interrupt(int irq, void *dev_instance) { struct net_device *dev = dev_instance; struct bnx2 *bp = netdev_priv(dev); + struct status_block *sblk = bp->status_blk; /* When using INTx, it is possible for the interrupt to arrive * at the CPU before the status block posted prior to the @@ -2290,7 +2575,7 @@ bnx2_interrupt(int irq, void *dev_instance) * When using MSI, the MSI message will always complete after * the status block write. */ - if ((bp->status_blk->status_idx == bp->last_status_idx) && + if ((sblk->status_idx == bp->last_status_idx) && (REG_RD(bp, BNX2_PCICFG_MISC_STATUS) & BNX2_PCICFG_MISC_STATUS_INTA_VALUE)) return IRQ_NONE; @@ -2299,16 +2584,25 @@ bnx2_interrupt(int irq, void *dev_instance) BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM | BNX2_PCICFG_INT_ACK_CMD_MASK_INT); + /* Read back to deassert IRQ immediately to avoid too many + * spurious interrupts. + */ + REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD); + /* Return here if interrupt is shared and is disabled. */ if (unlikely(atomic_read(&bp->intr_sem) != 0)) return IRQ_HANDLED; - netif_rx_schedule(dev); + if (netif_rx_schedule_prep(dev)) { + bp->last_status_idx = sblk->status_idx; + __netif_rx_schedule(dev); + } return IRQ_HANDLED; } -#define STATUS_ATTN_EVENTS STATUS_ATTN_BITS_LINK_STATE +#define STATUS_ATTN_EVENTS (STATUS_ATTN_BITS_LINK_STATE | \ + STATUS_ATTN_BITS_TIMER_ABORT) static inline int bnx2_has_work(struct bnx2 *bp) @@ -3548,6 +3842,36 @@ nvram_write_end: return rc; } +static void +bnx2_init_remote_phy(struct bnx2 *bp) +{ + u32 val; + + bp->phy_flags &= ~REMOTE_PHY_CAP_FLAG; + if (!(bp->phy_flags & PHY_SERDES_FLAG)) + return; + + val = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_CAP_MB); + if ((val & BNX2_FW_CAP_SIGNATURE_MASK) != BNX2_FW_CAP_SIGNATURE) + return; + + if (val & BNX2_FW_CAP_REMOTE_PHY_CAPABLE) { + if (netif_running(bp->dev)) { + val = BNX2_DRV_ACK_CAP_SIGNATURE | + BNX2_FW_CAP_REMOTE_PHY_CAPABLE; + REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_ACK_CAP_MB, + val); + } + bp->phy_flags |= REMOTE_PHY_CAP_FLAG; + + val = REG_RD_IND(bp, bp->shmem_base + BNX2_LINK_STATUS); + if (val & BNX2_LINK_STATUS_SERDES_LINK) + bp->phy_port = PORT_FIBRE; + else + bp->phy_port = PORT_TP; + } +} + static int bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) { @@ -3628,6 +3952,12 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) if (rc) return rc; + spin_lock_bh(&bp->phy_lock); + bnx2_init_remote_phy(bp); + if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) + bnx2_set_default_remote_link(bp); + spin_unlock_bh(&bp->phy_lock); + if (CHIP_ID(bp) == CHIP_ID_5706_A0) { /* Adjust the voltage regular to two steps lower. The default * of this register is 0x0000000e. */ @@ -3691,9 +4021,11 @@ bnx2_init_chip(struct bnx2 *bp) /* Initialize context mapping and zero out the quick contexts. The * context block must have already been enabled. */ - if (CHIP_NUM(bp) == CHIP_NUM_5709) - bnx2_init_5709_context(bp); - else + if (CHIP_NUM(bp) == CHIP_NUM_5709) { + rc = bnx2_init_5709_context(bp); + if (rc) + return rc; + } else bnx2_init_context(bp); if ((rc = bnx2_init_cpus(bp)) != 0) @@ -3772,7 +4104,10 @@ bnx2_init_chip(struct bnx2 *bp) REG_WR(bp, BNX2_HC_CMD_TICKS, (bp->cmd_ticks_int << 16) | bp->cmd_ticks); - REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks & 0xffff00); + if (CHIP_NUM(bp) == CHIP_NUM_5708) + REG_WR(bp, BNX2_HC_STATS_TICKS, 0); + else + REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks & 0xffff00); REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */ if (CHIP_ID(bp) == CHIP_ID_5706_A1) @@ -3799,10 +4134,15 @@ bnx2_init_chip(struct bnx2 *bp) /* Initialize the receive filter. */ bnx2_set_rx_mode(bp->dev); + if (CHIP_NUM(bp) == CHIP_NUM_5709) { + val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL); + val |= BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE; + REG_WR(bp, BNX2_MISC_NEW_CORE_CTL, val); + } rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET, 0); - REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, 0x5ffffff); + REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, BNX2_MISC_ENABLE_DEFAULT); REG_RD(bp, BNX2_MISC_ENABLE_SET_BITS); udelay(20); @@ -4045,8 +4385,8 @@ bnx2_init_nic(struct bnx2 *bp) spin_lock_bh(&bp->phy_lock); bnx2_init_phy(bp); - spin_unlock_bh(&bp->phy_lock); bnx2_set_link(bp); + spin_unlock_bh(&bp->phy_lock); return 0; } @@ -4576,6 +4916,9 @@ bnx2_5706_serdes_timer(struct bnx2 *bp) static void bnx2_5708_serdes_timer(struct bnx2 *bp) { + if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) + return; + if ((bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) == 0) { bp->serdes_an_pending = 0; return; @@ -4607,7 +4950,6 @@ static void bnx2_timer(unsigned long data) { struct bnx2 *bp = (struct bnx2 *) data; - u32 msg; if (!netif_running(bp->dev)) return; @@ -4615,11 +4957,15 @@ bnx2_timer(unsigned long data) if (atomic_read(&bp->intr_sem) != 0) goto bnx2_restart_timer; - msg = (u32) ++bp->fw_drv_pulse_wr_seq; - REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_PULSE_MB, msg); + bnx2_send_heart_beat(bp); bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT); + /* workaround occasional corrupted counters */ + if (CHIP_NUM(bp) == CHIP_NUM_5708 && bp->stats_ticks) + REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | + BNX2_HC_COMMAND_STATS_NOW); + if (bp->phy_flags & PHY_SERDES_FLAG) { if (CHIP_NUM(bp) == CHIP_NUM_5706) bnx2_5706_serdes_timer(bp); @@ -4786,19 +5132,6 @@ bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp) bnx2_netif_start(bp); } - -/* Called with rtnl_lock */ -static void -bnx2_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) -{ - struct bnx2 *bp = netdev_priv(dev); - - bnx2_netif_stop(bp); - vlan_group_set_device(bp->vlgrp, vid, NULL); - bnx2_set_rx_mode(dev); - - bnx2_netif_start(bp); -} #endif /* Called with netif_tx_lock. @@ -5067,17 +5400,25 @@ static int bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct bnx2 *bp = netdev_priv(dev); + int support_serdes = 0, support_copper = 0; cmd->supported = SUPPORTED_Autoneg; - if (bp->phy_flags & PHY_SERDES_FLAG) { + if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) { + support_serdes = 1; + support_copper = 1; + } else if (bp->phy_port == PORT_FIBRE) + support_serdes = 1; + else + support_copper = 1; + + if (support_serdes) { cmd->supported |= SUPPORTED_1000baseT_Full | SUPPORTED_FIBRE; if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) cmd->supported |= SUPPORTED_2500baseX_Full; - cmd->port = PORT_FIBRE; } - else { + if (support_copper) { cmd->supported |= SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | @@ -5085,9 +5426,10 @@ bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) SUPPORTED_1000baseT_Full | SUPPORTED_TP; - cmd->port = PORT_TP; } + spin_lock_bh(&bp->phy_lock); + cmd->port = bp->phy_port; cmd->advertising = bp->advertising; if (bp->autoneg & AUTONEG_SPEED) { @@ -5105,6 +5447,7 @@ bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->speed = -1; cmd->duplex = -1; } + spin_unlock_bh(&bp->phy_lock); cmd->transceiver = XCVR_INTERNAL; cmd->phy_address = bp->phy_addr; @@ -5120,6 +5463,15 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) u8 req_duplex = bp->req_duplex; u16 req_line_speed = bp->req_line_speed; u32 advertising = bp->advertising; + int err = -EINVAL; + + spin_lock_bh(&bp->phy_lock); + + if (cmd->port != PORT_TP && cmd->port != PORT_FIBRE) + goto err_out_unlock; + + if (cmd->port != bp->phy_port && !(bp->phy_flags & REMOTE_PHY_CAP_FLAG)) + goto err_out_unlock; if (cmd->autoneg == AUTONEG_ENABLE) { autoneg |= AUTONEG_SPEED; @@ -5132,44 +5484,41 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) (cmd->advertising == ADVERTISED_100baseT_Half) || (cmd->advertising == ADVERTISED_100baseT_Full)) { - if (bp->phy_flags & PHY_SERDES_FLAG) - return -EINVAL; + if (cmd->port == PORT_FIBRE) + goto err_out_unlock; advertising = cmd->advertising; } else if (cmd->advertising == ADVERTISED_2500baseX_Full) { - if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)) - return -EINVAL; - } else if (cmd->advertising == ADVERTISED_1000baseT_Full) { + if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) || + (cmd->port == PORT_TP)) + goto err_out_unlock; + } else if (cmd->advertising == ADVERTISED_1000baseT_Full) advertising = cmd->advertising; - } - else if (cmd->advertising == ADVERTISED_1000baseT_Half) { - return -EINVAL; - } + else if (cmd->advertising == ADVERTISED_1000baseT_Half) + goto err_out_unlock; else { - if (bp->phy_flags & PHY_SERDES_FLAG) { + if (cmd->port == PORT_FIBRE) advertising = ETHTOOL_ALL_FIBRE_SPEED; - } - else { + else advertising = ETHTOOL_ALL_COPPER_SPEED; - } } advertising |= ADVERTISED_Autoneg; } else { - if (bp->phy_flags & PHY_SERDES_FLAG) { + if (cmd->port == PORT_FIBRE) { if ((cmd->speed != SPEED_1000 && cmd->speed != SPEED_2500) || (cmd->duplex != DUPLEX_FULL)) - return -EINVAL; + goto err_out_unlock; if (cmd->speed == SPEED_2500 && !(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)) - return -EINVAL; - } - else if (cmd->speed == SPEED_1000) { - return -EINVAL; + goto err_out_unlock; } + else if (cmd->speed == SPEED_1000 || cmd->speed == SPEED_2500) + goto err_out_unlock; + autoneg &= ~AUTONEG_SPEED; req_line_speed = cmd->speed; req_duplex = cmd->duplex; @@ -5181,13 +5530,12 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) bp->req_line_speed = req_line_speed; bp->req_duplex = req_duplex; - spin_lock_bh(&bp->phy_lock); - - bnx2_setup_phy(bp); + err = bnx2_setup_phy(bp, cmd->port); +err_out_unlock: spin_unlock_bh(&bp->phy_lock); - return 0; + return err; } static void @@ -5198,11 +5546,7 @@ bnx2_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) strcpy(info->driver, DRV_MODULE_NAME); strcpy(info->version, DRV_MODULE_VERSION); strcpy(info->bus_info, pci_name(bp->pdev)); - info->fw_version[0] = ((bp->fw_ver & 0xff000000) >> 24) + '0'; - info->fw_version[2] = ((bp->fw_ver & 0xff0000) >> 16) + '0'; - info->fw_version[4] = ((bp->fw_ver & 0xff00) >> 8) + '0'; - info->fw_version[1] = info->fw_version[3] = '.'; - info->fw_version[5] = 0; + strcpy(info->fw_version, bp->fw_version); } #define BNX2_REGDUMP_LEN (32 * 1024) @@ -5314,6 +5658,14 @@ bnx2_nway_reset(struct net_device *dev) spin_lock_bh(&bp->phy_lock); + if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) { + int rc; + + rc = bnx2_setup_remote_phy(bp, bp->phy_port); + spin_unlock_bh(&bp->phy_lock); + return rc; + } + /* Force a link down visible on the other side */ if (bp->phy_flags & PHY_SERDES_FLAG) { bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK); @@ -5430,6 +5782,10 @@ bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal) 0xff; bp->stats_ticks = coal->stats_block_coalesce_usecs; + if (CHIP_NUM(bp) == CHIP_NUM_5708) { + if (bp->stats_ticks != 0 && bp->stats_ticks != USEC_PER_SEC) + bp->stats_ticks = USEC_PER_SEC; + } if (bp->stats_ticks > 0xffff00) bp->stats_ticks = 0xffff00; bp->stats_ticks &= 0xffff00; @@ -5523,7 +5879,7 @@ bnx2_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) spin_lock_bh(&bp->phy_lock); - bnx2_setup_phy(bp); + bnx2_setup_phy(bp, bp->phy_port); spin_unlock_bh(&bp->phy_lock); @@ -5862,7 +6218,7 @@ bnx2_set_tx_csum(struct net_device *dev, u32 data) struct bnx2 *bp = netdev_priv(dev); if (CHIP_NUM(bp) == CHIP_NUM_5709) - return (ethtool_op_set_tx_hw_csum(dev, data)); + return (ethtool_op_set_tx_ipv6_csum(dev, data)); else return (ethtool_op_set_tx_csum(dev, data)); } @@ -5919,6 +6275,9 @@ bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SIOCGMIIREG: { u32 mii_regval; + if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) + return -EOPNOTSUPP; + if (!netif_running(dev)) return -EAGAIN; @@ -5935,6 +6294,9 @@ bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if (!capable(CAP_NET_ADMIN)) return -EPERM; + if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) + return -EOPNOTSUPP; + if (!netif_running(dev)) return -EAGAIN; @@ -6096,7 +6458,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) { struct bnx2 *bp; unsigned long mem_len; - int rc; + int rc, i, j; u32 reg; u64 dma_mask, persist_dma_mask; @@ -6253,7 +6615,35 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) goto err_out_unmap; } - bp->fw_ver = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_BC_REV); + reg = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_BC_REV); + for (i = 0, j = 0; i < 3; i++) { + u8 num, k, skip0; + + num = (u8) (reg >> (24 - (i * 8))); + for (k = 100, skip0 = 1; k >= 1; num %= k, k /= 10) { + if (num >= k || !skip0 || k == 1) { + bp->fw_version[j++] = (num / k) + '0'; + skip0 = 0; + } + } + if (i != 2) + bp->fw_version[j++] = '.'; + } + reg = REG_RD_IND(bp, bp->shmem_base + BNX2_BC_STATE_CONDITION); + reg &= BNX2_CONDITION_MFW_RUN_MASK; + if (reg != BNX2_CONDITION_MFW_RUN_UNKNOWN && + reg != BNX2_CONDITION_MFW_RUN_NONE) { + int i; + u32 addr = REG_RD_IND(bp, bp->shmem_base + BNX2_MFW_VER_PTR); + + bp->fw_version[j++] = ' '; + for (i = 0; i < 3; i++) { + reg = REG_RD_IND(bp, addr + i * 4); + reg = swab32(reg); + memcpy(&bp->fw_version[j], ®, 4); + j += 4; + } + } reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_MAC_UPPER); bp->mac_addr[0] = (u8) (reg >> 8); @@ -6295,7 +6685,9 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) else if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT) bp->phy_flags |= PHY_SERDES_FLAG; + bp->phy_port = PORT_TP; if (bp->phy_flags & PHY_SERDES_FLAG) { + bp->phy_port = PORT_FIBRE; bp->flags |= NO_WOL_FLAG; if (CHIP_NUM(bp) != CHIP_NUM_5706) { bp->phy_addr = 2; @@ -6304,6 +6696,8 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G) bp->phy_flags |= PHY_2_5G_CAPABLE_FLAG; } + bnx2_init_remote_phy(bp); + } else if (CHIP_NUM(bp) == CHIP_NUM_5706 || CHIP_NUM(bp) == CHIP_NUM_5708) bp->phy_flags |= PHY_CRC_FIX_FLAG; @@ -6343,10 +6737,9 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) while ((amd_8132 = pci_get_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE, amd_8132))) { - u8 rev; - pci_read_config_byte(amd_8132, PCI_REVISION_ID, &rev); - if (rev >= 0x10 && rev <= 0x13) { + if (amd_8132->revision >= 0x10 && + amd_8132->revision <= 0x13) { disable_msi = 1; pci_dev_put(amd_8132); break; @@ -6354,23 +6747,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) } } - bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL; - bp->req_line_speed = 0; - if (bp->phy_flags & PHY_SERDES_FLAG) { - bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg; - - reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG); - reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK; - if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) { - bp->autoneg = 0; - bp->req_line_speed = bp->line_speed = SPEED_1000; - bp->req_duplex = DUPLEX_FULL; - } - } - else { - bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg; - } - + bnx2_set_default_link(bp); bp->req_flow_ctrl = FLOW_CTRL_RX | FLOW_CTRL_TX; init_timer(&bp->timer); @@ -6453,7 +6830,6 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->watchdog_timeo = TX_TIMEOUT; #ifdef BCM_VLAN dev->vlan_rx_register = bnx2_vlan_rx_register; - dev->vlan_rx_kill_vid = bnx2_vlan_rx_kill_vid; #endif dev->poll = bnx2_poll; dev->ethtool_ops = &bnx2_ethtool_ops; @@ -6471,10 +6847,10 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) memcpy(dev->perm_addr, bp->mac_addr, 6); bp->name = board_info[ent->driver_data].name; + dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; if (CHIP_NUM(bp) == CHIP_NUM_5709) - dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG; - else - dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; + dev->features |= NETIF_F_IPV6_CSUM; + #ifdef BCM_VLAN dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; #endif diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index bd6288d6350..d8cd1afeb23 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -1373,6 +1373,7 @@ struct l2_fhdr { #define BNX2_MISC_NEW_CORE_CTL 0x000008c8 #define BNX2_MISC_NEW_CORE_CTL_LINK_HOLDOFF_SUCCESS (1L<<0) #define BNX2_MISC_NEW_CORE_CTL_LINK_HOLDOFF_REQ (1L<<1) +#define BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE (1L<<16) #define BNX2_MISC_NEW_CORE_CTL_RESERVED_CMN (0x3fffL<<2) #define BNX2_MISC_NEW_CORE_CTL_RESERVED_TC (0xffffL<<16) @@ -6337,6 +6338,8 @@ struct l2_fhdr { #define RX_COPY_THRESH 92 +#define BNX2_MISC_ENABLE_DEFAULT 0x7ffffff + #define DMA_READ_CHANS 5 #define DMA_WRITE_CHANS 3 @@ -6536,6 +6539,7 @@ struct bnx2 { #define PHY_INT_MODE_AUTO_POLLING_FLAG 0x100 #define PHY_INT_MODE_LINK_READY_FLAG 0x200 #define PHY_DIS_EARLY_DAC_FLAG 0x400 +#define REMOTE_PHY_CAP_FLAG 0x800 u32 mii_bmcr; u32 mii_bmsr; @@ -6624,6 +6628,7 @@ struct bnx2 { u16 req_line_speed; u8 req_duplex; + u8 phy_port; u8 link_up; u16 line_speed; @@ -6655,7 +6660,7 @@ struct bnx2 { u32 shmem_base; - u32 fw_ver; + char fw_version[32]; int pm_cap; int pcix_cap; @@ -6769,7 +6774,7 @@ struct fw_info { * the firmware has timed out, the driver will assume there is no firmware * running and there won't be any firmware-driver synchronization during a * driver reset. */ -#define FW_ACK_TIME_OUT_MS 100 +#define FW_ACK_TIME_OUT_MS 1000 #define BNX2_DRV_RESET_SIGNATURE 0x00000000 @@ -6787,6 +6792,7 @@ struct fw_info { #define BNX2_DRV_MSG_CODE_DIAG 0x07000000 #define BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL 0x09000000 #define BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN 0x0b000000 +#define BNX2_DRV_MSG_CODE_CMD_SET_LINK 0x10000000 #define BNX2_DRV_MSG_DATA 0x00ff0000 #define BNX2_DRV_MSG_DATA_WAIT0 0x00010000 @@ -6835,6 +6841,7 @@ struct fw_info { #define BNX2_LINK_STATUS_SERDES_LINK (1<<20) #define BNX2_LINK_STATUS_PARTNER_AD_2500FULL (1<<21) #define BNX2_LINK_STATUS_PARTNER_AD_2500HALF (1<<22) +#define BNX2_LINK_STATUS_HEART_BEAT_EXPIRED (1<<31) #define BNX2_DRV_PULSE_MB 0x00000010 #define BNX2_DRV_PULSE_SEQ_MASK 0x00007fff @@ -6844,6 +6851,30 @@ struct fw_info { * This is used for debugging. */ #define BNX2_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE 0x00080000 +#define BNX2_DRV_MB_ARG0 0x00000014 +#define BNX2_NETLINK_SET_LINK_SPEED_10HALF (1<<0) +#define BNX2_NETLINK_SET_LINK_SPEED_10FULL (1<<1) +#define BNX2_NETLINK_SET_LINK_SPEED_10 \ + (BNX2_NETLINK_SET_LINK_SPEED_10HALF | \ + BNX2_NETLINK_SET_LINK_SPEED_10FULL) +#define BNX2_NETLINK_SET_LINK_SPEED_100HALF (1<<2) +#define BNX2_NETLINK_SET_LINK_SPEED_100FULL (1<<3) +#define BNX2_NETLINK_SET_LINK_SPEED_100 \ + (BNX2_NETLINK_SET_LINK_SPEED_100HALF | \ + BNX2_NETLINK_SET_LINK_SPEED_100FULL) +#define BNX2_NETLINK_SET_LINK_SPEED_1GHALF (1<<4) +#define BNX2_NETLINK_SET_LINK_SPEED_1GFULL (1<<5) +#define BNX2_NETLINK_SET_LINK_SPEED_2G5HALF (1<<6) +#define BNX2_NETLINK_SET_LINK_SPEED_2G5FULL (1<<7) +#define BNX2_NETLINK_SET_LINK_SPEED_10GHALF (1<<8) +#define BNX2_NETLINK_SET_LINK_SPEED_10GFULL (1<<9) +#define BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG (1<<10) +#define BNX2_NETLINK_SET_LINK_PHY_APP_REMOTE (1<<11) +#define BNX2_NETLINK_SET_LINK_FC_SYM_PAUSE (1<<12) +#define BNX2_NETLINK_SET_LINK_FC_ASYM_PAUSE (1<<13) +#define BNX2_NETLINK_SET_LINK_ETH_AT_WIRESPEED (1<<14) +#define BNX2_NETLINK_SET_LINK_PHY_RESET (1<<15) + #define BNX2_DEV_INFO_SIGNATURE 0x00000020 #define BNX2_DEV_INFO_SIGNATURE_MAGIC 0x44564900 #define BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK 0xffffff00 @@ -7005,6 +7036,8 @@ struct fw_info { #define BNX2_PORT_FEATURE_MBA_VLAN_TAG_MASK 0xffff #define BNX2_PORT_FEATURE_MBA_VLAN_ENABLE 0x10000 +#define BNX2_MFW_VER_PTR 0x00000014c + #define BNX2_BC_STATE_RESET_TYPE 0x000001c0 #define BNX2_BC_STATE_RESET_TYPE_SIG 0x00005254 #define BNX2_BC_STATE_RESET_TYPE_SIG_MASK 0x0000ffff @@ -7058,12 +7091,42 @@ struct fw_info { #define BNX2_BC_STATE_ERR_NO_RXP (BNX2_BC_STATE_SIGN | 0x0600) #define BNX2_BC_STATE_ERR_TOO_MANY_RBUF (BNX2_BC_STATE_SIGN | 0x0700) +#define BNX2_BC_STATE_CONDITION 0x000001c8 +#define BNX2_CONDITION_MFW_RUN_UNKNOWN 0x00000000 +#define BNX2_CONDITION_MFW_RUN_IPMI 0x00002000 +#define BNX2_CONDITION_MFW_RUN_UMP 0x00004000 +#define BNX2_CONDITION_MFW_RUN_NCSI 0x00006000 +#define BNX2_CONDITION_MFW_RUN_NONE 0x0000e000 +#define BNX2_CONDITION_MFW_RUN_MASK 0x0000e000 + #define BNX2_BC_STATE_DEBUG_CMD 0x1dc #define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE 0x42440000 #define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE_MASK 0xffff0000 #define BNX2_BC_STATE_BC_DBG_CMD_LOOP_CNT_MASK 0xffff #define BNX2_BC_STATE_BC_DBG_CMD_LOOP_INFINITE 0xffff +#define BNX2_FW_EVT_CODE_MB 0x354 +#define BNX2_FW_EVT_CODE_SW_TIMER_EXPIRATION_EVENT 0x00000000 +#define BNX2_FW_EVT_CODE_LINK_EVENT 0x00000001 + +#define BNX2_DRV_ACK_CAP_MB 0x364 +#define BNX2_DRV_ACK_CAP_SIGNATURE 0x35450000 +#define BNX2_CAPABILITY_SIGNATURE_MASK 0xFFFF0000 + +#define BNX2_FW_CAP_MB 0x368 +#define BNX2_FW_CAP_SIGNATURE 0xaa550000 +#define BNX2_FW_ACK_DRV_SIGNATURE 0x52500000 +#define BNX2_FW_CAP_SIGNATURE_MASK 0xffff0000 +#define BNX2_FW_CAP_REMOTE_PHY_CAPABLE 0x00000001 +#define BNX2_FW_CAP_REMOTE_PHY_PRESENT 0x00000002 + +#define BNX2_RPHY_SIGNATURE 0x36c +#define BNX2_RPHY_LOAD_SIGNATURE 0x5a5a5a5a + +#define BNX2_RPHY_FLAGS 0x370 +#define BNX2_RPHY_SERDES_LINK 0x374 +#define BNX2_RPHY_COPPER_LINK 0x378 + #define HOST_VIEW_SHMEM_BASE 0x167c00 #endif diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 7e03f41ae2c..f829e4ad8b4 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -2303,19 +2303,18 @@ void bond_3ad_handle_link_change(struct slave *slave, char link) } /* - * set link state for bonding master: if we have an active partnered + * set link state for bonding master: if we have an active * aggregator, we're up, if not, we're down. Presumes that we cannot * have an active aggregator if there are no slaves with link up. * + * This behavior complies with IEEE 802.3 section 43.3.9. + * * Called by bond_set_carrier(). Return zero if carrier state does not * change, nonzero if it does. */ int bond_3ad_set_carrier(struct bonding *bond) { - struct aggregator *agg; - - agg = __get_active_agg(&(SLAVE_AD_INFO(bond->first_slave).aggregator)); - if (agg && MAC_ADDRESS_COMPARE(&agg->partner_system, &null_mac_addr)) { + if (__get_active_agg(&(SLAVE_AD_INFO(bond->first_slave).aggregator))) { if (!netif_carrier_ok(bond->dev)) { netif_carrier_on(bond->dev); return 1; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 223517dcbcf..cb9cb3013f4 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -187,7 +187,7 @@ static void bond_send_gratuitous_arp(struct bonding *bond); /*---------------------------- General routines -----------------------------*/ -const char *bond_mode_name(int mode) +static const char *bond_mode_name(int mode) { switch (mode) { case BOND_MODE_ROUNDROBIN : @@ -1224,7 +1224,8 @@ static void bond_detach_slave(struct bonding *bond, struct slave *slave) /*---------------------------------- IOCTL ----------------------------------*/ -int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev) +static int bond_sethwaddr(struct net_device *bond_dev, + struct net_device *slave_dev) { dprintk("bond_dev=%p\n", bond_dev); dprintk("slave_dev=%p\n", slave_dev); @@ -1390,6 +1391,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) goto err_free; } + res = netdev_set_master(slave_dev, bond_dev); + if (res) { + dprintk("Error %d calling netdev_set_master\n", res); + goto err_close; + } /* open the slave since the application closed it */ res = dev_open(slave_dev); if (res) { @@ -1397,12 +1403,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) goto err_restore_mac; } - res = netdev_set_master(slave_dev, bond_dev); - if (res) { - dprintk("Error %d calling netdev_set_master\n", res); - goto err_close; - } - new_slave->dev = slave_dev; slave_dev->priv_flags |= IFF_BONDING; @@ -4345,8 +4345,8 @@ static void bond_free_all(void) bond_mc_list_destroy(bond); /* Release the bonded slaves */ bond_release_all(bond_dev); - unregister_netdevice(bond_dev); bond_deinit(bond_dev); + unregister_netdevice(bond_dev); } #ifdef CONFIG_PROC_FS diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index a122baa5c7b..60cccf2aa95 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -164,9 +164,9 @@ static ssize_t bonding_store_bonds(struct class *cls, const char *buffer, size_t printk(KERN_INFO DRV_NAME ": %s is being deleted...\n", bond->dev->name); - unregister_netdevice(bond->dev); bond_deinit(bond->dev); bond_destroy_sysfs_entry(bond); + unregister_netdevice(bond->dev); rtnl_unlock(); goto out; } diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 41aa78bf1f7..6dcbd25e3ef 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -22,8 +22,8 @@ #include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "3.1.2" -#define DRV_RELDATE "January 20, 2007" +#define DRV_VERSION "3.1.3" +#define DRV_RELDATE "June 13, 2007" #define DRV_NAME "bonding" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" @@ -301,13 +301,11 @@ int bond_create_slave_symlinks(struct net_device *master, struct net_device *sla void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave); int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev); int bond_release(struct net_device *bond_dev, struct net_device *slave_dev); -int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev); void bond_mii_monitor(struct net_device *bond_dev); void bond_loadbalance_arp_mon(struct net_device *bond_dev); void bond_activebackup_arp_mon(struct net_device *bond_dev); void bond_set_mode_ops(struct bonding *bond, int mode); int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl); -const char *bond_mode_name(int mode); void bond_select_active_slave(struct bonding *bond); void bond_change_active_slave(struct bonding *bond, struct slave *new_active); void bond_register_arp(struct bonding *); diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 9fe3a38883e..f6e4030c73d 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -3422,21 +3422,19 @@ done: static void cas_check_pci_invariants(struct cas *cp) { struct pci_dev *pdev = cp->pdev; - u8 rev; cp->cas_flags = 0; - pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); if ((pdev->vendor == PCI_VENDOR_ID_SUN) && (pdev->device == PCI_DEVICE_ID_SUN_CASSINI)) { - if (rev >= CAS_ID_REVPLUS) + if (pdev->revision >= CAS_ID_REVPLUS) cp->cas_flags |= CAS_FLAG_REG_PLUS; - if (rev < CAS_ID_REVPLUS02u) + if (pdev->revision < CAS_ID_REVPLUS02u) cp->cas_flags |= CAS_FLAG_TARGET_ABORT; /* Original Cassini supports HW CSUM, but it's not * enabled by default as it can trigger TX hangs. */ - if (rev < CAS_ID_REV2) + if (pdev->revision < CAS_ID_REV2) cp->cas_flags |= CAS_FLAG_NO_HW_CSUM; } else { /* Only sun has original cassini chips. */ @@ -4919,13 +4917,13 @@ static int __devinit cas_init_one(struct pci_dev *pdev, pci_cmd &= ~PCI_COMMAND_SERR; pci_cmd |= PCI_COMMAND_PARITY; pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - if (pci_set_mwi(pdev)) - printk(KERN_WARNING PFX "Could enable MWI for %s\n", + if (pci_try_set_mwi(pdev)) + printk(KERN_WARNING PFX "Could not enable MWI for %s\n", pci_name(pdev)); /* * On some architectures, the default cache line size set - * by pci_set_mwi reduces perforamnce. We have to increase + * by pci_try_set_mwi reduces perforamnce. We have to increase * it for this case. To start, we'll print some configuration * data. */ diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index 125c9b10586..231ce43b97c 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -883,15 +883,6 @@ static void vlan_rx_register(struct net_device *dev, t1_set_vlan_accel(adapter, grp != NULL); spin_unlock_irq(&adapter->async_lock); } - -static void vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) -{ - struct adapter *adapter = dev->priv; - - spin_lock_irq(&adapter->async_lock); - vlan_group_set_device(adapter->vlan_grp, vid, NULL); - spin_unlock_irq(&adapter->async_lock); -} #endif #ifdef CONFIG_NET_POLL_CONTROLLER @@ -1099,7 +1090,6 @@ static int __devinit init_one(struct pci_dev *pdev, netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; netdev->vlan_rx_register = vlan_rx_register; - netdev->vlan_rx_kill_vid = vlan_rx_kill_vid; #endif /* T204: disable TSO */ diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h index 80c3d8f268a..ab72563b81e 100644 --- a/drivers/net/cxgb3/adapter.h +++ b/drivers/net/cxgb3/adapter.h @@ -71,27 +71,29 @@ enum { /* adapter flags */ QUEUES_BOUND = (1 << 3), }; +struct fl_pg_chunk { + struct page *page; + void *va; + unsigned int offset; +}; + struct rx_desc; struct rx_sw_desc; -struct sge_fl_page { - struct skb_frag_struct frag; - unsigned char *va; -}; - -struct sge_fl { /* SGE per free-buffer list state */ - unsigned int buf_size; /* size of each Rx buffer */ - unsigned int credits; /* # of available Rx buffers */ - unsigned int size; /* capacity of free list */ - unsigned int cidx; /* consumer index */ - unsigned int pidx; /* producer index */ - unsigned int gen; /* free list generation */ - unsigned int cntxt_id; /* SGE context id for the free list */ - struct sge_fl_page page; - struct rx_desc *desc; /* address of HW Rx descriptor ring */ - struct rx_sw_desc *sdesc; /* address of SW Rx descriptor ring */ - dma_addr_t phys_addr; /* physical address of HW ring start */ - unsigned long empty; /* # of times queue ran out of buffers */ +struct sge_fl { /* SGE per free-buffer list state */ + unsigned int buf_size; /* size of each Rx buffer */ + unsigned int credits; /* # of available Rx buffers */ + unsigned int size; /* capacity of free list */ + unsigned int cidx; /* consumer index */ + unsigned int pidx; /* producer index */ + unsigned int gen; /* free list generation */ + struct fl_pg_chunk pg_chunk;/* page chunk cache */ + unsigned int use_pages; /* whether FL uses pages or sk_buffs */ + struct rx_desc *desc; /* address of HW Rx descriptor ring */ + struct rx_sw_desc *sdesc; /* address of SW Rx descriptor ring */ + dma_addr_t phys_addr; /* physical address of HW ring start */ + unsigned int cntxt_id; /* SGE context id for the free list */ + unsigned long empty; /* # of times queue ran out of buffers */ unsigned long alloc_failed; /* # of times buffer allocation failed */ }; diff --git a/drivers/net/cxgb3/ael1002.c b/drivers/net/cxgb3/ael1002.c index 73a41e6a5bf..ee140e63ddc 100644 --- a/drivers/net/cxgb3/ael1002.c +++ b/drivers/net/cxgb3/ael1002.c @@ -219,7 +219,13 @@ static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok, unsigned int status; status = t3_read_reg(phy->adapter, - XGM_REG(A_XGM_SERDES_STAT0, phy->addr)); + XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) | + t3_read_reg(phy->adapter, + XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) | + t3_read_reg(phy->adapter, + XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) | + t3_read_reg(phy->adapter, + XGM_REG(A_XGM_SERDES_STAT3, phy->addr)); *link_ok = !(status & F_LOWSIG0); } if (speed) @@ -247,5 +253,5 @@ static struct cphy_ops xaui_direct_ops = { void t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr, const struct mdio_ops *mdio_ops) { - cphy_init(phy, adapter, 1, &xaui_direct_ops, mdio_ops); + cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops); } diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h index 8d137963369..16378004507 100644 --- a/drivers/net/cxgb3/common.h +++ b/drivers/net/cxgb3/common.h @@ -101,6 +101,7 @@ enum { TCB_SIZE = 128, /* TCB size */ NMTUS = 16, /* size of MTU table */ NCCTRL_WIN = 32, /* # of congestion control windows */ + PROTO_SRAM_LINES = 128, /* size of TP sram */ }; #define MAX_RX_COALESCING_LEN 16224U @@ -124,6 +125,30 @@ enum { /* adapter interrupt-maintained statistics */ }; enum { + TP_VERSION_MAJOR = 1, + TP_VERSION_MINOR = 0, + TP_VERSION_MICRO = 44 +}; + +#define S_TP_VERSION_MAJOR 16 +#define M_TP_VERSION_MAJOR 0xFF +#define V_TP_VERSION_MAJOR(x) ((x) << S_TP_VERSION_MAJOR) +#define G_TP_VERSION_MAJOR(x) \ + (((x) >> S_TP_VERSION_MAJOR) & M_TP_VERSION_MAJOR) + +#define S_TP_VERSION_MINOR 8 +#define M_TP_VERSION_MINOR 0xFF +#define V_TP_VERSION_MINOR(x) ((x) << S_TP_VERSION_MINOR) +#define G_TP_VERSION_MINOR(x) \ + (((x) >> S_TP_VERSION_MINOR) & M_TP_VERSION_MINOR) + +#define S_TP_VERSION_MICRO 0 +#define M_TP_VERSION_MICRO 0xFF +#define V_TP_VERSION_MICRO(x) ((x) << S_TP_VERSION_MICRO) +#define G_TP_VERSION_MICRO(x) \ + (((x) >> S_TP_VERSION_MICRO) & M_TP_VERSION_MICRO) + +enum { SGE_QSETS = 8, /* # of SGE Tx/Rx/RspQ sets */ SGE_RXQ_PER_SET = 2, /* # of Rx queues per set */ SGE_TXQ_PER_SET = 3 /* # of Tx queues per set */ @@ -654,6 +679,9 @@ const struct adapter_info *t3_get_adapter_info(unsigned int board_id); int t3_seeprom_read(struct adapter *adapter, u32 addr, u32 *data); int t3_seeprom_write(struct adapter *adapter, u32 addr, u32 data); int t3_seeprom_wp(struct adapter *adapter, int enable); +int t3_check_tpsram_version(struct adapter *adapter); +int t3_check_tpsram(struct adapter *adapter, u8 *tp_ram, unsigned int size); +int t3_set_proto_sram(struct adapter *adap, u8 *data); int t3_read_flash(struct adapter *adapter, unsigned int addr, unsigned int nwords, u32 *data, int byte_oriented); int t3_load_fw(struct adapter *adapter, const u8 * fw_data, unsigned int size); diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 67b4b219d92..6fd1e524183 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -43,6 +43,7 @@ #include <linux/proc_fs.h> #include <linux/rtnetlink.h> #include <linux/firmware.h> +#include <linux/log2.h> #include <asm/uaccess.h> #include "common.h" @@ -1818,8 +1819,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) return -EBUSY; if (copy_from_user(&m, useraddr, sizeof(m))) return -EFAULT; - if (!m.rx_pg_sz || (m.rx_pg_sz & (m.rx_pg_sz - 1)) || - !m.tx_pg_sz || (m.tx_pg_sz & (m.tx_pg_sz - 1))) + if (!is_power_of_2(m.rx_pg_sz) || + !is_power_of_2(m.tx_pg_sz)) return -EINVAL; /* not power of 2 */ if (!(m.rx_pg_sz & 0x14000)) return -EINVAL; /* not 16KB or 64KB */ @@ -2067,22 +2068,63 @@ static void vlan_rx_register(struct net_device *dev, struct vlan_group *grp) t3_synchronize_rx(adapter, pi); } -static void vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) -{ - /* nothing */ -} - #ifdef CONFIG_NET_POLL_CONTROLLER static void cxgb_netpoll(struct net_device *dev) { struct adapter *adapter = dev->priv; - struct sge_qset *qs = dev2qset(dev); + struct port_info *pi = netdev_priv(dev); + int qidx; + + for (qidx = pi->first_qset; qidx < pi->first_qset + pi->nqsets; qidx++) { + struct sge_qset *qs = &adapter->sge.qs[qidx]; + void *source; + + if (adapter->flags & USING_MSIX) + source = qs; + else + source = adapter; - t3_intr_handler(adapter, qs->rspq.polling) (adapter->pdev->irq, - adapter); + t3_intr_handler(adapter, qs->rspq.polling) (0, source); + } } #endif +#define TPSRAM_NAME "t3%c_protocol_sram-%d.%d.%d.bin" +int update_tpsram(struct adapter *adap) +{ + const struct firmware *tpsram; + char buf[64]; + struct device *dev = &adap->pdev->dev; + int ret; + char rev; + + rev = adap->params.rev == T3_REV_B2 ? 'b' : 'a'; + + snprintf(buf, sizeof(buf), TPSRAM_NAME, rev, + TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO); + + ret = request_firmware(&tpsram, buf, dev); + if (ret < 0) { + dev_err(dev, "could not load TP SRAM: unable to load %s\n", + buf); + return ret; + } + + ret = t3_check_tpsram(adap, tpsram->data, tpsram->size); + if (ret) + goto release_tpsram; + + ret = t3_set_proto_sram(adap, tpsram->data); + if (ret) + dev_err(dev, "loading protocol SRAM failed\n"); + +release_tpsram: + release_firmware(tpsram); + + return ret; +} + + /* * Periodic accumulation of MAC statistics. */ @@ -2409,7 +2451,6 @@ static int __devinit init_one(struct pci_dev *pdev, netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; netdev->vlan_rx_register = vlan_rx_register; - netdev->vlan_rx_kill_vid = vlan_rx_kill_vid; netdev->open = cxgb_open; netdev->stop = cxgb_close; @@ -2433,6 +2474,13 @@ static int __devinit init_one(struct pci_dev *pdev, goto out_free_dev; } + err = t3_check_tpsram_version(adapter); + if (err == -EINVAL) + err = update_tpsram(adapter); + + if (err) + goto out_free_dev; + /* * The card is now ready to go. If any errors occur during device * registration we do not fail the whole card but rather proceed only diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h index e5a553410e2..aa80313c922 100644 --- a/drivers/net/cxgb3/regs.h +++ b/drivers/net/cxgb3/regs.h @@ -1160,6 +1160,8 @@ #define A_TP_MOD_CHANNEL_WEIGHT 0x434 +#define A_TP_MOD_RATE_LIMIT 0x438 + #define A_TP_PIO_ADDR 0x440 #define A_TP_PIO_DATA 0x444 @@ -1214,6 +1216,15 @@ #define G_TXDROPCNTCH0RCVD(x) (((x) >> S_TXDROPCNTCH0RCVD) & \ M_TXDROPCNTCH0RCVD) +#define A_TP_PROXY_FLOW_CNTL 0x4b0 + +#define A_TP_EMBED_OP_FIELD0 0x4e8 +#define A_TP_EMBED_OP_FIELD1 0x4ec +#define A_TP_EMBED_OP_FIELD2 0x4f0 +#define A_TP_EMBED_OP_FIELD3 0x4f4 +#define A_TP_EMBED_OP_FIELD4 0x4f8 +#define A_TP_EMBED_OP_FIELD5 0x4fc + #define A_ULPRX_CTL 0x500 #define S_ROUND_ROBIN 4 @@ -1882,6 +1893,10 @@ #define V_COPYALLFRAMES(x) ((x) << S_COPYALLFRAMES) #define F_COPYALLFRAMES V_COPYALLFRAMES(1U) +#define S_DISBCAST 1 +#define V_DISBCAST(x) ((x) << S_DISBCAST) +#define F_DISBCAST V_DISBCAST(1U) + #define A_XGM_RX_HASH_LOW 0x814 #define A_XGM_RX_HASH_HIGH 0x818 @@ -2128,6 +2143,8 @@ #define F_RESETPLL01 V_RESETPLL01(1U) #define A_XGM_SERDES_STAT0 0x8f0 +#define A_XGM_SERDES_STAT1 0x8f4 +#define A_XGM_SERDES_STAT2 0x8f8 #define S_LOWSIG0 0 #define V_LOWSIG0(x) ((x) << S_LOWSIG0) diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 3666586a483..a2cfd68ac75 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -46,23 +46,16 @@ #define SGE_RX_SM_BUF_SIZE 1536 -/* - * If USE_RX_PAGE is defined, the small freelist populated with (partial) - * pages instead of skbs. Pages are carved up into RX_PAGE_SIZE chunks (must - * be a multiple of the host page size). - */ -#define USE_RX_PAGE -#define RX_PAGE_SIZE 2048 - -/* - * skb freelist packets are copied into a new skb (and the freelist one is - * reused) if their len is <= - */ #define SGE_RX_COPY_THRES 256 +#define SGE_RX_PULL_LEN 128 /* - * Minimum number of freelist entries before we start dropping TUNNEL frames. + * Page chunk size for FL0 buffers if FL0 is to be populated with page chunks. + * It must be a divisor of PAGE_SIZE. If set to 0 FL0 will use sk_buffs + * directly. */ +#define FL0_PG_CHUNK_SIZE 2048 + #define SGE_RX_DROP_THRES 16 /* @@ -100,12 +93,12 @@ struct tx_sw_desc { /* SW state per Tx descriptor */ struct sk_buff *skb; }; -struct rx_sw_desc { /* SW state per Rx descriptor */ +struct rx_sw_desc { /* SW state per Rx descriptor */ union { struct sk_buff *skb; - struct sge_fl_page page; - } t; - DECLARE_PCI_UNMAP_ADDR(dma_addr); + struct fl_pg_chunk pg_chunk; + }; + DECLARE_PCI_UNMAP_ADDR(dma_addr); }; struct rsp_desc { /* response queue descriptor */ @@ -351,27 +344,26 @@ static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q) pci_unmap_single(pdev, pci_unmap_addr(d, dma_addr), q->buf_size, PCI_DMA_FROMDEVICE); - - if (q->buf_size != RX_PAGE_SIZE) { - kfree_skb(d->t.skb); - d->t.skb = NULL; + if (q->use_pages) { + put_page(d->pg_chunk.page); + d->pg_chunk.page = NULL; } else { - if (d->t.page.frag.page) - put_page(d->t.page.frag.page); - d->t.page.frag.page = NULL; + kfree_skb(d->skb); + d->skb = NULL; } if (++cidx == q->size) cidx = 0; } - if (q->page.frag.page) - put_page(q->page.frag.page); - q->page.frag.page = NULL; + if (q->pg_chunk.page) { + __free_page(q->pg_chunk.page); + q->pg_chunk.page = NULL; + } } /** * add_one_rx_buf - add a packet buffer to a free-buffer list - * @va: va of the buffer to add + * @va: buffer start VA * @len: the buffer length * @d: the HW Rx descriptor to write * @sd: the SW Rx descriptor to write @@ -381,7 +373,7 @@ static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q) * Add a buffer of the given length to the supplied HW and SW Rx * descriptors. */ -static inline void add_one_rx_buf(unsigned char *va, unsigned int len, +static inline void add_one_rx_buf(void *va, unsigned int len, struct rx_desc *d, struct rx_sw_desc *sd, unsigned int gen, struct pci_dev *pdev) { @@ -397,6 +389,27 @@ static inline void add_one_rx_buf(unsigned char *va, unsigned int len, d->gen2 = cpu_to_be32(V_FLD_GEN2(gen)); } +static int alloc_pg_chunk(struct sge_fl *q, struct rx_sw_desc *sd, gfp_t gfp) +{ + if (!q->pg_chunk.page) { + q->pg_chunk.page = alloc_page(gfp); + if (unlikely(!q->pg_chunk.page)) + return -ENOMEM; + q->pg_chunk.va = page_address(q->pg_chunk.page); + q->pg_chunk.offset = 0; + } + sd->pg_chunk = q->pg_chunk; + + q->pg_chunk.offset += q->buf_size; + if (q->pg_chunk.offset == PAGE_SIZE) + q->pg_chunk.page = NULL; + else { + q->pg_chunk.va += q->buf_size; + get_page(q->pg_chunk.page); + } + return 0; +} + /** * refill_fl - refill an SGE free-buffer list * @adapter: the adapter @@ -410,49 +423,29 @@ static inline void add_one_rx_buf(unsigned char *va, unsigned int len, */ static void refill_fl(struct adapter *adap, struct sge_fl *q, int n, gfp_t gfp) { + void *buf_start; struct rx_sw_desc *sd = &q->sdesc[q->pidx]; struct rx_desc *d = &q->desc[q->pidx]; - struct sge_fl_page *p = &q->page; while (n--) { - unsigned char *va; - - if (unlikely(q->buf_size != RX_PAGE_SIZE)) { - struct sk_buff *skb = alloc_skb(q->buf_size, gfp); - - if (!skb) { - q->alloc_failed++; + if (q->use_pages) { + if (unlikely(alloc_pg_chunk(q, sd, gfp))) { +nomem: q->alloc_failed++; break; } - va = skb->data; - sd->t.skb = skb; + buf_start = sd->pg_chunk.va; } else { - if (!p->frag.page) { - p->frag.page = alloc_pages(gfp, 0); - if (unlikely(!p->frag.page)) { - q->alloc_failed++; - break; - } else { - p->frag.size = RX_PAGE_SIZE; - p->frag.page_offset = 0; - p->va = page_address(p->frag.page); - } - } + struct sk_buff *skb = alloc_skb(q->buf_size, gfp); - memcpy(&sd->t, p, sizeof(*p)); - va = p->va; + if (!skb) + goto nomem; - p->frag.page_offset += RX_PAGE_SIZE; - BUG_ON(p->frag.page_offset > PAGE_SIZE); - p->va += RX_PAGE_SIZE; - if (p->frag.page_offset == PAGE_SIZE) - p->frag.page = NULL; - else - get_page(p->frag.page); + sd->skb = skb; + buf_start = skb->data; } - add_one_rx_buf(va, q->buf_size, d, sd, q->gen, adap->pdev); - + add_one_rx_buf(buf_start, q->buf_size, d, sd, q->gen, + adap->pdev); d++; sd++; if (++q->pidx == q->size) { @@ -487,7 +480,7 @@ static void recycle_rx_buf(struct adapter *adap, struct sge_fl *q, struct rx_desc *from = &q->desc[idx]; struct rx_desc *to = &q->desc[q->pidx]; - memcpy(&q->sdesc[q->pidx], &q->sdesc[idx], sizeof(struct rx_sw_desc)); + q->sdesc[q->pidx] = q->sdesc[idx]; to->addr_lo = from->addr_lo; /* already big endian */ to->addr_hi = from->addr_hi; /* likewise */ wmb(); @@ -650,6 +643,132 @@ static inline unsigned int flits_to_desc(unsigned int n) } /** + * get_packet - return the next ingress packet buffer from a free list + * @adap: the adapter that received the packet + * @fl: the SGE free list holding the packet + * @len: the packet length including any SGE padding + * @drop_thres: # of remaining buffers before we start dropping packets + * + * Get the next packet from a free list and complete setup of the + * sk_buff. If the packet is small we make a copy and recycle the + * original buffer, otherwise we use the original buffer itself. If a + * positive drop threshold is supplied packets are dropped and their + * buffers recycled if (a) the number of remaining buffers is under the + * threshold and the packet is too big to copy, or (b) the packet should + * be copied but there is no memory for the copy. + */ +static struct sk_buff *get_packet(struct adapter *adap, struct sge_fl *fl, + unsigned int len, unsigned int drop_thres) +{ + struct sk_buff *skb = NULL; + struct rx_sw_desc *sd = &fl->sdesc[fl->cidx]; + + prefetch(sd->skb->data); + fl->credits--; + + if (len <= SGE_RX_COPY_THRES) { + skb = alloc_skb(len, GFP_ATOMIC); + if (likely(skb != NULL)) { + __skb_put(skb, len); + pci_dma_sync_single_for_cpu(adap->pdev, + pci_unmap_addr(sd, dma_addr), len, + PCI_DMA_FROMDEVICE); + memcpy(skb->data, sd->skb->data, len); + pci_dma_sync_single_for_device(adap->pdev, + pci_unmap_addr(sd, dma_addr), len, + PCI_DMA_FROMDEVICE); + } else if (!drop_thres) + goto use_orig_buf; +recycle: + recycle_rx_buf(adap, fl, fl->cidx); + return skb; + } + + if (unlikely(fl->credits < drop_thres)) + goto recycle; + +use_orig_buf: + pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr), + fl->buf_size, PCI_DMA_FROMDEVICE); + skb = sd->skb; + skb_put(skb, len); + __refill_fl(adap, fl); + return skb; +} + +/** + * get_packet_pg - return the next ingress packet buffer from a free list + * @adap: the adapter that received the packet + * @fl: the SGE free list holding the packet + * @len: the packet length including any SGE padding + * @drop_thres: # of remaining buffers before we start dropping packets + * + * Get the next packet from a free list populated with page chunks. + * If the packet is small we make a copy and recycle the original buffer, + * otherwise we attach the original buffer as a page fragment to a fresh + * sk_buff. If a positive drop threshold is supplied packets are dropped + * and their buffers recycled if (a) the number of remaining buffers is + * under the threshold and the packet is too big to copy, or (b) there's + * no system memory. + * + * Note: this function is similar to @get_packet but deals with Rx buffers + * that are page chunks rather than sk_buffs. + */ +static struct sk_buff *get_packet_pg(struct adapter *adap, struct sge_fl *fl, + unsigned int len, unsigned int drop_thres) +{ + struct sk_buff *skb = NULL; + struct rx_sw_desc *sd = &fl->sdesc[fl->cidx]; + + if (len <= SGE_RX_COPY_THRES) { + skb = alloc_skb(len, GFP_ATOMIC); + if (likely(skb != NULL)) { + __skb_put(skb, len); + pci_dma_sync_single_for_cpu(adap->pdev, + pci_unmap_addr(sd, dma_addr), len, + PCI_DMA_FROMDEVICE); + memcpy(skb->data, sd->pg_chunk.va, len); + pci_dma_sync_single_for_device(adap->pdev, + pci_unmap_addr(sd, dma_addr), len, + PCI_DMA_FROMDEVICE); + } else if (!drop_thres) + return NULL; +recycle: + fl->credits--; + recycle_rx_buf(adap, fl, fl->cidx); + return skb; + } + + if (unlikely(fl->credits <= drop_thres)) + goto recycle; + + skb = alloc_skb(SGE_RX_PULL_LEN, GFP_ATOMIC); + if (unlikely(!skb)) { + if (!drop_thres) + return NULL; + goto recycle; + } + + pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr), + fl->buf_size, PCI_DMA_FROMDEVICE); + __skb_put(skb, SGE_RX_PULL_LEN); + memcpy(skb->data, sd->pg_chunk.va, SGE_RX_PULL_LEN); + skb_fill_page_desc(skb, 0, sd->pg_chunk.page, + sd->pg_chunk.offset + SGE_RX_PULL_LEN, + len - SGE_RX_PULL_LEN); + skb->len = len; + skb->data_len = len - SGE_RX_PULL_LEN; + skb->truesize += skb->data_len; + + fl->credits--; + /* + * We do not refill FLs here, we let the caller do it to overlap a + * prefetch. + */ + return skb; +} + +/** * get_imm_packet - return the next ingress packet buffer from a response * @resp: the response descriptor containing the packet data * @@ -1690,8 +1809,8 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq, struct port_info *pi; skb_pull(skb, sizeof(*p) + pad); - skb->dev->last_rx = jiffies; skb->protocol = eth_type_trans(skb, adap->port[p->iff]); + skb->dev->last_rx = jiffies; pi = netdev_priv(skb->dev); if (pi->rx_csum_offload && p->csum_valid && p->csum == 0xffff && !p->fragment) { @@ -1715,85 +1834,6 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq, netif_rx(skb); } -#define SKB_DATA_SIZE 128 - -static void skb_data_init(struct sk_buff *skb, struct sge_fl_page *p, - unsigned int len) -{ - skb->len = len; - if (len <= SKB_DATA_SIZE) { - skb_copy_to_linear_data(skb, p->va, len); - skb->tail += len; - put_page(p->frag.page); - } else { - skb_copy_to_linear_data(skb, p->va, SKB_DATA_SIZE); - skb_shinfo(skb)->frags[0].page = p->frag.page; - skb_shinfo(skb)->frags[0].page_offset = - p->frag.page_offset + SKB_DATA_SIZE; - skb_shinfo(skb)->frags[0].size = len - SKB_DATA_SIZE; - skb_shinfo(skb)->nr_frags = 1; - skb->data_len = len - SKB_DATA_SIZE; - skb->tail += SKB_DATA_SIZE; - skb->truesize += skb->data_len; - } -} - -/** -* get_packet - return the next ingress packet buffer from a free list -* @adap: the adapter that received the packet -* @fl: the SGE free list holding the packet -* @len: the packet length including any SGE padding -* @drop_thres: # of remaining buffers before we start dropping packets -* -* Get the next packet from a free list and complete setup of the -* sk_buff. If the packet is small we make a copy and recycle the -* original buffer, otherwise we use the original buffer itself. If a -* positive drop threshold is supplied packets are dropped and their -* buffers recycled if (a) the number of remaining buffers is under the -* threshold and the packet is too big to copy, or (b) the packet should -* be copied but there is no memory for the copy. -*/ -static struct sk_buff *get_packet(struct adapter *adap, struct sge_fl *fl, - unsigned int len, unsigned int drop_thres) -{ - struct sk_buff *skb = NULL; - struct rx_sw_desc *sd = &fl->sdesc[fl->cidx]; - - prefetch(sd->t.skb->data); - - if (len <= SGE_RX_COPY_THRES) { - skb = alloc_skb(len, GFP_ATOMIC); - if (likely(skb != NULL)) { - struct rx_desc *d = &fl->desc[fl->cidx]; - dma_addr_t mapping = - (dma_addr_t)((u64) be32_to_cpu(d->addr_hi) << 32 | - be32_to_cpu(d->addr_lo)); - - __skb_put(skb, len); - pci_dma_sync_single_for_cpu(adap->pdev, mapping, len, - PCI_DMA_FROMDEVICE); - skb_copy_from_linear_data(sd->t.skb, skb->data, len); - pci_dma_sync_single_for_device(adap->pdev, mapping, len, - PCI_DMA_FROMDEVICE); - } else if (!drop_thres) - goto use_orig_buf; -recycle: - recycle_rx_buf(adap, fl, fl->cidx); - return skb; - } - - if (unlikely(fl->credits < drop_thres)) - goto recycle; - -use_orig_buf: - pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr), - fl->buf_size, PCI_DMA_FROMDEVICE); - skb = sd->t.skb; - skb_put(skb, len); - __refill_fl(adap, fl); - return skb; -} - /** * handle_rsp_cntrl_info - handles control information in a response * @qs: the queue set corresponding to the response @@ -1935,7 +1975,7 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs, } else if (flags & F_RSPD_IMM_DATA_VALID) { skb = get_imm_packet(r); if (unlikely(!skb)) { - no_mem: +no_mem: q->next_holdoff = NOMEM_INTR_DELAY; q->nomem++; /* consume one credit since we tried */ @@ -1945,53 +1985,29 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs, q->imm_data++; ethpad = 0; } else if ((len = ntohl(r->len_cq)) != 0) { - struct sge_fl *fl = - (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0]; + struct sge_fl *fl; - if (fl->buf_size == RX_PAGE_SIZE) { - struct rx_sw_desc *sd = &fl->sdesc[fl->cidx]; - struct sge_fl_page *p = &sd->t.page; - - prefetch(p->va); - prefetch(p->va + L1_CACHE_BYTES); + fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0]; + if (fl->use_pages) { + void *addr = fl->sdesc[fl->cidx].pg_chunk.va; + prefetch(addr); +#if L1_CACHE_BYTES < 128 + prefetch(addr + L1_CACHE_BYTES); +#endif __refill_fl(adap, fl); - pci_unmap_single(adap->pdev, - pci_unmap_addr(sd, dma_addr), - fl->buf_size, - PCI_DMA_FROMDEVICE); - - if (eth) { - if (unlikely(fl->credits < - SGE_RX_DROP_THRES)) - goto eth_recycle; - - skb = alloc_skb(SKB_DATA_SIZE, - GFP_ATOMIC); - if (unlikely(!skb)) { -eth_recycle: - q->rx_drops++; - recycle_rx_buf(adap, fl, - fl->cidx); - goto eth_done; - } - } else { - skb = alloc_skb(SKB_DATA_SIZE, - GFP_ATOMIC); - if (unlikely(!skb)) - goto no_mem; - } - - skb_data_init(skb, p, G_RSPD_LEN(len)); -eth_done: - fl->credits--; - q->eth_pkts++; - } else { - fl->credits--; + skb = get_packet_pg(adap, fl, G_RSPD_LEN(len), + eth ? SGE_RX_DROP_THRES : 0); + } else skb = get_packet(adap, fl, G_RSPD_LEN(len), eth ? SGE_RX_DROP_THRES : 0); - } + if (unlikely(!skb)) { + if (!eth) + goto no_mem; + q->rx_drops++; + } else if (unlikely(r->rss_hdr.opcode == CPL_TRACE_PKT)) + __skb_pull(skb, 2); if (++fl->cidx == fl->size) fl->cidx = 0; @@ -2016,20 +2032,15 @@ eth_done: q->credits = 0; } - if (skb) { - /* Preserve the RSS info in csum & priority */ - skb->csum = rss_hi; - skb->priority = rss_lo; - + if (likely(skb != NULL)) { if (eth) rx_eth(adap, q, skb, ethpad); else { - if (unlikely(r->rss_hdr.opcode == - CPL_TRACE_PKT)) - __skb_pull(skb, ethpad); - - ngathered = rx_offload(&adap->tdev, q, - skb, offload_skbs, + /* Preserve the RSS info in csum & priority */ + skb->csum = rss_hi; + skb->priority = rss_lo; + ngathered = rx_offload(&adap->tdev, q, skb, + offload_skbs, ngathered); } } @@ -2217,7 +2228,6 @@ irqreturn_t t3_sge_intr_msix_napi(int irq, void *cookie) struct sge_rspq *q = &qs->rspq; spin_lock(&q->lock); - BUG_ON(napi_is_scheduled(qs->netdev)); if (handle_responses(adap, q) < 0) q->unhandled_irqs++; @@ -2636,25 +2646,15 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, q->txq[TXQ_ETH].stop_thres = nports * flits_to_desc(sgl_len(MAX_SKB_FRAGS + 1) + 3); - if (!is_offload(adapter)) { -#ifdef USE_RX_PAGE - q->fl[0].buf_size = RX_PAGE_SIZE; +#if FL0_PG_CHUNK_SIZE > 0 + q->fl[0].buf_size = FL0_PG_CHUNK_SIZE; #else - q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + 2 + - sizeof(struct cpl_rx_pkt); + q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + sizeof(struct cpl_rx_data); #endif - q->fl[1].buf_size = MAX_FRAME_SIZE + 2 + - sizeof(struct cpl_rx_pkt); - } else { -#ifdef USE_RX_PAGE - q->fl[0].buf_size = RX_PAGE_SIZE; -#else - q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + - sizeof(struct cpl_rx_data); -#endif - q->fl[1].buf_size = (16 * 1024) - - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); - } + q->fl[0].use_pages = FL0_PG_CHUNK_SIZE > 0; + q->fl[1].buf_size = is_offload(adapter) ? + (16 * 1024) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) : + MAX_FRAME_SIZE + 2 + sizeof(struct cpl_rx_pkt); spin_lock(&adapter->sge.reg_lock); diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index fb485d0a43d..dd3149d94ba 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c @@ -847,6 +847,64 @@ static int t3_write_flash(struct adapter *adapter, unsigned int addr, return 0; } +/** + * t3_check_tpsram_version - read the tp sram version + * @adapter: the adapter + * + * Reads the protocol sram version from serial eeprom. + */ +int t3_check_tpsram_version(struct adapter *adapter) +{ + int ret; + u32 vers; + unsigned int major, minor; + + /* Get version loaded in SRAM */ + t3_write_reg(adapter, A_TP_EMBED_OP_FIELD0, 0); + ret = t3_wait_op_done(adapter, A_TP_EMBED_OP_FIELD0, + 1, 1, 5, 1); + if (ret) + return ret; + + vers = t3_read_reg(adapter, A_TP_EMBED_OP_FIELD1); + + major = G_TP_VERSION_MAJOR(vers); + minor = G_TP_VERSION_MINOR(vers); + + if (major == TP_VERSION_MAJOR && minor == TP_VERSION_MINOR) + return 0; + + return -EINVAL; +} + +/** + * t3_check_tpsram - check if provided protocol SRAM + * is compatible with this driver + * @adapter: the adapter + * @tp_sram: the firmware image to write + * @size: image size + * + * Checks if an adapter's tp sram is compatible with the driver. + * Returns 0 if the versions are compatible, a negative error otherwise. + */ +int t3_check_tpsram(struct adapter *adapter, u8 *tp_sram, unsigned int size) +{ + u32 csum; + unsigned int i; + const u32 *p = (const u32 *)tp_sram; + + /* Verify checksum */ + for (csum = 0, i = 0; i < size / sizeof(csum); i++) + csum += ntohl(p[i]); + if (csum != 0xffffffff) { + CH_ERR(adapter, "corrupted protocol SRAM image, checksum %u\n", + csum); + return -EINVAL; + } + + return 0; +} + enum fw_version_type { FW_VERSION_N3, FW_VERSION_T3 @@ -921,7 +979,7 @@ static int t3_flash_erase_sectors(struct adapter *adapter, int start, int end) /* * t3_load_fw - download firmware * @adapter: the adapter - * @fw_data: the firrware image to write + * @fw_data: the firmware image to write * @size: image size * * Write the supplied firmware image to the card's serial flash. @@ -2362,7 +2420,7 @@ static void tp_config(struct adapter *adap, const struct tp_params *p) F_TCPCHECKSUMOFFLOAD | V_IPTTL(64)); t3_write_reg(adap, A_TP_TCP_OPTIONS, V_MTUDEFAULT(576) | F_MTUENABLE | V_WINDOWSCALEMODE(1) | - V_TIMESTAMPSMODE(1) | V_SACKMODE(1) | V_SACKRX(1)); + V_TIMESTAMPSMODE(0) | V_SACKMODE(1) | V_SACKRX(1)); t3_write_reg(adap, A_TP_DACK_CONFIG, V_AUTOSTATE3(1) | V_AUTOSTATE2(1) | V_AUTOSTATE1(0) | V_BYTETHRESHOLD(16384) | V_MSSTHRESHOLD(2) | @@ -2371,16 +2429,18 @@ static void tp_config(struct adapter *adap, const struct tp_params *p) F_IPV6ENABLE | F_NICMODE); t3_write_reg(adap, A_TP_TX_RESOURCE_LIMIT, 0x18141814); t3_write_reg(adap, A_TP_PARA_REG4, 0x5050105); - t3_set_reg_field(adap, A_TP_PARA_REG6, - adap->params.rev > 0 ? F_ENABLEESND : F_T3A_ENABLEESND, - 0); + t3_set_reg_field(adap, A_TP_PARA_REG6, 0, + adap->params.rev > 0 ? F_ENABLEESND : + F_T3A_ENABLEESND); t3_set_reg_field(adap, A_TP_PC_CONFIG, - F_ENABLEEPCMDAFULL | F_ENABLEOCSPIFULL, - F_TXDEFERENABLE | F_HEARBEATDACK | F_TXCONGESTIONMODE | - F_RXCONGESTIONMODE); + F_ENABLEEPCMDAFULL, + F_ENABLEOCSPIFULL |F_TXDEFERENABLE | F_HEARBEATDACK | + F_TXCONGESTIONMODE | F_RXCONGESTIONMODE); t3_set_reg_field(adap, A_TP_PC_CONFIG2, F_CHDRAFULL, 0); - + t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1080); + t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1000); + if (adap->params.rev > 0) { tp_wr_indirect(adap, A_TP_EGRESS_CONFIG, F_REWRITEFORCETOSIZE); t3_set_reg_field(adap, A_TP_PARA_REG3, F_TXPACEAUTO, @@ -2390,9 +2450,10 @@ static void tp_config(struct adapter *adap, const struct tp_params *p) } else t3_set_reg_field(adap, A_TP_PARA_REG3, 0, F_TXPACEFIXED); - t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0x12121212); - t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0x12121212); - t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0x1212); + t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0); + t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0); + t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0); + t3_write_reg(adap, A_TP_MOD_RATE_LIMIT, 0xf2200000); } /* Desired TP timer resolution in usec */ @@ -2468,6 +2529,7 @@ int t3_tp_set_coalescing_size(struct adapter *adap, unsigned int size, int psh) val |= F_RXCOALESCEENABLE; if (psh) val |= F_RXCOALESCEPSHEN; + size = min(MAX_RX_COALESCING_LEN, size); t3_write_reg(adap, A_TP_PARA_REG2, V_RXCOALESCESIZE(size) | V_MAXRXDATA(MAX_RX_COALESCING_LEN)); } @@ -2496,11 +2558,11 @@ static void __devinit init_mtus(unsigned short mtus[]) * it can accomodate max size TCP/IP headers when SACK and timestamps * are enabled and still have at least 8 bytes of payload. */ - mtus[0] = 88; - mtus[1] = 256; - mtus[2] = 512; - mtus[3] = 576; - mtus[4] = 808; + mtus[1] = 88; + mtus[1] = 88; + mtus[2] = 256; + mtus[3] = 512; + mtus[4] = 576; mtus[5] = 1024; mtus[6] = 1280; mtus[7] = 1492; @@ -2682,6 +2744,34 @@ static void ulp_config(struct adapter *adap, const struct tp_params *p) t3_write_reg(adap, A_ULPRX_TDDP_TAGMASK, 0xffffffff); } +/** + * t3_set_proto_sram - set the contents of the protocol sram + * @adapter: the adapter + * @data: the protocol image + * + * Write the contents of the protocol SRAM. + */ +int t3_set_proto_sram(struct adapter *adap, u8 *data) +{ + int i; + u32 *buf = (u32 *)data; + + for (i = 0; i < PROTO_SRAM_LINES; i++) { + t3_write_reg(adap, A_TP_EMBED_OP_FIELD5, cpu_to_be32(*buf++)); + t3_write_reg(adap, A_TP_EMBED_OP_FIELD4, cpu_to_be32(*buf++)); + t3_write_reg(adap, A_TP_EMBED_OP_FIELD3, cpu_to_be32(*buf++)); + t3_write_reg(adap, A_TP_EMBED_OP_FIELD2, cpu_to_be32(*buf++)); + t3_write_reg(adap, A_TP_EMBED_OP_FIELD1, cpu_to_be32(*buf++)); + + t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, i << 1 | 1 << 31); + if (t3_wait_op_done(adap, A_TP_EMBED_OP_FIELD0, 1, 1, 5, 1)) + return -EIO; + } + t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, 0); + + return 0; +} + void t3_config_trace_filter(struct adapter *adapter, const struct trace_params *tp, int filter_index, int invert, int enable) @@ -2802,7 +2892,7 @@ static void init_hw_for_avail_ports(struct adapter *adap, int nports) t3_set_reg_field(adap, A_ULPTX_CONFIG, F_CFG_RR_ARB, 0); t3_write_reg(adap, A_MPS_CFG, F_TPRXPORTEN | F_TPTXPORT0EN | F_PORT0ACTIVE | F_ENFORCEPKT); - t3_write_reg(adap, A_PM1_TX_CFG, 0xc000c000); + t3_write_reg(adap, A_PM1_TX_CFG, 0xffffffff); } else { t3_set_reg_field(adap, A_ULPRX_CTL, 0, F_ROUND_ROBIN); t3_set_reg_field(adap, A_ULPTX_CONFIG, 0, F_CFG_RR_ARB); @@ -3097,7 +3187,7 @@ int t3_init_hw(struct adapter *adapter, u32 fw_params) else t3_set_reg_field(adapter, A_PCIX_CFG, 0, F_CLIDECEN); - t3_write_reg(adapter, A_PM1_RX_CFG, 0xf000f000); + t3_write_reg(adapter, A_PM1_RX_CFG, 0xffffffff); init_hw_for_avail_ports(adapter, adapter->params.nports); t3_sge_init(adapter, &adapter->params.sge); diff --git a/drivers/net/cxgb3/version.h b/drivers/net/cxgb3/version.h index b112317f033..eb508bf8022 100644 --- a/drivers/net/cxgb3/version.h +++ b/drivers/net/cxgb3/version.h @@ -39,6 +39,6 @@ /* Firmware version */ #define FW_VERSION_MAJOR 4 -#define FW_VERSION_MINOR 0 +#define FW_VERSION_MINOR 3 #define FW_VERSION_MICRO 0 #endif /* __CHELSIO_VERSION_H */ diff --git a/drivers/net/cxgb3/xgmac.c b/drivers/net/cxgb3/xgmac.c index a506792f957..c302b1a30cb 100644 --- a/drivers/net/cxgb3/xgmac.c +++ b/drivers/net/cxgb3/xgmac.c @@ -231,6 +231,28 @@ int t3_mac_set_num_ucast(struct cmac *mac, int n) return 0; } +static void disable_exact_filters(struct cmac *mac) +{ + unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_LOW_1; + + for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) { + u32 v = t3_read_reg(mac->adapter, reg); + t3_write_reg(mac->adapter, reg, v); + } + t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1); /* flush */ +} + +static void enable_exact_filters(struct cmac *mac) +{ + unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_HIGH_1; + + for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) { + u32 v = t3_read_reg(mac->adapter, reg); + t3_write_reg(mac->adapter, reg, v); + } + t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1); /* flush */ +} + /* Calculate the RX hash filter index of an Ethernet address */ static int hash_hw_addr(const u8 * addr) { @@ -281,6 +303,14 @@ int t3_mac_set_rx_mode(struct cmac *mac, struct t3_rx_mode *rm) return 0; } +static int rx_fifo_hwm(int mtu) +{ + int hwm; + + hwm = max(MAC_RXFIFO_SIZE - 3 * mtu, (MAC_RXFIFO_SIZE * 38) / 100); + return min(hwm, MAC_RXFIFO_SIZE - 8192); +} + int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu) { int hwm, lwm; @@ -305,12 +335,41 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu) hwm = min(hwm, MAC_RXFIFO_SIZE - 8192); lwm = min(3 * (int)mtu, MAC_RXFIFO_SIZE / 4); + if (adap->params.rev == T3_REV_B2 && + (t3_read_reg(adap, A_XGM_RX_CTRL + mac->offset) & F_RXEN)) { + disable_exact_filters(mac); + v = t3_read_reg(adap, A_XGM_RX_CFG + mac->offset); + t3_set_reg_field(adap, A_XGM_RX_CFG + mac->offset, + F_ENHASHMCAST | F_COPYALLFRAMES, F_DISBCAST); + + /* drain rx FIFO */ + if (t3_wait_op_done(adap, + A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + + mac->offset, + 1 << 31, 1, 20, 5)) { + t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v); + enable_exact_filters(mac); + return -EIO; + } + t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu); + t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v); + enable_exact_filters(mac); + } else + t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu); + + /* + * Adjust the PAUSE frame watermarks. We always set the LWM, and the + * HWM only if flow-control is enabled. + */ + hwm = rx_fifo_hwm(mtu); + lwm = min(3 * (int)mtu, MAC_RXFIFO_SIZE / 4); v = t3_read_reg(adap, A_XGM_RXFIFO_CFG + mac->offset); v &= ~V_RXFIFOPAUSELWM(M_RXFIFOPAUSELWM); v |= V_RXFIFOPAUSELWM(lwm / 8); if (G_RXFIFOPAUSEHWM(v)) v = (v & ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM)) | V_RXFIFOPAUSEHWM(hwm / 8); + t3_write_reg(adap, A_XGM_RXFIFO_CFG + mac->offset, v); /* Adjust the TX FIFO threshold based on the MTU */ @@ -329,7 +388,6 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu) (hwm - lwm) * 4 / 8); t3_write_reg(adap, A_XGM_TX_PAUSE_QUANTA + mac->offset, MAC_RXFIFO_SIZE * 4 * 8 / 512); - return 0; } @@ -357,6 +415,15 @@ int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc) V_PORTSPEED(M_PORTSPEED), val); } + val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft); + val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM); + if (fc & PAUSE_TX) + val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm( + t3_read_reg(adap, + A_XGM_RX_MAX_PKT_SIZE + + oft)) / 8); + t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val); + t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN, (fc & PAUSE_RX) ? F_TXPAUSEEN : 0); return 0; @@ -436,6 +503,10 @@ int t3b2_mac_watchdog_task(struct cmac *mac) unsigned int rx_xcnt; int status; + status = 0; + tx_xcnt = 1; /* By default tx_xcnt is making progress */ + tx_tcnt = mac->tx_tcnt; /* If tx_mcnt is progressing ignore tx_tcnt */ + rx_xcnt = 1; /* By default rx_xcnt is making progress */ if (tx_mcnt == mac->tx_mcnt) { tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, A_XGM_TX_SPI4_SOP_EOP_CNT + @@ -446,37 +517,44 @@ int t3b2_mac_watchdog_task(struct cmac *mac) tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap, A_TP_PIO_DATA))); } else { - mac->toggle_cnt = 0; - return 0; + goto rxcheck; } } else { mac->toggle_cnt = 0; - return 0; + goto rxcheck; } if (((tx_tcnt != mac->tx_tcnt) && (tx_xcnt == 0) && (mac->tx_xcnt == 0)) || ((mac->tx_mcnt == tx_mcnt) && (tx_xcnt != 0) && (mac->tx_xcnt != 0))) { - if (mac->toggle_cnt > 4) + if (mac->toggle_cnt > 4) { status = 2; - else + goto out; + } else { status = 1; + goto out; + } } else { mac->toggle_cnt = 0; - return 0; + goto rxcheck; } +rxcheck: if (rx_mcnt != mac->rx_mcnt) rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, A_XGM_RX_SPI4_SOP_EOP_CNT + mac->offset))); - else - return 0; + else + goto out; - if (mac->rx_mcnt != s->rx_frames && rx_xcnt == 0 && mac->rx_xcnt == 0) + if (mac->rx_mcnt != s->rx_frames && rx_xcnt == 0 && + mac->rx_xcnt == 0) { status = 2; - + goto out; + } + +out: mac->tx_tcnt = tx_tcnt; mac->tx_xcnt = tx_xcnt; mac->tx_mcnt = s->tx_frames; diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c index 74ec64a1625..04e3710c908 100644 --- a/drivers/net/dl2k.c +++ b/drivers/net/dl2k.c @@ -250,7 +250,6 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) np->an_enable = 1; mii_set_media (dev); } - pci_read_config_byte(pdev, PCI_REVISION_ID, &np->pci_rev_id); err = register_netdev (dev); if (err) @@ -866,9 +865,9 @@ receive_packet (struct net_device *dev) PCI_DMA_FROMDEVICE); /* 16 byte align the IP header */ skb_reserve (skb, 2); - eth_copy_and_sum (skb, + skb_copy_to_linear_data (skb, np->rx_skbuff[entry]->data, - pkt_len, 0); + pkt_len); skb_put (skb, pkt_len); pci_dma_sync_single_for_device(np->pdev, desc->fraginfo & @@ -879,7 +878,7 @@ receive_packet (struct net_device *dev) skb->protocol = eth_type_trans (skb, dev); #if 0 /* Checksum done by hw, but csum value unavailable. */ - if (np->pci_rev_id >= 0x0c && + if (np->pdev->pci_rev_id >= 0x0c && !(frame_status & (TCPError | UDPError | IPError))) { skb->ip_summed = CHECKSUM_UNNECESSARY; } diff --git a/drivers/net/dl2k.h b/drivers/net/dl2k.h index 814c449c359..e443065a452 100644 --- a/drivers/net/dl2k.h +++ b/drivers/net/dl2k.h @@ -668,7 +668,6 @@ struct netdev_private { unsigned int rx_flow:1; /* Rx flow control enable */ unsigned int phy_media:1; /* 1: fiber, 0: copper */ unsigned int link_status:1; /* Current link status */ - unsigned char pci_rev_id; /* PCI revision ID */ struct netdev_desc *last_tx; /* Last Tx descriptor used. */ unsigned long cur_rx, old_rx; /* Producer/consumer ring indices */ unsigned long cur_tx, old_tx; diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index 264fa0e2e07..c3de81bf090 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -104,6 +104,18 @@ #define PRINTK(args...) printk(KERN_DEBUG args) #endif +#ifdef CONFIG_BLACKFIN +#define readsb insb +#define readsw insw +#define readsl insl +#define writesb outsb +#define writesw outsw +#define writesl outsl +#define DM9000_IRQ_FLAGS (IRQF_SHARED | IRQF_TRIGGER_HIGH) +#else +#define DM9000_IRQ_FLAGS IRQF_SHARED +#endif + /* * Transmit timeout, default 5 seconds. */ @@ -431,6 +443,9 @@ dm9000_probe(struct platform_device *pdev) db->io_addr = (void __iomem *)base; db->io_data = (void __iomem *)(base + 4); + /* ensure at least we have a default set of IO routines */ + dm9000_set_io(db, 2); + } else { db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); @@ -614,7 +629,7 @@ dm9000_open(struct net_device *dev) PRINTK2("entering dm9000_open\n"); - if (request_irq(dev->irq, &dm9000_interrupt, IRQF_SHARED, dev->name, dev)) + if (request_irq(dev->irq, &dm9000_interrupt, DM9000_IRQ_FLAGS, dev->name, dev)) return -EAGAIN; /* Initialize DM9000 board */ diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c index 60673bc292c..756a6bcb038 100644 --- a/drivers/net/dummy.c +++ b/drivers/net/dummy.c @@ -34,11 +34,12 @@ #include <linux/etherdevice.h> #include <linux/init.h> #include <linux/moduleparam.h> +#include <linux/rtnetlink.h> +#include <net/rtnetlink.h> static int numdummies = 1; static int dummy_xmit(struct sk_buff *skb, struct net_device *dev); -static struct net_device_stats *dummy_get_stats(struct net_device *dev); static int dummy_set_address(struct net_device *dev, void *p) { @@ -56,13 +57,13 @@ static void set_multicast_list(struct net_device *dev) { } -static void __init dummy_setup(struct net_device *dev) +static void dummy_setup(struct net_device *dev) { /* Initialize the device structure. */ - dev->get_stats = dummy_get_stats; dev->hard_start_xmit = dummy_xmit; dev->set_multicast_list = set_multicast_list; dev->set_mac_address = dummy_set_address; + dev->destructor = free_netdev; /* Fill in device structure with ethernet-generic values. */ ether_setup(dev); @@ -76,77 +77,80 @@ static void __init dummy_setup(struct net_device *dev) static int dummy_xmit(struct sk_buff *skb, struct net_device *dev) { - struct net_device_stats *stats = netdev_priv(dev); - - stats->tx_packets++; - stats->tx_bytes+=skb->len; + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; dev_kfree_skb(skb); return 0; } -static struct net_device_stats *dummy_get_stats(struct net_device *dev) +static int dummy_validate(struct nlattr *tb[], struct nlattr *data[]) { - return netdev_priv(dev); + if (tb[IFLA_ADDRESS]) { + if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) + return -EINVAL; + if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) + return -EADDRNOTAVAIL; + } + return 0; } -static struct net_device **dummies; +static struct rtnl_link_ops dummy_link_ops __read_mostly = { + .kind = "dummy", + .setup = dummy_setup, + .validate = dummy_validate, +}; /* Number of dummy devices to be set up by this module. */ module_param(numdummies, int, 0); MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices"); -static int __init dummy_init_one(int index) +static int __init dummy_init_one(void) { struct net_device *dev_dummy; int err; - dev_dummy = alloc_netdev(sizeof(struct net_device_stats), - "dummy%d", dummy_setup); - + dev_dummy = alloc_netdev(0, "dummy%d", dummy_setup); if (!dev_dummy) return -ENOMEM; - if ((err = register_netdev(dev_dummy))) { - free_netdev(dev_dummy); - dev_dummy = NULL; - } else { - dummies[index] = dev_dummy; - } + err = dev_alloc_name(dev_dummy, dev_dummy->name); + if (err < 0) + goto err; - return err; -} + dev_dummy->rtnl_link_ops = &dummy_link_ops; + err = register_netdevice(dev_dummy); + if (err < 0) + goto err; + return 0; -static void dummy_free_one(int index) -{ - unregister_netdev(dummies[index]); - free_netdev(dummies[index]); +err: + free_netdev(dev_dummy); + return err; } static int __init dummy_init_module(void) { int i, err = 0; - dummies = kmalloc(numdummies * sizeof(void *), GFP_KERNEL); - if (!dummies) - return -ENOMEM; + + rtnl_lock(); + err = __rtnl_link_register(&dummy_link_ops); + for (i = 0; i < numdummies && !err; i++) - err = dummy_init_one(i); - if (err) { - i--; - while (--i >= 0) - dummy_free_one(i); - } + err = dummy_init_one(); + if (err < 0) + __rtnl_link_unregister(&dummy_link_ops); + rtnl_unlock(); + return err; } static void __exit dummy_cleanup_module(void) { - int i; - for (i = 0; i < numdummies; i++) - dummy_free_one(i); - kfree(dummies); + rtnl_link_unregister(&dummy_link_ops); } module_init(dummy_init_module); module_exit(dummy_cleanup_module); MODULE_LICENSE("GPL"); +MODULE_ALIAS_RTNL_LINK("dummy"); diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 61696637a21..6b6401e9304 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -159,7 +159,7 @@ #define DRV_NAME "e100" #define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.17-k4"DRV_EXT +#define DRV_VERSION "3.5.23-k4"DRV_EXT #define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" #define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" #define PFX DRV_NAME ": " @@ -285,6 +285,12 @@ enum scb_status { rus_mask = 0x3C, }; +enum ru_state { + RU_SUSPENDED = 0, + RU_RUNNING = 1, + RU_UNINITIALIZED = -1, +}; + enum scb_stat_ack { stat_ack_not_ours = 0x00, stat_ack_sw_gen = 0x04, @@ -526,6 +532,7 @@ struct nic { struct rx *rx_to_use; struct rx *rx_to_clean; struct rfd blank_rfd; + enum ru_state ru_running; spinlock_t cb_lock ____cacheline_aligned; spinlock_t cmd_lock; @@ -576,7 +583,6 @@ struct nic { u32 rx_tco_frames; u32 rx_over_length_errors; - u8 rev_id; u16 leds; u16 eeprom_wc; u16 eeprom[256]; @@ -930,9 +936,8 @@ static void e100_get_defaults(struct nic *nic) struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; - pci_read_config_byte(nic->pdev, PCI_REVISION_ID, &nic->rev_id); /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ - nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->rev_id; + nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; if(nic->mac == mac_unknown) nic->mac = mac_82557_D100_A; @@ -947,7 +952,7 @@ static void e100_get_defaults(struct nic *nic) ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i)); /* Template for a freshly allocated RFD */ - nic->blank_rfd.command = cpu_to_le16(cb_el & cb_s); + nic->blank_rfd.command = cpu_to_le16(cb_el); nic->blank_rfd.rbd = 0xFFFFFFFF; nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); @@ -1017,10 +1022,16 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) config->mwi_enable = 0x1; /* 1=enable, 0=disable */ config->standard_tcb = 0x0; /* 1=standard, 0=extended */ config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ - if(nic->mac >= mac_82559_D101M) + if (nic->mac >= mac_82559_D101M) { config->tno_intr = 0x1; /* TCO stats enable */ - else + /* Enable TCO in extended config */ + if (nic->mac >= mac_82551_10) { + config->byte_count = 0x20; /* extended bytes */ + config->rx_d102_mode = 0x1; /* GMRC for TCO */ + } + } else { config->standard_stat_counter = 0x0; + } } DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", @@ -1266,7 +1277,7 @@ static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb if (nic->flags & ich) goto noloaducode; - /* Search for ucode match against h/w rev_id */ + /* Search for ucode match against h/w revision */ for (opts = ucode_opts; opts->mac; opts++) { int i; u32 *ucode = opts->ucode; @@ -1742,11 +1753,19 @@ static int e100_alloc_cbs(struct nic *nic) return 0; } -static inline void e100_start_receiver(struct nic *nic) +static inline void e100_start_receiver(struct nic *nic, struct rx *rx) { - /* Start if RFA is non-NULL */ - if(nic->rx_to_clean->skb) - e100_exec_cmd(nic, ruc_start, nic->rx_to_clean->dma_addr); + if(!nic->rxs) return; + if(RU_SUSPENDED != nic->ru_running) return; + + /* handle init time starts */ + if(!rx) rx = nic->rxs; + + /* (Re)start RU if suspended or idle and RFA is non-NULL */ + if(rx->skb) { + e100_exec_cmd(nic, ruc_start, rx->dma_addr); + nic->ru_running = RU_RUNNING; + } } #define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) @@ -1775,7 +1794,7 @@ static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) put_unaligned(cpu_to_le32(rx->dma_addr), (u32 *)&prev_rfd->link); wmb(); - prev_rfd->command &= ~cpu_to_le16(cb_el & cb_s); + prev_rfd->command &= ~cpu_to_le16(cb_el); pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, sizeof(struct rfd), PCI_DMA_TODEVICE); } @@ -1813,6 +1832,10 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, pci_unmap_single(nic->pdev, rx->dma_addr, RFD_BUF_LEN, PCI_DMA_FROMDEVICE); + /* this allows for a fast restart without re-enabling interrupts */ + if(le16_to_cpu(rfd->command) & cb_el) + nic->ru_running = RU_SUSPENDED; + /* Pull off the RFD and put the actual data (minus eth hdr) */ skb_reserve(skb, sizeof(struct rfd)); skb_put(skb, actual_size); @@ -1843,18 +1866,45 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done, unsigned int work_to_do) { struct rx *rx; + int restart_required = 0; + struct rx *rx_to_start = NULL; + + /* are we already rnr? then pay attention!!! this ensures that + * the state machine progression never allows a start with a + * partially cleaned list, avoiding a race between hardware + * and rx_to_clean when in NAPI mode */ + if(RU_SUSPENDED == nic->ru_running) + restart_required = 1; /* Indicate newly arrived packets */ for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { - if(e100_rx_indicate(nic, rx, work_done, work_to_do)) + int err = e100_rx_indicate(nic, rx, work_done, work_to_do); + if(-EAGAIN == err) { + /* hit quota so have more work to do, restart once + * cleanup is complete */ + restart_required = 0; + break; + } else if(-ENODATA == err) break; /* No more to clean */ } + /* save our starting point as the place we'll restart the receiver */ + if(restart_required) + rx_to_start = nic->rx_to_clean; + /* Alloc new skbs to refill list */ for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { if(unlikely(e100_rx_alloc_skb(nic, rx))) break; /* Better luck next time (see watchdog) */ } + + if(restart_required) { + // ack the rnr? + writeb(stat_ack_rnr, &nic->csr->scb.stat_ack); + e100_start_receiver(nic, rx_to_start); + if(work_done) + (*work_done)++; + } } static void e100_rx_clean_list(struct nic *nic) @@ -1862,6 +1912,8 @@ static void e100_rx_clean_list(struct nic *nic) struct rx *rx; unsigned int i, count = nic->params.rfds.count; + nic->ru_running = RU_UNINITIALIZED; + if(nic->rxs) { for(rx = nic->rxs, i = 0; i < count; rx++, i++) { if(rx->skb) { @@ -1883,6 +1935,7 @@ static int e100_rx_alloc_list(struct nic *nic) unsigned int i, count = nic->params.rfds.count; nic->rx_to_use = nic->rx_to_clean = NULL; + nic->ru_running = RU_UNINITIALIZED; if(!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) return -ENOMEM; @@ -1897,6 +1950,7 @@ static int e100_rx_alloc_list(struct nic *nic) } nic->rx_to_use = nic->rx_to_clean = nic->rxs; + nic->ru_running = RU_SUSPENDED; return 0; } @@ -1916,6 +1970,10 @@ static irqreturn_t e100_intr(int irq, void *dev_id) /* Ack interrupt(s) */ iowrite8(stat_ack, &nic->csr->scb.stat_ack); + /* We hit Receive No Resource (RNR); restart RU after cleaning */ + if(stat_ack & stat_ack_rnr) + nic->ru_running = RU_SUSPENDED; + if(likely(netif_rx_schedule_prep(netdev))) { e100_disable_irq(nic); __netif_rx_schedule(netdev); @@ -2007,7 +2065,7 @@ static int e100_up(struct nic *nic) if((err = e100_hw_init(nic))) goto err_clean_cbs; e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic); + e100_start_receiver(nic, NULL); mod_timer(&nic->watchdog, jiffies); if((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, nic->netdev->name, nic->netdev))) @@ -2088,7 +2146,7 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, BMCR_LOOPBACK); - e100_start_receiver(nic); + e100_start_receiver(nic, NULL); if(!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { err = -ENOMEM; @@ -2178,7 +2236,7 @@ static void e100_get_regs(struct net_device *netdev, u32 *buff = p; int i; - regs->version = (1 << 24) | nic->rev_id; + regs->version = (1 << 24) | nic->pdev->revision; buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | ioread8(&nic->csr->scb.cmd_lo) << 16 | ioread16(&nic->csr->scb.status); diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 9ec35b7a820..f48b659e0c2 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1142,13 +1142,16 @@ e1000_probe(struct pci_dev *pdev, !e1000_check_mng_mode(&adapter->hw)) e1000_get_hw_control(adapter); - strcpy(netdev->name, "eth%d"); - if ((err = register_netdev(netdev))) - goto err_register; - /* tell the stack to leave us alone until e1000_open() is called */ netif_carrier_off(netdev); netif_stop_queue(netdev); +#ifdef CONFIG_E1000_NAPI + netif_poll_disable(netdev); +#endif + + strcpy(netdev->name, "eth%d"); + if ((err = register_netdev(netdev))) + goto err_register; DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n"); @@ -1263,8 +1266,7 @@ e1000_sw_init(struct e1000_adapter *adapter) hw->device_id = pdev->device; hw->subsystem_vendor_id = pdev->subsystem_vendor; hw->subsystem_id = pdev->subsystem_device; - - pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); + hw->revision_id = pdev->revision; pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word); diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 9800341956a..9afa47edfc5 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -1801,7 +1801,7 @@ speedo_rx(struct net_device *dev) #if 1 || USE_IP_CSUM /* Packet is in one chunk -- we can copy + cksum. */ - eth_copy_and_sum(skb, sp->rx_skbuff[entry]->data, pkt_len, 0); + skb_copy_to_linear_data(skb, sp->rx_skbuff[entry]->data, pkt_len); skb_put(skb, pkt_len); #else skb_copy_from_linear_data(sp->rx_skbuff[entry], diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index e85a933a476..f03f070451d 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -39,7 +39,13 @@ #include <asm/io.h> #define DRV_NAME "ehea" -#define DRV_VERSION "EHEA_0061" +#define DRV_VERSION "EHEA_0067" + +/* EHEA capability flags */ +#define DLPAR_PORT_ADD_REM 1 +#define DLPAR_MEM_ADD 2 +#define DLPAR_MEM_REM 4 +#define EHEA_CAPABILITIES (DLPAR_PORT_ADD_REM) #define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \ | NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR) @@ -136,10 +142,10 @@ void ehea_dump(void *adr, int len, char *msg); (0xffffffffffffffffULL >> ((64 - (mask)) & 0xffff)) #define EHEA_BMASK_SET(mask, value) \ - ((EHEA_BMASK_MASK(mask) & ((u64)(value))) << EHEA_BMASK_SHIFTPOS(mask)) + ((EHEA_BMASK_MASK(mask) & ((u64)(value))) << EHEA_BMASK_SHIFTPOS(mask)) #define EHEA_BMASK_GET(mask, value) \ - (EHEA_BMASK_MASK(mask) & (((u64)(value)) >> EHEA_BMASK_SHIFTPOS(mask))) + (EHEA_BMASK_MASK(mask) & (((u64)(value)) >> EHEA_BMASK_SHIFTPOS(mask))) /* * Generic ehea page @@ -190,7 +196,7 @@ struct ehea_av; * Queue attributes passed to ehea_create_qp() */ struct ehea_qp_init_attr { - /* input parameter */ + /* input parameter */ u32 qp_token; /* queue token */ u8 low_lat_rq1; u8 signalingtype; /* cqe generation flag */ @@ -212,7 +218,7 @@ struct ehea_qp_init_attr { u64 recv_cq_handle; u64 aff_eq_handle; - /* output parameter */ + /* output parameter */ u32 qp_nr; u16 act_nr_send_wqes; u16 act_nr_rwqes_rq1; @@ -279,12 +285,12 @@ struct ehea_qp { * Completion Queue attributes */ struct ehea_cq_attr { - /* input parameter */ + /* input parameter */ u32 max_nr_of_cqes; u32 cq_token; u64 eq_handle; - /* output parameter */ + /* output parameter */ u32 act_nr_of_cqes; u32 nr_pages; }; diff --git a/drivers/net/ehea/ehea_hw.h b/drivers/net/ehea/ehea_hw.h index 1246757f2c2..1af7ca499ec 100644 --- a/drivers/net/ehea/ehea_hw.h +++ b/drivers/net/ehea/ehea_hw.h @@ -211,34 +211,34 @@ static inline void epa_store_acc(struct h_epa epa, u32 offset, u64 value) } #define epa_store_eq(epa, offset, value)\ - epa_store(epa, EQTEMM_OFFSET(offset), value) + epa_store(epa, EQTEMM_OFFSET(offset), value) #define epa_load_eq(epa, offset)\ - epa_load(epa, EQTEMM_OFFSET(offset)) + epa_load(epa, EQTEMM_OFFSET(offset)) #define epa_store_cq(epa, offset, value)\ - epa_store(epa, CQTEMM_OFFSET(offset), value) + epa_store(epa, CQTEMM_OFFSET(offset), value) #define epa_load_cq(epa, offset)\ - epa_load(epa, CQTEMM_OFFSET(offset)) + epa_load(epa, CQTEMM_OFFSET(offset)) #define epa_store_qp(epa, offset, value)\ - epa_store(epa, QPTEMM_OFFSET(offset), value) + epa_store(epa, QPTEMM_OFFSET(offset), value) #define epa_load_qp(epa, offset)\ - epa_load(epa, QPTEMM_OFFSET(offset)) + epa_load(epa, QPTEMM_OFFSET(offset)) #define epa_store_qped(epa, offset, value)\ - epa_store(epa, QPEDMM_OFFSET(offset), value) + epa_store(epa, QPEDMM_OFFSET(offset), value) #define epa_load_qped(epa, offset)\ - epa_load(epa, QPEDMM_OFFSET(offset)) + epa_load(epa, QPEDMM_OFFSET(offset)) #define epa_store_mrmw(epa, offset, value)\ - epa_store(epa, MRMWMM_OFFSET(offset), value) + epa_store(epa, MRMWMM_OFFSET(offset), value) #define epa_load_mrmw(epa, offset)\ - epa_load(epa, MRMWMM_OFFSET(offset)) + epa_load(epa, MRMWMM_OFFSET(offset)) #define epa_store_base(epa, offset, value)\ - epa_store(epa, HCAGR_OFFSET(offset), value) + epa_store(epa, HCAGR_OFFSET(offset), value) #define epa_load_base(epa, offset)\ - epa_load(epa, HCAGR_OFFSET(offset)) + epa_load(epa, HCAGR_OFFSET(offset)) static inline void ehea_update_sqa(struct ehea_qp *qp, u16 nr_wqes) { diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 152bb2016a2..383144db4d1 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -81,7 +81,7 @@ MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 1 "); static int port_name_cnt = 0; static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev, - const struct of_device_id *id); + const struct of_device_id *id); static int __devexit ehea_remove(struct ibmebus_dev *dev); @@ -236,7 +236,7 @@ static int ehea_refill_rq_def(struct ehea_port_res *pr, rwqe = ehea_get_next_rwqe(qp, rq_nr); rwqe->wr_id = EHEA_BMASK_SET(EHEA_WR_ID_TYPE, wqe_type) - | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index); + | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index); rwqe->sg_list[0].l_key = pr->recv_mr.lkey; rwqe->sg_list[0].vaddr = (u64)skb->data; rwqe->sg_list[0].len = packet_size; @@ -427,7 +427,7 @@ static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev, break; } skb_copy_to_linear_data(skb, ((char*)cqe) + 64, - cqe->num_bytes_transfered - 4); + cqe->num_bytes_transfered - 4); ehea_fill_skb(port->netdev, skb, cqe); } else if (rq == 2) { /* RQ2 */ skb = get_skb_by_index(skb_arr_rq2, @@ -451,7 +451,8 @@ static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev, processed_rq3++; } - if (cqe->status & EHEA_CQE_VLAN_TAG_XTRACT) + if ((cqe->status & EHEA_CQE_VLAN_TAG_XTRACT) + && port->vgrp) vlan_hwaccel_receive_skb(skb, port->vgrp, cqe->vlan_tag); else @@ -617,7 +618,7 @@ static struct ehea_port *ehea_get_port(struct ehea_adapter *adapter, for (i = 0; i < EHEA_MAX_PORTS; i++) if (adapter->port[i]) - if (adapter->port[i]->logical_port_id == logical_port) + if (adapter->port[i]->logical_port_id == logical_port) return adapter->port[i]; return NULL; } @@ -1694,6 +1695,7 @@ static void ehea_xmit2(struct sk_buff *skb, struct net_device *dev, { if (skb->protocol == htons(ETH_P_IP)) { const struct iphdr *iph = ip_hdr(skb); + /* IPv4 */ swqe->tx_control |= EHEA_SWQE_CRC | EHEA_SWQE_IP_CHECKSUM @@ -1704,13 +1706,12 @@ static void ehea_xmit2(struct sk_buff *skb, struct net_device *dev, write_ip_start_end(swqe, skb); if (iph->protocol == IPPROTO_UDP) { - if ((iph->frag_off & IP_MF) || - (iph->frag_off & IP_OFFSET)) + if ((iph->frag_off & IP_MF) + || (iph->frag_off & IP_OFFSET)) /* IP fragment, so don't change cs */ swqe->tx_control &= ~EHEA_SWQE_TCP_CHECKSUM; else write_udp_offset_end(swqe, skb); - } else if (iph->protocol == IPPROTO_TCP) { write_tcp_offset_end(swqe, skb); } @@ -1738,6 +1739,7 @@ static void ehea_xmit3(struct sk_buff *skb, struct net_device *dev, if (skb->protocol == htons(ETH_P_IP)) { const struct iphdr *iph = ip_hdr(skb); + /* IPv4 */ write_ip_start_end(swqe, skb); @@ -1750,8 +1752,8 @@ static void ehea_xmit3(struct sk_buff *skb, struct net_device *dev, write_tcp_offset_end(swqe, skb); } else if (iph->protocol == IPPROTO_UDP) { - if ((iph->frag_off & IP_MF) || - (iph->frag_off & IP_OFFSET)) + if ((iph->frag_off & IP_MF) + || (iph->frag_off & IP_OFFSET)) /* IP fragment, so don't change cs */ swqe->tx_control |= EHEA_SWQE_CRC | EHEA_SWQE_IMM_DATA_PRESENT; @@ -1910,10 +1912,7 @@ static void ehea_vlan_rx_register(struct net_device *dev, goto out; } - if (grp) - memset(cb1->vlan_filter, 0, sizeof(cb1->vlan_filter)); - else - memset(cb1->vlan_filter, 0xFF, sizeof(cb1->vlan_filter)); + memset(cb1->vlan_filter, 0, sizeof(cb1->vlan_filter)); hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id, H_PORT_CB1, H_PORT_CB1_ALL, cb1); @@ -1947,7 +1946,7 @@ static void ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) } index = (vid / 64); - cb1->vlan_filter[index] |= ((u64)(1 << (vid & 0x3F))); + cb1->vlan_filter[index] |= ((u64)(0x8000000000000000 >> (vid & 0x3F))); hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id, H_PORT_CB1, H_PORT_CB1_ALL, cb1); @@ -1982,7 +1981,7 @@ static void ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) } index = (vid / 64); - cb1->vlan_filter[index] &= ~((u64)(1 << (vid & 0x3F))); + cb1->vlan_filter[index] &= ~((u64)(0x8000000000000000 >> (vid & 0x3F))); hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id, H_PORT_CB1, H_PORT_CB1_ALL, cb1); @@ -2409,7 +2408,7 @@ static void __devinit logical_port_release(struct device *dev) } static int ehea_driver_sysfs_add(struct device *dev, - struct device_driver *driver) + struct device_driver *driver) { int ret; @@ -2426,7 +2425,7 @@ static int ehea_driver_sysfs_add(struct device *dev, } static void ehea_driver_sysfs_remove(struct device *dev, - struct device_driver *driver) + struct device_driver *driver) { struct device_driver *drv = driver; @@ -2455,7 +2454,7 @@ static struct device *ehea_register_port(struct ehea_port *port, } ret = device_create_file(&port->ofdev.dev, &dev_attr_log_port_id); - if (ret) { + if (ret) { ehea_error("failed to register attributes, ret=%d", ret); goto out_unreg_of_dev; } @@ -2603,6 +2602,7 @@ static int ehea_setup_ports(struct ehea_adapter *adapter) { struct device_node *lhea_dn; struct device_node *eth_dn = NULL; + const u32 *dn_log_port_id; int i = 0; @@ -2610,7 +2610,7 @@ static int ehea_setup_ports(struct ehea_adapter *adapter) while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) { dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no", - NULL); + NULL); if (!dn_log_port_id) { ehea_error("bad device node: eth_dn name=%s", eth_dn->full_name); @@ -2650,7 +2650,7 @@ static struct device_node *ehea_get_eth_dn(struct ehea_adapter *adapter, while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) { dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no", - NULL); + NULL); if (dn_log_port_id) if (*dn_log_port_id == logical_port_id) return eth_dn; @@ -2791,7 +2791,7 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev, adapter->ebus_dev = dev; adapter_handle = of_get_property(dev->ofdev.node, "ibm,hea-handle", - NULL); + NULL); if (adapter_handle) adapter->handle = *adapter_handle; @@ -2923,6 +2923,15 @@ static int check_module_parm(void) return ret; } +static ssize_t ehea_show_capabilities(struct device_driver *drv, + char *buf) +{ + return sprintf(buf, "%d", EHEA_CAPABILITIES); +} + +static DRIVER_ATTR(capabilities, S_IRUSR | S_IRGRP | S_IROTH, + ehea_show_capabilities, NULL); + int __init ehea_module_init(void) { int ret; @@ -2934,8 +2943,19 @@ int __init ehea_module_init(void) if (ret) goto out; ret = ibmebus_register_driver(&ehea_driver); - if (ret) + if (ret) { ehea_error("failed registering eHEA device driver on ebus"); + goto out; + } + + ret = driver_create_file(&ehea_driver.driver, + &driver_attr_capabilities); + if (ret) { + ehea_error("failed to register capabilities attribute, ret=%d", + ret); + ibmebus_unregister_driver(&ehea_driver); + goto out; + } out: return ret; @@ -2943,6 +2963,7 @@ out: static void __exit ehea_module_exit(void) { + driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities); ibmebus_unregister_driver(&ehea_driver); } diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c index f24a8862977..29eaa46948b 100644 --- a/drivers/net/ehea/ehea_qmr.c +++ b/drivers/net/ehea/ehea_qmr.c @@ -211,7 +211,7 @@ u64 ehea_destroy_cq_res(struct ehea_cq *cq, u64 force) u64 hret; u64 adapter_handle = cq->adapter->handle; - /* deregister all previous registered pages */ + /* deregister all previous registered pages */ hret = ehea_h_free_resource(adapter_handle, cq->fw_handle, force); if (hret != H_SUCCESS) return hret; @@ -362,7 +362,7 @@ int ehea_destroy_eq(struct ehea_eq *eq) if (hret != H_SUCCESS) { ehea_error("destroy EQ failed"); return -EIO; - } + } return 0; } @@ -507,44 +507,44 @@ out_freemem: u64 ehea_destroy_qp_res(struct ehea_qp *qp, u64 force) { - u64 hret; - struct ehea_qp_init_attr *qp_attr = &qp->init_attr; + u64 hret; + struct ehea_qp_init_attr *qp_attr = &qp->init_attr; - ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle); - hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle, force); - if (hret != H_SUCCESS) - return hret; + ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle); + hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle, force); + if (hret != H_SUCCESS) + return hret; - hw_queue_dtor(&qp->hw_squeue); - hw_queue_dtor(&qp->hw_rqueue1); + hw_queue_dtor(&qp->hw_squeue); + hw_queue_dtor(&qp->hw_rqueue1); - if (qp_attr->rq_count > 1) - hw_queue_dtor(&qp->hw_rqueue2); - if (qp_attr->rq_count > 2) - hw_queue_dtor(&qp->hw_rqueue3); - kfree(qp); + if (qp_attr->rq_count > 1) + hw_queue_dtor(&qp->hw_rqueue2); + if (qp_attr->rq_count > 2) + hw_queue_dtor(&qp->hw_rqueue3); + kfree(qp); - return hret; + return hret; } int ehea_destroy_qp(struct ehea_qp *qp) { - u64 hret; - if (!qp) - return 0; + u64 hret; + if (!qp) + return 0; - if ((hret = ehea_destroy_qp_res(qp, NORMAL_FREE)) == H_R_STATE) { - ehea_error_data(qp->adapter, qp->fw_handle); - hret = ehea_destroy_qp_res(qp, FORCE_FREE); - } + if ((hret = ehea_destroy_qp_res(qp, NORMAL_FREE)) == H_R_STATE) { + ehea_error_data(qp->adapter, qp->fw_handle); + hret = ehea_destroy_qp_res(qp, FORCE_FREE); + } - if (hret != H_SUCCESS) { - ehea_error("destroy QP failed"); - return -EIO; - } + if (hret != H_SUCCESS) { + ehea_error("destroy QP failed"); + return -EIO; + } - return 0; + return 0; } int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr) diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index 5e517946f46..119778401e4 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -1201,7 +1201,7 @@ static int epic_rx(struct net_device *dev, int budget) ep->rx_ring[entry].bufaddr, ep->rx_buf_sz, PCI_DMA_FROMDEVICE); - eth_copy_and_sum(skb, ep->rx_skbuff[entry]->data, pkt_len, 0); + skb_copy_to_linear_data(skb, ep->rx_skbuff[entry]->data, pkt_len); skb_put(skb, pkt_len); pci_dma_sync_single_for_device(ep->pci_dev, ep->rx_ring[entry].bufaddr, diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c index abe9b089c61..ff9f177d715 100644 --- a/drivers/net/fealnx.c +++ b/drivers/net/fealnx.c @@ -1727,8 +1727,8 @@ static int netdev_rx(struct net_device *dev) /* Call copy + cksum if available. */ #if ! defined(__alpha__) - eth_copy_and_sum(skb, - np->cur_rx->skbuff->data, pkt_len, 0); + skb_copy_to_linear_data(skb, + np->cur_rx->skbuff->data, pkt_len); skb_put(skb, pkt_len); #else memcpy(skb_put(skb, pkt_len), diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 255b09124e1..03023dd1782 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -648,7 +648,7 @@ while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) { fep->stats.rx_dropped++; } else { skb_put(skb,pkt_len-4); /* Make room */ - eth_copy_and_sum(skb, data, pkt_len-4, 0); + skb_copy_to_linear_data(skb, data, pkt_len-4); skb->protocol=eth_type_trans(skb,dev); netif_rx(skb); } diff --git a/drivers/net/fec_8xx/Kconfig b/drivers/net/fec_8xx/Kconfig index a84c232395e..afb34ded26e 100644 --- a/drivers/net/fec_8xx/Kconfig +++ b/drivers/net/fec_8xx/Kconfig @@ -1,6 +1,6 @@ config FEC_8XX tristate "Motorola 8xx FEC driver" - depends on NET_ETHERNET && 8xx + depends on 8XX select MII config FEC_8XX_GENERIC_PHY diff --git a/drivers/net/fec_8xx/fec_main.c b/drivers/net/fec_8xx/fec_main.c index 88efe9731ba..e5502af5b8e 100644 --- a/drivers/net/fec_8xx/fec_main.c +++ b/drivers/net/fec_8xx/fec_main.c @@ -550,7 +550,7 @@ static int fec_enet_rx_common(struct net_device *dev, int *budget) skbn = dev_alloc_skb(pkt_len + 2); if (skbn != NULL) { skb_reserve(skbn, 2); /* align IP header */ - skb_copy_from_linear_data(skb + skb_copy_from_linear_data(skb, skbn->data, pkt_len); /* swap */ diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 4154fd00074..67046e8c21e 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -4605,12 +4605,7 @@ static void nv_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) writel(np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl); spin_unlock_irq(&np->lock); -}; - -static void nv_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) -{ - /* nothing to do */ -}; +} /* The mgmt unit and driver use a semaphore to access the phy during init */ static int nv_mgmt_acquire_sema(struct net_device *dev) @@ -4830,8 +4825,10 @@ static int nv_close(struct net_device *dev) drain_ring(dev); - if (np->wolenabled) + if (np->wolenabled) { + writel(NVREG_PFF_ALWAYS|NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags); nv_start_rx(dev); + } /* FIXME: power down nic */ @@ -4956,7 +4953,6 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i np->vlanctl_bits = NVREG_VLANCONTROL_ENABLE; dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX; dev->vlan_rx_register = nv_vlan_rx_register; - dev->vlan_rx_kill_vid = nv_vlan_rx_kill_vid; } np->msi_flags = 0; @@ -5088,15 +5084,13 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i np->wolenabled = 0; if (id->driver_data & DEV_HAS_POWER_CNTRL) { - u8 revision_id; - pci_read_config_byte(pci_dev, PCI_REVISION_ID, &revision_id); /* take phy and nic out of low power mode */ powerstate = readl(base + NvRegPowerState2); powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK; if ((id->device == PCI_DEVICE_ID_NVIDIA_NVENET_12 || id->device == PCI_DEVICE_ID_NVIDIA_NVENET_13) && - revision_id >= 0xA3) + pci_dev->revision >= 0xA3) powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3; writel(powerstate, base + NvRegPowerState2); } diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig index 6aaee67dd4b..e27ee210b60 100644 --- a/drivers/net/fs_enet/Kconfig +++ b/drivers/net/fs_enet/Kconfig @@ -1,6 +1,6 @@ config FS_ENET tristate "Freescale Ethernet Driver" - depends on NET_ETHERNET && (CPM1 || CPM2) + depends on CPM1 || CPM2 select MII config FS_ENET_HAS_SCC diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index f5b3cba23fc..d7a1a58de76 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -130,6 +130,9 @@ static int gfar_remove(struct platform_device *pdev); static void free_skb_resources(struct gfar_private *priv); static void gfar_set_multi(struct net_device *dev); static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr); +static void gfar_configure_serdes(struct net_device *dev); +extern int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id, int regnum, u16 value); +extern int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum); #ifdef CONFIG_GFAR_NAPI static int gfar_poll(struct net_device *dev, int *budget); #endif @@ -140,7 +143,6 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit); static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length); static void gfar_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp); -static void gfar_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid); void gfar_halt(struct net_device *dev); void gfar_start(struct net_device *dev); static void gfar_clear_exact_match(struct net_device *dev); @@ -284,7 +286,6 @@ static int gfar_probe(struct platform_device *pdev) if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) { dev->vlan_rx_register = gfar_vlan_rx_register; - dev->vlan_rx_kill_vid = gfar_vlan_rx_kill_vid; dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; @@ -453,6 +454,9 @@ static int init_phy(struct net_device *dev) phydev = phy_connect(dev, phy_id, &adjust_link, 0, interface); + if (interface == PHY_INTERFACE_MODE_SGMII) + gfar_configure_serdes(dev); + if (IS_ERR(phydev)) { printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); return PTR_ERR(phydev); @@ -467,6 +471,27 @@ static int init_phy(struct net_device *dev) return 0; } +static void gfar_configure_serdes(struct net_device *dev) +{ + struct gfar_private *priv = netdev_priv(dev); + struct gfar_mii __iomem *regs = + (void __iomem *)&priv->regs->gfar_mii_regs; + + /* Initialise TBI i/f to communicate with serdes (lynx phy) */ + + /* Single clk mode, mii mode off(for aerdes communication) */ + gfar_local_mdio_write(regs, TBIPA_VALUE, MII_TBICON, TBICON_CLK_SELECT); + + /* Supported pause and full-duplex, no half-duplex */ + gfar_local_mdio_write(regs, TBIPA_VALUE, MII_ADVERTISE, + ADVERTISE_1000XFULL | ADVERTISE_1000XPAUSE | + ADVERTISE_1000XPSE_ASYM); + + /* ANEG enable, restart ANEG, full duplex mode, speed[1] set */ + gfar_local_mdio_write(regs, TBIPA_VALUE, MII_BMCR, BMCR_ANENABLE | + BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000); +} + static void init_registers(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); @@ -946,7 +971,7 @@ static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb) flags |= TXFCB_UDP; fcb->phcs = udp_hdr(skb)->check; } else - fcb->phcs = udp_hdr(skb)->check; + fcb->phcs = tcp_hdr(skb)->check; /* l3os is the distance between the start of the * frame (skb->data) and the start of the IP hdr. @@ -1133,20 +1158,6 @@ static void gfar_vlan_rx_register(struct net_device *dev, spin_unlock_irqrestore(&priv->rxlock, flags); } - -static void gfar_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) -{ - struct gfar_private *priv = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&priv->rxlock, flags); - - vlan_group_set_device(priv->vlgrp, vid, NULL); - - spin_unlock_irqrestore(&priv->rxlock, flags); -} - - static int gfar_change_mtu(struct net_device *dev, int new_mtu) { int tempsize, tempval; diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 39e9e321fcb..d8e779c102f 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -136,6 +136,12 @@ extern const char gfar_driver_version[]; #define MIIMCFG_RESET 0x80000000 #define MIIMIND_BUSY 0x00000001 +/* TBI register addresses */ +#define MII_TBICON 0x11 + +/* TBICON register bit fields */ +#define TBICON_CLK_SELECT 0x0020 + /* MAC register bits */ #define MACCFG1_SOFT_RESET 0x80000000 #define MACCFG1_RESET_RX_MC 0x00080000 diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c index bcc6b82f4a3..5dd34a1a7b8 100644 --- a/drivers/net/gianfar_mii.c +++ b/drivers/net/gianfar_mii.c @@ -43,13 +43,18 @@ #include "gianfar.h" #include "gianfar_mii.h" -/* Write value to the PHY at mii_id at register regnum, - * on the bus, waiting until the write is done before returning. - * All PHY configuration is done through the TSEC1 MIIM regs */ -int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) +/* + * Write value to the PHY at mii_id at register regnum, + * on the bus attached to the local interface, which may be different from the + * generic mdio bus (tied to a single interface), waiting until the write is + * done before returning. This is helpful in programming interfaces like + * the TBI which control interfaces like onchip SERDES and are always tied to + * the local mdio pins, which may not be the same as system mdio bus, used for + * controlling the external PHYs, for example. + */ +int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id, + int regnum, u16 value) { - struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; - /* Set the PHY address and the register address we want to write */ gfar_write(®s->miimadd, (mii_id << 8) | regnum); @@ -63,12 +68,19 @@ int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) return 0; } -/* Read the bus for PHY at addr mii_id, register regnum, and - * return the value. Clears miimcom first. All PHY - * configuration has to be done through the TSEC1 MIIM regs */ -int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum) +/* + * Read the bus for PHY at addr mii_id, register regnum, and + * return the value. Clears miimcom first. All PHY operation + * done on the bus attached to the local interface, + * which may be different from the generic mdio bus + * This is helpful in programming interfaces like + * the TBI which, inturn, control interfaces like onchip SERDES + * and are always tied to the local mdio pins, which may not be the + * same as system mdio bus, used for controlling the external PHYs, for eg. + */ +int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum) + { - struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; u16 value; /* Set the PHY address and the register address we want to read */ @@ -88,6 +100,27 @@ int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum) return value; } +/* Write value to the PHY at mii_id at register regnum, + * on the bus, waiting until the write is done before returning. + * All PHY configuration is done through the TSEC1 MIIM regs */ +int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) +{ + struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; + + /* Write to the local MII regs */ + return(gfar_local_mdio_write(regs, mii_id, regnum, value)); +} + +/* Read the bus for PHY at addr mii_id, register regnum, and + * return the value. Clears miimcom first. All PHY + * configuration has to be done through the TSEC1 MIIM regs */ +int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum) +{ + struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; + + /* Read the local MII regs */ + return(gfar_local_mdio_read(regs, mii_id, regnum)); +} /* Reset the MIIM registers, and wait for the bus to free */ int gfar_mdio_reset(struct mii_bus *bus) diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index 2521b111b3a..15254dc7876 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -1575,8 +1575,8 @@ static int hamachi_rx(struct net_device *dev) PCI_DMA_FROMDEVICE); /* Call copy + cksum if available. */ #if 1 || USE_IP_COPYSUM - eth_copy_and_sum(skb, - hmp->rx_skbuff[entry]->data, pkt_len, 0); + skb_copy_to_linear_data(skb, + hmp->rx_skbuff[entry]->data, pkt_len); skb_put(skb, pkt_len); #else memcpy(skb_put(skb, pkt_len), hmp->rx_ring_dma diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index 8118a6750b6..8caa591c564 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -3005,7 +3005,7 @@ static int __init hp100_isa_init(void) return cards > 0 ? 0 : -ENODEV; } -static void __exit hp100_isa_cleanup(void) +static void hp100_isa_cleanup(void) { int i; diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 3bec0f733f0..d96eb722954 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -915,17 +915,36 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu) { struct ibmveth_adapter *adapter = dev->priv; int new_mtu_oh = new_mtu + IBMVETH_BUFF_OH; - int i; + int reinit = 0; + int i, rc; if (new_mtu < IBMVETH_MAX_MTU) return -EINVAL; + for (i = 0; i < IbmVethNumBufferPools; i++) + if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size) + break; + + if (i == IbmVethNumBufferPools) + return -EINVAL; + /* Look for an active buffer pool that can hold the new MTU */ for(i = 0; i<IbmVethNumBufferPools; i++) { - if (!adapter->rx_buff_pool[i].active) - continue; + if (!adapter->rx_buff_pool[i].active) { + adapter->rx_buff_pool[i].active = 1; + reinit = 1; + } + if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size) { - dev->mtu = new_mtu; + if (reinit && netif_running(adapter->netdev)) { + adapter->pool_config = 1; + ibmveth_close(adapter->netdev); + adapter->pool_config = 0; + dev->mtu = new_mtu; + if ((rc = ibmveth_open(adapter->netdev))) + return rc; + } else + dev->mtu = new_mtu; return 0; } } @@ -1243,16 +1262,19 @@ const char * buf, size_t count) if (attr == &veth_active_attr) { if (value && !pool->active) { - if(ibmveth_alloc_buffer_pool(pool)) { - ibmveth_error_printk("unable to alloc pool\n"); - return -ENOMEM; - } - pool->active = 1; - adapter->pool_config = 1; - ibmveth_close(netdev); - adapter->pool_config = 0; - if ((rc = ibmveth_open(netdev))) - return rc; + if (netif_running(netdev)) { + if(ibmveth_alloc_buffer_pool(pool)) { + ibmveth_error_printk("unable to alloc pool\n"); + return -ENOMEM; + } + pool->active = 1; + adapter->pool_config = 1; + ibmveth_close(netdev); + adapter->pool_config = 0; + if ((rc = ibmveth_open(netdev))) + return rc; + } else + pool->active = 1; } else if (!value && pool->active) { int mtu = netdev->mtu + IBMVETH_BUFF_OH; int i; @@ -1281,23 +1303,29 @@ const char * buf, size_t count) if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT) return -EINVAL; else { - adapter->pool_config = 1; - ibmveth_close(netdev); - adapter->pool_config = 0; - pool->size = value; - if ((rc = ibmveth_open(netdev))) - return rc; + if (netif_running(netdev)) { + adapter->pool_config = 1; + ibmveth_close(netdev); + adapter->pool_config = 0; + pool->size = value; + if ((rc = ibmveth_open(netdev))) + return rc; + } else + pool->size = value; } } else if (attr == &veth_size_attr) { if (value <= IBMVETH_BUFF_OH || value > IBMVETH_MAX_BUF_SIZE) return -EINVAL; else { - adapter->pool_config = 1; - ibmveth_close(netdev); - adapter->pool_config = 0; - pool->buff_size = value; - if ((rc = ibmveth_open(netdev))) - return rc; + if (netif_running(netdev)) { + adapter->pool_config = 1; + ibmveth_close(netdev); + adapter->pool_config = 0; + pool->buff_size = value; + if ((rc = ibmveth_open(netdev))) + return rc; + } else + pool->buff_size = value; } } @@ -1309,7 +1337,7 @@ const char * buf, size_t count) #define ATTR(_name, _mode) \ struct attribute veth_##_name##_attr = { \ - .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE \ + .name = __stringify(_name), .mode = _mode, \ }; static ATTR(active, 0644); diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c index 07b4c0d7a75..f5c3598e59a 100644 --- a/drivers/net/ifb.c +++ b/drivers/net/ifb.c @@ -136,13 +136,14 @@ resched: } -static void __init ifb_setup(struct net_device *dev) +static void ifb_setup(struct net_device *dev) { /* Initialize the device structure. */ dev->get_stats = ifb_get_stats; dev->hard_start_xmit = ifb_xmit; dev->open = &ifb_open; dev->stop = &ifb_close; + dev->destructor = free_netdev; /* Fill in device structure with ethernet-generic values. */ ether_setup(dev); @@ -197,12 +198,6 @@ static struct net_device_stats *ifb_get_stats(struct net_device *dev) return stats; } -static struct net_device **ifbs; - -/* Number of ifb devices to be set up by this module. */ -module_param(numifbs, int, 0); -MODULE_PARM_DESC(numifbs, "Number of ifb devices"); - static int ifb_close(struct net_device *dev) { struct ifb_private *dp = netdev_priv(dev); @@ -226,6 +221,28 @@ static int ifb_open(struct net_device *dev) return 0; } +static int ifb_validate(struct nlattr *tb[], struct nlattr *data[]) +{ + if (tb[IFLA_ADDRESS]) { + if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) + return -EINVAL; + if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) + return -EADDRNOTAVAIL; + } + return 0; +} + +static struct rtnl_link_ops ifb_link_ops __read_mostly = { + .kind = "ifb", + .priv_size = sizeof(struct ifb_private), + .setup = ifb_setup, + .validate = ifb_validate, +}; + +/* Number of ifb devices to be set up by this module. */ +module_param(numifbs, int, 0); +MODULE_PARM_DESC(numifbs, "Number of ifb devices"); + static int __init ifb_init_one(int index) { struct net_device *dev_ifb; @@ -237,49 +254,44 @@ static int __init ifb_init_one(int index) if (!dev_ifb) return -ENOMEM; - if ((err = register_netdev(dev_ifb))) { - free_netdev(dev_ifb); - dev_ifb = NULL; - } else { - ifbs[index] = dev_ifb; - } + err = dev_alloc_name(dev_ifb, dev_ifb->name); + if (err < 0) + goto err; - return err; -} + dev_ifb->rtnl_link_ops = &ifb_link_ops; + err = register_netdevice(dev_ifb); + if (err < 0) + goto err; + return 0; -static void ifb_free_one(int index) -{ - unregister_netdev(ifbs[index]); - free_netdev(ifbs[index]); +err: + free_netdev(dev_ifb); + return err; } static int __init ifb_init_module(void) { - int i, err = 0; - ifbs = kmalloc(numifbs * sizeof(void *), GFP_KERNEL); - if (!ifbs) - return -ENOMEM; + int i, err; + + rtnl_lock(); + err = __rtnl_link_register(&ifb_link_ops); + for (i = 0; i < numifbs && !err; i++) err = ifb_init_one(i); - if (err) { - i--; - while (--i >= 0) - ifb_free_one(i); - } + if (err) + __rtnl_link_unregister(&ifb_link_ops); + rtnl_unlock(); return err; } static void __exit ifb_cleanup_module(void) { - int i; - - for (i = 0; i < numifbs; i++) - ifb_free_one(i); - kfree(ifbs); + rtnl_link_unregister(&ifb_link_ops); } module_init(ifb_init_module); module_exit(ifb_cleanup_module); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jamal Hadi Salim"); +MODULE_ALIAS_RTNL_LINK("ifb"); diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index f749e07c642..3ca1e8ece54 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -352,13 +352,12 @@ static u64 nic_find(struct ioc3 *ioc3, int *last) static int nic_init(struct ioc3 *ioc3) { - const char *type; + const char *unknown = "unknown"; + const char *type = unknown; u8 crc; u8 serial[6]; int save = 0, i; - type = "unknown"; - while (1) { u64 reg; reg = nic_find(ioc3, &save); @@ -392,7 +391,7 @@ static int nic_init(struct ioc3 *ioc3) } printk("Found %s NIC", type); - if (type != "unknown") { + if (type != unknown) { printk (" registration number %02x:%02x:%02x:%02x:%02x:%02x," " CRC %02x", serial[0], serial[1], serial[2], serial[3], serial[4], serial[5], crc); @@ -1103,20 +1102,28 @@ static int ioc3_close(struct net_device *dev) * MiniDINs; all other subdevices are left swinging in the wind, leave * them disabled. */ -static inline int ioc3_is_menet(struct pci_dev *pdev) + +static int ioc3_adjacent_is_ioc3(struct pci_dev *pdev, int slot) +{ + struct pci_dev *dev = pci_get_slot(pdev->bus, PCI_DEVFN(slot, 0)); + int ret = 0; + + if (dev) { + if (dev->vendor == PCI_VENDOR_ID_SGI && + dev->device == PCI_DEVICE_ID_SGI_IOC3) + ret = 1; + pci_dev_put(dev); + } + + return ret; +} + +static int ioc3_is_menet(struct pci_dev *pdev) { - struct pci_dev *dev; - - return pdev->bus->parent == NULL - && (dev = pci_find_slot(pdev->bus->number, PCI_DEVFN(0, 0))) - && dev->vendor == PCI_VENDOR_ID_SGI - && dev->device == PCI_DEVICE_ID_SGI_IOC3 - && (dev = pci_find_slot(pdev->bus->number, PCI_DEVFN(1, 0))) - && dev->vendor == PCI_VENDOR_ID_SGI - && dev->device == PCI_DEVICE_ID_SGI_IOC3 - && (dev = pci_find_slot(pdev->bus->number, PCI_DEVFN(2, 0))) - && dev->vendor == PCI_VENDOR_ID_SGI - && dev->device == PCI_DEVICE_ID_SGI_IOC3; + return pdev->bus->parent == NULL && + ioc3_adjacent_is_ioc3(pdev, 0) && + ioc3_adjacent_is_ioc3(pdev, 1) && + ioc3_adjacent_is_ioc3(pdev, 2); } #ifdef CONFIG_SERIAL_8250 diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c index 3098960dc2a..3078c419cb0 100644 --- a/drivers/net/irda/irport.c +++ b/drivers/net/irda/irport.c @@ -509,7 +509,7 @@ static void irport_timeout(struct net_device *dev) IRDA_DEBUG(0, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n", __FUNCTION__, iir, lsr, iobase); - IRDA_DEBUG(0, "%s(), transmitting=%d, remain=%d, done=%d\n", + IRDA_DEBUG(0, "%s(), transmitting=%d, remain=%d, done=%td\n", __FUNCTION__, self->transmitting, self->tx_buff.len, self->tx_buff.data - self->tx_buff.head); diff --git a/drivers/net/irda/kingsun-sir.c b/drivers/net/irda/kingsun-sir.c index 217429122e7..bdd5c979bea 100644 --- a/drivers/net/irda/kingsun-sir.c +++ b/drivers/net/irda/kingsun-sir.c @@ -4,7 +4,7 @@ * Version: 0.1.1 * Description: Irda KingSun/DonShine USB Dongle * Status: Experimental -* Author: Alex Villac�s Lasso <a_villacis@palosanto.com> +* Author: Alex VillacÃs Lasso <a_villacis@palosanto.com> * * Based on stir4200 and mcs7780 drivers, with (strange?) differences * @@ -652,6 +652,6 @@ static void __exit kingsun_cleanup(void) } module_exit(kingsun_cleanup); -MODULE_AUTHOR("Alex Villac�s Lasso <a_villacis@palosanto.com>"); +MODULE_AUTHOR("Alex VillacÃs Lasso <a_villacis@palosanto.com>"); MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun/DonShine"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c index 9043bf4aa49..36ab98386be 100644 --- a/drivers/net/irda/smsc-ircc2.c +++ b/drivers/net/irda/smsc-ircc2.c @@ -79,7 +79,7 @@ MODULE_AUTHOR("Daniele Peri <peri@csai.unipa.it>"); MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver"); MODULE_LICENSE("GPL"); -static int smsc_nopnp; +static int smsc_nopnp = 1; module_param_named(nopnp, smsc_nopnp, bool, 0); MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings"); @@ -416,6 +416,13 @@ static int __init smsc_ircc_legacy_probe(void) { int ret = 0; +#ifdef CONFIG_PCI + if (smsc_ircc_preconfigure_subsystems(ircc_cfg, ircc_fir, ircc_sir, ircc_dma, ircc_irq) < 0) { + /* Ignore errors from preconfiguration */ + IRDA_ERROR("%s, Preconfiguration failed !\n", driver_name); + } +#endif + if (ircc_fir > 0 && ircc_sir > 0) { IRDA_MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir); IRDA_MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir); @@ -459,13 +466,6 @@ static int __init smsc_ircc_init(void) return ret; } -#ifdef CONFIG_PCI - if (smsc_ircc_preconfigure_subsystems(ircc_cfg, ircc_fir, ircc_sir, ircc_dma, ircc_irq) < 0) { - /* Ignore errors from preconfiguration */ - IRDA_ERROR("%s, Preconfiguration failed !\n", driver_name); - } -#endif - dev_count = 0; if (smsc_nopnp || !pnp_platform_devices || diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c index bf78ef1120a..0538ca9ce05 100644 --- a/drivers/net/irda/vlsi_ir.c +++ b/drivers/net/irda/vlsi_ir.c @@ -44,6 +44,7 @@ MODULE_LICENSE("GPL"); #include <linux/time.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> +#include <linux/mutex.h> #include <asm/uaccess.h> #include <asm/byteorder.h> @@ -1660,8 +1661,8 @@ vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id) idev = ndev->priv; spin_lock_init(&idev->lock); - init_MUTEX(&idev->sem); - down(&idev->sem); + mutex_init(&idev->mtx); + mutex_lock(&idev->mtx); idev->pdev = pdev; if (vlsi_irda_init(ndev) < 0) @@ -1689,12 +1690,12 @@ vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id) IRDA_MESSAGE("%s: registered device %s\n", drivername, ndev->name); pci_set_drvdata(pdev, ndev); - up(&idev->sem); + mutex_unlock(&idev->mtx); return 0; out_freedev: - up(&idev->sem); + mutex_unlock(&idev->mtx); free_netdev(ndev); out_disable: pci_disable_device(pdev); @@ -1716,12 +1717,12 @@ static void __devexit vlsi_irda_remove(struct pci_dev *pdev) unregister_netdev(ndev); idev = ndev->priv; - down(&idev->sem); + mutex_lock(&idev->mtx); if (idev->proc_entry) { remove_proc_entry(ndev->name, vlsi_proc_root); idev->proc_entry = NULL; } - up(&idev->sem); + mutex_unlock(&idev->mtx); free_netdev(ndev); @@ -1751,7 +1752,7 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state) return 0; } idev = ndev->priv; - down(&idev->sem); + mutex_lock(&idev->mtx); if (pdev->current_state != 0) { /* already suspended */ if (state.event > pdev->current_state) { /* simply go deeper */ pci_set_power_state(pdev, pci_choose_state(pdev, state)); @@ -1759,7 +1760,7 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state) } else IRDA_ERROR("%s - %s: invalid suspend request %u -> %u\n", __FUNCTION__, pci_name(pdev), pdev->current_state, state.event); - up(&idev->sem); + mutex_unlock(&idev->mtx); return 0; } @@ -1775,7 +1776,7 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state) pci_set_power_state(pdev, pci_choose_state(pdev, state)); pdev->current_state = state.event; idev->resume_ok = 1; - up(&idev->sem); + mutex_unlock(&idev->mtx); return 0; } @@ -1790,9 +1791,9 @@ static int vlsi_irda_resume(struct pci_dev *pdev) return 0; } idev = ndev->priv; - down(&idev->sem); + mutex_lock(&idev->mtx); if (pdev->current_state == 0) { - up(&idev->sem); + mutex_unlock(&idev->mtx); IRDA_WARNING("%s - %s: already resumed\n", __FUNCTION__, pci_name(pdev)); return 0; @@ -1814,7 +1815,7 @@ static int vlsi_irda_resume(struct pci_dev *pdev) * device and independently resume_ok should catch any garbage config. */ IRDA_WARNING("%s - hm, nothing to resume?\n", __FUNCTION__); - up(&idev->sem); + mutex_unlock(&idev->mtx); return 0; } @@ -1824,7 +1825,7 @@ static int vlsi_irda_resume(struct pci_dev *pdev) netif_device_attach(ndev); } idev->resume_ok = 0; - up(&idev->sem); + mutex_unlock(&idev->mtx); return 0; } diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h index 2d3b773d8e3..ca12a609641 100644 --- a/drivers/net/irda/vlsi_ir.h +++ b/drivers/net/irda/vlsi_ir.h @@ -728,7 +728,7 @@ typedef struct vlsi_irda_dev { struct timeval last_rx; spinlock_t lock; - struct semaphore sem; + struct mutex mtx; u8 resume_ok; struct proc_dir_entry *proc_entry; diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c index 6683afc02aa..d9ce1aef148 100644 --- a/drivers/net/ixp2000/ixpdev.c +++ b/drivers/net/ixp2000/ixpdev.c @@ -111,7 +111,7 @@ static int ixpdev_rx(struct net_device *dev, int *budget) skb = dev_alloc_skb(desc->pkt_length + 2); if (likely(skb != NULL)) { skb_reserve(skb, 2); - eth_copy_and_sum(skb, buf, desc->pkt_length, 0); + skb_copy_to_linear_data(skb, buf, desc->pkt_length); skb_put(skb, desc->pkt_length); skb->protocol = eth_type_trans(skb, nds[desc->channel]); @@ -222,7 +222,7 @@ static irqreturn_t ixpdev_interrupt(int irq, void *dev_id) static void ixpdev_poll_controller(struct net_device *dev) { disable_irq(IRQ_IXP2000_THDA0); - ixpdev_interrupt(IRQ_IXP2000_THDA0, dev, NULL); + ixpdev_interrupt(IRQ_IXP2000_THDA0, dev); enable_irq(IRQ_IXP2000_THDA0); } #endif diff --git a/drivers/net/lance.c b/drivers/net/lance.c index 0fe96c85828..a2f37e52b92 100644 --- a/drivers/net/lance.c +++ b/drivers/net/lance.c @@ -1186,9 +1186,9 @@ lance_rx(struct net_device *dev) } skb_reserve(skb,2); /* 16 byte align */ skb_put(skb,pkt_len); /* Make room */ - eth_copy_and_sum(skb, + skb_copy_to_linear_data(skb, (unsigned char *)isa_bus_to_virt((lp->rx_ring[entry].base & 0x00ffffff)), - pkt_len,0); + pkt_len); skb->protocol=eth_type_trans(skb,dev); netif_rx(skb); dev->last_rx = jiffies; diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c index 6b49fc4bd1a..efbae4b8398 100644 --- a/drivers/net/lasi_82596.c +++ b/drivers/net/lasi_82596.c @@ -83,95 +83,39 @@ #include <linux/init.h> #include <linux/types.h> #include <linux/bitops.h> +#include <linux/dma-mapping.h> #include <asm/io.h> -#include <asm/pgtable.h> #include <asm/irq.h> #include <asm/pdc.h> -#include <asm/cache.h> #include <asm/parisc-device.h> #define LASI_82596_DRIVER_VERSION "LASI 82596 driver - Revision: 1.30" -/* DEBUG flags - */ - -#define DEB_INIT 0x0001 -#define DEB_PROBE 0x0002 -#define DEB_SERIOUS 0x0004 -#define DEB_ERRORS 0x0008 -#define DEB_MULTI 0x0010 -#define DEB_TDR 0x0020 -#define DEB_OPEN 0x0040 -#define DEB_RESET 0x0080 -#define DEB_ADDCMD 0x0100 -#define DEB_STATUS 0x0200 -#define DEB_STARTTX 0x0400 -#define DEB_RXADDR 0x0800 -#define DEB_TXADDR 0x1000 -#define DEB_RXFRAME 0x2000 -#define DEB_INTS 0x4000 -#define DEB_STRUCT 0x8000 -#define DEB_ANY 0xffff - - -#define DEB(x,y) if (i596_debug & (x)) { y; } - - -#define CHECK_WBACK(priv, addr,len) \ - do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_TO_DEVICE); } while (0) - -#define CHECK_INV(priv, addr,len) \ - do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_FROM_DEVICE); } while(0) - -#define CHECK_WBACK_INV(priv, addr,len) \ - do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_BIDIRECTIONAL); } while (0) - - #define PA_I82596_RESET 0 /* Offsets relative to LASI-LAN-Addr.*/ #define PA_CPU_PORT_L_ACCESS 4 #define PA_CHANNEL_ATTENTION 8 +#define OPT_SWAP_PORT 0x0001 /* Need to wordswp on the MPU port */ -/* - * Define various macros for Channel Attention, word swapping etc., dependent - * on architecture. MVME and BVME are 680x0 based, otherwise it is Intel. - */ +#define DMA_ALLOC dma_alloc_noncoherent +#define DMA_FREE dma_free_noncoherent +#define DMA_WBACK(ndev, addr, len) \ + do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_TO_DEVICE); } while (0) -#ifdef __BIG_ENDIAN -#define WSWAPrfd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) -#define WSWAPrbd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) -#define WSWAPiscp(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) -#define WSWAPscb(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) -#define WSWAPcmd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) -#define WSWAPtbd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) -#define WSWAPchar(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) -#define ISCP_BUSY 0x00010000 -#define MACH_IS_APRICOT 0 -#else -#define WSWAPrfd(x) ((struct i596_rfd *)(x)) -#define WSWAPrbd(x) ((struct i596_rbd *)(x)) -#define WSWAPiscp(x) ((struct i596_iscp *)(x)) -#define WSWAPscb(x) ((struct i596_scb *)(x)) -#define WSWAPcmd(x) ((struct i596_cmd *)(x)) -#define WSWAPtbd(x) ((struct i596_tbd *)(x)) -#define WSWAPchar(x) ((char *)(x)) -#define ISCP_BUSY 0x0001 -#define MACH_IS_APRICOT 1 -#endif +#define DMA_INV(ndev, addr, len) \ + do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_FROM_DEVICE); } while (0) -/* - * The MPU_PORT command allows direct access to the 82596. With PORT access - * the following commands are available (p5-18). The 32-bit port command - * must be word-swapped with the most significant word written first. - * This only applies to VME boards. - */ -#define PORT_RESET 0x00 /* reset 82596 */ -#define PORT_SELFTEST 0x01 /* selftest */ -#define PORT_ALTSCP 0x02 /* alternate SCB address */ -#define PORT_ALTDUMP 0x03 /* Alternate DUMP address */ +#define DMA_WBACK_INV(ndev, addr, len) \ + do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_BIDIRECTIONAL); } while (0) + +#define SYSBUS 0x0000006c; + +/* big endian CPU, 82596 "big" endian mode */ +#define SWAP32(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) +#define SWAP16(x) (x) -static int i596_debug = (DEB_SERIOUS|DEB_PROBE); +#include "lib82596.c" MODULE_AUTHOR("Richard Hirst"); MODULE_DESCRIPTION("i82596 driver"); @@ -179,255 +123,15 @@ MODULE_LICENSE("GPL"); module_param(i596_debug, int, 0); MODULE_PARM_DESC(i596_debug, "lasi_82596 debug mask"); -/* Copy frames shorter than rx_copybreak, otherwise pass on up in - * a full sized sk_buff. Value of 100 stolen from tulip.c (!alpha). - */ -static int rx_copybreak = 100; - -#define MAX_DRIVERS 4 /* max count of drivers */ - -#define PKT_BUF_SZ 1536 -#define MAX_MC_CNT 64 - -#define I596_NULL ((u32)0xffffffff) - -#define CMD_EOL 0x8000 /* The last command of the list, stop. */ -#define CMD_SUSP 0x4000 /* Suspend after doing cmd. */ -#define CMD_INTR 0x2000 /* Interrupt after doing cmd. */ - -#define CMD_FLEX 0x0008 /* Enable flexible memory model */ - -enum commands { - CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3, - CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7 -}; - -#define STAT_C 0x8000 /* Set to 0 after execution */ -#define STAT_B 0x4000 /* Command being executed */ -#define STAT_OK 0x2000 /* Command executed ok */ -#define STAT_A 0x1000 /* Command aborted */ - -#define CUC_START 0x0100 -#define CUC_RESUME 0x0200 -#define CUC_SUSPEND 0x0300 -#define CUC_ABORT 0x0400 -#define RX_START 0x0010 -#define RX_RESUME 0x0020 -#define RX_SUSPEND 0x0030 -#define RX_ABORT 0x0040 - -#define TX_TIMEOUT 5 - -#define OPT_SWAP_PORT 0x0001 /* Need to wordswp on the MPU port */ - - -struct i596_reg { - unsigned short porthi; - unsigned short portlo; - u32 ca; -}; - -#define EOF 0x8000 -#define SIZE_MASK 0x3fff - -struct i596_tbd { - unsigned short size; - unsigned short pad; - dma_addr_t next; - dma_addr_t data; - u32 cache_pad[5]; /* Total 32 bytes... */ -}; - -/* The command structure has two 'next' pointers; v_next is the address of - * the next command as seen by the CPU, b_next is the address of the next - * command as seen by the 82596. The b_next pointer, as used by the 82596 - * always references the status field of the next command, rather than the - * v_next field, because the 82596 is unaware of v_next. It may seem more - * logical to put v_next at the end of the structure, but we cannot do that - * because the 82596 expects other fields to be there, depending on command - * type. - */ - -struct i596_cmd { - struct i596_cmd *v_next; /* Address from CPUs viewpoint */ - unsigned short status; - unsigned short command; - dma_addr_t b_next; /* Address from i596 viewpoint */ -}; - -struct tx_cmd { - struct i596_cmd cmd; - dma_addr_t tbd; - unsigned short size; - unsigned short pad; - struct sk_buff *skb; /* So we can free it after tx */ - dma_addr_t dma_addr; -#ifdef __LP64__ - u32 cache_pad[6]; /* Total 64 bytes... */ -#else - u32 cache_pad[1]; /* Total 32 bytes... */ -#endif -}; - -struct tdr_cmd { - struct i596_cmd cmd; - unsigned short status; - unsigned short pad; -}; - -struct mc_cmd { - struct i596_cmd cmd; - short mc_cnt; - char mc_addrs[MAX_MC_CNT*6]; -}; - -struct sa_cmd { - struct i596_cmd cmd; - char eth_addr[8]; -}; - -struct cf_cmd { - struct i596_cmd cmd; - char i596_config[16]; -}; - -struct i596_rfd { - unsigned short stat; - unsigned short cmd; - dma_addr_t b_next; /* Address from i596 viewpoint */ - dma_addr_t rbd; - unsigned short count; - unsigned short size; - struct i596_rfd *v_next; /* Address from CPUs viewpoint */ - struct i596_rfd *v_prev; -#ifndef __LP64__ - u32 cache_pad[2]; /* Total 32 bytes... */ -#endif -}; - -struct i596_rbd { - /* hardware data */ - unsigned short count; - unsigned short zero1; - dma_addr_t b_next; - dma_addr_t b_data; /* Address from i596 viewpoint */ - unsigned short size; - unsigned short zero2; - /* driver data */ - struct sk_buff *skb; - struct i596_rbd *v_next; - dma_addr_t b_addr; /* This rbd addr from i596 view */ - unsigned char *v_data; /* Address from CPUs viewpoint */ - /* Total 32 bytes... */ -#ifdef __LP64__ - u32 cache_pad[4]; -#endif -}; - -/* These values as chosen so struct i596_private fits in one page... */ - -#define TX_RING_SIZE 32 -#define RX_RING_SIZE 16 - -struct i596_scb { - unsigned short status; - unsigned short command; - dma_addr_t cmd; - dma_addr_t rfd; - u32 crc_err; - u32 align_err; - u32 resource_err; - u32 over_err; - u32 rcvdt_err; - u32 short_err; - unsigned short t_on; - unsigned short t_off; -}; - -struct i596_iscp { - u32 stat; - dma_addr_t scb; -}; - -struct i596_scp { - u32 sysbus; - u32 pad; - dma_addr_t iscp; -}; - -struct i596_private { - volatile struct i596_scp scp __attribute__((aligned(32))); - volatile struct i596_iscp iscp __attribute__((aligned(32))); - volatile struct i596_scb scb __attribute__((aligned(32))); - struct sa_cmd sa_cmd __attribute__((aligned(32))); - struct cf_cmd cf_cmd __attribute__((aligned(32))); - struct tdr_cmd tdr_cmd __attribute__((aligned(32))); - struct mc_cmd mc_cmd __attribute__((aligned(32))); - struct i596_rfd rfds[RX_RING_SIZE] __attribute__((aligned(32))); - struct i596_rbd rbds[RX_RING_SIZE] __attribute__((aligned(32))); - struct tx_cmd tx_cmds[TX_RING_SIZE] __attribute__((aligned(32))); - struct i596_tbd tbds[TX_RING_SIZE] __attribute__((aligned(32))); - u32 stat; - int last_restart; - struct i596_rfd *rfd_head; - struct i596_rbd *rbd_head; - struct i596_cmd *cmd_tail; - struct i596_cmd *cmd_head; - int cmd_backlog; - u32 last_cmd; - struct net_device_stats stats; - int next_tx_cmd; - int options; - spinlock_t lock; - dma_addr_t dma_addr; - struct device *dev; -}; - -static const char init_setup[] = -{ - 0x8E, /* length, prefetch on */ - 0xC8, /* fifo to 8, monitor off */ - 0x80, /* don't save bad frames */ - 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 */ - 0x00, /* promiscuous mode */ - 0x00, /* collision detect */ - 0x40, /* minimum frame length */ - 0xff, - 0x00, - 0x7f /* *multi IA */ }; - -static int i596_open(struct net_device *dev); -static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t i596_interrupt(int irq, void *dev_id); -static int i596_close(struct net_device *dev); -static struct net_device_stats *i596_get_stats(struct net_device *dev); -static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd); -static void i596_tx_timeout (struct net_device *dev); -static void print_eth(unsigned char *buf, char *str); -static void set_multicast_list(struct net_device *dev); - -static int rx_ring_size = RX_RING_SIZE; -static int ticks_limit = 100; -static int max_cmd_backlog = TX_RING_SIZE-1; - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void i596_poll_controller(struct net_device *dev); -#endif - - -static inline void CA(struct net_device *dev) +static inline void ca(struct net_device *dev) { gsc_writel(0, dev->base_addr + PA_CHANNEL_ATTENTION); } -static inline void MPU_PORT(struct net_device *dev, int c, dma_addr_t x) +static void mpu_port(struct net_device *dev, int c, dma_addr_t x) { - struct i596_private *lp = dev->priv; + struct i596_private *lp = netdev_priv(dev); u32 v = (u32) (c) | (u32) (x); u16 a, b; @@ -445,1078 +149,15 @@ static inline void MPU_PORT(struct net_device *dev, int c, dma_addr_t x) gsc_writel(b, dev->base_addr + PA_CPU_PORT_L_ACCESS); } - -static inline int wait_istat(struct net_device *dev, struct i596_private *lp, int delcnt, char *str) -{ - CHECK_INV(lp, &(lp->iscp), sizeof(struct i596_iscp)); - while (--delcnt && lp->iscp.stat) { - udelay(10); - CHECK_INV(lp, &(lp->iscp), sizeof(struct i596_iscp)); - } - if (!delcnt) { - printk("%s: %s, iscp.stat %04x, didn't clear\n", - dev->name, str, lp->iscp.stat); - return -1; - } - else - return 0; -} - - -static inline int wait_cmd(struct net_device *dev, struct i596_private *lp, int delcnt, char *str) -{ - CHECK_INV(lp, &(lp->scb), sizeof(struct i596_scb)); - while (--delcnt && lp->scb.command) { - udelay(10); - CHECK_INV(lp, &(lp->scb), sizeof(struct i596_scb)); - } - if (!delcnt) { - printk("%s: %s, status %4.4x, cmd %4.4x.\n", - dev->name, str, lp->scb.status, lp->scb.command); - return -1; - } - else - return 0; -} - - -static void i596_display_data(struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - struct i596_cmd *cmd; - struct i596_rfd *rfd; - struct i596_rbd *rbd; - - printk("lp and scp at %p, .sysbus = %08x, .iscp = %08x\n", - &lp->scp, lp->scp.sysbus, lp->scp.iscp); - printk("iscp at %p, iscp.stat = %08x, .scb = %08x\n", - &lp->iscp, lp->iscp.stat, lp->iscp.scb); - printk("scb at %p, scb.status = %04x, .command = %04x," - " .cmd = %08x, .rfd = %08x\n", - &lp->scb, lp->scb.status, lp->scb.command, - lp->scb.cmd, lp->scb.rfd); - printk(" errors: crc %x, align %x, resource %x," - " over %x, rcvdt %x, short %x\n", - lp->scb.crc_err, lp->scb.align_err, lp->scb.resource_err, - lp->scb.over_err, lp->scb.rcvdt_err, lp->scb.short_err); - cmd = lp->cmd_head; - while (cmd != NULL) { - printk("cmd at %p, .status = %04x, .command = %04x, .b_next = %08x\n", - cmd, cmd->status, cmd->command, cmd->b_next); - cmd = cmd->v_next; - } - rfd = lp->rfd_head; - printk("rfd_head = %p\n", rfd); - do { - printk(" %p .stat %04x, .cmd %04x, b_next %08x, rbd %08x," - " count %04x\n", - rfd, rfd->stat, rfd->cmd, rfd->b_next, rfd->rbd, - rfd->count); - rfd = rfd->v_next; - } while (rfd != lp->rfd_head); - rbd = lp->rbd_head; - printk("rbd_head = %p\n", rbd); - do { - printk(" %p .count %04x, b_next %08x, b_data %08x, size %04x\n", - rbd, rbd->count, rbd->b_next, rbd->b_data, rbd->size); - rbd = rbd->v_next; - } while (rbd != lp->rbd_head); - CHECK_INV(lp, lp, sizeof(struct i596_private)); -} - - -#if defined(ENABLE_MVME16x_NET) || defined(ENABLE_BVME6000_NET) -static void i596_error(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000; - - pcc2[0x28] = 1; - pcc2[0x2b] = 0x1d; - printk("%s: Error interrupt\n", dev->name); - i596_display_data(dev); -} -#endif - -#define virt_to_dma(lp,v) ((lp)->dma_addr + (dma_addr_t)((unsigned long)(v)-(unsigned long)(lp))) - -static inline void init_rx_bufs(struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - int i; - struct i596_rfd *rfd; - struct i596_rbd *rbd; - - /* First build the Receive Buffer Descriptor List */ - - for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) { - dma_addr_t dma_addr; - struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ + 4); - - if (skb == NULL) - panic("%s: alloc_skb() failed", __FILE__); - skb_reserve(skb, 2); - dma_addr = dma_map_single(lp->dev, skb->data,PKT_BUF_SZ, - DMA_FROM_DEVICE); - skb->dev = dev; - rbd->v_next = rbd+1; - rbd->b_next = WSWAPrbd(virt_to_dma(lp,rbd+1)); - rbd->b_addr = WSWAPrbd(virt_to_dma(lp,rbd)); - rbd->skb = skb; - rbd->v_data = skb->data; - rbd->b_data = WSWAPchar(dma_addr); - rbd->size = PKT_BUF_SZ; - } - lp->rbd_head = lp->rbds; - rbd = lp->rbds + rx_ring_size - 1; - rbd->v_next = lp->rbds; - rbd->b_next = WSWAPrbd(virt_to_dma(lp,lp->rbds)); - - /* Now build the Receive Frame Descriptor List */ - - for (i = 0, rfd = lp->rfds; i < rx_ring_size; i++, rfd++) { - rfd->rbd = I596_NULL; - rfd->v_next = rfd+1; - rfd->v_prev = rfd-1; - rfd->b_next = WSWAPrfd(virt_to_dma(lp,rfd+1)); - rfd->cmd = CMD_FLEX; - } - lp->rfd_head = lp->rfds; - lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds)); - rfd = lp->rfds; - rfd->rbd = WSWAPrbd(virt_to_dma(lp,lp->rbd_head)); - rfd->v_prev = lp->rfds + rx_ring_size - 1; - rfd = lp->rfds + rx_ring_size - 1; - rfd->v_next = lp->rfds; - rfd->b_next = WSWAPrfd(virt_to_dma(lp,lp->rfds)); - rfd->cmd = CMD_EOL|CMD_FLEX; - - CHECK_WBACK_INV(lp, lp, sizeof(struct i596_private)); -} - -static inline void remove_rx_bufs(struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - struct i596_rbd *rbd; - int i; - - for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) { - if (rbd->skb == NULL) - break; - dma_unmap_single(lp->dev, - (dma_addr_t)WSWAPchar(rbd->b_data), - PKT_BUF_SZ, DMA_FROM_DEVICE); - dev_kfree_skb(rbd->skb); - } -} - - -static void rebuild_rx_bufs(struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - int i; - - /* Ensure rx frame/buffer descriptors are tidy */ - - for (i = 0; i < rx_ring_size; i++) { - lp->rfds[i].rbd = I596_NULL; - lp->rfds[i].cmd = CMD_FLEX; - } - lp->rfds[rx_ring_size-1].cmd = CMD_EOL|CMD_FLEX; - lp->rfd_head = lp->rfds; - lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds)); - lp->rbd_head = lp->rbds; - lp->rfds[0].rbd = WSWAPrbd(virt_to_dma(lp,lp->rbds)); - - CHECK_WBACK_INV(lp, lp, sizeof(struct i596_private)); -} - - -static int init_i596_mem(struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - unsigned long flags; - - disable_irq(dev->irq); /* disable IRQs from LAN */ - DEB(DEB_INIT, - printk("RESET 82596 port: %lx (with IRQ %d disabled)\n", - (dev->base_addr + PA_I82596_RESET), - dev->irq)); - - gsc_writel(0, (dev->base_addr + PA_I82596_RESET)); /* Hard Reset */ - udelay(100); /* Wait 100us - seems to help */ - - /* change the scp address */ - - lp->last_cmd = jiffies; - - - lp->scp.sysbus = 0x0000006c; - lp->scp.iscp = WSWAPiscp(virt_to_dma(lp,&(lp->iscp))); - lp->iscp.scb = WSWAPscb(virt_to_dma(lp,&(lp->scb))); - lp->iscp.stat = ISCP_BUSY; - lp->cmd_backlog = 0; - - lp->cmd_head = NULL; - lp->scb.cmd = I596_NULL; - - DEB(DEB_INIT, printk("%s: starting i82596.\n", dev->name)); - - CHECK_WBACK(lp, &(lp->scp), sizeof(struct i596_scp)); - CHECK_WBACK(lp, &(lp->iscp), sizeof(struct i596_iscp)); - - MPU_PORT(dev, PORT_ALTSCP, virt_to_dma(lp,&lp->scp)); - - CA(dev); - - if (wait_istat(dev, lp, 1000, "initialization timed out")) - goto failed; - DEB(DEB_INIT, printk("%s: i82596 initialization successful\n", dev->name)); - - /* Ensure rx frame/buffer descriptors are tidy */ - rebuild_rx_bufs(dev); - - lp->scb.command = 0; - CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb)); - - enable_irq(dev->irq); /* enable IRQs from LAN */ - - DEB(DEB_INIT, printk("%s: queuing CmdConfigure\n", dev->name)); - memcpy(lp->cf_cmd.i596_config, init_setup, sizeof(init_setup)); - lp->cf_cmd.cmd.command = CmdConfigure; - CHECK_WBACK(lp, &(lp->cf_cmd), sizeof(struct cf_cmd)); - i596_add_cmd(dev, &lp->cf_cmd.cmd); - - DEB(DEB_INIT, printk("%s: queuing CmdSASetup\n", dev->name)); - memcpy(lp->sa_cmd.eth_addr, dev->dev_addr, 6); - lp->sa_cmd.cmd.command = CmdSASetup; - CHECK_WBACK(lp, &(lp->sa_cmd), sizeof(struct sa_cmd)); - i596_add_cmd(dev, &lp->sa_cmd.cmd); - - DEB(DEB_INIT, printk("%s: queuing CmdTDR\n", dev->name)); - lp->tdr_cmd.cmd.command = CmdTDR; - CHECK_WBACK(lp, &(lp->tdr_cmd), sizeof(struct tdr_cmd)); - i596_add_cmd(dev, &lp->tdr_cmd.cmd); - - spin_lock_irqsave (&lp->lock, flags); - - if (wait_cmd(dev, lp, 1000, "timed out waiting to issue RX_START")) { - spin_unlock_irqrestore (&lp->lock, flags); - goto failed; - } - DEB(DEB_INIT, printk("%s: Issuing RX_START\n", dev->name)); - lp->scb.command = RX_START; - lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds)); - CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb)); - - CA(dev); - - spin_unlock_irqrestore (&lp->lock, flags); - - if (wait_cmd(dev, lp, 1000, "RX_START not processed")) - goto failed; - DEB(DEB_INIT, printk("%s: Receive unit started OK\n", dev->name)); - - return 0; - -failed: - printk("%s: Failed to initialise 82596\n", dev->name); - MPU_PORT(dev, PORT_RESET, 0); - return -1; -} - - -static inline int i596_rx(struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - struct i596_rfd *rfd; - struct i596_rbd *rbd; - int frames = 0; - - DEB(DEB_RXFRAME, printk("i596_rx(), rfd_head %p, rbd_head %p\n", - lp->rfd_head, lp->rbd_head)); - - - rfd = lp->rfd_head; /* Ref next frame to check */ - - CHECK_INV(lp, rfd, sizeof(struct i596_rfd)); - while ((rfd->stat) & STAT_C) { /* Loop while complete frames */ - if (rfd->rbd == I596_NULL) - rbd = NULL; - else if (rfd->rbd == lp->rbd_head->b_addr) { - rbd = lp->rbd_head; - CHECK_INV(lp, rbd, sizeof(struct i596_rbd)); - } - else { - printk("%s: rbd chain broken!\n", dev->name); - /* XXX Now what? */ - rbd = NULL; - } - DEB(DEB_RXFRAME, printk(" rfd %p, rfd.rbd %08x, rfd.stat %04x\n", - rfd, rfd->rbd, rfd->stat)); - - if (rbd != NULL && ((rfd->stat) & STAT_OK)) { - /* a good frame */ - int pkt_len = rbd->count & 0x3fff; - struct sk_buff *skb = rbd->skb; - int rx_in_place = 0; - - DEB(DEB_RXADDR,print_eth(rbd->v_data, "received")); - frames++; - - /* Check if the packet is long enough to just accept - * without copying to a properly sized skbuff. - */ - - if (pkt_len > rx_copybreak) { - struct sk_buff *newskb; - dma_addr_t dma_addr; - - dma_unmap_single(lp->dev,(dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, DMA_FROM_DEVICE); - /* Get fresh skbuff to replace filled one. */ - newskb = dev_alloc_skb(PKT_BUF_SZ + 4); - if (newskb == NULL) { - skb = NULL; /* drop pkt */ - goto memory_squeeze; - } - skb_reserve(newskb, 2); - - /* Pass up the skb already on the Rx ring. */ - skb_put(skb, pkt_len); - rx_in_place = 1; - rbd->skb = newskb; - newskb->dev = dev; - dma_addr = dma_map_single(lp->dev, newskb->data, PKT_BUF_SZ, DMA_FROM_DEVICE); - rbd->v_data = newskb->data; - rbd->b_data = WSWAPchar(dma_addr); - CHECK_WBACK_INV(lp, rbd, sizeof(struct i596_rbd)); - } - else - skb = dev_alloc_skb(pkt_len + 2); -memory_squeeze: - if (skb == NULL) { - /* XXX tulip.c can defer packets here!! */ - printk("%s: i596_rx Memory squeeze, dropping packet.\n", dev->name); - lp->stats.rx_dropped++; - } - else { - if (!rx_in_place) { - /* 16 byte align the data fields */ - dma_sync_single_for_cpu(lp->dev, (dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, DMA_FROM_DEVICE); - skb_reserve(skb, 2); - memcpy(skb_put(skb,pkt_len), rbd->v_data, pkt_len); - dma_sync_single_for_device(lp->dev, (dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, DMA_FROM_DEVICE); - } - skb->len = pkt_len; - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - dev->last_rx = jiffies; - lp->stats.rx_packets++; - lp->stats.rx_bytes+=pkt_len; - } - } - else { - DEB(DEB_ERRORS, printk("%s: Error, rfd.stat = 0x%04x\n", - dev->name, rfd->stat)); - lp->stats.rx_errors++; - if ((rfd->stat) & 0x0001) - lp->stats.collisions++; - if ((rfd->stat) & 0x0080) - lp->stats.rx_length_errors++; - if ((rfd->stat) & 0x0100) - lp->stats.rx_over_errors++; - if ((rfd->stat) & 0x0200) - lp->stats.rx_fifo_errors++; - if ((rfd->stat) & 0x0400) - lp->stats.rx_frame_errors++; - if ((rfd->stat) & 0x0800) - lp->stats.rx_crc_errors++; - if ((rfd->stat) & 0x1000) - lp->stats.rx_length_errors++; - } - - /* Clear the buffer descriptor count and EOF + F flags */ - - if (rbd != NULL && (rbd->count & 0x4000)) { - rbd->count = 0; - lp->rbd_head = rbd->v_next; - CHECK_WBACK_INV(lp, rbd, sizeof(struct i596_rbd)); - } - - /* Tidy the frame descriptor, marking it as end of list */ - - rfd->rbd = I596_NULL; - rfd->stat = 0; - rfd->cmd = CMD_EOL|CMD_FLEX; - rfd->count = 0; - - /* Remove end-of-list from old end descriptor */ - - rfd->v_prev->cmd = CMD_FLEX; - - /* Update record of next frame descriptor to process */ - - lp->scb.rfd = rfd->b_next; - lp->rfd_head = rfd->v_next; - CHECK_WBACK_INV(lp, rfd->v_prev, sizeof(struct i596_rfd)); - CHECK_WBACK_INV(lp, rfd, sizeof(struct i596_rfd)); - rfd = lp->rfd_head; - CHECK_INV(lp, rfd, sizeof(struct i596_rfd)); - } - - DEB(DEB_RXFRAME, printk("frames %d\n", frames)); - - return 0; -} - - -static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp) -{ - struct i596_cmd *ptr; - - while (lp->cmd_head != NULL) { - ptr = lp->cmd_head; - lp->cmd_head = ptr->v_next; - lp->cmd_backlog--; - - switch ((ptr->command) & 0x7) { - case CmdTx: - { - struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr; - struct sk_buff *skb = tx_cmd->skb; - dma_unmap_single(lp->dev, tx_cmd->dma_addr, skb->len, DMA_TO_DEVICE); - - dev_kfree_skb(skb); - - lp->stats.tx_errors++; - lp->stats.tx_aborted_errors++; - - ptr->v_next = NULL; - ptr->b_next = I596_NULL; - tx_cmd->cmd.command = 0; /* Mark as free */ - break; - } - default: - ptr->v_next = NULL; - ptr->b_next = I596_NULL; - } - CHECK_WBACK_INV(lp, ptr, sizeof(struct i596_cmd)); - } - - wait_cmd(dev, lp, 100, "i596_cleanup_cmd timed out"); - lp->scb.cmd = I596_NULL; - CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb)); -} - - -static inline void i596_reset(struct net_device *dev, struct i596_private *lp) -{ - unsigned long flags; - - DEB(DEB_RESET, printk("i596_reset\n")); - - spin_lock_irqsave (&lp->lock, flags); - - wait_cmd(dev, lp, 100, "i596_reset timed out"); - - netif_stop_queue(dev); - - /* FIXME: this command might cause an lpmc */ - lp->scb.command = CUC_ABORT | RX_ABORT; - CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb)); - CA(dev); - - /* wait for shutdown */ - wait_cmd(dev, lp, 1000, "i596_reset 2 timed out"); - spin_unlock_irqrestore (&lp->lock, flags); - - i596_cleanup_cmd(dev,lp); - i596_rx(dev); - - netif_start_queue(dev); - init_i596_mem(dev); -} - - -static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd) -{ - struct i596_private *lp = dev->priv; - unsigned long flags; - - DEB(DEB_ADDCMD, printk("i596_add_cmd cmd_head %p\n", lp->cmd_head)); - - cmd->status = 0; - cmd->command |= (CMD_EOL | CMD_INTR); - cmd->v_next = NULL; - cmd->b_next = I596_NULL; - CHECK_WBACK(lp, cmd, sizeof(struct i596_cmd)); - - spin_lock_irqsave (&lp->lock, flags); - - if (lp->cmd_head != NULL) { - lp->cmd_tail->v_next = cmd; - lp->cmd_tail->b_next = WSWAPcmd(virt_to_dma(lp,&cmd->status)); - CHECK_WBACK(lp, lp->cmd_tail, sizeof(struct i596_cmd)); - } else { - lp->cmd_head = cmd; - wait_cmd(dev, lp, 100, "i596_add_cmd timed out"); - lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&cmd->status)); - lp->scb.command = CUC_START; - CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb)); - CA(dev); - } - lp->cmd_tail = cmd; - lp->cmd_backlog++; - - spin_unlock_irqrestore (&lp->lock, flags); - - if (lp->cmd_backlog > max_cmd_backlog) { - unsigned long tickssofar = jiffies - lp->last_cmd; - - if (tickssofar < ticks_limit) - return; - - printk("%s: command unit timed out, status resetting.\n", dev->name); -#if 1 - i596_reset(dev, lp); -#endif - } -} - -#if 0 -/* this function makes a perfectly adequate probe... but we have a - device list */ -static int i596_test(struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - volatile int *tint; - u32 data; - - tint = (volatile int *)(&(lp->scp)); - data = virt_to_dma(lp,tint); - - tint[1] = -1; - CHECK_WBACK(lp, tint, PAGE_SIZE); - - MPU_PORT(dev, 1, data); - - for(data = 1000000; data; data--) { - CHECK_INV(lp, tint, PAGE_SIZE); - if(tint[1] != -1) - break; - - } - - printk("i596_test result %d\n", tint[1]); - -} -#endif - - -static int i596_open(struct net_device *dev) -{ - DEB(DEB_OPEN, printk("%s: i596_open() irq %d.\n", dev->name, dev->irq)); - - if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev)) { - printk("%s: IRQ %d not free\n", dev->name, dev->irq); - goto out; - } - - init_rx_bufs(dev); - - if (init_i596_mem(dev)) { - printk("%s: Failed to init memory\n", dev->name); - goto out_remove_rx_bufs; - } - - netif_start_queue(dev); - - return 0; - -out_remove_rx_bufs: - remove_rx_bufs(dev); - free_irq(dev->irq, dev); -out: - return -EAGAIN; -} - -static void i596_tx_timeout (struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - - /* Transmitter timeout, serious problems. */ - DEB(DEB_ERRORS, printk("%s: transmit timed out, status resetting.\n", - dev->name)); - - lp->stats.tx_errors++; - - /* Try to restart the adaptor */ - if (lp->last_restart == lp->stats.tx_packets) { - DEB(DEB_ERRORS, printk("Resetting board.\n")); - /* Shutdown and restart */ - i596_reset (dev, lp); - } else { - /* Issue a channel attention signal */ - DEB(DEB_ERRORS, printk("Kicking board.\n")); - lp->scb.command = CUC_START | RX_START; - CHECK_WBACK_INV(lp, &(lp->scb), sizeof(struct i596_scb)); - CA (dev); - lp->last_restart = lp->stats.tx_packets; - } - - dev->trans_start = jiffies; - netif_wake_queue (dev); -} - - -static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - struct tx_cmd *tx_cmd; - struct i596_tbd *tbd; - short length = skb->len; - dev->trans_start = jiffies; - - DEB(DEB_STARTTX, printk("%s: i596_start_xmit(%x,%p) called\n", dev->name, - skb->len, skb->data)); - - if (length < ETH_ZLEN) { - if (skb_padto(skb, ETH_ZLEN)) - return 0; - length = ETH_ZLEN; - } - - netif_stop_queue(dev); - - tx_cmd = lp->tx_cmds + lp->next_tx_cmd; - tbd = lp->tbds + lp->next_tx_cmd; - - if (tx_cmd->cmd.command) { - DEB(DEB_ERRORS, printk("%s: xmit ring full, dropping packet.\n", - dev->name)); - lp->stats.tx_dropped++; - - dev_kfree_skb(skb); - } else { - if (++lp->next_tx_cmd == TX_RING_SIZE) - lp->next_tx_cmd = 0; - tx_cmd->tbd = WSWAPtbd(virt_to_dma(lp,tbd)); - tbd->next = I596_NULL; - - tx_cmd->cmd.command = CMD_FLEX | CmdTx; - tx_cmd->skb = skb; - - tx_cmd->pad = 0; - tx_cmd->size = 0; - tbd->pad = 0; - tbd->size = EOF | length; - - tx_cmd->dma_addr = dma_map_single(lp->dev, skb->data, skb->len, - DMA_TO_DEVICE); - tbd->data = WSWAPchar(tx_cmd->dma_addr); - - DEB(DEB_TXADDR,print_eth(skb->data, "tx-queued")); - CHECK_WBACK_INV(lp, tx_cmd, sizeof(struct tx_cmd)); - CHECK_WBACK_INV(lp, tbd, sizeof(struct i596_tbd)); - i596_add_cmd(dev, &tx_cmd->cmd); - - lp->stats.tx_packets++; - lp->stats.tx_bytes += length; - } - - netif_start_queue(dev); - - return 0; -} - -static void print_eth(unsigned char *add, char *str) -{ - int i; - - printk("i596 0x%p, ", add); - for (i = 0; i < 6; i++) - printk(" %02X", add[i + 6]); - printk(" -->"); - for (i = 0; i < 6; i++) - printk(" %02X", add[i]); - printk(" %02X%02X, %s\n", add[12], add[13], str); -} - - #define LAN_PROM_ADDR 0xF0810000 -static int __devinit i82596_probe(struct net_device *dev, - struct device *gen_dev) -{ - int i; - struct i596_private *lp; - char eth_addr[6]; - dma_addr_t dma_addr; - - /* This lot is ensure things have been cache line aligned. */ - BUILD_BUG_ON(sizeof(struct i596_rfd) != 32); - BUILD_BUG_ON(sizeof(struct i596_rbd) & 31); - BUILD_BUG_ON(sizeof(struct tx_cmd) & 31); - BUILD_BUG_ON(sizeof(struct i596_tbd) != 32); -#ifndef __LP64__ - BUILD_BUG_ON(sizeof(struct i596_private) > 4096); -#endif - - if (!dev->base_addr || !dev->irq) - return -ENODEV; - - if (pdc_lan_station_id(eth_addr, dev->base_addr)) { - for (i=0; i < 6; i++) { - eth_addr[i] = gsc_readb(LAN_PROM_ADDR + i); - } - printk(KERN_INFO "%s: MAC of HP700 LAN read from EEPROM\n", __FILE__); - } - - dev->mem_start = (unsigned long) dma_alloc_noncoherent(gen_dev, - sizeof(struct i596_private), &dma_addr, GFP_KERNEL); - if (!dev->mem_start) { - printk(KERN_ERR "%s: Couldn't get shared memory\n", __FILE__); - return -ENOMEM; - } - - for (i = 0; i < 6; i++) - dev->dev_addr[i] = eth_addr[i]; - - /* The 82596-specific entries in the device structure. */ - dev->open = i596_open; - dev->stop = i596_close; - dev->hard_start_xmit = i596_start_xmit; - dev->get_stats = i596_get_stats; - dev->set_multicast_list = set_multicast_list; - dev->tx_timeout = i596_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = i596_poll_controller; -#endif - - dev->priv = (void *)(dev->mem_start); - - lp = dev->priv; - memset(lp, 0, sizeof(struct i596_private)); - - lp->scb.command = 0; - lp->scb.cmd = I596_NULL; - lp->scb.rfd = I596_NULL; - spin_lock_init(&lp->lock); - lp->dma_addr = dma_addr; - lp->dev = gen_dev; - - CHECK_WBACK_INV(lp, dev->mem_start, sizeof(struct i596_private)); - - i = register_netdev(dev); - if (i) { - lp = dev->priv; - dma_free_noncoherent(lp->dev, sizeof(struct i596_private), - (void *)dev->mem_start, lp->dma_addr); - return i; - }; - - DEB(DEB_PROBE, printk(KERN_INFO "%s: 82596 at %#3lx,", dev->name, dev->base_addr)); - for (i = 0; i < 6; i++) - DEB(DEB_PROBE, printk(" %2.2X", dev->dev_addr[i])); - DEB(DEB_PROBE, printk(" IRQ %d.\n", dev->irq)); - DEB(DEB_INIT, printk(KERN_INFO "%s: lp at 0x%p (%d bytes), lp->scb at 0x%p\n", - dev->name, lp, (int)sizeof(struct i596_private), &lp->scb)); - - return 0; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void i596_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - i596_interrupt(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -static irqreturn_t i596_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct i596_private *lp; - unsigned short status, ack_cmd = 0; - - if (dev == NULL) { - printk("%s: irq %d for unknown device.\n", __FUNCTION__, irq); - return IRQ_NONE; - } - - lp = dev->priv; - - spin_lock (&lp->lock); - - wait_cmd(dev, lp, 100, "i596 interrupt, timeout"); - status = lp->scb.status; - - DEB(DEB_INTS, printk("%s: i596 interrupt, IRQ %d, status %4.4x.\n", - dev->name, irq, status)); - - ack_cmd = status & 0xf000; - - if (!ack_cmd) { - DEB(DEB_ERRORS, printk("%s: interrupt with no events\n", dev->name)); - spin_unlock (&lp->lock); - return IRQ_NONE; - } - - if ((status & 0x8000) || (status & 0x2000)) { - struct i596_cmd *ptr; - - if ((status & 0x8000)) - DEB(DEB_INTS, printk("%s: i596 interrupt completed command.\n", dev->name)); - if ((status & 0x2000)) - DEB(DEB_INTS, printk("%s: i596 interrupt command unit inactive %x.\n", dev->name, status & 0x0700)); - - while (lp->cmd_head != NULL) { - CHECK_INV(lp, lp->cmd_head, sizeof(struct i596_cmd)); - if (!(lp->cmd_head->status & STAT_C)) - break; - - ptr = lp->cmd_head; - - DEB(DEB_STATUS, printk("cmd_head->status = %04x, ->command = %04x\n", - lp->cmd_head->status, lp->cmd_head->command)); - lp->cmd_head = ptr->v_next; - lp->cmd_backlog--; - - switch ((ptr->command) & 0x7) { - case CmdTx: - { - struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr; - struct sk_buff *skb = tx_cmd->skb; - - if ((ptr->status) & STAT_OK) { - DEB(DEB_TXADDR, print_eth(skb->data, "tx-done")); - } else { - lp->stats.tx_errors++; - if ((ptr->status) & 0x0020) - lp->stats.collisions++; - if (!((ptr->status) & 0x0040)) - lp->stats.tx_heartbeat_errors++; - if ((ptr->status) & 0x0400) - lp->stats.tx_carrier_errors++; - if ((ptr->status) & 0x0800) - lp->stats.collisions++; - if ((ptr->status) & 0x1000) - lp->stats.tx_aborted_errors++; - } - dma_unmap_single(lp->dev, tx_cmd->dma_addr, skb->len, DMA_TO_DEVICE); - dev_kfree_skb_irq(skb); - - tx_cmd->cmd.command = 0; /* Mark free */ - break; - } - case CmdTDR: - { - unsigned short status = ((struct tdr_cmd *)ptr)->status; - - if (status & 0x8000) { - DEB(DEB_ANY, printk("%s: link ok.\n", dev->name)); - } else { - if (status & 0x4000) - printk("%s: Transceiver problem.\n", dev->name); - if (status & 0x2000) - printk("%s: Termination problem.\n", dev->name); - if (status & 0x1000) - printk("%s: Short circuit.\n", dev->name); - - DEB(DEB_TDR, printk("%s: Time %d.\n", dev->name, status & 0x07ff)); - } - break; - } - case CmdConfigure: - /* Zap command so set_multicast_list() knows it is free */ - ptr->command = 0; - break; - } - ptr->v_next = NULL; - ptr->b_next = I596_NULL; - CHECK_WBACK(lp, ptr, sizeof(struct i596_cmd)); - lp->last_cmd = jiffies; - } - - /* This mess is arranging that only the last of any outstanding - * commands has the interrupt bit set. Should probably really - * only add to the cmd queue when the CU is stopped. - */ - ptr = lp->cmd_head; - while ((ptr != NULL) && (ptr != lp->cmd_tail)) { - struct i596_cmd *prev = ptr; - - ptr->command &= 0x1fff; - ptr = ptr->v_next; - CHECK_WBACK_INV(lp, prev, sizeof(struct i596_cmd)); - } - - if ((lp->cmd_head != NULL)) - ack_cmd |= CUC_START; - lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&lp->cmd_head->status)); - CHECK_WBACK_INV(lp, &lp->scb, sizeof(struct i596_scb)); - } - if ((status & 0x1000) || (status & 0x4000)) { - if ((status & 0x4000)) - DEB(DEB_INTS, printk("%s: i596 interrupt received a frame.\n", dev->name)); - i596_rx(dev); - /* Only RX_START if stopped - RGH 07-07-96 */ - if (status & 0x1000) { - if (netif_running(dev)) { - DEB(DEB_ERRORS, printk("%s: i596 interrupt receive unit inactive, status 0x%x\n", dev->name, status)); - ack_cmd |= RX_START; - lp->stats.rx_errors++; - lp->stats.rx_fifo_errors++; - rebuild_rx_bufs(dev); - } - } - } - wait_cmd(dev, lp, 100, "i596 interrupt, timeout"); - lp->scb.command = ack_cmd; - CHECK_WBACK(lp, &lp->scb, sizeof(struct i596_scb)); - - /* DANGER: I suspect that some kind of interrupt - acknowledgement aside from acking the 82596 might be needed - here... but it's running acceptably without */ - - CA(dev); - - wait_cmd(dev, lp, 100, "i596 interrupt, exit timeout"); - DEB(DEB_INTS, printk("%s: exiting interrupt.\n", dev->name)); - - spin_unlock (&lp->lock); - return IRQ_HANDLED; -} - -static int i596_close(struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - unsigned long flags; - - netif_stop_queue(dev); - - DEB(DEB_INIT, printk("%s: Shutting down ethercard, status was %4.4x.\n", - dev->name, lp->scb.status)); - - spin_lock_irqsave(&lp->lock, flags); - - wait_cmd(dev, lp, 100, "close1 timed out"); - lp->scb.command = CUC_ABORT | RX_ABORT; - CHECK_WBACK(lp, &lp->scb, sizeof(struct i596_scb)); - - CA(dev); - - wait_cmd(dev, lp, 100, "close2 timed out"); - spin_unlock_irqrestore(&lp->lock, flags); - DEB(DEB_STRUCT,i596_display_data(dev)); - i596_cleanup_cmd(dev,lp); - - disable_irq(dev->irq); - - free_irq(dev->irq, dev); - remove_rx_bufs(dev); - - return 0; -} - -static struct net_device_stats * - i596_get_stats(struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - - return &lp->stats; -} - -/* - * Set or clear the multicast filter for this adaptor. - */ - -static void set_multicast_list(struct net_device *dev) -{ - struct i596_private *lp = dev->priv; - int config = 0, cnt; - - DEB(DEB_MULTI, printk("%s: set multicast list, %d entries, promisc %s, allmulti %s\n", - dev->name, dev->mc_count, dev->flags & IFF_PROMISC ? "ON" : "OFF", - dev->flags & IFF_ALLMULTI ? "ON" : "OFF")); - - if ((dev->flags & IFF_PROMISC) && !(lp->cf_cmd.i596_config[8] & 0x01)) { - lp->cf_cmd.i596_config[8] |= 0x01; - config = 1; - } - if (!(dev->flags & IFF_PROMISC) && (lp->cf_cmd.i596_config[8] & 0x01)) { - lp->cf_cmd.i596_config[8] &= ~0x01; - config = 1; - } - if ((dev->flags & IFF_ALLMULTI) && (lp->cf_cmd.i596_config[11] & 0x20)) { - lp->cf_cmd.i596_config[11] &= ~0x20; - config = 1; - } - if (!(dev->flags & IFF_ALLMULTI) && !(lp->cf_cmd.i596_config[11] & 0x20)) { - lp->cf_cmd.i596_config[11] |= 0x20; - config = 1; - } - if (config) { - if (lp->cf_cmd.cmd.command) - printk("%s: config change request already queued\n", - dev->name); - else { - lp->cf_cmd.cmd.command = CmdConfigure; - CHECK_WBACK_INV(lp, &lp->cf_cmd, sizeof(struct cf_cmd)); - i596_add_cmd(dev, &lp->cf_cmd.cmd); - } - } - - cnt = dev->mc_count; - if (cnt > MAX_MC_CNT) - { - cnt = MAX_MC_CNT; - printk("%s: Only %d multicast addresses supported", - dev->name, cnt); - } - - if (dev->mc_count > 0) { - struct dev_mc_list *dmi; - unsigned char *cp; - struct mc_cmd *cmd; - - cmd = &lp->mc_cmd; - cmd->cmd.command = CmdMulticastList; - cmd->mc_cnt = dev->mc_count * 6; - cp = cmd->mc_addrs; - for (dmi = dev->mc_list; cnt && dmi != NULL; dmi = dmi->next, cnt--, cp += 6) { - memcpy(cp, dmi->dmi_addr, 6); - if (i596_debug > 1) - DEB(DEB_MULTI, printk("%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n", - dev->name, cp[0],cp[1],cp[2],cp[3],cp[4],cp[5])); - } - CHECK_WBACK_INV(lp, &lp->mc_cmd, sizeof(struct mc_cmd)); - i596_add_cmd(dev, &cmd->cmd); - } -} - -static int debug = -1; -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "lasi_82596 debug mask"); - -static int num_drivers; -static struct net_device *netdevs[MAX_DRIVERS]; - static int __devinit lan_init_chip(struct parisc_device *dev) { struct net_device *netdevice; + struct i596_private *lp; int retval; - - if (num_drivers >= MAX_DRIVERS) { - /* max count of possible i82596 drivers reached */ - return -ENOMEM; - } - - if (num_drivers == 0) - printk(KERN_INFO LASI_82596_DRIVER_VERSION "\n"); + int i; if (!dev->irq) { printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n", @@ -1527,28 +168,45 @@ lan_init_chip(struct parisc_device *dev) printk(KERN_INFO "Found i82596 at 0x%lx, IRQ %d\n", dev->hpa.start, dev->irq); - netdevice = alloc_etherdev(0); + netdevice = alloc_etherdev(sizeof(struct i596_private)); if (!netdevice) return -ENOMEM; + SET_NETDEV_DEV(netdevice, &dev->dev); + parisc_set_drvdata (dev, netdevice); netdevice->base_addr = dev->hpa.start; netdevice->irq = dev->irq; - retval = i82596_probe(netdevice, &dev->dev); + if (pdc_lan_station_id(netdevice->dev_addr, netdevice->base_addr)) { + for (i = 0; i < 6; i++) { + netdevice->dev_addr[i] = gsc_readb(LAN_PROM_ADDR + i); + } + printk(KERN_INFO + "%s: MAC of HP700 LAN read from EEPROM\n", __FILE__); + } + + lp = netdev_priv(netdevice); + lp->options = dev->id.sversion == 0x72 ? OPT_SWAP_PORT : 0; + + retval = i82596_probe(netdevice); if (retval) { free_netdev(netdevice); return -ENODEV; } - - if (dev->id.sversion == 0x72) { - ((struct i596_private *)netdevice->priv)->options = OPT_SWAP_PORT; - } - - netdevs[num_drivers++] = netdevice; - return retval; } +static int __devexit lan_remove_chip (struct parisc_device *pdev) +{ + struct net_device *dev = parisc_get_drvdata(pdev); + struct i596_private *lp = netdev_priv(dev); + + unregister_netdev (dev); + DMA_FREE(&pdev->dev, sizeof(struct i596_private), + (void *)lp->dma, lp->dma_addr); + free_netdev (dev); + return 0; +} static struct parisc_device_id lan_tbl[] = { { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008a }, @@ -1562,12 +220,12 @@ static struct parisc_driver lan_driver = { .name = "lasi_82596", .id_table = lan_tbl, .probe = lan_init_chip, + .remove = __devexit_p(lan_remove_chip), }; static int __devinit lasi_82596_init(void) { - if (debug >= 0) - i596_debug = debug; + printk(KERN_INFO LASI_82596_DRIVER_VERSION "\n"); return register_parisc_driver(&lan_driver); } @@ -1575,25 +233,6 @@ module_init(lasi_82596_init); static void __exit lasi_82596_exit(void) { - int i; - - for (i=0; i<MAX_DRIVERS; i++) { - struct i596_private *lp; - struct net_device *netdevice; - - netdevice = netdevs[i]; - if (!netdevice) - continue; - - unregister_netdev(netdevice); - - lp = netdevice->priv; - dma_free_noncoherent(lp->dev, sizeof(struct i596_private), - (void *)netdevice->mem_start, lp->dma_addr); - free_netdev(netdevice); - } - num_drivers = 0; - unregister_parisc_driver(&lan_driver); } diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c new file mode 100644 index 00000000000..5884f5bd04a --- /dev/null +++ b/drivers/net/lib82596.c @@ -0,0 +1,1434 @@ +/* lasi_82596.c -- driver for the intel 82596 ethernet controller, as + munged into HPPA boxen . + + This driver is based upon 82596.c, original credits are below... + but there were too many hoops which HP wants jumped through to + keep this code in there in a sane manner. + + 3 primary sources of the mess -- + 1) hppa needs *lots* of cacheline flushing to keep this kind of + MMIO running. + + 2) The 82596 needs to see all of its pointers as their physical + address. Thus virt_to_bus/bus_to_virt are *everywhere*. + + 3) The implementation HP is using seems to be significantly pickier + about when and how the command and RX units are started. some + command ordering was changed. + + Examination of the mach driver leads one to believe that there + might be a saner way to pull this off... anyone who feels like a + full rewrite can be my guest. + + Split 02/13/2000 Sam Creasey (sammy@oh.verio.com) + + 02/01/2000 Initial modifications for parisc by Helge Deller (deller@gmx.de) + 03/02/2000 changes for better/correct(?) cache-flushing (deller) +*/ + +/* 82596.c: A generic 82596 ethernet driver for linux. */ +/* + Based on Apricot.c + Written 1994 by Mark Evans. + This driver is for the Apricot 82596 bus-master interface + + Modularised 12/94 Mark Evans + + + Modified to support the 82596 ethernet chips on 680x0 VME boards. + by Richard Hirst <richard@sleepie.demon.co.uk> + Renamed to be 82596.c + + 980825: Changed to receive directly in to sk_buffs which are + allocated at open() time. Eliminates copy on incoming frames + (small ones are still copied). Shared data now held in a + non-cached page, so we can run on 68060 in copyback mode. + + TBD: + * look at deferring rx frames rather than discarding (as per tulip) + * handle tx ring full as per tulip + * performace test to tune rx_copybreak + + Most of my modifications relate to the braindead big-endian + implementation by Intel. When the i596 is operating in + 'big-endian' mode, it thinks a 32 bit value of 0x12345678 + should be stored as 0x56781234. This is a real pain, when + you have linked lists which are shared by the 680x0 and the + i596. + + Driver skeleton + Written 1993 by Donald Becker. + Copyright 1993 United States Government as represented by the Director, + National Security Agency. This software may only be used and distributed + according to the terms of the GNU General Public License as modified by SRC, + incorporated herein by reference. + + The author may be reached as becker@scyld.com, or C/O + Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403 + + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/errno.h> +#include <linux/ioport.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/skbuff.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/bitops.h> +#include <linux/dma-mapping.h> +#include <linux/io.h> +#include <linux/irq.h> + +/* DEBUG flags + */ + +#define DEB_INIT 0x0001 +#define DEB_PROBE 0x0002 +#define DEB_SERIOUS 0x0004 +#define DEB_ERRORS 0x0008 +#define DEB_MULTI 0x0010 +#define DEB_TDR 0x0020 +#define DEB_OPEN 0x0040 +#define DEB_RESET 0x0080 +#define DEB_ADDCMD 0x0100 +#define DEB_STATUS 0x0200 +#define DEB_STARTTX 0x0400 +#define DEB_RXADDR 0x0800 +#define DEB_TXADDR 0x1000 +#define DEB_RXFRAME 0x2000 +#define DEB_INTS 0x4000 +#define DEB_STRUCT 0x8000 +#define DEB_ANY 0xffff + + +#define DEB(x, y) if (i596_debug & (x)) { y; } + + +/* + * The MPU_PORT command allows direct access to the 82596. With PORT access + * the following commands are available (p5-18). The 32-bit port command + * must be word-swapped with the most significant word written first. + * This only applies to VME boards. + */ +#define PORT_RESET 0x00 /* reset 82596 */ +#define PORT_SELFTEST 0x01 /* selftest */ +#define PORT_ALTSCP 0x02 /* alternate SCB address */ +#define PORT_ALTDUMP 0x03 /* Alternate DUMP address */ + +static int i596_debug = (DEB_SERIOUS|DEB_PROBE); + +/* Copy frames shorter than rx_copybreak, otherwise pass on up in + * a full sized sk_buff. Value of 100 stolen from tulip.c (!alpha). + */ +static int rx_copybreak = 100; + +#define PKT_BUF_SZ 1536 +#define MAX_MC_CNT 64 + +#define ISCP_BUSY 0x0001 + +#define I596_NULL ((u32)0xffffffff) + +#define CMD_EOL 0x8000 /* The last command of the list, stop. */ +#define CMD_SUSP 0x4000 /* Suspend after doing cmd. */ +#define CMD_INTR 0x2000 /* Interrupt after doing cmd. */ + +#define CMD_FLEX 0x0008 /* Enable flexible memory model */ + +enum commands { + CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3, + CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7 +}; + +#define STAT_C 0x8000 /* Set to 0 after execution */ +#define STAT_B 0x4000 /* Command being executed */ +#define STAT_OK 0x2000 /* Command executed ok */ +#define STAT_A 0x1000 /* Command aborted */ + +#define CUC_START 0x0100 +#define CUC_RESUME 0x0200 +#define CUC_SUSPEND 0x0300 +#define CUC_ABORT 0x0400 +#define RX_START 0x0010 +#define RX_RESUME 0x0020 +#define RX_SUSPEND 0x0030 +#define RX_ABORT 0x0040 + +#define TX_TIMEOUT 5 + + +struct i596_reg { + unsigned short porthi; + unsigned short portlo; + u32 ca; +}; + +#define EOF 0x8000 +#define SIZE_MASK 0x3fff + +struct i596_tbd { + unsigned short size; + unsigned short pad; + dma_addr_t next; + dma_addr_t data; + u32 cache_pad[5]; /* Total 32 bytes... */ +}; + +/* The command structure has two 'next' pointers; v_next is the address of + * the next command as seen by the CPU, b_next is the address of the next + * command as seen by the 82596. The b_next pointer, as used by the 82596 + * always references the status field of the next command, rather than the + * v_next field, because the 82596 is unaware of v_next. It may seem more + * logical to put v_next at the end of the structure, but we cannot do that + * because the 82596 expects other fields to be there, depending on command + * type. + */ + +struct i596_cmd { + struct i596_cmd *v_next; /* Address from CPUs viewpoint */ + unsigned short status; + unsigned short command; + dma_addr_t b_next; /* Address from i596 viewpoint */ +}; + +struct tx_cmd { + struct i596_cmd cmd; + dma_addr_t tbd; + unsigned short size; + unsigned short pad; + struct sk_buff *skb; /* So we can free it after tx */ + dma_addr_t dma_addr; +#ifdef __LP64__ + u32 cache_pad[6]; /* Total 64 bytes... */ +#else + u32 cache_pad[1]; /* Total 32 bytes... */ +#endif +}; + +struct tdr_cmd { + struct i596_cmd cmd; + unsigned short status; + unsigned short pad; +}; + +struct mc_cmd { + struct i596_cmd cmd; + short mc_cnt; + char mc_addrs[MAX_MC_CNT*6]; +}; + +struct sa_cmd { + struct i596_cmd cmd; + char eth_addr[8]; +}; + +struct cf_cmd { + struct i596_cmd cmd; + char i596_config[16]; +}; + +struct i596_rfd { + unsigned short stat; + unsigned short cmd; + dma_addr_t b_next; /* Address from i596 viewpoint */ + dma_addr_t rbd; + unsigned short count; + unsigned short size; + struct i596_rfd *v_next; /* Address from CPUs viewpoint */ + struct i596_rfd *v_prev; +#ifndef __LP64__ + u32 cache_pad[2]; /* Total 32 bytes... */ +#endif +}; + +struct i596_rbd { + /* hardware data */ + unsigned short count; + unsigned short zero1; + dma_addr_t b_next; + dma_addr_t b_data; /* Address from i596 viewpoint */ + unsigned short size; + unsigned short zero2; + /* driver data */ + struct sk_buff *skb; + struct i596_rbd *v_next; + dma_addr_t b_addr; /* This rbd addr from i596 view */ + unsigned char *v_data; /* Address from CPUs viewpoint */ + /* Total 32 bytes... */ +#ifdef __LP64__ + u32 cache_pad[4]; +#endif +}; + +/* These values as chosen so struct i596_dma fits in one page... */ + +#define TX_RING_SIZE 32 +#define RX_RING_SIZE 16 + +struct i596_scb { + unsigned short status; + unsigned short command; + dma_addr_t cmd; + dma_addr_t rfd; + u32 crc_err; + u32 align_err; + u32 resource_err; + u32 over_err; + u32 rcvdt_err; + u32 short_err; + unsigned short t_on; + unsigned short t_off; +}; + +struct i596_iscp { + u32 stat; + dma_addr_t scb; +}; + +struct i596_scp { + u32 sysbus; + u32 pad; + dma_addr_t iscp; +}; + +struct i596_dma { + struct i596_scp scp __attribute__((aligned(32))); + volatile struct i596_iscp iscp __attribute__((aligned(32))); + volatile struct i596_scb scb __attribute__((aligned(32))); + struct sa_cmd sa_cmd __attribute__((aligned(32))); + struct cf_cmd cf_cmd __attribute__((aligned(32))); + struct tdr_cmd tdr_cmd __attribute__((aligned(32))); + struct mc_cmd mc_cmd __attribute__((aligned(32))); + struct i596_rfd rfds[RX_RING_SIZE] __attribute__((aligned(32))); + struct i596_rbd rbds[RX_RING_SIZE] __attribute__((aligned(32))); + struct tx_cmd tx_cmds[TX_RING_SIZE] __attribute__((aligned(32))); + struct i596_tbd tbds[TX_RING_SIZE] __attribute__((aligned(32))); +}; + +struct i596_private { + struct i596_dma *dma; + u32 stat; + int last_restart; + struct i596_rfd *rfd_head; + struct i596_rbd *rbd_head; + struct i596_cmd *cmd_tail; + struct i596_cmd *cmd_head; + int cmd_backlog; + u32 last_cmd; + struct net_device_stats stats; + int next_tx_cmd; + int options; + spinlock_t lock; /* serialize access to chip */ + dma_addr_t dma_addr; + void __iomem *mpu_port; + void __iomem *ca; +}; + +static const char init_setup[] = +{ + 0x8E, /* length, prefetch on */ + 0xC8, /* fifo to 8, monitor off */ + 0x80, /* don't save bad frames */ + 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 */ + 0x00, /* promiscuous mode */ + 0x00, /* collision detect */ + 0x40, /* minimum frame length */ + 0xff, + 0x00, + 0x7f /* *multi IA */ }; + +static int i596_open(struct net_device *dev); +static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev); +static irqreturn_t i596_interrupt(int irq, void *dev_id); +static int i596_close(struct net_device *dev); +static struct net_device_stats *i596_get_stats(struct net_device *dev); +static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd); +static void i596_tx_timeout (struct net_device *dev); +static void print_eth(unsigned char *buf, char *str); +static void set_multicast_list(struct net_device *dev); +static inline void ca(struct net_device *dev); +static void mpu_port(struct net_device *dev, int c, dma_addr_t x); + +static int rx_ring_size = RX_RING_SIZE; +static int ticks_limit = 100; +static int max_cmd_backlog = TX_RING_SIZE-1; + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void i596_poll_controller(struct net_device *dev); +#endif + + +static inline int wait_istat(struct net_device *dev, struct i596_dma *dma, int delcnt, char *str) +{ + DMA_INV(dev, &(dma->iscp), sizeof(struct i596_iscp)); + while (--delcnt && dma->iscp.stat) { + udelay(10); + DMA_INV(dev, &(dma->iscp), sizeof(struct i596_iscp)); + } + if (!delcnt) { + printk(KERN_ERR "%s: %s, iscp.stat %04x, didn't clear\n", + dev->name, str, SWAP16(dma->iscp.stat)); + return -1; + } else + return 0; +} + + +static inline int wait_cmd(struct net_device *dev, struct i596_dma *dma, int delcnt, char *str) +{ + DMA_INV(dev, &(dma->scb), sizeof(struct i596_scb)); + while (--delcnt && dma->scb.command) { + udelay(10); + DMA_INV(dev, &(dma->scb), sizeof(struct i596_scb)); + } + if (!delcnt) { + printk(KERN_ERR "%s: %s, status %4.4x, cmd %4.4x.\n", + dev->name, str, + SWAP16(dma->scb.status), + SWAP16(dma->scb.command)); + return -1; + } else + return 0; +} + + +static void i596_display_data(struct net_device *dev) +{ + struct i596_private *lp = netdev_priv(dev); + struct i596_dma *dma = lp->dma; + struct i596_cmd *cmd; + struct i596_rfd *rfd; + struct i596_rbd *rbd; + + printk(KERN_DEBUG "lp and scp at %p, .sysbus = %08x, .iscp = %08x\n", + &dma->scp, dma->scp.sysbus, SWAP32(dma->scp.iscp)); + printk(KERN_DEBUG "iscp at %p, iscp.stat = %08x, .scb = %08x\n", + &dma->iscp, SWAP32(dma->iscp.stat), SWAP32(dma->iscp.scb)); + printk(KERN_DEBUG "scb at %p, scb.status = %04x, .command = %04x," + " .cmd = %08x, .rfd = %08x\n", + &dma->scb, SWAP16(dma->scb.status), SWAP16(dma->scb.command), + SWAP16(dma->scb.cmd), SWAP32(dma->scb.rfd)); + printk(KERN_DEBUG " errors: crc %x, align %x, resource %x," + " over %x, rcvdt %x, short %x\n", + SWAP32(dma->scb.crc_err), SWAP32(dma->scb.align_err), + SWAP32(dma->scb.resource_err), SWAP32(dma->scb.over_err), + SWAP32(dma->scb.rcvdt_err), SWAP32(dma->scb.short_err)); + cmd = lp->cmd_head; + while (cmd != NULL) { + printk(KERN_DEBUG + "cmd at %p, .status = %04x, .command = %04x," + " .b_next = %08x\n", + cmd, SWAP16(cmd->status), SWAP16(cmd->command), + SWAP32(cmd->b_next)); + cmd = cmd->v_next; + } + rfd = lp->rfd_head; + printk(KERN_DEBUG "rfd_head = %p\n", rfd); + do { + printk(KERN_DEBUG + " %p .stat %04x, .cmd %04x, b_next %08x, rbd %08x," + " count %04x\n", + rfd, SWAP16(rfd->stat), SWAP16(rfd->cmd), + SWAP32(rfd->b_next), SWAP32(rfd->rbd), + SWAP16(rfd->count)); + rfd = rfd->v_next; + } while (rfd != lp->rfd_head); + rbd = lp->rbd_head; + printk(KERN_DEBUG "rbd_head = %p\n", rbd); + do { + printk(KERN_DEBUG + " %p .count %04x, b_next %08x, b_data %08x," + " size %04x\n", + rbd, SWAP16(rbd->count), SWAP32(rbd->b_next), + SWAP32(rbd->b_data), SWAP16(rbd->size)); + rbd = rbd->v_next; + } while (rbd != lp->rbd_head); + DMA_INV(dev, dma, sizeof(struct i596_dma)); +} + + +#define virt_to_dma(lp, v) ((lp)->dma_addr + (dma_addr_t)((unsigned long)(v)-(unsigned long)((lp)->dma))) + +static inline int init_rx_bufs(struct net_device *dev) +{ + struct i596_private *lp = netdev_priv(dev); + struct i596_dma *dma = lp->dma; + int i; + struct i596_rfd *rfd; + struct i596_rbd *rbd; + + /* First build the Receive Buffer Descriptor List */ + + for (i = 0, rbd = dma->rbds; i < rx_ring_size; i++, rbd++) { + dma_addr_t dma_addr; + struct sk_buff *skb = netdev_alloc_skb(dev, PKT_BUF_SZ + 4); + + if (skb == NULL) + return -1; + skb_reserve(skb, 2); + dma_addr = dma_map_single(dev->dev.parent, skb->data, + PKT_BUF_SZ, DMA_FROM_DEVICE); + rbd->v_next = rbd+1; + rbd->b_next = SWAP32(virt_to_dma(lp, rbd+1)); + rbd->b_addr = SWAP32(virt_to_dma(lp, rbd)); + rbd->skb = skb; + rbd->v_data = skb->data; + rbd->b_data = SWAP32(dma_addr); + rbd->size = SWAP16(PKT_BUF_SZ); + } + lp->rbd_head = dma->rbds; + rbd = dma->rbds + rx_ring_size - 1; + rbd->v_next = dma->rbds; + rbd->b_next = SWAP32(virt_to_dma(lp, dma->rbds)); + + /* Now build the Receive Frame Descriptor List */ + + for (i = 0, rfd = dma->rfds; i < rx_ring_size; i++, rfd++) { + rfd->rbd = I596_NULL; + rfd->v_next = rfd+1; + rfd->v_prev = rfd-1; + rfd->b_next = SWAP32(virt_to_dma(lp, rfd+1)); + rfd->cmd = SWAP16(CMD_FLEX); + } + lp->rfd_head = dma->rfds; + dma->scb.rfd = SWAP32(virt_to_dma(lp, dma->rfds)); + rfd = dma->rfds; + rfd->rbd = SWAP32(virt_to_dma(lp, lp->rbd_head)); + rfd->v_prev = dma->rfds + rx_ring_size - 1; + rfd = dma->rfds + rx_ring_size - 1; + rfd->v_next = dma->rfds; + rfd->b_next = SWAP32(virt_to_dma(lp, dma->rfds)); + rfd->cmd = SWAP16(CMD_EOL|CMD_FLEX); + + DMA_WBACK_INV(dev, dma, sizeof(struct i596_dma)); + return 0; +} + +static inline void remove_rx_bufs(struct net_device *dev) +{ + struct i596_private *lp = netdev_priv(dev); + struct i596_rbd *rbd; + int i; + + for (i = 0, rbd = lp->dma->rbds; i < rx_ring_size; i++, rbd++) { + if (rbd->skb == NULL) + break; + dma_unmap_single(dev->dev.parent, + (dma_addr_t)SWAP32(rbd->b_data), + PKT_BUF_SZ, DMA_FROM_DEVICE); + dev_kfree_skb(rbd->skb); + } +} + + +static void rebuild_rx_bufs(struct net_device *dev) +{ + struct i596_private *lp = netdev_priv(dev); + struct i596_dma *dma = lp->dma; + int i; + + /* Ensure rx frame/buffer descriptors are tidy */ + + for (i = 0; i < rx_ring_size; i++) { + dma->rfds[i].rbd = I596_NULL; + dma->rfds[i].cmd = SWAP16(CMD_FLEX); + } + dma->rfds[rx_ring_size-1].cmd = SWAP16(CMD_EOL|CMD_FLEX); + lp->rfd_head = dma->rfds; + dma->scb.rfd = SWAP32(virt_to_dma(lp, dma->rfds)); + lp->rbd_head = dma->rbds; + dma->rfds[0].rbd = SWAP32(virt_to_dma(lp, dma->rbds)); + + DMA_WBACK_INV(dev, dma, sizeof(struct i596_dma)); +} + + +static int init_i596_mem(struct net_device *dev) +{ + struct i596_private *lp = netdev_priv(dev); + struct i596_dma *dma = lp->dma; + unsigned long flags; + + mpu_port(dev, PORT_RESET, 0); + udelay(100); /* Wait 100us - seems to help */ + + /* change the scp address */ + + lp->last_cmd = jiffies; + + dma->scp.sysbus = SYSBUS; + dma->scp.iscp = SWAP32(virt_to_dma(lp, &(dma->iscp))); + dma->iscp.scb = SWAP32(virt_to_dma(lp, &(dma->scb))); + dma->iscp.stat = SWAP32(ISCP_BUSY); + lp->cmd_backlog = 0; + + lp->cmd_head = NULL; + dma->scb.cmd = I596_NULL; + + DEB(DEB_INIT, printk(KERN_DEBUG "%s: starting i82596.\n", dev->name)); + + DMA_WBACK(dev, &(dma->scp), sizeof(struct i596_scp)); + DMA_WBACK(dev, &(dma->iscp), sizeof(struct i596_iscp)); + DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb)); + + mpu_port(dev, PORT_ALTSCP, virt_to_dma(lp, &dma->scp)); + ca(dev); + if (wait_istat(dev, dma, 1000, "initialization timed out")) + goto failed; + DEB(DEB_INIT, printk(KERN_DEBUG + "%s: i82596 initialization successful\n", + dev->name)); + + if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev)) { + printk(KERN_ERR "%s: IRQ %d not free\n", dev->name, dev->irq); + goto failed; + } + + /* Ensure rx frame/buffer descriptors are tidy */ + rebuild_rx_bufs(dev); + + dma->scb.command = 0; + DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb)); + + DEB(DEB_INIT, printk(KERN_DEBUG + "%s: queuing CmdConfigure\n", dev->name)); + memcpy(dma->cf_cmd.i596_config, init_setup, 14); + dma->cf_cmd.cmd.command = SWAP16(CmdConfigure); + DMA_WBACK(dev, &(dma->cf_cmd), sizeof(struct cf_cmd)); + i596_add_cmd(dev, &dma->cf_cmd.cmd); + + DEB(DEB_INIT, printk(KERN_DEBUG "%s: queuing CmdSASetup\n", dev->name)); + memcpy(dma->sa_cmd.eth_addr, dev->dev_addr, 6); + dma->sa_cmd.cmd.command = SWAP16(CmdSASetup); + DMA_WBACK(dev, &(dma->sa_cmd), sizeof(struct sa_cmd)); + i596_add_cmd(dev, &dma->sa_cmd.cmd); + + DEB(DEB_INIT, printk(KERN_DEBUG "%s: queuing CmdTDR\n", dev->name)); + dma->tdr_cmd.cmd.command = SWAP16(CmdTDR); + DMA_WBACK(dev, &(dma->tdr_cmd), sizeof(struct tdr_cmd)); + i596_add_cmd(dev, &dma->tdr_cmd.cmd); + + spin_lock_irqsave (&lp->lock, flags); + + if (wait_cmd(dev, dma, 1000, "timed out waiting to issue RX_START")) { + spin_unlock_irqrestore (&lp->lock, flags); + goto failed_free_irq; + } + DEB(DEB_INIT, printk(KERN_DEBUG "%s: Issuing RX_START\n", dev->name)); + dma->scb.command = SWAP16(RX_START); + dma->scb.rfd = SWAP32(virt_to_dma(lp, dma->rfds)); + DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb)); + + ca(dev); + + spin_unlock_irqrestore (&lp->lock, flags); + if (wait_cmd(dev, dma, 1000, "RX_START not processed")) + goto failed_free_irq; + DEB(DEB_INIT, printk(KERN_DEBUG + "%s: Receive unit started OK\n", dev->name)); + return 0; + +failed_free_irq: + free_irq(dev->irq, dev); +failed: + printk(KERN_ERR "%s: Failed to initialise 82596\n", dev->name); + mpu_port(dev, PORT_RESET, 0); + return -1; +} + + +static inline int i596_rx(struct net_device *dev) +{ + struct i596_private *lp = netdev_priv(dev); + struct i596_rfd *rfd; + struct i596_rbd *rbd; + int frames = 0; + + DEB(DEB_RXFRAME, printk(KERN_DEBUG + "i596_rx(), rfd_head %p, rbd_head %p\n", + lp->rfd_head, lp->rbd_head)); + + + rfd = lp->rfd_head; /* Ref next frame to check */ + + DMA_INV(dev, rfd, sizeof(struct i596_rfd)); + while (rfd->stat & SWAP16(STAT_C)) { /* Loop while complete frames */ + if (rfd->rbd == I596_NULL) + rbd = NULL; + else if (rfd->rbd == lp->rbd_head->b_addr) { + rbd = lp->rbd_head; + DMA_INV(dev, rbd, sizeof(struct i596_rbd)); + } else { + printk(KERN_ERR "%s: rbd chain broken!\n", dev->name); + /* XXX Now what? */ + rbd = NULL; + } + DEB(DEB_RXFRAME, printk(KERN_DEBUG + " rfd %p, rfd.rbd %08x, rfd.stat %04x\n", + rfd, rfd->rbd, rfd->stat)); + + if (rbd != NULL && (rfd->stat & SWAP16(STAT_OK))) { + /* a good frame */ + int pkt_len = SWAP16(rbd->count) & 0x3fff; + struct sk_buff *skb = rbd->skb; + int rx_in_place = 0; + + DEB(DEB_RXADDR, print_eth(rbd->v_data, "received")); + frames++; + + /* Check if the packet is long enough to just accept + * without copying to a properly sized skbuff. + */ + + if (pkt_len > rx_copybreak) { + struct sk_buff *newskb; + dma_addr_t dma_addr; + + dma_unmap_single(dev->dev.parent, + (dma_addr_t)SWAP32(rbd->b_data), + PKT_BUF_SZ, DMA_FROM_DEVICE); + /* Get fresh skbuff to replace filled one. */ + newskb = netdev_alloc_skb(dev, PKT_BUF_SZ + 4); + if (newskb == NULL) { + skb = NULL; /* drop pkt */ + goto memory_squeeze; + } + skb_reserve(newskb, 2); + + /* Pass up the skb already on the Rx ring. */ + skb_put(skb, pkt_len); + rx_in_place = 1; + rbd->skb = newskb; + dma_addr = dma_map_single(dev->dev.parent, + newskb->data, + PKT_BUF_SZ, + DMA_FROM_DEVICE); + rbd->v_data = newskb->data; + rbd->b_data = SWAP32(dma_addr); + DMA_WBACK_INV(dev, rbd, sizeof(struct i596_rbd)); + } else + skb = netdev_alloc_skb(dev, pkt_len + 2); +memory_squeeze: + if (skb == NULL) { + /* XXX tulip.c can defer packets here!! */ + printk(KERN_ERR + "%s: i596_rx Memory squeeze, dropping packet.\n", + dev->name); + lp->stats.rx_dropped++; + } else { + if (!rx_in_place) { + /* 16 byte align the data fields */ + dma_sync_single_for_cpu(dev->dev.parent, + (dma_addr_t)SWAP32(rbd->b_data), + PKT_BUF_SZ, DMA_FROM_DEVICE); + skb_reserve(skb, 2); + memcpy(skb_put(skb, pkt_len), rbd->v_data, pkt_len); + dma_sync_single_for_device(dev->dev.parent, + (dma_addr_t)SWAP32(rbd->b_data), + PKT_BUF_SZ, DMA_FROM_DEVICE); + } + skb->len = pkt_len; + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + dev->last_rx = jiffies; + lp->stats.rx_packets++; + lp->stats.rx_bytes += pkt_len; + } + } else { + DEB(DEB_ERRORS, printk(KERN_DEBUG + "%s: Error, rfd.stat = 0x%04x\n", + dev->name, rfd->stat)); + lp->stats.rx_errors++; + if (rfd->stat & SWAP16(0x0100)) + lp->stats.collisions++; + if (rfd->stat & SWAP16(0x8000)) + lp->stats.rx_length_errors++; + if (rfd->stat & SWAP16(0x0001)) + lp->stats.rx_over_errors++; + if (rfd->stat & SWAP16(0x0002)) + lp->stats.rx_fifo_errors++; + if (rfd->stat & SWAP16(0x0004)) + lp->stats.rx_frame_errors++; + if (rfd->stat & SWAP16(0x0008)) + lp->stats.rx_crc_errors++; + if (rfd->stat & SWAP16(0x0010)) + lp->stats.rx_length_errors++; + } + + /* Clear the buffer descriptor count and EOF + F flags */ + + if (rbd != NULL && (rbd->count & SWAP16(0x4000))) { + rbd->count = 0; + lp->rbd_head = rbd->v_next; + DMA_WBACK_INV(dev, rbd, sizeof(struct i596_rbd)); + } + + /* Tidy the frame descriptor, marking it as end of list */ + + rfd->rbd = I596_NULL; + rfd->stat = 0; + rfd->cmd = SWAP16(CMD_EOL|CMD_FLEX); + rfd->count = 0; + + /* Update record of next frame descriptor to process */ + + lp->dma->scb.rfd = rfd->b_next; + lp->rfd_head = rfd->v_next; + DMA_WBACK_INV(dev, rfd, sizeof(struct i596_rfd)); + + /* Remove end-of-list from old end descriptor */ + + rfd->v_prev->cmd = SWAP16(CMD_FLEX); + DMA_WBACK_INV(dev, rfd->v_prev, sizeof(struct i596_rfd)); + rfd = lp->rfd_head; + DMA_INV(dev, rfd, sizeof(struct i596_rfd)); + } + + DEB(DEB_RXFRAME, printk(KERN_DEBUG "frames %d\n", frames)); + + return 0; +} + + +static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp) +{ + struct i596_cmd *ptr; + + while (lp->cmd_head != NULL) { + ptr = lp->cmd_head; + lp->cmd_head = ptr->v_next; + lp->cmd_backlog--; + + switch (SWAP16(ptr->command) & 0x7) { + case CmdTx: + { + struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr; + struct sk_buff *skb = tx_cmd->skb; + dma_unmap_single(dev->dev.parent, + tx_cmd->dma_addr, + skb->len, DMA_TO_DEVICE); + + dev_kfree_skb(skb); + + lp->stats.tx_errors++; + lp->stats.tx_aborted_errors++; + + ptr->v_next = NULL; + ptr->b_next = I596_NULL; + tx_cmd->cmd.command = 0; /* Mark as free */ + break; + } + default: + ptr->v_next = NULL; + ptr->b_next = I596_NULL; + } + DMA_WBACK_INV(dev, ptr, sizeof(struct i596_cmd)); + } + + wait_cmd(dev, lp->dma, 100, "i596_cleanup_cmd timed out"); + lp->dma->scb.cmd = I596_NULL; + DMA_WBACK(dev, &(lp->dma->scb), sizeof(struct i596_scb)); +} + + +static inline void i596_reset(struct net_device *dev, struct i596_private *lp) +{ + unsigned long flags; + + DEB(DEB_RESET, printk(KERN_DEBUG "i596_reset\n")); + + spin_lock_irqsave (&lp->lock, flags); + + wait_cmd(dev, lp->dma, 100, "i596_reset timed out"); + + netif_stop_queue(dev); + + /* FIXME: this command might cause an lpmc */ + lp->dma->scb.command = SWAP16(CUC_ABORT | RX_ABORT); + DMA_WBACK(dev, &(lp->dma->scb), sizeof(struct i596_scb)); + ca(dev); + + /* wait for shutdown */ + wait_cmd(dev, lp->dma, 1000, "i596_reset 2 timed out"); + spin_unlock_irqrestore (&lp->lock, flags); + + i596_cleanup_cmd(dev, lp); + i596_rx(dev); + + netif_start_queue(dev); + init_i596_mem(dev); +} + + +static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd) +{ + struct i596_private *lp = netdev_priv(dev); + struct i596_dma *dma = lp->dma; + unsigned long flags; + + DEB(DEB_ADDCMD, printk(KERN_DEBUG "i596_add_cmd cmd_head %p\n", + lp->cmd_head)); + + cmd->status = 0; + cmd->command |= SWAP16(CMD_EOL | CMD_INTR); + cmd->v_next = NULL; + cmd->b_next = I596_NULL; + DMA_WBACK(dev, cmd, sizeof(struct i596_cmd)); + + spin_lock_irqsave (&lp->lock, flags); + + if (lp->cmd_head != NULL) { + lp->cmd_tail->v_next = cmd; + lp->cmd_tail->b_next = SWAP32(virt_to_dma(lp, &cmd->status)); + DMA_WBACK(dev, lp->cmd_tail, sizeof(struct i596_cmd)); + } else { + lp->cmd_head = cmd; + wait_cmd(dev, dma, 100, "i596_add_cmd timed out"); + dma->scb.cmd = SWAP32(virt_to_dma(lp, &cmd->status)); + dma->scb.command = SWAP16(CUC_START); + DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb)); + ca(dev); + } + lp->cmd_tail = cmd; + lp->cmd_backlog++; + + spin_unlock_irqrestore (&lp->lock, flags); + + if (lp->cmd_backlog > max_cmd_backlog) { + unsigned long tickssofar = jiffies - lp->last_cmd; + + if (tickssofar < ticks_limit) + return; + + printk(KERN_ERR + "%s: command unit timed out, status resetting.\n", + dev->name); +#if 1 + i596_reset(dev, lp); +#endif + } +} + +static int i596_open(struct net_device *dev) +{ + DEB(DEB_OPEN, printk(KERN_DEBUG + "%s: i596_open() irq %d.\n", dev->name, dev->irq)); + + if (init_rx_bufs(dev)) { + printk(KERN_ERR "%s: Failed to init rx bufs\n", dev->name); + return -EAGAIN; + } + if (init_i596_mem(dev)) { + printk(KERN_ERR "%s: Failed to init memory\n", dev->name); + goto out_remove_rx_bufs; + } + netif_start_queue(dev); + + return 0; + +out_remove_rx_bufs: + remove_rx_bufs(dev); + return -EAGAIN; +} + +static void i596_tx_timeout (struct net_device *dev) +{ + struct i596_private *lp = netdev_priv(dev); + + /* Transmitter timeout, serious problems. */ + DEB(DEB_ERRORS, printk(KERN_DEBUG + "%s: transmit timed out, status resetting.\n", + dev->name)); + + lp->stats.tx_errors++; + + /* Try to restart the adaptor */ + if (lp->last_restart == lp->stats.tx_packets) { + DEB(DEB_ERRORS, printk(KERN_DEBUG "Resetting board.\n")); + /* Shutdown and restart */ + i596_reset (dev, lp); + } else { + /* Issue a channel attention signal */ + DEB(DEB_ERRORS, printk(KERN_DEBUG "Kicking board.\n")); + lp->dma->scb.command = SWAP16(CUC_START | RX_START); + DMA_WBACK_INV(dev, &(lp->dma->scb), sizeof(struct i596_scb)); + ca (dev); + lp->last_restart = lp->stats.tx_packets; + } + + dev->trans_start = jiffies; + netif_wake_queue (dev); +} + + +static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct i596_private *lp = netdev_priv(dev); + struct tx_cmd *tx_cmd; + struct i596_tbd *tbd; + short length = skb->len; + dev->trans_start = jiffies; + + DEB(DEB_STARTTX, printk(KERN_DEBUG + "%s: i596_start_xmit(%x,%p) called\n", + dev->name, skb->len, skb->data)); + + if (length < ETH_ZLEN) { + if (skb_padto(skb, ETH_ZLEN)) + return 0; + length = ETH_ZLEN; + } + + netif_stop_queue(dev); + + tx_cmd = lp->dma->tx_cmds + lp->next_tx_cmd; + tbd = lp->dma->tbds + lp->next_tx_cmd; + + if (tx_cmd->cmd.command) { + DEB(DEB_ERRORS, printk(KERN_DEBUG + "%s: xmit ring full, dropping packet.\n", + dev->name)); + lp->stats.tx_dropped++; + + dev_kfree_skb(skb); + } else { + if (++lp->next_tx_cmd == TX_RING_SIZE) + lp->next_tx_cmd = 0; + tx_cmd->tbd = SWAP32(virt_to_dma(lp, tbd)); + tbd->next = I596_NULL; + + tx_cmd->cmd.command = SWAP16(CMD_FLEX | CmdTx); + tx_cmd->skb = skb; + + tx_cmd->pad = 0; + tx_cmd->size = 0; + tbd->pad = 0; + tbd->size = SWAP16(EOF | length); + + tx_cmd->dma_addr = dma_map_single(dev->dev.parent, skb->data, + skb->len, DMA_TO_DEVICE); + tbd->data = SWAP32(tx_cmd->dma_addr); + + DEB(DEB_TXADDR, print_eth(skb->data, "tx-queued")); + DMA_WBACK_INV(dev, tx_cmd, sizeof(struct tx_cmd)); + DMA_WBACK_INV(dev, tbd, sizeof(struct i596_tbd)); + i596_add_cmd(dev, &tx_cmd->cmd); + + lp->stats.tx_packets++; + lp->stats.tx_bytes += length; + } + + netif_start_queue(dev); + + return 0; +} + +static void print_eth(unsigned char *add, char *str) +{ + int i; + + printk(KERN_DEBUG "i596 0x%p, ", add); + for (i = 0; i < 6; i++) + printk(" %02X", add[i + 6]); + printk(" -->"); + for (i = 0; i < 6; i++) + printk(" %02X", add[i]); + printk(" %02X%02X, %s\n", add[12], add[13], str); +} + +static int __devinit i82596_probe(struct net_device *dev) +{ + int i; + struct i596_private *lp = netdev_priv(dev); + struct i596_dma *dma; + + /* This lot is ensure things have been cache line aligned. */ + BUILD_BUG_ON(sizeof(struct i596_rfd) != 32); + BUILD_BUG_ON(sizeof(struct i596_rbd) & 31); + BUILD_BUG_ON(sizeof(struct tx_cmd) & 31); + BUILD_BUG_ON(sizeof(struct i596_tbd) != 32); +#ifndef __LP64__ + BUILD_BUG_ON(sizeof(struct i596_dma) > 4096); +#endif + + if (!dev->base_addr || !dev->irq) + return -ENODEV; + + dma = (struct i596_dma *) DMA_ALLOC(dev->dev.parent, + sizeof(struct i596_dma), &lp->dma_addr, GFP_KERNEL); + if (!dma) { + printk(KERN_ERR "%s: Couldn't get shared memory\n", __FILE__); + return -ENOMEM; + } + + /* The 82596-specific entries in the device structure. */ + dev->open = i596_open; + dev->stop = i596_close; + dev->hard_start_xmit = i596_start_xmit; + dev->get_stats = i596_get_stats; + dev->set_multicast_list = set_multicast_list; + dev->tx_timeout = i596_tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = i596_poll_controller; +#endif + + memset(dma, 0, sizeof(struct i596_dma)); + lp->dma = dma; + + dma->scb.command = 0; + dma->scb.cmd = I596_NULL; + dma->scb.rfd = I596_NULL; + spin_lock_init(&lp->lock); + + DMA_WBACK_INV(dev, dma, sizeof(struct i596_dma)); + + i = register_netdev(dev); + if (i) { + DMA_FREE(dev->dev.parent, sizeof(struct i596_dma), + (void *)dma, lp->dma_addr); + return i; + }; + + DEB(DEB_PROBE, printk(KERN_INFO "%s: 82596 at %#3lx,", + dev->name, dev->base_addr)); + for (i = 0; i < 6; i++) + DEB(DEB_PROBE, printk(" %2.2X", dev->dev_addr[i])); + DEB(DEB_PROBE, printk(" IRQ %d.\n", dev->irq)); + DEB(DEB_INIT, printk(KERN_INFO + "%s: dma at 0x%p (%d bytes), lp->scb at 0x%p\n", + dev->name, dma, (int)sizeof(struct i596_dma), + &dma->scb)); + + return 0; +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void i596_poll_controller(struct net_device *dev) +{ + disable_irq(dev->irq); + i596_interrupt(dev->irq, dev); + enable_irq(dev->irq); +} +#endif + +static irqreturn_t i596_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct i596_private *lp; + struct i596_dma *dma; + unsigned short status, ack_cmd = 0; + + if (dev == NULL) { + printk(KERN_WARNING "%s: irq %d for unknown device.\n", + __FUNCTION__, irq); + return IRQ_NONE; + } + + lp = netdev_priv(dev); + dma = lp->dma; + + spin_lock (&lp->lock); + + wait_cmd(dev, dma, 100, "i596 interrupt, timeout"); + status = SWAP16(dma->scb.status); + + DEB(DEB_INTS, printk(KERN_DEBUG + "%s: i596 interrupt, IRQ %d, status %4.4x.\n", + dev->name, irq, status)); + + ack_cmd = status & 0xf000; + + if (!ack_cmd) { + DEB(DEB_ERRORS, printk(KERN_DEBUG + "%s: interrupt with no events\n", + dev->name)); + spin_unlock (&lp->lock); + return IRQ_NONE; + } + + if ((status & 0x8000) || (status & 0x2000)) { + struct i596_cmd *ptr; + + if ((status & 0x8000)) + DEB(DEB_INTS, + printk(KERN_DEBUG + "%s: i596 interrupt completed command.\n", + dev->name)); + if ((status & 0x2000)) + DEB(DEB_INTS, + printk(KERN_DEBUG + "%s: i596 interrupt command unit inactive %x.\n", + dev->name, status & 0x0700)); + + while (lp->cmd_head != NULL) { + DMA_INV(dev, lp->cmd_head, sizeof(struct i596_cmd)); + if (!(lp->cmd_head->status & SWAP16(STAT_C))) + break; + + ptr = lp->cmd_head; + + DEB(DEB_STATUS, + printk(KERN_DEBUG + "cmd_head->status = %04x, ->command = %04x\n", + SWAP16(lp->cmd_head->status), + SWAP16(lp->cmd_head->command))); + lp->cmd_head = ptr->v_next; + lp->cmd_backlog--; + + switch (SWAP16(ptr->command) & 0x7) { + case CmdTx: + { + struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr; + struct sk_buff *skb = tx_cmd->skb; + + if (ptr->status & SWAP16(STAT_OK)) { + DEB(DEB_TXADDR, + print_eth(skb->data, "tx-done")); + } else { + lp->stats.tx_errors++; + if (ptr->status & SWAP16(0x0020)) + lp->stats.collisions++; + if (!(ptr->status & SWAP16(0x0040))) + lp->stats.tx_heartbeat_errors++; + if (ptr->status & SWAP16(0x0400)) + lp->stats.tx_carrier_errors++; + if (ptr->status & SWAP16(0x0800)) + lp->stats.collisions++; + if (ptr->status & SWAP16(0x1000)) + lp->stats.tx_aborted_errors++; + } + dma_unmap_single(dev->dev.parent, + tx_cmd->dma_addr, + skb->len, DMA_TO_DEVICE); + dev_kfree_skb_irq(skb); + + tx_cmd->cmd.command = 0; /* Mark free */ + break; + } + case CmdTDR: + { + unsigned short status = SWAP16(((struct tdr_cmd *)ptr)->status); + + if (status & 0x8000) { + DEB(DEB_ANY, + printk(KERN_DEBUG "%s: link ok.\n", + dev->name)); + } else { + if (status & 0x4000) + printk(KERN_ERR + "%s: Transceiver problem.\n", + dev->name); + if (status & 0x2000) + printk(KERN_ERR + "%s: Termination problem.\n", + dev->name); + if (status & 0x1000) + printk(KERN_ERR + "%s: Short circuit.\n", + dev->name); + + DEB(DEB_TDR, + printk(KERN_DEBUG "%s: Time %d.\n", + dev->name, status & 0x07ff)); + } + break; + } + case CmdConfigure: + /* + * Zap command so set_multicast_list() know + * it is free + */ + ptr->command = 0; + break; + } + ptr->v_next = NULL; + ptr->b_next = I596_NULL; + DMA_WBACK(dev, ptr, sizeof(struct i596_cmd)); + lp->last_cmd = jiffies; + } + + /* This mess is arranging that only the last of any outstanding + * commands has the interrupt bit set. Should probably really + * only add to the cmd queue when the CU is stopped. + */ + ptr = lp->cmd_head; + while ((ptr != NULL) && (ptr != lp->cmd_tail)) { + struct i596_cmd *prev = ptr; + + ptr->command &= SWAP16(0x1fff); + ptr = ptr->v_next; + DMA_WBACK_INV(dev, prev, sizeof(struct i596_cmd)); + } + + if (lp->cmd_head != NULL) + ack_cmd |= CUC_START; + dma->scb.cmd = SWAP32(virt_to_dma(lp, &lp->cmd_head->status)); + DMA_WBACK_INV(dev, &dma->scb, sizeof(struct i596_scb)); + } + if ((status & 0x1000) || (status & 0x4000)) { + if ((status & 0x4000)) + DEB(DEB_INTS, + printk(KERN_DEBUG + "%s: i596 interrupt received a frame.\n", + dev->name)); + i596_rx(dev); + /* Only RX_START if stopped - RGH 07-07-96 */ + if (status & 0x1000) { + if (netif_running(dev)) { + DEB(DEB_ERRORS, + printk(KERN_DEBUG + "%s: i596 interrupt receive unit inactive, status 0x%x\n", + dev->name, status)); + ack_cmd |= RX_START; + lp->stats.rx_errors++; + lp->stats.rx_fifo_errors++; + rebuild_rx_bufs(dev); + } + } + } + wait_cmd(dev, dma, 100, "i596 interrupt, timeout"); + dma->scb.command = SWAP16(ack_cmd); + DMA_WBACK(dev, &dma->scb, sizeof(struct i596_scb)); + + /* DANGER: I suspect that some kind of interrupt + acknowledgement aside from acking the 82596 might be needed + here... but it's running acceptably without */ + + ca(dev); + + wait_cmd(dev, dma, 100, "i596 interrupt, exit timeout"); + DEB(DEB_INTS, printk(KERN_DEBUG "%s: exiting interrupt.\n", dev->name)); + + spin_unlock (&lp->lock); + return IRQ_HANDLED; +} + +static int i596_close(struct net_device *dev) +{ + struct i596_private *lp = netdev_priv(dev); + unsigned long flags; + + netif_stop_queue(dev); + + DEB(DEB_INIT, + printk(KERN_DEBUG + "%s: Shutting down ethercard, status was %4.4x.\n", + dev->name, SWAP16(lp->dma->scb.status))); + + spin_lock_irqsave(&lp->lock, flags); + + wait_cmd(dev, lp->dma, 100, "close1 timed out"); + lp->dma->scb.command = SWAP16(CUC_ABORT | RX_ABORT); + DMA_WBACK(dev, &lp->dma->scb, sizeof(struct i596_scb)); + + ca(dev); + + wait_cmd(dev, lp->dma, 100, "close2 timed out"); + spin_unlock_irqrestore(&lp->lock, flags); + DEB(DEB_STRUCT, i596_display_data(dev)); + i596_cleanup_cmd(dev, lp); + + free_irq(dev->irq, dev); + remove_rx_bufs(dev); + + return 0; +} + +static struct net_device_stats *i596_get_stats(struct net_device *dev) +{ + struct i596_private *lp = netdev_priv(dev); + + return &lp->stats; +} + +/* + * Set or clear the multicast filter for this adaptor. + */ + +static void set_multicast_list(struct net_device *dev) +{ + struct i596_private *lp = netdev_priv(dev); + struct i596_dma *dma = lp->dma; + int config = 0, cnt; + + DEB(DEB_MULTI, + printk(KERN_DEBUG + "%s: set multicast list, %d entries, promisc %s, allmulti %s\n", + dev->name, dev->mc_count, + dev->flags & IFF_PROMISC ? "ON" : "OFF", + dev->flags & IFF_ALLMULTI ? "ON" : "OFF")); + + if ((dev->flags & IFF_PROMISC) && + !(dma->cf_cmd.i596_config[8] & 0x01)) { + dma->cf_cmd.i596_config[8] |= 0x01; + config = 1; + } + if (!(dev->flags & IFF_PROMISC) && + (dma->cf_cmd.i596_config[8] & 0x01)) { + dma->cf_cmd.i596_config[8] &= ~0x01; + config = 1; + } + if ((dev->flags & IFF_ALLMULTI) && + (dma->cf_cmd.i596_config[11] & 0x20)) { + dma->cf_cmd.i596_config[11] &= ~0x20; + config = 1; + } + if (!(dev->flags & IFF_ALLMULTI) && + !(dma->cf_cmd.i596_config[11] & 0x20)) { + dma->cf_cmd.i596_config[11] |= 0x20; + config = 1; + } + if (config) { + if (dma->cf_cmd.cmd.command) + printk(KERN_INFO + "%s: config change request already queued\n", + dev->name); + else { + dma->cf_cmd.cmd.command = SWAP16(CmdConfigure); + DMA_WBACK_INV(dev, &dma->cf_cmd, sizeof(struct cf_cmd)); + i596_add_cmd(dev, &dma->cf_cmd.cmd); + } + } + + cnt = dev->mc_count; + if (cnt > MAX_MC_CNT) { + cnt = MAX_MC_CNT; + printk(KERN_NOTICE "%s: Only %d multicast addresses supported", + dev->name, cnt); + } + + if (dev->mc_count > 0) { + struct dev_mc_list *dmi; + unsigned char *cp; + struct mc_cmd *cmd; + + cmd = &dma->mc_cmd; + cmd->cmd.command = SWAP16(CmdMulticastList); + cmd->mc_cnt = SWAP16(dev->mc_count * 6); + cp = cmd->mc_addrs; + for (dmi = dev->mc_list; + cnt && dmi != NULL; + dmi = dmi->next, cnt--, cp += 6) { + memcpy(cp, dmi->dmi_addr, 6); + if (i596_debug > 1) + DEB(DEB_MULTI, + printk(KERN_DEBUG + "%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n", + dev->name, cp[0], cp[1], cp[2], cp[3], cp[4], cp[5])); + } + DMA_WBACK_INV(dev, &dma->mc_cmd, sizeof(struct mc_cmd)); + i596_add_cmd(dev, &cmd->cmd); + } +} diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c index fef3193121f..9a343b96597 100644 --- a/drivers/net/macmace.c +++ b/drivers/net/macmace.c @@ -577,7 +577,7 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id) struct mace_data *mp = netdev_priv(dev); volatile struct mace *mb = mp->mace; int intr, fs; - unsigned int flags; + unsigned long flags; /* don't want the dma interrupt handler to fire */ local_irq_save(flags); diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c new file mode 100644 index 00000000000..dc74d006e01 --- /dev/null +++ b/drivers/net/macvlan.c @@ -0,0 +1,496 @@ +/* + * Copyright (c) 2007 Patrick McHardy <kaber@trash.net> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * The code this is based on carried the following copyright notice: + * --- + * (C) Copyright 2001-2006 + * Alex Zeffertt, Cambridge Broadband Ltd, ajz@cambridgebroadband.com + * Re-worked by Ben Greear <greearb@candelatech.com> + * --- + */ +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/list.h> +#include <linux/notifier.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/ethtool.h> +#include <linux/if_arp.h> +#include <linux/if_link.h> +#include <linux/if_macvlan.h> +#include <net/rtnetlink.h> + +#define MACVLAN_HASH_SIZE (1 << BITS_PER_BYTE) + +struct macvlan_port { + struct net_device *dev; + struct hlist_head vlan_hash[MACVLAN_HASH_SIZE]; + struct list_head vlans; +}; + +struct macvlan_dev { + struct net_device *dev; + struct list_head list; + struct hlist_node hlist; + struct macvlan_port *port; + struct net_device *lowerdev; +}; + + +static struct macvlan_dev *macvlan_hash_lookup(const struct macvlan_port *port, + const unsigned char *addr) +{ + struct macvlan_dev *vlan; + struct hlist_node *n; + + hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[addr[5]], hlist) { + if (!compare_ether_addr(vlan->dev->dev_addr, addr)) + return vlan; + } + return NULL; +} + +static void macvlan_broadcast(struct sk_buff *skb, + const struct macvlan_port *port) +{ + const struct ethhdr *eth = eth_hdr(skb); + const struct macvlan_dev *vlan; + struct hlist_node *n; + struct net_device *dev; + struct sk_buff *nskb; + unsigned int i; + + for (i = 0; i < MACVLAN_HASH_SIZE; i++) { + hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[i], hlist) { + dev = vlan->dev; + if (unlikely(!(dev->flags & IFF_UP))) + continue; + + nskb = skb_clone(skb, GFP_ATOMIC); + if (nskb == NULL) { + dev->stats.rx_errors++; + dev->stats.rx_dropped++; + continue; + } + + dev->stats.rx_bytes += skb->len + ETH_HLEN; + dev->stats.rx_packets++; + dev->stats.multicast++; + dev->last_rx = jiffies; + + nskb->dev = dev; + if (!compare_ether_addr(eth->h_dest, dev->broadcast)) + nskb->pkt_type = PACKET_BROADCAST; + else + nskb->pkt_type = PACKET_MULTICAST; + + netif_rx(nskb); + } + } +} + +/* called under rcu_read_lock() from netif_receive_skb */ +static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb) +{ + const struct ethhdr *eth = eth_hdr(skb); + const struct macvlan_port *port; + const struct macvlan_dev *vlan; + struct net_device *dev; + + port = rcu_dereference(skb->dev->macvlan_port); + if (port == NULL) + return skb; + + if (is_multicast_ether_addr(eth->h_dest)) { + macvlan_broadcast(skb, port); + return skb; + } + + vlan = macvlan_hash_lookup(port, eth->h_dest); + if (vlan == NULL) + return skb; + + dev = vlan->dev; + if (unlikely(!(dev->flags & IFF_UP))) { + kfree_skb(skb); + return NULL; + } + + skb = skb_share_check(skb, GFP_ATOMIC); + if (skb == NULL) { + dev->stats.rx_errors++; + dev->stats.rx_dropped++; + return NULL; + } + + dev->stats.rx_bytes += skb->len + ETH_HLEN; + dev->stats.rx_packets++; + dev->last_rx = jiffies; + + skb->dev = dev; + skb->pkt_type = PACKET_HOST; + + netif_rx(skb); + return NULL; +} + +static int macvlan_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + const struct macvlan_dev *vlan = netdev_priv(dev); + unsigned int len = skb->len; + int ret; + + skb->dev = vlan->lowerdev; + ret = dev_queue_xmit(skb); + + if (likely(ret == NET_XMIT_SUCCESS)) { + dev->stats.tx_packets++; + dev->stats.tx_bytes += len; + } else { + dev->stats.tx_errors++; + dev->stats.tx_aborted_errors++; + } + return NETDEV_TX_OK; +} + +static int macvlan_hard_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, void *daddr, void *saddr, + unsigned len) +{ + const struct macvlan_dev *vlan = netdev_priv(dev); + struct net_device *lowerdev = vlan->lowerdev; + + return lowerdev->hard_header(skb, lowerdev, type, daddr, + saddr ? : dev->dev_addr, len); +} + +static int macvlan_open(struct net_device *dev) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + struct macvlan_port *port = vlan->port; + struct net_device *lowerdev = vlan->lowerdev; + int err; + + err = dev_unicast_add(lowerdev, dev->dev_addr, ETH_ALEN); + if (err < 0) + return err; + if (dev->flags & IFF_ALLMULTI) + dev_set_allmulti(lowerdev, 1); + + hlist_add_head_rcu(&vlan->hlist, &port->vlan_hash[dev->dev_addr[5]]); + return 0; +} + +static int macvlan_stop(struct net_device *dev) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + struct net_device *lowerdev = vlan->lowerdev; + + dev_mc_unsync(lowerdev, dev); + if (dev->flags & IFF_ALLMULTI) + dev_set_allmulti(lowerdev, -1); + + dev_unicast_delete(lowerdev, dev->dev_addr, ETH_ALEN); + + hlist_del_rcu(&vlan->hlist); + synchronize_rcu(); + return 0; +} + +static void macvlan_change_rx_flags(struct net_device *dev, int change) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + struct net_device *lowerdev = vlan->lowerdev; + + if (change & IFF_ALLMULTI) + dev_set_allmulti(lowerdev, dev->flags & IFF_ALLMULTI ? 1 : -1); +} + +static void macvlan_set_multicast_list(struct net_device *dev) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + + dev_mc_sync(vlan->lowerdev, dev); +} + +static int macvlan_change_mtu(struct net_device *dev, int new_mtu) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + + if (new_mtu < 68 || vlan->lowerdev->mtu < new_mtu) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + +/* + * macvlan network devices have devices nesting below it and are a special + * "super class" of normal network devices; split their locks off into a + * separate class since they always nest. + */ +static struct lock_class_key macvlan_netdev_xmit_lock_key; + +#define MACVLAN_FEATURES \ + (NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \ + NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO_ROBUST | \ + NETIF_F_TSO_ECN | NETIF_F_TSO6) + +#define MACVLAN_STATE_MASK \ + ((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT)) + +static int macvlan_init(struct net_device *dev) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + const struct net_device *lowerdev = vlan->lowerdev; + + dev->state = (dev->state & ~MACVLAN_STATE_MASK) | + (lowerdev->state & MACVLAN_STATE_MASK); + dev->features = lowerdev->features & MACVLAN_FEATURES; + dev->iflink = lowerdev->ifindex; + + lockdep_set_class(&dev->_xmit_lock, &macvlan_netdev_xmit_lock_key); + return 0; +} + +static void macvlan_ethtool_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *drvinfo) +{ + snprintf(drvinfo->driver, 32, "macvlan"); + snprintf(drvinfo->version, 32, "0.1"); +} + +static u32 macvlan_ethtool_get_rx_csum(struct net_device *dev) +{ + const struct macvlan_dev *vlan = netdev_priv(dev); + struct net_device *lowerdev = vlan->lowerdev; + + if (lowerdev->ethtool_ops->get_rx_csum == NULL) + return 0; + return lowerdev->ethtool_ops->get_rx_csum(lowerdev); +} + +static const struct ethtool_ops macvlan_ethtool_ops = { + .get_link = ethtool_op_get_link, + .get_rx_csum = macvlan_ethtool_get_rx_csum, + .get_tx_csum = ethtool_op_get_tx_csum, + .get_tso = ethtool_op_get_tso, + .get_ufo = ethtool_op_get_ufo, + .get_sg = ethtool_op_get_sg, + .get_drvinfo = macvlan_ethtool_get_drvinfo, +}; + +static void macvlan_setup(struct net_device *dev) +{ + ether_setup(dev); + + dev->init = macvlan_init; + dev->open = macvlan_open; + dev->stop = macvlan_stop; + dev->change_mtu = macvlan_change_mtu; + dev->change_rx_flags = macvlan_change_rx_flags; + dev->set_multicast_list = macvlan_set_multicast_list; + dev->hard_header = macvlan_hard_header; + dev->hard_start_xmit = macvlan_hard_start_xmit; + dev->destructor = free_netdev; + dev->ethtool_ops = &macvlan_ethtool_ops; + dev->tx_queue_len = 0; +} + +static int macvlan_port_create(struct net_device *dev) +{ + struct macvlan_port *port; + unsigned int i; + + if (dev->type != ARPHRD_ETHER || dev->flags & IFF_LOOPBACK) + return -EINVAL; + + port = kzalloc(sizeof(*port), GFP_KERNEL); + if (port == NULL) + return -ENOMEM; + + port->dev = dev; + INIT_LIST_HEAD(&port->vlans); + for (i = 0; i < MACVLAN_HASH_SIZE; i++) + INIT_HLIST_HEAD(&port->vlan_hash[i]); + rcu_assign_pointer(dev->macvlan_port, port); + return 0; +} + +static void macvlan_port_destroy(struct net_device *dev) +{ + struct macvlan_port *port = dev->macvlan_port; + + rcu_assign_pointer(dev->macvlan_port, NULL); + synchronize_rcu(); + kfree(port); +} + +static void macvlan_transfer_operstate(struct net_device *dev) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + const struct net_device *lowerdev = vlan->lowerdev; + + if (lowerdev->operstate == IF_OPER_DORMANT) + netif_dormant_on(dev); + else + netif_dormant_off(dev); + + if (netif_carrier_ok(lowerdev)) { + if (!netif_carrier_ok(dev)) + netif_carrier_on(dev); + } else { + if (netif_carrier_ok(lowerdev)) + netif_carrier_off(dev); + } +} + +static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[]) +{ + if (tb[IFLA_ADDRESS]) { + if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) + return -EINVAL; + if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) + return -EADDRNOTAVAIL; + } + return 0; +} + +static int macvlan_newlink(struct net_device *dev, + struct nlattr *tb[], struct nlattr *data[]) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + struct macvlan_port *port; + struct net_device *lowerdev; + int err; + + if (!tb[IFLA_LINK]) + return -EINVAL; + + lowerdev = __dev_get_by_index(nla_get_u32(tb[IFLA_LINK])); + if (lowerdev == NULL) + return -ENODEV; + + if (!tb[IFLA_MTU]) + dev->mtu = lowerdev->mtu; + else if (dev->mtu > lowerdev->mtu) + return -EINVAL; + + if (!tb[IFLA_ADDRESS]) + random_ether_addr(dev->dev_addr); + + if (lowerdev->macvlan_port == NULL) { + err = macvlan_port_create(lowerdev); + if (err < 0) + return err; + } + port = lowerdev->macvlan_port; + + vlan->lowerdev = lowerdev; + vlan->dev = dev; + vlan->port = port; + + err = register_netdevice(dev); + if (err < 0) + return err; + + list_add_tail(&vlan->list, &port->vlans); + macvlan_transfer_operstate(dev); + return 0; +} + +static void macvlan_dellink(struct net_device *dev) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + struct macvlan_port *port = vlan->port; + + list_del(&vlan->list); + unregister_netdevice(dev); + + if (list_empty(&port->vlans)) + macvlan_port_destroy(dev); +} + +static struct rtnl_link_ops macvlan_link_ops __read_mostly = { + .kind = "macvlan", + .priv_size = sizeof(struct macvlan_dev), + .setup = macvlan_setup, + .validate = macvlan_validate, + .newlink = macvlan_newlink, + .dellink = macvlan_dellink, +}; + +static int macvlan_device_event(struct notifier_block *unused, + unsigned long event, void *ptr) +{ + struct net_device *dev = ptr; + struct macvlan_dev *vlan, *next; + struct macvlan_port *port; + + port = dev->macvlan_port; + if (port == NULL) + return NOTIFY_DONE; + + switch (event) { + case NETDEV_CHANGE: + list_for_each_entry(vlan, &port->vlans, list) + macvlan_transfer_operstate(vlan->dev); + break; + case NETDEV_FEAT_CHANGE: + list_for_each_entry(vlan, &port->vlans, list) { + vlan->dev->features = dev->features & MACVLAN_FEATURES; + netdev_features_change(vlan->dev); + } + break; + case NETDEV_UNREGISTER: + list_for_each_entry_safe(vlan, next, &port->vlans, list) + macvlan_dellink(vlan->dev); + break; + } + return NOTIFY_DONE; +} + +static struct notifier_block macvlan_notifier_block __read_mostly = { + .notifier_call = macvlan_device_event, +}; + +static int __init macvlan_init_module(void) +{ + int err; + + register_netdevice_notifier(&macvlan_notifier_block); + macvlan_handle_frame_hook = macvlan_handle_frame; + + err = rtnl_link_register(&macvlan_link_ops); + if (err < 0) + goto err1; + return 0; +err1: + macvlan_handle_frame_hook = macvlan_handle_frame; + unregister_netdevice_notifier(&macvlan_notifier_block); + return err; +} + +static void __exit macvlan_cleanup_module(void) +{ + rtnl_link_unregister(&macvlan_link_ops); + macvlan_handle_frame_hook = NULL; + unregister_netdevice_notifier(&macvlan_notifier_block); +} + +module_init(macvlan_init_module); +module_exit(macvlan_cleanup_module); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); +MODULE_DESCRIPTION("Driver for MAC address based VLANs"); +MODULE_ALIAS_RTNL_LINK("macvlan"); diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c index 638a279ec50..9853c74f6bb 100644 --- a/drivers/net/mipsnet.c +++ b/drivers/net/mipsnet.c @@ -240,7 +240,7 @@ static int __init mipsnet_probe(struct device *dev) * TODO: probe for these or load them from PARAM */ netdev->base_addr = 0x4200; - netdev->irq = MIPSCPU_INT_BASE + MIPSCPU_INT_MB0 + + netdev->irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB0 + inl(mipsnet_reg_address(netdev, interruptInfo)); // Get the io region now, get irq on open() diff --git a/drivers/net/mlx4/cq.c b/drivers/net/mlx4/cq.c index 437d78ad091..39253d0c159 100644 --- a/drivers/net/mlx4/cq.c +++ b/drivers/net/mlx4/cq.c @@ -61,7 +61,7 @@ struct mlx4_cq_context { __be32 solicit_producer_index; __be32 consumer_index; __be32 producer_index; - u8 reserved6[2]; + u32 reserved6[2]; __be64 db_rec_addr; }; diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c index 0f11adb8eb4..27a82cecd69 100644 --- a/drivers/net/mlx4/eq.c +++ b/drivers/net/mlx4/eq.c @@ -490,9 +490,11 @@ static void mlx4_free_irqs(struct mlx4_dev *dev) if (eq_table->have_irq) free_irq(dev->pdev->irq, dev); - for (i = 0; i < MLX4_NUM_EQ; ++i) + for (i = 0; i < MLX4_EQ_CATAS; ++i) if (eq_table->eq[i].have_irq) free_irq(eq_table->eq[i].irq, eq_table->eq + i); + if (eq_table->eq[MLX4_EQ_CATAS].have_irq) + free_irq(eq_table->eq[MLX4_EQ_CATAS].irq, dev); } static int __devinit mlx4_map_clr_int(struct mlx4_dev *dev) diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c index cfa5cc07233..c45cbe43a0c 100644 --- a/drivers/net/mlx4/fw.c +++ b/drivers/net/mlx4/fw.c @@ -37,6 +37,12 @@ #include "fw.h" #include "icm.h" +enum { + MLX4_COMMAND_INTERFACE_MIN_REV = 2, + MLX4_COMMAND_INTERFACE_MAX_REV = 3, + MLX4_COMMAND_INTERFACE_NEW_PORT_CMDS = 3, +}; + extern void __buggy_use_of_MLX4_GET(void); extern void __buggy_use_of_MLX4_PUT(void); @@ -103,6 +109,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) u16 size; u16 stat_rate; int err; + int i; #define QUERY_DEV_CAP_OUT_SIZE 0x100 #define QUERY_DEV_CAP_MAX_SRQ_SZ_OFFSET 0x10 @@ -131,6 +138,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) #define QUERY_DEV_CAP_ACK_DELAY_OFFSET 0x35 #define QUERY_DEV_CAP_MTU_WIDTH_OFFSET 0x36 #define QUERY_DEV_CAP_VL_PORT_OFFSET 0x37 +#define QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET 0x38 #define QUERY_DEV_CAP_MAX_GID_OFFSET 0x3b #define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET 0x3c #define QUERY_DEV_CAP_MAX_PKEY_OFFSET 0x3f @@ -172,7 +180,6 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP, MLX4_CMD_TIME_CLASS_A); - if (err) goto out; @@ -212,18 +219,12 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev_cap->max_rdma_global = 1 << (field & 0x3f); MLX4_GET(field, outbox, QUERY_DEV_CAP_ACK_DELAY_OFFSET); dev_cap->local_ca_ack_delay = field & 0x1f; - MLX4_GET(field, outbox, QUERY_DEV_CAP_MTU_WIDTH_OFFSET); - dev_cap->max_mtu = field >> 4; - dev_cap->max_port_width = field & 0xf; MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET); - dev_cap->max_vl = field >> 4; dev_cap->num_ports = field & 0xf; - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GID_OFFSET); - dev_cap->max_gids = 1 << (field & 0xf); + MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET); + dev_cap->max_msg_sz = 1 << (field & 0x1f); MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET); dev_cap->stat_rate_support = stat_rate; - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PKEY_OFFSET); - dev_cap->max_pkeys = 1 << (field & 0xf); MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET); MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET); dev_cap->reserved_uars = field >> 4; @@ -300,6 +301,42 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) MLX4_GET(dev_cap->max_icm_sz, outbox, QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET); + if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { + for (i = 1; i <= dev_cap->num_ports; ++i) { + MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET); + dev_cap->max_vl[i] = field >> 4; + MLX4_GET(field, outbox, QUERY_DEV_CAP_MTU_WIDTH_OFFSET); + dev_cap->max_mtu[i] = field >> 4; + dev_cap->max_port_width[i] = field & 0xf; + MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GID_OFFSET); + dev_cap->max_gids[i] = 1 << (field & 0xf); + MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PKEY_OFFSET); + dev_cap->max_pkeys[i] = 1 << (field & 0xf); + } + } else { +#define QUERY_PORT_MTU_OFFSET 0x01 +#define QUERY_PORT_WIDTH_OFFSET 0x06 +#define QUERY_PORT_MAX_GID_PKEY_OFFSET 0x07 +#define QUERY_PORT_MAX_VL_OFFSET 0x0b + + for (i = 1; i <= dev_cap->num_ports; ++i) { + err = mlx4_cmd_box(dev, 0, mailbox->dma, i, 0, MLX4_CMD_QUERY_PORT, + MLX4_CMD_TIME_CLASS_B); + if (err) + goto out; + + MLX4_GET(field, outbox, QUERY_PORT_MTU_OFFSET); + dev_cap->max_mtu[i] = field & 0xf; + MLX4_GET(field, outbox, QUERY_PORT_WIDTH_OFFSET); + dev_cap->max_port_width[i] = field & 0xf; + MLX4_GET(field, outbox, QUERY_PORT_MAX_GID_PKEY_OFFSET); + dev_cap->max_gids[i] = 1 << (field >> 4); + dev_cap->max_pkeys[i] = 1 << (field & 0xf); + MLX4_GET(field, outbox, QUERY_PORT_MAX_VL_OFFSET); + dev_cap->max_vl[i] = field & 0xf; + } + } + if (dev_cap->bmme_flags & 1) mlx4_dbg(dev, "Base MM extensions: yes " "(flags %d, rsvd L_Key %08x)\n", @@ -334,8 +371,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) mlx4_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n", dev_cap->max_cq_sz, dev_cap->max_qp_sz, dev_cap->max_srq_sz); mlx4_dbg(dev, "Local CA ACK delay: %d, max MTU: %d, port width cap: %d\n", - dev_cap->local_ca_ack_delay, 128 << dev_cap->max_mtu, - dev_cap->max_port_width); + dev_cap->local_ca_ack_delay, 128 << dev_cap->max_mtu[1], + dev_cap->max_port_width[1]); mlx4_dbg(dev, "Max SQ desc size: %d, max SQ S/G: %d\n", dev_cap->max_sq_desc_sz, dev_cap->max_sq_sg); mlx4_dbg(dev, "Max RQ desc size: %d, max RQ S/G: %d\n", @@ -452,10 +489,12 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev) u32 *outbox; int err = 0; u64 fw_ver; + u16 cmd_if_rev; u8 lg; #define QUERY_FW_OUT_SIZE 0x100 #define QUERY_FW_VER_OFFSET 0x00 +#define QUERY_FW_CMD_IF_REV_OFFSET 0x0a #define QUERY_FW_MAX_CMD_OFFSET 0x0f #define QUERY_FW_ERR_START_OFFSET 0x30 #define QUERY_FW_ERR_SIZE_OFFSET 0x38 @@ -477,21 +516,40 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev) MLX4_GET(fw_ver, outbox, QUERY_FW_VER_OFFSET); /* - * FW subminor version is at more signifant bits than minor + * FW subminor version is at more significant bits than minor * version, so swap here. */ dev->caps.fw_ver = (fw_ver & 0xffff00000000ull) | ((fw_ver & 0xffff0000ull) >> 16) | ((fw_ver & 0x0000ffffull) << 16); + MLX4_GET(cmd_if_rev, outbox, QUERY_FW_CMD_IF_REV_OFFSET); + if (cmd_if_rev < MLX4_COMMAND_INTERFACE_MIN_REV || + cmd_if_rev > MLX4_COMMAND_INTERFACE_MAX_REV) { + mlx4_err(dev, "Installed FW has unsupported " + "command interface revision %d.\n", + cmd_if_rev); + mlx4_err(dev, "(Installed FW version is %d.%d.%03d)\n", + (int) (dev->caps.fw_ver >> 32), + (int) (dev->caps.fw_ver >> 16) & 0xffff, + (int) dev->caps.fw_ver & 0xffff); + mlx4_err(dev, "This driver version supports only revisions %d to %d.\n", + MLX4_COMMAND_INTERFACE_MIN_REV, MLX4_COMMAND_INTERFACE_MAX_REV); + err = -ENODEV; + goto out; + } + + if (cmd_if_rev < MLX4_COMMAND_INTERFACE_NEW_PORT_CMDS) + dev->flags |= MLX4_FLAG_OLD_PORT_CMDS; + MLX4_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET); cmd->max_cmds = 1 << lg; - mlx4_dbg(dev, "FW version %d.%d.%03d, max commands %d\n", + mlx4_dbg(dev, "FW version %d.%d.%03d (cmd intf rev %d), max commands %d\n", (int) (dev->caps.fw_ver >> 32), (int) (dev->caps.fw_ver >> 16) & 0xffff, (int) dev->caps.fw_ver & 0xffff, - cmd->max_cmds); + cmd_if_rev, cmd->max_cmds); MLX4_GET(fw->catas_offset, outbox, QUERY_FW_ERR_START_OFFSET); MLX4_GET(fw->catas_size, outbox, QUERY_FW_ERR_SIZE_OFFSET); @@ -687,13 +745,15 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) return err; } -int mlx4_INIT_PORT(struct mlx4_dev *dev, struct mlx4_init_port_param *param, int port) +int mlx4_INIT_PORT(struct mlx4_dev *dev, int port) { struct mlx4_cmd_mailbox *mailbox; u32 *inbox; int err; u32 flags; + u16 field; + if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { #define INIT_PORT_IN_SIZE 256 #define INIT_PORT_FLAGS_OFFSET 0x00 #define INIT_PORT_FLAG_SIG (1 << 18) @@ -708,32 +768,32 @@ int mlx4_INIT_PORT(struct mlx4_dev *dev, struct mlx4_init_port_param *param, int #define INIT_PORT_NODE_GUID_OFFSET 0x18 #define INIT_PORT_SI_GUID_OFFSET 0x20 - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - inbox = mailbox->buf; + mailbox = mlx4_alloc_cmd_mailbox(dev); + if (IS_ERR(mailbox)) + return PTR_ERR(mailbox); + inbox = mailbox->buf; - memset(inbox, 0, INIT_PORT_IN_SIZE); + memset(inbox, 0, INIT_PORT_IN_SIZE); - flags = 0; - flags |= param->set_guid0 ? INIT_PORT_FLAG_G0 : 0; - flags |= param->set_node_guid ? INIT_PORT_FLAG_NG : 0; - flags |= param->set_si_guid ? INIT_PORT_FLAG_SIG : 0; - flags |= (param->vl_cap & 0xf) << INIT_PORT_VL_SHIFT; - flags |= (param->port_width_cap & 0xf) << INIT_PORT_PORT_WIDTH_SHIFT; - MLX4_PUT(inbox, flags, INIT_PORT_FLAGS_OFFSET); + flags = 0; + flags |= (dev->caps.vl_cap[port] & 0xf) << INIT_PORT_VL_SHIFT; + flags |= (dev->caps.port_width_cap[port] & 0xf) << INIT_PORT_PORT_WIDTH_SHIFT; + MLX4_PUT(inbox, flags, INIT_PORT_FLAGS_OFFSET); - MLX4_PUT(inbox, param->mtu, INIT_PORT_MTU_OFFSET); - MLX4_PUT(inbox, param->max_gid, INIT_PORT_MAX_GID_OFFSET); - MLX4_PUT(inbox, param->max_pkey, INIT_PORT_MAX_PKEY_OFFSET); - MLX4_PUT(inbox, param->guid0, INIT_PORT_GUID0_OFFSET); - MLX4_PUT(inbox, param->node_guid, INIT_PORT_NODE_GUID_OFFSET); - MLX4_PUT(inbox, param->si_guid, INIT_PORT_SI_GUID_OFFSET); + field = 128 << dev->caps.mtu_cap[port]; + MLX4_PUT(inbox, field, INIT_PORT_MTU_OFFSET); + field = dev->caps.gid_table_len[port]; + MLX4_PUT(inbox, field, INIT_PORT_MAX_GID_OFFSET); + field = dev->caps.pkey_table_len[port]; + MLX4_PUT(inbox, field, INIT_PORT_MAX_PKEY_OFFSET); - err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_INIT_PORT, - MLX4_CMD_TIME_CLASS_A); + err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_INIT_PORT, + MLX4_CMD_TIME_CLASS_A); - mlx4_free_cmd_mailbox(dev, mailbox); + mlx4_free_cmd_mailbox(dev, mailbox); + } else + err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT, + MLX4_CMD_TIME_CLASS_A); return err; } diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h index 2616fa53d4d..7e1dd9e25cf 100644 --- a/drivers/net/mlx4/fw.h +++ b/drivers/net/mlx4/fw.h @@ -59,13 +59,14 @@ struct mlx4_dev_cap { int max_responder_per_qp; int max_rdma_global; int local_ca_ack_delay; - int max_mtu; - int max_port_width; - int max_vl; int num_ports; - int max_gids; + u32 max_msg_sz; + int max_mtu[MLX4_MAX_PORTS + 1]; + int max_port_width[MLX4_MAX_PORTS + 1]; + int max_vl[MLX4_MAX_PORTS + 1]; + int max_gids[MLX4_MAX_PORTS + 1]; + int max_pkeys[MLX4_MAX_PORTS + 1]; u16 stat_rate_support; - int max_pkeys; u32 flags; int reserved_uars; int uar_size; diff --git a/drivers/net/mlx4/intf.c b/drivers/net/mlx4/intf.c index 65854f9e9c7..9ae951bf6aa 100644 --- a/drivers/net/mlx4/intf.c +++ b/drivers/net/mlx4/intf.c @@ -135,9 +135,6 @@ int mlx4_register_device(struct mlx4_dev *dev) struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_interface *intf; - INIT_LIST_HEAD(&priv->ctx_list); - spin_lock_init(&priv->ctx_lock); - mutex_lock(&intf_mutex); list_add_tail(&priv->dev_list, &dev_list); diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c index 20b8c0d3ced..a4f2e0475a7 100644 --- a/drivers/net/mlx4/main.c +++ b/drivers/net/mlx4/main.c @@ -88,6 +88,7 @@ static struct mlx4_profile default_profile = { static int __devinit mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) { int err; + int i; err = mlx4_QUERY_DEV_CAP(dev, dev_cap); if (err) { @@ -117,11 +118,15 @@ static int __devinit mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev } dev->caps.num_ports = dev_cap->num_ports; + for (i = 1; i <= dev->caps.num_ports; ++i) { + dev->caps.vl_cap[i] = dev_cap->max_vl[i]; + dev->caps.mtu_cap[i] = dev_cap->max_mtu[i]; + dev->caps.gid_table_len[i] = dev_cap->max_gids[i]; + dev->caps.pkey_table_len[i] = dev_cap->max_pkeys[i]; + dev->caps.port_width_cap[i] = dev_cap->max_port_width[i]; + } + dev->caps.num_uars = dev_cap->uar_size / PAGE_SIZE; - dev->caps.vl_cap = dev_cap->max_vl; - dev->caps.mtu_cap = dev_cap->max_mtu; - dev->caps.gid_table_len = dev_cap->max_gids; - dev->caps.pkey_table_len = dev_cap->max_pkeys; dev->caps.local_ca_ack_delay = dev_cap->local_ca_ack_delay; dev->caps.bf_reg_size = dev_cap->bf_reg_size; dev->caps.bf_regs_per_page = dev_cap->bf_regs_per_page; @@ -148,8 +153,8 @@ static int __devinit mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev dev->caps.reserved_mrws = dev_cap->reserved_mrws; dev->caps.reserved_uars = dev_cap->reserved_uars; dev->caps.reserved_pds = dev_cap->reserved_pds; - dev->caps.port_width_cap = dev_cap->max_port_width; dev->caps.mtt_entry_sz = MLX4_MTT_ENTRY_PER_SEG * dev_cap->mtt_entry_sz; + dev->caps.max_msg_sz = dev_cap->max_msg_sz; dev->caps.page_size_cap = ~(u32) (dev_cap->min_page_sz - 1); dev->caps.flags = dev_cap->flags; dev->caps.stat_rate_support = dev_cap->stat_rate_support; @@ -787,6 +792,8 @@ static int __devinit mlx4_init_one(struct pci_dev *pdev, dev = &priv->dev; dev->pdev = pdev; + INIT_LIST_HEAD(&priv->ctx_list); + spin_lock_init(&priv->ctx_lock); /* * Now reset the HCA before we touch the PCI capabilities or @@ -905,6 +912,8 @@ static struct pci_device_id mlx4_pci_table[] = { { PCI_VDEVICE(MELLANOX, 0x6340) }, /* MT25408 "Hermon" SDR */ { PCI_VDEVICE(MELLANOX, 0x634a) }, /* MT25408 "Hermon" DDR */ { PCI_VDEVICE(MELLANOX, 0x6354) }, /* MT25408 "Hermon" QDR */ + { PCI_VDEVICE(MELLANOX, 0x6732) }, /* MT25408 "Hermon" DDR PCIe gen2 */ + { PCI_VDEVICE(MELLANOX, 0x673c) }, /* MT25408 "Hermon" QDR PCIe gen2 */ { 0, } }; diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h index 3d3b6d24d8d..d9c91a71fc8 100644 --- a/drivers/net/mlx4/mlx4.h +++ b/drivers/net/mlx4/mlx4.h @@ -37,6 +37,7 @@ #ifndef MLX4_H #define MLX4_H +#include <linux/mutex.h> #include <linux/radix-tree.h> #include <linux/mlx4/device.h> diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c index b33864dab17..d0808fa3ec8 100644 --- a/drivers/net/mlx4/mr.c +++ b/drivers/net/mlx4/mr.c @@ -324,15 +324,17 @@ int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr) MLX4_MPT_FLAG_MIO | MLX4_MPT_FLAG_REGION | mr->access); - if (mr->mtt.order < 0) - mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_PHYSICAL); mpt_entry->key = cpu_to_be32(key_to_hw_index(mr->key)); mpt_entry->pd = cpu_to_be32(mr->pd); mpt_entry->start = cpu_to_be64(mr->iova); mpt_entry->length = cpu_to_be64(mr->size); mpt_entry->entity_size = cpu_to_be32(mr->mtt.page_shift); - mpt_entry->mtt_seg = cpu_to_be64(mlx4_mtt_addr(dev, &mr->mtt)); + if (mr->mtt.order < 0) { + mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_PHYSICAL); + mpt_entry->mtt_seg = 0; + } else + mpt_entry->mtt_seg = cpu_to_be64(mlx4_mtt_addr(dev, &mr->mtt)); err = mlx4_SW2HW_MPT(dev, mailbox, key_to_hw_index(mr->key) & (dev->caps.num_mpts - 1)); diff --git a/drivers/net/mlx4/qp.c b/drivers/net/mlx4/qp.c index 7f8b7d55b6e..19b48c71cf7 100644 --- a/drivers/net/mlx4/qp.c +++ b/drivers/net/mlx4/qp.c @@ -113,8 +113,7 @@ int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt, struct mlx4_cmd_mailbox *mailbox; int ret = 0; - if (cur_state < 0 || cur_state >= MLX4_QP_NUM_STATE || - new_state < 0 || cur_state >= MLX4_QP_NUM_STATE || + if (cur_state >= MLX4_QP_NUM_STATE || cur_state >= MLX4_QP_NUM_STATE || !op[cur_state][new_state]) return -EINVAL; @@ -278,3 +277,24 @@ void mlx4_cleanup_qp_table(struct mlx4_dev *dev) mlx4_CONF_SPECIAL_QP(dev, 0); mlx4_bitmap_cleanup(&mlx4_priv(dev)->qp_table.bitmap); } + +int mlx4_qp_query(struct mlx4_dev *dev, struct mlx4_qp *qp, + struct mlx4_qp_context *context) +{ + struct mlx4_cmd_mailbox *mailbox; + int err; + + mailbox = mlx4_alloc_cmd_mailbox(dev); + if (IS_ERR(mailbox)) + return PTR_ERR(mailbox); + + err = mlx4_cmd_box(dev, 0, mailbox->dma, qp->qpn, 0, + MLX4_CMD_QUERY_QP, MLX4_CMD_TIME_CLASS_A); + if (!err) + memcpy(context, mailbox->buf + 8, sizeof *context); + + mlx4_free_cmd_mailbox(dev, mailbox); + return err; +} +EXPORT_SYMBOL_GPL(mlx4_qp_query); + diff --git a/drivers/net/mlx4/srq.c b/drivers/net/mlx4/srq.c index 2134f83aed8..b061c86d683 100644 --- a/drivers/net/mlx4/srq.c +++ b/drivers/net/mlx4/srq.c @@ -102,6 +102,13 @@ static int mlx4_ARM_SRQ(struct mlx4_dev *dev, int srq_num, int limit_watermark) MLX4_CMD_TIME_CLASS_B); } +static int mlx4_QUERY_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, + int srq_num) +{ + return mlx4_cmd_box(dev, 0, mailbox->dma, srq_num, 0, MLX4_CMD_QUERY_SRQ, + MLX4_CMD_TIME_CLASS_A); +} + int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt, u64 db_rec, struct mlx4_srq *srq) { @@ -205,6 +212,29 @@ int mlx4_srq_arm(struct mlx4_dev *dev, struct mlx4_srq *srq, int limit_watermark } EXPORT_SYMBOL_GPL(mlx4_srq_arm); +int mlx4_srq_query(struct mlx4_dev *dev, struct mlx4_srq *srq, int *limit_watermark) +{ + struct mlx4_cmd_mailbox *mailbox; + struct mlx4_srq_context *srq_context; + int err; + + mailbox = mlx4_alloc_cmd_mailbox(dev); + if (IS_ERR(mailbox)) + return PTR_ERR(mailbox); + + srq_context = mailbox->buf; + + err = mlx4_QUERY_SRQ(dev, mailbox, srq->srqn); + if (err) + goto err_out; + *limit_watermark = srq_context->limit_watermark; + +err_out: + mlx4_free_cmd_mailbox(dev, mailbox); + return err; +} +EXPORT_SYMBOL_GPL(mlx4_srq_query); + int __devinit mlx4_init_srq_table(struct mlx4_dev *dev) { struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table; diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 5d14be7405a..e1732c164a4 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -60,6 +60,7 @@ #include <linux/crc32.h> #include <linux/moduleparam.h> #include <linux/io.h> +#include <linux/log2.h> #include <net/checksum.h> #include <asm/byteorder.h> #include <asm/io.h> @@ -71,7 +72,7 @@ #include "myri10ge_mcp.h" #include "myri10ge_mcp_gen_header.h" -#define MYRI10GE_VERSION_STR "1.3.0-1.233" +#define MYRI10GE_VERSION_STR "1.3.1-1.248" MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); MODULE_AUTHOR("Maintainer: help@myri.com"); @@ -279,6 +280,8 @@ static int myri10ge_fill_thresh = 256; module_param(myri10ge_fill_thresh, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed\n"); +static int myri10ge_reset_recover = 1; + static int myri10ge_wcfifo = 0; module_param(myri10ge_wcfifo, int, S_IRUGO); MODULE_PARM_DESC(myri10ge_wcfifo, "Enable WC Fifo when WC is enabled\n"); @@ -1154,9 +1157,11 @@ static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp) struct mcp_irq_data *stats = mgp->fw_stats; if (unlikely(stats->stats_updated)) { - if (mgp->link_state != stats->link_up) { - mgp->link_state = stats->link_up; - if (mgp->link_state) { + unsigned link_up = ntohl(stats->link_up); + if (mgp->link_state != link_up) { + mgp->link_state = link_up; + + if (mgp->link_state == MXGEFW_LINK_UP) { if (netif_msg_link(mgp)) printk(KERN_INFO "myri10ge: %s: link up\n", @@ -1166,8 +1171,11 @@ static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp) } else { if (netif_msg_link(mgp)) printk(KERN_INFO - "myri10ge: %s: link down\n", - mgp->dev->name); + "myri10ge: %s: link %s\n", + mgp->dev->name, + (link_up == MXGEFW_LINK_MYRINET ? + "mismatch (Myrinet detected)" : + "down")); netif_carrier_off(mgp->dev); mgp->link_changes++; } @@ -1472,6 +1480,7 @@ static const struct ethtool_ops myri10ge_ethtool_ops = { .set_sg = ethtool_op_set_sg, .get_tso = ethtool_op_get_tso, .set_tso = ethtool_op_set_tso, + .get_link = ethtool_op_get_link, .get_strings = myri10ge_get_strings, .get_stats_count = myri10ge_get_stats_count, .get_ethtool_stats = myri10ge_get_ethtool_stats, @@ -1796,7 +1805,7 @@ static int myri10ge_open(struct net_device *dev) */ big_pow2 = dev->mtu + ETH_HLEN + VLAN_HLEN + MXGEFW_PAD; if (big_pow2 < MYRI10GE_ALLOC_SIZE / 2) { - while ((big_pow2 & (big_pow2 - 1)) != 0) + while (!is_power_of_2(big_pow2)) big_pow2++; mgp->big_bytes = dev->mtu + ETH_HLEN + VLAN_HLEN + MXGEFW_PAD; } else { @@ -2729,8 +2738,14 @@ static void myri10ge_watchdog(struct work_struct *work) * For now, just report it */ reboot = myri10ge_read_reboot(mgp); printk(KERN_ERR - "myri10ge: %s: NIC rebooted (0x%x), resetting\n", - mgp->dev->name, reboot); + "myri10ge: %s: NIC rebooted (0x%x),%s resetting\n", + mgp->dev->name, reboot, + myri10ge_reset_recover ? " " : " not"); + if (myri10ge_reset_recover == 0) + return; + + myri10ge_reset_recover--; + /* * A rebooted nic will come back with config space as * it was after power was applied to PCIe bus. @@ -2840,6 +2855,8 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return -ENOMEM; } + SET_NETDEV_DEV(netdev, &pdev->dev); + mgp = netdev_priv(netdev); memset(mgp, 0, sizeof(*mgp)); mgp->dev = netdev; diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 4cf0d3fcb51..3450051ae56 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -690,7 +690,7 @@ static ssize_t natsemi_set_dspcfg_workaround(struct device *dev, { struct netdev_private *np = netdev_priv(to_net_dev(dev)); int new_setting; - u32 flags; + unsigned long flags; /* Find out the new setting */ if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1)) @@ -2357,8 +2357,8 @@ static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do) np->rx_dma[entry], buflen, PCI_DMA_FROMDEVICE); - eth_copy_and_sum(skb, - np->rx_skbuff[entry]->data, pkt_len, 0); + skb_copy_to_linear_data(skb, + np->rx_skbuff[entry]->data, pkt_len); skb_put(skb, pkt_len); pci_dma_sync_single_for_device(np->pci_dev, np->rx_dma[entry], diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index ad6688eab26..325269d8ae3 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -68,9 +68,10 @@ #define _NETXEN_NIC_LINUX_SUBVERSION 2 #define NETXEN_NIC_LINUX_VERSIONID "3.4.2" -#define NUM_FLASH_SECTORS (64) -#define FLASH_SECTOR_SIZE (64 * 1024) -#define FLASH_TOTAL_SIZE (NUM_FLASH_SECTORS * FLASH_SECTOR_SIZE) +#define NETXEN_NUM_FLASH_SECTORS (64) +#define NETXEN_FLASH_SECTOR_SIZE (64 * 1024) +#define NETXEN_FLASH_TOTAL_SIZE (NETXEN_NUM_FLASH_SECTORS \ + * NETXEN_FLASH_SECTOR_SIZE) #define PHAN_VENDOR_ID 0x4040 @@ -677,28 +678,28 @@ struct netxen_new_user_info { /* Flash memory map */ typedef enum { - CRBINIT_START = 0, /* Crbinit section */ - BRDCFG_START = 0x4000, /* board config */ - INITCODE_START = 0x6000, /* pegtune code */ - BOOTLD_START = 0x10000, /* bootld */ - IMAGE_START = 0x43000, /* compressed image */ - SECONDARY_START = 0x200000, /* backup images */ - PXE_START = 0x3E0000, /* user defined region */ - USER_START = 0x3E8000, /* User defined region for new boards */ - FIXED_START = 0x3F0000 /* backup of crbinit */ + NETXEN_CRBINIT_START = 0, /* Crbinit section */ + NETXEN_BRDCFG_START = 0x4000, /* board config */ + NETXEN_INITCODE_START = 0x6000, /* pegtune code */ + NETXEN_BOOTLD_START = 0x10000, /* bootld */ + NETXEN_IMAGE_START = 0x43000, /* compressed image */ + NETXEN_SECONDARY_START = 0x200000, /* backup images */ + NETXEN_PXE_START = 0x3E0000, /* user defined region */ + NETXEN_USER_START = 0x3E8000, /* User defined region for new boards */ + NETXEN_FIXED_START = 0x3F0000 /* backup of crbinit */ } netxen_flash_map_t; -#define USER_START_OLD PXE_START /* for backward compatibility */ - -#define FLASH_START (CRBINIT_START) -#define INIT_SECTOR (0) -#define PRIMARY_START (BOOTLD_START) -#define FLASH_CRBINIT_SIZE (0x4000) -#define FLASH_BRDCFG_SIZE (sizeof(struct netxen_board_info)) -#define FLASH_USER_SIZE (sizeof(struct netxen_user_info)/sizeof(u32)) -#define FLASH_SECONDARY_SIZE (USER_START-SECONDARY_START) -#define NUM_PRIMARY_SECTORS (0x20) -#define NUM_CONFIG_SECTORS (1) +#define NETXEN_USER_START_OLD NETXEN_PXE_START /* for backward compatibility */ + +#define NETXEN_FLASH_START (NETXEN_CRBINIT_START) +#define NETXEN_INIT_SECTOR (0) +#define NETXEN_PRIMARY_START (NETXEN_BOOTLD_START) +#define NETXEN_FLASH_CRBINIT_SIZE (0x4000) +#define NETXEN_FLASH_BRDCFG_SIZE (sizeof(struct netxen_board_info)) +#define NETXEN_FLASH_USER_SIZE (sizeof(struct netxen_user_info)/sizeof(u32)) +#define NETXEN_FLASH_SECONDARY_SIZE (NETXEN_USER_START-NETXEN_SECONDARY_START) +#define NETXEN_NUM_PRIMARY_SECTORS (0x20) +#define NETXEN_NUM_CONFIG_SECTORS (1) #define PFX "NetXen: " extern char netxen_nic_driver_name[]; @@ -936,6 +937,7 @@ struct netxen_adapter { struct netxen_ring_ctx *ctx_desc; struct pci_dev *ctx_desc_pdev; dma_addr_t ctx_desc_phys_addr; + int intr_scheme; int (*enable_phy_interrupts) (struct netxen_adapter *); int (*disable_phy_interrupts) (struct netxen_adapter *); void (*handle_phy_intr) (struct netxen_adapter *); @@ -950,6 +952,24 @@ struct netxen_adapter { int (*stop_port) (struct netxen_adapter *); }; /* netxen_adapter structure */ +/* + * NetXen dma watchdog control structure + * + * Bit 0 : enabled => R/O: 1 watchdog active, 0 inactive + * Bit 1 : disable_request => 1 req disable dma watchdog + * Bit 2 : enable_request => 1 req enable dma watchdog + * Bit 3-31 : unused + */ + +#define netxen_set_dma_watchdog_disable_req(config_word) \ + _netxen_set_bits(config_word, 1, 1, 1) +#define netxen_set_dma_watchdog_enable_req(config_word) \ + _netxen_set_bits(config_word, 2, 1, 1) +#define netxen_get_dma_watchdog_enabled(config_word) \ + ((config_word) & 0x1) +#define netxen_get_dma_watchdog_disabled(config_word) \ + (((config_word) >> 1) & 0x1) + /* Max number of xmit producer threads that can run simultaneously */ #define MAX_XMIT_PRODUCERS 16 @@ -1029,8 +1049,8 @@ int netxen_nic_erase_pxe(struct netxen_adapter *adapter); /* Functions from netxen_nic_init.c */ void netxen_free_adapter_offload(struct netxen_adapter *adapter); int netxen_initialize_adapter_offload(struct netxen_adapter *adapter); -void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val); -void netxen_load_firmware(struct netxen_adapter *adapter); +int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val); +int netxen_load_firmware(struct netxen_adapter *adapter); int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose); int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp); int netxen_rom_fast_read_words(struct netxen_adapter *adapter, int addr, @@ -1048,6 +1068,7 @@ int netxen_rom_se(struct netxen_adapter *adapter, int addr); int netxen_do_rom_se(struct netxen_adapter *adapter, int addr); /* Functions from netxen_nic_isr.c */ +int netxen_nic_link_ok(struct netxen_adapter *adapter); void netxen_nic_isr_other(struct netxen_adapter *adapter); void netxen_indicate_link_status(struct netxen_adapter *adapter, u32 link); void netxen_handle_port_int(struct netxen_adapter *adapter, u32 enable); @@ -1076,40 +1097,6 @@ int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu); int netxen_nic_set_mac(struct net_device *netdev, void *p); struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev); -static inline void netxen_nic_disable_int(struct netxen_adapter *adapter) -{ - /* - * ISR_INT_MASK: Can be read from window 0 or 1. - */ - writel(0x7ff, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK)); - -} - -static inline void netxen_nic_enable_int(struct netxen_adapter *adapter) -{ - u32 mask; - - switch (adapter->ahw.board_type) { - case NETXEN_NIC_GBE: - mask = 0x77b; - break; - case NETXEN_NIC_XGBE: - mask = 0x77f; - break; - default: - mask = 0x7ff; - break; - } - - writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK)); - - if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { - mask = 0xbff; - writel(0X0, NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); - writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, - ISR_INT_TARGET_MASK)); - } -} /* * NetXen Board information @@ -1162,6 +1149,62 @@ static inline void get_brd_name_by_type(u32 type, char *name) name = "Unknown"; } +static inline int +dma_watchdog_shutdown_request(struct netxen_adapter *adapter) +{ + u32 ctrl; + + /* check if already inactive */ + if (netxen_nic_hw_read_wx(adapter, + NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4)) + printk(KERN_ERR "failed to read dma watchdog status\n"); + + if (netxen_get_dma_watchdog_enabled(ctrl) == 0) + return 1; + + /* Send the disable request */ + netxen_set_dma_watchdog_disable_req(ctrl); + netxen_crb_writelit_adapter(adapter, + NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl); + + return 0; +} + +static inline int +dma_watchdog_shutdown_poll_result(struct netxen_adapter *adapter) +{ + u32 ctrl; + + if (netxen_nic_hw_read_wx(adapter, + NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4)) + printk(KERN_ERR "failed to read dma watchdog status\n"); + + return ((netxen_get_dma_watchdog_enabled(ctrl) == 0) && + (netxen_get_dma_watchdog_disabled(ctrl) == 0)); +} + +static inline int +dma_watchdog_wakeup(struct netxen_adapter *adapter) +{ + u32 ctrl; + + if (netxen_nic_hw_read_wx(adapter, + NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4)) + printk(KERN_ERR "failed to read dma watchdog status\n"); + + if (netxen_get_dma_watchdog_enabled(ctrl)) + return 1; + + /* send the wakeup request */ + netxen_set_dma_watchdog_enable_req(ctrl); + + netxen_crb_writelit_adapter(adapter, + NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl); + + return 0; +} + + int netxen_is_flash_supported(struct netxen_adapter *adapter); int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[]); extern void netxen_change_ringparam(struct netxen_adapter *adapter); diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index 16fabb37748..0175f6c353f 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -94,7 +94,7 @@ static const char netxen_nic_gstrings_test[][ETH_GSTRING_LEN] = { static int netxen_nic_get_eeprom_len(struct net_device *dev) { - return FLASH_TOTAL_SIZE; + return NETXEN_FLASH_TOTAL_SIZE; } static void @@ -470,7 +470,7 @@ netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, return 0; } - if (offset == BOOTLD_START) { + if (offset == NETXEN_BOOTLD_START) { ret = netxen_flash_erase_primary(adapter); if (ret != FLASH_SUCCESS) { printk(KERN_ERR "%s: Flash erase failed.\n", @@ -478,10 +478,10 @@ netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, return ret; } - ret = netxen_rom_se(adapter, USER_START); + ret = netxen_rom_se(adapter, NETXEN_USER_START); if (ret != FLASH_SUCCESS) return ret; - ret = netxen_rom_se(adapter, FIXED_START); + ret = netxen_rom_se(adapter, NETXEN_FIXED_START); if (ret != FLASH_SUCCESS) return ret; diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h index 608e37b349b..3276866b17e 100644 --- a/drivers/net/netxen/netxen_nic_hdr.h +++ b/drivers/net/netxen/netxen_nic_hdr.h @@ -687,4 +687,6 @@ enum { #define PCIE_MAX_MASTER_SPLIT (0x14048) +#define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL (0x14) + #endif /* __NETXEN_NIC_HDR_H_ */ diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index baff17a24d6..aac15421bd1 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -257,7 +257,7 @@ u64 ctx_addr_sig_regs[][3] = { #define ADDR_IN_RANGE(addr, low, high) \ (((addr) <= (high)) && ((addr) >= (low))) -#define NETXEN_FLASH_BASE (BOOTLD_START) +#define NETXEN_FLASH_BASE (NETXEN_BOOTLD_START) #define NETXEN_PHANTOM_MEM_BASE (NETXEN_FLASH_BASE) #define NETXEN_MAX_MTU 8000 + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE #define NETXEN_MIN_MTU 64 @@ -377,7 +377,7 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter) recv_crb_registers[ctx]. crb_rcvpeg_state)); while (state != PHAN_PEG_RCV_INITIALIZED && loops < 20) { - udelay(100); + msleep(1); /* Window 1 call */ state = readl(NETXEN_CRB_NORMALIZE(adapter, recv_crb_registers @@ -392,7 +392,11 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter) return err; } } - DPRINTK(INFO, "Recieve Peg ready too. starting stuff\n"); + adapter->intr_scheme = readl( + NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_FW)); + printk(KERN_NOTICE "%s: FW capabilities:0x%x\n", netxen_nic_driver_name, + adapter->intr_scheme); + DPRINTK(INFO, "Receive Peg ready too. starting stuff\n"); addr = netxen_alloc(adapter->ahw.pdev, sizeof(struct netxen_ring_ctx) + @@ -611,7 +615,7 @@ int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[]) u32 *pmac = (u32 *) & mac[0]; if (netxen_get_flash_block(adapter, - USER_START + + NETXEN_USER_START + offsetof(struct netxen_new_user_info, mac_addr), FLASH_NUM_PORTS * sizeof(u64), pmac) == -1) { @@ -619,7 +623,7 @@ int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[]) } if (*mac == ~0ULL) { if (netxen_get_flash_block(adapter, - USER_START_OLD + + NETXEN_USER_START_OLD + offsetof(struct netxen_user_old_info, mac_addr), FLASH_NUM_PORTS * sizeof(u64), @@ -697,7 +701,7 @@ void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw) adapter->curr_window = 0; } -void netxen_load_firmware(struct netxen_adapter *adapter) +int netxen_load_firmware(struct netxen_adapter *adapter) { int i; u32 data, size = 0; @@ -709,15 +713,24 @@ void netxen_load_firmware(struct netxen_adapter *adapter) writel(1, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST)); for (i = 0; i < size; i++) { - if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0) { - DPRINTK(ERR, - "Error in netxen_rom_fast_read(). Will skip" - "loading flash image\n"); - return; - } + int retries = 10; + if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0) + return -EIO; + off = netxen_nic_pci_set_window(adapter, memaddr); addr = pci_base_offset(adapter, off); writel(data, addr); + do { + if (readl(addr) == data) + break; + msleep(100); + writel(data, addr); + } while (--retries); + if (!retries) { + printk(KERN_ERR "%s: firmware load aborted, write failed at 0x%x\n", + netxen_nic_driver_name, memaddr); + return -EIO; + } flashaddr += 4; memaddr += 4; } @@ -727,7 +740,7 @@ void netxen_load_firmware(struct netxen_adapter *adapter) NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL)); writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST)); - udelay(100); + return 0; } int @@ -942,7 +955,7 @@ netxen_nic_pci_set_window(struct netxen_adapter *adapter, int netxen_nic_erase_pxe(struct netxen_adapter *adapter) { - if (netxen_rom_fast_write(adapter, PXE_START, 0) == -1) { + if (netxen_rom_fast_write(adapter, NETXEN_PXE_START, 0) == -1) { printk(KERN_ERR "%s: erase pxe failed\n", netxen_nic_driver_name); return -1; @@ -953,7 +966,7 @@ netxen_nic_erase_pxe(struct netxen_adapter *adapter) int netxen_nic_get_board_info(struct netxen_adapter *adapter) { int rv = 0; - int addr = BRDCFG_START; + int addr = NETXEN_BRDCFG_START; struct netxen_board_info *boardinfo; int index; u32 *ptr32; @@ -1115,7 +1128,7 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter) u32 fw_build = 0; char brd_name[NETXEN_MAX_SHORT_NAME]; struct netxen_new_user_info user_info; - int i, addr = USER_START; + int i, addr = NETXEN_USER_START; __le32 *ptr32; struct netxen_board_info *board_info = &(adapter->ahw.boardcfg); diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index a3689245776..1811bcb8c38 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -139,6 +139,8 @@ int netxen_init_firmware(struct netxen_adapter *adapter) return err; } /* Window 1 call */ + writel(INTR_SCHEME_PERPORT, + NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_HOST)); writel(MPORT_MULTI_FUNCTION_MODE, NETXEN_CRB_NORMALIZE(adapter, CRB_MPORT_MODE)); writel(PHAN_INITIALIZE_ACK, @@ -405,10 +407,7 @@ static inline int do_rom_fast_write(struct netxen_adapter *adapter, int addr, static inline int do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) { - if (jiffies > (last_schedule_time + (8 * HZ))) { - last_schedule_time = jiffies; - schedule(); - } + cond_resched(); netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr); netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3); @@ -585,7 +584,7 @@ int netxen_backup_crbinit(struct netxen_adapter *adapter) { int ret = FLASH_SUCCESS; int val; - char *buffer = kmalloc(FLASH_SECTOR_SIZE, GFP_KERNEL); + char *buffer = kmalloc(NETXEN_FLASH_SECTOR_SIZE, GFP_KERNEL); if (!buffer) return -ENOMEM; @@ -601,13 +600,13 @@ int netxen_backup_crbinit(struct netxen_adapter *adapter) goto out_kfree; /* copy sector 0 to sector 63 */ - ret = netxen_rom_fast_read_words(adapter, CRBINIT_START, - buffer, FLASH_SECTOR_SIZE); + ret = netxen_rom_fast_read_words(adapter, NETXEN_CRBINIT_START, + buffer, NETXEN_FLASH_SECTOR_SIZE); if (ret != FLASH_SUCCESS) goto out_kfree; - ret = netxen_rom_fast_write_words(adapter, FIXED_START, - buffer, FLASH_SECTOR_SIZE); + ret = netxen_rom_fast_write_words(adapter, NETXEN_FIXED_START, + buffer, NETXEN_FLASH_SECTOR_SIZE); if (ret != FLASH_SUCCESS) goto out_kfree; @@ -654,7 +653,8 @@ void check_erased_flash(struct netxen_adapter *adapter, int addr) int count = 0, erased_errors = 0; int range; - range = (addr == USER_START) ? FIXED_START : addr + FLASH_SECTOR_SIZE; + range = (addr == NETXEN_USER_START) ? + NETXEN_FIXED_START : addr + NETXEN_FLASH_SECTOR_SIZE; for (i = addr; i < range; i += 4) { netxen_rom_fast_read(adapter, i, &val); @@ -689,7 +689,7 @@ netxen_flash_erase_sections(struct netxen_adapter *adapter, int start, int end) int i; for (i = start; i < end; i++) { - ret = netxen_rom_se(adapter, i * FLASH_SECTOR_SIZE); + ret = netxen_rom_se(adapter, i * NETXEN_FLASH_SECTOR_SIZE); if (ret) break; ret = netxen_rom_wip_poll(adapter); @@ -706,8 +706,8 @@ netxen_flash_erase_secondary(struct netxen_adapter *adapter) int ret = FLASH_SUCCESS; int start, end; - start = SECONDARY_START / FLASH_SECTOR_SIZE; - end = USER_START / FLASH_SECTOR_SIZE; + start = NETXEN_SECONDARY_START / NETXEN_FLASH_SECTOR_SIZE; + end = NETXEN_USER_START / NETXEN_FLASH_SECTOR_SIZE; ret = netxen_flash_erase_sections(adapter, start, end); return ret; @@ -719,8 +719,8 @@ netxen_flash_erase_primary(struct netxen_adapter *adapter) int ret = FLASH_SUCCESS; int start, end; - start = PRIMARY_START / FLASH_SECTOR_SIZE; - end = SECONDARY_START / FLASH_SECTOR_SIZE; + start = NETXEN_PRIMARY_START / NETXEN_FLASH_SECTOR_SIZE; + end = NETXEN_SECONDARY_START / NETXEN_FLASH_SECTOR_SIZE; ret = netxen_flash_erase_sections(adapter, start, end); return ret; @@ -853,10 +853,10 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) netxen_nic_pci_change_crbwindow(adapter, 1); } if (init_delay == 1) { - ssleep(1); + msleep(2000); init_delay = 0; } - msleep(1); + msleep(20); } kfree(buf); @@ -932,10 +932,6 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter) void netxen_free_adapter_offload(struct netxen_adapter *adapter) { if (adapter->dummy_dma.addr) { - writel(0, NETXEN_CRB_NORMALIZE(adapter, - CRB_HOST_DUMMY_BUF_ADDR_HI)); - writel(0, NETXEN_CRB_NORMALIZE(adapter, - CRB_HOST_DUMMY_BUF_ADDR_LO)); pci_free_consistent(adapter->ahw.pdev, NETXEN_HOST_DUMMY_DMA_SIZE, adapter->dummy_dma.addr, @@ -944,25 +940,32 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter) } } -void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) +int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) { u32 val = 0; - int loops = 0; + int retries = 30; if (!pegtune_val) { - val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)); - while (val != PHAN_INITIALIZE_COMPLETE && - val != PHAN_INITIALIZE_ACK && loops < 200000) { - udelay(100); - schedule(); - val = - readl(NETXEN_CRB_NORMALIZE + do { + val = readl(NETXEN_CRB_NORMALIZE (adapter, CRB_CMDPEG_STATE)); - loops++; + pegtune_val = readl(NETXEN_CRB_NORMALIZE + (adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE)); + + if (val == PHAN_INITIALIZE_COMPLETE || + val == PHAN_INITIALIZE_ACK) + return 0; + + msleep(1000); + } while (--retries); + if (!retries) { + printk(KERN_WARNING "netxen_phantom_init: init failed, " + "pegtune_val=%x\n", pegtune_val); + return -1; } - if (val != PHAN_INITIALIZE_COMPLETE) - printk("WARNING: Initial boot wait loop failed...\n"); } + + return 0; } int netxen_nic_rx_has_work(struct netxen_adapter *adapter) @@ -1036,18 +1039,23 @@ void netxen_watchdog_task(struct work_struct *work) if ((adapter->portnum == 0) && netxen_nic_check_temp(adapter)) return; + if (adapter->handle_phy_intr) + adapter->handle_phy_intr(adapter); + netdev = adapter->netdev; - if ((netif_running(netdev)) && !netif_carrier_ok(netdev)) { - printk(KERN_INFO "%s port %d, %s carrier is now ok\n", - netxen_nic_driver_name, adapter->portnum, netdev->name); + if ((netif_running(netdev)) && !netif_carrier_ok(netdev) && + netxen_nic_link_ok(adapter) ) { + printk(KERN_INFO "%s %s (port %d), Link is up\n", + netxen_nic_driver_name, netdev->name, adapter->portnum); netif_carrier_on(netdev); - } - - if (netif_queue_stopped(netdev)) netif_wake_queue(netdev); + } else if(!(netif_running(netdev)) && netif_carrier_ok(netdev)) { + printk(KERN_ERR "%s %s Link is Down\n", + netxen_nic_driver_name, netdev->name); + netif_carrier_off(netdev); + netif_stop_queue(netdev); + } - if (adapter->handle_phy_intr) - adapter->handle_phy_intr(adapter); mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); } @@ -1114,6 +1122,7 @@ netxen_process_rcv(struct netxen_adapter *adapter, int ctxid, adapter->stats.csummed++; skb->ip_summed = CHECKSUM_UNNECESSARY; } + skb->dev = netdev; if (desc_ctx == RCV_DESC_LRO_CTXID) { /* True length was only available on the last pkt */ skb_put(skb, buffer->lro_length); @@ -1218,6 +1227,7 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max) NETXEN_CRB_NORMALIZE(adapter, recv_crb_registers[adapter->portnum]. crb_rcv_status_consumer)); + wmb(); } return count; @@ -1270,11 +1280,13 @@ int netxen_process_cmd_ring(unsigned long data) if (skb && (cmpxchg(&buffer->skb, skb, 0) == skb)) { pci_unmap_single(pdev, frag->dma, frag->length, PCI_DMA_TODEVICE); + frag->dma = 0ULL; for (i = 1; i < buffer->frag_count; i++) { DPRINTK(INFO, "getting fragment no %d\n", i); frag++; /* Get the next frag */ pci_unmap_page(pdev, frag->dma, frag->length, PCI_DMA_TODEVICE); + frag->dma = 0ULL; } adapter->stats.skbfreed++; @@ -1440,6 +1452,7 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) writel(msg, DB_NORMALIZE(adapter, NETXEN_RCV_PRODUCER_OFFSET)); + wmb(); } } } diff --git a/drivers/net/netxen/netxen_nic_isr.c b/drivers/net/netxen/netxen_nic_isr.c index b213b062eb5..b2de6b6c2a7 100644 --- a/drivers/net/netxen/netxen_nic_isr.c +++ b/drivers/net/netxen/netxen_nic_isr.c @@ -169,6 +169,24 @@ void netxen_nic_gbe_handle_phy_intr(struct netxen_adapter *adapter) netxen_nic_isr_other(adapter); } +int netxen_nic_link_ok(struct netxen_adapter *adapter) +{ + switch (adapter->ahw.board_type) { + case NETXEN_NIC_GBE: + return ((adapter->ahw.qg_linksup) & 1); + + case NETXEN_NIC_XGBE: + return ((adapter->ahw.xg_linkup) & 1); + + default: + printk(KERN_ERR"%s: Function: %s, Unknown board type\n", + netxen_nic_driver_name, __FUNCTION__); + break; + } + + return 0; +} + void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter) { struct net_device *netdev = adapter->netdev; @@ -183,6 +201,10 @@ void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter) printk(KERN_INFO "%s: %s NIC Link is down\n", netxen_nic_driver_name, netdev->name); adapter->ahw.xg_linkup = 0; + if (netif_running(netdev)) { + netif_carrier_off(netdev); + netif_stop_queue(netdev); + } /* read twice to clear sticky bits */ /* WINDOW = 0 */ netxen_nic_read_w0(adapter, NETXEN_NIU_XG_STATUS, &val1); @@ -196,5 +218,7 @@ void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter) printk(KERN_INFO "%s: %s NIC Link is up\n", netxen_nic_driver_name, netdev->name); adapter->ahw.xg_linkup = 1; + netif_carrier_on(netdev); + netif_wake_queue(netdev); } } diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 2c5c6d20e6e..b703ccfe040 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -54,8 +54,6 @@ static char netxen_nic_driver_string[] = "NetXen Network Driver version " #define NETXEN_ADAPTER_UP_MAGIC 777 #define NETXEN_NIC_PEG_TUNE 0 -u8 nx_p2_id = NX_P2_C0; - #define DMA_32BIT_MASK 0x00000000ffffffffULL #define DMA_35BIT_MASK 0x00000007ffffffffULL @@ -156,6 +154,103 @@ static inline void netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter #define ADAPTER_LIST_SIZE 12 int netxen_cards_found; +static void netxen_nic_disable_int(struct netxen_adapter *adapter) +{ + uint32_t mask = 0x7ff; + int retries = 32; + + DPRINTK(1, INFO, "Entered ISR Disable \n"); + + switch (adapter->portnum) { + case 0: + writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0)); + break; + case 1: + writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1)); + break; + case 2: + writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2)); + break; + case 3: + writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3)); + break; + } + + if (adapter->intr_scheme != -1 && + adapter->intr_scheme != INTR_SCHEME_PERPORT) + writel(mask,PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK)); + + /* Window = 0 or 1 */ + if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { + do { + writel(0xffffffff, + PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_STATUS)); + mask = readl(pci_base_offset(adapter, ISR_INT_VECTOR)); + if (!(mask & 0x80)) + break; + udelay(10); + } while (--retries); + + if (!retries) { + printk(KERN_NOTICE "%s: Failed to disable interrupt completely\n", + netxen_nic_driver_name); + } + } + + DPRINTK(1, INFO, "Done with Disable Int\n"); +} + +static void netxen_nic_enable_int(struct netxen_adapter *adapter) +{ + u32 mask; + + DPRINTK(1, INFO, "Entered ISR Enable \n"); + + if (adapter->intr_scheme != -1 && + adapter->intr_scheme != INTR_SCHEME_PERPORT) { + switch (adapter->ahw.board_type) { + case NETXEN_NIC_GBE: + mask = 0x77b; + break; + case NETXEN_NIC_XGBE: + mask = 0x77f; + break; + default: + mask = 0x7ff; + break; + } + + writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK)); + } + + switch (adapter->portnum) { + case 0: + writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0)); + break; + case 1: + writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1)); + break; + case 2: + writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2)); + break; + case 3: + writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3)); + break; + } + + if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { + mask = 0xbff; + if (adapter->intr_scheme != -1 && + adapter->intr_scheme != INTR_SCHEME_PERPORT) { + writel(0X0, NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); + } + writel(mask, + PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_MASK)); + } + + DPRINTK(1, INFO, "Done with enable Int\n"); +} + /* * netxen_nic_probe() * @@ -210,8 +305,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_disable_pdev; pci_set_master(pdev); - pci_read_config_byte(pdev, PCI_REVISION_ID, &nx_p2_id); - if (nx_p2_id == NX_P2_C1 && + if (pdev->revision == NX_P2_C1 && (pci_set_dma_mask(pdev, DMA_35BIT_MASK) == 0) && (pci_set_consistent_dma_mask(pdev, DMA_35BIT_MASK) == 0)) { pci_using_dac = 1; @@ -308,7 +402,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->netdev = netdev; adapter->pdev = pdev; + + /* this will be read from FW later */ + adapter->intr_scheme = -1; + + /* This will be reset for mezz cards */ adapter->portnum = pci_func_id; + adapter->status &= ~NETXEN_NETDEV_STATUS; netdev->open = netxen_nic_open; netdev->stop = netxen_nic_close; @@ -336,11 +436,9 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; - if (pci_enable_msi(pdev)) { + if (pci_enable_msi(pdev)) adapter->flags &= ~NETXEN_NIC_MSI_ENABLED; - printk(KERN_WARNING "%s: unable to allocate MSI interrupt" - " error\n", netxen_nic_driver_name); - } else + else adapter->flags |= NETXEN_NIC_MSI_ENABLED; netdev->irq = pdev->irq; @@ -355,13 +453,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* initialize the adapter */ netxen_initialize_adapter_hw(adapter); -#ifdef CONFIG_PPC - if ((adapter->ahw.boardcfg.board_type == - NETXEN_BRDTYPE_P2_SB31_10G_IMEZ) && - (pci_func_id == 2)) - goto err_out_free_adapter; -#endif /* CONFIG_PPC */ - /* * Adapter in our case is quad port so initialize it before * initializing the ports @@ -458,7 +549,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task); adapter->ahw.pdev = pdev; adapter->proc_cmd_buf_counter = 0; - adapter->ahw.revision_id = nx_p2_id; + adapter->ahw.revision_id = pdev->revision; /* make sure Window == 1 */ netxen_nic_pci_change_crbwindow(adapter, 1); @@ -509,22 +600,30 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) NETXEN_CAM_RAM(0x1fc))); if (val == 0x55555555) { /* This is the first boot after power up */ + netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(0x4), &val); + if (!(val & 0x4)) { + val |= 0x4; + netxen_nic_write_w0(adapter, NETXEN_PCIE_REG(0x4), val); + netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(0x4), &val); + if (!(val & 0x4)) + printk(KERN_ERR "%s: failed to set MSI bit in PCI-e reg\n", + netxen_nic_driver_name); + } val = readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_SW_RESET)); printk(KERN_INFO"NetXen: read 0x%08x for reset reg.\n",val); if (val != 0x80000f) { /* clear the register for future unloads/loads */ - writel(0, NETXEN_CRB_NORMALIZE(adapter, - NETXEN_CAM_RAM(0x1fc))); - printk(KERN_ERR "ERROR in NetXen HW init sequence.\n"); - err = -ENODEV; - goto err_out_free_dev; + writel(0, NETXEN_CRB_NORMALIZE(adapter, + NETXEN_CAM_RAM(0x1fc))); + printk(KERN_ERR "ERROR in NetXen HW init sequence.\n"); + err = -ENODEV; + goto err_out_free_dev; } - - /* clear the register for future unloads/loads */ - writel(0, NETXEN_CRB_NORMALIZE(adapter, - NETXEN_CAM_RAM(0x1fc))); } + + /* clear the register for future unloads/loads */ + writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_CAM_RAM(0x1fc))); printk(KERN_INFO "State: 0x%0x\n", readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE))); @@ -632,8 +731,8 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) struct netxen_rx_buffer *buffer; struct netxen_recv_context *recv_ctx; struct netxen_rcv_desc_ctx *rcv_desc; - int i; - int ctxid, ring; + int i, ctxid, ring; + static int init_firmware_done = 0; adapter = pci_get_drvdata(pdev); if (adapter == NULL) @@ -641,32 +740,20 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) netdev = adapter->netdev; - netxen_nic_disable_int(adapter); - if (adapter->irq) - free_irq(adapter->irq, adapter); - + unregister_netdev(netdev); + if (adapter->stop_port) adapter->stop_port(adapter); - if ((adapter->flags & NETXEN_NIC_MSI_ENABLED)) - pci_disable_msi(pdev); - - if (adapter->portnum == 0) - netxen_free_adapter_offload(adapter); + netxen_nic_disable_int(adapter); if (adapter->irq) free_irq(adapter->irq, adapter); - if(adapter->portnum == 0) { - /* leave the hw in the same state as reboot */ - writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)); - netxen_pinit_from_rom(adapter, 0); - udelay(500); - netxen_load_firmware(adapter); - netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); - } - if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) + if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { + init_firmware_done++; netxen_free_hw_resources(adapter); + } for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) { recv_ctx = &adapter->recv_ctx[ctxid]; @@ -686,17 +773,73 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) } } - unregister_netdev(netdev); + if (adapter->flags & NETXEN_NIC_MSI_ENABLED) + pci_disable_msi(pdev); vfree(adapter->cmd_buf_arr); + pci_disable_device(pdev); + + if (adapter->portnum == 0) { + if (init_firmware_done) { + dma_watchdog_shutdown_request(adapter); + msleep(100); + i = 100; + while ((dma_watchdog_shutdown_poll_result(adapter) != 1) && i) { + printk(KERN_INFO "dma_watchdog_shutdown_poll still in progress\n"); + msleep(100); + i--; + } + + if (i == 0) { + printk(KERN_ERR "dma_watchdog_shutdown_request failed\n"); + return; + } + + /* clear the register for future unloads/loads */ + writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_CAM_RAM(0x1fc))); + printk(KERN_INFO "State: 0x%0x\n", + readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE))); + + /* leave the hw in the same state as reboot */ + writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)); + if (netxen_pinit_from_rom(adapter, 0)) + return; + msleep(1); + if (netxen_load_firmware(adapter)) + return; + netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); + } + + /* clear the register for future unloads/loads */ + writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_CAM_RAM(0x1fc))); + printk(KERN_INFO "State: 0x%0x\n", + readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE))); + + dma_watchdog_shutdown_request(adapter); + msleep(100); + i = 100; + while ((dma_watchdog_shutdown_poll_result(adapter) != 1) && i) { + printk(KERN_INFO "dma_watchdog_shutdown_poll still in progress\n"); + msleep(100); + i--; + } + + if (i) { + netxen_free_adapter_offload(adapter); + } else { + printk(KERN_ERR "failed to dma shutdown\n"); + return; + } + + } + iounmap(adapter->ahw.db_base); iounmap(adapter->ahw.pci_base0); iounmap(adapter->ahw.pci_base1); iounmap(adapter->ahw.pci_base2); pci_release_regions(pdev); - pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); free_netdev(netdev); @@ -793,7 +936,7 @@ static int netxen_nic_close(struct net_device *netdev) if (buffrag->dma) { pci_unmap_single(adapter->pdev, buffrag->dma, buffrag->length, PCI_DMA_TODEVICE); - buffrag->dma = (u64) NULL; + buffrag->dma = 0ULL; } for (j = 0; j < cmd_buff->frag_count; j++) { buffrag++; @@ -801,7 +944,7 @@ static int netxen_nic_close(struct net_device *netdev) pci_unmap_page(adapter->pdev, buffrag->dma, buffrag->length, PCI_DMA_TODEVICE); - buffrag->dma = (u64) NULL; + buffrag->dma = 0ULL; } } /* Free the skb we received in netxen_nic_xmit_frame */ @@ -811,8 +954,10 @@ static int netxen_nic_close(struct net_device *netdev) } cmd_buff++; } - FLUSH_SCHEDULED_WORK(); - del_timer_sync(&adapter->watchdog_timer); + if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { + FLUSH_SCHEDULED_WORK(); + del_timer_sync(&adapter->watchdog_timer); + } return 0; } @@ -1098,28 +1243,26 @@ static int netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev) { u32 ret = 0; + u32 our_int = 0; DPRINTK(INFO, "Entered handle ISR\n"); adapter->stats.ints++; if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { - int count = 0; - u32 mask; - u32 our_int = 0; our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); /* not our interrupt */ if ((our_int & (0x80 << adapter->portnum)) == 0) return ret; - netxen_nic_disable_int(adapter); - /* Window = 0 or 1 */ - do { - writel(0xffffffff, PCI_OFFSET_SECOND_RANGE(adapter, - ISR_INT_TARGET_STATUS)); - mask = readl(pci_base_offset(adapter, ISR_INT_VECTOR)); - } while (((mask & 0x80) != 0) && (++count < 32)); - if ((mask & 0x80) != 0) - printk("Could not disable interrupt completely\n"); + } + netxen_nic_disable_int(adapter); + + if (adapter->intr_scheme == INTR_SCHEME_PERPORT) { + /* claim interrupt */ + if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { + writel(our_int & ~((u32)(0x80 << adapter->portnum)), + NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR)); + } } if (netxen_nic_rx_has_work(adapter) || netxen_nic_tx_has_work(adapter)) { @@ -1131,7 +1274,7 @@ netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev) } else { static unsigned int intcount = 0; if ((++intcount & 0xfff) == 0xfff) - printk(KERN_ERR + DPRINTK(KERN_ERR "%s: %s interrupt %d while in poll\n", netxen_nic_driver_name, netdev->name, intcount); @@ -1253,6 +1396,7 @@ static void __exit netxen_exit_module(void) /* * Wait for some time to allow the dma to drain, if any. */ + msleep(100); pci_unregister_driver(&netxen_driver); destroy_workqueue(netxen_workq); } diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c index cef90a78351..05e0577a0e1 100644 --- a/drivers/net/netxen/netxen_nic_niu.c +++ b/drivers/net/netxen/netxen_nic_niu.c @@ -454,16 +454,12 @@ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port) int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port) { - u32 reg; u32 portnum = physical_port[adapter->portnum]; netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_XGE_CONFIG_0+(0x10000*portnum), 0x5); - netxen_nic_hw_read_wx(adapter, - NETXEN_NIU_XGE_CONFIG_1+(0x10000*portnum), ®, 4); - reg = (reg & ~0x2000UL); + NETXEN_NIU_XGE_CONFIG_1+(0x10000*portnum), 0x1447); netxen_crb_writelit_adapter(adapter, - NETXEN_NIU_XGE_CONFIG_1+(0x10000*portnum), reg); + NETXEN_NIU_XGE_CONFIG_0+(0x10000*portnum), 0x5); return 0; } @@ -728,7 +724,7 @@ int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter) __u32 mac_cfg0; u32 port = physical_port[adapter->portnum]; - if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS)) + if (port > NETXEN_NIU_MAX_GBE_PORTS) return -EINVAL; mac_cfg0 = 0; netxen_gb_soft_reset(mac_cfg0); @@ -761,7 +757,7 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, __u32 reg; u32 port = physical_port[adapter->portnum]; - if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS)) + if (port > NETXEN_NIU_MAX_GBE_PORTS) return -EINVAL; /* save previous contents */ @@ -898,7 +894,7 @@ int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter, __u32 reg; u32 port = physical_port[adapter->portnum]; - if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS)) + if (port > NETXEN_NIU_MAX_XG_PORTS) return -EINVAL; if (netxen_nic_hw_read_wx(adapter, diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h index 9457fc7249c..10fe6fafa6f 100644 --- a/drivers/net/netxen/netxen_nic_phan_reg.h +++ b/drivers/net/netxen/netxen_nic_phan_reg.h @@ -114,6 +114,20 @@ #define CRB_V2P_3 NETXEN_NIC_REG(0x29c) #define CRB_V2P(port) (CRB_V2P_0+((port)*4)) #define CRB_DRIVER_VERSION NETXEN_NIC_REG(0x2a0) +/* sw int status/mask registers */ +#define CRB_SW_INT_MASK_0 NETXEN_NIC_REG(0x1d8) +#define CRB_SW_INT_MASK_1 NETXEN_NIC_REG(0x1e0) +#define CRB_SW_INT_MASK_2 NETXEN_NIC_REG(0x1e4) +#define CRB_SW_INT_MASK_3 NETXEN_NIC_REG(0x1e8) + +/* + * capabilities register, can be used to selectively enable/disable features + * for backward compability + */ +#define CRB_NIC_CAPABILITIES_HOST NETXEN_NIC_REG(0x1a8) +#define CRB_NIC_CAPABILITIES_FW NETXEN_NIC_REG(0x1dc) + +#define INTR_SCHEME_PERPORT 0x1 /* used for ethtool tests */ #define CRB_SCRATCHPAD_TEST NETXEN_NIC_REG(0x280) diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c index 8dbd6d1900b..5e7999db209 100644 --- a/drivers/net/ni52.c +++ b/drivers/net/ni52.c @@ -936,7 +936,7 @@ static void ni52_rcv_int(struct net_device *dev) { skb_reserve(skb,2); skb_put(skb,totlen); - eth_copy_and_sum(skb,(char *) p->base+(unsigned long) rbd->buffer,totlen,0); + skb_copy_to_linear_data(skb,(char *) p->base+(unsigned long) rbd->buffer,totlen); skb->protocol=eth_type_trans(skb,dev); netif_rx(skb); dev->last_rx = jiffies; diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c index 3818edf0ac1..4ef5fe34519 100644 --- a/drivers/net/ni65.c +++ b/drivers/net/ni65.c @@ -1096,7 +1096,7 @@ static void ni65_recv_intr(struct net_device *dev,int csr0) #ifdef RCV_VIA_SKB if( (unsigned long) (skb->data + R_BUF_SIZE) > 0x1000000) { skb_put(skb,len); - eth_copy_and_sum(skb, (unsigned char *)(p->recv_skb[p->rmdnum]->data),len,0); + skb_copy_to_linear_data(skb, (unsigned char *)(p->recv_skb[p->rmdnum]->data),len); } else { struct sk_buff *skb1 = p->recv_skb[p->rmdnum]; @@ -1108,7 +1108,7 @@ static void ni65_recv_intr(struct net_device *dev,int csr0) } #else skb_put(skb,len); - eth_copy_and_sum(skb, (unsigned char *) p->recvbounce[p->rmdnum],len,0); + skb_copy_to_linear_data(skb, (unsigned char *) p->recvbounce[p->rmdnum],len); #endif p->stats.rx_packets++; p->stats.rx_bytes += len; diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index 3439f8c649f..104aab3c957 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -506,17 +506,6 @@ static void ns83820_vlan_rx_register(struct net_device *ndev, struct vlan_group spin_unlock(&dev->tx_lock); spin_unlock_irq(&dev->misc_lock); } - -static void ns83820_vlan_rx_kill_vid(struct net_device *ndev, unsigned short vid) -{ - struct ns83820 *dev = PRIV(ndev); - - spin_lock_irq(&dev->misc_lock); - spin_lock(&dev->tx_lock); - vlan_group_set_device(dev->vlgrp, vid, NULL); - spin_unlock(&dev->tx_lock); - spin_unlock_irq(&dev->misc_lock); -} #endif /* Packet Receiver @@ -1842,11 +1831,13 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ ndev = alloc_etherdev(sizeof(struct ns83820)); dev = PRIV(ndev); - dev->ndev = ndev; + err = -ENOMEM; if (!dev) goto out; + dev->ndev = ndev; + spin_lock_init(&dev->rx_info.lock); spin_lock_init(&dev->tx_lock); spin_lock_init(&dev->misc_lock); @@ -2083,7 +2074,6 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ /* We also support hardware vlan acceleration */ ndev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; ndev->vlan_rx_register = ns83820_vlan_rx_register; - ndev->vlan_rx_kill_vid = ns83820_vlan_rx_kill_vid; #endif if (using_dac) { diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c index 8d38425e46c..0b3066a6fe4 100644 --- a/drivers/net/pasemi_mac.c +++ b/drivers/net/pasemi_mac.c @@ -755,7 +755,7 @@ static int pasemi_mac_open(struct net_device *dev) flags |= PAS_MAC_CFG_PCFG_TSR_1G | PAS_MAC_CFG_PCFG_SPD_1G; pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_RXCH_CFG(mac->dma_rxch), - PAS_IOB_DMA_RXCH_CFG_CNTTH(1)); + PAS_IOB_DMA_RXCH_CFG_CNTTH(0)); pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_TXCH_CFG(mac->dma_txch), PAS_IOB_DMA_TXCH_CFG_CNTTH(32)); diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c index df8998b4f37..3cdbe118200 100644 --- a/drivers/net/pci-skeleton.c +++ b/drivers/net/pci-skeleton.c @@ -1567,7 +1567,7 @@ static void netdrv_rx_interrupt (struct net_device *dev, if (skb) { skb_reserve (skb, 2); /* 16 byte align the IP fields. */ - eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0); + skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); skb_put (skb, pkt_size); skb->protocol = eth_type_trans (skb, dev); diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 143ae2ff309..503f2685fb7 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -629,9 +629,9 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev) outw(SetTxThreshold + 1536, ioaddr + EL3_CMD); } - dev_kfree_skb(skb); pop_tx_status(dev); spin_unlock_irqrestore(&priv->lock, flags); + dev_kfree_skb(skb); return 0; } diff --git a/drivers/net/pcmcia/Kconfig b/drivers/net/pcmcia/Kconfig index 5d658bc9791..e8f55d8ed7a 100644 --- a/drivers/net/pcmcia/Kconfig +++ b/drivers/net/pcmcia/Kconfig @@ -19,7 +19,7 @@ menuconfig NET_PCMCIA If unsure, say N. -if NET_PCMCIA +if NET_PCMCIA && PCMCIA config PCMCIA_3C589 tristate "3Com 3c589 PCMCIA support" diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 808fae1577e..50dff1b81d3 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -521,6 +521,7 @@ static void mdio_write(kio_addr_t addr, int phy_id, int loc, int value) static int axnet_open(struct net_device *dev) { + int ret; axnet_dev_t *info = PRIV(dev); struct pcmcia_device *link = info->p_dev; @@ -529,9 +530,11 @@ static int axnet_open(struct net_device *dev) if (!pcmcia_dev_present(link)) return -ENODEV; - link->open++; + ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev); + if (ret) + return ret; - request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev); + link->open++; info->link_status = 0x00; init_timer(&info->watchdog); diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 3f93d493323..85d5f2ca4bb 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -109,7 +109,7 @@ static const struct ethtool_ops netdev_ethtool_ops; card type */ typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN, - XXX10304 + XXX10304, NEC, KME } cardtype_t; /* @@ -374,6 +374,18 @@ static int fmvj18x_config(struct pcmcia_device *link) link->io.NumPorts2 = 8; } break; + case MANFID_NEC: + cardtype = NEC; /* MultiFunction Card */ + link->conf.ConfigBase = 0x800; + link->conf.ConfigIndex = 0x47; + link->io.NumPorts2 = 8; + break; + case MANFID_KME: + cardtype = KME; /* MultiFunction Card */ + link->conf.ConfigBase = 0x800; + link->conf.ConfigIndex = 0x47; + link->io.NumPorts2 = 8; + break; case MANFID_CONTEC: cardtype = CONTEC; break; @@ -450,6 +462,8 @@ static int fmvj18x_config(struct pcmcia_device *link) case TDK: case LA501: case CONTEC: + case NEC: + case KME: tuple.DesiredTuple = CISTPL_FUNCE; tuple.TupleOffset = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); @@ -469,6 +483,10 @@ static int fmvj18x_config(struct pcmcia_device *link) card_name = "TDK LAK-CD021"; } else if( cardtype == LA501 ) { card_name = "LA501"; + } else if( cardtype == NEC ) { + card_name = "PK-UG-J001"; + } else if( cardtype == KME ) { + card_name = "Panasonic"; } else { card_name = "C-NET(PC)C"; } @@ -678,8 +696,11 @@ static struct pcmcia_device_id fmvj18x_ids[] = { PCMCIA_DEVICE_PROD_ID1("PCMCIA MBH10302", 0x8f4005da), PCMCIA_DEVICE_PROD_ID1("UBKK,V2.0", 0x90888080), PCMCIA_PFC_DEVICE_PROD_ID12(0, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed), + PCMCIA_PFC_DEVICE_PROD_ID12(0, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064), PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0d0a), PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0e0a), + PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0a05), + PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x1101), PCMCIA_DEVICE_NULL, }; MODULE_DEVICE_TABLE(pcmcia, fmvj18x_ids); diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index d88e9b2e93c..63de89e93b7 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -960,6 +960,7 @@ static void mii_phy_probe(struct net_device *dev) static int pcnet_open(struct net_device *dev) { + int ret; pcnet_dev_t *info = PRIV(dev); struct pcmcia_device *link = info->p_dev; @@ -968,10 +969,12 @@ static int pcnet_open(struct net_device *dev) if (!pcmcia_dev_present(link)) return -ENODEV; - link->open++; - set_misc_reg(dev); - request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev_info, dev); + ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev_info, dev); + if (ret) + return ret; + + link->open++; info->phy_id = info->eth_phy; info->link_status = 0x00; @@ -1552,6 +1555,7 @@ static struct pcmcia_device_id pcnet_ids[] = { PCMCIA_PFC_DEVICE_PROD_ID12(0, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae), PCMCIA_PFC_DEVICE_PROD_ID12(0, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033), PCMCIA_PFC_DEVICE_PROD_ID12(0, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58), + PCMCIA_PFC_DEVICE_PROD_ID12(0, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555), PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc), PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f), PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away 28.8 PC Card ", 0xb569a6e5, 0x5bd4ff2c), @@ -1577,6 +1581,7 @@ static struct pcmcia_device_id pcnet_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1103), PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1121), PCMCIA_DEVICE_PROD_ID12("2408LAN", "Ethernet", 0x352fff7f, 0x00b2e941), + PCMCIA_DEVICE_PROD_ID1234("Socket", "CF 10/100 Ethernet Card", "Revision B", "05/11/06", 0xb38bcc2e, 0x4de88352, 0xeaca6c8d, 0x7e57c22e), PCMCIA_DEVICE_PROD_ID123("Cardwell", "PCMCIA", "ETHERNET", 0x9533672e, 0x281f1c5d, 0x3ff7175b), PCMCIA_DEVICE_PROD_ID123("CNet ", "CN30BC", "ETHERNET", 0x9fe55d3d, 0x85601198, 0x3ff7175b), PCMCIA_DEVICE_PROD_ID123("Digital", "Ethernet", "Adapter", 0x9999ab35, 0x00b2e941, 0x4b0d829e), diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 9c171a7390e..465485a3fbc 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -1235,9 +1235,9 @@ static void pcnet32_rx_entry(struct net_device *dev, lp->rx_dma_addr[entry], pkt_len, PCI_DMA_FROMDEVICE); - eth_copy_and_sum(skb, + skb_copy_to_linear_data(skb, (unsigned char *)(lp->rx_skbuff[entry]->data), - pkt_len, 0); + pkt_len); pci_dma_sync_single_for_device(lp->pci_dev, lp->rx_dma_addr[entry], pkt_len, diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 09b6f259eb9..dd09011c7ee 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -55,6 +55,11 @@ config BROADCOM_PHY ---help--- Currently supports the BCM5411, BCM5421 and BCM5461 PHYs. +config ICPLUS_PHY + tristate "Drivers for ICPlus PHYs" + ---help--- + Currently supports the IP175C PHY. + config FIXED_PHY tristate "Drivers for PHY emulation on fixed speed/link" ---help--- diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index bcd1efbd2a1..8885650647f 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -11,4 +11,5 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o obj-$(CONFIG_SMSC_PHY) += smsc.o obj-$(CONFIG_VITESSE_PHY) += vitesse.o obj-$(CONFIG_BROADCOM_PHY) += broadcom.o +obj-$(CONFIG_ICPLUS_PHY) += icplus.o obj-$(CONFIG_FIXED_PHY) += fixed.o diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c new file mode 100644 index 00000000000..af3f1f2a9f8 --- /dev/null +++ b/drivers/net/phy/icplus.c @@ -0,0 +1,134 @@ +/* + * Driver for ICPlus PHYs + * + * Copyright (c) 2007 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/errno.h> +#include <linux/unistd.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/skbuff.h> +#include <linux/spinlock.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/mii.h> +#include <linux/ethtool.h> +#include <linux/phy.h> + +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/uaccess.h> + +MODULE_DESCRIPTION("ICPlus IP175C PHY driver"); +MODULE_AUTHOR("Michael Barkowski"); +MODULE_LICENSE("GPL"); + +static int ip175c_config_init(struct phy_device *phydev) +{ + int err, i; + static int full_reset_performed = 0; + + if (full_reset_performed == 0) { + + /* master reset */ + err = phydev->bus->write(phydev->bus, 30, 0, 0x175c); + if (err < 0) + return err; + + /* ensure no bus delays overlap reset period */ + err = phydev->bus->read(phydev->bus, 30, 0); + + /* data sheet specifies reset period is 2 msec */ + mdelay(2); + + /* enable IP175C mode */ + err = phydev->bus->write(phydev->bus, 29, 31, 0x175c); + if (err < 0) + return err; + + /* Set MII0 speed and duplex (in PHY mode) */ + err = phydev->bus->write(phydev->bus, 29, 22, 0x420); + if (err < 0) + return err; + + /* reset switch ports */ + for (i = 0; i < 5; i++) { + err = phydev->bus->write(phydev->bus, i, + MII_BMCR, BMCR_RESET); + if (err < 0) + return err; + } + + for (i = 0; i < 5; i++) + err = phydev->bus->read(phydev->bus, i, MII_BMCR); + + mdelay(2); + + full_reset_performed = 1; + } + + if (phydev->addr != 4) { + phydev->state = PHY_RUNNING; + phydev->speed = SPEED_100; + phydev->duplex = DUPLEX_FULL; + phydev->link = 1; + netif_carrier_on(phydev->attached_dev); + } + + return 0; +} + +static int ip175c_read_status(struct phy_device *phydev) +{ + if (phydev->addr == 4) /* WAN port */ + genphy_read_status(phydev); + else + /* Don't need to read status for switch ports */ + phydev->irq = PHY_IGNORE_INTERRUPT; + + return 0; +} + +static int ip175c_config_aneg(struct phy_device *phydev) +{ + if (phydev->addr == 4) /* WAN port */ + genphy_config_aneg(phydev); + + return 0; +} + +static struct phy_driver ip175c_driver = { + .phy_id = 0x02430d80, + .name = "ICPlus IP175C", + .phy_id_mask = 0x0ffffff0, + .features = PHY_BASIC_FEATURES, + .config_init = &ip175c_config_init, + .config_aneg = &ip175c_config_aneg, + .read_status = &ip175c_read_status, + .driver = { .owner = THIS_MODULE,}, +}; + +static int __init ip175c_init(void) +{ + return phy_driver_register(&ip175c_driver); +} + +static void __exit ip175c_exit(void) +{ + phy_driver_unregister(&ip175c_driver); +} + +module_init(ip175c_init); +module_exit(ip175c_exit); diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 22aec5cce68..d2ede5ff9ff 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -54,6 +54,13 @@ #define MII_M1111_PHY_LED_CONTROL 0x18 #define MII_M1111_PHY_LED_DIRECT 0x4100 #define MII_M1111_PHY_LED_COMBINE 0x411c +#define MII_M1111_PHY_EXT_CR 0x14 +#define MII_M1111_RX_DELAY 0x80 +#define MII_M1111_TX_DELAY 0x2 +#define MII_M1111_PHY_EXT_SR 0x1b +#define MII_M1111_HWCFG_MODE_MASK 0xf +#define MII_M1111_HWCFG_MODE_RGMII 0xb +#define MII_M1111_HWCFG_MODE_SGMII_NO_CLK 0x4 MODULE_DESCRIPTION("Marvell PHY driver"); MODULE_AUTHOR("Andy Fleming"); @@ -131,6 +138,60 @@ static int marvell_config_aneg(struct phy_device *phydev) return err; } +static int m88e1111_config_init(struct phy_device *phydev) +{ + int err; + + if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || + (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)) { + int temp; + + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { + temp = phy_read(phydev, MII_M1111_PHY_EXT_CR); + if (temp < 0) + return temp; + + temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY); + + err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp); + if (err < 0) + return err; + } + + temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); + if (temp < 0) + return temp; + + temp &= ~(MII_M1111_HWCFG_MODE_MASK); + temp |= MII_M1111_HWCFG_MODE_RGMII; + + err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); + if (err < 0) + return err; + } + + if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { + int temp; + + temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); + if (temp < 0) + return temp; + + temp &= ~(MII_M1111_HWCFG_MODE_MASK); + temp |= MII_M1111_HWCFG_MODE_SGMII_NO_CLK; + + err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); + if (err < 0) + return err; + } + + err = phy_write(phydev, MII_BMCR, BMCR_RESET); + if (err < 0) + return err; + + return 0; +} + static int m88e1145_config_init(struct phy_device *phydev) { int err; @@ -152,7 +213,7 @@ static int m88e1145_config_init(struct phy_device *phydev) if (err < 0) return err; - if (phydev->interface == PHY_INTERFACE_MODE_RGMII) { + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { int temp = phy_read(phydev, MII_M1145_PHY_EXT_CR); if (temp < 0) return temp; @@ -193,76 +254,84 @@ static int m88e1145_config_init(struct phy_device *phydev) return 0; } -static struct phy_driver m88e1101_driver = { - .phy_id = 0x01410c60, - .phy_id_mask = 0xfffffff0, - .name = "Marvell 88E1101", - .features = PHY_GBIT_FEATURES, - .flags = PHY_HAS_INTERRUPT, - .config_aneg = &marvell_config_aneg, - .read_status = &genphy_read_status, - .ack_interrupt = &marvell_ack_interrupt, - .config_intr = &marvell_config_intr, - .driver = {.owner = THIS_MODULE,}, -}; - -static struct phy_driver m88e1111s_driver = { - .phy_id = 0x01410cc0, - .phy_id_mask = 0xfffffff0, - .name = "Marvell 88E1111", - .features = PHY_GBIT_FEATURES, - .flags = PHY_HAS_INTERRUPT, - .config_aneg = &marvell_config_aneg, - .read_status = &genphy_read_status, - .ack_interrupt = &marvell_ack_interrupt, - .config_intr = &marvell_config_intr, - .driver = {.owner = THIS_MODULE,}, -}; - -static struct phy_driver m88e1145_driver = { - .phy_id = 0x01410cd0, - .phy_id_mask = 0xfffffff0, - .name = "Marvell 88E1145", - .features = PHY_GBIT_FEATURES, - .flags = PHY_HAS_INTERRUPT, - .config_init = &m88e1145_config_init, - .config_aneg = &marvell_config_aneg, - .read_status = &genphy_read_status, - .ack_interrupt = &marvell_ack_interrupt, - .config_intr = &marvell_config_intr, - .driver = {.owner = THIS_MODULE,}, +static struct phy_driver marvell_drivers[] = { + { + .phy_id = 0x01410c60, + .phy_id_mask = 0xfffffff0, + .name = "Marvell 88E1101", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_aneg = &marvell_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &marvell_ack_interrupt, + .config_intr = &marvell_config_intr, + .driver = {.owner = THIS_MODULE,}, + }, + { + .phy_id = 0x01410c90, + .phy_id_mask = 0xfffffff0, + .name = "Marvell 88E1112", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_init = &m88e1111_config_init, + .config_aneg = &marvell_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &marvell_ack_interrupt, + .config_intr = &marvell_config_intr, + .driver = {.owner = THIS_MODULE,}, + }, + { + .phy_id = 0x01410cc0, + .phy_id_mask = 0xfffffff0, + .name = "Marvell 88E1111", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_init = &m88e1111_config_init, + .config_aneg = &marvell_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &marvell_ack_interrupt, + .config_intr = &marvell_config_intr, + .driver = {.owner = THIS_MODULE,}, + }, + { + .phy_id = 0x01410cd0, + .phy_id_mask = 0xfffffff0, + .name = "Marvell 88E1145", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_init = &m88e1145_config_init, + .config_aneg = &marvell_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &marvell_ack_interrupt, + .config_intr = &marvell_config_intr, + .driver = {.owner = THIS_MODULE,}, + } }; static int __init marvell_init(void) { int ret; + int i; - ret = phy_driver_register(&m88e1101_driver); - if (ret) - return ret; + for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) { + ret = phy_driver_register(&marvell_drivers[i]); - ret = phy_driver_register(&m88e1111s_driver); - if (ret) - goto err1111s; - - ret = phy_driver_register(&m88e1145_driver); - if (ret) - goto err1145; + if (ret) { + while (i-- > 0) + phy_driver_unregister(&marvell_drivers[i]); + return ret; + } + } return 0; - - err1145: - phy_driver_unregister(&m88e1111s_driver); - err1111s: - phy_driver_unregister(&m88e1101_driver); - return ret; } static void __exit marvell_exit(void) { - phy_driver_unregister(&m88e1101_driver); - phy_driver_unregister(&m88e1111s_driver); - phy_driver_unregister(&m88e1145_driver); + int i; + + for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) + phy_driver_unregister(&marvell_drivers[i]); } module_init(marvell_init); diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index fc4aee96cdf..fc2f0e695a1 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -131,7 +131,8 @@ static int mdio_bus_match(struct device *dev, struct device_driver *drv) struct phy_device *phydev = to_phy_device(dev); struct phy_driver *phydrv = to_phy_driver(drv); - return (phydrv->phy_id == (phydev->phy_id & phydrv->phy_id_mask)); + return ((phydrv->phy_id & phydrv->phy_id_mask) == + (phydev->phy_id & phydrv->phy_id_mask)); } /* Suspend and resume. Copied from platform_suspend and diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c index 792716beb05..596222b260d 100644 --- a/drivers/net/phy/vitesse.c +++ b/drivers/net/phy/vitesse.c @@ -84,7 +84,7 @@ static int vsc824x_config_intr(struct phy_device *phydev) /* Vitesse 824x */ static struct phy_driver vsc8244_driver = { - .phy_id = 0x000fc6c2, + .phy_id = 0x000fc6c0, .name = "Vitesse VSC8244", .phy_id_mask = 0x000fffc0, .features = PHY_GBIT_FEATURES, diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 541168713f1..3ef0092dc09 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -1708,7 +1708,18 @@ ppp_decompress_frame(struct ppp *ppp, struct sk_buff *skb) goto err; if (proto == PPP_COMP) { - ns = dev_alloc_skb(ppp->mru + PPP_HDRLEN); + int obuff_size; + + switch(ppp->rcomp->compress_proto) { + case CI_MPPE: + obuff_size = ppp->mru + PPP_HDRLEN + 1; + break; + default: + obuff_size = ppp->mru + PPP_HDRLEN; + break; + } + + ns = dev_alloc_skb(obuff_size); if (ns == 0) { printk(KERN_ERR "ppp_decompress_frame: no memory\n"); goto err; diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c new file mode 100644 index 00000000000..5891a0fbdc8 --- /dev/null +++ b/drivers/net/pppol2tp.c @@ -0,0 +1,2486 @@ +/***************************************************************************** + * Linux PPP over L2TP (PPPoX/PPPoL2TP) Sockets + * + * PPPoX --- Generic PPP encapsulation socket family + * PPPoL2TP --- PPP over L2TP (RFC 2661) + * + * Version: 1.0.0 + * + * Authors: Martijn van Oosterhout <kleptog@svana.org> + * James Chapman (jchapman@katalix.com) + * Contributors: + * Michal Ostrowski <mostrows@speakeasy.net> + * Arnaldo Carvalho de Melo <acme@xconectiva.com.br> + * David S. Miller (davem@redhat.com) + * + * License: + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +/* This driver handles only L2TP data frames; control frames are handled by a + * userspace application. + * + * To send data in an L2TP session, userspace opens a PPPoL2TP socket and + * attaches it to a bound UDP socket with local tunnel_id / session_id and + * peer tunnel_id / session_id set. Data can then be sent or received using + * regular socket sendmsg() / recvmsg() calls. Kernel parameters of the socket + * can be read or modified using ioctl() or [gs]etsockopt() calls. + * + * When a PPPoL2TP socket is connected with local and peer session_id values + * zero, the socket is treated as a special tunnel management socket. + * + * Here's example userspace code to create a socket for sending/receiving data + * over an L2TP session:- + * + * struct sockaddr_pppol2tp sax; + * int fd; + * int session_fd; + * + * fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP); + * + * sax.sa_family = AF_PPPOX; + * sax.sa_protocol = PX_PROTO_OL2TP; + * sax.pppol2tp.fd = tunnel_fd; // bound UDP socket + * sax.pppol2tp.addr.sin_addr.s_addr = addr->sin_addr.s_addr; + * sax.pppol2tp.addr.sin_port = addr->sin_port; + * sax.pppol2tp.addr.sin_family = AF_INET; + * sax.pppol2tp.s_tunnel = tunnel_id; + * sax.pppol2tp.s_session = session_id; + * sax.pppol2tp.d_tunnel = peer_tunnel_id; + * sax.pppol2tp.d_session = peer_session_id; + * + * session_fd = connect(fd, (struct sockaddr *)&sax, sizeof(sax)); + * + * A pppd plugin that allows PPP traffic to be carried over L2TP using + * this driver is available from the OpenL2TP project at + * http://openl2tp.sourceforge.net. + */ + +#include <linux/module.h> +#include <linux/version.h> +#include <linux/string.h> +#include <linux/list.h> +#include <asm/uaccess.h> + +#include <linux/kernel.h> +#include <linux/spinlock.h> +#include <linux/kthread.h> +#include <linux/sched.h> +#include <linux/slab.h> +#include <linux/errno.h> +#include <linux/jiffies.h> + +#include <linux/netdevice.h> +#include <linux/net.h> +#include <linux/inetdevice.h> +#include <linux/skbuff.h> +#include <linux/init.h> +#include <linux/ip.h> +#include <linux/udp.h> +#include <linux/if_pppox.h> +#include <linux/if_pppol2tp.h> +#include <net/sock.h> +#include <linux/ppp_channel.h> +#include <linux/ppp_defs.h> +#include <linux/if_ppp.h> +#include <linux/file.h> +#include <linux/hash.h> +#include <linux/sort.h> +#include <linux/proc_fs.h> +#include <net/dst.h> +#include <net/ip.h> +#include <net/udp.h> +#include <net/xfrm.h> + +#include <asm/byteorder.h> +#include <asm/atomic.h> + + +#define PPPOL2TP_DRV_VERSION "V1.0" + +/* L2TP header constants */ +#define L2TP_HDRFLAG_T 0x8000 +#define L2TP_HDRFLAG_L 0x4000 +#define L2TP_HDRFLAG_S 0x0800 +#define L2TP_HDRFLAG_O 0x0200 +#define L2TP_HDRFLAG_P 0x0100 + +#define L2TP_HDR_VER_MASK 0x000F +#define L2TP_HDR_VER 0x0002 + +/* Space for UDP, L2TP and PPP headers */ +#define PPPOL2TP_HEADER_OVERHEAD 40 + +/* Just some random numbers */ +#define L2TP_TUNNEL_MAGIC 0x42114DDA +#define L2TP_SESSION_MAGIC 0x0C04EB7D + +#define PPPOL2TP_HASH_BITS 4 +#define PPPOL2TP_HASH_SIZE (1 << PPPOL2TP_HASH_BITS) + +/* Default trace flags */ +#define PPPOL2TP_DEFAULT_DEBUG_FLAGS 0 + +#define PRINTK(_mask, _type, _lvl, _fmt, args...) \ + do { \ + if ((_mask) & (_type)) \ + printk(_lvl "PPPOL2TP: " _fmt, ##args); \ + } while(0) + +/* Number of bytes to build transmit L2TP headers. + * Unfortunately the size is different depending on whether sequence numbers + * are enabled. + */ +#define PPPOL2TP_L2TP_HDR_SIZE_SEQ 10 +#define PPPOL2TP_L2TP_HDR_SIZE_NOSEQ 6 + +struct pppol2tp_tunnel; + +/* Describes a session. It is the sk_user_data field in the PPPoL2TP + * socket. Contains information to determine incoming packets and transmit + * outgoing ones. + */ +struct pppol2tp_session +{ + int magic; /* should be + * L2TP_SESSION_MAGIC */ + int owner; /* pid that opened the socket */ + + struct sock *sock; /* Pointer to the session + * PPPoX socket */ + struct sock *tunnel_sock; /* Pointer to the tunnel UDP + * socket */ + + struct pppol2tp_addr tunnel_addr; /* Description of tunnel */ + + struct pppol2tp_tunnel *tunnel; /* back pointer to tunnel + * context */ + + char name[20]; /* "sess xxxxx/yyyyy", where + * x=tunnel_id, y=session_id */ + int mtu; + int mru; + int flags; /* accessed by PPPIOCGFLAGS. + * Unused. */ + unsigned recv_seq:1; /* expect receive packets with + * sequence numbers? */ + unsigned send_seq:1; /* send packets with sequence + * numbers? */ + unsigned lns_mode:1; /* behave as LNS? LAC enables + * sequence numbers under + * control of LNS. */ + int debug; /* bitmask of debug message + * categories */ + int reorder_timeout; /* configured reorder timeout + * (in jiffies) */ + u16 nr; /* session NR state (receive) */ + u16 ns; /* session NR state (send) */ + struct sk_buff_head reorder_q; /* receive reorder queue */ + struct pppol2tp_ioc_stats stats; + struct hlist_node hlist; /* Hash list node */ +}; + +/* The sk_user_data field of the tunnel's UDP socket. It contains info to track + * all the associated sessions so incoming packets can be sorted out + */ +struct pppol2tp_tunnel +{ + int magic; /* Should be L2TP_TUNNEL_MAGIC */ + rwlock_t hlist_lock; /* protect session_hlist */ + struct hlist_head session_hlist[PPPOL2TP_HASH_SIZE]; + /* hashed list of sessions, + * hashed by id */ + int debug; /* bitmask of debug message + * categories */ + char name[12]; /* "tunl xxxxx" */ + struct pppol2tp_ioc_stats stats; + + void (*old_sk_destruct)(struct sock *); + + struct sock *sock; /* Parent socket */ + struct list_head list; /* Keep a list of all open + * prepared sockets */ + + atomic_t ref_count; +}; + +/* Private data stored for received packets in the skb. + */ +struct pppol2tp_skb_cb { + u16 ns; + u16 nr; + u16 has_seq; + u16 length; + unsigned long expires; +}; + +#define PPPOL2TP_SKB_CB(skb) ((struct pppol2tp_skb_cb *) &skb->cb[sizeof(struct inet_skb_parm)]) + +static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb); +static void pppol2tp_tunnel_free(struct pppol2tp_tunnel *tunnel); + +static atomic_t pppol2tp_tunnel_count; +static atomic_t pppol2tp_session_count; +static struct ppp_channel_ops pppol2tp_chan_ops = { pppol2tp_xmit , NULL }; +static struct proto_ops pppol2tp_ops; +static LIST_HEAD(pppol2tp_tunnel_list); +static DEFINE_RWLOCK(pppol2tp_tunnel_list_lock); + +/* Helpers to obtain tunnel/session contexts from sockets. + */ +static inline struct pppol2tp_session *pppol2tp_sock_to_session(struct sock *sk) +{ + struct pppol2tp_session *session; + + if (sk == NULL) + return NULL; + + session = (struct pppol2tp_session *)(sk->sk_user_data); + if (session == NULL) + return NULL; + + BUG_ON(session->magic != L2TP_SESSION_MAGIC); + + return session; +} + +static inline struct pppol2tp_tunnel *pppol2tp_sock_to_tunnel(struct sock *sk) +{ + struct pppol2tp_tunnel *tunnel; + + if (sk == NULL) + return NULL; + + tunnel = (struct pppol2tp_tunnel *)(sk->sk_user_data); + if (tunnel == NULL) + return NULL; + + BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC); + + return tunnel; +} + +/* Tunnel reference counts. Incremented per session that is added to + * the tunnel. + */ +static inline void pppol2tp_tunnel_inc_refcount(struct pppol2tp_tunnel *tunnel) +{ + atomic_inc(&tunnel->ref_count); +} + +static inline void pppol2tp_tunnel_dec_refcount(struct pppol2tp_tunnel *tunnel) +{ + if (atomic_dec_and_test(&tunnel->ref_count)) + pppol2tp_tunnel_free(tunnel); +} + +/* Session hash list. + * The session_id SHOULD be random according to RFC2661, but several + * L2TP implementations (Cisco and Microsoft) use incrementing + * session_ids. So we do a real hash on the session_id, rather than a + * simple bitmask. + */ +static inline struct hlist_head * +pppol2tp_session_id_hash(struct pppol2tp_tunnel *tunnel, u16 session_id) +{ + unsigned long hash_val = (unsigned long) session_id; + return &tunnel->session_hlist[hash_long(hash_val, PPPOL2TP_HASH_BITS)]; +} + +/* Lookup a session by id + */ +static struct pppol2tp_session * +pppol2tp_session_find(struct pppol2tp_tunnel *tunnel, u16 session_id) +{ + struct hlist_head *session_list = + pppol2tp_session_id_hash(tunnel, session_id); + struct pppol2tp_session *session; + struct hlist_node *walk; + + read_lock(&tunnel->hlist_lock); + hlist_for_each_entry(session, walk, session_list, hlist) { + if (session->tunnel_addr.s_session == session_id) { + read_unlock(&tunnel->hlist_lock); + return session; + } + } + read_unlock(&tunnel->hlist_lock); + + return NULL; +} + +/* Lookup a tunnel by id + */ +static struct pppol2tp_tunnel *pppol2tp_tunnel_find(u16 tunnel_id) +{ + struct pppol2tp_tunnel *tunnel = NULL; + + read_lock(&pppol2tp_tunnel_list_lock); + list_for_each_entry(tunnel, &pppol2tp_tunnel_list, list) { + if (tunnel->stats.tunnel_id == tunnel_id) { + read_unlock(&pppol2tp_tunnel_list_lock); + return tunnel; + } + } + read_unlock(&pppol2tp_tunnel_list_lock); + + return NULL; +} + +/***************************************************************************** + * Receive data handling + *****************************************************************************/ + +/* Queue a skb in order. We come here only if the skb has an L2TP sequence + * number. + */ +static void pppol2tp_recv_queue_skb(struct pppol2tp_session *session, struct sk_buff *skb) +{ + struct sk_buff *skbp; + u16 ns = PPPOL2TP_SKB_CB(skb)->ns; + + spin_lock(&session->reorder_q.lock); + skb_queue_walk(&session->reorder_q, skbp) { + if (PPPOL2TP_SKB_CB(skbp)->ns > ns) { + __skb_insert(skb, skbp->prev, skbp, &session->reorder_q); + PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG, + "%s: pkt %hu, inserted before %hu, reorder_q len=%d\n", + session->name, ns, PPPOL2TP_SKB_CB(skbp)->ns, + skb_queue_len(&session->reorder_q)); + session->stats.rx_oos_packets++; + goto out; + } + } + + __skb_queue_tail(&session->reorder_q, skb); + +out: + spin_unlock(&session->reorder_q.lock); +} + +/* Dequeue a single skb. + */ +static void pppol2tp_recv_dequeue_skb(struct pppol2tp_session *session, struct sk_buff *skb) +{ + struct pppol2tp_tunnel *tunnel = session->tunnel; + int length = PPPOL2TP_SKB_CB(skb)->length; + struct sock *session_sock = NULL; + + /* We're about to requeue the skb, so unlink it and return resources + * to its current owner (a socket receive buffer). + */ + skb_unlink(skb, &session->reorder_q); + skb_orphan(skb); + + tunnel->stats.rx_packets++; + tunnel->stats.rx_bytes += length; + session->stats.rx_packets++; + session->stats.rx_bytes += length; + + if (PPPOL2TP_SKB_CB(skb)->has_seq) { + /* Bump our Nr */ + session->nr++; + PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG, + "%s: updated nr to %hu\n", session->name, session->nr); + } + + /* If the socket is bound, send it in to PPP's input queue. Otherwise + * queue it on the session socket. + */ + session_sock = session->sock; + if (session_sock->sk_state & PPPOX_BOUND) { + struct pppox_sock *po; + PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG, + "%s: recv %d byte data frame, passing to ppp\n", + session->name, length); + + /* We need to forget all info related to the L2TP packet + * gathered in the skb as we are going to reuse the same + * skb for the inner packet. + * Namely we need to: + * - reset xfrm (IPSec) information as it applies to + * the outer L2TP packet and not to the inner one + * - release the dst to force a route lookup on the inner + * IP packet since skb->dst currently points to the dst + * of the UDP tunnel + * - reset netfilter information as it doesn't apply + * to the inner packet either + */ + secpath_reset(skb); + dst_release(skb->dst); + skb->dst = NULL; + nf_reset(skb); + + po = pppox_sk(session_sock); + ppp_input(&po->chan, skb); + } else { + PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_INFO, + "%s: socket not bound\n", session->name); + + /* Not bound. Nothing we can do, so discard. */ + session->stats.rx_errors++; + kfree_skb(skb); + } + + sock_put(session->sock); +} + +/* Dequeue skbs from the session's reorder_q, subject to packet order. + * Skbs that have been in the queue for too long are simply discarded. + */ +static void pppol2tp_recv_dequeue(struct pppol2tp_session *session) +{ + struct sk_buff *skb; + struct sk_buff *tmp; + + /* If the pkt at the head of the queue has the nr that we + * expect to send up next, dequeue it and any other + * in-sequence packets behind it. + */ + spin_lock(&session->reorder_q.lock); + skb_queue_walk_safe(&session->reorder_q, skb, tmp) { + if (time_after(jiffies, PPPOL2TP_SKB_CB(skb)->expires)) { + session->stats.rx_seq_discards++; + session->stats.rx_errors++; + PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG, + "%s: oos pkt %hu len %d discarded (too old), " + "waiting for %hu, reorder_q_len=%d\n", + session->name, PPPOL2TP_SKB_CB(skb)->ns, + PPPOL2TP_SKB_CB(skb)->length, session->nr, + skb_queue_len(&session->reorder_q)); + __skb_unlink(skb, &session->reorder_q); + kfree_skb(skb); + continue; + } + + if (PPPOL2TP_SKB_CB(skb)->has_seq) { + if (PPPOL2TP_SKB_CB(skb)->ns != session->nr) { + PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG, + "%s: holding oos pkt %hu len %d, " + "waiting for %hu, reorder_q_len=%d\n", + session->name, PPPOL2TP_SKB_CB(skb)->ns, + PPPOL2TP_SKB_CB(skb)->length, session->nr, + skb_queue_len(&session->reorder_q)); + goto out; + } + } + spin_unlock(&session->reorder_q.lock); + pppol2tp_recv_dequeue_skb(session, skb); + spin_lock(&session->reorder_q.lock); + } + +out: + spin_unlock(&session->reorder_q.lock); +} + +/* Internal receive frame. Do the real work of receiving an L2TP data frame + * here. The skb is not on a list when we get here. + * Returns 0 if the packet was a data packet and was successfully passed on. + * Returns 1 if the packet was not a good data packet and could not be + * forwarded. All such packets are passed up to userspace to deal with. + */ +static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb) +{ + struct pppol2tp_session *session = NULL; + struct pppol2tp_tunnel *tunnel; + unsigned char *ptr; + u16 hdrflags; + u16 tunnel_id, session_id; + int length; + struct udphdr *uh; + + tunnel = pppol2tp_sock_to_tunnel(sock); + if (tunnel == NULL) + goto error; + + /* Short packet? */ + if (skb->len < sizeof(struct udphdr)) { + PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_INFO, + "%s: recv short packet (len=%d)\n", tunnel->name, skb->len); + goto error; + } + + /* Point to L2TP header */ + ptr = skb->data + sizeof(struct udphdr); + + /* Get L2TP header flags */ + hdrflags = ntohs(*(__be16*)ptr); + + /* Trace packet contents, if enabled */ + if (tunnel->debug & PPPOL2TP_MSG_DATA) { + printk(KERN_DEBUG "%s: recv: ", tunnel->name); + + for (length = 0; length < 16; length++) + printk(" %02X", ptr[length]); + printk("\n"); + } + + /* Get length of L2TP packet */ + uh = (struct udphdr *) skb_transport_header(skb); + length = ntohs(uh->len) - sizeof(struct udphdr); + + /* Too short? */ + if (length < 12) { + PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_INFO, + "%s: recv short L2TP packet (len=%d)\n", tunnel->name, length); + goto error; + } + + /* If type is control packet, it is handled by userspace. */ + if (hdrflags & L2TP_HDRFLAG_T) { + PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG, + "%s: recv control packet, len=%d\n", tunnel->name, length); + goto error; + } + + /* Skip flags */ + ptr += 2; + + /* If length is present, skip it */ + if (hdrflags & L2TP_HDRFLAG_L) + ptr += 2; + + /* Extract tunnel and session ID */ + tunnel_id = ntohs(*(__be16 *) ptr); + ptr += 2; + session_id = ntohs(*(__be16 *) ptr); + ptr += 2; + + /* Find the session context */ + session = pppol2tp_session_find(tunnel, session_id); + if (!session) { + /* Not found? Pass to userspace to deal with */ + PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_INFO, + "%s: no socket found (%hu/%hu). Passing up.\n", + tunnel->name, tunnel_id, session_id); + goto error; + } + sock_hold(session->sock); + + /* The ref count on the socket was increased by the above call since + * we now hold a pointer to the session. Take care to do sock_put() + * when exiting this function from now on... + */ + + /* Handle the optional sequence numbers. If we are the LAC, + * enable/disable sequence numbers under the control of the LNS. If + * no sequence numbers present but we were expecting them, discard + * frame. + */ + if (hdrflags & L2TP_HDRFLAG_S) { + u16 ns, nr; + ns = ntohs(*(__be16 *) ptr); + ptr += 2; + nr = ntohs(*(__be16 *) ptr); + ptr += 2; + + /* Received a packet with sequence numbers. If we're the LNS, + * check if we sre sending sequence numbers and if not, + * configure it so. + */ + if ((!session->lns_mode) && (!session->send_seq)) { + PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_INFO, + "%s: requested to enable seq numbers by LNS\n", + session->name); + session->send_seq = -1; + } + + /* Store L2TP info in the skb */ + PPPOL2TP_SKB_CB(skb)->ns = ns; + PPPOL2TP_SKB_CB(skb)->nr = nr; + PPPOL2TP_SKB_CB(skb)->has_seq = 1; + + PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG, + "%s: recv data ns=%hu, nr=%hu, session nr=%hu\n", + session->name, ns, nr, session->nr); + } else { + /* No sequence numbers. + * If user has configured mandatory sequence numbers, discard. + */ + if (session->recv_seq) { + PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_WARNING, + "%s: recv data has no seq numbers when required. " + "Discarding\n", session->name); + session->stats.rx_seq_discards++; + session->stats.rx_errors++; + goto discard; + } + + /* If we're the LAC and we're sending sequence numbers, the + * LNS has requested that we no longer send sequence numbers. + * If we're the LNS and we're sending sequence numbers, the + * LAC is broken. Discard the frame. + */ + if ((!session->lns_mode) && (session->send_seq)) { + PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_INFO, + "%s: requested to disable seq numbers by LNS\n", + session->name); + session->send_seq = 0; + } else if (session->send_seq) { + PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_WARNING, + "%s: recv data has no seq numbers when required. " + "Discarding\n", session->name); + session->stats.rx_seq_discards++; + session->stats.rx_errors++; + goto discard; + } + + /* Store L2TP info in the skb */ + PPPOL2TP_SKB_CB(skb)->has_seq = 0; + } + + /* If offset bit set, skip it. */ + if (hdrflags & L2TP_HDRFLAG_O) + ptr += 2 + ntohs(*(__be16 *) ptr); + + skb_pull(skb, ptr - skb->data); + + /* Skip PPP header, if present. In testing, Microsoft L2TP clients + * don't send the PPP header (PPP header compression enabled), but + * other clients can include the header. So we cope with both cases + * here. The PPP header is always FF03 when using L2TP. + * + * Note that skb->data[] isn't dereferenced from a u16 ptr here since + * the field may be unaligned. + */ + if ((skb->data[0] == 0xff) && (skb->data[1] == 0x03)) + skb_pull(skb, 2); + + /* Prepare skb for adding to the session's reorder_q. Hold + * packets for max reorder_timeout or 1 second if not + * reordering. + */ + PPPOL2TP_SKB_CB(skb)->length = length; + PPPOL2TP_SKB_CB(skb)->expires = jiffies + + (session->reorder_timeout ? session->reorder_timeout : HZ); + + /* Add packet to the session's receive queue. Reordering is done here, if + * enabled. Saved L2TP protocol info is stored in skb->sb[]. + */ + if (PPPOL2TP_SKB_CB(skb)->has_seq) { + if (session->reorder_timeout != 0) { + /* Packet reordering enabled. Add skb to session's + * reorder queue, in order of ns. + */ + pppol2tp_recv_queue_skb(session, skb); + } else { + /* Packet reordering disabled. Discard out-of-sequence + * packets + */ + if (PPPOL2TP_SKB_CB(skb)->ns != session->nr) { + session->stats.rx_seq_discards++; + session->stats.rx_errors++; + PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG, + "%s: oos pkt %hu len %d discarded, " + "waiting for %hu, reorder_q_len=%d\n", + session->name, PPPOL2TP_SKB_CB(skb)->ns, + PPPOL2TP_SKB_CB(skb)->length, session->nr, + skb_queue_len(&session->reorder_q)); + goto discard; + } + skb_queue_tail(&session->reorder_q, skb); + } + } else { + /* No sequence numbers. Add the skb to the tail of the + * reorder queue. This ensures that it will be + * delivered after all previous sequenced skbs. + */ + skb_queue_tail(&session->reorder_q, skb); + } + + /* Try to dequeue as many skbs from reorder_q as we can. */ + pppol2tp_recv_dequeue(session); + + return 0; + +discard: + kfree_skb(skb); + sock_put(session->sock); + + return 0; + +error: + return 1; +} + +/* UDP encapsulation receive handler. See net/ipv4/udp.c. + * Return codes: + * 0 : success. + * <0: error + * >0: skb should be passed up to userspace as UDP. + */ +static int pppol2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb) +{ + struct pppol2tp_tunnel *tunnel; + + tunnel = pppol2tp_sock_to_tunnel(sk); + if (tunnel == NULL) + goto pass_up; + + PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG, + "%s: received %d bytes\n", tunnel->name, skb->len); + + if (pppol2tp_recv_core(sk, skb)) + goto pass_up; + + return 0; + +pass_up: + return 1; +} + +/* Receive message. This is the recvmsg for the PPPoL2TP socket. + */ +static int pppol2tp_recvmsg(struct kiocb *iocb, struct socket *sock, + struct msghdr *msg, size_t len, + int flags) +{ + int err; + struct sk_buff *skb; + struct sock *sk = sock->sk; + + err = -EIO; + if (sk->sk_state & PPPOX_BOUND) + goto end; + + msg->msg_namelen = 0; + + err = 0; + skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, + flags & MSG_DONTWAIT, &err); + if (skb) { + err = memcpy_toiovec(msg->msg_iov, (unsigned char *) skb->data, + skb->len); + if (err < 0) + goto do_skb_free; + err = skb->len; + } +do_skb_free: + kfree_skb(skb); +end: + return err; +} + +/************************************************************************ + * Transmit handling + ***********************************************************************/ + +/* Tell how big L2TP headers are for a particular session. This + * depends on whether sequence numbers are being used. + */ +static inline int pppol2tp_l2tp_header_len(struct pppol2tp_session *session) +{ + if (session->send_seq) + return PPPOL2TP_L2TP_HDR_SIZE_SEQ; + + return PPPOL2TP_L2TP_HDR_SIZE_NOSEQ; +} + +/* Build an L2TP header for the session into the buffer provided. + */ +static void pppol2tp_build_l2tp_header(struct pppol2tp_session *session, + void *buf) +{ + __be16 *bufp = buf; + u16 flags = L2TP_HDR_VER; + + if (session->send_seq) + flags |= L2TP_HDRFLAG_S; + + /* Setup L2TP header. + * FIXME: Can this ever be unaligned? Is direct dereferencing of + * 16-bit header fields safe here for all architectures? + */ + *bufp++ = htons(flags); + *bufp++ = htons(session->tunnel_addr.d_tunnel); + *bufp++ = htons(session->tunnel_addr.d_session); + if (session->send_seq) { + *bufp++ = htons(session->ns); + *bufp++ = 0; + session->ns++; + PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG, + "%s: updated ns to %hu\n", session->name, session->ns); + } +} + +/* This is the sendmsg for the PPPoL2TP pppol2tp_session socket. We come here + * when a user application does a sendmsg() on the session socket. L2TP and + * PPP headers must be inserted into the user's data. + */ +static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, + size_t total_len) +{ + static const unsigned char ppph[2] = { 0xff, 0x03 }; + struct sock *sk = sock->sk; + struct inet_sock *inet; + __wsum csum = 0; + struct sk_buff *skb; + int error; + int hdr_len; + struct pppol2tp_session *session; + struct pppol2tp_tunnel *tunnel; + struct udphdr *uh; + + error = -ENOTCONN; + if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED)) + goto error; + + /* Get session and tunnel contexts */ + error = -EBADF; + session = pppol2tp_sock_to_session(sk); + if (session == NULL) + goto error; + + tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); + if (tunnel == NULL) + goto error; + + /* What header length is configured for this session? */ + hdr_len = pppol2tp_l2tp_header_len(session); + + /* Allocate a socket buffer */ + error = -ENOMEM; + skb = sock_wmalloc(sk, NET_SKB_PAD + sizeof(struct iphdr) + + sizeof(struct udphdr) + hdr_len + + sizeof(ppph) + total_len, + 0, GFP_KERNEL); + if (!skb) + goto error; + + /* Reserve space for headers. */ + skb_reserve(skb, NET_SKB_PAD); + skb_reset_network_header(skb); + skb_reserve(skb, sizeof(struct iphdr)); + skb_reset_transport_header(skb); + + /* Build UDP header */ + inet = inet_sk(session->tunnel_sock); + uh = (struct udphdr *) skb->data; + uh->source = inet->sport; + uh->dest = inet->dport; + uh->len = htons(hdr_len + sizeof(ppph) + total_len); + uh->check = 0; + skb_put(skb, sizeof(struct udphdr)); + + /* Build L2TP header */ + pppol2tp_build_l2tp_header(session, skb->data); + skb_put(skb, hdr_len); + + /* Add PPP header */ + skb->data[0] = ppph[0]; + skb->data[1] = ppph[1]; + skb_put(skb, 2); + + /* Copy user data into skb */ + error = memcpy_fromiovec(skb->data, m->msg_iov, total_len); + if (error < 0) { + kfree_skb(skb); + goto error; + } + skb_put(skb, total_len); + + /* Calculate UDP checksum if configured to do so */ + if (session->tunnel_sock->sk_no_check != UDP_CSUM_NOXMIT) + csum = udp_csum_outgoing(sk, skb); + + /* Debug */ + if (session->send_seq) + PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG, + "%s: send %Zd bytes, ns=%hu\n", session->name, + total_len, session->ns - 1); + else + PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG, + "%s: send %Zd bytes\n", session->name, total_len); + + if (session->debug & PPPOL2TP_MSG_DATA) { + int i; + unsigned char *datap = skb->data; + + printk(KERN_DEBUG "%s: xmit:", session->name); + for (i = 0; i < total_len; i++) { + printk(" %02X", *datap++); + if (i == 15) { + printk(" ..."); + break; + } + } + printk("\n"); + } + + /* Queue the packet to IP for output */ + error = ip_queue_xmit(skb, 1); + + /* Update stats */ + if (error >= 0) { + tunnel->stats.tx_packets++; + tunnel->stats.tx_bytes += skb->len; + session->stats.tx_packets++; + session->stats.tx_bytes += skb->len; + } else { + tunnel->stats.tx_errors++; + session->stats.tx_errors++; + } + +error: + return error; +} + +/* Transmit function called by generic PPP driver. Sends PPP frame + * over PPPoL2TP socket. + * + * This is almost the same as pppol2tp_sendmsg(), but rather than + * being called with a msghdr from userspace, it is called with a skb + * from the kernel. + * + * The supplied skb from ppp doesn't have enough headroom for the + * insertion of L2TP, UDP and IP headers so we need to allocate more + * headroom in the skb. This will create a cloned skb. But we must be + * careful in the error case because the caller will expect to free + * the skb it supplied, not our cloned skb. So we take care to always + * leave the original skb unfreed if we return an error. + */ +static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) +{ + static const u8 ppph[2] = { 0xff, 0x03 }; + struct sock *sk = (struct sock *) chan->private; + struct sock *sk_tun; + int hdr_len; + struct pppol2tp_session *session; + struct pppol2tp_tunnel *tunnel; + int rc; + int headroom; + int data_len = skb->len; + struct inet_sock *inet; + __wsum csum = 0; + struct sk_buff *skb2 = NULL; + struct udphdr *uh; + + if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED)) + goto abort; + + /* Get session and tunnel contexts from the socket */ + session = pppol2tp_sock_to_session(sk); + if (session == NULL) + goto abort; + + sk_tun = session->tunnel_sock; + if (sk_tun == NULL) + goto abort; + tunnel = pppol2tp_sock_to_tunnel(sk_tun); + if (tunnel == NULL) + goto abort; + + /* What header length is configured for this session? */ + hdr_len = pppol2tp_l2tp_header_len(session); + + /* Check that there's enough headroom in the skb to insert IP, + * UDP and L2TP and PPP headers. If not enough, expand it to + * make room. Note that a new skb (or a clone) is + * allocated. If we return an error from this point on, make + * sure we free the new skb but do not free the original skb + * since that is done by the caller for the error case. + */ + headroom = NET_SKB_PAD + sizeof(struct iphdr) + + sizeof(struct udphdr) + hdr_len + sizeof(ppph); + if (skb_headroom(skb) < headroom) { + skb2 = skb_realloc_headroom(skb, headroom); + if (skb2 == NULL) + goto abort; + } else + skb2 = skb; + + /* Check that the socket has room */ + if (atomic_read(&sk_tun->sk_wmem_alloc) < sk_tun->sk_sndbuf) + skb_set_owner_w(skb2, sk_tun); + else + goto discard; + + /* Setup PPP header */ + skb_push(skb2, sizeof(ppph)); + skb2->data[0] = ppph[0]; + skb2->data[1] = ppph[1]; + + /* Setup L2TP header */ + skb_push(skb2, hdr_len); + pppol2tp_build_l2tp_header(session, skb2->data); + + /* Setup UDP header */ + inet = inet_sk(sk_tun); + skb_push(skb2, sizeof(struct udphdr)); + skb_reset_transport_header(skb2); + uh = (struct udphdr *) skb2->data; + uh->source = inet->sport; + uh->dest = inet->dport; + uh->len = htons(sizeof(struct udphdr) + hdr_len + sizeof(ppph) + data_len); + uh->check = 0; + + /* Calculate UDP checksum if configured to do so */ + if (sk_tun->sk_no_check != UDP_CSUM_NOXMIT) + csum = udp_csum_outgoing(sk_tun, skb2); + + /* Debug */ + if (session->send_seq) + PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG, + "%s: send %d bytes, ns=%hu\n", session->name, + data_len, session->ns - 1); + else + PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG, + "%s: send %d bytes\n", session->name, data_len); + + if (session->debug & PPPOL2TP_MSG_DATA) { + int i; + unsigned char *datap = skb2->data; + + printk(KERN_DEBUG "%s: xmit:", session->name); + for (i = 0; i < data_len; i++) { + printk(" %02X", *datap++); + if (i == 31) { + printk(" ..."); + break; + } + } + printk("\n"); + } + + /* Get routing info from the tunnel socket */ + skb2->dst = sk_dst_get(sk_tun); + + /* Queue the packet to IP for output */ + rc = ip_queue_xmit(skb2, 1); + + /* Update stats */ + if (rc >= 0) { + tunnel->stats.tx_packets++; + tunnel->stats.tx_bytes += skb2->len; + session->stats.tx_packets++; + session->stats.tx_bytes += skb2->len; + } else { + tunnel->stats.tx_errors++; + session->stats.tx_errors++; + } + + /* Free the original skb */ + kfree_skb(skb); + + return 1; + +discard: + /* Free the new skb. Caller will free original skb. */ + if (skb2 != skb) + kfree_skb(skb2); +abort: + return 0; +} + +/***************************************************************************** + * Session (and tunnel control) socket create/destroy. + *****************************************************************************/ + +/* When the tunnel UDP socket is closed, all the attached sockets need to go + * too. + */ +static void pppol2tp_tunnel_closeall(struct pppol2tp_tunnel *tunnel) +{ + int hash; + struct hlist_node *walk; + struct hlist_node *tmp; + struct pppol2tp_session *session; + struct sock *sk; + + if (tunnel == NULL) + BUG(); + + PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: closing all sessions...\n", tunnel->name); + + write_lock(&tunnel->hlist_lock); + for (hash = 0; hash < PPPOL2TP_HASH_SIZE; hash++) { +again: + hlist_for_each_safe(walk, tmp, &tunnel->session_hlist[hash]) { + session = hlist_entry(walk, struct pppol2tp_session, hlist); + + sk = session->sock; + + PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: closing session\n", session->name); + + hlist_del_init(&session->hlist); + + /* Since we should hold the sock lock while + * doing any unbinding, we need to release the + * lock we're holding before taking that lock. + * Hold a reference to the sock so it doesn't + * disappear as we're jumping between locks. + */ + sock_hold(sk); + write_unlock(&tunnel->hlist_lock); + lock_sock(sk); + + if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) { + pppox_unbind_sock(sk); + sk->sk_state = PPPOX_DEAD; + sk->sk_state_change(sk); + } + + /* Purge any queued data */ + skb_queue_purge(&sk->sk_receive_queue); + skb_queue_purge(&sk->sk_write_queue); + skb_queue_purge(&session->reorder_q); + + release_sock(sk); + sock_put(sk); + + /* Now restart from the beginning of this hash + * chain. We always remove a session from the + * list so we are guaranteed to make forward + * progress. + */ + write_lock(&tunnel->hlist_lock); + goto again; + } + } + write_unlock(&tunnel->hlist_lock); +} + +/* Really kill the tunnel. + * Come here only when all sessions have been cleared from the tunnel. + */ +static void pppol2tp_tunnel_free(struct pppol2tp_tunnel *tunnel) +{ + /* Remove from socket list */ + write_lock(&pppol2tp_tunnel_list_lock); + list_del_init(&tunnel->list); + write_unlock(&pppol2tp_tunnel_list_lock); + + atomic_dec(&pppol2tp_tunnel_count); + kfree(tunnel); +} + +/* Tunnel UDP socket destruct hook. + * The tunnel context is deleted only when all session sockets have been + * closed. + */ +static void pppol2tp_tunnel_destruct(struct sock *sk) +{ + struct pppol2tp_tunnel *tunnel; + + tunnel = pppol2tp_sock_to_tunnel(sk); + if (tunnel == NULL) + goto end; + + PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: closing...\n", tunnel->name); + + /* Close all sessions */ + pppol2tp_tunnel_closeall(tunnel); + + /* No longer an encapsulation socket. See net/ipv4/udp.c */ + (udp_sk(sk))->encap_type = 0; + (udp_sk(sk))->encap_rcv = NULL; + + /* Remove hooks into tunnel socket */ + tunnel->sock = NULL; + sk->sk_destruct = tunnel->old_sk_destruct; + sk->sk_user_data = NULL; + + /* Call original (UDP) socket descructor */ + if (sk->sk_destruct != NULL) + (*sk->sk_destruct)(sk); + + pppol2tp_tunnel_dec_refcount(tunnel); + +end: + return; +} + +/* Really kill the session socket. (Called from sock_put() if + * refcnt == 0.) + */ +static void pppol2tp_session_destruct(struct sock *sk) +{ + struct pppol2tp_session *session = NULL; + + if (sk->sk_user_data != NULL) { + struct pppol2tp_tunnel *tunnel; + + session = pppol2tp_sock_to_session(sk); + if (session == NULL) + goto out; + + /* Don't use pppol2tp_sock_to_tunnel() here to + * get the tunnel context because the tunnel + * socket might have already been closed (its + * sk->sk_user_data will be NULL) so use the + * session's private tunnel ptr instead. + */ + tunnel = session->tunnel; + if (tunnel != NULL) { + BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC); + + /* If session_id is zero, this is a null + * session context, which was created for a + * socket that is being used only to manage + * tunnels. + */ + if (session->tunnel_addr.s_session != 0) { + /* Delete the session socket from the + * hash + */ + write_lock(&tunnel->hlist_lock); + hlist_del_init(&session->hlist); + write_unlock(&tunnel->hlist_lock); + + atomic_dec(&pppol2tp_session_count); + } + + /* This will delete the tunnel context if this + * is the last session on the tunnel. + */ + session->tunnel = NULL; + session->tunnel_sock = NULL; + pppol2tp_tunnel_dec_refcount(tunnel); + } + } + + kfree(session); +out: + return; +} + +/* Called when the PPPoX socket (session) is closed. + */ +static int pppol2tp_release(struct socket *sock) +{ + struct sock *sk = sock->sk; + int error; + + if (!sk) + return 0; + + error = -EBADF; + lock_sock(sk); + if (sock_flag(sk, SOCK_DEAD) != 0) + goto error; + + pppox_unbind_sock(sk); + + /* Signal the death of the socket. */ + sk->sk_state = PPPOX_DEAD; + sock_orphan(sk); + sock->sk = NULL; + + /* Purge any queued data */ + skb_queue_purge(&sk->sk_receive_queue); + skb_queue_purge(&sk->sk_write_queue); + + release_sock(sk); + + /* This will delete the session context via + * pppol2tp_session_destruct() if the socket's refcnt drops to + * zero. + */ + sock_put(sk); + + return 0; + +error: + release_sock(sk); + return error; +} + +/* Internal function to prepare a tunnel (UDP) socket to have PPPoX + * sockets attached to it. + */ +static struct sock *pppol2tp_prepare_tunnel_socket(int fd, u16 tunnel_id, + int *error) +{ + int err; + struct socket *sock = NULL; + struct sock *sk; + struct pppol2tp_tunnel *tunnel; + struct sock *ret = NULL; + + /* Get the tunnel UDP socket from the fd, which was opened by + * the userspace L2TP daemon. + */ + err = -EBADF; + sock = sockfd_lookup(fd, &err); + if (!sock) { + PRINTK(-1, PPPOL2TP_MSG_CONTROL, KERN_ERR, + "tunl %hu: sockfd_lookup(fd=%d) returned %d\n", + tunnel_id, fd, err); + goto err; + } + + /* Quick sanity checks */ + err = -ESOCKTNOSUPPORT; + if (sock->type != SOCK_DGRAM) { + PRINTK(-1, PPPOL2TP_MSG_CONTROL, KERN_ERR, + "tunl %hu: fd %d wrong type, got %d, expected %d\n", + tunnel_id, fd, sock->type, SOCK_DGRAM); + goto err; + } + err = -EAFNOSUPPORT; + if (sock->ops->family != AF_INET) { + PRINTK(-1, PPPOL2TP_MSG_CONTROL, KERN_ERR, + "tunl %hu: fd %d wrong family, got %d, expected %d\n", + tunnel_id, fd, sock->ops->family, AF_INET); + goto err; + } + + err = -ENOTCONN; + sk = sock->sk; + + /* Check if this socket has already been prepped */ + tunnel = (struct pppol2tp_tunnel *)sk->sk_user_data; + if (tunnel != NULL) { + /* User-data field already set */ + err = -EBUSY; + BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC); + + /* This socket has already been prepped */ + ret = tunnel->sock; + goto out; + } + + /* This socket is available and needs prepping. Create a new tunnel + * context and init it. + */ + sk->sk_user_data = tunnel = kzalloc(sizeof(struct pppol2tp_tunnel), GFP_KERNEL); + if (sk->sk_user_data == NULL) { + err = -ENOMEM; + goto err; + } + + tunnel->magic = L2TP_TUNNEL_MAGIC; + sprintf(&tunnel->name[0], "tunl %hu", tunnel_id); + + tunnel->stats.tunnel_id = tunnel_id; + tunnel->debug = PPPOL2TP_DEFAULT_DEBUG_FLAGS; + + /* Hook on the tunnel socket destructor so that we can cleanup + * if the tunnel socket goes away. + */ + tunnel->old_sk_destruct = sk->sk_destruct; + sk->sk_destruct = &pppol2tp_tunnel_destruct; + + tunnel->sock = sk; + sk->sk_allocation = GFP_ATOMIC; + + /* Misc init */ + rwlock_init(&tunnel->hlist_lock); + + /* Add tunnel to our list */ + INIT_LIST_HEAD(&tunnel->list); + write_lock(&pppol2tp_tunnel_list_lock); + list_add(&tunnel->list, &pppol2tp_tunnel_list); + write_unlock(&pppol2tp_tunnel_list_lock); + atomic_inc(&pppol2tp_tunnel_count); + + /* Bump the reference count. The tunnel context is deleted + * only when this drops to zero. + */ + pppol2tp_tunnel_inc_refcount(tunnel); + + /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */ + (udp_sk(sk))->encap_type = UDP_ENCAP_L2TPINUDP; + (udp_sk(sk))->encap_rcv = pppol2tp_udp_encap_recv; + + ret = tunnel->sock; + + *error = 0; +out: + if (sock) + sockfd_put(sock); + + return ret; + +err: + *error = err; + goto out; +} + +static struct proto pppol2tp_sk_proto = { + .name = "PPPOL2TP", + .owner = THIS_MODULE, + .obj_size = sizeof(struct pppox_sock), +}; + +/* socket() handler. Initialize a new struct sock. + */ +static int pppol2tp_create(struct socket *sock) +{ + int error = -ENOMEM; + struct sock *sk; + + sk = sk_alloc(PF_PPPOX, GFP_KERNEL, &pppol2tp_sk_proto, 1); + if (!sk) + goto out; + + sock_init_data(sock, sk); + + sock->state = SS_UNCONNECTED; + sock->ops = &pppol2tp_ops; + + sk->sk_backlog_rcv = pppol2tp_recv_core; + sk->sk_protocol = PX_PROTO_OL2TP; + sk->sk_family = PF_PPPOX; + sk->sk_state = PPPOX_NONE; + sk->sk_type = SOCK_STREAM; + sk->sk_destruct = pppol2tp_session_destruct; + + error = 0; + +out: + return error; +} + +/* connect() handler. Attach a PPPoX socket to a tunnel UDP socket + */ +static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, + int sockaddr_len, int flags) +{ + struct sock *sk = sock->sk; + struct sockaddr_pppol2tp *sp = (struct sockaddr_pppol2tp *) uservaddr; + struct pppox_sock *po = pppox_sk(sk); + struct sock *tunnel_sock = NULL; + struct pppol2tp_session *session = NULL; + struct pppol2tp_tunnel *tunnel; + struct dst_entry *dst; + int error = 0; + + lock_sock(sk); + + error = -EINVAL; + if (sp->sa_protocol != PX_PROTO_OL2TP) + goto end; + + /* Check for already bound sockets */ + error = -EBUSY; + if (sk->sk_state & PPPOX_CONNECTED) + goto end; + + /* We don't supporting rebinding anyway */ + error = -EALREADY; + if (sk->sk_user_data) + goto end; /* socket is already attached */ + + /* Don't bind if s_tunnel is 0 */ + error = -EINVAL; + if (sp->pppol2tp.s_tunnel == 0) + goto end; + + /* Special case: prepare tunnel socket if s_session and + * d_session is 0. Otherwise look up tunnel using supplied + * tunnel id. + */ + if ((sp->pppol2tp.s_session == 0) && (sp->pppol2tp.d_session == 0)) { + tunnel_sock = pppol2tp_prepare_tunnel_socket(sp->pppol2tp.fd, + sp->pppol2tp.s_tunnel, + &error); + if (tunnel_sock == NULL) + goto end; + + tunnel = tunnel_sock->sk_user_data; + } else { + tunnel = pppol2tp_tunnel_find(sp->pppol2tp.s_tunnel); + + /* Error if we can't find the tunnel */ + error = -ENOENT; + if (tunnel == NULL) + goto end; + + tunnel_sock = tunnel->sock; + } + + /* Check that this session doesn't already exist */ + error = -EEXIST; + session = pppol2tp_session_find(tunnel, sp->pppol2tp.s_session); + if (session != NULL) + goto end; + + /* Allocate and initialize a new session context. */ + session = kzalloc(sizeof(struct pppol2tp_session), GFP_KERNEL); + if (session == NULL) { + error = -ENOMEM; + goto end; + } + + skb_queue_head_init(&session->reorder_q); + + session->magic = L2TP_SESSION_MAGIC; + session->owner = current->pid; + session->sock = sk; + session->tunnel = tunnel; + session->tunnel_sock = tunnel_sock; + session->tunnel_addr = sp->pppol2tp; + sprintf(&session->name[0], "sess %hu/%hu", + session->tunnel_addr.s_tunnel, + session->tunnel_addr.s_session); + + session->stats.tunnel_id = session->tunnel_addr.s_tunnel; + session->stats.session_id = session->tunnel_addr.s_session; + + INIT_HLIST_NODE(&session->hlist); + + /* Inherit debug options from tunnel */ + session->debug = tunnel->debug; + + /* Default MTU must allow space for UDP/L2TP/PPP + * headers. + */ + session->mtu = session->mru = 1500 - PPPOL2TP_HEADER_OVERHEAD; + + /* If PMTU discovery was enabled, use the MTU that was discovered */ + dst = sk_dst_get(sk); + if (dst != NULL) { + u32 pmtu = dst_mtu(__sk_dst_get(sk)); + if (pmtu != 0) + session->mtu = session->mru = pmtu - + PPPOL2TP_HEADER_OVERHEAD; + dst_release(dst); + } + + /* Special case: if source & dest session_id == 0x0000, this socket is + * being created to manage the tunnel. Don't add the session to the + * session hash list, just set up the internal context for use by + * ioctl() and sockopt() handlers. + */ + if ((session->tunnel_addr.s_session == 0) && + (session->tunnel_addr.d_session == 0)) { + error = 0; + sk->sk_user_data = session; + goto out_no_ppp; + } + + /* Get tunnel context from the tunnel socket */ + tunnel = pppol2tp_sock_to_tunnel(tunnel_sock); + if (tunnel == NULL) { + error = -EBADF; + goto end; + } + + /* Right now, because we don't have a way to push the incoming skb's + * straight through the UDP layer, the only header we need to worry + * about is the L2TP header. This size is different depending on + * whether sequence numbers are enabled for the data channel. + */ + po->chan.hdrlen = PPPOL2TP_L2TP_HDR_SIZE_NOSEQ; + + po->chan.private = sk; + po->chan.ops = &pppol2tp_chan_ops; + po->chan.mtu = session->mtu; + + error = ppp_register_channel(&po->chan); + if (error) + goto end; + + /* This is how we get the session context from the socket. */ + sk->sk_user_data = session; + + /* Add session to the tunnel's hash list */ + write_lock(&tunnel->hlist_lock); + hlist_add_head(&session->hlist, + pppol2tp_session_id_hash(tunnel, + session->tunnel_addr.s_session)); + write_unlock(&tunnel->hlist_lock); + + atomic_inc(&pppol2tp_session_count); + +out_no_ppp: + pppol2tp_tunnel_inc_refcount(tunnel); + sk->sk_state = PPPOX_CONNECTED; + PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: created\n", session->name); + +end: + release_sock(sk); + + if (error != 0) + PRINTK(session ? session->debug : -1, PPPOL2TP_MSG_CONTROL, KERN_WARNING, + "%s: connect failed: %d\n", session->name, error); + + return error; +} + +/* getname() support. + */ +static int pppol2tp_getname(struct socket *sock, struct sockaddr *uaddr, + int *usockaddr_len, int peer) +{ + int len = sizeof(struct sockaddr_pppol2tp); + struct sockaddr_pppol2tp sp; + int error = 0; + struct pppol2tp_session *session; + + error = -ENOTCONN; + if (sock->sk->sk_state != PPPOX_CONNECTED) + goto end; + + session = pppol2tp_sock_to_session(sock->sk); + if (session == NULL) { + error = -EBADF; + goto end; + } + + sp.sa_family = AF_PPPOX; + sp.sa_protocol = PX_PROTO_OL2TP; + memcpy(&sp.pppol2tp, &session->tunnel_addr, + sizeof(struct pppol2tp_addr)); + + memcpy(uaddr, &sp, len); + + *usockaddr_len = len; + + error = 0; + +end: + return error; +} + +/**************************************************************************** + * ioctl() handlers. + * + * The PPPoX socket is created for L2TP sessions: tunnels have their own UDP + * sockets. However, in order to control kernel tunnel features, we allow + * userspace to create a special "tunnel" PPPoX socket which is used for + * control only. Tunnel PPPoX sockets have session_id == 0 and simply allow + * the user application to issue L2TP setsockopt(), getsockopt() and ioctl() + * calls. + ****************************************************************************/ + +/* Session ioctl helper. + */ +static int pppol2tp_session_ioctl(struct pppol2tp_session *session, + unsigned int cmd, unsigned long arg) +{ + struct ifreq ifr; + int err = 0; + struct sock *sk = session->sock; + int val = (int) arg; + + PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_DEBUG, + "%s: pppol2tp_session_ioctl(cmd=%#x, arg=%#lx)\n", + session->name, cmd, arg); + + sock_hold(sk); + + switch (cmd) { + case SIOCGIFMTU: + err = -ENXIO; + if (!(sk->sk_state & PPPOX_CONNECTED)) + break; + + err = -EFAULT; + if (copy_from_user(&ifr, (void __user *) arg, sizeof(struct ifreq))) + break; + ifr.ifr_mtu = session->mtu; + if (copy_to_user((void __user *) arg, &ifr, sizeof(struct ifreq))) + break; + + PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: get mtu=%d\n", session->name, session->mtu); + err = 0; + break; + + case SIOCSIFMTU: + err = -ENXIO; + if (!(sk->sk_state & PPPOX_CONNECTED)) + break; + + err = -EFAULT; + if (copy_from_user(&ifr, (void __user *) arg, sizeof(struct ifreq))) + break; + + session->mtu = ifr.ifr_mtu; + + PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: set mtu=%d\n", session->name, session->mtu); + err = 0; + break; + + case PPPIOCGMRU: + err = -ENXIO; + if (!(sk->sk_state & PPPOX_CONNECTED)) + break; + + err = -EFAULT; + if (put_user(session->mru, (int __user *) arg)) + break; + + PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: get mru=%d\n", session->name, session->mru); + err = 0; + break; + + case PPPIOCSMRU: + err = -ENXIO; + if (!(sk->sk_state & PPPOX_CONNECTED)) + break; + + err = -EFAULT; + if (get_user(val,(int __user *) arg)) + break; + + session->mru = val; + PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: set mru=%d\n", session->name, session->mru); + err = 0; + break; + + case PPPIOCGFLAGS: + err = -EFAULT; + if (put_user(session->flags, (int __user *) arg)) + break; + + PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: get flags=%d\n", session->name, session->flags); + err = 0; + break; + + case PPPIOCSFLAGS: + err = -EFAULT; + if (get_user(val, (int __user *) arg)) + break; + session->flags = val; + PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: set flags=%d\n", session->name, session->flags); + err = 0; + break; + + case PPPIOCGL2TPSTATS: + err = -ENXIO; + if (!(sk->sk_state & PPPOX_CONNECTED)) + break; + + if (copy_to_user((void __user *) arg, &session->stats, + sizeof(session->stats))) + break; + PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: get L2TP stats\n", session->name); + err = 0; + break; + + default: + err = -ENOSYS; + break; + } + + sock_put(sk); + + return err; +} + +/* Tunnel ioctl helper. + * + * Note the special handling for PPPIOCGL2TPSTATS below. If the ioctl data + * specifies a session_id, the session ioctl handler is called. This allows an + * application to retrieve session stats via a tunnel socket. + */ +static int pppol2tp_tunnel_ioctl(struct pppol2tp_tunnel *tunnel, + unsigned int cmd, unsigned long arg) +{ + int err = 0; + struct sock *sk = tunnel->sock; + struct pppol2tp_ioc_stats stats_req; + + PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_DEBUG, + "%s: pppol2tp_tunnel_ioctl(cmd=%#x, arg=%#lx)\n", tunnel->name, + cmd, arg); + + sock_hold(sk); + + switch (cmd) { + case PPPIOCGL2TPSTATS: + err = -ENXIO; + if (!(sk->sk_state & PPPOX_CONNECTED)) + break; + + if (copy_from_user(&stats_req, (void __user *) arg, + sizeof(stats_req))) { + err = -EFAULT; + break; + } + if (stats_req.session_id != 0) { + /* resend to session ioctl handler */ + struct pppol2tp_session *session = + pppol2tp_session_find(tunnel, stats_req.session_id); + if (session != NULL) + err = pppol2tp_session_ioctl(session, cmd, arg); + else + err = -EBADR; + break; + } +#ifdef CONFIG_XFRM + tunnel->stats.using_ipsec = (sk->sk_policy[0] || sk->sk_policy[1]) ? 1 : 0; +#endif + if (copy_to_user((void __user *) arg, &tunnel->stats, + sizeof(tunnel->stats))) { + err = -EFAULT; + break; + } + PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: get L2TP stats\n", tunnel->name); + err = 0; + break; + + default: + err = -ENOSYS; + break; + } + + sock_put(sk); + + return err; +} + +/* Main ioctl() handler. + * Dispatch to tunnel or session helpers depending on the socket. + */ +static int pppol2tp_ioctl(struct socket *sock, unsigned int cmd, + unsigned long arg) +{ + struct sock *sk = sock->sk; + struct pppol2tp_session *session; + struct pppol2tp_tunnel *tunnel; + int err; + + if (!sk) + return 0; + + err = -EBADF; + if (sock_flag(sk, SOCK_DEAD) != 0) + goto end; + + err = -ENOTCONN; + if ((sk->sk_user_data == NULL) || + (!(sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)))) + goto end; + + /* Get session context from the socket */ + err = -EBADF; + session = pppol2tp_sock_to_session(sk); + if (session == NULL) + goto end; + + /* Special case: if session's session_id is zero, treat ioctl as a + * tunnel ioctl + */ + if ((session->tunnel_addr.s_session == 0) && + (session->tunnel_addr.d_session == 0)) { + err = -EBADF; + tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); + if (tunnel == NULL) + goto end; + + err = pppol2tp_tunnel_ioctl(tunnel, cmd, arg); + goto end; + } + + err = pppol2tp_session_ioctl(session, cmd, arg); + +end: + return err; +} + +/***************************************************************************** + * setsockopt() / getsockopt() support. + * + * The PPPoX socket is created for L2TP sessions: tunnels have their own UDP + * sockets. In order to control kernel tunnel features, we allow userspace to + * create a special "tunnel" PPPoX socket which is used for control only. + * Tunnel PPPoX sockets have session_id == 0 and simply allow the user + * application to issue L2TP setsockopt(), getsockopt() and ioctl() calls. + *****************************************************************************/ + +/* Tunnel setsockopt() helper. + */ +static int pppol2tp_tunnel_setsockopt(struct sock *sk, + struct pppol2tp_tunnel *tunnel, + int optname, int val) +{ + int err = 0; + + switch (optname) { + case PPPOL2TP_SO_DEBUG: + tunnel->debug = val; + PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: set debug=%x\n", tunnel->name, tunnel->debug); + break; + + default: + err = -ENOPROTOOPT; + break; + } + + return err; +} + +/* Session setsockopt helper. + */ +static int pppol2tp_session_setsockopt(struct sock *sk, + struct pppol2tp_session *session, + int optname, int val) +{ + int err = 0; + + switch (optname) { + case PPPOL2TP_SO_RECVSEQ: + if ((val != 0) && (val != 1)) { + err = -EINVAL; + break; + } + session->recv_seq = val ? -1 : 0; + PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: set recv_seq=%d\n", session->name, + session->recv_seq); + break; + + case PPPOL2TP_SO_SENDSEQ: + if ((val != 0) && (val != 1)) { + err = -EINVAL; + break; + } + session->send_seq = val ? -1 : 0; + { + struct sock *ssk = session->sock; + struct pppox_sock *po = pppox_sk(ssk); + po->chan.hdrlen = val ? PPPOL2TP_L2TP_HDR_SIZE_SEQ : + PPPOL2TP_L2TP_HDR_SIZE_NOSEQ; + } + PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: set send_seq=%d\n", session->name, session->send_seq); + break; + + case PPPOL2TP_SO_LNSMODE: + if ((val != 0) && (val != 1)) { + err = -EINVAL; + break; + } + session->lns_mode = val ? -1 : 0; + PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: set lns_mode=%d\n", session->name, + session->lns_mode); + break; + + case PPPOL2TP_SO_DEBUG: + session->debug = val; + PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: set debug=%x\n", session->name, session->debug); + break; + + case PPPOL2TP_SO_REORDERTO: + session->reorder_timeout = msecs_to_jiffies(val); + PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: set reorder_timeout=%d\n", session->name, + session->reorder_timeout); + break; + + default: + err = -ENOPROTOOPT; + break; + } + + return err; +} + +/* Main setsockopt() entry point. + * Does API checks, then calls either the tunnel or session setsockopt + * handler, according to whether the PPPoL2TP socket is a for a regular + * session or the special tunnel type. + */ +static int pppol2tp_setsockopt(struct socket *sock, int level, int optname, + char __user *optval, int optlen) +{ + struct sock *sk = sock->sk; + struct pppol2tp_session *session = sk->sk_user_data; + struct pppol2tp_tunnel *tunnel; + int val; + int err; + + if (level != SOL_PPPOL2TP) + return udp_prot.setsockopt(sk, level, optname, optval, optlen); + + if (optlen < sizeof(int)) + return -EINVAL; + + if (get_user(val, (int __user *)optval)) + return -EFAULT; + + err = -ENOTCONN; + if (sk->sk_user_data == NULL) + goto end; + + /* Get session context from the socket */ + err = -EBADF; + session = pppol2tp_sock_to_session(sk); + if (session == NULL) + goto end; + + /* Special case: if session_id == 0x0000, treat as operation on tunnel + */ + if ((session->tunnel_addr.s_session == 0) && + (session->tunnel_addr.d_session == 0)) { + err = -EBADF; + tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); + if (tunnel == NULL) + goto end; + + err = pppol2tp_tunnel_setsockopt(sk, tunnel, optname, val); + } else + err = pppol2tp_session_setsockopt(sk, session, optname, val); + + err = 0; + +end: + return err; +} + +/* Tunnel getsockopt helper. Called with sock locked. + */ +static int pppol2tp_tunnel_getsockopt(struct sock *sk, + struct pppol2tp_tunnel *tunnel, + int optname, int __user *val) +{ + int err = 0; + + switch (optname) { + case PPPOL2TP_SO_DEBUG: + *val = tunnel->debug; + PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: get debug=%x\n", tunnel->name, tunnel->debug); + break; + + default: + err = -ENOPROTOOPT; + break; + } + + return err; +} + +/* Session getsockopt helper. Called with sock locked. + */ +static int pppol2tp_session_getsockopt(struct sock *sk, + struct pppol2tp_session *session, + int optname, int __user *val) +{ + int err = 0; + + switch (optname) { + case PPPOL2TP_SO_RECVSEQ: + *val = session->recv_seq; + PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: get recv_seq=%d\n", session->name, *val); + break; + + case PPPOL2TP_SO_SENDSEQ: + *val = session->send_seq; + PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: get send_seq=%d\n", session->name, *val); + break; + + case PPPOL2TP_SO_LNSMODE: + *val = session->lns_mode; + PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: get lns_mode=%d\n", session->name, *val); + break; + + case PPPOL2TP_SO_DEBUG: + *val = session->debug; + PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: get debug=%d\n", session->name, *val); + break; + + case PPPOL2TP_SO_REORDERTO: + *val = (int) jiffies_to_msecs(session->reorder_timeout); + PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, + "%s: get reorder_timeout=%d\n", session->name, *val); + break; + + default: + err = -ENOPROTOOPT; + } + + return err; +} + +/* Main getsockopt() entry point. + * Does API checks, then calls either the tunnel or session getsockopt + * handler, according to whether the PPPoX socket is a for a regular session + * or the special tunnel type. + */ +static int pppol2tp_getsockopt(struct socket *sock, int level, + int optname, char __user *optval, int __user *optlen) +{ + struct sock *sk = sock->sk; + struct pppol2tp_session *session = sk->sk_user_data; + struct pppol2tp_tunnel *tunnel; + int val, len; + int err; + + if (level != SOL_PPPOL2TP) + return udp_prot.getsockopt(sk, level, optname, optval, optlen); + + if (get_user(len, (int __user *) optlen)) + return -EFAULT; + + len = min_t(unsigned int, len, sizeof(int)); + + if (len < 0) + return -EINVAL; + + err = -ENOTCONN; + if (sk->sk_user_data == NULL) + goto end; + + /* Get the session context */ + err = -EBADF; + session = pppol2tp_sock_to_session(sk); + if (session == NULL) + goto end; + + /* Special case: if session_id == 0x0000, treat as operation on tunnel */ + if ((session->tunnel_addr.s_session == 0) && + (session->tunnel_addr.d_session == 0)) { + err = -EBADF; + tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); + if (tunnel == NULL) + goto end; + + err = pppol2tp_tunnel_getsockopt(sk, tunnel, optname, &val); + } else + err = pppol2tp_session_getsockopt(sk, session, optname, &val); + + err = -EFAULT; + if (put_user(len, (int __user *) optlen)) + goto end; + + if (copy_to_user((void __user *) optval, &val, len)) + goto end; + + err = 0; +end: + return err; +} + +/***************************************************************************** + * /proc filesystem for debug + *****************************************************************************/ + +#ifdef CONFIG_PROC_FS + +#include <linux/seq_file.h> + +struct pppol2tp_seq_data { + struct pppol2tp_tunnel *tunnel; /* current tunnel */ + struct pppol2tp_session *session; /* NULL means get first session in tunnel */ +}; + +static struct pppol2tp_session *next_session(struct pppol2tp_tunnel *tunnel, struct pppol2tp_session *curr) +{ + struct pppol2tp_session *session = NULL; + struct hlist_node *walk; + int found = 0; + int next = 0; + int i; + + read_lock(&tunnel->hlist_lock); + for (i = 0; i < PPPOL2TP_HASH_SIZE; i++) { + hlist_for_each_entry(session, walk, &tunnel->session_hlist[i], hlist) { + if (curr == NULL) { + found = 1; + goto out; + } + if (session == curr) { + next = 1; + continue; + } + if (next) { + found = 1; + goto out; + } + } + } +out: + read_unlock(&tunnel->hlist_lock); + if (!found) + session = NULL; + + return session; +} + +static struct pppol2tp_tunnel *next_tunnel(struct pppol2tp_tunnel *curr) +{ + struct pppol2tp_tunnel *tunnel = NULL; + + read_lock(&pppol2tp_tunnel_list_lock); + if (list_is_last(&curr->list, &pppol2tp_tunnel_list)) { + goto out; + } + tunnel = list_entry(curr->list.next, struct pppol2tp_tunnel, list); +out: + read_unlock(&pppol2tp_tunnel_list_lock); + + return tunnel; +} + +static void *pppol2tp_seq_start(struct seq_file *m, loff_t *offs) +{ + struct pppol2tp_seq_data *pd = SEQ_START_TOKEN; + loff_t pos = *offs; + + if (!pos) + goto out; + + BUG_ON(m->private == NULL); + pd = m->private; + + if (pd->tunnel == NULL) { + if (!list_empty(&pppol2tp_tunnel_list)) + pd->tunnel = list_entry(pppol2tp_tunnel_list.next, struct pppol2tp_tunnel, list); + } else { + pd->session = next_session(pd->tunnel, pd->session); + if (pd->session == NULL) { + pd->tunnel = next_tunnel(pd->tunnel); + } + } + + /* NULL tunnel and session indicates end of list */ + if ((pd->tunnel == NULL) && (pd->session == NULL)) + pd = NULL; + +out: + return pd; +} + +static void *pppol2tp_seq_next(struct seq_file *m, void *v, loff_t *pos) +{ + (*pos)++; + return NULL; +} + +static void pppol2tp_seq_stop(struct seq_file *p, void *v) +{ + /* nothing to do */ +} + +static void pppol2tp_seq_tunnel_show(struct seq_file *m, void *v) +{ + struct pppol2tp_tunnel *tunnel = v; + + seq_printf(m, "\nTUNNEL '%s', %c %d\n", + tunnel->name, + (tunnel == tunnel->sock->sk_user_data) ? 'Y':'N', + atomic_read(&tunnel->ref_count) - 1); + seq_printf(m, " %08x %llu/%llu/%llu %llu/%llu/%llu\n", + tunnel->debug, + tunnel->stats.tx_packets, tunnel->stats.tx_bytes, + tunnel->stats.tx_errors, + tunnel->stats.rx_packets, tunnel->stats.rx_bytes, + tunnel->stats.rx_errors); +} + +static void pppol2tp_seq_session_show(struct seq_file *m, void *v) +{ + struct pppol2tp_session *session = v; + + seq_printf(m, " SESSION '%s' %08X/%d %04X/%04X -> " + "%04X/%04X %d %c\n", + session->name, + ntohl(session->tunnel_addr.addr.sin_addr.s_addr), + ntohs(session->tunnel_addr.addr.sin_port), + session->tunnel_addr.s_tunnel, + session->tunnel_addr.s_session, + session->tunnel_addr.d_tunnel, + session->tunnel_addr.d_session, + session->sock->sk_state, + (session == session->sock->sk_user_data) ? + 'Y' : 'N'); + seq_printf(m, " %d/%d/%c/%c/%s %08x %u\n", + session->mtu, session->mru, + session->recv_seq ? 'R' : '-', + session->send_seq ? 'S' : '-', + session->lns_mode ? "LNS" : "LAC", + session->debug, + jiffies_to_msecs(session->reorder_timeout)); + seq_printf(m, " %hu/%hu %llu/%llu/%llu %llu/%llu/%llu\n", + session->nr, session->ns, + session->stats.tx_packets, + session->stats.tx_bytes, + session->stats.tx_errors, + session->stats.rx_packets, + session->stats.rx_bytes, + session->stats.rx_errors); +} + +static int pppol2tp_seq_show(struct seq_file *m, void *v) +{ + struct pppol2tp_seq_data *pd = v; + + /* display header on line 1 */ + if (v == SEQ_START_TOKEN) { + seq_puts(m, "PPPoL2TP driver info, " PPPOL2TP_DRV_VERSION "\n"); + seq_puts(m, "TUNNEL name, user-data-ok session-count\n"); + seq_puts(m, " debug tx-pkts/bytes/errs rx-pkts/bytes/errs\n"); + seq_puts(m, " SESSION name, addr/port src-tid/sid " + "dest-tid/sid state user-data-ok\n"); + seq_puts(m, " mtu/mru/rcvseq/sendseq/lns debug reorderto\n"); + seq_puts(m, " nr/ns tx-pkts/bytes/errs rx-pkts/bytes/errs\n"); + goto out; + } + + /* Show the tunnel or session context. + */ + if (pd->session == NULL) + pppol2tp_seq_tunnel_show(m, pd->tunnel); + else + pppol2tp_seq_session_show(m, pd->session); + +out: + return 0; +} + +static struct seq_operations pppol2tp_seq_ops = { + .start = pppol2tp_seq_start, + .next = pppol2tp_seq_next, + .stop = pppol2tp_seq_stop, + .show = pppol2tp_seq_show, +}; + +/* Called when our /proc file is opened. We allocate data for use when + * iterating our tunnel / session contexts and store it in the private + * data of the seq_file. + */ +static int pppol2tp_proc_open(struct inode *inode, struct file *file) +{ + struct seq_file *m; + struct pppol2tp_seq_data *pd; + int ret = 0; + + ret = seq_open(file, &pppol2tp_seq_ops); + if (ret < 0) + goto out; + + m = file->private_data; + + /* Allocate and fill our proc_data for access later */ + ret = -ENOMEM; + m->private = kzalloc(sizeof(struct pppol2tp_seq_data), GFP_KERNEL); + if (m->private == NULL) + goto out; + + pd = m->private; + ret = 0; + +out: + return ret; +} + +/* Called when /proc file access completes. + */ +static int pppol2tp_proc_release(struct inode *inode, struct file *file) +{ + struct seq_file *m = (struct seq_file *)file->private_data; + + kfree(m->private); + m->private = NULL; + + return seq_release(inode, file); +} + +static struct file_operations pppol2tp_proc_fops = { + .owner = THIS_MODULE, + .open = pppol2tp_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = pppol2tp_proc_release, +}; + +static struct proc_dir_entry *pppol2tp_proc; + +#endif /* CONFIG_PROC_FS */ + +/***************************************************************************** + * Init and cleanup + *****************************************************************************/ + +static struct proto_ops pppol2tp_ops = { + .family = AF_PPPOX, + .owner = THIS_MODULE, + .release = pppol2tp_release, + .bind = sock_no_bind, + .connect = pppol2tp_connect, + .socketpair = sock_no_socketpair, + .accept = sock_no_accept, + .getname = pppol2tp_getname, + .poll = datagram_poll, + .listen = sock_no_listen, + .shutdown = sock_no_shutdown, + .setsockopt = pppol2tp_setsockopt, + .getsockopt = pppol2tp_getsockopt, + .sendmsg = pppol2tp_sendmsg, + .recvmsg = pppol2tp_recvmsg, + .mmap = sock_no_mmap, + .ioctl = pppox_ioctl, +}; + +static struct pppox_proto pppol2tp_proto = { + .create = pppol2tp_create, + .ioctl = pppol2tp_ioctl +}; + +static int __init pppol2tp_init(void) +{ + int err; + + err = proto_register(&pppol2tp_sk_proto, 0); + if (err) + goto out; + err = register_pppox_proto(PX_PROTO_OL2TP, &pppol2tp_proto); + if (err) + goto out_unregister_pppol2tp_proto; + +#ifdef CONFIG_PROC_FS + pppol2tp_proc = create_proc_entry("pppol2tp", 0, proc_net); + if (!pppol2tp_proc) { + err = -ENOMEM; + goto out_unregister_pppox_proto; + } + pppol2tp_proc->proc_fops = &pppol2tp_proc_fops; +#endif /* CONFIG_PROC_FS */ + printk(KERN_INFO "PPPoL2TP kernel driver, %s\n", + PPPOL2TP_DRV_VERSION); + +out: + return err; + +out_unregister_pppox_proto: + unregister_pppox_proto(PX_PROTO_OL2TP); +out_unregister_pppol2tp_proto: + proto_unregister(&pppol2tp_sk_proto); + goto out; +} + +static void __exit pppol2tp_exit(void) +{ + unregister_pppox_proto(PX_PROTO_OL2TP); + +#ifdef CONFIG_PROC_FS + remove_proc_entry("pppol2tp", proc_net); +#endif + proto_unregister(&pppol2tp_sk_proto); +} + +module_init(pppol2tp_init); +module_exit(pppol2tp_exit); + +MODULE_AUTHOR("Martijn van Oosterhout <kleptog@svana.org>," + "James Chapman <jchapman@katalix.com>"); +MODULE_DESCRIPTION("PPP over L2TP over UDP"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(PPPOL2TP_DRV_VERSION); diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c new file mode 100644 index 00000000000..08d25066f05 --- /dev/null +++ b/drivers/net/ps3_gelic_net.c @@ -0,0 +1,1576 @@ +/* + * PS3 gelic network driver. + * + * Copyright (C) 2007 Sony Computer Entertainment Inc. + * Copyright 2006, 2007 Sony Corporation + * + * This file is based on: spider_net.c + * + * (C) Copyright IBM Corp. 2005 + * + * Authors : Utz Bacher <utz.bacher@de.ibm.com> + * Jens Osterkamp <Jens.Osterkamp@de.ibm.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#undef DEBUG + +#include <linux/kernel.h> +#include <linux/module.h> + +#include <linux/etherdevice.h> +#include <linux/ethtool.h> +#include <linux/if_vlan.h> + +#include <linux/in.h> +#include <linux/ip.h> +#include <linux/tcp.h> + +#include <linux/dma-mapping.h> +#include <net/checksum.h> +#include <asm/firmware.h> +#include <asm/ps3.h> +#include <asm/lv1call.h> + +#include "ps3_gelic_net.h" + +#define DRV_NAME "Gelic Network Driver" +#define DRV_VERSION "1.0" + +MODULE_AUTHOR("SCE Inc."); +MODULE_DESCRIPTION("Gelic Network driver"); +MODULE_LICENSE("GPL"); + +static inline struct device *ctodev(struct gelic_net_card *card) +{ + return &card->dev->core; +} +static inline unsigned int bus_id(struct gelic_net_card *card) +{ + return card->dev->bus_id; +} +static inline unsigned int dev_id(struct gelic_net_card *card) +{ + return card->dev->dev_id; +} + +/* set irq_mask */ +static int gelic_net_set_irq_mask(struct gelic_net_card *card, u64 mask) +{ + int status; + + status = lv1_net_set_interrupt_mask(bus_id(card), dev_id(card), + mask, 0); + if (status) + dev_info(ctodev(card), + "lv1_net_set_interrupt_mask failed %d\n", status); + return status; +} +static inline void gelic_net_rx_irq_on(struct gelic_net_card *card) +{ + gelic_net_set_irq_mask(card, card->ghiintmask | GELIC_NET_RXINT); +} +static inline void gelic_net_rx_irq_off(struct gelic_net_card *card) +{ + gelic_net_set_irq_mask(card, card->ghiintmask & ~GELIC_NET_RXINT); +} +/** + * gelic_net_get_descr_status -- returns the status of a descriptor + * @descr: descriptor to look at + * + * returns the status as in the dmac_cmd_status field of the descriptor + */ +static enum gelic_net_descr_status +gelic_net_get_descr_status(struct gelic_net_descr *descr) +{ + u32 cmd_status; + + cmd_status = descr->dmac_cmd_status; + cmd_status >>= GELIC_NET_DESCR_IND_PROC_SHIFT; + return cmd_status; +} + +/** + * gelic_net_set_descr_status -- sets the status of a descriptor + * @descr: descriptor to change + * @status: status to set in the descriptor + * + * changes the status to the specified value. Doesn't change other bits + * in the status + */ +static void gelic_net_set_descr_status(struct gelic_net_descr *descr, + enum gelic_net_descr_status status) +{ + u32 cmd_status; + + /* read the status */ + cmd_status = descr->dmac_cmd_status; + /* clean the upper 4 bits */ + cmd_status &= GELIC_NET_DESCR_IND_PROC_MASKO; + /* add the status to it */ + cmd_status |= ((u32)status) << GELIC_NET_DESCR_IND_PROC_SHIFT; + /* and write it back */ + descr->dmac_cmd_status = cmd_status; + /* + * dma_cmd_status field is used to indicate whether the descriptor + * is valid or not. + * Usually caller of this function wants to inform that to the + * hardware, so we assure here the hardware sees the change. + */ + wmb(); +} + +/** + * gelic_net_free_chain - free descriptor chain + * @card: card structure + * @descr_in: address of desc + */ +static void gelic_net_free_chain(struct gelic_net_card *card, + struct gelic_net_descr *descr_in) +{ + struct gelic_net_descr *descr; + + for (descr = descr_in; descr && descr->bus_addr; descr = descr->next) { + dma_unmap_single(ctodev(card), descr->bus_addr, + GELIC_NET_DESCR_SIZE, DMA_BIDIRECTIONAL); + descr->bus_addr = 0; + } +} + +/** + * gelic_net_init_chain - links descriptor chain + * @card: card structure + * @chain: address of chain + * @start_descr: address of descriptor array + * @no: number of descriptors + * + * we manage a circular list that mirrors the hardware structure, + * except that the hardware uses bus addresses. + * + * returns 0 on success, <0 on failure + */ +static int gelic_net_init_chain(struct gelic_net_card *card, + struct gelic_net_descr_chain *chain, + struct gelic_net_descr *start_descr, int no) +{ + int i; + struct gelic_net_descr *descr; + + descr = start_descr; + memset(descr, 0, sizeof(*descr) * no); + + /* set up the hardware pointers in each descriptor */ + for (i = 0; i < no; i++, descr++) { + gelic_net_set_descr_status(descr, GELIC_NET_DESCR_NOT_IN_USE); + descr->bus_addr = + dma_map_single(ctodev(card), descr, + GELIC_NET_DESCR_SIZE, + DMA_BIDIRECTIONAL); + + if (!descr->bus_addr) + goto iommu_error; + + descr->next = descr + 1; + descr->prev = descr - 1; + } + /* make them as ring */ + (descr - 1)->next = start_descr; + start_descr->prev = (descr - 1); + + /* chain bus addr of hw descriptor */ + descr = start_descr; + for (i = 0; i < no; i++, descr++) { + descr->next_descr_addr = descr->next->bus_addr; + } + + chain->head = start_descr; + chain->tail = start_descr; + + /* do not chain last hw descriptor */ + (descr - 1)->next_descr_addr = 0; + + return 0; + +iommu_error: + for (i--, descr--; 0 <= i; i--, descr--) + if (descr->bus_addr) + dma_unmap_single(ctodev(card), descr->bus_addr, + GELIC_NET_DESCR_SIZE, + DMA_BIDIRECTIONAL); + return -ENOMEM; +} + +/** + * gelic_net_prepare_rx_descr - reinitializes a rx descriptor + * @card: card structure + * @descr: descriptor to re-init + * + * return 0 on succes, <0 on failure + * + * allocates a new rx skb, iommu-maps it and attaches it to the descriptor. + * Activate the descriptor state-wise + */ +static int gelic_net_prepare_rx_descr(struct gelic_net_card *card, + struct gelic_net_descr *descr) +{ + int offset; + unsigned int bufsize; + + if (gelic_net_get_descr_status(descr) != GELIC_NET_DESCR_NOT_IN_USE) { + dev_info(ctodev(card), "%s: ERROR status \n", __func__); + } + /* we need to round up the buffer size to a multiple of 128 */ + bufsize = ALIGN(GELIC_NET_MAX_MTU, GELIC_NET_RXBUF_ALIGN); + + /* and we need to have it 128 byte aligned, therefore we allocate a + * bit more */ + descr->skb = netdev_alloc_skb(card->netdev, + bufsize + GELIC_NET_RXBUF_ALIGN - 1); + if (!descr->skb) { + descr->buf_addr = 0; /* tell DMAC don't touch memory */ + dev_info(ctodev(card), + "%s:allocate skb failed !!\n", __func__); + return -ENOMEM; + } + descr->buf_size = bufsize; + descr->dmac_cmd_status = 0; + descr->result_size = 0; + descr->valid_size = 0; + descr->data_error = 0; + + offset = ((unsigned long)descr->skb->data) & + (GELIC_NET_RXBUF_ALIGN - 1); + if (offset) + skb_reserve(descr->skb, GELIC_NET_RXBUF_ALIGN - offset); + /* io-mmu-map the skb */ + descr->buf_addr = dma_map_single(ctodev(card), descr->skb->data, + GELIC_NET_MAX_MTU, + DMA_FROM_DEVICE); + if (!descr->buf_addr) { + dev_kfree_skb_any(descr->skb); + descr->skb = NULL; + dev_info(ctodev(card), + "%s:Could not iommu-map rx buffer\n", __func__); + gelic_net_set_descr_status(descr, GELIC_NET_DESCR_NOT_IN_USE); + return -ENOMEM; + } else { + gelic_net_set_descr_status(descr, GELIC_NET_DESCR_CARDOWNED); + return 0; + } +} + +/** + * gelic_net_release_rx_chain - free all skb of rx descr + * @card: card structure + * + */ +static void gelic_net_release_rx_chain(struct gelic_net_card *card) +{ + struct gelic_net_descr *descr = card->rx_chain.head; + + do { + if (descr->skb) { + dma_unmap_single(ctodev(card), + descr->buf_addr, + descr->skb->len, + DMA_FROM_DEVICE); + descr->buf_addr = 0; + dev_kfree_skb_any(descr->skb); + descr->skb = NULL; + descr->dmac_cmd_status = GELIC_NET_DESCR_NOT_IN_USE; + } + descr = descr->next; + } while (descr != card->rx_chain.head); +} + +/** + * gelic_net_fill_rx_chain - fills descriptors/skbs in the rx chains + * @card: card structure + * + * fills all descriptors in the rx chain: allocates skbs + * and iommu-maps them. + * returns 0 on success, <0 on failure + */ +static int gelic_net_fill_rx_chain(struct gelic_net_card *card) +{ + struct gelic_net_descr *descr = card->rx_chain.head; + int ret; + + do { + if (!descr->skb) { + ret = gelic_net_prepare_rx_descr(card, descr); + if (ret) + goto rewind; + } + descr = descr->next; + } while (descr != card->rx_chain.head); + + return 0; +rewind: + gelic_net_release_rx_chain(card); + return ret; +} + +/** + * gelic_net_alloc_rx_skbs - allocates rx skbs in rx descriptor chains + * @card: card structure + * + * returns 0 on success, <0 on failure + */ +static int gelic_net_alloc_rx_skbs(struct gelic_net_card *card) +{ + struct gelic_net_descr_chain *chain; + int ret; + chain = &card->rx_chain; + ret = gelic_net_fill_rx_chain(card); + chain->head = card->rx_top->prev; /* point to the last */ + return ret; +} + +/** + * gelic_net_release_tx_descr - processes a used tx descriptor + * @card: card structure + * @descr: descriptor to release + * + * releases a used tx descriptor (unmapping, freeing of skb) + */ +static void gelic_net_release_tx_descr(struct gelic_net_card *card, + struct gelic_net_descr *descr) +{ + struct sk_buff *skb; + + + if (descr->data_status & (1 << GELIC_NET_TXDESC_TAIL)) { + /* 2nd descriptor */ + skb = descr->skb; + dma_unmap_single(ctodev(card), descr->buf_addr, skb->len, + DMA_TO_DEVICE); + dev_kfree_skb_any(skb); + } else { + dma_unmap_single(ctodev(card), descr->buf_addr, + descr->buf_size, DMA_TO_DEVICE); + } + + descr->buf_addr = 0; + descr->buf_size = 0; + descr->next_descr_addr = 0; + descr->result_size = 0; + descr->valid_size = 0; + descr->data_status = 0; + descr->data_error = 0; + descr->skb = NULL; + + /* set descr status */ + descr->dmac_cmd_status = GELIC_NET_DMAC_CMDSTAT_NOT_IN_USE; +} + +/** + * gelic_net_release_tx_chain - processes sent tx descriptors + * @card: adapter structure + * @stop: net_stop sequence + * + * releases the tx descriptors that gelic has finished with + */ +static void gelic_net_release_tx_chain(struct gelic_net_card *card, int stop) +{ + struct gelic_net_descr_chain *tx_chain; + enum gelic_net_descr_status status; + int release = 0; + + for (tx_chain = &card->tx_chain; + tx_chain->head != tx_chain->tail && tx_chain->tail; + tx_chain->tail = tx_chain->tail->next) { + status = gelic_net_get_descr_status(tx_chain->tail); + switch (status) { + case GELIC_NET_DESCR_RESPONSE_ERROR: + case GELIC_NET_DESCR_PROTECTION_ERROR: + case GELIC_NET_DESCR_FORCE_END: + if (printk_ratelimit()) + dev_info(ctodev(card), + "%s: forcing end of tx descriptor " \ + "with status %x\n", + __func__, status); + card->netdev_stats.tx_dropped++; + break; + + case GELIC_NET_DESCR_COMPLETE: + card->netdev_stats.tx_packets++; + card->netdev_stats.tx_bytes += + tx_chain->tail->skb->len; + break; + + case GELIC_NET_DESCR_CARDOWNED: + /* pending tx request */ + default: + /* any other value (== GELIC_NET_DESCR_NOT_IN_USE) */ + goto out; + } + gelic_net_release_tx_descr(card, tx_chain->tail); + release = 1; + } +out: + if (!stop && release) + netif_wake_queue(card->netdev); +} + +/** + * gelic_net_set_multi - sets multicast addresses and promisc flags + * @netdev: interface device structure + * + * gelic_net_set_multi configures multicast addresses as needed for the + * netdev interface. It also sets up multicast, allmulti and promisc + * flags appropriately + */ +static void gelic_net_set_multi(struct net_device *netdev) +{ + struct gelic_net_card *card = netdev_priv(netdev); + struct dev_mc_list *mc; + unsigned int i; + uint8_t *p; + u64 addr; + int status; + + /* clear all multicast address */ + status = lv1_net_remove_multicast_address(bus_id(card), dev_id(card), + 0, 1); + if (status) + dev_err(ctodev(card), + "lv1_net_remove_multicast_address failed %d\n", + status); + /* set broadcast address */ + status = lv1_net_add_multicast_address(bus_id(card), dev_id(card), + GELIC_NET_BROADCAST_ADDR, 0); + if (status) + dev_err(ctodev(card), + "lv1_net_add_multicast_address failed, %d\n", + status); + + if (netdev->flags & IFF_ALLMULTI + || netdev->mc_count > GELIC_NET_MC_COUNT_MAX) { /* list max */ + status = lv1_net_add_multicast_address(bus_id(card), + dev_id(card), + 0, 1); + if (status) + dev_err(ctodev(card), + "lv1_net_add_multicast_address failed, %d\n", + status); + return; + } + + /* set multicast address */ + for (mc = netdev->mc_list; mc; mc = mc->next) { + addr = 0; + p = mc->dmi_addr; + for (i = 0; i < ETH_ALEN; i++) { + addr <<= 8; + addr |= *p++; + } + status = lv1_net_add_multicast_address(bus_id(card), + dev_id(card), + addr, 0); + if (status) + dev_err(ctodev(card), + "lv1_net_add_multicast_address failed, %d\n", + status); + } +} + +/** + * gelic_net_enable_rxdmac - enables the receive DMA controller + * @card: card structure + * + * gelic_net_enable_rxdmac enables the DMA controller by setting RX_DMA_EN + * in the GDADMACCNTR register + */ +static inline void gelic_net_enable_rxdmac(struct gelic_net_card *card) +{ + int status; + + status = lv1_net_start_rx_dma(bus_id(card), dev_id(card), + card->rx_chain.tail->bus_addr, 0); + if (status) + dev_info(ctodev(card), + "lv1_net_start_rx_dma failed, status=%d\n", status); +} + +/** + * gelic_net_disable_rxdmac - disables the receive DMA controller + * @card: card structure + * + * gelic_net_disable_rxdmac terminates processing on the DMA controller by + * turing off DMA and issueing a force end + */ +static inline void gelic_net_disable_rxdmac(struct gelic_net_card *card) +{ + int status; + + /* this hvc blocks until the DMA in progress really stopped */ + status = lv1_net_stop_rx_dma(bus_id(card), dev_id(card), 0); + if (status) + dev_err(ctodev(card), + "lv1_net_stop_rx_dma faild, %d\n", status); +} + +/** + * gelic_net_disable_txdmac - disables the transmit DMA controller + * @card: card structure + * + * gelic_net_disable_txdmac terminates processing on the DMA controller by + * turing off DMA and issueing a force end + */ +static inline void gelic_net_disable_txdmac(struct gelic_net_card *card) +{ + int status; + + /* this hvc blocks until the DMA in progress really stopped */ + status = lv1_net_stop_tx_dma(bus_id(card), dev_id(card), 0); + if (status) + dev_err(ctodev(card), + "lv1_net_stop_tx_dma faild, status=%d\n", status); +} + +/** + * gelic_net_stop - called upon ifconfig down + * @netdev: interface device structure + * + * always returns 0 + */ +static int gelic_net_stop(struct net_device *netdev) +{ + struct gelic_net_card *card = netdev_priv(netdev); + + netif_poll_disable(netdev); + netif_stop_queue(netdev); + + /* turn off DMA, force end */ + gelic_net_disable_rxdmac(card); + gelic_net_disable_txdmac(card); + + gelic_net_set_irq_mask(card, 0); + + /* disconnect event port */ + free_irq(card->netdev->irq, card->netdev); + ps3_sb_event_receive_port_destroy(card->dev, card->netdev->irq); + card->netdev->irq = NO_IRQ; + + netif_carrier_off(netdev); + + /* release chains */ + gelic_net_release_tx_chain(card, 1); + gelic_net_release_rx_chain(card); + + gelic_net_free_chain(card, card->tx_top); + gelic_net_free_chain(card, card->rx_top); + + return 0; +} + +/** + * gelic_net_get_next_tx_descr - returns the next available tx descriptor + * @card: device structure to get descriptor from + * + * returns the address of the next descriptor, or NULL if not available. + */ +static struct gelic_net_descr * +gelic_net_get_next_tx_descr(struct gelic_net_card *card) +{ + if (!card->tx_chain.head) + return NULL; + /* see if we can two consecutive free descrs */ + if (card->tx_chain.tail != card->tx_chain.head->next && + gelic_net_get_descr_status(card->tx_chain.head) == + GELIC_NET_DESCR_NOT_IN_USE && + card->tx_chain.tail != card->tx_chain.head->next->next && + gelic_net_get_descr_status(card->tx_chain.head->next) == + GELIC_NET_DESCR_NOT_IN_USE ) + return card->tx_chain.head; + else + return NULL; + +} + +/** + * gelic_net_set_txdescr_cmdstat - sets the tx descriptor command field + * @descr: descriptor structure to fill out + * @skb: packet to consider + * @middle: middle of frame + * + * fills out the command and status field of the descriptor structure, + * depending on hardware checksum settings. This function assumes a wmb() + * has executed before. + */ +static void gelic_net_set_txdescr_cmdstat(struct gelic_net_descr *descr, + struct sk_buff *skb, int middle) +{ + u32 eofr; + + if (middle) + eofr = 0; + else + eofr = GELIC_NET_DMAC_CMDSTAT_END_FRAME; + + if (skb->ip_summed != CHECKSUM_PARTIAL) + descr->dmac_cmd_status = GELIC_NET_DMAC_CMDSTAT_NOCS | eofr; + else { + /* is packet ip? + * if yes: tcp? udp? */ + if (skb->protocol == htons(ETH_P_IP)) { + if (ip_hdr(skb)->protocol == IPPROTO_TCP) + descr->dmac_cmd_status = + GELIC_NET_DMAC_CMDSTAT_TCPCS | eofr; + else if (ip_hdr(skb)->protocol == IPPROTO_UDP) + descr->dmac_cmd_status = + GELIC_NET_DMAC_CMDSTAT_UDPCS | eofr; + else /* + * the stack should checksum non-tcp and non-udp + * packets on his own: NETIF_F_IP_CSUM + */ + descr->dmac_cmd_status = + GELIC_NET_DMAC_CMDSTAT_NOCS | eofr; + } + } +} + +/** + * gelic_net_prepare_tx_descr_v - get dma address of skb_data + * @card: card structure + * @descr: descriptor structure + * @skb: packet to use + * + * returns 0 on success, <0 on failure. + * + */ +static int gelic_net_prepare_tx_descr_v(struct gelic_net_card *card, + struct gelic_net_descr *descr, + struct sk_buff *skb) +{ + dma_addr_t buf[2]; + unsigned int vlan_len; + + if (skb->len < GELIC_NET_VLAN_POS) + return -EINVAL; + + memcpy(&descr->vlan, skb->data, GELIC_NET_VLAN_POS); + if (card->vlan_index != -1) { + descr->vlan.h_vlan_proto = htons(ETH_P_8021Q); /* vlan 0x8100*/ + descr->vlan.h_vlan_TCI = htons(card->vlan_id[card->vlan_index]); + vlan_len = GELIC_NET_VLAN_POS + VLAN_HLEN; /* VLAN_HLEN=4 */ + } else + vlan_len = GELIC_NET_VLAN_POS; /* no vlan tag */ + + /* first descr */ + buf[0] = dma_map_single(ctodev(card), &descr->vlan, + vlan_len, DMA_TO_DEVICE); + + if (!buf[0]) { + dev_err(ctodev(card), + "dma map 1 failed (%p, %i). Dropping packet\n", + skb->data, vlan_len); + return -ENOMEM; + } + + descr->buf_addr = buf[0]; + descr->buf_size = vlan_len; + descr->skb = skb; /* not used */ + descr->data_status = 0; + gelic_net_set_txdescr_cmdstat(descr, skb, 1); /* not the frame end */ + + /* second descr */ + card->tx_chain.head = card->tx_chain.head->next; + descr->next_descr_addr = descr->next->bus_addr; + descr = descr->next; + if (gelic_net_get_descr_status(descr) != GELIC_NET_DESCR_NOT_IN_USE) + /* XXX will be removed */ + dev_err(ctodev(card), "descr is not free!\n"); + + buf[1] = dma_map_single(ctodev(card), skb->data + GELIC_NET_VLAN_POS, + skb->len - GELIC_NET_VLAN_POS, + DMA_TO_DEVICE); + + if (!buf[1]) { + dev_err(ctodev(card), + "dma map 2 failed (%p, %i). Dropping packet\n", + skb->data + GELIC_NET_VLAN_POS, + skb->len - GELIC_NET_VLAN_POS); + dma_unmap_single(ctodev(card), buf[0], vlan_len, + DMA_TO_DEVICE); + return -ENOMEM; + } + + descr->buf_addr = buf[1]; + descr->buf_size = skb->len - GELIC_NET_VLAN_POS; + descr->skb = skb; + descr->data_status = 0; + descr->next_descr_addr = 0; /* terminate hw descr */ + gelic_net_set_txdescr_cmdstat(descr, skb, 0); + + return 0; +} + +/** + * gelic_net_kick_txdma - enables TX DMA processing + * @card: card structure + * @descr: descriptor address to enable TX processing at + * + */ +static int gelic_net_kick_txdma(struct gelic_net_card *card, + struct gelic_net_descr *descr) +{ + int status = -ENXIO; + int count = 10; + + if (card->tx_dma_progress) + return 0; + + if (gelic_net_get_descr_status(descr) == GELIC_NET_DESCR_CARDOWNED) { + card->tx_dma_progress = 1; + /* sometimes we need retry here */ + while (count--) { + status = lv1_net_start_tx_dma(bus_id(card), + dev_id(card), + descr->bus_addr, 0); + if (!status) + break; + } + if (!count) + dev_info(ctodev(card), "lv1_net_start_txdma failed," \ + "status=%d %#lx\n", + status, card->irq_status); + } + return status; +} + +/** + * gelic_net_xmit - transmits a frame over the device + * @skb: packet to send out + * @netdev: interface device structure + * + * returns 0 on success, <0 on failure + */ +static int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev) +{ + struct gelic_net_card *card = netdev_priv(netdev); + struct gelic_net_descr *descr = NULL; + int result; + unsigned long flags; + + spin_lock_irqsave(&card->tx_dma_lock, flags); + + gelic_net_release_tx_chain(card, 0); + if (!skb) + goto kick; + descr = gelic_net_get_next_tx_descr(card); + if (!descr) { + netif_stop_queue(netdev); + spin_unlock_irqrestore(&card->tx_dma_lock, flags); + return NETDEV_TX_BUSY; + } + result = gelic_net_prepare_tx_descr_v(card, descr, skb); + + if (result) + goto error; + + card->tx_chain.head = card->tx_chain.head->next; + + if (descr->prev) + descr->prev->next_descr_addr = descr->bus_addr; +kick: + /* + * as hardware descriptor is modified in the above lines, + * ensure that the hardware sees it + */ + wmb(); + if (gelic_net_kick_txdma(card, card->tx_chain.tail)) + goto error; + + netdev->trans_start = jiffies; + spin_unlock_irqrestore(&card->tx_dma_lock, flags); + return NETDEV_TX_OK; + +error: + card->netdev_stats.tx_dropped++; + spin_unlock_irqrestore(&card->tx_dma_lock, flags); + return NETDEV_TX_LOCKED; +} + +/** + * gelic_net_pass_skb_up - takes an skb from a descriptor and passes it on + * @descr: descriptor to process + * @card: card structure + * + * iommu-unmaps the skb, fills out skb structure and passes the data to the + * stack. The descriptor state is not changed. + */ +static void gelic_net_pass_skb_up(struct gelic_net_descr *descr, + struct gelic_net_card *card) +{ + struct sk_buff *skb; + struct net_device *netdev; + u32 data_status, data_error; + + data_status = descr->data_status; + data_error = descr->data_error; + netdev = card->netdev; + /* unmap skb buffer */ + skb = descr->skb; + dma_unmap_single(ctodev(card), descr->buf_addr, GELIC_NET_MAX_MTU, + DMA_FROM_DEVICE); + + skb_put(skb, descr->valid_size? descr->valid_size : descr->result_size); + if (!descr->valid_size) + dev_info(ctodev(card), "buffer full %x %x %x\n", + descr->result_size, descr->buf_size, + descr->dmac_cmd_status); + + descr->skb = NULL; + /* + * the card put 2 bytes vlan tag in front + * of the ethernet frame + */ + skb_pull(skb, 2); + skb->protocol = eth_type_trans(skb, netdev); + + /* checksum offload */ + if (card->rx_csum) { + if ((data_status & GELIC_NET_DATA_STATUS_CHK_MASK) && + (!(data_error & GELIC_NET_DATA_ERROR_CHK_MASK))) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; + } else + skb->ip_summed = CHECKSUM_NONE; + + /* update netdevice statistics */ + card->netdev_stats.rx_packets++; + card->netdev_stats.rx_bytes += skb->len; + + /* pass skb up to stack */ + netif_receive_skb(skb); +} + +/** + * gelic_net_decode_one_descr - processes an rx descriptor + * @card: card structure + * + * returns 1 if a packet has been sent to the stack, otherwise 0 + * + * processes an rx descriptor by iommu-unmapping the data buffer and passing + * the packet up to the stack + */ +static int gelic_net_decode_one_descr(struct gelic_net_card *card) +{ + enum gelic_net_descr_status status; + struct gelic_net_descr_chain *chain = &card->rx_chain; + struct gelic_net_descr *descr = chain->tail; + int dmac_chain_ended; + + status = gelic_net_get_descr_status(descr); + /* is this descriptor terminated with next_descr == NULL? */ + dmac_chain_ended = + descr->dmac_cmd_status & GELIC_NET_DMAC_CMDSTAT_RXDCEIS; + + if (status == GELIC_NET_DESCR_CARDOWNED) + return 0; + + if (status == GELIC_NET_DESCR_NOT_IN_USE) { + dev_dbg(ctodev(card), "dormant descr? %p\n", descr); + return 0; + } + + if ((status == GELIC_NET_DESCR_RESPONSE_ERROR) || + (status == GELIC_NET_DESCR_PROTECTION_ERROR) || + (status == GELIC_NET_DESCR_FORCE_END)) { + dev_info(ctodev(card), "dropping RX descriptor with state %x\n", + status); + card->netdev_stats.rx_dropped++; + goto refill; + } + + if ((status != GELIC_NET_DESCR_COMPLETE) && + (status != GELIC_NET_DESCR_FRAME_END)) { + dev_dbg(ctodev(card), "RX descriptor with state %x\n", + status); + goto refill; + } + + /* ok, we've got a packet in descr */ + gelic_net_pass_skb_up(descr, card); /* 1: skb_up sccess */ + +refill: + descr->next_descr_addr = 0; /* unlink the descr */ + + /* change the descriptor state: */ + gelic_net_set_descr_status(descr, GELIC_NET_DESCR_NOT_IN_USE); + + /* refill one desc + * FIXME: this can fail, but for now, just leave this + * descriptor without skb + */ + gelic_net_prepare_rx_descr(card, descr); + chain->head = descr; + chain->tail = descr->next; + descr->prev->next_descr_addr = descr->bus_addr; + + if (dmac_chain_ended) { + gelic_net_enable_rxdmac(card); + dev_dbg(ctodev(card), "reenable rx dma\n"); + } + + return 1; +} + +/** + * gelic_net_poll - NAPI poll function called by the stack to return packets + * @netdev: interface device structure + * @budget: number of packets we can pass to the stack at most + * + * returns 0 if no more packets available to the driver/stack. Returns 1, + * if the quota is exceeded, but the driver has still packets. + * + */ +static int gelic_net_poll(struct net_device *netdev, int *budget) +{ + struct gelic_net_card *card = netdev_priv(netdev); + int packets_to_do, packets_done = 0; + int no_more_packets = 0; + + packets_to_do = min(*budget, netdev->quota); + + while (packets_to_do) { + if (gelic_net_decode_one_descr(card)) { + packets_done++; + packets_to_do--; + } else { + /* no more packets for the stack */ + no_more_packets = 1; + break; + } + } + netdev->quota -= packets_done; + *budget -= packets_done; + if (no_more_packets) { + netif_rx_complete(netdev); + gelic_net_rx_irq_on(card); + return 0; + } else + return 1; +} + +/** + * gelic_net_get_stats - get interface statistics + * @netdev: interface device structure + * + * returns the interface statistics residing in the gelic_net_card struct + */ +static struct net_device_stats *gelic_net_get_stats(struct net_device *netdev) +{ + struct gelic_net_card *card = netdev_priv(netdev); + + return &card->netdev_stats; +} + +/** + * gelic_net_change_mtu - changes the MTU of an interface + * @netdev: interface device structure + * @new_mtu: new MTU value + * + * returns 0 on success, <0 on failure + */ +static int gelic_net_change_mtu(struct net_device *netdev, int new_mtu) +{ + /* no need to re-alloc skbs or so -- the max mtu is about 2.3k + * and mtu is outbound only anyway */ + if ((new_mtu < GELIC_NET_MIN_MTU) || + (new_mtu > GELIC_NET_MAX_MTU)) { + return -EINVAL; + } + netdev->mtu = new_mtu; + return 0; +} + +/** + * gelic_net_interrupt - event handler for gelic_net + */ +static irqreturn_t gelic_net_interrupt(int irq, void *ptr) +{ + unsigned long flags; + struct net_device *netdev = ptr; + struct gelic_net_card *card = netdev_priv(netdev); + u64 status; + + status = card->irq_status; + + if (!status) + return IRQ_NONE; + + if (status & GELIC_NET_RXINT) { + gelic_net_rx_irq_off(card); + netif_rx_schedule(netdev); + } + + if (status & GELIC_NET_TXINT) { + spin_lock_irqsave(&card->tx_dma_lock, flags); + card->tx_dma_progress = 0; + spin_unlock_irqrestore(&card->tx_dma_lock, flags); + /* start pending DMA */ + gelic_net_xmit(NULL, netdev); + } + return IRQ_HANDLED; +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +/** + * gelic_net_poll_controller - artificial interrupt for netconsole etc. + * @netdev: interface device structure + * + * see Documentation/networking/netconsole.txt + */ +static void gelic_net_poll_controller(struct net_device *netdev) +{ + struct gelic_net_card *card = netdev_priv(netdev); + + gelic_net_set_irq_mask(card, 0); + gelic_net_interrupt(netdev->irq, netdev); + gelic_net_set_irq_mask(card, card->ghiintmask); +} +#endif /* CONFIG_NET_POLL_CONTROLLER */ + +/** + * gelic_net_open_device - open device and map dma region + * @card: card structure + */ +static int gelic_net_open_device(struct gelic_net_card *card) +{ + int result; + + result = ps3_sb_event_receive_port_setup(card->dev, PS3_BINDING_CPU_ANY, + &card->netdev->irq); + + if (result) { + dev_info(ctodev(card), + "%s:%d: gelic_net_open_device failed (%d)\n", + __func__, __LINE__, result); + result = -EPERM; + goto fail_alloc_irq; + } + + result = request_irq(card->netdev->irq, gelic_net_interrupt, + IRQF_DISABLED, "gelic network", card->netdev); + + if (result) { + dev_info(ctodev(card), "%s:%d: request_irq failed (%d)\n", + __func__, __LINE__, result); + goto fail_request_irq; + } + + return 0; + +fail_request_irq: + ps3_sb_event_receive_port_destroy(card->dev, card->netdev->irq); + card->netdev->irq = NO_IRQ; +fail_alloc_irq: + return result; +} + + +/** + * gelic_net_open - called upon ifonfig up + * @netdev: interface device structure + * + * returns 0 on success, <0 on failure + * + * gelic_net_open allocates all the descriptors and memory needed for + * operation, sets up multicast list and enables interrupts + */ +static int gelic_net_open(struct net_device *netdev) +{ + struct gelic_net_card *card = netdev_priv(netdev); + + dev_dbg(ctodev(card), " -> %s:%d\n", __func__, __LINE__); + + gelic_net_open_device(card); + + if (gelic_net_init_chain(card, &card->tx_chain, + card->descr, GELIC_NET_TX_DESCRIPTORS)) + goto alloc_tx_failed; + if (gelic_net_init_chain(card, &card->rx_chain, + card->descr + GELIC_NET_RX_DESCRIPTORS, + GELIC_NET_RX_DESCRIPTORS)) + goto alloc_rx_failed; + + /* head of chain */ + card->tx_top = card->tx_chain.head; + card->rx_top = card->rx_chain.head; + dev_dbg(ctodev(card), "descr rx %p, tx %p, size %#lx, num %#x\n", + card->rx_top, card->tx_top, sizeof(struct gelic_net_descr), + GELIC_NET_RX_DESCRIPTORS); + /* allocate rx skbs */ + if (gelic_net_alloc_rx_skbs(card)) + goto alloc_skbs_failed; + + card->tx_dma_progress = 0; + card->ghiintmask = GELIC_NET_RXINT | GELIC_NET_TXINT; + + gelic_net_set_irq_mask(card, card->ghiintmask); + gelic_net_enable_rxdmac(card); + + netif_start_queue(netdev); + netif_carrier_on(netdev); + netif_poll_enable(netdev); + + return 0; + +alloc_skbs_failed: + gelic_net_free_chain(card, card->rx_top); +alloc_rx_failed: + gelic_net_free_chain(card, card->tx_top); +alloc_tx_failed: + return -ENOMEM; +} + +#ifdef GELIC_NET_ETHTOOL +static void gelic_net_get_drvinfo (struct net_device *netdev, + struct ethtool_drvinfo *info) +{ + strncpy(info->driver, DRV_NAME, sizeof(info->driver) - 1); + strncpy(info->version, DRV_VERSION, sizeof(info->version) - 1); +} + +static int gelic_net_get_settings(struct net_device *netdev, + struct ethtool_cmd *cmd) +{ + struct gelic_net_card *card = netdev_priv(netdev); + int status; + u64 v1, v2; + int speed, duplex; + + speed = duplex = -1; + status = lv1_net_control(bus_id(card), dev_id(card), + GELIC_NET_GET_ETH_PORT_STATUS, GELIC_NET_PORT, 0, 0, + &v1, &v2); + if (status) { + /* link down */ + } else { + if (v1 & GELIC_NET_FULL_DUPLEX) { + duplex = DUPLEX_FULL; + } else { + duplex = DUPLEX_HALF; + } + + if (v1 & GELIC_NET_SPEED_10 ) { + speed = SPEED_10; + } else if (v1 & GELIC_NET_SPEED_100) { + speed = SPEED_100; + } else if (v1 & GELIC_NET_SPEED_1000) { + speed = SPEED_1000; + } + } + cmd->supported = SUPPORTED_TP | SUPPORTED_Autoneg | + SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full; + cmd->advertising = cmd->supported; + cmd->speed = speed; + cmd->duplex = duplex; + cmd->autoneg = AUTONEG_ENABLE; /* always enabled */ + cmd->port = PORT_TP; + + return 0; +} + +static u32 gelic_net_get_link(struct net_device *netdev) +{ + struct gelic_net_card *card = netdev_priv(netdev); + int status; + u64 v1, v2; + int link; + + status = lv1_net_control(bus_id(card), dev_id(card), + GELIC_NET_GET_ETH_PORT_STATUS, GELIC_NET_PORT, 0, 0, + &v1, &v2); + if (status) + return 0; /* link down */ + + if (v1 & GELIC_NET_LINK_UP) + link = 1; + else + link = 0; + + return link; +} + +static int gelic_net_nway_reset(struct net_device *netdev) +{ + if (netif_running(netdev)) { + gelic_net_stop(netdev); + gelic_net_open(netdev); + } + return 0; +} + +static u32 gelic_net_get_tx_csum(struct net_device *netdev) +{ + return (netdev->features & NETIF_F_IP_CSUM) != 0; +} + +static int gelic_net_set_tx_csum(struct net_device *netdev, u32 data) +{ + if (data) + netdev->features |= NETIF_F_IP_CSUM; + else + netdev->features &= ~NETIF_F_IP_CSUM; + + return 0; +} + +static u32 gelic_net_get_rx_csum(struct net_device *netdev) +{ + struct gelic_net_card *card = netdev_priv(netdev); + + return card->rx_csum; +} + +static int gelic_net_set_rx_csum(struct net_device *netdev, u32 data) +{ + struct gelic_net_card *card = netdev_priv(netdev); + + card->rx_csum = data; + return 0; +} + +static struct ethtool_ops gelic_net_ethtool_ops = { + .get_drvinfo = gelic_net_get_drvinfo, + .get_settings = gelic_net_get_settings, + .get_link = gelic_net_get_link, + .nway_reset = gelic_net_nway_reset, + .get_tx_csum = gelic_net_get_tx_csum, + .set_tx_csum = gelic_net_set_tx_csum, + .get_rx_csum = gelic_net_get_rx_csum, + .set_rx_csum = gelic_net_set_rx_csum, +}; +#endif + +/** + * gelic_net_tx_timeout_task - task scheduled by the watchdog timeout + * function (to be called not under interrupt status) + * @work: work is context of tx timout task + * + * called as task when tx hangs, resets interface (if interface is up) + */ +static void gelic_net_tx_timeout_task(struct work_struct *work) +{ + struct gelic_net_card *card = + container_of(work, struct gelic_net_card, tx_timeout_task); + struct net_device *netdev = card->netdev; + + dev_info(ctodev(card), "%s:Timed out. Restarting... \n", __func__); + + if (!(netdev->flags & IFF_UP)) + goto out; + + netif_device_detach(netdev); + gelic_net_stop(netdev); + + gelic_net_open(netdev); + netif_device_attach(netdev); + +out: + atomic_dec(&card->tx_timeout_task_counter); +} + +/** + * gelic_net_tx_timeout - called when the tx timeout watchdog kicks in. + * @netdev: interface device structure + * + * called, if tx hangs. Schedules a task that resets the interface + */ +static void gelic_net_tx_timeout(struct net_device *netdev) +{ + struct gelic_net_card *card; + + card = netdev_priv(netdev); + atomic_inc(&card->tx_timeout_task_counter); + if (netdev->flags & IFF_UP) + schedule_work(&card->tx_timeout_task); + else + atomic_dec(&card->tx_timeout_task_counter); +} + +/** + * gelic_net_setup_netdev_ops - initialization of net_device operations + * @netdev: net_device structure + * + * fills out function pointers in the net_device structure + */ +static void gelic_net_setup_netdev_ops(struct net_device *netdev) +{ + netdev->open = &gelic_net_open; + netdev->stop = &gelic_net_stop; + netdev->hard_start_xmit = &gelic_net_xmit; + netdev->get_stats = &gelic_net_get_stats; + netdev->set_multicast_list = &gelic_net_set_multi; + netdev->change_mtu = &gelic_net_change_mtu; + /* tx watchdog */ + netdev->tx_timeout = &gelic_net_tx_timeout; + netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT; + /* NAPI */ + netdev->poll = &gelic_net_poll; + netdev->weight = GELIC_NET_NAPI_WEIGHT; +#ifdef GELIC_NET_ETHTOOL + netdev->ethtool_ops = &gelic_net_ethtool_ops; +#endif +} + +/** + * gelic_net_setup_netdev - initialization of net_device + * @card: card structure + * + * Returns 0 on success or <0 on failure + * + * gelic_net_setup_netdev initializes the net_device structure + **/ +static int gelic_net_setup_netdev(struct gelic_net_card *card) +{ + struct net_device *netdev = card->netdev; + struct sockaddr addr; + unsigned int i; + int status; + u64 v1, v2; + + SET_MODULE_OWNER(netdev); + SET_NETDEV_DEV(netdev, &card->dev->core); + spin_lock_init(&card->tx_dma_lock); + + card->rx_csum = GELIC_NET_RX_CSUM_DEFAULT; + + gelic_net_setup_netdev_ops(netdev); + + netdev->features = NETIF_F_IP_CSUM; + + status = lv1_net_control(bus_id(card), dev_id(card), + GELIC_NET_GET_MAC_ADDRESS, + 0, 0, 0, &v1, &v2); + if (status || !is_valid_ether_addr((u8 *)&v1)) { + dev_info(ctodev(card), + "%s:lv1_net_control GET_MAC_ADDR failed %d\n", + __func__, status); + return -EINVAL; + } + v1 <<= 16; + memcpy(addr.sa_data, &v1, ETH_ALEN); + memcpy(netdev->dev_addr, addr.sa_data, ETH_ALEN); + dev_info(ctodev(card), "MAC addr %02x:%02x:%02x:%02x:%02x:%02x\n", + netdev->dev_addr[0], netdev->dev_addr[1], + netdev->dev_addr[2], netdev->dev_addr[3], + netdev->dev_addr[4], netdev->dev_addr[5]); + + card->vlan_index = -1; /* no vlan */ + for (i = 0; i < GELIC_NET_VLAN_MAX; i++) { + status = lv1_net_control(bus_id(card), dev_id(card), + GELIC_NET_GET_VLAN_ID, + i + 1, /* index; one based */ + 0, 0, &v1, &v2); + if (status == GELIC_NET_VLAN_NO_ENTRY) { + dev_dbg(ctodev(card), + "GELIC_VLAN_ID no entry:%d, VLAN disabled\n", + status); + card->vlan_id[i] = 0; + } else if (status) { + dev_dbg(ctodev(card), + "%s:GELIC_NET_VLAN_ID faild, status=%d\n", + __func__, status); + card->vlan_id[i] = 0; + } else { + card->vlan_id[i] = (u32)v1; + dev_dbg(ctodev(card), "vlan_id:%d, %lx\n", i, v1); + } + } + if (card->vlan_id[GELIC_NET_VLAN_WIRED - 1]) + card->vlan_index = GELIC_NET_VLAN_WIRED - 1; + + status = register_netdev(netdev); + if (status) { + dev_err(ctodev(card), "%s:Couldn't register net_device: %d\n", + __func__, status); + return status; + } + + return 0; +} + +/** + * gelic_net_alloc_card - allocates net_device and card structure + * + * returns the card structure or NULL in case of errors + * + * the card and net_device structures are linked to each other + */ +static struct gelic_net_card *gelic_net_alloc_card(void) +{ + struct net_device *netdev; + struct gelic_net_card *card; + size_t alloc_size; + + alloc_size = sizeof (*card) + + sizeof (struct gelic_net_descr) * GELIC_NET_RX_DESCRIPTORS + + sizeof (struct gelic_net_descr) * GELIC_NET_TX_DESCRIPTORS; + /* + * we assume private data is allocated 32 bytes (or more) aligned + * so that gelic_net_descr should be 32 bytes aligned. + * Current alloc_etherdev() does do it because NETDEV_ALIGN + * is 32. + * check this assumption here. + */ + BUILD_BUG_ON(NETDEV_ALIGN < 32); + BUILD_BUG_ON(offsetof(struct gelic_net_card, irq_status) % 8); + BUILD_BUG_ON(offsetof(struct gelic_net_card, descr) % 32); + + netdev = alloc_etherdev(alloc_size); + if (!netdev) + return NULL; + + card = netdev_priv(netdev); + card->netdev = netdev; + INIT_WORK(&card->tx_timeout_task, gelic_net_tx_timeout_task); + init_waitqueue_head(&card->waitq); + atomic_set(&card->tx_timeout_task_counter, 0); + + return card; +} + +/** + * ps3_gelic_driver_probe - add a device to the control of this driver + */ +static int ps3_gelic_driver_probe (struct ps3_system_bus_device *dev) +{ + struct gelic_net_card *card = gelic_net_alloc_card(); + int result; + + if (!card) { + dev_info(&dev->core, "gelic_net_alloc_card failed\n"); + result = -ENOMEM; + goto fail_alloc_card; + } + + ps3_system_bus_set_driver_data(dev, card); + card->dev = dev; + + result = ps3_open_hv_device(dev); + + if (result) { + dev_dbg(&dev->core, "ps3_open_hv_device failed\n"); + goto fail_open; + } + + result = ps3_dma_region_create(dev->d_region); + + if (result) { + dev_dbg(&dev->core, "ps3_dma_region_create failed(%d)\n", + result); + BUG_ON("check region type"); + goto fail_dma_region; + } + + result = lv1_net_set_interrupt_status_indicator(bus_id(card), + dev_id(card), + ps3_mm_phys_to_lpar(__pa(&card->irq_status)), + 0); + + if (result) { + dev_dbg(&dev->core, + "lv1_net_set_interrupt_status_indicator failed: %s\n", + ps3_result(result)); + result = -EIO; + goto fail_status_indicator; + } + + result = gelic_net_setup_netdev(card); + + if (result) { + dev_dbg(&dev->core, "%s:%d: ps3_dma_region_create failed: " + "(%d)\n", __func__, __LINE__, result); + goto fail_setup_netdev; + } + + return 0; + +fail_setup_netdev: + lv1_net_set_interrupt_status_indicator(bus_id(card), + bus_id(card), + 0 , 0); +fail_status_indicator: + ps3_dma_region_free(dev->d_region); +fail_dma_region: + ps3_close_hv_device(dev); +fail_open: + ps3_system_bus_set_driver_data(dev, NULL); + free_netdev(card->netdev); +fail_alloc_card: + return result; +} + +/** + * ps3_gelic_driver_remove - remove a device from the control of this driver + */ + +static int ps3_gelic_driver_remove (struct ps3_system_bus_device *dev) +{ + struct gelic_net_card *card = ps3_system_bus_get_driver_data(dev); + + wait_event(card->waitq, + atomic_read(&card->tx_timeout_task_counter) == 0); + + lv1_net_set_interrupt_status_indicator(bus_id(card), dev_id(card), + 0 , 0); + + unregister_netdev(card->netdev); + free_netdev(card->netdev); + + ps3_system_bus_set_driver_data(dev, NULL); + + ps3_dma_region_free(dev->d_region); + + ps3_close_hv_device(dev); + + return 0; +} + +static struct ps3_system_bus_driver ps3_gelic_driver = { + .match_id = PS3_MATCH_ID_GELIC, + .probe = ps3_gelic_driver_probe, + .remove = ps3_gelic_driver_remove, + .shutdown = ps3_gelic_driver_remove, + .core.name = "ps3_gelic_driver", + .core.owner = THIS_MODULE, +}; + +static int __init ps3_gelic_driver_init (void) +{ + return firmware_has_feature(FW_FEATURE_PS3_LV1) + ? ps3_system_bus_driver_register(&ps3_gelic_driver) + : -ENODEV; +} + +static void __exit ps3_gelic_driver_exit (void) +{ + ps3_system_bus_driver_unregister(&ps3_gelic_driver); +} + +module_init (ps3_gelic_driver_init); +module_exit (ps3_gelic_driver_exit); + +MODULE_ALIAS(PS3_MODULE_ALIAS_GELIC); + diff --git a/drivers/net/ps3_gelic_net.h b/drivers/net/ps3_gelic_net.h new file mode 100644 index 00000000000..5e1c28654e1 --- /dev/null +++ b/drivers/net/ps3_gelic_net.h @@ -0,0 +1,239 @@ +/* + * PS3 Platfom gelic network driver. + * + * Copyright (C) 2007 Sony Computer Entertainment Inc. + * Copyright 2006, 2007 Sony Corporation. + * + * This file is based on: spider_net.h + * + * (C) Copyright IBM Corp. 2005 + * + * Authors : Utz Bacher <utz.bacher@de.ibm.com> + * Jens Osterkamp <Jens.Osterkamp@de.ibm.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef _GELIC_NET_H +#define _GELIC_NET_H + +#define GELIC_NET_DRV_NAME "Gelic Network Driver" +#define GELIC_NET_DRV_VERSION "1.0" + +#define GELIC_NET_ETHTOOL /* use ethtool */ + +/* ioctl */ +#define GELIC_NET_GET_MODE (SIOCDEVPRIVATE + 0) +#define GELIC_NET_SET_MODE (SIOCDEVPRIVATE + 1) + +/* descriptors */ +#define GELIC_NET_RX_DESCRIPTORS 128 /* num of descriptors */ +#define GELIC_NET_TX_DESCRIPTORS 128 /* num of descriptors */ + +#define GELIC_NET_MAX_MTU 2308 +#define GELIC_NET_MIN_MTU 64 +#define GELIC_NET_RXBUF_ALIGN 128 +#define GELIC_NET_RX_CSUM_DEFAULT 1 /* hw chksum */ +#define GELIC_NET_WATCHDOG_TIMEOUT 5*HZ +#define GELIC_NET_NAPI_WEIGHT (GELIC_NET_RX_DESCRIPTORS) +#define GELIC_NET_BROADCAST_ADDR 0xffffffffffffL +#define GELIC_NET_VLAN_POS (VLAN_ETH_ALEN * 2) +#define GELIC_NET_VLAN_MAX 4 +#define GELIC_NET_MC_COUNT_MAX 32 /* multicast address list */ + +enum gelic_net_int0_status { + GELIC_NET_GDTDCEINT = 24, + GELIC_NET_GRFANMINT = 28, +}; + +/* GHIINT1STS bits */ +enum gelic_net_int1_status { + GELIC_NET_GDADCEINT = 14, +}; + +/* interrupt mask */ +#define GELIC_NET_TXINT (1L << (GELIC_NET_GDTDCEINT + 32)) + +#define GELIC_NET_RXINT0 (1L << (GELIC_NET_GRFANMINT + 32)) +#define GELIC_NET_RXINT1 (1L << GELIC_NET_GDADCEINT) +#define GELIC_NET_RXINT (GELIC_NET_RXINT0 | GELIC_NET_RXINT1) + + /* RX descriptor data_status bits */ +#define GELIC_NET_RXDMADU 0x80000000 /* destination MAC addr unknown */ +#define GELIC_NET_RXLSTFBF 0x40000000 /* last frame buffer */ +#define GELIC_NET_RXIPCHK 0x20000000 /* IP checksum performed */ +#define GELIC_NET_RXTCPCHK 0x10000000 /* TCP/UDP checksup performed */ +#define GELIC_NET_RXIPSPKT 0x08000000 /* IPsec packet */ +#define GELIC_NET_RXIPSAHPRT 0x04000000 /* IPsec AH protocol performed */ +#define GELIC_NET_RXIPSESPPRT 0x02000000 /* IPsec ESP protocol performed */ +#define GELIC_NET_RXSESPAH 0x01000000 /* + * IPsec ESP protocol auth + * performed + */ + +#define GELIC_NET_RXWTPKT 0x00C00000 /* + * wakeup trigger packet + * 01: Magic Packet (TM) + * 10: ARP packet + * 11: Multicast MAC addr + */ +#define GELIC_NET_RXVLNPKT 0x00200000 /* VLAN packet */ +/* bit 20..16 reserved */ +#define GELIC_NET_RXRECNUM 0x0000ff00 /* reception receipt number */ +/* bit 7..0 reserved */ + +#define GELIC_NET_TXDESC_TAIL 0 +#define GELIC_NET_DATA_STATUS_CHK_MASK (GELIC_NET_RXIPCHK | GELIC_NET_RXTCPCHK) + +/* RX descriptor data_error bits */ +/* bit 31 reserved */ +#define GELIC_NET_RXALNERR 0x40000000 /* alignement error 10/100M */ +#define GELIC_NET_RXOVERERR 0x20000000 /* oversize error */ +#define GELIC_NET_RXRNTERR 0x10000000 /* Runt error */ +#define GELIC_NET_RXIPCHKERR 0x08000000 /* IP checksum error */ +#define GELIC_NET_RXTCPCHKERR 0x04000000 /* TCP/UDP checksum error */ +#define GELIC_NET_RXUMCHSP 0x02000000 /* unmatched sp on sp */ +#define GELIC_NET_RXUMCHSPI 0x01000000 /* unmatched SPI on SAD */ +#define GELIC_NET_RXUMCHSAD 0x00800000 /* unmatched SAD */ +#define GELIC_NET_RXIPSAHERR 0x00400000 /* auth error on AH protocol + * processing */ +#define GELIC_NET_RXIPSESPAHERR 0x00200000 /* auth error on ESP protocol + * processing */ +#define GELIC_NET_RXDRPPKT 0x00100000 /* drop packet */ +#define GELIC_NET_RXIPFMTERR 0x00080000 /* IP packet format error */ +/* bit 18 reserved */ +#define GELIC_NET_RXDATAERR 0x00020000 /* IP packet format error */ +#define GELIC_NET_RXCALERR 0x00010000 /* cariier extension length + * error */ +#define GELIC_NET_RXCREXERR 0x00008000 /* carrier extention error */ +#define GELIC_NET_RXMLTCST 0x00004000 /* multicast address frame */ +/* bit 13..0 reserved */ +#define GELIC_NET_DATA_ERROR_CHK_MASK \ + (GELIC_NET_RXIPCHKERR | GELIC_NET_RXTCPCHKERR) + + +/* tx descriptor command and status */ +#define GELIC_NET_DMAC_CMDSTAT_NOCS 0xa0080000 /* middle of frame */ +#define GELIC_NET_DMAC_CMDSTAT_TCPCS 0xa00a0000 +#define GELIC_NET_DMAC_CMDSTAT_UDPCS 0xa00b0000 +#define GELIC_NET_DMAC_CMDSTAT_END_FRAME 0x00040000 /* end of frame */ + +#define GELIC_NET_DMAC_CMDSTAT_RXDCEIS 0x00000002 /* descriptor chain end + * interrupt status */ + +#define GELIC_NET_DMAC_CMDSTAT_CHAIN_END 0x00000002 /* RXDCEIS:DMA stopped */ +#define GELIC_NET_DMAC_CMDSTAT_NOT_IN_USE 0xb0000000 +#define GELIC_NET_DESCR_IND_PROC_SHIFT 28 +#define GELIC_NET_DESCR_IND_PROC_MASKO 0x0fffffff + + +enum gelic_net_descr_status { + GELIC_NET_DESCR_COMPLETE = 0x00, /* used in rx and tx */ + GELIC_NET_DESCR_RESPONSE_ERROR = 0x01, /* used in rx and tx */ + GELIC_NET_DESCR_PROTECTION_ERROR = 0x02, /* used in rx and tx */ + GELIC_NET_DESCR_FRAME_END = 0x04, /* used in rx */ + GELIC_NET_DESCR_FORCE_END = 0x05, /* used in rx and tx */ + GELIC_NET_DESCR_CARDOWNED = 0x0a, /* used in rx and tx */ + GELIC_NET_DESCR_NOT_IN_USE /* any other value */ +}; +/* for lv1_net_control */ +#define GELIC_NET_GET_MAC_ADDRESS 0x0000000000000001 +#define GELIC_NET_GET_ETH_PORT_STATUS 0x0000000000000002 +#define GELIC_NET_SET_NEGOTIATION_MODE 0x0000000000000003 +#define GELIC_NET_GET_VLAN_ID 0x0000000000000004 + +#define GELIC_NET_LINK_UP 0x0000000000000001 +#define GELIC_NET_FULL_DUPLEX 0x0000000000000002 +#define GELIC_NET_AUTO_NEG 0x0000000000000004 +#define GELIC_NET_SPEED_10 0x0000000000000010 +#define GELIC_NET_SPEED_100 0x0000000000000020 +#define GELIC_NET_SPEED_1000 0x0000000000000040 + +#define GELIC_NET_VLAN_ALL 0x0000000000000001 +#define GELIC_NET_VLAN_WIRED 0x0000000000000002 +#define GELIC_NET_VLAN_WIRELESS 0x0000000000000003 +#define GELIC_NET_VLAN_PSP 0x0000000000000004 +#define GELIC_NET_VLAN_PORT0 0x0000000000000010 +#define GELIC_NET_VLAN_PORT1 0x0000000000000011 +#define GELIC_NET_VLAN_PORT2 0x0000000000000012 +#define GELIC_NET_VLAN_DAEMON_CLIENT_BSS 0x0000000000000013 +#define GELIC_NET_VLAN_LIBERO_CLIENT_BSS 0x0000000000000014 +#define GELIC_NET_VLAN_NO_ENTRY -6 + +#define GELIC_NET_PORT 2 /* for port status */ + +/* size of hardware part of gelic descriptor */ +#define GELIC_NET_DESCR_SIZE (32) +struct gelic_net_descr { + /* as defined by the hardware */ + u32 buf_addr; + u32 buf_size; + u32 next_descr_addr; + u32 dmac_cmd_status; + u32 result_size; + u32 valid_size; /* all zeroes for tx */ + u32 data_status; + u32 data_error; /* all zeroes for tx */ + + /* used in the driver */ + struct sk_buff *skb; + dma_addr_t bus_addr; + struct gelic_net_descr *next; + struct gelic_net_descr *prev; + struct vlan_ethhdr vlan; +} __attribute__((aligned(32))); + +struct gelic_net_descr_chain { + /* we walk from tail to head */ + struct gelic_net_descr *head; + struct gelic_net_descr *tail; +}; + +struct gelic_net_card { + struct net_device *netdev; + /* + * hypervisor requires irq_status should be + * 8 bytes aligned, but u64 member is + * always disposed in that manner + */ + u64 irq_status; + u64 ghiintmask; + + struct ps3_system_bus_device *dev; + u32 vlan_id[GELIC_NET_VLAN_MAX]; + int vlan_index; + + struct gelic_net_descr_chain tx_chain; + struct gelic_net_descr_chain rx_chain; + /* gurad dmac descriptor chain*/ + spinlock_t chain_lock; + + struct net_device_stats netdev_stats; + int rx_csum; + /* guard tx_dma_progress */ + spinlock_t tx_dma_lock; + int tx_dma_progress; + + struct work_struct tx_timeout_task; + atomic_t tx_timeout_task_counter; + wait_queue_head_t waitq; + + struct gelic_net_descr *tx_top, *rx_top; + struct gelic_net_descr descr[0]; +}; + + +extern unsigned long p_to_lp(long pa); + +#endif /* _GELIC_NET_H */ diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index d8766c0e825..8be8be451ad 100755 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -2433,37 +2433,22 @@ static int ql_get_seg_count(struct ql3_adapter *qdev, return -1; } -static void ql_hw_csum_setup(struct sk_buff *skb, +static void ql_hw_csum_setup(const struct sk_buff *skb, struct ob_mac_iocb_req *mac_iocb_ptr) { - struct ethhdr *eth; - struct iphdr *ip = NULL; - u8 offset = ETH_HLEN; + const struct iphdr *ip = ip_hdr(skb); - eth = (struct ethhdr *)(skb->data); + mac_iocb_ptr->ip_hdr_off = skb_network_offset(skb); + mac_iocb_ptr->ip_hdr_len = ip->ihl; - if (eth->h_proto == __constant_htons(ETH_P_IP)) { - ip = (struct iphdr *)&skb->data[ETH_HLEN]; - } else if (eth->h_proto == htons(ETH_P_8021Q) && - ((struct vlan_ethhdr *)skb->data)-> - h_vlan_encapsulated_proto == __constant_htons(ETH_P_IP)) { - ip = (struct iphdr *)&skb->data[VLAN_ETH_HLEN]; - offset = VLAN_ETH_HLEN; - } - - if (ip) { - if (ip->protocol == IPPROTO_TCP) { - mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_TC | + if (ip->protocol == IPPROTO_TCP) { + mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_TC | OB_3032MAC_IOCB_REQ_IC; - mac_iocb_ptr->ip_hdr_off = offset; - mac_iocb_ptr->ip_hdr_len = ip->ihl; - } else if (ip->protocol == IPPROTO_UDP) { - mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_UC | + } else { + mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_UC | OB_3032MAC_IOCB_REQ_IC; - mac_iocb_ptr->ip_hdr_off = offset; - mac_iocb_ptr->ip_hdr_len = ip->ihl; - } } + } /* @@ -4044,7 +4029,7 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev, if (pci_using_dac) ndev->features |= NETIF_F_HIGHDMA; if (qdev->device_id == QL3032_DEVICE_ID) - ndev->features |= (NETIF_F_HW_CSUM | NETIF_F_SG); + ndev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; qdev->mem_map_registers = ioremap_nocache(pci_resource_start(pdev, 1), diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 45876a854f0..982a9010c7a 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1,53 +1,11 @@ /* -========================================================================= - r8169.c: A RealTek RTL-8169 Gigabit Ethernet driver for Linux kernel 2.4.x. - -------------------------------------------------------------------- - - History: - Feb 4 2002 - created initially by ShuChen <shuchen@realtek.com.tw>. - May 20 2002 - Add link status force-mode and TBI mode support. - 2004 - Massive updates. See kernel SCM system for details. -========================================================================= - 1. [DEPRECATED: use ethtool instead] The media can be forced in 5 modes. - Command: 'insmod r8169 media = SET_MEDIA' - Ex: 'insmod r8169 media = 0x04' will force PHY to operate in 100Mpbs Half-duplex. - - SET_MEDIA can be: - _10_Half = 0x01 - _10_Full = 0x02 - _100_Half = 0x04 - _100_Full = 0x08 - _1000_Full = 0x10 - - 2. Support TBI mode. -========================================================================= -VERSION 1.1 <2002/10/4> - - The bit4:0 of MII register 4 is called "selector field", and have to be - 00001b to indicate support of IEEE std 802.3 during NWay process of - exchanging Link Code Word (FLP). - -VERSION 1.2 <2002/11/30> - - - Large style cleanup - - Use ether_crc in stock kernel (linux/crc32.h) - - Copy mc_filter setup code from 8139cp - (includes an optimization, and avoids set_bit use) - -VERSION 1.6LK <2004/04/14> - - - Merge of Realtek's version 1.6 - - Conversion to DMA API - - Suspend/resume - - Endianness - - Misc Rx/Tx bugs - -VERSION 2.2LK <2005/01/25> - - - RX csum, TX csum/SG, TSO - - VLAN - - baby (< 7200) Jumbo frames support - - Merge of Realtek's version 2.2 (new phy) + * r8169.c: RealTek 8169/8168/8101 ethernet driver. + * + * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw> + * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com> + * Copyright (c) a lot of people too. Please respect their work. + * + * See MAINTAINERS file for support contact information. */ #include <linux/module.h> @@ -108,11 +66,6 @@ VERSION 2.2LK <2005/01/25> #define rtl8169_rx_quota(count, quota) count #endif -/* media options */ -#define MAX_UNITS 8 -static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; -static int num_media = 0; - /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ static const int max_interrupt_work = 20; @@ -126,7 +79,7 @@ static const int multicast_filter_limit = 32; #define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ #define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ #define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ +#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ #define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */ #define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ #define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ @@ -151,16 +104,17 @@ static const int multicast_filter_limit = 32; #define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) enum mac_version { - RTL_GIGA_MAC_VER_01 = 0x00, - RTL_GIGA_MAC_VER_02 = 0x01, - RTL_GIGA_MAC_VER_03 = 0x02, - RTL_GIGA_MAC_VER_04 = 0x03, - RTL_GIGA_MAC_VER_05 = 0x04, - RTL_GIGA_MAC_VER_11 = 0x0b, - RTL_GIGA_MAC_VER_12 = 0x0c, - RTL_GIGA_MAC_VER_13 = 0x0d, - RTL_GIGA_MAC_VER_14 = 0x0e, - RTL_GIGA_MAC_VER_15 = 0x0f + RTL_GIGA_MAC_VER_01 = 0x01, // 8169 + RTL_GIGA_MAC_VER_02 = 0x02, // 8169S + RTL_GIGA_MAC_VER_03 = 0x03, // 8110S + RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB + RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd + RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe + RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb + RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be 8168Bf + RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb 8101Ec + RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 + RTL_GIGA_MAC_VER_15 = 0x0f // 8101 }; enum phy_version { @@ -180,11 +134,12 @@ static const struct { u8 mac_version; u32 RxConfigMask; /* Clears the bits supported by this chip */ } rtl_chip_info[] = { - _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), - _R("RTL8169s/8110s", RTL_GIGA_MAC_VER_02, 0xff7e1880), - _R("RTL8169s/8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), - _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), - _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), + _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169 + _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S + _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S + _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB + _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd + _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 @@ -199,20 +154,15 @@ enum cfg_version { RTL_CFG_2 }; -static const struct { - unsigned int region; - unsigned int align; -} rtl_cfg_info[] = { - [RTL_CFG_0] = { 1, NET_IP_ALIGN }, - [RTL_CFG_1] = { 2, NET_IP_ALIGN }, - [RTL_CFG_2] = { 2, 8 } -}; +static void rtl_hw_start_8169(struct net_device *); +static void rtl_hw_start_8168(struct net_device *); +static void rtl_hw_start_8101(struct net_device *); static struct pci_device_id rtl8169_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_2 }, + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, { PCI_DEVICE(0x1259, 0xc107), 0, 0, RTL_CFG_0 }, @@ -230,62 +180,63 @@ static struct { u32 msg_enable; } debug = { -1 }; -enum RTL8169_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - RxMissed = 0x4C, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5C, - PHYAR = 0x60, - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6A, - PHYstatus = 0x6C, - RxMaxSize = 0xDA, - CPlusCmd = 0xE0, - IntrMitigate = 0xE2, - RxDescAddrLow = 0xE4, - RxDescAddrHigh = 0xE8, - EarlyTxThres = 0xEC, - FuncEvent = 0xF0, - FuncEventMask = 0xF4, - FuncPresetState = 0xF8, - FuncForceEvent = 0xFC, +enum rtl_registers { + MAC0 = 0, /* Ethernet hardware address. */ + MAC4 = 4, + MAR0 = 8, /* Multicast filter. */ + CounterAddrLow = 0x10, + CounterAddrHigh = 0x14, + TxDescStartAddrLow = 0x20, + TxDescStartAddrHigh = 0x24, + TxHDescStartAddrLow = 0x28, + TxHDescStartAddrHigh = 0x2c, + FLASH = 0x30, + ERSR = 0x36, + ChipCmd = 0x37, + TxPoll = 0x38, + IntrMask = 0x3c, + IntrStatus = 0x3e, + TxConfig = 0x40, + RxConfig = 0x44, + RxMissed = 0x4c, + Cfg9346 = 0x50, + Config0 = 0x51, + Config1 = 0x52, + Config2 = 0x53, + Config3 = 0x54, + Config4 = 0x55, + Config5 = 0x56, + MultiIntr = 0x5c, + PHYAR = 0x60, + TBICSR = 0x64, + TBI_ANAR = 0x68, + TBI_LPAR = 0x6a, + PHYstatus = 0x6c, + RxMaxSize = 0xda, + CPlusCmd = 0xe0, + IntrMitigate = 0xe2, + RxDescAddrLow = 0xe4, + RxDescAddrHigh = 0xe8, + EarlyTxThres = 0xec, + FuncEvent = 0xf0, + FuncEventMask = 0xf4, + FuncPresetState = 0xf8, + FuncForceEvent = 0xfc, }; -enum RTL8169_register_content { +enum rtl_register_content { /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x80, - RxFIFOOver = 0x40, - LinkChg = 0x20, - RxOverflow = 0x10, - TxErr = 0x08, - TxOK = 0x04, - RxErr = 0x02, - RxOK = 0x01, + SYSErr = 0x8000, + PCSTimeout = 0x4000, + SWInt = 0x0100, + TxDescUnavail = 0x0080, + RxFIFOOver = 0x0040, + LinkChg = 0x0020, + RxOverflow = 0x0010, + TxErr = 0x0008, + TxOK = 0x0004, + RxErr = 0x0002, + RxOK = 0x0001, /* RxStatusDesc */ RxFOVF = (1 << 23), @@ -295,26 +246,31 @@ enum RTL8169_register_content { RxCRC = (1 << 19), /* ChipCmdBits */ - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, + CmdReset = 0x10, + CmdRxEnb = 0x08, + CmdTxEnb = 0x04, + RxBufEmpty = 0x01, + + /* TXPoll register p.5 */ + HPQ = 0x80, /* Poll cmd on the high prio queue */ + NPQ = 0x40, /* Poll cmd on the low prio queue */ + FSWInt = 0x01, /* Forced software interrupt */ /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, + Cfg9346_Lock = 0x00, + Cfg9346_Unlock = 0xc0, /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, + AcceptErr = 0x20, + AcceptRunt = 0x10, + AcceptBroadcast = 0x08, + AcceptMulticast = 0x04, + AcceptMyPhys = 0x02, + AcceptAllPhys = 0x01, /* RxConfigBits */ - RxCfgFIFOShift = 13, - RxCfgDMAShift = 8, + RxCfgFIFOShift = 13, + RxCfgDMAShift = 8, /* TxConfigBits */ TxInterFrameGapShift = 24, @@ -323,6 +279,10 @@ enum RTL8169_register_content { /* Config1 register p.24 */ PMEnable = (1 << 0), /* Power Management Enable */ + /* Config2 register p. 25 */ + PCI_Clock_66MHz = 0x01, + PCI_Clock_33MHz = 0x00, + /* Config3 register p.25 */ MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ @@ -343,36 +303,34 @@ enum RTL8169_register_content { TBINwComplete = 0x01000000, /* CPlusCmd p.31 */ + PktCntrDisable = (1 << 7), // 8168 RxVlan = (1 << 6), RxChkSum = (1 << 5), PCIDAC = (1 << 4), PCIMulRW = (1 << 3), + INTT_0 = 0x0000, // 8168 + INTT_1 = 0x0001, // 8168 + INTT_2 = 0x0002, // 8168 + INTT_3 = 0x0003, // 8168 /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _MediaType */ - _10_Half = 0x01, - _10_Full = 0x02, - _100_Half = 0x04, - _100_Full = 0x08, - _1000_Full = 0x10, + TBI_Enable = 0x80, + TxFlowCtrl = 0x40, + RxFlowCtrl = 0x20, + _1000bpsF = 0x10, + _100bps = 0x08, + _10bps = 0x04, + LinkStatus = 0x02, + FullDup = 0x01, /* _TBICSRBit */ - TBILinkOK = 0x02000000, + TBILinkOK = 0x02000000, /* DumpCounterCommand */ - CounterDump = 0x8, + CounterDump = 0x8, }; -enum _DescStatusBit { +enum desc_status_bit { DescOwn = (1 << 31), /* Descriptor is owned by NIC */ RingEnd = (1 << 30), /* End of descriptor ring */ FirstFrag = (1 << 29), /* First segment of a packet */ @@ -405,15 +363,15 @@ enum _DescStatusBit { #define RsvdMask 0x3fffc000 struct TxDesc { - u32 opts1; - u32 opts2; - u64 addr; + __le32 opts1; + __le32 opts2; + __le64 addr; }; struct RxDesc { - u32 opts1; - u32 opts2; - u64 addr; + __le32 opts1; + __le32 opts2; + __le64 addr; }; struct ring_info { @@ -446,6 +404,8 @@ struct rtl8169_private { unsigned rx_buf_sz; struct timer_list timer; u16 cp_cmd; + u16 intr_event; + u16 napi_event; u16 intr_mask; int phy_auto_nego_reg; int phy_1000_ctrl_reg; @@ -455,6 +415,7 @@ struct rtl8169_private { int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); void (*get_settings)(struct net_device *, struct ethtool_cmd *); void (*phy_reset_enable)(void __iomem *); + void (*hw_start)(struct net_device *); unsigned int (*phy_reset_pending)(void __iomem *); unsigned int (*link_ok)(void __iomem *); struct delayed_work task; @@ -463,8 +424,6 @@ struct rtl8169_private { MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>"); MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver"); -module_param_array(media, int, &num_media, 0); -MODULE_PARM_DESC(media, "force phy operation. Deprecated by ethtool (8)."); module_param(rx_copybreak, int, 0); MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); module_param(use_dac, int, 0); @@ -478,9 +437,9 @@ static int rtl8169_open(struct net_device *dev); static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev); static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance); static int rtl8169_init_ring(struct net_device *dev); -static void rtl8169_hw_start(struct net_device *dev); +static void rtl_hw_start(struct net_device *dev); static int rtl8169_close(struct net_device *dev); -static void rtl8169_set_rx_mode(struct net_device *dev); +static void rtl_set_rx_mode(struct net_device *dev); static void rtl8169_tx_timeout(struct net_device *dev); static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, @@ -493,35 +452,37 @@ static void rtl8169_rx_clear(struct rtl8169_private *tp); static int rtl8169_poll(struct net_device *dev, int *budget); #endif -static const u16 rtl8169_intr_mask = - SYSErr | LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK; -static const u16 rtl8169_napi_event = - RxOK | RxOverflow | RxFIFOOver | TxOK | TxErr; static const unsigned int rtl8169_rx_config = (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); -static void mdio_write(void __iomem *ioaddr, int RegAddr, int value) +static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) { int i; - RTL_W32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value); + RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0xFF) << 16 | value); for (i = 20; i > 0; i--) { - /* Check if the RTL8169 has completed writing to the specified MII register */ + /* + * Check if the RTL8169 has completed writing to the specified + * MII register. + */ if (!(RTL_R32(PHYAR) & 0x80000000)) break; udelay(25); } } -static int mdio_read(void __iomem *ioaddr, int RegAddr) +static int mdio_read(void __iomem *ioaddr, int reg_addr) { int i, value = -1; - RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16); + RTL_W32(PHYAR, 0x0 | (reg_addr & 0xFF) << 16); for (i = 20; i > 0; i--) { - /* Check if the RTL8169 has completed retrieving data from the specified MII register */ + /* + * Check if the RTL8169 has completed retrieving data from + * the specified MII register. + */ if (RTL_R32(PHYAR) & 0x80000000) { value = (int) (RTL_R32(PHYAR) & 0xFFFF); break; @@ -579,7 +540,8 @@ static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) } static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, void __iomem *ioaddr) + struct rtl8169_private *tp, + void __iomem *ioaddr) { unsigned long flags; @@ -596,38 +558,6 @@ static void rtl8169_check_link_status(struct net_device *dev, spin_unlock_irqrestore(&tp->lock, flags); } -static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex) -{ - struct { - u16 speed; - u8 duplex; - u8 autoneg; - u8 media; - } link_settings[] = { - { SPEED_10, DUPLEX_HALF, AUTONEG_DISABLE, _10_Half }, - { SPEED_10, DUPLEX_FULL, AUTONEG_DISABLE, _10_Full }, - { SPEED_100, DUPLEX_HALF, AUTONEG_DISABLE, _100_Half }, - { SPEED_100, DUPLEX_FULL, AUTONEG_DISABLE, _100_Full }, - { SPEED_1000, DUPLEX_FULL, AUTONEG_DISABLE, _1000_Full }, - /* Make TBI happy */ - { SPEED_1000, DUPLEX_FULL, AUTONEG_ENABLE, 0xff } - }, *p; - unsigned char option; - - option = ((idx < MAX_UNITS) && (idx >= 0)) ? media[idx] : 0xff; - - if ((option != 0xff) && !idx && netif_msg_drv(&debug)) - printk(KERN_WARNING PFX "media option is deprecated.\n"); - - for (p = link_settings; p->media != 0xff; p++) { - if (p->media == option) - break; - } - *autoneg = p->autoneg; - *speed = p->speed; - *duplex = p->duplex; -} - static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct rtl8169_private *tp = netdev_priv(dev); @@ -667,7 +597,7 @@ static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; - int i; + unsigned int i; static struct { u32 opt; u16 reg; @@ -886,16 +816,6 @@ static void rtl8169_vlan_rx_register(struct net_device *dev, spin_unlock_irqrestore(&tp->lock, flags); } -static void rtl8169_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - vlan_group_set_device(tp->vlgrp, vid, NULL); - spin_unlock_irqrestore(&tp->lock, flags); -} - static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, struct sk_buff *skb) { @@ -903,8 +823,7 @@ static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, int ret; if (tp->vlgrp && (opts2 & RxVlanTag)) { - rtl8169_rx_hwaccel_skb(skb, tp->vlgrp, - swab16(opts2 & 0xffff)); + rtl8169_rx_hwaccel_skb(skb, tp->vlgrp, swab16(opts2 & 0xffff)); ret = 0; } else ret = -1; @@ -1125,7 +1044,6 @@ static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) } } - static const struct ethtool_ops rtl8169_ethtool_ops = { .get_drvinfo = rtl8169_get_drvinfo, .get_regs_len = rtl8169_get_regs_len, @@ -1151,8 +1069,8 @@ static const struct ethtool_ops rtl8169_ethtool_ops = { .get_perm_addr = ethtool_op_get_perm_addr, }; -static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum, - int bitval) +static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, + int bitnum, int bitval) { int val; @@ -1162,8 +1080,20 @@ static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum mdio_write(ioaddr, reg, val & 0xffff); } -static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *ioaddr) +static void rtl8169_get_mac_version(struct rtl8169_private *tp, + void __iomem *ioaddr) { + /* + * The driver currently handles the 8168Bf and the 8168Be identically + * but they can be identified more specifically through the test below + * if needed: + * + * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be + * + * Same thing for the 8101Eb and the 8101Ec: + * + * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec + */ const struct { u32 mask; int mac_version; @@ -1173,6 +1103,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *io { 0x34000000, RTL_GIGA_MAC_VER_13 }, { 0x30800000, RTL_GIGA_MAC_VER_14 }, { 0x30000000, RTL_GIGA_MAC_VER_11 }, + { 0x98000000, RTL_GIGA_MAC_VER_06 }, { 0x18000000, RTL_GIGA_MAC_VER_05 }, { 0x10000000, RTL_GIGA_MAC_VER_04 }, { 0x04000000, RTL_GIGA_MAC_VER_03 }, @@ -1181,7 +1112,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *io }, *p = mac_info; u32 reg; - reg = RTL_R32(TxConfig) & 0x7c800000; + reg = RTL_R32(TxConfig) & 0xfc800000; while ((reg & p->mask) != p->mask) p++; tp->mac_version = p->mac_version; @@ -1192,7 +1123,8 @@ static void rtl8169_print_mac_version(struct rtl8169_private *tp) dprintk("mac_version = 0x%02x\n", tp->mac_version); } -static void rtl8169_get_phy_version(struct rtl8169_private *tp, void __iomem *ioaddr) +static void rtl8169_get_phy_version(struct rtl8169_private *tp, + void __iomem *ioaddr) { const struct { u16 mask; @@ -1269,7 +1201,7 @@ static void rtl8169_hw_phy_config(struct net_device *dev) 0xbf00 } //w 0 15 0 bf00 } }, *p = phy_magic; - int i; + unsigned int i; rtl8169_print_mac_version(tp); rtl8169_print_phy_version(tp); @@ -1403,7 +1335,7 @@ static void rtl8169_phy_reset(struct net_device *dev, struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; - int i; + unsigned int i; tp->phy_reset_enable(ioaddr); for (i = 0; i < 100; i++) { @@ -1418,21 +1350,16 @@ static void rtl8169_phy_reset(struct net_device *dev, static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; - static int board_idx = -1; - u8 autoneg, duplex; - u16 speed; - - board_idx++; rtl8169_hw_phy_config(dev); dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); RTL_W8(0x82, 0x01); - if (tp->mac_version < RTL_GIGA_MAC_VER_03) { - dprintk("Set PCI Latency=0x40\n"); - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - } + pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); + + if (tp->mac_version <= RTL_GIGA_MAC_VER_06) + pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); if (tp->mac_version == RTL_GIGA_MAC_VER_02) { dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); @@ -1441,16 +1368,52 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 } - rtl8169_link_option(board_idx, &autoneg, &speed, &duplex); - rtl8169_phy_reset(dev, tp); - rtl8169_set_speed(dev, autoneg, speed, duplex); + /* + * rtl8169_set_speed_xmii takes good care of the Fast Ethernet + * only 8101. Don't panic. + */ + rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp)) printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name); } +static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) +{ + void __iomem *ioaddr = tp->mmio_addr; + u32 high; + u32 low; + + low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); + high = addr[4] | (addr[5] << 8); + + spin_lock_irq(&tp->lock); + + RTL_W8(Cfg9346, Cfg9346_Unlock); + RTL_W32(MAC0, low); + RTL_W32(MAC4, high); + RTL_W8(Cfg9346, Cfg9346_Lock); + + spin_unlock_irq(&tp->lock); +} + +static int rtl_set_mac_address(struct net_device *dev, void *p) +{ + struct rtl8169_private *tp = netdev_priv(dev); + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + + rtl_rar_set(tp, dev->dev_addr); + + return 0; +} + static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct rtl8169_private *tp = netdev_priv(dev); @@ -1477,15 +1440,49 @@ static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return -EOPNOTSUPP; } +static const struct rtl_cfg_info { + void (*hw_start)(struct net_device *); + unsigned int region; + unsigned int align; + u16 intr_event; + u16 napi_event; +} rtl_cfg_infos [] = { + [RTL_CFG_0] = { + .hw_start = rtl_hw_start_8169, + .region = 1, + .align = 0, + .intr_event = SYSErr | LinkChg | RxOverflow | + RxFIFOOver | TxErr | TxOK | RxOK | RxErr, + .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow + }, + [RTL_CFG_1] = { + .hw_start = rtl_hw_start_8168, + .region = 2, + .align = 8, + .intr_event = SYSErr | LinkChg | RxOverflow | + TxErr | TxOK | RxOK | RxErr, + .napi_event = TxErr | TxOK | RxOK | RxOverflow + }, + [RTL_CFG_2] = { + .hw_start = rtl_hw_start_8101, + .region = 2, + .align = 8, + .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | + RxFIFOOver | TxErr | TxOK | RxOK | RxErr, + .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow + } +}; + static int __devinit rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - const unsigned int region = rtl_cfg_info[ent->driver_data].region; + const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; + const unsigned int region = cfg->region; struct rtl8169_private *tp; struct net_device *dev; void __iomem *ioaddr; - unsigned int pm_cap; - int i, rc; + unsigned int i; + int rc; if (netif_msg_drv(&debug)) { printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", @@ -1518,20 +1515,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (rc < 0) goto err_out_disable_2; - /* save power state before pci_enable_device overwrites it */ - pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); - if (pm_cap) { - u16 pwr_command, acpi_idle_state; - - pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command); - acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK; - } else { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "PowerManagement capability not found.\n"); - } - } - /* make sure PCI base addr 1 is MMIO */ if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { if (netif_msg_probe(tp)) { @@ -1595,7 +1578,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) RTL_W8(ChipCmd, CmdReset); /* Check that the chip has finished the reset. */ - for (i = 100; i > 0; i--) { + for (i = 0; i < 100; i++) { if ((RTL_R8(ChipCmd) & CmdReset) == 0) break; msleep_interruptible(1); @@ -1657,11 +1640,12 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); dev->stop = rtl8169_close; dev->tx_timeout = rtl8169_tx_timeout; - dev->set_multicast_list = rtl8169_set_rx_mode; + dev->set_multicast_list = rtl_set_rx_mode; dev->watchdog_timeo = RTL8169_TX_TIMEOUT; dev->irq = pdev->irq; dev->base_addr = (unsigned long) ioaddr; dev->change_mtu = rtl8169_change_mtu; + dev->set_mac_address = rtl_set_mac_address; #ifdef CONFIG_R8169_NAPI dev->poll = rtl8169_poll; @@ -1671,7 +1655,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) #ifdef CONFIG_R8169_VLAN dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; dev->vlan_rx_register = rtl8169_vlan_rx_register; - dev->vlan_rx_kill_vid = rtl8169_vlan_rx_kill_vid; #endif #ifdef CONFIG_NET_POLL_CONTROLLER @@ -1681,7 +1664,10 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->intr_mask = 0xffff; tp->pci_dev = pdev; tp->mmio_addr = ioaddr; - tp->align = rtl_cfg_info[ent->driver_data].align; + tp->align = cfg->align; + tp->hw_start = cfg->hw_start; + tp->intr_event = cfg->intr_event; + tp->napi_event = cfg->napi_event; init_timer(&tp->timer); tp->timer.data = (unsigned long) dev; @@ -1696,15 +1682,17 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_drvdata(pdev, dev); if (netif_msg_probe(tp)) { + u32 xid = RTL_R32(TxConfig) & 0x7cf0f8ff; + printk(KERN_INFO "%s: %s at 0x%lx, " "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "IRQ %d\n", + "XID %08x IRQ %d\n", dev->name, rtl_chip_info[tp->chipset].name, dev->base_addr, dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], dev->irq); + dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq); } rtl8169_init_phy(dev, tp); @@ -1725,15 +1713,11 @@ err_out_free_dev_1: goto out; } -static void __devexit -rtl8169_remove_one(struct pci_dev *pdev) +static void __devexit rtl8169_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct rtl8169_private *tp = netdev_priv(dev); - assert(dev != NULL); - assert(tp != NULL); - flush_scheduled_work(); unregister_netdev(dev); @@ -1785,7 +1769,7 @@ static int rtl8169_open(struct net_device *dev) if (retval < 0) goto err_release_ring_2; - rtl8169_hw_start(dev); + rtl_hw_start(dev); rtl8169_request_timer(dev); @@ -1816,7 +1800,7 @@ static void rtl8169_hw_reset(void __iomem *ioaddr) RTL_R8(ChipCmd); } -static void rtl8169_set_rx_tx_config_registers(struct rtl8169_private *tp) +static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; u32 cfg = rtl8169_rx_config; @@ -1829,45 +1813,90 @@ static void rtl8169_set_rx_tx_config_registers(struct rtl8169_private *tp) (InterFrameGap << TxInterFrameGapShift)); } -static void rtl8169_hw_start(struct net_device *dev) +static void rtl_hw_start(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - u16 cmd; - u32 i; + unsigned int i; /* Soft reset the chip. */ RTL_W8(ChipCmd, CmdReset); /* Check that the chip has finished the reset. */ - for (i = 100; i > 0; i--) { + for (i = 0; i < 100; i++) { if ((RTL_R8(ChipCmd) & CmdReset) == 0) break; msleep_interruptible(1); } - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } + tp->hw_start(dev); - if (tp->mac_version == RTL_GIGA_MAC_VER_13) { - pci_write_config_word(pdev, 0x68, 0x00); - pci_write_config_word(pdev, 0x69, 0x08); - } + netif_start_queue(dev); +} - /* Undocumented stuff. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - /* Realtek's r1000_n.c driver uses '&& 0x01' here. Well... */ - if ((RTL_R8(Config2) & 0x07) & 0x01) - RTL_W32(0x7c, 0x0007ffff); - RTL_W32(0x7c, 0x0007ff00); +static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, + void __iomem *ioaddr) +{ + /* + * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh + * register to be written before TxDescAddrLow to work. + * Switching from MMIO to I/O access fixes the issue as well. + */ + RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); + RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_32BIT_MASK); + RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); + RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_32BIT_MASK); +} + +static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) +{ + u16 cmd; - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - cmd = cmd & 0xef; - pci_write_config_word(pdev, PCI_COMMAND, cmd); + cmd = RTL_R16(CPlusCmd); + RTL_W16(CPlusCmd, cmd); + return cmd; +} + +static void rtl_set_rx_max_size(void __iomem *ioaddr) +{ + /* Low hurts. Let's disable the filtering. */ + RTL_W16(RxMaxSize, 16383); +} + +static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) +{ + struct { + u32 mac_version; + u32 clk; + u32 val; + } cfg2_info [] = { + { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd + { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, + { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe + { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } + }, *p = cfg2_info; + unsigned int i; + u32 clk; + + clk = RTL_R8(Config2) & PCI_Clock_66MHz; + for (i = 0; i < ARRAY_SIZE(cfg2_info); i++) { + if ((p->mac_version == mac_version) && (p->clk == clk)) { + RTL_W32(0x7c, p->val); + break; + } + } +} + +static void rtl_hw_start_8169(struct net_device *dev) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; + struct pci_dev *pdev = tp->pci_dev; + + if (tp->mac_version == RTL_GIGA_MAC_VER_05) { + RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); + pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); } RTL_W8(Cfg9346, Cfg9346_Unlock); @@ -1879,19 +1908,11 @@ static void rtl8169_hw_start(struct net_device *dev) RTL_W8(EarlyTxThres, EarlyTxThld); - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, 16383); + rtl_set_rx_max_size(ioaddr); - if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || - (tp->mac_version == RTL_GIGA_MAC_VER_02) || - (tp->mac_version == RTL_GIGA_MAC_VER_03) || - (tp->mac_version == RTL_GIGA_MAC_VER_04)) - rtl8169_set_rx_tx_config_registers(tp); + rtl_set_rx_tx_config_registers(tp); - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - - tp->cp_cmd |= cmd | PCIMulRW; + tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || (tp->mac_version == RTL_GIGA_MAC_VER_03)) { @@ -1902,29 +1923,15 @@ static void rtl8169_hw_start(struct net_device *dev) RTL_W16(CPlusCmd, tp->cp_cmd); + rtl8169_set_magic_reg(ioaddr, tp->mac_version); + /* * Undocumented corner. Supposedly: * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets */ RTL_W16(IntrMitigate, 0x0000); - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr >> 32)); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr & DMA_32BIT_MASK)); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr >> 32)); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr & DMA_32BIT_MASK)); - - if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && - (tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03) && - (tp->mac_version != RTL_GIGA_MAC_VER_04)) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl8169_set_rx_tx_config_registers(tp); - } + rtl_set_rx_tx_desc_registers(tp, ioaddr); RTL_W8(Cfg9346, Cfg9346_Lock); @@ -1933,15 +1940,107 @@ static void rtl8169_hw_start(struct net_device *dev) RTL_W32(RxMissed, 0); - rtl8169_set_rx_mode(dev); + rtl_set_rx_mode(dev); /* no early-rx interrupts */ RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16(IntrMask, rtl8169_intr_mask); + RTL_W16(IntrMask, tp->intr_event); - netif_start_queue(dev); + RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); +} + +static void rtl_hw_start_8168(struct net_device *dev) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; + struct pci_dev *pdev = tp->pci_dev; + u8 ctl; + + RTL_W8(Cfg9346, Cfg9346_Unlock); + + RTL_W8(EarlyTxThres, EarlyTxThld); + + rtl_set_rx_max_size(ioaddr); + + rtl_set_rx_tx_config_registers(tp); + + tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; + + RTL_W16(CPlusCmd, tp->cp_cmd); + + /* Tx performance tweak. */ + pci_read_config_byte(pdev, 0x69, &ctl); + ctl = (ctl & ~0x70) | 0x50; + pci_write_config_byte(pdev, 0x69, ctl); + + RTL_W16(IntrMitigate, 0x5151); + + /* Work around for RxFIFO overflow. */ + if (tp->mac_version == RTL_GIGA_MAC_VER_11) { + tp->intr_event |= RxFIFOOver | PCSTimeout; + tp->intr_event &= ~RxOverflow; + } + + rtl_set_rx_tx_desc_registers(tp, ioaddr); + + RTL_W8(Cfg9346, Cfg9346_Lock); + + RTL_R8(IntrMask); + + RTL_W32(RxMissed, 0); + + rtl_set_rx_mode(dev); + + RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); + + RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); + + RTL_W16(IntrMask, tp->intr_event); +} + +static void rtl_hw_start_8101(struct net_device *dev) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; + struct pci_dev *pdev = tp->pci_dev; + + if (tp->mac_version == RTL_GIGA_MAC_VER_13) { + pci_write_config_word(pdev, 0x68, 0x00); + pci_write_config_word(pdev, 0x69, 0x08); + } + + RTL_W8(Cfg9346, Cfg9346_Unlock); + + RTL_W8(EarlyTxThres, EarlyTxThld); + + rtl_set_rx_max_size(ioaddr); + + tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; + + RTL_W16(CPlusCmd, tp->cp_cmd); + + RTL_W16(IntrMitigate, 0x0000); + + rtl_set_rx_tx_desc_registers(tp, ioaddr); + + RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); + rtl_set_rx_tx_config_registers(tp); + + RTL_W8(Cfg9346, Cfg9346_Lock); + + RTL_R8(IntrMask); + + RTL_W32(RxMissed, 0); + + rtl_set_rx_mode(dev); + + RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); + + RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); + + RTL_W16(IntrMask, tp->intr_event); } static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) @@ -1967,7 +2066,7 @@ static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) netif_poll_enable(dev); - rtl8169_hw_start(dev); + rtl_hw_start(dev); rtl8169_request_timer(dev); @@ -2008,38 +2107,38 @@ static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, rtl8169_mark_to_asic(desc, rx_buf_sz); } -static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff, - struct RxDesc *desc, int rx_buf_sz, - unsigned int align) +static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, + struct net_device *dev, + struct RxDesc *desc, int rx_buf_sz, + unsigned int align) { struct sk_buff *skb; dma_addr_t mapping; - int ret = 0; + unsigned int pad; + + pad = align ? align : NET_IP_ALIGN; - skb = dev_alloc_skb(rx_buf_sz + align); + skb = netdev_alloc_skb(dev, rx_buf_sz + pad); if (!skb) goto err_out; - skb_reserve(skb, (align - 1) & (unsigned long)skb->data); - *sk_buff = skb; + skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); mapping = pci_map_single(pdev, skb->data, rx_buf_sz, PCI_DMA_FROMDEVICE); rtl8169_map_to_asic(desc, mapping, rx_buf_sz); - out: - return ret; + return skb; err_out: - ret = -ENOMEM; rtl8169_make_unusable_by_asic(desc); goto out; } static void rtl8169_rx_clear(struct rtl8169_private *tp) { - int i; + unsigned int i; for (i = 0; i < NUM_RX_DESC; i++) { if (tp->Rx_skbuff[i]) { @@ -2054,16 +2153,22 @@ static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, { u32 cur; - for (cur = start; end - cur > 0; cur++) { - int ret, i = cur % NUM_RX_DESC; + for (cur = start; end - cur != 0; cur++) { + struct sk_buff *skb; + unsigned int i = cur % NUM_RX_DESC; + + WARN_ON((s32)(end - cur) < 0); if (tp->Rx_skbuff[i]) continue; - ret = rtl8169_alloc_rx_skb(tp->pci_dev, tp->Rx_skbuff + i, - tp->RxDescArray + i, tp->rx_buf_sz, tp->align); - if (ret < 0) + skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, + tp->RxDescArray + i, + tp->rx_buf_sz, tp->align); + if (!skb) break; + + tp->Rx_skbuff[i] = skb; } return cur - start; } @@ -2175,14 +2280,9 @@ static void rtl8169_reinit_task(struct work_struct *work) ret = rtl8169_open(dev); if (unlikely(ret < 0)) { - if (net_ratelimit()) { - struct rtl8169_private *tp = netdev_priv(dev); - - if (netif_msg_drv(tp)) { - printk(PFX KERN_ERR - "%s: reinit failure (status = %d)." - " Rescheduling.\n", dev->name, ret); - } + if (net_ratelimit() && netif_msg_drv(tp)) { + printk(PFX KERN_ERR "%s: reinit failure (status = %d)." + " Rescheduling.\n", dev->name, ret); } rtl8169_schedule_work(dev, rtl8169_reinit_task); } @@ -2209,16 +2309,12 @@ static void rtl8169_reset_task(struct work_struct *work) if (tp->dirty_rx == tp->cur_rx) { rtl8169_init_ring_indexes(tp); - rtl8169_hw_start(dev); + rtl_hw_start(dev); netif_wake_queue(dev); } else { - if (net_ratelimit()) { - struct rtl8169_private *tp = netdev_priv(dev); - - if (netif_msg_intr(tp)) { - printk(PFX KERN_EMERG - "%s: Rx buffers shortage\n", dev->name); - } + if (net_ratelimit() && netif_msg_intr(tp)) { + printk(PFX KERN_EMERG "%s: Rx buffers shortage\n", + dev->name); } rtl8169_schedule_work(dev, rtl8169_reset_task); } @@ -2355,7 +2451,7 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) smp_wmb(); - RTL_W8(TxPoll, 0x40); /* set polling bit */ + RTL_W8(TxPoll, NPQ); /* set polling bit */ if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { netif_stop_queue(dev); @@ -2425,16 +2521,12 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev) rtl8169_schedule_work(dev, rtl8169_reinit_task); } -static void -rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp, - void __iomem *ioaddr) +static void rtl8169_tx_interrupt(struct net_device *dev, + struct rtl8169_private *tp, + void __iomem *ioaddr) { unsigned int dirty_tx, tx_left; - assert(dev != NULL); - assert(tp != NULL); - assert(ioaddr != NULL); - dirty_tx = tp->dirty_tx; smp_rmb(); tx_left = tp->cur_tx - dirty_tx; @@ -2491,38 +2583,37 @@ static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) skb->ip_summed = CHECKSUM_NONE; } -static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size, - struct RxDesc *desc, int rx_buf_sz, - unsigned int align) +static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, + struct rtl8169_private *tp, int pkt_size, + dma_addr_t addr) { - int ret = -1; + struct sk_buff *skb; + bool done = false; - if (pkt_size < rx_copybreak) { - struct sk_buff *skb; + if (pkt_size >= rx_copybreak) + goto out; - skb = dev_alloc_skb(pkt_size + align); - if (skb) { - skb_reserve(skb, (align - 1) & (unsigned long)skb->data); - eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0); - *sk_buff = skb; - rtl8169_mark_to_asic(desc, rx_buf_sz); - ret = 0; - } - } - return ret; + skb = netdev_alloc_skb(tp->dev, pkt_size + NET_IP_ALIGN); + if (!skb) + goto out; + + pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size, + PCI_DMA_FROMDEVICE); + skb_reserve(skb, NET_IP_ALIGN); + skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); + *sk_buff = skb; + done = true; +out: + return done; } -static int -rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, - void __iomem *ioaddr) +static int rtl8169_rx_interrupt(struct net_device *dev, + struct rtl8169_private *tp, + void __iomem *ioaddr) { unsigned int cur_rx, rx_left; unsigned int delta, count; - assert(dev != NULL); - assert(tp != NULL); - assert(ioaddr != NULL); - cur_rx = tp->cur_rx; rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; rx_left = rtl8169_rx_quota(rx_left, (u32) dev->quota); @@ -2555,9 +2646,9 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, rtl8169_mark_to_asic(desc, tp->rx_buf_sz); } else { struct sk_buff *skb = tp->Rx_skbuff[entry]; + dma_addr_t addr = le64_to_cpu(desc->addr); int pkt_size = (status & 0x00001FFF) - 4; - void (*pci_action)(struct pci_dev *, dma_addr_t, - size_t, int) = pci_dma_sync_single_for_device; + struct pci_dev *pdev = tp->pci_dev; /* * The driver does not support incoming fragmented @@ -2573,19 +2664,16 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, rtl8169_rx_csum(skb, desc); - pci_dma_sync_single_for_cpu(tp->pci_dev, - le64_to_cpu(desc->addr), tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - - if (rtl8169_try_rx_copy(&skb, pkt_size, desc, - tp->rx_buf_sz, tp->align)) { - pci_action = pci_unmap_single; + if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { + pci_dma_sync_single_for_device(pdev, addr, + pkt_size, PCI_DMA_FROMDEVICE); + rtl8169_mark_to_asic(desc, tp->rx_buf_sz); + } else { + pci_unmap_single(pdev, addr, pkt_size, + PCI_DMA_FROMDEVICE); tp->Rx_skbuff[entry] = NULL; } - pci_action(tp->pci_dev, le64_to_cpu(desc->addr), - tp->rx_buf_sz, PCI_DMA_FROMDEVICE); - skb_put(skb, pkt_size); skb->protocol = eth_type_trans(skb, dev); @@ -2596,6 +2684,13 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, tp->stats.rx_bytes += pkt_size; tp->stats.rx_packets++; } + + /* Work around for AMD plateform. */ + if ((desc->opts2 & 0xfffe000) && + (tp->mac_version == RTL_GIGA_MAC_VER_05)) { + desc->opts2 = 0; + cur_rx++; + } } count = cur_rx - tp->cur_rx; @@ -2619,11 +2714,9 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, return count; } -/* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ -static irqreturn_t -rtl8169_interrupt(int irq, void *dev_instance) +static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) { - struct net_device *dev = (struct net_device *) dev_instance; + struct net_device *dev = dev_instance; struct rtl8169_private *tp = netdev_priv(dev); int boguscnt = max_interrupt_work; void __iomem *ioaddr = tp->mmio_addr; @@ -2648,8 +2741,16 @@ rtl8169_interrupt(int irq, void *dev_instance) RTL_W16(IntrStatus, (status & RxFIFOOver) ? (status | RxOverflow) : status); - if (!(status & rtl8169_intr_mask)) + if (!(status & tp->intr_event)) + break; + + /* Work around for rx fifo overflow */ + if (unlikely(status & RxFIFOOver) && + (tp->mac_version == RTL_GIGA_MAC_VER_11)) { + netif_stop_queue(dev); + rtl8169_tx_timeout(dev); break; + } if (unlikely(status & SYSErr)) { rtl8169_pcierr_interrupt(dev); @@ -2660,8 +2761,8 @@ rtl8169_interrupt(int irq, void *dev_instance) rtl8169_check_link_status(dev, tp, ioaddr); #ifdef CONFIG_R8169_NAPI - RTL_W16(IntrMask, rtl8169_intr_mask & ~rtl8169_napi_event); - tp->intr_mask = ~rtl8169_napi_event; + RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); + tp->intr_mask = ~tp->napi_event; if (likely(netif_rx_schedule_prep(dev))) __netif_rx_schedule(dev); @@ -2672,9 +2773,9 @@ rtl8169_interrupt(int irq, void *dev_instance) break; #else /* Rx interrupt */ - if (status & (RxOK | RxOverflow | RxFIFOOver)) { + if (status & (RxOK | RxOverflow | RxFIFOOver)) rtl8169_rx_interrupt(dev, tp, ioaddr); - } + /* Tx interrupt */ if (status & (TxOK | TxErr)) rtl8169_tx_interrupt(dev, tp, ioaddr); @@ -2718,7 +2819,7 @@ static int rtl8169_poll(struct net_device *dev, int *budget) * write is safe - FR */ smp_wmb(); - RTL_W16(IntrMask, rtl8169_intr_mask); + RTL_W16(IntrMask, tp->intr_event); } return (work_done >= work_to_do); @@ -2800,14 +2901,13 @@ static int rtl8169_close(struct net_device *dev) return 0; } -static void -rtl8169_set_rx_mode(struct net_device *dev) +static void rtl_set_rx_mode(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; unsigned long flags; u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; + int rx_mode; u32 tmp = 0; if (dev->flags & IFF_PROMISC) { @@ -2827,6 +2927,8 @@ rtl8169_set_rx_mode(struct net_device *dev) mc_filter[1] = mc_filter[0] = 0xffffffff; } else { struct dev_mc_list *mclist; + unsigned int i; + rx_mode = AcceptBroadcast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0; for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; @@ -2851,10 +2953,11 @@ rtl8169_set_rx_mode(struct net_device *dev) mc_filter[1] = 0xffffffff; } - RTL_W32(RxConfig, tmp); RTL_W32(MAR0 + 0, mc_filter[0]); RTL_W32(MAR0 + 4, mc_filter[1]); + RTL_W32(RxConfig, tmp); + spin_unlock_irqrestore(&tp->lock, flags); } @@ -2942,14 +3045,12 @@ static struct pci_driver rtl8169_pci_driver = { #endif }; -static int __init -rtl8169_init_module(void) +static int __init rtl8169_init_module(void) { return pci_register_driver(&rtl8169_pci_driver); } -static void __exit -rtl8169_cleanup_module(void) +static void __exit rtl8169_cleanup_module(void) { pci_unregister_driver(&rtl8169_pci_driver); } diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c index 25c73d47daa..5c2e41fac6d 100644 --- a/drivers/net/rrunner.c +++ b/drivers/net/rrunner.c @@ -516,7 +516,7 @@ static unsigned int write_eeprom(struct rr_private *rrpriv, } -static int __init rr_init(struct net_device *dev) +static int __devinit rr_init(struct net_device *dev) { struct rr_private *rrpriv; struct rr_regs __iomem *regs; diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index e3e6d410d72..58bbfdd4f90 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -340,17 +340,6 @@ static void s2io_vlan_rx_register(struct net_device *dev, /* A flag indicating whether 'RX_PA_CFG_STRIP_VLAN_TAG' bit is set or not */ static int vlan_strip_flag; -/* Unregister the vlan */ -static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid) -{ - struct s2io_nic *nic = dev->priv; - unsigned long flags; - - spin_lock_irqsave(&nic->tx_lock, flags); - vlan_group_set_device(nic->vlgrp, vid, NULL); - spin_unlock_irqrestore(&nic->tx_lock, flags); -} - /* * Constants to be programmed into the Xena's registers, to configure * the XAUI. @@ -480,11 +469,18 @@ static struct pci_device_id s2io_tbl[] __devinitdata = { MODULE_DEVICE_TABLE(pci, s2io_tbl); +static struct pci_error_handlers s2io_err_handler = { + .error_detected = s2io_io_error_detected, + .slot_reset = s2io_io_slot_reset, + .resume = s2io_io_resume, +}; + static struct pci_driver s2io_driver = { .name = "S2IO", .id_table = s2io_tbl, .probe = s2io_init_nic, .remove = __devexit_p(s2io_rem_nic), + .err_handler = &s2io_err_handler, }; /* A simplifier macro used both by init and free shared_mem Fns(). */ @@ -1139,7 +1135,7 @@ static int init_nic(struct s2io_nic *nic) * SXE-008 TRANSMIT DMA ARBITRATION ISSUE. */ if ((nic->device_type == XFRAME_I_DEVICE) && - (get_xena_rev_id(nic->pdev) < 4)) + (nic->pdev->revision < 4)) writeq(PCC_ENABLE_FOUR, &bar0->pcc_enable); val64 = readq(&bar0->tx_fifo_partition_0); @@ -1877,7 +1873,7 @@ static int verify_pcc_quiescent(struct s2io_nic *sp, int flag) herc = (sp->device_type == XFRAME_II_DEVICE); if (flag == FALSE) { - if ((!herc && (get_xena_rev_id(sp->pdev) >= 4)) || herc) { + if ((!herc && (sp->pdev->revision >= 4)) || herc) { if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE)) ret = 1; } else { @@ -1885,7 +1881,7 @@ static int verify_pcc_quiescent(struct s2io_nic *sp, int flag) ret = 1; } } else { - if ((!herc && (get_xena_rev_id(sp->pdev) >= 4)) || herc) { + if ((!herc && (sp->pdev->revision >= 4)) || herc) { if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) == ADAPTER_STATUS_RMAC_PCC_IDLE)) ret = 1; @@ -2700,6 +2696,9 @@ static void s2io_netpoll(struct net_device *dev) u64 val64 = 0xFFFFFFFFFFFFFFFFULL; int i; + if (pci_channel_offline(nic->pdev)) + return; + disable_irq(dev->irq); atomic_inc(&nic->isr_cnt); @@ -2879,6 +2878,7 @@ static void tx_intr_handler(struct fifo_info *fifo_data) struct tx_curr_get_info get_info, put_info; struct sk_buff *skb; struct TxD *txdlp; + u8 err_mask; get_info = fifo_data->tx_curr_get_info; memcpy(&put_info, &fifo_data->tx_curr_put_info, sizeof(put_info)); @@ -2897,8 +2897,8 @@ static void tx_intr_handler(struct fifo_info *fifo_data) } /* update t_code statistics */ - err >>= 48; - switch(err) { + err_mask = err >> 48; + switch(err_mask) { case 2: nic->mac_control.stats_info->sw_stat. tx_buf_abort_cnt++; @@ -3225,6 +3225,8 @@ static void alarm_intr_handler(struct s2io_nic *nic) int i; if (atomic_read(&nic->card_state) == CARD_DOWN) return; + if (pci_channel_offline(nic->pdev)) + return; nic->mac_control.stats_info->sw_stat.ring_full_cnt = 0; /* Handling the XPAK counters update */ if(nic->mac_control.stats_info->xpak_stat.xpak_timer_count < 72000) { @@ -3968,7 +3970,6 @@ static int s2io_close(struct net_device *dev) /* Reset card, kill tasklet and free Tx and Rx buffers. */ s2io_card_down(sp); - sp->device_close_flag = TRUE; /* Device is shut down. */ return 0; } @@ -4324,6 +4325,10 @@ static irqreturn_t s2io_isr(int irq, void *dev_id) struct mac_info *mac_control; struct config_param *config; + /* Pretend we handled any irq's from a disconnected card */ + if (pci_channel_offline(sp->pdev)) + return IRQ_NONE; + atomic_inc(&sp->isr_cnt); mac_control = &sp->mac_control; config = &sp->config; @@ -6579,7 +6584,7 @@ static void s2io_rem_isr(struct s2io_nic * sp) } while(cnt < 5); } -static void s2io_card_down(struct s2io_nic * sp) +static void do_s2io_card_down(struct s2io_nic * sp, int do_io) { int cnt = 0; struct XENA_dev_config __iomem *bar0 = sp->bar0; @@ -6594,7 +6599,8 @@ static void s2io_card_down(struct s2io_nic * sp) atomic_set(&sp->card_state, CARD_DOWN); /* disable Tx and Rx traffic on the NIC */ - stop_nic(sp); + if (do_io) + stop_nic(sp); s2io_rem_isr(sp); @@ -6602,7 +6608,7 @@ static void s2io_card_down(struct s2io_nic * sp) tasklet_kill(&sp->task); /* Check if the device is Quiescent and then Reset the NIC */ - do { + while(do_io) { /* As per the HW requirement we need to replenish the * receive buffer to avoid the ring bump. Since there is * no intention of processing the Rx frame at this pointwe are @@ -6627,8 +6633,9 @@ static void s2io_card_down(struct s2io_nic * sp) (unsigned long long) val64); break; } - } while (1); - s2io_reset(sp); + } + if (do_io) + s2io_reset(sp); spin_lock_irqsave(&sp->tx_lock, flags); /* Free all Tx buffers */ @@ -6643,6 +6650,11 @@ static void s2io_card_down(struct s2io_nic * sp) clear_bit(0, &(sp->link_state)); } +static void s2io_card_down(struct s2io_nic * sp) +{ + do_s2io_card_down(sp, 1); +} + static int s2io_card_up(struct s2io_nic * sp) { int i, ret = 0; @@ -6816,6 +6828,7 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) u16 l3_csum, l4_csum; unsigned long long err = rxdp->Control_1 & RXD_T_CODE; struct lro *lro; + u8 err_mask; skb->dev = dev; @@ -6824,8 +6837,8 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) if (err & 0x1) { sp->mac_control.stats_info->sw_stat.parity_err_cnt++; } - err >>= 48; - switch(err) { + err_mask = err >> 48; + switch(err_mask) { case 1: sp->mac_control.stats_info->sw_stat. rx_parity_err_cnt++; @@ -6878,9 +6891,9 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) * Note that in this case, since checksum will be incorrect, * stack will validate the same. */ - if (err != 0x5) { - DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%llx\n", - dev->name, err); + if (err_mask != 0x5) { + DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%x\n", + dev->name, err_mask); sp->stats.rx_crc_errors++; sp->mac_control.stats_info->sw_stat.mem_freed += skb->truesize; @@ -7063,23 +7076,6 @@ static void s2io_link(struct s2io_nic * sp, int link) } /** - * get_xena_rev_id - to identify revision ID of xena. - * @pdev : PCI Dev structure - * Description: - * Function to identify the Revision ID of xena. - * Return value: - * returns the revision ID of the device. - */ - -static int get_xena_rev_id(struct pci_dev *pdev) -{ - u8 id = 0; - int ret; - ret = pci_read_config_byte(pdev, PCI_REVISION_ID, (u8 *) & id); - return id; -} - -/** * s2io_init_pci -Initialization of PCI and PCI-X configuration registers . * @sp : private member of the device structure, which is a pointer to the * s2io_nic structure. @@ -7412,7 +7408,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; dev->vlan_rx_register = s2io_vlan_rx_register; - dev->vlan_rx_kill_vid = (void *)s2io_vlan_rx_kill_vid; /* * will use eth_mac_addr() for dev->set_mac_address @@ -7538,7 +7533,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) s2io_vpd_read(sp); DBG_PRINT(ERR_DBG, "Copyright(c) 2002-2007 Neterion Inc.\n"); DBG_PRINT(ERR_DBG, "%s: Neterion %s (rev %d)\n",dev->name, - sp->product_name, get_xena_rev_id(sp->pdev)); + sp->product_name, pdev->revision); DBG_PRINT(ERR_DBG, "%s: Driver version %s\n", dev->name, s2io_driver_version); DBG_PRINT(ERR_DBG, "%s: MAC ADDR: " @@ -8020,3 +8015,85 @@ static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro, sp->mac_control.stats_info->sw_stat.clubbed_frms_cnt++; return; } + +/** + * s2io_io_error_detected - called when PCI error is detected + * @pdev: Pointer to PCI device + * @state: The current pci connection state + * + * This function is called after a PCI bus error affecting + * this device has been detected. + */ +static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct s2io_nic *sp = netdev->priv; + + netif_device_detach(netdev); + + if (netif_running(netdev)) { + /* Bring down the card, while avoiding PCI I/O */ + do_s2io_card_down(sp, 0); + } + pci_disable_device(pdev); + + return PCI_ERS_RESULT_NEED_RESET; +} + +/** + * s2io_io_slot_reset - called after the pci bus has been reset. + * @pdev: Pointer to PCI device + * + * Restart the card from scratch, as if from a cold-boot. + * At this point, the card has exprienced a hard reset, + * followed by fixups by BIOS, and has its config space + * set up identically to what it was at cold boot. + */ +static pci_ers_result_t s2io_io_slot_reset(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct s2io_nic *sp = netdev->priv; + + if (pci_enable_device(pdev)) { + printk(KERN_ERR "s2io: " + "Cannot re-enable PCI device after reset.\n"); + return PCI_ERS_RESULT_DISCONNECT; + } + + pci_set_master(pdev); + s2io_reset(sp); + + return PCI_ERS_RESULT_RECOVERED; +} + +/** + * s2io_io_resume - called when traffic can start flowing again. + * @pdev: Pointer to PCI device + * + * This callback is called when the error recovery driver tells + * us that its OK to resume normal operation. + */ +static void s2io_io_resume(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct s2io_nic *sp = netdev->priv; + + if (netif_running(netdev)) { + if (s2io_card_up(sp)) { + printk(KERN_ERR "s2io: " + "Can't bring device back up after reset.\n"); + return; + } + + if (s2io_set_mac_addr(netdev, netdev->dev_addr) == FAILURE) { + s2io_card_down(sp); + printk(KERN_ERR "s2io: " + "Can't resetore mac addr after reset.\n"); + return; + } + } + + netif_device_attach(netdev); + netif_wake_queue(netdev); +} diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index 54baa0b8ec7..3887fe63a90 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -794,7 +794,6 @@ struct s2io_nic { struct net_device_stats stats; int high_dma_flag; - int device_close_flag; int device_enabled_once; char name[60]; @@ -1034,7 +1033,6 @@ static void s2io_set_link(struct work_struct *work); static int s2io_set_swapper(struct s2io_nic * sp); static void s2io_card_down(struct s2io_nic *nic); static int s2io_card_up(struct s2io_nic *nic); -static int get_xena_rev_id(struct pci_dev *pdev); static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit, int bit_state); static int s2io_add_isr(struct s2io_nic * sp); @@ -1052,6 +1050,11 @@ static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro, struct sk_buff *skb, u32 tcp_len); static int rts_ds_steer(struct s2io_nic *nic, u8 ds_codepoint, u8 ring); +static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev, + pci_channel_state_t state); +static pci_ers_result_t s2io_io_slot_reset(struct pci_dev *pdev); +static void s2io_io_resume(struct pci_dev *pdev); + #define s2io_tcp_mss(skb) skb_shinfo(skb)->gso_size #define s2io_udp_mss(skb) skb_shinfo(skb)->gso_size #define s2io_offload_type(skb) skb_shinfo(skb)->gso_type diff --git a/drivers/net/saa9730.c b/drivers/net/saa9730.c index ad94358ece8..451486b32f2 100644 --- a/drivers/net/saa9730.c +++ b/drivers/net/saa9730.c @@ -690,9 +690,9 @@ static int lan_saa9730_rx(struct net_device *dev) lp->stats.rx_packets++; skb_reserve(skb, 2); /* 16 byte align */ skb_put(skb, len); /* make room */ - eth_copy_and_sum(skb, + skb_copy_to_linear_data(skb, (unsigned char *) pData, - len, 0); + len); skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); dev->last_rx = jiffies; diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index 132e2148b21..e7fdcf15b5a 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -1159,7 +1159,7 @@ static void sbmac_netpoll(struct net_device *netdev) __raw_writeq(0, sc->sbm_imr); - sbmac_intr(irq, netdev, NULL); + sbmac_intr(irq, netdev); #ifdef CONFIG_SBMAC_COALESCE __raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) | diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c index 2106becf699..384b4685e97 100644 --- a/drivers/net/sgiseeq.c +++ b/drivers/net/sgiseeq.c @@ -320,7 +320,7 @@ static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp skb_put(skb, len); /* Copy out of kseg1 to avoid silly cache flush. */ - eth_copy_and_sum(skb, pkt_pointer + 2, len, 0); + skb_copy_to_linear_data(skb, pkt_pointer + 2, len); skb->protocol = eth_type_trans(skb, dev); /* We don't want to receive our own packets */ diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index bc8de48da31..ec2ad9f0efa 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -548,7 +548,7 @@ static inline int sis190_try_rx_copy(struct sk_buff **sk_buff, int pkt_size, skb = dev_alloc_skb(pkt_size + NET_IP_ALIGN); if (skb) { skb_reserve(skb, NET_IP_ALIGN); - eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0); + skb_copy_to_linear_data(skb, sk_buff[0]->data, pkt_size); *sk_buff = skb; sis190_give_to_asic(desc, rx_buf_sz); ret = 0; diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 2cb2e156c75..7c6e4808399 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -573,7 +573,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev, * return error if it failed to found. */ -static int __init sis900_mii_probe(struct net_device * net_dev) +static int __devinit sis900_mii_probe(struct net_device * net_dev) { struct sis900_private * sis_priv = net_dev->priv; const char *dev_name = pci_name(sis_priv->pci_dev); diff --git a/drivers/net/sk98lin/Makefile b/drivers/net/sk98lin/Makefile deleted file mode 100644 index afd900d5d73..00000000000 --- a/drivers/net/sk98lin/Makefile +++ /dev/null @@ -1,87 +0,0 @@ -# -# Makefile for the SysKonnect SK-98xx device driver. -# - - -# -# Standalone driver params -# SKPARAM += -DSK_KERNEL_24 -# SKPARAM += -DSK_KERNEL_24_26 -# SKPARAM += -DSK_KERNEL_26 -# SKPARAM += -DSK_KERNEL_22_24 - -obj-$(CONFIG_SK98LIN) += sk98lin.o -sk98lin-objs := \ - skge.o \ - skethtool.o \ - skdim.o \ - skaddr.o \ - skgehwt.o \ - skgeinit.o \ - skgepnmi.o \ - skgesirq.o \ - ski2c.o \ - sklm80.o \ - skqueue.o \ - skrlmt.o \ - sktimer.o \ - skvpd.o \ - skxmac2.o - -# DBGDEF = \ -# -DDEBUG - -ifdef DEBUG -DBGDEF += \ --DSK_DEBUG_CHKMOD=0x00000000L \ --DSK_DEBUG_CHKCAT=0x00000000L -endif - - -# **** possible debug modules for SK_DEBUG_CHKMOD ***************** -# SK_DBGMOD_MERR 0x00000001L /* general module error indication */ -# SK_DBGMOD_HWM 0x00000002L /* Hardware init module */ -# SK_DBGMOD_RLMT 0x00000004L /* RLMT module */ -# SK_DBGMOD_VPD 0x00000008L /* VPD module */ -# SK_DBGMOD_I2C 0x00000010L /* I2C module */ -# SK_DBGMOD_PNMI 0x00000020L /* PNMI module */ -# SK_DBGMOD_CSUM 0x00000040L /* CSUM module */ -# SK_DBGMOD_ADDR 0x00000080L /* ADDR module */ -# SK_DBGMOD_DRV 0x00010000L /* DRV module */ - -# **** possible debug categories for SK_DEBUG_CHKCAT ************** -# *** common modules *** -# SK_DBGCAT_INIT 0x00000001L module/driver initialization -# SK_DBGCAT_CTRL 0x00000002L controlling: add/rmv MCA/MAC and other controls (IOCTL) -# SK_DBGCAT_ERR 0x00000004L error handling paths -# SK_DBGCAT_TX 0x00000008L transmit path -# SK_DBGCAT_RX 0x00000010L receive path -# SK_DBGCAT_IRQ 0x00000020L general IRQ handling -# SK_DBGCAT_QUEUE 0x00000040L any queue management -# SK_DBGCAT_DUMP 0x00000080L large data output e.g. hex dump -# SK_DBGCAT_FATAL 0x00000100L large data output e.g. hex dump - -# *** driver (file skge.c) *** -# SK_DBGCAT_DRV_ENTRY 0x00010000 entry points -# SK_DBGCAT_DRV_??? 0x00020000 not used -# SK_DBGCAT_DRV_MCA 0x00040000 multicast -# SK_DBGCAT_DRV_TX_PROGRESS 0x00080000 tx path -# SK_DBGCAT_DRV_RX_PROGRESS 0x00100000 rx path -# SK_DBGCAT_DRV_PROGRESS 0x00200000 general runtime -# SK_DBGCAT_DRV_??? 0x00400000 not used -# SK_DBGCAT_DRV_PROM 0x00800000 promiscuous mode -# SK_DBGCAT_DRV_TX_FRAME 0x01000000 display tx frames -# SK_DBGCAT_DRV_ERROR 0x02000000 error conditions -# SK_DBGCAT_DRV_INT_SRC 0x04000000 interrupts sources -# SK_DBGCAT_DRV_EVENT 0x08000000 driver events - -EXTRA_CFLAGS += -Idrivers/net/sk98lin -DSK_DIAG_SUPPORT -DGENESIS -DYUKON $(DBGDEF) $(SKPARAM) - -clean: - rm -f core *.o *.a *.s - - - - - - diff --git a/drivers/net/sk98lin/h/lm80.h b/drivers/net/sk98lin/h/lm80.h deleted file mode 100644 index 4e2dbbf7800..00000000000 --- a/drivers/net/sk98lin/h/lm80.h +++ /dev/null @@ -1,179 +0,0 @@ -/****************************************************************************** - * - * Name: lm80.h - * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.6 $ - * Date: $Date: 2003/05/13 17:26:52 $ - * Purpose: Contains all defines for the LM80 Chip - * (National Semiconductor). - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#ifndef __INC_LM80_H -#define __INC_LM80_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* defines ********************************************************************/ - -/* - * LM80 register definition - * - * All registers are 8 bit wide - */ -#define LM80_CFG 0x00 /* Configuration Register */ -#define LM80_ISRC_1 0x01 /* Interrupt Status Register 1 */ -#define LM80_ISRC_2 0x02 /* Interrupt Status Register 2 */ -#define LM80_IMSK_1 0x03 /* Interrupt Mask Register 1 */ -#define LM80_IMSK_2 0x04 /* Interrupt Mask Register 2 */ -#define LM80_FAN_CTRL 0x05 /* Fan Devisor/RST#/OS# Register */ -#define LM80_TEMP_CTRL 0x06 /* OS# Config, Temp Res. Reg */ - /* 0x07 - 0x1f reserved */ - /* current values */ -#define LM80_VT0_IN 0x20 /* current Voltage 0 value */ -#define LM80_VT1_IN 0x21 /* current Voltage 1 value */ -#define LM80_VT2_IN 0x22 /* current Voltage 2 value */ -#define LM80_VT3_IN 0x23 /* current Voltage 3 value */ -#define LM80_VT4_IN 0x24 /* current Voltage 4 value */ -#define LM80_VT5_IN 0x25 /* current Voltage 5 value */ -#define LM80_VT6_IN 0x26 /* current Voltage 6 value */ -#define LM80_TEMP_IN 0x27 /* current Temperature value */ -#define LM80_FAN1_IN 0x28 /* current Fan 1 count */ -#define LM80_FAN2_IN 0x29 /* current Fan 2 count */ - /* limit values */ -#define LM80_VT0_HIGH_LIM 0x2a /* high limit val for Voltage 0 */ -#define LM80_VT0_LOW_LIM 0x2b /* low limit val for Voltage 0 */ -#define LM80_VT1_HIGH_LIM 0x2c /* high limit val for Voltage 1 */ -#define LM80_VT1_LOW_LIM 0x2d /* low limit val for Voltage 1 */ -#define LM80_VT2_HIGH_LIM 0x2e /* high limit val for Voltage 2 */ -#define LM80_VT2_LOW_LIM 0x2f /* low limit val for Voltage 2 */ -#define LM80_VT3_HIGH_LIM 0x30 /* high limit val for Voltage 3 */ -#define LM80_VT3_LOW_LIM 0x31 /* low limit val for Voltage 3 */ -#define LM80_VT4_HIGH_LIM 0x32 /* high limit val for Voltage 4 */ -#define LM80_VT4_LOW_LIM 0x33 /* low limit val for Voltage 4 */ -#define LM80_VT5_HIGH_LIM 0x34 /* high limit val for Voltage 5 */ -#define LM80_VT5_LOW_LIM 0x35 /* low limit val for Voltage 5 */ -#define LM80_VT6_HIGH_LIM 0x36 /* high limit val for Voltage 6 */ -#define LM80_VT6_LOW_LIM 0x37 /* low limit val for Voltage 6 */ -#define LM80_THOT_LIM_UP 0x38 /* hot temperature limit (high) */ -#define LM80_THOT_LIM_LO 0x39 /* hot temperature limit (low) */ -#define LM80_TOS_LIM_UP 0x3a /* OS temperature limit (high) */ -#define LM80_TOS_LIM_LO 0x3b /* OS temperature limit (low) */ -#define LM80_FAN1_COUNT_LIM 0x3c /* Fan 1 count limit (high) */ -#define LM80_FAN2_COUNT_LIM 0x3d /* Fan 2 count limit (low) */ - /* 0x3e - 0x3f reserved */ - -/* - * LM80 bit definitions - */ - -/* LM80_CFG Configuration Register */ -#define LM80_CFG_START (1<<0) /* start monitoring operation */ -#define LM80_CFG_INT_ENA (1<<1) /* enables the INT# Interrupt output */ -#define LM80_CFG_INT_POL (1<<2) /* INT# pol: 0 act low, 1 act high */ -#define LM80_CFG_INT_CLR (1<<3) /* disables INT#/RST_OUT#/OS# outputs */ -#define LM80_CFG_RESET (1<<4) /* signals a reset */ -#define LM80_CFG_CHASS_CLR (1<<5) /* clears Chassis Intrusion (CI) pin */ -#define LM80_CFG_GPO (1<<6) /* drives the GPO# pin */ -#define LM80_CFG_INIT (1<<7) /* restore power on defaults */ - -/* LM80_ISRC_1 Interrupt Status Register 1 */ -/* LM80_IMSK_1 Interrupt Mask Register 1 */ -#define LM80_IS_VT0 (1<<0) /* limit exceeded for Voltage 0 */ -#define LM80_IS_VT1 (1<<1) /* limit exceeded for Voltage 1 */ -#define LM80_IS_VT2 (1<<2) /* limit exceeded for Voltage 2 */ -#define LM80_IS_VT3 (1<<3) /* limit exceeded for Voltage 3 */ -#define LM80_IS_VT4 (1<<4) /* limit exceeded for Voltage 4 */ -#define LM80_IS_VT5 (1<<5) /* limit exceeded for Voltage 5 */ -#define LM80_IS_VT6 (1<<6) /* limit exceeded for Voltage 6 */ -#define LM80_IS_INT_IN (1<<7) /* state of INT_IN# */ - -/* LM80_ISRC_2 Interrupt Status Register 2 */ -/* LM80_IMSK_2 Interrupt Mask Register 2 */ -#define LM80_IS_TEMP (1<<0) /* HOT temperature limit exceeded */ -#define LM80_IS_BTI (1<<1) /* state of BTI# pin */ -#define LM80_IS_FAN1 (1<<2) /* count limit exceeded for Fan 1 */ -#define LM80_IS_FAN2 (1<<3) /* count limit exceeded for Fan 2 */ -#define LM80_IS_CI (1<<4) /* Chassis Intrusion occured */ -#define LM80_IS_OS (1<<5) /* OS temperature limit exceeded */ - /* bit 6 and 7 are reserved in LM80_ISRC_2 */ -#define LM80_IS_HT_IRQ_MD (1<<6) /* Hot temperature interrupt mode */ -#define LM80_IS_OT_IRQ_MD (1<<7) /* OS temperature interrupt mode */ - -/* LM80_FAN_CTRL Fan Devisor/RST#/OS# Register */ -#define LM80_FAN1_MD_SEL (1<<0) /* Fan 1 mode select */ -#define LM80_FAN2_MD_SEL (1<<1) /* Fan 2 mode select */ -#define LM80_FAN1_PRM_CTL (3<<2) /* Fan 1 speed control */ -#define LM80_FAN2_PRM_CTL (3<<4) /* Fan 2 speed control */ -#define LM80_FAN_OS_ENA (1<<6) /* enable OS mode on RST_OUT#/OS# pins*/ -#define LM80_FAN_RST_ENA (1<<7) /* sets RST_OUT#/OS# pins in RST mode */ - -/* LM80_TEMP_CTRL OS# Config, Temp Res. Reg */ -#define LM80_TEMP_OS_STAT (1<<0) /* mirrors the state of RST_OUT#/OS# */ -#define LM80_TEMP_OS_POL (1<<1) /* select OS# polarity */ -#define LM80_TEMP_OS_MODE (1<<2) /* selects Interrupt mode */ -#define LM80_TEMP_RES (1<<3) /* selects 9 or 11 bit temp resulution*/ -#define LM80_TEMP_LSB (0xf<<4)/* 4 LSBs of 11 bit temp data */ -#define LM80_TEMP_LSB_9 (1<<7) /* LSB of 9 bit temperature data */ - - /* 0x07 - 0x1f reserved */ -/* LM80_VT0_IN current Voltage 0 value */ -/* LM80_VT1_IN current Voltage 1 value */ -/* LM80_VT2_IN current Voltage 2 value */ -/* LM80_VT3_IN current Voltage 3 value */ -/* LM80_VT4_IN current Voltage 4 value */ -/* LM80_VT5_IN current Voltage 5 value */ -/* LM80_VT6_IN current Voltage 6 value */ -/* LM80_TEMP_IN current temperature value */ -/* LM80_FAN1_IN current Fan 1 count */ -/* LM80_FAN2_IN current Fan 2 count */ -/* LM80_VT0_HIGH_LIM high limit val for Voltage 0 */ -/* LM80_VT0_LOW_LIM low limit val for Voltage 0 */ -/* LM80_VT1_HIGH_LIM high limit val for Voltage 1 */ -/* LM80_VT1_LOW_LIM low limit val for Voltage 1 */ -/* LM80_VT2_HIGH_LIM high limit val for Voltage 2 */ -/* LM80_VT2_LOW_LIM low limit val for Voltage 2 */ -/* LM80_VT3_HIGH_LIM high limit val for Voltage 3 */ -/* LM80_VT3_LOW_LIM low limit val for Voltage 3 */ -/* LM80_VT4_HIGH_LIM high limit val for Voltage 4 */ -/* LM80_VT4_LOW_LIM low limit val for Voltage 4 */ -/* LM80_VT5_HIGH_LIM high limit val for Voltage 5 */ -/* LM80_VT5_LOW_LIM low limit val for Voltage 5 */ -/* LM80_VT6_HIGH_LIM high limit val for Voltage 6 */ -/* LM80_VT6_LOW_LIM low limit val for Voltage 6 */ -/* LM80_THOT_LIM_UP hot temperature limit (high) */ -/* LM80_THOT_LIM_LO hot temperature limit (low) */ -/* LM80_TOS_LIM_UP OS temperature limit (high) */ -/* LM80_TOS_LIM_LO OS temperature limit (low) */ -/* LM80_FAN1_COUNT_LIM Fan 1 count limit (high) */ -/* LM80_FAN2_COUNT_LIM Fan 2 count limit (low) */ - /* 0x3e - 0x3f reserved */ - -#define LM80_ADDR 0x28 /* LM80 default addr */ - -/* typedefs *******************************************************************/ - - -/* function prototypes ********************************************************/ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __INC_LM80_H */ diff --git a/drivers/net/sk98lin/h/skaddr.h b/drivers/net/sk98lin/h/skaddr.h deleted file mode 100644 index 423ad063d09..00000000000 --- a/drivers/net/sk98lin/h/skaddr.h +++ /dev/null @@ -1,285 +0,0 @@ -/****************************************************************************** - * - * Name: skaddr.h - * Project: Gigabit Ethernet Adapters, ADDR-Modul - * Version: $Revision: 1.29 $ - * Date: $Date: 2003/05/13 16:57:24 $ - * Purpose: Header file for Address Management (MC, UC, Prom). - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This module is intended to manage multicast addresses and promiscuous mode - * on GEnesis adapters. - * - * Include File Hierarchy: - * - * "skdrv1st.h" - * ... - * "sktypes.h" - * "skqueue.h" - * "skaddr.h" - * ... - * "skdrv2nd.h" - * - ******************************************************************************/ - -#ifndef __INC_SKADDR_H -#define __INC_SKADDR_H - -#ifdef __cplusplus -extern "C" { -#endif /* cplusplus */ - -/* defines ********************************************************************/ - -#define SK_MAC_ADDR_LEN 6 /* Length of MAC address. */ -#define SK_MAX_ADDRS 14 /* #Addrs for exact match. */ - -/* ----- Common return values ----- */ - -#define SK_ADDR_SUCCESS 0 /* Function returned successfully. */ -#define SK_ADDR_ILLEGAL_PORT 100 /* Port number too high. */ -#define SK_ADDR_TOO_EARLY 101 /* Function called too early. */ - -/* ----- Clear/Add flag bits ----- */ - -#define SK_ADDR_PERMANENT 1 /* RLMT Address */ - -/* ----- Additional Clear flag bits ----- */ - -#define SK_MC_SW_ONLY 2 /* Do not update HW when clearing. */ - -/* ----- Override flag bits ----- */ - -#define SK_ADDR_LOGICAL_ADDRESS 0 -#define SK_ADDR_VIRTUAL_ADDRESS (SK_ADDR_LOGICAL_ADDRESS) /* old */ -#define SK_ADDR_PHYSICAL_ADDRESS 1 -#define SK_ADDR_CLEAR_LOGICAL 2 -#define SK_ADDR_SET_LOGICAL 4 - -/* ----- Override return values ----- */ - -#define SK_ADDR_OVERRIDE_SUCCESS (SK_ADDR_SUCCESS) -#define SK_ADDR_DUPLICATE_ADDRESS 1 -#define SK_ADDR_MULTICAST_ADDRESS 2 - -/* ----- Partitioning of excact match table ----- */ - -#define SK_ADDR_EXACT_MATCHES 16 /* #Exact match entries. */ - -#define SK_ADDR_FIRST_MATCH_RLMT 1 -#define SK_ADDR_LAST_MATCH_RLMT 2 -#define SK_ADDR_FIRST_MATCH_DRV 3 -#define SK_ADDR_LAST_MATCH_DRV (SK_ADDR_EXACT_MATCHES - 1) - -/* ----- SkAddrMcAdd/SkAddrMcUpdate return values ----- */ - -#define SK_MC_FILTERING_EXACT 0 /* Exact filtering. */ -#define SK_MC_FILTERING_INEXACT 1 /* Inexact filtering. */ - -/* ----- Additional SkAddrMcAdd return values ----- */ - -#define SK_MC_ILLEGAL_ADDRESS 2 /* Illegal address. */ -#define SK_MC_ILLEGAL_PORT 3 /* Illegal port (not the active one). */ -#define SK_MC_RLMT_OVERFLOW 4 /* Too many RLMT mc addresses. */ - -/* Promiscuous mode bits ----- */ - -#define SK_PROM_MODE_NONE 0 /* Normal receive. */ -#define SK_PROM_MODE_LLC 1 /* Receive all LLC frames. */ -#define SK_PROM_MODE_ALL_MC 2 /* Receive all multicast frames. */ -/* #define SK_PROM_MODE_NON_LLC 4 */ /* Receive all non-LLC frames. */ - -/* Macros */ - -#ifdef OLD_STUFF -#ifndef SK_ADDR_EQUAL -/* - * "&" instead of "&&" allows better optimization on IA-64. - * The replacement is safe here, as all bytes exist. - */ -#ifndef SK_ADDR_DWORD_COMPARE -#define SK_ADDR_EQUAL(A1,A2) ( \ - (((SK_U8 *)(A1))[5] == ((SK_U8 *)(A2))[5]) & \ - (((SK_U8 *)(A1))[4] == ((SK_U8 *)(A2))[4]) & \ - (((SK_U8 *)(A1))[3] == ((SK_U8 *)(A2))[3]) & \ - (((SK_U8 *)(A1))[2] == ((SK_U8 *)(A2))[2]) & \ - (((SK_U8 *)(A1))[1] == ((SK_U8 *)(A2))[1]) & \ - (((SK_U8 *)(A1))[0] == ((SK_U8 *)(A2))[0])) -#else /* SK_ADDR_DWORD_COMPARE */ -#define SK_ADDR_EQUAL(A1,A2) ( \ - (*(SK_U32 *)&(((SK_U8 *)(A1))[2]) == *(SK_U32 *)&(((SK_U8 *)(A2))[2])) & \ - (*(SK_U32 *)&(((SK_U8 *)(A1))[0]) == *(SK_U32 *)&(((SK_U8 *)(A2))[0]))) -#endif /* SK_ADDR_DWORD_COMPARE */ -#endif /* SK_ADDR_EQUAL */ -#endif /* 0 */ - -#ifndef SK_ADDR_EQUAL -#ifndef SK_ADDR_DWORD_COMPARE -#define SK_ADDR_EQUAL(A1,A2) ( \ - (((SK_U8 SK_FAR *)(A1))[5] == ((SK_U8 SK_FAR *)(A2))[5]) & \ - (((SK_U8 SK_FAR *)(A1))[4] == ((SK_U8 SK_FAR *)(A2))[4]) & \ - (((SK_U8 SK_FAR *)(A1))[3] == ((SK_U8 SK_FAR *)(A2))[3]) & \ - (((SK_U8 SK_FAR *)(A1))[2] == ((SK_U8 SK_FAR *)(A2))[2]) & \ - (((SK_U8 SK_FAR *)(A1))[1] == ((SK_U8 SK_FAR *)(A2))[1]) & \ - (((SK_U8 SK_FAR *)(A1))[0] == ((SK_U8 SK_FAR *)(A2))[0])) -#else /* SK_ADDR_DWORD_COMPARE */ -#define SK_ADDR_EQUAL(A1,A2) ( \ - (*(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[4]) == \ - *(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[4])) && \ - (*(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[0]) == \ - *(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[0]))) -#endif /* SK_ADDR_DWORD_COMPARE */ -#endif /* SK_ADDR_EQUAL */ - -/* typedefs *******************************************************************/ - -typedef struct s_MacAddr { - SK_U8 a[SK_MAC_ADDR_LEN]; -} SK_MAC_ADDR; - - -/* SK_FILTER is used to ensure alignment of the filter. */ -typedef union s_InexactFilter { - SK_U8 Bytes[8]; - SK_U64 Val; /* Dummy entry for alignment only. */ -} SK_FILTER64; - - -typedef struct s_AddrNet SK_ADDR_NET; - - -typedef struct s_AddrPort { - -/* ----- Public part (read-only) ----- */ - - SK_MAC_ADDR CurrentMacAddress; /* Current physical MAC Address. */ - SK_MAC_ADDR PermanentMacAddress; /* Permanent physical MAC Address. */ - int PromMode; /* Promiscuous Mode. */ - -/* ----- Private part ----- */ - - SK_MAC_ADDR PreviousMacAddress; /* Prev. phys. MAC Address. */ - SK_BOOL CurrentMacAddressSet; /* CurrentMacAddress is set. */ - SK_U8 Align01; - - SK_U32 FirstExactMatchRlmt; - SK_U32 NextExactMatchRlmt; - SK_U32 FirstExactMatchDrv; - SK_U32 NextExactMatchDrv; - SK_MAC_ADDR Exact[SK_ADDR_EXACT_MATCHES]; - SK_FILTER64 InexactFilter; /* For 64-bit hash register. */ - SK_FILTER64 InexactRlmtFilter; /* For 64-bit hash register. */ - SK_FILTER64 InexactDrvFilter; /* For 64-bit hash register. */ -} SK_ADDR_PORT; - - -struct s_AddrNet { -/* ----- Public part (read-only) ----- */ - - SK_MAC_ADDR CurrentMacAddress; /* Logical MAC Address. */ - SK_MAC_ADDR PermanentMacAddress; /* Logical MAC Address. */ - -/* ----- Private part ----- */ - - SK_U32 ActivePort; /* View of module ADDR. */ - SK_BOOL CurrentMacAddressSet; /* CurrentMacAddress is set. */ - SK_U8 Align01; - SK_U16 Align02; -}; - - -typedef struct s_Addr { - -/* ----- Public part (read-only) ----- */ - - SK_ADDR_NET Net[SK_MAX_NETS]; - SK_ADDR_PORT Port[SK_MAX_MACS]; - -/* ----- Private part ----- */ -} SK_ADDR; - -/* function prototypes ********************************************************/ - -#ifndef SK_KR_PROTO - -/* Functions provided by SkAddr */ - -/* ANSI/C++ compliant function prototypes */ - -extern int SkAddrInit( - SK_AC *pAC, - SK_IOC IoC, - int Level); - -extern int SkAddrMcClear( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - int Flags); - -extern int SkAddrMcAdd( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - SK_MAC_ADDR *pMc, - int Flags); - -extern int SkAddrMcUpdate( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber); - -extern int SkAddrOverride( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - SK_MAC_ADDR SK_FAR *pNewAddr, - int Flags); - -extern int SkAddrPromiscuousChange( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - int NewPromMode); - -#ifndef SK_SLIM -extern int SkAddrSwap( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 FromPortNumber, - SK_U32 ToPortNumber); -#endif - -#else /* defined(SK_KR_PROTO)) */ - -/* Non-ANSI/C++ compliant function prototypes */ - -#error KR-style prototypes are not yet provided. - -#endif /* defined(SK_KR_PROTO)) */ - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __INC_SKADDR_H */ diff --git a/drivers/net/sk98lin/h/skcsum.h b/drivers/net/sk98lin/h/skcsum.h deleted file mode 100644 index 6e256bd9a28..00000000000 --- a/drivers/net/sk98lin/h/skcsum.h +++ /dev/null @@ -1,213 +0,0 @@ -/****************************************************************************** - * - * Name: skcsum.h - * Project: GEnesis - SysKonnect SK-NET Gigabit Ethernet (SK-98xx) - * Version: $Revision: 1.10 $ - * Date: $Date: 2003/08/20 13:59:57 $ - * Purpose: Store/verify Internet checksum in send/receive packets. - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2001 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * Public header file for the "GEnesis" common module "CSUM". - * - * "GEnesis" is an abbreviation of "Gigabit Ethernet Network System in Silicon" - * and is the code name of this SysKonnect project. - * - * Compilation Options: - * - * SK_USE_CSUM - Define if CSUM is to be used. Otherwise, CSUM will be an - * empty module. - * - * SKCS_OVERWRITE_PROTO - Define to overwrite the default protocol id - * definitions. In this case, all SKCS_PROTO_xxx definitions must be made - * external. - * - * SKCS_OVERWRITE_STATUS - Define to overwrite the default return status - * definitions. In this case, all SKCS_STATUS_xxx definitions must be made - * external. - * - * Include File Hierarchy: - * - * "h/skcsum.h" - * "h/sktypes.h" - * "h/skqueue.h" - * - ******************************************************************************/ - -#ifndef __INC_SKCSUM_H -#define __INC_SKCSUM_H - -#include "h/sktypes.h" -#include "h/skqueue.h" - -/* defines ********************************************************************/ - -/* - * Define the default bit flags for 'SKCS_PACKET_INFO.ProtocolFlags' if no user - * overwrite. - */ -#ifndef SKCS_OVERWRITE_PROTO /* User overwrite? */ -#define SKCS_PROTO_IP 0x1 /* IP (Internet Protocol version 4) */ -#define SKCS_PROTO_TCP 0x2 /* TCP (Transmission Control Protocol) */ -#define SKCS_PROTO_UDP 0x4 /* UDP (User Datagram Protocol) */ - -/* Indices for protocol statistics. */ -#define SKCS_PROTO_STATS_IP 0 -#define SKCS_PROTO_STATS_UDP 1 -#define SKCS_PROTO_STATS_TCP 2 -#define SKCS_NUM_PROTOCOLS 3 /* Number of supported protocols. */ -#endif /* !SKCS_OVERWRITE_PROTO */ - -/* - * Define the default SKCS_STATUS type and values if no user overwrite. - * - * SKCS_STATUS_UNKNOWN_IP_VERSION - Not an IP v4 frame. - * SKCS_STATUS_IP_CSUM_ERROR - IP checksum error. - * SKCS_STATUS_IP_CSUM_ERROR_TCP - IP checksum error in TCP frame. - * SKCS_STATUS_IP_CSUM_ERROR_UDP - IP checksum error in UDP frame - * SKCS_STATUS_IP_FRAGMENT - IP fragment (IP checksum ok). - * SKCS_STATUS_IP_CSUM_OK - IP checksum ok (not a TCP or UDP frame). - * SKCS_STATUS_TCP_CSUM_ERROR - TCP checksum error (IP checksum ok). - * SKCS_STATUS_UDP_CSUM_ERROR - UDP checksum error (IP checksum ok). - * SKCS_STATUS_TCP_CSUM_OK - IP and TCP checksum ok. - * SKCS_STATUS_UDP_CSUM_OK - IP and UDP checksum ok. - * SKCS_STATUS_IP_CSUM_OK_NO_UDP - IP checksum OK and no UDP checksum. - */ -#ifndef SKCS_OVERWRITE_STATUS /* User overwrite? */ -#define SKCS_STATUS int /* Define status type. */ - -#define SKCS_STATUS_UNKNOWN_IP_VERSION 1 -#define SKCS_STATUS_IP_CSUM_ERROR 2 -#define SKCS_STATUS_IP_FRAGMENT 3 -#define SKCS_STATUS_IP_CSUM_OK 4 -#define SKCS_STATUS_TCP_CSUM_ERROR 5 -#define SKCS_STATUS_UDP_CSUM_ERROR 6 -#define SKCS_STATUS_TCP_CSUM_OK 7 -#define SKCS_STATUS_UDP_CSUM_OK 8 -/* needed for Microsoft */ -#define SKCS_STATUS_IP_CSUM_ERROR_UDP 9 -#define SKCS_STATUS_IP_CSUM_ERROR_TCP 10 -/* UDP checksum may be omitted */ -#define SKCS_STATUS_IP_CSUM_OK_NO_UDP 11 -#endif /* !SKCS_OVERWRITE_STATUS */ - -/* Clear protocol statistics event. */ -#define SK_CSUM_EVENT_CLEAR_PROTO_STATS 1 - -/* - * Add two values in one's complement. - * - * Note: One of the two input values may be "longer" than 16-bit, but then the - * resulting sum may be 17 bits long. In this case, add zero to the result using - * SKCS_OC_ADD() again. - * - * Result = Value1 + Value2 - */ -#define SKCS_OC_ADD(Result, Value1, Value2) { \ - unsigned long Sum; \ - \ - Sum = (unsigned long) (Value1) + (unsigned long) (Value2); \ - /* Add-in any carry. */ \ - (Result) = (Sum & 0xffff) + (Sum >> 16); \ -} - -/* - * Subtract two values in one's complement. - * - * Result = Value1 - Value2 - */ -#define SKCS_OC_SUB(Result, Value1, Value2) \ - SKCS_OC_ADD((Result), (Value1), ~(Value2) & 0xffff) - -/* typedefs *******************************************************************/ - -/* - * SKCS_PROTO_STATS - The CSUM protocol statistics structure. - * - * There is one instance of this structure for each protocol supported. - */ -typedef struct s_CsProtocolStatistics { - SK_U64 RxOkCts; /* Receive checksum ok. */ - SK_U64 RxUnableCts; /* Unable to verify receive checksum. */ - SK_U64 RxErrCts; /* Receive checksum error. */ - SK_U64 TxOkCts; /* Transmit checksum ok. */ - SK_U64 TxUnableCts; /* Unable to calculate checksum in hw. */ -} SKCS_PROTO_STATS; - -/* - * s_Csum - The CSUM module context structure. - */ -typedef struct s_Csum { - /* Enabled receive SK_PROTO_XXX bit flags. */ - unsigned ReceiveFlags[SK_MAX_NETS]; -#ifdef TX_CSUM - unsigned TransmitFlags[SK_MAX_NETS]; -#endif /* TX_CSUM */ - - /* The protocol statistics structure; one per supported protocol. */ - SKCS_PROTO_STATS ProtoStats[SK_MAX_NETS][SKCS_NUM_PROTOCOLS]; -} SK_CSUM; - -/* - * SKCS_PACKET_INFO - The packet information structure. - */ -typedef struct s_CsPacketInfo { - /* Bit field specifiying the desired/found protocols. */ - unsigned ProtocolFlags; - - /* Length of complete IP header, including any option fields. */ - unsigned IpHeaderLength; - - /* IP header checksum. */ - unsigned IpHeaderChecksum; - - /* TCP/UDP pseudo header checksum. */ - unsigned PseudoHeaderChecksum; -} SKCS_PACKET_INFO; - -/* function prototypes ********************************************************/ - -#ifndef SK_CS_CALCULATE_CHECKSUM -extern unsigned SkCsCalculateChecksum( - void *pData, - unsigned Length); -#endif /* SK_CS_CALCULATE_CHECKSUM */ - -extern int SkCsEvent( - SK_AC *pAc, - SK_IOC Ioc, - SK_U32 Event, - SK_EVPARA Param); - -extern SKCS_STATUS SkCsGetReceiveInfo( - SK_AC *pAc, - void *pIpHeader, - unsigned Checksum1, - unsigned Checksum2, - int NetNumber); - -extern void SkCsSetReceiveFlags( - SK_AC *pAc, - unsigned ReceiveFlags, - unsigned *pChecksum1Offset, - unsigned *pChecksum2Offset, - int NetNumber); - -#endif /* __INC_SKCSUM_H */ diff --git a/drivers/net/sk98lin/h/skdebug.h b/drivers/net/sk98lin/h/skdebug.h deleted file mode 100644 index 3cba171d74b..00000000000 --- a/drivers/net/sk98lin/h/skdebug.h +++ /dev/null @@ -1,74 +0,0 @@ -/****************************************************************************** - * - * Name: skdebug.h - * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.14 $ - * Date: $Date: 2003/05/13 17:26:00 $ - * Purpose: SK specific DEBUG support - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#ifndef __INC_SKDEBUG_H -#define __INC_SKDEBUG_H - -#ifdef DEBUG -#ifndef SK_DBG_MSG -#define SK_DBG_MSG(pAC,comp,cat,arg) \ - if ( ((comp) & SK_DBG_CHKMOD(pAC)) && \ - ((cat) & SK_DBG_CHKCAT(pAC)) ) { \ - SK_DBG_PRINTF arg ; \ - } -#endif -#else -#define SK_DBG_MSG(pAC,comp,lev,arg) -#endif - -/* PLS NOTE: - * ========= - * Due to any restrictions of kernel printf routines do not use other - * format identifiers as: %x %d %c %s . - * Never use any combined format identifiers such as: %lx %ld in your - * printf - argument (arg) because some OS specific kernel printfs may - * only support some basic identifiers. - */ - -/* Debug modules */ - -#define SK_DBGMOD_MERR 0x00000001L /* general module error indication */ -#define SK_DBGMOD_HWM 0x00000002L /* Hardware init module */ -#define SK_DBGMOD_RLMT 0x00000004L /* RLMT module */ -#define SK_DBGMOD_VPD 0x00000008L /* VPD module */ -#define SK_DBGMOD_I2C 0x00000010L /* I2C module */ -#define SK_DBGMOD_PNMI 0x00000020L /* PNMI module */ -#define SK_DBGMOD_CSUM 0x00000040L /* CSUM module */ -#define SK_DBGMOD_ADDR 0x00000080L /* ADDR module */ -#define SK_DBGMOD_PECP 0x00000100L /* PECP module */ -#define SK_DBGMOD_POWM 0x00000200L /* Power Management module */ - -/* Debug events */ - -#define SK_DBGCAT_INIT 0x00000001L /* module/driver initialization */ -#define SK_DBGCAT_CTRL 0x00000002L /* controlling devices */ -#define SK_DBGCAT_ERR 0x00000004L /* error handling paths */ -#define SK_DBGCAT_TX 0x00000008L /* transmit path */ -#define SK_DBGCAT_RX 0x00000010L /* receive path */ -#define SK_DBGCAT_IRQ 0x00000020L /* general IRQ handling */ -#define SK_DBGCAT_QUEUE 0x00000040L /* any queue management */ -#define SK_DBGCAT_DUMP 0x00000080L /* large data output e.g. hex dump */ -#define SK_DBGCAT_FATAL 0x00000100L /* fatal error */ - -#endif /* __INC_SKDEBUG_H */ diff --git a/drivers/net/sk98lin/h/skdrv1st.h b/drivers/net/sk98lin/h/skdrv1st.h deleted file mode 100644 index 91b8d4f4590..00000000000 --- a/drivers/net/sk98lin/h/skdrv1st.h +++ /dev/null @@ -1,188 +0,0 @@ -/****************************************************************************** - * - * Name: skdrv1st.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.4 $ - * Date: $Date: 2003/11/12 14:28:14 $ - * Purpose: First header file for driver and all other modules - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This is the first include file of the driver, which includes all - * neccessary system header files and some of the GEnesis header files. - * It also defines some basic items. - * - * Include File Hierarchy: - * - * see skge.c - * - ******************************************************************************/ - -#ifndef __INC_SKDRV1ST_H -#define __INC_SKDRV1ST_H - -typedef struct s_AC SK_AC; - -/* Set card versions */ -#define SK_FAR - -/* override some default functions with optimized linux functions */ - -#define SK_PNMI_STORE_U16(p,v) memcpy((char*)(p),(char*)&(v),2) -#define SK_PNMI_STORE_U32(p,v) memcpy((char*)(p),(char*)&(v),4) -#define SK_PNMI_STORE_U64(p,v) memcpy((char*)(p),(char*)&(v),8) -#define SK_PNMI_READ_U16(p,v) memcpy((char*)&(v),(char*)(p),2) -#define SK_PNMI_READ_U32(p,v) memcpy((char*)&(v),(char*)(p),4) -#define SK_PNMI_READ_U64(p,v) memcpy((char*)&(v),(char*)(p),8) - -#define SK_ADDR_EQUAL(a1,a2) (!memcmp(a1,a2,6)) - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/bitops.h> -#include <asm/byteorder.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -#include <linux/init.h> -#include <asm/uaccess.h> -#include <net/checksum.h> - -#define SK_CS_CALCULATE_CHECKSUM -#ifndef CONFIG_X86_64 -#define SkCsCalculateChecksum(p,l) ((~ip_compute_csum(p, l)) & 0xffff) -#else -#define SkCsCalculateChecksum(p,l) ((~ip_fast_csum(p, l)) & 0xffff) -#endif - -#include "h/sktypes.h" -#include "h/skerror.h" -#include "h/skdebug.h" -#include "h/lm80.h" -#include "h/xmac_ii.h" - -#ifdef __LITTLE_ENDIAN -#define SK_LITTLE_ENDIAN -#else -#define SK_BIG_ENDIAN -#endif - -#define SK_NET_DEVICE net_device - - -/* we use gethrtime(), return unit: nanoseconds */ -#define SK_TICKS_PER_SEC 100 - -#define SK_MEM_MAPPED_IO - -// #define SK_RLMT_SLOW_LOOKAHEAD - -#define SK_MAX_MACS 2 -#define SK_MAX_NETS 2 - -#define SK_IOC char __iomem * - -typedef struct s_DrvRlmtMbuf SK_MBUF; - -#define SK_CONST64 INT64_C -#define SK_CONSTU64 UINT64_C - -#define SK_MEMCPY(dest,src,size) memcpy(dest,src,size) -#define SK_MEMCMP(s1,s2,size) memcmp(s1,s2,size) -#define SK_MEMSET(dest,val,size) memset(dest,val,size) -#define SK_STRLEN(pStr) strlen((char*)(pStr)) -#define SK_STRNCPY(pDest,pSrc,size) strncpy((char*)(pDest),(char*)(pSrc),size) -#define SK_STRCMP(pStr1,pStr2) strcmp((char*)(pStr1),(char*)(pStr2)) - -/* macros to access the adapter */ -#define SK_OUT8(b,a,v) writeb((v), ((b)+(a))) -#define SK_OUT16(b,a,v) writew((v), ((b)+(a))) -#define SK_OUT32(b,a,v) writel((v), ((b)+(a))) -#define SK_IN8(b,a,pv) (*(pv) = readb((b)+(a))) -#define SK_IN16(b,a,pv) (*(pv) = readw((b)+(a))) -#define SK_IN32(b,a,pv) (*(pv) = readl((b)+(a))) - -#define int8_t char -#define int16_t short -#define int32_t long -#define int64_t long long -#define uint8_t u_char -#define uint16_t u_short -#define uint32_t u_long -#define uint64_t unsigned long long -#define t_scalar_t int -#define t_uscalar_t unsigned int -#define uintptr_t unsigned long - -#define __CONCAT__(A,B) A##B - -#define INT32_C(a) __CONCAT__(a,L) -#define INT64_C(a) __CONCAT__(a,LL) -#define UINT32_C(a) __CONCAT__(a,UL) -#define UINT64_C(a) __CONCAT__(a,ULL) - -#ifdef DEBUG -#define SK_DBG_PRINTF printk -#ifndef SK_DEBUG_CHKMOD -#define SK_DEBUG_CHKMOD 0 -#endif -#ifndef SK_DEBUG_CHKCAT -#define SK_DEBUG_CHKCAT 0 -#endif -/* those come from the makefile */ -#define SK_DBG_CHKMOD(pAC) (SK_DEBUG_CHKMOD) -#define SK_DBG_CHKCAT(pAC) (SK_DEBUG_CHKCAT) - -extern void SkDbgPrintf(const char *format,...); - -#define SK_DBGMOD_DRV 0x00010000 - -/**** possible driver debug categories ********************************/ -#define SK_DBGCAT_DRV_ENTRY 0x00010000 -#define SK_DBGCAT_DRV_SAP 0x00020000 -#define SK_DBGCAT_DRV_MCA 0x00040000 -#define SK_DBGCAT_DRV_TX_PROGRESS 0x00080000 -#define SK_DBGCAT_DRV_RX_PROGRESS 0x00100000 -#define SK_DBGCAT_DRV_PROGRESS 0x00200000 -#define SK_DBGCAT_DRV_MSG 0x00400000 -#define SK_DBGCAT_DRV_PROM 0x00800000 -#define SK_DBGCAT_DRV_TX_FRAME 0x01000000 -#define SK_DBGCAT_DRV_ERROR 0x02000000 -#define SK_DBGCAT_DRV_INT_SRC 0x04000000 -#define SK_DBGCAT_DRV_EVENT 0x08000000 - -#endif - -#define SK_ERR_LOG SkErrorLog - -extern void SkErrorLog(SK_AC*, int, int, char*); - -#endif - diff --git a/drivers/net/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h deleted file mode 100644 index 3fa67171e83..00000000000 --- a/drivers/net/sk98lin/h/skdrv2nd.h +++ /dev/null @@ -1,447 +0,0 @@ -/****************************************************************************** - * - * Name: skdrv2nd.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.10 $ - * Date: $Date: 2003/12/11 16:04:45 $ - * Purpose: Second header file for driver and all other modules - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This is the second include file of the driver, which includes all other - * neccessary files and defines all structures and constants used by the - * driver and the common modules. - * - * Include File Hierarchy: - * - * see skge.c - * - ******************************************************************************/ - -#ifndef __INC_SKDRV2ND_H -#define __INC_SKDRV2ND_H - -#include "h/skqueue.h" -#include "h/skgehwt.h" -#include "h/sktimer.h" -#include "h/ski2c.h" -#include "h/skgepnmi.h" -#include "h/skvpd.h" -#include "h/skgehw.h" -#include "h/skgeinit.h" -#include "h/skaddr.h" -#include "h/skgesirq.h" -#include "h/skcsum.h" -#include "h/skrlmt.h" -#include "h/skgedrv.h" - - -extern SK_MBUF *SkDrvAllocRlmtMbuf(SK_AC*, SK_IOC, unsigned); -extern void SkDrvFreeRlmtMbuf(SK_AC*, SK_IOC, SK_MBUF*); -extern SK_U64 SkOsGetTime(SK_AC*); -extern int SkPciReadCfgDWord(SK_AC*, int, SK_U32*); -extern int SkPciReadCfgWord(SK_AC*, int, SK_U16*); -extern int SkPciReadCfgByte(SK_AC*, int, SK_U8*); -extern int SkPciWriteCfgWord(SK_AC*, int, SK_U16); -extern int SkPciWriteCfgByte(SK_AC*, int, SK_U8); -extern int SkDrvEvent(SK_AC*, SK_IOC IoC, SK_U32, SK_EVPARA); - -#ifdef SK_DIAG_SUPPORT -extern int SkDrvEnterDiagMode(SK_AC *pAc); -extern int SkDrvLeaveDiagMode(SK_AC *pAc); -#endif - -struct s_DrvRlmtMbuf { - SK_MBUF *pNext; /* Pointer to next RLMT Mbuf. */ - SK_U8 *pData; /* Data buffer (virtually contig.). */ - unsigned Size; /* Data buffer size. */ - unsigned Length; /* Length of packet (<= Size). */ - SK_U32 PortIdx; /* Receiving/transmitting port. */ -#ifdef SK_RLMT_MBUF_PRIVATE - SK_RLMT_MBUF Rlmt; /* Private part for RLMT. */ -#endif /* SK_RLMT_MBUF_PRIVATE */ - struct sk_buff *pOs; /* Pointer to message block */ -}; - - -/* - * Time macros - */ -#if SK_TICKS_PER_SEC == 100 -#define SK_PNMI_HUNDREDS_SEC(t) (t) -#else -#define SK_PNMI_HUNDREDS_SEC(t) ((((unsigned long)t) * 100) / \ - (SK_TICKS_PER_SEC)) -#endif - -/* - * New SkOsGetTime - */ -#define SkOsGetTimeCurrent(pAC, pUsec) {\ - struct timeval t;\ - do_gettimeofday(&t);\ - *pUsec = ((((t.tv_sec) * 1000000L)+t.tv_usec)/10000);\ -} - - -/* - * ioctl definitions - */ -#define SK_IOCTL_BASE (SIOCDEVPRIVATE) -#define SK_IOCTL_GETMIB (SK_IOCTL_BASE + 0) -#define SK_IOCTL_SETMIB (SK_IOCTL_BASE + 1) -#define SK_IOCTL_PRESETMIB (SK_IOCTL_BASE + 2) -#define SK_IOCTL_GEN (SK_IOCTL_BASE + 3) -#define SK_IOCTL_DIAG (SK_IOCTL_BASE + 4) - -typedef struct s_IOCTL SK_GE_IOCTL; - -struct s_IOCTL { - char __user * pData; - unsigned int Len; -}; - - -/* - * define sizes of descriptor rings in bytes - */ - -#define TX_RING_SIZE (8*1024) -#define RX_RING_SIZE (24*1024) - -/* - * Buffer size for ethernet packets - */ -#define ETH_BUF_SIZE 1540 -#define ETH_MAX_MTU 1514 -#define ETH_MIN_MTU 60 -#define ETH_MULTICAST_BIT 0x01 -#define SK_JUMBO_MTU 9000 - -/* - * transmit priority selects the queue: LOW=asynchron, HIGH=synchron - */ -#define TX_PRIO_LOW 0 -#define TX_PRIO_HIGH 1 - -/* - * alignment of rx/tx descriptors - */ -#define DESCR_ALIGN 64 - -/* - * definitions for pnmi. TODO - */ -#define SK_DRIVER_RESET(pAC, IoC) 0 -#define SK_DRIVER_SENDEVENT(pAC, IoC) 0 -#define SK_DRIVER_SELFTEST(pAC, IoC) 0 -/* For get mtu you must add an own function */ -#define SK_DRIVER_GET_MTU(pAc,IoC,i) 0 -#define SK_DRIVER_SET_MTU(pAc,IoC,i,v) 0 -#define SK_DRIVER_PRESET_MTU(pAc,IoC,i,v) 0 - -/* -** Interim definition of SK_DRV_TIMER placed in this file until -** common modules have been finalized -*/ -#define SK_DRV_TIMER 11 -#define SK_DRV_MODERATION_TIMER 1 -#define SK_DRV_MODERATION_TIMER_LENGTH 1000000 /* 1 second */ -#define SK_DRV_RX_CLEANUP_TIMER 2 -#define SK_DRV_RX_CLEANUP_TIMER_LENGTH 1000000 /* 100 millisecs */ - -/* -** Definitions regarding transmitting frames -** any calculating any checksum. -*/ -#define C_LEN_ETHERMAC_HEADER_DEST_ADDR 6 -#define C_LEN_ETHERMAC_HEADER_SRC_ADDR 6 -#define C_LEN_ETHERMAC_HEADER_LENTYPE 2 -#define C_LEN_ETHERMAC_HEADER ( (C_LEN_ETHERMAC_HEADER_DEST_ADDR) + \ - (C_LEN_ETHERMAC_HEADER_SRC_ADDR) + \ - (C_LEN_ETHERMAC_HEADER_LENTYPE) ) - -#define C_LEN_ETHERMTU_MINSIZE 46 -#define C_LEN_ETHERMTU_MAXSIZE_STD 1500 -#define C_LEN_ETHERMTU_MAXSIZE_JUMBO 9000 - -#define C_LEN_ETHERNET_MINSIZE ( (C_LEN_ETHERMAC_HEADER) + \ - (C_LEN_ETHERMTU_MINSIZE) ) - -#define C_OFFSET_IPHEADER C_LEN_ETHERMAC_HEADER -#define C_OFFSET_IPHEADER_IPPROTO 9 -#define C_OFFSET_TCPHEADER_TCPCS 16 -#define C_OFFSET_UDPHEADER_UDPCS 6 - -#define C_OFFSET_IPPROTO ( (C_LEN_ETHERMAC_HEADER) + \ - (C_OFFSET_IPHEADER_IPPROTO) ) - -#define C_PROTO_ID_UDP 17 /* refer to RFC 790 or Stevens' */ -#define C_PROTO_ID_TCP 6 /* TCP/IP illustrated for details */ - -/* TX and RX descriptors *****************************************************/ - -typedef struct s_RxD RXD; /* the receive descriptor */ - -struct s_RxD { - volatile SK_U32 RBControl; /* Receive Buffer Control */ - SK_U32 VNextRxd; /* Next receive descriptor,low dword */ - SK_U32 VDataLow; /* Receive buffer Addr, low dword */ - SK_U32 VDataHigh; /* Receive buffer Addr, high dword */ - SK_U32 FrameStat; /* Receive Frame Status word */ - SK_U32 TimeStamp; /* Time stamp from XMAC */ - SK_U32 TcpSums; /* TCP Sum 2 / TCP Sum 1 */ - SK_U32 TcpSumStarts; /* TCP Sum Start 2 / TCP Sum Start 1 */ - RXD *pNextRxd; /* Pointer to next Rxd */ - struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */ -}; - -typedef struct s_TxD TXD; /* the transmit descriptor */ - -struct s_TxD { - volatile SK_U32 TBControl; /* Transmit Buffer Control */ - SK_U32 VNextTxd; /* Next transmit descriptor,low dword */ - SK_U32 VDataLow; /* Transmit Buffer Addr, low dword */ - SK_U32 VDataHigh; /* Transmit Buffer Addr, high dword */ - SK_U32 FrameStat; /* Transmit Frame Status Word */ - SK_U32 TcpSumOfs; /* Reserved / TCP Sum Offset */ - SK_U16 TcpSumSt; /* TCP Sum Start */ - SK_U16 TcpSumWr; /* TCP Sum Write */ - SK_U32 TcpReserved; /* not used */ - TXD *pNextTxd; /* Pointer to next Txd */ - struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */ -}; - -/* Used interrupt bits in the interrupts source register *********************/ - -#define DRIVER_IRQS ((IS_IRQ_SW) | \ - (IS_R1_F) |(IS_R2_F) | \ - (IS_XS1_F) |(IS_XA1_F) | \ - (IS_XS2_F) |(IS_XA2_F)) - -#define SPECIAL_IRQS ((IS_HW_ERR) |(IS_I2C_READY) | \ - (IS_EXT_REG) |(IS_TIMINT) | \ - (IS_PA_TO_RX1) |(IS_PA_TO_RX2) | \ - (IS_PA_TO_TX1) |(IS_PA_TO_TX2) | \ - (IS_MAC1) |(IS_LNK_SYNC_M1)| \ - (IS_MAC2) |(IS_LNK_SYNC_M2)| \ - (IS_R1_C) |(IS_R2_C) | \ - (IS_XS1_C) |(IS_XA1_C) | \ - (IS_XS2_C) |(IS_XA2_C)) - -#define IRQ_MASK ((IS_IRQ_SW) | \ - (IS_R1_B) |(IS_R1_F) |(IS_R2_B) |(IS_R2_F) | \ - (IS_XS1_B) |(IS_XS1_F) |(IS_XA1_B)|(IS_XA1_F)| \ - (IS_XS2_B) |(IS_XS2_F) |(IS_XA2_B)|(IS_XA2_F)| \ - (IS_HW_ERR) |(IS_I2C_READY)| \ - (IS_EXT_REG) |(IS_TIMINT) | \ - (IS_PA_TO_RX1) |(IS_PA_TO_RX2)| \ - (IS_PA_TO_TX1) |(IS_PA_TO_TX2)| \ - (IS_MAC1) |(IS_MAC2) | \ - (IS_R1_C) |(IS_R2_C) | \ - (IS_XS1_C) |(IS_XA1_C) | \ - (IS_XS2_C) |(IS_XA2_C)) - -#define IRQ_HWE_MASK (IS_ERR_MSK) /* enable all HW irqs */ - -typedef struct s_DevNet DEV_NET; - -struct s_DevNet { - int PortNr; - int NetNr; - SK_AC *pAC; -}; - -typedef struct s_TxPort TX_PORT; - -struct s_TxPort { - /* the transmit descriptor rings */ - caddr_t pTxDescrRing; /* descriptor area memory */ - SK_U64 VTxDescrRing; /* descr. area bus virt. addr. */ - TXD *pTxdRingHead; /* Head of Tx rings */ - TXD *pTxdRingTail; /* Tail of Tx rings */ - TXD *pTxdRingPrev; /* descriptor sent previously */ - int TxdRingFree; /* # of free entrys */ - spinlock_t TxDesRingLock; /* serialize descriptor accesses */ - SK_IOC HwAddr; /* bmu registers address */ - int PortIndex; /* index number of port (0 or 1) */ -}; - -typedef struct s_RxPort RX_PORT; - -struct s_RxPort { - /* the receive descriptor rings */ - caddr_t pRxDescrRing; /* descriptor area memory */ - SK_U64 VRxDescrRing; /* descr. area bus virt. addr. */ - RXD *pRxdRingHead; /* Head of Rx rings */ - RXD *pRxdRingTail; /* Tail of Rx rings */ - RXD *pRxdRingPrev; /* descriptor given to BMU previously */ - int RxdRingFree; /* # of free entrys */ - int RxCsum; /* use receive checksum hardware */ - spinlock_t RxDesRingLock; /* serialize descriptor accesses */ - int RxFillLimit; /* limit for buffers in ring */ - SK_IOC HwAddr; /* bmu registers address */ - int PortIndex; /* index number of port (0 or 1) */ -}; - -/* Definitions needed for interrupt moderation *******************************/ - -#define IRQ_EOF_AS_TX ((IS_XA1_F) | (IS_XA2_F)) -#define IRQ_EOF_SY_TX ((IS_XS1_F) | (IS_XS2_F)) -#define IRQ_MASK_TX_ONLY ((IRQ_EOF_AS_TX)| (IRQ_EOF_SY_TX)) -#define IRQ_MASK_RX_ONLY ((IS_R1_F) | (IS_R2_F)) -#define IRQ_MASK_SP_ONLY (SPECIAL_IRQS) -#define IRQ_MASK_TX_RX ((IRQ_MASK_TX_ONLY)| (IRQ_MASK_RX_ONLY)) -#define IRQ_MASK_SP_RX ((SPECIAL_IRQS) | (IRQ_MASK_RX_ONLY)) -#define IRQ_MASK_SP_TX ((SPECIAL_IRQS) | (IRQ_MASK_TX_ONLY)) -#define IRQ_MASK_RX_TX_SP ((SPECIAL_IRQS) | (IRQ_MASK_TX_RX)) - -#define C_INT_MOD_NONE 1 -#define C_INT_MOD_STATIC 2 -#define C_INT_MOD_DYNAMIC 4 - -#define C_CLK_FREQ_GENESIS 53215000 /* shorter: 53.125 MHz */ -#define C_CLK_FREQ_YUKON 78215000 /* shorter: 78.125 MHz */ - -#define C_INTS_PER_SEC_DEFAULT 2000 -#define C_INT_MOD_ENABLE_PERCENTAGE 50 /* if higher 50% enable */ -#define C_INT_MOD_DISABLE_PERCENTAGE 50 /* if lower 50% disable */ -#define C_INT_MOD_IPS_LOWER_RANGE 30 -#define C_INT_MOD_IPS_UPPER_RANGE 40000 - - -typedef struct s_DynIrqModInfo DIM_INFO; -struct s_DynIrqModInfo { - unsigned long PrevTimeVal; - unsigned int PrevSysLoad; - unsigned int PrevUsedTime; - unsigned int PrevTotalTime; - int PrevUsedDescrRatio; - int NbrProcessedDescr; - SK_U64 PrevPort0RxIntrCts; - SK_U64 PrevPort1RxIntrCts; - SK_U64 PrevPort0TxIntrCts; - SK_U64 PrevPort1TxIntrCts; - SK_BOOL ModJustEnabled; /* Moderation just enabled yes/no */ - - int MaxModIntsPerSec; /* Moderation Threshold */ - int MaxModIntsPerSecUpperLimit; /* Upper limit for DIM */ - int MaxModIntsPerSecLowerLimit; /* Lower limit for DIM */ - - long MaskIrqModeration; /* ModIrqType (eg. 'TxRx') */ - SK_BOOL DisplayStats; /* Stats yes/no */ - SK_BOOL AutoSizing; /* Resize DIM-timer on/off */ - int IntModTypeSelect; /* EnableIntMod (eg. 'dynamic') */ - - SK_TIMER ModTimer; /* just some timer */ -}; - -typedef struct s_PerStrm PER_STRM; - -#define SK_ALLOC_IRQ 0x00000001 - -#ifdef SK_DIAG_SUPPORT -#define DIAG_ACTIVE 1 -#define DIAG_NOTACTIVE 0 -#endif - -/**************************************************************************** - * Per board structure / Adapter Context structure: - * Allocated within attach(9e) and freed within detach(9e). - * Contains all 'per device' necessary handles, flags, locks etc.: - */ -struct s_AC { - SK_GEINIT GIni; /* GE init struct */ - SK_PNMI Pnmi; /* PNMI data struct */ - SK_VPD vpd; /* vpd data struct */ - SK_QUEUE Event; /* Event queue */ - SK_HWT Hwt; /* Hardware Timer control struct */ - SK_TIMCTRL Tim; /* Software Timer control struct */ - SK_I2C I2c; /* I2C relevant data structure */ - SK_ADDR Addr; /* for Address module */ - SK_CSUM Csum; /* for checksum module */ - SK_RLMT Rlmt; /* for rlmt module */ - spinlock_t SlowPathLock; /* Normal IRQ lock */ - struct timer_list BlinkTimer; /* for LED blinking */ - int LedsOn; - SK_PNMI_STRUCT_DATA PnmiStruct; /* structure to get all Pnmi-Data */ - int RlmtMode; /* link check mode to set */ - int RlmtNets; /* Number of nets */ - - SK_IOC IoBase; /* register set of adapter */ - int BoardLevel; /* level of active hw init (0-2) */ - - SK_U32 AllocFlag; /* flag allocation of resources */ - struct pci_dev *PciDev; /* for access to pci config space */ - struct SK_NET_DEVICE *dev[2]; /* pointer to device struct */ - - int RxBufSize; /* length of receive buffers */ - struct net_device_stats stats; /* linux 'netstat -i' statistics */ - int Index; /* internal board index number */ - - /* adapter RAM sizes for queues of active port */ - int RxQueueSize; /* memory used for receive queue */ - int TxSQueueSize; /* memory used for sync. tx queue */ - int TxAQueueSize; /* memory used for async. tx queue */ - - int PromiscCount; /* promiscuous mode counter */ - int AllMultiCount; /* allmulticast mode counter */ - int MulticCount; /* number of different MC */ - /* addresses for this board */ - /* (may be more than HW can)*/ - - int HWRevision; /* Hardware revision */ - int ActivePort; /* the active XMAC port */ - int MaxPorts; /* number of activated ports */ - int TxDescrPerRing; /* # of descriptors per tx ring */ - int RxDescrPerRing; /* # of descriptors per rx ring */ - - caddr_t pDescrMem; /* Pointer to the descriptor area */ - dma_addr_t pDescrMemDMA; /* PCI DMA address of area */ - - /* the port structures with descriptor rings */ - TX_PORT TxPort[SK_MAX_MACS][2]; - RX_PORT RxPort[SK_MAX_MACS]; - - SK_BOOL CheckQueue; /* check event queue soon */ - SK_TIMER DrvCleanupTimer;/* to check for pending descriptors */ - DIM_INFO DynIrqModInfo; /* all data related to DIM */ - - /* Only for tests */ - int PortDown; - int ChipsetType; /* Chipset family type - * 0 == Genesis family support - * 1 == Yukon family support - */ -#ifdef SK_DIAG_SUPPORT - SK_U32 DiagModeActive; /* is diag active? */ - SK_BOOL DiagFlowCtrl; /* for control purposes */ - SK_PNMI_STRUCT_DATA PnmiBackup; /* backup structure for all Pnmi-Data */ - SK_BOOL WasIfUp[SK_MAX_MACS]; /* for OpenClose while - * DIAG is busy with NIC - */ -#endif - -}; - - -#endif /* __INC_SKDRV2ND_H */ - diff --git a/drivers/net/sk98lin/h/skerror.h b/drivers/net/sk98lin/h/skerror.h deleted file mode 100644 index da062f76623..00000000000 --- a/drivers/net/sk98lin/h/skerror.h +++ /dev/null @@ -1,55 +0,0 @@ -/****************************************************************************** - * - * Name: skerror.h - * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.7 $ - * Date: $Date: 2003/05/13 17:25:13 $ - * Purpose: SK specific Error log support - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#ifndef _INC_SKERROR_H_ -#define _INC_SKERROR_H_ - -/* - * Define Error Classes - */ -#define SK_ERRCL_OTHER (0) /* Other error */ -#define SK_ERRCL_CONFIG (1L<<0) /* Configuration error */ -#define SK_ERRCL_INIT (1L<<1) /* Initialization error */ -#define SK_ERRCL_NORES (1L<<2) /* Out of Resources error */ -#define SK_ERRCL_SW (1L<<3) /* Internal Software error */ -#define SK_ERRCL_HW (1L<<4) /* Hardware Failure */ -#define SK_ERRCL_COMM (1L<<5) /* Communication error */ - - -/* - * Define Error Code Bases - */ -#define SK_ERRBASE_RLMT 100 /* Base Error number for RLMT */ -#define SK_ERRBASE_HWINIT 200 /* Base Error number for HWInit */ -#define SK_ERRBASE_VPD 300 /* Base Error number for VPD */ -#define SK_ERRBASE_PNMI 400 /* Base Error number for PNMI */ -#define SK_ERRBASE_CSUM 500 /* Base Error number for Checksum */ -#define SK_ERRBASE_SIRQ 600 /* Base Error number for Special IRQ */ -#define SK_ERRBASE_I2C 700 /* Base Error number for I2C module */ -#define SK_ERRBASE_QUEUE 800 /* Base Error number for Scheduler */ -#define SK_ERRBASE_ADDR 900 /* Base Error number for Address module */ -#define SK_ERRBASE_PECP 1000 /* Base Error number for PECP */ -#define SK_ERRBASE_DRV 1100 /* Base Error number for Driver */ - -#endif /* _INC_SKERROR_H_ */ diff --git a/drivers/net/sk98lin/h/skgedrv.h b/drivers/net/sk98lin/h/skgedrv.h deleted file mode 100644 index 44fd4c3de81..00000000000 --- a/drivers/net/sk98lin/h/skgedrv.h +++ /dev/null @@ -1,51 +0,0 @@ -/****************************************************************************** - * - * Name: skgedrv.h - * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.10 $ - * Date: $Date: 2003/07/04 12:25:01 $ - * Purpose: Interface with the driver - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#ifndef __INC_SKGEDRV_H_ -#define __INC_SKGEDRV_H_ - -/* defines ********************************************************************/ - -/* - * Define the driver events. - * Usually the events are defined by the destination module. - * In case of the driver we put the definition of the events here. - */ -#define SK_DRV_PORT_RESET 1 /* The port needs to be reset */ -#define SK_DRV_NET_UP 2 /* The net is operational */ -#define SK_DRV_NET_DOWN 3 /* The net is down */ -#define SK_DRV_SWITCH_SOFT 4 /* Ports switch with both links connected */ -#define SK_DRV_SWITCH_HARD 5 /* Port switch due to link failure */ -#define SK_DRV_RLMT_SEND 6 /* Send a RLMT packet */ -#define SK_DRV_ADAP_FAIL 7 /* The whole adapter fails */ -#define SK_DRV_PORT_FAIL 8 /* One port fails */ -#define SK_DRV_SWITCH_INTERN 9 /* Port switch by the driver itself */ -#define SK_DRV_POWER_DOWN 10 /* Power down mode */ -#define SK_DRV_TIMER 11 /* Timer for free use */ -#ifdef SK_NO_RLMT -#define SK_DRV_LINK_UP 12 /* Link Up event for driver */ -#define SK_DRV_LINK_DOWN 13 /* Link Down event for driver */ -#endif -#define SK_DRV_DOWNSHIFT_DET 14 /* Downshift 4-Pair / 2-Pair (YUKON only) */ -#endif /* __INC_SKGEDRV_H_ */ diff --git a/drivers/net/sk98lin/h/skgehw.h b/drivers/net/sk98lin/h/skgehw.h deleted file mode 100644 index f6282b7956d..00000000000 --- a/drivers/net/sk98lin/h/skgehw.h +++ /dev/null @@ -1,2126 +0,0 @@ -/****************************************************************************** - * - * Name: skgehw.h - * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.56 $ - * Date: $Date: 2003/09/23 09:01:00 $ - * Purpose: Defines and Macros for the Gigabit Ethernet Adapter Product Family - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#ifndef __INC_SKGEHW_H -#define __INC_SKGEHW_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* defines ********************************************************************/ - -#define BIT_31 (1UL << 31) -#define BIT_30 (1L << 30) -#define BIT_29 (1L << 29) -#define BIT_28 (1L << 28) -#define BIT_27 (1L << 27) -#define BIT_26 (1L << 26) -#define BIT_25 (1L << 25) -#define BIT_24 (1L << 24) -#define BIT_23 (1L << 23) -#define BIT_22 (1L << 22) -#define BIT_21 (1L << 21) -#define BIT_20 (1L << 20) -#define BIT_19 (1L << 19) -#define BIT_18 (1L << 18) -#define BIT_17 (1L << 17) -#define BIT_16 (1L << 16) -#define BIT_15 (1L << 15) -#define BIT_14 (1L << 14) -#define BIT_13 (1L << 13) -#define BIT_12 (1L << 12) -#define BIT_11 (1L << 11) -#define BIT_10 (1L << 10) -#define BIT_9 (1L << 9) -#define BIT_8 (1L << 8) -#define BIT_7 (1L << 7) -#define BIT_6 (1L << 6) -#define BIT_5 (1L << 5) -#define BIT_4 (1L << 4) -#define BIT_3 (1L << 3) -#define BIT_2 (1L << 2) -#define BIT_1 (1L << 1) -#define BIT_0 1L - -#define BIT_15S (1U << 15) -#define BIT_14S (1 << 14) -#define BIT_13S (1 << 13) -#define BIT_12S (1 << 12) -#define BIT_11S (1 << 11) -#define BIT_10S (1 << 10) -#define BIT_9S (1 << 9) -#define BIT_8S (1 << 8) -#define BIT_7S (1 << 7) -#define BIT_6S (1 << 6) -#define BIT_5S (1 << 5) -#define BIT_4S (1 << 4) -#define BIT_3S (1 << 3) -#define BIT_2S (1 << 2) -#define BIT_1S (1 << 1) -#define BIT_0S 1 - -#define SHIFT31(x) ((x) << 31) -#define SHIFT30(x) ((x) << 30) -#define SHIFT29(x) ((x) << 29) -#define SHIFT28(x) ((x) << 28) -#define SHIFT27(x) ((x) << 27) -#define SHIFT26(x) ((x) << 26) -#define SHIFT25(x) ((x) << 25) -#define SHIFT24(x) ((x) << 24) -#define SHIFT23(x) ((x) << 23) -#define SHIFT22(x) ((x) << 22) -#define SHIFT21(x) ((x) << 21) -#define SHIFT20(x) ((x) << 20) -#define SHIFT19(x) ((x) << 19) -#define SHIFT18(x) ((x) << 18) -#define SHIFT17(x) ((x) << 17) -#define SHIFT16(x) ((x) << 16) -#define SHIFT15(x) ((x) << 15) -#define SHIFT14(x) ((x) << 14) -#define SHIFT13(x) ((x) << 13) -#define SHIFT12(x) ((x) << 12) -#define SHIFT11(x) ((x) << 11) -#define SHIFT10(x) ((x) << 10) -#define SHIFT9(x) ((x) << 9) -#define SHIFT8(x) ((x) << 8) -#define SHIFT7(x) ((x) << 7) -#define SHIFT6(x) ((x) << 6) -#define SHIFT5(x) ((x) << 5) -#define SHIFT4(x) ((x) << 4) -#define SHIFT3(x) ((x) << 3) -#define SHIFT2(x) ((x) << 2) -#define SHIFT1(x) ((x) << 1) -#define SHIFT0(x) ((x) << 0) - -/* - * Configuration Space header - * Since this module is used for different OS', those may be - * duplicate on some of them (e.g. Linux). But to keep the - * common source, we have to live with this... - */ -#define PCI_VENDOR_ID 0x00 /* 16 bit Vendor ID */ -#define PCI_DEVICE_ID 0x02 /* 16 bit Device ID */ -#define PCI_COMMAND 0x04 /* 16 bit Command */ -#define PCI_STATUS 0x06 /* 16 bit Status */ -#define PCI_REV_ID 0x08 /* 8 bit Revision ID */ -#define PCI_CLASS_CODE 0x09 /* 24 bit Class Code */ -#define PCI_CACHE_LSZ 0x0c /* 8 bit Cache Line Size */ -#define PCI_LAT_TIM 0x0d /* 8 bit Latency Timer */ -#define PCI_HEADER_T 0x0e /* 8 bit Header Type */ -#define PCI_BIST 0x0f /* 8 bit Built-in selftest */ -#define PCI_BASE_1ST 0x10 /* 32 bit 1st Base address */ -#define PCI_BASE_2ND 0x14 /* 32 bit 2nd Base address */ - /* Byte 0x18..0x2b: reserved */ -#define PCI_SUB_VID 0x2c /* 16 bit Subsystem Vendor ID */ -#define PCI_SUB_ID 0x2e /* 16 bit Subsystem ID */ -#define PCI_BASE_ROM 0x30 /* 32 bit Expansion ROM Base Address */ -#define PCI_CAP_PTR 0x34 /* 8 bit Capabilities Ptr */ - /* Byte 0x35..0x3b: reserved */ -#define PCI_IRQ_LINE 0x3c /* 8 bit Interrupt Line */ -#define PCI_IRQ_PIN 0x3d /* 8 bit Interrupt Pin */ -#define PCI_MIN_GNT 0x3e /* 8 bit Min_Gnt */ -#define PCI_MAX_LAT 0x3f /* 8 bit Max_Lat */ - /* Device Dependent Region */ -#define PCI_OUR_REG_1 0x40 /* 32 bit Our Register 1 */ -#define PCI_OUR_REG_2 0x44 /* 32 bit Our Register 2 */ - /* Power Management Region */ -#define PCI_PM_CAP_ID 0x48 /* 8 bit Power Management Cap. ID */ -#define PCI_PM_NITEM 0x49 /* 8 bit Next Item Ptr */ -#define PCI_PM_CAP_REG 0x4a /* 16 bit Power Management Capabilities */ -#define PCI_PM_CTL_STS 0x4c /* 16 bit Power Manag. Control/Status */ - /* Byte 0x4e: reserved */ -#define PCI_PM_DAT_REG 0x4f /* 8 bit Power Manag. Data Register */ - /* VPD Region */ -#define PCI_VPD_CAP_ID 0x50 /* 8 bit VPD Cap. ID */ -#define PCI_VPD_NITEM 0x51 /* 8 bit Next Item Ptr */ -#define PCI_VPD_ADR_REG 0x52 /* 16 bit VPD Address Register */ -#define PCI_VPD_DAT_REG 0x54 /* 32 bit VPD Data Register */ - /* Byte 0x58..0x59: reserved */ -#define PCI_SER_LD_CTRL 0x5a /* 16 bit SEEPROM Loader Ctrl (YUKON only) */ - /* Byte 0x5c..0xff: reserved */ - -/* - * I2C Address (PCI Config) - * - * Note: The temperature and voltage sensors are relocated on a different - * I2C bus. - */ -#define I2C_ADDR_VPD 0xa0 /* I2C address for the VPD EEPROM */ - -/* - * Define Bits and Values of the registers - */ -/* PCI_COMMAND 16 bit Command */ - /* Bit 15..11: reserved */ -#define PCI_INT_DIS BIT_10S /* Interrupt INTx# disable (PCI 2.3) */ -#define PCI_FBTEN BIT_9S /* Fast Back-To-Back enable */ -#define PCI_SERREN BIT_8S /* SERR enable */ -#define PCI_ADSTEP BIT_7S /* Address Stepping */ -#define PCI_PERREN BIT_6S /* Parity Report Response enable */ -#define PCI_VGA_SNOOP BIT_5S /* VGA palette snoop */ -#define PCI_MWIEN BIT_4S /* Memory write an inv cycl ena */ -#define PCI_SCYCEN BIT_3S /* Special Cycle enable */ -#define PCI_BMEN BIT_2S /* Bus Master enable */ -#define PCI_MEMEN BIT_1S /* Memory Space Access enable */ -#define PCI_IOEN BIT_0S /* I/O Space Access enable */ - -#define PCI_COMMAND_VAL (PCI_FBTEN | PCI_SERREN | PCI_PERREN | PCI_MWIEN |\ - PCI_BMEN | PCI_MEMEN | PCI_IOEN) - -/* PCI_STATUS 16 bit Status */ -#define PCI_PERR BIT_15S /* Parity Error */ -#define PCI_SERR BIT_14S /* Signaled SERR */ -#define PCI_RMABORT BIT_13S /* Received Master Abort */ -#define PCI_RTABORT BIT_12S /* Received Target Abort */ - /* Bit 11: reserved */ -#define PCI_DEVSEL (3<<9) /* Bit 10.. 9: DEVSEL Timing */ -#define PCI_DEV_FAST (0<<9) /* fast */ -#define PCI_DEV_MEDIUM (1<<9) /* medium */ -#define PCI_DEV_SLOW (2<<9) /* slow */ -#define PCI_DATAPERR BIT_8S /* DATA Parity error detected */ -#define PCI_FB2BCAP BIT_7S /* Fast Back-to-Back Capability */ -#define PCI_UDF BIT_6S /* User Defined Features */ -#define PCI_66MHZCAP BIT_5S /* 66 MHz PCI bus clock capable */ -#define PCI_NEWCAP BIT_4S /* New cap. list implemented */ -#define PCI_INT_STAT BIT_3S /* Interrupt INTx# Status (PCI 2.3) */ - /* Bit 2.. 0: reserved */ - -#define PCI_ERRBITS (PCI_PERR | PCI_SERR | PCI_RMABORT | PCI_RTABORT |\ - PCI_DATAPERR) - -/* PCI_CLASS_CODE 24 bit Class Code */ -/* Byte 2: Base Class (02) */ -/* Byte 1: SubClass (00) */ -/* Byte 0: Programming Interface (00) */ - -/* PCI_CACHE_LSZ 8 bit Cache Line Size */ -/* Possible values: 0,2,4,8,16,32,64,128 */ - -/* PCI_HEADER_T 8 bit Header Type */ -#define PCI_HD_MF_DEV BIT_7S /* 0= single, 1= multi-func dev */ -#define PCI_HD_TYPE 0x7f /* Bit 6..0: Header Layout 0= normal */ - -/* PCI_BIST 8 bit Built-in selftest */ -/* Built-in Self test not supported (optional) */ - -/* PCI_BASE_1ST 32 bit 1st Base address */ -#define PCI_MEMSIZE 0x4000L /* use 16 kB Memory Base */ -#define PCI_MEMBASE_MSK 0xffffc000L /* Bit 31..14: Memory Base Address */ -#define PCI_MEMSIZE_MSK 0x00003ff0L /* Bit 13.. 4: Memory Size Req. */ -#define PCI_PREFEN BIT_3 /* Prefetchable */ -#define PCI_MEM_TYP (3L<<2) /* Bit 2.. 1: Memory Type */ -#define PCI_MEM32BIT (0L<<1) /* Base addr anywhere in 32 Bit range */ -#define PCI_MEM1M (1L<<1) /* Base addr below 1 MegaByte */ -#define PCI_MEM64BIT (2L<<1) /* Base addr anywhere in 64 Bit range */ -#define PCI_MEMSPACE BIT_0 /* Memory Space Indicator */ - -/* PCI_BASE_2ND 32 bit 2nd Base address */ -#define PCI_IOBASE 0xffffff00L /* Bit 31.. 8: I/O Base address */ -#define PCI_IOSIZE 0x000000fcL /* Bit 7.. 2: I/O Size Requirements */ - /* Bit 1: reserved */ -#define PCI_IOSPACE BIT_0 /* I/O Space Indicator */ - -/* PCI_BASE_ROM 32 bit Expansion ROM Base Address */ -#define PCI_ROMBASE_MSK 0xfffe0000L /* Bit 31..17: ROM Base address */ -#define PCI_ROMBASE_SIZ (0x1cL<<14) /* Bit 16..14: Treat as Base or Size */ -#define PCI_ROMSIZE (0x38L<<11) /* Bit 13..11: ROM Size Requirements */ - /* Bit 10.. 1: reserved */ -#define PCI_ROMEN BIT_0 /* Address Decode enable */ - -/* Device Dependent Region */ -/* PCI_OUR_REG_1 32 bit Our Register 1 */ - /* Bit 31..29: reserved */ -#define PCI_PHY_COMA BIT_28 /* Set PHY to Coma Mode (YUKON only) */ -#define PCI_TEST_CAL BIT_27 /* Test PCI buffer calib. (YUKON only) */ -#define PCI_EN_CAL BIT_26 /* Enable PCI buffer calib. (YUKON only) */ -#define PCI_VIO BIT_25 /* PCI I/O Voltage, 0 = 3.3V, 1 = 5V */ -#define PCI_DIS_BOOT BIT_24 /* Disable BOOT via ROM */ -#define PCI_EN_IO BIT_23 /* Mapping to I/O space */ -#define PCI_EN_FPROM BIT_22 /* Enable FLASH mapping to memory */ - /* 1 = Map Flash to memory */ - /* 0 = Disable addr. dec */ -#define PCI_PAGESIZE (3L<<20) /* Bit 21..20: FLASH Page Size */ -#define PCI_PAGE_16 (0L<<20) /* 16 k pages */ -#define PCI_PAGE_32K (1L<<20) /* 32 k pages */ -#define PCI_PAGE_64K (2L<<20) /* 64 k pages */ -#define PCI_PAGE_128K (3L<<20) /* 128 k pages */ - /* Bit 19: reserved */ -#define PCI_PAGEREG (7L<<16) /* Bit 18..16: Page Register */ -#define PCI_NOTAR BIT_15 /* No turnaround cycle */ -#define PCI_FORCE_BE BIT_14 /* Assert all BEs on MR */ -#define PCI_DIS_MRL BIT_13 /* Disable Mem Read Line */ -#define PCI_DIS_MRM BIT_12 /* Disable Mem Read Multiple */ -#define PCI_DIS_MWI BIT_11 /* Disable Mem Write & Invalidate */ -#define PCI_DISC_CLS BIT_10 /* Disc: cacheLsz bound */ -#define PCI_BURST_DIS BIT_9 /* Burst Disable */ -#define PCI_DIS_PCI_CLK BIT_8 /* Disable PCI clock driving */ -#define PCI_SKEW_DAS (0xfL<<4) /* Bit 7.. 4: Skew Ctrl, DAS Ext */ -#define PCI_SKEW_BASE 0xfL /* Bit 3.. 0: Skew Ctrl, Base */ - - -/* PCI_OUR_REG_2 32 bit Our Register 2 */ -#define PCI_VPD_WR_THR (0xffL<<24) /* Bit 31..24: VPD Write Threshold */ -#define PCI_DEV_SEL (0x7fL<<17) /* Bit 23..17: EEPROM Device Select */ -#define PCI_VPD_ROM_SZ (7L<<14) /* Bit 16..14: VPD ROM Size */ - /* Bit 13..12: reserved */ -#define PCI_PATCH_DIR (0xfL<<8) /* Bit 11.. 8: Ext Patches dir 3..0 */ -#define PCI_PATCH_DIR_3 BIT_11 -#define PCI_PATCH_DIR_2 BIT_10 -#define PCI_PATCH_DIR_1 BIT_9 -#define PCI_PATCH_DIR_0 BIT_8 -#define PCI_EXT_PATCHS (0xfL<<4) /* Bit 7.. 4: Extended Patches 3..0 */ -#define PCI_EXT_PATCH_3 BIT_7 -#define PCI_EXT_PATCH_2 BIT_6 -#define PCI_EXT_PATCH_1 BIT_5 -#define PCI_EXT_PATCH_0 BIT_4 -#define PCI_EN_DUMMY_RD BIT_3 /* Enable Dummy Read */ -#define PCI_REV_DESC BIT_2 /* Reverse Desc. Bytes */ - /* Bit 1: reserved */ -#define PCI_USEDATA64 BIT_0 /* Use 64Bit Data bus ext */ - - -/* Power Management Region */ -/* PCI_PM_CAP_REG 16 bit Power Management Capabilities */ -#define PCI_PME_SUP_MSK (0x1f<<11) /* Bit 15..11: PM Event Support Mask */ -#define PCI_PME_D3C_SUP BIT_15S /* PME from D3cold Support (if Vaux) */ -#define PCI_PME_D3H_SUP BIT_14S /* PME from D3hot Support */ -#define PCI_PME_D2_SUP BIT_13S /* PME from D2 Support */ -#define PCI_PME_D1_SUP BIT_12S /* PME from D1 Support */ -#define PCI_PME_D0_SUP BIT_11S /* PME from D0 Support */ -#define PCI_PM_D2_SUP BIT_10S /* D2 Support in 33 MHz mode */ -#define PCI_PM_D1_SUP BIT_9S /* D1 Support */ - /* Bit 8.. 6: reserved */ -#define PCI_PM_DSI BIT_5S /* Device Specific Initialization */ -#define PCI_PM_APS BIT_4S /* Auxialiary Power Source */ -#define PCI_PME_CLOCK BIT_3S /* PM Event Clock */ -#define PCI_PM_VER_MSK 7 /* Bit 2.. 0: PM PCI Spec. version */ - -/* PCI_PM_CTL_STS 16 bit Power Management Control/Status */ -#define PCI_PME_STATUS BIT_15S /* PME Status (YUKON only) */ -#define PCI_PM_DAT_SCL (3<<13) /* Bit 14..13: Data Reg. scaling factor */ -#define PCI_PM_DAT_SEL (0xf<<9) /* Bit 12.. 9: PM data selector field */ -#define PCI_PME_EN BIT_8S /* Enable PME# generation (YUKON only) */ - /* Bit 7.. 2: reserved */ -#define PCI_PM_STATE_MSK 3 /* Bit 1.. 0: Power Management State */ - -#define PCI_PM_STATE_D0 0 /* D0: Operational (default) */ -#define PCI_PM_STATE_D1 1 /* D1: (YUKON only) */ -#define PCI_PM_STATE_D2 2 /* D2: (YUKON only) */ -#define PCI_PM_STATE_D3 3 /* D3: HOT, Power Down and Reset */ - -/* VPD Region */ -/* PCI_VPD_ADR_REG 16 bit VPD Address Register */ -#define PCI_VPD_FLAG BIT_15S /* starts VPD rd/wr cycle */ -#define PCI_VPD_ADR_MSK 0x7fffL /* Bit 14.. 0: VPD address mask */ - -/* Control Register File (Address Map) */ - -/* - * Bank 0 - */ -#define B0_RAP 0x0000 /* 8 bit Register Address Port */ - /* 0x0001 - 0x0003: reserved */ -#define B0_CTST 0x0004 /* 16 bit Control/Status register */ -#define B0_LED 0x0006 /* 8 Bit LED register */ -#define B0_POWER_CTRL 0x0007 /* 8 Bit Power Control reg (YUKON only) */ -#define B0_ISRC 0x0008 /* 32 bit Interrupt Source Register */ -#define B0_IMSK 0x000c /* 32 bit Interrupt Mask Register */ -#define B0_HWE_ISRC 0x0010 /* 32 bit HW Error Interrupt Src Reg */ -#define B0_HWE_IMSK 0x0014 /* 32 bit HW Error Interrupt Mask Reg */ -#define B0_SP_ISRC 0x0018 /* 32 bit Special Interrupt Source Reg */ - /* 0x001c: reserved */ - -/* B0 XMAC 1 registers (GENESIS only) */ -#define B0_XM1_IMSK 0x0020 /* 16 bit r/w XMAC 1 Interrupt Mask Register*/ - /* 0x0022 - 0x0027: reserved */ -#define B0_XM1_ISRC 0x0028 /* 16 bit ro XMAC 1 Interrupt Status Reg */ - /* 0x002a - 0x002f: reserved */ -#define B0_XM1_PHY_ADDR 0x0030 /* 16 bit r/w XMAC 1 PHY Address Register */ - /* 0x0032 - 0x0033: reserved */ -#define B0_XM1_PHY_DATA 0x0034 /* 16 bit r/w XMAC 1 PHY Data Register */ - /* 0x0036 - 0x003f: reserved */ - -/* B0 XMAC 2 registers (GENESIS only) */ -#define B0_XM2_IMSK 0x0040 /* 16 bit r/w XMAC 2 Interrupt Mask Register*/ - /* 0x0042 - 0x0047: reserved */ -#define B0_XM2_ISRC 0x0048 /* 16 bit ro XMAC 2 Interrupt Status Reg */ - /* 0x004a - 0x004f: reserved */ -#define B0_XM2_PHY_ADDR 0x0050 /* 16 bit r/w XMAC 2 PHY Address Register */ - /* 0x0052 - 0x0053: reserved */ -#define B0_XM2_PHY_DATA 0x0054 /* 16 bit r/w XMAC 2 PHY Data Register */ - /* 0x0056 - 0x005f: reserved */ - -/* BMU Control Status Registers */ -#define B0_R1_CSR 0x0060 /* 32 bit BMU Ctrl/Stat Rx Queue 1 */ -#define B0_R2_CSR 0x0064 /* 32 bit BMU Ctrl/Stat Rx Queue 2 */ -#define B0_XS1_CSR 0x0068 /* 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */ -#define B0_XA1_CSR 0x006c /* 32 bit BMU Ctrl/Stat Async Tx Queue 1*/ -#define B0_XS2_CSR 0x0070 /* 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */ -#define B0_XA2_CSR 0x0074 /* 32 bit BMU Ctrl/Stat Async Tx Queue 2*/ - /* 0x0078 - 0x007f: reserved */ - -/* - * Bank 1 - * - completely empty (this is the RAP Block window) - * Note: if RAP = 1 this page is reserved - */ - -/* - * Bank 2 - */ -/* NA reg = 48 bit Network Address Register, 3x16 or 8x8 bit readable */ -#define B2_MAC_1 0x0100 /* NA reg MAC Address 1 */ - /* 0x0106 - 0x0107: reserved */ -#define B2_MAC_2 0x0108 /* NA reg MAC Address 2 */ - /* 0x010e - 0x010f: reserved */ -#define B2_MAC_3 0x0110 /* NA reg MAC Address 3 */ - /* 0x0116 - 0x0117: reserved */ -#define B2_CONN_TYP 0x0118 /* 8 bit Connector type */ -#define B2_PMD_TYP 0x0119 /* 8 bit PMD type */ -#define B2_MAC_CFG 0x011a /* 8 bit MAC Configuration / Chip Revision */ -#define B2_CHIP_ID 0x011b /* 8 bit Chip Identification Number */ - /* Eprom registers are currently of no use */ -#define B2_E_0 0x011c /* 8 bit EPROM Byte 0 (ext. SRAM size */ -#define B2_E_1 0x011d /* 8 bit EPROM Byte 1 (PHY type) */ -#define B2_E_2 0x011e /* 8 bit EPROM Byte 2 */ -#define B2_E_3 0x011f /* 8 bit EPROM Byte 3 */ -#define B2_FAR 0x0120 /* 32 bit Flash-Prom Addr Reg/Cnt */ -#define B2_FDP 0x0124 /* 8 bit Flash-Prom Data Port */ - /* 0x0125 - 0x0127: reserved */ -#define B2_LD_CTRL 0x0128 /* 8 bit EPROM loader control register */ -#define B2_LD_TEST 0x0129 /* 8 bit EPROM loader test register */ - /* 0x012a - 0x012f: reserved */ -#define B2_TI_INI 0x0130 /* 32 bit Timer Init Value */ -#define B2_TI_VAL 0x0134 /* 32 bit Timer Value */ -#define B2_TI_CTRL 0x0138 /* 8 bit Timer Control */ -#define B2_TI_TEST 0x0139 /* 8 Bit Timer Test */ - /* 0x013a - 0x013f: reserved */ -#define B2_IRQM_INI 0x0140 /* 32 bit IRQ Moderation Timer Init Reg.*/ -#define B2_IRQM_VAL 0x0144 /* 32 bit IRQ Moderation Timer Value */ -#define B2_IRQM_CTRL 0x0148 /* 8 bit IRQ Moderation Timer Control */ -#define B2_IRQM_TEST 0x0149 /* 8 bit IRQ Moderation Timer Test */ -#define B2_IRQM_MSK 0x014c /* 32 bit IRQ Moderation Mask */ -#define B2_IRQM_HWE_MSK 0x0150 /* 32 bit IRQ Moderation HW Error Mask */ - /* 0x0154 - 0x0157: reserved */ -#define B2_TST_CTRL1 0x0158 /* 8 bit Test Control Register 1 */ -#define B2_TST_CTRL2 0x0159 /* 8 bit Test Control Register 2 */ - /* 0x015a - 0x015b: reserved */ -#define B2_GP_IO 0x015c /* 32 bit General Purpose I/O Register */ -#define B2_I2C_CTRL 0x0160 /* 32 bit I2C HW Control Register */ -#define B2_I2C_DATA 0x0164 /* 32 bit I2C HW Data Register */ -#define B2_I2C_IRQ 0x0168 /* 32 bit I2C HW IRQ Register */ -#define B2_I2C_SW 0x016c /* 32 bit I2C SW Port Register */ - -/* Blink Source Counter (GENESIS only) */ -#define B2_BSC_INI 0x0170 /* 32 bit Blink Source Counter Init Val */ -#define B2_BSC_VAL 0x0174 /* 32 bit Blink Source Counter Value */ -#define B2_BSC_CTRL 0x0178 /* 8 bit Blink Source Counter Control */ -#define B2_BSC_STAT 0x0179 /* 8 bit Blink Source Counter Status */ -#define B2_BSC_TST 0x017a /* 16 bit Blink Source Counter Test Reg */ - /* 0x017c - 0x017f: reserved */ - -/* - * Bank 3 - */ -/* RAM Random Registers */ -#define B3_RAM_ADDR 0x0180 /* 32 bit RAM Address, to read or write */ -#define B3_RAM_DATA_LO 0x0184 /* 32 bit RAM Data Word (low dWord) */ -#define B3_RAM_DATA_HI 0x0188 /* 32 bit RAM Data Word (high dWord) */ - /* 0x018c - 0x018f: reserved */ - -/* RAM Interface Registers */ -/* - * The HW-Spec. calls this registers Timeout Value 0..11. But this names are - * not usable in SW. Please notice these are NOT real timeouts, these are - * the number of qWords transferred continuously. - */ -#define B3_RI_WTO_R1 0x0190 /* 8 bit WR Timeout Queue R1 (TO0) */ -#define B3_RI_WTO_XA1 0x0191 /* 8 bit WR Timeout Queue XA1 (TO1) */ -#define B3_RI_WTO_XS1 0x0192 /* 8 bit WR Timeout Queue XS1 (TO2) */ -#define B3_RI_RTO_R1 0x0193 /* 8 bit RD Timeout Queue R1 (TO3) */ -#define B3_RI_RTO_XA1 0x0194 /* 8 bit RD Timeout Queue XA1 (TO4) */ -#define B3_RI_RTO_XS1 0x0195 /* 8 bit RD Timeout Queue XS1 (TO5) */ -#define B3_RI_WTO_R2 0x0196 /* 8 bit WR Timeout Queue R2 (TO6) */ -#define B3_RI_WTO_XA2 0x0197 /* 8 bit WR Timeout Queue XA2 (TO7) */ -#define B3_RI_WTO_XS2 0x0198 /* 8 bit WR Timeout Queue XS2 (TO8) */ -#define B3_RI_RTO_R2 0x0199 /* 8 bit RD Timeout Queue R2 (TO9) */ -#define B3_RI_RTO_XA2 0x019a /* 8 bit RD Timeout Queue XA2 (TO10)*/ -#define B3_RI_RTO_XS2 0x019b /* 8 bit RD Timeout Queue XS2 (TO11)*/ -#define B3_RI_TO_VAL 0x019c /* 8 bit Current Timeout Count Val */ - /* 0x019d - 0x019f: reserved */ -#define B3_RI_CTRL 0x01a0 /* 16 bit RAM Interface Control Register */ -#define B3_RI_TEST 0x01a2 /* 8 bit RAM Interface Test Register */ - /* 0x01a3 - 0x01af: reserved */ - -/* MAC Arbiter Registers (GENESIS only) */ -/* these are the no. of qWord transferred continuously and NOT real timeouts */ -#define B3_MA_TOINI_RX1 0x01b0 /* 8 bit Timeout Init Val Rx Path MAC 1 */ -#define B3_MA_TOINI_RX2 0x01b1 /* 8 bit Timeout Init Val Rx Path MAC 2 */ -#define B3_MA_TOINI_TX1 0x01b2 /* 8 bit Timeout Init Val Tx Path MAC 1 */ -#define B3_MA_TOINI_TX2 0x01b3 /* 8 bit Timeout Init Val Tx Path MAC 2 */ -#define B3_MA_TOVAL_RX1 0x01b4 /* 8 bit Timeout Value Rx Path MAC 1 */ -#define B3_MA_TOVAL_RX2 0x01b5 /* 8 bit Timeout Value Rx Path MAC 1 */ -#define B3_MA_TOVAL_TX1 0x01b6 /* 8 bit Timeout Value Tx Path MAC 2 */ -#define B3_MA_TOVAL_TX2 0x01b7 /* 8 bit Timeout Value Tx Path MAC 2 */ -#define B3_MA_TO_CTRL 0x01b8 /* 16 bit MAC Arbiter Timeout Ctrl Reg */ -#define B3_MA_TO_TEST 0x01ba /* 16 bit MAC Arbiter Timeout Test Reg */ - /* 0x01bc - 0x01bf: reserved */ -#define B3_MA_RCINI_RX1 0x01c0 /* 8 bit Recovery Init Val Rx Path MAC 1 */ -#define B3_MA_RCINI_RX2 0x01c1 /* 8 bit Recovery Init Val Rx Path MAC 2 */ -#define B3_MA_RCINI_TX1 0x01c2 /* 8 bit Recovery Init Val Tx Path MAC 1 */ -#define B3_MA_RCINI_TX2 0x01c3 /* 8 bit Recovery Init Val Tx Path MAC 2 */ -#define B3_MA_RCVAL_RX1 0x01c4 /* 8 bit Recovery Value Rx Path MAC 1 */ -#define B3_MA_RCVAL_RX2 0x01c5 /* 8 bit Recovery Value Rx Path MAC 1 */ -#define B3_MA_RCVAL_TX1 0x01c6 /* 8 bit Recovery Value Tx Path MAC 2 */ -#define B3_MA_RCVAL_TX2 0x01c7 /* 8 bit Recovery Value Tx Path MAC 2 */ -#define B3_MA_RC_CTRL 0x01c8 /* 16 bit MAC Arbiter Recovery Ctrl Reg */ -#define B3_MA_RC_TEST 0x01ca /* 16 bit MAC Arbiter Recovery Test Reg */ - /* 0x01cc - 0x01cf: reserved */ - -/* Packet Arbiter Registers (GENESIS only) */ -/* these are real timeouts */ -#define B3_PA_TOINI_RX1 0x01d0 /* 16 bit Timeout Init Val Rx Path MAC 1 */ - /* 0x01d2 - 0x01d3: reserved */ -#define B3_PA_TOINI_RX2 0x01d4 /* 16 bit Timeout Init Val Rx Path MAC 2 */ - /* 0x01d6 - 0x01d7: reserved */ -#define B3_PA_TOINI_TX1 0x01d8 /* 16 bit Timeout Init Val Tx Path MAC 1 */ - /* 0x01da - 0x01db: reserved */ -#define B3_PA_TOINI_TX2 0x01dc /* 16 bit Timeout Init Val Tx Path MAC 2 */ - /* 0x01de - 0x01df: reserved */ -#define B3_PA_TOVAL_RX1 0x01e0 /* 16 bit Timeout Val Rx Path MAC 1 */ - /* 0x01e2 - 0x01e3: reserved */ -#define B3_PA_TOVAL_RX2 0x01e4 /* 16 bit Timeout Val Rx Path MAC 2 */ - /* 0x01e6 - 0x01e7: reserved */ -#define B3_PA_TOVAL_TX1 0x01e8 /* 16 bit Timeout Val Tx Path MAC 1 */ - /* 0x01ea - 0x01eb: reserved */ -#define B3_PA_TOVAL_TX2 0x01ec /* 16 bit Timeout Val Tx Path MAC 2 */ - /* 0x01ee - 0x01ef: reserved */ -#define B3_PA_CTRL 0x01f0 /* 16 bit Packet Arbiter Ctrl Register */ -#define B3_PA_TEST 0x01f2 /* 16 bit Packet Arbiter Test Register */ - /* 0x01f4 - 0x01ff: reserved */ - -/* - * Bank 4 - 5 - */ -/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */ -#define TXA_ITI_INI 0x0200 /* 32 bit Tx Arb Interval Timer Init Val*/ -#define TXA_ITI_VAL 0x0204 /* 32 bit Tx Arb Interval Timer Value */ -#define TXA_LIM_INI 0x0208 /* 32 bit Tx Arb Limit Counter Init Val */ -#define TXA_LIM_VAL 0x020c /* 32 bit Tx Arb Limit Counter Value */ -#define TXA_CTRL 0x0210 /* 8 bit Tx Arbiter Control Register */ -#define TXA_TEST 0x0211 /* 8 bit Tx Arbiter Test Register */ -#define TXA_STAT 0x0212 /* 8 bit Tx Arbiter Status Register */ - /* 0x0213 - 0x027f: reserved */ - /* 0x0280 - 0x0292: MAC 2 */ - /* 0x0213 - 0x027f: reserved */ - -/* - * Bank 6 - */ -/* External registers (GENESIS only) */ -#define B6_EXT_REG 0x0300 - -/* - * Bank 7 - */ -/* This is a copy of the Configuration register file (lower half) */ -#define B7_CFG_SPC 0x0380 - -/* - * Bank 8 - 15 - */ -/* Receive and Transmit Queue Registers, use Q_ADDR() to access */ -#define B8_Q_REGS 0x0400 - -/* Queue Register Offsets, use Q_ADDR() to access */ -#define Q_D 0x00 /* 8*32 bit Current Descriptor */ -#define Q_DA_L 0x20 /* 32 bit Current Descriptor Address Low dWord */ -#define Q_DA_H 0x24 /* 32 bit Current Descriptor Address High dWord */ -#define Q_AC_L 0x28 /* 32 bit Current Address Counter Low dWord */ -#define Q_AC_H 0x2c /* 32 bit Current Address Counter High dWord */ -#define Q_BC 0x30 /* 32 bit Current Byte Counter */ -#define Q_CSR 0x34 /* 32 bit BMU Control/Status Register */ -#define Q_F 0x38 /* 32 bit Flag Register */ -#define Q_T1 0x3c /* 32 bit Test Register 1 */ -#define Q_T1_TR 0x3c /* 8 bit Test Register 1 Transfer SM */ -#define Q_T1_WR 0x3d /* 8 bit Test Register 1 Write Descriptor SM */ -#define Q_T1_RD 0x3e /* 8 bit Test Register 1 Read Descriptor SM */ -#define Q_T1_SV 0x3f /* 8 bit Test Register 1 Supervisor SM */ -#define Q_T2 0x40 /* 32 bit Test Register 2 */ -#define Q_T3 0x44 /* 32 bit Test Register 3 */ - /* 0x48 - 0x7f: reserved */ - -/* - * Bank 16 - 23 - */ -/* RAM Buffer Registers */ -#define B16_RAM_REGS 0x0800 - -/* RAM Buffer Register Offsets, use RB_ADDR() to access */ -#define RB_START 0x00 /* 32 bit RAM Buffer Start Address */ -#define RB_END 0x04 /* 32 bit RAM Buffer End Address */ -#define RB_WP 0x08 /* 32 bit RAM Buffer Write Pointer */ -#define RB_RP 0x0c /* 32 bit RAM Buffer Read Pointer */ -#define RB_RX_UTPP 0x10 /* 32 bit Rx Upper Threshold, Pause Pack */ -#define RB_RX_LTPP 0x14 /* 32 bit Rx Lower Threshold, Pause Pack */ -#define RB_RX_UTHP 0x18 /* 32 bit Rx Upper Threshold, High Prio */ -#define RB_RX_LTHP 0x1c /* 32 bit Rx Lower Threshold, High Prio */ - /* 0x10 - 0x1f: reserved at Tx RAM Buffer Registers */ -#define RB_PC 0x20 /* 32 bit RAM Buffer Packet Counter */ -#define RB_LEV 0x24 /* 32 bit RAM Buffer Level Register */ -#define RB_CTRL 0x28 /* 8 bit RAM Buffer Control Register */ -#define RB_TST1 0x29 /* 8 bit RAM Buffer Test Register 1 */ -#define RB_TST2 0x2A /* 8 bit RAM Buffer Test Register 2 */ - /* 0x2c - 0x7f: reserved */ - -/* - * Bank 24 - */ -/* - * Receive MAC FIFO, Receive LED, and Link_Sync regs (GENESIS only) - * use MR_ADDR() to access - */ -#define RX_MFF_EA 0x0c00 /* 32 bit Receive MAC FIFO End Address */ -#define RX_MFF_WP 0x0c04 /* 32 bit Receive MAC FIFO Write Pointer */ - /* 0x0c08 - 0x0c0b: reserved */ -#define RX_MFF_RP 0x0c0c /* 32 bit Receive MAC FIFO Read Pointer */ -#define RX_MFF_PC 0x0c10 /* 32 bit Receive MAC FIFO Packet Cnt */ -#define RX_MFF_LEV 0x0c14 /* 32 bit Receive MAC FIFO Level */ -#define RX_MFF_CTRL1 0x0c18 /* 16 bit Receive MAC FIFO Control Reg 1*/ -#define RX_MFF_STAT_TO 0x0c1a /* 8 bit Receive MAC Status Timeout */ -#define RX_MFF_TIST_TO 0x0c1b /* 8 bit Receive MAC Time Stamp Timeout */ -#define RX_MFF_CTRL2 0x0c1c /* 8 bit Receive MAC FIFO Control Reg 2*/ -#define RX_MFF_TST1 0x0c1d /* 8 bit Receive MAC FIFO Test Reg 1 */ -#define RX_MFF_TST2 0x0c1e /* 8 bit Receive MAC FIFO Test Reg 2 */ - /* 0x0c1f: reserved */ -#define RX_LED_INI 0x0c20 /* 32 bit Receive LED Cnt Init Value */ -#define RX_LED_VAL 0x0c24 /* 32 bit Receive LED Cnt Current Value */ -#define RX_LED_CTRL 0x0c28 /* 8 bit Receive LED Cnt Control Reg */ -#define RX_LED_TST 0x0c29 /* 8 bit Receive LED Cnt Test Register */ - /* 0x0c2a - 0x0c2f: reserved */ -#define LNK_SYNC_INI 0x0c30 /* 32 bit Link Sync Cnt Init Value */ -#define LNK_SYNC_VAL 0x0c34 /* 32 bit Link Sync Cnt Current Value */ -#define LNK_SYNC_CTRL 0x0c38 /* 8 bit Link Sync Cnt Control Register */ -#define LNK_SYNC_TST 0x0c39 /* 8 bit Link Sync Cnt Test Register */ - /* 0x0c3a - 0x0c3b: reserved */ -#define LNK_LED_REG 0x0c3c /* 8 bit Link LED Register */ - /* 0x0c3d - 0x0c3f: reserved */ - -/* Receive GMAC FIFO (YUKON only), use MR_ADDR() to access */ -#define RX_GMF_EA 0x0c40 /* 32 bit Rx GMAC FIFO End Address */ -#define RX_GMF_AF_THR 0x0c44 /* 32 bit Rx GMAC FIFO Almost Full Thresh. */ -#define RX_GMF_CTRL_T 0x0c48 /* 32 bit Rx GMAC FIFO Control/Test */ -#define RX_GMF_FL_MSK 0x0c4c /* 32 bit Rx GMAC FIFO Flush Mask */ -#define RX_GMF_FL_THR 0x0c50 /* 32 bit Rx GMAC FIFO Flush Threshold */ - /* 0x0c54 - 0x0c5f: reserved */ -#define RX_GMF_WP 0x0c60 /* 32 bit Rx GMAC FIFO Write Pointer */ - /* 0x0c64 - 0x0c67: reserved */ -#define RX_GMF_WLEV 0x0c68 /* 32 bit Rx GMAC FIFO Write Level */ - /* 0x0c6c - 0x0c6f: reserved */ -#define RX_GMF_RP 0x0c70 /* 32 bit Rx GMAC FIFO Read Pointer */ - /* 0x0c74 - 0x0c77: reserved */ -#define RX_GMF_RLEV 0x0c78 /* 32 bit Rx GMAC FIFO Read Level */ - /* 0x0c7c - 0x0c7f: reserved */ - -/* - * Bank 25 - */ - /* 0x0c80 - 0x0cbf: MAC 2 */ - /* 0x0cc0 - 0x0cff: reserved */ - -/* - * Bank 26 - */ -/* - * Transmit MAC FIFO and Transmit LED Registers (GENESIS only), - * use MR_ADDR() to access - */ -#define TX_MFF_EA 0x0d00 /* 32 bit Transmit MAC FIFO End Address */ -#define TX_MFF_WP 0x0d04 /* 32 bit Transmit MAC FIFO WR Pointer */ -#define TX_MFF_WSP 0x0d08 /* 32 bit Transmit MAC FIFO WR Shadow Ptr */ -#define TX_MFF_RP 0x0d0c /* 32 bit Transmit MAC FIFO RD Pointer */ -#define TX_MFF_PC 0x0d10 /* 32 bit Transmit MAC FIFO Packet Cnt */ -#define TX_MFF_LEV 0x0d14 /* 32 bit Transmit MAC FIFO Level */ -#define TX_MFF_CTRL1 0x0d18 /* 16 bit Transmit MAC FIFO Ctrl Reg 1 */ -#define TX_MFF_WAF 0x0d1a /* 8 bit Transmit MAC Wait after flush */ - /* 0x0c1b: reserved */ -#define TX_MFF_CTRL2 0x0d1c /* 8 bit Transmit MAC FIFO Ctrl Reg 2 */ -#define TX_MFF_TST1 0x0d1d /* 8 bit Transmit MAC FIFO Test Reg 1 */ -#define TX_MFF_TST2 0x0d1e /* 8 bit Transmit MAC FIFO Test Reg 2 */ - /* 0x0d1f: reserved */ -#define TX_LED_INI 0x0d20 /* 32 bit Transmit LED Cnt Init Value */ -#define TX_LED_VAL 0x0d24 /* 32 bit Transmit LED Cnt Current Val */ -#define TX_LED_CTRL 0x0d28 /* 8 bit Transmit LED Cnt Control Reg */ -#define TX_LED_TST 0x0d29 /* 8 bit Transmit LED Cnt Test Reg */ - /* 0x0d2a - 0x0d3f: reserved */ - -/* Transmit GMAC FIFO (YUKON only), use MR_ADDR() to access */ -#define TX_GMF_EA 0x0d40 /* 32 bit Tx GMAC FIFO End Address */ -#define TX_GMF_AE_THR 0x0d44 /* 32 bit Tx GMAC FIFO Almost Empty Thresh.*/ -#define TX_GMF_CTRL_T 0x0d48 /* 32 bit Tx GMAC FIFO Control/Test */ - /* 0x0d4c - 0x0d5f: reserved */ -#define TX_GMF_WP 0x0d60 /* 32 bit Tx GMAC FIFO Write Pointer */ -#define TX_GMF_WSP 0x0d64 /* 32 bit Tx GMAC FIFO Write Shadow Ptr. */ -#define TX_GMF_WLEV 0x0d68 /* 32 bit Tx GMAC FIFO Write Level */ - /* 0x0d6c - 0x0d6f: reserved */ -#define TX_GMF_RP 0x0d70 /* 32 bit Tx GMAC FIFO Read Pointer */ -#define TX_GMF_RSTP 0x0d74 /* 32 bit Tx GMAC FIFO Restart Pointer */ -#define TX_GMF_RLEV 0x0d78 /* 32 bit Tx GMAC FIFO Read Level */ - /* 0x0d7c - 0x0d7f: reserved */ - -/* - * Bank 27 - */ - /* 0x0d80 - 0x0dbf: MAC 2 */ - /* 0x0daa - 0x0dff: reserved */ - -/* - * Bank 28 - */ -/* Descriptor Poll Timer Registers */ -#define B28_DPT_INI 0x0e00 /* 24 bit Descriptor Poll Timer Init Val */ -#define B28_DPT_VAL 0x0e04 /* 24 bit Descriptor Poll Timer Curr Val */ -#define B28_DPT_CTRL 0x0e08 /* 8 bit Descriptor Poll Timer Ctrl Reg */ - /* 0x0e09: reserved */ -#define B28_DPT_TST 0x0e0a /* 8 bit Descriptor Poll Timer Test Reg */ - /* 0x0e0b: reserved */ - -/* Time Stamp Timer Registers (YUKON only) */ - /* 0x0e10: reserved */ -#define GMAC_TI_ST_VAL 0x0e14 /* 32 bit Time Stamp Timer Curr Val */ -#define GMAC_TI_ST_CTRL 0x0e18 /* 8 bit Time Stamp Timer Ctrl Reg */ - /* 0x0e19: reserved */ -#define GMAC_TI_ST_TST 0x0e1a /* 8 bit Time Stamp Timer Test Reg */ - /* 0x0e1b - 0x0e7f: reserved */ - -/* - * Bank 29 - */ - /* 0x0e80 - 0x0efc: reserved */ - -/* - * Bank 30 - */ -/* GMAC and GPHY Control Registers (YUKON only) */ -#define GMAC_CTRL 0x0f00 /* 32 bit GMAC Control Reg */ -#define GPHY_CTRL 0x0f04 /* 32 bit GPHY Control Reg */ -#define GMAC_IRQ_SRC 0x0f08 /* 8 bit GMAC Interrupt Source Reg */ - /* 0x0f09 - 0x0f0b: reserved */ -#define GMAC_IRQ_MSK 0x0f0c /* 8 bit GMAC Interrupt Mask Reg */ - /* 0x0f0d - 0x0f0f: reserved */ -#define GMAC_LINK_CTRL 0x0f10 /* 16 bit Link Control Reg */ - /* 0x0f14 - 0x0f1f: reserved */ - -/* Wake-up Frame Pattern Match Control Registers (YUKON only) */ - -#define WOL_REG_OFFS 0x20 /* HW-Bug: Address is + 0x20 against spec. */ - -#define WOL_CTRL_STAT 0x0f20 /* 16 bit WOL Control/Status Reg */ -#define WOL_MATCH_CTL 0x0f22 /* 8 bit WOL Match Control Reg */ -#define WOL_MATCH_RES 0x0f23 /* 8 bit WOL Match Result Reg */ -#define WOL_MAC_ADDR_LO 0x0f24 /* 32 bit WOL MAC Address Low */ -#define WOL_MAC_ADDR_HI 0x0f28 /* 16 bit WOL MAC Address High */ -#define WOL_PATT_RPTR 0x0f2c /* 8 bit WOL Pattern Read Ptr */ - -/* use this macro to access above registers */ -#define WOL_REG(Reg) ((Reg) + (pAC->GIni.GIWolOffs)) - - -/* WOL Pattern Length Registers (YUKON only) */ - -#define WOL_PATT_LEN_LO 0x0f30 /* 32 bit WOL Pattern Length 3..0 */ -#define WOL_PATT_LEN_HI 0x0f34 /* 24 bit WOL Pattern Length 6..4 */ - -/* WOL Pattern Counter Registers (YUKON only) */ - -#define WOL_PATT_CNT_0 0x0f38 /* 32 bit WOL Pattern Counter 3..0 */ -#define WOL_PATT_CNT_4 0x0f3c /* 24 bit WOL Pattern Counter 6..4 */ - /* 0x0f40 - 0x0f7f: reserved */ - -/* - * Bank 31 - */ -/* 0x0f80 - 0x0fff: reserved */ - -/* - * Bank 32 - 33 - */ -#define WOL_PATT_RAM_1 0x1000 /* WOL Pattern RAM Link 1 */ - -/* - * Bank 0x22 - 0x3f - */ -/* 0x1100 - 0x1fff: reserved */ - -/* - * Bank 0x40 - 0x4f - */ -#define BASE_XMAC_1 0x2000 /* XMAC 1 registers */ - -/* - * Bank 0x50 - 0x5f - */ - -#define BASE_GMAC_1 0x2800 /* GMAC 1 registers */ - -/* - * Bank 0x60 - 0x6f - */ -#define BASE_XMAC_2 0x3000 /* XMAC 2 registers */ - -/* - * Bank 0x70 - 0x7f - */ -#define BASE_GMAC_2 0x3800 /* GMAC 2 registers */ - -/* - * Control Register Bit Definitions: - */ -/* B0_RAP 8 bit Register Address Port */ - /* Bit 7: reserved */ -#define RAP_RAP 0x3f /* Bit 6..0: 0 = block 0,..,6f = block 6f */ - -/* B0_CTST 16 bit Control/Status register */ - /* Bit 15..14: reserved */ -#define CS_CLK_RUN_HOT BIT_13S /* CLK_RUN hot m. (YUKON-Lite only) */ -#define CS_CLK_RUN_RST BIT_12S /* CLK_RUN reset (YUKON-Lite only) */ -#define CS_CLK_RUN_ENA BIT_11S /* CLK_RUN enable (YUKON-Lite only) */ -#define CS_VAUX_AVAIL BIT_10S /* VAUX available (YUKON only) */ -#define CS_BUS_CLOCK BIT_9S /* Bus Clock 0/1 = 33/66 MHz */ -#define CS_BUS_SLOT_SZ BIT_8S /* Slot Size 0/1 = 32/64 bit slot */ -#define CS_ST_SW_IRQ BIT_7S /* Set IRQ SW Request */ -#define CS_CL_SW_IRQ BIT_6S /* Clear IRQ SW Request */ -#define CS_STOP_DONE BIT_5S /* Stop Master is finished */ -#define CS_STOP_MAST BIT_4S /* Command Bit to stop the master */ -#define CS_MRST_CLR BIT_3S /* Clear Master reset */ -#define CS_MRST_SET BIT_2S /* Set Master reset */ -#define CS_RST_CLR BIT_1S /* Clear Software reset */ -#define CS_RST_SET BIT_0S /* Set Software reset */ - -/* B0_LED 8 Bit LED register */ - /* Bit 7.. 2: reserved */ -#define LED_STAT_ON BIT_1S /* Status LED on */ -#define LED_STAT_OFF BIT_0S /* Status LED off */ - -/* B0_POWER_CTRL 8 Bit Power Control reg (YUKON only) */ -#define PC_VAUX_ENA BIT_7 /* Switch VAUX Enable */ -#define PC_VAUX_DIS BIT_6 /* Switch VAUX Disable */ -#define PC_VCC_ENA BIT_5 /* Switch VCC Enable */ -#define PC_VCC_DIS BIT_4 /* Switch VCC Disable */ -#define PC_VAUX_ON BIT_3 /* Switch VAUX On */ -#define PC_VAUX_OFF BIT_2 /* Switch VAUX Off */ -#define PC_VCC_ON BIT_1 /* Switch VCC On */ -#define PC_VCC_OFF BIT_0 /* Switch VCC Off */ - -/* B0_ISRC 32 bit Interrupt Source Register */ -/* B0_IMSK 32 bit Interrupt Mask Register */ -/* B0_SP_ISRC 32 bit Special Interrupt Source Reg */ -/* B2_IRQM_MSK 32 bit IRQ Moderation Mask */ -#define IS_ALL_MSK 0xbfffffffUL /* All Interrupt bits */ -#define IS_HW_ERR BIT_31 /* Interrupt HW Error */ - /* Bit 30: reserved */ -#define IS_PA_TO_RX1 BIT_29 /* Packet Arb Timeout Rx1 */ -#define IS_PA_TO_RX2 BIT_28 /* Packet Arb Timeout Rx2 */ -#define IS_PA_TO_TX1 BIT_27 /* Packet Arb Timeout Tx1 */ -#define IS_PA_TO_TX2 BIT_26 /* Packet Arb Timeout Tx2 */ -#define IS_I2C_READY BIT_25 /* IRQ on end of I2C Tx */ -#define IS_IRQ_SW BIT_24 /* SW forced IRQ */ -#define IS_EXT_REG BIT_23 /* IRQ from LM80 or PHY (GENESIS only) */ - /* IRQ from PHY (YUKON only) */ -#define IS_TIMINT BIT_22 /* IRQ from Timer */ -#define IS_MAC1 BIT_21 /* IRQ from MAC 1 */ -#define IS_LNK_SYNC_M1 BIT_20 /* Link Sync Cnt wrap MAC 1 */ -#define IS_MAC2 BIT_19 /* IRQ from MAC 2 */ -#define IS_LNK_SYNC_M2 BIT_18 /* Link Sync Cnt wrap MAC 2 */ -/* Receive Queue 1 */ -#define IS_R1_B BIT_17 /* Q_R1 End of Buffer */ -#define IS_R1_F BIT_16 /* Q_R1 End of Frame */ -#define IS_R1_C BIT_15 /* Q_R1 Encoding Error */ -/* Receive Queue 2 */ -#define IS_R2_B BIT_14 /* Q_R2 End of Buffer */ -#define IS_R2_F BIT_13 /* Q_R2 End of Frame */ -#define IS_R2_C BIT_12 /* Q_R2 Encoding Error */ -/* Synchronous Transmit Queue 1 */ -#define IS_XS1_B BIT_11 /* Q_XS1 End of Buffer */ -#define IS_XS1_F BIT_10 /* Q_XS1 End of Frame */ -#define IS_XS1_C BIT_9 /* Q_XS1 Encoding Error */ -/* Asynchronous Transmit Queue 1 */ -#define IS_XA1_B BIT_8 /* Q_XA1 End of Buffer */ -#define IS_XA1_F BIT_7 /* Q_XA1 End of Frame */ -#define IS_XA1_C BIT_6 /* Q_XA1 Encoding Error */ -/* Synchronous Transmit Queue 2 */ -#define IS_XS2_B BIT_5 /* Q_XS2 End of Buffer */ -#define IS_XS2_F BIT_4 /* Q_XS2 End of Frame */ -#define IS_XS2_C BIT_3 /* Q_XS2 Encoding Error */ -/* Asynchronous Transmit Queue 2 */ -#define IS_XA2_B BIT_2 /* Q_XA2 End of Buffer */ -#define IS_XA2_F BIT_1 /* Q_XA2 End of Frame */ -#define IS_XA2_C BIT_0 /* Q_XA2 Encoding Error */ - - -/* B0_HWE_ISRC 32 bit HW Error Interrupt Src Reg */ -/* B0_HWE_IMSK 32 bit HW Error Interrupt Mask Reg */ -/* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */ -#define IS_ERR_MSK 0x00000fffL /* All Error bits */ - /* Bit 31..14: reserved */ -#define IS_IRQ_TIST_OV BIT_13 /* Time Stamp Timer Overflow (YUKON only) */ -#define IS_IRQ_SENSOR BIT_12 /* IRQ from Sensor (YUKON only) */ -#define IS_IRQ_MST_ERR BIT_11 /* IRQ master error detected */ -#define IS_IRQ_STAT BIT_10 /* IRQ status exception */ -#define IS_NO_STAT_M1 BIT_9 /* No Rx Status from MAC 1 */ -#define IS_NO_STAT_M2 BIT_8 /* No Rx Status from MAC 2 */ -#define IS_NO_TIST_M1 BIT_7 /* No Time Stamp from MAC 1 */ -#define IS_NO_TIST_M2 BIT_6 /* No Time Stamp from MAC 2 */ -#define IS_RAM_RD_PAR BIT_5 /* RAM Read Parity Error */ -#define IS_RAM_WR_PAR BIT_4 /* RAM Write Parity Error */ -#define IS_M1_PAR_ERR BIT_3 /* MAC 1 Parity Error */ -#define IS_M2_PAR_ERR BIT_2 /* MAC 2 Parity Error */ -#define IS_R1_PAR_ERR BIT_1 /* Queue R1 Parity Error */ -#define IS_R2_PAR_ERR BIT_0 /* Queue R2 Parity Error */ - -/* B2_CONN_TYP 8 bit Connector type */ -/* B2_PMD_TYP 8 bit PMD type */ -/* Values of connector and PMD type comply to SysKonnect internal std */ - -/* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */ -#define CFG_CHIP_R_MSK (0xf<<4) /* Bit 7.. 4: Chip Revision */ - /* Bit 3.. 2: reserved */ -#define CFG_DIS_M2_CLK BIT_1S /* Disable Clock for 2nd MAC */ -#define CFG_SNG_MAC BIT_0S /* MAC Config: 0=2 MACs / 1=1 MAC*/ - -/* B2_CHIP_ID 8 bit Chip Identification Number */ -#define CHIP_ID_GENESIS 0x0a /* Chip ID for GENESIS */ -#define CHIP_ID_YUKON 0xb0 /* Chip ID for YUKON */ -#define CHIP_ID_YUKON_LITE 0xb1 /* Chip ID for YUKON-Lite (Rev. A1-A3) */ -#define CHIP_ID_YUKON_LP 0xb2 /* Chip ID for YUKON-LP */ - -#define CHIP_REV_YU_LITE_A1 3 /* Chip Rev. for YUKON-Lite A1,A2 */ -#define CHIP_REV_YU_LITE_A3 7 /* Chip Rev. for YUKON-Lite A3 */ - -/* B2_FAR 32 bit Flash-Prom Addr Reg/Cnt */ -#define FAR_ADDR 0x1ffffL /* Bit 16.. 0: FPROM Address mask */ - -/* B2_LD_CTRL 8 bit EPROM loader control register */ -/* Bits are currently reserved */ - -/* B2_LD_TEST 8 bit EPROM loader test register */ - /* Bit 7.. 4: reserved */ -#define LD_T_ON BIT_3S /* Loader Test mode on */ -#define LD_T_OFF BIT_2S /* Loader Test mode off */ -#define LD_T_STEP BIT_1S /* Decrement FPROM addr. Counter */ -#define LD_START BIT_0S /* Start loading FPROM */ - -/* - * Timer Section - */ -/* B2_TI_CTRL 8 bit Timer control */ -/* B2_IRQM_CTRL 8 bit IRQ Moderation Timer Control */ - /* Bit 7.. 3: reserved */ -#define TIM_START BIT_2S /* Start Timer */ -#define TIM_STOP BIT_1S /* Stop Timer */ -#define TIM_CLR_IRQ BIT_0S /* Clear Timer IRQ (!IRQM) */ - -/* B2_TI_TEST 8 Bit Timer Test */ -/* B2_IRQM_TEST 8 bit IRQ Moderation Timer Test */ -/* B28_DPT_TST 8 bit Descriptor Poll Timer Test Reg */ - /* Bit 7.. 3: reserved */ -#define TIM_T_ON BIT_2S /* Test mode on */ -#define TIM_T_OFF BIT_1S /* Test mode off */ -#define TIM_T_STEP BIT_0S /* Test step */ - -/* B28_DPT_INI 32 bit Descriptor Poll Timer Init Val */ -/* B28_DPT_VAL 32 bit Descriptor Poll Timer Curr Val */ - /* Bit 31..24: reserved */ -#define DPT_MSK 0x00ffffffL /* Bit 23.. 0: Desc Poll Timer Bits */ - -/* B28_DPT_CTRL 8 bit Descriptor Poll Timer Ctrl Reg */ - /* Bit 7.. 2: reserved */ -#define DPT_START BIT_1S /* Start Descriptor Poll Timer */ -#define DPT_STOP BIT_0S /* Stop Descriptor Poll Timer */ - -/* B2_E_3 8 bit lower 4 bits used for HW self test result */ -#define B2_E3_RES_MASK 0x0f - -/* B2_TST_CTRL1 8 bit Test Control Register 1 */ -#define TST_FRC_DPERR_MR BIT_7S /* force DATAPERR on MST RD */ -#define TST_FRC_DPERR_MW BIT_6S /* force DATAPERR on MST WR */ -#define TST_FRC_DPERR_TR BIT_5S /* force DATAPERR on TRG RD */ -#define TST_FRC_DPERR_TW BIT_4S /* force DATAPERR on TRG WR */ -#define TST_FRC_APERR_M BIT_3S /* force ADDRPERR on MST */ -#define TST_FRC_APERR_T BIT_2S /* force ADDRPERR on TRG */ -#define TST_CFG_WRITE_ON BIT_1S /* Enable Config Reg WR */ -#define TST_CFG_WRITE_OFF BIT_0S /* Disable Config Reg WR */ - -/* B2_TST_CTRL2 8 bit Test Control Register 2 */ - /* Bit 7.. 4: reserved */ - /* force the following error on the next master read/write */ -#define TST_FRC_DPERR_MR64 BIT_3S /* DataPERR RD 64 */ -#define TST_FRC_DPERR_MW64 BIT_2S /* DataPERR WR 64 */ -#define TST_FRC_APERR_1M64 BIT_1S /* AddrPERR on 1. phase */ -#define TST_FRC_APERR_2M64 BIT_0S /* AddrPERR on 2. phase */ - -/* B2_GP_IO 32 bit General Purpose I/O Register */ - /* Bit 31..26: reserved */ -#define GP_DIR_9 BIT_25 /* IO_9 direct, 0=In/1=Out */ -#define GP_DIR_8 BIT_24 /* IO_8 direct, 0=In/1=Out */ -#define GP_DIR_7 BIT_23 /* IO_7 direct, 0=In/1=Out */ -#define GP_DIR_6 BIT_22 /* IO_6 direct, 0=In/1=Out */ -#define GP_DIR_5 BIT_21 /* IO_5 direct, 0=In/1=Out */ -#define GP_DIR_4 BIT_20 /* IO_4 direct, 0=In/1=Out */ -#define GP_DIR_3 BIT_19 /* IO_3 direct, 0=In/1=Out */ -#define GP_DIR_2 BIT_18 /* IO_2 direct, 0=In/1=Out */ -#define GP_DIR_1 BIT_17 /* IO_1 direct, 0=In/1=Out */ -#define GP_DIR_0 BIT_16 /* IO_0 direct, 0=In/1=Out */ - /* Bit 15..10: reserved */ -#define GP_IO_9 BIT_9 /* IO_9 pin */ -#define GP_IO_8 BIT_8 /* IO_8 pin */ -#define GP_IO_7 BIT_7 /* IO_7 pin */ -#define GP_IO_6 BIT_6 /* IO_6 pin */ -#define GP_IO_5 BIT_5 /* IO_5 pin */ -#define GP_IO_4 BIT_4 /* IO_4 pin */ -#define GP_IO_3 BIT_3 /* IO_3 pin */ -#define GP_IO_2 BIT_2 /* IO_2 pin */ -#define GP_IO_1 BIT_1 /* IO_1 pin */ -#define GP_IO_0 BIT_0 /* IO_0 pin */ - -/* B2_I2C_CTRL 32 bit I2C HW Control Register */ -#define I2C_FLAG BIT_31 /* Start read/write if WR */ -#define I2C_ADDR (0x7fffL<<16) /* Bit 30..16: Addr to be RD/WR */ -#define I2C_DEV_SEL (0x7fL<<9) /* Bit 15.. 9: I2C Device Select */ - /* Bit 8.. 5: reserved */ -#define I2C_BURST_LEN BIT_4 /* Burst Len, 1/4 bytes */ -#define I2C_DEV_SIZE (7<<1) /* Bit 3.. 1: I2C Device Size */ -#define I2C_025K_DEV (0<<1) /* 0: 256 Bytes or smal. */ -#define I2C_05K_DEV (1<<1) /* 1: 512 Bytes */ -#define I2C_1K_DEV (2<<1) /* 2: 1024 Bytes */ -#define I2C_2K_DEV (3<<1) /* 3: 2048 Bytes */ -#define I2C_4K_DEV (4<<1) /* 4: 4096 Bytes */ -#define I2C_8K_DEV (5<<1) /* 5: 8192 Bytes */ -#define I2C_16K_DEV (6<<1) /* 6: 16384 Bytes */ -#define I2C_32K_DEV (7<<1) /* 7: 32768 Bytes */ -#define I2C_STOP BIT_0 /* Interrupt I2C transfer */ - -/* B2_I2C_IRQ 32 bit I2C HW IRQ Register */ - /* Bit 31.. 1 reserved */ -#define I2C_CLR_IRQ BIT_0 /* Clear I2C IRQ */ - -/* B2_I2C_SW 32 bit (8 bit access) I2C HW SW Port Register */ - /* Bit 7.. 3: reserved */ -#define I2C_DATA_DIR BIT_2S /* direction of I2C_DATA */ -#define I2C_DATA BIT_1S /* I2C Data Port */ -#define I2C_CLK BIT_0S /* I2C Clock Port */ - -/* - * I2C Address - */ -#define I2C_SENS_ADDR LM80_ADDR /* I2C Sensor Address, (Volt and Temp)*/ - - -/* B2_BSC_CTRL 8 bit Blink Source Counter Control */ - /* Bit 7.. 2: reserved */ -#define BSC_START BIT_1S /* Start Blink Source Counter */ -#define BSC_STOP BIT_0S /* Stop Blink Source Counter */ - -/* B2_BSC_STAT 8 bit Blink Source Counter Status */ - /* Bit 7.. 1: reserved */ -#define BSC_SRC BIT_0S /* Blink Source, 0=Off / 1=On */ - -/* B2_BSC_TST 16 bit Blink Source Counter Test Reg */ -#define BSC_T_ON BIT_2S /* Test mode on */ -#define BSC_T_OFF BIT_1S /* Test mode off */ -#define BSC_T_STEP BIT_0S /* Test step */ - - -/* B3_RAM_ADDR 32 bit RAM Address, to read or write */ - /* Bit 31..19: reserved */ -#define RAM_ADR_RAN 0x0007ffffL /* Bit 18.. 0: RAM Address Range */ - -/* RAM Interface Registers */ -/* B3_RI_CTRL 16 bit RAM Iface Control Register */ - /* Bit 15..10: reserved */ -#define RI_CLR_RD_PERR BIT_9S /* Clear IRQ RAM Read Parity Err */ -#define RI_CLR_WR_PERR BIT_8S /* Clear IRQ RAM Write Parity Err*/ - /* Bit 7.. 2: reserved */ -#define RI_RST_CLR BIT_1S /* Clear RAM Interface Reset */ -#define RI_RST_SET BIT_0S /* Set RAM Interface Reset */ - -/* B3_RI_TEST 8 bit RAM Iface Test Register */ - /* Bit 15.. 4: reserved */ -#define RI_T_EV BIT_3S /* Timeout Event occured */ -#define RI_T_ON BIT_2S /* Timeout Timer Test On */ -#define RI_T_OFF BIT_1S /* Timeout Timer Test Off */ -#define RI_T_STEP BIT_0S /* Timeout Timer Step */ - -/* MAC Arbiter Registers */ -/* B3_MA_TO_CTRL 16 bit MAC Arbiter Timeout Ctrl Reg */ - /* Bit 15.. 4: reserved */ -#define MA_FOE_ON BIT_3S /* XMAC Fast Output Enable ON */ -#define MA_FOE_OFF BIT_2S /* XMAC Fast Output Enable OFF */ -#define MA_RST_CLR BIT_1S /* Clear MAC Arbiter Reset */ -#define MA_RST_SET BIT_0S /* Set MAC Arbiter Reset */ - -/* B3_MA_RC_CTRL 16 bit MAC Arbiter Recovery Ctrl Reg */ - /* Bit 15.. 8: reserved */ -#define MA_ENA_REC_TX2 BIT_7S /* Enable Recovery Timer TX2 */ -#define MA_DIS_REC_TX2 BIT_6S /* Disable Recovery Timer TX2 */ -#define MA_ENA_REC_TX1 BIT_5S /* Enable Recovery Timer TX1 */ -#define MA_DIS_REC_TX1 BIT_4S /* Disable Recovery Timer TX1 */ -#define MA_ENA_REC_RX2 BIT_3S /* Enable Recovery Timer RX2 */ -#define MA_DIS_REC_RX2 BIT_2S /* Disable Recovery Timer RX2 */ -#define MA_ENA_REC_RX1 BIT_1S /* Enable Recovery Timer RX1 */ -#define MA_DIS_REC_RX1 BIT_0S /* Disable Recovery Timer RX1 */ - -/* Packet Arbiter Registers */ -/* B3_PA_CTRL 16 bit Packet Arbiter Ctrl Register */ - /* Bit 15..14: reserved */ -#define PA_CLR_TO_TX2 BIT_13S /* Clear IRQ Packet Timeout TX2 */ -#define PA_CLR_TO_TX1 BIT_12S /* Clear IRQ Packet Timeout TX1 */ -#define PA_CLR_TO_RX2 BIT_11S /* Clear IRQ Packet Timeout RX2 */ -#define PA_CLR_TO_RX1 BIT_10S /* Clear IRQ Packet Timeout RX1 */ -#define PA_ENA_TO_TX2 BIT_9S /* Enable Timeout Timer TX2 */ -#define PA_DIS_TO_TX2 BIT_8S /* Disable Timeout Timer TX2 */ -#define PA_ENA_TO_TX1 BIT_7S /* Enable Timeout Timer TX1 */ -#define PA_DIS_TO_TX1 BIT_6S /* Disable Timeout Timer TX1 */ -#define PA_ENA_TO_RX2 BIT_5S /* Enable Timeout Timer RX2 */ -#define PA_DIS_TO_RX2 BIT_4S /* Disable Timeout Timer RX2 */ -#define PA_ENA_TO_RX1 BIT_3S /* Enable Timeout Timer RX1 */ -#define PA_DIS_TO_RX1 BIT_2S /* Disable Timeout Timer RX1 */ -#define PA_RST_CLR BIT_1S /* Clear MAC Arbiter Reset */ -#define PA_RST_SET BIT_0S /* Set MAC Arbiter Reset */ - -#define PA_ENA_TO_ALL (PA_ENA_TO_RX1 | PA_ENA_TO_RX2 |\ - PA_ENA_TO_TX1 | PA_ENA_TO_TX2) - -/* Rx/Tx Path related Arbiter Test Registers */ -/* B3_MA_TO_TEST 16 bit MAC Arbiter Timeout Test Reg */ -/* B3_MA_RC_TEST 16 bit MAC Arbiter Recovery Test Reg */ -/* B3_PA_TEST 16 bit Packet Arbiter Test Register */ -/* Bit 15, 11, 7, and 3 are reserved in B3_PA_TEST */ -#define TX2_T_EV BIT_15S /* TX2 Timeout/Recv Event occured */ -#define TX2_T_ON BIT_14S /* TX2 Timeout/Recv Timer Test On */ -#define TX2_T_OFF BIT_13S /* TX2 Timeout/Recv Timer Tst Off */ -#define TX2_T_STEP BIT_12S /* TX2 Timeout/Recv Timer Step */ -#define TX1_T_EV BIT_11S /* TX1 Timeout/Recv Event occured */ -#define TX1_T_ON BIT_10S /* TX1 Timeout/Recv Timer Test On */ -#define TX1_T_OFF BIT_9S /* TX1 Timeout/Recv Timer Tst Off */ -#define TX1_T_STEP BIT_8S /* TX1 Timeout/Recv Timer Step */ -#define RX2_T_EV BIT_7S /* RX2 Timeout/Recv Event occured */ -#define RX2_T_ON BIT_6S /* RX2 Timeout/Recv Timer Test On */ -#define RX2_T_OFF BIT_5S /* RX2 Timeout/Recv Timer Tst Off */ -#define RX2_T_STEP BIT_4S /* RX2 Timeout/Recv Timer Step */ -#define RX1_T_EV BIT_3S /* RX1 Timeout/Recv Event occured */ -#define RX1_T_ON BIT_2S /* RX1 Timeout/Recv Timer Test On */ -#define RX1_T_OFF BIT_1S /* RX1 Timeout/Recv Timer Tst Off */ -#define RX1_T_STEP BIT_0S /* RX1 Timeout/Recv Timer Step */ - - -/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */ -/* TXA_ITI_INI 32 bit Tx Arb Interval Timer Init Val */ -/* TXA_ITI_VAL 32 bit Tx Arb Interval Timer Value */ -/* TXA_LIM_INI 32 bit Tx Arb Limit Counter Init Val */ -/* TXA_LIM_VAL 32 bit Tx Arb Limit Counter Value */ - /* Bit 31..24: reserved */ -#define TXA_MAX_VAL 0x00ffffffUL/* Bit 23.. 0: Max TXA Timer/Cnt Val */ - -/* TXA_CTRL 8 bit Tx Arbiter Control Register */ -#define TXA_ENA_FSYNC BIT_7S /* Enable force of sync Tx queue */ -#define TXA_DIS_FSYNC BIT_6S /* Disable force of sync Tx queue */ -#define TXA_ENA_ALLOC BIT_5S /* Enable alloc of free bandwidth */ -#define TXA_DIS_ALLOC BIT_4S /* Disable alloc of free bandwidth */ -#define TXA_START_RC BIT_3S /* Start sync Rate Control */ -#define TXA_STOP_RC BIT_2S /* Stop sync Rate Control */ -#define TXA_ENA_ARB BIT_1S /* Enable Tx Arbiter */ -#define TXA_DIS_ARB BIT_0S /* Disable Tx Arbiter */ - -/* TXA_TEST 8 bit Tx Arbiter Test Register */ - /* Bit 7.. 6: reserved */ -#define TXA_INT_T_ON BIT_5S /* Tx Arb Interval Timer Test On */ -#define TXA_INT_T_OFF BIT_4S /* Tx Arb Interval Timer Test Off */ -#define TXA_INT_T_STEP BIT_3S /* Tx Arb Interval Timer Step */ -#define TXA_LIM_T_ON BIT_2S /* Tx Arb Limit Timer Test On */ -#define TXA_LIM_T_OFF BIT_1S /* Tx Arb Limit Timer Test Off */ -#define TXA_LIM_T_STEP BIT_0S /* Tx Arb Limit Timer Step */ - -/* TXA_STAT 8 bit Tx Arbiter Status Register */ - /* Bit 7.. 1: reserved */ -#define TXA_PRIO_XS BIT_0S /* sync queue has prio to send */ - -/* Q_BC 32 bit Current Byte Counter */ - /* Bit 31..16: reserved */ -#define BC_MAX 0xffff /* Bit 15.. 0: Byte counter */ - -/* BMU Control Status Registers */ -/* B0_R1_CSR 32 bit BMU Ctrl/Stat Rx Queue 1 */ -/* B0_R2_CSR 32 bit BMU Ctrl/Stat Rx Queue 2 */ -/* B0_XA1_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */ -/* B0_XS1_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 1 */ -/* B0_XA2_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */ -/* B0_XS2_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 2 */ -/* Q_CSR 32 bit BMU Control/Status Register */ - /* Bit 31..25: reserved */ -#define CSR_SV_IDLE BIT_24 /* BMU SM Idle */ - /* Bit 23..22: reserved */ -#define CSR_DESC_CLR BIT_21 /* Clear Reset for Descr */ -#define CSR_DESC_SET BIT_20 /* Set Reset for Descr */ -#define CSR_FIFO_CLR BIT_19 /* Clear Reset for FIFO */ -#define CSR_FIFO_SET BIT_18 /* Set Reset for FIFO */ -#define CSR_HPI_RUN BIT_17 /* Release HPI SM */ -#define CSR_HPI_RST BIT_16 /* Reset HPI SM to Idle */ -#define CSR_SV_RUN BIT_15 /* Release Supervisor SM */ -#define CSR_SV_RST BIT_14 /* Reset Supervisor SM */ -#define CSR_DREAD_RUN BIT_13 /* Release Descr Read SM */ -#define CSR_DREAD_RST BIT_12 /* Reset Descr Read SM */ -#define CSR_DWRITE_RUN BIT_11 /* Release Descr Write SM */ -#define CSR_DWRITE_RST BIT_10 /* Reset Descr Write SM */ -#define CSR_TRANS_RUN BIT_9 /* Release Transfer SM */ -#define CSR_TRANS_RST BIT_8 /* Reset Transfer SM */ -#define CSR_ENA_POL BIT_7 /* Enable Descr Polling */ -#define CSR_DIS_POL BIT_6 /* Disable Descr Polling */ -#define CSR_STOP BIT_5 /* Stop Rx/Tx Queue */ -#define CSR_START BIT_4 /* Start Rx/Tx Queue */ -#define CSR_IRQ_CL_P BIT_3 /* (Rx) Clear Parity IRQ */ -#define CSR_IRQ_CL_B BIT_2 /* Clear EOB IRQ */ -#define CSR_IRQ_CL_F BIT_1 /* Clear EOF IRQ */ -#define CSR_IRQ_CL_C BIT_0 /* Clear ERR IRQ */ - -#define CSR_SET_RESET (CSR_DESC_SET | CSR_FIFO_SET | CSR_HPI_RST |\ - CSR_SV_RST | CSR_DREAD_RST | CSR_DWRITE_RST |\ - CSR_TRANS_RST) -#define CSR_CLR_RESET (CSR_DESC_CLR | CSR_FIFO_CLR | CSR_HPI_RUN |\ - CSR_SV_RUN | CSR_DREAD_RUN | CSR_DWRITE_RUN |\ - CSR_TRANS_RUN) - -/* Q_F 32 bit Flag Register */ - /* Bit 31..28: reserved */ -#define F_ALM_FULL BIT_27 /* Rx FIFO: almost full */ -#define F_EMPTY BIT_27 /* Tx FIFO: empty flag */ -#define F_FIFO_EOF BIT_26 /* Tag (EOF Flag) bit in FIFO */ -#define F_WM_REACHED BIT_25 /* Watermark reached */ - /* reserved */ -#define F_FIFO_LEVEL (0x1fL<<16) /* Bit 23..16: # of Qwords in FIFO */ - /* Bit 15..11: reserved */ -#define F_WATER_MARK 0x0007ffL /* Bit 10.. 0: Watermark */ - -/* Q_T1 32 bit Test Register 1 */ -/* Holds four State Machine control Bytes */ -#define SM_CTRL_SV_MSK (0xffL<<24) /* Bit 31..24: Control Supervisor SM */ -#define SM_CTRL_RD_MSK (0xffL<<16) /* Bit 23..16: Control Read Desc SM */ -#define SM_CTRL_WR_MSK (0xffL<<8) /* Bit 15.. 8: Control Write Desc SM */ -#define SM_CTRL_TR_MSK 0xffL /* Bit 7.. 0: Control Transfer SM */ - -/* Q_T1_TR 8 bit Test Register 1 Transfer SM */ -/* Q_T1_WR 8 bit Test Register 1 Write Descriptor SM */ -/* Q_T1_RD 8 bit Test Register 1 Read Descriptor SM */ -/* Q_T1_SV 8 bit Test Register 1 Supervisor SM */ - -/* The control status byte of each machine looks like ... */ -#define SM_STATE 0xf0 /* Bit 7.. 4: State which shall be loaded */ -#define SM_LOAD BIT_3S /* Load the SM with SM_STATE */ -#define SM_TEST_ON BIT_2S /* Switch on SM Test Mode */ -#define SM_TEST_OFF BIT_1S /* Go off the Test Mode */ -#define SM_STEP BIT_0S /* Step the State Machine */ -/* The encoding of the states is not supported by the Diagnostics Tool */ - -/* Q_T2 32 bit Test Register 2 */ - /* Bit 31.. 8: reserved */ -#define T2_AC_T_ON BIT_7 /* Address Counter Test Mode on */ -#define T2_AC_T_OFF BIT_6 /* Address Counter Test Mode off */ -#define T2_BC_T_ON BIT_5 /* Byte Counter Test Mode on */ -#define T2_BC_T_OFF BIT_4 /* Byte Counter Test Mode off */ -#define T2_STEP04 BIT_3 /* Inc AC/Dec BC by 4 */ -#define T2_STEP03 BIT_2 /* Inc AC/Dec BC by 3 */ -#define T2_STEP02 BIT_1 /* Inc AC/Dec BC by 2 */ -#define T2_STEP01 BIT_0 /* Inc AC/Dec BC by 1 */ - -/* Q_T3 32 bit Test Register 3 */ - /* Bit 31.. 7: reserved */ -#define T3_MUX_MSK (7<<4) /* Bit 6.. 4: Mux Position */ - /* Bit 3: reserved */ -#define T3_VRAM_MSK 7 /* Bit 2.. 0: Virtual RAM Buffer Address */ - -/* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */ -/* RB_START 32 bit RAM Buffer Start Address */ -/* RB_END 32 bit RAM Buffer End Address */ -/* RB_WP 32 bit RAM Buffer Write Pointer */ -/* RB_RP 32 bit RAM Buffer Read Pointer */ -/* RB_RX_UTPP 32 bit Rx Upper Threshold, Pause Pack */ -/* RB_RX_LTPP 32 bit Rx Lower Threshold, Pause Pack */ -/* RB_RX_UTHP 32 bit Rx Upper Threshold, High Prio */ -/* RB_RX_LTHP 32 bit Rx Lower Threshold, High Prio */ -/* RB_PC 32 bit RAM Buffer Packet Counter */ -/* RB_LEV 32 bit RAM Buffer Level Register */ - /* Bit 31..19: reserved */ -#define RB_MSK 0x0007ffff /* Bit 18.. 0: RAM Buffer Pointer Bits */ - -/* RB_TST2 8 bit RAM Buffer Test Register 2 */ - /* Bit 7.. 4: reserved */ -#define RB_PC_DEC BIT_3S /* Packet Counter Decrem */ -#define RB_PC_T_ON BIT_2S /* Packet Counter Test On */ -#define RB_PC_T_OFF BIT_1S /* Packet Counter Tst Off */ -#define RB_PC_INC BIT_0S /* Packet Counter Increm */ - -/* RB_TST1 8 bit RAM Buffer Test Register 1 */ - /* Bit 7: reserved */ -#define RB_WP_T_ON BIT_6S /* Write Pointer Test On */ -#define RB_WP_T_OFF BIT_5S /* Write Pointer Test Off */ -#define RB_WP_INC BIT_4S /* Write Pointer Increm */ - /* Bit 3: reserved */ -#define RB_RP_T_ON BIT_2S /* Read Pointer Test On */ -#define RB_RP_T_OFF BIT_1S /* Read Pointer Test Off */ -#define RB_RP_DEC BIT_0S /* Read Pointer Decrement */ - -/* RB_CTRL 8 bit RAM Buffer Control Register */ - /* Bit 7.. 6: reserved */ -#define RB_ENA_STFWD BIT_5S /* Enable Store & Forward */ -#define RB_DIS_STFWD BIT_4S /* Disable Store & Forward */ -#define RB_ENA_OP_MD BIT_3S /* Enable Operation Mode */ -#define RB_DIS_OP_MD BIT_2S /* Disable Operation Mode */ -#define RB_RST_CLR BIT_1S /* Clear RAM Buf STM Reset */ -#define RB_RST_SET BIT_0S /* Set RAM Buf STM Reset */ - - -/* Receive and Transmit MAC FIFO Registers (GENESIS only) */ - -/* RX_MFF_EA 32 bit Receive MAC FIFO End Address */ -/* RX_MFF_WP 32 bit Receive MAC FIFO Write Pointer */ -/* RX_MFF_RP 32 bit Receive MAC FIFO Read Pointer */ -/* RX_MFF_PC 32 bit Receive MAC FIFO Packet Counter */ -/* RX_MFF_LEV 32 bit Receive MAC FIFO Level */ -/* TX_MFF_EA 32 bit Transmit MAC FIFO End Address */ -/* TX_MFF_WP 32 bit Transmit MAC FIFO Write Pointer */ -/* TX_MFF_WSP 32 bit Transmit MAC FIFO WR Shadow Pointer */ -/* TX_MFF_RP 32 bit Transmit MAC FIFO Read Pointer */ -/* TX_MFF_PC 32 bit Transmit MAC FIFO Packet Cnt */ -/* TX_MFF_LEV 32 bit Transmit MAC FIFO Level */ - /* Bit 31.. 6: reserved */ -#define MFF_MSK 0x007fL /* Bit 5.. 0: MAC FIFO Address/Ptr Bits */ - -/* RX_MFF_CTRL1 16 bit Receive MAC FIFO Control Reg 1 */ - /* Bit 15..14: reserved */ -#define MFF_ENA_RDY_PAT BIT_13S /* Enable Ready Patch */ -#define MFF_DIS_RDY_PAT BIT_12S /* Disable Ready Patch */ -#define MFF_ENA_TIM_PAT BIT_11S /* Enable Timing Patch */ -#define MFF_DIS_TIM_PAT BIT_10S /* Disable Timing Patch */ -#define MFF_ENA_ALM_FUL BIT_9S /* Enable AlmostFull Sign */ -#define MFF_DIS_ALM_FUL BIT_8S /* Disable AlmostFull Sign */ -#define MFF_ENA_PAUSE BIT_7S /* Enable Pause Signaling */ -#define MFF_DIS_PAUSE BIT_6S /* Disable Pause Signaling */ -#define MFF_ENA_FLUSH BIT_5S /* Enable Frame Flushing */ -#define MFF_DIS_FLUSH BIT_4S /* Disable Frame Flushing */ -#define MFF_ENA_TIST BIT_3S /* Enable Time Stamp Gener */ -#define MFF_DIS_TIST BIT_2S /* Disable Time Stamp Gener */ -#define MFF_CLR_INTIST BIT_1S /* Clear IRQ No Time Stamp */ -#define MFF_CLR_INSTAT BIT_0S /* Clear IRQ No Status */ - -#define MFF_RX_CTRL_DEF MFF_ENA_TIM_PAT - -/* TX_MFF_CTRL1 16 bit Transmit MAC FIFO Control Reg 1 */ -#define MFF_CLR_PERR BIT_15S /* Clear Parity Error IRQ */ - /* Bit 14: reserved */ -#define MFF_ENA_PKT_REC BIT_13S /* Enable Packet Recovery */ -#define MFF_DIS_PKT_REC BIT_12S /* Disable Packet Recovery */ -/* MFF_ENA_TIM_PAT (see RX_MFF_CTRL1) Bit 11: Enable Timing Patch */ -/* MFF_DIS_TIM_PAT (see RX_MFF_CTRL1) Bit 10: Disable Timing Patch */ -/* MFF_ENA_ALM_FUL (see RX_MFF_CTRL1) Bit 9: Enable Almost Full Sign */ -/* MFF_DIS_ALM_FUL (see RX_MFF_CTRL1) Bit 8: Disable Almost Full Sign */ -#define MFF_ENA_W4E BIT_7S /* Enable Wait for Empty */ -#define MFF_DIS_W4E BIT_6S /* Disable Wait for Empty */ -/* MFF_ENA_FLUSH (see RX_MFF_CTRL1) Bit 5: Enable Frame Flushing */ -/* MFF_DIS_FLUSH (see RX_MFF_CTRL1) Bit 4: Disable Frame Flushing */ -#define MFF_ENA_LOOPB BIT_3S /* Enable Loopback */ -#define MFF_DIS_LOOPB BIT_2S /* Disable Loopback */ -#define MFF_CLR_MAC_RST BIT_1S /* Clear XMAC Reset */ -#define MFF_SET_MAC_RST BIT_0S /* Set XMAC Reset */ - -#define MFF_TX_CTRL_DEF (MFF_ENA_PKT_REC | MFF_ENA_TIM_PAT | MFF_ENA_FLUSH) - -/* RX_MFF_TST2 8 bit Receive MAC FIFO Test Register 2 */ -/* TX_MFF_TST2 8 bit Transmit MAC FIFO Test Register 2 */ - /* Bit 7: reserved */ -#define MFF_WSP_T_ON BIT_6S /* Tx: Write Shadow Ptr TestOn */ -#define MFF_WSP_T_OFF BIT_5S /* Tx: Write Shadow Ptr TstOff */ -#define MFF_WSP_INC BIT_4S /* Tx: Write Shadow Ptr Increment */ -#define MFF_PC_DEC BIT_3S /* Packet Counter Decrement */ -#define MFF_PC_T_ON BIT_2S /* Packet Counter Test On */ -#define MFF_PC_T_OFF BIT_1S /* Packet Counter Test Off */ -#define MFF_PC_INC BIT_0S /* Packet Counter Increment */ - -/* RX_MFF_TST1 8 bit Receive MAC FIFO Test Register 1 */ -/* TX_MFF_TST1 8 bit Transmit MAC FIFO Test Register 1 */ - /* Bit 7: reserved */ -#define MFF_WP_T_ON BIT_6S /* Write Pointer Test On */ -#define MFF_WP_T_OFF BIT_5S /* Write Pointer Test Off */ -#define MFF_WP_INC BIT_4S /* Write Pointer Increm */ - /* Bit 3: reserved */ -#define MFF_RP_T_ON BIT_2S /* Read Pointer Test On */ -#define MFF_RP_T_OFF BIT_1S /* Read Pointer Test Off */ -#define MFF_RP_DEC BIT_0S /* Read Pointer Decrement */ - -/* RX_MFF_CTRL2 8 bit Receive MAC FIFO Control Reg 2 */ -/* TX_MFF_CTRL2 8 bit Transmit MAC FIFO Control Reg 2 */ - /* Bit 7..4: reserved */ -#define MFF_ENA_OP_MD BIT_3S /* Enable Operation Mode */ -#define MFF_DIS_OP_MD BIT_2S /* Disable Operation Mode */ -#define MFF_RST_CLR BIT_1S /* Clear MAC FIFO Reset */ -#define MFF_RST_SET BIT_0S /* Set MAC FIFO Reset */ - - -/* Link LED Counter Registers (GENESIS only) */ - -/* RX_LED_CTRL 8 bit Receive LED Cnt Control Reg */ -/* TX_LED_CTRL 8 bit Transmit LED Cnt Control Reg */ -/* LNK_SYNC_CTRL 8 bit Link Sync Cnt Control Register */ - /* Bit 7.. 3: reserved */ -#define LED_START BIT_2S /* Start Timer */ -#define LED_STOP BIT_1S /* Stop Timer */ -#define LED_STATE BIT_0S /* Rx/Tx: LED State, 1=LED on */ -#define LED_CLR_IRQ BIT_0S /* Lnk: Clear Link IRQ */ - -/* RX_LED_TST 8 bit Receive LED Cnt Test Register */ -/* TX_LED_TST 8 bit Transmit LED Cnt Test Register */ -/* LNK_SYNC_TST 8 bit Link Sync Cnt Test Register */ - /* Bit 7.. 3: reserved */ -#define LED_T_ON BIT_2S /* LED Counter Test mode On */ -#define LED_T_OFF BIT_1S /* LED Counter Test mode Off */ -#define LED_T_STEP BIT_0S /* LED Counter Step */ - -/* LNK_LED_REG 8 bit Link LED Register */ - /* Bit 7.. 6: reserved */ -#define LED_BLK_ON BIT_5S /* Link LED Blinking On */ -#define LED_BLK_OFF BIT_4S /* Link LED Blinking Off */ -#define LED_SYNC_ON BIT_3S /* Use Sync Wire to switch LED */ -#define LED_SYNC_OFF BIT_2S /* Disable Sync Wire Input */ -#define LED_ON BIT_1S /* switch LED on */ -#define LED_OFF BIT_0S /* switch LED off */ - -/* Receive and Transmit GMAC FIFO Registers (YUKON only) */ - -/* RX_GMF_EA 32 bit Rx GMAC FIFO End Address */ -/* RX_GMF_AF_THR 32 bit Rx GMAC FIFO Almost Full Thresh. */ -/* RX_GMF_WP 32 bit Rx GMAC FIFO Write Pointer */ -/* RX_GMF_WLEV 32 bit Rx GMAC FIFO Write Level */ -/* RX_GMF_RP 32 bit Rx GMAC FIFO Read Pointer */ -/* RX_GMF_RLEV 32 bit Rx GMAC FIFO Read Level */ -/* TX_GMF_EA 32 bit Tx GMAC FIFO End Address */ -/* TX_GMF_AE_THR 32 bit Tx GMAC FIFO Almost Empty Thresh.*/ -/* TX_GMF_WP 32 bit Tx GMAC FIFO Write Pointer */ -/* TX_GMF_WSP 32 bit Tx GMAC FIFO Write Shadow Ptr. */ -/* TX_GMF_WLEV 32 bit Tx GMAC FIFO Write Level */ -/* TX_GMF_RP 32 bit Tx GMAC FIFO Read Pointer */ -/* TX_GMF_RSTP 32 bit Tx GMAC FIFO Restart Pointer */ -/* TX_GMF_RLEV 32 bit Tx GMAC FIFO Read Level */ - -/* RX_GMF_CTRL_T 32 bit Rx GMAC FIFO Control/Test */ - /* Bits 31..15: reserved */ -#define GMF_WP_TST_ON BIT_14 /* Write Pointer Test On */ -#define GMF_WP_TST_OFF BIT_13 /* Write Pointer Test Off */ -#define GMF_WP_STEP BIT_12 /* Write Pointer Step/Increment */ - /* Bit 11: reserved */ -#define GMF_RP_TST_ON BIT_10 /* Read Pointer Test On */ -#define GMF_RP_TST_OFF BIT_9 /* Read Pointer Test Off */ -#define GMF_RP_STEP BIT_8 /* Read Pointer Step/Increment */ -#define GMF_RX_F_FL_ON BIT_7 /* Rx FIFO Flush Mode On */ -#define GMF_RX_F_FL_OFF BIT_6 /* Rx FIFO Flush Mode Off */ -#define GMF_CLI_RX_FO BIT_5 /* Clear IRQ Rx FIFO Overrun */ -#define GMF_CLI_RX_FC BIT_4 /* Clear IRQ Rx Frame Complete */ -#define GMF_OPER_ON BIT_3 /* Operational Mode On */ -#define GMF_OPER_OFF BIT_2 /* Operational Mode Off */ -#define GMF_RST_CLR BIT_1 /* Clear GMAC FIFO Reset */ -#define GMF_RST_SET BIT_0 /* Set GMAC FIFO Reset */ - -/* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */ - /* Bits 31..19: reserved */ -#define GMF_WSP_TST_ON BIT_18 /* Write Shadow Pointer Test On */ -#define GMF_WSP_TST_OFF BIT_17 /* Write Shadow Pointer Test Off */ -#define GMF_WSP_STEP BIT_16 /* Write Shadow Pointer Step/Increment */ - /* Bits 15..7: same as for RX_GMF_CTRL_T */ -#define GMF_CLI_TX_FU BIT_6 /* Clear IRQ Tx FIFO Underrun */ -#define GMF_CLI_TX_FC BIT_5 /* Clear IRQ Tx Frame Complete */ -#define GMF_CLI_TX_PE BIT_4 /* Clear IRQ Tx Parity Error */ - /* Bits 3..0: same as for RX_GMF_CTRL_T */ - -#define GMF_RX_CTRL_DEF (GMF_OPER_ON | GMF_RX_F_FL_ON) -#define GMF_TX_CTRL_DEF GMF_OPER_ON - -#define RX_GMF_FL_THR_DEF 0x0a /* Rx GMAC FIFO Flush Threshold default */ - -/* GMAC_TI_ST_CTRL 8 bit Time Stamp Timer Ctrl Reg (YUKON only) */ - /* Bit 7.. 3: reserved */ -#define GMT_ST_START BIT_2S /* Start Time Stamp Timer */ -#define GMT_ST_STOP BIT_1S /* Stop Time Stamp Timer */ -#define GMT_ST_CLR_IRQ BIT_0S /* Clear Time Stamp Timer IRQ */ - -/* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */ - /* Bits 31.. 8: reserved */ -#define GMC_H_BURST_ON BIT_7 /* Half Duplex Burst Mode On */ -#define GMC_H_BURST_OFF BIT_6 /* Half Duplex Burst Mode Off */ -#define GMC_F_LOOPB_ON BIT_5 /* FIFO Loopback On */ -#define GMC_F_LOOPB_OFF BIT_4 /* FIFO Loopback Off */ -#define GMC_PAUSE_ON BIT_3 /* Pause On */ -#define GMC_PAUSE_OFF BIT_2 /* Pause Off */ -#define GMC_RST_CLR BIT_1 /* Clear GMAC Reset */ -#define GMC_RST_SET BIT_0 /* Set GMAC Reset */ - -/* GPHY_CTRL 32 bit GPHY Control Reg (YUKON only) */ - /* Bits 31..29: reserved */ -#define GPC_SEL_BDT BIT_28 /* Select Bi-Dir. Transfer for MDC/MDIO */ -#define GPC_INT_POL_HI BIT_27 /* IRQ Polarity is Active HIGH */ -#define GPC_75_OHM BIT_26 /* Use 75 Ohm Termination instead of 50 */ -#define GPC_DIS_FC BIT_25 /* Disable Automatic Fiber/Copper Detection */ -#define GPC_DIS_SLEEP BIT_24 /* Disable Energy Detect */ -#define GPC_HWCFG_M_3 BIT_23 /* HWCFG_MODE[3] */ -#define GPC_HWCFG_M_2 BIT_22 /* HWCFG_MODE[2] */ -#define GPC_HWCFG_M_1 BIT_21 /* HWCFG_MODE[1] */ -#define GPC_HWCFG_M_0 BIT_20 /* HWCFG_MODE[0] */ -#define GPC_ANEG_0 BIT_19 /* ANEG[0] */ -#define GPC_ENA_XC BIT_18 /* Enable MDI crossover */ -#define GPC_DIS_125 BIT_17 /* Disable 125 MHz clock */ -#define GPC_ANEG_3 BIT_16 /* ANEG[3] */ -#define GPC_ANEG_2 BIT_15 /* ANEG[2] */ -#define GPC_ANEG_1 BIT_14 /* ANEG[1] */ -#define GPC_ENA_PAUSE BIT_13 /* Enable Pause (SYM_OR_REM) */ -#define GPC_PHYADDR_4 BIT_12 /* Bit 4 of Phy Addr */ -#define GPC_PHYADDR_3 BIT_11 /* Bit 3 of Phy Addr */ -#define GPC_PHYADDR_2 BIT_10 /* Bit 2 of Phy Addr */ -#define GPC_PHYADDR_1 BIT_9 /* Bit 1 of Phy Addr */ -#define GPC_PHYADDR_0 BIT_8 /* Bit 0 of Phy Addr */ - /* Bits 7..2: reserved */ -#define GPC_RST_CLR BIT_1 /* Clear GPHY Reset */ -#define GPC_RST_SET BIT_0 /* Set GPHY Reset */ - -#define GPC_HWCFG_GMII_COP (GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | \ - GPC_HWCFG_M_1 | GPC_HWCFG_M_0) - -#define GPC_HWCFG_GMII_FIB ( GPC_HWCFG_M_2 | \ - GPC_HWCFG_M_1 | GPC_HWCFG_M_0) - -#define GPC_ANEG_ADV_ALL_M (GPC_ANEG_3 | GPC_ANEG_2 | \ - GPC_ANEG_1 | GPC_ANEG_0) - -/* forced speed and duplex mode (don't mix with other ANEG bits) */ -#define GPC_FRC10MBIT_HALF 0 -#define GPC_FRC10MBIT_FULL GPC_ANEG_0 -#define GPC_FRC100MBIT_HALF GPC_ANEG_1 -#define GPC_FRC100MBIT_FULL (GPC_ANEG_0 | GPC_ANEG_1) - -/* auto-negotiation with limited advertised speeds */ -/* mix only with master/slave settings (for copper) */ -#define GPC_ADV_1000_HALF GPC_ANEG_2 -#define GPC_ADV_1000_FULL GPC_ANEG_3 -#define GPC_ADV_ALL (GPC_ANEG_2 | GPC_ANEG_3) - -/* master/slave settings */ -/* only for copper with 1000 Mbps */ -#define GPC_FORCE_MASTER 0 -#define GPC_FORCE_SLAVE GPC_ANEG_0 -#define GPC_PREF_MASTER GPC_ANEG_1 -#define GPC_PREF_SLAVE (GPC_ANEG_1 | GPC_ANEG_0) - -/* GMAC_IRQ_SRC 8 bit GMAC Interrupt Source Reg (YUKON only) */ -/* GMAC_IRQ_MSK 8 bit GMAC Interrupt Mask Reg (YUKON only) */ -#define GM_IS_TX_CO_OV BIT_5 /* Transmit Counter Overflow IRQ */ -#define GM_IS_RX_CO_OV BIT_4 /* Receive Counter Overflow IRQ */ -#define GM_IS_TX_FF_UR BIT_3 /* Transmit FIFO Underrun */ -#define GM_IS_TX_COMPL BIT_2 /* Frame Transmission Complete */ -#define GM_IS_RX_FF_OR BIT_1 /* Receive FIFO Overrun */ -#define GM_IS_RX_COMPL BIT_0 /* Frame Reception Complete */ - -#define GMAC_DEF_MSK (GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | \ - GM_IS_TX_FF_UR) - -/* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */ - /* Bits 15.. 2: reserved */ -#define GMLC_RST_CLR BIT_1S /* Clear GMAC Link Reset */ -#define GMLC_RST_SET BIT_0S /* Set GMAC Link Reset */ - - -/* WOL_CTRL_STAT 16 bit WOL Control/Status Reg */ -#define WOL_CTL_LINK_CHG_OCC BIT_15S -#define WOL_CTL_MAGIC_PKT_OCC BIT_14S -#define WOL_CTL_PATTERN_OCC BIT_13S - -#define WOL_CTL_CLEAR_RESULT BIT_12S - -#define WOL_CTL_ENA_PME_ON_LINK_CHG BIT_11S -#define WOL_CTL_DIS_PME_ON_LINK_CHG BIT_10S -#define WOL_CTL_ENA_PME_ON_MAGIC_PKT BIT_9S -#define WOL_CTL_DIS_PME_ON_MAGIC_PKT BIT_8S -#define WOL_CTL_ENA_PME_ON_PATTERN BIT_7S -#define WOL_CTL_DIS_PME_ON_PATTERN BIT_6S - -#define WOL_CTL_ENA_LINK_CHG_UNIT BIT_5S -#define WOL_CTL_DIS_LINK_CHG_UNIT BIT_4S -#define WOL_CTL_ENA_MAGIC_PKT_UNIT BIT_3S -#define WOL_CTL_DIS_MAGIC_PKT_UNIT BIT_2S -#define WOL_CTL_ENA_PATTERN_UNIT BIT_1S -#define WOL_CTL_DIS_PATTERN_UNIT BIT_0S - -#define WOL_CTL_DEFAULT \ - (WOL_CTL_DIS_PME_ON_LINK_CHG | \ - WOL_CTL_DIS_PME_ON_PATTERN | \ - WOL_CTL_DIS_PME_ON_MAGIC_PKT | \ - WOL_CTL_DIS_LINK_CHG_UNIT | \ - WOL_CTL_DIS_PATTERN_UNIT | \ - WOL_CTL_DIS_MAGIC_PKT_UNIT) - -/* WOL_MATCH_CTL 8 bit WOL Match Control Reg */ -#define WOL_CTL_PATT_ENA(x) (BIT_0 << (x)) - -#define SK_NUM_WOL_PATTERN 7 -#define SK_PATTERN_PER_WORD 4 -#define SK_BITMASK_PATTERN 7 -#define SK_POW_PATTERN_LENGTH 128 - -#define WOL_LENGTH_MSK 0x7f -#define WOL_LENGTH_SHIFT 8 - - -/* Receive and Transmit Descriptors ******************************************/ - -/* Transmit Descriptor struct */ -typedef struct s_HwTxd { - SK_U32 volatile TxCtrl; /* Transmit Buffer Control Field */ - SK_U32 TxNext; /* Physical Address Pointer to the next TxD */ - SK_U32 TxAdrLo; /* Physical Tx Buffer Address lower dword */ - SK_U32 TxAdrHi; /* Physical Tx Buffer Address upper dword */ - SK_U32 TxStat; /* Transmit Frame Status Word */ -#ifndef SK_USE_REV_DESC - SK_U16 TxTcpOffs; /* TCP Checksum Calculation Start Value */ - SK_U16 TxRes1; /* 16 bit reserved field */ - SK_U16 TxTcpWp; /* TCP Checksum Write Position */ - SK_U16 TxTcpSp; /* TCP Checksum Calculation Start Position */ -#else /* SK_USE_REV_DESC */ - SK_U16 TxRes1; /* 16 bit reserved field */ - SK_U16 TxTcpOffs; /* TCP Checksum Calculation Start Value */ - SK_U16 TxTcpSp; /* TCP Checksum Calculation Start Position */ - SK_U16 TxTcpWp; /* TCP Checksum Write Position */ -#endif /* SK_USE_REV_DESC */ - SK_U32 TxRes2; /* 32 bit reserved field */ -} SK_HWTXD; - -/* Receive Descriptor struct */ -typedef struct s_HwRxd { - SK_U32 volatile RxCtrl; /* Receive Buffer Control Field */ - SK_U32 RxNext; /* Physical Address Pointer to the next RxD */ - SK_U32 RxAdrLo; /* Physical Rx Buffer Address lower dword */ - SK_U32 RxAdrHi; /* Physical Rx Buffer Address upper dword */ - SK_U32 RxStat; /* Receive Frame Status Word */ - SK_U32 RxTiSt; /* Receive Time Stamp (from XMAC on GENESIS) */ -#ifndef SK_USE_REV_DESC - SK_U16 RxTcpSum1; /* TCP Checksum 1 */ - SK_U16 RxTcpSum2; /* TCP Checksum 2 */ - SK_U16 RxTcpSp1; /* TCP Checksum Calculation Start Position 1 */ - SK_U16 RxTcpSp2; /* TCP Checksum Calculation Start Position 2 */ -#else /* SK_USE_REV_DESC */ - SK_U16 RxTcpSum2; /* TCP Checksum 2 */ - SK_U16 RxTcpSum1; /* TCP Checksum 1 */ - SK_U16 RxTcpSp2; /* TCP Checksum Calculation Start Position 2 */ - SK_U16 RxTcpSp1; /* TCP Checksum Calculation Start Position 1 */ -#endif /* SK_USE_REV_DESC */ -} SK_HWRXD; - -/* - * Drivers which use the reverse descriptor feature (PCI_OUR_REG_2) - * should set the define SK_USE_REV_DESC. - * Structures are 'normaly' not endianess dependent. But in - * this case the SK_U16 fields are bound to bit positions inside the - * descriptor. RxTcpSum1 e.g. must start at bit 0 within the 6.th DWord. - * The bit positions inside a DWord are of course endianess dependent and - * swaps if the DWord is swapped by the hardware. - */ - - -/* Descriptor Bit Definition */ -/* TxCtrl Transmit Buffer Control Field */ -/* RxCtrl Receive Buffer Control Field */ -#define BMU_OWN BIT_31 /* OWN bit: 0=host/1=BMU */ -#define BMU_STF BIT_30 /* Start of Frame */ -#define BMU_EOF BIT_29 /* End of Frame */ -#define BMU_IRQ_EOB BIT_28 /* Req "End of Buffer" IRQ */ -#define BMU_IRQ_EOF BIT_27 /* Req "End of Frame" IRQ */ -/* TxCtrl specific bits */ -#define BMU_STFWD BIT_26 /* (Tx) Store & Forward Frame */ -#define BMU_NO_FCS BIT_25 /* (Tx) Disable MAC FCS (CRC) generation */ -#define BMU_SW BIT_24 /* (Tx) 1 bit res. for SW use */ -/* RxCtrl specific bits */ -#define BMU_DEV_0 BIT_26 /* (Rx) Transfer data to Dev0 */ -#define BMU_STAT_VAL BIT_25 /* (Rx) Rx Status Valid */ -#define BMU_TIST_VAL BIT_24 /* (Rx) Rx TimeStamp Valid */ - /* Bit 23..16: BMU Check Opcodes */ -#define BMU_CHECK (0x55L<<16) /* Default BMU check */ -#define BMU_TCP_CHECK (0x56L<<16) /* Descr with TCP ext */ -#define BMU_UDP_CHECK (0x57L<<16) /* Descr with UDP ext (YUKON only) */ -#define BMU_BBC 0xffffL /* Bit 15.. 0: Buffer Byte Counter */ - -/* TxStat Transmit Frame Status Word */ -/* RxStat Receive Frame Status Word */ -/* - *Note: TxStat is reserved for ASIC loopback mode only - * - * The Bits of the Status words are defined in xmac_ii.h - * (see XMR_FS bits) - */ - -/* macros ********************************************************************/ - -/* Receive and Transmit Queues */ -#define Q_R1 0x0000 /* Receive Queue 1 */ -#define Q_R2 0x0080 /* Receive Queue 2 */ -#define Q_XS1 0x0200 /* Synchronous Transmit Queue 1 */ -#define Q_XA1 0x0280 /* Asynchronous Transmit Queue 1 */ -#define Q_XS2 0x0300 /* Synchronous Transmit Queue 2 */ -#define Q_XA2 0x0380 /* Asynchronous Transmit Queue 2 */ - -/* - * Macro Q_ADDR() - * - * Use this macro to access the Receive and Transmit Queue Registers. - * - * para: - * Queue Queue to access. - * Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2 - * Offs Queue register offset. - * Values: Q_D, Q_DA_L ... Q_T2, Q_T3 - * - * usage SK_IN32(pAC, Q_ADDR(Q_R2, Q_BC), pVal) - */ -#define Q_ADDR(Queue, Offs) (B8_Q_REGS + (Queue) + (Offs)) - -/* - * Macro RB_ADDR() - * - * Use this macro to access the RAM Buffer Registers. - * - * para: - * Queue Queue to access. - * Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2 - * Offs Queue register offset. - * Values: RB_START, RB_END ... RB_LEV, RB_CTRL - * - * usage SK_IN32(pAC, RB_ADDR(Q_R2, RB_RP), pVal) - */ -#define RB_ADDR(Queue, Offs) (B16_RAM_REGS + (Queue) + (Offs)) - - -/* MAC Related Registers */ -#define MAC_1 0 /* belongs to the port near the slot */ -#define MAC_2 1 /* belongs to the port far away from the slot */ - -/* - * Macro MR_ADDR() - * - * Use this macro to access a MAC Related Registers inside the ASIC. - * - * para: - * Mac MAC to access. - * Values: MAC_1, MAC_2 - * Offs MAC register offset. - * Values: RX_MFF_EA, RX_MFF_WP ... LNK_LED_REG, - * TX_MFF_EA, TX_MFF_WP ... TX_LED_TST - * - * usage SK_IN32(pAC, MR_ADDR(MAC_1, TX_MFF_EA), pVal) - */ -#define MR_ADDR(Mac, Offs) (((Mac) << 7) + (Offs)) - -#ifdef SK_LITTLE_ENDIAN -#define XM_WORD_LO 0 -#define XM_WORD_HI 1 -#else /* !SK_LITTLE_ENDIAN */ -#define XM_WORD_LO 1 -#define XM_WORD_HI 0 -#endif /* !SK_LITTLE_ENDIAN */ - - -/* - * macros to access the XMAC (GENESIS only) - * - * XM_IN16(), to read a 16 bit register (e.g. XM_MMU_CMD) - * XM_OUT16(), to write a 16 bit register (e.g. XM_MMU_CMD) - * XM_IN32(), to read a 32 bit register (e.g. XM_TX_EV_CNT) - * XM_OUT32(), to write a 32 bit register (e.g. XM_TX_EV_CNT) - * XM_INADDR(), to read a network address register (e.g. XM_SRC_CHK) - * XM_OUTADDR(), to write a network address register (e.g. XM_SRC_CHK) - * XM_INHASH(), to read the XM_HSM_CHK register - * XM_OUTHASH() to write the XM_HSM_CHK register - * - * para: - * Mac XMAC to access values: MAC_1 or MAC_2 - * IoC I/O context needed for SK I/O macros - * Reg XMAC Register to read or write - * (p)Val Value or pointer to the value which should be read or written - * - * usage: XM_OUT16(IoC, MAC_1, XM_MMU_CMD, Value); - */ - -#define XMA(Mac, Reg) \ - ((BASE_XMAC_1 + (Mac) * (BASE_XMAC_2 - BASE_XMAC_1)) | ((Reg) << 1)) - -#define XM_IN16(IoC, Mac, Reg, pVal) \ - SK_IN16((IoC), XMA((Mac), (Reg)), (pVal)) - -#define XM_OUT16(IoC, Mac, Reg, Val) \ - SK_OUT16((IoC), XMA((Mac), (Reg)), (Val)) - -#define XM_IN32(IoC, Mac, Reg, pVal) { \ - SK_IN16((IoC), XMA((Mac), (Reg)), \ - (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_LO]); \ - SK_IN16((IoC), XMA((Mac), (Reg+2)), \ - (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_HI]); \ -} - -#define XM_OUT32(IoC, Mac, Reg, Val) { \ - SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL)); \ - SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16)(((Val) >> 16) & 0xffffL));\ -} - -/* Remember: we are always writing to / reading from LITTLE ENDIAN memory */ - -#define XM_INADDR(IoC, Mac, Reg, pVal) { \ - SK_U16 Word; \ - SK_U8 *pByte; \ - pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ - SK_IN16((IoC), XMA((Mac), (Reg)), &Word); \ - pByte[0] = (SK_U8)(Word & 0x00ff); \ - pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word); \ - pByte[2] = (SK_U8)(Word & 0x00ff); \ - pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word); \ - pByte[4] = (SK_U8)(Word & 0x00ff); \ - pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \ -} - -#define XM_OUTADDR(IoC, Mac, Reg, pVal) { \ - SK_U8 SK_FAR *pByte; \ - pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \ - SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16) \ - (((SK_U16)(pByte[0]) & 0x00ff) | \ - (((SK_U16)(pByte[1]) << 8) & 0xff00))); \ - SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16) \ - (((SK_U16)(pByte[2]) & 0x00ff) | \ - (((SK_U16)(pByte[3]) << 8) & 0xff00))); \ - SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16) \ - (((SK_U16)(pByte[4]) & 0x00ff) | \ - (((SK_U16)(pByte[5]) << 8) & 0xff00))); \ -} - -#define XM_INHASH(IoC, Mac, Reg, pVal) { \ - SK_U16 Word; \ - SK_U8 SK_FAR *pByte; \ - pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \ - SK_IN16((IoC), XMA((Mac), (Reg)), &Word); \ - pByte[0] = (SK_U8)(Word & 0x00ff); \ - pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word); \ - pByte[2] = (SK_U8)(Word & 0x00ff); \ - pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word); \ - pByte[4] = (SK_U8)(Word & 0x00ff); \ - pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), XMA((Mac), (Reg+6)), &Word); \ - pByte[6] = (SK_U8)(Word & 0x00ff); \ - pByte[7] = (SK_U8)((Word >> 8) & 0x00ff); \ -} - -#define XM_OUTHASH(IoC, Mac, Reg, pVal) { \ - SK_U8 SK_FAR *pByte; \ - pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \ - SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16) \ - (((SK_U16)(pByte[0]) & 0x00ff)| \ - (((SK_U16)(pByte[1]) << 8) & 0xff00))); \ - SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16) \ - (((SK_U16)(pByte[2]) & 0x00ff)| \ - (((SK_U16)(pByte[3]) << 8) & 0xff00))); \ - SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16) \ - (((SK_U16)(pByte[4]) & 0x00ff)| \ - (((SK_U16)(pByte[5]) << 8) & 0xff00))); \ - SK_OUT16((IoC), XMA((Mac), (Reg+6)), (SK_U16) \ - (((SK_U16)(pByte[6]) & 0x00ff)| \ - (((SK_U16)(pByte[7]) << 8) & 0xff00))); \ -} - -/* - * macros to access the GMAC (YUKON only) - * - * GM_IN16(), to read a 16 bit register (e.g. GM_GP_STAT) - * GM_OUT16(), to write a 16 bit register (e.g. GM_GP_CTRL) - * GM_IN32(), to read a 32 bit register (e.g. GM_) - * GM_OUT32(), to write a 32 bit register (e.g. GM_) - * GM_INADDR(), to read a network address register (e.g. GM_SRC_ADDR_1L) - * GM_OUTADDR(), to write a network address register (e.g. GM_SRC_ADDR_2L) - * GM_INHASH(), to read the GM_MC_ADDR_H1 register - * GM_OUTHASH() to write the GM_MC_ADDR_H1 register - * - * para: - * Mac GMAC to access values: MAC_1 or MAC_2 - * IoC I/O context needed for SK I/O macros - * Reg GMAC Register to read or write - * (p)Val Value or pointer to the value which should be read or written - * - * usage: GM_OUT16(IoC, MAC_1, GM_GP_CTRL, Value); - */ - -#define GMA(Mac, Reg) \ - ((BASE_GMAC_1 + (Mac) * (BASE_GMAC_2 - BASE_GMAC_1)) | (Reg)) - -#define GM_IN16(IoC, Mac, Reg, pVal) \ - SK_IN16((IoC), GMA((Mac), (Reg)), (pVal)) - -#define GM_OUT16(IoC, Mac, Reg, Val) \ - SK_OUT16((IoC), GMA((Mac), (Reg)), (Val)) - -#define GM_IN32(IoC, Mac, Reg, pVal) { \ - SK_IN16((IoC), GMA((Mac), (Reg)), \ - (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_LO]); \ - SK_IN16((IoC), GMA((Mac), (Reg+4)), \ - (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_HI]); \ -} - -#define GM_OUT32(IoC, Mac, Reg, Val) { \ - SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL)); \ - SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16)(((Val) >> 16) & 0xffffL));\ -} - -#define GM_INADDR(IoC, Mac, Reg, pVal) { \ - SK_U16 Word; \ - SK_U8 *pByte; \ - pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ - SK_IN16((IoC), GMA((Mac), (Reg)), &Word); \ - pByte[0] = (SK_U8)(Word & 0x00ff); \ - pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word); \ - pByte[2] = (SK_U8)(Word & 0x00ff); \ - pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word); \ - pByte[4] = (SK_U8)(Word & 0x00ff); \ - pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \ -} - -#define GM_OUTADDR(IoC, Mac, Reg, pVal) { \ - SK_U8 SK_FAR *pByte; \ - pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \ - SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16) \ - (((SK_U16)(pByte[0]) & 0x00ff) | \ - (((SK_U16)(pByte[1]) << 8) & 0xff00))); \ - SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16) \ - (((SK_U16)(pByte[2]) & 0x00ff) | \ - (((SK_U16)(pByte[3]) << 8) & 0xff00))); \ - SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16) \ - (((SK_U16)(pByte[4]) & 0x00ff) | \ - (((SK_U16)(pByte[5]) << 8) & 0xff00))); \ -} - -#define GM_INHASH(IoC, Mac, Reg, pVal) { \ - SK_U16 Word; \ - SK_U8 *pByte; \ - pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ - SK_IN16((IoC), GMA((Mac), (Reg)), &Word); \ - pByte[0] = (SK_U8)(Word & 0x00ff); \ - pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word); \ - pByte[2] = (SK_U8)(Word & 0x00ff); \ - pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word); \ - pByte[4] = (SK_U8)(Word & 0x00ff); \ - pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), GMA((Mac), (Reg+12)), &Word); \ - pByte[6] = (SK_U8)(Word & 0x00ff); \ - pByte[7] = (SK_U8)((Word >> 8) & 0x00ff); \ -} - -#define GM_OUTHASH(IoC, Mac, Reg, pVal) { \ - SK_U8 *pByte; \ - pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ - SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16) \ - (((SK_U16)(pByte[0]) & 0x00ff)| \ - (((SK_U16)(pByte[1]) << 8) & 0xff00))); \ - SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16) \ - (((SK_U16)(pByte[2]) & 0x00ff)| \ - (((SK_U16)(pByte[3]) << 8) & 0xff00))); \ - SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16) \ - (((SK_U16)(pByte[4]) & 0x00ff)| \ - (((SK_U16)(pByte[5]) << 8) & 0xff00))); \ - SK_OUT16((IoC), GMA((Mac), (Reg+12)), (SK_U16) \ - (((SK_U16)(pByte[6]) & 0x00ff)| \ - (((SK_U16)(pByte[7]) << 8) & 0xff00))); \ -} - -/* - * Different MAC Types - */ -#define SK_MAC_XMAC 0 /* Xaqti XMAC II */ -#define SK_MAC_GMAC 1 /* Marvell GMAC */ - -/* - * Different PHY Types - */ -#define SK_PHY_XMAC 0 /* integrated in XMAC II */ -#define SK_PHY_BCOM 1 /* Broadcom BCM5400 */ -#define SK_PHY_LONE 2 /* Level One LXT1000 */ -#define SK_PHY_NAT 3 /* National DP83891 */ -#define SK_PHY_MARV_COPPER 4 /* Marvell 88E1011S */ -#define SK_PHY_MARV_FIBER 5 /* Marvell 88E1011S working on fiber */ - -/* - * PHY addresses (bits 12..8 of PHY address reg) - */ -#define PHY_ADDR_XMAC (0<<8) -#define PHY_ADDR_BCOM (1<<8) -#define PHY_ADDR_LONE (3<<8) -#define PHY_ADDR_NAT (0<<8) - -/* GPHY address (bits 15..11 of SMI control reg) */ -#define PHY_ADDR_MARV 0 - -/* - * macros to access the PHY - * - * PHY_READ() read a 16 bit value from the PHY - * PHY_WRITE() write a 16 bit value to the PHY - * - * para: - * IoC I/O context needed for SK I/O macros - * pPort Pointer to port struct for PhyAddr - * Mac XMAC to access values: MAC_1 or MAC_2 - * PhyReg PHY Register to read or write - * (p)Val Value or pointer to the value which should be read or - * written. - * - * usage: PHY_READ(IoC, pPort, MAC_1, PHY_CTRL, Value); - * Warning: a PHY_READ on an uninitialized PHY (PHY still in reset) never - * comes back. This is checked in DEBUG mode. - */ -#ifndef DEBUG -#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) { \ - SK_U16 Mmu; \ - \ - XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \ - XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \ - if ((pPort)->PhyType != SK_PHY_XMAC) { \ - do { \ - XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \ - } while ((Mmu & XM_MMU_PHY_RDY) == 0); \ - XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \ - } \ -} -#else -#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) { \ - SK_U16 Mmu; \ - int __i = 0; \ - \ - XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \ - XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \ - if ((pPort)->PhyType != SK_PHY_XMAC) { \ - do { \ - XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \ - __i++; \ - if (__i > 100000) { \ - SK_DBG_PRINTF("*****************************\n"); \ - SK_DBG_PRINTF("PHY_READ on uninitialized PHY\n"); \ - SK_DBG_PRINTF("*****************************\n"); \ - break; \ - } \ - } while ((Mmu & XM_MMU_PHY_RDY) == 0); \ - XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \ - } \ -} -#endif /* DEBUG */ - -#define PHY_WRITE(IoC, pPort, Mac, PhyReg, Val) { \ - SK_U16 Mmu; \ - \ - if ((pPort)->PhyType != SK_PHY_XMAC) { \ - do { \ - XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \ - } while ((Mmu & XM_MMU_PHY_BUSY) != 0); \ - } \ - XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \ - XM_OUT16((IoC), (Mac), XM_PHY_DATA, (Val)); \ - if ((pPort)->PhyType != SK_PHY_XMAC) { \ - do { \ - XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \ - } while ((Mmu & XM_MMU_PHY_BUSY) != 0); \ - } \ -} - -/* - * Macro PCI_C() - * - * Use this macro to access PCI config register from the I/O space. - * - * para: - * Addr PCI configuration register to access. - * Values: PCI_VENDOR_ID ... PCI_VPD_ADR_REG, - * - * usage SK_IN16(pAC, PCI_C(PCI_VENDOR_ID), pVal); - */ -#define PCI_C(Addr) (B7_CFG_SPC + (Addr)) /* PCI Config Space */ - -/* - * Macro SK_HW_ADDR(Base, Addr) - * - * Calculates the effective HW address - * - * para: - * Base I/O or memory base address - * Addr Address offset - * - * usage: May be used in SK_INxx and SK_OUTxx macros - * #define SK_IN8(pAC, Addr, pVal) ...\ - * *pVal = (SK_U8)inp(SK_HW_ADDR(pAC->Hw.Iop, Addr))) - */ -#ifdef SK_MEM_MAPPED_IO -#define SK_HW_ADDR(Base, Addr) ((Base) + (Addr)) -#else /* SK_MEM_MAPPED_IO */ -#define SK_HW_ADDR(Base, Addr) \ - ((Base) + (((Addr) & 0x7f) | (((Addr) >> 7 > 0) ? 0x80 : 0))) -#endif /* SK_MEM_MAPPED_IO */ - -#define SZ_LONG (sizeof(SK_U32)) - -/* - * Macro SK_HWAC_LINK_LED() - * - * Use this macro to set the link LED mode. - * para: - * pAC Pointer to adapter context struct - * IoC I/O context needed for SK I/O macros - * Port Port number - * Mode Mode to set for this LED - */ -#define SK_HWAC_LINK_LED(pAC, IoC, Port, Mode) \ - SK_OUT8(IoC, MR_ADDR(Port, LNK_LED_REG), Mode); - - -/* typedefs *******************************************************************/ - - -/* function prototypes ********************************************************/ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __INC_SKGEHW_H */ diff --git a/drivers/net/sk98lin/h/skgehwt.h b/drivers/net/sk98lin/h/skgehwt.h deleted file mode 100644 index e6b0016a695..00000000000 --- a/drivers/net/sk98lin/h/skgehwt.h +++ /dev/null @@ -1,48 +0,0 @@ -/****************************************************************************** - * - * Name: skhwt.h - * Project: Gigabit Ethernet Adapters, Event Scheduler Module - * Version: $Revision: 1.7 $ - * Date: $Date: 2003/09/16 12:55:08 $ - * Purpose: Defines for the hardware timer functions - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - * SKGEHWT.H contains all defines and types for the timer functions - */ - -#ifndef _SKGEHWT_H_ -#define _SKGEHWT_H_ - -/* - * SK Hardware Timer - * - needed wherever the HWT module is used - * - use in Adapters context name pAC->Hwt - */ -typedef struct s_Hwt { - SK_U32 TStart; /* HWT start */ - SK_U32 TStop; /* HWT stop */ - int TActive; /* HWT: flag : active/inactive */ -} SK_HWT; - -extern void SkHwtInit(SK_AC *pAC, SK_IOC Ioc); -extern void SkHwtStart(SK_AC *pAC, SK_IOC Ioc, SK_U32 Time); -extern void SkHwtStop(SK_AC *pAC, SK_IOC Ioc); -extern SK_U32 SkHwtRead(SK_AC *pAC, SK_IOC Ioc); -extern void SkHwtIsr(SK_AC *pAC, SK_IOC Ioc); -#endif /* _SKGEHWT_H_ */ diff --git a/drivers/net/sk98lin/h/skgei2c.h b/drivers/net/sk98lin/h/skgei2c.h deleted file mode 100644 index d9b6f6d8dfe..00000000000 --- a/drivers/net/sk98lin/h/skgei2c.h +++ /dev/null @@ -1,210 +0,0 @@ -/****************************************************************************** - * - * Name: skgei2c.h - * Project: Gigabit Ethernet Adapters, TWSI-Module - * Version: $Revision: 1.25 $ - * Date: $Date: 2003/10/20 09:06:05 $ - * Purpose: Special defines for TWSI - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - * SKGEI2C.H contains all SK-98xx specific defines for the TWSI handling - */ - -#ifndef _INC_SKGEI2C_H_ -#define _INC_SKGEI2C_H_ - -/* - * Macros to access the B2_I2C_CTRL - */ -#define SK_I2C_CTL(IoC, flag, dev, dev_size, reg, burst) \ - SK_OUT32(IoC, B2_I2C_CTRL,\ - (flag ? 0x80000000UL : 0x0L) | \ - (((SK_U32)reg << 16) & I2C_ADDR) | \ - (((SK_U32)dev << 9) & I2C_DEV_SEL) | \ - (dev_size & I2C_DEV_SIZE) | \ - ((burst << 4) & I2C_BURST_LEN)) - -#define SK_I2C_STOP(IoC) { \ - SK_U32 I2cCtrl; \ - SK_IN32(IoC, B2_I2C_CTRL, &I2cCtrl); \ - SK_OUT32(IoC, B2_I2C_CTRL, I2cCtrl | I2C_STOP); \ -} - -#define SK_I2C_GET_CTL(IoC, pI2cCtrl) SK_IN32(IoC, B2_I2C_CTRL, pI2cCtrl) - -/* - * Macros to access the TWSI SW Registers - */ -#define SK_I2C_SET_BIT(IoC, SetBits) { \ - SK_U8 OrgBits; \ - SK_IN8(IoC, B2_I2C_SW, &OrgBits); \ - SK_OUT8(IoC, B2_I2C_SW, OrgBits | (SK_U8)(SetBits)); \ -} - -#define SK_I2C_CLR_BIT(IoC, ClrBits) { \ - SK_U8 OrgBits; \ - SK_IN8(IoC, B2_I2C_SW, &OrgBits); \ - SK_OUT8(IoC, B2_I2C_SW, OrgBits & ~((SK_U8)(ClrBits))); \ -} - -#define SK_I2C_GET_SW(IoC, pI2cSw) SK_IN8(IoC, B2_I2C_SW, pI2cSw) - -/* - * define the possible sensor states - */ -#define SK_SEN_IDLE 0 /* Idle: sensor not read */ -#define SK_SEN_VALUE 1 /* Value Read cycle */ -#define SK_SEN_VALEXT 2 /* Extended Value Read cycle */ - -/* - * Conversion factor to convert read Voltage sensor to milli Volt - * Conversion factor to convert read Temperature sensor to 10th degree Celsius - */ -#define SK_LM80_VT_LSB 22 /* 22mV LSB resolution */ -#define SK_LM80_TEMP_LSB 10 /* 1 degree LSB resolution */ -#define SK_LM80_TEMPEXT_LSB 5 /* 0.5 degree LSB resolution for ext. val. */ - -/* - * formula: counter = (22500*60)/(rpm * divisor * pulses/2) - * assuming: 6500rpm, 4 pulses, divisor 1 - */ -#define SK_LM80_FAN_FAKTOR ((22500L*60)/(1*2)) - -/* - * Define sensor management data - * Maximum is reached on Genesis copper dual port and Yukon-64 - * Board specific maximum is in pAC->I2c.MaxSens - */ -#define SK_MAX_SENSORS 8 /* maximal no. of installed sensors */ -#define SK_MIN_SENSORS 5 /* minimal no. of installed sensors */ - -/* - * To watch the state machine (SM) use the timer in two ways - * instead of one as hitherto - */ -#define SK_TIMER_WATCH_SM 0 /* Watch the SM to finish in a spec. time */ -#define SK_TIMER_NEW_GAUGING 1 /* Start a new gauging when timer expires */ - -/* - * Defines for the individual thresholds - */ - -/* Temperature sensor */ -#define SK_SEN_TEMP_HIGH_ERR 800 /* Temperature High Err Threshold */ -#define SK_SEN_TEMP_HIGH_WARN 700 /* Temperature High Warn Threshold */ -#define SK_SEN_TEMP_LOW_WARN 100 /* Temperature Low Warn Threshold */ -#define SK_SEN_TEMP_LOW_ERR 0 /* Temperature Low Err Threshold */ - -/* VCC which should be 5 V */ -#define SK_SEN_PCI_5V_HIGH_ERR 5588 /* Voltage PCI High Err Threshold */ -#define SK_SEN_PCI_5V_HIGH_WARN 5346 /* Voltage PCI High Warn Threshold */ -#define SK_SEN_PCI_5V_LOW_WARN 4664 /* Voltage PCI Low Warn Threshold */ -#define SK_SEN_PCI_5V_LOW_ERR 4422 /* Voltage PCI Low Err Threshold */ - -/* - * VIO may be 5 V or 3.3 V. Initialization takes two parts: - * 1. Initialize lowest lower limit and highest higher limit. - * 2. After the first value is read correct the upper or the lower limit to - * the appropriate C constant. - * - * Warning limits are +-5% of the exepected voltage. - * Error limits are +-10% of the expected voltage. - */ - -/* Bug fix AF: 16.Aug.2001: Correct the init base of LM80 sensor */ - -#define SK_SEN_PCI_IO_5V_HIGH_ERR 5566 /* + 10% V PCI-IO High Err Threshold */ -#define SK_SEN_PCI_IO_5V_HIGH_WARN 5324 /* + 5% V PCI-IO High Warn Threshold */ - /* 5000 mVolt */ -#define SK_SEN_PCI_IO_5V_LOW_WARN 4686 /* - 5% V PCI-IO Low Warn Threshold */ -#define SK_SEN_PCI_IO_5V_LOW_ERR 4444 /* - 10% V PCI-IO Low Err Threshold */ - -#define SK_SEN_PCI_IO_RANGE_LIMITER 4000 /* 4000 mV range delimiter */ - -/* correction values for the second pass */ -#define SK_SEN_PCI_IO_3V3_HIGH_ERR 3850 /* + 15% V PCI-IO High Err Threshold */ -#define SK_SEN_PCI_IO_3V3_HIGH_WARN 3674 /* + 10% V PCI-IO High Warn Threshold */ - /* 3300 mVolt */ -#define SK_SEN_PCI_IO_3V3_LOW_WARN 2926 /* - 10% V PCI-IO Low Warn Threshold */ -#define SK_SEN_PCI_IO_3V3_LOW_ERR 2772 /* - 15% V PCI-IO Low Err Threshold */ - -/* - * VDD voltage - */ -#define SK_SEN_VDD_HIGH_ERR 3630 /* Voltage ASIC High Err Threshold */ -#define SK_SEN_VDD_HIGH_WARN 3476 /* Voltage ASIC High Warn Threshold */ -#define SK_SEN_VDD_LOW_WARN 3146 /* Voltage ASIC Low Warn Threshold */ -#define SK_SEN_VDD_LOW_ERR 2970 /* Voltage ASIC Low Err Threshold */ - -/* - * PHY PLL 3V3 voltage - */ -#define SK_SEN_PLL_3V3_HIGH_ERR 3630 /* Voltage PMA High Err Threshold */ -#define SK_SEN_PLL_3V3_HIGH_WARN 3476 /* Voltage PMA High Warn Threshold */ -#define SK_SEN_PLL_3V3_LOW_WARN 3146 /* Voltage PMA Low Warn Threshold */ -#define SK_SEN_PLL_3V3_LOW_ERR 2970 /* Voltage PMA Low Err Threshold */ - -/* - * VAUX (YUKON only) - */ -#define SK_SEN_VAUX_3V3_HIGH_ERR 3630 /* Voltage VAUX High Err Threshold */ -#define SK_SEN_VAUX_3V3_HIGH_WARN 3476 /* Voltage VAUX High Warn Threshold */ -#define SK_SEN_VAUX_3V3_LOW_WARN 3146 /* Voltage VAUX Low Warn Threshold */ -#define SK_SEN_VAUX_3V3_LOW_ERR 2970 /* Voltage VAUX Low Err Threshold */ -#define SK_SEN_VAUX_0V_WARN_ERR 0 /* if VAUX not present */ -#define SK_SEN_VAUX_RANGE_LIMITER 1000 /* 1000 mV range delimiter */ - -/* - * PHY 2V5 voltage - */ -#define SK_SEN_PHY_2V5_HIGH_ERR 2750 /* Voltage PHY High Err Threshold */ -#define SK_SEN_PHY_2V5_HIGH_WARN 2640 /* Voltage PHY High Warn Threshold */ -#define SK_SEN_PHY_2V5_LOW_WARN 2376 /* Voltage PHY Low Warn Threshold */ -#define SK_SEN_PHY_2V5_LOW_ERR 2222 /* Voltage PHY Low Err Threshold */ - -/* - * ASIC Core 1V5 voltage (YUKON only) - */ -#define SK_SEN_CORE_1V5_HIGH_ERR 1650 /* Voltage ASIC Core High Err Threshold */ -#define SK_SEN_CORE_1V5_HIGH_WARN 1575 /* Voltage ASIC Core High Warn Threshold */ -#define SK_SEN_CORE_1V5_LOW_WARN 1425 /* Voltage ASIC Core Low Warn Threshold */ -#define SK_SEN_CORE_1V5_LOW_ERR 1350 /* Voltage ASIC Core Low Err Threshold */ - -/* - * FAN 1 speed - */ -/* assuming: 6500rpm +-15%, 4 pulses, - * warning at: 80 % - * error at: 70 % - * no upper limit - */ -#define SK_SEN_FAN_HIGH_ERR 20000 /* FAN Speed High Err Threshold */ -#define SK_SEN_FAN_HIGH_WARN 20000 /* FAN Speed High Warn Threshold */ -#define SK_SEN_FAN_LOW_WARN 5200 /* FAN Speed Low Warn Threshold */ -#define SK_SEN_FAN_LOW_ERR 4550 /* FAN Speed Low Err Threshold */ - -/* - * Some Voltages need dynamic thresholds - */ -#define SK_SEN_DYN_INIT_NONE 0 /* No dynamic init of thresholds */ -#define SK_SEN_DYN_INIT_PCI_IO 10 /* Init PCI-IO with new thresholds */ -#define SK_SEN_DYN_INIT_VAUX 11 /* Init VAUX with new thresholds */ - -extern int SkLm80ReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen); -#endif /* n_INC_SKGEI2C_H */ diff --git a/drivers/net/sk98lin/h/skgeinit.h b/drivers/net/sk98lin/h/skgeinit.h deleted file mode 100644 index 143e635ec24..00000000000 --- a/drivers/net/sk98lin/h/skgeinit.h +++ /dev/null @@ -1,797 +0,0 @@ -/****************************************************************************** - * - * Name: skgeinit.h - * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.83 $ - * Date: $Date: 2003/09/16 14:07:37 $ - * Purpose: Structures and prototypes for the GE Init Module - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#ifndef __INC_SKGEINIT_H_ -#define __INC_SKGEINIT_H_ - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* defines ********************************************************************/ - -#define SK_TEST_VAL 0x11335577UL - -/* modifying Link LED behaviour (used with SkGeLinkLED()) */ -#define SK_LNK_OFF LED_OFF -#define SK_LNK_ON (LED_ON | LED_BLK_OFF | LED_SYNC_OFF) -#define SK_LNK_BLINK (LED_ON | LED_BLK_ON | LED_SYNC_ON) -#define SK_LNK_PERM (LED_ON | LED_BLK_OFF | LED_SYNC_ON) -#define SK_LNK_TST (LED_ON | LED_BLK_ON | LED_SYNC_OFF) - -/* parameter 'Mode' when calling SK_HWAC_LINK_LED() */ -#define SK_LED_OFF LED_OFF -#define SK_LED_ACTIVE (LED_ON | LED_BLK_OFF | LED_SYNC_OFF) -#define SK_LED_STANDBY (LED_ON | LED_BLK_ON | LED_SYNC_OFF) - -/* addressing LED Registers in SkGeXmitLED() */ -#define XMIT_LED_INI 0 -#define XMIT_LED_CNT (RX_LED_VAL - RX_LED_INI) -#define XMIT_LED_CTRL (RX_LED_CTRL- RX_LED_INI) -#define XMIT_LED_TST (RX_LED_TST - RX_LED_INI) - -/* parameter 'Mode' when calling SkGeXmitLED() */ -#define SK_LED_DIS 0 -#define SK_LED_ENA 1 -#define SK_LED_TST 2 - -/* Counter and Timer constants, for a host clock of 62.5 MHz */ -#define SK_XMIT_DUR 0x002faf08UL /* 50 ms */ -#define SK_BLK_DUR 0x01dcd650UL /* 500 ms */ - -#define SK_DPOLL_DEF 0x00ee6b28UL /* 250 ms at 62.5 MHz */ - -#define SK_DPOLL_MAX 0x00ffffffUL /* 268 ms at 62.5 MHz */ - /* 215 ms at 78.12 MHz */ - -#define SK_FACT_62 100 /* is given in percent */ -#define SK_FACT_53 85 /* on GENESIS: 53.12 MHz */ -#define SK_FACT_78 125 /* on YUKON: 78.12 MHz */ - -/* Timeout values */ -#define SK_MAC_TO_53 72 /* MAC arbiter timeout */ -#define SK_PKT_TO_53 0x2000 /* Packet arbiter timeout */ -#define SK_PKT_TO_MAX 0xffff /* Maximum value */ -#define SK_RI_TO_53 36 /* RAM interface timeout */ - -#define SK_PHY_ACC_TO 600000 /* PHY access timeout */ - -/* RAM Buffer High Pause Threshold values */ -#define SK_RB_ULPP ( 8 * 1024) /* Upper Level in kB/8 */ -#define SK_RB_LLPP_S (10 * 1024) /* Lower Level for small Queues */ -#define SK_RB_LLPP_B (16 * 1024) /* Lower Level for big Queues */ - -#ifndef SK_BMU_RX_WM -#define SK_BMU_RX_WM 0x600 /* BMU Rx Watermark */ -#endif -#ifndef SK_BMU_TX_WM -#define SK_BMU_TX_WM 0x600 /* BMU Tx Watermark */ -#endif - -/* XMAC II Rx High Watermark */ -#define SK_XM_RX_HI_WM 0x05aa /* 1450 */ - -/* XMAC II Tx Threshold */ -#define SK_XM_THR_REDL 0x01fb /* .. for redundant link usage */ -#define SK_XM_THR_SL 0x01fb /* .. for single link adapters */ -#define SK_XM_THR_MULL 0x01fb /* .. for multiple link usage */ -#define SK_XM_THR_JUMBO 0x03fc /* .. for jumbo frame usage */ - -/* values for GIPortUsage */ -#define SK_RED_LINK 1 /* redundant link usage */ -#define SK_MUL_LINK 2 /* multiple link usage */ -#define SK_JUMBO_LINK 3 /* driver uses jumbo frames */ - -/* Minimum RAM Buffer Rx Queue Size */ -#define SK_MIN_RXQ_SIZE 16 /* 16 kB */ - -/* Minimum RAM Buffer Tx Queue Size */ -#define SK_MIN_TXQ_SIZE 16 /* 16 kB */ - -/* Queue Size units */ -#define QZ_UNITS 0x7 -#define QZ_STEP 8 - -/* Percentage of queue size from whole memory */ -/* 80 % for receive */ -#define RAM_QUOTA_RX 80L -/* 0% for sync transfer */ -#define RAM_QUOTA_SYNC 0L -/* the rest (20%) is taken for async transfer */ - -/* Get the rounded queue size in Bytes in 8k steps */ -#define ROUND_QUEUE_SIZE(SizeInBytes) \ - ((((unsigned long) (SizeInBytes) + (QZ_STEP*1024L)-1) / 1024) & \ - ~(QZ_STEP-1)) - -/* Get the rounded queue size in KBytes in 8k steps */ -#define ROUND_QUEUE_SIZE_KB(Kilobytes) \ - ROUND_QUEUE_SIZE((Kilobytes) * 1024L) - -/* Types of RAM Buffer Queues */ -#define SK_RX_SRAM_Q 1 /* small receive queue */ -#define SK_RX_BRAM_Q 2 /* big receive queue */ -#define SK_TX_RAM_Q 3 /* small or big transmit queue */ - -/* parameter 'Dir' when calling SkGeStopPort() */ -#define SK_STOP_TX 1 /* Stops the transmit path, resets the XMAC */ -#define SK_STOP_RX 2 /* Stops the receive path */ -#define SK_STOP_ALL 3 /* Stops Rx and Tx path, resets the XMAC */ - -/* parameter 'RstMode' when calling SkGeStopPort() */ -#define SK_SOFT_RST 1 /* perform a software reset */ -#define SK_HARD_RST 2 /* perform a hardware reset */ - -/* Init Levels */ -#define SK_INIT_DATA 0 /* Init level 0: init data structures */ -#define SK_INIT_IO 1 /* Init level 1: init with IOs */ -#define SK_INIT_RUN 2 /* Init level 2: init for run time */ - -/* Link Mode Parameter */ -#define SK_LMODE_HALF 1 /* Half Duplex Mode */ -#define SK_LMODE_FULL 2 /* Full Duplex Mode */ -#define SK_LMODE_AUTOHALF 3 /* AutoHalf Duplex Mode */ -#define SK_LMODE_AUTOFULL 4 /* AutoFull Duplex Mode */ -#define SK_LMODE_AUTOBOTH 5 /* AutoBoth Duplex Mode */ -#define SK_LMODE_AUTOSENSE 6 /* configured mode auto sensing */ -#define SK_LMODE_INDETERMINATED 7 /* indeterminated */ - -/* Auto-negotiation timeout in 100ms granularity */ -#define SK_AND_MAX_TO 6 /* Wait 600 msec before link comes up */ - -/* Auto-negotiation error codes */ -#define SK_AND_OK 0 /* no error */ -#define SK_AND_OTHER 1 /* other error than below */ -#define SK_AND_DUP_CAP 2 /* Duplex capabilities error */ - - -/* Link Speed Capabilities */ -#define SK_LSPEED_CAP_AUTO (1<<0) /* Automatic resolution */ -#define SK_LSPEED_CAP_10MBPS (1<<1) /* 10 Mbps */ -#define SK_LSPEED_CAP_100MBPS (1<<2) /* 100 Mbps */ -#define SK_LSPEED_CAP_1000MBPS (1<<3) /* 1000 Mbps */ -#define SK_LSPEED_CAP_INDETERMINATED (1<<4) /* indeterminated */ - -/* Link Speed Parameter */ -#define SK_LSPEED_AUTO 1 /* Automatic resolution */ -#define SK_LSPEED_10MBPS 2 /* 10 Mbps */ -#define SK_LSPEED_100MBPS 3 /* 100 Mbps */ -#define SK_LSPEED_1000MBPS 4 /* 1000 Mbps */ -#define SK_LSPEED_INDETERMINATED 5 /* indeterminated */ - -/* Link Speed Current State */ -#define SK_LSPEED_STAT_UNKNOWN 1 -#define SK_LSPEED_STAT_10MBPS 2 -#define SK_LSPEED_STAT_100MBPS 3 -#define SK_LSPEED_STAT_1000MBPS 4 -#define SK_LSPEED_STAT_INDETERMINATED 5 - - -/* Link Capability Parameter */ -#define SK_LMODE_CAP_HALF (1<<0) /* Half Duplex Mode */ -#define SK_LMODE_CAP_FULL (1<<1) /* Full Duplex Mode */ -#define SK_LMODE_CAP_AUTOHALF (1<<2) /* AutoHalf Duplex Mode */ -#define SK_LMODE_CAP_AUTOFULL (1<<3) /* AutoFull Duplex Mode */ -#define SK_LMODE_CAP_INDETERMINATED (1<<4) /* indeterminated */ - -/* Link Mode Current State */ -#define SK_LMODE_STAT_UNKNOWN 1 /* Unknown Duplex Mode */ -#define SK_LMODE_STAT_HALF 2 /* Half Duplex Mode */ -#define SK_LMODE_STAT_FULL 3 /* Full Duplex Mode */ -#define SK_LMODE_STAT_AUTOHALF 4 /* Half Duplex Mode obtained by Auto-Neg */ -#define SK_LMODE_STAT_AUTOFULL 5 /* Full Duplex Mode obtained by Auto-Neg */ -#define SK_LMODE_STAT_INDETERMINATED 6 /* indeterminated */ - -/* Flow Control Mode Parameter (and capabilities) */ -#define SK_FLOW_MODE_NONE 1 /* No Flow-Control */ -#define SK_FLOW_MODE_LOC_SEND 2 /* Local station sends PAUSE */ -#define SK_FLOW_MODE_SYMMETRIC 3 /* Both stations may send PAUSE */ -#define SK_FLOW_MODE_SYM_OR_REM 4 /* Both stations may send PAUSE or - * just the remote station may send PAUSE - */ -#define SK_FLOW_MODE_INDETERMINATED 5 /* indeterminated */ - -/* Flow Control Status Parameter */ -#define SK_FLOW_STAT_NONE 1 /* No Flow Control */ -#define SK_FLOW_STAT_REM_SEND 2 /* Remote Station sends PAUSE */ -#define SK_FLOW_STAT_LOC_SEND 3 /* Local station sends PAUSE */ -#define SK_FLOW_STAT_SYMMETRIC 4 /* Both station may send PAUSE */ -#define SK_FLOW_STAT_INDETERMINATED 5 /* indeterminated */ - -/* Master/Slave Mode Capabilities */ -#define SK_MS_CAP_AUTO (1<<0) /* Automatic resolution */ -#define SK_MS_CAP_MASTER (1<<1) /* This station is master */ -#define SK_MS_CAP_SLAVE (1<<2) /* This station is slave */ -#define SK_MS_CAP_INDETERMINATED (1<<3) /* indeterminated */ - -/* Set Master/Slave Mode Parameter (and capabilities) */ -#define SK_MS_MODE_AUTO 1 /* Automatic resolution */ -#define SK_MS_MODE_MASTER 2 /* This station is master */ -#define SK_MS_MODE_SLAVE 3 /* This station is slave */ -#define SK_MS_MODE_INDETERMINATED 4 /* indeterminated */ - -/* Master/Slave Status Parameter */ -#define SK_MS_STAT_UNSET 1 /* The M/S status is not set */ -#define SK_MS_STAT_MASTER 2 /* This station is master */ -#define SK_MS_STAT_SLAVE 3 /* This station is slave */ -#define SK_MS_STAT_FAULT 4 /* M/S resolution failed */ -#define SK_MS_STAT_INDETERMINATED 5 /* indeterminated */ - -/* parameter 'Mode' when calling SkXmSetRxCmd() */ -#define SK_STRIP_FCS_ON (1<<0) /* Enable FCS stripping of Rx frames */ -#define SK_STRIP_FCS_OFF (1<<1) /* Disable FCS stripping of Rx frames */ -#define SK_STRIP_PAD_ON (1<<2) /* Enable pad byte stripping of Rx fr */ -#define SK_STRIP_PAD_OFF (1<<3) /* Disable pad byte stripping of Rx fr */ -#define SK_LENERR_OK_ON (1<<4) /* Don't chk fr for in range len error */ -#define SK_LENERR_OK_OFF (1<<5) /* Check frames for in range len error */ -#define SK_BIG_PK_OK_ON (1<<6) /* Don't set Rx Error bit for big frames */ -#define SK_BIG_PK_OK_OFF (1<<7) /* Set Rx Error bit for big frames */ -#define SK_SELF_RX_ON (1<<8) /* Enable Rx of own packets */ -#define SK_SELF_RX_OFF (1<<9) /* Disable Rx of own packets */ - -/* parameter 'Para' when calling SkMacSetRxTxEn() */ -#define SK_MAC_LOOPB_ON (1<<0) /* Enable MAC Loopback Mode */ -#define SK_MAC_LOOPB_OFF (1<<1) /* Disable MAC Loopback Mode */ -#define SK_PHY_LOOPB_ON (1<<2) /* Enable PHY Loopback Mode */ -#define SK_PHY_LOOPB_OFF (1<<3) /* Disable PHY Loopback Mode */ -#define SK_PHY_FULLD_ON (1<<4) /* Enable GMII Full Duplex */ -#define SK_PHY_FULLD_OFF (1<<5) /* Disable GMII Full Duplex */ - -/* States of PState */ -#define SK_PRT_RESET 0 /* the port is reset */ -#define SK_PRT_STOP 1 /* the port is stopped (similar to SW reset) */ -#define SK_PRT_INIT 2 /* the port is initialized */ -#define SK_PRT_RUN 3 /* the port has an active link */ - -/* PHY power down modes */ -#define PHY_PM_OPERATIONAL_MODE 0 /* PHY operational mode */ -#define PHY_PM_DEEP_SLEEP 1 /* coma mode --> minimal power */ -#define PHY_PM_IEEE_POWER_DOWN 2 /* IEEE 22.2.4.1.5 compl. power down */ -#define PHY_PM_ENERGY_DETECT 3 /* energy detect */ -#define PHY_PM_ENERGY_DETECT_PLUS 4 /* energy detect plus */ - -/* Default receive frame limit for Workaround of XMAC Errata */ -#define SK_DEF_RX_WA_LIM SK_CONSTU64(100) - -/* values for GILedBlinkCtrl (LED Blink Control) */ -#define SK_ACT_LED_BLINK (1<<0) /* Active LED blinking */ -#define SK_DUP_LED_NORMAL (1<<1) /* Duplex LED normal */ -#define SK_LED_LINK100_ON (1<<2) /* Link 100M LED on */ - -/* Link Partner Status */ -#define SK_LIPA_UNKNOWN 0 /* Link partner is in unknown state */ -#define SK_LIPA_MANUAL 1 /* Link partner is in detected manual state */ -#define SK_LIPA_AUTO 2 /* Link partner is in auto-negotiation state */ - -/* Maximum Restarts before restart is ignored (3Com WA) */ -#define SK_MAX_LRESTART 3 /* Max. 3 times the link is restarted */ - -/* Max. Auto-neg. timeouts before link detection in sense mode is reset */ -#define SK_MAX_ANEG_TO 10 /* Max. 10 times the sense mode is reset */ - -/* structures *****************************************************************/ - -/* - * MAC specific functions - */ -typedef struct s_GeMacFunc { - int (*pFnMacUpdateStats)(SK_AC *pAC, SK_IOC IoC, unsigned int Port); - int (*pFnMacStatistic)(SK_AC *pAC, SK_IOC IoC, unsigned int Port, - SK_U16 StatAddr, SK_U32 SK_FAR *pVal); - int (*pFnMacResetCounter)(SK_AC *pAC, SK_IOC IoC, unsigned int Port); - int (*pFnMacOverflow)(SK_AC *pAC, SK_IOC IoC, unsigned int Port, - SK_U16 IStatus, SK_U64 SK_FAR *pVal); -} SK_GEMACFUNC; - -/* - * Port Structure - */ -typedef struct s_GePort { -#ifndef SK_DIAG - SK_TIMER PWaTimer; /* Workaround Timer */ - SK_TIMER HalfDupChkTimer; -#endif /* SK_DIAG */ - SK_U32 PPrevShorts; /* Previous Short Counter checking */ - SK_U32 PPrevFcs; /* Previous FCS Error Counter checking */ - SK_U64 PPrevRx; /* Previous RxOk Counter checking */ - SK_U64 PRxLim; /* Previous RxOk Counter checking */ - SK_U64 LastOctets; /* For half duplex hang check */ - int PLinkResCt; /* Link Restart Counter */ - int PAutoNegTimeOut;/* Auto-negotiation timeout current value */ - int PAutoNegTOCt; /* Auto-negotiation Timeout Counter */ - int PRxQSize; /* Port Rx Queue Size in kB */ - int PXSQSize; /* Port Synchronous Transmit Queue Size in kB */ - int PXAQSize; /* Port Asynchronous Transmit Queue Size in kB */ - SK_U32 PRxQRamStart; /* Receive Queue RAM Buffer Start Address */ - SK_U32 PRxQRamEnd; /* Receive Queue RAM Buffer End Address */ - SK_U32 PXsQRamStart; /* Sync Tx Queue RAM Buffer Start Address */ - SK_U32 PXsQRamEnd; /* Sync Tx Queue RAM Buffer End Address */ - SK_U32 PXaQRamStart; /* Async Tx Queue RAM Buffer Start Address */ - SK_U32 PXaQRamEnd; /* Async Tx Queue RAM Buffer End Address */ - SK_U32 PRxOverCnt; /* Receive Overflow Counter */ - int PRxQOff; /* Rx Queue Address Offset */ - int PXsQOff; /* Synchronous Tx Queue Address Offset */ - int PXaQOff; /* Asynchronous Tx Queue Address Offset */ - int PhyType; /* PHY used on this port */ - int PState; /* Port status (reset, stop, init, run) */ - SK_U16 PhyId1; /* PHY Id1 on this port */ - SK_U16 PhyAddr; /* MDIO/MDC PHY address */ - SK_U16 PIsave; /* Saved Interrupt status word */ - SK_U16 PSsave; /* Saved PHY status word */ - SK_U16 PGmANegAdv; /* Saved GPhy AutoNegAdvertisment register */ - SK_BOOL PHWLinkUp; /* The hardware Link is up (wiring) */ - SK_BOOL PLinkBroken; /* Is Link broken ? */ - SK_BOOL PCheckPar; /* Do we check for parity errors ? */ - SK_BOOL HalfDupTimerActive; - SK_U8 PLinkCap; /* Link Capabilities */ - SK_U8 PLinkModeConf; /* Link Mode configured */ - SK_U8 PLinkMode; /* Link Mode currently used */ - SK_U8 PLinkModeStatus;/* Link Mode Status */ - SK_U8 PLinkSpeedCap; /* Link Speed Capabilities(10/100/1000 Mbps) */ - SK_U8 PLinkSpeed; /* configured Link Speed (10/100/1000 Mbps) */ - SK_U8 PLinkSpeedUsed; /* current Link Speed (10/100/1000 Mbps) */ - SK_U8 PFlowCtrlCap; /* Flow Control Capabilities */ - SK_U8 PFlowCtrlMode; /* Flow Control Mode */ - SK_U8 PFlowCtrlStatus;/* Flow Control Status */ - SK_U8 PMSCap; /* Master/Slave Capabilities */ - SK_U8 PMSMode; /* Master/Slave Mode */ - SK_U8 PMSStatus; /* Master/Slave Status */ - SK_BOOL PAutoNegFail; /* Auto-negotiation fail flag */ - SK_U8 PLipaAutoNeg; /* Auto-negotiation possible with Link Partner */ - SK_U8 PCableLen; /* Cable Length */ - SK_U8 PMdiPairLen[4]; /* MDI[0..3] Pair Length */ - SK_U8 PMdiPairSts[4]; /* MDI[0..3] Pair Diagnostic Status */ - SK_U8 PPhyPowerState; /* PHY current power state */ - int PMacColThres; /* MAC Collision Threshold */ - int PMacJamLen; /* MAC Jam length */ - int PMacJamIpgVal; /* MAC Jam IPG */ - int PMacJamIpgData; /* MAC IPG Jam to Data */ - int PMacIpgData; /* MAC Data IPG */ - SK_BOOL PMacLimit4; /* reset collision counter and backoff algorithm */ -} SK_GEPORT; - -/* - * Gigabit Ethernet Initialization Struct - * (has to be included in the adapter context) - */ -typedef struct s_GeInit { - int GIChipId; /* Chip Identification Number */ - int GIChipRev; /* Chip Revision Number */ - SK_U8 GIPciHwRev; /* PCI HW Revision Number */ - SK_BOOL GIGenesis; /* Genesis adapter ? */ - SK_BOOL GIYukon; /* YUKON-A1/Bx chip */ - SK_BOOL GIYukonLite; /* YUKON-Lite chip */ - SK_BOOL GICopperType; /* Copper Type adapter ? */ - SK_BOOL GIPciSlot64; /* 64-bit PCI Slot */ - SK_BOOL GIPciClock66; /* 66 MHz PCI Clock */ - SK_BOOL GIVauxAvail; /* VAUX available (YUKON) */ - SK_BOOL GIYukon32Bit; /* 32-Bit YUKON adapter */ - SK_U16 GILedBlinkCtrl; /* LED Blink Control */ - int GIMacsFound; /* Number of MACs found on this adapter */ - int GIMacType; /* MAC Type used on this adapter */ - int GIHstClkFact; /* Host Clock Factor (62.5 / HstClk * 100) */ - int GIPortUsage; /* Driver Port Usage */ - int GILevel; /* Initialization Level completed */ - int GIRamSize; /* The RAM size of the adapter in kB */ - int GIWolOffs; /* WOL Register Offset (HW-Bug in Rev. A) */ - SK_U32 GIRamOffs; /* RAM Address Offset for addr calculation */ - SK_U32 GIPollTimerVal; /* Descr. Poll Timer Init Val (HstClk ticks) */ - SK_U32 GIValIrqMask; /* Value for Interrupt Mask */ - SK_U32 GITimeStampCnt; /* Time Stamp High Counter (YUKON only) */ - SK_GEPORT GP[SK_MAX_MACS];/* Port Dependent Information */ - SK_GEMACFUNC GIFunc; /* MAC depedent functions */ -} SK_GEINIT; - -/* - * Error numbers and messages for skxmac2.c and skgeinit.c - */ -#define SKERR_HWI_E001 (SK_ERRBASE_HWINIT) -#define SKERR_HWI_E001MSG "SkXmClrExactAddr() has got illegal parameters" -#define SKERR_HWI_E002 (SKERR_HWI_E001+1) -#define SKERR_HWI_E002MSG "SkGeInit(): Level 1 call missing" -#define SKERR_HWI_E003 (SKERR_HWI_E002+1) -#define SKERR_HWI_E003MSG "SkGeInit() called with illegal init Level" -#define SKERR_HWI_E004 (SKERR_HWI_E003+1) -#define SKERR_HWI_E004MSG "SkGeInitPort(): Queue Size illegal configured" -#define SKERR_HWI_E005 (SKERR_HWI_E004+1) -#define SKERR_HWI_E005MSG "SkGeInitPort(): cannot init running ports" -#define SKERR_HWI_E006 (SKERR_HWI_E005+1) -#define SKERR_HWI_E006MSG "SkGeMacInit(): PState does not match HW state" -#define SKERR_HWI_E007 (SKERR_HWI_E006+1) -#define SKERR_HWI_E007MSG "SkXmInitDupMd() called with invalid Dup Mode" -#define SKERR_HWI_E008 (SKERR_HWI_E007+1) -#define SKERR_HWI_E008MSG "SkXmSetRxCmd() called with invalid Mode" -#define SKERR_HWI_E009 (SKERR_HWI_E008+1) -#define SKERR_HWI_E009MSG "SkGeCfgSync() called although PXSQSize zero" -#define SKERR_HWI_E010 (SKERR_HWI_E009+1) -#define SKERR_HWI_E010MSG "SkGeCfgSync() called with invalid parameters" -#define SKERR_HWI_E011 (SKERR_HWI_E010+1) -#define SKERR_HWI_E011MSG "SkGeInitPort(): Receive Queue Size too small" -#define SKERR_HWI_E012 (SKERR_HWI_E011+1) -#define SKERR_HWI_E012MSG "SkGeInitPort(): invalid Queue Size specified" -#define SKERR_HWI_E013 (SKERR_HWI_E012+1) -#define SKERR_HWI_E013MSG "SkGeInitPort(): cfg changed for running queue" -#define SKERR_HWI_E014 (SKERR_HWI_E013+1) -#define SKERR_HWI_E014MSG "SkGeInitPort(): unknown GIPortUsage specified" -#define SKERR_HWI_E015 (SKERR_HWI_E014+1) -#define SKERR_HWI_E015MSG "Illegal Link mode parameter" -#define SKERR_HWI_E016 (SKERR_HWI_E015+1) -#define SKERR_HWI_E016MSG "Illegal Flow control mode parameter" -#define SKERR_HWI_E017 (SKERR_HWI_E016+1) -#define SKERR_HWI_E017MSG "Illegal value specified for GIPollTimerVal" -#define SKERR_HWI_E018 (SKERR_HWI_E017+1) -#define SKERR_HWI_E018MSG "FATAL: SkGeStopPort() does not terminate (Tx)" -#define SKERR_HWI_E019 (SKERR_HWI_E018+1) -#define SKERR_HWI_E019MSG "Illegal Speed parameter" -#define SKERR_HWI_E020 (SKERR_HWI_E019+1) -#define SKERR_HWI_E020MSG "Illegal Master/Slave parameter" -#define SKERR_HWI_E021 (SKERR_HWI_E020+1) -#define SKERR_HWI_E021MSG "MacUpdateStats(): cannot update statistic counter" -#define SKERR_HWI_E022 (SKERR_HWI_E021+1) -#define SKERR_HWI_E022MSG "MacStatistic(): illegal statistic base address" -#define SKERR_HWI_E023 (SKERR_HWI_E022+1) -#define SKERR_HWI_E023MSG "SkGeInitPort(): Transmit Queue Size too small" -#define SKERR_HWI_E024 (SKERR_HWI_E023+1) -#define SKERR_HWI_E024MSG "FATAL: SkGeStopPort() does not terminate (Rx)" -#define SKERR_HWI_E025 (SKERR_HWI_E024+1) -#define SKERR_HWI_E025MSG "" - -/* function prototypes ********************************************************/ - -#ifndef SK_KR_PROTO - -/* - * public functions in skgeinit.c - */ -extern void SkGePollTxD( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL PollTxD); - -extern void SkGeYellowLED( - SK_AC *pAC, - SK_IOC IoC, - int State); - -extern int SkGeCfgSync( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_U32 IntTime, - SK_U32 LimCount, - int SyncMode); - -extern void SkGeLoadLnkSyncCnt( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_U32 CntVal); - -extern void SkGeStopPort( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Dir, - int RstMode); - -extern int SkGeInit( - SK_AC *pAC, - SK_IOC IoC, - int Level); - -extern void SkGeDeInit( - SK_AC *pAC, - SK_IOC IoC); - -extern int SkGeInitPort( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkGeXmitLED( - SK_AC *pAC, - SK_IOC IoC, - int Led, - int Mode); - -extern int SkGeInitAssignRamToQueues( - SK_AC *pAC, - int ActivePort, - SK_BOOL DualNet); - -/* - * public functions in skxmac2.c - */ -extern void SkMacRxTxDisable( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkMacSoftRst( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkMacHardRst( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkXmInitMac( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkGmInitMac( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkMacInitPhy( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL DoLoop); - -extern void SkMacIrqDisable( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkMacFlushTxFifo( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkMacIrq( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern int SkMacAutoNegDone( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkMacAutoNegLipaPhy( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_U16 IStatus); - -extern int SkMacRxTxEnable( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkMacPromiscMode( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL Enable); - -extern void SkMacHashing( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL Enable); - -extern void SkXmPhyRead( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Addr, - SK_U16 SK_FAR *pVal); - -extern void SkXmPhyWrite( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Addr, - SK_U16 Val); - -extern void SkGmPhyRead( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Addr, - SK_U16 SK_FAR *pVal); - -extern void SkGmPhyWrite( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Addr, - SK_U16 Val); - -extern void SkXmClrExactAddr( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int StartNum, - int StopNum); - -extern void SkXmAutoNegLipaXmac( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_U16 IStatus); - -extern int SkXmUpdateStats( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port); - -extern int SkGmUpdateStats( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port); - -extern int SkXmMacStatistic( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port, - SK_U16 StatAddr, - SK_U32 SK_FAR *pVal); - -extern int SkGmMacStatistic( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port, - SK_U16 StatAddr, - SK_U32 SK_FAR *pVal); - -extern int SkXmResetCounter( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port); - -extern int SkGmResetCounter( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port); - -extern int SkXmOverflowStatus( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port, - SK_U16 IStatus, - SK_U64 SK_FAR *pStatus); - -extern int SkGmOverflowStatus( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port, - SK_U16 MacStatus, - SK_U64 SK_FAR *pStatus); - -extern int SkGmCableDiagStatus( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL StartTest); - -#ifdef SK_DIAG -extern void SkGePhyRead( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Addr, - SK_U16 *pVal); - -extern void SkGePhyWrite( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Addr, - SK_U16 Val); - -extern void SkMacSetRxCmd( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Mode); -extern void SkMacCrcGener( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL Enable); -extern void SkMacTimeStamp( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL Enable); -extern void SkXmSendCont( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL Enable); -#endif /* SK_DIAG */ - -#else /* SK_KR_PROTO */ - -/* - * public functions in skgeinit.c - */ -extern void SkGePollTxD(); -extern void SkGeYellowLED(); -extern int SkGeCfgSync(); -extern void SkGeLoadLnkSyncCnt(); -extern void SkGeStopPort(); -extern int SkGeInit(); -extern void SkGeDeInit(); -extern int SkGeInitPort(); -extern void SkGeXmitLED(); -extern int SkGeInitAssignRamToQueues(); - -/* - * public functions in skxmac2.c - */ -extern void SkMacRxTxDisable(); -extern void SkMacSoftRst(); -extern void SkMacHardRst(); -extern void SkMacInitPhy(); -extern int SkMacRxTxEnable(); -extern void SkMacPromiscMode(); -extern void SkMacHashing(); -extern void SkMacIrqDisable(); -extern void SkMacFlushTxFifo(); -extern void SkMacIrq(); -extern int SkMacAutoNegDone(); -extern void SkMacAutoNegLipaPhy(); -extern void SkXmInitMac(); -extern void SkXmPhyRead(); -extern void SkXmPhyWrite(); -extern void SkGmInitMac(); -extern void SkGmPhyRead(); -extern void SkGmPhyWrite(); -extern void SkXmClrExactAddr(); -extern void SkXmAutoNegLipaXmac(); -extern int SkXmUpdateStats(); -extern int SkGmUpdateStats(); -extern int SkXmMacStatistic(); -extern int SkGmMacStatistic(); -extern int SkXmResetCounter(); -extern int SkGmResetCounter(); -extern int SkXmOverflowStatus(); -extern int SkGmOverflowStatus(); -extern int SkGmCableDiagStatus(); - -#ifdef SK_DIAG -extern void SkGePhyRead(); -extern void SkGePhyWrite(); -extern void SkMacSetRxCmd(); -extern void SkMacCrcGener(); -extern void SkMacTimeStamp(); -extern void SkXmSendCont(); -#endif /* SK_DIAG */ - -#endif /* SK_KR_PROTO */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __INC_SKGEINIT_H_ */ diff --git a/drivers/net/sk98lin/h/skgepnm2.h b/drivers/net/sk98lin/h/skgepnm2.h deleted file mode 100644 index ddd304f1a48..00000000000 --- a/drivers/net/sk98lin/h/skgepnm2.h +++ /dev/null @@ -1,334 +0,0 @@ -/***************************************************************************** - * - * Name: skgepnm2.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.36 $ - * Date: $Date: 2003/05/23 12:45:13 $ - * Purpose: Defines for Private Network Management Interface - * - ****************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#ifndef _SKGEPNM2_H_ -#define _SKGEPNM2_H_ - -/* - * General definitions - */ -#define SK_PNMI_CHIPSET_XMAC 1 /* XMAC11800FP */ -#define SK_PNMI_CHIPSET_YUKON 2 /* YUKON */ - -#define SK_PNMI_BUS_PCI 1 /* PCI bus*/ - -/* - * Actions - */ -#define SK_PNMI_ACT_IDLE 1 -#define SK_PNMI_ACT_RESET 2 -#define SK_PNMI_ACT_SELFTEST 3 -#define SK_PNMI_ACT_RESETCNT 4 - -/* - * VPD releated defines - */ - -#define SK_PNMI_VPD_RW 1 -#define SK_PNMI_VPD_RO 2 - -#define SK_PNMI_VPD_OK 0 -#define SK_PNMI_VPD_NOTFOUND 1 -#define SK_PNMI_VPD_CUT 2 -#define SK_PNMI_VPD_TIMEOUT 3 -#define SK_PNMI_VPD_FULL 4 -#define SK_PNMI_VPD_NOWRITE 5 -#define SK_PNMI_VPD_FATAL 6 - -#define SK_PNMI_VPD_IGNORE 0 -#define SK_PNMI_VPD_CREATE 1 -#define SK_PNMI_VPD_DELETE 2 - - -/* - * RLMT related defines - */ -#define SK_PNMI_DEF_RLMT_CHG_THRES 240 /* 4 changes per minute */ - - -/* - * VCT internal status values - */ -#define SK_PNMI_VCT_PENDING 32 -#define SK_PNMI_VCT_TEST_DONE 64 -#define SK_PNMI_VCT_LINK 128 - -/* - * Internal table definitions - */ -#define SK_PNMI_GET 0 -#define SK_PNMI_PRESET 1 -#define SK_PNMI_SET 2 - -#define SK_PNMI_RO 0 -#define SK_PNMI_RW 1 -#define SK_PNMI_WO 2 - -typedef struct s_OidTabEntry { - SK_U32 Id; - SK_U32 InstanceNo; - unsigned int StructSize; - unsigned int Offset; - int Access; - int (* Func)(SK_AC *pAc, SK_IOC pIo, int action, - SK_U32 Id, char* pBuf, unsigned int* pLen, - SK_U32 Instance, unsigned int TableIndex, - SK_U32 NetNumber); - SK_U16 Param; -} SK_PNMI_TAB_ENTRY; - - -/* - * Trap lengths - */ -#define SK_PNMI_TRAP_SIMPLE_LEN 17 -#define SK_PNMI_TRAP_SENSOR_LEN_BASE 46 -#define SK_PNMI_TRAP_RLMT_CHANGE_LEN 23 -#define SK_PNMI_TRAP_RLMT_PORT_LEN 23 - -/* - * Number of MAC types supported - */ -#define SK_PNMI_MAC_TYPES (SK_MAC_GMAC + 1) - -/* - * MAC statistic data list (overall set for MAC types used) - */ -enum SK_MACSTATS { - SK_PNMI_HTX = 0, - SK_PNMI_HTX_OCTET, - SK_PNMI_HTX_OCTETHIGH = SK_PNMI_HTX_OCTET, - SK_PNMI_HTX_OCTETLOW, - SK_PNMI_HTX_BROADCAST, - SK_PNMI_HTX_MULTICAST, - SK_PNMI_HTX_UNICAST, - SK_PNMI_HTX_BURST, - SK_PNMI_HTX_PMACC, - SK_PNMI_HTX_MACC, - SK_PNMI_HTX_COL, - SK_PNMI_HTX_SINGLE_COL, - SK_PNMI_HTX_MULTI_COL, - SK_PNMI_HTX_EXCESS_COL, - SK_PNMI_HTX_LATE_COL, - SK_PNMI_HTX_DEFFERAL, - SK_PNMI_HTX_EXCESS_DEF, - SK_PNMI_HTX_UNDERRUN, - SK_PNMI_HTX_CARRIER, - SK_PNMI_HTX_UTILUNDER, - SK_PNMI_HTX_UTILOVER, - SK_PNMI_HTX_64, - SK_PNMI_HTX_127, - SK_PNMI_HTX_255, - SK_PNMI_HTX_511, - SK_PNMI_HTX_1023, - SK_PNMI_HTX_MAX, - SK_PNMI_HTX_LONGFRAMES, - SK_PNMI_HTX_SYNC, - SK_PNMI_HTX_SYNC_OCTET, - SK_PNMI_HTX_RESERVED, - - SK_PNMI_HRX, - SK_PNMI_HRX_OCTET, - SK_PNMI_HRX_OCTETHIGH = SK_PNMI_HRX_OCTET, - SK_PNMI_HRX_OCTETLOW, - SK_PNMI_HRX_BADOCTET, - SK_PNMI_HRX_BADOCTETHIGH = SK_PNMI_HRX_BADOCTET, - SK_PNMI_HRX_BADOCTETLOW, - SK_PNMI_HRX_BROADCAST, - SK_PNMI_HRX_MULTICAST, - SK_PNMI_HRX_UNICAST, - SK_PNMI_HRX_PMACC, - SK_PNMI_HRX_MACC, - SK_PNMI_HRX_PMACC_ERR, - SK_PNMI_HRX_MACC_UNKWN, - SK_PNMI_HRX_BURST, - SK_PNMI_HRX_MISSED, - SK_PNMI_HRX_FRAMING, - SK_PNMI_HRX_UNDERSIZE, - SK_PNMI_HRX_OVERFLOW, - SK_PNMI_HRX_JABBER, - SK_PNMI_HRX_CARRIER, - SK_PNMI_HRX_IRLENGTH, - SK_PNMI_HRX_SYMBOL, - SK_PNMI_HRX_SHORTS, - SK_PNMI_HRX_RUNT, - SK_PNMI_HRX_TOO_LONG, - SK_PNMI_HRX_FCS, - SK_PNMI_HRX_CEXT, - SK_PNMI_HRX_UTILUNDER, - SK_PNMI_HRX_UTILOVER, - SK_PNMI_HRX_64, - SK_PNMI_HRX_127, - SK_PNMI_HRX_255, - SK_PNMI_HRX_511, - SK_PNMI_HRX_1023, - SK_PNMI_HRX_MAX, - SK_PNMI_HRX_LONGFRAMES, - - SK_PNMI_HRX_RESERVED, - - SK_PNMI_MAX_IDX /* NOTE: Ensure SK_PNMI_CNT_NO is set to this value */ -}; - -/* - * MAC specific data - */ -typedef struct s_PnmiStatAddr { - SK_U16 Reg; /* MAC register containing the value */ - SK_BOOL GetOffset; /* TRUE: Offset managed by PNMI (call GetStatVal())*/ -} SK_PNMI_STATADDR; - - -/* - * SK_PNMI_STRUCT_DATA copy offset evaluation macros - */ -#define SK_PNMI_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e)) -#define SK_PNMI_MAI_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e)) -#define SK_PNMI_VPD_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_VPD *)0)->e)) -#define SK_PNMI_SEN_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_SENSOR *)0)->e)) -#define SK_PNMI_CHK_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_CHECKSUM *)0)->e)) -#define SK_PNMI_STA_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_STAT *)0)->e)) -#define SK_PNMI_CNF_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_CONF *)0)->e)) -#define SK_PNMI_RLM_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT *)0)->e)) -#define SK_PNMI_MON_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT_MONITOR *)0)->e)) -#define SK_PNMI_TRP_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_TRAP *)0)->e)) - -#define SK_PNMI_SET_STAT(b,s,o) {SK_U32 Val32; char *pVal; \ - Val32 = (s); \ - pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \ - &(((SK_PNMI_STRUCT_DATA *)0)-> \ - ReturnStatus.ErrorStatus)); \ - SK_PNMI_STORE_U32(pVal, Val32); \ - Val32 = (o); \ - pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \ - &(((SK_PNMI_STRUCT_DATA *)0)-> \ - ReturnStatus.ErrorOffset)); \ - SK_PNMI_STORE_U32(pVal, Val32);} - -/* - * Time macros - */ -#ifndef SK_PNMI_HUNDREDS_SEC -#if SK_TICKS_PER_SEC == 100 -#define SK_PNMI_HUNDREDS_SEC(t) (t) -#else -#define SK_PNMI_HUNDREDS_SEC(t) (((t) * 100) / (SK_TICKS_PER_SEC)) -#endif /* !SK_TICKS_PER_SEC */ -#endif /* !SK_PNMI_HUNDREDS_SEC */ - -/* - * Macros to work around alignment problems - */ -#ifndef SK_PNMI_STORE_U16 -#define SK_PNMI_STORE_U16(p,v) {*(char *)(p) = *((char *)&(v)); \ - *((char *)(p) + 1) = \ - *(((char *)&(v)) + 1);} -#endif - -#ifndef SK_PNMI_STORE_U32 -#define SK_PNMI_STORE_U32(p,v) {*(char *)(p) = *((char *)&(v)); \ - *((char *)(p) + 1) = \ - *(((char *)&(v)) + 1); \ - *((char *)(p) + 2) = \ - *(((char *)&(v)) + 2); \ - *((char *)(p) + 3) = \ - *(((char *)&(v)) + 3);} -#endif - -#ifndef SK_PNMI_STORE_U64 -#define SK_PNMI_STORE_U64(p,v) {*(char *)(p) = *((char *)&(v)); \ - *((char *)(p) + 1) = \ - *(((char *)&(v)) + 1); \ - *((char *)(p) + 2) = \ - *(((char *)&(v)) + 2); \ - *((char *)(p) + 3) = \ - *(((char *)&(v)) + 3); \ - *((char *)(p) + 4) = \ - *(((char *)&(v)) + 4); \ - *((char *)(p) + 5) = \ - *(((char *)&(v)) + 5); \ - *((char *)(p) + 6) = \ - *(((char *)&(v)) + 6); \ - *((char *)(p) + 7) = \ - *(((char *)&(v)) + 7);} -#endif - -#ifndef SK_PNMI_READ_U16 -#define SK_PNMI_READ_U16(p,v) {*((char *)&(v)) = *(char *)(p); \ - *(((char *)&(v)) + 1) = \ - *((char *)(p) + 1);} -#endif - -#ifndef SK_PNMI_READ_U32 -#define SK_PNMI_READ_U32(p,v) {*((char *)&(v)) = *(char *)(p); \ - *(((char *)&(v)) + 1) = \ - *((char *)(p) + 1); \ - *(((char *)&(v)) + 2) = \ - *((char *)(p) + 2); \ - *(((char *)&(v)) + 3) = \ - *((char *)(p) + 3);} -#endif - -#ifndef SK_PNMI_READ_U64 -#define SK_PNMI_READ_U64(p,v) {*((char *)&(v)) = *(char *)(p); \ - *(((char *)&(v)) + 1) = \ - *((char *)(p) + 1); \ - *(((char *)&(v)) + 2) = \ - *((char *)(p) + 2); \ - *(((char *)&(v)) + 3) = \ - *((char *)(p) + 3); \ - *(((char *)&(v)) + 4) = \ - *((char *)(p) + 4); \ - *(((char *)&(v)) + 5) = \ - *((char *)(p) + 5); \ - *(((char *)&(v)) + 6) = \ - *((char *)(p) + 6); \ - *(((char *)&(v)) + 7) = \ - *((char *)(p) + 7);} -#endif - -/* - * Macros for Debug - */ -#ifdef DEBUG - -#define SK_PNMI_CHECKFLAGS(vSt) {if (pAC->Pnmi.MacUpdatedFlag > 0 || \ - pAC->Pnmi.RlmtUpdatedFlag > 0 || \ - pAC->Pnmi.SirqUpdatedFlag > 0) { \ - SK_DBG_MSG(pAC, \ - SK_DBGMOD_PNMI, \ - SK_DBGCAT_CTRL, \ - ("PNMI: ERR: %s MacUFlag=%d, RlmtUFlag=%d, SirqUFlag=%d\n", \ - vSt, \ - pAC->Pnmi.MacUpdatedFlag, \ - pAC->Pnmi.RlmtUpdatedFlag, \ - pAC->Pnmi.SirqUpdatedFlag))}} - -#else /* !DEBUG */ - -#define SK_PNMI_CHECKFLAGS(vSt) /* Nothing */ - -#endif /* !DEBUG */ - -#endif /* _SKGEPNM2_H_ */ diff --git a/drivers/net/sk98lin/h/skgepnmi.h b/drivers/net/sk98lin/h/skgepnmi.h deleted file mode 100644 index 1ed214ccb25..00000000000 --- a/drivers/net/sk98lin/h/skgepnmi.h +++ /dev/null @@ -1,962 +0,0 @@ -/***************************************************************************** - * - * Name: skgepnmi.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.62 $ - * Date: $Date: 2003/08/15 12:31:52 $ - * Purpose: Defines for Private Network Management Interface - * - ****************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#ifndef _SKGEPNMI_H_ -#define _SKGEPNMI_H_ - -/* - * Include dependencies - */ -#include "h/sktypes.h" -#include "h/skerror.h" -#include "h/sktimer.h" -#include "h/ski2c.h" -#include "h/skaddr.h" -#include "h/skrlmt.h" -#include "h/skvpd.h" - -/* - * Management Database Version - */ -#define SK_PNMI_MDB_VERSION 0x00030001 /* 3.1 */ - - -/* - * Event definitions - */ -#define SK_PNMI_EVT_SIRQ_OVERFLOW 1 /* Counter overflow */ -#define SK_PNMI_EVT_SEN_WAR_LOW 2 /* Lower war thres exceeded */ -#define SK_PNMI_EVT_SEN_WAR_UPP 3 /* Upper war thres exceeded */ -#define SK_PNMI_EVT_SEN_ERR_LOW 4 /* Lower err thres exceeded */ -#define SK_PNMI_EVT_SEN_ERR_UPP 5 /* Upper err thres exceeded */ -#define SK_PNMI_EVT_CHG_EST_TIMER 6 /* Timer event for RLMT Chg */ -#define SK_PNMI_EVT_UTILIZATION_TIMER 7 /* Timer event for Utiliza. */ -#define SK_PNMI_EVT_CLEAR_COUNTER 8 /* Clear statistic counters */ -#define SK_PNMI_EVT_XMAC_RESET 9 /* XMAC will be reset */ - -#define SK_PNMI_EVT_RLMT_PORT_UP 10 /* Port came logically up */ -#define SK_PNMI_EVT_RLMT_PORT_DOWN 11 /* Port went logically down */ -#define SK_PNMI_EVT_RLMT_SEGMENTATION 13 /* Two SP root bridges found */ -#define SK_PNMI_EVT_RLMT_ACTIVE_DOWN 14 /* Port went logically down */ -#define SK_PNMI_EVT_RLMT_ACTIVE_UP 15 /* Port came logically up */ -#define SK_PNMI_EVT_RLMT_SET_NETS 16 /* 1. Parameter is number of nets - 1 = single net; 2 = dual net */ -#define SK_PNMI_EVT_VCT_RESET 17 /* VCT port reset timer event started with SET. */ - - -/* - * Return values - */ -#define SK_PNMI_ERR_OK 0 -#define SK_PNMI_ERR_GENERAL 1 -#define SK_PNMI_ERR_TOO_SHORT 2 -#define SK_PNMI_ERR_BAD_VALUE 3 -#define SK_PNMI_ERR_READ_ONLY 4 -#define SK_PNMI_ERR_UNKNOWN_OID 5 -#define SK_PNMI_ERR_UNKNOWN_INST 6 -#define SK_PNMI_ERR_UNKNOWN_NET 7 -#define SK_PNMI_ERR_NOT_SUPPORTED 10 - - -/* - * Return values of driver reset function SK_DRIVER_RESET() and - * driver event function SK_DRIVER_EVENT() - */ -#define SK_PNMI_ERR_OK 0 -#define SK_PNMI_ERR_FAIL 1 - - -/* - * Return values of driver test function SK_DRIVER_SELFTEST() - */ -#define SK_PNMI_TST_UNKNOWN (1 << 0) -#define SK_PNMI_TST_TRANCEIVER (1 << 1) -#define SK_PNMI_TST_ASIC (1 << 2) -#define SK_PNMI_TST_SENSOR (1 << 3) -#define SK_PNMI_TST_POWERMGMT (1 << 4) -#define SK_PNMI_TST_PCI (1 << 5) -#define SK_PNMI_TST_MAC (1 << 6) - - -/* - * RLMT specific definitions - */ -#define SK_PNMI_RLMT_STATUS_STANDBY 1 -#define SK_PNMI_RLMT_STATUS_ACTIVE 2 -#define SK_PNMI_RLMT_STATUS_ERROR 3 - -#define SK_PNMI_RLMT_LSTAT_PHY_DOWN 1 -#define SK_PNMI_RLMT_LSTAT_AUTONEG 2 -#define SK_PNMI_RLMT_LSTAT_LOG_DOWN 3 -#define SK_PNMI_RLMT_LSTAT_LOG_UP 4 -#define SK_PNMI_RLMT_LSTAT_INDETERMINATED 5 - -#define SK_PNMI_RLMT_MODE_CHK_LINK (SK_RLMT_CHECK_LINK) -#define SK_PNMI_RLMT_MODE_CHK_RX (SK_RLMT_CHECK_LOC_LINK) -#define SK_PNMI_RLMT_MODE_CHK_SPT (SK_RLMT_CHECK_SEG) -/* #define SK_PNMI_RLMT_MODE_CHK_EX */ - -/* - * OID definition - */ -#ifndef _NDIS_ /* Check, whether NDIS already included OIDs */ - -#define OID_GEN_XMIT_OK 0x00020101 -#define OID_GEN_RCV_OK 0x00020102 -#define OID_GEN_XMIT_ERROR 0x00020103 -#define OID_GEN_RCV_ERROR 0x00020104 -#define OID_GEN_RCV_NO_BUFFER 0x00020105 - -/* #define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 */ -#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 -/* #define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 */ -#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 -/* #define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 */ -#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 -/* #define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 */ -#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 -/* #define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 */ -#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A -/* #define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B */ -#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C -#define OID_GEN_RCV_CRC_ERROR 0x0002020D -#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E - -#define OID_802_3_PERMANENT_ADDRESS 0x01010101 -#define OID_802_3_CURRENT_ADDRESS 0x01010102 -/* #define OID_802_3_MULTICAST_LIST 0x01010103 */ -/* #define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 */ -/* #define OID_802_3_MAC_OPTIONS 0x01010105 */ - -#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 -#define OID_802_3_XMIT_ONE_COLLISION 0x01020102 -#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 -#define OID_802_3_XMIT_DEFERRED 0x01020201 -#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 -#define OID_802_3_RCV_OVERRUN 0x01020203 -#define OID_802_3_XMIT_UNDERRUN 0x01020204 -#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 -#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 - -/* - * PnP and PM OIDs - */ -#ifdef SK_POWER_MGMT -#define OID_PNP_CAPABILITIES 0xFD010100 -#define OID_PNP_SET_POWER 0xFD010101 -#define OID_PNP_QUERY_POWER 0xFD010102 -#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103 -#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104 -#define OID_PNP_ENABLE_WAKE_UP 0xFD010106 -#endif /* SK_POWER_MGMT */ - -#endif /* _NDIS_ */ - -#define OID_SKGE_MDB_VERSION 0xFF010100 -#define OID_SKGE_SUPPORTED_LIST 0xFF010101 -#define OID_SKGE_VPD_FREE_BYTES 0xFF010102 -#define OID_SKGE_VPD_ENTRIES_LIST 0xFF010103 -#define OID_SKGE_VPD_ENTRIES_NUMBER 0xFF010104 -#define OID_SKGE_VPD_KEY 0xFF010105 -#define OID_SKGE_VPD_VALUE 0xFF010106 -#define OID_SKGE_VPD_ACCESS 0xFF010107 -#define OID_SKGE_VPD_ACTION 0xFF010108 - -#define OID_SKGE_PORT_NUMBER 0xFF010110 -#define OID_SKGE_DEVICE_TYPE 0xFF010111 -#define OID_SKGE_DRIVER_DESCR 0xFF010112 -#define OID_SKGE_DRIVER_VERSION 0xFF010113 -#define OID_SKGE_HW_DESCR 0xFF010114 -#define OID_SKGE_HW_VERSION 0xFF010115 -#define OID_SKGE_CHIPSET 0xFF010116 -#define OID_SKGE_ACTION 0xFF010117 -#define OID_SKGE_RESULT 0xFF010118 -#define OID_SKGE_BUS_TYPE 0xFF010119 -#define OID_SKGE_BUS_SPEED 0xFF01011A -#define OID_SKGE_BUS_WIDTH 0xFF01011B -/* 0xFF01011C unused */ -#define OID_SKGE_DIAG_ACTION 0xFF01011D -#define OID_SKGE_DIAG_RESULT 0xFF01011E -#define OID_SKGE_MTU 0xFF01011F -#define OID_SKGE_PHYS_CUR_ADDR 0xFF010120 -#define OID_SKGE_PHYS_FAC_ADDR 0xFF010121 -#define OID_SKGE_PMD 0xFF010122 -#define OID_SKGE_CONNECTOR 0xFF010123 -#define OID_SKGE_LINK_CAP 0xFF010124 -#define OID_SKGE_LINK_MODE 0xFF010125 -#define OID_SKGE_LINK_MODE_STATUS 0xFF010126 -#define OID_SKGE_LINK_STATUS 0xFF010127 -#define OID_SKGE_FLOWCTRL_CAP 0xFF010128 -#define OID_SKGE_FLOWCTRL_MODE 0xFF010129 -#define OID_SKGE_FLOWCTRL_STATUS 0xFF01012A -#define OID_SKGE_PHY_OPERATION_CAP 0xFF01012B -#define OID_SKGE_PHY_OPERATION_MODE 0xFF01012C -#define OID_SKGE_PHY_OPERATION_STATUS 0xFF01012D -#define OID_SKGE_MULTICAST_LIST 0xFF01012E -#define OID_SKGE_CURRENT_PACKET_FILTER 0xFF01012F - -#define OID_SKGE_TRAP 0xFF010130 -#define OID_SKGE_TRAP_NUMBER 0xFF010131 - -#define OID_SKGE_RLMT_MODE 0xFF010140 -#define OID_SKGE_RLMT_PORT_NUMBER 0xFF010141 -#define OID_SKGE_RLMT_PORT_ACTIVE 0xFF010142 -#define OID_SKGE_RLMT_PORT_PREFERRED 0xFF010143 -#define OID_SKGE_INTERMEDIATE_SUPPORT 0xFF010160 - -#define OID_SKGE_SPEED_CAP 0xFF010170 -#define OID_SKGE_SPEED_MODE 0xFF010171 -#define OID_SKGE_SPEED_STATUS 0xFF010172 - -#define OID_SKGE_BOARDLEVEL 0xFF010180 - -#define OID_SKGE_SENSOR_NUMBER 0xFF020100 -#define OID_SKGE_SENSOR_INDEX 0xFF020101 -#define OID_SKGE_SENSOR_DESCR 0xFF020102 -#define OID_SKGE_SENSOR_TYPE 0xFF020103 -#define OID_SKGE_SENSOR_VALUE 0xFF020104 -#define OID_SKGE_SENSOR_WAR_THRES_LOW 0xFF020105 -#define OID_SKGE_SENSOR_WAR_THRES_UPP 0xFF020106 -#define OID_SKGE_SENSOR_ERR_THRES_LOW 0xFF020107 -#define OID_SKGE_SENSOR_ERR_THRES_UPP 0xFF020108 -#define OID_SKGE_SENSOR_STATUS 0xFF020109 -#define OID_SKGE_SENSOR_WAR_CTS 0xFF02010A -#define OID_SKGE_SENSOR_ERR_CTS 0xFF02010B -#define OID_SKGE_SENSOR_WAR_TIME 0xFF02010C -#define OID_SKGE_SENSOR_ERR_TIME 0xFF02010D - -#define OID_SKGE_CHKSM_NUMBER 0xFF020110 -#define OID_SKGE_CHKSM_RX_OK_CTS 0xFF020111 -#define OID_SKGE_CHKSM_RX_UNABLE_CTS 0xFF020112 -#define OID_SKGE_CHKSM_RX_ERR_CTS 0xFF020113 -#define OID_SKGE_CHKSM_TX_OK_CTS 0xFF020114 -#define OID_SKGE_CHKSM_TX_UNABLE_CTS 0xFF020115 - -#define OID_SKGE_STAT_TX 0xFF020120 -#define OID_SKGE_STAT_TX_OCTETS 0xFF020121 -#define OID_SKGE_STAT_TX_BROADCAST 0xFF020122 -#define OID_SKGE_STAT_TX_MULTICAST 0xFF020123 -#define OID_SKGE_STAT_TX_UNICAST 0xFF020124 -#define OID_SKGE_STAT_TX_LONGFRAMES 0xFF020125 -#define OID_SKGE_STAT_TX_BURST 0xFF020126 -#define OID_SKGE_STAT_TX_PFLOWC 0xFF020127 -#define OID_SKGE_STAT_TX_FLOWC 0xFF020128 -#define OID_SKGE_STAT_TX_SINGLE_COL 0xFF020129 -#define OID_SKGE_STAT_TX_MULTI_COL 0xFF02012A -#define OID_SKGE_STAT_TX_EXCESS_COL 0xFF02012B -#define OID_SKGE_STAT_TX_LATE_COL 0xFF02012C -#define OID_SKGE_STAT_TX_DEFFERAL 0xFF02012D -#define OID_SKGE_STAT_TX_EXCESS_DEF 0xFF02012E -#define OID_SKGE_STAT_TX_UNDERRUN 0xFF02012F -#define OID_SKGE_STAT_TX_CARRIER 0xFF020130 -/* #define OID_SKGE_STAT_TX_UTIL 0xFF020131 */ -#define OID_SKGE_STAT_TX_64 0xFF020132 -#define OID_SKGE_STAT_TX_127 0xFF020133 -#define OID_SKGE_STAT_TX_255 0xFF020134 -#define OID_SKGE_STAT_TX_511 0xFF020135 -#define OID_SKGE_STAT_TX_1023 0xFF020136 -#define OID_SKGE_STAT_TX_MAX 0xFF020137 -#define OID_SKGE_STAT_TX_SYNC 0xFF020138 -#define OID_SKGE_STAT_TX_SYNC_OCTETS 0xFF020139 -#define OID_SKGE_STAT_RX 0xFF02013A -#define OID_SKGE_STAT_RX_OCTETS 0xFF02013B -#define OID_SKGE_STAT_RX_BROADCAST 0xFF02013C -#define OID_SKGE_STAT_RX_MULTICAST 0xFF02013D -#define OID_SKGE_STAT_RX_UNICAST 0xFF02013E -#define OID_SKGE_STAT_RX_PFLOWC 0xFF02013F -#define OID_SKGE_STAT_RX_FLOWC 0xFF020140 -#define OID_SKGE_STAT_RX_PFLOWC_ERR 0xFF020141 -#define OID_SKGE_STAT_RX_FLOWC_UNKWN 0xFF020142 -#define OID_SKGE_STAT_RX_BURST 0xFF020143 -#define OID_SKGE_STAT_RX_MISSED 0xFF020144 -#define OID_SKGE_STAT_RX_FRAMING 0xFF020145 -#define OID_SKGE_STAT_RX_OVERFLOW 0xFF020146 -#define OID_SKGE_STAT_RX_JABBER 0xFF020147 -#define OID_SKGE_STAT_RX_CARRIER 0xFF020148 -#define OID_SKGE_STAT_RX_IR_LENGTH 0xFF020149 -#define OID_SKGE_STAT_RX_SYMBOL 0xFF02014A -#define OID_SKGE_STAT_RX_SHORTS 0xFF02014B -#define OID_SKGE_STAT_RX_RUNT 0xFF02014C -#define OID_SKGE_STAT_RX_CEXT 0xFF02014D -#define OID_SKGE_STAT_RX_TOO_LONG 0xFF02014E -#define OID_SKGE_STAT_RX_FCS 0xFF02014F -/* #define OID_SKGE_STAT_RX_UTIL 0xFF020150 */ -#define OID_SKGE_STAT_RX_64 0xFF020151 -#define OID_SKGE_STAT_RX_127 0xFF020152 -#define OID_SKGE_STAT_RX_255 0xFF020153 -#define OID_SKGE_STAT_RX_511 0xFF020154 -#define OID_SKGE_STAT_RX_1023 0xFF020155 -#define OID_SKGE_STAT_RX_MAX 0xFF020156 -#define OID_SKGE_STAT_RX_LONGFRAMES 0xFF020157 - -#define OID_SKGE_RLMT_CHANGE_CTS 0xFF020160 -#define OID_SKGE_RLMT_CHANGE_TIME 0xFF020161 -#define OID_SKGE_RLMT_CHANGE_ESTIM 0xFF020162 -#define OID_SKGE_RLMT_CHANGE_THRES 0xFF020163 - -#define OID_SKGE_RLMT_PORT_INDEX 0xFF020164 -#define OID_SKGE_RLMT_STATUS 0xFF020165 -#define OID_SKGE_RLMT_TX_HELLO_CTS 0xFF020166 -#define OID_SKGE_RLMT_RX_HELLO_CTS 0xFF020167 -#define OID_SKGE_RLMT_TX_SP_REQ_CTS 0xFF020168 -#define OID_SKGE_RLMT_RX_SP_CTS 0xFF020169 - -#define OID_SKGE_RLMT_MONITOR_NUMBER 0xFF010150 -#define OID_SKGE_RLMT_MONITOR_INDEX 0xFF010151 -#define OID_SKGE_RLMT_MONITOR_ADDR 0xFF010152 -#define OID_SKGE_RLMT_MONITOR_ERRS 0xFF010153 -#define OID_SKGE_RLMT_MONITOR_TIMESTAMP 0xFF010154 -#define OID_SKGE_RLMT_MONITOR_ADMIN 0xFF010155 - -#define OID_SKGE_TX_SW_QUEUE_LEN 0xFF020170 -#define OID_SKGE_TX_SW_QUEUE_MAX 0xFF020171 -#define OID_SKGE_TX_RETRY 0xFF020172 -#define OID_SKGE_RX_INTR_CTS 0xFF020173 -#define OID_SKGE_TX_INTR_CTS 0xFF020174 -#define OID_SKGE_RX_NO_BUF_CTS 0xFF020175 -#define OID_SKGE_TX_NO_BUF_CTS 0xFF020176 -#define OID_SKGE_TX_USED_DESCR_NO 0xFF020177 -#define OID_SKGE_RX_DELIVERED_CTS 0xFF020178 -#define OID_SKGE_RX_OCTETS_DELIV_CTS 0xFF020179 -#define OID_SKGE_RX_HW_ERROR_CTS 0xFF02017A -#define OID_SKGE_TX_HW_ERROR_CTS 0xFF02017B -#define OID_SKGE_IN_ERRORS_CTS 0xFF02017C -#define OID_SKGE_OUT_ERROR_CTS 0xFF02017D -#define OID_SKGE_ERR_RECOVERY_CTS 0xFF02017E -#define OID_SKGE_SYSUPTIME 0xFF02017F - -#define OID_SKGE_ALL_DATA 0xFF020190 - -/* Defines for VCT. */ -#define OID_SKGE_VCT_GET 0xFF020200 -#define OID_SKGE_VCT_SET 0xFF020201 -#define OID_SKGE_VCT_STATUS 0xFF020202 - -#ifdef SK_DIAG_SUPPORT -/* Defines for driver DIAG mode. */ -#define OID_SKGE_DIAG_MODE 0xFF020204 -#endif /* SK_DIAG_SUPPORT */ - -/* New OIDs */ -#define OID_SKGE_DRIVER_RELDATE 0xFF020210 -#define OID_SKGE_DRIVER_FILENAME 0xFF020211 -#define OID_SKGE_CHIPID 0xFF020212 -#define OID_SKGE_RAMSIZE 0xFF020213 -#define OID_SKGE_VAUXAVAIL 0xFF020214 -#define OID_SKGE_PHY_TYPE 0xFF020215 -#define OID_SKGE_PHY_LP_MODE 0xFF020216 - -/* VCT struct to store a backup copy of VCT data after a port reset. */ -typedef struct s_PnmiVct { - SK_U8 VctStatus; - SK_U8 PCableLen; - SK_U32 PMdiPairLen[4]; - SK_U8 PMdiPairSts[4]; -} SK_PNMI_VCT; - - -/* VCT status values (to be given to CPA via OID_SKGE_VCT_STATUS). */ -#define SK_PNMI_VCT_NONE 0 -#define SK_PNMI_VCT_OLD_VCT_DATA 1 -#define SK_PNMI_VCT_NEW_VCT_DATA 2 -#define SK_PNMI_VCT_OLD_DSP_DATA 4 -#define SK_PNMI_VCT_NEW_DSP_DATA 8 -#define SK_PNMI_VCT_RUNNING 16 - - -/* VCT cable test status. */ -#define SK_PNMI_VCT_NORMAL_CABLE 0 -#define SK_PNMI_VCT_SHORT_CABLE 1 -#define SK_PNMI_VCT_OPEN_CABLE 2 -#define SK_PNMI_VCT_TEST_FAIL 3 -#define SK_PNMI_VCT_IMPEDANCE_MISMATCH 4 - -#define OID_SKGE_TRAP_SEN_WAR_LOW 500 -#define OID_SKGE_TRAP_SEN_WAR_UPP 501 -#define OID_SKGE_TRAP_SEN_ERR_LOW 502 -#define OID_SKGE_TRAP_SEN_ERR_UPP 503 -#define OID_SKGE_TRAP_RLMT_CHANGE_THRES 520 -#define OID_SKGE_TRAP_RLMT_CHANGE_PORT 521 -#define OID_SKGE_TRAP_RLMT_PORT_DOWN 522 -#define OID_SKGE_TRAP_RLMT_PORT_UP 523 -#define OID_SKGE_TRAP_RLMT_SEGMENTATION 524 - -#ifdef SK_DIAG_SUPPORT -/* Defines for driver DIAG mode. */ -#define SK_DIAG_ATTACHED 2 -#define SK_DIAG_RUNNING 1 -#define SK_DIAG_IDLE 0 -#endif /* SK_DIAG_SUPPORT */ - -/* - * Generic PNMI IOCTL subcommand definitions. - */ -#define SK_GET_SINGLE_VAR 1 -#define SK_SET_SINGLE_VAR 2 -#define SK_PRESET_SINGLE_VAR 3 -#define SK_GET_FULL_MIB 4 -#define SK_SET_FULL_MIB 5 -#define SK_PRESET_FULL_MIB 6 - - -/* - * Define error numbers and messages for syslog - */ -#define SK_PNMI_ERR001 (SK_ERRBASE_PNMI + 1) -#define SK_PNMI_ERR001MSG "SkPnmiGetStruct: Unknown OID" -#define SK_PNMI_ERR002 (SK_ERRBASE_PNMI + 2) -#define SK_PNMI_ERR002MSG "SkPnmiGetStruct: Cannot read VPD keys" -#define SK_PNMI_ERR003 (SK_ERRBASE_PNMI + 3) -#define SK_PNMI_ERR003MSG "OidStruct: Called with wrong OID" -#define SK_PNMI_ERR004 (SK_ERRBASE_PNMI + 4) -#define SK_PNMI_ERR004MSG "OidStruct: Called with wrong action" -#define SK_PNMI_ERR005 (SK_ERRBASE_PNMI + 5) -#define SK_PNMI_ERR005MSG "Perform: Cannot reset driver" -#define SK_PNMI_ERR006 (SK_ERRBASE_PNMI + 6) -#define SK_PNMI_ERR006MSG "Perform: Unknown OID action command" -#define SK_PNMI_ERR007 (SK_ERRBASE_PNMI + 7) -#define SK_PNMI_ERR007MSG "General: Driver description not initialized" -#define SK_PNMI_ERR008 (SK_ERRBASE_PNMI + 8) -#define SK_PNMI_ERR008MSG "Addr: Tried to get unknown OID" -#define SK_PNMI_ERR009 (SK_ERRBASE_PNMI + 9) -#define SK_PNMI_ERR009MSG "Addr: Unknown OID" -#define SK_PNMI_ERR010 (SK_ERRBASE_PNMI + 10) -#define SK_PNMI_ERR010MSG "CsumStat: Unknown OID" -#define SK_PNMI_ERR011 (SK_ERRBASE_PNMI + 11) -#define SK_PNMI_ERR011MSG "SensorStat: Sensor descr string too long" -#define SK_PNMI_ERR012 (SK_ERRBASE_PNMI + 12) -#define SK_PNMI_ERR012MSG "SensorStat: Unknown OID" -#define SK_PNMI_ERR013 (SK_ERRBASE_PNMI + 13) -#define SK_PNMI_ERR013MSG "" -#define SK_PNMI_ERR014 (SK_ERRBASE_PNMI + 14) -#define SK_PNMI_ERR014MSG "Vpd: Cannot read VPD keys" -#define SK_PNMI_ERR015 (SK_ERRBASE_PNMI + 15) -#define SK_PNMI_ERR015MSG "Vpd: Internal array for VPD keys to small" -#define SK_PNMI_ERR016 (SK_ERRBASE_PNMI + 16) -#define SK_PNMI_ERR016MSG "Vpd: Key string too long" -#define SK_PNMI_ERR017 (SK_ERRBASE_PNMI + 17) -#define SK_PNMI_ERR017MSG "Vpd: Invalid VPD status pointer" -#define SK_PNMI_ERR018 (SK_ERRBASE_PNMI + 18) -#define SK_PNMI_ERR018MSG "Vpd: VPD data not valid" -#define SK_PNMI_ERR019 (SK_ERRBASE_PNMI + 19) -#define SK_PNMI_ERR019MSG "Vpd: VPD entries list string too long" -#define SK_PNMI_ERR021 (SK_ERRBASE_PNMI + 21) -#define SK_PNMI_ERR021MSG "Vpd: VPD data string too long" -#define SK_PNMI_ERR022 (SK_ERRBASE_PNMI + 22) -#define SK_PNMI_ERR022MSG "Vpd: VPD data string too long should be errored before" -#define SK_PNMI_ERR023 (SK_ERRBASE_PNMI + 23) -#define SK_PNMI_ERR023MSG "Vpd: Unknown OID in get action" -#define SK_PNMI_ERR024 (SK_ERRBASE_PNMI + 24) -#define SK_PNMI_ERR024MSG "Vpd: Unknown OID in preset/set action" -#define SK_PNMI_ERR025 (SK_ERRBASE_PNMI + 25) -#define SK_PNMI_ERR025MSG "Vpd: Cannot write VPD after modify entry" -#define SK_PNMI_ERR026 (SK_ERRBASE_PNMI + 26) -#define SK_PNMI_ERR026MSG "Vpd: Cannot update VPD" -#define SK_PNMI_ERR027 (SK_ERRBASE_PNMI + 27) -#define SK_PNMI_ERR027MSG "Vpd: Cannot delete VPD entry" -#define SK_PNMI_ERR028 (SK_ERRBASE_PNMI + 28) -#define SK_PNMI_ERR028MSG "Vpd: Cannot update VPD after delete entry" -#define SK_PNMI_ERR029 (SK_ERRBASE_PNMI + 29) -#define SK_PNMI_ERR029MSG "General: Driver description string too long" -#define SK_PNMI_ERR030 (SK_ERRBASE_PNMI + 30) -#define SK_PNMI_ERR030MSG "General: Driver version not initialized" -#define SK_PNMI_ERR031 (SK_ERRBASE_PNMI + 31) -#define SK_PNMI_ERR031MSG "General: Driver version string too long" -#define SK_PNMI_ERR032 (SK_ERRBASE_PNMI + 32) -#define SK_PNMI_ERR032MSG "General: Cannot read VPD Name for HW descr" -#define SK_PNMI_ERR033 (SK_ERRBASE_PNMI + 33) -#define SK_PNMI_ERR033MSG "General: HW description string too long" -#define SK_PNMI_ERR034 (SK_ERRBASE_PNMI + 34) -#define SK_PNMI_ERR034MSG "General: Unknown OID" -#define SK_PNMI_ERR035 (SK_ERRBASE_PNMI + 35) -#define SK_PNMI_ERR035MSG "Rlmt: Unknown OID" -#define SK_PNMI_ERR036 (SK_ERRBASE_PNMI + 36) -#define SK_PNMI_ERR036MSG "" -#define SK_PNMI_ERR037 (SK_ERRBASE_PNMI + 37) -#define SK_PNMI_ERR037MSG "Rlmt: SK_RLMT_MODE_CHANGE event return not 0" -#define SK_PNMI_ERR038 (SK_ERRBASE_PNMI + 38) -#define SK_PNMI_ERR038MSG "Rlmt: SK_RLMT_PREFPORT_CHANGE event return not 0" -#define SK_PNMI_ERR039 (SK_ERRBASE_PNMI + 39) -#define SK_PNMI_ERR039MSG "RlmtStat: Unknown OID" -#define SK_PNMI_ERR040 (SK_ERRBASE_PNMI + 40) -#define SK_PNMI_ERR040MSG "PowerManagement: Unknown OID" -#define SK_PNMI_ERR041 (SK_ERRBASE_PNMI + 41) -#define SK_PNMI_ERR041MSG "MacPrivateConf: Unknown OID" -#define SK_PNMI_ERR042 (SK_ERRBASE_PNMI + 42) -#define SK_PNMI_ERR042MSG "MacPrivateConf: SK_HWEV_SET_ROLE returned not 0" -#define SK_PNMI_ERR043 (SK_ERRBASE_PNMI + 43) -#define SK_PNMI_ERR043MSG "MacPrivateConf: SK_HWEV_SET_LMODE returned not 0" -#define SK_PNMI_ERR044 (SK_ERRBASE_PNMI + 44) -#define SK_PNMI_ERR044MSG "MacPrivateConf: SK_HWEV_SET_FLOWMODE returned not 0" -#define SK_PNMI_ERR045 (SK_ERRBASE_PNMI + 45) -#define SK_PNMI_ERR045MSG "MacPrivateConf: SK_HWEV_SET_SPEED returned not 0" -#define SK_PNMI_ERR046 (SK_ERRBASE_PNMI + 46) -#define SK_PNMI_ERR046MSG "Monitor: Unknown OID" -#define SK_PNMI_ERR047 (SK_ERRBASE_PNMI + 47) -#define SK_PNMI_ERR047MSG "SirqUpdate: Event function returns not 0" -#define SK_PNMI_ERR048 (SK_ERRBASE_PNMI + 48) -#define SK_PNMI_ERR048MSG "RlmtUpdate: Event function returns not 0" -#define SK_PNMI_ERR049 (SK_ERRBASE_PNMI + 49) -#define SK_PNMI_ERR049MSG "SkPnmiInit: Invalid size of 'CounterOffset' struct!!" -#define SK_PNMI_ERR050 (SK_ERRBASE_PNMI + 50) -#define SK_PNMI_ERR050MSG "SkPnmiInit: Invalid size of 'StatAddr' table!!" -#define SK_PNMI_ERR051 (SK_ERRBASE_PNMI + 51) -#define SK_PNMI_ERR051MSG "SkPnmiEvent: Port switch suspicious" -#define SK_PNMI_ERR052 (SK_ERRBASE_PNMI + 52) -#define SK_PNMI_ERR052MSG "" -#define SK_PNMI_ERR053 (SK_ERRBASE_PNMI + 53) -#define SK_PNMI_ERR053MSG "General: Driver release date not initialized" -#define SK_PNMI_ERR054 (SK_ERRBASE_PNMI + 54) -#define SK_PNMI_ERR054MSG "General: Driver release date string too long" -#define SK_PNMI_ERR055 (SK_ERRBASE_PNMI + 55) -#define SK_PNMI_ERR055MSG "General: Driver file name not initialized" -#define SK_PNMI_ERR056 (SK_ERRBASE_PNMI + 56) -#define SK_PNMI_ERR056MSG "General: Driver file name string too long" - -/* - * Management counter macros called by the driver - */ -#define SK_PNMI_SET_DRIVER_DESCR(pAC,v) ((pAC)->Pnmi.pDriverDescription = \ - (char *)(v)) - -#define SK_PNMI_SET_DRIVER_VER(pAC,v) ((pAC)->Pnmi.pDriverVersion = \ - (char *)(v)) - -#define SK_PNMI_SET_DRIVER_RELDATE(pAC,v) ((pAC)->Pnmi.pDriverReleaseDate = \ - (char *)(v)) - -#define SK_PNMI_SET_DRIVER_FILENAME(pAC,v) ((pAC)->Pnmi.pDriverFileName = \ - (char *)(v)) - -#define SK_PNMI_CNT_TX_QUEUE_LEN(pAC,v,p) \ - { \ - (pAC)->Pnmi.Port[p].TxSwQueueLen = (SK_U64)(v); \ - if ((pAC)->Pnmi.Port[p].TxSwQueueLen > (pAC)->Pnmi.Port[p].TxSwQueueMax) { \ - (pAC)->Pnmi.Port[p].TxSwQueueMax = (pAC)->Pnmi.Port[p].TxSwQueueLen; \ - } \ - } -#define SK_PNMI_CNT_TX_RETRY(pAC,p) (((pAC)->Pnmi.Port[p].TxRetryCts)++) -#define SK_PNMI_CNT_RX_INTR(pAC,p) (((pAC)->Pnmi.Port[p].RxIntrCts)++) -#define SK_PNMI_CNT_TX_INTR(pAC,p) (((pAC)->Pnmi.Port[p].TxIntrCts)++) -#define SK_PNMI_CNT_NO_RX_BUF(pAC,p) (((pAC)->Pnmi.Port[p].RxNoBufCts)++) -#define SK_PNMI_CNT_NO_TX_BUF(pAC,p) (((pAC)->Pnmi.Port[p].TxNoBufCts)++) -#define SK_PNMI_CNT_USED_TX_DESCR(pAC,v,p) \ - ((pAC)->Pnmi.Port[p].TxUsedDescrNo=(SK_U64)(v)); -#define SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,v,p) \ - { \ - ((pAC)->Pnmi.Port[p].RxDeliveredCts)++; \ - (pAC)->Pnmi.Port[p].RxOctetsDeliveredCts += (SK_U64)(v); \ - } -#define SK_PNMI_CNT_ERR_RECOVERY(pAC,p) (((pAC)->Pnmi.Port[p].ErrRecoveryCts)++); - -#define SK_PNMI_CNT_SYNC_OCTETS(pAC,p,v) \ - { \ - if ((p) < SK_MAX_MACS) { \ - ((pAC)->Pnmi.Port[p].StatSyncCts)++; \ - (pAC)->Pnmi.Port[p].StatSyncOctetsCts += (SK_U64)(v); \ - } \ - } - -#define SK_PNMI_CNT_RX_LONGFRAMES(pAC,p) \ - { \ - if ((p) < SK_MAX_MACS) { \ - ((pAC)->Pnmi.Port[p].StatRxLongFrameCts++); \ - } \ - } - -#define SK_PNMI_CNT_RX_FRAMETOOLONG(pAC,p) \ - { \ - if ((p) < SK_MAX_MACS) { \ - ((pAC)->Pnmi.Port[p].StatRxFrameTooLongCts++); \ - } \ - } - -#define SK_PNMI_CNT_RX_PMACC_ERR(pAC,p) \ - { \ - if ((p) < SK_MAX_MACS) { \ - ((pAC)->Pnmi.Port[p].StatRxPMaccErr++); \ - } \ - } - -/* - * Conversion Macros - */ -#define SK_PNMI_PORT_INST2LOG(i) ((unsigned int)(i) - 1) -#define SK_PNMI_PORT_LOG2INST(l) ((unsigned int)(l) + 1) -#define SK_PNMI_PORT_PHYS2LOG(p) ((unsigned int)(p) + 1) -#define SK_PNMI_PORT_LOG2PHYS(pAC,l) ((unsigned int)(l) - 1) -#define SK_PNMI_PORT_PHYS2INST(pAC,p) \ - (pAC->Pnmi.DualNetActiveFlag ? 2 : ((unsigned int)(p) + 2)) -#define SK_PNMI_PORT_INST2PHYS(pAC,i) ((unsigned int)(i) - 2) - -/* - * Structure definition for SkPnmiGetStruct and SkPnmiSetStruct - */ -#define SK_PNMI_VPD_KEY_SIZE 5 -#define SK_PNMI_VPD_BUFSIZE (VPD_SIZE) -#define SK_PNMI_VPD_ENTRIES (VPD_SIZE / 4) -#define SK_PNMI_VPD_DATALEN 128 /* Number of data bytes */ - -#define SK_PNMI_MULTICAST_LISTLEN 64 -#define SK_PNMI_SENSOR_ENTRIES (SK_MAX_SENSORS) -#define SK_PNMI_CHECKSUM_ENTRIES 3 -#define SK_PNMI_MAC_ENTRIES (SK_MAX_MACS + 1) -#define SK_PNMI_MONITOR_ENTRIES 20 -#define SK_PNMI_TRAP_ENTRIES 10 -#define SK_PNMI_TRAPLEN 128 -#define SK_PNMI_STRINGLEN1 80 -#define SK_PNMI_STRINGLEN2 25 -#define SK_PNMI_TRAP_QUEUE_LEN 512 - -typedef struct s_PnmiVpd { - char VpdKey[SK_PNMI_VPD_KEY_SIZE]; - char VpdValue[SK_PNMI_VPD_DATALEN]; - SK_U8 VpdAccess; - SK_U8 VpdAction; -} SK_PNMI_VPD; - -typedef struct s_PnmiSensor { - SK_U8 SensorIndex; - char SensorDescr[SK_PNMI_STRINGLEN2]; - SK_U8 SensorType; - SK_U32 SensorValue; - SK_U32 SensorWarningThresholdLow; - SK_U32 SensorWarningThresholdHigh; - SK_U32 SensorErrorThresholdLow; - SK_U32 SensorErrorThresholdHigh; - SK_U8 SensorStatus; - SK_U64 SensorWarningCts; - SK_U64 SensorErrorCts; - SK_U64 SensorWarningTimestamp; - SK_U64 SensorErrorTimestamp; -} SK_PNMI_SENSOR; - -typedef struct s_PnmiChecksum { - SK_U64 ChecksumRxOkCts; - SK_U64 ChecksumRxUnableCts; - SK_U64 ChecksumRxErrCts; - SK_U64 ChecksumTxOkCts; - SK_U64 ChecksumTxUnableCts; -} SK_PNMI_CHECKSUM; - -typedef struct s_PnmiStat { - SK_U64 StatTxOkCts; - SK_U64 StatTxOctetsOkCts; - SK_U64 StatTxBroadcastOkCts; - SK_U64 StatTxMulticastOkCts; - SK_U64 StatTxUnicastOkCts; - SK_U64 StatTxLongFramesCts; - SK_U64 StatTxBurstCts; - SK_U64 StatTxPauseMacCtrlCts; - SK_U64 StatTxMacCtrlCts; - SK_U64 StatTxSingleCollisionCts; - SK_U64 StatTxMultipleCollisionCts; - SK_U64 StatTxExcessiveCollisionCts; - SK_U64 StatTxLateCollisionCts; - SK_U64 StatTxDeferralCts; - SK_U64 StatTxExcessiveDeferralCts; - SK_U64 StatTxFifoUnderrunCts; - SK_U64 StatTxCarrierCts; - SK_U64 Dummy1; /* StatTxUtilization */ - SK_U64 StatTx64Cts; - SK_U64 StatTx127Cts; - SK_U64 StatTx255Cts; - SK_U64 StatTx511Cts; - SK_U64 StatTx1023Cts; - SK_U64 StatTxMaxCts; - SK_U64 StatTxSyncCts; - SK_U64 StatTxSyncOctetsCts; - SK_U64 StatRxOkCts; - SK_U64 StatRxOctetsOkCts; - SK_U64 StatRxBroadcastOkCts; - SK_U64 StatRxMulticastOkCts; - SK_U64 StatRxUnicastOkCts; - SK_U64 StatRxLongFramesCts; - SK_U64 StatRxPauseMacCtrlCts; - SK_U64 StatRxMacCtrlCts; - SK_U64 StatRxPauseMacCtrlErrorCts; - SK_U64 StatRxMacCtrlUnknownCts; - SK_U64 StatRxBurstCts; - SK_U64 StatRxMissedCts; - SK_U64 StatRxFramingCts; - SK_U64 StatRxFifoOverflowCts; - SK_U64 StatRxJabberCts; - SK_U64 StatRxCarrierCts; - SK_U64 StatRxIRLengthCts; - SK_U64 StatRxSymbolCts; - SK_U64 StatRxShortsCts; - SK_U64 StatRxRuntCts; - SK_U64 StatRxCextCts; - SK_U64 StatRxTooLongCts; - SK_U64 StatRxFcsCts; - SK_U64 Dummy2; /* StatRxUtilization */ - SK_U64 StatRx64Cts; - SK_U64 StatRx127Cts; - SK_U64 StatRx255Cts; - SK_U64 StatRx511Cts; - SK_U64 StatRx1023Cts; - SK_U64 StatRxMaxCts; -} SK_PNMI_STAT; - -typedef struct s_PnmiConf { - char ConfMacCurrentAddr[6]; - char ConfMacFactoryAddr[6]; - SK_U8 ConfPMD; - SK_U8 ConfConnector; - SK_U32 ConfPhyType; - SK_U32 ConfPhyMode; - SK_U8 ConfLinkCapability; - SK_U8 ConfLinkMode; - SK_U8 ConfLinkModeStatus; - SK_U8 ConfLinkStatus; - SK_U8 ConfFlowCtrlCapability; - SK_U8 ConfFlowCtrlMode; - SK_U8 ConfFlowCtrlStatus; - SK_U8 ConfPhyOperationCapability; - SK_U8 ConfPhyOperationMode; - SK_U8 ConfPhyOperationStatus; - SK_U8 ConfSpeedCapability; - SK_U8 ConfSpeedMode; - SK_U8 ConfSpeedStatus; -} SK_PNMI_CONF; - -typedef struct s_PnmiRlmt { - SK_U32 RlmtIndex; - SK_U32 RlmtStatus; - SK_U64 RlmtTxHelloCts; - SK_U64 RlmtRxHelloCts; - SK_U64 RlmtTxSpHelloReqCts; - SK_U64 RlmtRxSpHelloCts; -} SK_PNMI_RLMT; - -typedef struct s_PnmiRlmtMonitor { - SK_U32 RlmtMonitorIndex; - char RlmtMonitorAddr[6]; - SK_U64 RlmtMonitorErrorCts; - SK_U64 RlmtMonitorTimestamp; - SK_U8 RlmtMonitorAdmin; -} SK_PNMI_RLMT_MONITOR; - -typedef struct s_PnmiRequestStatus { - SK_U32 ErrorStatus; - SK_U32 ErrorOffset; -} SK_PNMI_REQUEST_STATUS; - -typedef struct s_PnmiStrucData { - SK_U32 MgmtDBVersion; - SK_PNMI_REQUEST_STATUS ReturnStatus; - SK_U32 VpdFreeBytes; - char VpdEntriesList[SK_PNMI_VPD_ENTRIES * SK_PNMI_VPD_KEY_SIZE]; - SK_U32 VpdEntriesNumber; - SK_PNMI_VPD Vpd[SK_PNMI_VPD_ENTRIES]; - SK_U32 PortNumber; - SK_U32 DeviceType; - char DriverDescr[SK_PNMI_STRINGLEN1]; - char DriverVersion[SK_PNMI_STRINGLEN2]; - char DriverReleaseDate[SK_PNMI_STRINGLEN1]; - char DriverFileName[SK_PNMI_STRINGLEN1]; - char HwDescr[SK_PNMI_STRINGLEN1]; - char HwVersion[SK_PNMI_STRINGLEN2]; - SK_U16 Chipset; - SK_U32 ChipId; - SK_U8 VauxAvail; - SK_U32 RamSize; - SK_U32 MtuSize; - SK_U32 Action; - SK_U32 TestResult; - SK_U8 BusType; - SK_U8 BusSpeed; - SK_U8 BusWidth; - SK_U8 SensorNumber; - SK_PNMI_SENSOR Sensor[SK_PNMI_SENSOR_ENTRIES]; - SK_U8 ChecksumNumber; - SK_PNMI_CHECKSUM Checksum[SK_PNMI_CHECKSUM_ENTRIES]; - SK_PNMI_STAT Stat[SK_PNMI_MAC_ENTRIES]; - SK_PNMI_CONF Conf[SK_PNMI_MAC_ENTRIES]; - SK_U8 RlmtMode; - SK_U32 RlmtPortNumber; - SK_U8 RlmtPortActive; - SK_U8 RlmtPortPreferred; - SK_U64 RlmtChangeCts; - SK_U64 RlmtChangeTime; - SK_U64 RlmtChangeEstimate; - SK_U64 RlmtChangeThreshold; - SK_PNMI_RLMT Rlmt[SK_MAX_MACS]; - SK_U32 RlmtMonitorNumber; - SK_PNMI_RLMT_MONITOR RlmtMonitor[SK_PNMI_MONITOR_ENTRIES]; - SK_U32 TrapNumber; - SK_U8 Trap[SK_PNMI_TRAP_QUEUE_LEN]; - SK_U64 TxSwQueueLen; - SK_U64 TxSwQueueMax; - SK_U64 TxRetryCts; - SK_U64 RxIntrCts; - SK_U64 TxIntrCts; - SK_U64 RxNoBufCts; - SK_U64 TxNoBufCts; - SK_U64 TxUsedDescrNo; - SK_U64 RxDeliveredCts; - SK_U64 RxOctetsDeliveredCts; - SK_U64 RxHwErrorsCts; - SK_U64 TxHwErrorsCts; - SK_U64 InErrorsCts; - SK_U64 OutErrorsCts; - SK_U64 ErrRecoveryCts; - SK_U64 SysUpTime; -} SK_PNMI_STRUCT_DATA; - -#define SK_PNMI_STRUCT_SIZE (sizeof(SK_PNMI_STRUCT_DATA)) -#define SK_PNMI_MIN_STRUCT_SIZE ((unsigned int)(SK_UPTR)\ - &(((SK_PNMI_STRUCT_DATA *)0)->VpdFreeBytes)) - /* - * ReturnStatus field - * must be located - * before VpdFreeBytes - */ - -/* - * Various definitions - */ -#define SK_PNMI_MAX_PROTOS 3 - -#define SK_PNMI_CNT_NO 66 /* Must have the value of the enum - * SK_PNMI_MAX_IDX. Define SK_PNMI_CHECK - * for check while init phase 1 - */ - -/* - * Estimate data structure - */ -typedef struct s_PnmiEstimate { - unsigned int EstValueIndex; - SK_U64 EstValue[7]; - SK_U64 Estimate; - SK_TIMER EstTimer; -} SK_PNMI_ESTIMATE; - - -/* - * VCT timer data structure - */ -typedef struct s_VctTimer { - SK_TIMER VctTimer; -} SK_PNMI_VCT_TIMER; - - -/* - * PNMI specific adapter context structure - */ -typedef struct s_PnmiPort { - SK_U64 StatSyncCts; - SK_U64 StatSyncOctetsCts; - SK_U64 StatRxLongFrameCts; - SK_U64 StatRxFrameTooLongCts; - SK_U64 StatRxPMaccErr; - SK_U64 TxSwQueueLen; - SK_U64 TxSwQueueMax; - SK_U64 TxRetryCts; - SK_U64 RxIntrCts; - SK_U64 TxIntrCts; - SK_U64 RxNoBufCts; - SK_U64 TxNoBufCts; - SK_U64 TxUsedDescrNo; - SK_U64 RxDeliveredCts; - SK_U64 RxOctetsDeliveredCts; - SK_U64 RxHwErrorsCts; - SK_U64 TxHwErrorsCts; - SK_U64 InErrorsCts; - SK_U64 OutErrorsCts; - SK_U64 ErrRecoveryCts; - SK_U64 RxShortZeroMark; - SK_U64 CounterOffset[SK_PNMI_CNT_NO]; - SK_U32 CounterHigh[SK_PNMI_CNT_NO]; - SK_BOOL ActiveFlag; - SK_U8 Align[3]; -} SK_PNMI_PORT; - - -typedef struct s_PnmiData { - SK_PNMI_PORT Port [SK_MAX_MACS]; - SK_PNMI_PORT BufPort [SK_MAX_MACS]; /* 2002-09-13 pweber */ - SK_U64 VirtualCounterOffset[SK_PNMI_CNT_NO]; - SK_U32 TestResult; - char HwVersion[10]; - SK_U16 Align01; - - char *pDriverDescription; - char *pDriverVersion; - char *pDriverReleaseDate; - char *pDriverFileName; - - int MacUpdatedFlag; - int RlmtUpdatedFlag; - int SirqUpdatedFlag; - - SK_U64 RlmtChangeCts; - SK_U64 RlmtChangeTime; - SK_PNMI_ESTIMATE RlmtChangeEstimate; - SK_U64 RlmtChangeThreshold; - - SK_U64 StartUpTime; - SK_U32 DeviceType; - char PciBusSpeed; - char PciBusWidth; - char Chipset; - char PMD; - char Connector; - SK_BOOL DualNetActiveFlag; - SK_U16 Align02; - - char TrapBuf[SK_PNMI_TRAP_QUEUE_LEN]; - unsigned int TrapBufFree; - unsigned int TrapQueueBeg; - unsigned int TrapQueueEnd; - unsigned int TrapBufPad; - unsigned int TrapUnique; - SK_U8 VctStatus[SK_MAX_MACS]; - SK_PNMI_VCT VctBackup[SK_MAX_MACS]; - SK_PNMI_VCT_TIMER VctTimeout[SK_MAX_MACS]; -#ifdef SK_DIAG_SUPPORT - SK_U32 DiagAttached; -#endif /* SK_DIAG_SUPPORT */ -} SK_PNMI; - - -/* - * Function prototypes - */ -extern int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int Level); -extern int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void* pBuf, - unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); -extern int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf, - unsigned int *pLen, SK_U32 NetIndex); -extern int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf, - unsigned int *pLen, SK_U32 NetIndex); -extern int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf, - unsigned int *pLen, SK_U32 NetIndex); -extern int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, - SK_EVPARA Param); -extern int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf, - unsigned int * pLen, SK_U32 NetIndex); - -#endif diff --git a/drivers/net/sk98lin/h/skgesirq.h b/drivers/net/sk98lin/h/skgesirq.h deleted file mode 100644 index 3eec6274e41..00000000000 --- a/drivers/net/sk98lin/h/skgesirq.h +++ /dev/null @@ -1,110 +0,0 @@ -/****************************************************************************** - * - * Name: skgesirq.h - * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.30 $ - * Date: $Date: 2003/07/04 12:34:13 $ - * Purpose: SK specific Gigabit Ethernet special IRQ functions - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#ifndef _INC_SKGESIRQ_H_ -#define _INC_SKGESIRQ_H_ - -/* Define return codes of SkGePortCheckUp and CheckShort */ -#define SK_HW_PS_NONE 0 /* No action needed */ -#define SK_HW_PS_RESTART 1 /* Restart needed */ -#define SK_HW_PS_LINK 2 /* Link Up actions needed */ - -/* - * Define the Event the special IRQ/INI module can handle - */ -#define SK_HWEV_WATIM 1 /* Timeout for WA Errata #2 XMAC */ -#define SK_HWEV_PORT_START 2 /* Port Start Event by RLMT */ -#define SK_HWEV_PORT_STOP 3 /* Port Stop Event by RLMT */ -#define SK_HWEV_CLEAR_STAT 4 /* Clear Statistics by PNMI */ -#define SK_HWEV_UPDATE_STAT 5 /* Update Statistics by PNMI */ -#define SK_HWEV_SET_LMODE 6 /* Set Link Mode by PNMI */ -#define SK_HWEV_SET_FLOWMODE 7 /* Set Flow Control Mode by PNMI */ -#define SK_HWEV_SET_ROLE 8 /* Set Master/Slave (Role) by PNMI */ -#define SK_HWEV_SET_SPEED 9 /* Set Link Speed by PNMI */ -#define SK_HWEV_HALFDUP_CHK 10 /* Half Duplex Hangup Workaround */ - -#define SK_WA_ACT_TIME (5000000UL) /* 5 sec */ -#define SK_WA_INA_TIME (100000UL) /* 100 msec */ - -#define SK_HALFDUP_CHK_TIME (10000UL) /* 10 msec */ - -/* - * Define the error numbers and messages - */ -#define SKERR_SIRQ_E001 (SK_ERRBASE_SIRQ+0) -#define SKERR_SIRQ_E001MSG "Unknown event" -#define SKERR_SIRQ_E002 (SKERR_SIRQ_E001+1) -#define SKERR_SIRQ_E002MSG "Packet timeout RX1" -#define SKERR_SIRQ_E003 (SKERR_SIRQ_E002+1) -#define SKERR_SIRQ_E003MSG "Packet timeout RX2" -#define SKERR_SIRQ_E004 (SKERR_SIRQ_E003+1) -#define SKERR_SIRQ_E004MSG "MAC 1 not correctly initialized" -#define SKERR_SIRQ_E005 (SKERR_SIRQ_E004+1) -#define SKERR_SIRQ_E005MSG "MAC 2 not correctly initialized" -#define SKERR_SIRQ_E006 (SKERR_SIRQ_E005+1) -#define SKERR_SIRQ_E006MSG "CHECK failure R1" -#define SKERR_SIRQ_E007 (SKERR_SIRQ_E006+1) -#define SKERR_SIRQ_E007MSG "CHECK failure R2" -#define SKERR_SIRQ_E008 (SKERR_SIRQ_E007+1) -#define SKERR_SIRQ_E008MSG "CHECK failure XS1" -#define SKERR_SIRQ_E009 (SKERR_SIRQ_E008+1) -#define SKERR_SIRQ_E009MSG "CHECK failure XA1" -#define SKERR_SIRQ_E010 (SKERR_SIRQ_E009+1) -#define SKERR_SIRQ_E010MSG "CHECK failure XS2" -#define SKERR_SIRQ_E011 (SKERR_SIRQ_E010+1) -#define SKERR_SIRQ_E011MSG "CHECK failure XA2" -#define SKERR_SIRQ_E012 (SKERR_SIRQ_E011+1) -#define SKERR_SIRQ_E012MSG "unexpected IRQ Master error" -#define SKERR_SIRQ_E013 (SKERR_SIRQ_E012+1) -#define SKERR_SIRQ_E013MSG "unexpected IRQ Status error" -#define SKERR_SIRQ_E014 (SKERR_SIRQ_E013+1) -#define SKERR_SIRQ_E014MSG "Parity error on RAM (read)" -#define SKERR_SIRQ_E015 (SKERR_SIRQ_E014+1) -#define SKERR_SIRQ_E015MSG "Parity error on RAM (write)" -#define SKERR_SIRQ_E016 (SKERR_SIRQ_E015+1) -#define SKERR_SIRQ_E016MSG "Parity error MAC 1" -#define SKERR_SIRQ_E017 (SKERR_SIRQ_E016+1) -#define SKERR_SIRQ_E017MSG "Parity error MAC 2" -#define SKERR_SIRQ_E018 (SKERR_SIRQ_E017+1) -#define SKERR_SIRQ_E018MSG "Parity error RX 1" -#define SKERR_SIRQ_E019 (SKERR_SIRQ_E018+1) -#define SKERR_SIRQ_E019MSG "Parity error RX 2" -#define SKERR_SIRQ_E020 (SKERR_SIRQ_E019+1) -#define SKERR_SIRQ_E020MSG "MAC transmit FIFO underrun" -#define SKERR_SIRQ_E021 (SKERR_SIRQ_E020+1) -#define SKERR_SIRQ_E021MSG "Spurious TWSI interrupt" -#define SKERR_SIRQ_E022 (SKERR_SIRQ_E021+1) -#define SKERR_SIRQ_E022MSG "Cable pair swap error" -#define SKERR_SIRQ_E023 (SKERR_SIRQ_E022+1) -#define SKERR_SIRQ_E023MSG "Auto-negotiation error" -#define SKERR_SIRQ_E024 (SKERR_SIRQ_E023+1) -#define SKERR_SIRQ_E024MSG "FIFO overflow error" -#define SKERR_SIRQ_E025 (SKERR_SIRQ_E024+1) -#define SKERR_SIRQ_E025MSG "2 Pair Downshift detected" - -extern void SkGeSirqIsr(SK_AC *pAC, SK_IOC IoC, SK_U32 Istatus); -extern int SkGeSirqEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para); -extern void SkHWLinkDown(SK_AC *pAC, SK_IOC IoC, int Port); - -#endif /* _INC_SKGESIRQ_H_ */ diff --git a/drivers/net/sk98lin/h/ski2c.h b/drivers/net/sk98lin/h/ski2c.h deleted file mode 100644 index 6a63f4a15de..00000000000 --- a/drivers/net/sk98lin/h/ski2c.h +++ /dev/null @@ -1,174 +0,0 @@ -/****************************************************************************** - * - * Name: ski2c.h - * Project: Gigabit Ethernet Adapters, TWSI-Module - * Version: $Revision: 1.35 $ - * Date: $Date: 2003/10/20 09:06:30 $ - * Purpose: Defines to access Voltage and Temperature Sensor - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - * SKI2C.H contains all I2C specific defines - */ - -#ifndef _SKI2C_H_ -#define _SKI2C_H_ - -typedef struct s_Sensor SK_SENSOR; - -#include "h/skgei2c.h" - -/* - * Define the I2C events. - */ -#define SK_I2CEV_IRQ 1 /* IRQ happened Event */ -#define SK_I2CEV_TIM 2 /* Timeout event */ -#define SK_I2CEV_CLEAR 3 /* Clear MIB Values */ - -/* - * Define READ and WRITE Constants. - */ -#define I2C_READ 0 -#define I2C_WRITE 1 -#define I2C_BURST 1 -#define I2C_SINGLE 0 - -#define SKERR_I2C_E001 (SK_ERRBASE_I2C+0) -#define SKERR_I2C_E001MSG "Sensor index unknown" -#define SKERR_I2C_E002 (SKERR_I2C_E001+1) -#define SKERR_I2C_E002MSG "TWSI: transfer does not complete" -#define SKERR_I2C_E003 (SKERR_I2C_E002+1) -#define SKERR_I2C_E003MSG "LM80: NAK on device send" -#define SKERR_I2C_E004 (SKERR_I2C_E003+1) -#define SKERR_I2C_E004MSG "LM80: NAK on register send" -#define SKERR_I2C_E005 (SKERR_I2C_E004+1) -#define SKERR_I2C_E005MSG "LM80: NAK on device (2) send" -#define SKERR_I2C_E006 (SKERR_I2C_E005+1) -#define SKERR_I2C_E006MSG "Unknown event" -#define SKERR_I2C_E007 (SKERR_I2C_E006+1) -#define SKERR_I2C_E007MSG "LM80 read out of state" -#define SKERR_I2C_E008 (SKERR_I2C_E007+1) -#define SKERR_I2C_E008MSG "Unexpected sensor read completed" -#define SKERR_I2C_E009 (SKERR_I2C_E008+1) -#define SKERR_I2C_E009MSG "WARNING: temperature sensor out of range" -#define SKERR_I2C_E010 (SKERR_I2C_E009+1) -#define SKERR_I2C_E010MSG "WARNING: voltage sensor out of range" -#define SKERR_I2C_E011 (SKERR_I2C_E010+1) -#define SKERR_I2C_E011MSG "ERROR: temperature sensor out of range" -#define SKERR_I2C_E012 (SKERR_I2C_E011+1) -#define SKERR_I2C_E012MSG "ERROR: voltage sensor out of range" -#define SKERR_I2C_E013 (SKERR_I2C_E012+1) -#define SKERR_I2C_E013MSG "ERROR: couldn't init sensor" -#define SKERR_I2C_E014 (SKERR_I2C_E013+1) -#define SKERR_I2C_E014MSG "WARNING: fan sensor out of range" -#define SKERR_I2C_E015 (SKERR_I2C_E014+1) -#define SKERR_I2C_E015MSG "ERROR: fan sensor out of range" -#define SKERR_I2C_E016 (SKERR_I2C_E015+1) -#define SKERR_I2C_E016MSG "TWSI: active transfer does not complete" - -/* - * Define Timeout values - */ -#define SK_I2C_TIM_LONG 2000000L /* 2 seconds */ -#define SK_I2C_TIM_SHORT 100000L /* 100 milliseconds */ -#define SK_I2C_TIM_WATCH 1000000L /* 1 second */ - -/* - * Define trap and error log hold times - */ -#ifndef SK_SEN_ERR_TR_HOLD -#define SK_SEN_ERR_TR_HOLD (4*SK_TICKS_PER_SEC) -#endif -#ifndef SK_SEN_ERR_LOG_HOLD -#define SK_SEN_ERR_LOG_HOLD (60*SK_TICKS_PER_SEC) -#endif -#ifndef SK_SEN_WARN_TR_HOLD -#define SK_SEN_WARN_TR_HOLD (15*SK_TICKS_PER_SEC) -#endif -#ifndef SK_SEN_WARN_LOG_HOLD -#define SK_SEN_WARN_LOG_HOLD (15*60*SK_TICKS_PER_SEC) -#endif - -/* - * Defines for SenType - */ -#define SK_SEN_UNKNOWN 0 -#define SK_SEN_TEMP 1 -#define SK_SEN_VOLT 2 -#define SK_SEN_FAN 3 - -/* - * Define for the SenErrorFlag - */ -#define SK_SEN_ERR_NOT_PRESENT 0 /* Error Flag: Sensor not present */ -#define SK_SEN_ERR_OK 1 /* Error Flag: O.K. */ -#define SK_SEN_ERR_WARN 2 /* Error Flag: Warning */ -#define SK_SEN_ERR_ERR 3 /* Error Flag: Error */ -#define SK_SEN_ERR_FAULTY 4 /* Error Flag: Faulty */ - -/* - * Define the Sensor struct - */ -struct s_Sensor { - char *SenDesc; /* Description */ - int SenType; /* Voltage or Temperature */ - SK_I32 SenValue; /* Current value of the sensor */ - SK_I32 SenThreErrHigh; /* High error Threshhold of this sensor */ - SK_I32 SenThreWarnHigh; /* High warning Threshhold of this sensor */ - SK_I32 SenThreErrLow; /* Lower error Threshold of the sensor */ - SK_I32 SenThreWarnLow; /* Lower warning Threshold of the sensor */ - int SenErrFlag; /* Sensor indicated an error */ - SK_BOOL SenInit; /* Is sensor initialized ? */ - SK_U64 SenErrCts; /* Error trap counter */ - SK_U64 SenWarnCts; /* Warning trap counter */ - SK_U64 SenBegErrTS; /* Begin error timestamp */ - SK_U64 SenBegWarnTS; /* Begin warning timestamp */ - SK_U64 SenLastErrTrapTS; /* Last error trap timestamp */ - SK_U64 SenLastErrLogTS; /* Last error log timestamp */ - SK_U64 SenLastWarnTrapTS; /* Last warning trap timestamp */ - SK_U64 SenLastWarnLogTS; /* Last warning log timestamp */ - int SenState; /* Sensor State (see HW specific include) */ - int (*SenRead)(SK_AC *pAC, SK_IOC IoC, struct s_Sensor *pSen); - /* Sensors read function */ - SK_U16 SenReg; /* Register Address for this sensor */ - SK_U8 SenDev; /* Device Selection for this sensor */ -}; - -typedef struct s_I2c { - SK_SENSOR SenTable[SK_MAX_SENSORS]; /* Sensor Table */ - int CurrSens; /* Which sensor is currently queried */ - int MaxSens; /* Max. number of sensors */ - int TimerMode; /* Use the timer also to watch the state machine */ - int InitLevel; /* Initialized Level */ -#ifndef SK_DIAG - int DummyReads; /* Number of non-checked dummy reads */ - SK_TIMER SenTimer; /* Sensors timer */ -#endif /* !SK_DIAG */ -} SK_I2C; - -extern int SkI2cInit(SK_AC *pAC, SK_IOC IoC, int Level); -#ifdef SK_DIAG -extern SK_U32 SkI2cRead(SK_AC *pAC, SK_IOC IoC, int Dev, int Size, int Reg, - int Burst); -#else /* !SK_DIAG */ -extern int SkI2cEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para); -extern void SkI2cWaitIrq(SK_AC *pAC, SK_IOC IoC); -extern void SkI2cIsr(SK_AC *pAC, SK_IOC IoC); -#endif /* !SK_DIAG */ -#endif /* n_SKI2C_H */ - diff --git a/drivers/net/sk98lin/h/skqueue.h b/drivers/net/sk98lin/h/skqueue.h deleted file mode 100644 index 2ec40d4fdf6..00000000000 --- a/drivers/net/sk98lin/h/skqueue.h +++ /dev/null @@ -1,94 +0,0 @@ -/****************************************************************************** - * - * Name: skqueue.h - * Project: Gigabit Ethernet Adapters, Event Scheduler Module - * Version: $Revision: 1.16 $ - * Date: $Date: 2003/09/16 12:50:32 $ - * Purpose: Defines for the Event queue - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - * SKQUEUE.H contains all defines and types for the event queue - */ - -#ifndef _SKQUEUE_H_ -#define _SKQUEUE_H_ - - -/* - * define the event classes to be served - */ -#define SKGE_DRV 1 /* Driver Event Class */ -#define SKGE_RLMT 2 /* RLMT Event Class */ -#define SKGE_I2C 3 /* I2C Event Class */ -#define SKGE_PNMI 4 /* PNMI Event Class */ -#define SKGE_CSUM 5 /* Checksum Event Class */ -#define SKGE_HWAC 6 /* Hardware Access Event Class */ - -#define SKGE_SWT 9 /* Software Timer Event Class */ -#define SKGE_LACP 10 /* LACP Aggregation Event Class */ -#define SKGE_RSF 11 /* RSF Aggregation Event Class */ -#define SKGE_MARKER 12 /* MARKER Aggregation Event Class */ -#define SKGE_FD 13 /* FD Distributor Event Class */ - -/* - * define event queue as circular buffer - */ -#define SK_MAX_EVENT 64 - -/* - * Parameter union for the Para stuff - */ -typedef union u_EvPara { - void *pParaPtr; /* Parameter Pointer */ - SK_U64 Para64; /* Parameter 64bit version */ - SK_U32 Para32[2]; /* Parameter Array of 32bit parameters */ -} SK_EVPARA; - -/* - * Event Queue - * skqueue.c - * events are class/value pairs - * class is addressee, e.g. RLMT, PNMI etc. - * value is command, e.g. line state change, ring op change etc. - */ -typedef struct s_EventElem { - SK_U32 Class; /* Event class */ - SK_U32 Event; /* Event value */ - SK_EVPARA Para; /* Event parameter */ -} SK_EVENTELEM; - -typedef struct s_Queue { - SK_EVENTELEM EvQueue[SK_MAX_EVENT]; - SK_EVENTELEM *EvPut; - SK_EVENTELEM *EvGet; -} SK_QUEUE; - -extern void SkEventInit(SK_AC *pAC, SK_IOC Ioc, int Level); -extern void SkEventQueue(SK_AC *pAC, SK_U32 Class, SK_U32 Event, - SK_EVPARA Para); -extern int SkEventDispatcher(SK_AC *pAC, SK_IOC Ioc); - - -/* Define Error Numbers and messages */ -#define SKERR_Q_E001 (SK_ERRBASE_QUEUE+0) -#define SKERR_Q_E001MSG "Event queue overflow" -#define SKERR_Q_E002 (SKERR_Q_E001+1) -#define SKERR_Q_E002MSG "Undefined event class" -#endif /* _SKQUEUE_H_ */ - diff --git a/drivers/net/sk98lin/h/skrlmt.h b/drivers/net/sk98lin/h/skrlmt.h deleted file mode 100644 index ca75dfdcf2d..00000000000 --- a/drivers/net/sk98lin/h/skrlmt.h +++ /dev/null @@ -1,438 +0,0 @@ -/****************************************************************************** - * - * Name: skrlmt.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.37 $ - * Date: $Date: 2003/04/15 09:43:43 $ - * Purpose: Header file for Redundant Link ManagemenT. - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This is the header file for Redundant Link ManagemenT. - * - * Include File Hierarchy: - * - * "skdrv1st.h" - * ... - * "sktypes.h" - * "skqueue.h" - * "skaddr.h" - * "skrlmt.h" - * ... - * "skdrv2nd.h" - * - ******************************************************************************/ - -#ifndef __INC_SKRLMT_H -#define __INC_SKRLMT_H - -#ifdef __cplusplus -extern "C" { -#endif /* cplusplus */ - -/* defines ********************************************************************/ - -#define SK_RLMT_NET_DOWN_TEMP 1 /* NET_DOWN due to last port down. */ -#define SK_RLMT_NET_DOWN_FINAL 2 /* NET_DOWN due to RLMT_STOP. */ - -/* ----- Default queue sizes - must be multiples of 8 KB ----- */ - -/* Less than 8 KB free in RX queue => pause frames. */ -#define SK_RLMT_STANDBY_QRXSIZE 128 /* Size of rx standby queue in KB. */ -#define SK_RLMT_STANDBY_QXASIZE 32 /* Size of async standby queue in KB. */ -#define SK_RLMT_STANDBY_QXSSIZE 0 /* Size of sync standby queue in KB. */ - -#define SK_RLMT_MAX_TX_BUF_SIZE 60 /* Maximum RLMT transmit size. */ - -/* ----- PORT states ----- */ - -#define SK_RLMT_PS_INIT 0 /* Port state: Init. */ -#define SK_RLMT_PS_LINK_DOWN 1 /* Port state: Link down. */ -#define SK_RLMT_PS_DOWN 2 /* Port state: Port down. */ -#define SK_RLMT_PS_GOING_UP 3 /* Port state: Going up. */ -#define SK_RLMT_PS_UP 4 /* Port state: Up. */ - -/* ----- RLMT states ----- */ - -#define SK_RLMT_RS_INIT 0 /* RLMT state: Init. */ -#define SK_RLMT_RS_NET_DOWN 1 /* RLMT state: Net down. */ -#define SK_RLMT_RS_NET_UP 2 /* RLMT state: Net up. */ - -/* ----- PORT events ----- */ - -#define SK_RLMT_LINK_UP 1001 /* Link came up. */ -#define SK_RLMT_LINK_DOWN 1002 /* Link went down. */ -#define SK_RLMT_PORT_ADDR 1003 /* Port address changed. */ - -/* ----- RLMT events ----- */ - -#define SK_RLMT_START 2001 /* Start RLMT. */ -#define SK_RLMT_STOP 2002 /* Stop RLMT. */ -#define SK_RLMT_PACKET_RECEIVED 2003 /* Packet was received for RLMT. */ -#define SK_RLMT_STATS_CLEAR 2004 /* Clear statistics. */ -#define SK_RLMT_STATS_UPDATE 2005 /* Update statistics. */ -#define SK_RLMT_PREFPORT_CHANGE 2006 /* Change preferred port. */ -#define SK_RLMT_MODE_CHANGE 2007 /* New RlmtMode. */ -#define SK_RLMT_SET_NETS 2008 /* Number of Nets (1 or 2). */ - -/* ----- RLMT mode bits ----- */ - -/* - * CAUTION: These defines are private to RLMT. - * Please use the RLMT mode defines below. - */ - -#define SK_RLMT_CHECK_LINK 1 /* Check Link. */ -#define SK_RLMT_CHECK_LOC_LINK 2 /* Check other link on same adapter. */ -#define SK_RLMT_CHECK_SEG 4 /* Check segmentation. */ - -#ifndef RLMT_CHECK_REMOTE -#define SK_RLMT_CHECK_OTHERS SK_RLMT_CHECK_LOC_LINK -#else /* RLMT_CHECK_REMOTE */ -#define SK_RLMT_CHECK_REM_LINK 8 /* Check link(s) on other adapter(s). */ -#define SK_RLMT_MAX_REMOTE_PORTS_CHECKED 3 -#define SK_RLMT_CHECK_OTHERS \ - (SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK) -#endif /* RLMT_CHECK_REMOTE */ - -#ifndef SK_RLMT_ENABLE_TRANSPARENT -#define SK_RLMT_TRANSPARENT 0 /* RLMT transparent - inactive. */ -#else /* SK_RLMT_ENABLE_TRANSPARENT */ -#define SK_RLMT_TRANSPARENT 128 /* RLMT transparent. */ -#endif /* SK_RLMT_ENABLE_TRANSPARENT */ - -/* ----- RLMT modes ----- */ - -/* Check Link State. */ -#define SK_RLMT_MODE_CLS (SK_RLMT_CHECK_LINK) - -/* Check Local Ports: check other links on the same adapter. */ -#define SK_RLMT_MODE_CLP (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK) - -/* Check Local Ports and Segmentation Status. */ -#define SK_RLMT_MODE_CLPSS \ - (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_SEG) - -#ifdef RLMT_CHECK_REMOTE -/* Check Local and Remote Ports: check links (local or remote). */ - Name of define TBD! -#define SK_RLMT_MODE_CRP \ - (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK) - -/* Check Local and Remote Ports and Segmentation Status. */ - Name of define TBD! -#define SK_RLMT_MODE_CRPSS \ - (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | \ - SK_RLMT_CHECK_REM_LINK | SK_RLMT_CHECK_SEG) -#endif /* RLMT_CHECK_REMOTE */ - -/* ----- RLMT lookahead result bits ----- */ - -#define SK_RLMT_RX_RLMT 1 /* Give packet to RLMT. */ -#define SK_RLMT_RX_PROTOCOL 2 /* Give packet to protocol. */ - -/* Macros */ - -#if 0 -SK_AC *pAC /* adapter context */ -SK_U32 PortNum /* receiving port */ -unsigned PktLen /* received packet's length */ -SK_BOOL IsBc /* Flag: packet is broadcast */ -unsigned *pOffset /* offs. of bytes to present to SK_RLMT_LOOKAHEAD */ -unsigned *pNumBytes /* #Bytes to present to SK_RLMT_LOOKAHEAD */ -#endif /* 0 */ - -#define SK_RLMT_PRE_LOOKAHEAD(pAC,PortNum,PktLen,IsBc,pOffset,pNumBytes) { \ - SK_AC *_pAC; \ - SK_U32 _PortNum; \ - _pAC = (pAC); \ - _PortNum = (SK_U32)(PortNum); \ - /* _pAC->Rlmt.Port[_PortNum].PacketsRx++; */ \ - _pAC->Rlmt.Port[_PortNum].PacketsPerTimeSlot++; \ - if (_pAC->Rlmt.RlmtOff) { \ - *(pNumBytes) = 0; \ - } \ - else {\ - if ((_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_TRANSPARENT) != 0) { \ - *(pNumBytes) = 0; \ - } \ - else if (IsBc) { \ - if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode != SK_RLMT_MODE_CLS) { \ - *(pNumBytes) = 6; \ - *(pOffset) = 6; \ - } \ - else { \ - *(pNumBytes) = 0; \ - } \ - } \ - else { \ - if ((PktLen) > SK_RLMT_MAX_TX_BUF_SIZE) { \ - /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \ - *(pNumBytes) = 0; \ - } \ - else { \ - *(pNumBytes) = 6; \ - *(pOffset) = 0; \ - } \ - } \ - } \ -} - -#if 0 -SK_AC *pAC /* adapter context */ -SK_U32 PortNum /* receiving port */ -SK_U8 *pLaPacket, /* received packet's data (points to pOffset) */ -SK_BOOL IsBc /* Flag: packet is broadcast */ -SK_BOOL IsMc /* Flag: packet is multicast */ -unsigned *pForRlmt /* Result: bits SK_RLMT_RX_RLMT, SK_RLMT_RX_PROTOCOL */ -SK_RLMT_LOOKAHEAD() expects *pNumBytes from -packet offset *pOffset (s.a.) at *pLaPacket. - -If you use SK_RLMT_LOOKAHEAD in a path where you already know if the packet is -BC, MC, or UC, you should use constants for IsBc and IsMc, so that your compiler -can trash unneeded parts of the if construction. -#endif /* 0 */ - -#define SK_RLMT_LOOKAHEAD(pAC,PortNum,pLaPacket,IsBc,IsMc,pForRlmt) { \ - SK_AC *_pAC; \ - SK_U32 _PortNum; \ - SK_U8 *_pLaPacket; \ - _pAC = (pAC); \ - _PortNum = (SK_U32)(PortNum); \ - _pLaPacket = (SK_U8 *)(pLaPacket); \ - if (IsBc) {\ - if (!SK_ADDR_EQUAL(_pLaPacket, _pAC->Addr.Net[_pAC->Rlmt.Port[ \ - _PortNum].Net->NetNumber].CurrentMacAddress.a)) { \ - _pAC->Rlmt.Port[_PortNum].BcTimeStamp = SkOsGetTime(_pAC); \ - _pAC->Rlmt.CheckSwitch = SK_TRUE; \ - } \ - /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \ - *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \ - } \ - else if (IsMc) { \ - if (SK_ADDR_EQUAL(_pLaPacket, BridgeMcAddr.a)) { \ - _pAC->Rlmt.Port[_PortNum].BpduPacketsPerTimeSlot++; \ - if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_CHECK_SEG) { \ - *(pForRlmt) = SK_RLMT_RX_RLMT | SK_RLMT_RX_PROTOCOL; \ - } \ - else { \ - *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \ - } \ - } \ - else if (SK_ADDR_EQUAL(_pLaPacket, SkRlmtMcAddr.a)) { \ - *(pForRlmt) = SK_RLMT_RX_RLMT; \ - } \ - else { \ - /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \ - *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \ - } \ - } \ - else { \ - if (SK_ADDR_EQUAL( \ - _pLaPacket, \ - _pAC->Addr.Port[_PortNum].CurrentMacAddress.a)) { \ - *(pForRlmt) = SK_RLMT_RX_RLMT; \ - } \ - else { \ - /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \ - *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \ - } \ - } \ -} - -#ifdef SK_RLMT_FAST_LOOKAHEAD -Error: SK_RLMT_FAST_LOOKAHEAD no longer used. Use new macros for lookahead. -#endif /* SK_RLMT_FAST_LOOKAHEAD */ -#ifdef SK_RLMT_SLOW_LOOKAHEAD -Error: SK_RLMT_SLOW_LOOKAHEAD no longer used. Use new macros for lookahead. -#endif /* SK_RLMT_SLOW_LOOKAHEAD */ - -/* typedefs *******************************************************************/ - -#ifdef SK_RLMT_MBUF_PRIVATE -typedef struct s_RlmtMbuf { - some content -} SK_RLMT_MBUF; -#endif /* SK_RLMT_MBUF_PRIVATE */ - - -#ifdef SK_LA_INFO -typedef struct s_Rlmt_PacketInfo { - unsigned PacketLength; /* Length of packet. */ - unsigned PacketType; /* Directed/Multicast/Broadcast. */ -} SK_RLMT_PINFO; -#endif /* SK_LA_INFO */ - - -typedef struct s_RootId { - SK_U8 Id[8]; /* Root Bridge Id. */ -} SK_RLMT_ROOT_ID; - - -typedef struct s_port { - SK_MAC_ADDR CheckAddr; - SK_BOOL SuspectTx; -} SK_PORT_CHECK; - - -typedef struct s_RlmtNet SK_RLMT_NET; - - -typedef struct s_RlmtPort { - -/* ----- Public part (read-only) ----- */ - - SK_U8 PortState; /* Current state of this port. */ - - /* For PNMI */ - SK_BOOL LinkDown; - SK_BOOL PortDown; - SK_U8 Align01; - - SK_U32 PortNumber; /* Number of port on adapter. */ - SK_RLMT_NET * Net; /* Net port belongs to. */ - - SK_U64 TxHelloCts; - SK_U64 RxHelloCts; - SK_U64 TxSpHelloReqCts; - SK_U64 RxSpHelloCts; - -/* ----- Private part ----- */ - -/* SK_U64 PacketsRx; */ /* Total packets received. */ - SK_U32 PacketsPerTimeSlot; /* Packets rxed between TOs. */ -/* SK_U32 DataPacketsPerTimeSlot; */ /* Data packets ... */ - SK_U32 BpduPacketsPerTimeSlot; /* BPDU packets rxed in TS. */ - SK_U64 BcTimeStamp; /* Time of last BC receive. */ - SK_U64 GuTimeStamp; /* Time of entering GOING_UP. */ - - SK_TIMER UpTimer; /* Timer struct Link/Port up. */ - SK_TIMER DownRxTimer; /* Timer struct down rx. */ - SK_TIMER DownTxTimer; /* Timer struct down tx. */ - - SK_U32 CheckingState; /* Checking State. */ - - SK_ADDR_PORT * AddrPort; - - SK_U8 Random[4]; /* Random value. */ - unsigned PortsChecked; /* #ports checked. */ - unsigned PortsSuspect; /* #ports checked that are s. */ - SK_PORT_CHECK PortCheck[1]; -/* SK_PORT_CHECK PortCheck[SK_MAX_MACS - 1]; */ - - SK_BOOL PortStarted; /* Port is started. */ - SK_BOOL PortNoRx; /* NoRx for >= 1 time slot. */ - SK_BOOL RootIdSet; - SK_RLMT_ROOT_ID Root; /* Root Bridge Id. */ -} SK_RLMT_PORT; - - -struct s_RlmtNet { - -/* ----- Public part (read-only) ----- */ - - SK_U32 NetNumber; /* Number of net. */ - - SK_RLMT_PORT * Port[SK_MAX_MACS]; /* Ports that belong to this net. */ - SK_U32 NumPorts; /* Number of ports. */ - SK_U32 PrefPort; /* Preferred port. */ - - /* For PNMI */ - - SK_U32 ChgBcPrio; /* Change Priority of last broadcast received */ - SK_U32 RlmtMode; /* Check ... */ - SK_U32 ActivePort; /* Active port. */ - SK_U32 Preference; /* 0xFFFFFFFF: Automatic. */ - - SK_U8 RlmtState; /* Current RLMT state. */ - -/* ----- Private part ----- */ - SK_BOOL RootIdSet; - SK_U16 Align01; - - int LinksUp; /* #Links up. */ - int PortsUp; /* #Ports up. */ - SK_U32 TimeoutValue; /* RLMT timeout value. */ - - SK_U32 CheckingState; /* Checking State. */ - SK_RLMT_ROOT_ID Root; /* Root Bridge Id. */ - - SK_TIMER LocTimer; /* Timer struct. */ - SK_TIMER SegTimer; /* Timer struct. */ -}; - - -typedef struct s_Rlmt { - -/* ----- Public part (read-only) ----- */ - - SK_U32 NumNets; /* Number of nets. */ - SK_U32 NetsStarted; /* Number of nets started. */ - SK_RLMT_NET Net[SK_MAX_NETS]; /* Array of available nets. */ - SK_RLMT_PORT Port[SK_MAX_MACS]; /* Array of available ports. */ - -/* ----- Private part ----- */ - SK_BOOL CheckSwitch; - SK_BOOL RlmtOff; /* set to zero if the Mac addresses - are equal or the second one - is zero */ - SK_U16 Align01; - -} SK_RLMT; - - -extern SK_MAC_ADDR BridgeMcAddr; -extern SK_MAC_ADDR SkRlmtMcAddr; - -/* function prototypes ********************************************************/ - - -#ifndef SK_KR_PROTO - -/* Functions provided by SkRlmt */ - -/* ANSI/C++ compliant function prototypes */ - -extern void SkRlmtInit( - SK_AC *pAC, - SK_IOC IoC, - int Level); - -extern int SkRlmtEvent( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 Event, - SK_EVPARA Para); - -#else /* defined(SK_KR_PROTO) */ - -/* Non-ANSI/C++ compliant function prototypes */ - -#error KR-style function prototypes are not yet provided. - -#endif /* defined(SK_KR_PROTO)) */ - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __INC_SKRLMT_H */ diff --git a/drivers/net/sk98lin/h/sktimer.h b/drivers/net/sk98lin/h/sktimer.h deleted file mode 100644 index 04e6d7c1ec3..00000000000 --- a/drivers/net/sk98lin/h/sktimer.h +++ /dev/null @@ -1,63 +0,0 @@ -/****************************************************************************** - * - * Name: sktimer.h - * Project: Gigabit Ethernet Adapters, Event Scheduler Module - * Version: $Revision: 1.11 $ - * Date: $Date: 2003/09/16 12:58:18 $ - * Purpose: Defines for the timer functions - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - * SKTIMER.H contains all defines and types for the timer functions - */ - -#ifndef _SKTIMER_H_ -#define _SKTIMER_H_ - -#include "h/skqueue.h" - -/* - * SK timer - * - needed wherever a timer is used. Put this in your data structure - * wherever you want. - */ -typedef struct s_Timer SK_TIMER; - -struct s_Timer { - SK_TIMER *TmNext; /* linked list */ - SK_U32 TmClass; /* Timer Event class */ - SK_U32 TmEvent; /* Timer Event value */ - SK_EVPARA TmPara; /* Timer Event parameter */ - SK_U32 TmDelta; /* delta time */ - int TmActive; /* flag: active/inactive */ -}; - -/* - * Timer control struct. - * - use in Adapters context name pAC->Tim - */ -typedef struct s_TimCtrl { - SK_TIMER *StQueue; /* Head of Timer queue */ -} SK_TIMCTRL; - -extern void SkTimerInit(SK_AC *pAC, SK_IOC Ioc, int Level); -extern void SkTimerStop(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer); -extern void SkTimerStart(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer, - SK_U32 Time, SK_U32 Class, SK_U32 Event, SK_EVPARA Para); -extern void SkTimerDone(SK_AC *pAC, SK_IOC Ioc); -#endif /* _SKTIMER_H_ */ diff --git a/drivers/net/sk98lin/h/sktypes.h b/drivers/net/sk98lin/h/sktypes.h deleted file mode 100644 index 40edc96e105..00000000000 --- a/drivers/net/sk98lin/h/sktypes.h +++ /dev/null @@ -1,69 +0,0 @@ -/****************************************************************************** - * - * Name: sktypes.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.2 $ - * Date: $Date: 2003/10/07 08:16:51 $ - * Purpose: Define data types for Linux - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * In this file, all data types that are needed by the common modules - * are mapped to Linux data types. - * - * - * Include File Hierarchy: - * - * - ******************************************************************************/ - -#ifndef __INC_SKTYPES_H -#define __INC_SKTYPES_H - - -/* defines *******************************************************************/ - -/* - * Data types with a specific size. 'I' = signed, 'U' = unsigned. - */ -#define SK_I8 s8 -#define SK_U8 u8 -#define SK_I16 s16 -#define SK_U16 u16 -#define SK_I32 s32 -#define SK_U32 u32 -#define SK_I64 s64 -#define SK_U64 u64 - -#define SK_UPTR ulong /* casting pointer <-> integral */ - -/* -* Boolean type. -*/ -#define SK_BOOL SK_U8 -#define SK_FALSE 0 -#define SK_TRUE (!SK_FALSE) - -/* typedefs *******************************************************************/ - -/* function prototypes ********************************************************/ - -#endif /* __INC_SKTYPES_H */ diff --git a/drivers/net/sk98lin/h/skversion.h b/drivers/net/sk98lin/h/skversion.h deleted file mode 100644 index a1a7294828e..00000000000 --- a/drivers/net/sk98lin/h/skversion.h +++ /dev/null @@ -1,38 +0,0 @@ -/****************************************************************************** - * - * Name: version.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.5 $ - * Date: $Date: 2003/10/07 08:16:51 $ - * Purpose: SK specific Error log support - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#ifdef lint -static const char SysKonnectFileId[] = "@(#) (C) SysKonnect GmbH."; -static const char SysKonnectBuildNumber[] = - "@(#)SK-BUILD: 6.23 PL: 01"; -#endif /* !defined(lint) */ - -#define BOOT_STRING "sk98lin: Network Device Driver v6.23\n" \ - "(C)Copyright 1999-2004 Marvell(R)." - -#define VER_STRING "6.23" -#define DRIVER_FILE_NAME "sk98lin" -#define DRIVER_REL_DATE "Feb-13-2004" - - diff --git a/drivers/net/sk98lin/h/skvpd.h b/drivers/net/sk98lin/h/skvpd.h deleted file mode 100644 index fdd9e48e804..00000000000 --- a/drivers/net/sk98lin/h/skvpd.h +++ /dev/null @@ -1,248 +0,0 @@ -/****************************************************************************** - * - * Name: skvpd.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.15 $ - * Date: $Date: 2003/01/13 10:39:38 $ - * Purpose: Defines and Macros for VPD handling - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2003 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - * skvpd.h contains Diagnostic specific defines for VPD handling - */ - -#ifndef __INC_SKVPD_H_ -#define __INC_SKVPD_H_ - -/* - * Define Resource Type Identifiers and VPD keywords - */ -#define RES_ID 0x82 /* Resource Type ID String (Product Name) */ -#define RES_VPD_R 0x90 /* start of VPD read only area */ -#define RES_VPD_W 0x91 /* start of VPD read/write area */ -#define RES_END 0x78 /* Resource Type End Tag */ - -#ifndef VPD_NAME -#define VPD_NAME "Name" /* Product Name, VPD name of RES_ID */ -#endif /* VPD_NAME */ -#define VPD_PN "PN" /* Adapter Part Number */ -#define VPD_EC "EC" /* Adapter Engineering Level */ -#define VPD_MN "MN" /* Manufacture ID */ -#define VPD_SN "SN" /* Serial Number */ -#define VPD_CP "CP" /* Extended Capability */ -#define VPD_RV "RV" /* Checksum and Reserved */ -#define VPD_YA "YA" /* Asset Tag Identifier */ -#define VPD_VL "VL" /* First Error Log Message (SK specific) */ -#define VPD_VF "VF" /* Second Error Log Message (SK specific) */ -#define VPD_RW "RW" /* Remaining Read / Write Area */ - -/* 'type' values for vpd_setup_para() */ -#define VPD_RO_KEY 1 /* RO keys are "PN", "EC", "MN", "SN", "RV" */ -#define VPD_RW_KEY 2 /* RW keys are "Yx", "Vx", and "RW" */ - -/* 'op' values for vpd_setup_para() */ -#define ADD_KEY 1 /* add the key at the pos "RV" or "RW" */ -#define OWR_KEY 2 /* overwrite key if already exists */ - -/* - * Define READ and WRITE Constants. - */ - -#define VPD_DEV_ID_GENESIS 0x4300 - -#define VPD_SIZE_YUKON 256 -#define VPD_SIZE_GENESIS 512 -#define VPD_SIZE 512 -#define VPD_READ 0x0000 -#define VPD_WRITE 0x8000 - -#define VPD_STOP(pAC,IoC) VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG,VPD_WRITE) - -#define VPD_GET_RES_LEN(p) ((unsigned int) \ - (* (SK_U8 *)&(p)[1]) |\ - ((* (SK_U8 *)&(p)[2]) << 8)) -#define VPD_GET_VPD_LEN(p) ((unsigned int)(* (SK_U8 *)&(p)[2])) -#define VPD_GET_VAL(p) ((char *)&(p)[3]) - -#define VPD_MAX_LEN 50 - -/* VPD status */ - /* bit 7..1 reserved */ -#define VPD_VALID (1<<0) /* VPD data buffer, vpd_free_ro, */ - /* and vpd_free_rw valid */ - -/* - * VPD structs - */ -typedef struct s_vpd_status { - unsigned short Align01; /* Alignment */ - unsigned short vpd_status; /* VPD status, description see above */ - int vpd_free_ro; /* unused bytes in read only area */ - int vpd_free_rw; /* bytes available in read/write area */ -} SK_VPD_STATUS; - -typedef struct s_vpd { - SK_VPD_STATUS v; /* VPD status structure */ - char vpd_buf[VPD_SIZE]; /* VPD buffer */ - int rom_size; /* VPD ROM Size from PCI_OUR_REG_2 */ - int vpd_size; /* saved VPD-size */ -} SK_VPD; - -typedef struct s_vpd_para { - unsigned int p_len; /* parameter length */ - char *p_val; /* points to the value */ -} SK_VPD_PARA; - -/* - * structure of Large Resource Type Identifiers - */ - -/* was removed because of alignment problems */ - -/* - * structure of VPD keywords - */ -typedef struct s_vpd_key { - char p_key[2]; /* 2 bytes ID string */ - unsigned char p_len; /* 1 byte length */ - char p_val; /* start of the value string */ -} SK_VPD_KEY; - - -/* - * System specific VPD macros - */ -#ifndef SKDIAG -#ifndef VPD_DO_IO -#define VPD_OUT8(pAC,IoC,Addr,Val) (void)SkPciWriteCfgByte(pAC,Addr,Val) -#define VPD_OUT16(pAC,IoC,Addr,Val) (void)SkPciWriteCfgWord(pAC,Addr,Val) -#define VPD_IN8(pAC,IoC,Addr,pVal) (void)SkPciReadCfgByte(pAC,Addr,pVal) -#define VPD_IN16(pAC,IoC,Addr,pVal) (void)SkPciReadCfgWord(pAC,Addr,pVal) -#define VPD_IN32(pAC,IoC,Addr,pVal) (void)SkPciReadCfgDWord(pAC,Addr,pVal) -#else /* VPD_DO_IO */ -#define VPD_OUT8(pAC,IoC,Addr,Val) SK_OUT8(IoC,PCI_C(Addr),Val) -#define VPD_OUT16(pAC,IoC,Addr,Val) SK_OUT16(IoC,PCI_C(Addr),Val) -#define VPD_IN8(pAC,IoC,Addr,pVal) SK_IN8(IoC,PCI_C(Addr),pVal) -#define VPD_IN16(pAC,IoC,Addr,pVal) SK_IN16(IoC,PCI_C(Addr),pVal) -#define VPD_IN32(pAC,IoC,Addr,pVal) SK_IN32(IoC,PCI_C(Addr),pVal) -#endif /* VPD_DO_IO */ -#else /* SKDIAG */ -#define VPD_OUT8(pAC,Ioc,Addr,Val) { \ - if ((pAC)->DgT.DgUseCfgCycle) \ - SkPciWriteCfgByte(pAC,Addr,Val); \ - else \ - SK_OUT8(pAC,PCI_C(Addr),Val); \ - } -#define VPD_OUT16(pAC,Ioc,Addr,Val) { \ - if ((pAC)->DgT.DgUseCfgCycle) \ - SkPciWriteCfgWord(pAC,Addr,Val); \ - else \ - SK_OUT16(pAC,PCI_C(Addr),Val); \ - } -#define VPD_IN8(pAC,Ioc,Addr,pVal) { \ - if ((pAC)->DgT.DgUseCfgCycle) \ - SkPciReadCfgByte(pAC,Addr,pVal); \ - else \ - SK_IN8(pAC,PCI_C(Addr),pVal); \ - } -#define VPD_IN16(pAC,Ioc,Addr,pVal) { \ - if ((pAC)->DgT.DgUseCfgCycle) \ - SkPciReadCfgWord(pAC,Addr,pVal); \ - else \ - SK_IN16(pAC,PCI_C(Addr),pVal); \ - } -#define VPD_IN32(pAC,Ioc,Addr,pVal) { \ - if ((pAC)->DgT.DgUseCfgCycle) \ - SkPciReadCfgDWord(pAC,Addr,pVal); \ - else \ - SK_IN32(pAC,PCI_C(Addr),pVal); \ - } -#endif /* nSKDIAG */ - -/* function prototypes ********************************************************/ - -#ifndef SK_KR_PROTO -#ifdef SKDIAG -extern SK_U32 VpdReadDWord( - SK_AC *pAC, - SK_IOC IoC, - int addr); -#endif /* SKDIAG */ - -extern SK_VPD_STATUS *VpdStat( - SK_AC *pAC, - SK_IOC IoC); - -extern int VpdKeys( - SK_AC *pAC, - SK_IOC IoC, - char *buf, - int *len, - int *elements); - -extern int VpdRead( - SK_AC *pAC, - SK_IOC IoC, - const char *key, - char *buf, - int *len); - -extern SK_BOOL VpdMayWrite( - char *key); - -extern int VpdWrite( - SK_AC *pAC, - SK_IOC IoC, - const char *key, - const char *buf); - -extern int VpdDelete( - SK_AC *pAC, - SK_IOC IoC, - char *key); - -extern int VpdUpdate( - SK_AC *pAC, - SK_IOC IoC); - -#ifdef SKDIAG -extern int VpdReadBlock( - SK_AC *pAC, - SK_IOC IoC, - char *buf, - int addr, - int len); - -extern int VpdWriteBlock( - SK_AC *pAC, - SK_IOC IoC, - char *buf, - int addr, - int len); -#endif /* SKDIAG */ -#else /* SK_KR_PROTO */ -extern SK_U32 VpdReadDWord(); -extern SK_VPD_STATUS *VpdStat(); -extern int VpdKeys(); -extern int VpdRead(); -extern SK_BOOL VpdMayWrite(); -extern int VpdWrite(); -extern int VpdDelete(); -extern int VpdUpdate(); -#endif /* SK_KR_PROTO */ - -#endif /* __INC_SKVPD_H_ */ diff --git a/drivers/net/sk98lin/h/xmac_ii.h b/drivers/net/sk98lin/h/xmac_ii.h deleted file mode 100644 index 7f8e6d0084c..00000000000 --- a/drivers/net/sk98lin/h/xmac_ii.h +++ /dev/null @@ -1,1579 +0,0 @@ -/****************************************************************************** - * - * Name: xmac_ii.h - * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.52 $ - * Date: $Date: 2003/10/02 16:35:50 $ - * Purpose: Defines and Macros for Gigabit Ethernet Controller - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#ifndef __INC_XMAC_H -#define __INC_XMAC_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* defines ********************************************************************/ - -/* - * XMAC II registers - * - * The XMAC registers are 16 or 32 bits wide. - * The XMACs host processor interface is set to 16 bit mode, - * therefore ALL registers will be addressed with 16 bit accesses. - * - * The following macros are provided to access the XMAC registers - * XM_IN16(), XM_OUT16, XM_IN32(), XM_OUT32(), XM_INADR(), XM_OUTADR(), - * XM_INHASH(), and XM_OUTHASH(). - * The macros are defined in SkGeHw.h. - * - * Note: NA reg = Network Address e.g DA, SA etc. - * - */ -#define XM_MMU_CMD 0x0000 /* 16 bit r/w MMU Command Register */ - /* 0x0004: reserved */ -#define XM_POFF 0x0008 /* 32 bit r/w Packet Offset Register */ -#define XM_BURST 0x000c /* 32 bit r/w Burst Register for half duplex*/ -#define XM_1L_VLAN_TAG 0x0010 /* 16 bit r/w One Level VLAN Tag ID */ -#define XM_2L_VLAN_TAG 0x0014 /* 16 bit r/w Two Level VLAN Tag ID */ - /* 0x0018 - 0x001e: reserved */ -#define XM_TX_CMD 0x0020 /* 16 bit r/w Transmit Command Register */ -#define XM_TX_RT_LIM 0x0024 /* 16 bit r/w Transmit Retry Limit Register */ -#define XM_TX_STIME 0x0028 /* 16 bit r/w Transmit Slottime Register */ -#define XM_TX_IPG 0x002c /* 16 bit r/w Transmit Inter Packet Gap */ -#define XM_RX_CMD 0x0030 /* 16 bit r/w Receive Command Register */ -#define XM_PHY_ADDR 0x0034 /* 16 bit r/w PHY Address Register */ -#define XM_PHY_DATA 0x0038 /* 16 bit r/w PHY Data Register */ - /* 0x003c: reserved */ -#define XM_GP_PORT 0x0040 /* 32 bit r/w General Purpose Port Register */ -#define XM_IMSK 0x0044 /* 16 bit r/w Interrupt Mask Register */ -#define XM_ISRC 0x0048 /* 16 bit r/o Interrupt Status Register */ -#define XM_HW_CFG 0x004c /* 16 bit r/w Hardware Config Register */ - /* 0x0050 - 0x005e: reserved */ -#define XM_TX_LO_WM 0x0060 /* 16 bit r/w Tx FIFO Low Water Mark */ -#define XM_TX_HI_WM 0x0062 /* 16 bit r/w Tx FIFO High Water Mark */ -#define XM_TX_THR 0x0064 /* 16 bit r/w Tx Request Threshold */ -#define XM_HT_THR 0x0066 /* 16 bit r/w Host Request Threshold */ -#define XM_PAUSE_DA 0x0068 /* NA reg r/w Pause Destination Address */ - /* 0x006e: reserved */ -#define XM_CTL_PARA 0x0070 /* 32 bit r/w Control Parameter Register */ -#define XM_MAC_OPCODE 0x0074 /* 16 bit r/w Opcode for MAC control frames */ -#define XM_MAC_PTIME 0x0076 /* 16 bit r/w Pause time for MAC ctrl frames*/ -#define XM_TX_STAT 0x0078 /* 32 bit r/o Tx Status LIFO Register */ - - /* 0x0080 - 0x00fc: 16 NA reg r/w Exact Match Address Registers */ - /* use the XM_EXM() macro to address */ -#define XM_EXM_START 0x0080 /* r/w Start Address of the EXM Regs */ - - /* - * XM_EXM(Reg) - * - * returns the XMAC address offset of specified Exact Match Addr Reg - * - * para: Reg EXM register to addr (0 .. 15) - * - * usage: XM_INADDR(IoC, MAC_1, XM_EXM(i), &val[i]); - */ -#define XM_EXM(Reg) (XM_EXM_START + ((Reg) << 3)) - -#define XM_SRC_CHK 0x0100 /* NA reg r/w Source Check Address Register */ -#define XM_SA 0x0108 /* NA reg r/w Station Address Register */ -#define XM_HSM 0x0110 /* 64 bit r/w Hash Match Address Registers */ -#define XM_RX_LO_WM 0x0118 /* 16 bit r/w Receive Low Water Mark */ -#define XM_RX_HI_WM 0x011a /* 16 bit r/w Receive High Water Mark */ -#define XM_RX_THR 0x011c /* 32 bit r/w Receive Request Threshold */ -#define XM_DEV_ID 0x0120 /* 32 bit r/o Device ID Register */ -#define XM_MODE 0x0124 /* 32 bit r/w Mode Register */ -#define XM_LSA 0x0128 /* NA reg r/o Last Source Register */ - /* 0x012e: reserved */ -#define XM_TS_READ 0x0130 /* 32 bit r/o Time Stamp Read Register */ -#define XM_TS_LOAD 0x0134 /* 32 bit r/o Time Stamp Load Value */ - /* 0x0138 - 0x01fe: reserved */ -#define XM_STAT_CMD 0x0200 /* 16 bit r/w Statistics Command Register */ -#define XM_RX_CNT_EV 0x0204 /* 32 bit r/o Rx Counter Event Register */ -#define XM_TX_CNT_EV 0x0208 /* 32 bit r/o Tx Counter Event Register */ -#define XM_RX_EV_MSK 0x020c /* 32 bit r/w Rx Counter Event Mask */ -#define XM_TX_EV_MSK 0x0210 /* 32 bit r/w Tx Counter Event Mask */ - /* 0x0204 - 0x027e: reserved */ -#define XM_TXF_OK 0x0280 /* 32 bit r/o Frames Transmitted OK Conuter */ -#define XM_TXO_OK_HI 0x0284 /* 32 bit r/o Octets Transmitted OK High Cnt*/ -#define XM_TXO_OK_LO 0x0288 /* 32 bit r/o Octets Transmitted OK Low Cnt */ -#define XM_TXF_BC_OK 0x028c /* 32 bit r/o Broadcast Frames Xmitted OK */ -#define XM_TXF_MC_OK 0x0290 /* 32 bit r/o Multicast Frames Xmitted OK */ -#define XM_TXF_UC_OK 0x0294 /* 32 bit r/o Unicast Frames Xmitted OK */ -#define XM_TXF_LONG 0x0298 /* 32 bit r/o Tx Long Frame Counter */ -#define XM_TXE_BURST 0x029c /* 32 bit r/o Tx Burst Event Counter */ -#define XM_TXF_MPAUSE 0x02a0 /* 32 bit r/o Tx Pause MAC Ctrl Frame Cnt */ -#define XM_TXF_MCTRL 0x02a4 /* 32 bit r/o Tx MAC Ctrl Frame Counter */ -#define XM_TXF_SNG_COL 0x02a8 /* 32 bit r/o Tx Single Collision Counter */ -#define XM_TXF_MUL_COL 0x02ac /* 32 bit r/o Tx Multiple Collision Counter */ -#define XM_TXF_ABO_COL 0x02b0 /* 32 bit r/o Tx aborted due to Exces. Col. */ -#define XM_TXF_LAT_COL 0x02b4 /* 32 bit r/o Tx Late Collision Counter */ -#define XM_TXF_DEF 0x02b8 /* 32 bit r/o Tx Deferred Frame Counter */ -#define XM_TXF_EX_DEF 0x02bc /* 32 bit r/o Tx Excessive Deferall Counter */ -#define XM_TXE_FIFO_UR 0x02c0 /* 32 bit r/o Tx FIFO Underrun Event Cnt */ -#define XM_TXE_CS_ERR 0x02c4 /* 32 bit r/o Tx Carrier Sense Error Cnt */ -#define XM_TXP_UTIL 0x02c8 /* 32 bit r/o Tx Utilization in % */ - /* 0x02cc - 0x02ce: reserved */ -#define XM_TXF_64B 0x02d0 /* 32 bit r/o 64 Byte Tx Frame Counter */ -#define XM_TXF_127B 0x02d4 /* 32 bit r/o 65-127 Byte Tx Frame Counter */ -#define XM_TXF_255B 0x02d8 /* 32 bit r/o 128-255 Byte Tx Frame Counter */ -#define XM_TXF_511B 0x02dc /* 32 bit r/o 256-511 Byte Tx Frame Counter */ -#define XM_TXF_1023B 0x02e0 /* 32 bit r/o 512-1023 Byte Tx Frame Counter*/ -#define XM_TXF_MAX_SZ 0x02e4 /* 32 bit r/o 1024-MaxSize Byte Tx Frame Cnt*/ - /* 0x02e8 - 0x02fe: reserved */ -#define XM_RXF_OK 0x0300 /* 32 bit r/o Frames Received OK */ -#define XM_RXO_OK_HI 0x0304 /* 32 bit r/o Octets Received OK High Cnt */ -#define XM_RXO_OK_LO 0x0308 /* 32 bit r/o Octets Received OK Low Counter*/ -#define XM_RXF_BC_OK 0x030c /* 32 bit r/o Broadcast Frames Received OK */ -#define XM_RXF_MC_OK 0x0310 /* 32 bit r/o Multicast Frames Received OK */ -#define XM_RXF_UC_OK 0x0314 /* 32 bit r/o Unicast Frames Received OK */ -#define XM_RXF_MPAUSE 0x0318 /* 32 bit r/o Rx Pause MAC Ctrl Frame Cnt */ -#define XM_RXF_MCTRL 0x031c /* 32 bit r/o Rx MAC Ctrl Frame Counter */ -#define XM_RXF_INV_MP 0x0320 /* 32 bit r/o Rx invalid Pause Frame Cnt */ -#define XM_RXF_INV_MOC 0x0324 /* 32 bit r/o Rx Frames with inv. MAC Opcode*/ -#define XM_RXE_BURST 0x0328 /* 32 bit r/o Rx Burst Event Counter */ -#define XM_RXE_FMISS 0x032c /* 32 bit r/o Rx Missed Frames Event Cnt */ -#define XM_RXF_FRA_ERR 0x0330 /* 32 bit r/o Rx Framing Error Counter */ -#define XM_RXE_FIFO_OV 0x0334 /* 32 bit r/o Rx FIFO overflow Event Cnt */ -#define XM_RXF_JAB_PKT 0x0338 /* 32 bit r/o Rx Jabber Packet Frame Cnt */ -#define XM_RXE_CAR_ERR 0x033c /* 32 bit r/o Rx Carrier Event Error Cnt */ -#define XM_RXF_LEN_ERR 0x0340 /* 32 bit r/o Rx in Range Length Error */ -#define XM_RXE_SYM_ERR 0x0344 /* 32 bit r/o Rx Symbol Error Counter */ -#define XM_RXE_SHT_ERR 0x0348 /* 32 bit r/o Rx Short Event Error Cnt */ -#define XM_RXE_RUNT 0x034c /* 32 bit r/o Rx Runt Event Counter */ -#define XM_RXF_LNG_ERR 0x0350 /* 32 bit r/o Rx Frame too Long Error Cnt */ -#define XM_RXF_FCS_ERR 0x0354 /* 32 bit r/o Rx Frame Check Seq. Error Cnt */ - /* 0x0358 - 0x035a: reserved */ -#define XM_RXF_CEX_ERR 0x035c /* 32 bit r/o Rx Carrier Ext Error Frame Cnt*/ -#define XM_RXP_UTIL 0x0360 /* 32 bit r/o Rx Utilization in % */ - /* 0x0364 - 0x0366: reserved */ -#define XM_RXF_64B 0x0368 /* 32 bit r/o 64 Byte Rx Frame Counter */ -#define XM_RXF_127B 0x036c /* 32 bit r/o 65-127 Byte Rx Frame Counter */ -#define XM_RXF_255B 0x0370 /* 32 bit r/o 128-255 Byte Rx Frame Counter */ -#define XM_RXF_511B 0x0374 /* 32 bit r/o 256-511 Byte Rx Frame Counter */ -#define XM_RXF_1023B 0x0378 /* 32 bit r/o 512-1023 Byte Rx Frame Counter*/ -#define XM_RXF_MAX_SZ 0x037c /* 32 bit r/o 1024-MaxSize Byte Rx Frame Cnt*/ - /* 0x02e8 - 0x02fe: reserved */ - - -/*----------------------------------------------------------------------------*/ -/* - * XMAC Bit Definitions - * - * If the bit access behaviour differs from the register access behaviour - * (r/w, r/o) this is documented after the bit number. - * The following bit access behaviours are used: - * (sc) self clearing - * (ro) read only - */ - -/* XM_MMU_CMD 16 bit r/w MMU Command Register */ - /* Bit 15..13: reserved */ -#define XM_MMU_PHY_RDY (1<<12) /* Bit 12: PHY Read Ready */ -#define XM_MMU_PHY_BUSY (1<<11) /* Bit 11: PHY Busy */ -#define XM_MMU_IGN_PF (1<<10) /* Bit 10: Ignore Pause Frame */ -#define XM_MMU_MAC_LB (1<<9) /* Bit 9: Enable MAC Loopback */ - /* Bit 8: reserved */ -#define XM_MMU_FRC_COL (1<<7) /* Bit 7: Force Collision */ -#define XM_MMU_SIM_COL (1<<6) /* Bit 6: Simulate Collision */ -#define XM_MMU_NO_PRE (1<<5) /* Bit 5: No MDIO Preamble */ -#define XM_MMU_GMII_FD (1<<4) /* Bit 4: GMII uses Full Duplex */ -#define XM_MMU_RAT_CTRL (1<<3) /* Bit 3: Enable Rate Control */ -#define XM_MMU_GMII_LOOP (1<<2) /* Bit 2: PHY is in Loopback Mode */ -#define XM_MMU_ENA_RX (1<<1) /* Bit 1: Enable Receiver */ -#define XM_MMU_ENA_TX (1<<0) /* Bit 0: Enable Transmitter */ - - -/* XM_TX_CMD 16 bit r/w Transmit Command Register */ - /* Bit 15..7: reserved */ -#define XM_TX_BK2BK (1<<6) /* Bit 6: Ignor Carrier Sense (Tx Bk2Bk)*/ -#define XM_TX_ENC_BYP (1<<5) /* Bit 5: Set Encoder in Bypass Mode */ -#define XM_TX_SAM_LINE (1<<4) /* Bit 4: (sc) Start utilization calculation */ -#define XM_TX_NO_GIG_MD (1<<3) /* Bit 3: Disable Carrier Extension */ -#define XM_TX_NO_PRE (1<<2) /* Bit 2: Disable Preamble Generation */ -#define XM_TX_NO_CRC (1<<1) /* Bit 1: Disable CRC Generation */ -#define XM_TX_AUTO_PAD (1<<0) /* Bit 0: Enable Automatic Padding */ - - -/* XM_TX_RT_LIM 16 bit r/w Transmit Retry Limit Register */ - /* Bit 15..5: reserved */ -#define XM_RT_LIM_MSK 0x1f /* Bit 4..0: Tx Retry Limit */ - - -/* XM_TX_STIME 16 bit r/w Transmit Slottime Register */ - /* Bit 15..7: reserved */ -#define XM_STIME_MSK 0x7f /* Bit 6..0: Tx Slottime bits */ - - -/* XM_TX_IPG 16 bit r/w Transmit Inter Packet Gap */ - /* Bit 15..8: reserved */ -#define XM_IPG_MSK 0xff /* Bit 7..0: IPG value bits */ - - -/* XM_RX_CMD 16 bit r/w Receive Command Register */ - /* Bit 15..9: reserved */ -#define XM_RX_LENERR_OK (1<<8) /* Bit 8 don't set Rx Err bit for */ - /* inrange error packets */ -#define XM_RX_BIG_PK_OK (1<<7) /* Bit 7 don't set Rx Err bit for */ - /* jumbo packets */ -#define XM_RX_IPG_CAP (1<<6) /* Bit 6 repl. type field with IPG */ -#define XM_RX_TP_MD (1<<5) /* Bit 5: Enable transparent Mode */ -#define XM_RX_STRIP_FCS (1<<4) /* Bit 4: Enable FCS Stripping */ -#define XM_RX_SELF_RX (1<<3) /* Bit 3: Enable Rx of own packets */ -#define XM_RX_SAM_LINE (1<<2) /* Bit 2: (sc) Start utilization calculation */ -#define XM_RX_STRIP_PAD (1<<1) /* Bit 1: Strip pad bytes of Rx frames */ -#define XM_RX_DIS_CEXT (1<<0) /* Bit 0: Disable carrier ext. check */ - - -/* XM_PHY_ADDR 16 bit r/w PHY Address Register */ - /* Bit 15..5: reserved */ -#define XM_PHY_ADDR_SZ 0x1f /* Bit 4..0: PHY Address bits */ - - -/* XM_GP_PORT 32 bit r/w General Purpose Port Register */ - /* Bit 31..7: reserved */ -#define XM_GP_ANIP (1L<<6) /* Bit 6: (ro) Auto-Neg. in progress */ -#define XM_GP_FRC_INT (1L<<5) /* Bit 5: (sc) Force Interrupt */ - /* Bit 4: reserved */ -#define XM_GP_RES_MAC (1L<<3) /* Bit 3: (sc) Reset MAC and FIFOs */ -#define XM_GP_RES_STAT (1L<<2) /* Bit 2: (sc) Reset the statistics module */ - /* Bit 1: reserved */ -#define XM_GP_INP_ASS (1L<<0) /* Bit 0: (ro) GP Input Pin asserted */ - - -/* XM_IMSK 16 bit r/w Interrupt Mask Register */ -/* XM_ISRC 16 bit r/o Interrupt Status Register */ - /* Bit 15: reserved */ -#define XM_IS_LNK_AE (1<<14) /* Bit 14: Link Asynchronous Event */ -#define XM_IS_TX_ABORT (1<<13) /* Bit 13: Transmit Abort, late Col. etc */ -#define XM_IS_FRC_INT (1<<12) /* Bit 12: Force INT bit set in GP */ -#define XM_IS_INP_ASS (1<<11) /* Bit 11: Input Asserted, GP bit 0 set */ -#define XM_IS_LIPA_RC (1<<10) /* Bit 10: Link Partner requests config */ -#define XM_IS_RX_PAGE (1<<9) /* Bit 9: Page Received */ -#define XM_IS_TX_PAGE (1<<8) /* Bit 8: Next Page Loaded for Transmit */ -#define XM_IS_AND (1<<7) /* Bit 7: Auto-Negotiation Done */ -#define XM_IS_TSC_OV (1<<6) /* Bit 6: Time Stamp Counter Overflow */ -#define XM_IS_RXC_OV (1<<5) /* Bit 5: Rx Counter Event Overflow */ -#define XM_IS_TXC_OV (1<<4) /* Bit 4: Tx Counter Event Overflow */ -#define XM_IS_RXF_OV (1<<3) /* Bit 3: Receive FIFO Overflow */ -#define XM_IS_TXF_UR (1<<2) /* Bit 2: Transmit FIFO Underrun */ -#define XM_IS_TX_COMP (1<<1) /* Bit 1: Frame Tx Complete */ -#define XM_IS_RX_COMP (1<<0) /* Bit 0: Frame Rx Complete */ - -#define XM_DEF_MSK (~(XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE |\ - XM_IS_AND | XM_IS_RXC_OV | XM_IS_TXC_OV | XM_IS_TXF_UR)) - - -/* XM_HW_CFG 16 bit r/w Hardware Config Register */ - /* Bit 15.. 4: reserved */ -#define XM_HW_GEN_EOP (1<<3) /* Bit 3: generate End of Packet pulse */ -#define XM_HW_COM4SIG (1<<2) /* Bit 2: use Comma Detect for Sig. Det.*/ - /* Bit 1: reserved */ -#define XM_HW_GMII_MD (1<<0) /* Bit 0: GMII Interface selected */ - - -/* XM_TX_LO_WM 16 bit r/w Tx FIFO Low Water Mark */ -/* XM_TX_HI_WM 16 bit r/w Tx FIFO High Water Mark */ - /* Bit 15..10 reserved */ -#define XM_TX_WM_MSK 0x01ff /* Bit 9.. 0 Tx FIFO Watermark bits */ - -/* XM_TX_THR 16 bit r/w Tx Request Threshold */ -/* XM_HT_THR 16 bit r/w Host Request Threshold */ -/* XM_RX_THR 16 bit r/w Rx Request Threshold */ - /* Bit 15..11 reserved */ -#define XM_THR_MSK 0x03ff /* Bit 10.. 0 Rx/Tx Request Threshold bits */ - - -/* XM_TX_STAT 32 bit r/o Tx Status LIFO Register */ -#define XM_ST_VALID (1UL<<31) /* Bit 31: Status Valid */ -#define XM_ST_BYTE_CNT (0x3fffL<<17) /* Bit 30..17: Tx frame Length */ -#define XM_ST_RETRY_CNT (0x1fL<<12) /* Bit 16..12: Retry Count */ -#define XM_ST_EX_COL (1L<<11) /* Bit 11: Excessive Collisions */ -#define XM_ST_EX_DEF (1L<<10) /* Bit 10: Excessive Deferral */ -#define XM_ST_BURST (1L<<9) /* Bit 9: p. xmitted in burst md*/ -#define XM_ST_DEFER (1L<<8) /* Bit 8: packet was defered */ -#define XM_ST_BC (1L<<7) /* Bit 7: Broadcast packet */ -#define XM_ST_MC (1L<<6) /* Bit 6: Multicast packet */ -#define XM_ST_UC (1L<<5) /* Bit 5: Unicast packet */ -#define XM_ST_TX_UR (1L<<4) /* Bit 4: FIFO Underrun occured */ -#define XM_ST_CS_ERR (1L<<3) /* Bit 3: Carrier Sense Error */ -#define XM_ST_LAT_COL (1L<<2) /* Bit 2: Late Collision Error */ -#define XM_ST_MUL_COL (1L<<1) /* Bit 1: Multiple Collisions */ -#define XM_ST_SGN_COL (1L<<0) /* Bit 0: Single Collision */ - -/* XM_RX_LO_WM 16 bit r/w Receive Low Water Mark */ -/* XM_RX_HI_WM 16 bit r/w Receive High Water Mark */ - /* Bit 15..11: reserved */ -#define XM_RX_WM_MSK 0x03ff /* Bit 11.. 0: Rx FIFO Watermark bits */ - - -/* XM_DEV_ID 32 bit r/o Device ID Register */ -#define XM_DEV_OUI (0x00ffffffUL<<8) /* Bit 31..8: Device OUI */ -#define XM_DEV_REV (0x07L << 5) /* Bit 7..5: Chip Rev Num */ - - -/* XM_MODE 32 bit r/w Mode Register */ - /* Bit 31..27: reserved */ -#define XM_MD_ENA_REJ (1L<<26) /* Bit 26: Enable Frame Reject */ -#define XM_MD_SPOE_E (1L<<25) /* Bit 25: Send Pause on Edge */ - /* extern generated */ -#define XM_MD_TX_REP (1L<<24) /* Bit 24: Transmit Repeater Mode */ -#define XM_MD_SPOFF_I (1L<<23) /* Bit 23: Send Pause on FIFO full */ - /* intern generated */ -#define XM_MD_LE_STW (1L<<22) /* Bit 22: Rx Stat Word in Little Endian */ -#define XM_MD_TX_CONT (1L<<21) /* Bit 21: Send Continuous */ -#define XM_MD_TX_PAUSE (1L<<20) /* Bit 20: (sc) Send Pause Frame */ -#define XM_MD_ATS (1L<<19) /* Bit 19: Append Time Stamp */ -#define XM_MD_SPOL_I (1L<<18) /* Bit 18: Send Pause on Low */ - /* intern generated */ -#define XM_MD_SPOH_I (1L<<17) /* Bit 17: Send Pause on High */ - /* intern generated */ -#define XM_MD_CAP (1L<<16) /* Bit 16: Check Address Pair */ -#define XM_MD_ENA_HASH (1L<<15) /* Bit 15: Enable Hashing */ -#define XM_MD_CSA (1L<<14) /* Bit 14: Check Station Address */ -#define XM_MD_CAA (1L<<13) /* Bit 13: Check Address Array */ -#define XM_MD_RX_MCTRL (1L<<12) /* Bit 12: Rx MAC Control Frame */ -#define XM_MD_RX_RUNT (1L<<11) /* Bit 11: Rx Runt Frames */ -#define XM_MD_RX_IRLE (1L<<10) /* Bit 10: Rx in Range Len Err Frame */ -#define XM_MD_RX_LONG (1L<<9) /* Bit 9: Rx Long Frame */ -#define XM_MD_RX_CRCE (1L<<8) /* Bit 8: Rx CRC Error Frame */ -#define XM_MD_RX_ERR (1L<<7) /* Bit 7: Rx Error Frame */ -#define XM_MD_DIS_UC (1L<<6) /* Bit 6: Disable Rx Unicast */ -#define XM_MD_DIS_MC (1L<<5) /* Bit 5: Disable Rx Multicast */ -#define XM_MD_DIS_BC (1L<<4) /* Bit 4: Disable Rx Broadcast */ -#define XM_MD_ENA_PROM (1L<<3) /* Bit 3: Enable Promiscuous */ -#define XM_MD_ENA_BE (1L<<2) /* Bit 2: Enable Big Endian */ -#define XM_MD_FTF (1L<<1) /* Bit 1: (sc) Flush Tx FIFO */ -#define XM_MD_FRF (1L<<0) /* Bit 0: (sc) Flush Rx FIFO */ - -#define XM_PAUSE_MODE (XM_MD_SPOE_E | XM_MD_SPOL_I | XM_MD_SPOH_I) -#define XM_DEF_MODE (XM_MD_RX_RUNT | XM_MD_RX_IRLE | XM_MD_RX_LONG |\ - XM_MD_RX_CRCE | XM_MD_RX_ERR | XM_MD_CSA | XM_MD_CAA) - -/* XM_STAT_CMD 16 bit r/w Statistics Command Register */ - /* Bit 16..6: reserved */ -#define XM_SC_SNP_RXC (1<<5) /* Bit 5: (sc) Snap Rx Counters */ -#define XM_SC_SNP_TXC (1<<4) /* Bit 4: (sc) Snap Tx Counters */ -#define XM_SC_CP_RXC (1<<3) /* Bit 3: Copy Rx Counters Continuously */ -#define XM_SC_CP_TXC (1<<2) /* Bit 2: Copy Tx Counters Continuously */ -#define XM_SC_CLR_RXC (1<<1) /* Bit 1: (sc) Clear Rx Counters */ -#define XM_SC_CLR_TXC (1<<0) /* Bit 0: (sc) Clear Tx Counters */ - - -/* XM_RX_CNT_EV 32 bit r/o Rx Counter Event Register */ -/* XM_RX_EV_MSK 32 bit r/w Rx Counter Event Mask */ -#define XMR_MAX_SZ_OV (1UL<<31) /* Bit 31: 1024-MaxSize Rx Cnt Ov*/ -#define XMR_1023B_OV (1L<<30) /* Bit 30: 512-1023Byte Rx Cnt Ov*/ -#define XMR_511B_OV (1L<<29) /* Bit 29: 256-511 Byte Rx Cnt Ov*/ -#define XMR_255B_OV (1L<<28) /* Bit 28: 128-255 Byte Rx Cnt Ov*/ -#define XMR_127B_OV (1L<<27) /* Bit 27: 65-127 Byte Rx Cnt Ov */ -#define XMR_64B_OV (1L<<26) /* Bit 26: 64 Byte Rx Cnt Ov */ -#define XMR_UTIL_OV (1L<<25) /* Bit 25: Rx Util Cnt Overflow */ -#define XMR_UTIL_UR (1L<<24) /* Bit 24: Rx Util Cnt Underrun */ -#define XMR_CEX_ERR_OV (1L<<23) /* Bit 23: CEXT Err Cnt Ov */ - /* Bit 22: reserved */ -#define XMR_FCS_ERR_OV (1L<<21) /* Bit 21: Rx FCS Error Cnt Ov */ -#define XMR_LNG_ERR_OV (1L<<20) /* Bit 20: Rx too Long Err Cnt Ov*/ -#define XMR_RUNT_OV (1L<<19) /* Bit 19: Runt Event Cnt Ov */ -#define XMR_SHT_ERR_OV (1L<<18) /* Bit 18: Rx Short Ev Err Cnt Ov*/ -#define XMR_SYM_ERR_OV (1L<<17) /* Bit 17: Rx Sym Err Cnt Ov */ - /* Bit 16: reserved */ -#define XMR_CAR_ERR_OV (1L<<15) /* Bit 15: Rx Carr Ev Err Cnt Ov */ -#define XMR_JAB_PKT_OV (1L<<14) /* Bit 14: Rx Jabb Packet Cnt Ov */ -#define XMR_FIFO_OV (1L<<13) /* Bit 13: Rx FIFO Ov Ev Cnt Ov */ -#define XMR_FRA_ERR_OV (1L<<12) /* Bit 12: Rx Framing Err Cnt Ov */ -#define XMR_FMISS_OV (1L<<11) /* Bit 11: Rx Missed Ev Cnt Ov */ -#define XMR_BURST (1L<<10) /* Bit 10: Rx Burst Event Cnt Ov */ -#define XMR_INV_MOC (1L<<9) /* Bit 9: Rx with inv. MAC OC Ov*/ -#define XMR_INV_MP (1L<<8) /* Bit 8: Rx inv Pause Frame Ov */ -#define XMR_MCTRL_OV (1L<<7) /* Bit 7: Rx MAC Ctrl-F Cnt Ov */ -#define XMR_MPAUSE_OV (1L<<6) /* Bit 6: Rx Pause MAC Ctrl-F Ov*/ -#define XMR_UC_OK_OV (1L<<5) /* Bit 5: Rx Unicast Frame CntOv*/ -#define XMR_MC_OK_OV (1L<<4) /* Bit 4: Rx Multicast Cnt Ov */ -#define XMR_BC_OK_OV (1L<<3) /* Bit 3: Rx Broadcast Cnt Ov */ -#define XMR_OK_LO_OV (1L<<2) /* Bit 2: Octets Rx OK Low CntOv*/ -#define XMR_OK_HI_OV (1L<<1) /* Bit 1: Octets Rx OK Hi Cnt Ov*/ -#define XMR_OK_OV (1L<<0) /* Bit 0: Frames Received Ok Ov */ - -#define XMR_DEF_MSK (XMR_OK_LO_OV | XMR_OK_HI_OV) - -/* XM_TX_CNT_EV 32 bit r/o Tx Counter Event Register */ -/* XM_TX_EV_MSK 32 bit r/w Tx Counter Event Mask */ - /* Bit 31..26: reserved */ -#define XMT_MAX_SZ_OV (1L<<25) /* Bit 25: 1024-MaxSize Tx Cnt Ov*/ -#define XMT_1023B_OV (1L<<24) /* Bit 24: 512-1023Byte Tx Cnt Ov*/ -#define XMT_511B_OV (1L<<23) /* Bit 23: 256-511 Byte Tx Cnt Ov*/ -#define XMT_255B_OV (1L<<22) /* Bit 22: 128-255 Byte Tx Cnt Ov*/ -#define XMT_127B_OV (1L<<21) /* Bit 21: 65-127 Byte Tx Cnt Ov */ -#define XMT_64B_OV (1L<<20) /* Bit 20: 64 Byte Tx Cnt Ov */ -#define XMT_UTIL_OV (1L<<19) /* Bit 19: Tx Util Cnt Overflow */ -#define XMT_UTIL_UR (1L<<18) /* Bit 18: Tx Util Cnt Underrun */ -#define XMT_CS_ERR_OV (1L<<17) /* Bit 17: Tx Carr Sen Err Cnt Ov*/ -#define XMT_FIFO_UR_OV (1L<<16) /* Bit 16: Tx FIFO Ur Ev Cnt Ov */ -#define XMT_EX_DEF_OV (1L<<15) /* Bit 15: Tx Ex Deferall Cnt Ov */ -#define XMT_DEF (1L<<14) /* Bit 14: Tx Deferred Cnt Ov */ -#define XMT_LAT_COL_OV (1L<<13) /* Bit 13: Tx Late Col Cnt Ov */ -#define XMT_ABO_COL_OV (1L<<12) /* Bit 12: Tx abo dueto Ex Col Ov*/ -#define XMT_MUL_COL_OV (1L<<11) /* Bit 11: Tx Mult Col Cnt Ov */ -#define XMT_SNG_COL (1L<<10) /* Bit 10: Tx Single Col Cnt Ov */ -#define XMT_MCTRL_OV (1L<<9) /* Bit 9: Tx MAC Ctrl Counter Ov*/ -#define XMT_MPAUSE (1L<<8) /* Bit 8: Tx Pause MAC Ctrl-F Ov*/ -#define XMT_BURST (1L<<7) /* Bit 7: Tx Burst Event Cnt Ov */ -#define XMT_LONG (1L<<6) /* Bit 6: Tx Long Frame Cnt Ov */ -#define XMT_UC_OK_OV (1L<<5) /* Bit 5: Tx Unicast Cnt Ov */ -#define XMT_MC_OK_OV (1L<<4) /* Bit 4: Tx Multicast Cnt Ov */ -#define XMT_BC_OK_OV (1L<<3) /* Bit 3: Tx Broadcast Cnt Ov */ -#define XMT_OK_LO_OV (1L<<2) /* Bit 2: Octets Tx OK Low CntOv*/ -#define XMT_OK_HI_OV (1L<<1) /* Bit 1: Octets Tx OK Hi Cnt Ov*/ -#define XMT_OK_OV (1L<<0) /* Bit 0: Frames Tx Ok Ov */ - -#define XMT_DEF_MSK (XMT_OK_LO_OV | XMT_OK_HI_OV) - -/* - * Receive Frame Status Encoding - */ -#define XMR_FS_LEN (0x3fffUL<<18) /* Bit 31..18: Rx Frame Length */ -#define XMR_FS_2L_VLAN (1L<<17) /* Bit 17: tagged wh 2Lev VLAN ID*/ -#define XMR_FS_1L_VLAN (1L<<16) /* Bit 16: tagged wh 1Lev VLAN ID*/ -#define XMR_FS_BC (1L<<15) /* Bit 15: Broadcast Frame */ -#define XMR_FS_MC (1L<<14) /* Bit 14: Multicast Frame */ -#define XMR_FS_UC (1L<<13) /* Bit 13: Unicast Frame */ - /* Bit 12: reserved */ -#define XMR_FS_BURST (1L<<11) /* Bit 11: Burst Mode */ -#define XMR_FS_CEX_ERR (1L<<10) /* Bit 10: Carrier Ext. Error */ -#define XMR_FS_802_3 (1L<<9) /* Bit 9: 802.3 Frame */ -#define XMR_FS_COL_ERR (1L<<8) /* Bit 8: Collision Error */ -#define XMR_FS_CAR_ERR (1L<<7) /* Bit 7: Carrier Event Error */ -#define XMR_FS_LEN_ERR (1L<<6) /* Bit 6: In-Range Length Error */ -#define XMR_FS_FRA_ERR (1L<<5) /* Bit 5: Framing Error */ -#define XMR_FS_RUNT (1L<<4) /* Bit 4: Runt Frame */ -#define XMR_FS_LNG_ERR (1L<<3) /* Bit 3: Giant (Jumbo) Frame */ -#define XMR_FS_FCS_ERR (1L<<2) /* Bit 2: Frame Check Sequ Err */ -#define XMR_FS_ERR (1L<<1) /* Bit 1: Frame Error */ -#define XMR_FS_MCTRL (1L<<0) /* Bit 0: MAC Control Packet */ - -/* - * XMR_FS_ERR will be set if - * XMR_FS_FCS_ERR, XMR_FS_LNG_ERR, XMR_FS_RUNT, - * XMR_FS_FRA_ERR, XMR_FS_LEN_ERR, or XMR_FS_CEX_ERR - * is set. XMR_FS_LNG_ERR and XMR_FS_LEN_ERR will issue - * XMR_FS_ERR unless the corresponding bit in the Receive Command - * Register is set. - */ -#define XMR_FS_ANY_ERR XMR_FS_ERR - -/*----------------------------------------------------------------------------*/ -/* - * XMAC-PHY Registers, indirect addressed over the XMAC - */ -#define PHY_XMAC_CTRL 0x00 /* 16 bit r/w PHY Control Register */ -#define PHY_XMAC_STAT 0x01 /* 16 bit r/w PHY Status Register */ -#define PHY_XMAC_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ -#define PHY_XMAC_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ -#define PHY_XMAC_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ -#define PHY_XMAC_AUNE_LP 0x05 /* 16 bit r/o Link Partner Abi Reg */ -#define PHY_XMAC_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ -#define PHY_XMAC_NEPG 0x07 /* 16 bit r/w Next Page Register */ -#define PHY_XMAC_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */ - /* 0x09 - 0x0e: reserved */ -#define PHY_XMAC_EXT_STAT 0x0f /* 16 bit r/o Ext Status Register */ -#define PHY_XMAC_RES_ABI 0x10 /* 16 bit r/o PHY Resolved Ability */ - -/*----------------------------------------------------------------------------*/ -/* - * Broadcom-PHY Registers, indirect addressed over XMAC - */ -#define PHY_BCOM_CTRL 0x00 /* 16 bit r/w PHY Control Register */ -#define PHY_BCOM_STAT 0x01 /* 16 bit r/o PHY Status Register */ -#define PHY_BCOM_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ -#define PHY_BCOM_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ -#define PHY_BCOM_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ -#define PHY_BCOM_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */ -#define PHY_BCOM_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ -#define PHY_BCOM_NEPG 0x07 /* 16 bit r/w Next Page Register */ -#define PHY_BCOM_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */ - /* Broadcom-specific registers */ -#define PHY_BCOM_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Ctrl Reg */ -#define PHY_BCOM_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */ - /* 0x0b - 0x0e: reserved */ -#define PHY_BCOM_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */ -#define PHY_BCOM_P_EXT_CTRL 0x10 /* 16 bit r/w PHY Extended Ctrl Reg */ -#define PHY_BCOM_P_EXT_STAT 0x11 /* 16 bit r/o PHY Extended Stat Reg */ -#define PHY_BCOM_RE_CTR 0x12 /* 16 bit r/w Receive Error Counter */ -#define PHY_BCOM_FC_CTR 0x13 /* 16 bit r/w False Carrier Sense Cnt */ -#define PHY_BCOM_RNO_CTR 0x14 /* 16 bit r/w Receiver NOT_OK Cnt */ - /* 0x15 - 0x17: reserved */ -#define PHY_BCOM_AUX_CTRL 0x18 /* 16 bit r/w Auxiliary Control Reg */ -#define PHY_BCOM_AUX_STAT 0x19 /* 16 bit r/o Auxiliary Stat Summary */ -#define PHY_BCOM_INT_STAT 0x1a /* 16 bit r/o Interrupt Status Reg */ -#define PHY_BCOM_INT_MASK 0x1b /* 16 bit r/w Interrupt Mask Reg */ - /* 0x1c: reserved */ - /* 0x1d - 0x1f: test registers */ - -/*----------------------------------------------------------------------------*/ -/* - * Marvel-PHY Registers, indirect addressed over GMAC - */ -#define PHY_MARV_CTRL 0x00 /* 16 bit r/w PHY Control Register */ -#define PHY_MARV_STAT 0x01 /* 16 bit r/o PHY Status Register */ -#define PHY_MARV_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ -#define PHY_MARV_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ -#define PHY_MARV_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ -#define PHY_MARV_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */ -#define PHY_MARV_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ -#define PHY_MARV_NEPG 0x07 /* 16 bit r/w Next Page Register */ -#define PHY_MARV_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */ - /* Marvel-specific registers */ -#define PHY_MARV_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Ctrl Reg */ -#define PHY_MARV_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */ - /* 0x0b - 0x0e: reserved */ -#define PHY_MARV_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */ -#define PHY_MARV_PHY_CTRL 0x10 /* 16 bit r/w PHY Specific Ctrl Reg */ -#define PHY_MARV_PHY_STAT 0x11 /* 16 bit r/o PHY Specific Stat Reg */ -#define PHY_MARV_INT_MASK 0x12 /* 16 bit r/w Interrupt Mask Reg */ -#define PHY_MARV_INT_STAT 0x13 /* 16 bit r/o Interrupt Status Reg */ -#define PHY_MARV_EXT_CTRL 0x14 /* 16 bit r/w Ext. PHY Specific Ctrl */ -#define PHY_MARV_RXE_CNT 0x15 /* 16 bit r/w Receive Error Counter */ -#define PHY_MARV_EXT_ADR 0x16 /* 16 bit r/w Ext. Ad. for Cable Diag. */ - /* 0x17: reserved */ -#define PHY_MARV_LED_CTRL 0x18 /* 16 bit r/w LED Control Reg */ -#define PHY_MARV_LED_OVER 0x19 /* 16 bit r/w Manual LED Override Reg */ -#define PHY_MARV_EXT_CTRL_2 0x1a /* 16 bit r/w Ext. PHY Specific Ctrl 2 */ -#define PHY_MARV_EXT_P_STAT 0x1b /* 16 bit r/w Ext. PHY Spec. Stat Reg */ -#define PHY_MARV_CABLE_DIAG 0x1c /* 16 bit r/o Cable Diagnostic Reg */ - /* 0x1d - 0x1f: reserved */ - -/*----------------------------------------------------------------------------*/ -/* - * Level One-PHY Registers, indirect addressed over XMAC - */ -#define PHY_LONE_CTRL 0x00 /* 16 bit r/w PHY Control Register */ -#define PHY_LONE_STAT 0x01 /* 16 bit r/o PHY Status Register */ -#define PHY_LONE_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ -#define PHY_LONE_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ -#define PHY_LONE_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ -#define PHY_LONE_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */ -#define PHY_LONE_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ -#define PHY_LONE_NEPG 0x07 /* 16 bit r/w Next Page Register */ -#define PHY_LONE_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */ - /* Level One-specific registers */ -#define PHY_LONE_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg*/ -#define PHY_LONE_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */ - /* 0x0b -0x0e: reserved */ -#define PHY_LONE_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */ -#define PHY_LONE_PORT_CFG 0x10 /* 16 bit r/w Port Configuration Reg*/ -#define PHY_LONE_Q_STAT 0x11 /* 16 bit r/o Quick Status Reg */ -#define PHY_LONE_INT_ENAB 0x12 /* 16 bit r/w Interrupt Enable Reg */ -#define PHY_LONE_INT_STAT 0x13 /* 16 bit r/o Interrupt Status Reg */ -#define PHY_LONE_LED_CFG 0x14 /* 16 bit r/w LED Configuration Reg */ -#define PHY_LONE_PORT_CTRL 0x15 /* 16 bit r/w Port Control Reg */ -#define PHY_LONE_CIM 0x16 /* 16 bit r/o CIM Reg */ - /* 0x17 -0x1c: reserved */ - -/*----------------------------------------------------------------------------*/ -/* - * National-PHY Registers, indirect addressed over XMAC - */ -#define PHY_NAT_CTRL 0x00 /* 16 bit r/w PHY Control Register */ -#define PHY_NAT_STAT 0x01 /* 16 bit r/w PHY Status Register */ -#define PHY_NAT_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ -#define PHY_NAT_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ -#define PHY_NAT_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ -#define PHY_NAT_AUNE_LP 0x05 /* 16 bit r/o Link Partner Ability Reg */ -#define PHY_NAT_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ -#define PHY_NAT_NEPG 0x07 /* 16 bit r/w Next Page Register */ -#define PHY_NAT_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner Reg */ - /* National-specific registers */ -#define PHY_NAT_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg */ -#define PHY_NAT_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */ - /* 0x0b -0x0e: reserved */ -#define PHY_NAT_EXT_STAT 0x0f /* 16 bit r/o Extended Status Register */ -#define PHY_NAT_EXT_CTRL1 0x10 /* 16 bit r/o Extended Control Reg1 */ -#define PHY_NAT_Q_STAT1 0x11 /* 16 bit r/o Quick Status Reg1 */ -#define PHY_NAT_10B_OP 0x12 /* 16 bit r/o 10Base-T Operations Reg */ -#define PHY_NAT_EXT_CTRL2 0x13 /* 16 bit r/o Extended Control Reg1 */ -#define PHY_NAT_Q_STAT2 0x14 /* 16 bit r/o Quick Status Reg2 */ - /* 0x15 -0x18: reserved */ -#define PHY_NAT_PHY_ADDR 0x19 /* 16 bit r/o PHY Address Register */ - - -/*----------------------------------------------------------------------------*/ - -/* - * PHY bit definitions - * Bits defined as PHY_X_..., PHY_B_..., PHY_L_... or PHY_N_... are - * XMAC/Broadcom/LevelOne/National/Marvell-specific. - * All other are general. - */ - -/***** PHY_XMAC_CTRL 16 bit r/w PHY Control Register *****/ -/***** PHY_BCOM_CTRL 16 bit r/w PHY Control Register *****/ -/***** PHY_MARV_CTRL 16 bit r/w PHY Status Register *****/ -/***** PHY_LONE_CTRL 16 bit r/w PHY Control Register *****/ -#define PHY_CT_RESET (1<<15) /* Bit 15: (sc) clear all PHY related regs */ -#define PHY_CT_LOOP (1<<14) /* Bit 14: enable Loopback over PHY */ -#define PHY_CT_SPS_LSB (1<<13) /* Bit 13: (BC,L1) Speed select, lower bit */ -#define PHY_CT_ANE (1<<12) /* Bit 12: Auto-Negotiation Enabled */ -#define PHY_CT_PDOWN (1<<11) /* Bit 11: (BC,L1) Power Down Mode */ -#define PHY_CT_ISOL (1<<10) /* Bit 10: (BC,L1) Isolate Mode */ -#define PHY_CT_RE_CFG (1<<9) /* Bit 9: (sc) Restart Auto-Negotiation */ -#define PHY_CT_DUP_MD (1<<8) /* Bit 8: Duplex Mode */ -#define PHY_CT_COL_TST (1<<7) /* Bit 7: (BC,L1) Collision Test enabled */ -#define PHY_CT_SPS_MSB (1<<6) /* Bit 6: (BC,L1) Speed select, upper bit */ - /* Bit 5..0: reserved */ - -#define PHY_CT_SP1000 PHY_CT_SPS_MSB /* enable speed of 1000 Mbps */ -#define PHY_CT_SP100 PHY_CT_SPS_LSB /* enable speed of 100 Mbps */ -#define PHY_CT_SP10 (0) /* enable speed of 10 Mbps */ - - -/***** PHY_XMAC_STAT 16 bit r/w PHY Status Register *****/ -/***** PHY_BCOM_STAT 16 bit r/w PHY Status Register *****/ -/***** PHY_MARV_STAT 16 bit r/w PHY Status Register *****/ -/***** PHY_LONE_STAT 16 bit r/w PHY Status Register *****/ - /* Bit 15..9: reserved */ - /* (BC/L1) 100/10 Mbps cap bits ignored*/ -#define PHY_ST_EXT_ST (1<<8) /* Bit 8: Extended Status Present */ - /* Bit 7: reserved */ -#define PHY_ST_PRE_SUP (1<<6) /* Bit 6: (BC/L1) preamble suppression */ -#define PHY_ST_AN_OVER (1<<5) /* Bit 5: Auto-Negotiation Over */ -#define PHY_ST_REM_FLT (1<<4) /* Bit 4: Remote Fault Condition Occured */ -#define PHY_ST_AN_CAP (1<<3) /* Bit 3: Auto-Negotiation Capability */ -#define PHY_ST_LSYNC (1<<2) /* Bit 2: Link Synchronized */ -#define PHY_ST_JAB_DET (1<<1) /* Bit 1: (BC/L1) Jabber Detected */ -#define PHY_ST_EXT_REG (1<<0) /* Bit 0: Extended Register available */ - - -/***** PHY_XMAC_ID1 16 bit r/o PHY ID1 Register */ -/***** PHY_BCOM_ID1 16 bit r/o PHY ID1 Register */ -/***** PHY_MARV_ID1 16 bit r/o PHY ID1 Register */ -/***** PHY_LONE_ID1 16 bit r/o PHY ID1 Register */ -#define PHY_I1_OUI_MSK (0x3f<<10) /* Bit 15..10: Organization Unique ID */ -#define PHY_I1_MOD_NUM (0x3f<<4) /* Bit 9.. 4: Model Number */ -#define PHY_I1_REV_MSK 0x0f /* Bit 3.. 0: Revision Number */ - -/* different Broadcom PHY Ids */ -#define PHY_BCOM_ID1_A1 0x6041 -#define PHY_BCOM_ID1_B2 0x6043 -#define PHY_BCOM_ID1_C0 0x6044 -#define PHY_BCOM_ID1_C5 0x6047 - - -/***** PHY_XMAC_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ -/***** PHY_XMAC_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/ -#define PHY_AN_NXT_PG (1<<15) /* Bit 15: Request Next Page */ -#define PHY_X_AN_ACK (1<<14) /* Bit 14: (ro) Acknowledge Received */ -#define PHY_X_AN_RFB (3<<12) /* Bit 13..12: Remote Fault Bits */ - /* Bit 11.. 9: reserved */ -#define PHY_X_AN_PAUSE (3<<7) /* Bit 8.. 7: Pause Bits */ -#define PHY_X_AN_HD (1<<6) /* Bit 6: Half Duplex */ -#define PHY_X_AN_FD (1<<5) /* Bit 5: Full Duplex */ - /* Bit 4.. 0: reserved */ - -/***** PHY_BCOM_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ -/***** PHY_BCOM_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/ -/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */ - /* Bit 14: reserved */ -#define PHY_B_AN_RF (1<<13) /* Bit 13: Remote Fault */ - /* Bit 12: reserved */ -#define PHY_B_AN_ASP (1<<11) /* Bit 11: Asymmetric Pause */ -#define PHY_B_AN_PC (1<<10) /* Bit 10: Pause Capable */ - /* Bit 9..5: 100/10 BT cap bits ingnored */ -#define PHY_B_AN_SEL 0x1f /* Bit 4..0: Selector Field, 00001=Ethernet*/ - -/***** PHY_LONE_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ -/***** PHY_LONE_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/ -/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */ - /* Bit 14: reserved */ -#define PHY_L_AN_RF (1<<13) /* Bit 13: Remote Fault */ - /* Bit 12: reserved */ -#define PHY_L_AN_ASP (1<<11) /* Bit 11: Asymmetric Pause */ -#define PHY_L_AN_PC (1<<10) /* Bit 10: Pause Capable */ - /* Bit 9..5: 100/10 BT cap bits ingnored */ -#define PHY_L_AN_SEL 0x1f /* Bit 4..0: Selector Field, 00001=Ethernet*/ - -/***** PHY_NAT_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ -/***** PHY_NAT_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/ -/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */ - /* Bit 14: reserved */ -#define PHY_N_AN_RF (1<<13) /* Bit 13: Remote Fault */ - /* Bit 12: reserved */ -#define PHY_N_AN_100F (1<<11) /* Bit 11: 100Base-T2 FD Support */ -#define PHY_N_AN_100H (1<<10) /* Bit 10: 100Base-T2 HD Support */ - /* Bit 9..5: 100/10 BT cap bits ingnored */ -#define PHY_N_AN_SEL 0x1f /* Bit 4..0: Selector Field, 00001=Ethernet*/ - -/* field type definition for PHY_x_AN_SEL */ -#define PHY_SEL_TYPE 0x01 /* 00001 = Ethernet */ - -/***** PHY_XMAC_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/ - /* Bit 15..4: reserved */ -#define PHY_ANE_LP_NP (1<<3) /* Bit 3: Link Partner can Next Page */ -#define PHY_ANE_LOC_NP (1<<2) /* Bit 2: Local PHY can Next Page */ -#define PHY_ANE_RX_PG (1<<1) /* Bit 1: Page Received */ - /* Bit 0: reserved */ - -/***** PHY_BCOM_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/ -/***** PHY_LONE_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/ -/***** PHY_MARV_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/ - /* Bit 15..5: reserved */ -#define PHY_ANE_PAR_DF (1<<4) /* Bit 4: Parallel Detection Fault */ -/* PHY_ANE_LP_NP (see XMAC) Bit 3: Link Partner can Next Page */ -/* PHY_ANE_LOC_NP (see XMAC) Bit 2: Local PHY can Next Page */ -/* PHY_ANE_RX_PG (see XMAC) Bit 1: Page Received */ -#define PHY_ANE_LP_CAP (1<<0) /* Bit 0: Link Partner Auto-Neg. Cap. */ - -/***** PHY_XMAC_NEPG 16 bit r/w Next Page Register *****/ -/***** PHY_BCOM_NEPG 16 bit r/w Next Page Register *****/ -/***** PHY_LONE_NEPG 16 bit r/w Next Page Register *****/ -/***** PHY_XMAC_NEPG_LP 16 bit r/o Next Page Link Partner *****/ -/***** PHY_BCOM_NEPG_LP 16 bit r/o Next Page Link Partner *****/ -/***** PHY_LONE_NEPG_LP 16 bit r/o Next Page Link Partner *****/ -#define PHY_NP_MORE (1<<15) /* Bit 15: More, Next Pages to follow */ -#define PHY_NP_ACK1 (1<<14) /* Bit 14: (ro) Ack1, for receiving a message */ -#define PHY_NP_MSG_VAL (1<<13) /* Bit 13: Message Page valid */ -#define PHY_NP_ACK2 (1<<12) /* Bit 12: Ack2, comply with msg content */ -#define PHY_NP_TOG (1<<11) /* Bit 11: Toggle Bit, ensure sync */ -#define PHY_NP_MSG 0x07ff /* Bit 10..0: Message from/to Link Partner */ - -/* - * XMAC-Specific - */ -/***** PHY_XMAC_EXT_STAT 16 bit r/w Extended Status Register *****/ -#define PHY_X_EX_FD (1<<15) /* Bit 15: Device Supports Full Duplex */ -#define PHY_X_EX_HD (1<<14) /* Bit 14: Device Supports Half Duplex */ - /* Bit 13..0: reserved */ - -/***** PHY_XMAC_RES_ABI 16 bit r/o PHY Resolved Ability *****/ - /* Bit 15..9: reserved */ -#define PHY_X_RS_PAUSE (3<<7) /* Bit 8..7: selected Pause Mode */ -#define PHY_X_RS_HD (1<<6) /* Bit 6: Half Duplex Mode selected */ -#define PHY_X_RS_FD (1<<5) /* Bit 5: Full Duplex Mode selected */ -#define PHY_X_RS_ABLMIS (1<<4) /* Bit 4: duplex or pause cap mismatch */ -#define PHY_X_RS_PAUMIS (1<<3) /* Bit 3: pause capability mismatch */ - /* Bit 2..0: reserved */ -/* - * Remote Fault Bits (PHY_X_AN_RFB) encoding - */ -#define X_RFB_OK (0<<12) /* Bit 13..12 No errors, Link OK */ -#define X_RFB_LF (1<<12) /* Bit 13..12 Link Failure */ -#define X_RFB_OFF (2<<12) /* Bit 13..12 Offline */ -#define X_RFB_AN_ERR (3<<12) /* Bit 13..12 Auto-Negotiation Error */ - -/* - * Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding - */ -#define PHY_X_P_NO_PAUSE (0<<7) /* Bit 8..7: no Pause Mode */ -#define PHY_X_P_SYM_MD (1<<7) /* Bit 8..7: symmetric Pause Mode */ -#define PHY_X_P_ASYM_MD (2<<7) /* Bit 8..7: asymmetric Pause Mode */ -#define PHY_X_P_BOTH_MD (3<<7) /* Bit 8..7: both Pause Mode */ - - -/* - * Broadcom-Specific - */ -/***** PHY_BCOM_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ -#define PHY_B_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */ -#define PHY_B_1000C_MSE (1<<12) /* Bit 12: Master/Slave Enable */ -#define PHY_B_1000C_MSC (1<<11) /* Bit 11: M/S Configuration */ -#define PHY_B_1000C_RD (1<<10) /* Bit 10: Repeater/DTE */ -#define PHY_B_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */ -#define PHY_B_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */ - /* Bit 7..0: reserved */ - -/***** PHY_BCOM_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ -/***** PHY_MARV_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ -#define PHY_B_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */ -#define PHY_B_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */ -#define PHY_B_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */ -#define PHY_B_1000S_RRS (1<<12) /* Bit 12: Remote Receiver Status */ -#define PHY_B_1000S_LP_FD (1<<11) /* Bit 11: Link Partner can FD */ -#define PHY_B_1000S_LP_HD (1<<10) /* Bit 10: Link Partner can HD */ - /* Bit 9..8: reserved */ -#define PHY_B_1000S_IEC 0xff /* Bit 7..0: Idle Error Count */ - -/***** PHY_BCOM_EXT_STAT 16 bit r/o Extended Status Register *****/ -#define PHY_B_ES_X_FD_CAP (1<<15) /* Bit 15: 1000Base-X FD capable */ -#define PHY_B_ES_X_HD_CAP (1<<14) /* Bit 14: 1000Base-X HD capable */ -#define PHY_B_ES_T_FD_CAP (1<<13) /* Bit 13: 1000Base-T FD capable */ -#define PHY_B_ES_T_HD_CAP (1<<12) /* Bit 12: 1000Base-T HD capable */ - /* Bit 11..0: reserved */ - -/***** PHY_BCOM_P_EXT_CTRL 16 bit r/w PHY Extended Control Reg *****/ -#define PHY_B_PEC_MAC_PHY (1<<15) /* Bit 15: 10BIT/GMI-Interface */ -#define PHY_B_PEC_DIS_CROSS (1<<14) /* Bit 14: Disable MDI Crossover */ -#define PHY_B_PEC_TX_DIS (1<<13) /* Bit 13: Tx output Disabled */ -#define PHY_B_PEC_INT_DIS (1<<12) /* Bit 12: Interrupts Disabled */ -#define PHY_B_PEC_F_INT (1<<11) /* Bit 11: Force Interrupt */ -#define PHY_B_PEC_BY_45 (1<<10) /* Bit 10: Bypass 4B5B-Decoder */ -#define PHY_B_PEC_BY_SCR (1<<9) /* Bit 9: Bypass Scrambler */ -#define PHY_B_PEC_BY_MLT3 (1<<8) /* Bit 8: Bypass MLT3 Encoder */ -#define PHY_B_PEC_BY_RXA (1<<7) /* Bit 7: Bypass Rx Alignm. */ -#define PHY_B_PEC_RES_SCR (1<<6) /* Bit 6: Reset Scrambler */ -#define PHY_B_PEC_EN_LTR (1<<5) /* Bit 5: Ena LED Traffic Mode */ -#define PHY_B_PEC_LED_ON (1<<4) /* Bit 4: Force LED's on */ -#define PHY_B_PEC_LED_OFF (1<<3) /* Bit 3: Force LED's off */ -#define PHY_B_PEC_EX_IPG (1<<2) /* Bit 2: Extend Tx IPG Mode */ -#define PHY_B_PEC_3_LED (1<<1) /* Bit 1: Three Link LED mode */ -#define PHY_B_PEC_HIGH_LA (1<<0) /* Bit 0: GMII FIFO Elasticy */ - -/***** PHY_BCOM_P_EXT_STAT 16 bit r/o PHY Extended Status Reg *****/ - /* Bit 15..14: reserved */ -#define PHY_B_PES_CROSS_STAT (1<<13) /* Bit 13: MDI Crossover Status */ -#define PHY_B_PES_INT_STAT (1<<12) /* Bit 12: Interrupt Status */ -#define PHY_B_PES_RRS (1<<11) /* Bit 11: Remote Receiver Stat. */ -#define PHY_B_PES_LRS (1<<10) /* Bit 10: Local Receiver Stat. */ -#define PHY_B_PES_LOCKED (1<<9) /* Bit 9: Locked */ -#define PHY_B_PES_LS (1<<8) /* Bit 8: Link Status */ -#define PHY_B_PES_RF (1<<7) /* Bit 7: Remote Fault */ -#define PHY_B_PES_CE_ER (1<<6) /* Bit 6: Carrier Ext Error */ -#define PHY_B_PES_BAD_SSD (1<<5) /* Bit 5: Bad SSD */ -#define PHY_B_PES_BAD_ESD (1<<4) /* Bit 4: Bad ESD */ -#define PHY_B_PES_RX_ER (1<<3) /* Bit 3: Receive Error */ -#define PHY_B_PES_TX_ER (1<<2) /* Bit 2: Transmit Error */ -#define PHY_B_PES_LOCK_ER (1<<1) /* Bit 1: Lock Error */ -#define PHY_B_PES_MLT3_ER (1<<0) /* Bit 0: MLT3 code Error */ - -/***** PHY_BCOM_FC_CTR 16 bit r/w False Carrier Counter *****/ - /* Bit 15..8: reserved */ -#define PHY_B_FC_CTR 0xff /* Bit 7..0: False Carrier Counter */ - -/***** PHY_BCOM_RNO_CTR 16 bit r/w Receive NOT_OK Counter *****/ -#define PHY_B_RC_LOC_MSK 0xff00 /* Bit 15..8: Local Rx NOT_OK cnt */ -#define PHY_B_RC_REM_MSK 0x00ff /* Bit 7..0: Remote Rx NOT_OK cnt */ - -/***** PHY_BCOM_AUX_CTRL 16 bit r/w Auxiliary Control Reg *****/ -#define PHY_B_AC_L_SQE (1<<15) /* Bit 15: Low Squelch */ -#define PHY_B_AC_LONG_PACK (1<<14) /* Bit 14: Rx Long Packets */ -#define PHY_B_AC_ER_CTRL (3<<12) /* Bit 13..12: Edgerate Control */ - /* Bit 11: reserved */ -#define PHY_B_AC_TX_TST (1<<10) /* Bit 10: Tx test bit, always 1 */ - /* Bit 9.. 8: reserved */ -#define PHY_B_AC_DIS_PRF (1<<7) /* Bit 7: dis part resp filter */ - /* Bit 6: reserved */ -#define PHY_B_AC_DIS_PM (1<<5) /* Bit 5: dis power management */ - /* Bit 4: reserved */ -#define PHY_B_AC_DIAG (1<<3) /* Bit 3: Diagnostic Mode */ - /* Bit 2.. 0: reserved */ - -/***** PHY_BCOM_AUX_STAT 16 bit r/o Auxiliary Status Reg *****/ -#define PHY_B_AS_AN_C (1<<15) /* Bit 15: AutoNeg complete */ -#define PHY_B_AS_AN_CA (1<<14) /* Bit 14: AN Complete Ack */ -#define PHY_B_AS_ANACK_D (1<<13) /* Bit 13: AN Ack Detect */ -#define PHY_B_AS_ANAB_D (1<<12) /* Bit 12: AN Ability Detect */ -#define PHY_B_AS_NPW (1<<11) /* Bit 11: AN Next Page Wait */ -#define PHY_B_AS_AN_RES_MSK (7<<8) /* Bit 10..8: AN HDC */ -#define PHY_B_AS_PDF (1<<7) /* Bit 7: Parallel Detect. Fault */ -#define PHY_B_AS_RF (1<<6) /* Bit 6: Remote Fault */ -#define PHY_B_AS_ANP_R (1<<5) /* Bit 5: AN Page Received */ -#define PHY_B_AS_LP_ANAB (1<<4) /* Bit 4: LP AN Ability */ -#define PHY_B_AS_LP_NPAB (1<<3) /* Bit 3: LP Next Page Ability */ -#define PHY_B_AS_LS (1<<2) /* Bit 2: Link Status */ -#define PHY_B_AS_PRR (1<<1) /* Bit 1: Pause Resolution-Rx */ -#define PHY_B_AS_PRT (1<<0) /* Bit 0: Pause Resolution-Tx */ - -#define PHY_B_AS_PAUSE_MSK (PHY_B_AS_PRR | PHY_B_AS_PRT) - -/***** PHY_BCOM_INT_STAT 16 bit r/o Interrupt Status Reg *****/ -/***** PHY_BCOM_INT_MASK 16 bit r/w Interrupt Mask Reg *****/ - /* Bit 15: reserved */ -#define PHY_B_IS_PSE (1<<14) /* Bit 14: Pair Swap Error */ -#define PHY_B_IS_MDXI_SC (1<<13) /* Bit 13: MDIX Status Change */ -#define PHY_B_IS_HCT (1<<12) /* Bit 12: counter above 32k */ -#define PHY_B_IS_LCT (1<<11) /* Bit 11: counter above 128 */ -#define PHY_B_IS_AN_PR (1<<10) /* Bit 10: Page Received */ -#define PHY_B_IS_NO_HDCL (1<<9) /* Bit 9: No HCD Link */ -#define PHY_B_IS_NO_HDC (1<<8) /* Bit 8: No HCD */ -#define PHY_B_IS_NEG_USHDC (1<<7) /* Bit 7: Negotiated Unsup. HCD */ -#define PHY_B_IS_SCR_S_ER (1<<6) /* Bit 6: Scrambler Sync Error */ -#define PHY_B_IS_RRS_CHANGE (1<<5) /* Bit 5: Remote Rx Stat Change */ -#define PHY_B_IS_LRS_CHANGE (1<<4) /* Bit 4: Local Rx Stat Change */ -#define PHY_B_IS_DUP_CHANGE (1<<3) /* Bit 3: Duplex Mode Change */ -#define PHY_B_IS_LSP_CHANGE (1<<2) /* Bit 2: Link Speed Change */ -#define PHY_B_IS_LST_CHANGE (1<<1) /* Bit 1: Link Status Changed */ -#define PHY_B_IS_CRC_ER (1<<0) /* Bit 0: CRC Error */ - -#define PHY_B_DEF_MSK (~(PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) - -/* Pause Bits (PHY_B_AN_ASP and PHY_B_AN_PC) encoding */ -#define PHY_B_P_NO_PAUSE (0<<10) /* Bit 11..10: no Pause Mode */ -#define PHY_B_P_SYM_MD (1<<10) /* Bit 11..10: symmetric Pause Mode */ -#define PHY_B_P_ASYM_MD (2<<10) /* Bit 11..10: asymmetric Pause Mode */ -#define PHY_B_P_BOTH_MD (3<<10) /* Bit 11..10: both Pause Mode */ - -/* - * Resolved Duplex mode and Capabilities (Aux Status Summary Reg) - */ -#define PHY_B_RES_1000FD (7<<8) /* Bit 10..8: 1000Base-T Full Dup. */ -#define PHY_B_RES_1000HD (6<<8) /* Bit 10..8: 1000Base-T Half Dup. */ -/* others: 100/10: invalid for us */ - -/* - * Level One-Specific - */ -/***** PHY_LONE_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ -#define PHY_L_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */ -#define PHY_L_1000C_MSE (1<<12) /* Bit 12: Master/Slave Enable */ -#define PHY_L_1000C_MSC (1<<11) /* Bit 11: M/S Configuration */ -#define PHY_L_1000C_RD (1<<10) /* Bit 10: Repeater/DTE */ -#define PHY_L_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */ -#define PHY_L_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */ - /* Bit 7..0: reserved */ - -/***** PHY_LONE_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ -#define PHY_L_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */ -#define PHY_L_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */ -#define PHY_L_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */ -#define PHY_L_1000S_RRS (1<<12) /* Bit 12: Remote Receiver Status */ -#define PHY_L_1000S_LP_FD (1<<11) /* Bit 11: Link Partner can FD */ -#define PHY_L_1000S_LP_HD (1<<10) /* Bit 10: Link Partner can HD */ - /* Bit 9..8: reserved */ -#define PHY_B_1000S_IEC 0xff /* Bit 7..0: Idle Error Count */ - -/***** PHY_LONE_EXT_STAT 16 bit r/o Extended Status Register *****/ -#define PHY_L_ES_X_FD_CAP (1<<15) /* Bit 15: 1000Base-X FD capable */ -#define PHY_L_ES_X_HD_CAP (1<<14) /* Bit 14: 1000Base-X HD capable */ -#define PHY_L_ES_T_FD_CAP (1<<13) /* Bit 13: 1000Base-T FD capable */ -#define PHY_L_ES_T_HD_CAP (1<<12) /* Bit 12: 1000Base-T HD capable */ - /* Bit 11..0: reserved */ - -/***** PHY_LONE_PORT_CFG 16 bit r/w Port Configuration Reg *****/ -#define PHY_L_PC_REP_MODE (1<<15) /* Bit 15: Repeater Mode */ - /* Bit 14: reserved */ -#define PHY_L_PC_TX_DIS (1<<13) /* Bit 13: Tx output Disabled */ -#define PHY_L_PC_BY_SCR (1<<12) /* Bit 12: Bypass Scrambler */ -#define PHY_L_PC_BY_45 (1<<11) /* Bit 11: Bypass 4B5B-Decoder */ -#define PHY_L_PC_JAB_DIS (1<<10) /* Bit 10: Jabber Disabled */ -#define PHY_L_PC_SQE (1<<9) /* Bit 9: Enable Heartbeat */ -#define PHY_L_PC_TP_LOOP (1<<8) /* Bit 8: TP Loopback */ -#define PHY_L_PC_SSS (1<<7) /* Bit 7: Smart Speed Selection */ -#define PHY_L_PC_FIFO_SIZE (1<<6) /* Bit 6: FIFO Size */ -#define PHY_L_PC_PRE_EN (1<<5) /* Bit 5: Preamble Enable */ -#define PHY_L_PC_CIM (1<<4) /* Bit 4: Carrier Integrity Mon */ -#define PHY_L_PC_10_SER (1<<3) /* Bit 3: Use Serial Output */ -#define PHY_L_PC_ANISOL (1<<2) /* Bit 2: Unisolate Port */ -#define PHY_L_PC_TEN_BIT (1<<1) /* Bit 1: 10bit iface mode on */ -#define PHY_L_PC_ALTCLOCK (1<<0) /* Bit 0: (ro) ALTCLOCK Mode on */ - -/***** PHY_LONE_Q_STAT 16 bit r/o Quick Status Reg *****/ -#define PHY_L_QS_D_RATE (3<<14) /* Bit 15..14: Data Rate */ -#define PHY_L_QS_TX_STAT (1<<13) /* Bit 13: Transmitting */ -#define PHY_L_QS_RX_STAT (1<<12) /* Bit 12: Receiving */ -#define PHY_L_QS_COL_STAT (1<<11) /* Bit 11: Collision */ -#define PHY_L_QS_L_STAT (1<<10) /* Bit 10: Link is up */ -#define PHY_L_QS_DUP_MOD (1<<9) /* Bit 9: Full/Half Duplex */ -#define PHY_L_QS_AN (1<<8) /* Bit 8: AutoNeg is On */ -#define PHY_L_QS_AN_C (1<<7) /* Bit 7: AN is Complete */ -#define PHY_L_QS_LLE (7<<4) /* Bit 6: Line Length Estim. */ -#define PHY_L_QS_PAUSE (1<<3) /* Bit 3: LP advertised Pause */ -#define PHY_L_QS_AS_PAUSE (1<<2) /* Bit 2: LP adv. asym. Pause */ -#define PHY_L_QS_ISOLATE (1<<1) /* Bit 1: CIM Isolated */ -#define PHY_L_QS_EVENT (1<<0) /* Bit 0: Event has occurred */ - -/***** PHY_LONE_INT_ENAB 16 bit r/w Interrupt Enable Reg *****/ -/***** PHY_LONE_INT_STAT 16 bit r/o Interrupt Status Reg *****/ - /* Bit 15..14: reserved */ -#define PHY_L_IS_AN_F (1<<13) /* Bit 13: Auto-Negotiation fault */ - /* Bit 12: not described */ -#define PHY_L_IS_CROSS (1<<11) /* Bit 11: Crossover used */ -#define PHY_L_IS_POL (1<<10) /* Bit 10: Polarity correct. used */ -#define PHY_L_IS_SS (1<<9) /* Bit 9: Smart Speed Downgrade */ -#define PHY_L_IS_CFULL (1<<8) /* Bit 8: Counter Full */ -#define PHY_L_IS_AN_C (1<<7) /* Bit 7: AutoNeg Complete */ -#define PHY_L_IS_SPEED (1<<6) /* Bit 6: Speed Changed */ -#define PHY_L_IS_DUP (1<<5) /* Bit 5: Duplex Changed */ -#define PHY_L_IS_LS (1<<4) /* Bit 4: Link Status Changed */ -#define PHY_L_IS_ISOL (1<<3) /* Bit 3: Isolate Occured */ -#define PHY_L_IS_MDINT (1<<2) /* Bit 2: (ro) STAT: MII Int Pending */ -#define PHY_L_IS_INTEN (1<<1) /* Bit 1: ENAB: Enable IRQs */ -#define PHY_L_IS_FORCE (1<<0) /* Bit 0: ENAB: Force Interrupt */ - -/* int. mask */ -#define PHY_L_DEF_MSK (PHY_L_IS_LS | PHY_L_IS_ISOL | PHY_L_IS_INTEN) - -/***** PHY_LONE_LED_CFG 16 bit r/w LED Configuration Reg *****/ -#define PHY_L_LC_LEDC (3<<14) /* Bit 15..14: Col/Blink/On/Off */ -#define PHY_L_LC_LEDR (3<<12) /* Bit 13..12: Rx/Blink/On/Off */ -#define PHY_L_LC_LEDT (3<<10) /* Bit 11..10: Tx/Blink/On/Off */ -#define PHY_L_LC_LEDG (3<<8) /* Bit 9..8: Giga/Blink/On/Off */ -#define PHY_L_LC_LEDS (3<<6) /* Bit 7..6: 10-100/Blink/On/Off */ -#define PHY_L_LC_LEDL (3<<4) /* Bit 5..4: Link/Blink/On/Off */ -#define PHY_L_LC_LEDF (3<<2) /* Bit 3..2: Duplex/Blink/On/Off */ -#define PHY_L_LC_PSTRECH (1<<1) /* Bit 1: Strech LED Pulses */ -#define PHY_L_LC_FREQ (1<<0) /* Bit 0: 30/100 ms */ - -/***** PHY_LONE_PORT_CTRL 16 bit r/w Port Control Reg *****/ -#define PHY_L_PC_TX_TCLK (1<<15) /* Bit 15: Enable TX_TCLK */ - /* Bit 14: reserved */ -#define PHY_L_PC_ALT_NP (1<<13) /* Bit 14: Alternate Next Page */ -#define PHY_L_PC_GMII_ALT (1<<12) /* Bit 13: Alternate GMII driver */ - /* Bit 11: reserved */ -#define PHY_L_PC_TEN_CRS (1<<10) /* Bit 10: Extend CRS*/ - /* Bit 9..0: not described */ - -/***** PHY_LONE_CIM 16 bit r/o CIM Reg *****/ -#define PHY_L_CIM_ISOL (255<<8)/* Bit 15..8: Isolate Count */ -#define PHY_L_CIM_FALSE_CAR (255<<0)/* Bit 7..0: False Carrier Count */ - - -/* - * Pause Bits (PHY_L_AN_ASP and PHY_L_AN_PC) encoding - */ -#define PHY_L_P_NO_PAUSE (0<<10) /* Bit 11..10: no Pause Mode */ -#define PHY_L_P_SYM_MD (1<<10) /* Bit 11..10: symmetric Pause Mode */ -#define PHY_L_P_ASYM_MD (2<<10) /* Bit 11..10: asymmetric Pause Mode */ -#define PHY_L_P_BOTH_MD (3<<10) /* Bit 11..10: both Pause Mode */ - - -/* - * National-Specific - */ -/***** PHY_NAT_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ -#define PHY_N_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */ -#define PHY_N_1000C_MSE (1<<12) /* Bit 12: Master/Slave Enable */ -#define PHY_N_1000C_MSC (1<<11) /* Bit 11: M/S Configuration */ -#define PHY_N_1000C_RD (1<<10) /* Bit 10: Repeater/DTE */ -#define PHY_N_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */ -#define PHY_N_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */ -#define PHY_N_1000C_APC (1<<7) /* Bit 7: Asymmetric Pause Cap. */ - /* Bit 6..0: reserved */ - -/***** PHY_NAT_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ -#define PHY_N_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */ -#define PHY_N_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */ -#define PHY_N_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */ -#define PHY_N_1000S_RRS (1<<12) /* Bit 12: Remote Receiver Status*/ -#define PHY_N_1000S_LP_FD (1<<11) /* Bit 11: Link Partner can FD */ -#define PHY_N_1000S_LP_HD (1<<10) /* Bit 10: Link Partner can HD */ -#define PHY_N_1000C_LP_APC (1<<9) /* Bit 9: LP Asym. Pause Cap. */ - /* Bit 8: reserved */ -#define PHY_N_1000S_IEC 0xff /* Bit 7..0: Idle Error Count */ - -/***** PHY_NAT_EXT_STAT 16 bit r/o Extended Status Register *****/ -#define PHY_N_ES_X_FD_CAP (1<<15) /* Bit 15: 1000Base-X FD capable */ -#define PHY_N_ES_X_HD_CAP (1<<14) /* Bit 14: 1000Base-X HD capable */ -#define PHY_N_ES_T_FD_CAP (1<<13) /* Bit 13: 1000Base-T FD capable */ -#define PHY_N_ES_T_HD_CAP (1<<12) /* Bit 12: 1000Base-T HD capable */ - /* Bit 11..0: reserved */ - -/* todo: those are still missing */ -/***** PHY_NAT_EXT_CTRL1 16 bit r/o Extended Control Reg1 *****/ -/***** PHY_NAT_Q_STAT1 16 bit r/o Quick Status Reg1 *****/ -/***** PHY_NAT_10B_OP 16 bit r/o 10Base-T Operations Reg *****/ -/***** PHY_NAT_EXT_CTRL2 16 bit r/o Extended Control Reg1 *****/ -/***** PHY_NAT_Q_STAT2 16 bit r/o Quick Status Reg2 *****/ -/***** PHY_NAT_PHY_ADDR 16 bit r/o PHY Address Register *****/ - -/* - * Marvell-Specific - */ -/***** PHY_MARV_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ -/***** PHY_MARV_AUNE_LP 16 bit r/w Link Part Ability Reg *****/ -#define PHY_M_AN_NXT_PG BIT_15 /* Request Next Page */ -#define PHY_M_AN_ACK BIT_14 /* (ro) Acknowledge Received */ -#define PHY_M_AN_RF BIT_13 /* Remote Fault */ - /* Bit 12: reserved */ -#define PHY_M_AN_ASP BIT_11 /* Asymmetric Pause */ -#define PHY_M_AN_PC BIT_10 /* MAC Pause implemented */ -#define PHY_M_AN_100_FD BIT_8 /* Advertise 100Base-TX Full Duplex */ -#define PHY_M_AN_100_HD BIT_7 /* Advertise 100Base-TX Half Duplex */ -#define PHY_M_AN_10_FD BIT_6 /* Advertise 10Base-TX Full Duplex */ -#define PHY_M_AN_10_HD BIT_5 /* Advertise 10Base-TX Half Duplex */ - -/* special defines for FIBER (88E1011S only) */ -#define PHY_M_AN_ASP_X BIT_8 /* Asymmetric Pause */ -#define PHY_M_AN_PC_X BIT_7 /* MAC Pause implemented */ -#define PHY_M_AN_1000X_AHD BIT_6 /* Advertise 10000Base-X Half Duplex */ -#define PHY_M_AN_1000X_AFD BIT_5 /* Advertise 10000Base-X Full Duplex */ - -/* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */ -#define PHY_M_P_NO_PAUSE_X (0<<7) /* Bit 8.. 7: no Pause Mode */ -#define PHY_M_P_SYM_MD_X (1<<7) /* Bit 8.. 7: symmetric Pause Mode */ -#define PHY_M_P_ASYM_MD_X (2<<7) /* Bit 8.. 7: asymmetric Pause Mode */ -#define PHY_M_P_BOTH_MD_X (3<<7) /* Bit 8.. 7: both Pause Mode */ - -/***** PHY_MARV_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ -#define PHY_M_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */ -#define PHY_M_1000C_MSE (1<<12) /* Bit 12: Manual Master/Slave Enable */ -#define PHY_M_1000C_MSC (1<<11) /* Bit 11: M/S Configuration (1=Master) */ -#define PHY_M_1000C_MPD (1<<10) /* Bit 10: Multi-Port Device */ -#define PHY_M_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */ -#define PHY_M_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */ - /* Bit 7..0: reserved */ - -/***** PHY_MARV_PHY_CTRL 16 bit r/w PHY Specific Ctrl Reg *****/ -#define PHY_M_PC_TX_FFD_MSK (3<<14) /* Bit 15..14: Tx FIFO Depth Mask */ -#define PHY_M_PC_RX_FFD_MSK (3<<12) /* Bit 13..12: Rx FIFO Depth Mask */ -#define PHY_M_PC_ASS_CRS_TX (1<<11) /* Bit 11: Assert CRS on Transmit */ -#define PHY_M_PC_FL_GOOD (1<<10) /* Bit 10: Force Link Good */ -#define PHY_M_PC_EN_DET_MSK (3<<8) /* Bit 9.. 8: Energy Detect Mask */ -#define PHY_M_PC_ENA_EXT_D (1<<7) /* Bit 7: Enable Ext. Distance (10BT) */ -#define PHY_M_PC_MDIX_MSK (3<<5) /* Bit 6.. 5: MDI/MDIX Config. Mask */ -#define PHY_M_PC_DIS_125CLK (1<<4) /* Bit 4: Disable 125 CLK */ -#define PHY_M_PC_MAC_POW_UP (1<<3) /* Bit 3: MAC Power up */ -#define PHY_M_PC_SQE_T_ENA (1<<2) /* Bit 2: SQE Test Enabled */ -#define PHY_M_PC_POL_R_DIS (1<<1) /* Bit 1: Polarity Reversal Disabled */ -#define PHY_M_PC_DIS_JABBER (1<<0) /* Bit 0: Disable Jabber */ - -#define PHY_M_PC_EN_DET SHIFT8(2) /* Energy Detect (Mode 1) */ -#define PHY_M_PC_EN_DET_PLUS SHIFT8(3) /* Energy Detect Plus (Mode 2) */ - -#define PHY_M_PC_MDI_XMODE(x) SHIFT5(x) -#define PHY_M_PC_MAN_MDI 0 /* 00 = Manual MDI configuration */ -#define PHY_M_PC_MAN_MDIX 1 /* 01 = Manual MDIX configuration */ -#define PHY_M_PC_ENA_AUTO 3 /* 11 = Enable Automatic Crossover */ - -/***** PHY_MARV_PHY_STAT 16 bit r/o PHY Specific Status Reg *****/ -#define PHY_M_PS_SPEED_MSK (3<<14) /* Bit 15..14: Speed Mask */ -#define PHY_M_PS_SPEED_1000 (1<<15) /* 10 = 1000 Mbps */ -#define PHY_M_PS_SPEED_100 (1<<14) /* 01 = 100 Mbps */ -#define PHY_M_PS_SPEED_10 0 /* 00 = 10 Mbps */ -#define PHY_M_PS_FULL_DUP (1<<13) /* Bit 13: Full Duplex */ -#define PHY_M_PS_PAGE_REC (1<<12) /* Bit 12: Page Received */ -#define PHY_M_PS_SPDUP_RES (1<<11) /* Bit 11: Speed & Duplex Resolved */ -#define PHY_M_PS_LINK_UP (1<<10) /* Bit 10: Link Up */ -#define PHY_M_PS_CABLE_MSK (3<<7) /* Bit 9.. 7: Cable Length Mask */ -#define PHY_M_PS_MDI_X_STAT (1<<6) /* Bit 6: MDI Crossover Stat (1=MDIX) */ -#define PHY_M_PS_DOWNS_STAT (1<<5) /* Bit 5: Downshift Status (1=downsh.) */ -#define PHY_M_PS_ENDET_STAT (1<<4) /* Bit 4: Energy Detect Status (1=act) */ -#define PHY_M_PS_TX_P_EN (1<<3) /* Bit 3: Tx Pause Enabled */ -#define PHY_M_PS_RX_P_EN (1<<2) /* Bit 2: Rx Pause Enabled */ -#define PHY_M_PS_POL_REV (1<<1) /* Bit 1: Polarity Reversed */ -#define PHY_M_PC_JABBER (1<<0) /* Bit 0: Jabber */ - -#define PHY_M_PS_PAUSE_MSK (PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN) - -/***** PHY_MARV_INT_MASK 16 bit r/w Interrupt Mask Reg *****/ -/***** PHY_MARV_INT_STAT 16 bit r/o Interrupt Status Reg *****/ -#define PHY_M_IS_AN_ERROR (1<<15) /* Bit 15: Auto-Negotiation Error */ -#define PHY_M_IS_LSP_CHANGE (1<<14) /* Bit 14: Link Speed Changed */ -#define PHY_M_IS_DUP_CHANGE (1<<13) /* Bit 13: Duplex Mode Changed */ -#define PHY_M_IS_AN_PR (1<<12) /* Bit 12: Page Received */ -#define PHY_M_IS_AN_COMPL (1<<11) /* Bit 11: Auto-Negotiation Completed */ -#define PHY_M_IS_LST_CHANGE (1<<10) /* Bit 10: Link Status Changed */ -#define PHY_M_IS_SYMB_ERROR (1<<9) /* Bit 9: Symbol Error */ -#define PHY_M_IS_FALSE_CARR (1<<8) /* Bit 8: False Carrier */ -#define PHY_M_IS_FIFO_ERROR (1<<7) /* Bit 7: FIFO Overflow/Underrun Error */ -#define PHY_M_IS_MDI_CHANGE (1<<6) /* Bit 6: MDI Crossover Changed */ -#define PHY_M_IS_DOWNSH_DET (1<<5) /* Bit 5: Downshift Detected */ -#define PHY_M_IS_END_CHANGE (1<<4) /* Bit 4: Energy Detect Changed */ - /* Bit 3..2: reserved */ -#define PHY_M_IS_POL_CHANGE (1<<1) /* Bit 1: Polarity Changed */ -#define PHY_M_IS_JABBER (1<<0) /* Bit 0: Jabber */ - -#define PHY_M_DEF_MSK (PHY_M_IS_AN_ERROR | PHY_M_IS_AN_PR | \ - PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR) - -/***** PHY_MARV_EXT_CTRL 16 bit r/w Ext. PHY Specific Ctrl *****/ -#define PHY_M_EC_M_DSC_MSK (3<<10) /* Bit 11..10: Master downshift counter */ -#define PHY_M_EC_S_DSC_MSK (3<<8) /* Bit 9.. 8: Slave downshift counter */ -#define PHY_M_EC_MAC_S_MSK (7<<4) /* Bit 6.. 4: Def. MAC interface speed */ -#define PHY_M_EC_FIB_AN_ENA (1<<3) /* Bit 3: Fiber Auto-Neg. Enable */ - -#define PHY_M_EC_M_DSC(x) SHIFT10(x) /* 00=1x; 01=2x; 10=3x; 11=4x */ -#define PHY_M_EC_S_DSC(x) SHIFT8(x) /* 00=dis; 01=1x; 10=2x; 11=3x */ -#define PHY_M_EC_MAC_S(x) SHIFT4(x) /* 01X=0; 110=2.5; 111=25 (MHz) */ - -#define MAC_TX_CLK_0_MHZ 2 -#define MAC_TX_CLK_2_5_MHZ 6 -#define MAC_TX_CLK_25_MHZ 7 - -/***** PHY_MARV_LED_CTRL 16 bit r/w LED Control Reg *****/ -#define PHY_M_LEDC_DIS_LED (1<<15) /* Bit 15: Disable LED */ -#define PHY_M_LEDC_PULS_MSK (7<<12) /* Bit 14..12: Pulse Stretch Mask */ -#define PHY_M_LEDC_F_INT (1<<11) /* Bit 11: Force Interrupt */ -#define PHY_M_LEDC_BL_R_MSK (7<<8) /* Bit 10.. 8: Blink Rate Mask */ - /* Bit 7.. 5: reserved */ -#define PHY_M_LEDC_LINK_MSK (3<<3) /* Bit 4.. 3: Link Control Mask */ -#define PHY_M_LEDC_DP_CTRL (1<<2) /* Bit 2: Duplex Control */ -#define PHY_M_LEDC_RX_CTRL (1<<1) /* Bit 1: Rx activity / Link */ -#define PHY_M_LEDC_TX_CTRL (1<<0) /* Bit 0: Tx activity / Link */ - -#define PHY_M_LED_PULS_DUR(x) SHIFT12(x) /* Pulse Stretch Duration */ - -#define PULS_NO_STR 0 /* no pulse stretching */ -#define PULS_21MS 1 /* 21 ms to 42 ms */ -#define PULS_42MS 2 /* 42 ms to 84 ms */ -#define PULS_84MS 3 /* 84 ms to 170 ms */ -#define PULS_170MS 4 /* 170 ms to 340 ms */ -#define PULS_340MS 5 /* 340 ms to 670 ms */ -#define PULS_670MS 6 /* 670 ms to 1.3 s */ -#define PULS_1300MS 7 /* 1.3 s to 2.7 s */ - -#define PHY_M_LED_BLINK_RT(x) SHIFT8(x) /* Blink Rate */ - -#define BLINK_42MS 0 /* 42 ms */ -#define BLINK_84MS 1 /* 84 ms */ -#define BLINK_170MS 2 /* 170 ms */ -#define BLINK_340MS 3 /* 340 ms */ -#define BLINK_670MS 4 /* 670 ms */ - /* values 5 - 7: reserved */ - -/***** PHY_MARV_LED_OVER 16 bit r/w Manual LED Override Reg *****/ -#define PHY_M_LED_MO_DUP(x) SHIFT10(x) /* Bit 11..10: Duplex */ -#define PHY_M_LED_MO_10(x) SHIFT8(x) /* Bit 9.. 8: Link 10 */ -#define PHY_M_LED_MO_100(x) SHIFT6(x) /* Bit 7.. 6: Link 100 */ -#define PHY_M_LED_MO_1000(x) SHIFT4(x) /* Bit 5.. 4: Link 1000 */ -#define PHY_M_LED_MO_RX(x) SHIFT2(x) /* Bit 3.. 2: Rx */ -#define PHY_M_LED_MO_TX(x) SHIFT0(x) /* Bit 1.. 0: Tx */ - -#define MO_LED_NORM 0 -#define MO_LED_BLINK 1 -#define MO_LED_OFF 2 -#define MO_LED_ON 3 - -/***** PHY_MARV_EXT_CTRL_2 16 bit r/w Ext. PHY Specific Ctrl 2 *****/ - /* Bit 15.. 7: reserved */ -#define PHY_M_EC2_FI_IMPED (1<<6) /* Bit 6: Fiber Input Impedance */ -#define PHY_M_EC2_FO_IMPED (1<<5) /* Bit 5: Fiber Output Impedance */ -#define PHY_M_EC2_FO_M_CLK (1<<4) /* Bit 4: Fiber Mode Clock Enable */ -#define PHY_M_EC2_FO_BOOST (1<<3) /* Bit 3: Fiber Output Boost */ -#define PHY_M_EC2_FO_AM_MSK 7 /* Bit 2.. 0: Fiber Output Amplitude */ - -/***** PHY_MARV_EXT_P_STAT 16 bit r/w Ext. PHY Specific Status *****/ -#define PHY_M_FC_AUTO_SEL (1<<15) /* Bit 15: Fiber/Copper Auto Sel. dis. */ -#define PHY_M_FC_AN_REG_ACC (1<<14) /* Bit 14: Fiber/Copper Autoneg. reg acc */ -#define PHY_M_FC_RESULUTION (1<<13) /* Bit 13: Fiber/Copper Resulution */ -#define PHY_M_SER_IF_AN_BP (1<<12) /* Bit 12: Ser IF autoneg. bypass enable */ -#define PHY_M_SER_IF_BP_ST (1<<11) /* Bit 11: Ser IF autoneg. bypass status */ -#define PHY_M_IRQ_POLARITY (1<<10) /* Bit 10: IRQ polarity */ - /* Bit 9..4: reserved */ -#define PHY_M_UNDOC1 (1<< 7) /* undocumented bit !! */ -#define PHY_M_MODE_MASK (0xf<<0)/* Bit 3..0: copy of HWCFG MODE[3:0] */ - - -/***** PHY_MARV_CABLE_DIAG 16 bit r/o Cable Diagnostic Reg *****/ -#define PHY_M_CABD_ENA_TEST (1<<15) /* Bit 15: Enable Test */ -#define PHY_M_CABD_STAT_MSK (3<<13) /* Bit 14..13: Status */ - /* Bit 12.. 8: reserved */ -#define PHY_M_CABD_DIST_MSK 0xff /* Bit 7.. 0: Distance */ - -/* values for Cable Diagnostic Status (11=fail; 00=OK; 10=open; 01=short) */ -#define CABD_STAT_NORMAL 0 -#define CABD_STAT_SHORT 1 -#define CABD_STAT_OPEN 2 -#define CABD_STAT_FAIL 3 - - -/* - * GMAC registers - * - * The GMAC registers are 16 or 32 bits wide. - * The GMACs host processor interface is 16 bits wide, - * therefore ALL registers will be addressed with 16 bit accesses. - * - * The following macros are provided to access the GMAC registers - * GM_IN16(), GM_OUT16, GM_IN32(), GM_OUT32(), GM_INADR(), GM_OUTADR(), - * GM_INHASH(), and GM_OUTHASH(). - * The macros are defined in SkGeHw.h. - * - * Note: NA reg = Network Address e.g DA, SA etc. - * - */ - -/* Port Registers */ -#define GM_GP_STAT 0x0000 /* 16 bit r/o General Purpose Status */ -#define GM_GP_CTRL 0x0004 /* 16 bit r/w General Purpose Control */ -#define GM_TX_CTRL 0x0008 /* 16 bit r/w Transmit Control Reg. */ -#define GM_RX_CTRL 0x000c /* 16 bit r/w Receive Control Reg. */ -#define GM_TX_FLOW_CTRL 0x0010 /* 16 bit r/w Transmit Flow-Control */ -#define GM_TX_PARAM 0x0014 /* 16 bit r/w Transmit Parameter Reg. */ -#define GM_SERIAL_MODE 0x0018 /* 16 bit r/w Serial Mode Register */ - -/* Source Address Registers */ -#define GM_SRC_ADDR_1L 0x001c /* 16 bit r/w Source Address 1 (low) */ -#define GM_SRC_ADDR_1M 0x0020 /* 16 bit r/w Source Address 1 (middle) */ -#define GM_SRC_ADDR_1H 0x0024 /* 16 bit r/w Source Address 1 (high) */ -#define GM_SRC_ADDR_2L 0x0028 /* 16 bit r/w Source Address 2 (low) */ -#define GM_SRC_ADDR_2M 0x002c /* 16 bit r/w Source Address 2 (middle) */ -#define GM_SRC_ADDR_2H 0x0030 /* 16 bit r/w Source Address 2 (high) */ - -/* Multicast Address Hash Registers */ -#define GM_MC_ADDR_H1 0x0034 /* 16 bit r/w Multicast Address Hash 1 */ -#define GM_MC_ADDR_H2 0x0038 /* 16 bit r/w Multicast Address Hash 2 */ -#define GM_MC_ADDR_H3 0x003c /* 16 bit r/w Multicast Address Hash 3 */ -#define GM_MC_ADDR_H4 0x0040 /* 16 bit r/w Multicast Address Hash 4 */ - -/* Interrupt Source Registers */ -#define GM_TX_IRQ_SRC 0x0044 /* 16 bit r/o Tx Overflow IRQ Source */ -#define GM_RX_IRQ_SRC 0x0048 /* 16 bit r/o Rx Overflow IRQ Source */ -#define GM_TR_IRQ_SRC 0x004c /* 16 bit r/o Tx/Rx Over. IRQ Source */ - -/* Interrupt Mask Registers */ -#define GM_TX_IRQ_MSK 0x0050 /* 16 bit r/w Tx Overflow IRQ Mask */ -#define GM_RX_IRQ_MSK 0x0054 /* 16 bit r/w Rx Overflow IRQ Mask */ -#define GM_TR_IRQ_MSK 0x0058 /* 16 bit r/w Tx/Rx Over. IRQ Mask */ - -/* Serial Management Interface (SMI) Registers */ -#define GM_SMI_CTRL 0x0080 /* 16 bit r/w SMI Control Register */ -#define GM_SMI_DATA 0x0084 /* 16 bit r/w SMI Data Register */ -#define GM_PHY_ADDR 0x0088 /* 16 bit r/w GPHY Address Register */ - -/* MIB Counters */ -#define GM_MIB_CNT_BASE 0x0100 /* Base Address of MIB Counters */ -#define GM_MIB_CNT_SIZE 44 /* Number of MIB Counters */ - -/* - * MIB Counters base address definitions (low word) - - * use offset 4 for access to high word (32 bit r/o) - */ -#define GM_RXF_UC_OK \ - (GM_MIB_CNT_BASE + 0) /* Unicast Frames Received OK */ -#define GM_RXF_BC_OK \ - (GM_MIB_CNT_BASE + 8) /* Broadcast Frames Received OK */ -#define GM_RXF_MPAUSE \ - (GM_MIB_CNT_BASE + 16) /* Pause MAC Ctrl Frames Received */ -#define GM_RXF_MC_OK \ - (GM_MIB_CNT_BASE + 24) /* Multicast Frames Received OK */ -#define GM_RXF_FCS_ERR \ - (GM_MIB_CNT_BASE + 32) /* Rx Frame Check Seq. Error */ - /* GM_MIB_CNT_BASE + 40: reserved */ -#define GM_RXO_OK_LO \ - (GM_MIB_CNT_BASE + 48) /* Octets Received OK Low */ -#define GM_RXO_OK_HI \ - (GM_MIB_CNT_BASE + 56) /* Octets Received OK High */ -#define GM_RXO_ERR_LO \ - (GM_MIB_CNT_BASE + 64) /* Octets Received Invalid Low */ -#define GM_RXO_ERR_HI \ - (GM_MIB_CNT_BASE + 72) /* Octets Received Invalid High */ -#define GM_RXF_SHT \ - (GM_MIB_CNT_BASE + 80) /* Frames <64 Byte Received OK */ -#define GM_RXE_FRAG \ - (GM_MIB_CNT_BASE + 88) /* Frames <64 Byte Received with FCS Err */ -#define GM_RXF_64B \ - (GM_MIB_CNT_BASE + 96) /* 64 Byte Rx Frame */ -#define GM_RXF_127B \ - (GM_MIB_CNT_BASE + 104) /* 65-127 Byte Rx Frame */ -#define GM_RXF_255B \ - (GM_MIB_CNT_BASE + 112) /* 128-255 Byte Rx Frame */ -#define GM_RXF_511B \ - (GM_MIB_CNT_BASE + 120) /* 256-511 Byte Rx Frame */ -#define GM_RXF_1023B \ - (GM_MIB_CNT_BASE + 128) /* 512-1023 Byte Rx Frame */ -#define GM_RXF_1518B \ - (GM_MIB_CNT_BASE + 136) /* 1024-1518 Byte Rx Frame */ -#define GM_RXF_MAX_SZ \ - (GM_MIB_CNT_BASE + 144) /* 1519-MaxSize Byte Rx Frame */ -#define GM_RXF_LNG_ERR \ - (GM_MIB_CNT_BASE + 152) /* Rx Frame too Long Error */ -#define GM_RXF_JAB_PKT \ - (GM_MIB_CNT_BASE + 160) /* Rx Jabber Packet Frame */ - /* GM_MIB_CNT_BASE + 168: reserved */ -#define GM_RXE_FIFO_OV \ - (GM_MIB_CNT_BASE + 176) /* Rx FIFO overflow Event */ - /* GM_MIB_CNT_BASE + 184: reserved */ -#define GM_TXF_UC_OK \ - (GM_MIB_CNT_BASE + 192) /* Unicast Frames Xmitted OK */ -#define GM_TXF_BC_OK \ - (GM_MIB_CNT_BASE + 200) /* Broadcast Frames Xmitted OK */ -#define GM_TXF_MPAUSE \ - (GM_MIB_CNT_BASE + 208) /* Pause MAC Ctrl Frames Xmitted */ -#define GM_TXF_MC_OK \ - (GM_MIB_CNT_BASE + 216) /* Multicast Frames Xmitted OK */ -#define GM_TXO_OK_LO \ - (GM_MIB_CNT_BASE + 224) /* Octets Transmitted OK Low */ -#define GM_TXO_OK_HI \ - (GM_MIB_CNT_BASE + 232) /* Octets Transmitted OK High */ -#define GM_TXF_64B \ - (GM_MIB_CNT_BASE + 240) /* 64 Byte Tx Frame */ -#define GM_TXF_127B \ - (GM_MIB_CNT_BASE + 248) /* 65-127 Byte Tx Frame */ -#define GM_TXF_255B \ - (GM_MIB_CNT_BASE + 256) /* 128-255 Byte Tx Frame */ -#define GM_TXF_511B \ - (GM_MIB_CNT_BASE + 264) /* 256-511 Byte Tx Frame */ -#define GM_TXF_1023B \ - (GM_MIB_CNT_BASE + 272) /* 512-1023 Byte Tx Frame */ -#define GM_TXF_1518B \ - (GM_MIB_CNT_BASE + 280) /* 1024-1518 Byte Tx Frame */ -#define GM_TXF_MAX_SZ \ - (GM_MIB_CNT_BASE + 288) /* 1519-MaxSize Byte Tx Frame */ - /* GM_MIB_CNT_BASE + 296: reserved */ -#define GM_TXF_COL \ - (GM_MIB_CNT_BASE + 304) /* Tx Collision */ -#define GM_TXF_LAT_COL \ - (GM_MIB_CNT_BASE + 312) /* Tx Late Collision */ -#define GM_TXF_ABO_COL \ - (GM_MIB_CNT_BASE + 320) /* Tx aborted due to Exces. Col. */ -#define GM_TXF_MUL_COL \ - (GM_MIB_CNT_BASE + 328) /* Tx Multiple Collision */ -#define GM_TXF_SNG_COL \ - (GM_MIB_CNT_BASE + 336) /* Tx Single Collision */ -#define GM_TXE_FIFO_UR \ - (GM_MIB_CNT_BASE + 344) /* Tx FIFO Underrun Event */ - -/*----------------------------------------------------------------------------*/ -/* - * GMAC Bit Definitions - * - * If the bit access behaviour differs from the register access behaviour - * (r/w, r/o) this is documented after the bit number. - * The following bit access behaviours are used: - * (sc) self clearing - * (r/o) read only - */ - -/* GM_GP_STAT 16 bit r/o General Purpose Status Register */ -#define GM_GPSR_SPEED (1<<15) /* Bit 15: Port Speed (1 = 100 Mbps) */ -#define GM_GPSR_DUPLEX (1<<14) /* Bit 14: Duplex Mode (1 = Full) */ -#define GM_GPSR_FC_TX_DIS (1<<13) /* Bit 13: Tx Flow-Control Mode Disabled */ -#define GM_GPSR_LINK_UP (1<<12) /* Bit 12: Link Up Status */ -#define GM_GPSR_PAUSE (1<<11) /* Bit 11: Pause State */ -#define GM_GPSR_TX_ACTIVE (1<<10) /* Bit 10: Tx in Progress */ -#define GM_GPSR_EXC_COL (1<<9) /* Bit 9: Excessive Collisions Occured */ -#define GM_GPSR_LAT_COL (1<<8) /* Bit 8: Late Collisions Occured */ - /* Bit 7..6: reserved */ -#define GM_GPSR_PHY_ST_CH (1<<5) /* Bit 5: PHY Status Change */ -#define GM_GPSR_GIG_SPEED (1<<4) /* Bit 4: Gigabit Speed (1 = 1000 Mbps) */ -#define GM_GPSR_PART_MODE (1<<3) /* Bit 3: Partition mode */ -#define GM_GPSR_FC_RX_DIS (1<<2) /* Bit 2: Rx Flow-Control Mode Disabled */ -#define GM_GPSR_PROM_EN (1<<1) /* Bit 1: Promiscuous Mode Enabled */ - /* Bit 0: reserved */ - -/* GM_GP_CTRL 16 bit r/w General Purpose Control Register */ - /* Bit 15: reserved */ -#define GM_GPCR_PROM_ENA (1<<14) /* Bit 14: Enable Promiscuous Mode */ -#define GM_GPCR_FC_TX_DIS (1<<13) /* Bit 13: Disable Tx Flow-Control Mode */ -#define GM_GPCR_TX_ENA (1<<12) /* Bit 12: Enable Transmit */ -#define GM_GPCR_RX_ENA (1<<11) /* Bit 11: Enable Receive */ -#define GM_GPCR_BURST_ENA (1<<10) /* Bit 10: Enable Burst Mode */ -#define GM_GPCR_LOOP_ENA (1<<9) /* Bit 9: Enable MAC Loopback Mode */ -#define GM_GPCR_PART_ENA (1<<8) /* Bit 8: Enable Partition Mode */ -#define GM_GPCR_GIGS_ENA (1<<7) /* Bit 7: Gigabit Speed (1000 Mbps) */ -#define GM_GPCR_FL_PASS (1<<6) /* Bit 6: Force Link Pass */ -#define GM_GPCR_DUP_FULL (1<<5) /* Bit 5: Full Duplex Mode */ -#define GM_GPCR_FC_RX_DIS (1<<4) /* Bit 4: Disable Rx Flow-Control Mode */ -#define GM_GPCR_SPEED_100 (1<<3) /* Bit 3: Port Speed 100 Mbps */ -#define GM_GPCR_AU_DUP_DIS (1<<2) /* Bit 2: Disable Auto-Update Duplex */ -#define GM_GPCR_AU_FCT_DIS (1<<1) /* Bit 1: Disable Auto-Update Flow-C. */ -#define GM_GPCR_AU_SPD_DIS (1<<0) /* Bit 0: Disable Auto-Update Speed */ - -#define GM_GPCR_SPEED_1000 (GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100) -#define GM_GPCR_AU_ALL_DIS (GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS |\ - GM_GPCR_AU_SPD_DIS) - -/* GM_TX_CTRL 16 bit r/w Transmit Control Register */ -#define GM_TXCR_FORCE_JAM (1<<15) /* Bit 15: Force Jam / Flow-Control */ -#define GM_TXCR_CRC_DIS (1<<14) /* Bit 14: Disable insertion of CRC */ -#define GM_TXCR_PAD_DIS (1<<13) /* Bit 13: Disable padding of packets */ -#define GM_TXCR_COL_THR_MSK (7<<10) /* Bit 12..10: Collision Threshold */ - -#define TX_COL_THR(x) (SHIFT10(x) & GM_TXCR_COL_THR_MSK) - -#define TX_COL_DEF 0x04 - -/* GM_RX_CTRL 16 bit r/w Receive Control Register */ -#define GM_RXCR_UCF_ENA (1<<15) /* Bit 15: Enable Unicast filtering */ -#define GM_RXCR_MCF_ENA (1<<14) /* Bit 14: Enable Multicast filtering */ -#define GM_RXCR_CRC_DIS (1<<13) /* Bit 13: Remove 4-byte CRC */ -#define GM_RXCR_PASS_FC (1<<12) /* Bit 12: Pass FC packets to FIFO */ - -/* GM_TX_PARAM 16 bit r/w Transmit Parameter Register */ -#define GM_TXPA_JAMLEN_MSK (0x03<<14) /* Bit 15..14: Jam Length */ -#define GM_TXPA_JAMIPG_MSK (0x1f<<9) /* Bit 13..9: Jam IPG */ -#define GM_TXPA_JAMDAT_MSK (0x1f<<4) /* Bit 8..4: IPG Jam to Data */ - /* Bit 3..0: reserved */ - -#define TX_JAM_LEN_VAL(x) (SHIFT14(x) & GM_TXPA_JAMLEN_MSK) -#define TX_JAM_IPG_VAL(x) (SHIFT9(x) & GM_TXPA_JAMIPG_MSK) -#define TX_IPG_JAM_DATA(x) (SHIFT4(x) & GM_TXPA_JAMDAT_MSK) - -#define TX_JAM_LEN_DEF 0x03 -#define TX_JAM_IPG_DEF 0x0b -#define TX_IPG_JAM_DEF 0x1c - -/* GM_SERIAL_MODE 16 bit r/w Serial Mode Register */ -#define GM_SMOD_DATABL_MSK (0x1f<<11) /* Bit 15..11: Data Blinder (r/o) */ -#define GM_SMOD_LIMIT_4 (1<<10) /* Bit 10: 4 consecutive Tx trials */ -#define GM_SMOD_VLAN_ENA (1<<9) /* Bit 9: Enable VLAN (Max. Frame Len) */ -#define GM_SMOD_JUMBO_ENA (1<<8) /* Bit 8: Enable Jumbo (Max. Frame Len) */ - /* Bit 7..5: reserved */ -#define GM_SMOD_IPG_MSK 0x1f /* Bit 4..0: Inter-Packet Gap (IPG) */ - -#define DATA_BLIND_VAL(x) (SHIFT11(x) & GM_SMOD_DATABL_MSK) -#define DATA_BLIND_DEF 0x04 - -#define IPG_DATA_VAL(x) (x & GM_SMOD_IPG_MSK) -#define IPG_DATA_DEF 0x1e - -/* GM_SMI_CTRL 16 bit r/w SMI Control Register */ -#define GM_SMI_CT_PHY_A_MSK (0x1f<<11) /* Bit 15..11: PHY Device Address */ -#define GM_SMI_CT_REG_A_MSK (0x1f<<6) /* Bit 10.. 6: PHY Register Address */ -#define GM_SMI_CT_OP_RD (1<<5) /* Bit 5: OpCode Read (0=Write)*/ -#define GM_SMI_CT_RD_VAL (1<<4) /* Bit 4: Read Valid (Read completed) */ -#define GM_SMI_CT_BUSY (1<<3) /* Bit 3: Busy (Operation in progress) */ - /* Bit 2..0: reserved */ - -#define GM_SMI_CT_PHY_AD(x) (SHIFT11(x) & GM_SMI_CT_PHY_A_MSK) -#define GM_SMI_CT_REG_AD(x) (SHIFT6(x) & GM_SMI_CT_REG_A_MSK) - - /* GM_PHY_ADDR 16 bit r/w GPHY Address Register */ - /* Bit 15..6: reserved */ -#define GM_PAR_MIB_CLR (1<<5) /* Bit 5: Set MIB Clear Counter Mode */ -#define GM_PAR_MIB_TST (1<<4) /* Bit 4: MIB Load Counter (Test Mode) */ - /* Bit 3..0: reserved */ - -/* Receive Frame Status Encoding */ -#define GMR_FS_LEN (0xffffUL<<16) /* Bit 31..16: Rx Frame Length */ - /* Bit 15..14: reserved */ -#define GMR_FS_VLAN (1L<<13) /* Bit 13: VLAN Packet */ -#define GMR_FS_JABBER (1L<<12) /* Bit 12: Jabber Packet */ -#define GMR_FS_UN_SIZE (1L<<11) /* Bit 11: Undersize Packet */ -#define GMR_FS_MC (1L<<10) /* Bit 10: Multicast Packet */ -#define GMR_FS_BC (1L<<9) /* Bit 9: Broadcast Packet */ -#define GMR_FS_RX_OK (1L<<8) /* Bit 8: Receive OK (Good Packet) */ -#define GMR_FS_GOOD_FC (1L<<7) /* Bit 7: Good Flow-Control Packet */ -#define GMR_FS_BAD_FC (1L<<6) /* Bit 6: Bad Flow-Control Packet */ -#define GMR_FS_MII_ERR (1L<<5) /* Bit 5: MII Error */ -#define GMR_FS_LONG_ERR (1L<<4) /* Bit 4: Too Long Packet */ -#define GMR_FS_FRAGMENT (1L<<3) /* Bit 3: Fragment */ - /* Bit 2: reserved */ -#define GMR_FS_CRC_ERR (1L<<1) /* Bit 1: CRC Error */ -#define GMR_FS_RX_FF_OV (1L<<0) /* Bit 0: Rx FIFO Overflow */ - -/* - * GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR) - */ -#define GMR_FS_ANY_ERR (GMR_FS_CRC_ERR | \ - GMR_FS_LONG_ERR | \ - GMR_FS_MII_ERR | \ - GMR_FS_BAD_FC | \ - GMR_FS_GOOD_FC | \ - GMR_FS_JABBER) - -/* Rx GMAC FIFO Flush Mask (default) */ -#define RX_FF_FL_DEF_MSK (GMR_FS_CRC_ERR | \ - GMR_FS_RX_FF_OV | \ - GMR_FS_MII_ERR | \ - GMR_FS_BAD_FC | \ - GMR_FS_GOOD_FC | \ - GMR_FS_UN_SIZE | \ - GMR_FS_JABBER) - -/* typedefs *******************************************************************/ - - -/* function prototypes ********************************************************/ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __INC_XMAC_H */ diff --git a/drivers/net/sk98lin/skaddr.c b/drivers/net/sk98lin/skaddr.c deleted file mode 100644 index 6e6c56aa6d6..00000000000 --- a/drivers/net/sk98lin/skaddr.c +++ /dev/null @@ -1,1788 +0,0 @@ -/****************************************************************************** - * - * Name: skaddr.c - * Project: Gigabit Ethernet Adapters, ADDR-Module - * Version: $Revision: 1.52 $ - * Date: $Date: 2003/06/02 13:46:15 $ - * Purpose: Manage Addresses (Multicast and Unicast) and Promiscuous Mode. - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This module is intended to manage multicast addresses, address override, - * and promiscuous mode on GEnesis and Yukon adapters. - * - * Address Layout: - * port address: physical MAC address - * 1st exact match: logical MAC address (GEnesis only) - * 2nd exact match: RLMT multicast (GEnesis only) - * exact match 3-13: OS-specific multicasts (GEnesis only) - * - * Include File Hierarchy: - * - * "skdrv1st.h" - * "skdrv2nd.h" - * - ******************************************************************************/ - -#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) -static const char SysKonnectFileId[] = - "@(#) $Id: skaddr.c,v 1.52 2003/06/02 13:46:15 tschilli Exp $ (C) Marvell."; -#endif /* DEBUG ||!LINT || !SK_SLIM */ - -#define __SKADDR_C - -#ifdef __cplusplus -extern "C" { -#endif /* cplusplus */ - -#include "h/skdrv1st.h" -#include "h/skdrv2nd.h" - -/* defines ********************************************************************/ - - -#define XMAC_POLY 0xEDB88320UL /* CRC32-Poly - XMAC: Little Endian */ -#define GMAC_POLY 0x04C11DB7L /* CRC16-Poly - GMAC: Little Endian */ -#define HASH_BITS 6 /* #bits in hash */ -#define SK_MC_BIT 0x01 - -/* Error numbers and messages. */ - -#define SKERR_ADDR_E001 (SK_ERRBASE_ADDR + 0) -#define SKERR_ADDR_E001MSG "Bad Flags." -#define SKERR_ADDR_E002 (SKERR_ADDR_E001 + 1) -#define SKERR_ADDR_E002MSG "New Error." - -/* typedefs *******************************************************************/ - -/* None. */ - -/* global variables ***********************************************************/ - -/* 64-bit hash values with all bits set. */ - -static const SK_U16 OnesHash[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}; - -/* local variables ************************************************************/ - -#ifdef DEBUG -static int Next0[SK_MAX_MACS] = {0}; -#endif /* DEBUG */ - -static int SkAddrGmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber, - SK_MAC_ADDR *pMc, int Flags); -static int SkAddrGmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber, - int Flags); -static int SkAddrGmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber); -static int SkAddrGmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC, - SK_U32 PortNumber, int NewPromMode); -static int SkAddrXmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber, - SK_MAC_ADDR *pMc, int Flags); -static int SkAddrXmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber, - int Flags); -static int SkAddrXmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber); -static int SkAddrXmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC, - SK_U32 PortNumber, int NewPromMode); - -/* functions ******************************************************************/ - -/****************************************************************************** - * - * SkAddrInit - initialize data, set state to init - * - * Description: - * - * SK_INIT_DATA - * ============ - * - * This routine clears the multicast tables and resets promiscuous mode. - * Some entries are reserved for the "logical MAC address", the - * SK-RLMT multicast address, and the BPDU multicast address. - * - * - * SK_INIT_IO - * ========== - * - * All permanent MAC addresses are read from EPROM. - * If the current MAC addresses are not already set in software, - * they are set to the values of the permanent addresses. - * The current addresses are written to the corresponding MAC. - * - * - * SK_INIT_RUN - * =========== - * - * Nothing. - * - * Context: - * init, pageable - * - * Returns: - * SK_ADDR_SUCCESS - */ -int SkAddrInit( -SK_AC *pAC, /* the adapter context */ -SK_IOC IoC, /* I/O context */ -int Level) /* initialization level */ -{ - int j; - SK_U32 i; - SK_U8 *InAddr; - SK_U16 *OutAddr; - SK_ADDR_PORT *pAPort; - - switch (Level) { - case SK_INIT_DATA: - SK_MEMSET((char *) &pAC->Addr, (SK_U8) 0, - (SK_U16) sizeof(SK_ADDR)); - - for (i = 0; i < SK_MAX_MACS; i++) { - pAPort = &pAC->Addr.Port[i]; - pAPort->PromMode = SK_PROM_MODE_NONE; - - pAPort->FirstExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT; - pAPort->FirstExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV; - pAPort->NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT; - pAPort->NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV; - } -#ifdef xDEBUG - for (i = 0; i < SK_MAX_MACS; i++) { - if (pAC->Addr.Port[i].NextExactMatchRlmt < - SK_ADDR_FIRST_MATCH_RLMT) { - Next0[i] |= 4; - } - } -#endif /* DEBUG */ - /* pAC->Addr.InitDone = SK_INIT_DATA; */ - break; - - case SK_INIT_IO: -#ifndef SK_NO_RLMT - for (i = 0; i < SK_MAX_NETS; i++) { - pAC->Addr.Net[i].ActivePort = pAC->Rlmt.Net[i].ActivePort; - } -#endif /* !SK_NO_RLMT */ -#ifdef xDEBUG - for (i = 0; i < SK_MAX_MACS; i++) { - if (pAC->Addr.Port[i].NextExactMatchRlmt < - SK_ADDR_FIRST_MATCH_RLMT) { - Next0[i] |= 8; - } - } -#endif /* DEBUG */ - - /* Read permanent logical MAC address from Control Register File. */ - for (j = 0; j < SK_MAC_ADDR_LEN; j++) { - InAddr = (SK_U8 *) &pAC->Addr.Net[0].PermanentMacAddress.a[j]; - SK_IN8(IoC, B2_MAC_1 + j, InAddr); - } - - if (!pAC->Addr.Net[0].CurrentMacAddressSet) { - /* Set the current logical MAC address to the permanent one. */ - pAC->Addr.Net[0].CurrentMacAddress = - pAC->Addr.Net[0].PermanentMacAddress; - pAC->Addr.Net[0].CurrentMacAddressSet = SK_TRUE; - } - - /* Set the current logical MAC address. */ - pAC->Addr.Port[pAC->Addr.Net[0].ActivePort].Exact[0] = - pAC->Addr.Net[0].CurrentMacAddress; -#if SK_MAX_NETS > 1 - /* Set logical MAC address for net 2 to (log | 3). */ - if (!pAC->Addr.Net[1].CurrentMacAddressSet) { - pAC->Addr.Net[1].PermanentMacAddress = - pAC->Addr.Net[0].PermanentMacAddress; - pAC->Addr.Net[1].PermanentMacAddress.a[5] |= 3; - /* Set the current logical MAC address to the permanent one. */ - pAC->Addr.Net[1].CurrentMacAddress = - pAC->Addr.Net[1].PermanentMacAddress; - pAC->Addr.Net[1].CurrentMacAddressSet = SK_TRUE; - } -#endif /* SK_MAX_NETS > 1 */ - -#ifdef DEBUG - for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT, - ("Permanent MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n", - i, - pAC->Addr.Net[i].PermanentMacAddress.a[0], - pAC->Addr.Net[i].PermanentMacAddress.a[1], - pAC->Addr.Net[i].PermanentMacAddress.a[2], - pAC->Addr.Net[i].PermanentMacAddress.a[3], - pAC->Addr.Net[i].PermanentMacAddress.a[4], - pAC->Addr.Net[i].PermanentMacAddress.a[5])) - - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT, - ("Logical MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n", - i, - pAC->Addr.Net[i].CurrentMacAddress.a[0], - pAC->Addr.Net[i].CurrentMacAddress.a[1], - pAC->Addr.Net[i].CurrentMacAddress.a[2], - pAC->Addr.Net[i].CurrentMacAddress.a[3], - pAC->Addr.Net[i].CurrentMacAddress.a[4], - pAC->Addr.Net[i].CurrentMacAddress.a[5])) - } -#endif /* DEBUG */ - - for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { - pAPort = &pAC->Addr.Port[i]; - - /* Read permanent port addresses from Control Register File. */ - for (j = 0; j < SK_MAC_ADDR_LEN; j++) { - InAddr = (SK_U8 *) &pAPort->PermanentMacAddress.a[j]; - SK_IN8(IoC, B2_MAC_2 + 8 * i + j, InAddr); - } - - if (!pAPort->CurrentMacAddressSet) { - /* - * Set the current and previous physical MAC address - * of this port to its permanent MAC address. - */ - pAPort->CurrentMacAddress = pAPort->PermanentMacAddress; - pAPort->PreviousMacAddress = pAPort->PermanentMacAddress; - pAPort->CurrentMacAddressSet = SK_TRUE; - } - - /* Set port's current physical MAC address. */ - OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0]; -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - XM_OUTADDR(IoC, i, XM_SA, OutAddr); - } -#endif /* GENESIS */ -#ifdef YUKON - if (!pAC->GIni.GIGenesis) { - GM_OUTADDR(IoC, i, GM_SRC_ADDR_1L, OutAddr); - } -#endif /* YUKON */ -#ifdef DEBUG - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT, - ("SkAddrInit: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n", - pAPort->PermanentMacAddress.a[0], - pAPort->PermanentMacAddress.a[1], - pAPort->PermanentMacAddress.a[2], - pAPort->PermanentMacAddress.a[3], - pAPort->PermanentMacAddress.a[4], - pAPort->PermanentMacAddress.a[5])) - - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT, - ("SkAddrInit: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n", - pAPort->CurrentMacAddress.a[0], - pAPort->CurrentMacAddress.a[1], - pAPort->CurrentMacAddress.a[2], - pAPort->CurrentMacAddress.a[3], - pAPort->CurrentMacAddress.a[4], - pAPort->CurrentMacAddress.a[5])) -#endif /* DEBUG */ - } - /* pAC->Addr.InitDone = SK_INIT_IO; */ - break; - - case SK_INIT_RUN: -#ifdef xDEBUG - for (i = 0; i < SK_MAX_MACS; i++) { - if (pAC->Addr.Port[i].NextExactMatchRlmt < - SK_ADDR_FIRST_MATCH_RLMT) { - Next0[i] |= 16; - } - } -#endif /* DEBUG */ - - /* pAC->Addr.InitDone = SK_INIT_RUN; */ - break; - - default: /* error */ - break; - } - - return (SK_ADDR_SUCCESS); - -} /* SkAddrInit */ - -#ifndef SK_SLIM - -/****************************************************************************** - * - * SkAddrMcClear - clear the multicast table - * - * Description: - * This routine clears the multicast table. - * - * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated - * immediately. - * - * It calls either SkAddrXmacMcClear or SkAddrGmacMcClear, according - * to the adapter in use. The real work is done there. - * - * Context: - * runtime, pageable - * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY - * may be called after SK_INIT_IO without limitation - * - * Returns: - * SK_ADDR_SUCCESS - * SK_ADDR_ILLEGAL_PORT - */ -int SkAddrMcClear( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* Index of affected port */ -int Flags) /* permanent/non-perm, sw-only */ -{ - int ReturnCode; - - if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { - return (SK_ADDR_ILLEGAL_PORT); - } - - if (pAC->GIni.GIGenesis) { - ReturnCode = SkAddrXmacMcClear(pAC, IoC, PortNumber, Flags); - } - else { - ReturnCode = SkAddrGmacMcClear(pAC, IoC, PortNumber, Flags); - } - - return (ReturnCode); - -} /* SkAddrMcClear */ - -#endif /* !SK_SLIM */ - -#ifndef SK_SLIM - -/****************************************************************************** - * - * SkAddrXmacMcClear - clear the multicast table - * - * Description: - * This routine clears the multicast table - * (either entry 2 or entries 3-16 and InexactFilter) of the given port. - * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated - * immediately. - * - * Context: - * runtime, pageable - * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY - * may be called after SK_INIT_IO without limitation - * - * Returns: - * SK_ADDR_SUCCESS - * SK_ADDR_ILLEGAL_PORT - */ -static int SkAddrXmacMcClear( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* Index of affected port */ -int Flags) /* permanent/non-perm, sw-only */ -{ - int i; - - if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */ - - /* Clear RLMT multicast addresses. */ - pAC->Addr.Port[PortNumber].NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT; - } - else { /* not permanent => DRV */ - - /* Clear InexactFilter */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0; - } - - /* Clear DRV multicast addresses. */ - - pAC->Addr.Port[PortNumber].NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV; - } - - if (!(Flags & SK_MC_SW_ONLY)) { - (void) SkAddrXmacMcUpdate(pAC, IoC, PortNumber); - } - - return (SK_ADDR_SUCCESS); - -} /* SkAddrXmacMcClear */ - -#endif /* !SK_SLIM */ - -#ifndef SK_SLIM - -/****************************************************************************** - * - * SkAddrGmacMcClear - clear the multicast table - * - * Description: - * This routine clears the multicast hashing table (InexactFilter) - * (either the RLMT or the driver bits) of the given port. - * - * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated - * immediately. - * - * Context: - * runtime, pageable - * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY - * may be called after SK_INIT_IO without limitation - * - * Returns: - * SK_ADDR_SUCCESS - * SK_ADDR_ILLEGAL_PORT - */ -static int SkAddrGmacMcClear( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* Index of affected port */ -int Flags) /* permanent/non-perm, sw-only */ -{ - int i; - -#ifdef DEBUG - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("GMAC InexactFilter (not cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n", - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7])) -#endif /* DEBUG */ - - /* Clear InexactFilter */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0; - } - - if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */ - - /* Copy DRV bits to InexactFilter. */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |= - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i]; - - /* Clear InexactRlmtFilter. */ - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i] = 0; - - } - } - else { /* not permanent => DRV */ - - /* Copy RLMT bits to InexactFilter. */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |= - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i]; - - /* Clear InexactDrvFilter. */ - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i] = 0; - } - } - -#ifdef DEBUG - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("GMAC InexactFilter (cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n", - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7])) -#endif /* DEBUG */ - - if (!(Flags & SK_MC_SW_ONLY)) { - (void) SkAddrGmacMcUpdate(pAC, IoC, PortNumber); - } - - return (SK_ADDR_SUCCESS); - -} /* SkAddrGmacMcClear */ - -#ifndef SK_ADDR_CHEAT - -/****************************************************************************** - * - * SkXmacMcHash - hash multicast address - * - * Description: - * This routine computes the hash value for a multicast address. - * A CRC32 algorithm is used. - * - * Notes: - * The code was adapted from the XaQti data sheet. - * - * Context: - * runtime, pageable - * - * Returns: - * Hash value of multicast address. - */ -static SK_U32 SkXmacMcHash( -unsigned char *pMc) /* Multicast address */ -{ - SK_U32 Idx; - SK_U32 Bit; - SK_U32 Data; - SK_U32 Crc; - - Crc = 0xFFFFFFFFUL; - for (Idx = 0; Idx < SK_MAC_ADDR_LEN; Idx++) { - Data = *pMc++; - for (Bit = 0; Bit < 8; Bit++, Data >>= 1) { - Crc = (Crc >> 1) ^ (((Crc ^ Data) & 1) ? XMAC_POLY : 0); - } - } - - return (Crc & ((1 << HASH_BITS) - 1)); - -} /* SkXmacMcHash */ - - -/****************************************************************************** - * - * SkGmacMcHash - hash multicast address - * - * Description: - * This routine computes the hash value for a multicast address. - * A CRC16 algorithm is used. - * - * Notes: - * - * - * Context: - * runtime, pageable - * - * Returns: - * Hash value of multicast address. - */ -static SK_U32 SkGmacMcHash( -unsigned char *pMc) /* Multicast address */ -{ - SK_U32 Data; - SK_U32 TmpData; - SK_U32 Crc; - int Byte; - int Bit; - - Crc = 0xFFFFFFFFUL; - for (Byte = 0; Byte < 6; Byte++) { - /* Get next byte. */ - Data = (SK_U32) pMc[Byte]; - - /* Change bit order in byte. */ - TmpData = Data; - for (Bit = 0; Bit < 8; Bit++) { - if (TmpData & 1L) { - Data |= 1L << (7 - Bit); - } - else { - Data &= ~(1L << (7 - Bit)); - } - TmpData >>= 1; - } - - Crc ^= (Data << 24); - for (Bit = 0; Bit < 8; Bit++) { - if (Crc & 0x80000000) { - Crc = (Crc << 1) ^ GMAC_POLY; - } - else { - Crc <<= 1; - } - } - } - - return (Crc & ((1 << HASH_BITS) - 1)); - -} /* SkGmacMcHash */ - -#endif /* !SK_ADDR_CHEAT */ - -/****************************************************************************** - * - * SkAddrMcAdd - add a multicast address to a port - * - * Description: - * This routine enables reception for a given address on the given port. - * - * It calls either SkAddrXmacMcAdd or SkAddrGmacMcAdd, according to the - * adapter in use. The real work is done there. - * - * Notes: - * The return code is only valid for SK_PROM_MODE_NONE. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_DATA - * - * Returns: - * SK_MC_FILTERING_EXACT - * SK_MC_FILTERING_INEXACT - * SK_MC_ILLEGAL_ADDRESS - * SK_MC_ILLEGAL_PORT - * SK_MC_RLMT_OVERFLOW - */ -int SkAddrMcAdd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* Port Number */ -SK_MAC_ADDR *pMc, /* multicast address to be added */ -int Flags) /* permanent/non-permanent */ -{ - int ReturnCode; - - if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { - return (SK_ADDR_ILLEGAL_PORT); - } - - if (pAC->GIni.GIGenesis) { - ReturnCode = SkAddrXmacMcAdd(pAC, IoC, PortNumber, pMc, Flags); - } - else { - ReturnCode = SkAddrGmacMcAdd(pAC, IoC, PortNumber, pMc, Flags); - } - - return (ReturnCode); - -} /* SkAddrMcAdd */ - - -/****************************************************************************** - * - * SkAddrXmacMcAdd - add a multicast address to a port - * - * Description: - * This routine enables reception for a given address on the given port. - * - * Notes: - * The return code is only valid for SK_PROM_MODE_NONE. - * - * The multicast bit is only checked if there are no free exact match - * entries. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_DATA - * - * Returns: - * SK_MC_FILTERING_EXACT - * SK_MC_FILTERING_INEXACT - * SK_MC_ILLEGAL_ADDRESS - * SK_MC_RLMT_OVERFLOW - */ -static int SkAddrXmacMcAdd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* Port Number */ -SK_MAC_ADDR *pMc, /* multicast address to be added */ -int Flags) /* permanent/non-permanent */ -{ - int i; - SK_U8 Inexact; -#ifndef SK_ADDR_CHEAT - SK_U32 HashBit; -#endif /* !defined(SK_ADDR_CHEAT) */ - - if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */ -#ifdef xDEBUG - if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt < - SK_ADDR_FIRST_MATCH_RLMT) { - Next0[PortNumber] |= 1; - return (SK_MC_RLMT_OVERFLOW); - } -#endif /* DEBUG */ - - if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt > - SK_ADDR_LAST_MATCH_RLMT) { - return (SK_MC_RLMT_OVERFLOW); - } - - /* Set a RLMT multicast address. */ - - pAC->Addr.Port[PortNumber].Exact[ - pAC->Addr.Port[PortNumber].NextExactMatchRlmt++] = *pMc; - - return (SK_MC_FILTERING_EXACT); - } - -#ifdef xDEBUG - if (pAC->Addr.Port[PortNumber].NextExactMatchDrv < - SK_ADDR_FIRST_MATCH_DRV) { - Next0[PortNumber] |= 2; - return (SK_MC_RLMT_OVERFLOW); - } -#endif /* DEBUG */ - - if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) { - - /* Set exact match entry. */ - pAC->Addr.Port[PortNumber].Exact[ - pAC->Addr.Port[PortNumber].NextExactMatchDrv++] = *pMc; - - /* Clear InexactFilter */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0; - } - } - else { - if (!(pMc->a[0] & SK_MC_BIT)) { - /* Hashing only possible with multicast addresses */ - return (SK_MC_ILLEGAL_ADDRESS); - } -#ifndef SK_ADDR_CHEAT - /* Compute hash value of address. */ - HashBit = 63 - SkXmacMcHash(&pMc->a[0]); - - /* Add bit to InexactFilter. */ - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[HashBit / 8] |= - 1 << (HashBit % 8); -#else /* SK_ADDR_CHEAT */ - /* Set all bits in InexactFilter. */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF; - } -#endif /* SK_ADDR_CHEAT */ - } - - for (Inexact = 0, i = 0; i < 8; i++) { - Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i]; - } - - if (Inexact == 0 && pAC->Addr.Port[PortNumber].PromMode == 0) { - return (SK_MC_FILTERING_EXACT); - } - else { - return (SK_MC_FILTERING_INEXACT); - } - -} /* SkAddrXmacMcAdd */ - - -/****************************************************************************** - * - * SkAddrGmacMcAdd - add a multicast address to a port - * - * Description: - * This routine enables reception for a given address on the given port. - * - * Notes: - * The return code is only valid for SK_PROM_MODE_NONE. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_DATA - * - * Returns: - * SK_MC_FILTERING_INEXACT - * SK_MC_ILLEGAL_ADDRESS - */ -static int SkAddrGmacMcAdd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* Port Number */ -SK_MAC_ADDR *pMc, /* multicast address to be added */ -int Flags) /* permanent/non-permanent */ -{ - int i; -#ifndef SK_ADDR_CHEAT - SK_U32 HashBit; -#endif /* !defined(SK_ADDR_CHEAT) */ - - if (!(pMc->a[0] & SK_MC_BIT)) { - /* Hashing only possible with multicast addresses */ - return (SK_MC_ILLEGAL_ADDRESS); - } - -#ifndef SK_ADDR_CHEAT - - /* Compute hash value of address. */ - HashBit = SkGmacMcHash(&pMc->a[0]); - - if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */ - - /* Add bit to InexactRlmtFilter. */ - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[HashBit / 8] |= - 1 << (HashBit % 8); - - /* Copy bit to InexactFilter. */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |= - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i]; - } -#ifdef DEBUG - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("GMAC InexactRlmtFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n", - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[0], - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[1], - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[2], - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[3], - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[4], - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[5], - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[6], - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[7])) -#endif /* DEBUG */ - } - else { /* not permanent => DRV */ - - /* Add bit to InexactDrvFilter. */ - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[HashBit / 8] |= - 1 << (HashBit % 8); - - /* Copy bit to InexactFilter. */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |= - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i]; - } -#ifdef DEBUG - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("GMAC InexactDrvFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n", - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[0], - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[1], - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[2], - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[3], - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[4], - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[5], - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[6], - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[7])) -#endif /* DEBUG */ - } - -#else /* SK_ADDR_CHEAT */ - - /* Set all bits in InexactFilter. */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF; - } -#endif /* SK_ADDR_CHEAT */ - - return (SK_MC_FILTERING_INEXACT); - -} /* SkAddrGmacMcAdd */ - -#endif /* !SK_SLIM */ - -/****************************************************************************** - * - * SkAddrMcUpdate - update the HW MC address table and set the MAC address - * - * Description: - * This routine enables reception of the addresses contained in a local - * table for a given port. - * It also programs the port's current physical MAC address. - * - * It calls either SkAddrXmacMcUpdate or SkAddrGmacMcUpdate, according - * to the adapter in use. The real work is done there. - * - * Notes: - * The return code is only valid for SK_PROM_MODE_NONE. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_MC_FILTERING_EXACT - * SK_MC_FILTERING_INEXACT - * SK_ADDR_ILLEGAL_PORT - */ -int SkAddrMcUpdate( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber) /* Port Number */ -{ - int ReturnCode = 0; -#if (!defined(SK_SLIM) || defined(DEBUG)) - if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { - return (SK_ADDR_ILLEGAL_PORT); - } -#endif /* !SK_SLIM || DEBUG */ - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - ReturnCode = SkAddrXmacMcUpdate(pAC, IoC, PortNumber); - } -#endif /* GENESIS */ -#ifdef YUKON - if (!pAC->GIni.GIGenesis) { - ReturnCode = SkAddrGmacMcUpdate(pAC, IoC, PortNumber); - } -#endif /* YUKON */ - return (ReturnCode); - -} /* SkAddrMcUpdate */ - - -#ifdef GENESIS - -/****************************************************************************** - * - * SkAddrXmacMcUpdate - update the HW MC address table and set the MAC address - * - * Description: - * This routine enables reception of the addresses contained in a local - * table for a given port. - * It also programs the port's current physical MAC address. - * - * Notes: - * The return code is only valid for SK_PROM_MODE_NONE. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_MC_FILTERING_EXACT - * SK_MC_FILTERING_INEXACT - * SK_ADDR_ILLEGAL_PORT - */ -static int SkAddrXmacMcUpdate( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber) /* Port Number */ -{ - SK_U32 i; - SK_U8 Inexact; - SK_U16 *OutAddr; - SK_ADDR_PORT *pAPort; - - SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("SkAddrXmacMcUpdate on Port %u.\n", PortNumber)) - - pAPort = &pAC->Addr.Port[PortNumber]; - -#ifdef DEBUG - SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber])) -#endif /* DEBUG */ - - /* Start with 0 to also program the logical MAC address. */ - for (i = 0; i < pAPort->NextExactMatchRlmt; i++) { - /* Set exact match address i on XMAC */ - OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0]; - XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr); - } - - /* Clear other permanent exact match addresses on XMAC */ - if (pAPort->NextExactMatchRlmt <= SK_ADDR_LAST_MATCH_RLMT) { - - SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchRlmt, - SK_ADDR_LAST_MATCH_RLMT); - } - - for (i = pAPort->FirstExactMatchDrv; i < pAPort->NextExactMatchDrv; i++) { - OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0]; - XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr); - } - - /* Clear other non-permanent exact match addresses on XMAC */ - if (pAPort->NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) { - - SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchDrv, - SK_ADDR_LAST_MATCH_DRV); - } - - for (Inexact = 0, i = 0; i < 8; i++) { - Inexact |= pAPort->InexactFilter.Bytes[i]; - } - - if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) { - - /* Set all bits in 64-bit hash register. */ - XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash); - - /* Enable Hashing */ - SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); - } - else if (Inexact != 0) { - - /* Set 64-bit hash register to InexactFilter. */ - XM_OUTHASH(IoC, PortNumber, XM_HSM, &pAPort->InexactFilter.Bytes[0]); - - /* Enable Hashing */ - SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); - } - else { - /* Disable Hashing */ - SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE); - } - - if (pAPort->PromMode != SK_PROM_MODE_NONE) { - (void) SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode); - } - - /* Set port's current physical MAC address. */ - OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0]; - - XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr); - -#ifdef xDEBUG - for (i = 0; i < pAPort->NextExactMatchRlmt; i++) { - SK_U8 InAddr8[6]; - SK_U16 *InAddr; - - /* Get exact match address i from port PortNumber. */ - InAddr = (SK_U16 *) &InAddr8[0]; - - XM_INADDR(IoC, PortNumber, XM_EXM(i), InAddr); - - SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("SkAddrXmacMcUpdate: MC address %d on Port %u: ", - "%02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x\n", - i, - PortNumber, - InAddr8[0], - InAddr8[1], - InAddr8[2], - InAddr8[3], - InAddr8[4], - InAddr8[5], - pAPort->Exact[i].a[0], - pAPort->Exact[i].a[1], - pAPort->Exact[i].a[2], - pAPort->Exact[i].a[3], - pAPort->Exact[i].a[4], - pAPort->Exact[i].a[5])) - } -#endif /* DEBUG */ - - /* Determine return value. */ - if (Inexact == 0 && pAPort->PromMode == 0) { - return (SK_MC_FILTERING_EXACT); - } - else { - return (SK_MC_FILTERING_INEXACT); - } - -} /* SkAddrXmacMcUpdate */ - -#endif /* GENESIS */ - -#ifdef YUKON - -/****************************************************************************** - * - * SkAddrGmacMcUpdate - update the HW MC address table and set the MAC address - * - * Description: - * This routine enables reception of the addresses contained in a local - * table for a given port. - * It also programs the port's current physical MAC address. - * - * Notes: - * The return code is only valid for SK_PROM_MODE_NONE. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_MC_FILTERING_EXACT - * SK_MC_FILTERING_INEXACT - * SK_ADDR_ILLEGAL_PORT - */ -static int SkAddrGmacMcUpdate( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber) /* Port Number */ -{ -#ifndef SK_SLIM - SK_U32 i; - SK_U8 Inexact; -#endif /* not SK_SLIM */ - SK_U16 *OutAddr; - SK_ADDR_PORT *pAPort; - - SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("SkAddrGmacMcUpdate on Port %u.\n", PortNumber)) - - pAPort = &pAC->Addr.Port[PortNumber]; - -#ifdef DEBUG - SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber])) -#endif /* DEBUG */ - -#ifndef SK_SLIM - for (Inexact = 0, i = 0; i < 8; i++) { - Inexact |= pAPort->InexactFilter.Bytes[i]; - } - - /* Set 64-bit hash register to InexactFilter. */ - GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, - &pAPort->InexactFilter.Bytes[0]); - - if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) { - - /* Set all bits in 64-bit hash register. */ - GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash); - - /* Enable Hashing */ - SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); - } - else { - /* Enable Hashing. */ - SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); - } - - if (pAPort->PromMode != SK_PROM_MODE_NONE) { - (void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode); - } -#else /* SK_SLIM */ - - /* Set all bits in 64-bit hash register. */ - GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash); - - /* Enable Hashing */ - SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); - - (void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode); - -#endif /* SK_SLIM */ - - /* Set port's current physical MAC address. */ - OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0]; - GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr); - - /* Set port's current logical MAC address. */ - OutAddr = (SK_U16 *) &pAPort->Exact[0].a[0]; - GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_2L, OutAddr); - -#ifdef DEBUG - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("SkAddrGmacMcUpdate: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n", - pAPort->Exact[0].a[0], - pAPort->Exact[0].a[1], - pAPort->Exact[0].a[2], - pAPort->Exact[0].a[3], - pAPort->Exact[0].a[4], - pAPort->Exact[0].a[5])) - - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("SkAddrGmacMcUpdate: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n", - pAPort->CurrentMacAddress.a[0], - pAPort->CurrentMacAddress.a[1], - pAPort->CurrentMacAddress.a[2], - pAPort->CurrentMacAddress.a[3], - pAPort->CurrentMacAddress.a[4], - pAPort->CurrentMacAddress.a[5])) -#endif /* DEBUG */ - -#ifndef SK_SLIM - /* Determine return value. */ - if (Inexact == 0 && pAPort->PromMode == 0) { - return (SK_MC_FILTERING_EXACT); - } - else { - return (SK_MC_FILTERING_INEXACT); - } -#else /* SK_SLIM */ - return (SK_MC_FILTERING_INEXACT); -#endif /* SK_SLIM */ - -} /* SkAddrGmacMcUpdate */ - -#endif /* YUKON */ - -#ifndef SK_NO_MAO - -/****************************************************************************** - * - * SkAddrOverride - override a port's MAC address - * - * Description: - * This routine overrides the MAC address of one port. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_ADDR_SUCCESS if successful. - * SK_ADDR_DUPLICATE_ADDRESS if duplicate MAC address. - * SK_ADDR_MULTICAST_ADDRESS if multicast or broadcast address. - * SK_ADDR_TOO_EARLY if SK_INIT_IO was not executed before. - */ -int SkAddrOverride( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* Port Number */ -SK_MAC_ADDR SK_FAR *pNewAddr, /* new MAC address */ -int Flags) /* logical/physical MAC address */ -{ -#ifndef SK_NO_RLMT - SK_EVPARA Para; -#endif /* !SK_NO_RLMT */ - SK_U32 NetNumber; - SK_U32 i; - SK_U16 SK_FAR *OutAddr; - -#ifndef SK_NO_RLMT - NetNumber = pAC->Rlmt.Port[PortNumber].Net->NetNumber; -#else - NetNumber = 0; -#endif /* SK_NO_RLMT */ -#if (!defined(SK_SLIM) || defined(DEBUG)) - if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { - return (SK_ADDR_ILLEGAL_PORT); - } -#endif /* !SK_SLIM || DEBUG */ - if (pNewAddr != NULL && (pNewAddr->a[0] & SK_MC_BIT) != 0) { - return (SK_ADDR_MULTICAST_ADDRESS); - } - - if (!pAC->Addr.Net[NetNumber].CurrentMacAddressSet) { - return (SK_ADDR_TOO_EARLY); - } - - if (Flags & SK_ADDR_SET_LOGICAL) { /* Activate logical MAC address. */ - /* Parameter *pNewAddr is ignored. */ - for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { - if (!pAC->Addr.Port[i].CurrentMacAddressSet) { - return (SK_ADDR_TOO_EARLY); - } - } -#ifndef SK_NO_RLMT - /* Set PortNumber to number of net's active port. */ - PortNumber = pAC->Rlmt.Net[NetNumber]. - Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber; -#endif /* !SK_NO_RLMT */ - pAC->Addr.Port[PortNumber].Exact[0] = - pAC->Addr.Net[NetNumber].CurrentMacAddress; - - /* Write address to first exact match entry of active port. */ - (void) SkAddrMcUpdate(pAC, IoC, PortNumber); - } - else if (Flags & SK_ADDR_CLEAR_LOGICAL) { - /* Deactivate logical MAC address. */ - /* Parameter *pNewAddr is ignored. */ - for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { - if (!pAC->Addr.Port[i].CurrentMacAddressSet) { - return (SK_ADDR_TOO_EARLY); - } - } -#ifndef SK_NO_RLMT - /* Set PortNumber to number of net's active port. */ - PortNumber = pAC->Rlmt.Net[NetNumber]. - Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber; -#endif /* !SK_NO_RLMT */ - for (i = 0; i < SK_MAC_ADDR_LEN; i++ ) { - pAC->Addr.Port[PortNumber].Exact[0].a[i] = 0; - } - - /* Write address to first exact match entry of active port. */ - (void) SkAddrMcUpdate(pAC, IoC, PortNumber); - } - else if (Flags & SK_ADDR_PHYSICAL_ADDRESS) { /* Physical MAC address. */ - if (SK_ADDR_EQUAL(pNewAddr->a, - pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) { - return (SK_ADDR_DUPLICATE_ADDRESS); - } - - for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { - if (!pAC->Addr.Port[i].CurrentMacAddressSet) { - return (SK_ADDR_TOO_EARLY); - } - - if (SK_ADDR_EQUAL(pNewAddr->a, - pAC->Addr.Port[i].CurrentMacAddress.a)) { - if (i == PortNumber) { - return (SK_ADDR_SUCCESS); - } - else { - return (SK_ADDR_DUPLICATE_ADDRESS); - } - } - } - - pAC->Addr.Port[PortNumber].PreviousMacAddress = - pAC->Addr.Port[PortNumber].CurrentMacAddress; - pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr; - - /* Change port's physical MAC address. */ - OutAddr = (SK_U16 SK_FAR *) pNewAddr; -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr); - } -#endif /* GENESIS */ -#ifdef YUKON - if (!pAC->GIni.GIGenesis) { - GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr); - } -#endif /* YUKON */ - -#ifndef SK_NO_RLMT - /* Report address change to RLMT. */ - Para.Para32[0] = PortNumber; - Para.Para32[0] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para); -#endif /* !SK_NO_RLMT */ - } - else { /* Logical MAC address. */ - if (SK_ADDR_EQUAL(pNewAddr->a, - pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) { - return (SK_ADDR_SUCCESS); - } - - for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { - if (!pAC->Addr.Port[i].CurrentMacAddressSet) { - return (SK_ADDR_TOO_EARLY); - } - - if (SK_ADDR_EQUAL(pNewAddr->a, - pAC->Addr.Port[i].CurrentMacAddress.a)) { - return (SK_ADDR_DUPLICATE_ADDRESS); - } - } - - /* - * In case that the physical and the logical MAC addresses are equal - * we must also change the physical MAC address here. - * In this case we have an adapter which initially was programmed with - * two identical MAC addresses. - */ - if (SK_ADDR_EQUAL(pAC->Addr.Port[PortNumber].CurrentMacAddress.a, - pAC->Addr.Port[PortNumber].Exact[0].a)) { - - pAC->Addr.Port[PortNumber].PreviousMacAddress = - pAC->Addr.Port[PortNumber].CurrentMacAddress; - pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr; - -#ifndef SK_NO_RLMT - /* Report address change to RLMT. */ - Para.Para32[0] = PortNumber; - Para.Para32[0] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para); -#endif /* !SK_NO_RLMT */ - } - -#ifndef SK_NO_RLMT - /* Set PortNumber to number of net's active port. */ - PortNumber = pAC->Rlmt.Net[NetNumber]. - Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber; -#endif /* !SK_NO_RLMT */ - pAC->Addr.Net[NetNumber].CurrentMacAddress = *pNewAddr; - pAC->Addr.Port[PortNumber].Exact[0] = *pNewAddr; -#ifdef DEBUG - SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("SkAddrOverride: Permanent MAC Address: %02X %02X %02X %02X %02X %02X\n", - pAC->Addr.Net[NetNumber].PermanentMacAddress.a[0], - pAC->Addr.Net[NetNumber].PermanentMacAddress.a[1], - pAC->Addr.Net[NetNumber].PermanentMacAddress.a[2], - pAC->Addr.Net[NetNumber].PermanentMacAddress.a[3], - pAC->Addr.Net[NetNumber].PermanentMacAddress.a[4], - pAC->Addr.Net[NetNumber].PermanentMacAddress.a[5])) - - SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("SkAddrOverride: New logical MAC Address: %02X %02X %02X %02X %02X %02X\n", - pAC->Addr.Net[NetNumber].CurrentMacAddress.a[0], - pAC->Addr.Net[NetNumber].CurrentMacAddress.a[1], - pAC->Addr.Net[NetNumber].CurrentMacAddress.a[2], - pAC->Addr.Net[NetNumber].CurrentMacAddress.a[3], - pAC->Addr.Net[NetNumber].CurrentMacAddress.a[4], - pAC->Addr.Net[NetNumber].CurrentMacAddress.a[5])) -#endif /* DEBUG */ - - /* Write address to first exact match entry of active port. */ - (void) SkAddrMcUpdate(pAC, IoC, PortNumber); - } - - return (SK_ADDR_SUCCESS); - -} /* SkAddrOverride */ - - -#endif /* SK_NO_MAO */ - -/****************************************************************************** - * - * SkAddrPromiscuousChange - set promiscuous mode for given port - * - * Description: - * This routine manages promiscuous mode: - * - none - * - all LLC frames - * - all MC frames - * - * It calls either SkAddrXmacPromiscuousChange or - * SkAddrGmacPromiscuousChange, according to the adapter in use. - * The real work is done there. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_ADDR_SUCCESS - * SK_ADDR_ILLEGAL_PORT - */ -int SkAddrPromiscuousChange( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* port whose promiscuous mode changes */ -int NewPromMode) /* new promiscuous mode */ -{ - int ReturnCode = 0; -#if (!defined(SK_SLIM) || defined(DEBUG)) - if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { - return (SK_ADDR_ILLEGAL_PORT); - } -#endif /* !SK_SLIM || DEBUG */ - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - ReturnCode = - SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode); - } -#endif /* GENESIS */ -#ifdef YUKON - if (!pAC->GIni.GIGenesis) { - ReturnCode = - SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode); - } -#endif /* YUKON */ - - return (ReturnCode); - -} /* SkAddrPromiscuousChange */ - -#ifdef GENESIS - -/****************************************************************************** - * - * SkAddrXmacPromiscuousChange - set promiscuous mode for given port - * - * Description: - * This routine manages promiscuous mode: - * - none - * - all LLC frames - * - all MC frames - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_ADDR_SUCCESS - * SK_ADDR_ILLEGAL_PORT - */ -static int SkAddrXmacPromiscuousChange( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* port whose promiscuous mode changes */ -int NewPromMode) /* new promiscuous mode */ -{ - int i; - SK_BOOL InexactModeBit; - SK_U8 Inexact; - SK_U8 HwInexact; - SK_FILTER64 HwInexactFilter; - SK_U16 LoMode; /* Lower 16 bits of XMAC Mode Register. */ - int CurPromMode = SK_PROM_MODE_NONE; - - /* Read CurPromMode from Hardware. */ - XM_IN16(IoC, PortNumber, XM_MODE, &LoMode); - - if ((LoMode & XM_MD_ENA_PROM) != 0) { - /* Promiscuous mode! */ - CurPromMode |= SK_PROM_MODE_LLC; - } - - for (Inexact = 0xFF, i = 0; i < 8; i++) { - Inexact &= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i]; - } - if (Inexact == 0xFF) { - CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC); - } - else { - /* Get InexactModeBit (bit XM_MD_ENA_HASH in mode register) */ - XM_IN16(IoC, PortNumber, XM_MODE, &LoMode); - - InexactModeBit = (LoMode & XM_MD_ENA_HASH) != 0; - - /* Read 64-bit hash register from XMAC */ - XM_INHASH(IoC, PortNumber, XM_HSM, &HwInexactFilter.Bytes[0]); - - for (HwInexact = 0xFF, i = 0; i < 8; i++) { - HwInexact &= HwInexactFilter.Bytes[i]; - } - - if (InexactModeBit && (HwInexact == 0xFF)) { - CurPromMode |= SK_PROM_MODE_ALL_MC; - } - } - - pAC->Addr.Port[PortNumber].PromMode = NewPromMode; - - if (NewPromMode == CurPromMode) { - return (SK_ADDR_SUCCESS); - } - - if ((NewPromMode & SK_PROM_MODE_ALL_MC) && - !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC. */ - - /* Set all bits in 64-bit hash register. */ - XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash); - - /* Enable Hashing */ - SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); - } - else if ((CurPromMode & SK_PROM_MODE_ALL_MC) && - !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm MC. */ - for (Inexact = 0, i = 0; i < 8; i++) { - Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i]; - } - if (Inexact == 0) { - /* Disable Hashing */ - SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE); - } - else { - /* Set 64-bit hash register to InexactFilter. */ - XM_OUTHASH(IoC, PortNumber, XM_HSM, - &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]); - - /* Enable Hashing */ - SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); - } - } - - if ((NewPromMode & SK_PROM_MODE_LLC) && - !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */ - /* Set the MAC in Promiscuous Mode */ - SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE); - } - else if ((CurPromMode & SK_PROM_MODE_LLC) && - !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC. */ - /* Clear Promiscuous Mode */ - SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE); - } - - return (SK_ADDR_SUCCESS); - -} /* SkAddrXmacPromiscuousChange */ - -#endif /* GENESIS */ - -#ifdef YUKON - -/****************************************************************************** - * - * SkAddrGmacPromiscuousChange - set promiscuous mode for given port - * - * Description: - * This routine manages promiscuous mode: - * - none - * - all LLC frames - * - all MC frames - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_ADDR_SUCCESS - * SK_ADDR_ILLEGAL_PORT - */ -static int SkAddrGmacPromiscuousChange( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* port whose promiscuous mode changes */ -int NewPromMode) /* new promiscuous mode */ -{ - SK_U16 ReceiveControl; /* GMAC Receive Control Register */ - int CurPromMode = SK_PROM_MODE_NONE; - - /* Read CurPromMode from Hardware. */ - GM_IN16(IoC, PortNumber, GM_RX_CTRL, &ReceiveControl); - - if ((ReceiveControl & (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA)) == 0) { - /* Promiscuous mode! */ - CurPromMode |= SK_PROM_MODE_LLC; - } - - if ((ReceiveControl & GM_RXCR_MCF_ENA) == 0) { - /* All Multicast mode! */ - CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC); - } - - pAC->Addr.Port[PortNumber].PromMode = NewPromMode; - - if (NewPromMode == CurPromMode) { - return (SK_ADDR_SUCCESS); - } - - if ((NewPromMode & SK_PROM_MODE_ALL_MC) && - !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC */ - - /* Set all bits in 64-bit hash register. */ - GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash); - - /* Enable Hashing */ - SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); - } - - if ((CurPromMode & SK_PROM_MODE_ALL_MC) && - !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm. MC */ - - /* Set 64-bit hash register to InexactFilter. */ - GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, - &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]); - - /* Enable Hashing. */ - SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); - } - - if ((NewPromMode & SK_PROM_MODE_LLC) && - !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */ - - /* Set the MAC to Promiscuous Mode. */ - SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE); - } - else if ((CurPromMode & SK_PROM_MODE_LLC) && - !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC */ - - /* Clear Promiscuous Mode. */ - SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE); - } - - return (SK_ADDR_SUCCESS); - -} /* SkAddrGmacPromiscuousChange */ - -#endif /* YUKON */ - -#ifndef SK_SLIM - -/****************************************************************************** - * - * SkAddrSwap - swap address info - * - * Description: - * This routine swaps address info of two ports. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_ADDR_SUCCESS - * SK_ADDR_ILLEGAL_PORT - */ -int SkAddrSwap( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 FromPortNumber, /* Port1 Index */ -SK_U32 ToPortNumber) /* Port2 Index */ -{ - int i; - SK_U8 Byte; - SK_MAC_ADDR MacAddr; - SK_U32 DWord; - - if (FromPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { - return (SK_ADDR_ILLEGAL_PORT); - } - - if (ToPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { - return (SK_ADDR_ILLEGAL_PORT); - } - - if (pAC->Rlmt.Port[FromPortNumber].Net != pAC->Rlmt.Port[ToPortNumber].Net) { - return (SK_ADDR_ILLEGAL_PORT); - } - - /* - * Swap: - * - Exact Match Entries (GEnesis and Yukon) - * Yukon uses first entry for the logical MAC - * address (stored in the second GMAC register). - * - FirstExactMatchRlmt (GEnesis only) - * - NextExactMatchRlmt (GEnesis only) - * - FirstExactMatchDrv (GEnesis only) - * - NextExactMatchDrv (GEnesis only) - * - 64-bit filter (InexactFilter) - * - Promiscuous Mode - * of ports. - */ - - for (i = 0; i < SK_ADDR_EXACT_MATCHES; i++) { - MacAddr = pAC->Addr.Port[FromPortNumber].Exact[i]; - pAC->Addr.Port[FromPortNumber].Exact[i] = - pAC->Addr.Port[ToPortNumber].Exact[i]; - pAC->Addr.Port[ToPortNumber].Exact[i] = MacAddr; - } - - for (i = 0; i < 8; i++) { - Byte = pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i]; - pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i] = - pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i]; - pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i] = Byte; - } - - i = pAC->Addr.Port[FromPortNumber].PromMode; - pAC->Addr.Port[FromPortNumber].PromMode = pAC->Addr.Port[ToPortNumber].PromMode; - pAC->Addr.Port[ToPortNumber].PromMode = i; - - if (pAC->GIni.GIGenesis) { - DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt; - pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt = - pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt; - pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt = DWord; - - DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt; - pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt = - pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt; - pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt = DWord; - - DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv; - pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv = - pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv; - pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv = DWord; - - DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchDrv; - pAC->Addr.Port[FromPortNumber].NextExactMatchDrv = - pAC->Addr.Port[ToPortNumber].NextExactMatchDrv; - pAC->Addr.Port[ToPortNumber].NextExactMatchDrv = DWord; - } - - /* CAUTION: Solution works if only ports of one adapter are in use. */ - for (i = 0; (SK_U32) i < pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber]. - Net->NetNumber].NumPorts; i++) { - if (pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber]. - Port[i]->PortNumber == ToPortNumber) { - pAC->Addr.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber]. - ActivePort = i; - /* 20001207 RA: Was "ToPortNumber;". */ - } - } - - (void) SkAddrMcUpdate(pAC, IoC, FromPortNumber); - (void) SkAddrMcUpdate(pAC, IoC, ToPortNumber); - - return (SK_ADDR_SUCCESS); - -} /* SkAddrSwap */ - -#endif /* !SK_SLIM */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - diff --git a/drivers/net/sk98lin/skdim.c b/drivers/net/sk98lin/skdim.c deleted file mode 100644 index 37ce03fb8de..00000000000 --- a/drivers/net/sk98lin/skdim.c +++ /dev/null @@ -1,742 +0,0 @@ -/****************************************************************************** - * - * Name: skdim.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.5 $ - * Date: $Date: 2003/11/28 12:55:40 $ - * Purpose: All functions to maintain interrupt moderation - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This module is intended to manage the dynamic interrupt moderation on both - * GEnesis and Yukon adapters. - * - * Include File Hierarchy: - * - * "skdrv1st.h" - * "skdrv2nd.h" - * - ******************************************************************************/ - -#ifndef lint -static const char SysKonnectFileId[] = - "@(#) $Id: skdim.c,v 1.5 2003/11/28 12:55:40 rroesler Exp $ (C) SysKonnect."; -#endif - -#define __SKADDR_C - -#ifdef __cplusplus -#error C++ is not yet supported. -extern "C" { -#endif - -/******************************************************************************* -** -** Includes -** -*******************************************************************************/ - -#ifndef __INC_SKDRV1ST_H -#include "h/skdrv1st.h" -#endif - -#ifndef __INC_SKDRV2ND_H -#include "h/skdrv2nd.h" -#endif - -#include <linux/kernel_stat.h> - -/******************************************************************************* -** -** Defines -** -*******************************************************************************/ - -/******************************************************************************* -** -** Typedefs -** -*******************************************************************************/ - -/******************************************************************************* -** -** Local function prototypes -** -*******************************************************************************/ - -static unsigned int GetCurrentSystemLoad(SK_AC *pAC); -static SK_U64 GetIsrCalls(SK_AC *pAC); -static SK_BOOL IsIntModEnabled(SK_AC *pAC); -static void SetCurrIntCtr(SK_AC *pAC); -static void EnableIntMod(SK_AC *pAC); -static void DisableIntMod(SK_AC *pAC); -static void ResizeDimTimerDuration(SK_AC *pAC); -static void DisplaySelectedModerationType(SK_AC *pAC); -static void DisplaySelectedModerationMask(SK_AC *pAC); -static void DisplayDescrRatio(SK_AC *pAC); - -/******************************************************************************* -** -** Global variables -** -*******************************************************************************/ - -/******************************************************************************* -** -** Local variables -** -*******************************************************************************/ - -/******************************************************************************* -** -** Global functions -** -*******************************************************************************/ - -/******************************************************************************* -** Function : SkDimModerate -** Description : Called in every ISR to check if moderation is to be applied -** or not for the current number of interrupts -** Programmer : Ralph Roesler -** Last Modified: 22-mar-03 -** Returns : void (!) -** Notes : - -*******************************************************************************/ - -void -SkDimModerate(SK_AC *pAC) { - unsigned int CurrSysLoad = 0; /* expressed in percent */ - unsigned int LoadIncrease = 0; /* expressed in percent */ - SK_U64 ThresholdInts = 0; - SK_U64 IsrCallsPerSec = 0; - -#define M_DIMINFO pAC->DynIrqModInfo - - if (!IsIntModEnabled(pAC)) { - if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) { - CurrSysLoad = GetCurrentSystemLoad(pAC); - if (CurrSysLoad > 75) { - /* - ** More than 75% total system load! Enable the moderation - ** to shield the system against too many interrupts. - */ - EnableIntMod(pAC); - } else if (CurrSysLoad > M_DIMINFO.PrevSysLoad) { - LoadIncrease = (CurrSysLoad - M_DIMINFO.PrevSysLoad); - if (LoadIncrease > ((M_DIMINFO.PrevSysLoad * - C_INT_MOD_ENABLE_PERCENTAGE) / 100)) { - if (CurrSysLoad > 10) { - /* - ** More than 50% increase with respect to the - ** previous load of the system. Most likely this - ** is due to our ISR-proc... - */ - EnableIntMod(pAC); - } - } - } else { - /* - ** Neither too much system load at all nor too much increase - ** with respect to the previous system load. Hence, we can leave - ** the ISR-handling like it is without enabling moderation. - */ - } - M_DIMINFO.PrevSysLoad = CurrSysLoad; - } - } else { - if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) { - ThresholdInts = ((M_DIMINFO.MaxModIntsPerSec * - C_INT_MOD_DISABLE_PERCENTAGE) / 100); - IsrCallsPerSec = GetIsrCalls(pAC); - if (IsrCallsPerSec <= ThresholdInts) { - /* - ** The number of interrupts within the last second is - ** lower than the disable_percentage of the desried - ** maxrate. Therefore we can disable the moderation. - */ - DisableIntMod(pAC); - M_DIMINFO.MaxModIntsPerSec = - (M_DIMINFO.MaxModIntsPerSecUpperLimit + - M_DIMINFO.MaxModIntsPerSecLowerLimit) / 2; - } else { - /* - ** The number of interrupts per sec is the same as expected. - ** Evalulate the descriptor-ratio. If it has changed, a resize - ** in the moderation timer might be useful - */ - if (M_DIMINFO.AutoSizing) { - ResizeDimTimerDuration(pAC); - } - } - } - } - - /* - ** Some information to the log... - */ - if (M_DIMINFO.DisplayStats) { - DisplaySelectedModerationType(pAC); - DisplaySelectedModerationMask(pAC); - DisplayDescrRatio(pAC); - } - - M_DIMINFO.NbrProcessedDescr = 0; - SetCurrIntCtr(pAC); -} - -/******************************************************************************* -** Function : SkDimStartModerationTimer -** Description : Starts the audit-timer for the dynamic interrupt moderation -** Programmer : Ralph Roesler -** Last Modified: 22-mar-03 -** Returns : void (!) -** Notes : - -*******************************************************************************/ - -void -SkDimStartModerationTimer(SK_AC *pAC) { - SK_EVPARA EventParam; /* Event struct for timer event */ - - SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam)); - EventParam.Para32[0] = SK_DRV_MODERATION_TIMER; - SkTimerStart(pAC, pAC->IoBase, &pAC->DynIrqModInfo.ModTimer, - SK_DRV_MODERATION_TIMER_LENGTH, - SKGE_DRV, SK_DRV_TIMER, EventParam); -} - -/******************************************************************************* -** Function : SkDimEnableModerationIfNeeded -** Description : Either enables or disables moderation -** Programmer : Ralph Roesler -** Last Modified: 22-mar-03 -** Returns : void (!) -** Notes : This function is called when a particular adapter is opened -** There is no Disable function, because when all interrupts -** might be disable, the moderation timer has no meaning at all -******************************************************************************/ - -void -SkDimEnableModerationIfNeeded(SK_AC *pAC) { - - if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_STATIC) { - EnableIntMod(pAC); /* notification print in this function */ - } else if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) { - SkDimStartModerationTimer(pAC); - if (M_DIMINFO.DisplayStats) { - printk("Dynamic moderation has been enabled\n"); - } - } else { - if (M_DIMINFO.DisplayStats) { - printk("No moderation has been enabled\n"); - } - } -} - -/******************************************************************************* -** Function : SkDimDisplayModerationSettings -** Description : Displays the current settings regarding interrupt moderation -** Programmer : Ralph Roesler -** Last Modified: 22-mar-03 -** Returns : void (!) -** Notes : - -*******************************************************************************/ - -void -SkDimDisplayModerationSettings(SK_AC *pAC) { - DisplaySelectedModerationType(pAC); - DisplaySelectedModerationMask(pAC); -} - -/******************************************************************************* -** -** Local functions -** -*******************************************************************************/ - -/******************************************************************************* -** Function : GetCurrentSystemLoad -** Description : Retrieves the current system load of the system. This load -** is evaluated for all processors within the system. -** Programmer : Ralph Roesler -** Last Modified: 22-mar-03 -** Returns : unsigned int: load expressed in percentage -** Notes : The possible range being returned is from 0 up to 100. -** Whereas 0 means 'no load at all' and 100 'system fully loaded' -** It is impossible to determine what actually causes the system -** to be in 100%, but maybe that is due to too much interrupts. -*******************************************************************************/ - -static unsigned int -GetCurrentSystemLoad(SK_AC *pAC) { - unsigned long jif = jiffies; - unsigned int UserTime = 0; - unsigned int SystemTime = 0; - unsigned int NiceTime = 0; - unsigned int IdleTime = 0; - unsigned int TotalTime = 0; - unsigned int UsedTime = 0; - unsigned int SystemLoad = 0; - - /* unsigned int NbrCpu = 0; */ - - /* - ** The following lines have been commented out, because - ** from kernel 2.5.44 onwards, the kernel-owned structure - ** - ** struct kernel_stat kstat - ** - ** is not marked as an exported symbol in the file - ** - ** kernel/ksyms.c - ** - ** As a consequence, using this driver as KLM is not possible - ** and any access of the structure kernel_stat via the - ** dedicated macros kstat_cpu(i).cpustat.xxx is to be avoided. - ** - ** The kstat-information might be added again in future - ** versions of the 2.5.xx kernel, but for the time being, - ** number of interrupts will serve as indication how much - ** load we currently have... - ** - ** for (NbrCpu = 0; NbrCpu < num_online_cpus(); NbrCpu++) { - ** UserTime = UserTime + kstat_cpu(NbrCpu).cpustat.user; - ** NiceTime = NiceTime + kstat_cpu(NbrCpu).cpustat.nice; - ** SystemTime = SystemTime + kstat_cpu(NbrCpu).cpustat.system; - ** } - */ - SK_U64 ThresholdInts = 0; - SK_U64 IsrCallsPerSec = 0; - - ThresholdInts = ((M_DIMINFO.MaxModIntsPerSec * - C_INT_MOD_ENABLE_PERCENTAGE) + 100); - IsrCallsPerSec = GetIsrCalls(pAC); - if (IsrCallsPerSec >= ThresholdInts) { - /* - ** We do not know how much the real CPU-load is! - ** Return 80% as a default in order to activate DIM - */ - SystemLoad = 80; - return (SystemLoad); - } - - UsedTime = UserTime + NiceTime + SystemTime; - - IdleTime = jif * num_online_cpus() - UsedTime; - TotalTime = UsedTime + IdleTime; - - SystemLoad = ( 100 * (UsedTime - M_DIMINFO.PrevUsedTime) ) / - (TotalTime - M_DIMINFO.PrevTotalTime); - - if (M_DIMINFO.DisplayStats) { - printk("Current system load is: %u\n", SystemLoad); - } - - M_DIMINFO.PrevTotalTime = TotalTime; - M_DIMINFO.PrevUsedTime = UsedTime; - - return (SystemLoad); -} - -/******************************************************************************* -** Function : GetIsrCalls -** Description : Depending on the selected moderation mask, this function will -** return the number of interrupts handled in the previous time- -** frame. This evaluated number is based on the current number -** of interrupts stored in PNMI-context and the previous stored -** interrupts. -** Programmer : Ralph Roesler -** Last Modified: 23-mar-03 -** Returns : int: the number of interrupts being executed in the last -** timeframe -** Notes : It makes only sense to call this function, when dynamic -** interrupt moderation is applied -*******************************************************************************/ - -static SK_U64 -GetIsrCalls(SK_AC *pAC) { - SK_U64 RxPort0IntDiff = 0; - SK_U64 RxPort1IntDiff = 0; - SK_U64 TxPort0IntDiff = 0; - SK_U64 TxPort1IntDiff = 0; - - if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_TX_ONLY) { - if (pAC->GIni.GIMacsFound == 2) { - TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts - - pAC->DynIrqModInfo.PrevPort1TxIntrCts; - } - TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts - - pAC->DynIrqModInfo.PrevPort0TxIntrCts; - } else if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_RX_ONLY) { - if (pAC->GIni.GIMacsFound == 2) { - RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts - - pAC->DynIrqModInfo.PrevPort1RxIntrCts; - } - RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - - pAC->DynIrqModInfo.PrevPort0RxIntrCts; - } else { - if (pAC->GIni.GIMacsFound == 2) { - RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts - - pAC->DynIrqModInfo.PrevPort1RxIntrCts; - TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts - - pAC->DynIrqModInfo.PrevPort1TxIntrCts; - } - RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - - pAC->DynIrqModInfo.PrevPort0RxIntrCts; - TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts - - pAC->DynIrqModInfo.PrevPort0TxIntrCts; - } - - return (RxPort0IntDiff + RxPort1IntDiff + TxPort0IntDiff + TxPort1IntDiff); -} - -/******************************************************************************* -** Function : GetRxCalls -** Description : This function will return the number of times a receive inter- -** rupt was processed. This is needed to evaluate any resizing -** factor. -** Programmer : Ralph Roesler -** Last Modified: 23-mar-03 -** Returns : SK_U64: the number of RX-ints being processed -** Notes : It makes only sense to call this function, when dynamic -** interrupt moderation is applied -*******************************************************************************/ - -static SK_U64 -GetRxCalls(SK_AC *pAC) { - SK_U64 RxPort0IntDiff = 0; - SK_U64 RxPort1IntDiff = 0; - - if (pAC->GIni.GIMacsFound == 2) { - RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts - - pAC->DynIrqModInfo.PrevPort1RxIntrCts; - } - RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - - pAC->DynIrqModInfo.PrevPort0RxIntrCts; - - return (RxPort0IntDiff + RxPort1IntDiff); -} - -/******************************************************************************* -** Function : SetCurrIntCtr -** Description : Will store the current number orf occured interrupts in the -** adapter context. This is needed to evaluated the number of -** interrupts within a current timeframe. -** Programmer : Ralph Roesler -** Last Modified: 23-mar-03 -** Returns : void (!) -** Notes : - -*******************************************************************************/ - -static void -SetCurrIntCtr(SK_AC *pAC) { - if (pAC->GIni.GIMacsFound == 2) { - pAC->DynIrqModInfo.PrevPort1RxIntrCts = pAC->Pnmi.Port[1].RxIntrCts; - pAC->DynIrqModInfo.PrevPort1TxIntrCts = pAC->Pnmi.Port[1].TxIntrCts; - } - pAC->DynIrqModInfo.PrevPort0RxIntrCts = pAC->Pnmi.Port[0].RxIntrCts; - pAC->DynIrqModInfo.PrevPort0TxIntrCts = pAC->Pnmi.Port[0].TxIntrCts; -} - -/******************************************************************************* -** Function : IsIntModEnabled() -** Description : Retrieves the current value of the interrupts moderation -** command register. Its content determines whether any -** moderation is running or not. -** Programmer : Ralph Roesler -** Last Modified: 23-mar-03 -** Returns : SK_TRUE : if mod timer running -** SK_FALSE : if no moderation is being performed -** Notes : - -*******************************************************************************/ - -static SK_BOOL -IsIntModEnabled(SK_AC *pAC) { - unsigned long CtrCmd; - - SK_IN32(pAC->IoBase, B2_IRQM_CTRL, &CtrCmd); - if ((CtrCmd & TIM_START) == TIM_START) { - return SK_TRUE; - } else { - return SK_FALSE; - } -} - -/******************************************************************************* -** Function : EnableIntMod() -** Description : Enables the interrupt moderation using the values stored in -** in the pAC->DynIntMod data structure -** Programmer : Ralph Roesler -** Last Modified: 22-mar-03 -** Returns : - -** Notes : - -*******************************************************************************/ - -static void -EnableIntMod(SK_AC *pAC) { - unsigned long ModBase; - - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { - ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec; - } else { - ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec; - } - - SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase); - SK_OUT32(pAC->IoBase, B2_IRQM_MSK, pAC->DynIrqModInfo.MaskIrqModeration); - SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START); - if (M_DIMINFO.DisplayStats) { - printk("Enabled interrupt moderation (%i ints/sec)\n", - M_DIMINFO.MaxModIntsPerSec); - } -} - -/******************************************************************************* -** Function : DisableIntMod() -** Description : Disables the interrupt moderation independent of what inter- -** rupts are running or not -** Programmer : Ralph Roesler -** Last Modified: 23-mar-03 -** Returns : - -** Notes : - -*******************************************************************************/ - -static void -DisableIntMod(SK_AC *pAC) { - - SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_STOP); - if (M_DIMINFO.DisplayStats) { - printk("Disabled interrupt moderation\n"); - } -} - -/******************************************************************************* -** Function : ResizeDimTimerDuration(); -** Description : Checks the current used descriptor ratio and resizes the -** duration timer (longer/smaller) if possible. -** Programmer : Ralph Roesler -** Last Modified: 23-mar-03 -** Returns : - -** Notes : There are both maximum and minimum timer duration value. -** This function assumes that interrupt moderation is already -** enabled! -*******************************************************************************/ - -static void -ResizeDimTimerDuration(SK_AC *pAC) { - SK_BOOL IncreaseTimerDuration; - int TotalMaxNbrDescr; - int UsedDescrRatio; - int RatioDiffAbs; - int RatioDiffRel; - int NewMaxModIntsPerSec; - int ModAdjValue; - long ModBase; - - /* - ** Check first if we are allowed to perform any modification - */ - if (IsIntModEnabled(pAC)) { - if (M_DIMINFO.IntModTypeSelect != C_INT_MOD_DYNAMIC) { - return; - } else { - if (M_DIMINFO.ModJustEnabled) { - M_DIMINFO.ModJustEnabled = SK_FALSE; - return; - } - } - } - - /* - ** If we got until here, we have to evaluate the amount of the - ** descriptor ratio change... - */ - TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC); - UsedDescrRatio = (M_DIMINFO.NbrProcessedDescr * 100) / TotalMaxNbrDescr; - - if (UsedDescrRatio > M_DIMINFO.PrevUsedDescrRatio) { - RatioDiffAbs = (UsedDescrRatio - M_DIMINFO.PrevUsedDescrRatio); - RatioDiffRel = (RatioDiffAbs * 100) / UsedDescrRatio; - M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio; - IncreaseTimerDuration = SK_FALSE; /* in other words: DECREASE */ - } else if (UsedDescrRatio < M_DIMINFO.PrevUsedDescrRatio) { - RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio); - RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio; - M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio; - IncreaseTimerDuration = SK_TRUE; /* in other words: INCREASE */ - } else { - RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio); - RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio; - M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio; - IncreaseTimerDuration = SK_TRUE; /* in other words: INCREASE */ - } - - /* - ** Now we can determine the change in percent - */ - if ((RatioDiffRel >= 0) && (RatioDiffRel <= 5) ) { - ModAdjValue = 1; /* 1% change - maybe some other value in future */ - } else if ((RatioDiffRel > 5) && (RatioDiffRel <= 10) ) { - ModAdjValue = 1; /* 1% change - maybe some other value in future */ - } else if ((RatioDiffRel > 10) && (RatioDiffRel <= 15) ) { - ModAdjValue = 1; /* 1% change - maybe some other value in future */ - } else { - ModAdjValue = 1; /* 1% change - maybe some other value in future */ - } - - if (IncreaseTimerDuration) { - NewMaxModIntsPerSec = M_DIMINFO.MaxModIntsPerSec + - (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100; - } else { - NewMaxModIntsPerSec = M_DIMINFO.MaxModIntsPerSec - - (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100; - } - - /* - ** Check if we exceed boundaries... - */ - if ( (NewMaxModIntsPerSec > M_DIMINFO.MaxModIntsPerSecUpperLimit) || - (NewMaxModIntsPerSec < M_DIMINFO.MaxModIntsPerSecLowerLimit)) { - if (M_DIMINFO.DisplayStats) { - printk("Cannot change ModTim from %i to %i ints/sec\n", - M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec); - } - return; - } else { - if (M_DIMINFO.DisplayStats) { - printk("Resized ModTim from %i to %i ints/sec\n", - M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec); - } - } - - M_DIMINFO.MaxModIntsPerSec = NewMaxModIntsPerSec; - - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { - ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec; - } else { - ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec; - } - - /* - ** We do not need to touch any other registers - */ - SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase); -} - -/******************************************************************************* -** Function : DisplaySelectedModerationType() -** Description : Displays what type of moderation we have -** Programmer : Ralph Roesler -** Last Modified: 23-mar-03 -** Returns : void! -** Notes : - -*******************************************************************************/ - -static void -DisplaySelectedModerationType(SK_AC *pAC) { - - if (pAC->DynIrqModInfo.DisplayStats) { - if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC) { - printk("Static int moderation runs with %i INTS/sec\n", - pAC->DynIrqModInfo.MaxModIntsPerSec); - } else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC) { - if (IsIntModEnabled(pAC)) { - printk("Dynamic int moderation runs with %i INTS/sec\n", - pAC->DynIrqModInfo.MaxModIntsPerSec); - } else { - printk("Dynamic int moderation currently not applied\n"); - } - } else { - printk("No interrupt moderation selected!\n"); - } - } -} - -/******************************************************************************* -** Function : DisplaySelectedModerationMask() -** Description : Displays what interrupts are moderated -** Programmer : Ralph Roesler -** Last Modified: 23-mar-03 -** Returns : void! -** Notes : - -*******************************************************************************/ - -static void -DisplaySelectedModerationMask(SK_AC *pAC) { - - if (pAC->DynIrqModInfo.DisplayStats) { - if (pAC->DynIrqModInfo.IntModTypeSelect != C_INT_MOD_NONE) { - switch (pAC->DynIrqModInfo.MaskIrqModeration) { - case IRQ_MASK_TX_ONLY: - printk("Only Tx-interrupts are moderated\n"); - break; - case IRQ_MASK_RX_ONLY: - printk("Only Rx-interrupts are moderated\n"); - break; - case IRQ_MASK_SP_ONLY: - printk("Only special-interrupts are moderated\n"); - break; - case IRQ_MASK_TX_RX: - printk("Tx- and Rx-interrupts are moderated\n"); - break; - case IRQ_MASK_SP_RX: - printk("Special- and Rx-interrupts are moderated\n"); - break; - case IRQ_MASK_SP_TX: - printk("Special- and Tx-interrupts are moderated\n"); - break; - case IRQ_MASK_RX_TX_SP: - printk("All Rx-, Tx and special-interrupts are moderated\n"); - break; - default: - printk("Don't know what is moderated\n"); - break; - } - } else { - printk("No specific interrupts masked for moderation\n"); - } - } -} - -/******************************************************************************* -** Function : DisplayDescrRatio -** Description : Like the name states... -** Programmer : Ralph Roesler -** Last Modified: 23-mar-03 -** Returns : void! -** Notes : - -*******************************************************************************/ - -static void -DisplayDescrRatio(SK_AC *pAC) { - int TotalMaxNbrDescr = 0; - - if (pAC->DynIrqModInfo.DisplayStats) { - TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC); - printk("Ratio descriptors: %i/%i\n", - M_DIMINFO.NbrProcessedDescr, TotalMaxNbrDescr); - } -} - -/******************************************************************************* -** -** End of file -** -*******************************************************************************/ diff --git a/drivers/net/sk98lin/skethtool.c b/drivers/net/sk98lin/skethtool.c deleted file mode 100644 index 36460694eb8..00000000000 --- a/drivers/net/sk98lin/skethtool.c +++ /dev/null @@ -1,628 +0,0 @@ -/****************************************************************************** - * - * Name: skethtool.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.7 $ - * Date: $Date: 2004/09/29 13:32:07 $ - * Purpose: All functions regarding ethtool handling - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2004 Marvell. - * - * Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet - * Server Adapters. - * - * Author: Ralph Roesler (rroesler@syskonnect.de) - * Mirko Lindner (mlindner@syskonnect.de) - * - * Address all question to: linux@syskonnect.de - * - * The technical manual for the adapters is available from SysKonnect's - * web pages: www.syskonnect.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - *****************************************************************************/ - -#include "h/skdrv1st.h" -#include "h/skdrv2nd.h" -#include "h/skversion.h" - -#include <linux/ethtool.h> -#include <linux/timer.h> -#include <linux/delay.h> - -/****************************************************************************** - * - * Defines - * - *****************************************************************************/ - -#define SUPP_COPPER_ALL (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \ - SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \ - SUPPORTED_1000baseT_Half| SUPPORTED_1000baseT_Full| \ - SUPPORTED_TP) - -#define ADV_COPPER_ALL (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \ - ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \ - ADVERTISED_1000baseT_Half| ADVERTISED_1000baseT_Full| \ - ADVERTISED_TP) - -#define SUPP_FIBRE_ALL (SUPPORTED_1000baseT_Full | \ - SUPPORTED_FIBRE | \ - SUPPORTED_Autoneg) - -#define ADV_FIBRE_ALL (ADVERTISED_1000baseT_Full | \ - ADVERTISED_FIBRE | \ - ADVERTISED_Autoneg) - - -/****************************************************************************** - * - * Local Functions - * - *****************************************************************************/ - -/***************************************************************************** - * - * getSettings - retrieves the current settings of the selected adapter - * - * Description: - * The current configuration of the selected adapter is returned. - * This configuration involves a)speed, b)duplex and c)autoneg plus - * a number of other variables. - * - * Returns: always 0 - * - */ -static int getSettings(struct net_device *dev, struct ethtool_cmd *ecmd) -{ - const DEV_NET *pNet = netdev_priv(dev); - int port = pNet->PortNr; - const SK_AC *pAC = pNet->pAC; - const SK_GEPORT *pPort = &pAC->GIni.GP[port]; - - static int DuplexAutoNegConfMap[9][3]= { - { -1 , -1 , -1 }, - { 0 , -1 , -1 }, - { SK_LMODE_HALF , DUPLEX_HALF, AUTONEG_DISABLE }, - { SK_LMODE_FULL , DUPLEX_FULL, AUTONEG_DISABLE }, - { SK_LMODE_AUTOHALF , DUPLEX_HALF, AUTONEG_ENABLE }, - { SK_LMODE_AUTOFULL , DUPLEX_FULL, AUTONEG_ENABLE }, - { SK_LMODE_AUTOBOTH , DUPLEX_FULL, AUTONEG_ENABLE }, - { SK_LMODE_AUTOSENSE , -1 , -1 }, - { SK_LMODE_INDETERMINATED, -1 , -1 } - }; - static int SpeedConfMap[6][2] = { - { 0 , -1 }, - { SK_LSPEED_AUTO , -1 }, - { SK_LSPEED_10MBPS , SPEED_10 }, - { SK_LSPEED_100MBPS , SPEED_100 }, - { SK_LSPEED_1000MBPS , SPEED_1000 }, - { SK_LSPEED_INDETERMINATED, -1 } - }; - static int AdvSpeedMap[6][2] = { - { 0 , -1 }, - { SK_LSPEED_AUTO , -1 }, - { SK_LSPEED_10MBPS , ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full }, - { SK_LSPEED_100MBPS , ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full }, - { SK_LSPEED_1000MBPS , ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full}, - { SK_LSPEED_INDETERMINATED, -1 } - }; - - ecmd->phy_address = port; - ecmd->speed = SpeedConfMap[pPort->PLinkSpeedUsed][1]; - ecmd->duplex = DuplexAutoNegConfMap[pPort->PLinkModeStatus][1]; - ecmd->autoneg = DuplexAutoNegConfMap[pPort->PLinkModeStatus][2]; - ecmd->transceiver = XCVR_INTERNAL; - - if (pAC->GIni.GICopperType) { - ecmd->port = PORT_TP; - ecmd->supported = (SUPP_COPPER_ALL|SUPPORTED_Autoneg); - if (pAC->GIni.GIGenesis) { - ecmd->supported &= ~(SUPPORTED_10baseT_Half); - ecmd->supported &= ~(SUPPORTED_10baseT_Full); - ecmd->supported &= ~(SUPPORTED_100baseT_Half); - ecmd->supported &= ~(SUPPORTED_100baseT_Full); - } else { - if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { - ecmd->supported &= ~(SUPPORTED_1000baseT_Half); - } -#ifdef CHIP_ID_YUKON_FE - if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) { - ecmd->supported &= ~(SUPPORTED_1000baseT_Half); - ecmd->supported &= ~(SUPPORTED_1000baseT_Full); - } -#endif - } - if (pAC->GIni.GP[0].PLinkSpeed != SK_LSPEED_AUTO) { - ecmd->advertising = AdvSpeedMap[pPort->PLinkSpeed][1]; - if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { - ecmd->advertising &= ~(SUPPORTED_1000baseT_Half); - } - } else { - ecmd->advertising = ecmd->supported; - } - - if (ecmd->autoneg == AUTONEG_ENABLE) - ecmd->advertising |= ADVERTISED_Autoneg; - } else { - ecmd->port = PORT_FIBRE; - ecmd->supported = SUPP_FIBRE_ALL; - ecmd->advertising = ADV_FIBRE_ALL; - } - return 0; -} - -/* - * MIB infrastructure uses instance value starting at 1 - * based on board and port. - */ -static inline u32 pnmiInstance(const DEV_NET *pNet) -{ - return 1 + (pNet->pAC->RlmtNets == 2) + pNet->PortNr; -} - -/***************************************************************************** - * - * setSettings - configures the settings of a selected adapter - * - * Description: - * Possible settings that may be altered are a)speed, b)duplex or - * c)autonegotiation. - * - * Returns: - * 0: everything fine, no error - * <0: the return value is the error code of the failure - */ -static int setSettings(struct net_device *dev, struct ethtool_cmd *ecmd) -{ - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - u32 instance; - char buf[4]; - int len = 1; - - if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100 - && ecmd->speed != SPEED_1000) - return -EINVAL; - - if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL) - return -EINVAL; - - if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE) - return -EINVAL; - - if (ecmd->autoneg == AUTONEG_DISABLE) - *buf = (ecmd->duplex == DUPLEX_FULL) - ? SK_LMODE_FULL : SK_LMODE_HALF; - else - *buf = (ecmd->duplex == DUPLEX_FULL) - ? SK_LMODE_AUTOFULL : SK_LMODE_AUTOHALF; - - instance = pnmiInstance(pNet); - if (SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_LINK_MODE, - &buf, &len, instance, pNet->NetNr) != SK_PNMI_ERR_OK) - return -EINVAL; - - switch(ecmd->speed) { - case SPEED_1000: - *buf = SK_LSPEED_1000MBPS; - break; - case SPEED_100: - *buf = SK_LSPEED_100MBPS; - break; - case SPEED_10: - *buf = SK_LSPEED_10MBPS; - } - - if (SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE, - &buf, &len, instance, pNet->NetNr) != SK_PNMI_ERR_OK) - return -EINVAL; - - return 0; -} - -/***************************************************************************** - * - * getDriverInfo - returns generic driver and adapter information - * - * Description: - * Generic driver information is returned via this function, such as - * the name of the driver, its version and and firmware version. - * In addition to this, the location of the selected adapter is - * returned as a bus info string (e.g. '01:05.0'). - * - * Returns: N/A - * - */ -static void getDriverInfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - const DEV_NET *pNet = netdev_priv(dev); - const SK_AC *pAC = pNet->pAC; - char vers[32]; - - snprintf(vers, sizeof(vers)-1, VER_STRING "(v%d.%d)", - (pAC->GIni.GIPciHwRev >> 4) & 0xf, pAC->GIni.GIPciHwRev & 0xf); - - strlcpy(info->driver, DRIVER_FILE_NAME, sizeof(info->driver)); - strcpy(info->version, vers); - strcpy(info->fw_version, "N/A"); - strlcpy(info->bus_info, pci_name(pAC->PciDev), ETHTOOL_BUSINFO_LEN); -} - -/* - * Ethtool statistics support. - */ -static const char StringsStats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", - "rx_bytes", "tx_bytes", - "rx_errors", "tx_errors", - "rx_dropped", "tx_dropped", - "multicasts", "collisions", - "rx_length_errors", "rx_buffer_overflow_errors", - "rx_crc_errors", "rx_frame_errors", - "rx_too_short_errors", "rx_too_long_errors", - "rx_carrier_extension_errors", "rx_symbol_errors", - "rx_llc_mac_size_errors", "rx_carrier_errors", - "rx_jabber_errors", "rx_missed_errors", - "tx_abort_collision_errors", "tx_carrier_errors", - "tx_buffer_underrun_errors", "tx_heartbeat_errors", - "tx_window_errors", -}; - -static int getStatsCount(struct net_device *dev) -{ - return ARRAY_SIZE(StringsStats); -} - -static void getStrings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *StringsStats, sizeof(StringsStats)); - break; - } -} - -static void getEthtoolStats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - const DEV_NET *pNet = netdev_priv(dev); - const SK_AC *pAC = pNet->pAC; - const SK_PNMI_STRUCT_DATA *pPnmiStruct = &pAC->PnmiStruct; - - *data++ = pPnmiStruct->Stat[0].StatRxOkCts; - *data++ = pPnmiStruct->Stat[0].StatTxOkCts; - *data++ = pPnmiStruct->Stat[0].StatRxOctetsOkCts; - *data++ = pPnmiStruct->Stat[0].StatTxOctetsOkCts; - *data++ = pPnmiStruct->InErrorsCts; - *data++ = pPnmiStruct->Stat[0].StatTxSingleCollisionCts; - *data++ = pPnmiStruct->RxNoBufCts; - *data++ = pPnmiStruct->TxNoBufCts; - *data++ = pPnmiStruct->Stat[0].StatRxMulticastOkCts; - *data++ = pPnmiStruct->Stat[0].StatTxSingleCollisionCts; - *data++ = pPnmiStruct->Stat[0].StatRxRuntCts; - *data++ = pPnmiStruct->Stat[0].StatRxFifoOverflowCts; - *data++ = pPnmiStruct->Stat[0].StatRxFcsCts; - *data++ = pPnmiStruct->Stat[0].StatRxFramingCts; - *data++ = pPnmiStruct->Stat[0].StatRxShortsCts; - *data++ = pPnmiStruct->Stat[0].StatRxTooLongCts; - *data++ = pPnmiStruct->Stat[0].StatRxCextCts; - *data++ = pPnmiStruct->Stat[0].StatRxSymbolCts; - *data++ = pPnmiStruct->Stat[0].StatRxIRLengthCts; - *data++ = pPnmiStruct->Stat[0].StatRxCarrierCts; - *data++ = pPnmiStruct->Stat[0].StatRxJabberCts; - *data++ = pPnmiStruct->Stat[0].StatRxMissedCts; - *data++ = pAC->stats.tx_aborted_errors; - *data++ = pPnmiStruct->Stat[0].StatTxCarrierCts; - *data++ = pPnmiStruct->Stat[0].StatTxFifoUnderrunCts; - *data++ = pPnmiStruct->Stat[0].StatTxCarrierCts; - *data++ = pAC->stats.tx_window_errors; -} - - -/***************************************************************************** - * - * toggleLeds - Changes the LED state of an adapter - * - * Description: - * This function changes the current state of all LEDs of an adapter so - * that it can be located by a user. - * - * Returns: N/A - * - */ -static void toggleLeds(DEV_NET *pNet, int on) -{ - SK_AC *pAC = pNet->pAC; - int port = pNet->PortNr; - void __iomem *io = pAC->IoBase; - - if (pAC->GIni.GIGenesis) { - SK_OUT8(io, MR_ADDR(port,LNK_LED_REG), - on ? SK_LNK_ON : SK_LNK_OFF); - SkGeYellowLED(pAC, io, - on ? (LED_ON >> 1) : (LED_OFF >> 1)); - SkGeXmitLED(pAC, io, MR_ADDR(port,RX_LED_INI), - on ? SK_LED_TST : SK_LED_DIS); - - if (pAC->GIni.GP[port].PhyType == SK_PHY_BCOM) - SkXmPhyWrite(pAC, io, port, PHY_BCOM_P_EXT_CTRL, - on ? PHY_B_PEC_LED_ON : PHY_B_PEC_LED_OFF); - else if (pAC->GIni.GP[port].PhyType == SK_PHY_LONE) - SkXmPhyWrite(pAC, io, port, PHY_LONE_LED_CFG, - on ? 0x0800 : PHY_L_LC_LEDT); - else - SkGeXmitLED(pAC, io, MR_ADDR(port,TX_LED_INI), - on ? SK_LED_TST : SK_LED_DIS); - } else { - const u16 YukLedOn = (PHY_M_LED_MO_DUP(MO_LED_ON) | - PHY_M_LED_MO_10(MO_LED_ON) | - PHY_M_LED_MO_100(MO_LED_ON) | - PHY_M_LED_MO_1000(MO_LED_ON) | - PHY_M_LED_MO_RX(MO_LED_ON)); - const u16 YukLedOff = (PHY_M_LED_MO_DUP(MO_LED_OFF) | - PHY_M_LED_MO_10(MO_LED_OFF) | - PHY_M_LED_MO_100(MO_LED_OFF) | - PHY_M_LED_MO_1000(MO_LED_OFF) | - PHY_M_LED_MO_RX(MO_LED_OFF)); - - - SkGmPhyWrite(pAC,io,port,PHY_MARV_LED_CTRL,0); - SkGmPhyWrite(pAC,io,port,PHY_MARV_LED_OVER, - on ? YukLedOn : YukLedOff); - } -} - -/***************************************************************************** - * - * skGeBlinkTimer - Changes the LED state of an adapter - * - * Description: - * This function changes the current state of all LEDs of an adapter so - * that it can be located by a user. If the requested time interval for - * this test has elapsed, this function cleans up everything that was - * temporarily setup during the locate NIC test. This involves of course - * also closing or opening any adapter so that the initial board state - * is recovered. - * - * Returns: N/A - * - */ -void SkGeBlinkTimer(unsigned long data) -{ - struct net_device *dev = (struct net_device *) data; - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - - toggleLeds(pNet, pAC->LedsOn); - - pAC->LedsOn = !pAC->LedsOn; - mod_timer(&pAC->BlinkTimer, jiffies + HZ/4); -} - -/***************************************************************************** - * - * locateDevice - start the locate NIC feature of the elected adapter - * - * Description: - * This function is used if the user want to locate a particular NIC. - * All LEDs are regularly switched on and off, so the NIC can easily - * be identified. - * - * Returns: - * ==0: everything fine, no error, locateNIC test was started - * !=0: one locateNIC test runs already - * - */ -static int locateDevice(struct net_device *dev, u32 data) -{ - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - - if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - - /* start blinking */ - pAC->LedsOn = 0; - mod_timer(&pAC->BlinkTimer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&pAC->BlinkTimer); - toggleLeds(pNet, 0); - - return 0; -} - -/***************************************************************************** - * - * getPauseParams - retrieves the pause parameters - * - * Description: - * All current pause parameters of a selected adapter are placed - * in the passed ethtool_pauseparam structure and are returned. - * - * Returns: N/A - * - */ -static void getPauseParams(struct net_device *dev, struct ethtool_pauseparam *epause) -{ - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - SK_GEPORT *pPort = &pAC->GIni.GP[pNet->PortNr]; - - epause->rx_pause = (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC) || - (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM); - - epause->tx_pause = epause->rx_pause || (pPort->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND); - epause->autoneg = epause->rx_pause || epause->tx_pause; -} - -/***************************************************************************** - * - * setPauseParams - configures the pause parameters of an adapter - * - * Description: - * This function sets the Rx or Tx pause parameters - * - * Returns: - * ==0: everything fine, no error - * !=0: the return value is the error code of the failure - */ -static int setPauseParams(struct net_device *dev , struct ethtool_pauseparam *epause) -{ - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - SK_GEPORT *pPort = &pAC->GIni.GP[pNet->PortNr]; - u32 instance = pnmiInstance(pNet); - struct ethtool_pauseparam old; - u8 oldspeed = pPort->PLinkSpeedUsed; - char buf[4]; - int len = 1; - int ret; - - /* - ** we have to determine the current settings to see if - ** the operator requested any modification of the flow - ** control parameters... - */ - getPauseParams(dev, &old); - - /* - ** perform modifications regarding the changes - ** requested by the operator - */ - if (epause->autoneg != old.autoneg) - *buf = epause->autoneg ? SK_FLOW_MODE_NONE : SK_FLOW_MODE_SYMMETRIC; - else { - if (epause->rx_pause && epause->tx_pause) - *buf = SK_FLOW_MODE_SYMMETRIC; - else if (epause->rx_pause && !epause->tx_pause) - *buf = SK_FLOW_MODE_SYM_OR_REM; - else if (!epause->rx_pause && epause->tx_pause) - *buf = SK_FLOW_MODE_LOC_SEND; - else - *buf = SK_FLOW_MODE_NONE; - } - - ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_FLOWCTRL_MODE, - &buf, &len, instance, pNet->NetNr); - - if (ret != SK_PNMI_ERR_OK) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL, - ("ethtool (sk98lin): error changing rx/tx pause (%i)\n", ret)); - goto err; - } - - /* - ** It may be that autoneg has been disabled! Therefore - ** set the speed to the previously used value... - */ - if (!epause->autoneg) { - len = 1; - ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE, - &oldspeed, &len, instance, pNet->NetNr); - if (ret != SK_PNMI_ERR_OK) - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL, - ("ethtool (sk98lin): error setting speed (%i)\n", ret)); - } - err: - return ret ? -EIO : 0; -} - -/* Only Yukon supports checksum offload. */ -static int setScatterGather(struct net_device *dev, u32 data) -{ - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) - return -EOPNOTSUPP; - return ethtool_op_set_sg(dev, data); -} - -static int setTxCsum(struct net_device *dev, u32 data) -{ - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) - return -EOPNOTSUPP; - - return ethtool_op_set_tx_csum(dev, data); -} - -static u32 getRxCsum(struct net_device *dev) -{ - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - - return pAC->RxPort[pNet->PortNr].RxCsum; -} - -static int setRxCsum(struct net_device *dev, u32 data) -{ - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) - return -EOPNOTSUPP; - - pAC->RxPort[pNet->PortNr].RxCsum = data != 0; - return 0; -} - -static int getRegsLen(struct net_device *dev) -{ - return 0x4000; -} - -/* - * Returns copy of whole control register region - * Note: skip RAM address register because accessing it will - * cause bus hangs! - */ -static void getRegs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - DEV_NET *pNet = netdev_priv(dev); - const void __iomem *io = pNet->pAC->IoBase; - - regs->version = 1; - memset(p, 0, regs->len); - memcpy_fromio(p, io, B3_RAM_ADDR); - - memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1, - regs->len - B3_RI_WTO_R1); -} - -const struct ethtool_ops SkGeEthtoolOps = { - .get_settings = getSettings, - .set_settings = setSettings, - .get_drvinfo = getDriverInfo, - .get_strings = getStrings, - .get_stats_count = getStatsCount, - .get_ethtool_stats = getEthtoolStats, - .phys_id = locateDevice, - .get_pauseparam = getPauseParams, - .set_pauseparam = setPauseParams, - .get_link = ethtool_op_get_link, - .get_perm_addr = ethtool_op_get_perm_addr, - .get_sg = ethtool_op_get_sg, - .set_sg = setScatterGather, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = setTxCsum, - .get_rx_csum = getRxCsum, - .set_rx_csum = setRxCsum, - .get_regs = getRegs, - .get_regs_len = getRegsLen, -}; diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c deleted file mode 100644 index bf218621db1..00000000000 --- a/drivers/net/sk98lin/skge.c +++ /dev/null @@ -1,5211 +0,0 @@ -/****************************************************************************** - * - * Name: skge.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.45 $ - * Date: $Date: 2004/02/12 14:41:02 $ - * Purpose: The main driver source module - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * Driver for Marvell Yukon chipset and SysKonnect Gigabit Ethernet - * Server Adapters. - * - * Created 10-Feb-1999, based on Linux' acenic.c, 3c59x.c and - * SysKonnects GEnesis Solaris driver - * Author: Christoph Goos (cgoos@syskonnect.de) - * Mirko Lindner (mlindner@syskonnect.de) - * - * Address all question to: linux@syskonnect.de - * - * The technical manual for the adapters is available from SysKonnect's - * web pages: www.syskonnect.com - * Goto "Support" and search Knowledge Base for "manual". - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Possible compiler options (#define xxx / -Dxxx): - * - * debugging can be enable by changing SK_DEBUG_CHKMOD and - * SK_DEBUG_CHKCAT in makefile (described there). - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This is the main module of the Linux GE driver. - * - * All source files except skge.c, skdrv1st.h, skdrv2nd.h and sktypes.h - * are part of SysKonnect's COMMON MODULES for the SK-98xx adapters. - * Those are used for drivers on multiple OS', so some thing may seem - * unnecessary complicated on Linux. Please do not try to 'clean up' - * them without VERY good reasons, because this will make it more - * difficult to keep the Linux driver in synchronisation with the - * other versions. - * - * Include file hierarchy: - * - * <linux/module.h> - * - * "h/skdrv1st.h" - * <linux/types.h> - * <linux/kernel.h> - * <linux/string.h> - * <linux/errno.h> - * <linux/ioport.h> - * <linux/slab.h> - * <linux/interrupt.h> - * <linux/pci.h> - * <linux/bitops.h> - * <asm/byteorder.h> - * <asm/io.h> - * <linux/netdevice.h> - * <linux/etherdevice.h> - * <linux/skbuff.h> - * those three depending on kernel version used: - * <linux/bios32.h> - * <linux/init.h> - * <asm/uaccess.h> - * <net/checksum.h> - * - * "h/skerror.h" - * "h/skdebug.h" - * "h/sktypes.h" - * "h/lm80.h" - * "h/xmac_ii.h" - * - * "h/skdrv2nd.h" - * "h/skqueue.h" - * "h/skgehwt.h" - * "h/sktimer.h" - * "h/ski2c.h" - * "h/skgepnmi.h" - * "h/skvpd.h" - * "h/skgehw.h" - * "h/skgeinit.h" - * "h/skaddr.h" - * "h/skgesirq.h" - * "h/skrlmt.h" - * - ******************************************************************************/ - -#include "h/skversion.h" - -#include <linux/in.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/init.h> -#include <linux/dma-mapping.h> -#include <linux/ip.h> -#include <linux/mii.h> -#include <linux/mm.h> - -#include "h/skdrv1st.h" -#include "h/skdrv2nd.h" - -/******************************************************************************* - * - * Defines - * - ******************************************************************************/ - -/* for debuging on x86 only */ -/* #define BREAKPOINT() asm(" int $3"); */ - -/* use the transmit hw checksum driver functionality */ -#define USE_SK_TX_CHECKSUM - -/* use the receive hw checksum driver functionality */ -#define USE_SK_RX_CHECKSUM - -/* use the scatter-gather functionality with sendfile() */ -#define SK_ZEROCOPY - -/* use of a transmit complete interrupt */ -#define USE_TX_COMPLETE - -/* - * threshold for copying small receive frames - * set to 0 to avoid copying, set to 9001 to copy all frames - */ -#define SK_COPY_THRESHOLD 50 - -/* number of adapters that can be configured via command line params */ -#define SK_MAX_CARD_PARAM 16 - - - -/* - * use those defines for a compile-in version of the driver instead - * of command line parameters - */ -// #define LINK_SPEED_A {"Auto", } -// #define LINK_SPEED_B {"Auto", } -// #define AUTO_NEG_A {"Sense", } -// #define AUTO_NEG_B {"Sense", } -// #define DUP_CAP_A {"Both", } -// #define DUP_CAP_B {"Both", } -// #define FLOW_CTRL_A {"SymOrRem", } -// #define FLOW_CTRL_B {"SymOrRem", } -// #define ROLE_A {"Auto", } -// #define ROLE_B {"Auto", } -// #define PREF_PORT {"A", } -// #define CON_TYPE {"Auto", } -// #define RLMT_MODE {"CheckLinkState", } - -#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb) -#define DEV_KFREE_SKB_IRQ(skb) dev_kfree_skb_irq(skb) -#define DEV_KFREE_SKB_ANY(skb) dev_kfree_skb_any(skb) - - -/* Set blink mode*/ -#define OEM_CONFIG_VALUE ( SK_ACT_LED_BLINK | \ - SK_DUP_LED_NORMAL | \ - SK_LED_LINK100_ON) - - -/* Isr return value */ -#define SkIsrRetVar irqreturn_t -#define SkIsrRetNone IRQ_NONE -#define SkIsrRetHandled IRQ_HANDLED - - -/******************************************************************************* - * - * Local Function Prototypes - * - ******************************************************************************/ - -static void FreeResources(struct SK_NET_DEVICE *dev); -static int SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC); -static SK_BOOL BoardAllocMem(SK_AC *pAC); -static void BoardFreeMem(SK_AC *pAC); -static void BoardInitMem(SK_AC *pAC); -static void SetupRing(SK_AC*, void*, uintptr_t, RXD**, RXD**, RXD**, int*, SK_BOOL); -static SkIsrRetVar SkGeIsr(int irq, void *dev_id); -static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id); -static int SkGeOpen(struct SK_NET_DEVICE *dev); -static int SkGeClose(struct SK_NET_DEVICE *dev); -static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev); -static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p); -static void SkGeSetRxMode(struct SK_NET_DEVICE *dev); -static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev); -static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd); -static void GetConfiguration(SK_AC*); -static int XmitFrame(SK_AC*, TX_PORT*, struct sk_buff*); -static void FreeTxDescriptors(SK_AC*pAC, TX_PORT*); -static void FillRxRing(SK_AC*, RX_PORT*); -static SK_BOOL FillRxDescriptor(SK_AC*, RX_PORT*); -static void ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL); -static void ClearAndStartRx(SK_AC*, int); -static void ClearTxIrq(SK_AC*, int, int); -static void ClearRxRing(SK_AC*, RX_PORT*); -static void ClearTxRing(SK_AC*, TX_PORT*); -static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int new_mtu); -static void PortReInitBmu(SK_AC*, int); -static int SkGeIocMib(DEV_NET*, unsigned int, int); -static int SkGeInitPCI(SK_AC *pAC); -static void StartDrvCleanupTimer(SK_AC *pAC); -static void StopDrvCleanupTimer(SK_AC *pAC); -static int XmitFrameSG(SK_AC*, TX_PORT*, struct sk_buff*); - -#ifdef SK_DIAG_SUPPORT -static SK_U32 ParseDeviceNbrFromSlotName(const char *SlotName); -static int SkDrvInitAdapter(SK_AC *pAC, int devNbr); -static int SkDrvDeInitAdapter(SK_AC *pAC, int devNbr); -#endif - -/******************************************************************************* - * - * Extern Function Prototypes - * - ******************************************************************************/ -extern void SkDimEnableModerationIfNeeded(SK_AC *pAC); -extern void SkDimDisplayModerationSettings(SK_AC *pAC); -extern void SkDimStartModerationTimer(SK_AC *pAC); -extern void SkDimModerate(SK_AC *pAC); -extern void SkGeBlinkTimer(unsigned long data); - -#ifdef DEBUG -static void DumpMsg(struct sk_buff*, char*); -static void DumpData(char*, int); -static void DumpLong(char*, int); -#endif - -/* global variables *********************************************************/ -static SK_BOOL DoPrintInterfaceChange = SK_TRUE; -extern const struct ethtool_ops SkGeEthtoolOps; - -/* local variables **********************************************************/ -static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}}; -static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480}; - -/***************************************************************************** - * - * SkPciWriteCfgDWord - write a 32 bit value to pci config space - * - * Description: - * This routine writes a 32 bit value to the pci configuration - * space. - * - * Returns: - * 0 - indicate everything worked ok. - * != 0 - error indication - */ -static inline int SkPciWriteCfgDWord( -SK_AC *pAC, /* Adapter Control structure pointer */ -int PciAddr, /* PCI register address */ -SK_U32 Val) /* pointer to store the read value */ -{ - pci_write_config_dword(pAC->PciDev, PciAddr, Val); - return(0); -} /* SkPciWriteCfgDWord */ - -/***************************************************************************** - * - * SkGeInitPCI - Init the PCI resources - * - * Description: - * This function initialize the PCI resources and IO - * - * Returns: - * 0 - indicate everything worked ok. - * != 0 - error indication - */ -static __devinit int SkGeInitPCI(SK_AC *pAC) -{ - struct SK_NET_DEVICE *dev = pAC->dev[0]; - struct pci_dev *pdev = pAC->PciDev; - int retval; - - dev->mem_start = pci_resource_start (pdev, 0); - pci_set_master(pdev); - - retval = pci_request_regions(pdev, "sk98lin"); - if (retval) - goto out; - -#ifdef SK_BIG_ENDIAN - /* - * On big endian machines, we use the adapter's aibility of - * reading the descriptors as big endian. - */ - { - SK_U32 our2; - SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2); - our2 |= PCI_REV_DESC; - SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2); - } -#endif - - /* - * Remap the regs into kernel space. - */ - pAC->IoBase = ioremap_nocache(dev->mem_start, 0x4000); - if (!pAC->IoBase) { - retval = -EIO; - goto out_release; - } - - return 0; - - out_release: - pci_release_regions(pdev); - out: - return retval; -} - - -/***************************************************************************** - * - * FreeResources - release resources allocated for adapter - * - * Description: - * This function releases the IRQ, unmaps the IO and - * frees the desriptor ring. - * - * Returns: N/A - * - */ -static void FreeResources(struct SK_NET_DEVICE *dev) -{ -SK_U32 AllocFlag; -DEV_NET *pNet; -SK_AC *pAC; - - pNet = netdev_priv(dev); - pAC = pNet->pAC; - AllocFlag = pAC->AllocFlag; - if (pAC->PciDev) { - pci_release_regions(pAC->PciDev); - } - if (AllocFlag & SK_ALLOC_IRQ) { - free_irq(dev->irq, dev); - } - if (pAC->IoBase) { - iounmap(pAC->IoBase); - } - if (pAC->pDescrMem) { - BoardFreeMem(pAC); - } - -} /* FreeResources */ - -MODULE_AUTHOR("Mirko Lindner <mlindner@syskonnect.de>"); -MODULE_DESCRIPTION("SysKonnect SK-NET Gigabit Ethernet SK-98xx driver"); -MODULE_LICENSE("GPL"); - -#ifdef LINK_SPEED_A -static char *Speed_A[SK_MAX_CARD_PARAM] = LINK_SPEED; -#else -static char *Speed_A[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef LINK_SPEED_B -static char *Speed_B[SK_MAX_CARD_PARAM] = LINK_SPEED; -#else -static char *Speed_B[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef AUTO_NEG_A -static char *AutoNeg_A[SK_MAX_CARD_PARAM] = AUTO_NEG_A; -#else -static char *AutoNeg_A[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef DUP_CAP_A -static char *DupCap_A[SK_MAX_CARD_PARAM] = DUP_CAP_A; -#else -static char *DupCap_A[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef FLOW_CTRL_A -static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = FLOW_CTRL_A; -#else -static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef ROLE_A -static char *Role_A[SK_MAX_CARD_PARAM] = ROLE_A; -#else -static char *Role_A[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef AUTO_NEG_B -static char *AutoNeg_B[SK_MAX_CARD_PARAM] = AUTO_NEG_B; -#else -static char *AutoNeg_B[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef DUP_CAP_B -static char *DupCap_B[SK_MAX_CARD_PARAM] = DUP_CAP_B; -#else -static char *DupCap_B[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef FLOW_CTRL_B -static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = FLOW_CTRL_B; -#else -static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef ROLE_B -static char *Role_B[SK_MAX_CARD_PARAM] = ROLE_B; -#else -static char *Role_B[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef CON_TYPE -static char *ConType[SK_MAX_CARD_PARAM] = CON_TYPE; -#else -static char *ConType[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef PREF_PORT -static char *PrefPort[SK_MAX_CARD_PARAM] = PREF_PORT; -#else -static char *PrefPort[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef RLMT_MODE -static char *RlmtMode[SK_MAX_CARD_PARAM] = RLMT_MODE; -#else -static char *RlmtMode[SK_MAX_CARD_PARAM] = {"", }; -#endif - -static int IntsPerSec[SK_MAX_CARD_PARAM]; -static char *Moderation[SK_MAX_CARD_PARAM]; -static char *ModerationMask[SK_MAX_CARD_PARAM]; -static char *AutoSizing[SK_MAX_CARD_PARAM]; -static char *Stats[SK_MAX_CARD_PARAM]; - -module_param_array(Speed_A, charp, NULL, 0); -module_param_array(Speed_B, charp, NULL, 0); -module_param_array(AutoNeg_A, charp, NULL, 0); -module_param_array(AutoNeg_B, charp, NULL, 0); -module_param_array(DupCap_A, charp, NULL, 0); -module_param_array(DupCap_B, charp, NULL, 0); -module_param_array(FlowCtrl_A, charp, NULL, 0); -module_param_array(FlowCtrl_B, charp, NULL, 0); -module_param_array(Role_A, charp, NULL, 0); -module_param_array(Role_B, charp, NULL, 0); -module_param_array(ConType, charp, NULL, 0); -module_param_array(PrefPort, charp, NULL, 0); -module_param_array(RlmtMode, charp, NULL, 0); -/* used for interrupt moderation */ -module_param_array(IntsPerSec, int, NULL, 0); -module_param_array(Moderation, charp, NULL, 0); -module_param_array(Stats, charp, NULL, 0); -module_param_array(ModerationMask, charp, NULL, 0); -module_param_array(AutoSizing, charp, NULL, 0); - -/***************************************************************************** - * - * SkGeBoardInit - do level 0 and 1 initialization - * - * Description: - * This function prepares the board hardware for running. The desriptor - * ring is set up, the IRQ is allocated and the configuration settings - * are examined. - * - * Returns: - * 0, if everything is ok - * !=0, on error - */ -static int __devinit SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC) -{ -short i; -unsigned long Flags; -char *DescrString = "sk98lin: Driver for Linux"; /* this is given to PNMI */ -char *VerStr = VER_STRING; -int Ret; /* return code of request_irq */ -SK_BOOL DualNet; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("IoBase: %08lX\n", (unsigned long)pAC->IoBase)); - for (i=0; i<SK_MAX_MACS; i++) { - pAC->TxPort[i][0].HwAddr = pAC->IoBase + TxQueueAddr[i][0]; - pAC->TxPort[i][0].PortIndex = i; - pAC->RxPort[i].HwAddr = pAC->IoBase + RxQueueAddr[i]; - pAC->RxPort[i].PortIndex = i; - } - - /* Initialize the mutexes */ - for (i=0; i<SK_MAX_MACS; i++) { - spin_lock_init(&pAC->TxPort[i][0].TxDesRingLock); - spin_lock_init(&pAC->RxPort[i].RxDesRingLock); - } - spin_lock_init(&pAC->SlowPathLock); - - /* setup phy_id blink timer */ - pAC->BlinkTimer.function = SkGeBlinkTimer; - pAC->BlinkTimer.data = (unsigned long) dev; - init_timer(&pAC->BlinkTimer); - - /* level 0 init common modules here */ - - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - /* Does a RESET on board ...*/ - if (SkGeInit(pAC, pAC->IoBase, SK_INIT_DATA) != 0) { - printk("HWInit (0) failed.\n"); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - return -EIO; - } - SkI2cInit( pAC, pAC->IoBase, SK_INIT_DATA); - SkEventInit(pAC, pAC->IoBase, SK_INIT_DATA); - SkPnmiInit( pAC, pAC->IoBase, SK_INIT_DATA); - SkAddrInit( pAC, pAC->IoBase, SK_INIT_DATA); - SkRlmtInit( pAC, pAC->IoBase, SK_INIT_DATA); - SkTimerInit(pAC, pAC->IoBase, SK_INIT_DATA); - - pAC->BoardLevel = SK_INIT_DATA; - pAC->RxBufSize = ETH_BUF_SIZE; - - SK_PNMI_SET_DRIVER_DESCR(pAC, DescrString); - SK_PNMI_SET_DRIVER_VER(pAC, VerStr); - - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - - /* level 1 init common modules here (HW init) */ - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) { - printk("sk98lin: HWInit (1) failed.\n"); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - return -EIO; - } - SkI2cInit( pAC, pAC->IoBase, SK_INIT_IO); - SkEventInit(pAC, pAC->IoBase, SK_INIT_IO); - SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO); - SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO); - SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO); - SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO); - - /* Set chipset type support */ - pAC->ChipsetType = 0; - if ((pAC->GIni.GIChipId == CHIP_ID_YUKON) || - (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE)) { - pAC->ChipsetType = 1; - } - - GetConfiguration(pAC); - if (pAC->RlmtNets == 2) { - pAC->GIni.GIPortUsage = SK_MUL_LINK; - } - - pAC->BoardLevel = SK_INIT_IO; - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - - if (pAC->GIni.GIMacsFound == 2) { - Ret = request_irq(dev->irq, SkGeIsr, IRQF_SHARED, "sk98lin", dev); - } else if (pAC->GIni.GIMacsFound == 1) { - Ret = request_irq(dev->irq, SkGeIsrOnePort, IRQF_SHARED, - "sk98lin", dev); - } else { - printk(KERN_WARNING "sk98lin: Illegal number of ports: %d\n", - pAC->GIni.GIMacsFound); - return -EIO; - } - - if (Ret) { - printk(KERN_WARNING "sk98lin: Requested IRQ %d is busy.\n", - dev->irq); - return Ret; - } - pAC->AllocFlag |= SK_ALLOC_IRQ; - - /* Alloc memory for this board (Mem for RxD/TxD) : */ - if(!BoardAllocMem(pAC)) { - printk("No memory for descriptor rings.\n"); - return -ENOMEM; - } - - BoardInitMem(pAC); - /* tschilling: New common function with minimum size check. */ - DualNet = SK_FALSE; - if (pAC->RlmtNets == 2) { - DualNet = SK_TRUE; - } - - if (SkGeInitAssignRamToQueues( - pAC, - pAC->ActivePort, - DualNet)) { - BoardFreeMem(pAC); - printk("sk98lin: SkGeInitAssignRamToQueues failed.\n"); - return -EIO; - } - - return (0); -} /* SkGeBoardInit */ - - -/***************************************************************************** - * - * BoardAllocMem - allocate the memory for the descriptor rings - * - * Description: - * This function allocates the memory for all descriptor rings. - * Each ring is aligned for the desriptor alignment and no ring - * has a 4 GByte boundary in it (because the upper 32 bit must - * be constant for all descriptiors in one rings). - * - * Returns: - * SK_TRUE, if all memory could be allocated - * SK_FALSE, if not - */ -static __devinit SK_BOOL BoardAllocMem(SK_AC *pAC) -{ -caddr_t pDescrMem; /* pointer to descriptor memory area */ -size_t AllocLength; /* length of complete descriptor area */ -int i; /* loop counter */ -unsigned long BusAddr; - - - /* rings plus one for alignment (do not cross 4 GB boundary) */ - /* RX_RING_SIZE is assumed bigger than TX_RING_SIZE */ -#if (BITS_PER_LONG == 32) - AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8; -#else - AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound - + RX_RING_SIZE + 8; -#endif - - pDescrMem = pci_alloc_consistent(pAC->PciDev, AllocLength, - &pAC->pDescrMemDMA); - - if (pDescrMem == NULL) { - return (SK_FALSE); - } - pAC->pDescrMem = pDescrMem; - BusAddr = (unsigned long) pAC->pDescrMemDMA; - - /* Descriptors need 8 byte alignment, and this is ensured - * by pci_alloc_consistent. - */ - for (i=0; i<pAC->GIni.GIMacsFound; i++) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, - ("TX%d/A: pDescrMem: %lX, PhysDescrMem: %lX\n", - i, (unsigned long) pDescrMem, - BusAddr)); - pAC->TxPort[i][0].pTxDescrRing = pDescrMem; - pAC->TxPort[i][0].VTxDescrRing = BusAddr; - pDescrMem += TX_RING_SIZE; - BusAddr += TX_RING_SIZE; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, - ("RX%d: pDescrMem: %lX, PhysDescrMem: %lX\n", - i, (unsigned long) pDescrMem, - (unsigned long)BusAddr)); - pAC->RxPort[i].pRxDescrRing = pDescrMem; - pAC->RxPort[i].VRxDescrRing = BusAddr; - pDescrMem += RX_RING_SIZE; - BusAddr += RX_RING_SIZE; - } /* for */ - - return (SK_TRUE); -} /* BoardAllocMem */ - - -/**************************************************************************** - * - * BoardFreeMem - reverse of BoardAllocMem - * - * Description: - * Free all memory allocated in BoardAllocMem: adapter context, - * descriptor rings, locks. - * - * Returns: N/A - */ -static void BoardFreeMem( -SK_AC *pAC) -{ -size_t AllocLength; /* length of complete descriptor area */ - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("BoardFreeMem\n")); -#if (BITS_PER_LONG == 32) - AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8; -#else - AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound - + RX_RING_SIZE + 8; -#endif - - pci_free_consistent(pAC->PciDev, AllocLength, - pAC->pDescrMem, pAC->pDescrMemDMA); - pAC->pDescrMem = NULL; -} /* BoardFreeMem */ - - -/***************************************************************************** - * - * BoardInitMem - initiate the descriptor rings - * - * Description: - * This function sets the descriptor rings up in memory. - * The adapter is initialized with the descriptor start addresses. - * - * Returns: N/A - */ -static __devinit void BoardInitMem(SK_AC *pAC) -{ -int i; /* loop counter */ -int RxDescrSize; /* the size of a rx descriptor rounded up to alignment*/ -int TxDescrSize; /* the size of a tx descriptor rounded up to alignment*/ - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("BoardInitMem\n")); - - RxDescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN; - pAC->RxDescrPerRing = RX_RING_SIZE / RxDescrSize; - TxDescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN; - pAC->TxDescrPerRing = TX_RING_SIZE / RxDescrSize; - - for (i=0; i<pAC->GIni.GIMacsFound; i++) { - SetupRing( - pAC, - pAC->TxPort[i][0].pTxDescrRing, - pAC->TxPort[i][0].VTxDescrRing, - (RXD**)&pAC->TxPort[i][0].pTxdRingHead, - (RXD**)&pAC->TxPort[i][0].pTxdRingTail, - (RXD**)&pAC->TxPort[i][0].pTxdRingPrev, - &pAC->TxPort[i][0].TxdRingFree, - SK_TRUE); - SetupRing( - pAC, - pAC->RxPort[i].pRxDescrRing, - pAC->RxPort[i].VRxDescrRing, - &pAC->RxPort[i].pRxdRingHead, - &pAC->RxPort[i].pRxdRingTail, - &pAC->RxPort[i].pRxdRingPrev, - &pAC->RxPort[i].RxdRingFree, - SK_FALSE); - } -} /* BoardInitMem */ - - -/***************************************************************************** - * - * SetupRing - create one descriptor ring - * - * Description: - * This function creates one descriptor ring in the given memory area. - * The head, tail and number of free descriptors in the ring are set. - * - * Returns: - * none - */ -static void SetupRing( -SK_AC *pAC, -void *pMemArea, /* a pointer to the memory area for the ring */ -uintptr_t VMemArea, /* the virtual bus address of the memory area */ -RXD **ppRingHead, /* address where the head should be written */ -RXD **ppRingTail, /* address where the tail should be written */ -RXD **ppRingPrev, /* address where the tail should be written */ -int *pRingFree, /* address where the # of free descr. goes */ -SK_BOOL IsTx) /* flag: is this a tx ring */ -{ -int i; /* loop counter */ -int DescrSize; /* the size of a descriptor rounded up to alignment*/ -int DescrNum; /* number of descriptors per ring */ -RXD *pDescr; /* pointer to a descriptor (receive or transmit) */ -RXD *pNextDescr; /* pointer to the next descriptor */ -RXD *pPrevDescr; /* pointer to the previous descriptor */ -uintptr_t VNextDescr; /* the virtual bus address of the next descriptor */ - - if (IsTx == SK_TRUE) { - DescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) * - DESCR_ALIGN; - DescrNum = TX_RING_SIZE / DescrSize; - } else { - DescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) * - DESCR_ALIGN; - DescrNum = RX_RING_SIZE / DescrSize; - } - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, - ("Descriptor size: %d Descriptor Number: %d\n", - DescrSize,DescrNum)); - - pDescr = (RXD*) pMemArea; - pPrevDescr = NULL; - pNextDescr = (RXD*) (((char*)pDescr) + DescrSize); - VNextDescr = VMemArea + DescrSize; - for(i=0; i<DescrNum; i++) { - /* set the pointers right */ - pDescr->VNextRxd = VNextDescr & 0xffffffffULL; - pDescr->pNextRxd = pNextDescr; - if (!IsTx) pDescr->TcpSumStarts = ETH_HLEN << 16 | ETH_HLEN; - - /* advance one step */ - pPrevDescr = pDescr; - pDescr = pNextDescr; - pNextDescr = (RXD*) (((char*)pDescr) + DescrSize); - VNextDescr += DescrSize; - } - pPrevDescr->pNextRxd = (RXD*) pMemArea; - pPrevDescr->VNextRxd = VMemArea; - pDescr = (RXD*) pMemArea; - *ppRingHead = (RXD*) pMemArea; - *ppRingTail = *ppRingHead; - *ppRingPrev = pPrevDescr; - *pRingFree = DescrNum; -} /* SetupRing */ - - -/***************************************************************************** - * - * PortReInitBmu - re-initiate the descriptor rings for one port - * - * Description: - * This function reinitializes the descriptor rings of one port - * in memory. The port must be stopped before. - * The HW is initialized with the descriptor start addresses. - * - * Returns: - * none - */ -static void PortReInitBmu( -SK_AC *pAC, /* pointer to adapter context */ -int PortIndex) /* index of the port for which to re-init */ -{ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("PortReInitBmu ")); - - /* set address of first descriptor of ring in BMU */ - SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_L, - (uint32_t)(((caddr_t) - (pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) - - pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing + - pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) & - 0xFFFFFFFF)); - SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_H, - (uint32_t)(((caddr_t) - (pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) - - pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing + - pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) >> 32)); - SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_L, - (uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) - - pAC->RxPort[PortIndex].pRxDescrRing + - pAC->RxPort[PortIndex].VRxDescrRing) & 0xFFFFFFFF)); - SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_H, - (uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) - - pAC->RxPort[PortIndex].pRxDescrRing + - pAC->RxPort[PortIndex].VRxDescrRing) >> 32)); -} /* PortReInitBmu */ - - -/**************************************************************************** - * - * SkGeIsr - handle adapter interrupts - * - * Description: - * The interrupt routine is called when the network adapter - * generates an interrupt. It may also be called if another device - * shares this interrupt vector with the driver. - * - * Returns: N/A - * - */ -static SkIsrRetVar SkGeIsr(int irq, void *dev_id) -{ -struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id; -DEV_NET *pNet; -SK_AC *pAC; -SK_U32 IntSrc; /* interrupts source register contents */ - - pNet = netdev_priv(dev); - pAC = pNet->pAC; - - /* - * Check and process if its our interrupt - */ - SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc); - if (IntSrc == 0) { - return SkIsrRetNone; - } - - while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) { -#if 0 /* software irq currently not used */ - if (IntSrc & IS_IRQ_SW) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("Software IRQ\n")); - } -#endif - if (IntSrc & IS_R1_F) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF RX1 IRQ\n")); - ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); - SK_PNMI_CNT_RX_INTR(pAC, 0); - } - if (IntSrc & IS_R2_F) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF RX2 IRQ\n")); - ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE); - SK_PNMI_CNT_RX_INTR(pAC, 1); - } -#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ - if (IntSrc & IS_XA1_F) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF AS TX1 IRQ\n")); - SK_PNMI_CNT_TX_INTR(pAC, 0); - spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); - FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]); - spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); - } - if (IntSrc & IS_XA2_F) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF AS TX2 IRQ\n")); - SK_PNMI_CNT_TX_INTR(pAC, 1); - spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock); - FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]); - spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock); - } -#if 0 /* only if sync. queues used */ - if (IntSrc & IS_XS1_F) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF SY TX1 IRQ\n")); - SK_PNMI_CNT_TX_INTR(pAC, 1); - spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); - FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH); - spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); - ClearTxIrq(pAC, 0, TX_PRIO_HIGH); - } - if (IntSrc & IS_XS2_F) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF SY TX2 IRQ\n")); - SK_PNMI_CNT_TX_INTR(pAC, 1); - spin_lock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock); - FreeTxDescriptors(pAC, 1, TX_PRIO_HIGH); - spin_unlock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock); - ClearTxIrq(pAC, 1, TX_PRIO_HIGH); - } -#endif -#endif - - /* do all IO at once */ - if (IntSrc & IS_R1_F) - ClearAndStartRx(pAC, 0); - if (IntSrc & IS_R2_F) - ClearAndStartRx(pAC, 1); -#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ - if (IntSrc & IS_XA1_F) - ClearTxIrq(pAC, 0, TX_PRIO_LOW); - if (IntSrc & IS_XA2_F) - ClearTxIrq(pAC, 1, TX_PRIO_LOW); -#endif - SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc); - } /* while (IntSrc & IRQ_MASK != 0) */ - - IntSrc &= pAC->GIni.GIValIrqMask; - if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, - ("SPECIAL IRQ DP-Cards => %x\n", IntSrc)); - pAC->CheckQueue = SK_FALSE; - spin_lock(&pAC->SlowPathLock); - if (IntSrc & SPECIAL_IRQS) - SkGeSirqIsr(pAC, pAC->IoBase, IntSrc); - - SkEventDispatcher(pAC, pAC->IoBase); - spin_unlock(&pAC->SlowPathLock); - } - /* - * do it all again is case we cleared an interrupt that - * came in after handling the ring (OUTs may be delayed - * in hardware buffers, but are through after IN) - * - * rroesler: has been commented out and shifted to - * SkGeDrvEvent(), because it is timer - * guarded now - * - ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); - ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE); - */ - - if (pAC->CheckQueue) { - pAC->CheckQueue = SK_FALSE; - spin_lock(&pAC->SlowPathLock); - SkEventDispatcher(pAC, pAC->IoBase); - spin_unlock(&pAC->SlowPathLock); - } - - /* IRQ is processed - Enable IRQs again*/ - SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask); - - return SkIsrRetHandled; -} /* SkGeIsr */ - - -/**************************************************************************** - * - * SkGeIsrOnePort - handle adapter interrupts for single port adapter - * - * Description: - * The interrupt routine is called when the network adapter - * generates an interrupt. It may also be called if another device - * shares this interrupt vector with the driver. - * This is the same as above, but handles only one port. - * - * Returns: N/A - * - */ -static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id) -{ -struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id; -DEV_NET *pNet; -SK_AC *pAC; -SK_U32 IntSrc; /* interrupts source register contents */ - - pNet = netdev_priv(dev); - pAC = pNet->pAC; - - /* - * Check and process if its our interrupt - */ - SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc); - if (IntSrc == 0) { - return SkIsrRetNone; - } - - while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) { -#if 0 /* software irq currently not used */ - if (IntSrc & IS_IRQ_SW) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("Software IRQ\n")); - } -#endif - if (IntSrc & IS_R1_F) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF RX1 IRQ\n")); - ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); - SK_PNMI_CNT_RX_INTR(pAC, 0); - } -#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ - if (IntSrc & IS_XA1_F) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF AS TX1 IRQ\n")); - SK_PNMI_CNT_TX_INTR(pAC, 0); - spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); - FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]); - spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); - } -#if 0 /* only if sync. queues used */ - if (IntSrc & IS_XS1_F) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF SY TX1 IRQ\n")); - SK_PNMI_CNT_TX_INTR(pAC, 0); - spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); - FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH); - spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); - ClearTxIrq(pAC, 0, TX_PRIO_HIGH); - } -#endif -#endif - - /* do all IO at once */ - if (IntSrc & IS_R1_F) - ClearAndStartRx(pAC, 0); -#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ - if (IntSrc & IS_XA1_F) - ClearTxIrq(pAC, 0, TX_PRIO_LOW); -#endif - SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc); - } /* while (IntSrc & IRQ_MASK != 0) */ - - IntSrc &= pAC->GIni.GIValIrqMask; - if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, - ("SPECIAL IRQ SP-Cards => %x\n", IntSrc)); - pAC->CheckQueue = SK_FALSE; - spin_lock(&pAC->SlowPathLock); - if (IntSrc & SPECIAL_IRQS) - SkGeSirqIsr(pAC, pAC->IoBase, IntSrc); - - SkEventDispatcher(pAC, pAC->IoBase); - spin_unlock(&pAC->SlowPathLock); - } - /* - * do it all again is case we cleared an interrupt that - * came in after handling the ring (OUTs may be delayed - * in hardware buffers, but are through after IN) - * - * rroesler: has been commented out and shifted to - * SkGeDrvEvent(), because it is timer - * guarded now - * - ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); - */ - - /* IRQ is processed - Enable IRQs again*/ - SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask); - - return SkIsrRetHandled; -} /* SkGeIsrOnePort */ - -#ifdef CONFIG_NET_POLL_CONTROLLER -/**************************************************************************** - * - * SkGePollController - polling receive, for netconsole - * - * Description: - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - * - * Returns: N/A - */ -static void SkGePollController(struct net_device *dev) -{ - disable_irq(dev->irq); - SkGeIsr(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -/**************************************************************************** - * - * SkGeOpen - handle start of initialized adapter - * - * Description: - * This function starts the initialized adapter. - * The board level variable is set and the adapter is - * brought to full functionality. - * The device flags are set for operation. - * Do all necessary level 2 initialization, enable interrupts and - * give start command to RLMT. - * - * Returns: - * 0 on success - * != 0 on error - */ -static int SkGeOpen( -struct SK_NET_DEVICE *dev) -{ - DEV_NET *pNet; - SK_AC *pAC; - unsigned long Flags; /* for spin lock */ - int i; - SK_EVPARA EvPara; /* an event parameter union */ - - pNet = netdev_priv(dev); - pAC = pNet->pAC; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeOpen: pAC=0x%lX:\n", (unsigned long)pAC)); - -#ifdef SK_DIAG_SUPPORT - if (pAC->DiagModeActive == DIAG_ACTIVE) { - if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) { - return (-1); /* still in use by diag; deny actions */ - } - } -#endif - - /* Set blink mode */ - if ((pAC->PciDev->vendor == 0x1186) || (pAC->PciDev->vendor == 0x11ab )) - pAC->GIni.GILedBlinkCtrl = OEM_CONFIG_VALUE; - - if (pAC->BoardLevel == SK_INIT_DATA) { - /* level 1 init common modules here */ - if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) { - printk("%s: HWInit (1) failed.\n", pAC->dev[pNet->PortNr]->name); - return (-1); - } - SkI2cInit (pAC, pAC->IoBase, SK_INIT_IO); - SkEventInit (pAC, pAC->IoBase, SK_INIT_IO); - SkPnmiInit (pAC, pAC->IoBase, SK_INIT_IO); - SkAddrInit (pAC, pAC->IoBase, SK_INIT_IO); - SkRlmtInit (pAC, pAC->IoBase, SK_INIT_IO); - SkTimerInit (pAC, pAC->IoBase, SK_INIT_IO); - pAC->BoardLevel = SK_INIT_IO; - } - - if (pAC->BoardLevel != SK_INIT_RUN) { - /* tschilling: Level 2 init modules here, check return value. */ - if (SkGeInit(pAC, pAC->IoBase, SK_INIT_RUN) != 0) { - printk("%s: HWInit (2) failed.\n", pAC->dev[pNet->PortNr]->name); - return (-1); - } - SkI2cInit (pAC, pAC->IoBase, SK_INIT_RUN); - SkEventInit (pAC, pAC->IoBase, SK_INIT_RUN); - SkPnmiInit (pAC, pAC->IoBase, SK_INIT_RUN); - SkAddrInit (pAC, pAC->IoBase, SK_INIT_RUN); - SkRlmtInit (pAC, pAC->IoBase, SK_INIT_RUN); - SkTimerInit (pAC, pAC->IoBase, SK_INIT_RUN); - pAC->BoardLevel = SK_INIT_RUN; - } - - for (i=0; i<pAC->GIni.GIMacsFound; i++) { - /* Enable transmit descriptor polling. */ - SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE); - FillRxRing(pAC, &pAC->RxPort[i]); - } - SkGeYellowLED(pAC, pAC->IoBase, 1); - - StartDrvCleanupTimer(pAC); - SkDimEnableModerationIfNeeded(pAC); - SkDimDisplayModerationSettings(pAC); - - pAC->GIni.GIValIrqMask &= IRQ_MASK; - - /* enable Interrupts */ - SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask); - SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK); - - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - - if ((pAC->RlmtMode != 0) && (pAC->MaxPorts == 0)) { - EvPara.Para32[0] = pAC->RlmtNets; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS, - EvPara); - EvPara.Para32[0] = pAC->RlmtMode; - EvPara.Para32[1] = 0; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_MODE_CHANGE, - EvPara); - } - - EvPara.Para32[0] = pNet->NetNr; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); - SkEventDispatcher(pAC, pAC->IoBase); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - - pAC->MaxPorts++; - - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeOpen suceeded\n")); - - return (0); -} /* SkGeOpen */ - - -/**************************************************************************** - * - * SkGeClose - Stop initialized adapter - * - * Description: - * Close initialized adapter. - * - * Returns: - * 0 - on success - * error code - on error - */ -static int SkGeClose( -struct SK_NET_DEVICE *dev) -{ - DEV_NET *pNet; - DEV_NET *newPtrNet; - SK_AC *pAC; - - unsigned long Flags; /* for spin lock */ - int i; - int PortIdx; - SK_EVPARA EvPara; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeClose: pAC=0x%lX ", (unsigned long)pAC)); - - pNet = netdev_priv(dev); - pAC = pNet->pAC; - -#ifdef SK_DIAG_SUPPORT - if (pAC->DiagModeActive == DIAG_ACTIVE) { - if (pAC->DiagFlowCtrl == SK_FALSE) { - /* - ** notify that the interface which has been closed - ** by operator interaction must not be started up - ** again when the DIAG has finished. - */ - newPtrNet = netdev_priv(pAC->dev[0]); - if (newPtrNet == pNet) { - pAC->WasIfUp[0] = SK_FALSE; - } else { - pAC->WasIfUp[1] = SK_FALSE; - } - return 0; /* return to system everything is fine... */ - } else { - pAC->DiagFlowCtrl = SK_FALSE; - } - } -#endif - - netif_stop_queue(dev); - - if (pAC->RlmtNets == 1) - PortIdx = pAC->ActivePort; - else - PortIdx = pNet->NetNr; - - StopDrvCleanupTimer(pAC); - - /* - * Clear multicast table, promiscuous mode .... - */ - SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0); - SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx, - SK_PROM_MODE_NONE); - - if (pAC->MaxPorts == 1) { - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - /* disable interrupts */ - SK_OUT32(pAC->IoBase, B0_IMSK, 0); - EvPara.Para32[0] = pNet->NetNr; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - SkEventDispatcher(pAC, pAC->IoBase); - SK_OUT32(pAC->IoBase, B0_IMSK, 0); - /* stop the hardware */ - SkGeDeInit(pAC, pAC->IoBase); - pAC->BoardLevel = SK_INIT_DATA; - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - } else { - - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - EvPara.Para32[0] = pNet->NetNr; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - SkPnmiEvent(pAC, pAC->IoBase, SK_PNMI_EVT_XMAC_RESET, EvPara); - SkEventDispatcher(pAC, pAC->IoBase); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - - /* Stop port */ - spin_lock_irqsave(&pAC->TxPort[pNet->PortNr] - [TX_PRIO_LOW].TxDesRingLock, Flags); - SkGeStopPort(pAC, pAC->IoBase, pNet->PortNr, - SK_STOP_ALL, SK_HARD_RST); - spin_unlock_irqrestore(&pAC->TxPort[pNet->PortNr] - [TX_PRIO_LOW].TxDesRingLock, Flags); - } - - if (pAC->RlmtNets == 1) { - /* clear all descriptor rings */ - for (i=0; i<pAC->GIni.GIMacsFound; i++) { - ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE); - ClearRxRing(pAC, &pAC->RxPort[i]); - ClearTxRing(pAC, &pAC->TxPort[i][TX_PRIO_LOW]); - } - } else { - /* clear port descriptor rings */ - ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE); - ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]); - ClearTxRing(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW]); - } - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeClose: done ")); - - SK_MEMSET(&(pAC->PnmiBackup), 0, sizeof(SK_PNMI_STRUCT_DATA)); - SK_MEMCPY(&(pAC->PnmiBackup), &(pAC->PnmiStruct), - sizeof(SK_PNMI_STRUCT_DATA)); - - pAC->MaxPorts--; - - return (0); -} /* SkGeClose */ - - -/***************************************************************************** - * - * SkGeXmit - Linux frame transmit function - * - * Description: - * The system calls this function to send frames onto the wire. - * It puts the frame in the tx descriptor ring. If the ring is - * full then, the 'tbusy' flag is set. - * - * Returns: - * 0, if everything is ok - * !=0, on error - * WARNING: returning 1 in 'tbusy' case caused system crashes (double - * allocated skb's) !!! - */ -static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev) -{ -DEV_NET *pNet; -SK_AC *pAC; -int Rc; /* return code of XmitFrame */ - - pNet = netdev_priv(dev); - pAC = pNet->pAC; - - if ((!skb_shinfo(skb)->nr_frags) || - (pAC->GIni.GIChipId == CHIP_ID_GENESIS)) { - /* Don't activate scatter-gather and hardware checksum */ - - if (pAC->RlmtNets == 2) - Rc = XmitFrame( - pAC, - &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW], - skb); - else - Rc = XmitFrame( - pAC, - &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW], - skb); - } else { - /* scatter-gather and hardware TCP checksumming anabled*/ - if (pAC->RlmtNets == 2) - Rc = XmitFrameSG( - pAC, - &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW], - skb); - else - Rc = XmitFrameSG( - pAC, - &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW], - skb); - } - - /* Transmitter out of resources? */ - if (Rc <= 0) { - netif_stop_queue(dev); - } - - /* If not taken, give buffer ownership back to the - * queueing layer. - */ - if (Rc < 0) - return (1); - - dev->trans_start = jiffies; - return (0); -} /* SkGeXmit */ - - -/***************************************************************************** - * - * XmitFrame - fill one socket buffer into the transmit ring - * - * Description: - * This function puts a message into the transmit descriptor ring - * if there is a descriptors left. - * Linux skb's consist of only one continuous buffer. - * The first step locks the ring. It is held locked - * all time to avoid problems with SWITCH_../PORT_RESET. - * Then the descriptoris allocated. - * The second part is linking the buffer to the descriptor. - * At the very last, the Control field of the descriptor - * is made valid for the BMU and a start TX command is given - * if necessary. - * - * Returns: - * > 0 - on succes: the number of bytes in the message - * = 0 - on resource shortage: this frame sent or dropped, now - * the ring is full ( -> set tbusy) - * < 0 - on failure: other problems ( -> return failure to upper layers) - */ -static int XmitFrame( -SK_AC *pAC, /* pointer to adapter context */ -TX_PORT *pTxPort, /* pointer to struct of port to send to */ -struct sk_buff *pMessage) /* pointer to send-message */ -{ - TXD *pTxd; /* the rxd to fill */ - TXD *pOldTxd; - unsigned long Flags; - SK_U64 PhysAddr; - int BytesSend = pMessage->len; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("X")); - - spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags); -#ifndef USE_TX_COMPLETE - FreeTxDescriptors(pAC, pTxPort); -#endif - if (pTxPort->TxdRingFree == 0) { - /* - ** no enough free descriptors in ring at the moment. - ** Maybe free'ing some old one help? - */ - FreeTxDescriptors(pAC, pTxPort); - if (pTxPort->TxdRingFree == 0) { - spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); - SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex); - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_TX_PROGRESS, - ("XmitFrame failed\n")); - /* - ** the desired message can not be sent - ** Because tbusy seems to be set, the message - ** should not be freed here. It will be used - ** by the scheduler of the ethernet handler - */ - return (-1); - } - } - - /* - ** If the passed socket buffer is of smaller MTU-size than 60, - ** copy everything into new buffer and fill all bytes between - ** the original packet end and the new packet end of 60 with 0x00. - ** This is to resolve faulty padding by the HW with 0xaa bytes. - */ - if (BytesSend < C_LEN_ETHERNET_MINSIZE) { - if (skb_padto(pMessage, C_LEN_ETHERNET_MINSIZE)) { - spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); - return 0; - } - pMessage->len = C_LEN_ETHERNET_MINSIZE; - } - - /* - ** advance head counter behind descriptor needed for this frame, - ** so that needed descriptor is reserved from that on. The next - ** action will be to add the passed buffer to the TX-descriptor - */ - pTxd = pTxPort->pTxdRingHead; - pTxPort->pTxdRingHead = pTxd->pNextTxd; - pTxPort->TxdRingFree--; - -#ifdef SK_DUMP_TX - DumpMsg(pMessage, "XmitFrame"); -#endif - - /* - ** First step is to map the data to be sent via the adapter onto - ** the DMA memory. Kernel 2.2 uses virt_to_bus(), but kernels 2.4 - ** and 2.6 need to use pci_map_page() for that mapping. - */ - PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, - virt_to_page(pMessage->data), - ((unsigned long) pMessage->data & ~PAGE_MASK), - pMessage->len, - PCI_DMA_TODEVICE); - pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); - pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); - pTxd->pMBuf = pMessage; - - if (pMessage->ip_summed == CHECKSUM_PARTIAL) { - u16 hdrlen = skb_transport_offset(pMessage); - u16 offset = hdrlen + pMessage->csum_offset; - - if ((ipip_hdr(pMessage)->protocol == IPPROTO_UDP) && - (pAC->GIni.GIChipRev == 0) && - (pAC->GIni.GIChipId == CHIP_ID_YUKON)) { - pTxd->TBControl = BMU_TCP_CHECK; - } else { - pTxd->TBControl = BMU_UDP_CHECK; - } - - pTxd->TcpSumOfs = 0; - pTxd->TcpSumSt = hdrlen; - pTxd->TcpSumWr = offset; - - pTxd->TBControl |= BMU_OWN | BMU_STF | - BMU_SW | BMU_EOF | -#ifdef USE_TX_COMPLETE - BMU_IRQ_EOF | -#endif - pMessage->len; - } else { - pTxd->TBControl = BMU_OWN | BMU_STF | BMU_CHECK | - BMU_SW | BMU_EOF | -#ifdef USE_TX_COMPLETE - BMU_IRQ_EOF | -#endif - pMessage->len; - } - - /* - ** If previous descriptor already done, give TX start cmd - */ - pOldTxd = xchg(&pTxPort->pTxdRingPrev, pTxd); - if ((pOldTxd->TBControl & BMU_OWN) == 0) { - SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START); - } - - /* - ** after releasing the lock, the skb may immediately be free'd - */ - spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); - if (pTxPort->TxdRingFree != 0) { - return (BytesSend); - } else { - return (0); - } - -} /* XmitFrame */ - -/***************************************************************************** - * - * XmitFrameSG - fill one socket buffer into the transmit ring - * (use SG and TCP/UDP hardware checksumming) - * - * Description: - * This function puts a message into the transmit descriptor ring - * if there is a descriptors left. - * - * Returns: - * > 0 - on succes: the number of bytes in the message - * = 0 - on resource shortage: this frame sent or dropped, now - * the ring is full ( -> set tbusy) - * < 0 - on failure: other problems ( -> return failure to upper layers) - */ -static int XmitFrameSG( -SK_AC *pAC, /* pointer to adapter context */ -TX_PORT *pTxPort, /* pointer to struct of port to send to */ -struct sk_buff *pMessage) /* pointer to send-message */ -{ - - TXD *pTxd; - TXD *pTxdFst; - TXD *pTxdLst; - int CurrFrag; - int BytesSend; - skb_frag_t *sk_frag; - SK_U64 PhysAddr; - unsigned long Flags; - SK_U32 Control; - - spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags); -#ifndef USE_TX_COMPLETE - FreeTxDescriptors(pAC, pTxPort); -#endif - if ((skb_shinfo(pMessage)->nr_frags +1) > pTxPort->TxdRingFree) { - FreeTxDescriptors(pAC, pTxPort); - if ((skb_shinfo(pMessage)->nr_frags + 1) > pTxPort->TxdRingFree) { - spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); - SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex); - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_TX_PROGRESS, - ("XmitFrameSG failed - Ring full\n")); - /* this message can not be sent now */ - return(-1); - } - } - - pTxd = pTxPort->pTxdRingHead; - pTxdFst = pTxd; - pTxdLst = pTxd; - BytesSend = 0; - - /* - ** Map the first fragment (header) into the DMA-space - */ - PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, - virt_to_page(pMessage->data), - ((unsigned long) pMessage->data & ~PAGE_MASK), - skb_headlen(pMessage), - PCI_DMA_TODEVICE); - - pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); - pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); - - /* - ** Does the HW need to evaluate checksum for TCP or UDP packets? - */ - if (pMessage->ip_summed == CHECKSUM_PARTIAL) { - u16 hdrlen = skb_transport_offset(pMessage); - u16 offset = hdrlen + pMessage->csum_offset; - - Control = BMU_STFWD; - - /* - ** We have to use the opcode for tcp here, because the - ** opcode for udp is not working in the hardware yet - ** (Revision 2.0) - */ - if ((ipip_hdr(pMessage)->protocol == IPPROTO_UDP) && - (pAC->GIni.GIChipRev == 0) && - (pAC->GIni.GIChipId == CHIP_ID_YUKON)) { - Control |= BMU_TCP_CHECK; - } else { - Control |= BMU_UDP_CHECK; - } - - pTxd->TcpSumOfs = 0; - pTxd->TcpSumSt = hdrlen; - pTxd->TcpSumWr = offset; - } else - Control = BMU_CHECK | BMU_SW; - - pTxd->TBControl = BMU_STF | Control | skb_headlen(pMessage); - - pTxd = pTxd->pNextTxd; - pTxPort->TxdRingFree--; - BytesSend += skb_headlen(pMessage); - - /* - ** Browse over all SG fragments and map each of them into the DMA space - */ - for (CurrFrag = 0; CurrFrag < skb_shinfo(pMessage)->nr_frags; CurrFrag++) { - sk_frag = &skb_shinfo(pMessage)->frags[CurrFrag]; - /* - ** we already have the proper value in entry - */ - PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, - sk_frag->page, - sk_frag->page_offset, - sk_frag->size, - PCI_DMA_TODEVICE); - - pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); - pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); - pTxd->pMBuf = pMessage; - - pTxd->TBControl = Control | BMU_OWN | sk_frag->size; - - /* - ** Do we have the last fragment? - */ - if( (CurrFrag+1) == skb_shinfo(pMessage)->nr_frags ) { -#ifdef USE_TX_COMPLETE - pTxd->TBControl |= BMU_EOF | BMU_IRQ_EOF; -#else - pTxd->TBControl |= BMU_EOF; -#endif - pTxdFst->TBControl |= BMU_OWN | BMU_SW; - } - pTxdLst = pTxd; - pTxd = pTxd->pNextTxd; - pTxPort->TxdRingFree--; - BytesSend += sk_frag->size; - } - - /* - ** If previous descriptor already done, give TX start cmd - */ - if ((pTxPort->pTxdRingPrev->TBControl & BMU_OWN) == 0) { - SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START); - } - - pTxPort->pTxdRingPrev = pTxdLst; - pTxPort->pTxdRingHead = pTxd; - - spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); - - if (pTxPort->TxdRingFree > 0) { - return (BytesSend); - } else { - return (0); - } -} - -/***************************************************************************** - * - * FreeTxDescriptors - release descriptors from the descriptor ring - * - * Description: - * This function releases descriptors from a transmit ring if they - * have been sent by the BMU. - * If a descriptors is sent, it can be freed and the message can - * be freed, too. - * The SOFTWARE controllable bit is used to prevent running around a - * completely free ring for ever. If this bit is no set in the - * frame (by XmitFrame), this frame has never been sent or is - * already freed. - * The Tx descriptor ring lock must be held while calling this function !!! - * - * Returns: - * none - */ -static void FreeTxDescriptors( -SK_AC *pAC, /* pointer to the adapter context */ -TX_PORT *pTxPort) /* pointer to destination port structure */ -{ -TXD *pTxd; /* pointer to the checked descriptor */ -TXD *pNewTail; /* pointer to 'end' of the ring */ -SK_U32 Control; /* TBControl field of descriptor */ -SK_U64 PhysAddr; /* address of DMA mapping */ - - pNewTail = pTxPort->pTxdRingTail; - pTxd = pNewTail; - /* - ** loop forever; exits if BMU_SW bit not set in start frame - ** or BMU_OWN bit set in any frame - */ - while (1) { - Control = pTxd->TBControl; - if ((Control & BMU_SW) == 0) { - /* - ** software controllable bit is set in first - ** fragment when given to BMU. Not set means that - ** this fragment was never sent or is already - ** freed ( -> ring completely free now). - */ - pTxPort->pTxdRingTail = pTxd; - netif_wake_queue(pAC->dev[pTxPort->PortIndex]); - return; - } - if (Control & BMU_OWN) { - pTxPort->pTxdRingTail = pTxd; - if (pTxPort->TxdRingFree > 0) { - netif_wake_queue(pAC->dev[pTxPort->PortIndex]); - } - return; - } - - /* - ** release the DMA mapping, because until not unmapped - ** this buffer is considered being under control of the - ** adapter card! - */ - PhysAddr = ((SK_U64) pTxd->VDataHigh) << (SK_U64) 32; - PhysAddr |= (SK_U64) pTxd->VDataLow; - pci_unmap_page(pAC->PciDev, PhysAddr, - pTxd->pMBuf->len, - PCI_DMA_TODEVICE); - - if (Control & BMU_EOF) - DEV_KFREE_SKB_ANY(pTxd->pMBuf); /* free message */ - - pTxPort->TxdRingFree++; - pTxd->TBControl &= ~BMU_SW; - pTxd = pTxd->pNextTxd; /* point behind fragment with EOF */ - } /* while(forever) */ -} /* FreeTxDescriptors */ - -/***************************************************************************** - * - * FillRxRing - fill the receive ring with valid descriptors - * - * Description: - * This function fills the receive ring descriptors with data - * segments and makes them valid for the BMU. - * The active ring is filled completely, if possible. - * The non-active ring is filled only partial to save memory. - * - * Description of rx ring structure: - * head - points to the descriptor which will be used next by the BMU - * tail - points to the next descriptor to give to the BMU - * - * Returns: N/A - */ -static void FillRxRing( -SK_AC *pAC, /* pointer to the adapter context */ -RX_PORT *pRxPort) /* ptr to port struct for which the ring - should be filled */ -{ -unsigned long Flags; - - spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags); - while (pRxPort->RxdRingFree > pRxPort->RxFillLimit) { - if(!FillRxDescriptor(pAC, pRxPort)) - break; - } - spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags); -} /* FillRxRing */ - - -/***************************************************************************** - * - * FillRxDescriptor - fill one buffer into the receive ring - * - * Description: - * The function allocates a new receive buffer and - * puts it into the next descriptor. - * - * Returns: - * SK_TRUE - a buffer was added to the ring - * SK_FALSE - a buffer could not be added - */ -static SK_BOOL FillRxDescriptor( -SK_AC *pAC, /* pointer to the adapter context struct */ -RX_PORT *pRxPort) /* ptr to port struct of ring to fill */ -{ -struct sk_buff *pMsgBlock; /* pointer to a new message block */ -RXD *pRxd; /* the rxd to fill */ -SK_U16 Length; /* data fragment length */ -SK_U64 PhysAddr; /* physical address of a rx buffer */ - - pMsgBlock = alloc_skb(pAC->RxBufSize, GFP_ATOMIC); - if (pMsgBlock == NULL) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_ENTRY, - ("%s: Allocation of rx buffer failed !\n", - pAC->dev[pRxPort->PortIndex]->name)); - SK_PNMI_CNT_NO_RX_BUF(pAC, pRxPort->PortIndex); - return(SK_FALSE); - } - skb_reserve(pMsgBlock, 2); /* to align IP frames */ - /* skb allocated ok, so add buffer */ - pRxd = pRxPort->pRxdRingTail; - pRxPort->pRxdRingTail = pRxd->pNextRxd; - pRxPort->RxdRingFree--; - Length = pAC->RxBufSize; - PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, - virt_to_page(pMsgBlock->data), - ((unsigned long) pMsgBlock->data & - ~PAGE_MASK), - pAC->RxBufSize - 2, - PCI_DMA_FROMDEVICE); - - pRxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); - pRxd->VDataHigh = (SK_U32) (PhysAddr >> 32); - pRxd->pMBuf = pMsgBlock; - pRxd->RBControl = BMU_OWN | - BMU_STF | - BMU_IRQ_EOF | - BMU_TCP_CHECK | - Length; - return (SK_TRUE); - -} /* FillRxDescriptor */ - - -/***************************************************************************** - * - * ReQueueRxBuffer - fill one buffer back into the receive ring - * - * Description: - * Fill a given buffer back into the rx ring. The buffer - * has been previously allocated and aligned, and its phys. - * address calculated, so this is no more necessary. - * - * Returns: N/A - */ -static void ReQueueRxBuffer( -SK_AC *pAC, /* pointer to the adapter context struct */ -RX_PORT *pRxPort, /* ptr to port struct of ring to fill */ -struct sk_buff *pMsg, /* pointer to the buffer */ -SK_U32 PhysHigh, /* phys address high dword */ -SK_U32 PhysLow) /* phys address low dword */ -{ -RXD *pRxd; /* the rxd to fill */ -SK_U16 Length; /* data fragment length */ - - pRxd = pRxPort->pRxdRingTail; - pRxPort->pRxdRingTail = pRxd->pNextRxd; - pRxPort->RxdRingFree--; - Length = pAC->RxBufSize; - - pRxd->VDataLow = PhysLow; - pRxd->VDataHigh = PhysHigh; - pRxd->pMBuf = pMsg; - pRxd->RBControl = BMU_OWN | - BMU_STF | - BMU_IRQ_EOF | - BMU_TCP_CHECK | - Length; - return; -} /* ReQueueRxBuffer */ - -/***************************************************************************** - * - * ReceiveIrq - handle a receive IRQ - * - * Description: - * This function is called when a receive IRQ is set. - * It walks the receive descriptor ring and sends up all - * frames that are complete. - * - * Returns: N/A - */ -static void ReceiveIrq( - SK_AC *pAC, /* pointer to adapter context */ - RX_PORT *pRxPort, /* pointer to receive port struct */ - SK_BOOL SlowPathLock) /* indicates if SlowPathLock is needed */ -{ -RXD *pRxd; /* pointer to receive descriptors */ -SK_U32 Control; /* control field of descriptor */ -struct sk_buff *pMsg; /* pointer to message holding frame */ -struct sk_buff *pNewMsg; /* pointer to a new message for copying frame */ -int FrameLength; /* total length of received frame */ -SK_MBUF *pRlmtMbuf; /* ptr to a buffer for giving a frame to rlmt */ -SK_EVPARA EvPara; /* an event parameter union */ -unsigned long Flags; /* for spin lock */ -int PortIndex = pRxPort->PortIndex; -unsigned int Offset; -unsigned int NumBytes; -unsigned int ForRlmt; -SK_BOOL IsBc; -SK_BOOL IsMc; -SK_BOOL IsBadFrame; /* Bad frame */ - -SK_U32 FrameStat; -SK_U64 PhysAddr; - -rx_start: - /* do forever; exit if BMU_OWN found */ - for ( pRxd = pRxPort->pRxdRingHead ; - pRxPort->RxdRingFree < pAC->RxDescrPerRing ; - pRxd = pRxd->pNextRxd, - pRxPort->pRxdRingHead = pRxd, - pRxPort->RxdRingFree ++) { - - /* - * For a better understanding of this loop - * Go through every descriptor beginning at the head - * Please note: the ring might be completely received so the OWN bit - * set is not a good crirteria to leave that loop. - * Therefore the RingFree counter is used. - * On entry of this loop pRxd is a pointer to the Rxd that needs - * to be checked next. - */ - - Control = pRxd->RBControl; - - /* check if this descriptor is ready */ - if ((Control & BMU_OWN) != 0) { - /* this descriptor is not yet ready */ - /* This is the usual end of the loop */ - /* We don't need to start the ring again */ - FillRxRing(pAC, pRxPort); - return; - } - pAC->DynIrqModInfo.NbrProcessedDescr++; - - /* get length of frame and check it */ - FrameLength = Control & BMU_BBC; - if (FrameLength > pAC->RxBufSize) { - goto rx_failed; - } - - /* check for STF and EOF */ - if ((Control & (BMU_STF | BMU_EOF)) != (BMU_STF | BMU_EOF)) { - goto rx_failed; - } - - /* here we have a complete frame in the ring */ - pMsg = pRxd->pMBuf; - - FrameStat = pRxd->FrameStat; - - /* check for frame length mismatch */ -#define XMR_FS_LEN_SHIFT 18 -#define GMR_FS_LEN_SHIFT 16 - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { - if (FrameLength != (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, - ("skge: Frame length mismatch (%u/%u).\n", - FrameLength, - (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT))); - goto rx_failed; - } - } - else { - if (FrameLength != (SK_U32) (FrameStat >> GMR_FS_LEN_SHIFT)) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, - ("skge: Frame length mismatch (%u/%u).\n", - FrameLength, - (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT))); - goto rx_failed; - } - } - - /* Set Rx Status */ - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { - IsBc = (FrameStat & XMR_FS_BC) != 0; - IsMc = (FrameStat & XMR_FS_MC) != 0; - IsBadFrame = (FrameStat & - (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0; - } else { - IsBc = (FrameStat & GMR_FS_BC) != 0; - IsMc = (FrameStat & GMR_FS_MC) != 0; - IsBadFrame = (((FrameStat & GMR_FS_ANY_ERR) != 0) || - ((FrameStat & GMR_FS_RX_OK) == 0)); - } - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0, - ("Received frame of length %d on port %d\n", - FrameLength, PortIndex)); - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0, - ("Number of free rx descriptors: %d\n", - pRxPort->RxdRingFree)); -/* DumpMsg(pMsg, "Rx"); */ - - if ((Control & BMU_STAT_VAL) != BMU_STAT_VAL || (IsBadFrame)) { -#if 0 - (FrameStat & (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0) { -#endif - /* there is a receive error in this frame */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, - ("skge: Error in received frame, dropped!\n" - "Control: %x\nRxStat: %x\n", - Control, FrameStat)); - - ReQueueRxBuffer(pAC, pRxPort, pMsg, - pRxd->VDataHigh, pRxd->VDataLow); - - continue; - } - - /* - * if short frame then copy data to reduce memory waste - */ - if ((FrameLength < SK_COPY_THRESHOLD) && - ((pNewMsg = alloc_skb(FrameLength+2, GFP_ATOMIC)) != NULL)) { - /* - * Short frame detected and allocation successfull - */ - /* use new skb and copy data */ - skb_reserve(pNewMsg, 2); - skb_put(pNewMsg, FrameLength); - PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32; - PhysAddr |= (SK_U64) pRxd->VDataLow; - - pci_dma_sync_single_for_cpu(pAC->PciDev, - (dma_addr_t) PhysAddr, - FrameLength, - PCI_DMA_FROMDEVICE); - skb_copy_to_linear_data(pNewMsg, pMsg, FrameLength); - - pci_dma_sync_single_for_device(pAC->PciDev, - (dma_addr_t) PhysAddr, - FrameLength, - PCI_DMA_FROMDEVICE); - ReQueueRxBuffer(pAC, pRxPort, pMsg, - pRxd->VDataHigh, pRxd->VDataLow); - - pMsg = pNewMsg; - - } - else { - /* - * if large frame, or SKB allocation failed, pass - * the SKB directly to the networking - */ - - PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32; - PhysAddr |= (SK_U64) pRxd->VDataLow; - - /* release the DMA mapping */ - pci_unmap_single(pAC->PciDev, - PhysAddr, - pAC->RxBufSize - 2, - PCI_DMA_FROMDEVICE); - - /* set length in message */ - skb_put(pMsg, FrameLength); - } /* frame > SK_COPY_TRESHOLD */ - -#ifdef USE_SK_RX_CHECKSUM - pMsg->csum = pRxd->TcpSums & 0xffff; - pMsg->ip_summed = CHECKSUM_COMPLETE; -#else - pMsg->ip_summed = CHECKSUM_NONE; -#endif - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("V")); - ForRlmt = SK_RLMT_RX_PROTOCOL; -#if 0 - IsBc = (FrameStat & XMR_FS_BC)==XMR_FS_BC; -#endif - SK_RLMT_PRE_LOOKAHEAD(pAC, PortIndex, FrameLength, - IsBc, &Offset, &NumBytes); - if (NumBytes != 0) { -#if 0 - IsMc = (FrameStat & XMR_FS_MC)==XMR_FS_MC; -#endif - SK_RLMT_LOOKAHEAD(pAC, PortIndex, - &pMsg->data[Offset], - IsBc, IsMc, &ForRlmt); - } - if (ForRlmt == SK_RLMT_RX_PROTOCOL) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("W")); - /* send up only frames from active port */ - if ((PortIndex == pAC->ActivePort) || - (pAC->RlmtNets == 2)) { - /* frame for upper layer */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("U")); -#ifdef xDEBUG - DumpMsg(pMsg, "Rx"); -#endif - SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC, - FrameLength, pRxPort->PortIndex); - - pMsg->protocol = eth_type_trans(pMsg, - pAC->dev[pRxPort->PortIndex]); - netif_rx(pMsg); - pAC->dev[pRxPort->PortIndex]->last_rx = jiffies; - } - else { - /* drop frame */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, - ("D")); - DEV_KFREE_SKB(pMsg); - } - - } /* if not for rlmt */ - else { - /* packet for rlmt */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, ("R")); - pRlmtMbuf = SkDrvAllocRlmtMbuf(pAC, - pAC->IoBase, FrameLength); - if (pRlmtMbuf != NULL) { - pRlmtMbuf->pNext = NULL; - pRlmtMbuf->Length = FrameLength; - pRlmtMbuf->PortIdx = PortIndex; - EvPara.pParaPtr = pRlmtMbuf; - memcpy((char*)(pRlmtMbuf->pData), - (char*)(pMsg->data), - FrameLength); - - /* SlowPathLock needed? */ - if (SlowPathLock == SK_TRUE) { - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - SkEventQueue(pAC, SKGE_RLMT, - SK_RLMT_PACKET_RECEIVED, - EvPara); - pAC->CheckQueue = SK_TRUE; - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - } else { - SkEventQueue(pAC, SKGE_RLMT, - SK_RLMT_PACKET_RECEIVED, - EvPara); - pAC->CheckQueue = SK_TRUE; - } - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, - ("Q")); - } - if ((pAC->dev[pRxPort->PortIndex]->flags & - (IFF_PROMISC | IFF_ALLMULTI)) != 0 || - (ForRlmt & SK_RLMT_RX_PROTOCOL) == - SK_RLMT_RX_PROTOCOL) { - pMsg->protocol = eth_type_trans(pMsg, - pAC->dev[pRxPort->PortIndex]); - netif_rx(pMsg); - pAC->dev[pRxPort->PortIndex]->last_rx = jiffies; - } - else { - DEV_KFREE_SKB(pMsg); - } - - } /* if packet for rlmt */ - } /* for ... scanning the RXD ring */ - - /* RXD ring is empty -> fill and restart */ - FillRxRing(pAC, pRxPort); - /* do not start if called from Close */ - if (pAC->BoardLevel > SK_INIT_DATA) { - ClearAndStartRx(pAC, PortIndex); - } - return; - -rx_failed: - /* remove error frame */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR, - ("Schrottdescriptor, length: 0x%x\n", FrameLength)); - - /* release the DMA mapping */ - - PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32; - PhysAddr |= (SK_U64) pRxd->VDataLow; - pci_unmap_page(pAC->PciDev, - PhysAddr, - pAC->RxBufSize - 2, - PCI_DMA_FROMDEVICE); - DEV_KFREE_SKB_IRQ(pRxd->pMBuf); - pRxd->pMBuf = NULL; - pRxPort->RxdRingFree++; - pRxPort->pRxdRingHead = pRxd->pNextRxd; - goto rx_start; - -} /* ReceiveIrq */ - - -/***************************************************************************** - * - * ClearAndStartRx - give a start receive command to BMU, clear IRQ - * - * Description: - * This function sends a start command and a clear interrupt - * command for one receive queue to the BMU. - * - * Returns: N/A - * none - */ -static void ClearAndStartRx( -SK_AC *pAC, /* pointer to the adapter context */ -int PortIndex) /* index of the receive port (XMAC) */ -{ - SK_OUT8(pAC->IoBase, - RxQueueAddr[PortIndex]+Q_CSR, - CSR_START | CSR_IRQ_CL_F); -} /* ClearAndStartRx */ - - -/***************************************************************************** - * - * ClearTxIrq - give a clear transmit IRQ command to BMU - * - * Description: - * This function sends a clear tx IRQ command for one - * transmit queue to the BMU. - * - * Returns: N/A - */ -static void ClearTxIrq( -SK_AC *pAC, /* pointer to the adapter context */ -int PortIndex, /* index of the transmit port (XMAC) */ -int Prio) /* priority or normal queue */ -{ - SK_OUT8(pAC->IoBase, - TxQueueAddr[PortIndex][Prio]+Q_CSR, - CSR_IRQ_CL_F); -} /* ClearTxIrq */ - - -/***************************************************************************** - * - * ClearRxRing - remove all buffers from the receive ring - * - * Description: - * This function removes all receive buffers from the ring. - * The receive BMU must be stopped before calling this function. - * - * Returns: N/A - */ -static void ClearRxRing( -SK_AC *pAC, /* pointer to adapter context */ -RX_PORT *pRxPort) /* pointer to rx port struct */ -{ -RXD *pRxd; /* pointer to the current descriptor */ -unsigned long Flags; -SK_U64 PhysAddr; - - if (pRxPort->RxdRingFree == pAC->RxDescrPerRing) { - return; - } - spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags); - pRxd = pRxPort->pRxdRingHead; - do { - if (pRxd->pMBuf != NULL) { - - PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32; - PhysAddr |= (SK_U64) pRxd->VDataLow; - pci_unmap_page(pAC->PciDev, - PhysAddr, - pAC->RxBufSize - 2, - PCI_DMA_FROMDEVICE); - DEV_KFREE_SKB(pRxd->pMBuf); - pRxd->pMBuf = NULL; - } - pRxd->RBControl &= BMU_OWN; - pRxd = pRxd->pNextRxd; - pRxPort->RxdRingFree++; - } while (pRxd != pRxPort->pRxdRingTail); - pRxPort->pRxdRingTail = pRxPort->pRxdRingHead; - spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags); -} /* ClearRxRing */ - -/***************************************************************************** - * - * ClearTxRing - remove all buffers from the transmit ring - * - * Description: - * This function removes all transmit buffers from the ring. - * The transmit BMU must be stopped before calling this function - * and transmitting at the upper level must be disabled. - * The BMU own bit of all descriptors is cleared, the rest is - * done by calling FreeTxDescriptors. - * - * Returns: N/A - */ -static void ClearTxRing( -SK_AC *pAC, /* pointer to adapter context */ -TX_PORT *pTxPort) /* pointer to tx prt struct */ -{ -TXD *pTxd; /* pointer to the current descriptor */ -int i; -unsigned long Flags; - - spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags); - pTxd = pTxPort->pTxdRingHead; - for (i=0; i<pAC->TxDescrPerRing; i++) { - pTxd->TBControl &= ~BMU_OWN; - pTxd = pTxd->pNextTxd; - } - FreeTxDescriptors(pAC, pTxPort); - spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); -} /* ClearTxRing */ - -/***************************************************************************** - * - * SkGeSetMacAddr - Set the hardware MAC address - * - * Description: - * This function sets the MAC address used by the adapter. - * - * Returns: - * 0, if everything is ok - * !=0, on error - */ -static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p) -{ - -DEV_NET *pNet = netdev_priv(dev); -SK_AC *pAC = pNet->pAC; - -struct sockaddr *addr = p; -unsigned long Flags; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeSetMacAddr starts now...\n")); - if(netif_running(dev)) - return -EBUSY; - - memcpy(dev->dev_addr, addr->sa_data,dev->addr_len); - - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - - if (pAC->RlmtNets == 2) - SkAddrOverride(pAC, pAC->IoBase, pNet->NetNr, - (SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS); - else - SkAddrOverride(pAC, pAC->IoBase, pAC->ActivePort, - (SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS); - - - - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - return 0; -} /* SkGeSetMacAddr */ - - -/***************************************************************************** - * - * SkGeSetRxMode - set receive mode - * - * Description: - * This function sets the receive mode of an adapter. The adapter - * supports promiscuous mode, allmulticast mode and a number of - * multicast addresses. If more multicast addresses the available - * are selected, a hash function in the hardware is used. - * - * Returns: - * 0, if everything is ok - * !=0, on error - */ -static void SkGeSetRxMode(struct SK_NET_DEVICE *dev) -{ - -DEV_NET *pNet; -SK_AC *pAC; - -struct dev_mc_list *pMcList; -int i; -int PortIdx; -unsigned long Flags; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeSetRxMode starts now... ")); - - pNet = netdev_priv(dev); - pAC = pNet->pAC; - if (pAC->RlmtNets == 1) - PortIdx = pAC->ActivePort; - else - PortIdx = pNet->NetNr; - - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - if (dev->flags & IFF_PROMISC) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("PROMISCUOUS mode\n")); - SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx, - SK_PROM_MODE_LLC); - } else if (dev->flags & IFF_ALLMULTI) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("ALLMULTI mode\n")); - SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx, - SK_PROM_MODE_ALL_MC); - } else { - SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx, - SK_PROM_MODE_NONE); - SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0); - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("Number of MC entries: %d ", dev->mc_count)); - - pMcList = dev->mc_list; - for (i=0; i<dev->mc_count; i++, pMcList = pMcList->next) { - SkAddrMcAdd(pAC, pAC->IoBase, PortIdx, - (SK_MAC_ADDR*)pMcList->dmi_addr, 0); - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MCA, - ("%02x:%02x:%02x:%02x:%02x:%02x\n", - pMcList->dmi_addr[0], - pMcList->dmi_addr[1], - pMcList->dmi_addr[2], - pMcList->dmi_addr[3], - pMcList->dmi_addr[4], - pMcList->dmi_addr[5])); - } - SkAddrMcUpdate(pAC, pAC->IoBase, PortIdx); - } - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - - return; -} /* SkGeSetRxMode */ - - -/***************************************************************************** - * - * SkGeChangeMtu - set the MTU to another value - * - * Description: - * This function sets is called whenever the MTU size is changed - * (ifconfig mtu xxx dev ethX). If the MTU is bigger than standard - * ethernet MTU size, long frame support is activated. - * - * Returns: - * 0, if everything is ok - * !=0, on error - */ -static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int NewMtu) -{ -DEV_NET *pNet; -struct net_device *pOtherDev; -SK_AC *pAC; -unsigned long Flags; -int i; -SK_EVPARA EvPara; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeChangeMtu starts now...\n")); - - pNet = netdev_priv(dev); - pAC = pNet->pAC; - - if ((NewMtu < 68) || (NewMtu > SK_JUMBO_MTU)) { - return -EINVAL; - } - - if(pAC->BoardLevel != SK_INIT_RUN) { - return -EINVAL; - } - -#ifdef SK_DIAG_SUPPORT - if (pAC->DiagModeActive == DIAG_ACTIVE) { - if (pAC->DiagFlowCtrl == SK_FALSE) { - return -1; /* still in use, deny any actions of MTU */ - } else { - pAC->DiagFlowCtrl = SK_FALSE; - } - } -#endif - - pOtherDev = pAC->dev[1 - pNet->NetNr]; - - if ( netif_running(pOtherDev) && (pOtherDev->mtu > 1500) - && (NewMtu <= 1500)) - return 0; - - pAC->RxBufSize = NewMtu + 32; - dev->mtu = NewMtu; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("New MTU: %d\n", NewMtu)); - - /* - ** Prevent any reconfiguration while changing the MTU - ** by disabling any interrupts - */ - SK_OUT32(pAC->IoBase, B0_IMSK, 0); - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - - /* - ** Notify RLMT that any ports are to be stopped - */ - EvPara.Para32[0] = 0; - EvPara.Para32[1] = -1; - if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - EvPara.Para32[0] = 1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - } else { - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - } - - /* - ** After calling the SkEventDispatcher(), RLMT is aware about - ** the stopped ports -> configuration can take place! - */ - SkEventDispatcher(pAC, pAC->IoBase); - - for (i=0; i<pAC->GIni.GIMacsFound; i++) { - spin_lock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock); - netif_stop_queue(pAC->dev[i]); - - } - - /* - ** Depending on the desired MTU size change, a different number of - ** RX buffers need to be allocated - */ - if (NewMtu > 1500) { - /* - ** Use less rx buffers - */ - for (i=0; i<pAC->GIni.GIMacsFound; i++) { - if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { - pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - - (pAC->RxDescrPerRing / 4); - } else { - if (i == pAC->ActivePort) { - pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - - (pAC->RxDescrPerRing / 4); - } else { - pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - - (pAC->RxDescrPerRing / 10); - } - } - } - } else { - /* - ** Use the normal amount of rx buffers - */ - for (i=0; i<pAC->GIni.GIMacsFound; i++) { - if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { - pAC->RxPort[i].RxFillLimit = 1; - } else { - if (i == pAC->ActivePort) { - pAC->RxPort[i].RxFillLimit = 1; - } else { - pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - - (pAC->RxDescrPerRing / 4); - } - } - } - } - - SkGeDeInit(pAC, pAC->IoBase); - - /* - ** enable/disable hardware support for long frames - */ - if (NewMtu > 1500) { -// pAC->JumboActivated = SK_TRUE; /* is never set back !!! */ - pAC->GIni.GIPortUsage = SK_JUMBO_LINK; - } else { - if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { - pAC->GIni.GIPortUsage = SK_MUL_LINK; - } else { - pAC->GIni.GIPortUsage = SK_RED_LINK; - } - } - - SkGeInit( pAC, pAC->IoBase, SK_INIT_IO); - SkI2cInit( pAC, pAC->IoBase, SK_INIT_IO); - SkEventInit(pAC, pAC->IoBase, SK_INIT_IO); - SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO); - SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO); - SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO); - SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO); - - /* - ** tschilling: - ** Speed and others are set back to default in level 1 init! - */ - GetConfiguration(pAC); - - SkGeInit( pAC, pAC->IoBase, SK_INIT_RUN); - SkI2cInit( pAC, pAC->IoBase, SK_INIT_RUN); - SkEventInit(pAC, pAC->IoBase, SK_INIT_RUN); - SkPnmiInit( pAC, pAC->IoBase, SK_INIT_RUN); - SkAddrInit( pAC, pAC->IoBase, SK_INIT_RUN); - SkRlmtInit( pAC, pAC->IoBase, SK_INIT_RUN); - SkTimerInit(pAC, pAC->IoBase, SK_INIT_RUN); - - /* - ** clear and reinit the rx rings here - */ - for (i=0; i<pAC->GIni.GIMacsFound; i++) { - ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE); - ClearRxRing(pAC, &pAC->RxPort[i]); - FillRxRing(pAC, &pAC->RxPort[i]); - - /* - ** Enable transmit descriptor polling - */ - SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE); - FillRxRing(pAC, &pAC->RxPort[i]); - }; - - SkGeYellowLED(pAC, pAC->IoBase, 1); - SkDimEnableModerationIfNeeded(pAC); - SkDimDisplayModerationSettings(pAC); - - netif_start_queue(pAC->dev[pNet->PortNr]); - for (i=pAC->GIni.GIMacsFound-1; i>=0; i--) { - spin_unlock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock); - } - - /* - ** Enable Interrupts again - */ - SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask); - SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK); - - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); - SkEventDispatcher(pAC, pAC->IoBase); - - /* - ** Notify RLMT about the changing and restarting one (or more) ports - */ - if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { - EvPara.Para32[0] = pAC->RlmtNets; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS, EvPara); - EvPara.Para32[0] = pNet->PortNr; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); - - if (netif_running(pOtherDev)) { - DEV_NET *pOtherNet = netdev_priv(pOtherDev); - EvPara.Para32[0] = pOtherNet->PortNr; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); - } - } else { - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); - } - - SkEventDispatcher(pAC, pAC->IoBase); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - - /* - ** While testing this driver with latest kernel 2.5 (2.5.70), it - ** seems as if upper layers have a problem to handle a successful - ** return value of '0'. If such a zero is returned, the complete - ** system hangs for several minutes (!), which is in acceptable. - ** - ** Currently it is not clear, what the exact reason for this problem - ** is. The implemented workaround for 2.5 is to return the desired - ** new MTU size if all needed changes for the new MTU size where - ** performed. In kernels 2.2 and 2.4, a zero value is returned, - ** which indicates the successful change of the mtu-size. - */ - return NewMtu; - -} /* SkGeChangeMtu */ - - -/***************************************************************************** - * - * SkGeStats - return ethernet device statistics - * - * Description: - * This function return statistic data about the ethernet device - * to the operating system. - * - * Returns: - * pointer to the statistic structure. - */ -static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev) -{ -DEV_NET *pNet = netdev_priv(dev); -SK_AC *pAC = pNet->pAC; -SK_PNMI_STRUCT_DATA *pPnmiStruct; /* structure for all Pnmi-Data */ -SK_PNMI_STAT *pPnmiStat; /* pointer to virtual XMAC stat. data */ -SK_PNMI_CONF *pPnmiConf; /* pointer to virtual link config. */ -unsigned int Size; /* size of pnmi struct */ -unsigned long Flags; /* for spin lock */ - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeStats starts now...\n")); - pPnmiStruct = &pAC->PnmiStruct; - -#ifdef SK_DIAG_SUPPORT - if ((pAC->DiagModeActive == DIAG_NOTACTIVE) && - (pAC->BoardLevel == SK_INIT_RUN)) { -#endif - SK_MEMSET(pPnmiStruct, 0, sizeof(SK_PNMI_STRUCT_DATA)); - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - Size = SK_PNMI_STRUCT_SIZE; - SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, pNet->NetNr); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); -#ifdef SK_DIAG_SUPPORT - } -#endif - - pPnmiStat = &pPnmiStruct->Stat[0]; - pPnmiConf = &pPnmiStruct->Conf[0]; - - pAC->stats.rx_packets = (SK_U32) pPnmiStruct->RxDeliveredCts & 0xFFFFFFFF; - pAC->stats.tx_packets = (SK_U32) pPnmiStat->StatTxOkCts & 0xFFFFFFFF; - pAC->stats.rx_bytes = (SK_U32) pPnmiStruct->RxOctetsDeliveredCts; - pAC->stats.tx_bytes = (SK_U32) pPnmiStat->StatTxOctetsOkCts; - - if (dev->mtu <= 1500) { - pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF; - } else { - pAC->stats.rx_errors = (SK_U32) ((pPnmiStruct->InErrorsCts - - pPnmiStat->StatRxTooLongCts) & 0xFFFFFFFF); - } - - - if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC && pAC->HWRevision < 12) - pAC->stats.rx_errors = pAC->stats.rx_errors - pPnmiStat->StatRxShortsCts; - - pAC->stats.tx_errors = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF; - pAC->stats.rx_dropped = (SK_U32) pPnmiStruct->RxNoBufCts & 0xFFFFFFFF; - pAC->stats.tx_dropped = (SK_U32) pPnmiStruct->TxNoBufCts & 0xFFFFFFFF; - pAC->stats.multicast = (SK_U32) pPnmiStat->StatRxMulticastOkCts & 0xFFFFFFFF; - pAC->stats.collisions = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF; - - /* detailed rx_errors: */ - pAC->stats.rx_length_errors = (SK_U32) pPnmiStat->StatRxRuntCts & 0xFFFFFFFF; - pAC->stats.rx_over_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF; - pAC->stats.rx_crc_errors = (SK_U32) pPnmiStat->StatRxFcsCts & 0xFFFFFFFF; - pAC->stats.rx_frame_errors = (SK_U32) pPnmiStat->StatRxFramingCts & 0xFFFFFFFF; - pAC->stats.rx_fifo_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF; - pAC->stats.rx_missed_errors = (SK_U32) pPnmiStat->StatRxMissedCts & 0xFFFFFFFF; - - /* detailed tx_errors */ - pAC->stats.tx_aborted_errors = (SK_U32) 0; - pAC->stats.tx_carrier_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF; - pAC->stats.tx_fifo_errors = (SK_U32) pPnmiStat->StatTxFifoUnderrunCts & 0xFFFFFFFF; - pAC->stats.tx_heartbeat_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF; - pAC->stats.tx_window_errors = (SK_U32) 0; - - return(&pAC->stats); -} /* SkGeStats */ - -/* - * Basic MII register access - */ -static int SkGeMiiIoctl(struct net_device *dev, - struct mii_ioctl_data *data, int cmd) -{ - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - SK_IOC IoC = pAC->IoBase; - int Port = pNet->PortNr; - SK_GEPORT *pPrt = &pAC->GIni.GP[Port]; - unsigned long Flags; - int err = 0; - int reg = data->reg_num & 0x1f; - SK_U16 val = data->val_in; - - if (!netif_running(dev)) - return -ENODEV; /* Phy still in reset */ - - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - switch(cmd) { - case SIOCGMIIPHY: - data->phy_id = pPrt->PhyAddr; - - /* fallthru */ - case SIOCGMIIREG: - if (pAC->GIni.GIGenesis) - SkXmPhyRead(pAC, IoC, Port, reg, &val); - else - SkGmPhyRead(pAC, IoC, Port, reg, &val); - - data->val_out = val; - break; - - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - err = -EPERM; - - else if (pAC->GIni.GIGenesis) - SkXmPhyWrite(pAC, IoC, Port, reg, val); - else - SkGmPhyWrite(pAC, IoC, Port, reg, val); - break; - default: - err = -EOPNOTSUPP; - } - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - return err; -} - - -/***************************************************************************** - * - * SkGeIoctl - IO-control function - * - * Description: - * This function is called if an ioctl is issued on the device. - * There are three subfunction for reading, writing and test-writing - * the private MIB data structure (useful for SysKonnect-internal tools). - * - * Returns: - * 0, if everything is ok - * !=0, on error - */ -static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd) -{ -DEV_NET *pNet; -SK_AC *pAC; -void *pMemBuf; -struct pci_dev *pdev = NULL; -SK_GE_IOCTL Ioctl; -unsigned int Err = 0; -int Size = 0; -int Ret = 0; -unsigned int Length = 0; -int HeaderLength = sizeof(SK_U32) + sizeof(SK_U32); - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeIoctl starts now...\n")); - - pNet = netdev_priv(dev); - pAC = pNet->pAC; - - if (cmd == SIOCGMIIPHY || cmd == SIOCSMIIREG || cmd == SIOCGMIIREG) - return SkGeMiiIoctl(dev, if_mii(rq), cmd); - - if(copy_from_user(&Ioctl, rq->ifr_data, sizeof(SK_GE_IOCTL))) { - return -EFAULT; - } - - switch(cmd) { - case SK_IOCTL_SETMIB: - case SK_IOCTL_PRESETMIB: - if (!capable(CAP_NET_ADMIN)) return -EPERM; - case SK_IOCTL_GETMIB: - if(copy_from_user(&pAC->PnmiStruct, Ioctl.pData, - Ioctl.Len<sizeof(pAC->PnmiStruct)? - Ioctl.Len : sizeof(pAC->PnmiStruct))) { - return -EFAULT; - } - Size = SkGeIocMib(pNet, Ioctl.Len, cmd); - if(copy_to_user(Ioctl.pData, &pAC->PnmiStruct, - Ioctl.Len<Size? Ioctl.Len : Size)) { - return -EFAULT; - } - Ioctl.Len = Size; - if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) { - return -EFAULT; - } - break; - case SK_IOCTL_GEN: - if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) { - Length = Ioctl.Len; - } else { - Length = sizeof(pAC->PnmiStruct) + HeaderLength; - } - if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) { - return -ENOMEM; - } - if(copy_from_user(pMemBuf, Ioctl.pData, Length)) { - Err = -EFAULT; - goto fault_gen; - } - if ((Ret = SkPnmiGenIoctl(pAC, pAC->IoBase, pMemBuf, &Length, 0)) < 0) { - Err = -EFAULT; - goto fault_gen; - } - if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) { - Err = -EFAULT; - goto fault_gen; - } - Ioctl.Len = Length; - if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) { - Err = -EFAULT; - goto fault_gen; - } -fault_gen: - kfree(pMemBuf); /* cleanup everything */ - break; -#ifdef SK_DIAG_SUPPORT - case SK_IOCTL_DIAG: - if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) { - Length = Ioctl.Len; - } else { - Length = sizeof(pAC->PnmiStruct) + HeaderLength; - } - if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) { - return -ENOMEM; - } - if(copy_from_user(pMemBuf, Ioctl.pData, Length)) { - Err = -EFAULT; - goto fault_diag; - } - pdev = pAC->PciDev; - Length = 3 * sizeof(SK_U32); /* Error, Bus and Device */ - /* - ** While coding this new IOCTL interface, only a few lines of code - ** are to to be added. Therefore no dedicated function has been - ** added. If more functionality is added, a separate function - ** should be used... - */ - * ((SK_U32 *)pMemBuf) = 0; - * ((SK_U32 *)pMemBuf + 1) = pdev->bus->number; - * ((SK_U32 *)pMemBuf + 2) = ParseDeviceNbrFromSlotName(pci_name(pdev)); - if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) { - Err = -EFAULT; - goto fault_diag; - } - Ioctl.Len = Length; - if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) { - Err = -EFAULT; - goto fault_diag; - } -fault_diag: - kfree(pMemBuf); /* cleanup everything */ - break; -#endif - default: - Err = -EOPNOTSUPP; - } - - return(Err); - -} /* SkGeIoctl */ - - -/***************************************************************************** - * - * SkGeIocMib - handle a GetMib, SetMib- or PresetMib-ioctl message - * - * Description: - * This function reads/writes the MIB data using PNMI (Private Network - * Management Interface). - * The destination for the data must be provided with the - * ioctl call and is given to the driver in the form of - * a user space address. - * Copying from the user-provided data area into kernel messages - * and back is done by copy_from_user and copy_to_user calls in - * SkGeIoctl. - * - * Returns: - * returned size from PNMI call - */ -static int SkGeIocMib( -DEV_NET *pNet, /* pointer to the adapter context */ -unsigned int Size, /* length of ioctl data */ -int mode) /* flag for set/preset */ -{ -unsigned long Flags; /* for spin lock */ -SK_AC *pAC; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeIocMib starts now...\n")); - pAC = pNet->pAC; - /* access MIB */ - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - switch(mode) { - case SK_IOCTL_GETMIB: - SkPnmiGetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size, - pNet->NetNr); - break; - case SK_IOCTL_PRESETMIB: - SkPnmiPreSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size, - pNet->NetNr); - break; - case SK_IOCTL_SETMIB: - SkPnmiSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size, - pNet->NetNr); - break; - default: - break; - } - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("MIB data access succeeded\n")); - return (Size); -} /* SkGeIocMib */ - - -/***************************************************************************** - * - * GetConfiguration - read configuration information - * - * Description: - * This function reads per-adapter configuration information from - * the options provided on the command line. - * - * Returns: - * none - */ -static void GetConfiguration( -SK_AC *pAC) /* pointer to the adapter context structure */ -{ -SK_I32 Port; /* preferred port */ -SK_BOOL AutoSet; -SK_BOOL DupSet; -int LinkSpeed = SK_LSPEED_AUTO; /* Link speed */ -int AutoNeg = 1; /* autoneg off (0) or on (1) */ -int DuplexCap = 0; /* 0=both,1=full,2=half */ -int FlowCtrl = SK_FLOW_MODE_SYM_OR_REM; /* FlowControl */ -int MSMode = SK_MS_MODE_AUTO; /* master/slave mode */ - -SK_BOOL IsConTypeDefined = SK_TRUE; -SK_BOOL IsLinkSpeedDefined = SK_TRUE; -SK_BOOL IsFlowCtrlDefined = SK_TRUE; -SK_BOOL IsRoleDefined = SK_TRUE; -SK_BOOL IsModeDefined = SK_TRUE; -/* - * The two parameters AutoNeg. and DuplexCap. map to one configuration - * parameter. The mapping is described by this table: - * DuplexCap -> | both | full | half | - * AutoNeg | | | | - * ----------------------------------------------------------------- - * Off | illegal | Full | Half | - * ----------------------------------------------------------------- - * On | AutoBoth | AutoFull | AutoHalf | - * ----------------------------------------------------------------- - * Sense | AutoSense | AutoSense | AutoSense | - */ -int Capabilities[3][3] = - { { -1, SK_LMODE_FULL , SK_LMODE_HALF }, - {SK_LMODE_AUTOBOTH , SK_LMODE_AUTOFULL , SK_LMODE_AUTOHALF }, - {SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE} }; - -#define DC_BOTH 0 -#define DC_FULL 1 -#define DC_HALF 2 -#define AN_OFF 0 -#define AN_ON 1 -#define AN_SENS 2 -#define M_CurrPort pAC->GIni.GP[Port] - - - /* - ** Set the default values first for both ports! - */ - for (Port = 0; Port < SK_MAX_MACS; Port++) { - M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH]; - M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM; - M_CurrPort.PMSMode = SK_MS_MODE_AUTO; - M_CurrPort.PLinkSpeed = SK_LSPEED_AUTO; - } - - /* - ** Check merged parameter ConType. If it has not been used, - ** verify any other parameter (e.g. AutoNeg) and use default values. - ** - ** Stating both ConType and other lowlevel link parameters is also - ** possible. If this is the case, the passed ConType-parameter is - ** overwritten by the lowlevel link parameter. - ** - ** The following settings are used for a merged ConType-parameter: - ** - ** ConType DupCap AutoNeg FlowCtrl Role Speed - ** ------- ------ ------- -------- ---------- ----- - ** Auto Both On SymOrRem Auto Auto - ** 100FD Full Off None <ignored> 100 - ** 100HD Half Off None <ignored> 100 - ** 10FD Full Off None <ignored> 10 - ** 10HD Half Off None <ignored> 10 - ** - ** This ConType parameter is used for all ports of the adapter! - */ - if ( (ConType != NULL) && - (pAC->Index < SK_MAX_CARD_PARAM) && - (ConType[pAC->Index] != NULL) ) { - - /* Check chipset family */ - if ((!pAC->ChipsetType) && - (strcmp(ConType[pAC->Index],"Auto")!=0) && - (strcmp(ConType[pAC->Index],"")!=0)) { - /* Set the speed parameter back */ - printk("sk98lin: Illegal value \"%s\" " - "for ConType." - " Using Auto.\n", - ConType[pAC->Index]); - - sprintf(ConType[pAC->Index], "Auto"); - } - - if (strcmp(ConType[pAC->Index],"")==0) { - IsConTypeDefined = SK_FALSE; /* No ConType defined */ - } else if (strcmp(ConType[pAC->Index],"Auto")==0) { - for (Port = 0; Port < SK_MAX_MACS; Port++) { - M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH]; - M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM; - M_CurrPort.PMSMode = SK_MS_MODE_AUTO; - M_CurrPort.PLinkSpeed = SK_LSPEED_AUTO; - } - } else if (strcmp(ConType[pAC->Index],"100FD")==0) { - for (Port = 0; Port < SK_MAX_MACS; Port++) { - M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL]; - M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE; - M_CurrPort.PMSMode = SK_MS_MODE_AUTO; - M_CurrPort.PLinkSpeed = SK_LSPEED_100MBPS; - } - } else if (strcmp(ConType[pAC->Index],"100HD")==0) { - for (Port = 0; Port < SK_MAX_MACS; Port++) { - M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF]; - M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE; - M_CurrPort.PMSMode = SK_MS_MODE_AUTO; - M_CurrPort.PLinkSpeed = SK_LSPEED_100MBPS; - } - } else if (strcmp(ConType[pAC->Index],"10FD")==0) { - for (Port = 0; Port < SK_MAX_MACS; Port++) { - M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL]; - M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE; - M_CurrPort.PMSMode = SK_MS_MODE_AUTO; - M_CurrPort.PLinkSpeed = SK_LSPEED_10MBPS; - } - } else if (strcmp(ConType[pAC->Index],"10HD")==0) { - for (Port = 0; Port < SK_MAX_MACS; Port++) { - M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF]; - M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE; - M_CurrPort.PMSMode = SK_MS_MODE_AUTO; - M_CurrPort.PLinkSpeed = SK_LSPEED_10MBPS; - } - } else { - printk("sk98lin: Illegal value \"%s\" for ConType\n", - ConType[pAC->Index]); - IsConTypeDefined = SK_FALSE; /* Wrong ConType defined */ - } - } else { - IsConTypeDefined = SK_FALSE; /* No ConType defined */ - } - - /* - ** Parse any parameter settings for port A: - ** a) any LinkSpeed stated? - */ - if (Speed_A != NULL && pAC->Index<SK_MAX_CARD_PARAM && - Speed_A[pAC->Index] != NULL) { - if (strcmp(Speed_A[pAC->Index],"")==0) { - IsLinkSpeedDefined = SK_FALSE; - } else if (strcmp(Speed_A[pAC->Index],"Auto")==0) { - LinkSpeed = SK_LSPEED_AUTO; - } else if (strcmp(Speed_A[pAC->Index],"10")==0) { - LinkSpeed = SK_LSPEED_10MBPS; - } else if (strcmp(Speed_A[pAC->Index],"100")==0) { - LinkSpeed = SK_LSPEED_100MBPS; - } else if (strcmp(Speed_A[pAC->Index],"1000")==0) { - LinkSpeed = SK_LSPEED_1000MBPS; - } else { - printk("sk98lin: Illegal value \"%s\" for Speed_A\n", - Speed_A[pAC->Index]); - IsLinkSpeedDefined = SK_FALSE; - } - } else { - IsLinkSpeedDefined = SK_FALSE; - } - - /* - ** Check speed parameter: - ** Only copper type adapter and GE V2 cards - */ - if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) && - ((LinkSpeed != SK_LSPEED_AUTO) && - (LinkSpeed != SK_LSPEED_1000MBPS))) { - printk("sk98lin: Illegal value for Speed_A. " - "Not a copper card or GE V2 card\n Using " - "speed 1000\n"); - LinkSpeed = SK_LSPEED_1000MBPS; - } - - /* - ** Decide whether to set new config value if somethig valid has - ** been received. - */ - if (IsLinkSpeedDefined) { - pAC->GIni.GP[0].PLinkSpeed = LinkSpeed; - } - - /* - ** b) Any Autonegotiation and DuplexCapabilities set? - ** Please note that both belong together... - */ - AutoNeg = AN_ON; /* tschilling: Default: Autonegotiation on! */ - AutoSet = SK_FALSE; - if (AutoNeg_A != NULL && pAC->Index<SK_MAX_CARD_PARAM && - AutoNeg_A[pAC->Index] != NULL) { - AutoSet = SK_TRUE; - if (strcmp(AutoNeg_A[pAC->Index],"")==0) { - AutoSet = SK_FALSE; - } else if (strcmp(AutoNeg_A[pAC->Index],"On")==0) { - AutoNeg = AN_ON; - } else if (strcmp(AutoNeg_A[pAC->Index],"Off")==0) { - AutoNeg = AN_OFF; - } else if (strcmp(AutoNeg_A[pAC->Index],"Sense")==0) { - AutoNeg = AN_SENS; - } else { - printk("sk98lin: Illegal value \"%s\" for AutoNeg_A\n", - AutoNeg_A[pAC->Index]); - } - } - - DuplexCap = DC_BOTH; - DupSet = SK_FALSE; - if (DupCap_A != NULL && pAC->Index<SK_MAX_CARD_PARAM && - DupCap_A[pAC->Index] != NULL) { - DupSet = SK_TRUE; - if (strcmp(DupCap_A[pAC->Index],"")==0) { - DupSet = SK_FALSE; - } else if (strcmp(DupCap_A[pAC->Index],"Both")==0) { - DuplexCap = DC_BOTH; - } else if (strcmp(DupCap_A[pAC->Index],"Full")==0) { - DuplexCap = DC_FULL; - } else if (strcmp(DupCap_A[pAC->Index],"Half")==0) { - DuplexCap = DC_HALF; - } else { - printk("sk98lin: Illegal value \"%s\" for DupCap_A\n", - DupCap_A[pAC->Index]); - } - } - - /* - ** Check for illegal combinations - */ - if ((LinkSpeed == SK_LSPEED_1000MBPS) && - ((DuplexCap == SK_LMODE_STAT_AUTOHALF) || - (DuplexCap == SK_LMODE_STAT_HALF)) && - (pAC->ChipsetType)) { - printk("sk98lin: Half Duplex not possible with Gigabit speed!\n" - " Using Full Duplex.\n"); - DuplexCap = DC_FULL; - } - - if ( AutoSet && AutoNeg==AN_SENS && DupSet) { - printk("sk98lin, Port A: DuplexCapabilities" - " ignored using Sense mode\n"); - } - - if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){ - printk("sk98lin: Port A: Illegal combination" - " of values AutoNeg. and DuplexCap.\n Using " - "Full Duplex\n"); - DuplexCap = DC_FULL; - } - - if (AutoSet && AutoNeg==AN_OFF && !DupSet) { - DuplexCap = DC_FULL; - } - - if (!AutoSet && DupSet) { - printk("sk98lin: Port A: Duplex setting not" - " possible in\n default AutoNegotiation mode" - " (Sense).\n Using AutoNegotiation On\n"); - AutoNeg = AN_ON; - } - - /* - ** set the desired mode - */ - if (AutoSet || DupSet) { - pAC->GIni.GP[0].PLinkModeConf = Capabilities[AutoNeg][DuplexCap]; - } - - /* - ** c) Any Flowcontrol-parameter set? - */ - if (FlowCtrl_A != NULL && pAC->Index<SK_MAX_CARD_PARAM && - FlowCtrl_A[pAC->Index] != NULL) { - if (strcmp(FlowCtrl_A[pAC->Index],"") == 0) { - IsFlowCtrlDefined = SK_FALSE; - } else if (strcmp(FlowCtrl_A[pAC->Index],"SymOrRem") == 0) { - FlowCtrl = SK_FLOW_MODE_SYM_OR_REM; - } else if (strcmp(FlowCtrl_A[pAC->Index],"Sym")==0) { - FlowCtrl = SK_FLOW_MODE_SYMMETRIC; - } else if (strcmp(FlowCtrl_A[pAC->Index],"LocSend")==0) { - FlowCtrl = SK_FLOW_MODE_LOC_SEND; - } else if (strcmp(FlowCtrl_A[pAC->Index],"None")==0) { - FlowCtrl = SK_FLOW_MODE_NONE; - } else { - printk("sk98lin: Illegal value \"%s\" for FlowCtrl_A\n", - FlowCtrl_A[pAC->Index]); - IsFlowCtrlDefined = SK_FALSE; - } - } else { - IsFlowCtrlDefined = SK_FALSE; - } - - if (IsFlowCtrlDefined) { - if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) { - printk("sk98lin: Port A: FlowControl" - " impossible without AutoNegotiation," - " disabled\n"); - FlowCtrl = SK_FLOW_MODE_NONE; - } - pAC->GIni.GP[0].PFlowCtrlMode = FlowCtrl; - } - - /* - ** d) What is with the RoleParameter? - */ - if (Role_A != NULL && pAC->Index<SK_MAX_CARD_PARAM && - Role_A[pAC->Index] != NULL) { - if (strcmp(Role_A[pAC->Index],"")==0) { - IsRoleDefined = SK_FALSE; - } else if (strcmp(Role_A[pAC->Index],"Auto")==0) { - MSMode = SK_MS_MODE_AUTO; - } else if (strcmp(Role_A[pAC->Index],"Master")==0) { - MSMode = SK_MS_MODE_MASTER; - } else if (strcmp(Role_A[pAC->Index],"Slave")==0) { - MSMode = SK_MS_MODE_SLAVE; - } else { - printk("sk98lin: Illegal value \"%s\" for Role_A\n", - Role_A[pAC->Index]); - IsRoleDefined = SK_FALSE; - } - } else { - IsRoleDefined = SK_FALSE; - } - - if (IsRoleDefined == SK_TRUE) { - pAC->GIni.GP[0].PMSMode = MSMode; - } - - - - /* - ** Parse any parameter settings for port B: - ** a) any LinkSpeed stated? - */ - IsConTypeDefined = SK_TRUE; - IsLinkSpeedDefined = SK_TRUE; - IsFlowCtrlDefined = SK_TRUE; - IsModeDefined = SK_TRUE; - - if (Speed_B != NULL && pAC->Index<SK_MAX_CARD_PARAM && - Speed_B[pAC->Index] != NULL) { - if (strcmp(Speed_B[pAC->Index],"")==0) { - IsLinkSpeedDefined = SK_FALSE; - } else if (strcmp(Speed_B[pAC->Index],"Auto")==0) { - LinkSpeed = SK_LSPEED_AUTO; - } else if (strcmp(Speed_B[pAC->Index],"10")==0) { - LinkSpeed = SK_LSPEED_10MBPS; - } else if (strcmp(Speed_B[pAC->Index],"100")==0) { - LinkSpeed = SK_LSPEED_100MBPS; - } else if (strcmp(Speed_B[pAC->Index],"1000")==0) { - LinkSpeed = SK_LSPEED_1000MBPS; - } else { - printk("sk98lin: Illegal value \"%s\" for Speed_B\n", - Speed_B[pAC->Index]); - IsLinkSpeedDefined = SK_FALSE; - } - } else { - IsLinkSpeedDefined = SK_FALSE; - } - - /* - ** Check speed parameter: - ** Only copper type adapter and GE V2 cards - */ - if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) && - ((LinkSpeed != SK_LSPEED_AUTO) && - (LinkSpeed != SK_LSPEED_1000MBPS))) { - printk("sk98lin: Illegal value for Speed_B. " - "Not a copper card or GE V2 card\n Using " - "speed 1000\n"); - LinkSpeed = SK_LSPEED_1000MBPS; - } - - /* - ** Decide whether to set new config value if somethig valid has - ** been received. - */ - if (IsLinkSpeedDefined) { - pAC->GIni.GP[1].PLinkSpeed = LinkSpeed; - } - - /* - ** b) Any Autonegotiation and DuplexCapabilities set? - ** Please note that both belong together... - */ - AutoNeg = AN_SENS; /* default: do auto Sense */ - AutoSet = SK_FALSE; - if (AutoNeg_B != NULL && pAC->Index<SK_MAX_CARD_PARAM && - AutoNeg_B[pAC->Index] != NULL) { - AutoSet = SK_TRUE; - if (strcmp(AutoNeg_B[pAC->Index],"")==0) { - AutoSet = SK_FALSE; - } else if (strcmp(AutoNeg_B[pAC->Index],"On")==0) { - AutoNeg = AN_ON; - } else if (strcmp(AutoNeg_B[pAC->Index],"Off")==0) { - AutoNeg = AN_OFF; - } else if (strcmp(AutoNeg_B[pAC->Index],"Sense")==0) { - AutoNeg = AN_SENS; - } else { - printk("sk98lin: Illegal value \"%s\" for AutoNeg_B\n", - AutoNeg_B[pAC->Index]); - } - } - - DuplexCap = DC_BOTH; - DupSet = SK_FALSE; - if (DupCap_B != NULL && pAC->Index<SK_MAX_CARD_PARAM && - DupCap_B[pAC->Index] != NULL) { - DupSet = SK_TRUE; - if (strcmp(DupCap_B[pAC->Index],"")==0) { - DupSet = SK_FALSE; - } else if (strcmp(DupCap_B[pAC->Index],"Both")==0) { - DuplexCap = DC_BOTH; - } else if (strcmp(DupCap_B[pAC->Index],"Full")==0) { - DuplexCap = DC_FULL; - } else if (strcmp(DupCap_B[pAC->Index],"Half")==0) { - DuplexCap = DC_HALF; - } else { - printk("sk98lin: Illegal value \"%s\" for DupCap_B\n", - DupCap_B[pAC->Index]); - } - } - - - /* - ** Check for illegal combinations - */ - if ((LinkSpeed == SK_LSPEED_1000MBPS) && - ((DuplexCap == SK_LMODE_STAT_AUTOHALF) || - (DuplexCap == SK_LMODE_STAT_HALF)) && - (pAC->ChipsetType)) { - printk("sk98lin: Half Duplex not possible with Gigabit speed!\n" - " Using Full Duplex.\n"); - DuplexCap = DC_FULL; - } - - if (AutoSet && AutoNeg==AN_SENS && DupSet) { - printk("sk98lin, Port B: DuplexCapabilities" - " ignored using Sense mode\n"); - } - - if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){ - printk("sk98lin: Port B: Illegal combination" - " of values AutoNeg. and DuplexCap.\n Using " - "Full Duplex\n"); - DuplexCap = DC_FULL; - } - - if (AutoSet && AutoNeg==AN_OFF && !DupSet) { - DuplexCap = DC_FULL; - } - - if (!AutoSet && DupSet) { - printk("sk98lin: Port B: Duplex setting not" - " possible in\n default AutoNegotiation mode" - " (Sense).\n Using AutoNegotiation On\n"); - AutoNeg = AN_ON; - } - - /* - ** set the desired mode - */ - if (AutoSet || DupSet) { - pAC->GIni.GP[1].PLinkModeConf = Capabilities[AutoNeg][DuplexCap]; - } - - /* - ** c) Any FlowCtrl parameter set? - */ - if (FlowCtrl_B != NULL && pAC->Index<SK_MAX_CARD_PARAM && - FlowCtrl_B[pAC->Index] != NULL) { - if (strcmp(FlowCtrl_B[pAC->Index],"") == 0) { - IsFlowCtrlDefined = SK_FALSE; - } else if (strcmp(FlowCtrl_B[pAC->Index],"SymOrRem") == 0) { - FlowCtrl = SK_FLOW_MODE_SYM_OR_REM; - } else if (strcmp(FlowCtrl_B[pAC->Index],"Sym")==0) { - FlowCtrl = SK_FLOW_MODE_SYMMETRIC; - } else if (strcmp(FlowCtrl_B[pAC->Index],"LocSend")==0) { - FlowCtrl = SK_FLOW_MODE_LOC_SEND; - } else if (strcmp(FlowCtrl_B[pAC->Index],"None")==0) { - FlowCtrl = SK_FLOW_MODE_NONE; - } else { - printk("sk98lin: Illegal value \"%s\" for FlowCtrl_B\n", - FlowCtrl_B[pAC->Index]); - IsFlowCtrlDefined = SK_FALSE; - } - } else { - IsFlowCtrlDefined = SK_FALSE; - } - - if (IsFlowCtrlDefined) { - if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) { - printk("sk98lin: Port B: FlowControl" - " impossible without AutoNegotiation," - " disabled\n"); - FlowCtrl = SK_FLOW_MODE_NONE; - } - pAC->GIni.GP[1].PFlowCtrlMode = FlowCtrl; - } - - /* - ** d) What is the RoleParameter? - */ - if (Role_B != NULL && pAC->Index<SK_MAX_CARD_PARAM && - Role_B[pAC->Index] != NULL) { - if (strcmp(Role_B[pAC->Index],"")==0) { - IsRoleDefined = SK_FALSE; - } else if (strcmp(Role_B[pAC->Index],"Auto")==0) { - MSMode = SK_MS_MODE_AUTO; - } else if (strcmp(Role_B[pAC->Index],"Master")==0) { - MSMode = SK_MS_MODE_MASTER; - } else if (strcmp(Role_B[pAC->Index],"Slave")==0) { - MSMode = SK_MS_MODE_SLAVE; - } else { - printk("sk98lin: Illegal value \"%s\" for Role_B\n", - Role_B[pAC->Index]); - IsRoleDefined = SK_FALSE; - } - } else { - IsRoleDefined = SK_FALSE; - } - - if (IsRoleDefined) { - pAC->GIni.GP[1].PMSMode = MSMode; - } - - /* - ** Evaluate settings for both ports - */ - pAC->ActivePort = 0; - if (PrefPort != NULL && pAC->Index<SK_MAX_CARD_PARAM && - PrefPort[pAC->Index] != NULL) { - if (strcmp(PrefPort[pAC->Index],"") == 0) { /* Auto */ - pAC->ActivePort = 0; - pAC->Rlmt.Net[0].Preference = -1; /* auto */ - pAC->Rlmt.Net[0].PrefPort = 0; - } else if (strcmp(PrefPort[pAC->Index],"A") == 0) { - /* - ** do not set ActivePort here, thus a port - ** switch is issued after net up. - */ - Port = 0; - pAC->Rlmt.Net[0].Preference = Port; - pAC->Rlmt.Net[0].PrefPort = Port; - } else if (strcmp(PrefPort[pAC->Index],"B") == 0) { - /* - ** do not set ActivePort here, thus a port - ** switch is issued after net up. - */ - if (pAC->GIni.GIMacsFound == 1) { - printk("sk98lin: Illegal value \"B\" for PrefPort.\n" - " Port B not available on single port adapters.\n"); - - pAC->ActivePort = 0; - pAC->Rlmt.Net[0].Preference = -1; /* auto */ - pAC->Rlmt.Net[0].PrefPort = 0; - } else { - Port = 1; - pAC->Rlmt.Net[0].Preference = Port; - pAC->Rlmt.Net[0].PrefPort = Port; - } - } else { - printk("sk98lin: Illegal value \"%s\" for PrefPort\n", - PrefPort[pAC->Index]); - } - } - - pAC->RlmtNets = 1; - - if (RlmtMode != NULL && pAC->Index<SK_MAX_CARD_PARAM && - RlmtMode[pAC->Index] != NULL) { - if (strcmp(RlmtMode[pAC->Index], "") == 0) { - pAC->RlmtMode = 0; - } else if (strcmp(RlmtMode[pAC->Index], "CheckLinkState") == 0) { - pAC->RlmtMode = SK_RLMT_CHECK_LINK; - } else if (strcmp(RlmtMode[pAC->Index], "CheckLocalPort") == 0) { - pAC->RlmtMode = SK_RLMT_CHECK_LINK | - SK_RLMT_CHECK_LOC_LINK; - } else if (strcmp(RlmtMode[pAC->Index], "CheckSeg") == 0) { - pAC->RlmtMode = SK_RLMT_CHECK_LINK | - SK_RLMT_CHECK_LOC_LINK | - SK_RLMT_CHECK_SEG; - } else if ((strcmp(RlmtMode[pAC->Index], "DualNet") == 0) && - (pAC->GIni.GIMacsFound == 2)) { - pAC->RlmtMode = SK_RLMT_CHECK_LINK; - pAC->RlmtNets = 2; - } else { - printk("sk98lin: Illegal value \"%s\" for" - " RlmtMode, using default\n", - RlmtMode[pAC->Index]); - pAC->RlmtMode = 0; - } - } else { - pAC->RlmtMode = 0; - } - - /* - ** Check the interrupt moderation parameters - */ - if (Moderation[pAC->Index] != NULL) { - if (strcmp(Moderation[pAC->Index], "") == 0) { - pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE; - } else if (strcmp(Moderation[pAC->Index], "Static") == 0) { - pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_STATIC; - } else if (strcmp(Moderation[pAC->Index], "Dynamic") == 0) { - pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_DYNAMIC; - } else if (strcmp(Moderation[pAC->Index], "None") == 0) { - pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE; - } else { - printk("sk98lin: Illegal value \"%s\" for Moderation.\n" - " Disable interrupt moderation.\n", - Moderation[pAC->Index]); - pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE; - } - } else { - pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE; - } - - if (Stats[pAC->Index] != NULL) { - if (strcmp(Stats[pAC->Index], "Yes") == 0) { - pAC->DynIrqModInfo.DisplayStats = SK_TRUE; - } else { - pAC->DynIrqModInfo.DisplayStats = SK_FALSE; - } - } else { - pAC->DynIrqModInfo.DisplayStats = SK_FALSE; - } - - if (ModerationMask[pAC->Index] != NULL) { - if (strcmp(ModerationMask[pAC->Index], "Rx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY; - } else if (strcmp(ModerationMask[pAC->Index], "Tx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_ONLY; - } else if (strcmp(ModerationMask[pAC->Index], "Sp") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_ONLY; - } else if (strcmp(ModerationMask[pAC->Index], "RxSp") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX; - } else if (strcmp(ModerationMask[pAC->Index], "SpRx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX; - } else if (strcmp(ModerationMask[pAC->Index], "RxTx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX; - } else if (strcmp(ModerationMask[pAC->Index], "TxRx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX; - } else if (strcmp(ModerationMask[pAC->Index], "TxSp") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX; - } else if (strcmp(ModerationMask[pAC->Index], "SpTx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX; - } else if (strcmp(ModerationMask[pAC->Index], "RxTxSp") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; - } else if (strcmp(ModerationMask[pAC->Index], "RxSpTx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; - } else if (strcmp(ModerationMask[pAC->Index], "TxRxSp") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; - } else if (strcmp(ModerationMask[pAC->Index], "TxSpRx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; - } else if (strcmp(ModerationMask[pAC->Index], "SpTxRx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; - } else if (strcmp(ModerationMask[pAC->Index], "SpRxTx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; - } else { /* some rubbish */ - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY; - } - } else { /* operator has stated nothing */ - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX; - } - - if (AutoSizing[pAC->Index] != NULL) { - if (strcmp(AutoSizing[pAC->Index], "On") == 0) { - pAC->DynIrqModInfo.AutoSizing = SK_FALSE; - } else { - pAC->DynIrqModInfo.AutoSizing = SK_FALSE; - } - } else { /* operator has stated nothing */ - pAC->DynIrqModInfo.AutoSizing = SK_FALSE; - } - - if (IntsPerSec[pAC->Index] != 0) { - if ((IntsPerSec[pAC->Index]< C_INT_MOD_IPS_LOWER_RANGE) || - (IntsPerSec[pAC->Index] > C_INT_MOD_IPS_UPPER_RANGE)) { - printk("sk98lin: Illegal value \"%d\" for IntsPerSec. (Range: %d - %d)\n" - " Using default value of %i.\n", - IntsPerSec[pAC->Index], - C_INT_MOD_IPS_LOWER_RANGE, - C_INT_MOD_IPS_UPPER_RANGE, - C_INTS_PER_SEC_DEFAULT); - pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT; - } else { - pAC->DynIrqModInfo.MaxModIntsPerSec = IntsPerSec[pAC->Index]; - } - } else { - pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT; - } - - /* - ** Evaluate upper and lower moderation threshold - */ - pAC->DynIrqModInfo.MaxModIntsPerSecUpperLimit = - pAC->DynIrqModInfo.MaxModIntsPerSec + - (pAC->DynIrqModInfo.MaxModIntsPerSec / 2); - - pAC->DynIrqModInfo.MaxModIntsPerSecLowerLimit = - pAC->DynIrqModInfo.MaxModIntsPerSec - - (pAC->DynIrqModInfo.MaxModIntsPerSec / 2); - - pAC->DynIrqModInfo.PrevTimeVal = jiffies; /* initial value */ - - -} /* GetConfiguration */ - - -/***************************************************************************** - * - * ProductStr - return a adapter identification string from vpd - * - * Description: - * This function reads the product name string from the vpd area - * and puts it the field pAC->DeviceString. - * - * Returns: N/A - */ -static inline int ProductStr( - SK_AC *pAC, /* pointer to adapter context */ - char *DeviceStr, /* result string */ - int StrLen /* length of the string */ -) -{ -char Keyword[] = VPD_NAME; /* vpd productname identifier */ -int ReturnCode; /* return code from vpd_read */ -unsigned long Flags; - - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - ReturnCode = VpdRead(pAC, pAC->IoBase, Keyword, DeviceStr, &StrLen); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - - return ReturnCode; -} /* ProductStr */ - -/***************************************************************************** - * - * StartDrvCleanupTimer - Start timer to check for descriptors which - * might be placed in descriptor ring, but - * havent been handled up to now - * - * Description: - * This function requests a HW-timer fo the Yukon card. The actions to - * perform when this timer expires, are located in the SkDrvEvent(). - * - * Returns: N/A - */ -static void -StartDrvCleanupTimer(SK_AC *pAC) { - SK_EVPARA EventParam; /* Event struct for timer event */ - - SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam)); - EventParam.Para32[0] = SK_DRV_RX_CLEANUP_TIMER; - SkTimerStart(pAC, pAC->IoBase, &pAC->DrvCleanupTimer, - SK_DRV_RX_CLEANUP_TIMER_LENGTH, - SKGE_DRV, SK_DRV_TIMER, EventParam); -} - -/***************************************************************************** - * - * StopDrvCleanupTimer - Stop timer to check for descriptors - * - * Description: - * This function requests a HW-timer fo the Yukon card. The actions to - * perform when this timer expires, are located in the SkDrvEvent(). - * - * Returns: N/A - */ -static void -StopDrvCleanupTimer(SK_AC *pAC) { - SkTimerStop(pAC, pAC->IoBase, &pAC->DrvCleanupTimer); - SK_MEMSET((char *) &pAC->DrvCleanupTimer, 0, sizeof(SK_TIMER)); -} - -/****************************************************************************/ -/* functions for common modules *********************************************/ -/****************************************************************************/ - - -/***************************************************************************** - * - * SkDrvAllocRlmtMbuf - allocate an RLMT mbuf - * - * Description: - * This routine returns an RLMT mbuf or NULL. The RLMT Mbuf structure - * is embedded into a socket buff data area. - * - * Context: - * runtime - * - * Returns: - * NULL or pointer to Mbuf. - */ -SK_MBUF *SkDrvAllocRlmtMbuf( -SK_AC *pAC, /* pointer to adapter context */ -SK_IOC IoC, /* the IO-context */ -unsigned BufferSize) /* size of the requested buffer */ -{ -SK_MBUF *pRlmtMbuf; /* pointer to a new rlmt-mbuf structure */ -struct sk_buff *pMsgBlock; /* pointer to a new message block */ - - pMsgBlock = alloc_skb(BufferSize + sizeof(SK_MBUF), GFP_ATOMIC); - if (pMsgBlock == NULL) { - return (NULL); - } - pRlmtMbuf = (SK_MBUF*) pMsgBlock->data; - skb_reserve(pMsgBlock, sizeof(SK_MBUF)); - pRlmtMbuf->pNext = NULL; - pRlmtMbuf->pOs = pMsgBlock; - pRlmtMbuf->pData = pMsgBlock->data; /* Data buffer. */ - pRlmtMbuf->Size = BufferSize; /* Data buffer size. */ - pRlmtMbuf->Length = 0; /* Length of packet (<= Size). */ - return (pRlmtMbuf); - -} /* SkDrvAllocRlmtMbuf */ - - -/***************************************************************************** - * - * SkDrvFreeRlmtMbuf - free an RLMT mbuf - * - * Description: - * This routine frees one or more RLMT mbuf(s). - * - * Context: - * runtime - * - * Returns: - * Nothing - */ -void SkDrvFreeRlmtMbuf( -SK_AC *pAC, /* pointer to adapter context */ -SK_IOC IoC, /* the IO-context */ -SK_MBUF *pMbuf) /* size of the requested buffer */ -{ -SK_MBUF *pFreeMbuf; -SK_MBUF *pNextMbuf; - - pFreeMbuf = pMbuf; - do { - pNextMbuf = pFreeMbuf->pNext; - DEV_KFREE_SKB_ANY(pFreeMbuf->pOs); - pFreeMbuf = pNextMbuf; - } while ( pFreeMbuf != NULL ); -} /* SkDrvFreeRlmtMbuf */ - - -/***************************************************************************** - * - * SkOsGetTime - provide a time value - * - * Description: - * This routine provides a time value. The unit is 1/HZ (defined by Linux). - * It is not used for absolute time, but only for time differences. - * - * - * Returns: - * Time value - */ -SK_U64 SkOsGetTime(SK_AC *pAC) -{ - SK_U64 PrivateJiffies; - SkOsGetTimeCurrent(pAC, &PrivateJiffies); - return PrivateJiffies; -} /* SkOsGetTime */ - - -/***************************************************************************** - * - * SkPciReadCfgDWord - read a 32 bit value from pci config space - * - * Description: - * This routine reads a 32 bit value from the pci configuration - * space. - * - * Returns: - * 0 - indicate everything worked ok. - * != 0 - error indication - */ -int SkPciReadCfgDWord( -SK_AC *pAC, /* Adapter Control structure pointer */ -int PciAddr, /* PCI register address */ -SK_U32 *pVal) /* pointer to store the read value */ -{ - pci_read_config_dword(pAC->PciDev, PciAddr, pVal); - return(0); -} /* SkPciReadCfgDWord */ - - -/***************************************************************************** - * - * SkPciReadCfgWord - read a 16 bit value from pci config space - * - * Description: - * This routine reads a 16 bit value from the pci configuration - * space. - * - * Returns: - * 0 - indicate everything worked ok. - * != 0 - error indication - */ -int SkPciReadCfgWord( -SK_AC *pAC, /* Adapter Control structure pointer */ -int PciAddr, /* PCI register address */ -SK_U16 *pVal) /* pointer to store the read value */ -{ - pci_read_config_word(pAC->PciDev, PciAddr, pVal); - return(0); -} /* SkPciReadCfgWord */ - - -/***************************************************************************** - * - * SkPciReadCfgByte - read a 8 bit value from pci config space - * - * Description: - * This routine reads a 8 bit value from the pci configuration - * space. - * - * Returns: - * 0 - indicate everything worked ok. - * != 0 - error indication - */ -int SkPciReadCfgByte( -SK_AC *pAC, /* Adapter Control structure pointer */ -int PciAddr, /* PCI register address */ -SK_U8 *pVal) /* pointer to store the read value */ -{ - pci_read_config_byte(pAC->PciDev, PciAddr, pVal); - return(0); -} /* SkPciReadCfgByte */ - - -/***************************************************************************** - * - * SkPciWriteCfgWord - write a 16 bit value to pci config space - * - * Description: - * This routine writes a 16 bit value to the pci configuration - * space. The flag PciConfigUp indicates whether the config space - * is accesible or must be set up first. - * - * Returns: - * 0 - indicate everything worked ok. - * != 0 - error indication - */ -int SkPciWriteCfgWord( -SK_AC *pAC, /* Adapter Control structure pointer */ -int PciAddr, /* PCI register address */ -SK_U16 Val) /* pointer to store the read value */ -{ - pci_write_config_word(pAC->PciDev, PciAddr, Val); - return(0); -} /* SkPciWriteCfgWord */ - - -/***************************************************************************** - * - * SkPciWriteCfgWord - write a 8 bit value to pci config space - * - * Description: - * This routine writes a 8 bit value to the pci configuration - * space. The flag PciConfigUp indicates whether the config space - * is accesible or must be set up first. - * - * Returns: - * 0 - indicate everything worked ok. - * != 0 - error indication - */ -int SkPciWriteCfgByte( -SK_AC *pAC, /* Adapter Control structure pointer */ -int PciAddr, /* PCI register address */ -SK_U8 Val) /* pointer to store the read value */ -{ - pci_write_config_byte(pAC->PciDev, PciAddr, Val); - return(0); -} /* SkPciWriteCfgByte */ - - -/***************************************************************************** - * - * SkDrvEvent - handle driver events - * - * Description: - * This function handles events from all modules directed to the driver - * - * Context: - * Is called under protection of slow path lock. - * - * Returns: - * 0 if everything ok - * < 0 on error - * - */ -int SkDrvEvent( -SK_AC *pAC, /* pointer to adapter context */ -SK_IOC IoC, /* io-context */ -SK_U32 Event, /* event-id */ -SK_EVPARA Param) /* event-parameter */ -{ -SK_MBUF *pRlmtMbuf; /* pointer to a rlmt-mbuf structure */ -struct sk_buff *pMsg; /* pointer to a message block */ -int FromPort; /* the port from which we switch away */ -int ToPort; /* the port we switch to */ -SK_EVPARA NewPara; /* parameter for further events */ -int Stat; -unsigned long Flags; -SK_BOOL DualNet; - - switch (Event) { - case SK_DRV_ADAP_FAIL: - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("ADAPTER FAIL EVENT\n")); - printk("%s: Adapter failed.\n", pAC->dev[0]->name); - /* disable interrupts */ - SK_OUT32(pAC->IoBase, B0_IMSK, 0); - /* cgoos */ - break; - case SK_DRV_PORT_FAIL: - FromPort = Param.Para32[0]; - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("PORT FAIL EVENT, Port: %d\n", FromPort)); - if (FromPort == 0) { - printk("%s: Port A failed.\n", pAC->dev[0]->name); - } else { - printk("%s: Port B failed.\n", pAC->dev[1]->name); - } - /* cgoos */ - break; - case SK_DRV_PORT_RESET: /* SK_U32 PortIdx */ - /* action list 4 */ - FromPort = Param.Para32[0]; - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("PORT RESET EVENT, Port: %d ", FromPort)); - NewPara.Para64 = FromPort; - SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara); - spin_lock_irqsave( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - - SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST); - netif_carrier_off(pAC->dev[Param.Para32[0]]); - spin_unlock_irqrestore( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - - /* clear rx ring from received frames */ - ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); - - ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]); - spin_lock_irqsave( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - - /* tschilling: Handling of return value inserted. */ - if (SkGeInitPort(pAC, IoC, FromPort)) { - if (FromPort == 0) { - printk("%s: SkGeInitPort A failed.\n", pAC->dev[0]->name); - } else { - printk("%s: SkGeInitPort B failed.\n", pAC->dev[1]->name); - } - } - SkAddrMcUpdate(pAC,IoC, FromPort); - PortReInitBmu(pAC, FromPort); - SkGePollTxD(pAC, IoC, FromPort, SK_TRUE); - ClearAndStartRx(pAC, FromPort); - spin_unlock_irqrestore( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - break; - case SK_DRV_NET_UP: /* SK_U32 PortIdx */ - { struct net_device *dev = pAC->dev[Param.Para32[0]]; - /* action list 5 */ - FromPort = Param.Para32[0]; - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("NET UP EVENT, Port: %d ", Param.Para32[0])); - /* Mac update */ - SkAddrMcUpdate(pAC,IoC, FromPort); - - if (DoPrintInterfaceChange) { - printk("%s: network connection up using" - " port %c\n", pAC->dev[Param.Para32[0]]->name, 'A'+Param.Para32[0]); - - /* tschilling: Values changed according to LinkSpeedUsed. */ - Stat = pAC->GIni.GP[FromPort].PLinkSpeedUsed; - if (Stat == SK_LSPEED_STAT_10MBPS) { - printk(" speed: 10\n"); - } else if (Stat == SK_LSPEED_STAT_100MBPS) { - printk(" speed: 100\n"); - } else if (Stat == SK_LSPEED_STAT_1000MBPS) { - printk(" speed: 1000\n"); - } else { - printk(" speed: unknown\n"); - } - - - Stat = pAC->GIni.GP[FromPort].PLinkModeStatus; - if (Stat == SK_LMODE_STAT_AUTOHALF || - Stat == SK_LMODE_STAT_AUTOFULL) { - printk(" autonegotiation: yes\n"); - } - else { - printk(" autonegotiation: no\n"); - } - if (Stat == SK_LMODE_STAT_AUTOHALF || - Stat == SK_LMODE_STAT_HALF) { - printk(" duplex mode: half\n"); - } - else { - printk(" duplex mode: full\n"); - } - Stat = pAC->GIni.GP[FromPort].PFlowCtrlStatus; - if (Stat == SK_FLOW_STAT_REM_SEND ) { - printk(" flowctrl: remote send\n"); - } - else if (Stat == SK_FLOW_STAT_LOC_SEND ){ - printk(" flowctrl: local send\n"); - } - else if (Stat == SK_FLOW_STAT_SYMMETRIC ){ - printk(" flowctrl: symmetric\n"); - } - else { - printk(" flowctrl: none\n"); - } - - /* tschilling: Check against CopperType now. */ - if ((pAC->GIni.GICopperType == SK_TRUE) && - (pAC->GIni.GP[FromPort].PLinkSpeedUsed == - SK_LSPEED_STAT_1000MBPS)) { - Stat = pAC->GIni.GP[FromPort].PMSStatus; - if (Stat == SK_MS_STAT_MASTER ) { - printk(" role: master\n"); - } - else if (Stat == SK_MS_STAT_SLAVE ) { - printk(" role: slave\n"); - } - else { - printk(" role: ???\n"); - } - } - - /* - Display dim (dynamic interrupt moderation) - informations - */ - if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC) - printk(" irq moderation: static (%d ints/sec)\n", - pAC->DynIrqModInfo.MaxModIntsPerSec); - else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC) - printk(" irq moderation: dynamic (%d ints/sec)\n", - pAC->DynIrqModInfo.MaxModIntsPerSec); - else - printk(" irq moderation: disabled\n"); - - - printk(" scatter-gather: %s\n", - (dev->features & NETIF_F_SG) ? "enabled" : "disabled"); - printk(" tx-checksum: %s\n", - (dev->features & NETIF_F_IP_CSUM) ? "enabled" : "disabled"); - printk(" rx-checksum: %s\n", - pAC->RxPort[Param.Para32[0]].RxCsum ? "enabled" : "disabled"); - - } else { - DoPrintInterfaceChange = SK_TRUE; - } - - if ((Param.Para32[0] != pAC->ActivePort) && - (pAC->RlmtNets == 1)) { - NewPara.Para32[0] = pAC->ActivePort; - NewPara.Para32[1] = Param.Para32[0]; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_INTERN, - NewPara); - } - - /* Inform the world that link protocol is up. */ - netif_carrier_on(dev); - break; - } - case SK_DRV_NET_DOWN: /* SK_U32 Reason */ - /* action list 7 */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("NET DOWN EVENT ")); - if (DoPrintInterfaceChange) { - printk("%s: network connection down\n", - pAC->dev[Param.Para32[1]]->name); - } else { - DoPrintInterfaceChange = SK_TRUE; - } - netif_carrier_off(pAC->dev[Param.Para32[1]]); - break; - case SK_DRV_SWITCH_HARD: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("PORT SWITCH HARD ")); - case SK_DRV_SWITCH_SOFT: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */ - /* action list 6 */ - printk("%s: switching to port %c\n", pAC->dev[0]->name, - 'A'+Param.Para32[1]); - case SK_DRV_SWITCH_INTERN: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */ - FromPort = Param.Para32[0]; - ToPort = Param.Para32[1]; - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("PORT SWITCH EVENT, From: %d To: %d (Pref %d) ", - FromPort, ToPort, pAC->Rlmt.Net[0].PrefPort)); - NewPara.Para64 = FromPort; - SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara); - NewPara.Para64 = ToPort; - SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara); - spin_lock_irqsave( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); - SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST); - SkGeStopPort(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST); - spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); - spin_unlock_irqrestore( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - - ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); /* clears rx ring */ - ReceiveIrq(pAC, &pAC->RxPort[ToPort], SK_FALSE); /* clears rx ring */ - - ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]); - ClearTxRing(pAC, &pAC->TxPort[ToPort][TX_PRIO_LOW]); - spin_lock_irqsave( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); - pAC->ActivePort = ToPort; -#if 0 - SetQueueSizes(pAC); -#else - /* tschilling: New common function with minimum size check. */ - DualNet = SK_FALSE; - if (pAC->RlmtNets == 2) { - DualNet = SK_TRUE; - } - - if (SkGeInitAssignRamToQueues( - pAC, - pAC->ActivePort, - DualNet)) { - spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); - spin_unlock_irqrestore( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - printk("SkGeInitAssignRamToQueues failed.\n"); - break; - } -#endif - /* tschilling: Handling of return values inserted. */ - if (SkGeInitPort(pAC, IoC, FromPort) || - SkGeInitPort(pAC, IoC, ToPort)) { - printk("%s: SkGeInitPort failed.\n", pAC->dev[0]->name); - } - if (Event == SK_DRV_SWITCH_SOFT) { - SkMacRxTxEnable(pAC, IoC, FromPort); - } - SkMacRxTxEnable(pAC, IoC, ToPort); - SkAddrSwap(pAC, IoC, FromPort, ToPort); - SkAddrMcUpdate(pAC, IoC, FromPort); - SkAddrMcUpdate(pAC, IoC, ToPort); - PortReInitBmu(pAC, FromPort); - PortReInitBmu(pAC, ToPort); - SkGePollTxD(pAC, IoC, FromPort, SK_TRUE); - SkGePollTxD(pAC, IoC, ToPort, SK_TRUE); - ClearAndStartRx(pAC, FromPort); - ClearAndStartRx(pAC, ToPort); - spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); - spin_unlock_irqrestore( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - break; - case SK_DRV_RLMT_SEND: /* SK_MBUF *pMb */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("RLS ")); - pRlmtMbuf = (SK_MBUF*) Param.pParaPtr; - pMsg = (struct sk_buff*) pRlmtMbuf->pOs; - skb_put(pMsg, pRlmtMbuf->Length); - if (XmitFrame(pAC, &pAC->TxPort[pRlmtMbuf->PortIdx][TX_PRIO_LOW], - pMsg) < 0) - - DEV_KFREE_SKB_ANY(pMsg); - break; - case SK_DRV_TIMER: - if (Param.Para32[0] == SK_DRV_MODERATION_TIMER) { - /* - ** expiration of the moderation timer implies that - ** dynamic moderation is to be applied - */ - SkDimStartModerationTimer(pAC); - SkDimModerate(pAC); - if (pAC->DynIrqModInfo.DisplayStats) { - SkDimDisplayModerationSettings(pAC); - } - } else if (Param.Para32[0] == SK_DRV_RX_CLEANUP_TIMER) { - /* - ** check if we need to check for descriptors which - ** haven't been handled the last millisecs - */ - StartDrvCleanupTimer(pAC); - if (pAC->GIni.GIMacsFound == 2) { - ReceiveIrq(pAC, &pAC->RxPort[1], SK_FALSE); - } - ReceiveIrq(pAC, &pAC->RxPort[0], SK_FALSE); - } else { - printk("Expiration of unknown timer\n"); - } - break; - default: - break; - } - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("END EVENT ")); - - return (0); -} /* SkDrvEvent */ - - -/***************************************************************************** - * - * SkErrorLog - log errors - * - * Description: - * This function logs errors to the system buffer and to the console - * - * Returns: - * 0 if everything ok - * < 0 on error - * - */ -void SkErrorLog( -SK_AC *pAC, -int ErrClass, -int ErrNum, -char *pErrorMsg) -{ -char ClassStr[80]; - - switch (ErrClass) { - case SK_ERRCL_OTHER: - strcpy(ClassStr, "Other error"); - break; - case SK_ERRCL_CONFIG: - strcpy(ClassStr, "Configuration error"); - break; - case SK_ERRCL_INIT: - strcpy(ClassStr, "Initialization error"); - break; - case SK_ERRCL_NORES: - strcpy(ClassStr, "Out of resources error"); - break; - case SK_ERRCL_SW: - strcpy(ClassStr, "internal Software error"); - break; - case SK_ERRCL_HW: - strcpy(ClassStr, "Hardware failure"); - break; - case SK_ERRCL_COMM: - strcpy(ClassStr, "Communication error"); - break; - } - printk(KERN_INFO "%s: -- ERROR --\n Class: %s\n" - " Nr: 0x%x\n Msg: %s\n", pAC->dev[0]->name, - ClassStr, ErrNum, pErrorMsg); - -} /* SkErrorLog */ - -#ifdef SK_DIAG_SUPPORT - -/***************************************************************************** - * - * SkDrvEnterDiagMode - handles DIAG attach request - * - * Description: - * Notify the kernel to NOT access the card any longer due to DIAG - * Deinitialize the Card - * - * Returns: - * int - */ -int SkDrvEnterDiagMode( -SK_AC *pAc) /* pointer to adapter context */ -{ - DEV_NET *pNet = netdev_priv(pAc->dev[0]); - SK_AC *pAC = pNet->pAC; - - SK_MEMCPY(&(pAc->PnmiBackup), &(pAc->PnmiStruct), - sizeof(SK_PNMI_STRUCT_DATA)); - - pAC->DiagModeActive = DIAG_ACTIVE; - if (pAC->BoardLevel > SK_INIT_DATA) { - if (netif_running(pAC->dev[0])) { - pAC->WasIfUp[0] = SK_TRUE; - pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */ - DoPrintInterfaceChange = SK_FALSE; - SkDrvDeInitAdapter(pAC, 0); /* performs SkGeClose */ - } else { - pAC->WasIfUp[0] = SK_FALSE; - } - if (pNet != netdev_priv(pAC->dev[1])) { - pNet = netdev_priv(pAC->dev[1]); - if (netif_running(pAC->dev[1])) { - pAC->WasIfUp[1] = SK_TRUE; - pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */ - DoPrintInterfaceChange = SK_FALSE; - SkDrvDeInitAdapter(pAC, 1); /* do SkGeClose */ - } else { - pAC->WasIfUp[1] = SK_FALSE; - } - } - pAC->BoardLevel = SK_INIT_DATA; - } - return(0); -} - -/***************************************************************************** - * - * SkDrvLeaveDiagMode - handles DIAG detach request - * - * Description: - * Notify the kernel to may access the card again after use by DIAG - * Initialize the Card - * - * Returns: - * int - */ -int SkDrvLeaveDiagMode( -SK_AC *pAc) /* pointer to adapter control context */ -{ - SK_MEMCPY(&(pAc->PnmiStruct), &(pAc->PnmiBackup), - sizeof(SK_PNMI_STRUCT_DATA)); - pAc->DiagModeActive = DIAG_NOTACTIVE; - pAc->Pnmi.DiagAttached = SK_DIAG_IDLE; - if (pAc->WasIfUp[0] == SK_TRUE) { - pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */ - DoPrintInterfaceChange = SK_FALSE; - SkDrvInitAdapter(pAc, 0); /* first device */ - } - if (pAc->WasIfUp[1] == SK_TRUE) { - pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */ - DoPrintInterfaceChange = SK_FALSE; - SkDrvInitAdapter(pAc, 1); /* second device */ - } - return(0); -} - -/***************************************************************************** - * - * ParseDeviceNbrFromSlotName - Evaluate PCI device number - * - * Description: - * This function parses the PCI slot name information string and will - * retrieve the devcie number out of it. The slot_name maintianed by - * linux is in the form of '02:0a.0', whereas the first two characters - * represent the bus number in hex (in the sample above this is - * pci bus 0x02) and the next two characters the device number (0x0a). - * - * Returns: - * SK_U32: The device number from the PCI slot name - */ - -static SK_U32 ParseDeviceNbrFromSlotName( -const char *SlotName) /* pointer to pci slot name eg. '02:0a.0' */ -{ - char *CurrCharPos = (char *) SlotName; - int FirstNibble = -1; - int SecondNibble = -1; - SK_U32 Result = 0; - - while (*CurrCharPos != '\0') { - if (*CurrCharPos == ':') { - while (*CurrCharPos != '.') { - CurrCharPos++; - if ( (*CurrCharPos >= '0') && - (*CurrCharPos <= '9')) { - if (FirstNibble == -1) { - /* dec. value for '0' */ - FirstNibble = *CurrCharPos - 48; - } else { - SecondNibble = *CurrCharPos - 48; - } - } else if ( (*CurrCharPos >= 'a') && - (*CurrCharPos <= 'f') ) { - if (FirstNibble == -1) { - FirstNibble = *CurrCharPos - 87; - } else { - SecondNibble = *CurrCharPos - 87; - } - } else { - Result = 0; - } - } - - Result = FirstNibble; - Result = Result << 4; /* first nibble is higher one */ - Result = Result | SecondNibble; - } - CurrCharPos++; /* next character */ - } - return (Result); -} - -/**************************************************************************** - * - * SkDrvDeInitAdapter - deinitialize adapter (this function is only - * called if Diag attaches to that card) - * - * Description: - * Close initialized adapter. - * - * Returns: - * 0 - on success - * error code - on error - */ -static int SkDrvDeInitAdapter( -SK_AC *pAC, /* pointer to adapter context */ -int devNbr) /* what device is to be handled */ -{ - struct SK_NET_DEVICE *dev; - - dev = pAC->dev[devNbr]; - - /* On Linux 2.6 the network driver does NOT mess with reference - ** counts. The driver MUST be able to be unloaded at any time - ** due to the possibility of hotplug. - */ - if (SkGeClose(dev) != 0) { - return (-1); - } - return (0); - -} /* SkDrvDeInitAdapter() */ - -/**************************************************************************** - * - * SkDrvInitAdapter - Initialize adapter (this function is only - * called if Diag deattaches from that card) - * - * Description: - * Close initialized adapter. - * - * Returns: - * 0 - on success - * error code - on error - */ -static int SkDrvInitAdapter( -SK_AC *pAC, /* pointer to adapter context */ -int devNbr) /* what device is to be handled */ -{ - struct SK_NET_DEVICE *dev; - - dev = pAC->dev[devNbr]; - - if (SkGeOpen(dev) != 0) { - return (-1); - } - - /* - ** Use correct MTU size and indicate to kernel TX queue can be started - */ - if (SkGeChangeMtu(dev, dev->mtu) != 0) { - return (-1); - } - return (0); - -} /* SkDrvInitAdapter */ - -#endif - -#ifdef DEBUG -/****************************************************************************/ -/* "debug only" section *****************************************************/ -/****************************************************************************/ - - -/***************************************************************************** - * - * DumpMsg - print a frame - * - * Description: - * This function prints frames to the system logfile/to the console. - * - * Returns: N/A - * - */ -static void DumpMsg(struct sk_buff *skb, char *str) -{ - int msglen; - - if (skb == NULL) { - printk("DumpMsg(): NULL-Message\n"); - return; - } - - if (skb->data == NULL) { - printk("DumpMsg(): Message empty\n"); - return; - } - - msglen = skb->len; - if (msglen > 64) - msglen = 64; - - printk("--- Begin of message from %s , len %d (from %d) ----\n", str, msglen, skb->len); - - DumpData((char *)skb->data, msglen); - - printk("------- End of message ---------\n"); -} /* DumpMsg */ - - - -/***************************************************************************** - * - * DumpData - print a data area - * - * Description: - * This function prints a area of data to the system logfile/to the - * console. - * - * Returns: N/A - * - */ -static void DumpData(char *p, int size) -{ -register int i; -int haddr, addr; -char hex_buffer[180]; -char asc_buffer[180]; -char HEXCHAR[] = "0123456789ABCDEF"; - - addr = 0; - haddr = 0; - hex_buffer[0] = 0; - asc_buffer[0] = 0; - for (i=0; i < size; ) { - if (*p >= '0' && *p <='z') - asc_buffer[addr] = *p; - else - asc_buffer[addr] = '.'; - addr++; - asc_buffer[addr] = 0; - hex_buffer[haddr] = HEXCHAR[(*p & 0xf0) >> 4]; - haddr++; - hex_buffer[haddr] = HEXCHAR[*p & 0x0f]; - haddr++; - hex_buffer[haddr] = ' '; - haddr++; - hex_buffer[haddr] = 0; - p++; - i++; - if (i%16 == 0) { - printk("%s %s\n", hex_buffer, asc_buffer); - addr = 0; - haddr = 0; - } - } -} /* DumpData */ - - -/***************************************************************************** - * - * DumpLong - print a data area as long values - * - * Description: - * This function prints a area of data to the system logfile/to the - * console. - * - * Returns: N/A - * - */ -static void DumpLong(char *pc, int size) -{ -register int i; -int haddr, addr; -char hex_buffer[180]; -char asc_buffer[180]; -char HEXCHAR[] = "0123456789ABCDEF"; -long *p; -int l; - - addr = 0; - haddr = 0; - hex_buffer[0] = 0; - asc_buffer[0] = 0; - p = (long*) pc; - for (i=0; i < size; ) { - l = (long) *p; - hex_buffer[haddr] = HEXCHAR[(l >> 28) & 0xf]; - haddr++; - hex_buffer[haddr] = HEXCHAR[(l >> 24) & 0xf]; - haddr++; - hex_buffer[haddr] = HEXCHAR[(l >> 20) & 0xf]; - haddr++; - hex_buffer[haddr] = HEXCHAR[(l >> 16) & 0xf]; - haddr++; - hex_buffer[haddr] = HEXCHAR[(l >> 12) & 0xf]; - haddr++; - hex_buffer[haddr] = HEXCHAR[(l >> 8) & 0xf]; - haddr++; - hex_buffer[haddr] = HEXCHAR[(l >> 4) & 0xf]; - haddr++; - hex_buffer[haddr] = HEXCHAR[l & 0x0f]; - haddr++; - hex_buffer[haddr] = ' '; - haddr++; - hex_buffer[haddr] = 0; - p++; - i++; - if (i%8 == 0) { - printk("%4x %s\n", (i-8)*4, hex_buffer); - haddr = 0; - } - } - printk("------------------------\n"); -} /* DumpLong */ - -#endif - -static int __devinit skge_probe_one(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - SK_AC *pAC; - DEV_NET *pNet = NULL; - struct net_device *dev = NULL; - static int boards_found = 0; - int error = -ENODEV; - int using_dac = 0; - char DeviceStr[80]; - - if (pci_enable_device(pdev)) - goto out; - - /* Configure DMA attributes. */ - if (sizeof(dma_addr_t) > sizeof(u32) && - !(error = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) { - using_dac = 1; - error = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); - if (error < 0) { - printk(KERN_ERR "sk98lin %s unable to obtain 64 bit DMA " - "for consistent allocations\n", pci_name(pdev)); - goto out_disable_device; - } - } else { - error = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (error) { - printk(KERN_ERR "sk98lin %s no usable DMA configuration\n", - pci_name(pdev)); - goto out_disable_device; - } - } - - error = -ENOMEM; - dev = alloc_etherdev(sizeof(DEV_NET)); - if (!dev) { - printk(KERN_ERR "sk98lin: unable to allocate etherdev " - "structure!\n"); - goto out_disable_device; - } - - pNet = netdev_priv(dev); - pNet->pAC = kzalloc(sizeof(SK_AC), GFP_KERNEL); - if (!pNet->pAC) { - printk(KERN_ERR "sk98lin: unable to allocate adapter " - "structure!\n"); - goto out_free_netdev; - } - - pAC = pNet->pAC; - pAC->PciDev = pdev; - - pAC->dev[0] = dev; - pAC->dev[1] = dev; - pAC->CheckQueue = SK_FALSE; - - dev->irq = pdev->irq; - - error = SkGeInitPCI(pAC); - if (error) { - printk(KERN_ERR "sk98lin: PCI setup failed: %i\n", error); - goto out_free_netdev; - } - - SET_MODULE_OWNER(dev); - dev->open = &SkGeOpen; - dev->stop = &SkGeClose; - dev->hard_start_xmit = &SkGeXmit; - dev->get_stats = &SkGeStats; - dev->set_multicast_list = &SkGeSetRxMode; - dev->set_mac_address = &SkGeSetMacAddr; - dev->do_ioctl = &SkGeIoctl; - dev->change_mtu = &SkGeChangeMtu; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = &SkGePollController; -#endif - SET_NETDEV_DEV(dev, &pdev->dev); - SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps); - - /* Use only if yukon hardware */ - if (pAC->ChipsetType) { -#ifdef USE_SK_TX_CHECKSUM - dev->features |= NETIF_F_IP_CSUM; -#endif -#ifdef SK_ZEROCOPY - dev->features |= NETIF_F_SG; -#endif -#ifdef USE_SK_RX_CHECKSUM - pAC->RxPort[0].RxCsum = 1; -#endif - } - - if (using_dac) - dev->features |= NETIF_F_HIGHDMA; - - pAC->Index = boards_found++; - - error = SkGeBoardInit(dev, pAC); - if (error) - goto out_free_netdev; - - /* Read Adapter name from VPD */ - if (ProductStr(pAC, DeviceStr, sizeof(DeviceStr)) != 0) { - error = -EIO; - printk(KERN_ERR "sk98lin: Could not read VPD data.\n"); - goto out_free_resources; - } - - /* Register net device */ - error = register_netdev(dev); - if (error) { - printk(KERN_ERR "sk98lin: Could not register device.\n"); - goto out_free_resources; - } - - /* Print adapter specific string from vpd */ - printk("%s: %s\n", dev->name, DeviceStr); - - /* Print configuration settings */ - printk(" PrefPort:%c RlmtMode:%s\n", - 'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber, - (pAC->RlmtMode==0) ? "Check Link State" : - ((pAC->RlmtMode==1) ? "Check Link State" : - ((pAC->RlmtMode==3) ? "Check Local Port" : - ((pAC->RlmtMode==7) ? "Check Segmentation" : - ((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error"))))); - - SkGeYellowLED(pAC, pAC->IoBase, 1); - - memcpy(&dev->dev_addr, &pAC->Addr.Net[0].CurrentMacAddress, 6); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - pNet->PortNr = 0; - pNet->NetNr = 0; - - boards_found++; - - pci_set_drvdata(pdev, dev); - - /* More then one port found */ - if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { - dev = alloc_etherdev(sizeof(DEV_NET)); - if (!dev) { - printk(KERN_ERR "sk98lin: unable to allocate etherdev " - "structure!\n"); - goto single_port; - } - - pNet = netdev_priv(dev); - pNet->PortNr = 1; - pNet->NetNr = 1; - pNet->pAC = pAC; - - dev->open = &SkGeOpen; - dev->stop = &SkGeClose; - dev->hard_start_xmit = &SkGeXmit; - dev->get_stats = &SkGeStats; - dev->set_multicast_list = &SkGeSetRxMode; - dev->set_mac_address = &SkGeSetMacAddr; - dev->do_ioctl = &SkGeIoctl; - dev->change_mtu = &SkGeChangeMtu; - SET_NETDEV_DEV(dev, &pdev->dev); - SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps); - - if (pAC->ChipsetType) { -#ifdef USE_SK_TX_CHECKSUM - dev->features |= NETIF_F_IP_CSUM; -#endif -#ifdef SK_ZEROCOPY - dev->features |= NETIF_F_SG; -#endif -#ifdef USE_SK_RX_CHECKSUM - pAC->RxPort[1].RxCsum = 1; -#endif - } - - if (using_dac) - dev->features |= NETIF_F_HIGHDMA; - - error = register_netdev(dev); - if (error) { - printk(KERN_ERR "sk98lin: Could not register device" - " for second port. (%d)\n", error); - free_netdev(dev); - goto single_port; - } - - pAC->dev[1] = dev; - memcpy(&dev->dev_addr, - &pAC->Addr.Net[1].CurrentMacAddress, 6); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - printk("%s: %s\n", dev->name, DeviceStr); - printk(" PrefPort:B RlmtMode:Dual Check Link State\n"); - } - -single_port: - - /* Save the hardware revision */ - pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) + - (pAC->GIni.GIPciHwRev & 0x0F); - - /* Set driver globals */ - pAC->Pnmi.pDriverFileName = DRIVER_FILE_NAME; - pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE; - - memset(&pAC->PnmiBackup, 0, sizeof(SK_PNMI_STRUCT_DATA)); - memcpy(&pAC->PnmiBackup, &pAC->PnmiStruct, sizeof(SK_PNMI_STRUCT_DATA)); - - return 0; - - out_free_resources: - FreeResources(dev); - out_free_netdev: - free_netdev(dev); - out_disable_device: - pci_disable_device(pdev); - out: - return error; -} - -static void __devexit skge_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - struct net_device *otherdev = pAC->dev[1]; - - unregister_netdev(dev); - - SkGeYellowLED(pAC, pAC->IoBase, 0); - - if (pAC->BoardLevel == SK_INIT_RUN) { - SK_EVPARA EvPara; - unsigned long Flags; - - /* board is still alive */ - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - EvPara.Para32[0] = 0; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - EvPara.Para32[0] = 1; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - SkEventDispatcher(pAC, pAC->IoBase); - /* disable interrupts */ - SK_OUT32(pAC->IoBase, B0_IMSK, 0); - SkGeDeInit(pAC, pAC->IoBase); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - pAC->BoardLevel = SK_INIT_DATA; - /* We do NOT check here, if IRQ was pending, of course*/ - } - - if (pAC->BoardLevel == SK_INIT_IO) { - /* board is still alive */ - SkGeDeInit(pAC, pAC->IoBase); - pAC->BoardLevel = SK_INIT_DATA; - } - - FreeResources(dev); - free_netdev(dev); - if (otherdev != dev) - free_netdev(otherdev); - kfree(pAC); -} - -#ifdef CONFIG_PM -static int skge_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata(pdev); - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - struct net_device *otherdev = pAC->dev[1]; - - if (netif_running(dev)) { - netif_carrier_off(dev); - DoPrintInterfaceChange = SK_FALSE; - SkDrvDeInitAdapter(pAC, 0); /* performs SkGeClose */ - netif_device_detach(dev); - } - if (otherdev != dev) { - if (netif_running(otherdev)) { - netif_carrier_off(otherdev); - DoPrintInterfaceChange = SK_FALSE; - SkDrvDeInitAdapter(pAC, 1); /* performs SkGeClose */ - netif_device_detach(otherdev); - } - } - - pci_save_state(pdev); - pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); - if (pAC->AllocFlag & SK_ALLOC_IRQ) { - free_irq(dev->irq, dev); - } - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - return 0; -} - -static int skge_resume(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - struct net_device *otherdev = pAC->dev[1]; - int ret; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - ret = pci_enable_device(pdev); - if (ret) { - printk(KERN_WARNING "sk98lin: unable to enable device %s " - "in resume\n", dev->name); - goto err_out; - } - pci_set_master(pdev); - if (pAC->GIni.GIMacsFound == 2) - ret = request_irq(dev->irq, SkGeIsr, IRQF_SHARED, "sk98lin", dev); - else - ret = request_irq(dev->irq, SkGeIsrOnePort, IRQF_SHARED, "sk98lin", dev); - if (ret) { - printk(KERN_WARNING "sk98lin: unable to acquire IRQ %d\n", dev->irq); - ret = -EBUSY; - goto err_out_disable_pdev; - } - - netif_device_attach(dev); - if (netif_running(dev)) { - DoPrintInterfaceChange = SK_FALSE; - SkDrvInitAdapter(pAC, 0); /* first device */ - } - if (otherdev != dev) { - netif_device_attach(otherdev); - if (netif_running(otherdev)) { - DoPrintInterfaceChange = SK_FALSE; - SkDrvInitAdapter(pAC, 1); /* second device */ - } - } - - return 0; - -err_out_disable_pdev: - pci_disable_device(pdev); -err_out: - pAC->AllocFlag &= ~SK_ALLOC_IRQ; - dev->irq = 0; - return ret; -} -#else -#define skge_suspend NULL -#define skge_resume NULL -#endif - -static struct pci_device_id skge_pci_tbl[] = { - { PCI_VENDOR_ID_3COM, 0x1700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, -/* DLink card does not have valid VPD so this driver gags - * { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - */ - { PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, }, - { PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { 0 } -}; - -MODULE_DEVICE_TABLE(pci, skge_pci_tbl); - -static struct pci_driver skge_driver = { - .name = "sk98lin", - .id_table = skge_pci_tbl, - .probe = skge_probe_one, - .remove = __devexit_p(skge_remove_one), - .suspend = skge_suspend, - .resume = skge_resume, -}; - -static int __init skge_init(void) -{ - printk(KERN_NOTICE "sk98lin: driver has been replaced by the skge driver" - " and is scheduled for removal\n"); - - return pci_register_driver(&skge_driver); -} - -static void __exit skge_exit(void) -{ - pci_unregister_driver(&skge_driver); -} - -module_init(skge_init); -module_exit(skge_exit); diff --git a/drivers/net/sk98lin/skgehwt.c b/drivers/net/sk98lin/skgehwt.c deleted file mode 100644 index db670993c2d..00000000000 --- a/drivers/net/sk98lin/skgehwt.c +++ /dev/null @@ -1,171 +0,0 @@ -/****************************************************************************** - * - * Name: skgehwt.c - * Project: Gigabit Ethernet Adapters, Event Scheduler Module - * Version: $Revision: 1.15 $ - * Date: $Date: 2003/09/16 13:41:23 $ - * Purpose: Hardware Timer - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - * Event queue and dispatcher - */ -#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) -static const char SysKonnectFileId[] = - "@(#) $Id: skgehwt.c,v 1.15 2003/09/16 13:41:23 rschmidt Exp $ (C) Marvell."; -#endif - -#include "h/skdrv1st.h" /* Driver Specific Definitions */ -#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ - -#ifdef __C2MAN__ -/* - * Hardware Timer function queue management. - */ -intro() -{} -#endif - -/* - * Prototypes of local functions. - */ -#define SK_HWT_MAX (65000) - -/* correction factor */ -#define SK_HWT_FAC (1000 * (SK_U32)pAC->GIni.GIHstClkFact / 100) - -/* - * Initialize hardware timer. - * - * Must be called during init level 1. - */ -void SkHwtInit( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc) /* IoContext */ -{ - pAC->Hwt.TStart = 0 ; - pAC->Hwt.TStop = 0 ; - pAC->Hwt.TActive = SK_FALSE; - - SkHwtStop(pAC, Ioc); -} - -/* - * - * Start hardware timer (clock ticks are 16us). - * - */ -void SkHwtStart( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc, /* IoContext */ -SK_U32 Time) /* Time in units of 16us to load the timer with. */ -{ - SK_U32 Cnt; - - if (Time > SK_HWT_MAX) - Time = SK_HWT_MAX; - - pAC->Hwt.TStart = Time; - pAC->Hwt.TStop = 0L; - - Cnt = Time; - - /* - * if time < 16 us - * time = 16 us - */ - if (!Cnt) { - Cnt++; - } - - SK_OUT32(Ioc, B2_TI_INI, Cnt * SK_HWT_FAC); - - SK_OUT16(Ioc, B2_TI_CTRL, TIM_START); /* Start timer. */ - - pAC->Hwt.TActive = SK_TRUE; -} - -/* - * Stop hardware timer. - * and clear the timer IRQ - */ -void SkHwtStop( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc) /* IoContext */ -{ - SK_OUT16(Ioc, B2_TI_CTRL, TIM_STOP); - - SK_OUT16(Ioc, B2_TI_CTRL, TIM_CLR_IRQ); - - pAC->Hwt.TActive = SK_FALSE; -} - - -/* - * Stop hardware timer and read time elapsed since last start. - * - * returns - * The elapsed time since last start in units of 16us. - * - */ -SK_U32 SkHwtRead( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc) /* IoContext */ -{ - SK_U32 TRead; - SK_U32 IStatus; - - if (pAC->Hwt.TActive) { - - SkHwtStop(pAC, Ioc); - - SK_IN32(Ioc, B2_TI_VAL, &TRead); - TRead /= SK_HWT_FAC; - - SK_IN32(Ioc, B0_ISRC, &IStatus); - - /* Check if timer expired (or wraped around) */ - if ((TRead > pAC->Hwt.TStart) || (IStatus & IS_TIMINT)) { - - SkHwtStop(pAC, Ioc); - - pAC->Hwt.TStop = pAC->Hwt.TStart; - } - else { - - pAC->Hwt.TStop = pAC->Hwt.TStart - TRead; - } - } - return(pAC->Hwt.TStop); -} - -/* - * interrupt source= timer - */ -void SkHwtIsr( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc) /* IoContext */ -{ - SkHwtStop(pAC, Ioc); - - pAC->Hwt.TStop = pAC->Hwt.TStart; - - SkTimerDone(pAC, Ioc); -} - -/* End of file */ diff --git a/drivers/net/sk98lin/skgeinit.c b/drivers/net/sk98lin/skgeinit.c deleted file mode 100644 index 67f1d6a5c15..00000000000 --- a/drivers/net/sk98lin/skgeinit.c +++ /dev/null @@ -1,2005 +0,0 @@ -/****************************************************************************** - * - * Name: skgeinit.c - * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.97 $ - * Date: $Date: 2003/10/02 16:45:31 $ - * Purpose: Contains functions to initialize the adapter - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#include "h/skdrv1st.h" -#include "h/skdrv2nd.h" - -/* global variables ***********************************************************/ - -/* local variables ************************************************************/ - -#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) -static const char SysKonnectFileId[] = - "@(#) $Id: skgeinit.c,v 1.97 2003/10/02 16:45:31 rschmidt Exp $ (C) Marvell."; -#endif - -struct s_QOffTab { - int RxQOff; /* Receive Queue Address Offset */ - int XsQOff; /* Sync Tx Queue Address Offset */ - int XaQOff; /* Async Tx Queue Address Offset */ -}; -static struct s_QOffTab QOffTab[] = { - {Q_R1, Q_XS1, Q_XA1}, {Q_R2, Q_XS2, Q_XA2} -}; - -struct s_Config { - char ScanString[8]; - SK_U32 Value; -}; - -static struct s_Config OemConfig = { - {'O','E','M','_','C','o','n','f'}, -#ifdef SK_OEM_CONFIG - OEM_CONFIG_VALUE, -#else - 0, -#endif -}; - -/****************************************************************************** - * - * SkGePollTxD() - Enable / Disable Descriptor Polling of TxD Rings - * - * Description: - * Enable or disable the descriptor polling of the transmit descriptor - * ring(s) (TxD) for port 'Port'. - * The new configuration is *not* saved over any SkGeStopPort() and - * SkGeInitPort() calls. - * - * Returns: - * nothing - */ -void SkGePollTxD( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL PollTxD) /* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */ -{ - SK_GEPORT *pPrt; - SK_U32 DWord; - - pPrt = &pAC->GIni.GP[Port]; - - DWord = (SK_U32)(PollTxD ? CSR_ENA_POL : CSR_DIS_POL); - - if (pPrt->PXSQSize != 0) { - SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), DWord); - } - - if (pPrt->PXAQSize != 0) { - SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), DWord); - } -} /* SkGePollTxD */ - - -/****************************************************************************** - * - * SkGeYellowLED() - Switch the yellow LED on or off. - * - * Description: - * Switch the yellow LED on or off. - * - * Note: - * This function may be called any time after SkGeInit(Level 1). - * - * Returns: - * nothing - */ -void SkGeYellowLED( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int State) /* yellow LED state, 0 = OFF, 0 != ON */ -{ - if (State == 0) { - /* Switch yellow LED OFF */ - SK_OUT8(IoC, B0_LED, LED_STAT_OFF); - } - else { - /* Switch yellow LED ON */ - SK_OUT8(IoC, B0_LED, LED_STAT_ON); - } -} /* SkGeYellowLED */ - - -#if (!defined(SK_SLIM) || defined(GENESIS)) -/****************************************************************************** - * - * SkGeXmitLED() - Modify the Operational Mode of a transmission LED. - * - * Description: - * The Rx or Tx LED which is specified by 'Led' will be - * enabled, disabled or switched on in test mode. - * - * Note: - * 'Led' must contain the address offset of the LEDs INI register. - * - * Usage: - * SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA); - * - * Returns: - * nothing - */ -void SkGeXmitLED( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Led, /* offset to the LED Init Value register */ -int Mode) /* Mode may be SK_LED_DIS, SK_LED_ENA, SK_LED_TST */ -{ - SK_U32 LedIni; - - switch (Mode) { - case SK_LED_ENA: - LedIni = SK_XMIT_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100; - SK_OUT32(IoC, Led + XMIT_LED_INI, LedIni); - SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START); - break; - case SK_LED_TST: - SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_ON); - SK_OUT32(IoC, Led + XMIT_LED_CNT, 100); - SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START); - break; - case SK_LED_DIS: - default: - /* - * Do NOT stop the LED Timer here. The LED might be - * in on state. But it needs to go off. - */ - SK_OUT32(IoC, Led + XMIT_LED_CNT, 0); - SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_OFF); - break; - } - - /* - * 1000BT: The Transmit LED is driven by the PHY. - * But the default LED configuration is used for - * Level One and Broadcom PHYs. - * (Broadcom: It may be that PHY_B_PEC_EN_LTR has to be set.) - * (In this case it has to be added here. But we will see. XXX) - */ -} /* SkGeXmitLED */ -#endif /* !SK_SLIM || GENESIS */ - - -/****************************************************************************** - * - * DoCalcAddr() - Calculates the start and the end address of a queue. - * - * Description: - * This function calculates the start and the end address of a queue. - * Afterwards the 'StartVal' is incremented to the next start position. - * If the port is already initialized the calculated values - * will be checked against the configured values and an - * error will be returned, if they are not equal. - * If the port is not initialized the values will be written to - * *StartAdr and *EndAddr. - * - * Returns: - * 0: success - * 1: configuration error - */ -static int DoCalcAddr( -SK_AC *pAC, /* adapter context */ -SK_GEPORT SK_FAR *pPrt, /* port index */ -int QuSize, /* size of the queue to configure in kB */ -SK_U32 SK_FAR *StartVal, /* start value for address calculation */ -SK_U32 SK_FAR *QuStartAddr,/* start addr to calculate */ -SK_U32 SK_FAR *QuEndAddr) /* end address to calculate */ -{ - SK_U32 EndVal; - SK_U32 NextStart; - int Rtv; - - Rtv = 0; - if (QuSize == 0) { - EndVal = *StartVal; - NextStart = EndVal; - } - else { - EndVal = *StartVal + ((SK_U32)QuSize * 1024) - 1; - NextStart = EndVal + 1; - } - - if (pPrt->PState >= SK_PRT_INIT) { - if (*StartVal != *QuStartAddr || EndVal != *QuEndAddr) { - Rtv = 1; - } - } - else { - *QuStartAddr = *StartVal; - *QuEndAddr = EndVal; - } - - *StartVal = NextStart; - return(Rtv); -} /* DoCalcAddr */ - -/****************************************************************************** - * - * SkGeInitAssignRamToQueues() - allocate default queue sizes - * - * Description: - * This function assigns the memory to the different queues and ports. - * When DualNet is set to SK_TRUE all ports get the same amount of memory. - * Otherwise the first port gets most of the memory and all the - * other ports just the required minimum. - * This function can only be called when pAC->GIni.GIRamSize and - * pAC->GIni.GIMacsFound have been initialized, usually this happens - * at init level 1 - * - * Returns: - * 0 - ok - * 1 - invalid input values - * 2 - not enough memory - */ - -int SkGeInitAssignRamToQueues( -SK_AC *pAC, /* Adapter context */ -int ActivePort, /* Active Port in RLMT mode */ -SK_BOOL DualNet) /* adapter context */ -{ - int i; - int UsedKilobytes; /* memory already assigned */ - int ActivePortKilobytes; /* memory available for active port */ - SK_GEPORT *pGePort; - - UsedKilobytes = 0; - - if (ActivePort >= pAC->GIni.GIMacsFound) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, - ("SkGeInitAssignRamToQueues: ActivePort (%d) invalid\n", - ActivePort)); - return(1); - } - if (((pAC->GIni.GIMacsFound * (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE)) + - ((RAM_QUOTA_SYNC == 0) ? 0 : SK_MIN_TXQ_SIZE)) > pAC->GIni.GIRamSize) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, - ("SkGeInitAssignRamToQueues: Not enough memory (%d)\n", - pAC->GIni.GIRamSize)); - return(2); - } - - if (DualNet) { - /* every port gets the same amount of memory */ - ActivePortKilobytes = pAC->GIni.GIRamSize / pAC->GIni.GIMacsFound; - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - - pGePort = &pAC->GIni.GP[i]; - - /* take away the minimum memory for active queues */ - ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE); - - /* receive queue gets the minimum + 80% of the rest */ - pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB(( - ActivePortKilobytes * (unsigned long) RAM_QUOTA_RX) / 100)) - + SK_MIN_RXQ_SIZE; - - ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE); - - /* synchronous transmit queue */ - pGePort->PXSQSize = 0; - - /* asynchronous transmit queue */ - pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes + - SK_MIN_TXQ_SIZE); - } - } - else { - /* Rlmt Mode or single link adapter */ - - /* Set standby queue size defaults for all standby ports */ - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - - if (i != ActivePort) { - pGePort = &pAC->GIni.GP[i]; - - pGePort->PRxQSize = SK_MIN_RXQ_SIZE; - pGePort->PXAQSize = SK_MIN_TXQ_SIZE; - pGePort->PXSQSize = 0; - - /* Count used RAM */ - UsedKilobytes += pGePort->PRxQSize + pGePort->PXAQSize; - } - } - /* what's left? */ - ActivePortKilobytes = pAC->GIni.GIRamSize - UsedKilobytes; - - /* assign it to the active port */ - /* first take away the minimum memory */ - ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE); - pGePort = &pAC->GIni.GP[ActivePort]; - - /* receive queue get's the minimum + 80% of the rest */ - pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB((ActivePortKilobytes * - (unsigned long) RAM_QUOTA_RX) / 100)) + SK_MIN_RXQ_SIZE; - - ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE); - - /* synchronous transmit queue */ - pGePort->PXSQSize = 0; - - /* asynchronous transmit queue */ - pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes) + - SK_MIN_TXQ_SIZE; - } -#ifdef VCPU - VCPUprintf(0, "PRxQSize=%u, PXSQSize=%u, PXAQSize=%u\n", - pGePort->PRxQSize, pGePort->PXSQSize, pGePort->PXAQSize); -#endif /* VCPU */ - - return(0); -} /* SkGeInitAssignRamToQueues */ - -/****************************************************************************** - * - * SkGeCheckQSize() - Checks the Adapters Queue Size Configuration - * - * Description: - * This function verifies the Queue Size Configuration specified - * in the variables PRxQSize, PXSQSize, and PXAQSize of all - * used ports. - * This requirements must be fullfilled to have a valid configuration: - * - The size of all queues must not exceed GIRamSize. - * - The queue sizes must be specified in units of 8 kB. - * - The size of Rx queues of available ports must not be - * smaller than 16 kB. - * - The size of at least one Tx queue (synch. or asynch.) - * of available ports must not be smaller than 16 kB - * when Jumbo Frames are used. - * - The RAM start and end addresses must not be changed - * for ports which are already initialized. - * Furthermore SkGeCheckQSize() defines the Start and End Addresses - * of all ports and stores them into the HWAC port structure. - * - * Returns: - * 0: Queue Size Configuration valid - * 1: Queue Size Configuration invalid - */ -static int SkGeCheckQSize( -SK_AC *pAC, /* adapter context */ -int Port) /* port index */ -{ - SK_GEPORT *pPrt; - int i; - int Rtv; - int Rtv2; - SK_U32 StartAddr; -#ifndef SK_SLIM - int UsedMem; /* total memory used (max. found ports) */ -#endif - - Rtv = 0; - -#ifndef SK_SLIM - - UsedMem = 0; - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - pPrt = &pAC->GIni.GP[i]; - - if ((pPrt->PRxQSize & QZ_UNITS) != 0 || - (pPrt->PXSQSize & QZ_UNITS) != 0 || - (pPrt->PXAQSize & QZ_UNITS) != 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG); - return(1); - } - - if (i == Port && pPrt->PRxQSize < SK_MIN_RXQ_SIZE) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E011, SKERR_HWI_E011MSG); - return(1); - } - - /* - * the size of at least one Tx queue (synch. or asynch.) has to be > 0. - * if Jumbo Frames are used, this size has to be >= 16 kB. - */ - if ((i == Port && pPrt->PXSQSize == 0 && pPrt->PXAQSize == 0) || - (pAC->GIni.GIPortUsage == SK_JUMBO_LINK && - ((pPrt->PXSQSize > 0 && pPrt->PXSQSize < SK_MIN_TXQ_SIZE) || - (pPrt->PXAQSize > 0 && pPrt->PXAQSize < SK_MIN_TXQ_SIZE)))) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E023, SKERR_HWI_E023MSG); - return(1); - } - - UsedMem += pPrt->PRxQSize + pPrt->PXSQSize + pPrt->PXAQSize; - } - - if (UsedMem > pAC->GIni.GIRamSize) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG); - return(1); - } -#endif /* !SK_SLIM */ - - /* Now start address calculation */ - StartAddr = pAC->GIni.GIRamOffs; - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - pPrt = &pAC->GIni.GP[i]; - - /* Calculate/Check values for the receive queue */ - Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PRxQSize, &StartAddr, - &pPrt->PRxQRamStart, &pPrt->PRxQRamEnd); - Rtv |= Rtv2; - - /* Calculate/Check values for the synchronous Tx queue */ - Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXSQSize, &StartAddr, - &pPrt->PXsQRamStart, &pPrt->PXsQRamEnd); - Rtv |= Rtv2; - - /* Calculate/Check values for the asynchronous Tx queue */ - Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXAQSize, &StartAddr, - &pPrt->PXaQRamStart, &pPrt->PXaQRamEnd); - Rtv |= Rtv2; - - if (Rtv) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E013, SKERR_HWI_E013MSG); - return(1); - } - } - - return(0); -} /* SkGeCheckQSize */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkGeInitMacArb() - Initialize the MAC Arbiter - * - * Description: - * This function initializes the MAC Arbiter. - * It must not be called if there is still an - * initialized or active port. - * - * Returns: - * nothing - */ -static void SkGeInitMacArb( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ -{ - /* release local reset */ - SK_OUT16(IoC, B3_MA_TO_CTRL, MA_RST_CLR); - - /* configure timeout values */ - SK_OUT8(IoC, B3_MA_TOINI_RX1, SK_MAC_TO_53); - SK_OUT8(IoC, B3_MA_TOINI_RX2, SK_MAC_TO_53); - SK_OUT8(IoC, B3_MA_TOINI_TX1, SK_MAC_TO_53); - SK_OUT8(IoC, B3_MA_TOINI_TX2, SK_MAC_TO_53); - - SK_OUT8(IoC, B3_MA_RCINI_RX1, 0); - SK_OUT8(IoC, B3_MA_RCINI_RX2, 0); - SK_OUT8(IoC, B3_MA_RCINI_TX1, 0); - SK_OUT8(IoC, B3_MA_RCINI_TX2, 0); - - /* recovery values are needed for XMAC II Rev. B2 only */ - /* Fast Output Enable Mode was intended to use with Rev. B2, but now? */ - - /* - * There is no start or enable button to push, therefore - * the MAC arbiter is configured and enabled now. - */ -} /* SkGeInitMacArb */ - - -/****************************************************************************** - * - * SkGeInitPktArb() - Initialize the Packet Arbiter - * - * Description: - * This function initializes the Packet Arbiter. - * It must not be called if there is still an - * initialized or active port. - * - * Returns: - * nothing - */ -static void SkGeInitPktArb( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ -{ - /* release local reset */ - SK_OUT16(IoC, B3_PA_CTRL, PA_RST_CLR); - - /* configure timeout values */ - SK_OUT16(IoC, B3_PA_TOINI_RX1, SK_PKT_TO_MAX); - SK_OUT16(IoC, B3_PA_TOINI_RX2, SK_PKT_TO_MAX); - SK_OUT16(IoC, B3_PA_TOINI_TX1, SK_PKT_TO_MAX); - SK_OUT16(IoC, B3_PA_TOINI_TX2, SK_PKT_TO_MAX); - - /* - * enable timeout timers if jumbo frames not used - * NOTE: the packet arbiter timeout interrupt is needed for - * half duplex hangup workaround - */ - if (pAC->GIni.GIPortUsage != SK_JUMBO_LINK) { - if (pAC->GIni.GIMacsFound == 1) { - SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1); - } - else { - SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1 | PA_ENA_TO_TX2); - } - } -} /* SkGeInitPktArb */ -#endif /* GENESIS */ - - -/****************************************************************************** - * - * SkGeInitMacFifo() - Initialize the MAC FIFOs - * - * Description: - * Initialize all MAC FIFOs of the specified port - * - * Returns: - * nothing - */ -static void SkGeInitMacFifo( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U16 Word; -#ifdef VCPU - SK_U32 DWord; -#endif /* VCPU */ - /* - * For each FIFO: - * - release local reset - * - use default value for MAC FIFO size - * - setup defaults for the control register - * - enable the FIFO - */ - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - /* Configure Rx MAC FIFO */ - SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_CLR); - SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_RX_CTRL_DEF); - SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_ENA_OP_MD); - - /* Configure Tx MAC FIFO */ - SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_CLR); - SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF); - SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_ENA_OP_MD); - - /* Enable frame flushing if jumbo frames used */ - if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { - SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_FLUSH); - } - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* set Rx GMAC FIFO Flush Mask */ - SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), (SK_U16)RX_FF_FL_DEF_MSK); - - Word = (SK_U16)GMF_RX_CTRL_DEF; - - /* disable Rx GMAC FIFO Flush for YUKON-Lite Rev. A0 only */ - if (pAC->GIni.GIYukonLite && pAC->GIni.GIChipId == CHIP_ID_YUKON) { - - Word &= ~GMF_RX_F_FL_ON; - } - - /* Configure Rx MAC FIFO */ - SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR); - SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), Word); - - /* set Rx GMAC FIFO Flush Threshold (default: 0x0a -> 56 bytes) */ - SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF); - - /* Configure Tx MAC FIFO */ - SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR); - SK_OUT16(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U16)GMF_TX_CTRL_DEF); - -#ifdef VCPU - SK_IN32(IoC, MR_ADDR(Port, RX_GMF_AF_THR), &DWord); - SK_IN32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), &DWord); -#endif /* VCPU */ - - /* set Tx GMAC FIFO Almost Empty Threshold */ -/* SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), 0); */ - } -#endif /* YUKON */ - -} /* SkGeInitMacFifo */ - -#ifdef SK_LNK_SYNC_CNT -/****************************************************************************** - * - * SkGeLoadLnkSyncCnt() - Load the Link Sync Counter and starts counting - * - * Description: - * This function starts the Link Sync Counter of the specified - * port and enables the generation of an Link Sync IRQ. - * The Link Sync Counter may be used to detect an active link, - * if autonegotiation is not used. - * - * Note: - * o To ensure receiving the Link Sync Event the LinkSyncCounter - * should be initialized BEFORE clearing the XMAC's reset! - * o Enable IS_LNK_SYNC_M1 and IS_LNK_SYNC_M2 after calling this - * function. - * - * Returns: - * nothing - */ -void SkGeLoadLnkSyncCnt( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_U32 CntVal) /* Counter value */ -{ - SK_U32 OrgIMsk; - SK_U32 NewIMsk; - SK_U32 ISrc; - SK_BOOL IrqPend; - - /* stop counter */ - SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_STOP); - - /* - * ASIC problem: - * Each time starting the Link Sync Counter an IRQ is generated - * by the adapter. See problem report entry from 21.07.98 - * - * Workaround: Disable Link Sync IRQ and clear the unexpeced IRQ - * if no IRQ is already pending. - */ - IrqPend = SK_FALSE; - SK_IN32(IoC, B0_ISRC, &ISrc); - SK_IN32(IoC, B0_IMSK, &OrgIMsk); - if (Port == MAC_1) { - NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M1; - if ((ISrc & IS_LNK_SYNC_M1) != 0) { - IrqPend = SK_TRUE; - } - } - else { - NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M2; - if ((ISrc & IS_LNK_SYNC_M2) != 0) { - IrqPend = SK_TRUE; - } - } - if (!IrqPend) { - SK_OUT32(IoC, B0_IMSK, NewIMsk); - } - - /* load counter */ - SK_OUT32(IoC, MR_ADDR(Port, LNK_SYNC_INI), CntVal); - - /* start counter */ - SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_START); - - if (!IrqPend) { - /* clear the unexpected IRQ, and restore the interrupt mask */ - SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_CLR_IRQ); - SK_OUT32(IoC, B0_IMSK, OrgIMsk); - } -} /* SkGeLoadLnkSyncCnt*/ -#endif /* SK_LNK_SYNC_CNT */ - -#if defined(SK_DIAG) || defined(SK_CFG_SYNC) -/****************************************************************************** - * - * SkGeCfgSync() - Configure synchronous bandwidth for this port. - * - * Description: - * This function may be used to configure synchronous bandwidth - * to the specified port. This may be done any time after - * initializing the port. The configuration values are NOT saved - * in the HWAC port structure and will be overwritten any - * time when stopping and starting the port. - * Any values for the synchronous configuration will be ignored - * if the size of the synchronous queue is zero! - * - * The default configuration for the synchronous service is - * TXA_ENA_FSYNC. This means if the size of - * the synchronous queue is unequal zero but no specific - * synchronous bandwidth is configured, the synchronous queue - * will always have the 'unlimited' transmit priority! - * - * This mode will be restored if the synchronous bandwidth is - * deallocated ('IntTime' = 0 and 'LimCount' = 0). - * - * Returns: - * 0: success - * 1: parameter configuration error - * 2: try to configure quality of service although no - * synchronous queue is configured - */ -int SkGeCfgSync( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_U32 IntTime, /* Interval Timer Value in units of 8ns */ -SK_U32 LimCount, /* Number of bytes to transfer during IntTime */ -int SyncMode) /* Sync Mode: TXA_ENA_ALLOC | TXA_DIS_ALLOC | 0 */ -{ - int Rtv; - - Rtv = 0; - - /* check the parameters */ - if (LimCount > IntTime || - (LimCount == 0 && IntTime != 0) || - (LimCount != 0 && IntTime == 0)) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG); - return(1); - } - - if (pAC->GIni.GP[Port].PXSQSize == 0) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E009, SKERR_HWI_E009MSG); - return(2); - } - - /* calculate register values */ - IntTime = (IntTime / 2) * pAC->GIni.GIHstClkFact / 100; - LimCount = LimCount / 8; - - if (IntTime > TXA_MAX_VAL || LimCount > TXA_MAX_VAL) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG); - return(1); - } - - /* - * - Enable 'Force Sync' to ensure the synchronous queue - * has the priority while configuring the new values. - * - Also 'disable alloc' to ensure the settings complies - * to the SyncMode parameter. - * - Disable 'Rate Control' to configure the new values. - * - write IntTime and LimCount - * - start 'Rate Control' and disable 'Force Sync' - * if Interval Timer or Limit Counter not zero. - */ - SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), - TXA_ENA_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC); - - SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), IntTime); - SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), LimCount); - - SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), - (SK_U8)(SyncMode & (TXA_ENA_ALLOC | TXA_DIS_ALLOC))); - - if (IntTime != 0 || LimCount != 0) { - SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_DIS_FSYNC | TXA_START_RC); - } - - return(0); -} /* SkGeCfgSync */ -#endif /* SK_DIAG || SK_CFG_SYNC*/ - - -/****************************************************************************** - * - * DoInitRamQueue() - Initialize the RAM Buffer Address of a single Queue - * - * Desccription: - * If the queue is used, enable and initialize it. - * Make sure the queue is still reset, if it is not used. - * - * Returns: - * nothing - */ -static void DoInitRamQueue( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int QuIoOffs, /* Queue IO Address Offset */ -SK_U32 QuStartAddr, /* Queue Start Address */ -SK_U32 QuEndAddr, /* Queue End Address */ -int QuType) /* Queue Type (SK_RX_SRAM_Q|SK_RX_BRAM_Q|SK_TX_RAM_Q) */ -{ - SK_U32 RxUpThresVal; - SK_U32 RxLoThresVal; - - if (QuStartAddr != QuEndAddr) { - /* calculate thresholds, assume we have a big Rx queue */ - RxUpThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_ULPP) / 8; - RxLoThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_LLPP_B)/8; - - /* build HW address format */ - QuStartAddr = QuStartAddr / 8; - QuEndAddr = QuEndAddr / 8; - - /* release local reset */ - SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_CLR); - - /* configure addresses */ - SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_START), QuStartAddr); - SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_END), QuEndAddr); - SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_WP), QuStartAddr); - SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RP), QuStartAddr); - - switch (QuType) { - case SK_RX_SRAM_Q: - /* configure threshold for small Rx Queue */ - RxLoThresVal += (SK_RB_LLPP_B - SK_RB_LLPP_S) / 8; - - /* continue with SK_RX_BRAM_Q */ - case SK_RX_BRAM_Q: - /* write threshold for Rx Queue */ - - SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_UTPP), RxUpThresVal); - SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_LTPP), RxLoThresVal); - - /* the high priority threshold not used */ - break; - case SK_TX_RAM_Q: - /* - * Do NOT use Store & Forward under normal operation due to - * performance optimization (GENESIS only). - * But if Jumbo Frames are configured (XMAC Tx FIFO is only 4 kB) - * or YUKON is used ((GMAC Tx FIFO is only 1 kB) - * we NEED Store & Forward of the RAM buffer. - */ - if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK || - pAC->GIni.GIYukon) { - /* enable Store & Forward Mode for the Tx Side */ - SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_STFWD); - } - break; - } - - /* set queue operational */ - SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_OP_MD); - } - else { - /* ensure the queue is still disabled */ - SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_SET); - } -} /* DoInitRamQueue */ - - -/****************************************************************************** - * - * SkGeInitRamBufs() - Initialize the RAM Buffer Queues - * - * Description: - * Initialize all RAM Buffer Queues of the specified port - * - * Returns: - * nothing - */ -static void SkGeInitRamBufs( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - int RxQType; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PRxQSize == SK_MIN_RXQ_SIZE) { - RxQType = SK_RX_SRAM_Q; /* small Rx Queue */ - } - else { - RxQType = SK_RX_BRAM_Q; /* big Rx Queue */ - } - - DoInitRamQueue(pAC, IoC, pPrt->PRxQOff, pPrt->PRxQRamStart, - pPrt->PRxQRamEnd, RxQType); - - DoInitRamQueue(pAC, IoC, pPrt->PXsQOff, pPrt->PXsQRamStart, - pPrt->PXsQRamEnd, SK_TX_RAM_Q); - - DoInitRamQueue(pAC, IoC, pPrt->PXaQOff, pPrt->PXaQRamStart, - pPrt->PXaQRamEnd, SK_TX_RAM_Q); - -} /* SkGeInitRamBufs */ - - -/****************************************************************************** - * - * SkGeInitRamIface() - Initialize the RAM Interface - * - * Description: - * This function initializes the Adapters RAM Interface. - * - * Note: - * This function is used in the diagnostics. - * - * Returns: - * nothing - */ -static void SkGeInitRamIface( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ -{ - /* release local reset */ - SK_OUT16(IoC, B3_RI_CTRL, RI_RST_CLR); - - /* configure timeout values */ - SK_OUT8(IoC, B3_RI_WTO_R1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_WTO_XA1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_WTO_XS1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_R1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_XA1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_XS1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_WTO_R2, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_WTO_XA2, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_WTO_XS2, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_R2, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_XA2, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_XS2, SK_RI_TO_53); - -} /* SkGeInitRamIface */ - - -/****************************************************************************** - * - * SkGeInitBmu() - Initialize the BMU state machines - * - * Description: - * Initialize all BMU state machines of the specified port - * - * Returns: - * nothing - */ -static void SkGeInitBmu( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U32 RxWm; - SK_U32 TxWm; - - pPrt = &pAC->GIni.GP[Port]; - - RxWm = SK_BMU_RX_WM; - TxWm = SK_BMU_TX_WM; - - if (!pAC->GIni.GIPciSlot64 && !pAC->GIni.GIPciClock66) { - /* for better performance */ - RxWm /= 2; - TxWm /= 2; - } - - /* Rx Queue: Release all local resets and set the watermark */ - SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_CLR_RESET); - SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_F), RxWm); - - /* - * Tx Queue: Release all local resets if the queue is used ! - * set watermark - */ - if (pPrt->PXSQSize != 0) { - SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_CLR_RESET); - SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_F), TxWm); - } - - if (pPrt->PXAQSize != 0) { - SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_CLR_RESET); - SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_F), TxWm); - } - /* - * Do NOT enable the descriptor poll timers here, because - * the descriptor addresses are not specified yet. - */ -} /* SkGeInitBmu */ - - -/****************************************************************************** - * - * TestStopBit() - Test the stop bit of the queue - * - * Description: - * Stopping a queue is not as simple as it seems to be. - * If descriptor polling is enabled, it may happen - * that RX/TX stop is done and SV idle is NOT set. - * In this case we have to issue another stop command. - * - * Returns: - * The queues control status register - */ -static SK_U32 TestStopBit( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int QuIoOffs) /* Queue IO Address Offset */ -{ - SK_U32 QuCsr; /* CSR contents */ - - SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr); - - if ((QuCsr & (CSR_STOP | CSR_SV_IDLE)) == 0) { - /* Stop Descriptor overridden by start command */ - SK_OUT32(IoC, Q_ADDR(QuIoOffs, Q_CSR), CSR_STOP); - - SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr); - } - - return(QuCsr); -} /* TestStopBit */ - - -/****************************************************************************** - * - * SkGeStopPort() - Stop the Rx/Tx activity of the port 'Port'. - * - * Description: - * After calling this function the descriptor rings and Rx and Tx - * queues of this port may be reconfigured. - * - * It is possible to stop the receive and transmit path separate or - * both together. - * - * Dir = SK_STOP_TX Stops the transmit path only and resets the MAC. - * The receive queue is still active and - * the pending Rx frames may be still transferred - * into the RxD. - * SK_STOP_RX Stop the receive path. The tansmit path - * has to be stopped once before. - * SK_STOP_ALL SK_STOP_TX + SK_STOP_RX - * - * RstMode = SK_SOFT_RST Resets the MAC. The PHY is still alive. - * SK_HARD_RST Resets the MAC and the PHY. - * - * Example: - * 1) A Link Down event was signaled for a port. Therefore the activity - * of this port should be stopped and a hardware reset should be issued - * to enable the workaround of XMAC Errata #2. But the received frames - * should not be discarded. - * ... - * SkGeStopPort(pAC, IoC, Port, SK_STOP_TX, SK_HARD_RST); - * (transfer all pending Rx frames) - * SkGeStopPort(pAC, IoC, Port, SK_STOP_RX, SK_HARD_RST); - * ... - * - * 2) An event was issued which request the driver to switch - * the 'virtual active' link to an other already active port - * as soon as possible. The frames in the receive queue of this - * port may be lost. But the PHY must not be reset during this - * event. - * ... - * SkGeStopPort(pAC, IoC, Port, SK_STOP_ALL, SK_SOFT_RST); - * ... - * - * Extended Description: - * If SK_STOP_TX is set, - * o disable the MAC's receive and transmitter to prevent - * from sending incomplete frames - * o stop the port's transmit queues before terminating the - * BMUs to prevent from performing incomplete PCI cycles - * on the PCI bus - * - The network Rx and Tx activity and PCI Tx transfer is - * disabled now. - * o reset the MAC depending on the RstMode - * o Stop Interval Timer and Limit Counter of Tx Arbiter, - * also disable Force Sync bit and Enable Alloc bit. - * o perform a local reset of the port's Tx path - * - reset the PCI FIFO of the async Tx queue - * - reset the PCI FIFO of the sync Tx queue - * - reset the RAM Buffer async Tx queue - * - reset the RAM Buffer sync Tx queue - * - reset the MAC Tx FIFO - * o switch Link and Tx LED off, stop the LED counters - * - * If SK_STOP_RX is set, - * o stop the port's receive queue - * - The path data transfer activity is fully stopped now. - * o perform a local reset of the port's Rx path - * - reset the PCI FIFO of the Rx queue - * - reset the RAM Buffer receive queue - * - reset the MAC Rx FIFO - * o switch Rx LED off, stop the LED counter - * - * If all ports are stopped, - * o reset the RAM Interface. - * - * Notes: - * o This function may be called during the driver states RESET_PORT and - * SWITCH_PORT. - */ -void SkGeStopPort( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -int Port, /* port to stop (MAC_1 + n) */ -int Dir, /* Direction to Stop (SK_STOP_RX, SK_STOP_TX, SK_STOP_ALL) */ -int RstMode)/* Reset Mode (SK_SOFT_RST, SK_HARD_RST) */ -{ -#ifndef SK_DIAG - SK_EVPARA Para; -#endif /* !SK_DIAG */ - SK_GEPORT *pPrt; - SK_U32 DWord; - SK_U32 XsCsr; - SK_U32 XaCsr; - SK_U64 ToutStart; - int i; - int ToutCnt; - - pPrt = &pAC->GIni.GP[Port]; - - if ((Dir & SK_STOP_TX) != 0) { - /* disable receiver and transmitter */ - SkMacRxTxDisable(pAC, IoC, Port); - - /* stop both transmit queues */ - /* - * If the BMU is in the reset state CSR_STOP will terminate - * immediately. - */ - SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_STOP); - SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_STOP); - - ToutStart = SkOsGetTime(pAC); - ToutCnt = 0; - do { - /* - * Clear packet arbiter timeout to make sure - * this loop will terminate. - */ - SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ? - PA_CLR_TO_TX1 : PA_CLR_TO_TX2)); - - /* - * If the transfer stucks at the MAC the STOP command will not - * terminate if we don't flush the XMAC's transmit FIFO ! - */ - SkMacFlushTxFifo(pAC, IoC, Port); - - XsCsr = TestStopBit(pAC, IoC, pPrt->PXsQOff); - XaCsr = TestStopBit(pAC, IoC, pPrt->PXaQOff); - - if (SkOsGetTime(pAC) - ToutStart > (SK_TICKS_PER_SEC / 18)) { - /* - * Timeout of 1/18 second reached. - * This needs to be checked at 1/18 sec only. - */ - ToutCnt++; - if (ToutCnt > 1) { - /* Might be a problem when the driver event handler - * calls StopPort again. XXX. - */ - - /* Fatal Error, Loop aborted */ - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E018, - SKERR_HWI_E018MSG); -#ifndef SK_DIAG - Para.Para64 = Port; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); -#endif /* !SK_DIAG */ - return; - } - /* - * Cache incoherency workaround: Assume a start command - * has been lost while sending the frame. - */ - ToutStart = SkOsGetTime(pAC); - - if ((XsCsr & CSR_STOP) != 0) { - SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_START); - } - if ((XaCsr & CSR_STOP) != 0) { - SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_START); - } - } - - /* - * Because of the ASIC problem report entry from 21.08.1998 it is - * required to wait until CSR_STOP is reset and CSR_SV_IDLE is set. - */ - } while ((XsCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE || - (XaCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE); - - /* Reset the MAC depending on the RstMode */ - if (RstMode == SK_SOFT_RST) { - SkMacSoftRst(pAC, IoC, Port); - } - else { - SkMacHardRst(pAC, IoC, Port); - } - - /* Disable Force Sync bit and Enable Alloc bit */ - SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), - TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC); - - /* Stop Interval Timer and Limit Counter of Tx Arbiter */ - SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), 0L); - SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), 0L); - - /* Perform a local reset of the port's Tx path */ - - /* Reset the PCI FIFO of the async Tx queue */ - SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_SET_RESET); - /* Reset the PCI FIFO of the sync Tx queue */ - SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_SET_RESET); - /* Reset the RAM Buffer async Tx queue */ - SK_OUT8(IoC, RB_ADDR(pPrt->PXaQOff, RB_CTRL), RB_RST_SET); - /* Reset the RAM Buffer sync Tx queue */ - SK_OUT8(IoC, RB_ADDR(pPrt->PXsQOff, RB_CTRL), RB_RST_SET); - - /* Reset Tx MAC FIFO */ -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - /* Note: MFF_RST_SET does NOT reset the XMAC ! */ - SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_SET); - - /* switch Link and Tx LED off, stop the LED counters */ - /* Link LED is switched off by the RLMT and the Diag itself */ - SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_DIS); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* Reset TX MAC FIFO */ - SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_SET); - } -#endif /* YUKON */ - } - - if ((Dir & SK_STOP_RX) != 0) { - /* - * The RX Stop Command will not terminate if no buffers - * are queued in the RxD ring. But it will always reach - * the Idle state. Therefore we can use this feature to - * stop the transfer of received packets. - */ - /* stop the port's receive queue */ - SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_STOP); - - i = 100; - do { - /* - * Clear packet arbiter timeout to make sure - * this loop will terminate - */ - SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ? - PA_CLR_TO_RX1 : PA_CLR_TO_RX2)); - - DWord = TestStopBit(pAC, IoC, pPrt->PRxQOff); - - /* timeout if i==0 (bug fix for #10748) */ - if (--i == 0) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E024, - SKERR_HWI_E024MSG); - break; - } - /* - * because of the ASIC problem report entry from 21.08.98 - * it is required to wait until CSR_STOP is reset and - * CSR_SV_IDLE is set. - */ - } while ((DWord & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE); - - /* The path data transfer activity is fully stopped now */ - - /* Perform a local reset of the port's Rx path */ - - /* Reset the PCI FIFO of the Rx queue */ - SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_SET_RESET); - /* Reset the RAM Buffer receive queue */ - SK_OUT8(IoC, RB_ADDR(pPrt->PRxQOff, RB_CTRL), RB_RST_SET); - - /* Reset Rx MAC FIFO */ -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_SET); - - /* switch Rx LED off, stop the LED counter */ - SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_DIS); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* Reset Rx MAC FIFO */ - SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_SET); - } -#endif /* YUKON */ - } -} /* SkGeStopPort */ - - -/****************************************************************************** - * - * SkGeInit0() - Level 0 Initialization - * - * Description: - * - Initialize the BMU address offsets - * - * Returns: - * nothing - */ -static void SkGeInit0( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ -{ - int i; - SK_GEPORT *pPrt; - - for (i = 0; i < SK_MAX_MACS; i++) { - pPrt = &pAC->GIni.GP[i]; - - pPrt->PState = SK_PRT_RESET; - pPrt->PRxQOff = QOffTab[i].RxQOff; - pPrt->PXsQOff = QOffTab[i].XsQOff; - pPrt->PXaQOff = QOffTab[i].XaQOff; - pPrt->PCheckPar = SK_FALSE; - pPrt->PIsave = 0; - pPrt->PPrevShorts = 0; - pPrt->PLinkResCt = 0; - pPrt->PAutoNegTOCt = 0; - pPrt->PPrevRx = 0; - pPrt->PPrevFcs = 0; - pPrt->PRxLim = SK_DEF_RX_WA_LIM; - pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL; - pPrt->PLinkSpeedCap = (SK_U8)SK_LSPEED_CAP_1000MBPS; - pPrt->PLinkSpeed = (SK_U8)SK_LSPEED_1000MBPS; - pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_UNKNOWN; - pPrt->PLinkModeConf = (SK_U8)SK_LMODE_AUTOSENSE; - pPrt->PFlowCtrlMode = (SK_U8)SK_FLOW_MODE_SYM_OR_REM; - pPrt->PLinkCap = (SK_U8)(SK_LMODE_CAP_HALF | SK_LMODE_CAP_FULL | - SK_LMODE_CAP_AUTOHALF | SK_LMODE_CAP_AUTOFULL); - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN; - pPrt->PFlowCtrlCap = (SK_U8)SK_FLOW_MODE_SYM_OR_REM; - pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE; - pPrt->PMSCap = 0; - pPrt->PMSMode = (SK_U8)SK_MS_MODE_AUTO; - pPrt->PMSStatus = (SK_U8)SK_MS_STAT_UNSET; - pPrt->PLipaAutoNeg = (SK_U8)SK_LIPA_UNKNOWN; - pPrt->PAutoNegFail = SK_FALSE; - pPrt->PHWLinkUp = SK_FALSE; - pPrt->PLinkBroken = SK_TRUE; /* See WA code */ - pPrt->PPhyPowerState = PHY_PM_OPERATIONAL_MODE; - pPrt->PMacColThres = TX_COL_DEF; - pPrt->PMacJamLen = TX_JAM_LEN_DEF; - pPrt->PMacJamIpgVal = TX_JAM_IPG_DEF; - pPrt->PMacJamIpgData = TX_IPG_JAM_DEF; - pPrt->PMacIpgData = IPG_DATA_DEF; - pPrt->PMacLimit4 = SK_FALSE; - } - - pAC->GIni.GIPortUsage = SK_RED_LINK; - pAC->GIni.GILedBlinkCtrl = (SK_U16)OemConfig.Value; - pAC->GIni.GIValIrqMask = IS_ALL_MSK; - -} /* SkGeInit0*/ - - -/****************************************************************************** - * - * SkGeInit1() - Level 1 Initialization - * - * Description: - * o Do a software reset. - * o Clear all reset bits. - * o Verify that the detected hardware is present. - * Return an error if not. - * o Get the hardware configuration - * + Read the number of MACs/Ports. - * + Read the RAM size. - * + Read the PCI Revision Id. - * + Find out the adapters host clock speed - * + Read and check the PHY type - * - * Returns: - * 0: success - * 5: Unexpected PHY type detected - * 6: HW self test failed - */ -static int SkGeInit1( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ -{ - SK_U8 Byte; - SK_U16 Word; - SK_U16 CtrlStat; - SK_U32 DWord; - int RetVal; - int i; - - RetVal = 0; - - /* save CLK_RUN bits (YUKON-Lite) */ - SK_IN16(IoC, B0_CTST, &CtrlStat); - - /* do the SW-reset */ - SK_OUT8(IoC, B0_CTST, CS_RST_SET); - - /* release the SW-reset */ - SK_OUT8(IoC, B0_CTST, CS_RST_CLR); - - /* reset all error bits in the PCI STATUS register */ - /* - * Note: PCI Cfg cycles cannot be used, because they are not - * available on some platforms after 'boot time'. - */ - SK_IN16(IoC, PCI_C(PCI_STATUS), &Word); - - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); - SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS)); - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); - - /* release Master Reset */ - SK_OUT8(IoC, B0_CTST, CS_MRST_CLR); - -#ifdef CLK_RUN - CtrlStat |= CS_CLK_RUN_ENA; -#endif /* CLK_RUN */ - - /* restore CLK_RUN bits */ - SK_OUT16(IoC, B0_CTST, (SK_U16)(CtrlStat & - (CS_CLK_RUN_HOT | CS_CLK_RUN_RST | CS_CLK_RUN_ENA))); - - /* read Chip Identification Number */ - SK_IN8(IoC, B2_CHIP_ID, &Byte); - pAC->GIni.GIChipId = Byte; - - /* read number of MACs */ - SK_IN8(IoC, B2_MAC_CFG, &Byte); - pAC->GIni.GIMacsFound = (Byte & CFG_SNG_MAC) ? 1 : 2; - - /* get Chip Revision Number */ - pAC->GIni.GIChipRev = (SK_U8)((Byte & CFG_CHIP_R_MSK) >> 4); - - /* get diff. PCI parameters */ - SK_IN16(IoC, B0_CTST, &CtrlStat); - - /* read the adapters RAM size */ - SK_IN8(IoC, B2_E_0, &Byte); - - pAC->GIni.GIGenesis = SK_FALSE; - pAC->GIni.GIYukon = SK_FALSE; - pAC->GIni.GIYukonLite = SK_FALSE; - -#ifdef GENESIS - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { - - pAC->GIni.GIGenesis = SK_TRUE; - - if (Byte == (SK_U8)3) { - /* special case: 4 x 64k x 36, offset = 0x80000 */ - pAC->GIni.GIRamSize = 1024; - pAC->GIni.GIRamOffs = (SK_U32)512 * 1024; - } - else { - pAC->GIni.GIRamSize = (int)Byte * 512; - pAC->GIni.GIRamOffs = 0; - } - /* all GE adapters work with 53.125 MHz host clock */ - pAC->GIni.GIHstClkFact = SK_FACT_53; - - /* set Descr. Poll Timer Init Value to 250 ms */ - pAC->GIni.GIPollTimerVal = - SK_DPOLL_DEF * (SK_U32)pAC->GIni.GIHstClkFact / 100; - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIChipId != CHIP_ID_GENESIS) { - - pAC->GIni.GIYukon = SK_TRUE; - - pAC->GIni.GIRamSize = (Byte == (SK_U8)0) ? 128 : (int)Byte * 4; - - pAC->GIni.GIRamOffs = 0; - - /* WA for chip Rev. A */ - pAC->GIni.GIWolOffs = (pAC->GIni.GIChipId == CHIP_ID_YUKON && - pAC->GIni.GIChipRev == 0) ? WOL_REG_OFFS : 0; - - /* get PM Capabilities of PCI config space */ - SK_IN16(IoC, PCI_C(PCI_PM_CAP_REG), &Word); - - /* check if VAUX is available */ - if (((CtrlStat & CS_VAUX_AVAIL) != 0) && - /* check also if PME from D3cold is set */ - ((Word & PCI_PME_D3C_SUP) != 0)) { - /* set entry in GE init struct */ - pAC->GIni.GIVauxAvail = SK_TRUE; - } - - if (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) { - /* this is Rev. A1 */ - pAC->GIni.GIYukonLite = SK_TRUE; - } - else { - /* save Flash-Address Register */ - SK_IN32(IoC, B2_FAR, &DWord); - - /* test Flash-Address Register */ - SK_OUT8(IoC, B2_FAR + 3, 0xff); - SK_IN8(IoC, B2_FAR + 3, &Byte); - - if (Byte != 0) { - /* this is Rev. A0 */ - pAC->GIni.GIYukonLite = SK_TRUE; - - /* restore Flash-Address Register */ - SK_OUT32(IoC, B2_FAR, DWord); - } - } - - /* switch power to VCC (WA for VAUX problem) */ - SK_OUT8(IoC, B0_POWER_CTRL, (SK_U8)(PC_VAUX_ENA | PC_VCC_ENA | - PC_VAUX_OFF | PC_VCC_ON)); - - /* read the Interrupt source */ - SK_IN32(IoC, B0_ISRC, &DWord); - - if ((DWord & IS_HW_ERR) != 0) { - /* read the HW Error Interrupt source */ - SK_IN32(IoC, B0_HWE_ISRC, &DWord); - - if ((DWord & IS_IRQ_SENSOR) != 0) { - /* disable HW Error IRQ */ - pAC->GIni.GIValIrqMask &= ~IS_HW_ERR; - } - } - - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - /* set GMAC Link Control reset */ - SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_SET); - - /* clear GMAC Link Control reset */ - SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_CLR); - } - /* all YU chips work with 78.125 MHz host clock */ - pAC->GIni.GIHstClkFact = SK_FACT_78; - - pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX; /* 215 ms */ - } -#endif /* YUKON */ - - /* check if 64-bit PCI Slot is present */ - pAC->GIni.GIPciSlot64 = (SK_BOOL)((CtrlStat & CS_BUS_SLOT_SZ) != 0); - - /* check if 66 MHz PCI Clock is active */ - pAC->GIni.GIPciClock66 = (SK_BOOL)((CtrlStat & CS_BUS_CLOCK) != 0); - - /* read PCI HW Revision Id. */ - SK_IN8(IoC, PCI_C(PCI_REV_ID), &Byte); - pAC->GIni.GIPciHwRev = Byte; - - /* read the PMD type */ - SK_IN8(IoC, B2_PMD_TYP, &Byte); - pAC->GIni.GICopperType = (SK_U8)(Byte == 'T'); - - /* read the PHY type */ - SK_IN8(IoC, B2_E_1, &Byte); - - Byte &= 0x0f; /* the PHY type is stored in the lower nibble */ - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - switch (Byte) { - case SK_PHY_XMAC: - pAC->GIni.GP[i].PhyAddr = PHY_ADDR_XMAC; - break; - case SK_PHY_BCOM: - pAC->GIni.GP[i].PhyAddr = PHY_ADDR_BCOM; - pAC->GIni.GP[i].PMSCap = (SK_U8)(SK_MS_CAP_AUTO | - SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE); - break; -#ifdef OTHER_PHY - case SK_PHY_LONE: - pAC->GIni.GP[i].PhyAddr = PHY_ADDR_LONE; - break; - case SK_PHY_NAT: - pAC->GIni.GP[i].PhyAddr = PHY_ADDR_NAT; - break; -#endif /* OTHER_PHY */ - default: - /* ERROR: unexpected PHY type detected */ - RetVal = 5; - break; - } - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - if (Byte < (SK_U8)SK_PHY_MARV_COPPER) { - /* if this field is not initialized */ - Byte = (SK_U8)SK_PHY_MARV_COPPER; - - pAC->GIni.GICopperType = SK_TRUE; - } - - pAC->GIni.GP[i].PhyAddr = PHY_ADDR_MARV; - - if (pAC->GIni.GICopperType) { - - pAC->GIni.GP[i].PLinkSpeedCap = (SK_U8)(SK_LSPEED_CAP_AUTO | - SK_LSPEED_CAP_10MBPS | SK_LSPEED_CAP_100MBPS | - SK_LSPEED_CAP_1000MBPS); - - pAC->GIni.GP[i].PLinkSpeed = (SK_U8)SK_LSPEED_AUTO; - - pAC->GIni.GP[i].PMSCap = (SK_U8)(SK_MS_CAP_AUTO | - SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE); - } - else { - Byte = (SK_U8)SK_PHY_MARV_FIBER; - } - } -#endif /* YUKON */ - - pAC->GIni.GP[i].PhyType = (int)Byte; - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, - ("PHY type: %d PHY addr: %04x\n", Byte, - pAC->GIni.GP[i].PhyAddr)); - } - - /* get MAC Type & set function pointers dependent on */ -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - pAC->GIni.GIMacType = SK_MAC_XMAC; - - pAC->GIni.GIFunc.pFnMacUpdateStats = SkXmUpdateStats; - pAC->GIni.GIFunc.pFnMacStatistic = SkXmMacStatistic; - pAC->GIni.GIFunc.pFnMacResetCounter = SkXmResetCounter; - pAC->GIni.GIFunc.pFnMacOverflow = SkXmOverflowStatus; - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - pAC->GIni.GIMacType = SK_MAC_GMAC; - - pAC->GIni.GIFunc.pFnMacUpdateStats = SkGmUpdateStats; - pAC->GIni.GIFunc.pFnMacStatistic = SkGmMacStatistic; - pAC->GIni.GIFunc.pFnMacResetCounter = SkGmResetCounter; - pAC->GIni.GIFunc.pFnMacOverflow = SkGmOverflowStatus; - -#ifdef SPECIAL_HANDLING - if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { - /* check HW self test result */ - SK_IN8(IoC, B2_E_3, &Byte); - if (Byte & B2_E3_RES_MASK) { - RetVal = 6; - } - } -#endif - } -#endif /* YUKON */ - - return(RetVal); -} /* SkGeInit1 */ - - -/****************************************************************************** - * - * SkGeInit2() - Level 2 Initialization - * - * Description: - * - start the Blink Source Counter - * - start the Descriptor Poll Timer - * - configure the MAC-Arbiter - * - configure the Packet-Arbiter - * - enable the Tx Arbiters - * - enable the RAM Interface Arbiter - * - * Returns: - * nothing - */ -static void SkGeInit2( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ -{ -#ifdef GENESIS - SK_U32 DWord; -#endif /* GENESIS */ - int i; - - /* start the Descriptor Poll Timer */ - if (pAC->GIni.GIPollTimerVal != 0) { - if (pAC->GIni.GIPollTimerVal > SK_DPOLL_MAX) { - pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX; - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E017, SKERR_HWI_E017MSG); - } - SK_OUT32(IoC, B28_DPT_INI, pAC->GIni.GIPollTimerVal); - SK_OUT8(IoC, B28_DPT_CTRL, DPT_START); - } - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - /* start the Blink Source Counter */ - DWord = SK_BLK_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100; - - SK_OUT32(IoC, B2_BSC_INI, DWord); - SK_OUT8(IoC, B2_BSC_CTRL, BSC_START); - - /* - * Configure the MAC Arbiter and the Packet Arbiter. - * They will be started once and never be stopped. - */ - SkGeInitMacArb(pAC, IoC); - - SkGeInitPktArb(pAC, IoC); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* start Time Stamp Timer */ - SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_START); - } -#endif /* YUKON */ - - /* enable the Tx Arbiters */ - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - SK_OUT8(IoC, MR_ADDR(i, TXA_CTRL), TXA_ENA_ARB); - } - - /* enable the RAM Interface Arbiter */ - SkGeInitRamIface(pAC, IoC); - -} /* SkGeInit2 */ - -/****************************************************************************** - * - * SkGeInit() - Initialize the GE Adapter with the specified level. - * - * Description: - * Level 0: Initialize the Module structures. - * Level 1: Generic Hardware Initialization. The IOP/MemBase pointer has - * to be set before calling this level. - * - * o Do a software reset. - * o Clear all reset bits. - * o Verify that the detected hardware is present. - * Return an error if not. - * o Get the hardware configuration - * + Set GIMacsFound with the number of MACs. - * + Store the RAM size in GIRamSize. - * + Save the PCI Revision ID in GIPciHwRev. - * o return an error - * if Number of MACs > SK_MAX_MACS - * - * After returning from Level 0 the adapter - * may be accessed with IO operations. - * - * Level 2: start the Blink Source Counter - * - * Returns: - * 0: success - * 1: Number of MACs exceeds SK_MAX_MACS (after level 1) - * 2: Adapter not present or not accessible - * 3: Illegal initialization level - * 4: Initialization Level 1 Call missing - * 5: Unexpected PHY type detected - * 6: HW self test failed - */ -int SkGeInit( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Level) /* initialization level */ -{ - int RetVal; /* return value */ - SK_U32 DWord; - - RetVal = 0; - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, - ("SkGeInit(Level %d)\n", Level)); - - switch (Level) { - case SK_INIT_DATA: - /* Initialization Level 0 */ - SkGeInit0(pAC, IoC); - pAC->GIni.GILevel = SK_INIT_DATA; - break; - - case SK_INIT_IO: - /* Initialization Level 1 */ - RetVal = SkGeInit1(pAC, IoC); - if (RetVal != 0) { - break; - } - - /* check if the adapter seems to be accessible */ - SK_OUT32(IoC, B2_IRQM_INI, SK_TEST_VAL); - SK_IN32(IoC, B2_IRQM_INI, &DWord); - SK_OUT32(IoC, B2_IRQM_INI, 0L); - - if (DWord != SK_TEST_VAL) { - RetVal = 2; - break; - } - - /* check if the number of GIMacsFound matches SK_MAX_MACS */ - if (pAC->GIni.GIMacsFound > SK_MAX_MACS) { - RetVal = 1; - break; - } - - /* Level 1 successfully passed */ - pAC->GIni.GILevel = SK_INIT_IO; - break; - - case SK_INIT_RUN: - /* Initialization Level 2 */ - if (pAC->GIni.GILevel != SK_INIT_IO) { -#ifndef SK_DIAG - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E002, SKERR_HWI_E002MSG); -#endif /* !SK_DIAG */ - RetVal = 4; - break; - } - SkGeInit2(pAC, IoC); - - /* Level 2 successfully passed */ - pAC->GIni.GILevel = SK_INIT_RUN; - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E003, SKERR_HWI_E003MSG); - RetVal = 3; - break; - } - - return(RetVal); -} /* SkGeInit */ - - -/****************************************************************************** - * - * SkGeDeInit() - Deinitialize the adapter - * - * Description: - * All ports of the adapter will be stopped if not already done. - * Do a software reset and switch off all LEDs. - * - * Returns: - * nothing - */ -void SkGeDeInit( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ -{ - int i; - SK_U16 Word; - -#if (!defined(SK_SLIM) && !defined(VCPU)) - /* ensure I2C is ready */ - SkI2cWaitIrq(pAC, IoC); -#endif - - /* stop all current transfer activity */ - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - if (pAC->GIni.GP[i].PState != SK_PRT_STOP && - pAC->GIni.GP[i].PState != SK_PRT_RESET) { - - SkGeStopPort(pAC, IoC, i, SK_STOP_ALL, SK_HARD_RST); - } - } - - /* Reset all bits in the PCI STATUS register */ - /* - * Note: PCI Cfg cycles cannot be used, because they are not - * available on some platforms after 'boot time'. - */ - SK_IN16(IoC, PCI_C(PCI_STATUS), &Word); - - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); - SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS)); - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); - - /* do the reset, all LEDs are switched off now */ - SK_OUT8(IoC, B0_CTST, CS_RST_SET); - - pAC->GIni.GILevel = SK_INIT_DATA; -} /* SkGeDeInit */ - - -/****************************************************************************** - * - * SkGeInitPort() Initialize the specified port. - * - * Description: - * PRxQSize, PXSQSize, and PXAQSize has to be - * configured for the specified port before calling this function. - * The descriptor rings has to be initialized too. - * - * o (Re)configure queues of the specified port. - * o configure the MAC of the specified port. - * o put ASIC and MAC(s) in operational mode. - * o initialize Rx/Tx and Sync LED - * o initialize RAM Buffers and MAC FIFOs - * - * The port is ready to connect when returning. - * - * Note: - * The MAC's Rx and Tx state machine is still disabled when returning. - * - * Returns: - * 0: success - * 1: Queue size initialization error. The configured values - * for PRxQSize, PXSQSize, or PXAQSize are invalid for one - * or more queues. The specified port was NOT initialized. - * An error log entry was generated. - * 2: The port has to be stopped before it can be initialized again. - */ -int SkGeInitPort( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port to configure */ -{ - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - if (SkGeCheckQSize(pAC, Port) != 0) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E004, SKERR_HWI_E004MSG); - return(1); - } - - if (pPrt->PState == SK_PRT_INIT || pPrt->PState == SK_PRT_RUN) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E005, SKERR_HWI_E005MSG); - return(2); - } - - /* configuration ok, initialize the Port now */ - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - /* initialize Rx, Tx and Link LED */ - /* - * If 1000BT Phy needs LED initialization than swap - * LED and XMAC initialization order - */ - SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA); - SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_ENA); - /* The Link LED is initialized by RLMT or Diagnostics itself */ - - SkXmInitMac(pAC, IoC, Port); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - SkGmInitMac(pAC, IoC, Port); - } -#endif /* YUKON */ - - /* do NOT initialize the Link Sync Counter */ - - SkGeInitMacFifo(pAC, IoC, Port); - - SkGeInitRamBufs(pAC, IoC, Port); - - if (pPrt->PXSQSize != 0) { - /* enable Force Sync bit if synchronous queue available */ - SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_ENA_FSYNC); - } - - SkGeInitBmu(pAC, IoC, Port); - - /* mark port as initialized */ - pPrt->PState = SK_PRT_INIT; - - return(0); -} /* SkGeInitPort */ diff --git a/drivers/net/sk98lin/skgemib.c b/drivers/net/sk98lin/skgemib.c deleted file mode 100644 index 0a6f67a7a39..00000000000 --- a/drivers/net/sk98lin/skgemib.c +++ /dev/null @@ -1,1075 +0,0 @@ -/***************************************************************************** - * - * Name: skgemib.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.11 $ - * Date: $Date: 2003/09/15 13:38:12 $ - * Purpose: Private Network Management Interface Management Database - * - ****************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - * PRIVATE OID handler function prototypes - */ -PNMI_STATIC int Addr(SK_AC *pAC, SK_IOC IoC, int action, - SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int CsumStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int General(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int Mac8023Stat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int MacPrivateConf(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int MacPrivateStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int Monitor(SK_AC *pAC, SK_IOC IoC, int action, - SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int OidStruct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int Perform(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int* pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int Rlmt(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int RlmtStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int SensorStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int Vpd(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); - -#ifdef SK_POWER_MGMT -PNMI_STATIC int PowerManagement(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -#endif /* SK_POWER_MGMT */ - -#ifdef SK_DIAG_SUPPORT -PNMI_STATIC int DiagActions(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -#endif /* SK_DIAG_SUPPORT */ - - -/* defines *******************************************************************/ -#define ID_TABLE_SIZE (sizeof(IdTable)/sizeof(IdTable[0])) - - -/* global variables **********************************************************/ - -/* - * Table to correlate OID with handler function and index to - * hardware register stored in StatAddress if applicable. - */ -PNMI_STATIC const SK_PNMI_TAB_ENTRY IdTable[] = { - {OID_GEN_XMIT_OK, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX}, - {OID_GEN_RCV_OK, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX}, - {OID_GEN_XMIT_ERROR, - 0, - 0, - 0, - SK_PNMI_RO, General, 0}, - {OID_GEN_RCV_ERROR, - 0, - 0, - 0, - SK_PNMI_RO, General, 0}, - {OID_GEN_RCV_NO_BUFFER, - 0, - 0, - 0, - SK_PNMI_RO, General, 0}, - {OID_GEN_DIRECTED_FRAMES_XMIT, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNICAST}, - {OID_GEN_MULTICAST_FRAMES_XMIT, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTICAST}, - {OID_GEN_BROADCAST_FRAMES_XMIT, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_BROADCAST}, - {OID_GEN_DIRECTED_FRAMES_RCV, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_UNICAST}, - {OID_GEN_MULTICAST_FRAMES_RCV, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_MULTICAST}, - {OID_GEN_BROADCAST_FRAMES_RCV, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_BROADCAST}, - {OID_GEN_RCV_CRC_ERROR, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FCS}, - {OID_GEN_TRANSMIT_QUEUE_LENGTH, - 0, - 0, - 0, - SK_PNMI_RO, General, 0}, - {OID_802_3_PERMANENT_ADDRESS, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, 0}, - {OID_802_3_CURRENT_ADDRESS, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, 0}, - {OID_802_3_RCV_ERROR_ALIGNMENT, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FRAMING}, - {OID_802_3_XMIT_ONE_COLLISION, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_SINGLE_COL}, - {OID_802_3_XMIT_MORE_COLLISIONS, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTI_COL}, - {OID_802_3_XMIT_DEFERRED, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_DEFFERAL}, - {OID_802_3_XMIT_MAX_COLLISIONS, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_EXCESS_COL}, - {OID_802_3_RCV_OVERRUN, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_OVERFLOW}, - {OID_802_3_XMIT_UNDERRUN, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNDERRUN}, - {OID_802_3_XMIT_TIMES_CRS_LOST, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_CARRIER}, - {OID_802_3_XMIT_LATE_COLLISIONS, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_LATE_COL}, -#ifdef SK_POWER_MGMT - {OID_PNP_CAPABILITIES, - 0, - 0, - 0, - SK_PNMI_RO, PowerManagement, 0}, - {OID_PNP_SET_POWER, - 0, - 0, - 0, - SK_PNMI_WO, PowerManagement, 0}, - {OID_PNP_QUERY_POWER, - 0, - 0, - 0, - SK_PNMI_RO, PowerManagement, 0}, - {OID_PNP_ADD_WAKE_UP_PATTERN, - 0, - 0, - 0, - SK_PNMI_WO, PowerManagement, 0}, - {OID_PNP_REMOVE_WAKE_UP_PATTERN, - 0, - 0, - 0, - SK_PNMI_WO, PowerManagement, 0}, - {OID_PNP_ENABLE_WAKE_UP, - 0, - 0, - 0, - SK_PNMI_RW, PowerManagement, 0}, -#endif /* SK_POWER_MGMT */ -#ifdef SK_DIAG_SUPPORT - {OID_SKGE_DIAG_MODE, - 0, - 0, - 0, - SK_PNMI_RW, DiagActions, 0}, -#endif /* SK_DIAG_SUPPORT */ - {OID_SKGE_MDB_VERSION, - 1, - 0, - SK_PNMI_MAI_OFF(MgmtDBVersion), - SK_PNMI_RO, General, 0}, - {OID_SKGE_SUPPORTED_LIST, - 0, - 0, - 0, - SK_PNMI_RO, General, 0}, - {OID_SKGE_ALL_DATA, - 0, - 0, - 0, - SK_PNMI_RW, OidStruct, 0}, - {OID_SKGE_VPD_FREE_BYTES, - 1, - 0, - SK_PNMI_MAI_OFF(VpdFreeBytes), - SK_PNMI_RO, Vpd, 0}, - {OID_SKGE_VPD_ENTRIES_LIST, - 1, - 0, - SK_PNMI_MAI_OFF(VpdEntriesList), - SK_PNMI_RO, Vpd, 0}, - {OID_SKGE_VPD_ENTRIES_NUMBER, - 1, - 0, - SK_PNMI_MAI_OFF(VpdEntriesNumber), - SK_PNMI_RO, Vpd, 0}, - {OID_SKGE_VPD_KEY, - SK_PNMI_VPD_ENTRIES, - sizeof(SK_PNMI_VPD), - SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdKey), - SK_PNMI_RO, Vpd, 0}, - {OID_SKGE_VPD_VALUE, - SK_PNMI_VPD_ENTRIES, - sizeof(SK_PNMI_VPD), - SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdValue), - SK_PNMI_RO, Vpd, 0}, - {OID_SKGE_VPD_ACCESS, - SK_PNMI_VPD_ENTRIES, - sizeof(SK_PNMI_VPD), - SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAccess), - SK_PNMI_RO, Vpd, 0}, - {OID_SKGE_VPD_ACTION, - SK_PNMI_VPD_ENTRIES, - sizeof(SK_PNMI_VPD), - SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAction), - SK_PNMI_RW, Vpd, 0}, - {OID_SKGE_PORT_NUMBER, - 1, - 0, - SK_PNMI_MAI_OFF(PortNumber), - SK_PNMI_RO, General, 0}, - {OID_SKGE_DEVICE_TYPE, - 1, - 0, - SK_PNMI_MAI_OFF(DeviceType), - SK_PNMI_RO, General, 0}, - {OID_SKGE_DRIVER_DESCR, - 1, - 0, - SK_PNMI_MAI_OFF(DriverDescr), - SK_PNMI_RO, General, 0}, - {OID_SKGE_DRIVER_VERSION, - 1, - 0, - SK_PNMI_MAI_OFF(DriverVersion), - SK_PNMI_RO, General, 0}, - {OID_SKGE_DRIVER_RELDATE, - 1, - 0, - SK_PNMI_MAI_OFF(DriverReleaseDate), - SK_PNMI_RO, General, 0}, - {OID_SKGE_DRIVER_FILENAME, - 1, - 0, - SK_PNMI_MAI_OFF(DriverFileName), - SK_PNMI_RO, General, 0}, - {OID_SKGE_HW_DESCR, - 1, - 0, - SK_PNMI_MAI_OFF(HwDescr), - SK_PNMI_RO, General, 0}, - {OID_SKGE_HW_VERSION, - 1, - 0, - SK_PNMI_MAI_OFF(HwVersion), - SK_PNMI_RO, General, 0}, - {OID_SKGE_CHIPSET, - 1, - 0, - SK_PNMI_MAI_OFF(Chipset), - SK_PNMI_RO, General, 0}, - {OID_SKGE_CHIPID, - 1, - 0, - SK_PNMI_MAI_OFF(ChipId), - SK_PNMI_RO, General, 0}, - {OID_SKGE_RAMSIZE, - 1, - 0, - SK_PNMI_MAI_OFF(RamSize), - SK_PNMI_RO, General, 0}, - {OID_SKGE_VAUXAVAIL, - 1, - 0, - SK_PNMI_MAI_OFF(VauxAvail), - SK_PNMI_RO, General, 0}, - {OID_SKGE_ACTION, - 1, - 0, - SK_PNMI_MAI_OFF(Action), - SK_PNMI_RW, Perform, 0}, - {OID_SKGE_RESULT, - 1, - 0, - SK_PNMI_MAI_OFF(TestResult), - SK_PNMI_RO, General, 0}, - {OID_SKGE_BUS_TYPE, - 1, - 0, - SK_PNMI_MAI_OFF(BusType), - SK_PNMI_RO, General, 0}, - {OID_SKGE_BUS_SPEED, - 1, - 0, - SK_PNMI_MAI_OFF(BusSpeed), - SK_PNMI_RO, General, 0}, - {OID_SKGE_BUS_WIDTH, - 1, - 0, - SK_PNMI_MAI_OFF(BusWidth), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TX_SW_QUEUE_LEN, - 1, - 0, - SK_PNMI_MAI_OFF(TxSwQueueLen), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TX_SW_QUEUE_MAX, - 1, - 0, - SK_PNMI_MAI_OFF(TxSwQueueMax), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TX_RETRY, - 1, - 0, - SK_PNMI_MAI_OFF(TxRetryCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_RX_INTR_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(RxIntrCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TX_INTR_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(TxIntrCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_RX_NO_BUF_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(RxNoBufCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TX_NO_BUF_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(TxNoBufCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TX_USED_DESCR_NO, - 1, - 0, - SK_PNMI_MAI_OFF(TxUsedDescrNo), - SK_PNMI_RO, General, 0}, - {OID_SKGE_RX_DELIVERED_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(RxDeliveredCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_RX_OCTETS_DELIV_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(RxOctetsDeliveredCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_RX_HW_ERROR_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(RxHwErrorsCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TX_HW_ERROR_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(TxHwErrorsCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_IN_ERRORS_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(InErrorsCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_OUT_ERROR_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(OutErrorsCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_ERR_RECOVERY_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(ErrRecoveryCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_SYSUPTIME, - 1, - 0, - SK_PNMI_MAI_OFF(SysUpTime), - SK_PNMI_RO, General, 0}, - {OID_SKGE_SENSOR_NUMBER, - 1, - 0, - SK_PNMI_MAI_OFF(SensorNumber), - SK_PNMI_RO, General, 0}, - {OID_SKGE_SENSOR_INDEX, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorIndex), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_DESCR, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorDescr), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_TYPE, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorType), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_VALUE, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorValue), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_WAR_THRES_LOW, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdLow), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_WAR_THRES_UPP, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdHigh), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_ERR_THRES_LOW, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdLow), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_ERR_THRES_UPP, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdHigh), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_STATUS, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorStatus), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_WAR_CTS, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningCts), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_ERR_CTS, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorCts), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_WAR_TIME, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningTimestamp), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_ERR_TIME, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorTimestamp), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_CHKSM_NUMBER, - 1, - 0, - SK_PNMI_MAI_OFF(ChecksumNumber), - SK_PNMI_RO, General, 0}, - {OID_SKGE_CHKSM_RX_OK_CTS, - SKCS_NUM_PROTOCOLS, - sizeof(SK_PNMI_CHECKSUM), - SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxOkCts), - SK_PNMI_RO, CsumStat, 0}, - {OID_SKGE_CHKSM_RX_UNABLE_CTS, - SKCS_NUM_PROTOCOLS, - sizeof(SK_PNMI_CHECKSUM), - SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxUnableCts), - SK_PNMI_RO, CsumStat, 0}, - {OID_SKGE_CHKSM_RX_ERR_CTS, - SKCS_NUM_PROTOCOLS, - sizeof(SK_PNMI_CHECKSUM), - SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxErrCts), - SK_PNMI_RO, CsumStat, 0}, - {OID_SKGE_CHKSM_TX_OK_CTS, - SKCS_NUM_PROTOCOLS, - sizeof(SK_PNMI_CHECKSUM), - SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxOkCts), - SK_PNMI_RO, CsumStat, 0}, - {OID_SKGE_CHKSM_TX_UNABLE_CTS, - SKCS_NUM_PROTOCOLS, - sizeof(SK_PNMI_CHECKSUM), - SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxUnableCts), - SK_PNMI_RO, CsumStat, 0}, - {OID_SKGE_STAT_TX, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX}, - {OID_SKGE_STAT_TX_OCTETS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOctetsOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_OCTET}, - {OID_SKGE_STAT_TX_BROADCAST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBroadcastOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BROADCAST}, - {OID_SKGE_STAT_TX_MULTICAST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMulticastOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTICAST}, - {OID_SKGE_STAT_TX_UNICAST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUnicastOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNICAST}, - {OID_SKGE_STAT_TX_LONGFRAMES, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLongFramesCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LONGFRAMES}, - {OID_SKGE_STAT_TX_BURST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBurstCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BURST}, - {OID_SKGE_STAT_TX_PFLOWC, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxPauseMacCtrlCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_PMACC}, - {OID_SKGE_STAT_TX_FLOWC, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMacCtrlCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MACC}, - {OID_SKGE_STAT_TX_SINGLE_COL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSingleCollisionCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SINGLE_COL}, - {OID_SKGE_STAT_TX_MULTI_COL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMultipleCollisionCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTI_COL}, - {OID_SKGE_STAT_TX_EXCESS_COL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveCollisionCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_COL}, - {OID_SKGE_STAT_TX_LATE_COL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLateCollisionCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LATE_COL}, - {OID_SKGE_STAT_TX_DEFFERAL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxDeferralCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_DEFFERAL}, - {OID_SKGE_STAT_TX_EXCESS_DEF, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveDeferralCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_DEF}, - {OID_SKGE_STAT_TX_UNDERRUN, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxFifoUnderrunCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNDERRUN}, - {OID_SKGE_STAT_TX_CARRIER, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxCarrierCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_CARRIER}, -/* {OID_SKGE_STAT_TX_UTIL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUtilization), - SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */ - {OID_SKGE_STAT_TX_64, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx64Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_64}, - {OID_SKGE_STAT_TX_127, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx127Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_127}, - {OID_SKGE_STAT_TX_255, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx255Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_255}, - {OID_SKGE_STAT_TX_511, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx511Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_511}, - {OID_SKGE_STAT_TX_1023, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx1023Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_1023}, - {OID_SKGE_STAT_TX_MAX, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMaxCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MAX}, - {OID_SKGE_STAT_TX_SYNC, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC}, - {OID_SKGE_STAT_TX_SYNC_OCTETS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncOctetsCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC_OCTET}, - {OID_SKGE_STAT_RX, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX}, - {OID_SKGE_STAT_RX_OCTETS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOctetsOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OCTET}, - {OID_SKGE_STAT_RX_BROADCAST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBroadcastOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BROADCAST}, - {OID_SKGE_STAT_RX_MULTICAST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMulticastOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MULTICAST}, - {OID_SKGE_STAT_RX_UNICAST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUnicastOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_UNICAST}, - {OID_SKGE_STAT_RX_LONGFRAMES, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxLongFramesCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_LONGFRAMES}, - {OID_SKGE_STAT_RX_PFLOWC, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC}, - {OID_SKGE_STAT_RX_FLOWC, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC}, - {OID_SKGE_STAT_RX_PFLOWC_ERR, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlErrorCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC_ERR}, - {OID_SKGE_STAT_RX_FLOWC_UNKWN, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlUnknownCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC_UNKWN}, - {OID_SKGE_STAT_RX_BURST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBurstCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BURST}, - {OID_SKGE_STAT_RX_MISSED, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMissedCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MISSED}, - {OID_SKGE_STAT_RX_FRAMING, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFramingCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FRAMING}, - {OID_SKGE_STAT_RX_OVERFLOW, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFifoOverflowCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OVERFLOW}, - {OID_SKGE_STAT_RX_JABBER, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxJabberCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_JABBER}, - {OID_SKGE_STAT_RX_CARRIER, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCarrierCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CARRIER}, - {OID_SKGE_STAT_RX_IR_LENGTH, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxIRLengthCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_IRLENGTH}, - {OID_SKGE_STAT_RX_SYMBOL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxSymbolCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SYMBOL}, - {OID_SKGE_STAT_RX_SHORTS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxShortsCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SHORTS}, - {OID_SKGE_STAT_RX_RUNT, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxRuntCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_RUNT}, - {OID_SKGE_STAT_RX_CEXT, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCextCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CEXT}, - {OID_SKGE_STAT_RX_TOO_LONG, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxTooLongCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_TOO_LONG}, - {OID_SKGE_STAT_RX_FCS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFcsCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FCS}, -/* {OID_SKGE_STAT_RX_UTIL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUtilization), - SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */ - {OID_SKGE_STAT_RX_64, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx64Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_64}, - {OID_SKGE_STAT_RX_127, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx127Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_127}, - {OID_SKGE_STAT_RX_255, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx255Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_255}, - {OID_SKGE_STAT_RX_511, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx511Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_511}, - {OID_SKGE_STAT_RX_1023, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx1023Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_1023}, - {OID_SKGE_STAT_RX_MAX, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMaxCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MAX}, - {OID_SKGE_PHYS_CUR_ADDR, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacCurrentAddr), - SK_PNMI_RW, Addr, 0}, - {OID_SKGE_PHYS_FAC_ADDR, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacFactoryAddr), - SK_PNMI_RO, Addr, 0}, - {OID_SKGE_PMD, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPMD), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_CONNECTOR, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfConnector), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_PHY_TYPE, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyType), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_LINK_CAP, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkCapability), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_LINK_MODE, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkMode), - SK_PNMI_RW, MacPrivateConf, 0}, - {OID_SKGE_LINK_MODE_STATUS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkModeStatus), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_LINK_STATUS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkStatus), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_FLOWCTRL_CAP, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlCapability), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_FLOWCTRL_MODE, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlMode), - SK_PNMI_RW, MacPrivateConf, 0}, - {OID_SKGE_FLOWCTRL_STATUS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlStatus), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_PHY_OPERATION_CAP, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationCapability), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_PHY_OPERATION_MODE, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationMode), - SK_PNMI_RW, MacPrivateConf, 0}, - {OID_SKGE_PHY_OPERATION_STATUS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationStatus), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_SPEED_CAP, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedCapability), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_SPEED_MODE, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedMode), - SK_PNMI_RW, MacPrivateConf, 0}, - {OID_SKGE_SPEED_STATUS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedStatus), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_TRAP, - 1, - 0, - SK_PNMI_MAI_OFF(Trap), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TRAP_NUMBER, - 1, - 0, - SK_PNMI_MAI_OFF(TrapNumber), - SK_PNMI_RO, General, 0}, - {OID_SKGE_RLMT_MODE, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtMode), - SK_PNMI_RW, Rlmt, 0}, - {OID_SKGE_RLMT_PORT_NUMBER, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtPortNumber), - SK_PNMI_RO, Rlmt, 0}, - {OID_SKGE_RLMT_PORT_ACTIVE, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtPortActive), - SK_PNMI_RO, Rlmt, 0}, - {OID_SKGE_RLMT_PORT_PREFERRED, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtPortPreferred), - SK_PNMI_RW, Rlmt, 0}, - {OID_SKGE_RLMT_CHANGE_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtChangeCts), - SK_PNMI_RO, Rlmt, 0}, - {OID_SKGE_RLMT_CHANGE_TIME, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtChangeTime), - SK_PNMI_RO, Rlmt, 0}, - {OID_SKGE_RLMT_CHANGE_ESTIM, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtChangeEstimate), - SK_PNMI_RO, Rlmt, 0}, - {OID_SKGE_RLMT_CHANGE_THRES, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtChangeThreshold), - SK_PNMI_RW, Rlmt, 0}, - {OID_SKGE_RLMT_PORT_INDEX, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_RLMT), - SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtIndex), - SK_PNMI_RO, RlmtStat, 0}, - {OID_SKGE_RLMT_STATUS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_RLMT), - SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtStatus), - SK_PNMI_RO, RlmtStat, 0}, - {OID_SKGE_RLMT_TX_HELLO_CTS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_RLMT), - SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxHelloCts), - SK_PNMI_RO, RlmtStat, 0}, - {OID_SKGE_RLMT_RX_HELLO_CTS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_RLMT), - SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxHelloCts), - SK_PNMI_RO, RlmtStat, 0}, - {OID_SKGE_RLMT_TX_SP_REQ_CTS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_RLMT), - SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxSpHelloReqCts), - SK_PNMI_RO, RlmtStat, 0}, - {OID_SKGE_RLMT_RX_SP_CTS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_RLMT), - SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxSpHelloCts), - SK_PNMI_RO, RlmtStat, 0}, - {OID_SKGE_RLMT_MONITOR_NUMBER, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtMonitorNumber), - SK_PNMI_RO, General, 0}, - {OID_SKGE_RLMT_MONITOR_INDEX, - SK_PNMI_MONITOR_ENTRIES, - sizeof(SK_PNMI_RLMT_MONITOR), - SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorIndex), - SK_PNMI_RO, Monitor, 0}, - {OID_SKGE_RLMT_MONITOR_ADDR, - SK_PNMI_MONITOR_ENTRIES, - sizeof(SK_PNMI_RLMT_MONITOR), - SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAddr), - SK_PNMI_RO, Monitor, 0}, - {OID_SKGE_RLMT_MONITOR_ERRS, - SK_PNMI_MONITOR_ENTRIES, - sizeof(SK_PNMI_RLMT_MONITOR), - SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorErrorCts), - SK_PNMI_RO, Monitor, 0}, - {OID_SKGE_RLMT_MONITOR_TIMESTAMP, - SK_PNMI_MONITOR_ENTRIES, - sizeof(SK_PNMI_RLMT_MONITOR), - SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorTimestamp), - SK_PNMI_RO, Monitor, 0}, - {OID_SKGE_RLMT_MONITOR_ADMIN, - SK_PNMI_MONITOR_ENTRIES, - sizeof(SK_PNMI_RLMT_MONITOR), - SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAdmin), - SK_PNMI_RW, Monitor, 0}, - {OID_SKGE_MTU, - 1, - 0, - SK_PNMI_MAI_OFF(MtuSize), - SK_PNMI_RW, MacPrivateConf, 0}, - {OID_SKGE_VCT_GET, - 0, - 0, - 0, - SK_PNMI_RO, Vct, 0}, - {OID_SKGE_VCT_SET, - 0, - 0, - 0, - SK_PNMI_WO, Vct, 0}, - {OID_SKGE_VCT_STATUS, - 0, - 0, - 0, - SK_PNMI_RO, Vct, 0}, - {OID_SKGE_BOARDLEVEL, - 0, - 0, - 0, - SK_PNMI_RO, General, 0}, -}; - diff --git a/drivers/net/sk98lin/skgepnmi.c b/drivers/net/sk98lin/skgepnmi.c deleted file mode 100644 index b36dd9ac6b2..00000000000 --- a/drivers/net/sk98lin/skgepnmi.c +++ /dev/null @@ -1,8210 +0,0 @@ -/***************************************************************************** - * - * Name: skgepnmi.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.111 $ - * Date: $Date: 2003/09/15 13:35:35 $ - * Purpose: Private Network Management Interface - * - ****************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - - -#ifndef _lint -static const char SysKonnectFileId[] = - "@(#) $Id: skgepnmi.c,v 1.111 2003/09/15 13:35:35 tschilli Exp $ (C) Marvell."; -#endif /* !_lint */ - -#include "h/skdrv1st.h" -#include "h/sktypes.h" -#include "h/xmac_ii.h" -#include "h/skdebug.h" -#include "h/skqueue.h" -#include "h/skgepnmi.h" -#include "h/skgesirq.h" -#include "h/skcsum.h" -#include "h/skvpd.h" -#include "h/skgehw.h" -#include "h/skgeinit.h" -#include "h/skdrv2nd.h" -#include "h/skgepnm2.h" -#ifdef SK_POWER_MGMT -#include "h/skgepmgt.h" -#endif -/* defines *******************************************************************/ - -#ifndef DEBUG -#define PNMI_STATIC static -#else /* DEBUG */ -#define PNMI_STATIC -#endif /* DEBUG */ - -/* - * Public Function prototypes - */ -int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int level); -int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf, - unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); -int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf, - unsigned int *pLen, SK_U32 NetIndex); -int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf, - unsigned int *pLen, SK_U32 NetIndex); -int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf, - unsigned int *pLen, SK_U32 NetIndex); -int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Param); -int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf, - unsigned int * pLen, SK_U32 NetIndex); - - -/* - * Private Function prototypes - */ - -PNMI_STATIC SK_U8 CalculateLinkModeStatus(SK_AC *pAC, SK_IOC IoC, unsigned int - PhysPortIndex); -PNMI_STATIC SK_U8 CalculateLinkStatus(SK_AC *pAC, SK_IOC IoC, unsigned int - PhysPortIndex); -PNMI_STATIC void CopyMac(char *pDst, SK_MAC_ADDR *pMac); -PNMI_STATIC void CopyTrapQueue(SK_AC *pAC, char *pDstBuf); -PNMI_STATIC SK_U64 GetPhysStatVal(SK_AC *pAC, SK_IOC IoC, - unsigned int PhysPortIndex, unsigned int StatIndex); -PNMI_STATIC SK_U64 GetStatVal(SK_AC *pAC, SK_IOC IoC, unsigned int LogPortIndex, - unsigned int StatIndex, SK_U32 NetIndex); -PNMI_STATIC char* GetTrapEntry(SK_AC *pAC, SK_U32 TrapId, unsigned int Size); -PNMI_STATIC void GetTrapQueueLen(SK_AC *pAC, unsigned int *pLen, - unsigned int *pEntries); -PNMI_STATIC int GetVpdKeyArr(SK_AC *pAC, SK_IOC IoC, char *pKeyArr, - unsigned int KeyArrLen, unsigned int *pKeyNo); -PNMI_STATIC int LookupId(SK_U32 Id); -PNMI_STATIC int MacUpdate(SK_AC *pAC, SK_IOC IoC, unsigned int FirstMac, - unsigned int LastMac); -PNMI_STATIC int PnmiStruct(SK_AC *pAC, SK_IOC IoC, int Action, char *pBuf, - unsigned int *pLen, SK_U32 NetIndex); -PNMI_STATIC int PnmiVar(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); -PNMI_STATIC void QueueRlmtNewMacTrap(SK_AC *pAC, unsigned int ActiveMac); -PNMI_STATIC void QueueRlmtPortTrap(SK_AC *pAC, SK_U32 TrapId, - unsigned int PortIndex); -PNMI_STATIC void QueueSensorTrap(SK_AC *pAC, SK_U32 TrapId, - unsigned int SensorIndex); -PNMI_STATIC void QueueSimpleTrap(SK_AC *pAC, SK_U32 TrapId); -PNMI_STATIC void ResetCounter(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex); -PNMI_STATIC int RlmtUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex); -PNMI_STATIC int SirqUpdate(SK_AC *pAC, SK_IOC IoC); -PNMI_STATIC void VirtualConf(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, char *pBuf); -PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id, char *pBuf, - unsigned int *pLen, SK_U32 Instance, unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC void CheckVctStatus(SK_AC *, SK_IOC, char *, SK_U32, SK_U32); - -/* - * Table to correlate OID with handler function and index to - * hardware register stored in StatAddress if applicable. - */ -#include "skgemib.c" - -/* global variables **********************************************************/ - -/* - * Overflow status register bit table and corresponding counter - * dependent on MAC type - the number relates to the size of overflow - * mask returned by the pFnMacOverflow function - */ -PNMI_STATIC const SK_U16 StatOvrflwBit[][SK_PNMI_MAC_TYPES] = { -/* Bit0 */ { SK_PNMI_HTX, SK_PNMI_HTX_UNICAST}, -/* Bit1 */ { SK_PNMI_HTX_OCTETHIGH, SK_PNMI_HTX_BROADCAST}, -/* Bit2 */ { SK_PNMI_HTX_OCTETLOW, SK_PNMI_HTX_PMACC}, -/* Bit3 */ { SK_PNMI_HTX_BROADCAST, SK_PNMI_HTX_MULTICAST}, -/* Bit4 */ { SK_PNMI_HTX_MULTICAST, SK_PNMI_HTX_OCTETLOW}, -/* Bit5 */ { SK_PNMI_HTX_UNICAST, SK_PNMI_HTX_OCTETHIGH}, -/* Bit6 */ { SK_PNMI_HTX_LONGFRAMES, SK_PNMI_HTX_64}, -/* Bit7 */ { SK_PNMI_HTX_BURST, SK_PNMI_HTX_127}, -/* Bit8 */ { SK_PNMI_HTX_PMACC, SK_PNMI_HTX_255}, -/* Bit9 */ { SK_PNMI_HTX_MACC, SK_PNMI_HTX_511}, -/* Bit10 */ { SK_PNMI_HTX_SINGLE_COL, SK_PNMI_HTX_1023}, -/* Bit11 */ { SK_PNMI_HTX_MULTI_COL, SK_PNMI_HTX_MAX}, -/* Bit12 */ { SK_PNMI_HTX_EXCESS_COL, SK_PNMI_HTX_LONGFRAMES}, -/* Bit13 */ { SK_PNMI_HTX_LATE_COL, SK_PNMI_HTX_RESERVED}, -/* Bit14 */ { SK_PNMI_HTX_DEFFERAL, SK_PNMI_HTX_COL}, -/* Bit15 */ { SK_PNMI_HTX_EXCESS_DEF, SK_PNMI_HTX_LATE_COL}, -/* Bit16 */ { SK_PNMI_HTX_UNDERRUN, SK_PNMI_HTX_EXCESS_COL}, -/* Bit17 */ { SK_PNMI_HTX_CARRIER, SK_PNMI_HTX_MULTI_COL}, -/* Bit18 */ { SK_PNMI_HTX_UTILUNDER, SK_PNMI_HTX_SINGLE_COL}, -/* Bit19 */ { SK_PNMI_HTX_UTILOVER, SK_PNMI_HTX_UNDERRUN}, -/* Bit20 */ { SK_PNMI_HTX_64, SK_PNMI_HTX_RESERVED}, -/* Bit21 */ { SK_PNMI_HTX_127, SK_PNMI_HTX_RESERVED}, -/* Bit22 */ { SK_PNMI_HTX_255, SK_PNMI_HTX_RESERVED}, -/* Bit23 */ { SK_PNMI_HTX_511, SK_PNMI_HTX_RESERVED}, -/* Bit24 */ { SK_PNMI_HTX_1023, SK_PNMI_HTX_RESERVED}, -/* Bit25 */ { SK_PNMI_HTX_MAX, SK_PNMI_HTX_RESERVED}, -/* Bit26 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, -/* Bit27 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, -/* Bit28 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, -/* Bit29 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, -/* Bit30 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, -/* Bit31 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, -/* Bit32 */ { SK_PNMI_HRX, SK_PNMI_HRX_UNICAST}, -/* Bit33 */ { SK_PNMI_HRX_OCTETHIGH, SK_PNMI_HRX_BROADCAST}, -/* Bit34 */ { SK_PNMI_HRX_OCTETLOW, SK_PNMI_HRX_PMACC}, -/* Bit35 */ { SK_PNMI_HRX_BROADCAST, SK_PNMI_HRX_MULTICAST}, -/* Bit36 */ { SK_PNMI_HRX_MULTICAST, SK_PNMI_HRX_FCS}, -/* Bit37 */ { SK_PNMI_HRX_UNICAST, SK_PNMI_HRX_RESERVED}, -/* Bit38 */ { SK_PNMI_HRX_PMACC, SK_PNMI_HRX_OCTETLOW}, -/* Bit39 */ { SK_PNMI_HRX_MACC, SK_PNMI_HRX_OCTETHIGH}, -/* Bit40 */ { SK_PNMI_HRX_PMACC_ERR, SK_PNMI_HRX_BADOCTETLOW}, -/* Bit41 */ { SK_PNMI_HRX_MACC_UNKWN, SK_PNMI_HRX_BADOCTETHIGH}, -/* Bit42 */ { SK_PNMI_HRX_BURST, SK_PNMI_HRX_UNDERSIZE}, -/* Bit43 */ { SK_PNMI_HRX_MISSED, SK_PNMI_HRX_RUNT}, -/* Bit44 */ { SK_PNMI_HRX_FRAMING, SK_PNMI_HRX_64}, -/* Bit45 */ { SK_PNMI_HRX_OVERFLOW, SK_PNMI_HRX_127}, -/* Bit46 */ { SK_PNMI_HRX_JABBER, SK_PNMI_HRX_255}, -/* Bit47 */ { SK_PNMI_HRX_CARRIER, SK_PNMI_HRX_511}, -/* Bit48 */ { SK_PNMI_HRX_IRLENGTH, SK_PNMI_HRX_1023}, -/* Bit49 */ { SK_PNMI_HRX_SYMBOL, SK_PNMI_HRX_MAX}, -/* Bit50 */ { SK_PNMI_HRX_SHORTS, SK_PNMI_HRX_LONGFRAMES}, -/* Bit51 */ { SK_PNMI_HRX_RUNT, SK_PNMI_HRX_TOO_LONG}, -/* Bit52 */ { SK_PNMI_HRX_TOO_LONG, SK_PNMI_HRX_JABBER}, -/* Bit53 */ { SK_PNMI_HRX_FCS, SK_PNMI_HRX_RESERVED}, -/* Bit54 */ { SK_PNMI_HRX_RESERVED, SK_PNMI_HRX_OVERFLOW}, -/* Bit55 */ { SK_PNMI_HRX_CEXT, SK_PNMI_HRX_RESERVED}, -/* Bit56 */ { SK_PNMI_HRX_UTILUNDER, SK_PNMI_HRX_RESERVED}, -/* Bit57 */ { SK_PNMI_HRX_UTILOVER, SK_PNMI_HRX_RESERVED}, -/* Bit58 */ { SK_PNMI_HRX_64, SK_PNMI_HRX_RESERVED}, -/* Bit59 */ { SK_PNMI_HRX_127, SK_PNMI_HRX_RESERVED}, -/* Bit60 */ { SK_PNMI_HRX_255, SK_PNMI_HRX_RESERVED}, -/* Bit61 */ { SK_PNMI_HRX_511, SK_PNMI_HRX_RESERVED}, -/* Bit62 */ { SK_PNMI_HRX_1023, SK_PNMI_HRX_RESERVED}, -/* Bit63 */ { SK_PNMI_HRX_MAX, SK_PNMI_HRX_RESERVED} -}; - -/* - * Table for hardware register saving on resets and port switches - */ -PNMI_STATIC const SK_PNMI_STATADDR StatAddr[SK_PNMI_MAX_IDX][SK_PNMI_MAC_TYPES] = { - /* SK_PNMI_HTX */ - {{XM_TXF_OK, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_OCTETHIGH */ - {{XM_TXO_OK_HI, SK_TRUE}, {GM_TXO_OK_HI, SK_TRUE}}, - /* SK_PNMI_HTX_OCTETLOW */ - {{XM_TXO_OK_LO, SK_FALSE}, {GM_TXO_OK_LO, SK_FALSE}}, - /* SK_PNMI_HTX_BROADCAST */ - {{XM_TXF_BC_OK, SK_TRUE}, {GM_TXF_BC_OK, SK_TRUE}}, - /* SK_PNMI_HTX_MULTICAST */ - {{XM_TXF_MC_OK, SK_TRUE}, {GM_TXF_MC_OK, SK_TRUE}}, - /* SK_PNMI_HTX_UNICAST */ - {{XM_TXF_UC_OK, SK_TRUE}, {GM_TXF_UC_OK, SK_TRUE}}, - /* SK_PNMI_HTX_BURST */ - {{XM_TXE_BURST, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_PMACC */ - {{XM_TXF_MPAUSE, SK_TRUE}, {GM_TXF_MPAUSE, SK_TRUE}}, - /* SK_PNMI_HTX_MACC */ - {{XM_TXF_MCTRL, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_COL */ - {{0, SK_FALSE}, {GM_TXF_COL, SK_TRUE}}, - /* SK_PNMI_HTX_SINGLE_COL */ - {{XM_TXF_SNG_COL, SK_TRUE}, {GM_TXF_SNG_COL, SK_TRUE}}, - /* SK_PNMI_HTX_MULTI_COL */ - {{XM_TXF_MUL_COL, SK_TRUE}, {GM_TXF_MUL_COL, SK_TRUE}}, - /* SK_PNMI_HTX_EXCESS_COL */ - {{XM_TXF_ABO_COL, SK_TRUE}, {GM_TXF_ABO_COL, SK_TRUE}}, - /* SK_PNMI_HTX_LATE_COL */ - {{XM_TXF_LAT_COL, SK_TRUE}, {GM_TXF_LAT_COL, SK_TRUE}}, - /* SK_PNMI_HTX_DEFFERAL */ - {{XM_TXF_DEF, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_EXCESS_DEF */ - {{XM_TXF_EX_DEF, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_UNDERRUN */ - {{XM_TXE_FIFO_UR, SK_TRUE}, {GM_TXE_FIFO_UR, SK_TRUE}}, - /* SK_PNMI_HTX_CARRIER */ - {{XM_TXE_CS_ERR, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_UTILUNDER */ - {{0, SK_FALSE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_UTILOVER */ - {{0, SK_FALSE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_64 */ - {{XM_TXF_64B, SK_TRUE}, {GM_TXF_64B, SK_TRUE}}, - /* SK_PNMI_HTX_127 */ - {{XM_TXF_127B, SK_TRUE}, {GM_TXF_127B, SK_TRUE}}, - /* SK_PNMI_HTX_255 */ - {{XM_TXF_255B, SK_TRUE}, {GM_TXF_255B, SK_TRUE}}, - /* SK_PNMI_HTX_511 */ - {{XM_TXF_511B, SK_TRUE}, {GM_TXF_511B, SK_TRUE}}, - /* SK_PNMI_HTX_1023 */ - {{XM_TXF_1023B, SK_TRUE}, {GM_TXF_1023B, SK_TRUE}}, - /* SK_PNMI_HTX_MAX */ - {{XM_TXF_MAX_SZ, SK_TRUE}, {GM_TXF_1518B, SK_TRUE}}, - /* SK_PNMI_HTX_LONGFRAMES */ - {{XM_TXF_LONG, SK_TRUE}, {GM_TXF_MAX_SZ, SK_TRUE}}, - /* SK_PNMI_HTX_SYNC */ - {{0, SK_FALSE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_SYNC_OCTET */ - {{0, SK_FALSE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_RESERVED */ - {{0, SK_FALSE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX */ - {{XM_RXF_OK, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_OCTETHIGH */ - {{XM_RXO_OK_HI, SK_TRUE}, {GM_RXO_OK_HI, SK_TRUE}}, - /* SK_PNMI_HRX_OCTETLOW */ - {{XM_RXO_OK_LO, SK_FALSE}, {GM_RXO_OK_LO, SK_FALSE}}, - /* SK_PNMI_HRX_BADOCTETHIGH */ - {{0, SK_FALSE}, {GM_RXO_ERR_HI, SK_TRUE}}, - /* SK_PNMI_HRX_BADOCTETLOW */ - {{0, SK_FALSE}, {GM_RXO_ERR_LO, SK_TRUE}}, - /* SK_PNMI_HRX_BROADCAST */ - {{XM_RXF_BC_OK, SK_TRUE}, {GM_RXF_BC_OK, SK_TRUE}}, - /* SK_PNMI_HRX_MULTICAST */ - {{XM_RXF_MC_OK, SK_TRUE}, {GM_RXF_MC_OK, SK_TRUE}}, - /* SK_PNMI_HRX_UNICAST */ - {{XM_RXF_UC_OK, SK_TRUE}, {GM_RXF_UC_OK, SK_TRUE}}, - /* SK_PNMI_HRX_PMACC */ - {{XM_RXF_MPAUSE, SK_TRUE}, {GM_RXF_MPAUSE, SK_TRUE}}, - /* SK_PNMI_HRX_MACC */ - {{XM_RXF_MCTRL, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_PMACC_ERR */ - {{XM_RXF_INV_MP, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_MACC_UNKWN */ - {{XM_RXF_INV_MOC, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_BURST */ - {{XM_RXE_BURST, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_MISSED */ - {{XM_RXE_FMISS, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_FRAMING */ - {{XM_RXF_FRA_ERR, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_UNDERSIZE */ - {{0, SK_FALSE}, {GM_RXF_SHT, SK_TRUE}}, - /* SK_PNMI_HRX_OVERFLOW */ - {{XM_RXE_FIFO_OV, SK_TRUE}, {GM_RXE_FIFO_OV, SK_TRUE}}, - /* SK_PNMI_HRX_JABBER */ - {{XM_RXF_JAB_PKT, SK_TRUE}, {GM_RXF_JAB_PKT, SK_TRUE}}, - /* SK_PNMI_HRX_CARRIER */ - {{XM_RXE_CAR_ERR, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_IRLENGTH */ - {{XM_RXF_LEN_ERR, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_SYMBOL */ - {{XM_RXE_SYM_ERR, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_SHORTS */ - {{XM_RXE_SHT_ERR, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_RUNT */ - {{XM_RXE_RUNT, SK_TRUE}, {GM_RXE_FRAG, SK_TRUE}}, - /* SK_PNMI_HRX_TOO_LONG */ - {{XM_RXF_LNG_ERR, SK_TRUE}, {GM_RXF_LNG_ERR, SK_TRUE}}, - /* SK_PNMI_HRX_FCS */ - {{XM_RXF_FCS_ERR, SK_TRUE}, {GM_RXF_FCS_ERR, SK_TRUE}}, - /* SK_PNMI_HRX_CEXT */ - {{XM_RXF_CEX_ERR, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_UTILUNDER */ - {{0, SK_FALSE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_UTILOVER */ - {{0, SK_FALSE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_64 */ - {{XM_RXF_64B, SK_TRUE}, {GM_RXF_64B, SK_TRUE}}, - /* SK_PNMI_HRX_127 */ - {{XM_RXF_127B, SK_TRUE}, {GM_RXF_127B, SK_TRUE}}, - /* SK_PNMI_HRX_255 */ - {{XM_RXF_255B, SK_TRUE}, {GM_RXF_255B, SK_TRUE}}, - /* SK_PNMI_HRX_511 */ - {{XM_RXF_511B, SK_TRUE}, {GM_RXF_511B, SK_TRUE}}, - /* SK_PNMI_HRX_1023 */ - {{XM_RXF_1023B, SK_TRUE}, {GM_RXF_1023B, SK_TRUE}}, - /* SK_PNMI_HRX_MAX */ - {{XM_RXF_MAX_SZ, SK_TRUE}, {GM_RXF_1518B, SK_TRUE}}, - /* SK_PNMI_HRX_LONGFRAMES */ - {{0, SK_FALSE}, {GM_RXF_MAX_SZ, SK_TRUE}}, - /* SK_PNMI_HRX_RESERVED */ - {{0, SK_FALSE}, {0, SK_FALSE}} -}; - - -/***************************************************************************** - * - * Public functions - * - */ - -/***************************************************************************** - * - * SkPnmiInit - Init function of PNMI - * - * Description: - * SK_INIT_DATA: Initialises the data structures - * SK_INIT_IO: Resets the XMAC statistics, determines the device and - * connector type. - * SK_INIT_RUN: Starts a timer event for port switch per hour - * calculation. - * - * Returns: - * Always 0 - */ -int SkPnmiInit( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Level) /* Initialization level */ -{ - unsigned int PortMax; /* Number of ports */ - unsigned int PortIndex; /* Current port index in loop */ - SK_U16 Val16; /* Multiple purpose 16 bit variable */ - SK_U8 Val8; /* Mulitple purpose 8 bit variable */ - SK_EVPARA EventParam; /* Event struct for timer event */ - SK_PNMI_VCT *pVctBackupData; - - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiInit: Called, level=%d\n", Level)); - - switch (Level) { - - case SK_INIT_DATA: - SK_MEMSET((char *)&pAC->Pnmi, 0, sizeof(pAC->Pnmi)); - pAC->Pnmi.TrapBufFree = SK_PNMI_TRAP_QUEUE_LEN; - pAC->Pnmi.StartUpTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC)); - pAC->Pnmi.RlmtChangeThreshold = SK_PNMI_DEF_RLMT_CHG_THRES; - for (PortIndex = 0; PortIndex < SK_MAX_MACS; PortIndex ++) { - - pAC->Pnmi.Port[PortIndex].ActiveFlag = SK_FALSE; - pAC->Pnmi.DualNetActiveFlag = SK_FALSE; - } - -#ifdef SK_PNMI_CHECK - if (SK_PNMI_MAX_IDX != SK_PNMI_CNT_NO) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR049, SK_PNMI_ERR049MSG); - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL, - ("CounterOffset struct size (%d) differs from" - "SK_PNMI_MAX_IDX (%d)\n", - SK_PNMI_CNT_NO, SK_PNMI_MAX_IDX)); - } - - if (SK_PNMI_MAX_IDX != - (sizeof(StatAddr) / (sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES))) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR050, SK_PNMI_ERR050MSG); - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL, - ("StatAddr table size (%d) differs from " - "SK_PNMI_MAX_IDX (%d)\n", - (sizeof(StatAddr) / - (sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES)), - SK_PNMI_MAX_IDX)); - } -#endif /* SK_PNMI_CHECK */ - break; - - case SK_INIT_IO: - /* - * Reset MAC counters - */ - PortMax = pAC->GIni.GIMacsFound; - - for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) { - - pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PortIndex); - } - - /* Initialize DSP variables for Vct() to 0xff => Never written! */ - for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) { - pAC->GIni.GP[PortIndex].PCableLen = 0xff; - pVctBackupData = &pAC->Pnmi.VctBackup[PortIndex]; - pVctBackupData->PCableLen = 0xff; - } - - /* - * Get pci bus speed - */ - SK_IN16(IoC, B0_CTST, &Val16); - if ((Val16 & CS_BUS_CLOCK) == 0) { - - pAC->Pnmi.PciBusSpeed = 33; - } - else { - pAC->Pnmi.PciBusSpeed = 66; - } - - /* - * Get pci bus width - */ - SK_IN16(IoC, B0_CTST, &Val16); - if ((Val16 & CS_BUS_SLOT_SZ) == 0) { - - pAC->Pnmi.PciBusWidth = 32; - } - else { - pAC->Pnmi.PciBusWidth = 64; - } - - /* - * Get chipset - */ - switch (pAC->GIni.GIChipId) { - case CHIP_ID_GENESIS: - pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_XMAC; - break; - - case CHIP_ID_YUKON: - pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON; - break; - - default: - break; - } - - /* - * Get PMD and DeviceType - */ - SK_IN8(IoC, B2_PMD_TYP, &Val8); - switch (Val8) { - case 'S': - pAC->Pnmi.PMD = 3; - if (pAC->GIni.GIMacsFound > 1) { - - pAC->Pnmi.DeviceType = 0x00020002; - } - else { - pAC->Pnmi.DeviceType = 0x00020001; - } - break; - - case 'L': - pAC->Pnmi.PMD = 2; - if (pAC->GIni.GIMacsFound > 1) { - - pAC->Pnmi.DeviceType = 0x00020004; - } - else { - pAC->Pnmi.DeviceType = 0x00020003; - } - break; - - case 'C': - pAC->Pnmi.PMD = 4; - if (pAC->GIni.GIMacsFound > 1) { - - pAC->Pnmi.DeviceType = 0x00020006; - } - else { - pAC->Pnmi.DeviceType = 0x00020005; - } - break; - - case 'T': - pAC->Pnmi.PMD = 5; - if (pAC->GIni.GIMacsFound > 1) { - - pAC->Pnmi.DeviceType = 0x00020008; - } - else { - pAC->Pnmi.DeviceType = 0x00020007; - } - break; - - default : - pAC->Pnmi.PMD = 1; - pAC->Pnmi.DeviceType = 0; - break; - } - - /* - * Get connector - */ - SK_IN8(IoC, B2_CONN_TYP, &Val8); - switch (Val8) { - case 'C': - pAC->Pnmi.Connector = 2; - break; - - case 'D': - pAC->Pnmi.Connector = 3; - break; - - case 'F': - pAC->Pnmi.Connector = 4; - break; - - case 'J': - pAC->Pnmi.Connector = 5; - break; - - case 'V': - pAC->Pnmi.Connector = 6; - break; - - default: - pAC->Pnmi.Connector = 1; - break; - } - break; - - case SK_INIT_RUN: - /* - * Start timer for RLMT change counter - */ - SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); - SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer, - 28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER, - EventParam); - break; - - default: - break; /* Nothing todo */ - } - - return (0); -} - -/***************************************************************************** - * - * SkPnmiGetVar - Retrieves the value of a single OID - * - * Description: - * Calls a general sub-function for all this stuff. If the instance - * -1 is passed, the values of all instances are returned in an - * array of values. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed - * SK_PNMI_ERR_GENERAL A general severe internal error occured - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take - * the data. - * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -static int SkPnmiGetVar( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -SK_U32 Id, /* Object ID that is to be processed */ -void *pBuf, /* Buffer to which the management data will be copied */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiGetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n", - Id, *pLen, Instance, NetIndex)); - - return (PnmiVar(pAC, IoC, SK_PNMI_GET, Id, (char *)pBuf, pLen, - Instance, NetIndex)); -} - -/***************************************************************************** - * - * SkPnmiPreSetVar - Presets the value of a single OID - * - * Description: - * Calls a general sub-function for all this stuff. The preset does - * the same as a set, but returns just before finally setting the - * new value. This is useful to check if a set might be successfull. - * If the instance -1 is passed, an array of values is supposed and - * all instances of the OID will be set. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -static int SkPnmiPreSetVar( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -SK_U32 Id, /* Object ID that is to be processed */ -void *pBuf, /* Buffer to which the management data will be copied */ -unsigned int *pLen, /* Total length of management data */ -SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiPreSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n", - Id, *pLen, Instance, NetIndex)); - - - return (PnmiVar(pAC, IoC, SK_PNMI_PRESET, Id, (char *)pBuf, pLen, - Instance, NetIndex)); -} - -/***************************************************************************** - * - * SkPnmiSetVar - Sets the value of a single OID - * - * Description: - * Calls a general sub-function for all this stuff. The preset does - * the same as a set, but returns just before finally setting the - * new value. This is useful to check if a set might be successfull. - * If the instance -1 is passed, an array of values is supposed and - * all instances of the OID will be set. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -int SkPnmiSetVar( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -SK_U32 Id, /* Object ID that is to be processed */ -void *pBuf, /* Buffer to which the management data will be copied */ -unsigned int *pLen, /* Total length of management data */ -SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n", - Id, *pLen, Instance, NetIndex)); - - return (PnmiVar(pAC, IoC, SK_PNMI_SET, Id, (char *)pBuf, pLen, - Instance, NetIndex)); -} - -/***************************************************************************** - * - * SkPnmiGetStruct - Retrieves the management database in SK_PNMI_STRUCT_DATA - * - * Description: - * Runs through the IdTable, queries the single OIDs and stores the - * returned data into the management database structure - * SK_PNMI_STRUCT_DATA. The offset of the OID in the structure - * is stored in the IdTable. The return value of the function will also - * be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the - * minimum size of SK_PNMI_MIN_STRUCT_SIZE. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed - * SK_PNMI_ERR_GENERAL A general severe internal error occured - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take - * the data. - * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist - */ -int SkPnmiGetStruct( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -void *pBuf, /* Buffer to which the management data will be copied. */ -unsigned int *pLen, /* Length of buffer */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - int Ret; - unsigned int TableIndex; - unsigned int DstOffset; - unsigned int InstanceNo; - unsigned int InstanceCnt; - SK_U32 Instance; - unsigned int TmpLen; - char KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE]; - - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiGetStruct: Called, BufLen=%d, NetIndex=%d\n", - *pLen, NetIndex)); - - if (*pLen < SK_PNMI_STRUCT_SIZE) { - - if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) { - - SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT, - (SK_U32)(-1)); - } - - *pLen = SK_PNMI_STRUCT_SIZE; - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* - * Check NetIndex - */ - if (NetIndex >= pAC->Rlmt.NumNets) { - return (SK_PNMI_ERR_UNKNOWN_NET); - } - - /* Update statistic */ - SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On call"); - - if ((Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1)) != - SK_PNMI_ERR_OK) { - - SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (Ret); - } - - if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) { - - SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (Ret); - } - - if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) { - - SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (Ret); - } - - /* - * Increment semaphores to indicate that an update was - * already done - */ - pAC->Pnmi.MacUpdatedFlag ++; - pAC->Pnmi.RlmtUpdatedFlag ++; - pAC->Pnmi.SirqUpdatedFlag ++; - - /* Get vpd keys for instance calculation */ - Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &TmpLen); - if (Ret != SK_PNMI_ERR_OK) { - - pAC->Pnmi.MacUpdatedFlag --; - pAC->Pnmi.RlmtUpdatedFlag --; - pAC->Pnmi.SirqUpdatedFlag --; - - SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return"); - SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (SK_PNMI_ERR_GENERAL); - } - - /* Retrieve values */ - SK_MEMSET((char *)pBuf, 0, SK_PNMI_STRUCT_SIZE); - for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) { - - InstanceNo = IdTable[TableIndex].InstanceNo; - for (InstanceCnt = 1; InstanceCnt <= InstanceNo; - InstanceCnt ++) { - - DstOffset = IdTable[TableIndex].Offset + - (InstanceCnt - 1) * - IdTable[TableIndex].StructSize; - - /* - * For the VPD the instance is not an index number - * but the key itself. Determin with the instance - * counter the VPD key to be used. - */ - if (IdTable[TableIndex].Id == OID_SKGE_VPD_KEY || - IdTable[TableIndex].Id == OID_SKGE_VPD_VALUE || - IdTable[TableIndex].Id == OID_SKGE_VPD_ACCESS || - IdTable[TableIndex].Id == OID_SKGE_VPD_ACTION) { - - SK_STRNCPY((char *)&Instance, KeyArr[InstanceCnt - 1], 4); - } - else { - Instance = (SK_U32)InstanceCnt; - } - - TmpLen = *pLen - DstOffset; - Ret = IdTable[TableIndex].Func(pAC, IoC, SK_PNMI_GET, - IdTable[TableIndex].Id, (char *)pBuf + - DstOffset, &TmpLen, Instance, TableIndex, NetIndex); - - /* - * An unknown instance error means that we reached - * the last instance of that variable. Proceed with - * the next OID in the table and ignore the return - * code. - */ - if (Ret == SK_PNMI_ERR_UNKNOWN_INST) { - - break; - } - - if (Ret != SK_PNMI_ERR_OK) { - - pAC->Pnmi.MacUpdatedFlag --; - pAC->Pnmi.RlmtUpdatedFlag --; - pAC->Pnmi.SirqUpdatedFlag --; - - SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return"); - SK_PNMI_SET_STAT(pBuf, Ret, DstOffset); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (Ret); - } - } - } - - pAC->Pnmi.MacUpdatedFlag --; - pAC->Pnmi.RlmtUpdatedFlag --; - pAC->Pnmi.SirqUpdatedFlag --; - - *pLen = SK_PNMI_STRUCT_SIZE; - SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return"); - SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1)); - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * SkPnmiPreSetStruct - Presets the management database in SK_PNMI_STRUCT_DATA - * - * Description: - * Calls a general sub-function for all this set stuff. The preset does - * the same as a set, but returns just before finally setting the - * new value. This is useful to check if a set might be successfull. - * The sub-function runs through the IdTable, checks which OIDs are able - * to set, and calls the handler function of the OID to perform the - * preset. The return value of the function will also be stored in - * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of - * SK_PNMI_MIN_STRUCT_SIZE. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - */ -int SkPnmiPreSetStruct( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -void *pBuf, /* Buffer which contains the data to be set */ -unsigned int *pLen, /* Length of buffer */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiPreSetStruct: Called, BufLen=%d, NetIndex=%d\n", - *pLen, NetIndex)); - - return (PnmiStruct(pAC, IoC, SK_PNMI_PRESET, (char *)pBuf, - pLen, NetIndex)); -} - -/***************************************************************************** - * - * SkPnmiSetStruct - Sets the management database in SK_PNMI_STRUCT_DATA - * - * Description: - * Calls a general sub-function for all this set stuff. The return value - * of the function will also be stored in SK_PNMI_STRUCT_DATA if the - * passed buffer has the minimum size of SK_PNMI_MIN_STRUCT_SIZE. - * The sub-function runs through the IdTable, checks which OIDs are able - * to set, and calls the handler function of the OID to perform the - * set. The return value of the function will also be stored in - * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of - * SK_PNMI_MIN_STRUCT_SIZE. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - */ -int SkPnmiSetStruct( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -void *pBuf, /* Buffer which contains the data to be set */ -unsigned int *pLen, /* Length of buffer */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiSetStruct: Called, BufLen=%d, NetIndex=%d\n", - *pLen, NetIndex)); - - return (PnmiStruct(pAC, IoC, SK_PNMI_SET, (char *)pBuf, - pLen, NetIndex)); -} - -/***************************************************************************** - * - * SkPnmiEvent - Event handler - * - * Description: - * Handles the following events: - * SK_PNMI_EVT_SIRQ_OVERFLOW When a hardware counter overflows an - * interrupt will be generated which is - * first handled by SIRQ which generates a - * this event. The event increments the - * upper 32 bit of the 64 bit counter. - * SK_PNMI_EVT_SEN_XXX The event is generated by the I2C module - * when a sensor reports a warning or - * error. The event will store a trap - * message in the trap buffer. - * SK_PNMI_EVT_CHG_EST_TIMER The timer event was initiated by this - * module and is used to calculate the - * port switches per hour. - * SK_PNMI_EVT_CLEAR_COUNTER The event clears all counters and - * timestamps. - * SK_PNMI_EVT_XMAC_RESET The event is generated by the driver - * before a hard reset of the XMAC is - * performed. All counters will be saved - * and added to the hardware counter - * values after reset to grant continuous - * counter values. - * SK_PNMI_EVT_RLMT_PORT_UP Generated by RLMT to notify that a port - * went logically up. A trap message will - * be stored to the trap buffer. - * SK_PNMI_EVT_RLMT_PORT_DOWN Generated by RLMT to notify that a port - * went logically down. A trap message will - * be stored to the trap buffer. - * SK_PNMI_EVT_RLMT_SEGMENTATION Generated by RLMT to notify that two - * spanning tree root bridges were - * detected. A trap message will be stored - * to the trap buffer. - * SK_PNMI_EVT_RLMT_ACTIVE_DOWN Notifies PNMI that an active port went - * down. PNMI will not further add the - * statistic values to the virtual port. - * SK_PNMI_EVT_RLMT_ACTIVE_UP Notifies PNMI that a port went up and - * is now an active port. PNMI will now - * add the statistic data of this port to - * the virtual port. - * SK_PNMI_EVT_RLMT_SET_NETS Notifies PNMI about the net mode. The first parameter - * contains the number of nets. 1 means single net, 2 means - * dual net. The second parameter is -1 - * - * Returns: - * Always 0 - */ -int SkPnmiEvent( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -SK_U32 Event, /* Event-Id */ -SK_EVPARA Param) /* Event dependent parameter */ -{ - unsigned int PhysPortIndex; - unsigned int MaxNetNumber; - int CounterIndex; - int Ret; - SK_U16 MacStatus; - SK_U64 OverflowStatus; - SK_U64 Mask; - int MacType; - SK_U64 Value; - SK_U32 Val32; - SK_U16 Register; - SK_EVPARA EventParam; - SK_U64 NewestValue; - SK_U64 OldestValue; - SK_U64 Delta; - SK_PNMI_ESTIMATE *pEst; - SK_U32 NetIndex; - SK_GEPORT *pPrt; - SK_PNMI_VCT *pVctBackupData; - SK_U32 RetCode; - int i; - SK_U32 CableLength; - - -#ifdef DEBUG - if (Event != SK_PNMI_EVT_XMAC_RESET) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiEvent: Called, Event=0x%x, Param=0x%x\n", - (unsigned int)Event, (unsigned int)Param.Para64)); - } -#endif /* DEBUG */ - SK_PNMI_CHECKFLAGS("SkPnmiEvent: On call"); - - MacType = pAC->GIni.GIMacType; - - switch (Event) { - - case SK_PNMI_EVT_SIRQ_OVERFLOW: - PhysPortIndex = (int)Param.Para32[0]; - MacStatus = (SK_U16)Param.Para32[1]; -#ifdef DEBUG - if (PhysPortIndex >= SK_MAX_MACS) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SIRQ_OVERFLOW parameter" - " wrong, PhysPortIndex=0x%x\n", - PhysPortIndex)); - return (0); - } -#endif /* DEBUG */ - OverflowStatus = 0; - - /* - * Check which source caused an overflow interrupt. - */ - if ((pAC->GIni.GIFunc.pFnMacOverflow(pAC, IoC, PhysPortIndex, - MacStatus, &OverflowStatus) != 0) || - (OverflowStatus == 0)) { - - SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); - return (0); - } - - /* - * Check the overflow status register and increment - * the upper dword of corresponding counter. - */ - for (CounterIndex = 0; CounterIndex < sizeof(Mask) * 8; - CounterIndex ++) { - - Mask = (SK_U64)1 << CounterIndex; - if ((OverflowStatus & Mask) == 0) { - - continue; - } - - switch (StatOvrflwBit[CounterIndex][MacType]) { - - case SK_PNMI_HTX_UTILUNDER: - case SK_PNMI_HTX_UTILOVER: - if (MacType == SK_MAC_XMAC) { - XM_IN16(IoC, PhysPortIndex, XM_TX_CMD, &Register); - Register |= XM_TX_SAM_LINE; - XM_OUT16(IoC, PhysPortIndex, XM_TX_CMD, Register); - } - break; - - case SK_PNMI_HRX_UTILUNDER: - case SK_PNMI_HRX_UTILOVER: - if (MacType == SK_MAC_XMAC) { - XM_IN16(IoC, PhysPortIndex, XM_RX_CMD, &Register); - Register |= XM_RX_SAM_LINE; - XM_OUT16(IoC, PhysPortIndex, XM_RX_CMD, Register); - } - break; - - case SK_PNMI_HTX_OCTETHIGH: - case SK_PNMI_HTX_OCTETLOW: - case SK_PNMI_HTX_RESERVED: - case SK_PNMI_HRX_OCTETHIGH: - case SK_PNMI_HRX_OCTETLOW: - case SK_PNMI_HRX_IRLENGTH: - case SK_PNMI_HRX_RESERVED: - - /* - * the following counters aren't be handled (id > 63) - */ - case SK_PNMI_HTX_SYNC: - case SK_PNMI_HTX_SYNC_OCTET: - break; - - case SK_PNMI_HRX_LONGFRAMES: - if (MacType == SK_MAC_GMAC) { - pAC->Pnmi.Port[PhysPortIndex]. - CounterHigh[CounterIndex] ++; - } - break; - - default: - pAC->Pnmi.Port[PhysPortIndex]. - CounterHigh[CounterIndex] ++; - } - } - break; - - case SK_PNMI_EVT_SEN_WAR_LOW: -#ifdef DEBUG - if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_LOW parameter wrong, SensorIndex=%d\n", - (unsigned int)Param.Para64)); - return (0); - } -#endif /* DEBUG */ - - /* - * Store a trap message in the trap buffer and generate - * an event for user space applications with the - * SK_DRIVER_SENDEVENT macro. - */ - QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_LOW, - (unsigned int)Param.Para64); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - break; - - case SK_PNMI_EVT_SEN_WAR_UPP: -#ifdef DEBUG - if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_UPP parameter wrong, SensorIndex=%d\n", - (unsigned int)Param.Para64)); - return (0); - } -#endif /* DEBUG */ - - /* - * Store a trap message in the trap buffer and generate - * an event for user space applications with the - * SK_DRIVER_SENDEVENT macro. - */ - QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_UPP, - (unsigned int)Param.Para64); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - break; - - case SK_PNMI_EVT_SEN_ERR_LOW: -#ifdef DEBUG - if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_LOW parameter wrong, SensorIndex=%d\n", - (unsigned int)Param.Para64)); - return (0); - } -#endif /* DEBUG */ - - /* - * Store a trap message in the trap buffer and generate - * an event for user space applications with the - * SK_DRIVER_SENDEVENT macro. - */ - QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_LOW, - (unsigned int)Param.Para64); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - break; - - case SK_PNMI_EVT_SEN_ERR_UPP: -#ifdef DEBUG - if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_UPP parameter wrong, SensorIndex=%d\n", - (unsigned int)Param.Para64)); - return (0); - } -#endif /* DEBUG */ - - /* - * Store a trap message in the trap buffer and generate - * an event for user space applications with the - * SK_DRIVER_SENDEVENT macro. - */ - QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_UPP, - (unsigned int)Param.Para64); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - break; - - case SK_PNMI_EVT_CHG_EST_TIMER: - /* - * Calculate port switch average on a per hour basis - * Time interval for check : 28125 ms - * Number of values for average : 8 - * - * Be careful in changing these values, on change check - * - typedef of SK_PNMI_ESTIMATE (Size of EstValue - * array one less than value number) - * - Timer initialization SkTimerStart() in SkPnmiInit - * - Delta value below must be multiplicated with - * power of 2 - * - */ - pEst = &pAC->Pnmi.RlmtChangeEstimate; - CounterIndex = pEst->EstValueIndex + 1; - if (CounterIndex == 7) { - - CounterIndex = 0; - } - pEst->EstValueIndex = CounterIndex; - - NewestValue = pAC->Pnmi.RlmtChangeCts; - OldestValue = pEst->EstValue[CounterIndex]; - pEst->EstValue[CounterIndex] = NewestValue; - - /* - * Calculate average. Delta stores the number of - * port switches per 28125 * 8 = 225000 ms - */ - if (NewestValue >= OldestValue) { - - Delta = NewestValue - OldestValue; - } - else { - /* Overflow situation */ - Delta = (SK_U64)(0 - OldestValue) + NewestValue; - } - - /* - * Extrapolate delta to port switches per hour. - * Estimate = Delta * (3600000 / 225000) - * = Delta * 16 - * = Delta << 4 - */ - pAC->Pnmi.RlmtChangeEstimate.Estimate = Delta << 4; - - /* - * Check if threshold is exceeded. If the threshold is - * permanently exceeded every 28125 ms an event will be - * generated to remind the user of this condition. - */ - if ((pAC->Pnmi.RlmtChangeThreshold != 0) && - (pAC->Pnmi.RlmtChangeEstimate.Estimate >= - pAC->Pnmi.RlmtChangeThreshold)) { - - QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_CHANGE_THRES); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - } - - SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); - SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer, - 28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER, - EventParam); - break; - - case SK_PNMI_EVT_CLEAR_COUNTER: - /* - * Param.Para32[0] contains the NetIndex (0 ..1). - * Param.Para32[1] is reserved, contains -1. - */ - NetIndex = (SK_U32)Param.Para32[0]; - -#ifdef DEBUG - if (NetIndex >= pAC->Rlmt.NumNets) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_CLEAR_COUNTER parameter wrong, NetIndex=%d\n", - NetIndex)); - - return (0); - } -#endif /* DEBUG */ - - /* - * Set all counters and timestamps to zero. - * The according NetIndex is required as a - * parameter of the event. - */ - ResetCounter(pAC, IoC, NetIndex); - break; - - case SK_PNMI_EVT_XMAC_RESET: - /* - * To grant continuous counter values store the current - * XMAC statistic values to the entries 1..n of the - * CounterOffset array. XMAC Errata #2 - */ -#ifdef DEBUG - if ((unsigned int)Param.Para64 >= SK_MAX_MACS) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_XMAC_RESET parameter wrong, PhysPortIndex=%d\n", - (unsigned int)Param.Para64)); - return (0); - } -#endif - PhysPortIndex = (unsigned int)Param.Para64; - - /* - * Update XMAC statistic to get fresh values - */ - Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1); - if (Ret != SK_PNMI_ERR_OK) { - - SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); - return (0); - } - /* - * Increment semaphore to indicate that an update was - * already done - */ - pAC->Pnmi.MacUpdatedFlag ++; - - for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX; - CounterIndex ++) { - - if (!StatAddr[CounterIndex][MacType].GetOffset) { - - continue; - } - - pAC->Pnmi.Port[PhysPortIndex].CounterOffset[CounterIndex] = - GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex); - - pAC->Pnmi.Port[PhysPortIndex].CounterHigh[CounterIndex] = 0; - } - - pAC->Pnmi.MacUpdatedFlag --; - break; - - case SK_PNMI_EVT_RLMT_PORT_UP: - PhysPortIndex = (unsigned int)Param.Para32[0]; -#ifdef DEBUG - if (PhysPortIndex >= SK_MAX_MACS) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_UP parameter" - " wrong, PhysPortIndex=%d\n", PhysPortIndex)); - - return (0); - } -#endif /* DEBUG */ - - /* - * Store a trap message in the trap buffer and generate an event for - * user space applications with the SK_DRIVER_SENDEVENT macro. - */ - QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_UP, PhysPortIndex); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - - /* Bugfix for XMAC errata (#10620)*/ - if (MacType == SK_MAC_XMAC) { - /* Add incremental difference to offset (#10620)*/ - (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex, - XM_RXE_SHT_ERR, &Val32); - - Value = (((SK_U64)pAC->Pnmi.Port[PhysPortIndex]. - CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32); - pAC->Pnmi.Port[PhysPortIndex].CounterOffset[SK_PNMI_HRX_SHORTS] += - Value - pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark; - } - - /* Tell VctStatus() that a link was up meanwhile. */ - pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_LINK; - break; - - case SK_PNMI_EVT_RLMT_PORT_DOWN: - PhysPortIndex = (unsigned int)Param.Para32[0]; - -#ifdef DEBUG - if (PhysPortIndex >= SK_MAX_MACS) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_DOWN parameter" - " wrong, PhysPortIndex=%d\n", PhysPortIndex)); - - return (0); - } -#endif /* DEBUG */ - - /* - * Store a trap message in the trap buffer and generate an event for - * user space applications with the SK_DRIVER_SENDEVENT macro. - */ - QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_DOWN, PhysPortIndex); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - - /* Bugfix #10620 - get zero level for incremental difference */ - if (MacType == SK_MAC_XMAC) { - - (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex, - XM_RXE_SHT_ERR, &Val32); - - pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark = - (((SK_U64)pAC->Pnmi.Port[PhysPortIndex]. - CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32); - } - break; - - case SK_PNMI_EVT_RLMT_ACTIVE_DOWN: - PhysPortIndex = (unsigned int)Param.Para32[0]; - NetIndex = (SK_U32)Param.Para32[1]; - -#ifdef DEBUG - if (PhysPortIndex >= SK_MAX_MACS) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, PhysPort=%d\n", - PhysPortIndex)); - } - - if (NetIndex >= pAC->Rlmt.NumNets) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, NetIndex=%d\n", - NetIndex)); - } -#endif /* DEBUG */ - - /* - * For now, ignore event if NetIndex != 0. - */ - if (Param.Para32[1] != 0) { - - return (0); - } - - /* - * Nothing to do if port is already inactive - */ - if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { - - return (0); - } - - /* - * Update statistic counters to calculate new offset for the virtual - * port and increment semaphore to indicate that an update was already - * done. - */ - if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) != - SK_PNMI_ERR_OK) { - - SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); - return (0); - } - pAC->Pnmi.MacUpdatedFlag ++; - - /* - * Calculate new counter offset for virtual port to grant continous - * counting on port switches. The virtual port consists of all currently - * active ports. The port down event indicates that a port is removed - * from the virtual port. Therefore add the counter value of the removed - * port to the CounterOffset for the virtual port to grant the same - * counter value. - */ - for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX; - CounterIndex ++) { - - if (!StatAddr[CounterIndex][MacType].GetOffset) { - - continue; - } - - Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex); - - pAC->Pnmi.VirtualCounterOffset[CounterIndex] += Value; - } - - /* - * Set port to inactive - */ - pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_FALSE; - - pAC->Pnmi.MacUpdatedFlag --; - break; - - case SK_PNMI_EVT_RLMT_ACTIVE_UP: - PhysPortIndex = (unsigned int)Param.Para32[0]; - NetIndex = (SK_U32)Param.Para32[1]; - -#ifdef DEBUG - if (PhysPortIndex >= SK_MAX_MACS) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, PhysPort=%d\n", - PhysPortIndex)); - } - - if (NetIndex >= pAC->Rlmt.NumNets) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, NetIndex=%d\n", - NetIndex)); - } -#endif /* DEBUG */ - - /* - * For now, ignore event if NetIndex != 0. - */ - if (Param.Para32[1] != 0) { - - return (0); - } - - /* - * Nothing to do if port is already active - */ - if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { - - return (0); - } - - /* - * Statistic maintenance - */ - pAC->Pnmi.RlmtChangeCts ++; - pAC->Pnmi.RlmtChangeTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC)); - - /* - * Store a trap message in the trap buffer and generate an event for - * user space applications with the SK_DRIVER_SENDEVENT macro. - */ - QueueRlmtNewMacTrap(pAC, PhysPortIndex); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - - /* - * Update statistic counters to calculate new offset for the virtual - * port and increment semaphore to indicate that an update was - * already done. - */ - if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) != - SK_PNMI_ERR_OK) { - - SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); - return (0); - } - pAC->Pnmi.MacUpdatedFlag ++; - - /* - * Calculate new counter offset for virtual port to grant continous - * counting on port switches. A new port is added to the virtual port. - * Therefore substract the counter value of the new port from the - * CounterOffset for the virtual port to grant the same value. - */ - for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX; - CounterIndex ++) { - - if (!StatAddr[CounterIndex][MacType].GetOffset) { - - continue; - } - - Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex); - - pAC->Pnmi.VirtualCounterOffset[CounterIndex] -= Value; - } - - /* Set port to active */ - pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_TRUE; - - pAC->Pnmi.MacUpdatedFlag --; - break; - - case SK_PNMI_EVT_RLMT_SEGMENTATION: - /* - * Para.Para32[0] contains the NetIndex. - */ - - /* - * Store a trap message in the trap buffer and generate an event for - * user space applications with the SK_DRIVER_SENDEVENT macro. - */ - QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_SEGMENTATION); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - break; - - case SK_PNMI_EVT_RLMT_SET_NETS: - /* - * Param.Para32[0] contains the number of Nets. - * Param.Para32[1] is reserved, contains -1. - */ - /* - * Check number of nets - */ - MaxNetNumber = pAC->GIni.GIMacsFound; - if (((unsigned int)Param.Para32[0] < 1) - || ((unsigned int)Param.Para32[0] > MaxNetNumber)) { - return (SK_PNMI_ERR_UNKNOWN_NET); - } - - if ((unsigned int)Param.Para32[0] == 1) { /* single net mode */ - pAC->Pnmi.DualNetActiveFlag = SK_FALSE; - } - else { /* dual net mode */ - pAC->Pnmi.DualNetActiveFlag = SK_TRUE; - } - break; - - case SK_PNMI_EVT_VCT_RESET: - PhysPortIndex = Param.Para32[0]; - pPrt = &pAC->GIni.GP[PhysPortIndex]; - pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex]; - - if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) { - RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE); - if (RetCode == 2) { - /* - * VCT test is still running. - * Start VCT timer counter again. - */ - SK_MEMSET((char *) &Param, 0, sizeof(Param)); - Param.Para32[0] = PhysPortIndex; - Param.Para32[1] = -1; - SkTimerStart(pAC, IoC, - &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer, - 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Param); - break; - } - pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING; - pAC->Pnmi.VctStatus[PhysPortIndex] |= - (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE); - - /* Copy results for later use to PNMI struct. */ - for (i = 0; i < 4; i++) { - if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) { - if ((pPrt->PMdiPairLen[i] > 35) && - (pPrt->PMdiPairLen[i] < 0xff)) { - pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH; - } - } - if ((pPrt->PMdiPairLen[i] > 35) && - (pPrt->PMdiPairLen[i] != 0xff)) { - CableLength = 1000 * - (((175 * pPrt->PMdiPairLen[i]) / 210) - 28); - } - else { - CableLength = 0; - } - pVctBackupData->PMdiPairLen[i] = CableLength; - pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i]; - } - - Param.Para32[0] = PhysPortIndex; - Param.Para32[1] = -1; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Param); - SkEventDispatcher(pAC, IoC); - } - - break; - - default: - break; - } - - SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); - return (0); -} - - -/****************************************************************************** - * - * Private functions - * - */ - -/***************************************************************************** - * - * PnmiVar - Gets, presets, and sets single OIDs - * - * Description: - * Looks up the requested OID, calls the corresponding handler - * function, and passes the parameters with the get, preset, or - * set command. The function is called by SkGePnmiGetVar, - * SkGePnmiPreSetVar, or SkGePnmiSetVar. - * - * Returns: - * SK_PNMI_ERR_XXX. For details have a look at the description of the - * calling functions. - * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist - */ -PNMI_STATIC int PnmiVar( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* Total length of pBuf management data */ -SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - unsigned int TableIndex; - int Ret; - - - if ((TableIndex = LookupId(Id)) == (unsigned int)(-1)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_OID); - } - - /* Check NetIndex */ - if (NetIndex >= pAC->Rlmt.NumNets) { - return (SK_PNMI_ERR_UNKNOWN_NET); - } - - SK_PNMI_CHECKFLAGS("PnmiVar: On call"); - - Ret = IdTable[TableIndex].Func(pAC, IoC, Action, Id, pBuf, pLen, - Instance, TableIndex, NetIndex); - - SK_PNMI_CHECKFLAGS("PnmiVar: On return"); - - return (Ret); -} - -/***************************************************************************** - * - * PnmiStruct - Presets and Sets data in structure SK_PNMI_STRUCT_DATA - * - * Description: - * The return value of the function will also be stored in - * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of - * SK_PNMI_MIN_STRUCT_SIZE. The sub-function runs through the IdTable, - * checks which OIDs are able to set, and calls the handler function of - * the OID to perform the set. The return value of the function will - * also be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the - * minimum size of SK_PNMI_MIN_STRUCT_SIZE. The function is called - * by SkGePnmiPreSetStruct and SkGePnmiSetStruct. - * - * Returns: - * SK_PNMI_ERR_XXX. The codes are described in the calling functions. - * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist - */ -PNMI_STATIC int PnmiStruct( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* PRESET/SET action to be performed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* Length of pBuf management data buffer */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - int Ret; - unsigned int TableIndex; - unsigned int DstOffset; - unsigned int Len; - unsigned int InstanceNo; - unsigned int InstanceCnt; - SK_U32 Instance; - SK_U32 Id; - - - /* Check if the passed buffer has the right size */ - if (*pLen < SK_PNMI_STRUCT_SIZE) { - - /* Check if we can return the error within the buffer */ - if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) { - - SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT, - (SK_U32)(-1)); - } - - *pLen = SK_PNMI_STRUCT_SIZE; - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* Check NetIndex */ - if (NetIndex >= pAC->Rlmt.NumNets) { - return (SK_PNMI_ERR_UNKNOWN_NET); - } - - SK_PNMI_CHECKFLAGS("PnmiStruct: On call"); - - /* - * Update the values of RLMT and SIRQ and increment semaphores to - * indicate that an update was already done. - */ - if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) { - - SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (Ret); - } - - if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) { - - SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (Ret); - } - - pAC->Pnmi.RlmtUpdatedFlag ++; - pAC->Pnmi.SirqUpdatedFlag ++; - - /* Preset/Set values */ - for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) { - - if ((IdTable[TableIndex].Access != SK_PNMI_RW) && - (IdTable[TableIndex].Access != SK_PNMI_WO)) { - - continue; - } - - InstanceNo = IdTable[TableIndex].InstanceNo; - Id = IdTable[TableIndex].Id; - - for (InstanceCnt = 1; InstanceCnt <= InstanceNo; - InstanceCnt ++) { - - DstOffset = IdTable[TableIndex].Offset + - (InstanceCnt - 1) * - IdTable[TableIndex].StructSize; - - /* - * Because VPD multiple instance variables are - * not setable we do not need to evaluate VPD - * instances. Have a look to VPD instance - * calculation in SkPnmiGetStruct(). - */ - Instance = (SK_U32)InstanceCnt; - - /* - * Evaluate needed buffer length - */ - Len = 0; - Ret = IdTable[TableIndex].Func(pAC, IoC, - SK_PNMI_GET, IdTable[TableIndex].Id, - NULL, &Len, Instance, TableIndex, NetIndex); - - if (Ret == SK_PNMI_ERR_UNKNOWN_INST) { - - break; - } - if (Ret != SK_PNMI_ERR_TOO_SHORT) { - - pAC->Pnmi.RlmtUpdatedFlag --; - pAC->Pnmi.SirqUpdatedFlag --; - - SK_PNMI_CHECKFLAGS("PnmiStruct: On return"); - SK_PNMI_SET_STAT(pBuf, - SK_PNMI_ERR_GENERAL, DstOffset); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (SK_PNMI_ERR_GENERAL); - } - if (Id == OID_SKGE_VPD_ACTION) { - - switch (*(pBuf + DstOffset)) { - - case SK_PNMI_VPD_CREATE: - Len = 3 + *(pBuf + DstOffset + 3); - break; - - case SK_PNMI_VPD_DELETE: - Len = 3; - break; - - default: - Len = 1; - break; - } - } - - /* Call the OID handler function */ - Ret = IdTable[TableIndex].Func(pAC, IoC, Action, - IdTable[TableIndex].Id, pBuf + DstOffset, - &Len, Instance, TableIndex, NetIndex); - - if (Ret != SK_PNMI_ERR_OK) { - - pAC->Pnmi.RlmtUpdatedFlag --; - pAC->Pnmi.SirqUpdatedFlag --; - - SK_PNMI_CHECKFLAGS("PnmiStruct: On return"); - SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_BAD_VALUE, - DstOffset); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (SK_PNMI_ERR_BAD_VALUE); - } - } - } - - pAC->Pnmi.RlmtUpdatedFlag --; - pAC->Pnmi.SirqUpdatedFlag --; - - SK_PNMI_CHECKFLAGS("PnmiStruct: On return"); - SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1)); - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * LookupId - Lookup an OID in the IdTable - * - * Description: - * Scans the IdTable to find the table entry of an OID. - * - * Returns: - * The table index or -1 if not found. - */ -PNMI_STATIC int LookupId( -SK_U32 Id) /* Object identifier to be searched */ -{ - int i; - - for (i = 0; i < ID_TABLE_SIZE; i++) { - - if (IdTable[i].Id == Id) { - - return i; - } - } - - return (-1); -} - -/***************************************************************************** - * - * OidStruct - Handler of OID_SKGE_ALL_DATA - * - * Description: - * This OID performs a Get/Preset/SetStruct call and returns all data - * in a SK_PNMI_STRUCT_DATA structure. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int OidStruct( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - if (Id != OID_SKGE_ALL_DATA) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR003, - SK_PNMI_ERR003MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * Check instance. We only handle single instance variables - */ - if (Instance != (SK_U32)(-1) && Instance != 1) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - switch (Action) { - - case SK_PNMI_GET: - return (SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex)); - - case SK_PNMI_PRESET: - return (SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex)); - - case SK_PNMI_SET: - return (SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex)); - } - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR004, SK_PNMI_ERR004MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); -} - -/***************************************************************************** - * - * Perform - OID handler of OID_SKGE_ACTION - * - * Description: - * None. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int Perform( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - int Ret; - SK_U32 ActionOp; - - - /* - * Check instance. We only handle single instance variables - */ - if (Instance != (SK_U32)(-1) && Instance != 1) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* Check if a get should be performed */ - if (Action == SK_PNMI_GET) { - - /* A get is easy. We always return the same value */ - ActionOp = (SK_U32)SK_PNMI_ACT_IDLE; - SK_PNMI_STORE_U32(pBuf, ActionOp); - *pLen = sizeof(SK_U32); - - return (SK_PNMI_ERR_OK); - } - - /* Continue with PRESET/SET action */ - if (*pLen > sizeof(SK_U32)) { - - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* Check if the command is a known one */ - SK_PNMI_READ_U32(pBuf, ActionOp); - if (*pLen > sizeof(SK_U32) || - (ActionOp != SK_PNMI_ACT_IDLE && - ActionOp != SK_PNMI_ACT_RESET && - ActionOp != SK_PNMI_ACT_SELFTEST && - ActionOp != SK_PNMI_ACT_RESETCNT)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* A preset ends here */ - if (Action == SK_PNMI_PRESET) { - - return (SK_PNMI_ERR_OK); - } - - switch (ActionOp) { - - case SK_PNMI_ACT_IDLE: - /* Nothing to do */ - break; - - case SK_PNMI_ACT_RESET: - /* - * Perform a driver reset or something that comes near - * to this. - */ - Ret = SK_DRIVER_RESET(pAC, IoC); - if (Ret != 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR005, - SK_PNMI_ERR005MSG); - - return (SK_PNMI_ERR_GENERAL); - } - break; - - case SK_PNMI_ACT_SELFTEST: - /* - * Perform a driver selftest or something similar to this. - * Currently this feature is not used and will probably - * implemented in another way. - */ - Ret = SK_DRIVER_SELFTEST(pAC, IoC); - pAC->Pnmi.TestResult = Ret; - break; - - case SK_PNMI_ACT_RESETCNT: - /* Set all counters and timestamps to zero */ - ResetCounter(pAC, IoC, NetIndex); - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR006, - SK_PNMI_ERR006MSG); - - return (SK_PNMI_ERR_GENERAL); - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * Mac8023Stat - OID handler of OID_GEN_XXX and OID_802_3_XXX - * - * Description: - * Retrieves the statistic values of the virtual port (logical - * index 0). Only special OIDs of NDIS are handled which consist - * of a 32 bit instead of a 64 bit value. The OIDs are public - * because perhaps some other platform can use them too. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int Mac8023Stat( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - int Ret; - SK_U64 StatVal; - SK_U32 StatVal32; - SK_BOOL Is64BitReq = SK_FALSE; - - /* - * Only the active Mac is returned - */ - if (Instance != (SK_U32)(-1) && Instance != 1) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - /* - * Check action type - */ - if (Action != SK_PNMI_GET) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* Check length */ - switch (Id) { - - case OID_802_3_PERMANENT_ADDRESS: - case OID_802_3_CURRENT_ADDRESS: - if (*pLen < sizeof(SK_MAC_ADDR)) { - - *pLen = sizeof(SK_MAC_ADDR); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: -#ifndef SK_NDIS_64BIT_CTR - if (*pLen < sizeof(SK_U32)) { - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - -#else /* SK_NDIS_64BIT_CTR */ - - /* for compatibility, at least 32bit are required for OID */ - if (*pLen < sizeof(SK_U32)) { - /* - * but indicate handling for 64bit values, - * if insufficient space is provided - */ - *pLen = sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - - Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE; -#endif /* SK_NDIS_64BIT_CTR */ - break; - } - - /* - * Update all statistics, because we retrieve virtual MAC, which - * consists of multiple physical statistics and increment semaphore - * to indicate that an update was already done. - */ - Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1); - if ( Ret != SK_PNMI_ERR_OK) { - - *pLen = 0; - return (Ret); - } - pAC->Pnmi.MacUpdatedFlag ++; - - /* - * Get value (MAC Index 0 identifies the virtual MAC) - */ - switch (Id) { - - case OID_802_3_PERMANENT_ADDRESS: - CopyMac(pBuf, &pAC->Addr.Net[NetIndex].PermanentMacAddress); - *pLen = sizeof(SK_MAC_ADDR); - break; - - case OID_802_3_CURRENT_ADDRESS: - CopyMac(pBuf, &pAC->Addr.Net[NetIndex].CurrentMacAddress); - *pLen = sizeof(SK_MAC_ADDR); - break; - - default: - StatVal = GetStatVal(pAC, IoC, 0, IdTable[TableIndex].Param, NetIndex); - - /* by default 32bit values are evaluated */ - if (!Is64BitReq) { - StatVal32 = (SK_U32)StatVal; - SK_PNMI_STORE_U32(pBuf, StatVal32); - *pLen = sizeof(SK_U32); - } - else { - SK_PNMI_STORE_U64(pBuf, StatVal); - *pLen = sizeof(SK_U64); - } - break; - } - - pAC->Pnmi.MacUpdatedFlag --; - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * MacPrivateStat - OID handler function of OID_SKGE_STAT_XXX - * - * Description: - * Retrieves the MAC statistic data. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int MacPrivateStat( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - unsigned int LogPortMax; - unsigned int LogPortIndex; - unsigned int PhysPortMax; - unsigned int Limit; - unsigned int Offset; - int MacType; - int Ret; - SK_U64 StatVal; - - - - /* Calculate instance if wished. MAC index 0 is the virtual MAC */ - PhysPortMax = pAC->GIni.GIMacsFound; - LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); - - MacType = pAC->GIni.GIMacType; - - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */ - LogPortMax--; - } - - if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */ - /* Check instance range */ - if ((Instance < 1) || (Instance > LogPortMax)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance); - Limit = LogPortIndex + 1; - } - - else { /* Instance == (SK_U32)(-1), get all Instances of that OID */ - - LogPortIndex = 0; - Limit = LogPortMax; - } - - /* Check action */ - if (Action != SK_PNMI_GET) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* Check length */ - if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U64)) { - - *pLen = (Limit - LogPortIndex) * sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* - * Update MAC statistic and increment semaphore to indicate that - * an update was already done. - */ - Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1); - if (Ret != SK_PNMI_ERR_OK) { - - *pLen = 0; - return (Ret); - } - pAC->Pnmi.MacUpdatedFlag ++; - - /* Get value */ - Offset = 0; - for (; LogPortIndex < Limit; LogPortIndex ++) { - - switch (Id) { - -/* XXX not yet implemented due to XMAC problems - case OID_SKGE_STAT_TX_UTIL: - return (SK_PNMI_ERR_GENERAL); -*/ -/* XXX not yet implemented due to XMAC problems - case OID_SKGE_STAT_RX_UTIL: - return (SK_PNMI_ERR_GENERAL); -*/ - case OID_SKGE_STAT_RX: - if (MacType == SK_MAC_GMAC) { - StatVal = - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HRX_BROADCAST, NetIndex) + - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HRX_MULTICAST, NetIndex) + - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HRX_UNICAST, NetIndex) + - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HRX_UNDERSIZE, NetIndex); - } - else { - StatVal = GetStatVal(pAC, IoC, LogPortIndex, - IdTable[TableIndex].Param, NetIndex); - } - break; - - case OID_SKGE_STAT_TX: - if (MacType == SK_MAC_GMAC) { - StatVal = - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HTX_BROADCAST, NetIndex) + - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HTX_MULTICAST, NetIndex) + - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HTX_UNICAST, NetIndex); - } - else { - StatVal = GetStatVal(pAC, IoC, LogPortIndex, - IdTable[TableIndex].Param, NetIndex); - } - break; - - default: - StatVal = GetStatVal(pAC, IoC, LogPortIndex, - IdTable[TableIndex].Param, NetIndex); - } - SK_PNMI_STORE_U64(pBuf + Offset, StatVal); - - Offset += sizeof(SK_U64); - } - *pLen = Offset; - - pAC->Pnmi.MacUpdatedFlag --; - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * Addr - OID handler function of OID_SKGE_PHYS_CUR_ADDR and _FAC_ADDR - * - * Description: - * Get/Presets/Sets the current and factory MAC address. The MAC - * address of the virtual port, which is reported to the OS, may - * not be changed, but the physical ones. A set to the virtual port - * will be ignored. No error should be reported because otherwise - * a multiple instance set (-1) would always fail. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int Addr( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - int Ret; - unsigned int LogPortMax; - unsigned int PhysPortMax; - unsigned int LogPortIndex; - unsigned int PhysPortIndex; - unsigned int Limit; - unsigned int Offset = 0; - - /* - * Calculate instance if wished. MAC index 0 is the virtual - * MAC. - */ - PhysPortMax = pAC->GIni.GIMacsFound; - LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); - - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */ - LogPortMax--; - } - - if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */ - /* Check instance range */ - if ((Instance < 1) || (Instance > LogPortMax)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance); - Limit = LogPortIndex + 1; - } - else { /* Instance == (SK_U32)(-1), get all Instances of that OID */ - - LogPortIndex = 0; - Limit = LogPortMax; - } - - /* - * Perform Action - */ - if (Action == SK_PNMI_GET) { - - /* Check length */ - if (*pLen < (Limit - LogPortIndex) * 6) { - - *pLen = (Limit - LogPortIndex) * 6; - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* - * Get value - */ - for (; LogPortIndex < Limit; LogPortIndex ++) { - - switch (Id) { - - case OID_SKGE_PHYS_CUR_ADDR: - if (LogPortIndex == 0) { - CopyMac(pBuf + Offset, &pAC->Addr.Net[NetIndex].CurrentMacAddress); - } - else { - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); - - CopyMac(pBuf + Offset, - &pAC->Addr.Port[PhysPortIndex].CurrentMacAddress); - } - Offset += 6; - break; - - case OID_SKGE_PHYS_FAC_ADDR: - if (LogPortIndex == 0) { - CopyMac(pBuf + Offset, - &pAC->Addr.Net[NetIndex].PermanentMacAddress); - } - else { - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - CopyMac(pBuf + Offset, - &pAC->Addr.Port[PhysPortIndex].PermanentMacAddress); - } - Offset += 6; - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR008, - SK_PNMI_ERR008MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - - *pLen = Offset; - } - else { - /* - * The logical MAC address may not be changed only - * the physical ones - */ - if (Id == OID_SKGE_PHYS_FAC_ADDR) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* - * Only the current address may be changed - */ - if (Id != OID_SKGE_PHYS_CUR_ADDR) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR009, - SK_PNMI_ERR009MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* Check length */ - if (*pLen < (Limit - LogPortIndex) * 6) { - - *pLen = (Limit - LogPortIndex) * 6; - return (SK_PNMI_ERR_TOO_SHORT); - } - if (*pLen > (Limit - LogPortIndex) * 6) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* - * Check Action - */ - if (Action == SK_PNMI_PRESET) { - - *pLen = 0; - return (SK_PNMI_ERR_OK); - } - - /* - * Set OID_SKGE_MAC_CUR_ADDR - */ - for (; LogPortIndex < Limit; LogPortIndex ++, Offset += 6) { - - /* - * A set to virtual port and set of broadcast - * address will be ignored - */ - if (LogPortIndex == 0 || SK_MEMCMP(pBuf + Offset, - "\xff\xff\xff\xff\xff\xff", 6) == 0) { - - continue; - } - - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, - LogPortIndex); - - Ret = SkAddrOverride(pAC, IoC, PhysPortIndex, - (SK_MAC_ADDR *)(pBuf + Offset), - (LogPortIndex == 0 ? SK_ADDR_VIRTUAL_ADDRESS : - SK_ADDR_PHYSICAL_ADDRESS)); - if (Ret != SK_ADDR_OVERRIDE_SUCCESS) { - - return (SK_PNMI_ERR_GENERAL); - } - } - *pLen = Offset; - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * CsumStat - OID handler function of OID_SKGE_CHKSM_XXX - * - * Description: - * Retrieves the statistic values of the CSUM module. The CSUM data - * structure must be available in the SK_AC even if the CSUM module - * is not included, because PNMI reads the statistic data from the - * CSUM part of SK_AC directly. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int CsumStat( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - unsigned int Index; - unsigned int Limit; - unsigned int Offset = 0; - SK_U64 StatVal; - - - /* - * Calculate instance if wished - */ - if (Instance != (SK_U32)(-1)) { - - if ((Instance < 1) || (Instance > SKCS_NUM_PROTOCOLS)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - Index = (unsigned int)Instance - 1; - Limit = Index + 1; - } - else { - Index = 0; - Limit = SKCS_NUM_PROTOCOLS; - } - - /* - * Check action - */ - if (Action != SK_PNMI_GET) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* Check length */ - if (*pLen < (Limit - Index) * sizeof(SK_U64)) { - - *pLen = (Limit - Index) * sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* - * Get value - */ - for (; Index < Limit; Index ++) { - - switch (Id) { - - case OID_SKGE_CHKSM_RX_OK_CTS: - StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxOkCts; - break; - - case OID_SKGE_CHKSM_RX_UNABLE_CTS: - StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxUnableCts; - break; - - case OID_SKGE_CHKSM_RX_ERR_CTS: - StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxErrCts; - break; - - case OID_SKGE_CHKSM_TX_OK_CTS: - StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxOkCts; - break; - - case OID_SKGE_CHKSM_TX_UNABLE_CTS: - StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxUnableCts; - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR010, - SK_PNMI_ERR010MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - SK_PNMI_STORE_U64(pBuf + Offset, StatVal); - Offset += sizeof(SK_U64); - } - - /* - * Store used buffer space - */ - *pLen = Offset; - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * SensorStat - OID handler function of OID_SKGE_SENSOR_XXX - * - * Description: - * Retrieves the statistic values of the I2C module, which handles - * the temperature and voltage sensors. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int SensorStat( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - unsigned int i; - unsigned int Index; - unsigned int Limit; - unsigned int Offset; - unsigned int Len; - SK_U32 Val32; - SK_U64 Val64; - - - /* - * Calculate instance if wished - */ - if ((Instance != (SK_U32)(-1))) { - - if ((Instance < 1) || (Instance > (SK_U32)pAC->I2c.MaxSens)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - Index = (unsigned int)Instance -1; - Limit = (unsigned int)Instance; - } - else { - Index = 0; - Limit = (unsigned int) pAC->I2c.MaxSens; - } - - /* - * Check action - */ - if (Action != SK_PNMI_GET) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* Check length */ - switch (Id) { - - case OID_SKGE_SENSOR_VALUE: - case OID_SKGE_SENSOR_WAR_THRES_LOW: - case OID_SKGE_SENSOR_WAR_THRES_UPP: - case OID_SKGE_SENSOR_ERR_THRES_LOW: - case OID_SKGE_SENSOR_ERR_THRES_UPP: - if (*pLen < (Limit - Index) * sizeof(SK_U32)) { - - *pLen = (Limit - Index) * sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_SENSOR_DESCR: - for (Offset = 0, i = Index; i < Limit; i ++) { - - Len = (unsigned int) - SK_STRLEN(pAC->I2c.SenTable[i].SenDesc) + 1; - if (Len >= SK_PNMI_STRINGLEN2) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR011, - SK_PNMI_ERR011MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - Offset += Len; - } - if (*pLen < Offset) { - - *pLen = Offset; - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_SENSOR_INDEX: - case OID_SKGE_SENSOR_TYPE: - case OID_SKGE_SENSOR_STATUS: - if (*pLen < Limit - Index) { - - *pLen = Limit - Index; - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_SENSOR_WAR_CTS: - case OID_SKGE_SENSOR_WAR_TIME: - case OID_SKGE_SENSOR_ERR_CTS: - case OID_SKGE_SENSOR_ERR_TIME: - if (*pLen < (Limit - Index) * sizeof(SK_U64)) { - - *pLen = (Limit - Index) * sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR012, - SK_PNMI_ERR012MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - - } - - /* - * Get value - */ - for (Offset = 0; Index < Limit; Index ++) { - - switch (Id) { - - case OID_SKGE_SENSOR_INDEX: - *(pBuf + Offset) = (char)Index; - Offset += sizeof(char); - break; - - case OID_SKGE_SENSOR_DESCR: - Len = SK_STRLEN(pAC->I2c.SenTable[Index].SenDesc); - SK_MEMCPY(pBuf + Offset + 1, - pAC->I2c.SenTable[Index].SenDesc, Len); - *(pBuf + Offset) = (char)Len; - Offset += Len + 1; - break; - - case OID_SKGE_SENSOR_TYPE: - *(pBuf + Offset) = - (char)pAC->I2c.SenTable[Index].SenType; - Offset += sizeof(char); - break; - - case OID_SKGE_SENSOR_VALUE: - Val32 = (SK_U32)pAC->I2c.SenTable[Index].SenValue; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - Offset += sizeof(SK_U32); - break; - - case OID_SKGE_SENSOR_WAR_THRES_LOW: - Val32 = (SK_U32)pAC->I2c.SenTable[Index]. - SenThreWarnLow; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - Offset += sizeof(SK_U32); - break; - - case OID_SKGE_SENSOR_WAR_THRES_UPP: - Val32 = (SK_U32)pAC->I2c.SenTable[Index]. - SenThreWarnHigh; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - Offset += sizeof(SK_U32); - break; - - case OID_SKGE_SENSOR_ERR_THRES_LOW: - Val32 = (SK_U32)pAC->I2c.SenTable[Index]. - SenThreErrLow; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - Offset += sizeof(SK_U32); - break; - - case OID_SKGE_SENSOR_ERR_THRES_UPP: - Val32 = pAC->I2c.SenTable[Index].SenThreErrHigh; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - Offset += sizeof(SK_U32); - break; - - case OID_SKGE_SENSOR_STATUS: - *(pBuf + Offset) = - (char)pAC->I2c.SenTable[Index].SenErrFlag; - Offset += sizeof(char); - break; - - case OID_SKGE_SENSOR_WAR_CTS: - Val64 = pAC->I2c.SenTable[Index].SenWarnCts; - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - case OID_SKGE_SENSOR_ERR_CTS: - Val64 = pAC->I2c.SenTable[Index].SenErrCts; - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - case OID_SKGE_SENSOR_WAR_TIME: - Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index]. - SenBegWarnTS); - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - case OID_SKGE_SENSOR_ERR_TIME: - Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index]. - SenBegErrTS); - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - default: - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, - ("SensorStat: Unknown OID should be handled before")); - - return (SK_PNMI_ERR_GENERAL); - } - } - - /* - * Store used buffer space - */ - *pLen = Offset; - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * Vpd - OID handler function of OID_SKGE_VPD_XXX - * - * Description: - * Get/preset/set of VPD data. As instance the name of a VPD key - * can be passed. The Instance parameter is a SK_U32 and can be - * used as a string buffer for the VPD key, because their maximum - * length is 4 byte. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int Vpd( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - SK_VPD_STATUS *pVpdStatus; - unsigned int BufLen; - char Buf[256]; - char KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE]; - char KeyStr[SK_PNMI_VPD_KEY_SIZE]; - unsigned int KeyNo; - unsigned int Offset; - unsigned int Index; - unsigned int FirstIndex; - unsigned int LastIndex; - unsigned int Len; - int Ret; - SK_U32 Val32; - - /* - * Get array of all currently stored VPD keys - */ - Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &KeyNo); - if (Ret != SK_PNMI_ERR_OK) { - *pLen = 0; - return (Ret); - } - - /* - * If instance is not -1, try to find the requested VPD key for - * the multiple instance variables. The other OIDs as for example - * OID VPD_ACTION are single instance variables and must be - * handled separatly. - */ - FirstIndex = 0; - LastIndex = KeyNo; - - if ((Instance != (SK_U32)(-1))) { - - if (Id == OID_SKGE_VPD_KEY || Id == OID_SKGE_VPD_VALUE || - Id == OID_SKGE_VPD_ACCESS) { - - SK_STRNCPY(KeyStr, (char *)&Instance, 4); - KeyStr[4] = 0; - - for (Index = 0; Index < KeyNo; Index ++) { - - if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) { - FirstIndex = Index; - LastIndex = Index+1; - break; - } - } - if (Index == KeyNo) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - } - else if (Instance != 1) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - } - - /* - * Get value, if a query should be performed - */ - if (Action == SK_PNMI_GET) { - - switch (Id) { - - case OID_SKGE_VPD_FREE_BYTES: - /* Check length of buffer */ - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - /* Get number of free bytes */ - pVpdStatus = VpdStat(pAC, IoC); - if (pVpdStatus == NULL) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR017, - SK_PNMI_ERR017MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - if ((pVpdStatus->vpd_status & VPD_VALID) == 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR018, - SK_PNMI_ERR018MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - Val32 = (SK_U32)pVpdStatus->vpd_free_rw; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_VPD_ENTRIES_LIST: - /* Check length */ - for (Len = 0, Index = 0; Index < KeyNo; Index ++) { - - Len += SK_STRLEN(KeyArr[Index]) + 1; - } - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* Get value */ - *(pBuf) = (char)Len - 1; - for (Offset = 1, Index = 0; Index < KeyNo; Index ++) { - - Len = SK_STRLEN(KeyArr[Index]); - SK_MEMCPY(pBuf + Offset, KeyArr[Index], Len); - - Offset += Len; - - if (Index < KeyNo - 1) { - - *(pBuf + Offset) = ' '; - Offset ++; - } - } - *pLen = Offset; - break; - - case OID_SKGE_VPD_ENTRIES_NUMBER: - /* Check length */ - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - - Val32 = (SK_U32)KeyNo; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_VPD_KEY: - /* Check buffer length, if it is large enough */ - for (Len = 0, Index = FirstIndex; - Index < LastIndex; Index ++) { - - Len += SK_STRLEN(KeyArr[Index]) + 1; - } - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* - * Get the key to an intermediate buffer, because - * we have to prepend a length byte. - */ - for (Offset = 0, Index = FirstIndex; - Index < LastIndex; Index ++) { - - Len = SK_STRLEN(KeyArr[Index]); - - *(pBuf + Offset) = (char)Len; - SK_MEMCPY(pBuf + Offset + 1, KeyArr[Index], - Len); - Offset += Len + 1; - } - *pLen = Offset; - break; - - case OID_SKGE_VPD_VALUE: - /* Check the buffer length if it is large enough */ - for (Offset = 0, Index = FirstIndex; - Index < LastIndex; Index ++) { - - BufLen = 256; - if (VpdRead(pAC, IoC, KeyArr[Index], Buf, - (int *)&BufLen) > 0 || - BufLen >= SK_PNMI_VPD_DATALEN) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR021, - SK_PNMI_ERR021MSG); - - return (SK_PNMI_ERR_GENERAL); - } - Offset += BufLen + 1; - } - if (*pLen < Offset) { - - *pLen = Offset; - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* - * Get the value to an intermediate buffer, because - * we have to prepend a length byte. - */ - for (Offset = 0, Index = FirstIndex; - Index < LastIndex; Index ++) { - - BufLen = 256; - if (VpdRead(pAC, IoC, KeyArr[Index], Buf, - (int *)&BufLen) > 0 || - BufLen >= SK_PNMI_VPD_DATALEN) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR022, - SK_PNMI_ERR022MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - *(pBuf + Offset) = (char)BufLen; - SK_MEMCPY(pBuf + Offset + 1, Buf, BufLen); - Offset += BufLen + 1; - } - *pLen = Offset; - break; - - case OID_SKGE_VPD_ACCESS: - if (*pLen < LastIndex - FirstIndex) { - - *pLen = LastIndex - FirstIndex; - return (SK_PNMI_ERR_TOO_SHORT); - } - - for (Offset = 0, Index = FirstIndex; - Index < LastIndex; Index ++) { - - if (VpdMayWrite(KeyArr[Index])) { - - *(pBuf + Offset) = SK_PNMI_VPD_RW; - } - else { - *(pBuf + Offset) = SK_PNMI_VPD_RO; - } - Offset ++; - } - *pLen = Offset; - break; - - case OID_SKGE_VPD_ACTION: - Offset = LastIndex - FirstIndex; - if (*pLen < Offset) { - - *pLen = Offset; - return (SK_PNMI_ERR_TOO_SHORT); - } - SK_MEMSET(pBuf, 0, Offset); - *pLen = Offset; - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR023, - SK_PNMI_ERR023MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - else { - /* The only OID which can be set is VPD_ACTION */ - if (Id != OID_SKGE_VPD_ACTION) { - - if (Id == OID_SKGE_VPD_FREE_BYTES || - Id == OID_SKGE_VPD_ENTRIES_LIST || - Id == OID_SKGE_VPD_ENTRIES_NUMBER || - Id == OID_SKGE_VPD_KEY || - Id == OID_SKGE_VPD_VALUE || - Id == OID_SKGE_VPD_ACCESS) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR024, - SK_PNMI_ERR024MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * From this point we handle VPD_ACTION. Check the buffer - * length. It should at least have the size of one byte. - */ - if (*pLen < 1) { - - *pLen = 1; - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* - * The first byte contains the VPD action type we should - * perform. - */ - switch (*pBuf) { - - case SK_PNMI_VPD_IGNORE: - /* Nothing to do */ - break; - - case SK_PNMI_VPD_CREATE: - /* - * We have to create a new VPD entry or we modify - * an existing one. Check first the buffer length. - */ - if (*pLen < 4) { - - *pLen = 4; - return (SK_PNMI_ERR_TOO_SHORT); - } - KeyStr[0] = pBuf[1]; - KeyStr[1] = pBuf[2]; - KeyStr[2] = 0; - - /* - * Is the entry writable or does it belong to the - * read-only area? - */ - if (!VpdMayWrite(KeyStr)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - Offset = (int)pBuf[3] & 0xFF; - - SK_MEMCPY(Buf, pBuf + 4, Offset); - Buf[Offset] = 0; - - /* A preset ends here */ - if (Action == SK_PNMI_PRESET) { - - return (SK_PNMI_ERR_OK); - } - - /* Write the new entry or modify an existing one */ - Ret = VpdWrite(pAC, IoC, KeyStr, Buf); - if (Ret == SK_PNMI_VPD_NOWRITE ) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - else if (Ret != SK_PNMI_VPD_OK) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR025, - SK_PNMI_ERR025MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * Perform an update of the VPD data. This is - * not mandantory, but just to be sure. - */ - Ret = VpdUpdate(pAC, IoC); - if (Ret != SK_PNMI_VPD_OK) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR026, - SK_PNMI_ERR026MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - break; - - case SK_PNMI_VPD_DELETE: - /* Check if the buffer size is plausible */ - if (*pLen < 3) { - - *pLen = 3; - return (SK_PNMI_ERR_TOO_SHORT); - } - if (*pLen > 3) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - KeyStr[0] = pBuf[1]; - KeyStr[1] = pBuf[2]; - KeyStr[2] = 0; - - /* Find the passed key in the array */ - for (Index = 0; Index < KeyNo; Index ++) { - - if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) { - - break; - } - } - /* - * If we cannot find the key it is wrong, so we - * return an appropriate error value. - */ - if (Index == KeyNo) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - if (Action == SK_PNMI_PRESET) { - - return (SK_PNMI_ERR_OK); - } - - /* Ok, you wanted it and you will get it */ - Ret = VpdDelete(pAC, IoC, KeyStr); - if (Ret != SK_PNMI_VPD_OK) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR027, - SK_PNMI_ERR027MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * Perform an update of the VPD data. This is - * not mandantory, but just to be sure. - */ - Ret = VpdUpdate(pAC, IoC); - if (Ret != SK_PNMI_VPD_OK) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR028, - SK_PNMI_ERR028MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - break; - - default: - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * General - OID handler function of various single instance OIDs - * - * Description: - * The code is simple. No description necessary. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int General( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - int Ret; - unsigned int Index; - unsigned int Len; - unsigned int Offset; - unsigned int Val; - SK_U8 Val8; - SK_U16 Val16; - SK_U32 Val32; - SK_U64 Val64; - SK_U64 Val64RxHwErrs = 0; - SK_U64 Val64TxHwErrs = 0; - SK_BOOL Is64BitReq = SK_FALSE; - char Buf[256]; - int MacType; - - /* - * Check instance. We only handle single instance variables. - */ - if (Instance != (SK_U32)(-1) && Instance != 1) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - /* - * Check action. We only allow get requests. - */ - if (Action != SK_PNMI_GET) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - MacType = pAC->GIni.GIMacType; - - /* - * Check length for the various supported OIDs - */ - switch (Id) { - - case OID_GEN_XMIT_ERROR: - case OID_GEN_RCV_ERROR: - case OID_GEN_RCV_NO_BUFFER: -#ifndef SK_NDIS_64BIT_CTR - if (*pLen < sizeof(SK_U32)) { - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - -#else /* SK_NDIS_64BIT_CTR */ - - /* - * for compatibility, at least 32bit are required for oid - */ - if (*pLen < sizeof(SK_U32)) { - /* - * but indicate handling for 64bit values, - * if insufficient space is provided - */ - *pLen = sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - - Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE; -#endif /* SK_NDIS_64BIT_CTR */ - break; - - case OID_SKGE_PORT_NUMBER: - case OID_SKGE_DEVICE_TYPE: - case OID_SKGE_RESULT: - case OID_SKGE_RLMT_MONITOR_NUMBER: - case OID_GEN_TRANSMIT_QUEUE_LENGTH: - case OID_SKGE_TRAP_NUMBER: - case OID_SKGE_MDB_VERSION: - case OID_SKGE_BOARDLEVEL: - case OID_SKGE_CHIPID: - case OID_SKGE_RAMSIZE: - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_CHIPSET: - if (*pLen < sizeof(SK_U16)) { - - *pLen = sizeof(SK_U16); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_BUS_TYPE: - case OID_SKGE_BUS_SPEED: - case OID_SKGE_BUS_WIDTH: - case OID_SKGE_SENSOR_NUMBER: - case OID_SKGE_CHKSM_NUMBER: - case OID_SKGE_VAUXAVAIL: - if (*pLen < sizeof(SK_U8)) { - - *pLen = sizeof(SK_U8); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_TX_SW_QUEUE_LEN: - case OID_SKGE_TX_SW_QUEUE_MAX: - case OID_SKGE_TX_RETRY: - case OID_SKGE_RX_INTR_CTS: - case OID_SKGE_TX_INTR_CTS: - case OID_SKGE_RX_NO_BUF_CTS: - case OID_SKGE_TX_NO_BUF_CTS: - case OID_SKGE_TX_USED_DESCR_NO: - case OID_SKGE_RX_DELIVERED_CTS: - case OID_SKGE_RX_OCTETS_DELIV_CTS: - case OID_SKGE_RX_HW_ERROR_CTS: - case OID_SKGE_TX_HW_ERROR_CTS: - case OID_SKGE_IN_ERRORS_CTS: - case OID_SKGE_OUT_ERROR_CTS: - case OID_SKGE_ERR_RECOVERY_CTS: - case OID_SKGE_SYSUPTIME: - if (*pLen < sizeof(SK_U64)) { - - *pLen = sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: - /* Checked later */ - break; - } - - /* Update statistic */ - if (Id == OID_SKGE_RX_HW_ERROR_CTS || - Id == OID_SKGE_TX_HW_ERROR_CTS || - Id == OID_SKGE_IN_ERRORS_CTS || - Id == OID_SKGE_OUT_ERROR_CTS || - Id == OID_GEN_XMIT_ERROR || - Id == OID_GEN_RCV_ERROR) { - - /* Force the XMAC to update its statistic counters and - * Increment semaphore to indicate that an update was - * already done. - */ - Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1); - if (Ret != SK_PNMI_ERR_OK) { - - *pLen = 0; - return (Ret); - } - pAC->Pnmi.MacUpdatedFlag ++; - - /* - * Some OIDs consist of multiple hardware counters. Those - * values which are contained in all of them will be added - * now. - */ - switch (Id) { - - case OID_SKGE_RX_HW_ERROR_CTS: - case OID_SKGE_IN_ERRORS_CTS: - case OID_GEN_RCV_ERROR: - Val64RxHwErrs = - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_MISSED, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FRAMING, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_JABBER, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CARRIER, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_IRLENGTH, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SYMBOL, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SHORTS, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_RUNT, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_TOO_LONG, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FCS, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CEXT, NetIndex); - break; - - case OID_SKGE_TX_HW_ERROR_CTS: - case OID_SKGE_OUT_ERROR_CTS: - case OID_GEN_XMIT_ERROR: - Val64TxHwErrs = - GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_EXCESS_COL, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_LATE_COL, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_UNDERRUN, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_CARRIER, NetIndex); - break; - } - } - - /* - * Retrieve value - */ - switch (Id) { - - case OID_SKGE_SUPPORTED_LIST: - Len = ID_TABLE_SIZE * sizeof(SK_U32); - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - for (Offset = 0, Index = 0; Offset < Len; - Offset += sizeof(SK_U32), Index ++) { - - Val32 = (SK_U32)IdTable[Index].Id; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - } - *pLen = Len; - break; - - case OID_SKGE_BOARDLEVEL: - Val32 = (SK_U32)pAC->GIni.GILevel; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_PORT_NUMBER: - Val32 = (SK_U32)pAC->GIni.GIMacsFound; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_DEVICE_TYPE: - Val32 = (SK_U32)pAC->Pnmi.DeviceType; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_DRIVER_DESCR: - if (pAC->Pnmi.pDriverDescription == NULL) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR007, - SK_PNMI_ERR007MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - Len = SK_STRLEN(pAC->Pnmi.pDriverDescription) + 1; - if (Len > SK_PNMI_STRINGLEN1) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR029, - SK_PNMI_ERR029MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - *pBuf = (char)(Len - 1); - SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverDescription, Len - 1); - *pLen = Len; - break; - - case OID_SKGE_DRIVER_VERSION: - if (pAC->Pnmi.pDriverVersion == NULL) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030, - SK_PNMI_ERR030MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - Len = SK_STRLEN(pAC->Pnmi.pDriverVersion) + 1; - if (Len > SK_PNMI_STRINGLEN1) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031, - SK_PNMI_ERR031MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - *pBuf = (char)(Len - 1); - SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverVersion, Len - 1); - *pLen = Len; - break; - - case OID_SKGE_DRIVER_RELDATE: - if (pAC->Pnmi.pDriverReleaseDate == NULL) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030, - SK_PNMI_ERR053MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - Len = SK_STRLEN(pAC->Pnmi.pDriverReleaseDate) + 1; - if (Len > SK_PNMI_STRINGLEN1) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031, - SK_PNMI_ERR054MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - *pBuf = (char)(Len - 1); - SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverReleaseDate, Len - 1); - *pLen = Len; - break; - - case OID_SKGE_DRIVER_FILENAME: - if (pAC->Pnmi.pDriverFileName == NULL) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030, - SK_PNMI_ERR055MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - Len = SK_STRLEN(pAC->Pnmi.pDriverFileName) + 1; - if (Len > SK_PNMI_STRINGLEN1) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031, - SK_PNMI_ERR056MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - *pBuf = (char)(Len - 1); - SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverFileName, Len - 1); - *pLen = Len; - break; - - case OID_SKGE_HW_DESCR: - /* - * The hardware description is located in the VPD. This - * query may move to the initialisation routine. But - * the VPD data is cached and therefore a call here - * will not make much difference. - */ - Len = 256; - if (VpdRead(pAC, IoC, VPD_NAME, Buf, (int *)&Len) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR032, - SK_PNMI_ERR032MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - Len ++; - if (Len > SK_PNMI_STRINGLEN1) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR033, - SK_PNMI_ERR033MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - *pBuf = (char)(Len - 1); - SK_MEMCPY(pBuf + 1, Buf, Len - 1); - *pLen = Len; - break; - - case OID_SKGE_HW_VERSION: - /* Oh, I love to do some string manipulation */ - if (*pLen < 5) { - - *pLen = 5; - return (SK_PNMI_ERR_TOO_SHORT); - } - Val8 = (SK_U8)pAC->GIni.GIPciHwRev; - pBuf[0] = 4; - pBuf[1] = 'v'; - pBuf[2] = (char)(0x30 | ((Val8 >> 4) & 0x0F)); - pBuf[3] = '.'; - pBuf[4] = (char)(0x30 | (Val8 & 0x0F)); - *pLen = 5; - break; - - case OID_SKGE_CHIPSET: - Val16 = pAC->Pnmi.Chipset; - SK_PNMI_STORE_U16(pBuf, Val16); - *pLen = sizeof(SK_U16); - break; - - case OID_SKGE_CHIPID: - Val32 = pAC->GIni.GIChipId; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_RAMSIZE: - Val32 = pAC->GIni.GIRamSize; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_VAUXAVAIL: - *pBuf = (char) pAC->GIni.GIVauxAvail; - *pLen = sizeof(char); - break; - - case OID_SKGE_BUS_TYPE: - *pBuf = (char) SK_PNMI_BUS_PCI; - *pLen = sizeof(char); - break; - - case OID_SKGE_BUS_SPEED: - *pBuf = pAC->Pnmi.PciBusSpeed; - *pLen = sizeof(char); - break; - - case OID_SKGE_BUS_WIDTH: - *pBuf = pAC->Pnmi.PciBusWidth; - *pLen = sizeof(char); - break; - - case OID_SKGE_RESULT: - Val32 = pAC->Pnmi.TestResult; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_SENSOR_NUMBER: - *pBuf = (char)pAC->I2c.MaxSens; - *pLen = sizeof(char); - break; - - case OID_SKGE_CHKSM_NUMBER: - *pBuf = SKCS_NUM_PROTOCOLS; - *pLen = sizeof(char); - break; - - case OID_SKGE_TRAP_NUMBER: - GetTrapQueueLen(pAC, &Len, &Val); - Val32 = (SK_U32)Val; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_TRAP: - GetTrapQueueLen(pAC, &Len, &Val); - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - CopyTrapQueue(pAC, pBuf); - *pLen = Len; - break; - - case OID_SKGE_RLMT_MONITOR_NUMBER: -/* XXX Not yet implemented by RLMT therefore we return zero elements */ - Val32 = 0; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_TX_SW_QUEUE_LEN: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueLen; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].TxSwQueueLen + - pAC->Pnmi.BufPort[1].TxSwQueueLen; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueLen; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].TxSwQueueLen + - pAC->Pnmi.Port[1].TxSwQueueLen; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - - case OID_SKGE_TX_SW_QUEUE_MAX: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueMax; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].TxSwQueueMax + - pAC->Pnmi.BufPort[1].TxSwQueueMax; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueMax; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].TxSwQueueMax + - pAC->Pnmi.Port[1].TxSwQueueMax; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_TX_RETRY: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].TxRetryCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].TxRetryCts + - pAC->Pnmi.BufPort[1].TxRetryCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].TxRetryCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].TxRetryCts + - pAC->Pnmi.Port[1].TxRetryCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RX_INTR_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].RxIntrCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].RxIntrCts + - pAC->Pnmi.BufPort[1].RxIntrCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].RxIntrCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].RxIntrCts + - pAC->Pnmi.Port[1].RxIntrCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_TX_INTR_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].TxIntrCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].TxIntrCts + - pAC->Pnmi.BufPort[1].TxIntrCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].TxIntrCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].TxIntrCts + - pAC->Pnmi.Port[1].TxIntrCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RX_NO_BUF_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].RxNoBufCts + - pAC->Pnmi.BufPort[1].RxNoBufCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].RxNoBufCts + - pAC->Pnmi.Port[1].RxNoBufCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_TX_NO_BUF_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].TxNoBufCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].TxNoBufCts + - pAC->Pnmi.BufPort[1].TxNoBufCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].TxNoBufCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].TxNoBufCts + - pAC->Pnmi.Port[1].TxNoBufCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_TX_USED_DESCR_NO: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].TxUsedDescrNo; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].TxUsedDescrNo + - pAC->Pnmi.BufPort[1].TxUsedDescrNo; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].TxUsedDescrNo; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].TxUsedDescrNo + - pAC->Pnmi.Port[1].TxUsedDescrNo; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RX_DELIVERED_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].RxDeliveredCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].RxDeliveredCts + - pAC->Pnmi.BufPort[1].RxDeliveredCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].RxDeliveredCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].RxDeliveredCts + - pAC->Pnmi.Port[1].RxDeliveredCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RX_OCTETS_DELIV_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].RxOctetsDeliveredCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].RxOctetsDeliveredCts + - pAC->Pnmi.BufPort[1].RxOctetsDeliveredCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].RxOctetsDeliveredCts + - pAC->Pnmi.Port[1].RxOctetsDeliveredCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RX_HW_ERROR_CTS: - SK_PNMI_STORE_U64(pBuf, Val64RxHwErrs); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_TX_HW_ERROR_CTS: - SK_PNMI_STORE_U64(pBuf, Val64TxHwErrs); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_IN_ERRORS_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; - } - /* Single net mode */ - else { - Val64 = Val64RxHwErrs + - pAC->Pnmi.BufPort[0].RxNoBufCts + - pAC->Pnmi.BufPort[1].RxNoBufCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts; - } - /* Single net mode */ - else { - Val64 = Val64RxHwErrs + - pAC->Pnmi.Port[0].RxNoBufCts + - pAC->Pnmi.Port[1].RxNoBufCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_OUT_ERROR_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts; - } - /* Single net mode */ - else { - Val64 = Val64TxHwErrs + - pAC->Pnmi.BufPort[0].TxNoBufCts + - pAC->Pnmi.BufPort[1].TxNoBufCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts; - } - /* Single net mode */ - else { - Val64 = Val64TxHwErrs + - pAC->Pnmi.Port[0].TxNoBufCts + - pAC->Pnmi.Port[1].TxNoBufCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_ERR_RECOVERY_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].ErrRecoveryCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].ErrRecoveryCts + - pAC->Pnmi.BufPort[1].ErrRecoveryCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].ErrRecoveryCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].ErrRecoveryCts + - pAC->Pnmi.Port[1].ErrRecoveryCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_SYSUPTIME: - Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC)); - Val64 -= pAC->Pnmi.StartUpTime; - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_MDB_VERSION: - Val32 = SK_PNMI_MDB_VERSION; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_GEN_RCV_ERROR: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; - } - else { - Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts; - } - - /* - * by default 32bit values are evaluated - */ - if (!Is64BitReq) { - Val32 = (SK_U32)Val64; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - } - else { - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - } - break; - - case OID_GEN_XMIT_ERROR: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts; - } - else { - Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts; - } - - /* - * by default 32bit values are evaluated - */ - if (!Is64BitReq) { - Val32 = (SK_U32)Val64; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - } - else { - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - } - break; - - case OID_GEN_RCV_NO_BUFFER: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; - } - else { - Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts; - } - - /* - * by default 32bit values are evaluated - */ - if (!Is64BitReq) { - Val32 = (SK_U32)Val64; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - } - else { - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - } - break; - - case OID_GEN_TRANSMIT_QUEUE_LENGTH: - Val32 = (SK_U32)pAC->Pnmi.Port[NetIndex].TxSwQueueLen; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR034, - SK_PNMI_ERR034MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - if (Id == OID_SKGE_RX_HW_ERROR_CTS || - Id == OID_SKGE_TX_HW_ERROR_CTS || - Id == OID_SKGE_IN_ERRORS_CTS || - Id == OID_SKGE_OUT_ERROR_CTS || - Id == OID_GEN_XMIT_ERROR || - Id == OID_GEN_RCV_ERROR) { - - pAC->Pnmi.MacUpdatedFlag --; - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * Rlmt - OID handler function of OID_SKGE_RLMT_XXX single instance. - * - * Description: - * Get/Presets/Sets the RLMT OIDs. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int Rlmt( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - int Ret; - unsigned int PhysPortIndex; - unsigned int PhysPortMax; - SK_EVPARA EventParam; - SK_U32 Val32; - SK_U64 Val64; - - - /* - * Check instance. Only single instance OIDs are allowed here. - */ - if (Instance != (SK_U32)(-1) && Instance != 1) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - /* - * Perform the requested action. - */ - if (Action == SK_PNMI_GET) { - - /* - * Check if the buffer length is large enough. - */ - - switch (Id) { - - case OID_SKGE_RLMT_MODE: - case OID_SKGE_RLMT_PORT_ACTIVE: - case OID_SKGE_RLMT_PORT_PREFERRED: - if (*pLen < sizeof(SK_U8)) { - - *pLen = sizeof(SK_U8); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_RLMT_PORT_NUMBER: - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_RLMT_CHANGE_CTS: - case OID_SKGE_RLMT_CHANGE_TIME: - case OID_SKGE_RLMT_CHANGE_ESTIM: - case OID_SKGE_RLMT_CHANGE_THRES: - if (*pLen < sizeof(SK_U64)) { - - *pLen = sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR035, - SK_PNMI_ERR035MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * Update RLMT statistic and increment semaphores to indicate - * that an update was already done. Maybe RLMT will hold its - * statistic always up to date some time. Then we can - * remove this type of call. - */ - if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) { - - *pLen = 0; - return (Ret); - } - pAC->Pnmi.RlmtUpdatedFlag ++; - - /* - * Retrieve Value - */ - switch (Id) { - - case OID_SKGE_RLMT_MODE: - *pBuf = (char)pAC->Rlmt.Net[0].RlmtMode; - *pLen = sizeof(char); - break; - - case OID_SKGE_RLMT_PORT_NUMBER: - Val32 = (SK_U32)pAC->GIni.GIMacsFound; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_RLMT_PORT_ACTIVE: - *pBuf = 0; - /* - * If multiple ports may become active this OID - * doesn't make sense any more. A new variable in - * the port structure should be created. However, - * for this variable the first active port is - * returned. - */ - PhysPortMax = pAC->GIni.GIMacsFound; - - for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { - - if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { - - *pBuf = (char)SK_PNMI_PORT_PHYS2LOG(PhysPortIndex); - break; - } - } - *pLen = sizeof(char); - break; - - case OID_SKGE_RLMT_PORT_PREFERRED: - *pBuf = (char)SK_PNMI_PORT_PHYS2LOG(pAC->Rlmt.Net[NetIndex].Preference); - *pLen = sizeof(char); - break; - - case OID_SKGE_RLMT_CHANGE_CTS: - Val64 = pAC->Pnmi.RlmtChangeCts; - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RLMT_CHANGE_TIME: - Val64 = pAC->Pnmi.RlmtChangeTime; - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RLMT_CHANGE_ESTIM: - Val64 = pAC->Pnmi.RlmtChangeEstimate.Estimate; - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RLMT_CHANGE_THRES: - Val64 = pAC->Pnmi.RlmtChangeThreshold; - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - default: - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, - ("Rlmt: Unknown OID should be handled before")); - - pAC->Pnmi.RlmtUpdatedFlag --; - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - pAC->Pnmi.RlmtUpdatedFlag --; - } - else { - /* Perform a preset or set */ - switch (Id) { - - case OID_SKGE_RLMT_MODE: - /* Check if the buffer length is plausible */ - if (*pLen < sizeof(char)) { - - *pLen = sizeof(char); - return (SK_PNMI_ERR_TOO_SHORT); - } - /* Check if the value range is correct */ - if (*pLen != sizeof(char) || - (*pBuf & SK_PNMI_RLMT_MODE_CHK_LINK) == 0 || - *(SK_U8 *)pBuf > 15) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - /* The preset ends here */ - if (Action == SK_PNMI_PRESET) { - - *pLen = 0; - return (SK_PNMI_ERR_OK); - } - /* Send an event to RLMT to change the mode */ - SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); - EventParam.Para32[0] |= (SK_U32)(*pBuf); - EventParam.Para32[1] = 0; - if (SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR037, - SK_PNMI_ERR037MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - break; - - case OID_SKGE_RLMT_PORT_PREFERRED: - /* Check if the buffer length is plausible */ - if (*pLen < sizeof(char)) { - - *pLen = sizeof(char); - return (SK_PNMI_ERR_TOO_SHORT); - } - /* Check if the value range is correct */ - if (*pLen != sizeof(char) || *(SK_U8 *)pBuf > - (SK_U8)pAC->GIni.GIMacsFound) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - /* The preset ends here */ - if (Action == SK_PNMI_PRESET) { - - *pLen = 0; - return (SK_PNMI_ERR_OK); - } - - /* - * Send an event to RLMT change the preferred port. - * A param of -1 means automatic mode. RLMT will - * make the decision which is the preferred port. - */ - SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); - EventParam.Para32[0] = (SK_U32)(*pBuf) - 1; - EventParam.Para32[1] = NetIndex; - if (SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR038, - SK_PNMI_ERR038MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - break; - - case OID_SKGE_RLMT_CHANGE_THRES: - /* Check if the buffer length is plausible */ - if (*pLen < sizeof(SK_U64)) { - - *pLen = sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - /* - * There are not many restrictions to the - * value range. - */ - if (*pLen != sizeof(SK_U64)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - /* A preset ends here */ - if (Action == SK_PNMI_PRESET) { - - *pLen = 0; - return (SK_PNMI_ERR_OK); - } - /* - * Store the new threshold, which will be taken - * on the next timer event. - */ - SK_PNMI_READ_U64(pBuf, Val64); - pAC->Pnmi.RlmtChangeThreshold = Val64; - break; - - default: - /* The other OIDs are not be able for set */ - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * RlmtStat - OID handler function of OID_SKGE_RLMT_XXX multiple instance. - * - * Description: - * Performs get requests on multiple instance variables. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int RlmtStat( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - unsigned int PhysPortMax; - unsigned int PhysPortIndex; - unsigned int Limit; - unsigned int Offset; - int Ret; - SK_U32 Val32; - SK_U64 Val64; - - /* - * Calculate the port indexes from the instance. - */ - PhysPortMax = pAC->GIni.GIMacsFound; - - if ((Instance != (SK_U32)(-1))) { - /* Check instance range */ - if ((Instance < 1) || (Instance > PhysPortMax)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - /* Single net mode */ - PhysPortIndex = Instance - 1; - - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - PhysPortIndex = NetIndex; - } - - /* Both net modes */ - Limit = PhysPortIndex + 1; - } - else { - /* Single net mode */ - PhysPortIndex = 0; - Limit = PhysPortMax; - - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - PhysPortIndex = NetIndex; - Limit = PhysPortIndex + 1; - } - } - - /* - * Currently only get requests are allowed. - */ - if (Action != SK_PNMI_GET) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* - * Check if the buffer length is large enough. - */ - switch (Id) { - - case OID_SKGE_RLMT_PORT_INDEX: - case OID_SKGE_RLMT_STATUS: - if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) { - - *pLen = (Limit - PhysPortIndex) * sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_RLMT_TX_HELLO_CTS: - case OID_SKGE_RLMT_RX_HELLO_CTS: - case OID_SKGE_RLMT_TX_SP_REQ_CTS: - case OID_SKGE_RLMT_RX_SP_CTS: - if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U64)) { - - *pLen = (Limit - PhysPortIndex) * sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR039, - SK_PNMI_ERR039MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - - } - - /* - * Update statistic and increment semaphores to indicate that - * an update was already done. - */ - if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) { - - *pLen = 0; - return (Ret); - } - pAC->Pnmi.RlmtUpdatedFlag ++; - - /* - * Get value - */ - Offset = 0; - for (; PhysPortIndex < Limit; PhysPortIndex ++) { - - switch (Id) { - - case OID_SKGE_RLMT_PORT_INDEX: - Val32 = PhysPortIndex; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - Offset += sizeof(SK_U32); - break; - - case OID_SKGE_RLMT_STATUS: - if (pAC->Rlmt.Port[PhysPortIndex].PortState == - SK_RLMT_PS_INIT || - pAC->Rlmt.Port[PhysPortIndex].PortState == - SK_RLMT_PS_DOWN) { - - Val32 = SK_PNMI_RLMT_STATUS_ERROR; - } - else if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { - - Val32 = SK_PNMI_RLMT_STATUS_ACTIVE; - } - else { - Val32 = SK_PNMI_RLMT_STATUS_STANDBY; - } - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - Offset += sizeof(SK_U32); - break; - - case OID_SKGE_RLMT_TX_HELLO_CTS: - Val64 = pAC->Rlmt.Port[PhysPortIndex].TxHelloCts; - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - case OID_SKGE_RLMT_RX_HELLO_CTS: - Val64 = pAC->Rlmt.Port[PhysPortIndex].RxHelloCts; - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - case OID_SKGE_RLMT_TX_SP_REQ_CTS: - Val64 = pAC->Rlmt.Port[PhysPortIndex].TxSpHelloReqCts; - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - case OID_SKGE_RLMT_RX_SP_CTS: - Val64 = pAC->Rlmt.Port[PhysPortIndex].RxSpHelloCts; - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - default: - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, - ("RlmtStat: Unknown OID should be errored before")); - - pAC->Pnmi.RlmtUpdatedFlag --; - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - *pLen = Offset; - - pAC->Pnmi.RlmtUpdatedFlag --; - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * MacPrivateConf - OID handler function of OIDs concerning the configuration - * - * Description: - * Get/Presets/Sets the OIDs concerning the configuration. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int MacPrivateConf( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - unsigned int PhysPortMax; - unsigned int PhysPortIndex; - unsigned int LogPortMax; - unsigned int LogPortIndex; - unsigned int Limit; - unsigned int Offset; - char Val8; - char *pBufPtr; - int Ret; - SK_EVPARA EventParam; - SK_U32 Val32; - - /* - * Calculate instance if wished. MAC index 0 is the virtual MAC. - */ - PhysPortMax = pAC->GIni.GIMacsFound; - LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); - - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */ - LogPortMax--; - } - - if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */ - /* Check instance range */ - if ((Instance < 1) || (Instance > LogPortMax)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance); - Limit = LogPortIndex + 1; - } - - else { /* Instance == (SK_U32)(-1), get all Instances of that OID */ - - LogPortIndex = 0; - Limit = LogPortMax; - } - - /* - * Perform action - */ - if (Action == SK_PNMI_GET) { - - /* Check length */ - switch (Id) { - - case OID_SKGE_PMD: - case OID_SKGE_CONNECTOR: - case OID_SKGE_LINK_CAP: - case OID_SKGE_LINK_MODE: - case OID_SKGE_LINK_MODE_STATUS: - case OID_SKGE_LINK_STATUS: - case OID_SKGE_FLOWCTRL_CAP: - case OID_SKGE_FLOWCTRL_MODE: - case OID_SKGE_FLOWCTRL_STATUS: - case OID_SKGE_PHY_OPERATION_CAP: - case OID_SKGE_PHY_OPERATION_MODE: - case OID_SKGE_PHY_OPERATION_STATUS: - case OID_SKGE_SPEED_CAP: - case OID_SKGE_SPEED_MODE: - case OID_SKGE_SPEED_STATUS: - if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U8)) { - - *pLen = (Limit - LogPortIndex) * sizeof(SK_U8); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_MTU: - case OID_SKGE_PHY_TYPE: - if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U32)) { - - *pLen = (Limit - LogPortIndex) * sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR041, - SK_PNMI_ERR041MSG); - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * Update statistic and increment semaphore to indicate - * that an update was already done. - */ - if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) { - - *pLen = 0; - return (Ret); - } - pAC->Pnmi.SirqUpdatedFlag ++; - - /* - * Get value - */ - Offset = 0; - for (; LogPortIndex < Limit; LogPortIndex ++) { - - pBufPtr = pBuf + Offset; - - switch (Id) { - - case OID_SKGE_PMD: - *pBufPtr = pAC->Pnmi.PMD; - Offset += sizeof(char); - break; - - case OID_SKGE_CONNECTOR: - *pBufPtr = pAC->Pnmi.Connector; - Offset += sizeof(char); - break; - - case OID_SKGE_PHY_TYPE: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - continue; - } - else { - /* Get value for physical ports */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - Val32 = pAC->GIni.GP[PhysPortIndex].PhyType; - SK_PNMI_STORE_U32(pBufPtr, Val32); - } - } - else { /* DualNetMode */ - - Val32 = pAC->GIni.GP[NetIndex].PhyType; - SK_PNMI_STORE_U32(pBufPtr, Val32); - } - Offset += sizeof(SK_U32); - break; - - case OID_SKGE_LINK_CAP: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical ports */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkCap; - } - } - else { /* DualNetMode */ - - *pBufPtr = pAC->GIni.GP[NetIndex].PLinkCap; - } - Offset += sizeof(char); - break; - - case OID_SKGE_LINK_MODE: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical ports */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkModeConf; - } - } - else { /* DualNetMode */ - - *pBufPtr = pAC->GIni.GP[NetIndex].PLinkModeConf; - } - Offset += sizeof(char); - break; - - case OID_SKGE_LINK_MODE_STATUS: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = - CalculateLinkModeStatus(pAC, IoC, PhysPortIndex); - } - } - else { /* DualNetMode */ - - *pBufPtr = CalculateLinkModeStatus(pAC, IoC, NetIndex); - } - Offset += sizeof(char); - break; - - case OID_SKGE_LINK_STATUS: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical ports */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = CalculateLinkStatus(pAC, IoC, PhysPortIndex); - } - } - else { /* DualNetMode */ - - *pBufPtr = CalculateLinkStatus(pAC, IoC, NetIndex); - } - Offset += sizeof(char); - break; - - case OID_SKGE_FLOWCTRL_CAP: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical ports */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap; - } - } - else { /* DualNetMode */ - - *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlCap; - } - Offset += sizeof(char); - break; - - case OID_SKGE_FLOWCTRL_MODE: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlMode; - } - } - else { /* DualNetMode */ - - *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlMode; - } - Offset += sizeof(char); - break; - - case OID_SKGE_FLOWCTRL_STATUS: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlStatus; - } - } - else { /* DualNetMode */ - - *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlStatus; - } - Offset += sizeof(char); - break; - - case OID_SKGE_PHY_OPERATION_CAP: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical ports */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSCap; - } - } - else { /* DualNetMode */ - - *pBufPtr = pAC->GIni.GP[NetIndex].PMSCap; - } - Offset += sizeof(char); - break; - - case OID_SKGE_PHY_OPERATION_MODE: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSMode; - } - } - else { /* DualNetMode */ - - *pBufPtr = pAC->GIni.GP[NetIndex].PMSMode; - } - Offset += sizeof(char); - break; - - case OID_SKGE_PHY_OPERATION_STATUS: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSStatus; - } - } - else { - - *pBufPtr = pAC->GIni.GP[NetIndex].PMSStatus; - } - Offset += sizeof(char); - break; - - case OID_SKGE_SPEED_CAP: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical ports */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedCap; - } - } - else { /* DualNetMode */ - - *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedCap; - } - Offset += sizeof(char); - break; - - case OID_SKGE_SPEED_MODE: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeed; - } - } - else { /* DualNetMode */ - - *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeed; - } - Offset += sizeof(char); - break; - - case OID_SKGE_SPEED_STATUS: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed; - } - } - else { /* DualNetMode */ - - *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedUsed; - } - Offset += sizeof(char); - break; - - case OID_SKGE_MTU: - Val32 = SK_DRIVER_GET_MTU(pAC, IoC, NetIndex); - SK_PNMI_STORE_U32(pBufPtr, Val32); - Offset += sizeof(SK_U32); - break; - - default: - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, - ("MacPrivateConf: Unknown OID should be handled before")); - - pAC->Pnmi.SirqUpdatedFlag --; - return (SK_PNMI_ERR_GENERAL); - } - } - *pLen = Offset; - pAC->Pnmi.SirqUpdatedFlag --; - - return (SK_PNMI_ERR_OK); - } - - /* - * From here SET or PRESET action. Check if the passed - * buffer length is plausible. - */ - switch (Id) { - - case OID_SKGE_LINK_MODE: - case OID_SKGE_FLOWCTRL_MODE: - case OID_SKGE_PHY_OPERATION_MODE: - case OID_SKGE_SPEED_MODE: - if (*pLen < Limit - LogPortIndex) { - - *pLen = Limit - LogPortIndex; - return (SK_PNMI_ERR_TOO_SHORT); - } - if (*pLen != Limit - LogPortIndex) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - break; - - case OID_SKGE_MTU: - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - if (*pLen != sizeof(SK_U32)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - break; - - default: - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* - * Perform preset or set - */ - Offset = 0; - for (; LogPortIndex < Limit; LogPortIndex ++) { - - switch (Id) { - - case OID_SKGE_LINK_MODE: - /* Check the value range */ - Val8 = *(pBuf + Offset); - if (Val8 == 0) { - - Offset += sizeof(char); - break; - } - if (Val8 < SK_LMODE_HALF || - (LogPortIndex != 0 && Val8 > SK_LMODE_AUTOSENSE) || - (LogPortIndex == 0 && Val8 > SK_LMODE_INDETERMINATED)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* The preset ends here */ - if (Action == SK_PNMI_PRESET) { - - return (SK_PNMI_ERR_OK); - } - - if (LogPortIndex == 0) { - - /* - * The virtual port consists of all currently - * active ports. Find them and send an event - * with the new link mode to SIRQ. - */ - for (PhysPortIndex = 0; - PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { - - if (!pAC->Pnmi.Port[PhysPortIndex]. - ActiveFlag) { - - continue; - } - - EventParam.Para32[0] = PhysPortIndex; - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_LMODE, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR043, - SK_PNMI_ERR043MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - } - else { - /* - * Send an event with the new link mode to - * the SIRQ module. - */ - EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR043, - SK_PNMI_ERR043MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - Offset += sizeof(char); - break; - - case OID_SKGE_FLOWCTRL_MODE: - /* Check the value range */ - Val8 = *(pBuf + Offset); - if (Val8 == 0) { - - Offset += sizeof(char); - break; - } - if (Val8 < SK_FLOW_MODE_NONE || - (LogPortIndex != 0 && Val8 > SK_FLOW_MODE_SYM_OR_REM) || - (LogPortIndex == 0 && Val8 > SK_FLOW_MODE_INDETERMINATED)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* The preset ends here */ - if (Action == SK_PNMI_PRESET) { - - return (SK_PNMI_ERR_OK); - } - - if (LogPortIndex == 0) { - - /* - * The virtual port consists of all currently - * active ports. Find them and send an event - * with the new flow control mode to SIRQ. - */ - for (PhysPortIndex = 0; - PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { - - if (!pAC->Pnmi.Port[PhysPortIndex]. - ActiveFlag) { - - continue; - } - - EventParam.Para32[0] = PhysPortIndex; - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_FLOWMODE, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR044, - SK_PNMI_ERR044MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - } - else { - /* - * Send an event with the new flow control - * mode to the SIRQ module. - */ - EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_FLOWMODE, EventParam) - > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR044, - SK_PNMI_ERR044MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - Offset += sizeof(char); - break; - - case OID_SKGE_PHY_OPERATION_MODE : - /* Check the value range */ - Val8 = *(pBuf + Offset); - if (Val8 == 0) { - /* mode of this port remains unchanged */ - Offset += sizeof(char); - break; - } - if (Val8 < SK_MS_MODE_AUTO || - (LogPortIndex != 0 && Val8 > SK_MS_MODE_SLAVE) || - (LogPortIndex == 0 && Val8 > SK_MS_MODE_INDETERMINATED)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* The preset ends here */ - if (Action == SK_PNMI_PRESET) { - - return (SK_PNMI_ERR_OK); - } - - if (LogPortIndex == 0) { - - /* - * The virtual port consists of all currently - * active ports. Find them and send an event - * with new master/slave (role) mode to SIRQ. - */ - for (PhysPortIndex = 0; - PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { - - if (!pAC->Pnmi.Port[PhysPortIndex]. - ActiveFlag) { - - continue; - } - - EventParam.Para32[0] = PhysPortIndex; - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_ROLE, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR042, - SK_PNMI_ERR042MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - } - else { - /* - * Send an event with the new master/slave - * (role) mode to the SIRQ module. - */ - EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_ROLE, EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR042, - SK_PNMI_ERR042MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - - Offset += sizeof(char); - break; - - case OID_SKGE_SPEED_MODE: - /* Check the value range */ - Val8 = *(pBuf + Offset); - if (Val8 == 0) { - - Offset += sizeof(char); - break; - } - if (Val8 < (SK_LSPEED_AUTO) || - (LogPortIndex != 0 && Val8 > (SK_LSPEED_1000MBPS)) || - (LogPortIndex == 0 && Val8 > (SK_LSPEED_INDETERMINATED))) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* The preset ends here */ - if (Action == SK_PNMI_PRESET) { - - return (SK_PNMI_ERR_OK); - } - - if (LogPortIndex == 0) { - - /* - * The virtual port consists of all currently - * active ports. Find them and send an event - * with the new flow control mode to SIRQ. - */ - for (PhysPortIndex = 0; - PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { - - if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { - - continue; - } - - EventParam.Para32[0] = PhysPortIndex; - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_SPEED, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR045, - SK_PNMI_ERR045MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - } - else { - /* - * Send an event with the new flow control - * mode to the SIRQ module. - */ - EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_SPEED, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR045, - SK_PNMI_ERR045MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - Offset += sizeof(char); - break; - - case OID_SKGE_MTU : - /* Check the value range */ - Val32 = *(SK_U32*)(pBuf + Offset); - if (Val32 == 0) { - /* mtu of this port remains unchanged */ - Offset += sizeof(SK_U32); - break; - } - if (SK_DRIVER_PRESET_MTU(pAC, IoC, NetIndex, Val32) != 0) { - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* The preset ends here */ - if (Action == SK_PNMI_PRESET) { - return (SK_PNMI_ERR_OK); - } - - if (SK_DRIVER_SET_MTU(pAC, IoC, NetIndex, Val32) != 0) { - return (SK_PNMI_ERR_GENERAL); - } - - Offset += sizeof(SK_U32); - break; - - default: - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, - ("MacPrivateConf: Unknown OID should be handled before set")); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * Monitor - OID handler function for RLMT_MONITOR_XXX - * - * Description: - * Because RLMT currently does not support the monitoring of - * remote adapter cards, we return always an empty table. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int Monitor( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - unsigned int Index; - unsigned int Limit; - unsigned int Offset; - unsigned int Entries; - - - /* - * Calculate instance if wished. - */ - /* XXX Not yet implemented. Return always an empty table. */ - Entries = 0; - - if ((Instance != (SK_U32)(-1))) { - - if ((Instance < 1) || (Instance > Entries)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - Index = (unsigned int)Instance - 1; - Limit = (unsigned int)Instance; - } - else { - Index = 0; - Limit = Entries; - } - - /* - * Get/Set value - */ - if (Action == SK_PNMI_GET) { - - for (Offset=0; Index < Limit; Index ++) { - - switch (Id) { - - case OID_SKGE_RLMT_MONITOR_INDEX: - case OID_SKGE_RLMT_MONITOR_ADDR: - case OID_SKGE_RLMT_MONITOR_ERRS: - case OID_SKGE_RLMT_MONITOR_TIMESTAMP: - case OID_SKGE_RLMT_MONITOR_ADMIN: - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR046, - SK_PNMI_ERR046MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - *pLen = Offset; - } - else { - /* Only MONITOR_ADMIN can be set */ - if (Id != OID_SKGE_RLMT_MONITOR_ADMIN) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* Check if the length is plausible */ - if (*pLen < (Limit - Index)) { - - return (SK_PNMI_ERR_TOO_SHORT); - } - /* Okay, we have a wide value range */ - if (*pLen != (Limit - Index)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } -/* - for (Offset=0; Index < Limit; Index ++) { - } -*/ -/* - * XXX Not yet implemented. Return always BAD_VALUE, because the table - * is empty. - */ - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * VirtualConf - Calculates the values of configuration OIDs for virtual port - * - * Description: - * We handle here the get of the configuration group OIDs, which are - * a little bit complicated. The virtual port consists of all currently - * active physical ports. If multiple ports are active and configured - * differently we get in some trouble to return a single value. So we - * get the value of the first active port and compare it with that of - * the other active ports. If they are not the same, we return a value - * that indicates that the state is indeterminated. - * - * Returns: - * Nothing - */ -PNMI_STATIC void VirtualConf( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf) /* Buffer used for the management data transfer */ -{ - unsigned int PhysPortMax; - unsigned int PhysPortIndex; - SK_U8 Val8; - SK_U32 Val32; - SK_BOOL PortActiveFlag; - SK_GEPORT *pPrt; - - *pBuf = 0; - PortActiveFlag = SK_FALSE; - PhysPortMax = pAC->GIni.GIMacsFound; - - for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { - - pPrt = &pAC->GIni.GP[PhysPortIndex]; - - /* Check if the physical port is active */ - if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { - - continue; - } - - PortActiveFlag = SK_TRUE; - - switch (Id) { - - case OID_SKGE_PHY_TYPE: - /* Check if it is the first active port */ - if (*pBuf == 0) { - Val32 = pPrt->PhyType; - SK_PNMI_STORE_U32(pBuf, Val32); - continue; - } - - case OID_SKGE_LINK_CAP: - - /* - * Different capabilities should not happen, but - * in the case of the cases OR them all together. - * From a curious point of view the virtual port - * is capable of all found capabilities. - */ - *pBuf |= pPrt->PLinkCap; - break; - - case OID_SKGE_LINK_MODE: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pPrt->PLinkModeConf; - continue; - } - - /* - * If we find an active port with a different link - * mode than the first one we return a value that - * indicates that the link mode is indeterminated. - */ - if (*pBuf != pPrt->PLinkModeConf) { - - *pBuf = SK_LMODE_INDETERMINATED; - } - break; - - case OID_SKGE_LINK_MODE_STATUS: - /* Get the link mode of the physical port */ - Val8 = CalculateLinkModeStatus(pAC, IoC, PhysPortIndex); - - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = Val8; - continue; - } - - /* - * If we find an active port with a different link - * mode status than the first one we return a value - * that indicates that the link mode status is - * indeterminated. - */ - if (*pBuf != Val8) { - - *pBuf = SK_LMODE_STAT_INDETERMINATED; - } - break; - - case OID_SKGE_LINK_STATUS: - /* Get the link status of the physical port */ - Val8 = CalculateLinkStatus(pAC, IoC, PhysPortIndex); - - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = Val8; - continue; - } - - /* - * If we find an active port with a different link - * status than the first one, we return a value - * that indicates that the link status is - * indeterminated. - */ - if (*pBuf != Val8) { - - *pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED; - } - break; - - case OID_SKGE_FLOWCTRL_CAP: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pPrt->PFlowCtrlCap; - continue; - } - - /* - * From a curious point of view the virtual port - * is capable of all found capabilities. - */ - *pBuf |= pPrt->PFlowCtrlCap; - break; - - case OID_SKGE_FLOWCTRL_MODE: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pPrt->PFlowCtrlMode; - continue; - } - - /* - * If we find an active port with a different flow - * control mode than the first one, we return a value - * that indicates that the mode is indeterminated. - */ - if (*pBuf != pPrt->PFlowCtrlMode) { - - *pBuf = SK_FLOW_MODE_INDETERMINATED; - } - break; - - case OID_SKGE_FLOWCTRL_STATUS: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pPrt->PFlowCtrlStatus; - continue; - } - - /* - * If we find an active port with a different flow - * control status than the first one, we return a - * value that indicates that the status is - * indeterminated. - */ - if (*pBuf != pPrt->PFlowCtrlStatus) { - - *pBuf = SK_FLOW_STAT_INDETERMINATED; - } - break; - - case OID_SKGE_PHY_OPERATION_CAP: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pPrt->PMSCap; - continue; - } - - /* - * From a curious point of view the virtual port - * is capable of all found capabilities. - */ - *pBuf |= pPrt->PMSCap; - break; - - case OID_SKGE_PHY_OPERATION_MODE: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pPrt->PMSMode; - continue; - } - - /* - * If we find an active port with a different master/ - * slave mode than the first one, we return a value - * that indicates that the mode is indeterminated. - */ - if (*pBuf != pPrt->PMSMode) { - - *pBuf = SK_MS_MODE_INDETERMINATED; - } - break; - - case OID_SKGE_PHY_OPERATION_STATUS: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pPrt->PMSStatus; - continue; - } - - /* - * If we find an active port with a different master/ - * slave status than the first one, we return a - * value that indicates that the status is - * indeterminated. - */ - if (*pBuf != pPrt->PMSStatus) { - - *pBuf = SK_MS_STAT_INDETERMINATED; - } - break; - - case OID_SKGE_SPEED_MODE: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pPrt->PLinkSpeed; - continue; - } - - /* - * If we find an active port with a different flow - * control mode than the first one, we return a value - * that indicates that the mode is indeterminated. - */ - if (*pBuf != pPrt->PLinkSpeed) { - - *pBuf = SK_LSPEED_INDETERMINATED; - } - break; - - case OID_SKGE_SPEED_STATUS: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pPrt->PLinkSpeedUsed; - continue; - } - - /* - * If we find an active port with a different flow - * control status than the first one, we return a - * value that indicates that the status is - * indeterminated. - */ - if (*pBuf != pPrt->PLinkSpeedUsed) { - - *pBuf = SK_LSPEED_STAT_INDETERMINATED; - } - break; - } - } - - /* - * If no port is active return an indeterminated answer - */ - if (!PortActiveFlag) { - - switch (Id) { - - case OID_SKGE_LINK_CAP: - *pBuf = SK_LMODE_CAP_INDETERMINATED; - break; - - case OID_SKGE_LINK_MODE: - *pBuf = SK_LMODE_INDETERMINATED; - break; - - case OID_SKGE_LINK_MODE_STATUS: - *pBuf = SK_LMODE_STAT_INDETERMINATED; - break; - - case OID_SKGE_LINK_STATUS: - *pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED; - break; - - case OID_SKGE_FLOWCTRL_CAP: - case OID_SKGE_FLOWCTRL_MODE: - *pBuf = SK_FLOW_MODE_INDETERMINATED; - break; - - case OID_SKGE_FLOWCTRL_STATUS: - *pBuf = SK_FLOW_STAT_INDETERMINATED; - break; - - case OID_SKGE_PHY_OPERATION_CAP: - *pBuf = SK_MS_CAP_INDETERMINATED; - break; - - case OID_SKGE_PHY_OPERATION_MODE: - *pBuf = SK_MS_MODE_INDETERMINATED; - break; - - case OID_SKGE_PHY_OPERATION_STATUS: - *pBuf = SK_MS_STAT_INDETERMINATED; - break; - case OID_SKGE_SPEED_CAP: - *pBuf = SK_LSPEED_CAP_INDETERMINATED; - break; - - case OID_SKGE_SPEED_MODE: - *pBuf = SK_LSPEED_INDETERMINATED; - break; - - case OID_SKGE_SPEED_STATUS: - *pBuf = SK_LSPEED_STAT_INDETERMINATED; - break; - } - } -} - -/***************************************************************************** - * - * CalculateLinkStatus - Determins the link status of a physical port - * - * Description: - * Determins the link status the following way: - * LSTAT_PHY_DOWN: Link is down - * LSTAT_AUTONEG: Auto-negotiation failed - * LSTAT_LOG_DOWN: Link is up but RLMT did not yet put the port - * logically up. - * LSTAT_LOG_UP: RLMT marked the port as up - * - * Returns: - * Link status of physical port - */ -PNMI_STATIC SK_U8 CalculateLinkStatus( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -unsigned int PhysPortIndex) /* Physical port index */ -{ - SK_U8 Result; - - if (!pAC->GIni.GP[PhysPortIndex].PHWLinkUp) { - - Result = SK_PNMI_RLMT_LSTAT_PHY_DOWN; - } - else if (pAC->GIni.GP[PhysPortIndex].PAutoNegFail > 0) { - - Result = SK_PNMI_RLMT_LSTAT_AUTONEG; - } - else if (!pAC->Rlmt.Port[PhysPortIndex].PortDown) { - - Result = SK_PNMI_RLMT_LSTAT_LOG_UP; - } - else { - Result = SK_PNMI_RLMT_LSTAT_LOG_DOWN; - } - - return (Result); -} - -/***************************************************************************** - * - * CalculateLinkModeStatus - Determins the link mode status of a phys. port - * - * Description: - * The COMMON module only tells us if the mode is half or full duplex. - * But in the decade of auto sensing it is useful for the user to - * know if the mode was negotiated or forced. Therefore we have a - * look to the mode, which was last used by the negotiation process. - * - * Returns: - * The link mode status - */ -PNMI_STATIC SK_U8 CalculateLinkModeStatus( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -unsigned int PhysPortIndex) /* Physical port index */ -{ - SK_U8 Result; - - /* Get the current mode, which can be full or half duplex */ - Result = pAC->GIni.GP[PhysPortIndex].PLinkModeStatus; - - /* Check if no valid mode could be found (link is down) */ - if (Result < SK_LMODE_STAT_HALF) { - - Result = SK_LMODE_STAT_UNKNOWN; - } - else if (pAC->GIni.GP[PhysPortIndex].PLinkMode >= SK_LMODE_AUTOHALF) { - - /* - * Auto-negotiation was used to bring up the link. Change - * the already found duplex status that it indicates - * auto-negotiation was involved. - */ - if (Result == SK_LMODE_STAT_HALF) { - - Result = SK_LMODE_STAT_AUTOHALF; - } - else if (Result == SK_LMODE_STAT_FULL) { - - Result = SK_LMODE_STAT_AUTOFULL; - } - } - - return (Result); -} - -/***************************************************************************** - * - * GetVpdKeyArr - Obtain an array of VPD keys - * - * Description: - * Read the VPD keys and build an array of VPD keys, which are - * easy to access. - * - * Returns: - * SK_PNMI_ERR_OK Task successfully performed. - * SK_PNMI_ERR_GENERAL Something went wrong. - */ -PNMI_STATIC int GetVpdKeyArr( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -char *pKeyArr, /* Ptr KeyArray */ -unsigned int KeyArrLen, /* Length of array in bytes */ -unsigned int *pKeyNo) /* Number of keys */ -{ - unsigned int BufKeysLen = SK_PNMI_VPD_BUFSIZE; - char BufKeys[SK_PNMI_VPD_BUFSIZE]; - unsigned int StartOffset; - unsigned int Offset; - int Index; - int Ret; - - - SK_MEMSET(pKeyArr, 0, KeyArrLen); - - /* - * Get VPD key list - */ - Ret = VpdKeys(pAC, IoC, (char *)&BufKeys, (int *)&BufKeysLen, - (int *)pKeyNo); - if (Ret > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR014, - SK_PNMI_ERR014MSG); - - return (SK_PNMI_ERR_GENERAL); - } - /* If no keys are available return now */ - if (*pKeyNo == 0 || BufKeysLen == 0) { - - return (SK_PNMI_ERR_OK); - } - /* - * If the key list is too long for us trunc it and give a - * errorlog notification. This case should not happen because - * the maximum number of keys is limited due to RAM limitations - */ - if (*pKeyNo > SK_PNMI_VPD_ENTRIES) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR015, - SK_PNMI_ERR015MSG); - - *pKeyNo = SK_PNMI_VPD_ENTRIES; - } - - /* - * Now build an array of fixed string length size and copy - * the keys together. - */ - for (Index = 0, StartOffset = 0, Offset = 0; Offset < BufKeysLen; - Offset ++) { - - if (BufKeys[Offset] != 0) { - - continue; - } - - if (Offset - StartOffset > SK_PNMI_VPD_KEY_SIZE) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR016, - SK_PNMI_ERR016MSG); - return (SK_PNMI_ERR_GENERAL); - } - - SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE, - &BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE); - - Index ++; - StartOffset = Offset + 1; - } - - /* Last key not zero terminated? Get it anyway */ - if (StartOffset < Offset) { - - SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE, - &BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE); - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * SirqUpdate - Let the SIRQ update its internal values - * - * Description: - * Just to be sure that the SIRQ module holds its internal data - * structures up to date, we send an update event before we make - * any access. - * - * Returns: - * SK_PNMI_ERR_OK Task successfully performed. - * SK_PNMI_ERR_GENERAL Something went wrong. - */ -PNMI_STATIC int SirqUpdate( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC) /* IO context handle */ -{ - SK_EVPARA EventParam; - - - /* Was the module already updated during the current PNMI call? */ - if (pAC->Pnmi.SirqUpdatedFlag > 0) { - - return (SK_PNMI_ERR_OK); - } - - /* Send an synchronuous update event to the module */ - SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); - if (SkGeSirqEvent(pAC, IoC, SK_HWEV_UPDATE_STAT, EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR047, - SK_PNMI_ERR047MSG); - - return (SK_PNMI_ERR_GENERAL); - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * RlmtUpdate - Let the RLMT update its internal values - * - * Description: - * Just to be sure that the RLMT module holds its internal data - * structures up to date, we send an update event before we make - * any access. - * - * Returns: - * SK_PNMI_ERR_OK Task successfully performed. - * SK_PNMI_ERR_GENERAL Something went wrong. - */ -PNMI_STATIC int RlmtUpdate( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - SK_EVPARA EventParam; - - - /* Was the module already updated during the current PNMI call? */ - if (pAC->Pnmi.RlmtUpdatedFlag > 0) { - - return (SK_PNMI_ERR_OK); - } - - /* Send an synchronuous update event to the module */ - SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); - EventParam.Para32[0] = NetIndex; - EventParam.Para32[1] = (SK_U32)-1; - if (SkRlmtEvent(pAC, IoC, SK_RLMT_STATS_UPDATE, EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR048, - SK_PNMI_ERR048MSG); - - return (SK_PNMI_ERR_GENERAL); - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * MacUpdate - Force the XMAC to output the current statistic - * - * Description: - * The XMAC holds its statistic internally. To obtain the current - * values we must send a command so that the statistic data will - * be written to a predefined memory area on the adapter. - * - * Returns: - * SK_PNMI_ERR_OK Task successfully performed. - * SK_PNMI_ERR_GENERAL Something went wrong. - */ -PNMI_STATIC int MacUpdate( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -unsigned int FirstMac, /* Index of the first Mac to be updated */ -unsigned int LastMac) /* Index of the last Mac to be updated */ -{ - unsigned int MacIndex; - - /* - * Were the statistics already updated during the - * current PNMI call? - */ - if (pAC->Pnmi.MacUpdatedFlag > 0) { - - return (SK_PNMI_ERR_OK); - } - - /* Send an update command to all MACs specified */ - for (MacIndex = FirstMac; MacIndex <= LastMac; MacIndex ++) { - - /* - * 2002-09-13 pweber: Freeze the current SW counters. - * (That should be done as close as - * possible to the update of the - * HW counters) - */ - if (pAC->GIni.GIMacType == SK_MAC_XMAC) { - pAC->Pnmi.BufPort[MacIndex] = pAC->Pnmi.Port[MacIndex]; - } - - /* 2002-09-13 pweber: Update the HW counter */ - if (pAC->GIni.GIFunc.pFnMacUpdateStats(pAC, IoC, MacIndex) != 0) { - - return (SK_PNMI_ERR_GENERAL); - } - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * GetStatVal - Retrieve an XMAC statistic counter - * - * Description: - * Retrieves the statistic counter of a virtual or physical port. The - * virtual port is identified by the index 0. It consists of all - * currently active ports. To obtain the counter value for this port - * we must add the statistic counter of all active ports. To grant - * continuous counter values for the virtual port even when port - * switches occur we must additionally add a delta value, which was - * calculated during a SK_PNMI_EVT_RLMT_ACTIVE_UP event. - * - * Returns: - * Requested statistic value - */ -PNMI_STATIC SK_U64 GetStatVal( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -unsigned int LogPortIndex, /* Index of the logical Port to be processed */ -unsigned int StatIndex, /* Index to statistic value */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - unsigned int PhysPortIndex; - unsigned int PhysPortMax; - SK_U64 Val = 0; - - - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */ - - PhysPortIndex = NetIndex; - - Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex); - } - else { /* Single Net mode */ - - if (LogPortIndex == 0) { - - PhysPortMax = pAC->GIni.GIMacsFound; - - /* Add counter of all active ports */ - for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { - - if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { - - Val += GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex); - } - } - - /* Correct value because of port switches */ - Val += pAC->Pnmi.VirtualCounterOffset[StatIndex]; - } - else { - /* Get counter value of physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); - - Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex); - } - } - return (Val); -} - -/***************************************************************************** - * - * GetPhysStatVal - Get counter value for physical port - * - * Description: - * Builds a 64bit counter value. Except for the octet counters - * the lower 32bit are counted in hardware and the upper 32bit - * in software by monitoring counter overflow interrupts in the - * event handler. To grant continous counter values during XMAC - * resets (caused by a workaround) we must add a delta value. - * The delta was calculated in the event handler when a - * SK_PNMI_EVT_XMAC_RESET was received. - * - * Returns: - * Counter value - */ -PNMI_STATIC SK_U64 GetPhysStatVal( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -unsigned int PhysPortIndex, /* Index of the logical Port to be processed */ -unsigned int StatIndex) /* Index to statistic value */ -{ - SK_U64 Val = 0; - SK_U32 LowVal = 0; - SK_U32 HighVal = 0; - SK_U16 Word; - int MacType; - unsigned int HelpIndex; - SK_GEPORT *pPrt; - - SK_PNMI_PORT *pPnmiPrt; - SK_GEMACFUNC *pFnMac; - - pPrt = &pAC->GIni.GP[PhysPortIndex]; - - MacType = pAC->GIni.GIMacType; - - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - pPnmiPrt = &pAC->Pnmi.BufPort[PhysPortIndex]; - } - else { - pPnmiPrt = &pAC->Pnmi.Port[PhysPortIndex]; - } - - pFnMac = &pAC->GIni.GIFunc; - - switch (StatIndex) { - case SK_PNMI_HTX: - if (MacType == SK_MAC_GMAC) { - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[SK_PNMI_HTX_BROADCAST][MacType].Reg, - &LowVal); - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[SK_PNMI_HTX_MULTICAST][MacType].Reg, - &HighVal); - LowVal += HighVal; - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[SK_PNMI_HTX_UNICAST][MacType].Reg, - &HighVal); - LowVal += HighVal; - } - else { - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - } - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - - case SK_PNMI_HRX: - if (MacType == SK_MAC_GMAC) { - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[SK_PNMI_HRX_BROADCAST][MacType].Reg, - &LowVal); - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[SK_PNMI_HRX_MULTICAST][MacType].Reg, - &HighVal); - LowVal += HighVal; - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[SK_PNMI_HRX_UNICAST][MacType].Reg, - &HighVal); - LowVal += HighVal; - } - else { - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - } - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - - case SK_PNMI_HTX_OCTET: - case SK_PNMI_HRX_OCTET: - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &HighVal); - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex + 1][MacType].Reg, - &LowVal); - break; - - case SK_PNMI_HTX_BURST: - case SK_PNMI_HTX_EXCESS_DEF: - case SK_PNMI_HTX_CARRIER: - /* Not supported by GMAC */ - if (MacType == SK_MAC_GMAC) { - return (Val); - } - - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - - case SK_PNMI_HTX_MACC: - /* GMAC only supports PAUSE MAC control frames */ - if (MacType == SK_MAC_GMAC) { - HelpIndex = SK_PNMI_HTX_PMACC; - } - else { - HelpIndex = StatIndex; - } - - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[HelpIndex][MacType].Reg, - &LowVal); - - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - - case SK_PNMI_HTX_COL: - case SK_PNMI_HRX_UNDERSIZE: - /* Not supported by XMAC */ - if (MacType == SK_MAC_XMAC) { - return (Val); - } - - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - - case SK_PNMI_HTX_DEFFERAL: - /* Not supported by GMAC */ - if (MacType == SK_MAC_GMAC) { - return (Val); - } - - /* - * XMAC counts frames with deferred transmission - * even in full-duplex mode. - * - * In full-duplex mode the counter remains constant! - */ - if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) || - (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL)) { - - LowVal = 0; - HighVal = 0; - } - else { - /* Otherwise get contents of hardware register */ - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - } - break; - - case SK_PNMI_HRX_BADOCTET: - /* Not supported by XMAC */ - if (MacType == SK_MAC_XMAC) { - return (Val); - } - - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &HighVal); - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex + 1][MacType].Reg, - &LowVal); - break; - - case SK_PNMI_HTX_OCTETLOW: - case SK_PNMI_HRX_OCTETLOW: - case SK_PNMI_HRX_BADOCTETLOW: - return (Val); - - case SK_PNMI_HRX_LONGFRAMES: - /* For XMAC the SW counter is managed by PNMI */ - if (MacType == SK_MAC_XMAC) { - return (pPnmiPrt->StatRxLongFrameCts); - } - - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - - case SK_PNMI_HRX_TOO_LONG: - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - - Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal); - - if (MacType == SK_MAC_GMAC) { - /* For GMAC the SW counter is additionally managed by PNMI */ - Val += pPnmiPrt->StatRxFrameTooLongCts; - } - else { - /* - * Frames longer than IEEE 802.3 frame max size are counted - * by XMAC in frame_too_long counter even reception of long - * frames was enabled and the frame was correct. - * So correct the value by subtracting RxLongFrame counter. - */ - Val -= pPnmiPrt->StatRxLongFrameCts; - } - - LowVal = (SK_U32)Val; - HighVal = (SK_U32)(Val >> 32); - break; - - case SK_PNMI_HRX_SHORTS: - /* Not supported by GMAC */ - if (MacType == SK_MAC_GMAC) { - /* GM_RXE_FRAG?? */ - return (Val); - } - - /* - * XMAC counts short frame errors even if link down (#10620) - * - * If link-down the counter remains constant - */ - if (pPrt->PLinkModeStatus != SK_LMODE_STAT_UNKNOWN) { - - /* Otherwise get incremental difference */ - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - - Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal); - Val -= pPnmiPrt->RxShortZeroMark; - - LowVal = (SK_U32)Val; - HighVal = (SK_U32)(Val >> 32); - } - break; - - case SK_PNMI_HRX_MACC: - case SK_PNMI_HRX_MACC_UNKWN: - case SK_PNMI_HRX_BURST: - case SK_PNMI_HRX_MISSED: - case SK_PNMI_HRX_FRAMING: - case SK_PNMI_HRX_CARRIER: - case SK_PNMI_HRX_IRLENGTH: - case SK_PNMI_HRX_SYMBOL: - case SK_PNMI_HRX_CEXT: - /* Not supported by GMAC */ - if (MacType == SK_MAC_GMAC) { - return (Val); - } - - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - - case SK_PNMI_HRX_PMACC_ERR: - /* For GMAC the SW counter is managed by PNMI */ - if (MacType == SK_MAC_GMAC) { - return (pPnmiPrt->StatRxPMaccErr); - } - - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - - /* SW counter managed by PNMI */ - case SK_PNMI_HTX_SYNC: - LowVal = (SK_U32)pPnmiPrt->StatSyncCts; - HighVal = (SK_U32)(pPnmiPrt->StatSyncCts >> 32); - break; - - /* SW counter managed by PNMI */ - case SK_PNMI_HTX_SYNC_OCTET: - LowVal = (SK_U32)pPnmiPrt->StatSyncOctetsCts; - HighVal = (SK_U32)(pPnmiPrt->StatSyncOctetsCts >> 32); - break; - - case SK_PNMI_HRX_FCS: - /* - * Broadcom filters FCS errors and counts it in - * Receive Error Counter register - */ - if (pPrt->PhyType == SK_PHY_BCOM) { - /* do not read while not initialized (PHY_READ hangs!)*/ - if (pPrt->PState != SK_PRT_RESET) { - SkXmPhyRead(pAC, IoC, PhysPortIndex, PHY_BCOM_RE_CTR, &Word); - - LowVal = Word; - } - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - } - else { - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - } - break; - - default: - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - } - - Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal); - - /* Correct value because of possible XMAC reset. XMAC Errata #2 */ - Val += pPnmiPrt->CounterOffset[StatIndex]; - - return (Val); -} - -/***************************************************************************** - * - * ResetCounter - Set all counters and timestamps to zero - * - * Description: - * Notifies other common modules which store statistic data to - * reset their counters and finally reset our own counters. - * - * Returns: - * Nothing - */ -PNMI_STATIC void ResetCounter( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -SK_U32 NetIndex) -{ - unsigned int PhysPortIndex; - SK_EVPARA EventParam; - - - SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); - - /* Notify sensor module */ - SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_CLEAR, EventParam); - - /* Notify RLMT module */ - EventParam.Para32[0] = NetIndex; - EventParam.Para32[1] = (SK_U32)-1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STATS_CLEAR, EventParam); - EventParam.Para32[1] = 0; - - /* Notify SIRQ module */ - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_CLEAR_STAT, EventParam); - - /* Notify CSUM module */ -#ifdef SK_USE_CSUM - EventParam.Para32[0] = NetIndex; - EventParam.Para32[1] = (SK_U32)-1; - SkEventQueue(pAC, SKGE_CSUM, SK_CSUM_EVENT_CLEAR_PROTO_STATS, - EventParam); -#endif /* SK_USE_CSUM */ - - /* Clear XMAC statistic */ - for (PhysPortIndex = 0; PhysPortIndex < - (unsigned int)pAC->GIni.GIMacsFound; PhysPortIndex ++) { - - (void)pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PhysPortIndex); - - SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].CounterHigh, - 0, sizeof(pAC->Pnmi.Port[PhysPortIndex].CounterHigh)); - SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. - CounterOffset, 0, sizeof(pAC->Pnmi.Port[ - PhysPortIndex].CounterOffset)); - SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].StatSyncCts, - 0, sizeof(pAC->Pnmi.Port[PhysPortIndex].StatSyncCts)); - SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. - StatSyncOctetsCts, 0, sizeof(pAC->Pnmi.Port[ - PhysPortIndex].StatSyncOctetsCts)); - SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. - StatRxLongFrameCts, 0, sizeof(pAC->Pnmi.Port[ - PhysPortIndex].StatRxLongFrameCts)); - SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. - StatRxFrameTooLongCts, 0, sizeof(pAC->Pnmi.Port[ - PhysPortIndex].StatRxFrameTooLongCts)); - SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. - StatRxPMaccErr, 0, sizeof(pAC->Pnmi.Port[ - PhysPortIndex].StatRxPMaccErr)); - } - - /* - * Clear local statistics - */ - SK_MEMSET((char *)&pAC->Pnmi.VirtualCounterOffset, 0, - sizeof(pAC->Pnmi.VirtualCounterOffset)); - pAC->Pnmi.RlmtChangeCts = 0; - pAC->Pnmi.RlmtChangeTime = 0; - SK_MEMSET((char *)&pAC->Pnmi.RlmtChangeEstimate.EstValue[0], 0, - sizeof(pAC->Pnmi.RlmtChangeEstimate.EstValue)); - pAC->Pnmi.RlmtChangeEstimate.EstValueIndex = 0; - pAC->Pnmi.RlmtChangeEstimate.Estimate = 0; - pAC->Pnmi.Port[NetIndex].TxSwQueueMax = 0; - pAC->Pnmi.Port[NetIndex].TxRetryCts = 0; - pAC->Pnmi.Port[NetIndex].RxIntrCts = 0; - pAC->Pnmi.Port[NetIndex].TxIntrCts = 0; - pAC->Pnmi.Port[NetIndex].RxNoBufCts = 0; - pAC->Pnmi.Port[NetIndex].TxNoBufCts = 0; - pAC->Pnmi.Port[NetIndex].TxUsedDescrNo = 0; - pAC->Pnmi.Port[NetIndex].RxDeliveredCts = 0; - pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts = 0; - pAC->Pnmi.Port[NetIndex].ErrRecoveryCts = 0; -} - -/***************************************************************************** - * - * GetTrapEntry - Get an entry in the trap buffer - * - * Description: - * The trap buffer stores various events. A user application somehow - * gets notified that an event occured and retrieves the trap buffer - * contens (or simply polls the buffer). The buffer is organized as - * a ring which stores the newest traps at the beginning. The oldest - * traps are overwritten by the newest ones. Each trap entry has a - * unique number, so that applications may detect new trap entries. - * - * Returns: - * A pointer to the trap entry - */ -PNMI_STATIC char* GetTrapEntry( -SK_AC *pAC, /* Pointer to adapter context */ -SK_U32 TrapId, /* SNMP ID of the trap */ -unsigned int Size) /* Space needed for trap entry */ -{ - unsigned int BufPad = pAC->Pnmi.TrapBufPad; - unsigned int BufFree = pAC->Pnmi.TrapBufFree; - unsigned int Beg = pAC->Pnmi.TrapQueueBeg; - unsigned int End = pAC->Pnmi.TrapQueueEnd; - char *pBuf = &pAC->Pnmi.TrapBuf[0]; - int Wrap; - unsigned int NeededSpace; - unsigned int EntrySize; - SK_U32 Val32; - SK_U64 Val64; - - - /* Last byte of entry will get a copy of the entry length */ - Size ++; - - /* - * Calculate needed buffer space */ - if (Beg >= Size) { - - NeededSpace = Size; - Wrap = SK_FALSE; - } - else { - NeededSpace = Beg + Size; - Wrap = SK_TRUE; - } - - /* - * Check if enough buffer space is provided. Otherwise - * free some entries. Leave one byte space between begin - * and end of buffer to make it possible to detect whether - * the buffer is full or empty - */ - while (BufFree < NeededSpace + 1) { - - if (End == 0) { - - End = SK_PNMI_TRAP_QUEUE_LEN; - } - - EntrySize = (unsigned int)*((unsigned char *)pBuf + End - 1); - BufFree += EntrySize; - End -= EntrySize; -#ifdef DEBUG - SK_MEMSET(pBuf + End, (char)(-1), EntrySize); -#endif /* DEBUG */ - if (End == BufPad) { -#ifdef DEBUG - SK_MEMSET(pBuf, (char)(-1), End); -#endif /* DEBUG */ - BufFree += End; - End = 0; - BufPad = 0; - } - } - - /* - * Insert new entry as first entry. Newest entries are - * stored at the beginning of the queue. - */ - if (Wrap) { - - BufPad = Beg; - Beg = SK_PNMI_TRAP_QUEUE_LEN - Size; - } - else { - Beg = Beg - Size; - } - BufFree -= NeededSpace; - - /* Save the current offsets */ - pAC->Pnmi.TrapQueueBeg = Beg; - pAC->Pnmi.TrapQueueEnd = End; - pAC->Pnmi.TrapBufPad = BufPad; - pAC->Pnmi.TrapBufFree = BufFree; - - /* Initialize the trap entry */ - *(pBuf + Beg + Size - 1) = (char)Size; - *(pBuf + Beg) = (char)Size; - Val32 = (pAC->Pnmi.TrapUnique) ++; - SK_PNMI_STORE_U32(pBuf + Beg + 1, Val32); - SK_PNMI_STORE_U32(pBuf + Beg + 1 + sizeof(SK_U32), TrapId); - Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC)); - SK_PNMI_STORE_U64(pBuf + Beg + 1 + 2 * sizeof(SK_U32), Val64); - - return (pBuf + Beg); -} - -/***************************************************************************** - * - * CopyTrapQueue - Copies the trap buffer for the TRAP OID - * - * Description: - * On a query of the TRAP OID the trap buffer contents will be - * copied continuously to the request buffer, which must be large - * enough. No length check is performed. - * - * Returns: - * Nothing - */ -PNMI_STATIC void CopyTrapQueue( -SK_AC *pAC, /* Pointer to adapter context */ -char *pDstBuf) /* Buffer to which the queued traps will be copied */ -{ - unsigned int BufPad = pAC->Pnmi.TrapBufPad; - unsigned int Trap = pAC->Pnmi.TrapQueueBeg; - unsigned int End = pAC->Pnmi.TrapQueueEnd; - char *pBuf = &pAC->Pnmi.TrapBuf[0]; - unsigned int Len; - unsigned int DstOff = 0; - - - while (Trap != End) { - - Len = (unsigned int)*(pBuf + Trap); - - /* - * Last byte containing a copy of the length will - * not be copied. - */ - *(pDstBuf + DstOff) = (char)(Len - 1); - SK_MEMCPY(pDstBuf + DstOff + 1, pBuf + Trap + 1, Len - 2); - DstOff += Len - 1; - - Trap += Len; - if (Trap == SK_PNMI_TRAP_QUEUE_LEN) { - - Trap = BufPad; - } - } -} - -/***************************************************************************** - * - * GetTrapQueueLen - Get the length of the trap buffer - * - * Description: - * Evaluates the number of currently stored traps and the needed - * buffer size to retrieve them. - * - * Returns: - * Nothing - */ -PNMI_STATIC void GetTrapQueueLen( -SK_AC *pAC, /* Pointer to adapter context */ -unsigned int *pLen, /* Length in Bytes of all queued traps */ -unsigned int *pEntries) /* Returns number of trapes stored in queue */ -{ - unsigned int BufPad = pAC->Pnmi.TrapBufPad; - unsigned int Trap = pAC->Pnmi.TrapQueueBeg; - unsigned int End = pAC->Pnmi.TrapQueueEnd; - char *pBuf = &pAC->Pnmi.TrapBuf[0]; - unsigned int Len; - unsigned int Entries = 0; - unsigned int TotalLen = 0; - - - while (Trap != End) { - - Len = (unsigned int)*(pBuf + Trap); - TotalLen += Len - 1; - Entries ++; - - Trap += Len; - if (Trap == SK_PNMI_TRAP_QUEUE_LEN) { - - Trap = BufPad; - } - } - - *pEntries = Entries; - *pLen = TotalLen; -} - -/***************************************************************************** - * - * QueueSimpleTrap - Store a simple trap to the trap buffer - * - * Description: - * A simple trap is a trap with now additional data. It consists - * simply of a trap code. - * - * Returns: - * Nothing - */ -PNMI_STATIC void QueueSimpleTrap( -SK_AC *pAC, /* Pointer to adapter context */ -SK_U32 TrapId) /* Type of sensor trap */ -{ - GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_SIMPLE_LEN); -} - -/***************************************************************************** - * - * QueueSensorTrap - Stores a sensor trap in the trap buffer - * - * Description: - * Gets an entry in the trap buffer and fills it with sensor related - * data. - * - * Returns: - * Nothing - */ -PNMI_STATIC void QueueSensorTrap( -SK_AC *pAC, /* Pointer to adapter context */ -SK_U32 TrapId, /* Type of sensor trap */ -unsigned int SensorIndex) /* Index of sensor which caused the trap */ -{ - char *pBuf; - unsigned int Offset; - unsigned int DescrLen; - SK_U32 Val32; - - - /* Get trap buffer entry */ - DescrLen = SK_STRLEN(pAC->I2c.SenTable[SensorIndex].SenDesc); - pBuf = GetTrapEntry(pAC, TrapId, - SK_PNMI_TRAP_SENSOR_LEN_BASE + DescrLen); - Offset = SK_PNMI_TRAP_SIMPLE_LEN; - - /* Store additionally sensor trap related data */ - Val32 = OID_SKGE_SENSOR_INDEX; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - *(pBuf + Offset + 4) = 4; - Val32 = (SK_U32)SensorIndex; - SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32); - Offset += 9; - - Val32 = (SK_U32)OID_SKGE_SENSOR_DESCR; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - *(pBuf + Offset + 4) = (char)DescrLen; - SK_MEMCPY(pBuf + Offset + 5, pAC->I2c.SenTable[SensorIndex].SenDesc, - DescrLen); - Offset += DescrLen + 5; - - Val32 = OID_SKGE_SENSOR_TYPE; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - *(pBuf + Offset + 4) = 1; - *(pBuf + Offset + 5) = (char)pAC->I2c.SenTable[SensorIndex].SenType; - Offset += 6; - - Val32 = OID_SKGE_SENSOR_VALUE; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - *(pBuf + Offset + 4) = 4; - Val32 = (SK_U32)pAC->I2c.SenTable[SensorIndex].SenValue; - SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32); -} - -/***************************************************************************** - * - * QueueRlmtNewMacTrap - Store a port switch trap in the trap buffer - * - * Description: - * Nothing further to explain. - * - * Returns: - * Nothing - */ -PNMI_STATIC void QueueRlmtNewMacTrap( -SK_AC *pAC, /* Pointer to adapter context */ -unsigned int ActiveMac) /* Index (0..n) of the currently active port */ -{ - char *pBuf; - SK_U32 Val32; - - - pBuf = GetTrapEntry(pAC, OID_SKGE_TRAP_RLMT_CHANGE_PORT, - SK_PNMI_TRAP_RLMT_CHANGE_LEN); - - Val32 = OID_SKGE_RLMT_PORT_ACTIVE; - SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32); - *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1; - *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)ActiveMac; -} - -/***************************************************************************** - * - * QueueRlmtPortTrap - Store port related RLMT trap to trap buffer - * - * Description: - * Nothing further to explain. - * - * Returns: - * Nothing - */ -PNMI_STATIC void QueueRlmtPortTrap( -SK_AC *pAC, /* Pointer to adapter context */ -SK_U32 TrapId, /* Type of RLMT port trap */ -unsigned int PortIndex) /* Index of the port, which changed its state */ -{ - char *pBuf; - SK_U32 Val32; - - - pBuf = GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_RLMT_PORT_LEN); - - Val32 = OID_SKGE_RLMT_PORT_INDEX; - SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32); - *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1; - *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)PortIndex; -} - -/***************************************************************************** - * - * CopyMac - Copies a MAC address - * - * Description: - * Nothing further to explain. - * - * Returns: - * Nothing - */ -PNMI_STATIC void CopyMac( -char *pDst, /* Pointer to destination buffer */ -SK_MAC_ADDR *pMac) /* Pointer of Source */ -{ - int i; - - - for (i = 0; i < sizeof(SK_MAC_ADDR); i ++) { - - *(pDst + i) = pMac->a[i]; - } -} - -#ifdef SK_POWER_MGMT -/***************************************************************************** - * - * PowerManagement - OID handler function of PowerManagement OIDs - * - * Description: - * The code is simple. No description necessary. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ - -PNMI_STATIC int PowerManagement( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - - SK_U32 RetCode = SK_PNMI_ERR_GENERAL; - - /* - * Check instance. We only handle single instance variables - */ - if (Instance != (SK_U32)(-1) && Instance != 1) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - - /* Check length */ - switch (Id) { - - case OID_PNP_CAPABILITIES: - if (*pLen < sizeof(SK_PNP_CAPABILITIES)) { - - *pLen = sizeof(SK_PNP_CAPABILITIES); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_PNP_SET_POWER: - case OID_PNP_QUERY_POWER: - if (*pLen < sizeof(SK_DEVICE_POWER_STATE)) - { - *pLen = sizeof(SK_DEVICE_POWER_STATE); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_PNP_ADD_WAKE_UP_PATTERN: - case OID_PNP_REMOVE_WAKE_UP_PATTERN: - if (*pLen < sizeof(SK_PM_PACKET_PATTERN)) { - - *pLen = sizeof(SK_PM_PACKET_PATTERN); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_PNP_ENABLE_WAKE_UP: - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - } - - /* - * Perform action - */ - if (Action == SK_PNMI_GET) { - - /* - * Get value - */ - switch (Id) { - - case OID_PNP_CAPABILITIES: - RetCode = SkPowerQueryPnPCapabilities(pAC, IoC, pBuf, pLen); - break; - - case OID_PNP_QUERY_POWER: - /* The Windows DDK describes: An OID_PNP_QUERY_POWER requests - the miniport to indicate whether it can transition its NIC - to the low-power state. - A miniport driver must always return NDIS_STATUS_SUCCESS - to a query of OID_PNP_QUERY_POWER. */ - *pLen = sizeof(SK_DEVICE_POWER_STATE); - RetCode = SK_PNMI_ERR_OK; - break; - - /* NDIS handles these OIDs as write-only. - * So in case of get action the buffer with written length = 0 - * is returned - */ - case OID_PNP_SET_POWER: - case OID_PNP_ADD_WAKE_UP_PATTERN: - case OID_PNP_REMOVE_WAKE_UP_PATTERN: - *pLen = 0; - RetCode = SK_PNMI_ERR_NOT_SUPPORTED; - break; - - case OID_PNP_ENABLE_WAKE_UP: - RetCode = SkPowerGetEnableWakeUp(pAC, IoC, pBuf, pLen); - break; - - default: - RetCode = SK_PNMI_ERR_GENERAL; - break; - } - - return (RetCode); - } - - - /* - * Perform preset or set - */ - - /* POWER module does not support PRESET action */ - if (Action == SK_PNMI_PRESET) { - return (SK_PNMI_ERR_OK); - } - - switch (Id) { - case OID_PNP_SET_POWER: - RetCode = SkPowerSetPower(pAC, IoC, pBuf, pLen); - break; - - case OID_PNP_ADD_WAKE_UP_PATTERN: - RetCode = SkPowerAddWakeUpPattern(pAC, IoC, pBuf, pLen); - break; - - case OID_PNP_REMOVE_WAKE_UP_PATTERN: - RetCode = SkPowerRemoveWakeUpPattern(pAC, IoC, pBuf, pLen); - break; - - case OID_PNP_ENABLE_WAKE_UP: - RetCode = SkPowerSetEnableWakeUp(pAC, IoC, pBuf, pLen); - break; - - default: - RetCode = SK_PNMI_ERR_READ_ONLY; - } - - return (RetCode); -} -#endif /* SK_POWER_MGMT */ - -#ifdef SK_DIAG_SUPPORT -/***************************************************************************** - * - * DiagActions - OID handler function of Diagnostic driver - * - * Description: - * The code is simple. No description necessary. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ - -PNMI_STATIC int DiagActions( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - - SK_U32 DiagStatus; - SK_U32 RetCode = SK_PNMI_ERR_GENERAL; - - /* - * Check instance. We only handle single instance variables. - */ - if (Instance != (SK_U32)(-1) && Instance != 1) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - /* - * Check length. - */ - switch (Id) { - - case OID_SKGE_DIAG_MODE: - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR040, SK_PNMI_ERR040MSG); - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* Perform action. */ - - /* GET value. */ - if (Action == SK_PNMI_GET) { - - switch (Id) { - - case OID_SKGE_DIAG_MODE: - DiagStatus = pAC->Pnmi.DiagAttached; - SK_PNMI_STORE_U32(pBuf, DiagStatus); - *pLen = sizeof(SK_U32); - RetCode = SK_PNMI_ERR_OK; - break; - - default: - *pLen = 0; - RetCode = SK_PNMI_ERR_GENERAL; - break; - } - return (RetCode); - } - - /* From here SET or PRESET value. */ - - /* PRESET value is not supported. */ - if (Action == SK_PNMI_PRESET) { - return (SK_PNMI_ERR_OK); - } - - /* SET value. */ - switch (Id) { - case OID_SKGE_DIAG_MODE: - - /* Handle the SET. */ - switch (*pBuf) { - - /* Attach the DIAG to this adapter. */ - case SK_DIAG_ATTACHED: - /* Check if we come from running */ - if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) { - - RetCode = SkDrvLeaveDiagMode(pAC); - - } - else if (pAC->Pnmi.DiagAttached == SK_DIAG_IDLE) { - - RetCode = SK_PNMI_ERR_OK; - } - - else { - - RetCode = SK_PNMI_ERR_GENERAL; - - } - - if (RetCode == SK_PNMI_ERR_OK) { - - pAC->Pnmi.DiagAttached = SK_DIAG_ATTACHED; - } - break; - - /* Enter the DIAG mode in the driver. */ - case SK_DIAG_RUNNING: - RetCode = SK_PNMI_ERR_OK; - - /* - * If DiagAttached is set, we can tell the driver - * to enter the DIAG mode. - */ - if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) { - /* If DiagMode is not active, we can enter it. */ - if (!pAC->DiagModeActive) { - - RetCode = SkDrvEnterDiagMode(pAC); - } - else { - - RetCode = SK_PNMI_ERR_GENERAL; - } - } - else { - - RetCode = SK_PNMI_ERR_GENERAL; - } - - if (RetCode == SK_PNMI_ERR_OK) { - - pAC->Pnmi.DiagAttached = SK_DIAG_RUNNING; - } - break; - - case SK_DIAG_IDLE: - /* Check if we come from running */ - if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) { - - RetCode = SkDrvLeaveDiagMode(pAC); - - } - else if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) { - - RetCode = SK_PNMI_ERR_OK; - } - - else { - - RetCode = SK_PNMI_ERR_GENERAL; - - } - - if (RetCode == SK_PNMI_ERR_OK) { - - pAC->Pnmi.DiagAttached = SK_DIAG_IDLE; - } - break; - - default: - RetCode = SK_PNMI_ERR_BAD_VALUE; - break; - } - break; - - default: - RetCode = SK_PNMI_ERR_GENERAL; - } - - if (RetCode == SK_PNMI_ERR_OK) { - *pLen = sizeof(SK_U32); - } - else { - - *pLen = 0; - } - return (RetCode); -} -#endif /* SK_DIAG_SUPPORT */ - -/***************************************************************************** - * - * Vct - OID handler function of OIDs - * - * Description: - * The code is simple. No description necessary. - * - * Returns: - * SK_PNMI_ERR_OK The request was performed successfully. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter). - * SK_PNMI_ERR_READ_ONLY Only the Get action is allowed. - * - */ - -PNMI_STATIC int Vct( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (-1,2..n) that is to be queried */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - SK_GEPORT *pPrt; - SK_PNMI_VCT *pVctBackupData; - SK_U32 LogPortMax; - SK_U32 PhysPortMax; - SK_U32 PhysPortIndex; - SK_U32 Limit; - SK_U32 Offset; - SK_BOOL Link; - SK_U32 RetCode = SK_PNMI_ERR_GENERAL; - int i; - SK_EVPARA Para; - SK_U32 CableLength; - - /* - * Calculate the port indexes from the instance. - */ - PhysPortMax = pAC->GIni.GIMacsFound; - LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); - - /* Dual net mode? */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - LogPortMax--; - } - - if ((Instance != (SK_U32) (-1))) { - /* Check instance range. */ - if ((Instance < 2) || (Instance > LogPortMax)) { - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - PhysPortIndex = NetIndex; - } - else { - PhysPortIndex = Instance - 2; - } - Limit = PhysPortIndex + 1; - } - else { - /* - * Instance == (SK_U32) (-1), get all Instances of that OID. - * - * Not implemented yet. May be used in future releases. - */ - PhysPortIndex = 0; - Limit = PhysPortMax; - } - - pPrt = &pAC->GIni.GP[PhysPortIndex]; - if (pPrt->PHWLinkUp) { - Link = SK_TRUE; - } - else { - Link = SK_FALSE; - } - - /* Check MAC type */ - if (pPrt->PhyType != SK_PHY_MARV_COPPER) { - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* Initialize backup data pointer. */ - pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex]; - - /* Check action type */ - if (Action == SK_PNMI_GET) { - /* Check length */ - switch (Id) { - - case OID_SKGE_VCT_GET: - if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT)) { - *pLen = (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_VCT_STATUS: - if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U8)) { - *pLen = (Limit - PhysPortIndex) * sizeof(SK_U8); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* Get value */ - Offset = 0; - for (; PhysPortIndex < Limit; PhysPortIndex++) { - switch (Id) { - - case OID_SKGE_VCT_GET: - if ((Link == SK_FALSE) && - (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING)) { - RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE); - if (RetCode == 0) { - pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING; - pAC->Pnmi.VctStatus[PhysPortIndex] |= - (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE); - - /* Copy results for later use to PNMI struct. */ - for (i = 0; i < 4; i++) { - if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) { - if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] < 0xff)) { - pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH; - } - } - if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] != 0xff)) { - CableLength = 1000 * (((175 * pPrt->PMdiPairLen[i]) / 210) - 28); - } - else { - CableLength = 0; - } - pVctBackupData->PMdiPairLen[i] = CableLength; - pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i]; - } - - Para.Para32[0] = PhysPortIndex; - Para.Para32[1] = -1; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para); - SkEventDispatcher(pAC, IoC); - } - else { - ; /* VCT test is running. */ - } - } - - /* Get all results. */ - CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex); - Offset += sizeof(SK_U8); - *(pBuf + Offset) = pPrt->PCableLen; - Offset += sizeof(SK_U8); - for (i = 0; i < 4; i++) { - SK_PNMI_STORE_U32((pBuf + Offset), pVctBackupData->PMdiPairLen[i]); - Offset += sizeof(SK_U32); - } - for (i = 0; i < 4; i++) { - *(pBuf + Offset) = pVctBackupData->PMdiPairSts[i]; - Offset += sizeof(SK_U8); - } - - RetCode = SK_PNMI_ERR_OK; - break; - - case OID_SKGE_VCT_STATUS: - CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex); - Offset += sizeof(SK_U8); - RetCode = SK_PNMI_ERR_OK; - break; - - default: - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } /* for */ - *pLen = Offset; - return (RetCode); - - } /* if SK_PNMI_GET */ - - /* - * From here SET or PRESET action. Check if the passed - * buffer length is plausible. - */ - - /* Check length */ - switch (Id) { - case OID_SKGE_VCT_SET: - if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) { - *pLen = (Limit - PhysPortIndex) * sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * Perform preset or set. - */ - - /* VCT does not support PRESET action. */ - if (Action == SK_PNMI_PRESET) { - return (SK_PNMI_ERR_OK); - } - - Offset = 0; - for (; PhysPortIndex < Limit; PhysPortIndex++) { - switch (Id) { - case OID_SKGE_VCT_SET: /* Start VCT test. */ - if (Link == SK_FALSE) { - SkGeStopPort(pAC, IoC, PhysPortIndex, SK_STOP_ALL, SK_SOFT_RST); - - RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_TRUE); - if (RetCode == 0) { /* RetCode: 0 => Start! */ - pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_PENDING; - pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_NEW_VCT_DATA; - pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_LINK; - - /* - * Start VCT timer counter. - */ - SK_MEMSET((char *) &Para, 0, sizeof(Para)); - Para.Para32[0] = PhysPortIndex; - Para.Para32[1] = -1; - SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer, - 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Para); - SK_PNMI_STORE_U32((pBuf + Offset), RetCode); - RetCode = SK_PNMI_ERR_OK; - } - else { /* RetCode: 2 => Running! */ - SK_PNMI_STORE_U32((pBuf + Offset), RetCode); - RetCode = SK_PNMI_ERR_OK; - } - } - else { /* RetCode: 4 => Link! */ - RetCode = 4; - SK_PNMI_STORE_U32((pBuf + Offset), RetCode); - RetCode = SK_PNMI_ERR_OK; - } - Offset += sizeof(SK_U32); - break; - - default: - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } /* for */ - *pLen = Offset; - return (RetCode); - -} /* Vct */ - - -PNMI_STATIC void CheckVctStatus( -SK_AC *pAC, -SK_IOC IoC, -char *pBuf, -SK_U32 Offset, -SK_U32 PhysPortIndex) -{ - SK_GEPORT *pPrt; - SK_PNMI_VCT *pVctData; - SK_U32 RetCode; - - pPrt = &pAC->GIni.GP[PhysPortIndex]; - - pVctData = (SK_PNMI_VCT *) (pBuf + Offset); - pVctData->VctStatus = SK_PNMI_VCT_NONE; - - if (!pPrt->PHWLinkUp) { - - /* Was a VCT test ever made before? */ - if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) { - if ((pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_LINK)) { - pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA; - } - else { - pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA; - } - } - - /* Check VCT test status. */ - RetCode = SkGmCableDiagStatus(pAC,IoC, PhysPortIndex, SK_FALSE); - if (RetCode == 2) { /* VCT test is running. */ - pVctData->VctStatus |= SK_PNMI_VCT_RUNNING; - } - else { /* VCT data was copied to pAC here. Check PENDING state. */ - if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) { - pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA; - } - } - - if (pPrt->PCableLen != 0xff) { /* Old DSP value. */ - pVctData->VctStatus |= SK_PNMI_VCT_OLD_DSP_DATA; - } - } - else { - - /* Was a VCT test ever made before? */ - if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) { - pVctData->VctStatus &= ~SK_PNMI_VCT_NEW_VCT_DATA; - pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA; - } - - /* DSP only valid in 100/1000 modes. */ - if (pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed != - SK_LSPEED_STAT_10MBPS) { - pVctData->VctStatus |= SK_PNMI_VCT_NEW_DSP_DATA; - } - } -} /* CheckVctStatus */ - - -/***************************************************************************** - * - * SkPnmiGenIoctl - Handles new generic PNMI IOCTL, calls the needed - * PNMI function depending on the subcommand and - * returns all data belonging to the complete database - * or OID request. - * - * Description: - * Looks up the requested subcommand, calls the corresponding handler - * function and passes all required parameters to it. - * The function is called by the driver. It is needed to handle the new - * generic PNMI IOCTL. This IOCTL is given to the driver and contains both - * the OID and a subcommand to decide what kind of request has to be done. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed - * SK_PNMI_ERR_GENERAL A general severe internal error occured - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take - * the data. - * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -int SkPnmiGenIoctl( -SK_AC *pAC, /* Pointer to adapter context struct */ -SK_IOC IoC, /* I/O context */ -void *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* Length of buffer */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ -SK_I32 Mode; /* Store value of subcommand. */ -SK_U32 Oid; /* Store value of OID. */ -int ReturnCode; /* Store return value to show status of PNMI action. */ -int HeaderLength; /* Length of desired action plus OID. */ - - ReturnCode = SK_PNMI_ERR_GENERAL; - - SK_MEMCPY(&Mode, pBuf, sizeof(SK_I32)); - SK_MEMCPY(&Oid, (char *) pBuf + sizeof(SK_I32), sizeof(SK_U32)); - HeaderLength = sizeof(SK_I32) + sizeof(SK_U32); - *pLen = *pLen - HeaderLength; - SK_MEMCPY((char *) pBuf + sizeof(SK_I32), (char *) pBuf + HeaderLength, *pLen); - - switch(Mode) { - case SK_GET_SINGLE_VAR: - ReturnCode = SkPnmiGetVar(pAC, IoC, Oid, - (char *) pBuf + sizeof(SK_I32), pLen, - ((SK_U32) (-1)), NetIndex); - SK_PNMI_STORE_U32(pBuf, ReturnCode); - *pLen = *pLen + sizeof(SK_I32); - break; - case SK_PRESET_SINGLE_VAR: - ReturnCode = SkPnmiPreSetVar(pAC, IoC, Oid, - (char *) pBuf + sizeof(SK_I32), pLen, - ((SK_U32) (-1)), NetIndex); - SK_PNMI_STORE_U32(pBuf, ReturnCode); - *pLen = *pLen + sizeof(SK_I32); - break; - case SK_SET_SINGLE_VAR: - ReturnCode = SkPnmiSetVar(pAC, IoC, Oid, - (char *) pBuf + sizeof(SK_I32), pLen, - ((SK_U32) (-1)), NetIndex); - SK_PNMI_STORE_U32(pBuf, ReturnCode); - *pLen = *pLen + sizeof(SK_I32); - break; - case SK_GET_FULL_MIB: - ReturnCode = SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex); - break; - case SK_PRESET_FULL_MIB: - ReturnCode = SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex); - break; - case SK_SET_FULL_MIB: - ReturnCode = SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex); - break; - default: - break; - } - - return (ReturnCode); - -} /* SkGeIocGen */ diff --git a/drivers/net/sk98lin/skgesirq.c b/drivers/net/sk98lin/skgesirq.c deleted file mode 100644 index 3e7aa49afd0..00000000000 --- a/drivers/net/sk98lin/skgesirq.c +++ /dev/null @@ -1,2229 +0,0 @@ -/****************************************************************************** - * - * Name: skgesirq.c - * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.92 $ - * Date: $Date: 2003/09/16 14:37:07 $ - * Purpose: Special IRQ module - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - * Special Interrupt handler - * - * The following abstract should show how this module is included - * in the driver path: - * - * In the ISR of the driver the bits for frame transmission complete and - * for receive complete are checked and handled by the driver itself. - * The bits of the slow path mask are checked after that and then the - * entry into the so-called "slow path" is prepared. It is an implementors - * decision whether this is executed directly or just scheduled by - * disabling the mask. In the interrupt service routine some events may be - * generated, so it would be a good idea to call the EventDispatcher - * right after this ISR. - * - * The Interrupt source register of the adapter is NOT read by this module. - * SO if the drivers implementor needs a while loop around the - * slow data paths interrupt bits, he needs to call the SkGeSirqIsr() for - * each loop entered. - * - * However, the MAC Interrupt status registers are read in a while loop. - * - */ - -#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) -static const char SysKonnectFileId[] = - "@(#) $Id: skgesirq.c,v 1.92 2003/09/16 14:37:07 rschmidt Exp $ (C) Marvell."; -#endif - -#include "h/skdrv1st.h" /* Driver Specific Definitions */ -#ifndef SK_SLIM -#include "h/skgepnmi.h" /* PNMI Definitions */ -#include "h/skrlmt.h" /* RLMT Definitions */ -#endif -#include "h/skdrv2nd.h" /* Adapter Control and Driver specific Def. */ - -/* local function prototypes */ -#ifdef GENESIS -static int SkGePortCheckUpXmac(SK_AC*, SK_IOC, int, SK_BOOL); -static int SkGePortCheckUpBcom(SK_AC*, SK_IOC, int, SK_BOOL); -static void SkPhyIsrBcom(SK_AC*, SK_IOC, int, SK_U16); -#endif /* GENESIS */ -#ifdef YUKON -static int SkGePortCheckUpGmac(SK_AC*, SK_IOC, int, SK_BOOL); -static void SkPhyIsrGmac(SK_AC*, SK_IOC, int, SK_U16); -#endif /* YUKON */ -#ifdef OTHER_PHY -static int SkGePortCheckUpLone(SK_AC*, SK_IOC, int, SK_BOOL); -static int SkGePortCheckUpNat(SK_AC*, SK_IOC, int, SK_BOOL); -static void SkPhyIsrLone(SK_AC*, SK_IOC, int, SK_U16); -#endif /* OTHER_PHY */ - -#ifdef GENESIS -/* - * array of Rx counter from XMAC which are checked - * in AutoSense mode to check whether a link is not able to auto-negotiate. - */ -static const SK_U16 SkGeRxRegs[]= { - XM_RXF_64B, - XM_RXF_127B, - XM_RXF_255B, - XM_RXF_511B, - XM_RXF_1023B, - XM_RXF_MAX_SZ -} ; -#endif /* GENESIS */ - -#ifdef __C2MAN__ -/* - * Special IRQ function - * - * General Description: - * - */ -intro() -{} -#endif - -/****************************************************************************** - * - * SkHWInitDefSense() - Default Autosensing mode initialization - * - * Description: sets the PLinkMode for HWInit - * - * Returns: N/A - */ -static void SkHWInitDefSense( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - - pPrt = &pAC->GIni.GP[Port]; - - pPrt->PAutoNegTimeOut = 0; - - if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) { - pPrt->PLinkMode = pPrt->PLinkModeConf; - return; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("AutoSensing: First mode %d on Port %d\n", - (int)SK_LMODE_AUTOFULL, Port)); - - pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL; - - return; -} /* SkHWInitDefSense */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkHWSenseGetNext() - Get Next Autosensing Mode - * - * Description: gets the appropriate next mode - * - * Note: - * - */ -static SK_U8 SkHWSenseGetNext( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - - pPrt = &pAC->GIni.GP[Port]; - - pPrt->PAutoNegTimeOut = 0; - - if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) { - /* Leave all as configured */ - return(pPrt->PLinkModeConf); - } - - if (pPrt->PLinkMode == (SK_U8)SK_LMODE_AUTOFULL) { - /* Return next mode AUTOBOTH */ - return ((SK_U8)SK_LMODE_AUTOBOTH); - } - - /* Return default autofull */ - return ((SK_U8)SK_LMODE_AUTOFULL); -} /* SkHWSenseGetNext */ - - -/****************************************************************************** - * - * SkHWSenseSetNext() - Autosensing Set next mode - * - * Description: sets the appropriate next mode - * - * Returns: N/A - */ -static void SkHWSenseSetNext( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_U8 NewMode) /* New Mode to be written in sense mode */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - - pPrt = &pAC->GIni.GP[Port]; - - pPrt->PAutoNegTimeOut = 0; - - if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) { - return; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("AutoSensing: next mode %d on Port %d\n", - (int)NewMode, Port)); - - pPrt->PLinkMode = NewMode; - - return; -} /* SkHWSenseSetNext */ -#endif /* GENESIS */ - - -/****************************************************************************** - * - * SkHWLinkDown() - Link Down handling - * - * Description: handles the hardware link down signal - * - * Returns: N/A - */ -void SkHWLinkDown( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - - pPrt = &pAC->GIni.GP[Port]; - - /* Disable all MAC interrupts */ - SkMacIrqDisable(pAC, IoC, Port); - - /* Disable Receiver and Transmitter */ - SkMacRxTxDisable(pAC, IoC, Port); - - /* Init default sense mode */ - SkHWInitDefSense(pAC, IoC, Port); - - if (pPrt->PHWLinkUp == SK_FALSE) { - return; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Link down Port %d\n", Port)); - - /* Set Link to DOWN */ - pPrt->PHWLinkUp = SK_FALSE; - - /* Reset Port stati */ - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN; - pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE; - pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_INDETERMINATED; - - /* Re-init Phy especially when the AutoSense default is set now */ - SkMacInitPhy(pAC, IoC, Port, SK_FALSE); - - /* GP0: used for workaround of Rev. C Errata 2 */ - - /* Do NOT signal to RLMT */ - - /* Do NOT start the timer here */ -} /* SkHWLinkDown */ - - -/****************************************************************************** - * - * SkHWLinkUp() - Link Up handling - * - * Description: handles the hardware link up signal - * - * Returns: N/A - */ -static void SkHWLinkUp( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PHWLinkUp) { - /* We do NOT need to proceed on active link */ - return; - } - - pPrt->PHWLinkUp = SK_TRUE; - pPrt->PAutoNegFail = SK_FALSE; - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN; - - if (pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOHALF && - pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOFULL && - pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOBOTH) { - /* Link is up and no Auto-negotiation should be done */ - - /* Link speed should be the configured one */ - switch (pPrt->PLinkSpeed) { - case SK_LSPEED_AUTO: - /* default is 1000 Mbps */ - case SK_LSPEED_1000MBPS: - pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS; - break; - case SK_LSPEED_100MBPS: - pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS; - break; - case SK_LSPEED_10MBPS: - pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS; - break; - } - - /* Set Link Mode Status */ - if (pPrt->PLinkMode == SK_LMODE_FULL) { - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_FULL; - } - else { - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_HALF; - } - - /* No flow control without auto-negotiation */ - pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE; - - /* enable Rx/Tx */ - (void)SkMacRxTxEnable(pAC, IoC, Port); - } -} /* SkHWLinkUp */ - - -/****************************************************************************** - * - * SkMacParity() - MAC parity workaround - * - * Description: handles MAC parity errors correctly - * - * Returns: N/A - */ -static void SkMacParity( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index of the port failed */ -{ - SK_EVPARA Para; - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - SK_U32 TxMax; /* Tx Max Size Counter */ - - pPrt = &pAC->GIni.GP[Port]; - - /* Clear IRQ Tx Parity Error */ -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_PERR); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */ - SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), - (SK_U8)((pAC->GIni.GIChipId == CHIP_ID_YUKON && - pAC->GIni.GIChipRev == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE)); - } -#endif /* YUKON */ - - if (pPrt->PCheckPar) { - - if (Port == MAC_1) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG); - } - else { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG); - } - Para.Para64 = Port; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - - Para.Para32[0] = Port; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - - return; - } - - /* Check whether frames with a size of 1k were sent */ -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - /* Snap statistic counters */ - (void)SkXmUpdateStats(pAC, IoC, Port); - - (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXF_MAX_SZ, &TxMax); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - (void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax); - } -#endif /* YUKON */ - - if (TxMax > 0) { - /* From now on check the parity */ - pPrt->PCheckPar = SK_TRUE; - } -} /* SkMacParity */ - - -/****************************************************************************** - * - * SkGeHwErr() - Hardware Error service routine - * - * Description: handles all HW Error interrupts - * - * Returns: N/A - */ -static void SkGeHwErr( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -SK_U32 HwStatus) /* Interrupt status word */ -{ - SK_EVPARA Para; - SK_U16 Word; - - if ((HwStatus & (IS_IRQ_MST_ERR | IS_IRQ_STAT)) != 0) { - /* PCI Errors occured */ - if ((HwStatus & IS_IRQ_STAT) != 0) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG); - } - else { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG); - } - - /* Reset all bits in the PCI STATUS register */ - SK_IN16(IoC, PCI_C(PCI_STATUS), &Word); - - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); - SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS)); - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); - - Para.Para64 = 0; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); - } - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - if ((HwStatus & IS_NO_STAT_M1) != 0) { - /* Ignore it */ - /* This situation is also indicated in the descriptor */ - SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INSTAT); - } - - if ((HwStatus & IS_NO_STAT_M2) != 0) { - /* Ignore it */ - /* This situation is also indicated in the descriptor */ - SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INSTAT); - } - - if ((HwStatus & IS_NO_TIST_M1) != 0) { - /* Ignore it */ - /* This situation is also indicated in the descriptor */ - SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INTIST); - } - - if ((HwStatus & IS_NO_TIST_M2) != 0) { - /* Ignore it */ - /* This situation is also indicated in the descriptor */ - SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INTIST); - } - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* This is necessary only for Rx timing measurements */ - if ((HwStatus & IS_IRQ_TIST_OV) != 0) { - /* increment Time Stamp Timer counter (high) */ - pAC->GIni.GITimeStampCnt++; - - /* Clear Time Stamp Timer IRQ */ - SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ); - } - - if ((HwStatus & IS_IRQ_SENSOR) != 0) { - /* no sensors on 32-bit Yukon */ - if (pAC->GIni.GIYukon32Bit) { - /* disable HW Error IRQ */ - pAC->GIni.GIValIrqMask &= ~IS_HW_ERR; - } - } - } -#endif /* YUKON */ - - if ((HwStatus & IS_RAM_RD_PAR) != 0) { - SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_RD_PERR); - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E014, SKERR_SIRQ_E014MSG); - Para.Para64 = 0; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); - } - - if ((HwStatus & IS_RAM_WR_PAR) != 0) { - SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_WR_PERR); - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E015, SKERR_SIRQ_E015MSG); - Para.Para64 = 0; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); - } - - if ((HwStatus & IS_M1_PAR_ERR) != 0) { - SkMacParity(pAC, IoC, MAC_1); - } - - if ((HwStatus & IS_M2_PAR_ERR) != 0) { - SkMacParity(pAC, IoC, MAC_2); - } - - if ((HwStatus & IS_R1_PAR_ERR) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_P); - - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG); - Para.Para64 = MAC_1; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - - Para.Para32[0] = MAC_1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - if ((HwStatus & IS_R2_PAR_ERR) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_P); - - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG); - Para.Para64 = MAC_2; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - - Para.Para32[0] = MAC_2; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } -} /* SkGeHwErr */ - - -/****************************************************************************** - * - * SkGeSirqIsr() - Special Interrupt Service Routine - * - * Description: handles all non data transfer specific interrupts (slow path) - * - * Returns: N/A - */ -void SkGeSirqIsr( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -SK_U32 Istatus) /* Interrupt status word */ -{ - SK_EVPARA Para; - SK_U32 RegVal32; /* Read register value */ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - SK_U16 PhyInt; - int i; - - if (((Istatus & IS_HW_ERR) & pAC->GIni.GIValIrqMask) != 0) { - /* read the HW Error Interrupt source */ - SK_IN32(IoC, B0_HWE_ISRC, &RegVal32); - - SkGeHwErr(pAC, IoC, RegVal32); - } - - /* - * Packet Timeout interrupts - */ - /* Check whether MACs are correctly initialized */ - if (((Istatus & (IS_PA_TO_RX1 | IS_PA_TO_TX1)) != 0) && - pAC->GIni.GP[MAC_1].PState == SK_PRT_RESET) { - /* MAC 1 was not initialized but Packet timeout occured */ - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E004, - SKERR_SIRQ_E004MSG); - } - - if (((Istatus & (IS_PA_TO_RX2 | IS_PA_TO_TX2)) != 0) && - pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) { - /* MAC 2 was not initialized but Packet timeout occured */ - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005, - SKERR_SIRQ_E005MSG); - } - - if ((Istatus & IS_PA_TO_RX1) != 0) { - /* Means network is filling us up */ - SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E002, - SKERR_SIRQ_E002MSG); - SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX1); - } - - if ((Istatus & IS_PA_TO_RX2) != 0) { - /* Means network is filling us up */ - SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E003, - SKERR_SIRQ_E003MSG); - SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX2); - } - - if ((Istatus & IS_PA_TO_TX1) != 0) { - - pPrt = &pAC->GIni.GP[0]; - - /* May be a normal situation in a server with a slow network */ - SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1); - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - /* - * workaround: if in half duplex mode, check for Tx hangup. - * Read number of TX'ed bytes, wait for 10 ms, then compare - * the number with current value. If nothing changed, we assume - * that Tx is hanging and do a FIFO flush (see event routine). - */ - if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || - pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) && - !pPrt->HalfDupTimerActive) { - /* - * many more pack. arb. timeouts may come in between, - * we ignore those - */ - pPrt->HalfDupTimerActive = SK_TRUE; - /* Snap statistic counters */ - (void)SkXmUpdateStats(pAC, IoC, 0); - - (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_HI, &RegVal32); - - pPrt->LastOctets = (SK_U64)RegVal32 << 32; - - (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_LO, &RegVal32); - - pPrt->LastOctets += RegVal32; - - Para.Para32[0] = 0; - SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME, - SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para); - } - } -#endif /* GENESIS */ - } - - if ((Istatus & IS_PA_TO_TX2) != 0) { - - pPrt = &pAC->GIni.GP[1]; - - /* May be a normal situation in a server with a slow network */ - SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2); - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - /* workaround: see above */ - if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || - pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) && - !pPrt->HalfDupTimerActive) { - pPrt->HalfDupTimerActive = SK_TRUE; - /* Snap statistic counters */ - (void)SkXmUpdateStats(pAC, IoC, 1); - - (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_HI, &RegVal32); - - pPrt->LastOctets = (SK_U64)RegVal32 << 32; - - (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_LO, &RegVal32); - - pPrt->LastOctets += RegVal32; - - Para.Para32[0] = 1; - SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME, - SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para); - } - } -#endif /* GENESIS */ - } - - /* Check interrupts of the particular queues */ - if ((Istatus & IS_R1_C) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_C); - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E006, - SKERR_SIRQ_E006MSG); - Para.Para64 = MAC_1; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - Para.Para32[0] = MAC_1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - if ((Istatus & IS_R2_C) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_C); - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E007, - SKERR_SIRQ_E007MSG); - Para.Para64 = MAC_2; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - Para.Para32[0] = MAC_2; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - if ((Istatus & IS_XS1_C) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_XS1_CSR, CSR_IRQ_CL_C); - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E008, - SKERR_SIRQ_E008MSG); - Para.Para64 = MAC_1; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - Para.Para32[0] = MAC_1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - if ((Istatus & IS_XA1_C) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_XA1_CSR, CSR_IRQ_CL_C); - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E009, - SKERR_SIRQ_E009MSG); - Para.Para64 = MAC_1; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - Para.Para32[0] = MAC_1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - if ((Istatus & IS_XS2_C) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_XS2_CSR, CSR_IRQ_CL_C); - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E010, - SKERR_SIRQ_E010MSG); - Para.Para64 = MAC_2; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - Para.Para32[0] = MAC_2; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - if ((Istatus & IS_XA2_C) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_XA2_CSR, CSR_IRQ_CL_C); - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E011, - SKERR_SIRQ_E011MSG); - Para.Para64 = MAC_2; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - Para.Para32[0] = MAC_2; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - /* External reg interrupt */ - if ((Istatus & IS_EXT_REG) != 0) { - /* Test IRQs from PHY */ - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - - pPrt = &pAC->GIni.GP[i]; - - if (pPrt->PState == SK_PRT_RESET) { - continue; - } - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - switch (pPrt->PhyType) { - - case SK_PHY_XMAC: - break; - - case SK_PHY_BCOM: - SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_STAT, &PhyInt); - - if ((PhyInt & ~PHY_B_DEF_MSK) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Port %d Bcom Int: 0x%04X\n", - i, PhyInt)); - SkPhyIsrBcom(pAC, IoC, i, PhyInt); - } - break; -#ifdef OTHER_PHY - case SK_PHY_LONE: - SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_STAT, &PhyInt); - - if ((PhyInt & PHY_L_DEF_MSK) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Port %d Lone Int: %x\n", - i, PhyInt)); - SkPhyIsrLone(pAC, IoC, i, PhyInt); - } - break; -#endif /* OTHER_PHY */ - } - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* Read PHY Interrupt Status */ - SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_STAT, &PhyInt); - - if ((PhyInt & PHY_M_DEF_MSK) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Port %d Marv Int: 0x%04X\n", - i, PhyInt)); - SkPhyIsrGmac(pAC, IoC, i, PhyInt); - } - } -#endif /* YUKON */ - } - } - - /* I2C Ready interrupt */ - if ((Istatus & IS_I2C_READY) != 0) { -#ifdef SK_SLIM - SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); -#else - SkI2cIsr(pAC, IoC); -#endif - } - - /* SW forced interrupt */ - if ((Istatus & IS_IRQ_SW) != 0) { - /* clear the software IRQ */ - SK_OUT8(IoC, B0_CTST, CS_CL_SW_IRQ); - } - - if ((Istatus & IS_LNK_SYNC_M1) != 0) { - /* - * We do NOT need the Link Sync interrupt, because it shows - * us only a link going down. - */ - /* clear interrupt */ - SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LED_CLR_IRQ); - } - - /* Check MAC after link sync counter */ - if ((Istatus & IS_MAC1) != 0) { - /* IRQ from MAC 1 */ - SkMacIrq(pAC, IoC, MAC_1); - } - - if ((Istatus & IS_LNK_SYNC_M2) != 0) { - /* - * We do NOT need the Link Sync interrupt, because it shows - * us only a link going down. - */ - /* clear interrupt */ - SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LED_CLR_IRQ); - } - - /* Check MAC after link sync counter */ - if ((Istatus & IS_MAC2) != 0) { - /* IRQ from MAC 2 */ - SkMacIrq(pAC, IoC, MAC_2); - } - - /* Timer interrupt (served last) */ - if ((Istatus & IS_TIMINT) != 0) { - /* check for HW Errors */ - if (((Istatus & IS_HW_ERR) & ~pAC->GIni.GIValIrqMask) != 0) { - /* read the HW Error Interrupt source */ - SK_IN32(IoC, B0_HWE_ISRC, &RegVal32); - - SkGeHwErr(pAC, IoC, RegVal32); - } - - SkHwtIsr(pAC, IoC); - } - -} /* SkGeSirqIsr */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2 - * - * return: - * 0 o.k. nothing needed - * 1 Restart needed on this port - */ -static int SkGePortCheckShorts( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port) /* Which port should be checked */ -{ - SK_U32 Shorts; /* Short Event Counter */ - SK_U32 CheckShorts; /* Check value for Short Event Counter */ - SK_U64 RxCts; /* Rx Counter (packets on network) */ - SK_U32 RxTmp; /* Rx temp. Counter */ - SK_U32 FcsErrCts; /* FCS Error Counter */ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - int Rtv; /* Return value */ - int i; - - pPrt = &pAC->GIni.GP[Port]; - - /* Default: no action */ - Rtv = SK_HW_PS_NONE; - - (void)SkXmUpdateStats(pAC, IoC, Port); - - /* Extra precaution: check for short Event counter */ - (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts); - - /* - * Read Rx counters (packets seen on the network and not necessarily - * really received. - */ - RxCts = 0; - - for (i = 0; i < sizeof(SkGeRxRegs)/sizeof(SkGeRxRegs[0]); i++) { - - (void)SkXmMacStatistic(pAC, IoC, Port, SkGeRxRegs[i], &RxTmp); - - RxCts += (SK_U64)RxTmp; - } - - /* On default: check shorts against zero */ - CheckShorts = 0; - - /* Extra precaution on active links */ - if (pPrt->PHWLinkUp) { - /* Reset Link Restart counter */ - pPrt->PLinkResCt = 0; - pPrt->PAutoNegTOCt = 0; - - /* If link is up check for 2 */ - CheckShorts = 2; - - (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXF_FCS_ERR, &FcsErrCts); - - if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && - pPrt->PLipaAutoNeg == SK_LIPA_UNKNOWN && - (pPrt->PLinkMode == SK_LMODE_HALF || - pPrt->PLinkMode == SK_LMODE_FULL)) { - /* - * This is autosensing and we are in the fallback - * manual full/half duplex mode. - */ - if (RxCts == pPrt->PPrevRx) { - /* Nothing received, restart link */ - pPrt->PPrevFcs = FcsErrCts; - pPrt->PPrevShorts = Shorts; - - return(SK_HW_PS_RESTART); - } - else { - pPrt->PLipaAutoNeg = SK_LIPA_MANUAL; - } - } - - if (((RxCts - pPrt->PPrevRx) > pPrt->PRxLim) || - (!(FcsErrCts - pPrt->PPrevFcs))) { - /* - * Note: The compare with zero above has to be done the way shown, - * otherwise the Linux driver will have a problem. - */ - /* - * We received a bunch of frames or no CRC error occured on the - * network -> ok. - */ - pPrt->PPrevRx = RxCts; - pPrt->PPrevFcs = FcsErrCts; - pPrt->PPrevShorts = Shorts; - - return(SK_HW_PS_NONE); - } - - pPrt->PPrevFcs = FcsErrCts; - } - - - if ((Shorts - pPrt->PPrevShorts) > CheckShorts) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Short Event Count Restart Port %d \n", Port)); - Rtv = SK_HW_PS_RESTART; - } - - pPrt->PPrevShorts = Shorts; - pPrt->PPrevRx = RxCts; - - return(Rtv); -} /* SkGePortCheckShorts */ -#endif /* GENESIS */ - - -/****************************************************************************** - * - * SkGePortCheckUp() - Check if the link is up - * - * return: - * 0 o.k. nothing needed - * 1 Restart needed on this port - * 2 Link came up - */ -static int SkGePortCheckUp( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port) /* Which port should be checked */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */ - int Rtv; /* Return value */ - - Rtv = SK_HW_PS_NONE; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - AutoNeg = SK_FALSE; - } - else { - AutoNeg = SK_TRUE; - } - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - switch (pPrt->PhyType) { - - case SK_PHY_XMAC: - Rtv = SkGePortCheckUpXmac(pAC, IoC, Port, AutoNeg); - break; - case SK_PHY_BCOM: - Rtv = SkGePortCheckUpBcom(pAC, IoC, Port, AutoNeg); - break; -#ifdef OTHER_PHY - case SK_PHY_LONE: - Rtv = SkGePortCheckUpLone(pAC, IoC, Port, AutoNeg); - break; - case SK_PHY_NAT: - Rtv = SkGePortCheckUpNat(pAC, IoC, Port, AutoNeg); - break; -#endif /* OTHER_PHY */ - } - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - Rtv = SkGePortCheckUpGmac(pAC, IoC, Port, AutoNeg); - } -#endif /* YUKON */ - - return(Rtv); -} /* SkGePortCheckUp */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2 - * - * return: - * 0 o.k. nothing needed - * 1 Restart needed on this port - * 2 Link came up - */ -static int SkGePortCheckUpXmac( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port, /* Which port should be checked */ -SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */ -{ - SK_U32 Shorts; /* Short Event Counter */ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - int Done; - SK_U32 GpReg; /* General Purpose register value */ - SK_U16 Isrc; /* Interrupt source register */ - SK_U16 IsrcSum; /* Interrupt source register sum */ - SK_U16 LpAb; /* Link Partner Ability */ - SK_U16 ResAb; /* Resolved Ability */ - SK_U16 ExtStat; /* Extended Status Register */ - SK_U8 NextMode; /* Next AutoSensing Mode */ - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PHWLinkUp) { - if (pPrt->PhyType != SK_PHY_XMAC) { - return(SK_HW_PS_NONE); - } - else { - return(SkGePortCheckShorts(pAC, IoC, Port)); - } - } - - IsrcSum = pPrt->PIsave; - pPrt->PIsave = 0; - - /* Now wait for each port's link */ - if (pPrt->PLinkBroken) { - /* Link was broken */ - XM_IN32(IoC, Port, XM_GP_PORT, &GpReg); - - if ((GpReg & XM_GP_INP_ASS) == 0) { - /* The Link is in sync */ - XM_IN16(IoC, Port, XM_ISRC, &Isrc); - IsrcSum |= Isrc; - SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum); - - if ((Isrc & XM_IS_INP_ASS) == 0) { - /* It has been in sync since last time */ - /* Restart the PORT */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Link in sync Restart Port %d\n", Port)); - - (void)SkXmUpdateStats(pAC, IoC, Port); - - /* We now need to reinitialize the PrevShorts counter */ - (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts); - pPrt->PPrevShorts = Shorts; - - pPrt->PLinkBroken = SK_FALSE; - - /* - * Link Restart Workaround: - * it may be possible that the other Link side - * restarts its link as well an we detect - * another LinkBroken. To prevent this - * happening we check for a maximum number - * of consecutive restart. If those happens, - * we do NOT restart the active link and - * check whether the link is now o.k. - */ - pPrt->PLinkResCt++; - - pPrt->PAutoNegTimeOut = 0; - - if (pPrt->PLinkResCt < SK_MAX_LRESTART) { - return(SK_HW_PS_RESTART); - } - - pPrt->PLinkResCt = 0; - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Do NOT restart on Port %d %x %x\n", Port, Isrc, IsrcSum)); - } - else { - pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Save Sync/nosync Port %d %x %x\n", Port, Isrc, IsrcSum)); - - /* Do nothing more if link is broken */ - return(SK_HW_PS_NONE); - } - } - else { - /* Do nothing more if link is broken */ - return(SK_HW_PS_NONE); - } - - } - else { - /* Link was not broken, check if it is */ - XM_IN16(IoC, Port, XM_ISRC, &Isrc); - IsrcSum |= Isrc; - if ((Isrc & XM_IS_INP_ASS) != 0) { - XM_IN16(IoC, Port, XM_ISRC, &Isrc); - IsrcSum |= Isrc; - if ((Isrc & XM_IS_INP_ASS) != 0) { - XM_IN16(IoC, Port, XM_ISRC, &Isrc); - IsrcSum |= Isrc; - if ((Isrc & XM_IS_INP_ASS) != 0) { - pPrt->PLinkBroken = SK_TRUE; - /* Re-Init Link partner Autoneg flag */ - pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN; - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Link broken Port %d\n", Port)); - - /* Cable removed-> reinit sense mode */ - SkHWInitDefSense(pAC, IoC, Port); - - return(SK_HW_PS_RESTART); - } - } - } - else { - SkXmAutoNegLipaXmac(pAC, IoC, Port, Isrc); - - if (SkGePortCheckShorts(pAC, IoC, Port) == SK_HW_PS_RESTART) { - return(SK_HW_PS_RESTART); - } - } - } - - /* - * here we usually can check whether the link is in sync and - * auto-negotiation is done. - */ - XM_IN32(IoC, Port, XM_GP_PORT, &GpReg); - XM_IN16(IoC, Port, XM_ISRC, &Isrc); - IsrcSum |= Isrc; - - SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum); - - if ((GpReg & XM_GP_INP_ASS) != 0 || (IsrcSum & XM_IS_INP_ASS) != 0) { - if ((GpReg & XM_GP_INP_ASS) == 0) { - /* Save Auto-negotiation Done interrupt only if link is in sync */ - pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND); - } -#ifdef DEBUG - if ((pPrt->PIsave & XM_IS_AND) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg done rescheduled Port %d\n", Port)); - } -#endif /* DEBUG */ - return(SK_HW_PS_NONE); - } - - if (AutoNeg) { - if ((IsrcSum & XM_IS_AND) != 0) { - SkHWLinkUp(pAC, IoC, Port); - Done = SkMacAutoNegDone(pAC, IoC, Port); - if (Done != SK_AND_OK) { - /* Get PHY parameters, for debugging only */ - SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LpAb); - SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg FAIL Port %d (LpAb %x, ResAb %x)\n", - Port, LpAb, ResAb)); - - /* Try next possible mode */ - NextMode = SkHWSenseGetNext(pAC, IoC, Port); - SkHWLinkDown(pAC, IoC, Port); - if (Done == SK_AND_DUP_CAP) { - /* GoTo next mode */ - SkHWSenseSetNext(pAC, IoC, Port, NextMode); - } - - return(SK_HW_PS_RESTART); - } - /* - * Dummy Read extended status to prevent extra link down/ups - * (clear Page Received bit if set) - */ - SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_EXP, &ExtStat); - - return(SK_HW_PS_LINK); - } - - /* AutoNeg not done, but HW link is up. Check for timeouts */ - pPrt->PAutoNegTimeOut++; - if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) { - /* Increase the Timeout counter */ - pPrt->PAutoNegTOCt++; - - /* Timeout occured */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("AutoNeg timeout Port %d\n", Port)); - if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && - pPrt->PLipaAutoNeg != SK_LIPA_AUTO) { - /* Set Link manually up */ - SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Set manual full duplex Port %d\n", Port)); - } - - if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && - pPrt->PLipaAutoNeg == SK_LIPA_AUTO && - pPrt->PAutoNegTOCt >= SK_MAX_ANEG_TO) { - /* - * This is rather complicated. - * we need to check here whether the LIPA_AUTO - * we saw before is false alert. We saw at one - * switch ( SR8800) that on boot time it sends - * just one auto-neg packet and does no further - * auto-negotiation. - * Solution: we restart the autosensing after - * a few timeouts. - */ - pPrt->PAutoNegTOCt = 0; - pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN; - SkHWInitDefSense(pAC, IoC, Port); - } - - /* Do the restart */ - return(SK_HW_PS_RESTART); - } - } - else { - /* Link is up and we don't need more */ -#ifdef DEBUG - if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("ERROR: Lipa auto detected on port %d\n", Port)); - } -#endif /* DEBUG */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Link sync(GP), Port %d\n", Port)); - SkHWLinkUp(pAC, IoC, Port); - - /* - * Link sync (GP) and so assume a good connection. But if not received - * a bunch of frames received in a time slot (maybe broken tx cable) - * the port is restart. - */ - return(SK_HW_PS_LINK); - } - - return(SK_HW_PS_NONE); -} /* SkGePortCheckUpXmac */ - - -/****************************************************************************** - * - * SkGePortCheckUpBcom() - Check if the link is up on Bcom PHY - * - * return: - * 0 o.k. nothing needed - * 1 Restart needed on this port - * 2 Link came up - */ -static int SkGePortCheckUpBcom( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port, /* Which port should be checked */ -SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - int Done; - SK_U16 Isrc; /* Interrupt source register */ - SK_U16 PhyStat; /* Phy Status Register */ - SK_U16 ResAb; /* Master/Slave resolution */ - SK_U16 Ctrl; /* Broadcom control flags */ -#ifdef DEBUG - SK_U16 LpAb; - SK_U16 ExtStat; -#endif /* DEBUG */ - - pPrt = &pAC->GIni.GP[Port]; - - /* Check for No HCD Link events (#10523) */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc); - -#ifdef xDEBUG - if ((Isrc & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) == - (PHY_B_IS_SCR_S_ER | PHY_B_IS_RRS_CHANGE | PHY_B_IS_LRS_CHANGE)) { - - SK_U32 Stat1, Stat2, Stat3; - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1); - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "CheckUp1 - Stat: %x, Mask: %x", - (void *)Isrc, - (void *)Stat1); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &Stat2); - Stat1 = Stat1 << 16 | Stat2; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3); - Stat2 = Stat2 << 16 | Stat3; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "Ctrl/Stat: %x, AN Adv/LP: %x", - (void *)Stat1, - (void *)Stat2); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2); - Stat1 = Stat1 << 16 | Stat2; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &Stat3); - Stat2 = Stat2 << 16 | Stat3; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x", - (void *)Stat1, - (void *)Stat2); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2); - Stat1 = Stat1 << 16 | Stat2; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3); - Stat2 = Stat2 << 16 | Stat3; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x", - (void *)Stat1, - (void *)Stat2); - } -#endif /* DEBUG */ - - if ((Isrc & (PHY_B_IS_NO_HDCL /* | PHY_B_IS_NO_HDC */)) != 0) { - /* - * Workaround BCom Errata: - * enable and disable loopback mode if "NO HCD" occurs. - */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Ctrl); - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, - (SK_U16)(Ctrl | PHY_CT_LOOP)); - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, - (SK_U16)(Ctrl & ~PHY_CT_LOOP)); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("No HCD Link event, Port %d\n", Port)); -#ifdef xDEBUG - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "No HCD link event, port %d.", - (void *)Port, - (void *)NULL); -#endif /* DEBUG */ - } - - /* Not obsolete: link status bit is latched to 0 and autoclearing! */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat); - - if (pPrt->PHWLinkUp) { - return(SK_HW_PS_NONE); - } - -#ifdef xDEBUG - { - SK_U32 Stat1, Stat2, Stat3; - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1); - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "CheckUp1a - Stat: %x, Mask: %x", - (void *)Isrc, - (void *)Stat1); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat); - Stat1 = Stat1 << 16 | PhyStat; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3); - Stat2 = Stat2 << 16 | Stat3; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "Ctrl/Stat: %x, AN Adv/LP: %x", - (void *)Stat1, - (void *)Stat2); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2); - Stat1 = Stat1 << 16 | Stat2; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb); - Stat2 = Stat2 << 16 | ResAb; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x", - (void *)Stat1, - (void *)Stat2); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2); - Stat1 = Stat1 << 16 | Stat2; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3); - Stat2 = Stat2 << 16 | Stat3; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x", - (void *)Stat1, - (void *)Stat2); - } -#endif /* DEBUG */ - - /* - * Here we usually can check whether the link is in sync and - * auto-negotiation is done. - */ - - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat); - - SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat)); - - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb); - - if ((ResAb & PHY_B_1000S_MSF) != 0) { - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Master/Slave Fault port %d\n", Port)); - - pPrt->PAutoNegFail = SK_TRUE; - pPrt->PMSStatus = SK_MS_STAT_FAULT; - - return(SK_HW_PS_RESTART); - } - - if ((PhyStat & PHY_ST_LSYNC) == 0) { - return(SK_HW_PS_NONE); - } - - pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? - SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE; - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Port %d, ResAb: 0x%04X\n", Port, ResAb)); - - if (AutoNeg) { - if ((PhyStat & PHY_ST_AN_OVER) != 0) { - - SkHWLinkUp(pAC, IoC, Port); - - Done = SkMacAutoNegDone(pAC, IoC, Port); - - if (Done != SK_AND_OK) { -#ifdef DEBUG - /* Get PHY parameters, for debugging only */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LpAb); - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ExtStat); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n", - Port, LpAb, ExtStat)); -#endif /* DEBUG */ - return(SK_HW_PS_RESTART); - } - else { -#ifdef xDEBUG - /* Dummy read ISR to prevent extra link downs/ups */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat); - - if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) { - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "CheckUp2 - Stat: %x", - (void *)ExtStat, - (void *)NULL); - } -#endif /* DEBUG */ - return(SK_HW_PS_LINK); - } - } - } - else { /* !AutoNeg */ - /* Link is up and we don't need more. */ -#ifdef DEBUG - if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("ERROR: Lipa auto detected on port %d\n", Port)); - } -#endif /* DEBUG */ - -#ifdef xDEBUG - /* Dummy read ISR to prevent extra link downs/ups */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat); - - if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) { - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "CheckUp3 - Stat: %x", - (void *)ExtStat, - (void *)NULL); - } -#endif /* DEBUG */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Link sync(GP), Port %d\n", Port)); - SkHWLinkUp(pAC, IoC, Port); - - return(SK_HW_PS_LINK); - } - - return(SK_HW_PS_NONE); -} /* SkGePortCheckUpBcom */ -#endif /* GENESIS */ - - -#ifdef YUKON -/****************************************************************************** - * - * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY - * - * return: - * 0 o.k. nothing needed - * 1 Restart needed on this port - * 2 Link came up - */ -static int SkGePortCheckUpGmac( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port, /* Which port should be checked */ -SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - int Done; - SK_U16 PhyIsrc; /* PHY Interrupt source */ - SK_U16 PhyStat; /* PPY Status */ - SK_U16 PhySpecStat;/* PHY Specific Status */ - SK_U16 ResAb; /* Master/Slave resolution */ - SK_EVPARA Para; -#ifdef DEBUG - SK_U16 Word; /* I/O helper */ -#endif /* DEBUG */ - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PHWLinkUp) { - return(SK_HW_PS_NONE); - } - - /* Read PHY Status */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat)); - - /* Read PHY Interrupt Status */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &PhyIsrc); - - if ((PhyIsrc & PHY_M_IS_AN_COMPL) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Auto-Negotiation Completed, PhyIsrc: 0x%04X\n", PhyIsrc)); - } - - if ((PhyIsrc & PHY_M_IS_LSP_CHANGE) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Link Speed Changed, PhyIsrc: 0x%04X\n", PhyIsrc)); - } - - SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); - - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb); - - if ((ResAb & PHY_B_1000S_MSF) != 0) { - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Master/Slave Fault port %d\n", Port)); - - pPrt->PAutoNegFail = SK_TRUE; - pPrt->PMSStatus = SK_MS_STAT_FAULT; - - return(SK_HW_PS_RESTART); - } - - /* Read PHY Specific Status */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Phy1000BT: 0x%04X, PhySpecStat: 0x%04X\n", ResAb, PhySpecStat)); - -#ifdef DEBUG - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_EXP, &Word); - - if ((PhyIsrc & PHY_M_IS_AN_PR) != 0 || (Word & PHY_ANE_RX_PG) != 0 || - (PhySpecStat & PHY_M_PS_PAGE_REC) != 0) { - /* Read PHY Next Page Link Partner */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_NEPG_LP, &Word); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Page Received, NextPage: 0x%04X\n", Word)); - } -#endif /* DEBUG */ - - if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) { - return(SK_HW_PS_NONE); - } - - if ((PhySpecStat & PHY_M_PS_DOWNS_STAT) != 0 || - (PhyIsrc & PHY_M_IS_DOWNSH_DET) != 0) { - /* Downshift detected */ - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E025, SKERR_SIRQ_E025MSG); - - Para.Para64 = Port; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_DOWNSHIFT_DET, Para); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Downshift detected, PhyIsrc: 0x%04X\n", PhyIsrc)); - } - - pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? - SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE; - - pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7); - - if (AutoNeg) { - /* Auto-Negotiation Over ? */ - if ((PhyStat & PHY_ST_AN_OVER) != 0) { - - SkHWLinkUp(pAC, IoC, Port); - - Done = SkMacAutoNegDone(pAC, IoC, Port); - - if (Done != SK_AND_OK) { - return(SK_HW_PS_RESTART); - } - - return(SK_HW_PS_LINK); - } - } - else { /* !AutoNeg */ - /* Link is up and we don't need more */ -#ifdef DEBUG - if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("ERROR: Lipa auto detected on port %d\n", Port)); - } -#endif /* DEBUG */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Link sync, Port %d\n", Port)); - SkHWLinkUp(pAC, IoC, Port); - - return(SK_HW_PS_LINK); - } - - return(SK_HW_PS_NONE); -} /* SkGePortCheckUpGmac */ -#endif /* YUKON */ - - -#ifdef OTHER_PHY -/****************************************************************************** - * - * SkGePortCheckUpLone() - Check if the link is up on Level One PHY - * - * return: - * 0 o.k. nothing needed - * 1 Restart needed on this port - * 2 Link came up - */ -static int SkGePortCheckUpLone( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port, /* Which port should be checked */ -SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - int Done; - SK_U16 Isrc; /* Interrupt source register */ - SK_U16 LpAb; /* Link Partner Ability */ - SK_U16 ExtStat; /* Extended Status Register */ - SK_U16 PhyStat; /* Phy Status Register */ - SK_U16 StatSum; - SK_U8 NextMode; /* Next AutoSensing Mode */ - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PHWLinkUp) { - return(SK_HW_PS_NONE); - } - - StatSum = pPrt->PIsave; - pPrt->PIsave = 0; - - /* - * here we usually can check whether the link is in sync and - * auto-negotiation is done. - */ - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_STAT, &PhyStat); - StatSum |= PhyStat; - - SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); - - if ((PhyStat & PHY_ST_LSYNC) == 0) { - /* Save Auto-negotiation Done bit */ - pPrt->PIsave = (SK_U16)(StatSum & PHY_ST_AN_OVER); -#ifdef DEBUG - if ((pPrt->PIsave & PHY_ST_AN_OVER) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg done rescheduled Port %d\n", Port)); - } -#endif /* DEBUG */ - return(SK_HW_PS_NONE); - } - - if (AutoNeg) { - if ((StatSum & PHY_ST_AN_OVER) != 0) { - SkHWLinkUp(pAC, IoC, Port); - Done = SkMacAutoNegDone(pAC, IoC, Port); - if (Done != SK_AND_OK) { - /* Get PHY parameters, for debugging only */ - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LpAb); - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ExtStat); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n", - Port, LpAb, ExtStat)); - - /* Try next possible mode */ - NextMode = SkHWSenseGetNext(pAC, IoC, Port); - SkHWLinkDown(pAC, IoC, Port); - if (Done == SK_AND_DUP_CAP) { - /* GoTo next mode */ - SkHWSenseSetNext(pAC, IoC, Port, NextMode); - } - - return(SK_HW_PS_RESTART); - - } - else { - /* - * Dummy Read interrupt status to prevent - * extra link down/ups - */ - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat); - return(SK_HW_PS_LINK); - } - } - - /* AutoNeg not done, but HW link is up. Check for timeouts */ - pPrt->PAutoNegTimeOut++; - if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) { - /* Timeout occured */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("AutoNeg timeout Port %d\n", Port)); - if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && - pPrt->PLipaAutoNeg != SK_LIPA_AUTO) { - /* Set Link manually up */ - SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Set manual full duplex Port %d\n", Port)); - } - - /* Do the restart */ - return(SK_HW_PS_RESTART); - } - } - else { - /* Link is up and we don't need more */ -#ifdef DEBUG - if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("ERROR: Lipa auto detected on port %d\n", Port)); - } -#endif /* DEBUG */ - - /* - * Dummy Read interrupt status to prevent - * extra link down/ups - */ - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Link sync(GP), Port %d\n", Port)); - SkHWLinkUp(pAC, IoC, Port); - - return(SK_HW_PS_LINK); - } - - return(SK_HW_PS_NONE); -} /* SkGePortCheckUpLone */ - - -/****************************************************************************** - * - * SkGePortCheckUpNat() - Check if the link is up on National PHY - * - * return: - * 0 o.k. nothing needed - * 1 Restart needed on this port - * 2 Link came up - */ -static int SkGePortCheckUpNat( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port, /* Which port should be checked */ -SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */ -{ - /* todo: National */ - return(SK_HW_PS_NONE); -} /* SkGePortCheckUpNat */ -#endif /* OTHER_PHY */ - - -/****************************************************************************** - * - * SkGeSirqEvent() - Event Service Routine - * - * Description: - * - * Notes: - */ -int SkGeSirqEvent( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* Io Context */ -SK_U32 Event, /* Module specific Event */ -SK_EVPARA Para) /* Event specific Parameter */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - SK_U32 Port; - SK_U32 Val32; - int PortStat; - SK_U8 Val8; -#ifdef GENESIS - SK_U64 Octets; -#endif /* GENESIS */ - - Port = Para.Para32[0]; - pPrt = &pAC->GIni.GP[Port]; - - switch (Event) { - case SK_HWEV_WATIM: - if (pPrt->PState == SK_PRT_RESET) { - - PortStat = SK_HW_PS_NONE; - } - else { - /* Check whether port came up */ - PortStat = SkGePortCheckUp(pAC, IoC, (int)Port); - } - - switch (PortStat) { - case SK_HW_PS_RESTART: - if (pPrt->PHWLinkUp) { - /* Set Link to down */ - SkHWLinkDown(pAC, IoC, (int)Port); - - /* - * Signal directly to RLMT to ensure correct - * sequence of SWITCH and RESET event. - */ - SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); - } - - /* Restart needed */ - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para); - break; - - case SK_HW_PS_LINK: - /* Signal to RLMT */ - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para); - break; - } - - /* Start again the check Timer */ - if (pPrt->PHWLinkUp) { - Val32 = SK_WA_ACT_TIME; - } - else { - Val32 = SK_WA_INA_TIME; - } - - /* Todo: still needed for non-XMAC PHYs??? */ - /* Start workaround Errata #2 timer */ - SkTimerStart(pAC, IoC, &pPrt->PWaTimer, Val32, - SKGE_HWAC, SK_HWEV_WATIM, Para); - break; - - case SK_HWEV_PORT_START: - if (pPrt->PHWLinkUp) { - /* - * Signal directly to RLMT to ensure correct - * sequence of SWITCH and RESET event. - */ - SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); - } - - SkHWLinkDown(pAC, IoC, (int)Port); - - /* Schedule Port RESET */ - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para); - - /* Start workaround Errata #2 timer */ - SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME, - SKGE_HWAC, SK_HWEV_WATIM, Para); - break; - - case SK_HWEV_PORT_STOP: - if (pPrt->PHWLinkUp) { - /* - * Signal directly to RLMT to ensure correct - * sequence of SWITCH and RESET event. - */ - SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); - } - - /* Stop Workaround Timer */ - SkTimerStop(pAC, IoC, &pPrt->PWaTimer); - - SkHWLinkDown(pAC, IoC, (int)Port); - break; - - case SK_HWEV_UPDATE_STAT: - /* We do NOT need to update any statistics */ - break; - - case SK_HWEV_CLEAR_STAT: - /* We do NOT need to clear any statistics */ - for (Port = 0; Port < (SK_U32)pAC->GIni.GIMacsFound; Port++) { - pPrt->PPrevRx = 0; - pPrt->PPrevFcs = 0; - pPrt->PPrevShorts = 0; - } - break; - - case SK_HWEV_SET_LMODE: - Val8 = (SK_U8)Para.Para32[1]; - if (pPrt->PLinkModeConf != Val8) { - /* Set New link mode */ - pPrt->PLinkModeConf = Val8; - - /* Restart Port */ - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); - } - break; - - case SK_HWEV_SET_FLOWMODE: - Val8 = (SK_U8)Para.Para32[1]; - if (pPrt->PFlowCtrlMode != Val8) { - /* Set New Flow Control mode */ - pPrt->PFlowCtrlMode = Val8; - - /* Restart Port */ - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); - } - break; - - case SK_HWEV_SET_ROLE: - /* not possible for fiber */ - if (!pAC->GIni.GICopperType) { - break; - } - Val8 = (SK_U8)Para.Para32[1]; - if (pPrt->PMSMode != Val8) { - /* Set New Role (Master/Slave) mode */ - pPrt->PMSMode = Val8; - - /* Restart Port */ - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); - } - break; - - case SK_HWEV_SET_SPEED: - if (pPrt->PhyType != SK_PHY_MARV_COPPER) { - break; - } - Val8 = (SK_U8)Para.Para32[1]; - if (pPrt->PLinkSpeed != Val8) { - /* Set New Speed parameter */ - pPrt->PLinkSpeed = Val8; - - /* Restart Port */ - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); - } - break; - -#ifdef GENESIS - case SK_HWEV_HALFDUP_CHK: - if (pAC->GIni.GIGenesis) { - /* - * half duplex hangup workaround. - * See packet arbiter timeout interrupt for description - */ - pPrt->HalfDupTimerActive = SK_FALSE; - if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || - pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) { - /* Snap statistic counters */ - (void)SkXmUpdateStats(pAC, IoC, Port); - - (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_HI, &Val32); - - Octets = (SK_U64)Val32 << 32; - - (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_LO, &Val32); - - Octets += Val32; - - if (pPrt->LastOctets == Octets) { - /* Tx hanging, a FIFO flush restarts it */ - SkMacFlushTxFifo(pAC, IoC, Port); - } - } - } - break; -#endif /* GENESIS */ - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG); - break; - } - - return(0); -} /* SkGeSirqEvent */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkPhyIsrBcom() - PHY interrupt service routine - * - * Description: handles all interrupts from BCom PHY - * - * Returns: N/A - */ -static void SkPhyIsrBcom( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* Io Context */ -int Port, /* Port Num = PHY Num */ -SK_U16 IStatus) /* Interrupt Status */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - SK_EVPARA Para; - - pPrt = &pAC->GIni.GP[Port]; - - if ((IStatus & PHY_B_IS_PSE) != 0) { - /* Incorrectable pair swap error */ - SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E022, - SKERR_SIRQ_E022MSG); - } - - if ((IStatus & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) != 0) { - - SkHWLinkDown(pAC, IoC, Port); - - Para.Para32[0] = (SK_U32)Port; - /* Signal to RLMT */ - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - - /* Start workaround Errata #2 timer */ - SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME, - SKGE_HWAC, SK_HWEV_WATIM, Para); - } - -} /* SkPhyIsrBcom */ -#endif /* GENESIS */ - - -#ifdef YUKON -/****************************************************************************** - * - * SkPhyIsrGmac() - PHY interrupt service routine - * - * Description: handles all interrupts from Marvell PHY - * - * Returns: N/A - */ -static void SkPhyIsrGmac( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* Io Context */ -int Port, /* Port Num = PHY Num */ -SK_U16 IStatus) /* Interrupt Status */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - SK_EVPARA Para; - SK_U16 Word; - - pPrt = &pAC->GIni.GP[Port]; - - if ((IStatus & (PHY_M_IS_AN_PR | PHY_M_IS_LST_CHANGE)) != 0) { - - SkHWLinkDown(pAC, IoC, Port); - - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &Word); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg.Adv: 0x%04X\n", Word)); - - /* Set Auto-negotiation advertisement */ - if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) { - /* restore Asymmetric Pause bit */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, - (SK_U16)(Word | PHY_M_AN_ASP)); - } - - Para.Para32[0] = (SK_U32)Port; - /* Signal to RLMT */ - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - if ((IStatus & PHY_M_IS_AN_ERROR) != 0) { - /* Auto-Negotiation Error */ - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG); - } - - if ((IStatus & PHY_M_IS_FIFO_ERROR) != 0) { - /* FIFO Overflow/Underrun Error */ - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E024, SKERR_SIRQ_E024MSG); - } - -} /* SkPhyIsrGmac */ -#endif /* YUKON */ - - -#ifdef OTHER_PHY -/****************************************************************************** - * - * SkPhyIsrLone() - PHY interrupt service routine - * - * Description: handles all interrupts from LONE PHY - * - * Returns: N/A - */ -static void SkPhyIsrLone( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* Io Context */ -int Port, /* Port Num = PHY Num */ -SK_U16 IStatus) /* Interrupt Status */ -{ - SK_EVPARA Para; - - if (IStatus & (PHY_L_IS_DUP | PHY_L_IS_ISOL)) { - - SkHWLinkDown(pAC, IoC, Port); - - Para.Para32[0] = (SK_U32)Port; - /* Signal to RLMT */ - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - -} /* SkPhyIsrLone */ -#endif /* OTHER_PHY */ - -/* End of File */ diff --git a/drivers/net/sk98lin/ski2c.c b/drivers/net/sk98lin/ski2c.c deleted file mode 100644 index 79bf57cb532..00000000000 --- a/drivers/net/sk98lin/ski2c.c +++ /dev/null @@ -1,1296 +0,0 @@ -/****************************************************************************** - * - * Name: ski2c.c - * Project: Gigabit Ethernet Adapters, TWSI-Module - * Version: $Revision: 1.59 $ - * Date: $Date: 2003/10/20 09:07:25 $ - * Purpose: Functions to access Voltage and Temperature Sensor - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - * I2C Protocol - */ -#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) -static const char SysKonnectFileId[] = - "@(#) $Id: ski2c.c,v 1.59 2003/10/20 09:07:25 rschmidt Exp $ (C) Marvell. "; -#endif - -#include "h/skdrv1st.h" /* Driver Specific Definitions */ -#include "h/lm80.h" -#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ - -#ifdef __C2MAN__ -/* - I2C protocol implementation. - - General Description: - - The I2C protocol is used for the temperature sensors and for - the serial EEPROM which hold the configuration. - - This file covers functions that allow to read write and do - some bulk requests a specified I2C address. - - The Genesis has 2 I2C buses. One for the EEPROM which holds - the VPD Data and one for temperature and voltage sensor. - The following picture shows the I2C buses, I2C devices and - their control registers. - - Note: The VPD functions are in skvpd.c -. -. PCI Config I2C Bus for VPD Data: -. -. +------------+ -. | VPD EEPROM | -. +------------+ -. | -. | <-- I2C -. | -. +-----------+-----------+ -. | | -. +-----------------+ +-----------------+ -. | PCI_VPD_ADR_REG | | PCI_VPD_DAT_REG | -. +-----------------+ +-----------------+ -. -. -. I2C Bus for LM80 sensor: -. -. +-----------------+ -. | Temperature and | -. | Voltage Sensor | -. | LM80 | -. +-----------------+ -. | -. | -. I2C --> | -. | -. +----+ -. +-------------->| OR |<--+ -. | +----+ | -. +------+------+ | -. | | | -. +--------+ +--------+ +----------+ -. | B2_I2C | | B2_I2C | | B2_I2C | -. | _CTRL | | _DATA | | _SW | -. +--------+ +--------+ +----------+ -. - The I2C bus may be driven by the B2_I2C_SW or by the B2_I2C_CTRL - and B2_I2C_DATA registers. - For driver software it is recommended to use the I2C control and - data register, because I2C bus timing is done by the ASIC and - an interrupt may be received when the I2C request is completed. - - Clock Rate Timing: MIN MAX generated by - VPD EEPROM: 50 kHz 100 kHz HW - LM80 over I2C Ctrl/Data reg. 50 kHz 100 kHz HW - LM80 over B2_I2C_SW register 0 400 kHz SW - - Note: The clock generated by the hardware is dependend on the - PCI clock. If the PCI bus clock is 33 MHz, the I2C/VPD - clock is 50 kHz. - */ -intro() -{} -#endif - -#ifdef SK_DIAG -/* - * I2C Fast Mode timing values used by the LM80. - * If new devices are added to the I2C bus the timing values have to be checked. - */ -#ifndef I2C_SLOW_TIMING -#define T_CLK_LOW 1300L /* clock low time in ns */ -#define T_CLK_HIGH 600L /* clock high time in ns */ -#define T_DATA_IN_SETUP 100L /* data in Set-up Time */ -#define T_START_HOLD 600L /* start condition hold time */ -#define T_START_SETUP 600L /* start condition Set-up time */ -#define T_STOP_SETUP 600L /* stop condition Set-up time */ -#define T_BUS_IDLE 1300L /* time the bus must free after Tx */ -#define T_CLK_2_DATA_OUT 900L /* max. clock low to data output valid */ -#else /* I2C_SLOW_TIMING */ -/* I2C Standard Mode Timing */ -#define T_CLK_LOW 4700L /* clock low time in ns */ -#define T_CLK_HIGH 4000L /* clock high time in ns */ -#define T_DATA_IN_SETUP 250L /* data in Set-up Time */ -#define T_START_HOLD 4000L /* start condition hold time */ -#define T_START_SETUP 4700L /* start condition Set-up time */ -#define T_STOP_SETUP 4000L /* stop condition Set-up time */ -#define T_BUS_IDLE 4700L /* time the bus must free after Tx */ -#endif /* !I2C_SLOW_TIMING */ - -#define NS2BCLK(x) (((x)*125)/10000) - -/* - * I2C Wire Operations - * - * About I2C_CLK_LOW(): - * - * The Data Direction bit (I2C_DATA_DIR) has to be set to input when setting - * clock to low, to prevent the ASIC and the I2C data client from driving the - * serial data line simultaneously (ASIC: last bit of a byte = '1', I2C client - * send an 'ACK'). See also Concentrator Bugreport No. 10192. - */ -#define I2C_DATA_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA) -#define I2C_DATA_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA) -#define I2C_DATA_OUT(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA_DIR) -#define I2C_DATA_IN(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA) -#define I2C_CLK_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_CLK) -#define I2C_CLK_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK | I2C_DATA_DIR) -#define I2C_START_COND(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK) - -#define NS2CLKT(x) ((x*125L)/10000) - -/*--------------- I2C Interface Register Functions --------------- */ - -/* - * sending one bit - */ -void SkI2cSndBit( -SK_IOC IoC, /* I/O Context */ -SK_U8 Bit) /* Bit to send */ -{ - I2C_DATA_OUT(IoC); - if (Bit) { - I2C_DATA_HIGH(IoC); - } - else { - I2C_DATA_LOW(IoC); - } - SkDgWaitTime(IoC, NS2BCLK(T_DATA_IN_SETUP)); - I2C_CLK_HIGH(IoC); - SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH)); - I2C_CLK_LOW(IoC); -} /* SkI2cSndBit*/ - - -/* - * Signal a start to the I2C Bus. - * - * A start is signaled when data goes to low in a high clock cycle. - * - * Ends with Clock Low. - * - * Status: not tested - */ -void SkI2cStart( -SK_IOC IoC) /* I/O Context */ -{ - /* Init data and Clock to output lines */ - /* Set Data high */ - I2C_DATA_OUT(IoC); - I2C_DATA_HIGH(IoC); - /* Set Clock high */ - I2C_CLK_HIGH(IoC); - - SkDgWaitTime(IoC, NS2BCLK(T_START_SETUP)); - - /* Set Data Low */ - I2C_DATA_LOW(IoC); - - SkDgWaitTime(IoC, NS2BCLK(T_START_HOLD)); - - /* Clock low without Data to Input */ - I2C_START_COND(IoC); - - SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW)); -} /* SkI2cStart */ - - -void SkI2cStop( -SK_IOC IoC) /* I/O Context */ -{ - /* Init data and Clock to output lines */ - /* Set Data low */ - I2C_DATA_OUT(IoC); - I2C_DATA_LOW(IoC); - - SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT)); - - /* Set Clock high */ - I2C_CLK_HIGH(IoC); - - SkDgWaitTime(IoC, NS2BCLK(T_STOP_SETUP)); - - /* - * Set Data High: Do it by setting the Data Line to Input. - * Because of a pull up resistor the Data Line - * floods to high. - */ - I2C_DATA_IN(IoC); - - /* - * When I2C activity is stopped - * o DATA should be set to input and - * o CLOCK should be set to high! - */ - SkDgWaitTime(IoC, NS2BCLK(T_BUS_IDLE)); -} /* SkI2cStop */ - - -/* - * Receive just one bit via the I2C bus. - * - * Note: Clock must be set to LOW before calling this function. - * - * Returns The received bit. - */ -int SkI2cRcvBit( -SK_IOC IoC) /* I/O Context */ -{ - int Bit; - SK_U8 I2cSwCtrl; - - /* Init data as input line */ - I2C_DATA_IN(IoC); - - SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT)); - - I2C_CLK_HIGH(IoC); - - SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH)); - - SK_I2C_GET_SW(IoC, &I2cSwCtrl); - - Bit = (I2cSwCtrl & I2C_DATA) ? 1 : 0; - - I2C_CLK_LOW(IoC); - SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW-T_CLK_2_DATA_OUT)); - - return(Bit); -} /* SkI2cRcvBit */ - - -/* - * Receive an ACK. - * - * returns 0 If acknowledged - * 1 in case of an error - */ -int SkI2cRcvAck( -SK_IOC IoC) /* I/O Context */ -{ - /* - * Received bit must be zero. - */ - return(SkI2cRcvBit(IoC) != 0); -} /* SkI2cRcvAck */ - - -/* - * Send an NACK. - */ -void SkI2cSndNAck( -SK_IOC IoC) /* I/O Context */ -{ - /* - * Received bit must be zero. - */ - SkI2cSndBit(IoC, 1); -} /* SkI2cSndNAck */ - - -/* - * Send an ACK. - */ -void SkI2cSndAck( -SK_IOC IoC) /* I/O Context */ -{ - /* - * Received bit must be zero. - */ - SkI2cSndBit(IoC, 0); -} /* SkI2cSndAck */ - - -/* - * Send one byte to the I2C device and wait for ACK. - * - * Return acknowleged status. - */ -int SkI2cSndByte( -SK_IOC IoC, /* I/O Context */ -int Byte) /* byte to send */ -{ - int i; - - for (i = 0; i < 8; i++) { - if (Byte & (1<<(7-i))) { - SkI2cSndBit(IoC, 1); - } - else { - SkI2cSndBit(IoC, 0); - } - } - - return(SkI2cRcvAck(IoC)); -} /* SkI2cSndByte */ - - -/* - * Receive one byte and ack it. - * - * Return byte. - */ -int SkI2cRcvByte( -SK_IOC IoC, /* I/O Context */ -int Last) /* Last Byte Flag */ -{ - int i; - int Byte = 0; - - for (i = 0; i < 8; i++) { - Byte <<= 1; - Byte |= SkI2cRcvBit(IoC); - } - - if (Last) { - SkI2cSndNAck(IoC); - } - else { - SkI2cSndAck(IoC); - } - - return(Byte); -} /* SkI2cRcvByte */ - - -/* - * Start dialog and send device address - * - * Return 0 if acknowleged, 1 in case of an error - */ -int SkI2cSndDev( -SK_IOC IoC, /* I/O Context */ -int Addr, /* Device Address */ -int Rw) /* Read / Write Flag */ -{ - SkI2cStart(IoC); - Rw = ~Rw; - Rw &= I2C_WRITE; - return(SkI2cSndByte(IoC, (Addr<<1) | Rw)); -} /* SkI2cSndDev */ - -#endif /* SK_DIAG */ - -/*----------------- I2C CTRL Register Functions ----------*/ - -/* - * waits for a completion of an I2C transfer - * - * returns 0: success, transfer completes - * 1: error, transfer does not complete, I2C transfer - * killed, wait loop terminated. - */ -static int SkI2cWait( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Event) /* complete event to wait for (I2C_READ or I2C_WRITE) */ -{ - SK_U64 StartTime; - SK_U64 CurrentTime; - SK_U32 I2cCtrl; - - StartTime = SkOsGetTime(pAC); - - do { - CurrentTime = SkOsGetTime(pAC); - - if (CurrentTime - StartTime > SK_TICKS_PER_SEC / 8) { - - SK_I2C_STOP(IoC); -#ifndef SK_DIAG - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E002, SKERR_I2C_E002MSG); -#endif /* !SK_DIAG */ - return(1); - } - - SK_I2C_GET_CTL(IoC, &I2cCtrl); - -#ifdef xYUKON_DBG - printf("StartTime=%lu, CurrentTime=%lu\n", - StartTime, CurrentTime); - if (kbhit()) { - return(1); - } -#endif /* YUKON_DBG */ - - } while ((I2cCtrl & I2C_FLAG) == (SK_U32)Event << 31); - - return(0); -} /* SkI2cWait */ - - -/* - * waits for a completion of an I2C transfer - * - * Returns - * Nothing - */ -void SkI2cWaitIrq( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC) /* I/O Context */ -{ - SK_SENSOR *pSen; - SK_U64 StartTime; - SK_U32 IrqSrc; - - pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; - - if (pSen->SenState == SK_SEN_IDLE) { - return; - } - - StartTime = SkOsGetTime(pAC); - - do { - if (SkOsGetTime(pAC) - StartTime > SK_TICKS_PER_SEC / 8) { - - SK_I2C_STOP(IoC); -#ifndef SK_DIAG - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E016, SKERR_I2C_E016MSG); -#endif /* !SK_DIAG */ - return; - } - - SK_IN32(IoC, B0_ISRC, &IrqSrc); - - } while ((IrqSrc & IS_I2C_READY) == 0); - - pSen->SenState = SK_SEN_IDLE; - return; -} /* SkI2cWaitIrq */ - -/* - * writes a single byte or 4 bytes into the I2C device - * - * returns 0: success - * 1: error - */ -static int SkI2cWrite( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 I2cData, /* I2C Data to write */ -int I2cDev, /* I2C Device Address */ -int I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */ -int I2cReg, /* I2C Device Register Address */ -int I2cBurst) /* I2C Burst Flag */ -{ - SK_OUT32(IoC, B2_I2C_DATA, I2cData); - - SK_I2C_CTL(IoC, I2C_WRITE, I2cDev, I2cDevSize, I2cReg, I2cBurst); - - return(SkI2cWait(pAC, IoC, I2C_WRITE)); -} /* SkI2cWrite*/ - - -#ifdef SK_DIAG -/* - * reads a single byte or 4 bytes from the I2C device - * - * returns the word read - */ -SK_U32 SkI2cRead( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int I2cDev, /* I2C Device Address */ -int I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */ -int I2cReg, /* I2C Device Register Address */ -int I2cBurst) /* I2C Burst Flag */ -{ - SK_U32 Data; - - SK_OUT32(IoC, B2_I2C_DATA, 0); - SK_I2C_CTL(IoC, I2C_READ, I2cDev, I2cDevSize, I2cReg, I2cBurst); - - if (SkI2cWait(pAC, IoC, I2C_READ) != 0) { - w_print("%s\n", SKERR_I2C_E002MSG); - } - - SK_IN32(IoC, B2_I2C_DATA, &Data); - - return(Data); -} /* SkI2cRead */ -#endif /* SK_DIAG */ - - -/* - * read a sensor's value - * - * This function reads a sensor's value from the I2C sensor chip. The sensor - * is defined by its index into the sensors database in the struct pAC points - * to. - * Returns - * 1 if the read is completed - * 0 if the read must be continued (I2C Bus still allocated) - */ -static int SkI2cReadSensor( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_SENSOR *pSen) /* Sensor to be read */ -{ - if (pSen->SenRead != NULL) { - return((*pSen->SenRead)(pAC, IoC, pSen)); - } - else { - return(0); /* no success */ - } -} /* SkI2cReadSensor */ - -/* - * Do the Init state 0 initialization - */ -static int SkI2cInit0( -SK_AC *pAC) /* Adapter Context */ -{ - int i; - - /* Begin with first sensor */ - pAC->I2c.CurrSens = 0; - - /* Begin with timeout control for state machine */ - pAC->I2c.TimerMode = SK_TIMER_WATCH_SM; - - /* Set sensor number to zero */ - pAC->I2c.MaxSens = 0; - -#ifndef SK_DIAG - /* Initialize Number of Dummy Reads */ - pAC->I2c.DummyReads = SK_MAX_SENSORS; -#endif - - for (i = 0; i < SK_MAX_SENSORS; i++) { - pAC->I2c.SenTable[i].SenDesc = "unknown"; - pAC->I2c.SenTable[i].SenType = SK_SEN_UNKNOWN; - pAC->I2c.SenTable[i].SenThreErrHigh = 0; - pAC->I2c.SenTable[i].SenThreErrLow = 0; - pAC->I2c.SenTable[i].SenThreWarnHigh = 0; - pAC->I2c.SenTable[i].SenThreWarnLow = 0; - pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN; - pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_NONE; - pAC->I2c.SenTable[i].SenValue = 0; - pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_NOT_PRESENT; - pAC->I2c.SenTable[i].SenErrCts = 0; - pAC->I2c.SenTable[i].SenBegErrTS = 0; - pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE; - pAC->I2c.SenTable[i].SenRead = NULL; - pAC->I2c.SenTable[i].SenDev = 0; - } - - /* Now we are "INIT data"ed */ - pAC->I2c.InitLevel = SK_INIT_DATA; - return(0); -} /* SkI2cInit0*/ - - -/* - * Do the init state 1 initialization - * - * initialize the following register of the LM80: - * Configuration register: - * - START, noINT, activeLOW, noINT#Clear, noRESET, noCI, noGPO#, noINIT - * - * Interrupt Mask Register 1: - * - all interrupts are Disabled (0xff) - * - * Interrupt Mask Register 2: - * - all interrupts are Disabled (0xff) Interrupt modi doesn't matter. - * - * Fan Divisor/RST_OUT register: - * - Divisors set to 1 (bits 00), all others 0s. - * - * OS# Configuration/Temperature resolution Register: - * - all 0s - * - */ -static int SkI2cInit1( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC) /* I/O Context */ -{ - int i; - SK_U8 I2cSwCtrl; - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - - if (pAC->I2c.InitLevel != SK_INIT_DATA) { - /* ReInit not needed in I2C module */ - return(0); - } - - /* Set the Direction of I2C-Data Pin to IN */ - SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA); - /* Check for 32-Bit Yukon with Low at I2C-Data Pin */ - SK_I2C_GET_SW(IoC, &I2cSwCtrl); - - if ((I2cSwCtrl & I2C_DATA) == 0) { - /* this is a 32-Bit board */ - pAC->GIni.GIYukon32Bit = SK_TRUE; - return(0); - } - - /* Check for 64 Bit Yukon without sensors */ - if (SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_CFG, 0) != 0) { - return(0); - } - - (void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_1, 0); - - (void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_2, 0); - - (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_FAN_CTRL, 0); - - (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_TEMP_CTRL, 0); - - (void)SkI2cWrite(pAC, IoC, (SK_U32)LM80_CFG_START, LM80_ADDR, I2C_025K_DEV, - LM80_CFG, 0); - - /* - * MaxSens has to be updated here, because PhyType is not - * set when performing Init Level 0 - */ - pAC->I2c.MaxSens = 5; - - pPrt = &pAC->GIni.GP[0]; - - if (pAC->GIni.GIGenesis) { - if (pPrt->PhyType == SK_PHY_BCOM) { - if (pAC->GIni.GIMacsFound == 1) { - pAC->I2c.MaxSens += 1; - } - else { - pAC->I2c.MaxSens += 3; - } - } - } - else { - pAC->I2c.MaxSens += 3; - } - - for (i = 0; i < pAC->I2c.MaxSens; i++) { - switch (i) { - case 0: - pAC->I2c.SenTable[i].SenDesc = "Temperature"; - pAC->I2c.SenTable[i].SenType = SK_SEN_TEMP; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_TEMP_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_TEMP_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_TEMP_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_TEMP_LOW_ERR; - pAC->I2c.SenTable[i].SenReg = LM80_TEMP_IN; - break; - case 1: - pAC->I2c.SenTable[i].SenDesc = "Voltage PCI"; - pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_5V_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_5V_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_5V_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_5V_LOW_ERR; - pAC->I2c.SenTable[i].SenReg = LM80_VT0_IN; - break; - case 2: - pAC->I2c.SenTable[i].SenDesc = "Voltage PCI-IO"; - pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_IO_5V_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_IO_5V_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_IO_3V3_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_IO_3V3_LOW_ERR; - pAC->I2c.SenTable[i].SenReg = LM80_VT1_IN; - pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_PCI_IO; - break; - case 3: - pAC->I2c.SenTable[i].SenDesc = "Voltage ASIC"; - pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VDD_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VDD_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VDD_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VDD_LOW_ERR; - pAC->I2c.SenTable[i].SenReg = LM80_VT2_IN; - break; - case 4: - if (pAC->GIni.GIGenesis) { - if (pPrt->PhyType == SK_PHY_BCOM) { - pAC->I2c.SenTable[i].SenDesc = "Voltage PHY A PLL"; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR; - } - else { - pAC->I2c.SenTable[i].SenDesc = "Voltage PMA"; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR; - } - } - else { - pAC->I2c.SenTable[i].SenDesc = "Voltage VAUX"; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VAUX_3V3_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VAUX_3V3_HIGH_WARN; - if (pAC->GIni.GIVauxAvail) { - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR; - } - else { - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_0V_WARN_ERR; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_0V_WARN_ERR; - } - } - pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; - pAC->I2c.SenTable[i].SenReg = LM80_VT3_IN; - break; - case 5: - if (pAC->GIni.GIGenesis) { - pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5"; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR; - } - else { - pAC->I2c.SenTable[i].SenDesc = "Voltage Core 1V5"; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_CORE_1V5_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_CORE_1V5_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_CORE_1V5_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_CORE_1V5_LOW_ERR; - } - pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; - pAC->I2c.SenTable[i].SenReg = LM80_VT4_IN; - break; - case 6: - if (pAC->GIni.GIGenesis) { - pAC->I2c.SenTable[i].SenDesc = "Voltage PHY B PLL"; - } - else { - pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 3V3"; - } - pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR; - pAC->I2c.SenTable[i].SenReg = LM80_VT5_IN; - break; - case 7: - if (pAC->GIni.GIGenesis) { - pAC->I2c.SenTable[i].SenDesc = "Speed Fan"; - pAC->I2c.SenTable[i].SenType = SK_SEN_FAN; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_FAN_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_FAN_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_FAN_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_FAN_LOW_ERR; - pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN; - } - else { - pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5"; - pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR; - pAC->I2c.SenTable[i].SenReg = LM80_VT6_IN; - } - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_INIT | SK_ERRCL_SW, - SKERR_I2C_E001, SKERR_I2C_E001MSG); - break; - } - - pAC->I2c.SenTable[i].SenValue = 0; - pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK; - pAC->I2c.SenTable[i].SenErrCts = 0; - pAC->I2c.SenTable[i].SenBegErrTS = 0; - pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE; - pAC->I2c.SenTable[i].SenRead = SkLm80ReadSensor; - pAC->I2c.SenTable[i].SenDev = LM80_ADDR; - } - -#ifndef SK_DIAG - pAC->I2c.DummyReads = pAC->I2c.MaxSens; -#endif /* !SK_DIAG */ - - /* Clear I2C IRQ */ - SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); - - /* Now we are I/O initialized */ - pAC->I2c.InitLevel = SK_INIT_IO; - return(0); -} /* SkI2cInit1 */ - - -/* - * Init level 2: Start first sensor read. - */ -static int SkI2cInit2( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC) /* I/O Context */ -{ - int ReadComplete; - SK_SENSOR *pSen; - - if (pAC->I2c.InitLevel != SK_INIT_IO) { - /* ReInit not needed in I2C module */ - /* Init0 and Init2 not permitted */ - return(0); - } - - pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; - ReadComplete = SkI2cReadSensor(pAC, IoC, pSen); - - if (ReadComplete) { - SK_ERR_LOG(pAC, SK_ERRCL_INIT, SKERR_I2C_E008, SKERR_I2C_E008MSG); - } - - /* Now we are correctly initialized */ - pAC->I2c.InitLevel = SK_INIT_RUN; - - return(0); -} /* SkI2cInit2*/ - - -/* - * Initialize I2C devices - * - * Get the first voltage value and discard it. - * Go into temperature read mode. A default pointer is not set. - * - * The things to be done depend on the init level in the parameter list: - * Level 0: - * Initialize only the data structures. Do NOT access hardware. - * Level 1: - * Initialize hardware through SK_IN / SK_OUT commands. Do NOT use interrupts. - * Level 2: - * Everything is possible. Interrupts may be used from now on. - * - * return: - * 0 = success - * other = error. - */ -int SkI2cInit( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context needed in levels 1 and 2 */ -int Level) /* Init Level */ -{ - - switch (Level) { - case SK_INIT_DATA: - return(SkI2cInit0(pAC)); - case SK_INIT_IO: - return(SkI2cInit1(pAC, IoC)); - case SK_INIT_RUN: - return(SkI2cInit2(pAC, IoC)); - default: - break; - } - - return(0); -} /* SkI2cInit */ - - -#ifndef SK_DIAG - -/* - * Interrupt service function for the I2C Interface - * - * Clears the Interrupt source - * - * Reads the register and check it for sending a trap. - * - * Starts the timer if necessary. - */ -void SkI2cIsr( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC) /* I/O Context */ -{ - SK_EVPARA Para; - - /* Clear I2C IRQ */ - SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); - - Para.Para64 = 0; - SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_IRQ, Para); -} /* SkI2cIsr */ - - -/* - * Check this sensors Value against the threshold and send events. - */ -static void SkI2cCheckSensor( -SK_AC *pAC, /* Adapter Context */ -SK_SENSOR *pSen) -{ - SK_EVPARA ParaLocal; - SK_BOOL TooHigh; /* Is sensor too high? */ - SK_BOOL TooLow; /* Is sensor too low? */ - SK_U64 CurrTime; /* Current Time */ - SK_BOOL DoTrapSend; /* We need to send a trap */ - SK_BOOL DoErrLog; /* We need to log the error */ - SK_BOOL IsError; /* We need to log the error */ - - /* Check Dummy Reads first */ - if (pAC->I2c.DummyReads > 0) { - pAC->I2c.DummyReads--; - return; - } - - /* Get the current time */ - CurrTime = SkOsGetTime(pAC); - - /* Set para to the most useful setting: The current sensor. */ - ParaLocal.Para64 = (SK_U64)pAC->I2c.CurrSens; - - /* Check the Value against the thresholds. First: Error Thresholds */ - TooHigh = (pSen->SenValue > pSen->SenThreErrHigh); - TooLow = (pSen->SenValue < pSen->SenThreErrLow); - - IsError = SK_FALSE; - if (TooHigh || TooLow) { - /* Error condition is satisfied */ - DoTrapSend = SK_TRUE; - DoErrLog = SK_TRUE; - - /* Now error condition is satisfied */ - IsError = SK_TRUE; - - if (pSen->SenErrFlag == SK_SEN_ERR_ERR) { - /* This state is the former one */ - - /* So check first whether we have to send a trap */ - if (pSen->SenLastErrTrapTS + SK_SEN_ERR_TR_HOLD > - CurrTime) { - /* - * Do NOT send the Trap. The hold back time - * has to run out first. - */ - DoTrapSend = SK_FALSE; - } - - /* Check now whether we have to log an Error */ - if (pSen->SenLastErrLogTS + SK_SEN_ERR_LOG_HOLD > - CurrTime) { - /* - * Do NOT log the error. The hold back time - * has to run out first. - */ - DoErrLog = SK_FALSE; - } - } - else { - /* We came from a different state -> Set Begin Time Stamp */ - pSen->SenBegErrTS = CurrTime; - pSen->SenErrFlag = SK_SEN_ERR_ERR; - } - - if (DoTrapSend) { - /* Set current Time */ - pSen->SenLastErrTrapTS = CurrTime; - pSen->SenErrCts++; - - /* Queue PNMI Event */ - SkEventQueue(pAC, SKGE_PNMI, (TooHigh ? - SK_PNMI_EVT_SEN_ERR_UPP : - SK_PNMI_EVT_SEN_ERR_LOW), - ParaLocal); - } - - if (DoErrLog) { - /* Set current Time */ - pSen->SenLastErrLogTS = CurrTime; - - if (pSen->SenType == SK_SEN_TEMP) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E011, SKERR_I2C_E011MSG); - } - else if (pSen->SenType == SK_SEN_VOLT) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E012, SKERR_I2C_E012MSG); - } - else { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E015, SKERR_I2C_E015MSG); - } - } - } - - /* Check the Value against the thresholds */ - /* 2nd: Warning thresholds */ - TooHigh = (pSen->SenValue > pSen->SenThreWarnHigh); - TooLow = (pSen->SenValue < pSen->SenThreWarnLow); - - if (!IsError && (TooHigh || TooLow)) { - /* Error condition is satisfied */ - DoTrapSend = SK_TRUE; - DoErrLog = SK_TRUE; - - if (pSen->SenErrFlag == SK_SEN_ERR_WARN) { - /* This state is the former one */ - - /* So check first whether we have to send a trap */ - if (pSen->SenLastWarnTrapTS + SK_SEN_WARN_TR_HOLD > CurrTime) { - /* - * Do NOT send the Trap. The hold back time - * has to run out first. - */ - DoTrapSend = SK_FALSE; - } - - /* Check now whether we have to log an Error */ - if (pSen->SenLastWarnLogTS + SK_SEN_WARN_LOG_HOLD > CurrTime) { - /* - * Do NOT log the error. The hold back time - * has to run out first. - */ - DoErrLog = SK_FALSE; - } - } - else { - /* We came from a different state -> Set Begin Time Stamp */ - pSen->SenBegWarnTS = CurrTime; - pSen->SenErrFlag = SK_SEN_ERR_WARN; - } - - if (DoTrapSend) { - /* Set current Time */ - pSen->SenLastWarnTrapTS = CurrTime; - pSen->SenWarnCts++; - - /* Queue PNMI Event */ - SkEventQueue(pAC, SKGE_PNMI, (TooHigh ? - SK_PNMI_EVT_SEN_WAR_UPP : - SK_PNMI_EVT_SEN_WAR_LOW), - ParaLocal); - } - - if (DoErrLog) { - /* Set current Time */ - pSen->SenLastWarnLogTS = CurrTime; - - if (pSen->SenType == SK_SEN_TEMP) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E009, SKERR_I2C_E009MSG); - } - else if (pSen->SenType == SK_SEN_VOLT) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E010, SKERR_I2C_E010MSG); - } - else { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E014, SKERR_I2C_E014MSG); - } - } - } - - /* Check for NO error at all */ - if (!IsError && !TooHigh && !TooLow) { - /* Set o.k. Status if no error and no warning condition */ - pSen->SenErrFlag = SK_SEN_ERR_OK; - } - - /* End of check against the thresholds */ - - /* Bug fix AF: 16.Aug.2001: Correct the init base - * of LM80 sensor. - */ - if (pSen->SenInit == SK_SEN_DYN_INIT_PCI_IO) { - - pSen->SenInit = SK_SEN_DYN_INIT_NONE; - - if (pSen->SenValue > SK_SEN_PCI_IO_RANGE_LIMITER) { - /* 5V PCI-IO Voltage */ - pSen->SenThreWarnLow = SK_SEN_PCI_IO_5V_LOW_WARN; - pSen->SenThreErrLow = SK_SEN_PCI_IO_5V_LOW_ERR; - } - else { - /* 3.3V PCI-IO Voltage */ - pSen->SenThreWarnHigh = SK_SEN_PCI_IO_3V3_HIGH_WARN; - pSen->SenThreErrHigh = SK_SEN_PCI_IO_3V3_HIGH_ERR; - } - } - -#ifdef TEST_ONLY - /* Dynamic thresholds also for VAUX of LM80 sensor */ - if (pSen->SenInit == SK_SEN_DYN_INIT_VAUX) { - - pSen->SenInit = SK_SEN_DYN_INIT_NONE; - - /* 3.3V VAUX Voltage */ - if (pSen->SenValue > SK_SEN_VAUX_RANGE_LIMITER) { - pSen->SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN; - pSen->SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR; - } - /* 0V VAUX Voltage */ - else { - pSen->SenThreWarnHigh = SK_SEN_VAUX_0V_WARN_ERR; - pSen->SenThreErrHigh = SK_SEN_VAUX_0V_WARN_ERR; - } - } - - /* - * Check initialization state: - * The VIO Thresholds need adaption - */ - if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN && - pSen->SenValue > SK_SEN_WARNLOW2C && - pSen->SenValue < SK_SEN_WARNHIGH2) { - pSen->SenThreErrLow = SK_SEN_ERRLOW2C; - pSen->SenThreWarnLow = SK_SEN_WARNLOW2C; - pSen->SenInit = SK_TRUE; - } - - if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN && - pSen->SenValue > SK_SEN_WARNLOW2 && - pSen->SenValue < SK_SEN_WARNHIGH2C) { - pSen->SenThreErrHigh = SK_SEN_ERRHIGH2C; - pSen->SenThreWarnHigh = SK_SEN_WARNHIGH2C; - pSen->SenInit = SK_TRUE; - } -#endif - - if (pSen->SenInit != SK_SEN_DYN_INIT_NONE) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E013, SKERR_I2C_E013MSG); - } -} /* SkI2cCheckSensor */ - - -/* - * The only Event to be served is the timeout event - * - */ -int SkI2cEvent( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Event, /* Module specific Event */ -SK_EVPARA Para) /* Event specific Parameter */ -{ - int ReadComplete; - SK_SENSOR *pSen; - SK_U32 Time; - SK_EVPARA ParaLocal; - int i; - - /* New case: no sensors */ - if (pAC->I2c.MaxSens == 0) { - return(0); - } - - switch (Event) { - case SK_I2CEV_IRQ: - pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; - ReadComplete = SkI2cReadSensor(pAC, IoC, pSen); - - if (ReadComplete) { - /* Check sensor against defined thresholds */ - SkI2cCheckSensor(pAC, pSen); - - /* Increment Current sensor and set appropriate Timeout */ - pAC->I2c.CurrSens++; - if (pAC->I2c.CurrSens >= pAC->I2c.MaxSens) { - pAC->I2c.CurrSens = 0; - Time = SK_I2C_TIM_LONG; - } - else { - Time = SK_I2C_TIM_SHORT; - } - - /* Start Timer */ - ParaLocal.Para64 = (SK_U64)0; - - pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING; - - SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time, - SKGE_I2C, SK_I2CEV_TIM, ParaLocal); - } - else { - /* Start Timer */ - ParaLocal.Para64 = (SK_U64)0; - - pAC->I2c.TimerMode = SK_TIMER_WATCH_SM; - - SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, SK_I2C_TIM_WATCH, - SKGE_I2C, SK_I2CEV_TIM, ParaLocal); - } - break; - case SK_I2CEV_TIM: - if (pAC->I2c.TimerMode == SK_TIMER_NEW_GAUGING) { - - ParaLocal.Para64 = (SK_U64)0; - SkTimerStop(pAC, IoC, &pAC->I2c.SenTimer); - - pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; - ReadComplete = SkI2cReadSensor(pAC, IoC, pSen); - - if (ReadComplete) { - /* Check sensor against defined thresholds */ - SkI2cCheckSensor(pAC, pSen); - - /* Increment Current sensor and set appropriate Timeout */ - pAC->I2c.CurrSens++; - if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) { - pAC->I2c.CurrSens = 0; - Time = SK_I2C_TIM_LONG; - } - else { - Time = SK_I2C_TIM_SHORT; - } - - /* Start Timer */ - ParaLocal.Para64 = (SK_U64)0; - - pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING; - - SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time, - SKGE_I2C, SK_I2CEV_TIM, ParaLocal); - } - } - else { - pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; - pSen->SenErrFlag = SK_SEN_ERR_FAULTY; - SK_I2C_STOP(IoC); - - /* Increment Current sensor and set appropriate Timeout */ - pAC->I2c.CurrSens++; - if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) { - pAC->I2c.CurrSens = 0; - Time = SK_I2C_TIM_LONG; - } - else { - Time = SK_I2C_TIM_SHORT; - } - - /* Start Timer */ - ParaLocal.Para64 = (SK_U64)0; - - pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING; - - SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time, - SKGE_I2C, SK_I2CEV_TIM, ParaLocal); - } - break; - case SK_I2CEV_CLEAR: - for (i = 0; i < SK_MAX_SENSORS; i++) { - pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK; - pAC->I2c.SenTable[i].SenErrCts = 0; - pAC->I2c.SenTable[i].SenWarnCts = 0; - pAC->I2c.SenTable[i].SenBegErrTS = 0; - pAC->I2c.SenTable[i].SenBegWarnTS = 0; - pAC->I2c.SenTable[i].SenLastErrTrapTS = (SK_U64)0; - pAC->I2c.SenTable[i].SenLastErrLogTS = (SK_U64)0; - pAC->I2c.SenTable[i].SenLastWarnTrapTS = (SK_U64)0; - pAC->I2c.SenTable[i].SenLastWarnLogTS = (SK_U64)0; - } - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E006, SKERR_I2C_E006MSG); - } - - return(0); -} /* SkI2cEvent*/ - -#endif /* !SK_DIAG */ diff --git a/drivers/net/sk98lin/sklm80.c b/drivers/net/sk98lin/sklm80.c deleted file mode 100644 index a204f5bb55d..00000000000 --- a/drivers/net/sk98lin/sklm80.c +++ /dev/null @@ -1,141 +0,0 @@ -/****************************************************************************** - * - * Name: sklm80.c - * Project: Gigabit Ethernet Adapters, TWSI-Module - * Version: $Revision: 1.22 $ - * Date: $Date: 2003/10/20 09:08:21 $ - * Purpose: Functions to access Voltage and Temperature Sensor (LM80) - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - LM80 functions -*/ -#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) -static const char SysKonnectFileId[] = - "@(#) $Id: sklm80.c,v 1.22 2003/10/20 09:08:21 rschmidt Exp $ (C) Marvell. "; -#endif - -#include "h/skdrv1st.h" /* Driver Specific Definitions */ -#include "h/lm80.h" -#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ - -#define BREAK_OR_WAIT(pAC,IoC,Event) break - -/* - * read a sensors value (LM80 specific) - * - * This function reads a sensors value from the I2C sensor chip LM80. - * The sensor is defined by its index into the sensors database in the struct - * pAC points to. - * - * Returns 1 if the read is completed - * 0 if the read must be continued (I2C Bus still allocated) - */ -int SkLm80ReadSensor( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context needed in level 1 and 2 */ -SK_SENSOR *pSen) /* Sensor to be read */ -{ - SK_I32 Value; - - switch (pSen->SenState) { - case SK_SEN_IDLE: - /* Send address to ADDR register */ - SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, pSen->SenReg, 0); - - pSen->SenState = SK_SEN_VALUE ; - BREAK_OR_WAIT(pAC, IoC, I2C_READ); - - case SK_SEN_VALUE: - /* Read value from data register */ - SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value)); - - Value &= 0xff; /* only least significant byte is valid */ - - /* Do NOT check the Value against the thresholds */ - /* Checking is done in the calling instance */ - - if (pSen->SenType == SK_SEN_VOLT) { - /* Voltage sensor */ - pSen->SenValue = Value * SK_LM80_VT_LSB; - pSen->SenState = SK_SEN_IDLE ; - return(1); - } - - if (pSen->SenType == SK_SEN_FAN) { - if (Value != 0 && Value != 0xff) { - /* Fan speed counter */ - pSen->SenValue = SK_LM80_FAN_FAKTOR/Value; - } - else { - /* Indicate Fan error */ - pSen->SenValue = 0; - } - pSen->SenState = SK_SEN_IDLE ; - return(1); - } - - /* First: correct the value: it might be negative */ - if ((Value & 0x80) != 0) { - /* Value is negative */ - Value = Value - 256; - } - - /* We have a temperature sensor and need to get the signed extension. - * For now we get the extension from the last reading, so in the normal - * case we won't see flickering temperatures. - */ - pSen->SenValue = (Value * SK_LM80_TEMP_LSB) + - (pSen->SenValue % SK_LM80_TEMP_LSB); - - /* Send address to ADDR register */ - SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, LM80_TEMP_CTRL, 0); - - pSen->SenState = SK_SEN_VALEXT ; - BREAK_OR_WAIT(pAC, IoC, I2C_READ); - - case SK_SEN_VALEXT: - /* Read value from data register */ - SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value)); - Value &= LM80_TEMP_LSB_9; /* only bit 7 is valid */ - - /* cut the LSB bit */ - pSen->SenValue = ((pSen->SenValue / SK_LM80_TEMP_LSB) * - SK_LM80_TEMP_LSB); - - if (pSen->SenValue < 0) { - /* Value negative: The bit value must be subtracted */ - pSen->SenValue -= ((Value >> 7) * SK_LM80_TEMPEXT_LSB); - } - else { - /* Value positive: The bit value must be added */ - pSen->SenValue += ((Value >> 7) * SK_LM80_TEMPEXT_LSB); - } - - pSen->SenState = SK_SEN_IDLE ; - return(1); - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E007, SKERR_I2C_E007MSG); - return(1); - } - - /* Not completed */ - return(0); -} - diff --git a/drivers/net/sk98lin/skqueue.c b/drivers/net/sk98lin/skqueue.c deleted file mode 100644 index 0275b4f71d9..00000000000 --- a/drivers/net/sk98lin/skqueue.c +++ /dev/null @@ -1,179 +0,0 @@ -/****************************************************************************** - * - * Name: skqueue.c - * Project: Gigabit Ethernet Adapters, Event Scheduler Module - * Version: $Revision: 1.20 $ - * Date: $Date: 2003/09/16 13:44:00 $ - * Purpose: Management of an event queue. - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - - -/* - * Event queue and dispatcher - */ -#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) -static const char SysKonnectFileId[] = - "@(#) $Id: skqueue.c,v 1.20 2003/09/16 13:44:00 rschmidt Exp $ (C) Marvell."; -#endif - -#include "h/skdrv1st.h" /* Driver Specific Definitions */ -#include "h/skqueue.h" /* Queue Definitions */ -#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ - -#ifdef __C2MAN__ -/* - Event queue management. - - General Description: - - */ -intro() -{} -#endif - -#define PRINTF(a,b,c) - -/* - * init event queue management - * - * Must be called during init level 0. - */ -void SkEventInit( -SK_AC *pAC, /* Adapter context */ -SK_IOC Ioc, /* IO context */ -int Level) /* Init level */ -{ - switch (Level) { - case SK_INIT_DATA: - pAC->Event.EvPut = pAC->Event.EvGet = pAC->Event.EvQueue; - break; - default: - break; - } -} - -/* - * add event to queue - */ -void SkEventQueue( -SK_AC *pAC, /* Adapters context */ -SK_U32 Class, /* Event Class */ -SK_U32 Event, /* Event to be queued */ -SK_EVPARA Para) /* Event parameter */ -{ - pAC->Event.EvPut->Class = Class; - pAC->Event.EvPut->Event = Event; - pAC->Event.EvPut->Para = Para; - - if (++pAC->Event.EvPut == &pAC->Event.EvQueue[SK_MAX_EVENT]) - pAC->Event.EvPut = pAC->Event.EvQueue; - - if (pAC->Event.EvPut == pAC->Event.EvGet) { - SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E001, SKERR_Q_E001MSG); - } -} - -/* - * event dispatcher - * while event queue is not empty - * get event from queue - * send command to state machine - * end - * return error reported by individual Event function - * 0 if no error occured. - */ -int SkEventDispatcher( -SK_AC *pAC, /* Adapters Context */ -SK_IOC Ioc) /* Io context */ -{ - SK_EVENTELEM *pEv; /* pointer into queue */ - SK_U32 Class; - int Rtv; - - pEv = pAC->Event.EvGet; - - PRINTF("dispatch get %x put %x\n", pEv, pAC->Event.ev_put); - - while (pEv != pAC->Event.EvPut) { - PRINTF("dispatch Class %d Event %d\n", pEv->Class, pEv->Event); - - switch (Class = pEv->Class) { -#ifndef SK_USE_LAC_EV -#ifndef SK_SLIM - case SKGE_RLMT: /* RLMT Event */ - Rtv = SkRlmtEvent(pAC, Ioc, pEv->Event, pEv->Para); - break; - case SKGE_I2C: /* I2C Event */ - Rtv = SkI2cEvent(pAC, Ioc, pEv->Event, pEv->Para); - break; - case SKGE_PNMI: /* PNMI Event */ - Rtv = SkPnmiEvent(pAC, Ioc, pEv->Event, pEv->Para); - break; -#endif /* not SK_SLIM */ -#endif /* not SK_USE_LAC_EV */ - case SKGE_DRV: /* Driver Event */ - Rtv = SkDrvEvent(pAC, Ioc, pEv->Event, pEv->Para); - break; -#ifndef SK_USE_SW_TIMER - case SKGE_HWAC: - Rtv = SkGeSirqEvent(pAC, Ioc, pEv->Event, pEv->Para); - break; -#else /* !SK_USE_SW_TIMER */ - case SKGE_SWT : - Rtv = SkSwtEvent(pAC, Ioc, pEv->Event, pEv->Para); - break; -#endif /* !SK_USE_SW_TIMER */ -#ifdef SK_USE_LAC_EV - case SKGE_LACP : - Rtv = SkLacpEvent(pAC, Ioc, pEv->Event, pEv->Para); - break; - case SKGE_RSF : - Rtv = SkRsfEvent(pAC, Ioc, pEv->Event, pEv->Para); - break; - case SKGE_MARKER : - Rtv = SkMarkerEvent(pAC, Ioc, pEv->Event, pEv->Para); - break; - case SKGE_FD : - Rtv = SkFdEvent(pAC, Ioc, pEv->Event, pEv->Para); - break; -#endif /* SK_USE_LAC_EV */ -#ifdef SK_USE_CSUM - case SKGE_CSUM : - Rtv = SkCsEvent(pAC, Ioc, pEv->Event, pEv->Para); - break; -#endif /* SK_USE_CSUM */ - default : - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_Q_E002, SKERR_Q_E002MSG); - Rtv = 0; - } - - if (Rtv != 0) { - return(Rtv); - } - - if (++pEv == &pAC->Event.EvQueue[SK_MAX_EVENT]) - pEv = pAC->Event.EvQueue; - - /* Renew get: it is used in queue_events to detect overruns */ - pAC->Event.EvGet = pEv; - } - - return(0); -} - -/* End of file */ diff --git a/drivers/net/sk98lin/skrlmt.c b/drivers/net/sk98lin/skrlmt.c deleted file mode 100644 index be8d1ccddf6..00000000000 --- a/drivers/net/sk98lin/skrlmt.c +++ /dev/null @@ -1,3257 +0,0 @@ -/****************************************************************************** - * - * Name: skrlmt.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.69 $ - * Date: $Date: 2003/04/15 09:39:22 $ - * Purpose: Manage links on SK-NET Adapters, esp. redundant ones. - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This module contains code for Link ManagemenT (LMT) of SK-NET Adapters. - * It is mainly intended for adapters with more than one link. - * For such adapters, this module realizes Redundant Link ManagemenT (RLMT). - * - * Include File Hierarchy: - * - * "skdrv1st.h" - * "skdrv2nd.h" - * - ******************************************************************************/ - -#ifndef lint -static const char SysKonnectFileId[] = - "@(#) $Id: skrlmt.c,v 1.69 2003/04/15 09:39:22 tschilli Exp $ (C) Marvell."; -#endif /* !defined(lint) */ - -#define __SKRLMT_C - -#ifdef __cplusplus -extern "C" { -#endif /* cplusplus */ - -#include "h/skdrv1st.h" -#include "h/skdrv2nd.h" - -/* defines ********************************************************************/ - -#ifndef SK_HWAC_LINK_LED -#define SK_HWAC_LINK_LED(a,b,c,d) -#endif /* !defined(SK_HWAC_LINK_LED) */ - -#ifndef DEBUG -#define RLMT_STATIC static -#else /* DEBUG */ -#define RLMT_STATIC - -#ifndef SK_LITTLE_ENDIAN -/* First 32 bits */ -#define OFFS_LO32 1 - -/* Second 32 bits */ -#define OFFS_HI32 0 -#else /* SK_LITTLE_ENDIAN */ -/* First 32 bits */ -#define OFFS_LO32 0 - -/* Second 32 bits */ -#define OFFS_HI32 1 -#endif /* SK_LITTLE_ENDIAN */ - -#endif /* DEBUG */ - -/* ----- Private timeout values ----- */ - -#define SK_RLMT_MIN_TO_VAL 125000 /* 1/8 sec. */ -#define SK_RLMT_DEF_TO_VAL 1000000 /* 1 sec. */ -#define SK_RLMT_PORTDOWN_TIM_VAL 900000 /* another 0.9 sec. */ -#define SK_RLMT_PORTSTART_TIM_VAL 100000 /* 0.1 sec. */ -#define SK_RLMT_PORTUP_TIM_VAL 2500000 /* 2.5 sec. */ -#define SK_RLMT_SEG_TO_VAL 900000000 /* 15 min. */ - -/* Assume tick counter increment is 1 - may be set OS-dependent. */ -#ifndef SK_TICK_INCR -#define SK_TICK_INCR SK_CONSTU64(1) -#endif /* !defined(SK_TICK_INCR) */ - -/* - * Amount that a time stamp must be later to be recognized as "substantially - * later". This is about 1/128 sec, but above 1 tick counter increment. - */ -#define SK_RLMT_BC_DELTA (1 + ((SK_TICKS_PER_SEC >> 7) > SK_TICK_INCR ? \ - (SK_TICKS_PER_SEC >> 7) : SK_TICK_INCR)) - -/* ----- Private RLMT defaults ----- */ - -#define SK_RLMT_DEF_PREF_PORT 0 /* "Lower" port. */ -#define SK_RLMT_DEF_MODE SK_RLMT_CHECK_LINK /* Default RLMT Mode. */ - -/* ----- Private RLMT checking states ----- */ - -#define SK_RLMT_RCS_SEG 1 /* RLMT Check State: check seg. */ -#define SK_RLMT_RCS_START_SEG 2 /* RLMT Check State: start check seg. */ -#define SK_RLMT_RCS_SEND_SEG 4 /* RLMT Check State: send BPDU packet */ -#define SK_RLMT_RCS_REPORT_SEG 8 /* RLMT Check State: report seg. */ - -/* ----- Private PORT checking states ----- */ - -#define SK_RLMT_PCS_TX 1 /* Port Check State: check tx. */ -#define SK_RLMT_PCS_RX 2 /* Port Check State: check rx. */ - -/* ----- Private PORT events ----- */ - -/* Note: Update simulation when changing these. */ -#define SK_RLMT_PORTSTART_TIM 1100 /* Port start timeout. */ -#define SK_RLMT_PORTUP_TIM 1101 /* Port can now go up. */ -#define SK_RLMT_PORTDOWN_RX_TIM 1102 /* Port did not receive once ... */ -#define SK_RLMT_PORTDOWN 1103 /* Port went down. */ -#define SK_RLMT_PORTDOWN_TX_TIM 1104 /* Partner did not receive ... */ - -/* ----- Private RLMT events ----- */ - -/* Note: Update simulation when changing these. */ -#define SK_RLMT_TIM 2100 /* RLMT timeout. */ -#define SK_RLMT_SEG_TIM 2101 /* RLMT segmentation check timeout. */ - -#define TO_SHORTEN(tim) ((tim) / 2) - -/* Error numbers and messages. */ -#define SKERR_RLMT_E001 (SK_ERRBASE_RLMT + 0) -#define SKERR_RLMT_E001_MSG "No Packet." -#define SKERR_RLMT_E002 (SKERR_RLMT_E001 + 1) -#define SKERR_RLMT_E002_MSG "Short Packet." -#define SKERR_RLMT_E003 (SKERR_RLMT_E002 + 1) -#define SKERR_RLMT_E003_MSG "Unknown RLMT event." -#define SKERR_RLMT_E004 (SKERR_RLMT_E003 + 1) -#define SKERR_RLMT_E004_MSG "PortsUp incorrect." -#define SKERR_RLMT_E005 (SKERR_RLMT_E004 + 1) -#define SKERR_RLMT_E005_MSG \ - "Net seems to be segmented (different root bridges are reported on the ports)." -#define SKERR_RLMT_E006 (SKERR_RLMT_E005 + 1) -#define SKERR_RLMT_E006_MSG "Duplicate MAC Address detected." -#define SKERR_RLMT_E007 (SKERR_RLMT_E006 + 1) -#define SKERR_RLMT_E007_MSG "LinksUp incorrect." -#define SKERR_RLMT_E008 (SKERR_RLMT_E007 + 1) -#define SKERR_RLMT_E008_MSG "Port not started but link came up." -#define SKERR_RLMT_E009 (SKERR_RLMT_E008 + 1) -#define SKERR_RLMT_E009_MSG "Corrected illegal setting of Preferred Port." -#define SKERR_RLMT_E010 (SKERR_RLMT_E009 + 1) -#define SKERR_RLMT_E010_MSG "Ignored illegal Preferred Port." - -/* LLC field values. */ -#define LLC_COMMAND_RESPONSE_BIT 1 -#define LLC_TEST_COMMAND 0xE3 -#define LLC_UI 0x03 - -/* RLMT Packet fields. */ -#define SK_RLMT_DSAP 0 -#define SK_RLMT_SSAP 0 -#define SK_RLMT_CTRL (LLC_TEST_COMMAND) -#define SK_RLMT_INDICATOR0 0x53 /* S */ -#define SK_RLMT_INDICATOR1 0x4B /* K */ -#define SK_RLMT_INDICATOR2 0x2D /* - */ -#define SK_RLMT_INDICATOR3 0x52 /* R */ -#define SK_RLMT_INDICATOR4 0x4C /* L */ -#define SK_RLMT_INDICATOR5 0x4D /* M */ -#define SK_RLMT_INDICATOR6 0x54 /* T */ -#define SK_RLMT_PACKET_VERSION 0 - -/* RLMT SPT Flag values. */ -#define SK_RLMT_SPT_FLAG_CHANGE 0x01 -#define SK_RLMT_SPT_FLAG_CHANGE_ACK 0x80 - -/* RLMT SPT Packet fields. */ -#define SK_RLMT_SPT_DSAP 0x42 -#define SK_RLMT_SPT_SSAP 0x42 -#define SK_RLMT_SPT_CTRL (LLC_UI) -#define SK_RLMT_SPT_PROTOCOL_ID0 0x00 -#define SK_RLMT_SPT_PROTOCOL_ID1 0x00 -#define SK_RLMT_SPT_PROTOCOL_VERSION_ID 0x00 -#define SK_RLMT_SPT_BPDU_TYPE 0x00 -#define SK_RLMT_SPT_FLAGS 0x00 /* ?? */ -#define SK_RLMT_SPT_ROOT_ID0 0xFF /* Lowest possible priority. */ -#define SK_RLMT_SPT_ROOT_ID1 0xFF /* Lowest possible priority. */ - -/* Remaining 6 bytes will be the current port address. */ -#define SK_RLMT_SPT_ROOT_PATH_COST0 0x00 -#define SK_RLMT_SPT_ROOT_PATH_COST1 0x00 -#define SK_RLMT_SPT_ROOT_PATH_COST2 0x00 -#define SK_RLMT_SPT_ROOT_PATH_COST3 0x00 -#define SK_RLMT_SPT_BRIDGE_ID0 0xFF /* Lowest possible priority. */ -#define SK_RLMT_SPT_BRIDGE_ID1 0xFF /* Lowest possible priority. */ - -/* Remaining 6 bytes will be the current port address. */ -#define SK_RLMT_SPT_PORT_ID0 0xFF /* Lowest possible priority. */ -#define SK_RLMT_SPT_PORT_ID1 0xFF /* Lowest possible priority. */ -#define SK_RLMT_SPT_MSG_AGE0 0x00 -#define SK_RLMT_SPT_MSG_AGE1 0x00 -#define SK_RLMT_SPT_MAX_AGE0 0x00 -#define SK_RLMT_SPT_MAX_AGE1 0xFF -#define SK_RLMT_SPT_HELLO_TIME0 0x00 -#define SK_RLMT_SPT_HELLO_TIME1 0xFF -#define SK_RLMT_SPT_FWD_DELAY0 0x00 -#define SK_RLMT_SPT_FWD_DELAY1 0x40 - -/* Size defines. */ -#define SK_RLMT_MIN_PACKET_SIZE 34 -#define SK_RLMT_MAX_PACKET_SIZE (SK_RLMT_MAX_TX_BUF_SIZE) -#define SK_PACKET_DATA_LEN (SK_RLMT_MAX_PACKET_SIZE - \ - SK_RLMT_MIN_PACKET_SIZE) - -/* ----- RLMT packet types ----- */ -#define SK_PACKET_ANNOUNCE 1 /* Port announcement. */ -#define SK_PACKET_ALIVE 2 /* Alive packet to port. */ -#define SK_PACKET_ADDR_CHANGED 3 /* Port address changed. */ -#define SK_PACKET_CHECK_TX 4 /* Check your tx line. */ - -#ifdef SK_LITTLE_ENDIAN -#define SK_U16_TO_NETWORK_ORDER(Val,Addr) { \ - SK_U8 *_Addr = (SK_U8*)(Addr); \ - SK_U16 _Val = (SK_U16)(Val); \ - *_Addr++ = (SK_U8)(_Val >> 8); \ - *_Addr = (SK_U8)(_Val & 0xFF); \ -} -#endif /* SK_LITTLE_ENDIAN */ - -#ifdef SK_BIG_ENDIAN -#define SK_U16_TO_NETWORK_ORDER(Val,Addr) (*(SK_U16*)(Addr) = (SK_U16)(Val)) -#endif /* SK_BIG_ENDIAN */ - -#define AUTONEG_FAILED SK_FALSE -#define AUTONEG_SUCCESS SK_TRUE - - -/* typedefs *******************************************************************/ - -/* RLMT packet. Length: SK_RLMT_MAX_PACKET_SIZE (60) bytes. */ -typedef struct s_RlmtPacket { - SK_U8 DstAddr[SK_MAC_ADDR_LEN]; - SK_U8 SrcAddr[SK_MAC_ADDR_LEN]; - SK_U8 TypeLen[2]; - SK_U8 DSap; - SK_U8 SSap; - SK_U8 Ctrl; - SK_U8 Indicator[7]; - SK_U8 RlmtPacketType[2]; - SK_U8 Align1[2]; - SK_U8 Random[4]; /* Random value of requesting(!) station. */ - SK_U8 RlmtPacketVersion[2]; /* RLMT Packet version. */ - SK_U8 Data[SK_PACKET_DATA_LEN]; -} SK_RLMT_PACKET; - -typedef struct s_SpTreeRlmtPacket { - SK_U8 DstAddr[SK_MAC_ADDR_LEN]; - SK_U8 SrcAddr[SK_MAC_ADDR_LEN]; - SK_U8 TypeLen[2]; - SK_U8 DSap; - SK_U8 SSap; - SK_U8 Ctrl; - SK_U8 ProtocolId[2]; - SK_U8 ProtocolVersionId; - SK_U8 BpduType; - SK_U8 Flags; - SK_U8 RootId[8]; - SK_U8 RootPathCost[4]; - SK_U8 BridgeId[8]; - SK_U8 PortId[2]; - SK_U8 MessageAge[2]; - SK_U8 MaxAge[2]; - SK_U8 HelloTime[2]; - SK_U8 ForwardDelay[2]; -} SK_SPTREE_PACKET; - -/* global variables ***********************************************************/ - -SK_MAC_ADDR SkRlmtMcAddr = {{0x01, 0x00, 0x5A, 0x52, 0x4C, 0x4D}}; -SK_MAC_ADDR BridgeMcAddr = {{0x01, 0x80, 0xC2, 0x00, 0x00, 0x00}}; - -/* local variables ************************************************************/ - -/* None. */ - -/* functions ******************************************************************/ - -RLMT_STATIC void SkRlmtCheckSwitch( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 NetIdx); -RLMT_STATIC void SkRlmtCheckSeg( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 NetIdx); -RLMT_STATIC void SkRlmtEvtSetNets( - SK_AC *pAC, - SK_IOC IoC, - SK_EVPARA Para); - -/****************************************************************************** - * - * SkRlmtInit - initialize data, set state to init - * - * Description: - * - * SK_INIT_DATA - * ============ - * - * This routine initializes all RLMT-related variables to a known state. - * The initial state is SK_RLMT_RS_INIT. - * All ports are initialized to SK_RLMT_PS_INIT. - * - * - * SK_INIT_IO - * ========== - * - * Nothing. - * - * - * SK_INIT_RUN - * =========== - * - * Determine the adapter's random value. - * Set the hw registers, the "logical MAC address", the - * RLMT multicast address, and eventually the BPDU multicast address. - * - * Context: - * init, pageable - * - * Returns: - * Nothing. - */ -void SkRlmtInit( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Level) /* Initialization Level */ -{ - SK_U32 i, j; - SK_U64 Random; - SK_EVPARA Para; - SK_MAC_ADDR VirtualMacAddress; - SK_MAC_ADDR PhysicalAMacAddress; - SK_BOOL VirtualMacAddressSet; - SK_BOOL PhysicalAMacAddressSet; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT, - ("RLMT Init level %d.\n", Level)) - - switch (Level) { - case SK_INIT_DATA: /* Initialize data structures. */ - SK_MEMSET((char *)&pAC->Rlmt, 0, sizeof(SK_RLMT)); - - for (i = 0; i < SK_MAX_MACS; i++) { - pAC->Rlmt.Port[i].PortState = SK_RLMT_PS_INIT; - pAC->Rlmt.Port[i].LinkDown = SK_TRUE; - pAC->Rlmt.Port[i].PortDown = SK_TRUE; - pAC->Rlmt.Port[i].PortStarted = SK_FALSE; - pAC->Rlmt.Port[i].PortNoRx = SK_FALSE; - pAC->Rlmt.Port[i].RootIdSet = SK_FALSE; - pAC->Rlmt.Port[i].PortNumber = i; - pAC->Rlmt.Port[i].Net = &pAC->Rlmt.Net[0]; - pAC->Rlmt.Port[i].AddrPort = &pAC->Addr.Port[i]; - } - - pAC->Rlmt.NumNets = 1; - for (i = 0; i < SK_MAX_NETS; i++) { - pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT; - pAC->Rlmt.Net[i].RootIdSet = SK_FALSE; - pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT; - pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* Automatic. */ - /* Just assuming. */ - pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort; - pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE; - pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL; - pAC->Rlmt.Net[i].NetNumber = i; - } - - pAC->Rlmt.Net[0].Port[0] = &pAC->Rlmt.Port[0]; - pAC->Rlmt.Net[0].Port[1] = &pAC->Rlmt.Port[1]; -#if SK_MAX_NETS > 1 - pAC->Rlmt.Net[1].Port[0] = &pAC->Rlmt.Port[1]; -#endif /* SK_MAX_NETS > 1 */ - break; - - case SK_INIT_IO: /* GIMacsFound first available here. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT, - ("RLMT: %d MACs were detected.\n", pAC->GIni.GIMacsFound)) - - pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound; - - /* Initialize HW registers? */ - if (pAC->GIni.GIMacsFound == 1) { - Para.Para32[0] = SK_RLMT_MODE_CLS; - Para.Para32[1] = 0; - (void)SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE, Para); - } - break; - - case SK_INIT_RUN: - /* Ensure RLMT is set to one net. */ - if (pAC->Rlmt.NumNets > 1) { - Para.Para32[0] = 1; - Para.Para32[1] = -1; - SkRlmtEvtSetNets(pAC, IoC, Para); - } - - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - Random = SkOsGetTime(pAC); - *(SK_U32*)&pAC->Rlmt.Port[i].Random = *(SK_U32*)&Random; - - for (j = 0; j < 4; j++) { - pAC->Rlmt.Port[i].Random[j] ^= pAC->Rlmt.Port[i].AddrPort-> - CurrentMacAddress.a[SK_MAC_ADDR_LEN - 1 - j]; - } - - (void)SkAddrMcClear(pAC, IoC, i, SK_ADDR_PERMANENT | SK_MC_SW_ONLY); - - /* Add RLMT MC address. */ - (void)SkAddrMcAdd(pAC, IoC, i, &SkRlmtMcAddr, SK_ADDR_PERMANENT); - - if (pAC->Rlmt.Net[0].RlmtMode & SK_RLMT_CHECK_SEG) { - /* Add BPDU MC address. */ - (void)SkAddrMcAdd(pAC, IoC, i, &BridgeMcAddr, SK_ADDR_PERMANENT); - } - - (void)SkAddrMcUpdate(pAC, IoC, i); - } - - VirtualMacAddressSet = SK_FALSE; - /* Read virtual MAC address from Control Register File. */ - for (j = 0; j < SK_MAC_ADDR_LEN; j++) { - - SK_IN8(IoC, B2_MAC_1 + j, &VirtualMacAddress.a[j]); - VirtualMacAddressSet |= VirtualMacAddress.a[j]; - } - - PhysicalAMacAddressSet = SK_FALSE; - /* Read physical MAC address for MAC A from Control Register File. */ - for (j = 0; j < SK_MAC_ADDR_LEN; j++) { - - SK_IN8(IoC, B2_MAC_2 + j, &PhysicalAMacAddress.a[j]); - PhysicalAMacAddressSet |= PhysicalAMacAddress.a[j]; - } - - /* check if the two mac addresses contain reasonable values */ - if (!VirtualMacAddressSet || !PhysicalAMacAddressSet) { - - pAC->Rlmt.RlmtOff = SK_TRUE; - } - - /* if the two mac addresses are equal switch off the RLMT_PRE_LOOKAHEAD - and the RLMT_LOOKAHEAD macros */ - else if (SK_ADDR_EQUAL(PhysicalAMacAddress.a, VirtualMacAddress.a)) { - - pAC->Rlmt.RlmtOff = SK_TRUE; - } - else { - pAC->Rlmt.RlmtOff = SK_FALSE; - } - break; - - default: /* error */ - break; - } - return; -} /* SkRlmtInit */ - - -/****************************************************************************** - * - * SkRlmtBuildCheckChain - build the check chain - * - * Description: - * This routine builds the local check chain: - * - Each port that is up checks the next port. - * - The last port that is up checks the first port that is up. - * - * Notes: - * - Currently only local ports are considered when building the chain. - * - Currently the SuspectState is just reset; - * it would be better to save it ... - * - * Context: - * runtime, pageable? - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtBuildCheckChain( -SK_AC *pAC, /* Adapter Context */ -SK_U32 NetIdx) /* Net Number */ -{ - SK_U32 i; - SK_U32 NumMacsUp; - SK_RLMT_PORT * FirstMacUp; - SK_RLMT_PORT * PrevMacUp; - - FirstMacUp = NULL; - PrevMacUp = NULL; - - if (!(pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) { - for (i = 0; i < pAC->Rlmt.Net[i].NumPorts; i++) { - pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0; - } - return; /* Done. */ - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SkRlmtBuildCheckChain.\n")) - - NumMacsUp = 0; - - for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) { - pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0; - pAC->Rlmt.Net[NetIdx].Port[i]->PortsSuspect = 0; - pAC->Rlmt.Net[NetIdx].Port[i]->CheckingState &= - ~(SK_RLMT_PCS_RX | SK_RLMT_PCS_TX); - - /* - * If more than two links are detected we should consider - * checking at least two other ports: - * 1. the next port that is not LinkDown and - * 2. the next port that is not PortDown. - */ - if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) { - if (NumMacsUp == 0) { - FirstMacUp = pAC->Rlmt.Net[NetIdx].Port[i]; - } - else { - PrevMacUp->PortCheck[ - pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked].CheckAddr = - pAC->Rlmt.Net[NetIdx].Port[i]->AddrPort->CurrentMacAddress; - PrevMacUp->PortCheck[ - PrevMacUp->PortsChecked].SuspectTx = SK_FALSE; - PrevMacUp->PortsChecked++; - } - PrevMacUp = pAC->Rlmt.Net[NetIdx].Port[i]; - NumMacsUp++; - } - } - - if (NumMacsUp > 1) { - PrevMacUp->PortCheck[PrevMacUp->PortsChecked].CheckAddr = - FirstMacUp->AddrPort->CurrentMacAddress; - PrevMacUp->PortCheck[PrevMacUp->PortsChecked].SuspectTx = - SK_FALSE; - PrevMacUp->PortsChecked++; - } - -#ifdef DEBUG - for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Port %d checks %d other ports: %2X.\n", i, - pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked, - pAC->Rlmt.Net[NetIdx].Port[i]->PortCheck[0].CheckAddr.a[5])) - } -#endif /* DEBUG */ - - return; -} /* SkRlmtBuildCheckChain */ - - -/****************************************************************************** - * - * SkRlmtBuildPacket - build an RLMT packet - * - * Description: - * This routine sets up an RLMT packet. - * - * Context: - * runtime, pageable? - * - * Returns: - * NULL or pointer to RLMT mbuf - */ -RLMT_STATIC SK_MBUF *SkRlmtBuildPacket( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 PortNumber, /* Sending port */ -SK_U16 PacketType, /* RLMT packet type */ -SK_MAC_ADDR *SrcAddr, /* Source address */ -SK_MAC_ADDR *DestAddr) /* Destination address */ -{ - int i; - SK_U16 Length; - SK_MBUF *pMb; - SK_RLMT_PACKET *pPacket; - -#ifdef DEBUG - SK_U8 CheckSrc = 0; - SK_U8 CheckDest = 0; - - for (i = 0; i < SK_MAC_ADDR_LEN; ++i) { - CheckSrc |= SrcAddr->a[i]; - CheckDest |= DestAddr->a[i]; - } - - if ((CheckSrc == 0) || (CheckDest == 0)) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_ERR, - ("SkRlmtBuildPacket: Invalid %s%saddr.\n", - (CheckSrc == 0 ? "Src" : ""), (CheckDest == 0 ? "Dest" : ""))) - } -#endif - - if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) != NULL) { - pPacket = (SK_RLMT_PACKET*)pMb->pData; - for (i = 0; i < SK_MAC_ADDR_LEN; i++) { - pPacket->DstAddr[i] = DestAddr->a[i]; - pPacket->SrcAddr[i] = SrcAddr->a[i]; - } - pPacket->DSap = SK_RLMT_DSAP; - pPacket->SSap = SK_RLMT_SSAP; - pPacket->Ctrl = SK_RLMT_CTRL; - pPacket->Indicator[0] = SK_RLMT_INDICATOR0; - pPacket->Indicator[1] = SK_RLMT_INDICATOR1; - pPacket->Indicator[2] = SK_RLMT_INDICATOR2; - pPacket->Indicator[3] = SK_RLMT_INDICATOR3; - pPacket->Indicator[4] = SK_RLMT_INDICATOR4; - pPacket->Indicator[5] = SK_RLMT_INDICATOR5; - pPacket->Indicator[6] = SK_RLMT_INDICATOR6; - - SK_U16_TO_NETWORK_ORDER(PacketType, &pPacket->RlmtPacketType[0]); - - for (i = 0; i < 4; i++) { - pPacket->Random[i] = pAC->Rlmt.Port[PortNumber].Random[i]; - } - - SK_U16_TO_NETWORK_ORDER( - SK_RLMT_PACKET_VERSION, &pPacket->RlmtPacketVersion[0]); - - for (i = 0; i < SK_PACKET_DATA_LEN; i++) { - pPacket->Data[i] = 0x00; - } - - Length = SK_RLMT_MAX_PACKET_SIZE; /* Or smaller. */ - pMb->Length = Length; - pMb->PortIdx = PortNumber; - Length -= 14; - SK_U16_TO_NETWORK_ORDER(Length, &pPacket->TypeLen[0]); - - if (PacketType == SK_PACKET_ALIVE) { - pAC->Rlmt.Port[PortNumber].TxHelloCts++; - } - } - - return (pMb); -} /* SkRlmtBuildPacket */ - - -/****************************************************************************** - * - * SkRlmtBuildSpanningTreePacket - build spanning tree check packet - * - * Description: - * This routine sets up a BPDU packet for spanning tree check. - * - * Context: - * runtime, pageable? - * - * Returns: - * NULL or pointer to RLMT mbuf - */ -RLMT_STATIC SK_MBUF *SkRlmtBuildSpanningTreePacket( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 PortNumber) /* Sending port */ -{ - unsigned i; - SK_U16 Length; - SK_MBUF *pMb; - SK_SPTREE_PACKET *pSPacket; - - if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) != - NULL) { - pSPacket = (SK_SPTREE_PACKET*)pMb->pData; - for (i = 0; i < SK_MAC_ADDR_LEN; i++) { - pSPacket->DstAddr[i] = BridgeMcAddr.a[i]; - pSPacket->SrcAddr[i] = - pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i]; - } - pSPacket->DSap = SK_RLMT_SPT_DSAP; - pSPacket->SSap = SK_RLMT_SPT_SSAP; - pSPacket->Ctrl = SK_RLMT_SPT_CTRL; - - pSPacket->ProtocolId[0] = SK_RLMT_SPT_PROTOCOL_ID0; - pSPacket->ProtocolId[1] = SK_RLMT_SPT_PROTOCOL_ID1; - pSPacket->ProtocolVersionId = SK_RLMT_SPT_PROTOCOL_VERSION_ID; - pSPacket->BpduType = SK_RLMT_SPT_BPDU_TYPE; - pSPacket->Flags = SK_RLMT_SPT_FLAGS; - pSPacket->RootId[0] = SK_RLMT_SPT_ROOT_ID0; - pSPacket->RootId[1] = SK_RLMT_SPT_ROOT_ID1; - pSPacket->RootPathCost[0] = SK_RLMT_SPT_ROOT_PATH_COST0; - pSPacket->RootPathCost[1] = SK_RLMT_SPT_ROOT_PATH_COST1; - pSPacket->RootPathCost[2] = SK_RLMT_SPT_ROOT_PATH_COST2; - pSPacket->RootPathCost[3] = SK_RLMT_SPT_ROOT_PATH_COST3; - pSPacket->BridgeId[0] = SK_RLMT_SPT_BRIDGE_ID0; - pSPacket->BridgeId[1] = SK_RLMT_SPT_BRIDGE_ID1; - - /* - * Use logical MAC address as bridge ID and filter these packets - * on receive. - */ - for (i = 0; i < SK_MAC_ADDR_LEN; i++) { - pSPacket->BridgeId[i + 2] = pSPacket->RootId[i + 2] = - pAC->Addr.Net[pAC->Rlmt.Port[PortNumber].Net->NetNumber]. - CurrentMacAddress.a[i]; - } - pSPacket->PortId[0] = SK_RLMT_SPT_PORT_ID0; - pSPacket->PortId[1] = SK_RLMT_SPT_PORT_ID1; - pSPacket->MessageAge[0] = SK_RLMT_SPT_MSG_AGE0; - pSPacket->MessageAge[1] = SK_RLMT_SPT_MSG_AGE1; - pSPacket->MaxAge[0] = SK_RLMT_SPT_MAX_AGE0; - pSPacket->MaxAge[1] = SK_RLMT_SPT_MAX_AGE1; - pSPacket->HelloTime[0] = SK_RLMT_SPT_HELLO_TIME0; - pSPacket->HelloTime[1] = SK_RLMT_SPT_HELLO_TIME1; - pSPacket->ForwardDelay[0] = SK_RLMT_SPT_FWD_DELAY0; - pSPacket->ForwardDelay[1] = SK_RLMT_SPT_FWD_DELAY1; - - Length = SK_RLMT_MAX_PACKET_SIZE; /* Or smaller. */ - pMb->Length = Length; - pMb->PortIdx = PortNumber; - Length -= 14; - SK_U16_TO_NETWORK_ORDER(Length, &pSPacket->TypeLen[0]); - - pAC->Rlmt.Port[PortNumber].TxSpHelloReqCts++; - } - - return (pMb); -} /* SkRlmtBuildSpanningTreePacket */ - - -/****************************************************************************** - * - * SkRlmtSend - build and send check packets - * - * Description: - * Depending on the RLMT state and the checking state, several packets - * are sent through the indicated port. - * - * Context: - * runtime, pageable? - * - * Returns: - * Nothing. - */ -RLMT_STATIC void SkRlmtSend( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 PortNumber) /* Sending port */ -{ - unsigned j; - SK_EVPARA Para; - SK_RLMT_PORT *pRPort; - - pRPort = &pAC->Rlmt.Port[PortNumber]; - if (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) { - if (pRPort->CheckingState & (SK_RLMT_PCS_TX | SK_RLMT_PCS_RX)) { - /* Port is suspicious. Send the RLMT packet to the RLMT mc addr. */ - if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber, - SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress, - &SkRlmtMcAddr)) != NULL) { - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - } - } - else { - /* - * Send a directed RLMT packet to all ports that are - * checked by the indicated port. - */ - for (j = 0; j < pRPort->PortsChecked; j++) { - if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber, - SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress, - &pRPort->PortCheck[j].CheckAddr)) != NULL) { - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - } - } - } - } - - if ((pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) && - (pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEND_SEG)) { - /* - * Send a BPDU packet to make a connected switch tell us - * the correct root bridge. - */ - if ((Para.pParaPtr = - SkRlmtBuildSpanningTreePacket(pAC, IoC, PortNumber)) != NULL) { - pAC->Rlmt.Port[PortNumber].Net->CheckingState &= ~SK_RLMT_RCS_SEND_SEG; - pRPort->RootIdSet = SK_FALSE; - - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_TX, - ("SkRlmtSend: BPDU Packet on Port %u.\n", PortNumber)) - } - } - return; -} /* SkRlmtSend */ - - -/****************************************************************************** - * - * SkRlmtPortReceives - check if port is (going) down and bring it up - * - * Description: - * This routine checks if a port who received a non-BPDU packet - * needs to go up or needs to be stopped going down. - * - * Context: - * runtime, pageable? - * - * Returns: - * Nothing. - */ -RLMT_STATIC void SkRlmtPortReceives( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 PortNumber) /* Port to check */ -{ - SK_RLMT_PORT *pRPort; - SK_EVPARA Para; - - pRPort = &pAC->Rlmt.Port[PortNumber]; - pRPort->PortNoRx = SK_FALSE; - - if ((pRPort->PortState == SK_RLMT_PS_DOWN) && - !(pRPort->CheckingState & SK_RLMT_PCS_TX)) { - /* - * Port is marked down (rx), but received a non-BPDU packet. - * Bring it up. - */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Received on PortDown.\n")) - - pRPort->PortState = SK_RLMT_PS_GOING_UP; - pRPort->GuTimeStamp = SkOsGetTime(pAC); - Para.Para32[0] = PortNumber; - Para.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL, - SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para); - pRPort->CheckingState &= ~SK_RLMT_PCS_RX; - /* pAC->Rlmt.CheckSwitch = SK_TRUE; */ - SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); - } /* PortDown && !SuspectTx */ - else if (pRPort->CheckingState & SK_RLMT_PCS_RX) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Stop bringing port down.\n")) - SkTimerStop(pAC, IoC, &pRPort->DownRxTimer); - pRPort->CheckingState &= ~SK_RLMT_PCS_RX; - /* pAC->Rlmt.CheckSwitch = SK_TRUE; */ - SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); - } /* PortGoingDown */ - - return; -} /* SkRlmtPortReceives */ - - -/****************************************************************************** - * - * SkRlmtPacketReceive - receive a packet for closer examination - * - * Description: - * This routine examines a packet more closely than SK_RLMT_LOOKAHEAD. - * - * Context: - * runtime, pageable? - * - * Returns: - * Nothing. - */ -RLMT_STATIC void SkRlmtPacketReceive( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_MBUF *pMb) /* Received packet */ -{ -#ifdef xDEBUG - extern void DumpData(char *p, int size); -#endif /* DEBUG */ - int i; - unsigned j; - SK_U16 PacketType; - SK_U32 PortNumber; - SK_ADDR_PORT *pAPort; - SK_RLMT_PORT *pRPort; - SK_RLMT_PACKET *pRPacket; - SK_SPTREE_PACKET *pSPacket; - SK_EVPARA Para; - - PortNumber = pMb->PortIdx; - pAPort = &pAC->Addr.Port[PortNumber]; - pRPort = &pAC->Rlmt.Port[PortNumber]; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: PortNumber == %d.\n", PortNumber)) - - pRPacket = (SK_RLMT_PACKET*)pMb->pData; - pSPacket = (SK_SPTREE_PACKET*)pRPacket; - -#ifdef xDEBUG - DumpData((char *)pRPacket, 32); -#endif /* DEBUG */ - - if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) != 0) { - SkRlmtPortReceives(pAC, IoC, PortNumber); - } - - /* Check destination address. */ - - if (!SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->DstAddr) && - !SK_ADDR_EQUAL(SkRlmtMcAddr.a, pRPacket->DstAddr) && - !SK_ADDR_EQUAL(BridgeMcAddr.a, pRPacket->DstAddr)) { - - /* Not sent to current MAC or registered MC address => Trash it. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Not for me.\n")) - - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - return; - } - else if (SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->SrcAddr)) { - - /* - * Was sent by same port (may happen during port switching - * or in case of duplicate MAC addresses). - */ - - /* - * Check for duplicate address here: - * If Packet.Random != My.Random => DupAddr. - */ - for (i = 3; i >= 0; i--) { - if (pRPort->Random[i] != pRPacket->Random[i]) { - break; - } - } - - /* - * CAUTION: Do not check for duplicate MAC address in RLMT Alive Reply - * packets (they have the LLC_COMMAND_RESPONSE_BIT set in - * pRPacket->SSap). - */ - if (i >= 0 && pRPacket->DSap == SK_RLMT_DSAP && - pRPacket->Ctrl == SK_RLMT_CTRL && - pRPacket->SSap == SK_RLMT_SSAP && - pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 && - pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 && - pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 && - pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 && - pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 && - pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 && - pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Duplicate MAC Address.\n")) - - /* Error Log entry. */ - SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E006, SKERR_RLMT_E006_MSG); - } - else { - /* Simply trash it. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Sent by me.\n")) - } - - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - return; - } - - /* Check SuspectTx entries. */ - if (pRPort->PortsSuspect > 0) { - for (j = 0; j < pRPort->PortsChecked; j++) { - if (pRPort->PortCheck[j].SuspectTx && - SK_ADDR_EQUAL( - pRPacket->SrcAddr, pRPort->PortCheck[j].CheckAddr.a)) { - pRPort->PortCheck[j].SuspectTx = SK_FALSE; - pRPort->PortsSuspect--; - break; - } - } - } - - /* Determine type of packet. */ - if (pRPacket->DSap == SK_RLMT_DSAP && - pRPacket->Ctrl == SK_RLMT_CTRL && - (pRPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SSAP && - pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 && - pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 && - pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 && - pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 && - pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 && - pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 && - pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) { - - /* It's an RLMT packet. */ - PacketType = (SK_U16)((pRPacket->RlmtPacketType[0] << 8) | - pRPacket->RlmtPacketType[1]); - - switch (PacketType) { - case SK_PACKET_ANNOUNCE: /* Not yet used. */ -#if 0 - /* Build the check chain. */ - SkRlmtBuildCheckChain(pAC); -#endif /* 0 */ - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Announce.\n")) - - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - break; - - case SK_PACKET_ALIVE: - if (pRPacket->SSap & LLC_COMMAND_RESPONSE_BIT) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Alive Reply.\n")) - - if (!(pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_LLC) || - SK_ADDR_EQUAL( - pRPacket->DstAddr, pAPort->CurrentMacAddress.a)) { - /* Obviously we could send something. */ - if (pRPort->CheckingState & SK_RLMT_PCS_TX) { - pRPort->CheckingState &= ~SK_RLMT_PCS_TX; - SkTimerStop(pAC, IoC, &pRPort->DownTxTimer); - } - - if ((pRPort->PortState == SK_RLMT_PS_DOWN) && - !(pRPort->CheckingState & SK_RLMT_PCS_RX)) { - pRPort->PortState = SK_RLMT_PS_GOING_UP; - pRPort->GuTimeStamp = SkOsGetTime(pAC); - - SkTimerStop(pAC, IoC, &pRPort->DownTxTimer); - - Para.Para32[0] = PortNumber; - Para.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pRPort->UpTimer, - SK_RLMT_PORTUP_TIM_VAL, SKGE_RLMT, - SK_RLMT_PORTUP_TIM, Para); - } - } - - /* Mark sending port as alive? */ - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - } - else { /* Alive Request Packet. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Alive Request.\n")) - - pRPort->RxHelloCts++; - - /* Answer. */ - for (i = 0; i < SK_MAC_ADDR_LEN; i++) { - pRPacket->DstAddr[i] = pRPacket->SrcAddr[i]; - pRPacket->SrcAddr[i] = - pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i]; - } - pRPacket->SSap |= LLC_COMMAND_RESPONSE_BIT; - - Para.pParaPtr = pMb; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - } - break; - - case SK_PACKET_CHECK_TX: - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Check your tx line.\n")) - - /* A port checking us requests us to check our tx line. */ - pRPort->CheckingState |= SK_RLMT_PCS_TX; - - /* Start PortDownTx timer. */ - Para.Para32[0] = PortNumber; - Para.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pRPort->DownTxTimer, - SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT, - SK_RLMT_PORTDOWN_TX_TIM, Para); - - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - - if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber, - SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress, - &SkRlmtMcAddr)) != NULL) { - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - } - break; - - case SK_PACKET_ADDR_CHANGED: - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Address Change.\n")) - - /* Build the check chain. */ - SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber); - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - break; - - default: - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Unknown RLMT packet.\n")) - - /* RA;:;: ??? */ - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - } - } - else if (pSPacket->DSap == SK_RLMT_SPT_DSAP && - pSPacket->Ctrl == SK_RLMT_SPT_CTRL && - (pSPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SPT_SSAP) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: BPDU Packet.\n")) - - /* Spanning Tree packet. */ - pRPort->RxSpHelloCts++; - - if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pAC->Addr.Net[pAC->Rlmt. - Port[PortNumber].Net->NetNumber].CurrentMacAddress.a[0])) { - /* - * Check segmentation if a new root bridge is set and - * the segmentation check is not currently running. - */ - if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pRPort->Root.Id[2]) && - (pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) && - (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) - != 0 && (pAC->Rlmt.Port[PortNumber].Net->CheckingState & - SK_RLMT_RCS_SEG) == 0) { - pAC->Rlmt.Port[PortNumber].Net->CheckingState |= - SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG; - } - - /* Store tree view of this port. */ - for (i = 0; i < 8; i++) { - pRPort->Root.Id[i] = pSPacket->RootId[i]; - } - pRPort->RootIdSet = SK_TRUE; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP, - ("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n", - PortNumber, - pRPort->Root.Id[0], pRPort->Root.Id[1], - pRPort->Root.Id[2], pRPort->Root.Id[3], - pRPort->Root.Id[4], pRPort->Root.Id[5], - pRPort->Root.Id[6], pRPort->Root.Id[7])) - } - - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - if ((pAC->Rlmt.Port[PortNumber].Net->CheckingState & - SK_RLMT_RCS_REPORT_SEG) != 0) { - SkRlmtCheckSeg(pAC, IoC, pAC->Rlmt.Port[PortNumber].Net->NetNumber); - } - } - else { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Unknown Packet Type.\n")) - - /* Unknown packet. */ - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - } - return; -} /* SkRlmtPacketReceive */ - - -/****************************************************************************** - * - * SkRlmtCheckPort - check if a port works - * - * Description: - * This routine checks if a port whose link is up received something - * and if it seems to transmit successfully. - * - * # PortState: PsInit, PsLinkDown, PsDown, PsGoingUp, PsUp - * # PortCheckingState (Bitfield): ChkTx, ChkRx, ChkSeg - * # RlmtCheckingState (Bitfield): ChkSeg, StartChkSeg, ReportSeg - * - * if (Rx - RxBpdu == 0) { # No rx. - * if (state == PsUp) { - * PortCheckingState |= ChkRx - * } - * if (ModeCheckSeg && (Timeout == - * TO_SHORTEN(RLMT_DEFAULT_TIMEOUT))) { - * RlmtCheckingState |= ChkSeg) - * PortCheckingState |= ChkSeg - * } - * NewTimeout = TO_SHORTEN(Timeout) - * if (NewTimeout < RLMT_MIN_TIMEOUT) { - * NewTimeout = RLMT_MIN_TIMEOUT - * PortState = PsDown - * ... - * } - * } - * else { # something was received - * # Set counter to 0 at LinkDown? - * # No - rx may be reported after LinkDown ??? - * PortCheckingState &= ~ChkRx - * NewTimeout = RLMT_DEFAULT_TIMEOUT - * if (RxAck == 0) { - * possible reasons: - * is my tx line bad? -- - * send RLMT multicast and report - * back internally? (only possible - * between ports on same adapter) - * } - * if (RxChk == 0) { - * possible reasons: - * - tx line of port set to check me - * maybe bad - * - no other port/adapter available or set - * to check me - * - adapter checking me has a longer - * timeout - * ??? anything that can be done here? - * } - * } - * - * Context: - * runtime, pageable? - * - * Returns: - * New timeout value. - */ -RLMT_STATIC SK_U32 SkRlmtCheckPort( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 PortNumber) /* Port to check */ -{ - unsigned i; - SK_U32 NewTimeout; - SK_RLMT_PORT *pRPort; - SK_EVPARA Para; - - pRPort = &pAC->Rlmt.Port[PortNumber]; - - if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) == 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SkRlmtCheckPort %d: No (%d) receives in last time slot.\n", - PortNumber, pRPort->PacketsPerTimeSlot)) - - /* - * Check segmentation if there was no receive at least twice - * in a row (PortNoRx is already set) and the segmentation - * check is not currently running. - */ - - if (pRPort->PortNoRx && (pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) && - (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) && - !(pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEG)) { - pAC->Rlmt.Port[PortNumber].Net->CheckingState |= - SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SkRlmtCheckPort: PortsSuspect %d, PcsRx %d.\n", - pRPort->PortsSuspect, pRPort->CheckingState & SK_RLMT_PCS_RX)) - - if (pRPort->PortState != SK_RLMT_PS_DOWN) { - NewTimeout = TO_SHORTEN(pAC->Rlmt.Port[PortNumber].Net->TimeoutValue); - if (NewTimeout < SK_RLMT_MIN_TO_VAL) { - NewTimeout = SK_RLMT_MIN_TO_VAL; - } - - if (!(pRPort->CheckingState & SK_RLMT_PCS_RX)) { - Para.Para32[0] = PortNumber; - pRPort->CheckingState |= SK_RLMT_PCS_RX; - - /* - * What shall we do if the port checked by this one receives - * our request frames? What's bad - our rx line or his tx line? - */ - Para.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pRPort->DownRxTimer, - SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT, - SK_RLMT_PORTDOWN_RX_TIM, Para); - - for (i = 0; i < pRPort->PortsChecked; i++) { - if (pRPort->PortCheck[i].SuspectTx) { - continue; - } - pRPort->PortCheck[i].SuspectTx = SK_TRUE; - pRPort->PortsSuspect++; - if ((Para.pParaPtr = - SkRlmtBuildPacket(pAC, IoC, PortNumber, SK_PACKET_CHECK_TX, - &pAC->Addr.Port[PortNumber].CurrentMacAddress, - &pRPort->PortCheck[i].CheckAddr)) != NULL) { - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - } - } - } - } - else { /* PortDown -- or all partners suspect. */ - NewTimeout = SK_RLMT_DEF_TO_VAL; - } - pRPort->PortNoRx = SK_TRUE; - } - else { /* A non-BPDU packet was received. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SkRlmtCheckPort %d: %d (%d) receives in last time slot.\n", - PortNumber, - pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot, - pRPort->PacketsPerTimeSlot)) - - SkRlmtPortReceives(pAC, IoC, PortNumber); - if (pAC->Rlmt.CheckSwitch) { - SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); - } - - NewTimeout = SK_RLMT_DEF_TO_VAL; - } - - return (NewTimeout); -} /* SkRlmtCheckPort */ - - -/****************************************************************************** - * - * SkRlmtSelectBcRx - select new active port, criteria 1 (CLP) - * - * Description: - * This routine selects the port that received a broadcast frame - * substantially later than all other ports. - * - * Context: - * runtime, pageable? - * - * Returns: - * SK_BOOL - */ -RLMT_STATIC SK_BOOL SkRlmtSelectBcRx( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Active, /* Active port */ -SK_U32 PrefPort, /* Preferred port */ -SK_U32 *pSelect) /* New active port */ -{ - SK_U64 BcTimeStamp; - SK_U32 i; - SK_BOOL PortFound; - - BcTimeStamp = 0; /* Not totally necessary, but feeling better. */ - PortFound = SK_FALSE; - - /* Select port with the latest TimeStamp. */ - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("TimeStamp Port %d (Down: %d, NoRx: %d): %08x %08x.\n", - i, - pAC->Rlmt.Port[i].PortDown, pAC->Rlmt.Port[i].PortNoRx, - *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_HI32), - *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_LO32))) - - if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx) { - if (!PortFound || pAC->Rlmt.Port[i].BcTimeStamp > BcTimeStamp) { - BcTimeStamp = pAC->Rlmt.Port[i].BcTimeStamp; - *pSelect = i; - PortFound = SK_TRUE; - } - } - } - - if (PortFound) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Port %d received the last broadcast.\n", *pSelect)) - - /* Look if another port's time stamp is similar. */ - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - if (i == *pSelect) { - continue; - } - if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx && - (pAC->Rlmt.Port[i].BcTimeStamp > - BcTimeStamp - SK_RLMT_BC_DELTA || - pAC->Rlmt.Port[i].BcTimeStamp + - SK_RLMT_BC_DELTA > BcTimeStamp)) { - PortFound = SK_FALSE; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Port %d received a broadcast at a similar time.\n", i)) - break; - } - } - } - -#ifdef DEBUG - if (PortFound) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SELECT_BCRX found Port %d receiving the substantially " - "latest broadcast (%u).\n", - *pSelect, - BcTimeStamp - pAC->Rlmt.Port[1 - *pSelect].BcTimeStamp)) - } -#endif /* DEBUG */ - - return (PortFound); -} /* SkRlmtSelectBcRx */ - - -/****************************************************************************** - * - * SkRlmtSelectNotSuspect - select new active port, criteria 2 (CLP) - * - * Description: - * This routine selects a good port (it is PortUp && !SuspectRx). - * - * Context: - * runtime, pageable? - * - * Returns: - * SK_BOOL - */ -RLMT_STATIC SK_BOOL SkRlmtSelectNotSuspect( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Active, /* Active port */ -SK_U32 PrefPort, /* Preferred port */ -SK_U32 *pSelect) /* New active port */ -{ - SK_U32 i; - SK_BOOL PortFound; - - PortFound = SK_FALSE; - - /* Select first port that is PortUp && !SuspectRx. */ - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - if (!pAC->Rlmt.Port[i].PortDown && - !(pAC->Rlmt.Port[i].CheckingState & SK_RLMT_PCS_RX)) { - *pSelect = i; - if (!pAC->Rlmt.Port[Active].PortDown && - !(pAC->Rlmt.Port[Active].CheckingState & SK_RLMT_PCS_RX)) { - *pSelect = Active; - } - if (!pAC->Rlmt.Port[PrefPort].PortDown && - !(pAC->Rlmt.Port[PrefPort].CheckingState & SK_RLMT_PCS_RX)) { - *pSelect = PrefPort; - } - PortFound = SK_TRUE; - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SELECT_NOTSUSPECT found Port %d up and not check RX.\n", - *pSelect)) - break; - } - } - return (PortFound); -} /* SkRlmtSelectNotSuspect */ - - -/****************************************************************************** - * - * SkRlmtSelectUp - select new active port, criteria 3, 4 (CLP) - * - * Description: - * This routine selects a port that is up. - * - * Context: - * runtime, pageable? - * - * Returns: - * SK_BOOL - */ -RLMT_STATIC SK_BOOL SkRlmtSelectUp( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Active, /* Active port */ -SK_U32 PrefPort, /* Preferred port */ -SK_U32 *pSelect, /* New active port */ -SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */ -{ - SK_U32 i; - SK_BOOL PortFound; - - PortFound = SK_FALSE; - - /* Select first port that is PortUp. */ - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_UP && - pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { - *pSelect = i; - if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_UP && - pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) { - *pSelect = Active; - } - if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_UP && - pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) { - *pSelect = PrefPort; - } - PortFound = SK_TRUE; - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SELECT_UP found Port %d up.\n", *pSelect)) - break; - } - } - return (PortFound); -} /* SkRlmtSelectUp */ - - -/****************************************************************************** - * - * SkRlmtSelectGoingUp - select new active port, criteria 5, 6 (CLP) - * - * Description: - * This routine selects the port that is going up for the longest time. - * - * Context: - * runtime, pageable? - * - * Returns: - * SK_BOOL - */ -RLMT_STATIC SK_BOOL SkRlmtSelectGoingUp( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Active, /* Active port */ -SK_U32 PrefPort, /* Preferred port */ -SK_U32 *pSelect, /* New active port */ -SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */ -{ - SK_U64 GuTimeStamp; - SK_U32 i; - SK_BOOL PortFound; - - GuTimeStamp = 0; - PortFound = SK_FALSE; - - /* Select port that is PortGoingUp for the longest time. */ - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP && - pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { - GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp; - *pSelect = i; - PortFound = SK_TRUE; - break; - } - } - - if (!PortFound) { - return (SK_FALSE); - } - - for (i = *pSelect + 1; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP && - pAC->Rlmt.Port[i].GuTimeStamp < GuTimeStamp && - pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { - GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp; - *pSelect = i; - } - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SELECT_GOINGUP found Port %d going up.\n", *pSelect)) - return (SK_TRUE); -} /* SkRlmtSelectGoingUp */ - - -/****************************************************************************** - * - * SkRlmtSelectDown - select new active port, criteria 7, 8 (CLP) - * - * Description: - * This routine selects a port that is down. - * - * Context: - * runtime, pageable? - * - * Returns: - * SK_BOOL - */ -RLMT_STATIC SK_BOOL SkRlmtSelectDown( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Active, /* Active port */ -SK_U32 PrefPort, /* Preferred port */ -SK_U32 *pSelect, /* New active port */ -SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */ -{ - SK_U32 i; - SK_BOOL PortFound; - - PortFound = SK_FALSE; - - /* Select first port that is PortDown. */ - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_DOWN && - pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { - *pSelect = i; - if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_DOWN && - pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) { - *pSelect = Active; - } - if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_DOWN && - pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) { - *pSelect = PrefPort; - } - PortFound = SK_TRUE; - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SELECT_DOWN found Port %d down.\n", *pSelect)) - break; - } - } - return (PortFound); -} /* SkRlmtSelectDown */ - - -/****************************************************************************** - * - * SkRlmtCheckSwitch - select new active port and switch to it - * - * Description: - * This routine decides which port should be the active one and queues - * port switching if necessary. - * - * Context: - * runtime, pageable? - * - * Returns: - * Nothing. - */ -RLMT_STATIC void SkRlmtCheckSwitch( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 NetIdx) /* Net index */ -{ - SK_EVPARA Para; - SK_U32 Active; - SK_U32 PrefPort; - SK_U32 i; - SK_BOOL PortFound; - - Active = pAC->Rlmt.Net[NetIdx].ActivePort; /* Index of active port. */ - PrefPort = pAC->Rlmt.Net[NetIdx].PrefPort; /* Index of preferred port. */ - PortFound = SK_FALSE; - pAC->Rlmt.CheckSwitch = SK_FALSE; - -#if 0 /* RW 2001/10/18 - active port becomes always prefered one */ - if (pAC->Rlmt.Net[NetIdx].Preference == 0xFFFFFFFF) { /* Automatic */ - /* disable auto-fail back */ - PrefPort = Active; - } -#endif - - if (pAC->Rlmt.Net[NetIdx].LinksUp == 0) { - /* Last link went down - shut down the net. */ - pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_DOWN; - Para.Para32[0] = SK_RLMT_NET_DOWN_TEMP; - Para.Para32[1] = NetIdx; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para); - - Para.Para32[0] = pAC->Rlmt.Net[NetIdx]. - Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber; - Para.Para32[1] = NetIdx; - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para); - return; - } /* pAC->Rlmt.LinksUp == 0 */ - else if (pAC->Rlmt.Net[NetIdx].LinksUp == 1 && - pAC->Rlmt.Net[NetIdx].RlmtState == SK_RLMT_RS_NET_DOWN) { - /* First link came up - get the net up. */ - pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_UP; - - /* - * If pAC->Rlmt.ActivePort != Para.Para32[0], - * the DRV switches to the port that came up. - */ - for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) { - if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) { - if (!pAC->Rlmt.Net[NetIdx].Port[Active]->LinkDown) { - i = Active; - } - if (!pAC->Rlmt.Net[NetIdx].Port[PrefPort]->LinkDown) { - i = PrefPort; - } - PortFound = SK_TRUE; - break; - } - } - - if (PortFound) { - Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber; - Para.Para32[1] = NetIdx; - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para); - - pAC->Rlmt.Net[NetIdx].ActivePort = i; - Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber; - Para.Para32[1] = NetIdx; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_UP, Para); - - if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 && - (Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, - pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber, - SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx]. - CurrentMacAddress, &SkRlmtMcAddr)) != NULL) { - /* - * Send announce packet to RLMT multicast address to force - * switches to learn the new location of the logical MAC address. - */ - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - } - } - else { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E007, SKERR_RLMT_E007_MSG); - } - - return; - } /* LinksUp == 1 && RlmtState == SK_RLMT_RS_NET_DOWN */ - else { /* Cannot be reached in dual-net mode. */ - Para.Para32[0] = Active; - - /* - * Preselection: - * If RLMT Mode != CheckLinkState - * select port that received a broadcast frame substantially later - * than all other ports - * else select first port that is not SuspectRx - * else select first port that is PortUp - * else select port that is PortGoingUp for the longest time - * else select first port that is PortDown - * else stop. - * - * For the preselected port: - * If ActivePort is equal in quality, select ActivePort. - * - * If PrefPort is equal in quality, select PrefPort. - * - * If ActivePort != SelectedPort, - * If old ActivePort is LinkDown, - * SwitchHard - * else - * SwitchSoft - */ - /* check of ChgBcPrio flag added */ - if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) && - (!pAC->Rlmt.Net[0].ChgBcPrio)) { - - if (!PortFound) { - PortFound = SkRlmtSelectBcRx( - pAC, IoC, Active, PrefPort, &Para.Para32[1]); - } - - if (!PortFound) { - PortFound = SkRlmtSelectNotSuspect( - pAC, IoC, Active, PrefPort, &Para.Para32[1]); - } - } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */ - - /* with changed priority for last broadcast received */ - if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) && - (pAC->Rlmt.Net[0].ChgBcPrio)) { - if (!PortFound) { - PortFound = SkRlmtSelectNotSuspect( - pAC, IoC, Active, PrefPort, &Para.Para32[1]); - } - - if (!PortFound) { - PortFound = SkRlmtSelectBcRx( - pAC, IoC, Active, PrefPort, &Para.Para32[1]); - } - } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */ - - if (!PortFound) { - PortFound = SkRlmtSelectUp( - pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS); - } - - if (!PortFound) { - PortFound = SkRlmtSelectUp( - pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED); - } - - if (!PortFound) { - PortFound = SkRlmtSelectGoingUp( - pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS); - } - - if (!PortFound) { - PortFound = SkRlmtSelectGoingUp( - pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED); - } - - if (pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) { - if (!PortFound) { - PortFound = SkRlmtSelectDown(pAC, IoC, - Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS); - } - - if (!PortFound) { - PortFound = SkRlmtSelectDown(pAC, IoC, - Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED); - } - } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */ - - if (PortFound) { - - if (Para.Para32[1] != Active) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Active: %d, Para1: %d.\n", Active, Para.Para32[1])) - pAC->Rlmt.Net[NetIdx].ActivePort = Para.Para32[1]; - Para.Para32[0] = pAC->Rlmt.Net[NetIdx]. - Port[Para.Para32[0]]->PortNumber; - Para.Para32[1] = pAC->Rlmt.Net[NetIdx]. - Port[Para.Para32[1]]->PortNumber; - SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[1], SK_LED_ACTIVE); - if (pAC->Rlmt.Port[Active].LinkDown) { - SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_HARD, Para); - } - else { - SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY); - SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_SOFT, Para); - } - Para.Para32[1] = NetIdx; - Para.Para32[0] = - pAC->Rlmt.Net[NetIdx].Port[Para.Para32[0]]->PortNumber; - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para); - Para.Para32[0] = pAC->Rlmt.Net[NetIdx]. - Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber; - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para); - if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 && - (Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, Para.Para32[0], - SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].CurrentMacAddress, - &SkRlmtMcAddr)) != NULL) { - /* - * Send announce packet to RLMT multicast address to force - * switches to learn the new location of the logical - * MAC address. - */ - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - } /* (Para.pParaPtr = SkRlmtBuildPacket(...)) != NULL */ - } /* Para.Para32[1] != Active */ - } /* PortFound */ - else { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E004, SKERR_RLMT_E004_MSG); - } - } /* LinksUp > 1 || LinksUp == 1 && RlmtState != SK_RLMT_RS_NET_DOWN */ - return; -} /* SkRlmtCheckSwitch */ - - -/****************************************************************************** - * - * SkRlmtCheckSeg - Report if segmentation is detected - * - * Description: - * This routine checks if the ports see different root bridges and reports - * segmentation in such a case. - * - * Context: - * runtime, pageable? - * - * Returns: - * Nothing. - */ -RLMT_STATIC void SkRlmtCheckSeg( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 NetIdx) /* Net number */ -{ - SK_EVPARA Para; - SK_RLMT_NET *pNet; - SK_U32 i, j; - SK_BOOL Equal; - - pNet = &pAC->Rlmt.Net[NetIdx]; - pNet->RootIdSet = SK_FALSE; - Equal = SK_TRUE; - - for (i = 0; i < pNet->NumPorts; i++) { - if (pNet->Port[i]->LinkDown || !pNet->Port[i]->RootIdSet) { - continue; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP, - ("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n", i, - pNet->Port[i]->Root.Id[0], pNet->Port[i]->Root.Id[1], - pNet->Port[i]->Root.Id[2], pNet->Port[i]->Root.Id[3], - pNet->Port[i]->Root.Id[4], pNet->Port[i]->Root.Id[5], - pNet->Port[i]->Root.Id[6], pNet->Port[i]->Root.Id[7])) - - if (!pNet->RootIdSet) { - pNet->Root = pNet->Port[i]->Root; - pNet->RootIdSet = SK_TRUE; - continue; - } - - for (j = 0; j < 8; j ++) { - Equal &= pNet->Port[i]->Root.Id[j] == pNet->Root.Id[j]; - if (!Equal) { - break; - } - } - - if (!Equal) { - SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E005, SKERR_RLMT_E005_MSG); - Para.Para32[0] = NetIdx; - Para.Para32[1] = (SK_U32)-1; - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SEGMENTATION, Para); - - pNet->CheckingState &= ~SK_RLMT_RCS_REPORT_SEG; - - /* 2000-03-06 RA: New. */ - Para.Para32[0] = NetIdx; - Para.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pNet->SegTimer, SK_RLMT_SEG_TO_VAL, - SKGE_RLMT, SK_RLMT_SEG_TIM, Para); - break; - } - } /* for (i = 0; i < pNet->NumPorts; i++) */ - - /* 2000-03-06 RA: Moved here. */ - /* Segmentation check not running anymore. */ - pNet->CheckingState &= ~SK_RLMT_RCS_SEG; - -} /* SkRlmtCheckSeg */ - - -/****************************************************************************** - * - * SkRlmtPortStart - initialize port variables and start port - * - * Description: - * This routine initializes a port's variables and issues a PORT_START - * to the HWAC module. This handles retries if the start fails or the - * link eventually goes down. - * - * Context: - * runtime, pageable? - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtPortStart( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 PortNumber) /* Port number */ -{ - SK_EVPARA Para; - - pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_LINK_DOWN; - pAC->Rlmt.Port[PortNumber].PortStarted = SK_TRUE; - pAC->Rlmt.Port[PortNumber].LinkDown = SK_TRUE; - pAC->Rlmt.Port[PortNumber].PortDown = SK_TRUE; - pAC->Rlmt.Port[PortNumber].CheckingState = 0; - pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE; - Para.Para32[0] = PortNumber; - Para.Para32[1] = (SK_U32)-1; - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); -} /* SkRlmtPortStart */ - - -/****************************************************************************** - * - * SkRlmtEvtPortStartTim - PORT_START_TIM - * - * Description: - * This routine handles PORT_START_TIM events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtPortStartTim( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ -{ - SK_U32 i; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTSTART_TIMEOUT Port %d Event BEGIN.\n", Para.Para32[0])) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTSTART_TIMEOUT Event EMPTY.\n")) - return; - } - - /* - * Used to start non-preferred ports if the preferred one - * does not come up. - * This timeout needs only be set when starting the first - * (preferred) port. - */ - if (pAC->Rlmt.Port[Para.Para32[0]].LinkDown) { - /* PORT_START failed. */ - for (i = 0; i < pAC->Rlmt.Port[Para.Para32[0]].Net->NumPorts; i++) { - if (!pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortStarted) { - SkRlmtPortStart(pAC, IoC, - pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortNumber); - } - } - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTSTART_TIMEOUT Event END.\n")) -} /* SkRlmtEvtPortStartTim */ - - -/****************************************************************************** - * - * SkRlmtEvtLinkUp - LINK_UP - * - * Description: - * This routine handles LLINK_UP events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtLinkUp( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 Undefined */ -{ - SK_U32 i; - SK_RLMT_PORT *pRPort; - SK_EVPARA Para2; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_UP Port %d Event BEGIN.\n", Para.Para32[0])) - - pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; - if (!pRPort->PortStarted) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E008, SKERR_RLMT_E008_MSG); - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_UP Event EMPTY.\n")) - return; - } - - if (!pRPort->LinkDown) { - /* RA;:;: Any better solution? */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_UP Event EMPTY.\n")) - return; - } - - SkTimerStop(pAC, IoC, &pRPort->UpTimer); - SkTimerStop(pAC, IoC, &pRPort->DownRxTimer); - SkTimerStop(pAC, IoC, &pRPort->DownTxTimer); - - /* Do something if timer already fired? */ - - pRPort->LinkDown = SK_FALSE; - pRPort->PortState = SK_RLMT_PS_GOING_UP; - pRPort->GuTimeStamp = SkOsGetTime(pAC); - pRPort->BcTimeStamp = 0; - pRPort->Net->LinksUp++; - if (pRPort->Net->LinksUp == 1) { - SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_ACTIVE); - } - else { - SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY); - } - - for (i = 0; i < pRPort->Net->NumPorts; i++) { - if (!pRPort->Net->Port[i]->PortStarted) { - SkRlmtPortStart(pAC, IoC, pRPort->Net->Port[i]->PortNumber); - } - } - - SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); - - if (pRPort->Net->LinksUp >= 2) { - if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) { - /* Build the check chain. */ - SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber); - } - } - - /* If the first link comes up, start the periodical RLMT timeout. */ - if (pRPort->Net->NumPorts > 1 && pRPort->Net->LinksUp == 1 && - (pRPort->Net->RlmtMode & SK_RLMT_CHECK_OTHERS) != 0) { - Para2.Para32[0] = pRPort->Net->NetNumber; - Para2.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pRPort->Net->LocTimer, - pRPort->Net->TimeoutValue, SKGE_RLMT, SK_RLMT_TIM, Para2); - } - - Para2 = Para; - Para2.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL, - SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para2); - - /* Later: if (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_LOC_LINK) && */ - if ((pRPort->Net->RlmtMode & SK_RLMT_TRANSPARENT) == 0 && - (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LINK) != 0 && - (Para2.pParaPtr = - SkRlmtBuildPacket(pAC, IoC, Para.Para32[0], SK_PACKET_ANNOUNCE, - &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress, &SkRlmtMcAddr) - ) != NULL) { - /* Send "new" packet to RLMT multicast address. */ - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2); - } - - if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_SEG) { - if ((Para2.pParaPtr = - SkRlmtBuildSpanningTreePacket(pAC, IoC, Para.Para32[0])) != NULL) { - pAC->Rlmt.Port[Para.Para32[0]].RootIdSet = SK_FALSE; - pRPort->Net->CheckingState |= - SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG; - - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2); - - Para.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pRPort->Net->SegTimer, - SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para); - } - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_UP Event END.\n")) -} /* SkRlmtEvtLinkUp */ - - -/****************************************************************************** - * - * SkRlmtEvtPortUpTim - PORT_UP_TIM - * - * Description: - * This routine handles PORT_UP_TIM events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtPortUpTim( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ -{ - SK_RLMT_PORT *pRPort; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTUP_TIM Port %d Event BEGIN.\n", Para.Para32[0])) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTUP_TIM Event EMPTY.\n")) - return; - } - - pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; - if (pRPort->LinkDown || (pRPort->PortState == SK_RLMT_PS_UP)) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTUP_TIM Port %d Event EMPTY.\n", Para.Para32[0])) - return; - } - - pRPort->PortDown = SK_FALSE; - pRPort->PortState = SK_RLMT_PS_UP; - pRPort->Net->PortsUp++; - if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) { - if (pAC->Rlmt.NumNets <= 1) { - SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); - } - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_UP, Para); - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTUP_TIM Event END.\n")) -} /* SkRlmtEvtPortUpTim */ - - -/****************************************************************************** - * - * SkRlmtEvtPortDownTim - PORT_DOWN_* - * - * Description: - * This routine handles PORT_DOWN_* events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtPortDownX( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Event, /* Event code */ -SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ -{ - SK_RLMT_PORT *pRPort; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTDOWN* Port %d Event (%d) BEGIN.\n", - Para.Para32[0], Event)) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTDOWN* Event EMPTY.\n")) - return; - } - - pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; - if (!pRPort->PortStarted || (Event == SK_RLMT_PORTDOWN_TX_TIM && - !(pRPort->CheckingState & SK_RLMT_PCS_TX))) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTDOWN* Event (%d) EMPTY.\n", Event)) - return; - } - - /* Stop port's timers. */ - SkTimerStop(pAC, IoC, &pRPort->UpTimer); - SkTimerStop(pAC, IoC, &pRPort->DownRxTimer); - SkTimerStop(pAC, IoC, &pRPort->DownTxTimer); - - if (pRPort->PortState != SK_RLMT_PS_LINK_DOWN) { - pRPort->PortState = SK_RLMT_PS_DOWN; - } - - if (!pRPort->PortDown) { - pRPort->Net->PortsUp--; - pRPort->PortDown = SK_TRUE; - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_DOWN, Para); - } - - pRPort->PacketsPerTimeSlot = 0; - /* pRPort->DataPacketsPerTimeSlot = 0; */ - pRPort->BpduPacketsPerTimeSlot = 0; - pRPort->BcTimeStamp = 0; - - /* - * RA;:;: To be checked: - * - actions at RLMT_STOP: We should not switch anymore. - */ - if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) { - if (Para.Para32[0] == - pRPort->Net->Port[pRPort->Net->ActivePort]->PortNumber) { - /* Active Port went down. */ - SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); - } - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTDOWN* Event (%d) END.\n", Event)) -} /* SkRlmtEvtPortDownX */ - - -/****************************************************************************** - * - * SkRlmtEvtLinkDown - LINK_DOWN - * - * Description: - * This routine handles LINK_DOWN events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtLinkDown( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 Undefined */ -{ - SK_RLMT_PORT *pRPort; - - pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_DOWN Port %d Event BEGIN.\n", Para.Para32[0])) - - if (!pAC->Rlmt.Port[Para.Para32[0]].LinkDown) { - pRPort->Net->LinksUp--; - pRPort->LinkDown = SK_TRUE; - pRPort->PortState = SK_RLMT_PS_LINK_DOWN; - SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_OFF); - - if ((pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) != 0) { - /* Build the check chain. */ - SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber); - } - - /* Ensure that port is marked down. */ - Para.Para32[1] = -1; - (void)SkRlmtEvent(pAC, IoC, SK_RLMT_PORTDOWN, Para); - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_DOWN Event END.\n")) -} /* SkRlmtEvtLinkDown */ - - -/****************************************************************************** - * - * SkRlmtEvtPortAddr - PORT_ADDR - * - * Description: - * This routine handles PORT_ADDR events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtPortAddr( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ -{ - SK_U32 i, j; - SK_RLMT_PORT *pRPort; - SK_MAC_ADDR *pOldMacAddr; - SK_MAC_ADDR *pNewMacAddr; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORT_ADDR Port %d Event BEGIN.\n", Para.Para32[0])) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORT_ADDR Event EMPTY.\n")) - return; - } - - /* Port's physical MAC address changed. */ - pOldMacAddr = &pAC->Addr.Port[Para.Para32[0]].PreviousMacAddress; - pNewMacAddr = &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress; - - /* - * NOTE: This is not scalable for solutions where ports are - * checked remotely. There, we need to send an RLMT - * address change packet - and how do we ensure delivery? - */ - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - pRPort = &pAC->Rlmt.Port[i]; - for (j = 0; j < pRPort->PortsChecked; j++) { - if (SK_ADDR_EQUAL( - pRPort->PortCheck[j].CheckAddr.a, pOldMacAddr->a)) { - pRPort->PortCheck[j].CheckAddr = *pNewMacAddr; - } - } - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORT_ADDR Event END.\n")) -} /* SkRlmtEvtPortAddr */ - - -/****************************************************************************** - * - * SkRlmtEvtStart - START - * - * Description: - * This routine handles START events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtStart( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ -{ - SK_EVPARA Para2; - SK_U32 PortIdx; - SK_U32 PortNumber; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Net %d Event BEGIN.\n", Para.Para32[0])) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Event EMPTY.\n")) - return; - } - - if (Para.Para32[0] >= pAC->Rlmt.NumNets) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[0])) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Event EMPTY.\n")) - return; - } - - if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState != SK_RLMT_RS_INIT) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Event EMPTY.\n")) - return; - } - - if (pAC->Rlmt.NetsStarted >= pAC->Rlmt.NumNets) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("All nets should have been started.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Event EMPTY.\n")) - return; - } - - if (pAC->Rlmt.Net[Para.Para32[0]].PrefPort >= - pAC->Rlmt.Net[Para.Para32[0]].NumPorts) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E009, SKERR_RLMT_E009_MSG); - - /* Change PrefPort to internal default. */ - Para2.Para32[0] = 0xFFFFFFFF; - Para2.Para32[1] = Para.Para32[0]; - (void)SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE, Para2); - } - - PortIdx = pAC->Rlmt.Net[Para.Para32[0]].PrefPort; - PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[PortIdx]->PortNumber; - - pAC->Rlmt.Net[Para.Para32[0]].LinksUp = 0; - pAC->Rlmt.Net[Para.Para32[0]].PortsUp = 0; - pAC->Rlmt.Net[Para.Para32[0]].CheckingState = 0; - pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_NET_DOWN; - - /* Start preferred port. */ - SkRlmtPortStart(pAC, IoC, PortNumber); - - /* Start Timer (for first port only). */ - Para2.Para32[0] = PortNumber; - Para2.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer, - SK_RLMT_PORTSTART_TIM_VAL, SKGE_RLMT, SK_RLMT_PORTSTART_TIM, Para2); - - pAC->Rlmt.NetsStarted++; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Event END.\n")) -} /* SkRlmtEvtStart */ - - -/****************************************************************************** - * - * SkRlmtEvtStop - STOP - * - * Description: - * This routine handles STOP events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtStop( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ -{ - SK_EVPARA Para2; - SK_U32 PortNumber; - SK_U32 i; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Net %d Event BEGIN.\n", Para.Para32[0])) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Event EMPTY.\n")) - return; - } - - if (Para.Para32[0] >= pAC->Rlmt.NumNets) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[0])) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Event EMPTY.\n")) - return; - } - - if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState == SK_RLMT_RS_INIT) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Event EMPTY.\n")) - return; - } - - if (pAC->Rlmt.NetsStarted == 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("All nets are stopped.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Event EMPTY.\n")) - return; - } - - /* Stop RLMT timers. */ - SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer); - SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer); - - /* Stop net. */ - pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_INIT; - pAC->Rlmt.Net[Para.Para32[0]].RootIdSet = SK_FALSE; - Para2.Para32[0] = SK_RLMT_NET_DOWN_FINAL; - Para2.Para32[1] = Para.Para32[0]; /* Net# */ - SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para2); - - /* Stop ports. */ - for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) { - PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber; - if (pAC->Rlmt.Port[PortNumber].PortState != SK_RLMT_PS_INIT) { - SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer); - SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownRxTimer); - SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownTxTimer); - - pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_INIT; - pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE; - pAC->Rlmt.Port[PortNumber].PortStarted = SK_FALSE; - Para2.Para32[0] = PortNumber; - Para2.Para32[1] = (SK_U32)-1; - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para2); - } - } - - pAC->Rlmt.NetsStarted--; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Event END.\n")) -} /* SkRlmtEvtStop */ - - -/****************************************************************************** - * - * SkRlmtEvtTim - TIM - * - * Description: - * This routine handles TIM events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtTim( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ -{ - SK_RLMT_PORT *pRPort; - SK_U32 Timeout; - SK_U32 NewTimeout; - SK_U32 PortNumber; - SK_U32 i; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_TIM Event BEGIN.\n")) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_TIM Event EMPTY.\n")) - return; - } - - if ((pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_OTHERS) == 0 || - pAC->Rlmt.Net[Para.Para32[0]].LinksUp == 0) { - /* Mode changed or all links down: No more link checking. */ - return; - } - -#if 0 - pAC->Rlmt.SwitchCheckCounter--; - if (pAC->Rlmt.SwitchCheckCounter == 0) { - pAC->Rlmt.SwitchCheckCounter; - } -#endif /* 0 */ - - NewTimeout = SK_RLMT_DEF_TO_VAL; - for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) { - PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber; - pRPort = &pAC->Rlmt.Port[PortNumber]; - if (!pRPort->LinkDown) { - Timeout = SkRlmtCheckPort(pAC, IoC, PortNumber); - if (Timeout < NewTimeout) { - NewTimeout = Timeout; - } - - /* - * These counters should be set to 0 for all ports before the - * first frame is sent in the next loop. - */ - pRPort->PacketsPerTimeSlot = 0; - /* pRPort->DataPacketsPerTimeSlot = 0; */ - pRPort->BpduPacketsPerTimeSlot = 0; - } - } - pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue = NewTimeout; - - if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1) { - /* - * If checking remote ports, also send packets if - * (LinksUp == 1) && - * this port checks at least one (remote) port. - */ - - /* - * Must be new loop, as SkRlmtCheckPort can request to - * check segmentation when e.g. checking the last port. - */ - for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) { - if (!pAC->Rlmt.Net[Para.Para32[0]].Port[i]->LinkDown) { - SkRlmtSend(pAC, IoC, - pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber); - } - } - } - - SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer, - pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue, SKGE_RLMT, SK_RLMT_TIM, - Para); - - if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1 && - (pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_SEG) && - (pAC->Rlmt.Net[Para.Para32[0]].CheckingState & SK_RLMT_RCS_START_SEG)) { - SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer, - SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para); - pAC->Rlmt.Net[Para.Para32[0]].CheckingState &= ~SK_RLMT_RCS_START_SEG; - pAC->Rlmt.Net[Para.Para32[0]].CheckingState |= - SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_TIM Event END.\n")) -} /* SkRlmtEvtTim */ - - -/****************************************************************************** - * - * SkRlmtEvtSegTim - SEG_TIM - * - * Description: - * This routine handles SEG_TIM events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtSegTim( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ -{ -#ifdef xDEBUG - int j; -#endif /* DEBUG */ - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SEG_TIM Event BEGIN.\n")) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SEG_TIM Event EMPTY.\n")) - return; - } - -#ifdef xDEBUG - for (j = 0; j < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; j++) { - SK_ADDR_PORT *pAPort; - SK_U32 k; - SK_U16 *InAddr; - SK_U8 InAddr8[6]; - - InAddr = (SK_U16 *)&InAddr8[0]; - pAPort = pAC->Rlmt.Net[Para.Para32[0]].Port[j]->AddrPort; - for (k = 0; k < pAPort->NextExactMatchRlmt; k++) { - /* Get exact match address k from port j. */ - XM_INADDR(IoC, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber, - XM_EXM(k), InAddr); - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("MC address %d on Port %u: %02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x.\n", - k, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber, - InAddr8[0], InAddr8[1], InAddr8[2], - InAddr8[3], InAddr8[4], InAddr8[5], - pAPort->Exact[k].a[0], pAPort->Exact[k].a[1], - pAPort->Exact[k].a[2], pAPort->Exact[k].a[3], - pAPort->Exact[k].a[4], pAPort->Exact[k].a[5])) - } - } -#endif /* xDEBUG */ - - SkRlmtCheckSeg(pAC, IoC, Para.Para32[0]); - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SEG_TIM Event END.\n")) -} /* SkRlmtEvtSegTim */ - - -/****************************************************************************** - * - * SkRlmtEvtPacketRx - PACKET_RECEIVED - * - * Description: - * This routine handles PACKET_RECEIVED events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtPacketRx( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_MBUF *pMb */ -{ - SK_MBUF *pMb; - SK_MBUF *pNextMb; - SK_U32 NetNumber; - - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PACKET_RECEIVED Event BEGIN.\n")) - - /* Should we ignore frames during port switching? */ - -#ifdef DEBUG - pMb = Para.pParaPtr; - if (pMb == NULL) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("No mbuf.\n")) - } - else if (pMb->pNext != NULL) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("More than one mbuf or pMb->pNext not set.\n")) - } -#endif /* DEBUG */ - - for (pMb = Para.pParaPtr; pMb != NULL; pMb = pNextMb) { - pNextMb = pMb->pNext; - pMb->pNext = NULL; - - NetNumber = pAC->Rlmt.Port[pMb->PortIdx].Net->NetNumber; - if (pAC->Rlmt.Net[NetNumber].RlmtState == SK_RLMT_RS_INIT) { - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - } - else { - SkRlmtPacketReceive(pAC, IoC, pMb); - } - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PACKET_RECEIVED Event END.\n")) -} /* SkRlmtEvtPacketRx */ - - -/****************************************************************************** - * - * SkRlmtEvtStatsClear - STATS_CLEAR - * - * Description: - * This routine handles STATS_CLEAR events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtStatsClear( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ -{ - SK_U32 i; - SK_RLMT_PORT *pRPort; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_CLEAR Event BEGIN.\n")) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_CLEAR Event EMPTY.\n")) - return; - } - - if (Para.Para32[0] >= pAC->Rlmt.NumNets) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[0])) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_CLEAR Event EMPTY.\n")) - return; - } - - /* Clear statistics for logical and physical ports. */ - for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) { - pRPort = - &pAC->Rlmt.Port[pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber]; - pRPort->TxHelloCts = 0; - pRPort->RxHelloCts = 0; - pRPort->TxSpHelloReqCts = 0; - pRPort->RxSpHelloCts = 0; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_CLEAR Event END.\n")) -} /* SkRlmtEvtStatsClear */ - - -/****************************************************************************** - * - * SkRlmtEvtStatsUpdate - STATS_UPDATE - * - * Description: - * This routine handles STATS_UPDATE events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtStatsUpdate( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ -{ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_UPDATE Event BEGIN.\n")) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_UPDATE Event EMPTY.\n")) - return; - } - - if (Para.Para32[0] >= pAC->Rlmt.NumNets) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[0])) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_UPDATE Event EMPTY.\n")) - return; - } - - /* Update statistics - currently always up-to-date. */ - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_UPDATE Event END.\n")) -} /* SkRlmtEvtStatsUpdate */ - - -/****************************************************************************** - * - * SkRlmtEvtPrefportChange - PREFPORT_CHANGE - * - * Description: - * This routine handles PREFPORT_CHANGE events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtPrefportChange( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 PortIndex; SK_U32 NetNumber */ -{ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PREFPORT_CHANGE to Port %d Event BEGIN.\n", Para.Para32[0])) - - if (Para.Para32[1] >= pAC->Rlmt.NumNets) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[1])) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n")) - return; - } - - /* 0xFFFFFFFF == auto-mode. */ - if (Para.Para32[0] == 0xFFFFFFFF) { - pAC->Rlmt.Net[Para.Para32[1]].PrefPort = SK_RLMT_DEF_PREF_PORT; - } - else { - if (Para.Para32[0] >= pAC->Rlmt.Net[Para.Para32[1]].NumPorts) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E010, SKERR_RLMT_E010_MSG); - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n")) - return; - } - - pAC->Rlmt.Net[Para.Para32[1]].PrefPort = Para.Para32[0]; - } - - pAC->Rlmt.Net[Para.Para32[1]].Preference = Para.Para32[0]; - - if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) { - SkRlmtCheckSwitch(pAC, IoC, Para.Para32[1]); - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PREFPORT_CHANGE Event END.\n")) -} /* SkRlmtEvtPrefportChange */ - - -/****************************************************************************** - * - * SkRlmtEvtSetNets - SET_NETS - * - * Description: - * This routine handles SET_NETS events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtSetNets( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NumNets; SK_U32 -1 */ -{ - int i; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event BEGIN.\n")) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event EMPTY.\n")) - return; - } - - if (Para.Para32[0] == 0 || Para.Para32[0] > SK_MAX_NETS || - Para.Para32[0] > (SK_U32)pAC->GIni.GIMacsFound) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad number of nets: %d.\n", Para.Para32[0])) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event EMPTY.\n")) - return; - } - - if (Para.Para32[0] == pAC->Rlmt.NumNets) { /* No change. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event EMPTY.\n")) - return; - } - - /* Entering and leaving dual mode only allowed while nets are stopped. */ - if (pAC->Rlmt.NetsStarted > 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Changing dual mode only allowed while all nets are stopped.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event EMPTY.\n")) - return; - } - - if (Para.Para32[0] == 1) { - if (pAC->Rlmt.NumNets > 1) { - /* Clear logical MAC addr from second net's active port. */ - (void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr. - Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_CLEAR_LOGICAL); - pAC->Rlmt.Net[1].NumPorts = 0; - } - - pAC->Rlmt.NumNets = Para.Para32[0]; - for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) { - pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT; - pAC->Rlmt.Net[i].RootIdSet = SK_FALSE; - pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* "Automatic" */ - pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT; - /* Just assuming. */ - pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort; - pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE; - pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL; - pAC->Rlmt.Net[i].NetNumber = i; - } - - pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[0]; - pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound; - - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para); - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("RLMT: Changed to one net with two ports.\n")) - } - else if (Para.Para32[0] == 2) { - pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[1]; - pAC->Rlmt.Net[1].NumPorts = pAC->GIni.GIMacsFound - 1; - pAC->Rlmt.Net[0].NumPorts = - pAC->GIni.GIMacsFound - pAC->Rlmt.Net[1].NumPorts; - - pAC->Rlmt.NumNets = Para.Para32[0]; - for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) { - pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT; - pAC->Rlmt.Net[i].RootIdSet = SK_FALSE; - pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* "Automatic" */ - pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT; - /* Just assuming. */ - pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort; - pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE; - pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL; - - pAC->Rlmt.Net[i].NetNumber = i; - } - - /* Set logical MAC addr on second net's active port. */ - (void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr. - Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_SET_LOGICAL); - - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para); - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("RLMT: Changed to two nets with one port each.\n")) - } - else { - /* Not implemented for more than two nets. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SetNets not implemented for more than two nets.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event EMPTY.\n")) - return; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event END.\n")) -} /* SkRlmtSetNets */ - - -/****************************************************************************** - * - * SkRlmtEvtModeChange - MODE_CHANGE - * - * Description: - * This routine handles MODE_CHANGE events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtModeChange( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NewMode; SK_U32 NetNumber */ -{ - SK_EVPARA Para2; - SK_U32 i; - SK_U32 PrevRlmtMode; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_MODE_CHANGE Event BEGIN.\n")) - - if (Para.Para32[1] >= pAC->Rlmt.NumNets) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[1])) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_MODE_CHANGE Event EMPTY.\n")) - return; - } - - Para.Para32[0] |= SK_RLMT_CHECK_LINK; - - if ((pAC->Rlmt.Net[Para.Para32[1]].NumPorts == 1) && - Para.Para32[0] != SK_RLMT_MODE_CLS) { - pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = SK_RLMT_MODE_CLS; - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Forced RLMT mode to CLS on single port net.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_MODE_CHANGE Event EMPTY.\n")) - return; - } - - /* Update RLMT mode. */ - PrevRlmtMode = pAC->Rlmt.Net[Para.Para32[1]].RlmtMode; - pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = Para.Para32[0]; - - if ((PrevRlmtMode & SK_RLMT_CHECK_LOC_LINK) != - (pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) { - /* SK_RLMT_CHECK_LOC_LINK bit changed. */ - if ((PrevRlmtMode & SK_RLMT_CHECK_OTHERS) == 0 && - pAC->Rlmt.Net[Para.Para32[1]].NumPorts > 1 && - pAC->Rlmt.Net[Para.Para32[1]].PortsUp >= 1) { - /* 20001207 RA: Was "PortsUp == 1". */ - Para2.Para32[0] = Para.Para32[1]; - Para2.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].LocTimer, - pAC->Rlmt.Net[Para.Para32[1]].TimeoutValue, - SKGE_RLMT, SK_RLMT_TIM, Para2); - } - } - - if ((PrevRlmtMode & SK_RLMT_CHECK_SEG) != - (pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG)) { - /* SK_RLMT_CHECK_SEG bit changed. */ - for (i = 0; i < pAC->Rlmt.Net[Para.Para32[1]].NumPorts; i++) { - (void)SkAddrMcClear(pAC, IoC, - pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber, - SK_ADDR_PERMANENT | SK_MC_SW_ONLY); - - /* Add RLMT MC address. */ - (void)SkAddrMcAdd(pAC, IoC, - pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber, - &SkRlmtMcAddr, SK_ADDR_PERMANENT); - - if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & - SK_RLMT_CHECK_SEG) != 0) { - /* Add BPDU MC address. */ - (void)SkAddrMcAdd(pAC, IoC, - pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber, - &BridgeMcAddr, SK_ADDR_PERMANENT); - - if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) { - if (!pAC->Rlmt.Net[Para.Para32[1]].Port[i]->LinkDown && - (Para2.pParaPtr = SkRlmtBuildSpanningTreePacket( - pAC, IoC, i)) != NULL) { - pAC->Rlmt.Net[Para.Para32[1]].Port[i]->RootIdSet = - SK_FALSE; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2); - } - } - } - (void)SkAddrMcUpdate(pAC, IoC, - pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber); - } /* for ... */ - - if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG) != 0) { - Para2.Para32[0] = Para.Para32[1]; - Para2.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].SegTimer, - SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para2); - } - } /* SK_RLMT_CHECK_SEG bit changed. */ - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_MODE_CHANGE Event END.\n")) -} /* SkRlmtEvtModeChange */ - - -/****************************************************************************** - * - * SkRlmtEvent - a PORT- or an RLMT-specific event happened - * - * Description: - * This routine calls subroutines to handle PORT- and RLMT-specific events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * 0 - */ -int SkRlmtEvent( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Event, /* Event code */ -SK_EVPARA Para) /* Event-specific parameter */ -{ - switch (Event) { - - /* ----- PORT events ----- */ - - case SK_RLMT_PORTSTART_TIM: /* From RLMT via TIME. */ - SkRlmtEvtPortStartTim(pAC, IoC, Para); - break; - case SK_RLMT_LINK_UP: /* From SIRQ. */ - SkRlmtEvtLinkUp(pAC, IoC, Para); - break; - case SK_RLMT_PORTUP_TIM: /* From RLMT via TIME. */ - SkRlmtEvtPortUpTim(pAC, IoC, Para); - break; - case SK_RLMT_PORTDOWN: /* From RLMT. */ - case SK_RLMT_PORTDOWN_RX_TIM: /* From RLMT via TIME. */ - case SK_RLMT_PORTDOWN_TX_TIM: /* From RLMT via TIME. */ - SkRlmtEvtPortDownX(pAC, IoC, Event, Para); - break; - case SK_RLMT_LINK_DOWN: /* From SIRQ. */ - SkRlmtEvtLinkDown(pAC, IoC, Para); - break; - case SK_RLMT_PORT_ADDR: /* From ADDR. */ - SkRlmtEvtPortAddr(pAC, IoC, Para); - break; - - /* ----- RLMT events ----- */ - - case SK_RLMT_START: /* From DRV. */ - SkRlmtEvtStart(pAC, IoC, Para); - break; - case SK_RLMT_STOP: /* From DRV. */ - SkRlmtEvtStop(pAC, IoC, Para); - break; - case SK_RLMT_TIM: /* From RLMT via TIME. */ - SkRlmtEvtTim(pAC, IoC, Para); - break; - case SK_RLMT_SEG_TIM: - SkRlmtEvtSegTim(pAC, IoC, Para); - break; - case SK_RLMT_PACKET_RECEIVED: /* From DRV. */ - SkRlmtEvtPacketRx(pAC, IoC, Para); - break; - case SK_RLMT_STATS_CLEAR: /* From PNMI. */ - SkRlmtEvtStatsClear(pAC, IoC, Para); - break; - case SK_RLMT_STATS_UPDATE: /* From PNMI. */ - SkRlmtEvtStatsUpdate(pAC, IoC, Para); - break; - case SK_RLMT_PREFPORT_CHANGE: /* From PNMI. */ - SkRlmtEvtPrefportChange(pAC, IoC, Para); - break; - case SK_RLMT_MODE_CHANGE: /* From PNMI. */ - SkRlmtEvtModeChange(pAC, IoC, Para); - break; - case SK_RLMT_SET_NETS: /* From DRV. */ - SkRlmtEvtSetNets(pAC, IoC, Para); - break; - - /* ----- Unknown events ----- */ - - default: /* Create error log entry. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Unknown RLMT Event %d.\n", Event)) - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E003, SKERR_RLMT_E003_MSG); - break; - } /* switch() */ - - return (0); -} /* SkRlmtEvent */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ diff --git a/drivers/net/sk98lin/sktimer.c b/drivers/net/sk98lin/sktimer.c deleted file mode 100644 index 4e462955ecd..00000000000 --- a/drivers/net/sk98lin/sktimer.c +++ /dev/null @@ -1,250 +0,0 @@ -/****************************************************************************** - * - * Name: sktimer.c - * Project: Gigabit Ethernet Adapters, Event Scheduler Module - * Version: $Revision: 1.14 $ - * Date: $Date: 2003/09/16 13:46:51 $ - * Purpose: High level timer functions. - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - - -/* - * Event queue and dispatcher - */ -#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) -static const char SysKonnectFileId[] = - "@(#) $Id: sktimer.c,v 1.14 2003/09/16 13:46:51 rschmidt Exp $ (C) Marvell."; -#endif - -#include "h/skdrv1st.h" /* Driver Specific Definitions */ -#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ - -#ifdef __C2MAN__ -/* - Event queue management. - - General Description: - - */ -intro() -{} -#endif - - -/* Forward declaration */ -static void timer_done(SK_AC *pAC,SK_IOC Ioc,int Restart); - - -/* - * Inits the software timer - * - * needs to be called during Init level 1. - */ -void SkTimerInit( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc, /* IoContext */ -int Level) /* Init Level */ -{ - switch (Level) { - case SK_INIT_DATA: - pAC->Tim.StQueue = NULL; - break; - case SK_INIT_IO: - SkHwtInit(pAC, Ioc); - SkTimerDone(pAC, Ioc); - break; - default: - break; - } -} - -/* - * Stops a high level timer - * - If a timer is not in the queue the function returns normally, too. - */ -void SkTimerStop( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc, /* IoContext */ -SK_TIMER *pTimer) /* Timer Pointer to be started */ -{ - SK_TIMER **ppTimPrev; - SK_TIMER *pTm; - - /* - * remove timer from queue - */ - pTimer->TmActive = SK_FALSE; - - if (pAC->Tim.StQueue == pTimer && !pTimer->TmNext) { - SkHwtStop(pAC, Ioc); - } - - for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev); - ppTimPrev = &pTm->TmNext ) { - - if (pTm == pTimer) { - /* - * Timer found in queue - * - dequeue it and - * - correct delta of the next timer - */ - *ppTimPrev = pTm->TmNext; - - if (pTm->TmNext) { - /* correct delta of next timer in queue */ - pTm->TmNext->TmDelta += pTm->TmDelta; - } - return; - } - } -} - -/* - * Start a high level software timer - */ -void SkTimerStart( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc, /* IoContext */ -SK_TIMER *pTimer, /* Timer Pointer to be started */ -SK_U32 Time, /* Time value */ -SK_U32 Class, /* Event Class for this timer */ -SK_U32 Event, /* Event Value for this timer */ -SK_EVPARA Para) /* Event Parameter for this timer */ -{ - SK_TIMER **ppTimPrev; - SK_TIMER *pTm; - SK_U32 Delta; - - Time /= 16; /* input is uS, clock ticks are 16uS */ - - if (!Time) - Time = 1; - - SkTimerStop(pAC, Ioc, pTimer); - - pTimer->TmClass = Class; - pTimer->TmEvent = Event; - pTimer->TmPara = Para; - pTimer->TmActive = SK_TRUE; - - if (!pAC->Tim.StQueue) { - /* First Timer to be started */ - pAC->Tim.StQueue = pTimer; - pTimer->TmNext = NULL; - pTimer->TmDelta = Time; - - SkHwtStart(pAC, Ioc, Time); - - return; - } - - /* - * timer correction - */ - timer_done(pAC, Ioc, 0); - - /* - * find position in queue - */ - Delta = 0; - for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev); - ppTimPrev = &pTm->TmNext ) { - - if (Delta + pTm->TmDelta > Time) { - /* Position found */ - /* Here the timer needs to be inserted. */ - break; - } - Delta += pTm->TmDelta; - } - - /* insert in queue */ - *ppTimPrev = pTimer; - pTimer->TmNext = pTm; - pTimer->TmDelta = Time - Delta; - - if (pTm) { - /* There is a next timer - * -> correct its Delta value. - */ - pTm->TmDelta -= pTimer->TmDelta; - } - - /* restart with first */ - SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta); -} - - -void SkTimerDone( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc) /* IoContext */ -{ - timer_done(pAC, Ioc, 1); -} - - -static void timer_done( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc, /* IoContext */ -int Restart) /* Do we need to restart the Hardware timer ? */ -{ - SK_U32 Delta; - SK_TIMER *pTm; - SK_TIMER *pTComp; /* Timer completed now now */ - SK_TIMER **ppLast; /* Next field of Last timer to be deq */ - int Done = 0; - - Delta = SkHwtRead(pAC, Ioc); - - ppLast = &pAC->Tim.StQueue; - pTm = pAC->Tim.StQueue; - while (pTm && !Done) { - if (Delta >= pTm->TmDelta) { - /* Timer ran out */ - pTm->TmActive = SK_FALSE; - Delta -= pTm->TmDelta; - ppLast = &pTm->TmNext; - pTm = pTm->TmNext; - } - else { - /* We found the first timer that did not run out */ - pTm->TmDelta -= Delta; - Delta = 0; - Done = 1; - } - } - *ppLast = NULL; - /* - * pTm points to the first Timer that did not run out. - * StQueue points to the first Timer that run out. - */ - - for ( pTComp = pAC->Tim.StQueue; pTComp; pTComp = pTComp->TmNext) { - SkEventQueue(pAC,pTComp->TmClass, pTComp->TmEvent, pTComp->TmPara); - } - - /* Set head of timer queue to the first timer that did not run out */ - pAC->Tim.StQueue = pTm; - - if (Restart && pAC->Tim.StQueue) { - /* Restart HW timer */ - SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta); - } -} - -/* End of file */ diff --git a/drivers/net/sk98lin/skvpd.c b/drivers/net/sk98lin/skvpd.c deleted file mode 100644 index 1e662aaebf8..00000000000 --- a/drivers/net/sk98lin/skvpd.c +++ /dev/null @@ -1,1091 +0,0 @@ -/****************************************************************************** - * - * Name: skvpd.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.37 $ - * Date: $Date: 2003/01/13 10:42:45 $ - * Purpose: Shared software to read and write VPD data - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2003 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - Please refer skvpd.txt for information how to include this module - */ -static const char SysKonnectFileId[] = - "@(#)$Id: skvpd.c,v 1.37 2003/01/13 10:42:45 rschmidt Exp $ (C) SK"; - -#include "h/skdrv1st.h" -#include "h/sktypes.h" -#include "h/skdebug.h" -#include "h/skdrv2nd.h" - -/* - * Static functions - */ -#ifndef SK_KR_PROTO -static SK_VPD_PARA *vpd_find_para( - SK_AC *pAC, - const char *key, - SK_VPD_PARA *p); -#else /* SK_KR_PROTO */ -static SK_VPD_PARA *vpd_find_para(); -#endif /* SK_KR_PROTO */ - -/* - * waits for a completion of a VPD transfer - * The VPD transfer must complete within SK_TICKS_PER_SEC/16 - * - * returns 0: success, transfer completes - * error exit(9) with a error message - */ -static int VpdWait( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC, /* IO Context */ -int event) /* event to wait for (VPD_READ / VPD_write) completion*/ -{ - SK_U64 start_time; - SK_U16 state; - - SK_DBG_MSG(pAC,SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("VPD wait for %s\n", event?"Write":"Read")); - start_time = SkOsGetTime(pAC); - do { - if (SkOsGetTime(pAC) - start_time > SK_TICKS_PER_SEC) { - - /* Bug fix AF: Thu Mar 28 2002 - * Do not call: VPD_STOP(pAC, IoC); - * A pending VPD read cycle can not be aborted by writing - * VPD_WRITE to the PCI_VPD_ADR_REG (VPD address register). - * Although the write threshold in the OUR-register protects - * VPD read only space from being overwritten this does not - * protect a VPD read from being `converted` into a VPD write - * operation (on the fly). As a consequence the VPD_STOP would - * delete VPD read only data. In case of any problems with the - * I2C bus we exit the loop here. The I2C read operation can - * not be aborted except by a reset (->LR). - */ - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_FATAL | SK_DBGCAT_ERR, - ("ERROR:VPD wait timeout\n")); - return(1); - } - - VPD_IN16(pAC, IoC, PCI_VPD_ADR_REG, &state); - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("state = %x, event %x\n",state,event)); - } while((int)(state & PCI_VPD_FLAG) == event); - - return(0); -} - -#ifdef SKDIAG - -/* - * Read the dword at address 'addr' from the VPD EEPROM. - * - * Needed Time: MIN 1,3 ms MAX 2,6 ms - * - * Note: The DWord is returned in the endianess of the machine the routine - * is running on. - * - * Returns the data read. - */ -SK_U32 VpdReadDWord( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC, /* IO Context */ -int addr) /* VPD address */ -{ - SK_U32 Rtv; - - /* start VPD read */ - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("VPD read dword at 0x%x\n",addr)); - addr &= ~VPD_WRITE; /* ensure the R/W bit is set to read */ - - VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, (SK_U16)addr); - - /* ignore return code here */ - (void)VpdWait(pAC, IoC, VPD_READ); - - /* Don't swap here, it's a data stream of bytes */ - Rtv = 0; - - VPD_IN32(pAC, IoC, PCI_VPD_DAT_REG, &Rtv); - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("VPD read dword data = 0x%x\n",Rtv)); - return(Rtv); -} - -#endif /* SKDIAG */ - -/* - * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from - * or to the I2C EEPROM. - * - * Returns number of bytes read / written. - */ -static int VpdWriteStream( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC, /* IO Context */ -char *buf, /* data buffer */ -int Addr, /* VPD start address */ -int Len) /* number of bytes to read / to write */ -{ - int i; - int j; - SK_U16 AdrReg; - int Rtv; - SK_U8 * pComp; /* Compare pointer */ - SK_U8 Data; /* Input Data for Compare */ - - /* Init Compare Pointer */ - pComp = (SK_U8 *) buf; - - for (i = 0; i < Len; i++, buf++) { - if ((i%sizeof(SK_U32)) == 0) { - /* - * At the begin of each cycle read the Data Reg - * So it is initialized even if only a few bytes - * are written. - */ - AdrReg = (SK_U16) Addr; - AdrReg &= ~VPD_WRITE; /* READ operation */ - - VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg); - - /* Wait for termination */ - Rtv = VpdWait(pAC, IoC, VPD_READ); - if (Rtv != 0) { - return(i); - } - } - - /* Write current Byte */ - VPD_OUT8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)), - *(SK_U8*)buf); - - if (((i%sizeof(SK_U32)) == 3) || (i == (Len - 1))) { - /* New Address needs to be written to VPD_ADDR reg */ - AdrReg = (SK_U16) Addr; - Addr += sizeof(SK_U32); - AdrReg |= VPD_WRITE; /* WRITE operation */ - - VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg); - - /* Wait for termination */ - Rtv = VpdWait(pAC, IoC, VPD_WRITE); - if (Rtv != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("Write Timed Out\n")); - return(i - (i%sizeof(SK_U32))); - } - - /* - * Now re-read to verify - */ - AdrReg &= ~VPD_WRITE; /* READ operation */ - - VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg); - - /* Wait for termination */ - Rtv = VpdWait(pAC, IoC, VPD_READ); - if (Rtv != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("Verify Timed Out\n")); - return(i - (i%sizeof(SK_U32))); - } - - for (j = 0; j <= (int)(i%sizeof(SK_U32)); j++, pComp++) { - - VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + j, &Data); - - if (Data != *pComp) { - /* Verify Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("WriteStream Verify Error\n")); - return(i - (i%sizeof(SK_U32)) + j); - } - } - } - } - - return(Len); -} - - -/* - * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from - * or to the I2C EEPROM. - * - * Returns number of bytes read / written. - */ -static int VpdReadStream( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC, /* IO Context */ -char *buf, /* data buffer */ -int Addr, /* VPD start address */ -int Len) /* number of bytes to read / to write */ -{ - int i; - SK_U16 AdrReg; - int Rtv; - - for (i = 0; i < Len; i++, buf++) { - if ((i%sizeof(SK_U32)) == 0) { - /* New Address needs to be written to VPD_ADDR reg */ - AdrReg = (SK_U16) Addr; - Addr += sizeof(SK_U32); - AdrReg &= ~VPD_WRITE; /* READ operation */ - - VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg); - - /* Wait for termination */ - Rtv = VpdWait(pAC, IoC, VPD_READ); - if (Rtv != 0) { - return(i); - } - } - VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)), - (SK_U8 *)buf); - } - - return(Len); -} - -/* - * Read ore writes 'len' bytes of VPD data, starting at 'addr' from - * or to the I2C EEPROM. - * - * Returns number of bytes read / written. - */ -static int VpdTransferBlock( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC, /* IO Context */ -char *buf, /* data buffer */ -int addr, /* VPD start address */ -int len, /* number of bytes to read / to write */ -int dir) /* transfer direction may be VPD_READ or VPD_WRITE */ -{ - int Rtv; /* Return value */ - int vpd_rom_size; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("VPD %s block, addr = 0x%x, len = %d\n", - dir ? "write" : "read", addr, len)); - - if (len == 0) - return(0); - - vpd_rom_size = pAC->vpd.rom_size; - - if (addr > vpd_rom_size - 4) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Address error: 0x%x, exp. < 0x%x\n", - addr, vpd_rom_size - 4)); - return(0); - } - - if (addr + len > vpd_rom_size) { - len = vpd_rom_size - addr; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("Warning: len was cut to %d\n", len)); - } - - if (dir == VPD_READ) { - Rtv = VpdReadStream(pAC, IoC, buf, addr, len); - } - else { - Rtv = VpdWriteStream(pAC, IoC, buf, addr, len); - } - - return(Rtv); -} - -#ifdef SKDIAG - -/* - * Read 'len' bytes of VPD data, starting at 'addr'. - * - * Returns number of bytes read. - */ -int VpdReadBlock( -SK_AC *pAC, /* pAC pointer */ -SK_IOC IoC, /* IO Context */ -char *buf, /* buffer were the data should be stored */ -int addr, /* start reading at the VPD address */ -int len) /* number of bytes to read */ -{ - return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_READ)); -} - -/* - * Write 'len' bytes of *but to the VPD EEPROM, starting at 'addr'. - * - * Returns number of bytes writes. - */ -int VpdWriteBlock( -SK_AC *pAC, /* pAC pointer */ -SK_IOC IoC, /* IO Context */ -char *buf, /* buffer, holds the data to write */ -int addr, /* start writing at the VPD address */ -int len) /* number of bytes to write */ -{ - return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_WRITE)); -} -#endif /* SKDIAG */ - -/* - * (re)initialize the VPD buffer - * - * Reads the VPD data from the EEPROM into the VPD buffer. - * Get the remaining read only and read / write space. - * - * return 0: success - * 1: fatal VPD error - */ -static int VpdInit( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC) /* IO Context */ -{ - SK_VPD_PARA *r, rp; /* RW or RV */ - int i; - unsigned char x; - int vpd_size; - SK_U16 dev_id; - SK_U32 our_reg2; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("VpdInit .. ")); - - VPD_IN16(pAC, IoC, PCI_DEVICE_ID, &dev_id); - - VPD_IN32(pAC, IoC, PCI_OUR_REG_2, &our_reg2); - - pAC->vpd.rom_size = 256 << ((our_reg2 & PCI_VPD_ROM_SZ) >> 14); - - /* - * this function might get used before the hardware is initialized - * therefore we cannot always trust in GIChipId - */ - if (((pAC->vpd.v.vpd_status & VPD_VALID) == 0 && - dev_id != VPD_DEV_ID_GENESIS) || - ((pAC->vpd.v.vpd_status & VPD_VALID) != 0 && - !pAC->GIni.GIGenesis)) { - - /* for Yukon the VPD size is always 256 */ - vpd_size = VPD_SIZE_YUKON; - } - else { - /* Genesis uses the maximum ROM size up to 512 for VPD */ - if (pAC->vpd.rom_size > VPD_SIZE_GENESIS) { - vpd_size = VPD_SIZE_GENESIS; - } - else { - vpd_size = pAC->vpd.rom_size; - } - } - - /* read the VPD data into the VPD buffer */ - if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf, 0, vpd_size, VPD_READ) - != vpd_size) { - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("Block Read Error\n")); - return(1); - } - - pAC->vpd.vpd_size = vpd_size; - - /* Asus K8V Se Deluxe bugfix. Correct VPD content */ - /* MBo April 2004 */ - if (((unsigned char)pAC->vpd.vpd_buf[0x3f] == 0x38) && - ((unsigned char)pAC->vpd.vpd_buf[0x40] == 0x3c) && - ((unsigned char)pAC->vpd.vpd_buf[0x41] == 0x45)) { - printk("sk98lin: Asus mainboard with buggy VPD? " - "Correcting data.\n"); - pAC->vpd.vpd_buf[0x40] = 0x38; - } - - - /* find the end tag of the RO area */ - if (!(r = vpd_find_para(pAC, VPD_RV, &rp))) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Encoding Error: RV Tag not found\n")); - return(1); - } - - if (r->p_val + r->p_len > pAC->vpd.vpd_buf + vpd_size/2) { - SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Encoding Error: Invalid VPD struct size\n")); - return(1); - } - pAC->vpd.v.vpd_free_ro = r->p_len - 1; - - /* test the checksum */ - for (i = 0, x = 0; (unsigned)i <= (unsigned)vpd_size/2 - r->p_len; i++) { - x += pAC->vpd.vpd_buf[i]; - } - - if (x != 0) { - /* checksum error */ - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("VPD Checksum Error\n")); - return(1); - } - - /* find and check the end tag of the RW area */ - if (!(r = vpd_find_para(pAC, VPD_RW, &rp))) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Encoding Error: RV Tag not found\n")); - return(1); - } - - if (r->p_val < pAC->vpd.vpd_buf + vpd_size/2) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Encoding Error: Invalid VPD struct size\n")); - return(1); - } - pAC->vpd.v.vpd_free_rw = r->p_len; - - /* everything seems to be ok */ - if (pAC->GIni.GIChipId != 0) { - pAC->vpd.v.vpd_status |= VPD_VALID; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, - ("done. Free RO = %d, Free RW = %d\n", - pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw)); - - return(0); -} - -/* - * find the Keyword 'key' in the VPD buffer and fills the - * parameter struct 'p' with it's values - * - * returns *p success - * 0: parameter was not found or VPD encoding error - */ -static SK_VPD_PARA *vpd_find_para( -SK_AC *pAC, /* common data base */ -const char *key, /* keyword to find (e.g. "MN") */ -SK_VPD_PARA *p) /* parameter description struct */ -{ - char *v ; /* points to VPD buffer */ - int max; /* Maximum Number of Iterations */ - - v = pAC->vpd.vpd_buf; - max = 128; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("VPD find para %s .. ",key)); - - /* check mandatory resource type ID string (Product Name) */ - if (*v != (char)RES_ID) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Error: 0x%x missing\n", RES_ID)); - return NULL; - } - - if (strcmp(key, VPD_NAME) == 0) { - p->p_len = VPD_GET_RES_LEN(v); - p->p_val = VPD_GET_VAL(v); - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("found, len = %d\n", p->p_len)); - return(p); - } - - v += 3 + VPD_GET_RES_LEN(v) + 3; - for (;; ) { - if (SK_MEMCMP(key,v,2) == 0) { - p->p_len = VPD_GET_VPD_LEN(v); - p->p_val = VPD_GET_VAL(v); - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("found, len = %d\n",p->p_len)); - return(p); - } - - /* exit when reaching the "RW" Tag or the maximum of itera. */ - max--; - if (SK_MEMCMP(VPD_RW,v,2) == 0 || max == 0) { - break; - } - - if (SK_MEMCMP(VPD_RV,v,2) == 0) { - v += 3 + VPD_GET_VPD_LEN(v) + 3; /* skip VPD-W */ - } - else { - v += 3 + VPD_GET_VPD_LEN(v); - } - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("scanning '%c%c' len = %d\n",v[0],v[1],v[2])); - } - -#ifdef DEBUG - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("not found\n")); - if (max == 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Key/Len Encoding error\n")); - } -#endif /* DEBUG */ - return NULL; -} - -/* - * Move 'n' bytes. Begin with the last byte if 'n' is > 0, - * Start with the last byte if n is < 0. - * - * returns nothing - */ -static void vpd_move_para( -char *start, /* start of memory block */ -char *end, /* end of memory block to move */ -int n) /* number of bytes the memory block has to be moved */ -{ - char *p; - int i; /* number of byte copied */ - - if (n == 0) - return; - - i = (int) (end - start + 1); - if (n < 0) { - p = start + n; - while (i != 0) { - *p++ = *start++; - i--; - } - } - else { - p = end + n; - while (i != 0) { - *p-- = *end--; - i--; - } - } -} - -/* - * setup the VPD keyword 'key' at 'ip'. - * - * returns nothing - */ -static void vpd_insert_key( -const char *key, /* keyword to insert */ -const char *buf, /* buffer with the keyword value */ -int len, /* length of the value string */ -char *ip) /* inseration point */ -{ - SK_VPD_KEY *p; - - p = (SK_VPD_KEY *) ip; - p->p_key[0] = key[0]; - p->p_key[1] = key[1]; - p->p_len = (unsigned char) len; - SK_MEMCPY(&p->p_val,buf,len); -} - -/* - * Setup the VPD end tag "RV" / "RW". - * Also correct the remaining space variables vpd_free_ro / vpd_free_rw. - * - * returns 0: success - * 1: encoding error - */ -static int vpd_mod_endtag( -SK_AC *pAC, /* common data base */ -char *etp) /* end pointer input position */ -{ - SK_VPD_KEY *p; - unsigned char x; - int i; - int vpd_size; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("VPD modify endtag at 0x%x = '%c%c'\n",etp,etp[0],etp[1])); - - vpd_size = pAC->vpd.vpd_size; - - p = (SK_VPD_KEY *) etp; - - if (p->p_key[0] != 'R' || (p->p_key[1] != 'V' && p->p_key[1] != 'W')) { - /* something wrong here, encoding error */ - SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Encoding Error: invalid end tag\n")); - return(1); - } - if (etp > pAC->vpd.vpd_buf + vpd_size/2) { - /* create "RW" tag */ - p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size-etp-3-1); - pAC->vpd.v.vpd_free_rw = (int) p->p_len; - i = pAC->vpd.v.vpd_free_rw; - etp += 3; - } - else { - /* create "RV" tag */ - p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size/2-etp-3); - pAC->vpd.v.vpd_free_ro = (int) p->p_len - 1; - - /* setup checksum */ - for (i = 0, x = 0; i < vpd_size/2 - p->p_len; i++) { - x += pAC->vpd.vpd_buf[i]; - } - p->p_val = (char) 0 - x; - i = pAC->vpd.v.vpd_free_ro; - etp += 4; - } - while (i) { - *etp++ = 0x00; - i--; - } - - return(0); -} - -/* - * Insert a VPD keyword into the VPD buffer. - * - * The keyword 'key' is inserted at the position 'ip' in the - * VPD buffer. - * The keywords behind the input position will - * be moved. The VPD end tag "RV" or "RW" is generated again. - * - * returns 0: success - * 2: value string was cut - * 4: VPD full, keyword was not written - * 6: fatal VPD error - * - */ -static int VpdSetupPara( -SK_AC *pAC, /* common data base */ -const char *key, /* keyword to insert */ -const char *buf, /* buffer with the keyword value */ -int len, /* length of the keyword value */ -int type, /* VPD_RO_KEY or VPD_RW_KEY */ -int op) /* operation to do: ADD_KEY or OWR_KEY */ -{ - SK_VPD_PARA vp; - char *etp; /* end tag position */ - int free; /* remaining space in selected area */ - char *ip; /* input position inside the VPD buffer */ - int rtv; /* return code */ - int head; /* additional haeder bytes to move */ - int found; /* additinoal bytes if the keyword was found */ - int vpd_size; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("VPD setup para key = %s, val = %s\n",key,buf)); - - vpd_size = pAC->vpd.vpd_size; - - rtv = 0; - ip = NULL; - if (type == VPD_RW_KEY) { - /* end tag is "RW" */ - free = pAC->vpd.v.vpd_free_rw; - etp = pAC->vpd.vpd_buf + (vpd_size - free - 1 - 3); - } - else { - /* end tag is "RV" */ - free = pAC->vpd.v.vpd_free_ro; - etp = pAC->vpd.vpd_buf + (vpd_size/2 - free - 4); - } - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("Free RO = %d, Free RW = %d\n", - pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw)); - - head = 0; - found = 0; - if (op == OWR_KEY) { - if (vpd_find_para(pAC, key, &vp)) { - found = 3; - ip = vp.p_val - 3; - free += vp.p_len + 3; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("Overwrite Key\n")); - } - else { - op = ADD_KEY; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("Add Key\n")); - } - } - if (op == ADD_KEY) { - ip = etp; - vp.p_len = 0; - head = 3; - } - - if (len + 3 > free) { - if (free < 7) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD Buffer Overflow, keyword not written\n")); - return(4); - } - /* cut it again */ - len = free - 3; - rtv = 2; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD Buffer Full, Keyword was cut\n")); - } - - vpd_move_para(ip + vp.p_len + found, etp+2, len-vp.p_len+head); - vpd_insert_key(key, buf, len, ip); - if (vpd_mod_endtag(pAC, etp + len - vp.p_len + head)) { - pAC->vpd.v.vpd_status &= ~VPD_VALID; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD Encoding Error\n")); - return(6); - } - - return(rtv); -} - - -/* - * Read the contents of the VPD EEPROM and copy it to the - * VPD buffer if not already done. - * - * return: A pointer to the vpd_status structure. The structure contains - * this fields. - */ -SK_VPD_STATUS *VpdStat( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC) /* IO Context */ -{ - if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { - (void)VpdInit(pAC, IoC); - } - return(&pAC->vpd.v); -} - - -/* - * Read the contents of the VPD EEPROM and copy it to the VPD - * buffer if not already done. - * Scan the VPD buffer for VPD keywords and create the VPD - * keyword list by copying the keywords to 'buf', all after - * each other and terminated with a '\0'. - * - * Exceptions: o The Resource Type ID String (product name) is called "Name" - * o The VPD end tags 'RV' and 'RW' are not listed - * - * The number of copied keywords is counted in 'elements'. - * - * returns 0: success - * 2: buffer overfull, one or more keywords are missing - * 6: fatal VPD error - * - * example values after returning: - * - * buf = "Name\0PN\0EC\0MN\0SN\0CP\0VF\0VL\0YA\0" - * *len = 30 - * *elements = 9 - */ -int VpdKeys( -SK_AC *pAC, /* common data base */ -SK_IOC IoC, /* IO Context */ -char *buf, /* buffer where to copy the keywords */ -int *len, /* buffer length */ -int *elements) /* number of keywords returned */ -{ - char *v; - int n; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("list VPD keys .. ")); - *elements = 0; - if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { - if (VpdInit(pAC, IoC) != 0) { - *len = 0; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD Init Error, terminated\n")); - return(6); - } - } - - if ((signed)strlen(VPD_NAME) + 1 <= *len) { - v = pAC->vpd.vpd_buf; - strcpy(buf,VPD_NAME); - n = strlen(VPD_NAME) + 1; - buf += n; - *elements = 1; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, - ("'%c%c' ",v[0],v[1])); - } - else { - *len = 0; - SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR, - ("buffer overflow\n")); - return(2); - } - - v += 3 + VPD_GET_RES_LEN(v) + 3; - for (;; ) { - /* exit when reaching the "RW" Tag */ - if (SK_MEMCMP(VPD_RW,v,2) == 0) { - break; - } - - if (SK_MEMCMP(VPD_RV,v,2) == 0) { - v += 3 + VPD_GET_VPD_LEN(v) + 3; /* skip VPD-W */ - continue; - } - - if (n+3 <= *len) { - SK_MEMCPY(buf,v,2); - buf += 2; - *buf++ = '\0'; - n += 3; - v += 3 + VPD_GET_VPD_LEN(v); - *elements += 1; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, - ("'%c%c' ",v[0],v[1])); - } - else { - *len = n; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("buffer overflow\n")); - return(2); - } - } - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("\n")); - *len = n; - return(0); -} - - -/* - * Read the contents of the VPD EEPROM and copy it to the - * VPD buffer if not already done. Search for the VPD keyword - * 'key' and copy its value to 'buf'. Add a terminating '\0'. - * If the value does not fit into the buffer cut it after - * 'len' - 1 bytes. - * - * returns 0: success - * 1: keyword not found - * 2: value string was cut - * 3: VPD transfer timeout - * 6: fatal VPD error - */ -int VpdRead( -SK_AC *pAC, /* common data base */ -SK_IOC IoC, /* IO Context */ -const char *key, /* keyword to read (e.g. "MN") */ -char *buf, /* buffer where to copy the keyword value */ -int *len) /* buffer length */ -{ - SK_VPD_PARA *p, vp; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("VPD read %s .. ", key)); - if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { - if (VpdInit(pAC, IoC) != 0) { - *len = 0; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD init error\n")); - return(6); - } - } - - if ((p = vpd_find_para(pAC, key, &vp)) != NULL) { - if (p->p_len > (*(unsigned *)len)-1) { - p->p_len = *len - 1; - } - SK_MEMCPY(buf, p->p_val, p->p_len); - buf[p->p_len] = '\0'; - *len = p->p_len; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, - ("%c%c%c%c.., len = %d\n", - buf[0],buf[1],buf[2],buf[3],*len)); - } - else { - *len = 0; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("not found\n")); - return(1); - } - return(0); -} - - -/* - * Check whether a given key may be written - * - * returns - * SK_TRUE Yes it may be written - * SK_FALSE No it may be written - */ -SK_BOOL VpdMayWrite( -char *key) /* keyword to write (allowed values "Yx", "Vx") */ -{ - if ((*key != 'Y' && *key != 'V') || - key[1] < '0' || key[1] > 'Z' || - (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) { - - return(SK_FALSE); - } - return(SK_TRUE); -} - -/* - * Read the contents of the VPD EEPROM and copy it to the VPD - * buffer if not already done. Insert/overwrite the keyword 'key' - * in the VPD buffer. Cut the keyword value if it does not fit - * into the VPD read / write area. - * - * returns 0: success - * 2: value string was cut - * 3: VPD transfer timeout - * 4: VPD full, keyword was not written - * 5: keyword cannot be written - * 6: fatal VPD error - */ -int VpdWrite( -SK_AC *pAC, /* common data base */ -SK_IOC IoC, /* IO Context */ -const char *key, /* keyword to write (allowed values "Yx", "Vx") */ -const char *buf) /* buffer where the keyword value can be read from */ -{ - int len; /* length of the keyword to write */ - int rtv; /* return code */ - int rtv2; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, - ("VPD write %s = %s\n",key,buf)); - - if ((*key != 'Y' && *key != 'V') || - key[1] < '0' || key[1] > 'Z' || - (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) { - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("illegal key tag, keyword not written\n")); - return(5); - } - - if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { - if (VpdInit(pAC, IoC) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD init error\n")); - return(6); - } - } - - rtv = 0; - len = strlen(buf); - if (len > VPD_MAX_LEN) { - /* cut it */ - len = VPD_MAX_LEN; - rtv = 2; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("keyword too long, cut after %d bytes\n",VPD_MAX_LEN)); - } - if ((rtv2 = VpdSetupPara(pAC, key, buf, len, VPD_RW_KEY, OWR_KEY)) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD write error\n")); - return(rtv2); - } - - return(rtv); -} - -/* - * Read the contents of the VPD EEPROM and copy it to the - * VPD buffer if not already done. Remove the VPD keyword - * 'key' from the VPD buffer. - * Only the keywords in the read/write area can be deleted. - * Keywords in the read only area cannot be deleted. - * - * returns 0: success, keyword was removed - * 1: keyword not found - * 5: keyword cannot be deleted - * 6: fatal VPD error - */ -int VpdDelete( -SK_AC *pAC, /* common data base */ -SK_IOC IoC, /* IO Context */ -char *key) /* keyword to read (e.g. "MN") */ -{ - SK_VPD_PARA *p, vp; - char *etp; - int vpd_size; - - vpd_size = pAC->vpd.vpd_size; - - SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("VPD delete key %s\n",key)); - if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { - if (VpdInit(pAC, IoC) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD init error\n")); - return(6); - } - } - - if ((p = vpd_find_para(pAC, key, &vp)) != NULL) { - if (p->p_val < pAC->vpd.vpd_buf + vpd_size/2) { - /* try to delete read only keyword */ - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("cannot delete RO keyword\n")); - return(5); - } - - etp = pAC->vpd.vpd_buf + (vpd_size-pAC->vpd.v.vpd_free_rw-1-3); - - vpd_move_para(vp.p_val+vp.p_len, etp+2, - - ((int)(vp.p_len + 3))); - if (vpd_mod_endtag(pAC, etp - vp.p_len - 3)) { - pAC->vpd.v.vpd_status &= ~VPD_VALID; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD encoding error\n")); - return(6); - } - } - else { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("keyword not found\n")); - return(1); - } - - return(0); -} - -/* - * If the VPD buffer contains valid data write the VPD - * read/write area back to the VPD EEPROM. - * - * returns 0: success - * 3: VPD transfer timeout - */ -int VpdUpdate( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC) /* IO Context */ -{ - int vpd_size; - - vpd_size = pAC->vpd.vpd_size; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("VPD update .. ")); - if ((pAC->vpd.v.vpd_status & VPD_VALID) != 0) { - if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf + vpd_size/2, - vpd_size/2, vpd_size/2, VPD_WRITE) != vpd_size/2) { - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("transfer timed out\n")); - return(3); - } - } - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("done\n")); - return(0); -} - diff --git a/drivers/net/sk98lin/skxmac2.c b/drivers/net/sk98lin/skxmac2.c deleted file mode 100644 index b4e75022a65..00000000000 --- a/drivers/net/sk98lin/skxmac2.c +++ /dev/null @@ -1,4160 +0,0 @@ -/****************************************************************************** - * - * Name: skxmac2.c - * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.102 $ - * Date: $Date: 2003/10/02 16:53:58 $ - * Purpose: Contains functions to initialize the MACs and PHYs - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#include "h/skdrv1st.h" -#include "h/skdrv2nd.h" - -/* typedefs *******************************************************************/ - -/* BCOM PHY magic pattern list */ -typedef struct s_PhyHack { - int PhyReg; /* Phy register */ - SK_U16 PhyVal; /* Value to write */ -} BCOM_HACK; - -/* local variables ************************************************************/ - -#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) -static const char SysKonnectFileId[] = - "@(#) $Id: skxmac2.c,v 1.102 2003/10/02 16:53:58 rschmidt Exp $ (C) Marvell."; -#endif - -#ifdef GENESIS -static BCOM_HACK BcomRegA1Hack[] = { - { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 }, - { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 }, - { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 }, - { 0, 0 } -}; -static BCOM_HACK BcomRegC0Hack[] = { - { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 }, - { 0x15, 0x0A04 }, { 0x18, 0x0420 }, - { 0, 0 } -}; -#endif - -/* function prototypes ********************************************************/ -#ifdef GENESIS -static void SkXmInitPhyXmac(SK_AC*, SK_IOC, int, SK_BOOL); -static void SkXmInitPhyBcom(SK_AC*, SK_IOC, int, SK_BOOL); -static int SkXmAutoNegDoneXmac(SK_AC*, SK_IOC, int); -static int SkXmAutoNegDoneBcom(SK_AC*, SK_IOC, int); -#endif /* GENESIS */ -#ifdef YUKON -static void SkGmInitPhyMarv(SK_AC*, SK_IOC, int, SK_BOOL); -static int SkGmAutoNegDoneMarv(SK_AC*, SK_IOC, int); -#endif /* YUKON */ -#ifdef OTHER_PHY -static void SkXmInitPhyLone(SK_AC*, SK_IOC, int, SK_BOOL); -static void SkXmInitPhyNat (SK_AC*, SK_IOC, int, SK_BOOL); -static int SkXmAutoNegDoneLone(SK_AC*, SK_IOC, int); -static int SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int); -#endif /* OTHER_PHY */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkXmPhyRead() - Read from XMAC PHY register - * - * Description: reads a 16-bit word from XMAC PHY or ext. PHY - * - * Returns: - * nothing - */ -void SkXmPhyRead( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Port, /* Port Index (MAC_1 + n) */ -int PhyReg, /* Register Address (Offset) */ -SK_U16 SK_FAR *pVal) /* Pointer to Value */ -{ - SK_U16 Mmu; - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - /* write the PHY register's address */ - XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr); - - /* get the PHY register's value */ - XM_IN16(IoC, Port, XM_PHY_DATA, pVal); - - if (pPrt->PhyType != SK_PHY_XMAC) { - do { - XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu); - /* wait until 'Ready' is set */ - } while ((Mmu & XM_MMU_PHY_RDY) == 0); - - /* get the PHY register's value */ - XM_IN16(IoC, Port, XM_PHY_DATA, pVal); - } -} /* SkXmPhyRead */ - - -/****************************************************************************** - * - * SkXmPhyWrite() - Write to XMAC PHY register - * - * Description: writes a 16-bit word to XMAC PHY or ext. PHY - * - * Returns: - * nothing - */ -void SkXmPhyWrite( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Port, /* Port Index (MAC_1 + n) */ -int PhyReg, /* Register Address (Offset) */ -SK_U16 Val) /* Value */ -{ - SK_U16 Mmu; - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PhyType != SK_PHY_XMAC) { - do { - XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu); - /* wait until 'Busy' is cleared */ - } while ((Mmu & XM_MMU_PHY_BUSY) != 0); - } - - /* write the PHY register's address */ - XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr); - - /* write the PHY register's value */ - XM_OUT16(IoC, Port, XM_PHY_DATA, Val); - - if (pPrt->PhyType != SK_PHY_XMAC) { - do { - XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu); - /* wait until 'Busy' is cleared */ - } while ((Mmu & XM_MMU_PHY_BUSY) != 0); - } -} /* SkXmPhyWrite */ -#endif /* GENESIS */ - - -#ifdef YUKON -/****************************************************************************** - * - * SkGmPhyRead() - Read from GPHY register - * - * Description: reads a 16-bit word from GPHY through MDIO - * - * Returns: - * nothing - */ -void SkGmPhyRead( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Port, /* Port Index (MAC_1 + n) */ -int PhyReg, /* Register Address (Offset) */ -SK_U16 SK_FAR *pVal) /* Pointer to Value */ -{ - SK_U16 Ctrl; - SK_GEPORT *pPrt; -#ifdef VCPU - u_long SimCyle; - u_long SimLowTime; - - VCPUgetTime(&SimCyle, &SimLowTime); - VCPUprintf(0, "SkGmPhyRead(%u), SimCyle=%u, SimLowTime=%u\n", - PhyReg, SimCyle, SimLowTime); -#endif /* VCPU */ - - pPrt = &pAC->GIni.GP[Port]; - - /* set PHY-Register offset and 'Read' OpCode (= 1) */ - *pVal = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | - GM_SMI_CT_REG_AD(PhyReg) | GM_SMI_CT_OP_RD); - - GM_OUT16(IoC, Port, GM_SMI_CTRL, *pVal); - - GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); - - /* additional check for MDC/MDIO activity */ - if ((Ctrl & GM_SMI_CT_BUSY) == 0) { - *pVal = 0; - return; - } - - *pVal |= GM_SMI_CT_BUSY; - - do { -#ifdef VCPU - VCPUwaitTime(1000); -#endif /* VCPU */ - - GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); - - /* wait until 'ReadValid' is set */ - } while (Ctrl == *pVal); - - /* get the PHY register's value */ - GM_IN16(IoC, Port, GM_SMI_DATA, pVal); - -#ifdef VCPU - VCPUgetTime(&SimCyle, &SimLowTime); - VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n", - SimCyle, SimLowTime); -#endif /* VCPU */ - -} /* SkGmPhyRead */ - - -/****************************************************************************** - * - * SkGmPhyWrite() - Write to GPHY register - * - * Description: writes a 16-bit word to GPHY through MDIO - * - * Returns: - * nothing - */ -void SkGmPhyWrite( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Port, /* Port Index (MAC_1 + n) */ -int PhyReg, /* Register Address (Offset) */ -SK_U16 Val) /* Value */ -{ - SK_U16 Ctrl; - SK_GEPORT *pPrt; -#ifdef VCPU - SK_U32 DWord; - u_long SimCyle; - u_long SimLowTime; - - VCPUgetTime(&SimCyle, &SimLowTime); - VCPUprintf(0, "SkGmPhyWrite(Reg=%u, Val=0x%04x), SimCyle=%u, SimLowTime=%u\n", - PhyReg, Val, SimCyle, SimLowTime); -#endif /* VCPU */ - - pPrt = &pAC->GIni.GP[Port]; - - /* write the PHY register's value */ - GM_OUT16(IoC, Port, GM_SMI_DATA, Val); - - /* set PHY-Register offset and 'Write' OpCode (= 0) */ - Val = GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | GM_SMI_CT_REG_AD(PhyReg); - - GM_OUT16(IoC, Port, GM_SMI_CTRL, Val); - - GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); - - /* additional check for MDC/MDIO activity */ - if ((Ctrl & GM_SMI_CT_BUSY) == 0) { - return; - } - - Val |= GM_SMI_CT_BUSY; - - do { -#ifdef VCPU - /* read Timer value */ - SK_IN32(IoC, B2_TI_VAL, &DWord); - - VCPUwaitTime(1000); -#endif /* VCPU */ - - GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); - - /* wait until 'Busy' is cleared */ - } while (Ctrl == Val); - -#ifdef VCPU - VCPUgetTime(&SimCyle, &SimLowTime); - VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n", - SimCyle, SimLowTime); -#endif /* VCPU */ - -} /* SkGmPhyWrite */ -#endif /* YUKON */ - - -#ifdef SK_DIAG -/****************************************************************************** - * - * SkGePhyRead() - Read from PHY register - * - * Description: calls a read PHY routine dep. on board type - * - * Returns: - * nothing - */ -void SkGePhyRead( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Port, /* Port Index (MAC_1 + n) */ -int PhyReg, /* Register Address (Offset) */ -SK_U16 *pVal) /* Pointer to Value */ -{ - void (*r_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 *pVal); - - if (pAC->GIni.GIGenesis) { - r_func = SkXmPhyRead; - } - else { - r_func = SkGmPhyRead; - } - - r_func(pAC, IoC, Port, PhyReg, pVal); -} /* SkGePhyRead */ - - -/****************************************************************************** - * - * SkGePhyWrite() - Write to PHY register - * - * Description: calls a write PHY routine dep. on board type - * - * Returns: - * nothing - */ -void SkGePhyWrite( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Port, /* Port Index (MAC_1 + n) */ -int PhyReg, /* Register Address (Offset) */ -SK_U16 Val) /* Value */ -{ - void (*w_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 Val); - - if (pAC->GIni.GIGenesis) { - w_func = SkXmPhyWrite; - } - else { - w_func = SkGmPhyWrite; - } - - w_func(pAC, IoC, Port, PhyReg, Val); -} /* SkGePhyWrite */ -#endif /* SK_DIAG */ - - -/****************************************************************************** - * - * SkMacPromiscMode() - Enable / Disable Promiscuous Mode - * - * Description: - * enables / disables promiscuous mode by setting Mode Register (XMAC) or - * Receive Control Register (GMAC) dep. on board type - * - * Returns: - * nothing - */ -void SkMacPromiscMode( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL Enable) /* Enable / Disable */ -{ -#ifdef YUKON - SK_U16 RcReg; -#endif -#ifdef GENESIS - SK_U32 MdReg; -#endif - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - XM_IN32(IoC, Port, XM_MODE, &MdReg); - /* enable or disable promiscuous mode */ - if (Enable) { - MdReg |= XM_MD_ENA_PROM; - } - else { - MdReg &= ~XM_MD_ENA_PROM; - } - /* setup Mode Register */ - XM_OUT32(IoC, Port, XM_MODE, MdReg); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg); - - /* enable or disable unicast and multicast filtering */ - if (Enable) { - RcReg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); - } - else { - RcReg |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); - } - /* setup Receive Control Register */ - GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg); - } -#endif /* YUKON */ - -} /* SkMacPromiscMode*/ - - -/****************************************************************************** - * - * SkMacHashing() - Enable / Disable Hashing - * - * Description: - * enables / disables hashing by setting Mode Register (XMAC) or - * Receive Control Register (GMAC) dep. on board type - * - * Returns: - * nothing - */ -void SkMacHashing( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL Enable) /* Enable / Disable */ -{ -#ifdef YUKON - SK_U16 RcReg; -#endif -#ifdef GENESIS - SK_U32 MdReg; -#endif - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - XM_IN32(IoC, Port, XM_MODE, &MdReg); - /* enable or disable hashing */ - if (Enable) { - MdReg |= XM_MD_ENA_HASH; - } - else { - MdReg &= ~XM_MD_ENA_HASH; - } - /* setup Mode Register */ - XM_OUT32(IoC, Port, XM_MODE, MdReg); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg); - - /* enable or disable multicast filtering */ - if (Enable) { - RcReg |= GM_RXCR_MCF_ENA; - } - else { - RcReg &= ~GM_RXCR_MCF_ENA; - } - /* setup Receive Control Register */ - GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg); - } -#endif /* YUKON */ - -} /* SkMacHashing*/ - - -#ifdef SK_DIAG -/****************************************************************************** - * - * SkXmSetRxCmd() - Modify the value of the XMAC's Rx Command Register - * - * Description: - * The features - * - FCS stripping, SK_STRIP_FCS_ON/OFF - * - pad byte stripping, SK_STRIP_PAD_ON/OFF - * - don't set XMR_FS_ERR in status SK_LENERR_OK_ON/OFF - * for inrange length error frames - * - don't set XMR_FS_ERR in status SK_BIG_PK_OK_ON/OFF - * for frames > 1514 bytes - * - enable Rx of own packets SK_SELF_RX_ON/OFF - * - * for incoming packets may be enabled/disabled by this function. - * Additional modes may be added later. - * Multiple modes can be enabled/disabled at the same time. - * The new configuration is written to the Rx Command register immediately. - * - * Returns: - * nothing - */ -static void SkXmSetRxCmd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF, - SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */ -{ - SK_U16 OldRxCmd; - SK_U16 RxCmd; - - XM_IN16(IoC, Port, XM_RX_CMD, &OldRxCmd); - - RxCmd = OldRxCmd; - - switch (Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) { - case SK_STRIP_FCS_ON: - RxCmd |= XM_RX_STRIP_FCS; - break; - case SK_STRIP_FCS_OFF: - RxCmd &= ~XM_RX_STRIP_FCS; - break; - } - - switch (Mode & (SK_STRIP_PAD_ON | SK_STRIP_PAD_OFF)) { - case SK_STRIP_PAD_ON: - RxCmd |= XM_RX_STRIP_PAD; - break; - case SK_STRIP_PAD_OFF: - RxCmd &= ~XM_RX_STRIP_PAD; - break; - } - - switch (Mode & (SK_LENERR_OK_ON | SK_LENERR_OK_OFF)) { - case SK_LENERR_OK_ON: - RxCmd |= XM_RX_LENERR_OK; - break; - case SK_LENERR_OK_OFF: - RxCmd &= ~XM_RX_LENERR_OK; - break; - } - - switch (Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) { - case SK_BIG_PK_OK_ON: - RxCmd |= XM_RX_BIG_PK_OK; - break; - case SK_BIG_PK_OK_OFF: - RxCmd &= ~XM_RX_BIG_PK_OK; - break; - } - - switch (Mode & (SK_SELF_RX_ON | SK_SELF_RX_OFF)) { - case SK_SELF_RX_ON: - RxCmd |= XM_RX_SELF_RX; - break; - case SK_SELF_RX_OFF: - RxCmd &= ~XM_RX_SELF_RX; - break; - } - - /* Write the new mode to the Rx command register if required */ - if (OldRxCmd != RxCmd) { - XM_OUT16(IoC, Port, XM_RX_CMD, RxCmd); - } -} /* SkXmSetRxCmd */ - - -/****************************************************************************** - * - * SkGmSetRxCmd() - Modify the value of the GMAC's Rx Control Register - * - * Description: - * The features - * - FCS (CRC) stripping, SK_STRIP_FCS_ON/OFF - * - don't set GMR_FS_LONG_ERR SK_BIG_PK_OK_ON/OFF - * for frames > 1514 bytes - * - enable Rx of own packets SK_SELF_RX_ON/OFF - * - * for incoming packets may be enabled/disabled by this function. - * Additional modes may be added later. - * Multiple modes can be enabled/disabled at the same time. - * The new configuration is written to the Rx Command register immediately. - * - * Returns: - * nothing - */ -static void SkGmSetRxCmd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF, - SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */ -{ - SK_U16 OldRxCmd; - SK_U16 RxCmd; - - if ((Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) != 0) { - - GM_IN16(IoC, Port, GM_RX_CTRL, &OldRxCmd); - - RxCmd = OldRxCmd; - - if ((Mode & SK_STRIP_FCS_ON) != 0) { - RxCmd |= GM_RXCR_CRC_DIS; - } - else { - RxCmd &= ~GM_RXCR_CRC_DIS; - } - /* Write the new mode to the Rx control register if required */ - if (OldRxCmd != RxCmd) { - GM_OUT16(IoC, Port, GM_RX_CTRL, RxCmd); - } - } - - if ((Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) != 0) { - - GM_IN16(IoC, Port, GM_SERIAL_MODE, &OldRxCmd); - - RxCmd = OldRxCmd; - - if ((Mode & SK_BIG_PK_OK_ON) != 0) { - RxCmd |= GM_SMOD_JUMBO_ENA; - } - else { - RxCmd &= ~GM_SMOD_JUMBO_ENA; - } - /* Write the new mode to the Rx control register if required */ - if (OldRxCmd != RxCmd) { - GM_OUT16(IoC, Port, GM_SERIAL_MODE, RxCmd); - } - } -} /* SkGmSetRxCmd */ - - -/****************************************************************************** - * - * SkMacSetRxCmd() - Modify the value of the MAC's Rx Control Register - * - * Description: modifies the MAC's Rx Control reg. dep. on board type - * - * Returns: - * nothing - */ -void SkMacSetRxCmd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -int Mode) /* Rx Mode */ -{ - if (pAC->GIni.GIGenesis) { - - SkXmSetRxCmd(pAC, IoC, Port, Mode); - } - else { - - SkGmSetRxCmd(pAC, IoC, Port, Mode); - } - -} /* SkMacSetRxCmd */ - - -/****************************************************************************** - * - * SkMacCrcGener() - Enable / Disable CRC Generation - * - * Description: enables / disables CRC generation dep. on board type - * - * Returns: - * nothing - */ -void SkMacCrcGener( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL Enable) /* Enable / Disable */ -{ - SK_U16 Word; - - if (pAC->GIni.GIGenesis) { - - XM_IN16(IoC, Port, XM_TX_CMD, &Word); - - if (Enable) { - Word &= ~XM_TX_NO_CRC; - } - else { - Word |= XM_TX_NO_CRC; - } - /* setup Tx Command Register */ - XM_OUT16(IoC, Port, XM_TX_CMD, Word); - } - else { - - GM_IN16(IoC, Port, GM_TX_CTRL, &Word); - - if (Enable) { - Word &= ~GM_TXCR_CRC_DIS; - } - else { - Word |= GM_TXCR_CRC_DIS; - } - /* setup Tx Control Register */ - GM_OUT16(IoC, Port, GM_TX_CTRL, Word); - } - -} /* SkMacCrcGener*/ - -#endif /* SK_DIAG */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkXmClrExactAddr() - Clear Exact Match Address Registers - * - * Description: - * All Exact Match Address registers of the XMAC 'Port' will be - * cleared starting with 'StartNum' up to (and including) the - * Exact Match address number of 'StopNum'. - * - * Returns: - * nothing - */ -void SkXmClrExactAddr( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -int StartNum, /* Begin with this Address Register Index (0..15) */ -int StopNum) /* Stop after finished with this Register Idx (0..15) */ -{ - int i; - SK_U16 ZeroAddr[3] = {0x0000, 0x0000, 0x0000}; - - if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 || - StartNum > StopNum) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E001, SKERR_HWI_E001MSG); - return; - } - - for (i = StartNum; i <= StopNum; i++) { - XM_OUTADDR(IoC, Port, XM_EXM(i), &ZeroAddr[0]); - } -} /* SkXmClrExactAddr */ -#endif /* GENESIS */ - - -/****************************************************************************** - * - * SkMacFlushTxFifo() - Flush the MAC's transmit FIFO - * - * Description: - * Flush the transmit FIFO of the MAC specified by the index 'Port' - * - * Returns: - * nothing - */ -void SkMacFlushTxFifo( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ -#ifdef GENESIS - SK_U32 MdReg; - - if (pAC->GIni.GIGenesis) { - - XM_IN32(IoC, Port, XM_MODE, &MdReg); - - XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* no way to flush the FIFO we have to issue a reset */ - /* TBD */ - } -#endif /* YUKON */ - -} /* SkMacFlushTxFifo */ - - -/****************************************************************************** - * - * SkMacFlushRxFifo() - Flush the MAC's receive FIFO - * - * Description: - * Flush the receive FIFO of the MAC specified by the index 'Port' - * - * Returns: - * nothing - */ -static void SkMacFlushRxFifo( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ -#ifdef GENESIS - SK_U32 MdReg; - - if (pAC->GIni.GIGenesis) { - - XM_IN32(IoC, Port, XM_MODE, &MdReg); - - XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* no way to flush the FIFO we have to issue a reset */ - /* TBD */ - } -#endif /* YUKON */ - -} /* SkMacFlushRxFifo */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkXmSoftRst() - Do a XMAC software reset - * - * Description: - * The PHY registers should not be destroyed during this - * kind of software reset. Therefore the XMAC Software Reset - * (XM_GP_RES_MAC bit in XM_GP_PORT) must not be used! - * - * The software reset is done by - * - disabling the Rx and Tx state machine, - * - resetting the statistics module, - * - clear all other significant XMAC Mode, - * Command, and Control Registers - * - clearing the Hash Register and the - * Exact Match Address registers, and - * - flushing the XMAC's Rx and Tx FIFOs. - * - * Note: - * Another requirement when stopping the XMAC is to - * avoid sending corrupted frames on the network. - * Disabling the Tx state machine will NOT interrupt - * the currently transmitted frame. But we must take care - * that the Tx FIFO is cleared AFTER the current frame - * is complete sent to the network. - * - * It takes about 12ns to send a frame with 1538 bytes. - * One PCI clock goes at least 15ns (66MHz). Therefore - * after reading XM_GP_PORT back, we are sure that the - * transmitter is disabled AND idle. And this means - * we may flush the transmit FIFO now. - * - * Returns: - * nothing - */ -static void SkXmSoftRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U16 ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000}; - - /* reset the statistics module */ - XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT); - - /* disable all XMAC IRQs */ - XM_OUT16(IoC, Port, XM_IMSK, 0xffff); - - XM_OUT32(IoC, Port, XM_MODE, 0); /* clear Mode Reg */ - - XM_OUT16(IoC, Port, XM_TX_CMD, 0); /* reset TX CMD Reg */ - XM_OUT16(IoC, Port, XM_RX_CMD, 0); /* reset RX CMD Reg */ - - /* disable all PHY IRQs */ - switch (pAC->GIni.GP[Port].PhyType) { - case SK_PHY_BCOM: - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff); - break; -#ifdef OTHER_PHY - case SK_PHY_LONE: - SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0); - break; - case SK_PHY_NAT: - /* todo: National - SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */ - break; -#endif /* OTHER_PHY */ - } - - /* clear the Hash Register */ - XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr); - - /* clear the Exact Match Address registers */ - SkXmClrExactAddr(pAC, IoC, Port, 0, 15); - - /* clear the Source Check Address registers */ - XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr); - -} /* SkXmSoftRst */ - - -/****************************************************************************** - * - * SkXmHardRst() - Do a XMAC hardware reset - * - * Description: - * The XMAC of the specified 'Port' and all connected devices - * (PHY and SERDES) will receive a reset signal on its *Reset pins. - * External PHYs must be reset by clearing a bit in the GPIO register - * (Timing requirements: Broadcom: 400ns, Level One: none, National: 80ns). - * - * ATTENTION: - * It is absolutely necessary to reset the SW_RST Bit first - * before calling this function. - * - * Returns: - * nothing - */ -static void SkXmHardRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U32 Reg; - int i; - int TOut; - SK_U16 Word; - - for (i = 0; i < 4; i++) { - /* TX_MFF_CTRL1 has 32 bits, but only the lowest 16 bits are used */ - SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); - - TOut = 0; - do { - if (TOut++ > 10000) { - /* - * Adapter seems to be in RESET state. - * Registers cannot be written. - */ - return; - } - - SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_SET_MAC_RST); - - SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &Word); - - } while ((Word & MFF_SET_MAC_RST) == 0); - } - - /* For external PHYs there must be special handling */ - if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) { - - SK_IN32(IoC, B2_GP_IO, &Reg); - - if (Port == 0) { - Reg |= GP_DIR_0; /* set to output */ - Reg &= ~GP_IO_0; /* set PHY reset (active low) */ - } - else { - Reg |= GP_DIR_2; /* set to output */ - Reg &= ~GP_IO_2; /* set PHY reset (active low) */ - } - /* reset external PHY */ - SK_OUT32(IoC, B2_GP_IO, Reg); - - /* short delay */ - SK_IN32(IoC, B2_GP_IO, &Reg); - } -} /* SkXmHardRst */ - - -/****************************************************************************** - * - * SkXmClearRst() - Release the PHY & XMAC reset - * - * Description: - * - * Returns: - * nothing - */ -static void SkXmClearRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U32 DWord; - - /* clear HW reset */ - SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); - - if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) { - - SK_IN32(IoC, B2_GP_IO, &DWord); - - if (Port == 0) { - DWord |= (GP_DIR_0 | GP_IO_0); /* set to output */ - } - else { - DWord |= (GP_DIR_2 | GP_IO_2); /* set to output */ - } - /* Clear PHY reset */ - SK_OUT32(IoC, B2_GP_IO, DWord); - - /* Enable GMII interface */ - XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD); - } -} /* SkXmClearRst */ -#endif /* GENESIS */ - - -#ifdef YUKON -/****************************************************************************** - * - * SkGmSoftRst() - Do a GMAC software reset - * - * Description: - * The GPHY registers should not be destroyed during this - * kind of software reset. - * - * Returns: - * nothing - */ -static void SkGmSoftRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U16 EmptyHash[4] = {0x0000, 0x0000, 0x0000, 0x0000}; - SK_U16 RxCtrl; - - /* reset the statistics module */ - - /* disable all GMAC IRQs */ - SK_OUT8(IoC, GMAC_IRQ_MSK, 0); - - /* disable all PHY IRQs */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0); - - /* clear the Hash Register */ - GM_OUTHASH(IoC, Port, GM_MC_ADDR_H1, EmptyHash); - - /* Enable Unicast and Multicast filtering */ - GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl); - - GM_OUT16(IoC, Port, GM_RX_CTRL, - (SK_U16)(RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA)); - -} /* SkGmSoftRst */ - - -/****************************************************************************** - * - * SkGmHardRst() - Do a GMAC hardware reset - * - * Description: - * - * Returns: - * nothing - */ -static void SkGmHardRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U32 DWord; - - /* WA code for COMA mode */ - if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { - - SK_IN32(IoC, B2_GP_IO, &DWord); - - DWord |= (GP_DIR_9 | GP_IO_9); - - /* set PHY reset */ - SK_OUT32(IoC, B2_GP_IO, DWord); - } - - /* set GPHY Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET); - - /* set GMAC Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET); - -} /* SkGmHardRst */ - - -/****************************************************************************** - * - * SkGmClearRst() - Release the GPHY & GMAC reset - * - * Description: - * - * Returns: - * nothing - */ -static void SkGmClearRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U32 DWord; - -#ifdef XXX - /* clear GMAC Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR); - - /* set GMAC Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET); -#endif /* XXX */ - - /* WA code for COMA mode */ - if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { - - SK_IN32(IoC, B2_GP_IO, &DWord); - - DWord |= GP_DIR_9; /* set to output */ - DWord &= ~GP_IO_9; /* clear PHY reset (active high) */ - - /* clear PHY reset */ - SK_OUT32(IoC, B2_GP_IO, DWord); - } - - /* set HWCFG_MODE */ - DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP | - GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE | - (pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP : - GPC_HWCFG_GMII_FIB); - - /* set GPHY Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET); - - /* release GPHY Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR); - -#ifdef VCPU - VCpuWait(9000); -#endif /* VCPU */ - - /* clear GMAC Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR); - -#ifdef VCPU - VCpuWait(2000); - - SK_IN32(IoC, MR_ADDR(Port, GPHY_CTRL), &DWord); - - SK_IN32(IoC, B0_ISRC, &DWord); -#endif /* VCPU */ - -} /* SkGmClearRst */ -#endif /* YUKON */ - - -/****************************************************************************** - * - * SkMacSoftRst() - Do a MAC software reset - * - * Description: calls a MAC software reset routine dep. on board type - * - * Returns: - * nothing - */ -void SkMacSoftRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - /* disable receiver and transmitter */ - SkMacRxTxDisable(pAC, IoC, Port); - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - SkXmSoftRst(pAC, IoC, Port); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - SkGmSoftRst(pAC, IoC, Port); - } -#endif /* YUKON */ - - /* flush the MAC's Rx and Tx FIFOs */ - SkMacFlushTxFifo(pAC, IoC, Port); - - SkMacFlushRxFifo(pAC, IoC, Port); - - pPrt->PState = SK_PRT_STOP; - -} /* SkMacSoftRst */ - - -/****************************************************************************** - * - * SkMacHardRst() - Do a MAC hardware reset - * - * Description: calls a MAC hardware reset routine dep. on board type - * - * Returns: - * nothing - */ -void SkMacHardRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - SkXmHardRst(pAC, IoC, Port); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - SkGmHardRst(pAC, IoC, Port); - } -#endif /* YUKON */ - - pAC->GIni.GP[Port].PState = SK_PRT_RESET; - -} /* SkMacHardRst */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkXmInitMac() - Initialize the XMAC II - * - * Description: - * Initialize the XMAC of the specified port. - * The XMAC must be reset or stopped before calling this function. - * - * Note: - * The XMAC's Rx and Tx state machine is still disabled when returning. - * - * Returns: - * nothing - */ -void SkXmInitMac( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - int i; - SK_U16 SWord; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PState == SK_PRT_STOP) { - /* Port State: SK_PRT_STOP */ - /* Verify that the reset bit is cleared */ - SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord); - - if ((SWord & MFF_SET_MAC_RST) != 0) { - /* PState does not match HW state */ - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG); - /* Correct it */ - pPrt->PState = SK_PRT_RESET; - } - } - - if (pPrt->PState == SK_PRT_RESET) { - - SkXmClearRst(pAC, IoC, Port); - - if (pPrt->PhyType != SK_PHY_XMAC) { - /* read Id from external PHY (all have the same address) */ - SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1); - - /* - * Optimize MDIO transfer by suppressing preamble. - * Must be done AFTER first access to BCOM chip. - */ - XM_IN16(IoC, Port, XM_MMU_CMD, &SWord); - - XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE); - - if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) { - /* - * Workaround BCOM Errata for the C0 type. - * Write magic patterns to reserved registers. - */ - i = 0; - while (BcomRegC0Hack[i].PhyReg != 0) { - SkXmPhyWrite(pAC, IoC, Port, BcomRegC0Hack[i].PhyReg, - BcomRegC0Hack[i].PhyVal); - i++; - } - } - else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) { - /* - * Workaround BCOM Errata for the A1 type. - * Write magic patterns to reserved registers. - */ - i = 0; - while (BcomRegA1Hack[i].PhyReg != 0) { - SkXmPhyWrite(pAC, IoC, Port, BcomRegA1Hack[i].PhyReg, - BcomRegA1Hack[i].PhyVal); - i++; - } - } - - /* - * Workaround BCOM Errata (#10523) for all BCom PHYs. - * Disable Power Management after reset. - */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord); - - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, - (SK_U16)(SWord | PHY_B_AC_DIS_PM)); - - /* PHY LED initialization is done in SkGeXmitLED() */ - } - - /* Dummy read the Interrupt source register */ - XM_IN16(IoC, Port, XM_ISRC, &SWord); - - /* - * The auto-negotiation process starts immediately after - * clearing the reset. The auto-negotiation process should be - * started by the SIRQ, therefore stop it here immediately. - */ - SkMacInitPhy(pAC, IoC, Port, SK_FALSE); - -#ifdef TEST_ONLY - /* temp. code: enable signal detect */ - /* WARNING: do not override GMII setting above */ - XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_COM4SIG); -#endif - } - - /* - * configure the XMACs Station Address - * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A - * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B - */ - for (i = 0; i < 3; i++) { - /* - * The following 2 statements are together endianess - * independent. Remember this when changing. - */ - SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord); - - XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord); - } - - /* Tx Inter Packet Gap (XM_TX_IPG): use default */ - /* Tx High Water Mark (XM_TX_HI_WM): use default */ - /* Tx Low Water Mark (XM_TX_LO_WM): use default */ - /* Host Request Threshold (XM_HT_THR): use default */ - /* Rx Request Threshold (XM_RX_THR): use default */ - /* Rx Low Water Mark (XM_RX_LO_WM): use default */ - - /* configure Rx High Water Mark (XM_RX_HI_WM) */ - XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM); - - /* Configure Tx Request Threshold */ - SWord = SK_XM_THR_SL; /* for single port */ - - if (pAC->GIni.GIMacsFound > 1) { - switch (pAC->GIni.GIPortUsage) { - case SK_RED_LINK: - SWord = SK_XM_THR_REDL; /* redundant link */ - break; - case SK_MUL_LINK: - SWord = SK_XM_THR_MULL; /* load balancing */ - break; - case SK_JUMBO_LINK: - SWord = SK_XM_THR_JUMBO; /* jumbo frames */ - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG); - break; - } - } - XM_OUT16(IoC, Port, XM_TX_THR, SWord); - - /* setup register defaults for the Tx Command Register */ - XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD); - - /* setup register defaults for the Rx Command Register */ - SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK; - - if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { - SWord |= XM_RX_BIG_PK_OK; - } - - if (pPrt->PLinkMode == SK_LMODE_HALF) { - /* - * If in manual half duplex mode the other side might be in - * full duplex mode, so ignore if a carrier extension is not seen - * on frames received - */ - SWord |= XM_RX_DIS_CEXT; - } - - XM_OUT16(IoC, Port, XM_RX_CMD, SWord); - - /* - * setup register defaults for the Mode Register - * - Don't strip error frames to avoid Store & Forward - * on the Rx side. - * - Enable 'Check Station Address' bit - * - Enable 'Check Address Array' bit - */ - XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE); - - /* - * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK) - * - Enable all bits excepting 'Octets Rx OK Low CntOv' - * and 'Octets Rx OK Hi Cnt Ov'. - */ - XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK); - - /* - * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK) - * - Enable all bits excepting 'Octets Tx OK Low CntOv' - * and 'Octets Tx OK Hi Cnt Ov'. - */ - XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK); - - /* - * Do NOT init XMAC interrupt mask here. - * All interrupts remain disable until link comes up! - */ - - /* - * Any additional configuration changes may be done now. - * The last action is to enable the Rx and Tx state machine. - * This should be done after the auto-negotiation process - * has been completed successfully. - */ -} /* SkXmInitMac */ -#endif /* GENESIS */ - - -#ifdef YUKON -/****************************************************************************** - * - * SkGmInitMac() - Initialize the GMAC - * - * Description: - * Initialize the GMAC of the specified port. - * The GMAC must be reset or stopped before calling this function. - * - * Note: - * The GMAC's Rx and Tx state machine is still disabled when returning. - * - * Returns: - * nothing - */ -void SkGmInitMac( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - int i; - SK_U16 SWord; - SK_U32 DWord; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PState == SK_PRT_STOP) { - /* Port State: SK_PRT_STOP */ - /* Verify that the reset bit is cleared */ - SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord); - - if ((DWord & GMC_RST_SET) != 0) { - /* PState does not match HW state */ - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG); - /* Correct it */ - pPrt->PState = SK_PRT_RESET; - } - } - - if (pPrt->PState == SK_PRT_RESET) { - - SkGmHardRst(pAC, IoC, Port); - - SkGmClearRst(pAC, IoC, Port); - - /* Auto-negotiation ? */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - /* Auto-negotiation disabled */ - - /* get General Purpose Control */ - GM_IN16(IoC, Port, GM_GP_CTRL, &SWord); - - /* disable auto-update for speed, duplex and flow-control */ - SWord |= GM_GPCR_AU_ALL_DIS; - - /* setup General Purpose Control Register */ - GM_OUT16(IoC, Port, GM_GP_CTRL, SWord); - - SWord = GM_GPCR_AU_ALL_DIS; - } - else { - SWord = 0; - } - - /* speed settings */ - switch (pPrt->PLinkSpeed) { - case SK_LSPEED_AUTO: - case SK_LSPEED_1000MBPS: - SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100; - break; - case SK_LSPEED_100MBPS: - SWord |= GM_GPCR_SPEED_100; - break; - case SK_LSPEED_10MBPS: - break; - } - - /* duplex settings */ - if (pPrt->PLinkMode != SK_LMODE_HALF) { - /* set full duplex */ - SWord |= GM_GPCR_DUP_FULL; - } - - /* flow-control settings */ - switch (pPrt->PFlowCtrlMode) { - case SK_FLOW_MODE_NONE: - /* set Pause Off */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_OFF); - /* disable Tx & Rx flow-control */ - SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS; - break; - case SK_FLOW_MODE_LOC_SEND: - /* disable Rx flow-control */ - SWord |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS; - break; - case SK_FLOW_MODE_SYMMETRIC: - case SK_FLOW_MODE_SYM_OR_REM: - /* enable Tx & Rx flow-control */ - break; - } - - /* setup General Purpose Control Register */ - GM_OUT16(IoC, Port, GM_GP_CTRL, SWord); - - /* dummy read the Interrupt Source Register */ - SK_IN16(IoC, GMAC_IRQ_SRC, &SWord); - -#ifndef VCPU - /* read Id from PHY */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1); - - SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE); -#endif /* VCPU */ - } - - (void)SkGmResetCounter(pAC, IoC, Port); - - /* setup Transmit Control Register */ - GM_OUT16(IoC, Port, GM_TX_CTRL, TX_COL_THR(pPrt->PMacColThres)); - - /* setup Receive Control Register */ - GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA | - GM_RXCR_CRC_DIS); - - /* setup Transmit Flow Control Register */ - GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff); - - /* setup Transmit Parameter Register */ -#ifdef VCPU - GM_IN16(IoC, Port, GM_TX_PARAM, &SWord); -#endif /* VCPU */ - - SWord = TX_JAM_LEN_VAL(pPrt->PMacJamLen) | - TX_JAM_IPG_VAL(pPrt->PMacJamIpgVal) | - TX_IPG_JAM_DATA(pPrt->PMacJamIpgData); - - GM_OUT16(IoC, Port, GM_TX_PARAM, SWord); - - /* configure the Serial Mode Register */ -#ifdef VCPU - GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord); -#endif /* VCPU */ - - SWord = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(pPrt->PMacIpgData); - - if (pPrt->PMacLimit4) { - /* reset of collision counter after 4 consecutive collisions */ - SWord |= GM_SMOD_LIMIT_4; - } - - if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { - /* enable jumbo mode (Max. Frame Length = 9018) */ - SWord |= GM_SMOD_JUMBO_ENA; - } - - GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord); - - /* - * configure the GMACs Station Addresses - * in PROM you can find our addresses at: - * B2_MAC_1 = xx xx xx xx xx x0 virtual address - * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A - * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort - */ - - for (i = 0; i < 3; i++) { - /* - * The following 2 statements are together endianess - * independent. Remember this when changing. - */ - /* physical address: will be used for pause frames */ - SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord); - -#ifdef WA_DEV_16 - /* WA for deviation #16 */ - if (pAC->GIni.GIChipId == CHIP_ID_YUKON && pAC->GIni.GIChipRev == 0) { - /* swap the address bytes */ - SWord = ((SWord & 0xff00) >> 8) | ((SWord & 0x00ff) << 8); - - /* write to register in reversed order */ - GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord); - } - else { - GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord); - } -#else - GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord); -#endif /* WA_DEV_16 */ - - /* virtual address: will be used for data */ - SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord); - - GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord); - - /* reset Multicast filtering Hash registers 1-3 */ - GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0); - } - - /* reset Multicast filtering Hash register 4 */ - GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0); - - /* enable interrupt mask for counter overflows */ - GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0); - GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0); - GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0); - -#if defined(SK_DIAG) || defined(DEBUG) - /* read General Purpose Status */ - GM_IN16(IoC, Port, GM_GP_STAT, &SWord); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("MAC Stat Reg.=0x%04X\n", SWord)); -#endif /* SK_DIAG || DEBUG */ - -#ifdef SK_DIAG - c_print("MAC Stat Reg=0x%04X\n", SWord); -#endif /* SK_DIAG */ - -} /* SkGmInitMac */ -#endif /* YUKON */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkXmInitDupMd() - Initialize the XMACs Duplex Mode - * - * Description: - * This function initializes the XMACs Duplex Mode. - * It should be called after successfully finishing - * the Auto-negotiation Process - * - * Returns: - * nothing - */ -static void SkXmInitDupMd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - switch (pAC->GIni.GP[Port].PLinkModeStatus) { - case SK_LMODE_STAT_AUTOHALF: - case SK_LMODE_STAT_HALF: - /* Configuration Actions for Half Duplex Mode */ - /* - * XM_BURST = default value. We are probable not quick - * enough at the 'XMAC' bus to burst 8kB. - * The XMAC stops bursting if no transmit frames - * are available or the burst limit is exceeded. - */ - /* XM_TX_RT_LIM = default value (15) */ - /* XM_TX_STIME = default value (0xff = 4096 bit times) */ - break; - case SK_LMODE_STAT_AUTOFULL: - case SK_LMODE_STAT_FULL: - /* Configuration Actions for Full Duplex Mode */ - /* - * The duplex mode is configured by the PHY, - * therefore it seems to be that there is nothing - * to do here. - */ - break; - case SK_LMODE_STAT_UNKNOWN: - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG); - break; - } -} /* SkXmInitDupMd */ - - -/****************************************************************************** - * - * SkXmInitPauseMd() - initialize the Pause Mode to be used for this port - * - * Description: - * This function initializes the Pause Mode which should - * be used for this port. - * It should be called after successfully finishing - * the Auto-negotiation Process - * - * Returns: - * nothing - */ -static void SkXmInitPauseMd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U32 DWord; - SK_U16 Word; - - pPrt = &pAC->GIni.GP[Port]; - - XM_IN16(IoC, Port, XM_MMU_CMD, &Word); - - if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE || - pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) { - - /* Disable Pause Frame Reception */ - Word |= XM_MMU_IGN_PF; - } - else { - /* - * enabling pause frame reception is required for 1000BT - * because the XMAC is not reset if the link is going down - */ - /* Enable Pause Frame Reception */ - Word &= ~XM_MMU_IGN_PF; - } - - XM_OUT16(IoC, Port, XM_MMU_CMD, Word); - - XM_IN32(IoC, Port, XM_MODE, &DWord); - - if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC || - pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) { - - /* - * Configure Pause Frame Generation - * Use internal and external Pause Frame Generation. - * Sending pause frames is edge triggered. - * Send a Pause frame with the maximum pause time if - * internal oder external FIFO full condition occurs. - * Send a zero pause time frame to re-start transmission. - */ - - /* XM_PAUSE_DA = '010000C28001' (default) */ - - /* XM_MAC_PTIME = 0xffff (maximum) */ - /* remember this value is defined in big endian (!) */ - XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff); - - /* Set Pause Mode in Mode Register */ - DWord |= XM_PAUSE_MODE; - - /* Set Pause Mode in MAC Rx FIFO */ - SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE); - } - else { - /* - * disable pause frame generation is required for 1000BT - * because the XMAC is not reset if the link is going down - */ - /* Disable Pause Mode in Mode Register */ - DWord &= ~XM_PAUSE_MODE; - - /* Disable Pause Mode in MAC Rx FIFO */ - SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE); - } - - XM_OUT32(IoC, Port, XM_MODE, DWord); -} /* SkXmInitPauseMd*/ - - -/****************************************************************************** - * - * SkXmInitPhyXmac() - Initialize the XMAC Phy registers - * - * Description: initializes all the XMACs Phy registers - * - * Note: - * - * Returns: - * nothing - */ -static void SkXmInitPhyXmac( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ -{ - SK_GEPORT *pPrt; - SK_U16 Ctrl; - - pPrt = &pAC->GIni.GP[Port]; - Ctrl = 0; - - /* Auto-negotiation ? */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyXmac: no auto-negotiation Port %d\n", Port)); - /* Set DuplexMode in Config register */ - if (pPrt->PLinkMode == SK_LMODE_FULL) { - Ctrl |= PHY_CT_DUP_MD; - } - - /* - * Do NOT enable Auto-negotiation here. This would hold - * the link down because no IDLEs are transmitted - */ - } - else { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyXmac: with auto-negotiation Port %d\n", Port)); - /* Set Auto-negotiation advertisement */ - - /* Set Full/half duplex capabilities */ - switch (pPrt->PLinkMode) { - case SK_LMODE_AUTOHALF: - Ctrl |= PHY_X_AN_HD; - break; - case SK_LMODE_AUTOFULL: - Ctrl |= PHY_X_AN_FD; - break; - case SK_LMODE_AUTOBOTH: - Ctrl |= PHY_X_AN_FD | PHY_X_AN_HD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, - SKERR_HWI_E015MSG); - } - - /* Set Flow-control capabilities */ - switch (pPrt->PFlowCtrlMode) { - case SK_FLOW_MODE_NONE: - Ctrl |= PHY_X_P_NO_PAUSE; - break; - case SK_FLOW_MODE_LOC_SEND: - Ctrl |= PHY_X_P_ASYM_MD; - break; - case SK_FLOW_MODE_SYMMETRIC: - Ctrl |= PHY_X_P_SYM_MD; - break; - case SK_FLOW_MODE_SYM_OR_REM: - Ctrl |= PHY_X_P_BOTH_MD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, - SKERR_HWI_E016MSG); - } - - /* Write AutoNeg Advertisement Register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_AUNE_ADV, Ctrl); - - /* Restart Auto-negotiation */ - Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG; - } - - if (DoLoop) { - /* Set the Phy Loopback bit, too */ - Ctrl |= PHY_CT_LOOP; - } - - /* Write to the Phy control register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl); -} /* SkXmInitPhyXmac */ - - -/****************************************************************************** - * - * SkXmInitPhyBcom() - Initialize the Broadcom Phy registers - * - * Description: initializes all the Broadcom Phy registers - * - * Note: - * - * Returns: - * nothing - */ -static void SkXmInitPhyBcom( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ -{ - SK_GEPORT *pPrt; - SK_U16 Ctrl1; - SK_U16 Ctrl2; - SK_U16 Ctrl3; - SK_U16 Ctrl4; - SK_U16 Ctrl5; - - Ctrl1 = PHY_CT_SP1000; - Ctrl2 = 0; - Ctrl3 = PHY_SEL_TYPE; - Ctrl4 = PHY_B_PEC_EN_LTR; - Ctrl5 = PHY_B_AC_TX_TST; - - pPrt = &pAC->GIni.GP[Port]; - - /* manually Master/Slave ? */ - if (pPrt->PMSMode != SK_MS_MODE_AUTO) { - Ctrl2 |= PHY_B_1000C_MSE; - - if (pPrt->PMSMode == SK_MS_MODE_MASTER) { - Ctrl2 |= PHY_B_1000C_MSC; - } - } - /* Auto-negotiation ? */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyBcom: no auto-negotiation Port %d\n", Port)); - /* Set DuplexMode in Config register */ - if (pPrt->PLinkMode == SK_LMODE_FULL) { - Ctrl1 |= PHY_CT_DUP_MD; - } - - /* Determine Master/Slave manually if not already done */ - if (pPrt->PMSMode == SK_MS_MODE_AUTO) { - Ctrl2 |= PHY_B_1000C_MSE; /* set it to Slave */ - } - - /* - * Do NOT enable Auto-negotiation here. This would hold - * the link down because no IDLES are transmitted - */ - } - else { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyBcom: with auto-negotiation Port %d\n", Port)); - /* Set Auto-negotiation advertisement */ - - /* - * Workaround BCOM Errata #1 for the C5 type. - * 1000Base-T Link Acquisition Failure in Slave Mode - * Set Repeater/DTE bit 10 of the 1000Base-T Control Register - */ - Ctrl2 |= PHY_B_1000C_RD; - - /* Set Full/half duplex capabilities */ - switch (pPrt->PLinkMode) { - case SK_LMODE_AUTOHALF: - Ctrl2 |= PHY_B_1000C_AHD; - break; - case SK_LMODE_AUTOFULL: - Ctrl2 |= PHY_B_1000C_AFD; - break; - case SK_LMODE_AUTOBOTH: - Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, - SKERR_HWI_E015MSG); - } - - /* Set Flow-control capabilities */ - switch (pPrt->PFlowCtrlMode) { - case SK_FLOW_MODE_NONE: - Ctrl3 |= PHY_B_P_NO_PAUSE; - break; - case SK_FLOW_MODE_LOC_SEND: - Ctrl3 |= PHY_B_P_ASYM_MD; - break; - case SK_FLOW_MODE_SYMMETRIC: - Ctrl3 |= PHY_B_P_SYM_MD; - break; - case SK_FLOW_MODE_SYM_OR_REM: - Ctrl3 |= PHY_B_P_BOTH_MD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, - SKERR_HWI_E016MSG); - } - - /* Restart Auto-negotiation */ - Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG; - } - - /* Initialize LED register here? */ - /* No. Please do it in SkDgXmitLed() (if required) and swap - init order of LEDs and XMAC. (MAl) */ - - /* Write 1000Base-T Control Register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Set 1000B-T Ctrl Reg=0x%04X\n", Ctrl2)); - - /* Write AutoNeg Advertisement Register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Set Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3)); - - if (DoLoop) { - /* Set the Phy Loopback bit, too */ - Ctrl1 |= PHY_CT_LOOP; - } - - if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { - /* configure FIFO to high latency for transmission of ext. packets */ - Ctrl4 |= PHY_B_PEC_HIGH_LA; - - /* configure reception of extended packets */ - Ctrl5 |= PHY_B_AC_LONG_PACK; - - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, Ctrl5); - } - - /* Configure LED Traffic Mode and Jumbo Frame usage if specified */ - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4); - - /* Write to the Phy control register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Control Reg=0x%04X\n", Ctrl1)); -} /* SkXmInitPhyBcom */ -#endif /* GENESIS */ - -#ifdef YUKON -/****************************************************************************** - * - * SkGmInitPhyMarv() - Initialize the Marvell Phy registers - * - * Description: initializes all the Marvell Phy registers - * - * Note: - * - * Returns: - * nothing - */ -static void SkGmInitPhyMarv( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ -{ - SK_GEPORT *pPrt; - SK_U16 PhyCtrl; - SK_U16 C1000BaseT; - SK_U16 AutoNegAdv; - SK_U16 ExtPhyCtrl; - SK_U16 LedCtrl; - SK_BOOL AutoNeg; -#if defined(SK_DIAG) || defined(DEBUG) - SK_U16 PhyStat; - SK_U16 PhyStat1; - SK_U16 PhySpecStat; -#endif /* SK_DIAG || DEBUG */ - - pPrt = &pAC->GIni.GP[Port]; - - /* Auto-negotiation ? */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - AutoNeg = SK_FALSE; - } - else { - AutoNeg = SK_TRUE; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyMarv: Port %d, auto-negotiation %s\n", - Port, AutoNeg ? "ON" : "OFF")); - -#ifdef VCPU - VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n", - Port, DoLoop); -#else /* VCPU */ - if (DoLoop) { - /* Set 'MAC Power up'-bit, set Manual MDI configuration */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, - PHY_M_PC_MAC_POW_UP); - } - else if (AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_AUTO) { - /* Read Ext. PHY Specific Control */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl); - - ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | - PHY_M_EC_MAC_S_MSK); - - ExtPhyCtrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ) | - PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1); - - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Set Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl)); - } - - /* Read PHY Control */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl); - - if (!AutoNeg) { - /* Disable Auto-negotiation */ - PhyCtrl &= ~PHY_CT_ANE; - } - - PhyCtrl |= PHY_CT_RESET; - /* Assert software reset */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl); -#endif /* VCPU */ - - PhyCtrl = 0 /* PHY_CT_COL_TST */; - C1000BaseT = 0; - AutoNegAdv = PHY_SEL_TYPE; - - /* manually Master/Slave ? */ - if (pPrt->PMSMode != SK_MS_MODE_AUTO) { - /* enable Manual Master/Slave */ - C1000BaseT |= PHY_M_1000C_MSE; - - if (pPrt->PMSMode == SK_MS_MODE_MASTER) { - C1000BaseT |= PHY_M_1000C_MSC; /* set it to Master */ - } - } - - /* Auto-negotiation ? */ - if (!AutoNeg) { - - if (pPrt->PLinkMode == SK_LMODE_FULL) { - /* Set Full Duplex Mode */ - PhyCtrl |= PHY_CT_DUP_MD; - } - - /* Set Master/Slave manually if not already done */ - if (pPrt->PMSMode == SK_MS_MODE_AUTO) { - C1000BaseT |= PHY_M_1000C_MSE; /* set it to Slave */ - } - - /* Set Speed */ - switch (pPrt->PLinkSpeed) { - case SK_LSPEED_AUTO: - case SK_LSPEED_1000MBPS: - PhyCtrl |= PHY_CT_SP1000; - break; - case SK_LSPEED_100MBPS: - PhyCtrl |= PHY_CT_SP100; - break; - case SK_LSPEED_10MBPS: - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019, - SKERR_HWI_E019MSG); - } - - if (!DoLoop) { - PhyCtrl |= PHY_CT_RESET; - } - } - else { - /* Set Auto-negotiation advertisement */ - - if (pAC->GIni.GICopperType) { - /* Set Speed capabilities */ - switch (pPrt->PLinkSpeed) { - case SK_LSPEED_AUTO: - C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD; - AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD | - PHY_M_AN_10_FD | PHY_M_AN_10_HD; - break; - case SK_LSPEED_1000MBPS: - C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD; - break; - case SK_LSPEED_100MBPS: - AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD | - /* advertise 10Base-T also */ - PHY_M_AN_10_FD | PHY_M_AN_10_HD; - break; - case SK_LSPEED_10MBPS: - AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019, - SKERR_HWI_E019MSG); - } - - /* Set Full/half duplex capabilities */ - switch (pPrt->PLinkMode) { - case SK_LMODE_AUTOHALF: - C1000BaseT &= ~PHY_M_1000C_AFD; - AutoNegAdv &= ~(PHY_M_AN_100_FD | PHY_M_AN_10_FD); - break; - case SK_LMODE_AUTOFULL: - C1000BaseT &= ~PHY_M_1000C_AHD; - AutoNegAdv &= ~(PHY_M_AN_100_HD | PHY_M_AN_10_HD); - break; - case SK_LMODE_AUTOBOTH: - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, - SKERR_HWI_E015MSG); - } - - /* Set Flow-control capabilities */ - switch (pPrt->PFlowCtrlMode) { - case SK_FLOW_MODE_NONE: - AutoNegAdv |= PHY_B_P_NO_PAUSE; - break; - case SK_FLOW_MODE_LOC_SEND: - AutoNegAdv |= PHY_B_P_ASYM_MD; - break; - case SK_FLOW_MODE_SYMMETRIC: - AutoNegAdv |= PHY_B_P_SYM_MD; - break; - case SK_FLOW_MODE_SYM_OR_REM: - AutoNegAdv |= PHY_B_P_BOTH_MD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, - SKERR_HWI_E016MSG); - } - } - else { /* special defines for FIBER (88E1011S only) */ - - /* Set Full/half duplex capabilities */ - switch (pPrt->PLinkMode) { - case SK_LMODE_AUTOHALF: - AutoNegAdv |= PHY_M_AN_1000X_AHD; - break; - case SK_LMODE_AUTOFULL: - AutoNegAdv |= PHY_M_AN_1000X_AFD; - break; - case SK_LMODE_AUTOBOTH: - AutoNegAdv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, - SKERR_HWI_E015MSG); - } - - /* Set Flow-control capabilities */ - switch (pPrt->PFlowCtrlMode) { - case SK_FLOW_MODE_NONE: - AutoNegAdv |= PHY_M_P_NO_PAUSE_X; - break; - case SK_FLOW_MODE_LOC_SEND: - AutoNegAdv |= PHY_M_P_ASYM_MD_X; - break; - case SK_FLOW_MODE_SYMMETRIC: - AutoNegAdv |= PHY_M_P_SYM_MD_X; - break; - case SK_FLOW_MODE_SYM_OR_REM: - AutoNegAdv |= PHY_M_P_BOTH_MD_X; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, - SKERR_HWI_E016MSG); - } - } - - if (!DoLoop) { - /* Restart Auto-negotiation */ - PhyCtrl |= PHY_CT_ANE | PHY_CT_RE_CFG; - } - } - -#ifdef VCPU - /* - * E-mail from Gu Lin (08-03-2002): - */ - - /* Program PHY register 30 as 16'h0708 for simulation speed up */ - SkGmPhyWrite(pAC, IoC, Port, 30, 0x0700 /* 0x0708 */); - - VCpuWait(2000); - -#else /* VCPU */ - - /* Write 1000Base-T Control Register */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Set 1000B-T Ctrl =0x%04X\n", C1000BaseT)); - - /* Write AutoNeg Advertisement Register */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Set Auto-Neg.Adv.=0x%04X\n", AutoNegAdv)); -#endif /* VCPU */ - - if (DoLoop) { - /* Set the PHY Loopback bit */ - PhyCtrl |= PHY_CT_LOOP; - -#ifdef XXX - /* Program PHY register 16 as 16'h0400 to force link good */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD); -#endif /* XXX */ - -#ifndef VCPU - if (pPrt->PLinkSpeed != SK_LSPEED_AUTO) { - /* Write Ext. PHY Specific Control */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, - (SK_U16)((pPrt->PLinkSpeed + 2) << 4)); - } -#endif /* VCPU */ - } -#ifdef TEST_ONLY - else if (pPrt->PLinkSpeed == SK_LSPEED_10MBPS) { - /* Write PHY Specific Control */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, - PHY_M_PC_EN_DET_MSK); - } -#endif - - /* Write to the PHY Control register */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Set PHY Ctrl Reg.=0x%04X\n", PhyCtrl)); - -#ifdef VCPU - VCpuWait(2000); -#else - - LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS) | PHY_M_LED_BLINK_RT(BLINK_84MS); - - if ((pAC->GIni.GILedBlinkCtrl & SK_ACT_LED_BLINK) != 0) { - LedCtrl |= PHY_M_LEDC_RX_CTRL | PHY_M_LEDC_TX_CTRL; - } - - if ((pAC->GIni.GILedBlinkCtrl & SK_DUP_LED_NORMAL) != 0) { - LedCtrl |= PHY_M_LEDC_DP_CTRL; - } - - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl); - - if ((pAC->GIni.GILedBlinkCtrl & SK_LED_LINK100_ON) != 0) { - /* only in forced 100 Mbps mode */ - if (!AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_100MBPS) { - - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_OVER, - PHY_M_LED_MO_100(MO_LED_ON)); - } - } - -#ifdef SK_DIAG - c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl); - c_print("Set 1000 B-T=0x%04X\n", C1000BaseT); - c_print("Set Auto-Neg=0x%04X\n", AutoNegAdv); - c_print("Set Ext Ctrl=0x%04X\n", ExtPhyCtrl); -#endif /* SK_DIAG */ - -#if defined(SK_DIAG) || defined(DEBUG) - /* Read PHY Control */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Ctrl Reg.=0x%04X\n", PhyCtrl)); - - /* Read 1000Base-T Control Register */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("1000B-T Ctrl =0x%04X\n", C1000BaseT)); - - /* Read AutoNeg Advertisement Register */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Auto-Neg.Adv.=0x%04X\n", AutoNegAdv)); - - /* Read Ext. PHY Specific Control */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl)); - - /* Read PHY Status */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Stat Reg.=0x%04X\n", PhyStat)); - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Stat Reg.=0x%04X\n", PhyStat1)); - - /* Read PHY Specific Status */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Spec Stat=0x%04X\n", PhySpecStat)); -#endif /* SK_DIAG || DEBUG */ - -#ifdef SK_DIAG - c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl); - c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT); - c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv); - c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl); - c_print("PHY Stat Reg=0x%04X\n", PhyStat); - c_print("PHY Stat Reg=0x%04X\n", PhyStat1); - c_print("PHY Spec Reg=0x%04X\n", PhySpecStat); -#endif /* SK_DIAG */ - -#endif /* VCPU */ - -} /* SkGmInitPhyMarv */ -#endif /* YUKON */ - - -#ifdef OTHER_PHY -/****************************************************************************** - * - * SkXmInitPhyLone() - Initialize the Level One Phy registers - * - * Description: initializes all the Level One Phy registers - * - * Note: - * - * Returns: - * nothing - */ -static void SkXmInitPhyLone( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ -{ - SK_GEPORT *pPrt; - SK_U16 Ctrl1; - SK_U16 Ctrl2; - SK_U16 Ctrl3; - - Ctrl1 = PHY_CT_SP1000; - Ctrl2 = 0; - Ctrl3 = PHY_SEL_TYPE; - - pPrt = &pAC->GIni.GP[Port]; - - /* manually Master/Slave ? */ - if (pPrt->PMSMode != SK_MS_MODE_AUTO) { - Ctrl2 |= PHY_L_1000C_MSE; - - if (pPrt->PMSMode == SK_MS_MODE_MASTER) { - Ctrl2 |= PHY_L_1000C_MSC; - } - } - /* Auto-negotiation ? */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - /* - * level one spec say: "1000 Mbps: manual mode not allowed" - * but lets see what happens... - */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyLone: no auto-negotiation Port %d\n", Port)); - /* Set DuplexMode in Config register */ - if (pPrt->PLinkMode == SK_LMODE_FULL) { - Ctrl1 |= PHY_CT_DUP_MD; - } - - /* Determine Master/Slave manually if not already done */ - if (pPrt->PMSMode == SK_MS_MODE_AUTO) { - Ctrl2 |= PHY_L_1000C_MSE; /* set it to Slave */ - } - - /* - * Do NOT enable Auto-negotiation here. This would hold - * the link down because no IDLES are transmitted - */ - } - else { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyLone: with auto-negotiation Port %d\n", Port)); - /* Set Auto-negotiation advertisement */ - - /* Set Full/half duplex capabilities */ - switch (pPrt->PLinkMode) { - case SK_LMODE_AUTOHALF: - Ctrl2 |= PHY_L_1000C_AHD; - break; - case SK_LMODE_AUTOFULL: - Ctrl2 |= PHY_L_1000C_AFD; - break; - case SK_LMODE_AUTOBOTH: - Ctrl2 |= PHY_L_1000C_AFD | PHY_L_1000C_AHD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, - SKERR_HWI_E015MSG); - } - - /* Set Flow-control capabilities */ - switch (pPrt->PFlowCtrlMode) { - case SK_FLOW_MODE_NONE: - Ctrl3 |= PHY_L_P_NO_PAUSE; - break; - case SK_FLOW_MODE_LOC_SEND: - Ctrl3 |= PHY_L_P_ASYM_MD; - break; - case SK_FLOW_MODE_SYMMETRIC: - Ctrl3 |= PHY_L_P_SYM_MD; - break; - case SK_FLOW_MODE_SYM_OR_REM: - Ctrl3 |= PHY_L_P_BOTH_MD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, - SKERR_HWI_E016MSG); - } - - /* Restart Auto-negotiation */ - Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG; - } - - /* Write 1000Base-T Control Register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2)); - - /* Write AutoNeg Advertisement Register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3)); - - if (DoLoop) { - /* Set the Phy Loopback bit, too */ - Ctrl1 |= PHY_CT_LOOP; - } - - /* Write to the Phy control register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Control Reg=0x%04X\n", Ctrl1)); -} /* SkXmInitPhyLone */ - - -/****************************************************************************** - * - * SkXmInitPhyNat() - Initialize the National Phy registers - * - * Description: initializes all the National Phy registers - * - * Note: - * - * Returns: - * nothing - */ -static void SkXmInitPhyNat( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ -{ -/* todo: National */ -} /* SkXmInitPhyNat */ -#endif /* OTHER_PHY */ - - -/****************************************************************************** - * - * SkMacInitPhy() - Initialize the PHY registers - * - * Description: calls the Init PHY routines dep. on board type - * - * Note: - * - * Returns: - * nothing - */ -void SkMacInitPhy( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ -{ - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - switch (pPrt->PhyType) { - case SK_PHY_XMAC: - SkXmInitPhyXmac(pAC, IoC, Port, DoLoop); - break; - case SK_PHY_BCOM: - SkXmInitPhyBcom(pAC, IoC, Port, DoLoop); - break; -#ifdef OTHER_PHY - case SK_PHY_LONE: - SkXmInitPhyLone(pAC, IoC, Port, DoLoop); - break; - case SK_PHY_NAT: - SkXmInitPhyNat(pAC, IoC, Port, DoLoop); - break; -#endif /* OTHER_PHY */ - } - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - SkGmInitPhyMarv(pAC, IoC, Port, DoLoop); - } -#endif /* YUKON */ - -} /* SkMacInitPhy */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkXmAutoNegDoneXmac() - Auto-negotiation handling - * - * Description: - * This function handles the auto-negotiation if the Done bit is set. - * - * Returns: - * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened - */ -static int SkXmAutoNegDoneXmac( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U16 ResAb; /* Resolved Ability */ - SK_U16 LPAb; /* Link Partner Ability */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegDoneXmac, Port %d\n", Port)); - - pPrt = &pAC->GIni.GP[Port]; - - /* Get PHY parameters */ - SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LPAb); - SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb); - - if ((LPAb & PHY_X_AN_RFB) != 0) { - /* At least one of the remote fault bit is set */ - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegFail: Remote fault bit set Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - return(SK_AND_OTHER); - } - - /* Check Duplex mismatch */ - if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) { - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL; - } - else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) { - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF; - } - else { - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegFail: Duplex mode mismatch Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - return(SK_AND_DUP_CAP); - } - - /* Check PAUSE mismatch */ - /* We are NOT using chapter 4.23 of the Xaqti manual */ - /* We are using IEEE 802.3z/D5.0 Table 37-4 */ - if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC || - pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) && - (LPAb & PHY_X_P_SYM_MD) != 0) { - /* Symmetric PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; - } - else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM && - (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) { - /* Enable PAUSE receive, disable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; - } - else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND && - (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) { - /* Disable PAUSE receive, enable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; - } - else { - /* PAUSE mismatch -> no PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; - } - pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS; - - return(SK_AND_OK); -} /* SkXmAutoNegDoneXmac */ - - -/****************************************************************************** - * - * SkXmAutoNegDoneBcom() - Auto-negotiation handling - * - * Description: - * This function handles the auto-negotiation if the Done bit is set. - * - * Returns: - * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened - */ -static int SkXmAutoNegDoneBcom( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U16 LPAb; /* Link Partner Ability */ - SK_U16 AuxStat; /* Auxiliary Status */ - -#ifdef TEST_ONLY -01-Sep-2000 RA;:;: - SK_U16 ResAb; /* Resolved Ability */ -#endif /* 0 */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegDoneBcom, Port %d\n", Port)); - pPrt = &pAC->GIni.GP[Port]; - - /* Get PHY parameters */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb); -#ifdef TEST_ONLY -01-Sep-2000 RA;:;: - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb); -#endif /* 0 */ - - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat); - - if ((LPAb & PHY_B_AN_RF) != 0) { - /* Remote fault bit is set: Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegFail: Remote fault bit set Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - return(SK_AND_OTHER); - } - - /* Check Duplex mismatch */ - if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) { - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL; - } - else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) { - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF; - } - else { - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegFail: Duplex mode mismatch Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - return(SK_AND_DUP_CAP); - } - -#ifdef TEST_ONLY -01-Sep-2000 RA;:;: - /* Check Master/Slave resolution */ - if ((ResAb & PHY_B_1000S_MSF) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Master/Slave Fault Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - pPrt->PMSStatus = SK_MS_STAT_FAULT; - return(SK_AND_OTHER); - } - - pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? - SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE; -#endif /* 0 */ - - /* Check PAUSE mismatch ??? */ - /* We are using IEEE 802.3z/D5.0 Table 37-4 */ - if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) { - /* Symmetric PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; - } - else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) { - /* Enable PAUSE receive, disable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; - } - else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) { - /* Disable PAUSE receive, enable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; - } - else { - /* PAUSE mismatch -> no PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; - } - pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS; - - return(SK_AND_OK); -} /* SkXmAutoNegDoneBcom */ -#endif /* GENESIS */ - - -#ifdef YUKON -/****************************************************************************** - * - * SkGmAutoNegDoneMarv() - Auto-negotiation handling - * - * Description: - * This function handles the auto-negotiation if the Done bit is set. - * - * Returns: - * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened - */ -static int SkGmAutoNegDoneMarv( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U16 LPAb; /* Link Partner Ability */ - SK_U16 ResAb; /* Resolved Ability */ - SK_U16 AuxStat; /* Auxiliary Status */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegDoneMarv, Port %d\n", Port)); - pPrt = &pAC->GIni.GP[Port]; - - /* Get PHY parameters */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Link P.Abil.=0x%04X\n", LPAb)); - - if ((LPAb & PHY_M_AN_RF) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegFail: Remote fault bit set Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - return(SK_AND_OTHER); - } - - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb); - - /* Check Master/Slave resolution */ - if ((ResAb & PHY_B_1000S_MSF) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Master/Slave Fault Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - pPrt->PMSStatus = SK_MS_STAT_FAULT; - return(SK_AND_OTHER); - } - - pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? - (SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE; - - /* Read PHY Specific Status */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat); - - /* Check Speed & Duplex resolved */ - if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegFail: Speed & Duplex not resolved, Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN; - return(SK_AND_DUP_CAP); - } - - if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) { - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL; - } - else { - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF; - } - - /* Check PAUSE mismatch ??? */ - /* We are using IEEE 802.3z/D5.0 Table 37-4 */ - if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_PAUSE_MSK) { - /* Symmetric PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; - } - else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_RX_P_EN) { - /* Enable PAUSE receive, disable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; - } - else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) { - /* Disable PAUSE receive, enable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; - } - else { - /* PAUSE mismatch -> no PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; - } - - /* set used link speed */ - switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) { - case (unsigned)PHY_M_PS_SPEED_1000: - pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS; - break; - case PHY_M_PS_SPEED_100: - pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS; - break; - default: - pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS; - } - - return(SK_AND_OK); -} /* SkGmAutoNegDoneMarv */ -#endif /* YUKON */ - - -#ifdef OTHER_PHY -/****************************************************************************** - * - * SkXmAutoNegDoneLone() - Auto-negotiation handling - * - * Description: - * This function handles the auto-negotiation if the Done bit is set. - * - * Returns: - * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened - */ -static int SkXmAutoNegDoneLone( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U16 ResAb; /* Resolved Ability */ - SK_U16 LPAb; /* Link Partner Ability */ - SK_U16 QuickStat; /* Auxiliary Status */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegDoneLone, Port %d\n", Port)); - pPrt = &pAC->GIni.GP[Port]; - - /* Get PHY parameters */ - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LPAb); - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb); - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat); - - if ((LPAb & PHY_L_AN_RF) != 0) { - /* Remote fault bit is set */ - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegFail: Remote fault bit set Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - return(SK_AND_OTHER); - } - - /* Check Duplex mismatch */ - if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) { - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL; - } - else { - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF; - } - - /* Check Master/Slave resolution */ - if ((ResAb & PHY_L_1000S_MSF) != 0) { - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Master/Slave Fault Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - pPrt->PMSStatus = SK_MS_STAT_FAULT; - return(SK_AND_OTHER); - } - else if (ResAb & PHY_L_1000S_MSR) { - pPrt->PMSStatus = SK_MS_STAT_MASTER; - } - else { - pPrt->PMSStatus = SK_MS_STAT_SLAVE; - } - - /* Check PAUSE mismatch */ - /* We are using IEEE 802.3z/D5.0 Table 37-4 */ - /* we must manually resolve the abilities here */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; - - switch (pPrt->PFlowCtrlMode) { - case SK_FLOW_MODE_NONE: - /* default */ - break; - case SK_FLOW_MODE_LOC_SEND: - if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) == - (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) { - /* Disable PAUSE receive, enable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; - } - break; - case SK_FLOW_MODE_SYMMETRIC: - if ((QuickStat & PHY_L_QS_PAUSE) != 0) { - /* Symmetric PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; - } - break; - case SK_FLOW_MODE_SYM_OR_REM: - if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) == - PHY_L_QS_AS_PAUSE) { - /* Enable PAUSE receive, disable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; - } - else if ((QuickStat & PHY_L_QS_PAUSE) != 0) { - /* Symmetric PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; - } - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, - SKERR_HWI_E016MSG); - } - - return(SK_AND_OK); -} /* SkXmAutoNegDoneLone */ - - -/****************************************************************************** - * - * SkXmAutoNegDoneNat() - Auto-negotiation handling - * - * Description: - * This function handles the auto-negotiation if the Done bit is set. - * - * Returns: - * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened - */ -static int SkXmAutoNegDoneNat( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ -/* todo: National */ - return(SK_AND_OK); -} /* SkXmAutoNegDoneNat */ -#endif /* OTHER_PHY */ - - -/****************************************************************************** - * - * SkMacAutoNegDone() - Auto-negotiation handling - * - * Description: calls the auto-negotiation done routines dep. on board type - * - * Returns: - * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened - */ -int SkMacAutoNegDone( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - int Rtv; - - Rtv = SK_AND_OK; - - pPrt = &pAC->GIni.GP[Port]; - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - switch (pPrt->PhyType) { - - case SK_PHY_XMAC: - Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port); - break; - case SK_PHY_BCOM: - Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port); - break; -#ifdef OTHER_PHY - case SK_PHY_LONE: - Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port); - break; - case SK_PHY_NAT: - Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port); - break; -#endif /* OTHER_PHY */ - default: - return(SK_AND_OTHER); - } - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port); - } -#endif /* YUKON */ - - if (Rtv != SK_AND_OK) { - return(Rtv); - } - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg done Port %d\n", Port)); - - /* We checked everything and may now enable the link */ - pPrt->PAutoNegFail = SK_FALSE; - - SkMacRxTxEnable(pAC, IoC, Port); - - return(SK_AND_OK); -} /* SkMacAutoNegDone */ - - -/****************************************************************************** - * - * SkMacRxTxEnable() - Enable Rx/Tx activity if port is up - * - * Description: enables Rx/Tx dep. on board type - * - * Returns: - * 0 o.k. - * != 0 Error happened - */ -int SkMacRxTxEnable( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U16 Reg; /* 16-bit register value */ - SK_U16 IntMask; /* MAC interrupt mask */ -#ifdef GENESIS - SK_U16 SWord; -#endif - - pPrt = &pAC->GIni.GP[Port]; - - if (!pPrt->PHWLinkUp) { - /* The Hardware link is NOT up */ - return(0); - } - - if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF || - pPrt->PLinkMode == SK_LMODE_AUTOFULL || - pPrt->PLinkMode == SK_LMODE_AUTOBOTH) && - pPrt->PAutoNegFail) { - /* Auto-negotiation is not done or failed */ - return(0); - } - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - /* set Duplex Mode and Pause Mode */ - SkXmInitDupMd(pAC, IoC, Port); - - SkXmInitPauseMd(pAC, IoC, Port); - - /* - * Initialize the Interrupt Mask Register. Default IRQs are... - * - Link Asynchronous Event - * - Link Partner requests config - * - Auto Negotiation Done - * - Rx Counter Event Overflow - * - Tx Counter Event Overflow - * - Transmit FIFO Underrun - */ - IntMask = XM_DEF_MSK; - -#ifdef DEBUG - /* add IRQ for Receive FIFO Overflow */ - IntMask &= ~XM_IS_RXF_OV; -#endif /* DEBUG */ - - if (pPrt->PhyType != SK_PHY_XMAC) { - /* disable GP0 interrupt bit */ - IntMask |= XM_IS_INP_ASS; - } - XM_OUT16(IoC, Port, XM_IMSK, IntMask); - - /* get MMU Command Reg. */ - XM_IN16(IoC, Port, XM_MMU_CMD, &Reg); - - if (pPrt->PhyType != SK_PHY_XMAC && - (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL || - pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL)) { - /* set to Full Duplex */ - Reg |= XM_MMU_GMII_FD; - } - - switch (pPrt->PhyType) { - case SK_PHY_BCOM: - /* - * Workaround BCOM Errata (#10523) for all BCom Phys - * Enable Power Management after link up - */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord); - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, - (SK_U16)(SWord & ~PHY_B_AC_DIS_PM)); - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, - (SK_U16)PHY_B_DEF_MSK); - break; -#ifdef OTHER_PHY - case SK_PHY_LONE: - SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK); - break; - case SK_PHY_NAT: - /* todo National: - SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */ - /* no interrupts possible from National ??? */ - break; -#endif /* OTHER_PHY */ - } - - /* enable Rx/Tx */ - XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* - * Initialize the Interrupt Mask Register. Default IRQs are... - * - Rx Counter Event Overflow - * - Tx Counter Event Overflow - * - Transmit FIFO Underrun - */ - IntMask = GMAC_DEF_MSK; - -#ifdef DEBUG - /* add IRQ for Receive FIFO Overrun */ - IntMask |= GM_IS_RX_FF_OR; -#endif /* DEBUG */ - - SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask); - - /* get General Purpose Control */ - GM_IN16(IoC, Port, GM_GP_CTRL, &Reg); - - if (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL || - pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) { - /* set to Full Duplex */ - Reg |= GM_GPCR_DUP_FULL; - } - - /* enable Rx/Tx */ - GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Reg | GM_GPCR_RX_ENA | - GM_GPCR_TX_ENA)); - -#ifndef VCPU - /* Enable all PHY interrupts */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, - (SK_U16)PHY_M_DEF_MSK); -#endif /* VCPU */ - } -#endif /* YUKON */ - - return(0); - -} /* SkMacRxTxEnable */ - - -/****************************************************************************** - * - * SkMacRxTxDisable() - Disable Receiver and Transmitter - * - * Description: disables Rx/Tx dep. on board type - * - * Returns: N/A - */ -void SkMacRxTxDisable( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U16 Word; - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - XM_IN16(IoC, Port, XM_MMU_CMD, &Word); - - XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX)); - - /* dummy read to ensure writing */ - XM_IN16(IoC, Port, XM_MMU_CMD, &Word); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - GM_IN16(IoC, Port, GM_GP_CTRL, &Word); - - GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Word & ~(GM_GPCR_RX_ENA | - GM_GPCR_TX_ENA))); - - /* dummy read to ensure writing */ - GM_IN16(IoC, Port, GM_GP_CTRL, &Word); - } -#endif /* YUKON */ - -} /* SkMacRxTxDisable */ - - -/****************************************************************************** - * - * SkMacIrqDisable() - Disable IRQ from MAC - * - * Description: sets the IRQ-mask to disable IRQ dep. on board type - * - * Returns: N/A - */ -void SkMacIrqDisable( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; -#ifdef GENESIS - SK_U16 Word; -#endif - - pPrt = &pAC->GIni.GP[Port]; - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - /* disable all XMAC IRQs */ - XM_OUT16(IoC, Port, XM_IMSK, 0xffff); - - /* Disable all PHY interrupts */ - switch (pPrt->PhyType) { - case SK_PHY_BCOM: - /* Make sure that PHY is initialized */ - if (pPrt->PState != SK_PRT_RESET) { - /* NOT allowed if BCOM is in RESET state */ - /* Workaround BCOM Errata (#10523) all BCom */ - /* Disable Power Management if link is down */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word); - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, - (SK_U16)(Word | PHY_B_AC_DIS_PM)); - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff); - } - break; -#ifdef OTHER_PHY - case SK_PHY_LONE: - SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0); - break; - case SK_PHY_NAT: - /* todo: National - SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */ - break; -#endif /* OTHER_PHY */ - } - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* disable all GMAC IRQs */ - SK_OUT8(IoC, GMAC_IRQ_MSK, 0); - -#ifndef VCPU - /* Disable all PHY interrupts */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0); -#endif /* VCPU */ - } -#endif /* YUKON */ - -} /* SkMacIrqDisable */ - - -#ifdef SK_DIAG -/****************************************************************************** - * - * SkXmSendCont() - Enable / Disable Send Continuous Mode - * - * Description: enable / disable Send Continuous Mode on XMAC - * - * Returns: - * nothing - */ -void SkXmSendCont( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL Enable) /* Enable / Disable */ -{ - SK_U32 MdReg; - - XM_IN32(IoC, Port, XM_MODE, &MdReg); - - if (Enable) { - MdReg |= XM_MD_TX_CONT; - } - else { - MdReg &= ~XM_MD_TX_CONT; - } - /* setup Mode Register */ - XM_OUT32(IoC, Port, XM_MODE, MdReg); - -} /* SkXmSendCont */ - - -/****************************************************************************** - * - * SkMacTimeStamp() - Enable / Disable Time Stamp - * - * Description: enable / disable Time Stamp generation for Rx packets - * - * Returns: - * nothing - */ -void SkMacTimeStamp( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL Enable) /* Enable / Disable */ -{ - SK_U32 MdReg; - SK_U8 TimeCtrl; - - if (pAC->GIni.GIGenesis) { - - XM_IN32(IoC, Port, XM_MODE, &MdReg); - - if (Enable) { - MdReg |= XM_MD_ATS; - } - else { - MdReg &= ~XM_MD_ATS; - } - /* setup Mode Register */ - XM_OUT32(IoC, Port, XM_MODE, MdReg); - } - else { - if (Enable) { - TimeCtrl = GMT_ST_START | GMT_ST_CLR_IRQ; - } - else { - TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ; - } - /* Start/Stop Time Stamp Timer */ - SK_OUT8(IoC, GMAC_TI_ST_CTRL, TimeCtrl); - } - -} /* SkMacTimeStamp*/ - -#else /* !SK_DIAG */ - -#ifdef GENESIS -/****************************************************************************** - * - * SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg - * - * This function analyses the Interrupt status word. If any of the - * Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable - * is set true. - */ -void SkXmAutoNegLipaXmac( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_U16 IStatus) /* Interrupt Status word to analyse */ -{ - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO && - (IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) { - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04X\n", - Port, IStatus)); - pPrt->PLipaAutoNeg = SK_LIPA_AUTO; - } -} /* SkXmAutoNegLipaXmac */ -#endif /* GENESIS */ - - -/****************************************************************************** - * - * SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg - * - * This function analyses the PHY status word. - * If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable - * is set true. - */ -void SkMacAutoNegLipaPhy( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_U16 PhyStat) /* PHY Status word to analyse */ -{ - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO && - (PhyStat & PHY_ST_AN_OVER) != 0) { - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04X\n", - Port, PhyStat)); - pPrt->PLipaAutoNeg = SK_LIPA_AUTO; - } -} /* SkMacAutoNegLipaPhy */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkXmIrq() - Interrupt Service Routine - * - * Description: services an Interrupt Request of the XMAC - * - * Note: - * With an external PHY, some interrupt bits are not meaningfull any more: - * - LinkAsyncEvent (bit #14) XM_IS_LNK_AE - * - LinkPartnerReqConfig (bit #10) XM_IS_LIPA_RC - * - Page Received (bit #9) XM_IS_RX_PAGE - * - NextPageLoadedForXmt (bit #8) XM_IS_TX_PAGE - * - AutoNegDone (bit #7) XM_IS_AND - * Also probably not valid any more is the GP0 input bit: - * - GPRegisterBit0set XM_IS_INP_ASS - * - * Returns: - * nothing - */ -static void SkXmIrq( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_EVPARA Para; - SK_U16 IStatus; /* Interrupt status read from the XMAC */ - SK_U16 IStatus2; -#ifdef SK_SLIM - SK_U64 OverflowStatus; -#endif - - pPrt = &pAC->GIni.GP[Port]; - - XM_IN16(IoC, Port, XM_ISRC, &IStatus); - - /* LinkPartner Auto-negable? */ - if (pPrt->PhyType == SK_PHY_XMAC) { - SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus); - } - else { - /* mask bits that are not used with ext. PHY */ - IStatus &= ~(XM_IS_LNK_AE | XM_IS_LIPA_RC | - XM_IS_RX_PAGE | XM_IS_TX_PAGE | - XM_IS_AND | XM_IS_INP_ASS); - } - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("XmacIrq Port %d Isr 0x%04X\n", Port, IStatus)); - - if (!pPrt->PHWLinkUp) { - /* Spurious XMAC interrupt */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("SkXmIrq: spurious interrupt on Port %d\n", Port)); - return; - } - - if ((IStatus & XM_IS_INP_ASS) != 0) { - /* Reread ISR Register if link is not in sync */ - XM_IN16(IoC, Port, XM_ISRC, &IStatus2); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("SkXmIrq: Link async. Double check Port %d 0x%04X 0x%04X\n", - Port, IStatus, IStatus2)); - IStatus &= ~XM_IS_INP_ASS; - IStatus |= IStatus2; - } - - if ((IStatus & XM_IS_LNK_AE) != 0) { - /* not used, GP0 is used instead */ - } - - if ((IStatus & XM_IS_TX_ABORT) != 0) { - /* not used */ - } - - if ((IStatus & XM_IS_FRC_INT) != 0) { - /* not used, use ASIC IRQ instead if needed */ - } - - if ((IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) != 0) { - SkHWLinkDown(pAC, IoC, Port); - - /* Signal to RLMT */ - Para.Para32[0] = (SK_U32)Port; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - - /* Start workaround Errata #2 timer */ - SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME, - SKGE_HWAC, SK_HWEV_WATIM, Para); - } - - if ((IStatus & XM_IS_RX_PAGE) != 0) { - /* not used */ - } - - if ((IStatus & XM_IS_TX_PAGE) != 0) { - /* not used */ - } - - if ((IStatus & XM_IS_AND) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("SkXmIrq: AND on link that is up Port %d\n", Port)); - } - - if ((IStatus & XM_IS_TSC_OV) != 0) { - /* not used */ - } - - /* Combined Tx & Rx Counter Overflow SIRQ Event */ - if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) { -#ifdef SK_SLIM - SkXmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus); -#else - Para.Para32[0] = (SK_U32)Port; - Para.Para32[1] = (SK_U32)IStatus; - SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para); -#endif /* SK_SLIM */ - } - - if ((IStatus & XM_IS_RXF_OV) != 0) { - /* normal situation -> no effect */ -#ifdef DEBUG - pPrt->PRxOverCnt++; -#endif /* DEBUG */ - } - - if ((IStatus & XM_IS_TXF_UR) != 0) { - /* may NOT happen -> error log */ - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG); - } - - if ((IStatus & XM_IS_TX_COMP) != 0) { - /* not served here */ - } - - if ((IStatus & XM_IS_RX_COMP) != 0) { - /* not served here */ - } -} /* SkXmIrq */ -#endif /* GENESIS */ - - -#ifdef YUKON -/****************************************************************************** - * - * SkGmIrq() - Interrupt Service Routine - * - * Description: services an Interrupt Request of the GMAC - * - * Note: - * - * Returns: - * nothing - */ -static void SkGmIrq( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U8 IStatus; /* Interrupt status */ -#ifdef SK_SLIM - SK_U64 OverflowStatus; -#else - SK_EVPARA Para; -#endif - - pPrt = &pAC->GIni.GP[Port]; - - SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus); - -#ifdef XXX - /* LinkPartner Auto-negable? */ - SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus); -#endif /* XXX */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("GmacIrq Port %d Isr 0x%04X\n", Port, IStatus)); - - /* Combined Tx & Rx Counter Overflow SIRQ Event */ - if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) { - /* these IRQs will be cleared by reading GMACs register */ -#ifdef SK_SLIM - SkGmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus); -#else - Para.Para32[0] = (SK_U32)Port; - Para.Para32[1] = (SK_U32)IStatus; - SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para); -#endif - } - - if (IStatus & GM_IS_RX_FF_OR) { - /* clear GMAC Rx FIFO Overrun IRQ */ - SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO); -#ifdef DEBUG - pPrt->PRxOverCnt++; -#endif /* DEBUG */ - } - - if (IStatus & GM_IS_TX_FF_UR) { - /* clear GMAC Tx FIFO Underrun IRQ */ - SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FU); - /* may NOT happen -> error log */ - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG); - } - - if (IStatus & GM_IS_TX_COMPL) { - /* not served here */ - } - - if (IStatus & GM_IS_RX_COMPL) { - /* not served here */ - } -} /* SkGmIrq */ -#endif /* YUKON */ - - -/****************************************************************************** - * - * SkMacIrq() - Interrupt Service Routine for MAC - * - * Description: calls the Interrupt Service Routine dep. on board type - * - * Returns: - * nothing - */ -void SkMacIrq( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - /* IRQ from XMAC */ - SkXmIrq(pAC, IoC, Port); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* IRQ from GMAC */ - SkGmIrq(pAC, IoC, Port); - } -#endif /* YUKON */ - -} /* SkMacIrq */ - -#endif /* !SK_DIAG */ - -#ifdef GENESIS -/****************************************************************************** - * - * SkXmUpdateStats() - Force the XMAC to output the current statistic - * - * Description: - * The XMAC holds its statistic internally. To obtain the current - * values a command must be sent so that the statistic data will - * be written to a predefined memory area on the adapter. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkXmUpdateStats( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U16 StatReg; - int WaitIndex; - - pPrt = &pAC->GIni.GP[Port]; - WaitIndex = 0; - - /* Send an update command to XMAC specified */ - XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC); - - /* - * It is an auto-clearing register. If the command bits - * went to zero again, the statistics are transferred. - * Normally the command should be executed immediately. - * But just to be sure we execute a loop. - */ - do { - - XM_IN16(IoC, Port, XM_STAT_CMD, &StatReg); - - if (++WaitIndex > 10) { - - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E021, SKERR_HWI_E021MSG); - - return(1); - } - } while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0); - - return(0); -} /* SkXmUpdateStats */ - - -/****************************************************************************** - * - * SkXmMacStatistic() - Get XMAC counter value - * - * Description: - * Gets the 32bit counter value. Except for the octet counters - * the lower 32bit are counted in hardware and the upper 32bit - * must be counted in software by monitoring counter overflow interrupts. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkXmMacStatistic( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port, /* Port Index (MAC_1 + n) */ -SK_U16 StatAddr, /* MIB counter base address */ -SK_U32 SK_FAR *pVal) /* ptr to return statistic value */ -{ - if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG); - - return(1); - } - - XM_IN32(IoC, Port, StatAddr, pVal); - - return(0); -} /* SkXmMacStatistic */ - - -/****************************************************************************** - * - * SkXmResetCounter() - Clear MAC statistic counter - * - * Description: - * Force the XMAC to clear its statistic counter. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkXmResetCounter( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port) /* Port Index (MAC_1 + n) */ -{ - XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC); - /* Clear two times according to Errata #3 */ - XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC); - - return(0); -} /* SkXmResetCounter */ - - -/****************************************************************************** - * - * SkXmOverflowStatus() - Gets the status of counter overflow interrupt - * - * Description: - * Checks the source causing an counter overflow interrupt. On success the - * resulting counter overflow status is written to <pStatus>, whereas the - * upper dword stores the XMAC ReceiveCounterEvent register and the lower - * dword the XMAC TransmitCounterEvent register. - * - * Note: - * For XMAC the interrupt source is a self-clearing register, so the source - * must be checked only once. SIRQ module does another check to be sure - * that no interrupt get lost during process time. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkXmOverflowStatus( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port, /* Port Index (MAC_1 + n) */ -SK_U16 IStatus, /* Interupt Status from MAC */ -SK_U64 SK_FAR *pStatus) /* ptr for return overflow status value */ -{ - SK_U64 Status; /* Overflow status */ - SK_U32 RegVal; - - Status = 0; - - if ((IStatus & XM_IS_RXC_OV) != 0) { - - XM_IN32(IoC, Port, XM_RX_CNT_EV, &RegVal); - Status |= (SK_U64)RegVal << 32; - } - - if ((IStatus & XM_IS_TXC_OV) != 0) { - - XM_IN32(IoC, Port, XM_TX_CNT_EV, &RegVal); - Status |= (SK_U64)RegVal; - } - - *pStatus = Status; - - return(0); -} /* SkXmOverflowStatus */ -#endif /* GENESIS */ - - -#ifdef YUKON -/****************************************************************************** - * - * SkGmUpdateStats() - Force the GMAC to output the current statistic - * - * Description: - * Empty function for GMAC. Statistic data is accessible in direct way. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkGmUpdateStats( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port) /* Port Index (MAC_1 + n) */ -{ - return(0); -} - - -/****************************************************************************** - * - * SkGmMacStatistic() - Get GMAC counter value - * - * Description: - * Gets the 32bit counter value. Except for the octet counters - * the lower 32bit are counted in hardware and the upper 32bit - * must be counted in software by monitoring counter overflow interrupts. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkGmMacStatistic( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port, /* Port Index (MAC_1 + n) */ -SK_U16 StatAddr, /* MIB counter base address */ -SK_U32 SK_FAR *pVal) /* ptr to return statistic value */ -{ - - if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr)); - return(1); - } - - GM_IN32(IoC, Port, StatAddr, pVal); - - return(0); -} /* SkGmMacStatistic */ - - -/****************************************************************************** - * - * SkGmResetCounter() - Clear MAC statistic counter - * - * Description: - * Force GMAC to clear its statistic counter. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkGmResetCounter( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U16 Reg; /* Phy Address Register */ - SK_U16 Word; - int i; - - GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg); - - /* set MIB Clear Counter Mode */ - GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR); - - /* read all MIB Counters with Clear Mode set */ - for (i = 0; i < GM_MIB_CNT_SIZE; i++) { - /* the reset is performed only when the lower 16 bits are read */ - GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word); - } - - /* clear MIB Clear Counter Mode */ - GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg); - - return(0); -} /* SkGmResetCounter */ - - -/****************************************************************************** - * - * SkGmOverflowStatus() - Gets the status of counter overflow interrupt - * - * Description: - * Checks the source causing an counter overflow interrupt. On success the - * resulting counter overflow status is written to <pStatus>, whereas the - * the following bit coding is used: - * 63:56 - unused - * 55:48 - TxRx interrupt register bit7:0 - * 32:47 - Rx interrupt register - * 31:24 - unused - * 23:16 - TxRx interrupt register bit15:8 - * 15:0 - Tx interrupt register - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkGmOverflowStatus( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port, /* Port Index (MAC_1 + n) */ -SK_U16 IStatus, /* Interupt Status from MAC */ -SK_U64 SK_FAR *pStatus) /* ptr for return overflow status value */ -{ - SK_U64 Status; /* Overflow status */ - SK_U16 RegVal; - - Status = 0; - - if ((IStatus & GM_IS_RX_CO_OV) != 0) { - /* this register is self-clearing after read */ - GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal); - Status |= (SK_U64)RegVal << 32; - } - - if ((IStatus & GM_IS_TX_CO_OV) != 0) { - /* this register is self-clearing after read */ - GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal); - Status |= (SK_U64)RegVal; - } - - /* this register is self-clearing after read */ - GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal); - /* Rx overflow interrupt register bits (LoByte)*/ - Status |= (SK_U64)((SK_U8)RegVal) << 48; - /* Tx overflow interrupt register bits (HiByte)*/ - Status |= (SK_U64)(RegVal >> 8) << 16; - - *pStatus = Status; - - return(0); -} /* SkGmOverflowStatus */ - - -#ifndef SK_SLIM -/****************************************************************************** - * - * SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test - * - * Description: - * starts the cable diagnostic test if 'StartTest' is true - * gets the results if 'StartTest' is true - * - * NOTE: this test is meaningful only when link is down - * - * Returns: - * 0: success - * 1: no YUKON copper - * 2: test in progress - */ -int SkGmCableDiagStatus( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL StartTest) /* flag for start / get result */ -{ - int i; - SK_U16 RegVal; - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PhyType != SK_PHY_MARV_COPPER) { - - return(1); - } - - if (StartTest) { - /* only start the cable test */ - if ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4) { - /* apply TDR workaround from Marvell */ - SkGmPhyWrite(pAC, IoC, Port, 29, 0x001e); - - SkGmPhyWrite(pAC, IoC, Port, 30, 0xcc00); - SkGmPhyWrite(pAC, IoC, Port, 30, 0xc800); - SkGmPhyWrite(pAC, IoC, Port, 30, 0xc400); - SkGmPhyWrite(pAC, IoC, Port, 30, 0xc000); - SkGmPhyWrite(pAC, IoC, Port, 30, 0xc100); - } - - /* set address to 0 for MDI[0] */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0); - - /* Read Cable Diagnostic Reg */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal); - - /* start Cable Diagnostic Test */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, - (SK_U16)(RegVal | PHY_M_CABD_ENA_TEST)); - - return(0); - } - - /* Read Cable Diagnostic Reg */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Cable Diag.=0x%04X\n", RegVal)); - - if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) { - /* test is running */ - return(2); - } - - /* get the test results */ - for (i = 0; i < 4; i++) { - /* set address to i for MDI[i] */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i); - - /* get Cable Diagnostic values */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal); - - pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK); - - pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13); - } - - return(0); -} /* SkGmCableDiagStatus */ -#endif /* !SK_SLIM */ -#endif /* YUKON */ - -/* End of file */ diff --git a/drivers/net/skfp/smt.c b/drivers/net/skfp/smt.c index fe847800acd..75afc1f07ba 100644 --- a/drivers/net/skfp/smt.c +++ b/drivers/net/skfp/smt.c @@ -1748,7 +1748,7 @@ char *addr_to_string(struct fddi_addr *addr) #endif #ifdef AM29K -smt_ifconfig(int argc, char *argv[]) +int smt_ifconfig(int argc, char *argv[]) { if (argc >= 2 && !strcmp(argv[0],"opt_bypass") && !strcmp(argv[1],"yes")) { diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index adfbe81693a..a2f32151559 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -39,6 +39,7 @@ #include <linux/workqueue.h> #include <linux/if_vlan.h> #include <linux/prefetch.h> +#include <linux/debugfs.h> #include <linux/mii.h> #include <asm/irq.h> @@ -50,7 +51,7 @@ #include "sky2.h" #define DRV_NAME "sky2" -#define DRV_VERSION "1.14" +#define DRV_VERSION "1.16" #define PFX DRV_NAME " " /* @@ -64,7 +65,6 @@ #define RX_MAX_PENDING (RX_LE_SIZE/6 - 2) #define RX_DEF_PENDING RX_MAX_PENDING #define RX_SKB_ALIGN 8 -#define RX_BUF_WRITE 16 #define TX_RING_SIZE 512 #define TX_DEF_PENDING (TX_RING_SIZE - 1) @@ -77,6 +77,9 @@ #define NAPI_WEIGHT 64 #define PHY_RETRIES 1000 +#define SKY2_EEPROM_MAGIC 0x9955aabb + + #define RING_NEXT(x,s) (((x)+1) & ((s)-1)) static const u32 default_msg = @@ -96,7 +99,7 @@ static int disable_msi = 0; module_param(disable_msi, int, 0); MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); -static int idle_timeout = 0; +static int idle_timeout = 100; module_param(idle_timeout, int, 0); MODULE_PARM_DESC(idle_timeout, "Watchdog timer for lost interrupts (ms)"); @@ -130,7 +133,7 @@ static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) }, /* 88EC042 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436A) }, /* 88E8058 */ -// { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */ { 0 } }; @@ -217,13 +220,24 @@ static void sky2_power_on(struct sky2_hw *hw) sky2_write8(hw, B2_Y2_CLK_GATE, 0); if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) { - u32 reg1; + u32 reg; - sky2_pci_write32(hw, PCI_DEV_REG3, 0); - reg1 = sky2_pci_read32(hw, PCI_DEV_REG4); - reg1 &= P_ASPM_CONTROL_MSK; - sky2_pci_write32(hw, PCI_DEV_REG4, reg1); - sky2_pci_write32(hw, PCI_DEV_REG5, 0); + reg = sky2_pci_read32(hw, PCI_DEV_REG4); + /* set all bits to 0 except bits 15..12 and 8 */ + reg &= P_ASPM_CONTROL_MSK; + sky2_pci_write32(hw, PCI_DEV_REG4, reg); + + reg = sky2_pci_read32(hw, PCI_DEV_REG5); + /* set all bits to 0 except bits 28 & 27 */ + reg &= P_CTL_TIM_VMAIN_AV_MSK; + sky2_pci_write32(hw, PCI_DEV_REG5, reg); + + sky2_pci_write32(hw, PCI_CFG_REG_1, 0); + + /* Enable workaround for dev 4.107 on Yukon-Ultra & Extreme */ + reg = sky2_read32(hw, B2_GP_IO); + reg |= GLB_GPIO_STAT_RACE_DIS; + sky2_write32(hw, B2_GP_IO, reg); } } @@ -650,6 +664,30 @@ static void sky2_wol_init(struct sky2_port *sky2) } +static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port) +{ + if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev != CHIP_REV_YU_EX_A0) { + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), + TX_STFW_ENA | + (hw->dev[port]->mtu > ETH_DATA_LEN) ? TX_JUMBO_ENA : TX_JUMBO_DIS); + } else { + if (hw->dev[port]->mtu > ETH_DATA_LEN) { + /* set Tx GMAC FIFO Almost Empty Threshold */ + sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR), + (ECU_JUMBO_WM << 16) | ECU_AE_THR); + + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), + TX_JUMBO_ENA | TX_STFW_DIS); + + /* Can't do offload because of lack of store/forward */ + hw->dev[port]->features &= ~(NETIF_F_TSO | NETIF_F_SG + | NETIF_F_ALL_CSUM); + } else + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), + TX_JUMBO_DIS | TX_STFW_ENA); + } +} + static void sky2_mac_init(struct sky2_hw *hw, unsigned port) { struct sky2_port *sky2 = netdev_priv(hw->dev[port]); @@ -730,8 +768,11 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) /* Configure Rx MAC FIFO */ sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR); - sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), - GMF_OPER_ON | GMF_RX_F_FL_ON); + reg = GMF_OPER_ON | GMF_RX_F_FL_ON; + if (hw->chip_id == CHIP_ID_YUKON_EX) + reg |= GMF_RX_OVER_ON; + + sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), reg); /* Flush Rx MAC FIFO on any flow control or error */ sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR); @@ -747,16 +788,7 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8); sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8); - /* set Tx GMAC FIFO Almost Empty Threshold */ - sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR), - (ECU_JUMBO_WM << 16) | ECU_AE_THR); - - if (hw->dev[port]->mtu > ETH_DATA_LEN) - sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), - TX_JUMBO_ENA | TX_STFW_DIS); - else - sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), - TX_JUMBO_DIS | TX_STFW_ENA); + sky2_set_tx_stfwd(hw, port); } } @@ -861,24 +893,18 @@ static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2) return le; } -/* Return high part of DMA address (could be 32 or 64 bit) */ -static inline u32 high32(dma_addr_t a) -{ - return sizeof(a) > sizeof(u32) ? (a >> 16) >> 16 : 0; -} - /* Build description to hardware for one receive segment */ static void sky2_rx_add(struct sky2_port *sky2, u8 op, dma_addr_t map, unsigned len) { struct sky2_rx_le *le; - u32 hi = high32(map); + u32 hi = upper_32_bits(map); if (sky2->rx_addr64 != hi) { le = sky2_next_rx(sky2); le->addr = cpu_to_le32(hi); le->opcode = OP_ADDR64 | HW_OWNER; - sky2->rx_addr64 = high32(map + len); + sky2->rx_addr64 = upper_32_bits(map + len); } le = sky2_next_rx(sky2); @@ -939,14 +965,16 @@ static void rx_set_checksum(struct sky2_port *sky2) { struct sky2_rx_le *le; - le = sky2_next_rx(sky2); - le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN); - le->ctrl = 0; - le->opcode = OP_TCPSTART | HW_OWNER; + if (sky2->hw->chip_id != CHIP_ID_YUKON_EX) { + le = sky2_next_rx(sky2); + le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN); + le->ctrl = 0; + le->opcode = OP_TCPSTART | HW_OWNER; - sky2_write32(sky2->hw, - Q_ADDR(rxqaddr[sky2->port], Q_CSR), - sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); + sky2_write32(sky2->hw, + Q_ADDR(rxqaddr[sky2->port], Q_CSR), + sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); + } } @@ -1049,26 +1077,22 @@ static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp u16 port = sky2->port; netif_tx_lock_bh(dev); + netif_poll_disable(sky2->hw->dev[0]); - sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_ON); - sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_ON); sky2->vlgrp = grp; + if (grp) { + sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), + RX_VLAN_STRIP_ON); + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), + TX_VLAN_TAG_ON); + } else { + sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), + RX_VLAN_STRIP_OFF); + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), + TX_VLAN_TAG_OFF); + } - netif_tx_unlock_bh(dev); -} - -static void sky2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) -{ - struct sky2_port *sky2 = netdev_priv(dev); - struct sky2_hw *hw = sky2->hw; - u16 port = sky2->port; - - netif_tx_lock_bh(dev); - - sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_OFF); - sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_OFF); - vlan_group_set_device(sky2->vlgrp, vid, NULL); - + netif_poll_enable(sky2->hw->dev[0]); netif_tx_unlock_bh(dev); } #endif @@ -1110,6 +1134,11 @@ nomem: return NULL; } +static inline void sky2_rx_update(struct sky2_port *sky2, unsigned rxq) +{ + sky2_put_idx(sky2->hw, rxq, sky2->rx_put); +} + /* * Allocate and setup receiver buffer pool. * Normal case this ends up creating one list element for skb @@ -1138,15 +1167,14 @@ static int sky2_rx_start(struct sky2_port *sky2) if (hw->chip_id == CHIP_ID_YUKON_EC_U && (hw->chip_rev == CHIP_REV_YU_EC_U_A1 || hw->chip_rev == CHIP_REV_YU_EC_U_B0)) - sky2_write32(hw, Q_ADDR(rxq, Q_F), F_M_RX_RAM_DIS); + sky2_write32(hw, Q_ADDR(rxq, Q_TEST), F_M_RX_RAM_DIS); sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1); rx_set_checksum(sky2); /* Space needed for frame data + headers rounded up */ - size = ALIGN(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8) - + 8; + size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8); /* Stopping point for hardware truncation */ thresh = (size - 8) / sizeof(u32); @@ -1201,7 +1229,7 @@ static int sky2_rx_start(struct sky2_port *sky2) } /* Tell chip about available buffers */ - sky2_put_idx(hw, rxq, sky2->rx_put); + sky2_rx_update(sky2, rxq); return 0; nomem: sky2_rx_clean(sky2); @@ -1238,6 +1266,8 @@ static int sky2_up(struct net_device *dev) if (netif_msg_ifup(sky2)) printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); + netif_carrier_off(dev); + /* must be power of 2 */ sky2->tx_le = pci_alloc_consistent(hw->pdev, TX_RING_SIZE * @@ -1289,6 +1319,10 @@ static int sky2_up(struct net_device *dev) sky2_qset(hw, txqaddr[port]); + /* This is copied from sk98lin 10.0.5.3; no one tells me about erratta's */ + if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev == CHIP_REV_YU_EX_B0) + sky2_write32(hw, Q_ADDR(txqaddr[port], Q_TEST), F_TX_CHK_AUTO_OFF); + /* Set almost empty threshold */ if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev == CHIP_REV_YU_EC_U_A0) @@ -1384,27 +1418,30 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) len = skb_headlen(skb); mapping = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); - addr64 = high32(mapping); + addr64 = upper_32_bits(mapping); /* Send high bits if changed or crosses boundary */ - if (addr64 != sky2->tx_addr64 || high32(mapping + len) != sky2->tx_addr64) { + if (addr64 != sky2->tx_addr64 || + upper_32_bits(mapping + len) != sky2->tx_addr64) { le = get_tx_le(sky2); le->addr = cpu_to_le32(addr64); le->opcode = OP_ADDR64 | HW_OWNER; - sky2->tx_addr64 = high32(mapping + len); + sky2->tx_addr64 = upper_32_bits(mapping + len); } /* Check for TCP Segmentation Offload */ mss = skb_shinfo(skb)->gso_size; if (mss != 0) { - mss += tcp_optlen(skb); /* TCP options */ - mss += ip_hdrlen(skb) + sizeof(struct tcphdr); - mss += ETH_HLEN; - - if (mss != sky2->tx_last_mss) { - le = get_tx_le(sky2); - le->addr = cpu_to_le32(mss); - le->opcode = OP_LRGLEN | HW_OWNER; + if (hw->chip_id != CHIP_ID_YUKON_EX) + mss += ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb); + + if (mss != sky2->tx_last_mss) { + le = get_tx_le(sky2); + le->addr = cpu_to_le32(mss); + if (hw->chip_id == CHIP_ID_YUKON_EX) + le->opcode = OP_MSS | HW_OWNER; + else + le->opcode = OP_LRGLEN | HW_OWNER; sky2->tx_last_mss = mss; } } @@ -1426,24 +1463,30 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) /* Handle TCP checksum offload */ if (skb->ip_summed == CHECKSUM_PARTIAL) { - const unsigned offset = skb_transport_offset(skb); - u32 tcpsum; - - tcpsum = offset << 16; /* sum start */ - tcpsum |= offset + skb->csum_offset; /* sum write */ - - ctrl |= CALSUM | WR_SUM | INIT_SUM | LOCK_SUM; - if (ip_hdr(skb)->protocol == IPPROTO_UDP) - ctrl |= UDPTCP; - - if (tcpsum != sky2->tx_tcpsum) { - sky2->tx_tcpsum = tcpsum; - - le = get_tx_le(sky2); - le->addr = cpu_to_le32(tcpsum); - le->length = 0; /* initial checksum value */ - le->ctrl = 1; /* one packet */ - le->opcode = OP_TCPLISW | HW_OWNER; + /* On Yukon EX (some versions) encoding change. */ + if (hw->chip_id == CHIP_ID_YUKON_EX + && hw->chip_rev != CHIP_REV_YU_EX_B0) + ctrl |= CALSUM; /* auto checksum */ + else { + const unsigned offset = skb_transport_offset(skb); + u32 tcpsum; + + tcpsum = offset << 16; /* sum start */ + tcpsum |= offset + skb->csum_offset; /* sum write */ + + ctrl |= CALSUM | WR_SUM | INIT_SUM | LOCK_SUM; + if (ip_hdr(skb)->protocol == IPPROTO_UDP) + ctrl |= UDPTCP; + + if (tcpsum != sky2->tx_tcpsum) { + sky2->tx_tcpsum = tcpsum; + + le = get_tx_le(sky2); + le->addr = cpu_to_le32(tcpsum); + le->length = 0; /* initial checksum value */ + le->ctrl = 1; /* one packet */ + le->opcode = OP_TCPLISW | HW_OWNER; + } } } @@ -1463,7 +1506,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) mapping = pci_map_page(hw->pdev, frag->page, frag->page_offset, frag->size, PCI_DMA_TODEVICE); - addr64 = high32(mapping); + addr64 = upper_32_bits(mapping); if (addr64 != sky2->tx_addr64) { le = get_tx_le(sky2); le->addr = cpu_to_le32(addr64); @@ -1533,13 +1576,13 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) if (unlikely(netif_msg_tx_done(sky2))) printk(KERN_DEBUG "%s: tx done %u\n", dev->name, idx); + sky2->net_stats.tx_packets++; sky2->net_stats.tx_bytes += re->skb->len; dev_kfree_skb_any(re->skb); + sky2->tx_next = RING_NEXT(idx, TX_RING_SIZE); } - - le->opcode = 0; /* paranoia */ } sky2->tx_cons = idx; @@ -1577,7 +1620,6 @@ static int sky2_down(struct net_device *dev) /* Stop more packets from being queued */ netif_stop_queue(dev); - netif_carrier_off(dev); /* Disable port IRQ */ imask = sky2_read32(hw, B0_IMSK); @@ -1629,6 +1671,8 @@ static int sky2_down(struct net_device *dev) sky2_phy_power(hw, port, 0); + netif_carrier_off(dev); + /* turn off LED's */ sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); @@ -1693,7 +1737,6 @@ static void sky2_link_up(struct sky2_port *sky2) gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); netif_carrier_on(sky2->netdev); - netif_wake_queue(sky2->netdev); /* Turn on link LED */ sky2_write8(hw, SK_REG(port, LNK_LED_REG), @@ -1745,7 +1788,6 @@ static void sky2_link_down(struct sky2_port *sky2) gma_write16(hw, port, GM_GP_CTRL, reg); netif_carrier_off(sky2->netdev); - netif_stop_queue(sky2->netdev); /* Turn on link LED */ sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); @@ -1917,15 +1959,8 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) synchronize_irq(hw->pdev->irq); - if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) { - if (new_mtu > ETH_DATA_LEN) { - sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), - TX_JUMBO_ENA | TX_STFW_DIS); - dev->features &= NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM; - } else - sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), - TX_JUMBO_DIS | TX_STFW_ENA); - } + if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) + sky2_set_tx_stfwd(hw, port); ctl = gma_read16(hw, port, GM_GP_CTRL); gma_write16(hw, port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA); @@ -2023,8 +2058,6 @@ static struct sk_buff *receive_new(struct sky2_port *sky2, struct sk_buff *skb, *nskb; unsigned hdr_space = sky2->rx_data_size; - pr_debug(PFX "receive new length=%d\n", length); - /* Don't be tricky about reusing pages (yet) */ nskb = sky2_rx_alloc(sky2); if (unlikely(!nskb)) @@ -2068,6 +2101,9 @@ static struct sk_buff *sky2_receive(struct net_device *dev, if (!(status & GMR_FS_RX_OK)) goto resubmit; + if (status >> 16 != length) + goto len_mismatch; + if (length < copybreak) skb = receive_copy(sky2, re, length); else @@ -2077,6 +2113,11 @@ resubmit: return skb; +len_mismatch: + /* Truncation of overlength packets + causes PHY length to not match MAC length */ + ++sky2->net_stats.rx_length_errors; + error: ++sky2->net_stats.rx_errors; if (status & GMR_FS_RX_FF_OV) { @@ -2113,15 +2154,16 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) /* Process status response ring */ static int sky2_status_intr(struct sky2_hw *hw, int to_do) { - struct sky2_port *sky2; int work_done = 0; - unsigned buf_write[2] = { 0, 0 }; + unsigned rx[2] = { 0, 0 }; u16 hwidx = sky2_read16(hw, STAT_PUT_IDX); rmb(); while (hw->st_idx != hwidx) { + struct sky2_port *sky2; struct sky2_status_le *le = hw->st_le + hw->st_idx; + unsigned port = le->css & CSS_LINK_BIT; struct net_device *dev; struct sk_buff *skb; u32 status; @@ -2129,19 +2171,28 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) hw->st_idx = RING_NEXT(hw->st_idx, STATUS_RING_SIZE); - BUG_ON(le->link >= 2); - dev = hw->dev[le->link]; - + dev = hw->dev[port]; sky2 = netdev_priv(dev); length = le16_to_cpu(le->length); status = le32_to_cpu(le->status); switch (le->opcode & ~HW_OWNER) { case OP_RXSTAT: + ++rx[port]; skb = sky2_receive(dev, length, status); if (unlikely(!skb)) { sky2->net_stats.rx_dropped++; - goto force_update; + break; + } + + /* This chip reports checksum status differently */ + if (hw->chip_id == CHIP_ID_YUKON_EX) { + if (sky2->rx_csum && + (le->css & (CSS_ISIPV4 | CSS_ISIPV6)) && + (le->css & CSS_TCPUDPCSOK)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; } skb->protocol = eth_type_trans(skb, dev); @@ -2158,13 +2209,6 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) #endif netif_receive_skb(skb); - /* Update receiver after 16 frames */ - if (++buf_write[le->link] == RX_BUF_WRITE) { -force_update: - sky2_put_idx(hw, rxqaddr[le->link], sky2->rx_put); - buf_write[le->link] = 0; - } - /* Stop after net poll weight */ if (++work_done >= to_do) goto exit_loop; @@ -2183,6 +2227,9 @@ force_update: if (!sky2->rx_csum) break; + if (hw->chip_id == CHIP_ID_YUKON_EX) + break; + /* Both checksum counters are programmed to start at * the same offset, so unless there is a problem they * should match. This failure is an early indication that @@ -2198,7 +2245,7 @@ force_update: dev->name, status); sky2->rx_csum = 0; sky2_write32(sky2->hw, - Q_ADDR(rxqaddr[le->link], Q_CSR), + Q_ADDR(rxqaddr[port], Q_CSR), BMU_DIS_RX_CHKSUM); } break; @@ -2217,24 +2264,18 @@ force_update: if (net_ratelimit()) printk(KERN_WARNING PFX "unknown status opcode 0x%x\n", le->opcode); - goto exit_loop; } } /* Fully processed status ring so clear irq */ sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); - mmiowb(); exit_loop: - if (buf_write[0]) { - sky2 = netdev_priv(hw->dev[0]); - sky2_put_idx(hw, Q_R1, sky2->rx_put); - } + if (rx[0]) + sky2_rx_update(netdev_priv(hw->dev[0]), Q_R1); - if (buf_write[1]) { - sky2 = netdev_priv(hw->dev[1]); - sky2_put_idx(hw, Q_R2, sky2->rx_put); - } + if (rx[1]) + sky2_rx_update(netdev_priv(hw->dev[1]), Q_R2); return work_done; } @@ -2431,8 +2472,7 @@ static void sky2_err_intr(struct sky2_hw *hw, u32 status) static int sky2_poll(struct net_device *dev0, int *budget) { struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; - int work_limit = min(dev0->quota, *budget); - int work_done = 0; + int work_done; u32 status = sky2_read32(hw, B0_Y2_SP_EISR); if (unlikely(status & Y2_IS_ERROR)) @@ -2444,18 +2484,25 @@ static int sky2_poll(struct net_device *dev0, int *budget) if (status & Y2_IS_IRQ_PHY2) sky2_phy_intr(hw, 1); - work_done = sky2_status_intr(hw, work_limit); - if (work_done < work_limit) { - netif_rx_complete(dev0); + work_done = sky2_status_intr(hw, min(dev0->quota, *budget)); + *budget -= work_done; + dev0->quota -= work_done; - /* end of interrupt, re-enables also acts as I/O synchronization */ - sky2_read32(hw, B0_Y2_SP_LISR); - return 0; - } else { - *budget -= work_done; - dev0->quota -= work_done; + /* More work? */ + if (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX)) return 1; + + /* Bug/Errata workaround? + * Need to kick the TX irq moderation timer. + */ + if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) { + sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); + sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); } + netif_rx_complete(dev0); + + sky2_read32(hw, B0_Y2_SP_LISR); + return 0; } static irqreturn_t sky2_intr(int irq, void *dev_id) @@ -2517,6 +2564,9 @@ static int __devinit sky2_init(struct sky2_hw *hw) { u8 t8; + /* Enable all clocks */ + sky2_pci_write32(hw, PCI_DEV_REG3, 0); + sky2_write8(hw, B0_CTST, CS_RST_CLR); hw->chip_id = sky2_read8(hw, B2_CHIP_ID); @@ -2526,14 +2576,6 @@ static int __devinit sky2_init(struct sky2_hw *hw) return -EOPNOTSUPP; } - if (hw->chip_id == CHIP_ID_YUKON_EX) - dev_warn(&hw->pdev->dev, "this driver not yet tested on this chip type\n" - "Please report success or failure to <netdev@vger.kernel.org>\n"); - - /* Make sure and enable all clocks */ - if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U) - sky2_pci_write32(hw, PCI_DEV_REG3, 0); - hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4; /* This rev is really old, and requires untested workarounds */ @@ -2593,6 +2635,11 @@ static void sky2_reset(struct sky2_hw *hw) for (i = 0; i < hw->ports; i++) { sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET); sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR); + + if (hw->chip_id == CHIP_ID_YUKON_EX) + sky2_write16(hw, SK_REG(i, GMAC_CTRL), + GMC_BYP_MACSECRX_ON | GMC_BYP_MACSECTX_ON + | GMC_BYP_RETR_ON); } sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); @@ -2679,8 +2726,6 @@ static void sky2_restart(struct work_struct *work) struct net_device *dev; int i, err; - dev_dbg(&hw->pdev->dev, "restarting\n"); - del_timer_sync(&hw->idle_timer); rtnl_lock(); @@ -2739,7 +2784,7 @@ static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) sky2->wol = wol->wolopts; - if (hw->chip_id == CHIP_ID_YUKON_EC_U) + if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) sky2_write32(hw, B0_CTST, sky2->wol ? Y2_HW_WOL_ON : Y2_HW_WOL_OFF); @@ -3334,7 +3379,7 @@ static int sky2_get_regs_len(struct net_device *dev) /* * Returns copy of control register region - * Note: access to the RAM address register set will cause timeouts. + * Note: ethtool_get_regs always provides full size (16k) buffer */ static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) @@ -3342,15 +3387,19 @@ static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs, const struct sky2_port *sky2 = netdev_priv(dev); const void __iomem *io = sky2->hw->regs; - BUG_ON(regs->len < B3_RI_WTO_R1); regs->version = 1; memset(p, 0, regs->len); memcpy_fromio(p, io, B3_RAM_ADDR); - memcpy_fromio(p + B3_RI_WTO_R1, - io + B3_RI_WTO_R1, - regs->len - B3_RI_WTO_R1); + /* skip diagnostic ram region */ + memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1, 0x2000 - B3_RI_WTO_R1); + + /* copy GMAC registers */ + memcpy_fromio(p + BASE_GMAC_1, io + BASE_GMAC_1, 0x1000); + if (sky2->hw->ports > 1) + memcpy_fromio(p + BASE_GMAC_2, io + BASE_GMAC_2, 0x1000); + } /* In order to do Jumbo packets on these chips, need to turn off the @@ -3361,9 +3410,7 @@ static int no_tx_offload(struct net_device *dev) const struct sky2_port *sky2 = netdev_priv(dev); const struct sky2_hw *hw = sky2->hw; - return dev->mtu > ETH_DATA_LEN && - (hw->chip_id == CHIP_ID_YUKON_EX - || hw->chip_id == CHIP_ID_YUKON_EC_U); + return dev->mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_EC_U; } static int sky2_set_tx_csum(struct net_device *dev, u32 data) @@ -3383,39 +3430,315 @@ static int sky2_set_tso(struct net_device *dev, u32 data) return ethtool_op_set_tso(dev, data); } +static int sky2_get_eeprom_len(struct net_device *dev) +{ + struct sky2_port *sky2 = netdev_priv(dev); + u16 reg2; + + reg2 = sky2_pci_read32(sky2->hw, PCI_DEV_REG2); + return 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8); +} + +static u32 sky2_vpd_read(struct sky2_hw *hw, int cap, u16 offset) +{ + sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset); + + while (!(sky2_pci_read16(hw, cap + PCI_VPD_ADDR) & PCI_VPD_ADDR_F)) + cpu_relax(); + return sky2_pci_read32(hw, cap + PCI_VPD_DATA); +} + +static void sky2_vpd_write(struct sky2_hw *hw, int cap, u16 offset, u32 val) +{ + sky2_pci_write32(hw, cap + PCI_VPD_DATA, val); + sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset | PCI_VPD_ADDR_F); + do { + cpu_relax(); + } while (sky2_pci_read16(hw, cap + PCI_VPD_ADDR) & PCI_VPD_ADDR_F); +} + +static int sky2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, + u8 *data) +{ + struct sky2_port *sky2 = netdev_priv(dev); + int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD); + int length = eeprom->len; + u16 offset = eeprom->offset; + + if (!cap) + return -EINVAL; + + eeprom->magic = SKY2_EEPROM_MAGIC; + + while (length > 0) { + u32 val = sky2_vpd_read(sky2->hw, cap, offset); + int n = min_t(int, length, sizeof(val)); + + memcpy(data, &val, n); + length -= n; + data += n; + offset += n; + } + return 0; +} + +static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, + u8 *data) +{ + struct sky2_port *sky2 = netdev_priv(dev); + int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD); + int length = eeprom->len; + u16 offset = eeprom->offset; + + if (!cap) + return -EINVAL; + + if (eeprom->magic != SKY2_EEPROM_MAGIC) + return -EINVAL; + + while (length > 0) { + u32 val; + int n = min_t(int, length, sizeof(val)); + + if (n < sizeof(val)) + val = sky2_vpd_read(sky2->hw, cap, offset); + memcpy(&val, data, n); + + sky2_vpd_write(sky2->hw, cap, offset, val); + + length -= n; + data += n; + offset += n; + } + return 0; +} + + static const struct ethtool_ops sky2_ethtool_ops = { - .get_settings = sky2_get_settings, - .set_settings = sky2_set_settings, - .get_drvinfo = sky2_get_drvinfo, - .get_wol = sky2_get_wol, - .set_wol = sky2_set_wol, - .get_msglevel = sky2_get_msglevel, - .set_msglevel = sky2_set_msglevel, - .nway_reset = sky2_nway_reset, - .get_regs_len = sky2_get_regs_len, - .get_regs = sky2_get_regs, - .get_link = ethtool_op_get_link, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = sky2_set_tx_csum, - .get_tso = ethtool_op_get_tso, - .set_tso = sky2_set_tso, - .get_rx_csum = sky2_get_rx_csum, - .set_rx_csum = sky2_set_rx_csum, - .get_strings = sky2_get_strings, - .get_coalesce = sky2_get_coalesce, - .set_coalesce = sky2_set_coalesce, - .get_ringparam = sky2_get_ringparam, - .set_ringparam = sky2_set_ringparam, + .get_settings = sky2_get_settings, + .set_settings = sky2_set_settings, + .get_drvinfo = sky2_get_drvinfo, + .get_wol = sky2_get_wol, + .set_wol = sky2_set_wol, + .get_msglevel = sky2_get_msglevel, + .set_msglevel = sky2_set_msglevel, + .nway_reset = sky2_nway_reset, + .get_regs_len = sky2_get_regs_len, + .get_regs = sky2_get_regs, + .get_link = ethtool_op_get_link, + .get_eeprom_len = sky2_get_eeprom_len, + .get_eeprom = sky2_get_eeprom, + .set_eeprom = sky2_set_eeprom, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = sky2_set_tx_csum, + .get_tso = ethtool_op_get_tso, + .set_tso = sky2_set_tso, + .get_rx_csum = sky2_get_rx_csum, + .set_rx_csum = sky2_set_rx_csum, + .get_strings = sky2_get_strings, + .get_coalesce = sky2_get_coalesce, + .set_coalesce = sky2_set_coalesce, + .get_ringparam = sky2_get_ringparam, + .set_ringparam = sky2_set_ringparam, .get_pauseparam = sky2_get_pauseparam, .set_pauseparam = sky2_set_pauseparam, - .phys_id = sky2_phys_id, + .phys_id = sky2_phys_id, .get_stats_count = sky2_get_stats_count, .get_ethtool_stats = sky2_get_ethtool_stats, .get_perm_addr = ethtool_op_get_perm_addr, }; +#ifdef CONFIG_SKY2_DEBUG + +static struct dentry *sky2_debug; + +static int sky2_debug_show(struct seq_file *seq, void *v) +{ + struct net_device *dev = seq->private; + const struct sky2_port *sky2 = netdev_priv(dev); + const struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; + unsigned idx, last; + int sop; + + if (!netif_running(dev)) + return -ENETDOWN; + + seq_printf(seq, "IRQ src=%x mask=%x control=%x\n", + sky2_read32(hw, B0_ISRC), + sky2_read32(hw, B0_IMSK), + sky2_read32(hw, B0_Y2_SP_ICR)); + + netif_poll_disable(hw->dev[0]); + last = sky2_read16(hw, STAT_PUT_IDX); + + if (hw->st_idx == last) + seq_puts(seq, "Status ring (empty)\n"); + else { + seq_puts(seq, "Status ring\n"); + for (idx = hw->st_idx; idx != last && idx < STATUS_RING_SIZE; + idx = RING_NEXT(idx, STATUS_RING_SIZE)) { + const struct sky2_status_le *le = hw->st_le + idx; + seq_printf(seq, "[%d] %#x %d %#x\n", + idx, le->opcode, le->length, le->status); + } + seq_puts(seq, "\n"); + } + + seq_printf(seq, "Tx ring pending=%u...%u report=%d done=%d\n", + sky2->tx_cons, sky2->tx_prod, + sky2_read16(hw, port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX), + sky2_read16(hw, Q_ADDR(txqaddr[port], Q_DONE))); + + /* Dump contents of tx ring */ + sop = 1; + for (idx = sky2->tx_next; idx != sky2->tx_prod && idx < TX_RING_SIZE; + idx = RING_NEXT(idx, TX_RING_SIZE)) { + const struct sky2_tx_le *le = sky2->tx_le + idx; + u32 a = le32_to_cpu(le->addr); + + if (sop) + seq_printf(seq, "%u:", idx); + sop = 0; + + switch(le->opcode & ~HW_OWNER) { + case OP_ADDR64: + seq_printf(seq, " %#x:", a); + break; + case OP_LRGLEN: + seq_printf(seq, " mtu=%d", a); + break; + case OP_VLAN: + seq_printf(seq, " vlan=%d", be16_to_cpu(le->length)); + break; + case OP_TCPLISW: + seq_printf(seq, " csum=%#x", a); + break; + case OP_LARGESEND: + seq_printf(seq, " tso=%#x(%d)", a, le16_to_cpu(le->length)); + break; + case OP_PACKET: + seq_printf(seq, " %#x(%d)", a, le16_to_cpu(le->length)); + break; + case OP_BUFFER: + seq_printf(seq, " frag=%#x(%d)", a, le16_to_cpu(le->length)); + break; + default: + seq_printf(seq, " op=%#x,%#x(%d)", le->opcode, + a, le16_to_cpu(le->length)); + } + + if (le->ctrl & EOP) { + seq_putc(seq, '\n'); + sop = 1; + } + } + + seq_printf(seq, "\nRx ring hw get=%d put=%d last=%d\n", + sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_GET_IDX)), + last = sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_PUT_IDX)), + sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_LAST_IDX))); + + netif_poll_enable(hw->dev[0]); + return 0; +} + +static int sky2_debug_open(struct inode *inode, struct file *file) +{ + return single_open(file, sky2_debug_show, inode->i_private); +} + +static const struct file_operations sky2_debug_fops = { + .owner = THIS_MODULE, + .open = sky2_debug_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* + * Use network device events to create/remove/rename + * debugfs file entries + */ +static int sky2_device_event(struct notifier_block *unused, + unsigned long event, void *ptr) +{ + struct net_device *dev = ptr; + + if (dev->open == sky2_up) { + struct sky2_port *sky2 = netdev_priv(dev); + + switch(event) { + case NETDEV_CHANGENAME: + if (!netif_running(dev)) + break; + /* fallthrough */ + case NETDEV_DOWN: + case NETDEV_GOING_DOWN: + if (sky2->debugfs) { + printk(KERN_DEBUG PFX "%s: remove debugfs\n", + dev->name); + debugfs_remove(sky2->debugfs); + sky2->debugfs = NULL; + } + + if (event != NETDEV_CHANGENAME) + break; + /* fallthrough for changename */ + case NETDEV_UP: + if (sky2_debug) { + struct dentry *d; + d = debugfs_create_file(dev->name, S_IRUGO, + sky2_debug, dev, + &sky2_debug_fops); + if (d == NULL || IS_ERR(d)) + printk(KERN_INFO PFX + "%s: debugfs create failed\n", + dev->name); + else + sky2->debugfs = d; + } + break; + } + } + + return NOTIFY_DONE; +} + +static struct notifier_block sky2_notifier = { + .notifier_call = sky2_device_event, +}; + + +static __init void sky2_debug_init(void) +{ + struct dentry *ent; + + ent = debugfs_create_dir("sky2", NULL); + if (!ent || IS_ERR(ent)) + return; + + sky2_debug = ent; + register_netdevice_notifier(&sky2_notifier); +} + +static __exit void sky2_debug_cleanup(void) +{ + if (sky2_debug) { + unregister_netdevice_notifier(&sky2_notifier); + debugfs_remove(sky2_debug); + sky2_debug = NULL; + } +} + +#else +#define sky2_debug_init() +#define sky2_debug_cleanup() +#endif + + /* Initialize network device */ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port, @@ -3484,17 +3807,12 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, #ifdef SKY2_VLAN_TAG_USED dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; dev->vlan_rx_register = sky2_vlan_rx_register; - dev->vlan_rx_kill_vid = sky2_vlan_rx_kill_vid; #endif /* read the mac address */ memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN); memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - /* device is off until link detection */ - netif_carrier_off(dev); - netif_stop_queue(dev); - return dev; } @@ -3911,12 +4229,14 @@ static struct pci_driver sky2_driver = { static int __init sky2_init_module(void) { + sky2_debug_init(); return pci_register_driver(&sky2_driver); } static void __exit sky2_cleanup_module(void) { pci_unregister_driver(&sky2_driver); + sky2_debug_cleanup(); } module_init(sky2_init_module); diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index b8c4a3b5ead..dce4d276d44 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -14,6 +14,8 @@ enum { PCI_DEV_REG3 = 0x80, PCI_DEV_REG4 = 0x84, PCI_DEV_REG5 = 0x88, + PCI_CFG_REG_0 = 0x90, + PCI_CFG_REG_1 = 0x94, }; enum { @@ -28,6 +30,7 @@ enum { enum pci_dev_reg_1 { PCI_Y2_PIG_ENA = 1<<31, /* Enable Plug-in-Go (YUKON-2) */ PCI_Y2_DLL_DIS = 1<<30, /* Disable PCI DLL (YUKON-2) */ + PCI_SW_PWR_ON_RST= 1<<30, /* SW Power on Reset (Yukon-EX) */ PCI_Y2_PHY2_COMA = 1<<29, /* Set PHY 2 to Coma Mode (YUKON-2) */ PCI_Y2_PHY1_COMA = 1<<28, /* Set PHY 1 to Coma Mode (YUKON-2) */ PCI_Y2_PHY2_POWD = 1<<27, /* Set PHY 2 to Power Down (YUKON-2) */ @@ -67,6 +70,80 @@ enum pci_dev_reg_4 { | P_ASPM_CLKRUN_REQUEST | P_ASPM_INT_FIFO_EMPTY, }; +/* PCI_OUR_REG_5 32 bit Our Register 5 (Yukon-ECU only) */ +enum pci_dev_reg_5 { + /* Bit 31..27: for A3 & later */ + P_CTL_DIV_CORE_CLK_ENA = 1<<31, /* Divide Core Clock Enable */ + P_CTL_SRESET_VMAIN_AV = 1<<30, /* Soft Reset for Vmain_av De-Glitch */ + P_CTL_BYPASS_VMAIN_AV = 1<<29, /* Bypass En. for Vmain_av De-Glitch */ + P_CTL_TIM_VMAIN_AV_MSK = 3<<27, /* Bit 28..27: Timer Vmain_av Mask */ + /* Bit 26..16: Release Clock on Event */ + P_REL_PCIE_RST_DE_ASS = 1<<26, /* PCIe Reset De-Asserted */ + P_REL_GPHY_REC_PACKET = 1<<25, /* GPHY Received Packet */ + P_REL_INT_FIFO_N_EMPTY = 1<<24, /* Internal FIFO Not Empty */ + P_REL_MAIN_PWR_AVAIL = 1<<23, /* Main Power Available */ + P_REL_CLKRUN_REQ_REL = 1<<22, /* CLKRUN Request Release */ + P_REL_PCIE_RESET_ASS = 1<<21, /* PCIe Reset Asserted */ + P_REL_PME_ASSERTED = 1<<20, /* PME Asserted */ + P_REL_PCIE_EXIT_L1_ST = 1<<19, /* PCIe Exit L1 State */ + P_REL_LOADER_NOT_FIN = 1<<18, /* EPROM Loader Not Finished */ + P_REL_PCIE_RX_EX_IDLE = 1<<17, /* PCIe Rx Exit Electrical Idle State */ + P_REL_GPHY_LINK_UP = 1<<16, /* GPHY Link Up */ + + /* Bit 10.. 0: Mask for Gate Clock */ + P_GAT_PCIE_RST_ASSERTED = 1<<10,/* PCIe Reset Asserted */ + P_GAT_GPHY_N_REC_PACKET = 1<<9, /* GPHY Not Received Packet */ + P_GAT_INT_FIFO_EMPTY = 1<<8, /* Internal FIFO Empty */ + P_GAT_MAIN_PWR_N_AVAIL = 1<<7, /* Main Power Not Available */ + P_GAT_CLKRUN_REQ_REL = 1<<6, /* CLKRUN Not Requested */ + P_GAT_PCIE_RESET_ASS = 1<<5, /* PCIe Reset Asserted */ + P_GAT_PME_DE_ASSERTED = 1<<4, /* PME De-Asserted */ + P_GAT_PCIE_ENTER_L1_ST = 1<<3, /* PCIe Enter L1 State */ + P_GAT_LOADER_FINISHED = 1<<2, /* EPROM Loader Finished */ + P_GAT_PCIE_RX_EL_IDLE = 1<<1, /* PCIe Rx Electrical Idle State */ + P_GAT_GPHY_LINK_DOWN = 1<<0, /* GPHY Link Down */ + + PCIE_OUR5_EVENT_CLK_D3_SET = P_REL_GPHY_REC_PACKET | + P_REL_INT_FIFO_N_EMPTY | + P_REL_PCIE_EXIT_L1_ST | + P_REL_PCIE_RX_EX_IDLE | + P_GAT_GPHY_N_REC_PACKET | + P_GAT_INT_FIFO_EMPTY | + P_GAT_PCIE_ENTER_L1_ST | + P_GAT_PCIE_RX_EL_IDLE, +}; + +#/* PCI_CFG_REG_1 32 bit Config Register 1 (Yukon-Ext only) */ +enum pci_cfg_reg1 { + P_CF1_DIS_REL_EVT_RST = 1<<24, /* Dis. Rel. Event during PCIE reset */ + /* Bit 23..21: Release Clock on Event */ + P_CF1_REL_LDR_NOT_FIN = 1<<23, /* EEPROM Loader Not Finished */ + P_CF1_REL_VMAIN_AVLBL = 1<<22, /* Vmain available */ + P_CF1_REL_PCIE_RESET = 1<<21, /* PCI-E reset */ + /* Bit 20..18: Gate Clock on Event */ + P_CF1_GAT_LDR_NOT_FIN = 1<<20, /* EEPROM Loader Finished */ + P_CF1_GAT_PCIE_RX_IDLE = 1<<19, /* PCI-E Rx Electrical idle */ + P_CF1_GAT_PCIE_RESET = 1<<18, /* PCI-E Reset */ + P_CF1_PRST_PHY_CLKREQ = 1<<17, /* Enable PCI-E rst & PM2PHY gen. CLKREQ */ + P_CF1_PCIE_RST_CLKREQ = 1<<16, /* Enable PCI-E rst generate CLKREQ */ + + P_CF1_ENA_CFG_LDR_DONE = 1<<8, /* Enable core level Config loader done */ + + P_CF1_ENA_TXBMU_RD_IDLE = 1<<1, /* Enable TX BMU Read IDLE for ASPM */ + P_CF1_ENA_TXBMU_WR_IDLE = 1<<0, /* Enable TX BMU Write IDLE for ASPM */ + + PCIE_CFG1_EVENT_CLK_D3_SET = P_CF1_DIS_REL_EVT_RST | + P_CF1_REL_LDR_NOT_FIN | + P_CF1_REL_VMAIN_AVLBL | + P_CF1_REL_PCIE_RESET | + P_CF1_GAT_LDR_NOT_FIN | + P_CF1_GAT_PCIE_RESET | + P_CF1_PRST_PHY_CLKREQ | + P_CF1_ENA_CFG_LDR_DONE | + P_CF1_ENA_TXBMU_RD_IDLE | + P_CF1_ENA_TXBMU_WR_IDLE, +}; + #define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \ PCI_STATUS_SIG_SYSTEM_ERROR | \ @@ -364,6 +441,20 @@ enum { TST_CFG_WRITE_OFF= 1<<0, /* Disable Config Reg WR */ }; +/* B2_GPIO */ +enum { + GLB_GPIO_CLK_DEB_ENA = 1<<31, /* Clock Debug Enable */ + GLB_GPIO_CLK_DBG_MSK = 0xf<<26, /* Clock Debug */ + + GLB_GPIO_INT_RST_D3_DIS = 1<<15, /* Disable Internal Reset After D3 to D0 */ + GLB_GPIO_LED_PAD_SPEED_UP = 1<<14, /* LED PAD Speed Up */ + GLB_GPIO_STAT_RACE_DIS = 1<<13, /* Status Race Disable */ + GLB_GPIO_TEST_SEL_MSK = 3<<11, /* Testmode Select */ + GLB_GPIO_TEST_SEL_BASE = 1<<11, + GLB_GPIO_RAND_ENA = 1<<10, /* Random Enable */ + GLB_GPIO_RAND_BIT_1 = 1<<9, /* Random Bit 1 */ +}; + /* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */ enum { CFG_CHIP_R_MSK = 0xf<<4, /* Bit 7.. 4: Chip Revision */ @@ -392,6 +483,11 @@ enum { CHIP_REV_YU_FE_A2 = 2, }; +enum yukon_ex_rev { + CHIP_REV_YU_EX_A0 = 1, + CHIP_REV_YU_EX_B0 = 2, +}; + /* B2_Y2_CLK_GATE 8 bit Clock Gating (Yukon-2 only) */ enum { @@ -515,23 +611,15 @@ enum { enum { B8_Q_REGS = 0x0400, /* base of Queue registers */ Q_D = 0x00, /* 8*32 bit Current Descriptor */ - Q_DA_L = 0x20, /* 32 bit Current Descriptor Address Low dWord */ - Q_DA_H = 0x24, /* 32 bit Current Descriptor Address High dWord */ + Q_VLAN = 0x20, /* 16 bit Current VLAN Tag */ + Q_DONE = 0x24, /* 16 bit Done Index */ Q_AC_L = 0x28, /* 32 bit Current Address Counter Low dWord */ Q_AC_H = 0x2c, /* 32 bit Current Address Counter High dWord */ Q_BC = 0x30, /* 32 bit Current Byte Counter */ Q_CSR = 0x34, /* 32 bit BMU Control/Status Register */ - Q_F = 0x38, /* 32 bit Flag Register */ - Q_T1 = 0x3c, /* 32 bit Test Register 1 */ - Q_T1_TR = 0x3c, /* 8 bit Test Register 1 Transfer SM */ - Q_T1_WR = 0x3d, /* 8 bit Test Register 1 Write Descriptor SM */ - Q_T1_RD = 0x3e, /* 8 bit Test Register 1 Read Descriptor SM */ - Q_T1_SV = 0x3f, /* 8 bit Test Register 1 Supervisor SM */ - Q_T2 = 0x40, /* 32 bit Test Register 2 */ - Q_T3 = 0x44, /* 32 bit Test Register 3 */ + Q_TEST = 0x38, /* 32 bit Test/Control Register */ /* Yukon-2 */ - Q_DONE = 0x24, /* 16 bit Done Index (Yukon-2 only) */ Q_WM = 0x40, /* 16 bit FIFO Watermark */ Q_AL = 0x42, /* 8 bit FIFO Alignment */ Q_RSP = 0x44, /* 16 bit FIFO Read Shadow Pointer */ @@ -545,15 +633,16 @@ enum { }; #define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs)) -/* Q_F 32 bit Flag Register */ +/* Q_TEST 32 bit Test Register */ enum { - F_ALM_FULL = 1<<27, /* Rx FIFO: almost full */ - F_EMPTY = 1<<27, /* Tx FIFO: empty flag */ - F_FIFO_EOF = 1<<26, /* Tag (EOF Flag) bit in FIFO */ - F_WM_REACHED = 1<<25, /* Watermark reached */ + /* Transmit */ + F_TX_CHK_AUTO_OFF = 1<<31, /* Tx checksum auto calc off (Yukon EX) */ + F_TX_CHK_AUTO_ON = 1<<30, /* Tx checksum auto calc off (Yukon EX) */ + + /* Receive */ F_M_RX_RAM_DIS = 1<<24, /* MAC Rx RAM Read Port disable */ - F_FIFO_LEVEL = 0x1fL<<16, /* Bit 23..16: # of Qwords in FIFO */ - F_WATER_MARK = 0x0007ffL, /* Bit 10.. 0: Watermark */ + + /* Hardware testbits not used */ }; /* Queue Prefetch Unit Offsets, use Y2_QADDR() to address (Yukon-2 only)*/ @@ -1608,6 +1697,16 @@ enum { RX_VLAN_STRIP_ON = 1<<25, /* enable VLAN stripping */ RX_VLAN_STRIP_OFF = 1<<24, /* disable VLAN stripping */ + RX_MACSEC_FLUSH_ON = 1<<23, + RX_MACSEC_FLUSH_OFF = 1<<22, + RX_MACSEC_ASF_FLUSH_ON = 1<<21, + RX_MACSEC_ASF_FLUSH_OFF = 1<<20, + + GMF_RX_OVER_ON = 1<<19, /* enable flushing on receive overrun */ + GMF_RX_OVER_OFF = 1<<18, /* disable flushing on receive overrun */ + GMF_ASF_RX_OVER_ON = 1<<17, /* enable flushing of ASF when overrun */ + GMF_ASF_RX_OVER_OFF = 1<<16, /* disable flushing of ASF when overrun */ + GMF_WP_TST_ON = 1<<14, /* Write Pointer Test On */ GMF_WP_TST_OFF = 1<<13, /* Write Pointer Test Off */ GMF_WP_STEP = 1<<12, /* Write Pointer Step/Increment */ @@ -1720,6 +1819,15 @@ enum { /* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */ enum { + GMC_SET_RST = 1<<15,/* MAC SEC RST */ + GMC_SEC_RST_OFF = 1<<14,/* MAC SEC RSt OFF */ + GMC_BYP_MACSECRX_ON = 1<<13,/* Bypass macsec RX */ + GMC_BYP_MACSECRX_OFF= 1<<12,/* Bypass macsec RX off */ + GMC_BYP_MACSECTX_ON = 1<<11,/* Bypass macsec TX */ + GMC_BYP_MACSECTX_OFF= 1<<10,/* Bypass macsec TX off*/ + GMC_BYP_RETR_ON = 1<<9, /* Bypass retransmit FIFO On */ + GMC_BYP_RETR_OFF= 1<<8, /* Bypass retransmit FIFO Off */ + GMC_H_BURST_ON = 1<<7, /* Half Duplex Burst Mode On */ GMC_H_BURST_OFF = 1<<6, /* Half Duplex Burst Mode Off */ GMC_F_LOOPB_ON = 1<<5, /* FIFO Loopback On */ @@ -1805,9 +1913,13 @@ enum { OP_ADDR64VLAN = OP_ADDR64 | OP_VLAN, OP_LRGLEN = 0x24, OP_LRGLENVLAN = OP_LRGLEN | OP_VLAN, + OP_MSS = 0x28, + OP_MSSVLAN = OP_MSS | OP_VLAN, + OP_BUFFER = 0x40, OP_PACKET = 0x41, OP_LARGESEND = 0x43, + OP_LSOV2 = 0x45, /* YUKON-2 STATUS opcodes defines */ OP_RXSTAT = 0x60, @@ -1818,6 +1930,19 @@ enum { OP_RXTIMEVLAN = OP_RXTIMESTAMP | OP_RXVLAN, OP_RSS_HASH = 0x65, OP_TXINDEXLE = 0x68, + OP_MACSEC = 0x6c, + OP_PUTIDX = 0x70, +}; + +enum status_css { + CSS_TCPUDPCSOK = 1<<7, /* TCP / UDP checksum is ok */ + CSS_ISUDP = 1<<6, /* packet is a UDP packet */ + CSS_ISTCP = 1<<5, /* packet is a TCP packet */ + CSS_ISIPFRAG = 1<<4, /* packet is a TCP/UDP frag, CS calc not done */ + CSS_ISIPV6 = 1<<3, /* packet is a IPv6 packet */ + CSS_IPV4CSUMOK = 1<<2, /* IP v4: TCP header checksum is ok */ + CSS_ISIPV4 = 1<<1, /* packet is a IPv4 packet */ + CSS_LINK_BIT = 1<<0, /* port number (legacy) */ }; /* Yukon 2 hardware interface */ @@ -1838,7 +1963,7 @@ struct sky2_rx_le { struct sky2_status_le { __le32 status; /* also checksum */ __le16 length; /* also vlan tag */ - u8 link; + u8 css; u8 opcode; } __attribute((packed)); @@ -1873,6 +1998,7 @@ struct sky2_port { struct sky2_tx_le *tx_le; u16 tx_cons; /* next le to check */ u16 tx_prod; /* next le to use */ + u16 tx_next; /* debug only */ u32 tx_addr64; u16 tx_pending; u16 tx_last_mss; @@ -1903,6 +2029,9 @@ struct sky2_port { enum flow_control flow_mode; enum flow_control flow_status; +#ifdef CONFIG_SKY2_DEBUG + struct dentry *debugfs; +#endif struct net_device_stats net_stats; }; diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 111f23d0576..f8429449dc1 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -58,6 +58,8 @@ #elif defined(CONFIG_BFIN) #define SMC_IRQ_FLAGS IRQF_TRIGGER_HIGH +#define RPC_LSA_DEFAULT RPC_LED_100_10 +#define RPC_LSB_DEFAULT RPC_LED_TX_RX # if defined (CONFIG_BFIN561_EZKIT) #define SMC_CAN_USE_8BIT 0 @@ -281,17 +283,14 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg) #elif defined(CONFIG_SUPERH) -#if defined(CONFIG_SH_7780_SOLUTION_ENGINE) || defined(CONFIG_SH_7722_SOLUTION_ENGINE) +#ifdef CONFIG_SOLUTION_ENGINE #define SMC_CAN_USE_8BIT 0 #define SMC_CAN_USE_16BIT 1 #define SMC_CAN_USE_32BIT 0 #define SMC_IO_SHIFT 0 #define SMC_NOWAIT 1 -#define SMC_inb(a, r) (inw((a) + ((r)&~1)) >> (8*(r%2)))&0xff #define SMC_inw(a, r) inw((a) + (r)) -#define SMC_outb(v, a, r) outw(((inw((a)+((r)&~1))*(0xff<<8*(r%2)))) | ((v)<<(8*(r&2)))), (a) + ((r)&~1)) - #define SMC_outw(v, a, r) outw(v, (a) + (r)) #define SMC_insw(a, r, p, l) insw((a) + (r), p, l) #define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l) diff --git a/drivers/net/sni_82596.c b/drivers/net/sni_82596.c new file mode 100644 index 00000000000..2cf6794acb4 --- /dev/null +++ b/drivers/net/sni_82596.c @@ -0,0 +1,185 @@ +/* + * sni_82596.c -- driver for intel 82596 ethernet controller, as + * used in older SNI RM machines + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/errno.h> +#include <linux/ioport.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/skbuff.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/bitops.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/irq.h> + +#define SNI_82596_DRIVER_VERSION "SNI RM 82596 driver - Revision: 0.01" + +static const char sni_82596_string[] = "snirm_82596"; + +#define DMA_ALLOC dma_alloc_coherent +#define DMA_FREE dma_free_coherent +#define DMA_WBACK(priv, addr, len) do { } while (0) +#define DMA_INV(priv, addr, len) do { } while (0) +#define DMA_WBACK_INV(priv, addr, len) do { } while (0) + +#define SYSBUS 0x00004400 + +/* big endian CPU, 82596 little endian */ +#define SWAP32(x) cpu_to_le32((u32)(x)) +#define SWAP16(x) cpu_to_le16((u16)(x)) + +#define OPT_MPU_16BIT 0x01 + +#include "lib82596.c" + +MODULE_AUTHOR("Thomas Bogendoerfer"); +MODULE_DESCRIPTION("i82596 driver"); +MODULE_LICENSE("GPL"); +module_param(i596_debug, int, 0); +MODULE_PARM_DESC(i596_debug, "82596 debug mask"); + +static inline void ca(struct net_device *dev) +{ + struct i596_private *lp = netdev_priv(dev); + + writel(0, lp->ca); +} + + +static void mpu_port(struct net_device *dev, int c, dma_addr_t x) +{ + struct i596_private *lp = netdev_priv(dev); + + u32 v = (u32) (c) | (u32) (x); + + if (lp->options & OPT_MPU_16BIT) { + writew(v & 0xffff, lp->mpu_port); + wmb(); /* order writes to MPU port */ + udelay(1); + writew(v >> 16, lp->mpu_port); + } else { + writel(v, lp->mpu_port); + wmb(); /* order writes to MPU port */ + udelay(1); + writel(v, lp->mpu_port); + } +} + + +static int __devinit sni_82596_probe(struct platform_device *dev) +{ + struct net_device *netdevice; + struct i596_private *lp; + struct resource *res, *ca, *idprom, *options; + int retval = -ENOMEM; + void __iomem *mpu_addr; + void __iomem *ca_addr; + u8 __iomem *eth_addr; + + res = platform_get_resource(dev, IORESOURCE_MEM, 0); + ca = platform_get_resource(dev, IORESOURCE_MEM, 1); + options = platform_get_resource(dev, 0, 0); + idprom = platform_get_resource(dev, IORESOURCE_MEM, 2); + if (!res || !ca || !options || !idprom) + return -ENODEV; + mpu_addr = ioremap_nocache(res->start, 4); + if (!mpu_addr) + return -ENOMEM; + ca_addr = ioremap_nocache(ca->start, 4); + if (!ca_addr) + goto probe_failed_free_mpu; + + printk(KERN_INFO "Found i82596 at 0x%x\n", res->start); + + netdevice = alloc_etherdev(sizeof(struct i596_private)); + if (!netdevice) + goto probe_failed_free_ca; + + SET_NETDEV_DEV(netdevice, &dev->dev); + platform_set_drvdata (dev, netdevice); + + netdevice->base_addr = res->start; + netdevice->irq = platform_get_irq(dev, 0); + + eth_addr = ioremap_nocache(idprom->start, 0x10); + if (!eth_addr) + goto probe_failed; + + /* someone seems to like messed up stuff */ + netdevice->dev_addr[0] = readb(eth_addr + 0x0b); + netdevice->dev_addr[1] = readb(eth_addr + 0x0a); + netdevice->dev_addr[2] = readb(eth_addr + 0x09); + netdevice->dev_addr[3] = readb(eth_addr + 0x08); + netdevice->dev_addr[4] = readb(eth_addr + 0x07); + netdevice->dev_addr[5] = readb(eth_addr + 0x06); + iounmap(eth_addr); + + if (!netdevice->irq) { + printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n", + __FILE__, netdevice->base_addr); + goto probe_failed; + } + + lp = netdev_priv(netdevice); + lp->options = options->flags & IORESOURCE_BITS; + lp->ca = ca_addr; + lp->mpu_port = mpu_addr; + + retval = i82596_probe(netdevice); + if (retval == 0) + return 0; + +probe_failed: + free_netdev(netdevice); +probe_failed_free_ca: + iounmap(ca_addr); +probe_failed_free_mpu: + iounmap(mpu_addr); + return retval; +} + +static int __devexit sni_82596_driver_remove(struct platform_device *pdev) +{ + struct net_device *dev = platform_get_drvdata(pdev); + struct i596_private *lp = netdev_priv(dev); + + unregister_netdev(dev); + DMA_FREE(dev->dev.parent, sizeof(struct i596_private), + lp->dma, lp->dma_addr); + iounmap(lp->ca); + iounmap(lp->mpu_port); + free_netdev (dev); + return 0; +} + +static struct platform_driver sni_82596_driver = { + .probe = sni_82596_probe, + .remove = __devexit_p(sni_82596_driver_remove), + .driver = { + .name = sni_82596_string, + }, +}; + +static int __devinit sni_82596_init(void) +{ + printk(KERN_INFO SNI_82596_DRIVER_VERSION "\n"); + return platform_driver_register(&sni_82596_driver); +} + + +static void __exit sni_82596_exit(void) +{ + platform_driver_unregister(&sni_82596_driver); +} + +module_init(sni_82596_init); +module_exit(sni_82596_exit); diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index ef84d7c757a..590b12c7246 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -434,7 +434,8 @@ spider_net_prepare_rx_descr(struct spider_net_card *card, bufsize + SPIDER_NET_RXBUF_ALIGN - 1); if (!descr->skb) { if (netif_msg_rx_err(card) && net_ratelimit()) - pr_err("Not enough memory to allocate rx buffer\n"); + dev_err(&card->netdev->dev, + "Not enough memory to allocate rx buffer\n"); card->spider_stats.alloc_rx_skb_error++; return -ENOMEM; } @@ -455,18 +456,14 @@ spider_net_prepare_rx_descr(struct spider_net_card *card, dev_kfree_skb_any(descr->skb); descr->skb = NULL; if (netif_msg_rx_err(card) && net_ratelimit()) - pr_err("Could not iommu-map rx buffer\n"); + dev_err(&card->netdev->dev, "Could not iommu-map rx buffer\n"); card->spider_stats.rx_iommu_map_error++; hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE; } else { hwdescr->buf_addr = buf; - hwdescr->next_descr_addr = 0; wmb(); hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_NOINTR_COMPLETE; - - wmb(); - descr->prev->hwdescr->next_descr_addr = descr->bus_addr; } return 0; @@ -504,6 +501,20 @@ spider_net_enable_rxdmac(struct spider_net_card *card) } /** + * spider_net_disable_rxdmac - disables the receive DMA controller + * @card: card structure + * + * spider_net_disable_rxdmac terminates processing on the DMA controller + * by turing off the DMA controller, with the force-end flag set. + */ +static inline void +spider_net_disable_rxdmac(struct spider_net_card *card) +{ + spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR, + SPIDER_NET_DMA_RX_FEND_VALUE); +} + +/** * spider_net_refill_rx_chain - refills descriptors/skbs in the rx chains * @card: card structure * @@ -541,12 +552,16 @@ spider_net_refill_rx_chain(struct spider_net_card *card) static int spider_net_alloc_rx_skbs(struct spider_net_card *card) { - int result; - struct spider_net_descr_chain *chain; + struct spider_net_descr_chain *chain = &card->rx_chain; + struct spider_net_descr *start = chain->tail; + struct spider_net_descr *descr = start; - result = -ENOMEM; + /* Link up the hardware chain pointers */ + do { + descr->prev->hwdescr->next_descr_addr = descr->bus_addr; + descr = descr->next; + } while (descr != start); - chain = &card->rx_chain; /* Put at least one buffer into the chain. if this fails, * we've got a problem. If not, spider_net_refill_rx_chain * will do the rest at the end of this function. */ @@ -563,7 +578,7 @@ spider_net_alloc_rx_skbs(struct spider_net_card *card) error: spider_net_free_rx_chain_contents(card); - return result; + return -ENOMEM; } /** @@ -655,20 +670,6 @@ write_hash: } /** - * spider_net_disable_rxdmac - disables the receive DMA controller - * @card: card structure - * - * spider_net_disable_rxdmac terminates processing on the DMA controller by - * turing off DMA and issueing a force end - */ -static void -spider_net_disable_rxdmac(struct spider_net_card *card) -{ - spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR, - SPIDER_NET_DMA_RX_FEND_VALUE); -} - -/** * spider_net_prepare_tx_descr - fill tx descriptor with skb data * @card: card structure * @descr: descriptor structure to fill out @@ -692,7 +693,7 @@ spider_net_prepare_tx_descr(struct spider_net_card *card, buf = pci_map_single(card->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); if (pci_dma_mapping_error(buf)) { if (netif_msg_tx_err(card) && net_ratelimit()) - pr_err("could not iommu-map packet (%p, %i). " + dev_err(&card->netdev->dev, "could not iommu-map packet (%p, %i). " "Dropping packet\n", skb->data, skb->len); card->spider_stats.tx_iommu_map_error++; return -ENOMEM; @@ -715,10 +716,10 @@ spider_net_prepare_tx_descr(struct spider_net_card *card, hwdescr->data_status = 0; hwdescr->dmac_cmd_status = - SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_NOCS; + SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_TXFRMTL; spin_unlock_irqrestore(&chain->lock, flags); - if (skb->protocol == htons(ETH_P_IP) && skb->ip_summed == CHECKSUM_PARTIAL) + if (skb->ip_summed == CHECKSUM_PARTIAL) switch (ip_hdr(skb)->protocol) { case IPPROTO_TCP: hwdescr->dmac_cmd_status |= SPIDER_NET_DMAC_TCP; @@ -832,9 +833,8 @@ spider_net_release_tx_chain(struct spider_net_card *card, int brutal) case SPIDER_NET_DESCR_PROTECTION_ERROR: case SPIDER_NET_DESCR_FORCE_END: if (netif_msg_tx_err(card)) - pr_err("%s: forcing end of tx descriptor " - "with status x%02x\n", - card->netdev->name, status); + dev_err(&card->netdev->dev, "forcing end of tx descriptor " + "with status x%02x\n", status); card->netdev_stats.tx_errors++; break; @@ -1022,34 +1022,154 @@ spider_net_pass_skb_up(struct spider_net_descr *descr, netif_receive_skb(skb); } -#ifdef DEBUG static void show_rx_chain(struct spider_net_card *card) { struct spider_net_descr_chain *chain = &card->rx_chain; struct spider_net_descr *start= chain->tail; struct spider_net_descr *descr= start; + struct spider_net_hw_descr *hwd = start->hwdescr; + struct device *dev = &card->netdev->dev; + u32 curr_desc, next_desc; int status; + int tot = 0; int cnt = 0; - int cstat = spider_net_get_descr_status(descr); - printk(KERN_INFO "RX chain tail at descr=%ld\n", - (start - card->descr) - card->tx_chain.num_desc); + int off = start - chain->ring; + int cstat = hwd->dmac_cmd_status; + + dev_info(dev, "Total number of descrs=%d\n", + chain->num_desc); + dev_info(dev, "Chain tail located at descr=%d, status=0x%x\n", + off, cstat); + + curr_desc = spider_net_read_reg(card, SPIDER_NET_GDACTDPA); + next_desc = spider_net_read_reg(card, SPIDER_NET_GDACNEXTDA); + status = cstat; do { - status = spider_net_get_descr_status(descr); + hwd = descr->hwdescr; + off = descr - chain->ring; + status = hwd->dmac_cmd_status; + + if (descr == chain->head) + dev_info(dev, "Chain head is at %d, head status=0x%x\n", + off, status); + + if (curr_desc == descr->bus_addr) + dev_info(dev, "HW curr desc (GDACTDPA) is at %d, status=0x%x\n", + off, status); + + if (next_desc == descr->bus_addr) + dev_info(dev, "HW next desc (GDACNEXTDA) is at %d, status=0x%x\n", + off, status); + + if (hwd->next_descr_addr == 0) + dev_info(dev, "chain is cut at %d\n", off); + if (cstat != status) { - printk(KERN_INFO "Have %d descrs with stat=x%08x\n", cnt, cstat); + int from = (chain->num_desc + off - cnt) % chain->num_desc; + int to = (chain->num_desc + off - 1) % chain->num_desc; + dev_info(dev, "Have %d (from %d to %d) descrs " + "with stat=0x%08x\n", cnt, from, to, cstat); cstat = status; cnt = 0; } + cnt ++; + tot ++; + descr = descr->next; + } while (descr != start); + + dev_info(dev, "Last %d descrs with stat=0x%08x " + "for a total of %d descrs\n", cnt, cstat, tot); + +#ifdef DEBUG + /* Now dump the whole ring */ + descr = start; + do + { + struct spider_net_hw_descr *hwd = descr->hwdescr; + status = spider_net_get_descr_status(hwd); + cnt = descr - chain->ring; + dev_info(dev, "Descr %d stat=0x%08x skb=%p\n", + cnt, status, descr->skb); + dev_info(dev, "bus addr=%08x buf addr=%08x sz=%d\n", + descr->bus_addr, hwd->buf_addr, hwd->buf_size); + dev_info(dev, "next=%08x result sz=%d valid sz=%d\n", + hwd->next_descr_addr, hwd->result_size, + hwd->valid_size); + dev_info(dev, "dmac=%08x data stat=%08x data err=%08x\n", + hwd->dmac_cmd_status, hwd->data_status, + hwd->data_error); + dev_info(dev, "\n"); + descr = descr->next; } while (descr != start); - printk(KERN_INFO "Last %d descrs with stat=x%08x\n", cnt, cstat); -} #endif +} + +/** + * spider_net_resync_head_ptr - Advance head ptr past empty descrs + * + * If the driver fails to keep up and empty the queue, then the + * hardware wil run out of room to put incoming packets. This + * will cause the hardware to skip descrs that are full (instead + * of halting/retrying). Thus, once the driver runs, it wil need + * to "catch up" to where the hardware chain pointer is at. + */ +static void spider_net_resync_head_ptr(struct spider_net_card *card) +{ + unsigned long flags; + struct spider_net_descr_chain *chain = &card->rx_chain; + struct spider_net_descr *descr; + int i, status; + + /* Advance head pointer past any empty descrs */ + descr = chain->head; + status = spider_net_get_descr_status(descr->hwdescr); + + if (status == SPIDER_NET_DESCR_NOT_IN_USE) + return; + + spin_lock_irqsave(&chain->lock, flags); + + descr = chain->head; + status = spider_net_get_descr_status(descr->hwdescr); + for (i=0; i<chain->num_desc; i++) { + if (status != SPIDER_NET_DESCR_CARDOWNED) break; + descr = descr->next; + status = spider_net_get_descr_status(descr->hwdescr); + } + chain->head = descr; + + spin_unlock_irqrestore(&chain->lock, flags); +} + +static int spider_net_resync_tail_ptr(struct spider_net_card *card) +{ + struct spider_net_descr_chain *chain = &card->rx_chain; + struct spider_net_descr *descr; + int i, status; + + /* Advance tail pointer past any empty and reaped descrs */ + descr = chain->tail; + status = spider_net_get_descr_status(descr->hwdescr); + + for (i=0; i<chain->num_desc; i++) { + if ((status != SPIDER_NET_DESCR_CARDOWNED) && + (status != SPIDER_NET_DESCR_NOT_IN_USE)) break; + descr = descr->next; + status = spider_net_get_descr_status(descr->hwdescr); + } + chain->tail = descr; + + if ((i == chain->num_desc) || (i == 0)) + return 1; + return 0; +} + /** * spider_net_decode_one_descr - processes an RX descriptor * @card: card structure @@ -1067,6 +1187,7 @@ spider_net_decode_one_descr(struct spider_net_card *card) struct spider_net_descr_chain *chain = &card->rx_chain; struct spider_net_descr *descr = chain->tail; struct spider_net_hw_descr *hwdescr = descr->hwdescr; + u32 hw_buf_addr; int status; status = spider_net_get_descr_status(hwdescr); @@ -1080,15 +1201,17 @@ spider_net_decode_one_descr(struct spider_net_card *card) chain->tail = descr->next; /* unmap descriptor */ - pci_unmap_single(card->pdev, hwdescr->buf_addr, + hw_buf_addr = hwdescr->buf_addr; + hwdescr->buf_addr = 0xffffffff; + pci_unmap_single(card->pdev, hw_buf_addr, SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE); if ( (status == SPIDER_NET_DESCR_RESPONSE_ERROR) || (status == SPIDER_NET_DESCR_PROTECTION_ERROR) || (status == SPIDER_NET_DESCR_FORCE_END) ) { if (netif_msg_rx_err(card)) - pr_err("%s: dropping RX descriptor with state %d\n", - card->netdev->name, status); + dev_err(&card->netdev->dev, + "dropping RX descriptor with state %d\n", status); card->netdev_stats.rx_dropped++; goto bad_desc; } @@ -1096,8 +1219,8 @@ spider_net_decode_one_descr(struct spider_net_card *card) if ( (status != SPIDER_NET_DESCR_COMPLETE) && (status != SPIDER_NET_DESCR_FRAME_END) ) { if (netif_msg_rx_err(card)) - pr_err("%s: RX descriptor with unknown state %d\n", - card->netdev->name, status); + dev_err(&card->netdev->dev, + "RX descriptor with unknown state %d\n", status); card->spider_stats.rx_desc_unk_state++; goto bad_desc; } @@ -1105,18 +1228,17 @@ spider_net_decode_one_descr(struct spider_net_card *card) /* The cases we'll throw away the packet immediately */ if (hwdescr->data_error & SPIDER_NET_DESTROY_RX_FLAGS) { if (netif_msg_rx_err(card)) - pr_err("%s: error in received descriptor found, " + dev_err(&card->netdev->dev, + "error in received descriptor found, " "data_status=x%08x, data_error=x%08x\n", - card->netdev->name, hwdescr->data_status, hwdescr->data_error); goto bad_desc; } - if (hwdescr->dmac_cmd_status & 0xfefe) { - pr_err("%s: bad status, cmd_status=x%08x\n", - card->netdev->name, + if (hwdescr->dmac_cmd_status & SPIDER_NET_DESCR_BAD_STATUS) { + dev_err(&card->netdev->dev, "bad status, cmd_status=x%08x\n", hwdescr->dmac_cmd_status); - pr_err("buf_addr=x%08x\n", hwdescr->buf_addr); + pr_err("buf_addr=x%08x\n", hw_buf_addr); pr_err("buf_size=x%08x\n", hwdescr->buf_size); pr_err("next_descr_addr=x%08x\n", hwdescr->next_descr_addr); pr_err("result_size=x%08x\n", hwdescr->result_size); @@ -1131,10 +1253,13 @@ spider_net_decode_one_descr(struct spider_net_card *card) /* Ok, we've got a packet in descr */ spider_net_pass_skb_up(descr, card); + descr->skb = NULL; hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE; return 1; bad_desc: + if (netif_msg_rx_err(card)) + show_rx_chain(card); dev_kfree_skb_irq(descr->skb); descr->skb = NULL; hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE; @@ -1160,7 +1285,6 @@ spider_net_poll(struct net_device *netdev, int *budget) int packets_to_do, packets_done = 0; int no_more_packets = 0; - spider_net_cleanup_tx_ring(card); packets_to_do = min(*budget, netdev->quota); while (packets_to_do) { @@ -1174,16 +1298,25 @@ spider_net_poll(struct net_device *netdev, int *budget) } } + if ((packets_done == 0) && (card->num_rx_ints != 0)) { + no_more_packets = spider_net_resync_tail_ptr(card); + spider_net_resync_head_ptr(card); + } + card->num_rx_ints = 0; + netdev->quota -= packets_done; *budget -= packets_done; spider_net_refill_rx_chain(card); spider_net_enable_rxdmac(card); + spider_net_cleanup_tx_ring(card); + /* if all packets are in the stack, enable interrupts and return 0 */ /* if not, return 1 */ if (no_more_packets) { netif_rx_complete(netdev); spider_net_rx_irq_on(card); + card->ignore_rx_ramfull = 0; return 0; } @@ -1191,43 +1324,6 @@ spider_net_poll(struct net_device *netdev, int *budget) } /** - * spider_net_vlan_rx_reg - initializes VLAN structures in the driver and card - * @netdev: interface device structure - * @grp: vlan_group structure that is registered (NULL on destroying interface) - */ -static void -spider_net_vlan_rx_reg(struct net_device *netdev, struct vlan_group *grp) -{ - /* further enhancement... yet to do */ - return; -} - -/** - * spider_net_vlan_rx_add - adds VLAN id to the card filter - * @netdev: interface device structure - * @vid: VLAN id to add - */ -static void -spider_net_vlan_rx_add(struct net_device *netdev, uint16_t vid) -{ - /* further enhancement... yet to do */ - /* add vid to card's VLAN filter table */ - return; -} - -/** - * spider_net_vlan_rx_kill - removes VLAN id to the card filter - * @netdev: interface device structure - * @vid: VLAN id to remove - */ -static void -spider_net_vlan_rx_kill(struct net_device *netdev, uint16_t vid) -{ - /* further enhancement... yet to do */ - /* remove vid from card's VLAN filter table */ -} - -/** * spider_net_get_stats - get interface statistics * @netdev: interface device structure * @@ -1345,11 +1441,17 @@ static void spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg) { u32 error_reg1, error_reg2; + u32 mask_reg1, mask_reg2; u32 i; int show_error = 1; error_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1STS); error_reg2 = spider_net_read_reg(card, SPIDER_NET_GHIINT2STS); + mask_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1MSK); + mask_reg2 = spider_net_read_reg(card,SPIDER_NET_GHIINT2MSK); + + error_reg1 &= mask_reg1; + error_reg2 &= mask_reg2; /* check GHIINT0STS ************************************/ if (status_reg) @@ -1384,7 +1486,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg) case SPIDER_NET_GPWFFINT: /* PHY command queue full */ if (netif_msg_intr(card)) - pr_err("PHY write queue full\n"); + dev_err(&card->netdev->dev, "PHY write queue full\n"); show_error = 0; break; @@ -1454,11 +1556,15 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg) case SPIDER_NET_GRFBFLLINT: /* fallthrough */ case SPIDER_NET_GRFAFLLINT: /* fallthrough */ case SPIDER_NET_GRMFLLINT: - if (netif_msg_intr(card) && net_ratelimit()) - pr_err("Spider RX RAM full, incoming packets " - "might be discarded!\n"); - spider_net_rx_irq_off(card); - netif_rx_schedule(card->netdev); + /* Could happen when rx chain is full */ + if (card->ignore_rx_ramfull == 0) { + card->ignore_rx_ramfull = 1; + spider_net_resync_head_ptr(card); + spider_net_refill_rx_chain(card); + spider_net_enable_rxdmac(card); + card->num_rx_ints ++; + netif_rx_schedule(card->netdev); + } show_error = 0; break; @@ -1473,12 +1579,11 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg) case SPIDER_NET_GDCDCEINT: /* fallthrough */ case SPIDER_NET_GDBDCEINT: /* fallthrough */ case SPIDER_NET_GDADCEINT: - if (netif_msg_intr(card) && net_ratelimit()) - pr_err("got descriptor chain end interrupt, " - "restarting DMAC %c.\n", - 'D'-(i-SPIDER_NET_GDDDCEINT)/3); + spider_net_resync_head_ptr(card); spider_net_refill_rx_chain(card); spider_net_enable_rxdmac(card); + card->num_rx_ints ++; + netif_rx_schedule(card->netdev); show_error = 0; break; @@ -1487,9 +1592,12 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg) case SPIDER_NET_GDCINVDINT: /* fallthrough */ case SPIDER_NET_GDBINVDINT: /* fallthrough */ case SPIDER_NET_GDAINVDINT: - /* could happen when rx chain is full */ + /* Could happen when rx chain is full */ + spider_net_resync_head_ptr(card); spider_net_refill_rx_chain(card); spider_net_enable_rxdmac(card); + card->num_rx_ints ++; + netif_rx_schedule(card->netdev); show_error = 0; break; @@ -1545,9 +1653,8 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg) } if ((show_error) && (netif_msg_intr(card)) && net_ratelimit()) - pr_err("Got error interrupt on %s, GHIINT0STS = 0x%08x, " + dev_err(&card->netdev->dev, "Error interrupt, GHIINT0STS = 0x%08x, " "GHIINT1STS = 0x%08x, GHIINT2STS = 0x%08x\n", - card->netdev->name, status_reg, error_reg1, error_reg2); /* clear interrupt sources */ @@ -1572,9 +1679,11 @@ spider_net_interrupt(int irq, void *ptr) { struct net_device *netdev = ptr; struct spider_net_card *card = netdev_priv(netdev); - u32 status_reg; + u32 status_reg, mask_reg; status_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0STS); + mask_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK); + status_reg &= mask_reg; if (!status_reg) return IRQ_NONE; @@ -1582,6 +1691,7 @@ spider_net_interrupt(int irq, void *ptr) if (status_reg & SPIDER_NET_RXINT ) { spider_net_rx_irq_off(card); netif_rx_schedule(netdev); + card->num_rx_ints ++; } if (status_reg & SPIDER_NET_TXINT) netif_rx_schedule(netdev); @@ -1615,6 +1725,38 @@ spider_net_poll_controller(struct net_device *netdev) #endif /* CONFIG_NET_POLL_CONTROLLER */ /** + * spider_net_enable_interrupts - enable interrupts + * @card: card structure + * + * spider_net_enable_interrupt enables several interrupts + */ +static void +spider_net_enable_interrupts(struct spider_net_card *card) +{ + spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, + SPIDER_NET_INT0_MASK_VALUE); + spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, + SPIDER_NET_INT1_MASK_VALUE); + spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, + SPIDER_NET_INT2_MASK_VALUE); +} + +/** + * spider_net_disable_interrupts - disable interrupts + * @card: card structure + * + * spider_net_disable_interrupts disables all the interrupts + */ +static void +spider_net_disable_interrupts(struct spider_net_card *card) +{ + spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0); + spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0); + spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0); + spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0); +} + +/** * spider_net_init_card - initializes the card * @card: card structure * @@ -1634,6 +1776,7 @@ spider_net_init_card(struct spider_net_card *card) spider_net_write_reg(card, SPIDER_NET_GMACOPEMD, spider_net_read_reg(card, SPIDER_NET_GMACOPEMD) | 0x4); + spider_net_disable_interrupts(card); } /** @@ -1721,14 +1864,6 @@ spider_net_enable_card(struct spider_net_card *card) spider_net_write_reg(card, SPIDER_NET_GMACOPEMD, SPIDER_NET_OPMODE_VALUE); - /* set interrupt mask registers */ - spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, - SPIDER_NET_INT0_MASK_VALUE); - spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, - SPIDER_NET_INT1_MASK_VALUE); - spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, - SPIDER_NET_INT2_MASK_VALUE); - spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR, SPIDER_NET_GDTBSTA); } @@ -1811,7 +1946,8 @@ spider_net_init_firmware(struct spider_net_card *card) SPIDER_NET_FIRMWARE_NAME, &card->pdev->dev) == 0) { if ( (firmware->size != SPIDER_NET_FIRMWARE_LEN) && netif_msg_probe(card) ) { - pr_err("Incorrect size of spidernet firmware in " \ + dev_err(&card->netdev->dev, + "Incorrect size of spidernet firmware in " \ "filesystem. Looking in host firmware...\n"); goto try_host_fw; } @@ -1835,8 +1971,8 @@ try_host_fw: if ( (fw_size != SPIDER_NET_FIRMWARE_LEN) && netif_msg_probe(card) ) { - pr_err("Incorrect size of spidernet firmware in " \ - "host firmware\n"); + dev_err(&card->netdev->dev, + "Incorrect size of spidernet firmware in host firmware\n"); goto done; } @@ -1846,7 +1982,8 @@ done: return err; out_err: if (netif_msg_probe(card)) - pr_err("Couldn't find spidernet firmware in filesystem " \ + dev_err(&card->netdev->dev, + "Couldn't find spidernet firmware in filesystem " \ "or host firmware\n"); return err; } @@ -1903,6 +2040,8 @@ spider_net_open(struct net_device *netdev) netif_carrier_on(netdev); netif_poll_enable(netdev); + spider_net_enable_interrupts(card); + return 0; register_int_failed: @@ -2075,11 +2214,7 @@ spider_net_stop(struct net_device *netdev) del_timer_sync(&card->tx_timer); del_timer_sync(&card->aneg_timer); - /* disable/mask all interrupts */ - spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0); - spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0); - spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0); - spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0); + spider_net_disable_interrupts(card); free_irq(netdev->irq, netdev); @@ -2177,9 +2312,6 @@ spider_net_setup_netdev_ops(struct net_device *netdev) netdev->poll = &spider_net_poll; netdev->weight = SPIDER_NET_NAPI_WEIGHT; /* HW VLAN */ - netdev->vlan_rx_register = &spider_net_vlan_rx_reg; - netdev->vlan_rx_add_vid = &spider_net_vlan_rx_add; - netdev->vlan_rx_kill_vid = &spider_net_vlan_rx_kill; #ifdef CONFIG_NET_POLL_CONTROLLER /* poll controller */ netdev->poll_controller = &spider_net_poll_controller; @@ -2225,11 +2357,13 @@ spider_net_setup_netdev(struct spider_net_card *card) spider_net_setup_netdev_ops(netdev); - netdev->features = NETIF_F_HW_CSUM | NETIF_F_LLTX; + netdev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX; /* some time: NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | * NETIF_F_HW_VLAN_FILTER */ netdev->irq = card->pdev->irq; + card->num_rx_ints = 0; + card->ignore_rx_ramfull = 0; dn = pci_device_to_OF_node(card->pdev); if (!dn) @@ -2242,13 +2376,14 @@ spider_net_setup_netdev(struct spider_net_card *card) result = spider_net_set_mac(netdev, &addr); if ((result) && (netif_msg_probe(card))) - pr_err("Failed to set MAC address: %i\n", result); + dev_err(&card->netdev->dev, + "Failed to set MAC address: %i\n", result); result = register_netdev(netdev); if (result) { if (netif_msg_probe(card)) - pr_err("Couldn't register net_device: %i\n", - result); + dev_err(&card->netdev->dev, + "Couldn't register net_device: %i\n", result); return result; } @@ -2326,17 +2461,19 @@ spider_net_setup_pci_dev(struct pci_dev *pdev) unsigned long mmio_start, mmio_len; if (pci_enable_device(pdev)) { - pr_err("Couldn't enable PCI device\n"); + dev_err(&pdev->dev, "Couldn't enable PCI device\n"); return NULL; } if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - pr_err("Couldn't find proper PCI device base address.\n"); + dev_err(&pdev->dev, + "Couldn't find proper PCI device base address.\n"); goto out_disable_dev; } if (pci_request_regions(pdev, spider_net_driver_name)) { - pr_err("Couldn't obtain PCI resources, aborting.\n"); + dev_err(&pdev->dev, + "Couldn't obtain PCI resources, aborting.\n"); goto out_disable_dev; } @@ -2344,8 +2481,8 @@ spider_net_setup_pci_dev(struct pci_dev *pdev) card = spider_net_alloc_card(); if (!card) { - pr_err("Couldn't allocate net_device structure, " - "aborting.\n"); + dev_err(&pdev->dev, + "Couldn't allocate net_device structure, aborting.\n"); goto out_release_regions; } card->pdev = pdev; @@ -2359,7 +2496,8 @@ spider_net_setup_pci_dev(struct pci_dev *pdev) card->regs = ioremap(mmio_start, mmio_len); if (!card->regs) { - pr_err("Couldn't obtain PCI resources, aborting.\n"); + dev_err(&pdev->dev, + "Couldn't obtain PCI resources, aborting.\n"); goto out_release_regions; } diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h index 4a1e0d28a50..dbbdb8cee3c 100644 --- a/drivers/net/spider_net.h +++ b/drivers/net/spider_net.h @@ -25,7 +25,7 @@ #ifndef _SPIDER_NET_H #define _SPIDER_NET_H -#define VERSION "2.0 A" +#define VERSION "2.0 B" #include "sungem_phy.h" @@ -222,6 +222,7 @@ extern char spider_net_driver_name[]; #define SPIDER_NET_GDTBSTA 0x00000300 #define SPIDER_NET_GDTDCEIDIS 0x00000002 #define SPIDER_NET_DMA_TX_VALUE SPIDER_NET_TX_DMA_EN | \ + SPIDER_NET_GDTDCEIDIS | \ SPIDER_NET_GDTBSTA #define SPIDER_NET_DMA_TX_FEND_VALUE 0x00030003 @@ -332,8 +333,7 @@ enum spider_net_int2_status { SPIDER_NET_GRISPDNGINT }; -#define SPIDER_NET_TXINT ( (1 << SPIDER_NET_GDTFDCINT) | \ - (1 << SPIDER_NET_GDTDCEINT) ) +#define SPIDER_NET_TXINT (1 << SPIDER_NET_GDTFDCINT) /* We rely on flagged descriptor interrupts */ #define SPIDER_NET_RXINT ( (1 << SPIDER_NET_GDAFDCINT) ) @@ -349,11 +349,23 @@ enum spider_net_int2_status { #define SPIDER_NET_GPRDAT_MASK 0x0000ffff #define SPIDER_NET_DMAC_NOINTR_COMPLETE 0x00800000 -#define SPIDER_NET_DMAC_NOCS 0x00040000 +#define SPIDER_NET_DMAC_TXFRMTL 0x00040000 #define SPIDER_NET_DMAC_TCP 0x00020000 #define SPIDER_NET_DMAC_UDP 0x00030000 #define SPIDER_NET_TXDCEST 0x08000000 +#define SPIDER_NET_DESCR_RXFDIS 0x00000001 +#define SPIDER_NET_DESCR_RXDCEIS 0x00000002 +#define SPIDER_NET_DESCR_RXDEN0IS 0x00000004 +#define SPIDER_NET_DESCR_RXINVDIS 0x00000008 +#define SPIDER_NET_DESCR_RXRERRIS 0x00000010 +#define SPIDER_NET_DESCR_RXFDCIMS 0x00000100 +#define SPIDER_NET_DESCR_RXDCEIMS 0x00000200 +#define SPIDER_NET_DESCR_RXDEN0IMS 0x00000400 +#define SPIDER_NET_DESCR_RXINVDIMS 0x00000800 +#define SPIDER_NET_DESCR_RXRERRMIS 0x00001000 +#define SPIDER_NET_DESCR_UNUSED 0x077fe0e0 + #define SPIDER_NET_DESCR_IND_PROC_MASK 0xF0000000 #define SPIDER_NET_DESCR_COMPLETE 0x00000000 /* used in rx and tx */ #define SPIDER_NET_DESCR_RESPONSE_ERROR 0x10000000 /* used in rx and tx */ @@ -364,6 +376,13 @@ enum spider_net_int2_status { #define SPIDER_NET_DESCR_NOT_IN_USE 0xF0000000 #define SPIDER_NET_DESCR_TXDESFLG 0x00800000 +#define SPIDER_NET_DESCR_BAD_STATUS (SPIDER_NET_DESCR_RXDEN0IS | \ + SPIDER_NET_DESCR_RXRERRIS | \ + SPIDER_NET_DESCR_RXDEN0IMS | \ + SPIDER_NET_DESCR_RXINVDIMS | \ + SPIDER_NET_DESCR_RXRERRMIS | \ + SPIDER_NET_DESCR_UNUSED) + /* Descriptor, as defined by the hardware */ struct spider_net_hw_descr { u32 buf_addr; @@ -461,6 +480,8 @@ struct spider_net_card { struct work_struct tx_timeout_task; atomic_t tx_timeout_task_counter; wait_queue_head_t waitq; + int num_rx_ints; + int ignore_rx_ramfull; /* for ethtool */ int msg_enable; diff --git a/drivers/net/spider_net_ethtool.c b/drivers/net/spider_net_ethtool.c index 6bcf03fc89b..d940474e024 100644 --- a/drivers/net/spider_net_ethtool.c +++ b/drivers/net/spider_net_ethtool.c @@ -134,22 +134,6 @@ spider_net_ethtool_set_rx_csum(struct net_device *netdev, u32 n) return 0; } -static uint32_t -spider_net_ethtool_get_tx_csum(struct net_device *netdev) -{ - return (netdev->features & NETIF_F_HW_CSUM) != 0; -} - -static int -spider_net_ethtool_set_tx_csum(struct net_device *netdev, uint32_t data) -{ - if (data) - netdev->features |= NETIF_F_HW_CSUM; - else - netdev->features &= ~NETIF_F_HW_CSUM; - - return 0; -} static void spider_net_ethtool_get_ringparam(struct net_device *netdev, @@ -200,11 +184,12 @@ const struct ethtool_ops spider_net_ethtool_ops = { .get_wol = spider_net_ethtool_get_wol, .get_msglevel = spider_net_ethtool_get_msglevel, .set_msglevel = spider_net_ethtool_set_msglevel, + .get_link = ethtool_op_get_link, .nway_reset = spider_net_ethtool_nway_reset, .get_rx_csum = spider_net_ethtool_get_rx_csum, .set_rx_csum = spider_net_ethtool_set_rx_csum, - .get_tx_csum = spider_net_ethtool_get_tx_csum, - .set_tx_csum = spider_net_ethtool_set_tx_csum, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_csum, .get_ringparam = spider_net_ethtool_get_ringparam, .get_strings = spider_net_get_strings, .get_stats_count = spider_net_get_stats_count, diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 9d6e454a8f9..8b6478663a5 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -152,7 +152,7 @@ static int full_duplex[MAX_UNITS] = {0, }; * This SUCKS. * We need a much better method to determine if dma_addr_t is 64-bit. */ -#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) +#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__alpha__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) /* 64-bit dma_addr_t */ #define ADDR_64BITS /* This chip uses 64 bit addresses. */ #define netdrv_addr_t u64 @@ -740,7 +740,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev, pci_set_master(pdev); /* enable MWI -- it vastly improves Rx performance on sparc64 */ - pci_set_mwi(pdev); + pci_try_set_mwi(pdev); #ifdef ZEROCOPY /* Starfire can do TCP/UDP checksumming */ @@ -1456,7 +1456,7 @@ static int __netdev_rx(struct net_device *dev, int *quota) pci_dma_sync_single_for_cpu(np->pci_dev, np->rx_info[entry].mapping, pkt_len, PCI_DMA_FROMDEVICE); - eth_copy_and_sum(skb, np->rx_info[entry].skb->data, pkt_len, 0); + skb_copy_to_linear_data(skb, np->rx_info[entry].skb->data, pkt_len); pci_dma_sync_single_for_device(np->pci_dev, np->rx_info[entry].mapping, pkt_len, PCI_DMA_FROMDEVICE); diff --git a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c index a123ea87893..b77ab6e8fd3 100644 --- a/drivers/net/sun3_82586.c +++ b/drivers/net/sun3_82586.c @@ -777,7 +777,7 @@ static void sun3_82586_rcv_int(struct net_device *dev) { skb_reserve(skb,2); skb_put(skb,totlen); - eth_copy_and_sum(skb,(char *) p->base+swab32((unsigned long) rbd->buffer),totlen,0); + skb_copy_to_linear_data(skb,(char *) p->base+swab32((unsigned long) rbd->buffer),totlen); skb->protocol=eth_type_trans(skb,dev); netif_rx(skb); p->stats.rx_packets++; diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c index 791e081fdc1..f1548c03332 100644 --- a/drivers/net/sun3lance.c +++ b/drivers/net/sun3lance.c @@ -853,10 +853,9 @@ static int lance_rx( struct net_device *dev ) skb_reserve( skb, 2 ); /* 16 byte align */ skb_put( skb, pkt_len ); /* Make room */ -// skb_copy_to_linear_data(skb, PKTBUF_ADDR(head), pkt_len); - eth_copy_and_sum(skb, + skb_copy_to_linear_data(skb, PKTBUF_ADDR(head), - pkt_len, 0); + pkt_len); skb->protocol = eth_type_trans( skb, dev ); netif_rx( skb ); diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index 2ad8d58dee3..b3e0158def4 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c @@ -860,7 +860,7 @@ static void bigmac_rx(struct bigmac *bp) sbus_dma_sync_single_for_cpu(bp->bigmac_sdev, this->rx_addr, len, SBUS_DMA_FROMDEVICE); - eth_copy_and_sum(copy_skb, (unsigned char *)skb->data, len, 0); + skb_copy_to_linear_data(copy_skb, (unsigned char *)skb->data, len); sbus_dma_sync_single_for_device(bp->bigmac_sdev, this->rx_addr, len, SBUS_DMA_FROMDEVICE); diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index e1f912d0404..af0c9831074 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -397,7 +397,6 @@ struct netdev_private { unsigned char phys[MII_CNT]; /* MII device addresses, only first one used. */ struct pci_dev *pci_dev; void __iomem *base; - unsigned char pci_rev_id; }; /* The station address location in the EEPROM. */ @@ -544,8 +543,6 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev, dev->change_mtu = &change_mtu; pci_set_drvdata(pdev, dev); - pci_read_config_byte(pdev, PCI_REVISION_ID, &np->pci_rev_id); - i = register_netdev(dev); if (i) goto err_out_unmap_rx; @@ -828,7 +825,7 @@ static int netdev_open(struct net_device *dev) iowrite8(100, ioaddr + RxDMAPollPeriod); iowrite8(127, ioaddr + TxDMAPollPeriod); /* Fix DFE-580TX packet drop issue */ - if (np->pci_rev_id >= 0x14) + if (np->pci_dev->revision >= 0x14) iowrite8(0x01, ioaddr + DebugCtrl1); netif_start_queue(dev); @@ -1194,7 +1191,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) hw_frame_id = ioread8(ioaddr + TxFrameId); } - if (np->pci_rev_id >= 0x14) { + if (np->pci_dev->revision >= 0x14) { spin_lock(&np->lock); for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) { int entry = np->dirty_tx % TX_RING_SIZE; @@ -1313,7 +1310,7 @@ static void rx_poll(unsigned long data) np->rx_buf_sz, PCI_DMA_FROMDEVICE); - eth_copy_and_sum(skb, np->rx_skbuff[entry]->data, pkt_len, 0); + skb_copy_to_linear_data(skb, np->rx_skbuff[entry]->data, pkt_len); pci_dma_sync_single_for_device(np->pci_dev, desc->frag[0].addr, np->rx_buf_sz, diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 51c3fe2108a..8b35f13318e 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -2625,7 +2625,7 @@ static void quattro_sbus_free_irqs(void) #endif /* CONFIG_SBUS */ #ifdef CONFIG_PCI -static struct quattro * __init quattro_pci_find(struct pci_dev *pdev) +static struct quattro * __devinit quattro_pci_find(struct pci_dev *pdev) { struct pci_dev *bdev = pdev->bus->self; struct quattro *qp; @@ -3095,12 +3095,8 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, #ifdef CONFIG_SPARC hp->hm_revision = of_getintprop_default(dp, "hm-rev", 0xff); - if (hp->hm_revision == 0xff) { - unsigned char prev; - - pci_read_config_byte(pdev, PCI_REVISION_ID, &prev); - hp->hm_revision = 0xc0 | (prev & 0x0f); - } + if (hp->hm_revision == 0xff) + hp->hm_revision = 0xc0 | (pdev->revision & 0x0f); #else /* works with this on non-sparc hosts */ hp->hm_revision = 0x20; diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index 42722530ab2..053b7cb0d94 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c @@ -549,9 +549,9 @@ static void lance_rx_dvma(struct net_device *dev) skb_reserve(skb, 2); /* 16 byte align */ skb_put(skb, len); /* make room */ - eth_copy_and_sum(skb, + skb_copy_to_linear_data(skb, (unsigned char *)&(ib->rx_buf [entry][0]), - len, 0); + len); skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); dev->last_rx = jiffies; diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index fa70e0b78af..1b65ae8a1c7 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c @@ -439,8 +439,8 @@ static void qe_rx(struct sunqe *qep) } else { skb_reserve(skb, 2); skb_put(skb, len); - eth_copy_and_sum(skb, (unsigned char *) this_qbuf, - len, 0); + skb_copy_to_linear_data(skb, (unsigned char *) this_qbuf, + len); skb->protocol = eth_type_trans(skb, qep->dev); netif_rx(skb); qep->dev->last_rx = jiffies; diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index 463d600ed83..75655add3f3 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -23,9 +23,9 @@ */ #ifdef TC35815_NAPI -#define DRV_VERSION "1.35-NAPI" +#define DRV_VERSION "1.36-NAPI" #else -#define DRV_VERSION "1.35" +#define DRV_VERSION "1.36" #endif static const char *version = "tc35815.c:v" DRV_VERSION "\n"; #define MODNAME "tc35815" @@ -49,6 +49,7 @@ static const char *version = "tc35815.c:v" DRV_VERSION "\n"; #include <linux/pci.h> #include <linux/mii.h> #include <linux/ethtool.h> +#include <linux/platform_device.h> #include <asm/io.h> #include <asm/byteorder.h> @@ -597,13 +598,46 @@ static int tc_mdio_read(struct net_device *dev, int phy_id, int location); static void tc_mdio_write(struct net_device *dev, int phy_id, int location, int val); -static void __devinit tc35815_init_dev_addr (struct net_device *dev) +#ifdef CONFIG_CPU_TX49XX +/* + * Find a platform_device providing a MAC address. The platform code + * should provide a "tc35815-mac" device with a MAC address in its + * platform_data. + */ +static int __devinit tc35815_mac_match(struct device *dev, void *data) +{ + struct platform_device *plat_dev = to_platform_device(dev); + struct pci_dev *pci_dev = data; + unsigned int id = (pci_dev->bus->number << 8) | pci_dev->devfn; + return !strcmp(plat_dev->name, "tc35815-mac") && plat_dev->id == id; +} + +static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev) +{ + struct tc35815_local *lp = dev->priv; + struct device *pd = bus_find_device(&platform_bus_type, NULL, + lp->pci_dev, tc35815_mac_match); + if (pd) { + if (pd->platform_data) + memcpy(dev->dev_addr, pd->platform_data, ETH_ALEN); + put_device(pd); + return is_valid_ether_addr(dev->dev_addr) ? 0 : -ENODEV; + } + return -ENODEV; +} +#else +static int __devinit tc35815_read_plat_dev_addr(struct device *dev) +{ + return -ENODEV; +} +#endif + +static int __devinit tc35815_init_dev_addr (struct net_device *dev) { struct tc35815_regs __iomem *tr = (struct tc35815_regs __iomem *)dev->base_addr; int i; - /* dev_addr will be overwritten on NETDEV_REGISTER event */ while (tc_readl(&tr->PROM_Ctl) & PROM_Busy) ; for (i = 0; i < 6; i += 2) { @@ -615,6 +649,9 @@ static void __devinit tc35815_init_dev_addr (struct net_device *dev) dev->dev_addr[i] = data & 0xff; dev->dev_addr[i+1] = data >> 8; } + if (!is_valid_ether_addr(dev->dev_addr)) + return tc35815_read_plat_dev_addr(dev); + return 0; } static int __devinit tc35815_init_one (struct pci_dev *pdev, @@ -724,7 +761,10 @@ static int __devinit tc35815_init_one (struct pci_dev *pdev, tc35815_chip_reset(dev); /* Retrieve the ethernet address. */ - tc35815_init_dev_addr(dev); + if (tc35815_init_dev_addr(dev)) { + dev_warn(&pdev->dev, "not valid ether addr\n"); + random_ether_addr(dev->dev_addr); + } rc = register_netdev (dev); if (rc) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 923b9c725cc..5ee14764fd7 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -64,8 +64,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.76" -#define DRV_MODULE_RELDATE "May 5, 2007" +#define DRV_MODULE_VERSION "3.78" +#define DRV_MODULE_RELDATE "July 11, 2007" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -721,6 +721,44 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val) return ret; } +static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable) +{ + u32 phy; + + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) || + (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)) + return; + + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + u32 ephy; + + if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &ephy)) { + tg3_writephy(tp, MII_TG3_EPHY_TEST, + ephy | MII_TG3_EPHY_SHADOW_EN); + if (!tg3_readphy(tp, MII_TG3_EPHYTST_MISCCTRL, &phy)) { + if (enable) + phy |= MII_TG3_EPHYTST_MISCCTRL_MDIX; + else + phy &= ~MII_TG3_EPHYTST_MISCCTRL_MDIX; + tg3_writephy(tp, MII_TG3_EPHYTST_MISCCTRL, phy); + } + tg3_writephy(tp, MII_TG3_EPHY_TEST, ephy); + } + } else { + phy = MII_TG3_AUXCTL_MISC_RDSEL_MISC | + MII_TG3_AUXCTL_SHDWSEL_MISC; + if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, phy) && + !tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy)) { + if (enable) + phy |= MII_TG3_AUXCTL_MISC_FORCE_AMDIX; + else + phy &= ~MII_TG3_AUXCTL_MISC_FORCE_AMDIX; + phy |= MII_TG3_AUXCTL_MISC_WREN; + tg3_writephy(tp, MII_TG3_AUX_CTRL, phy); + } + } +} + static void tg3_phy_set_wirespeed(struct tg3 *tp) { u32 val; @@ -1045,23 +1083,11 @@ out: } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { - u32 phy_reg; - /* adjust output voltage */ tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x12); - - if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &phy_reg)) { - u32 phy_reg2; - - tg3_writephy(tp, MII_TG3_EPHY_TEST, - phy_reg | MII_TG3_EPHY_SHADOW_EN); - /* Enable auto-MDIX */ - if (!tg3_readphy(tp, 0x10, &phy_reg2)) - tg3_writephy(tp, 0x10, phy_reg2 | 0x4000); - tg3_writephy(tp, MII_TG3_EPHY_TEST, phy_reg); - } } + tg3_phy_toggle_automdix(tp, 1); tg3_phy_set_wirespeed(tp); return 0; } @@ -1162,6 +1188,19 @@ static void tg3_frob_aux_power(struct tg3 *tp) } } +static int tg3_5700_link_polarity(struct tg3 *tp, u32 speed) +{ + if (tp->led_ctrl == LED_CTRL_MODE_PHY_2) + return 1; + else if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411) { + if (speed != SPEED_10) + return 1; + } else if (speed == SPEED_10) + return 1; + + return 0; +} + static int tg3_setup_phy(struct tg3 *, int); #define RESET_KIND_SHUTDOWN 0 @@ -1320,9 +1359,17 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) else mac_mode = MAC_MODE_PORT_MODE_MII; - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 || - !(tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB)) - mac_mode |= MAC_MODE_LINK_POLARITY; + mac_mode |= tp->mac_mode & MAC_MODE_LINK_POLARITY; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == + ASIC_REV_5700) { + u32 speed = (tp->tg3_flags & + TG3_FLAG_WOL_SPEED_100MB) ? + SPEED_100 : SPEED_10; + if (tg3_5700_link_polarity(tp, speed)) + mac_mode |= MAC_MODE_LINK_POLARITY; + else + mac_mode &= ~MAC_MODE_LINK_POLARITY; + } } else { mac_mode = MAC_MODE_PORT_MODE_TBI; } @@ -1990,15 +2037,12 @@ relink: if (tp->link_config.active_duplex == DUPLEX_HALF) tp->mac_mode |= MAC_MODE_HALF_DUPLEX; - tp->mac_mode &= ~MAC_MODE_LINK_POLARITY; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) { - if ((tp->led_ctrl == LED_CTRL_MODE_PHY_2) || - (current_link_up == 1 && - tp->link_config.active_speed == SPEED_10)) - tp->mac_mode |= MAC_MODE_LINK_POLARITY; - } else { - if (current_link_up == 1) + if (current_link_up == 1 && + tg3_5700_link_polarity(tp, tp->link_config.active_speed)) tp->mac_mode |= MAC_MODE_LINK_POLARITY; + else + tp->mac_mode &= ~MAC_MODE_LINK_POLARITY; } /* ??? Without this setting Netgear GA302T PHY does not @@ -2639,6 +2683,9 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status) tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS)); udelay(40); + + tw32_f(MAC_MODE, tp->mac_mode); + udelay(40); } out: @@ -2698,10 +2745,6 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) else current_link_up = tg3_setup_fiber_by_hand(tp, mac_status); - tp->mac_mode &= ~MAC_MODE_LINK_POLARITY; - tw32_f(MAC_MODE, tp->mac_mode); - udelay(40); - tp->hw_status->status = (SD_STATUS_UPDATED | (tp->hw_status->status & ~SD_STATUS_LINK_CHG)); @@ -3512,9 +3555,9 @@ static inline int tg3_irq_sync(struct tg3 *tp) */ static inline void tg3_full_lock(struct tg3 *tp, int irq_sync) { + spin_lock_bh(&tp->lock); if (irq_sync) tg3_irq_quiesce(tp); - spin_lock_bh(&tp->lock); } static inline void tg3_full_unlock(struct tg3 *tp) @@ -6444,6 +6487,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE | MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE; + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && + !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) + tp->mac_mode |= MAC_MODE_LINK_POLARITY; tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR); udelay(40); @@ -8271,7 +8318,7 @@ static int tg3_set_tx_csum(struct net_device *dev, u32 data) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) - ethtool_op_set_tx_hw_csum(dev, data); + ethtool_op_set_tx_ipv6_csum(dev, data); else ethtool_op_set_tx_csum(dev, data); @@ -8805,7 +8852,9 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) return 0; mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) | - MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY; + MAC_MODE_PORT_INT_LPBACK; + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + mac_mode |= MAC_MODE_LINK_POLARITY; if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) mac_mode |= MAC_MODE_PORT_MODE_MII; else @@ -8824,19 +8873,18 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) phytest | MII_TG3_EPHY_SHADOW_EN); if (!tg3_readphy(tp, 0x1b, &phy)) tg3_writephy(tp, 0x1b, phy & ~0x20); - if (!tg3_readphy(tp, 0x10, &phy)) - tg3_writephy(tp, 0x10, phy & ~0x4000); tg3_writephy(tp, MII_TG3_EPHY_TEST, phytest); } val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED100; } else val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED1000; + tg3_phy_toggle_automdix(tp, 0); + tg3_writephy(tp, MII_BMCR, val); udelay(40); - mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) | - MAC_MODE_LINK_POLARITY; + mac_mode = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x1800); mac_mode |= MAC_MODE_PORT_MODE_MII; @@ -8849,8 +8897,11 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) udelay(10); tw32_f(MAC_RX_MODE, tp->rx_mode); } - if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) { - mac_mode &= ~MAC_MODE_LINK_POLARITY; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) { + if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) + mac_mode &= ~MAC_MODE_LINK_POLARITY; + else if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411) + mac_mode |= MAC_MODE_LINK_POLARITY; tg3_writephy(tp, MII_TG3_EXT_CTRL, MII_TG3_EXT_CTRL_LNK3_LED_MODE); } @@ -9116,25 +9167,10 @@ static void tg3_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) /* Update RX_MODE_KEEP_VLAN_TAG bit in RX_MODE register. */ __tg3_set_rx_mode(dev); - tg3_full_unlock(tp); - if (netif_running(dev)) tg3_netif_start(tp); -} - -static void tg3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) -{ - struct tg3 *tp = netdev_priv(dev); - - if (netif_running(dev)) - tg3_netif_stop(tp); - tg3_full_lock(tp, 0); - vlan_group_set_device(tp->vlgrp, vid, NULL); tg3_full_unlock(tp); - - if (netif_running(dev)) - tg3_netif_start(tp); } #endif @@ -9425,11 +9461,13 @@ static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp) case FLASH_5755VENDOR_ATMEL_FLASH_1: case FLASH_5755VENDOR_ATMEL_FLASH_2: case FLASH_5755VENDOR_ATMEL_FLASH_3: + case FLASH_5755VENDOR_ATMEL_FLASH_5: tp->nvram_jedecnum = JEDEC_ATMEL; tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED; tp->tg3_flags2 |= TG3_FLG2_FLASH; tp->nvram_pagesize = 264; - if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_1) + if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_1 || + nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_5) tp->nvram_size = (protect ? 0x3e200 : 0x80000); else if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_2) tp->nvram_size = (protect ? 0x1f200 : 0x40000); @@ -10513,11 +10551,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) continue; } if (pci_id->rev != PCI_ANY_ID) { - u8 rev; - - pci_read_config_byte(bridge, PCI_REVISION_ID, - &rev); - if (rev > pci_id->rev) + if (bridge->revision > pci_id->rev) continue; } if (bridge->subordinate && @@ -10976,6 +11010,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) * upon subsystem IDs. */ if (tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL && + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 && !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { tp->tg3_flags |= (TG3_FLAG_USE_MI_INTERRUPT | TG3_FLAG_USE_LINKCHG_REG); @@ -11778,7 +11813,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, #if TG3_VLAN_TAG_USED dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; dev->vlan_rx_register = tg3_vlan_rx_register; - dev->vlan_rx_kill_vid = tg3_vlan_rx_kill_vid; #endif tp = netdev_priv(dev); @@ -11959,12 +11993,11 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, * checksumming. */ if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) { + dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) - dev->features |= NETIF_F_HW_CSUM; - else - dev->features |= NETIF_F_IP_CSUM; - dev->features |= NETIF_F_SG; + dev->features |= NETIF_F_IPV6_CSUM; + tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS; } else tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index bd9f4f428e5..d84e75e7365 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -1467,6 +1467,7 @@ #define FLASH_5755VENDOR_ATMEL_FLASH_2 0x03400002 #define FLASH_5755VENDOR_ATMEL_FLASH_3 0x03400000 #define FLASH_5755VENDOR_ATMEL_FLASH_4 0x00000003 +#define FLASH_5755VENDOR_ATMEL_FLASH_5 0x02000003 #define FLASH_5755VENDOR_ATMEL_EEPROM_64KHZ 0x03c00003 #define FLASH_5755VENDOR_ATMEL_EEPROM_376KHZ 0x03c00002 #define FLASH_5787VENDOR_ATMEL_EEPROM_64KHZ 0x03000003 @@ -1642,6 +1643,11 @@ #define MII_TG3_AUX_CTRL 0x18 /* auxilliary control register */ +#define MII_TG3_AUXCTL_MISC_WREN 0x8000 +#define MII_TG3_AUXCTL_MISC_FORCE_AMDIX 0x0200 +#define MII_TG3_AUXCTL_MISC_RDSEL_MISC 0x7000 +#define MII_TG3_AUXCTL_SHDWSEL_MISC 0x0007 + #define MII_TG3_AUX_STAT 0x19 /* auxilliary status register */ #define MII_TG3_AUX_STAT_LPASS 0x0004 #define MII_TG3_AUX_STAT_SPDMASK 0x0700 @@ -1667,6 +1673,9 @@ #define MII_TG3_EPHY_TEST 0x1f /* 5906 PHY register */ #define MII_TG3_EPHY_SHADOW_EN 0x80 +#define MII_TG3_EPHYTST_MISCCTRL 0x10 /* 5906 EPHY misc ctrl shadow register */ +#define MII_TG3_EPHYTST_MISCCTRL_MDIX 0x4000 + #define MII_TG3_TEST1 0x1e #define MII_TG3_TEST1_TRIM_EN 0x0010 #define MII_TG3_TEST1_CRC_EN 0x8000 diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index 106dc1ef0ac..74eb12107e6 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -533,7 +533,6 @@ static int __devinit TLan_probe1(struct pci_dev *pdev, struct net_device *dev; TLanPrivateInfo *priv; - u8 pci_rev; u16 device_id; int reg, rc = -ENODEV; @@ -577,8 +576,6 @@ static int __devinit TLan_probe1(struct pci_dev *pdev, goto err_out_free_dev; } - pci_read_config_byte ( pdev, PCI_REVISION_ID, &pci_rev); - for ( reg= 0; reg <= 5; reg ++ ) { if (pci_resource_flags(pdev, reg) & IORESOURCE_IO) { pci_io_base = pci_resource_start(pdev, reg); @@ -595,7 +592,7 @@ static int __devinit TLan_probe1(struct pci_dev *pdev, dev->base_addr = pci_io_base; dev->irq = pdev->irq; - priv->adapterRev = pci_rev; + priv->adapterRev = pdev->revision; pci_set_master(pdev); pci_set_drvdata(pdev, dev); diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c index e22a3f5333e..9f1b6ab9c22 100644 --- a/drivers/net/tokenring/3c359.c +++ b/drivers/net/tokenring/3c359.c @@ -363,7 +363,7 @@ static int __devinit xl_probe(struct pci_dev *pdev, } -static int __init xl_init(struct net_device *dev) +static int __devinit xl_init(struct net_device *dev) { struct xl_private *xl_priv = (struct xl_private *)dev->priv ; diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig index 8c9634a98c1..1c537d5a306 100644 --- a/drivers/net/tulip/Kconfig +++ b/drivers/net/tulip/Kconfig @@ -2,17 +2,17 @@ # Tulip family network device configuration # -menu "Tulip family network device support" - depends on NET_ETHERNET && (PCI || EISA || CARDBUS) - -config NET_TULIP +menuconfig NET_TULIP bool "\"Tulip\" family network device support" + depends on PCI || EISA || CARDBUS help This selects the "Tulip" family of EISA/PCI network cards. +if NET_TULIP + config DE2104X tristate "Early DECchip Tulip (dc2104x) PCI support (EXPERIMENTAL)" - depends on NET_TULIP && PCI && EXPERIMENTAL + depends on PCI && EXPERIMENTAL select CRC32 ---help--- This driver is developed for the SMC EtherPower series Ethernet @@ -30,7 +30,7 @@ config DE2104X config TULIP tristate "DECchip Tulip (dc2114x) PCI support" - depends on NET_TULIP && PCI + depends on PCI select CRC32 ---help--- This driver is developed for the SMC EtherPower series Ethernet @@ -95,7 +95,7 @@ config TULIP_NAPI_HW_MITIGATION config DE4X5 tristate "Generic DECchip & DIGITAL EtherWORKS PCI/EISA" - depends on NET_TULIP && (PCI || EISA) + depends on PCI || EISA select CRC32 ---help--- This is support for the DIGITAL series of PCI/EISA Ethernet cards. @@ -112,7 +112,7 @@ config DE4X5 config WINBOND_840 tristate "Winbond W89c840 Ethernet support" - depends on NET_TULIP && PCI + depends on PCI select CRC32 select MII help @@ -123,7 +123,7 @@ config WINBOND_840 config DM9102 tristate "Davicom DM910x/DM980x support" - depends on NET_TULIP && PCI + depends on PCI select CRC32 ---help--- This driver is for DM9102(A)/DM9132/DM9801 compatible PCI cards from @@ -137,7 +137,7 @@ config DM9102 config ULI526X tristate "ULi M526x controller support" - depends on NET_TULIP && PCI + depends on PCI select CRC32 ---help--- This driver is for ULi M5261/M5263 10/100M Ethernet Controller @@ -149,7 +149,7 @@ config ULI526X config PCMCIA_XIRCOM tristate "Xircom CardBus support (new driver)" - depends on NET_TULIP && CARDBUS + depends on CARDBUS ---help--- This driver is for the Digital "Tulip" Ethernet CardBus adapters. It should work with most DEC 21*4*-based chips/ethercards, as well @@ -162,7 +162,7 @@ config PCMCIA_XIRCOM config PCMCIA_XIRTULIP tristate "Xircom Tulip-like CardBus support (old driver)" - depends on NET_TULIP && CARDBUS && BROKEN_ON_SMP + depends on CARDBUS && BROKEN_ON_SMP select CRC32 ---help--- This driver is for the Digital "Tulip" Ethernet CardBus adapters. @@ -174,5 +174,4 @@ config PCMCIA_XIRTULIP <file:Documentation/networking/net-modules.txt>. The module will be called xircom_tulip_cb. If unsure, say N. -endmenu - +endif # NET_TULIP diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 861729806dc..d380e0b3f05 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -785,7 +785,6 @@ static void __de_set_rx_mode (struct net_device *dev) de->tx_head = NEXT_TX(entry); - BUG_ON(TX_BUFFS_AVAIL(de) < 0); if (TX_BUFFS_AVAIL(de) == 0) netif_stop_queue(dev); diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index 62143f92c23..09902891a6e 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -597,7 +597,7 @@ static char *args; #endif struct parameters { - int fdx; + bool fdx; int autosense; }; @@ -809,10 +809,10 @@ struct de4x5_private { s32 irq_en; /* Summary interrupt bits */ int media; /* Media (eg TP), mode (eg 100B)*/ int c_media; /* Remember the last media conn */ - int fdx; /* media full duplex flag */ + bool fdx; /* media full duplex flag */ int linkOK; /* Link is OK */ int autosense; /* Allow/disallow autosensing */ - int tx_enable; /* Enable descriptor polling */ + bool tx_enable; /* Enable descriptor polling */ int setup_f; /* Setup frame filtering type */ int local_state; /* State within a 'media' state */ struct mii_phy phy[DE4X5_MAX_PHY]; /* List of attached PHY devices */ @@ -838,8 +838,8 @@ struct de4x5_private { struct de4x5_srom srom; /* A copy of the SROM */ int cfrv; /* Card CFRV copy */ int rx_ovf; /* Check for 'RX overflow' tag */ - int useSROM; /* For non-DEC card use SROM */ - int useMII; /* Infoblock using the MII */ + bool useSROM; /* For non-DEC card use SROM */ + bool useMII; /* Infoblock using the MII */ int asBitValid; /* Autosense bits in GEP? */ int asPolarity; /* 0 => asserted high */ int asBit; /* Autosense bit number in GEP */ @@ -928,7 +928,7 @@ static int dc21040_state(struct net_device *dev, int csr13, int csr14, int c static int test_media(struct net_device *dev, s32 irqs, s32 irq_mask, s32 csr13, s32 csr14, s32 csr15, s32 msec); static int test_for_100Mb(struct net_device *dev, int msec); static int wait_for_link(struct net_device *dev); -static int test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec); +static int test_mii_reg(struct net_device *dev, int reg, int mask, bool pol, long msec); static int is_spd_100(struct net_device *dev); static int is_100_up(struct net_device *dev); static int is_10_up(struct net_device *dev); @@ -1109,7 +1109,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev) /* ** Now find out what kind of DC21040/DC21041/DC21140 board we have. */ - lp->useSROM = FALSE; + lp->useSROM = false; if (lp->bus == PCI) { PCI_signature(name, lp); } else { @@ -1137,7 +1137,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev) lp->cache.gepc = GEP_INIT; lp->asBit = GEP_SLNK; lp->asPolarity = GEP_SLNK; - lp->asBitValid = TRUE; + lp->asBitValid = ~0; lp->timeout = -1; lp->gendev = gendev; spin_lock_init(&lp->lock); @@ -1463,7 +1463,7 @@ de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev) u_long flags = 0; netif_stop_queue(dev); - if (lp->tx_enable == NO) { /* Cannot send for now */ + if (!lp->tx_enable) { /* Cannot send for now */ return -1; } @@ -2134,7 +2134,7 @@ srom_search(struct net_device *dev, struct pci_dev *pdev) u_short vendor, status; u_int irq = 0, device; u_long iobase = 0; /* Clear upper 32 bits in Alphas */ - int i, j, cfrv; + int i, j; struct de4x5_private *lp = netdev_priv(dev); struct list_head *walk; @@ -2150,7 +2150,6 @@ srom_search(struct net_device *dev, struct pci_dev *pdev) /* Get the chip configuration revision register */ pb = this_dev->bus->number; - pci_read_config_dword(this_dev, PCI_REVISION_ID, &cfrv); /* Set the device number information */ lp->device = PCI_SLOT(this_dev->devfn); @@ -2158,7 +2157,8 @@ srom_search(struct net_device *dev, struct pci_dev *pdev) /* Set the chipset information */ if (is_DC2114x) { - device = ((cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143); + device = ((this_dev->revision & CFRV_RN) < DC2114x_BRK + ? DC21142 : DC21143); } lp->chipset = device; @@ -2254,7 +2254,7 @@ static int __devinit de4x5_pci_probe (struct pci_dev *pdev, } /* Get the chip configuration revision register */ - pci_read_config_dword(pdev, PCI_REVISION_ID, &lp->cfrv); + lp->cfrv = pdev->revision; /* Set the device number information */ lp->device = dev_num; @@ -2424,7 +2424,7 @@ dc21040_autoconf(struct net_device *dev) switch (lp->media) { case INIT: DISABLE_IRQs; - lp->tx_enable = NO; + lp->tx_enable = false; lp->timeout = -1; de4x5_save_skbs(dev); if ((lp->autosense == AUTO) || (lp->autosense == TP)) { @@ -2477,7 +2477,7 @@ dc21040_autoconf(struct net_device *dev) lp->c_media = lp->media; } lp->media = INIT; - lp->tx_enable = NO; + lp->tx_enable = false; break; } @@ -2578,7 +2578,7 @@ dc21041_autoconf(struct net_device *dev) switch (lp->media) { case INIT: DISABLE_IRQs; - lp->tx_enable = NO; + lp->tx_enable = false; lp->timeout = -1; de4x5_save_skbs(dev); /* Save non transmitted skb's */ if ((lp->autosense == AUTO) || (lp->autosense == TP_NW)) { @@ -2757,7 +2757,7 @@ dc21041_autoconf(struct net_device *dev) lp->c_media = lp->media; } lp->media = INIT; - lp->tx_enable = NO; + lp->tx_enable = false; break; } @@ -2781,7 +2781,7 @@ dc21140m_autoconf(struct net_device *dev) case INIT: if (lp->timeout < 0) { DISABLE_IRQs; - lp->tx_enable = FALSE; + lp->tx_enable = false; lp->linkOK = 0; de4x5_save_skbs(dev); /* Save non transmitted skb's */ } @@ -2830,7 +2830,7 @@ dc21140m_autoconf(struct net_device *dev) if (lp->timeout < 0) { mii_wr(MII_CR_ASSE | MII_CR_RAN, MII_CR, lp->phy[lp->active].addr, DE4X5_MII); } - cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, FALSE, 500); + cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, false, 500); if (cr < 0) { next_tick = cr & ~TIMER_CB; } else { @@ -2845,7 +2845,7 @@ dc21140m_autoconf(struct net_device *dev) break; case 1: - if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) { + if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, true, 2000)) < 0) { next_tick = sr & ~TIMER_CB; } else { lp->media = SPD_DET; @@ -2857,10 +2857,10 @@ dc21140m_autoconf(struct net_device *dev) if (!(anlpa & MII_ANLPA_RF) && (cap = anlpa & MII_ANLPA_TAF & ana)) { if (cap & MII_ANA_100M) { - lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) ? TRUE : FALSE); + lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) != 0; lp->media = _100Mb; } else if (cap & MII_ANA_10M) { - lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) ? TRUE : FALSE); + lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) != 0; lp->media = _10Mb; } @@ -2932,7 +2932,7 @@ dc21140m_autoconf(struct net_device *dev) lp->c_media = lp->media; } lp->media = INIT; - lp->tx_enable = FALSE; + lp->tx_enable = false; break; } @@ -2965,7 +2965,7 @@ dc2114x_autoconf(struct net_device *dev) case INIT: if (lp->timeout < 0) { DISABLE_IRQs; - lp->tx_enable = FALSE; + lp->tx_enable = false; lp->linkOK = 0; lp->timeout = -1; de4x5_save_skbs(dev); /* Save non transmitted skb's */ @@ -3013,7 +3013,7 @@ dc2114x_autoconf(struct net_device *dev) if (lp->timeout < 0) { mii_wr(MII_CR_ASSE | MII_CR_RAN, MII_CR, lp->phy[lp->active].addr, DE4X5_MII); } - cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, FALSE, 500); + cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, false, 500); if (cr < 0) { next_tick = cr & ~TIMER_CB; } else { @@ -3028,7 +3028,8 @@ dc2114x_autoconf(struct net_device *dev) break; case 1: - if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) { + sr = test_mii_reg(dev, MII_SR, MII_SR_ASSC, true, 2000); + if (sr < 0) { next_tick = sr & ~TIMER_CB; } else { lp->media = SPD_DET; @@ -3040,10 +3041,10 @@ dc2114x_autoconf(struct net_device *dev) if (!(anlpa & MII_ANLPA_RF) && (cap = anlpa & MII_ANLPA_TAF & ana)) { if (cap & MII_ANA_100M) { - lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) ? TRUE : FALSE); + lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) != 0; lp->media = _100Mb; } else if (cap & MII_ANA_10M) { - lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) ? TRUE : FALSE); + lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) != 0; lp->media = _10Mb; } } @@ -3222,14 +3223,14 @@ srom_map_media(struct net_device *dev) { struct de4x5_private *lp = netdev_priv(dev); - lp->fdx = 0; + lp->fdx = false; if (lp->infoblock_media == lp->media) return 0; switch(lp->infoblock_media) { case SROM_10BASETF: if (!lp->params.fdx) return -1; - lp->fdx = TRUE; + lp->fdx = true; case SROM_10BASET: if (lp->params.fdx && !lp->fdx) return -1; if ((lp->chipset == DC21140) || ((lp->chipset & ~0x00ff) == DC2114x)) { @@ -3249,7 +3250,7 @@ srom_map_media(struct net_device *dev) case SROM_100BASETF: if (!lp->params.fdx) return -1; - lp->fdx = TRUE; + lp->fdx = true; case SROM_100BASET: if (lp->params.fdx && !lp->fdx) return -1; lp->media = _100Mb; @@ -3261,7 +3262,7 @@ srom_map_media(struct net_device *dev) case SROM_100BASEFF: if (!lp->params.fdx) return -1; - lp->fdx = TRUE; + lp->fdx = true; case SROM_100BASEF: if (lp->params.fdx && !lp->fdx) return -1; lp->media = _100Mb; @@ -3297,7 +3298,7 @@ de4x5_init_connection(struct net_device *dev) spin_lock_irqsave(&lp->lock, flags); de4x5_rst_desc_ring(dev); de4x5_setup_intr(dev); - lp->tx_enable = YES; + lp->tx_enable = true; spin_unlock_irqrestore(&lp->lock, flags); outl(POLL_DEMAND, DE4X5_TPD); @@ -3336,7 +3337,7 @@ de4x5_reset_phy(struct net_device *dev) } } if (lp->useMII) { - next_tick = test_mii_reg(dev, MII_CR, MII_CR_RST, FALSE, 500); + next_tick = test_mii_reg(dev, MII_CR, MII_CR_RST, false, 500); } } else if (lp->chipset == DC21140) { PHY_HARD_RESET; @@ -3466,7 +3467,7 @@ wait_for_link(struct net_device *dev) ** */ static int -test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec) +test_mii_reg(struct net_device *dev, int reg, int mask, bool pol, long msec) { struct de4x5_private *lp = netdev_priv(dev); int test; @@ -3476,9 +3477,8 @@ test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec) lp->timeout = msec/100; } - if (pol) pol = ~0; reg = mii_rd((u_char)reg, lp->phy[lp->active].addr, DE4X5_MII) & mask; - test = (reg ^ pol) & mask; + test = (reg ^ (pol ? ~0 : 0)) & mask; if (test && --lp->timeout) { reg = 100 | TIMER_CB; @@ -3992,10 +3992,10 @@ PCI_signature(char *name, struct de4x5_private *lp) ))))))); } if (lp->chipset != DC21041) { - lp->useSROM = TRUE; /* card is not recognisably DEC */ + lp->useSROM = true; /* card is not recognisably DEC */ } } else if ((lp->chipset & ~0x00ff) == DC2114x) { - lp->useSROM = TRUE; + lp->useSROM = true; } return status; @@ -4216,7 +4216,7 @@ srom_repair(struct net_device *dev, int card) memset((char *)&lp->srom, 0, sizeof(struct de4x5_srom)); memcpy(lp->srom.ieee_addr, (char *)dev->dev_addr, ETH_ALEN); memcpy(lp->srom.info, (char *)&srom_repair_info[SMC-1], 100); - lp->useSROM = TRUE; + lp->useSROM = true; break; } @@ -4392,7 +4392,7 @@ srom_infoleaf_info(struct net_device *dev) if (lp->chipset == infoleaf_array[i].chipset) break; } if (i == INFOLEAF_SIZE) { - lp->useSROM = FALSE; + lp->useSROM = false; printk("%s: Cannot find correct chipset for SROM decoding!\n", dev->name); return -ENXIO; @@ -4409,7 +4409,7 @@ srom_infoleaf_info(struct net_device *dev) if (lp->device == *p) break; } if (i == 0) { - lp->useSROM = FALSE; + lp->useSROM = false; printk("%s: Cannot find correct PCI device [%d] for SROM decoding!\n", dev->name, lp->device); return -ENXIO; @@ -4542,7 +4542,7 @@ dc21140_infoleaf(struct net_device *dev) } lp->media = INIT; lp->tcount = 0; - lp->tx_enable = FALSE; + lp->tx_enable = false; } return next_tick & ~TIMER_CB; @@ -4577,7 +4577,7 @@ dc21142_infoleaf(struct net_device *dev) } lp->media = INIT; lp->tcount = 0; - lp->tx_enable = FALSE; + lp->tx_enable = false; } return next_tick & ~TIMER_CB; @@ -4611,7 +4611,7 @@ dc21143_infoleaf(struct net_device *dev) } lp->media = INIT; lp->tcount = 0; - lp->tx_enable = FALSE; + lp->tx_enable = false; } return next_tick & ~TIMER_CB; @@ -4650,7 +4650,7 @@ compact_infoblock(struct net_device *dev, u_char count, u_char *p) lp->asBit = 1 << ((csr6 >> 1) & 0x07); lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit; lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18); - lp->useMII = FALSE; + lp->useMII = false; de4x5_switch_mac_port(dev); } @@ -4691,7 +4691,7 @@ type0_infoblock(struct net_device *dev, u_char count, u_char *p) lp->asBit = 1 << ((csr6 >> 1) & 0x07); lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit; lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18); - lp->useMII = FALSE; + lp->useMII = false; de4x5_switch_mac_port(dev); } @@ -4731,7 +4731,7 @@ type1_infoblock(struct net_device *dev, u_char count, u_char *p) lp->ibn = 1; lp->active = *p; lp->infoblock_csr6 = OMR_MII_100; - lp->useMII = TRUE; + lp->useMII = true; lp->infoblock_media = ANS; de4x5_switch_mac_port(dev); @@ -4773,7 +4773,7 @@ type2_infoblock(struct net_device *dev, u_char count, u_char *p) lp->cache.gepc = ((s32)(TWIDDLE(p)) << 16); p += 2; lp->cache.gep = ((s32)(TWIDDLE(p)) << 16); lp->infoblock_csr6 = OMR_SIA; - lp->useMII = FALSE; + lp->useMII = false; de4x5_switch_mac_port(dev); } @@ -4814,7 +4814,7 @@ type3_infoblock(struct net_device *dev, u_char count, u_char *p) lp->active = *p; if (MOTO_SROM_BUG) lp->active = 0; lp->infoblock_csr6 = OMR_MII_100; - lp->useMII = TRUE; + lp->useMII = true; lp->infoblock_media = ANS; de4x5_switch_mac_port(dev); @@ -4856,7 +4856,7 @@ type4_infoblock(struct net_device *dev, u_char count, u_char *p) lp->asBit = 1 << ((csr6 >> 1) & 0x07); lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit; lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18); - lp->useMII = FALSE; + lp->useMII = false; de4x5_switch_mac_port(dev); } @@ -5077,7 +5077,7 @@ mii_get_phy(struct net_device *dev) int id; lp->active = 0; - lp->useMII = TRUE; + lp->useMII = true; /* Search the MII address space for possible PHY devices */ for (n=0, lp->mii_cnt=0, i=1; !((i==1) && (n==1)); i=(i+1)%DE4X5_MAX_MII) { @@ -5127,7 +5127,7 @@ mii_get_phy(struct net_device *dev) de4x5_dbg_mii(dev, k); } } - if (!lp->mii_cnt) lp->useMII = FALSE; + if (!lp->mii_cnt) lp->useMII = false; return lp->mii_cnt; } diff --git a/drivers/net/tulip/de4x5.h b/drivers/net/tulip/de4x5.h index 57226e5eb8a..12af0cc037f 100644 --- a/drivers/net/tulip/de4x5.h +++ b/drivers/net/tulip/de4x5.h @@ -893,15 +893,6 @@ #define PHYS_ADDR_ONLY 1 /* Update the physical address only */ /* -** Booleans -*/ -#define NO 0 -#define FALSE 0 - -#define YES ~0 -#define TRUE ~0 - -/* ** Adapter state */ #define INITIALISED 0 /* After h/w initialised and mem alloc'd */ diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index 4ed67ff0e81..dab74feb44b 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -181,11 +181,12 @@ udelay(5); #define __CHK_IO_SIZE(pci_id, dev_rev) \ - (( ((pci_id)==PCI_DM9132_ID) || ((dev_rev) >= 0x02000030) ) ? \ + (( ((pci_id)==PCI_DM9132_ID) || ((dev_rev) >= 0x30) ) ? \ DM9102A_IO_SIZE: DM9102_IO_SIZE) -#define CHK_IO_SIZE(pci_dev, dev_rev) \ - (__CHK_IO_SIZE(((pci_dev)->device << 16) | (pci_dev)->vendor, dev_rev)) +#define CHK_IO_SIZE(pci_dev) \ + (__CHK_IO_SIZE(((pci_dev)->device << 16) | (pci_dev)->vendor, \ + (pci_dev)->revision)) /* Sten Check */ #define DEVICE net_device @@ -205,7 +206,7 @@ struct rx_desc { struct dmfe_board_info { u32 chip_id; /* Chip vendor/Device ID */ - u32 chip_revision; /* Chip revision */ + u8 chip_revision; /* Chip revision */ struct DEVICE *next_dev; /* next device */ struct pci_dev *pdev; /* PCI device */ spinlock_t lock; @@ -359,7 +360,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, { struct dmfe_board_info *db; /* board information structure */ struct net_device *dev; - u32 dev_rev, pci_pmr; + u32 pci_pmr; int i, err; DMFE_DBUG(0, "dmfe_init_one()", 0); @@ -392,10 +393,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, goto err_out_disable; } - /* Read Chip revision */ - pci_read_config_dword(pdev, PCI_REVISION_ID, &dev_rev); - - if (pci_resource_len(pdev, 0) < (CHK_IO_SIZE(pdev, dev_rev)) ) { + if (pci_resource_len(pdev, 0) < (CHK_IO_SIZE(pdev)) ) { printk(KERN_ERR DRV_NAME ": Allocated I/O size too small\n"); err = -ENODEV; goto err_out_disable; @@ -433,7 +431,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, db->chip_id = ent->driver_data; db->ioaddr = pci_resource_start(pdev, 0); - db->chip_revision = dev_rev; + db->chip_revision = pdev->revision; db->wol_mode = 0; db->pdev = pdev; @@ -455,7 +453,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, pci_read_config_dword(pdev, 0x50, &pci_pmr); pci_pmr &= 0x70000; - if ( (pci_pmr == 0x10000) && (dev_rev == 0x02000031) ) + if ( (pci_pmr == 0x10000) && (db->chip_revision == 0x31) ) db->chip_type = 1; /* DM9102A E3 */ else db->chip_type = 0; @@ -553,7 +551,7 @@ static int dmfe_open(struct DEVICE *dev) /* CR6 operation mode decision */ if ( !chkmode || (db->chip_id == PCI_DM9132_ID) || - (db->chip_revision >= 0x02000030) ) { + (db->chip_revision >= 0x30) ) { db->cr6_data |= DMFE_TXTH_256; db->cr0_data = CR0_DEFAULT; db->dm910x_chk_mode=4; /* Enter the normal mode */ @@ -1199,9 +1197,9 @@ static void dmfe_timer(unsigned long data) tmp_cr12 = inb(db->ioaddr + DCR12); /* DM9102/DM9102A */ if ( ((db->chip_id == PCI_DM9102_ID) && - (db->chip_revision == 0x02000030)) || + (db->chip_revision == 0x30)) || ((db->chip_id == PCI_DM9132_ID) && - (db->chip_revision == 0x02000010)) ) { + (db->chip_revision == 0x10)) ) { /* DM9102A Chip */ if (tmp_cr12 & 2) link_ok = 0; diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c index ea896777bca..53efd6694e7 100644 --- a/drivers/net/tulip/interrupt.c +++ b/drivers/net/tulip/interrupt.c @@ -197,8 +197,8 @@ int tulip_poll(struct net_device *dev, int *budget) tp->rx_buffers[entry].mapping, pkt_len, PCI_DMA_FROMDEVICE); #if ! defined(__alpha__) - eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->data, - pkt_len, 0); + skb_copy_to_linear_data(skb, tp->rx_buffers[entry].skb->data, + pkt_len); skb_put(skb, pkt_len); #else memcpy(skb_put(skb, pkt_len), @@ -420,8 +420,8 @@ static int tulip_rx(struct net_device *dev) tp->rx_buffers[entry].mapping, pkt_len, PCI_DMA_FROMDEVICE); #if ! defined(__alpha__) - eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->data, - pkt_len, 0); + skb_copy_to_linear_data(skb, tp->rx_buffers[entry].skb->data, + pkt_len); skb_put(skb, pkt_len); #else memcpy(skb_put(skb, pkt_len), diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index 041af63f281..f87d76981ab 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -1155,7 +1155,7 @@ static void __devinit tulip_mwi_config (struct pci_dev *pdev, /* set or disable MWI in the standard PCI command bit. * Check for the case where mwi is desired but not available */ - if (csr0 & MWI) pci_set_mwi(pdev); + if (csr0 & MWI) pci_try_set_mwi(pdev); else pci_clear_mwi(pdev); /* read result from hardware (in case bit refused to enable) */ @@ -1238,7 +1238,6 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, }; static int last_irq; static int multiport_cnt; /* For four-port boards w/one EEPROM */ - u8 chip_rev; int i, irq; unsigned short sum; unsigned char *ee_data; @@ -1274,10 +1273,8 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, if (pdev->vendor == 0x1282 && pdev->device == 0x9100) { - u32 dev_rev; /* Read Chip revision */ - pci_read_config_dword(pdev, PCI_REVISION_ID, &dev_rev); - if(dev_rev < 0x02000030) + if (pdev->revision < 0x30) { printk(KERN_ERR PFX "skipping early DM9100 with Crc bug (use dmfe)\n"); return -ENODEV; @@ -1360,8 +1357,6 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, if (!ioaddr) goto err_out_free_res; - pci_read_config_byte (pdev, PCI_REVISION_ID, &chip_rev); - /* * initialize private data structure 'tp' * it is zeroed and aligned in alloc_etherdev @@ -1382,7 +1377,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, tp->flags = tulip_tbl[chip_idx].flags; tp->pdev = pdev; tp->base_addr = ioaddr; - tp->revision = chip_rev; + tp->revision = pdev->revision; tp->csr0 = csr0; spin_lock_init(&tp->lock); spin_lock_init(&tp->mii_lock); @@ -1399,7 +1394,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, tulip_mwi_config (pdev, dev); #else /* MWI is broken for DC21143 rev 65... */ - if (chip_idx == DC21143 && chip_rev == 65) + if (chip_idx == DC21143 && pdev->revision == 65) tp->csr0 &= ~MWI; #endif @@ -1640,7 +1635,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, #else "Port" #endif - " %#llx,", dev->name, chip_name, chip_rev, + " %#llx,", dev->name, chip_name, pdev->revision, (unsigned long long) pci_resource_start(pdev, TULIP_BAR)); pci_set_drvdata(pdev, dev); diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index 38f3b99716b..5824f6a3549 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -1232,7 +1232,7 @@ static int netdev_rx(struct net_device *dev) pci_dma_sync_single_for_cpu(np->pci_dev,np->rx_addr[entry], np->rx_skbuff[entry]->len, PCI_DMA_FROMDEVICE); - eth_copy_and_sum(skb, np->rx_skbuff[entry]->data, pkt_len, 0); + skb_copy_to_linear_data(skb, np->rx_skbuff[entry]->data, pkt_len); skb_put(skb, pkt_len); pci_dma_sync_single_for_device(np->pci_dev,np->rx_addr[entry], np->rx_skbuff[entry]->len, diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c index 2470b1ee33c..16a54e6b8d4 100644 --- a/drivers/net/tulip/xircom_cb.c +++ b/drivers/net/tulip/xircom_cb.c @@ -205,7 +205,6 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_ { struct net_device *dev = NULL; struct xircom_private *private; - unsigned char chip_rev; unsigned long flags; unsigned short tmp16; enter("xircom_probe"); @@ -224,8 +223,6 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_ pci_read_config_word (pdev,PCI_STATUS, &tmp16); pci_write_config_word (pdev, PCI_STATUS,tmp16); - pci_read_config_byte(pdev, PCI_REVISION_ID, &chip_rev); - if (!request_region(pci_resource_start(pdev, 0), 128, "xircom_cb")) { printk(KERN_ERR "xircom_probe: failed to allocate io-region\n"); return -ENODEV; @@ -286,7 +283,7 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_ goto reg_fail; } - printk(KERN_INFO "%s: Xircom cardbus revision %i at irq %i \n", dev->name, chip_rev, pdev->irq); + printk(KERN_INFO "%s: Xircom cardbus revision %i at irq %i \n", dev->name, pdev->revision, pdev->irq); /* start the transmitter to get a heartbeat */ /* TODO: send 2 dummy packets here */ transceiver_voodoo(private); @@ -1208,7 +1205,7 @@ static void investigate_read_descriptor(struct net_device *dev,struct xircom_pri goto out; } skb_reserve(skb, 2); - eth_copy_and_sum(skb, (unsigned char*)&card->rx_buffer[bufferoffset / 4], pkt_len, 0); + skb_copy_to_linear_data(skb, (unsigned char*)&card->rx_buffer[bufferoffset / 4], pkt_len); skb_put(skb, pkt_len); skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); diff --git a/drivers/net/tulip/xircom_tulip_cb.c b/drivers/net/tulip/xircom_tulip_cb.c index f6417292737..fc439f33335 100644 --- a/drivers/net/tulip/xircom_tulip_cb.c +++ b/drivers/net/tulip/xircom_tulip_cb.c @@ -524,7 +524,6 @@ static int __devinit xircom_init_one(struct pci_dev *pdev, const struct pci_devi int chip_idx = id->driver_data; long ioaddr; int i; - u8 chip_rev; /* when built into the kernel, we only print version if device is found */ #ifndef MODULE @@ -620,9 +619,8 @@ static int __devinit xircom_init_one(struct pci_dev *pdev, const struct pci_devi if (register_netdev(dev)) goto err_out_cleardev; - pci_read_config_byte(pdev, PCI_REVISION_ID, &chip_rev); printk(KERN_INFO "%s: %s rev %d at %#3lx,", - dev->name, xircom_tbl[chip_idx].chip_name, chip_rev, ioaddr); + dev->name, xircom_tbl[chip_idx].chip_name, pdev->revision, ioaddr); for (i = 0; i < 6; i++) printk("%c%2.2X", i ? ':' : ' ', dev->dev_addr[i]); printk(", IRQ %d.\n", dev->irq); @@ -1242,8 +1240,8 @@ xircom_rx(struct net_device *dev) && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { skb_reserve(skb, 2); /* 16 byte align the IP header */ #if ! defined(__alpha__) - eth_copy_and_sum(skb, bus_to_virt(tp->rx_ring[entry].buffer1), - pkt_len, 0); + skb_copy_to_linear_data(skb, bus_to_virt(tp->rx_ring[entry].buffer1), + pkt_len); skb_put(skb, pkt_len); #else memcpy(skb_put(skb, pkt_len), diff --git a/drivers/net/tun.c b/drivers/net/tun.c index a2c6caaaae9..62b2b300501 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -432,6 +432,7 @@ static void tun_setup(struct net_device *dev) init_waitqueue_head(&tun->read_wait); tun->owner = -1; + tun->group = -1; SET_MODULE_OWNER(dev); dev->open = tun_net_open; @@ -467,8 +468,11 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr) return -EBUSY; /* Check permissions */ - if (tun->owner != -1 && - current->euid != tun->owner && !capable(CAP_NET_ADMIN)) + if (((tun->owner != -1 && + current->euid != tun->owner) || + (tun->group != -1 && + current->egid != tun->group)) && + !capable(CAP_NET_ADMIN)) return -EPERM; } else if (__dev_get_by_name(ifr->ifr_name)) @@ -610,6 +614,13 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, DBG(KERN_INFO "%s: owner set to %d\n", tun->dev->name, tun->owner); break; + case TUNSETGROUP: + /* Set group of the device */ + tun->group= (gid_t) arg; + + DBG(KERN_INFO "%s: group set to %d\n", tun->dev->name, tun->group); + break; + case TUNSETLINK: /* Only allow setting the type when the interface is down */ if (tun->dev->flags & IFF_UP) { diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index f7257359412..03587205546 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -741,15 +741,6 @@ typhoon_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) spin_unlock_bh(&tp->state_lock); } -static void -typhoon_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) -{ - struct typhoon *tp = netdev_priv(dev); - spin_lock_bh(&tp->state_lock); - vlan_group_set_device(tp->vlgrp, vid, NULL); - spin_unlock_bh(&tp->state_lock); -} - static inline void typhoon_tso_fill(struct sk_buff *skb, struct transmit_ring *txRing, u32 ring_dma) @@ -1712,7 +1703,7 @@ typhoon_rx(struct typhoon *tp, struct basic_ring *rxRing, volatile u32 * ready, pci_dma_sync_single_for_cpu(tp->pdev, dma_addr, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); - eth_copy_and_sum(new_skb, skb->data, pkt_len, 0); + skb_copy_to_linear_data(new_skb, skb->data, pkt_len); pci_dma_sync_single_for_device(tp->pdev, dma_addr, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); @@ -2276,12 +2267,6 @@ need_resume: typhoon_resume(pdev); return -EBUSY; } - -static int -typhoon_enable_wake(struct pci_dev *pdev, pci_power_t state, int enable) -{ - return pci_enable_wake(pdev, state, enable); -} #endif static int __devinit @@ -2542,7 +2527,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->get_stats = typhoon_get_stats; dev->set_mac_address = typhoon_set_mac_address; dev->vlan_rx_register = typhoon_vlan_rx_register; - dev->vlan_rx_kill_vid = typhoon_vlan_rx_kill_vid; + SET_ETHTOOL_OPS(dev, &typhoon_ethtool_ops); /* We can handle scatter gather, up to 16 entries, and @@ -2645,7 +2630,6 @@ static struct pci_driver typhoon_driver = { #ifdef CONFIG_PM .suspend = typhoon_suspend, .resume = typhoon_resume, - .enable_wake = typhoon_enable_wake, #endif }; diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 18b731bb4da..e4736a3b1b7 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -2276,7 +2276,7 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth) phy_stop(phydev); /* Mask all interrupts */ - out_be32(ugeth->uccf->p_ucce, 0x00000000); + out_be32(ugeth->uccf->p_uccm, 0x00000000); /* Clear all interrupts */ out_be32(ugeth->uccf->p_ucce, 0xffffffff); diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 3de564b2314..8dc09a3790c 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -313,8 +313,8 @@ config USB_KC2190 boolean "KT Technology KC2190 based cables (InstaNet)" depends on USB_NET_CDC_SUBSET && EXPERIMENTAL help - Choose this option if you're using a host-to-host cable - with one of these chips. + Choose this option if you're using a host-to-host cable + with one of these chips. config USB_NET_ZAURUS tristate "Sharp Zaurus (stock ROMs) and compatible" diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c index 86e90c59d55..76752d84a30 100644 --- a/drivers/net/usb/catc.c +++ b/drivers/net/usb/catc.c @@ -255,7 +255,7 @@ static void catc_rx_done(struct urb *urb) if (!(skb = dev_alloc_skb(pkt_len))) return; - eth_copy_and_sum(skb, pkt_start + pkt_offset, pkt_len, 0); + skb_copy_to_linear_data(skb, pkt_start + pkt_offset, pkt_len); skb_put(skb, pkt_len); skb->protocol = eth_type_trans(skb, catc->netdev); diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 675ac99a79c..a42acc3cc60 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -144,14 +144,14 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) * modem interface from an RNDIS non-modem. */ if (rndis) { - struct usb_cdc_acm_descriptor *d; + struct usb_cdc_acm_descriptor *acm; - d = (void *) buf; - if (d->bmCapabilities) { + acm = (void *) buf; + if (acm->bmCapabilities) { dev_dbg(&intf->dev, "ACM capabilities %02x, " "not really RNDIS?\n", - d->bmCapabilities); + acm->bmCapabilities); goto bad_desc; } } diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index a6763860147..16c7a0e8785 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -414,18 +414,16 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf) dev->mii.reg_num_mask = 0x1f; /* reset */ - ret = dm_write_reg(dev, DM_NET_CTRL, 1); + dm_write_reg(dev, DM_NET_CTRL, 1); udelay(20); /* read MAC */ - ret = dm_read(dev, DM_PHY_ADDR, ETH_ALEN, dev->net->dev_addr); - if (ret < 0) { + if (dm_read(dev, DM_PHY_ADDR, ETH_ALEN, dev->net->dev_addr) < 0) { printk(KERN_ERR "Error reading MAC address\n"); ret = -ENODEV; goto out; } - /* power up phy */ dm_write_reg(dev, DM_GPR_CTRL, 1); dm_write_reg(dev, DM_GPR_DATA, 0); @@ -489,6 +487,8 @@ static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb, b3..n: packet data */ + len = skb->len; + if (skb_headroom(skb) < DM_TX_OVERHEAD) { struct sk_buff *skb2; @@ -501,10 +501,9 @@ static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb, __skb_push(skb, DM_TX_OVERHEAD); - len = skb->len; /* usbnet adds padding if length is a multiple of packet size if so, adjust length value in header */ - if ((len % dev->maxpacket) == 0) + if ((skb->len % dev->maxpacket) == 0) len++; skb->data[0] = len; diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index 60d29440f31..524dc5f5e46 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -635,7 +635,7 @@ static void kaweth_usb_receive(struct urb *urb) skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ - eth_copy_and_sum(skb, kaweth->rx_buf + 2, pkt_len, 0); + skb_copy_to_linear_data(skb, kaweth->rx_buf + 2, pkt_len); skb_put(skb, pkt_len); diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 5b16d9a1269..37bf4f2c0a4 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -192,7 +192,7 @@ static int init_status (struct usbnet *dev, struct usb_interface *intf) usb_pipeendpoint(pipe), maxp, period); } } - return 0; + return 0; } /* Passes this packet up the stack, updating its accounting. @@ -326,7 +326,7 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) if (netif_running (dev->net) && netif_device_present (dev->net) && !test_bit (EVENT_RX_HALT, &dev->flags)) { - switch (retval = usb_submit_urb (urb, GFP_ATOMIC)){ + switch (retval = usb_submit_urb (urb, GFP_ATOMIC)) { case -EPIPE: usbnet_defer_kevent (dev, EVENT_RX_HALT); break; @@ -393,8 +393,8 @@ static void rx_complete (struct urb *urb) entry->urb = NULL; switch (urb_status) { - // success - case 0: + /* success */ + case 0: if (skb->len < dev->net->hard_header_len) { entry->state = rx_cleanup; dev->stats.rx_errors++; @@ -404,28 +404,30 @@ static void rx_complete (struct urb *urb) } break; - // stalls need manual reset. this is rare ... except that - // when going through USB 2.0 TTs, unplug appears this way. - // we avoid the highspeed version of the ETIMEOUT/EILSEQ - // storm, recovering as needed. - case -EPIPE: + /* stalls need manual reset. this is rare ... except that + * when going through USB 2.0 TTs, unplug appears this way. + * we avoid the highspeed version of the ETIMEOUT/EILSEQ + * storm, recovering as needed. + */ + case -EPIPE: dev->stats.rx_errors++; usbnet_defer_kevent (dev, EVENT_RX_HALT); // FALLTHROUGH - // software-driven interface shutdown - case -ECONNRESET: // async unlink - case -ESHUTDOWN: // hardware gone + /* software-driven interface shutdown */ + case -ECONNRESET: /* async unlink */ + case -ESHUTDOWN: /* hardware gone */ if (netif_msg_ifdown (dev)) devdbg (dev, "rx shutdown, code %d", urb_status); goto block; - // we get controller i/o faults during khubd disconnect() delays. - // throttle down resubmits, to avoid log floods; just temporarily, - // so we still recover when the fault isn't a khubd delay. - case -EPROTO: - case -ETIME: - case -EILSEQ: + /* we get controller i/o faults during khubd disconnect() delays. + * throttle down resubmits, to avoid log floods; just temporarily, + * so we still recover when the fault isn't a khubd delay. + */ + case -EPROTO: + case -ETIME: + case -EILSEQ: dev->stats.rx_errors++; if (!timer_pending (&dev->delay)) { mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES); @@ -438,12 +440,12 @@ block: urb = NULL; break; - // data overrun ... flush fifo? - case -EOVERFLOW: + /* data overrun ... flush fifo? */ + case -EOVERFLOW: dev->stats.rx_over_errors++; // FALLTHROUGH - default: + default: entry->state = rx_cleanup; dev->stats.rx_errors++; if (netif_msg_rx_err (dev)) @@ -471,22 +473,22 @@ static void intr_complete (struct urb *urb) int status = urb->status; switch (status) { - /* success */ - case 0: + /* success */ + case 0: dev->driver_info->status(dev, urb); break; - /* software-driven interface shutdown */ - case -ENOENT: // urb killed - case -ESHUTDOWN: // hardware gone + /* software-driven interface shutdown */ + case -ENOENT: /* urb killed */ + case -ESHUTDOWN: /* hardware gone */ if (netif_msg_ifdown (dev)) devdbg (dev, "intr shutdown, code %d", status); return; - /* NOTE: not throttling like RX/TX, since this endpoint - * already polls infrequently - */ - default: + /* NOTE: not throttling like RX/TX, since this endpoint + * already polls infrequently + */ + default: devdbg (dev, "intr status %d", status); break; } @@ -569,9 +571,9 @@ static int usbnet_stop (struct net_device *net) temp = unlink_urbs (dev, &dev->txq) + unlink_urbs (dev, &dev->rxq); // maybe wait for deletions to finish. - while (!skb_queue_empty(&dev->rxq) && - !skb_queue_empty(&dev->txq) && - !skb_queue_empty(&dev->done)) { + while (!skb_queue_empty(&dev->rxq) + && !skb_queue_empty(&dev->txq) + && !skb_queue_empty(&dev->done)) { msleep(UNLINK_TIMEOUT_MS); if (netif_msg_ifdown (dev)) devdbg (dev, "waited for %d urb completions", temp); @@ -953,11 +955,14 @@ static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net) /* don't assume the hardware handles USB_ZERO_PACKET * NOTE: strictly conforming cdc-ether devices should expect * the ZLP here, but ignore the one-byte packet. - * - * FIXME zero that byte, if it doesn't require a new skb. */ - if ((length % dev->maxpacket) == 0) + if ((length % dev->maxpacket) == 0) { urb->transfer_buffer_length++; + if (skb_tailroom(skb)) { + skb->data[skb->len] = 0; + __skb_put(skb, 1); + } + } spin_lock_irqsave (&dev->txq.lock, flags); @@ -1008,16 +1013,16 @@ static void usbnet_bh (unsigned long param) while ((skb = skb_dequeue (&dev->done))) { entry = (struct skb_data *) skb->cb; switch (entry->state) { - case rx_done: + case rx_done: entry->state = rx_cleanup; rx_process (dev, skb); continue; - case tx_done: - case rx_cleanup: + case tx_done: + case rx_cleanup: usb_free_urb (entry->urb); dev_kfree_skb (skb); continue; - default: + default: devdbg (dev, "bogus skb state %d", entry->state); } } @@ -1208,7 +1213,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) status = 0; } - if (status == 0 && dev->status) + if (status >= 0 && dev->status) status = init_status (dev, udev); if (status < 0) goto out3; diff --git a/drivers/net/usb/usbnet.h b/drivers/net/usb/usbnet.h index a3f8b9e7bc0..a6c5820767d 100644 --- a/drivers/net/usb/usbnet.h +++ b/drivers/net/usb/usbnet.h @@ -47,7 +47,7 @@ struct usbnet { unsigned long data [5]; u32 xid; u32 hard_mtu; /* count any extra framing */ - size_t rx_urb_size; /* size for rx urbs */ + size_t rx_urb_size; /* size for rx urbs */ struct mii_if_info mii; /* various kinds of pending driver work */ @@ -85,7 +85,7 @@ struct driver_info { #define FLAG_NO_SETINT 0x0010 /* device can't set_interface() */ #define FLAG_ETHER 0x0020 /* maybe use "eth%d" names */ -#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */ +#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */ /* init device ... can sleep, or cause probe() failure */ int (*bind)(struct usbnet *, struct usb_interface *); @@ -146,9 +146,9 @@ extern void usbnet_cdc_unbind (struct usbnet *, struct usb_interface *); /* CDC and RNDIS support the same host-chosen packet filters for IN transfers */ #define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \ - |USB_CDC_PACKET_TYPE_ALL_MULTICAST \ - |USB_CDC_PACKET_TYPE_PROMISCUOUS \ - |USB_CDC_PACKET_TYPE_DIRECTED) + |USB_CDC_PACKET_TYPE_ALL_MULTICAST \ + |USB_CDC_PACKET_TYPE_PROMISCUOUS \ + |USB_CDC_PACKET_TYPE_DIRECTED) /* we record the state for each of our queued skbs */ diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index adea290a9d5..f51c2c138f1 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -622,7 +622,6 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, struct net_device *dev; struct rhine_private *rp; int i, rc; - u8 pci_rev; u32 quirks; long pioaddr; long memaddr; @@ -642,27 +641,25 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, printk(version); #endif - pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); - io_size = 256; phy_id = 0; quirks = 0; name = "Rhine"; - if (pci_rev < VTunknown0) { + if (pdev->revision < VTunknown0) { quirks = rqRhineI; io_size = 128; } - else if (pci_rev >= VT6102) { + else if (pdev->revision >= VT6102) { quirks = rqWOL | rqForceReset; - if (pci_rev < VT6105) { + if (pdev->revision < VT6105) { name = "Rhine II"; quirks |= rqStatusWBRace; /* Rhine-II exclusive */ } else { phy_id = 1; /* Integrated PHY, phy_id fixed to 1 */ - if (pci_rev >= VT6105_B0) + if (pdev->revision >= VT6105_B0) quirks |= rq6patterns; - if (pci_rev < VT6105M) + if (pdev->revision < VT6105M) name = "Rhine III"; else name = "Rhine III (Management Adapter)"; @@ -1492,9 +1489,9 @@ static int rhine_rx(struct net_device *dev, int limit) rp->rx_buf_sz, PCI_DMA_FROMDEVICE); - eth_copy_and_sum(skb, + skb_copy_to_linear_data(skb, rp->rx_skbuff[entry]->data, - pkt_len, 0); + pkt_len); skb_put(skb, pkt_len); pci_dma_sync_single_for_device(rp->pdev, rp->rx_skbuff_dma[entry], diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 25b75b61518..f331843d110 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -890,8 +890,7 @@ static void __devinit velocity_init_info(struct pci_dev *pdev, static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pci_dev *pdev) { - if (pci_read_config_byte(pdev, PCI_REVISION_ID, &vptr->rev_id) < 0) - return -EIO; + vptr->rev_id = pdev->revision; pci_set_master(pdev); @@ -1562,7 +1561,7 @@ static void velocity_print_link_status(struct velocity_info *vptr) if (vptr->mii_status & VELOCITY_LINK_FAIL) { VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: failed to detect cable link\n", vptr->dev->name); } else if (vptr->options.spd_dpx == SPD_DPX_AUTO) { - VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link autonegation", vptr->dev->name); + VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link auto-negotiation", vptr->dev->name); if (vptr->mii_status & VELOCITY_SPEED_1000) VELOCITY_PRT(MSG_LEVEL_INFO, " speed 1000M bps"); diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c index 999bf71937c..ec1c556a47c 100644 --- a/drivers/net/wan/pc300_drv.c +++ b/drivers/net/wan/pc300_drv.c @@ -3439,7 +3439,6 @@ static int __devinit cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int first_time = 1; - ucchar cpc_rev_id; int err, eeprom_outdated = 0; ucshort device_id; pc300_t *card; @@ -3480,7 +3479,6 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) card->hw.falcsize = pci_resource_len(pdev, 4); card->hw.plxphys = pci_resource_start(pdev, 5); card->hw.plxsize = pci_resource_len(pdev, 5); - pci_read_config_byte(pdev, PCI_REVISION_ID, &cpc_rev_id); switch (device_id) { case PCI_DEVICE_ID_PC300_RX_1: @@ -3498,7 +3496,7 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } #ifdef PC300_DEBUG_PCI printk("cpc (bus=0x0%x,pci_id=0x%x,", pdev->bus->number, pdev->devfn); - printk("rev_id=%d) IRQ%d\n", cpc_rev_id, card->hw.irq); + printk("rev_id=%d) IRQ%d\n", pdev->revision, card->hw.irq); printk("cpc:found ramaddr=0x%08lx plxaddr=0x%08lx " "ctladdr=0x%08lx falcaddr=0x%08lx\n", card->hw.ramphys, card->hw.plxphys, card->hw.scaphys, diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c index aff05dba720..dfbd3b00f03 100644 --- a/drivers/net/wan/pc300too.c +++ b/drivers/net/wan/pc300too.c @@ -311,7 +311,6 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { card_t *card; - u8 rev_id; u32 __iomem *p; int i; u32 ramsize; @@ -366,7 +365,6 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev, return -ENOMEM; } - pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); if (pci_resource_len(pdev, 0) != PC300_PLX_SIZE || pci_resource_len(pdev, 2) != PC300_SCA_SIZE || pci_resource_len(pdev, 3) < 16384) { diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c index ca06a00d9d8..7f720de2e9f 100644 --- a/drivers/net/wan/pci200syn.c +++ b/drivers/net/wan/pci200syn.c @@ -289,7 +289,6 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { card_t *card; - u8 rev_id; u32 __iomem *p; int i; u32 ramsize; @@ -330,7 +329,6 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev, return -ENOMEM; } - pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); if (pci_resource_len(pdev, 0) != PCI200SYN_PLX_SIZE || pci_resource_len(pdev, 2) != PCI200SYN_SCA_SIZE || pci_resource_len(pdev, 3) < 16384) { diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index e3f5bb0fe60..ae27af0141c 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -266,16 +266,23 @@ config IPW2200_DEBUG If you are not sure, say N here. -config LIBERTAS_USB - tristate "Marvell Libertas 8388 802.11a/b/g cards" - depends on USB && WLAN_80211 +config LIBERTAS + tristate "Marvell 8xxx Libertas WLAN driver support" + depends on WLAN_80211 + select IEEE80211 select FW_LOADER ---help--- + A library for Marvell Libertas 8xxx devices. + +config LIBERTAS_USB + tristate "Marvell Libertas 8388 USB 802.11b/g cards" + depends on LIBERTAS && USB + ---help--- A driver for Marvell Libertas 8388 USB devices. -config LIBERTAS_USB_DEBUG - bool "Enable full debugging output in the Libertas USB module." - depends on LIBERTAS_USB +config LIBERTAS_DEBUG + bool "Enable full debugging output in the Libertas module." + depends on LIBERTAS ---help--- Debugging support. @@ -539,6 +546,18 @@ config USB_ZD1201 To compile this driver as a module, choose M here: the module will be called zd1201. +config RTL8187 + tristate "Realtek 8187 USB support" + depends on MAC80211 && USB && WLAN_80211 && EXPERIMENTAL + select EEPROM_93CX6 + ---help--- + This is a driver for RTL8187 based cards. + These are USB based chips found in cards such as: + + Netgear WG111v2 + + Thanks to Realtek for their support! + source "drivers/net/wireless/hostap/Kconfig" source "drivers/net/wireless/bcm43xx/Kconfig" source "drivers/net/wireless/zd1211rw/Kconfig" diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index d2124602263..ef35bc6c4a2 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -44,3 +44,6 @@ obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o obj-$(CONFIG_USB_ZD1201) += zd1201.o obj-$(CONFIG_LIBERTAS_USB) += libertas/ + +rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o +obj-$(CONFIG_RTL8187) += rtl8187.o diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index ef6b253a92c..c5d6753a55e 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3741,10 +3741,8 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm) &bcm->board_type); if (err) goto err_iounmap; - err = bcm43xx_pci_read_config16(bcm, PCI_REVISION_ID, - &bcm->board_revision); - if (err) - goto err_iounmap; + + bcm->board_revision = bcm->pci_dev->revision; err = bcm43xx_chipset_attach(bcm); if (err) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index b37f1e34870..d779199c30d 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -1638,7 +1638,7 @@ void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm, return; } - if (phy->analog > 1) { + if (phy->analog == 1) { value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C; value |= (baseband_attenuation << 2) & 0x003C; } else { diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index 5b3abd54d0e..90900525379 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c @@ -326,7 +326,6 @@ static int ap_control_proc_read(char *page, char **start, off_t off, char *p = page; struct ap_data *ap = (struct ap_data *) data; char *policy_txt; - struct list_head *ptr; struct mac_entry *entry; if (off != 0) { @@ -352,14 +351,12 @@ static int ap_control_proc_read(char *page, char **start, off_t off, p += sprintf(p, "MAC entries: %u\n", ap->mac_restrictions.entries); p += sprintf(p, "MAC list:\n"); spin_lock_bh(&ap->mac_restrictions.lock); - for (ptr = ap->mac_restrictions.mac_list.next; - ptr != &ap->mac_restrictions.mac_list; ptr = ptr->next) { + list_for_each_entry(entry, &ap->mac_restrictions.mac_list, list) { if (p - page > PAGE_SIZE - 80) { p += sprintf(p, "All entries did not fit one page.\n"); break; } - entry = list_entry(ptr, struct mac_entry, list); p += sprintf(p, MACSTR "\n", MAC2STR(entry->addr)); } spin_unlock_bh(&ap->mac_restrictions.lock); @@ -413,7 +410,6 @@ int ap_control_del_mac(struct mac_restrictions *mac_restrictions, u8 *mac) static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions, u8 *mac) { - struct list_head *ptr; struct mac_entry *entry; int found = 0; @@ -421,10 +417,7 @@ static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions, return 0; spin_lock_bh(&mac_restrictions->lock); - for (ptr = mac_restrictions->mac_list.next; - ptr != &mac_restrictions->mac_list; ptr = ptr->next) { - entry = list_entry(ptr, struct mac_entry, list); - + list_for_each_entry(entry, &mac_restrictions->mac_list, list) { if (memcmp(entry->addr, mac, ETH_ALEN) == 0) { found = 1; break; @@ -519,7 +512,7 @@ static int prism2_ap_proc_read(char *page, char **start, off_t off, { char *p = page; struct ap_data *ap = (struct ap_data *) data; - struct list_head *ptr; + struct sta_info *sta; int i; if (off > PROC_LIMIT) { @@ -529,9 +522,7 @@ static int prism2_ap_proc_read(char *page, char **start, off_t off, p += sprintf(p, "# BSSID CHAN SIGNAL NOISE RATE SSID FLAGS\n"); spin_lock_bh(&ap->sta_table_lock); - for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) { - struct sta_info *sta = (struct sta_info *) ptr; - + list_for_each_entry(sta, &ap->sta_list, list) { if (!sta->ap) continue; @@ -861,7 +852,7 @@ void hostap_init_ap_proc(local_info_t *local) void hostap_free_data(struct ap_data *ap) { - struct list_head *n, *ptr; + struct sta_info *n, *sta; if (ap == NULL || !ap->initialized) { printk(KERN_DEBUG "hostap_free_data: ap has not yet been " @@ -875,8 +866,7 @@ void hostap_free_data(struct ap_data *ap) ap->crypt = ap->crypt_priv = NULL; #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - list_for_each_safe(ptr, n, &ap->sta_list) { - struct sta_info *sta = list_entry(ptr, struct sta_info, list); + list_for_each_entry_safe(sta, n, &ap->sta_list, list) { ap_sta_hash_del(ap, sta); list_del(&sta->list); if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local) @@ -2704,6 +2694,8 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx) if (hdr->addr1[0] & 0x01) { /* broadcast/multicast frame - no AP related processing */ + if (local->ap->num_sta <= 0) + ret = AP_TX_DROP; goto out; } @@ -3198,15 +3190,14 @@ int hostap_update_rx_stats(struct ap_data *ap, void hostap_update_rates(local_info_t *local) { - struct list_head *ptr; + struct sta_info *sta; struct ap_data *ap = local->ap; if (!ap) return; spin_lock_bh(&ap->sta_table_lock); - for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) { - struct sta_info *sta = (struct sta_info *) ptr; + list_for_each_entry(sta, &ap->sta_list, list) { prism2_check_tx_rates(sta); } spin_unlock_bh(&ap->sta_table_lock); @@ -3242,11 +3233,10 @@ void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent, void hostap_add_wds_links(local_info_t *local) { struct ap_data *ap = local->ap; - struct list_head *ptr; + struct sta_info *sta; spin_lock_bh(&ap->sta_table_lock); - list_for_each(ptr, &ap->sta_list) { - struct sta_info *sta = list_entry(ptr, struct sta_info, list); + list_for_each_entry(sta, &ap->sta_list, list) { if (sta->ap) hostap_wds_link_oper(local, sta->addr, WDS_ADD); } diff --git a/drivers/net/wireless/hostap/hostap_config.h b/drivers/net/wireless/hostap/hostap_config.h index c090a5aebb5..30acd39d76a 100644 --- a/drivers/net/wireless/hostap/hostap_config.h +++ b/drivers/net/wireless/hostap/hostap_config.h @@ -1,8 +1,6 @@ #ifndef HOSTAP_CONFIG_H #define HOSTAP_CONFIG_H -#define PRISM2_VERSION "0.4.4-kernel" - /* In the previous versions of Host AP driver, support for user space version * of IEEE 802.11 management (hostapd) used to be disabled in the default * configuration. From now on, support for hostapd is always included and it is diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index ee1532b62e4..30e723f6597 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -22,7 +22,6 @@ #include "hostap_wlan.h" -static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)"; static dev_info_t dev_info = "hostap_cs"; MODULE_AUTHOR("Jouni Malinen"); @@ -30,7 +29,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN " "cards (PC Card)."); MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PC Card)"); MODULE_LICENSE("GPL"); -MODULE_VERSION(PRISM2_VERSION); static int ignore_cis_vcc; @@ -910,14 +908,12 @@ static struct pcmcia_driver hostap_driver = { static int __init init_prism2_pccard(void) { - printk(KERN_INFO "%s: %s\n", dev_info, version); return pcmcia_register_driver(&hostap_driver); } static void __exit exit_prism2_pccard(void) { pcmcia_unregister_driver(&hostap_driver); - printk(KERN_INFO "%s: Driver unloaded\n", dev_info); } diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c index cdea7f71b9e..8c71077d653 100644 --- a/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/hostap/hostap_ioctl.c @@ -3893,8 +3893,6 @@ static void prism2_get_drvinfo(struct net_device *dev, local = iface->local; strncpy(info->driver, "hostap", sizeof(info->driver) - 1); - strncpy(info->version, PRISM2_VERSION, - sizeof(info->version) - 1); snprintf(info->fw_version, sizeof(info->fw_version) - 1, "%d.%d.%d", (local->sta_fw_ver >> 16) & 0xff, (local->sta_fw_ver >> 8) & 0xff, diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c index 4743426cf6a..446de51bab7 100644 --- a/drivers/net/wireless/hostap/hostap_main.c +++ b/drivers/net/wireless/hostap/hostap_main.c @@ -37,7 +37,6 @@ MODULE_AUTHOR("Jouni Malinen"); MODULE_DESCRIPTION("Host AP common routines"); MODULE_LICENSE("GPL"); -MODULE_VERSION(PRISM2_VERSION); #define TX_TIMEOUT (2 * HZ) diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c index db4899ed4bb..7da3664b851 100644 --- a/drivers/net/wireless/hostap/hostap_pci.c +++ b/drivers/net/wireless/hostap/hostap_pci.c @@ -20,7 +20,6 @@ #include "hostap_wlan.h" -static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)"; static char *dev_info = "hostap_pci"; @@ -29,7 +28,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2.5-based 802.11 wireless LAN " "PCI cards."); MODULE_SUPPORTED_DEVICE("Intersil Prism2.5-based WLAN PCI cards"); MODULE_LICENSE("GPL"); -MODULE_VERSION(PRISM2_VERSION); /* struct local_info::hw_priv */ @@ -455,15 +453,11 @@ static struct pci_driver prism2_pci_drv_id = { .suspend = prism2_pci_suspend, .resume = prism2_pci_resume, #endif /* CONFIG_PM */ - /* Linux 2.4.6 added save_state and enable_wake that are not used here - */ }; static int __init init_prism2_pci(void) { - printk(KERN_INFO "%s: %s\n", dev_info, version); - return pci_register_driver(&prism2_pci_drv_id); } @@ -471,7 +465,6 @@ static int __init init_prism2_pci(void) static void __exit exit_prism2_pci(void) { pci_unregister_driver(&prism2_pci_drv_id); - printk(KERN_INFO "%s: Driver unloaded\n", dev_info); } diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c index f0fd5ecdb24..040dc3e3641 100644 --- a/drivers/net/wireless/hostap/hostap_plx.c +++ b/drivers/net/wireless/hostap/hostap_plx.c @@ -23,7 +23,6 @@ #include "hostap_wlan.h" -static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)"; static char *dev_info = "hostap_plx"; @@ -32,7 +31,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN " "cards (PLX)."); MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PLX)"); MODULE_LICENSE("GPL"); -MODULE_VERSION(PRISM2_VERSION); static int ignore_cis; @@ -615,16 +613,11 @@ static struct pci_driver prism2_plx_drv_id = { .id_table = prism2_plx_id_table, .probe = prism2_plx_probe, .remove = prism2_plx_remove, - .suspend = NULL, - .resume = NULL, - .enable_wake = NULL }; static int __init init_prism2_plx(void) { - printk(KERN_INFO "%s: %s\n", dev_info, version); - return pci_register_driver(&prism2_plx_drv_id); } @@ -632,7 +625,6 @@ static int __init init_prism2_plx(void) static void __exit exit_prism2_plx(void) { pci_unregister_driver(&prism2_plx_drv_id); - printk(KERN_INFO "%s: Driver unloaded\n", dev_info); } diff --git a/drivers/net/wireless/libertas/11d.c b/drivers/net/wireless/libertas/11d.c index e0ecc4d483b..4cf0ff7b833 100644 --- a/drivers/net/wireless/libertas/11d.c +++ b/drivers/net/wireless/libertas/11d.c @@ -95,7 +95,7 @@ static u8 wlan_get_chan_11d(u8 band, u8 firstchan, u8 nrchan, u8 * chan) for (i = 0; i < cfp_no; i++) { if ((cfp + i)->channel == firstchan) { - lbs_pr_debug(1, "firstchan found\n"); + lbs_deb_11d("firstchan found\n"); break; } } @@ -129,12 +129,12 @@ static u8 wlan_channel_known_11d(u8 chan, for (i = 0; i < nr_chan; i++) { if (chan == chanpwr[i].chan) { - lbs_pr_debug(1, "11D: Found Chan:%d\n", chan); + lbs_deb_11d("11D: Found Chan:%d\n", chan); return 1; } } - lbs_pr_debug(1, "11D: Not Find Chan:%d\n", chan); + lbs_deb_11d("11D: Not Find Chan:%d\n", chan); return 0; } @@ -174,7 +174,7 @@ static int generate_domain_info_11d(struct parsed_region_chan_11d memcpy(domaininfo->countrycode, parsed_region_chan->countrycode, COUNTRY_CODE_LEN); - lbs_pr_debug(1, "11D:nrchan=%d\n", nr_chan); + lbs_deb_11d("11D:nrchan=%d\n", nr_chan); lbs_dbg_hex("11D:parsed_region_chan:", (char *)parsed_region_chan, sizeof(struct parsed_region_chan_11d)); @@ -212,7 +212,7 @@ static int generate_domain_info_11d(struct parsed_region_chan_11d } domaininfo->nr_subband = nr_subband; - lbs_pr_debug(1, "nr_subband=%x\n", domaininfo->nr_subband); + lbs_deb_11d("nr_subband=%x\n", domaininfo->nr_subband); lbs_dbg_hex("11D:domaininfo:", (char *)domaininfo, COUNTRY_CODE_LEN + 1 + sizeof(struct ieeetypes_subbandset) * nr_subband); @@ -233,13 +233,13 @@ static void wlan_generate_parsed_region_chan_11d(struct region_channel * region_ struct chan_freq_power *cfp; if (region_chan == NULL) { - lbs_pr_debug(1, "11D: region_chan is NULL\n"); + lbs_deb_11d("11D: region_chan is NULL\n"); return; } cfp = region_chan->CFP; if (cfp == NULL) { - lbs_pr_debug(1, "11D: cfp equal NULL \n"); + lbs_deb_11d("11D: cfp equal NULL \n"); return; } @@ -248,19 +248,19 @@ static void wlan_generate_parsed_region_chan_11d(struct region_channel * region_ memcpy(parsed_region_chan->countrycode, wlan_code_2_region(region_chan->region), COUNTRY_CODE_LEN); - lbs_pr_debug(1, "11D: region[0x%x] band[%d]\n", parsed_region_chan->region, + lbs_deb_11d("11D: region[0x%x] band[%d]\n", parsed_region_chan->region, parsed_region_chan->band); for (i = 0; i < region_chan->nrcfp; i++, cfp++) { parsed_region_chan->chanpwr[i].chan = cfp->channel; parsed_region_chan->chanpwr[i].pwr = cfp->maxtxpower; - lbs_pr_debug(1, "11D: Chan[%d] Pwr[%d]\n", + lbs_deb_11d("11D: Chan[%d] Pwr[%d]\n", parsed_region_chan->chanpwr[i].chan, parsed_region_chan->chanpwr[i].pwr); } parsed_region_chan->nr_chan = region_chan->nrcfp; - lbs_pr_debug(1, "11D: nrchan[%d]\n", parsed_region_chan->nr_chan); + lbs_deb_11d("11D: nrchan[%d]\n", parsed_region_chan->nr_chan); return; } @@ -277,8 +277,9 @@ static u8 wlan_region_chan_supported_11d(u8 region, u8 band, u8 chan) struct chan_freq_power *cfp; int cfp_no; u8 idx; + int ret = 0; - ENTER(); + lbs_deb_enter(LBS_DEB_11D); cfp = libertas_get_region_cfp_table(region, band, &cfp_no); if (cfp == NULL) @@ -288,16 +289,19 @@ static u8 wlan_region_chan_supported_11d(u8 region, u8 band, u8 chan) if (chan == (cfp + idx)->channel) { /* If Mrvl Chip Supported? */ if ((cfp + idx)->unsupported) { - return 0; + ret = 0; } else { - return 1; + ret = 1; } + goto done; } } /*chan is not in the region table */ - LEAVE(); - return 0; + +done: + lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret); + return ret; } /** @@ -321,7 +325,7 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset* u8 j, i; - ENTER(); + lbs_deb_enter(LBS_DEB_11D); /*validation Rules: 1. valid region Code @@ -337,15 +341,14 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset* if ((*(countryinfo->countrycode)) == 0 || (countryinfo->len <= COUNTRY_CODE_LEN)) { /* No region Info or Wrong region info: treat as No 11D info */ - LEAVE(); - return 0; + goto done; } /*Step1: check region_code */ parsed_region_chan->region = region = wlan_region_2_code(countryinfo->countrycode); - lbs_pr_debug(1, "regioncode=%x\n", (u8) parsed_region_chan->region); + lbs_deb_11d("regioncode=%x\n", (u8) parsed_region_chan->region); lbs_dbg_hex("CountryCode:", (char *)countryinfo->countrycode, COUNTRY_CODE_LEN); @@ -361,7 +364,7 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset* if (countryinfo->subband[j].firstchan <= lastchan) { /*Step2&3. Check First Chan Num increment and no overlap */ - lbs_pr_debug(1, "11D: Chan[%d>%d] Overlap\n", + lbs_deb_11d("11D: Chan[%d>%d] Overlap\n", countryinfo->subband[j].firstchan, lastchan); continue; } @@ -374,7 +377,7 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset* if (!wlan_get_chan_11d(band, firstchan, i, &curchan)) { /* Chan is not found in UN table */ - lbs_pr_debug(1, "chan is not supported: %d \n", i); + lbs_deb_11d("chan is not supported: %d \n", i); break; } @@ -389,7 +392,7 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset* idx++; } else { /*not supported and ignore the chan */ - lbs_pr_debug(1, + lbs_deb_11d( "11D:i[%d] chan[%d] unsupported in region[%x] band[%d]\n", i, curchan, region, band); } @@ -401,11 +404,12 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset* parsed_region_chan->nr_chan = idx; - lbs_pr_debug(1, "nrchan=%x\n", parsed_region_chan->nr_chan); + lbs_deb_11d("nrchan=%x\n", parsed_region_chan->nr_chan); lbs_dbg_hex("11D:parsed_region_chan:", (u8 *) parsed_region_chan, 2 + COUNTRY_CODE_LEN + sizeof(struct parsed_region_chan_11d) * idx); - LEAVE(); +done: + lbs_deb_enter(LBS_DEB_11D); return 0; } @@ -420,16 +424,16 @@ u8 libertas_get_scan_type_11d(u8 chan, { u8 scan_type = cmd_scan_type_passive; - ENTER(); + lbs_deb_enter(LBS_DEB_11D); if (wlan_channel_known_11d(chan, parsed_region_chan)) { - lbs_pr_debug(1, "11D: Found and do Active Scan\n"); + lbs_deb_11d("11D: Found and do Active Scan\n"); scan_type = cmd_scan_type_active; } else { - lbs_pr_debug(1, "11D: Not Find and do Passive Scan\n"); + lbs_deb_11d("11D: Not Find and do Passive Scan\n"); } - LEAVE(); + lbs_deb_leave_args(LBS_DEB_11D, "ret scan_type %d", scan_type); return scan_type; } @@ -456,7 +460,7 @@ static int wlan_enable_11d(wlan_private * priv, u8 flag) OID_802_11D_ENABLE, &priv->adapter->enable11d); if (ret) - lbs_pr_debug(1, "11D: Fail to enable 11D \n"); + lbs_deb_11d("11D: Fail to enable 11D \n"); return 0; } @@ -471,7 +475,7 @@ static int set_domain_info_11d(wlan_private * priv) int ret; if (!priv->adapter->enable11d) { - lbs_pr_debug(1, "11D: dnld domain Info with 11d disabled\n"); + lbs_deb_11d("11D: dnld domain Info with 11d disabled\n"); return 0; } @@ -479,7 +483,7 @@ static int set_domain_info_11d(wlan_private * priv) cmd_act_set, cmd_option_waitforrsp, 0, NULL); if (ret) - lbs_pr_debug(1, "11D: Fail to dnld domain Info\n"); + lbs_deb_11d("11D: Fail to dnld domain Info\n"); return ret; } @@ -501,7 +505,7 @@ int libertas_set_universaltable(wlan_private * priv, u8 band) adapter->universal_channel[i].nrcfp = sizeof(channel_freq_power_UN_BG) / size; - lbs_pr_debug(1, "11D: BG-band nrcfp=%d\n", + lbs_deb_11d("11D: BG-band nrcfp=%d\n", adapter->universal_channel[i].nrcfp); adapter->universal_channel[i].CFP = channel_freq_power_UN_BG; @@ -531,9 +535,9 @@ int libertas_cmd_802_11d_domain_info(wlan_private * priv, wlan_adapter *adapter = priv->adapter; u8 nr_subband = adapter->domainreg.nr_subband; - ENTER(); + lbs_deb_enter(LBS_DEB_11D); - lbs_pr_debug(1, "nr_subband=%x\n", nr_subband); + lbs_deb_11d("nr_subband=%x\n", nr_subband); cmd->command = cpu_to_le16(cmdno); pdomaininfo->action = cpu_to_le16(cmdoption); @@ -542,8 +546,7 @@ int libertas_cmd_802_11d_domain_info(wlan_private * priv, cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN); lbs_dbg_hex("11D: 802_11D_DOMAIN_INFO:", (u8 *) cmd, (int)(cmd->size)); - LEAVE(); - return 0; + goto done; } domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN); @@ -567,10 +570,10 @@ int libertas_cmd_802_11d_domain_info(wlan_private * priv, cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN); } - lbs_dbg_hex("11D:802_11D_DOMAIN_INFO:", (u8 *) cmd, (int)(cmd->size)); - - LEAVE(); + lbs_dbg_hex("11D:802_11D_DOMAIN_INFO:", (u8 *) cmd, le16_to_cpu(cmd->size)); +done: + lbs_deb_enter(LBS_DEB_11D); return 0; } @@ -585,17 +588,17 @@ int libertas_cmd_enable_11d(wlan_private * priv, struct iwreq *wrq) int data = 0; int *val; - ENTER(); + lbs_deb_enter(LBS_DEB_11D); data = SUBCMD_DATA(wrq); - lbs_pr_debug(1, "enable 11D: %s\n", + lbs_deb_11d("enable 11D: %s\n", (data == 1) ? "enable" : "Disable"); wlan_enable_11d(priv, data); val = (int *)wrq->u.name; *val = priv->adapter->enable11d; - LEAVE(); + lbs_deb_enter(LBS_DEB_11D); return 0; } @@ -608,25 +611,24 @@ int libertas_cmd_enable_11d(wlan_private * priv, struct iwreq *wrq) int libertas_ret_802_11d_domain_info(wlan_private * priv, struct cmd_ds_command *resp) { - struct cmd_ds_802_11d_domain_info - *domaininfo = &resp->params.domaininforesp; + struct cmd_ds_802_11d_domain_info *domaininfo = &resp->params.domaininforesp; struct mrvlietypes_domainparamset *domain = &domaininfo->domain; u16 action = le16_to_cpu(domaininfo->action); s16 ret = 0; u8 nr_subband = 0; - ENTER(); + lbs_deb_enter(LBS_DEB_11D); lbs_dbg_hex("11D DOMAIN Info Rsp Data:", (u8 *) resp, (int)le16_to_cpu(resp->size)); - nr_subband = (domain->header.len - 3) / sizeof(struct ieeetypes_subbandset); - /* countrycode 3 bytes */ + nr_subband = (le16_to_cpu(domain->header.len) - COUNTRY_CODE_LEN) / + sizeof(struct ieeetypes_subbandset); - lbs_pr_debug(1, "11D Domain Info Resp: nr_subband=%d\n", nr_subband); + lbs_deb_11d("11D Domain Info Resp: nr_subband=%d\n", nr_subband); if (nr_subband > MRVDRV_MAX_SUBBAND_802_11D) { - lbs_pr_debug(1, "Invalid Numrer of Subband returned!!\n"); + lbs_deb_11d("Invalid Numrer of Subband returned!!\n"); return -1; } @@ -637,12 +639,12 @@ int libertas_ret_802_11d_domain_info(wlan_private * priv, case cmd_act_get: break; default: - lbs_pr_debug(1, "Invalid action:%d\n", domaininfo->action); + lbs_deb_11d("Invalid action:%d\n", domaininfo->action); ret = -1; break; } - LEAVE(); + lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret); return ret; } @@ -651,23 +653,22 @@ int libertas_ret_802_11d_domain_info(wlan_private * priv, * @param priv pointer to wlan_private * @return 0; -1 */ -int libertas_parse_dnld_countryinfo_11d(wlan_private * priv) +int libertas_parse_dnld_countryinfo_11d(wlan_private * priv, + struct bss_descriptor * bss) { int ret; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_11D); if (priv->adapter->enable11d) { memset(&adapter->parsed_region_chan, 0, sizeof(struct parsed_region_chan_11d)); - ret = parse_domain_info_11d(&adapter->pattemptedbssdesc-> - countryinfo, 0, + ret = parse_domain_info_11d(&bss->countryinfo, 0, &adapter->parsed_region_chan); if (ret == -1) { - lbs_pr_debug(1, "11D: Err Parse domain_info from AP..\n"); - LEAVE(); - return ret; + lbs_deb_11d("11D: Err Parse domain_info from AP..\n"); + goto done; } memset(&adapter->domainreg, 0, @@ -678,13 +679,15 @@ int libertas_parse_dnld_countryinfo_11d(wlan_private * priv) ret = set_domain_info_11d(priv); if (ret) { - lbs_pr_debug(1, "11D: Err set domainInfo to FW\n"); - LEAVE(); - return ret; + lbs_deb_11d("11D: Err set domainInfo to FW\n"); + goto done; } } - LEAVE(); - return 0; + ret = 0; + +done: + lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret); + return ret; } /** @@ -699,8 +702,8 @@ int libertas_create_dnld_countryinfo_11d(wlan_private * priv) struct region_channel *region_chan; u8 j; - ENTER(); - lbs_pr_debug(1, "11D:curbssparams.band[%d]\n", adapter->curbssparams.band); + lbs_deb_enter(LBS_DEB_11D); + lbs_deb_11d("11D:curbssparams.band[%d]\n", adapter->curbssparams.band); if (priv->adapter->enable11d) { /* update parsed_region_chan_11; dnld domaininf to FW */ @@ -709,7 +712,7 @@ int libertas_create_dnld_countryinfo_11d(wlan_private * priv) sizeof(adapter->region_channel[0]); j++) { region_chan = &adapter->region_channel[j]; - lbs_pr_debug(1, "11D:[%d] region_chan->band[%d]\n", j, + lbs_deb_11d("11D:[%d] region_chan->band[%d]\n", j, region_chan->band); if (!region_chan || !region_chan->valid @@ -722,10 +725,10 @@ int libertas_create_dnld_countryinfo_11d(wlan_private * priv) if (j >= sizeof(adapter->region_channel) / sizeof(adapter->region_channel[0])) { - lbs_pr_debug(1, "11D:region_chan not found. band[%d]\n", + lbs_deb_11d("11D:region_chan not found. band[%d]\n", adapter->curbssparams.band); - LEAVE(); - return -1; + ret = -1; + goto done; } memset(&adapter->parsed_region_chan, 0, @@ -742,13 +745,14 @@ int libertas_create_dnld_countryinfo_11d(wlan_private * priv) ret = set_domain_info_11d(priv); if (ret) { - lbs_pr_debug(1, "11D: Err set domainInfo to FW\n"); - LEAVE(); - return ret; + lbs_deb_11d("11D: Err set domainInfo to FW\n"); + goto done; } } + ret = 0; - LEAVE(); - return 0; +done: + lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret); + return ret; } diff --git a/drivers/net/wireless/libertas/11d.h b/drivers/net/wireless/libertas/11d.h index db2ebea9f23..73e42e71291 100644 --- a/drivers/net/wireless/libertas/11d.h +++ b/drivers/net/wireless/libertas/11d.h @@ -47,7 +47,7 @@ struct mrvlietypes_domainparamset { } __attribute__ ((packed)); struct cmd_ds_802_11d_domain_info { - u16 action; + __le16 action; struct mrvlietypes_domainparamset domain; } __attribute__ ((packed)); @@ -98,7 +98,9 @@ int libertas_cmd_enable_11d(wlan_private * priv, struct iwreq *wrq); int libertas_ret_802_11d_domain_info(wlan_private * priv, struct cmd_ds_command *resp); -int libertas_parse_dnld_countryinfo_11d(wlan_private * priv); +struct bss_descriptor; +int libertas_parse_dnld_countryinfo_11d(wlan_private * priv, + struct bss_descriptor * bss); int libertas_create_dnld_countryinfo_11d(wlan_private * priv); diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile index 56a8ea1fbf0..32ed4136b0d 100644 --- a/drivers/net/wireless/libertas/Makefile +++ b/drivers/net/wireless/libertas/Makefile @@ -1,12 +1,12 @@ -usb8xxx-objs := main.o fw.o wext.o \ +libertas-objs := main.o fw.o wext.o \ rx.o tx.o cmd.o \ cmdresp.o scan.o \ join.o 11d.o \ - ioctl.o debugfs.o \ + debugfs.o \ ethtool.o assoc.o usb8xxx-objs += if_bootcmd.o usb8xxx-objs += if_usb.o +obj-$(CONFIG_LIBERTAS) += libertas.o obj-$(CONFIG_LIBERTAS_USB) += usb8xxx.o - diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README index 378577200b5..0b133ce6380 100644 --- a/drivers/net/wireless/libertas/README +++ b/drivers/net/wireless/libertas/README @@ -1,7 +1,7 @@ ================================================================================ README for USB8388 - (c) Copyright © 2003-2006, Marvell International Ltd. + (c) Copyright © 2003-2006, Marvell International Ltd. All Rights Reserved This software file (the "File") is distributed by Marvell International @@ -28,293 +28,6 @@ DRIVER LOADING insmod usb8388.ko [fw_name=usb8388.bin] -===================== -IWPRIV COMMAND -===================== - -NAME - This manual describes the usage of private commands used in Marvell WLAN - Linux Driver. All the commands available in Wlanconfig will not be available - in the iwpriv. - -SYNOPSIS - iwpriv <ethX> <command> [sub-command] ... - - iwpriv ethX setregioncode <n> - iwpriv ethX getregioncode - -Version 5 Command: - iwpriv ethX ledgpio <n> - -BT Commands: - The blinding table (BT) contains a list of mac addresses that should be - ignored by the firmware. It is primarily used for debugging and - testing networks. It can be edited and inspected with the following - commands: - - iwpriv ethX bt_reset - iwpriv ethX bt_add <mac_address> - iwpriv ethX bt_del <mac_address> - iwpriv ethX bt_list <id> - -FWT Commands: - The forwarding table (FWT) is a feature used to manage mesh network - routing in the firmware. The FWT is essentially a routing table that - associates a destination mac address (da) with a next hop receiver - address (ra). The FWT can be inspected and edited with the following - iwpriv commands, which are described in greater detail below. - Eventually, the table will be automatically maintained by a custom - routing protocol. - - NOTE: FWT commands replace the previous DFT commands. What were the DFT - commands?, you might ask. They were an earlier API to the firmware that - implemented a simple MAC-layer forwarding mechanism. In the unlikely - event that you were using these commands, you must migrate to the new - FWT commands which can be used to achieve the same functionality. - - iwpriv ethX fwt_add [parameters] - iwpriv ethX fwt_del [parameters] - iwpriv ethX fwt_lookup [parameters] - iwpriv ethX fwt_list [parameters] - iwpriv ethX fwt_list_route [parameters] - iwpriv ethX fwt_list_neigh [parameters] - iwpriv ethX fwt_reset [parameters] - iwpriv ethX fwt_cleanup - iwpriv ethX fwt_time - -MESH Commands: - - The MESH commands are used to configure various features of the mesh - routing protocol. The following commands are supported: - - iwpriv ethX mesh_get_ttl - iwpriv ethX mesh_set_ttl ttl - -DESCRIPTION - Those commands are used to send additional commands to the Marvell WLAN - card via the Linux device driver. - - The ethX parameter specifies the network device that is to be used to - perform this command on. it could be eth0, eth1 etc. - -setregioncode - This command is used to set the region code in the station. - where value is 'region code' for various regions like - USA FCC, Canada IC, Spain, France, Europe ETSI, Japan ... - - Usage: - iwpriv ethX setregioncode 0x10: set region code to USA (0x10). - -getregioncode - This command is used to get the region code information set in the - station. - -ledgpio - This command is used to set/get LEDs. - - iwpriv ethX ledgpio <LEDs> - will set the corresponding LED for the GPIO Line. - - iwpriv ethX ledgpio - will give u which LEDs are Enabled. - - Usage: - iwpriv eth1 ledgpio 1 0 2 1 3 4 - will enable - LED 1 -> GPIO 0 - LED 2 -> GPIO 1 - LED 3 -> GPIO 4 - - iwpriv eth1 ledgpio - shows LED information in the format as mentioned above. - - Note: LED0 is invalid - Note: Maximum Number of LEDs are 16. - -fwt_add - This command is used to insert an entry into the FWT table. The list of - parameters must follow the following structure: - - iwpriv ethX fwt_add da ra [metric dir ssn dsn hopcount ttl expiration sleepmode snr] - - The parameters between brackets are optional, but they must appear in - the order specified. For example, if you want to specify the metric, - you must also specify the dir, ssn, and dsn but you need not specify the - hopcount, expiration, sleepmode, or snr. Any unspecified parameters - will be assigned the defaults specified below. - - The different parameters are:- - da -- DA MAC address in the form 00:11:22:33:44:55 - ra -- RA MAC address in the form 00:11:22:33:44:55 - metric -- route metric (cost: smaller-metric routes are - preferred, default is 0) - dir -- direction (1 for direct, 0 for reverse, - default is 1) - ssn -- Source Sequence Number (time at the RA for - reverse routes. Default is 0) - dsn -- Destination Sequence Number (time at the DA - for direct routes. Default is 0) - hopcount -- hop count (currently unused, default is 0) - ttl -- TTL (Only used in reverse entries) - expiration -- entry expiration (in ticks, where a tick is - 1024us, or ~ 1ms. Use 0 for an indefinite - entry, default is 0) - sleepmode -- RA's sleep mode (currently unused, default is - 0) - snr -- SNR in the link to RA (currently unused, - default is 0) - - The command does not return anything. - -fwt_del - This command is used to remove an entry to the FWT table. The list of - parameters must follow the following structure: - - iwpriv ethX fwt_del da ra [dir] - - where the different parameters are:- - da -- DA MAC address (in the form "00:11:22:33:44:55") - ra -- RA MAC address (in the form "00:11:22:33:44:55") - dir -- direction (1 for direct, 0 for reverse, - default is 1) - - The command does not return anything. - -fwt_lookup - This command is used to get the best route in the FWT table to a given - host. The only parameter is the MAC address of the host that is being - looked for. - - iwpriv ethX fwt_lookup da - - where:- - da -- DA MAC address (in the form "00:11:22:33:44:55") - - The command returns an output string identical to the one returned by - fwt_list described below. - - -fwt_list - This command is used to list a route from the FWT table. The only - parameter is the index into the table. If you want to list all the - routes in a table, start with index=0, and keep listing until you get a - "(null)" string. Note that the indicies may change as the fwt is - updated. It is expected that most users will not use fwt_list directly, - but that a utility similar to the traditional route command will be used - to invoke fwt_list over and over. - - iwpriv ethX fwt_list index - - The output is a string of the following form: - - da ra metric dir ssn dsn hopcount ttl expiration sleepmode snr - - where the different fields are:- - da -- DA MAC address (in the form "00:11:22:33:44:55") - ra -- RA MAC address (in the form "00:11:22:33:44:55") - metric -- route metric (cost: smaller-metric routes are preferred) - dir -- direction (1 for direct, 0 for reverse) - ssn -- Source Sequence Number (time at the RA for reverse routes) - dsn -- Destination Sequence Number (time at the DA for direct routes) - hopcount -- hop count (currently unused) - ttl -- TTL (only used in reverse entries) - expiration -- entry expiration (in ticks, where a tick is 1024us, or ~ 1ms. Use 0 for an indefinite entry) - sleepmode -- RA's sleep mode (currently unused) - snr -- SNR in the link to RA (currently unused) - -fwt_list_route - This command is used to list a route from the FWT table. The only - parameter is the route ID. If you want to list all the routes in a - table, start with rid=0, and keep incrementing rid until you get a - "(null)" string. This function is similar to fwt_list. The only - difference is the output format. Also note that this command is meant - for debugging. It is expected that users will use fwt_lookup and - fwt_list. One important reason for this is that the route id may change - as the route table is altered. - - iwpriv ethX fwt_list_route rid - - The output is a string of the following form: - - da metric dir nid ssn dsn hopcount ttl expiration - - where the different fields are:- - da -- DA MAC address (in the form "00:11:22:33:44:55") - metric -- route metric (cost: smaller-metric routes are preferred) - dir -- direction (1 for direct, 0 for reverse) - nid -- Next-hop (neighbor) host ID (nid) - ssn -- Source Sequence Number (time at the RA for reverse routes) - dsn -- Destination Sequence Number (time at the DA for direct routes) - hopcount -- hop count (currently unused) - ttl -- TTL count (only used in reverse entries) - expiration -- entry expiration (in ticks, where a tick is 1024us, or ~ 1ms. Use 0 for an indefinite entry) - -fwt_list_neigh - This command is used to list a neighbor from the FWT table. The only - parameter is the neighbor ID. If you want to list all the neighbors in a - table, start with nid=0, and keep incrementing nid until you get a - "(null)" string. Note that the nid from a fwt_list_route command can be - used as an input to this command. Also note that this command is meant - mostly for debugging. It is expected that users will use fwt_lookup. - One important reason for this is that the neighbor id may change as the - neighbor table is altered. - - iwpriv ethX fwt_list_neigh nid - - The output is a string of the following form: - - ra sleepmode snr references - - where the different fields are:- - ra -- RA MAC address (in the form "00:11:22:33:44:55") - sleepmode -- RA's sleep mode (currently unused) - snr -- SNR in the link to RA (currently unused) - references -- RA's reference counter - -fwt_reset - This command is used to reset the FWT table, getting rid of all the - entries. There are no input parameters. - - iwpriv ethX fwt_reset - - The command does not return anything. - -fwt_cleanup - This command is used to perform user-based garbage recollection. The - FWT table is checked, and all the entries that are expired or invalid - are cleaned. Note that this is exported to the driver for debugging - purposes, as garbage collection is also fired by the firmware when in - space problems. There are no input parameters. - - iwpriv ethX fwt_cleanup - - The command does returns the number of invalid/expired routes deleted. - -fwt_time - This command returns a card's internal time representation. It is this - time that is used to represent the expiration times of FWT entries. The - number is not consistent from card to card; it is simply a timer count. - The fwt_time command is used to inspect the timer so that expiration - times reported by fwt_list can be properly interpreted. - - iwpriv ethX fwt_time - -mesh_get_ttl - - The mesh ttl is the number of hops a mesh packet can traverse before it - is dropped. This parameter is used to prevent infinite loops in the - mesh network. The value returned by this function is the ttl assigned - to all mesh packets. Currently there is no way to control the ttl on a - per packet or per socket basis. - - iwpriv ethX mesh_get_ttl - -mesh_set_ttl ttl - - Set the ttl. The argument must be between 0 and 255. - - iwpriv ethX mesh_set_ttl <ttl> - ========================= ETHTOOL ========================= diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index c260bd1b3d4..afd5617dd92 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -2,6 +2,7 @@ #include <linux/bitops.h> #include <net/ieee80211.h> +#include <linux/etherdevice.h> #include "assoc.h" #include "join.h" @@ -13,59 +14,88 @@ static const u8 bssid_any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; static const u8 bssid_off[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static void print_assoc_req(const char * extra, struct assoc_request * assoc_req) +{ + lbs_deb_assoc( + "#### Association Request: %s\n" + " flags: 0x%08lX\n" + " SSID: '%s'\n" + " channel: %d\n" + " band: %d\n" + " mode: %d\n" + " BSSID: " MAC_FMT "\n" + " Encryption:%s%s%s\n" + " auth: %d\n", + extra, assoc_req->flags, + escape_essid(assoc_req->ssid, assoc_req->ssid_len), + assoc_req->channel, assoc_req->band, assoc_req->mode, + MAC_ARG(assoc_req->bssid), + assoc_req->secinfo.WPAenabled ? " WPA" : "", + assoc_req->secinfo.WPA2enabled ? " WPA2" : "", + assoc_req->secinfo.wep_enabled ? " WEP" : "", + assoc_req->secinfo.auth_mode); +} + + static int assoc_helper_essid(wlan_private *priv, struct assoc_request * assoc_req) { wlan_adapter *adapter = priv->adapter; int ret = 0; - int i; + struct bss_descriptor * bss; + int channel = -1; + + lbs_deb_enter(LBS_DEB_ASSOC); - ENTER(); + /* FIXME: take channel into account when picking SSIDs if a channel + * is set. + */ + + if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) + channel = assoc_req->channel; - lbs_pr_debug(1, "New SSID requested: %s\n", assoc_req->ssid.ssid); + lbs_deb_assoc("New SSID requested: '%s'\n", + escape_essid(assoc_req->ssid, assoc_req->ssid_len)); if (assoc_req->mode == IW_MODE_INFRA) { if (adapter->prescan) { - libertas_send_specific_SSID_scan(priv, &assoc_req->ssid, 1); + libertas_send_specific_ssid_scan(priv, assoc_req->ssid, + assoc_req->ssid_len, 0); } - i = libertas_find_SSID_in_list(adapter, &assoc_req->ssid, - NULL, IW_MODE_INFRA); - if (i >= 0) { - lbs_pr_debug(1, - "SSID found in scan list ... associating...\n"); - - ret = wlan_associate(priv, &adapter->scantable[i]); - if (ret == 0) { - memcpy(&assoc_req->bssid, - &adapter->scantable[i].macaddress, - ETH_ALEN); - } + bss = libertas_find_ssid_in_list(adapter, assoc_req->ssid, + assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel); + if (bss != NULL) { + lbs_deb_assoc("SSID found in scan list, associating\n"); + memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); + ret = wlan_associate(priv, assoc_req); } else { - lbs_pr_debug(1, "SSID '%s' not found; cannot associate\n", - assoc_req->ssid.ssid); + lbs_deb_assoc("SSID not found; cannot associate\n"); } } else if (assoc_req->mode == IW_MODE_ADHOC) { /* Scan for the network, do not save previous results. Stale * scan data will cause us to join a non-existant adhoc network */ - libertas_send_specific_SSID_scan(priv, &assoc_req->ssid, 0); + libertas_send_specific_ssid_scan(priv, assoc_req->ssid, + assoc_req->ssid_len, 1); /* Search for the requested SSID in the scan table */ - i = libertas_find_SSID_in_list(adapter, &assoc_req->ssid, NULL, - IW_MODE_ADHOC); - if (i >= 0) { - lbs_pr_debug(1, "SSID found at %d in List, so join\n", ret); - libertas_join_adhoc_network(priv, &adapter->scantable[i]); + bss = libertas_find_ssid_in_list(adapter, assoc_req->ssid, + assoc_req->ssid_len, NULL, IW_MODE_ADHOC, channel); + if (bss != NULL) { + lbs_deb_assoc("SSID found, will join\n"); + memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); + libertas_join_adhoc_network(priv, assoc_req); } else { /* else send START command */ - lbs_pr_debug(1, "SSID not found in list, so creating adhoc" - " with SSID '%s'\n", assoc_req->ssid.ssid); - libertas_start_adhoc_network(priv, &assoc_req->ssid); + lbs_deb_assoc("SSID not found, creating adhoc network\n"); + memcpy(&assoc_req->bss.ssid, &assoc_req->ssid, + IW_ESSID_MAX_SIZE); + assoc_req->bss.ssid_len = assoc_req->ssid_len; + libertas_start_adhoc_network(priv, assoc_req); } - memcpy(&assoc_req->bssid, &adapter->current_addr, ETH_ALEN); } - LEAVE(); + lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); return ret; } @@ -74,33 +104,31 @@ static int assoc_helper_bssid(wlan_private *priv, struct assoc_request * assoc_req) { wlan_adapter *adapter = priv->adapter; - int i, ret = 0; - - ENTER(); + int ret = 0; + struct bss_descriptor * bss; - lbs_pr_debug(1, "ASSOC: WAP: BSSID = " MAC_FMT "\n", + lbs_deb_enter_args(LBS_DEB_ASSOC, "BSSID " MAC_FMT, MAC_ARG(assoc_req->bssid)); /* Search for index position in list for requested MAC */ - i = libertas_find_BSSID_in_list(adapter, assoc_req->bssid, + bss = libertas_find_bssid_in_list(adapter, assoc_req->bssid, assoc_req->mode); - if (i < 0) { - lbs_pr_debug(1, "ASSOC: WAP: BSSID " MAC_FMT " not found, " + if (bss == NULL) { + lbs_deb_assoc("ASSOC: WAP: BSSID " MAC_FMT " not found, " "cannot associate.\n", MAC_ARG(assoc_req->bssid)); goto out; } + memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); if (assoc_req->mode == IW_MODE_INFRA) { - ret = wlan_associate(priv, &adapter->scantable[i]); - lbs_pr_debug(1, "ASSOC: return from wlan_associate(bssd) was %d\n", ret); + ret = wlan_associate(priv, assoc_req); + lbs_deb_assoc("ASSOC: wlan_associate(bssid) returned %d\n", ret); } else if (assoc_req->mode == IW_MODE_ADHOC) { - libertas_join_adhoc_network(priv, &adapter->scantable[i]); + libertas_join_adhoc_network(priv, assoc_req); } - memcpy(&assoc_req->ssid, &adapter->scantable[i].ssid, - sizeof(struct WLAN_802_11_SSID)); out: - LEAVE(); + lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); return ret; } @@ -113,12 +141,12 @@ static int assoc_helper_associate(wlan_private *priv, /* If we're given and 'any' BSSID, try associating based on SSID */ if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { - if (memcmp(bssid_any, assoc_req->bssid, ETH_ALEN) - && memcmp(bssid_off, assoc_req->bssid, ETH_ALEN)) { + if (compare_ether_addr(bssid_any, assoc_req->bssid) + && compare_ether_addr(bssid_off, assoc_req->bssid)) { ret = assoc_helper_bssid(priv, assoc_req); done = 1; if (ret) { - lbs_pr_debug(1, "ASSOC: bssid: ret = %d\n", ret); + lbs_deb_assoc("ASSOC: bssid: ret = %d\n", ret); } } } @@ -126,7 +154,7 @@ static int assoc_helper_associate(wlan_private *priv, if (!done && test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { ret = assoc_helper_essid(priv, assoc_req); if (ret) { - lbs_pr_debug(1, "ASSOC: bssid: ret = %d\n", ret); + lbs_deb_assoc("ASSOC: bssid: ret = %d\n", ret); } } @@ -140,12 +168,10 @@ static int assoc_helper_mode(wlan_private *priv, wlan_adapter *adapter = priv->adapter; int ret = 0; - ENTER(); + lbs_deb_enter(LBS_DEB_ASSOC); - if (assoc_req->mode == adapter->mode) { - LEAVE(); - return 0; - } + if (assoc_req->mode == adapter->mode) + goto done; if (assoc_req->mode == IW_MODE_INFRA) { if (adapter->psstate != PS_STATE_FULL_POWER) @@ -158,9 +184,81 @@ static int assoc_helper_mode(wlan_private *priv, cmd_802_11_snmp_mib, 0, cmd_option_waitforrsp, OID_802_11_INFRASTRUCTURE_MODE, - (void *) (size_t) assoc_req->mode); + /* Shoot me now */ (void *) (size_t) assoc_req->mode); - LEAVE(); +done: + lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); + return ret; +} + + +static int update_channel(wlan_private * priv) +{ + /* the channel in f/w could be out of sync, get the current channel */ + return libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel, + cmd_opt_802_11_rf_channel_get, + cmd_option_waitforrsp, 0, NULL); +} + +void libertas_sync_channel(struct work_struct *work) +{ + wlan_private *priv = container_of(work, wlan_private, sync_channel); + + if (update_channel(priv) != 0) + lbs_pr_info("Channel synchronization failed."); +} + +static int assoc_helper_channel(wlan_private *priv, + struct assoc_request * assoc_req) +{ + wlan_adapter *adapter = priv->adapter; + int ret = 0; + + lbs_deb_enter(LBS_DEB_ASSOC); + + ret = update_channel(priv); + if (ret < 0) { + lbs_deb_assoc("ASSOC: channel: error getting channel."); + } + + if (assoc_req->channel == adapter->curbssparams.channel) + goto done; + + lbs_deb_assoc("ASSOC: channel: %d -> %d\n", + adapter->curbssparams.channel, assoc_req->channel); + + ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel, + cmd_opt_802_11_rf_channel_set, + cmd_option_waitforrsp, 0, &assoc_req->channel); + if (ret < 0) { + lbs_deb_assoc("ASSOC: channel: error setting channel."); + } + + ret = update_channel(priv); + if (ret < 0) { + lbs_deb_assoc("ASSOC: channel: error getting channel."); + } + + if (assoc_req->channel != adapter->curbssparams.channel) { + lbs_deb_assoc("ASSOC: channel: failed to update channel to %d", + assoc_req->channel); + goto done; + } + + if ( assoc_req->secinfo.wep_enabled + && (assoc_req->wep_keys[0].len + || assoc_req->wep_keys[1].len + || assoc_req->wep_keys[2].len + || assoc_req->wep_keys[3].len)) { + /* Make sure WEP keys are re-sent to firmware */ + set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); + } + + /* Must restart/rejoin adhoc networks after channel change */ + set_bit(ASSOC_FLAG_SSID, &assoc_req->flags); + +done: + lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); return ret; } @@ -172,7 +270,7 @@ static int assoc_helper_wep_keys(wlan_private *priv, int i; int ret = 0; - ENTER(); + lbs_deb_enter(LBS_DEB_ASSOC); /* Set or remove WEP keys */ if ( assoc_req->wep_keys[0].len @@ -216,7 +314,7 @@ static int assoc_helper_wep_keys(wlan_private *priv, mutex_unlock(&adapter->lock); out: - LEAVE(); + lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); return ret; } @@ -225,15 +323,49 @@ static int assoc_helper_secinfo(wlan_private *priv, { wlan_adapter *adapter = priv->adapter; int ret = 0; + u32 do_wpa; + u32 rsn = 0; - ENTER(); + lbs_deb_enter(LBS_DEB_ASSOC); memcpy(&adapter->secinfo, &assoc_req->secinfo, sizeof(struct wlan_802_11_security)); ret = libertas_set_mac_packet_filter(priv); + if (ret) + goto out; + + /* If RSN is already enabled, don't try to enable it again, since + * ENABLE_RSN resets internal state machines and will clobber the + * 4-way WPA handshake. + */ - LEAVE(); + /* Get RSN enabled/disabled */ + ret = libertas_prepare_and_send_command(priv, + cmd_802_11_enable_rsn, + cmd_act_set, + cmd_option_waitforrsp, + 0, &rsn); + if (ret) { + lbs_deb_assoc("Failed to get RSN status: %d", ret); + goto out; + } + + /* Don't re-enable RSN if it's already enabled */ + do_wpa = (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled); + if (do_wpa == rsn) + goto out; + + /* Set RSN enabled/disabled */ + rsn = do_wpa; + ret = libertas_prepare_and_send_command(priv, + cmd_802_11_enable_rsn, + cmd_act_set, + cmd_option_waitforrsp, + 0, &rsn); + +out: + lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); return ret; } @@ -243,16 +375,7 @@ static int assoc_helper_wpa_keys(wlan_private *priv, { int ret = 0; - ENTER(); - - /* enable/Disable RSN */ - ret = libertas_prepare_and_send_command(priv, - cmd_802_11_enable_rsn, - cmd_act_set, - cmd_option_waitforrsp, - 0, assoc_req); - if (ret) - goto out; + lbs_deb_enter(LBS_DEB_ASSOC); ret = libertas_prepare_and_send_command(priv, cmd_802_11_key_material, @@ -260,8 +383,7 @@ static int assoc_helper_wpa_keys(wlan_private *priv, cmd_option_waitforrsp, 0, assoc_req); -out: - LEAVE(); + lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); return ret; } @@ -272,7 +394,7 @@ static int assoc_helper_wpa_ie(wlan_private *priv, wlan_adapter *adapter = priv->adapter; int ret = 0; - ENTER(); + lbs_deb_enter(LBS_DEB_ASSOC); if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) { memcpy(&adapter->wpa_ie, &assoc_req->wpa_ie, assoc_req->wpa_ie_len); @@ -282,7 +404,7 @@ static int assoc_helper_wpa_ie(wlan_private *priv, adapter->wpa_ie_len = 0; } - LEAVE(); + lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); return ret; } @@ -294,25 +416,30 @@ static int should_deauth_infrastructure(wlan_adapter *adapter, return 0; if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { - lbs_pr_debug(1, "Deauthenticating due to new SSID in " + lbs_deb_assoc("Deauthenticating due to new SSID in " " configuration request.\n"); return 1; } if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) { if (adapter->secinfo.auth_mode != assoc_req->secinfo.auth_mode) { - lbs_pr_debug(1, "Deauthenticating due to updated security " + lbs_deb_assoc("Deauthenticating due to updated security " "info in configuration request.\n"); return 1; } } if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { - lbs_pr_debug(1, "Deauthenticating due to new BSSID in " + lbs_deb_assoc("Deauthenticating due to new BSSID in " " configuration request.\n"); return 1; } + if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) { + lbs_deb_assoc("Deauthenticating due to channel switch.\n"); + return 1; + } + /* FIXME: deal with 'auto' mode somehow */ if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) { if (assoc_req->mode != IW_MODE_INFRA) @@ -329,10 +456,9 @@ static int should_stop_adhoc(wlan_adapter *adapter, if (adapter->connect_status != libertas_connected) return 0; - if (adapter->curbssparams.ssid.ssidlength != assoc_req->ssid.ssidlength) - return 1; - if (memcmp(adapter->curbssparams.ssid.ssid, assoc_req->ssid.ssid, - adapter->curbssparams.ssid.ssidlength)) + if (libertas_ssid_cmp(adapter->curbssparams.ssid, + adapter->curbssparams.ssid_len, + assoc_req->ssid, assoc_req->ssid_len) != 0) return 1; /* FIXME: deal with 'auto' mode somehow */ @@ -341,11 +467,16 @@ static int should_stop_adhoc(wlan_adapter *adapter, return 1; } + if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) { + if (assoc_req->channel != adapter->curbssparams.channel) + return 1; + } + return 0; } -void wlan_association_worker(struct work_struct *work) +void libertas_association_worker(struct work_struct *work) { wlan_private *priv = container_of(work, wlan_private, assoc_work.work); wlan_adapter *adapter = priv->adapter; @@ -353,40 +484,38 @@ void wlan_association_worker(struct work_struct *work) int ret = 0; int find_any_ssid = 0; - ENTER(); + lbs_deb_enter(LBS_DEB_ASSOC); mutex_lock(&adapter->lock); - assoc_req = adapter->assoc_req; - adapter->assoc_req = NULL; + assoc_req = adapter->pending_assoc_req; + adapter->pending_assoc_req = NULL; + adapter->in_progress_assoc_req = assoc_req; mutex_unlock(&adapter->lock); - if (!assoc_req) { - LEAVE(); - return; - } + if (!assoc_req) + goto done; - lbs_pr_debug(1, "ASSOC: starting new association request: flags = 0x%lX\n", - assoc_req->flags); + print_assoc_req(__func__, assoc_req); /* If 'any' SSID was specified, find an SSID to associate with */ if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags) - && !assoc_req->ssid.ssidlength) + && !assoc_req->ssid_len) find_any_ssid = 1; /* But don't use 'any' SSID if there's a valid locked BSSID to use */ if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { - if (memcmp(&assoc_req->bssid, bssid_any, ETH_ALEN) - && memcmp(&assoc_req->bssid, bssid_off, ETH_ALEN)) + if (compare_ether_addr(assoc_req->bssid, bssid_any) + && compare_ether_addr(assoc_req->bssid, bssid_off)) find_any_ssid = 0; } if (find_any_ssid) { u8 new_mode; - ret = libertas_find_best_network_SSID(priv, &assoc_req->ssid, - assoc_req->mode, &new_mode); + ret = libertas_find_best_network_ssid(priv, assoc_req->ssid, + &assoc_req->ssid_len, assoc_req->mode, &new_mode); if (ret) { - lbs_pr_debug(1, "Could not find best network\n"); + lbs_deb_assoc("Could not find best network\n"); ret = -ENETUNREACH; goto out; } @@ -406,7 +535,7 @@ void wlan_association_worker(struct work_struct *work) if (should_deauth_infrastructure(adapter, assoc_req)) { ret = libertas_send_deauthentication(priv); if (ret) { - lbs_pr_debug(1, "Deauthentication due to new " + lbs_deb_assoc("Deauthentication due to new " "configuration request failed: %d\n", ret); } @@ -415,7 +544,7 @@ void wlan_association_worker(struct work_struct *work) if (should_stop_adhoc(adapter, assoc_req)) { ret = libertas_stop_adhoc_network(priv); if (ret) { - lbs_pr_debug(1, "Teardown of AdHoc network due to " + lbs_deb_assoc("Teardown of AdHoc network due to " "new configuration request failed: %d\n", ret); } @@ -427,7 +556,16 @@ void wlan_association_worker(struct work_struct *work) if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) { ret = assoc_helper_mode(priv, assoc_req); if (ret) { -lbs_pr_debug(1, "ASSOC(:%d) mode: ret = %d\n", __LINE__, ret); +lbs_deb_assoc("ASSOC(:%d) mode: ret = %d\n", __LINE__, ret); + goto out; + } + } + + if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) { + ret = assoc_helper_channel(priv, assoc_req); + if (ret) { + lbs_deb_assoc("ASSOC(:%d) channel: ret = %d\n", + __LINE__, ret); goto out; } } @@ -436,7 +574,7 @@ lbs_pr_debug(1, "ASSOC(:%d) mode: ret = %d\n", __LINE__, ret); || test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) { ret = assoc_helper_wep_keys(priv, assoc_req); if (ret) { -lbs_pr_debug(1, "ASSOC(:%d) wep_keys: ret = %d\n", __LINE__, ret); +lbs_deb_assoc("ASSOC(:%d) wep_keys: ret = %d\n", __LINE__, ret); goto out; } } @@ -444,7 +582,7 @@ lbs_pr_debug(1, "ASSOC(:%d) wep_keys: ret = %d\n", __LINE__, ret); if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) { ret = assoc_helper_secinfo(priv, assoc_req); if (ret) { -lbs_pr_debug(1, "ASSOC(:%d) secinfo: ret = %d\n", __LINE__, ret); +lbs_deb_assoc("ASSOC(:%d) secinfo: ret = %d\n", __LINE__, ret); goto out; } } @@ -452,7 +590,7 @@ lbs_pr_debug(1, "ASSOC(:%d) secinfo: ret = %d\n", __LINE__, ret); if (test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) { ret = assoc_helper_wpa_ie(priv, assoc_req); if (ret) { -lbs_pr_debug(1, "ASSOC(:%d) wpa_ie: ret = %d\n", __LINE__, ret); +lbs_deb_assoc("ASSOC(:%d) wpa_ie: ret = %d\n", __LINE__, ret); goto out; } } @@ -461,7 +599,7 @@ lbs_pr_debug(1, "ASSOC(:%d) wpa_ie: ret = %d\n", __LINE__, ret); || test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { ret = assoc_helper_wpa_keys(priv, assoc_req); if (ret) { -lbs_pr_debug(1, "ASSOC(:%d) wpa_keys: ret = %d\n", __LINE__, ret); +lbs_deb_assoc("ASSOC(:%d) wpa_keys: ret = %d\n", __LINE__, ret); goto out; } } @@ -475,21 +613,23 @@ lbs_pr_debug(1, "ASSOC(:%d) wpa_keys: ret = %d\n", __LINE__, ret); ret = assoc_helper_associate(priv, assoc_req); if (ret) { - lbs_pr_debug(1, "ASSOC: association attempt unsuccessful: %d\n", + lbs_deb_assoc("ASSOC: association attempt unsuccessful: %d\n", ret); success = 0; } if (adapter->connect_status != libertas_connected) { - lbs_pr_debug(1, "ASSOC: assoication attempt unsuccessful, " + lbs_deb_assoc("ASSOC: assoication attempt unsuccessful, " "not connected.\n"); success = 0; } if (success) { - lbs_pr_debug(1, "ASSOC: association attempt successful. " + lbs_deb_assoc("ASSOC: association attempt successful. " "Associated to '%s' (" MAC_FMT ")\n", - assoc_req->ssid.ssid, MAC_ARG(assoc_req->bssid)); + escape_essid(adapter->curbssparams.ssid, + adapter->curbssparams.ssid_len), + MAC_ARG(adapter->curbssparams.bssid)); libertas_prepare_and_send_command(priv, cmd_802_11_rssi, 0, cmd_option_waitforrsp, 0, NULL); @@ -498,18 +638,23 @@ lbs_pr_debug(1, "ASSOC(:%d) wpa_keys: ret = %d\n", __LINE__, ret); cmd_802_11_get_log, 0, cmd_option_waitforrsp, 0, NULL); } else { - ret = -1; } } out: if (ret) { - lbs_pr_debug(1, "ASSOC: reconfiguration attempt unsuccessful: %d\n", + lbs_deb_assoc("ASSOC: reconfiguration attempt unsuccessful: %d\n", ret); } + + mutex_lock(&adapter->lock); + adapter->in_progress_assoc_req = NULL; + mutex_unlock(&adapter->lock); kfree(assoc_req); - LEAVE(); + +done: + lbs_deb_leave(LBS_DEB_ASSOC); } @@ -520,9 +665,10 @@ struct assoc_request * wlan_get_association_request(wlan_adapter *adapter) { struct assoc_request * assoc_req; - if (!adapter->assoc_req) { - adapter->assoc_req = kzalloc(sizeof(struct assoc_request), GFP_KERNEL); - if (!adapter->assoc_req) { + if (!adapter->pending_assoc_req) { + adapter->pending_assoc_req = kzalloc(sizeof(struct assoc_request), + GFP_KERNEL); + if (!adapter->pending_assoc_req) { lbs_pr_info("Not enough memory to allocate association" " request!\n"); return NULL; @@ -532,15 +678,19 @@ struct assoc_request * wlan_get_association_request(wlan_adapter *adapter) /* Copy current configuration attributes to the association request, * but don't overwrite any that are already set. */ - assoc_req = adapter->assoc_req; + assoc_req = adapter->pending_assoc_req; if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { - memcpy(&assoc_req->ssid, adapter->curbssparams.ssid.ssid, - adapter->curbssparams.ssid.ssidlength); + memcpy(&assoc_req->ssid, &adapter->curbssparams.ssid, + IW_ESSID_MAX_SIZE); + assoc_req->ssid_len = adapter->curbssparams.ssid_len; } if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) assoc_req->channel = adapter->curbssparams.channel; + if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags)) + assoc_req->band = adapter->curbssparams.band; + if (!test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) assoc_req->mode = adapter->mode; @@ -581,7 +731,7 @@ struct assoc_request * wlan_get_association_request(wlan_adapter *adapter) assoc_req->wpa_ie_len = adapter->wpa_ie_len; } + print_assoc_req(__func__, assoc_req); + return assoc_req; } - - diff --git a/drivers/net/wireless/libertas/assoc.h b/drivers/net/wireless/libertas/assoc.h index 2ffd82d99b3..5e9c31f0932 100644 --- a/drivers/net/wireless/libertas/assoc.h +++ b/drivers/net/wireless/libertas/assoc.h @@ -5,10 +5,12 @@ #include "dev.h" -void wlan_association_worker(struct work_struct *work); +void libertas_association_worker(struct work_struct *work); struct assoc_request * wlan_get_association_request(wlan_adapter *adapter); +void libertas_sync_channel(struct work_struct *work); + #define ASSOC_DELAY (HZ / 2) static inline void wlan_postpone_association_work(wlan_private *priv) { @@ -21,9 +23,9 @@ static inline void wlan_postpone_association_work(wlan_private *priv) static inline void wlan_cancel_association_work(wlan_private *priv) { cancel_delayed_work(&priv->assoc_work); - if (priv->adapter->assoc_req) { - kfree(priv->adapter->assoc_req); - priv->adapter->assoc_req = NULL; + if (priv->adapter->pending_assoc_req) { + kfree(priv->adapter->pending_assoc_req); + priv->adapter->pending_assoc_req = NULL; } } diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index de9cb46a70f..13f6528abb0 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -6,7 +6,6 @@ #include <net/iw_handler.h> #include "host.h" #include "hostcmd.h" -#include "sbi.h" #include "decl.h" #include "defs.h" #include "dev.h" @@ -26,13 +25,11 @@ static u16 commands_allowed_in_ps[] = { * @param command the command ID * @return TRUE or FALSE */ -static u8 is_command_allowed_in_ps(u16 command) +static u8 is_command_allowed_in_ps(__le16 command) { - int count = sizeof(commands_allowed_in_ps) - / sizeof(commands_allowed_in_ps[0]); int i; - for (i = 0; i < count; i++) { + for (i = 0; i < ARRAY_SIZE(commands_allowed_in_ps); i++) { if (command == cpu_to_le16(commands_allowed_in_ps[i])) return 1; } @@ -44,14 +41,13 @@ static int wlan_cmd_hw_spec(wlan_private * priv, struct cmd_ds_command *cmd) { struct cmd_ds_get_hw_spec *hwspec = &cmd->params.hwspec; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); cmd->command = cpu_to_le16(cmd_get_hw_spec); - cmd->size = - cpu_to_le16(sizeof(struct cmd_ds_get_hw_spec) + S_DS_GEN); + cmd->size = cpu_to_le16(sizeof(struct cmd_ds_get_hw_spec) + S_DS_GEN); memcpy(hwspec->permanentaddr, priv->adapter->current_addr, ETH_ALEN); - LEAVE(); + lbs_deb_leave(LBS_DEB_CMD); return 0; } @@ -60,21 +56,19 @@ static int wlan_cmd_802_11_ps_mode(wlan_private * priv, u16 cmd_action) { struct cmd_ds_802_11_ps_mode *psm = &cmd->params.psmode; - u16 action = cmd_action; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); cmd->command = cpu_to_le16(cmd_802_11_ps_mode); - cmd->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) + - S_DS_GEN); + cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) + + S_DS_GEN); psm->action = cpu_to_le16(cmd_action); psm->multipledtim = 0; - switch (action) { + switch (cmd_action) { case cmd_subcmd_enter_ps: - lbs_pr_debug(1, "PS command:" "SubCode- Enter PS\n"); - lbs_pr_debug(1, "locallisteninterval = %d\n", + lbs_deb_cmd("PS command:" "SubCode- Enter PS\n"); + lbs_deb_cmd("locallisteninterval = %d\n", adapter->locallisteninterval); psm->locallisteninterval = @@ -86,18 +80,18 @@ static int wlan_cmd_802_11_ps_mode(wlan_private * priv, break; case cmd_subcmd_exit_ps: - lbs_pr_debug(1, "PS command:" "SubCode- Exit PS\n"); + lbs_deb_cmd("PS command:" "SubCode- Exit PS\n"); break; case cmd_subcmd_sleep_confirmed: - lbs_pr_debug(1, "PS command: SubCode- sleep confirm\n"); + lbs_deb_cmd("PS command: SubCode- sleep confirm\n"); break; default: break; } - LEAVE(); + lbs_deb_leave(LBS_DEB_CMD); return 0; } @@ -115,8 +109,7 @@ static int wlan_cmd_802_11_inactivity_timeout(wlan_private * priv, cmd->params.inactivity_timeout.action = cpu_to_le16(cmd_action); if (cmd_action) - cmd->params.inactivity_timeout.timeout = - cpu_to_le16(*timeout); + cmd->params.inactivity_timeout.timeout = cpu_to_le16(*timeout); else cmd->params.inactivity_timeout.timeout = 0; @@ -130,11 +123,10 @@ static int wlan_cmd_802_11_sleep_params(wlan_private * priv, wlan_adapter *adapter = priv->adapter; struct cmd_ds_802_11_sleep_params *sp = &cmd->params.sleep_params; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); - cmd->size = - cpu_to_le16((sizeof(struct cmd_ds_802_11_sleep_params)) + - S_DS_GEN); + cmd->size = cpu_to_le16((sizeof(struct cmd_ds_802_11_sleep_params)) + + S_DS_GEN); cmd->command = cpu_to_le16(cmd_802_11_sleep_params); if (cmd_action == cmd_act_get) { @@ -151,7 +143,7 @@ static int wlan_cmd_802_11_sleep_params(wlan_private * priv, sp->reserved = cpu_to_le16(adapter->sp.sp_reserved); } - LEAVE(); + lbs_deb_leave(LBS_DEB_CMD); return 0; } @@ -165,17 +157,16 @@ static int wlan_cmd_802_11_set_wep(wlan_private * priv, int ret = 0; struct assoc_request * assoc_req = pdata_buf; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); cmd->command = cpu_to_le16(cmd_802_11_set_wep); - cmd->size = cpu_to_le16((sizeof(struct cmd_ds_802_11_set_wep)) - + S_DS_GEN); + cmd->size = cpu_to_le16(sizeof(*wep) + S_DS_GEN); if (cmd_act == cmd_act_add) { int i; if (!assoc_req) { - lbs_pr_debug(1, "Invalid association request!"); + lbs_deb_cmd("Invalid association request!"); ret = -1; goto done; } @@ -183,11 +174,10 @@ static int wlan_cmd_802_11_set_wep(wlan_private * priv, wep->action = cpu_to_le16(cmd_act_add); /* default tx key index */ - wep->keyindex = cpu_to_le16((u16) - (assoc_req->wep_tx_keyidx & - (u32)cmd_WEP_KEY_INDEX_MASK)); + wep->keyindex = cpu_to_le16((u16)(assoc_req->wep_tx_keyidx & + (u32)cmd_WEP_KEY_INDEX_MASK)); - lbs_pr_debug(1, "Tx key Index: %u\n", wep->keyindex); + lbs_deb_cmd("Tx key Index: %u\n", le16_to_cpu(wep->keyindex)); /* Copy key types and material to host command structure */ for (i = 0; i < 4; i++) { @@ -195,19 +185,21 @@ static int wlan_cmd_802_11_set_wep(wlan_private * priv, switch (pkey->len) { case KEY_LEN_WEP_40: - wep->keytype[i] = cmd_type_wep_40_bit; + wep->keytype[i] = + cpu_to_le16(cmd_type_wep_40_bit); memmove(&wep->keymaterial[i], pkey->key, pkey->len); break; case KEY_LEN_WEP_104: - wep->keytype[i] = cmd_type_wep_104_bit; + wep->keytype[i] = + cpu_to_le16(cmd_type_wep_104_bit); memmove(&wep->keymaterial[i], pkey->key, pkey->len); break; case 0: break; default: - lbs_pr_debug(1, "Invalid WEP key %d length of %d\n", + lbs_deb_cmd("Invalid WEP key %d length of %d\n", i, pkey->len); ret = -1; goto done; @@ -219,36 +211,39 @@ static int wlan_cmd_802_11_set_wep(wlan_private * priv, wep->action = cpu_to_le16(cmd_act_remove); /* default tx key index */ - wep->keyindex = cpu_to_le16((u16) - (adapter->wep_tx_keyidx & - (u32)cmd_WEP_KEY_INDEX_MASK)); + wep->keyindex = cpu_to_le16((u16)(adapter->wep_tx_keyidx & + (u32)cmd_WEP_KEY_INDEX_MASK)); } ret = 0; done: - LEAVE(); + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; } static int wlan_cmd_802_11_enable_rsn(wlan_private * priv, struct cmd_ds_command *cmd, - u16 cmd_action) + u16 cmd_action, + void * pdata_buf) { struct cmd_ds_802_11_enable_rsn *penableRSN = &cmd->params.enbrsn; - wlan_adapter *adapter = priv->adapter; + u32 * enable = pdata_buf; + + lbs_deb_enter(LBS_DEB_CMD); cmd->command = cpu_to_le16(cmd_802_11_enable_rsn); - cmd->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_enable_rsn) + - S_DS_GEN); + cmd->size = cpu_to_le16(sizeof(*penableRSN) + S_DS_GEN); penableRSN->action = cpu_to_le16(cmd_action); - if (adapter->secinfo.WPAenabled || adapter->secinfo.WPA2enabled) { - penableRSN->enable = cpu_to_le16(cmd_enable_rsn); - } else { - penableRSN->enable = cpu_to_le16(cmd_disable_rsn); + + if (cmd_action == cmd_act_set) { + if (*enable) + penableRSN->enable = cpu_to_le16(cmd_enable_rsn); + else + penableRSN->enable = cpu_to_le16(cmd_enable_rsn); } + lbs_deb_leave(LBS_DEB_CMD); return 0; } @@ -259,14 +254,12 @@ static void set_one_wpa_key(struct MrvlIEtype_keyParamSet * pkeyparamset, pkeyparamset->keytypeid = cpu_to_le16(pkey->type); if (pkey->flags & KEY_INFO_WPA_ENABLED) { - pkeyparamset->keyinfo = cpu_to_le16(KEY_INFO_WPA_ENABLED); - } else { - pkeyparamset->keyinfo = cpu_to_le16(!KEY_INFO_WPA_ENABLED); + pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED); } - if (pkey->flags & KEY_INFO_WPA_UNICAST) { pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST); - } else if (pkey->flags & KEY_INFO_WPA_MCAST) { + } + if (pkey->flags & KEY_INFO_WPA_MCAST) { pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST); } @@ -284,46 +277,45 @@ static int wlan_cmd_802_11_key_material(wlan_private * priv, u16 cmd_action, u32 cmd_oid, void *pdata_buf) { - wlan_adapter *adapter = priv->adapter; struct cmd_ds_802_11_key_material *pkeymaterial = &cmd->params.keymaterial; + struct assoc_request * assoc_req = pdata_buf; int ret = 0; int index = 0; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); cmd->command = cpu_to_le16(cmd_802_11_key_material); pkeymaterial->action = cpu_to_le16(cmd_action); if (cmd_action == cmd_act_get) { - cmd->size = cpu_to_le16( S_DS_GEN - + sizeof (pkeymaterial->action)); + cmd->size = cpu_to_le16(S_DS_GEN + sizeof (pkeymaterial->action)); ret = 0; goto done; } memset(&pkeymaterial->keyParamSet, 0, sizeof(pkeymaterial->keyParamSet)); - if (adapter->wpa_unicast_key.len) { + if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { set_one_wpa_key(&pkeymaterial->keyParamSet[index], - &adapter->wpa_unicast_key); + &assoc_req->wpa_unicast_key); index++; } - if (adapter->wpa_mcast_key.len) { + if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) { set_one_wpa_key(&pkeymaterial->keyParamSet[index], - &adapter->wpa_mcast_key); + &assoc_req->wpa_mcast_key); index++; } cmd->size = cpu_to_le16( S_DS_GEN - + sizeof (pkeymaterial->action) - + index * sizeof(struct MrvlIEtype_keyParamSet)); + + sizeof (pkeymaterial->action) + + (index * sizeof(struct MrvlIEtype_keyParamSet))); ret = 0; done: - LEAVE(); + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; } @@ -354,8 +346,7 @@ static int wlan_cmd_802_11_get_stat(wlan_private * priv, { cmd->command = cpu_to_le16(cmd_802_11_get_stat); cmd->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_get_stat) + - S_DS_GEN); + cpu_to_le16(sizeof(struct cmd_ds_802_11_get_stat) + S_DS_GEN); return 0; } @@ -369,14 +360,12 @@ static int wlan_cmd_802_11_snmp_mib(wlan_private * priv, wlan_adapter *adapter = priv->adapter; u8 ucTemp; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); - lbs_pr_debug(1, "SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid); + lbs_deb_cmd("SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid); cmd->command = cpu_to_le16(cmd_802_11_snmp_mib); - cmd->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_snmp_mib) + - S_DS_GEN); + cmd->size = cpu_to_le16(sizeof(*pSNMPMIB) + S_DS_GEN); switch (cmd_oid) { case OID_802_11_INFRASTRUCTURE_MODE: @@ -407,7 +396,7 @@ static int wlan_cmd_802_11_snmp_mib(wlan_private * priv, pSNMPMIB->querytype = cmd_act_set; pSNMPMIB->bufsize = sizeof(u16); ulTemp = *(u32 *)pdata_buf; - *((unsigned short *)(pSNMPMIB->value)) = + *((__le16 *)(pSNMPMIB->value)) = cpu_to_le16((u16) ulTemp); } break; @@ -420,15 +409,12 @@ static int wlan_cmd_802_11_snmp_mib(wlan_private * priv, pSNMPMIB->oid = cpu_to_le16((u16) fragthresh_i); if (cmd_action == cmd_act_get) { - pSNMPMIB->querytype = - cpu_to_le16(cmd_act_get); + pSNMPMIB->querytype = cpu_to_le16(cmd_act_get); } else if (cmd_action == cmd_act_set) { - pSNMPMIB->querytype = - cpu_to_le16(cmd_act_set); - pSNMPMIB->bufsize = - cpu_to_le16(sizeof(u16)); + pSNMPMIB->querytype = cpu_to_le16(cmd_act_set); + pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16)); ulTemp = *((u32 *) pdata_buf); - *((unsigned short *)(pSNMPMIB->value)) = + *((__le16 *)(pSNMPMIB->value)) = cpu_to_le16((u16) ulTemp); } @@ -443,16 +429,12 @@ static int wlan_cmd_802_11_snmp_mib(wlan_private * priv, pSNMPMIB->oid = le16_to_cpu((u16) rtsthresh_i); if (cmd_action == cmd_act_get) { - pSNMPMIB->querytype = - cpu_to_le16(cmd_act_get); + pSNMPMIB->querytype = cpu_to_le16(cmd_act_get); } else if (cmd_action == cmd_act_set) { - pSNMPMIB->querytype = - cpu_to_le16(cmd_act_set); - pSNMPMIB->bufsize = - cpu_to_le16(sizeof(u16)); - ulTemp = *((u32 *) - pdata_buf); - *(unsigned short *)(pSNMPMIB->value) = + pSNMPMIB->querytype = cpu_to_le16(cmd_act_set); + pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16)); + ulTemp = *((u32 *)pdata_buf); + *(__le16 *)(pSNMPMIB->value) = cpu_to_le16((u16) ulTemp); } @@ -462,13 +444,11 @@ static int wlan_cmd_802_11_snmp_mib(wlan_private * priv, pSNMPMIB->oid = cpu_to_le16((u16) short_retrylim_i); if (cmd_action == cmd_act_get) { - pSNMPMIB->querytype = - cpu_to_le16(cmd_act_get); + pSNMPMIB->querytype = cpu_to_le16(cmd_act_get); } else if (cmd_action == cmd_act_set) { - pSNMPMIB->querytype = - cpu_to_le16(cmd_act_set); + pSNMPMIB->querytype = cpu_to_le16(cmd_act_set); pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16)); - *((unsigned short *)(pSNMPMIB->value)) = + *((__le16 *)(pSNMPMIB->value)) = cpu_to_le16((u16) adapter->txretrycount); } @@ -477,16 +457,18 @@ static int wlan_cmd_802_11_snmp_mib(wlan_private * priv, break; } - lbs_pr_debug(1, + lbs_deb_cmd( "SNMP_CMD: command=0x%x, size=0x%x, seqnum=0x%x, result=0x%x\n", - cmd->command, cmd->size, cmd->seqnum, cmd->result); + le16_to_cpu(cmd->command), le16_to_cpu(cmd->size), + le16_to_cpu(cmd->seqnum), le16_to_cpu(cmd->result)); - lbs_pr_debug(1, + lbs_deb_cmd( "SNMP_CMD: action=0x%x, oid=0x%x, oidsize=0x%x, value=0x%x\n", - pSNMPMIB->querytype, pSNMPMIB->oid, pSNMPMIB->bufsize, - *(u16 *) pSNMPMIB->value); + le16_to_cpu(pSNMPMIB->querytype), le16_to_cpu(pSNMPMIB->oid), + le16_to_cpu(pSNMPMIB->bufsize), + le16_to_cpu(*(__le16 *) pSNMPMIB->value)); - LEAVE(); + lbs_deb_leave(LBS_DEB_CMD); return 0; } @@ -495,10 +477,9 @@ static int wlan_cmd_802_11_radio_control(wlan_private * priv, int cmd_action) { wlan_adapter *adapter = priv->adapter; - struct cmd_ds_802_11_radio_control *pradiocontrol = - &cmd->params.radio; + struct cmd_ds_802_11_radio_control *pradiocontrol = &cmd->params.radio; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); cmd->size = cpu_to_le16((sizeof(struct cmd_ds_802_11_radio_control)) + @@ -527,7 +508,7 @@ static int wlan_cmd_802_11_radio_control(wlan_private * priv, else pradiocontrol->control &= cpu_to_le16(~TURN_ON_RF); - LEAVE(); + lbs_deb_leave(LBS_DEB_CMD); return 0; } @@ -538,16 +519,16 @@ static int wlan_cmd_802_11_rf_tx_power(wlan_private * priv, struct cmd_ds_802_11_rf_tx_power *prtp = &cmd->params.txp; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); cmd->size = - cpu_to_le16((sizeof(struct cmd_ds_802_11_rf_tx_power)) + - S_DS_GEN); + cpu_to_le16((sizeof(struct cmd_ds_802_11_rf_tx_power)) + S_DS_GEN); cmd->command = cpu_to_le16(cmd_802_11_rf_tx_power); - prtp->action = cmd_action; + prtp->action = cpu_to_le16(cmd_action); - lbs_pr_debug(1, "RF_TX_POWER_CMD: size:%d cmd:0x%x Act:%d\n", cmd->size, - cmd->command, prtp->action); + lbs_deb_cmd("RF_TX_POWER_CMD: size:%d cmd:0x%x Act:%d\n", + le16_to_cpu(cmd->size), le16_to_cpu(cmd->command), + le16_to_cpu(prtp->action)); switch (cmd_action) { case cmd_act_tx_power_opt_get: @@ -557,14 +538,12 @@ static int wlan_cmd_802_11_rf_tx_power(wlan_private * priv, case cmd_act_tx_power_opt_set_high: prtp->action = cpu_to_le16(cmd_act_set); - prtp->currentlevel = - cpu_to_le16(cmd_act_tx_power_index_high); + prtp->currentlevel = cpu_to_le16(cmd_act_tx_power_index_high); break; case cmd_act_tx_power_opt_set_mid: prtp->action = cpu_to_le16(cmd_act_set); - prtp->currentlevel = - cpu_to_le16(cmd_act_tx_power_index_mid); + prtp->currentlevel = cpu_to_le16(cmd_act_tx_power_index_mid); break; case cmd_act_tx_power_opt_set_low: @@ -572,7 +551,8 @@ static int wlan_cmd_802_11_rf_tx_power(wlan_private * priv, prtp->currentlevel = cpu_to_le16(*((u16 *) pdata_buf)); break; } - LEAVE(); + + lbs_deb_leave(LBS_DEB_CMD); return 0; } @@ -583,15 +563,12 @@ static int wlan_cmd_802_11_rf_antenna(wlan_private * priv, struct cmd_ds_802_11_rf_antenna *rant = &cmd->params.rant; cmd->command = cpu_to_le16(cmd_802_11_rf_antenna); - cmd->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_rf_antenna) + - S_DS_GEN); + cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rf_antenna) + + S_DS_GEN); rant->action = cpu_to_le16(cmd_action); - if ((cmd_action == cmd_act_set_rx) || - (cmd_action == cmd_act_set_tx)) { - rant->antennamode = - cpu_to_le16((u16) (*(u32 *) pdata_buf)); + if ((cmd_action == cmd_act_set_rx) || (cmd_action == cmd_act_set_tx)) { + rant->antennamode = cpu_to_le16((u16) (*(u32 *) pdata_buf)); } return 0; @@ -610,13 +587,13 @@ static int wlan_cmd_802_11_rate_adapt_rateset(wlan_private * priv, + S_DS_GEN); cmd->command = cpu_to_le16(cmd_802_11_rate_adapt_rateset); - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); - rateadapt->action = cmd_action; - rateadapt->enablehwauto = adapter->enablehwauto; - rateadapt->bitmap = adapter->ratebitmap; + rateadapt->action = cpu_to_le16(cmd_action); + rateadapt->enablehwauto = cpu_to_le16(adapter->enablehwauto); + rateadapt->bitmap = cpu_to_le16(adapter->ratebitmap); - LEAVE(); + lbs_deb_leave(LBS_DEB_CMD); return 0; } @@ -626,12 +603,10 @@ static int wlan_cmd_802_11_data_rate(wlan_private * priv, { struct cmd_ds_802_11_data_rate *pdatarate = &cmd->params.drate; wlan_adapter *adapter = priv->adapter; - u16 action = cmd_action; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); - cmd->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_data_rate) + + cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_data_rate) + S_DS_GEN); cmd->command = cpu_to_le16(cmd_802_11_data_rate); @@ -640,15 +615,15 @@ static int wlan_cmd_802_11_data_rate(wlan_private * priv, pdatarate->action = cpu_to_le16(cmd_action); - if (action == cmd_act_set_tx_fix_rate) { + if (cmd_action == cmd_act_set_tx_fix_rate) { pdatarate->datarate[0] = libertas_data_rate_to_index(adapter->datarate); - lbs_pr_debug(1, "Setting FW for fixed rate 0x%02X\n", + lbs_deb_cmd("Setting FW for fixed rate 0x%02X\n", adapter->datarate); - } else if (action == cmd_act_set_tx_auto) { - lbs_pr_debug(1, "Setting FW for AUTO rate\n"); + } else if (cmd_action == cmd_act_set_tx_auto) { + lbs_deb_cmd("Setting FW for AUTO rate\n"); } - LEAVE(); + lbs_deb_leave(LBS_DEB_CMD); return 0; } @@ -659,8 +634,7 @@ static int wlan_cmd_mac_multicast_adr(wlan_private * priv, struct cmd_ds_mac_multicast_adr *pMCastAdr = &cmd->params.madr; wlan_adapter *adapter = priv->adapter; - cmd->size = - cpu_to_le16(sizeof(struct cmd_ds_mac_multicast_adr) + + cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_multicast_adr) + S_DS_GEN); cmd->command = cpu_to_le16(cmd_mac_multicast_adr); @@ -680,8 +654,8 @@ static int wlan_cmd_802_11_rf_channel(wlan_private * priv, struct cmd_ds_802_11_rf_channel *rfchan = &cmd->params.rfchannel; cmd->command = cpu_to_le16(cmd_802_11_rf_channel); - cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rf_channel) - + S_DS_GEN); + cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rf_channel) + + S_DS_GEN); if (option == cmd_opt_802_11_rf_channel_set) { rfchan->currentchannel = cpu_to_le16(*((u16 *) pdata_buf)); @@ -698,9 +672,8 @@ static int wlan_cmd_802_11_rssi(wlan_private * priv, wlan_adapter *adapter = priv->adapter; cmd->command = cpu_to_le16(cmd_802_11_rssi); - cmd->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + S_DS_GEN); - cmd->params.rssi.N = priv->adapter->bcn_avg_factor; + cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + S_DS_GEN); + cmd->params.rssi.N = cpu_to_le16(priv->adapter->bcn_avg_factor); /* reset Beacon SNR/NF/RSSI values */ adapter->SNR[TYPE_BEACON][TYPE_NOAVG] = 0; @@ -719,7 +692,7 @@ static int wlan_cmd_reg_access(wlan_private * priv, { struct wlan_offset_value *offval; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); offval = (struct wlan_offset_value *)pdata_buf; @@ -729,9 +702,8 @@ static int wlan_cmd_reg_access(wlan_private * priv, struct cmd_ds_mac_reg_access *macreg; cmdptr->size = - cpu_to_le16(sizeof - (struct cmd_ds_mac_reg_access) - + S_DS_GEN); + cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access) + + S_DS_GEN); macreg = (struct cmd_ds_mac_reg_access *)&cmdptr->params. macreg; @@ -785,7 +757,7 @@ static int wlan_cmd_reg_access(wlan_private * priv, break; } - LEAVE(); + lbs_deb_leave(LBS_DEB_CMD); return 0; } @@ -796,8 +768,7 @@ static int wlan_cmd_802_11_mac_address(wlan_private * priv, wlan_adapter *adapter = priv->adapter; cmd->command = cpu_to_le16(cmd_802_11_mac_address); - cmd->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_mac_address) + + cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_mac_address) + S_DS_GEN); cmd->result = 0; @@ -818,12 +789,11 @@ static int wlan_cmd_802_11_eeprom_access(wlan_private * priv, { struct wlan_ioctl_regrdwr *ea = pdata_buf; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); cmd->command = cpu_to_le16(cmd_802_11_eeprom_access); - cmd->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) + - S_DS_GEN); + cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) + + S_DS_GEN); cmd->result = 0; cmd->params.rdeeprom.action = cpu_to_le16(ea->action); @@ -839,11 +809,10 @@ static int wlan_cmd_bt_access(wlan_private * priv, u16 cmd_action, void *pdata_buf) { struct cmd_ds_bt_access *bt_access = &cmd->params.bt; - lbs_pr_debug(1, "BT CMD(%d)\n", cmd_action); + lbs_deb_cmd("BT CMD(%d)\n", cmd_action); cmd->command = cpu_to_le16(cmd_bt_access); - cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) - + S_DS_GEN); + cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) + S_DS_GEN); cmd->result = 0; bt_access->action = cpu_to_le16(cmd_action); @@ -861,6 +830,11 @@ static int wlan_cmd_bt_access(wlan_private * priv, break; case cmd_act_bt_access_reset: break; + case cmd_act_bt_access_set_invert: + bt_access->id = cpu_to_le32(*(u32 *) pdata_buf); + break; + case cmd_act_bt_access_get_invert: + break; default: break; } @@ -872,11 +846,10 @@ static int wlan_cmd_fwt_access(wlan_private * priv, u16 cmd_action, void *pdata_buf) { struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt; - lbs_pr_debug(1, "FWT CMD(%d)\n", cmd_action); + lbs_deb_cmd("FWT CMD(%d)\n", cmd_action); cmd->command = cpu_to_le16(cmd_fwt_access); - cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) - + S_DS_GEN); + cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) + S_DS_GEN); cmd->result = 0; if (pdata_buf) @@ -894,11 +867,10 @@ static int wlan_cmd_mesh_access(wlan_private * priv, u16 cmd_action, void *pdata_buf) { struct cmd_ds_mesh_access *mesh_access = &cmd->params.mesh; - lbs_pr_debug(1, "FWT CMD(%d)\n", cmd_action); + lbs_deb_cmd("FWT CMD(%d)\n", cmd_action); cmd->command = cpu_to_le16(cmd_mesh_access); - cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mesh_access) - + S_DS_GEN); + cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mesh_access) + S_DS_GEN); cmd->result = 0; if (pdata_buf) @@ -916,23 +888,23 @@ void libertas_queue_cmd(wlan_adapter * adapter, struct cmd_ctrl_node *cmdnode, u unsigned long flags; struct cmd_ds_command *cmdptr; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); if (!cmdnode) { - lbs_pr_debug(1, "QUEUE_CMD: cmdnode is NULL\n"); + lbs_deb_cmd("QUEUE_CMD: cmdnode is NULL\n"); goto done; } cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr; if (!cmdptr) { - lbs_pr_debug(1, "QUEUE_CMD: cmdptr is NULL\n"); + lbs_deb_cmd("QUEUE_CMD: cmdptr is NULL\n"); goto done; } /* Exit_PS command needs to be queued in the header always. */ if (cmdptr->command == cmd_802_11_ps_mode) { struct cmd_ds_802_11_ps_mode *psm = &cmdptr->params.psmode; - if (psm->action == cmd_subcmd_exit_ps) { + if (psm->action == cpu_to_le16(cmd_subcmd_exit_ps)) { if (adapter->psstate != PS_STATE_FULL_POWER) addtail = 0; } @@ -948,13 +920,12 @@ void libertas_queue_cmd(wlan_adapter * adapter, struct cmd_ctrl_node *cmdnode, u spin_unlock_irqrestore(&adapter->driver_lock, flags); - lbs_pr_debug(1, "QUEUE_CMD: Inserted node=%p, cmd=0x%x in cmdpendingq\n", + lbs_deb_cmd("QUEUE_CMD: Inserted node=%p, cmd=0x%x in cmdpendingq\n", cmdnode, - ((struct cmd_ds_gen*)cmdnode->bufvirtualaddr)->command); + le16_to_cpu(((struct cmd_ds_gen*)cmdnode->bufvirtualaddr)->command)); done: - LEAVE(); - return; + lbs_deb_leave(LBS_DEB_CMD); } /* @@ -974,10 +945,10 @@ static int DownloadcommandToStation(wlan_private * priv, u16 cmdsize; u16 command; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); if (!adapter || !cmdnode) { - lbs_pr_debug(1, "DNLD_CMD: adapter = %p, cmdnode = %p\n", + lbs_deb_cmd("DNLD_CMD: adapter = %p, cmdnode = %p\n", adapter, cmdnode); if (cmdnode) { spin_lock_irqsave(&adapter->driver_lock, flags); @@ -993,7 +964,7 @@ static int DownloadcommandToStation(wlan_private * priv, spin_lock_irqsave(&adapter->driver_lock, flags); if (!cmdptr || !cmdptr->size) { - lbs_pr_debug(1, "DNLD_CMD: cmdptr is Null or cmd size is Zero, " + lbs_deb_cmd("DNLD_CMD: cmdptr is Null or cmd size is Zero, " "Not sending\n"); __libertas_cleanup_and_insert_cmd(priv, cmdnode); spin_unlock_irqrestore(&adapter->driver_lock, flags); @@ -1004,8 +975,8 @@ static int DownloadcommandToStation(wlan_private * priv, adapter->cur_cmd = cmdnode; adapter->cur_cmd_retcode = 0; spin_unlock_irqrestore(&adapter->driver_lock, flags); - lbs_pr_debug(1, "DNLD_CMD:: Before download, size of cmd = %d\n", - cmdptr->size); + lbs_deb_cmd("DNLD_CMD:: Before download, size of cmd = %d\n", + le16_to_cpu(cmdptr->size)); cmdsize = cmdptr->size; @@ -1014,10 +985,10 @@ static int DownloadcommandToStation(wlan_private * priv, cmdnode->cmdwaitqwoken = 0; cmdsize = cpu_to_le16(cmdsize); - ret = libertas_sbi_host_to_card(priv, MVMS_CMD, (u8 *) cmdptr, cmdsize); + ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmdptr, cmdsize); if (ret != 0) { - lbs_pr_debug(1, "DNLD_CMD: Host to Card failed\n"); + lbs_deb_cmd("DNLD_CMD: Host to Card failed\n"); spin_lock_irqsave(&adapter->driver_lock, flags); __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd); adapter->cur_cmd = NULL; @@ -1026,12 +997,11 @@ static int DownloadcommandToStation(wlan_private * priv, goto done; } - lbs_pr_debug(1, "DNLD_CMD: Sent command 0x%x @ %lu\n", command, jiffies); + lbs_deb_cmd("DNLD_CMD: Sent command 0x%x @ %lu\n", command, jiffies); lbs_dbg_hex("DNLD_CMD: command", cmdnode->bufvirtualaddr, cmdsize); /* Setup the timer after transmit command */ - if (command == cmd_802_11_scan - || command == cmd_802_11_authenticate + if (command == cmd_802_11_scan || command == cmd_802_11_authenticate || command == cmd_802_11_associate) mod_timer(&adapter->command_timer, jiffies + (10*HZ)); else @@ -1039,8 +1009,8 @@ static int DownloadcommandToStation(wlan_private * priv, ret = 0; - done: - LEAVE(); +done: + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; } @@ -1049,17 +1019,16 @@ static int wlan_cmd_mac_control(wlan_private * priv, { struct cmd_ds_mac_control *mac = &cmd->params.macctrl; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); cmd->command = cpu_to_le16(cmd_mac_control); - cmd->size = - cpu_to_le16(sizeof(struct cmd_ds_mac_control) + S_DS_GEN); + cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_control) + S_DS_GEN); mac->action = cpu_to_le16(priv->adapter->currentpacketfilter); - lbs_pr_debug(1, "wlan_cmd_mac_control(): action=0x%X size=%d\n", - mac->action, cmd->size); + lbs_deb_cmd("wlan_cmd_mac_control(): action=0x%X size=%d\n", + le16_to_cpu(mac->action), le16_to_cpu(cmd->size)); - LEAVE(); + lbs_deb_leave(LBS_DEB_CMD); return 0; } @@ -1093,17 +1062,17 @@ int libertas_set_radio_control(wlan_private * priv) { int ret = 0; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); ret = libertas_prepare_and_send_command(priv, cmd_802_11_radio_control, cmd_act_set, cmd_option_waitforrsp, 0, NULL); - lbs_pr_debug(1, "RADIO_SET: on or off: 0x%X, preamble = 0x%X\n", + lbs_deb_cmd("RADIO_SET: on or off: 0x%X, preamble = 0x%X\n", priv->adapter->radioon, priv->adapter->preamble); - LEAVE(); + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; } @@ -1111,16 +1080,16 @@ int libertas_set_mac_packet_filter(wlan_private * priv) { int ret = 0; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); - lbs_pr_debug(1, "libertas_set_mac_packet_filter value = %x\n", + lbs_deb_cmd("libertas_set_mac_packet_filter value = %x\n", priv->adapter->currentpacketfilter); /* Send MAC control command to station */ ret = libertas_prepare_and_send_command(priv, cmd_mac_control, 0, 0, 0, NULL); - LEAVE(); + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; } @@ -1146,16 +1115,16 @@ int libertas_prepare_and_send_command(wlan_private * priv, struct cmd_ds_command *cmdptr; unsigned long flags; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); if (!adapter) { - lbs_pr_debug(1, "PREP_CMD: adapter is Null\n"); + lbs_deb_cmd("PREP_CMD: adapter is Null\n"); ret = -1; goto done; } if (adapter->surpriseremoved) { - lbs_pr_debug(1, "PREP_CMD: Card is Removed\n"); + lbs_deb_cmd("PREP_CMD: Card is Removed\n"); ret = -1; goto done; } @@ -1163,7 +1132,7 @@ int libertas_prepare_and_send_command(wlan_private * priv, cmdnode = libertas_get_free_cmd_ctrl_node(priv); if (cmdnode == NULL) { - lbs_pr_debug(1, "PREP_CMD: No free cmdnode\n"); + lbs_deb_cmd("PREP_CMD: No free cmdnode\n"); /* Wake up main thread to execute next command */ wake_up_interruptible(&priv->mainthread.waitq); @@ -1175,11 +1144,11 @@ int libertas_prepare_and_send_command(wlan_private * priv, cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr; - lbs_pr_debug(1, "PREP_CMD: Val of cmd ptr=%p, command=0x%X\n", + lbs_deb_cmd("PREP_CMD: Val of cmd ptr=%p, command=0x%X\n", cmdptr, cmd_no); if (!cmdptr) { - lbs_pr_debug(1, "PREP_CMD: bufvirtualaddr of cmdnode is NULL\n"); + lbs_deb_cmd("PREP_CMD: bufvirtualaddr of cmdnode is NULL\n"); libertas_cleanup_and_insert_cmd(priv, cmdnode); ret = -1; goto done; @@ -1189,7 +1158,7 @@ int libertas_prepare_and_send_command(wlan_private * priv, adapter->seqnum++; cmdptr->seqnum = cpu_to_le16(adapter->seqnum); - cmdptr->command = cmd_no; + cmdptr->command = cpu_to_le16(cmd_no); cmdptr->result = 0; switch (cmd_no) { @@ -1298,13 +1267,13 @@ int libertas_prepare_and_send_command(wlan_private * priv, break; case cmd_802_11_enable_rsn: - ret = wlan_cmd_802_11_enable_rsn(priv, cmdptr, cmd_action); + ret = wlan_cmd_802_11_enable_rsn(priv, cmdptr, cmd_action, + pdata_buf); break; case cmd_802_11_key_material: - ret = wlan_cmd_802_11_key_material(priv, cmdptr, - cmd_action, cmd_oid, - pdata_buf); + ret = wlan_cmd_802_11_key_material(priv, cmdptr, cmd_action, + cmd_oid, pdata_buf); break; case cmd_802_11_pairwise_tsc: @@ -1325,9 +1294,8 @@ int libertas_prepare_and_send_command(wlan_private * priv, case cmd_802_11_get_afc: cmdptr->command = cpu_to_le16(cmd_no); - cmdptr->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) + - S_DS_GEN); + cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) + + S_DS_GEN); memmove(&cmdptr->params.afc, pdata_buf, sizeof(struct cmd_ds_802_11_afc)); @@ -1406,29 +1374,26 @@ int libertas_prepare_and_send_command(wlan_private * priv, case cmd_get_tsf: cmdptr->command = cpu_to_le16(cmd_get_tsf); - cmdptr->size = - cpu_to_le16(sizeof(struct cmd_ds_get_tsf) - + S_DS_GEN); + cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_get_tsf) + + S_DS_GEN); ret = 0; break; case cmd_802_11_tx_rate_query: - cmdptr->command = - cpu_to_le16(cmd_802_11_tx_rate_query); - cmdptr->size = - cpu_to_le16(sizeof(struct cmd_tx_rate_query) + - S_DS_GEN); + cmdptr->command = cpu_to_le16(cmd_802_11_tx_rate_query); + cmdptr->size = cpu_to_le16(sizeof(struct cmd_tx_rate_query) + + S_DS_GEN); adapter->txrate = 0; ret = 0; break; default: - lbs_pr_debug(1, "PREP_CMD: unknown command- %#x\n", cmd_no); + lbs_deb_cmd("PREP_CMD: unknown command- %#x\n", cmd_no); ret = -1; break; } /* return error, since the command preparation failed */ if (ret != 0) { - lbs_pr_debug(1, "PREP_CMD: command preparation failed\n"); + lbs_deb_cmd("PREP_CMD: command preparation failed\n"); libertas_cleanup_and_insert_cmd(priv, cmdnode); ret = -1; goto done; @@ -1441,7 +1406,7 @@ int libertas_prepare_and_send_command(wlan_private * priv, wake_up_interruptible(&priv->mainthread.waitq); if (wait_option & cmd_option_waitforrsp) { - lbs_pr_debug(1, "PREP_CMD: Wait for CMD response\n"); + lbs_deb_cmd("PREP_CMD: Wait for CMD response\n"); might_sleep(); wait_event_interruptible(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken); @@ -1449,7 +1414,7 @@ int libertas_prepare_and_send_command(wlan_private * priv, spin_lock_irqsave(&adapter->driver_lock, flags); if (adapter->cur_cmd_retcode) { - lbs_pr_debug(1, "PREP_CMD: command failed with return code=%d\n", + lbs_deb_cmd("PREP_CMD: command failed with return code=%d\n", adapter->cur_cmd_retcode); adapter->cur_cmd_retcode = 0; ret = -1; @@ -1457,9 +1422,10 @@ int libertas_prepare_and_send_command(wlan_private * priv, spin_unlock_irqrestore(&adapter->driver_lock, flags); done: - LEAVE(); + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; } +EXPORT_SYMBOL_GPL(libertas_prepare_and_send_command); /** * @brief This function allocates the command buffer and link @@ -1477,33 +1443,29 @@ int libertas_allocate_cmd_buffer(wlan_private * priv) u8 *ptempvirtualaddr; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); /* Allocate and initialize cmdCtrlNode */ ulbufsize = sizeof(struct cmd_ctrl_node) * MRVDRV_NUM_OF_CMD_BUFFER; - if (!(tempcmd_array = kmalloc(ulbufsize, GFP_KERNEL))) { - lbs_pr_debug(1, + if (!(tempcmd_array = kzalloc(ulbufsize, GFP_KERNEL))) { + lbs_deb_cmd( "ALLOC_CMD_BUF: failed to allocate tempcmd_array\n"); ret = -1; goto done; } - adapter->cmd_array = tempcmd_array; - memset(adapter->cmd_array, 0, ulbufsize); /* Allocate and initialize command buffers */ ulbufsize = MRVDRV_SIZE_OF_CMD_BUFFER; for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) { - if (!(ptempvirtualaddr = kmalloc(ulbufsize, GFP_KERNEL))) { - lbs_pr_debug(1, + if (!(ptempvirtualaddr = kzalloc(ulbufsize, GFP_KERNEL))) { + lbs_deb_cmd( "ALLOC_CMD_BUF: ptempvirtualaddr: out of memory\n"); ret = -1; goto done; } - memset(ptempvirtualaddr, 0, ulbufsize); - /* Update command buffer virtual */ tempcmd_array[i].bufvirtualaddr = ptempvirtualaddr; } @@ -1514,8 +1476,9 @@ int libertas_allocate_cmd_buffer(wlan_private * priv) } ret = 0; - done: - LEAVE(); + +done: + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; } @@ -1527,16 +1490,16 @@ int libertas_allocate_cmd_buffer(wlan_private * priv) */ int libertas_free_cmd_buffer(wlan_private * priv) { - u32 ulbufsize; + u32 ulbufsize; /* Someone needs to die for this. Slowly and painfully */ unsigned int i; struct cmd_ctrl_node *tempcmd_array; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); /* need to check if cmd array is allocated or not */ if (adapter->cmd_array == NULL) { - lbs_pr_debug(1, "FREE_CMD_BUF: cmd_array is Null\n"); + lbs_deb_cmd("FREE_CMD_BUF: cmd_array is Null\n"); goto done; } @@ -1546,7 +1509,7 @@ int libertas_free_cmd_buffer(wlan_private * priv) ulbufsize = MRVDRV_SIZE_OF_CMD_BUFFER; for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) { if (tempcmd_array[i].bufvirtualaddr) { - lbs_pr_debug(1, "Free all the array\n"); + lbs_deb_cmd("Free all the array\n"); kfree(tempcmd_array[i].bufvirtualaddr); tempcmd_array[i].bufvirtualaddr = NULL; } @@ -1554,13 +1517,13 @@ int libertas_free_cmd_buffer(wlan_private * priv) /* Release cmd_ctrl_node */ if (adapter->cmd_array) { - lbs_pr_debug(1, "Free cmd_array\n"); + lbs_deb_cmd("Free cmd_array\n"); kfree(adapter->cmd_array); adapter->cmd_array = NULL; } done: - LEAVE(); + lbs_deb_leave(LBS_DEB_CMD); return 0; } @@ -1586,16 +1549,18 @@ struct cmd_ctrl_node *libertas_get_free_cmd_ctrl_node(wlan_private * priv) tempnode = (struct cmd_ctrl_node *)adapter->cmdfreeq.next; list_del((struct list_head *)tempnode); } else { - lbs_pr_debug(1, "GET_CMD_NODE: cmd_ctrl_node is not available\n"); + lbs_deb_cmd("GET_CMD_NODE: cmd_ctrl_node is not available\n"); tempnode = NULL; } spin_unlock_irqrestore(&adapter->driver_lock, flags); if (tempnode) { + /* lbs_pr_debug(3, "GET_CMD_NODE: cmdCtrlNode available\n"); lbs_pr_debug(3, "GET_CMD_NODE: cmdCtrlNode Address = %p\n", tempnode); + */ cleanup_cmdnode(tempnode); } @@ -1638,7 +1603,7 @@ void libertas_set_cmd_ctrl_node(wlan_private * priv, struct cmd_ctrl_node *ptempnode, u32 cmd_oid, u16 wait_option, void *pdata_buf) { - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); if (!ptempnode) return; @@ -1647,7 +1612,7 @@ void libertas_set_cmd_ctrl_node(wlan_private * priv, ptempnode->wait_option = wait_option; ptempnode->pdata_buf = pdata_buf; - LEAVE(); + lbs_deb_leave(LBS_DEB_CMD); } /** @@ -1666,7 +1631,7 @@ int libertas_execute_next_command(wlan_private * priv) unsigned long flags; int ret = 0; - lbs_pr_debug(1, "libertas_execute_next_command\n"); + lbs_deb_enter(LBS_DEB_CMD); spin_lock_irqsave(&adapter->driver_lock, flags); @@ -1685,23 +1650,24 @@ int libertas_execute_next_command(wlan_private * priv) spin_unlock_irqrestore(&adapter->driver_lock, flags); if (cmdnode) { - lbs_pr_debug(1, + lbs_deb_cmd( "EXEC_NEXT_CMD: Got next command from cmdpendingq\n"); cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr; if (is_command_allowed_in_ps(cmdptr->command)) { - if ((adapter->psstate == PS_STATE_SLEEP) - || (adapter->psstate == PS_STATE_PRE_SLEEP) - ) { - lbs_pr_debug(1, + if ((adapter->psstate == PS_STATE_SLEEP) || + (adapter->psstate == PS_STATE_PRE_SLEEP)) { + lbs_deb_cmd( "EXEC_NEXT_CMD: Cannot send cmd 0x%x in psstate %d\n", - cmdptr->command, adapter->psstate); + le16_to_cpu(cmdptr->command), + adapter->psstate); ret = -1; goto done; } - lbs_pr_debug(1, "EXEC_NEXT_CMD: OK to send command " + lbs_deb_cmd("EXEC_NEXT_CMD: OK to send command " "0x%x in psstate %d\n", - cmdptr->command, adapter->psstate); + le16_to_cpu(cmdptr->command), + adapter->psstate); } else if (adapter->psstate != PS_STATE_FULL_POWER) { /* * 1. Non-PS command: @@ -1737,12 +1703,12 @@ int libertas_execute_next_command(wlan_private * priv) struct cmd_ds_802_11_ps_mode *psm = &cmdptr->params.psmode; - lbs_pr_debug(1, + lbs_deb_cmd( "EXEC_NEXT_CMD: PS cmd- action=0x%x\n", psm->action); if (psm->action != cpu_to_le16(cmd_subcmd_exit_ps)) { - lbs_pr_debug(1, + lbs_deb_cmd( "EXEC_NEXT_CMD: Ignore Enter PS cmd\n"); list_del((struct list_head *)cmdnode); libertas_cleanup_and_insert_cmd(priv, cmdnode); @@ -1751,10 +1717,9 @@ int libertas_execute_next_command(wlan_private * priv) goto done; } - if ((adapter->psstate == PS_STATE_SLEEP) - || (adapter->psstate == PS_STATE_PRE_SLEEP) - ) { - lbs_pr_debug(1, + if ((adapter->psstate == PS_STATE_SLEEP) || + (adapter->psstate == PS_STATE_PRE_SLEEP)) { + lbs_deb_cmd( "EXEC_NEXT_CMD: Ignore ExitPS cmd in sleep\n"); list_del((struct list_head *)cmdnode); libertas_cleanup_and_insert_cmd(priv, cmdnode); @@ -1764,13 +1729,13 @@ int libertas_execute_next_command(wlan_private * priv) goto done; } - lbs_pr_debug(1, + lbs_deb_cmd( "EXEC_NEXT_CMD: Sending Exit_PS down...\n"); } } list_del((struct list_head *)cmdnode); - lbs_pr_debug(1, "EXEC_NEXT_CMD: Sending 0x%04X command\n", - cmdptr->command); + lbs_deb_cmd("EXEC_NEXT_CMD: Sending 0x%04X command\n", + le16_to_cpu(cmdptr->command)); DownloadcommandToStation(priv, cmdnode); } else { /* @@ -1780,18 +1745,18 @@ int libertas_execute_next_command(wlan_private * priv) if ((adapter->psmode != wlan802_11powermodecam) && (adapter->psstate == PS_STATE_FULL_POWER) && (adapter->connect_status == libertas_connected)) { - if (adapter->secinfo.WPAenabled - || adapter->secinfo.WPA2enabled) { + if (adapter->secinfo.WPAenabled || + adapter->secinfo.WPA2enabled) { /* check for valid WPA group keys */ - if (adapter->wpa_mcast_key.len - || adapter->wpa_unicast_key.len) { - lbs_pr_debug(1, + if (adapter->wpa_mcast_key.len || + adapter->wpa_unicast_key.len) { + lbs_deb_cmd( "EXEC_NEXT_CMD: WPA enabled and GTK_SET" " go back to PS_SLEEP"); libertas_ps_sleep(priv, 0); } } else { - lbs_pr_debug(1, + lbs_deb_cmd( "EXEC_NEXT_CMD: command PendQ is empty," " go back to PS_SLEEP"); libertas_ps_sleep(priv, 0); @@ -1801,6 +1766,7 @@ int libertas_execute_next_command(wlan_private * priv) ret = 0; done: + lbs_deb_leave(LBS_DEB_CMD); return ret; } @@ -1809,7 +1775,7 @@ void libertas_send_iwevcustom_event(wlan_private * priv, s8 * str) union iwreq_data iwrq; u8 buf[50]; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); memset(&iwrq, 0, sizeof(union iwreq_data)); memset(buf, 0, sizeof(buf)); @@ -1819,15 +1785,13 @@ void libertas_send_iwevcustom_event(wlan_private * priv, s8 * str) iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN; /* Send Event to upper layer */ - lbs_pr_debug(1, "Event Indication string = %s\n", - (char *)buf); - lbs_pr_debug(1, "Event Indication String length = %d\n", iwrq.data.length); + lbs_deb_cmd("Event Indication string = %s\n", (char *)buf); + lbs_deb_cmd("Event Indication String length = %d\n", iwrq.data.length); - lbs_pr_debug(1, "Sending wireless event IWEVCUSTOM for %s\n", str); - wireless_send_event(priv->wlan_dev.netdev, IWEVCUSTOM, &iwrq, buf); + lbs_deb_cmd("Sending wireless event IWEVCUSTOM for %s\n", str); + wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf); - LEAVE(); - return; + lbs_deb_leave(LBS_DEB_CMD); } static int sendconfirmsleep(wlan_private * priv, u8 * cmdptr, u16 size) @@ -1836,19 +1800,19 @@ static int sendconfirmsleep(wlan_private * priv, u8 * cmdptr, u16 size) wlan_adapter *adapter = priv->adapter; int ret = 0; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); - lbs_pr_debug(1, "SEND_SLEEPC_CMD: Before download, size of cmd = %d\n", + lbs_deb_cmd("SEND_SLEEPC_CMD: Before download, size of cmd = %d\n", size); lbs_dbg_hex("SEND_SLEEPC_CMD: Sleep confirm command", cmdptr, size); - ret = libertas_sbi_host_to_card(priv, MVMS_CMD, cmdptr, size); - priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED; + ret = priv->hw_host_to_card(priv, MVMS_CMD, cmdptr, size); + priv->dnld_sent = DNLD_RES_RECEIVED; spin_lock_irqsave(&adapter->driver_lock, flags); if (adapter->intcounter || adapter->currenttxskb) - lbs_pr_debug(1, "SEND_SLEEPC_CMD: intcounter=%d currenttxskb=%p\n", + lbs_deb_cmd("SEND_SLEEPC_CMD: intcounter=%d currenttxskb=%p\n", adapter->intcounter, adapter->currenttxskb); spin_unlock_irqrestore(&adapter->driver_lock, flags); @@ -1860,23 +1824,22 @@ static int sendconfirmsleep(wlan_private * priv, u8 * cmdptr, u16 size) if (!adapter->intcounter) { adapter->psstate = PS_STATE_SLEEP; } else { - lbs_pr_debug(1, "SEND_SLEEPC_CMD: After sent,IntC=%d\n", + lbs_deb_cmd("SEND_SLEEPC_CMD: After sent,IntC=%d\n", adapter->intcounter); } spin_unlock_irqrestore(&adapter->driver_lock, flags); - lbs_pr_debug(1, "SEND_SLEEPC_CMD: Sent Confirm Sleep command\n"); - lbs_pr_debug(1, "+"); + lbs_deb_cmd("SEND_SLEEPC_CMD: Sent Confirm Sleep command\n"); + lbs_deb_cmd("+"); } - LEAVE(); + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; } void libertas_ps_sleep(wlan_private * priv, int wait_option) { - - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); /* * PS is currently supported only in Infrastructure mode @@ -1886,8 +1849,7 @@ void libertas_ps_sleep(wlan_private * priv, int wait_option) libertas_prepare_and_send_command(priv, cmd_802_11_ps_mode, cmd_subcmd_enter_ps, wait_option, 0, NULL); - LEAVE(); - return; + lbs_deb_leave(LBS_DEB_CMD); } /** @@ -1899,20 +1861,19 @@ void libertas_ps_sleep(wlan_private * priv, int wait_option) */ void libertas_ps_wakeup(wlan_private * priv, int wait_option) { - enum WLAN_802_11_POWER_MODE Localpsmode; + __le32 Localpsmode; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); - Localpsmode = wlan802_11powermodecam; + Localpsmode = cpu_to_le32(wlan802_11powermodecam); - lbs_pr_debug(1, "Exit_PS: Localpsmode = %d\n", Localpsmode); + lbs_deb_cmd("Exit_PS: Localpsmode = %d\n", wlan802_11powermodecam); libertas_prepare_and_send_command(priv, cmd_802_11_ps_mode, cmd_subcmd_exit_ps, wait_option, 0, &Localpsmode); - LEAVE(); - return; + lbs_deb_leave(LBS_DEB_CMD); } /** @@ -1929,31 +1890,31 @@ void libertas_ps_confirm_sleep(wlan_private * priv, u16 psmode) wlan_adapter *adapter = priv->adapter; u8 allowed = 1; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); - if (priv->wlan_dev.dnld_sent) { + if (priv->dnld_sent) { allowed = 0; - lbs_pr_debug(1, "D"); + lbs_deb_cmd("D"); } spin_lock_irqsave(&adapter->driver_lock, flags); if (adapter->cur_cmd) { allowed = 0; - lbs_pr_debug(1, "C"); + lbs_deb_cmd("C"); } if (adapter->intcounter > 0) { allowed = 0; - lbs_pr_debug(1, "I%d", adapter->intcounter); + lbs_deb_cmd("I%d", adapter->intcounter); } spin_unlock_irqrestore(&adapter->driver_lock, flags); if (allowed) { - lbs_pr_debug(1, "Sending libertas_ps_confirm_sleep\n"); + lbs_deb_cmd("Sending libertas_ps_confirm_sleep\n"); sendconfirmsleep(priv, (u8 *) & adapter->libertas_ps_confirm_sleep, sizeof(struct PS_CMD_ConfirmSleep)); } else { - lbs_pr_debug(1, "Sleep Confirm has been delayed\n"); + lbs_deb_cmd("Sleep Confirm has been delayed\n"); } - LEAVE(); + lbs_deb_leave(LBS_DEB_CMD); } diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index c86454034b5..6ac0d4752fa 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -9,7 +9,6 @@ #include <net/iw_handler.h> #include "host.h" -#include "sbi.h" #include "decl.h" #include "defs.h" #include "dev.h" @@ -32,7 +31,7 @@ void libertas_mac_event_disconnected(wlan_private * priv) if (adapter->connect_status != libertas_connected) return; - lbs_pr_debug(1, "Handles disconnect event.\n"); + lbs_deb_cmd("Handles disconnect event.\n"); memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN); wrqu.ap_addr.sa_family = ARPHRD_ETHER; @@ -43,15 +42,15 @@ void libertas_mac_event_disconnected(wlan_private * priv) */ msleep_interruptible(1000); - wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL); + wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); /* Free Tx and Rx packets */ kfree_skb(priv->adapter->currenttxskb); priv->adapter->currenttxskb = NULL; /* report disconnect to upper layer */ - netif_stop_queue(priv->wlan_dev.netdev); - netif_carrier_off(priv->wlan_dev.netdev); + netif_stop_queue(priv->dev); + netif_carrier_off(priv->dev); /* reset SNR/NF/RSSI values */ memset(adapter->SNR, 0x00, sizeof(adapter->SNR)); @@ -62,35 +61,32 @@ void libertas_mac_event_disconnected(wlan_private * priv) adapter->nextSNRNF = 0; adapter->numSNRNF = 0; adapter->rxpd_rate = 0; - lbs_pr_debug(1, "Current SSID=%s, ssid length=%u\n", - adapter->curbssparams.ssid.ssid, - adapter->curbssparams.ssid.ssidlength); - lbs_pr_debug(1, "Previous SSID=%s, ssid length=%u\n", - adapter->previousssid.ssid, adapter->previousssid.ssidlength); - - /* reset internal flags */ - adapter->secinfo.WPAenabled = 0; - adapter->secinfo.WPA2enabled = 0; - adapter->wpa_ie_len = 0; + lbs_deb_cmd("Current SSID='%s', ssid length=%u\n", + escape_essid(adapter->curbssparams.ssid, + adapter->curbssparams.ssid_len), + adapter->curbssparams.ssid_len); + lbs_deb_cmd("Previous SSID='%s', ssid length=%u\n", + escape_essid(adapter->prev_ssid, adapter->prev_ssid_len), + adapter->prev_ssid_len); adapter->connect_status = libertas_disconnected; - /* - * memorize the previous SSID and BSSID - * it could be used for re-assoc - */ - memcpy(&adapter->previousssid, - &adapter->curbssparams.ssid, sizeof(struct WLAN_802_11_SSID)); - memcpy(adapter->previousbssid, - adapter->curbssparams.bssid, ETH_ALEN); + /* Save previous SSID and BSSID for possible reassociation */ + memcpy(&adapter->prev_ssid, &adapter->curbssparams.ssid, + IW_ESSID_MAX_SIZE); + adapter->prev_ssid_len = adapter->curbssparams.ssid_len; + memcpy(adapter->prev_bssid, adapter->curbssparams.bssid, ETH_ALEN); - /* need to erase the current SSID and BSSID info */ - adapter->pattemptedbssdesc = NULL; - memset(&adapter->curbssparams, 0, sizeof(adapter->curbssparams)); + /* Clear out associated SSID and BSSID since connection is + * no longer valid. + */ + memset(&adapter->curbssparams.bssid, 0, ETH_ALEN); + memset(&adapter->curbssparams.ssid, 0, IW_ESSID_MAX_SIZE); + adapter->curbssparams.ssid_len = 0; if (adapter->psstate != PS_STATE_FULL_POWER) { /* make firmware to exit PS mode */ - lbs_pr_debug(1, "Disconnected, so exit PS mode.\n"); + lbs_deb_cmd("Disconnected, so exit PS mode.\n"); libertas_ps_wakeup(priv, 0); } } @@ -122,55 +118,45 @@ static void handle_mic_failureevent(wlan_private * priv, u32 event) static int wlan_ret_reg_access(wlan_private * priv, u16 type, struct cmd_ds_command *resp) { + int ret = 0; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); switch (type) { case cmd_ret_mac_reg_access: { - struct cmd_ds_mac_reg_access *reg; + struct cmd_ds_mac_reg_access *reg = &resp->params.macreg; - reg = - (struct cmd_ds_mac_reg_access *)&resp->params. - macreg; - - adapter->offsetvalue.offset = reg->offset; - adapter->offsetvalue.value = reg->value; + adapter->offsetvalue.offset = (u32)le16_to_cpu(reg->offset); + adapter->offsetvalue.value = le32_to_cpu(reg->value); break; } case cmd_ret_bbp_reg_access: { - struct cmd_ds_bbp_reg_access *reg; - reg = - (struct cmd_ds_bbp_reg_access *)&resp->params. - bbpreg; + struct cmd_ds_bbp_reg_access *reg = &resp->params.bbpreg; - adapter->offsetvalue.offset = reg->offset; + adapter->offsetvalue.offset = (u32)le16_to_cpu(reg->offset); adapter->offsetvalue.value = reg->value; break; } case cmd_ret_rf_reg_access: { - struct cmd_ds_rf_reg_access *reg; - reg = - (struct cmd_ds_rf_reg_access *)&resp->params. - rfreg; + struct cmd_ds_rf_reg_access *reg = &resp->params.rfreg; - adapter->offsetvalue.offset = reg->offset; + adapter->offsetvalue.offset = (u32)le16_to_cpu(reg->offset); adapter->offsetvalue.value = reg->value; break; } default: - LEAVE(); - return -1; + ret = -1; } - LEAVE(); - return 0; + lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret); + return ret; } static int wlan_ret_get_hw_spec(wlan_private * priv, @@ -181,19 +167,20 @@ static int wlan_ret_get_hw_spec(wlan_private * priv, wlan_adapter *adapter = priv->adapter; int ret = 0; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); adapter->fwcapinfo = le32_to_cpu(hwspec->fwcapinfo); - adapter->fwreleasenumber = hwspec->fwreleasenumber; + memcpy(adapter->fwreleasenumber, hwspec->fwreleasenumber, 4); - lbs_pr_debug(1, "GET_HW_SPEC: FWReleaseVersion- 0x%X\n", - adapter->fwreleasenumber); - lbs_pr_debug(1, "GET_HW_SPEC: Permanent addr- %2x:%2x:%2x:%2x:%2x:%2x\n", + lbs_deb_cmd("GET_HW_SPEC: FWReleaseVersion- %u.%u.%u.p%u\n", + adapter->fwreleasenumber[2], adapter->fwreleasenumber[1], + adapter->fwreleasenumber[0], adapter->fwreleasenumber[3]); + lbs_deb_cmd("GET_HW_SPEC: Permanent addr- %2x:%2x:%2x:%2x:%2x:%2x\n", hwspec->permanentaddr[0], hwspec->permanentaddr[1], hwspec->permanentaddr[2], hwspec->permanentaddr[3], hwspec->permanentaddr[4], hwspec->permanentaddr[5]); - lbs_pr_debug(1, "GET_HW_SPEC: hwifversion=0x%X version=0x%X\n", + lbs_deb_cmd("GET_HW_SPEC: hwifversion=0x%X version=0x%X\n", hwspec->hwifversion, hwspec->version); adapter->regioncode = le16_to_cpu(hwspec->regioncode); @@ -210,17 +197,15 @@ static int wlan_ret_get_hw_spec(wlan_private * priv, if (i >= MRVDRV_MAX_REGION_CODE) { adapter->regioncode = 0x10; adapter->regiontableindex = 0; - lbs_pr_info( - "unidentified region code, use the default (USA)\n"); + lbs_pr_info("unidentified region code; using the default (USA)\n"); } - if (adapter->current_addr[0] == 0xff) { - memmove(adapter->current_addr, hwspec->permanentaddr, - ETH_ALEN); - } + if (adapter->current_addr[0] == 0xff) + memmove(adapter->current_addr, hwspec->permanentaddr, ETH_ALEN); - memcpy(priv->wlan_dev.netdev->dev_addr, adapter->current_addr, ETH_ALEN); - memcpy(priv->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN); + memcpy(priv->dev->dev_addr, adapter->current_addr, ETH_ALEN); + if (priv->mesh_dev) + memcpy(priv->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN); if (libertas_set_regiontable(priv, adapter->regioncode, 0)) { ret = -1; @@ -232,8 +217,8 @@ static int wlan_ret_get_hw_spec(wlan_private * priv, goto done; } - done: - LEAVE(); +done: + lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret); return ret; } @@ -243,19 +228,21 @@ static int wlan_ret_802_11_sleep_params(wlan_private * priv, struct cmd_ds_802_11_sleep_params *sp = &resp->params.sleep_params; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); + + lbs_deb_cmd("error=%x offset=%x stabletime=%x calcontrol=%x\n" + " extsleepclk=%x\n", le16_to_cpu(sp->error), + le16_to_cpu(sp->offset), le16_to_cpu(sp->stabletime), + sp->calcontrol, sp->externalsleepclk); - lbs_pr_debug(1, "error=%x offset=%x stabletime=%x calcontrol=%x\n" - " extsleepclk=%x\n", sp->error, sp->offset, - sp->stabletime, sp->calcontrol, sp->externalsleepclk); adapter->sp.sp_error = le16_to_cpu(sp->error); adapter->sp.sp_offset = le16_to_cpu(sp->offset); adapter->sp.sp_stabletime = le16_to_cpu(sp->stabletime); - adapter->sp.sp_calcontrol = le16_to_cpu(sp->calcontrol); - adapter->sp.sp_extsleepclk = le16_to_cpu(sp->externalsleepclk); + adapter->sp.sp_calcontrol = sp->calcontrol; + adapter->sp.sp_extsleepclk = sp->externalsleepclk; adapter->sp.sp_reserved = le16_to_cpu(sp->reserved); - LEAVE(); + lbs_deb_enter(LBS_DEB_CMD); return 0; } @@ -281,42 +268,38 @@ static int wlan_ret_802_11_snmp_mib(wlan_private * priv, u16 oid = le16_to_cpu(smib->oid); u16 querytype = le16_to_cpu(smib->querytype); - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); - lbs_pr_debug(1, "SNMP_RESP: value of the oid = %x, querytype=%x\n", oid, + lbs_deb_cmd("SNMP_RESP: value of the oid = %x, querytype=%x\n", oid, querytype); - lbs_pr_debug(1, "SNMP_RESP: Buf size = %x\n", - le16_to_cpu(smib->bufsize)); + lbs_deb_cmd("SNMP_RESP: Buf size = %x\n", le16_to_cpu(smib->bufsize)); if (querytype == cmd_act_get) { switch (oid) { case fragthresh_i: priv->adapter->fragthsd = - le16_to_cpu(* - ((unsigned short *)(smib->value))); - lbs_pr_debug(1, "SNMP_RESP: fragthsd =%u\n", - priv->adapter->fragthsd); + le16_to_cpu(*((__le16 *)(smib->value))); + lbs_deb_cmd("SNMP_RESP: fragthsd =%u\n", + priv->adapter->fragthsd); break; case rtsthresh_i: priv->adapter->rtsthsd = - le16_to_cpu(* - ((unsigned short *)(smib->value))); - lbs_pr_debug(1, "SNMP_RESP: rtsthsd =%u\n", - priv->adapter->rtsthsd); + le16_to_cpu(*((__le16 *)(smib->value))); + lbs_deb_cmd("SNMP_RESP: rtsthsd =%u\n", + priv->adapter->rtsthsd); break; case short_retrylim_i: priv->adapter->txretrycount = - le16_to_cpu(* - ((unsigned short *)(smib->value))); - lbs_pr_debug(1, "SNMP_RESP: txretrycount =%u\n", - priv->adapter->rtsthsd); + le16_to_cpu(*((__le16 *)(smib->value))); + lbs_deb_cmd("SNMP_RESP: txretrycount =%u\n", + priv->adapter->rtsthsd); break; default: break; } } - LEAVE(); + lbs_deb_enter(LBS_DEB_CMD); return 0; } @@ -328,7 +311,7 @@ static int wlan_ret_802_11_key_material(wlan_private * priv, wlan_adapter *adapter = priv->adapter; u16 action = le16_to_cpu(pkeymaterial->action); - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); /* Copy the returned key to driver private data */ if (action == cmd_act_get) { @@ -371,7 +354,7 @@ static int wlan_ret_802_11_key_material(wlan_private * priv, } } - LEAVE(); + lbs_deb_enter(LBS_DEB_CMD); return 0; } @@ -381,11 +364,11 @@ static int wlan_ret_802_11_mac_address(wlan_private * priv, struct cmd_ds_802_11_mac_address *macadd = &resp->params.macadd; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); memcpy(adapter->current_addr, macadd->macadd, ETH_ALEN); - LEAVE(); + lbs_deb_enter(LBS_DEB_CMD); return 0; } @@ -395,13 +378,13 @@ static int wlan_ret_802_11_rf_tx_power(wlan_private * priv, struct cmd_ds_802_11_rf_tx_power *rtp = &resp->params.txp; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); adapter->txpowerlevel = le16_to_cpu(rtp->currentlevel); - lbs_pr_debug(1, "Current TxPower Level = %d\n", adapter->txpowerlevel); + lbs_deb_cmd("Current TxPower Level = %d\n", adapter->txpowerlevel); - LEAVE(); + lbs_deb_enter(LBS_DEB_CMD); return 0; } @@ -413,14 +396,12 @@ static int wlan_ret_802_11_rf_antenna(wlan_private * priv, u16 action = le16_to_cpu(pAntenna->action); if (action == cmd_act_get_rx) - adapter->rxantennamode = - le16_to_cpu(pAntenna->antennamode); + adapter->rxantennamode = le16_to_cpu(pAntenna->antennamode); if (action == cmd_act_get_tx) - adapter->txantennamode = - le16_to_cpu(pAntenna->antennamode); + adapter->txantennamode = le16_to_cpu(pAntenna->antennamode); - lbs_pr_debug(1, "RF_ANT_RESP: action = 0x%x, mode = 0x%04x\n", + lbs_deb_cmd("RF_ANT_RESP: action = 0x%x, mode = 0x%04x\n", action, le16_to_cpu(pAntenna->antennamode)); return 0; @@ -429,19 +410,17 @@ static int wlan_ret_802_11_rf_antenna(wlan_private * priv, static int wlan_ret_802_11_rate_adapt_rateset(wlan_private * priv, struct cmd_ds_command *resp) { - struct cmd_ds_802_11_rate_adapt_rateset *rates = - &resp->params.rateset; + struct cmd_ds_802_11_rate_adapt_rateset *rates = &resp->params.rateset; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); if (rates->action == cmd_act_get) { - adapter->enablehwauto = rates->enablehwauto; - adapter->ratebitmap = rates->bitmap; + adapter->enablehwauto = le16_to_cpu(rates->enablehwauto); + adapter->ratebitmap = le16_to_cpu(rates->bitmap); } - LEAVE(); - + lbs_deb_enter(LBS_DEB_CMD); return 0; } @@ -452,43 +431,42 @@ static int wlan_ret_802_11_data_rate(wlan_private * priv, wlan_adapter *adapter = priv->adapter; u8 dot11datarate; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); lbs_dbg_hex("DATA_RATE_RESP: data_rate- ", (u8 *) pdatarate, sizeof(struct cmd_ds_802_11_data_rate)); dot11datarate = pdatarate->datarate[0]; - if (pdatarate->action == cmd_act_get_tx_rate) { + if (pdatarate->action == cpu_to_le16(cmd_act_get_tx_rate)) { memcpy(adapter->libertas_supported_rates, pdatarate->datarate, sizeof(adapter->libertas_supported_rates)); } adapter->datarate = libertas_index_to_data_rate(dot11datarate); - LEAVE(); + lbs_deb_enter(LBS_DEB_CMD); return 0; } static int wlan_ret_802_11_rf_channel(wlan_private * priv, struct cmd_ds_command *resp) { - struct cmd_ds_802_11_rf_channel *rfchannel = - &resp->params.rfchannel; + struct cmd_ds_802_11_rf_channel *rfchannel = &resp->params.rfchannel; wlan_adapter *adapter = priv->adapter; u16 action = le16_to_cpu(rfchannel->action); u16 newchannel = le16_to_cpu(rfchannel->currentchannel); - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); if (action == cmd_opt_802_11_rf_channel_get && adapter->curbssparams.channel != newchannel) { - lbs_pr_debug(1, "channel Switch: %d to %d\n", + lbs_deb_cmd("channel Switch: %d to %d\n", adapter->curbssparams.channel, newchannel); /* Update the channel again */ adapter->curbssparams.channel = newchannel; } - LEAVE(); + lbs_deb_enter(LBS_DEB_CMD); return 0; } @@ -500,12 +478,10 @@ static int wlan_ret_802_11_rssi(wlan_private * priv, /* store the non average value */ adapter->SNR[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->SNR); - adapter->NF[TYPE_BEACON][TYPE_NOAVG] = - le16_to_cpu(rssirsp->noisefloor); + adapter->NF[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->noisefloor); adapter->SNR[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgSNR); - adapter->NF[TYPE_BEACON][TYPE_AVG] = - le16_to_cpu(rssirsp->avgnoisefloor); + adapter->NF[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgnoisefloor); adapter->RSSI[TYPE_BEACON][TYPE_NOAVG] = CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_NOAVG], @@ -515,7 +491,7 @@ static int wlan_ret_802_11_rssi(wlan_private * priv, CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE, adapter->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE); - lbs_pr_debug(1, "Beacon RSSI value = 0x%x\n", + lbs_deb_cmd("Beacon RSSI value = 0x%x\n", adapter->RSSI[TYPE_BEACON][TYPE_AVG]); return 0; @@ -528,11 +504,11 @@ static int wlan_ret_802_11_eeprom_access(wlan_private * priv, struct wlan_ioctl_regrdwr *pbuf; pbuf = (struct wlan_ioctl_regrdwr *) adapter->prdeeprom; - lbs_pr_debug(1, "eeprom read len=%x\n", + lbs_deb_cmd("eeprom read len=%x\n", le16_to_cpu(resp->params.rdeeprom.bytecount)); if (pbuf->NOB < le16_to_cpu(resp->params.rdeeprom.bytecount)) { pbuf->NOB = 0; - lbs_pr_debug(1, "eeprom read return length is too big\n"); + lbs_deb_cmd("eeprom read return length is too big\n"); return -1; } pbuf->NOB = le16_to_cpu(resp->params.rdeeprom.bytecount); @@ -549,17 +525,33 @@ static int wlan_ret_802_11_eeprom_access(wlan_private * priv, static int wlan_ret_get_log(wlan_private * priv, struct cmd_ds_command *resp) { - struct cmd_ds_802_11_get_log *logmessage = - (struct cmd_ds_802_11_get_log *)&resp->params.glog; + struct cmd_ds_802_11_get_log *logmessage = &resp->params.glog; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); - /* TODO Convert it to Big Endian before copy */ - memcpy(&adapter->logmsg, logmessage, - sizeof(struct cmd_ds_802_11_get_log)); + /* Stored little-endian */ + memcpy(&adapter->logmsg, logmessage, sizeof(struct cmd_ds_802_11_get_log)); - LEAVE(); + lbs_deb_enter(LBS_DEB_CMD); + return 0; +} + +static int libertas_ret_802_11_enable_rsn(wlan_private * priv, + struct cmd_ds_command *resp) +{ + struct cmd_ds_802_11_enable_rsn *enable_rsn = &resp->params.enbrsn; + wlan_adapter *adapter = priv->adapter; + u32 * pdata_buf = adapter->cur_cmd->pdata_buf; + + lbs_deb_enter(LBS_DEB_CMD); + + if (enable_rsn->action == cpu_to_le16(cmd_act_get)) { + if (pdata_buf) + *pdata_buf = (u32) le16_to_cpu(enable_rsn->enable); + } + + lbs_deb_enter(LBS_DEB_CMD); return 0; } @@ -620,8 +612,7 @@ static inline int handle_cmd_response(u16 respcmd, case cmd_ret_802_11_set_afc: case cmd_ret_802_11_get_afc: spin_lock_irqsave(&adapter->driver_lock, flags); - memmove(adapter->cur_cmd->pdata_buf, - &resp->params.afc, + memmove(adapter->cur_cmd->pdata_buf, &resp->params.afc, sizeof(struct cmd_ds_802_11_afc)); spin_unlock_irqrestore(&adapter->driver_lock, flags); @@ -637,7 +628,10 @@ static inline int handle_cmd_response(u16 respcmd, case cmd_ret_802_11_authenticate: case cmd_ret_802_11_radio_control: case cmd_ret_802_11_beacon_stop: + break; + case cmd_ret_802_11_enable_rsn: + ret = libertas_ret_802_11_enable_rsn(priv, resp); break; case cmd_ret_802_11_data_rate: @@ -663,7 +657,7 @@ static inline int handle_cmd_response(u16 respcmd, break; case cmd_ret_802_11_key_material: - lbs_pr_debug(1, "CMD_RESP: KEY_MATERIAL command response\n"); + lbs_deb_cmd("CMD_RESP: KEY_MATERIAL command response\n"); ret = wlan_ret_802_11_key_material(priv, resp); break; @@ -687,22 +681,19 @@ static inline int handle_cmd_response(u16 respcmd, case cmd_ret_802_11_tpc_cfg: spin_lock_irqsave(&adapter->driver_lock, flags); - memmove(adapter->cur_cmd->pdata_buf, - &resp->params.tpccfg, + memmove(adapter->cur_cmd->pdata_buf, &resp->params.tpccfg, sizeof(struct cmd_ds_802_11_tpc_cfg)); spin_unlock_irqrestore(&adapter->driver_lock, flags); break; case cmd_ret_802_11_led_gpio_ctrl: spin_lock_irqsave(&adapter->driver_lock, flags); - memmove(adapter->cur_cmd->pdata_buf, - &resp->params.ledgpio, + memmove(adapter->cur_cmd->pdata_buf, &resp->params.ledgpio, sizeof(struct cmd_ds_802_11_led_ctrl)); spin_unlock_irqrestore(&adapter->driver_lock, flags); break; case cmd_ret_802_11_pwr_cfg: spin_lock_irqsave(&adapter->driver_lock, flags); - memmove(adapter->cur_cmd->pdata_buf, - &resp->params.pwrcfg, + memmove(adapter->cur_cmd->pdata_buf, &resp->params.pwrcfg, sizeof(struct cmd_ds_802_11_pwr_cfg)); spin_unlock_irqrestore(&adapter->driver_lock, flags); @@ -724,23 +715,21 @@ static inline int handle_cmd_response(u16 respcmd, case cmd_ret_fwt_access: spin_lock_irqsave(&adapter->driver_lock, flags); if (adapter->cur_cmd->pdata_buf) - memcpy(adapter->cur_cmd->pdata_buf, - &resp->params.fwt, - sizeof(resp->params.fwt)); + memcpy(adapter->cur_cmd->pdata_buf, &resp->params.fwt, + sizeof(resp->params.fwt)); spin_unlock_irqrestore(&adapter->driver_lock, flags); break; case cmd_ret_mesh_access: if (adapter->cur_cmd->pdata_buf) - memcpy(adapter->cur_cmd->pdata_buf, - &resp->params.mesh, + memcpy(adapter->cur_cmd->pdata_buf, &resp->params.mesh, sizeof(resp->params.mesh)); break; case cmd_rte_802_11_tx_rate_query: priv->adapter->txrate = resp->params.txrate.txrate; break; default: - lbs_pr_debug(1, "CMD_RESP: Unknown command response %#x\n", - resp->command); + lbs_deb_cmd("CMD_RESP: Unknown command response %#x\n", + resp->command); break; } return ret; @@ -755,9 +744,9 @@ int libertas_process_rx_command(wlan_private * priv) ulong flags; u16 result; - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); - lbs_pr_debug(1, "CMD_RESP: @ %lu\n", jiffies); + lbs_deb_cmd("CMD_RESP: @ %lu\n", jiffies); /* Now we got response from FW, cancel the command timer */ del_timer(&adapter->command_timer); @@ -766,7 +755,7 @@ int libertas_process_rx_command(wlan_private * priv) spin_lock_irqsave(&adapter->driver_lock, flags); if (!adapter->cur_cmd) { - lbs_pr_debug(1, "CMD_RESP: NULL cur_cmd=%p\n", adapter->cur_cmd); + lbs_deb_cmd("CMD_RESP: NULL cur_cmd=%p\n", adapter->cur_cmd); ret = -1; spin_unlock_irqrestore(&adapter->driver_lock, flags); goto done; @@ -774,17 +763,17 @@ int libertas_process_rx_command(wlan_private * priv) resp = (struct cmd_ds_command *)(adapter->cur_cmd->bufvirtualaddr); lbs_dbg_hex("CMD_RESP:", adapter->cur_cmd->bufvirtualaddr, - priv->wlan_dev.upld_len); + priv->upld_len); respcmd = le16_to_cpu(resp->command); result = le16_to_cpu(resp->result); - lbs_pr_debug(1, "CMD_RESP: %x result: %d length: %d\n", respcmd, - result, priv->wlan_dev.upld_len); + lbs_deb_cmd("CMD_RESP: %x result: %d length: %d\n", respcmd, + result, priv->upld_len); if (!(respcmd & 0x8000)) { - lbs_pr_debug(1, "Invalid response to command!"); + lbs_deb_cmd("Invalid response to command!"); adapter->cur_cmd_retcode = -1; __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd); adapter->nr_cmd_pending--; @@ -795,56 +784,52 @@ int libertas_process_rx_command(wlan_private * priv) } /* Store the response code to cur_cmd_retcode. */ - adapter->cur_cmd_retcode = le16_to_cpu(resp->result); + adapter->cur_cmd_retcode = result;; if (respcmd == cmd_ret_802_11_ps_mode) { - struct cmd_ds_802_11_ps_mode *psmode; + struct cmd_ds_802_11_ps_mode *psmode = &resp->params.psmode; + u16 action = le16_to_cpu(psmode->action); - psmode = &resp->params.psmode; - lbs_pr_debug(1, + lbs_deb_cmd( "CMD_RESP: PS_MODE cmd reply result=%#x action=0x%X\n", - resp->result, psmode->action); - psmode->action = cpu_to_le16(psmode->action); + result, action); if (result) { - lbs_pr_debug(1, "CMD_RESP: PS command failed- %#x \n", - resp->result); - if (adapter->mode == IW_MODE_ADHOC) { - /* - * We should not re-try enter-ps command in - * ad-hoc mode. It takes place in - * libertas_execute_next_command(). - */ - if (psmode->action == cmd_subcmd_enter_ps) - adapter->psmode = - wlan802_11powermodecam; - } - } else if (psmode->action == cmd_subcmd_enter_ps) { + lbs_deb_cmd("CMD_RESP: PS command failed- %#x \n", + result); + /* + * We should not re-try enter-ps command in + * ad-hoc mode. It takes place in + * libertas_execute_next_command(). + */ + if (adapter->mode == IW_MODE_ADHOC && + action == cmd_subcmd_enter_ps) + adapter->psmode = wlan802_11powermodecam; + } else if (action == cmd_subcmd_enter_ps) { adapter->needtowakeup = 0; adapter->psstate = PS_STATE_AWAKE; - lbs_pr_debug(1, "CMD_RESP: Enter_PS command response\n"); + lbs_deb_cmd("CMD_RESP: Enter_PS command response\n"); if (adapter->connect_status != libertas_connected) { /* * When Deauth Event received before Enter_PS command * response, We need to wake up the firmware. */ - lbs_pr_debug(1, + lbs_deb_cmd( "Disconnected, Going to invoke libertas_ps_wakeup\n"); - mutex_unlock(&adapter->lock); spin_unlock_irqrestore(&adapter->driver_lock, flags); + mutex_unlock(&adapter->lock); libertas_ps_wakeup(priv, 0); mutex_lock(&adapter->lock); spin_lock_irqsave(&adapter->driver_lock, flags); } - } else if (psmode->action == cmd_subcmd_exit_ps) { + } else if (action == cmd_subcmd_exit_ps) { adapter->needtowakeup = 0; adapter->psstate = PS_STATE_FULL_POWER; - lbs_pr_debug(1, "CMD_RESP: Exit_PS command response\n"); + lbs_deb_cmd("CMD_RESP: Exit_PS command response\n"); } else { - lbs_pr_debug(1, "CMD_RESP: PS- action=0x%X\n", - psmode->action); + lbs_deb_cmd("CMD_RESP: PS- action=0x%X\n", action); } __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd); @@ -865,15 +850,15 @@ int libertas_process_rx_command(wlan_private * priv) /* If the command is not successful, cleanup and return failure */ if ((result != 0 || !(respcmd & 0x8000))) { - lbs_pr_debug(1, "CMD_RESP: command reply %#x result=%#x\n", - resp->command, resp->result); + lbs_deb_cmd("CMD_RESP: command reply %#x result=%#x\n", + respcmd, result); /* * Handling errors here */ switch (respcmd) { case cmd_ret_hw_spec_info: case cmd_ret_802_11_reset: - lbs_pr_debug(1, "CMD_RESP: Reset command failed\n"); + lbs_deb_cmd("CMD_RESP: Reset command failed\n"); break; } @@ -903,7 +888,7 @@ int libertas_process_rx_command(wlan_private * priv) done: mutex_unlock(&adapter->lock); - LEAVE(); + lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret); return ret; } @@ -917,37 +902,37 @@ int libertas_process_event(wlan_private * priv) eventcause = adapter->eventcause; spin_unlock_irq(&adapter->driver_lock); - ENTER(); + lbs_deb_enter(LBS_DEB_CMD); - lbs_pr_debug(1, "EVENT Cause %x\n", eventcause); + lbs_deb_cmd("EVENT Cause %x\n", eventcause); switch (eventcause >> SBI_EVENT_CAUSE_SHIFT) { case MACREG_INT_CODE_LINK_SENSED: - lbs_pr_debug(1, "EVENT: MACREG_INT_CODE_LINK_SENSED\n"); + lbs_deb_cmd("EVENT: MACREG_INT_CODE_LINK_SENSED\n"); break; case MACREG_INT_CODE_DEAUTHENTICATED: - lbs_pr_debug(1, "EVENT: Deauthenticated\n"); + lbs_deb_cmd("EVENT: Deauthenticated\n"); libertas_mac_event_disconnected(priv); break; case MACREG_INT_CODE_DISASSOCIATED: - lbs_pr_debug(1, "EVENT: Disassociated\n"); + lbs_deb_cmd("EVENT: Disassociated\n"); libertas_mac_event_disconnected(priv); break; case MACREG_INT_CODE_LINK_LOSE_NO_SCAN: - lbs_pr_debug(1, "EVENT: Link lost\n"); + lbs_deb_cmd("EVENT: Link lost\n"); libertas_mac_event_disconnected(priv); break; case MACREG_INT_CODE_PS_SLEEP: - lbs_pr_debug(1, "EVENT: SLEEP\n"); - lbs_pr_debug(1, "_"); + lbs_deb_cmd("EVENT: SLEEP\n"); + lbs_deb_cmd("_"); /* handle unexpected PS SLEEP event */ if (adapter->psstate == PS_STATE_FULL_POWER) { - lbs_pr_debug(1, + lbs_deb_cmd( "EVENT: In FULL POWER mode - ignore PS SLEEP\n"); break; } @@ -958,12 +943,12 @@ int libertas_process_event(wlan_private * priv) break; case MACREG_INT_CODE_PS_AWAKE: - lbs_pr_debug(1, "EVENT: AWAKE \n"); - lbs_pr_debug(1, "|"); + lbs_deb_cmd("EVENT: AWAKE \n"); + lbs_deb_cmd("|"); /* handle unexpected PS AWAKE event */ if (adapter->psstate == PS_STATE_FULL_POWER) { - lbs_pr_debug(1, + lbs_deb_cmd( "EVENT: In FULL POWER mode - ignore PS AWAKE\n"); break; } @@ -977,18 +962,18 @@ int libertas_process_event(wlan_private * priv) * adapter->needtowakeup will be set to FALSE * in libertas_ps_wakeup() */ - lbs_pr_debug(1, "Waking up...\n"); + lbs_deb_cmd("Waking up...\n"); libertas_ps_wakeup(priv, 0); } break; case MACREG_INT_CODE_MIC_ERR_UNICAST: - lbs_pr_debug(1, "EVENT: UNICAST MIC ERROR\n"); + lbs_deb_cmd("EVENT: UNICAST MIC ERROR\n"); handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_UNICAST); break; case MACREG_INT_CODE_MIC_ERR_MULTICAST: - lbs_pr_debug(1, "EVENT: MULTICAST MIC ERROR\n"); + lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n"); handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST); break; case MACREG_INT_CODE_MIB_CHANGED: @@ -996,7 +981,7 @@ int libertas_process_event(wlan_private * priv) break; case MACREG_INT_CODE_ADHOC_BCN_LOST: - lbs_pr_debug(1, "EVENT: HWAC - ADHOC BCN LOST\n"); + lbs_deb_cmd("EVENT: HWAC - ADHOC BCN LOST\n"); break; case MACREG_INT_CODE_RSSI_LOW: @@ -1015,6 +1000,17 @@ int libertas_process_event(wlan_private * priv) lbs_pr_alert( "EVENT: SNR_HIGH\n"); break; + case MACREG_INT_CODE_MESH_AUTO_STARTED: + lbs_pr_alert( "EVENT: MESH_AUTO_STARTED\n"); + adapter->connect_status = libertas_connected ; + if (priv->mesh_open == 1) { + netif_wake_queue(priv->mesh_dev) ; + netif_carrier_on(priv->mesh_dev) ; + } + adapter->mode = IW_MODE_ADHOC ; + schedule_work(&priv->sync_channel); + break; + default: lbs_pr_alert( "EVENT: unknown event id: %#x\n", eventcause >> SBI_EVENT_CAUSE_SHIFT); @@ -1024,6 +1020,7 @@ int libertas_process_event(wlan_private * priv) spin_lock_irq(&adapter->driver_lock); adapter->eventcause = 0; spin_unlock_irq(&adapter->driver_lock); - LEAVE(); + + lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret); return ret; } diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index 7d7bc5e86a5..715cbdaa1d4 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -4,6 +4,7 @@ #include <linux/delay.h> #include <linux/mm.h> #include <net/iw_handler.h> + #include "dev.h" #include "decl.h" #include "host.h" @@ -15,7 +16,9 @@ static char *szStates[] = { "Disconnected" }; -void libertas_debug_init(wlan_private * priv, struct net_device *dev); +#ifdef PROC_DEBUG +static void libertas_debug_init(wlan_private * priv, struct net_device *dev); +#endif static int open_file_generic(struct inode *inode, struct file *file) { @@ -60,43 +63,33 @@ static ssize_t libertas_getscantable(struct file *file, char __user *userbuf, int numscansdone = 0, res; unsigned long addr = get_zeroed_page(GFP_KERNEL); char *buf = (char *)addr; + struct bss_descriptor * iter_bss; pos += snprintf(buf+pos, len-pos, - "---------------------------------------"); - pos += snprintf(buf+pos, len-pos, - "---------------------------------------\n"); - pos += snprintf(buf+pos, len-pos, "# | ch | ss | bssid | cap | TSF | Qual | SSID \n"); - pos += snprintf(buf+pos, len-pos, - "---------------------------------------"); - pos += snprintf(buf+pos, len-pos, - "---------------------------------------\n"); - while (numscansdone < priv->adapter->numinscantable) { - struct bss_descriptor *pbssinfo; + mutex_lock(&priv->adapter->lock); + list_for_each_entry (iter_bss, &priv->adapter->network_list, list) { u16 cap; - pbssinfo = &priv->adapter->scantable[numscansdone]; - memcpy(&cap, &pbssinfo->cap, sizeof(cap)); + memcpy(&cap, &iter_bss->cap, sizeof(cap)); pos += snprintf(buf+pos, len-pos, - "%02u| %03d | %03ld | %02x:%02x:%02x:%02x:%02x:%02x |", - numscansdone, pbssinfo->channel, pbssinfo->rssi, - pbssinfo->macaddress[0], pbssinfo->macaddress[1], - pbssinfo->macaddress[2], pbssinfo->macaddress[3], - pbssinfo->macaddress[4], pbssinfo->macaddress[5]); + "%02u| %03d | %03ld | " MAC_FMT " |", + numscansdone, iter_bss->channel, iter_bss->rssi, + MAC_ARG(iter_bss->bssid)); pos += snprintf(buf+pos, len-pos, " %04x-", cap); pos += snprintf(buf+pos, len-pos, "%c%c%c |", - pbssinfo->cap.ibss ? 'A' : 'I', - pbssinfo->cap.privacy ? 'P' : ' ', - pbssinfo->cap.spectrummgmt ? 'S' : ' '); - pos += snprintf(buf+pos, len-pos, " %08llx |", pbssinfo->networktsf); - pos += snprintf(buf+pos, len-pos, " %d |", - SCAN_RSSI(priv->adapter->scantable[numscansdone].rssi)); - - pos += snprintf(buf+pos, len-pos, " %s\n", pbssinfo->ssid.ssid); + iter_bss->cap.ibss ? 'A' : 'I', + iter_bss->cap.privacy ? 'P' : ' ', + iter_bss->cap.spectrummgmt ? 'S' : ' '); + pos += snprintf(buf+pos, len-pos, " %08llx |", iter_bss->networktsf); + pos += snprintf(buf+pos, len-pos, " %d |", SCAN_RSSI(iter_bss->rssi)); + pos += snprintf(buf+pos, len-pos, " %s\n", + escape_essid(iter_bss->ssid, iter_bss->ssid_len)); numscansdone++; } + mutex_unlock(&priv->adapter->lock); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); @@ -111,7 +104,6 @@ static ssize_t libertas_sleepparams_write(struct file *file, wlan_private *priv = file->private_data; ssize_t buf_size, res; int p1, p2, p3, p4, p5, p6; - struct sleep_params sp; unsigned long addr = get_zeroed_page(GFP_KERNEL); char *buf = (char *)addr; @@ -125,14 +117,12 @@ static ssize_t libertas_sleepparams_write(struct file *file, res = -EFAULT; goto out_unlock; } - sp.sp_error = p1; - sp.sp_offset = p2; - sp.sp_stabletime = p3; - sp.sp_calcontrol = p4; - sp.sp_extsleepclk = p5; - sp.sp_reserved = p6; - - memcpy(&priv->adapter->sp, &sp, sizeof(struct sleep_params)); + priv->adapter->sp.sp_error = p1; + priv->adapter->sp.sp_offset = p2; + priv->adapter->sp.sp_stabletime = p3; + priv->adapter->sp.sp_calcontrol = p4; + priv->adapter->sp.sp_extsleepclk = p5; + priv->adapter->sp.sp_reserved = p6; res = libertas_prepare_and_send_command(priv, cmd_802_11_sleep_params, @@ -185,7 +175,6 @@ static ssize_t libertas_extscan(struct file *file, const char __user *userbuf, { wlan_private *priv = file->private_data; ssize_t res, buf_size; - struct WLAN_802_11_SSID extscan_ssid; union iwreq_data wrqu; unsigned long addr = get_zeroed_page(GFP_KERNEL); char *buf = (char *)addr; @@ -196,13 +185,10 @@ static ssize_t libertas_extscan(struct file *file, const char __user *userbuf, goto out_unlock; } - memcpy(&extscan_ssid.ssid, buf, strlen(buf)-1); - extscan_ssid.ssidlength = strlen(buf)-1; - - libertas_send_specific_SSID_scan(priv, &extscan_ssid, 1); + libertas_send_specific_ssid_scan(priv, buf, strlen(buf)-1, 0); memset(&wrqu, 0, sizeof(union iwreq_data)); - wireless_send_event(priv->wlan_dev.netdev, SIOCGIWSCAN, &wrqu, NULL); + wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL); out_unlock: free_page(addr); @@ -251,16 +237,13 @@ static void libertas_parse_bssid(char *buf, size_t count, { char *hold; unsigned int mac[ETH_ALEN]; - int i; hold = strstr(buf, "bssid="); if (!hold) return; hold += 6; - sscanf(hold, "%2x:%2x:%2x:%2x:%2x:%2x", mac, mac+1, mac+2, mac+3, - mac+4, mac+5); - for(i=0;i<ETH_ALEN;i++) - scan_cfg->specificBSSID[i] = mac[i]; + sscanf(hold, MAC_FMT, mac, mac+1, mac+2, mac+3, mac+4, mac+5); + memcpy(scan_cfg->bssid, mac, ETH_ALEN); } static void libertas_parse_ssid(char *buf, size_t count, @@ -278,28 +261,26 @@ static void libertas_parse_ssid(char *buf, size_t count, end = buf + count - 1; size = min((size_t)IW_ESSID_MAX_SIZE, (size_t) (end - hold)); - strncpy(scan_cfg->specificSSID, hold, size); + strncpy(scan_cfg->ssid, hold, size); return; } -static void libertas_parse_keep(char *buf, size_t count, - struct wlan_ioctl_user_scan_cfg *scan_cfg) +static int libertas_parse_clear(char *buf, size_t count, const char *tag) { char *hold; int val; - hold = strstr(buf, "keep="); + hold = strstr(buf, tag); if (!hold) - return; - hold += 5; + return 0; + hold += strlen(tag); sscanf(hold, "%d", &val); if (val != 0) val = 1; - scan_cfg->keeppreviousscan = val; - return; + return val; } static int libertas_parse_dur(char *buf, size_t count, @@ -382,17 +363,18 @@ static ssize_t libertas_setuserscan(struct file *file, dur = libertas_parse_dur(buf, count, scan_cfg); libertas_parse_chan(buf, count, scan_cfg, dur); libertas_parse_bssid(buf, count, scan_cfg); + scan_cfg->clear_bssid = libertas_parse_clear(buf, count, "clear_bssid="); libertas_parse_ssid(buf, count, scan_cfg); - libertas_parse_keep(buf, count, scan_cfg); + scan_cfg->clear_ssid = libertas_parse_clear(buf, count, "clear_ssid="); libertas_parse_probes(buf, count, scan_cfg); libertas_parse_type(buf, count, scan_cfg); - wlan_scan_networks(priv, scan_cfg); + wlan_scan_networks(priv, scan_cfg, 1); wait_event_interruptible(priv->adapter->cmd_pending, !priv->adapter->nr_cmd_pending); memset(&wrqu, 0x00, sizeof(union iwreq_data)); - wireless_send_event(priv->wlan_dev.netdev, SIOCGIWSCAN, &wrqu, NULL); + wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL); out_unlock: free_page(addr); @@ -407,11 +389,11 @@ static int libertas_event_initcmd(wlan_private *priv, void **response_buf, u16 wait_option = cmd_option_waitforrsp; if (!(*cmdnode = libertas_get_free_cmd_ctrl_node(priv))) { - lbs_pr_debug(1, "failed libertas_get_free_cmd_ctrl_node\n"); + lbs_deb_debugfs("failed libertas_get_free_cmd_ctrl_node\n"); return -ENOMEM; } if (!(*response_buf = kmalloc(3000, GFP_KERNEL))) { - lbs_pr_debug(1, "failed to allocate response buffer!\n"); + lbs_deb_debugfs("failed to allocate response buffer!\n"); return -ENOMEM; } libertas_set_cmd_ctrl_node(priv, *cmdnode, 0, wait_option, NULL); @@ -420,8 +402,8 @@ static int libertas_event_initcmd(wlan_private *priv, void **response_buf, (*cmdnode)->cmdflags |= CMD_F_HOSTCMD; (*cmdnode)->cmdwaitqwoken = 0; *cmd = (struct cmd_ds_command *)(*cmdnode)->bufvirtualaddr; - (*cmd)->command = cmd_802_11_subscribe_event; - (*cmd)->seqnum = ++priv->adapter->seqnum; + (*cmd)->command = cpu_to_le16(cmd_802_11_subscribe_event); + (*cmd)->seqnum = cpu_to_le16(++priv->adapter->seqnum); (*cmd)->result = 0; return 0; } @@ -447,26 +429,25 @@ static ssize_t libertas_lowrssi_read(struct file *file, char __user *userbuf, } event = &pcmdptr->params.subscribe_event; - event->action = cmd_act_get; - pcmdptr->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN); + event->action = cpu_to_le16(cmd_act_get); + pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN); libertas_queue_cmd(adapter, pcmdnode, 1); wake_up_interruptible(&priv->mainthread.waitq); /* Sleep until response is generated by FW */ wait_event_interruptible(pcmdnode->cmdwait_q, - pcmdnode->cmdwaitqwoken); + pcmdnode->cmdwaitqwoken); pcmdptr = response_buf; if (pcmdptr->result) { - lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__, - pcmdptr->result); + lbs_pr_err("%s: fail, result=%d\n", __func__, + le16_to_cpu(pcmdptr->result)); kfree(response_buf); free_page(addr); return 0; } - if (pcmdptr->command != cmd_ret_802_11_subscribe_event) { + if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) { lbs_pr_err("command response incorrect!\n"); kfree(response_buf); free_page(addr); @@ -474,17 +455,17 @@ static ssize_t libertas_lowrssi_read(struct file *file, char __user *userbuf, } cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event); - event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN); - while (cmd_len < pcmdptr->size) { - struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len); - switch(header->type) { + event = (void *)(response_buf + S_DS_GEN); + while (cmd_len < le16_to_cpu(pcmdptr->size)) { + struct mrvlietypesheader *header = (void *)(response_buf + cmd_len); + switch (header->type) { struct mrvlietypes_rssithreshold *Lowrssi; - case TLV_TYPE_RSSI_LOW: - Lowrssi = (struct mrvlietypes_rssithreshold *)(response_buf + cmd_len); - pos += snprintf(buf+pos, len-pos, "%d %d %d\n", - Lowrssi->rssivalue, - Lowrssi->rssifreq, - (event->events & 0x0001)?1:0); + case __constant_cpu_to_le16(TLV_TYPE_RSSI_LOW): + Lowrssi = (void *)(response_buf + cmd_len); + pos += snprintf(buf+pos, len-pos, "%d %d %d\n", + Lowrssi->rssivalue, + Lowrssi->rssifreq, + (event->events & cpu_to_le16(0x0001))?1:0); default: cmd_len += sizeof(struct mrvlietypes_snrthreshold); break; @@ -512,21 +493,20 @@ static u16 libertas_get_events_bitmap(wlan_private *priv) return res; event = &pcmdptr->params.subscribe_event; - event->action = cmd_act_get; - pcmdptr->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN); + event->action = cpu_to_le16(cmd_act_get); + pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN); libertas_queue_cmd(adapter, pcmdnode, 1); wake_up_interruptible(&priv->mainthread.waitq); /* Sleep until response is generated by FW */ wait_event_interruptible(pcmdnode->cmdwait_q, - pcmdnode->cmdwaitqwoken); + pcmdnode->cmdwaitqwoken); pcmdptr = response_buf; if (pcmdptr->result) { - lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__, - pcmdptr->result); + lbs_pr_err("%s: fail, result=%d\n", __func__, + le16_to_cpu(pcmdptr->result)); kfree(response_buf); return 0; } @@ -538,7 +518,7 @@ static u16 libertas_get_events_bitmap(wlan_private *priv) } event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN); - event_bitmap = event->events; + event_bitmap = le16_to_cpu(event->events); kfree(response_buf); return event_bitmap; } @@ -579,7 +559,7 @@ static ssize_t libertas_lowrssi_write(struct file *file, goto out_unlock; event = &pcmdptr->params.subscribe_event; - event->action = cmd_act_set; + event->action = cpu_to_le16(cmd_act_set); pcmdptr->size = cpu_to_le16(S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event) + sizeof(struct mrvlietypes_rssithreshold)); @@ -588,30 +568,30 @@ static ssize_t libertas_lowrssi_write(struct file *file, ptr = (u8*) pcmdptr+cmd_len; rssi_threshold = (struct mrvlietypes_rssithreshold *)(ptr); rssi_threshold->header.type = cpu_to_le16(0x0104); - rssi_threshold->header.len = 2; - rssi_threshold->rssivalue = cpu_to_le16(value); - rssi_threshold->rssifreq = cpu_to_le16(freq); + rssi_threshold->header.len = cpu_to_le16(2); + rssi_threshold->rssivalue = value; + rssi_threshold->rssifreq = freq; event_bitmap |= subscribed ? 0x0001 : 0x0; - event->events = event_bitmap; + event->events = cpu_to_le16(event_bitmap); libertas_queue_cmd(adapter, pcmdnode, 1); wake_up_interruptible(&priv->mainthread.waitq); /* Sleep until response is generated by FW */ wait_event_interruptible(pcmdnode->cmdwait_q, - pcmdnode->cmdwaitqwoken); + pcmdnode->cmdwaitqwoken); pcmdptr = response_buf; if (pcmdptr->result) { - lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__, - pcmdptr->result); + lbs_pr_err("%s: fail, result=%d\n", __func__, + le16_to_cpu(pcmdptr->result)); kfree(response_buf); free_page(addr); return 0; } - if (pcmdptr->command != cmd_ret_802_11_subscribe_event) { + if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) { lbs_pr_err("command response incorrect!\n"); kfree(response_buf); free_page(addr); @@ -645,27 +625,26 @@ static ssize_t libertas_lowsnr_read(struct file *file, char __user *userbuf, } event = &pcmdptr->params.subscribe_event; - event->action = cmd_act_get; - pcmdptr->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN); + event->action = cpu_to_le16(cmd_act_get); + pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN); libertas_queue_cmd(adapter, pcmdnode, 1); wake_up_interruptible(&priv->mainthread.waitq); /* Sleep until response is generated by FW */ wait_event_interruptible(pcmdnode->cmdwait_q, - pcmdnode->cmdwaitqwoken); + pcmdnode->cmdwaitqwoken); pcmdptr = response_buf; if (pcmdptr->result) { - lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__, - pcmdptr->result); + lbs_pr_err("%s: fail, result=%d\n", __func__, + le16_to_cpu(pcmdptr->result)); kfree(response_buf); free_page(addr); return 0; } - if (pcmdptr->command != cmd_ret_802_11_subscribe_event) { + if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) { lbs_pr_err("command response incorrect!\n"); kfree(response_buf); free_page(addr); @@ -673,17 +652,17 @@ static ssize_t libertas_lowsnr_read(struct file *file, char __user *userbuf, } cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event); - event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN); - while (cmd_len < pcmdptr->size) { - struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len); - switch(header->type) { + event = (void *)(response_buf + S_DS_GEN); + while (cmd_len < le16_to_cpu(pcmdptr->size)) { + struct mrvlietypesheader *header = (void *)(response_buf + cmd_len); + switch (header->type) { struct mrvlietypes_snrthreshold *LowSnr; - case TLV_TYPE_SNR_LOW: - LowSnr = (struct mrvlietypes_snrthreshold *)(response_buf + cmd_len); - pos += snprintf(buf+pos, len-pos, "%d %d %d\n", - LowSnr->snrvalue, - LowSnr->snrfreq, - (event->events & 0x0002)?1:0); + case __constant_cpu_to_le16(TLV_TYPE_SNR_LOW): + LowSnr = (void *)(response_buf + cmd_len); + pos += snprintf(buf+pos, len-pos, "%d %d %d\n", + LowSnr->snrvalue, + LowSnr->snrfreq, + (event->events & cpu_to_le16(0x0002))?1:0); default: cmd_len += sizeof(struct mrvlietypes_snrthreshold); break; @@ -733,7 +712,7 @@ static ssize_t libertas_lowsnr_write(struct file *file, goto out_unlock; event = &pcmdptr->params.subscribe_event; - event->action = cmd_act_set; + event->action = cpu_to_le16(cmd_act_set); pcmdptr->size = cpu_to_le16(S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event) + sizeof(struct mrvlietypes_snrthreshold)); @@ -741,30 +720,30 @@ static ssize_t libertas_lowsnr_write(struct file *file, ptr = (u8*) pcmdptr+cmd_len; snr_threshold = (struct mrvlietypes_snrthreshold *)(ptr); snr_threshold->header.type = cpu_to_le16(TLV_TYPE_SNR_LOW); - snr_threshold->header.len = 2; - snr_threshold->snrvalue = cpu_to_le16(value); - snr_threshold->snrfreq = cpu_to_le16(freq); + snr_threshold->header.len = cpu_to_le16(2); + snr_threshold->snrvalue = value; + snr_threshold->snrfreq = freq; event_bitmap |= subscribed ? 0x0002 : 0x0; - event->events = event_bitmap; + event->events = cpu_to_le16(event_bitmap); libertas_queue_cmd(adapter, pcmdnode, 1); wake_up_interruptible(&priv->mainthread.waitq); /* Sleep until response is generated by FW */ wait_event_interruptible(pcmdnode->cmdwait_q, - pcmdnode->cmdwaitqwoken); + pcmdnode->cmdwaitqwoken); pcmdptr = response_buf; if (pcmdptr->result) { - lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__, - pcmdptr->result); + lbs_pr_err("%s: fail, result=%d\n", __func__, + le16_to_cpu(pcmdptr->result)); kfree(response_buf); free_page(addr); return 0; } - if (pcmdptr->command != cmd_ret_802_11_subscribe_event) { + if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) { lbs_pr_err("command response incorrect!\n"); kfree(response_buf); free_page(addr); @@ -799,27 +778,26 @@ static ssize_t libertas_failcount_read(struct file *file, char __user *userbuf, } event = &pcmdptr->params.subscribe_event; - event->action = cmd_act_get; - pcmdptr->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN); + event->action = cpu_to_le16(cmd_act_get); + pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN); libertas_queue_cmd(adapter, pcmdnode, 1); wake_up_interruptible(&priv->mainthread.waitq); /* Sleep until response is generated by FW */ wait_event_interruptible(pcmdnode->cmdwait_q, - pcmdnode->cmdwaitqwoken); + pcmdnode->cmdwaitqwoken); pcmdptr = response_buf; if (pcmdptr->result) { - lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__, - pcmdptr->result); + lbs_pr_err("%s: fail, result=%d\n", __func__, + le16_to_cpu(pcmdptr->result)); kfree(response_buf); free_page(addr); return 0; } - if (pcmdptr->command != cmd_ret_802_11_subscribe_event) { + if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) { lbs_pr_err("command response incorrect!\n"); kfree(response_buf); free_page(addr); @@ -827,17 +805,17 @@ static ssize_t libertas_failcount_read(struct file *file, char __user *userbuf, } cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event); - event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN); - while (cmd_len < pcmdptr->size) { - struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len); - switch(header->type) { + event = (void *)(response_buf + S_DS_GEN); + while (cmd_len < le16_to_cpu(pcmdptr->size)) { + struct mrvlietypesheader *header = (void *)(response_buf + cmd_len); + switch (header->type) { struct mrvlietypes_failurecount *failcount; - case TLV_TYPE_FAILCOUNT: - failcount = (struct mrvlietypes_failurecount *)(response_buf + cmd_len); - pos += snprintf(buf+pos, len-pos, "%d %d %d\n", - failcount->failvalue, - failcount->Failfreq, - (event->events & 0x0004)?1:0); + case __constant_cpu_to_le16(TLV_TYPE_FAILCOUNT): + failcount = (void *)(response_buf + cmd_len); + pos += snprintf(buf+pos, len-pos, "%d %d %d\n", + failcount->failvalue, + failcount->Failfreq, + (event->events & cpu_to_le16(0x0004))?1:0); default: cmd_len += sizeof(struct mrvlietypes_failurecount); break; @@ -886,7 +864,7 @@ static ssize_t libertas_failcount_write(struct file *file, goto out_unlock; event = &pcmdptr->params.subscribe_event; - event->action = cmd_act_set; + event->action = cpu_to_le16(cmd_act_set); pcmdptr->size = cpu_to_le16(S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event) + sizeof(struct mrvlietypes_failurecount)); @@ -894,30 +872,30 @@ static ssize_t libertas_failcount_write(struct file *file, ptr = (u8*) pcmdptr+cmd_len; failcount = (struct mrvlietypes_failurecount *)(ptr); failcount->header.type = cpu_to_le16(TLV_TYPE_FAILCOUNT); - failcount->header.len = 2; - failcount->failvalue = cpu_to_le16(value); - failcount->Failfreq = cpu_to_le16(freq); + failcount->header.len = cpu_to_le16(2); + failcount->failvalue = value; + failcount->Failfreq = freq; event_bitmap |= subscribed ? 0x0004 : 0x0; - event->events = event_bitmap; + event->events = cpu_to_le16(event_bitmap); libertas_queue_cmd(adapter, pcmdnode, 1); wake_up_interruptible(&priv->mainthread.waitq); /* Sleep until response is generated by FW */ wait_event_interruptible(pcmdnode->cmdwait_q, - pcmdnode->cmdwaitqwoken); + pcmdnode->cmdwaitqwoken); pcmdptr = (struct cmd_ds_command *)response_buf; if (pcmdptr->result) { - lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__, - pcmdptr->result); + lbs_pr_err("%s: fail, result=%d\n", __func__, + le16_to_cpu(pcmdptr->result)); kfree(response_buf); free_page(addr); return 0; } - if (pcmdptr->command != cmd_ret_802_11_subscribe_event) { + if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) { lbs_pr_err("command response incorrect!\n"); kfree(response_buf); free_page(addr); @@ -951,27 +929,26 @@ static ssize_t libertas_bcnmiss_read(struct file *file, char __user *userbuf, } event = &pcmdptr->params.subscribe_event; - event->action = cmd_act_get; - pcmdptr->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN); + event->action = cpu_to_le16(cmd_act_get); + pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN); libertas_queue_cmd(adapter, pcmdnode, 1); wake_up_interruptible(&priv->mainthread.waitq); /* Sleep until response is generated by FW */ wait_event_interruptible(pcmdnode->cmdwait_q, - pcmdnode->cmdwaitqwoken); + pcmdnode->cmdwaitqwoken); pcmdptr = response_buf; if (pcmdptr->result) { - lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__, - pcmdptr->result); + lbs_pr_err("%s: fail, result=%d\n", __func__, + le16_to_cpu(pcmdptr->result)); free_page(addr); kfree(response_buf); return 0; } - if (pcmdptr->command != cmd_ret_802_11_subscribe_event) { + if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) { lbs_pr_err("command response incorrect!\n"); free_page(addr); kfree(response_buf); @@ -979,16 +956,16 @@ static ssize_t libertas_bcnmiss_read(struct file *file, char __user *userbuf, } cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event); - event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN); - while (cmd_len < pcmdptr->size) { - struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len); - switch(header->type) { + event = (void *)(response_buf + S_DS_GEN); + while (cmd_len < le16_to_cpu(pcmdptr->size)) { + struct mrvlietypesheader *header = (void *)(response_buf + cmd_len); + switch (header->type) { struct mrvlietypes_beaconsmissed *bcnmiss; - case TLV_TYPE_BCNMISS: - bcnmiss = (struct mrvlietypes_beaconsmissed *)(response_buf + cmd_len); - pos += snprintf(buf+pos, len-pos, "%d N/A %d\n", - bcnmiss->beaconmissed, - (event->events & 0x0008)?1:0); + case __constant_cpu_to_le16(TLV_TYPE_BCNMISS): + bcnmiss = (void *)(response_buf + cmd_len); + pos += snprintf(buf+pos, len-pos, "%d N/A %d\n", + bcnmiss->beaconmissed, + (event->events & cpu_to_le16(0x0008))?1:0); default: cmd_len += sizeof(struct mrvlietypes_beaconsmissed); break; @@ -1038,7 +1015,7 @@ static ssize_t libertas_bcnmiss_write(struct file *file, goto out_unlock; event = &pcmdptr->params.subscribe_event; - event->action = cmd_act_set; + event->action = cpu_to_le16(cmd_act_set); pcmdptr->size = cpu_to_le16(S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event) + sizeof(struct mrvlietypes_beaconsmissed)); @@ -1046,29 +1023,29 @@ static ssize_t libertas_bcnmiss_write(struct file *file, ptr = (u8*) pcmdptr+cmd_len; bcnmiss = (struct mrvlietypes_beaconsmissed *)(ptr); bcnmiss->header.type = cpu_to_le16(TLV_TYPE_BCNMISS); - bcnmiss->header.len = 2; - bcnmiss->beaconmissed = cpu_to_le16(value); + bcnmiss->header.len = cpu_to_le16(2); + bcnmiss->beaconmissed = value; event_bitmap |= subscribed ? 0x0008 : 0x0; - event->events = event_bitmap; + event->events = cpu_to_le16(event_bitmap); libertas_queue_cmd(adapter, pcmdnode, 1); wake_up_interruptible(&priv->mainthread.waitq); /* Sleep until response is generated by FW */ wait_event_interruptible(pcmdnode->cmdwait_q, - pcmdnode->cmdwaitqwoken); + pcmdnode->cmdwaitqwoken); pcmdptr = response_buf; if (pcmdptr->result) { - lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__, - pcmdptr->result); + lbs_pr_err("%s: fail, result=%d\n", __func__, + le16_to_cpu(pcmdptr->result)); kfree(response_buf); free_page(addr); return 0; } - if (pcmdptr->command != cmd_ret_802_11_subscribe_event) { + if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) { lbs_pr_err("command response incorrect!\n"); free_page(addr); kfree(response_buf); @@ -1102,27 +1079,26 @@ static ssize_t libertas_highrssi_read(struct file *file, char __user *userbuf, } event = &pcmdptr->params.subscribe_event; - event->action = cmd_act_get; - pcmdptr->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN); + event->action = cpu_to_le16(cmd_act_get); + pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN); libertas_queue_cmd(adapter, pcmdnode, 1); wake_up_interruptible(&priv->mainthread.waitq); /* Sleep until response is generated by FW */ wait_event_interruptible(pcmdnode->cmdwait_q, - pcmdnode->cmdwaitqwoken); + pcmdnode->cmdwaitqwoken); pcmdptr = response_buf; if (pcmdptr->result) { - lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__, - pcmdptr->result); + lbs_pr_err("%s: fail, result=%d\n", __func__, + le16_to_cpu(pcmdptr->result)); kfree(response_buf); free_page(addr); return 0; } - if (pcmdptr->command != cmd_ret_802_11_subscribe_event) { + if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) { lbs_pr_err("command response incorrect!\n"); kfree(response_buf); free_page(addr); @@ -1130,17 +1106,17 @@ static ssize_t libertas_highrssi_read(struct file *file, char __user *userbuf, } cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event); - event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN); - while (cmd_len < pcmdptr->size) { - struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len); - switch(header->type) { + event = (void *)(response_buf + S_DS_GEN); + while (cmd_len < le16_to_cpu(pcmdptr->size)) { + struct mrvlietypesheader *header = (void *)(response_buf + cmd_len); + switch (header->type) { struct mrvlietypes_rssithreshold *Highrssi; - case TLV_TYPE_RSSI_HIGH: - Highrssi = (struct mrvlietypes_rssithreshold *)(response_buf + cmd_len); - pos += snprintf(buf+pos, len-pos, "%d %d %d\n", - Highrssi->rssivalue, - Highrssi->rssifreq, - (event->events & 0x0010)?1:0); + case __constant_cpu_to_le16(TLV_TYPE_RSSI_HIGH): + Highrssi = (void *)(response_buf + cmd_len); + pos += snprintf(buf+pos, len-pos, "%d %d %d\n", + Highrssi->rssivalue, + Highrssi->rssifreq, + (event->events & cpu_to_le16(0x0010))?1:0); default: cmd_len += sizeof(struct mrvlietypes_snrthreshold); break; @@ -1190,7 +1166,7 @@ static ssize_t libertas_highrssi_write(struct file *file, goto out_unlock; event = &pcmdptr->params.subscribe_event; - event->action = cmd_act_set; + event->action = cpu_to_le16(cmd_act_set); pcmdptr->size = cpu_to_le16(S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event) + sizeof(struct mrvlietypes_rssithreshold)); @@ -1198,29 +1174,29 @@ static ssize_t libertas_highrssi_write(struct file *file, ptr = (u8*) pcmdptr+cmd_len; rssi_threshold = (struct mrvlietypes_rssithreshold *)(ptr); rssi_threshold->header.type = cpu_to_le16(TLV_TYPE_RSSI_HIGH); - rssi_threshold->header.len = 2; - rssi_threshold->rssivalue = cpu_to_le16(value); - rssi_threshold->rssifreq = cpu_to_le16(freq); + rssi_threshold->header.len = cpu_to_le16(2); + rssi_threshold->rssivalue = value; + rssi_threshold->rssifreq = freq; event_bitmap |= subscribed ? 0x0010 : 0x0; - event->events = event_bitmap; + event->events = cpu_to_le16(event_bitmap); libertas_queue_cmd(adapter, pcmdnode, 1); wake_up_interruptible(&priv->mainthread.waitq); /* Sleep until response is generated by FW */ wait_event_interruptible(pcmdnode->cmdwait_q, - pcmdnode->cmdwaitqwoken); + pcmdnode->cmdwaitqwoken); pcmdptr = response_buf; if (pcmdptr->result) { - lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__, - pcmdptr->result); + lbs_pr_err("%s: fail, result=%d\n", __func__, + le16_to_cpu(pcmdptr->result)); kfree(response_buf); return 0; } - if (pcmdptr->command != cmd_ret_802_11_subscribe_event) { + if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) { lbs_pr_err("command response incorrect!\n"); kfree(response_buf); return 0; @@ -1253,27 +1229,26 @@ static ssize_t libertas_highsnr_read(struct file *file, char __user *userbuf, } event = &pcmdptr->params.subscribe_event; - event->action = cmd_act_get; - pcmdptr->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN); + event->action = cpu_to_le16(cmd_act_get); + pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN); libertas_queue_cmd(adapter, pcmdnode, 1); wake_up_interruptible(&priv->mainthread.waitq); /* Sleep until response is generated by FW */ wait_event_interruptible(pcmdnode->cmdwait_q, - pcmdnode->cmdwaitqwoken); + pcmdnode->cmdwaitqwoken); pcmdptr = response_buf; if (pcmdptr->result) { - lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__, - pcmdptr->result); + lbs_pr_err("%s: fail, result=%d\n", __func__, + le16_to_cpu(pcmdptr->result)); kfree(response_buf); free_page(addr); return 0; } - if (pcmdptr->command != cmd_ret_802_11_subscribe_event) { + if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) { lbs_pr_err("command response incorrect!\n"); kfree(response_buf); free_page(addr); @@ -1281,17 +1256,17 @@ static ssize_t libertas_highsnr_read(struct file *file, char __user *userbuf, } cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event); - event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN); - while (cmd_len < pcmdptr->size) { - struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len); - switch(header->type) { + event = (void *)(response_buf + S_DS_GEN); + while (cmd_len < le16_to_cpu(pcmdptr->size)) { + struct mrvlietypesheader *header = (void *)(response_buf + cmd_len); + switch (header->type) { struct mrvlietypes_snrthreshold *HighSnr; - case TLV_TYPE_SNR_HIGH: - HighSnr = (struct mrvlietypes_snrthreshold *)(response_buf + cmd_len); - pos += snprintf(buf+pos, len-pos, "%d %d %d\n", - HighSnr->snrvalue, - HighSnr->snrfreq, - (event->events & 0x0020)?1:0); + case __constant_cpu_to_le16(TLV_TYPE_SNR_HIGH): + HighSnr = (void *)(response_buf + cmd_len); + pos += snprintf(buf+pos, len-pos, "%d %d %d\n", + HighSnr->snrvalue, + HighSnr->snrfreq, + (event->events & cpu_to_le16(0x0020))?1:0); default: cmd_len += sizeof(struct mrvlietypes_snrthreshold); break; @@ -1341,7 +1316,7 @@ static ssize_t libertas_highsnr_write(struct file *file, goto out_unlock; event = &pcmdptr->params.subscribe_event; - event->action = cmd_act_set; + event->action = cpu_to_le16(cmd_act_set); pcmdptr->size = cpu_to_le16(S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event) + sizeof(struct mrvlietypes_snrthreshold)); @@ -1349,30 +1324,30 @@ static ssize_t libertas_highsnr_write(struct file *file, ptr = (u8*) pcmdptr+cmd_len; snr_threshold = (struct mrvlietypes_snrthreshold *)(ptr); snr_threshold->header.type = cpu_to_le16(TLV_TYPE_SNR_HIGH); - snr_threshold->header.len = 2; - snr_threshold->snrvalue = cpu_to_le16(value); - snr_threshold->snrfreq = cpu_to_le16(freq); + snr_threshold->header.len = cpu_to_le16(2); + snr_threshold->snrvalue = value; + snr_threshold->snrfreq = freq; event_bitmap |= subscribed ? 0x0020 : 0x0; - event->events = event_bitmap; + event->events = cpu_to_le16(event_bitmap); libertas_queue_cmd(adapter, pcmdnode, 1); wake_up_interruptible(&priv->mainthread.waitq); /* Sleep until response is generated by FW */ wait_event_interruptible(pcmdnode->cmdwait_q, - pcmdnode->cmdwaitqwoken); + pcmdnode->cmdwaitqwoken); pcmdptr = response_buf; if (pcmdptr->result) { - lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__, - pcmdptr->result); + lbs_pr_err("%s: fail, result=%d\n", __func__, + le16_to_cpu(pcmdptr->result)); kfree(response_buf); free_page(addr); return 0; } - if (pcmdptr->command != cmd_ret_802_11_subscribe_event) { + if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) { lbs_pr_err("command response incorrect!\n"); kfree(response_buf); free_page(addr); @@ -1760,7 +1735,7 @@ void libertas_debugfs_remove_one(wlan_private *priv) debugfs_remove(priv->regs_dir); - for(i=0; i<ARRAY_SIZE(debugfs_files); i++) + for(i=0; i<ARRAY_SIZE(debugfs_events_files); i++) debugfs_remove(priv->debugfs_events_files[i]); debugfs_remove(priv->events_dir); @@ -1769,13 +1744,19 @@ void libertas_debugfs_remove_one(wlan_private *priv) #endif for(i=0; i<ARRAY_SIZE(debugfs_files); i++) debugfs_remove(priv->debugfs_files[i]); + debugfs_remove(priv->debugfs_dir); } + + /* debug entry */ +#ifdef PROC_DEBUG + #define item_size(n) (FIELD_SIZEOF(wlan_adapter, n)) #define item_addr(n) (offsetof(wlan_adapter, n)) + struct debug_data { char name[32]; u32 size; @@ -1863,7 +1844,7 @@ static ssize_t wlan_debugfs_write(struct file *f, const char __user *buf, return 0; if (copy_from_user(pdata, buf, cnt)) { - lbs_pr_debug(1, "Copy from user failed\n"); + lbs_deb_debugfs("Copy from user failed\n"); kfree(pdata); return 0; } @@ -1913,7 +1894,7 @@ static struct file_operations libertas_debug_fops = { * @param dev pointer net_device * @return N/A */ -void libertas_debug_init(wlan_private * priv, struct net_device *dev) +static void libertas_debug_init(wlan_private * priv, struct net_device *dev) { int i; @@ -1927,4 +1908,5 @@ void libertas_debug_init(wlan_private * priv, struct net_device *dev) priv->debugfs_dir, &items[0], &libertas_debug_fops); } +#endif diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index dfe27642322..40f56bb1eac 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h @@ -6,6 +6,8 @@ #ifndef _WLAN_DECL_H_ #define _WLAN_DECL_H_ +#include <linux/device.h> + #include "defs.h" /** Function Prototype Declaration */ @@ -66,18 +68,24 @@ void libertas_ps_wakeup(wlan_private * priv, int wait_option); void libertas_tx_runqueue(wlan_private *priv); -extern struct chan_freq_power *libertas_find_cfp_by_band_and_channel( +struct chan_freq_power *libertas_find_cfp_by_band_and_channel( wlan_adapter * adapter, u8 band, u16 channel); -extern void libertas_mac_event_disconnected(wlan_private * priv); +void libertas_mac_event_disconnected(wlan_private * priv); void libertas_send_iwevcustom_event(wlan_private * priv, s8 * str); -int reset_device(wlan_private *priv); +/* fw.c */ +int libertas_init_fw(wlan_private * priv, char *fw_name); + /* main.c */ -extern struct chan_freq_power *libertas_get_region_cfp_table(u8 region, u8 band, +struct chan_freq_power *libertas_get_region_cfp_table(u8 region, u8 band, int *cfp_no); -wlan_private *wlan_add_card(void *card); -int wlan_remove_card(void *card); +wlan_private *libertas_add_card(void *card, struct device *dmdev); +int libertas_activate_card(wlan_private *priv, char *fw_name); +int libertas_remove_card(wlan_private *priv); +int libertas_add_mesh(wlan_private *priv, struct device *dev); +void libertas_remove_mesh(wlan_private *priv); + #endif /* _WLAN_DECL_H_ */ diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index 80dd9ea19c8..4dd43e59bda 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h @@ -7,14 +7,79 @@ #include <linux/spinlock.h> -extern unsigned int libertas_debug; - #ifdef CONFIG_LIBERTAS_DEBUG #define DEBUG #define PROC_DEBUG #endif -#define DRV_NAME "usb8xxx" +#ifndef DRV_NAME +#define DRV_NAME "libertas" +#endif + + +#define LBS_DEB_ENTER 0x00000001 +#define LBS_DEB_LEAVE 0x00000002 +#define LBS_DEB_MAIN 0x00000004 +#define LBS_DEB_NET 0x00000008 +#define LBS_DEB_MESH 0x00000010 +#define LBS_DEB_WEXT 0x00000020 +#define LBS_DEB_IOCTL 0x00000040 +#define LBS_DEB_SCAN 0x00000080 +#define LBS_DEB_ASSOC 0x00000100 +#define LBS_DEB_JOIN 0x00000200 +#define LBS_DEB_11D 0x00000400 +#define LBS_DEB_DEBUGFS 0x00000800 +#define LBS_DEB_ETHTOOL 0x00001000 +#define LBS_DEB_HOST 0x00002000 +#define LBS_DEB_CMD 0x00004000 +#define LBS_DEB_RX 0x00008000 +#define LBS_DEB_TX 0x00010000 +#define LBS_DEB_USB 0x00020000 +#define LBS_DEB_CS 0x00040000 +#define LBS_DEB_FW 0x00080000 +#define LBS_DEB_THREAD 0x00100000 +#define LBS_DEB_HEX 0x00200000 + +extern unsigned int libertas_debug; + +#ifdef DEBUG +#define LBS_DEB_LL(grp, fmt, args...) \ +do { if ((libertas_debug & (grp)) == (grp)) \ + printk(KERN_DEBUG DRV_NAME "%s: " fmt, \ + in_interrupt() ? " (INT)" : "", ## args); } while (0) +#else +#define LBS_DEB_LL(grp, fmt, args...) do {} while (0) +#endif + +#define lbs_deb_enter(grp) \ + LBS_DEB_LL(grp | LBS_DEB_ENTER, "%s():%d enter\n", __FUNCTION__, __LINE__); +#define lbs_deb_enter_args(grp, fmt, args...) \ + LBS_DEB_LL(grp | LBS_DEB_ENTER, "%s(" fmt "):%d\n", __FUNCTION__, ## args, __LINE__); +#define lbs_deb_leave(grp) \ + LBS_DEB_LL(grp | LBS_DEB_LEAVE, "%s():%d leave\n", __FUNCTION__, __LINE__); +#define lbs_deb_leave_args(grp, fmt, args...) \ + LBS_DEB_LL(grp | LBS_DEB_LEAVE, "%s():%d leave, " fmt "\n", \ + __FUNCTION__, __LINE__, ##args); +#define lbs_deb_main(fmt, args...) LBS_DEB_LL(LBS_DEB_MAIN, fmt, ##args) +#define lbs_deb_net(fmt, args...) LBS_DEB_LL(LBS_DEB_NET, fmt, ##args) +#define lbs_deb_mesh(fmt, args...) LBS_DEB_LL(LBS_DEB_MESH, fmt, ##args) +#define lbs_deb_wext(fmt, args...) LBS_DEB_LL(LBS_DEB_WEXT, fmt, ##args) +#define lbs_deb_ioctl(fmt, args...) LBS_DEB_LL(LBS_DEB_IOCTL, fmt, ##args) +#define lbs_deb_scan(fmt, args...) LBS_DEB_LL(LBS_DEB_SCAN, fmt, ##args) +#define lbs_deb_assoc(fmt, args...) LBS_DEB_LL(LBS_DEB_ASSOC, fmt, ##args) +#define lbs_deb_join(fmt, args...) LBS_DEB_LL(LBS_DEB_JOIN, fmt, ##args) +#define lbs_deb_11d(fmt, args...) LBS_DEB_LL(LBS_DEB_11D, fmt, ##args) +#define lbs_deb_debugfs(fmt, args...) LBS_DEB_LL(LBS_DEB_DEBUGFS, fmt, ##args) +#define lbs_deb_ethtool(fmt, args...) LBS_DEB_LL(LBS_DEB_ETHTOOL, fmt, ##args) +#define lbs_deb_host(fmt, args...) LBS_DEB_LL(LBS_DEB_HOST, fmt, ##args) +#define lbs_deb_cmd(fmt, args...) LBS_DEB_LL(LBS_DEB_CMD, fmt, ##args) +#define lbs_deb_rx(fmt, args...) LBS_DEB_LL(LBS_DEB_RX, fmt, ##args) +#define lbs_deb_tx(fmt, args...) LBS_DEB_LL(LBS_DEB_TX, fmt, ##args) +#define lbs_deb_fw(fmt, args...) LBS_DEB_LL(LBS_DEB_FW, fmt, ##args) +#define lbs_deb_usb(fmt, args...) LBS_DEB_LL(LBS_DEB_USB, fmt, ##args) +#define lbs_deb_usbd(dev, fmt, args...) LBS_DEB_LL(LBS_DEB_USB, "%s:" fmt, (dev)->bus_id, ##args) +#define lbs_deb_cs(fmt, args...) LBS_DEB_LL(LBS_DEB_CS, fmt, ##args) +#define lbs_deb_thread(fmt, args...) LBS_DEB_LL(LBS_DEB_THREAD, fmt, ##args) #define lbs_pr_info(format, args...) \ printk(KERN_INFO DRV_NAME": " format, ## args) @@ -24,37 +89,25 @@ extern unsigned int libertas_debug; printk(KERN_ALERT DRV_NAME": " format, ## args) #ifdef DEBUG -#define lbs_pr_debug(level, format, args...) \ - do { if (libertas_debug >= level) \ - printk(KERN_INFO DRV_NAME": " format, ##args); } while (0) -#define lbs_dev_dbg(level, device, format, args...) \ - lbs_pr_debug(level, "%s: " format, \ - (device)->bus_id , ## args) - static inline void lbs_dbg_hex(char *prompt, u8 * buf, int len) { int i = 0; - if (!libertas_debug) + if (!(libertas_debug & LBS_DEB_HEX)) return; printk(KERN_DEBUG "%s: ", prompt); for (i = 1; i <= len; i++) { - printk(KERN_DEBUG "%02x ", (u8) * buf); + printk("%02x ", (u8) * buf); buf++; } printk("\n"); } #else -#define lbs_pr_debug(level, format, args...) do {} while (0) -#define lbs_dev_dbg(level, device, format, args...) do {} while (0) #define lbs_dbg_hex(x,y,z) do {} while (0) #endif -#define ENTER() lbs_pr_debug(1, "Enter: %s, %s:%i\n", \ - __FUNCTION__, __FILE__, __LINE__) -#define LEAVE() lbs_pr_debug(1, "Leave: %s, %s:%i\n", \ - __FUNCTION__, __FILE__, __LINE__) + /** Buffer Constants */ @@ -74,7 +127,6 @@ static inline void lbs_dbg_hex(char *prompt, u8 * buf, int len) #define MRVDRV_NUM_OF_CMD_BUFFER 10 #define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024) #define MRVDRV_MAX_CHANNEL_SIZE 14 -#define MRVDRV_MAX_BSSID_LIST 64 #define MRVDRV_ASSOCIATION_TIME_OUT 255 #define MRVDRV_SNAP_HEADER_LEN 8 @@ -104,6 +156,13 @@ static inline void lbs_dbg_hex(char *prompt, u8 * buf, int len) #define MRVDRV_MAX_BEACON_INTERVAL 1000 #define MRVDRV_BEACON_INTERVAL 100 +/** INT status Bit Definition*/ +#define his_cmddnldrdy 0x01 +#define his_cardevent 0x02 +#define his_cmdupldrdy 0x04 + +#define SBI_EVENT_CAUSE_SHIFT 3 + /** TxPD status */ /* Station firmware use TxPD status field to report final Tx transmit @@ -205,8 +264,6 @@ typedef struct _wlan_adapter wlan_adapter; extern const char libertas_driver_version[]; extern u16 libertas_region_code_to_index[MRVDRV_MAX_REGION_CODE]; -extern u8 libertas_wlan_data_rates[WLAN_SUPPORTED_RATES]; - extern u8 libertas_supported_rates[G_SUPPORTED_RATES]; extern u8 libertas_adhoc_rates_g[G_SUPPORTED_RATES]; @@ -316,6 +373,8 @@ enum SNMP_MIB_VALUE_e { /* Default values for fwt commands. */ #define FWT_DEFAULT_METRIC 0 #define FWT_DEFAULT_DIR 1 +/* Default Rate, 11Mbps */ +#define FWT_DEFAULT_RATE 3 #define FWT_DEFAULT_SSN 0xffffffff #define FWT_DEFAULT_DSN 0 #define FWT_DEFAULT_HOPCOUNT 0 diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index e8b9020f9bd..785192b884b 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -63,11 +63,11 @@ struct wlan_802_11_security { /** Current Basic Service Set State Structure */ struct current_bss_params { - struct bss_descriptor bssdescriptor; /** bssid */ u8 bssid[ETH_ALEN]; /** ssid */ - struct WLAN_802_11_SSID ssid; + u8 ssid[IW_ESSID_MAX_SIZE + 1]; + u8 ssid_len; /** band */ u8 band; @@ -89,31 +89,6 @@ struct sleep_params { u16 sp_reserved; }; -/** Data structure for the Marvell WLAN device */ -typedef struct _wlan_dev { - /** device name */ - char name[DEV_NAME_LEN]; - /** card pointer */ - void *card; - /** IO port */ - u32 ioport; - /** Upload received */ - u32 upld_rcv; - /** Upload type */ - u32 upld_typ; - /** Upload length */ - u32 upld_len; - /** netdev pointer */ - struct net_device *netdev; - /* Upload buffer */ - u8 upld_buf[WLAN_UPLD_SIZE]; - /* Download sent: - bit0 1/0=data_sent/data_tx_done, - bit1 1/0=cmd_sent/cmd_tx_done, - all other bits reserved 0 */ - u8 dnld_sent; -} wlan_dev_t, *pwlan_dev_t; - /* Mesh statistics */ struct wlan_mesh_stats { u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */ @@ -123,6 +98,7 @@ struct wlan_mesh_stats { u32 fwd_drop_noroute; /* Fwd: No route to Destination */ u32 fwd_drop_nobuf; /* Fwd: Run out of internal buffers */ u32 drop_blind; /* Rx: Dropped by blinding table */ + u32 tx_failed_cnt; /* Tx: Failed transmissions */ }; /** Private structure for the MV device */ @@ -131,8 +107,11 @@ struct _wlan_private { int mesh_open; int infra_open; + char name[DEV_NAME_LEN]; + + void *card; wlan_adapter *adapter; - wlan_dev_t wlan_dev; + struct net_device *dev; struct net_device_stats stats; struct net_device *mesh_dev ; /* Virtual device */ @@ -153,6 +132,16 @@ struct _wlan_private { u32 bbp_offset; u32 rf_offset; + /** Upload length */ + u32 upld_len; + /* Upload buffer */ + u8 upld_buf[WLAN_UPLD_SIZE]; + /* Download sent: + bit0 1/0=data_sent/data_tx_done, + bit1 1/0=cmd_sent/cmd_tx_done, + all other bits reserved 0 */ + u8 dnld_sent; + const struct firmware *firmware; struct device *hotplug_device; @@ -161,6 +150,15 @@ struct _wlan_private { struct delayed_work assoc_work; struct workqueue_struct *assoc_thread; + struct work_struct sync_channel; + + /** Hardware access */ + int (*hw_register_dev) (wlan_private * priv); + int (*hw_unregister_dev) (wlan_private *); + int (*hw_prog_firmware) (wlan_private *); + int (*hw_host_to_card) (wlan_private * priv, u8 type, u8 * payload, u16 nb); + int (*hw_get_int_status) (wlan_private * priv, u8 *); + int (*hw_read_event_cause) (wlan_private *); }; /** Association request @@ -171,18 +169,21 @@ struct _wlan_private { struct assoc_request { #define ASSOC_FLAG_SSID 1 #define ASSOC_FLAG_CHANNEL 2 -#define ASSOC_FLAG_MODE 3 -#define ASSOC_FLAG_BSSID 4 -#define ASSOC_FLAG_WEP_KEYS 5 -#define ASSOC_FLAG_WEP_TX_KEYIDX 6 -#define ASSOC_FLAG_WPA_MCAST_KEY 7 -#define ASSOC_FLAG_WPA_UCAST_KEY 8 -#define ASSOC_FLAG_SECINFO 9 -#define ASSOC_FLAG_WPA_IE 10 +#define ASSOC_FLAG_BAND 3 +#define ASSOC_FLAG_MODE 4 +#define ASSOC_FLAG_BSSID 5 +#define ASSOC_FLAG_WEP_KEYS 6 +#define ASSOC_FLAG_WEP_TX_KEYIDX 7 +#define ASSOC_FLAG_WPA_MCAST_KEY 8 +#define ASSOC_FLAG_WPA_UCAST_KEY 9 +#define ASSOC_FLAG_SECINFO 10 +#define ASSOC_FLAG_WPA_IE 11 unsigned long flags; - struct WLAN_802_11_SSID ssid; + u8 ssid[IW_ESSID_MAX_SIZE + 1]; + u8 ssid_len; u8 channel; + u8 band; u8 mode; u8 bssid[ETH_ALEN]; @@ -199,12 +200,15 @@ struct assoc_request { /** WPA Information Elements*/ u8 wpa_ie[MAX_WPA_IE_LEN]; u8 wpa_ie_len; + + /* BSS to associate with for infrastructure of Ad-Hoc join */ + struct bss_descriptor bss; }; /** Wlan adapter data structure*/ struct _wlan_adapter { /** STATUS variables */ - u32 fwreleasenumber; + u8 fwreleasenumber[4]; u32 fwcapinfo; /* protected with big lock */ @@ -255,13 +259,14 @@ struct _wlan_adapter { /* IW_MODE_* */ u8 mode; - struct bss_descriptor *pattemptedbssdesc; - - struct WLAN_802_11_SSID previousssid; - u8 previousbssid[ETH_ALEN]; + u8 prev_ssid[IW_ESSID_MAX_SIZE + 1]; + u8 prev_ssid_len; + u8 prev_bssid[ETH_ALEN]; - struct bss_descriptor *scantable; - u32 numinscantable; + /* Scan results list */ + struct list_head network_list; + struct list_head network_free_list; + struct bss_descriptor *networks; u8 scantype; u32 scanmode; @@ -288,7 +293,6 @@ struct _wlan_adapter { u32 txantenna; u32 rxantenna; - u8 adhocchannel; u32 fragthsd; u32 rtsthsd; @@ -324,7 +328,8 @@ struct _wlan_adapter { u16 locallisteninterval; u16 nullpktinterval; - struct assoc_request * assoc_req; + struct assoc_request * pending_assoc_req; + struct assoc_request * in_progress_assoc_req; /** Encryption parameter */ struct wlan_802_11_security secinfo; @@ -396,6 +401,8 @@ struct _wlan_adapter { u32 radiomode; u32 debugmode; u8 fw_ready; + + u8 last_scanned_channel; }; #endif /* _WLAN_DEV_H_ */ diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c index 0064de54296..96f1974685d 100644 --- a/drivers/net/wireless/libertas/ethtool.c +++ b/drivers/net/wireless/libertas/ethtool.c @@ -1,10 +1,8 @@ - #include <linux/netdevice.h> #include <linux/ethtool.h> #include <linux/delay.h> #include "host.h" -#include "sbi.h" #include "decl.h" #include "defs.h" #include "dev.h" @@ -17,7 +15,8 @@ static const char * mesh_stat_strings[]= { "drop_no_buffers", "fwded_unicast_cnt", "fwded_bcast_cnt", - "drop_blind_table" + "drop_blind_table", + "tx_failed_cnt" }; static void libertas_ethtool_get_drvinfo(struct net_device *dev, @@ -69,7 +68,7 @@ static int libertas_ethtool_get_eeprom(struct net_device *dev, /* +14 is for action, offset, and NOB in * response */ - lbs_pr_debug(1, "action:%d offset: %x NOB: %02x\n", + lbs_deb_ethtool("action:%d offset: %x NOB: %02x\n", regctrl.action, regctrl.offset, regctrl.NOB); ret = libertas_prepare_and_send_command(priv, @@ -81,8 +80,7 @@ static int libertas_ethtool_get_eeprom(struct net_device *dev, if (ret) { if (adapter->prdeeprom) kfree(adapter->prdeeprom); - LEAVE(); - return ret; + goto done; } mdelay(10); @@ -101,7 +99,11 @@ static int libertas_ethtool_get_eeprom(struct net_device *dev, kfree(adapter->prdeeprom); // mutex_unlock(&priv->mutex); - return 0; + ret = 0; + +done: + lbs_deb_enter_args(LBS_DEB_ETHTOOL, "ret %d", ret); + return ret; } static void libertas_ethtool_get_stats(struct net_device * dev, @@ -109,7 +111,7 @@ static void libertas_ethtool_get_stats(struct net_device * dev, { wlan_private *priv = dev->priv; - ENTER(); + lbs_deb_enter(LBS_DEB_ETHTOOL); stats->cmd = ETHTOOL_GSTATS; BUG_ON(stats->n_stats != MESH_STATS_NUM); @@ -121,8 +123,9 @@ static void libertas_ethtool_get_stats(struct net_device * dev, data[4] = priv->mstats.fwd_unicast_cnt; data[5] = priv->mstats.fwd_bcast_cnt; data[6] = priv->mstats.drop_blind; + data[7] = priv->mstats.tx_failed_cnt; - LEAVE(); + lbs_deb_enter(LBS_DEB_ETHTOOL); } static int libertas_ethtool_get_stats_count(struct net_device * dev) @@ -131,27 +134,32 @@ static int libertas_ethtool_get_stats_count(struct net_device * dev) wlan_private *priv = dev->priv; struct cmd_ds_mesh_access mesh_access; - ENTER(); + lbs_deb_enter(LBS_DEB_ETHTOOL); + /* Get Mesh Statistics */ ret = libertas_prepare_and_send_command(priv, cmd_mesh_access, cmd_act_mesh_get_stats, cmd_option_waitforrsp, 0, &mesh_access); if (ret) { - LEAVE(); - return 0; + ret = 0; + goto done; } - priv->mstats.fwd_drop_rbt = mesh_access.data[0]; - priv->mstats.fwd_drop_ttl = mesh_access.data[1]; - priv->mstats.fwd_drop_noroute = mesh_access.data[2]; - priv->mstats.fwd_drop_nobuf = mesh_access.data[3]; - priv->mstats.fwd_unicast_cnt = mesh_access.data[4]; - priv->mstats.fwd_bcast_cnt = mesh_access.data[5]; - priv->mstats.drop_blind = mesh_access.data[6]; + priv->mstats.fwd_drop_rbt = le32_to_cpu(mesh_access.data[0]); + priv->mstats.fwd_drop_ttl = le32_to_cpu(mesh_access.data[1]); + priv->mstats.fwd_drop_noroute = le32_to_cpu(mesh_access.data[2]); + priv->mstats.fwd_drop_nobuf = le32_to_cpu(mesh_access.data[3]); + priv->mstats.fwd_unicast_cnt = le32_to_cpu(mesh_access.data[4]); + priv->mstats.fwd_bcast_cnt = le32_to_cpu(mesh_access.data[5]); + priv->mstats.drop_blind = le32_to_cpu(mesh_access.data[6]); + priv->mstats.tx_failed_cnt = le32_to_cpu(mesh_access.data[7]); - LEAVE(); - return MESH_STATS_NUM; + ret = MESH_STATS_NUM; + +done: + lbs_deb_enter_args(LBS_DEB_ETHTOOL, "ret %d", ret); + return ret; } static void libertas_ethtool_get_strings (struct net_device * dev, @@ -160,7 +168,8 @@ static void libertas_ethtool_get_strings (struct net_device * dev, { int i; - ENTER(); + lbs_deb_enter(LBS_DEB_ETHTOOL); + switch (stringset) { case ETH_SS_STATS: for (i=0; i < MESH_STATS_NUM; i++) { @@ -170,7 +179,7 @@ static void libertas_ethtool_get_strings (struct net_device * dev, } break; } - LEAVE(); + lbs_deb_enter(LBS_DEB_ETHTOOL); } struct ethtool_ops libertas_ethtool_ops = { diff --git a/drivers/net/wireless/libertas/fw.c b/drivers/net/wireless/libertas/fw.c index 5c63c9b1659..2dc84ff7a54 100644 --- a/drivers/net/wireless/libertas/fw.c +++ b/drivers/net/wireless/libertas/fw.c @@ -1,28 +1,15 @@ /** * This file contains the initialization for FW and HW */ -#include <linux/module.h> -#include <linux/moduleparam.h> - -#include <linux/vmalloc.h> #include <linux/firmware.h> -#include <linux/version.h> #include "host.h" -#include "sbi.h" #include "defs.h" #include "decl.h" #include "dev.h" -#include "fw.h" #include "wext.h" #include "if_usb.h" -char *libertas_fw_name = NULL; -module_param_named(fw_name, libertas_fw_name, charp, 0644); - -unsigned int libertas_debug = 0; -module_param(libertas_debug, int, 0); - /** * @brief This function checks the validity of Boot2/FW image. * @@ -32,7 +19,7 @@ module_param(libertas_debug, int, 0); */ static int check_fwfile_format(u8 *data, u32 totlen) { - u8 bincmd, exit; + u32 bincmd, exit; u32 blksize, offset, len; int ret; @@ -40,8 +27,10 @@ static int check_fwfile_format(u8 *data, u32 totlen) exit = len = 0; do { - bincmd = *data; - blksize = *(u32*)(data + offsetof(struct fwheader, datalength)); + struct fwheader *fwh = (void *)data; + + bincmd = le32_to_cpu(fwh->dnldcmd); + blksize = le32_to_cpu(fwh->datalength); switch (bincmd) { case FW_HAS_DATA_TO_RECV: offset = sizeof(struct fwheader) + blksize; @@ -61,9 +50,9 @@ static int check_fwfile_format(u8 *data, u32 totlen) } while (!exit); if (ret) - lbs_pr_err("bin file format check FAIL...\n"); + lbs_pr_err("firmware file format check FAIL\n"); else - lbs_pr_debug(1, "bin file format check PASS...\n"); + lbs_deb_fw("firmware file format check PASS\n"); return ret; } @@ -76,32 +65,31 @@ static int check_fwfile_format(u8 *data, u32 totlen) * @param priv A pointer to wlan_private structure * @return 0 or -1 */ -static int wlan_setup_station_hw(wlan_private * priv) +static int wlan_setup_station_hw(wlan_private * priv, char *fw_name) { int ret = -1; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_FW); - if ((ret = request_firmware(&priv->firmware, libertas_fw_name, + if ((ret = request_firmware(&priv->firmware, fw_name, priv->hotplug_device)) < 0) { - lbs_pr_err("request_firmware() failed, error code = %#x\n", - ret); - lbs_pr_err("%s not found in /lib/firmware\n", libertas_fw_name); + lbs_pr_err("request_firmware() failed with %#x\n", ret); + lbs_pr_err("firmware %s not found\n", fw_name); goto done; } - if(check_fwfile_format(priv->firmware->data, priv->firmware->size)) { + if (check_fwfile_format(priv->firmware->data, priv->firmware->size)) { release_firmware(priv->firmware); goto done; } - ret = libertas_sbi_prog_firmware(priv); + ret = priv->hw_prog_firmware(priv); release_firmware(priv->firmware); if (ret) { - lbs_pr_debug(1, "Bootloader in invalid state!\n"); + lbs_deb_fw("bootloader in invalid state\n"); ret = -1; goto done; } @@ -133,28 +121,24 @@ static int wlan_setup_station_hw(wlan_private * priv) ret = 0; done: - LEAVE(); - - return (ret); + lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); + return ret; } static int wlan_allocate_adapter(wlan_private * priv) { - u32 ulbufsize; + size_t bufsize; wlan_adapter *adapter = priv->adapter; - struct bss_descriptor *ptempscantable; - /* Allocate buffer to store the BSSID list */ - ulbufsize = sizeof(struct bss_descriptor) * MRVDRV_MAX_BSSID_LIST; - if (!(ptempscantable = kmalloc(ulbufsize, GFP_KERNEL))) { + bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor); + adapter->networks = kzalloc(bufsize, GFP_KERNEL); + if (!adapter->networks) { + lbs_pr_err("Out of memory allocating beacons\n"); libertas_free_adapter(priv); - return -1; + return -ENOMEM; } - adapter->scantable = ptempscantable; - memset(adapter->scantable, 0, ulbufsize); - /* Allocate the command buffers */ libertas_allocate_cmd_buffer(priv); @@ -202,15 +186,23 @@ static void wlan_init_adapter(wlan_private * priv) adapter->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; adapter->mode = IW_MODE_INFRA; - adapter->assoc_req = NULL; + adapter->pending_assoc_req = NULL; + adapter->in_progress_assoc_req = NULL; + + /* Initialize scan result lists */ + INIT_LIST_HEAD(&adapter->network_free_list); + INIT_LIST_HEAD(&adapter->network_list); + for (i = 0; i < MAX_NETWORK_COUNT; i++) { + list_add_tail(&adapter->networks[i].list, + &adapter->network_free_list); + } - adapter->numinscantable = 0; - adapter->pattemptedbssdesc = NULL; mutex_init(&adapter->lock); adapter->prescan = 1; memset(&adapter->curbssparams, 0, sizeof(adapter->curbssparams)); + adapter->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL; /* PnP and power profile */ adapter->surpriseremoved = 0; @@ -230,8 +222,6 @@ static void wlan_init_adapter(wlan_private * priv) memset(&adapter->capinfo, 0, sizeof(adapter->capinfo)); adapter->capinfo.shortpreamble = SHORT_PREAMBLE_ALLOWED; - adapter->adhocchannel = DEFAULT_AD_HOC_CHANNEL; - adapter->psmode = wlan802_11powermodecam; adapter->multipledtim = MRVDRV_DEFAULT_MULTIPLE_DTIM; @@ -259,12 +249,12 @@ static void wlan_init_adapter(wlan_private * priv) static void command_timer_fn(unsigned long data); -int libertas_init_fw(wlan_private * priv) +int libertas_init_fw(wlan_private * priv, char *fw_name) { int ret = -1; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_FW); /* Allocate adapter structure */ if ((ret = wlan_allocate_adapter(priv)) != 0) @@ -278,7 +268,7 @@ int libertas_init_fw(wlan_private * priv) (unsigned long)priv); /* download fimrware etc. */ - if ((ret = wlan_setup_station_hw(priv)) != 0) { + if ((ret = wlan_setup_station_hw(priv, fw_name)) != 0) { del_timer_sync(&adapter->command_timer); goto done; } @@ -288,7 +278,7 @@ int libertas_init_fw(wlan_private * priv) ret = 0; done: - LEAVE(); + lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); return ret; } @@ -297,25 +287,22 @@ void libertas_free_adapter(wlan_private * priv) wlan_adapter *adapter = priv->adapter; if (!adapter) { - lbs_pr_debug(1, "Why double free adapter?:)\n"); + lbs_deb_fw("why double free adapter?\n"); return; } - lbs_pr_debug(1, "Free command buffer\n"); + lbs_deb_fw("free command buffer\n"); libertas_free_cmd_buffer(priv); - lbs_pr_debug(1, "Free commandTimer\n"); + lbs_deb_fw("free command_timer\n"); del_timer(&adapter->command_timer); - lbs_pr_debug(1, "Free scantable\n"); - if (adapter->scantable) { - kfree(adapter->scantable); - adapter->scantable = NULL; - } - - lbs_pr_debug(1, "Free adapter\n"); + lbs_deb_fw("free scan results table\n"); + kfree(adapter->networks); + adapter->networks = NULL; /* Free the adapter object itself */ + lbs_deb_fw("free adapter\n"); kfree(adapter); priv->adapter = NULL; } @@ -334,17 +321,17 @@ static void command_timer_fn(unsigned long data) ptempnode = adapter->cur_cmd; if (ptempnode == NULL) { - lbs_pr_debug(1, "PTempnode Empty\n"); + lbs_deb_fw("ptempnode empty\n"); return; } cmd = (struct cmd_ds_command *)ptempnode->bufvirtualaddr; if (!cmd) { - lbs_pr_debug(1, "cmd is NULL\n"); + lbs_deb_fw("cmd is NULL\n"); return; } - lbs_pr_info("command_timer_fn fired (%x)\n", cmd->command); + lbs_deb_fw("command_timer_fn fired, cmd %x\n", cmd->command); if (!adapter->fw_ready) return; @@ -353,7 +340,7 @@ static void command_timer_fn(unsigned long data) adapter->cur_cmd = NULL; spin_unlock_irqrestore(&adapter->driver_lock, flags); - lbs_pr_debug(1, "Re-sending same command as it timeout...!\n"); + lbs_deb_fw("re-sending same command because of timeout\n"); libertas_queue_cmd(adapter, ptempnode, 0); wake_up_interruptible(&priv->mainthread.waitq); diff --git a/drivers/net/wireless/libertas/fw.h b/drivers/net/wireless/libertas/fw.h deleted file mode 100644 index 1f9ae267a9e..00000000000 --- a/drivers/net/wireless/libertas/fw.h +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This header file contains FW interface related definitions. - */ -#ifndef _WLAN_FW_H_ -#define _WLAN_FW_H_ - -#ifndef DEV_NAME_LEN -#define DEV_NAME_LEN 32 -#endif - -int libertas_init_fw(wlan_private * priv); - -#endif /* _WLAN_FW_H_ */ diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h index c0faaecaf5b..7509cc10af3 100644 --- a/drivers/net/wireless/libertas/host.h +++ b/drivers/net/wireless/libertas/host.h @@ -99,11 +99,11 @@ #define cmd_bt_access 0x0087 #define cmd_ret_bt_access 0x8087 -#define cmd_fwt_access 0x0088 -#define cmd_ret_fwt_access 0x8088 +#define cmd_fwt_access 0x0095 +#define cmd_ret_fwt_access 0x8095 -#define cmd_mesh_access 0x0090 -#define cmd_ret_mesh_access 0x8090 +#define cmd_mesh_access 0x009b +#define cmd_ret_mesh_access 0x809b /* For the IEEE Power Save */ #define cmd_subcmd_enter_ps 0x0030 @@ -287,7 +287,9 @@ enum cmd_bt_access_opts { cmd_act_bt_access_add = 5, cmd_act_bt_access_del, cmd_act_bt_access_list, - cmd_act_bt_access_reset + cmd_act_bt_access_reset, + cmd_act_bt_access_set_invert, + cmd_act_bt_access_get_invert }; /* Define action or option for cmd_fwt_access */ @@ -308,8 +310,8 @@ enum cmd_mesh_access_opts { cmd_act_mesh_get_ttl = 1, cmd_act_mesh_set_ttl, cmd_act_mesh_get_stats, - cmd_act_mesh_get_mpp, - cmd_act_mesh_set_mpp, + cmd_act_mesh_get_anycast, + cmd_act_mesh_set_anycast, }; /** Card Event definition */ @@ -334,5 +336,6 @@ enum cmd_mesh_access_opts { #define MACREG_INT_CODE_MAX_FAIL 0x0000001b #define MACREG_INT_CODE_RSSI_HIGH 0x0000001c #define MACREG_INT_CODE_SNR_HIGH 0x0000001d +#define MACREG_INT_CODE_MESH_AUTO_STARTED 0x00000023 #endif /* _HOST_H_ */ diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h index f239e5d2435..09b898f6719 100644 --- a/drivers/net/wireless/libertas/hostcmd.h +++ b/drivers/net/wireless/libertas/hostcmd.h @@ -14,12 +14,12 @@ /* TxPD descriptor */ struct txpd { /* Current Tx packet status */ - u32 tx_status; + __le32 tx_status; /* Tx control */ - u32 tx_control; - u32 tx_packet_location; + __le32 tx_control; + __le32 tx_packet_location; /* Tx packet length */ - u16 tx_packet_length; + __le16 tx_packet_length; /* First 2 byte of destination MAC address */ u8 tx_dest_addr_high[2]; /* Last 4 byte of destination MAC address */ @@ -37,7 +37,7 @@ struct txpd { /* RxPD Descriptor */ struct rxpd { /* Current Rx packet status */ - u16 status; + __le16 status; /* SNR */ u8 snr; @@ -46,7 +46,7 @@ struct rxpd { u8 rx_control; /* Pkt length */ - u16 pkt_len; + __le16 pkt_len; /* Noise Floor */ u8 nf; @@ -55,10 +55,10 @@ struct rxpd { u8 rx_rate; /* Pkt addr */ - u32 pkt_ptr; + __le32 pkt_ptr; /* Next Rx RxPD addr */ - u32 next_rxpd_ptr; + __le32 next_rxpd_ptr; /* Pkt Priority */ u8 priority; @@ -89,30 +89,17 @@ struct cmd_ctrl_node { * is determined from the keylength field. */ struct WLAN_802_11_KEY { - u32 len; - u32 flags; /* KEY_INFO_* from wlan_defs.h */ + __le32 len; + __le32 flags; /* KEY_INFO_* from wlan_defs.h */ u8 key[MRVL_MAX_KEY_WPA_KEY_LENGTH]; - u16 type; /* KEY_TYPE_* from wlan_defs.h */ + __le16 type; /* KEY_TYPE_* from wlan_defs.h */ }; struct IE_WPA { u8 elementid; u8 len; u8 oui[4]; - u16 version; -}; - -struct WLAN_802_11_SSID { - /* SSID length */ - u32 ssidlength; - - /* SSID information field */ - u8 ssid[IW_ESSID_MAX_SIZE]; -}; - -struct WPA_SUPPLICANT { - u8 wpa_ie[256]; - u8 wpa_ie_len; + __le16 version; }; /* wlan_offset_value */ @@ -122,9 +109,9 @@ struct wlan_offset_value { }; struct WLAN_802_11_FIXED_IEs { - u8 timestamp[8]; - u16 beaconinterval; - u16 capabilities; + __le64 timestamp; + __le16 beaconinterval; + u16 capabilities; /* Actually struct ieeetypes_capinfo */ }; struct WLAN_802_11_VARIABLE_IEs { @@ -136,10 +123,10 @@ struct WLAN_802_11_VARIABLE_IEs { /* Define general data structure */ /* cmd_DS_GEN */ struct cmd_ds_gen { - u16 command; - u16 size; - u16 seqnum; - u16 result; + __le16 command; + __le16 size; + __le16 seqnum; + __le16 result; }; #define S_DS_GEN sizeof(struct cmd_ds_gen) @@ -149,44 +136,44 @@ struct cmd_ds_gen { */ struct cmd_ds_get_hw_spec { /* HW Interface version number */ - u16 hwifversion; + __le16 hwifversion; /* HW version number */ - u16 version; + __le16 version; /* Max number of TxPD FW can handle */ - u16 nr_txpd; + __le16 nr_txpd; /* Max no of Multicast address */ - u16 nr_mcast_adr; + __le16 nr_mcast_adr; /* MAC address */ u8 permanentaddr[6]; /* region Code */ - u16 regioncode; + __le16 regioncode; /* Number of antenna used */ - u16 nr_antenna; + __le16 nr_antenna; - /* FW release number, example 0x1234=1.2.3.4 */ - u32 fwreleasenumber; + /* FW release number, example 1,2,3,4 = 3.2.1p4 */ + u8 fwreleasenumber[4]; /* Base Address of TxPD queue */ - u32 wcb_base; + __le32 wcb_base; /* Read Pointer of RxPd queue */ - u32 rxpd_rdptr; + __le32 rxpd_rdptr; /* Write Pointer of RxPd queue */ - u32 rxpd_wrptr; + __le32 rxpd_wrptr; /*FW/HW capability */ - u32 fwcapinfo; + __le32 fwcapinfo; } __attribute__ ((packed)); struct cmd_ds_802_11_reset { - u16 action; + __le16 action; }; struct cmd_ds_802_11_subscribe_event { - u16 action; - u16 events; + __le16 action; + __le16 events; }; /* @@ -205,35 +192,35 @@ struct cmd_ds_802_11_scan { }; struct cmd_ds_802_11_scan_rsp { - u16 bssdescriptsize; + __le16 bssdescriptsize; u8 nr_sets; u8 bssdesc_and_tlvbuffer[1]; }; struct cmd_ds_802_11_get_log { - u32 mcasttxframe; - u32 failed; - u32 retry; - u32 multiretry; - u32 framedup; - u32 rtssuccess; - u32 rtsfailure; - u32 ackfailure; - u32 rxfrag; - u32 mcastrxframe; - u32 fcserror; - u32 txframe; - u32 wepundecryptable; + __le32 mcasttxframe; + __le32 failed; + __le32 retry; + __le32 multiretry; + __le32 framedup; + __le32 rtssuccess; + __le32 rtsfailure; + __le32 ackfailure; + __le32 rxfrag; + __le32 mcastrxframe; + __le32 fcserror; + __le32 txframe; + __le32 wepundecryptable; }; struct cmd_ds_mac_control { - u16 action; - u16 reserved; + __le16 action; + __le16 reserved; }; struct cmd_ds_mac_multicast_adr { - u16 action; - u16 nr_of_adrs; + __le16 action; + __le16 nr_of_adrs; u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE]; }; @@ -245,14 +232,14 @@ struct cmd_ds_802_11_authenticate { struct cmd_ds_802_11_deauthenticate { u8 macaddr[6]; - u16 reasoncode; + __le16 reasoncode; }; struct cmd_ds_802_11_associate { u8 peerstaaddr[6]; struct ieeetypes_capinfo capinfo; - u16 listeninterval; - u16 bcnperiod; + __le16 listeninterval; + __le16 bcnperiod; u8 dtimperiod; #if 0 @@ -265,7 +252,7 @@ struct cmd_ds_802_11_associate { struct cmd_ds_802_11_disassociate { u8 destmacaddr[6]; - u16 reasoncode; + __le16 reasoncode; }; struct cmd_ds_802_11_associate_rsp { @@ -279,10 +266,10 @@ struct cmd_ds_802_11_ad_hoc_result { struct cmd_ds_802_11_set_wep { /* ACT_ADD, ACT_REMOVE or ACT_ENABLE */ - u16 action; + __le16 action; /* key Index selected for Tx */ - u16 keyindex; + __le16 keyindex; /* 40, 128bit or TXWEP */ u8 keytype[4]; @@ -290,96 +277,96 @@ struct cmd_ds_802_11_set_wep { }; struct cmd_ds_802_3_get_stat { - u32 xmitok; - u32 rcvok; - u32 xmiterror; - u32 rcverror; - u32 rcvnobuffer; - u32 rcvcrcerror; + __le32 xmitok; + __le32 rcvok; + __le32 xmiterror; + __le32 rcverror; + __le32 rcvnobuffer; + __le32 rcvcrcerror; }; struct cmd_ds_802_11_get_stat { - u32 txfragmentcnt; - u32 mcasttxframecnt; - u32 failedcnt; - u32 retrycnt; - u32 Multipleretrycnt; - u32 rtssuccesscnt; - u32 rtsfailurecnt; - u32 ackfailurecnt; - u32 frameduplicatecnt; - u32 rxfragmentcnt; - u32 mcastrxframecnt; - u32 fcserrorcnt; - u32 bcasttxframecnt; - u32 bcastrxframecnt; - u32 txbeacon; - u32 rxbeacon; - u32 wepundecryptable; + __le32 txfragmentcnt; + __le32 mcasttxframecnt; + __le32 failedcnt; + __le32 retrycnt; + __le32 Multipleretrycnt; + __le32 rtssuccesscnt; + __le32 rtsfailurecnt; + __le32 ackfailurecnt; + __le32 frameduplicatecnt; + __le32 rxfragmentcnt; + __le32 mcastrxframecnt; + __le32 fcserrorcnt; + __le32 bcasttxframecnt; + __le32 bcastrxframecnt; + __le32 txbeacon; + __le32 rxbeacon; + __le32 wepundecryptable; }; struct cmd_ds_802_11_snmp_mib { - u16 querytype; - u16 oid; - u16 bufsize; + __le16 querytype; + __le16 oid; + __le16 bufsize; u8 value[128]; }; struct cmd_ds_mac_reg_map { - u16 buffersize; + __le16 buffersize; u8 regmap[128]; - u16 reserved; + __le16 reserved; }; struct cmd_ds_bbp_reg_map { - u16 buffersize; + __le16 buffersize; u8 regmap[128]; - u16 reserved; + __le16 reserved; }; struct cmd_ds_rf_reg_map { - u16 buffersize; + __le16 buffersize; u8 regmap[64]; - u16 reserved; + __le16 reserved; }; struct cmd_ds_mac_reg_access { - u16 action; - u16 offset; - u32 value; + __le16 action; + __le16 offset; + __le32 value; }; struct cmd_ds_bbp_reg_access { - u16 action; - u16 offset; + __le16 action; + __le16 offset; u8 value; u8 reserved[3]; }; struct cmd_ds_rf_reg_access { - u16 action; - u16 offset; + __le16 action; + __le16 offset; u8 value; u8 reserved[3]; }; struct cmd_ds_802_11_radio_control { - u16 action; - u16 control; + __le16 action; + __le16 control; }; struct cmd_ds_802_11_sleep_params { /* ACT_GET/ACT_SET */ - u16 action; + __le16 action; /* Sleep clock error in ppm */ - u16 error; + __le16 error; /* Wakeup offset in usec */ - u16 offset; + __le16 offset; /* Clock stabilization time in usec */ - u16 stabletime; + __le16 stabletime; /* control periodic calibration */ u8 calcontrol; @@ -388,100 +375,100 @@ struct cmd_ds_802_11_sleep_params { u8 externalsleepclk; /* reserved field, should be set to zero */ - u16 reserved; + __le16 reserved; }; struct cmd_ds_802_11_inactivity_timeout { /* ACT_GET/ACT_SET */ - u16 action; + __le16 action; /* Inactivity timeout in msec */ - u16 timeout; + __le16 timeout; }; struct cmd_ds_802_11_rf_channel { - u16 action; - u16 currentchannel; - u16 rftype; - u16 reserved; + __le16 action; + __le16 currentchannel; + __le16 rftype; + __le16 reserved; u8 channellist[32]; }; struct cmd_ds_802_11_rssi { /* weighting factor */ - u16 N; + __le16 N; - u16 reserved_0; - u16 reserved_1; - u16 reserved_2; + __le16 reserved_0; + __le16 reserved_1; + __le16 reserved_2; }; struct cmd_ds_802_11_rssi_rsp { - u16 SNR; - u16 noisefloor; - u16 avgSNR; - u16 avgnoisefloor; + __le16 SNR; + __le16 noisefloor; + __le16 avgSNR; + __le16 avgnoisefloor; }; struct cmd_ds_802_11_mac_address { - u16 action; + __le16 action; u8 macadd[ETH_ALEN]; }; struct cmd_ds_802_11_rf_tx_power { - u16 action; - u16 currentlevel; + __le16 action; + __le16 currentlevel; }; struct cmd_ds_802_11_rf_antenna { - u16 action; + __le16 action; /* Number of antennas or 0xffff(diversity) */ - u16 antennamode; + __le16 antennamode; }; struct cmd_ds_802_11_ps_mode { - u16 action; - u16 nullpktinterval; - u16 multipledtim; - u16 reserved; - u16 locallisteninterval; + __le16 action; + __le16 nullpktinterval; + __le16 multipledtim; + __le16 reserved; + __le16 locallisteninterval; }; struct PS_CMD_ConfirmSleep { - u16 command; - u16 size; - u16 seqnum; - u16 result; + __le16 command; + __le16 size; + __le16 seqnum; + __le16 result; - u16 action; - u16 reserved1; - u16 multipledtim; - u16 reserved; - u16 locallisteninterval; + __le16 action; + __le16 reserved1; + __le16 multipledtim; + __le16 reserved; + __le16 locallisteninterval; }; struct cmd_ds_802_11_data_rate { - u16 action; - u16 reserverd; + __le16 action; + __le16 reserverd; u8 datarate[G_SUPPORTED_RATES]; }; struct cmd_ds_802_11_rate_adapt_rateset { - u16 action; - u16 enablehwauto; - u16 bitmap; + __le16 action; + __le16 enablehwauto; + __le16 bitmap; }; struct cmd_ds_802_11_ad_hoc_start { u8 SSID[IW_ESSID_MAX_SIZE]; u8 bsstype; - u16 beaconperiod; + __le16 beaconperiod; u8 dtimperiod; union IEEEtypes_ssparamset ssparamset; union ieeetypes_phyparamset phyparamset; - u16 probedelay; + __le16 probedelay; struct ieeetypes_capinfo cap; u8 datarate[G_SUPPORTED_RATES]; u8 tlv_memory_size_pad[100]; @@ -491,10 +478,10 @@ struct adhoc_bssdesc { u8 BSSID[6]; u8 SSID[32]; u8 bsstype; - u16 beaconperiod; + __le16 beaconperiod; u8 dtimperiod; - u8 timestamp[8]; - u8 localtime[8]; + __le64 timestamp; + __le64 localtime; union ieeetypes_phyparamset phyparamset; union IEEEtypes_ssparamset ssparamset; struct ieeetypes_capinfo cap; @@ -508,52 +495,52 @@ struct adhoc_bssdesc { struct cmd_ds_802_11_ad_hoc_join { struct adhoc_bssdesc bssdescriptor; - u16 failtimeout; - u16 probedelay; + __le16 failtimeout; + __le16 probedelay; } __attribute__ ((packed)); struct cmd_ds_802_11_enable_rsn { - u16 action; - u16 enable; -}; + __le16 action; + __le16 enable; +} __attribute__ ((packed)); struct MrvlIEtype_keyParamSet { /* type ID */ - u16 type; + __le16 type; /* length of Payload */ - u16 length; + __le16 length; /* type of key: WEP=0, TKIP=1, AES=2 */ - u16 keytypeid; + __le16 keytypeid; /* key control Info specific to a keytypeid */ - u16 keyinfo; + __le16 keyinfo; /* length of key */ - u16 keylen; + __le16 keylen; /* key material of size keylen */ u8 key[32]; }; struct cmd_ds_802_11_key_material { - u16 action; + __le16 action; struct MrvlIEtype_keyParamSet keyParamSet[2]; } __attribute__ ((packed)); struct cmd_ds_802_11_eeprom_access { - u16 action; + __le16 action; /* multiple 4 */ - u16 offset; - u16 bytecount; + __le16 offset; + __le16 bytecount; u8 value; } __attribute__ ((packed)); struct cmd_ds_802_11_tpc_cfg { - u16 action; + __le16 action; u8 enable; s8 P0; s8 P1; @@ -562,13 +549,13 @@ struct cmd_ds_802_11_tpc_cfg { } __attribute__ ((packed)); struct cmd_ds_802_11_led_ctrl { - u16 action; - u16 numled; + __le16 action; + __le16 numled; u8 data[256]; } __attribute__ ((packed)); struct cmd_ds_802_11_pwr_cfg { - u16 action; + __le16 action; u8 enable; s8 PA_P0; s8 PA_P1; @@ -576,21 +563,21 @@ struct cmd_ds_802_11_pwr_cfg { } __attribute__ ((packed)); struct cmd_ds_802_11_afc { - u16 afc_auto; + __le16 afc_auto; union { struct { - u16 threshold; - u16 period; + __le16 threshold; + __le16 period; }; struct { - s16 timing_offset; - s16 carrier_offset; + __le16 timing_offset; /* signed */ + __le16 carrier_offset; /* signed */ }; }; } __attribute__ ((packed)); struct cmd_tx_rate_query { - u16 txrate; + __le16 txrate; } __attribute__ ((packed)); struct cmd_ds_get_tsf { @@ -598,41 +585,46 @@ struct cmd_ds_get_tsf { } __attribute__ ((packed)); struct cmd_ds_bt_access { - u16 action; - u32 id; + __le16 action; + __le32 id; u8 addr1[ETH_ALEN]; u8 addr2[ETH_ALEN]; } __attribute__ ((packed)); struct cmd_ds_fwt_access { - u16 action; - u32 id; + __le16 action; + __le32 id; + u8 valid; u8 da[ETH_ALEN]; u8 dir; u8 ra[ETH_ALEN]; - u32 ssn; - u32 dsn; - u32 metric; + __le32 ssn; + __le32 dsn; + __le32 metric; + u8 rate; u8 hopcount; u8 ttl; - u32 expiration; + __le32 expiration; u8 sleepmode; - u32 snr; - u32 references; + __le32 snr; + __le32 references; + u8 prec[ETH_ALEN]; } __attribute__ ((packed)); -#define MESH_STATS_NUM 7 struct cmd_ds_mesh_access { - u16 action; - u32 data[MESH_STATS_NUM + 1]; /* last position reserved */ + __le16 action; + __le32 data[32]; /* last position reserved */ } __attribute__ ((packed)); +/* Number of stats counters returned by the firmware */ +#define MESH_STATS_NUM 8 + struct cmd_ds_command { /* command header */ - u16 command; - u16 size; - u16 seqnum; - u16 result; + __le16 command; + __le16 size; + __le16 seqnum; + __le16 result; /* command Body */ union { diff --git a/drivers/net/wireless/libertas/if_bootcmd.c b/drivers/net/wireless/libertas/if_bootcmd.c index 567000c3e87..8bca306ffad 100644 --- a/drivers/net/wireless/libertas/if_bootcmd.c +++ b/drivers/net/wireless/libertas/if_bootcmd.c @@ -8,6 +8,8 @@ #include <linux/netdevice.h> #include <linux/usb.h> +#define DRV_NAME "usb8xxx" + #include "defs.h" #include "dev.h" #include "if_usb.h" @@ -20,12 +22,12 @@ */ int if_usb_issue_boot_command(wlan_private *priv, int ivalue) { - struct usb_card_rec *cardp = priv->wlan_dev.card; + struct usb_card_rec *cardp = priv->card; struct bootcmdstr sbootcmd; int i; /* Prepare command */ - sbootcmd.u32magicnumber = BOOT_CMD_MAGIC_NUMBER; + sbootcmd.u32magicnumber = cpu_to_le32(BOOT_CMD_MAGIC_NUMBER); sbootcmd.u8cmd_tag = ivalue; for (i=0; i<11; i++) sbootcmd.au8dumy[i]=0x00; diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index ae6f72a6cdf..998317571ec 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -2,12 +2,15 @@ * This file contains functions used in USB interface module. */ #include <linux/delay.h> +#include <linux/moduleparam.h> #include <linux/firmware.h> #include <linux/netdevice.h> +#include <linux/list.h> #include <linux/usb.h> +#define DRV_NAME "usb8xxx" + #include "host.h" -#include "sbi.h" #include "decl.h" #include "defs.h" #include "dev.h" @@ -16,15 +19,24 @@ #define MESSAGE_HEADER_LEN 4 static const char usbdriver_name[] = "usb8xxx"; +static u8 *default_fw_name = "usb8388.bin"; + +char *libertas_fw_name = NULL; +module_param_named(fw_name, libertas_fw_name, charp, 0644); + +/* + * We need to send a RESET command to all USB devices before + * we tear down the USB connection. Otherwise we would not + * be able to re-init device the device if the module gets + * loaded again. This is a list of all initialized USB devices, + * for the reset code see if_usb_reset_device() +*/ +static LIST_HEAD(usb_devices); static struct usb_device_id if_usb_table[] = { /* Enter the device signature inside */ - { - USB_DEVICE(USB8388_VID_1, USB8388_PID_1), - }, - { - USB_DEVICE(USB8388_VID_2, USB8388_PID_2), - }, + { USB_DEVICE(0x1286, 0x2001) }, + { USB_DEVICE(0x05a3, 0x8388) }, {} /* Terminating entry */ }; @@ -32,6 +44,13 @@ MODULE_DEVICE_TABLE(usb, if_usb_table); static void if_usb_receive(struct urb *urb); static void if_usb_receive_fwload(struct urb *urb); +static int if_usb_reset_device(wlan_private *priv); +static int if_usb_register_dev(wlan_private * priv); +static int if_usb_unregister_dev(wlan_private *); +static int if_usb_prog_firmware(wlan_private *); +static int if_usb_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb); +static int if_usb_get_int_status(wlan_private * priv, u8 *); +static int if_usb_read_event_cause(wlan_private *); /** * @brief call back function to handle the status of the URB @@ -42,23 +61,27 @@ static void if_usb_write_bulk_callback(struct urb *urb) { wlan_private *priv = (wlan_private *) (urb->context); wlan_adapter *adapter = priv->adapter; - struct net_device *dev = priv->wlan_dev.netdev; + struct net_device *dev = priv->dev; /* handle the transmission complete validations */ if (urb->status != 0) { /* print the failure status number for debug */ - lbs_pr_info("URB in failure status\n"); + lbs_pr_info("URB in failure status: %d\n", urb->status); } else { - lbs_dev_dbg(2, &urb->dev->dev, "URB status is successfull\n"); - lbs_dev_dbg(2, &urb->dev->dev, "Actual length transmitted %d\n", + /* + lbs_deb_usbd(&urb->dev->dev, "URB status is successfull\n"); + lbs_deb_usbd(&urb->dev->dev, "Actual length transmitted %d\n", urb->actual_length); - priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED; + */ + priv->dnld_sent = DNLD_RES_RECEIVED; /* Wake main thread if commands are pending */ if (!adapter->cur_cmd) wake_up_interruptible(&priv->mainthread.waitq); - if ((adapter->connect_status == libertas_connected)) + if ((adapter->connect_status == libertas_connected)) { netif_wake_queue(dev); + netif_wake_queue(priv->mesh_dev); + } } return; @@ -71,7 +94,7 @@ static void if_usb_write_bulk_callback(struct urb *urb) */ void if_usb_free(struct usb_card_rec *cardp) { - ENTER(); + lbs_deb_enter(LBS_DEB_USB); /* Unlink tx & rx urb */ usb_kill_urb(cardp->tx_urb); @@ -86,8 +109,7 @@ void if_usb_free(struct usb_card_rec *cardp) kfree(cardp->bulk_out_buffer); cardp->bulk_out_buffer = NULL; - LEAVE(); - return; + lbs_deb_leave(LBS_DEB_USB); } /** @@ -102,27 +124,27 @@ static int if_usb_probe(struct usb_interface *intf, struct usb_device *udev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; - wlan_private *pwlanpriv; - struct usb_card_rec *usb_cardp; + wlan_private *priv; + struct usb_card_rec *cardp; int i; udev = interface_to_usbdev(intf); - usb_cardp = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL); - if (!usb_cardp) { + cardp = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL); + if (!cardp) { lbs_pr_err("Out of memory allocating private data.\n"); goto error; } - usb_cardp->udev = udev; + cardp->udev = udev; iface_desc = intf->cur_altsetting; - lbs_dev_dbg(1, &udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X" + lbs_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X" " bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n", - udev->descriptor.bcdUSB, - udev->descriptor.bDeviceClass, - udev->descriptor.bDeviceSubClass, - udev->descriptor.bDeviceProtocol); + le16_to_cpu(udev->descriptor.bcdUSB), + udev->descriptor.bDeviceClass, + udev->descriptor.bDeviceSubClass, + udev->descriptor.bDeviceProtocol); for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; @@ -130,23 +152,21 @@ static int if_usb_probe(struct usb_interface *intf, && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)) { /* we found a bulk in endpoint */ - lbs_dev_dbg(1, &udev->dev, "Bulk in size is %d\n", - endpoint->wMaxPacketSize); - if (! - (usb_cardp->rx_urb = - usb_alloc_urb(0, GFP_KERNEL))) { - lbs_dev_dbg(1, &udev->dev, + lbs_deb_usbd(&udev->dev, "Bulk in size is %d\n", + le16_to_cpu(endpoint->wMaxPacketSize)); + if (!(cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL))) { + lbs_deb_usbd(&udev->dev, "Rx URB allocation failed\n"); goto dealloc; } - usb_cardp->rx_urb_recall = 0; + cardp->rx_urb_recall = 0; - usb_cardp->bulk_in_size = - endpoint->wMaxPacketSize; - usb_cardp->bulk_in_endpointAddr = + cardp->bulk_in_size = + le16_to_cpu(endpoint->wMaxPacketSize); + cardp->bulk_in_endpointAddr = (endpoint-> bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); - lbs_dev_dbg(1, &udev->dev, "in_endpoint = %d\n", + lbs_deb_usbd(&udev->dev, "in_endpoint = %d\n", endpoint->bEndpointAddress); } @@ -156,55 +176,63 @@ static int if_usb_probe(struct usb_interface *intf, && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)) { /* We found bulk out endpoint */ - if (! - (usb_cardp->tx_urb = - usb_alloc_urb(0, GFP_KERNEL))) { - lbs_dev_dbg(1,&udev->dev, + if (!(cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL))) { + lbs_deb_usbd(&udev->dev, "Tx URB allocation failed\n"); goto dealloc; } - usb_cardp->bulk_out_size = - endpoint->wMaxPacketSize; - lbs_dev_dbg(1, &udev->dev, - "Bulk out size is %d\n", - endpoint->wMaxPacketSize); - usb_cardp->bulk_out_endpointAddr = + cardp->bulk_out_size = + le16_to_cpu(endpoint->wMaxPacketSize); + lbs_deb_usbd(&udev->dev, + "Bulk out size is %d\n", + le16_to_cpu(endpoint->wMaxPacketSize)); + cardp->bulk_out_endpointAddr = endpoint->bEndpointAddress; - lbs_dev_dbg(1, &udev->dev, "out_endpoint = %d\n", + lbs_deb_usbd(&udev->dev, "out_endpoint = %d\n", endpoint->bEndpointAddress); - usb_cardp->bulk_out_buffer = + cardp->bulk_out_buffer = kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE, GFP_KERNEL); - if (!usb_cardp->bulk_out_buffer) { - lbs_dev_dbg(1, &udev->dev, + if (!cardp->bulk_out_buffer) { + lbs_deb_usbd(&udev->dev, "Could not allocate buffer\n"); goto dealloc; } } } - - /* At this point wlan_add_card() will be called. Don't worry - * about keeping pwlanpriv around since it will be set on our - * usb device data in -> add() -> libertas_sbi_register_dev(). - */ - if (!(pwlanpriv = wlan_add_card(usb_cardp))) + if (!(priv = libertas_add_card(cardp, &udev->dev))) goto dealloc; + if (libertas_add_mesh(priv, &udev->dev)) + goto err_add_mesh; + + priv->hw_register_dev = if_usb_register_dev; + priv->hw_unregister_dev = if_usb_unregister_dev; + priv->hw_prog_firmware = if_usb_prog_firmware; + priv->hw_host_to_card = if_usb_host_to_card; + priv->hw_get_int_status = if_usb_get_int_status; + priv->hw_read_event_cause = if_usb_read_event_cause; + + if (libertas_activate_card(priv, libertas_fw_name)) + goto err_activate_card; + + list_add_tail(&cardp->list, &usb_devices); + usb_get_dev(udev); - usb_set_intfdata(intf, usb_cardp); + usb_set_intfdata(intf, cardp); - /* - * return card structure, which can be got back in the - * diconnect function as the ptr - * argument. - */ return 0; +err_activate_card: + libertas_remove_mesh(priv); +err_add_mesh: + free_netdev(priv->dev); + kfree(priv->adapter); dealloc: - if_usb_free(usb_cardp); + if_usb_free(cardp); error: return -ENOMEM; @@ -212,8 +240,7 @@ error: /** * @brief free resource and cleanup - * @param udev pointer to usb_device - * @param ptr pointer to usb_cardp + * @param intf USB interface structure * @return N/A */ static void if_usb_disconnect(struct usb_interface *intf) @@ -229,9 +256,12 @@ static void if_usb_disconnect(struct usb_interface *intf) */ adapter->surpriseremoved = 1; + list_del(&cardp->list); + /* card is removed and we can call wlan_remove_card */ - lbs_dev_dbg(1, &cardp->udev->dev, "call remove card\n"); - wlan_remove_card(cardp); + lbs_deb_usbd(&cardp->udev->dev, "call remove card\n"); + libertas_remove_mesh(priv); + libertas_remove_card(priv); /* Unlink and free urb */ if_usb_free(cardp); @@ -249,7 +279,7 @@ static void if_usb_disconnect(struct usb_interface *intf) */ static int if_prog_firmware(wlan_private * priv) { - struct usb_card_rec *cardp = priv->wlan_dev.card; + struct usb_card_rec *cardp = priv->card; struct FWData *fwdata; struct fwheader *fwheader; u8 *firmware = priv->firmware->data; @@ -266,8 +296,10 @@ static int if_prog_firmware(wlan_private * priv) cardp->fwseqnum = cardp->lastseqnum - 1; } - lbs_dev_dbg(2, &cardp->udev->dev, "totalbytes = %d\n", + /* + lbs_deb_usbd(&cardp->udev->dev, "totalbytes = %d\n", cardp->totalbytes); + */ memcpy(fwheader, &firmware[cardp->totalbytes], sizeof(struct fwheader)); @@ -275,40 +307,48 @@ static int if_prog_firmware(wlan_private * priv) cardp->fwlastblksent = cardp->totalbytes; cardp->totalbytes += sizeof(struct fwheader); - lbs_dev_dbg(2, &cardp->udev->dev,"Copy Data\n"); + /* lbs_deb_usbd(&cardp->udev->dev,"Copy Data\n"); */ memcpy(fwdata->data, &firmware[cardp->totalbytes], - fwdata->fwheader.datalength); + le32_to_cpu(fwdata->fwheader.datalength)); - lbs_dev_dbg(2, &cardp->udev->dev, - "Data length = %d\n", fwdata->fwheader.datalength); + /* + lbs_deb_usbd(&cardp->udev->dev, + "Data length = %d\n", le32_to_cpu(fwdata->fwheader.datalength)); + */ cardp->fwseqnum = cardp->fwseqnum + 1; - fwdata->seqnum = cardp->fwseqnum; - cardp->lastseqnum = fwdata->seqnum; - cardp->totalbytes += fwdata->fwheader.datalength; + fwdata->seqnum = cpu_to_le32(cardp->fwseqnum); + cardp->lastseqnum = cardp->fwseqnum; + cardp->totalbytes += le32_to_cpu(fwdata->fwheader.datalength); - if (fwheader->dnldcmd == FW_HAS_DATA_TO_RECV) { - lbs_dev_dbg(2, &cardp->udev->dev, "There is data to follow\n"); - lbs_dev_dbg(2, &cardp->udev->dev, + if (fwheader->dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) { + /* + lbs_deb_usbd(&cardp->udev->dev, "There are data to follow\n"); + lbs_deb_usbd(&cardp->udev->dev, "seqnum = %d totalbytes = %d\n", cardp->fwseqnum, cardp->totalbytes); + */ memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE); usb_tx_block(priv, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE); - } else if (fwdata->fwheader.dnldcmd == FW_HAS_LAST_BLOCK) { - lbs_dev_dbg(2, &cardp->udev->dev, + } else if (fwdata->fwheader.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) { + /* + lbs_deb_usbd(&cardp->udev->dev, "Host has finished FW downloading\n"); - lbs_dev_dbg(2, &cardp->udev->dev, + lbs_deb_usbd(&cardp->udev->dev, "Donwloading FW JUMP BLOCK\n"); + */ memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE); usb_tx_block(priv, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE); cardp->fwfinalblk = 1; } - lbs_dev_dbg(2, &cardp->udev->dev, + /* + lbs_deb_usbd(&cardp->udev->dev, "The firmware download is done size is %d\n", cardp->totalbytes); + */ kfree(fwdata); @@ -318,14 +358,19 @@ static int if_prog_firmware(wlan_private * priv) static int libertas_do_reset(wlan_private *priv) { int ret; - struct usb_card_rec *cardp = priv->wlan_dev.card; + struct usb_card_rec *cardp = priv->card; + + lbs_deb_enter(LBS_DEB_USB); ret = usb_reset_device(cardp->udev); if (!ret) { msleep(10); - reset_device(priv); + if_usb_reset_device(priv); msleep(10); } + + lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret); + return ret; } @@ -339,12 +384,12 @@ static int libertas_do_reset(wlan_private *priv) int usb_tx_block(wlan_private * priv, u8 * payload, u16 nb) { /* pointer to card structure */ - struct usb_card_rec *cardp = priv->wlan_dev.card; + struct usb_card_rec *cardp = priv->card; int ret = -1; /* check if device is removed */ if (priv->adapter->surpriseremoved) { - lbs_dev_dbg(1, &cardp->udev->dev, "Device removed\n"); + lbs_deb_usbd(&cardp->udev->dev, "Device removed\n"); goto tx_ret; } @@ -357,10 +402,10 @@ int usb_tx_block(wlan_private * priv, u8 * payload, u16 nb) if ((ret = usb_submit_urb(cardp->tx_urb, GFP_ATOMIC))) { /* transfer failed */ - lbs_dev_dbg(1, &cardp->udev->dev, "usb_submit_urb failed\n"); + lbs_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed\n"); ret = -1; } else { - lbs_dev_dbg(2, &cardp->udev->dev, "usb_submit_urb success\n"); + /* lbs_deb_usbd(&cardp->udev->dev, "usb_submit_urb success\n"); */ ret = 0; } @@ -372,7 +417,7 @@ static int __if_usb_submit_rx_urb(wlan_private * priv, void (*callbackfn) (struct urb *urb)) { - struct usb_card_rec *cardp = priv->wlan_dev.card; + struct usb_card_rec *cardp = priv->card; struct sk_buff *skb; struct read_cb_info *rinfo = &cardp->rinfo; int ret = -1; @@ -394,13 +439,13 @@ static int __if_usb_submit_rx_urb(wlan_private * priv, cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET; - lbs_dev_dbg(2, &cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb); + /* lbs_deb_usbd(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb); */ if ((ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC))) { /* handle failure conditions */ - lbs_dev_dbg(1, &cardp->udev->dev, "Submit Rx URB failed\n"); + lbs_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed\n"); ret = -1; } else { - lbs_dev_dbg(2, &cardp->udev->dev, "Submit Rx URB success\n"); + /* lbs_deb_usbd(&cardp->udev->dev, "Submit Rx URB success\n"); */ ret = 0; } @@ -423,12 +468,12 @@ static void if_usb_receive_fwload(struct urb *urb) struct read_cb_info *rinfo = (struct read_cb_info *)urb->context; wlan_private *priv = rinfo->priv; struct sk_buff *skb = rinfo->skb; - struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card; + struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card; struct fwsyncheader *syncfwheader; struct bootcmdrespStr bootcmdresp; if (urb->status) { - lbs_dev_dbg(1, &cardp->udev->dev, + lbs_deb_usbd(&cardp->udev->dev, "URB status is failed during fw load\n"); kfree_skb(skb); return; @@ -437,18 +482,18 @@ static void if_usb_receive_fwload(struct urb *urb) if (cardp->bootcmdresp == 0) { memcpy (&bootcmdresp, skb->data + IPFIELD_ALIGN_OFFSET, sizeof(bootcmdresp)); - if (cardp->udev->descriptor.bcdDevice < 0x3106) { + if (le16_to_cpu(cardp->udev->descriptor.bcdDevice) < 0x3106) { kfree_skb(skb); if_usb_submit_rx_urb_fwload(priv); cardp->bootcmdresp = 1; - lbs_dev_dbg(1, &cardp->udev->dev, + lbs_deb_usbd(&cardp->udev->dev, "Received valid boot command response\n"); return; } - if (bootcmdresp.u32magicnumber != BOOT_CMD_MAGIC_NUMBER) { + if (bootcmdresp.u32magicnumber != cpu_to_le32(BOOT_CMD_MAGIC_NUMBER)) { lbs_pr_info( "boot cmd response wrong magic number (0x%x)\n", - bootcmdresp.u32magicnumber); + le32_to_cpu(bootcmdresp.u32magicnumber)); } else if (bootcmdresp.u8cmd_tag != BOOT_CMD_FW_BY_USB) { lbs_pr_info( "boot cmd response cmd_tag error (%d)\n", @@ -459,7 +504,7 @@ static void if_usb_receive_fwload(struct urb *urb) bootcmdresp.u8result); } else { cardp->bootcmdresp = 1; - lbs_dev_dbg(1, &cardp->udev->dev, + lbs_deb_usbd(&cardp->udev->dev, "Received valid boot command response\n"); } kfree_skb(skb); @@ -469,7 +514,7 @@ static void if_usb_receive_fwload(struct urb *urb) syncfwheader = kmalloc(sizeof(struct fwsyncheader), GFP_ATOMIC); if (!syncfwheader) { - lbs_dev_dbg(1, &cardp->udev->dev, "Failure to allocate syncfwheader\n"); + lbs_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n"); kfree_skb(skb); return; } @@ -478,14 +523,16 @@ static void if_usb_receive_fwload(struct urb *urb) sizeof(struct fwsyncheader)); if (!syncfwheader->cmd) { - lbs_dev_dbg(2, &cardp->udev->dev, + /* + lbs_deb_usbd(&cardp->udev->dev, "FW received Blk with correct CRC\n"); - lbs_dev_dbg(2, &cardp->udev->dev, + lbs_deb_usbd(&cardp->udev->dev, "FW received Blk seqnum = %d\n", syncfwheader->seqnum); + */ cardp->CRC_OK = 1; } else { - lbs_dev_dbg(1, &cardp->udev->dev, + lbs_deb_usbd(&cardp->udev->dev, "FW received Blk with CRC error\n"); cardp->CRC_OK = 0; } @@ -515,7 +562,7 @@ static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb, { if (recvlength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + MESSAGE_HEADER_LEN || recvlength < MRVDRV_MIN_PKT_LEN) { - lbs_dev_dbg(1, &cardp->udev->dev, + lbs_deb_usbd(&cardp->udev->dev, "Packet length is Invalid\n"); kfree_skb(skb); return; @@ -525,7 +572,7 @@ static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb, skb_put(skb, recvlength); skb_pull(skb, MESSAGE_HEADER_LEN); libertas_process_rxed_packet(priv, skb); - priv->wlan_dev.upld_len = (recvlength - MESSAGE_HEADER_LEN); + priv->upld_len = (recvlength - MESSAGE_HEADER_LEN); } static inline void process_cmdrequest(int recvlength, u8 *recvbuff, @@ -535,7 +582,7 @@ static inline void process_cmdrequest(int recvlength, u8 *recvbuff, { u8 *cmdbuf; if (recvlength > MRVDRV_SIZE_OF_CMD_BUFFER) { - lbs_dev_dbg(1, &cardp->udev->dev, + lbs_deb_usbd(&cardp->udev->dev, "The receive buffer is too large\n"); kfree_skb(skb); return; @@ -548,21 +595,21 @@ static inline void process_cmdrequest(int recvlength, u8 *recvbuff, /* take care of cur_cmd = NULL case by reading the * data to clear the interrupt */ if (!priv->adapter->cur_cmd) { - cmdbuf = priv->wlan_dev.upld_buf; + cmdbuf = priv->upld_buf; priv->adapter->hisregcpy &= ~his_cmdupldrdy; } else cmdbuf = priv->adapter->cur_cmd->bufvirtualaddr; cardp->usb_int_cause |= his_cmdupldrdy; - priv->wlan_dev.upld_len = (recvlength - MESSAGE_HEADER_LEN); + priv->upld_len = (recvlength - MESSAGE_HEADER_LEN); memcpy(cmdbuf, recvbuff + MESSAGE_HEADER_LEN, - priv->wlan_dev.upld_len); + priv->upld_len); kfree_skb(skb); - libertas_interrupt(priv->wlan_dev.netdev); + libertas_interrupt(priv->dev); spin_unlock(&priv->adapter->driver_lock); - lbs_dev_dbg(1, &cardp->udev->dev, + lbs_deb_usbd(&cardp->udev->dev, "Wake up main thread to handle cmd response\n"); return; @@ -580,17 +627,17 @@ static void if_usb_receive(struct urb *urb) struct read_cb_info *rinfo = (struct read_cb_info *)urb->context; wlan_private *priv = rinfo->priv; struct sk_buff *skb = rinfo->skb; - struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card; + struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card; int recvlength = urb->actual_length; u8 *recvbuff = NULL; u32 recvtype; - ENTER(); + lbs_deb_enter(LBS_DEB_USB); if (recvlength) { if (urb->status) { - lbs_dev_dbg(1, &cardp->udev->dev, + lbs_deb_usbd(&cardp->udev->dev, "URB status is failed\n"); kfree_skb(skb); goto setup_for_next; @@ -598,12 +645,12 @@ static void if_usb_receive(struct urb *urb) recvbuff = skb->data + IPFIELD_ALIGN_OFFSET; memcpy(&recvtype, recvbuff, sizeof(u32)); - lbs_dev_dbg(1, &cardp->udev->dev, + lbs_deb_usbd(&cardp->udev->dev, "Recv length = 0x%x\n", recvlength); - lbs_dev_dbg(1, &cardp->udev->dev, + lbs_deb_usbd(&cardp->udev->dev, "Receive type = 0x%X\n", recvtype); recvtype = le32_to_cpu(recvtype); - lbs_dev_dbg(1, &cardp->udev->dev, + lbs_deb_usbd(&cardp->udev->dev, "Receive type after = 0x%X\n", recvtype); } else if (urb->status) goto rx_exit; @@ -621,18 +668,18 @@ static void if_usb_receive(struct urb *urb) case CMD_TYPE_INDICATION: /* Event cause handling */ spin_lock(&priv->adapter->driver_lock); - cardp->usb_event_cause = *(u32 *) (recvbuff + MESSAGE_HEADER_LEN); - lbs_dev_dbg(1, &cardp->udev->dev,"**EVENT** 0x%X\n", + cardp->usb_event_cause = le32_to_cpu(*(__le32 *) (recvbuff + MESSAGE_HEADER_LEN)); + lbs_deb_usbd(&cardp->udev->dev,"**EVENT** 0x%X\n", cardp->usb_event_cause); if (cardp->usb_event_cause & 0xffff0000) { libertas_send_tx_feedback(priv); spin_unlock(&priv->adapter->driver_lock); break; } - cardp->usb_event_cause = le32_to_cpu(cardp->usb_event_cause) << 3; + cardp->usb_event_cause <<= 3; cardp->usb_int_cause |= his_cardevent; kfree_skb(skb); - libertas_interrupt(priv->wlan_dev.netdev); + libertas_interrupt(priv->dev); spin_unlock(&priv->adapter->driver_lock); goto rx_exit; default: @@ -643,8 +690,7 @@ static void if_usb_receive(struct urb *urb) setup_for_next: if_usb_submit_rx_urb(priv); rx_exit: - LEAVE(); - return; + lbs_deb_leave(LBS_DEB_USB); } /** @@ -655,24 +701,24 @@ rx_exit: * @param len number of bytes * @return 0 or -1 */ -int libertas_sbi_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb) +static int if_usb_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb) { int ret = -1; u32 tmp; - struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card; + struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card; - lbs_dev_dbg(1, &cardp->udev->dev,"*** type = %u\n", type); - lbs_dev_dbg(1, &cardp->udev->dev,"size after = %d\n", nb); + lbs_deb_usbd(&cardp->udev->dev,"*** type = %u\n", type); + lbs_deb_usbd(&cardp->udev->dev,"size after = %d\n", nb); if (type == MVMS_CMD) { tmp = cpu_to_le32(CMD_TYPE_REQUEST); - priv->wlan_dev.dnld_sent = DNLD_CMD_SENT; + priv->dnld_sent = DNLD_CMD_SENT; memcpy(cardp->bulk_out_buffer, (u8 *) & tmp, MESSAGE_HEADER_LEN); } else { tmp = cpu_to_le32(CMD_TYPE_DATA); - priv->wlan_dev.dnld_sent = DNLD_DATA_SENT; + priv->dnld_sent = DNLD_DATA_SENT; memcpy(cardp->bulk_out_buffer, (u8 *) & tmp, MESSAGE_HEADER_LEN); } @@ -686,39 +732,41 @@ int libertas_sbi_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb } /* called with adapter->driver_lock held */ -int libertas_sbi_get_int_status(wlan_private * priv, u8 * ireg) +static int if_usb_get_int_status(wlan_private * priv, u8 * ireg) { - struct usb_card_rec *cardp = priv->wlan_dev.card; + struct usb_card_rec *cardp = priv->card; *ireg = cardp->usb_int_cause; cardp->usb_int_cause = 0; - lbs_dev_dbg(1, &cardp->udev->dev,"Int cause is 0x%X\n", *ireg); + lbs_deb_usbd(&cardp->udev->dev,"Int cause is 0x%X\n", *ireg); return 0; } -int libertas_sbi_read_event_cause(wlan_private * priv) +static int if_usb_read_event_cause(wlan_private * priv) { - struct usb_card_rec *cardp = priv->wlan_dev.card; + struct usb_card_rec *cardp = priv->card; priv->adapter->eventcause = cardp->usb_event_cause; /* Re-submit rx urb here to avoid event lost issue */ if_usb_submit_rx_urb(priv); return 0; } -int reset_device(wlan_private *priv) +static int if_usb_reset_device(wlan_private *priv) { int ret; + lbs_deb_enter(LBS_DEB_USB); ret = libertas_prepare_and_send_command(priv, cmd_802_11_reset, cmd_act_halt, 0, 0, NULL); msleep_interruptible(10); + lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret); return ret; } -int libertas_sbi_unregister_dev(wlan_private * priv) +static int if_usb_unregister_dev(wlan_private * priv) { int ret = 0; @@ -727,7 +775,7 @@ int libertas_sbi_unregister_dev(wlan_private * priv) * again. */ if (priv) - reset_device(priv); + if_usb_reset_device(priv); return ret; } @@ -738,42 +786,41 @@ int libertas_sbi_unregister_dev(wlan_private * priv) * @param priv pointer to wlan_private * @return 0 or -1 */ -int libertas_sbi_register_dev(wlan_private * priv) +static int if_usb_register_dev(wlan_private * priv) { + struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card; - struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card; - ENTER(); + lbs_deb_enter(LBS_DEB_USB); cardp->priv = priv; - cardp->eth_dev = priv->wlan_dev.netdev; + cardp->eth_dev = priv->dev; priv->hotplug_device = &(cardp->udev->dev); - SET_NETDEV_DEV(cardp->eth_dev, &(cardp->udev->dev)); - - lbs_dev_dbg(1, &cardp->udev->dev, "udev pointer is at %p\n", + lbs_deb_usbd(&cardp->udev->dev, "udev pointer is at %p\n", cardp->udev); - LEAVE(); + lbs_deb_leave(LBS_DEB_USB); return 0; } -int libertas_sbi_prog_firmware(wlan_private * priv) +static int if_usb_prog_firmware(wlan_private * priv) { - struct usb_card_rec *cardp = priv->wlan_dev.card; + struct usb_card_rec *cardp = priv->card; int i = 0; static int reset_count = 10; + int ret = 0; - ENTER(); + lbs_deb_enter(LBS_DEB_USB); cardp->rinfo.priv = priv; restart: if (if_usb_submit_rx_urb_fwload(priv) < 0) { - lbs_dev_dbg(1, &cardp->udev->dev, "URB submission is failed\n"); - LEAVE(); - return -1; + lbs_deb_usbd(&cardp->udev->dev, "URB submission is failed\n"); + ret = -1; + goto done; } cardp->bootcmdresp = 0; @@ -811,7 +858,7 @@ restart: if_prog_firmware(priv); do { - lbs_dev_dbg(1, &cardp->udev->dev,"Wlan sched timeout\n"); + lbs_deb_usbd(&cardp->udev->dev,"Wlan sched timeout\n"); i++; msleep_interruptible(100); if (priv->adapter->surpriseremoved || i >= 20) @@ -826,8 +873,8 @@ restart: } lbs_pr_info("FW download failure, time = %d ms\n", i * 100); - LEAVE(); - return -1; + ret = -1; + goto done; } if_usb_submit_rx_urb(priv); @@ -837,32 +884,10 @@ restart: priv->adapter->fw_ready = 1; - LEAVE(); - return 0; -} - -/** - * @brief Given a usb_card_rec return its wlan_private - * @param card pointer to a usb_card_rec - * @return pointer to wlan_private - */ -wlan_private *libertas_sbi_get_priv(void *card) -{ - struct usb_card_rec *cardp = card; - return cardp->priv; -} - -#ifdef ENABLE_PM -int libertas_sbi_suspend(wlan_private * priv) -{ - return 0; -} - -int libertas_sbi_resume(wlan_private * priv) -{ - return 0; +done: + lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret); + return ret; } -#endif #ifdef CONFIG_PM static int if_usb_suspend(struct usb_interface *intf, pm_message_t message) @@ -870,12 +895,13 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message) struct usb_card_rec *cardp = usb_get_intfdata(intf); wlan_private *priv = cardp->priv; - ENTER(); + lbs_deb_enter(LBS_DEB_USB); if (priv->adapter->psstate != PS_STATE_FULL_POWER) return -1; netif_device_detach(cardp->eth_dev); + netif_device_detach(priv->mesh_dev); /* Unlink tx & rx urb */ usb_kill_urb(cardp->tx_urb); @@ -883,23 +909,25 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message) cardp->rx_urb_recall = 1; - LEAVE(); + lbs_deb_leave(LBS_DEB_USB); return 0; } static int if_usb_resume(struct usb_interface *intf) { struct usb_card_rec *cardp = usb_get_intfdata(intf); + wlan_private *priv = cardp->priv; - ENTER(); + lbs_deb_enter(LBS_DEB_USB); cardp->rx_urb_recall = 0; if_usb_submit_rx_urb(cardp->priv); netif_device_attach(cardp->eth_dev); + netif_device_attach(priv->mesh_dev); - LEAVE(); + lbs_deb_leave(LBS_DEB_USB); return 0; } #else @@ -920,32 +948,40 @@ static struct usb_driver if_usb_driver = { .resume = if_usb_resume, }; -/** - * @brief This function registers driver. - * @param add pointer to add_card callback function - * @param remove pointer to remove card callback function - * @param arg pointer to call back function parameter - * @return dummy success variable - */ -int libertas_sbi_register(void) +static int if_usb_init_module(void) { - /* - * API registers the Marvell USB driver - * to the USB system - */ - usb_register(&if_usb_driver); + int ret = 0; - /* Return success to wlan layer */ - return 0; + lbs_deb_enter(LBS_DEB_MAIN); + + if (libertas_fw_name == NULL) { + libertas_fw_name = default_fw_name; + } + + ret = usb_register(&if_usb_driver); + + lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret); + return ret; } -/** - * @brief This function removes usb driver. - * @return N/A - */ -void libertas_sbi_unregister(void) +static void if_usb_exit_module(void) { + struct usb_card_rec *cardp, *cardp_temp; + + lbs_deb_enter(LBS_DEB_MAIN); + + list_for_each_entry_safe(cardp, cardp_temp, &usb_devices, list) + if_usb_reset_device((wlan_private *) cardp->priv); + /* API unregisters the driver from USB subsystem */ usb_deregister(&if_usb_driver); - return; + + lbs_deb_leave(LBS_DEB_MAIN); } + +module_init(if_usb_init_module); +module_exit(if_usb_exit_module); + +MODULE_DESCRIPTION("8388 USB WLAN Driver"); +MODULE_AUTHOR("Marvell International Ltd."); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h index 170dfe6809f..156bb485e1a 100644 --- a/drivers/net/wireless/libertas/if_usb.h +++ b/drivers/net/wireless/libertas/if_usb.h @@ -1,3 +1,8 @@ +#ifndef _LIBERTAS_IF_USB_H +#define _LIBERTAS_IF_USB_H + +#include <linux/list.h> + /** * This file contains definition for USB interface. */ @@ -7,11 +12,6 @@ #define IPFIELD_ALIGN_OFFSET 2 -#define USB8388_VID_1 0x1286 -#define USB8388_PID_1 0x2001 -#define USB8388_VID_2 0x05a3 -#define USB8388_PID_2 0x8388 - #define BOOT_CMD_FW_BY_USB 0x01 #define BOOT_CMD_FW_IN_EEPROM 0x02 #define BOOT_CMD_UPDATE_BOOT2 0x03 @@ -20,7 +20,7 @@ struct bootcmdstr { - u32 u32magicnumber; + __le32 u32magicnumber; u8 u8cmd_tag; u8 au8dumy[11]; }; @@ -30,7 +30,7 @@ struct bootcmdstr struct bootcmdrespStr { - u32 u32magicnumber; + __le32 u32magicnumber; u8 u8cmd_tag; u8 u8result; u8 au8dumy[2]; @@ -44,6 +44,7 @@ struct read_cb_info { /** USB card description structure*/ struct usb_card_rec { + struct list_head list; struct net_device *eth_dev; struct usb_device *udev; struct urb *rx_urb, *tx_urb; @@ -75,33 +76,34 @@ struct usb_card_rec { /** fwheader */ struct fwheader { - u32 dnldcmd; - u32 baseaddr; - u32 datalength; - u32 CRC; + __le32 dnldcmd; + __le32 baseaddr; + __le32 datalength; + __le32 CRC; }; #define FW_MAX_DATA_BLK_SIZE 600 /** FWData */ struct FWData { struct fwheader fwheader; - u32 seqnum; + __le32 seqnum; u8 data[FW_MAX_DATA_BLK_SIZE]; }; /** fwsyncheader */ struct fwsyncheader { - u32 cmd; - u32 seqnum; + __le32 cmd; + __le32 seqnum; }; #define FW_HAS_DATA_TO_RECV 0x00000001 #define FW_HAS_LAST_BLOCK 0x00000004 #define FW_DATA_XMIT_SIZE \ - sizeof(struct fwheader) + fwdata->fwheader.datalength + sizeof(u32) + sizeof(struct fwheader) + le32_to_cpu(fwdata->fwheader.datalength) + sizeof(u32) int usb_tx_block(wlan_private *priv, u8 *payload, u16 nb); void if_usb_free(struct usb_card_rec *cardp); int if_usb_issue_boot_command(wlan_private *priv, int ivalue); +#endif diff --git a/drivers/net/wireless/libertas/ioctl.c b/drivers/net/wireless/libertas/ioctl.c deleted file mode 100644 index a8f76c35899..00000000000 --- a/drivers/net/wireless/libertas/ioctl.c +++ /dev/null @@ -1,991 +0,0 @@ -/** - * This file contains ioctl functions - */ - -#include <linux/ctype.h> -#include <linux/delay.h> -#include <linux/if.h> -#include <linux/if_arp.h> -#include <linux/wireless.h> - -#include <net/iw_handler.h> -#include <net/ieee80211.h> - -#include "host.h" -#include "radiotap.h" -#include "decl.h" -#include "defs.h" -#include "dev.h" -#include "join.h" -#include "wext.h" - -#define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN + \ - IW_ESSID_MAX_SIZE + \ - IW_EV_UINT_LEN + IW_EV_FREQ_LEN + \ - IW_EV_QUAL_LEN + IW_ESSID_MAX_SIZE + \ - IW_EV_PARAM_LEN + 40) /* 40 for WPAIE */ - -#define WAIT_FOR_SCAN_RRESULT_MAX_TIME (10 * HZ) - -static int wlan_set_region(wlan_private * priv, u16 region_code) -{ - int i; - - for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) { - // use the region code to search for the index - if (region_code == libertas_region_code_to_index[i]) { - priv->adapter->regiontableindex = (u16) i; - priv->adapter->regioncode = region_code; - break; - } - } - - // if it's unidentified region code - if (i >= MRVDRV_MAX_REGION_CODE) { - lbs_pr_debug(1, "region Code not identified\n"); - LEAVE(); - return -1; - } - - if (libertas_set_regiontable(priv, priv->adapter->regioncode, 0)) { - LEAVE(); - return -EINVAL; - } - - return 0; -} - -static inline int hex2int(char c) -{ - if (c >= '0' && c <= '9') - return (c - '0'); - if (c >= 'a' && c <= 'f') - return (c - 'a' + 10); - if (c >= 'A' && c <= 'F') - return (c - 'A' + 10); - return -1; -} - -/* Convert a string representation of a MAC address ("xx:xx:xx:xx:xx:xx") - into binary format (6 bytes). - - This function expects that each byte is represented with 2 characters - (e.g., 11:2:11:11:11:11 is invalid) - - */ -static char *eth_str2addr(char *ethstr, u8 * addr) -{ - int i, val, val2; - char *pos = ethstr; - - /* get rid of initial blanks */ - while (*pos == ' ' || *pos == '\t') - ++pos; - - for (i = 0; i < 6; i++) { - val = hex2int(*pos++); - if (val < 0) - return NULL; - val2 = hex2int(*pos++); - if (val2 < 0) - return NULL; - addr[i] = (val * 16 + val2) & 0xff; - - if (i < 5 && *pos++ != ':') - return NULL; - } - return pos; -} - -/* this writes xx:xx:xx:xx:xx:xx into ethstr - (ethstr must have space for 18 chars) */ -static int eth_addr2str(u8 * addr, char *ethstr) -{ - int i; - char *pos = ethstr; - - for (i = 0; i < 6; i++) { - sprintf(pos, "%02x", addr[i] & 0xff); - pos += 2; - if (i < 5) - *pos++ = ':'; - } - return 17; -} - -/** - * @brief Add an entry to the BT table - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int wlan_bt_add_ioctl(wlan_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - char ethaddrs_str[18]; - char *pos; - u8 ethaddr[ETH_ALEN]; - - ENTER(); - if (copy_from_user(ethaddrs_str, wrq->u.data.pointer, - sizeof(ethaddrs_str))) - return -EFAULT; - - if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) { - lbs_pr_info("BT_ADD: Invalid MAC address\n"); - return -EINVAL; - } - - lbs_pr_debug(1, "BT: adding %s\n", ethaddrs_str); - LEAVE(); - return (libertas_prepare_and_send_command(priv, cmd_bt_access, - cmd_act_bt_access_add, - cmd_option_waitforrsp, 0, ethaddr)); -} - -/** - * @brief Delete an entry from the BT table - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int wlan_bt_del_ioctl(wlan_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - char ethaddrs_str[18]; - u8 ethaddr[ETH_ALEN]; - char *pos; - - ENTER(); - if (copy_from_user(ethaddrs_str, wrq->u.data.pointer, - sizeof(ethaddrs_str))) - return -EFAULT; - - if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) { - lbs_pr_info("Invalid MAC address\n"); - return -EINVAL; - } - - lbs_pr_debug(1, "BT: deleting %s\n", ethaddrs_str); - - return (libertas_prepare_and_send_command(priv, - cmd_bt_access, - cmd_act_bt_access_del, - cmd_option_waitforrsp, 0, ethaddr)); - LEAVE(); - return 0; -} - -/** - * @brief Reset all entries from the BT table - * @param priv A pointer to wlan_private structure - * @return 0 --success, otherwise fail - */ -static int wlan_bt_reset_ioctl(wlan_private * priv) -{ - ENTER(); - - lbs_pr_alert( "BT: resetting\n"); - - return (libertas_prepare_and_send_command(priv, - cmd_bt_access, - cmd_act_bt_access_reset, - cmd_option_waitforrsp, 0, NULL)); - - LEAVE(); - return 0; -} - -/** - * @brief List an entry from the BT table - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int wlan_bt_list_ioctl(wlan_private * priv, struct ifreq *req) -{ - int pos; - char *addr1; - struct iwreq *wrq = (struct iwreq *)req; - /* used to pass id and store the bt entry returned by the FW */ - union { - int id; - char addr1addr2[2 * ETH_ALEN]; - } param; - static char outstr[64]; - char *pbuf = outstr; - int ret; - - ENTER(); - - if (copy_from_user(outstr, wrq->u.data.pointer, sizeof(outstr))) { - lbs_pr_debug(1, "Copy from user failed\n"); - return -1; - } - param.id = simple_strtoul(outstr, NULL, 10); - pos = sprintf(pbuf, "%d: ", param.id); - pbuf += pos; - - ret = libertas_prepare_and_send_command(priv, cmd_bt_access, - cmd_act_bt_access_list, - cmd_option_waitforrsp, 0, - (char *)¶m); - - if (ret == 0) { - addr1 = param.addr1addr2; - - pos = sprintf(pbuf, "ignoring traffic from "); - pbuf += pos; - pos = eth_addr2str(addr1, pbuf); - pbuf += pos; - } else { - sprintf(pbuf, "(null)"); - pbuf += pos; - } - - wrq->u.data.length = strlen(outstr); - if (copy_to_user(wrq->u.data.pointer, (char *)outstr, - wrq->u.data.length)) { - lbs_pr_debug(1, "BT_LIST: Copy to user failed!\n"); - return -EFAULT; - } - - LEAVE(); - return 0; -} - -/** - * @brief Find the next parameter in an input string - * @param ptr A pointer to the input parameter string - * @return A pointer to the next parameter, or 0 if no parameters left. - */ -static char * next_param(char * ptr) -{ - if (!ptr) return NULL; - while (*ptr == ' ' || *ptr == '\t') ++ptr; - return (*ptr == '\0') ? NULL : ptr; -} - -/** - * @brief Add an entry to the FWT table - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int wlan_fwt_add_ioctl(wlan_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - char in_str[128]; - static struct cmd_ds_fwt_access fwt_access; - char *ptr; - - ENTER(); - if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str))) - return -EFAULT; - - if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) { - lbs_pr_alert( "FWT_ADD: Invalid MAC address 1\n"); - return -EINVAL; - } - - if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) { - lbs_pr_alert( "FWT_ADD: Invalid MAC address 2\n"); - return -EINVAL; - } - - if ((ptr = next_param(ptr))) - fwt_access.metric = - cpu_to_le32(simple_strtoul(ptr, &ptr, 10)); - else - fwt_access.metric = FWT_DEFAULT_METRIC; - - if ((ptr = next_param(ptr))) - fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10); - else - fwt_access.dir = FWT_DEFAULT_DIR; - - if ((ptr = next_param(ptr))) - fwt_access.ssn = - cpu_to_le32(simple_strtoul(ptr, &ptr, 10)); - else - fwt_access.ssn = FWT_DEFAULT_SSN; - - if ((ptr = next_param(ptr))) - fwt_access.dsn = - cpu_to_le32(simple_strtoul(ptr, &ptr, 10)); - else - fwt_access.dsn = FWT_DEFAULT_DSN; - - if ((ptr = next_param(ptr))) - fwt_access.hopcount = simple_strtoul(ptr, &ptr, 10); - else - fwt_access.hopcount = FWT_DEFAULT_HOPCOUNT; - - if ((ptr = next_param(ptr))) - fwt_access.ttl = simple_strtoul(ptr, &ptr, 10); - else - fwt_access.ttl = FWT_DEFAULT_TTL; - - if ((ptr = next_param(ptr))) - fwt_access.expiration = - cpu_to_le32(simple_strtoul(ptr, &ptr, 10)); - else - fwt_access.expiration = FWT_DEFAULT_EXPIRATION; - - if ((ptr = next_param(ptr))) - fwt_access.sleepmode = (u8)simple_strtoul(ptr, &ptr, 10); - else - fwt_access.sleepmode = FWT_DEFAULT_SLEEPMODE; - - if ((ptr = next_param(ptr))) - fwt_access.snr = - cpu_to_le32(simple_strtoul(ptr, &ptr, 10)); - else - fwt_access.snr = FWT_DEFAULT_SNR; - -#ifdef DEBUG - { - char ethaddr1_str[18], ethaddr2_str[18]; - eth_addr2str(fwt_access.da, ethaddr1_str); - eth_addr2str(fwt_access.ra, ethaddr2_str); - lbs_pr_debug(1, "FWT_ADD: adding (da:%s,%i,ra:%s)\n", ethaddr1_str, - fwt_access.dir, ethaddr2_str); - lbs_pr_debug(1, "FWT_ADD: ssn:%u dsn:%u met:%u hop:%u ttl:%u exp:%u slp:%u snr:%u\n", - fwt_access.ssn, fwt_access.dsn, fwt_access.metric, - fwt_access.hopcount, fwt_access.ttl, fwt_access.expiration, - fwt_access.sleepmode, fwt_access.snr); - } -#endif - - LEAVE(); - return (libertas_prepare_and_send_command(priv, cmd_fwt_access, - cmd_act_fwt_access_add, - cmd_option_waitforrsp, 0, - (void *)&fwt_access)); -} - -/** - * @brief Delete an entry from the FWT table - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int wlan_fwt_del_ioctl(wlan_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - char in_str[64]; - static struct cmd_ds_fwt_access fwt_access; - char *ptr; - - ENTER(); - if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str))) - return -EFAULT; - - if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) { - lbs_pr_alert( "FWT_DEL: Invalid MAC address 1\n"); - return -EINVAL; - } - - if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) { - lbs_pr_alert( "FWT_DEL: Invalid MAC address 2\n"); - return -EINVAL; - } - - if ((ptr = next_param(ptr))) - fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10); - else - fwt_access.dir = FWT_DEFAULT_DIR; - -#ifdef DEBUG - { - char ethaddr1_str[18], ethaddr2_str[18]; - lbs_pr_debug(1, "FWT_DEL: line is %s\n", in_str); - eth_addr2str(fwt_access.da, ethaddr1_str); - eth_addr2str(fwt_access.ra, ethaddr2_str); - lbs_pr_debug(1, "FWT_DEL: removing (da:%s,ra:%s,dir:%d)\n", ethaddr1_str, - ethaddr2_str, fwt_access.dir); - } -#endif - - LEAVE(); - return (libertas_prepare_and_send_command(priv, - cmd_fwt_access, - cmd_act_fwt_access_del, - cmd_option_waitforrsp, 0, - (void *)&fwt_access)); -} - - -/** - * @brief Print route parameters - * @param fwt_access struct cmd_ds_fwt_access with route info - * @param buf destination buffer for route info - */ -static void print_route(struct cmd_ds_fwt_access fwt_access, char *buf) -{ - buf += sprintf(buf, " "); - buf += eth_addr2str(fwt_access.da, buf); - buf += sprintf(buf, " "); - buf += eth_addr2str(fwt_access.ra, buf); - buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.metric)); - buf += sprintf(buf, " %u", fwt_access.dir); - buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.ssn)); - buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.dsn)); - buf += sprintf(buf, " %u", fwt_access.hopcount); - buf += sprintf(buf, " %u", fwt_access.ttl); - buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.expiration)); - buf += sprintf(buf, " %u", fwt_access.sleepmode); - buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.snr)); -} - -/** - * @brief Lookup an entry in the FWT table - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int wlan_fwt_lookup_ioctl(wlan_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - char in_str[64]; - char *ptr; - static struct cmd_ds_fwt_access fwt_access; - static char out_str[128]; - int ret; - - ENTER(); - if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str))) - return -EFAULT; - - if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) { - lbs_pr_alert( "FWT_LOOKUP: Invalid MAC address\n"); - return -EINVAL; - } - -#ifdef DEBUG - { - char ethaddr1_str[18]; - lbs_pr_debug(1, "FWT_LOOKUP: line is %s\n", in_str); - eth_addr2str(fwt_access.da, ethaddr1_str); - lbs_pr_debug(1, "FWT_LOOKUP: looking for (da:%s)\n", ethaddr1_str); - } -#endif - - ret = libertas_prepare_and_send_command(priv, - cmd_fwt_access, - cmd_act_fwt_access_lookup, - cmd_option_waitforrsp, 0, - (void *)&fwt_access); - - if (ret == 0) - print_route(fwt_access, out_str); - else - sprintf(out_str, "(null)"); - - wrq->u.data.length = strlen(out_str); - if (copy_to_user(wrq->u.data.pointer, (char *)out_str, - wrq->u.data.length)) { - lbs_pr_debug(1, "FWT_LOOKUP: Copy to user failed!\n"); - return -EFAULT; - } - - LEAVE(); - return 0; -} - -/** - * @brief Reset all entries from the FWT table - * @param priv A pointer to wlan_private structure - * @return 0 --success, otherwise fail - */ -static int wlan_fwt_reset_ioctl(wlan_private * priv) -{ - lbs_pr_debug(1, "FWT: resetting\n"); - - return (libertas_prepare_and_send_command(priv, - cmd_fwt_access, - cmd_act_fwt_access_reset, - cmd_option_waitforrsp, 0, NULL)); -} - -/** - * @brief List an entry from the FWT table - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int wlan_fwt_list_ioctl(wlan_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - char in_str[8]; - static struct cmd_ds_fwt_access fwt_access; - char *ptr = in_str; - static char out_str[128]; - char *pbuf = out_str; - int ret; - - ENTER(); - if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str))) - return -EFAULT; - - fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10)); - -#ifdef DEBUG - { - lbs_pr_debug(1, "FWT_LIST: line is %s\n", in_str); - lbs_pr_debug(1, "FWT_LIST: listing id:%i\n", le32_to_cpu(fwt_access.id)); - } -#endif - - ret = libertas_prepare_and_send_command(priv, cmd_fwt_access, - cmd_act_fwt_access_list, - cmd_option_waitforrsp, 0, (void *)&fwt_access); - - if (ret == 0) - print_route(fwt_access, pbuf); - else - pbuf += sprintf(pbuf, " (null)"); - - wrq->u.data.length = strlen(out_str); - if (copy_to_user(wrq->u.data.pointer, (char *)out_str, - wrq->u.data.length)) { - lbs_pr_debug(1, "FWT_LIST: Copy to user failed!\n"); - return -EFAULT; - } - - LEAVE(); - return 0; -} - -/** - * @brief List an entry from the FRT table - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int wlan_fwt_list_route_ioctl(wlan_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - char in_str[64]; - static struct cmd_ds_fwt_access fwt_access; - char *ptr = in_str; - static char out_str[128]; - char *pbuf = out_str; - int ret; - - ENTER(); - if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str))) - return -EFAULT; - - fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10)); - -#ifdef DEBUG - { - lbs_pr_debug(1, "FWT_LIST_ROUTE: line is %s\n", in_str); - lbs_pr_debug(1, "FWT_LIST_ROUTE: listing id:%i\n", le32_to_cpu(fwt_access.id)); - } -#endif - - ret = libertas_prepare_and_send_command(priv, cmd_fwt_access, - cmd_act_fwt_access_list_route, - cmd_option_waitforrsp, 0, (void *)&fwt_access); - - if (ret == 0) { - pbuf += sprintf(pbuf, " "); - pbuf += eth_addr2str(fwt_access.da, pbuf); - pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.metric)); - pbuf += sprintf(pbuf, " %u", fwt_access.dir); - /* note that the firmware returns the nid in the id field */ - pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.id)); - pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.ssn)); - pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.dsn)); - pbuf += sprintf(pbuf, " hop %u", fwt_access.hopcount); - pbuf += sprintf(pbuf, " ttl %u", fwt_access.ttl); - pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.expiration)); - } else - pbuf += sprintf(pbuf, " (null)"); - - wrq->u.data.length = strlen(out_str); - if (copy_to_user(wrq->u.data.pointer, (char *)out_str, - wrq->u.data.length)) { - lbs_pr_debug(1, "FWT_LIST_ROUTE: Copy to user failed!\n"); - return -EFAULT; - } - - LEAVE(); - return 0; -} - -/** - * @brief List an entry from the FNT table - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int wlan_fwt_list_neighbor_ioctl(wlan_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - char in_str[8]; - static struct cmd_ds_fwt_access fwt_access; - char *ptr = in_str; - static char out_str[128]; - char *pbuf = out_str; - int ret; - - ENTER(); - if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str))) - return -EFAULT; - - memset(&fwt_access, 0, sizeof(fwt_access)); - fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10)); - -#ifdef DEBUG - { - lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: line is %s\n", in_str); - lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: listing id:%i\n", le32_to_cpu(fwt_access.id)); - } -#endif - - ret = libertas_prepare_and_send_command(priv, cmd_fwt_access, - cmd_act_fwt_access_list_neighbor, - cmd_option_waitforrsp, 0, - (void *)&fwt_access); - - if (ret == 0) { - pbuf += sprintf(pbuf, " ra "); - pbuf += eth_addr2str(fwt_access.ra, pbuf); - pbuf += sprintf(pbuf, " slp %u", fwt_access.sleepmode); - pbuf += sprintf(pbuf, " snr %u", le32_to_cpu(fwt_access.snr)); - pbuf += sprintf(pbuf, " ref %u", le32_to_cpu(fwt_access.references)); - } else - pbuf += sprintf(pbuf, " (null)"); - - wrq->u.data.length = strlen(out_str); - if (copy_to_user(wrq->u.data.pointer, (char *)out_str, - wrq->u.data.length)) { - lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: Copy to user failed!\n"); - return -EFAULT; - } - - LEAVE(); - return 0; -} - -/** - * @brief Cleans up the route (FRT) and neighbor (FNT) tables - * (Garbage Collection) - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int wlan_fwt_cleanup_ioctl(wlan_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - static struct cmd_ds_fwt_access fwt_access; - int ret; - - ENTER(); - - lbs_pr_debug(1, "FWT: cleaning up\n"); - - memset(&fwt_access, 0, sizeof(fwt_access)); - - ret = libertas_prepare_and_send_command(priv, cmd_fwt_access, - cmd_act_fwt_access_cleanup, - cmd_option_waitforrsp, 0, - (void *)&fwt_access); - - if (ret == 0) - wrq->u.param.value = le32_to_cpu(fwt_access.references); - else - return -EFAULT; - - LEAVE(); - return 0; -} - -/** - * @brief Gets firmware internal time (debug purposes) - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int wlan_fwt_time_ioctl(wlan_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - static struct cmd_ds_fwt_access fwt_access; - int ret; - - ENTER(); - - lbs_pr_debug(1, "FWT: getting time\n"); - - memset(&fwt_access, 0, sizeof(fwt_access)); - - ret = libertas_prepare_and_send_command(priv, cmd_fwt_access, - cmd_act_fwt_access_time, - cmd_option_waitforrsp, 0, - (void *)&fwt_access); - - if (ret == 0) - wrq->u.param.value = le32_to_cpu(fwt_access.references); - else - return -EFAULT; - - LEAVE(); - return 0; -} - -/** - * @brief Gets mesh ttl from firmware - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return 0 --success, otherwise fail - */ -static int wlan_mesh_get_ttl_ioctl(wlan_private * priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *)req; - struct cmd_ds_mesh_access mesh_access; - int ret; - - ENTER(); - - memset(&mesh_access, 0, sizeof(mesh_access)); - - ret = libertas_prepare_and_send_command(priv, cmd_mesh_access, - cmd_act_mesh_get_ttl, - cmd_option_waitforrsp, 0, - (void *)&mesh_access); - - if (ret == 0) - wrq->u.param.value = le32_to_cpu(mesh_access.data[0]); - else - return -EFAULT; - - LEAVE(); - return 0; -} - -/** - * @brief Gets mesh ttl from firmware - * @param priv A pointer to wlan_private structure - * @param ttl New ttl value - * @return 0 --success, otherwise fail - */ -static int wlan_mesh_set_ttl_ioctl(wlan_private * priv, int ttl) -{ - struct cmd_ds_mesh_access mesh_access; - int ret; - - ENTER(); - - if( (ttl > 0xff) || (ttl < 0) ) - return -EINVAL; - - memset(&mesh_access, 0, sizeof(mesh_access)); - mesh_access.data[0] = ttl; - - ret = libertas_prepare_and_send_command(priv, cmd_mesh_access, - cmd_act_mesh_set_ttl, - cmd_option_waitforrsp, 0, - (void *)&mesh_access); - - if (ret != 0) - ret = -EFAULT; - - LEAVE(); - return ret; -} - -/** - * @brief ioctl function - entry point - * - * @param dev A pointer to net_device structure - * @param req A pointer to ifreq structure - * @param cmd command - * @return 0--success, otherwise fail - */ -int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd) -{ - int subcmd = 0; - int idata = 0; - int *pdata; - int ret = 0; - wlan_private *priv = dev->priv; - wlan_adapter *adapter = priv->adapter; - struct iwreq *wrq = (struct iwreq *)req; - - ENTER(); - - lbs_pr_debug(1, "libertas_do_ioctl: ioctl cmd = 0x%x\n", cmd); - switch (cmd) { - case WLAN_SETNONE_GETNONE: /* set WPA mode on/off ioctl #20 */ - switch (wrq->u.data.flags) { - case WLAN_SUBCMD_BT_RESET: /* bt_reset */ - wlan_bt_reset_ioctl(priv); - break; - case WLAN_SUBCMD_FWT_RESET: /* fwt_reset */ - wlan_fwt_reset_ioctl(priv); - break; - } /* End of switch */ - break; - - case WLAN_SETONEINT_GETNONE: - /* The first 4 bytes of req->ifr_data is sub-ioctl number - * after 4 bytes sits the payload. - */ - subcmd = wrq->u.data.flags; - if (!subcmd) - subcmd = (int)wrq->u.param.value; - - switch (subcmd) { - case WLANSETREGION: - idata = SUBCMD_DATA(wrq); - ret = wlan_set_region(priv, (u16) idata); - break; - case WLAN_SUBCMD_MESH_SET_TTL: - idata = SUBCMD_DATA(wrq); - ret = wlan_mesh_set_ttl_ioctl(priv, idata); - break; - - default: - ret = -EOPNOTSUPP; - break; - } - - break; - - case WLAN_SET128CHAR_GET128CHAR: - switch ((int)wrq->u.data.flags) { - case WLAN_SUBCMD_BT_ADD: - ret = wlan_bt_add_ioctl(priv, req); - break; - case WLAN_SUBCMD_BT_DEL: - ret = wlan_bt_del_ioctl(priv, req); - break; - case WLAN_SUBCMD_BT_LIST: - ret = wlan_bt_list_ioctl(priv, req); - break; - case WLAN_SUBCMD_FWT_ADD: - ret = wlan_fwt_add_ioctl(priv, req); - break; - case WLAN_SUBCMD_FWT_DEL: - ret = wlan_fwt_del_ioctl(priv, req); - break; - case WLAN_SUBCMD_FWT_LOOKUP: - ret = wlan_fwt_lookup_ioctl(priv, req); - break; - case WLAN_SUBCMD_FWT_LIST_NEIGHBOR: - ret = wlan_fwt_list_neighbor_ioctl(priv, req); - break; - case WLAN_SUBCMD_FWT_LIST: - ret = wlan_fwt_list_ioctl(priv, req); - break; - case WLAN_SUBCMD_FWT_LIST_ROUTE: - ret = wlan_fwt_list_route_ioctl(priv, req); - break; - } - break; - - case WLAN_SETNONE_GETONEINT: - switch (wrq->u.param.value) { - case WLANGETREGION: - pdata = (int *)wrq->u.name; - *pdata = (int)adapter->regioncode; - break; - case WLAN_SUBCMD_FWT_CLEANUP: /* fwt_cleanup */ - ret = wlan_fwt_cleanup_ioctl(priv, req); - break; - - case WLAN_SUBCMD_FWT_TIME: /* fwt_time */ - ret = wlan_fwt_time_ioctl(priv, req); - break; - - case WLAN_SUBCMD_MESH_GET_TTL: - ret = wlan_mesh_get_ttl_ioctl(priv, req); - break; - - default: - ret = -EOPNOTSUPP; - - } - - break; - - case WLAN_SET_GET_SIXTEEN_INT: - switch ((int)wrq->u.data.flags) { - case WLAN_LED_GPIO_CTRL: - { - int i; - int data[16]; - - struct cmd_ds_802_11_led_ctrl ctrl; - struct mrvlietypes_ledgpio *gpio = - (struct mrvlietypes_ledgpio *) ctrl.data; - - memset(&ctrl, 0, sizeof(ctrl)); - if (wrq->u.data.length > MAX_LEDS * 2) - return -ENOTSUPP; - if ((wrq->u.data.length % 2) != 0) - return -ENOTSUPP; - if (wrq->u.data.length == 0) { - ctrl.action = - cpu_to_le16 - (cmd_act_get); - } else { - if (copy_from_user - (data, wrq->u.data.pointer, - sizeof(int) * - wrq->u.data.length)) { - lbs_pr_debug(1, - "Copy from user failed\n"); - return -EFAULT; - } - - ctrl.action = - cpu_to_le16 - (cmd_act_set); - ctrl.numled = cpu_to_le16(0); - gpio->header.type = - cpu_to_le16(TLV_TYPE_LED_GPIO); - gpio->header.len = wrq->u.data.length; - for (i = 0; i < wrq->u.data.length; - i += 2) { - gpio->ledpin[i / 2].led = - data[i]; - gpio->ledpin[i / 2].pin = - data[i + 1]; - } - } - ret = - libertas_prepare_and_send_command(priv, - cmd_802_11_led_gpio_ctrl, - 0, - cmd_option_waitforrsp, - 0, (void *)&ctrl); - for (i = 0; i < gpio->header.len; i += 2) { - data[i] = gpio->ledpin[i / 2].led; - data[i + 1] = gpio->ledpin[i / 2].pin; - } - if (copy_to_user(wrq->u.data.pointer, data, - sizeof(int) * - gpio->header.len)) { - lbs_pr_debug(1, "Copy to user failed\n"); - return -EFAULT; - } - - wrq->u.data.length = gpio->header.len; - } - break; - } - break; - - default: - ret = -EINVAL; - break; - } - LEAVE(); - return ret; -} - - diff --git a/drivers/net/wireless/libertas/join.c b/drivers/net/wireless/libertas/join.c index d4926b83e14..78ac3064a0b 100644 --- a/drivers/net/wireless/libertas/join.c +++ b/drivers/net/wireless/libertas/join.c @@ -7,6 +7,7 @@ #include <linux/netdevice.h> #include <linux/if_arp.h> #include <linux/wireless.h> +#include <linux/etherdevice.h> #include <net/iw_handler.h> @@ -14,6 +15,7 @@ #include "decl.h" #include "join.h" #include "dev.h" +#include "assoc.h" #define AD_HOC_CAP_PRIVACY_ON 1 @@ -60,7 +62,7 @@ static int get_common_rates(wlan_adapter * adapter, u8 * rate1, lbs_dbg_hex("rate1 (AP) rates:", tmp, sizeof(tmp)); lbs_dbg_hex("rate2 (Card) rates:", rate2, rate2_size); lbs_dbg_hex("Common rates:", ptr, rate1_size); - lbs_pr_debug(1, "Tx datarate is set to 0x%X\n", adapter->datarate); + lbs_deb_join("Tx datarate is set to 0x%X\n", adapter->datarate); if (!adapter->is_datarate_auto) { while (*ptr) { @@ -104,24 +106,22 @@ int libertas_send_deauth(wlan_private * priv) * * @return 0-success, otherwise fail */ -int wlan_associate(wlan_private * priv, struct bss_descriptor * pbssdesc) +int wlan_associate(wlan_private * priv, struct assoc_request * assoc_req) { wlan_adapter *adapter = priv->adapter; int ret; - ENTER(); + lbs_deb_enter(LBS_DEB_JOIN); ret = libertas_prepare_and_send_command(priv, cmd_802_11_authenticate, 0, cmd_option_waitforrsp, - 0, pbssdesc->macaddress); + 0, assoc_req->bss.bssid); - if (ret) { - LEAVE(); - return ret; - } + if (ret) + goto done; /* set preamble to firmware */ - if (adapter->capinfo.shortpreamble && pbssdesc->cap.shortpreamble) + if (adapter->capinfo.shortpreamble && assoc_req->bss.cap.shortpreamble) adapter->preamble = cmd_type_short_preamble; else adapter->preamble = cmd_type_long_preamble; @@ -129,9 +129,10 @@ int wlan_associate(wlan_private * priv, struct bss_descriptor * pbssdesc) libertas_set_radio_control(priv); ret = libertas_prepare_and_send_command(priv, cmd_802_11_associate, - 0, cmd_option_waitforrsp, 0, pbssdesc); + 0, cmd_option_waitforrsp, 0, assoc_req); - LEAVE(); +done: + lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); return ret; } @@ -142,7 +143,7 @@ int wlan_associate(wlan_private * priv, struct bss_descriptor * pbssdesc) * @param adhocssid The ssid of the Adhoc Network * @return 0--success, -1--fail */ -int libertas_start_adhoc_network(wlan_private * priv, struct WLAN_802_11_SSID *adhocssid) +int libertas_start_adhoc_network(wlan_private * priv, struct assoc_request * assoc_req) { wlan_adapter *adapter = priv->adapter; int ret = 0; @@ -150,22 +151,20 @@ int libertas_start_adhoc_network(wlan_private * priv, struct WLAN_802_11_SSID *a adapter->adhoccreate = 1; if (!adapter->capinfo.shortpreamble) { - lbs_pr_debug(1, "AdhocStart: Long preamble\n"); + lbs_deb_join("AdhocStart: Long preamble\n"); adapter->preamble = cmd_type_long_preamble; } else { - lbs_pr_debug(1, "AdhocStart: Short preamble\n"); + lbs_deb_join("AdhocStart: Short preamble\n"); adapter->preamble = cmd_type_short_preamble; } libertas_set_radio_control(priv); - lbs_pr_debug(1, "Adhoc channel = %d\n", adapter->adhocchannel); - lbs_pr_debug(1, "curbssparams.channel = %d\n", - adapter->curbssparams.channel); - lbs_pr_debug(1, "curbssparams.band = %d\n", adapter->curbssparams.band); + lbs_deb_join("AdhocStart: channel = %d\n", assoc_req->channel); + lbs_deb_join("AdhocStart: band = %d\n", assoc_req->band); ret = libertas_prepare_and_send_command(priv, cmd_802_11_ad_hoc_start, - 0, cmd_option_waitforrsp, 0, adhocssid); + 0, cmd_option_waitforrsp, 0, assoc_req); return ret; } @@ -179,52 +178,53 @@ int libertas_start_adhoc_network(wlan_private * priv, struct WLAN_802_11_SSID *a * * @return 0--success, -1--fail */ -int libertas_join_adhoc_network(wlan_private * priv, struct bss_descriptor * pbssdesc) +int libertas_join_adhoc_network(wlan_private * priv, struct assoc_request * assoc_req) { wlan_adapter *adapter = priv->adapter; + struct bss_descriptor * bss = &assoc_req->bss; int ret = 0; - lbs_pr_debug(1, "libertas_join_adhoc_network: CurBss.ssid =%s\n", - adapter->curbssparams.ssid.ssid); - lbs_pr_debug(1, "libertas_join_adhoc_network: CurBss.ssid_len =%u\n", - adapter->curbssparams.ssid.ssidlength); - lbs_pr_debug(1, "libertas_join_adhoc_network: ssid =%s\n", pbssdesc->ssid.ssid); - lbs_pr_debug(1, "libertas_join_adhoc_network: ssid len =%u\n", - pbssdesc->ssid.ssidlength); + lbs_deb_join("%s: Current SSID '%s', ssid length %u\n", + __func__, + escape_essid(adapter->curbssparams.ssid, + adapter->curbssparams.ssid_len), + adapter->curbssparams.ssid_len); + lbs_deb_join("%s: requested ssid '%s', ssid length %u\n", + __func__, escape_essid(bss->ssid, bss->ssid_len), + bss->ssid_len); /* check if the requested SSID is already joined */ - if (adapter->curbssparams.ssid.ssidlength - && !libertas_SSID_cmp(&pbssdesc->ssid, &adapter->curbssparams.ssid) + if (adapter->curbssparams.ssid_len + && !libertas_ssid_cmp(adapter->curbssparams.ssid, + adapter->curbssparams.ssid_len, + bss->ssid, bss->ssid_len) && (adapter->mode == IW_MODE_ADHOC)) { - - lbs_pr_debug(1, + lbs_deb_join( "ADHOC_J_CMD: New ad-hoc SSID is the same as current, " "not attempting to re-join"); - return -1; } /*Use shortpreamble only when both creator and card supports short preamble */ - if (!pbssdesc->cap.shortpreamble || !adapter->capinfo.shortpreamble) { - lbs_pr_debug(1, "AdhocJoin: Long preamble\n"); + if (!bss->cap.shortpreamble || !adapter->capinfo.shortpreamble) { + lbs_deb_join("AdhocJoin: Long preamble\n"); adapter->preamble = cmd_type_long_preamble; } else { - lbs_pr_debug(1, "AdhocJoin: Short preamble\n"); + lbs_deb_join("AdhocJoin: Short preamble\n"); adapter->preamble = cmd_type_short_preamble; } libertas_set_radio_control(priv); - lbs_pr_debug(1, "curbssparams.channel = %d\n", - adapter->curbssparams.channel); - lbs_pr_debug(1, "curbssparams.band = %c\n", adapter->curbssparams.band); + lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel); + lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band); adapter->adhoccreate = 0; ret = libertas_prepare_and_send_command(priv, cmd_802_11_ad_hoc_join, 0, cmd_option_waitforrsp, - OID_802_11_SSID, pbssdesc); + OID_802_11_SSID, assoc_req); return ret; } @@ -265,6 +265,8 @@ int libertas_cmd_80211_authenticate(wlan_private * priv, int ret = -1; u8 *bssid = pdata_buf; + lbs_deb_enter(LBS_DEB_JOIN); + cmd->command = cpu_to_le16(cmd_802_11_authenticate); cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate) + S_DS_GEN); @@ -281,18 +283,19 @@ int libertas_cmd_80211_authenticate(wlan_private * priv, pauthenticate->authtype = 0x80; break; default: - lbs_pr_debug(1, "AUTH_CMD: invalid auth alg 0x%X\n", + lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n", adapter->secinfo.auth_mode); goto out; } memcpy(pauthenticate->macaddr, bssid, ETH_ALEN); - lbs_pr_debug(1, "AUTH_CMD: Bssid is : %x:%x:%x:%x:%x:%x\n", - bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); + lbs_deb_join("AUTH_CMD: BSSID is : " MAC_FMT " auth=0x%X\n", + MAC_ARG(bssid), pauthenticate->authtype); ret = 0; out: + lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); return ret; } @@ -302,22 +305,20 @@ int libertas_cmd_80211_deauthenticate(wlan_private * priv, wlan_adapter *adapter = priv->adapter; struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth; - ENTER(); + lbs_deb_enter(LBS_DEB_JOIN); cmd->command = cpu_to_le16(cmd_802_11_deauthenticate); - cmd->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) + + cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) + S_DS_GEN); /* set AP MAC address */ - memmove(dauth->macaddr, adapter->curbssparams.bssid, - ETH_ALEN); + memmove(dauth->macaddr, adapter->curbssparams.bssid, ETH_ALEN); /* Reason code 3 = Station is leaving */ #define REASON_CODE_STA_LEAVING 3 dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING); - LEAVE(); + lbs_deb_leave(LBS_DEB_JOIN); return 0; } @@ -327,20 +328,20 @@ int libertas_cmd_80211_associate(wlan_private * priv, wlan_adapter *adapter = priv->adapter; struct cmd_ds_802_11_associate *passo = &cmd->params.associate; int ret = 0; - struct bss_descriptor *pbssdesc; + struct assoc_request * assoc_req = pdata_buf; + struct bss_descriptor * bss = &assoc_req->bss; u8 *card_rates; u8 *pos; int card_rates_size; - u16 tmpcap; + u16 tmpcap, tmplen; struct mrvlietypes_ssidparamset *ssid; struct mrvlietypes_phyparamset *phy; struct mrvlietypes_ssparamset *ss; struct mrvlietypes_ratesparamset *rates; struct mrvlietypes_rsnparamset *rsn; - ENTER(); + lbs_deb_enter(LBS_DEB_JOIN); - pbssdesc = pdata_buf; pos = (u8 *) passo; if (!adapter) { @@ -350,15 +351,11 @@ int libertas_cmd_80211_associate(wlan_private * priv, cmd->command = cpu_to_le16(cmd_802_11_associate); - /* Save so we know which BSS Desc to use in the response handler */ - adapter->pattemptedbssdesc = pbssdesc; - - memcpy(passo->peerstaaddr, - pbssdesc->macaddress, sizeof(passo->peerstaaddr)); + memcpy(passo->peerstaaddr, bss->bssid, sizeof(passo->peerstaaddr)); pos += sizeof(passo->peerstaaddr); /* set the listen interval */ - passo->listeninterval = adapter->listeninterval; + passo->listeninterval = cpu_to_le16(adapter->listeninterval); pos += sizeof(passo->capinfo); pos += sizeof(passo->listeninterval); @@ -367,30 +364,30 @@ int libertas_cmd_80211_associate(wlan_private * priv, ssid = (struct mrvlietypes_ssidparamset *) pos; ssid->header.type = cpu_to_le16(TLV_TYPE_SSID); - ssid->header.len = pbssdesc->ssid.ssidlength; - memcpy(ssid->ssid, pbssdesc->ssid.ssid, ssid->header.len); - pos += sizeof(ssid->header) + ssid->header.len; - ssid->header.len = cpu_to_le16(ssid->header.len); + tmplen = bss->ssid_len; + ssid->header.len = cpu_to_le16(tmplen); + memcpy(ssid->ssid, bss->ssid, tmplen); + pos += sizeof(ssid->header) + tmplen; phy = (struct mrvlietypes_phyparamset *) pos; phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS); - phy->header.len = sizeof(phy->fh_ds.dsparamset); + tmplen = sizeof(phy->fh_ds.dsparamset); + phy->header.len = cpu_to_le16(tmplen); memcpy(&phy->fh_ds.dsparamset, - &pbssdesc->phyparamset.dsparamset.currentchan, - sizeof(phy->fh_ds.dsparamset)); - pos += sizeof(phy->header) + phy->header.len; - phy->header.len = cpu_to_le16(phy->header.len); + &bss->phyparamset.dsparamset.currentchan, + tmplen); + pos += sizeof(phy->header) + tmplen; ss = (struct mrvlietypes_ssparamset *) pos; ss->header.type = cpu_to_le16(TLV_TYPE_CF); - ss->header.len = sizeof(ss->cf_ibss.cfparamset); - pos += sizeof(ss->header) + ss->header.len; - ss->header.len = cpu_to_le16(ss->header.len); + tmplen = sizeof(ss->cf_ibss.cfparamset); + ss->header.len = cpu_to_le16(tmplen); + pos += sizeof(ss->header) + tmplen; rates = (struct mrvlietypes_ratesparamset *) pos; rates->header.type = cpu_to_le16(TLV_TYPE_RATES); - memcpy(&rates->rates, &pbssdesc->libertas_supported_rates, WLAN_SUPPORTED_RATES); + memcpy(&rates->rates, &bss->libertas_supported_rates, WLAN_SUPPORTED_RATES); card_rates = libertas_supported_rates; card_rates_size = sizeof(libertas_supported_rates); @@ -401,41 +398,42 @@ int libertas_cmd_80211_associate(wlan_private * priv, goto done; } - rates->header.len = min_t(size_t, strlen(rates->rates), WLAN_SUPPORTED_RATES); - adapter->curbssparams.numofrates = rates->header.len; + tmplen = min_t(size_t, strlen(rates->rates), WLAN_SUPPORTED_RATES); + adapter->curbssparams.numofrates = tmplen; - pos += sizeof(rates->header) + rates->header.len; - rates->header.len = cpu_to_le16(rates->header.len); + pos += sizeof(rates->header) + tmplen; + rates->header.len = cpu_to_le16(tmplen); - if (adapter->secinfo.WPAenabled || adapter->secinfo.WPA2enabled) { + if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) { rsn = (struct mrvlietypes_rsnparamset *) pos; - rsn->header.type = (u16) adapter->wpa_ie[0]; /* WPA_IE or WPA2_IE */ - rsn->header.type = cpu_to_le16(rsn->header.type); - rsn->header.len = (u16) adapter->wpa_ie[1]; - memcpy(rsn->rsnie, &adapter->wpa_ie[2], rsn->header.len); + /* WPA_IE or WPA2_IE */ + rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]); + tmplen = (u16) assoc_req->wpa_ie[1]; + rsn->header.len = cpu_to_le16(tmplen); + memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen); lbs_dbg_hex("ASSOC_CMD: RSN IE", (u8 *) rsn, - sizeof(rsn->header) + rsn->header.len); - pos += sizeof(rsn->header) + rsn->header.len; - rsn->header.len = cpu_to_le16(rsn->header.len); + sizeof(rsn->header) + tmplen); + pos += sizeof(rsn->header) + tmplen; } /* update curbssparams */ - adapter->curbssparams.channel = - (pbssdesc->phyparamset.dsparamset.currentchan); + adapter->curbssparams.channel = bss->phyparamset.dsparamset.currentchan; /* Copy the infra. association rates into Current BSS state structure */ memcpy(&adapter->curbssparams.datarates, &rates->rates, - min_t(size_t, sizeof(adapter->curbssparams.datarates), rates->header.len)); + min_t(size_t, sizeof(adapter->curbssparams.datarates), + cpu_to_le16(rates->header.len))); - lbs_pr_debug(1, "ASSOC_CMD: rates->header.len = %d\n", rates->header.len); + lbs_deb_join("ASSOC_CMD: rates->header.len = %d\n", + cpu_to_le16(rates->header.len)); /* set IBSS field */ - if (pbssdesc->mode == IW_MODE_INFRA) { + if (bss->mode == IW_MODE_INFRA) { #define CAPINFO_ESS_MODE 1 passo->capinfo.ess = CAPINFO_ESS_MODE; } - if (libertas_parse_dnld_countryinfo_11d(priv)) { + if (libertas_parse_dnld_countryinfo_11d(priv, bss)) { ret = -1; goto done; } @@ -443,31 +441,28 @@ int libertas_cmd_80211_associate(wlan_private * priv, cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN); /* set the capability info at last */ - memcpy(&tmpcap, &pbssdesc->cap, sizeof(passo->capinfo)); + memcpy(&tmpcap, &bss->cap, sizeof(passo->capinfo)); tmpcap &= CAPINFO_MASK; - lbs_pr_debug(1, "ASSOC_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n", - tmpcap, CAPINFO_MASK); - tmpcap = cpu_to_le16(tmpcap); + lbs_deb_join("ASSOC_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n", + tmpcap, CAPINFO_MASK); memcpy(&passo->capinfo, &tmpcap, sizeof(passo->capinfo)); - done: - LEAVE(); +done: + lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); return ret; } int libertas_cmd_80211_ad_hoc_start(wlan_private * priv, - struct cmd_ds_command *cmd, void *pssid) + struct cmd_ds_command *cmd, void *pdata_buf) { wlan_adapter *adapter = priv->adapter; struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads; int ret = 0; int cmdappendsize = 0; int i; - u16 tmpcap; - struct bss_descriptor *pbssdesc; - struct WLAN_802_11_SSID *ssid = pssid; + struct assoc_request * assoc_req = pdata_buf; - ENTER(); + lbs_deb_enter(LBS_DEB_JOIN); if (!adapter) { ret = -1; @@ -476,9 +471,6 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv, cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_start); - pbssdesc = &adapter->curbssparams.bssdescriptor; - adapter->pattemptedbssdesc = pbssdesc; - /* * Fill in the parameters for 2 data structures: * 1. cmd_ds_802_11_ad_hoc_start command @@ -492,20 +484,16 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv, */ memset(adhs->SSID, 0, IW_ESSID_MAX_SIZE); + memcpy(adhs->SSID, assoc_req->ssid, assoc_req->ssid_len); - memcpy(adhs->SSID, ssid->ssid, ssid->ssidlength); - - lbs_pr_debug(1, "ADHOC_S_CMD: SSID = %s\n", adhs->SSID); - - memset(pbssdesc->ssid.ssid, 0, IW_ESSID_MAX_SIZE); - memcpy(pbssdesc->ssid.ssid, ssid->ssid, ssid->ssidlength); - - pbssdesc->ssid.ssidlength = ssid->ssidlength; + lbs_deb_join("ADHOC_S_CMD: SSID '%s', ssid length %u\n", + escape_essid(assoc_req->ssid, assoc_req->ssid_len), + assoc_req->ssid_len); /* set the BSS type */ adhs->bsstype = cmd_bss_type_ibss; - pbssdesc->mode = IW_MODE_ADHOC; - adhs->beaconperiod = adapter->beaconperiod; + adapter->mode = IW_MODE_ADHOC; + adhs->beaconperiod = cpu_to_le16(adapter->beaconperiod); /* set Physical param set */ #define DS_PARA_IE_ID 3 @@ -514,18 +502,12 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv, adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID; adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN; - WARN_ON(!adapter->adhocchannel); + WARN_ON(!assoc_req->channel); - lbs_pr_debug(1, "ADHOC_S_CMD: Creating ADHOC on channel %d\n", - adapter->adhocchannel); + lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n", + assoc_req->channel); - adapter->curbssparams.channel = adapter->adhocchannel; - - pbssdesc->channel = adapter->adhocchannel; - adhs->phyparamset.dsparamset.currentchan = adapter->adhocchannel; - - memcpy(&pbssdesc->phyparamset, - &adhs->phyparamset, sizeof(union ieeetypes_phyparamset)); + adhs->phyparamset.dsparamset.currentchan = assoc_req->channel; /* set IBSS param set */ #define IBSS_PARA_IE_ID 6 @@ -533,26 +515,21 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv, adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID; adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN; - adhs->ssparamset.ibssparamset.atimwindow = adapter->atimwindow; - memcpy(&pbssdesc->ssparamset, - &adhs->ssparamset, sizeof(union IEEEtypes_ssparamset)); + adhs->ssparamset.ibssparamset.atimwindow = cpu_to_le16(adapter->atimwindow); /* set capability info */ adhs->cap.ess = 0; adhs->cap.ibss = 1; - pbssdesc->cap.ibss = 1; /* probedelay */ adhs->probedelay = cpu_to_le16(cmd_scan_probe_delay_time); /* set up privacy in adapter->scantable[i] */ - if (adapter->secinfo.wep_enabled) { - lbs_pr_debug(1, "ADHOC_S_CMD: WEP enabled, setting privacy on\n"); - pbssdesc->privacy = wlan802_11privfilter8021xWEP; + if (assoc_req->secinfo.wep_enabled) { + lbs_deb_join("ADHOC_S_CMD: WEP enabled, setting privacy on\n"); adhs->cap.privacy = AD_HOC_CAP_PRIVACY_ON; } else { - lbs_pr_debug(1, "ADHOC_S_CMD: WEP disabled, setting privacy off\n"); - pbssdesc->privacy = wlan802_11privfilteracceptall; + lbs_deb_join("ADHOC_S_CMD: WEP disabled, setting privacy off\n"); } memset(adhs->datarate, 0, sizeof(adhs->datarate)); @@ -574,29 +551,24 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv, memcpy(&adapter->curbssparams.datarates, &adhs->datarate, adapter->curbssparams.numofrates); - lbs_pr_debug(1, "ADHOC_S_CMD: rates=%02x %02x %02x %02x \n", + lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n", adhs->datarate[0], adhs->datarate[1], adhs->datarate[2], adhs->datarate[3]); - lbs_pr_debug(1, "ADHOC_S_CMD: AD HOC Start command is ready\n"); + lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n"); if (libertas_create_dnld_countryinfo_11d(priv)) { - lbs_pr_debug(1, "ADHOC_S_CMD: dnld_countryinfo_11d failed\n"); + lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n"); ret = -1; goto done; } - cmd->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start) - + S_DS_GEN + cmdappendsize); - - memcpy(&tmpcap, &adhs->cap, sizeof(u16)); - tmpcap = cpu_to_le16(tmpcap); - memcpy(&adhs->cap, &tmpcap, sizeof(u16)); + cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start) + + S_DS_GEN + cmdappendsize); ret = 0; done: - LEAVE(); + lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); return ret; } @@ -614,7 +586,8 @@ int libertas_cmd_80211_ad_hoc_join(wlan_private * priv, { wlan_adapter *adapter = priv->adapter; struct cmd_ds_802_11_ad_hoc_join *padhocjoin = &cmd->params.adj; - struct bss_descriptor *pbssdesc = pdata_buf; + struct assoc_request * assoc_req = pdata_buf; + struct bss_descriptor *bss = &assoc_req->bss; int cmdappendsize = 0; int ret = 0; u8 *card_rates; @@ -622,70 +595,59 @@ int libertas_cmd_80211_ad_hoc_join(wlan_private * priv, u16 tmpcap; int i; - ENTER(); - - adapter->pattemptedbssdesc = pbssdesc; + lbs_deb_enter(LBS_DEB_JOIN); cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_join); padhocjoin->bssdescriptor.bsstype = cmd_bss_type_ibss; - padhocjoin->bssdescriptor.beaconperiod = pbssdesc->beaconperiod; - - memcpy(&padhocjoin->bssdescriptor.BSSID, - &pbssdesc->macaddress, ETH_ALEN); + padhocjoin->bssdescriptor.beaconperiod = cpu_to_le16(bss->beaconperiod); - memcpy(&padhocjoin->bssdescriptor.SSID, - &pbssdesc->ssid.ssid, pbssdesc->ssid.ssidlength); + memcpy(&padhocjoin->bssdescriptor.BSSID, &bss->bssid, ETH_ALEN); + memcpy(&padhocjoin->bssdescriptor.SSID, &bss->ssid, bss->ssid_len); memcpy(&padhocjoin->bssdescriptor.phyparamset, - &pbssdesc->phyparamset, sizeof(union ieeetypes_phyparamset)); + &bss->phyparamset, sizeof(union ieeetypes_phyparamset)); memcpy(&padhocjoin->bssdescriptor.ssparamset, - &pbssdesc->ssparamset, sizeof(union IEEEtypes_ssparamset)); + &bss->ssparamset, sizeof(union IEEEtypes_ssparamset)); - memcpy(&tmpcap, &pbssdesc->cap, sizeof(struct ieeetypes_capinfo)); + memcpy(&tmpcap, &bss->cap, sizeof(struct ieeetypes_capinfo)); tmpcap &= CAPINFO_MASK; - lbs_pr_debug(1, "ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n", + lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n", tmpcap, CAPINFO_MASK); memcpy(&padhocjoin->bssdescriptor.cap, &tmpcap, sizeof(struct ieeetypes_capinfo)); /* information on BSSID descriptor passed to FW */ - lbs_pr_debug(1, - "ADHOC_J_CMD: BSSID = %2x-%2x-%2x-%2x-%2x-%2x, SSID = %s\n", - padhocjoin->bssdescriptor.BSSID[0], - padhocjoin->bssdescriptor.BSSID[1], - padhocjoin->bssdescriptor.BSSID[2], - padhocjoin->bssdescriptor.BSSID[3], - padhocjoin->bssdescriptor.BSSID[4], - padhocjoin->bssdescriptor.BSSID[5], + lbs_deb_join( + "ADHOC_J_CMD: BSSID = " MAC_FMT ", SSID = '%s'\n", + MAC_ARG(padhocjoin->bssdescriptor.BSSID), padhocjoin->bssdescriptor.SSID); /* failtimeout */ padhocjoin->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT); /* probedelay */ - padhocjoin->probedelay = - cpu_to_le16(cmd_scan_probe_delay_time); + padhocjoin->probedelay = cpu_to_le16(cmd_scan_probe_delay_time); /* Copy Data rates from the rates recorded in scan response */ memset(padhocjoin->bssdescriptor.datarates, 0, sizeof(padhocjoin->bssdescriptor.datarates)); - memcpy(padhocjoin->bssdescriptor.datarates, pbssdesc->datarates, + memcpy(padhocjoin->bssdescriptor.datarates, bss->datarates, min(sizeof(padhocjoin->bssdescriptor.datarates), - sizeof(pbssdesc->datarates))); + sizeof(bss->datarates))); card_rates = libertas_supported_rates; card_rates_size = sizeof(libertas_supported_rates); - adapter->curbssparams.channel = pbssdesc->channel; + adapter->curbssparams.channel = bss->channel; if (get_common_rates(adapter, padhocjoin->bssdescriptor.datarates, sizeof(padhocjoin->bssdescriptor.datarates), card_rates, card_rates_size)) { - lbs_pr_debug(1, "ADHOC_J_CMD: get_common_rates returns error.\n"); + lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n"); ret = -1; goto done; } @@ -704,17 +666,17 @@ int libertas_cmd_80211_ad_hoc_join(wlan_private * priv, adapter->curbssparams.numofrates); padhocjoin->bssdescriptor.ssparamset.ibssparamset.atimwindow = - cpu_to_le16(pbssdesc->atimwindow); + cpu_to_le16(bss->atimwindow); - if (adapter->secinfo.wep_enabled) { + if (assoc_req->secinfo.wep_enabled) { padhocjoin->bssdescriptor.cap.privacy = AD_HOC_CAP_PRIVACY_ON; } if (adapter->psmode == wlan802_11powermodemax_psp) { /* wake up first */ - enum WLAN_802_11_POWER_MODE Localpsmode; + __le32 Localpsmode; - Localpsmode = wlan802_11powermodecam; + Localpsmode = cpu_to_le32(wlan802_11powermodecam); ret = libertas_prepare_and_send_command(priv, cmd_802_11_ps_mode, cmd_act_set, @@ -726,24 +688,16 @@ int libertas_cmd_80211_ad_hoc_join(wlan_private * priv, } } - if (libertas_parse_dnld_countryinfo_11d(priv)) { + if (libertas_parse_dnld_countryinfo_11d(priv, bss)) { ret = -1; goto done; } - cmd->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join) - + S_DS_GEN + cmdappendsize); - - memcpy(&tmpcap, &padhocjoin->bssdescriptor.cap, - sizeof(struct ieeetypes_capinfo)); - tmpcap = cpu_to_le16(tmpcap); - - memcpy(&padhocjoin->bssdescriptor.cap, - &tmpcap, sizeof(struct ieeetypes_capinfo)); + cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join) + + S_DS_GEN + cmdappendsize); - done: - LEAVE(); +done: + lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); return ret; } @@ -754,19 +708,24 @@ int libertas_ret_80211_associate(wlan_private * priv, int ret = 0; union iwreq_data wrqu; struct ieeetypes_assocrsp *passocrsp; - struct bss_descriptor *pbssdesc; + struct bss_descriptor * bss; - ENTER(); + lbs_deb_enter(LBS_DEB_JOIN); - passocrsp = (struct ieeetypes_assocrsp *) & resp->params; + if (!adapter->in_progress_assoc_req) { + lbs_deb_join("ASSOC_RESP: no in-progress association request\n"); + ret = -1; + goto done; + } + bss = &adapter->in_progress_assoc_req->bss; - if (passocrsp->statuscode) { + passocrsp = (struct ieeetypes_assocrsp *) & resp->params; + if (le16_to_cpu(passocrsp->statuscode)) { libertas_mac_event_disconnected(priv); - lbs_pr_debug(1, - "ASSOC_RESP: Association failed, status code = %d\n", - passocrsp->statuscode); + lbs_deb_join("ASSOC_RESP: Association failed, status code = %d\n", + le16_to_cpu(passocrsp->statuscode)); ret = -1; goto done; @@ -778,24 +737,15 @@ int libertas_ret_80211_associate(wlan_private * priv, /* Send a Media Connected event, according to the Spec */ adapter->connect_status = libertas_connected; - /* Set the attempted BSSID Index to current */ - pbssdesc = adapter->pattemptedbssdesc; - - lbs_pr_debug(1, "ASSOC_RESP: %s\n", pbssdesc->ssid.ssid); + lbs_deb_join("ASSOC_RESP: assocated to '%s'\n", + escape_essid(bss->ssid, bss->ssid_len)); - /* Set the new SSID to current SSID */ - memcpy(&adapter->curbssparams.ssid, - &pbssdesc->ssid, sizeof(struct WLAN_802_11_SSID)); - - /* Set the new BSSID (AP's MAC address) to current BSSID */ - memcpy(adapter->curbssparams.bssid, - pbssdesc->macaddress, ETH_ALEN); - - /* Make a copy of current BSSID descriptor */ - memcpy(&adapter->curbssparams.bssdescriptor, - pbssdesc, sizeof(struct bss_descriptor)); + /* Update current SSID and BSSID */ + memcpy(&adapter->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); + adapter->curbssparams.ssid_len = bss->ssid_len; + memcpy(adapter->curbssparams.bssid, bss->bssid, ETH_ALEN); - lbs_pr_debug(1, "ASSOC_RESP: currentpacketfilter is %x\n", + lbs_deb_join("ASSOC_RESP: currentpacketfilter is %x\n", adapter->currentpacketfilter); adapter->SNR[TYPE_RXPD][TYPE_AVG] = 0; @@ -806,28 +756,31 @@ int libertas_ret_80211_associate(wlan_private * priv, adapter->nextSNRNF = 0; adapter->numSNRNF = 0; - netif_carrier_on(priv->wlan_dev.netdev); - netif_wake_queue(priv->wlan_dev.netdev); + netif_carrier_on(priv->dev); + netif_wake_queue(priv->dev); - lbs_pr_debug(1, "ASSOC_RESP: Associated \n"); + netif_carrier_on(priv->mesh_dev); + netif_wake_queue(priv->mesh_dev); + + lbs_deb_join("ASSOC_RESP: Associated \n"); memcpy(wrqu.ap_addr.sa_data, adapter->curbssparams.bssid, ETH_ALEN); wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL); + wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); - done: - LEAVE(); +done: + lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); return ret; } int libertas_ret_80211_disassociate(wlan_private * priv, struct cmd_ds_command *resp) { - ENTER(); + lbs_deb_enter(LBS_DEB_JOIN); libertas_mac_event_disconnected(priv); - LEAVE(); + lbs_deb_leave(LBS_DEB_JOIN); return 0; } @@ -840,90 +793,85 @@ int libertas_ret_80211_ad_hoc_start(wlan_private * priv, u16 result = le16_to_cpu(resp->result); struct cmd_ds_802_11_ad_hoc_result *padhocresult; union iwreq_data wrqu; - struct bss_descriptor *pbssdesc; + struct bss_descriptor *bss; - ENTER(); + lbs_deb_enter(LBS_DEB_JOIN); padhocresult = &resp->params.result; - lbs_pr_debug(1, "ADHOC_S_RESP: size = %d\n", le16_to_cpu(resp->size)); - lbs_pr_debug(1, "ADHOC_S_RESP: command = %x\n", command); - lbs_pr_debug(1, "ADHOC_S_RESP: result = %x\n", result); + lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp->size)); + lbs_deb_join("ADHOC_RESP: command = %x\n", command); + lbs_deb_join("ADHOC_RESP: result = %x\n", result); - pbssdesc = adapter->pattemptedbssdesc; + if (!adapter->in_progress_assoc_req) { + lbs_deb_join("ADHOC_RESP: no in-progress association request\n"); + ret = -1; + goto done; + } + bss = &adapter->in_progress_assoc_req->bss; /* * Join result code 0 --> SUCCESS */ if (result) { - lbs_pr_debug(1, "ADHOC_RESP failed\n"); + lbs_deb_join("ADHOC_RESP: failed\n"); if (adapter->connect_status == libertas_connected) { libertas_mac_event_disconnected(priv); } - - memset(&adapter->curbssparams.bssdescriptor, - 0x00, sizeof(adapter->curbssparams.bssdescriptor)); - - LEAVE(); - return -1; + ret = -1; + goto done; } /* * Now the join cmd should be successful * If BSSID has changed use SSID to compare instead of BSSID */ - lbs_pr_debug(1, "ADHOC_J_RESP %s\n", pbssdesc->ssid.ssid); + lbs_deb_join("ADHOC_RESP: associated to '%s'\n", + escape_essid(bss->ssid, bss->ssid_len)); /* Send a Media Connected event, according to the Spec */ adapter->connect_status = libertas_connected; if (command == cmd_ret_802_11_ad_hoc_start) { /* Update the created network descriptor with the new BSSID */ - memcpy(pbssdesc->macaddress, - padhocresult->BSSID, ETH_ALEN); - } else { - - /* Make a copy of current BSSID descriptor, only needed for join since - * the current descriptor is already being used for adhoc start - */ - memmove(&adapter->curbssparams.bssdescriptor, - pbssdesc, sizeof(struct bss_descriptor)); + memcpy(bss->bssid, padhocresult->BSSID, ETH_ALEN); } /* Set the BSSID from the joined/started descriptor */ - memcpy(&adapter->curbssparams.bssid, - pbssdesc->macaddress, ETH_ALEN); + memcpy(&adapter->curbssparams.bssid, bss->bssid, ETH_ALEN); /* Set the new SSID to current SSID */ - memcpy(&adapter->curbssparams.ssid, - &pbssdesc->ssid, sizeof(struct WLAN_802_11_SSID)); + memcpy(&adapter->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); + adapter->curbssparams.ssid_len = bss->ssid_len; - netif_carrier_on(priv->wlan_dev.netdev); - netif_wake_queue(priv->wlan_dev.netdev); + netif_carrier_on(priv->dev); + netif_wake_queue(priv->dev); + + netif_carrier_on(priv->mesh_dev); + netif_wake_queue(priv->mesh_dev); memset(&wrqu, 0, sizeof(wrqu)); memcpy(wrqu.ap_addr.sa_data, adapter->curbssparams.bssid, ETH_ALEN); wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL); + wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); - lbs_pr_debug(1, "ADHOC_RESP: - Joined/Started Ad Hoc\n"); - lbs_pr_debug(1, "ADHOC_RESP: channel = %d\n", adapter->adhocchannel); - lbs_pr_debug(1, "ADHOC_RESP: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n", - padhocresult->BSSID[0], padhocresult->BSSID[1], - padhocresult->BSSID[2], padhocresult->BSSID[3], - padhocresult->BSSID[4], padhocresult->BSSID[5]); + lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n"); + lbs_deb_join("ADHOC_RESP: channel = %d\n", adapter->curbssparams.channel); + lbs_deb_join("ADHOC_RESP: BSSID = " MAC_FMT "\n", + MAC_ARG(padhocresult->BSSID)); - LEAVE(); +done: + lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); return ret; } int libertas_ret_80211_ad_hoc_stop(wlan_private * priv, struct cmd_ds_command *resp) { - ENTER(); + lbs_deb_enter(LBS_DEB_JOIN); libertas_mac_event_disconnected(priv); - LEAVE(); + lbs_deb_leave(LBS_DEB_JOIN); return 0; } diff --git a/drivers/net/wireless/libertas/join.h b/drivers/net/wireless/libertas/join.h index 115f5a8ba34..d522630ff8c 100644 --- a/drivers/net/wireless/libertas/join.h +++ b/drivers/net/wireless/libertas/join.h @@ -9,6 +9,7 @@ #define _WLAN_JOIN_H #include "defs.h" +#include "dev.h" struct cmd_ds_command; extern int libertas_cmd_80211_authenticate(wlan_private * priv, @@ -21,7 +22,7 @@ extern int libertas_cmd_80211_ad_hoc_stop(wlan_private * priv, struct cmd_ds_command *cmd); extern int libertas_cmd_80211_ad_hoc_start(wlan_private * priv, struct cmd_ds_command *cmd, - void *pssid); + void *pdata_buf); extern int libertas_cmd_80211_deauthenticate(wlan_private * priv, struct cmd_ds_command *cmd); extern int libertas_cmd_80211_associate(wlan_private * priv, @@ -39,12 +40,10 @@ extern int libertas_ret_80211_associate(wlan_private * priv, extern int libertas_reassociation_thread(void *data); -struct WLAN_802_11_SSID; -struct bss_descriptor; - extern int libertas_start_adhoc_network(wlan_private * priv, - struct WLAN_802_11_SSID *adhocssid); -extern int libertas_join_adhoc_network(wlan_private * priv, struct bss_descriptor *pbssdesc); + struct assoc_request * assoc_req); +extern int libertas_join_adhoc_network(wlan_private * priv, + struct assoc_request * assoc_req); extern int libertas_stop_adhoc_network(wlan_private * priv); extern int libertas_send_deauthentication(wlan_private * priv); @@ -52,6 +51,6 @@ extern int libertas_send_deauth(wlan_private * priv); extern int libertas_do_adhocstop_ioctl(wlan_private * priv); -int wlan_associate(wlan_private * priv, struct bss_descriptor * pbssdesc); +int wlan_associate(wlan_private * priv, struct assoc_request * assoc_req); #endif diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index b9b25ce6591..4a59306a3f0 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -4,6 +4,7 @@ * thread etc.. */ +#include <linux/moduleparam.h> #include <linux/delay.h> #include <linux/freezer.h> #include <linux/etherdevice.h> @@ -11,26 +12,28 @@ #include <linux/if_arp.h> #include <net/iw_handler.h> +#include <net/ieee80211.h> #include "host.h" -#include "sbi.h" #include "decl.h" #include "dev.h" -#include "fw.h" #include "wext.h" #include "debugfs.h" #include "assoc.h" -#define DRIVER_RELEASE_VERSION "320.p0" +#define DRIVER_RELEASE_VERSION "322.p0" const char libertas_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION #ifdef DEBUG "-dbg" #endif ""; -#ifdef ENABLE_PM -static struct pm_dev *wlan_pm_dev = NULL; -#endif + +/* Module parameters */ +unsigned int libertas_debug = 0; +module_param(libertas_debug, int, 0644); +EXPORT_SYMBOL_GPL(libertas_debug); + #define WLAN_TX_PWR_DEFAULT 20 /*100mW */ #define WLAN_TX_PWR_US_DEFAULT 20 /*100mW */ @@ -146,14 +149,6 @@ static struct region_cfp_table region_cfp_table[] = { }; /** - * the rates supported by the card - */ -u8 libertas_wlan_data_rates[WLAN_SUPPORTED_RATES] = - { 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12, - 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x00 -}; - -/** * the rates supported */ u8 libertas_supported_rates[G_SUPPORTED_RATES] = @@ -173,66 +168,57 @@ u8 libertas_adhoc_rates_g[G_SUPPORTED_RATES] = u8 libertas_adhoc_rates_b[4] = { 0x82, 0x84, 0x8b, 0x96 }; /** - * the global variable of a pointer to wlan_private - * structure variable - */ -static wlan_private *wlanpriv = NULL; - -#define MAX_DEVS 5 -static struct net_device *libertas_devs[MAX_DEVS]; -static int libertas_found = 0; - -/** * the table to keep region code */ u16 libertas_region_code_to_index[MRVDRV_MAX_REGION_CODE] = { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 }; -static u8 *default_fw_name = "usb8388.bin"; - /** * Attributes exported through sysfs */ /** - * @brief Get function for sysfs attribute libertas_mpp + * @brief Get function for sysfs attribute anycast_mask */ -static ssize_t libertas_mpp_get(struct device * dev, - struct device_attribute *attr, char * buf) { +static ssize_t libertas_anycast_get(struct device * dev, + struct device_attribute *attr, char * buf) +{ struct cmd_ds_mesh_access mesh_access; memset(&mesh_access, 0, sizeof(mesh_access)); libertas_prepare_and_send_command(to_net_dev(dev)->priv, cmd_mesh_access, - cmd_act_mesh_get_mpp, + cmd_act_mesh_get_anycast, cmd_option_waitforrsp, 0, (void *)&mesh_access); - return snprintf(buf, 3, "%d\n", mesh_access.data[0]); + return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0])); } /** - * @brief Set function for sysfs attribute libertas_mpp + * @brief Set function for sysfs attribute anycast_mask */ -static ssize_t libertas_mpp_set(struct device * dev, - struct device_attribute *attr, const char * buf, size_t count) { +static ssize_t libertas_anycast_set(struct device * dev, + struct device_attribute *attr, const char * buf, size_t count) +{ struct cmd_ds_mesh_access mesh_access; - + uint32_t datum; memset(&mesh_access, 0, sizeof(mesh_access)); - sscanf(buf, "%d", &(mesh_access.data[0])); + sscanf(buf, "%x", &datum); + mesh_access.data[0] = cpu_to_le32(datum); + libertas_prepare_and_send_command((to_net_dev(dev))->priv, cmd_mesh_access, - cmd_act_mesh_set_mpp, + cmd_act_mesh_set_anycast, cmd_option_waitforrsp, 0, (void *)&mesh_access); return strlen(buf); } /** - * libertas_mpp attribute to be exported per mshX interface - * through sysfs (/sys/class/net/mshX/libertas-mpp) + * anycast_mask attribute to be exported per mshX interface + * through sysfs (/sys/class/net/mshX/anycast_mask) */ -static DEVICE_ATTR(libertas_mpp, 0644, libertas_mpp_get, - libertas_mpp_set ); +static DEVICE_ATTR(anycast_mask, 0644, libertas_anycast_get, libertas_anycast_set); /** * @brief Check if the device can be open and wait if necessary. @@ -245,7 +231,8 @@ static DEVICE_ATTR(libertas_mpp, 0644, libertas_mpp_get, * function to work around the issue. * */ -static int pre_open_check(struct net_device *dev) { +static int pre_open_check(struct net_device *dev) +{ wlan_private *priv = (wlan_private *) dev->priv; wlan_adapter *adapter = priv->adapter; int i = 0; @@ -255,8 +242,7 @@ static int pre_open_check(struct net_device *dev) { msleep_interruptible(100); } if (!adapter->fw_ready) { - lbs_pr_info("FW not ready, pre_open_check() return failure\n"); - LEAVE(); + lbs_pr_err("firmware not ready\n"); return -1; } @@ -274,17 +260,19 @@ static int wlan_dev_open(struct net_device *dev) wlan_private *priv = (wlan_private *) dev->priv; wlan_adapter *adapter = priv->adapter; - ENTER(); - + lbs_deb_enter(LBS_DEB_NET); priv->open = 1; if (adapter->connect_status == libertas_connected) { - netif_carrier_on(priv->wlan_dev.netdev); - } else - netif_carrier_off(priv->wlan_dev.netdev); + netif_carrier_on(priv->dev); + netif_carrier_on(priv->mesh_dev); + } else { + netif_carrier_off(priv->dev); + netif_carrier_off(priv->mesh_dev); + } - LEAVE(); + lbs_deb_leave(LBS_DEB_NET); return 0; } /** @@ -297,12 +285,12 @@ static int mesh_open(struct net_device *dev) { wlan_private *priv = (wlan_private *) dev->priv ; - if(pre_open_check(dev) == -1) + if (pre_open_check(dev) == -1) return -1; priv->mesh_open = 1 ; - netif_start_queue(priv->mesh_dev); + netif_wake_queue(priv->mesh_dev); if (priv->infra_open == 0) - return wlan_dev_open(priv->wlan_dev.netdev) ; + return wlan_dev_open(priv->dev) ; return 0; } @@ -319,9 +307,9 @@ static int wlan_open(struct net_device *dev) if(pre_open_check(dev) == -1) return -1; priv->infra_open = 1 ; - netif_wake_queue(priv->wlan_dev.netdev); + netif_wake_queue(priv->dev); if (priv->open == 0) - return wlan_dev_open(priv->wlan_dev.netdev) ; + return wlan_dev_open(priv->dev) ; return 0; } @@ -329,12 +317,12 @@ static int wlan_dev_close(struct net_device *dev) { wlan_private *priv = dev->priv; - ENTER(); + lbs_deb_enter(LBS_DEB_NET); - netif_carrier_off(priv->wlan_dev.netdev); + netif_carrier_off(priv->dev); priv->open = 0; - LEAVE(); + lbs_deb_leave(LBS_DEB_NET); return 0; } @@ -351,7 +339,7 @@ static int mesh_close(struct net_device *dev) priv->mesh_open = 0; netif_stop_queue(priv->mesh_dev); if (priv->infra_open == 0) - return wlan_dev_close( ((wlan_private *) dev->priv)->wlan_dev.netdev) ; + return wlan_dev_close(dev); else return 0; } @@ -362,147 +350,38 @@ static int mesh_close(struct net_device *dev) * @param dev A pointer to net_device structure * @return 0 */ -static int wlan_close(struct net_device *dev) { +static int wlan_close(struct net_device *dev) +{ wlan_private *priv = (wlan_private *) dev->priv; - netif_stop_queue(priv->wlan_dev.netdev); + netif_stop_queue(dev); priv->infra_open = 0; if (priv->mesh_open == 0) - return wlan_dev_close( ((wlan_private *) dev->priv)->wlan_dev.netdev) ; + return wlan_dev_close(dev); else return 0; } -#ifdef ENABLE_PM - -/** - * @brief This function is a callback function. it is called by - * kernel to enter or exit power saving mode. - * - * @param pmdev A pointer to pm_dev - * @param pmreq pm_request_t - * @param pmdata A pointer to pmdata - * @return 0 or -1 - */ -static int wlan_pm_callback(struct pm_dev *pmdev, pm_request_t pmreq, - void *pmdata) -{ - wlan_private *priv = wlanpriv; - wlan_adapter *adapter = priv->adapter; - struct net_device *dev = priv->wlan_dev.netdev; - - lbs_pr_debug(1, "WPRM_PM_CALLBACK: pmreq = %d.\n", pmreq); - - switch (pmreq) { - case PM_SUSPEND: - lbs_pr_debug(1, "WPRM_PM_CALLBACK: enter PM_SUSPEND.\n"); - - /* in associated mode */ - if (adapter->connect_status == libertas_connected) { - if ((adapter->psstate != PS_STATE_SLEEP) - ) { - lbs_pr_debug(1, - "wlan_pm_callback: can't enter sleep mode\n"); - return -1; - } else { - - /* - * Detach the network interface - * if the network is running - */ - if (netif_running(dev)) { - netif_device_detach(dev); - lbs_pr_debug(1, - "netif_device_detach().\n"); - } - libertas_sbi_suspend(priv); - } - break; - } - - /* in non associated mode */ - - /* - * Detach the network interface - * if the network is running - */ - if (netif_running(dev)) - netif_device_detach(dev); - - /* - * Storing and restoring of the regs be taken care - * at the driver rest will be done at wlan driver - * this makes driver independent of the card - */ - - libertas_sbi_suspend(priv); - - break; - - case PM_RESUME: - /* in associated mode */ - if (adapter->connect_status == libertas_connected) { - { - /* - * Bring the inteface up first - * This case should not happen still ... - */ - libertas_sbi_resume(priv); - - /* - * Attach the network interface - * if the network is running - */ - if (netif_running(dev)) { - netif_device_attach(dev); - lbs_pr_debug(1, - "after netif_device_attach().\n"); - } - lbs_pr_debug(1, - "After netif attach, in associated mode.\n"); - } - break; - } - - /* in non associated mode */ - - /* - * Bring the inteface up first - * This case should not happen still ... - */ - - libertas_sbi_resume(priv); - - if (netif_running(dev)) - netif_device_attach(dev); - - lbs_pr_debug(1, "after netif attach, in NON associated mode.\n"); - break; - } - - return 0; -} -#endif /* ENABLE_PM */ - static int wlan_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { int ret = 0; wlan_private *priv = dev->priv; - ENTER(); + lbs_deb_enter(LBS_DEB_NET); - if (priv->wlan_dev.dnld_sent || priv->adapter->TxLockFlag) { + if (priv->dnld_sent || priv->adapter->TxLockFlag) { priv->stats.tx_dropped++; goto done; } - netif_stop_queue(priv->wlan_dev.netdev); + netif_stop_queue(priv->dev); + netif_stop_queue(priv->mesh_dev); if (libertas_process_tx(priv, skb) == 0) dev->trans_start = jiffies; done: - LEAVE(); + lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); return ret; } @@ -513,33 +392,43 @@ done: static int mesh_pre_start_xmit(struct sk_buff *skb, struct net_device *dev) { wlan_private *priv = dev->priv; - ENTER(); + int ret; + + lbs_deb_enter(LBS_DEB_MESH); + SET_MESH_FRAME(skb); - LEAVE(); - return wlan_hard_start_xmit(skb, priv->wlan_dev.netdev); + ret = wlan_hard_start_xmit(skb, priv->dev); + lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret); + return ret; } /** * @brief Mark non-mesh packets and handover them to wlan_hard_start_xmit * */ -static int wlan_pre_start_xmit(struct sk_buff *skb, struct net_device *dev) { - ENTER(); +static int wlan_pre_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + int ret; + + lbs_deb_enter(LBS_DEB_NET); + UNSET_MESH_FRAME(skb); - LEAVE(); - return wlan_hard_start_xmit(skb, dev); + + ret = wlan_hard_start_xmit(skb, dev); + lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); + return ret; } static void wlan_tx_timeout(struct net_device *dev) { wlan_private *priv = (wlan_private *) dev->priv; - ENTER(); + lbs_deb_enter(LBS_DEB_TX); - lbs_pr_err("tx watch dog timeout!\n"); + lbs_pr_err("tx watch dog timeout\n"); - priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED; + priv->dnld_sent = DNLD_RES_RECEIVED; dev->trans_start = jiffies; if (priv->adapter->currenttxskb) { @@ -550,10 +439,12 @@ static void wlan_tx_timeout(struct net_device *dev) libertas_send_tx_feedback(priv); } else wake_up_interruptible(&priv->mainthread.waitq); - } else if (priv->adapter->connect_status == libertas_connected) - netif_wake_queue(priv->wlan_dev.netdev); + } else if (priv->adapter->connect_status == libertas_connected) { + netif_wake_queue(priv->dev); + netif_wake_queue(priv->mesh_dev); + } - LEAVE(); + lbs_deb_leave(LBS_DEB_TX); } /** @@ -576,7 +467,10 @@ static int wlan_set_mac_address(struct net_device *dev, void *addr) wlan_adapter *adapter = priv->adapter; struct sockaddr *phwaddr = addr; - ENTER(); + lbs_deb_enter(LBS_DEB_NET); + + /* In case it was called from the mesh device */ + dev = priv->dev ; memset(adapter->current_addr, 0, ETH_ALEN); @@ -591,17 +485,18 @@ static int wlan_set_mac_address(struct net_device *dev, void *addr) cmd_option_waitforrsp, 0, NULL); if (ret) { - lbs_pr_debug(1, "set mac address failed.\n"); + lbs_deb_net("set MAC address failed\n"); ret = -1; goto done; } lbs_dbg_hex("adapter->macaddr:", adapter->current_addr, ETH_ALEN); memcpy(dev->dev_addr, adapter->current_addr, ETH_ALEN); - memcpy(((wlan_private *) dev->priv)->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN); + if (priv->mesh_dev) + memcpy(priv->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN); done: - LEAVE(); + lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); return ret; } @@ -626,12 +521,12 @@ static void wlan_set_multicast_list(struct net_device *dev) wlan_adapter *adapter = priv->adapter; int oldpacketfilter; - ENTER(); + lbs_deb_enter(LBS_DEB_NET); oldpacketfilter = adapter->currentpacketfilter; if (dev->flags & IFF_PROMISC) { - lbs_pr_debug(1, "enable Promiscuous mode\n"); + lbs_deb_net("enable promiscuous mode\n"); adapter->currentpacketfilter |= cmd_act_mac_promiscuous_enable; adapter->currentpacketfilter &= @@ -644,7 +539,7 @@ static void wlan_set_multicast_list(struct net_device *dev) if (dev->flags & IFF_ALLMULTI || dev->mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE) { - lbs_pr_debug(1, "Enabling All Multicast!\n"); + lbs_deb_net( "enabling all multicast\n"); adapter->currentpacketfilter |= cmd_act_mac_all_multicast_enable; adapter->currentpacketfilter &= @@ -654,8 +549,8 @@ static void wlan_set_multicast_list(struct net_device *dev) ~cmd_act_mac_all_multicast_enable; if (!dev->mc_count) { - lbs_pr_debug(1, "No multicast addresses - " - "disabling multicast!\n"); + lbs_deb_net("no multicast addresses, " + "disabling multicast\n"); adapter->currentpacketfilter &= ~cmd_act_mac_multicast_enable; } else { @@ -667,12 +562,12 @@ static void wlan_set_multicast_list(struct net_device *dev) adapter->nr_of_multicastmacaddr = wlan_copy_multicast_address(adapter, dev); - lbs_pr_debug(1, "Multicast addresses: %d\n", + lbs_deb_net("multicast addresses: %d\n", dev->mc_count); for (i = 0; i < dev->mc_count; i++) { - lbs_pr_debug(1, "Multicast address %d:" - "%x %x %x %x %x %x\n", i, + lbs_deb_net("Multicast address %d:" + MAC_FMT "\n", i, adapter->multicastlist[i][0], adapter->multicastlist[i][1], adapter->multicastlist[i][2], @@ -680,7 +575,7 @@ static void wlan_set_multicast_list(struct net_device *dev) adapter->multicastlist[i][4], adapter->multicastlist[i][5]); } - /* set multicast addresses to firmware */ + /* send multicast addresses to firmware */ libertas_prepare_and_send_command(priv, cmd_mac_multicast_adr, cmd_act_set, 0, 0, @@ -693,13 +588,13 @@ static void wlan_set_multicast_list(struct net_device *dev) libertas_set_mac_packet_filter(priv); } - LEAVE(); + lbs_deb_leave(LBS_DEB_NET); } /** - * @brief This function hanldes the major job in WLAN driver. - * it handles the event generated by firmware, rx data received - * from firmware and tx data sent from kernel. + * @brief This function handles the major jobs in the WLAN driver. + * It handles all events generated by firmware, RX data received + * from firmware and TX data sent from kernel. * * @param data A pointer to wlan_thread structure * @return 0 @@ -712,26 +607,26 @@ static int wlan_service_main_thread(void *data) wait_queue_t wait; u8 ireg = 0; - ENTER(); + lbs_deb_enter(LBS_DEB_THREAD); wlan_activate_thread(thread); init_waitqueue_entry(&wait, current); for (;;) { - lbs_pr_debug(1, "main-thread 111: intcounter=%d " + lbs_deb_thread( "main-thread 111: intcounter=%d " "currenttxskb=%p dnld_sent=%d\n", adapter->intcounter, - adapter->currenttxskb, priv->wlan_dev.dnld_sent); + adapter->currenttxskb, priv->dnld_sent); add_wait_queue(&thread->waitq, &wait); set_current_state(TASK_INTERRUPTIBLE); spin_lock_irq(&adapter->driver_lock); if ((adapter->psstate == PS_STATE_SLEEP) || (!adapter->intcounter - && (priv->wlan_dev.dnld_sent || adapter->cur_cmd || + && (priv->dnld_sent || adapter->cur_cmd || list_empty(&adapter->cmdpendingq)))) { - lbs_pr_debug(1, + lbs_deb_thread( "main-thread sleeping... Conn=%d IntC=%d PS_mode=%d PS_State=%d\n", adapter->connect_status, adapter->intcounter, adapter->psmode, adapter->psstate); @@ -741,23 +636,23 @@ static int wlan_service_main_thread(void *data) spin_unlock_irq(&adapter->driver_lock); - lbs_pr_debug(1, + lbs_deb_thread( "main-thread 222 (waking up): intcounter=%d currenttxskb=%p " "dnld_sent=%d\n", adapter->intcounter, - adapter->currenttxskb, priv->wlan_dev.dnld_sent); + adapter->currenttxskb, priv->dnld_sent); set_current_state(TASK_RUNNING); remove_wait_queue(&thread->waitq, &wait); try_to_freeze(); - lbs_pr_debug(1, "main-thread 333: intcounter=%d currenttxskb=%p " + lbs_deb_thread("main-thread 333: intcounter=%d currenttxskb=%p " "dnld_sent=%d\n", adapter->intcounter, - adapter->currenttxskb, priv->wlan_dev.dnld_sent); + adapter->currenttxskb, priv->dnld_sent); if (kthread_should_stop() || adapter->surpriseremoved) { - lbs_pr_debug(1, + lbs_deb_thread( "main-thread: break from main thread: surpriseremoved=0x%x\n", adapter->surpriseremoved); break; @@ -768,10 +663,10 @@ static int wlan_service_main_thread(void *data) if (adapter->intcounter) { u8 int_status; adapter->intcounter = 0; - int_status = libertas_sbi_get_int_status(priv, &ireg); + int_status = priv->hw_get_int_status(priv, &ireg); if (int_status) { - lbs_pr_debug(1, + lbs_deb_thread( "main-thread: reading HOST_INT_STATUS_REG failed\n"); spin_unlock_irq(&adapter->driver_lock); continue; @@ -779,14 +674,14 @@ static int wlan_service_main_thread(void *data) adapter->hisregcpy |= ireg; } - lbs_pr_debug(1, "main-thread 444: intcounter=%d currenttxskb=%p " + lbs_deb_thread("main-thread 444: intcounter=%d currenttxskb=%p " "dnld_sent=%d\n", adapter->intcounter, - adapter->currenttxskb, priv->wlan_dev.dnld_sent); + adapter->currenttxskb, priv->dnld_sent); /* command response? */ if (adapter->hisregcpy & his_cmdupldrdy) { - lbs_pr_debug(1, "main-thread: cmd response ready.\n"); + lbs_deb_thread("main-thread: cmd response ready\n"); adapter->hisregcpy &= ~his_cmdupldrdy; spin_unlock_irq(&adapter->driver_lock); @@ -796,13 +691,13 @@ static int wlan_service_main_thread(void *data) /* Any Card Event */ if (adapter->hisregcpy & his_cardevent) { - lbs_pr_debug(1, "main-thread: Card Event Activity.\n"); + lbs_deb_thread("main-thread: Card Event Activity\n"); adapter->hisregcpy &= ~his_cardevent; - if (libertas_sbi_read_event_cause(priv)) { + if (priv->hw_read_event_cause(priv)) { lbs_pr_alert( - "main-thread: libertas_sbi_read_event_cause failed.\n"); + "main-thread: hw_read_event_cause failed\n"); spin_unlock_irq(&adapter->driver_lock); continue; } @@ -813,15 +708,15 @@ static int wlan_service_main_thread(void *data) /* Check if we need to confirm Sleep Request received previously */ if (adapter->psstate == PS_STATE_PRE_SLEEP) { - if (!priv->wlan_dev.dnld_sent && !adapter->cur_cmd) { + if (!priv->dnld_sent && !adapter->cur_cmd) { if (adapter->connect_status == libertas_connected) { - lbs_pr_debug(1, + lbs_deb_thread( "main_thread: PRE_SLEEP--intcounter=%d currenttxskb=%p " "dnld_sent=%d cur_cmd=%p, confirm now\n", adapter->intcounter, adapter->currenttxskb, - priv->wlan_dev.dnld_sent, + priv->dnld_sent, adapter->cur_cmd); libertas_ps_confirm_sleep(priv, @@ -847,7 +742,7 @@ static int wlan_service_main_thread(void *data) continue; /* Execute the next command */ - if (!priv->wlan_dev.dnld_sent && !priv->adapter->cur_cmd) + if (!priv->dnld_sent && !priv->adapter->cur_cmd) libertas_execute_next_command(priv); /* Wake-up command waiters which can't sleep in @@ -864,7 +759,7 @@ static int wlan_service_main_thread(void *data) wake_up_all(&adapter->cmd_pending); wlan_deactivate_thread(thread); - LEAVE(); + lbs_deb_leave(LBS_DEB_THREAD); return 0; } @@ -875,166 +770,203 @@ static int wlan_service_main_thread(void *data) * @param card A pointer to card * @return A pointer to wlan_private structure */ -wlan_private *wlan_add_card(void *card) +wlan_private *libertas_add_card(void *card, struct device *dmdev) { struct net_device *dev = NULL; - struct net_device *mesh_dev = NULL; wlan_private *priv = NULL; - ENTER(); + lbs_deb_enter(LBS_DEB_NET); /* Allocate an Ethernet device and register it */ if (!(dev = alloc_etherdev(sizeof(wlan_private)))) { - lbs_pr_alert( "Init ethernet device failed!\n"); + lbs_pr_err("init ethX device failed\n"); return NULL; } - priv = dev->priv; /* allocate buffer for wlan_adapter */ - if (!(priv->adapter = kmalloc(sizeof(wlan_adapter), GFP_KERNEL))) { - lbs_pr_alert( "Allocate buffer for wlan_adapter failed!\n"); - goto err_kmalloc; - } - - /* Allocate a virtual mesh device */ - if (!(mesh_dev = alloc_netdev(0, "msh%d", ether_setup))) { - lbs_pr_debug(1, "Init ethernet device failed!\n"); - return NULL; + if (!(priv->adapter = kzalloc(sizeof(wlan_adapter), GFP_KERNEL))) { + lbs_pr_err("allocate buffer for wlan_adapter failed\n"); + goto err_kzalloc; } - /* Both intervaces share the priv structure */ - mesh_dev->priv = priv; - - /* init wlan_adapter */ - memset(priv->adapter, 0, sizeof(wlan_adapter)); - - priv->wlan_dev.netdev = dev; - priv->wlan_dev.card = card; + priv->dev = dev; + priv->card = card; priv->mesh_open = 0; priv->infra_open = 0; - priv->mesh_dev = mesh_dev; - wlanpriv = priv; SET_MODULE_OWNER(dev); - SET_MODULE_OWNER(mesh_dev); /* Setup the OS Interface to our functions */ dev->open = wlan_open; dev->hard_start_xmit = wlan_pre_start_xmit; dev->stop = wlan_close; - dev->do_ioctl = libertas_do_ioctl; dev->set_mac_address = wlan_set_mac_address; - mesh_dev->open = mesh_open; - mesh_dev->hard_start_xmit = mesh_pre_start_xmit; - mesh_dev->stop = mesh_close; - mesh_dev->do_ioctl = libertas_do_ioctl; - memcpy(mesh_dev->dev_addr, wlanpriv->wlan_dev.netdev->dev_addr, - sizeof(wlanpriv->wlan_dev.netdev->dev_addr)); - -#define WLAN_WATCHDOG_TIMEOUT (5 * HZ) - dev->tx_timeout = wlan_tx_timeout; dev->get_stats = wlan_get_stats; - dev->watchdog_timeo = WLAN_WATCHDOG_TIMEOUT; + dev->watchdog_timeo = 5 * HZ; dev->ethtool_ops = &libertas_ethtool_ops; - mesh_dev->get_stats = wlan_get_stats; - mesh_dev->ethtool_ops = &libertas_ethtool_ops; - #ifdef WIRELESS_EXT dev->wireless_handlers = (struct iw_handler_def *)&libertas_handler_def; - mesh_dev->wireless_handlers = (struct iw_handler_def *)&libertas_handler_def; #endif #define NETIF_F_DYNALLOC 16 dev->features |= NETIF_F_DYNALLOC; dev->flags |= IFF_BROADCAST | IFF_MULTICAST; dev->set_multicast_list = wlan_set_multicast_list; + SET_NETDEV_DEV(dev, dmdev); + INIT_LIST_HEAD(&priv->adapter->cmdfreeq); INIT_LIST_HEAD(&priv->adapter->cmdpendingq); spin_lock_init(&priv->adapter->driver_lock); init_waitqueue_head(&priv->adapter->cmd_pending); priv->adapter->nr_cmd_pending = 0; + goto done; + +err_kzalloc: + free_netdev(dev); + priv = NULL; +done: + lbs_deb_leave_args(LBS_DEB_NET, "priv %p", priv); + return priv; +} +EXPORT_SYMBOL_GPL(libertas_add_card); - lbs_pr_debug(1, "Starting kthread...\n"); +int libertas_activate_card(wlan_private *priv, char *fw_name) +{ + struct net_device *dev = priv->dev; + int ret = -1; + + lbs_deb_enter(LBS_DEB_MAIN); + + lbs_deb_thread("Starting kthread...\n"); priv->mainthread.priv = priv; wlan_create_thread(wlan_service_main_thread, &priv->mainthread, "wlan_main_service"); priv->assoc_thread = create_singlethread_workqueue("libertas_assoc"); - INIT_DELAYED_WORK(&priv->assoc_work, wlan_association_worker); + INIT_DELAYED_WORK(&priv->assoc_work, libertas_association_worker); + INIT_WORK(&priv->sync_channel, libertas_sync_channel); /* * Register the device. Fillup the private data structure with * relevant information from the card and request for the required * IRQ. */ - if (libertas_sbi_register_dev(priv) < 0) { - lbs_pr_info("failed to register wlan device!\n"); + if (priv->hw_register_dev(priv) < 0) { + lbs_pr_err("failed to register WLAN device\n"); goto err_registerdev; } /* init FW and HW */ - if (libertas_init_fw(priv)) { - lbs_pr_debug(1, "Firmware Init failed\n"); + if (fw_name && libertas_init_fw(priv, fw_name)) { + lbs_pr_err("firmware init failed\n"); goto err_registerdev; } if (register_netdev(dev)) { - lbs_pr_err("Cannot register network device!\n"); - goto err_init_fw; - } - - /* Register virtual mesh interface */ - if (register_netdev(mesh_dev)) { - lbs_pr_info("Cannot register mesh virtual interface!\n"); + lbs_pr_err("cannot register ethX device\n"); goto err_init_fw; } - lbs_pr_info("%s: Marvell Wlan 802.11 adapter ", dev->name); + lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name); libertas_debugfs_init_one(priv, dev); - if (libertas_found == MAX_DEVS) - goto err_init_fw; - libertas_devs[libertas_found] = dev; - libertas_found++; -#ifdef ENABLE_PM - if (!(wlan_pm_dev = pm_register(PM_UNKNOWN_DEV, 0, wlan_pm_callback))) - lbs_pr_alert( "failed to register PM callback\n"); -#endif - if (device_create_file(&(mesh_dev->dev), &dev_attr_libertas_mpp)) - goto err_create_file; + ret = 0; + goto done; - LEAVE(); - return priv; - -err_create_file: - device_remove_file(&(mesh_dev->dev), &dev_attr_libertas_mpp); err_init_fw: - libertas_sbi_unregister_dev(priv); + priv->hw_unregister_dev(priv); err_registerdev: destroy_workqueue(priv->assoc_thread); /* Stop the thread servicing the interrupts */ wake_up_interruptible(&priv->mainthread.waitq); wlan_terminate_thread(&priv->mainthread); - kfree(priv->adapter); -err_kmalloc: - free_netdev(dev); +done: + lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); + return ret; +} +EXPORT_SYMBOL_GPL(libertas_activate_card); + + +/** + * @brief This function adds mshX interface + * + * @param priv A pointer to the wlan_private structure + * @return 0 if successful, -X otherwise + */ +int libertas_add_mesh(wlan_private *priv, struct device *dev) +{ + struct net_device *mesh_dev = NULL; + int ret = 0; + + lbs_deb_enter(LBS_DEB_MESH); + + /* Allocate a virtual mesh device */ + if (!(mesh_dev = alloc_netdev(0, "msh%d", ether_setup))) { + lbs_deb_mesh("init mshX device failed\n"); + ret = -ENOMEM; + goto done; + } + mesh_dev->priv = priv; + priv->mesh_dev = mesh_dev; + + SET_MODULE_OWNER(mesh_dev); + + mesh_dev->open = mesh_open; + mesh_dev->hard_start_xmit = mesh_pre_start_xmit; + mesh_dev->stop = mesh_close; + mesh_dev->get_stats = wlan_get_stats; + mesh_dev->set_mac_address = wlan_set_mac_address; + mesh_dev->ethtool_ops = &libertas_ethtool_ops; + memcpy(mesh_dev->dev_addr, priv->dev->dev_addr, + sizeof(priv->dev->dev_addr)); + + SET_NETDEV_DEV(priv->mesh_dev, dev); + +#ifdef WIRELESS_EXT + mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def; +#endif +#define NETIF_F_DYNALLOC 16 + + /* Register virtual mesh interface */ + ret = register_netdev(mesh_dev); + if (ret) { + lbs_pr_err("cannot register mshX virtual interface\n"); + goto err_free; + } + + ret = device_create_file(&(mesh_dev->dev), &dev_attr_anycast_mask); + if (ret) + goto err_unregister; + + /* Everything successful */ + ret = 0; + goto done; + + +err_unregister: + unregister_netdev(mesh_dev); + +err_free: free_netdev(mesh_dev); - wlanpriv = NULL; - LEAVE(); - return NULL; +done: + lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret); + return ret; } +EXPORT_SYMBOL_GPL(libertas_add_mesh); static void wake_pending_cmdnodes(wlan_private *priv) { struct cmd_ctrl_node *cmdnode; unsigned long flags; + lbs_deb_enter(LBS_DEB_CMD); + spin_lock_irqsave(&priv->adapter->driver_lock, flags); list_for_each_entry(cmdnode, &priv->adapter->cmdpendingq, list) { cmdnode->cmdwaitqwoken = 1; @@ -1044,40 +976,29 @@ static void wake_pending_cmdnodes(wlan_private *priv) } -int wlan_remove_card(void *card) +int libertas_remove_card(wlan_private *priv) { - wlan_private *priv = libertas_sbi_get_priv(card); wlan_adapter *adapter; struct net_device *dev; - struct net_device *mesh_dev; union iwreq_data wrqu; - int i; - ENTER(); + lbs_deb_enter(LBS_DEB_NET); - if (!priv) { - LEAVE(); - return 0; - } + if (!priv) + goto out; adapter = priv->adapter; - if (!adapter) { - LEAVE(); - return 0; - } + if (!adapter) + goto out; - dev = priv->wlan_dev.netdev; - mesh_dev = priv->mesh_dev; + dev = priv->dev; - netif_stop_queue(mesh_dev); - netif_stop_queue(priv->wlan_dev.netdev); - netif_carrier_off(priv->wlan_dev.netdev); + netif_stop_queue(priv->dev); + netif_carrier_off(priv->dev); wake_pending_cmdnodes(priv); - device_remove_file(&(mesh_dev->dev), &dev_attr_libertas_mpp); - unregister_netdev(mesh_dev); unregister_netdev(dev); cancel_delayed_work(&priv->assoc_work); @@ -1090,11 +1011,7 @@ int wlan_remove_card(void *card) memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN); wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL); - -#ifdef ENABLE_PM - pm_unregister(wlan_pm_dev); -#endif + wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); adapter->surpriseremoved = 1; @@ -1103,28 +1020,45 @@ int wlan_remove_card(void *card) libertas_debugfs_remove_one(priv); - lbs_pr_debug(1, "Free adapter\n"); + lbs_deb_net("free adapter\n"); libertas_free_adapter(priv); - for (i = 0; i<libertas_found; i++) { - if (libertas_devs[i]==priv->wlan_dev.netdev) { - libertas_devs[i] = libertas_devs[--libertas_found]; - libertas_devs[libertas_found] = NULL ; - break ; - } - } + lbs_deb_net("unregister finish\n"); + + priv->dev = NULL; + free_netdev(dev); + +out: + lbs_deb_leave(LBS_DEB_NET); + return 0; +} +EXPORT_SYMBOL_GPL(libertas_remove_card); + + +void libertas_remove_mesh(wlan_private *priv) +{ + struct net_device *mesh_dev; + + lbs_deb_enter(LBS_DEB_NET); + + if (!priv) + goto out; + + mesh_dev = priv->mesh_dev; + + netif_stop_queue(mesh_dev); + netif_carrier_off(priv->mesh_dev); - lbs_pr_debug(1, "Unregister finish\n"); + device_remove_file(&(mesh_dev->dev), &dev_attr_anycast_mask); + unregister_netdev(mesh_dev); - priv->wlan_dev.netdev = NULL; priv->mesh_dev = NULL ; free_netdev(mesh_dev); - free_netdev(dev); - wlanpriv = NULL; - LEAVE(); - return 0; +out: + lbs_deb_leave(LBS_DEB_NET); } +EXPORT_SYMBOL_GPL(libertas_remove_mesh); /** * @brief This function finds the CFP in @@ -1139,33 +1073,34 @@ struct chan_freq_power *libertas_get_region_cfp_table(u8 region, u8 band, int *c { int i, end; - ENTER(); + lbs_deb_enter(LBS_DEB_MAIN); end = sizeof(region_cfp_table)/sizeof(struct region_cfp_table); for (i = 0; i < end ; i++) { - lbs_pr_debug(1, "region_cfp_table[i].region=%d\n", + lbs_deb_main("region_cfp_table[i].region=%d\n", region_cfp_table[i].region); if (region_cfp_table[i].region == region) { *cfp_no = region_cfp_table[i].cfp_no_BG; - LEAVE(); + lbs_deb_leave(LBS_DEB_MAIN); return region_cfp_table[i].cfp_BG; } } - LEAVE(); + lbs_deb_leave_args(LBS_DEB_MAIN, "ret NULL"); return NULL; } int libertas_set_regiontable(wlan_private * priv, u8 region, u8 band) { wlan_adapter *adapter = priv->adapter; + int ret = 0; int i = 0; struct chan_freq_power *cfp; int cfp_no; - ENTER(); + lbs_deb_enter(LBS_DEB_MAIN); memset(adapter->region_channel, 0, sizeof(adapter->region_channel)); @@ -1175,17 +1110,19 @@ int libertas_set_regiontable(wlan_private * priv, u8 region, u8 band) adapter->region_channel[i].nrcfp = cfp_no; adapter->region_channel[i].CFP = cfp; } else { - lbs_pr_debug(1, "wrong region code %#x in band B-G\n", + lbs_deb_main("wrong region code %#x in band B/G\n", region); - return -1; + ret = -1; + goto out; } adapter->region_channel[i].valid = 1; adapter->region_channel[i].region = region; adapter->region_channel[i].band = band; i++; } - LEAVE(); - return 0; +out: + lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret); + return ret; } /** @@ -1200,9 +1137,9 @@ void libertas_interrupt(struct net_device *dev) { wlan_private *priv = dev->priv; - ENTER(); + lbs_deb_enter(LBS_DEB_THREAD); - lbs_pr_debug(1, "libertas_interrupt: intcounter=%d\n", + lbs_deb_thread("libertas_interrupt: intcounter=%d\n", priv->adapter->intcounter); priv->adapter->intcounter++; @@ -1210,56 +1147,35 @@ void libertas_interrupt(struct net_device *dev) if (priv->adapter->psstate == PS_STATE_SLEEP) { priv->adapter->psstate = PS_STATE_AWAKE; netif_wake_queue(dev); + netif_wake_queue(priv->mesh_dev); } wake_up_interruptible(&priv->mainthread.waitq); - LEAVE(); + lbs_deb_leave(LBS_DEB_THREAD); } +EXPORT_SYMBOL_GPL(libertas_interrupt); -static int wlan_init_module(void) +static int libertas_init_module(void) { - int ret = 0; - - ENTER(); - - if (libertas_fw_name == NULL) { - libertas_fw_name = default_fw_name; - } - + lbs_deb_enter(LBS_DEB_MAIN); libertas_debugfs_init(); - - if (libertas_sbi_register()) { - ret = -1; - libertas_debugfs_remove(); - goto done; - } - -done: - LEAVE(); - return ret; + lbs_deb_leave(LBS_DEB_MAIN); + return 0; } -static void wlan_cleanup_module(void) +static void libertas_exit_module(void) { - int i; - - ENTER(); - - for (i = 0; i<libertas_found; i++) { - wlan_private *priv = libertas_devs[i]->priv; - reset_device(priv); - } + lbs_deb_enter(LBS_DEB_MAIN); - libertas_sbi_unregister(); libertas_debugfs_remove(); - LEAVE(); + lbs_deb_leave(LBS_DEB_MAIN); } -module_init(wlan_init_module); -module_exit(wlan_cleanup_module); +module_init(libertas_init_module); +module_exit(libertas_exit_module); -MODULE_DESCRIPTION("M-WLAN Driver"); +MODULE_DESCRIPTION("Libertas WLAN Driver Library"); MODULE_AUTHOR("Marvell International Ltd."); MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 96619a32951..88d9d2d787d 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c @@ -106,10 +106,10 @@ static void wlan_compute_rssi(wlan_private * priv, struct rxpd *p_rx_pd) { wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_RX); - lbs_pr_debug(1, "rxpd: SNR = %d, NF = %d\n", p_rx_pd->snr, p_rx_pd->nf); - lbs_pr_debug(1, "Before computing SNR: SNR- avg = %d, NF-avg = %d\n", + lbs_deb_rx("rxpd: SNR %d, NF %d\n", p_rx_pd->snr, p_rx_pd->nf); + lbs_deb_rx("before computing SNR: SNR-avg = %d, NF-avg = %d\n", adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE, adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE); @@ -121,7 +121,7 @@ static void wlan_compute_rssi(wlan_private * priv, struct rxpd *p_rx_pd) adapter->SNR[TYPE_RXPD][TYPE_AVG] = wlan_getavgsnr(priv) * AVG_SCALE; adapter->NF[TYPE_RXPD][TYPE_AVG] = wlan_getavgnf(priv) * AVG_SCALE; - lbs_pr_debug(1, "After computing SNR: SNR-avg = %d, NF-avg = %d\n", + lbs_deb_rx("after computing SNR: SNR-avg = %d, NF-avg = %d\n", adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE, adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE); @@ -133,18 +133,17 @@ static void wlan_compute_rssi(wlan_private * priv, struct rxpd *p_rx_pd) CAL_RSSI(adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE, adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE); - LEAVE(); + lbs_deb_leave(LBS_DEB_RX); } void libertas_upload_rx_packet(wlan_private * priv, struct sk_buff *skb) { - lbs_pr_debug(1, "skb->data=%p\n", skb->data); + lbs_deb_rx("skb->data %p\n", skb->data); - if(IS_MESH_FRAME(skb)) - skb->dev = priv->mesh_dev; + if (priv->mesh_dev && IS_MESH_FRAME(skb)) + skb->protocol = eth_type_trans(skb, priv->mesh_dev); else - skb->dev = priv->wlan_dev.netdev; - skb->protocol = eth_type_trans(skb, priv->wlan_dev.netdev); + skb->protocol = eth_type_trans(skb, priv->dev); skb->ip_summed = CHECKSUM_UNNECESSARY; netif_rx(skb); @@ -171,7 +170,7 @@ int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *skb) const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; - ENTER(); + lbs_deb_enter(LBS_DEB_RX); if (priv->adapter->debugmode & MRVDRV_DEBUG_RX_PATH) lbs_dbg_hex("RX packet: ", skb->data, @@ -191,7 +190,7 @@ int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *skb) min_t(unsigned int, skb->len, 100)); if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) { - lbs_pr_debug(1, "RX error: FRAME RECEIVED WITH BAD LENGTH\n"); + lbs_deb_rx("rx err: frame received with bad length\n"); priv->stats.rx_length_errors++; ret = 0; goto done; @@ -200,15 +199,15 @@ int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *skb) /* * Check rxpd status and update 802.3 stat, */ - if (!(p_rx_pd->status & MRVDRV_RXPD_STATUS_OK)) { - lbs_pr_debug(1, "RX error: frame received with bad status\n"); - lbs_pr_alert("rxpd Not OK\n"); + if (!(p_rx_pd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) { + lbs_deb_rx("rx err: frame received with bad status\n"); + lbs_pr_alert("rxpd not ok\n"); priv->stats.rx_errors++; ret = 0; goto done; } - lbs_pr_debug(1, "RX Data: skb->len - sizeof(RxPd) = %d - %zd = %zd\n", + lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n", skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd)); lbs_dbg_hex("RX Data: Dest", p_rx_pkt->eth803_hdr.dest_addr, @@ -266,7 +265,7 @@ int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *skb) wlan_compute_rssi(priv, p_rx_pd); - lbs_pr_debug(1, "RX Data: size of actual packet = %d\n", skb->len); + lbs_deb_rx("rx data: size of actual packet %d\n", skb->len); priv->stats.rx_bytes += skb->len; priv->stats.rx_packets++; @@ -274,10 +273,10 @@ int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *skb) ret = 0; done: - LEAVE(); - + lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret); return ret; } +EXPORT_SYMBOL_GPL(libertas_process_rxed_packet); /** * @brief This function converts Tx/Rx rates from the Marvell WLAN format @@ -314,7 +313,7 @@ static u8 convert_mv_rate_to_radiotap(u8 rate) case 11: /* 54 Mbps */ return 108; } - lbs_pr_alert( "Invalid Marvell WLAN rate (%i)\n", rate); + lbs_pr_alert("Invalid Marvell WLAN rate %i\n", rate); return 0; } @@ -336,7 +335,7 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb) struct rx_radiotap_hdr radiotap_hdr; struct rx_radiotap_hdr *pradiotap_hdr; - ENTER(); + lbs_deb_enter(LBS_DEB_RX); p_rx_pkt = (struct rx80211packethdr *) skb->data; prxpd = &p_rx_pkt->rx_pd; @@ -344,7 +343,7 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb) // lbs_dbg_hex("RX Data: Before chop rxpd", skb->data, min(skb->len, 100)); if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) { - lbs_pr_debug(1, "RX error: FRAME RECEIVED WITH BAD LENGTH\n"); + lbs_deb_rx("rx err: frame received wit bad length\n"); priv->stats.rx_length_errors++; ret = 0; goto done; @@ -353,12 +352,12 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb) /* * Check rxpd status and update 802.3 stat, */ - if (!(prxpd->status & MRVDRV_RXPD_STATUS_OK)) { - //lbs_pr_debug(1, "RX error: frame received with bad status\n"); + if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) { + //lbs_deb_rx("rx err: frame received with bad status\n"); priv->stats.rx_errors++; } - lbs_pr_debug(1, "RX Data: skb->len - sizeof(RxPd) = %d - %zd = %zd\n", + lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n", skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd)); /* create the exported radio header */ @@ -386,7 +385,7 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb) /* XXX must check no carryout */ radiotap_hdr.antsignal = prxpd->snr + prxpd->nf; radiotap_hdr.rx_flags = 0; - if (!(prxpd->status & MRVDRV_RXPD_STATUS_OK)) + if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) radiotap_hdr.rx_flags |= IEEE80211_RADIOTAP_F_RX_BADFCS; //memset(radiotap_hdr.pad, 0x11, IEEE80211_RADIOTAP_HDRLEN - 18); @@ -399,7 +398,7 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb) if ((skb_headroom(skb) < sizeof(struct rx_radiotap_hdr)) && pskb_expand_head(skb, sizeof(struct rx_radiotap_hdr), 0, GFP_ATOMIC)) { - lbs_pr_alert( "%s: couldn't pskb_expand_head\n", + lbs_pr_alert("%s: couldn't pskb_expand_head\n", __func__); } @@ -414,7 +413,7 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb) default: /* unknown header */ - lbs_pr_alert( "Unknown radiomode (%i)\n", + lbs_pr_alert("Unknown radiomode %i\n", priv->adapter->radiomode); /* don't export any header */ /* chop the rxpd */ @@ -431,15 +430,16 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb) wlan_compute_rssi(priv, prxpd); - lbs_pr_debug(1, "RX Data: size of actual packet = %d\n", skb->len); + lbs_deb_rx("rx data: size of actual packet %d\n", skb->len); priv->stats.rx_bytes += skb->len; priv->stats.rx_packets++; libertas_upload_rx_packet(priv, skb); ret = 0; -done: - LEAVE(); - return (ret); +done: + skb->protocol = __constant_htons(0x0019); /* ETH_P_80211_RAW */ + lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret); + return ret; } diff --git a/drivers/net/wireless/libertas/sbi.h b/drivers/net/wireless/libertas/sbi.h deleted file mode 100644 index 59d3a59ccef..00000000000 --- a/drivers/net/wireless/libertas/sbi.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - * This file contains IF layer definitions. - */ - -#ifndef _SBI_H_ -#define _SBI_H_ - -#include <linux/interrupt.h> - -#include "defs.h" - -/** INT status Bit Definition*/ -#define his_cmddnldrdy 0x01 -#define his_cardevent 0x02 -#define his_cmdupldrdy 0x04 - -#ifndef DEV_NAME_LEN -#define DEV_NAME_LEN 32 -#endif - -#define SBI_EVENT_CAUSE_SHIFT 3 - -/* Probe and Check if the card is present*/ -int libertas_sbi_register_dev(wlan_private * priv); -int libertas_sbi_unregister_dev(wlan_private *); -int libertas_sbi_get_int_status(wlan_private * priv, u8 *); -int libertas_sbi_register(void); -void libertas_sbi_unregister(void); -int libertas_sbi_prog_firmware(wlan_private *); - -int libertas_sbi_read_event_cause(wlan_private *); -int libertas_sbi_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb); -wlan_private *libertas_sbi_get_priv(void *card); - -#ifdef ENABLE_PM -int libertas_sbi_suspend(wlan_private *); -int libertas_sbi_resume(wlan_private *); -#endif - -#endif /* _SBI_H */ diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 3c0b1a2a172..c3043dcb541 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -8,6 +8,7 @@ #include <linux/if.h> #include <linux/netdevice.h> #include <linux/wireless.h> +#include <linux/etherdevice.h> #include <net/ieee80211.h> #include <net/iw_handler.h> @@ -58,12 +59,82 @@ //! Scan time specified in the channel TLV for each channel for active scans #define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100 -//! Macro to enable/disable SSID checking before storing a scan table -#ifdef DISCARD_BAD_SSID -#define CHECK_SSID_IS_VALID(x) ssid_valid(&bssidEntry.ssid) -#else -#define CHECK_SSID_IS_VALID(x) 1 -#endif +static const u8 zeromac[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const u8 bcastmac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + +static inline void clear_bss_descriptor (struct bss_descriptor * bss) +{ + /* Don't blow away ->list, just BSS data */ + memset(bss, 0, offsetof(struct bss_descriptor, list)); +} + +static inline int match_bss_no_security(struct wlan_802_11_security * secinfo, + struct bss_descriptor * match_bss) +{ + if ( !secinfo->wep_enabled + && !secinfo->WPAenabled + && !secinfo->WPA2enabled + && match_bss->wpa_ie[0] != WPA_IE + && match_bss->rsn_ie[0] != WPA2_IE + && !match_bss->privacy) { + return 1; + } + return 0; +} + +static inline int match_bss_static_wep(struct wlan_802_11_security * secinfo, + struct bss_descriptor * match_bss) +{ + if ( secinfo->wep_enabled + && !secinfo->WPAenabled + && !secinfo->WPA2enabled + && match_bss->privacy) { + return 1; + } + return 0; +} + +static inline int match_bss_wpa(struct wlan_802_11_security * secinfo, + struct bss_descriptor * match_bss) +{ + if ( !secinfo->wep_enabled + && secinfo->WPAenabled + && (match_bss->wpa_ie[0] == WPA_IE) + /* privacy bit may NOT be set in some APs like LinkSys WRT54G + && bss->privacy */ + ) { + return 1; + } + return 0; +} + +static inline int match_bss_wpa2(struct wlan_802_11_security * secinfo, + struct bss_descriptor * match_bss) +{ + if ( !secinfo->wep_enabled + && secinfo->WPA2enabled + && (match_bss->rsn_ie[0] == WPA2_IE) + /* privacy bit may NOT be set in some APs like LinkSys WRT54G + && bss->privacy */ + ) { + return 1; + } + return 0; +} + +static inline int match_bss_dynamic_wep(struct wlan_802_11_security * secinfo, + struct bss_descriptor * match_bss) +{ + if ( !secinfo->wep_enabled + && !secinfo->WPAenabled + && !secinfo->WPA2enabled + && (match_bss->wpa_ie[0] != WPA_IE) + && (match_bss->rsn_ie[0] != WPA2_IE) + && match_bss->privacy) { + return 1; + } + return 0; +} /** * @brief Check if a scanned network compatible with the driver settings @@ -84,180 +155,63 @@ * * @return Index in scantable, or error code if negative */ -static int is_network_compatible(wlan_adapter * adapter, int index, u8 mode) +static int is_network_compatible(wlan_adapter * adapter, + struct bss_descriptor * bss, u8 mode) { - ENTER(); - - if (adapter->scantable[index].mode == mode) { - if ( !adapter->secinfo.wep_enabled - && !adapter->secinfo.WPAenabled - && !adapter->secinfo.WPA2enabled - && adapter->scantable[index].wpa_ie[0] != WPA_IE - && adapter->scantable[index].rsn_ie[0] != WPA2_IE - && !adapter->scantable[index].privacy) { - /* no security */ - LEAVE(); - return index; - } else if ( adapter->secinfo.wep_enabled - && !adapter->secinfo.WPAenabled - && !adapter->secinfo.WPA2enabled - && adapter->scantable[index].privacy) { - /* static WEP enabled */ - LEAVE(); - return index; - } else if ( !adapter->secinfo.wep_enabled - && adapter->secinfo.WPAenabled - && !adapter->secinfo.WPA2enabled - && (adapter->scantable[index].wpa_ie[0] == WPA_IE) - /* privacy bit may NOT be set in some APs like LinkSys WRT54G - && adapter->scantable[index].privacy */ - ) { - /* WPA enabled */ - lbs_pr_debug(1, - "is_network_compatible() WPA: index=%d wpa_ie=%#x " - "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s " - "privacy=%#x\n", index, - adapter->scantable[index].wpa_ie[0], - adapter->scantable[index].rsn_ie[0], - adapter->secinfo.wep_enabled ? "e" : "d", - adapter->secinfo.WPAenabled ? "e" : "d", - adapter->secinfo.WPA2enabled ? "e" : "d", - adapter->scantable[index].privacy); - LEAVE(); - return index; - } else if ( !adapter->secinfo.wep_enabled - && !adapter->secinfo.WPAenabled - && adapter->secinfo.WPA2enabled - && (adapter->scantable[index].rsn_ie[0] == WPA2_IE) - /* privacy bit may NOT be set in some APs like LinkSys WRT54G - && adapter->scantable[index].privacy */ - ) { - /* WPA2 enabled */ - lbs_pr_debug(1, - "is_network_compatible() WPA2: index=%d wpa_ie=%#x " - "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s " - "privacy=%#x\n", index, - adapter->scantable[index].wpa_ie[0], - adapter->scantable[index].rsn_ie[0], - adapter->secinfo.wep_enabled ? "e" : "d", - adapter->secinfo.WPAenabled ? "e" : "d", - adapter->secinfo.WPA2enabled ? "e" : "d", - adapter->scantable[index].privacy); - LEAVE(); - return index; - } else if ( !adapter->secinfo.wep_enabled - && !adapter->secinfo.WPAenabled - && !adapter->secinfo.WPA2enabled - && (adapter->scantable[index].wpa_ie[0] != WPA_IE) - && (adapter->scantable[index].rsn_ie[0] != WPA2_IE) - && adapter->scantable[index].privacy) { - /* dynamic WEP enabled */ - lbs_pr_debug(1, - "is_network_compatible() dynamic WEP: index=%d " - "wpa_ie=%#x wpa2_ie=%#x privacy=%#x\n", - index, - adapter->scantable[index].wpa_ie[0], - adapter->scantable[index].rsn_ie[0], - adapter->scantable[index].privacy); - LEAVE(); - return index; - } - - /* security doesn't match */ - lbs_pr_debug(1, - "is_network_compatible() FAILED: index=%d wpa_ie=%#x " - "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s privacy=%#x\n", - index, - adapter->scantable[index].wpa_ie[0], - adapter->scantable[index].rsn_ie[0], + int matched = 0; + + lbs_deb_enter(LBS_DEB_ASSOC); + + if (bss->mode != mode) + goto done; + + if ((matched = match_bss_no_security(&adapter->secinfo, bss))) { + goto done; + } else if ((matched = match_bss_static_wep(&adapter->secinfo, bss))) { + goto done; + } else if ((matched = match_bss_wpa(&adapter->secinfo, bss))) { + lbs_deb_scan( + "is_network_compatible() WPA: wpa_ie=%#x " + "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s " + "privacy=%#x\n", bss->wpa_ie[0], bss->rsn_ie[0], adapter->secinfo.wep_enabled ? "e" : "d", adapter->secinfo.WPAenabled ? "e" : "d", adapter->secinfo.WPA2enabled ? "e" : "d", - adapter->scantable[index].privacy); - LEAVE(); - return -ECONNREFUSED; - } - - /* mode doesn't match */ - LEAVE(); - return -ENETUNREACH; -} - -/** - * @brief This function validates a SSID as being able to be printed - * - * @param pssid SSID structure to validate - * - * @return TRUE or FALSE - */ -static u8 ssid_valid(struct WLAN_802_11_SSID *pssid) -{ - int ssididx; - - for (ssididx = 0; ssididx < pssid->ssidlength; ssididx++) { - if (!isprint(pssid->ssid[ssididx])) { - return 0; - } - } - - return 1; -} - -/** - * @brief Post process the scan table after a new scan command has completed - * - * Inspect each entry of the scan table and try to find an entry that - * matches our current associated/joined network from the scan. If - * one is found, update the stored copy of the bssdescriptor for our - * current network. - * - * Debug dump the current scan table contents if compiled accordingly. - * - * @param priv A pointer to wlan_private structure - * - * @return void - */ -static void wlan_scan_process_results(wlan_private * priv) -{ - wlan_adapter *adapter = priv->adapter; - int foundcurrent; - int i; - - foundcurrent = 0; - - if (adapter->connect_status == libertas_connected) { - /* try to find the current BSSID in the new scan list */ - for (i = 0; i < adapter->numinscantable; i++) { - if (!libertas_SSID_cmp(&adapter->scantable[i].ssid, - &adapter->curbssparams.ssid) && - !memcmp(adapter->curbssparams.bssid, - adapter->scantable[i].macaddress, - ETH_ALEN)) { - foundcurrent = 1; - } - } - - if (foundcurrent) { - /* Make a copy of current BSSID descriptor */ - memcpy(&adapter->curbssparams.bssdescriptor, - &adapter->scantable[i], - sizeof(adapter->curbssparams.bssdescriptor)); - } + bss->privacy); + goto done; + } else if ((matched = match_bss_wpa2(&adapter->secinfo, bss))) { + lbs_deb_scan( + "is_network_compatible() WPA2: wpa_ie=%#x " + "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s " + "privacy=%#x\n", bss->wpa_ie[0], bss->rsn_ie[0], + adapter->secinfo.wep_enabled ? "e" : "d", + adapter->secinfo.WPAenabled ? "e" : "d", + adapter->secinfo.WPA2enabled ? "e" : "d", + bss->privacy); + goto done; + } else if ((matched = match_bss_dynamic_wep(&adapter->secinfo, bss))) { + lbs_deb_scan( + "is_network_compatible() dynamic WEP: " + "wpa_ie=%#x wpa2_ie=%#x privacy=%#x\n", + bss->wpa_ie[0], + bss->rsn_ie[0], + bss->privacy); + goto done; } - for (i = 0; i < adapter->numinscantable; i++) { - lbs_pr_debug(1, "Scan:(%02d) %02x:%02x:%02x:%02x:%02x:%02x, " - "RSSI[%03d], SSID[%s]\n", - i, - adapter->scantable[i].macaddress[0], - adapter->scantable[i].macaddress[1], - adapter->scantable[i].macaddress[2], - adapter->scantable[i].macaddress[3], - adapter->scantable[i].macaddress[4], - adapter->scantable[i].macaddress[5], - (s32) adapter->scantable[i].rssi, - adapter->scantable[i].ssid.ssid); - } + /* bss security settings don't match those configured on card */ + lbs_deb_scan( + "is_network_compatible() FAILED: wpa_ie=%#x " + "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s privacy=%#x\n", + bss->wpa_ie[0], bss->rsn_ie[0], + adapter->secinfo.wep_enabled ? "e" : "d", + adapter->secinfo.WPAenabled ? "e" : "d", + adapter->secinfo.WPA2enabled ? "e" : "d", + bss->privacy); + +done: + lbs_deb_leave(LBS_DEB_SCAN); + return matched; } /** @@ -338,14 +292,12 @@ static void wlan_scan_create_channel_list(wlan_private * priv, if (scantype == cmd_scan_type_passive) { scanchanlist[chanidx].maxscantime = - cpu_to_le16 - (MRVDRV_PASSIVE_SCAN_CHAN_TIME); + cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME); scanchanlist[chanidx].chanscanmode.passivescan = 1; } else { scanchanlist[chanidx].maxscantime = - cpu_to_le16 - (MRVDRV_ACTIVE_SCAN_CHAN_TIME); + cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME); scanchanlist[chanidx].chanscanmode.passivescan = 0; } @@ -408,13 +360,11 @@ wlan_scan_setup_scan_config(wlan_private * priv, u8 * pscancurrentonly) { wlan_adapter *adapter = priv->adapter; - const u8 zeromac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; struct mrvlietypes_numprobes *pnumprobestlv; struct mrvlietypes_ssidparamset *pssidtlv; struct wlan_scan_cmd_config * pscancfgout = NULL; u8 *ptlvpos; u16 numprobes; - u16 ssidlen; int chanidx; int scantype; int scandur; @@ -471,21 +421,18 @@ wlan_scan_setup_scan_config(wlan_private * priv, * Set the BSSID filter to the incoming configuration, * if non-zero. If not set, it will remain disabled (all zeros). */ - memcpy(pscancfgout->specificBSSID, - puserscanin->specificBSSID, - sizeof(pscancfgout->specificBSSID)); - - ssidlen = strlen(puserscanin->specificSSID); + memcpy(pscancfgout->bssid, puserscanin->bssid, + sizeof(pscancfgout->bssid)); - if (ssidlen) { + if (puserscanin->ssid_len) { pssidtlv = (struct mrvlietypes_ssidparamset *) pscancfgout-> tlvbuffer; pssidtlv->header.type = cpu_to_le16(TLV_TYPE_SSID); - pssidtlv->header.len = cpu_to_le16(ssidlen); - memcpy(pssidtlv->ssid, puserscanin->specificSSID, - ssidlen); - ptlvpos += sizeof(pssidtlv->header) + ssidlen; + pssidtlv->header.len = cpu_to_le16(puserscanin->ssid_len); + memcpy(pssidtlv->ssid, puserscanin->ssid, + puserscanin->ssid_len); + ptlvpos += sizeof(pssidtlv->header) + puserscanin->ssid_len; } /* @@ -494,8 +441,8 @@ wlan_scan_setup_scan_config(wlan_private * priv, * scan results. That is not an issue with an SSID or BSSID * filter applied to the scan results in the firmware. */ - if (ssidlen || (memcmp(pscancfgout->specificBSSID, - &zeromac, sizeof(zeromac)) != 0)) { + if ( puserscanin->ssid_len + || (compare_ether_addr(pscancfgout->bssid, &zeromac[0]) != 0)) { *pmaxchanperscan = MRVDRV_MAX_CHANNELS_PER_SCAN; *pfilteredscan = 1; } @@ -507,16 +454,11 @@ wlan_scan_setup_scan_config(wlan_private * priv, /* If the input config or adapter has the number of Probes set, add tlv */ if (numprobes) { pnumprobestlv = (struct mrvlietypes_numprobes *) ptlvpos; - pnumprobestlv->header.type = - cpu_to_le16(TLV_TYPE_NUMPROBES); - pnumprobestlv->header.len = sizeof(pnumprobestlv->numprobes); + pnumprobestlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES); + pnumprobestlv->header.len = cpu_to_le16(2); pnumprobestlv->numprobes = cpu_to_le16(numprobes); - ptlvpos += - sizeof(pnumprobestlv->header) + pnumprobestlv->header.len; - - pnumprobestlv->header.len = - cpu_to_le16(pnumprobestlv->header.len); + ptlvpos += sizeof(*pnumprobestlv); } /* @@ -529,7 +471,7 @@ wlan_scan_setup_scan_config(wlan_private * priv, if (puserscanin && puserscanin->chanlist[0].channumber) { - lbs_pr_debug(1, "Scan: Using supplied channel list\n"); + lbs_deb_scan("Scan: Using supplied channel list\n"); for (chanidx = 0; chanidx < WLAN_IOCTL_USER_SCAN_CHAN_MAX @@ -573,11 +515,11 @@ wlan_scan_setup_scan_config(wlan_private * priv, == priv->adapter->curbssparams.channel)) { *pscancurrentonly = 1; - lbs_pr_debug(1, "Scan: Scanning current channel only"); + lbs_deb_scan("Scan: Scanning current channel only"); } } else { - lbs_pr_debug(1, "Scan: Creating full region channel list\n"); + lbs_deb_scan("Scan: Creating full region channel list\n"); wlan_scan_create_channel_list(priv, pscanchanlist, *pfilteredscan); } @@ -613,7 +555,9 @@ static int wlan_scan_channel_list(wlan_private * priv, u8 filteredscan, struct wlan_scan_cmd_config * pscancfgout, struct mrvlietypes_chanlistparamset * pchantlvout, - struct chanscanparamset * pscanchanlist) + struct chanscanparamset * pscanchanlist, + const struct wlan_ioctl_user_scan_cfg * puserscanin, + int full_scan) { struct chanscanparamset *ptmpchan; struct chanscanparamset *pstartchan; @@ -621,11 +565,13 @@ static int wlan_scan_channel_list(wlan_private * priv, int doneearly; int tlvidx; int ret = 0; + int scanned = 0; + union iwreq_data wrqu; - ENTER(); + lbs_deb_enter(LBS_DEB_ASSOC); if (pscancfgout == 0 || pchantlvout == 0 || pscanchanlist == 0) { - lbs_pr_debug(1, "Scan: Null detect: %p, %p, %p\n", + lbs_deb_scan("Scan: Null detect: %p, %p, %p\n", pscancfgout, pchantlvout, pscanchanlist); return -1; } @@ -635,6 +581,9 @@ static int wlan_scan_channel_list(wlan_private * priv, /* Set the temp channel struct pointer to the start of the desired list */ ptmpchan = pscanchanlist; + if (priv->adapter->last_scanned_channel && !puserscanin) + ptmpchan += priv->adapter->last_scanned_channel; + /* Loop through the desired channel list, sending a new firmware scan * commands for each maxchanperscan channels (or for 1,6,11 individually * if configured accordingly) @@ -654,9 +603,9 @@ static int wlan_scan_channel_list(wlan_private * priv, * - doneearly is set (controlling individual scanning of 1,6,11) */ while (tlvidx < maxchanperscan && ptmpchan->channumber - && !doneearly) { + && !doneearly && scanned < 2) { - lbs_pr_debug(1, + lbs_deb_scan( "Scan: Chan(%3d), Radio(%d), mode(%d,%d), Dur(%d)\n", ptmpchan->channumber, ptmpchan->radiotype, ptmpchan->chanscanmode.passivescan, @@ -668,8 +617,11 @@ static int wlan_scan_channel_list(wlan_private * priv, ptmpchan, sizeof(pchantlvout->chanscanparam)); /* Increment the TLV header length by the size appended */ - pchantlvout->header.len += - sizeof(pchantlvout->chanscanparam); + /* Ew, it would be _so_ nice if we could just declare the + variable little-endian and let GCC handle it for us */ + pchantlvout->header.len = + cpu_to_le16(le16_to_cpu(pchantlvout->header.len) + + sizeof(pchantlvout->chanscanparam)); /* * The tlv buffer length is set to the number of bytes of the @@ -683,7 +635,7 @@ static int wlan_scan_channel_list(wlan_private * priv, /* Add the size of the channel tlv header and the data length */ pscancfgout->tlvbufferlen += (sizeof(pchantlvout->header) - + pchantlvout->header.len); + + le16_to_cpu(pchantlvout->header.len)); /* Increment the index to the channel tlv we are constructing */ tlvidx++; @@ -701,6 +653,7 @@ static int wlan_scan_channel_list(wlan_private * priv, /* Increment the tmp pointer to the next channel to be scanned */ ptmpchan++; + scanned++; /* Stop the loop if the *next* channel is in the 1,6,11 set. * This will cause it to be the only channel scanned on the next @@ -716,12 +669,71 @@ static int wlan_scan_channel_list(wlan_private * priv, /* Send the scan command to the firmware with the specified cfg */ ret = libertas_prepare_and_send_command(priv, cmd_802_11_scan, 0, 0, 0, pscancfgout); + if (scanned >= 2 && !full_scan) { + ret = 0; + goto done; + } + scanned = 0; } - LEAVE(); +done: + priv->adapter->last_scanned_channel = ptmpchan->channumber; + + /* Tell userspace the scan table has been updated */ + memset(&wrqu, 0, sizeof(union iwreq_data)); + wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL); + + lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); return ret; } +static void +clear_selected_scan_list_entries(wlan_adapter * adapter, + const struct wlan_ioctl_user_scan_cfg * scan_cfg) +{ + struct bss_descriptor * bss; + struct bss_descriptor * safe; + u32 clear_ssid_flag = 0, clear_bssid_flag = 0; + + if (!scan_cfg) + return; + + if (scan_cfg->clear_ssid && scan_cfg->ssid_len) + clear_ssid_flag = 1; + + if (scan_cfg->clear_bssid + && (compare_ether_addr(scan_cfg->bssid, &zeromac[0]) != 0) + && (compare_ether_addr(scan_cfg->bssid, &bcastmac[0]) != 0)) { + clear_bssid_flag = 1; + } + + if (!clear_ssid_flag && !clear_bssid_flag) + return; + + mutex_lock(&adapter->lock); + list_for_each_entry_safe (bss, safe, &adapter->network_list, list) { + u32 clear = 0; + + /* Check for an SSID match */ + if ( clear_ssid_flag + && (bss->ssid_len == scan_cfg->ssid_len) + && !memcmp(bss->ssid, scan_cfg->ssid, bss->ssid_len)) + clear = 1; + + /* Check for a BSSID match */ + if ( clear_bssid_flag + && !compare_ether_addr(bss->bssid, scan_cfg->bssid)) + clear = 1; + + if (clear) { + list_move_tail (&bss->list, &adapter->network_free_list); + clear_bss_descriptor(bss); + } + } + mutex_unlock(&adapter->lock); +} + + /** * @brief Internal function used to start a scan based on an input config * @@ -736,19 +748,23 @@ static int wlan_scan_channel_list(wlan_private * priv, * @return 0 or < 0 if error */ int wlan_scan_networks(wlan_private * priv, - const struct wlan_ioctl_user_scan_cfg * puserscanin) + const struct wlan_ioctl_user_scan_cfg * puserscanin, + int full_scan) { - wlan_adapter *adapter = priv->adapter; + wlan_adapter * adapter = priv->adapter; struct mrvlietypes_chanlistparamset *pchantlvout; struct chanscanparamset * scan_chan_list = NULL; struct wlan_scan_cmd_config * scan_cfg = NULL; - u8 keeppreviousscan; u8 filteredscan; u8 scancurrentchanonly; int maxchanperscan; int ret; +#ifdef CONFIG_LIBERTAS_DEBUG + struct bss_descriptor * iter_bss; + int i = 0; +#endif - ENTER(); + lbs_deb_enter(LBS_DEB_ASSOC); scan_chan_list = kzalloc(sizeof(struct chanscanparamset) * WLAN_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL); @@ -769,22 +785,14 @@ int wlan_scan_networks(wlan_private * priv, goto out; } - keeppreviousscan = 0; - - if (puserscanin) { - keeppreviousscan = puserscanin->keeppreviousscan; - } - - if (!keeppreviousscan) { - memset(adapter->scantable, 0x00, - sizeof(struct bss_descriptor) * MRVDRV_MAX_BSSID_LIST); - adapter->numinscantable = 0; - } + clear_selected_scan_list_entries(adapter, puserscanin); /* Keep the data path active if we are only scanning our current channel */ if (!scancurrentchanonly) { - netif_stop_queue(priv->wlan_dev.netdev); - netif_carrier_off(priv->wlan_dev.netdev); + netif_stop_queue(priv->dev); + netif_carrier_off(priv->dev); + netif_stop_queue(priv->mesh_dev); + netif_carrier_off(priv->mesh_dev); } ret = wlan_scan_channel_list(priv, @@ -792,17 +800,26 @@ int wlan_scan_networks(wlan_private * priv, filteredscan, scan_cfg, pchantlvout, - scan_chan_list); - - /* Process the resulting scan table: - * - Remove any bad ssids - * - Update our current BSS information from scan data - */ - wlan_scan_process_results(priv); + scan_chan_list, + puserscanin, + full_scan); + +#ifdef CONFIG_LIBERTAS_DEBUG + /* Dump the scan table */ + mutex_lock(&adapter->lock); + list_for_each_entry (iter_bss, &adapter->network_list, list) { + lbs_deb_scan("Scan:(%02d) " MAC_FMT ", RSSI[%03d], SSID[%s]\n", + i++, MAC_ARG(iter_bss->bssid), (s32) iter_bss->rssi, + escape_essid(iter_bss->ssid, iter_bss->ssid_len)); + } + mutex_unlock(&adapter->lock); +#endif if (priv->adapter->connect_status == libertas_connected) { - netif_carrier_on(priv->wlan_dev.netdev); - netif_wake_queue(priv->wlan_dev.netdev); + netif_carrier_on(priv->dev); + netif_wake_queue(priv->dev); + netif_carrier_on(priv->mesh_dev); + netif_wake_queue(priv->mesh_dev); } out: @@ -812,7 +829,7 @@ out: if (scan_chan_list) kfree(scan_chan_list); - LEAVE(); + lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); return ret; } @@ -843,7 +860,7 @@ void wlan_ret_802_11_scan_get_tlv_ptrs(struct mrvlietypes_data * ptlv, tlvbufleft = tlvbufsize; *ptsftlv = NULL; - lbs_pr_debug(1, "SCAN_RESP: tlvbufsize = %d\n", tlvbufsize); + lbs_deb_scan("SCAN_RESP: tlvbufsize = %d\n", tlvbufsize); lbs_dbg_hex("SCAN_RESP: TLV Buf", (u8 *) ptlv, tlvbufsize); while (tlvbufleft >= sizeof(struct mrvlietypesheader)) { @@ -856,7 +873,7 @@ void wlan_ret_802_11_scan_get_tlv_ptrs(struct mrvlietypes_data * ptlv, break; default: - lbs_pr_debug(1, "SCAN_RESP: Unhandled TLV = %d\n", + lbs_deb_scan("SCAN_RESP: Unhandled TLV = %d\n", tlvtype); /* Give up, this seems corrupted */ return; @@ -875,12 +892,12 @@ void wlan_ret_802_11_scan_get_tlv_ptrs(struct mrvlietypes_data * ptlv, * response or beacon from the scan command. Record information as needed * in the scan table struct bss_descriptor for that entry. * - * @param pBSSIDEntry Output parameter: Pointer to the BSS Entry + * @param bss Output parameter: Pointer to the BSS Entry * * @return 0 or -1 */ -static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry, - u8 ** pbeaconinfo, int *bytesleft) +static int libertas_process_bss(struct bss_descriptor * bss, + u8 ** pbeaconinfo, int *bytesleft) { enum ieeetypes_elementid elemID; struct ieeetypes_fhparamset *pFH; @@ -897,13 +914,14 @@ static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry, u16 beaconsize; u8 founddatarateie; int bytesleftforcurrentbeacon; + int ret; struct IE_WPA *pIe; const u8 oui01[4] = { 0x00, 0x50, 0xf2, 0x01 }; struct ieeetypes_countryinfoset *pcountryinfo; - ENTER(); + lbs_deb_enter(LBS_DEB_ASSOC); founddatarateie = 0; ratesize = 0; @@ -911,8 +929,7 @@ static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry, if (*bytesleft >= sizeof(beaconsize)) { /* Extract & convert beacon size from the command buffer */ - memcpy(&beaconsize, *pbeaconinfo, sizeof(beaconsize)); - beaconsize = le16_to_cpu(beaconsize); + beaconsize = le16_to_cpup((void *)*pbeaconinfo); *bytesleft -= sizeof(beaconsize); *pbeaconinfo += sizeof(beaconsize); } @@ -934,17 +951,14 @@ static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry, bytesleftforcurrentbeacon = beaconsize; - memcpy(pBSSEntry->macaddress, pcurrentptr, ETH_ALEN); - lbs_pr_debug(1, "InterpretIE: AP MAC Addr-%x:%x:%x:%x:%x:%x\n", - pBSSEntry->macaddress[0], pBSSEntry->macaddress[1], - pBSSEntry->macaddress[2], pBSSEntry->macaddress[3], - pBSSEntry->macaddress[4], pBSSEntry->macaddress[5]); + memcpy(bss->bssid, pcurrentptr, ETH_ALEN); + lbs_deb_scan("process_bss: AP BSSID " MAC_FMT "\n", MAC_ARG(bss->bssid)); pcurrentptr += ETH_ALEN; bytesleftforcurrentbeacon -= ETH_ALEN; if (bytesleftforcurrentbeacon < 12) { - lbs_pr_debug(1, "InterpretIE: Not enough bytes left\n"); + lbs_deb_scan("process_bss: Not enough bytes left\n"); return -1; } @@ -954,51 +968,48 @@ static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry, */ /* RSSI is 1 byte long */ - pBSSEntry->rssi = le32_to_cpu((long)(*pcurrentptr)); - lbs_pr_debug(1, "InterpretIE: RSSI=%02X\n", *pcurrentptr); + bss->rssi = *pcurrentptr; + lbs_deb_scan("process_bss: RSSI=%02X\n", *pcurrentptr); pcurrentptr += 1; bytesleftforcurrentbeacon -= 1; /* time stamp is 8 bytes long */ - memcpy(fixedie.timestamp, pcurrentptr, 8); - memcpy(pBSSEntry->timestamp, pcurrentptr, 8); + fixedie.timestamp = bss->timestamp = le64_to_cpup((void *)pcurrentptr); pcurrentptr += 8; bytesleftforcurrentbeacon -= 8; /* beacon interval is 2 bytes long */ - memcpy(&fixedie.beaconinterval, pcurrentptr, 2); - pBSSEntry->beaconperiod = le16_to_cpu(fixedie.beaconinterval); + fixedie.beaconinterval = bss->beaconperiod = le16_to_cpup((void *)pcurrentptr); pcurrentptr += 2; bytesleftforcurrentbeacon -= 2; /* capability information is 2 bytes long */ - memcpy(&fixedie.capabilities, pcurrentptr, 2); - lbs_pr_debug(1, "InterpretIE: fixedie.capabilities=0x%X\n", + memcpy(&fixedie.capabilities, pcurrentptr, 2); + lbs_deb_scan("process_bss: fixedie.capabilities=0x%X\n", fixedie.capabilities); - fixedie.capabilities = le16_to_cpu(fixedie.capabilities); pcap = (struct ieeetypes_capinfo *) & fixedie.capabilities; - memcpy(&pBSSEntry->cap, pcap, sizeof(struct ieeetypes_capinfo)); + memcpy(&bss->cap, pcap, sizeof(struct ieeetypes_capinfo)); pcurrentptr += 2; bytesleftforcurrentbeacon -= 2; /* rest of the current buffer are IE's */ - lbs_pr_debug(1, "InterpretIE: IElength for this AP = %d\n", + lbs_deb_scan("process_bss: IE length for this AP = %d\n", bytesleftforcurrentbeacon); - lbs_dbg_hex("InterpretIE: IE info", (u8 *) pcurrentptr, + lbs_dbg_hex("process_bss: IE info", (u8 *) pcurrentptr, bytesleftforcurrentbeacon); if (pcap->privacy) { - lbs_pr_debug(1, "InterpretIE: AP WEP enabled\n"); - pBSSEntry->privacy = wlan802_11privfilter8021xWEP; + lbs_deb_scan("process_bss: AP WEP enabled\n"); + bss->privacy = wlan802_11privfilter8021xWEP; } else { - pBSSEntry->privacy = wlan802_11privfilteracceptall; + bss->privacy = wlan802_11privfilteracceptall; } if (pcap->ibss == 1) { - pBSSEntry->mode = IW_MODE_ADHOC; + bss->mode = IW_MODE_ADHOC; } else { - pBSSEntry->mode = IW_MODE_INFRA; + bss->mode = IW_MODE_INFRA; } /* process variable IE */ @@ -1007,94 +1018,83 @@ static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry, elemlen = *((u8 *) pcurrentptr + 1); if (bytesleftforcurrentbeacon < elemlen) { - lbs_pr_debug(1, "InterpretIE: error in processing IE, " + lbs_deb_scan("process_bss: error in processing IE, " "bytes left < IE length\n"); bytesleftforcurrentbeacon = 0; continue; } switch (elemID) { - case SSID: - pBSSEntry->ssid.ssidlength = elemlen; - memcpy(pBSSEntry->ssid.ssid, (pcurrentptr + 2), - elemlen); - lbs_pr_debug(1, "ssid: %32s", pBSSEntry->ssid.ssid); + bss->ssid_len = elemlen; + memcpy(bss->ssid, (pcurrentptr + 2), elemlen); + lbs_deb_scan("ssid '%s', ssid length %u\n", + escape_essid(bss->ssid, bss->ssid_len), + bss->ssid_len); break; case SUPPORTED_RATES: - memcpy(pBSSEntry->datarates, (pcurrentptr + 2), - elemlen); - memmove(pBSSEntry->libertas_supported_rates, (pcurrentptr + 2), + memcpy(bss->datarates, (pcurrentptr + 2), elemlen); + memmove(bss->libertas_supported_rates, (pcurrentptr + 2), elemlen); ratesize = elemlen; founddatarateie = 1; break; case EXTRA_IE: - lbs_pr_debug(1, "InterpretIE: EXTRA_IE Found!\n"); - pBSSEntry->extra_ie = 1; + lbs_deb_scan("process_bss: EXTRA_IE Found!\n"); break; case FH_PARAM_SET: pFH = (struct ieeetypes_fhparamset *) pcurrentptr; - memmove(&pBSSEntry->phyparamset.fhparamset, pFH, + memmove(&bss->phyparamset.fhparamset, pFH, sizeof(struct ieeetypes_fhparamset)); - pBSSEntry->phyparamset.fhparamset.dwelltime - = - le16_to_cpu(pBSSEntry->phyparamset.fhparamset. - dwelltime); +#if 0 /* I think we can store these LE */ + bss->phyparamset.fhparamset.dwelltime + = le16_to_cpu(bss->phyparamset.fhparamset.dwelltime); +#endif break; case DS_PARAM_SET: pDS = (struct ieeetypes_dsparamset *) pcurrentptr; - - pBSSEntry->channel = pDS->currentchan; - - memcpy(&pBSSEntry->phyparamset.dsparamset, pDS, + bss->channel = pDS->currentchan; + memcpy(&bss->phyparamset.dsparamset, pDS, sizeof(struct ieeetypes_dsparamset)); break; case CF_PARAM_SET: pCF = (struct ieeetypes_cfparamset *) pcurrentptr; - - memcpy(&pBSSEntry->ssparamset.cfparamset, pCF, + memcpy(&bss->ssparamset.cfparamset, pCF, sizeof(struct ieeetypes_cfparamset)); break; case IBSS_PARAM_SET: pibss = (struct ieeetypes_ibssparamset *) pcurrentptr; - pBSSEntry->atimwindow = - le32_to_cpu(pibss->atimwindow); - - memmove(&pBSSEntry->ssparamset.ibssparamset, pibss, + bss->atimwindow = le32_to_cpu(pibss->atimwindow); + memmove(&bss->ssparamset.ibssparamset, pibss, sizeof(struct ieeetypes_ibssparamset)); - - pBSSEntry->ssparamset.ibssparamset.atimwindow - = - le16_to_cpu(pBSSEntry->ssparamset.ibssparamset. - atimwindow); +#if 0 + bss->ssparamset.ibssparamset.atimwindow + = le16_to_cpu(bss->ssparamset.ibssparamset.atimwindow); +#endif break; /* Handle Country Info IE */ case COUNTRY_INFO: - pcountryinfo = - (struct ieeetypes_countryinfoset *) pcurrentptr; - - if (pcountryinfo->len < - sizeof(pcountryinfo->countrycode) + pcountryinfo = (struct ieeetypes_countryinfoset *) pcurrentptr; + if (pcountryinfo->len < sizeof(pcountryinfo->countrycode) || pcountryinfo->len > 254) { - lbs_pr_debug(1, "InterpretIE: 11D- Err " + lbs_deb_scan("process_bss: 11D- Err " "CountryInfo len =%d min=%zd max=254\n", pcountryinfo->len, sizeof(pcountryinfo->countrycode)); - LEAVE(); - return -1; + ret = -1; + goto done; } - memcpy(&pBSSEntry->countryinfo, + memcpy(&bss->countryinfo, pcountryinfo, pcountryinfo->len + 2); - lbs_dbg_hex("InterpretIE: 11D- CountryInfo:", + lbs_dbg_hex("process_bss: 11D- CountryInfo:", (u8 *) pcountryinfo, (u32) (pcountryinfo->len + 2)); break; @@ -1114,12 +1114,10 @@ static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry, bytestocopy = elemlen; } - pRate = (u8 *) pBSSEntry->datarates; + pRate = (u8 *) bss->datarates; pRate += ratesize; memmove(pRate, (pcurrentptr + 2), bytestocopy); - - pRate = (u8 *) pBSSEntry->libertas_supported_rates; - + pRate = (u8 *) bss->libertas_supported_rates; pRate += ratesize; memmove(pRate, (pcurrentptr + 2), bytestocopy); } @@ -1132,24 +1130,17 @@ static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry, if (memcmp(pIe->oui, oui01, sizeof(oui01))) break; - pBSSEntry->wpa_ie_len = min_t(size_t, - elemlen + IE_ID_LEN_FIELDS_BYTES, - sizeof(pBSSEntry->wpa_ie)); - memcpy(pBSSEntry->wpa_ie, pcurrentptr, - pBSSEntry->wpa_ie_len); - lbs_dbg_hex("InterpretIE: Resp WPA_IE", - pBSSEntry->wpa_ie, elemlen); + bss->wpa_ie_len = min(elemlen + IE_ID_LEN_FIELDS_BYTES, + MAX_WPA_IE_LEN); + memcpy(bss->wpa_ie, pcurrentptr, bss->wpa_ie_len); + lbs_dbg_hex("process_bss: WPA IE", bss->wpa_ie, elemlen); break; case WPA2_IE: pIe = (struct IE_WPA *)pcurrentptr; - - pBSSEntry->rsn_ie_len = min_t(size_t, - elemlen + IE_ID_LEN_FIELDS_BYTES, - sizeof(pBSSEntry->rsn_ie)); - memcpy(pBSSEntry->rsn_ie, pcurrentptr, - pBSSEntry->rsn_ie_len); - lbs_dbg_hex("InterpretIE: Resp WPA2_IE", - pBSSEntry->rsn_ie, elemlen); + bss->rsn_ie_len = min(elemlen + IE_ID_LEN_FIELDS_BYTES, + MAX_WPA_IE_LEN); + memcpy(bss->rsn_ie, pcurrentptr, bss->rsn_ie_len); + lbs_dbg_hex("process_bss: RSN_IE", bss->rsn_ie, elemlen); break; case TIM: break; @@ -1165,7 +1156,14 @@ static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry, } /* while (bytesleftforcurrentbeacon > 2) */ - return 0; + /* Timestamp */ + bss->last_scanned = jiffies; + + ret = 0; + +done: + lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); + return ret; } /** @@ -1176,15 +1174,12 @@ static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry, * * @return 0--ssid is same, otherwise is different */ -int libertas_SSID_cmp(struct WLAN_802_11_SSID *ssid1, struct WLAN_802_11_SSID *ssid2) +int libertas_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len) { - if (!ssid1 || !ssid2) - return -1; - - if (ssid1->ssidlength != ssid2->ssidlength) + if (ssid1_len != ssid2_len) return -1; - return memcmp(ssid1->ssid, ssid2->ssid, ssid1->ssidlength); + return memcmp(ssid1, ssid2, ssid1_len); } /** @@ -1196,38 +1191,41 @@ int libertas_SSID_cmp(struct WLAN_802_11_SSID *ssid1, struct WLAN_802_11_SSID *s * * @return index in BSSID list, or error return code (< 0) */ -int libertas_find_BSSID_in_list(wlan_adapter * adapter, u8 * bssid, u8 mode) +struct bss_descriptor * libertas_find_bssid_in_list(wlan_adapter * adapter, + u8 * bssid, u8 mode) { - int ret = -ENETUNREACH; - int i; + struct bss_descriptor * iter_bss; + struct bss_descriptor * found_bss = NULL; if (!bssid) - return -EFAULT; + return NULL; - lbs_pr_debug(1, "FindBSSID: Num of BSSIDs = %d\n", - adapter->numinscantable); + lbs_dbg_hex("libertas_find_BSSID_in_list: looking for ", + bssid, ETH_ALEN); - /* Look through the scan table for a compatible match. The ret return - * variable will be equal to the index in the scan table (greater - * than zero) if the network is compatible. The loop will continue - * past a matched bssid that is not compatible in case there is an - * AP with multiple SSIDs assigned to the same BSSID + /* Look through the scan table for a compatible match. The loop will + * continue past a matched bssid that is not compatible in case there + * is an AP with multiple SSIDs assigned to the same BSSID */ - for (i = 0; ret < 0 && i < adapter->numinscantable; i++) { - if (!memcmp(adapter->scantable[i].macaddress, bssid, ETH_ALEN)) { - switch (mode) { - case IW_MODE_INFRA: - case IW_MODE_ADHOC: - ret = is_network_compatible(adapter, i, mode); - break; - default: - ret = i; + mutex_lock(&adapter->lock); + list_for_each_entry (iter_bss, &adapter->network_list, list) { + if (compare_ether_addr(iter_bss->bssid, bssid)) + continue; /* bssid doesn't match */ + switch (mode) { + case IW_MODE_INFRA: + case IW_MODE_ADHOC: + if (!is_network_compatible(adapter, iter_bss, mode)) break; - } + found_bss = iter_bss; + break; + default: + found_bss = iter_bss; + break; } } + mutex_unlock(&adapter->lock); - return ret; + return found_bss; } /** @@ -1240,61 +1238,60 @@ int libertas_find_BSSID_in_list(wlan_adapter * adapter, u8 * bssid, u8 mode) * * @return index in BSSID list */ -int libertas_find_SSID_in_list(wlan_adapter * adapter, - struct WLAN_802_11_SSID *ssid, u8 * bssid, u8 mode) +struct bss_descriptor * libertas_find_ssid_in_list(wlan_adapter * adapter, + u8 *ssid, u8 ssid_len, u8 * bssid, u8 mode, + int channel) { - int net = -ENETUNREACH; u8 bestrssi = 0; - int i; - int j; + struct bss_descriptor * iter_bss = NULL; + struct bss_descriptor * found_bss = NULL; + struct bss_descriptor * tmp_oldest = NULL; - lbs_pr_debug(1, "Num of Entries in Table = %d\n", adapter->numinscantable); - - for (i = 0; i < adapter->numinscantable; i++) { - if (!libertas_SSID_cmp(&adapter->scantable[i].ssid, ssid) && - (!bssid || - !memcmp(adapter->scantable[i]. - macaddress, bssid, ETH_ALEN))) { - switch (mode) { - case IW_MODE_INFRA: - case IW_MODE_ADHOC: - j = is_network_compatible(adapter, i, mode); - - if (j >= 0) { - if (bssid) { - return i; - } - - if (SCAN_RSSI - (adapter->scantable[i].rssi) - > bestrssi) { - bestrssi = - SCAN_RSSI(adapter-> - scantable[i]. - rssi); - net = i; - } - } else { - if (net == -ENETUNREACH) { - net = j; - } - } - break; - case IW_MODE_AUTO: - default: - if (SCAN_RSSI(adapter->scantable[i].rssi) - > bestrssi) { - bestrssi = - SCAN_RSSI(adapter->scantable[i]. - rssi); - net = i; - } + mutex_lock(&adapter->lock); + + list_for_each_entry (iter_bss, &adapter->network_list, list) { + if ( !tmp_oldest + || (iter_bss->last_scanned < tmp_oldest->last_scanned)) + tmp_oldest = iter_bss; + + if (libertas_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len, + ssid, ssid_len) != 0) + continue; /* ssid doesn't match */ + if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0) + continue; /* bssid doesn't match */ + if ((channel > 0) && (iter_bss->channel != channel)) + continue; /* channel doesn't match */ + + switch (mode) { + case IW_MODE_INFRA: + case IW_MODE_ADHOC: + if (!is_network_compatible(adapter, iter_bss, mode)) break; + + if (bssid) { + /* Found requested BSSID */ + found_bss = iter_bss; + goto out; + } + + if (SCAN_RSSI(iter_bss->rssi) > bestrssi) { + bestrssi = SCAN_RSSI(iter_bss->rssi); + found_bss = iter_bss; } + break; + case IW_MODE_AUTO: + default: + if (SCAN_RSSI(iter_bss->rssi) > bestrssi) { + bestrssi = SCAN_RSSI(iter_bss->rssi); + found_bss = iter_bss; + } + break; } } - return net; +out: + mutex_unlock(&adapter->lock); + return found_bss; } /** @@ -1307,43 +1304,38 @@ int libertas_find_SSID_in_list(wlan_adapter * adapter, * * @return index in BSSID list */ -int libertas_find_best_SSID_in_list(wlan_adapter * adapter, u8 mode) +struct bss_descriptor * libertas_find_best_ssid_in_list(wlan_adapter * adapter, + u8 mode) { - int bestnet = -ENETUNREACH; u8 bestrssi = 0; - int i; - - ENTER(); + struct bss_descriptor * iter_bss; + struct bss_descriptor * best_bss = NULL; - lbs_pr_debug(1, "Num of BSSIDs = %d\n", adapter->numinscantable); + mutex_lock(&adapter->lock); - for (i = 0; i < adapter->numinscantable; i++) { + list_for_each_entry (iter_bss, &adapter->network_list, list) { switch (mode) { case IW_MODE_INFRA: case IW_MODE_ADHOC: - if (is_network_compatible(adapter, i, mode) >= 0) { - if (SCAN_RSSI(adapter->scantable[i].rssi) > - bestrssi) { - bestrssi = - SCAN_RSSI(adapter->scantable[i]. - rssi); - bestnet = i; - } - } + if (!is_network_compatible(adapter, iter_bss, mode)) + break; + if (SCAN_RSSI(iter_bss->rssi) <= bestrssi) + break; + bestrssi = SCAN_RSSI(iter_bss->rssi); + best_bss = iter_bss; break; case IW_MODE_AUTO: default: - if (SCAN_RSSI(adapter->scantable[i].rssi) > bestrssi) { - bestrssi = - SCAN_RSSI(adapter->scantable[i].rssi); - bestnet = i; - } + if (SCAN_RSSI(iter_bss->rssi) <= bestrssi) + break; + bestrssi = SCAN_RSSI(iter_bss->rssi); + best_bss = iter_bss; break; } } - LEAVE(); - return bestnet; + mutex_unlock(&adapter->lock); + return best_bss; } /** @@ -1354,41 +1346,30 @@ int libertas_find_best_SSID_in_list(wlan_adapter * adapter, u8 mode) * * @return 0--success, otherwise--fail */ -int libertas_find_best_network_SSID(wlan_private * priv, - struct WLAN_802_11_SSID *pSSID, - u8 preferred_mode, u8 *out_mode) +int libertas_find_best_network_ssid(wlan_private * priv, + u8 *out_ssid, u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode) { wlan_adapter *adapter = priv->adapter; - int ret = 0; - struct bss_descriptor *preqbssid; - int i; + int ret = -1; + struct bss_descriptor * found; - ENTER(); + lbs_deb_enter(LBS_DEB_ASSOC); - memset(pSSID, 0, sizeof(struct WLAN_802_11_SSID)); - - wlan_scan_networks(priv, NULL); + wlan_scan_networks(priv, NULL, 1); if (adapter->surpriseremoved) return -1; - wait_event_interruptible(adapter->cmd_pending, !adapter->nr_cmd_pending); - i = libertas_find_best_SSID_in_list(adapter, preferred_mode); - if (i < 0) { - ret = -1; - goto out; - } - - preqbssid = &adapter->scantable[i]; - memcpy(pSSID, &preqbssid->ssid, - sizeof(struct WLAN_802_11_SSID)); - *out_mode = preqbssid->mode; + wait_event_interruptible(adapter->cmd_pending, !adapter->nr_cmd_pending); - if (!pSSID->ssidlength) { - ret = -1; + found = libertas_find_best_ssid_in_list(adapter, preferred_mode); + if (found && (found->ssid_len > 0)) { + memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE); + *out_ssid_len = found->ssid_len; + *out_mode = found->mode; + ret = 0; } -out: - LEAVE(); + lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); return ret; } @@ -1407,20 +1388,15 @@ int libertas_set_scan(struct net_device *dev, struct iw_request_info *info, { wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; - union iwreq_data wrqu; - ENTER(); + lbs_deb_enter(LBS_DEB_SCAN); - if (!wlan_scan_networks(priv, NULL)) { - memset(&wrqu, 0, sizeof(union iwreq_data)); - wireless_send_event(priv->wlan_dev.netdev, SIOCGIWSCAN, &wrqu, - NULL); - } + wlan_scan_networks(priv, NULL, 0); if (adapter->surpriseremoved) return -1; - LEAVE(); + lbs_deb_leave(LBS_DEB_SCAN); return 0; } @@ -1433,32 +1409,31 @@ int libertas_set_scan(struct net_device *dev, struct iw_request_info *info, * * @return 0-success, otherwise fail */ -int libertas_send_specific_SSID_scan(wlan_private * priv, - struct WLAN_802_11_SSID *prequestedssid, - u8 keeppreviousscan) +int libertas_send_specific_ssid_scan(wlan_private * priv, + u8 *ssid, u8 ssid_len, u8 clear_ssid) { wlan_adapter *adapter = priv->adapter; struct wlan_ioctl_user_scan_cfg scancfg; + int ret = 0; - ENTER(); + lbs_deb_enter(LBS_DEB_ASSOC); - if (prequestedssid == NULL) { - return -1; - } + if (!ssid_len) + goto out; memset(&scancfg, 0x00, sizeof(scancfg)); + memcpy(scancfg.ssid, ssid, ssid_len); + scancfg.ssid_len = ssid_len; + scancfg.clear_ssid = clear_ssid; - memcpy(scancfg.specificSSID, prequestedssid->ssid, - prequestedssid->ssidlength); - scancfg.keeppreviousscan = keeppreviousscan; - - wlan_scan_networks(priv, &scancfg); + wlan_scan_networks(priv, &scancfg, 1); if (adapter->surpriseremoved) return -1; wait_event_interruptible(adapter->cmd_pending, !adapter->nr_cmd_pending); - LEAVE(); - return 0; +out: + lbs_deb_leave(LBS_DEB_ASSOC); + return ret; } /** @@ -1470,304 +1445,235 @@ int libertas_send_specific_SSID_scan(wlan_private * priv, * * @return 0-success, otherwise fail */ -int libertas_send_specific_BSSID_scan(wlan_private * priv, u8 * bssid, u8 keeppreviousscan) +int libertas_send_specific_bssid_scan(wlan_private * priv, u8 * bssid, u8 clear_bssid) { struct wlan_ioctl_user_scan_cfg scancfg; - ENTER(); + lbs_deb_enter(LBS_DEB_ASSOC); - if (bssid == NULL) { - return -1; - } + if (bssid == NULL) + goto out; memset(&scancfg, 0x00, sizeof(scancfg)); - memcpy(scancfg.specificBSSID, bssid, sizeof(scancfg.specificBSSID)); - scancfg.keeppreviousscan = keeppreviousscan; + memcpy(scancfg.bssid, bssid, ETH_ALEN); + scancfg.clear_bssid = clear_bssid; - wlan_scan_networks(priv, &scancfg); + wlan_scan_networks(priv, &scancfg, 1); if (priv->adapter->surpriseremoved) return -1; wait_event_interruptible(priv->adapter->cmd_pending, !priv->adapter->nr_cmd_pending); - LEAVE(); +out: + lbs_deb_leave(LBS_DEB_ASSOC); return 0; } -/** - * @brief Retrieve the scan table entries via wireless tools IOCTL call - * - * @param dev A pointer to net_device structure - * @param info A pointer to iw_request_info structure - * @param dwrq A pointer to iw_point structure - * @param extra A pointer to extra data buf - * - * @return 0 --success, otherwise fail - */ -int libertas_get_scan(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra) +static inline char *libertas_translate_scan(wlan_private *priv, + char *start, char *stop, + struct bss_descriptor *bss) { - wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; - int ret = 0; - char *current_ev = extra; - char *end_buf = extra + IW_SCAN_MAX_DATA; struct chan_freq_power *cfp; - struct bss_descriptor *pscantable; char *current_val; /* For rates */ struct iw_event iwe; /* Temporary buffer */ - int i; int j; - int rate; #define PERFECT_RSSI ((u8)50) #define WORST_RSSI ((u8)0) #define RSSI_DIFF ((u8)(PERFECT_RSSI - WORST_RSSI)) u8 rssi; - u8 buf[16 + 256 * 2]; - u8 *ptr; - - ENTER(); - - /* - * if there's either commands in the queue or one being - * processed return -EAGAIN for iwlist to retry later. - */ - if (adapter->nr_cmd_pending) - return -EAGAIN; - - if (adapter->connect_status == libertas_connected) - lbs_pr_debug(1, "Current ssid: %32s\n", - adapter->curbssparams.ssid.ssid); + cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, bss->channel); + if (!cfp) { + lbs_deb_scan("Invalid channel number %d\n", bss->channel); + return NULL; + } - lbs_pr_debug(1, "Scan: Get: numinscantable = %d\n", - adapter->numinscantable); + /* First entry *MUST* be the AP BSSID */ + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe.u.ap_addr.sa_data, &bss->bssid, ETH_ALEN); + start = iwe_stream_add_event(start, stop, &iwe, IW_EV_ADDR_LEN); + + /* SSID */ + iwe.cmd = SIOCGIWESSID; + iwe.u.data.flags = 1; + iwe.u.data.length = min((u32) bss->ssid_len, (u32) IW_ESSID_MAX_SIZE); + start = iwe_stream_add_point(start, stop, &iwe, bss->ssid); + + /* Mode */ + iwe.cmd = SIOCGIWMODE; + iwe.u.mode = bss->mode; + start = iwe_stream_add_event(start, stop, &iwe, IW_EV_UINT_LEN); + + /* Frequency */ + iwe.cmd = SIOCGIWFREQ; + iwe.u.freq.m = (long)cfp->freq * 100000; + iwe.u.freq.e = 1; + start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN); + + /* Add quality statistics */ + iwe.cmd = IWEVQUAL; + iwe.u.qual.updated = IW_QUAL_ALL_UPDATED; + iwe.u.qual.level = SCAN_RSSI(bss->rssi); + + rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE; + iwe.u.qual.qual = + (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) * + (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) / + (RSSI_DIFF * RSSI_DIFF); + if (iwe.u.qual.qual > 100) + iwe.u.qual.qual = 100; + + if (adapter->NF[TYPE_BEACON][TYPE_NOAVG] == 0) { + iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE; + } else { + iwe.u.qual.noise = + CAL_NF(adapter->NF[TYPE_BEACON][TYPE_NOAVG]); + } - /* The old API using SIOCGIWAPLIST had a hard limit of IW_MAX_AP. - * The new API using SIOCGIWSCAN is only limited by buffer size - * WE-14 -> WE-16 the buffer is limited to IW_SCAN_MAX_DATA bytes - * which is 4096. + /* Locally created ad-hoc BSSs won't have beacons if this is the + * only station in the adhoc network; so get signal strength + * from receive statistics. */ - for (i = 0; i < adapter->numinscantable; i++) { - if ((current_ev + MAX_SCAN_CELL_SIZE) >= end_buf) { - lbs_pr_debug(1, "i=%d break out: current_ev=%p end_buf=%p " - "MAX_SCAN_CELL_SIZE=%zd\n", - i, current_ev, end_buf, MAX_SCAN_CELL_SIZE); - break; - } - - pscantable = &adapter->scantable[i]; - - lbs_pr_debug(1, "i=%d ssid: %32s\n", i, pscantable->ssid.ssid); - - cfp = - libertas_find_cfp_by_band_and_channel(adapter, 0, - pscantable->channel); - if (!cfp) { - lbs_pr_debug(1, "Invalid channel number %d\n", - pscantable->channel); - continue; - } - - if (!ssid_valid(&adapter->scantable[i].ssid)) { - continue; - } - - /* First entry *MUST* be the AP MAC address */ - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, - &adapter->scantable[i].macaddress, ETH_ALEN); - - iwe.len = IW_EV_ADDR_LEN; - current_ev = - iwe_stream_add_event(current_ev, end_buf, &iwe, iwe.len); - - //Add the ESSID - iwe.u.data.length = adapter->scantable[i].ssid.ssidlength; - - if (iwe.u.data.length > 32) { - iwe.u.data.length = 32; - } - - iwe.cmd = SIOCGIWESSID; - iwe.u.data.flags = 1; - iwe.len = IW_EV_POINT_LEN + iwe.u.data.length; - current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, - adapter->scantable[i].ssid. - ssid); - - //Add mode - iwe.cmd = SIOCGIWMODE; - iwe.u.mode = adapter->scantable[i].mode; - iwe.len = IW_EV_UINT_LEN; - current_ev = - iwe_stream_add_event(current_ev, end_buf, &iwe, iwe.len); - - //frequency - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = (long)cfp->freq * 100000; - iwe.u.freq.e = 1; - iwe.len = IW_EV_FREQ_LEN; - current_ev = - iwe_stream_add_event(current_ev, end_buf, &iwe, iwe.len); - - /* Add quality statistics */ - iwe.cmd = IWEVQUAL; - iwe.u.qual.updated = IW_QUAL_ALL_UPDATED; - iwe.u.qual.level = SCAN_RSSI(adapter->scantable[i].rssi); - - rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE; - iwe.u.qual.qual = - (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) * - (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) / - (RSSI_DIFF * RSSI_DIFF); - if (iwe.u.qual.qual > 100) - iwe.u.qual.qual = 100; - else if (iwe.u.qual.qual < 1) - iwe.u.qual.qual = 0; - - if (adapter->NF[TYPE_BEACON][TYPE_NOAVG] == 0) { - iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE; - } else { - iwe.u.qual.noise = - CAL_NF(adapter->NF[TYPE_BEACON][TYPE_NOAVG]); - } - if ((adapter->mode == IW_MODE_ADHOC) && - !libertas_SSID_cmp(&adapter->curbssparams.ssid, - &adapter->scantable[i].ssid) - && adapter->adhoccreate) { - ret = libertas_prepare_and_send_command(priv, - cmd_802_11_rssi, - 0, - cmd_option_waitforrsp, - 0, NULL); - - if (!ret) { - iwe.u.qual.level = - CAL_RSSI(adapter->SNR[TYPE_RXPD][TYPE_AVG] / - AVG_SCALE, - adapter->NF[TYPE_RXPD][TYPE_AVG] / - AVG_SCALE); - } - } - iwe.len = IW_EV_QUAL_LEN; - current_ev = - iwe_stream_add_event(current_ev, end_buf, &iwe, iwe.len); - - /* Add encryption capability */ - iwe.cmd = SIOCGIWENCODE; - if (adapter->scantable[i].privacy) { - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - } else { - iwe.u.data.flags = IW_ENCODE_DISABLED; - } - iwe.u.data.length = 0; - iwe.len = IW_EV_POINT_LEN + iwe.u.data.length; - current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, - adapter->scantable->ssid. - ssid); + if ((adapter->mode == IW_MODE_ADHOC) + && adapter->adhoccreate + && !libertas_ssid_cmp(adapter->curbssparams.ssid, + adapter->curbssparams.ssid_len, + bss->ssid, bss->ssid_len)) { + int snr, nf; + snr = adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; + nf = adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; + iwe.u.qual.level = CAL_RSSI(snr, nf); + } + start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN); - current_val = current_ev + IW_EV_LCP_LEN; + /* Add encryption capability */ + iwe.cmd = SIOCGIWENCODE; + if (bss->privacy) { + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + } else { + iwe.u.data.flags = IW_ENCODE_DISABLED; + } + iwe.u.data.length = 0; + start = iwe_stream_add_point(start, stop, &iwe, bss->ssid); - iwe.cmd = SIOCGIWRATE; + current_val = start + IW_EV_LCP_LEN; - iwe.u.bitrate.fixed = 0; - iwe.u.bitrate.disabled = 0; - iwe.u.bitrate.value = 0; + iwe.cmd = SIOCGIWRATE; + iwe.u.bitrate.fixed = 0; + iwe.u.bitrate.disabled = 0; + iwe.u.bitrate.value = 0; + for (j = 0; j < sizeof(bss->libertas_supported_rates); j++) { + u8 rate = bss->libertas_supported_rates[j]; + if (rate == 0) + break; /* no more rates */ /* Bit rate given in 500 kb/s units (+ 0x80) */ - for (j = 0; j < sizeof(adapter->scantable[i].libertas_supported_rates); - j++) { - if (adapter->scantable[i].libertas_supported_rates[j] == 0) { - break; - } - rate = - (adapter->scantable[i].libertas_supported_rates[j] & 0x7F) * - 500000; - if (rate > iwe.u.bitrate.value) { - iwe.u.bitrate.value = rate; - } - - iwe.u.bitrate.value = - (adapter->scantable[i].libertas_supported_rates[j] - & 0x7f) * 500000; - iwe.len = IW_EV_PARAM_LEN; - current_ev = - iwe_stream_add_value(current_ev, current_val, - end_buf, &iwe, iwe.len); + iwe.u.bitrate.value = (rate & 0x7f) * 500000; + current_val = iwe_stream_add_value(start, current_val, + stop, &iwe, IW_EV_PARAM_LEN); + } + if ((bss->mode == IW_MODE_ADHOC) + && !libertas_ssid_cmp(adapter->curbssparams.ssid, + adapter->curbssparams.ssid_len, + bss->ssid, bss->ssid_len) + && adapter->adhoccreate) { + iwe.u.bitrate.value = 22 * 500000; + current_val = iwe_stream_add_value(start, current_val, + stop, &iwe, IW_EV_PARAM_LEN); + } + /* Check if we added any event */ + if((current_val - start) > IW_EV_LCP_LEN) + start = current_val; + + memset(&iwe, 0, sizeof(iwe)); + if (bss->wpa_ie_len) { + char buf[MAX_WPA_IE_LEN]; + memcpy(buf, bss->wpa_ie, bss->wpa_ie_len); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = bss->wpa_ie_len; + start = iwe_stream_add_point(start, stop, &iwe, buf); + } - } - if ((adapter->scantable[i].mode == IW_MODE_ADHOC) - && !libertas_SSID_cmp(&adapter->curbssparams.ssid, - &adapter->scantable[i].ssid) - && adapter->adhoccreate) { - iwe.u.bitrate.value = 22 * 500000; - } - iwe.len = IW_EV_PARAM_LEN; - current_ev = - iwe_stream_add_value(current_ev, current_val, end_buf, &iwe, - iwe.len); - - /* Add new value to event */ - current_val = current_ev + IW_EV_LCP_LEN; - - if (adapter->scantable[i].rsn_ie[0] == WPA2_IE) { - memset(&iwe, 0, sizeof(iwe)); - memset(buf, 0, sizeof(buf)); - memcpy(buf, adapter->scantable[i].rsn_ie, - adapter->scantable[i].rsn_ie_len); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = adapter->scantable[i].rsn_ie_len; - iwe.len = IW_EV_POINT_LEN + iwe.u.data.length; - current_ev = iwe_stream_add_point(current_ev, end_buf, - &iwe, buf); - } - if (adapter->scantable[i].wpa_ie[0] == WPA_IE) { - memset(&iwe, 0, sizeof(iwe)); - memset(buf, 0, sizeof(buf)); - memcpy(buf, adapter->scantable[i].wpa_ie, - adapter->scantable[i].wpa_ie_len); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = adapter->scantable[i].wpa_ie_len; - iwe.len = IW_EV_POINT_LEN + iwe.u.data.length; - current_ev = iwe_stream_add_point(current_ev, end_buf, - &iwe, buf); - } + memset(&iwe, 0, sizeof(iwe)); + if (bss->rsn_ie_len) { + char buf[MAX_WPA_IE_LEN]; + memcpy(buf, bss->rsn_ie, bss->rsn_ie_len); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = bss->rsn_ie_len; + start = iwe_stream_add_point(start, stop, &iwe, buf); + } + return start; +} - if (adapter->scantable[i].extra_ie != 0) { - memset(&iwe, 0, sizeof(iwe)); - memset(buf, 0, sizeof(buf)); - ptr = buf; - ptr += sprintf(ptr, "extra_ie"); - iwe.u.data.length = strlen(buf); +/** + * @brief Retrieve the scan table entries via wireless tools IOCTL call + * + * @param dev A pointer to net_device structure + * @param info A pointer to iw_request_info structure + * @param dwrq A pointer to iw_point structure + * @param extra A pointer to extra data buf + * + * @return 0 --success, otherwise fail + */ +int libertas_get_scan(struct net_device *dev, struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ +#define SCAN_ITEM_SIZE 128 + wlan_private *priv = dev->priv; + wlan_adapter *adapter = priv->adapter; + int err = 0; + char *ev = extra; + char *stop = ev + dwrq->length; + struct bss_descriptor * iter_bss; + struct bss_descriptor * safe; + + lbs_deb_enter(LBS_DEB_ASSOC); + + /* If we've got an uncompleted scan, schedule the next part */ + if (!adapter->nr_cmd_pending && adapter->last_scanned_channel) + wlan_scan_networks(priv, NULL, 0); + + /* Update RSSI if current BSS is a locally created ad-hoc BSS */ + if ((adapter->mode == IW_MODE_ADHOC) && adapter->adhoccreate) { + libertas_prepare_and_send_command(priv, cmd_802_11_rssi, 0, + cmd_option_waitforrsp, 0, NULL); + } - lbs_pr_debug(1, "iwe.u.data.length %d\n", - iwe.u.data.length); - lbs_pr_debug(1, "BUF: %s \n", buf); + mutex_lock(&adapter->lock); + list_for_each_entry_safe (iter_bss, safe, &adapter->network_list, list) { + char * next_ev; + unsigned long stale_time; - iwe.cmd = IWEVCUSTOM; - iwe.len = IW_EV_POINT_LEN + iwe.u.data.length; - current_ev = - iwe_stream_add_point(current_ev, end_buf, &iwe, - buf); + if (stop - ev < SCAN_ITEM_SIZE) { + err = -E2BIG; + break; } - current_val = current_ev + IW_EV_LCP_LEN; + /* Prune old an old scan result */ + stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE; + if (time_after(jiffies, stale_time)) { + list_move_tail (&iter_bss->list, + &adapter->network_free_list); + clear_bss_descriptor(iter_bss); + continue; + } - /* - * Check if we added any event - */ - if ((current_val - current_ev) > IW_EV_LCP_LEN) - current_ev = current_val; + /* Translate to WE format this entry */ + next_ev = libertas_translate_scan(priv, ev, stop, iter_bss); + if (next_ev == NULL) + continue; + ev = next_ev; } + mutex_unlock(&adapter->lock); - dwrq->length = (current_ev - extra); + dwrq->length = (ev - extra); dwrq->flags = 0; - LEAVE(); - return 0; + lbs_deb_leave(LBS_DEB_ASSOC); + return err; } /** @@ -1796,13 +1702,13 @@ int libertas_cmd_80211_scan(wlan_private * priv, struct cmd_ds_802_11_scan *pscan = &cmd->params.scan; struct wlan_scan_cmd_config *pscancfg; - ENTER(); + lbs_deb_enter(LBS_DEB_ASSOC); pscancfg = pdata_buf; /* Set fixed field variables in scan command */ pscan->bsstype = pscancfg->bsstype; - memcpy(pscan->BSSID, pscancfg->specificBSSID, sizeof(pscan->BSSID)); + memcpy(pscan->BSSID, pscancfg->bssid, sizeof(pscan->BSSID)); memcpy(pscan->tlvbuffer, pscancfg->tlvbuffer, pscancfg->tlvbufferlen); cmd->command = cpu_to_le16(cmd_802_11_scan); @@ -1812,12 +1718,26 @@ int libertas_cmd_80211_scan(wlan_private * priv, + sizeof(pscan->BSSID) + pscancfg->tlvbufferlen + S_DS_GEN); - lbs_pr_debug(1, "SCAN_CMD: command=%x, size=%x, seqnum=%x\n", - cmd->command, cmd->size, cmd->seqnum); - LEAVE(); + lbs_deb_scan("SCAN_CMD: command=%x, size=%x, seqnum=%x\n", + le16_to_cpu(cmd->command), le16_to_cpu(cmd->size), + le16_to_cpu(cmd->seqnum)); + + lbs_deb_leave(LBS_DEB_ASSOC); return 0; } +static inline int is_same_network(struct bss_descriptor *src, + struct bss_descriptor *dst) +{ + /* A network is only a duplicate if the channel, BSSID, and ESSID + * all match. We treat all <hidden> with the same BSSID and channel + * as one network */ + return ((src->ssid_len == dst->ssid_len) && + (src->channel == dst->channel) && + !compare_ether_addr(src->bssid, dst->bssid) && + !memcmp(src->ssid, dst->ssid, src->ssid_len)); +} + /** * @brief This function handles the command response of scan * @@ -1846,38 +1766,45 @@ int libertas_ret_80211_scan(wlan_private * priv, struct cmd_ds_command *resp) { wlan_adapter *adapter = priv->adapter; struct cmd_ds_802_11_scan_rsp *pscan; - struct bss_descriptor newbssentry; struct mrvlietypes_data *ptlv; struct mrvlietypes_tsftimestamp *ptsftlv; + struct bss_descriptor * iter_bss; + struct bss_descriptor * safe; u8 *pbssinfo; u16 scanrespsize; int bytesleft; - int numintable; - int bssIdx; int idx; int tlvbufsize; - u64 tsfval; + int ret; - ENTER(); + lbs_deb_enter(LBS_DEB_ASSOC); + + /* Prune old entries from scan table */ + list_for_each_entry_safe (iter_bss, safe, &adapter->network_list, list) { + unsigned long stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE; + if (time_before(jiffies, stale_time)) + continue; + list_move_tail (&iter_bss->list, &adapter->network_free_list); + clear_bss_descriptor(iter_bss); + } pscan = &resp->params.scanresp; - if (pscan->nr_sets > MRVDRV_MAX_BSSID_LIST) { - lbs_pr_debug(1, - "SCAN_RESP: Invalid number of AP returned (%d)!!\n", - pscan->nr_sets); - LEAVE(); - return -1; + if (pscan->nr_sets > MAX_NETWORK_COUNT) { + lbs_deb_scan( + "SCAN_RESP: too many scan results (%d, max %d)!!\n", + pscan->nr_sets, MAX_NETWORK_COUNT); + ret = -1; + goto done; } bytesleft = le16_to_cpu(pscan->bssdescriptsize); - lbs_pr_debug(1, "SCAN_RESP: bssdescriptsize %d\n", bytesleft); + lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft); scanrespsize = le16_to_cpu(resp->size); - lbs_pr_debug(1, "SCAN_RESP: returned %d AP before parsing\n", + lbs_deb_scan("SCAN_RESP: returned %d AP before parsing\n", pscan->nr_sets); - numintable = adapter->numinscantable; pbssinfo = pscan->bssdesc_and_tlvbuffer; /* The size of the TLV buffer is equal to the entire command response @@ -1901,105 +1828,68 @@ int libertas_ret_80211_scan(wlan_private * priv, struct cmd_ds_command *resp) * or as an addition at the end of the table */ for (idx = 0; idx < pscan->nr_sets && bytesleft; idx++) { - /* Zero out the newbssentry we are about to store info in */ - memset(&newbssentry, 0x00, sizeof(newbssentry)); + struct bss_descriptor new; + struct bss_descriptor * found = NULL; + struct bss_descriptor * oldest = NULL; /* Process the data fields and IEs returned for this BSS */ - if ((InterpretBSSDescriptionWithIE(&newbssentry, - &pbssinfo, - &bytesleft) == - 0) - && CHECK_SSID_IS_VALID(&newbssentry.ssid)) { - - lbs_pr_debug(1, - "SCAN_RESP: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n", - newbssentry.macaddress[0], - newbssentry.macaddress[1], - newbssentry.macaddress[2], - newbssentry.macaddress[3], - newbssentry.macaddress[4], - newbssentry.macaddress[5]); - - /* - * Search the scan table for the same bssid - */ - for (bssIdx = 0; bssIdx < numintable; bssIdx++) { - if (memcmp(newbssentry.macaddress, - adapter->scantable[bssIdx]. - macaddress, - sizeof(newbssentry.macaddress)) == - 0) { - /* - * If the SSID matches as well, it is a duplicate of - * this entry. Keep the bssIdx set to this - * entry so we replace the old contents in the table - */ - if ((newbssentry.ssid.ssidlength == - adapter->scantable[bssIdx].ssid. - ssidlength) - && - (memcmp - (newbssentry.ssid.ssid, - adapter->scantable[bssIdx].ssid. - ssid, - newbssentry.ssid.ssidlength) == - 0)) { - lbs_pr_debug(1, - "SCAN_RESP: Duplicate of index: %d\n", - bssIdx); - break; - } - } - } - /* - * If the bssIdx is equal to the number of entries in the table, - * the new entry was not a duplicate; append it to the scan - * table - */ - if (bssIdx == numintable) { - /* Range check the bssIdx, keep it limited to the last entry */ - if (bssIdx == MRVDRV_MAX_BSSID_LIST) { - bssIdx--; - } else { - numintable++; - } - } - - /* - * If the TSF TLV was appended to the scan results, save the - * this entries TSF value in the networktsf field. The - * networktsf is the firmware's TSF value at the time the - * beacon or probe response was received. - */ - if (ptsftlv) { - memcpy(&tsfval, &ptsftlv->tsftable[idx], - sizeof(tsfval)); - tsfval = le64_to_cpu(tsfval); + memset(&new, 0, sizeof (struct bss_descriptor)); + if (libertas_process_bss(&new, &pbssinfo, &bytesleft) != 0) { + /* error parsing the scan response, skipped */ + lbs_deb_scan("SCAN_RESP: process_bss returned ERROR\n"); + continue; + } - memcpy(&newbssentry.networktsf, - &tsfval, sizeof(newbssentry.networktsf)); + /* Try to find this bss in the scan table */ + list_for_each_entry (iter_bss, &adapter->network_list, list) { + if (is_same_network(iter_bss, &new)) { + found = iter_bss; + break; } - /* Copy the locally created newbssentry to the scan table */ - memcpy(&adapter->scantable[bssIdx], - &newbssentry, - sizeof(adapter->scantable[bssIdx])); + if ((oldest == NULL) || + (iter_bss->last_scanned < oldest->last_scanned)) + oldest = iter_bss; + } + if (found) { + /* found, clear it */ + clear_bss_descriptor(found); + } else if (!list_empty(&adapter->network_free_list)) { + /* Pull one from the free list */ + found = list_entry(adapter->network_free_list.next, + struct bss_descriptor, list); + list_move_tail(&found->list, &adapter->network_list); + } else if (oldest) { + /* If there are no more slots, expire the oldest */ + found = oldest; + clear_bss_descriptor(found); + list_move_tail(&found->list, &adapter->network_list); } else { + continue; + } + + lbs_deb_scan("SCAN_RESP: BSSID = " MAC_FMT "\n", + new.bssid[0], new.bssid[1], new.bssid[2], + new.bssid[3], new.bssid[4], new.bssid[5]); - /* error parsing/interpreting the scan response, skipped */ - lbs_pr_debug(1, "SCAN_RESP: " - "InterpretBSSDescriptionWithIE returned ERROR\n"); + /* + * If the TSF TLV was appended to the scan results, save the + * this entries TSF value in the networktsf field. The + * networktsf is the firmware's TSF value at the time the + * beacon or probe response was received. + */ + if (ptsftlv) { + new.networktsf = le64_to_cpup(&ptsftlv->tsftable[idx]); } - } - lbs_pr_debug(1, "SCAN_RESP: Scanned %2d APs, %d valid, %d total\n", - pscan->nr_sets, numintable - adapter->numinscantable, - numintable); + /* Copy the locally created newbssentry to the scan table */ + memcpy(found, &new, offsetof(struct bss_descriptor, list)); + } - /* Update the total number of BSSIDs in the scan table */ - adapter->numinscantable = numintable; + ret = 0; - LEAVE(); - return 0; +done: + lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); + return ret; } diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h index 405f4f0fe57..bd019e5ff1e 100644 --- a/drivers/net/wireless/libertas/scan.h +++ b/drivers/net/wireless/libertas/scan.h @@ -51,7 +51,7 @@ struct wlan_scan_cmd_config { /** * @brief Specific BSSID used to filter scan results in the firmware */ - u8 specificBSSID[ETH_ALEN]; + u8 bssid[ETH_ALEN]; /** * @brief length of TLVs sent in command starting at tlvBuffer @@ -91,15 +91,6 @@ struct wlan_ioctl_user_scan_chan { * @sa libertas_set_user_scan_ioctl */ struct wlan_ioctl_user_scan_cfg { - - /** - * @brief Flag set to keep the previous scan table intact - * - * If set, the scan results will accumulate, replacing any previous - * matched entries for a BSS with the new scan data - */ - u8 keeppreviousscan; //!< Do not erase the existing scan results - /** * @brief BSS type to be sent in the firmware command * @@ -117,15 +108,22 @@ struct wlan_ioctl_user_scan_cfg { */ u8 numprobes; - /** - * @brief BSSID filter sent in the firmware command to limit the results - */ - u8 specificBSSID[ETH_ALEN]; + /** + * @brief BSSID filter sent in the firmware command to limit the results + */ + u8 bssid[ETH_ALEN]; - /** - * @brief SSID filter sent in the firmware command to limit the results - */ - char specificSSID[IW_ESSID_MAX_SIZE + 1]; + /* Clear existing scan results matching this BSSID */ + u8 clear_bssid; + + /** + * @brief SSID filter sent in the firmware command to limit the results + */ + char ssid[IW_ESSID_MAX_SIZE]; + u8 ssid_len; + + /* Clear existing scan results matching this SSID */ + u8 clear_ssid; /** * @brief Variable number (fixed maximum) of channels to scan up @@ -137,9 +135,10 @@ struct wlan_ioctl_user_scan_cfg { * @brief Structure used to store information for each beacon/probe response */ struct bss_descriptor { - u8 macaddress[ETH_ALEN]; + u8 bssid[ETH_ALEN]; - struct WLAN_802_11_SSID ssid; + u8 ssid[IW_ESSID_MAX_SIZE + 1]; + u8 ssid_len; /* WEP encryption requirement */ u32 privacy; @@ -156,15 +155,15 @@ struct bss_descriptor { u8 mode; u8 libertas_supported_rates[WLAN_SUPPORTED_RATES]; - int extra_ie; + __le64 timestamp; //!< TSF value included in the beacon/probe response + unsigned long last_scanned; - u8 timestamp[8]; //!< TSF value included in the beacon/probe response union ieeetypes_phyparamset phyparamset; union IEEEtypes_ssparamset ssparamset; struct ieeetypes_capinfo cap; u8 datarates[WLAN_SUPPORTED_RATES]; - __le64 networktsf; //!< TSF timestamp from the current firmware TSF + u64 networktsf; //!< TSF timestamp from the current firmware TSF struct ieeetypes_countryinfofullset countryinfo; @@ -172,24 +171,29 @@ struct bss_descriptor { size_t wpa_ie_len; u8 rsn_ie[MAX_WPA_IE_LEN]; size_t rsn_ie_len; + + struct list_head list; }; -extern int libertas_SSID_cmp(struct WLAN_802_11_SSID *ssid1, - struct WLAN_802_11_SSID *ssid2); -extern int libertas_find_SSID_in_list(wlan_adapter * adapter, struct WLAN_802_11_SSID *ssid, - u8 * bssid, u8 mode); -int libertas_find_best_SSID_in_list(wlan_adapter * adapter, u8 mode); -extern int libertas_find_BSSID_in_list(wlan_adapter * adapter, u8 * bssid, u8 mode); +extern int libertas_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len); + +struct bss_descriptor * libertas_find_ssid_in_list(wlan_adapter * adapter, + u8 *ssid, u8 ssid_len, u8 * bssid, u8 mode, + int channel); + +struct bss_descriptor * libertas_find_best_ssid_in_list(wlan_adapter * adapter, + u8 mode); + +extern struct bss_descriptor * libertas_find_bssid_in_list(wlan_adapter * adapter, + u8 * bssid, u8 mode); -int libertas_find_best_network_SSID(wlan_private * priv, - struct WLAN_802_11_SSID *pSSID, - u8 preferred_mode, u8 *out_mode); +int libertas_find_best_network_ssid(wlan_private * priv, u8 *out_ssid, + u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode); -extern int libertas_send_specific_SSID_scan(wlan_private * priv, - struct WLAN_802_11_SSID *prequestedssid, - u8 keeppreviousscan); -extern int libertas_send_specific_BSSID_scan(wlan_private * priv, - u8 * bssid, u8 keeppreviousscan); +extern int libertas_send_specific_ssid_scan(wlan_private * priv, u8 *ssid, + u8 ssid_len, u8 clear_ssid); +extern int libertas_send_specific_bssid_scan(wlan_private * priv, + u8 * bssid, u8 clear_bssid); extern int libertas_cmd_80211_scan(wlan_private * priv, struct cmd_ds_command *cmd, @@ -199,7 +203,8 @@ extern int libertas_ret_80211_scan(wlan_private * priv, struct cmd_ds_command *resp); int wlan_scan_networks(wlan_private * priv, - const struct wlan_ioctl_user_scan_cfg * puserscanin); + const struct wlan_ioctl_user_scan_cfg * puserscanin, + int full_scan); struct ifreq; diff --git a/drivers/net/wireless/libertas/thread.h b/drivers/net/wireless/libertas/thread.h index 207b8a6cc33..b1f34d92ff3 100644 --- a/drivers/net/wireless/libertas/thread.h +++ b/drivers/net/wireless/libertas/thread.h @@ -21,11 +21,11 @@ static inline void wlan_activate_thread(struct wlan_thread * thr) static inline void wlan_deactivate_thread(struct wlan_thread * thr) { - ENTER(); + lbs_deb_enter(LBS_DEB_THREAD); thr->pid = 0; - LEAVE(); + lbs_deb_leave(LBS_DEB_THREAD); } static inline void wlan_create_thread(int (*wlanfunc) (void *), @@ -36,7 +36,7 @@ static inline void wlan_create_thread(int (*wlanfunc) (void *), static inline int wlan_terminate_thread(struct wlan_thread * thr) { - ENTER(); + lbs_deb_enter(LBS_DEB_THREAD); /* Check if the thread is active or not */ if (!thr->pid) { @@ -45,7 +45,7 @@ static inline int wlan_terminate_thread(struct wlan_thread * thr) } kthread_stop(thr->task); - LEAVE(); + lbs_deb_leave(LBS_DEB_THREAD); return 0; } diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index d4b13478c9a..17c437635a0 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c @@ -5,7 +5,6 @@ #include "hostcmd.h" #include "radiotap.h" -#include "sbi.h" #include "decl.h" #include "defs.h" #include "dev.h" @@ -68,7 +67,7 @@ static int SendSinglePacket(wlan_private * priv, struct sk_buff *skb) u32 new_rate; u8 *ptr = priv->adapter->tmptxbuf; - ENTER(); + lbs_deb_enter(LBS_DEB_TX); if (priv->adapter->surpriseremoved) return -1; @@ -78,7 +77,7 @@ static int SendSinglePacket(wlan_private * priv, struct sk_buff *skb) min_t(unsigned int, skb->len, 100)); if (!skb->len || (skb->len > MRVDRV_ETH_TX_PACKET_BUFFER_SIZE)) { - lbs_pr_debug(1, "Tx error: Bad skb length %d : %zd\n", + lbs_deb_tx("tx err: skb length %d 0 or > %zd\n", skb->len, MRVDRV_ETH_TX_PACKET_BUFFER_SIZE); ret = -1; goto done; @@ -86,13 +85,13 @@ static int SendSinglePacket(wlan_private * priv, struct sk_buff *skb) memset(plocaltxpd, 0, sizeof(struct txpd)); - plocaltxpd->tx_packet_length = skb->len; + plocaltxpd->tx_packet_length = cpu_to_le16(skb->len); /* offset of actual data */ - plocaltxpd->tx_packet_location = sizeof(struct txpd); + plocaltxpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd)); /* TxCtrl set by user or default */ - plocaltxpd->tx_control = adapter->pkttxctrl; + plocaltxpd->tx_control = cpu_to_le32(adapter->pkttxctrl); p802x_hdr = skb->data; if (priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP) { @@ -103,15 +102,16 @@ static int SendSinglePacket(wlan_private * priv, struct sk_buff *skb) /* set txpd fields from the radiotap header */ new_rate = convert_radiotap_rate_to_mv(pradiotap_hdr->rate); if (new_rate != 0) { - /* erase tx_control[4:0] */ - plocaltxpd->tx_control &= ~0x1f; - /* write new tx_control[4:0] */ - plocaltxpd->tx_control |= new_rate; + /* use new tx_control[4:0] */ + new_rate |= (adapter->pkttxctrl & ~0x1f); + plocaltxpd->tx_control = cpu_to_le32(new_rate); } /* skip the radiotap header */ p802x_hdr += sizeof(struct tx_radiotap_hdr); - plocaltxpd->tx_packet_length -= sizeof(struct tx_radiotap_hdr); + plocaltxpd->tx_packet_length = + cpu_to_le16(le16_to_cpu(plocaltxpd->tx_packet_length) + - sizeof(struct tx_radiotap_hdr)); } /* copy destination address from 802.3 or 802.11 header */ @@ -123,28 +123,28 @@ static int SendSinglePacket(wlan_private * priv, struct sk_buff *skb) lbs_dbg_hex("txpd", (u8 *) plocaltxpd, sizeof(struct txpd)); if (IS_MESH_FRAME(skb)) { - plocaltxpd->tx_control |= TxPD_MESH_FRAME; + plocaltxpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME); } memcpy(ptr, plocaltxpd, sizeof(struct txpd)); ptr += sizeof(struct txpd); - lbs_dbg_hex("Tx Data", (u8 *) p802x_hdr, plocaltxpd->tx_packet_length); - memcpy(ptr, p802x_hdr, plocaltxpd->tx_packet_length); - ret = libertas_sbi_host_to_card(priv, MVMS_DAT, - priv->adapter->tmptxbuf, - plocaltxpd->tx_packet_length + - sizeof(struct txpd)); + lbs_dbg_hex("Tx Data", (u8 *) p802x_hdr, le16_to_cpu(plocaltxpd->tx_packet_length)); + memcpy(ptr, p802x_hdr, le16_to_cpu(plocaltxpd->tx_packet_length)); + ret = priv->hw_host_to_card(priv, MVMS_DAT, + priv->adapter->tmptxbuf, + le16_to_cpu(plocaltxpd->tx_packet_length) + + sizeof(struct txpd)); if (ret) { - lbs_pr_debug(1, "Tx error: libertas_sbi_host_to_card failed: 0x%X\n", ret); + lbs_deb_tx("tx err: hw_host_to_card returned 0x%X\n", ret); goto done; } - lbs_pr_debug(1, "SendSinglePacket succeeds\n"); + lbs_deb_tx("SendSinglePacket succeeds\n"); - done: +done: if (!ret) { priv->stats.tx_packets++; priv->stats.tx_bytes += skb->len; @@ -158,7 +158,8 @@ static int SendSinglePacket(wlan_private * priv, struct sk_buff *skb) received from FW */ skb_orphan(skb); /* stop processing outgoing pkts */ - netif_stop_queue(priv->wlan_dev.netdev); + netif_stop_queue(priv->dev); + netif_stop_queue(priv->mesh_dev); /* freeze any packets already in our queues */ priv->adapter->TxLockFlag = 1; } else { @@ -166,7 +167,7 @@ static int SendSinglePacket(wlan_private * priv, struct sk_buff *skb) priv->adapter->currenttxskb = NULL; } - LEAVE(); + lbs_deb_leave_args(LBS_DEB_TX, "ret %d", ret); return ret; } @@ -195,10 +196,13 @@ static void wlan_tx_queue(wlan_private *priv, struct sk_buff *skb) WARN_ON(priv->adapter->tx_queue_idx >= NR_TX_QUEUE); adapter->tx_queue_ps[adapter->tx_queue_idx++] = skb; - if (adapter->tx_queue_idx == NR_TX_QUEUE) - netif_stop_queue(priv->wlan_dev.netdev); - else - netif_start_queue(priv->wlan_dev.netdev); + if (adapter->tx_queue_idx == NR_TX_QUEUE) { + netif_stop_queue(priv->dev); + netif_stop_queue(priv->mesh_dev); + } else { + netif_start_queue(priv->dev); + netif_start_queue(priv->mesh_dev); + } spin_unlock(&adapter->txqueue_lock); } @@ -214,13 +218,12 @@ int libertas_process_tx(wlan_private * priv, struct sk_buff *skb) { int ret = -1; - ENTER(); - + lbs_deb_enter(LBS_DEB_TX); lbs_dbg_hex("TX Data", skb->data, min_t(unsigned int, skb->len, 100)); - if (priv->wlan_dev.dnld_sent) { + if (priv->dnld_sent) { lbs_pr_alert( "TX error: dnld_sent = %d, not sending\n", - priv->wlan_dev.dnld_sent); + priv->dnld_sent); goto done; } @@ -234,7 +237,7 @@ int libertas_process_tx(wlan_private * priv, struct sk_buff *skb) ret = SendSinglePacket(priv, skb); done: - LEAVE(); + lbs_deb_leave_args(LBS_DEB_TX, "ret %d", ret); return ret; } @@ -280,6 +283,9 @@ void libertas_send_tx_feedback(wlan_private * priv) libertas_upload_rx_packet(priv, adapter->currenttxskb); adapter->currenttxskb = NULL; priv->adapter->TxLockFlag = 0; - if (priv->adapter->connect_status == libertas_connected) - netif_wake_queue(priv->wlan_dev.netdev); + if (priv->adapter->connect_status == libertas_connected) { + netif_wake_queue(priv->dev); + netif_wake_queue(priv->mesh_dev); + } } +EXPORT_SYMBOL_GPL(libertas_send_tx_feedback); diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h index 09d62f8b1a1..028e2f3b53d 100644 --- a/drivers/net/wireless/libertas/types.h +++ b/drivers/net/wireless/libertas/types.h @@ -5,6 +5,7 @@ #define _WLAN_TYPES_ #include <linux/if_ether.h> +#include <asm/byteorder.h> /** IEEE type definitions */ enum ieeetypes_elementid { @@ -29,9 +30,30 @@ enum ieeetypes_elementid { EXTRA_IE = 133, } __attribute__ ((packed)); +#ifdef __BIG_ENDIAN #define CAPINFO_MASK (~(0xda00)) +#else +#define CAPINFO_MASK (~(0x00da)) +#endif struct ieeetypes_capinfo { +#ifdef __BIG_ENDIAN_BITFIELD + u8 chanagility:1; + u8 pbcc:1; + u8 shortpreamble:1; + u8 privacy:1; + u8 cfpollrqst:1; + u8 cfpollable:1; + u8 ibss:1; + u8 ess:1; + u8 rsrvd1:2; + u8 dsssofdm:1; + u8 rsvrd2:1; + u8 apsd:1; + u8 shortslottime:1; + u8 rsrvd3:1; + u8 spectrummgmt:1; +#else u8 ess:1; u8 ibss:1; u8 cfpollable:1; @@ -47,6 +69,7 @@ struct ieeetypes_capinfo { u8 rsvrd2:1; u8 dsssofdm:1; u8 rsrvd1:2; +#endif } __attribute__ ((packed)); struct ieeetypes_cfparamset { @@ -54,15 +77,15 @@ struct ieeetypes_cfparamset { u8 len; u8 cfpcnt; u8 cfpperiod; - u16 cfpmaxduration; - u16 cfpdurationremaining; + __le16 cfpmaxduration; + __le16 cfpdurationremaining; } __attribute__ ((packed)); struct ieeetypes_ibssparamset { u8 elementid; u8 len; - u16 atimwindow; + __le16 atimwindow; } __attribute__ ((packed)); union IEEEtypes_ssparamset { @@ -73,7 +96,7 @@ union IEEEtypes_ssparamset { struct ieeetypes_fhparamset { u8 elementid; u8 len; - u16 dwelltime; + __le16 dwelltime; u8 hopset; u8 hoppattern; u8 hopindex; @@ -92,8 +115,8 @@ union ieeetypes_phyparamset { struct ieeetypes_assocrsp { struct ieeetypes_capinfo capability; - u16 statuscode; - u16 aid; + __le16 statuscode; + __le16 aid; u8 iebuffer[1]; } __attribute__ ((packed)); @@ -138,8 +161,8 @@ struct ieeetypes_assocrsp { /** TLV related data structures*/ struct mrvlietypesheader { - u16 type; - u16 len; + __le16 type; + __le16 len; } __attribute__ ((packed)); struct mrvlietypes_data { @@ -164,17 +187,23 @@ struct mrvlietypes_wildcardssidparamset { } __attribute__ ((packed)); struct chanscanmode { +#ifdef __BIG_ENDIAN_BITFIELD + u8 reserved_2_7:6; + u8 disablechanfilt:1; + u8 passivescan:1; +#else u8 passivescan:1; u8 disablechanfilt:1; u8 reserved_2_7:6; +#endif } __attribute__ ((packed)); struct chanscanparamset { u8 radiotype; u8 channumber; struct chanscanmode chanscanmode; - u16 minscantime; - u16 maxscantime; + __le16 minscantime; + __le16 maxscantime; } __attribute__ ((packed)); struct mrvlietypes_chanlistparamset { @@ -185,12 +214,12 @@ struct mrvlietypes_chanlistparamset { struct cfparamset { u8 cfpcnt; u8 cfpperiod; - u16 cfpmaxduration; - u16 cfpdurationremaining; + __le16 cfpmaxduration; + __le16 cfpdurationremaining; } __attribute__ ((packed)); struct ibssparamset { - u16 atimwindow; + __le16 atimwindow; } __attribute__ ((packed)); struct mrvlietypes_ssparamset { @@ -202,7 +231,7 @@ struct mrvlietypes_ssparamset { } __attribute__ ((packed)); struct fhparamset { - u16 dwelltime; + __le16 dwelltime; u8 hopset; u8 hoppattern; u8 hopindex; @@ -263,17 +292,17 @@ struct mrvlietypes_beaconsmissed { struct mrvlietypes_numprobes { struct mrvlietypesheader header; - u16 numprobes; + __le16 numprobes; } __attribute__ ((packed)); struct mrvlietypes_bcastprobe { struct mrvlietypesheader header; - u16 bcastprobe; + __le16 bcastprobe; } __attribute__ ((packed)); struct mrvlietypes_numssidprobe { struct mrvlietypesheader header; - u16 numssidprobe; + __le16 numssidprobe; } __attribute__ ((packed)); struct led_pin { diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index 69f52b6e59c..f42b796b5e4 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -22,6 +22,14 @@ /** + * the rates supported by the card + */ +static u8 libertas_wlan_data_rates[WLAN_SUPPORTED_RATES] = + { 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12, + 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x00 +}; + +/** * @brief Convert mw value to dbm value * * @param mw the value of mw @@ -102,8 +110,8 @@ struct chan_freq_power *libertas_find_cfp_by_band_and_channel(wlan_adapter * ada } if (!cfp && channel) - lbs_pr_debug(1, "libertas_find_cfp_by_band_and_channel(): cannot find " - "cfp by band %d & channel %d\n", band, channel); + lbs_deb_wext("libertas_find_cfp_by_band_and_channel: can't find " + "cfp by band %d / channel %d\n", band, channel); return cfp; } @@ -143,113 +151,12 @@ static struct chan_freq_power *find_cfp_by_band_and_freq(wlan_adapter * adapter, } if (!cfp && freq) - lbs_pr_debug(1, "find_cfp_by_band_and_freql(): cannot find cfp by " - "band %d & freq %d\n", band, freq); + lbs_deb_wext("find_cfp_by_band_and_freql: can't find cfp by " + "band %d / freq %d\n", band, freq); return cfp; } -static int updatecurrentchannel(wlan_private * priv) -{ - int ret; - - /* - ** the channel in f/w could be out of sync, get the current channel - */ - ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel, - cmd_opt_802_11_rf_channel_get, - cmd_option_waitforrsp, 0, NULL); - - lbs_pr_debug(1, "Current channel = %d\n", - priv->adapter->curbssparams.channel); - - return ret; -} - -static int setcurrentchannel(wlan_private * priv, int channel) -{ - lbs_pr_debug(1, "Set channel = %d\n", channel); - - /* - ** Current channel is not set to adhocchannel requested, set channel - */ - return (libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel, - cmd_opt_802_11_rf_channel_set, - cmd_option_waitforrsp, 0, &channel)); -} - -static int changeadhocchannel(wlan_private * priv, int channel) -{ - int ret = 0; - wlan_adapter *adapter = priv->adapter; - - adapter->adhocchannel = channel; - - updatecurrentchannel(priv); - - if (adapter->curbssparams.channel == adapter->adhocchannel) { - /* adhocchannel is set to the current channel already */ - LEAVE(); - return 0; - } - - lbs_pr_debug(1, "Updating channel from %d to %d\n", - adapter->curbssparams.channel, adapter->adhocchannel); - - setcurrentchannel(priv, adapter->adhocchannel); - - updatecurrentchannel(priv); - - if (adapter->curbssparams.channel != adapter->adhocchannel) { - lbs_pr_debug(1, "failed to updated channel to %d, channel = %d\n", - adapter->adhocchannel, adapter->curbssparams.channel); - LEAVE(); - return -1; - } - - if (adapter->connect_status == libertas_connected) { - int i; - struct WLAN_802_11_SSID curadhocssid; - - lbs_pr_debug(1, "channel Changed while in an IBSS\n"); - - /* Copy the current ssid */ - memcpy(&curadhocssid, &adapter->curbssparams.ssid, - sizeof(struct WLAN_802_11_SSID)); - - /* Exit Adhoc mode */ - lbs_pr_debug(1, "In changeadhocchannel(): Sending Adhoc Stop\n"); - ret = libertas_stop_adhoc_network(priv); - - if (ret) { - LEAVE(); - return ret; - } - /* Scan for the network, do not save previous results. Stale - * scan data will cause us to join a non-existant adhoc network - */ - libertas_send_specific_SSID_scan(priv, &curadhocssid, 0); - - // find out the BSSID that matches the current SSID - i = libertas_find_SSID_in_list(adapter, &curadhocssid, NULL, - IW_MODE_ADHOC); - - if (i >= 0) { - lbs_pr_debug(1, "SSID found at %d in List," - "so join\n", i); - libertas_join_adhoc_network(priv, &adapter->scantable[i]); - } else { - // else send START command - lbs_pr_debug(1, "SSID not found in list, " - "so creating adhoc with ssid = %s\n", - curadhocssid.ssid); - libertas_start_adhoc_network(priv, &curadhocssid); - } // end of else (START command) - } - - LEAVE(); - return 0; -} /** * @brief Set Radio On/OFF @@ -263,10 +170,10 @@ int wlan_radio_ioctl(wlan_private * priv, u8 option) int ret = 0; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); if (adapter->radioon != option) { - lbs_pr_debug(1, "Switching %s the Radio\n", option ? "On" : "Off"); + lbs_deb_wext("switching radio %s\n", option ? "on" : "off"); adapter->radioon = option; ret = libertas_prepare_and_send_command(priv, @@ -275,7 +182,7 @@ int wlan_radio_ioctl(wlan_private * priv, u8 option) cmd_option_waitforrsp, 0, NULL); } - LEAVE(); + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret; } @@ -312,15 +219,15 @@ static int get_active_data_rates(wlan_adapter * adapter, { int k = 0; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); if (adapter->connect_status != libertas_connected) { if (adapter->mode == IW_MODE_INFRA) { - lbs_pr_debug(1, "Infra\n"); + lbs_deb_wext("infra\n"); k = copyrates(rates, k, libertas_supported_rates, sizeof(libertas_supported_rates)); } else { - lbs_pr_debug(1, "Adhoc G\n"); + lbs_deb_wext("Adhoc G\n"); k = copyrates(rates, k, libertas_adhoc_rates_g, sizeof(libertas_adhoc_rates_g)); } @@ -329,8 +236,7 @@ static int get_active_data_rates(wlan_adapter * adapter, adapter->curbssparams.numofrates); } - LEAVE(); - + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", k); return k; } @@ -342,7 +248,7 @@ static int wlan_get_name(struct net_device *dev, struct iw_request_info *info, char mrvl[6] = { "MRVL-" }; int cnt; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); strcpy(cwrq, mrvl); @@ -360,8 +266,7 @@ static int wlan_get_name(struct net_device *dev, struct iw_request_info *info, } *cwrq = '\0'; - LEAVE(); - + lbs_deb_leave(LBS_DEB_WEXT); return 0; } @@ -372,14 +277,14 @@ static int wlan_get_freq(struct net_device *dev, struct iw_request_info *info, wlan_adapter *adapter = priv->adapter; struct chan_freq_power *cfp; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, adapter->curbssparams.channel); if (!cfp) { if (adapter->curbssparams.channel) - lbs_pr_debug(1, "Invalid channel=%d\n", + lbs_deb_wext("invalid channel %d\n", adapter->curbssparams.channel); return -EINVAL; } @@ -387,9 +292,8 @@ static int wlan_get_freq(struct net_device *dev, struct iw_request_info *info, fwrq->m = (long)cfp->freq * 100000; fwrq->e = 1; - lbs_pr_debug(1, "freq=%u\n", fwrq->m); - - LEAVE(); + lbs_deb_wext("freq %u\n", fwrq->m); + lbs_deb_leave(LBS_DEB_WEXT); return 0; } @@ -399,7 +303,7 @@ static int wlan_get_wap(struct net_device *dev, struct iw_request_info *info, wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); if (adapter->connect_status == libertas_connected) { memcpy(awrq->sa_data, adapter->curbssparams.bssid, ETH_ALEN); @@ -408,7 +312,7 @@ static int wlan_get_wap(struct net_device *dev, struct iw_request_info *info, } awrq->sa_family = ARPHRD_ETHER; - LEAVE(); + lbs_deb_leave(LBS_DEB_WEXT); return 0; } @@ -418,7 +322,7 @@ static int wlan_set_nick(struct net_device *dev, struct iw_request_info *info, wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); /* * Check the size of the string @@ -433,7 +337,7 @@ static int wlan_set_nick(struct net_device *dev, struct iw_request_info *info, memcpy(adapter->nodename, extra, dwrq->length); mutex_unlock(&adapter->lock); - LEAVE(); + lbs_deb_leave(LBS_DEB_WEXT); return 0; } @@ -443,7 +347,7 @@ static int wlan_get_nick(struct net_device *dev, struct iw_request_info *info, wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); /* * Get the Nick Name saved @@ -464,19 +368,43 @@ static int wlan_get_nick(struct net_device *dev, struct iw_request_info *info, */ dwrq->length = strlen(extra) + 1; - LEAVE(); + lbs_deb_leave(LBS_DEB_WEXT); return 0; } +static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + wlan_private *priv = dev->priv; + wlan_adapter *adapter = priv->adapter; + + lbs_deb_enter(LBS_DEB_WEXT); + + /* Use nickname to indicate that mesh is on */ + + if (adapter->connect_status == libertas_connected) { + strncpy(extra, "Mesh", 12); + extra[12] = '\0'; + dwrq->length = strlen(extra) + 1; + } + + else { + extra[0] = '\0'; + dwrq->length = 1 ; + } + + lbs_deb_leave(LBS_DEB_WEXT); + return 0; +} static int wlan_set_rts(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { int ret = 0; wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; - int rthr = vwrq->value; + u32 rthr = vwrq->value; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); if (vwrq->disabled) { adapter->rtsthsd = rthr = MRVDRV_RTS_MAX_VALUE; @@ -490,7 +418,7 @@ static int wlan_set_rts(struct net_device *dev, struct iw_request_info *info, cmd_act_set, cmd_option_waitforrsp, OID_802_11_RTS_THRESHOLD, &rthr); - LEAVE(); + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret; } @@ -501,35 +429,34 @@ static int wlan_get_rts(struct net_device *dev, struct iw_request_info *info, wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); adapter->rtsthsd = 0; ret = libertas_prepare_and_send_command(priv, cmd_802_11_snmp_mib, cmd_act_get, cmd_option_waitforrsp, OID_802_11_RTS_THRESHOLD, NULL); - if (ret) { - LEAVE(); - return ret; - } + if (ret) + goto out; vwrq->value = adapter->rtsthsd; vwrq->disabled = ((vwrq->value < MRVDRV_RTS_MIN_VALUE) || (vwrq->value > MRVDRV_RTS_MAX_VALUE)); vwrq->fixed = 1; - LEAVE(); - return 0; +out: + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); + return ret; } static int wlan_set_frag(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { int ret = 0; - int fthr = vwrq->value; + u32 fthr = vwrq->value; wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); if (vwrq->disabled) { adapter->fragthsd = fthr = MRVDRV_FRAG_MAX_VALUE; @@ -543,7 +470,8 @@ static int wlan_set_frag(struct net_device *dev, struct iw_request_info *info, ret = libertas_prepare_and_send_command(priv, cmd_802_11_snmp_mib, cmd_act_set, cmd_option_waitforrsp, OID_802_11_FRAGMENTATION_THRESHOLD, &fthr); - LEAVE(); + + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret; } @@ -554,24 +482,23 @@ static int wlan_get_frag(struct net_device *dev, struct iw_request_info *info, wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); adapter->fragthsd = 0; ret = libertas_prepare_and_send_command(priv, cmd_802_11_snmp_mib, cmd_act_get, cmd_option_waitforrsp, OID_802_11_FRAGMENTATION_THRESHOLD, NULL); - if (ret) { - LEAVE(); - return ret; - } + if (ret) + goto out; vwrq->value = adapter->fragthsd; vwrq->disabled = ((vwrq->value < MRVDRV_FRAG_MIN_VALUE) || (vwrq->value > MRVDRV_FRAG_MAX_VALUE)); vwrq->fixed = 1; - LEAVE(); +out: + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret; } @@ -581,11 +508,23 @@ static int wlan_get_mode(struct net_device *dev, wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); *uwrq = adapter->mode; - LEAVE(); + lbs_deb_leave(LBS_DEB_WEXT); + return 0; +} + +static int mesh_wlan_get_mode(struct net_device *dev, + struct iw_request_info *info, u32 * uwrq, + char *extra) +{ + lbs_deb_enter(LBS_DEB_WEXT); + + *uwrq = IW_MODE_REPEAT ; + + lbs_deb_leave(LBS_DEB_WEXT); return 0; } @@ -597,19 +536,17 @@ static int wlan_get_txpow(struct net_device *dev, wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_tx_power, cmd_act_tx_power_opt_get, cmd_option_waitforrsp, 0, NULL); - if (ret) { - LEAVE(); - return ret; - } + if (ret) + goto out; - lbs_pr_debug(1, "TXPOWER GET %d dbm.\n", adapter->txpowerlevel); + lbs_deb_wext("tx power level %d dbm\n", adapter->txpowerlevel); vwrq->value = adapter->txpowerlevel; vwrq->fixed = 1; if (adapter->radioon) { @@ -619,8 +556,9 @@ static int wlan_get_txpow(struct net_device *dev, vwrq->disabled = 1; } - LEAVE(); - return 0; +out: + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); + return ret; } static int wlan_set_retry(struct net_device *dev, struct iw_request_info *info, @@ -630,7 +568,7 @@ static int wlan_set_retry(struct net_device *dev, struct iw_request_info *info, wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); if (vwrq->flags == IW_RETRY_LIMIT) { /* The MAC has a 4-bit Total_Tx_Count register @@ -648,16 +586,15 @@ static int wlan_set_retry(struct net_device *dev, struct iw_request_info *info, cmd_option_waitforrsp, OID_802_11_TX_RETRYCOUNT, NULL); - if (ret) { - LEAVE(); - return ret; - } + if (ret) + goto out; } else { return -EOPNOTSUPP; } - LEAVE(); - return 0; +out: + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); + return ret; } static int wlan_get_retry(struct net_device *dev, struct iw_request_info *info, @@ -667,16 +604,16 @@ static int wlan_get_retry(struct net_device *dev, struct iw_request_info *info, wlan_adapter *adapter = priv->adapter; int ret = 0; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); + adapter->txretrycount = 0; ret = libertas_prepare_and_send_command(priv, cmd_802_11_snmp_mib, cmd_act_get, cmd_option_waitforrsp, OID_802_11_TX_RETRYCOUNT, NULL); - if (ret) { - LEAVE(); - return ret; - } + if (ret) + goto out; + vwrq->disabled = 0; if (!vwrq->flags) { vwrq->flags = IW_RETRY_LIMIT; @@ -684,8 +621,9 @@ static int wlan_get_retry(struct net_device *dev, struct iw_request_info *info, vwrq->value = adapter->txretrycount - 1; } - LEAVE(); - return 0; +out: + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); + return ret; } static inline void sort_channels(struct iw_freq *freq, int num) @@ -739,7 +677,7 @@ static int wlan_get_range(struct net_device *dev, struct iw_request_info *info, u8 flag = 0; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); dwrq->length = sizeof(struct iw_range); memset(range, 0, sizeof(struct iw_range)); @@ -755,7 +693,7 @@ static int wlan_get_range(struct net_device *dev, struct iw_request_info *info, range->bitrate[i] = (rates[i] & 0x7f) * 500000; } range->num_bitrates = i; - lbs_pr_debug(1, "IW_MAX_BITRATES=%d num_bitrates=%d\n", IW_MAX_BITRATES, + lbs_deb_wext("IW_MAX_BITRATES %d, num_bitrates %d\n", IW_MAX_BITRATES, range->num_bitrates); range->num_frequency = 0; @@ -768,18 +706,17 @@ static int wlan_get_range(struct net_device *dev, struct iw_request_info *info, &adapter->parsed_region_chan; if (parsed_region_chan == NULL) { - lbs_pr_debug(1, "11D:parsed_region_chan is NULL\n"); - LEAVE(); - return 0; + lbs_deb_wext("11d: parsed_region_chan is NULL\n"); + goto out; } band = parsed_region_chan->band; - lbs_pr_debug(1, "band=%d NoOfChan=%d\n", band, + lbs_deb_wext("band %d, nr_char %d\n", band, parsed_region_chan->nr_chan); for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES) && (i < parsed_region_chan->nr_chan); i++) { chan_no = parsed_region_chan->chanpwr[i].chan; - lbs_pr_debug(1, "chan_no=%d\n", chan_no); + lbs_deb_wext("chan_no %d\n", chan_no); range->freq[range->num_frequency].i = (long)chan_no; range->freq[range->num_frequency].m = (long)libertas_chan_2_freq(chan_no, band) * 100000; @@ -808,7 +745,7 @@ static int wlan_get_range(struct net_device *dev, struct iw_request_info *info, } } - lbs_pr_debug(1, "IW_MAX_FREQUENCIES=%d num_frequency=%d\n", + lbs_deb_wext("IW_MAX_FREQUENCIES %d, num_frequency %d\n", IW_MAX_FREQUENCIES, range->num_frequency); range->num_channels = range->num_frequency; @@ -903,7 +840,8 @@ static int wlan_get_range(struct net_device *dev, struct iw_request_info *info, | IW_ENC_CAPA_CIPHER_CCMP; } - LEAVE(); +out: + lbs_deb_leave(LBS_DEB_WEXT); return 0; } @@ -913,7 +851,7 @@ static int wlan_set_power(struct net_device *dev, struct iw_request_info *info, wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); /* PS is currently supported only in Infrastructure mode * Remove this check if it is to be supported in IBSS mode also @@ -929,11 +867,11 @@ static int wlan_set_power(struct net_device *dev, struct iw_request_info *info, } if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { - lbs_pr_debug(1, - "Setting power timeout command is not supported\n"); + lbs_deb_wext( + "setting power timeout is not supported\n"); return -EINVAL; } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) { - lbs_pr_debug(1, "Setting power period command is not supported\n"); + lbs_deb_wext("setting power period not supported\n"); return -EINVAL; } @@ -947,7 +885,7 @@ static int wlan_set_power(struct net_device *dev, struct iw_request_info *info, libertas_ps_sleep(priv, cmd_option_waitforrsp); } - LEAVE(); + lbs_deb_leave(LBS_DEB_WEXT); return 0; } @@ -958,154 +896,23 @@ static int wlan_get_power(struct net_device *dev, struct iw_request_info *info, wlan_adapter *adapter = priv->adapter; int mode; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); mode = adapter->psmode; if ((vwrq->disabled = (mode == wlan802_11powermodecam)) - || adapter->connect_status == libertas_disconnected) { - LEAVE(); - return 0; + || adapter->connect_status == libertas_disconnected) + { + goto out; } vwrq->value = 0; - LEAVE(); +out: + lbs_deb_leave(LBS_DEB_WEXT); return 0; } -/* - * iwpriv settable callbacks - */ - -static const iw_handler wlan_private_handler[] = { - NULL, /* SIOCIWFIRSTPRIV */ -}; - -static const struct iw_priv_args wlan_private_args[] = { - /* - * { cmd, set_args, get_args, name } - */ - /* Using iwpriv sub-command feature */ - { - WLAN_SETONEINT_GETNONE, /* IOCTL: 24 */ - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, - ""}, - { - WLANSETREGION, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, - "setregioncode"}, - { - WLAN_SUBCMD_MESH_SET_TTL, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, - "mesh_set_ttl"}, - { - WLAN_SETNONE_GETONEINT, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - ""}, - { - WLANGETREGION, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "getregioncode"}, - { - WLAN_SUBCMD_FWT_CLEANUP, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "fwt_cleanup"}, - { - WLAN_SUBCMD_FWT_TIME, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "fwt_time"}, - { - WLAN_SUBCMD_MESH_GET_TTL, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "mesh_get_ttl"}, - { - WLAN_SETNONE_GETNONE, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_NONE, - ""}, - { - WLAN_SUBCMD_FWT_RESET, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_NONE, - "fwt_reset"}, - { - WLAN_SUBCMD_BT_RESET, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_NONE, - "bt_reset"}, - { - WLAN_SET128CHAR_GET128CHAR, - IW_PRIV_TYPE_CHAR | 128, - IW_PRIV_TYPE_CHAR | 128, - ""}, - /* BT Management */ - { - WLAN_SUBCMD_BT_ADD, - IW_PRIV_TYPE_CHAR | 128, - IW_PRIV_TYPE_CHAR | 128, - "bt_add"}, - { - WLAN_SUBCMD_BT_DEL, - IW_PRIV_TYPE_CHAR | 128, - IW_PRIV_TYPE_CHAR | 128, - "bt_del"}, - { - WLAN_SUBCMD_BT_LIST, - IW_PRIV_TYPE_CHAR | 128, - IW_PRIV_TYPE_CHAR | 128, - "bt_list"}, - /* FWT Management */ - { - WLAN_SUBCMD_FWT_ADD, - IW_PRIV_TYPE_CHAR | 128, - IW_PRIV_TYPE_CHAR | 128, - "fwt_add"}, - { - WLAN_SUBCMD_FWT_DEL, - IW_PRIV_TYPE_CHAR | 128, - IW_PRIV_TYPE_CHAR | 128, - "fwt_del"}, - { - WLAN_SUBCMD_FWT_LOOKUP, - IW_PRIV_TYPE_CHAR | 128, - IW_PRIV_TYPE_CHAR | 128, - "fwt_lookup"}, - { - WLAN_SUBCMD_FWT_LIST_NEIGHBOR, - IW_PRIV_TYPE_CHAR | 128, - IW_PRIV_TYPE_CHAR | 128, - "fwt_list_neigh"}, - { - WLAN_SUBCMD_FWT_LIST, - IW_PRIV_TYPE_CHAR | 128, - IW_PRIV_TYPE_CHAR | 128, - "fwt_list"}, - { - WLAN_SUBCMD_FWT_LIST_ROUTE, - IW_PRIV_TYPE_CHAR | 128, - IW_PRIV_TYPE_CHAR | 128, - "fwt_list_route"}, - { - WLAN_SET_GET_SIXTEEN_INT, - IW_PRIV_TYPE_INT | 16, - IW_PRIV_TYPE_INT | 16, - ""}, - { - WLAN_LED_GPIO_CTRL, - IW_PRIV_TYPE_INT | 16, - IW_PRIV_TYPE_INT | 16, - "ledgpio"}, -}; - static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev) { enum { @@ -1125,7 +932,7 @@ static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev) u8 rssi; u32 tx_retries; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); priv->wstats.status = adapter->mode; @@ -1145,8 +952,8 @@ static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev) CAL_NF(adapter->NF[TYPE_BEACON][TYPE_NOAVG]); } - lbs_pr_debug(1, "Signal Level = %#x\n", priv->wstats.qual.level); - lbs_pr_debug(1, "Noise = %#x\n", priv->wstats.qual.noise); + lbs_deb_wext("signal level %#x\n", priv->wstats.qual.level); + lbs_deb_wext("noise %#x\n", priv->wstats.qual.noise); rssi = priv->wstats.qual.level - priv->wstats.qual.noise; if (rssi < 15) @@ -1166,7 +973,7 @@ static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev) /* Quality by TX errors */ priv->wstats.discard.retries = priv->stats.tx_errors; - tx_retries = adapter->logmsg.retry; + tx_retries = le16_to_cpu(adapter->logmsg.retry); if (tx_retries > 75) tx_qual = (90 - tx_retries) * POOR / 15; @@ -1182,10 +989,10 @@ static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev) (PERFECT - VERY_GOOD) / 50 + VERY_GOOD; quality = min(quality, tx_qual); - priv->wstats.discard.code = adapter->logmsg.wepundecryptable; - priv->wstats.discard.fragment = adapter->logmsg.fcserror; + priv->wstats.discard.code = le16_to_cpu(adapter->logmsg.wepundecryptable); + priv->wstats.discard.fragment = le16_to_cpu(adapter->logmsg.rxfrag); priv->wstats.discard.retries = tx_retries; - priv->wstats.discard.misc = adapter->logmsg.ackfailure; + priv->wstats.discard.misc = le16_to_cpu(adapter->logmsg.ackfailure); /* Calculate quality */ priv->wstats.qual.qual = max(quality, (u32)100); @@ -1209,7 +1016,7 @@ out: IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID; } - LEAVE (); + lbs_deb_leave(LBS_DEB_WEXT); return &priv->wstats; @@ -1218,81 +1025,59 @@ out: static int wlan_set_freq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *fwrq, char *extra) { - int ret = 0; + int ret = -EINVAL; wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; - int rc = -EINPROGRESS; /* Call commit handler */ struct chan_freq_power *cfp; + struct assoc_request * assoc_req; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); - /* - * If setting by frequency, convert to a channel - */ - if (fwrq->e == 1) { + mutex_lock(&adapter->lock); + assoc_req = wlan_get_association_request(adapter); + if (!assoc_req) { + ret = -ENOMEM; + goto out; + } + /* If setting by frequency, convert to a channel */ + if (fwrq->e == 1) { long f = fwrq->m / 100000; - int c = 0; cfp = find_cfp_by_band_and_freq(adapter, 0, f); if (!cfp) { - lbs_pr_debug(1, "Invalid freq=%ld\n", f); - return -EINVAL; + lbs_deb_wext("invalid freq %ld\n", f); + goto out; } - c = (int)cfp->channel; - - if (c < 0) - return -EINVAL; - fwrq->e = 0; - fwrq->m = c; + fwrq->m = (int) cfp->channel; } - /* - * Setting by channel number - */ + /* Setting by channel number */ if (fwrq->m > 1000 || fwrq->e > 0) { - rc = -EOPNOTSUPP; - } else { - int channel = fwrq->m; + goto out; + } - cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, channel); - if (!cfp) { - rc = -EINVAL; - } else { - if (adapter->mode == IW_MODE_ADHOC) { - rc = changeadhocchannel(priv, channel); - /* If station is WEP enabled, send the - * command to set WEP in firmware - */ - if (adapter->secinfo.wep_enabled) { - lbs_pr_debug(1, "set_freq: WEP enabled\n"); - ret = libertas_prepare_and_send_command(priv, - cmd_802_11_set_wep, - cmd_act_add, - cmd_option_waitforrsp, - 0, - NULL); - - if (ret) { - LEAVE(); - return ret; - } - - adapter->currentpacketfilter |= - cmd_act_mac_wep_enable; - - libertas_set_mac_packet_filter(priv); - } - } else { - rc = -EOPNOTSUPP; - } - } + cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, fwrq->m); + if (!cfp) { + goto out; } - LEAVE(); - return rc; + assoc_req->channel = fwrq->m; + ret = 0; + +out: + if (ret == 0) { + set_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags); + wlan_postpone_association_work(priv); + } else { + wlan_cancel_association_work(priv); + } + mutex_unlock(&adapter->lock); + + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); + return ret; } /** @@ -1338,9 +1123,9 @@ static int wlan_set_rate(struct net_device *dev, struct iw_request_info *info, u8 rates[WLAN_SUPPORTED_RATES]; u8 *rate; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); - lbs_pr_debug(1, "Vwrq->value = %d\n", vwrq->value); + lbs_deb_wext("vwrq->value %d\n", vwrq->value); if (vwrq->value == -1) { action = cmd_act_set_tx_auto; // Auto @@ -1357,15 +1142,15 @@ static int wlan_set_rate(struct net_device *dev, struct iw_request_info *info, get_active_data_rates(adapter, rates); rate = rates; while (*rate) { - lbs_pr_debug(1, "Rate=0x%X Wanted=0x%X\n", *rate, + lbs_deb_wext("rate=0x%X, wanted data_rate 0x%X\n", *rate, data_rate); if ((*rate & 0x7f) == (data_rate & 0x7f)) break; rate++; } if (!*rate) { - lbs_pr_alert( "The fixed data rate 0x%X is out " - "of range.\n", data_rate); + lbs_pr_alert("fixed data rate 0x%X out " + "of range\n", data_rate); return -EINVAL; } @@ -1377,7 +1162,7 @@ static int wlan_set_rate(struct net_device *dev, struct iw_request_info *info, ret = libertas_prepare_and_send_command(priv, cmd_802_11_data_rate, action, cmd_option_waitforrsp, 0, NULL); - LEAVE(); + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret; } @@ -1387,7 +1172,7 @@ static int wlan_get_rate(struct net_device *dev, struct iw_request_info *info, wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); if (adapter->is_datarate_auto) { vwrq->fixed = 0; @@ -1397,7 +1182,7 @@ static int wlan_get_rate(struct net_device *dev, struct iw_request_info *info, vwrq->value = adapter->datarate * 500000; - LEAVE(); + lbs_deb_leave(LBS_DEB_WEXT); return 0; } @@ -1409,12 +1194,12 @@ static int wlan_set_mode(struct net_device *dev, wlan_adapter *adapter = priv->adapter; struct assoc_request * assoc_req; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); if ( (*uwrq != IW_MODE_ADHOC) && (*uwrq != IW_MODE_INFRA) && (*uwrq != IW_MODE_AUTO)) { - lbs_pr_debug(1, "Invalid mode: 0x%x\n", *uwrq); + lbs_deb_wext("Invalid mode: 0x%x\n", *uwrq); ret = -EINVAL; goto out; } @@ -1428,12 +1213,12 @@ static int wlan_set_mode(struct net_device *dev, assoc_req->mode = *uwrq; set_bit(ASSOC_FLAG_MODE, &assoc_req->flags); wlan_postpone_association_work(priv); - lbs_pr_debug(1, "Switching to mode: 0x%x\n", *uwrq); + lbs_deb_wext("Switching to mode: 0x%x\n", *uwrq); } mutex_unlock(&adapter->lock); out: - LEAVE(); + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret; } @@ -1455,9 +1240,9 @@ static int wlan_get_encode(struct net_device *dev, wlan_adapter *adapter = priv->adapter; int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); - lbs_pr_debug(1, "flags=0x%x index=%d length=%d wep_tx_keyidx=%d\n", + lbs_deb_wext("flags 0x%x, index %d, length %d, wep_tx_keyidx %d\n", dwrq->flags, index, dwrq->length, adapter->wep_tx_keyidx); dwrq->flags = 0; @@ -1513,13 +1298,13 @@ static int wlan_get_encode(struct net_device *dev, dwrq->flags |= IW_ENCODE_NOKEY; - lbs_pr_debug(1, "key:%02x:%02x:%02x:%02x:%02x:%02x keylen=%d\n", + lbs_deb_wext("key: " MAC_FMT ", keylen %d\n", extra[0], extra[1], extra[2], extra[3], extra[4], extra[5], dwrq->length); - lbs_pr_debug(1, "Return flags=0x%x\n", dwrq->flags); + lbs_deb_wext("return flags 0x%x\n", dwrq->flags); - LEAVE(); + lbs_deb_leave(LBS_DEB_WEXT); return 0; } @@ -1539,20 +1324,21 @@ static int wlan_set_wep_key(struct assoc_request *assoc_req, u16 index, int set_tx_key) { + int ret = 0; struct WLAN_802_11_KEY *pkey; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); /* Paranoid validation of key index */ if (index > 3) { - LEAVE(); - return -EINVAL; + ret = -EINVAL; + goto out; } /* validate max key length */ if (key_length > KEY_LEN_WEP_104) { - LEAVE(); - return -EINVAL; + ret = -EINVAL; + goto out; } pkey = &assoc_req->wep_keys[index]; @@ -1570,17 +1356,18 @@ static int wlan_set_wep_key(struct assoc_request *assoc_req, if (set_tx_key) { /* Ensure the chosen key is valid */ if (!pkey->len) { - lbs_pr_debug(1, "key not set, so cannot enable it\n"); - LEAVE(); - return -EINVAL; + lbs_deb_wext("key not set, so cannot enable it\n"); + ret = -EINVAL; + goto out; } assoc_req->wep_tx_keyidx = index; } assoc_req->secinfo.wep_enabled = 1; - LEAVE(); - return 0; +out: + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); + return ret; } static int validate_key_index(u16 def_index, u16 raw_index, @@ -1605,6 +1392,8 @@ static void disable_wep(struct assoc_request *assoc_req) { int i; + lbs_deb_enter(LBS_DEB_WEXT); + /* Set Open System auth mode */ assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; @@ -1615,6 +1404,27 @@ static void disable_wep(struct assoc_request *assoc_req) set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); + + lbs_deb_leave(LBS_DEB_WEXT); +} + +static void disable_wpa(struct assoc_request *assoc_req) +{ + lbs_deb_enter(LBS_DEB_WEXT); + + memset(&assoc_req->wpa_mcast_key, 0, sizeof (struct WLAN_802_11_KEY)); + assoc_req->wpa_mcast_key.flags = KEY_INFO_WPA_MCAST; + set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags); + + memset(&assoc_req->wpa_unicast_key, 0, sizeof (struct WLAN_802_11_KEY)); + assoc_req->wpa_unicast_key.flags = KEY_INFO_WPA_UNICAST; + set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags); + + assoc_req->secinfo.WPAenabled = 0; + assoc_req->secinfo.WPA2enabled = 0; + set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); + + lbs_deb_leave(LBS_DEB_WEXT); } /** @@ -1636,7 +1446,7 @@ static int wlan_set_encode(struct net_device *dev, struct assoc_request * assoc_req; u16 is_default = 0, index = 0, set_tx_key = 0; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); mutex_lock(&adapter->lock); assoc_req = wlan_get_association_request(adapter); @@ -1647,6 +1457,7 @@ static int wlan_set_encode(struct net_device *dev, if (dwrq->flags & IW_ENCODE_DISABLED) { disable_wep (assoc_req); + disable_wpa (assoc_req); goto out; } @@ -1688,7 +1499,7 @@ out: } mutex_unlock(&adapter->lock); - LEAVE(); + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret; } @@ -1712,7 +1523,7 @@ static int wlan_get_encodeext(struct net_device *dev, struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; int index, max_key_len; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); max_key_len = dwrq->length - sizeof(*ext); if (max_key_len < 0) @@ -1748,6 +1559,7 @@ static int wlan_get_encodeext(struct net_device *dev, if ( adapter->secinfo.wep_enabled && !adapter->secinfo.WPAenabled && !adapter->secinfo.WPA2enabled) { + /* WEP */ ext->alg = IW_ENCODE_ALG_WEP; ext->key_len = adapter->wep_keys[index].len; key = &adapter->wep_keys[index].key[0]; @@ -1755,8 +1567,27 @@ static int wlan_get_encodeext(struct net_device *dev, && (adapter->secinfo.WPAenabled || adapter->secinfo.WPA2enabled)) { /* WPA */ - ext->alg = IW_ENCODE_ALG_TKIP; - ext->key_len = 0; + struct WLAN_802_11_KEY * pkey = NULL; + + if ( adapter->wpa_mcast_key.len + && (adapter->wpa_mcast_key.flags & KEY_INFO_WPA_ENABLED)) + pkey = &adapter->wpa_mcast_key; + else if ( adapter->wpa_unicast_key.len + && (adapter->wpa_unicast_key.flags & KEY_INFO_WPA_ENABLED)) + pkey = &adapter->wpa_unicast_key; + + if (pkey) { + if (pkey->type == KEY_TYPE_ID_AES) { + ext->alg = IW_ENCODE_ALG_CCMP; + } else { + ext->alg = IW_ENCODE_ALG_TKIP; + } + ext->key_len = pkey->len; + key = &pkey->key[0]; + } else { + ext->alg = IW_ENCODE_ALG_TKIP; + ext->key_len = 0; + } } else { goto out; } @@ -1775,7 +1606,7 @@ static int wlan_get_encodeext(struct net_device *dev, ret = 0; out: - LEAVE(); + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret; } @@ -1800,7 +1631,7 @@ static int wlan_set_encodeext(struct net_device *dev, int alg = ext->alg; struct assoc_request * assoc_req; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); mutex_lock(&adapter->lock); assoc_req = wlan_get_association_request(adapter); @@ -1811,6 +1642,7 @@ static int wlan_set_encodeext(struct net_device *dev, if ((alg == IW_ENCODE_ALG_NONE) || (dwrq->flags & IW_ENCODE_DISABLED)) { disable_wep (assoc_req); + disable_wpa (assoc_req); } else if (alg == IW_ENCODE_ALG_WEP) { u16 is_default = 0, index, set_tx_key = 0; @@ -1846,7 +1678,6 @@ static int wlan_set_encodeext(struct net_device *dev, set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); if (set_tx_key) set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags); - } else if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) { struct WLAN_802_11_KEY * pkey; @@ -1855,36 +1686,43 @@ static int wlan_set_encodeext(struct net_device *dev, && (ext->key_len != KEY_LEN_WPA_TKIP)) || ((alg == IW_ENCODE_ALG_CCMP) && (ext->key_len != KEY_LEN_WPA_AES))) { - lbs_pr_debug(1, "Invalid size %d for key of alg" - "type %d.\n", + lbs_deb_wext("invalid size %d for key of alg" + "type %d\n", ext->key_len, alg); ret = -EINVAL; goto out; } - if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) + if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { pkey = &assoc_req->wpa_mcast_key; - else + set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags); + } else { pkey = &assoc_req->wpa_unicast_key; + set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags); + } memset(pkey, 0, sizeof (struct WLAN_802_11_KEY)); memcpy(pkey->key, ext->key, ext->key_len); pkey->len = ext->key_len; - pkey->flags = KEY_INFO_WPA_ENABLED; + if (pkey->len) + pkey->flags |= KEY_INFO_WPA_ENABLED; + /* Do this after zeroing key structure */ if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { pkey->flags |= KEY_INFO_WPA_MCAST; - set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags); } else { pkey->flags |= KEY_INFO_WPA_UNICAST; - set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags); } - if (alg == IW_ENCODE_ALG_TKIP) + if (alg == IW_ENCODE_ALG_TKIP) { pkey->type = KEY_TYPE_ID_TKIP; - else if (alg == IW_ENCODE_ALG_CCMP) + } else if (alg == IW_ENCODE_ALG_CCMP) { pkey->type = KEY_TYPE_ID_AES; + } else { + ret = -EINVAL; + goto out; + } /* If WPA isn't enabled yet, do that now */ if ( assoc_req->secinfo.WPAenabled == 0 @@ -1905,7 +1743,7 @@ out: } mutex_unlock(&adapter->lock); - LEAVE(); + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret; } @@ -1920,7 +1758,7 @@ static int wlan_set_genie(struct net_device *dev, int ret = 0; struct assoc_request * assoc_req; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); mutex_lock(&adapter->lock); assoc_req = wlan_get_association_request(adapter); @@ -1952,7 +1790,7 @@ out: } mutex_unlock(&adapter->lock); - LEAVE(); + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret; } @@ -1961,27 +1799,28 @@ static int wlan_get_genie(struct net_device *dev, struct iw_point *dwrq, char *extra) { + int ret = 0; wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); if (adapter->wpa_ie_len == 0) { dwrq->length = 0; - LEAVE(); - return 0; + goto out; } if (dwrq->length < adapter->wpa_ie_len) { - LEAVE(); - return -E2BIG; + ret = -E2BIG; + goto out; } dwrq->length = adapter->wpa_ie_len; memcpy(extra, &adapter->wpa_ie[0], adapter->wpa_ie_len); - LEAVE(); - return 0; +out: + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); + return ret; } @@ -1996,7 +1835,7 @@ static int wlan_set_auth(struct net_device *dev, int ret = 0; int updated = 0; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); mutex_lock(&adapter->lock); assoc_req = wlan_get_association_request(adapter); @@ -2010,6 +1849,7 @@ static int wlan_set_auth(struct net_device *dev, case IW_AUTH_CIPHER_PAIRWISE: case IW_AUTH_CIPHER_GROUP: case IW_AUTH_KEY_MGMT: + case IW_AUTH_DROP_UNENCRYPTED: /* * libertas does not use these parameters */ @@ -2019,6 +1859,7 @@ static int wlan_set_auth(struct net_device *dev, if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) { assoc_req->secinfo.WPAenabled = 0; assoc_req->secinfo.WPA2enabled = 0; + disable_wpa (assoc_req); } if (dwrq->value & IW_AUTH_WPA_VERSION_WPA) { assoc_req->secinfo.WPAenabled = 1; @@ -2033,17 +1874,6 @@ static int wlan_set_auth(struct net_device *dev, updated = 1; break; - case IW_AUTH_DROP_UNENCRYPTED: - if (dwrq->value) { - adapter->currentpacketfilter |= - cmd_act_mac_strict_protection_enable; - } else { - adapter->currentpacketfilter &= - ~cmd_act_mac_strict_protection_enable; - } - updated = 1; - break; - case IW_AUTH_80211_AUTH_ALG: if (dwrq->value & IW_AUTH_ALG_SHARED_KEY) { assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY; @@ -2069,6 +1899,7 @@ static int wlan_set_auth(struct net_device *dev, } else { assoc_req->secinfo.WPAenabled = 0; assoc_req->secinfo.WPA2enabled = 0; + disable_wpa (assoc_req); } updated = 1; break; @@ -2088,7 +1919,7 @@ out: } mutex_unlock(&adapter->lock); - LEAVE(); + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret; } @@ -2097,10 +1928,11 @@ static int wlan_get_auth(struct net_device *dev, struct iw_param *dwrq, char *extra) { + int ret = 0; wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); switch (dwrq->flags & IW_AUTH_INDEX) { case IW_AUTH_WPA_VERSION: @@ -2113,13 +1945,6 @@ static int wlan_get_auth(struct net_device *dev, dwrq->value |= IW_AUTH_WPA_VERSION_DISABLED; break; - case IW_AUTH_DROP_UNENCRYPTED: - dwrq->value = 0; - if (adapter->currentpacketfilter & - cmd_act_mac_strict_protection_enable) - dwrq->value = 1; - break; - case IW_AUTH_80211_AUTH_ALG: dwrq->value = adapter->secinfo.auth_mode; break; @@ -2130,12 +1955,11 @@ static int wlan_get_auth(struct net_device *dev, break; default: - LEAVE(); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; } - LEAVE(); - return 0; + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); + return ret; } @@ -2148,7 +1972,7 @@ static int wlan_set_txpow(struct net_device *dev, struct iw_request_info *info, u16 dbm; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); if (vwrq->disabled) { wlan_radio_ioctl(priv, RADIO_OFF); @@ -2169,14 +1993,14 @@ static int wlan_set_txpow(struct net_device *dev, struct iw_request_info *info, if (vwrq->fixed == 0) dbm = 0xffff; - lbs_pr_debug(1, "<1>TXPOWER SET %d dbm.\n", dbm); + lbs_deb_wext("txpower set %d dbm\n", dbm); ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_tx_power, cmd_act_tx_power_opt_set_low, cmd_option_waitforrsp, 0, (void *)&dbm); - LEAVE(); + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret; } @@ -2186,7 +2010,8 @@ static int wlan_get_essid(struct net_device *dev, struct iw_request_info *info, wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); + /* * Note : if dwrq->flags != 0, we should get the relevant SSID from * the SSID list... @@ -2196,12 +2021,12 @@ static int wlan_get_essid(struct net_device *dev, struct iw_request_info *info, * Get the current SSID */ if (adapter->connect_status == libertas_connected) { - memcpy(extra, adapter->curbssparams.ssid.ssid, - adapter->curbssparams.ssid.ssidlength); - extra[adapter->curbssparams.ssid.ssidlength] = '\0'; + memcpy(extra, adapter->curbssparams.ssid, + adapter->curbssparams.ssid_len); + extra[adapter->curbssparams.ssid_len] = '\0'; } else { memset(extra, 0, 32); - extra[adapter->curbssparams.ssid.ssidlength] = '\0'; + extra[adapter->curbssparams.ssid_len] = '\0'; } /* * If none, we may want to get the one that was set @@ -2209,14 +2034,14 @@ static int wlan_get_essid(struct net_device *dev, struct iw_request_info *info, /* To make the driver backward compatible with WPA supplicant v0.2.4 */ if (dwrq->length == 32) /* check with WPA supplicant buffer size */ - dwrq->length = min_t(size_t, adapter->curbssparams.ssid.ssidlength, + dwrq->length = min_t(size_t, adapter->curbssparams.ssid_len, IW_ESSID_MAX_SIZE); else - dwrq->length = adapter->curbssparams.ssid.ssidlength + 1; + dwrq->length = adapter->curbssparams.ssid_len + 1; dwrq->flags = 1; /* active */ - LEAVE(); + lbs_deb_leave(LBS_DEB_WEXT); return 0; } @@ -2226,38 +2051,43 @@ static int wlan_set_essid(struct net_device *dev, struct iw_request_info *info, wlan_private *priv = dev->priv; wlan_adapter *adapter = priv->adapter; int ret = 0; - struct WLAN_802_11_SSID ssid; + u8 ssid[IW_ESSID_MAX_SIZE]; + u8 ssid_len = 0; struct assoc_request * assoc_req; - int ssid_len = dwrq->length; + int in_ssid_len = dwrq->length; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); /* * WE-20 and earlier NULL pad the end of the SSID and increment * SSID length so it can be used like a string. WE-21 and later don't, * but some userspace tools aren't able to cope with the change. */ - if ((ssid_len > 0) && (extra[ssid_len - 1] == '\0')) - ssid_len--; + if ((in_ssid_len > 0) && (extra[in_ssid_len - 1] == '\0')) + in_ssid_len--; /* Check the size of the string */ - if (ssid_len > IW_ESSID_MAX_SIZE) { + if (in_ssid_len > IW_ESSID_MAX_SIZE) { ret = -E2BIG; goto out; } - memset(&ssid, 0, sizeof(struct WLAN_802_11_SSID)); + memset(&ssid, 0, sizeof(ssid)); - if (!dwrq->flags || !ssid_len) { + if (!dwrq->flags || !in_ssid_len) { /* "any" SSID requested; leave SSID blank */ } else { /* Specific SSID requested */ - memcpy(&ssid.ssid, extra, ssid_len); - ssid.ssidlength = ssid_len; + memcpy(&ssid, extra, in_ssid_len); + ssid_len = in_ssid_len; } - lbs_pr_debug(1, "Requested new SSID = %s\n", - (ssid.ssidlength > 0) ? (char *)ssid.ssid : "any"); + if (!ssid_len) { + lbs_deb_wext("requested any SSID\n"); + } else { + lbs_deb_wext("requested SSID '%s'\n", + escape_essid(ssid, ssid_len)); + } out: mutex_lock(&adapter->lock); @@ -2268,7 +2098,8 @@ out: ret = -ENOMEM; } else { /* Copy the SSID to the association request */ - memcpy(&assoc_req->ssid, &ssid, sizeof(struct WLAN_802_11_SSID)); + memcpy(&assoc_req->ssid, &ssid, IW_ESSID_MAX_SIZE); + assoc_req->ssid_len = ssid_len; set_bit(ASSOC_FLAG_SSID, &assoc_req->flags); wlan_postpone_association_work(priv); } @@ -2281,7 +2112,7 @@ out: mutex_unlock(&adapter->lock); - LEAVE(); + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret; } @@ -2302,12 +2133,12 @@ static int wlan_set_wap(struct net_device *dev, struct iw_request_info *info, struct assoc_request * assoc_req; int ret = 0; - ENTER(); + lbs_deb_enter(LBS_DEB_WEXT); if (awrq->sa_family != ARPHRD_ETHER) return -EINVAL; - lbs_pr_debug(1, "ASSOC: WAP: sa_data: " MAC_FMT "\n", MAC_ARG(awrq->sa_data)); + lbs_deb_wext("ASSOC: WAP: sa_data " MAC_FMT "\n", MAC_ARG(awrq->sa_data)); mutex_lock(&adapter->lock); @@ -2330,22 +2161,23 @@ static int wlan_set_wap(struct net_device *dev, struct iw_request_info *info, void libertas_get_fwversion(wlan_adapter * adapter, char *fwversion, int maxlen) { - union { - u32 l; - u8 c[4]; - } ver; char fwver[32]; mutex_lock(&adapter->lock); - ver.l = adapter->fwreleasenumber; - mutex_unlock(&adapter->lock); - if (ver.c[3] == 0) - sprintf(fwver, "%u.%u.%u", ver.c[2], ver.c[1], ver.c[0]); + if (adapter->fwreleasenumber[3] == 0) + sprintf(fwver, "%u.%u.%u", + adapter->fwreleasenumber[2], + adapter->fwreleasenumber[1], + adapter->fwreleasenumber[0]); else sprintf(fwver, "%u.%u.%u.p%u", - ver.c[2], ver.c[1], ver.c[0], ver.c[3]); + adapter->fwreleasenumber[2], + adapter->fwreleasenumber[1], + adapter->fwreleasenumber[0], + adapter->fwreleasenumber[3]); + mutex_unlock(&adapter->lock); snprintf(fwversion, maxlen, fwver); } @@ -2411,13 +2243,71 @@ static const iw_handler wlan_handler[] = { (iw_handler) NULL, /* SIOCSIWPMKSA */ }; +static const iw_handler mesh_wlan_handler[] = { + (iw_handler) NULL, /* SIOCSIWCOMMIT */ + (iw_handler) wlan_get_name, /* SIOCGIWNAME */ + (iw_handler) NULL, /* SIOCSIWNWID */ + (iw_handler) NULL, /* SIOCGIWNWID */ + (iw_handler) wlan_set_freq, /* SIOCSIWFREQ */ + (iw_handler) wlan_get_freq, /* SIOCGIWFREQ */ + (iw_handler) NULL, /* SIOCSIWMODE */ + (iw_handler) mesh_wlan_get_mode, /* SIOCGIWMODE */ + (iw_handler) NULL, /* SIOCSIWSENS */ + (iw_handler) NULL, /* SIOCGIWSENS */ + (iw_handler) NULL, /* SIOCSIWRANGE */ + (iw_handler) wlan_get_range, /* SIOCGIWRANGE */ + (iw_handler) NULL, /* SIOCSIWPRIV */ + (iw_handler) NULL, /* SIOCGIWPRIV */ + (iw_handler) NULL, /* SIOCSIWSTATS */ + (iw_handler) NULL, /* SIOCGIWSTATS */ + iw_handler_set_spy, /* SIOCSIWSPY */ + iw_handler_get_spy, /* SIOCGIWSPY */ + iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ + iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ + (iw_handler) NULL, /* SIOCSIWAP */ + (iw_handler) NULL, /* SIOCGIWAP */ + (iw_handler) NULL, /* SIOCSIWMLME */ + (iw_handler) NULL, /* SIOCGIWAPLIST - deprecated */ + (iw_handler) libertas_set_scan, /* SIOCSIWSCAN */ + (iw_handler) libertas_get_scan, /* SIOCGIWSCAN */ + (iw_handler) NULL, /* SIOCSIWESSID */ + (iw_handler) NULL, /* SIOCGIWESSID */ + (iw_handler) NULL, /* SIOCSIWNICKN */ + (iw_handler) mesh_get_nick, /* SIOCGIWNICKN */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) wlan_set_rate, /* SIOCSIWRATE */ + (iw_handler) wlan_get_rate, /* SIOCGIWRATE */ + (iw_handler) wlan_set_rts, /* SIOCSIWRTS */ + (iw_handler) wlan_get_rts, /* SIOCGIWRTS */ + (iw_handler) wlan_set_frag, /* SIOCSIWFRAG */ + (iw_handler) wlan_get_frag, /* SIOCGIWFRAG */ + (iw_handler) wlan_set_txpow, /* SIOCSIWTXPOW */ + (iw_handler) wlan_get_txpow, /* SIOCGIWTXPOW */ + (iw_handler) wlan_set_retry, /* SIOCSIWRETRY */ + (iw_handler) wlan_get_retry, /* SIOCGIWRETRY */ + (iw_handler) wlan_set_encode, /* SIOCSIWENCODE */ + (iw_handler) wlan_get_encode, /* SIOCGIWENCODE */ + (iw_handler) wlan_set_power, /* SIOCSIWPOWER */ + (iw_handler) wlan_get_power, /* SIOCGIWPOWER */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) wlan_set_genie, /* SIOCSIWGENIE */ + (iw_handler) wlan_get_genie, /* SIOCGIWGENIE */ + (iw_handler) wlan_set_auth, /* SIOCSIWAUTH */ + (iw_handler) wlan_get_auth, /* SIOCGIWAUTH */ + (iw_handler) wlan_set_encodeext,/* SIOCSIWENCODEEXT */ + (iw_handler) wlan_get_encodeext,/* SIOCGIWENCODEEXT */ + (iw_handler) NULL, /* SIOCSIWPMKSA */ +}; struct iw_handler_def libertas_handler_def = { .num_standard = sizeof(wlan_handler) / sizeof(iw_handler), - .num_private = sizeof(wlan_private_handler) / sizeof(iw_handler), - .num_private_args = sizeof(wlan_private_args) / - sizeof(struct iw_priv_args), .standard = (iw_handler *) wlan_handler, - .private = (iw_handler *) wlan_private_handler, - .private_args = (struct iw_priv_args *)wlan_private_args, + .get_wireless_stats = wlan_get_wireless_stats, +}; + +struct iw_handler_def mesh_handler_def = { + .num_standard = sizeof(mesh_wlan_handler) / sizeof(iw_handler), + .standard = (iw_handler *) mesh_wlan_handler, .get_wireless_stats = wlan_get_wireless_stats, }; diff --git a/drivers/net/wireless/libertas/wext.h b/drivers/net/wireless/libertas/wext.h index 15cfaaf0797..3d5196c9553 100644 --- a/drivers/net/wireless/libertas/wext.h +++ b/drivers/net/wireless/libertas/wext.h @@ -7,43 +7,6 @@ #define SUBCMD_OFFSET 4 #define SUBCMD_DATA(x) *((int *)(x->u.name + SUBCMD_OFFSET)) -/** PRIVATE CMD ID */ -#define WLANIOCTL SIOCIWFIRSTPRIV - -#define WLAN_SETNONE_GETNONE (WLANIOCTL + 8) -#define WLAN_SUBCMD_BT_RESET 13 -#define WLAN_SUBCMD_FWT_RESET 14 - -#define WLAN_SETNONE_GETONEINT (WLANIOCTL + 15) -#define WLANGETREGION 1 - -#define WLAN_SUBCMD_FWT_CLEANUP 15 -#define WLAN_SUBCMD_FWT_TIME 16 -#define WLAN_SUBCMD_MESH_GET_TTL 17 - -#define WLAN_SETONEINT_GETNONE (WLANIOCTL + 24) -#define WLANSETREGION 8 -#define WLAN_SUBCMD_MESH_SET_TTL 18 - -#define WLAN_SET128CHAR_GET128CHAR (WLANIOCTL + 25) -#define WLAN_SUBCMD_BT_ADD 18 -#define WLAN_SUBCMD_BT_DEL 19 -#define WLAN_SUBCMD_BT_LIST 20 -#define WLAN_SUBCMD_FWT_ADD 21 -#define WLAN_SUBCMD_FWT_DEL 22 -#define WLAN_SUBCMD_FWT_LOOKUP 23 -#define WLAN_SUBCMD_FWT_LIST_NEIGHBOR 24 -#define WLAN_SUBCMD_FWT_LIST 25 -#define WLAN_SUBCMD_FWT_LIST_ROUTE 26 - -#define WLAN_SET_GET_SIXTEEN_INT (WLANIOCTL + 29) -#define WLAN_LED_GPIO_CTRL 5 - -#define WLAN_LINKMODE_802_3 0 -#define WLAN_LINKMODE_802_11 2 -#define WLAN_RADIOMODE_NONE 0 -#define WLAN_RADIOMODE_RADIOTAP 2 - /** wlan_ioctl_regrdwr */ struct wlan_ioctl_regrdwr { /** Which register to access */ @@ -55,8 +18,13 @@ struct wlan_ioctl_regrdwr { u32 value; }; +#define WLAN_LINKMODE_802_3 0 +#define WLAN_LINKMODE_802_11 2 +#define WLAN_RADIOMODE_NONE 0 +#define WLAN_RADIOMODE_RADIOTAP 2 + extern struct iw_handler_def libertas_handler_def; -int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int i); +extern struct iw_handler_def mesh_handler_def; int wlan_radio_ioctl(wlan_private * priv, u8 option); #endif /* _WLAN_WEXT_H_ */ diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c index 3dcb13bb7d5..af2e4f2405f 100644 --- a/drivers/net/wireless/prism54/islpci_hotplug.c +++ b/drivers/net/wireless/prism54/islpci_hotplug.c @@ -87,7 +87,6 @@ static struct pci_driver prism54_driver = { .remove = prism54_remove, .suspend = prism54_suspend, .resume = prism54_resume, - /* .enable_wake ; we don't support this yet */ }; /****************************************************************************** @@ -167,8 +166,7 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_master(pdev); /* enable MWI */ - if (!pci_set_mwi(pdev)) - printk(KERN_INFO "%s: pci_set_mwi(pdev) succeeded\n", DRV_NAME); + pci_try_set_mwi(pdev); /* setup the network device interface and its structure */ if (!(ndev = islpci_setup(pdev))) { diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h new file mode 100644 index 00000000000..6124e467b15 --- /dev/null +++ b/drivers/net/wireless/rtl8187.h @@ -0,0 +1,145 @@ +/* + * Definitions for RTL8187 hardware + * + * Copyright 2007 Michael Wu <flamingice@sourmilk.net> + * Copyright 2007 Andrea Merello <andreamrl@tiscali.it> + * + * Based on the r8187 driver, which is: + * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef RTL8187_H +#define RTL8187_H + +#include "rtl818x.h" + +#define RTL8187_EEPROM_TXPWR_BASE 0x05 +#define RTL8187_EEPROM_MAC_ADDR 0x07 +#define RTL8187_EEPROM_TXPWR_CHAN_1 0x16 /* 3 channels */ +#define RTL8187_EEPROM_TXPWR_CHAN_6 0x1B /* 2 channels */ +#define RTL8187_EEPROM_TXPWR_CHAN_4 0x3D /* 2 channels */ + +#define RTL8187_REQT_READ 0xC0 +#define RTL8187_REQT_WRITE 0x40 +#define RTL8187_REQ_GET_REG 0x05 +#define RTL8187_REQ_SET_REG 0x05 + +#define RTL8187_MAX_RX 0x9C4 + +struct rtl8187_rx_info { + struct urb *urb; + struct ieee80211_hw *dev; +}; + +struct rtl8187_rx_hdr { + __le16 len; + __le16 rate; + u8 noise; + u8 signal; + u8 agc; + u8 reserved; + __le64 mac_time; +} __attribute__((packed)); + +struct rtl8187_tx_info { + struct ieee80211_tx_control *control; + struct urb *urb; + struct ieee80211_hw *dev; +}; + +struct rtl8187_tx_hdr { + __le32 flags; +#define RTL8187_TX_FLAG_NO_ENCRYPT (1 << 15) +#define RTL8187_TX_FLAG_MORE_FRAG (1 << 17) +#define RTL8187_TX_FLAG_CTS (1 << 18) +#define RTL8187_TX_FLAG_RTS (1 << 23) + __le16 rts_duration; + __le16 len; + __le32 retry; +} __attribute__((packed)); + +struct rtl8187_priv { + /* common between rtl818x drivers */ + struct rtl818x_csr *map; + void (*rf_init)(struct ieee80211_hw *); + int mode; + + /* rtl8187 specific */ + struct ieee80211_channel channels[14]; + struct ieee80211_rate rates[12]; + struct ieee80211_hw_mode modes[2]; + struct usb_device *udev; + u8 *hwaddr; + u16 txpwr_base; + u8 asic_rev; + struct sk_buff_head rx_queue; +}; + +void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data); + +static inline u8 rtl818x_ioread8(struct rtl8187_priv *priv, u8 *addr) +{ + u8 val; + + usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), + RTL8187_REQ_GET_REG, RTL8187_REQT_READ, + (unsigned long)addr, 0, &val, sizeof(val), HZ / 2); + + return val; +} + +static inline u16 rtl818x_ioread16(struct rtl8187_priv *priv, __le16 *addr) +{ + __le16 val; + + usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), + RTL8187_REQ_GET_REG, RTL8187_REQT_READ, + (unsigned long)addr, 0, &val, sizeof(val), HZ / 2); + + return le16_to_cpu(val); +} + +static inline u32 rtl818x_ioread32(struct rtl8187_priv *priv, __le32 *addr) +{ + __le32 val; + + usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), + RTL8187_REQ_GET_REG, RTL8187_REQT_READ, + (unsigned long)addr, 0, &val, sizeof(val), HZ / 2); + + return le32_to_cpu(val); +} + +static inline void rtl818x_iowrite8(struct rtl8187_priv *priv, + u8 *addr, u8 val) +{ + usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), + RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, + (unsigned long)addr, 0, &val, sizeof(val), HZ / 2); +} + +static inline void rtl818x_iowrite16(struct rtl8187_priv *priv, + __le16 *addr, u16 val) +{ + __le16 buf = cpu_to_le16(val); + + usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), + RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, + (unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2); +} + +static inline void rtl818x_iowrite32(struct rtl8187_priv *priv, + __le32 *addr, u32 val) +{ + __le32 buf = cpu_to_le32(val); + + usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), + RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, + (unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2); +} + +#endif /* RTL8187_H */ diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c new file mode 100644 index 00000000000..cea85894b7f --- /dev/null +++ b/drivers/net/wireless/rtl8187_dev.c @@ -0,0 +1,731 @@ +/* + * Linux device driver for RTL8187 + * + * Copyright 2007 Michael Wu <flamingice@sourmilk.net> + * Copyright 2007 Andrea Merello <andreamrl@tiscali.it> + * + * Based on the r8187 driver, which is: + * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al. + * + * Magic delays and register offsets below are taken from the original + * r8187 driver sources. Thanks to Realtek for their support! + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/usb.h> +#include <linux/delay.h> +#include <linux/etherdevice.h> +#include <linux/eeprom_93cx6.h> +#include <net/mac80211.h> + +#include "rtl8187.h" +#include "rtl8187_rtl8225.h" + +MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>"); +MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>"); +MODULE_DESCRIPTION("RTL8187 USB wireless driver"); +MODULE_LICENSE("GPL"); + +static struct usb_device_id rtl8187_table[] __devinitdata = { + /* Realtek */ + {USB_DEVICE(0x0bda, 0x8187)}, + /* Netgear */ + {USB_DEVICE(0x0846, 0x6100)}, + {USB_DEVICE(0x0846, 0x6a00)}, + {} +}; + +MODULE_DEVICE_TABLE(usb, rtl8187_table); + +void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) +{ + struct rtl8187_priv *priv = dev->priv; + + data <<= 8; + data |= addr | 0x80; + + rtl818x_iowrite8(priv, &priv->map->PHY[3], (data >> 24) & 0xFF); + rtl818x_iowrite8(priv, &priv->map->PHY[2], (data >> 16) & 0xFF); + rtl818x_iowrite8(priv, &priv->map->PHY[1], (data >> 8) & 0xFF); + rtl818x_iowrite8(priv, &priv->map->PHY[0], data & 0xFF); + + msleep(1); +} + +static void rtl8187_tx_cb(struct urb *urb) +{ + struct ieee80211_tx_status status = { {0} }; + struct sk_buff *skb = (struct sk_buff *)urb->context; + struct rtl8187_tx_info *info = (struct rtl8187_tx_info *)skb->cb; + + usb_free_urb(info->urb); + if (info->control) + memcpy(&status.control, info->control, sizeof(status.control)); + kfree(info->control); + skb_pull(skb, sizeof(struct rtl8187_tx_hdr)); + status.flags |= IEEE80211_TX_STATUS_ACK; + ieee80211_tx_status_irqsafe(info->dev, skb, &status); +} + +static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb, + struct ieee80211_tx_control *control) +{ + struct rtl8187_priv *priv = dev->priv; + struct rtl8187_tx_hdr *hdr; + struct rtl8187_tx_info *info; + struct urb *urb; + u32 tmp; + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) { + kfree_skb(skb); + return 0; + } + + hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr)); + tmp = skb->len - sizeof(*hdr); + tmp |= RTL8187_TX_FLAG_NO_ENCRYPT; + tmp |= control->rts_cts_rate << 19; + tmp |= control->tx_rate << 24; + if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb)) + tmp |= RTL8187_TX_FLAG_MORE_FRAG; + if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) { + tmp |= RTL8187_TX_FLAG_RTS; + hdr->rts_duration = + ieee80211_rts_duration(dev, skb->len, control); + } + if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) + tmp |= RTL8187_TX_FLAG_CTS; + hdr->flags = cpu_to_le32(tmp); + hdr->len = 0; + tmp = control->retry_limit << 8; + hdr->retry = cpu_to_le32(tmp); + + info = (struct rtl8187_tx_info *)skb->cb; + info->control = kmemdup(control, sizeof(*control), GFP_ATOMIC); + info->urb = urb; + info->dev = dev; + usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, 2), + hdr, skb->len, rtl8187_tx_cb, skb); + usb_submit_urb(urb, GFP_ATOMIC); + + return 0; +} + +static void rtl8187_rx_cb(struct urb *urb) +{ + struct sk_buff *skb = (struct sk_buff *)urb->context; + struct rtl8187_rx_info *info = (struct rtl8187_rx_info *)skb->cb; + struct ieee80211_hw *dev = info->dev; + struct rtl8187_priv *priv = dev->priv; + struct rtl8187_rx_hdr *hdr; + struct ieee80211_rx_status rx_status = { 0 }; + int rate, signal; + + spin_lock(&priv->rx_queue.lock); + if (skb->next) + __skb_unlink(skb, &priv->rx_queue); + else { + spin_unlock(&priv->rx_queue.lock); + return; + } + spin_unlock(&priv->rx_queue.lock); + + if (unlikely(urb->status)) { + usb_free_urb(urb); + dev_kfree_skb_irq(skb); + return; + } + + skb_put(skb, urb->actual_length); + hdr = (struct rtl8187_rx_hdr *)(skb_tail_pointer(skb) - sizeof(*hdr)); + skb_trim(skb, le16_to_cpu(hdr->len) & 0x0FFF); + + signal = hdr->agc >> 1; + rate = (le16_to_cpu(hdr->rate) >> 4) & 0xF; + if (rate > 3) { /* OFDM rate */ + if (signal > 90) + signal = 90; + else if (signal < 25) + signal = 25; + signal = 90 - signal; + } else { /* CCK rate */ + if (signal > 95) + signal = 95; + else if (signal < 30) + signal = 30; + signal = 95 - signal; + } + + rx_status.antenna = (hdr->signal >> 7) & 1; + rx_status.signal = 64 - min(hdr->noise, (u8)64); + rx_status.ssi = signal; + rx_status.rate = rate; + rx_status.freq = dev->conf.freq; + rx_status.channel = dev->conf.channel; + rx_status.phymode = dev->conf.phymode; + rx_status.mactime = le64_to_cpu(hdr->mac_time); + ieee80211_rx_irqsafe(dev, skb, &rx_status); + + skb = dev_alloc_skb(RTL8187_MAX_RX); + if (unlikely(!skb)) { + usb_free_urb(urb); + /* TODO check rx queue length and refill *somewhere* */ + return; + } + + info = (struct rtl8187_rx_info *)skb->cb; + info->urb = urb; + info->dev = dev; + urb->transfer_buffer = skb_tail_pointer(skb); + urb->context = skb; + skb_queue_tail(&priv->rx_queue, skb); + + usb_submit_urb(urb, GFP_ATOMIC); +} + +static int rtl8187_init_urbs(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + struct urb *entry; + struct sk_buff *skb; + struct rtl8187_rx_info *info; + + while (skb_queue_len(&priv->rx_queue) < 8) { + skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL); + if (!skb) + break; + entry = usb_alloc_urb(0, GFP_KERNEL); + if (!entry) { + kfree_skb(skb); + break; + } + usb_fill_bulk_urb(entry, priv->udev, + usb_rcvbulkpipe(priv->udev, 1), + skb_tail_pointer(skb), + RTL8187_MAX_RX, rtl8187_rx_cb, skb); + info = (struct rtl8187_rx_info *)skb->cb; + info->urb = entry; + info->dev = dev; + skb_queue_tail(&priv->rx_queue, skb); + usb_submit_urb(entry, GFP_KERNEL); + } + + return 0; +} + +static int rtl8187_init_hw(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + u8 reg; + int i; + + /* reset */ + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + + rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); + + msleep(200); + rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x10); + rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x11); + rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x00); + msleep(200); + + reg = rtl818x_ioread8(priv, &priv->map->CMD); + reg &= (1 << 1); + reg |= RTL818X_CMD_RESET; + rtl818x_iowrite8(priv, &priv->map->CMD, reg); + + i = 10; + do { + msleep(2); + if (!(rtl818x_ioread8(priv, &priv->map->CMD) & + RTL818X_CMD_RESET)) + break; + } while (--i); + + if (!i) { + printk(KERN_ERR "%s: Reset timeout!\n", wiphy_name(dev->wiphy)); + return -ETIMEDOUT; + } + + /* reload registers from eeprom */ + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_LOAD); + + i = 10; + do { + msleep(4); + if (!(rtl818x_ioread8(priv, &priv->map->EEPROM_CMD) & + RTL818X_EEPROM_CMD_CONFIG)) + break; + } while (--i); + + if (!i) { + printk(KERN_ERR "%s: eeprom reset timeout!\n", + wiphy_name(dev->wiphy)); + return -ETIMEDOUT; + } + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + + /* setup card */ + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0); + rtl818x_iowrite8(priv, &priv->map->GPIO, 0); + + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8)); + rtl818x_iowrite8(priv, &priv->map->GPIO, 1); + rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0); + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + for (i = 0; i < ETH_ALEN; i++) + rtl818x_iowrite8(priv, &priv->map->MAC[i], priv->hwaddr[i]); + + rtl818x_iowrite16(priv, (__le16 *)0xFFF4, 0xFFFF); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG1); + reg &= 0x3F; + reg |= 0x80; + rtl818x_iowrite8(priv, &priv->map->CONFIG1, reg); + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + + rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0); + rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0); + rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0x81); + + // TODO: set RESP_RATE and BRSR properly + rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (8 << 4) | 0); + rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3); + + /* host_usb_init */ + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0); + rtl818x_iowrite8(priv, &priv->map->GPIO, 0); + reg = rtl818x_ioread8(priv, (u8 *)0xFE53); + rtl818x_iowrite8(priv, (u8 *)0xFE53, reg | (1 << 7)); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8)); + rtl818x_iowrite8(priv, &priv->map->GPIO, 0x20); + rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x80); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x80); + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x80); + msleep(100); + + rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008); + rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF); + rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FF7); + msleep(100); + + priv->rf_init(dev); + + rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3); + reg = rtl818x_ioread16(priv, &priv->map->PGSELECT) & 0xfffe; + rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg | 0x1); + rtl818x_iowrite16(priv, (__le16 *)0xFFFE, 0x10); + rtl818x_iowrite8(priv, &priv->map->TALLY_SEL, 0x80); + rtl818x_iowrite8(priv, (u8 *)0xFFFF, 0x60); + rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg); + + return 0; +} + +static void rtl8187_set_channel(struct ieee80211_hw *dev, int channel) +{ + u32 reg; + struct rtl8187_priv *priv = dev->priv; + + reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); + /* Enable TX loopback on MAC level to avoid TX during channel + * changes, as this has be seen to causes problems and the + * card will stop work until next reset + */ + rtl818x_iowrite32(priv, &priv->map->TX_CONF, + reg | RTL818X_TX_CONF_LOOPBACK_MAC); + msleep(10); + rtl8225_rf_set_channel(dev, channel); + msleep(10); + rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg); +} + +static int rtl8187_open(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + u32 reg; + int ret; + + ret = rtl8187_init_hw(dev); + if (ret) + return ret; + + rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); + + rtl8187_init_urbs(dev); + + reg = RTL818X_RX_CONF_ONLYERLPKT | + RTL818X_RX_CONF_RX_AUTORESETPHY | + RTL818X_RX_CONF_BSSID | + RTL818X_RX_CONF_MGMT | + RTL818X_RX_CONF_CTRL | + RTL818X_RX_CONF_DATA | + (7 << 13 /* RX FIFO threshold NONE */) | + (7 << 10 /* MAX RX DMA */) | + RTL818X_RX_CONF_BROADCAST | + RTL818X_RX_CONF_MULTICAST | + RTL818X_RX_CONF_NICMAC; + if (priv->mode == IEEE80211_IF_TYPE_MNTR) + reg |= RTL818X_RX_CONF_MONITOR; + + rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg); + + reg = rtl818x_ioread8(priv, &priv->map->CW_CONF); + reg &= ~RTL818X_CW_CONF_PERPACKET_CW_SHIFT; + reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT; + rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg); + + reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL); + reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT; + reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT; + reg &= ~RTL818X_TX_AGC_CTL_FEEDBACK_ANT; + rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg); + + reg = RTL818X_TX_CONF_CW_MIN | + (7 << 21 /* MAX TX DMA */) | + RTL818X_TX_CONF_NO_ICV; + rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg); + + reg = rtl818x_ioread8(priv, &priv->map->CMD); + reg |= RTL818X_CMD_TX_ENABLE; + reg |= RTL818X_CMD_RX_ENABLE; + rtl818x_iowrite8(priv, &priv->map->CMD, reg); + + return 0; +} + +static int rtl8187_stop(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + struct rtl8187_rx_info *info; + struct sk_buff *skb; + u32 reg; + + rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); + + reg = rtl818x_ioread8(priv, &priv->map->CMD); + reg &= ~RTL818X_CMD_TX_ENABLE; + reg &= ~RTL818X_CMD_RX_ENABLE; + rtl818x_iowrite8(priv, &priv->map->CMD, reg); + + rtl8225_rf_stop(dev); + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG4); + rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + + while ((skb = skb_dequeue(&priv->rx_queue))) { + info = (struct rtl8187_rx_info *)skb->cb; + usb_kill_urb(info->urb); + kfree_skb(skb); + } + return 0; +} + +static int rtl8187_add_interface(struct ieee80211_hw *dev, + struct ieee80211_if_init_conf *conf) +{ + struct rtl8187_priv *priv = dev->priv; + + /* NOTE: using IEEE80211_IF_TYPE_MGMT to indicate no mode selected */ + if (priv->mode != IEEE80211_IF_TYPE_MGMT) + return -1; + + switch (conf->type) { + case IEEE80211_IF_TYPE_STA: + case IEEE80211_IF_TYPE_MNTR: + priv->mode = conf->type; + break; + default: + return -EOPNOTSUPP; + } + + priv->hwaddr = conf->mac_addr; + + return 0; +} + +static void rtl8187_remove_interface(struct ieee80211_hw *dev, + struct ieee80211_if_init_conf *conf) +{ + struct rtl8187_priv *priv = dev->priv; + priv->mode = IEEE80211_IF_TYPE_MGMT; +} + +static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) +{ + struct rtl8187_priv *priv = dev->priv; + rtl8187_set_channel(dev, conf->channel); + + rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); + + if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) { + rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9); + rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14); + rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14); + rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73); + } else { + rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14); + rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24); + rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24); + rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5); + } + + rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2); + rtl818x_iowrite16(priv, &priv->map->ATIMTR_INTERVAL, 100); + rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100); + rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL_TIME, 100); + return 0; +} + +static int rtl8187_config_interface(struct ieee80211_hw *dev, int if_id, + struct ieee80211_if_conf *conf) +{ + struct rtl8187_priv *priv = dev->priv; + int i; + + for (i = 0; i < ETH_ALEN; i++) + rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]); + + if (is_valid_ether_addr(conf->bssid)) + rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_INFRA); + else + rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_NO_LINK); + + return 0; +} + +static const struct ieee80211_ops rtl8187_ops = { + .tx = rtl8187_tx, + .open = rtl8187_open, + .stop = rtl8187_stop, + .add_interface = rtl8187_add_interface, + .remove_interface = rtl8187_remove_interface, + .config = rtl8187_config, + .config_interface = rtl8187_config_interface, +}; + +static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom) +{ + struct ieee80211_hw *dev = eeprom->data; + struct rtl8187_priv *priv = dev->priv; + u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + + eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE; + eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ; + eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK; + eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS; +} + +static void rtl8187_eeprom_register_write(struct eeprom_93cx6 *eeprom) +{ + struct ieee80211_hw *dev = eeprom->data; + struct rtl8187_priv *priv = dev->priv; + u8 reg = RTL818X_EEPROM_CMD_PROGRAM; + + if (eeprom->reg_data_in) + reg |= RTL818X_EEPROM_CMD_WRITE; + if (eeprom->reg_data_out) + reg |= RTL818X_EEPROM_CMD_READ; + if (eeprom->reg_data_clock) + reg |= RTL818X_EEPROM_CMD_CK; + if (eeprom->reg_chip_select) + reg |= RTL818X_EEPROM_CMD_CS; + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, reg); + udelay(10); +} + +static int __devinit rtl8187_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct ieee80211_hw *dev; + struct rtl8187_priv *priv; + struct eeprom_93cx6 eeprom; + struct ieee80211_channel *channel; + u16 txpwr, reg; + int err, i; + + dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops); + if (!dev) { + printk(KERN_ERR "rtl8187: ieee80211 alloc failed\n"); + return -ENOMEM; + } + + priv = dev->priv; + + SET_IEEE80211_DEV(dev, &intf->dev); + usb_set_intfdata(intf, dev); + priv->udev = udev; + + usb_get_dev(udev); + + skb_queue_head_init(&priv->rx_queue); + memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels)); + memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates)); + priv->map = (struct rtl818x_csr *)0xFF00; + priv->modes[0].mode = MODE_IEEE80211G; + priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates); + priv->modes[0].rates = priv->rates; + priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels); + priv->modes[0].channels = priv->channels; + priv->modes[1].mode = MODE_IEEE80211B; + priv->modes[1].num_rates = 4; + priv->modes[1].rates = priv->rates; + priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels); + priv->modes[1].channels = priv->channels; + priv->mode = IEEE80211_IF_TYPE_MGMT; + dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | + IEEE80211_HW_RX_INCLUDES_FCS | + IEEE80211_HW_WEP_INCLUDE_IV | + IEEE80211_HW_DATA_NULLFUNC_ACK; + dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr); + dev->queues = 1; + dev->max_rssi = 65; + dev->max_signal = 64; + + for (i = 0; i < 2; i++) + if ((err = ieee80211_register_hwmode(dev, &priv->modes[i]))) + goto err_free_dev; + + eeprom.data = dev; + eeprom.register_read = rtl8187_eeprom_register_read; + eeprom.register_write = rtl8187_eeprom_register_write; + if (rtl818x_ioread32(priv, &priv->map->RX_CONF) & (1 << 6)) + eeprom.width = PCI_EEPROM_WIDTH_93C66; + else + eeprom.width = PCI_EEPROM_WIDTH_93C46; + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + udelay(10); + + eeprom_93cx6_multiread(&eeprom, RTL8187_EEPROM_MAC_ADDR, + (__le16 __force *)dev->wiphy->perm_addr, 3); + if (!is_valid_ether_addr(dev->wiphy->perm_addr)) { + printk(KERN_WARNING "rtl8187: Invalid hwaddr! Using randomly " + "generated MAC address\n"); + random_ether_addr(dev->wiphy->perm_addr); + } + + channel = priv->channels; + for (i = 0; i < 3; i++) { + eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_1 + i, + &txpwr); + (*channel++).val = txpwr & 0xFF; + (*channel++).val = txpwr >> 8; + } + for (i = 0; i < 2; i++) { + eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_4 + i, + &txpwr); + (*channel++).val = txpwr & 0xFF; + (*channel++).val = txpwr >> 8; + } + for (i = 0; i < 2; i++) { + eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6 + i, + &txpwr); + (*channel++).val = txpwr & 0xFF; + (*channel++).val = txpwr >> 8; + } + + eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE, + &priv->txpwr_base); + + reg = rtl818x_ioread16(priv, &priv->map->PGSELECT) & ~1; + rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg | 1); + /* 0 means asic B-cut, we should use SW 3 wire + * bit-by-bit banging for radio. 1 means we can use + * USB specific request to write radio registers */ + priv->asic_rev = rtl818x_ioread8(priv, (u8 *)0xFFFE) & 0x3; + rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + + rtl8225_write(dev, 0, 0x1B7); + + if (rtl8225_read(dev, 8) != 0x588 || rtl8225_read(dev, 9) != 0x700) + priv->rf_init = rtl8225_rf_init; + else + priv->rf_init = rtl8225z2_rf_init; + + rtl8225_write(dev, 0, 0x0B7); + + err = ieee80211_register_hw(dev); + if (err) { + printk(KERN_ERR "rtl8187: Cannot register device\n"); + goto err_free_dev; + } + + printk(KERN_INFO "%s: hwaddr " MAC_FMT ", rtl8187 V%d + %s\n", + wiphy_name(dev->wiphy), MAC_ARG(dev->wiphy->perm_addr), + priv->asic_rev, priv->rf_init == rtl8225_rf_init ? + "rtl8225" : "rtl8225z2"); + + return 0; + + err_free_dev: + ieee80211_free_hw(dev); + usb_set_intfdata(intf, NULL); + usb_put_dev(udev); + return err; +} + +static void __devexit rtl8187_disconnect(struct usb_interface *intf) +{ + struct ieee80211_hw *dev = usb_get_intfdata(intf); + struct rtl8187_priv *priv; + + if (!dev) + return; + + ieee80211_unregister_hw(dev); + + priv = dev->priv; + usb_put_dev(interface_to_usbdev(intf)); + ieee80211_free_hw(dev); +} + +static struct usb_driver rtl8187_driver = { + .name = KBUILD_MODNAME, + .id_table = rtl8187_table, + .probe = rtl8187_probe, + .disconnect = rtl8187_disconnect, +}; + +static int __init rtl8187_init(void) +{ + return usb_register(&rtl8187_driver); +} + +static void __exit rtl8187_exit(void) +{ + usb_deregister(&rtl8187_driver); +} + +module_init(rtl8187_init); +module_exit(rtl8187_exit); diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c new file mode 100644 index 00000000000..e25a09f1b06 --- /dev/null +++ b/drivers/net/wireless/rtl8187_rtl8225.c @@ -0,0 +1,745 @@ +/* + * Radio tuning for RTL8225 on RTL8187 + * + * Copyright 2007 Michael Wu <flamingice@sourmilk.net> + * Copyright 2007 Andrea Merello <andreamrl@tiscali.it> + * + * Based on the r8187 driver, which is: + * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al. + * + * Magic delays, register offsets, and phy value tables below are + * taken from the original r8187 driver sources. Thanks to Realtek + * for their support! + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/usb.h> +#include <net/mac80211.h> + +#include "rtl8187.h" +#include "rtl8187_rtl8225.h" + +static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data) +{ + struct rtl8187_priv *priv = dev->priv; + u16 reg80, reg84, reg82; + u32 bangdata; + int i; + + bangdata = (data << 4) | (addr & 0xf); + + reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3; + reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable); + + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7); + + reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7); + udelay(10); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); + udelay(2); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80); + udelay(10); + + for (i = 15; i >= 0; i--) { + u16 reg = reg80 | (bangdata & (1 << i)) >> i; + + if (i & 1) + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1)); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1)); + + if (!(i & 1)) + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); + } + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); + udelay(10); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84); + msleep(2); +} + +static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, u16 data) +{ + struct rtl8187_priv *priv = dev->priv; + u16 reg80, reg82, reg84; + + reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput); + reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable); + reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect); + + reg80 &= ~(0x3 << 2); + reg84 &= ~0xF; + + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x0007); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x0007); + udelay(10); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); + udelay(2); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80); + udelay(10); + + usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), + RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, + addr, 0x8225, &data, sizeof(data), HZ / 2); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); + udelay(10); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84); + msleep(2); +} + +void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data) +{ + struct rtl8187_priv *priv = dev->priv; + + if (priv->asic_rev) + rtl8225_write_8051(dev, addr, data); + else + rtl8225_write_bitbang(dev, addr, data); +} + +u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr) +{ + struct rtl8187_priv *priv = dev->priv; + u16 reg80, reg82, reg84, out; + int i; + + reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput); + reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable); + reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect); + + reg80 &= ~0xF; + + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); + udelay(4); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80); + udelay(5); + + for (i = 4; i >= 0; i--) { + u16 reg = reg80 | ((addr >> i) & 1); + + if (!(i & 1)) { + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); + udelay(1); + } + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg | (1 << 1)); + udelay(2); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg | (1 << 1)); + udelay(2); + + if (i & 1) { + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); + udelay(1); + } + } + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3) | (1 << 1)); + udelay(2); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3)); + udelay(2); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3)); + udelay(2); + + out = 0; + for (i = 11; i >= 0; i--) { + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3)); + udelay(1); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3) | (1 << 1)); + udelay(2); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3) | (1 << 1)); + udelay(2); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3) | (1 << 1)); + udelay(2); + + if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1)) + out |= 1 << i; + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3)); + udelay(2); + } + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3) | (1 << 2)); + udelay(2); + + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0); + + return out; +} + +static const u16 rtl8225bcd_rxgain[] = { + 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, + 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, + 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, + 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, + 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, + 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, + 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, + 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, + 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, + 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, + 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3, + 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb +}; + +static const u8 rtl8225_agc[] = { + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, + 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, + 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, + 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e, + 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, + 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, + 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, + 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, + 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, + 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, + 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, + 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 +}; + +static const u8 rtl8225_gain[] = { + 0x23, 0x88, 0x7c, 0xa5, /* -82dBm */ + 0x23, 0x88, 0x7c, 0xb5, /* -82dBm */ + 0x23, 0x88, 0x7c, 0xc5, /* -82dBm */ + 0x33, 0x80, 0x79, 0xc5, /* -78dBm */ + 0x43, 0x78, 0x76, 0xc5, /* -74dBm */ + 0x53, 0x60, 0x73, 0xc5, /* -70dBm */ + 0x63, 0x58, 0x70, 0xc5, /* -66dBm */ +}; + +static const u8 rtl8225_threshold[] = { + 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd +}; + +static const u8 rtl8225_tx_gain_cck_ofdm[] = { + 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e +}; + +static const u8 rtl8225_tx_power_cck[] = { + 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02, + 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02, + 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02, + 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02, + 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03, + 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03 +}; + +static const u8 rtl8225_tx_power_cck_ch14[] = { + 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, + 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00 +}; + +static const u8 rtl8225_tx_power_ofdm[] = { + 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4 +}; + +static const u32 rtl8225_chan[] = { + 0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c, + 0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72 +}; + +static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel) +{ + struct rtl8187_priv *priv = dev->priv; + u8 cck_power, ofdm_power; + const u8 *tmp; + u32 reg; + int i; + + cck_power = priv->channels[channel - 1].val & 0xF; + ofdm_power = priv->channels[channel - 1].val >> 4; + + cck_power = min(cck_power, (u8)11); + ofdm_power = min(ofdm_power, (u8)35); + + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, + rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1); + + if (channel == 14) + tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8]; + else + tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8]; + + for (i = 0; i < 8; i++) + rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++); + + msleep(1); // FIXME: optional? + + /* anaparam2 on */ + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + + rtl8225_write_phy_ofdm(dev, 2, 0x42); + rtl8225_write_phy_ofdm(dev, 6, 0x00); + rtl8225_write_phy_ofdm(dev, 8, 0x00); + + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, + rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1); + + tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6]; + + rtl8225_write_phy_ofdm(dev, 5, *tmp); + rtl8225_write_phy_ofdm(dev, 7, *tmp); + + msleep(1); +} + +void rtl8225_rf_init(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + int i; + + rtl8225_write(dev, 0x0, 0x067); msleep(1); + rtl8225_write(dev, 0x1, 0xFE0); msleep(1); + rtl8225_write(dev, 0x2, 0x44D); msleep(1); + rtl8225_write(dev, 0x3, 0x441); msleep(1); + rtl8225_write(dev, 0x4, 0x486); msleep(1); + rtl8225_write(dev, 0x5, 0xBC0); msleep(1); + rtl8225_write(dev, 0x6, 0xAE6); msleep(1); + rtl8225_write(dev, 0x7, 0x82A); msleep(1); + rtl8225_write(dev, 0x8, 0x01F); msleep(1); + rtl8225_write(dev, 0x9, 0x334); msleep(1); + rtl8225_write(dev, 0xA, 0xFD4); msleep(1); + rtl8225_write(dev, 0xB, 0x391); msleep(1); + rtl8225_write(dev, 0xC, 0x050); msleep(1); + rtl8225_write(dev, 0xD, 0x6DB); msleep(1); + rtl8225_write(dev, 0xE, 0x029); msleep(1); + rtl8225_write(dev, 0xF, 0x914); msleep(100); + + rtl8225_write(dev, 0x2, 0xC4D); msleep(200); + rtl8225_write(dev, 0x2, 0x44D); msleep(200); + + if (!(rtl8225_read(dev, 6) & (1 << 7))) { + rtl8225_write(dev, 0x02, 0x0c4d); + msleep(200); + rtl8225_write(dev, 0x02, 0x044d); + msleep(100); + if (!(rtl8225_read(dev, 6) & (1 << 7))) + printk(KERN_WARNING "%s: RF Calibration Failed! %x\n", + wiphy_name(dev->wiphy), rtl8225_read(dev, 6)); + } + + rtl8225_write(dev, 0x0, 0x127); + + for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) { + rtl8225_write(dev, 0x1, i + 1); + rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]); + } + + rtl8225_write(dev, 0x0, 0x027); + rtl8225_write(dev, 0x0, 0x22F); + + for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) { + rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]); + msleep(1); + rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i); + msleep(1); + } + + msleep(1); + + rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x11, 0x06); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1); + + rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]); + rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]); + rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]); + rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]); + + rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1); + rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1); + rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1); + rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1); + rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1); + rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1); + rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1); + rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); + rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1); + rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1); + rtl8225_write_phy_cck(dev, 0x13, 0xd0); + rtl8225_write_phy_cck(dev, 0x19, 0x00); + rtl8225_write_phy_cck(dev, 0x1a, 0xa0); + rtl8225_write_phy_cck(dev, 0x1b, 0x08); + rtl8225_write_phy_cck(dev, 0x40, 0x86); + rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1); + rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1); + rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1); + rtl8225_write_phy_cck(dev, 0x44, 0x1f); msleep(1); + rtl8225_write_phy_cck(dev, 0x45, 0x1e); msleep(1); + rtl8225_write_phy_cck(dev, 0x46, 0x1a); msleep(1); + rtl8225_write_phy_cck(dev, 0x47, 0x15); msleep(1); + rtl8225_write_phy_cck(dev, 0x48, 0x10); msleep(1); + rtl8225_write_phy_cck(dev, 0x49, 0x0a); msleep(1); + rtl8225_write_phy_cck(dev, 0x4a, 0x05); msleep(1); + rtl8225_write_phy_cck(dev, 0x4b, 0x02); msleep(1); + rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1); + + rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D); + + rtl8225_rf_set_tx_power(dev, 1); + + /* RX antenna default to A */ + rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */ + rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */ + + rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */ + msleep(1); + rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002); + + /* set sensitivity */ + rtl8225_write(dev, 0x0c, 0x50); + rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]); + rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]); + rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]); + rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]); + rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]); +} + +static const u8 rtl8225z2_tx_power_cck_ch14[] = { + 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00 +}; + +static const u8 rtl8225z2_tx_power_cck[] = { + 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04 +}; + +static const u8 rtl8225z2_tx_power_ofdm[] = { + 0x42, 0x00, 0x40, 0x00, 0x40 +}; + +static const u8 rtl8225z2_tx_gain_cck_ofdm[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, + 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, + 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23 +}; + +static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel) +{ + struct rtl8187_priv *priv = dev->priv; + u8 cck_power, ofdm_power; + const u8 *tmp; + u32 reg; + int i; + + cck_power = priv->channels[channel - 1].val & 0xF; + ofdm_power = priv->channels[channel - 1].val >> 4; + + cck_power = min(cck_power, (u8)15); + cck_power += priv->txpwr_base & 0xF; + cck_power = min(cck_power, (u8)35); + + ofdm_power = min(ofdm_power, (u8)15); + ofdm_power += priv->txpwr_base >> 4; + ofdm_power = min(ofdm_power, (u8)35); + + if (channel == 14) + tmp = rtl8225z2_tx_power_cck_ch14; + else + tmp = rtl8225z2_tx_power_cck; + + for (i = 0; i < 8; i++) + rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++); + + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, + rtl8225z2_tx_gain_cck_ofdm[cck_power]); + msleep(1); + + /* anaparam2 on */ + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + + rtl8225_write_phy_ofdm(dev, 2, 0x42); + rtl8225_write_phy_ofdm(dev, 5, 0x00); + rtl8225_write_phy_ofdm(dev, 6, 0x40); + rtl8225_write_phy_ofdm(dev, 7, 0x00); + rtl8225_write_phy_ofdm(dev, 8, 0x40); + + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, + rtl8225z2_tx_gain_cck_ofdm[ofdm_power]); + msleep(1); +} + +static const u16 rtl8225z2_rxgain[] = { + 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, + 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, + 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, + 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, + 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, + 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, + 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, + 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, + 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, + 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, + 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3, + 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb +}; + +static const u8 rtl8225z2_gain_bg[] = { + 0x23, 0x15, 0xa5, /* -82-1dBm */ + 0x23, 0x15, 0xb5, /* -82-2dBm */ + 0x23, 0x15, 0xc5, /* -82-3dBm */ + 0x33, 0x15, 0xc5, /* -78dBm */ + 0x43, 0x15, 0xc5, /* -74dBm */ + 0x53, 0x15, 0xc5, /* -70dBm */ + 0x63, 0x15, 0xc5 /* -66dBm */ +}; + +void rtl8225z2_rf_init(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + int i; + + rtl8225_write(dev, 0x0, 0x2BF); msleep(1); + rtl8225_write(dev, 0x1, 0xEE0); msleep(1); + rtl8225_write(dev, 0x2, 0x44D); msleep(1); + rtl8225_write(dev, 0x3, 0x441); msleep(1); + rtl8225_write(dev, 0x4, 0x8C3); msleep(1); + rtl8225_write(dev, 0x5, 0xC72); msleep(1); + rtl8225_write(dev, 0x6, 0x0E6); msleep(1); + rtl8225_write(dev, 0x7, 0x82A); msleep(1); + rtl8225_write(dev, 0x8, 0x03F); msleep(1); + rtl8225_write(dev, 0x9, 0x335); msleep(1); + rtl8225_write(dev, 0xa, 0x9D4); msleep(1); + rtl8225_write(dev, 0xb, 0x7BB); msleep(1); + rtl8225_write(dev, 0xc, 0x850); msleep(1); + rtl8225_write(dev, 0xd, 0xCDF); msleep(1); + rtl8225_write(dev, 0xe, 0x02B); msleep(1); + rtl8225_write(dev, 0xf, 0x114); msleep(100); + + rtl8225_write(dev, 0x0, 0x1B7); + + for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) { + rtl8225_write(dev, 0x1, i + 1); + rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]); + } + + rtl8225_write(dev, 0x3, 0x080); + rtl8225_write(dev, 0x5, 0x004); + rtl8225_write(dev, 0x0, 0x0B7); + rtl8225_write(dev, 0x2, 0xc4D); + + msleep(200); + rtl8225_write(dev, 0x2, 0x44D); + msleep(100); + + if (!(rtl8225_read(dev, 6) & (1 << 7))) { + rtl8225_write(dev, 0x02, 0x0C4D); + msleep(200); + rtl8225_write(dev, 0x02, 0x044D); + msleep(100); + if (!(rtl8225_read(dev, 6) & (1 << 7))) + printk(KERN_WARNING "%s: RF Calibration Failed! %x\n", + wiphy_name(dev->wiphy), rtl8225_read(dev, 6)); + } + + msleep(200); + + rtl8225_write(dev, 0x0, 0x2BF); + + for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) { + rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]); + msleep(1); + rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i); + msleep(1); + } + + msleep(1); + + rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x0a, 0x08); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x0d, 0x43); + rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x11, 0x07); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x1b, 0x15); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x21, 0x17); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x23, 0x80); msleep(1); //FIXME: not needed? + rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x25, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1); + + rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]); + rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]); + rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]); + rtl8225_write_phy_ofdm(dev, 0x21, 0x37); + + rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1); + rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1); + rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1); + rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1); + rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1); + rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1); + rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1); + rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); + rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1); + rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1); + rtl8225_write_phy_cck(dev, 0x13, 0xd0); + rtl8225_write_phy_cck(dev, 0x19, 0x00); + rtl8225_write_phy_cck(dev, 0x1a, 0xa0); + rtl8225_write_phy_cck(dev, 0x1b, 0x08); + rtl8225_write_phy_cck(dev, 0x40, 0x86); + rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1); + rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1); + rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1); + rtl8225_write_phy_cck(dev, 0x44, 0x36); msleep(1); + rtl8225_write_phy_cck(dev, 0x45, 0x35); msleep(1); + rtl8225_write_phy_cck(dev, 0x46, 0x2e); msleep(1); + rtl8225_write_phy_cck(dev, 0x47, 0x25); msleep(1); + rtl8225_write_phy_cck(dev, 0x48, 0x1c); msleep(1); + rtl8225_write_phy_cck(dev, 0x49, 0x12); msleep(1); + rtl8225_write_phy_cck(dev, 0x4a, 0x09); msleep(1); + rtl8225_write_phy_cck(dev, 0x4b, 0x04); msleep(1); + rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1); + + rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1); + + rtl8225z2_rf_set_tx_power(dev, 1); + + /* RX antenna default to A */ + rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */ + rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */ + + rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */ + msleep(1); + rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002); +} + +void rtl8225_rf_stop(struct ieee80211_hw *dev) +{ + u8 reg; + struct rtl8187_priv *priv = dev->priv; + + rtl8225_write(dev, 0x4, 0x1f); msleep(1); + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); +} + +void rtl8225_rf_set_channel(struct ieee80211_hw *dev, int channel) +{ + struct rtl8187_priv *priv = dev->priv; + + if (priv->rf_init == rtl8225_rf_init) + rtl8225_rf_set_tx_power(dev, channel); + else + rtl8225z2_rf_set_tx_power(dev, channel); + + rtl8225_write(dev, 0x7, rtl8225_chan[channel - 1]); + msleep(10); +} diff --git a/drivers/net/wireless/rtl8187_rtl8225.h b/drivers/net/wireless/rtl8187_rtl8225.h new file mode 100644 index 00000000000..798ba4a9737 --- /dev/null +++ b/drivers/net/wireless/rtl8187_rtl8225.h @@ -0,0 +1,44 @@ +/* + * Radio tuning definitions for RTL8225 on RTL8187 + * + * Copyright 2007 Michael Wu <flamingice@sourmilk.net> + * Copyright 2007 Andrea Merello <andreamrl@tiscali.it> + * + * Based on the r8187 driver, which is: + * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef RTL8187_RTL8225_H +#define RTL8187_RTL8225_H + +#define RTL8225_ANAPARAM_ON 0xa0000a59 +#define RTL8225_ANAPARAM2_ON 0x860c7312 +#define RTL8225_ANAPARAM_OFF 0xa00beb59 +#define RTL8225_ANAPARAM2_OFF 0x840dec11 + +void rtl8225_write(struct ieee80211_hw *, u8 addr, u16 data); +u16 rtl8225_read(struct ieee80211_hw *, u8 addr); + +void rtl8225_rf_init(struct ieee80211_hw *); +void rtl8225z2_rf_init(struct ieee80211_hw *); +void rtl8225_rf_stop(struct ieee80211_hw *); +void rtl8225_rf_set_channel(struct ieee80211_hw *, int); + + +static inline void rtl8225_write_phy_ofdm(struct ieee80211_hw *dev, + u8 addr, u32 data) +{ + rtl8187_write_phy(dev, addr, data); +} + +static inline void rtl8225_write_phy_cck(struct ieee80211_hw *dev, + u8 addr, u32 data) +{ + rtl8187_write_phy(dev, addr, data | 0x10000); +} + +#endif /* RTL8187_RTL8225_H */ diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x.h new file mode 100644 index 00000000000..283de30628e --- /dev/null +++ b/drivers/net/wireless/rtl818x.h @@ -0,0 +1,226 @@ +/* + * Definitions for RTL818x hardware + * + * Copyright 2007 Michael Wu <flamingice@sourmilk.net> + * Copyright 2007 Andrea Merello <andreamrl@tiscali.it> + * + * Based on the r8187 driver, which is: + * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef RTL818X_H +#define RTL818X_H + +struct rtl818x_csr { + u8 MAC[6]; + u8 reserved_0[2]; + __le32 MAR[2]; + u8 RX_FIFO_COUNT; + u8 reserved_1; + u8 TX_FIFO_COUNT; + u8 BQREQ; + u8 reserved_2[4]; + __le32 TSFT[2]; + __le32 TLPDA; + __le32 TNPDA; + __le32 THPDA; + __le16 BRSR; + u8 BSSID[6]; + u8 RESP_RATE; + u8 EIFS; + u8 reserved_3[1]; + u8 CMD; +#define RTL818X_CMD_TX_ENABLE (1 << 2) +#define RTL818X_CMD_RX_ENABLE (1 << 3) +#define RTL818X_CMD_RESET (1 << 4) + u8 reserved_4[4]; + __le16 INT_MASK; + __le16 INT_STATUS; +#define RTL818X_INT_RX_OK (1 << 0) +#define RTL818X_INT_RX_ERR (1 << 1) +#define RTL818X_INT_TXL_OK (1 << 2) +#define RTL818X_INT_TXL_ERR (1 << 3) +#define RTL818X_INT_RX_DU (1 << 4) +#define RTL818X_INT_RX_FO (1 << 5) +#define RTL818X_INT_TXN_OK (1 << 6) +#define RTL818X_INT_TXN_ERR (1 << 7) +#define RTL818X_INT_TXH_OK (1 << 8) +#define RTL818X_INT_TXH_ERR (1 << 9) +#define RTL818X_INT_TXB_OK (1 << 10) +#define RTL818X_INT_TXB_ERR (1 << 11) +#define RTL818X_INT_ATIM (1 << 12) +#define RTL818X_INT_BEACON (1 << 13) +#define RTL818X_INT_TIME_OUT (1 << 14) +#define RTL818X_INT_TX_FO (1 << 15) + __le32 TX_CONF; +#define RTL818X_TX_CONF_LOOPBACK_MAC (1 << 17) +#define RTL818X_TX_CONF_NO_ICV (1 << 19) +#define RTL818X_TX_CONF_DISCW (1 << 20) +#define RTL818X_TX_CONF_R8180_ABCD (2 << 25) +#define RTL818X_TX_CONF_R8180_F (3 << 25) +#define RTL818X_TX_CONF_R8185_ABC (4 << 25) +#define RTL818X_TX_CONF_R8185_D (5 << 25) +#define RTL818X_TX_CONF_HWVER_MASK (7 << 25) +#define RTL818X_TX_CONF_CW_MIN (1 << 31) + __le32 RX_CONF; +#define RTL818X_RX_CONF_MONITOR (1 << 0) +#define RTL818X_RX_CONF_NICMAC (1 << 1) +#define RTL818X_RX_CONF_MULTICAST (1 << 2) +#define RTL818X_RX_CONF_BROADCAST (1 << 3) +#define RTL818X_RX_CONF_DATA (1 << 18) +#define RTL818X_RX_CONF_CTRL (1 << 19) +#define RTL818X_RX_CONF_MGMT (1 << 20) +#define RTL818X_RX_CONF_BSSID (1 << 23) +#define RTL818X_RX_CONF_RX_AUTORESETPHY (1 << 28) +#define RTL818X_RX_CONF_ONLYERLPKT (1 << 31) + __le32 INT_TIMEOUT; + __le32 TBDA; + u8 EEPROM_CMD; +#define RTL818X_EEPROM_CMD_READ (1 << 0) +#define RTL818X_EEPROM_CMD_WRITE (1 << 1) +#define RTL818X_EEPROM_CMD_CK (1 << 2) +#define RTL818X_EEPROM_CMD_CS (1 << 3) +#define RTL818X_EEPROM_CMD_NORMAL (0 << 6) +#define RTL818X_EEPROM_CMD_LOAD (1 << 6) +#define RTL818X_EEPROM_CMD_PROGRAM (2 << 6) +#define RTL818X_EEPROM_CMD_CONFIG (3 << 6) + u8 CONFIG0; + u8 CONFIG1; + u8 CONFIG2; + __le32 ANAPARAM; + u8 MSR; +#define RTL818X_MSR_NO_LINK (0 << 2) +#define RTL818X_MSR_ADHOC (1 << 2) +#define RTL818X_MSR_INFRA (2 << 2) + u8 CONFIG3; +#define RTL818X_CONFIG3_ANAPARAM_WRITE (1 << 6) + u8 CONFIG4; +#define RTL818X_CONFIG4_POWEROFF (1 << 6) +#define RTL818X_CONFIG4_VCOOFF (1 << 7) + u8 TESTR; + u8 reserved_9[2]; + __le16 PGSELECT; + __le32 ANAPARAM2; + u8 reserved_10[12]; + __le16 BEACON_INTERVAL; + __le16 ATIM_WND; + __le16 BEACON_INTERVAL_TIME; + __le16 ATIMTR_INTERVAL; + u8 reserved_11[4]; + u8 PHY[4]; + __le16 RFPinsOutput; + __le16 RFPinsEnable; + __le16 RFPinsSelect; + __le16 RFPinsInput; + __le32 RF_PARA; + __le32 RF_TIMING; + u8 GP_ENABLE; + u8 GPIO; + u8 reserved_12[10]; + u8 TX_AGC_CTL; +#define RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT (1 << 0) +#define RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT (1 << 1) +#define RTL818X_TX_AGC_CTL_FEEDBACK_ANT (1 << 2) + u8 TX_GAIN_CCK; + u8 TX_GAIN_OFDM; + u8 TX_ANTENNA; + u8 reserved_13[16]; + u8 WPA_CONF; + u8 reserved_14[3]; + u8 SIFS; + u8 DIFS; + u8 SLOT; + u8 reserved_15[5]; + u8 CW_CONF; +#define RTL818X_CW_CONF_PERPACKET_CW_SHIFT (1 << 0) +#define RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT (1 << 1) + u8 CW_VAL; + u8 RATE_FALLBACK; + u8 reserved_16[25]; + u8 CONFIG5; + u8 TX_DMA_POLLING; + u8 reserved_17[2]; + __le16 CWR; + u8 RETRY_CTR; + u8 reserved_18[5]; + __le32 RDSAR; + u8 reserved_19[18]; + u16 TALLY_CNT; + u8 TALLY_SEL; +} __attribute__((packed)); + +static const struct ieee80211_rate rtl818x_rates[] = { + { .rate = 10, + .val = 0, + .flags = IEEE80211_RATE_CCK }, + { .rate = 20, + .val = 1, + .flags = IEEE80211_RATE_CCK }, + { .rate = 55, + .val = 2, + .flags = IEEE80211_RATE_CCK }, + { .rate = 110, + .val = 3, + .flags = IEEE80211_RATE_CCK }, + { .rate = 60, + .val = 4, + .flags = IEEE80211_RATE_OFDM }, + { .rate = 90, + .val = 5, + .flags = IEEE80211_RATE_OFDM }, + { .rate = 120, + .val = 6, + .flags = IEEE80211_RATE_OFDM }, + { .rate = 180, + .val = 7, + .flags = IEEE80211_RATE_OFDM }, + { .rate = 240, + .val = 8, + .flags = IEEE80211_RATE_OFDM }, + { .rate = 360, + .val = 9, + .flags = IEEE80211_RATE_OFDM }, + { .rate = 480, + .val = 10, + .flags = IEEE80211_RATE_OFDM }, + { .rate = 540, + .val = 11, + .flags = IEEE80211_RATE_OFDM }, +}; + +static const struct ieee80211_channel rtl818x_channels[] = { + { .chan = 1, + .freq = 2412}, + { .chan = 2, + .freq = 2417}, + { .chan = 3, + .freq = 2422}, + { .chan = 4, + .freq = 2427}, + { .chan = 5, + .freq = 2432}, + { .chan = 6, + .freq = 2437}, + { .chan = 7, + .freq = 2442}, + { .chan = 8, + .freq = 2447}, + { .chan = 9, + .freq = 2452}, + { .chan = 10, + .freq = 2457}, + { .chan = 11, + .freq = 2462}, + { .chan = 12, + .freq = 2467}, + { .chan = 13, + .freq = 2472}, + { .chan = 14, + .freq = 2484} +}; + +#endif /* RTL818X_H */ diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index ce9230b2f63..c8b5c227193 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -1011,7 +1011,7 @@ static inline void wl3501_md_ind_interrupt(struct net_device *dev, } else { skb->dev = dev; skb_reserve(skb, 2); /* IP headers on 16 bytes boundaries */ - eth_copy_and_sum(skb, (unsigned char *)&sig.daddr, 12, 0); + skb_copy_to_linear_data(skb, (unsigned char *)&sig.daddr, 12); wl3501_receive(this, skb->data, pkt_len); skb_put(skb, pkt_len); skb->protocol = eth_type_trans(skb, dev); diff --git a/drivers/net/wireless/zd1211rw/Makefile b/drivers/net/wireless/zd1211rw/Makefile index 6603ad5be63..4d505903352 100644 --- a/drivers/net/wireless/zd1211rw/Makefile +++ b/drivers/net/wireless/zd1211rw/Makefile @@ -3,7 +3,7 @@ obj-$(CONFIG_ZD1211RW) += zd1211rw.o zd1211rw-objs := zd_chip.o zd_ieee80211.o \ zd_mac.o zd_netdev.o \ zd_rf_al2230.o zd_rf_rf2959.o \ - zd_rf_al7230b.o \ + zd_rf_al7230b.o zd_rf_uw2453.o \ zd_rf.o zd_usb.o zd_util.o ifeq ($(CONFIG_ZD1211RW_DEBUG),y) diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index 95b4a2a2670..5b624bfc01a 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c @@ -1253,6 +1253,9 @@ static int update_channel_integration_and_calibration(struct zd_chip *chip, { int r; + if (!zd_rf_should_update_pwr_int(&chip->rf)) + return 0; + r = update_pwr_int(chip, channel); if (r) return r; @@ -1283,7 +1286,7 @@ static int patch_cck_gain(struct zd_chip *chip) int r; u32 value; - if (!chip->patch_cck_gain) + if (!chip->patch_cck_gain || !zd_rf_should_patch_cck_gain(&chip->rf)) return 0; ZD_ASSERT(mutex_is_locked(&chip->mutex)); diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index ce0a5f6da0d..79d0288c193 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h @@ -608,6 +608,9 @@ enum { #define CR_ZD1211B_TXOP CTL_REG(0x0b20) #define CR_ZD1211B_RETRY_MAX CTL_REG(0x0b28) +/* Used to detect PLL lock */ +#define UW2453_INTR_REG ((zd_addr_t)0x85c1) + #define CWIN_SIZE 0x007f043f diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c index 549c23bcd6c..7407409b60b 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf.c +++ b/drivers/net/wireless/zd1211rw/zd_rf.c @@ -52,34 +52,38 @@ const char *zd_rf_name(u8 type) void zd_rf_init(struct zd_rf *rf) { memset(rf, 0, sizeof(*rf)); + + /* default to update channel integration, as almost all RF's do want + * this */ + rf->update_channel_int = 1; } void zd_rf_clear(struct zd_rf *rf) { + if (rf->clear) + rf->clear(rf); ZD_MEMCLEAR(rf, sizeof(*rf)); } int zd_rf_init_hw(struct zd_rf *rf, u8 type) { - int r, t; + int r = 0; + int t; struct zd_chip *chip = zd_rf_to_chip(rf); ZD_ASSERT(mutex_is_locked(&chip->mutex)); switch (type) { case RF2959_RF: r = zd_rf_init_rf2959(rf); - if (r) - return r; break; case AL2230_RF: r = zd_rf_init_al2230(rf); - if (r) - return r; break; case AL7230B_RF: r = zd_rf_init_al7230b(rf); - if (r) - return r; + break; + case UW2453_RF: + r = zd_rf_init_uw2453(rf); break; default: dev_err(zd_chip_dev(chip), @@ -88,6 +92,9 @@ int zd_rf_init_hw(struct zd_rf *rf, u8 type) return -ENODEV; } + if (r) + return r; + rf->type = type; r = zd_chip_lock_phy_regs(chip); diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h index aa9cc105ce6..c6dfd8227f6 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf.h +++ b/drivers/net/wireless/zd1211rw/zd_rf.h @@ -48,12 +48,26 @@ struct zd_rf { u8 channel; + /* whether channel integration and calibration should be updated + * defaults to 1 (yes) */ + u8 update_channel_int:1; + + /* whether CR47 should be patched from the EEPROM, if the appropriate + * flag is set in the POD. The vendor driver suggests that this should + * be done for all RF's, but a bug in their code prevents but their + * HW_OverWritePhyRegFromE2P() routine from ever taking effect. */ + u8 patch_cck_gain:1; + + /* private RF driver data */ + void *priv; + /* RF-specific functions */ int (*init_hw)(struct zd_rf *rf); int (*set_channel)(struct zd_rf *rf, u8 channel); int (*switch_radio_on)(struct zd_rf *rf); int (*switch_radio_off)(struct zd_rf *rf); int (*patch_6m_band_edge)(struct zd_rf *rf, u8 channel); + void (*clear)(struct zd_rf *rf); }; const char *zd_rf_name(u8 type); @@ -71,10 +85,24 @@ int zd_switch_radio_off(struct zd_rf *rf); int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel); int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel); +static inline int zd_rf_should_update_pwr_int(struct zd_rf *rf) +{ + return rf->update_channel_int; +} + +static inline int zd_rf_should_patch_cck_gain(struct zd_rf *rf) +{ + return rf->patch_cck_gain; +} + +int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel); +int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel); + /* Functions for individual RF chips */ int zd_rf_init_rf2959(struct zd_rf *rf); int zd_rf_init_al2230(struct zd_rf *rf); int zd_rf_init_al7230b(struct zd_rf *rf); +int zd_rf_init_uw2453(struct zd_rf *rf); #endif /* _ZD_RF_H */ diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c index 511392acfed..e7a4ecf7b6e 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c +++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c @@ -432,5 +432,6 @@ int zd_rf_init_al2230(struct zd_rf *rf) rf->switch_radio_on = zd1211_al2230_switch_radio_on; } rf->patch_6m_band_edge = zd_rf_generic_patch_6m; + rf->patch_cck_gain = 1; return 0; } diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c index 5e5e9ddc6a7..f4e8b6ada85 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c +++ b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c @@ -483,6 +483,7 @@ int zd_rf_init_al7230b(struct zd_rf *rf) rf->switch_radio_on = zd1211_al7230b_switch_radio_on; rf->set_channel = zd1211_al7230b_set_channel; rf->patch_6m_band_edge = zd_rf_generic_patch_6m; + rf->patch_cck_gain = 1; } rf->switch_radio_off = al7230b_switch_radio_off; diff --git a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c new file mode 100644 index 00000000000..414e40d571a --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c @@ -0,0 +1,534 @@ +/* zd_rf_uw2453.c: Functions for the UW2453 RF controller + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/kernel.h> + +#include "zd_rf.h" +#include "zd_usb.h" +#include "zd_chip.h" + +/* This RF programming code is based upon the code found in v2.16.0.0 of the + * ZyDAS vendor driver. Unlike other RF's, Ubec publish full technical specs + * for this RF on their website, so we're able to understand more than + * usual as to what is going on. Thumbs up for Ubec for doing that. */ + +/* The 3-wire serial interface provides access to 8 write-only registers. + * The data format is a 4 bit register address followed by a 20 bit value. */ +#define UW2453_REGWRITE(reg, val) ((((reg) & 0xf) << 20) | ((val) & 0xfffff)) + +/* For channel tuning, we have to configure registers 1 (synthesizer), 2 (synth + * fractional divide ratio) and 3 (VCO config). + * + * We configure the RF to produce an interrupt when the PLL is locked onto + * the configured frequency. During initialization, we run through a variety + * of different VCO configurations on channel 1 until we detect a PLL lock. + * When this happens, we remember which VCO configuration produced the lock + * and use it later. Actually, we use the configuration *after* the one that + * produced the lock, which seems odd, but it works. + * + * If we do not see a PLL lock on any standard VCO config, we fall back on an + * autocal configuration, which has a fixed (as opposed to per-channel) VCO + * config and different synth values from the standard set (divide ratio + * is still shared with the standard set). */ + +/* The per-channel synth values for all standard VCO configurations. These get + * written to register 1. */ +static const u8 uw2453_std_synth[] = { + RF_CHANNEL( 1) = 0x47, + RF_CHANNEL( 2) = 0x47, + RF_CHANNEL( 3) = 0x67, + RF_CHANNEL( 4) = 0x67, + RF_CHANNEL( 5) = 0x67, + RF_CHANNEL( 6) = 0x67, + RF_CHANNEL( 7) = 0x57, + RF_CHANNEL( 8) = 0x57, + RF_CHANNEL( 9) = 0x57, + RF_CHANNEL(10) = 0x57, + RF_CHANNEL(11) = 0x77, + RF_CHANNEL(12) = 0x77, + RF_CHANNEL(13) = 0x77, + RF_CHANNEL(14) = 0x4f, +}; + +/* This table stores the synthesizer fractional divide ratio for *all* VCO + * configurations (both standard and autocal). These get written to register 2. + */ +static const u16 uw2453_synth_divide[] = { + RF_CHANNEL( 1) = 0x999, + RF_CHANNEL( 2) = 0x99b, + RF_CHANNEL( 3) = 0x998, + RF_CHANNEL( 4) = 0x99a, + RF_CHANNEL( 5) = 0x999, + RF_CHANNEL( 6) = 0x99b, + RF_CHANNEL( 7) = 0x998, + RF_CHANNEL( 8) = 0x99a, + RF_CHANNEL( 9) = 0x999, + RF_CHANNEL(10) = 0x99b, + RF_CHANNEL(11) = 0x998, + RF_CHANNEL(12) = 0x99a, + RF_CHANNEL(13) = 0x999, + RF_CHANNEL(14) = 0xccc, +}; + +/* Here is the data for all the standard VCO configurations. We shrink our + * table a little by observing that both channels in a consecutive pair share + * the same value. We also observe that the high 4 bits ([0:3] in the specs) + * are all 'Reserved' and are always set to 0x4 - we chop them off in the data + * below. */ +#define CHAN_TO_PAIRIDX(a) ((a - 1) / 2) +#define RF_CHANPAIR(a,b) [CHAN_TO_PAIRIDX(a)] +static const u16 uw2453_std_vco_cfg[][7] = { + { /* table 1 */ + RF_CHANPAIR( 1, 2) = 0x664d, + RF_CHANPAIR( 3, 4) = 0x604d, + RF_CHANPAIR( 5, 6) = 0x6675, + RF_CHANPAIR( 7, 8) = 0x6475, + RF_CHANPAIR( 9, 10) = 0x6655, + RF_CHANPAIR(11, 12) = 0x6455, + RF_CHANPAIR(13, 14) = 0x6665, + }, + { /* table 2 */ + RF_CHANPAIR( 1, 2) = 0x666d, + RF_CHANPAIR( 3, 4) = 0x606d, + RF_CHANPAIR( 5, 6) = 0x664d, + RF_CHANPAIR( 7, 8) = 0x644d, + RF_CHANPAIR( 9, 10) = 0x6675, + RF_CHANPAIR(11, 12) = 0x6475, + RF_CHANPAIR(13, 14) = 0x6655, + }, + { /* table 3 */ + RF_CHANPAIR( 1, 2) = 0x665d, + RF_CHANPAIR( 3, 4) = 0x605d, + RF_CHANPAIR( 5, 6) = 0x666d, + RF_CHANPAIR( 7, 8) = 0x646d, + RF_CHANPAIR( 9, 10) = 0x664d, + RF_CHANPAIR(11, 12) = 0x644d, + RF_CHANPAIR(13, 14) = 0x6675, + }, + { /* table 4 */ + RF_CHANPAIR( 1, 2) = 0x667d, + RF_CHANPAIR( 3, 4) = 0x607d, + RF_CHANPAIR( 5, 6) = 0x665d, + RF_CHANPAIR( 7, 8) = 0x645d, + RF_CHANPAIR( 9, 10) = 0x666d, + RF_CHANPAIR(11, 12) = 0x646d, + RF_CHANPAIR(13, 14) = 0x664d, + }, + { /* table 5 */ + RF_CHANPAIR( 1, 2) = 0x6643, + RF_CHANPAIR( 3, 4) = 0x6043, + RF_CHANPAIR( 5, 6) = 0x667d, + RF_CHANPAIR( 7, 8) = 0x647d, + RF_CHANPAIR( 9, 10) = 0x665d, + RF_CHANPAIR(11, 12) = 0x645d, + RF_CHANPAIR(13, 14) = 0x666d, + }, + { /* table 6 */ + RF_CHANPAIR( 1, 2) = 0x6663, + RF_CHANPAIR( 3, 4) = 0x6063, + RF_CHANPAIR( 5, 6) = 0x6643, + RF_CHANPAIR( 7, 8) = 0x6443, + RF_CHANPAIR( 9, 10) = 0x667d, + RF_CHANPAIR(11, 12) = 0x647d, + RF_CHANPAIR(13, 14) = 0x665d, + }, + { /* table 7 */ + RF_CHANPAIR( 1, 2) = 0x6653, + RF_CHANPAIR( 3, 4) = 0x6053, + RF_CHANPAIR( 5, 6) = 0x6663, + RF_CHANPAIR( 7, 8) = 0x6463, + RF_CHANPAIR( 9, 10) = 0x6643, + RF_CHANPAIR(11, 12) = 0x6443, + RF_CHANPAIR(13, 14) = 0x667d, + }, + { /* table 8 */ + RF_CHANPAIR( 1, 2) = 0x6673, + RF_CHANPAIR( 3, 4) = 0x6073, + RF_CHANPAIR( 5, 6) = 0x6653, + RF_CHANPAIR( 7, 8) = 0x6453, + RF_CHANPAIR( 9, 10) = 0x6663, + RF_CHANPAIR(11, 12) = 0x6463, + RF_CHANPAIR(13, 14) = 0x6643, + }, + { /* table 9 */ + RF_CHANPAIR( 1, 2) = 0x664b, + RF_CHANPAIR( 3, 4) = 0x604b, + RF_CHANPAIR( 5, 6) = 0x6673, + RF_CHANPAIR( 7, 8) = 0x6473, + RF_CHANPAIR( 9, 10) = 0x6653, + RF_CHANPAIR(11, 12) = 0x6453, + RF_CHANPAIR(13, 14) = 0x6663, + }, + { /* table 10 */ + RF_CHANPAIR( 1, 2) = 0x666b, + RF_CHANPAIR( 3, 4) = 0x606b, + RF_CHANPAIR( 5, 6) = 0x664b, + RF_CHANPAIR( 7, 8) = 0x644b, + RF_CHANPAIR( 9, 10) = 0x6673, + RF_CHANPAIR(11, 12) = 0x6473, + RF_CHANPAIR(13, 14) = 0x6653, + }, + { /* table 11 */ + RF_CHANPAIR( 1, 2) = 0x665b, + RF_CHANPAIR( 3, 4) = 0x605b, + RF_CHANPAIR( 5, 6) = 0x666b, + RF_CHANPAIR( 7, 8) = 0x646b, + RF_CHANPAIR( 9, 10) = 0x664b, + RF_CHANPAIR(11, 12) = 0x644b, + RF_CHANPAIR(13, 14) = 0x6673, + }, + +}; + +/* The per-channel synth values for autocal. These get written to register 1. */ +static const u16 uw2453_autocal_synth[] = { + RF_CHANNEL( 1) = 0x6847, + RF_CHANNEL( 2) = 0x6847, + RF_CHANNEL( 3) = 0x6867, + RF_CHANNEL( 4) = 0x6867, + RF_CHANNEL( 5) = 0x6867, + RF_CHANNEL( 6) = 0x6867, + RF_CHANNEL( 7) = 0x6857, + RF_CHANNEL( 8) = 0x6857, + RF_CHANNEL( 9) = 0x6857, + RF_CHANNEL(10) = 0x6857, + RF_CHANNEL(11) = 0x6877, + RF_CHANNEL(12) = 0x6877, + RF_CHANNEL(13) = 0x6877, + RF_CHANNEL(14) = 0x684f, +}; + +/* The VCO configuration for autocal (all channels) */ +static const u16 UW2453_AUTOCAL_VCO_CFG = 0x6662; + +/* TX gain settings. The array index corresponds to the TX power integration + * values found in the EEPROM. The values get written to register 7. */ +static u32 uw2453_txgain[] = { + [0x00] = 0x0e313, + [0x01] = 0x0fb13, + [0x02] = 0x0e093, + [0x03] = 0x0f893, + [0x04] = 0x0ea93, + [0x05] = 0x1f093, + [0x06] = 0x1f493, + [0x07] = 0x1f693, + [0x08] = 0x1f393, + [0x09] = 0x1f35b, + [0x0a] = 0x1e6db, + [0x0b] = 0x1ff3f, + [0x0c] = 0x1ffff, + [0x0d] = 0x361d7, + [0x0e] = 0x37fbf, + [0x0f] = 0x3ff8b, + [0x10] = 0x3ff33, + [0x11] = 0x3fb3f, + [0x12] = 0x3ffff, +}; + +/* RF-specific structure */ +struct uw2453_priv { + /* index into synth/VCO config tables where PLL lock was found + * -1 means autocal */ + int config; +}; + +#define UW2453_PRIV(rf) ((struct uw2453_priv *) (rf)->priv) + +static int uw2453_synth_set_channel(struct zd_chip *chip, int channel, + bool autocal) +{ + int r; + int idx = channel - 1; + u32 val; + + if (autocal) + val = UW2453_REGWRITE(1, uw2453_autocal_synth[idx]); + else + val = UW2453_REGWRITE(1, uw2453_std_synth[idx]); + + r = zd_rfwrite_locked(chip, val, RF_RV_BITS); + if (r) + return r; + + return zd_rfwrite_locked(chip, + UW2453_REGWRITE(2, uw2453_synth_divide[idx]), RF_RV_BITS); +} + +static int uw2453_write_vco_cfg(struct zd_chip *chip, u16 value) +{ + /* vendor driver always sets these upper bits even though the specs say + * they are reserved */ + u32 val = 0x40000 | value; + return zd_rfwrite_locked(chip, UW2453_REGWRITE(3, val), RF_RV_BITS); +} + +static int uw2453_init_mode(struct zd_chip *chip) +{ + static const u32 rv[] = { + UW2453_REGWRITE(0, 0x25f98), /* enter IDLE mode */ + UW2453_REGWRITE(0, 0x25f9a), /* enter CAL_VCO mode */ + UW2453_REGWRITE(0, 0x25f94), /* enter RX/TX mode */ + UW2453_REGWRITE(0, 0x27fd4), /* power down RSSI circuit */ + }; + + return zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS); +} + +static int uw2453_set_tx_gain_level(struct zd_chip *chip, int channel) +{ + u8 int_value = chip->pwr_int_values[channel - 1]; + + if (int_value >= ARRAY_SIZE(uw2453_txgain)) { + dev_dbg_f(zd_chip_dev(chip), "can't configure TX gain for " + "int value %x on channel %d\n", int_value, channel); + return 0; + } + + return zd_rfwrite_locked(chip, + UW2453_REGWRITE(7, uw2453_txgain[int_value]), RF_RV_BITS); +} + +static int uw2453_init_hw(struct zd_rf *rf) +{ + int i, r; + int found_config = -1; + u16 intr_status; + struct zd_chip *chip = zd_rf_to_chip(rf); + + static const struct zd_ioreq16 ioreqs[] = { + { CR10, 0x89 }, { CR15, 0x20 }, + { CR17, 0x28 }, /* 6112 no change */ + { CR23, 0x38 }, { CR24, 0x20 }, { CR26, 0x93 }, + { CR27, 0x15 }, { CR28, 0x3e }, { CR29, 0x00 }, + { CR33, 0x28 }, { CR34, 0x30 }, + { CR35, 0x43 }, /* 6112 3e->43 */ + { CR41, 0x24 }, { CR44, 0x32 }, + { CR46, 0x92 }, /* 6112 96->92 */ + { CR47, 0x1e }, + { CR48, 0x04 }, /* 5602 Roger */ + { CR49, 0xfa }, { CR79, 0x58 }, { CR80, 0x30 }, + { CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 }, + { CR91, 0x00 }, { CR92, 0x0a }, { CR98, 0x8d }, + { CR99, 0x28 }, { CR100, 0x02 }, + { CR101, 0x09 }, /* 6112 13->1f 6220 1f->13 6407 13->9 */ + { CR102, 0x27 }, + { CR106, 0x1c }, /* 5d07 5112 1f->1c 6220 1c->1f 6221 1f->1c */ + { CR107, 0x1c }, /* 6220 1c->1a 5221 1a->1c */ + { CR109, 0x13 }, + { CR110, 0x1f }, /* 6112 13->1f 6221 1f->13 6407 13->0x09 */ + { CR111, 0x13 }, { CR112, 0x1f }, { CR113, 0x27 }, + { CR114, 0x23 }, /* 6221 27->23 */ + { CR115, 0x24 }, /* 6112 24->1c 6220 1c->24 */ + { CR116, 0x24 }, /* 6220 1c->24 */ + { CR117, 0xfa }, /* 6112 fa->f8 6220 f8->f4 6220 f4->fa */ + { CR118, 0xf0 }, /* 5d07 6112 f0->f2 6220 f2->f0 */ + { CR119, 0x1a }, /* 6112 1a->10 6220 10->14 6220 14->1a */ + { CR120, 0x4f }, + { CR121, 0x1f }, /* 6220 4f->1f */ + { CR122, 0xf0 }, { CR123, 0x57 }, { CR125, 0xad }, + { CR126, 0x6c }, { CR127, 0x03 }, + { CR128, 0x14 }, /* 6302 12->11 */ + { CR129, 0x12 }, /* 6301 10->0f */ + { CR130, 0x10 }, { CR137, 0x50 }, { CR138, 0xa8 }, + { CR144, 0xac }, { CR146, 0x20 }, { CR252, 0xff }, + { CR253, 0xff }, + }; + + static const u32 rv[] = { + UW2453_REGWRITE(4, 0x2b), /* configure reciever gain */ + UW2453_REGWRITE(5, 0x19e4f), /* configure transmitter gain */ + UW2453_REGWRITE(6, 0xf81ad), /* enable RX/TX filter tuning */ + UW2453_REGWRITE(7, 0x3fffe), /* disable TX gain in test mode */ + + /* enter CAL_FIL mode, TX gain set by registers, RX gain set by pins, + * RSSI circuit powered down, reduced RSSI range */ + UW2453_REGWRITE(0, 0x25f9c), /* 5d01 cal_fil */ + + /* synthesizer configuration for channel 1 */ + UW2453_REGWRITE(1, 0x47), + UW2453_REGWRITE(2, 0x999), + + /* disable manual VCO band selection */ + UW2453_REGWRITE(3, 0x7602), + + /* enable manual VCO band selection, configure current level */ + UW2453_REGWRITE(3, 0x46063), + }; + + r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); + if (r) + return r; + + r = zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS); + if (r) + return r; + + r = uw2453_init_mode(chip); + if (r) + return r; + + /* Try all standard VCO configuration settings on channel 1 */ + for (i = 0; i < ARRAY_SIZE(uw2453_std_vco_cfg) - 1; i++) { + /* Configure synthesizer for channel 1 */ + r = uw2453_synth_set_channel(chip, 1, false); + if (r) + return r; + + /* Write VCO config */ + r = uw2453_write_vco_cfg(chip, uw2453_std_vco_cfg[i][0]); + if (r) + return r; + + /* ack interrupt event */ + r = zd_iowrite16_locked(chip, 0x0f, UW2453_INTR_REG); + if (r) + return r; + + /* check interrupt status */ + r = zd_ioread16_locked(chip, &intr_status, UW2453_INTR_REG); + if (r) + return r; + + if (!intr_status & 0xf) { + dev_dbg_f(zd_chip_dev(chip), + "PLL locked on configuration %d\n", i); + found_config = i; + break; + } + } + + if (found_config == -1) { + /* autocal */ + dev_dbg_f(zd_chip_dev(chip), + "PLL did not lock, using autocal\n"); + + r = uw2453_synth_set_channel(chip, 1, true); + if (r) + return r; + + r = uw2453_write_vco_cfg(chip, UW2453_AUTOCAL_VCO_CFG); + if (r) + return r; + } + + /* To match the vendor driver behaviour, we use the configuration after + * the one that produced a lock. */ + UW2453_PRIV(rf)->config = found_config + 1; + + return zd_iowrite16_locked(chip, 0x06, CR203); +} + +static int uw2453_set_channel(struct zd_rf *rf, u8 channel) +{ + int r; + u16 vco_cfg; + int config = UW2453_PRIV(rf)->config; + bool autocal = (config == -1); + struct zd_chip *chip = zd_rf_to_chip(rf); + + static const struct zd_ioreq16 ioreqs[] = { + { CR80, 0x30 }, { CR81, 0x30 }, { CR79, 0x58 }, + { CR12, 0xf0 }, { CR77, 0x1b }, { CR78, 0x58 }, + }; + + r = uw2453_synth_set_channel(chip, channel, autocal); + if (r) + return r; + + if (autocal) + vco_cfg = UW2453_AUTOCAL_VCO_CFG; + else + vco_cfg = uw2453_std_vco_cfg[config][CHAN_TO_PAIRIDX(channel)]; + + r = uw2453_write_vco_cfg(chip, vco_cfg); + if (r) + return r; + + r = uw2453_init_mode(chip); + if (r) + return r; + + r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); + if (r) + return r; + + r = uw2453_set_tx_gain_level(chip, channel); + if (r) + return r; + + return zd_iowrite16_locked(chip, 0x06, CR203); +} + +static int uw2453_switch_radio_on(struct zd_rf *rf) +{ + int r; + struct zd_chip *chip = zd_rf_to_chip(rf); + struct zd_ioreq16 ioreqs[] = { + { CR11, 0x00 }, { CR251, 0x3f }, + }; + + /* enter RXTX mode */ + r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f94), RF_RV_BITS); + if (r) + return r; + + if (chip->is_zd1211b) + ioreqs[1].value = 0x7f; + + return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); +} + +static int uw2453_switch_radio_off(struct zd_rf *rf) +{ + int r; + struct zd_chip *chip = zd_rf_to_chip(rf); + static const struct zd_ioreq16 ioreqs[] = { + { CR11, 0x04 }, { CR251, 0x2f }, + }; + + /* enter IDLE mode */ + /* FIXME: shouldn't we go to SLEEP? sent email to zydas */ + r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f90), RF_RV_BITS); + if (r) + return r; + + return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); +} + +static void uw2453_clear(struct zd_rf *rf) +{ + kfree(rf->priv); +} + +int zd_rf_init_uw2453(struct zd_rf *rf) +{ + rf->init_hw = uw2453_init_hw; + rf->set_channel = uw2453_set_channel; + rf->switch_radio_on = uw2453_switch_radio_on; + rf->switch_radio_off = uw2453_switch_radio_off; + rf->patch_6m_band_edge = zd_rf_generic_patch_6m; + rf->clear = uw2453_clear; + /* we have our own TX integration code */ + rf->update_channel_int = 0; + + rf->priv = kmalloc(sizeof(struct uw2453_priv), GFP_KERNEL); + if (rf->priv == NULL) + return -ENOMEM; + + return 0; +} + diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 8459549d0ce..ca24299a26c 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -15,7 +15,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <asm/unaligned.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> @@ -26,6 +25,7 @@ #include <linux/usb.h> #include <linux/workqueue.h> #include <net/ieee80211.h> +#include <asm/unaligned.h> #include "zd_def.h" #include "zd_netdev.h" @@ -54,6 +54,7 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x0586, 0x3401), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x14ea, 0xab13), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x13b1, 0x001e), .driver_info = DEVICE_ZD1211 }, + { USB_DEVICE(0x0586, 0x3407), .driver_info = DEVICE_ZD1211 }, /* ZD1211B */ { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index f2a90a7fa2d..870c5393c21 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -1137,7 +1137,7 @@ static int yellowfin_rx(struct net_device *dev) if (skb == NULL) break; skb_reserve(skb, 2); /* 16 byte align the IP header */ - eth_copy_and_sum(skb, rx_skb->data, pkt_len, 0); + skb_copy_to_linear_data(skb, rx_skb->data, pkt_len); skb_put(skb, pkt_len); pci_dma_sync_single_for_device(yp->pci_dev, desc->addr, yp->rx_buf_sz, |