diff --git a/Config.in b/Config.in index b04c65a71..2ff2862a2 100644 --- a/Config.in +++ b/Config.in @@ -25,6 +25,7 @@ menu "Target Images" depends TARGET_ROOTFS_INITRAMFS depends !LINUX_2_6_25 default TARGET_INITRAMFS_COMPRESSION_LZMA if TARGET_ar71xx + default TARGET_INITRAMFS_COMPRESSION_LZMA if TARGET_ramips default TARGET_INITRAMFS_COMPRESSION_NONE help Select ramdisk compression. diff --git a/include/download.mk b/include/download.mk index c924ca051..9dd26a744 100644 --- a/include/download.mk +++ b/include/download.mk @@ -104,10 +104,10 @@ define DownloadMethod/bzr cd $(TMP_DIR)/dl && \ rm -rf $(SUBDIR) && \ [ \! -d $(SUBDIR) ] && \ - bzr export -r$(VERSION) $(URL) $(SUBDIR) && \ + bzr export -r$(VERSION) $(SUBDIR) $(URL) && \ echo "Packing checkout..." && \ $(call dl_pack,$(TMP_DIR)/dl/$(FILE),$(SUBDIR)) && \ - mv $(TMP_DIR)/dl/$(FILE) $(DL_DIR)/ && + mv $(TMP_DIR)/dl/$(FILE) $(DL_DIR)/ && \ rm -rf $(SUBDIR); \ ) endef diff --git a/package/base-files/files/sbin/hotplug-call b/package/base-files/files/sbin/hotplug-call index c5a76a76c..e56460de9 100755 --- a/package/base-files/files/sbin/hotplug-call +++ b/package/base-files/files/sbin/hotplug-call @@ -10,7 +10,7 @@ export HOTPLUG_TYPE="$1" echo 1 > "/sys$DEVPATH/loading" dd if="/lib/firmware/$FIRMWARE" of="/sys$DEVPATH/data" bs=64k echo 0 > "/sys$DEVPATH/loading" - } + } || echo -1 > "/sys$DEVPATH/loading" exit 0 } diff --git a/package/ep80579-drivers/Makefile b/package/ep80579-drivers/Makefile new file mode 100644 index 000000000..fac0fbbad --- /dev/null +++ b/package/ep80579-drivers/Makefile @@ -0,0 +1,80 @@ +# +# Copyright (C) 2010 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=ep80579-drivers +PKG_VERSION:=1.0.34 +PKG_RELEASE:=1 + +PKG_SOURCE:=Embedded.L.1.0.34.ADI.R100.tar.gz +PKG_SOURCE_URL:=ftp://ftp.adiengineering.com/Archive/OcracokeIsland/Drivers/Linux/1.0.34/ +PKG_MD5SUM:=61df9778f8c1f919257d2f48a0bcb000 + +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/ep80579-drivers/Default + DEPENDS:=@TARGET_x86 +endef + +define KernelPackage/ep80579-eth +$(call KernelPackage/ep80579-drivers/Default) + SUBMENU:=Network Devices + TITLE:=Intel EP80579 ethernet driver + FILES:= \ + $(PKG_BUILD_DIR)/Embedded/build/gcu.$(LINUX_KMOD_SUFFIX) \ + $(PKG_BUILD_DIR)/Embedded/build/iegbe.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoLoad,40,gcu iegbe) +endef + +define KernelPackage/ep80579-misc +$(call KernelPackage/ep80579-drivers/Default) + SUBMENU:=Other modules + TITLE:=Misc. Intel EP80579 drivers (DMA,, gpio) + FILES:= \ + $(PKG_BUILD_DIR)/Embedded/build/dma.$(LINUX_KMOD_SUFFIX) \ + $(PKG_BUILD_DIR)/Embedded/build/gpio.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoLoad,40,gpio dma) +endef + +define KernelPackage/ep80579-can +$(call KernelPackage/ep80579-drivers/Default) + SUBMENU:=Other modules + TITLE:=Intel EP80579 CAN driver + FILES:= \ + $(PKG_BUILD_DIR)/Embedded/build/timesync.$(LINUX_KMOD_SUFFIX) \ + $(PKG_BUILD_DIR)/Embedded/build/can.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoLoad,40,timesync can) +endef + +define Build/Prepare + rm -rf $(PKG_BUILD_DIR) + mkdir -p $(PKG_BUILD_DIR) + tar xzvf $(DL_DIR)/$(PKG_SOURCE) -C $(PKG_BUILD_DIR)/ + $(Build/Patch) +endef + +define Build/Compile + (cd $(PKG_BUILD_DIR)/Embedded; \ + $(MAKE) KERNEL_SOURCE_ROOT=$(LINUX_DIR) \ + KSRC=$(LINUX_DIR) \ + KOBJ=$(LINUX_DIR) \ + ENV_DIR=$(PKG_BUILD_DIR)/Embedded \ + all \ + ) +endef + +define KernelPackage/ep80579-eth/install +endef + +$(eval $(call KernelPackage,ep80579-can)) +$(eval $(call KernelPackage,ep80579-eth)) +$(eval $(call KernelPackage,ep80579-misc)) + diff --git a/package/ep80579-drivers/patches/001-igbe_update.patch b/package/ep80579-drivers/patches/001-igbe_update.patch new file mode 100644 index 000000000..67560b8de --- /dev/null +++ b/package/ep80579-drivers/patches/001-igbe_update.patch @@ -0,0 +1,11755 @@ +--- a/Embedded/src/GbE/gcu.h ++++ b/Embedded/src/GbE/gcu.h +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +--- a/Embedded/src/GbE/gcu_if.c ++++ b/Embedded/src/GbE/gcu_if.c +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -330,10 +330,17 @@ gcu_write_verify(uint32_t phy_num, uint3 + */ + void gcu_iegbe_resume(struct pci_dev *pdev) + { ++#if ( ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,6) ) && \ ++ ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) ) ++ struct net_device *netdev = pci_get_drvdata(pdev); ++ struct gcu_adapter *adapter = netdev_priv(netdev); ++#endif ++ + GCU_DBG("%s\n", __func__); + + pci_restore_state(pdev); +- pci_enable_device(pdev); ++ if(!pci_enable_device(pdev)) ++ GCU_DBG("pci_enable_device failed!\n",); + + return; + } +@@ -348,6 +355,12 @@ EXPORT_SYMBOL(gcu_iegbe_resume); + */ + int gcu_iegbe_suspend(struct pci_dev *pdev, uint32_t state) + { ++#if ( ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,6) ) && \ ++ ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) ) ++ struct net_device *netdev = pci_get_drvdata(pdev); ++ struct gcu_adapter *adapter = netdev_priv(netdev); ++#endif ++ + GCU_DBG("%s\n", __func__); + + pci_save_state(pdev); +--- a/Embedded/src/GbE/gcu_if.h ++++ b/Embedded/src/GbE/gcu_if.h +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +--- a/Embedded/src/GbE/gcu_main.c ++++ b/Embedded/src/GbE/gcu_main.c +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -94,6 +94,7 @@ static struct pci_driver gcu_driver = { + + static struct gcu_adapter *global_adapter = 0; + static spinlock_t global_adapter_spinlock = SPIN_LOCK_UNLOCKED; ++static unsigned long g_intflags = 0; + + MODULE_AUTHOR("Intel(R) Corporation"); + MODULE_DESCRIPTION("Global Configuration Unit Driver"); +@@ -124,7 +125,7 @@ gcu_init_module(void) + + printk(KERN_INFO "%s\n", gcu_copyright); + +- ret = pci_module_init(&gcu_driver); ++ ret = pci_register_driver(&gcu_driver); + if(ret >= 0) { + register_reboot_notifier(&gcu_notifier_reboot); + } +@@ -199,8 +200,6 @@ gcu_probe(struct pci_dev *pdev, + return -ENOMEM; + } + +- SET_MODULE_OWNER(adapter); +- + pci_set_drvdata(pdev, adapter); + + adapter->pdev = pdev; +@@ -238,7 +237,6 @@ gcu_probe(struct pci_dev *pdev, + return 0; + } + +- + /** + * gcu_probe_err - gcu_probe error handler + * @err: gcu_err_type +@@ -295,7 +293,7 @@ gcu_notify_reboot(struct notifier_block + case SYS_DOWN: + case SYS_HALT: + case SYS_POWER_OFF: +- while((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) { ++ while((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) { + if(pci_dev_driver(pdev) == &gcu_driver){ + gcu_suspend(pdev, 0x3); + } +@@ -318,6 +316,11 @@ static int + gcu_suspend(struct pci_dev *pdev, uint32_t state) + { + /*struct gcu_adapter *adapter = pci_get_drvdata(pdev); */ ++#if ( ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,6) ) && \ ++ ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) ) ++ struct net_device *netdev = pci_get_drvdata(pdev); ++ struct gcu_adapter *adapter = netdev_priv(netdev); ++#endif + + GCU_DBG("%s\n", __func__); + +@@ -338,7 +341,6 @@ gcu_suspend(struct pci_dev *pdev, uint32 + return state; + } + +- + /** + * alloc_gcu_adapter + * +@@ -412,7 +414,7 @@ gcu_get_adapter(void) + return NULL; + } + +- spin_lock(&global_adapter_spinlock); ++ spin_lock_irqsave(&global_adapter_spinlock, g_intflags); + + return global_adapter; + } +@@ -437,7 +439,7 @@ gcu_release_adapter(const struct gcu_ada + *adapter = 0; + } + +- spin_unlock(&global_adapter_spinlock); ++ spin_unlock_irqrestore(&global_adapter_spinlock, g_intflags); + + return; + } +--- a/Embedded/src/GbE/gcu_reg.h ++++ b/Embedded/src/GbE/gcu_reg.h +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +--- a/Embedded/src/GbE/iegbe.7 ++++ b/Embedded/src/GbE/iegbe.7 +@@ -1,7 +1,7 @@ + + .\" GPL LICENSE SUMMARY + .\" +-.\" Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++.\" Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + .\" + .\" This program is free software; you can redistribute it and/or modify + .\" it under the terms of version 2 of the GNU General Public License as +@@ -21,7 +21,7 @@ + .\" Contact Information: + .\" Intel Corporation + .\" +-.\" version: Embedded.L.1.0.34 ++.\" version: Embedded.Release.Patch.L.1.0.7-5 + + .\" LICENSE + .\" +--- a/Embedded/src/GbE/iegbe_ethtool.c ++++ b/Embedded/src/GbE/iegbe_ethtool.c +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -132,22 +132,6 @@ static const struct iegbe_stats iegbe_gs + { "cpp_master", E1000_STAT(icr_cpp_master) }, + { "stat", E1000_STAT(icr_stat) }, + #endif +-#ifdef IEGBE_GBE_WORKAROUND +- { "txqec", E1000_STAT(stats.txqec) }, +- { "tx_next_to_clean", E1000_STAT(stats.tx_next_to_clean) }, +- { "tx_next_to_use", E1000_STAT(stats.tx_next_to_use) }, +- { "num_tx_queues", E1000_STAT(stats.num_tx_queues) }, +- +- { "num_rx_buf_alloc", E1000_STAT(stats.num_rx_buf_alloc) }, +- { "rx_next_to_clean", E1000_STAT(stats.rx_next_to_clean) }, +- { "rx_next_to_use", E1000_STAT(stats.rx_next_to_use) }, +- { "cc_gt_num_rx", E1000_STAT(stats.cc_gt_num_rx) }, +- { "tx_hnet", E1000_STAT(stats.tx_hnet) }, +- { "tx_hnentu", E1000_STAT(stats.tx_hnentu) }, +- { "RUC", E1000_STAT(stats.ruc) }, +- { "RFC", E1000_STAT(stats.rfc) }, +- +-#endif + }; + #define E1000_STATS_LEN \ + sizeof(iegbe_gstrings_stats) / sizeof(struct iegbe_stats) +@@ -158,7 +142,7 @@ static const char iegbe_gstrings_test[][ + "Interrupt test (offline)", "Loopback test (offline)", + "Link test (on/offline)" + }; +-#define E1000_TEST_LEN (sizeof(iegbe_gstrings_test) / (ETH_GSTRING_LEN)) ++#define E1000_TEST_LEN (sizeof(iegbe_gstrings_test) / ETH_GSTRING_LEN) + #endif /* ETHTOOL_TEST */ + + #define E1000_REGS_LEN 0x20 +@@ -176,9 +160,7 @@ iegbe_get_settings(struct net_device *ne + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | +-#ifndef IEGBE_10_100_ONLY + SUPPORTED_1000baseT_Full| +-#endif + SUPPORTED_Autoneg | + SUPPORTED_TP); + +@@ -259,21 +241,13 @@ iegbe_set_settings(struct net_device *ne + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | +-#ifndef IEGBE_10_100_ONLY + ADVERTISED_1000baseT_Full| +-#endif +- + ADVERTISED_Autoneg | + ADVERTISED_TP; + ecmd->advertising = hw->autoneg_advertised; + } +- } else { +- uint16_t duplex; +- +- // ethtool uses DUPLEX_FULL/DUPLEX_HALF +- // the driver needs FULL_DUPLEX/HALF_DUPLEX +- duplex = (ecmd->duplex == DUPLEX_FULL) ? FULL_DUPLEX : HALF_DUPLEX; +- if(iegbe_set_spd_dplx(adapter, ecmd->speed + duplex)) ++ } else ++ if(iegbe_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)){ + return -EINVAL; + } + /* reset the link */ +@@ -728,8 +702,8 @@ iegbe_set_ringparam(struct net_device *n + struct iegbe_rx_ring *rxdr, *rx_old, *rx_new; + int i, err, tx_ring_size, rx_ring_size; + +- tx_ring_size = sizeof(struct iegbe_tx_ring) * adapter->num_queues; +- rx_ring_size = sizeof(struct iegbe_rx_ring) * adapter->num_queues; ++ tx_ring_size = sizeof(struct iegbe_tx_ring) * adapter->num_tx_queues; ++ rx_ring_size = sizeof(struct iegbe_rx_ring) * adapter->num_rx_queues; + + if (netif_running(adapter->netdev)){ + iegbe_down(adapter); +@@ -768,10 +742,10 @@ iegbe_set_ringparam(struct net_device *n + E1000_MAX_TXD : E1000_MAX_82544_TXD)); + E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE); + +- for (i = 0; i < adapter->num_queues; i++) { +- txdr[i].count = txdr->count; +- rxdr[i].count = rxdr->count; +- } ++ for (i = 0; i < adapter->num_tx_queues; i++) ++ txdr[i].count = txdr->count; ++ for (i = 0; i < adapter->num_rx_queues; i++) ++ rxdr[i].count = rxdr->count; + + if(netif_running(adapter->netdev)) { + /* Try to get new resources before deleting old */ +@@ -950,8 +924,7 @@ iegbe_eeprom_test(struct iegbe_adapter * + + static irqreturn_t + iegbe_test_intr(int irq, +- void *data, +- struct pt_regs *regs) ++ void *data) + { + struct net_device *netdev = (struct net_device *) data; + struct iegbe_adapter *adapter = netdev_priv(netdev); +@@ -973,7 +946,7 @@ iegbe_intr_test(struct iegbe_adapter *ad + /* Hook up test interrupt handler just for this test */ + if(!request_irq(irq, &iegbe_test_intr, 0, netdev->name, netdev)) { + shared_int = FALSE; +- } else if(request_irq(irq, &iegbe_test_intr, SA_SHIRQ, ++ } else if(request_irq(irq, &iegbe_test_intr, IRQF_SHARED, + netdev->name, netdev)){ + *data = 1; + return -1; +@@ -1393,7 +1366,7 @@ iegbe_set_phy_loopback(struct iegbe_adap + * attempt this 10 times. + */ + while(iegbe_nonintegrated_phy_loopback(adapter) && +- count++ < 0xa) { }; ++ count++ < 0xa); + if(count < 0xb) { + return 0; + } +--- a/Embedded/src/GbE/iegbe.h ++++ b/Embedded/src/GbE/iegbe.h +@@ -1,7 +1,7 @@ + /******************************************************************************* + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -21,7 +21,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -127,9 +127,12 @@ struct iegbe_adapter; + #define E1000_MIN_RXD 80 + #define E1000_MAX_82544_RXD 4096 + ++#define MAXIMUM_ETHERNET_VLAN_SIZE 1522 + /* Supported Rx Buffer Sizes */ + #define E1000_RXBUFFER_128 128 /* Used for packet split */ + #define E1000_RXBUFFER_256 256 /* Used for packet split */ ++#define E1000_RXBUFFER_512 512 ++#define E1000_RXBUFFER_1024 1024 + #define E1000_RXBUFFER_2048 2048 + #define E1000_RXBUFFER_4096 4096 + #define E1000_RXBUFFER_8192 8192 +@@ -164,11 +167,9 @@ struct iegbe_adapter; + #define E1000_MASTER_SLAVE iegbe_ms_hw_default + #endif + +-#ifdef NETIF_F_HW_VLAN_TX +-#define E1000_MNG_VLAN_NONE -1 +-#endif ++#define E1000_MNG_VLAN_NONE (-1) + /* Number of packet split data buffers (not including the header buffer) */ +-#define PS_PAGE_BUFFERS MAX_PS_BUFFERS-1 ++#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1) + + /* only works for sizes that are powers of 2 */ + #define E1000_ROUNDUP(i, size) ((i) = (((i) + (size) - 1) & ~((size) - 1))) +@@ -206,6 +207,7 @@ struct iegbe_tx_ring { + spinlock_t tx_lock; + uint16_t tdh; + uint16_t tdt; ++ boolean_t last_tx_tso; + uint64_t pkt; + }; + +@@ -228,6 +230,9 @@ struct iegbe_rx_ring { + struct iegbe_ps_page *ps_page; + struct iegbe_ps_page_dma *ps_page_dma; + ++ /* cpu for rx queue */ ++ int cpu; ++ + uint16_t rdh; + uint16_t rdt; + uint64_t pkt; +@@ -252,10 +257,8 @@ struct iegbe_adapter { + struct timer_list tx_fifo_stall_timer; + struct timer_list watchdog_timer; + struct timer_list phy_info_timer; +-#ifdef NETIF_F_HW_VLAN_TX + struct vlan_group *vlgrp; + uint16_t mng_vlan_id; +-#endif + uint32_t bd_number; + uint32_t rx_buffer_len; + uint32_t part_num; +@@ -265,8 +268,18 @@ struct iegbe_adapter { + uint16_t link_speed; + uint16_t link_duplex; + spinlock_t stats_lock; +- atomic_t irq_sem; +- struct work_struct tx_timeout_task; ++ spinlock_t tx_queue_lock; ++ unsigned int total_tx_bytes; ++ unsigned int total_tx_packets; ++ unsigned int total_rx_bytes; ++ unsigned int total_rx_packets; ++ /* Interrupt Throttle Rate */ ++ uint32_t itr; ++ uint32_t itr_setting; ++ uint16_t tx_itr; ++ uint16_t rx_itr; ++ ++ struct work_struct reset_task; + uint8_t fc_autoneg; + + #ifdef ETHTOOL_PHYS_ID +@@ -276,9 +289,8 @@ struct iegbe_adapter { + + /* TX */ + struct iegbe_tx_ring *tx_ring; /* One per active queue */ +-#ifdef CONFIG_E1000_MQ +- struct iegbe_tx_ring **cpu_tx_ring; /* per-cpu */ +-#endif ++ unsigned int restart_queue; ++ unsigned long tx_queue_len; + uint32_t txd_cmd; + uint32_t tx_int_delay; + uint32_t tx_abs_int_delay; +@@ -286,46 +298,33 @@ struct iegbe_adapter { + uint64_t gotcl_old; + uint64_t tpt_old; + uint64_t colc_old; ++ uint32_t tx_timeout_count; + uint32_t tx_fifo_head; + uint32_t tx_head_addr; + uint32_t tx_fifo_size; ++ uint8_t tx_timeout_factor; + atomic_t tx_fifo_stall; + boolean_t pcix_82544; + boolean_t detect_tx_hung; + + /* RX */ +-#ifdef CONFIG_E1000_NAPI +- boolean_t (*clean_rx) (struct iegbe_adapter *adapter, ++ bool (*clean_rx)(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int *work_done, int work_to_do); +-#else +- boolean_t (*clean_rx) (struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring); +-#endif +- +-#ifdef IEGBE_GBE_WORKAROUND + void (*alloc_rx_buf) (struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring, +- int cleaned_count); +-#else +- void (*alloc_rx_buf) (struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring); +-#endif +- ++ struct iegbe_rx_ring *rx_ring, ++ int cleaned_count); + struct iegbe_rx_ring *rx_ring; /* One per active queue */ +-#ifdef CONFIG_E1000_NAPI ++ struct napi_struct napi; + struct net_device *polling_netdev; /* One per active queue */ +-#endif +-#ifdef CONFIG_E1000_MQ +- struct net_device **cpu_netdev; /* per-cpu */ +- struct call_async_data_struct rx_sched_call_data; +- int cpu_for_queue[4]; +-#endif +- int num_queues; ++ ++ int num_tx_queues; ++ int num_rx_queues; + + uint64_t hw_csum_err; + uint64_t hw_csum_good; + uint64_t rx_hdr_split; ++ uint32_t alloc_rx_buff_failed; + uint32_t rx_int_delay; + uint32_t rx_abs_int_delay; + boolean_t rx_csum; +@@ -334,8 +333,6 @@ struct iegbe_adapter { + uint64_t gorcl_old; + uint16_t rx_ps_bsize0; + +- /* Interrupt Throttle Rate */ +- uint32_t itr; + + /* OS defined structs */ + struct net_device *netdev; +@@ -378,7 +375,21 @@ struct iegbe_adapter { + #ifdef CONFIG_PCI_MSI + boolean_t have_msi; + #endif +-#define IEGBE_INTD_DISABLE 0x0400 ++ /* to not mess up cache alignment, always add to the bottom */ ++ boolean_t tso_force; ++ boolean_t smart_power_down; /* phy smart power down */ ++ boolean_t quad_port_a; ++ unsigned long flags; ++ uint32_t eeprom_wol; ++ int bars; ++ int need_ioport; + }; ++ ++enum iegbe_state_t { ++ __E1000_TESTING, ++ __E1000_RESETTING, ++ __E1000_DOWN ++}; ++#define IEGBE_INTD_DISABLE 0x0400 + #endif /* _IEGBE_H_ */ + +--- a/Embedded/src/GbE/iegbe_hw.c ++++ b/Embedded/src/GbE/iegbe_hw.c +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -2115,7 +2115,7 @@ iegbe_config_mac_to_phy(struct iegbe_hw + + ret_val = iegbe_oem_set_trans_gasket(hw); + if(ret_val){ +- return ret_val; ++ return ret_val; + } + ret_val = iegbe_oem_phy_is_full_duplex( + hw, (int *) &is_FullDuplex); +@@ -2164,7 +2164,7 @@ iegbe_config_mac_to_phy(struct iegbe_hw + } + /* Write the configured values back to the Device Control Reg. */ + E1000_WRITE_REG(hw, CTRL, ctrl); +- return E1000_SUCCESS; ++ return ret_val; + } + + /***************************************************************************** +@@ -2684,7 +2684,7 @@ iegbe_check_for_link(struct iegbe_hw *hw + + if(hw->autoneg_failed == 0) { + hw->autoneg_failed = 1; +- return 0; ++ return E1000_SUCCESS; + } + DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\r\n"); + +@@ -5875,7 +5875,7 @@ iegbe_get_cable_length(struct iegbe_hw * + max_agc = cur_agc; + } + } +- ++ + /* This is to fix a Klockwork defect, that the array index might + * be out of bounds. 113 is table size */ + if (cur_agc < 0x71){ +--- a/Embedded/src/GbE/iegbe_hw.h ++++ b/Embedded/src/GbE/iegbe_hw.h +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -299,7 +299,7 @@ void iegbe_set_media_type(struct iegbe_h + /* Link Configuration */ + int32_t iegbe_setup_link(struct iegbe_hw *hw); + int32_t iegbe_phy_setup_autoneg(struct iegbe_hw *hw); +-void iegbe_config_collision_dist(struct iegbe_hw *hw); ++void iegbe_config_collision_dist(struct iegbe_hw *hw); + int32_t iegbe_config_fc_after_link_up(struct iegbe_hw *hw); + int32_t iegbe_check_for_link(struct iegbe_hw *hw); + int32_t iegbe_get_speed_and_duplex(struct iegbe_hw *hw, uint16_t * speed, uint16_t * duplex); +@@ -588,14 +588,6 @@ uint8_t iegbe_arc_subsystem_valid(struct + * o LSC = Link Status Change + */ + +-#ifdef IEGBE_GBE_WORKAROUND +-#define IMS_ENABLE_MASK ( \ +- E1000_IMS_RXT0 | \ +- E1000_IMS_TXQE | \ +- E1000_IMS_RXDMT0 | \ +- E1000_IMS_RXSEQ | \ +- E1000_IMS_LSC) +-#else + #define IMS_ENABLE_MASK ( \ + E1000_IMS_RXT0 | \ + E1000_IMS_TXDW | \ +@@ -606,8 +598,7 @@ uint8_t iegbe_arc_subsystem_valid(struct + E1000_ICR_PB | \ + E1000_ICR_CPP_TARGET | \ + E1000_ICR_CPP_MASTER | \ +- E1000_IMS_LSC) +-#endif ++ E1000_ICR_LSC) + + /* Number of high/low register pairs in the RAR. The RAR (Receive Address + * Registers) holds the directed and multicast addresses that we monitor. We +@@ -923,10 +914,15 @@ struct iegbe_ffvt_entry { + #define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */ + #define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */ + #define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */ +-// Register conflict, does not exist for ICP_xxxx hardware +-// #define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */ + #define E1000_CTRL_AUX 0x000E0 /* Aux Control -RW */ ++#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */ + #define E1000_RCTL 0x00100 /* RX Control - RW */ ++#define E1000_RDTR1 0x02820 /* RX Delay Timer (1) - RW */ ++#define E1000_RDBAL1 0x02900 /* RX Descriptor Base Address Low (1) - RW */ ++#define E1000_RDBAH1 0x02904 /* RX Descriptor Base Address High (1) - RW */ ++#define E1000_RDLEN1 0x02908 /* RX Descriptor Length (1) - RW */ ++#define E1000_RDH1 0x02910 /* RX Descriptor Head (1) - RW */ ++#define E1000_RDT1 0x02918 /* RX Descriptor Tail (1) - RW */ + #define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */ + #define E1000_TXCW 0x00178 /* TX Configuration Word - RW */ + #define E1000_RXCW 0x00180 /* RX Configuration Word - RO */ +@@ -1282,8 +1278,6 @@ struct iegbe_ffvt_entry { + #define E1000_82542_FFMT E1000_FFMT + #define E1000_82542_FFVT E1000_FFVT + #define E1000_82542_HOST_IF E1000_HOST_IF +-// Register conflict with ICP_xxxx hardware, no IAM +-// #define E1000_82542_IAM E1000_IAM + #define E1000_82542_EEMNGCTL E1000_EEMNGCTL + #define E1000_82542_PSRCTL E1000_PSRCTL + #define E1000_82542_RAID E1000_RAID +@@ -1329,6 +1323,7 @@ struct iegbe_hw_stats { + uint64_t algnerrc; + uint64_t symerrs; + uint64_t rxerrc; ++ uint64_t txerrc; + uint64_t mpc; + uint64_t scc; + uint64_t ecol; +@@ -1363,6 +1358,7 @@ struct iegbe_hw_stats { + uint64_t ruc; + uint64_t rfc; + uint64_t roc; ++ uint64_t rlerrc; + uint64_t rjc; + uint64_t mgprc; + uint64_t mgpdc; +@@ -1392,19 +1388,6 @@ struct iegbe_hw_stats { + uint64_t ictxqmtc; + uint64_t icrxdmtc; + uint64_t icrxoc; +-#ifdef IEGBE_GBE_WORKAROUND +- u64 txqec; +- u64 tx_next_to_clean; +- u64 tx_next_to_use; +- u64 cc_gt_num_rx; +- u64 tx_hnet; +- u64 tx_hnentu; +- u64 num_tx_queues; +- +- u64 num_rx_buf_alloc; +- u64 rx_next_to_clean; +- u64 rx_next_to_use; +-#endif + }; + + /* Structure containing variables used by the shared code (iegbe_hw.c) */ +@@ -1484,6 +1467,7 @@ struct iegbe_hw { + boolean_t ifs_params_forced; + boolean_t in_ifs_mode; + boolean_t mng_reg_access_disabled; ++ boolean_t rx_needs_kicking; + boolean_t icp_xxxx_is_link_up; + }; + +@@ -2358,17 +2342,23 @@ struct iegbe_host_command_info { + #define E1000_EXTCNF_SIZE_EXT_PHY_LENGTH 0x000000FF + #define E1000_EXTCNF_SIZE_EXT_DOCK_LENGTH 0x0000FF00 + #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH 0x00FF0000 ++#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001 ++#define E1000_EXTCNF_CTRL_SWFLAG 0x00000020 + + /* PBA constants */ ++#define E1000_PBA_8K 0x0008 /* 8KB, default Rx allocation */ + #define E1000_PBA_12K 0x000C /* 12KB, default Rx allocation */ + #define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */ ++#define E1000_PBA_20K 0x0014 + #define E1000_PBA_22K 0x0016 + #define E1000_PBA_24K 0x0018 + #define E1000_PBA_30K 0x001E + #define E1000_PBA_32K 0x0020 ++#define E1000_PBA_34K 0x0022 + #define E1000_PBA_38K 0x0026 + #define E1000_PBA_40K 0x0028 + #define E1000_PBA_48K 0x0030 /* 48KB, default RX allocation */ ++#define E1000_PBS_16K E1000_PBA_16K + + /* Flow Control Constants */ + #define FLOW_CONTROL_ADDRESS_LOW 0x00C28001 +@@ -2899,7 +2889,7 @@ struct iegbe_host_command_info { + #define M88E1000_14_PHY_ID M88E1000_E_PHY_ID + #define M88E1011_I_REV_4 0x04 + #define M88E1111_I_PHY_ID 0x01410CC2 +-#define M88E1141_E_PHY_ID 0x01410CD4 ++#define M88E1141_E_PHY_ID 0x01410CD0 + #define L1LXT971A_PHY_ID 0x001378E0 + + /* Miscellaneous PHY bit definitions. */ +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -42,103 +42,15 @@ GPL LICENSE SUMMARY + + #include "iegbe.h" + #include "gcu_if.h" +- +-/* Change Log +- * 6.0.58 4/20/05 +- * o iegbe_set_spd_dplx tests for compatible speed/duplex specification +- * for fiber adapters +- * 6.0.57 4/19/05 +- * o Added code to fix register test failure for devices >= 82571 +- * +- * 6.0.52 3/15/05 +- * o Added stats_lock around iegbe_read_phy_reg commands to avoid concurrent +- * calls, one from mii_ioctl and other from within update_stats while +- * processing MIIREG ioctl. +- * +- * 6.1.2 4/13/05 +- * o Fixed ethtool diagnostics +- * o Enabled flow control to take default eeprom settings +- * o Added stats_lock around iegbe_read_phy_reg commands to avoid concurrent +- * calls, one from mii_ioctl and other from within update_stats while processing +- * MIIREG ioctl. +- * 6.0.55 3/23/05 +- * o Support for MODULE_VERSION +- * o Fix APM setting for 82544 based adapters +- * 6.0.54 3/26/05 +- * o Added a timer to expire packets that were deferred for cleanup +- * 6.0.52 3/15/05 +- * o Added stats_lock around iegbe_read_phy_reg commands to avoid concurrent +- * calls, one from mii_ioctl and other from within update_stats while +- * processing MIIREG ioctl. +- * 6.0.47 3/2/05 +- * o Added enhanced functionality to the loopback diags to wrap the +- * descriptor rings +- * o Added manageability vlan filtering workaround. +- * +- * 6.0.44+ 2/15/05 +- * o Added code to handle raw packet based DHCP packets +- * o Added code to fix the errata 10 buffer overflow issue +- * o Sync up with WR01-05 +- * o applied Anton's patch to resolve tx hang in hardware +- * o iegbe timeouts with early writeback patch +- * o Removed Queensport IDs +- * o fixed driver panic if MAC receives a bad large packets when packet +- * split is enabled +- * o Applied Andrew Mortons patch - iegbe stops working after resume +- * 5.2.29 12/24/03 +- * o Bug fix: Endianess issue causing ethtool diags to fail on ppc. +- * o Bug fix: Use pdev->irq instead of netdev->irq for MSI support. +- * o Report driver message on user override of InterruptThrottleRate module +- * parameter. +- * o Bug fix: Change I/O address storage from uint32_t to unsigned long. +- * o Feature: Added ethtool RINGPARAM support. +- * o Feature: Added netpoll support. +- * o Bug fix: Race between Tx queue and Tx clean fixed with a spin lock. +- * o Bug fix: Allow 1000/Full setting for autoneg param for fiber connections. +- * Jon D Mason [jonmason@us.ibm.com]. +- * +- * 5.2.22 10/15/03 +- * o Bug fix: SERDES devices might be connected to a back-plane switch that +- * doesn't support auto-neg, so add the capability to force 1000/Full. +- * Also, since forcing 1000/Full, sample RxSynchronize bit to detect link +- * state. +- * o Bug fix: Flow control settings for hi/lo watermark didn't consider +- * changes in the RX FIFO size, which could occur with Jumbo Frames or with +- * the reduced FIFO in 82547. +- * o Bug fix: Better propagation of error codes. +- * [Janice Girouard (janiceg -a-t- us.ibm.com)] +- * o Bug fix: hang under heavy Tx stress when running out of Tx descriptors; +- * wasn't clearing context descriptor when backing out of send because of +- * no-resource condition. +- * o Bug fix: check netif_running in dev->poll so we don't have to hang in +- * dev->close until all polls are finished. [Rober Olsson +- * (robert.olsson@data.slu.se)]. +- * o Revert TxDescriptor ring size back to 256 since change to 1024 wasn't +- * accepted into the kernel. +- * +- * 5.2.16 8/8/03 +- */ +- +-#ifdef IEGBE_GBE_WORKAROUND +-#define IEGBE_GBE_WORKAROUND_NUM_RX_DESCRIPTORS 1 +-#endif ++#include ++#include + + char iegbe_driver_name[] = "iegbe"; + char iegbe_driver_string[] = "Gigabit Ethernet Controller Driver"; +-#ifndef CONFIG_E1000_NAPI +-#define DRIVERNAPI +-#else +-#define DRIVERNAPI "-NAPI" +-#endif +-#define DRV_VERSION "0.8.0"DRIVERNAPI ++#define DRV_VERSION "1.0.0-K28-NAPI" + char iegbe_driver_version[] = DRV_VERSION; +-char iegbe_copyright[] = "Copyright (c) 1999-2007 Intel Corporation."; ++char iegbe_copyright[] = "Copyright (c) 1999-2009 Intel Corporation."; + +-#define E1000_FIFO_HDR 0x10 +-#define E1000_82547_PAD_LEN 0x3E0 +-#define MINIMUM_DHCP_PACKET_SIZE 282 +-#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 ) +-#define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 + + /* iegbe_pci_tbl - PCI Device ID Table + * +@@ -148,95 +60,48 @@ char iegbe_copyright[] = "Copyright (c) + * {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)} + */ + static struct pci_device_id iegbe_pci_tbl[] = { +-/* INTEL_E1000_ETHERNET_DEVICE(0x1000), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1001), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1004), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1008), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1009), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x100C), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x100D), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x100E), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x100F), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1010), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1011), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1012), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1013), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1014), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1015), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1016), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1017), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1018), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1019), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x101A), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x101D), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x101E), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1026), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1027), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1028), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x105E), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x105F), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1060), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1075), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1076), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1077), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1078), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1079), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x107A), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x107B), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x107C), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x107D), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x107E), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x107F), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x108A), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x108B), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x108C), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x109A), */ +- INTEL_E1000_ETHERNET_DEVICE(0x5040), +- INTEL_E1000_ETHERNET_DEVICE(0x5041), +- INTEL_E1000_ETHERNET_DEVICE(0x5042), +- INTEL_E1000_ETHERNET_DEVICE(0x5043), +- INTEL_E1000_ETHERNET_DEVICE(0x5044), +- INTEL_E1000_ETHERNET_DEVICE(0x5045), +- INTEL_E1000_ETHERNET_DEVICE(0x5046), +- INTEL_E1000_ETHERNET_DEVICE(0x5047), +- INTEL_E1000_ETHERNET_DEVICE(0x5048), +- INTEL_E1000_ETHERNET_DEVICE(0x5049), +- INTEL_E1000_ETHERNET_DEVICE(0x504A), +- INTEL_E1000_ETHERNET_DEVICE(0x504B), +- /* required last entry */ ++ INTEL_E1000_ETHERNET_DEVICE(0x5040), ++ INTEL_E1000_ETHERNET_DEVICE(0x5041), ++ INTEL_E1000_ETHERNET_DEVICE(0x5042), ++ INTEL_E1000_ETHERNET_DEVICE(0x5043), ++ INTEL_E1000_ETHERNET_DEVICE(0x5044), ++ INTEL_E1000_ETHERNET_DEVICE(0x5045), ++ INTEL_E1000_ETHERNET_DEVICE(0x5046), ++ INTEL_E1000_ETHERNET_DEVICE(0x5047), ++ INTEL_E1000_ETHERNET_DEVICE(0x5048), ++ INTEL_E1000_ETHERNET_DEVICE(0x5049), ++ INTEL_E1000_ETHERNET_DEVICE(0x504A), ++ INTEL_E1000_ETHERNET_DEVICE(0x504B), ++ /* required last entry */ + {0,} + }; + + MODULE_DEVICE_TABLE(pci, iegbe_pci_tbl); + +-DEFINE_SPINLOCK(print_lock); + + int iegbe_up(struct iegbe_adapter *adapter); + void iegbe_down(struct iegbe_adapter *adapter); ++void iegbe_reinit_locked(struct iegbe_adapter *adapter); + void iegbe_reset(struct iegbe_adapter *adapter); + int iegbe_set_spd_dplx(struct iegbe_adapter *adapter, uint16_t spddplx); + int iegbe_setup_all_tx_resources(struct iegbe_adapter *adapter); + int iegbe_setup_all_rx_resources(struct iegbe_adapter *adapter); + void iegbe_free_all_tx_resources(struct iegbe_adapter *adapter); + void iegbe_free_all_rx_resources(struct iegbe_adapter *adapter); +-int iegbe_setup_tx_resources(struct iegbe_adapter *adapter, ++static int iegbe_setup_tx_resources(struct iegbe_adapter *adapter, + struct iegbe_tx_ring *txdr); +-int iegbe_setup_rx_resources(struct iegbe_adapter *adapter, ++static int iegbe_setup_rx_resources(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rxdr); +-void iegbe_free_tx_resources(struct iegbe_adapter *adapter, ++static void iegbe_free_tx_resources(struct iegbe_adapter *adapter, + struct iegbe_tx_ring *tx_ring); +-void iegbe_free_rx_resources(struct iegbe_adapter *adapter, ++static void iegbe_free_rx_resources(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring); + void iegbe_update_stats(struct iegbe_adapter *adapter); +- + static int iegbe_init_module(void); + static void iegbe_exit_module(void); + static int iegbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent); + static void __devexit iegbe_remove(struct pci_dev *pdev); + static int iegbe_alloc_queues(struct iegbe_adapter *adapter); +-#ifdef CONFIG_E1000_MQ +-static void iegbe_setup_queue_mapping(struct iegbe_adapter *adapter); +-#endif + static int iegbe_sw_init(struct iegbe_adapter *adapter); + static int iegbe_open(struct net_device *netdev); + static int iegbe_close(struct net_device *netdev); +@@ -249,7 +114,8 @@ static void iegbe_clean_tx_ring(struct i + struct iegbe_tx_ring *tx_ring); + static void iegbe_clean_rx_ring(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring); +-static void iegbe_set_multi(struct net_device *netdev); ++ ++static void iegbe_set_rx_mode(struct net_device *netdev); + static void iegbe_update_phy_info(unsigned long data); + static void iegbe_watchdog(unsigned long data); + static void iegbe_82547_tx_fifo_stall(unsigned long data); +@@ -257,66 +123,46 @@ static int iegbe_xmit_frame(struct sk_bu + static struct net_device_stats * iegbe_get_stats(struct net_device *netdev); + static int iegbe_change_mtu(struct net_device *netdev, int new_mtu); + static int iegbe_set_mac(struct net_device *netdev, void *p); +-static irqreturn_t iegbe_intr(int irq, void *data, struct pt_regs *regs); ++static irqreturn_t iegbe_intr(int irq, void *data); + +-void iegbe_tasklet(unsigned long); ++static irqreturn_t iegbe_intr_msi(int irq, void *data); + +-#ifndef IEGBE_GBE_WORKAROUND +-static boolean_t iegbe_clean_tx_irq(struct iegbe_adapter *adapter, ++static bool iegbe_clean_tx_irq(struct iegbe_adapter *adapter, + struct iegbe_tx_ring *tx_ring); +-#endif +- +-#ifdef CONFIG_E1000_NAPI +-static int iegbe_clean(struct net_device *poll_dev, int *budget); +-static boolean_t iegbe_clean_rx_irq(struct iegbe_adapter *adapter, ++static int iegbe_clean(struct napi_struct *napi, int budget); ++static bool iegbe_clean_rx_irq(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int *work_done, int work_to_do); +-static boolean_t iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter, ++static bool iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int *work_done, int work_to_do); +-#else +-static boolean_t iegbe_clean_rx_irq(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring); +-static boolean_t iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring); +-#endif + +-#ifdef IEGBE_GBE_WORKAROUND ++ + static void iegbe_alloc_rx_buffers(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int cleaned_count); + static void iegbe_alloc_rx_buffers_ps(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int cleaned_count); +-#else +-static void iegbe_alloc_rx_buffers(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring); +-static void iegbe_alloc_rx_buffers_ps(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring); +-#endif ++ + + static int iegbe_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); +-#ifdef SIOCGMIIPHY + static int iegbe_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, +- int cmd); +-#endif ++ int cmd); + void set_ethtool_ops(struct net_device *netdev); + extern int ethtool_ioctl(struct ifreq *ifr); + static void iegbe_enter_82542_rst(struct iegbe_adapter *adapter); + static void iegbe_leave_82542_rst(struct iegbe_adapter *adapter); + static void iegbe_tx_timeout(struct net_device *dev); +-static void iegbe_tx_timeout_task(struct net_device *dev); ++static void iegbe_reset_task(struct work_struct *work); + static void iegbe_smartspeed(struct iegbe_adapter *adapter); + static inline int iegbe_82547_fifo_workaround(struct iegbe_adapter *adapter, +- struct sk_buff *skb); ++ struct sk_buff *skb); + +-#ifdef NETIF_F_HW_VLAN_TX +-static void iegbe_vlan_rx_register(struct net_device *netdev, +- struct vlan_group *grp); ++static void iegbe_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp); + static void iegbe_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid); + static void iegbe_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid); + static void iegbe_restore_vlan(struct iegbe_adapter *adapter); +-#endif + + static int iegbe_notify_reboot(struct notifier_block *, + unsigned long event, +@@ -331,15 +177,17 @@ static int iegbe_resume(struct pci_dev * + static void iegbe_netpoll (struct net_device *netdev); + #endif + +-#ifdef CONFIG_E1000_MQ +-/* for multiple Rx queues */ ++#define COPYBREAK_DEFAULT 256 ++static unsigned int copybreak __read_mostly = COPYBREAK_DEFAULT; ++module_param(copybreak, uint, 0644); ++MODULE_PARM_DESC(copybreak, ++ "Maximum size of packet that is copied to a new buffer on receive"); + void iegbe_rx_schedule(void *data); +-#endif + + struct notifier_block iegbe_notifier_reboot = { +- .notifier_call = iegbe_notify_reboot, +- .next = NULL, +- .priority = 0 ++ .notifier_call = iegbe_notify_reboot, ++ .next = NULL, ++ .priority = 0 + }; + + /* Exported from other modules */ +@@ -347,14 +195,14 @@ struct notifier_block iegbe_notifier_reb + extern void iegbe_check_options(struct iegbe_adapter *adapter); + + static struct pci_driver iegbe_driver = { +- .name = iegbe_driver_name, +- .id_table = iegbe_pci_tbl, +- .probe = iegbe_probe, +- .remove = __devexit_p(iegbe_remove), +- /* Power Managment Hooks */ ++ .name = iegbe_driver_name, ++ .id_table = iegbe_pci_tbl, ++ .probe = iegbe_probe, ++ .remove = __devexit_p(iegbe_remove), ++ /* Power Managment Hooks */ + #ifdef CONFIG_PM +- .suspend = iegbe_suspend, +- .resume = iegbe_resume ++ .suspend = iegbe_suspend, ++ .resume = iegbe_resume + #endif + }; + +@@ -364,46 +212,17 @@ MODULE_LICENSE("GPL"); + MODULE_VERSION(DRV_VERSION); + + static int debug = NETIF_MSG_DRV | NETIF_MSG_PROBE; +-module_param(debug, int, 0); ++module_param(debug, int, 0x0); + MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); + +-static uint8_t gcu_suspend = 0; +-static uint8_t gcu_resume = 0; ++static uint8_t gcu_suspend = 0x0; ++static uint8_t gcu_resume = 0x0; + struct pci_dev *gcu = NULL; + +-unsigned long tasklet_data; +-DECLARE_TASKLET(iegbe_reset_tasklet, iegbe_tasklet, (unsigned long) &tasklet_data); + + /** + * iegbe_iegbe_tasklet -* + **/ +-void iegbe_tasklet(unsigned long data) +-{ +- char* err_msg = "TEST"; +- uint32_t *icr = (uint32_t*) data; +- uint32_t gbe = *icr & 0x000000FF; +- if( *icr & E1000_ICR_RX_DESC_FIFO_PAR) { /* 21 */ +- err_msg = "DMA Transmit Descriptor 2-bit ECC Error!"; +- } +- if( *icr & E1000_ICR_TX_DESC_FIFO_PAR) { /* 20 */ +- err_msg = "DMA Receive Descriptor 2-bit ECC Error!"; +- } +- if( *icr & E1000_ICR_PB) { /* 23 */ +- err_msg = "DMA Packet Buffer 2-bit ECC Error!"; +- } +- if( *icr & E1000_ICR_CPP_TARGET) { /* 27 */ +- err_msg = "Statistic Register ECC Error!"; +- } +- if( *icr & E1000_ICR_CPP_MASTER) { +- err_msg = "CPP Error!"; +- } +- spin_lock(&print_lock); +- printk("IEGBE%d: System Reset due to: %s\n", gbe, err_msg); +- dump_stack(); +- spin_unlock(&print_lock); +- panic(err_msg); +- return; +-} + /** + * iegbe_init_module - Driver Registration Routine + * +@@ -411,21 +230,24 @@ void iegbe_tasklet(unsigned long data) + * loaded. All it does is register with the PCI subsystem. + **/ + +-static int __init +-iegbe_init_module(void) ++static int __init iegbe_init_module(void) + { +- int ret; ++ int ret; + + printk(KERN_INFO "%s - version %s\n", +- iegbe_driver_string, iegbe_driver_version); ++ iegbe_driver_string, iegbe_driver_version); + +- printk(KERN_INFO "%s\n", iegbe_copyright); ++ printk(KERN_INFO "%s\n", iegbe_copyright); + +- ret = pci_module_init(&iegbe_driver); +- if(ret >= 0) { +- register_reboot_notifier(&iegbe_notifier_reboot); +- } +- return ret; ++ ret = pci_register_driver(&iegbe_driver); ++ if (copybreak != COPYBREAK_DEFAULT) { ++ if (copybreak == 0) ++ printk(KERN_INFO "iegbe: copybreak disabled\n"); ++ else ++ printk(KERN_INFO "iegbe: copybreak enabled for " ++ "packets <= %u bytes\n", copybreak); ++ } ++ return ret; + } + + module_init(iegbe_init_module); +@@ -437,29 +259,51 @@ module_init(iegbe_init_module); + * from memory. + **/ + +-static void __exit +-iegbe_exit_module(void) ++static void __exit iegbe_exit_module(void) + { +- +- unregister_reboot_notifier(&iegbe_notifier_reboot); +- pci_unregister_driver(&iegbe_driver); ++ pci_unregister_driver(&iegbe_driver); + } + + module_exit(iegbe_exit_module); + ++static int iegbe_request_irq(struct iegbe_adapter *adapter) ++{ ++ struct net_device *netdev = adapter->netdev; ++ irq_handler_t handler = iegbe_intr; ++ int irq_flags = IRQF_SHARED; ++ int err; ++ adapter->have_msi = !pci_enable_msi(adapter->pdev); ++ if (adapter->have_msi) { ++ handler = iegbe_intr_msi; ++ irq_flags = 0; ++ } ++ err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name, ++ netdev); ++ if (err) { ++ if (adapter->have_msi) ++ pci_disable_msi(adapter->pdev); ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate interrupt Error: %d\n", err); ++ } ++ return err; ++} ++static void iegbe_free_irq(struct iegbe_adapter *adapter) ++{ ++ struct net_device *netdev = adapter->netdev; ++ free_irq(adapter->pdev->irq, netdev); ++ if (adapter->have_msi) ++ pci_disable_msi(adapter->pdev); ++} + /** + * iegbe_irq_disable - Mask off interrupt generation on the NIC + * @adapter: board private structure + **/ + +-static inline void +-iegbe_irq_disable(struct iegbe_adapter *adapter) ++static void iegbe_irq_disable(struct iegbe_adapter *adapter) + { +- +- atomic_inc(&adapter->irq_sem); +- E1000_WRITE_REG(&adapter->hw, IMC, ~0); +- E1000_WRITE_FLUSH(&adapter->hw); +- synchronize_irq(adapter->pdev->irq); ++ E1000_WRITE_REG(&adapter->hw, IMC, ~0); ++ E1000_WRITE_FLUSH(&adapter->hw); ++ synchronize_irq(adapter->pdev->irq); + } + + /** +@@ -470,244 +314,414 @@ iegbe_irq_disable(struct iegbe_adapter * + static inline void + iegbe_irq_enable(struct iegbe_adapter *adapter) + { +- +- if(likely(atomic_dec_and_test(&adapter->irq_sem))) { +- E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK); +- E1000_WRITE_FLUSH(&adapter->hw); +- } ++ E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK); ++ E1000_WRITE_FLUSH(&adapter->hw); + } +-#ifdef NETIF_F_HW_VLAN_TX +-void +-iegbe_update_mng_vlan(struct iegbe_adapter *adapter) +-{ +- struct net_device *netdev = adapter->netdev; +- uint16_t vid = adapter->hw.mng_cookie.vlan_id; +- uint16_t old_vid = adapter->mng_vlan_id; + +- if(adapter->vlgrp) { +- if(!adapter->vlgrp->vlan_devices[vid]) { +- if(adapter->hw.mng_cookie.status & +- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) { +- iegbe_vlan_rx_add_vid(netdev, vid); +- adapter->mng_vlan_id = vid; +- } else { +- adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; +- } +- if((old_vid != (uint16_t)E1000_MNG_VLAN_NONE) && +- (vid != old_vid) && +- !adapter->vlgrp->vlan_devices[old_vid]) { +- iegbe_vlan_rx_kill_vid(netdev, old_vid); +- } +- } +-} ++static void iegbe_update_mng_vlan(struct iegbe_adapter *adapter) ++{ ++ struct iegbe_hw *hw = &adapter->hw; ++ struct net_device *netdev = adapter->netdev; ++ u16 vid = hw->mng_cookie.vlan_id; ++ u16 old_vid = adapter->mng_vlan_id; ++ if (adapter->vlgrp) { ++ if (!vlan_group_get_device(adapter->vlgrp, vid)) { ++ if (hw->mng_cookie.status & ++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) { ++ iegbe_vlan_rx_add_vid(netdev, vid); ++ adapter->mng_vlan_id = vid; ++ } else ++ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; ++ ++ if ((old_vid != (u16)E1000_MNG_VLAN_NONE) && ++ (vid != old_vid) && ++ !vlan_group_get_device(adapter->vlgrp, old_vid)) ++ iegbe_vlan_rx_kill_vid(netdev, old_vid); ++ } else ++ adapter->mng_vlan_id = vid; ++ } + } +-#endif + +-int +-iegbe_up(struct iegbe_adapter *adapter) ++/** ++ * iegbe_configure - configure the hardware for RX and TX ++ * @adapter = private board structure ++ **/ ++static void iegbe_configure(struct iegbe_adapter *adapter) + { + struct net_device *netdev = adapter->netdev; +- int i, err; +- uint16_t pci_cmd; +- +- /* hardware has been reset, we need to reload some things */ +- +- /* Reset the PHY if it was previously powered down */ +- if(adapter->hw.media_type == iegbe_media_type_copper +- || (adapter->hw.media_type == iegbe_media_type_oem +- && iegbe_oem_phy_is_copper(&adapter->hw))) { +- uint16_t mii_reg; +- iegbe_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg); +- if(mii_reg & MII_CR_POWER_DOWN){ +- iegbe_phy_reset(&adapter->hw); +- } +- } ++ int i; + +- iegbe_set_multi(netdev); ++ iegbe_set_rx_mode(netdev); + +-#ifdef NETIF_F_HW_VLAN_TX + iegbe_restore_vlan(adapter); +-#endif + + iegbe_configure_tx(adapter); + iegbe_setup_rctl(adapter); + iegbe_configure_rx(adapter); ++ /* call E1000_DESC_UNUSED which always leaves ++ * at least 1 descriptor unused to make sure ++ * next_to_use != next_to_clean */ ++ for (i = 0; i < adapter->num_rx_queues; i++) { ++ struct iegbe_rx_ring *ring = &adapter->rx_ring[i]; ++ adapter->alloc_rx_buf(adapter, ring, ++ E1000_DESC_UNUSED(ring)); ++ } + +-#ifdef IEGBE_GBE_WORKAROUND +- for (i = 0; i < adapter->num_queues; i++) +- adapter->alloc_rx_buf(adapter, &adapter->rx_ring[i], +- IEGBE_GBE_WORKAROUND_NUM_RX_DESCRIPTORS + 1); +-#else +- for (i = 0; i < adapter->num_queues; i++) +- adapter->alloc_rx_buf(adapter, &adapter->rx_ring[i]); +-#endif ++ adapter->tx_queue_len = netdev->tx_queue_len; ++} + +-#ifdef CONFIG_PCI_MSI +- if(adapter->hw.mac_type > iegbe_82547_rev_2 +- || adapter->hw.mac_type == iegbe_icp_xxxx) { +- adapter->have_msi = TRUE; +- if((err = pci_enable_msi(adapter->pdev))) { +- DPRINTK(PROBE, ERR, +- "Unable to allocate MSI interrupt Error: %d\n", err); +- adapter->have_msi = FALSE; +- } +- } +- pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd); +- pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd | IEGBE_INTD_DISABLE); ++int iegbe_up(struct iegbe_adapter *adapter) ++{ ++ /* hardware has been reset, we need to reload some things */ ++ iegbe_configure(adapter); + +-#endif +- if((err = request_irq(adapter->pdev->irq, &iegbe_intr, +- SA_SHIRQ | SA_SAMPLE_RANDOM, +- netdev->name, netdev))) { +- DPRINTK(PROBE, ERR, +- "Unable to allocate interrupt Error: %d\n", err); +- return err; +- } ++ clear_bit(__E1000_DOWN, &adapter->flags); + +- mod_timer(&adapter->watchdog_timer, jiffies); ++ napi_enable(&adapter->napi); + +-#ifdef CONFIG_E1000_NAPI +- netif_poll_enable(netdev); +-#endif + iegbe_irq_enable(adapter); + ++ adapter->hw.get_link_status = 0x1; + return 0; + } + +-void +-iegbe_down(struct iegbe_adapter *adapter) +-{ +- struct net_device *netdev = adapter->netdev; +- +- iegbe_irq_disable(adapter); +-#ifdef CONFIG_E1000_MQ +- while (atomic_read(&adapter->rx_sched_call_data.count) != 0) { }; +-#endif +- free_irq(adapter->pdev->irq, netdev); +-#ifdef CONFIG_PCI_MSI +- if((adapter->hw.mac_type > iegbe_82547_rev_2 +- || adapter->hw.mac_type == iegbe_icp_xxxx) +- && adapter->have_msi == TRUE) { +- pci_disable_msi(adapter->pdev); +- } +-#endif +- del_timer_sync(&adapter->tx_fifo_stall_timer); +- del_timer_sync(&adapter->watchdog_timer); +- del_timer_sync(&adapter->phy_info_timer); ++/** ++ * iegbe_power_up_phy - restore link in case the phy was powered down ++ * @adapter: address of board private structure ++ * ++ * The phy may be powered down to save power and turn off link when the ++ * driver is unloaded and wake on lan is not enabled (among others) ++ * *** this routine MUST be followed by a call to iegbe_reset *** ++ * ++ **/ + +-#ifdef CONFIG_E1000_NAPI +- netif_poll_disable(netdev); +-#endif +- adapter->link_speed = 0; +- adapter->link_duplex = 0; +- netif_carrier_off(netdev); +- netif_stop_queue(netdev); ++void iegbe_power_up_phy(struct iegbe_adapter *adapter) ++{ ++ struct iegbe_hw *hw = &adapter->hw; ++ u16 mii_reg = 0; + +- iegbe_reset(adapter); +- iegbe_clean_all_tx_rings(adapter); +- iegbe_clean_all_rx_rings(adapter); ++ /* Just clear the power down bit to wake the phy back up */ ++ if (hw->media_type == iegbe_media_type_copper) { ++ /* according to the manual, the phy will retain its ++ * settings across a power-down/up cycle */ ++ iegbe_read_phy_reg(hw, PHY_CTRL, &mii_reg); ++ mii_reg &= ~MII_CR_POWER_DOWN; ++ iegbe_write_phy_reg(hw, PHY_CTRL, mii_reg); ++ } ++} + +- /* If WoL is not enabled and management mode is not IAMT +- * or if WoL is not enabled and OEM PHY is copper based, +- * power down the PHY so no link is implied when interface is down */ +- if(!adapter->wol +- && ((adapter->hw.mac_type >= iegbe_82540 +- && adapter->hw.media_type == iegbe_media_type_copper +- && !iegbe_check_mng_mode(&adapter->hw) +- && !(E1000_READ_REG(&adapter->hw, MANC) & E1000_MANC_SMBUS_EN)) +- || (adapter->hw.media_type == iegbe_media_type_oem +- && iegbe_oem_phy_is_copper(&adapter->hw)))){ ++static void iegbe_power_down_phy(struct iegbe_adapter *adapter) ++{ ++ struct iegbe_hw *hw = &adapter->hw; + +- uint16_t mii_reg; +- iegbe_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg); ++ /* Power down the PHY so no link is implied when interface is down * ++ * The PHY cannot be powered down if any of the following is true * ++ * (a) WoL is enabled ++ * (b) AMT is active ++ * (c) SoL/IDER session is active */ ++ if (!adapter->wol && hw->mac_type >= iegbe_82540 && ++ hw->media_type == iegbe_media_type_copper) { ++ u16 mii_reg = 0; ++ ++ switch (hw->mac_type) { ++ case iegbe_82540: ++ case iegbe_82545: ++ case iegbe_82545_rev_3: ++ case iegbe_82546: ++ case iegbe_82546_rev_3: ++ case iegbe_82541: ++ case iegbe_82541_rev_2: ++ case iegbe_82547: ++ case iegbe_82547_rev_2: ++ if (E1000_READ_REG(&adapter->hw, MANC) & E1000_MANC_SMBUS_EN) ++ goto out; ++ break; ++ case iegbe_82571: ++ case iegbe_82572: ++ case iegbe_82573: ++ if (iegbe_check_mng_mode(hw) || ++ iegbe_check_phy_reset_block(hw)) ++ goto out; ++ break; ++ default: ++ goto out; ++ } ++ iegbe_read_phy_reg(hw, PHY_CTRL, &mii_reg); + mii_reg |= MII_CR_POWER_DOWN; +- iegbe_write_phy_reg(&adapter->hw, PHY_CTRL, mii_reg); ++ iegbe_write_phy_reg(hw, PHY_CTRL, mii_reg); + mdelay(1); + } ++out: ++ return; + } + +-void +-iegbe_reset(struct iegbe_adapter *adapter) ++void iegbe_down(struct iegbe_adapter *adapter) + { +- struct net_device *netdev = adapter->netdev; +- uint32_t pba, manc; +- uint16_t fc_high_water_mark = E1000_FC_HIGH_DIFF; +- uint16_t fc_low_water_mark = E1000_FC_LOW_DIFF; ++ struct net_device *netdev = adapter->netdev; + ++ /* signal that we're down so the interrupt handler does not ++ * reschedule our watchdog timer */ ++ set_bit(__E1000_DOWN, &adapter->flags); + +- /* Repartition Pba for greater than 9k mtu +- * To take effect CTRL.RST is required. +- */ ++ napi_disable(&adapter->napi); + +- switch (adapter->hw.mac_type) { +- case iegbe_82547: +- case iegbe_82547_rev_2: +- pba = E1000_PBA_30K; +- break; +- case iegbe_82571: +- case iegbe_82572: +- pba = E1000_PBA_38K; +- break; +- case iegbe_82573: +- pba = E1000_PBA_12K; ++ iegbe_irq_disable(adapter); ++ ++ del_timer_sync(&adapter->tx_fifo_stall_timer); ++ del_timer_sync(&adapter->watchdog_timer); ++ del_timer_sync(&adapter->phy_info_timer); ++ ++ netdev->tx_queue_len = adapter->tx_queue_len; ++ adapter->link_speed = 0; ++ adapter->link_duplex = 0; ++ netif_carrier_off(netdev); ++ netif_stop_queue(netdev); ++ ++ iegbe_reset(adapter); ++ iegbe_clean_all_tx_rings(adapter); ++ iegbe_clean_all_rx_rings(adapter); ++} ++void iegbe_reinit_locked(struct iegbe_adapter *adapter) ++{ ++ WARN_ON(in_interrupt()); ++ while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) ++ msleep(1); ++ iegbe_down(adapter); ++ iegbe_up(adapter); ++ clear_bit(__E1000_RESETTING, &adapter->flags); ++} ++ ++void iegbe_reset(struct iegbe_adapter *adapter) ++{ ++ struct iegbe_hw *hw = &adapter->hw; ++ u32 pba = 0, tx_space, min_tx_space, min_rx_space; ++ u16 fc_high_water_mark = E1000_FC_HIGH_DIFF; ++ bool legacy_pba_adjust = false; ++ ++ /* Repartition Pba for greater than 9k mtu ++ * To take effect CTRL.RST is required. ++ */ ++ ++ switch (hw->mac_type) { ++ case iegbe_82542_rev2_0: ++ case iegbe_82542_rev2_1: ++ case iegbe_82543: ++ case iegbe_82544: ++ case iegbe_82540: ++ case iegbe_82541: ++ case iegbe_82541_rev_2: ++ case iegbe_icp_xxxx: ++ legacy_pba_adjust = true; ++ pba = E1000_PBA_48K; + break; +- default: ++ case iegbe_82545: ++ case iegbe_82545_rev_3: ++ case iegbe_82546: ++ case iegbe_82546_rev_3: + pba = E1000_PBA_48K; + break; +- } ++ case iegbe_82547: ++ case iegbe_82573: ++ case iegbe_82547_rev_2: ++ legacy_pba_adjust = true; ++ pba = E1000_PBA_30K; ++ break; ++ case iegbe_82571: ++ case iegbe_82572: ++ case iegbe_undefined: ++ case iegbe_num_macs: ++ break; ++ } ++ ++ if (legacy_pba_adjust) { ++ if (adapter->netdev->mtu > E1000_RXBUFFER_8192) ++ pba -= 8; /* allocate more FIFO for Tx */ ++ /* send an XOFF when there is enough space in the ++ * Rx FIFO to hold one extra full size Rx packet ++ */ + +- if((adapter->hw.mac_type != iegbe_82573) && +- (adapter->rx_buffer_len > E1000_RXBUFFER_8192)) { +- pba -= 0x8; /* allocate more FIFO for Tx */ +- /* send an XOFF when there is enough space in the +- * Rx FIFO to hold one extra full size Rx packet +- */ +- fc_high_water_mark = netdev->mtu + ENET_HEADER_SIZE + +- ETHERNET_FCS_SIZE + 0x1; +- fc_low_water_mark = fc_high_water_mark + 0x8; +- } + ++ if (hw->mac_type == iegbe_82547) { ++ adapter->tx_fifo_head = 0; ++ adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT; ++ adapter->tx_fifo_size = ++ (E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT; ++ atomic_set(&adapter->tx_fifo_stall, 0); ++ } ++ } else if (hw->max_frame_size > MAXIMUM_ETHERNET_FRAME_SIZE) { ++ E1000_WRITE_REG(&adapter->hw, PBA, pba); ++ ++ /* To maintain wire speed transmits, the Tx FIFO should be ++ * large enough to accomodate two full transmit packets, ++ * rounded up to the next 1KB and expressed in KB. Likewise, ++ * the Rx FIFO should be large enough to accomodate at least ++ * one full receive packet and is similarly rounded up and ++ * expressed in KB. */ ++ pba = E1000_READ_REG(&adapter->hw, PBA); ++ /* upper 16 bits has Tx packet buffer allocation size in KB */ ++ tx_space = pba >> 16; ++ /* lower 16 bits has Rx packet buffer allocation size in KB */ ++ pba &= 0xffff; ++ /* don't include ethernet FCS because hardware appends/strips */ ++ min_rx_space = adapter->netdev->mtu + ENET_HEADER_SIZE + ++ VLAN_TAG_SIZE; ++ min_tx_space = min_rx_space; ++ min_tx_space *= 2; ++ min_tx_space = ALIGN(min_tx_space, 1024); ++ min_tx_space >>= 10; ++ min_rx_space = ALIGN(min_rx_space, 1024); ++ min_rx_space >>= 10; ++ ++ /* If current Tx allocation is less than the min Tx FIFO size, ++ * and the min Tx FIFO size is less than the current Rx FIFO ++ * allocation, take space away from current Rx allocation */ ++ if (tx_space < min_tx_space && ++ ((min_tx_space - tx_space) < pba)) { ++ pba = pba - (min_tx_space - tx_space); ++ ++ /* PCI/PCIx hardware has PBA alignment constraints */ ++ switch (hw->mac_type) { ++ case iegbe_82545 ... iegbe_82546_rev_3: ++ pba &= ~(E1000_PBA_8K - 1); ++ break; ++ default: ++ break; ++ } + +- if(adapter->hw.mac_type == iegbe_82547) { +- adapter->tx_fifo_head = 0; +- adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT; +- adapter->tx_fifo_size = +- (E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT; +- atomic_set(&adapter->tx_fifo_stall, 0); ++ /* if short on rx space, rx wins and must trump tx ++ * adjustment or use Early Receive if available */ ++ if (pba < min_rx_space) { ++ switch (hw->mac_type) { ++ case iegbe_82573: ++ /* ERT enabled in iegbe_configure_rx */ ++ break; ++ default: ++ pba = min_rx_space; ++ break; ++ } ++ } ++ } + } + + E1000_WRITE_REG(&adapter->hw, PBA, pba); + + /* flow control settings */ +- adapter->hw.fc_high_water = (pba << E1000_PBA_BYTES_SHIFT) - +- fc_high_water_mark; +- adapter->hw.fc_low_water = (pba << E1000_PBA_BYTES_SHIFT) - +- fc_low_water_mark; +- adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME; +- adapter->hw.fc_send_xon = 1; +- adapter->hw.fc = adapter->hw.original_fc; ++ /* Set the FC high water mark to 90% of the FIFO size. ++ * Required to clear last 3 LSB */ ++ fc_high_water_mark = ((pba * 9216)/10) & 0xFFF8; ++ /* We can't use 90% on small FIFOs because the remainder ++ * would be less than 1 full frame. In this case, we size ++ * it to allow at least a full frame above the high water ++ * mark. */ ++ if (pba < E1000_PBA_16K) ++ fc_high_water_mark = (pba * 1024) - 1600; ++ ++ hw->fc_high_water = fc_high_water_mark; ++ hw->fc_low_water = fc_high_water_mark - 8; ++ hw->fc_pause_time = E1000_FC_PAUSE_TIME; ++ hw->fc_send_xon = 1; ++ hw->fc = hw->original_fc; + + /* Allow time for pending master requests to run */ +- iegbe_reset_hw(&adapter->hw); +- if(adapter->hw.mac_type >= iegbe_82544){ ++ iegbe_reset_hw(hw); ++ if (hw->mac_type >= iegbe_82544) + E1000_WRITE_REG(&adapter->hw, WUC, 0); +- } +- if(iegbe_init_hw(&adapter->hw)) { ++ ++ if (iegbe_init_hw(hw)) + DPRINTK(PROBE, ERR, "Hardware Error\n"); +- } +-#ifdef NETIF_F_HW_VLAN_TX + iegbe_update_mng_vlan(adapter); +-#endif ++ ++ /* if (adapter->hwflags & HWFLAGS_PHY_PWR_BIT) { */ ++ if (hw->mac_type >= iegbe_82544 && ++ hw->mac_type <= iegbe_82547_rev_2 && ++ hw->autoneg == 1 && ++ hw->autoneg_advertised == ADVERTISE_1000_FULL) { ++ u32 ctrl = E1000_READ_REG(&adapter->hw, CTRL); ++ /* clear phy power management bit if we are in gig only mode, ++ * which if enabled will attempt negotiation to 100Mb, which ++ * can cause a loss of link at power off or driver unload */ ++ ctrl &= ~E1000_CTRL_SWDPIN3; ++ E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); ++ } ++ + /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ + E1000_WRITE_REG(&adapter->hw, VET, ETHERNET_IEEE_VLAN_TYPE); + +- iegbe_reset_adaptive(&adapter->hw); +- iegbe_phy_get_info(&adapter->hw, &adapter->phy_info); +- if(adapter->en_mng_pt) { +- manc = E1000_READ_REG(&adapter->hw, MANC); +- manc |= (E1000_MANC_ARP_EN | E1000_MANC_EN_MNG2HOST); +- E1000_WRITE_REG(&adapter->hw, MANC, manc); ++ iegbe_reset_adaptive(hw); ++ iegbe_phy_get_info(hw, &adapter->phy_info); ++ ++ if (!adapter->smart_power_down && ++ (hw->mac_type == iegbe_82571 || ++ hw->mac_type == iegbe_82572)) { ++ u16 phy_data = 0; ++ /* speed up time to link by disabling smart power down, ignore ++ * the return value of this function because there is nothing ++ * different we would do if it failed */ ++ iegbe_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, ++ &phy_data); ++ phy_data &= ~IGP02E1000_PM_SPD; ++ iegbe_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, ++ phy_data); ++ } ++ ++} ++ ++/** ++ * Dump the eeprom for users having checksum issues ++ **/ ++static void iegbe_dump_eeprom(struct iegbe_adapter *adapter) ++{ ++ struct net_device *netdev = adapter->netdev; ++ struct ethtool_eeprom eeprom; ++ const struct ethtool_ops *ops = netdev->ethtool_ops; ++ u8 *data; ++ int i; ++ u16 csum_old, csum_new = 0; ++ ++ eeprom.len = ops->get_eeprom_len(netdev); ++ eeprom.offset = 0; ++ ++ data = kmalloc(eeprom.len, GFP_KERNEL); ++ if (!data) { ++ printk(KERN_ERR "Unable to allocate memory to dump EEPROM" ++ " data\n"); ++ return; + } ++ ++ ops->get_eeprom(netdev, &eeprom, data); ++ ++ csum_old = (data[EEPROM_CHECKSUM_REG * 2]) + ++ (data[EEPROM_CHECKSUM_REG * 2 + 1] << 8); ++ for (i = 0; i < EEPROM_CHECKSUM_REG * 2; i += 2) ++ csum_new += data[i] + (data[i + 1] << 8); ++ csum_new = EEPROM_SUM - csum_new; ++ ++ printk(KERN_ERR "/*********************/\n"); ++ printk(KERN_ERR "Current EEPROM Checksum : 0x%04x\n", csum_old); ++ printk(KERN_ERR "Calculated : 0x%04x\n", csum_new); ++ ++ printk(KERN_ERR "Offset Values\n"); ++ printk(KERN_ERR "======== ======\n"); ++ print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 16, 1, data, 128, 0); ++ ++ printk(KERN_ERR "Include this output when contacting your support " ++ "provider.\n"); ++ printk(KERN_ERR "This is not a software error! Something bad " ++ "happened to your hardware or\n"); ++ printk(KERN_ERR "EEPROM image. Ignoring this " ++ "problem could result in further problems,\n"); ++ printk(KERN_ERR "possibly loss of data, corruption or system hangs!\n"); ++ printk(KERN_ERR "The MAC Address will be reset to 00:00:00:00:00:00, " ++ "which is invalid\n"); ++ printk(KERN_ERR "and requires you to set the proper MAC " ++ "address manually before continuing\n"); ++ printk(KERN_ERR "to enable this network device.\n"); ++ printk(KERN_ERR "Please inspect the EEPROM dump and report the issue " ++ "to your hardware vendor\n"); ++ printk(KERN_ERR "or Intel Customer Support.\n"); ++ printk(KERN_ERR "/*********************/\n"); ++ ++ kfree(data); + } + + /** +@@ -721,184 +735,166 @@ iegbe_reset(struct iegbe_adapter *adapte + * The OS initialization, configuring of the adapter private structure, + * and a hardware reset occur. + **/ +- +-static int __devinit +-iegbe_probe(struct pci_dev *pdev, ++static int __devinit iegbe_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) + { +- struct net_device *netdev; +- struct iegbe_adapter *adapter; +- unsigned long mmio_start, mmio_len; +- uint32_t ctrl_ext; +- uint32_t swsm; ++ struct net_device *netdev; ++ struct iegbe_adapter *adapter; ++ struct iegbe_hw *hw; + + static int cards_found = 0; ++ int i, err, pci_using_dac; ++ u16 eeprom_data = 0; ++ u16 eeprom_apme_mask = E1000_EEPROM_APME; ++ int bars; ++ DECLARE_MAC_BUF(mac); + +- int i, err, pci_using_dac; +- uint16_t eeprom_data = 0; +- uint16_t eeprom_apme_mask = E1000_EEPROM_APME; ++ bars = pci_select_bars(pdev, IORESOURCE_MEM); ++ err = pci_enable_device(pdev); + ++ if (err) ++ return err; + +- if((err = pci_enable_device(pdev))) { +- return err; +- } +- if(!(err = pci_set_dma_mask(pdev, PCI_DMA_64BIT))) { ++ if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK) && ++ !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) { + pci_using_dac = 1; +- } else { +- if((err = pci_set_dma_mask(pdev, PCI_DMA_32BIT))) { +- E1000_ERR("No usable DMA configuration, aborting\n"); +- return err; +- } ++ } else { ++ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); ++ if (err) { ++ err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); ++ if (err) { ++ E1000_ERR("No usable DMA configuration, " ++ "aborting\n"); ++ goto err_dma; ++ } ++ } + pci_using_dac = 0; +- } +- +- if((err = pci_request_regions(pdev, iegbe_driver_name))) { +- return err; + } +- pci_set_master(pdev); + +- netdev = alloc_etherdev(sizeof(struct iegbe_adapter)); +- if(!netdev) { +- err = -ENOMEM; +- goto err_alloc_etherdev; +- } ++ err = pci_request_selected_regions(pdev, bars, iegbe_driver_name); ++ if (err) ++ goto err_pci_reg; ++ ++ pci_set_master(pdev); ++ ++ err = -ENOMEM; ++ netdev = alloc_etherdev(sizeof(struct iegbe_adapter)); ++ if (!netdev) ++ goto err_alloc_etherdev; + +- SET_MODULE_OWNER(netdev); + SET_NETDEV_DEV(netdev, &pdev->dev); + +- pci_set_drvdata(pdev, netdev); +- adapter = netdev_priv(netdev); +- adapter->netdev = netdev; +- adapter->pdev = pdev; +- adapter->hw.back = adapter; +- adapter->msg_enable = (0x1 << debug) - 0x1; +- +- mmio_start = pci_resource_start(pdev, BAR_0); +- mmio_len = pci_resource_len(pdev, BAR_0); +- +- adapter->hw.hw_addr = ioremap(mmio_start, mmio_len); +- if(!adapter->hw.hw_addr) { +- err = -EIO; +- goto err_ioremap; +- } +- +- for(i = BAR_1; i <= BAR_5; i++) { +- if(pci_resource_len(pdev, i) == 0) { +- continue; +- } +- if(pci_resource_flags(pdev, i) & IORESOURCE_IO) { +- adapter->hw.io_base = pci_resource_start(pdev, i); +- break; +- } +- } +- +- netdev->open = &iegbe_open; +- netdev->stop = &iegbe_close; +- netdev->hard_start_xmit = &iegbe_xmit_frame; +- netdev->get_stats = &iegbe_get_stats; +- netdev->set_multicast_list = &iegbe_set_multi; ++ pci_set_drvdata(pdev, netdev); ++ adapter = netdev_priv(netdev); ++ adapter->netdev = netdev; ++ adapter->pdev = pdev; ++ adapter->msg_enable = (1 << debug) - 1; ++ adapter->bars = bars; ++ ++ hw = &adapter->hw; ++ hw->back = adapter; ++ ++ err = -EIO; ++ hw->hw_addr = ioremap(pci_resource_start(pdev, BAR_0), ++ pci_resource_len(pdev, BAR_0)); ++ if (!hw->hw_addr) ++ goto err_ioremap; ++ ++ netdev->open = &iegbe_open; ++ netdev->stop = &iegbe_close; ++ netdev->hard_start_xmit = &iegbe_xmit_frame; ++ netdev->get_stats = &iegbe_get_stats; ++ netdev->set_rx_mode = &iegbe_set_rx_mode; + netdev->set_mac_address = &iegbe_set_mac; +- netdev->change_mtu = &iegbe_change_mtu; +- netdev->do_ioctl = &iegbe_ioctl; ++ netdev->change_mtu = &iegbe_change_mtu; ++ netdev->do_ioctl = &iegbe_ioctl; + set_ethtool_ops(netdev); +-#ifdef HAVE_TX_TIMEOUT +- netdev->tx_timeout = &iegbe_tx_timeout; +- netdev->watchdog_timeo = 0x5 * HZ; +-#endif +-#ifdef CONFIG_E1000_NAPI +- netdev->poll = &iegbe_clean; +- netdev->weight = 0x40; +-#endif +-#ifdef NETIF_F_HW_VLAN_TX +- netdev->vlan_rx_register = iegbe_vlan_rx_register; +- netdev->vlan_rx_add_vid = iegbe_vlan_rx_add_vid; +- netdev->vlan_rx_kill_vid = iegbe_vlan_rx_kill_vid; +-#endif ++ netdev->tx_timeout = &iegbe_tx_timeout; ++ netdev->watchdog_timeo = 5 * HZ; ++ netif_napi_add(netdev, &adapter->napi, iegbe_clean, 64); ++ netdev->vlan_rx_register = iegbe_vlan_rx_register; ++ netdev->vlan_rx_add_vid = iegbe_vlan_rx_add_vid; ++ netdev->vlan_rx_kill_vid = iegbe_vlan_rx_kill_vid; + #ifdef CONFIG_NET_POLL_CONTROLLER +- netdev->poll_controller = iegbe_netpoll; ++ netdev->poll_controller = iegbe_netpoll; + #endif +- strcpy(netdev->name, pci_name(pdev)); ++ strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); + +- netdev->mem_start = mmio_start; +- netdev->mem_end = mmio_start + mmio_len; +- netdev->base_addr = adapter->hw.io_base; + +- adapter->bd_number = cards_found; ++ adapter->bd_number = cards_found; + +- /* setup the private structure */ ++ /* setup the private structure */ + +- if((err = iegbe_sw_init(adapter))) { +- goto err_sw_init; +- } +- if((err = iegbe_check_phy_reset_block(&adapter->hw))) { +- DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n"); +- } +-#ifdef MAX_SKB_FRAGS +- if(adapter->hw.mac_type >= iegbe_82543) { +-#ifdef NETIF_F_HW_VLAN_TX +- netdev->features = NETIF_F_SG | +- NETIF_F_HW_CSUM | +- NETIF_F_HW_VLAN_TX | +- NETIF_F_HW_VLAN_RX | +- NETIF_F_HW_VLAN_FILTER; +-#else +- netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM; +-#endif +- } ++ err = iegbe_sw_init(adapter); ++ if (err) ++ goto err_sw_init; ++ err = -EIO; ++ if (iegbe_check_phy_reset_block(hw)) ++ DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n"); + +-#ifdef NETIF_F_TSO +- if((adapter->hw.mac_type >= iegbe_82544) && +- (adapter->hw.mac_type != iegbe_82547)) { +- netdev->features |= NETIF_F_TSO; +- } +-#ifdef NETIF_F_TSO_IPV6 +- if(adapter->hw.mac_type > iegbe_82547_rev_2) { +- netdev->features |= NETIF_F_TSO_IPV6; +- } +-#endif +-#endif +- if(pci_using_dac) { +- netdev->features |= NETIF_F_HIGHDMA; ++ if (hw->mac_type >= iegbe_82543) { ++ netdev->features = NETIF_F_SG | ++ NETIF_F_HW_CSUM | ++ NETIF_F_HW_VLAN_TX | ++ NETIF_F_HW_VLAN_RX | ++ NETIF_F_HW_VLAN_FILTER; + } +-#endif +-#ifdef NETIF_F_LLTX +- netdev->features |= NETIF_F_LLTX; +-#endif + +- adapter->en_mng_pt = iegbe_enable_mng_pass_thru(&adapter->hw); ++ if ((hw->mac_type >= iegbe_82544) && ++ (hw->mac_type != iegbe_82547)) ++ netdev->features |= NETIF_F_TSO; + +- /* before reading the EEPROM, reset the controller to +- * put the device in a known good starting state */ ++ if (hw->mac_type > iegbe_82547_rev_2) ++ netdev->features |= NETIF_F_TSO6; ++ if (pci_using_dac) ++ netdev->features |= NETIF_F_HIGHDMA; ++ ++ netdev->features |= NETIF_F_LLTX; + +- iegbe_reset_hw(&adapter->hw); ++ adapter->en_mng_pt = iegbe_enable_mng_pass_thru(hw); + +- /* make sure the EEPROM is good */ +- if(iegbe_validate_eeprom_checksum(&adapter->hw) < 0) { +- DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n"); +- err = -EIO; ++ /* initialize eeprom parameters */ ++ ++ if (iegbe_init_eeprom_params(hw)) { ++ E1000_ERR("EEPROM initialization failed\n"); + goto err_eeprom; + } + +- /* copy the MAC address out of the EEPROM */ ++ /* before reading the EEPROM, reset the controller to ++ * put the device in a known good starting state */ + +- if(iegbe_read_mac_addr(&adapter->hw)) { +- DPRINTK(PROBE, ERR, "EEPROM Read Error\n"); +- } +- memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); ++ iegbe_reset_hw(hw); + +- if(!is_valid_ether_addr(netdev->dev_addr)) { +- DPRINTK(PROBE, ERR, "Invalid MAC Address\n"); +- err = -EIO; +- goto err_eeprom; +- } ++ /* make sure the EEPROM is good */ ++ if (iegbe_validate_eeprom_checksum(hw) < 0) { ++ DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n"); ++ iegbe_dump_eeprom(adapter); ++ /* ++ * set MAC address to all zeroes to invalidate and temporary ++ * disable this device for the user. This blocks regular ++ * traffic while still permitting ethtool ioctls from reaching ++ * the hardware as well as allowing the user to run the ++ * interface after manually setting a hw addr using ++ * `ip set address` ++ */ ++ memset(hw->mac_addr, 0, netdev->addr_len); ++ } else { ++ /* copy the MAC address out of the EEPROM */ ++ if (iegbe_read_mac_addr(hw)) ++ DPRINTK(PROBE, ERR, "EEPROM Read Error\n"); ++ } ++ /* don't block initalization here due to bad MAC address */ ++ memcpy(netdev->dev_addr, hw->mac_addr, netdev->addr_len); ++ memcpy(netdev->perm_addr, hw->mac_addr, netdev->addr_len); + +- iegbe_read_part_num(&adapter->hw, &(adapter->part_num)); ++ if (!is_valid_ether_addr(netdev->perm_addr)) ++ DPRINTK(PROBE, ERR, "Invalid MAC Address\n"); + +- iegbe_get_bus_info(&adapter->hw); ++ iegbe_get_bus_info(hw); + + init_timer(&adapter->tx_fifo_stall_timer); + adapter->tx_fifo_stall_timer.function = &iegbe_82547_tx_fifo_stall; +- adapter->tx_fifo_stall_timer.data = (unsigned long) adapter; ++ adapter->tx_fifo_stall_timer.data = (unsigned long)adapter; + + init_timer(&adapter->watchdog_timer); + adapter->watchdog_timer.function = &iegbe_watchdog; +@@ -906,75 +902,50 @@ iegbe_probe(struct pci_dev *pdev, + + init_timer(&adapter->phy_info_timer); + adapter->phy_info_timer.function = &iegbe_update_phy_info; +- adapter->phy_info_timer.data = (unsigned long) adapter; +- +- INIT_WORK(&adapter->tx_timeout_task, +- (void (*)(void *))iegbe_tx_timeout_task, netdev); ++ adapter->phy_info_timer.data = (unsigned long)adapter; + +- /* we're going to reset, so assume we have no link for now */ +- +- netif_carrier_off(netdev); +- netif_stop_queue(netdev); ++ INIT_WORK(&adapter->reset_task, iegbe_reset_task); + +- iegbe_check_options(adapter); ++ iegbe_check_options(adapter); + +- /* Initial Wake on LAN setting +- * If APM wake is enabled in the EEPROM, +- * enable the ACPI Magic Packet filter +- */ ++ /* Initial Wake on LAN setting ++ * If APM wake is enabled in the EEPROM, ++ * enable the ACPI Magic Packet filter ++ */ + +- switch(adapter->hw.mac_type) { +- case iegbe_82542_rev2_0: +- case iegbe_82542_rev2_1: +- case iegbe_82543: +- break; +- case iegbe_82544: +- iegbe_read_eeprom(&adapter->hw, +- EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data); +- eeprom_apme_mask = E1000_EEPROM_82544_APM; +- break; ++ switch(adapter->hw.mac_type) { ++ case iegbe_82542_rev2_0: ++ case iegbe_82542_rev2_1: ++ case iegbe_82543: ++ break; ++ case iegbe_82544: ++ iegbe_read_eeprom(&adapter->hw, ++ EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data); ++ eeprom_apme_mask = E1000_EEPROM_82544_APM; ++ break; + case iegbe_icp_xxxx: +- iegbe_read_eeprom(&adapter->hw, +- EEPROM_INIT_CONTROL3_ICP_xxxx(adapter->bd_number), +- 1, &eeprom_data); +- eeprom_apme_mask = EEPROM_CTRL3_APME_ICP_xxxx; +- break; +- case iegbe_82546: +- case iegbe_82546_rev_3: +- if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1) +- && (adapter->hw.media_type == iegbe_media_type_copper)) { +- iegbe_read_eeprom(&adapter->hw, +- EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); +- break; +- } +- /* Fall Through */ +- default: +- iegbe_read_eeprom(&adapter->hw, +- EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); +- break; +- } ++ iegbe_read_eeprom(&adapter->hw, ++ EEPROM_INIT_CONTROL3_ICP_xxxx(adapter->bd_number), ++ 1, &eeprom_data); ++ eeprom_apme_mask = EEPROM_CTRL3_APME_ICP_xxxx; ++ break; ++ case iegbe_82546: ++ case iegbe_82546_rev_3: ++ if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1) ++ && (adapter->hw.media_type == iegbe_media_type_copper)) { ++ iegbe_read_eeprom(&adapter->hw, ++ EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); ++ break; ++ } ++ /* Fall Through */ ++ default: ++ iegbe_read_eeprom(&adapter->hw, ++ EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); ++ break; ++ } + if(eeprom_data & eeprom_apme_mask) { +- adapter->wol |= E1000_WUFC_MAG; ++ adapter->wol |= E1000_WUFC_MAG; + } +- /* reset the hardware with the new settings */ +- iegbe_reset(adapter); +- +- /* Let firmware know the driver has taken over */ +- switch(adapter->hw.mac_type) { +- case iegbe_82571: +- case iegbe_82572: +- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); +- E1000_WRITE_REG(&adapter->hw, CTRL_EXT, +- ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); +- break; +- case iegbe_82573: +- swsm = E1000_READ_REG(&adapter->hw, SWSM); +- E1000_WRITE_REG(&adapter->hw, SWSM, +- swsm | E1000_SWSM_DRV_LOAD); +- break; +- default: +- break; +- } + + /* The ICP_xxxx device has multiple, duplicate interrupt + * registers, so disable all but the first one +@@ -987,24 +958,40 @@ iegbe_probe(struct pci_dev *pdev, + E1000_WRITE_REG(&adapter->hw, IMC2, ~0UL); + } + +- strcpy(netdev->name, "eth%d"); +- if((err = register_netdev(netdev))) { +- goto err_register; +- } ++ iegbe_reset(adapter); ++ netif_carrier_off(netdev); ++ netif_stop_queue(netdev); ++ strcpy(netdev->name, "eth%d"); ++ err = register_netdev(netdev); ++ if (err) ++ goto err_register; ++ + DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n"); + +- cards_found++; +- return 0; ++ cards_found++; ++ return 0; + + err_register: +-err_sw_init: + err_eeprom: +- iounmap(adapter->hw.hw_addr); ++ if (!iegbe_check_phy_reset_block(hw)) ++ iegbe_phy_hw_reset(hw); ++ if (hw->flash_address) ++ iounmap(hw->flash_address); ++ for (i = 0; i < adapter->num_rx_queues; i++) ++ dev_put(&adapter->polling_netdev[i]); ++ kfree(adapter->tx_ring); ++ kfree(adapter->rx_ring); ++ kfree(adapter->polling_netdev); ++err_sw_init: ++ iounmap(hw->hw_addr); + err_ioremap: +- free_netdev(netdev); ++ free_netdev(netdev); + err_alloc_etherdev: +- pci_release_regions(pdev); +- return err; ++ pci_release_selected_regions(pdev, bars); ++err_pci_reg: ++err_dma: ++ pci_disable_device(pdev); ++ return err; + } + + /** +@@ -1020,64 +1007,36 @@ err_alloc_etherdev: + static void __devexit + iegbe_remove(struct pci_dev *pdev) + { +- struct net_device *netdev = pci_get_drvdata(pdev); +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- uint32_t ctrl_ext; +- uint32_t manc, swsm; +-#ifdef CONFIG_E1000_NAPI +- int i; +-#endif +- +- if(adapter->hw.mac_type >= iegbe_82540 +- && adapter->hw.mac_type != iegbe_icp_xxxx +- && adapter->hw.media_type == iegbe_media_type_copper) { +- manc = E1000_READ_REG(&adapter->hw, MANC); +- if(manc & E1000_MANC_SMBUS_EN) { +- manc |= E1000_MANC_ARP_EN; +- E1000_WRITE_REG(&adapter->hw, MANC, manc); +- } +- } +- +- switch(adapter->hw.mac_type) { +- case iegbe_82571: +- case iegbe_82572: +- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); +- E1000_WRITE_REG(&adapter->hw, CTRL_EXT, +- ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); +- break; +- case iegbe_82573: +- swsm = E1000_READ_REG(&adapter->hw, SWSM); +- E1000_WRITE_REG(&adapter->hw, SWSM, +- swsm & ~E1000_SWSM_DRV_LOAD); +- break; +- +- default: +- break; +- } ++ struct net_device *netdev = pci_get_drvdata(pdev); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ uint32_t manc; ++ int i; ++ ++ if(adapter->hw.mac_type >= iegbe_82540 ++ && adapter->hw.mac_type != iegbe_icp_xxxx ++ && adapter->hw.media_type == iegbe_media_type_copper) { ++ manc = E1000_READ_REG(&adapter->hw, MANC); ++ if(manc & E1000_MANC_SMBUS_EN) { ++ manc |= E1000_MANC_ARP_EN; ++ E1000_WRITE_REG(&adapter->hw, MANC, manc); ++ } ++ } + +- unregister_netdev(netdev); +-#ifdef CONFIG_E1000_NAPI +- for (i = 0; i < adapter->num_queues; i++) ++ unregister_netdev(netdev); ++ for (i = 0x0; i < adapter->num_rx_queues; i++) + dev_put(&adapter->polling_netdev[i]); +-#endif + + if(!iegbe_check_phy_reset_block(&adapter->hw)) { +- iegbe_phy_hw_reset(&adapter->hw); ++ iegbe_phy_hw_reset(&adapter->hw); + } +- kfree(adapter->tx_ring); +- kfree(adapter->rx_ring); +-#ifdef CONFIG_E1000_NAPI +- kfree(adapter->polling_netdev); +-#endif ++ kfree(adapter->tx_ring); ++ kfree(adapter->rx_ring); ++ kfree(adapter->polling_netdev); + +- iounmap(adapter->hw.hw_addr); +- pci_release_regions(pdev); ++ iounmap(adapter->hw.hw_addr); ++ pci_release_regions(pdev); + +-#ifdef CONFIG_E1000_MQ +- free_percpu(adapter->cpu_netdev); +- free_percpu(adapter->cpu_tx_ring); +-#endif +- free_netdev(netdev); ++ free_netdev(netdev); + } + + /** +@@ -1092,118 +1051,78 @@ iegbe_remove(struct pci_dev *pdev) + static int __devinit + iegbe_sw_init(struct iegbe_adapter *adapter) + { +- struct iegbe_hw *hw = &adapter->hw; +- struct net_device *netdev = adapter->netdev; +- struct pci_dev *pdev = adapter->pdev; +-#ifdef CONFIG_E1000_NAPI +- int i; +-#endif ++ struct iegbe_hw *hw = &adapter->hw; ++ struct net_device *netdev = adapter->netdev; ++ struct pci_dev *pdev = adapter->pdev; ++ int i; + +- /* PCI config space info */ ++ /* PCI config space info */ + +- hw->vendor_id = pdev->vendor; +- hw->device_id = pdev->device; +- hw->subsystem_vendor_id = pdev->subsystem_vendor; +- hw->subsystem_id = pdev->subsystem_device; ++ hw->vendor_id = pdev->vendor; ++ 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); ++ pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); + +- pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word); ++ pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word); + +- adapter->rx_buffer_len = E1000_RXBUFFER_2048; +- adapter->rx_ps_bsize0 = E1000_RXBUFFER_256; +- hw->max_frame_size = netdev->mtu + +- ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; +- hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE; ++ adapter->rx_buffer_len = E1000_RXBUFFER_2048; ++ adapter->rx_ps_bsize0 = E1000_RXBUFFER_256; ++ hw->max_frame_size = netdev->mtu + ++ ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; ++ hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE; + +- /* identify the MAC */ ++ /* identify the MAC */ + +- if(iegbe_set_mac_type(hw)) { ++ if (iegbe_set_mac_type(hw)) { + DPRINTK(PROBE, ERR, "Unknown MAC Type\n"); + return -EIO; + } + +- /* initialize eeprom parameters */ +- +- if(iegbe_init_eeprom_params(hw)) { +- E1000_ERR("EEPROM initialization failed\n"); +- return -EIO; +- } +- +- switch(hw->mac_type) { +- default: +- break; +- case iegbe_82541: +- case iegbe_82547: +- case iegbe_82541_rev_2: +- case iegbe_82547_rev_2: +- hw->phy_init_script = 0x1; +- break; +- } +- +- iegbe_set_media_type(hw); ++ iegbe_set_media_type(hw); + +- hw->wait_autoneg_complete = FALSE; +- hw->tbi_compatibility_en = TRUE; +- hw->adaptive_ifs = TRUE; ++ hw->wait_autoneg_complete = FALSE; ++ hw->tbi_compatibility_en = TRUE; ++ hw->adaptive_ifs = TRUE; + +- /* Copper options */ ++ /* Copper options */ + +- if(hw->media_type == iegbe_media_type_copper ++ if(hw->media_type == iegbe_media_type_copper + || (hw->media_type == iegbe_media_type_oem + && iegbe_oem_phy_is_copper(&adapter->hw))) { +- hw->mdix = AUTO_ALL_MODES; +- hw->disable_polarity_correction = FALSE; +- hw->master_slave = E1000_MASTER_SLAVE; +- } ++ hw->mdix = AUTO_ALL_MODES; ++ hw->disable_polarity_correction = FALSE; ++ hw->master_slave = E1000_MASTER_SLAVE; ++ } + +-#ifdef CONFIG_E1000_MQ +- /* Number of supported queues */ +- switch (hw->mac_type) { +- case iegbe_82571: +- case iegbe_82572: +- adapter->num_queues = 0x2; +- break; +- default: +- adapter->num_queues = 0x1; +- break; +- } +- adapter->num_queues = min(adapter->num_queues, num_online_cpus()); +-#else +- adapter->num_queues = 0x1; +-#endif ++ adapter->num_tx_queues = 0x1; ++ adapter->num_rx_queues = 0x1; + + if (iegbe_alloc_queues(adapter)) { + DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n"); + return -ENOMEM; + } + +-#ifdef CONFIG_E1000_NAPI +- for (i = 0; i < adapter->num_queues; i++) { ++ for (i = 0; i < adapter->num_rx_queues; i++) { + adapter->polling_netdev[i].priv = adapter; +- adapter->polling_netdev[i].poll = &iegbe_clean; +- adapter->polling_netdev[i].weight = 0x40; + dev_hold(&adapter->polling_netdev[i]); + set_bit(__LINK_STATE_START, &adapter->polling_netdev[i].state); + } +-#endif +- +-#ifdef CONFIG_E1000_MQ +- iegbe_setup_queue_mapping(adapter); +-#endif ++ spin_lock_init(&adapter->tx_queue_lock); + + /* +- * for ICP_XXXX style controllers, it is necessary to keep +- * track of the last known state of the link to determine if +- * the link experienced a change in state when iegbe_watchdog +- * fires +- */ +- adapter->hw.icp_xxxx_is_link_up = FALSE; ++ * for ICP_XXXX style controllers, it is necessary to keep ++ * track of the last known state of the link to determine if ++ * the link experienced a change in state when iegbe_watchdog ++ * fires ++ */ ++ adapter->hw.icp_xxxx_is_link_up = FALSE; + +- atomic_set(&adapter->irq_sem, 1); +- spin_lock_init(&adapter->stats_lock); ++ spin_lock_init(&adapter->stats_lock); + +- return 0; ++ set_bit(__E1000_DOWN, &adapter->flags); ++ return 0x0; + } + + /** +@@ -1218,71 +1137,31 @@ iegbe_sw_init(struct iegbe_adapter *adap + static int __devinit + iegbe_alloc_queues(struct iegbe_adapter *adapter) + { +- int size; + +- size = sizeof(struct iegbe_tx_ring) * adapter->num_queues; +- adapter->tx_ring = kmalloc(size, GFP_KERNEL); +- if (!adapter->tx_ring){ ++ ++ adapter->tx_ring = kcalloc(adapter->num_tx_queues, ++ sizeof(struct iegbe_tx_ring), GFP_KERNEL); ++ if (!adapter->tx_ring) + return -ENOMEM; +- } +- memset(adapter->tx_ring, 0, size); + +- size = sizeof(struct iegbe_rx_ring) * adapter->num_queues; +- adapter->rx_ring = kmalloc(size, GFP_KERNEL); ++ adapter->rx_ring = kcalloc(adapter->num_rx_queues, ++ sizeof(struct iegbe_rx_ring), GFP_KERNEL); + if (!adapter->rx_ring) { + kfree(adapter->tx_ring); + return -ENOMEM; + } +- memset(adapter->rx_ring, 0, size); + +-#ifdef CONFIG_E1000_NAPI +- size = sizeof(struct net_device) * adapter->num_queues; +- adapter->polling_netdev = kmalloc(size, GFP_KERNEL); ++ adapter->polling_netdev = kcalloc(adapter->num_rx_queues, ++ sizeof(struct net_device), ++ GFP_KERNEL); + if (!adapter->polling_netdev) { + kfree(adapter->tx_ring); + kfree(adapter->rx_ring); + return -ENOMEM; + } +- memset(adapter->polling_netdev, 0, size); +-#endif +- +- return E1000_SUCCESS; +-} + +-#ifdef CONFIG_E1000_MQ +-static void __devinit +-iegbe_setup_queue_mapping(struct iegbe_adapter *adapter) +-{ +- int i, cpu; +- +- adapter->rx_sched_call_data.func = iegbe_rx_schedule; +- adapter->rx_sched_call_data.info = adapter->netdev; +- cpus_clear(adapter->rx_sched_call_data.cpumask); +- +- adapter->cpu_netdev = alloc_percpu(struct net_device *); +- adapter->cpu_tx_ring = alloc_percpu(struct iegbe_tx_ring *); +- +- lock_cpu_hotplug(); +- i = 0; +- for_each_online_cpu(cpu) { +- *per_cpu_ptr(adapter->cpu_tx_ring, cpu) = +- &adapter->tx_ring[i % adapter->num_queues]; +- /* This is incomplete because we'd like to assign separate +- * physical cpus to these netdev polling structures and +- * avoid saturating a subset of cpus. +- */ +- if (i < adapter->num_queues) { +- *per_cpu_ptr(adapter->cpu_netdev, cpu) = +- &adapter->polling_netdev[i]; +- adapter->cpu_for_queue[i] = cpu; +- } else { +- *per_cpu_ptr(adapter->cpu_netdev, cpu) = NULL; +- } +- i++; +- } +- unlock_cpu_hotplug(); ++ return E1000_SUCCESS; + } +-#endif + + /** + * iegbe_open - Called when a network interface is made active +@@ -1300,40 +1179,62 @@ iegbe_setup_queue_mapping(struct iegbe_a + static int + iegbe_open(struct net_device *netdev) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- int err; ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_hw *hw = &adapter->hw; ++ int err; ++ + ++ /* allocate receive descriptors */ ++ if (test_bit(__E1000_TESTING, &adapter->flags)) ++ return -EBUSY; + +- /* allocate receive descriptors */ ++ /* allocate transmit descriptors */ ++ err = iegbe_setup_all_tx_resources(adapter); ++ if (err) ++ goto err_setup_tx; + +- if ((err = iegbe_setup_all_rx_resources(adapter))) { ++ err = iegbe_setup_all_rx_resources(adapter); ++ if (err) + goto err_setup_rx; +- } +- /* allocate transmit descriptors */ +- if ((err = iegbe_setup_all_tx_resources(adapter))) { +- goto err_setup_tx; +- } +- if ((err = iegbe_up(adapter))) { +- goto err_up; +- } +-#ifdef NETIF_F_HW_VLAN_TX +- adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; +- if ((adapter->hw.mng_cookie.status & +- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) { +- iegbe_update_mng_vlan(adapter); +- } +-#endif + +- return E1000_SUCCESS; ++ iegbe_power_up_phy(adapter); ++ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; ++ if ((hw->mng_cookie.status & ++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) { ++ iegbe_update_mng_vlan(adapter); ++ } ++ ++ /* before we allocate an interrupt, we must be ready to handle it. ++ * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt ++ * as soon as we call pci_request_irq, so we have to setup our ++ * clean_rx handler before we do so. */ ++ iegbe_configure(adapter); ++ err = iegbe_request_irq(adapter); ++ if (err) ++ goto err_req_irq; + +-err_up: +- iegbe_free_all_tx_resources(adapter); +-err_setup_tx: +- iegbe_free_all_rx_resources(adapter); ++ /* From here on the code is the same as iegbe_up() */ ++ clear_bit(__E1000_DOWN, &adapter->flags); ++ ++ napi_enable(&adapter->napi); ++ ++ iegbe_irq_enable(adapter); ++ ++ netif_start_queue(netdev); ++ ++ /* fire a link status change interrupt to start the watchdog */ ++ ++ return E1000_SUCCESS; ++ ++err_req_irq: ++ iegbe_power_down_phy(adapter); ++ iegbe_free_all_rx_resources(adapter); + err_setup_rx: +- iegbe_reset(adapter); ++ iegbe_free_all_tx_resources(adapter); ++err_setup_tx: ++ iegbe_reset(adapter); + +- return err; ++ return err; + } + + /** +@@ -1348,22 +1249,25 @@ err_setup_rx: + * hardware, and all transmit and receive resources are freed. + **/ + +-static int +-iegbe_close(struct net_device *netdev) ++static int iegbe_close(struct net_device *netdev) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- +- iegbe_down(adapter); +- +- iegbe_free_all_tx_resources(adapter); +- iegbe_free_all_rx_resources(adapter); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_hw *hw = &adapter->hw; + +-#ifdef NETIF_F_HW_VLAN_TX +- if((adapter->hw.mng_cookie.status & +- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) { ++ WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags)); ++ iegbe_down(adapter); ++ iegbe_power_down_phy(adapter); ++ iegbe_free_irq(adapter); ++ ++ iegbe_free_all_tx_resources(adapter); ++ iegbe_free_all_rx_resources(adapter); ++ ++ if ((hw->mng_cookie.status & ++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && ++ !(adapter->vlgrp && ++ vlan_group_get_device(adapter->vlgrp, adapter->mng_vlan_id))) { + iegbe_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); + } +-#endif + return 0; + } + +@@ -1375,19 +1279,19 @@ iegbe_close(struct net_device *netdev) + **/ + static inline boolean_t + iegbe_check_64k_bound(struct iegbe_adapter *adapter, +- void *start, unsigned long len) ++ void *start, unsigned long len) + { +- unsigned long begin = (unsigned long) start; +- unsigned long end = begin + len; ++ unsigned long begin = (unsigned long) start; ++ unsigned long end = begin + len; + +- /* First rev 82545 and 82546 need to not allow any memory +- * write location to cross 64k boundary due to errata 23 */ +- if(adapter->hw.mac_type == iegbe_82545 || +- adapter->hw.mac_type == iegbe_82546) { +- return ((begin ^ (end - 1)) >> 0x10) != 0 ? FALSE : TRUE; +- } ++ /* First rev 82545 and 82546 need to not allow any memory ++ * write location to cross 64k boundary due to errata 23 */ ++ if(adapter->hw.mac_type == iegbe_82545 || ++ adapter->hw.mac_type == iegbe_82546) { ++ return ((begin ^ (end - 1)) >> 0x10) != 0x0 ? FALSE : TRUE; ++ } + +- return TRUE; ++ return TRUE; + } + + /** +@@ -1398,102 +1302,98 @@ iegbe_check_64k_bound(struct iegbe_adapt + * Return 0 on success, negative on failure + **/ + +-int +-iegbe_setup_tx_resources(struct iegbe_adapter *adapter, ++static int iegbe_setup_tx_resources(struct iegbe_adapter *adapter, + struct iegbe_tx_ring *txdr) + { +- struct pci_dev *pdev = adapter->pdev; +- int size; ++ struct pci_dev *pdev = adapter->pdev; ++ int size; + +- size = sizeof(struct iegbe_buffer) * txdr->count; +- txdr->buffer_info = vmalloc(size); +- if (!txdr->buffer_info) { +- DPRINTK(PROBE, ERR, +- "Unable to allocate memory for the transmit descriptor ring\n"); +- return -ENOMEM; +- } ++ size = sizeof(struct iegbe_buffer) * txdr->count; ++ txdr->buffer_info = vmalloc(size); ++ if (!txdr->buffer_info) { ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate memory for the transmit descriptor ring\n"); ++ return -ENOMEM; ++ } + memset(txdr->buffer_info, 0, size); +- memset(&txdr->previous_buffer_info, 0, sizeof(struct iegbe_buffer)); + +- /* round up to nearest 4K */ ++ /* round up to nearest 4K */ + +- txdr->size = txdr->count * sizeof(struct iegbe_tx_desc); +- E1000_ROUNDUP(txdr->size, 0x1000); ++ txdr->size = txdr->count * sizeof(struct iegbe_tx_desc); ++ txdr->size = ALIGN(txdr->size, 4096); + +- txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); +- if (!txdr->desc) { ++ txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); ++ if (!txdr->desc) { + setup_tx_desc_die: +- vfree(txdr->buffer_info); +- DPRINTK(PROBE, ERR, +- "Unable to allocate memory for the transmit descriptor ring\n"); +- return -ENOMEM; +- } +- +- /* Fix for errata 23, can't cross 64kB boundary */ +- if (!iegbe_check_64k_bound(adapter, txdr->desc, txdr->size)) { +- void *olddesc = txdr->desc; +- dma_addr_t olddma = txdr->dma; +- DPRINTK(TX_ERR, ERR, "txdr align check failed: %u bytes " +- "at %p\n", txdr->size, txdr->desc); +- /* Try again, without freeing the previous */ +- txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); +- /* Failed allocation, critical failure */ +- if (!txdr->desc) { +- pci_free_consistent(pdev, txdr->size, olddesc, olddma); +- goto setup_tx_desc_die; +- } ++ vfree(txdr->buffer_info); ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate memory for the transmit descriptor ring\n"); ++ return -ENOMEM; ++ } ++ ++ /* Fix for errata 23, can't cross 64kB boundary */ ++ if (!iegbe_check_64k_bound(adapter, txdr->desc, txdr->size)) { ++ void *olddesc = txdr->desc; ++ dma_addr_t olddma = txdr->dma; ++ DPRINTK(TX_ERR, ERR, "txdr align check failed: %u bytes " ++ "at %p\n", txdr->size, txdr->desc); ++ /* Try again, without freeing the previous */ ++ txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); ++ /* Failed allocation, critical failure */ ++ if (!txdr->desc) { ++ pci_free_consistent(pdev, txdr->size, olddesc, olddma); ++ goto setup_tx_desc_die; ++ } + +- if (!iegbe_check_64k_bound(adapter, txdr->desc, txdr->size)) { +- /* give up */ +- pci_free_consistent(pdev, txdr->size, txdr->desc, +- txdr->dma); +- pci_free_consistent(pdev, txdr->size, olddesc, olddma); +- DPRINTK(PROBE, ERR, +- "Unable to allocate aligned memory " +- "for the transmit descriptor ring\n"); +- vfree(txdr->buffer_info); +- return -ENOMEM; +- } else { +- /* Free old allocation, new allocation was successful */ +- pci_free_consistent(pdev, txdr->size, olddesc, olddma); +- } +- } ++ if (!iegbe_check_64k_bound(adapter, txdr->desc, txdr->size)) { ++ /* give up */ ++ pci_free_consistent(pdev, txdr->size, txdr->desc, ++ txdr->dma); ++ pci_free_consistent(pdev, txdr->size, olddesc, olddma); ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate aligned memory " ++ "for the transmit descriptor ring\n"); ++ vfree(txdr->buffer_info); ++ return -ENOMEM; ++ } else { ++ /* Free old allocation, new allocation was successful */ ++ pci_free_consistent(pdev, txdr->size, olddesc, olddma); ++ } ++ } + memset(txdr->desc, 0, txdr->size); + + txdr->next_to_use = 0; + txdr->next_to_clean = 0; +- spin_lock_init(&txdr->tx_lock); ++ spin_lock_init(&txdr->tx_lock); + + return 0; + } + + /** + * iegbe_setup_all_tx_resources - wrapper to allocate Tx resources +- * (Descriptors) for all queues ++ * (Descriptors) for all queues + * @adapter: board private structure + * +- * If this function returns with an error, then it's possible one or +- * more of the rings is populated (while the rest are not). It is the +- * callers duty to clean those orphaned rings. +- * + * Return 0 on success, negative on failure + **/ + +-int +-iegbe_setup_all_tx_resources(struct iegbe_adapter *adapter) ++int iegbe_setup_all_tx_resources(struct iegbe_adapter *adapter) + { + int i, err = 0; + +- for (i = 0; i < adapter->num_queues; i++) { ++ for (i = 0; i < adapter->num_tx_queues; i++) { + err = iegbe_setup_tx_resources(adapter, &adapter->tx_ring[i]); + if (err) { + DPRINTK(PROBE, ERR, + "Allocation for Tx Queue %u failed\n", i); ++ for (i-- ; i >= 0; i--) ++ iegbe_free_tx_resources(adapter, ++ &adapter->tx_ring[i]); + break; + } + } + +- return err; ++ return err; + } + + /** +@@ -1512,113 +1412,108 @@ iegbe_configure_tx(struct iegbe_adapter + + /* Setup the HW Tx Head and Tail descriptor pointers */ + +- switch (adapter->num_queues) { ++ switch (adapter->num_tx_queues) { + case 0x2: + tdba = adapter->tx_ring[0x1].dma; + tdlen = adapter->tx_ring[0x1].count * +- sizeof(struct iegbe_tx_desc); +- E1000_WRITE_REG(hw, TDBAL1, (tdba & 0x00000000ffffffffULL)); ++ sizeof(struct iegbe_tx_desc); ++ E1000_WRITE_REG(hw, TDBAL1, (tdba & 0x00000000ffffffffULL)); + E1000_WRITE_REG(hw, TDBAH1, (tdba >> 0x20)); +- E1000_WRITE_REG(hw, TDLEN1, tdlen); +- E1000_WRITE_REG(hw, TDH1, 0); +- E1000_WRITE_REG(hw, TDT1, 0); ++ E1000_WRITE_REG(hw, TDLEN1, tdlen); ++ E1000_WRITE_REG(hw, TDH1, 0x0); ++ E1000_WRITE_REG(hw, TDT1, 0x0); + adapter->tx_ring[0x1].tdh = E1000_TDH1; + adapter->tx_ring[0x1].tdt = E1000_TDT1; +- /* Fall Through */ ++ /* Fall Through */ + case 0x1: +- default: +- tdba = adapter->tx_ring[0].dma; +- tdlen = adapter->tx_ring[0].count * +- sizeof(struct iegbe_tx_desc); +- E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL)); ++ default: ++ tdba = adapter->tx_ring[0x0].dma; ++ tdlen = adapter->tx_ring[0x0].count * ++ sizeof(struct iegbe_tx_desc); ++ E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL)); + E1000_WRITE_REG(hw, TDBAH, (tdba >> 0x20)); +- E1000_WRITE_REG(hw, TDLEN, tdlen); +- E1000_WRITE_REG(hw, TDH, 0); +- E1000_WRITE_REG(hw, TDT, 0); +- adapter->tx_ring[0].tdh = E1000_TDH; +- adapter->tx_ring[0].tdt = E1000_TDT; +- break; +- } +- +- /* Set the default values for the Tx Inter Packet Gap timer */ +- +- switch (hw->mac_type) { +- case iegbe_82542_rev2_0: +- case iegbe_82542_rev2_1: +- tipg = DEFAULT_82542_TIPG_IPGT; +- tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; +- tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; +- break; +- default: +- switch(hw->media_type) { +- case iegbe_media_type_fiber: +- case iegbe_media_type_internal_serdes: +- tipg = DEFAULT_82543_TIPG_IPGT_FIBER; +- break; +- case iegbe_media_type_copper: +- tipg = DEFAULT_82543_TIPG_IPGT_COPPER; +- break; +- case iegbe_media_type_oem: +- default: ++ E1000_WRITE_REG(hw, TDLEN, tdlen); ++ E1000_WRITE_REG(hw, TDH, 0x0); ++ E1000_WRITE_REG(hw, TDT, 0x0); ++ adapter->tx_ring[0x0].tdh = E1000_TDH; ++ adapter->tx_ring[0x0].tdt = E1000_TDT; ++ break; ++ } ++ ++ /* Set the default values for the Tx Inter Packet Gap timer */ ++ ++ switch (hw->mac_type) { ++ case iegbe_82542_rev2_0: ++ case iegbe_82542_rev2_1: ++ tipg = DEFAULT_82542_TIPG_IPGT; ++ tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; ++ tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; ++ break; ++ default: ++ switch(hw->media_type) { ++ case iegbe_media_type_fiber: ++ case iegbe_media_type_internal_serdes: ++ tipg = DEFAULT_82543_TIPG_IPGT_FIBER; ++ break; ++ case iegbe_media_type_copper: ++ tipg = DEFAULT_82543_TIPG_IPGT_COPPER; ++ break; ++ case iegbe_media_type_oem: ++ default: + tipg = (0xFFFFFFFFUL >> (sizeof(tipg)*0x8 - + E1000_TIPG_IPGR1_SHIFT)) +- & iegbe_oem_get_tipg(&adapter->hw); +- break; +- } +- tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; +- tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; +- } +- E1000_WRITE_REG(hw, TIPG, tipg); ++ & iegbe_oem_get_tipg(&adapter->hw); ++ break; ++ } ++ tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; ++ tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; ++ } ++ E1000_WRITE_REG(hw, TIPG, tipg); + +- /* Set the Tx Interrupt Delay register */ ++ /* Set the Tx Interrupt Delay register */ + +- E1000_WRITE_REG(hw, TIDV, adapter->tx_int_delay); ++ E1000_WRITE_REG(hw, TIDV, adapter->tx_int_delay); + if (hw->mac_type >= iegbe_82540) { +- E1000_WRITE_REG(hw, TADV, adapter->tx_abs_int_delay); ++ E1000_WRITE_REG(hw, TADV, adapter->tx_abs_int_delay); + } +- /* Program the Transmit Control Register */ ++ /* Program the Transmit Control Register */ + +- tctl = E1000_READ_REG(hw, TCTL); ++ tctl = E1000_READ_REG(hw, TCTL); + +- tctl &= ~E1000_TCTL_CT; +- tctl |= E1000_TCTL_EN | E1000_TCTL_PSP | E1000_TCTL_RTLC | +- (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); ++ tctl &= ~E1000_TCTL_CT; ++ tctl |= E1000_TCTL_EN | E1000_TCTL_PSP | E1000_TCTL_RTLC | ++ (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); + +- E1000_WRITE_REG(hw, TCTL, tctl); ++ E1000_WRITE_REG(hw, TCTL, tctl); + +- if (hw->mac_type == iegbe_82571 || hw->mac_type == iegbe_82572) { +- tarc = E1000_READ_REG(hw, TARC0); ++ if (hw->mac_type == iegbe_82571 || hw->mac_type == iegbe_82572) { ++ tarc = E1000_READ_REG(hw, TARC0); + tarc |= ((0x1 << 0x19) | (0x1 << 0x15)); +- E1000_WRITE_REG(hw, TARC0, tarc); +- tarc = E1000_READ_REG(hw, TARC1); ++ E1000_WRITE_REG(hw, TARC0, tarc); ++ tarc = E1000_READ_REG(hw, TARC1); + tarc |= (0x1 << 0x19); + if (tctl & E1000_TCTL_MULR) { + tarc &= ~(0x1 << 0x1c); + } else { + tarc |= (0x1 << 0x1c); + } +- E1000_WRITE_REG(hw, TARC1, tarc); +- } ++ E1000_WRITE_REG(hw, TARC1, tarc); ++ } + +- iegbe_config_collision_dist(hw); ++ iegbe_config_collision_dist(hw); + +- /* Setup Transmit Descriptor Settings for eop descriptor */ +- adapter->txd_cmd = E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP | +- E1000_TXD_CMD_IFCS; ++ /* Setup Transmit Descriptor Settings for eop descriptor */ ++ adapter->txd_cmd = E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP | ++ E1000_TXD_CMD_IFCS; + + if (hw->mac_type < iegbe_82543) { +- adapter->txd_cmd |= E1000_TXD_CMD_RPS; ++ adapter->txd_cmd |= E1000_TXD_CMD_RPS; + } else { +-#ifdef IEGBE_GBE_WORKAROUND +- /* Disable the RS bit in the Tx descriptor */ +- adapter->txd_cmd &= ~E1000_TXD_CMD_RS; +-#else +- adapter->txd_cmd |= E1000_TXD_CMD_RS; +-#endif ++ adapter->txd_cmd |= E1000_TXD_CMD_RS; + } +- /* Cache if we're 82544 running in PCI-X because we'll +- * need this to apply a workaround later in the send path. */ +- if (hw->mac_type == iegbe_82544 && ++ /* Cache if we're 82544 running in PCI-X because we'll ++ * need this to apply a workaround later in the send path. */ ++ if (hw->mac_type == iegbe_82544 && + hw->bus_type == iegbe_bus_type_pcix) { + adapter->pcix_82544 = 0x1; + } +@@ -1632,96 +1527,95 @@ iegbe_configure_tx(struct iegbe_adapter + * Returns 0 on success, negative on failure + **/ + +-int +-iegbe_setup_rx_resources(struct iegbe_adapter *adapter, ++static int iegbe_setup_rx_resources(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rxdr) + { +- struct pci_dev *pdev = adapter->pdev; +- int size, desc_len; +- +- size = sizeof(struct iegbe_buffer) * rxdr->count; +- rxdr->buffer_info = vmalloc(size); +- if (!rxdr->buffer_info) { +- DPRINTK(PROBE, ERR, +- "Unable to allocate memory for the receive descriptor ring\n"); +- return -ENOMEM; +- } +- memset(rxdr->buffer_info, 0, size); +- +- size = sizeof(struct iegbe_ps_page) * rxdr->count; +- rxdr->ps_page = kmalloc(size, GFP_KERNEL); +- if (!rxdr->ps_page) { +- vfree(rxdr->buffer_info); +- DPRINTK(PROBE, ERR, +- "Unable to allocate memory for the receive descriptor ring\n"); +- return -ENOMEM; +- } +- memset(rxdr->ps_page, 0, size); +- +- size = sizeof(struct iegbe_ps_page_dma) * rxdr->count; +- rxdr->ps_page_dma = kmalloc(size, GFP_KERNEL); +- if (!rxdr->ps_page_dma) { +- vfree(rxdr->buffer_info); +- kfree(rxdr->ps_page); +- DPRINTK(PROBE, ERR, +- "Unable to allocate memory for the receive descriptor ring\n"); +- return -ENOMEM; +- } +- memset(rxdr->ps_page_dma, 0, size); ++ struct iegbe_hw *hw = &adapter->hw; ++ struct pci_dev *pdev = adapter->pdev; ++ int size, desc_len; + +- if (adapter->hw.mac_type <= iegbe_82547_rev_2) { +- desc_len = sizeof(struct iegbe_rx_desc); +- } else { +- desc_len = sizeof(union iegbe_rx_desc_packet_split); ++ size = sizeof(struct iegbe_buffer) * rxdr->count; ++ rxdr->buffer_info = vmalloc(size); ++ if (!rxdr->buffer_info) { ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate memory for the receive descriptor ring\n"); ++ return -ENOMEM; + } +- /* Round up to nearest 4K */ +- +- rxdr->size = rxdr->count * desc_len; +- E1000_ROUNDUP(rxdr->size, 0x1000); +- +- rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma); ++ memset(rxdr->buffer_info, 0, size); + +- if (!rxdr->desc) { +- DPRINTK(PROBE, ERR, +- "Unable to allocate memory for the receive descriptor ring\n"); ++ rxdr->ps_page = kcalloc(rxdr->count, sizeof(struct iegbe_ps_page), ++ GFP_KERNEL); ++ if (!rxdr->ps_page) { ++ vfree(rxdr->buffer_info); ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate memory for the receive descriptor ring\n"); ++ return -ENOMEM; ++ } ++ ++ rxdr->ps_page_dma = kcalloc(rxdr->count, ++ sizeof(struct iegbe_ps_page_dma), ++ GFP_KERNEL); ++ if (!rxdr->ps_page_dma) { ++ vfree(rxdr->buffer_info); ++ kfree(rxdr->ps_page); ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate memory for the receive descriptor ring\n"); ++ return -ENOMEM; ++ } ++ ++ if (hw->mac_type <= iegbe_82547_rev_2) ++ desc_len = sizeof(struct iegbe_rx_desc); ++ else ++ desc_len = sizeof(union iegbe_rx_desc_packet_split); ++ ++ /* Round up to nearest 4K */ ++ ++ rxdr->size = rxdr->count * desc_len; ++ rxdr->size = ALIGN(rxdr->size, 4096); ++ ++ rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma); ++ ++ if (!rxdr->desc) { ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate memory for the receive descriptor ring\n"); + setup_rx_desc_die: +- vfree(rxdr->buffer_info); +- kfree(rxdr->ps_page); +- kfree(rxdr->ps_page_dma); +- return -ENOMEM; +- } +- +- /* Fix for errata 23, can't cross 64kB boundary */ +- if (!iegbe_check_64k_bound(adapter, rxdr->desc, rxdr->size)) { +- void *olddesc = rxdr->desc; +- dma_addr_t olddma = rxdr->dma; +- DPRINTK(RX_ERR, ERR, "rxdr align check failed: %u bytes " +- "at %p\n", rxdr->size, rxdr->desc); +- /* Try again, without freeing the previous */ +- rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma); +- /* Failed allocation, critical failure */ +- if (!rxdr->desc) { +- pci_free_consistent(pdev, rxdr->size, olddesc, olddma); +- DPRINTK(PROBE, ERR, +- "Unable to allocate memory " +- "for the receive descriptor ring\n"); +- goto setup_rx_desc_die; +- } ++ vfree(rxdr->buffer_info); ++ kfree(rxdr->ps_page); ++ kfree(rxdr->ps_page_dma); ++ return -ENOMEM; ++ } ++ ++ /* Fix for errata 23, can't cross 64kB boundary */ ++ if (!iegbe_check_64k_bound(adapter, rxdr->desc, rxdr->size)) { ++ void *olddesc = rxdr->desc; ++ dma_addr_t olddma = rxdr->dma; ++ DPRINTK(RX_ERR, ERR, "rxdr align check failed: %u bytes " ++ "at %p\n", rxdr->size, rxdr->desc); ++ /* Try again, without freeing the previous */ ++ rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma); ++ /* Failed allocation, critical failure */ ++ if (!rxdr->desc) { ++ pci_free_consistent(pdev, rxdr->size, olddesc, olddma); ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate memory " ++ "for the receive descriptor ring\n"); ++ goto setup_rx_desc_die; ++ } + +- if (!iegbe_check_64k_bound(adapter, rxdr->desc, rxdr->size)) { +- /* give up */ +- pci_free_consistent(pdev, rxdr->size, rxdr->desc, +- rxdr->dma); +- pci_free_consistent(pdev, rxdr->size, olddesc, olddma); +- DPRINTK(PROBE, ERR, +- "Unable to allocate aligned memory " +- "for the receive descriptor ring\n"); +- goto setup_rx_desc_die; +- } else { +- /* Free old allocation, new allocation was successful */ +- pci_free_consistent(pdev, rxdr->size, olddesc, olddma); +- } +- } ++ if (!iegbe_check_64k_bound(adapter, rxdr->desc, rxdr->size)) { ++ /* give up */ ++ pci_free_consistent(pdev, rxdr->size, rxdr->desc, ++ rxdr->dma); ++ pci_free_consistent(pdev, rxdr->size, olddesc, olddma); ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate aligned memory " ++ "for the receive descriptor ring\n"); ++ goto setup_rx_desc_die; ++ } else { ++ /* Free old allocation, new allocation was successful */ ++ pci_free_consistent(pdev, rxdr->size, olddesc, olddma); ++ } ++ } + memset(rxdr->desc, 0, rxdr->size); + + rxdr->next_to_clean = 0; +@@ -1732,7 +1626,7 @@ setup_rx_desc_die: + + /** + * iegbe_setup_all_rx_resources - wrapper to allocate Rx resources +- * (Descriptors) for all queues ++ * (Descriptors) for all queues + * @adapter: board private structure + * + * If this function returns with an error, then it's possible one or +@@ -1742,21 +1636,23 @@ setup_rx_desc_die: + * Return 0 on success, negative on failure + **/ + +-int +-iegbe_setup_all_rx_resources(struct iegbe_adapter *adapter) ++int iegbe_setup_all_rx_resources(struct iegbe_adapter *adapter) + { + int i, err = 0; + +- for (i = 0; i < adapter->num_queues; i++) { ++ for (i = 0; i < adapter->num_rx_queues; i++) { + err = iegbe_setup_rx_resources(adapter, &adapter->rx_ring[i]); + if (err) { + DPRINTK(PROBE, ERR, + "Allocation for Rx Queue %u failed\n", i); ++ for (i-- ; i >= 0; i--) ++ iegbe_free_rx_resources(adapter, ++ &adapter->rx_ring[i]); + break; + } + } + +- return err; ++ return err; + } + + /** +@@ -1765,105 +1661,104 @@ iegbe_setup_all_rx_resources(struct iegb + **/ + #define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \ + (((S) & (PAGE_SIZE - 1)) ? 1 : 0)) +-static void +-iegbe_setup_rctl(struct iegbe_adapter *adapter) ++static void iegbe_setup_rctl(struct iegbe_adapter *adapter) + { +- uint32_t rctl, rfctl; +- uint32_t psrctl = 0; +-#ifdef CONFIG_E1000_PACKET_SPLIT +- uint32_t pages = 0; +-#endif +- +- rctl = E1000_READ_REG(&adapter->hw, RCTL); +- +- rctl &= ~(0x3 << E1000_RCTL_MO_SHIFT); +- +- rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | +- E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | +- (adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT); +- +- if(adapter->hw.tbi_compatibility_on == 0x1) { +- rctl |= E1000_RCTL_SBP; +- } else { +- rctl &= ~E1000_RCTL_SBP; +- } +- if(adapter->netdev->mtu <= ETH_DATA_LEN) { +- rctl &= ~E1000_RCTL_LPE; +- } else { +- rctl |= E1000_RCTL_LPE; +- } +- /* Setup buffer sizes */ +- if(adapter->hw.mac_type >= iegbe_82571) { +- /* We can now specify buffers in 1K increments. +- * BSIZE and BSEX are ignored in this case. */ +- rctl |= adapter->rx_buffer_len << 0x11; +- } else { +- rctl &= ~E1000_RCTL_SZ_4096; +- rctl |= E1000_RCTL_BSEX; +- switch (adapter->rx_buffer_len) { +- case E1000_RXBUFFER_2048: +- default: +- rctl |= E1000_RCTL_SZ_2048; ++ struct iegbe_hw *hw = &adapter->hw; ++ u32 rctl, rfctl; ++ u32 psrctl = 0; ++#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT ++ u32 pages = 0; ++#endif ++ ++ rctl = E1000_READ_REG(&adapter->hw, RCTL); ++ ++ rctl &= ~(3 << E1000_RCTL_MO_SHIFT); ++ ++ rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | ++ E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | ++ (hw->mc_filter_type << E1000_RCTL_MO_SHIFT); ++ ++ if (hw->tbi_compatibility_on == 1) ++ rctl |= E1000_RCTL_SBP; ++ else ++ rctl &= ~E1000_RCTL_SBP; ++ ++ if (adapter->netdev->mtu <= ETH_DATA_LEN) ++ rctl &= ~E1000_RCTL_LPE; ++ else ++ rctl |= E1000_RCTL_LPE; ++ ++ /* Setup buffer sizes */ ++ /* We can now specify buffers in 1K increments. ++ * BSIZE and BSEX are ignored in this case. */ ++ rctl &= ~E1000_RCTL_SZ_4096; ++ rctl |= E1000_RCTL_BSEX; ++ switch (adapter->rx_buffer_len) { ++ case E1000_RXBUFFER_256: ++ rctl |= E1000_RCTL_SZ_256; + rctl &= ~E1000_RCTL_BSEX; + break; +- case E1000_RXBUFFER_4096: +- rctl |= E1000_RCTL_SZ_4096; +- break; +- case E1000_RXBUFFER_8192: +- rctl |= E1000_RCTL_SZ_8192; +- break; +- case E1000_RXBUFFER_16384: +- rctl |= E1000_RCTL_SZ_16384; +- break; +- } +- } ++ case E1000_RXBUFFER_2048: ++ default: ++ rctl |= E1000_RCTL_SZ_2048; ++ rctl &= ~E1000_RCTL_BSEX; ++ break; ++ case E1000_RXBUFFER_4096: ++ rctl |= E1000_RCTL_SZ_4096; ++ break; ++ case E1000_RXBUFFER_8192: ++ rctl |= E1000_RCTL_SZ_8192; ++ break; ++ case E1000_RXBUFFER_16384: ++ rctl |= E1000_RCTL_SZ_16384; ++ break; ++ } + +-#ifdef CONFIG_E1000_PACKET_SPLIT +- /* 82571 and greater support packet-split where the protocol +- * header is placed in skb->data and the packet data is +- * placed in pages hanging off of skb_shinfo(skb)->nr_frags. +- * In the case of a non-split, skb->data is linearly filled, +- * followed by the page buffers. Therefore, skb->data is +- * sized to hold the largest protocol header. +- */ +- pages = PAGE_USE_COUNT(adapter->netdev->mtu); +- if ((adapter->hw.mac_type > iegbe_82547_rev_2) && (pages <= 0x3) && +- PAGE_SIZE <= 0x4000) { +- adapter->rx_ps_pages = pages; +- } else { ++#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT ++ /* 82571 and greater support packet-split where the protocol ++ * header is placed in skb->data and the packet data is ++ * placed in pages hanging off of skb_shinfo(skb)->nr_frags. ++ * In the case of a non-split, skb->data is linearly filled, ++ * followed by the page buffers. Therefore, skb->data is ++ * sized to hold the largest protocol header. ++ */ ++ pages = PAGE_USE_COUNT(adapter->netdev->mtu); ++ if ((hw->mac_type >= iegbe_82571) && (pages <= 3) && ++ PAGE_SIZE <= 16384 && (rctl & E1000_RCTL_LPE)) ++ adapter->rx_ps_pages = pages; ++ else + adapter->rx_ps_pages = 0; +- } + #endif +- if (adapter->rx_ps_pages) { +- /* Configure extra packet-split registers */ +- rfctl = E1000_READ_REG(&adapter->hw, RFCTL); +- rfctl |= E1000_RFCTL_EXTEN; +- /* disable IPv6 packet split support */ +- rfctl |= E1000_RFCTL_IPV6_DIS; +- E1000_WRITE_REG(&adapter->hw, RFCTL, rfctl); +- +- rctl |= E1000_RCTL_DTYP_PS | E1000_RCTL_SECRC; +- +- psrctl |= adapter->rx_ps_bsize0 >> +- E1000_PSRCTL_BSIZE0_SHIFT; +- +- switch (adapter->rx_ps_pages) { +- case 0x3: +- psrctl |= PAGE_SIZE << +- E1000_PSRCTL_BSIZE3_SHIFT; +- case 0x2: +- psrctl |= PAGE_SIZE << +- E1000_PSRCTL_BSIZE2_SHIFT; +- case 0x1: +- psrctl |= PAGE_SIZE >> +- E1000_PSRCTL_BSIZE1_SHIFT; +- break; +- } ++ if (adapter->rx_ps_pages) { ++ /* Configure extra packet-split registers */ ++ rfctl = E1000_READ_REG(&adapter->hw, RFCTL); ++ rfctl |= E1000_RFCTL_EXTEN; ++ /* disable IPv6 packet split support */ ++ rfctl |= (E1000_RFCTL_IPV6_EX_DIS | ++ E1000_RFCTL_NEW_IPV6_EXT_DIS); ++ ++ rctl |= E1000_RCTL_DTYP_PS; ++ ++ psrctl |= adapter->rx_ps_bsize0 >> ++ E1000_PSRCTL_BSIZE0_SHIFT; ++ ++ switch (adapter->rx_ps_pages) { ++ case 3: ++ psrctl |= PAGE_SIZE << ++ E1000_PSRCTL_BSIZE3_SHIFT; ++ case 2: ++ psrctl |= PAGE_SIZE << ++ E1000_PSRCTL_BSIZE2_SHIFT; ++ case 1: ++ psrctl |= PAGE_SIZE >> ++ E1000_PSRCTL_BSIZE1_SHIFT; ++ break; ++ } + +- E1000_WRITE_REG(&adapter->hw, PSRCTL, psrctl); +- } ++ E1000_WRITE_REG(&adapter->hw, PSRCTL, psrctl); ++ } + +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl); ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); + } + + /** +@@ -1873,145 +1768,87 @@ iegbe_setup_rctl(struct iegbe_adapter *a + * Configure the Rx unit of the MAC after a reset. + **/ + +-static void +-iegbe_configure_rx(struct iegbe_adapter *adapter) ++static void iegbe_configure_rx(struct iegbe_adapter *adapter) + { +- uint64_t rdba; +- struct iegbe_hw *hw = &adapter->hw; +- uint32_t rdlen, rctl, rxcsum, ctrl_ext; +-#ifdef CONFIG_E1000_MQ +- uint32_t reta, mrqc; +- int i; +-#endif ++ u64 rdba; ++ struct iegbe_hw *hw = &adapter->hw; ++ u32 rdlen, rctl, rxcsum, ctrl_ext; + +- if (adapter->rx_ps_pages) { ++ if (adapter->rx_ps_pages) { + rdlen = adapter->rx_ring[0].count * +- sizeof(union iegbe_rx_desc_packet_split); +- adapter->clean_rx = iegbe_clean_rx_irq_ps; +- adapter->alloc_rx_buf = iegbe_alloc_rx_buffers_ps; +- } else { ++ sizeof(union iegbe_rx_desc_packet_split); ++ adapter->clean_rx = iegbe_clean_rx_irq_ps; ++ adapter->alloc_rx_buf = iegbe_alloc_rx_buffers_ps; ++ } else { + rdlen = adapter->rx_ring[0].count * +- sizeof(struct iegbe_rx_desc); +- adapter->clean_rx = iegbe_clean_rx_irq; +- adapter->alloc_rx_buf = iegbe_alloc_rx_buffers; +- } ++ sizeof(struct iegbe_rx_desc); ++ adapter->clean_rx = iegbe_clean_rx_irq; ++ adapter->alloc_rx_buf = iegbe_alloc_rx_buffers; ++ } + +- /* disable receives while setting up the descriptors */ +- rctl = E1000_READ_REG(hw, RCTL); +- E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN); ++ /* disable receives while setting up the descriptors */ ++ rctl = E1000_READ_REG(hw, RCTL); ++ E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN); + +- /* set the Receive Delay Timer Register */ +- E1000_WRITE_REG(hw, RDTR, adapter->rx_int_delay); ++ /* set the Receive Delay Timer Register */ ++ E1000_WRITE_REG(hw, RDTR, adapter->rx_int_delay); + +- if (hw->mac_type >= iegbe_82540) { +- E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay); +- if(adapter->itr > 0x1) { +- E1000_WRITE_REG(hw, ITR, +- 0x3b9aca00 / (adapter->itr * 0x100)); ++ if (hw->mac_type >= iegbe_82540) { ++ E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay); ++ if (adapter->itr_setting != 0) ++ E1000_WRITE_REG(&adapter->hw, ITR, 1000000000 / (adapter->itr * 256)); + } +- } + +- if (hw->mac_type >= iegbe_82571) { +- /* Reset delay timers after every interrupt */ +- ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); +- ctrl_ext |= E1000_CTRL_EXT_CANC; +- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); +- E1000_WRITE_FLUSH(hw); +- } ++ if (hw->mac_type >= iegbe_82571) { ++ /* Reset delay timers after every interrupt */ ++ ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); ++ ctrl_ext |= E1000_CTRL_EXT_CANC; ++ E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); ++ E1000_WRITE_FLUSH(hw); ++ } + + /* Setup the HW Rx Head and Tail Descriptor Pointers and + * the Base and Length of the Rx Descriptor Ring */ +- switch (adapter->num_queues) { +-#ifdef CONFIG_E1000_MQ +- case 0x2: +- rdba = adapter->rx_ring[0x1].dma; +- E1000_WRITE_REG(hw, RDBAL1, (rdba & 0x00000000ffffffffULL)); +- E1000_WRITE_REG(hw, RDBAH1, (rdba >> 0x20)); +- E1000_WRITE_REG(hw, RDLEN1, rdlen); +- E1000_WRITE_REG(hw, RDH1, 0); +- E1000_WRITE_REG(hw, RDT1, 0); +- adapter->rx_ring[1].rdh = E1000_RDH1; +- adapter->rx_ring[1].rdt = E1000_RDT1; +- /* Fall Through */ +-#endif +- case 0x1: +- default: ++ switch (adapter->num_rx_queues) { ++ case 1: ++ default: + rdba = adapter->rx_ring[0].dma; +- E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL)); ++ E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL)); + E1000_WRITE_REG(hw, RDBAH, (rdba >> 0x20)); +- E1000_WRITE_REG(hw, RDLEN, rdlen); +- E1000_WRITE_REG(hw, RDH, 0); +- E1000_WRITE_REG(hw, RDT, 0); +- adapter->rx_ring[0].rdh = E1000_RDH; +- adapter->rx_ring[0].rdt = E1000_RDT; +- break; +- } ++ E1000_WRITE_REG(hw, RDLEN, rdlen); ++ adapter->rx_ring[0].rdh = ((hw->mac_type >= iegbe_82543) ? E1000_RDH : E1000_82542_RDH); ++ adapter->rx_ring[0].rdt = ((hw->mac_type >= iegbe_82543) ? E1000_RDT : E1000_82542_RDT); ++ break; ++ } + +-#ifdef CONFIG_E1000_MQ +- if (adapter->num_queues > 0x1) { +- uint32_t random[0xa]; +- +- get_random_bytes(&random[0], FORTY); +- +- if (hw->mac_type <= iegbe_82572) { +- E1000_WRITE_REG(hw, RSSIR, 0); +- E1000_WRITE_REG(hw, RSSIM, 0); +- } + +- switch (adapter->num_queues) { +- case 0x2: +- default: +- reta = 0x00800080; +- mrqc = E1000_MRQC_ENABLE_RSS_2Q; +- break; +- } +- +- /* Fill out redirection table */ +- for (i = 0; i < 0x20; i++) +- E1000_WRITE_REG_ARRAY(hw, RETA, i, reta); +- /* Fill out hash function seeds */ +- for (i = 0; i < 0xa; i++) +- E1000_WRITE_REG_ARRAY(hw, RSSRK, i, random[i]); +- +- mrqc |= (E1000_MRQC_RSS_FIELD_IPV4 | +- E1000_MRQC_RSS_FIELD_IPV4_TCP); +- E1000_WRITE_REG(hw, MRQC, mrqc); +- } +- +- /* Multiqueue and packet checksumming are mutually exclusive. */ +- if (hw->mac_type >= iegbe_82571) { +- rxcsum = E1000_READ_REG(hw, RXCSUM); +- rxcsum |= E1000_RXCSUM_PCSD; +- E1000_WRITE_REG(hw, RXCSUM, rxcsum); +- } +- +-#else ++ /* Enable 82543 Receive Checksum Offload for TCP and UDP */ ++ if (hw->mac_type >= iegbe_82543) { ++ rxcsum = E1000_READ_REG(hw, RXCSUM); ++ if(adapter->rx_csum == TRUE) { ++ rxcsum |= E1000_RXCSUM_TUOFL; ++ ++ /* Enable 82571 IPv4 payload checksum for UDP fragments ++ * Must be used in conjunction with packet-split. */ ++ if ((hw->mac_type >= iegbe_82571) && ++ (adapter->rx_ps_pages)) { ++ rxcsum |= E1000_RXCSUM_IPPCSE; ++ } ++ } else { ++ rxcsum &= ~E1000_RXCSUM_TUOFL; ++ /* don't need to clear IPPCSE as it defaults to 0 */ ++ } ++ E1000_WRITE_REG(hw, RXCSUM, rxcsum); ++ } + +- /* Enable 82543 Receive Checksum Offload for TCP and UDP */ +- if (hw->mac_type >= iegbe_82543) { +- rxcsum = E1000_READ_REG(hw, RXCSUM); +- if(adapter->rx_csum == TRUE) { +- rxcsum |= E1000_RXCSUM_TUOFL; +- +- /* Enable 82571 IPv4 payload checksum for UDP fragments +- * Must be used in conjunction with packet-split. */ +- if ((hw->mac_type >= iegbe_82571) && +- (adapter->rx_ps_pages)) { +- rxcsum |= E1000_RXCSUM_IPPCSE; +- } +- } else { +- rxcsum &= ~E1000_RXCSUM_TUOFL; +- /* don't need to clear IPPCSE as it defaults to 0 */ +- } +- E1000_WRITE_REG(hw, RXCSUM, rxcsum); +- } +-#endif /* CONFIG_E1000_MQ */ ++ /* enable early receives on 82573, only takes effect if using > 2048 ++ * byte total frame size. for example only for jumbo frames */ ++#define E1000_ERT_2048 0x100 ++ if (hw->mac_type == iegbe_82573) ++ E1000_WRITE_REG(&adapter->hw, ERT, E1000_ERT_2048); + +- if (hw->mac_type == iegbe_82573) { +- E1000_WRITE_REG(hw, ERT, 0x0100); +- } + /* Enable Receives */ +- E1000_WRITE_REG(hw, RCTL, rctl); ++ E1000_WRITE_REG(hw, RCTL, rctl); + } + + /** +@@ -2022,20 +1859,19 @@ iegbe_configure_rx(struct iegbe_adapter + * Free all transmit software resources + **/ + +-void +-iegbe_free_tx_resources(struct iegbe_adapter *adapter, ++static void iegbe_free_tx_resources(struct iegbe_adapter *adapter, + struct iegbe_tx_ring *tx_ring) + { +- struct pci_dev *pdev = adapter->pdev; ++ struct pci_dev *pdev = adapter->pdev; + +- iegbe_clean_tx_ring(adapter, tx_ring); ++ iegbe_clean_tx_ring(adapter, tx_ring); + +- vfree(tx_ring->buffer_info); +- tx_ring->buffer_info = NULL; ++ vfree(tx_ring->buffer_info); ++ tx_ring->buffer_info = NULL; + +- pci_free_consistent(pdev, tx_ring->size, tx_ring->desc, tx_ring->dma); ++ pci_free_consistent(pdev, tx_ring->size, tx_ring->desc, tx_ring->dma); + +- tx_ring->desc = NULL; ++ tx_ring->desc = NULL; + } + + /** +@@ -2048,85 +1884,29 @@ iegbe_free_tx_resources(struct iegbe_ada + void + iegbe_free_all_tx_resources(struct iegbe_adapter *adapter) + { +- int i; ++ int i; + +- for (i = 0; i < adapter->num_queues; i++) ++ for (i = 0x0; i < adapter->num_tx_queues; i++) + iegbe_free_tx_resources(adapter, &adapter->tx_ring[i]); + } + + static inline void + iegbe_unmap_and_free_tx_resource(struct iegbe_adapter *adapter, +- struct iegbe_buffer *buffer_info) +-{ +- if(buffer_info->dma) { +- pci_unmap_page(adapter->pdev, +- buffer_info->dma, +- buffer_info->length, +- PCI_DMA_TODEVICE); +- buffer_info->dma = 0; +- } +- if(buffer_info->skb) { +- dev_kfree_skb_any(buffer_info->skb); +- buffer_info->skb = NULL; +- } +-} +- +-#ifdef IEGBE_GBE_WORKAROUND +-/** +- * iegbe_clean_tx_ring_partial - Free Tx Buffers without using the DD +- * bit in the descriptor +- * @adapter: board private structure +- * @tx_ring: ring to be cleaned +- **/ +-static void iegbe_clean_tx_ring_partial(struct iegbe_adapter *adapter, +- struct iegbe_tx_ring *tx_ring) ++ struct iegbe_buffer *buffer_info) + { +- struct iegbe_buffer *buffer_info; +- struct iegbe_tx_desc *tx_desc; +- struct net_device *netdev = adapter->netdev; +- unsigned int i; +- unsigned tail; +- unsigned head; +- int cleaned = FALSE; +- +- tail = readl(adapter->hw.hw_addr + tx_ring->tdt); +- head = readl(adapter->hw.hw_addr + tx_ring->tdh); +- +- if (head != tail) { +- adapter->stats.tx_hnet++; +- } +- if (head != tx_ring->next_to_use) { +- adapter->stats.tx_hnentu++; +- } +- /* Free all the Tx ring sk_buffs from next_to_clean up until +- * the current head pointer +- */ +- i = tx_ring->next_to_clean; +- while(i != head) { +- cleaned = TRUE; +- tx_desc = E1000_TX_DESC(*tx_ring, i); +- +- buffer_info = &tx_ring->buffer_info[i]; +- iegbe_unmap_and_free_tx_resource(adapter, buffer_info); +- +- tx_desc->upper.data = 0; +- +- if (unlikely(++i == tx_ring->count)) { i = 0; } +- +- } +- tx_ring->next_to_clean = head; +- +- spin_lock(&tx_ring->tx_lock); +- +- /* Wake up the queue if it's currently stopped */ +- if (unlikely(cleaned && netif_queue_stopped(netdev) && +- netif_carrier_ok(netdev))) { +- netif_wake_queue(netdev); ++ if(buffer_info->dma) { ++ pci_unmap_page(adapter->pdev, ++ buffer_info->dma, ++ buffer_info->length, ++ PCI_DMA_TODEVICE); ++ buffer_info->dma = 0x0; ++ } ++ if(buffer_info->skb) { ++ dev_kfree_skb_any(buffer_info->skb); ++ buffer_info->skb = NULL; + } +- +- spin_unlock(&tx_ring->tx_lock); + } +-#endif ++ + + /** + * iegbe_clean_tx_ring - Free Tx Buffers +@@ -2134,38 +1914,34 @@ static void iegbe_clean_tx_ring_partial( + * @tx_ring: ring to be cleaned + **/ + +-static void +-iegbe_clean_tx_ring(struct iegbe_adapter *adapter, ++static void iegbe_clean_tx_ring(struct iegbe_adapter *adapter, + struct iegbe_tx_ring *tx_ring) + { +- struct iegbe_buffer *buffer_info; +- unsigned long size; +- unsigned int i; +- +- /* Free all the Tx ring sk_buffs */ ++ struct iegbe_hw *hw = &adapter->hw; ++ struct iegbe_buffer *buffer_info; ++ unsigned long size; ++ unsigned int i; + +- if (likely(tx_ring->previous_buffer_info.skb != NULL)) { +- iegbe_unmap_and_free_tx_resource(adapter, +- &tx_ring->previous_buffer_info); +- } ++ /* Free all the Tx ring sk_buffs */ + + for (i = 0; i < tx_ring->count; i++) { +- buffer_info = &tx_ring->buffer_info[i]; +- iegbe_unmap_and_free_tx_resource(adapter, buffer_info); +- } ++ buffer_info = &tx_ring->buffer_info[i]; ++ iegbe_unmap_and_free_tx_resource(adapter, buffer_info); ++ } + +- size = sizeof(struct iegbe_buffer) * tx_ring->count; ++ size = sizeof(struct iegbe_buffer) * tx_ring->count; + memset(tx_ring->buffer_info, 0, size); + +- /* Zero out the descriptor ring */ ++ /* Zero out the descriptor ring */ + + memset(tx_ring->desc, 0, tx_ring->size); + + tx_ring->next_to_use = 0; + tx_ring->next_to_clean = 0; ++ tx_ring->last_tx_tso = 0; + +- writel(0, adapter->hw.hw_addr + tx_ring->tdh); +- writel(0, adapter->hw.hw_addr + tx_ring->tdt); ++ writel(0, hw->hw_addr + tx_ring->tdh); ++ writel(0, hw->hw_addr + tx_ring->tdt); + } + + /** +@@ -2173,12 +1949,11 @@ iegbe_clean_tx_ring(struct iegbe_adapter + * @adapter: board private structure + **/ + +-static void +-iegbe_clean_all_tx_rings(struct iegbe_adapter *adapter) ++static void iegbe_clean_all_tx_rings(struct iegbe_adapter *adapter) + { +- int i; ++ int i; + +- for (i = 0; i < adapter->num_queues; i++) ++ for (i = 0; i < adapter->num_tx_queues; i++) + iegbe_clean_tx_ring(adapter, &adapter->tx_ring[i]); + } + +@@ -2190,24 +1965,23 @@ iegbe_clean_all_tx_rings(struct iegbe_ad + * Free all receive software resources + **/ + +-void +-iegbe_free_rx_resources(struct iegbe_adapter *adapter, ++static void iegbe_free_rx_resources(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring) + { +- struct pci_dev *pdev = adapter->pdev; ++ struct pci_dev *pdev = adapter->pdev; + +- iegbe_clean_rx_ring(adapter, rx_ring); ++ iegbe_clean_rx_ring(adapter, rx_ring); + +- vfree(rx_ring->buffer_info); +- rx_ring->buffer_info = NULL; +- kfree(rx_ring->ps_page); +- rx_ring->ps_page = NULL; +- kfree(rx_ring->ps_page_dma); +- rx_ring->ps_page_dma = NULL; ++ vfree(rx_ring->buffer_info); ++ rx_ring->buffer_info = NULL; ++ kfree(rx_ring->ps_page); ++ rx_ring->ps_page = NULL; ++ kfree(rx_ring->ps_page_dma); ++ rx_ring->ps_page_dma = NULL; + +- pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma); ++ pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma); + +- rx_ring->desc = NULL; ++ rx_ring->desc = NULL; + } + + /** +@@ -2217,12 +1991,11 @@ iegbe_free_rx_resources(struct iegbe_ada + * Free all receive software resources + **/ + +-void +-iegbe_free_all_rx_resources(struct iegbe_adapter *adapter) ++void iegbe_free_all_rx_resources(struct iegbe_adapter *adapter) + { +- int i; ++ int i; + +- for (i = 0; i < adapter->num_queues; i++) ++ for (i = 0; i < adapter->num_rx_queues; i++) + iegbe_free_rx_resources(adapter, &adapter->rx_ring[i]); + } + +@@ -2232,60 +2005,59 @@ iegbe_free_all_rx_resources(struct iegbe + * @rx_ring: ring to free buffers from + **/ + +-static void +-iegbe_clean_rx_ring(struct iegbe_adapter *adapter, ++static void iegbe_clean_rx_ring(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring) + { +- struct iegbe_buffer *buffer_info; +- struct iegbe_ps_page *ps_page; +- struct iegbe_ps_page_dma *ps_page_dma; +- struct pci_dev *pdev = adapter->pdev; +- unsigned long size; +- unsigned int i, j; +- +- /* Free all the Rx ring sk_buffs */ ++ struct iegbe_hw *hw = &adapter->hw; ++ struct iegbe_buffer *buffer_info; ++ struct iegbe_ps_page *ps_page; ++ struct iegbe_ps_page_dma *ps_page_dma; ++ struct pci_dev *pdev = adapter->pdev; ++ unsigned long size; ++ unsigned int i, j; ++ ++ /* Free all the Rx ring sk_buffs */ ++ ++ for (i = 0; i < rx_ring->count; i++) { ++ buffer_info = &rx_ring->buffer_info[i]; ++ if(buffer_info->skb) { ++ pci_unmap_single(pdev, ++ buffer_info->dma, ++ buffer_info->length, ++ PCI_DMA_FROMDEVICE); + +- for(i = 0; i < rx_ring->count; i++) { +- buffer_info = &rx_ring->buffer_info[i]; +- if(buffer_info->skb) { +- ps_page = &rx_ring->ps_page[i]; +- ps_page_dma = &rx_ring->ps_page_dma[i]; +- pci_unmap_single(pdev, +- buffer_info->dma, +- buffer_info->length, +- PCI_DMA_FROMDEVICE); +- +- dev_kfree_skb(buffer_info->skb); +- buffer_info->skb = NULL; +- +- for(j = 0; j < adapter->rx_ps_pages; j++) { +- if(!ps_page->ps_page[j]) { break; } +- pci_unmap_single(pdev, +- ps_page_dma->ps_page_dma[j], +- PAGE_SIZE, PCI_DMA_FROMDEVICE); +- ps_page_dma->ps_page_dma[j] = 0; +- put_page(ps_page->ps_page[j]); +- ps_page->ps_page[j] = NULL; +- } ++ dev_kfree_skb(buffer_info->skb); ++ buffer_info->skb = NULL; + } +- } ++ ps_page = &rx_ring->ps_page[i]; ++ ps_page_dma = &rx_ring->ps_page_dma[i]; ++ for (j = 0; j < adapter->rx_ps_pages; j++) { ++ if (!ps_page->ps_page[j]) break; ++ pci_unmap_page(pdev, ++ ps_page_dma->ps_page_dma[j], ++ PAGE_SIZE, PCI_DMA_FROMDEVICE); ++ ps_page_dma->ps_page_dma[j] = 0; ++ put_page(ps_page->ps_page[j]); ++ ps_page->ps_page[j] = NULL; ++ } ++ } + +- size = sizeof(struct iegbe_buffer) * rx_ring->count; ++ size = sizeof(struct iegbe_buffer) * rx_ring->count; + memset(rx_ring->buffer_info, 0, size); +- size = sizeof(struct iegbe_ps_page) * rx_ring->count; ++ size = sizeof(struct iegbe_ps_page) * rx_ring->count; + memset(rx_ring->ps_page, 0, size); +- size = sizeof(struct iegbe_ps_page_dma) * rx_ring->count; ++ size = sizeof(struct iegbe_ps_page_dma) * rx_ring->count; + memset(rx_ring->ps_page_dma, 0, size); + +- /* Zero out the descriptor ring */ ++ /* Zero out the descriptor ring */ + + memset(rx_ring->desc, 0, rx_ring->size); + + rx_ring->next_to_clean = 0; + rx_ring->next_to_use = 0; + +- writel(0, adapter->hw.hw_addr + rx_ring->rdh); +- writel(0, adapter->hw.hw_addr + rx_ring->rdt); ++ writel(0, hw->hw_addr + rx_ring->rdh); ++ writel(0, hw->hw_addr + rx_ring->rdt); + } + + /** +@@ -2293,60 +2065,54 @@ iegbe_clean_rx_ring(struct iegbe_adapter + * @adapter: board private structure + **/ + +-static void +-iegbe_clean_all_rx_rings(struct iegbe_adapter *adapter) ++static void iegbe_clean_all_rx_rings(struct iegbe_adapter *adapter) + { +- int i; ++ int i; + +- for (i = 0; i < adapter->num_queues; i++) ++ for (i = 0; i < adapter->num_rx_queues; i++) + iegbe_clean_rx_ring(adapter, &adapter->rx_ring[i]); + } + + /* The 82542 2.0 (revision 2) needs to have the receive unit in reset + * and memory write and invalidate disabled for certain operations + */ +-static void +-iegbe_enter_82542_rst(struct iegbe_adapter *adapter) ++static void iegbe_enter_82542_rst(struct iegbe_adapter *adapter) + { +- struct net_device *netdev = adapter->netdev; +- uint32_t rctl; ++ struct net_device *netdev = adapter->netdev; ++ uint32_t rctl; + +- iegbe_pci_clear_mwi(&adapter->hw); ++ iegbe_pci_clear_mwi(&adapter->hw); + +- rctl = E1000_READ_REG(&adapter->hw, RCTL); +- rctl |= E1000_RCTL_RST; +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl); +- E1000_WRITE_FLUSH(&adapter->hw); ++ rctl = E1000_READ_REG(&adapter->hw, RCTL); ++ rctl |= E1000_RCTL_RST; ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); ++ E1000_WRITE_FLUSH(&adapter->hw); + mdelay(0x5); + + if(netif_running(netdev)) { +- iegbe_clean_all_rx_rings(adapter); +-} ++ iegbe_clean_all_rx_rings(adapter); ++ } + } + + static void + iegbe_leave_82542_rst(struct iegbe_adapter *adapter) + { +- struct net_device *netdev = adapter->netdev; +- uint32_t rctl; ++ struct net_device *netdev = adapter->netdev; ++ uint32_t rctl; + +- rctl = E1000_READ_REG(&adapter->hw, RCTL); +- rctl &= ~E1000_RCTL_RST; +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl); +- E1000_WRITE_FLUSH(&adapter->hw); ++ rctl = E1000_READ_REG(&adapter->hw, RCTL); ++ rctl &= ~E1000_RCTL_RST; ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); ++ E1000_WRITE_FLUSH(&adapter->hw); + mdelay(0x5); + + if(adapter->hw.pci_cmd_word & PCI_COMMAND_INVALIDATE) { +- iegbe_pci_set_mwi(&adapter->hw); ++ iegbe_pci_set_mwi(&adapter->hw); + } + if(netif_running(netdev)) { ++ struct iegbe_rx_ring *ring = &adapter->rx_ring[0x0]; + iegbe_configure_rx(adapter); +-#ifdef IEGBE_GBE_WORKAROUND +- iegbe_alloc_rx_buffers(adapter, &adapter->rx_ring[0], +- IEGBE_GBE_WORKAROUND_NUM_RX_DESCRIPTORS + 1); +-#else +- iegbe_alloc_rx_buffers(adapter, &adapter->rx_ring[0]); +-#endif ++ adapter->alloc_rx_buf(adapter, ring, E1000_DESC_UNUSED(ring)); + } + } + +@@ -2358,133 +2124,153 @@ iegbe_leave_82542_rst(struct iegbe_adapt + * Returns 0 on success, negative on failure + **/ + +-static int +-iegbe_set_mac(struct net_device *netdev, void *p) ++static int iegbe_set_mac(struct net_device *netdev, void *p) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- struct sockaddr *addr = p; ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct sockaddr *addr = p; + + if(!is_valid_ether_addr(addr->sa_data)) { +- return -EADDRNOTAVAIL; ++ return -EADDRNOTAVAIL; + } +- /* 82542 2.0 needs to be in reset to write receive address registers */ ++ /* 82542 2.0 needs to be in reset to write receive address registers */ + + if(adapter->hw.mac_type == iegbe_82542_rev2_0) { +- iegbe_enter_82542_rst(adapter); ++ iegbe_enter_82542_rst(adapter); + } +- memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); +- memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); ++ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); ++ memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); + +- iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr, 0); ++ iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr, 0x0); + +- /* With 82571 controllers, LAA may be overwritten (with the default) +- * due to controller reset from the other port. */ +- if (adapter->hw.mac_type == iegbe_82571) { +- /* activate the work around */ ++ /* With 82571 controllers, LAA may be overwritten (with the default) ++ * due to controller reset from the other port. */ ++ if (adapter->hw.mac_type == iegbe_82571) { ++ /* activate the work around */ + adapter->hw.laa_is_present = 0x1; + +- /* Hold a copy of the LAA in RAR[14] This is done so that +- * between the time RAR[0] gets clobbered and the time it +- * gets fixed (in iegbe_watchdog), the actual LAA is in one +- * of the RARs and no incoming packets directed to this port +- * are dropped. Eventaully the LAA will be in RAR[0] and +- * RAR[14] */ +- iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr, ++ /* Hold a copy of the LAA in RAR[14] This is done so that ++ * between the time RAR[0] gets clobbered and the time it ++ * gets fixed (in iegbe_watchdog), the actual LAA is in one ++ * of the RARs and no incoming packets directed to this port ++ * are dropped. Eventaully the LAA will be in RAR[0] and ++ * RAR[14] */ ++ iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr, + E1000_RAR_ENTRIES - 0x1); +- } ++ } + + if(adapter->hw.mac_type == iegbe_82542_rev2_0) { +- iegbe_leave_82542_rst(adapter); ++ iegbe_leave_82542_rst(adapter); + } +- return 0; ++ return 0x0; + } + + /** +- * iegbe_set_multi - Multicast and Promiscuous mode set ++ * iegbe_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set + * @netdev: network interface device structure + * +- * The set_multi entry point is called whenever the multicast address +- * list or the network interface flags are updated. This routine is +- * responsible for configuring the hardware for proper multicast, ++ * The set_rx_mode entry point is called whenever the unicast or multicast ++ * address lists or the network interface flags are updated. This routine is ++ * responsible for configuring the hardware for proper unicast, multicast, + * promiscuous mode, and all-multi behavior. + **/ + +-static void +-iegbe_set_multi(struct net_device *netdev) ++static void iegbe_set_rx_mode(struct net_device *netdev) + { + struct iegbe_adapter *adapter = netdev_priv(netdev); + struct iegbe_hw *hw = &adapter->hw; +- struct dev_mc_list *mc_ptr; +- uint32_t rctl; +- uint32_t hash_value; ++ struct dev_addr_list *uc_ptr; ++ struct dev_addr_list *mc_ptr; ++ u32 rctl; ++ u32 hash_value; + int i, rar_entries = E1000_RAR_ENTRIES; ++int mta_reg_count = E1000_NUM_MTA_REGISTERS; + + /* reserve RAR[14] for LAA over-write work-around */ +- if (adapter->hw.mac_type == iegbe_82571) { ++ if (hw->mac_type == iegbe_82571) + rar_entries--; +- } ++ + /* Check for Promiscuous and All Multicast modes */ + +- rctl = E1000_READ_REG(hw, RCTL); ++ rctl = E1000_READ_REG(&adapter->hw, RCTL); + + if (netdev->flags & IFF_PROMISC) { + rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); +- } else if (netdev->flags & IFF_ALLMULTI) { +- rctl |= E1000_RCTL_MPE; +- rctl &= ~E1000_RCTL_UPE; ++ rctl &= ~E1000_RCTL_VFE; + } else { +- rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE); ++ if (netdev->flags & IFF_ALLMULTI) { ++ rctl |= E1000_RCTL_MPE; ++ } else { ++ rctl &= ~E1000_RCTL_MPE; ++ } ++ } ++ ++ uc_ptr = NULL; ++ if (netdev->uc_count > rar_entries - 1) { ++ rctl |= E1000_RCTL_UPE; ++ } else if (!(netdev->flags & IFF_PROMISC)) { ++ rctl &= ~E1000_RCTL_UPE; ++ uc_ptr = netdev->uc_list; + } + +- E1000_WRITE_REG(hw, RCTL, rctl); ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); + + /* 82542 2.0 needs to be in reset to write receive address registers */ + +- if (hw->mac_type == iegbe_82542_rev2_0) { ++ if (hw->mac_type == iegbe_82542_rev2_0) + iegbe_enter_82542_rst(adapter); +- } +- /* load the first 14 multicast address into the exact filters 1-14 ++ ++ /* load the first 14 addresses into the exact filters 1-14. Unicast ++ * addresses take precedence to avoid disabling unicast filtering ++ * when possible. ++ * + * RAR 0 is used for the station MAC adddress + * if there are not 14 addresses, go ahead and clear the filters + * -- with 82571 controllers only 0-13 entries are filled here + */ + mc_ptr = netdev->mc_list; + +- for (i = 0x1; i < rar_entries; i++) { +- if (mc_ptr) { +- iegbe_rar_set(hw, mc_ptr->dmi_addr, i); ++ for (i = 1; i < rar_entries; i++) { ++ if (uc_ptr) { ++ iegbe_rar_set(hw, uc_ptr->da_addr, i); ++ uc_ptr = uc_ptr->next; ++ } else if (mc_ptr) { ++ iegbe_rar_set(hw, mc_ptr->da_addr, i); + mc_ptr = mc_ptr->next; + } else { +- E1000_WRITE_REG_ARRAY(hw, RA, i << 0x1, 0); +- E1000_WRITE_REG_ARRAY(hw, RA, (i << 0x1) + 0x1, 0); ++ E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0); ++ E1000_WRITE_FLUSH(&adapter->hw); ++ E1000_WRITE_REG_ARRAY(hw, RA, (i << 1) + 1, 0); ++ E1000_WRITE_FLUSH(&adapter->hw); + } + } ++ WARN_ON(uc_ptr != NULL); + + /* clear the old settings from the multicast hash table */ + +- for (i = 0; i < E1000_NUM_MTA_REGISTERS; i++) ++ for (i = 0; i < mta_reg_count; i++) { + E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); ++ E1000_WRITE_FLUSH(&adapter->hw); ++ } + + /* load any remaining addresses into the hash table */ + + for (; mc_ptr; mc_ptr = mc_ptr->next) { +- hash_value = iegbe_hash_mc_addr(hw, mc_ptr->dmi_addr); ++ hash_value = iegbe_hash_mc_addr(hw, mc_ptr->da_addr); + iegbe_mta_set(hw, hash_value); + } + +- if (hw->mac_type == iegbe_82542_rev2_0) { ++ if (hw->mac_type == iegbe_82542_rev2_0) + iegbe_leave_82542_rst(adapter); + } +-} + + /* Need to wait a few seconds after link up to get diagnostic information from + * the phy */ + +-static void +-iegbe_update_phy_info(unsigned long data) ++static void iegbe_update_phy_info(unsigned long data) + { +- struct iegbe_adapter *adapter = (struct iegbe_adapter *) data; +- iegbe_phy_get_info(&adapter->hw, &adapter->phy_info); ++ struct iegbe_adapter *adapter = (struct iegbe_adapter *) data; ++ struct iegbe_hw *hw = &adapter->hw; ++ iegbe_phy_get_info(hw, &adapter->phy_info); + } + + /** +@@ -2492,54 +2278,54 @@ iegbe_update_phy_info(unsigned long data + * @data: pointer to adapter cast into an unsigned long + **/ + +-static void +-iegbe_82547_tx_fifo_stall(unsigned long data) ++static void iegbe_82547_tx_fifo_stall(unsigned long data) + { +- struct iegbe_adapter *adapter = (struct iegbe_adapter *) data; +- struct net_device *netdev = adapter->netdev; +- uint32_t tctl; ++ struct iegbe_adapter *adapter = (struct iegbe_adapter *) data; ++ struct net_device *netdev = adapter->netdev; ++ u32 tctl; + +- if(atomic_read(&adapter->tx_fifo_stall)) { +- if((E1000_READ_REG(&adapter->hw, TDT) == +- E1000_READ_REG(&adapter->hw, TDH)) && +- (E1000_READ_REG(&adapter->hw, TDFT) == +- E1000_READ_REG(&adapter->hw, TDFH)) && +- (E1000_READ_REG(&adapter->hw, TDFTS) == +- E1000_READ_REG(&adapter->hw, TDFHS))) { +- tctl = E1000_READ_REG(&adapter->hw, TCTL); +- E1000_WRITE_REG(&adapter->hw, TCTL, +- tctl & ~E1000_TCTL_EN); +- E1000_WRITE_REG(&adapter->hw, TDFT, +- adapter->tx_head_addr); +- E1000_WRITE_REG(&adapter->hw, TDFH, +- adapter->tx_head_addr); +- E1000_WRITE_REG(&adapter->hw, TDFTS, +- adapter->tx_head_addr); +- E1000_WRITE_REG(&adapter->hw, TDFHS, +- adapter->tx_head_addr); +- E1000_WRITE_REG(&adapter->hw, TCTL, tctl); +- E1000_WRITE_FLUSH(&adapter->hw); +- +- adapter->tx_fifo_head = 0; +- atomic_set(&adapter->tx_fifo_stall, 0); +- netif_wake_queue(netdev); +- } else { ++ if(atomic_read(&adapter->tx_fifo_stall)) { ++ if((E1000_READ_REG(&adapter->hw, TDT) == ++ E1000_READ_REG(&adapter->hw, TDH)) && ++ (E1000_READ_REG(&adapter->hw, TDFT) == ++ E1000_READ_REG(&adapter->hw, TDFH)) && ++ (E1000_READ_REG(&adapter->hw, TDFTS) == ++ E1000_READ_REG(&adapter->hw, TDFHS))) { ++ tctl = E1000_READ_REG(&adapter->hw, TCTL); ++ E1000_WRITE_REG(&adapter->hw, TCTL, ++ tctl & ~E1000_TCTL_EN); ++ E1000_WRITE_REG(&adapter->hw, TDFT, ++ adapter->tx_head_addr); ++ E1000_WRITE_REG(&adapter->hw, TDFH, ++ adapter->tx_head_addr); ++ E1000_WRITE_REG(&adapter->hw, TDFTS, ++ adapter->tx_head_addr); ++ E1000_WRITE_REG(&adapter->hw, TDFHS, ++ adapter->tx_head_addr); ++ E1000_WRITE_REG(&adapter->hw, TCTL, tctl); ++ E1000_WRITE_FLUSH(&adapter->hw); ++ ++ adapter->tx_fifo_head = 0x0; ++ atomic_set(&adapter->tx_fifo_stall, 0x0); ++ netif_wake_queue(netdev); ++ } else { + mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 0x1); +- } +- } ++ } ++ } + } + ++ + /** + * iegbe_watchdog - Timer Call-back + * @data: pointer to adapter cast into an unsigned long + **/ +-static void +-iegbe_watchdog(unsigned long data) ++static void iegbe_watchdog(unsigned long data) + { +- struct iegbe_adapter *adapter = (struct iegbe_adapter *) data; +- struct net_device *netdev = adapter->netdev; +- struct iegbe_tx_ring *txdr = &adapter->tx_ring[0]; +- uint32_t link; ++ struct iegbe_adapter *adapter = (struct iegbe_adapter *) data; ++ struct iegbe_hw *hw = &adapter->hw; ++ struct net_device *netdev = adapter->netdev; ++ struct iegbe_tx_ring *txdr = adapter->tx_ring; ++ u32 link, tctl; + + /* + * Test the PHY for link status on icp_xxxx MACs. +@@ -2547,123 +2333,305 @@ iegbe_watchdog(unsigned long data) + * in the adapter->hw structure, then set hw->get_link_status = 1 + */ + if(adapter->hw.mac_type == iegbe_icp_xxxx) { +- int isUp = 0; ++ int isUp = 0x0; + int32_t ret_val; + + ret_val = iegbe_oem_phy_is_link_up(&adapter->hw, &isUp); + if(ret_val != E1000_SUCCESS) { +- isUp = 0; +- } ++ isUp = 0x0; ++ } + if(isUp != adapter->hw.icp_xxxx_is_link_up) { + adapter->hw.get_link_status = 0x1; + } + } + +- iegbe_check_for_link(&adapter->hw); +- if (adapter->hw.mac_type == iegbe_82573) { +- iegbe_enable_tx_pkt_filtering(&adapter->hw); ++ iegbe_check_for_link(&adapter->hw); ++ if (adapter->hw.mac_type == iegbe_82573) { ++ iegbe_enable_tx_pkt_filtering(&adapter->hw); + #ifdef NETIF_F_HW_VLAN_TX + if (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id) { +- iegbe_update_mng_vlan(adapter); ++ iegbe_update_mng_vlan(adapter); + } + #endif +- } ++ } + +- if ((adapter->hw.media_type == iegbe_media_type_internal_serdes) && +- !(E1000_READ_REG(&adapter->hw, TXCW) & E1000_TXCW_ANE)) { +- link = !adapter->hw.serdes_link_down; +- } else { ++ if ((adapter->hw.media_type == iegbe_media_type_internal_serdes) && ++ !(E1000_READ_REG(&adapter->hw, TXCW) & E1000_TXCW_ANE)) { ++ link = !adapter->hw.serdes_link_down; ++ } else { + +- if(adapter->hw.mac_type != iegbe_icp_xxxx) { +- link = E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU; +- } else { +- int isUp = 0; ++ if(adapter->hw.mac_type != iegbe_icp_xxxx) { ++ link = E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU; ++ } else { ++ int isUp = 0x0; + if(iegbe_oem_phy_is_link_up(&adapter->hw, &isUp) != E1000_SUCCESS) { +- isUp = 0; ++ isUp = 0x0; + } +- link = isUp; +- } +- } ++ link = isUp; ++ } ++ } + +- if (link) { +- if (!netif_carrier_ok(netdev)) { +- iegbe_get_speed_and_duplex(&adapter->hw, +- &adapter->link_speed, +- &adapter->link_duplex); +- +- DPRINTK(LINK, INFO, "NIC Link is Up %d Mbps %s\n", +- adapter->link_speed, +- adapter->link_duplex == FULL_DUPLEX ? +- "Full Duplex" : "Half Duplex"); ++ if (link) { ++ if (!netif_carrier_ok(netdev)) { ++ u32 ctrl; ++ bool txb2b = true; ++ iegbe_get_speed_and_duplex(hw, ++ &adapter->link_speed, ++ &adapter->link_duplex); + +- netif_carrier_on(netdev); +- netif_wake_queue(netdev); +- mod_timer(&adapter->phy_info_timer, jiffies + 0x2 * HZ); ++ ctrl = E1000_READ_REG(&adapter->hw, CTRL); ++ DPRINTK(LINK, INFO, "NIC Link is Up %d Mbps %s, " ++ "Flow Control: %s\n", ++ adapter->link_speed, ++ adapter->link_duplex == FULL_DUPLEX ? ++ "Full Duplex" : "Half Duplex", ++ ((ctrl & E1000_CTRL_TFCE) && (ctrl & ++ E1000_CTRL_RFCE)) ? "RX/TX" : ((ctrl & ++ E1000_CTRL_RFCE) ? "RX" : ((ctrl & ++ E1000_CTRL_TFCE) ? "TX" : "None" ))); ++ ++ /* tweak tx_queue_len according to speed/duplex ++ * and adjust the timeout factor */ ++ netdev->tx_queue_len = adapter->tx_queue_len; ++ adapter->tx_timeout_factor = 1; ++ switch (adapter->link_speed) { ++ case SPEED_10: ++ txb2b = false; ++ netdev->tx_queue_len = 10; ++ adapter->tx_timeout_factor = 8; ++ break; ++ case SPEED_100: ++ txb2b = false; ++ netdev->tx_queue_len = 100; ++ break; ++ } ++ if ((hw->mac_type == iegbe_82571 || ++ hw->mac_type == iegbe_82572) && ++ !txb2b) { ++ u32 tarc0; ++ tarc0 = E1000_READ_REG(&adapter->hw, TARC0); ++ tarc0 &= ~(1 << 21); ++ E1000_WRITE_REG(&adapter->hw, TARC0, tarc0); ++ } ++ /* disable TSO for pcie and 10/100 speeds, to avoid ++ * some hardware issues */ ++ if (!adapter->tso_force && ++ hw->bus_type == iegbe_bus_type_pci_express){ ++ switch (adapter->link_speed) { ++ case SPEED_10: ++ case SPEED_100: ++ DPRINTK(PROBE,INFO, ++ "10/100 speed: disabling TSO\n"); ++ netdev->features &= ~NETIF_F_TSO; ++ netdev->features &= ~NETIF_F_TSO6; ++ break; ++ case SPEED_1000: ++ netdev->features |= NETIF_F_TSO; ++ netdev->features |= NETIF_F_TSO6; ++ break; ++ default: ++ break; ++ } ++ } ++ tctl = E1000_READ_REG(&adapter->hw, TCTL); ++ tctl |= E1000_TCTL_EN; ++ E1000_WRITE_REG(&adapter->hw, TCTL, tctl); ++ netif_carrier_on(netdev); ++ netif_wake_queue(netdev); ++ mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ)); + adapter->smartspeed = 0; ++ } else { ++ if (hw->rx_needs_kicking) { ++ u32 rctl = E1000_READ_REG(&adapter->hw, RCTL); ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl | E1000_RCTL_EN); ++ } + } +- } else { +- if (netif_carrier_ok(netdev)) { ++ } else { ++ if (netif_carrier_ok(netdev)) { + adapter->link_speed = 0; + adapter->link_duplex = 0; +- DPRINTK(LINK, INFO, "NIC Link is Down\n"); +- netif_carrier_off(netdev); +- netif_stop_queue(netdev); +- mod_timer(&adapter->phy_info_timer, jiffies + 0x2 * HZ); +- } ++ DPRINTK(LINK, INFO, "NIC Link is Down\n"); ++ netif_carrier_off(netdev); ++ netif_stop_queue(netdev); ++ mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ)); ++ } + +- iegbe_smartspeed(adapter); +- } ++ iegbe_smartspeed(adapter); ++ } ++ ++ iegbe_update_stats(adapter); ++ ++ hw->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old; ++ adapter->tpt_old = adapter->stats.tpt; ++ hw->collision_delta = adapter->stats.colc - adapter->colc_old; ++ adapter->colc_old = adapter->stats.colc; ++ ++ adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old; ++ adapter->gorcl_old = adapter->stats.gorcl; ++ adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old; ++ adapter->gotcl_old = adapter->stats.gotcl; ++ ++ iegbe_update_adaptive(hw); ++ ++ if (!netif_carrier_ok(netdev)) { ++ if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) { ++ /* We've lost link, so the controller stops DMA, ++ * but we've got queued Tx work that's never going ++ * to get done, so reset controller to flush Tx. ++ * (Do the reset outside of interrupt context). */ ++ adapter->tx_timeout_count++; ++ schedule_work(&adapter->reset_task); ++ } ++ } ++ ++ /* Cause software interrupt to ensure rx ring is cleaned */ ++ E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0); ++ ++ /* Force detection of hung controller every watchdog period */ ++ adapter->detect_tx_hung = TRUE; ++ ++ /* With 82571 controllers, LAA may be overwritten due to controller ++ * reset from the other port. Set the appropriate LAA in RAR[0] */ ++ if (adapter->hw.mac_type == iegbe_82571 && adapter->hw.laa_is_present) { ++ iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr, 0x0); ++ } ++ /* Reset the timer */ ++ mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + 2 * HZ)); ++} ++ ++enum latency_range { ++ lowest_latency = 0, ++ low_latency = 1, ++ bulk_latency = 2, ++ latency_invalid = 255 ++}; + +- iegbe_update_stats(adapter); ++/** ++ * iegbe_update_itr - update the dynamic ITR value based on statistics ++ * Stores a new ITR value based on packets and byte ++ * counts during the last interrupt. The advantage of per interrupt ++ * computation is faster updates and more accurate ITR for the current ++ * traffic pattern. Constants in this function were computed ++ * based on theoretical maximum wire speed and thresholds were set based ++ * on testing data as well as attempting to minimize response time ++ * while increasing bulk throughput. ++ * this functionality is controlled by the InterruptThrottleRate module ++ * parameter (see iegbe_param.c) ++ * @adapter: pointer to adapter ++ * @itr_setting: current adapter->itr ++ * @packets: the number of packets during this measurement interval ++ * @bytes: the number of bytes during this measurement interval ++ **/ ++static unsigned int iegbe_update_itr(struct iegbe_adapter *adapter, ++ u16 itr_setting, int packets, int bytes) ++{ ++ unsigned int retval = itr_setting; ++ struct iegbe_hw *hw = &adapter->hw; + +- adapter->hw.tx_packet_delta = adapter->stats.tpt - adapter->tpt_old; +- adapter->tpt_old = adapter->stats.tpt; +- adapter->hw.collision_delta = adapter->stats.colc - adapter->colc_old; +- adapter->colc_old = adapter->stats.colc; +- +- adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old; +- adapter->gorcl_old = adapter->stats.gorcl; +- adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old; +- adapter->gotcl_old = adapter->stats.gotcl; +- +- iegbe_update_adaptive(&adapter->hw); +- +- if (adapter->num_queues == 0x1 && !netif_carrier_ok(netdev)) { +- if (E1000_DESC_UNUSED(txdr) + 0x1 < txdr->count) { +- /* We've lost link, so the controller stops DMA, +- * but we've got queued Tx work that's never going +- * to get done, so reset controller to flush Tx. +- * (Do the reset outside of interrupt context). */ +- schedule_work(&adapter->tx_timeout_task); ++ if (unlikely(hw->mac_type < iegbe_82540)) ++ goto update_itr_done; ++ ++ if (packets == 0) ++ goto update_itr_done; ++ ++ switch (itr_setting) { ++ case lowest_latency: ++ /* jumbo frames get bulk treatment*/ ++ if (bytes/packets > 8000) ++ retval = bulk_latency; ++ else if ((packets < 5) && (bytes > 512)) ++ retval = low_latency; ++ break; ++ case low_latency: /* 50 usec aka 20000 ints/s */ ++ if (bytes > 10000) { ++ /* jumbo frames need bulk latency setting */ ++ if (bytes/packets > 8000) ++ retval = bulk_latency; ++ else if ((packets < 10) || ((bytes/packets) > 1200)) ++ retval = bulk_latency; ++ else if ((packets > 35)) ++ retval = lowest_latency; ++ } else if (bytes/packets > 2000) ++ retval = bulk_latency; ++ else if (packets <= 2 && bytes < 512) ++ retval = lowest_latency; ++ break; ++ case bulk_latency: /* 250 usec aka 4000 ints/s */ ++ if (bytes > 25000) { ++ if (packets > 35) ++ retval = low_latency; ++ } else if (bytes < 6000) { ++ retval = low_latency; + } ++ break; + } + +- /* Dynamic mode for Interrupt Throttle Rate (ITR) */ +- if (adapter->hw.mac_type >= iegbe_82540 && adapter->itr == 0x1) { +- /* Symmetric Tx/Rx gets a reduced ITR=2000; Total +- * asymmetrical Tx or Rx gets ITR=8000; everyone +- * else is between 2000-8000. */ +- uint32_t goc = (adapter->gotcl + adapter->gorcl) / 0x2710; +- uint32_t dif = (adapter->gotcl > adapter->gorcl ? +- adapter->gotcl - adapter->gorcl : +- adapter->gorcl - adapter->gotcl) / 0x2710; +- uint32_t itr = goc > 0 ? (dif * 0x1770 / goc + 0x7d0) : 0x1f40; +- E1000_WRITE_REG(&adapter->hw, ITR, 0x3b9aca00 / (itr * 0x100)); +- } ++update_itr_done: ++ return retval; ++} + +- /* Cause software interrupt to ensure rx ring is cleaned */ +- E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0); ++static void iegbe_set_itr(struct iegbe_adapter *adapter) ++{ ++ struct iegbe_hw *hw = &adapter->hw; ++ u16 current_itr; ++ u32 new_itr = adapter->itr; + +- /* Force detection of hung controller every watchdog period */ +- adapter->detect_tx_hung = TRUE; ++ if (unlikely(hw->mac_type < iegbe_82540)) ++ return; + +- /* With 82571 controllers, LAA may be overwritten due to controller +- * reset from the other port. Set the appropriate LAA in RAR[0] */ +- if (adapter->hw.mac_type == iegbe_82571 && adapter->hw.laa_is_present) { +- iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr, 0); +- } +- /* Reset the timer */ +- mod_timer(&adapter->watchdog_timer, jiffies + 0x2 * HZ); ++ /* for non-gigabit speeds, just fix the interrupt rate at 4000 */ ++ if (unlikely(adapter->link_speed != SPEED_1000)) { ++ current_itr = 0; ++ new_itr = 4000; ++ goto set_itr_now; ++ } ++ ++ adapter->tx_itr = iegbe_update_itr(adapter, ++ adapter->tx_itr, ++ adapter->total_tx_packets, ++ adapter->total_tx_bytes); ++ /* conservative mode (itr 3) eliminates the lowest_latency setting */ ++ if (adapter->itr_setting == 3 && adapter->tx_itr == lowest_latency) ++ adapter->tx_itr = low_latency; ++ ++ adapter->rx_itr = iegbe_update_itr(adapter, ++ adapter->rx_itr, ++ adapter->total_rx_packets, ++ adapter->total_rx_bytes); ++ /* conservative mode (itr 3) eliminates the lowest_latency setting */ ++ if (adapter->itr_setting == 3 && adapter->rx_itr == lowest_latency) ++ adapter->rx_itr = low_latency; ++ ++ current_itr = max(adapter->rx_itr, adapter->tx_itr); ++ ++ switch (current_itr) { ++ /* counts and packets in update_itr are dependent on these numbers */ ++ case lowest_latency: ++ new_itr = 70000; ++ break; ++ case low_latency: ++ new_itr = 20000; /* aka hwitr = ~200 */ ++ break; ++ case bulk_latency: ++ new_itr = 4000; ++ break; ++ default: ++ break; ++ } ++ ++set_itr_now: ++ if (new_itr != adapter->itr) { ++ /* this attempts to bias the interrupt rate towards Bulk ++ * by adding intermediate steps when interrupt rate is ++ * increasing */ ++ new_itr = new_itr > adapter->itr ? ++ min(adapter->itr + (new_itr >> 2), new_itr) : ++ new_itr; ++ adapter->itr = new_itr; ++ E1000_WRITE_REG(&adapter->hw, ITR, 1000000000 / (new_itr * 256)); ++ } ++ ++ return; + } + + #define E1000_TX_FLAGS_CSUM 0x00000001 +@@ -2673,55 +2641,48 @@ iegbe_watchdog(unsigned long data) + #define E1000_TX_FLAGS_VLAN_MASK 0xffff0000 + #define E1000_TX_FLAGS_VLAN_SHIFT 16 + +-static inline int +-iegbe_tso(struct iegbe_adapter *adapter, struct iegbe_tx_ring *tx_ring, +- struct sk_buff *skb) ++static int iegbe_tso(struct iegbe_adapter *adapter, ++ struct iegbe_tx_ring *tx_ring, struct sk_buff *skb) + { +-#ifdef NETIF_F_TSO + struct iegbe_context_desc *context_desc; ++ struct iegbe_buffer *buffer_info; + unsigned int i; +- uint32_t cmd_length = 0; +- uint16_t ipcse = 0, tucse, mss; +- uint8_t ipcss, ipcso, tucss, tucso, hdr_len; ++ u32 cmd_length = 0; ++ u16 ipcse = 0, tucse, mss; ++ u8 ipcss, ipcso, tucss, tucso, hdr_len; + int err; + + if (skb_is_gso(skb)) { + if (skb_header_cloned(skb)) { + err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); +- if (err) { ++ if (err) + return err; + } +- } + +- hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 0x2)); ++ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); + mss = skb_shinfo(skb)->gso_size; + if (skb->protocol == htons(ETH_P_IP)) { +- skb->nh.iph->tot_len = 0; +- skb->nh.iph->check = 0; +- skb->h.th->check = +- ~csum_tcpudp_magic(skb->nh.iph->saddr, +- skb->nh.iph->daddr, +- 0, +- IPPROTO_TCP, +- 0); ++ struct iphdr *iph = ip_hdr(skb); ++ iph->tot_len = 0; ++ iph->check = 0; ++ tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, ++ iph->daddr, 0, ++ IPPROTO_TCP, ++ 0); + cmd_length = E1000_TXD_CMD_IP; +- ipcse = skb->h.raw - skb->data - 0x1; +-#ifdef NETIF_F_TSO_IPV6 +- } else if (skb->protocol == ntohs(ETH_P_IPV6)) { +- skb->nh.ipv6h->payload_len = 0; +- skb->h.th->check = +- ~csum_ipv6_magic(&skb->nh.ipv6h->saddr, +- &skb->nh.ipv6h->daddr, +- 0, +- IPPROTO_TCP, +- 0); ++ ipcse = skb_transport_offset(skb) - 1; ++ } else if (skb->protocol == htons(ETH_P_IPV6)) { ++ ipv6_hdr(skb)->payload_len = 0; ++ tcp_hdr(skb)->check = ++ ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, ++ &ipv6_hdr(skb)->daddr, ++ 0, IPPROTO_TCP, 0); + ipcse = 0; +-#endif + } +- ipcss = skb->nh.raw - skb->data; +- ipcso = (void *)&(skb->nh.iph->check) - (void *)skb->data; +- tucss = skb->h.raw - skb->data; +- tucso = (void *)&(skb->h.th->check) - (void *)skb->data; ++ ipcss = skb_network_offset(skb); ++ ipcso = (void *)&(ip_hdr(skb)->check) - (void *)skb->data; ++ tucss = skb_transport_offset(skb); ++ tucso = (void *)&(tcp_hdr(skb)->check) - (void *)skb->data; + tucse = 0; + + cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE | +@@ -2729,6 +2690,7 @@ iegbe_tso(struct iegbe_adapter *adapter, + + i = tx_ring->next_to_use; + context_desc = E1000_CONTEXT_DESC(*tx_ring, i); ++ buffer_info = &tx_ring->buffer_info[i]; + + context_desc->lower_setup.ip_fields.ipcss = ipcss; + context_desc->lower_setup.ip_fields.ipcso = ipcso; +@@ -2740,205 +2702,218 @@ iegbe_tso(struct iegbe_adapter *adapter, + context_desc->tcp_seg_setup.fields.hdr_len = hdr_len; + context_desc->cmd_and_length = cpu_to_le32(cmd_length); + +- if (++i == tx_ring->count) { i = 0; } ++ buffer_info->time_stamp = jiffies; ++ buffer_info->next_to_watch = i; ++ ++ if (++i == tx_ring->count) i = 0; + tx_ring->next_to_use = i; + +- return TRUE; ++ return true; + } +-#endif +- +- return FALSE; ++ return false; + } + +-static inline boolean_t +-iegbe_tx_csum(struct iegbe_adapter *adapter, struct iegbe_tx_ring *tx_ring, +- struct sk_buff *skb) ++static bool iegbe_tx_csum(struct iegbe_adapter *adapter, ++ struct iegbe_tx_ring *tx_ring, struct sk_buff *skb) + { + struct iegbe_context_desc *context_desc; ++ struct iegbe_buffer *buffer_info; + unsigned int i; +- uint8_t css; ++ u8 css; + +- if (likely(skb->ip_summed == CHECKSUM_HW)) { +- css = skb->h.raw - skb->data; ++ if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { ++ css = skb_transport_offset(skb); + +- i = tx_ring->next_to_use; +- context_desc = E1000_CONTEXT_DESC(*tx_ring, i); ++ i = tx_ring->next_to_use; ++ buffer_info = &tx_ring->buffer_info[i]; ++ context_desc = E1000_CONTEXT_DESC(*tx_ring, i); + ++ context_desc->lower_setup.ip_config = 0; + context_desc->upper_setup.tcp_fields.tucss = css; +- context_desc->upper_setup.tcp_fields.tucso = css + skb->csum; ++ context_desc->upper_setup.tcp_fields.tucso = ++ css + skb->csum_offset; + context_desc->upper_setup.tcp_fields.tucse = 0; + context_desc->tcp_seg_setup.data = 0; + context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT); + +- if (unlikely(++i == tx_ring->count)) { i = 0; } ++ buffer_info->time_stamp = jiffies; ++ buffer_info->next_to_watch = i; ++ ++ if (unlikely(++i == tx_ring->count)) i = 0; + tx_ring->next_to_use = i; + +- return TRUE; ++ return true; + } + +- return FALSE; ++ return false; + } + +-#define E1000_MAX_TXD_PWR 12 +-#define E1000_MAX_DATA_PER_TXD (1<len; ++ struct iegbe_hw *hw = &adapter->hw; ++ struct iegbe_buffer *buffer_info; ++ unsigned int len = skb->len; + unsigned int offset = 0, size, count = 0, i; +-#ifdef MAX_SKB_FRAGS +- unsigned int f; +- len -= skb->data_len; +-#endif ++ unsigned int f; ++ len -= skb->data_len; + +- i = tx_ring->next_to_use; ++ i = tx_ring->next_to_use; ++ ++ while(len) { ++ buffer_info = &tx_ring->buffer_info[i]; ++ size = min(len, max_per_txd); ++ /* Workaround for Controller erratum -- ++ * descriptor for non-tso packet in a linear SKB that follows a ++ * tso gets written back prematurely before the data is fully ++ * DMA'd to the controller */ ++ if (!skb->data_len && tx_ring->last_tx_tso && ++ !skb_is_gso(skb)) { ++ tx_ring->last_tx_tso = 0; ++ size -= 4; ++ } + +- while(len) { +- buffer_info = &tx_ring->buffer_info[i]; +- size = min(len, max_per_txd); +-#ifdef NETIF_F_TSO + /* Workaround for premature desc write-backs + * in TSO mode. Append 4-byte sentinel desc */ +- if(unlikely(mss && !nr_frags && size == len && size > 0x8)) { +- size -= 0x4; ++ if (unlikely(mss && !nr_frags && size == len && size > 8)) ++ size -= 4; ++ /* work-around for errata 10 and it applies ++ * to all controllers in PCI-X mode ++ * The fix is to make sure that the first descriptor of a ++ * packet is smaller than 2048 - 16 - 16 (or 2016) bytes ++ */ ++ if (unlikely((hw->bus_type == iegbe_bus_type_pcix) && ++ (size > 2015) && count == 0)) ++ size = 2015; ++ ++ /* Workaround for potential 82544 hang in PCI-X. Avoid ++ * terminating buffers within evenly-aligned dwords. */ ++ if(unlikely(adapter->pcix_82544 && ++ !((unsigned long)(skb->data + offset + size - 1) & 4) && ++ size > 4)) ++ size -= 4; ++ ++ buffer_info->length = size; ++ buffer_info->dma = ++ pci_map_single(adapter->pdev, ++ skb->data + offset, ++ size, ++ PCI_DMA_TODEVICE); ++ buffer_info->time_stamp = jiffies; ++ buffer_info->next_to_watch = i; ++ ++ len -= size; ++ offset += size; ++ count++; ++ if (unlikely(++i == tx_ring->count)) i = 0; ++ } ++ ++ for (f = 0; f < nr_frags; f++) { ++ struct skb_frag_struct *frag; ++ ++ frag = &skb_shinfo(skb)->frags[f]; ++ len = frag->size; ++ offset = frag->page_offset; ++ ++ while(len) { ++ buffer_info = &tx_ring->buffer_info[i]; ++ size = min(len, max_per_txd); ++ /* Workaround for premature desc write-backs ++ * in TSO mode. Append 4-byte sentinel desc */ ++ if (unlikely(mss && f == (nr_frags-1) && size == len && size > 8)) ++ size -= 4; ++ /* Workaround for potential 82544 hang in PCI-X. ++ * Avoid terminating buffers within evenly-aligned ++ * dwords. */ ++ if(unlikely(adapter->pcix_82544 && ++ !((unsigned long)(frag->page+offset+size-1) & 4) && ++ size > 4)) ++ size -= 4; ++ ++ buffer_info->length = size; ++ buffer_info->dma = ++ pci_map_page(adapter->pdev, ++ frag->page, ++ offset, ++ size, ++ PCI_DMA_TODEVICE); ++ buffer_info->time_stamp = jiffies; ++ buffer_info->next_to_watch = i; ++ ++ len -= size; ++ offset += size; ++ count++; ++ if (unlikely(++i == tx_ring->count)) i = 0; + } +-#endif +- /* work-around for errata 10 and it applies +- * to all controllers in PCI-X mode +- * The fix is to make sure that the first descriptor of a +- * packet is smaller than 2048 - 16 - 16 (or 2016) bytes +- */ +- if(unlikely((adapter->hw.bus_type == iegbe_bus_type_pcix) && +- (size > 0x7df) && count == 0)) { +- size = 0x7df; +- } +- /* Workaround for potential 82544 hang in PCI-X. Avoid +- * terminating buffers within evenly-aligned dwords. */ +- if(unlikely(adapter->pcix_82544 && +- !((unsigned long)(skb->data + offset + size - 0x8) & 0x4) && +- size > 0x4)) { +- size -= 0x4; +- } +- buffer_info->length = size; +- buffer_info->dma = +- pci_map_single(adapter->pdev, +- skb->data + offset, +- size, +- PCI_DMA_TODEVICE); +- buffer_info->time_stamp = jiffies; +- +- len -= size; +- offset += size; +- count++; +- if(unlikely(++i == tx_ring->count)) { i = 0; } +- } +- +-#ifdef MAX_SKB_FRAGS +- for(f = 0; f < nr_frags; f++) { +- struct skb_frag_struct *frag; +- +- frag = &skb_shinfo(skb)->frags[f]; +- len = frag->size; +- offset = frag->page_offset; +- +- while(len) { +- buffer_info = &tx_ring->buffer_info[i]; +- size = min(len, max_per_txd); +-#ifdef NETIF_F_TSO +- /* Workaround for premature desc write-backs +- * in TSO mode. Append 4-byte sentinel desc */ +- if(unlikely(mss && f == (nr_frags-0x1) && +- size == len && size > 0x8)) { +- size -= 0x4; +- } +-#endif +- /* Workaround for potential 82544 hang in PCI-X. +- * Avoid terminating buffers within evenly-aligned +- * dwords. */ +- if(unlikely(adapter->pcix_82544 && +- !((unsigned long)(frag->page+offset+size-0x1) & 0x4) && +- size > 0x4)) { +- size -= 0x4; +- } +- buffer_info->length = size; +- buffer_info->dma = +- pci_map_page(adapter->pdev, +- frag->page, +- offset, +- size, +- PCI_DMA_TODEVICE); +- buffer_info->time_stamp = jiffies; +- +- len -= size; +- offset += size; +- count++; +- if(unlikely(++i == tx_ring->count)) { i = 0; } +- } +- } +-#endif ++ } + +- i = (i == 0) ? tx_ring->count - 0x1 : i - 0x1; +- tx_ring->buffer_info[i].skb = skb; +- tx_ring->buffer_info[first].next_to_watch = i; ++ i = (i == 0) ? tx_ring->count - 1 : i - 1; ++ tx_ring->buffer_info[i].skb = skb; ++ tx_ring->buffer_info[first].next_to_watch = i; + +- return count; ++ return count; + } + +-static inline void +-iegbe_tx_queue(struct iegbe_adapter *adapter, struct iegbe_tx_ring *tx_ring, +- int tx_flags, int count) ++static void iegbe_tx_queue(struct iegbe_adapter *adapter, ++ struct iegbe_tx_ring *tx_ring, int tx_flags, ++ int count) + { ++ struct iegbe_hw *hw = &adapter->hw; + struct iegbe_tx_desc *tx_desc = NULL; + struct iegbe_buffer *buffer_info; +- uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS; ++ u32 txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS; + unsigned int i; + +- if(likely(tx_flags & E1000_TX_FLAGS_TSO)) { ++ if (likely(tx_flags & E1000_TX_FLAGS_TSO)) { + txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D | + E1000_TXD_CMD_TSE; +- txd_upper |= E1000_TXD_POPTS_TXSM << 0x8; ++ txd_upper |= E1000_TXD_POPTS_TXSM << 8; + +- if(likely(tx_flags & E1000_TX_FLAGS_IPV4)) { +- txd_upper |= E1000_TXD_POPTS_IXSM << 0x8; +- } ++ if (likely(tx_flags & E1000_TX_FLAGS_IPV4)) ++ txd_upper |= E1000_TXD_POPTS_IXSM << 8; + } + +- if(likely(tx_flags & E1000_TX_FLAGS_CSUM)) { ++ if (likely(tx_flags & E1000_TX_FLAGS_CSUM)) { + txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; +- txd_upper |= E1000_TXD_POPTS_TXSM << 0x8; +- } +- +- if(unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) { +- txd_lower |= E1000_TXD_CMD_VLE; +- txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK); ++ txd_upper |= E1000_TXD_POPTS_TXSM << 8; + } + +- i = tx_ring->next_to_use; ++ if(unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) { ++ txd_lower |= E1000_TXD_CMD_VLE; ++ txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK); ++ } + +- while(count--) { +- buffer_info = &tx_ring->buffer_info[i]; +- tx_desc = E1000_TX_DESC(*tx_ring, i); +- tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); +- tx_desc->lower.data = +- cpu_to_le32(txd_lower | buffer_info->length); +- tx_desc->upper.data = cpu_to_le32(txd_upper); +- if(unlikely(++i == tx_ring->count)) { i = 0; } +- } +- if(tx_desc != NULL) { +- tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd); +- } +- /* Force memory writes to complete before letting h/w +- * know there are new descriptors to fetch. (Only +- * applicable for weak-ordered memory model archs, +- * such as IA-64). */ +- wmb(); ++ i = tx_ring->next_to_use; + +- tx_ring->next_to_use = i; +- writel(i, adapter->hw.hw_addr + tx_ring->tdt); ++ while(count--) { ++ buffer_info = &tx_ring->buffer_info[i]; ++ tx_desc = E1000_TX_DESC(*tx_ring, i); ++ tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); ++ tx_desc->lower.data = ++ cpu_to_le32(txd_lower | buffer_info->length); ++ tx_desc->upper.data = cpu_to_le32(txd_upper); ++ if (unlikely(++i == tx_ring->count)) i = 0; ++ } ++ ++ tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd); ++ ++ /* Force memory writes to complete before letting h/w ++ * know there are new descriptors to fetch. (Only ++ * applicable for weak-ordered memory model archs, ++ * such as IA-64). */ ++ wmb(); ++ ++ tx_ring->next_to_use = i; ++ writel(i, hw->hw_addr + tx_ring->tdt); ++ /* we need this if more than one processor can write to our tail ++ * at a time, it syncronizes IO on IA64/Altix systems */ ++ mmiowb(); + } + + /** +@@ -2950,113 +2925,132 @@ iegbe_tx_queue(struct iegbe_adapter *ada + * to the beginning of the Tx FIFO. + **/ + +-static inline int +-iegbe_82547_fifo_workaround(struct iegbe_adapter *adapter, struct sk_buff *skb) ++#define E1000_FIFO_HDR 0x10 ++#define E1000_82547_PAD_LEN 0x3E0 ++static int iegbe_82547_fifo_workaround(struct iegbe_adapter *adapter, ++ struct sk_buff *skb) + { +- uint32_t fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head; +- uint32_t skb_fifo_len = skb->len + E1000_FIFO_HDR; ++ u32 fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head; ++ u32 skb_fifo_len = skb->len + E1000_FIFO_HDR; + +- E1000_ROUNDUP(skb_fifo_len, E1000_FIFO_HDR); ++ skb_fifo_len = ALIGN(skb_fifo_len, E1000_FIFO_HDR); + +- if(adapter->link_duplex != HALF_DUPLEX) { +- goto no_fifo_stall_required; +- } +- if(atomic_read(&adapter->tx_fifo_stall)) { +- return 1; ++ if (adapter->link_duplex != HALF_DUPLEX) ++ goto no_fifo_stall_required; ++ ++ if (atomic_read(&adapter->tx_fifo_stall)) ++ return 1; ++ ++ if(skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) { ++ atomic_set(&adapter->tx_fifo_stall, 1); ++ return 1; + } +- if(skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) { +- atomic_set(&adapter->tx_fifo_stall, 0x1); +- return 1; +- } + + no_fifo_stall_required: +- adapter->tx_fifo_head += skb_fifo_len; +- if(adapter->tx_fifo_head >= adapter->tx_fifo_size) { +- adapter->tx_fifo_head -= adapter->tx_fifo_size; +- } ++ adapter->tx_fifo_head += skb_fifo_len; ++ if (adapter->tx_fifo_head >= adapter->tx_fifo_size) ++ adapter->tx_fifo_head -= adapter->tx_fifo_size; + return 0; + } + +-static inline int +-iegbe_transfer_dhcp_info(struct iegbe_adapter *adapter, struct sk_buff *skb) ++#define MINIMUM_DHCP_PACKET_SIZE 282 ++static int iegbe_transfer_dhcp_info(struct iegbe_adapter *adapter, ++ struct sk_buff *skb) + { + struct iegbe_hw *hw = &adapter->hw; +- uint16_t length, offset; +-#ifdef NETIF_F_HW_VLAN_TX +- if(vlan_tx_tag_present(skb)) { +- if(!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) && +- ( adapter->hw.mng_cookie.status & +- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) ) { ++ u16 length, offset; ++ if (vlan_tx_tag_present(skb)) { ++ if (!((vlan_tx_tag_get(skb) == hw->mng_cookie.vlan_id) && ++ ( hw->mng_cookie.status & ++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) ) + return 0; + } +- } +-#endif +- if(htons(ETH_P_IP) == skb->protocol) { +- const struct iphdr *ip = skb->nh.iph; +- if(IPPROTO_UDP == ip->protocol) { +- struct udphdr *udp = (struct udphdr *)(skb->h.uh); +- if(ntohs(udp->dest) == 0x43) { /* 0x43 = 67 */ +- offset = (uint8_t *)udp + 0x8 - skb->data; +- length = skb->len - offset; +- +- return iegbe_mng_write_dhcp_info(hw, +- (uint8_t *)udp + 0x8, length); +- } +- } +- } else if((skb->len > MINIMUM_DHCP_PACKET_SIZE) && (!skb->protocol)) { +- struct ethhdr *eth = (struct ethhdr *) skb->data; +- if((htons(ETH_P_IP) == eth->h_proto)) { ++ if (skb->len > MINIMUM_DHCP_PACKET_SIZE) { ++ struct ethhdr *eth = (struct ethhdr *)skb->data; ++ if ((htons(ETH_P_IP) == eth->h_proto)) { + const struct iphdr *ip = +- (struct iphdr *)((uint8_t *)skb->data+0xe); +- if(IPPROTO_UDP == ip->protocol) { ++ (struct iphdr *)((u8 *)skb->data+14); ++ if (IPPROTO_UDP == ip->protocol) { + struct udphdr *udp = +- (struct udphdr *)((uint8_t *)ip + +- (ip->ihl << 0x2)); +- if(ntohs(udp->dest) == 0x43) { +- offset = (uint8_t *)udp + 0x8 - skb->data; ++ (struct udphdr *)((u8 *)ip + ++ (ip->ihl << 2)); ++ if (ntohs(udp->dest) == 67) { ++ offset = (u8 *)udp + 8 - skb->data; + length = skb->len - offset; + + return iegbe_mng_write_dhcp_info(hw, +- (uint8_t *)udp + 0x8, ++ (u8 *)udp + 8, + length); +- } ++ } + } + } + } + return 0; + } + +-static int +-iegbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ++static int __iegbe_maybe_stop_tx(struct net_device *netdev, int size) ++{ ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_tx_ring *tx_ring = adapter->tx_ring; ++ ++ netif_stop_queue(netdev); ++ /* Herbert's original patch had: ++ * smp_mb__after_netif_stop_queue(); ++ * but since that doesn't exist yet, just open code it. */ ++ smp_mb(); ++ ++ /* We need to check again in a case another CPU has just ++ * made room available. */ ++ if (likely(E1000_DESC_UNUSED(tx_ring) < size)) ++ return -EBUSY; ++ ++ /* A reprieve! */ ++ netif_start_queue(netdev); ++ ++adapter->restart_queue; ++ return 0; ++} ++ ++static int iegbe_maybe_stop_tx(struct net_device *netdev, ++ struct iegbe_tx_ring *tx_ring, int size) ++{ ++ if (likely(E1000_DESC_UNUSED(tx_ring) >= size)) ++ return 0; ++ return __iegbe_maybe_stop_tx(netdev, size); ++} ++ ++#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 ) ++static int iegbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) + { + struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_hw *hw = &adapter->hw; + struct iegbe_tx_ring *tx_ring; + unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD; + unsigned int max_txd_pwr = E1000_MAX_TXD_PWR; + unsigned int tx_flags = 0; +- unsigned int len = skb->len; ++ unsigned int len = skb->len - skb->data_len; + unsigned long flags = 0; +- unsigned int nr_frags = 0; +- unsigned int mss = 0; ++ unsigned int nr_frags; ++ unsigned int mss; + int count = 0; +- int tso; +-#ifdef MAX_SKB_FRAGS ++ int tso; + unsigned int f; +- len -= skb->data_len; +-#endif + +-#ifdef CONFIG_E1000_MQ +- tx_ring = *per_cpu_ptr(adapter->cpu_tx_ring, smp_processor_id()); +-#else ++ /* This goes back to the question of how to logically map a tx queue ++ * to a flow. Right now, performance is impacted slightly negatively ++ * if using multiple tx queues. If the stack breaks away from a ++ * single qdisc implementation, we can look at this again. */ + tx_ring = adapter->tx_ring; +-#endif + + if (unlikely(skb->len <= 0)) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + +-#ifdef NETIF_F_TSO ++ /* 82571 and newer doesn't need the workaround that limited descriptor ++ * length to 4kB */ ++ if (hw->mac_type >= iegbe_82571) ++ max_per_txd = 8192; ++ + mss = skb_shinfo(skb)->gso_size; + /* The controller does a simple calculation to + * make sure there is enough room in the FIFO before +@@ -3064,164 +3058,150 @@ iegbe_xmit_frame(struct sk_buff *skb, st + * 4 = ceil(buffer len/mss). To make sure we don't + * overrun the FIFO, adjust the max buffer len if mss + * drops. */ +- if(mss) { +- max_per_txd = min(mss << 0x2, max_per_txd); +- max_txd_pwr = fls(max_per_txd) - 0x1; ++ if (mss) { ++ u8 hdr_len; ++ max_per_txd = min(mss << 2, max_per_txd); ++ max_txd_pwr = fls(max_per_txd) - 1; ++ ++ /* TSO Workaround for 82571/2/3 Controllers -- if skb->data ++ * points to just header, pull a few bytes of payload from ++ * frags into skb->data */ ++ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); ++ if (skb->data_len && hdr_len == len) { ++ switch (hw->mac_type) { ++ case iegbe_82544: ++ /* Make sure we have room to chop off 4 bytes, ++ * and that the end alignment will work out to ++ * this hardware's requirements ++ * NOTE: this is a TSO only workaround ++ * if end byte alignment not correct move us ++ * into the next dword */ ++ break; ++ /* fall through */ ++ case iegbe_82571: ++ case iegbe_82572: ++ case iegbe_82573: ++ break; ++ default: ++ /* do nothing */ ++ break; ++ } ++ } + } + +- if((mss) || (skb->ip_summed == CHECKSUM_HW)) { ++ /* reserve a descriptor for the offload context */ ++ if ((mss) || (skb->ip_summed == CHECKSUM_PARTIAL)) + count++; +- } + count++; +-#else +- if(skb->ip_summed == CHECKSUM_HW) { ++ ++ /* Controller Erratum workaround */ ++ if (!skb->data_len && tx_ring->last_tx_tso && !skb_is_gso(skb)) + count++; +- { +-#endif ++ + count += TXD_USE_COUNT(len, max_txd_pwr); + +- if(adapter->pcix_82544) { ++ if (adapter->pcix_82544) + count++; +- } ++ + /* work-around for errata 10 and it applies to all controllers + * in PCI-X mode, so add one more descriptor to the count + */ +- if(unlikely((adapter->hw.bus_type == iegbe_bus_type_pcix) && +- (len > 0x7df))) { ++ if (unlikely((hw->bus_type == iegbe_bus_type_pcix) && ++ (len > 2015))) + count++; +- } +-#ifdef MAX_SKB_FRAGS ++ + nr_frags = skb_shinfo(skb)->nr_frags; +- for(f = 0; f < nr_frags; f++) ++ for (f = 0; f < nr_frags; f++) + count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size, + max_txd_pwr); +- if(adapter->pcix_82544) { ++ if (adapter->pcix_82544) + count += nr_frags; +- } +-#ifdef NETIF_F_TSO +- /* TSO Workaround for 82571/2 Controllers -- if skb->data +- * points to just header, pull a few bytes of payload from +- * frags into skb->data */ +- if (skb_is_gso(skb)) { +- uint8_t hdr_len; +- hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 0x2)); +- if (skb->data_len && (hdr_len < (skb->len - skb->data_len)) && +- (adapter->hw.mac_type == iegbe_82571 || +- adapter->hw.mac_type == iegbe_82572)) { +- unsigned int pull_size; +- pull_size = min((unsigned int)0x4, skb->data_len); +- if (!__pskb_pull_tail(skb, pull_size)) { +- printk(KERN_ERR "__pskb_pull_tail failed.\n"); +- dev_kfree_skb_any(skb); +- return -EFAULT; +- } +- } +- } +-#endif +-#endif + +- if(adapter->hw.tx_pkt_filtering && (adapter->hw.mac_type == iegbe_82573) ) { ++ ++ if (hw->tx_pkt_filtering && ++ (hw->mac_type == iegbe_82573)) + iegbe_transfer_dhcp_info(adapter, skb); +- } +-#ifdef NETIF_F_LLTX +- local_irq_save(flags); +- if (!spin_trylock(&tx_ring->tx_lock)) { ++ ++ if (!spin_trylock_irqsave(&tx_ring->tx_lock, flags)) + /* Collision - tell upper layer to requeue */ +- local_irq_restore(flags); + return NETDEV_TX_LOCKED; +- } +-#else +- spin_lock_irqsave(&tx_ring->tx_lock, flags); +-#endif + + /* need: count + 2 desc gap to keep tail from touching + * head, otherwise try next time */ +- if (unlikely(E1000_DESC_UNUSED(tx_ring) < count + 0x2)) { +- netif_stop_queue(netdev); ++ if (unlikely(iegbe_maybe_stop_tx(netdev, tx_ring, count + 2))) { + spin_unlock_irqrestore(&tx_ring->tx_lock, flags); + return NETDEV_TX_BUSY; + } + +- if(unlikely(adapter->hw.mac_type == iegbe_82547)) { +- if(unlikely(iegbe_82547_fifo_workaround(adapter, skb))) { ++ if (unlikely(hw->mac_type == iegbe_82547)) { ++ if (unlikely(iegbe_82547_fifo_workaround(adapter, skb))) { + netif_stop_queue(netdev); +- mod_timer(&adapter->tx_fifo_stall_timer, jiffies); ++ mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1); + spin_unlock_irqrestore(&tx_ring->tx_lock, flags); + return NETDEV_TX_BUSY; + } + } + +-#ifndef NETIF_F_LLTX +- spin_unlock_irqrestore(&tx_ring->tx_lock, flags); +-#endif +- +-#ifdef NETIF_F_HW_VLAN_TX +- if(unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) { ++ if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) { + tx_flags |= E1000_TX_FLAGS_VLAN; + tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT); + } +-#endif + + first = tx_ring->next_to_use; + + tso = iegbe_tso(adapter, tx_ring, skb); + if (tso < 0) { + dev_kfree_skb_any(skb); +-#ifdef NETIF_F_LLTX + spin_unlock_irqrestore(&tx_ring->tx_lock, flags); +-#endif + return NETDEV_TX_OK; + } + +- if (likely(tso)) { ++ if (likely(tso)) { ++ tx_ring->last_tx_tso = 1; + tx_flags |= E1000_TX_FLAGS_TSO; +- } else if (likely(iegbe_tx_csum(adapter, tx_ring, skb))) { ++ } else if (likely(iegbe_tx_csum(adapter, tx_ring, skb))) + tx_flags |= E1000_TX_FLAGS_CSUM; +- } ++ + /* Old method was to assume IPv4 packet by default if TSO was enabled. + * 82571 hardware supports TSO capabilities for IPv6 as well... + * no longer assume, we must. */ +- if (likely(skb->protocol == ntohs(ETH_P_IP))) { ++ if (likely(skb->protocol == htons(ETH_P_IP))) + tx_flags |= E1000_TX_FLAGS_IPV4; +- } ++ + iegbe_tx_queue(adapter, tx_ring, tx_flags, + iegbe_tx_map(adapter, tx_ring, skb, first, + max_per_txd, nr_frags, mss)); + + netdev->trans_start = jiffies; + +-#ifdef NETIF_F_LLTX + /* Make sure there is space in the ring for the next send. */ +- if (unlikely(E1000_DESC_UNUSED(tx_ring) < MAX_SKB_FRAGS + 0x2)) { +- netif_stop_queue(netdev); +- } +- spin_unlock_irqrestore(&tx_ring->tx_lock, flags); +-#endif ++ iegbe_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2); + ++ spin_unlock_irqrestore(&tx_ring->tx_lock, flags); + return NETDEV_TX_OK; + } + ++ + /** + * iegbe_tx_timeout - Respond to a Tx Hang + * @netdev: network interface device structure + **/ + +-static void +-iegbe_tx_timeout(struct net_device *netdev) ++static void iegbe_tx_timeout(struct net_device *netdev) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); + +- /* Do the reset outside of interrupt context */ +- schedule_work(&adapter->tx_timeout_task); ++ /* Do the reset outside of interrupt context */ ++ adapter->tx_timeout_count++; ++ schedule_work(&adapter->reset_task); + } + +-static void +-iegbe_tx_timeout_task(struct net_device *netdev) ++static void iegbe_reset_task(struct work_struct *work) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_adapter *adapter = ++ container_of(work, struct iegbe_adapter, reset_task); + +- iegbe_down(adapter); +- iegbe_up(adapter); ++ iegbe_reinit_locked(adapter); + } + + /** +@@ -3232,13 +3212,12 @@ iegbe_tx_timeout_task(struct net_device + * The statistics are actually updated from the timer callback. + **/ + +-static struct net_device_stats * +-iegbe_get_stats(struct net_device *netdev) ++static struct net_device_stats *iegbe_get_stats(struct net_device *netdev) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); + +- iegbe_update_stats(adapter); +- return &adapter->net_stats; ++ /* only return the current stats */ ++ return &adapter->net_stats; + } + + /** +@@ -3249,67 +3228,55 @@ iegbe_get_stats(struct net_device *netde + * Returns 0 on success, negative on failure + **/ + +-static int +-iegbe_change_mtu(struct net_device *netdev, int new_mtu) ++static int iegbe_change_mtu(struct net_device *netdev, int new_mtu) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_hw *hw = &adapter->hw; ++ int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; + +- if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || +- (max_frame > MAX_JUMBO_FRAME_SIZE)) { +- DPRINTK(PROBE, ERR, "Invalid MTU setting\n"); +- return -EINVAL; +- } ++ if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || ++ (max_frame > MAX_JUMBO_FRAME_SIZE)) { ++ DPRINTK(PROBE, ERR, "Invalid MTU setting\n"); ++ return -EINVAL; ++ } + ++ /* Adapter-specific max frame size limits. */ ++ switch (hw->mac_type) { ++ case iegbe_undefined ... iegbe_82542_rev2_1: ++ if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) { ++ DPRINTK(PROBE, ERR, "Jumbo Frames not supported.\n"); ++ return -EINVAL; ++ } ++ break; ++ case iegbe_82571: ++ case iegbe_82572: + #define MAX_STD_JUMBO_FRAME_SIZE 9234 +- /* might want this to be bigger enum check... */ +- /* 82571 controllers limit jumbo frame size to 10500 bytes */ +- if ((adapter->hw.mac_type == iegbe_82571 || +- adapter->hw.mac_type == iegbe_82572) && +- max_frame > MAX_STD_JUMBO_FRAME_SIZE) { +- DPRINTK(PROBE, ERR, "MTU > 9216 bytes not supported " +- "on 82571 and 82572 controllers.\n"); +- return -EINVAL; +- } +- +- if(adapter->hw.mac_type == iegbe_82573 && +- max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) { +- DPRINTK(PROBE, ERR, "Jumbo Frames not supported " +- "on 82573\n"); +- return -EINVAL; +- } +- +- if(adapter->hw.mac_type > iegbe_82547_rev_2) { +- adapter->rx_buffer_len = max_frame; +- E1000_ROUNDUP(adapter->rx_buffer_len, 0x1024); +- } else { +- if(unlikely((adapter->hw.mac_type < iegbe_82543) && +- (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE))) { +- DPRINTK(PROBE, ERR, "Jumbo Frames not supported " +- "on 82542\n"); +- return -EINVAL; +- +- } else { +- if(max_frame <= E1000_RXBUFFER_2048) { +- adapter->rx_buffer_len = E1000_RXBUFFER_2048; +- } else if(max_frame <= E1000_RXBUFFER_4096) { +- adapter->rx_buffer_len = E1000_RXBUFFER_4096; +- } else if(max_frame <= E1000_RXBUFFER_8192) { +- adapter->rx_buffer_len = E1000_RXBUFFER_8192; +- } else if(max_frame <= E1000_RXBUFFER_16384) { +- adapter->rx_buffer_len = E1000_RXBUFFER_16384; +- } ++ if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) { ++ DPRINTK(PROBE, ERR, "MTU > 9216 not supported.\n"); ++ return -EINVAL; + } ++ break; ++ default: ++ break; + } ++ if (max_frame <= E1000_RXBUFFER_256) ++ adapter->rx_buffer_len = E1000_RXBUFFER_256; ++ else if (max_frame <= E1000_RXBUFFER_2048) ++ adapter->rx_buffer_len = E1000_RXBUFFER_2048; ++ else if (max_frame <= E1000_RXBUFFER_4096) ++ adapter->rx_buffer_len = E1000_RXBUFFER_4096; ++ else if (max_frame <= E1000_RXBUFFER_8192) ++ adapter->rx_buffer_len = E1000_RXBUFFER_8192; ++ else if (max_frame <= E1000_RXBUFFER_16384) ++ adapter->rx_buffer_len = E1000_RXBUFFER_16384; + +- netdev->mtu = new_mtu; ++ /* adjust allocation if LPE protects us, and we aren't using SBP */ + +- if(netif_running(netdev)) { +- iegbe_down(adapter); +- iegbe_up(adapter); +- } ++ netdev->mtu = new_mtu; ++ hw->max_frame_size = max_frame; + +- adapter->hw.max_frame_size = max_frame; ++ if (netif_running(netdev)) ++ iegbe_reinit_locked(adapter); + + return 0; + } +@@ -3319,224 +3286,189 @@ iegbe_change_mtu(struct net_device *netd + * @adapter: board private structure + **/ + +-void +-iegbe_update_stats(struct iegbe_adapter *adapter) ++void iegbe_update_stats(struct iegbe_adapter *adapter) + { +- struct iegbe_hw *hw = &adapter->hw; +- unsigned long flags = 0; +- uint16_t phy_tmp; ++ struct iegbe_hw *hw = &adapter->hw; ++ unsigned long flags = 0x0; ++ uint16_t phy_tmp; + + #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF + +- spin_lock_irqsave(&adapter->stats_lock, flags); ++ spin_lock_irqsave(&adapter->stats_lock, flags); + +- /* these counters are modified from iegbe_adjust_tbi_stats, +- * called from the interrupt context, so they must only +- * be written while holding adapter->stats_lock +- */ ++ /* these counters are modified from iegbe_adjust_tbi_stats, ++ * called from the interrupt context, so they must only ++ * be written while holding adapter->stats_lock ++ */ + +- adapter->stats.crcerrs += E1000_READ_REG(hw, CRCERRS); +- adapter->stats.gprc += E1000_READ_REG(hw, GPRC); +- adapter->stats.gorcl += E1000_READ_REG(hw, GORCL); +- adapter->stats.gorch += E1000_READ_REG(hw, GORCH); +- adapter->stats.bprc += E1000_READ_REG(hw, BPRC); +- adapter->stats.mprc += E1000_READ_REG(hw, MPRC); +- adapter->stats.roc += E1000_READ_REG(hw, ROC); +- adapter->stats.prc64 += E1000_READ_REG(hw, PRC64); +- adapter->stats.prc127 += E1000_READ_REG(hw, PRC127); +- adapter->stats.prc255 += E1000_READ_REG(hw, PRC255); +- adapter->stats.prc511 += E1000_READ_REG(hw, PRC511); +- adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023); +- adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522); +- +- adapter->stats.symerrs += E1000_READ_REG(hw, SYMERRS); +- adapter->stats.mpc += E1000_READ_REG(hw, MPC); +- adapter->stats.scc += E1000_READ_REG(hw, SCC); +- adapter->stats.ecol += E1000_READ_REG(hw, ECOL); +- adapter->stats.mcc += E1000_READ_REG(hw, MCC); +- adapter->stats.latecol += E1000_READ_REG(hw, LATECOL); +- adapter->stats.dc += E1000_READ_REG(hw, DC); +- adapter->stats.sec += E1000_READ_REG(hw, SEC); +- adapter->stats.rlec += E1000_READ_REG(hw, RLEC); +- adapter->stats.xonrxc += E1000_READ_REG(hw, XONRXC); +- adapter->stats.xontxc += E1000_READ_REG(hw, XONTXC); +- adapter->stats.xoffrxc += E1000_READ_REG(hw, XOFFRXC); +- adapter->stats.xofftxc += E1000_READ_REG(hw, XOFFTXC); +- adapter->stats.fcruc += E1000_READ_REG(hw, FCRUC); +- adapter->stats.gptc += E1000_READ_REG(hw, GPTC); +- adapter->stats.gotcl += E1000_READ_REG(hw, GOTCL); +- adapter->stats.gotch += E1000_READ_REG(hw, GOTCH); +- adapter->stats.rnbc += E1000_READ_REG(hw, RNBC); +- adapter->stats.ruc += E1000_READ_REG(hw, RUC); +- adapter->stats.rfc += E1000_READ_REG(hw, RFC); +- adapter->stats.rjc += E1000_READ_REG(hw, RJC); +- adapter->stats.torl += E1000_READ_REG(hw, TORL); +- adapter->stats.torh += E1000_READ_REG(hw, TORH); +- adapter->stats.totl += E1000_READ_REG(hw, TOTL); +- adapter->stats.toth += E1000_READ_REG(hw, TOTH); +- adapter->stats.tpr += E1000_READ_REG(hw, TPR); +- adapter->stats.ptc64 += E1000_READ_REG(hw, PTC64); +- adapter->stats.ptc127 += E1000_READ_REG(hw, PTC127); +- adapter->stats.ptc255 += E1000_READ_REG(hw, PTC255); +- adapter->stats.ptc511 += E1000_READ_REG(hw, PTC511); +- adapter->stats.ptc1023 += E1000_READ_REG(hw, PTC1023); +- adapter->stats.ptc1522 += E1000_READ_REG(hw, PTC1522); +- adapter->stats.mptc += E1000_READ_REG(hw, MPTC); +- adapter->stats.bptc += E1000_READ_REG(hw, BPTC); +- +- /* used for adaptive IFS */ +- +- hw->tx_packet_delta = E1000_READ_REG(hw, TPT); +- adapter->stats.tpt += hw->tx_packet_delta; +- hw->collision_delta = E1000_READ_REG(hw, COLC); +- adapter->stats.colc += hw->collision_delta; +- +- if(hw->mac_type >= iegbe_82543) { +- adapter->stats.algnerrc += E1000_READ_REG(hw, ALGNERRC); +- adapter->stats.rxerrc += E1000_READ_REG(hw, RXERRC); +- adapter->stats.tncrs += E1000_READ_REG(hw, TNCRS); +- adapter->stats.cexterr += E1000_READ_REG(hw, CEXTERR); +- adapter->stats.tsctc += E1000_READ_REG(hw, TSCTC); +- adapter->stats.tsctfc += E1000_READ_REG(hw, TSCTFC); +- } +- if(hw->mac_type > iegbe_82547_rev_2) { +- adapter->stats.iac += E1000_READ_REG(hw, IAC); +- adapter->stats.icrxoc += E1000_READ_REG(hw, ICRXOC); +- adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC); +- adapter->stats.icrxatc += E1000_READ_REG(hw, ICRXATC); +- adapter->stats.ictxptc += E1000_READ_REG(hw, ICTXPTC); +- adapter->stats.ictxatc += E1000_READ_REG(hw, ICTXATC); +- adapter->stats.ictxqec += E1000_READ_REG(hw, ICTXQEC); +- adapter->stats.ictxqmtc += E1000_READ_REG(hw, ICTXQMTC); +- adapter->stats.icrxdmtc += E1000_READ_REG(hw, ICRXDMTC); +- } +- +- /* Fill out the OS statistics structure */ +- +- adapter->net_stats.rx_packets = adapter->stats.gprc; +- adapter->net_stats.tx_packets = adapter->stats.gptc; +- adapter->net_stats.rx_bytes = adapter->stats.gorcl; +- adapter->net_stats.tx_bytes = adapter->stats.gotcl; +- adapter->net_stats.multicast = adapter->stats.mprc; +- adapter->net_stats.collisions = adapter->stats.colc; +- +- /* Rx Errors */ +- +- adapter->net_stats.rx_errors = adapter->stats.rxerrc + +- adapter->stats.crcerrs + adapter->stats.algnerrc + +- adapter->stats.rlec + adapter->stats.mpc + +- adapter->stats.cexterr; +- adapter->net_stats.rx_dropped = adapter->stats.mpc; +- adapter->net_stats.rx_length_errors = adapter->stats.rlec; +- adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs; +- adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc; +- adapter->net_stats.rx_fifo_errors = adapter->stats.mpc; +- adapter->net_stats.rx_missed_errors = adapter->stats.mpc; +- +- /* Tx Errors */ +- +- adapter->net_stats.tx_errors = adapter->stats.ecol + +- adapter->stats.latecol; +- adapter->net_stats.tx_aborted_errors = adapter->stats.ecol; +- adapter->net_stats.tx_window_errors = adapter->stats.latecol; +- adapter->net_stats.tx_carrier_errors = adapter->stats.tncrs; ++ adapter->stats.crcerrs += E1000_READ_REG(hw, CRCERRS); ++ adapter->stats.gprc += E1000_READ_REG(hw, GPRC); ++ adapter->stats.gorcl += E1000_READ_REG(hw, GORCL); ++ adapter->stats.gorch += E1000_READ_REG(hw, GORCH); ++ adapter->stats.bprc += E1000_READ_REG(hw, BPRC); ++ adapter->stats.mprc += E1000_READ_REG(hw, MPRC); ++ adapter->stats.roc += E1000_READ_REG(hw, ROC); ++ adapter->stats.prc64 += E1000_READ_REG(hw, PRC64); ++ adapter->stats.prc127 += E1000_READ_REG(hw, PRC127); ++ adapter->stats.prc255 += E1000_READ_REG(hw, PRC255); ++ adapter->stats.prc511 += E1000_READ_REG(hw, PRC511); ++ adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023); ++ adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522); ++ ++ adapter->stats.symerrs += E1000_READ_REG(hw, SYMERRS); ++ adapter->stats.mpc += E1000_READ_REG(hw, MPC); ++ adapter->stats.scc += E1000_READ_REG(hw, SCC); ++ adapter->stats.ecol += E1000_READ_REG(hw, ECOL); ++ adapter->stats.mcc += E1000_READ_REG(hw, MCC); ++ adapter->stats.latecol += E1000_READ_REG(hw, LATECOL); ++ adapter->stats.dc += E1000_READ_REG(hw, DC); ++ adapter->stats.sec += E1000_READ_REG(hw, SEC); ++ adapter->stats.rlec += E1000_READ_REG(hw, RLEC); ++ adapter->stats.xonrxc += E1000_READ_REG(hw, XONRXC); ++ adapter->stats.xontxc += E1000_READ_REG(hw, XONTXC); ++ adapter->stats.xoffrxc += E1000_READ_REG(hw, XOFFRXC); ++ adapter->stats.xofftxc += E1000_READ_REG(hw, XOFFTXC); ++ adapter->stats.fcruc += E1000_READ_REG(hw, FCRUC); ++ adapter->stats.gptc += E1000_READ_REG(hw, GPTC); ++ adapter->stats.gotcl += E1000_READ_REG(hw, GOTCL); ++ adapter->stats.gotch += E1000_READ_REG(hw, GOTCH); ++ adapter->stats.rnbc += E1000_READ_REG(hw, RNBC); ++ adapter->stats.ruc += E1000_READ_REG(hw, RUC); ++ adapter->stats.rfc += E1000_READ_REG(hw, RFC); ++ adapter->stats.rjc += E1000_READ_REG(hw, RJC); ++ adapter->stats.torl += E1000_READ_REG(hw, TORL); ++ adapter->stats.torh += E1000_READ_REG(hw, TORH); ++ adapter->stats.totl += E1000_READ_REG(hw, TOTL); ++ adapter->stats.toth += E1000_READ_REG(hw, TOTH); ++ adapter->stats.tpr += E1000_READ_REG(hw, TPR); ++ adapter->stats.ptc64 += E1000_READ_REG(hw, PTC64); ++ adapter->stats.ptc127 += E1000_READ_REG(hw, PTC127); ++ adapter->stats.ptc255 += E1000_READ_REG(hw, PTC255); ++ adapter->stats.ptc511 += E1000_READ_REG(hw, PTC511); ++ adapter->stats.ptc1023 += E1000_READ_REG(hw, PTC1023); ++ adapter->stats.ptc1522 += E1000_READ_REG(hw, PTC1522); ++ adapter->stats.mptc += E1000_READ_REG(hw, MPTC); ++ adapter->stats.bptc += E1000_READ_REG(hw, BPTC); ++ ++ /* used for adaptive IFS */ ++ ++ hw->tx_packet_delta = E1000_READ_REG(hw, TPT); ++ adapter->stats.tpt += hw->tx_packet_delta; ++ hw->collision_delta = E1000_READ_REG(hw, COLC); ++ adapter->stats.colc += hw->collision_delta; ++ ++ if(hw->mac_type >= iegbe_82543) { ++ adapter->stats.algnerrc += E1000_READ_REG(hw, ALGNERRC); ++ adapter->stats.rxerrc += E1000_READ_REG(hw, RXERRC); ++ adapter->stats.tncrs += E1000_READ_REG(hw, TNCRS); ++ adapter->stats.cexterr += E1000_READ_REG(hw, CEXTERR); ++ adapter->stats.tsctc += E1000_READ_REG(hw, TSCTC); ++ adapter->stats.tsctfc += E1000_READ_REG(hw, TSCTFC); ++ } ++ if(hw->mac_type > iegbe_82547_rev_2) { ++ adapter->stats.iac += E1000_READ_REG(hw, IAC); ++ adapter->stats.icrxoc += E1000_READ_REG(hw, ICRXOC); ++ adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC); ++ adapter->stats.icrxatc += E1000_READ_REG(hw, ICRXATC); ++ adapter->stats.ictxptc += E1000_READ_REG(hw, ICTXPTC); ++ adapter->stats.ictxatc += E1000_READ_REG(hw, ICTXATC); ++ adapter->stats.ictxqec += E1000_READ_REG(hw, ICTXQEC); ++ adapter->stats.ictxqmtc += E1000_READ_REG(hw, ICTXQMTC); ++ adapter->stats.icrxdmtc += E1000_READ_REG(hw, ICRXDMTC); ++ } ++ ++ /* Fill out the OS statistics structure */ ++ ++ adapter->net_stats.rx_packets = adapter->stats.gprc; ++ adapter->net_stats.tx_packets = adapter->stats.gptc; ++ adapter->net_stats.rx_bytes = adapter->stats.gorcl; ++ adapter->net_stats.tx_bytes = adapter->stats.gotcl; ++ adapter->net_stats.multicast = adapter->stats.mprc; ++ adapter->net_stats.collisions = adapter->stats.colc; ++ ++ /* Rx Errors */ ++ ++ adapter->net_stats.rx_errors = adapter->stats.rxerrc + ++ adapter->stats.crcerrs + adapter->stats.algnerrc + ++ adapter->stats.rlec + adapter->stats.mpc + ++ adapter->stats.cexterr; ++ adapter->net_stats.rx_dropped = adapter->stats.mpc; ++ adapter->net_stats.rx_length_errors = adapter->stats.rlec; ++ adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs; ++ adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc; ++ adapter->net_stats.rx_fifo_errors = adapter->stats.mpc; ++ adapter->net_stats.rx_missed_errors = adapter->stats.mpc; ++ ++ /* Tx Errors */ ++ ++ adapter->net_stats.tx_errors = adapter->stats.ecol + ++ adapter->stats.latecol; ++ adapter->net_stats.tx_aborted_errors = adapter->stats.ecol; ++ adapter->net_stats.tx_window_errors = adapter->stats.latecol; ++ adapter->net_stats.tx_carrier_errors = adapter->stats.tncrs; + +- /* Tx Dropped needs to be maintained elsewhere */ ++ /* Tx Dropped needs to be maintained elsewhere */ + +- /* Phy Stats */ ++ /* Phy Stats */ + +- if(hw->media_type == iegbe_media_type_copper ++ if(hw->media_type == iegbe_media_type_copper + || (hw->media_type == iegbe_media_type_oem + && iegbe_oem_phy_is_copper(&adapter->hw))) { +- if((adapter->link_speed == SPEED_1000) && +- (!iegbe_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) { +- phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK; +- adapter->phy_stats.idle_errors += phy_tmp; +- } ++ if((adapter->link_speed == SPEED_1000) && ++ (!iegbe_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) { ++ phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK; ++ adapter->phy_stats.idle_errors += phy_tmp; ++ } + +- if((hw->mac_type <= iegbe_82546) && +- (hw->phy_type == iegbe_phy_m88) && ++ if((hw->mac_type <= iegbe_82546) && ++ (hw->phy_type == iegbe_phy_m88) && + !iegbe_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp)) { +- adapter->phy_stats.receive_errors += phy_tmp; +- } ++ adapter->phy_stats.receive_errors += phy_tmp; ++ } + } + +- spin_unlock_irqrestore(&adapter->stats_lock, flags); ++ spin_unlock_irqrestore(&adapter->stats_lock, flags); + } + +-#ifdef CONFIG_E1000_MQ +-void +-iegbe_rx_schedule(void *data) ++/** ++ * iegbe_intr_msi - Interrupt Handler ++ * @irq: interrupt number ++ * @data: pointer to a network interface device structure ++ **/ ++ ++static irqreturn_t iegbe_intr_msi(int irq, void *data) + { +- struct net_device *poll_dev, *netdev = data; +- struct iegbe_adapter *adapter = netdev->priv; +- int this_cpu = get_cpu(); +- +- poll_dev = *per_cpu_ptr(adapter->cpu_netdev, this_cpu); +- if (poll_dev == NULL) { +- put_cpu(); +- return; ++ struct net_device *netdev = data; ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_hw *hw = &adapter->hw; ++ u32 icr = E1000_READ_REG(&adapter->hw, ICR); ++ if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { ++ hw->get_link_status = 1; ++ if (!test_bit(__E1000_DOWN, &adapter->flags)) ++ mod_timer(&adapter->watchdog_timer, jiffies + 1); + } + +- if (likely(netif_rx_schedule_prep(poll_dev))) { +- __netif_rx_schedule(poll_dev); +- } else { +- iegbe_irq_enable(adapter); +- } +- put_cpu(); +-} +-#endif +- +-#ifdef IEGBE_GBE_WORKAROUND +-/* +- * Check for tx hang condition. This is the condition where a +- * decsriptor is in the hardware and hasn't been processed for a +- * while. This code is similar to the check in iegbe_clean_rx_irq() +- */ +-static void +-iegbe_tx_hang_check(struct iegbe_adapter *adapter, +- struct iegbe_tx_ring *tx_ring) +-{ +- struct net_device *netdev = adapter->netdev; +- unsigned int i; ++ if(unlikely(icr & (E1000_ICR_RX_DESC_FIFO_PAR ++ | E1000_ICR_TX_DESC_FIFO_PAR ++ | E1000_ICR_PB ++ | E1000_ICR_CPP_TARGET ++ | E1000_ICR_CPP_MASTER ))) { + +- /* Check for a hang condition using the buffer currently at the Tx +- head pointer */ +- i = readl(adapter->hw.hw_addr + tx_ring->tdh); +- +- if (adapter->detect_tx_hung) { +- /* Detect a transmit hang in hardware, this serializes the +- * check with the clearing of time_stamp and movement of i */ +- adapter->detect_tx_hung = FALSE; +- +- if (tx_ring->buffer_info[i].dma && +- time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ) +- && !(E1000_READ_REG(&adapter->hw, STATUS) & +- E1000_STATUS_TXOFF)) { +- +- /* detected Tx unit hang */ +- DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n" +- " TDH <%x>\n" +- " TDT <%x>\n" +- " next_to_use <%x>\n" +- " next_to_clean <%x>\n" +- "buffer_info[tdh]\n" +- " dma <%zx>\n" +- " time_stamp <%lx>\n" +- " jiffies <%lx>\n", +- readl(adapter->hw.hw_addr + tx_ring->tdh), +- readl(adapter->hw.hw_addr + tx_ring->tdt), +- tx_ring->next_to_use, +- tx_ring->next_to_clean, +- (size_t)tx_ring->buffer_info[i].dma, +- tx_ring->buffer_info[i].time_stamp, +- jiffies); +- netif_stop_queue(netdev); +- } ++ iegbe_irq_disable(adapter); ++ printk("Critical error! ICR = 0x%x\n", icr); ++ return IRQ_HANDLED; + } +-} ++ if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) { ++ adapter->total_tx_bytes = 0; ++ adapter->total_tx_packets = 0; ++ adapter->total_rx_bytes = 0; ++ adapter->total_rx_packets = 0; ++ __netif_rx_schedule(netdev, &adapter->napi); ++ } else ++ iegbe_irq_enable(adapter); + +-#endif ++ return IRQ_HANDLED; ++} + + /** + * iegbe_intr - Interrupt Handler +@@ -3546,364 +3478,208 @@ iegbe_tx_hang_check(struct iegbe_adapter + **/ + + static irqreturn_t +-iegbe_intr(int irq, void *data, struct pt_regs *regs) ++iegbe_intr(int irq, void *data) + { +- struct net_device *netdev = data; +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- struct iegbe_hw *hw = &adapter->hw; +- uint32_t rctl, tctl; +- uint32_t icr = E1000_READ_REG(hw, ICR); +-#ifndef CONFIG_E1000_NAPI +- uint32_t i; +-#ifdef IEGBE_GBE_WORKAROUND +- int rx_cleaned; +-#endif +-#endif ++ struct net_device *netdev = data; ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_hw *hw = &adapter->hw; ++ u32 icr = E1000_READ_REG(&adapter->hw, ICR); + +- if(unlikely(!icr)) { ++ if (unlikely(!icr)) + return IRQ_NONE; /* Not our interrupt */ +- } ++ ++ /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is ++ * not set, then the adapter didn't send an interrupt */ ++ if (unlikely(hw->mac_type >= iegbe_82571 && ++ !(icr & E1000_ICR_INT_ASSERTED))) ++ return IRQ_NONE; ++ ++ + if(unlikely(icr & (E1000_ICR_RX_DESC_FIFO_PAR +- | E1000_ICR_TX_DESC_FIFO_PAR +- | E1000_ICR_PB +- | E1000_ICR_CPP_TARGET +- | E1000_ICR_CPP_MASTER ))) { ++ | E1000_ICR_TX_DESC_FIFO_PAR ++ | E1000_ICR_PB ++ | E1000_ICR_CPP_TARGET ++ | E1000_ICR_CPP_MASTER ))) { + + iegbe_irq_disable(adapter); +- tctl = E1000_READ_REG(&adapter->hw, TCTL); +- rctl = E1000_READ_REG(&adapter->hw, RCTL); +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_TCTL_EN); +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN); +- +- tasklet_data = (unsigned long) (icr + adapter->bd_number); +- tasklet_schedule(&iegbe_reset_tasklet); +- +- return IRQ_HANDLED; +- } +- +-#ifdef CONFIG_E1000_NAPI +- atomic_inc(&adapter->irq_sem); +-#ifdef IEGBE_GBE_WORKAROUND +- /* Ensure that the TXQE interrupt is enabled in NAPI mode */ +- E1000_WRITE_REG(hw, IMC, ~E1000_IMS_TXQE); +-#else +- E1000_WRITE_REG(hw, IMC, ~0); +-#endif +- E1000_WRITE_FLUSH(hw); +-#ifdef CONFIG_E1000_MQ +- if (atomic_read(&adapter->rx_sched_call_data.count) == 0) { +- cpu_set(adapter->cpu_for_queue[0], +- adapter->rx_sched_call_data.cpumask); +- for (i = 1; i < adapter->num_queues; i++) { +- cpu_set(adapter->cpu_for_queue[i], +- adapter->rx_sched_call_data.cpumask); +- atomic_inc(&adapter->irq_sem); +- } +- atomic_set(&adapter->rx_sched_call_data.count, i); +- smp_call_async_mask(&adapter->rx_sched_call_data); +- } else { +- DEBUGOUT("call_data.count == %u\n", +- atomic_read(&adapter->rx_sched_call_data.count)); ++ printk("Critical error! ICR = 0x%x\n", icr); ++ return IRQ_HANDLED; + } +-#else +- if (likely(netif_rx_schedule_prep(&adapter->polling_netdev[0]))) { +- __netif_rx_schedule(&adapter->polling_netdev[0]); +- } else { +- iegbe_irq_enable(adapter); +- } +-#endif +- +-#ifdef IEGBE_GBE_WORKAROUND +- /* Clean the Tx ring */ +- for (i = 0; i < E1000_MAX_INTR; i++) { +- adapter->stats.rx_next_to_clean = adapter->rx_ring->next_to_clean; +- adapter->stats.rx_next_to_use = adapter->rx_ring->next_to_use; +- +- adapter->stats.tx_next_to_clean = adapter->tx_ring->next_to_clean; +- adapter->stats.tx_next_to_use = adapter->tx_ring->next_to_use; +- +- /* Only clean Tx descriptors for a TXQE interrupt */ +- if(icr & E1000_ICR_TXQE) { +- adapter->stats.txqec++; +- iegbe_clean_tx_ring_partial(adapter, adapter->tx_ring); +- } +- else { +- iegbe_tx_hang_check(adapter, adapter->tx_ring); +- } +- } + +-#endif /*IEGBE_GBE_WORKAROUND */ +- +-#else +- /* Writing IMC and IMS is needed for 82547. +- * Due to Hub Link bus being occupied, an interrupt +- * de-assertion message is not able to be sent. +- * When an interrupt assertion message is generated later, +- * two messages are re-ordered and sent out. +- * That causes APIC to think 82547 is in de-assertion +- * state, while 82547 is in assertion state, resulting +- * in dead lock. Writing IMC forces 82547 into +- * de-assertion state. +- */ +- if (hw->mac_type == iegbe_82547 || hw->mac_type == iegbe_82547_rev_2) { +- atomic_inc(&adapter->irq_sem); +- E1000_WRITE_REG(hw, IMC, ~0); +- } +- +-#ifdef IEGBE_GBE_WORKAROUND +- +- for (i = 0; i < E1000_MAX_INTR; i++) { +- rx_cleaned = adapter->clean_rx(adapter, adapter->rx_ring); +- adapter->stats.rx_next_to_clean = adapter->rx_ring->next_to_clean; +- adapter->stats.rx_next_to_use = adapter->rx_ring->next_to_use; +- +- adapter->stats.tx_next_to_clean = adapter->tx_ring->next_to_clean; +- adapter->stats.tx_next_to_use = adapter->tx_ring->next_to_use; +- +- /* Only clean Tx descriptors for a TXQE interrupt */ +- if(icr & E1000_ICR_TXQE) { +- adapter->stats.txqec++; +- iegbe_clean_tx_ring_partial(adapter, adapter->tx_ring); +- } +- else { +- iegbe_tx_hang_check(adapter, adapter->tx_ring); +- } +- if(!rx_cleaned) { +- break; +- } ++ /* Interrupt Auto-Mask...upon reading ICR, interrupts are masked. No ++ * need for the IMC write */ ++ if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) { ++ hw->get_link_status = 1; ++ /* guard against interrupt when we're going down */ ++ if (!test_bit(__E1000_DOWN, &adapter->flags)) ++ mod_timer(&adapter->watchdog_timer, jiffies + 1); ++ + } + +-#else +- for (i = 0; i < E1000_MAX_INTR; i++) +- if(unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) & +- !iegbe_clean_tx_irq(adapter, adapter->tx_ring))) { +- break; +- } +-#endif +- +- if (hw->mac_type == iegbe_82547 || hw->mac_type == iegbe_82547_rev_2) { +- iegbe_irq_enable(adapter); +- } +-#endif +-#ifdef E1000_COUNT_ICR +- adapter->icr_txdw += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_txqe += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_lsc += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_rxseq += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_rxdmt += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_rxo += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_rxt += icr & 0x01UL; +- if(hw->mac_type != iegbe_icp_xxxx) { +- icr >>= 0x2; +- adapter->icr_mdac += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_rxcfg += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_gpi += icr & 0x01UL; +- } else { +- icr >>= 0x4; +- } +- if(hw->mac_type == iegbe_icp_xxxx) { +- icr >>= 0xc; +- adapter->icr_pb += icr & 0x01UL; +- icr >>= 0x3; +- adapter->icr_intmem_icp_xxxx += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_cpp_target += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_cpp_master += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_stat += icr & 0x01UL; ++ if (unlikely(hw->mac_type < iegbe_82571)) { ++ E1000_WRITE_REG(&adapter->hw, IMC, ~0); ++ E1000_WRITE_FLUSH(&adapter->hw); + } +-#endif ++ if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) { ++ adapter->total_tx_bytes = 0; ++ adapter->total_tx_packets = 0; ++ adapter->total_rx_bytes = 0; ++ adapter->total_rx_packets = 0; ++ __netif_rx_schedule(netdev, &adapter->napi); ++ } else ++ /* this really should not happen! if it does it is basically a ++ * bug, but not a hard error, so enable ints and continue */ ++ iegbe_irq_enable(adapter); + + return IRQ_HANDLED; + } + +-#ifdef CONFIG_E1000_NAPI + /** + * iegbe_clean - NAPI Rx polling callback + * @adapter: board private structure + **/ +- +-static int +-iegbe_clean(struct net_device *poll_dev, int *budget) ++static int iegbe_clean(struct napi_struct *napi, int budget) + { +- struct iegbe_adapter *adapter; +- int work_to_do = min(*budget, poll_dev->quota); +- int tx_cleaned, i = 0, work_done = 0; ++ struct iegbe_adapter *adapter = container_of(napi, struct iegbe_adapter, napi); ++ struct net_device *poll_dev = adapter->netdev; ++ int tx_cleaned = 0, work_done = 0; + + /* Must NOT use netdev_priv macro here. */ + adapter = poll_dev->priv; + +- /* Keep link state information with original netdev */ +- if (!netif_carrier_ok(adapter->netdev)) { +- goto quit_polling; +- } +- while (poll_dev != &adapter->polling_netdev[i]) { +- i++; +- if (unlikely(i == adapter->num_queues)) { +- BUG(); +- } +- } +- +-#ifdef IEGBE_GBE_WORKAROUND +- /* Tx descriptors are cleaned in iegbe_intr(). No need to clean +- them here */ +- tx_cleaned = FALSE; +-#else +- tx_cleaned = iegbe_clean_tx_irq(adapter, &adapter->tx_ring[i]); +-#endif +- adapter->clean_rx(adapter, &adapter->rx_ring[i], +- &work_done, work_to_do); +- +- *budget -= work_done; +- poll_dev->quota -= work_done; +- +- /* If no Tx and not enough Rx work done, exit the polling mode */ +- if((!tx_cleaned && (work_done == 0)) || +- !netif_running(adapter->netdev)) { +-quit_polling: +- netif_rx_complete(poll_dev); ++ /* iegbe_clean is called per-cpu. This lock protects ++ * tx_ring[0] from being cleaned by multiple cpus ++ * simultaneously. A failure obtaining the lock means ++ * tx_ring[0] is currently being cleaned anyway. */ ++ if (spin_trylock(&adapter->tx_queue_lock)) { ++ tx_cleaned = iegbe_clean_tx_irq(adapter, ++ &adapter->tx_ring[0]); ++ spin_unlock(&adapter->tx_queue_lock); ++ } ++ ++ adapter->clean_rx(adapter, &adapter->rx_ring[0], ++ &work_done, budget); ++ ++ if (tx_cleaned) ++ work_done = budget; ++ ++ /* If budget not fully consumed, exit the polling mode */ ++ if (work_done < budget) { ++ if (likely(adapter->itr_setting & 3)) ++ iegbe_set_itr(adapter); ++ netif_rx_complete(poll_dev, napi); + iegbe_irq_enable(adapter); +- return 0; + } + +- return 1; ++ return work_done; + } + +-#endif +- +- +-#ifndef IEGBE_GBE_WORKAROUND + /** + * iegbe_clean_tx_irq - Reclaim resources after transmit completes + * @adapter: board private structure + **/ +- +-static boolean_t +-iegbe_clean_tx_irq(struct iegbe_adapter *adapter, ++static bool iegbe_clean_tx_irq(struct iegbe_adapter *adapter, + struct iegbe_tx_ring *tx_ring) + { +- struct net_device *netdev = adapter->netdev; +- struct iegbe_tx_desc *tx_desc, *eop_desc; +- struct iegbe_buffer *buffer_info; +- unsigned int i, eop; +- boolean_t cleaned = FALSE; ++ struct iegbe_hw *hw = &adapter->hw; ++ struct net_device *netdev = adapter->netdev; ++ struct iegbe_tx_desc *tx_desc, *eop_desc; ++ struct iegbe_buffer *buffer_info; ++ unsigned int i, eop; ++ unsigned int count = 0; ++ bool cleaned = false; ++ unsigned int total_tx_bytes=0, total_tx_packets=0; + +- i = tx_ring->next_to_clean; +- eop = tx_ring->buffer_info[i].next_to_watch; +- eop_desc = E1000_TX_DESC(*tx_ring, eop); ++ i = tx_ring->next_to_clean; ++ eop = tx_ring->buffer_info[i].next_to_watch; ++ eop_desc = E1000_TX_DESC(*tx_ring, eop); + + while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) { +- /* Premature writeback of Tx descriptors clear (free buffers +- * and unmap pci_mapping) previous_buffer_info */ +- if (likely(tx_ring->previous_buffer_info.skb != NULL)) { +- iegbe_unmap_and_free_tx_resource(adapter, +- &tx_ring->previous_buffer_info); +- } +- +- for (cleaned = FALSE; !cleaned; ) { +- tx_desc = E1000_TX_DESC(*tx_ring, i); +- buffer_info = &tx_ring->buffer_info[i]; +- cleaned = (i == eop); +- +-#ifdef NETIF_F_TSO +- if (!(netdev->features & NETIF_F_TSO)) { +-#endif +- iegbe_unmap_and_free_tx_resource(adapter, +- buffer_info); +-#ifdef NETIF_F_TSO +- } else { +- if (cleaned) { +- memcpy(&tx_ring->previous_buffer_info, +- buffer_info, +- sizeof(struct iegbe_buffer)); +- memset(buffer_info, 0, +- sizeof(struct iegbe_buffer)); +- } else { +- iegbe_unmap_and_free_tx_resource( +- adapter, buffer_info); +- } +- } +-#endif +- +- tx_desc->buffer_addr = 0; +- tx_desc->lower.data = 0; ++ for (cleaned = false; !cleaned; ) { ++ tx_desc = E1000_TX_DESC(*tx_ring, i); ++ buffer_info = &tx_ring->buffer_info[i]; ++ cleaned = (i == eop); ++ ++ if (cleaned) { ++ struct sk_buff *skb = buffer_info->skb; ++ unsigned int segs = 0, bytecount; ++ segs = skb_shinfo(skb)->gso_segs ?: 1; ++ bytecount = ((segs - 1) * skb_headlen(skb)) + ++ skb->len; ++ total_tx_packets += segs; ++ total_tx_bytes += bytecount; ++ } ++ iegbe_unmap_and_free_tx_resource(adapter, buffer_info); + tx_desc->upper.data = 0; + +- if (unlikely(++i == tx_ring->count)) { i = 0; } +- } +- +- tx_ring->pkt++; ++ if (unlikely(++i == tx_ring->count)) i = 0; ++ } + +- eop = tx_ring->buffer_info[i].next_to_watch; +- eop_desc = E1000_TX_DESC(*tx_ring, eop); +- } ++ eop = tx_ring->buffer_info[i].next_to_watch; ++ eop_desc = E1000_TX_DESC(*tx_ring, eop); ++#define E1000_TX_WEIGHT 64 ++ /* weight of a sort for tx, to avoid endless transmit cleanup */ ++ if (count++ == E1000_TX_WEIGHT) ++ break; ++ } + + tx_ring->next_to_clean = i; + +- spin_lock(&tx_ring->tx_lock); ++#define TX_WAKE_THRESHOLD 32 + +- if (unlikely(cleaned && netif_queue_stopped(netdev) && +- netif_carrier_ok(netdev))) { +- netif_wake_queue(netdev); +- } +- spin_unlock(&tx_ring->tx_lock); +- +- if (adapter->detect_tx_hung) { +- /* Detect a transmit hang in hardware, this serializes the +- * check with the clearing of time_stamp and movement of i */ +- adapter->detect_tx_hung = FALSE; +- +- if (tx_ring->buffer_info[i].dma && +- time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ) +- && !(E1000_READ_REG(&adapter->hw, STATUS) & +- E1000_STATUS_TXOFF)) { +- +- /* detected Tx unit hang */ +- i = tx_ring->next_to_clean; +- eop = tx_ring->buffer_info[i].next_to_watch; +- eop_desc = E1000_TX_DESC(*tx_ring, eop); +- DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n" +- " TDH <%x>\n" +- " TDT <%x>\n" +- " next_to_use <%x>\n" +- " next_to_clean <%x>\n" +- "buffer_info[next_to_clean]\n" +- " dma <%zx>\n" +- " time_stamp <%lx>\n" +- " next_to_watch <%x>\n" +- " jiffies <%lx>\n" +- " next_to_watch.status <%x>\n", +- readl(adapter->hw.hw_addr + tx_ring->tdh), +- readl(adapter->hw.hw_addr + tx_ring->tdt), +- tx_ring->next_to_use, +- i, +- (size_t)tx_ring->buffer_info[i].dma, +- tx_ring->buffer_info[i].time_stamp, +- eop, +- jiffies, +- eop_desc->upper.fields.status); +- netif_stop_queue(netdev); ++ if (unlikely(cleaned && netif_carrier_ok(netdev) && ++ E1000_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD)) { ++ /* Make sure that anybody stopping the queue after this ++ * sees the new next_to_clean. ++ */ ++ smp_mb(); ++ if (netif_queue_stopped(netdev)) { ++ netif_wake_queue(netdev); ++ ++adapter->restart_queue; + } + } +-#ifdef NETIF_F_TSO +- if (unlikely(!(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) && +- time_after(jiffies, tx_ring->previous_buffer_info.time_stamp + HZ))) { +- iegbe_unmap_and_free_tx_resource( +- adapter, &tx_ring->previous_buffer_info); ++ ++ if (adapter->detect_tx_hung) { ++ /* Detect a transmit hang in hardware, this serializes the ++ * check with the clearing of time_stamp and movement of i */ ++ adapter->detect_tx_hung = false; ++ ++ if (tx_ring->buffer_info[eop].dma && ++ time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + ++ (adapter->tx_timeout_factor * HZ)) ++ && !(E1000_READ_REG(hw, STATUS) & E1000_STATUS_TXOFF)) { ++ ++ /* detected Tx unit hang */ ++ DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n" ++ " Tx Queue <%lu>\n" ++ " TDH <%x>\n" ++ " TDT <%x>\n" ++ " next_to_use <%x>\n" ++ " next_to_clean <%x>\n" ++ "buffer_info[next_to_clean]\n" ++ " time_stamp <%lx>\n" ++ " next_to_watch <%x>\n" ++ " jiffies <%lx>\n" ++ " next_to_watch.status <%x>\n", ++ (unsigned long)((tx_ring - adapter->tx_ring) / ++ sizeof(struct iegbe_tx_ring)), ++ readl(hw->hw_addr + tx_ring->tdh), ++ readl(hw->hw_addr + tx_ring->tdt), ++ tx_ring->next_to_use, ++ tx_ring->next_to_clean, ++ tx_ring->buffer_info[eop].time_stamp, ++ eop, ++ jiffies, ++ eop_desc->upper.fields.status); ++ netif_stop_queue(netdev); ++ } + } +-#endif +- return cleaned; ++ adapter->total_tx_bytes += total_tx_bytes; ++ adapter->total_tx_packets += total_tx_packets; ++ adapter->net_stats.tx_bytes += total_tx_bytes; ++ adapter->net_stats.tx_packets += total_tx_packets; ++ return cleaned; + } +-#endif + + /** + * iegbe_rx_checksum - Receive Checksum Offload for 82543 +@@ -3913,192 +3689,193 @@ iegbe_clean_tx_irq(struct iegbe_adapter + * @sk_buff: socket buffer with received data + **/ + +-static inline void +-iegbe_rx_checksum(struct iegbe_adapter *adapter, +- uint32_t status_err, uint32_t csum, +- struct sk_buff *skb) ++static void iegbe_rx_checksum(struct iegbe_adapter *adapter, u32 status_err, ++ u32 csum, struct sk_buff *skb) + { +- uint16_t status = (uint16_t)status_err; +- uint8_t errors = (uint8_t)(status_err >> 0x18); ++ struct iegbe_hw *hw = &adapter->hw; ++ u16 status = (u16)status_err; ++ u8 errors = (u8)(status_err >> 24); + skb->ip_summed = CHECKSUM_NONE; + +- /* 82543 or newer only */ +- if(unlikely(adapter->hw.mac_type < iegbe_82543)) { return; } +- /* Ignore Checksum bit is set */ +- if(unlikely(status & E1000_RXD_STAT_IXSM)) { return; } +- /* TCP/UDP checksum error bit is set */ +- if(unlikely(errors & E1000_RXD_ERR_TCPE)) { +- /* let the stack verify checksum errors */ +- adapter->hw_csum_err++; +- return; +- } +- /* TCP/UDP Checksum has not been calculated */ +- if(adapter->hw.mac_type <= iegbe_82547_rev_2) { +- if(!(status & E1000_RXD_STAT_TCPCS)) { +- return; ++ /* 82543 or newer only */ ++ if (unlikely(hw->mac_type < iegbe_82543)) return; ++ /* Ignore Checksum bit is set */ ++ if (unlikely(status & E1000_RXD_STAT_IXSM)) return; ++ /* TCP/UDP checksum error bit is set */ ++ if(unlikely(errors & E1000_RXD_ERR_TCPE)) { ++ /* let the stack verify checksum errors */ ++ adapter->hw_csum_err++; ++ return; ++ } ++ /* TCP/UDP Checksum has not been calculated */ ++ if (hw->mac_type <= iegbe_82547_rev_2) { ++ if (!(status & E1000_RXD_STAT_TCPCS)) ++ return; ++ } else { ++ if (!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS))) ++ return; + } +- } else { +- if(!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS))) { +- return; +- } ++ /* It must be a TCP or UDP packet with a valid checksum */ ++ if(likely(status & E1000_RXD_STAT_TCPCS)) { ++ /* TCP checksum is good */ ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ } else if (hw->mac_type > iegbe_82547_rev_2) { ++ /* IP fragment with UDP payload */ ++ /* Hardware complements the payload checksum, so we undo it ++ * and then put the value in host order for further stack use. ++ */ ++ __sum16 sum = (__force __sum16)htons(csum); ++ skb->csum = csum_unfold(~sum); ++ skb->ip_summed = CHECKSUM_COMPLETE; + } +- /* It must be a TCP or UDP packet with a valid checksum */ +- if(likely(status & E1000_RXD_STAT_TCPCS)) { +- /* TCP checksum is good */ +- skb->ip_summed = CHECKSUM_UNNECESSARY; +- } else if(adapter->hw.mac_type > iegbe_82547_rev_2) { +- /* IP fragment with UDP payload */ +- /* Hardware complements the payload checksum, so we undo it +- * and then put the value in host order for further stack use. +- */ +- csum = ntohl(csum ^ 0xFFFF); +- skb->csum = csum; +- skb->ip_summed = CHECKSUM_HW; +- } +- adapter->hw_csum_good++; ++ adapter->hw_csum_good++; + } + + /** + * iegbe_clean_rx_irq - Send received data up the network stack; legacy + * @adapter: board private structure + **/ +- +-static boolean_t +-#ifdef CONFIG_E1000_NAPI +-iegbe_clean_rx_irq(struct iegbe_adapter *adapter, ++static bool iegbe_clean_rx_irq(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int *work_done, int work_to_do) +-#else +-iegbe_clean_rx_irq(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring) +-#endif + { +- struct net_device *netdev = adapter->netdev; +- struct pci_dev *pdev = adapter->pdev; +- struct iegbe_rx_desc *rx_desc; +- struct iegbe_buffer *buffer_info; +- struct sk_buff *skb; +- unsigned long flags = 0; +- uint32_t length; +- uint8_t last_byte; +- unsigned int i; +- boolean_t cleaned = FALSE; +- +-#ifdef IEGBE_GBE_WORKAROUND +- /* Need to keep track of the amount of Rx descriptors that we +- cleaned to ensure that we don't supply too many back to the +- hardware */ +- int cleaned_count = 0; +-#endif +- +- i = rx_ring->next_to_clean; +- rx_desc = E1000_RX_DESC(*rx_ring, i); +- +- while(rx_desc->status & E1000_RXD_STAT_DD) { +- buffer_info = &rx_ring->buffer_info[i]; +-#ifdef CONFIG_E1000_NAPI +- if(*work_done >= work_to_do) { +- break; +- } +- (*work_done)++; +-#endif +- cleaned = TRUE; ++ struct iegbe_hw *hw = &adapter->hw; ++ struct net_device *netdev = adapter->netdev; ++ struct pci_dev *pdev = adapter->pdev; ++ struct iegbe_rx_desc *rx_desc, *next_rxd; ++ struct iegbe_buffer *buffer_info, *next_buffer; ++ unsigned long flags; ++ u32 length; ++ u8 last_byte; ++ unsigned int i; ++ int cleaned_count = 0; ++ bool cleaned = false; ++ unsigned int total_rx_bytes=0, total_rx_packets=0; + +-#ifdef IEGBE_GBE_WORKAROUND +- cleaned_count++; +-#endif ++ i = rx_ring->next_to_clean; ++ rx_desc = E1000_RX_DESC(*rx_ring, i); ++ buffer_info = &rx_ring->buffer_info[i]; + +- pci_unmap_single(pdev, +- buffer_info->dma, +- buffer_info->length, +- PCI_DMA_FROMDEVICE); ++ while(rx_desc->status & E1000_RXD_STAT_DD) { ++ struct sk_buff *skb; ++ u8 status; ++ if (*work_done >= work_to_do) ++ break; ++ (*work_done)++; + ++ status = rx_desc->status; + skb = buffer_info->skb; +- length = le16_to_cpu(rx_desc->length); ++ buffer_info->skb = NULL; ++ prefetch(skb->data - NET_IP_ALIGN); ++ if (++i == rx_ring->count) i = 0; ++ next_rxd = E1000_RX_DESC(*rx_ring, i); ++ prefetch(next_rxd); ++ next_buffer = &rx_ring->buffer_info[i]; ++ cleaned = true; ++ cleaned_count++; ++ pci_unmap_single(pdev, ++ buffer_info->dma, ++ buffer_info->length, ++ PCI_DMA_FROMDEVICE); ++ ++ length = le16_to_cpu(rx_desc->length); ++ ++ if (unlikely(!(status & E1000_RXD_STAT_EOP))) { ++ /* All receives must fit into a single buffer */ ++ E1000_DBG("%s: Receive packet consumed multiple" ++ " buffers\n", netdev->name); ++ buffer_info->skb = skb; ++ goto next_desc; ++ } + +- if(unlikely(!(rx_desc->status & E1000_RXD_STAT_EOP))) { +- /* All receives must fit into a single buffer */ +- E1000_DBG("%s: Receive packet consumed multiple" +- " buffers\n", netdev->name); +- dev_kfree_skb_irq(skb); +- goto next_desc; +- } ++ if(unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) { ++ last_byte = *(skb->data + length - 1); ++ if (TBI_ACCEPT(hw, status, rx_desc->errors, length, ++ last_byte)) { ++ spin_lock_irqsave(&adapter->stats_lock, flags); ++ iegbe_tbi_adjust_stats(hw, &adapter->stats, ++ length, skb->data); ++ spin_unlock_irqrestore(&adapter->stats_lock, ++ flags); ++ length--; ++ } else { ++ buffer_info->skb = skb; ++ goto next_desc; ++ } ++ } + +- if(unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) { +- last_byte = *(skb->data + length - 0x1); +- if(TBI_ACCEPT(&adapter->hw, rx_desc->status, +- rx_desc->errors, length, last_byte)) { +- spin_lock_irqsave(&adapter->stats_lock, flags); +- iegbe_tbi_adjust_stats(&adapter->hw, +- &adapter->stats, +- length, skb->data); +- spin_unlock_irqrestore(&adapter->stats_lock, +- flags); +- length--; +- } else { +- dev_kfree_skb_irq(skb); +- goto next_desc; ++ /* adjust length to remove Ethernet CRC, this must be ++ * done after the TBI_ACCEPT workaround above */ ++ length -= 4; ++ ++ /* probably a little skewed due to removing CRC */ ++ total_rx_bytes += length; ++ total_rx_packets++; ++ ++ /* code added for copybreak, this should improve ++ * performance for small packets with large amounts ++ * of reassembly being done in the stack */ ++ if (length < copybreak) { ++ struct sk_buff *new_skb = ++ netdev_alloc_skb(netdev, length + NET_IP_ALIGN); ++ if (new_skb) { ++ skb_reserve(new_skb, NET_IP_ALIGN); ++ skb_copy_to_linear_data_offset(new_skb, ++ -NET_IP_ALIGN, ++ (skb->data - ++ NET_IP_ALIGN), ++ (length + ++ NET_IP_ALIGN)); ++ /* save the skb in buffer_info as good */ ++ buffer_info->skb = skb; ++ skb = new_skb; + } ++ /* else just continue with the old one */ + } +- +- /* Good Receive */ +- skb_put(skb, length - ETHERNET_FCS_SIZE); ++ /* Good Receive */ ++ skb_put(skb, length); + + /* Receive Checksum Offload */ + iegbe_rx_checksum(adapter, +- (uint32_t)(rx_desc->status) | +- ((uint32_t)(rx_desc->errors) << 0x18), +- rx_desc->csum, skb); ++ (u32)(status) | ++ ((u32)(rx_desc->errors) << 24), ++ le16_to_cpu(rx_desc->csum), skb); ++ + skb->protocol = eth_type_trans(skb, netdev); +-#ifdef CONFIG_E1000_NAPI +-#ifdef NETIF_F_HW_VLAN_TX +- if(unlikely(adapter->vlgrp && +- (rx_desc->status & E1000_RXD_STAT_VP))) { ++ ++ if (unlikely(adapter->vlgrp && ++ (status & E1000_RXD_STAT_VP))) { + vlan_hwaccel_receive_skb(skb, adapter->vlgrp, +- le16_to_cpu(rx_desc->special) & +- E1000_RXD_SPC_VLAN_MASK); ++ le16_to_cpu(rx_desc->special)); + } else { + netif_receive_skb(skb); + } +-#else +- netif_receive_skb(skb); +-#endif +-#else /* CONFIG_E1000_NAPI */ +-#ifdef NETIF_F_HW_VLAN_TX +- if(unlikely(adapter->vlgrp && +- (rx_desc->status & E1000_RXD_STAT_VP))) { +- vlan_hwaccel_rx(skb, adapter->vlgrp, +- le16_to_cpu(rx_desc->special) & +- E1000_RXD_SPC_VLAN_MASK); +- } else { +- netif_rx(skb); +- } +-#else +- netif_rx(skb); +-#endif +-#endif /* CONFIG_E1000_NAPI */ ++ + netdev->last_rx = jiffies; +- rx_ring->pkt++; + + next_desc: + rx_desc->status = 0; +- buffer_info->skb = NULL; +- if(unlikely(++i == rx_ring->count)) { i = 0; } + +- rx_desc = E1000_RX_DESC(*rx_ring, i); ++ /* return some buffers to hardware, one at a time is too slow */ ++ if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) { ++ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); ++ cleaned_count = 0; ++ } ++ ++ /* use prefetched values */ ++ rx_desc = next_rxd; ++ buffer_info = next_buffer; + } + rx_ring->next_to_clean = i; + +-#ifdef IEGBE_GBE_WORKAROUND +- /* Only allocate the number of buffers that we have actually +- cleaned! */ +- if (cleaned_count) { +- adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); +- } +-#else +- adapter->alloc_rx_buf(adapter, rx_ring); +-#endif +- ++ cleaned_count = E1000_DESC_UNUSED(rx_ring); ++ if (cleaned_count) ++ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); ++ ++ adapter->total_rx_packets += total_rx_packets; ++ adapter->total_rx_bytes += total_rx_bytes; ++ adapter->net_stats.rx_bytes += total_rx_bytes; ++ adapter->net_stats.rx_packets += total_rx_packets; + return cleaned; + } + +@@ -4107,161 +3884,153 @@ next_desc: + * @adapter: board private structure + **/ + +-static boolean_t +-#ifdef CONFIG_E1000_NAPI +-iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter, ++static bool iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int *work_done, int work_to_do) +-#else +-iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring) +-#endif + { +- union iegbe_rx_desc_packet_split *rx_desc; +- struct net_device *netdev = adapter->netdev; +- struct pci_dev *pdev = adapter->pdev; +- struct iegbe_buffer *buffer_info; +- struct iegbe_ps_page *ps_page; +- struct iegbe_ps_page_dma *ps_page_dma; +- struct sk_buff *skb; +- unsigned int i, j; +- uint32_t length, staterr; +- boolean_t cleaned = FALSE; +- +-#ifdef IEGBE_GBE_WORKAROUND +- /* Need to keep track of the amount of Rx descriptors that we +- cleaned to ensure that we don't supply too many back to the +- hardware */ +- int cleaned_count = 0; +-#endif +- +- i = rx_ring->next_to_clean; +- rx_desc = E1000_RX_DESC_PS(*rx_ring, i); +- staterr = le32_to_cpu(rx_desc->wb.middle.status_error); +- +- while(staterr & E1000_RXD_STAT_DD) { +- buffer_info = &rx_ring->buffer_info[i]; +- ps_page = &rx_ring->ps_page[i]; +- ps_page_dma = &rx_ring->ps_page_dma[i]; +-#ifdef CONFIG_E1000_NAPI +- if(unlikely(*work_done >= work_to_do)) { +- break; +- } +- (*work_done)++; +-#endif +- cleaned = TRUE; +- +-#ifdef IEGBE_GBE_WORKAROUND +- cleaned_count++; +-#endif ++ union iegbe_rx_desc_packet_split *rx_desc, *next_rxd; ++ struct net_device *netdev = adapter->netdev; ++ struct pci_dev *pdev = adapter->pdev; ++ struct iegbe_buffer *buffer_info, *next_buffer; ++ struct iegbe_ps_page *ps_page; ++ struct iegbe_ps_page_dma *ps_page_dma; ++ struct sk_buff *skb; ++ unsigned int i, j; ++ u32 length, staterr; ++ int cleaned_count = 0; ++ bool cleaned = false; ++ unsigned int total_rx_bytes=0, total_rx_packets=0; ++ ++ i = rx_ring->next_to_clean; ++ rx_desc = E1000_RX_DESC_PS(*rx_ring, i); ++ staterr = le32_to_cpu(rx_desc->wb.middle.status_error); ++ buffer_info = &rx_ring->buffer_info[i]; + +- pci_unmap_single(pdev, buffer_info->dma, +- buffer_info->length, +- PCI_DMA_FROMDEVICE); ++ while(staterr & E1000_RXD_STAT_DD) { ++ ps_page = &rx_ring->ps_page[i]; ++ ps_page_dma = &rx_ring->ps_page_dma[i]; ++ ++ if (unlikely(*work_done >= work_to_do)) ++ break; ++ (*work_done)++; + + skb = buffer_info->skb; ++ prefetch(skb->data - NET_IP_ALIGN); ++ if (++i == rx_ring->count) i = 0; ++ next_rxd = E1000_RX_DESC_PS(*rx_ring, i); ++ prefetch(next_rxd); ++ next_buffer = &rx_ring->buffer_info[i]; ++ cleaned = true; ++ cleaned_count++; ++ pci_unmap_single(pdev, buffer_info->dma, ++ buffer_info->length, ++ PCI_DMA_FROMDEVICE); ++ ++ if(unlikely(!(staterr & E1000_RXD_STAT_EOP))) { ++ E1000_DBG("%s: Packet Split buffers didn't pick up" ++ " the full packet\n", netdev->name); ++ dev_kfree_skb_irq(skb); ++ goto next_desc; ++ } + +- if(unlikely(!(staterr & E1000_RXD_STAT_EOP))) { +- E1000_DBG("%s: Packet Split buffers didn't pick up" +- " the full packet\n", netdev->name); +- dev_kfree_skb_irq(skb); +- goto next_desc; +- } +- +- if(unlikely(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) { +- dev_kfree_skb_irq(skb); +- goto next_desc; +- } +- +- length = le16_to_cpu(rx_desc->wb.middle.length0); ++ if(unlikely(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) { ++ dev_kfree_skb_irq(skb); ++ goto next_desc; ++ } + +- if(unlikely(!length)) { +- E1000_DBG("%s: Last part of the packet spanning" +- " multiple descriptors\n", netdev->name); +- dev_kfree_skb_irq(skb); +- goto next_desc; +- } ++ length = le16_to_cpu(rx_desc->wb.middle.length0); + +- /* Good Receive */ +- skb_put(skb, length); +- +- for(j = 0; j < adapter->rx_ps_pages; j++) { +- if(!(length = le16_to_cpu(rx_desc->wb.upper.length[j]))) { +- break; +- } +- pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j], +- PAGE_SIZE, PCI_DMA_FROMDEVICE); +- ps_page_dma->ps_page_dma[j] = 0; +- skb_shinfo(skb)->frags[j].page = +- ps_page->ps_page[j]; +- ps_page->ps_page[j] = NULL; +- skb_shinfo(skb)->frags[j].page_offset = 0; +- skb_shinfo(skb)->frags[j].size = length; +- skb_shinfo(skb)->nr_frags++; +- skb->len += length; +- skb->data_len += length; +- } ++ if(unlikely(!length)) { ++ E1000_DBG("%s: Last part of the packet spanning" ++ " multiple descriptors\n", netdev->name); ++ dev_kfree_skb_irq(skb); ++ goto next_desc; ++ } + +- iegbe_rx_checksum(adapter, staterr, +- rx_desc->wb.lower.hi_dword.csum_ip.csum, skb); +- skb->protocol = eth_type_trans(skb, netdev); ++ /* Good Receive */ ++ skb_put(skb, length); + +- if(likely(rx_desc->wb.upper.header_status & +- E1000_RXDPS_HDRSTAT_HDRSP)) { +- adapter->rx_hdr_split++; +-#ifdef HAVE_RX_ZERO_COPY +- skb_shinfo(skb)->zero_copy = TRUE; +-#endif +- } +-#ifdef CONFIG_E1000_NAPI +-#ifdef NETIF_F_HW_VLAN_TX +- if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { +- vlan_hwaccel_receive_skb(skb, adapter->vlgrp, +- le16_to_cpu(rx_desc->wb.middle.vlan) & +- E1000_RXD_SPC_VLAN_MASK); +- } else { +- netif_receive_skb(skb); +- } +-#else +- netif_receive_skb(skb); +-#endif +-#else /* CONFIG_E1000_NAPI */ +-#ifdef NETIF_F_HW_VLAN_TX +- if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { +- vlan_hwaccel_rx(skb, adapter->vlgrp, +- le16_to_cpu(rx_desc->wb.middle.vlan) & +- E1000_RXD_SPC_VLAN_MASK); +- } else { +- netif_rx(skb); +- } +-#else +- netif_rx(skb); +-#endif +-#endif /* CONFIG_E1000_NAPI */ +- netdev->last_rx = jiffies; +- rx_ring->pkt++; ++ { ++ int l1 = le16_to_cpu(rx_desc->wb.upper.length[0]); ++ if (l1 && (l1 <= copybreak) && ((length + l1) <= adapter->rx_ps_bsize0)) { ++ u8 *vaddr; ++ pci_dma_sync_single_for_cpu(pdev, ++ ps_page_dma->ps_page_dma[0], ++ PAGE_SIZE, ++ PCI_DMA_FROMDEVICE); ++ vaddr = kmap_atomic(ps_page->ps_page[0], ++ KM_SKB_DATA_SOFTIRQ); ++ memcpy(skb_tail_pointer(skb), vaddr, l1); ++ kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ); ++ pci_dma_sync_single_for_device(pdev, ++ ps_page_dma->ps_page_dma[0], ++ PAGE_SIZE, PCI_DMA_FROMDEVICE); ++ l1 -= 4; ++ skb_put(skb, l1); ++ goto copydone; ++ } /* if */ ++ } ++ for (j = 0; j < adapter->rx_ps_pages; j++) { ++ length = le16_to_cpu(rx_desc->wb.upper.length[j]); ++ if (!length) ++ break; ++ pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j], ++ PAGE_SIZE, PCI_DMA_FROMDEVICE); ++ ps_page_dma->ps_page_dma[j] = 0; ++ skb_fill_page_desc(skb, j, ps_page->ps_page[j], 0, ++ length); ++ ps_page->ps_page[j] = NULL; ++ skb->len += length; ++ skb->data_len += length; ++ skb->truesize += length; ++ } + +-next_desc: +- rx_desc->wb.middle.status_error &= ~0xFF; +- buffer_info->skb = NULL; +- if(unlikely(++i == rx_ring->count)) { i = 0; } ++ pskb_trim(skb, skb->len - 4); ++copydone: ++ total_rx_bytes += skb->len; ++ total_rx_packets++; ++ iegbe_rx_checksum(adapter, staterr, ++ le16_to_cpu(rx_desc->wb.lower.hi_dword.csum_ip.csum), skb); ++ skb->protocol = eth_type_trans(skb, netdev); ++ ++ if(likely(rx_desc->wb.upper.header_status & ++ cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP))) ++ adapter->rx_hdr_split++; ++ ++ if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { ++ vlan_hwaccel_receive_skb(skb, adapter->vlgrp, ++ le16_to_cpu(rx_desc->wb.middle.vlan)); ++ } else { ++ netif_receive_skb(skb); ++ } + +- rx_desc = E1000_RX_DESC_PS(*rx_ring, i); +- staterr = le32_to_cpu(rx_desc->wb.middle.status_error); +- } +- rx_ring->next_to_clean = i; ++ netdev->last_rx = jiffies; + +-#ifdef IEGBE_GBE_WORKAROUND +- /* Only allocate the number of buffers that we have actually +- cleaned! */ +- if (cleaned_count) { +- adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); +- } +-#else +- adapter->alloc_rx_buf(adapter, rx_ring); +-#endif ++next_desc: ++ rx_desc->wb.middle.status_error &= cpu_to_le32(~0xFF); ++ buffer_info->skb = NULL; + +- return cleaned; ++ if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) { ++ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); ++ cleaned_count = 0; ++ } ++ ++ /* use prefetched values */ ++ rx_desc = next_rxd; ++ buffer_info = next_buffer; ++ staterr = le32_to_cpu(rx_desc->wb.middle.status_error); ++ } ++ rx_ring->next_to_clean = i; ++ ++ cleaned_count = E1000_DESC_UNUSED(rx_ring); ++ if (cleaned_count) ++ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); ++ ++ adapter->total_rx_packets += total_rx_packets; ++ adapter->total_rx_bytes += total_rx_bytes; ++ adapter->net_stats.rx_bytes += total_rx_bytes; ++ adapter->net_stats.rx_packets += total_rx_packets; ++ return cleaned; + } + + /** +@@ -4269,142 +4038,115 @@ next_desc: + * @adapter: address of board private structure + **/ + +-#ifdef IEGBE_GBE_WORKAROUND +-static void +-iegbe_alloc_rx_buffers(struct iegbe_adapter *adapter, ++ ++static void iegbe_alloc_rx_buffers(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int cleaned_count) +-#else +-static void +-iegbe_alloc_rx_buffers(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring) +-#endif + { +- struct net_device *netdev = adapter->netdev; +- struct pci_dev *pdev = adapter->pdev; +- struct iegbe_rx_desc *rx_desc; +- struct iegbe_buffer *buffer_info; +- struct sk_buff *skb; +- unsigned int i; +- unsigned int bufsz = adapter->rx_buffer_len + NET_IP_ALIGN; +- +- i = rx_ring->next_to_use; +- buffer_info = &rx_ring->buffer_info[i]; ++ struct iegbe_hw *hw = &adapter->hw; ++ struct net_device *netdev = adapter->netdev; ++ struct pci_dev *pdev = adapter->pdev; ++ struct iegbe_rx_desc *rx_desc; ++ struct iegbe_buffer *buffer_info; ++ struct sk_buff *skb; ++ unsigned int i; ++ unsigned int bufsz = adapter->rx_buffer_len + NET_IP_ALIGN; + +-#ifdef IEGBE_GBE_WORKAROUND +- if (cleaned_count > IEGBE_GBE_WORKAROUND_NUM_RX_DESCRIPTORS) { +- adapter->stats.cc_gt_num_rx++; +- } +- while(cleaned_count-- && !buffer_info->skb) { +-#else +- while(!buffer_info->skb) { +-#endif +- skb = dev_alloc_skb(bufsz); ++ i = rx_ring->next_to_use; ++ buffer_info = &rx_ring->buffer_info[i]; + +- if(unlikely(!skb)) { +- /* Better luck next round */ +- break; +- } ++ while (cleaned_count--) { ++ skb = buffer_info->skb; ++ if (skb) { ++ skb_trim(skb, 0); ++ goto map_skb; ++ } ++ skb = netdev_alloc_skb(netdev, bufsz); ++ ++ if(unlikely(!skb)) { ++ /* Better luck next round */ ++ adapter->alloc_rx_buff_failed++; ++ break; ++ } + +- /* Fix for errata 23, can't cross 64kB boundary */ +- if(!iegbe_check_64k_bound(adapter, skb->data, bufsz)) { +- struct sk_buff *oldskb = skb; +- DPRINTK(RX_ERR, ERR, "skb align check failed: %u bytes " +- "at %p\n", bufsz, skb->data); +- /* Try again, without freeing the previous */ +- skb = dev_alloc_skb(bufsz); +- /* Failed allocation, critical failure */ +- if(!skb) { +- dev_kfree_skb(oldskb); +- break; +- } ++ /* Fix for errata 23, can't cross 64kB boundary */ ++ if(!iegbe_check_64k_bound(adapter, skb->data, bufsz)) { ++ struct sk_buff *oldskb = skb; ++ DPRINTK(RX_ERR, ERR, "skb align check failed: %u bytes " ++ "at %p\n", bufsz, skb->data); ++ /* Try again, without freeing the previous */ ++ skb = netdev_alloc_skb(netdev, bufsz); ++ /* Failed allocation, critical failure */ ++ if(!skb) { ++ dev_kfree_skb(oldskb); ++ break; ++ } + +- if(!iegbe_check_64k_bound(adapter, skb->data, bufsz)) { +- /* give up */ +- dev_kfree_skb(skb); +- dev_kfree_skb(oldskb); +- break; /* while !buffer_info->skb */ +- } else { +- /* Use new allocation */ +- dev_kfree_skb(oldskb); ++ if(!iegbe_check_64k_bound(adapter, skb->data, bufsz)) { ++ /* give up */ ++ dev_kfree_skb(skb); ++ dev_kfree_skb(oldskb); ++ break; /* while !buffer_info->skb */ + } +- } +- /* Make buffer alignment 2 beyond a 16 byte boundary +- * this will result in a 16 byte aligned IP header after +- * the 14 byte MAC header is removed +- */ +- skb_reserve(skb, NET_IP_ALIGN); +- +- skb->dev = netdev; +- +- buffer_info->skb = skb; +- buffer_info->length = adapter->rx_buffer_len; +- buffer_info->dma = pci_map_single(pdev, +- skb->data, +- adapter->rx_buffer_len, +- PCI_DMA_FROMDEVICE); +- +- /* Fix for errata 23, can't cross 64kB boundary */ +- if(!iegbe_check_64k_bound(adapter, +- (void *)(unsigned long)buffer_info->dma, +- adapter->rx_buffer_len)) { +- DPRINTK(RX_ERR, ERR, +- "dma align check failed: %u bytes at %p\n", +- adapter->rx_buffer_len, +- (void *)(unsigned long)buffer_info->dma); +- dev_kfree_skb(skb); +- buffer_info->skb = NULL; +- +- pci_unmap_single(pdev, buffer_info->dma, +- adapter->rx_buffer_len, +- PCI_DMA_FROMDEVICE); +- +- break; /* while !buffer_info->skb */ +- } +- rx_desc = E1000_RX_DESC(*rx_ring, i); +- rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); +- +-#ifdef IEGBE_GBE_WORKAROUND_DISABLED +- adapter->stats.num_rx_buf_alloc++; ++ /* Use new allocation */ ++ dev_kfree_skb(oldskb); ++ } ++ /* Make buffer alignment 2 beyond a 16 byte boundary ++ * this will result in a 16 byte aligned IP header after ++ * the 14 byte MAC header is removed ++ */ ++ skb_reserve(skb, NET_IP_ALIGN); ++ ++ ++ buffer_info->skb = skb; ++ buffer_info->length = adapter->rx_buffer_len; ++map_skb: ++ buffer_info->dma = pci_map_single(pdev, ++ skb->data, ++ adapter->rx_buffer_len, ++ PCI_DMA_FROMDEVICE); ++ ++ /* Fix for errata 23, can't cross 64kB boundary */ ++ if(!iegbe_check_64k_bound(adapter, ++ (void *)(unsigned long)buffer_info->dma, ++ adapter->rx_buffer_len)) { ++ DPRINTK(RX_ERR, ERR, ++ "dma align check failed: %u bytes at %p\n", ++ adapter->rx_buffer_len, ++ (void *)(unsigned long)buffer_info->dma); ++ dev_kfree_skb(skb); ++ buffer_info->skb = NULL; ++ ++ pci_unmap_single(pdev, buffer_info->dma, ++ adapter->rx_buffer_len, ++ PCI_DMA_FROMDEVICE); + +- /* Force memory writes to complete before letting h/w +- * know there are new descriptors to fetch. (Only +- * applicable for weak-ordered memory model archs, +- * such as IA-64). */ +- wmb(); +- writel(i, adapter->hw.hw_addr + rx_ring->rdt); ++ break; /* while !buffer_info->skb */ ++ } ++ rx_desc = E1000_RX_DESC(*rx_ring, i); ++ rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); + +-#endif +-#ifndef IEGBE_GBE_WORKAROUND +- if(unlikely((i & ~(E1000_RX_BUFFER_WRITE - 0x1)) == i)) { +- /* Force memory writes to complete before letting h/w +- * know there are new descriptors to fetch. (Only +- * applicable for weak-ordered memory model archs, +- * such as IA-64). */ +- wmb(); +- writel(i, adapter->hw.hw_addr + rx_ring->rdt); +- } +-#endif +- if(unlikely(++i == rx_ring->count)) { i = 0; } +- buffer_info = &rx_ring->buffer_info[i]; +- } ++ /* Force memory writes to complete before letting h/w ++ * know there are new descriptors to fetch. (Only ++ * applicable for weak-ordered memory model archs, ++ * such as IA-64). */ ++ if (unlikely(++i == rx_ring->count)) ++ i = 0; ++ buffer_info = &rx_ring->buffer_info[i]; ++ } + +-#ifdef IEGBE_GBE_WORKAROUND + if (likely(rx_ring->next_to_use != i)) { +- rx_ring->next_to_use = i; +- if (unlikely(i-- == 0)) { +- i = (rx_ring->count - 0x1); +- } ++ rx_ring->next_to_use = i; ++ if (unlikely(i-- == 0)) ++ i = (rx_ring->count - 1); ++ + /* Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). */ + wmb(); +- writel(i, adapter->hw.hw_addr + rx_ring->rdt); ++ writel(i, hw->hw_addr + rx_ring->rdt); + } +-#else +- rx_ring->next_to_use = i; +-#endif + } + + /** +@@ -4412,49 +4154,41 @@ iegbe_alloc_rx_buffers(struct iegbe_adap + * @adapter: address of board private structure + **/ + +-#ifdef IEGBE_GBE_WORKAROUND +-static void +-iegbe_alloc_rx_buffers_ps(struct iegbe_adapter *adapter, ++ ++static void iegbe_alloc_rx_buffers_ps(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int cleaned_count) +-#else +-static void +-iegbe_alloc_rx_buffers_ps(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring) +-#endif + { +- struct net_device *netdev = adapter->netdev; +- struct pci_dev *pdev = adapter->pdev; +- union iegbe_rx_desc_packet_split *rx_desc; +- struct iegbe_buffer *buffer_info; +- struct iegbe_ps_page *ps_page; +- struct iegbe_ps_page_dma *ps_page_dma; +- struct sk_buff *skb; +- unsigned int i, j; +- +- i = rx_ring->next_to_use; +- buffer_info = &rx_ring->buffer_info[i]; +- ps_page = &rx_ring->ps_page[i]; +- ps_page_dma = &rx_ring->ps_page_dma[i]; ++ struct iegbe_hw *hw = &adapter->hw; ++ struct net_device *netdev = adapter->netdev; ++ struct pci_dev *pdev = adapter->pdev; ++ union iegbe_rx_desc_packet_split *rx_desc; ++ struct iegbe_buffer *buffer_info; ++ struct iegbe_ps_page *ps_page; ++ struct iegbe_ps_page_dma *ps_page_dma; ++ struct sk_buff *skb; ++ unsigned int i, j; ++ ++ i = rx_ring->next_to_use; ++ buffer_info = &rx_ring->buffer_info[i]; ++ ps_page = &rx_ring->ps_page[i]; ++ ps_page_dma = &rx_ring->ps_page_dma[i]; + +-#ifdef IEGBE_GBE_WORKAROUND +- while(cleaned_count-- && !buffer_info->skb) { +-#else +- while(!buffer_info->skb) { +-#endif +- rx_desc = E1000_RX_DESC_PS(*rx_ring, i); ++ while (cleaned_count--) { ++ rx_desc = E1000_RX_DESC_PS(*rx_ring, i); + + for (j = 0; j < PS_PAGE_BUFFERS; j++) { +- if (j < adapter->rx_ps_pages) { +- if (likely(!ps_page->ps_page[j])) { +- ps_page->ps_page[j] = +- alloc_page(GFP_ATOMIC); ++ if (j < adapter->rx_ps_pages) { ++ if (likely(!ps_page->ps_page[j])) { ++ ps_page->ps_page[j] = ++ alloc_page(GFP_ATOMIC); + if (unlikely(!ps_page->ps_page[j])) { +- goto no_buffers; ++ adapter->alloc_rx_buff_failed++; ++ goto no_buffers; + } +- ps_page_dma->ps_page_dma[j] = +- pci_map_page(pdev, +- ps_page->ps_page[j], ++ ps_page_dma->ps_page_dma[j] = ++ pci_map_page(pdev, ++ ps_page->ps_page[j], + 0, PAGE_SIZE, + PCI_DMA_FROMDEVICE); + } +@@ -4462,26 +4196,26 @@ iegbe_alloc_rx_buffers_ps(struct iegbe_a + * change because each write-back erases + * this info. + */ +- rx_desc->read.buffer_addr[j+0x1] = ++ rx_desc->read.buffer_addr[j+1] = + cpu_to_le64(ps_page_dma->ps_page_dma[j]); +- } else { +- rx_desc->read.buffer_addr[j+0x1] = ~0; +- } ++ } else ++ rx_desc->read.buffer_addr[j+1] = ~cpu_to_le64(0); + } + +- skb = dev_alloc_skb(adapter->rx_ps_bsize0 + NET_IP_ALIGN); ++ skb = netdev_alloc_skb(netdev, ++ adapter->rx_ps_bsize0 + NET_IP_ALIGN); + +- if (unlikely(!skb)) { ++ if (unlikely(!skb)) { ++ adapter->alloc_rx_buff_failed++; + break; +- } ++ } ++ + /* Make buffer alignment 2 beyond a 16 byte boundary + * this will result in a 16 byte aligned IP header after + * the 14 byte MAC header is removed + */ + skb_reserve(skb, NET_IP_ALIGN); + +- skb->dev = netdev; +- + buffer_info->skb = skb; + buffer_info->length = adapter->rx_ps_bsize0; + buffer_info->dma = pci_map_single(pdev, skb->data, +@@ -4490,27 +4224,28 @@ iegbe_alloc_rx_buffers_ps(struct iegbe_a + + rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma); + +- if (unlikely((i & ~(E1000_RX_BUFFER_WRITE - 0x1)) == i)) { +- /* Force memory writes to complete before letting h/w +- * know there are new descriptors to fetch. (Only +- * applicable for weak-ordered memory model archs, +- * such as IA-64). */ +- wmb(); +- /* Hardware increments by 16 bytes, but packet split +- * descriptors are 32 bytes...so we increment tail +- * twice as much. +- */ +- writel(i<<1, adapter->hw.hw_addr + rx_ring->rdt); +- } +- +- if (unlikely(++i == rx_ring->count)) { i = 0; } ++ if (unlikely(++i == rx_ring->count)) i = 0; + buffer_info = &rx_ring->buffer_info[i]; + ps_page = &rx_ring->ps_page[i]; + ps_page_dma = &rx_ring->ps_page_dma[i]; + } + + no_buffers: +- rx_ring->next_to_use = i; ++ if (likely(rx_ring->next_to_use != i)) { ++ rx_ring->next_to_use = i; ++ if (unlikely(i-- == 0)) i = (rx_ring->count - 1); ++ ++ /* Force memory writes to complete before letting h/w ++ * know there are new descriptors to fetch. (Only ++ * applicable for weak-ordered memory model archs, ++ * such as IA-64). */ ++ wmb(); ++ /* Hardware increments by 16 bytes, but packet split ++ * descriptors are 32 bytes...so we increment tail ++ * twice as much. ++ */ ++ writel(i<<1, hw->hw_addr + rx_ring->rdt); ++ } + } + + /** +@@ -4521,52 +4256,52 @@ no_buffers: + static void + iegbe_smartspeed(struct iegbe_adapter *adapter) + { +- uint16_t phy_status; +- uint16_t phy_ctrl; ++ uint16_t phy_status; ++ uint16_t phy_ctrl; + +- if((adapter->hw.phy_type != iegbe_phy_igp) || !adapter->hw.autoneg || ++ if((adapter->hw.phy_type != iegbe_phy_igp) || !adapter->hw.autoneg || + !(adapter->hw.autoneg_advertised & ADVERTISE_1000_FULL)) { +- return; ++ return; + } +- if(adapter->smartspeed == 0) { +- /* If Master/Slave config fault is asserted twice, +- * we assume back-to-back */ +- iegbe_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status); ++ if(adapter->smartspeed == 0x0) { ++ /* If Master/Slave config fault is asserted twice, ++ * we assume back-to-back */ ++ iegbe_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status); + if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) { return; } +- iegbe_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status); ++ iegbe_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status); + if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) { return; } +- iegbe_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl); +- if(phy_ctrl & CR_1000T_MS_ENABLE) { +- phy_ctrl &= ~CR_1000T_MS_ENABLE; +- iegbe_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, +- phy_ctrl); +- adapter->smartspeed++; +- if(!iegbe_phy_setup_autoneg(&adapter->hw) && +- !iegbe_read_phy_reg(&adapter->hw, PHY_CTRL, +- &phy_ctrl)) { +- phy_ctrl |= (MII_CR_AUTO_NEG_EN | +- MII_CR_RESTART_AUTO_NEG); +- iegbe_write_phy_reg(&adapter->hw, PHY_CTRL, +- phy_ctrl); +- } +- } +- return; +- } else if(adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) { +- /* If still no link, perhaps using 2/3 pair cable */ +- iegbe_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl); +- phy_ctrl |= CR_1000T_MS_ENABLE; +- iegbe_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_ctrl); +- if(!iegbe_phy_setup_autoneg(&adapter->hw) && +- !iegbe_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_ctrl)) { +- phy_ctrl |= (MII_CR_AUTO_NEG_EN | +- MII_CR_RESTART_AUTO_NEG); +- iegbe_write_phy_reg(&adapter->hw, PHY_CTRL, phy_ctrl); +- } +- } +- /* Restart process after E1000_SMARTSPEED_MAX iterations */ ++ iegbe_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl); ++ if(phy_ctrl & CR_1000T_MS_ENABLE) { ++ phy_ctrl &= ~CR_1000T_MS_ENABLE; ++ iegbe_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, ++ phy_ctrl); ++ adapter->smartspeed++; ++ if(!iegbe_phy_setup_autoneg(&adapter->hw) && ++ !iegbe_read_phy_reg(&adapter->hw, PHY_CTRL, ++ &phy_ctrl)) { ++ phy_ctrl |= (MII_CR_AUTO_NEG_EN | ++ MII_CR_RESTART_AUTO_NEG); ++ iegbe_write_phy_reg(&adapter->hw, PHY_CTRL, ++ phy_ctrl); ++ } ++ } ++ return; ++ } else if(adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) { ++ /* If still no link, perhaps using 2/3 pair cable */ ++ iegbe_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl); ++ phy_ctrl |= CR_1000T_MS_ENABLE; ++ iegbe_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_ctrl); ++ if(!iegbe_phy_setup_autoneg(&adapter->hw) && ++ !iegbe_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_ctrl)) { ++ phy_ctrl |= (MII_CR_AUTO_NEG_EN | ++ MII_CR_RESTART_AUTO_NEG); ++ iegbe_write_phy_reg(&adapter->hw, PHY_CTRL, phy_ctrl); ++ } ++ } ++ /* Restart process after E1000_SMARTSPEED_MAX iterations */ + if(adapter->smartspeed++ == E1000_SMARTSPEED_MAX) { +- adapter->smartspeed = 0; +-} ++ adapter->smartspeed = 0x0; ++ } + } + + /** +@@ -4576,23 +4311,22 @@ iegbe_smartspeed(struct iegbe_adapter *a + * @cmd: + **/ + +-static int +-iegbe_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) ++static int iegbe_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) + { +- switch (cmd) { ++ switch (cmd) { + #ifdef SIOCGMIIPHY +- case SIOCGMIIPHY: +- case SIOCGMIIREG: +- case SIOCSMIIREG: +- return iegbe_mii_ioctl(netdev, ifr, cmd); ++ case SIOCGMIIPHY: ++ case SIOCGMIIREG: ++ case SIOCSMIIREG: ++ return iegbe_mii_ioctl(netdev, ifr, cmd); + #endif + #ifdef ETHTOOL_OPS_COMPAT +- case SIOCETHTOOL: +- return ethtool_ioctl(ifr); ++ case SIOCETHTOOL: ++ return ethtool_ioctl(ifr); + #endif +- default: +- return -EOPNOTSUPP; +- } ++ default: ++ return -EOPNOTSUPP; ++ } + } + + #ifdef SIOCGMIIPHY +@@ -4603,534 +4337,510 @@ iegbe_ioctl(struct net_device *netdev, s + * @cmd: + **/ + +-static int +-iegbe_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) ++static int iegbe_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, ++ int cmd) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- struct mii_ioctl_data *data = if_mii(ifr); +- int retval; +- uint16_t mii_reg; +- uint16_t spddplx; +- unsigned long flags; +- +- if((adapter->hw.media_type == iegbe_media_type_oem && +- !iegbe_oem_phy_is_copper(&adapter->hw)) || +- adapter->hw.media_type == iegbe_media_type_fiber || +- adapter->hw.media_type == iegbe_media_type_internal_serdes ) { +- return -EOPNOTSUPP; +- } +- switch (cmd) { +- case SIOCGMIIPHY: +- data->phy_id = adapter->hw.phy_addr; +- break; +- case SIOCGMIIREG: ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct mii_ioctl_data *data = if_mii(ifr); ++ int retval; ++ uint16_t mii_reg; ++ uint16_t spddplx; ++ unsigned long flags = 0; ++ ++ if((adapter->hw.media_type == iegbe_media_type_oem ++ && !iegbe_oem_phy_is_copper(&adapter->hw)) ++ ||adapter->hw.media_type != iegbe_media_type_copper) { ++ return -EOPNOTSUPP; ++ } ++ switch (cmd) { ++ case SIOCGMIIPHY: ++ data->phy_id = adapter->hw.phy_addr; ++ break; ++ case SIOCGMIIREG: + if(!capable(CAP_NET_ADMIN)) { +- return -EPERM; ++ return -EPERM; + } +- spin_lock_irqsave(&adapter->stats_lock, flags); +- if(iegbe_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, +- &data->val_out)) { +- spin_unlock_irqrestore(&adapter->stats_lock, flags); +- return -EIO; +- } +- spin_unlock_irqrestore(&adapter->stats_lock, flags); +- break; +- case SIOCSMIIREG: ++ spin_lock_irqsave(&adapter->stats_lock, flags); ++ if(iegbe_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, ++ &data->val_out)) { ++ spin_unlock_irqrestore(&adapter->stats_lock, flags); ++ return -EIO; ++ } ++ spin_unlock_irqrestore(&adapter->stats_lock, flags); ++ break; ++ case SIOCSMIIREG: + if(!capable(CAP_NET_ADMIN)){ +- return -EPERM; ++ return -EPERM; + } + if(data->reg_num & ~(0x1F)) { +- return -EFAULT; ++ return -EFAULT; + } +- mii_reg = data->val_in; +- spin_lock_irqsave(&adapter->stats_lock, flags); +- if(iegbe_write_phy_reg(&adapter->hw, data->reg_num, +- mii_reg)) { +- spin_unlock_irqrestore(&adapter->stats_lock, flags); +- return -EIO; +- } +- switch(adapter->hw.phy_type) { +- case iegbe_phy_m88: +- switch (data->reg_num) { +- case PHY_CTRL: ++ mii_reg = data->val_in; ++ spin_lock_irqsave(&adapter->stats_lock, flags); ++ if(iegbe_write_phy_reg(&adapter->hw, data->reg_num, ++ mii_reg)) { ++ spin_unlock_irqrestore(&adapter->stats_lock, flags); ++ return -EIO; ++ } ++ switch(adapter->hw.phy_type) { ++ case iegbe_phy_m88: ++ switch (data->reg_num) { ++ case PHY_CTRL: + if(mii_reg & MII_CR_POWER_DOWN) { +- break; ++ break; + } +- if(mii_reg & MII_CR_AUTO_NEG_EN) { +- adapter->hw.autoneg = 1; +- adapter->hw.autoneg_advertised = 0x2F; +- } else { ++ if(mii_reg & MII_CR_AUTO_NEG_EN) { ++ adapter->hw.autoneg = 1; ++ adapter->hw.autoneg_advertised = 0x2F; ++ } else { + if(mii_reg & 0x40){ +- spddplx = SPEED_1000; ++ spddplx = SPEED_1000; + } else if(mii_reg & 0x2000) { +- spddplx = SPEED_100; ++ spddplx = SPEED_100; + } else { +- spddplx = SPEED_10; ++ spddplx = SPEED_10; + } +- spddplx += (mii_reg & 0x100) +- ? FULL_DUPLEX : +- HALF_DUPLEX; +- retval = iegbe_set_spd_dplx(adapter, +- spddplx); +- if(retval) { +- spin_unlock_irqrestore( +- &adapter->stats_lock, +- flags); +- return retval; +- } +- } +- if(netif_running(adapter->netdev)) { +- iegbe_down(adapter); +- iegbe_up(adapter); ++ spddplx += (mii_reg & 0x100) ++ ? FULL_DUPLEX : ++ HALF_DUPLEX; ++ retval = iegbe_set_spd_dplx(adapter, ++ spddplx); ++ if(retval) { ++ spin_unlock_irqrestore( ++ &adapter->stats_lock, ++ flags); ++ return retval; ++ } ++ } ++ if(netif_running(adapter->netdev)) { ++ iegbe_down(adapter); ++ iegbe_up(adapter); + } else { +- iegbe_reset(adapter); ++ iegbe_reset(adapter); + } +- break; +- case M88E1000_PHY_SPEC_CTRL: +- case M88E1000_EXT_PHY_SPEC_CTRL: +- if(iegbe_phy_reset(&adapter->hw)) { +- spin_unlock_irqrestore( +- &adapter->stats_lock, flags); +- return -EIO; +- } +- break; +- } +- break; ++ break; ++ case M88E1000_PHY_SPEC_CTRL: ++ case M88E1000_EXT_PHY_SPEC_CTRL: ++ if(iegbe_phy_reset(&adapter->hw)) { ++ spin_unlock_irqrestore( ++ &adapter->stats_lock, flags); ++ return -EIO; ++ } ++ break; ++ } ++ break; + +- case iegbe_phy_oem: +- retval = iegbe_oem_mii_ioctl(adapter, flags, ifr, cmd); +- if(retval) { +- spin_unlock_irqrestore( +- &adapter->stats_lock, flags); +- return retval; +- } +- break; ++ case iegbe_phy_oem: ++ retval = iegbe_oem_mii_ioctl(adapter, flags, ifr, cmd); ++ if(retval) { ++ spin_unlock_irqrestore( ++ &adapter->stats_lock, flags); ++ return retval; ++ } ++ break; + +- default: +- switch (data->reg_num) { +- case PHY_CTRL: ++ default: ++ switch (data->reg_num) { ++ case PHY_CTRL: + if(mii_reg & MII_CR_POWER_DOWN) { +- break; ++ break; + } +- if(netif_running(adapter->netdev)) { +- iegbe_down(adapter); +- iegbe_up(adapter); ++ if(netif_running(adapter->netdev)) { ++ iegbe_down(adapter); ++ iegbe_up(adapter); + } else { +- iegbe_reset(adapter); ++ iegbe_reset(adapter); + } +- break; +- } +- } +- spin_unlock_irqrestore(&adapter->stats_lock, flags); +- break; +- default: +- return -EOPNOTSUPP; +- } +- return E1000_SUCCESS; ++ break; ++ } ++ } ++ spin_unlock_irqrestore(&adapter->stats_lock, flags); ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ return E1000_SUCCESS; + } + #endif + +-void +-iegbe_pci_set_mwi(struct iegbe_hw *hw) ++void iegbe_pci_set_mwi(struct iegbe_hw *hw) + { +- struct iegbe_adapter *adapter = hw->back; +-#ifdef HAVE_PCI_SET_MWI +- int ret_val = pci_set_mwi(adapter->pdev); +- +- if(ret_val) { +- DPRINTK(PROBE, ERR, "Error in setting MWI\n"); +- } +-#else +- pci_write_config_word(adapter->pdev, PCI_COMMAND, +- adapter->hw.pci_cmd_word | +- PCI_COMMAND_INVALIDATE); +-#endif ++ struct iegbe_adapter *adapter = hw->back; ++ int ret_val = pci_set_mwi(adapter->pdev); ++ ++ if (ret_val) ++ DPRINTK(PROBE, ERR, "Error in setting MWI\n"); + } + +-void +-iegbe_pci_clear_mwi(struct iegbe_hw *hw) ++void iegbe_pci_clear_mwi(struct iegbe_hw *hw) + { +- struct iegbe_adapter *adapter = hw->back; ++ struct iegbe_adapter *adapter = hw->back; + +-#ifdef HAVE_PCI_SET_MWI +- pci_clear_mwi(adapter->pdev); +-#else +- pci_write_config_word(adapter->pdev, PCI_COMMAND, +- adapter->hw.pci_cmd_word & +- ~PCI_COMMAND_INVALIDATE); +-#endif ++ pci_clear_mwi(adapter->pdev); + } + + void + iegbe_read_pci_cfg(struct iegbe_hw *hw, uint32_t reg, uint16_t *value) + { +- struct iegbe_adapter *adapter = hw->back; ++ struct iegbe_adapter *adapter = hw->back; + +- pci_read_config_word(adapter->pdev, reg, value); ++ pci_read_config_word(adapter->pdev, reg, value); + } + + void + iegbe_write_pci_cfg(struct iegbe_hw *hw, uint32_t reg, uint16_t *value) + { +- struct iegbe_adapter *adapter = hw->back; ++ struct iegbe_adapter *adapter = hw->back; + +- pci_write_config_word(adapter->pdev, reg, *value); ++ pci_write_config_word(adapter->pdev, reg, *value); + } + + uint32_t + iegbe_io_read(struct iegbe_hw *hw, unsigned long port) + { +- return inl(port); ++ return inl(port); + } + + void + iegbe_io_write(struct iegbe_hw *hw, unsigned long port, uint32_t value) + { +- outl(value, port); ++ outl(value, port); + } + +-#ifdef NETIF_F_HW_VLAN_TX +-static void +-iegbe_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) ++static void iegbe_vlan_rx_register(struct net_device *netdev, ++ struct vlan_group *grp) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- uint32_t ctrl, rctl; +- +- iegbe_irq_disable(adapter); +- adapter->vlgrp = grp; +- +- if(grp) { +- /* enable VLAN tag insert/strip */ +- ctrl = E1000_READ_REG(&adapter->hw, CTRL); +- ctrl |= E1000_CTRL_VME; +- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); +- +- /* enable VLAN receive filtering */ +- rctl = E1000_READ_REG(&adapter->hw, RCTL); +- rctl |= E1000_RCTL_VFE; +- rctl &= ~E1000_RCTL_CFIEN; +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl); +- iegbe_update_mng_vlan(adapter); +- } else { +- /* disable VLAN tag insert/strip */ +- ctrl = E1000_READ_REG(&adapter->hw, CTRL); +- ctrl &= ~E1000_CTRL_VME; +- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ uint32_t ctrl, rctl; + +- /* disable VLAN filtering */ +- rctl = E1000_READ_REG(&adapter->hw, RCTL); +- rctl &= ~E1000_RCTL_VFE; +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl); +- if(adapter->mng_vlan_id != (uint16_t)E1000_MNG_VLAN_NONE) { +- iegbe_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); +- adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; +- } +- } ++ if (!test_bit(__E1000_DOWN, &adapter->flags)) ++ iegbe_irq_disable(adapter); ++ adapter->vlgrp = grp; ++ ++ if(grp) { ++ /* enable VLAN tag insert/strip */ ++ ctrl = E1000_READ_REG(&adapter->hw, CTRL); ++ ctrl |= E1000_CTRL_VME; ++ E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); ++ ++ /* enable VLAN receive filtering */ ++ rctl = E1000_READ_REG(&adapter->hw, RCTL); ++ rctl |= E1000_RCTL_VFE; ++ rctl &= ~E1000_RCTL_CFIEN; ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); ++ iegbe_update_mng_vlan(adapter); ++ } else { ++ /* disable VLAN tag insert/strip */ ++ ctrl = E1000_READ_REG(&adapter->hw, CTRL); ++ ctrl &= ~E1000_CTRL_VME; ++ E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); ++ ++ /* disable VLAN filtering */ ++ rctl = E1000_READ_REG(&adapter->hw, RCTL); ++ rctl &= ~E1000_RCTL_VFE; ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); ++ if(adapter->mng_vlan_id != (uint16_t)E1000_MNG_VLAN_NONE) { ++ iegbe_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); ++ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; ++ } ++ } + +- iegbe_irq_enable(adapter); ++ if (!test_bit(__E1000_DOWN, &adapter->flags)) ++ iegbe_irq_enable(adapter); + } + +-static void +-iegbe_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid) ++static void iegbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- uint32_t vfta, index; +- if((adapter->hw.mng_cookie.status & +- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ uint32_t vfta, index; ++ if((adapter->hw.mng_cookie.status & ++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && + (vid == adapter->mng_vlan_id)) { +- return; ++ return; + } +- /* add VID to filter table */ ++ /* add VID to filter table */ + index = (vid >> 0x5) & 0x7F; +- vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index); ++ vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index); + vfta |= (0x1 << (vid & 0x1F)); +- iegbe_write_vfta(&adapter->hw, index, vfta); ++ iegbe_write_vfta(&adapter->hw, index, vfta); + } + +-static void +-iegbe_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid) ++static void iegbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) + { + struct iegbe_adapter *adapter = netdev_priv(netdev); +- uint32_t vfta, index; ++ u32 vfta, index; + ++ if (!test_bit(__E1000_DOWN, &adapter->flags)) + iegbe_irq_disable(adapter); +- +- if(adapter->vlgrp) { +- adapter->vlgrp->vlan_devices[vid] = NULL; +- } ++ vlan_group_set_device(adapter->vlgrp, vid, NULL); ++ if (!test_bit(__E1000_DOWN, &adapter->flags)) + iegbe_irq_enable(adapter); + +- if((adapter->hw.mng_cookie.status & +- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && +- (vid == adapter->mng_vlan_id)) { +- return; +- } + /* remove VID from filter table */ +- index = (vid >> 0x5) & 0x7F; ++ index = (vid >> 0x5) & 0x7F; + vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index); +- vfta &= ~(0x1 << (vid & 0x1F)); ++ vfta &= ~(0x1 << (vid & 0x1F)); + iegbe_write_vfta(&adapter->hw, index, vfta); + } + +-static void +-iegbe_restore_vlan(struct iegbe_adapter *adapter) ++static void iegbe_restore_vlan(struct iegbe_adapter *adapter) + { + iegbe_vlan_rx_register(adapter->netdev, adapter->vlgrp); + +- if(adapter->vlgrp) { +- uint16_t vid; +- for(vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { +- if(!adapter->vlgrp->vlan_devices[vid]) { ++ if (adapter->vlgrp) { ++ u16 vid; ++ for (vid = 0x0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { ++ if (!vlan_group_get_device(adapter->vlgrp, vid)) + continue; +- } + iegbe_vlan_rx_add_vid(adapter->netdev, vid); + } + } + } +-#endif + +-int +-iegbe_set_spd_dplx(struct iegbe_adapter *adapter, uint16_t spddplx) ++ ++int iegbe_set_spd_dplx(struct iegbe_adapter *adapter, u16 spddplx) + { +- adapter->hw.autoneg = 0; ++ adapter->hw.autoneg = 0x0; + +- /* Fiber NICs only allow 1000 gbps Full duplex */ +- if((adapter->hw.media_type == iegbe_media_type_fiber ++ /* Fiber NICs only allow 1000 gbps Full duplex */ ++ if((adapter->hw.media_type == iegbe_media_type_fiber + || (adapter->hw.media_type == iegbe_media_type_oem + && !iegbe_oem_phy_is_copper(&adapter->hw))) +- && spddplx != (SPEED_1000 + FULL_DUPLEX)) { +- DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n"); +- return -EINVAL; +- } +- +- switch(spddplx) { +- case SPEED_10 + HALF_DUPLEX: +- adapter->hw.forced_speed_duplex = iegbe_10_half; +- break; +- case SPEED_10 + FULL_DUPLEX: +- adapter->hw.forced_speed_duplex = iegbe_10_full; +- break; +- case SPEED_100 + HALF_DUPLEX: +- adapter->hw.forced_speed_duplex = iegbe_100_half; +- break; +- case SPEED_100 + FULL_DUPLEX: +- adapter->hw.forced_speed_duplex = iegbe_100_full; +- break; +- case SPEED_1000 + FULL_DUPLEX: ++ && spddplx != (SPEED_1000 + DUPLEX_FULL)) { ++ DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n"); ++ return -EINVAL; ++ } ++ ++ switch(spddplx) { ++ case SPEED_10 + DUPLEX_HALF: ++ adapter->hw.forced_speed_duplex = iegbe_10_half; ++ break; ++ case SPEED_10 + DUPLEX_FULL: ++ adapter->hw.forced_speed_duplex = iegbe_10_full; ++ break; ++ case SPEED_100 + DUPLEX_HALF: ++ adapter->hw.forced_speed_duplex = iegbe_100_half; ++ break; ++ case SPEED_100 + DUPLEX_FULL: ++ adapter->hw.forced_speed_duplex = iegbe_100_full; ++ break; ++ case SPEED_1000 + DUPLEX_FULL: + adapter->hw.autoneg = 0x1; +- adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; +- break; +- case SPEED_1000 + HALF_DUPLEX: /* not supported */ +- default: +- DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n"); +- return -EINVAL; +- } +- return 0; ++ adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; ++ break; ++ case SPEED_1000 + DUPLEX_HALF: /* not supported */ ++ default: ++ DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n"); ++ return -EINVAL; ++ } ++ return 0x0; + } + + static int + iegbe_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) + { +- struct pci_dev *pdev = NULL; ++ struct pci_dev *pdev = NULL; + pm_message_t state = {0x3}; + + +- switch(event) { +- case SYS_DOWN: +- case SYS_HALT: +- case SYS_POWER_OFF: +- while((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) { ++ switch(event) { ++ case SYS_DOWN: ++ case SYS_HALT: ++ case SYS_POWER_OFF: ++ while((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) { + if(pci_dev_driver(pdev) == &iegbe_driver) { +- iegbe_suspend(pdev, state); +- } +- } ++ iegbe_suspend(pdev, state); ++ } ++ } + } +- return NOTIFY_DONE; ++ return NOTIFY_DONE; + } + + static int + iegbe_suspend(struct pci_dev *pdev, pm_message_t state) + { +- struct net_device *netdev = pci_get_drvdata(pdev); +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- uint32_t ctrl, ctrl_ext, rctl, manc, status, swsm; +- uint32_t wufc = adapter->wol; +- uint16_t cmd_word; ++ struct net_device *netdev = pci_get_drvdata(pdev); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ uint32_t ctrl, ctrl_ext, rctl, manc, status, swsm; ++ uint32_t wufc = adapter->wol; ++ uint16_t cmd_word; + +- netif_device_detach(netdev); ++ netif_device_detach(netdev); + + if(netif_running(netdev)) { +- iegbe_down(adapter); ++ WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags)); ++ iegbe_down(adapter); + } +- /* +- * ICP_XXXX style MACs do not have a link up bit in +- * the STATUS register, query the PHY directly +- */ +- if(adapter->hw.mac_type != iegbe_icp_xxxx) { +- status = E1000_READ_REG(&adapter->hw, STATUS); ++ /* ++ * ICP_XXXX style MACs do not have a link up bit in ++ * the STATUS register, query the PHY directly ++ */ ++ if(adapter->hw.mac_type != iegbe_icp_xxxx) { ++ status = E1000_READ_REG(&adapter->hw, STATUS); + if(status & E1000_STATUS_LU) { +- wufc &= ~E1000_WUFC_LNKC; ++ wufc &= ~E1000_WUFC_LNKC; + } +- } else { +- int isUp = 0; ++ } else { ++ int isUp = 0x0; + if(iegbe_oem_phy_is_link_up(&adapter->hw, &isUp) != E1000_SUCCESS) { +- isUp = 0; ++ isUp = 0x0; + } + if(isUp) { +- wufc &= ~E1000_WUFC_LNKC; +- } ++ wufc &= ~E1000_WUFC_LNKC; ++ } + } + +- if(wufc) { +- iegbe_setup_rctl(adapter); +- iegbe_set_multi(netdev); +- +- /* turn on all-multi mode if wake on multicast is enabled */ +- if(adapter->wol & E1000_WUFC_MC) { +- rctl = E1000_READ_REG(&adapter->hw, RCTL); +- rctl |= E1000_RCTL_MPE; +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl); +- } ++ if(wufc) { ++ iegbe_setup_rctl(adapter); ++ iegbe_set_rx_mode(netdev); ++ ++ /* turn on all-multi mode if wake on multicast is enabled */ ++ if(adapter->wol & E1000_WUFC_MC) { ++ rctl = E1000_READ_REG(&adapter->hw, RCTL); ++ rctl |= E1000_RCTL_MPE; ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); ++ } + +- if(adapter->hw.mac_type >= iegbe_82540) { +- ctrl = E1000_READ_REG(&adapter->hw, CTRL); +- /* advertise wake from D3Cold */ +- #define E1000_CTRL_ADVD3WUC 0x00100000 +- /* phy power management enable */ +- ctrl |= E1000_CTRL_ADVD3WUC | +- (adapter->hw.mac_type != iegbe_icp_xxxx +- ? E1000_CTRL_EN_PHY_PWR_MGMT : 0); ++ if(adapter->hw.mac_type >= iegbe_82540) { ++ ctrl = E1000_READ_REG(&adapter->hw, CTRL); ++ /* advertise wake from D3Cold */ ++ #define E1000_CTRL_ADVD3WUC 0x00100000 ++ /* phy power management enable */ ++ #define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 ++ ctrl |= E1000_CTRL_ADVD3WUC | ++ (adapter->hw.mac_type != iegbe_icp_xxxx ++ ? E1000_CTRL_EN_PHY_PWR_MGMT : 0x0); + +- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); +- } ++ E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); ++ } + +- if(adapter->hw.media_type == iegbe_media_type_fiber || +- adapter->hw.media_type == iegbe_media_type_internal_serdes) { +- /* keep the laser running in D3 */ +- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); +- ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA; +- E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ctrl_ext); +- } ++ if(adapter->hw.media_type == iegbe_media_type_fiber || ++ adapter->hw.media_type == iegbe_media_type_internal_serdes) { ++ /* keep the laser running in D3 */ ++ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); ++ ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA; ++ E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ctrl_ext); ++ } + + /* Allow OEM PHYs (if any exist) to keep the laser + *running in D3 */ + iegbe_oem_fiber_live_in_suspend(&adapter->hw); + +- /* Allow time for pending master requests to run */ +- iegbe_disable_pciex_master(&adapter->hw); ++ /* Allow time for pending master requests to run */ ++ iegbe_disable_pciex_master(&adapter->hw); + +- E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN); +- E1000_WRITE_REG(&adapter->hw, WUFC, wufc); ++ E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN); ++ E1000_WRITE_REG(&adapter->hw, WUFC, wufc); + pci_enable_wake(pdev, 0x3, 0x1); + pci_enable_wake(pdev, 0x4, 0x1); /* 4 == D3 cold */ +- } else { +- E1000_WRITE_REG(&adapter->hw, WUC, 0); +- E1000_WRITE_REG(&adapter->hw, WUFC, 0); +- pci_enable_wake(pdev, 0x3, 0); +- pci_enable_wake(pdev, 0x4, 0); /* 4 == D3 cold */ +- } ++ } else { ++ E1000_WRITE_REG(&adapter->hw, WUC, 0x0); ++ E1000_WRITE_REG(&adapter->hw, WUFC, 0x0); ++ pci_enable_wake(pdev, 0x3, 0x0); ++ pci_enable_wake(pdev, 0x4, 0x0); /* 4 == D3 cold */ ++ } + +- pci_save_state(pdev); +- +- if(adapter->hw.mac_type >= iegbe_82540 +- && adapter->hw.mac_type != iegbe_icp_xxxx +- && adapter->hw.media_type == iegbe_media_type_copper) { +- manc = E1000_READ_REG(&adapter->hw, MANC); +- if(manc & E1000_MANC_SMBUS_EN) { +- manc |= E1000_MANC_ARP_EN; +- E1000_WRITE_REG(&adapter->hw, MANC, manc); ++ pci_save_state(pdev); ++ ++ if(adapter->hw.mac_type >= iegbe_82540 ++ && adapter->hw.mac_type != iegbe_icp_xxxx ++ && adapter->hw.media_type == iegbe_media_type_copper) { ++ manc = E1000_READ_REG(&adapter->hw, MANC); ++ if(manc & E1000_MANC_SMBUS_EN) { ++ manc |= E1000_MANC_ARP_EN; ++ E1000_WRITE_REG(&adapter->hw, MANC, manc); + pci_enable_wake(pdev, 0x3, 0x1); + pci_enable_wake(pdev, 0x4, 0x1); /* 4 == D3 cold */ +- } +- } ++ } ++ } + +- switch(adapter->hw.mac_type) { +- case iegbe_82571: +- case iegbe_82572: +- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); +- E1000_WRITE_REG(&adapter->hw, CTRL_EXT, +- ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); +- break; +- case iegbe_82573: +- swsm = E1000_READ_REG(&adapter->hw, SWSM); +- E1000_WRITE_REG(&adapter->hw, SWSM, +- swsm & ~E1000_SWSM_DRV_LOAD); +- break; +- default: +- break; +- } ++ switch(adapter->hw.mac_type) { ++ case iegbe_82571: ++ case iegbe_82572: ++ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); ++ E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ++ ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); ++ break; ++ case iegbe_82573: ++ swsm = E1000_READ_REG(&adapter->hw, SWSM); ++ E1000_WRITE_REG(&adapter->hw, SWSM, ++ swsm & ~E1000_SWSM_DRV_LOAD); ++ break; ++ default: ++ break; ++ } + +- pci_disable_device(pdev); +- if(adapter->hw.mac_type == iegbe_icp_xxxx) { +- /* +- * ICP xxxx devices are not true PCI devices, in the context +- * of power management, disabling the bus mastership is not +- * sufficient to disable the device, it is also necessary to +- * disable IO, Memory, and Interrupts if they are enabled. +- */ +- pci_read_config_word(pdev, PCI_COMMAND, &cmd_word); ++ pci_disable_device(pdev); ++ if(adapter->hw.mac_type == iegbe_icp_xxxx) { ++ /* ++ * ICP xxxx devices are not true PCI devices, in the context ++ * of power management, disabling the bus mastership is not ++ * sufficient to disable the device, it is also necessary to ++ * disable IO, Memory, and Interrupts if they are enabled. ++ */ ++ pci_read_config_word(pdev, PCI_COMMAND, &cmd_word); + if(cmd_word & PCI_COMMAND_IO) { +- cmd_word &= ~PCI_COMMAND_IO; ++ cmd_word &= ~PCI_COMMAND_IO; + } + if(cmd_word & PCI_COMMAND_MEMORY) { +- cmd_word &= ~PCI_COMMAND_MEMORY; ++ cmd_word &= ~PCI_COMMAND_MEMORY; + } + if(cmd_word & PCI_COMMAND_INTX_DISABLE) { +- cmd_word &= ~PCI_COMMAND_INTX_DISABLE; ++ cmd_word &= ~PCI_COMMAND_INTX_DISABLE; + } +- pci_write_config_word(pdev, PCI_COMMAND, cmd_word); +- } ++ pci_write_config_word(pdev, PCI_COMMAND, cmd_word); ++ } + +- state.event = (state.event > 0) ? 0x3 : 0; +- pci_set_power_state(pdev, state.event); +- if(gcu_suspend == 0) ++ state.event = (state.event > 0x0) ? 0x3 : 0x0; ++ pci_set_power_state(pdev, state.event); ++ if(gcu_suspend == 0x0) + { + if(gcu == NULL) { +- gcu = pci_find_device(PCI_VENDOR_ID_INTEL, GCU_DEVID, NULL); +- } ++ gcu = pci_get_device(PCI_VENDOR_ID_INTEL, GCU_DEVID, NULL); ++ } + gcu_iegbe_suspend(gcu, 0x3); +- gcu_suspend = 1; +- gcu_resume = 0; ++ gcu_suspend = 0x1; ++ gcu_resume = 0x0; + } +- return 0; ++ return 0x0; + } + + #ifdef CONFIG_PM + static int + iegbe_resume(struct pci_dev *pdev) + { +- struct net_device *netdev = pci_get_drvdata(pdev); +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- uint32_t manc, ret_val, swsm; +- uint32_t ctrl_ext; ++ struct net_device *netdev = pci_get_drvdata(pdev); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ uint32_t manc, ret_val, swsm; ++ uint32_t ctrl_ext; + int offset; + uint32_t vdid; + +- if(gcu_resume == 0) ++ if(gcu_resume == 0x0) + { + if(gcu == NULL) { +- gcu = pci_find_device(PCI_VENDOR_ID_INTEL, GCU_DEVID, NULL); ++ gcu = pci_get_device(PCI_VENDOR_ID_INTEL, GCU_DEVID, NULL); + pci_read_config_dword(gcu, 0x00, &vdid); +- } +- ++ } ++ + if(gcu) { + gcu_iegbe_resume(gcu); +- gcu_resume = 1; +- gcu_suspend = 0; ++ gcu_resume = 0x1; ++ gcu_suspend = 0x0; + } else { + printk("Unable to resume GCU!\n"); +- } ++ } + } + pci_set_power_state(pdev, 0x0); +- pci_restore_state(pdev); +- ret_val = pci_enable_device(pdev); +- pci_set_master(pdev); ++ pci_restore_state(pdev); ++ ret_val = pci_enable_device(pdev); ++ pci_set_master(pdev); + + pci_enable_wake(pdev, 0x3, 0x0); + pci_enable_wake(pdev, 0x4, 0x0); /* 4 == D3 cold */ + +- iegbe_reset(adapter); +- E1000_WRITE_REG(&adapter->hw, WUS, ~0); ++ iegbe_reset(adapter); ++ E1000_WRITE_REG(&adapter->hw, WUS, ~0); + offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_ST) + + PCI_ST_SMIA_OFFSET; + pci_write_config_dword(adapter->pdev, offset, 0x00000006); +@@ -5138,51 +4848,52 @@ iegbe_resume(struct pci_dev *pdev) + E1000_WRITE_REG(&adapter->hw, IMC2, ~0UL); + + if(netif_running(netdev)) { +- iegbe_up(adapter); ++ iegbe_up(adapter); + } +- netif_device_attach(netdev); +- +- if(adapter->hw.mac_type >= iegbe_82540 +- && adapter->hw.mac_type != iegbe_icp_xxxx +- && adapter->hw.media_type == iegbe_media_type_copper) { +- manc = E1000_READ_REG(&adapter->hw, MANC); +- manc &= ~(E1000_MANC_ARP_EN); +- E1000_WRITE_REG(&adapter->hw, MANC, manc); +- } ++ netif_device_attach(netdev); + +- switch(adapter->hw.mac_type) { +- case iegbe_82571: +- case iegbe_82572: +- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); +- E1000_WRITE_REG(&adapter->hw, CTRL_EXT, +- ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); +- break; +- case iegbe_82573: +- swsm = E1000_READ_REG(&adapter->hw, SWSM); +- E1000_WRITE_REG(&adapter->hw, SWSM, +- swsm | E1000_SWSM_DRV_LOAD); +- break; +- default: +- break; +- } ++ if(adapter->hw.mac_type >= iegbe_82540 ++ && adapter->hw.mac_type != iegbe_icp_xxxx ++ && adapter->hw.media_type == iegbe_media_type_copper) { ++ manc = E1000_READ_REG(&adapter->hw, MANC); ++ manc &= ~(E1000_MANC_ARP_EN); ++ E1000_WRITE_REG(&adapter->hw, MANC, manc); ++ } ++ ++ switch(adapter->hw.mac_type) { ++ case iegbe_82571: ++ case iegbe_82572: ++ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); ++ E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ++ ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); ++ break; ++ case iegbe_82573: ++ swsm = E1000_READ_REG(&adapter->hw, SWSM); ++ E1000_WRITE_REG(&adapter->hw, SWSM, ++ swsm | E1000_SWSM_DRV_LOAD); ++ break; ++ default: ++ break; ++ } ++#endif + +- return 0; ++ return 0x0; + } +-#endif ++ + #ifdef CONFIG_NET_POLL_CONTROLLER + /* + * Polling 'interrupt' - used by things like netconsole to send skbs + * without having to re-enable interrupts. It's not called while + * the interrupt routine is executing. + */ +-static void +-iegbe_netpoll(struct net_device *netdev) ++static void iegbe_netpoll(struct net_device *netdev) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- disable_irq(adapter->pdev->irq); +- iegbe_intr(adapter->pdev->irq, netdev, NULL); +- enable_irq(adapter->pdev->irq); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ disable_irq(adapter->pdev->irq); ++ iegbe_intr(adapter->pdev->irq, netdev); ++ enable_irq(adapter->pdev->irq); + } + #endif + ++ + /* iegbe_main.c */ +--- a/Embedded/src/GbE/iegbe_oem_phy.c ++++ b/Embedded/src/GbE/iegbe_oem_phy.c +@@ -2,31 +2,31 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + +- This program is free software; you can redistribute it and/or modify ++ This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + +- 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 ++ 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 ++ 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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- The full GNU General Public License is included in this distribution ++ The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +- Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226 ++ Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226 + + *****************************************************************************/ + /************************************************************************** +@@ -65,11 +65,6 @@ static int32_t iegbe_oem_link_m88_setup( + static int32_t iegbe_oem_set_phy_mode(struct iegbe_hw *hw); + static int32_t iegbe_oem_detect_phy(struct iegbe_hw *hw); + +-/* Define specific BCM functions */ +-static int32_t iegbe_oem_link_bcm5481_setup(struct iegbe_hw *hw); +-static int32_t bcm5481_read_18sv (struct iegbe_hw *hw, int sv, uint16_t *data); +-static int32_t oi_phy_setup (struct iegbe_hw *hw); +- + /** + * iegbe_oem_setup_link + * @hw: iegbe_hw struct containing device specific information +@@ -84,7 +79,7 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + { + #ifdef EXTERNAL_MDIO + +- /* ++ /* + * see iegbe_setup_copper_link() as the primary example. Look at both + * the M88 and IGP functions that are called for ideas, possibly for + * power management. +@@ -102,14 +97,14 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + } + /* AFU: add test to exit out if improper phy type + */ +- /* relevent parts of iegbe_copper_link_preconfig */ +- ctrl = E1000_READ_REG(hw, CTRL); +- ctrl |= E1000_CTRL_SLU; +- ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); +- E1000_WRITE_REG(hw, CTRL, ctrl); +- ++ /* relevent parts of iegbe_copper_link_preconfig */ ++ ctrl = E1000_READ_REG(hw, CTRL); ++ ctrl |= E1000_CTRL_SLU; ++ ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); ++ E1000_WRITE_REG(hw, CTRL, ctrl); ++ + /* this is required for *hw init */ +- ret_val = iegbe_oem_detect_phy(hw); ++ ret_val = iegbe_oem_detect_phy(hw); + if(ret_val) { + return ret_val; + } +@@ -119,23 +114,13 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + } + + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- return E1000_SUCCESS; +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_link_m88_setup(hw); +- if(ret_val) { +- return ret_val; +- } +- break; +- case BCM5481_PHY_ID: +- ret_val = iegbe_oem_link_bcm5481_setup(hw); +- if(ret_val) { +- return ret_val; ++ if(ret_val) { ++ return ret_val; + } +- break; ++ break; + default: + DEBUGOUT("Invalid PHY ID\n"); + return -E1000_ERR_PHY_TYPE; +@@ -143,16 +128,16 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + + if(hw->autoneg) { + ret_val = iegbe_copper_link_autoneg(hw); +- if(ret_val) { +- return ret_val; +- } ++ if(ret_val) { ++ return ret_val; + } ++ } + else { + DEBUGOUT("Forcing speed and duplex\n"); + ret_val = iegbe_phy_force_speed_duplex(hw); + } +- +- /* ++ ++ /* + * Check link status. Wait up to 100 microseconds for link to become + * valid. + */ +@@ -194,51 +179,6 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + #endif /* ifdef EXTERNAL_MDIO */ + } + +-/** +- * iegbe_oem_link_bcm5481_setup +- * @hw: iegbe_hw struct containing device specific information +- * +- * Returns E1000_SUCCESS, negative E1000 error code on failure +- * +- * copied verbatim from iegbe_oem_link_m88_setup +- **/ +-static int32_t +-iegbe_oem_link_bcm5481_setup(struct iegbe_hw *hw) +-{ +- int32_t ret_val; +- uint16_t phy_data; +- +- //DEBUGFUNC(__func__); +- +- if(!hw) +- return -1; +- +- /* phy_reset_disable is set in iegbe_oem_set_phy_mode */ +- if(hw->phy_reset_disable) +- return E1000_SUCCESS; +- +- // Enable MDIX in extended control reg. +- ret_val = iegbe_oem_read_phy_reg_ex(hw, BCM5481_ECTRL, &phy_data); +- if(ret_val) +- { +- DEBUGOUT("Unable to read BCM5481_ECTRL register\n"); +- return ret_val; +- } +- +- phy_data &= ~BCM5481_ECTRL_DISMDIX; +- ret_val = iegbe_oem_write_phy_reg_ex(hw, BCM5481_ECTRL, phy_data); +- if(ret_val) +- { +- DEBUGOUT("Unable to write BCM5481_ECTRL register\n"); +- return ret_val; +- } +- +- ret_val = oi_phy_setup (hw); +- if (ret_val) +- return ret_val; +- +- return E1000_SUCCESS; +-} + + /** + * iegbe_oem_link_m88_setup +@@ -253,7 +193,7 @@ static int32_t + iegbe_oem_link_m88_setup(struct iegbe_hw *hw) + { + int32_t ret_val; +- uint16_t phy_data; ++ uint16_t phy_data = 0; + + DEBUGFUNC1("%s",__func__); + +@@ -261,7 +201,7 @@ iegbe_oem_link_m88_setup(struct iegbe_hw + return -1; + } + +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, + &phy_data); + phy_data |= 0x00000008; + ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, phy_data); +@@ -279,7 +219,7 @@ iegbe_oem_link_m88_setup(struct iegbe_hw + + phy_data &= ~M88E1000_PSCR_ASSERT_CRS_ON_TX; + +- /* ++ /* + * Options: + * MDI/MDI-X = 0 (default) + * 0 - Auto for all speeds +@@ -305,7 +245,7 @@ iegbe_oem_link_m88_setup(struct iegbe_hw + break; + } + +- /* ++ /* + * Options: + * disable_polarity_correction = 0 (default) + * Automatic Correction for Reversed Cable Polarity +@@ -316,25 +256,25 @@ iegbe_oem_link_m88_setup(struct iegbe_hw + + if(hw->disable_polarity_correction == 1) { + phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; +- } ++ } + ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, phy_data); + if(ret_val) { + DEBUGOUT("Unable to write M88E1000_PHY_SPEC_CTRL register\n"); + return ret_val; + } + +- /* ++ /* + * Force TX_CLK in the Extended PHY Specific Control Register + * to 25MHz clock. + */ +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_EXT_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_EXT_PHY_SPEC_CTRL, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read M88E1000_EXT_PHY_SPEC_CTRL register\n"); + return ret_val; + } + +- /* ++ /* + * For Truxton, it is necessary to add RGMII tx and rx + * timing delay though the EXT_PHY_SPEC_CTRL register + */ +@@ -350,13 +290,13 @@ iegbe_oem_link_m88_setup(struct iegbe_hw + phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | + M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); + } +- ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_EXT_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_EXT_PHY_SPEC_CTRL, + phy_data); + if(ret_val) { + DEBUGOUT("Unable to read M88E1000_EXT_PHY_SPEC_CTRL register\n"); + return ret_val; + } +- ++ + + /* SW Reset the PHY so all changes take effect */ + ret_val = iegbe_phy_hw_reset(hw); +@@ -371,7 +311,7 @@ iegbe_oem_link_m88_setup(struct iegbe_hw + /** + * iegbe_oem_force_mdi + * @hw: iegbe_hw struct containing device specific information +- * @resetPhy: returns true if after calling this function the ++ * @resetPhy: returns true if after calling this function the + * PHY requires a reset + * + * Returns E1000_SUCCESS, negative E1000 error code on failure +@@ -379,7 +319,7 @@ iegbe_oem_link_m88_setup(struct iegbe_hw + * This is called from iegbe_phy_force_speed_duplex, which is + * called from iegbe_oem_setup_link. + **/ +-int32_t ++int32_t + iegbe_oem_force_mdi(struct iegbe_hw *hw, int *resetPhy) + { + #ifdef EXTERNAL_MDIO +@@ -393,35 +333,30 @@ iegbe_oem_force_mdi(struct iegbe_hw *hw, + return -1; + } + +- /* ++ /* + * a boolean to indicate if the phy needs to be reset +- * ++ * + * Make note that the M88 phy is what'll be used on Truxton + * see iegbe_phy_force_speed_duplex, which does the following for M88 + */ + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_force_mdi() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- ret_val = iegbe_oem_read_phy_reg_ex(hw, +- M88E1000_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, ++ M88E1000_PHY_SPEC_CTRL, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read M88E1000_PHY_SPEC_CTRL register\n"); + return ret_val; + } +- ++ + /* +- * Clear Auto-Crossover to force MDI manually. M88E1000 requires ++ * Clear Auto-Crossover to force MDI manually. M88E1000 requires + * MDI forced whenever speed are duplex are forced. + */ +- ++ + phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; +- ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, + phy_data); + if(ret_val) { + DEBUGOUT("Unable to write M88E1000_PHY_SPEC_CTRL register\n"); +@@ -458,7 +393,7 @@ iegbe_oem_force_mdi(struct iegbe_hw *hw, + * This is called from iegbe_phy_force_speed_duplex, which is + * called from iegbe_oem_setup_link. + **/ +-int32_t ++int32_t + iegbe_oem_phy_reset_dsp(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -478,10 +413,8 @@ iegbe_oem_phy_reset_dsp(struct iegbe_hw + * no-op. + */ + switch (hw->phy_id) { +- case M88E1000_I_PHY_ID: +- case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: +- case BCM5395S_PHY_ID: ++ case M88E1000_I_PHY_ID: ++ case M88E1141_E_PHY_ID: + DEBUGOUT("No DSP to reset on OEM PHY\n"); + break; + default: +@@ -508,7 +441,7 @@ iegbe_oem_phy_reset_dsp(struct iegbe_hw + * This is called from iegbe_phy_force_speed_duplex, which is + * called from iegbe_oem_setup_link. + **/ +-int32_t ++int32_t + iegbe_oem_cleanup_after_phy_reset(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -520,29 +453,24 @@ iegbe_oem_cleanup_after_phy_reset(struct + + if(!hw) { + return -1; +- } ++ } + +- /* ++ /* + * Make note that the M88 phy is what'll be used on Truxton. + * see iegbe_phy_force_speed_duplex, which does the following for M88 + */ + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_cleanup_after_phy_reset() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + /* +- * Because we reset the PHY above, we need to re-force ++ * Because we reset the PHY above, we need to re-force + * TX_CLK in the Extended PHY Specific Control Register to + * 25MHz clock. This value defaults back to a 2.5MHz clock + * when the PHY is reset. + */ + + ret_val = iegbe_oem_read_phy_reg_ex(hw, +- M88E1000_EXT_PHY_SPEC_CTRL, ++ M88E1000_EXT_PHY_SPEC_CTRL, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read M88E1000_EXT_SPEC_CTRL register\n"); +@@ -550,22 +478,23 @@ iegbe_oem_cleanup_after_phy_reset(struct + } + + phy_data |= M88E1000_EPSCR_TX_CLK_25; +- ret_val = iegbe_oem_write_phy_reg_ex(hw, +- M88E1000_EXT_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_write_phy_reg_ex(hw, ++ M88E1000_EXT_PHY_SPEC_CTRL, + phy_data); + if(ret_val) { +- DEBUGOUT("Unable to write M88E1000_EXT_PHY_SPEC_CTRL register\n"); ++ DEBUGOUT("Unable to write M88E1000_EXT_PHY_SPEC_CTRL " ++ "register\n"); + return ret_val; + } + + /* + * In addition, because of the s/w reset above, we need to enable +- * CRX on TX. This must be set for both full and half duplex ++ * CRX on TX. This must be set for both full and half duplex + * operation. + */ + +- ret_val = iegbe_oem_read_phy_reg_ex(hw, +- M88E1000_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, ++ M88E1000_PHY_SPEC_CTRL, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read M88E1000_PHY_SPEC_CTRL register\n"); +@@ -573,12 +502,12 @@ iegbe_oem_cleanup_after_phy_reset(struct + } + + phy_data &= ~M88E1000_PSCR_ASSERT_CRS_ON_TX; +- ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, + phy_data); + if(ret_val) { + DEBUGOUT("Unable to write M88E1000_PHY_SPEC_CTRL register\n"); + return ret_val; +- } ++ } + break; + default: + DEBUGOUT("Invalid PHY ID\n"); +@@ -604,12 +533,12 @@ iegbe_oem_cleanup_after_phy_reset(struct + * This is called from iegbe_oem_setup_link which is + * called from iegbe_setup_link. + **/ +-static int32_t ++static int32_t + iegbe_oem_set_phy_mode(struct iegbe_hw *hw) + { + /* + * it is unclear if it is necessary to set the phy mode. Right now only +- * one MAC 82545 Rev 3 does it, but the other MACs like Tolapai do not. ++ * one MAC 82545 Rev 3 does it, but the other MACs like tola do not. + * Leave the functionality off for now until it is determined that Tolapai + * needs it as well. + */ +@@ -638,41 +567,37 @@ iegbe_oem_set_phy_mode(struct iegbe_hw * + #ifndef skip_set_mode + DEBUGOUT("No need to call oem_set_phy_mode on Truxton\n"); + #else +- /* ++ /* + * Make note that the M88 phy is what'll be used on Truxton. + * + * use iegbe_set_phy_mode as example + */ + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_set_phy_mode() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- ret_val = iegbe_read_eeprom(hw, +- EEPROM_PHY_CLASS_WORD, +- 1, ++ ret_val = iegbe_read_eeprom(hw, ++ EEPROM_PHY_CLASS_WORD, ++ 1, + &eeprom_data); + if(ret_val) { + return ret_val; + } + +- if((eeprom_data != EEPROM_RESERVED_WORD) && +- (eeprom_data & EEPROM_PHY_CLASS_A)) ++ if((eeprom_data != EEPROM_RESERVED_WORD) && ++ (eeprom_data & EEPROM_PHY_CLASS_A)) + { +- ret_val = iegbe_oem_write_phy_reg_ex(hw, +- M88E1000_PHY_PAGE_SELECT, +- 0x000B); ++ ret_val = iegbe_oem_write_phy_reg_ex(hw, ++ M88E1000_PHY_PAGE_SELECT, ++ 0x000B); + if(ret_val) { +- DEBUGOUT("Unable to write to M88E1000_PHY_PAGE_SELECT register on PHY\n"); ++ DEBUGOUT("Unable to write to M88E1000_PHY_PAGE_SELECT " ++ "register on PHY\n"); + return ret_val; + } + +- ret_val = iegbe_oem_write_phy_reg_ex(hw, +- M88E1000_PHY_GEN_CONTROL, +- 0x8104); ++ ret_val = iegbe_oem_write_phy_reg_ex(hw, ++ M88E1000_PHY_GEN_CONTROL, ++ 0x8104); + if(ret_val) { + DEBUGOUT("Unable to write to M88E1000_PHY_GEN_CONTROL" + "register on PHY\n"); +@@ -687,11 +612,12 @@ iegbe_oem_set_phy_mode(struct iegbe_hw * + return -E1000_ERR_PHY_TYPE; + } + #endif +- ++ + return E1000_SUCCESS; + + } + ++ + /** + * iegbe_oem_detect_phy + * @hw: iegbe_hw struct containing device specific information +@@ -702,7 +628,7 @@ iegbe_oem_set_phy_mode(struct iegbe_hw * + * + * This borrows heavily from iegbe_detect_gig_phy + **/ +-static int32_t ++static int32_t + iegbe_oem_detect_phy(struct iegbe_hw *hw) + { + int32_t ret_val; +@@ -715,33 +641,20 @@ iegbe_oem_detect_phy(struct iegbe_hw *hw + } + hw->phy_type = iegbe_phy_oem; + +-{ +- // If MAC2 (BCM5395 switch), manually detect the phy +- struct iegbe_adapter *adapter; +- uint32_t device_number; +- adapter = (struct iegbe_adapter *) hw->back; +- device_number = PCI_SLOT(adapter->pdev->devfn); +- if (device_number == ICP_XXXX_MAC_2) { +- hw->phy_id = BCM5395S_PHY_ID; +- hw->phy_revision = 0; +- return E1000_SUCCESS; +- } +-} +- +- + ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_ID1, &phy_id_high); + if(ret_val) { + DEBUGOUT("Unable to read PHY register PHY_ID1\n"); + return ret_val; + } +- ++ + usec_delay(0x14); + ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_ID2, &phy_id_low); + if(ret_val) { + DEBUGOUT("Unable to read PHY register PHY_ID2\n"); + return ret_val; + } +- hw->phy_id = (uint32_t) ((phy_id_high << 0x10) + phy_id_low); ++ hw->phy_id = (uint32_t) ((phy_id_high << 0x10) + ++ (phy_id_low & PHY_REVISION_MASK)); + hw->phy_revision = (uint32_t) phy_id_low & ~PHY_REVISION_MASK; + + return E1000_SUCCESS; +@@ -753,15 +666,15 @@ iegbe_oem_detect_phy(struct iegbe_hw *hw + * @hw: iegbe_hw struct containing device specific information + * + * Returns the value of the Inter Packet Gap (IPG) Transmit Time (IPGT) in the +- * Transmit IPG register appropriate for the given PHY. This field is only 10 ++ * Transmit IPG register appropriate for the given PHY. This field is only 10 + * bits wide. + * + * In the original iegbe code, only the IPGT field varied between media types. +- * If the OEM phy requires setting IPG Receive Time 1 & 2 Registers, it would ++ * If the OEM phy requires setting IPG Receive Time 1 & 2 Registers, it would + * be required to modify the iegbe_config_tx() function to accomdate the change + * + **/ +-uint32_t ++uint32_t + iegbe_oem_get_tipg(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -777,15 +690,13 @@ iegbe_oem_get_tipg(struct iegbe_hw *hw) + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: +- case BCM5395S_PHY_ID: + phy_num = DEFAULT_ICP_XXXX_TIPG_IPGT; + break; + default: + DEBUGOUT("Invalid PHY ID\n"); + return DEFAULT_ICP_XXXX_TIPG_IPGT; + } +- ++ + return phy_num; + + #else /* ifdef EXTERNAL_MDIO */ +@@ -803,15 +714,15 @@ iegbe_oem_get_tipg(struct iegbe_hw *hw) + * iegbe_oem_phy_is_copper + * @hw: iegbe_hw struct containing device specific information + * +- * Test for media type within the iegbe driver is common, so this is a simple +- * test for copper PHYs. The ICP_XXXX family of controllers initially only +- * supported copper interconnects (no TBI (ten bit interface) for Fiber +- * existed). If future revs support either Fiber or an internal SERDES, it +- * may become necessary to evaluate where this function is used to go beyond ++ * Test for media type within the iegbe driver is common, so this is a simple ++ * test for copper PHYs. The ICP_XXXX family of controllers initially only ++ * supported copper interconnects (no TBI (ten bit interface) for Fiber ++ * existed). If future revs support either Fiber or an internal SERDES, it ++ * may become necessary to evaluate where this function is used to go beyond + * determining whether or not media type is just copper. + * + **/ +-int ++int + iegbe_oem_phy_is_copper(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -827,23 +738,21 @@ iegbe_oem_phy_is_copper(struct iegbe_hw + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: +- case BCM5395S_PHY_ID: + isCopper = TRUE; + break; + default: + DEBUGOUT("Invalid PHY ID\n"); + return -E1000_ERR_PHY_TYPE; + } +- ++ + return isCopper; + + #else /* ifdef EXTERNAL_MDIO */ + +- /* ++ /* + * caught between returning true or false. True allows it to + * be entered into && statements w/o ill effect, but false +- * would make more sense ++ * would make more sense + */ + DEBUGOUT("Invalid value for transceiver type, return FALSE\n"); + return FALSE; +@@ -856,19 +765,19 @@ iegbe_oem_phy_is_copper(struct iegbe_hw + * iegbe_oem_get_phy_dev_number + * @hw: iegbe_hw struct containing device specific information + * +- * For ICP_XXXX family of devices, there are 3 MACs, each of which may +- * have a different PHY (and indeed a different media interface). This +- * function is used to indicate which of the MAC/PHY pairs we are interested ++ * For ICP_XXXX family of devices, there are 3 MACs, each of which may ++ * have a different PHY (and indeed a different media interface). This ++ * function is used to indicate which of the MAC/PHY pairs we are interested + * in. +- * ++ * + **/ +-uint32_t ++uint32_t + iegbe_oem_get_phy_dev_number(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO + +- /* +- * for ICP_XXXX family of devices, the three network interfaces are ++ /* ++ * for ICP_XXXX family of devices, the three network interfaces are + * differentiated by their PCI device number, where the three share + * the same PCI bus + */ +@@ -886,15 +795,15 @@ iegbe_oem_get_phy_dev_number(struct iegb + + switch(device_number) + { +- case ICP_XXXX_MAC_0: ++ case ICP_XXXX_MAC_0: ++ hw->phy_addr = 0x00; ++ break; ++ case ICP_XXXX_MAC_1: + hw->phy_addr = 0x01; + break; +- case ICP_XXXX_MAC_1: ++ case ICP_XXXX_MAC_2: + hw->phy_addr = 0x02; + break; +- case ICP_XXXX_MAC_2: +- hw->phy_addr = 0x00; +- break; + default: hw->phy_addr = 0x00; + } + return hw->phy_addr; +@@ -915,7 +824,7 @@ iegbe_oem_get_phy_dev_number(struct iegb + * @cmd: the original IOCTL command that instigated the call chain. + * + * This function abstracts out the code necessary to service the +- * SIOCSMIIREG case within the iegbe_mii_ioctl() for oem PHYs. ++ * SIOCSMIIREG case within the iegbe_mii_ioctl() for oem PHYs. + * iegbe_mii_ioctl() was implemented for copper phy's only and this + * function will only be called if iegbe_oem_phy_is_copper() returns true for + * a given MAC. Note that iegbe_mii_ioctl() has a compile flag +@@ -924,14 +833,14 @@ iegbe_oem_get_phy_dev_number(struct iegb + * NOTE: a spinlock is in effect for the duration of this call. It is + * imperative that a negative value be returned on any error, so + * the spinlock can be released properly. +- * ++ * + **/ + int + iegbe_oem_mii_ioctl(struct iegbe_adapter *adapter, unsigned long flags, + struct ifreq *ifr, int cmd) + { + #ifdef EXTERNAL_MDIO +- ++ + struct mii_ioctl_data *data = if_mii(ifr); + uint16_t mii_reg = data->val_in; + uint16_t spddplx; +@@ -942,12 +851,6 @@ iegbe_oem_mii_ioctl(struct iegbe_adapter + if(!adapter || !ifr) { + return -1; + } +- +- // If MAC2 (BCM5395 switch) then leave now +- if ((PCI_SLOT(adapter->pdev->devfn)) == ICP_XXXX_MAC_2) { +- return -1; +- } +- + switch (data->reg_num) { + case PHY_CTRL: + if(mii_reg & MII_CR_POWER_DOWN) { +@@ -956,7 +859,7 @@ iegbe_oem_mii_ioctl(struct iegbe_adapter + if(mii_reg & MII_CR_AUTO_NEG_EN) { + adapter->hw.autoneg = 1; + adapter->hw.autoneg_advertised = ICP_XXXX_AUTONEG_ADV_DEFAULT; +- } ++ } + else { + if(mii_reg & 0x40) { + spddplx = SPEED_1000; +@@ -976,7 +879,7 @@ iegbe_oem_mii_ioctl(struct iegbe_adapter + if(netif_running(adapter->netdev)) { + iegbe_down(adapter); + iegbe_up(adapter); +- } ++ } + else { + iegbe_reset(adapter); + } +@@ -1043,10 +946,10 @@ void iegbe_oem_fiber_live_in_suspend(str + * Note: The call to iegbe_get_regs() assumed an array of 24 elements + * where the last 11 are passed to this function. If the array + * that is passed to the calling function has its size or element +- * defintions changed, this function becomes broken. ++ * defintions changed, this function becomes broken. + * + **/ +-void iegbe_oem_get_phy_regs(struct iegbe_adapter *adapter, uint32_t *data, ++void iegbe_oem_get_phy_regs(struct iegbe_adapter *adapter, uint32_t *data, + uint32_t data_len) + { + #define EXPECTED_ARRAY_LEN 11 +@@ -1062,13 +965,13 @@ void iegbe_oem_get_phy_regs(struct iegbe + * Use the corrected_length variable to make sure we don't exceed that + * length + */ +- corrected_len = data_len>EXPECTED_ARRAY_LEN ++ corrected_len = data_len>EXPECTED_ARRAY_LEN + ? EXPECTED_ARRAY_LEN : data_len; + memset(data, 0, corrected_len*sizeof(uint32_t)); + + #ifdef EXTERNAL_MDIO + +- /* ++ /* + * Fill data[] with... + * + * [0] = cable length +@@ -1084,16 +987,11 @@ void iegbe_oem_get_phy_regs(struct iegbe + * [10] = mdix mode + */ + switch (adapter->hw.phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_get_phy_regs() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + if(corrected_len > 0) { +- iegbe_oem_read_phy_reg_ex(&adapter->hw, +- M88E1000_PHY_SPEC_STATUS, ++ iegbe_oem_read_phy_reg_ex(&adapter->hw, ++ M88E1000_PHY_SPEC_STATUS, + (uint16_t *) &data[0]); + } + if(corrected_len > 0x1){ +@@ -1106,7 +1004,7 @@ void iegbe_oem_get_phy_regs(struct iegbe + data[0x3] = 0x0; /* Dummy (to align w/ IGP phy reg dump) */ + } + if(corrected_len > 0x4) { +- iegbe_oem_read_phy_reg_ex(&adapter->hw, M88E1000_PHY_SPEC_CTRL, ++ iegbe_oem_read_phy_reg_ex(&adapter->hw, M88E1000_PHY_SPEC_CTRL, + (uint16_t *) &data[0x4]); + } + if(corrected_len > 0x5) { +@@ -1144,7 +1042,7 @@ void iegbe_oem_get_phy_regs(struct iegbe + * This is called from iegbe_set_phy_loopback in response from call from + * ethtool to place the PHY into loopback mode. + **/ +-int ++int + iegbe_oem_phy_loopback(struct iegbe_adapter *adapter) + { + #ifdef EXTERNAL_MDIO +@@ -1165,23 +1063,18 @@ iegbe_oem_phy_loopback(struct iegbe_adap + * was that nonintegrated called iegbe_phy_reset_clk_and_crs(), + * hopefully this won't matter as CRS required for half-duplex + * operation and this is set to full duplex. +- * ++ * + * Make note that the M88 phy is what'll be used on Truxton + * Loopback configuration is the same for each of the supported PHYs. + */ + switch (adapter->hw.phy_id) { +- case BCM5395S_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_phy_loopback() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: + + adapter->hw.autoneg = FALSE; + + /* turn off Auto-MDI/MDIX */ +- /*ret_val = iegbe_oem_write_phy_reg_ex(&adapter->hw, ++ /*ret_val = iegbe_oem_write_phy_reg_ex(&adapter->hw, + M88E1000_PHY_SPEC_CTRL, 0x0808); + if(ret_val) + { +@@ -1206,10 +1099,10 @@ iegbe_oem_phy_loopback(struct iegbe_adap + DEBUGOUT("Unable to write to register PHY_CTRL\n"); + return ret_val; + } +- +- ++ ++ + /* force 1000, set loopback */ +- /*ret_val = ++ /*ret_val = + iegbe_oem_write_phy_reg_ex(&adapter->hw, PHY_CTRL, 0x4140); */ + ret_val = iegbe_oem_write_phy_reg_ex(&adapter->hw, PHY_CTRL, 0x6100); + if(ret_val) { +@@ -1228,21 +1121,21 @@ iegbe_oem_phy_loopback(struct iegbe_adap + E1000_WRITE_REG(&adapter->hw, CTRL, ctrl_reg); + + /* +- * Write out to PHY registers 29 and 30 to disable the Receiver. ++ * Write out to PHY registers 29 and 30 to disable the Receiver. + * This directly lifted from iegbe_phy_disable_receiver(). +- * ++ * + * The code is currently commented out as for the M88 used in + * Truxton, registers 29 and 30 are unutilized. Leave in, just +- * in case we are on the receiving end of an 'undocumented' ++ * in case we are on the receiving end of an 'undocumented' + * feature + */ +- /* ++ /* + * iegbe_oem_write_phy_reg_ex(&adapter->hw, 29, 0x001F); + * iegbe_oem_write_phy_reg_ex(&adapter->hw, 30, 0x8FFC); + * iegbe_oem_write_phy_reg_ex(&adapter->hw, 29, 0x001A); + * iegbe_oem_write_phy_reg_ex(&adapter->hw, 30, 0x8FF0); + */ +- ++ + break; + default: + DEBUGOUT("Invalid PHY ID\n"); +@@ -1268,15 +1161,15 @@ iegbe_oem_phy_loopback(struct iegbe_adap + * ethtool to place the PHY out of loopback mode. This handles the OEM + * specific part of loopback cleanup. + **/ +-void ++void + iegbe_oem_loopback_cleanup(struct iegbe_adapter *adapter) + { + #ifdef EXTERNAL_MDIO + +- /* +- * This borrows liberally from iegbe_loopback_cleanup(). ++ /* ++ * This borrows liberally from iegbe_loopback_cleanup(). + * making note that the M88 phy is what'll be used on Truxton +- * ++ * + * Loopback cleanup is the same for all supported PHYs. + */ + int32_t ret_val; +@@ -1289,38 +1182,32 @@ iegbe_oem_loopback_cleanup(struct iegbe_ + } + + switch (adapter->hw.phy_id) { +- case BCM5395S_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_loopback_cleanup() has been called!\n"); +- return; +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: + default: + adapter->hw.autoneg = TRUE; +- +- ret_val = iegbe_oem_read_phy_reg_ex(&adapter->hw, PHY_CTRL, ++ ++ ret_val = iegbe_oem_read_phy_reg_ex(&adapter->hw, PHY_CTRL, + &phy_reg); + if(ret_val) { + DEBUGOUT("Unable to read to register PHY_CTRL\n"); + return; + } +- ++ + if(phy_reg & MII_CR_LOOPBACK) { + phy_reg &= ~MII_CR_LOOPBACK; +- +- ret_val = iegbe_oem_write_phy_reg_ex(&adapter->hw, PHY_CTRL, ++ ++ ret_val = iegbe_oem_write_phy_reg_ex(&adapter->hw, PHY_CTRL, + phy_reg); + if(ret_val) { + DEBUGOUT("Unable to write to register PHY_CTRL\n"); + return; + } +- ++ + iegbe_phy_reset(&adapter->hw); + } + } +- ++ + #endif /* ifdef EXTERNAL_MDIO */ + return; + +@@ -1336,7 +1223,7 @@ iegbe_oem_loopback_cleanup(struct iegbe_ + * Called by iegbe_check_downshift(), checks the PHY to see if it running + * at as speed slower than its maximum. + **/ +-uint32_t ++uint32_t + iegbe_oem_phy_speed_downgraded(struct iegbe_hw *hw, uint16_t *isDowngraded) + { + #ifdef EXTERNAL_MDIO +@@ -1356,24 +1243,19 @@ iegbe_oem_phy_speed_downgraded(struct ie + */ + + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- *isDowngraded = 0; +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n"); + return ret_val; + } +- +- *isDowngraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) ++ ++ *isDowngraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) + >> M88E1000_PSSR_DOWNSHIFT_SHIFT; +- +- break; ++ ++ break; + default: + DEBUGOUT("Invalid PHY ID\n"); + return 1; +@@ -1388,7 +1270,7 @@ iegbe_oem_phy_speed_downgraded(struct ie + } + + *isDowngraded = 0; +- return 0; ++ return 0; + + #endif /* ifdef EXTERNAL_MDIO */ + } +@@ -1403,7 +1285,7 @@ iegbe_oem_phy_speed_downgraded(struct ie + * Called by iegbe_check_downshift(), checks the PHY to see if it running + * at as speed slower than its maximum. + **/ +-int32_t ++int32_t + iegbe_oem_check_polarity(struct iegbe_hw *hw, uint16_t *polarity) + { + #ifdef EXTERNAL_MDIO +@@ -1417,33 +1299,27 @@ iegbe_oem_check_polarity(struct iegbe_hw + return -1; + } + +- /* ++ /* + * borrow liberally from iegbe_check_polarity. + * Make note that the M88 phy is what'll be used on Truxton + */ + + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- *polarity = 0; +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + /* return the Polarity bit in the Status register. */ +- ret_val = iegbe_oem_read_phy_reg_ex(hw, +- M88E1000_PHY_SPEC_STATUS, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, ++ M88E1000_PHY_SPEC_STATUS, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n"); + return ret_val; + } + +- *polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) ++ *polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) + >> M88E1000_PSSR_REV_POLARITY_SHIFT; +- +- break; +- ++ ++ break; + default: + DEBUGOUT("Invalid PHY ID\n"); + return -E1000_ERR_PHY_TYPE; +@@ -1472,7 +1348,7 @@ iegbe_oem_check_polarity(struct iegbe_hw + * the MAC with the PHY. It turns out on ICP_XXXX, this is not + * done automagically. + **/ +-int32_t ++int32_t + iegbe_oem_phy_is_full_duplex(struct iegbe_hw *hw, int *isFD) + { + #ifdef EXTERNAL_MDIO +@@ -1485,40 +1361,22 @@ iegbe_oem_phy_is_full_duplex(struct iegb + if(!hw || !isFD) { + return -1; + } +- /* ++ /* + * Make note that the M88 phy is what'll be used on Truxton + * see iegbe_config_mac_to_phy + */ +- ++ + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- /* Always full duplex */ +- *isFD = 1; +- break; +- +- case BCM5481_PHY_ID: +- ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data); +- if(ret_val) return ret_val; +- +- switch (BCM5481_ASTAT_HCD(phy_data)) { +- case BCM5481_ASTAT_1KBTFD: +- case BCM5481_ASTAT_100BTXFD: +- *isFD = 1; +- break; +- default: +- *isFD = 0; +- } +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); +- if(ret_val) { +- DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n"); +- return ret_val; +- } ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, ++ &phy_data); ++ if(ret_val) { ++ DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n"); ++ return ret_val; ++ } + *isFD = (phy_data & M88E1000_PSSR_DPLX) != 0; +- ++ + break; + default: + DEBUGOUT("Invalid PHY ID\n"); +@@ -1546,7 +1404,7 @@ iegbe_oem_phy_is_full_duplex(struct iegb + * the MAC with the PHY. It turns out on ICP_XXXX, this is not + * done automagically. + **/ +-int32_t ++int32_t + iegbe_oem_phy_is_speed_1000(struct iegbe_hw *hw, int *is1000) + { + #ifdef EXTERNAL_MDIO +@@ -1565,28 +1423,10 @@ iegbe_oem_phy_is_speed_1000(struct iegbe + */ + + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- /* Always 1000mb */ +- *is1000 = 1; +- break; +- +- case BCM5481_PHY_ID: +- ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data); +- if(ret_val) return ret_val; +- +- switch (BCM5481_ASTAT_HCD(phy_data)) { +- case BCM5481_ASTAT_1KBTFD: +- case BCM5481_ASTAT_1KBTHD: +- *is1000 = 1; +- break; +- default: +- *is1000 = 0; +- } +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, ++ &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n"); + return ret_val; +@@ -1638,28 +1478,9 @@ iegbe_oem_phy_is_speed_100(struct iegbe_ + * see iegbe_config_mac_to_phy + */ + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- /* Always 1000Mb, never 100mb */ +- *is100 = 0; +- break; +- +- case BCM5481_PHY_ID: +- ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data); +- if(ret_val) return ret_val; +- +- switch (BCM5481_ASTAT_HCD(phy_data)) { +- case BCM5481_ASTAT_100BTXFD: +- case BCM5481_ASTAT_100BTXHD: +- *is100 = 1; +- break; +- default: +- *is100 = 0; +- } +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- ret_val = iegbe_oem_read_phy_reg_ex(hw, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, + M88E1000_PHY_SPEC_STATUS, + &phy_data); + if(ret_val) { +@@ -1714,29 +1535,24 @@ iegbe_oem_phy_get_info(struct iegbe_hw * + * see iegbe_phy_m88_get_info + */ + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_phy_get_info() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- /* The downshift status is checked only once, after link is +- * established and it stored in the hw->speed_downgraded parameter.*/ ++ /* The downshift status is checked only once, after link is ++ * established and it stored in the hw->speed_downgraded parameter.*/ + phy_info->downshift = (iegbe_downshift)hw->speed_downgraded; +- +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, ++ ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_CTRL\n"); + return ret_val; + } + +- phy_info->extended_10bt_distance = +- (phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) ++ phy_info->extended_10bt_distance = ++ (phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) + >> M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT; + phy_info->polarity_correction = +- (phy_data & M88E1000_PSCR_POLARITY_REVERSAL) ++ (phy_data & M88E1000_PSCR_POLARITY_REVERSAL) + >> M88E1000_PSCR_POLARITY_REVERSAL_SHIFT; + + /* Check polarity status */ +@@ -1747,11 +1563,11 @@ iegbe_oem_phy_get_info(struct iegbe_hw * + + phy_info->cable_polarity = polarity; + +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, + &phy_data); + if(ret_val) { +- DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n"); +- return ret_val; ++ DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n"); ++ return ret_val; + } + + phy_info->mdix_mode = (phy_data & M88E1000_PSSR_MDIX) +@@ -1761,24 +1577,24 @@ iegbe_oem_phy_get_info(struct iegbe_hw * + /* Cable Length Estimation and Local/Remote Receiver Information + * are only valid at 1000 Mbps. + */ +- phy_info->cable_length = ++ phy_info->cable_length = + (phy_data & M88E1000_PSSR_CABLE_LENGTH) + >> M88E1000_PSSR_CABLE_LENGTH_SHIFT; + +- ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_1000T_STATUS, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_1000T_STATUS, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read register PHY_1000T_STATUS\n"); + return ret_val; + } + +- phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) ++ phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) + >> SR_1000T_LOCAL_RX_STATUS_SHIFT; +- +- phy_info->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) ++ ++ phy_info->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) + >> SR_1000T_REMOTE_RX_STATUS_SHIFT; + } +- ++ + break; + default: + DEBUGOUT("Invalid PHY ID\n"); +@@ -1801,7 +1617,7 @@ iegbe_oem_phy_get_info(struct iegbe_hw * + * This function will perform a software initiated reset of + * the PHY + **/ +-int32_t ++int32_t + iegbe_oem_phy_hw_reset(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -1815,18 +1631,13 @@ iegbe_oem_phy_hw_reset(struct iegbe_hw * + return -1; + } + /* +- * This code pretty much copies the default case from ++ * This code pretty much copies the default case from + * iegbe_phy_reset() as that is what is appropriate for +- * the M88 used in truxton. ++ * the M88 used in truxton. + */ + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_phy_hw_reset() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_CTRL, &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read register PHY_CTRL\n"); +@@ -1864,7 +1675,7 @@ iegbe_oem_phy_hw_reset(struct iegbe_hw * + * to perform and post reset initialiation. Not all PHYs require + * this, which is why it was split off as a seperate function. + **/ +-void ++void + iegbe_oem_phy_init_script(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -1877,19 +1688,17 @@ iegbe_oem_phy_init_script(struct iegbe_h + + /* call the GCU func that can do any phy specific init + * functions after a reset +- * ++ * + * Make note that the M88 phy is what'll be used on Truxton + * +- * The closest thing is in iegbe_phy_init_script, however this is ++ * The closest thing is in iegbe_phy_init_script, however this is + * for the IGP style of phy. This is probably a no-op for truxton + * but may be needed by OEM's later on +- * ++ * + */ + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: +- case BCM5395S_PHY_ID: + DEBUGOUT("Nothing to do for OEM PHY Init"); + break; + default: +@@ -1926,13 +1735,8 @@ iegbe_oem_read_phy_reg_ex(struct iegbe_h + return -1; + } + +- if (hw->phy_id == BCM5395S_PHY_ID) { +- DEBUGOUT("WARNING: iegbe_oem_read_phy_reg_ex() has been unexpectedly called!\n"); +- return -1; +- } +- + /* call the GCU func that will read the phy +- * ++ * + * Make note that the M88 phy is what'll be used on Truxton. + * + * The closest thing is in iegbe_read_phy_reg_ex. +@@ -1940,7 +1744,7 @@ iegbe_oem_read_phy_reg_ex(struct iegbe_h + * NOTE: this is 1 (of 2) functions that is truly dependant on the + * gcu module + */ +- ++ + ret_val = gcu_read_eth_phy(iegbe_oem_get_phy_dev_number(hw), + reg_addr, phy_data); + if(ret_val) { +@@ -1962,10 +1766,10 @@ iegbe_oem_read_phy_reg_ex(struct iegbe_h + * + * Returns E1000_SUCCESS, negative E1000 error code on failure + * +- * This is called from iegbe_config_mac_to_phy. Various supported ++ * This is called from iegbe_config_mac_to_phy. Various supported + * Phys may require the RGMII/RMII Translation gasket be set to RMII. + **/ +-int32_t ++int32_t + iegbe_oem_set_trans_gasket(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -1978,17 +1782,12 @@ iegbe_oem_set_trans_gasket(struct iegbe_ + } + + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_set_trans_gasket() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + /* Gasket set correctly for Marvell Phys, so nothing to do */ + break; + /* Add your PHY_ID here if your device requires an RMII interface +- case YOUR_PHY_ID: ++ case YOUR_PHY_ID: + ctrl_aux_reg = E1000_READ_REG(hw, CTRL_AUX); + ctrl_aux_reg |= E1000_CTRL_AUX_ICP_xxxx_MII_TGS; // Set the RGMII_RMII bit + */ +@@ -2032,7 +1831,7 @@ iegbe_oem_write_phy_reg_ex(struct iegbe_ + return -1; + } + /* call the GCU func that will write to the phy +- * ++ * + * Make note that the M88 phy is what'll be used on Truxton. + * + * The closest thing is in iegbe_write_phy_reg_ex +@@ -2062,11 +1861,11 @@ iegbe_oem_write_phy_reg_ex(struct iegbe_ + * @hw struct iegbe_hw hardware specific data + * + * iegbe_reset_hw is called to reset the MAC. If, for +- * some reason the PHY needs to be reset as well, this ++ * some reason the PHY needs to be reset as well, this + * should return TRUE and then iegbe_oem_phy_hw_reset() + * will be called. + **/ +-int ++int + iegbe_oem_phy_needs_reset_with_mac(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -2079,16 +1878,14 @@ iegbe_oem_phy_needs_reset_with_mac(struc + return FALSE; + } + +- /* ++ /* + * From the original iegbe driver, the M88 +- * PHYs did not seem to need this reset, ++ * PHYs did not seem to need this reset, + * so returning FALSE. + */ + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: +- case BCM5395S_PHY_ID: + ret_val = FALSE; + break; + default: +@@ -2116,7 +1913,7 @@ iegbe_oem_phy_needs_reset_with_mac(struc + * tweaking of the PHY, for PHYs that support a DSP. + * + **/ +-int32_t ++int32_t + iegbe_oem_config_dsp_after_link_change(struct iegbe_hw *hw, + int link_up) + { +@@ -2138,8 +1935,6 @@ iegbe_oem_config_dsp_after_link_change(s + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: +- case BCM5395S_PHY_ID: + DEBUGOUT("No DSP to configure on OEM PHY"); + break; + default: +@@ -2165,7 +1960,7 @@ iegbe_oem_config_dsp_after_link_change(s + * + * + **/ +-int32_t ++int32_t + iegbe_oem_get_cable_length(struct iegbe_hw *hw, + uint16_t *min_length, + uint16_t *max_length) +@@ -2177,21 +1972,15 @@ iegbe_oem_get_cable_length(struct iegbe_ + uint16_t phy_data; + + DEBUGFUNC1("%s",__func__); +- ++ + if(!hw || !min_length || !max_length) { + return -1; + } + + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- *min_length = 0; +- *max_length = iegbe_igp_cable_length_150; +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- ret_val = iegbe_oem_read_phy_reg_ex(hw, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, + M88E1000_PHY_SPEC_STATUS, + &phy_data); + if(ret_val) { +@@ -2246,13 +2035,13 @@ iegbe_oem_get_cable_length(struct iegbe_ + /** + * iegbe_oem_phy_is_link_up + * @hw iegbe_hw struct containing device specific information +- * @isUp a boolean returning true if link is up ++ * @isUp a boolean returning true if link is up + * + * This is called as part of iegbe_config_mac_to_phy() to align + * the MAC with the PHY. It turns out on ICP_XXXX, this is not + * done automagically. + **/ +-int32_t ++int32_t + iegbe_oem_phy_is_link_up(struct iegbe_hw *hw, int *isUp) + { + #ifdef EXTERNAL_MDIO +@@ -2266,35 +2055,19 @@ iegbe_oem_phy_is_link_up(struct iegbe_hw + if(!hw || !isUp) { + return -1; + } +- /* ++ /* + * Make note that the M88 phy is what'll be used on Truxton + * see iegbe_config_mac_to_phy + */ + + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- /* Link always up */ +- *isUp = TRUE; +- return E1000_SUCCESS; +- break; +- +- case BCM5481_PHY_ID: +- iegbe_oem_read_phy_reg_ex(hw, BCM5481_ESTAT, &phy_data); +- ret_val = iegbe_oem_read_phy_reg_ex(hw, BCM5481_ESTAT, &phy_data); +- if(ret_val) +- { +- DEBUGOUT("Unable to read PHY register BCM5481_ESTAT\n"); +- return ret_val; +- } +- statusMask = BCM5481_ESTAT_LINK; +- break; +- +- case M88E1000_I_PHY_ID: ++ case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); ++ iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, ++ &phy_data); + statusMask = M88E1000_PSSR_LINK; +- break; ++ break; + default: + DEBUGOUT("Invalid PHY ID\n"); + return -E1000_ERR_PHY_TYPE; +@@ -2319,213 +2092,3 @@ iegbe_oem_phy_is_link_up(struct iegbe_hw + #endif /* ifdef EXTERNAL_MDIO */ + } + +- +- +-//----- +-// Read BCM5481 expansion register +-// +-int32_t +-bcm5481_read_ex (struct iegbe_hw *hw, uint16_t reg, uint16_t *data) +-{ +- int ret; +- uint16_t selector; +- uint16_t reg_data; +- +- // Get the current value of bits 15:12 +- ret = iegbe_oem_read_phy_reg_ex (hw, 0x15, &selector); +- if (ret) +- return ret; +- +- // Select the expansion register +- selector &= 0xf000; +- selector |= (0xf << 8) | (reg); +- iegbe_oem_write_phy_reg_ex (hw, 0x17, selector); +- +- // Read the expansion register +- ret = iegbe_oem_read_phy_reg_ex (hw, 0x15, ®_data); +- +- // De-select the expansion registers. +- selector &= 0xf000; +- iegbe_oem_write_phy_reg_ex (hw, 0x17, selector); +- +- if (ret) +- return ret; +- +- *data = reg_data; +- return ret; +-} +- +-//----- +-// Read reg 0x18 sub-register +-// +-static int32_t +-bcm5481_read_18sv (struct iegbe_hw *hw, int sv, uint16_t *data) +-{ +- int ret; +- uint16_t tmp_data; +- +- // Select reg 0x18, sv +- tmp_data = ((sv & BCM5481_R18H_SV_MASK) << 12) | BCM5481_R18H_SV_MCTRL; +- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, tmp_data); +- if(ret) +- return ret; +- +- // Read reg 0x18, sv +- ret = iegbe_oem_read_phy_reg_ex (hw, BCM5481_R18H, &tmp_data); +- if(ret) +- return ret; +- +- *data = tmp_data; +- return ret; +-} +- +-//----- +-// Read reg 0x1C sub-register +-// +-int32_t +-bcm5481_read_1csv (struct iegbe_hw *hw, int sv, uint16_t *data) +-{ +- int ret; +- uint16_t tmp_data; +- +- // Select reg 0x1c, sv +- tmp_data = ((sv & BCM5481_R1CH_SV_MASK) << BCM5481_R1CH_SV_SHIFT); +- +- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, tmp_data); +- if(ret) +- return ret; +- +- // Read reg 0x1c, sv +- ret = iegbe_oem_read_phy_reg_ex (hw, BCM5481_R1CH, &tmp_data); +- if(ret) +- return ret; +- +- *data = tmp_data; +- return ret; +-} +- +-//----- +-// Read-modify-write a 0x1C register. +-// +-// hw - hardware access info. +-// reg - 0x1C register to modify. +-// data - bits which should be set. +-// mask - the '1' bits in this argument will be cleared in the data +-// read from 'reg' then 'data' will be or'd in and the result +-// will be written to 'reg'. +- +-int32_t +-bcm5481_rmw_1csv (struct iegbe_hw *hw, uint16_t reg, uint16_t data, uint16_t mask) +-{ +- int32_t ret; +- uint16_t reg_data; +- +- ret = 0; +- +- ret = bcm5481_read_1csv (hw, reg, ®_data); +- if (ret) +- { +- DEBUGOUT("Unable to read BCM5481 1CH register\n"); +- printk (KERN_ERR "Unable to read BCM5481 1CH register [0x%x]\n", reg); +- return ret; +- } +- +- reg_data &= ~mask; +- reg_data |= (BCM5481_R1CH_WE | data); +- +- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, reg_data); +- if(ret) +- { +- DEBUGOUT("Unable to write BCM5481 1CH register\n"); +- printk (KERN_ERR "Unable to write BCM5481 1CH register\n"); +- return ret; +- } +- +- return ret; +-} +- +-int32_t +-oi_phy_setup (struct iegbe_hw *hw) +-{ +- int ret; +- uint16_t pmii_data; +- uint16_t mctrl_data; +- uint16_t cacr_data; +- uint16_t sc1_data; +- uint16_t lctl_data; +- +- ret = 0; +- +- // Set low power mode via reg 0x18, sv010, bit 6 +- // Do a read-modify-write on reg 0x18, sv010 register to preserve existing bits. +- ret = bcm5481_read_18sv (hw, BCM5481_R18H_SV_PMII, &pmii_data); +- if (ret) +- { +- DEBUGOUT("Unable to read BCM5481_R18H_SV_PMII register\n"); +- printk (KERN_ERR "Unable to read BCM5481_R18H_SV_PMII register\n"); +- return ret; +- } +- +- // Set the LPM bit in the data just read and write back to sv010 +- // The shadow register select bits [2:0] are set by reading the sv010 +- // register. +- pmii_data |= BCM5481_R18H_SV010_LPM; +- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, pmii_data); +- if(ret) +- { +- DEBUGOUT("Unable to write BCM5481_R18H register\n"); +- printk (KERN_ERR "Unable to write BCM5481_R18H register\n"); +- return ret; +- } +- +- +- // Set the RGMII RXD to RXC skew bit in reg 0x18, sv111 +- +- if (bcm5481_read_18sv (hw, BCM5481_R18H_SV_MCTRL, &mctrl_data)) +- { +- DEBUGOUT("Unable to read BCM5481_R18H_SV_MCTRL register\n"); +- printk (KERN_ERR "Unable to read BCM5481_R18H_SV_MCTRL register\n"); +- return ret; +- } +- mctrl_data |= (BCM5481_R18H_WE | BCM5481_R18H_SV111_SKEW); +- +- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, mctrl_data); +- if(ret) +- { +- DEBUGOUT("Unable to write BCM5481_R18H register\n"); +- printk (KERN_ERR "Unable to write BCM5481_R18H register\n"); +- return ret; +- } +- +- +- // Enable RGMII transmit clock delay in reg 0x1c, sv00011 +- ret = bcm5481_read_1csv (hw, BCM5481_R1CH_CACR, &cacr_data); +- if (ret) +- { +- DEBUGOUT("Unable to read BCM5481_R1CH_CACR register\n"); +- printk (KERN_ERR "Unable to read BCM5481_R1CH_CACR register\n"); +- return ret; +- } +- +- cacr_data |= (BCM5481_R1CH_WE | BCM5481_R1CH_CACR_TCD); +- +- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, cacr_data); +- if(ret) +- { +- DEBUGOUT("Unable to write BCM5481_R1CH register\n"); +- printk (KERN_ERR "Unable to write BCM5481_R1CH register\n"); +- return ret; +- } +- +- // Enable dual link speed indication (0x1c, sv 00010, bit 2) +- ret = bcm5481_rmw_1csv (hw, BCM5481_R1CH_SC1, BCM5481_R1CH_SC1_LINK, BCM5481_R1CH_SC1_LINK); +- if (ret) +- return ret; +- +- // Enable link and activity on ACTIVITY LED (0x1c, sv 01001, bit 4=1, bit 3=0) +- ret = bcm5481_rmw_1csv (hw, BCM5481_R1CH_LCTRL, BCM5481_R1CH_LCTRL_ALEN, BCM5481_R1CH_LCTRL_ALEN | BCM5481_R1CH_LCTRL_AEN); +- if (ret) +- return ret; +- +- return ret; +-} +--- a/Embedded/src/GbE/iegbe_oem_phy.h ++++ b/Embedded/src/GbE/iegbe_oem_phy.h +@@ -2,31 +2,31 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + +- This program is free software; you can redistribute it and/or modify ++ This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + +- 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 ++ 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 ++ 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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- The full GNU General Public License is included in this distribution ++ The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: +- +- Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226 ++ ++ Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226 + + *******************************************************************************/ + #ifndef _IEGBE_OEM_PHY_H_ +@@ -45,10 +45,10 @@ int32_t iegbe_oem_set_trans_gasket(struc + uint32_t iegbe_oem_get_tipg(struct iegbe_hw *hw); + int iegbe_oem_phy_is_copper(struct iegbe_hw *hw); + uint32_t iegbe_oem_get_phy_dev_number(struct iegbe_hw *hw); +-int iegbe_oem_mii_ioctl(struct iegbe_adapter *adapter, unsigned long flags, ++int iegbe_oem_mii_ioctl(struct iegbe_adapter *adapter, unsigned long flags, + struct ifreq *ifr, int cmd); + void iegbe_oem_fiber_live_in_suspend(struct iegbe_hw *hw); +-void iegbe_oem_get_phy_regs(struct iegbe_adapter *adapter, uint32_t *data, ++void iegbe_oem_get_phy_regs(struct iegbe_adapter *adapter, uint32_t *data, + uint32_t data_length); + int iegbe_oem_phy_loopback(struct iegbe_adapter *adapter); + void iegbe_oem_loopback_cleanup(struct iegbe_adapter *adapter); +@@ -94,81 +94,14 @@ int32_t iegbe_oem_phy_is_link_up(struct + #define ICP_XXXX_MAC_2 2 + + #define DEFAULT_ICP_XXXX_TIPG_IPGT 8 /* Inter Packet Gap Transmit Time */ +-#define ICP_XXXX_TIPG_IPGT_MASK 0x000003FFUL +-#define BCM5481_PHY_ID 0x0143BCA2 +-#define BCM5395S_PHY_ID 0x0143BCF0 ++#define ICP_XXXX_TIPG_IPGT_MASK 0x000003FFUL + + /* Miscellaneous defines */ + #ifdef IEGBE_10_100_ONLY +- #define ICP_XXXX_AUTONEG_ADV_DEFAULT 0x0F ++ #define ICP_XXXX_AUTONEG_ADV_DEFAULT 0x0F + #else + #define ICP_XXXX_AUTONEG_ADV_DEFAULT 0x2F + #endif + +-//----- +-// BCM5481 specifics +- +-#define BCM5481_ECTRL (0x10) +-#define BCM5481_ESTAT (0x11) +-#define BCM5481_RXERR (0x12) +-#define BCM5481_EXPRW (0x15) +-#define BCM5481_EXPACC (0x17) +-#define BCM5481_ASTAT (0x19) +-#define BCM5481_R18H (0x18) +-#define BCM5481_R1CH (0x1c) +- +-//----- +-// indirect register access via register 18h +- +-#define BCM5481_R18H_SV_MASK (7) // Mask for SV bits. +-#define BCM5481_R18H_SV_ACTRL (0) // SV000 Aux. control +-#define BCM5481_R18H_SV_10BT (1) // SV001 10Base-T +-#define BCM5481_R18H_SV_PMII (2) // SV010 Power/MII control +-#define BCM5481_R18H_SV_MTEST (4) // SV100 Misc. test +-#define BCM5481_R18H_SV_MCTRL (7) // SV111 Misc. control +- +-#define BCM5481_R18H_SV001_POL (1 << 13) // Polarity +-#define BCM5481_R18H_SV010_LPM (1 << 6) +-#define BCM5481_R18H_SV111_SKEW (1 << 8) +-#define BCM5481_R18H_WE (1 << 15) // Write enable +- +-// 0x1c registers +-#define BCM5481_R1CH_SV_SHIFT (10) +-#define BCM5481_R1CH_SV_MASK (0x1f) +-#define BCM5481_R1CH_SC1 (0x02) // sv00010 Spare control 1 +-#define BCM5481_R1CH_CACR (0x03) // sv00011 Clock alignment control +-#define BCM5481_R1CH_LCTRL (0x09) // sv01001 LED control +-#define BCM5481_R1CH_LEDS1 (0x0d) // sv01101 LED selector 1 +- +-// 0x1c common +-#define BCM5481_R1CH_WE (1 << 15) // Write enable +- +-// 0x1c, sv 00010 +-#define BCM5481_R1CH_SC1_LINK (1 << 2) // sv00010 Linkspeed +- +-// 0x1c, sv 00011 +-#define BCM5481_R1CH_CACR_TCD (1 << 9) // sv00011 RGMII tx clock delay +- +-// 0x1c, sv 01001 +-#define BCM5481_R1CH_LCTRL_ALEN (1 << 4) // Activity/Link enable on ACTIVITY LED +-#define BCM5481_R1CH_LCTRL_AEN (1 << 3) // Activity enable on ACTIVITY LED +- +- +-#define BCM5481_ECTRL_DISMDIX (1 <<14) +- +-#define BCM5481_MCTRL_AUTOMDIX (1 <<9) +- +-#define BCM5481_ESTAT_LINK (1 << 8) +- +-#define BCM5481_ASTAT_ANC (1 << 15) +-#define BCM5481_ASTAT_ANHCD (7 << 8) +-#define BCM5481_ASTAT_HCD(x) ((x >> 8) & 7) +-#define BCM5481_ASTAT_1KBTFD (0x7) +-#define BCM5481_ASTAT_1KBTHD (0x6) +-#define BCM5481_ASTAT_100BTXFD (0x5) +-#define BCM5481_ASTAT_100BTXHD (0x3) +- +-// end BCM5481 specifics +- + #endif /* ifndef _IEGBE_OEM_PHY_H_ */ +- ++ +--- a/Embedded/src/GbE/iegbe_osdep.h ++++ b/Embedded/src/GbE/iegbe_osdep.h +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +--- a/Embedded/src/GbE/iegbe_param.c ++++ b/Embedded/src/GbE/iegbe_param.c +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -239,11 +239,7 @@ E1000_PARAM(InterruptThrottleRate, "Inte + #define MAX_TXABSDELAY 0xFFFF + #define MIN_TXABSDELAY 0 + +-#ifdef IEGBE_GBE_WORKAROUND +-#define DEFAULT_ITR 0 +-#else + #define DEFAULT_ITR 8000 +-#endif + + + #define MAX_ITR 100000 +@@ -373,7 +369,7 @@ iegbe_check_options(struct iegbe_adapter + tx_ring->count = opt.def; + } + #endif +- for (i = 0; i < adapter->num_queues; i++) ++ for (i = 0; i < adapter->num_tx_queues; i++) + tx_ring[i].count = tx_ring->count; + } + { /* Receive Descriptor Count */ +@@ -403,7 +399,7 @@ iegbe_check_options(struct iegbe_adapter + rx_ring->count = opt.def; + } + #endif +- for (i = 0; i < adapter->num_queues; i++) ++ for (i = 0; i < adapter->num_rx_queues; i++) + rx_ring[i].count = rx_ring->count; + } + { /* Checksum Offload Enable/Disable */ +--- a/Embedded/src/GbE/kcompat.c ++++ b/Embedded/src/GbE/kcompat.c +@@ -1,8 +1,8 @@ +-/************************************************************ +- ++/************************************************************ ++ + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,183 +22,192 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 +- +- Contact Information: +- +- Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226 +- +-**************************************************************/ +-/************************************************************************** +- * @ingroup KCOMPAT_GENERAL +- * +- * @file kcompat.c +- * +- * @description +- * +- * +- **************************************************************************/ +-#include "kcompat.h" +- +-/*************************************************************/ +-/* 2.4.13 => 2.4.3 */ +-#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0xd) ) +- +-/**************************************/ +-/* PCI DMA MAPPING */ +- +-#if defined(CONFIG_HIGHMEM) +- +-#ifndef PCI_DRAM_OFFSET +-#define PCI_DRAM_OFFSET 0 +-#endif +- +-u64 _kc_pci_map_page(struct pci_dev *dev, +- struct page *page, +- unsigned long offset, +- size_t size, +- int direction) +-{ +- u64 ret_val; +- ret_val = (((u64)(page - mem_map) << PAGE_SHIFT) + offset + +- PCI_DRAM_OFFSET); +- return ret_val; +-} +- +-#else /* CONFIG_HIGHMEM */ +- +-u64 _kc_pci_map_page(struct pci_dev *dev, +- struct page *page, +- unsigned long offset, +- size_t size, +- int direction) +-{ +- return pci_map_single(dev, (void *)page_address(page) + offset, +- size, direction); +-} +- +-#endif /* CONFIG_HIGHMEM */ +- +-void _kc_pci_unmap_page(struct pci_dev *dev, +- u64 dma_addr, +- size_t size, +- int direction) +-{ +- return pci_unmap_single(dev, dma_addr, size, direction); +-} +- +-#endif /* 2.4.13 => 2.4.3 */ +- +- +-/*****************************************************************************/ +-/* 2.4.3 => 2.4.0 */ +-#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0x3) ) +- +-/**************************************/ +-/* PCI DRIVER API */ +- +-int _kc_pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask) +-{ +- if(!pci_dma_supported(dev, mask)) { +- return -EIO; +- } +- dev->dma_mask = mask; +- return 0; +-} +- +-int _kc_pci_request_regions(struct pci_dev *dev, char *res_name) +-{ +- int i; +- +- for (i = 0; i < 0x6; i++) { +- if (pci_resource_len(dev, i) == 0) { +- continue; +- } +- if (pci_resource_flags(dev, i) & IORESOURCE_IO) { +- if (!request_region(pci_resource_start(dev, i), +- pci_resource_len(dev, i), res_name)) { +- pci_release_regions(dev); +- return -EBUSY; +- } +- } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) { +- if (!request_mem_region(pci_resource_start(dev, i), +- pci_resource_len(dev, i), +- res_name)) { +- pci_release_regions(dev); +- return -EBUSY; +- } +- } +- } +- return 0; +-} +- +-void _kc_pci_release_regions(struct pci_dev *dev) +-{ +- int i; +- +- for (i = 0; i < 0x6; i++) { +- if (pci_resource_len(dev, i) == 0) { +- continue; +- } +- if (pci_resource_flags(dev, i) & IORESOURCE_IO){ +- release_region(pci_resource_start(dev, i), +- pci_resource_len(dev, i)); +- } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) { +- release_mem_region(pci_resource_start(dev, i), +- pci_resource_len(dev, i)); +- } +- } +-} +- +-/**************************************/ +-/* NETWORK DRIVER API */ +- +-struct net_device * _kc_alloc_etherdev(int sizeof_priv) +-{ +- struct net_device *dev; +- int alloc_size; +- +- alloc_size = sizeof(*dev) + sizeof_priv + IFNAMSIZ + 0x1f; +- +- dev = kmalloc(alloc_size, GFP_KERNEL); +- +- if (!dev) { return NULL; } +- +- memset(dev, 0, alloc_size); +- +- if (sizeof_priv) { +- dev->priv = (void *) (((unsigned long)(dev + 1) + 0x1f) & ~0x1f); +- } +- dev->name[0] = '\0'; +- +- ether_setup(dev); +- +- return dev; +-} +- +-int _kc_is_valid_ether_addr(u8 *addr) +-{ +- const char zaddr[0x6] = {0,}; +- +- return !(addr[0]&1) && memcmp( addr, zaddr, 0x6); +-} +- +-#endif /* 2.4.3 => 2.4.0 */ +- +- +-/*****************************************************************/ +-/* 2.4.6 => 2.4.3 */ +-#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0x6) ) +- +-int _kc_pci_set_power_state(struct pci_dev *dev, int state) +-{ return 0; } +-int _kc_pci_save_state(struct pci_dev *dev, u32 *buffer) +-{ return 0; } +-int _kc_pci_restore_state(struct pci_dev *pdev, u32 *buffer) +-{ return 0; } +-int _kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable) +-{ return 0; } +- +-#endif /* 2.4.6 => 2.4.3 */ +- +- ++ version: Embedded.Release.Patch.L.1.0.7-5 ++ ++ Contact Information: ++ ++ Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226 ++ ++**************************************************************/ ++/************************************************************************** ++ * @ingroup KCOMPAT_GENERAL ++ * ++ * @file kcompat.c ++ * ++ * @description ++ * ++ * ++ **************************************************************************/ ++#include "kcompat.h" ++ ++/*************************************************************/ ++/* 2.4.13 => 2.4.3 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0xd) ) ++ ++/**************************************/ ++/* PCI DMA MAPPING */ ++ ++#if defined(CONFIG_HIGHMEM) ++ ++#ifndef PCI_DRAM_OFFSET ++#define PCI_DRAM_OFFSET 0 ++#endif ++ ++u64 _kc_pci_map_page(struct pci_dev *dev, ++ struct page *page, ++ unsigned long offset, ++ size_t size, ++ int direction) ++{ ++ u64 ret_val; ++ ret_val = (((u64)(page - mem_map) << PAGE_SHIFT) + offset + ++ PCI_DRAM_OFFSET); ++ return ret_val; ++} ++ ++#else /* CONFIG_HIGHMEM */ ++ ++u64 _kc_pci_map_page(struct pci_dev *dev, ++ struct page *page, ++ unsigned long offset, ++ size_t size, ++ int direction) ++{ ++ return pci_map_single(dev, (void *)page_address(page) + offset, ++ size, direction); ++} ++ ++#endif /* CONFIG_HIGHMEM */ ++ ++void _kc_pci_unmap_page(struct pci_dev *dev, ++ u64 dma_addr, ++ size_t size, ++ int direction) ++{ ++ return pci_unmap_single(dev, dma_addr, size, direction); ++} ++ ++#endif /* 2.4.13 => 2.4.3 */ ++ ++ ++/*****************************************************************************/ ++/* 2.4.3 => 2.4.0 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0x3) ) ++ ++/**************************************/ ++/* PCI DRIVER API */ ++ ++int _kc_pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask) ++{ ++ if(!pci_dma_supported(dev, mask)) { ++ return -EIO; ++ } ++ dev->dma_mask = mask; ++ return 0; ++} ++ ++int _kc_pci_request_regions(struct pci_dev *dev, char *res_name) ++{ ++ int i; ++ ++ for (i = 0; i < 0x6; i++) { ++ if (pci_resource_len(dev, i) == 0) { ++ continue; ++ } ++ if (pci_resource_flags(dev, i) & IORESOURCE_IO) { ++ if (!request_region(pci_resource_start(dev, i), ++ pci_resource_len(dev, i), res_name)) { ++ pci_release_regions(dev); ++ return -EBUSY; ++ } ++ } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) { ++ if (!request_mem_region(pci_resource_start(dev, i), ++ pci_resource_len(dev, i), ++ res_name)) { ++ pci_release_regions(dev); ++ return -EBUSY; ++ } ++ } ++ } ++ return 0; ++} ++ ++void _kc_pci_release_regions(struct pci_dev *dev) ++{ ++ int i; ++ ++ for (i = 0; i < 0x6; i++) { ++ if (pci_resource_len(dev, i) == 0) { ++ continue; ++ } ++ if (pci_resource_flags(dev, i) & IORESOURCE_IO){ ++ release_region(pci_resource_start(dev, i), ++ pci_resource_len(dev, i)); ++ } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) { ++ release_mem_region(pci_resource_start(dev, i), ++ pci_resource_len(dev, i)); ++ } ++ } ++} ++ ++/**************************************/ ++/* NETWORK DRIVER API */ ++ ++struct net_device * _kc_alloc_etherdev(int sizeof_priv) ++{ ++ struct net_device *dev; ++ int alloc_size; ++ ++ alloc_size = sizeof(*dev) + sizeof_priv + IFNAMSIZ + 0x1f; ++ ++ dev = kmalloc(alloc_size, GFP_KERNEL); ++ ++ if (!dev) { return NULL; } ++ ++ memset(dev, 0, alloc_size); ++ ++ if (sizeof_priv) { ++ dev->priv = (void *) (((unsigned long)(dev + 1) + 0x1f) & ~0x1f); ++ } ++ dev->name[0] = '\0'; ++ ++ ether_setup(dev); ++ ++ return dev; ++} ++ ++int _kc_is_valid_ether_addr(u8 *addr) ++{ ++ const char zaddr[0x6] = {0,}; ++ ++ return !(addr[0]&1) && memcmp( addr, zaddr, 0x6); ++} ++ ++#endif /* 2.4.3 => 2.4.0 */ ++ ++ ++/*****************************************************************/ ++/* 2.4.6 => 2.4.3 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0x6) ) ++ ++int _kc_pci_set_power_state(struct pci_dev *dev, int state) ++{ return 0; } ++int _kc_pci_save_state(struct pci_dev *dev, u32 *buffer) ++{ return 0; } ++int _kc_pci_restore_state(struct pci_dev *pdev, u32 *buffer) ++{ return 0; } ++int _kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable) ++{ return 0; } ++ ++#endif /* 2.4.6 => 2.4.3 */ ++ ++ ++ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,24) ) ++ ++void dump_stack(void) ++{ ++} ++ ++#endif /* 2.4.24 */ ++ +--- a/Embedded/src/GbE/kcompat_ethtool.c ++++ b/Embedded/src/GbE/kcompat_ethtool.c +@@ -2,7 +2,7 @@ + /* + * GPL LICENSE SUMMARY + * +- * Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ * Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ + * Contact Information: + * Intel Corporation + * +- * version: Embedded.L.1.0.34 ++ * version: Embedded.Release.Patch.L.1.0.7-5 + */ + + /************************************************************************** +@@ -779,6 +779,7 @@ static int ethtool_get_stats(struct net_ + } + + /* The main entry point in this file. Called from net/core/dev.c */ ++ + #define ETHTOOL_OPS_COMPAT + int ethtool_ioctl(struct ifreq *ifr) + { +--- a/Embedded/src/GbE/kcompat.h ++++ b/Embedded/src/GbE/kcompat.h +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -69,15 +69,6 @@ GPL LICENSE SUMMARY + #define CONFIG_NET_POLL_CONTROLLER + #endif + +-#ifdef E1000_NAPI +-#undef CONFIG_E1000_NAPI +-#define CONFIG_E1000_NAPI +-#endif +- +-#ifdef E1000_NO_NAPI +-#undef CONFIG_E1000_NAPI +-#endif +- + #ifndef module_param + #define module_param(v,t,p) MODULE_PARM(v, "i"); + #endif +@@ -554,35 +545,14 @@ extern void _kc_pci_unmap_page(struct pc + #endif + + /*****************************************************************************/ +-/* 2.4.23 => 2.4.22 */ +-#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) ) +-#ifdef CONFIG_E1000_NAPI +-#ifndef netif_poll_disable +-#define netif_poll_disable(x) _kc_netif_poll_disable(x) +-static inline void _kc_netif_poll_disable(struct net_device *netdev) +-{ +- while (test_and_set_bit(__LINK_STATE_RX_SCHED, &netdev->state)) { +- /* No hurry */ +- current->state = TASK_INTERRUPTIBLE; +- schedule_timeout(1); +- } +-} +-#endif +-#ifndef netif_poll_enable +-#define netif_poll_enable(x) _kc_netif_poll_enable(x) +-static inline void _kc_netif_poll_enable(struct net_device *netdev) +-{ +- clear_bit(__LINK_STATE_RX_SCHED, &netdev->state); +-} +-#endif +-#endif +-#endif +- +-/*****************************************************************************/ + /* 2.5.28 => 2.4.23 */ + #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) ) + ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) ) ++static inline void _kc_synchronize_irq(void) { barrier(); } ++#else + static inline void _kc_synchronize_irq() { synchronize_irq(); } ++#endif /* 2.4.23 */ + #undef synchronize_irq + #define synchronize_irq(X) _kc_synchronize_irq() + +@@ -747,6 +717,37 @@ static inline struct mii_ioctl_data *_kc + #define skb_header_cloned(x) 0 + #endif /* SKB_DATAREF_SHIFT not defined */ + ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) ++ ++#define ioread32(addr) readl(addr) ++#define iowrite32(val,addr) writel(val,addr) ++ ++#endif /* 2.6.10 */ ++ ++#ifndef DEFINE_SPINLOCK ++#define DEFINE_SPINLOCK(s) spinlock_t s = SPIN_LOCK_UNLOCKED ++#endif /* DEFINE_SPINLOCK */ ++ ++#ifndef PCI_COMMAND_INTX_DISABLE ++#define PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */ ++#endif /* PCI_COMMAND_INTX_DISABLE */ ++ ++#ifndef ETH_GSTRING_LEN ++#define ETH_GSTRING_LEN 32 ++#endif /* ETH_GSTRING_LEN */ ++ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,24) ) ++ ++extern void dump_stack(void); ++ ++#undef register_reboot_notifier ++#define register_reboot_notifier(a) ++ ++#undef unregister_reboot_notifier ++#define unregister_reboot_notifier(a) ++ ++#endif /* 2.4.24 */ ++ + #endif /* _KCOMPAT_H_ */ + + +--- a/Embedded/src/GbE/Makefile ++++ b/Embedded/src/GbE/Makefile +@@ -1,6 +1,6 @@ + # GPL LICENSE SUMMARY + # +-# Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++# Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + # + # This program is free software; you can redistribute it and/or modify + # it under the terms of version 2 of the GNU General Public License as +@@ -20,7 +20,7 @@ + # Contact Information: + # Intel Corporation + # +-# version: Embedded.L.1.0.34 ++# version: Embedded.Release.Patch.L.1.0.7-5 + + ########################################################################### + # Driver files +@@ -35,6 +35,8 @@ MDIO_PHONY_CFILES = gcu.c + MDIO_CFILES = gcu_main.c gcu_if.c + MDIO_HFILES = gcu.h gcu_if.h gcu_reg.h kcompat.h + ++KVER=$(shell uname -r) ++ + # + # Variables: + # KSRC (path to kernel source to build against) +@@ -50,45 +52,16 @@ MDIO_HFILES = gcu.h gcu_if.h gcu_reg.h k + + # set KSRC, KOBJ, and EXTERNAL_MDIO to default values of not already set + # +-KOBJ ?= /usr/src/kernels/linux +-KSRC ?= /usr/src/kernels/linux ++#KOBJ=/usr/src/kernels/linux ++#KSRC=/usr/src/kernels/linux ++#KSRC=$(KOBJ) + EXTERNAL_MDIO ?= 1 + GBE_NAME = iegbe + GCU_NAME = gcu + +-# By default the workaround for the IEGBE writeback issue is enabled +-# +-IEGBE_GBE_WORKAROUND ?= 0 +- +-# If the platform only supports 10/100 this variable needs to be set +-# so the default advertisement is set appropriately. +-# By default, this variable will be disabled. +-# +-IEGBE_10_100_ONLY ?= 0 +- +-# check for version.h and autoconf.h for running kernel in /boot (SUSE) +-ifneq (,$(wildcard /boot/vmlinuz.version.h)) +- VERSION_FILE := /boot/vmlinuz.version.h +- CONFIG_FILE := /boot/vmlinuz.autoconf.h +- KVER := $(shell $(CC) $(CFLAGS) -E -dM $(VERSION_FILE) | \ +- grep UTS_RELEASE | awk '{ print $$3 }' | sed 's/\"//g') +- ifeq ($(KVER),$(shell uname -r)) +- # set up include path to override headers from kernel source +- x:=$(shell rm -rf include) +- x:=$(shell mkdir -p include/linux) +- x:=$(shell cp /boot/vmlinuz.version.h include/linux/version.h) +- x:=$(shell cp /boot/vmlinuz.autoconf.h include/linux/autoconf.h) +- CFLAGS += -I./include +- else +- VERSION_FILE := $(KOBJ)/include/linux/version.h +- UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h +- CONFIG_FILE := $(KOBJ)/include/linux/autoconf.h +- endif +-else +- VERSION_FILE := $(KOBJ)/include/linux/version.h +- UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h +- CONFIG_FILE := $(KOBJ)/include/linux/autoconf.h +-endif ++VERSION_FILE := $(KSRC)/include/linux/version.h ++UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h ++CONFIG_FILE := $(KSRC)/include/linux/autoconf.h + + ifeq (,$(wildcard $(VERSION_FILE))) + $(error Linux kernel source not configured - missing version.h) +@@ -98,83 +71,8 @@ ifeq (,$(wildcard $(CONFIG_FILE))) + $(error Linux kernel source not configured - missing autoconf.h) + endif + +-# as of 2.6.16, kernel define UTS_RELEASE has been moved to utsrelease.h +-# so check that file for kernel version string instead of version.h +-USE_UTS_REL := $(shell [ -f $(UTS_REL_FILE) ] && echo "1") +- +-# pick a compiler +-ifneq (,$(findstring egcs-2.91.66, $(shell cat /proc/version))) +- CC := kgcc gcc cc +-else +- CC := gcc cc +-endif +-test_cc = $(shell $(cc) --version > /dev/null 2>&1 && echo $(cc)) +-CC := $(foreach cc, $(CC), $(test_cc)) +-CC := $(firstword $(CC)) +-ifeq (,$(CC)) +- $(error Compiler not found) +-endif +- +-# we need to know what platform the driver is being built on +-# some additional features are only built on Intel platforms +-ARCH := $(shell uname -m | sed 's/i.86/i386/') +-ifeq ($(ARCH),alpha) +- CFLAGS += -ffixed-8 -mno-fp-regs +-endif +-ifeq ($(ARCH),x86_64) +- CFLAGS += -mcmodel=kernel -mno-red-zone +-endif +-ifeq ($(ARCH),ppc) +- CFLAGS += -msoft-float +-endif +-ifeq ($(ARCH),ppc64) +- CFLAGS += -m64 -msoft-float +- LDFLAGS += -melf64ppc +-endif +- +-# standard flags for module builds +-CFLAGS += -DLINUX -D__KERNEL__ -DMODULE -O2 -pipe -Wall +-CFLAGS += -I$(KSRC)/include -I. +-CFLAGS += $(shell [ -f $(KSRC)/include/linux/modversions.h ] && \ +- echo "-DMODVERSIONS -DEXPORT_SYMTAB \ +- -include $(KSRC)/include/linux/modversions.h") +- +-ifeq ($(IEGBE_GBE_WORKAROUND), 1) +-CFLAGS += -DIEGBE_GBE_WORKAROUND -DE1000_NO_NAPI +-endif +- +-ifeq ($(IEGBE_10_100_ONLY), 1) +-CFLAGS += -DIEGBE_10_100_ONLY +-endif +- +-CFLAGS += $(CFLAGS_EXTRA) +-#ifeq (,$(shell echo $(CFLAGS_EXTRA) | grep NAPI)) +-#CFLAGS += -DE1000_NO_NAPI +-#CFLAGS_EXTRA += -DE1000_NO_NAPI +-#endif +- +-RHC := $(KSRC)/include/linux/rhconfig.h +-ifneq (,$(wildcard $(RHC))) +- # 7.3 typo in rhconfig.h +- ifneq (,$(shell $(CC) $(CFLAGS) -E -dM $(RHC) | grep __module__bigmem)) +- CFLAGS += -D__module_bigmem +- endif +-endif +- +-# get the kernel version - we use this to find the correct install path +-ifeq ($(USE_UTS_REL), 1) +- KVER := $(shell $(CC) $(CFLAGS) -E -dM $(UTS_REL_FILE) | grep UTS_RELEASE | \ +- awk '{ print $$3 }' | sed 's/\"//g') +-else +- KVER := $(shell $(CC) $(CFLAGS) -E -dM $(VERSION_FILE) | grep UTS_RELEASE | \ +- awk '{ print $$3 }' | sed 's/\"//g') +-endif +- +-KKVER := $(shell echo $(KVER) | \ +- awk '{ if ($$0 ~ /2\.[6-9]\./) print "1"; else print "0"}') +-ifeq ($(KKVER), 0) +- $(error *** Aborting the build. \ +- *** This driver is not supported on kernel versions older than 2.6.18) ++ifeq (,$(wildcard $(UTS_REL_FILE))) ++ $(error Linux kernel source not configured - missing utsrelease.h) + endif + + # set the install path +@@ -202,11 +100,11 @@ ifneq ($(SMP),$(shell uname -a | grep SM + endif + + ifeq ($(SMP),1) +- CFLAGS += -D__SMP__ ++ EXTRA_CFLAGS += -D__SMP__ + endif + + ifeq ($(EXTERNAL_MDIO), 1) +- CFLAGS += -DEXTERNAL_MDIO ++ EXTRA_CFLAGS += -DEXTERNAL_MDIO + endif + + ########################################################################### +@@ -223,7 +121,6 @@ MANSECTION = 7 + MANFILE = $(TARGET:.ko=.$(MANSECTION)) + + ifneq ($(PATCHLEVEL),) +- EXTRA_CFLAGS += $(CFLAGS_EXTRA) + obj-m += $(TARGET:.ko=.o) + iegbe-objs := $(CFILES:.c=.o) + ifeq ($(EXTERNAL_MDIO),1) +--- a/filelist ++++ b/filelist +@@ -1,41 +1,3 @@ +-Embedded/Makefile +-Embedded/environment.mk +-Embedded/src/1588/1588.c +-Embedded/src/1588/1588.h +-Embedded/src/1588/IxTimeSyncAcc_p.h +-Embedded/src/1588/Makefile +-Embedded/src/1588/ixtimesyncacc.c +-Embedded/src/1588/ixtimesyncacc.h +-Embedded/src/1588/linux_ioctls.h +-Embedded/src/CAN/Makefile +-Embedded/src/CAN/can_fifo.c +-Embedded/src/CAN/can_fifo.h +-Embedded/src/CAN/can_ioctl.h +-Embedded/src/CAN/can_main.c +-Embedded/src/CAN/can_main.h +-Embedded/src/CAN/can_port.h +-Embedded/src/CAN/icp_can.c +-Embedded/src/CAN/icp_can.h +-Embedded/src/CAN/icp_can_regs.h +-Embedded/src/CAN/icp_can_types.h +-Embedded/src/CAN/icp_can_user.h +-Embedded/src/EDMA/Makefile +-Embedded/src/EDMA/dma.h +-Embedded/src/EDMA/dma_api.h +-Embedded/src/EDMA/dma_client_api.c +-Embedded/src/EDMA/dma_common.c +-Embedded/src/EDMA/dma_internals.h +-Embedded/src/EDMA/dma_linux.c +-Embedded/src/EDMA/os/os.c +-Embedded/src/EDMA/os/os.h +-Embedded/src/EDMA/os/os_list.c +-Embedded/src/EDMA/os/os_list.h +-Embedded/src/EDMA/os/os_types.h +-Embedded/src/GPIO/Makefile +-Embedded/src/GPIO/common.h +-Embedded/src/GPIO/gpio.h +-Embedded/src/GPIO/gpio_ref.c +-Embedded/src/GPIO/linux_ioctls.h + Embedded/src/GbE/Makefile + Embedded/src/GbE/gcu.h + Embedded/src/GbE/gcu_if.c +@@ -55,16 +17,6 @@ Embedded/src/GbE/iegbe_param.c + Embedded/src/GbE/kcompat.c + Embedded/src/GbE/kcompat.h + Embedded/src/GbE/kcompat_ethtool.c +-Embedded/src/WDT/Makefile +-Embedded/src/WDT/iwdt.c +-Embedded/src/WDT/iwdt.h +-Embedded/src/patches/Intel_EP80579_RHEL5.patch +-Embedded/src/patches/pci.ids_RHEL5.patch + LICENSE.GPL +-build_system/build_files/Core/ia.mk +-build_system/build_files/OS/linux_2.6.mk +-build_system/build_files/OS/linux_2.6_kernel_space_rules.mk +-build_system/build_files/common.mk +-build_system/build_files/rules.mk + filelist + versionfile +--- a/versionfile ++++ b/versionfile +@@ -1,4 +1,4 @@ +-PACKAGE_TYPE=Embedded ++PACKAGE_TYPE=Embedded.Release.Patch + + PACKAGE_OS=L + +@@ -6,4 +6,6 @@ PACKAGE_VERSION_MAJOR_NUMBER=1 + + PACKAGE_VERSION_MINOR_NUMBER=0 + +-PACKAGE_VERSION_PATCH_NUMBER=34 ++PACKAGE_VERSION_PATCH_NUMBER=7 ++ ++PACKAGE_VERSION_BUILD_NUMBER=5 diff --git a/package/ep80579-drivers/patches/002-cflags_cleanup.patch b/package/ep80579-drivers/patches/002-cflags_cleanup.patch new file mode 100644 index 000000000..f89752795 --- /dev/null +++ b/package/ep80579-drivers/patches/002-cflags_cleanup.patch @@ -0,0 +1,22 @@ +--- a/build_system/build_files/common.mk ++++ b/build_system/build_files/common.mk +@@ -122,7 +122,7 @@ CC=$(COMPILER) + LD=$(LINKER) + AR=$(ARCHIVER) + +-CFLAGS+=-O2 ++#CFLAGS+=-O2 + + + PWD= $(shell pwd) +--- a/build_system/build_files/OS/linux_2.6.mk ++++ b/build_system/build_files/OS/linux_2.6.mk +@@ -80,7 +80,7 @@ endif + + + ifeq ($(OS_LEVEL), kernel_space) +-CFLAGS+= ++#CFLAGS+= + endif + + diff --git a/package/ep80579-drivers/patches/003-new_irqf_constants.patch b/package/ep80579-drivers/patches/003-new_irqf_constants.patch new file mode 100644 index 000000000..af231f218 --- /dev/null +++ b/package/ep80579-drivers/patches/003-new_irqf_constants.patch @@ -0,0 +1,53 @@ +--- a/Embedded/src/1588/1588.c ++++ b/Embedded/src/1588/1588.c +@@ -291,7 +291,7 @@ int pci_probe(struct pci_dev *dev, const + + } + +- if ( request_irq(dev->irq, ×ync_isr, SA_SHIRQ, DRIVERNAME, ++ if ( request_irq(dev->irq, ×ync_isr, IRQF_SHARED, DRIVERNAME, + &g_drvr_data) ) + { + printk("%s-pci_probe: irq\n", DRIVERNAME); +--- a/Embedded/src/CAN/can_main.c ++++ b/Embedded/src/CAN/can_main.c +@@ -424,7 +424,7 @@ int can_open(struct inode *inode, struct + err = request_irq( + can_os->irq, + can_irq_handler, +- SA_SHIRQ, ++ IRQF_SHARED, + iminor(can_os->inode) ? CAN_PROC_1 : CAN_PROC_0, + &(g_can_os[iminor(can_os->inode)]) + ); +--- a/Embedded/src/EDMA/dma_linux.c ++++ b/Embedded/src/EDMA/dma_linux.c +@@ -367,7 +367,7 @@ int32_t edma_resume(struct pci_dev *dev) + return -ENODEV; + } + +- if (request_irq(dev->irq, &edma_irq_handler, SA_SHIRQ, ++ if (request_irq(dev->irq, &edma_irq_handler, IRQF_SHARED, + g_char_drvr_name, dev) ) + { + +@@ -829,7 +829,7 @@ int32_t edma_probe(struct pci_dev * dev, + /* + * Obtain a (shared) Interrupt Request (IRQ) Line from the OS. + */ +- if (request_irq(dev->irq, &edma_irq_handler, SA_SHIRQ, ++ if (request_irq(dev->irq, &edma_irq_handler, IRQF_SHARED, + g_char_drvr_name, dev) ) + { + +--- a/Embedded/src/WDT/iwdt.c ++++ b/Embedded/src/WDT/iwdt.c +@@ -1461,7 +1461,7 @@ static int __init wdt_init_one(struct pc + + /* Request irq only if wdt_irq is other than 0 */ + if (wdt_irq) { +- if (request_irq(wdt_irq, wdt_isr, SA_INTERRUPT | SA_SHIRQ, ++ if (request_irq(wdt_irq, wdt_isr, IRQF_DISABLED | IRQF_SHARED, + "iwdt", &wdt_miscdev)) { + printk("IRQ %d is not free.\n", wdt_irq); + return -EIO; diff --git a/package/ep80579-drivers/patches/100-iegbe_netdev_ops.patch b/package/ep80579-drivers/patches/100-iegbe_netdev_ops.patch new file mode 100644 index 000000000..ab23da63f --- /dev/null +++ b/package/ep80579-drivers/patches/100-iegbe_netdev_ops.patch @@ -0,0 +1,56 @@ +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -724,6 +724,26 @@ static void iegbe_dump_eeprom(struct ieg + kfree(data); + } + ++static const struct net_device_ops iegbe_netdev_ops = { ++ .ndo_open = iegbe_open, ++ .ndo_stop = iegbe_close, ++ .ndo_start_xmit = iegbe_xmit_frame, ++ .ndo_get_stats = iegbe_get_stats, ++ .ndo_set_rx_mode = iegbe_set_rx_mode, ++ .ndo_set_mac_address = iegbe_set_mac, ++ .ndo_tx_timeout = iegbe_tx_timeout, ++ .ndo_change_mtu = iegbe_change_mtu, ++ .ndo_do_ioctl = iegbe_ioctl, ++ .ndo_validate_addr = eth_validate_addr, ++ ++ .ndo_vlan_rx_register = iegbe_vlan_rx_register, ++ .ndo_vlan_rx_add_vid = iegbe_vlan_rx_add_vid, ++ .ndo_vlan_rx_kill_vid = iegbe_vlan_rx_kill_vid, ++#ifdef CONFIG_NET_POLL_CONTROLLER ++ .ndo_poll_controller = iegbe_netpoll, ++#endif ++}; ++ + /** + * iegbe_probe - Device Initialization Routine + * @pdev: PCI device information struct +@@ -800,24 +820,11 @@ static int __devinit iegbe_probe(struct + if (!hw->hw_addr) + goto err_ioremap; + +- netdev->open = &iegbe_open; +- netdev->stop = &iegbe_close; +- netdev->hard_start_xmit = &iegbe_xmit_frame; +- netdev->get_stats = &iegbe_get_stats; +- netdev->set_rx_mode = &iegbe_set_rx_mode; +- netdev->set_mac_address = &iegbe_set_mac; +- netdev->change_mtu = &iegbe_change_mtu; +- netdev->do_ioctl = &iegbe_ioctl; ++ netdev->netdev_ops = &iegbe_netdev_ops; + set_ethtool_ops(netdev); +- netdev->tx_timeout = &iegbe_tx_timeout; + netdev->watchdog_timeo = 5 * HZ; + netif_napi_add(netdev, &adapter->napi, iegbe_clean, 64); +- netdev->vlan_rx_register = iegbe_vlan_rx_register; +- netdev->vlan_rx_add_vid = iegbe_vlan_rx_add_vid; +- netdev->vlan_rx_kill_vid = iegbe_vlan_rx_kill_vid; +-#ifdef CONFIG_NET_POLL_CONTROLLER +- netdev->poll_controller = iegbe_netpoll; +-#endif ++ + strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); + + diff --git a/package/ep80579-drivers/patches/101-iegbe_fix_napi_interface.patch b/package/ep80579-drivers/patches/101-iegbe_fix_napi_interface.patch new file mode 100644 index 000000000..921d464ba --- /dev/null +++ b/package/ep80579-drivers/patches/101-iegbe_fix_napi_interface.patch @@ -0,0 +1,41 @@ +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -3465,12 +3465,12 @@ static irqreturn_t iegbe_intr_msi(int ir + printk("Critical error! ICR = 0x%x\n", icr); + return IRQ_HANDLED; + } +- if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) { ++ if (likely(napi_schedule_prep(&adapter->napi))) { + adapter->total_tx_bytes = 0; + adapter->total_tx_packets = 0; + adapter->total_rx_bytes = 0; + adapter->total_rx_packets = 0; +- __netif_rx_schedule(netdev, &adapter->napi); ++ __napi_schedule(&adapter->napi); + } else + iegbe_irq_enable(adapter); + +@@ -3527,12 +3527,12 @@ iegbe_intr(int irq, void *data) + E1000_WRITE_REG(&adapter->hw, IMC, ~0); + E1000_WRITE_FLUSH(&adapter->hw); + } +- if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) { ++ if (likely(napi_schedule_prep(&adapter->napi))) { + adapter->total_tx_bytes = 0; + adapter->total_tx_packets = 0; + adapter->total_rx_bytes = 0; + adapter->total_rx_packets = 0; +- __netif_rx_schedule(netdev, &adapter->napi); ++ __napi_schedule(&adapter->napi); + } else + /* this really should not happen! if it does it is basically a + * bug, but not a hard error, so enable ints and continue */ +@@ -3574,7 +3574,7 @@ static int iegbe_clean(struct napi_struc + if (work_done < budget) { + if (likely(adapter->itr_setting & 3)) + iegbe_set_itr(adapter); +- netif_rx_complete(poll_dev, napi); ++ napi_complete(napi); + iegbe_irq_enable(adapter); + } + diff --git a/package/ep80579-drivers/patches/102-iegbe_nuke_polling_netdev.patch b/package/ep80579-drivers/patches/102-iegbe_nuke_polling_netdev.patch new file mode 100644 index 000000000..7147449c2 --- /dev/null +++ b/package/ep80579-drivers/patches/102-iegbe_nuke_polling_netdev.patch @@ -0,0 +1,103 @@ +--- a/Embedded/src/GbE/iegbe.h ++++ b/Embedded/src/GbE/iegbe.h +@@ -316,7 +316,6 @@ struct iegbe_adapter { + int cleaned_count); + struct iegbe_rx_ring *rx_ring; /* One per active queue */ + struct napi_struct napi; +- struct net_device *polling_netdev; /* One per active queue */ + + int num_tx_queues; + int num_rx_queues; +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -763,7 +763,7 @@ static int __devinit iegbe_probe(struct + struct iegbe_hw *hw; + + static int cards_found = 0; +- int i, err, pci_using_dac; ++ int err, pci_using_dac; + u16 eeprom_data = 0; + u16 eeprom_apme_mask = E1000_EEPROM_APME; + int bars; +@@ -984,11 +984,8 @@ err_eeprom: + iegbe_phy_hw_reset(hw); + if (hw->flash_address) + iounmap(hw->flash_address); +- for (i = 0; i < adapter->num_rx_queues; i++) +- dev_put(&adapter->polling_netdev[i]); + kfree(adapter->tx_ring); + kfree(adapter->rx_ring); +- kfree(adapter->polling_netdev); + err_sw_init: + iounmap(hw->hw_addr); + err_ioremap: +@@ -1017,7 +1014,6 @@ iegbe_remove(struct pci_dev *pdev) + struct net_device *netdev = pci_get_drvdata(pdev); + struct iegbe_adapter *adapter = netdev_priv(netdev); + uint32_t manc; +- int i; + + if(adapter->hw.mac_type >= iegbe_82540 + && adapter->hw.mac_type != iegbe_icp_xxxx +@@ -1030,15 +1026,11 @@ iegbe_remove(struct pci_dev *pdev) + } + + unregister_netdev(netdev); +- for (i = 0x0; i < adapter->num_rx_queues; i++) +- dev_put(&adapter->polling_netdev[i]); +- + if(!iegbe_check_phy_reset_block(&adapter->hw)) { + iegbe_phy_hw_reset(&adapter->hw); + } + kfree(adapter->tx_ring); + kfree(adapter->rx_ring); +- kfree(adapter->polling_netdev); + + iounmap(adapter->hw.hw_addr); + pci_release_regions(pdev); +@@ -1061,7 +1053,6 @@ iegbe_sw_init(struct iegbe_adapter *adap + struct iegbe_hw *hw = &adapter->hw; + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; +- int i; + + /* PCI config space info */ + +@@ -1111,11 +1102,6 @@ iegbe_sw_init(struct iegbe_adapter *adap + return -ENOMEM; + } + +- for (i = 0; i < adapter->num_rx_queues; i++) { +- adapter->polling_netdev[i].priv = adapter; +- dev_hold(&adapter->polling_netdev[i]); +- set_bit(__LINK_STATE_START, &adapter->polling_netdev[i].state); +- } + spin_lock_init(&adapter->tx_queue_lock); + + /* +@@ -1137,8 +1123,7 @@ iegbe_sw_init(struct iegbe_adapter *adap + * @adapter: board private structure to initialize + * + * We allocate one ring per queue at run-time since we don't know the +- * number of queues at compile-time. The polling_netdev array is +- * intended for Multiqueue, but should work fine with a single queue. ++ * number of queues at compile-time. + **/ + + static int __devinit +@@ -1158,15 +1143,6 @@ iegbe_alloc_queues(struct iegbe_adapter + return -ENOMEM; + } + +- adapter->polling_netdev = kcalloc(adapter->num_rx_queues, +- sizeof(struct net_device), +- GFP_KERNEL); +- if (!adapter->polling_netdev) { +- kfree(adapter->tx_ring); +- kfree(adapter->rx_ring); +- return -ENOMEM; +- } +- + return E1000_SUCCESS; + } + diff --git a/package/ep80579-drivers/patches/103-iegbe_convert_unicast_addr_list.patch b/package/ep80579-drivers/patches/103-iegbe_convert_unicast_addr_list.patch new file mode 100644 index 000000000..71d2d54e6 --- /dev/null +++ b/package/ep80579-drivers/patches/103-iegbe_convert_unicast_addr_list.patch @@ -0,0 +1,60 @@ +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -2161,7 +2161,8 @@ static void iegbe_set_rx_mode(struct net + { + struct iegbe_adapter *adapter = netdev_priv(netdev); + struct iegbe_hw *hw = &adapter->hw; +- struct dev_addr_list *uc_ptr; ++ struct netdev_hw_addr *ha; ++ bool use_uc = false; + struct dev_addr_list *mc_ptr; + u32 rctl; + u32 hash_value; +@@ -2187,12 +2188,11 @@ int mta_reg_count = E1000_NUM_MTA_REGIST + } + } + +- uc_ptr = NULL; + if (netdev->uc_count > rar_entries - 1) { + rctl |= E1000_RCTL_UPE; + } else if (!(netdev->flags & IFF_PROMISC)) { + rctl &= ~E1000_RCTL_UPE; +- uc_ptr = netdev->uc_list; ++ use_uc = true; + } + + E1000_WRITE_REG(&adapter->hw, RCTL, rctl); +@@ -2210,13 +2210,20 @@ int mta_reg_count = E1000_NUM_MTA_REGIST + * if there are not 14 addresses, go ahead and clear the filters + * -- with 82571 controllers only 0-13 entries are filled here + */ ++ i = 1; ++ if (use_uc) ++ list_for_each_entry(ha, &netdev->uc_list, list) { ++ if (i == rar_entries) ++ break; ++ iegbe_rar_set(hw, ha->addr, i++); ++ } ++ ++ WARN_ON(i == rar_entries); ++ + mc_ptr = netdev->mc_list; + +- for (i = 1; i < rar_entries; i++) { +- if (uc_ptr) { +- iegbe_rar_set(hw, uc_ptr->da_addr, i); +- uc_ptr = uc_ptr->next; +- } else if (mc_ptr) { ++ for (; i < rar_entries; i++) { ++ if (mc_ptr) { + iegbe_rar_set(hw, mc_ptr->da_addr, i); + mc_ptr = mc_ptr->next; + } else { +@@ -2226,7 +2233,6 @@ int mta_reg_count = E1000_NUM_MTA_REGIST + E1000_WRITE_FLUSH(&adapter->hw); + } + } +- WARN_ON(uc_ptr != NULL); + + /* clear the old settings from the multicast hash table */ + diff --git a/package/ep80579-drivers/patches/104-iegbe_group_address_list_and_its_count.patch b/package/ep80579-drivers/patches/104-iegbe_group_address_list_and_its_count.patch new file mode 100644 index 000000000..c6eced6a5 --- /dev/null +++ b/package/ep80579-drivers/patches/104-iegbe_group_address_list_and_its_count.patch @@ -0,0 +1,20 @@ +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -2188,7 +2188,7 @@ int mta_reg_count = E1000_NUM_MTA_REGIST + } + } + +- if (netdev->uc_count > rar_entries - 1) { ++ if (netdev->uc.count > rar_entries - 1) { + rctl |= E1000_RCTL_UPE; + } else if (!(netdev->flags & IFF_PROMISC)) { + rctl &= ~E1000_RCTL_UPE; +@@ -2212,7 +2212,7 @@ int mta_reg_count = E1000_NUM_MTA_REGIST + */ + i = 1; + if (use_uc) +- list_for_each_entry(ha, &netdev->uc_list, list) { ++ list_for_each_entry(ha, &netdev->uc.list, list) { + if (i == rar_entries) + break; + iegbe_rar_set(hw, ha->addr, i++); diff --git a/package/ep80579-drivers/patches/105-iegbe_new_dma_masks.patch b/package/ep80579-drivers/patches/105-iegbe_new_dma_masks.patch new file mode 100644 index 000000000..c7a103b44 --- /dev/null +++ b/package/ep80579-drivers/patches/105-iegbe_new_dma_masks.patch @@ -0,0 +1,20 @@ +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -775,13 +775,13 @@ static int __devinit iegbe_probe(struct + if (err) + return err; + +- if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK) && +- !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) { ++ if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && ++ !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { + pci_using_dac = 1; + } else { +- err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); ++ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (err) { +- err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); ++ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + if (err) { + E1000_ERR("No usable DMA configuration, " + "aborting\n"); diff --git a/package/ep80579-drivers/patches/106-iegbe_new_irqf_constant.patch b/package/ep80579-drivers/patches/106-iegbe_new_irqf_constant.patch new file mode 100644 index 000000000..a08e8c769 --- /dev/null +++ b/package/ep80579-drivers/patches/106-iegbe_new_irqf_constant.patch @@ -0,0 +1,12 @@ +--- a/Embedded/src/GbE/iegbe_ethtool.c ++++ b/Embedded/src/GbE/iegbe_ethtool.c +@@ -944,7 +944,8 @@ iegbe_intr_test(struct iegbe_adapter *ad + *data = 0; + + /* Hook up test interrupt handler just for this test */ +- if(!request_irq(irq, &iegbe_test_intr, 0, netdev->name, netdev)) { ++ if(!request_irq(irq, &iegbe_test_intr, IRQF_PROBE_SHARED, netdev->name, ++ netdev)) { + shared_int = FALSE; + } else if(request_irq(irq, &iegbe_test_intr, IRQF_SHARED, + netdev->name, netdev)){ diff --git a/package/ep80579-drivers/patches/150-ocracoke_island.patch b/package/ep80579-drivers/patches/150-ocracoke_island.patch new file mode 100644 index 000000000..34c11daac --- /dev/null +++ b/package/ep80579-drivers/patches/150-ocracoke_island.patch @@ -0,0 +1,747 @@ +--- a/Embedded/src/GbE/iegbe_oem_phy.c ++++ b/Embedded/src/GbE/iegbe_oem_phy.c +@@ -65,6 +65,10 @@ static int32_t iegbe_oem_link_m88_setup( + static int32_t iegbe_oem_set_phy_mode(struct iegbe_hw *hw); + static int32_t iegbe_oem_detect_phy(struct iegbe_hw *hw); + ++static int32_t iegbe_oem_link_bcm5481_setup(struct iegbe_hw *hw); ++static int32_t bcm5481_read_18sv (struct iegbe_hw *hw, int sv, uint16_t *data); ++static int32_t oi_phy_setup (struct iegbe_hw *hw); ++ + /** + * iegbe_oem_setup_link + * @hw: iegbe_hw struct containing device specific information +@@ -114,6 +118,10 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + } + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ return E1000_SUCCESS; ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_link_m88_setup(hw); +@@ -121,6 +129,12 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + return ret_val; + } + break; ++ case BCM5481_PHY_ID: ++ ret_val = iegbe_oem_link_bcm5481_setup(hw); ++ if(ret_val) { ++ return ret_val; ++ } ++ break; + default: + DEBUGOUT("Invalid PHY ID\n"); + return -E1000_ERR_PHY_TYPE; +@@ -179,6 +193,51 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + #endif /* ifdef EXTERNAL_MDIO */ + } + ++/** ++ * iegbe_oem_link_bcm5481_setup ++ * @hw: iegbe_hw struct containing device specific information ++ * ++ * Returns E1000_SUCCESS, negative E1000 error code on failure ++ * ++ * copied verbatim from iegbe_oem_link_m88_setup ++ **/ ++static int32_t ++iegbe_oem_link_bcm5481_setup(struct iegbe_hw *hw) ++{ ++ int32_t ret_val; ++ uint16_t phy_data; ++ ++ //DEBUGFUNC(__func__); ++ ++ if(!hw) ++ return -1; ++ ++ /* phy_reset_disable is set in iegbe_oem_set_phy_mode */ ++ if(hw->phy_reset_disable) ++ return E1000_SUCCESS; ++ ++ // Enable MDIX in extended control reg. ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, BCM5481_ECTRL, &phy_data); ++ if(ret_val) ++ { ++ DEBUGOUT("Unable to read BCM5481_ECTRL register\n"); ++ return ret_val; ++ } ++ ++ phy_data &= ~BCM5481_ECTRL_DISMDIX; ++ ret_val = iegbe_oem_write_phy_reg_ex(hw, BCM5481_ECTRL, phy_data); ++ if(ret_val) ++ { ++ DEBUGOUT("Unable to write BCM5481_ECTRL register\n"); ++ return ret_val; ++ } ++ ++ ret_val = oi_phy_setup (hw); ++ if (ret_val) ++ return ret_val; ++ ++ return E1000_SUCCESS; ++} + + /** + * iegbe_oem_link_m88_setup +@@ -340,6 +399,11 @@ iegbe_oem_force_mdi(struct iegbe_hw *hw, + * see iegbe_phy_force_speed_duplex, which does the following for M88 + */ + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_force_mdi() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, +@@ -415,6 +479,8 @@ iegbe_oem_phy_reset_dsp(struct iegbe_hw + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: ++ case BCM5395S_PHY_ID: + DEBUGOUT("No DSP to reset on OEM PHY\n"); + break; + default: +@@ -460,6 +526,11 @@ iegbe_oem_cleanup_after_phy_reset(struct + * see iegbe_phy_force_speed_duplex, which does the following for M88 + */ + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_cleanup_after_phy_reset() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + /* +@@ -573,6 +644,11 @@ iegbe_oem_set_phy_mode(struct iegbe_hw * + * use iegbe_set_phy_mode as example + */ + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_set_phy_mode() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_read_eeprom(hw, +@@ -641,6 +717,19 @@ iegbe_oem_detect_phy(struct iegbe_hw *hw + } + hw->phy_type = iegbe_phy_oem; + ++{ ++ // If MAC2 (BCM5395 switch), manually detect the phy ++ struct iegbe_adapter *adapter; ++ uint32_t device_number; ++ adapter = (struct iegbe_adapter *) hw->back; ++ device_number = PCI_SLOT(adapter->pdev->devfn); ++ if (device_number == ICP_XXXX_MAC_2) { ++ hw->phy_id = BCM5395S_PHY_ID; ++ hw->phy_revision = 0; ++ return E1000_SUCCESS; ++ } ++} ++ + ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_ID1, &phy_id_high); + if(ret_val) { + DEBUGOUT("Unable to read PHY register PHY_ID1\n"); +@@ -690,6 +779,8 @@ iegbe_oem_get_tipg(struct iegbe_hw *hw) + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: ++ case BCM5395S_PHY_ID: + phy_num = DEFAULT_ICP_XXXX_TIPG_IPGT; + break; + default: +@@ -738,6 +829,8 @@ iegbe_oem_phy_is_copper(struct iegbe_hw + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: ++ case BCM5395S_PHY_ID: + isCopper = TRUE; + break; + default: +@@ -796,13 +889,13 @@ iegbe_oem_get_phy_dev_number(struct iegb + switch(device_number) + { + case ICP_XXXX_MAC_0: +- hw->phy_addr = 0x00; ++ hw->phy_addr = 0x01; + break; + case ICP_XXXX_MAC_1: +- hw->phy_addr = 0x01; ++ hw->phy_addr = 0x02; + break; + case ICP_XXXX_MAC_2: +- hw->phy_addr = 0x02; ++ hw->phy_addr = 0x00; + break; + default: hw->phy_addr = 0x00; + } +@@ -851,6 +944,12 @@ iegbe_oem_mii_ioctl(struct iegbe_adapter + if(!adapter || !ifr) { + return -1; + } ++ ++ // If MAC2 (BCM5395 switch) then leave now ++ if ((PCI_SLOT(adapter->pdev->devfn)) == ICP_XXXX_MAC_2) { ++ return -1; ++ } ++ + switch (data->reg_num) { + case PHY_CTRL: + if(mii_reg & MII_CR_POWER_DOWN) { +@@ -987,6 +1086,11 @@ void iegbe_oem_get_phy_regs(struct iegbe + * [10] = mdix mode + */ + switch (adapter->hw.phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_get_phy_regs() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + if(corrected_len > 0) { +@@ -1068,8 +1172,13 @@ iegbe_oem_phy_loopback(struct iegbe_adap + * Loopback configuration is the same for each of the supported PHYs. + */ + switch (adapter->hw.phy_id) { ++ case BCM5395S_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_phy_loopback() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: + + adapter->hw.autoneg = FALSE; + +@@ -1182,8 +1291,14 @@ iegbe_oem_loopback_cleanup(struct iegbe_ + } + + switch (adapter->hw.phy_id) { ++ case BCM5395S_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_loopback_cleanup() has been called!\n"); ++ return; ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: + default: + adapter->hw.autoneg = TRUE; + +@@ -1243,6 +1358,11 @@ iegbe_oem_phy_speed_downgraded(struct ie + */ + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ *isDowngraded = 0; ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, +@@ -1305,6 +1425,11 @@ iegbe_oem_check_polarity(struct iegbe_hw + */ + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ *polarity = 0; ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + /* return the Polarity bit in the Status register. */ +@@ -1367,6 +1492,25 @@ iegbe_oem_phy_is_full_duplex(struct iegb + */ + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ /* Always full duplex */ ++ *isFD = 1; ++ break; ++ ++ case BCM5481_PHY_ID: ++ ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data); ++ if(ret_val) return ret_val; ++ ++ switch (BCM5481_ASTAT_HCD(phy_data)) { ++ case BCM5481_ASTAT_1KBTFD: ++ case BCM5481_ASTAT_100BTXFD: ++ *isFD = 1; ++ break; ++ default: ++ *isFD = 0; ++ } ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, +@@ -1423,6 +1567,25 @@ iegbe_oem_phy_is_speed_1000(struct iegbe + */ + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ /* Always 1000mb */ ++ *is1000 = 1; ++ break; ++ ++ case BCM5481_PHY_ID: ++ ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data); ++ if(ret_val) return ret_val; ++ ++ switch (BCM5481_ASTAT_HCD(phy_data)) { ++ case BCM5481_ASTAT_1KBTFD: ++ case BCM5481_ASTAT_1KBTHD: ++ *is1000 = 1; ++ break; ++ default: ++ *is1000 = 0; ++ } ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, +@@ -1478,6 +1641,25 @@ iegbe_oem_phy_is_speed_100(struct iegbe_ + * see iegbe_config_mac_to_phy + */ + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ /* Always 1000Mb, never 100mb */ ++ *is100 = 0; ++ break; ++ ++ case BCM5481_PHY_ID: ++ ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data); ++ if(ret_val) return ret_val; ++ ++ switch (BCM5481_ASTAT_HCD(phy_data)) { ++ case BCM5481_ASTAT_100BTXFD: ++ case BCM5481_ASTAT_100BTXHD: ++ *is100 = 1; ++ break; ++ default: ++ *is100 = 0; ++ } ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, +@@ -1535,6 +1717,11 @@ iegbe_oem_phy_get_info(struct iegbe_hw * + * see iegbe_phy_m88_get_info + */ + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_phy_get_info() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + /* The downshift status is checked only once, after link is +@@ -1636,8 +1823,13 @@ iegbe_oem_phy_hw_reset(struct iegbe_hw * + * the M88 used in truxton. + */ + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_phy_hw_reset() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_CTRL, &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read register PHY_CTRL\n"); +@@ -1699,6 +1891,8 @@ iegbe_oem_phy_init_script(struct iegbe_h + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: ++ case BCM5395S_PHY_ID: + DEBUGOUT("Nothing to do for OEM PHY Init"); + break; + default: +@@ -1735,6 +1929,11 @@ iegbe_oem_read_phy_reg_ex(struct iegbe_h + return -1; + } + ++ if (hw->phy_id == BCM5395S_PHY_ID) { ++ DEBUGOUT("WARNING: iegbe_oem_read_phy_reg_ex() has been unexpectedly called!\n"); ++ return -1; ++ } ++ + /* call the GCU func that will read the phy + * + * Make note that the M88 phy is what'll be used on Truxton. +@@ -1782,6 +1981,11 @@ iegbe_oem_set_trans_gasket(struct iegbe_ + } + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_set_trans_gasket() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + /* Gasket set correctly for Marvell Phys, so nothing to do */ +@@ -1886,6 +2090,8 @@ iegbe_oem_phy_needs_reset_with_mac(struc + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: ++ case BCM5395S_PHY_ID: + ret_val = FALSE; + break; + default: +@@ -1935,6 +2141,8 @@ iegbe_oem_config_dsp_after_link_change(s + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: ++ case BCM5395S_PHY_ID: + DEBUGOUT("No DSP to configure on OEM PHY"); + break; + default: +@@ -1978,6 +2186,12 @@ iegbe_oem_get_cable_length(struct iegbe_ + } + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ *min_length = 0; ++ *max_length = iegbe_igp_cable_length_150; ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, +@@ -2061,6 +2275,23 @@ iegbe_oem_phy_is_link_up(struct iegbe_hw + */ + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ /* Link always up */ ++ *isUp = TRUE; ++ return E1000_SUCCESS; ++ break; ++ ++ case BCM5481_PHY_ID: ++ iegbe_oem_read_phy_reg_ex(hw, BCM5481_ESTAT, &phy_data); ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, BCM5481_ESTAT, &phy_data); ++ if(ret_val) ++ { ++ DEBUGOUT("Unable to read PHY register BCM5481_ESTAT\n"); ++ return ret_val; ++ } ++ statusMask = BCM5481_ESTAT_LINK; ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); +@@ -2092,3 +2323,210 @@ iegbe_oem_phy_is_link_up(struct iegbe_hw + #endif /* ifdef EXTERNAL_MDIO */ + } + ++ ++ ++//----- ++// Read BCM5481 expansion register ++// ++int32_t ++bcm5481_read_ex (struct iegbe_hw *hw, uint16_t reg, uint16_t *data) ++{ ++ int ret; ++ uint16_t selector; ++ uint16_t reg_data; ++ ++ // Get the current value of bits 15:12 ++ ret = iegbe_oem_read_phy_reg_ex (hw, 0x15, &selector); ++ if (ret) ++ return ret; ++ ++ // Select the expansion register ++ selector &= 0xf000; ++ selector |= (0xf << 8) | (reg); ++ iegbe_oem_write_phy_reg_ex (hw, 0x17, selector); ++ ++ // Read the expansion register ++ ret = iegbe_oem_read_phy_reg_ex (hw, 0x15, ®_data); ++ ++ // De-select the expansion registers. ++ selector &= 0xf000; ++ iegbe_oem_write_phy_reg_ex (hw, 0x17, selector); ++ ++ if (ret) ++ return ret; ++ ++ *data = reg_data; ++ return ret; ++} ++ ++//----- ++// Read reg 0x18 sub-register ++// ++static int32_t ++bcm5481_read_18sv (struct iegbe_hw *hw, int sv, uint16_t *data) ++{ ++ int ret; ++ uint16_t tmp_data; ++ ++ // Select reg 0x18, sv ++ tmp_data = ((sv & BCM5481_R18H_SV_MASK) << 12) | BCM5481_R18H_SV_MCTRL; ++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, tmp_data); ++ if(ret) ++ return ret; ++ ++ // Read reg 0x18, sv ++ ret = iegbe_oem_read_phy_reg_ex (hw, BCM5481_R18H, &tmp_data); ++ if(ret) ++ return ret; ++ ++ *data = tmp_data; ++ return ret; ++} ++ ++//----- ++// Read reg 0x1C sub-register ++// ++int32_t ++bcm5481_read_1csv (struct iegbe_hw *hw, int sv, uint16_t *data) ++{ ++ int ret; ++ uint16_t tmp_data; ++ ++ // Select reg 0x1c, sv ++ tmp_data = ((sv & BCM5481_R1CH_SV_MASK) << BCM5481_R1CH_SV_SHIFT); ++ ++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, tmp_data); ++ if(ret) ++ return ret; ++ ++ // Read reg 0x1c, sv ++ ret = iegbe_oem_read_phy_reg_ex (hw, BCM5481_R1CH, &tmp_data); ++ if(ret) ++ return ret; ++ ++ *data = tmp_data; ++ return ret; ++} ++ ++//----- ++// Read-modify-write a 0x1C register. ++// ++// hw - hardware access info. ++// reg - 0x1C register to modify. ++// data - bits which should be set. ++// mask - the '1' bits in this argument will be cleared in the data ++// read from 'reg' then 'data' will be or'd in and the result ++// will be written to 'reg'. ++ ++int32_t ++bcm5481_rmw_1csv (struct iegbe_hw *hw, uint16_t reg, uint16_t data, uint16_t mask) ++{ ++ int32_t ret; ++ uint16_t reg_data; ++ ++ ret = 0; ++ ++ ret = bcm5481_read_1csv (hw, reg, ®_data); ++ if (ret) ++ { ++ DEBUGOUT("Unable to read BCM5481 1CH register\n"); ++ printk (KERN_ERR "Unable to read BCM5481 1CH register [0x%x]\n", reg); ++ return ret; ++ } ++ ++ reg_data &= ~mask; ++ reg_data |= (BCM5481_R1CH_WE | data); ++ ++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, reg_data); ++ if(ret) ++ { ++ DEBUGOUT("Unable to write BCM5481 1CH register\n"); ++ printk (KERN_ERR "Unable to write BCM5481 1CH register\n"); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++int32_t ++oi_phy_setup (struct iegbe_hw *hw) ++{ ++ int ret; ++ uint16_t pmii_data; ++ uint16_t mctrl_data; ++ uint16_t cacr_data; ++ ++ ret = 0; ++ ++ // Set low power mode via reg 0x18, sv010, bit 6 ++ // Do a read-modify-write on reg 0x18, sv010 register to preserve existing bits. ++ ret = bcm5481_read_18sv (hw, BCM5481_R18H_SV_PMII, &pmii_data); ++ if (ret) ++ { ++ DEBUGOUT("Unable to read BCM5481_R18H_SV_PMII register\n"); ++ printk (KERN_ERR "Unable to read BCM5481_R18H_SV_PMII register\n"); ++ return ret; ++ } ++ ++ // Set the LPM bit in the data just read and write back to sv010 ++ // The shadow register select bits [2:0] are set by reading the sv010 ++ // register. ++ pmii_data |= BCM5481_R18H_SV010_LPM; ++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, pmii_data); ++ if(ret) ++ { ++ DEBUGOUT("Unable to write BCM5481_R18H register\n"); ++ printk (KERN_ERR "Unable to write BCM5481_R18H register\n"); ++ return ret; ++ } ++ ++ ++ // Set the RGMII RXD to RXC skew bit in reg 0x18, sv111 ++ ++ if (bcm5481_read_18sv (hw, BCM5481_R18H_SV_MCTRL, &mctrl_data)) ++ { ++ DEBUGOUT("Unable to read BCM5481_R18H_SV_MCTRL register\n"); ++ printk (KERN_ERR "Unable to read BCM5481_R18H_SV_MCTRL register\n"); ++ return ret; ++ } ++ mctrl_data |= (BCM5481_R18H_WE | BCM5481_R18H_SV111_SKEW); ++ ++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, mctrl_data); ++ if(ret) ++ { ++ DEBUGOUT("Unable to write BCM5481_R18H register\n"); ++ printk (KERN_ERR "Unable to write BCM5481_R18H register\n"); ++ return ret; ++ } ++ ++ // Enable RGMII transmit clock delay in reg 0x1c, sv00011 ++ ret = bcm5481_read_1csv (hw, BCM5481_R1CH_CACR, &cacr_data); ++ if (ret) ++ { ++ DEBUGOUT("Unable to read BCM5481_R1CH_CACR register\n"); ++ printk (KERN_ERR "Unable to read BCM5481_R1CH_CACR register\n"); ++ return ret; ++ } ++ ++ cacr_data |= (BCM5481_R1CH_WE | BCM5481_R1CH_CACR_TCD); ++ ++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, cacr_data); ++ if(ret) ++ { ++ DEBUGOUT("Unable to write BCM5481_R1CH register\n"); ++ printk (KERN_ERR "Unable to write BCM5481_R1CH register\n"); ++ return ret; ++ } ++ ++ // Enable dual link speed indication (0x1c, sv 00010, bit 2) ++ ret = bcm5481_rmw_1csv (hw, BCM5481_R1CH_SC1, BCM5481_R1CH_SC1_LINK, BCM5481_R1CH_SC1_LINK); ++ if (ret) ++ return ret; ++ ++ // Enable link and activity on ACTIVITY LED (0x1c, sv 01001, bit 4=1, bit 3=0) ++ ret = bcm5481_rmw_1csv (hw, BCM5481_R1CH_LCTRL, BCM5481_R1CH_LCTRL_ALEN, BCM5481_R1CH_LCTRL_ALEN | BCM5481_R1CH_LCTRL_AEN); ++ if (ret) ++ return ret; ++ ++ return ret; ++} +--- a/Embedded/src/GbE/iegbe_oem_phy.h ++++ b/Embedded/src/GbE/iegbe_oem_phy.h +@@ -95,6 +95,8 @@ int32_t iegbe_oem_phy_is_link_up(struct + + #define DEFAULT_ICP_XXXX_TIPG_IPGT 8 /* Inter Packet Gap Transmit Time */ + #define ICP_XXXX_TIPG_IPGT_MASK 0x000003FFUL ++#define BCM5481_PHY_ID 0x0143BCA0 ++#define BCM5395S_PHY_ID 0x0143BCF0 + + /* Miscellaneous defines */ + #ifdef IEGBE_10_100_ONLY +@@ -103,5 +105,65 @@ int32_t iegbe_oem_phy_is_link_up(struct + #define ICP_XXXX_AUTONEG_ADV_DEFAULT 0x2F + #endif + ++/* BCM5481 specifics */ ++ ++#define BCM5481_ECTRL (0x10) ++#define BCM5481_ESTAT (0x11) ++#define BCM5481_RXERR (0x12) ++#define BCM5481_EXPRW (0x15) ++#define BCM5481_EXPACC (0x17) ++#define BCM5481_ASTAT (0x19) ++#define BCM5481_R18H (0x18) ++#define BCM5481_R1CH (0x1c) ++ ++/* indirect register access via register 18h */ ++ ++#define BCM5481_R18H_SV_MASK (7) // Mask for SV bits. ++#define BCM5481_R18H_SV_ACTRL (0) // SV000 Aux. control ++#define BCM5481_R18H_SV_10BT (1) // SV001 10Base-T ++#define BCM5481_R18H_SV_PMII (2) // SV010 Power/MII control ++#define BCM5481_R18H_SV_MTEST (4) // SV100 Misc. test ++#define BCM5481_R18H_SV_MCTRL (7) // SV111 Misc. control ++ ++#define BCM5481_R18H_SV001_POL (1 << 13) // Polarity ++#define BCM5481_R18H_SV010_LPM (1 << 6) ++#define BCM5481_R18H_SV111_SKEW (1 << 8) ++#define BCM5481_R18H_WE (1 << 15) // Write enable ++ ++// 0x1c registers ++#define BCM5481_R1CH_SV_SHIFT (10) ++#define BCM5481_R1CH_SV_MASK (0x1f) ++#define BCM5481_R1CH_SC1 (0x02) // sv00010 Spare control 1 ++#define BCM5481_R1CH_CACR (0x03) // sv00011 Clock alignment control ++#define BCM5481_R1CH_LCTRL (0x09) // sv01001 LED control ++#define BCM5481_R1CH_LEDS1 (0x0d) // sv01101 LED selector 1 ++ ++// 0x1c common ++#define BCM5481_R1CH_WE (1 << 15) // Write enable ++ ++// 0x1c, sv 00010 ++#define BCM5481_R1CH_SC1_LINK (1 << 2) // sv00010 Linkspeed ++ ++// 0x1c, sv 00011 ++#define BCM5481_R1CH_CACR_TCD (1 << 9) // sv00011 RGMII tx clock delay ++ ++// 0x1c, sv 01001 ++#define BCM5481_R1CH_LCTRL_ALEN (1 << 4) // Activity/Link enable on ACTIVITY LED ++#define BCM5481_R1CH_LCTRL_AEN (1 << 3) // Activity enable on ACTIVITY LED ++ ++#define BCM5481_ECTRL_DISMDIX (1 <<14) ++ ++#define BCM5481_MCTRL_AUTOMDIX (1 <<9) ++ ++#define BCM5481_ESTAT_LINK (1 << 8) ++ ++#define BCM5481_ASTAT_ANC (1 << 15) ++#define BCM5481_ASTAT_ANHCD (7 << 8) ++#define BCM5481_ASTAT_HCD(x) ((x >> 8) & 7) ++#define BCM5481_ASTAT_1KBTFD (0x7) ++#define BCM5481_ASTAT_1KBTHD (0x6) ++#define BCM5481_ASTAT_100BTXFD (0x5) ++#define BCM5481_ASTAT_100BTXHD (0x3) ++ + #endif /* ifndef _IEGBE_OEM_PHY_H_ */ + diff --git a/package/ep80579-drivers/patches/200-can_fix_ioctl_numbers.patch b/package/ep80579-drivers/patches/200-can_fix_ioctl_numbers.patch new file mode 100644 index 000000000..291946625 --- /dev/null +++ b/package/ep80579-drivers/patches/200-can_fix_ioctl_numbers.patch @@ -0,0 +1,11 @@ +--- a/Embedded/src/CAN/icp_can_user.h ++++ b/Embedded/src/CAN/icp_can_user.h +@@ -63,6 +63,8 @@ + #ifndef __ICP_CAN_USER_H__ + #define __ICP_CAN_USER_H__ + ++#include ++ + /***************************************************************************** + * Device IO control codes. + *****************************************************************************/ diff --git a/package/ep80579-drivers/patches/210-can_include_linux_fs_h.patch b/package/ep80579-drivers/patches/210-can_include_linux_fs_h.patch new file mode 100644 index 000000000..26c53dcea --- /dev/null +++ b/package/ep80579-drivers/patches/210-can_include_linux_fs_h.patch @@ -0,0 +1,11 @@ +--- a/Embedded/src/CAN/can_main.c ++++ b/Embedded/src/CAN/can_main.c +@@ -70,6 +70,8 @@ + + #include "can_main.h" + #include "can_ioctl.h" ++#include ++ + + MODULE_AUTHOR("Intel(R) Corporation"); + MODULE_DESCRIPTION("Controller Area Network Driver"); diff --git a/package/ep80579-drivers/patches/220-can_fix_irq_request.patch b/package/ep80579-drivers/patches/220-can_fix_irq_request.patch new file mode 100644 index 000000000..2950cc79e --- /dev/null +++ b/package/ep80579-drivers/patches/220-can_fix_irq_request.patch @@ -0,0 +1,23 @@ +--- a/Embedded/src/CAN/can_main.c ++++ b/Embedded/src/CAN/can_main.c +@@ -654,7 +654,7 @@ int can_dev_io(struct inode *inode, stru + /***************************************************************************** + * Interrupt handler. + *****************************************************************************/ +-irqreturn_t can_irq_handler(int irq, void *dev_id, struct pt_regs *regs) ++irqreturn_t can_irq_handler(int irq, void *dev_id) + { + can_os_t *can_os = (can_os_t *) dev_id; + unsigned int int_status; +--- a/Embedded/src/CAN/can_main.h ++++ b/Embedded/src/CAN/can_main.h +@@ -165,8 +165,7 @@ int can_dev_io( + + irqreturn_t can_irq_handler( + int irq, +- void *dev_id, +- struct pt_regs *regs); ++ void *dev_id); + + void can_tasklet( + unsigned long arg diff --git a/package/ep80579-drivers/patches/230-can_remove_driver_data_direct_access.patch b/package/ep80579-drivers/patches/230-can_remove_driver_data_direct_access.patch new file mode 100644 index 000000000..57e9c8fc0 --- /dev/null +++ b/package/ep80579-drivers/patches/230-can_remove_driver_data_direct_access.patch @@ -0,0 +1,41 @@ +diff -Nur a/Embedded/src/CAN/can_main.c b/Embedded/src/CAN/can_main.c +--- a/Embedded/src/CAN/can_main.c 2009-11-30 10:44:39.044269751 +0100 ++++ b/Embedded/src/CAN/can_main.c 2009-11-30 10:54:41.434355642 +0100 +@@ -213,8 +213,8 @@ + spin_lock_init(&(g_can_os[can_num].int_spinlock)); + spin_lock_init(&(g_can_os[can_num].open_spinlock)); + +- dev->dev.driver_data = (void *) &(g_can_os[can_num]); +- if (!dev->dev.driver_data) ++ dev_set_drvdata(&dev->dev, (void *) &(g_can_os[can_num])); ++ if (!dev_get_drvdata(&dev->dev)) + { + printk("Couldn't create CAN device %d. Exiting.\n", + dev->device); +@@ -236,7 +236,7 @@ + *****************************************************************************/ + void can_pci_remove(struct pci_dev *dev) + { +- can_os_t *can_os = dev->dev.driver_data; ++ can_os_t *can_os = dev_get_drvdata(&dev->dev); + + iounmap(can_os->pci_remap); + icp_can_destroy(can_os->can); +@@ -250,7 +250,7 @@ + { + unsigned int i; + unsigned int int_status; +- can_os_t *can_os = dev->dev.driver_data; ++ can_os_t *can_os = dev_get_drvdata(&dev->dev); + int err; + + /* Indicate that we are suspending */ +@@ -321,7 +321,7 @@ + int can_pci_resume(struct pci_dev *dev) + { + unsigned int i; +- can_os_t *can_os = dev->dev.driver_data; ++ can_os_t *can_os = dev_get_drvdata(&dev->dev); + + /* Restore PCI CFG space */ + pci_restore_state(dev); diff --git a/package/ep80579-drivers/patches/300-wdt_compile_fix.patch b/package/ep80579-drivers/patches/300-wdt_compile_fix.patch new file mode 100644 index 000000000..59242b80b --- /dev/null +++ b/package/ep80579-drivers/patches/300-wdt_compile_fix.patch @@ -0,0 +1,59 @@ +--- a/Embedded/src/WDT/iwdt.c ++++ b/Embedded/src/WDT/iwdt.c +@@ -180,19 +180,19 @@ MODULE_PARM_DESC(wdt_scale, "Intel WDT s + module_param(wdt_intr_type, byte, WDT_INT_TYPE_IRQ); + MODULE_PARM_DESC(wdt_intr_type, "Intel WDT interrupt type (default SERIRQ)."); + +-module_param(wdt_margin1, uint, TIMER_MARGIN); ++module_param(wdt_margin1, uint, 0); + MODULE_PARM_DESC(wdt_margin1, "First stage Intel WDT timeout in steps of 1 ms by default."); + +-module_param(wdt_margin2, uint, TIMER_MARGIN); ++module_param(wdt_margin2, uint, 0); + MODULE_PARM_DESC(wdt_margin2, "Second stage Intel WDT timeout in steps of 1 ms by default."); + + module_param(nowayout, int, 0); + MODULE_PARM_DESC(nowayout, "Intel WDT can't be stopped once started (default=0)"); + +-module_param(wdt_index_port, int, 0x4E); ++module_param(wdt_index_port, int, 0); + MODULE_PARM_DESC(wdt_index_port, "WDT Index Port (default 0x4e)"); + +-module_param(wdt_data_port, int, 0x4E); ++module_param(wdt_data_port, int, 0); + MODULE_PARM_DESC(wdt_data_port, "WDT Data Port (default 0x4f)"); + + static int wdt_get_iobase(struct pci_dev *dev, u16 *iobase, int *irq); +@@ -218,7 +218,7 @@ static ssize_t wdt_write(struct file *fi + size_t count, loff_t * pos); + static int wdt_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); +-static irqreturn_t wdt_isr(int irq, void *dev_id, struct pt_regs *regs); ++static irqreturn_t wdt_isr(int irq, void *dev_id); + static void __exit wdt_cleanup(void); + static int __init wdt_init(void); + static int __init wdt_init_one(struct pci_dev *dev, +@@ -255,7 +255,7 @@ static struct pci_driver wdt_driver = { + name: "iwdt", + id_table: lpc_pci_tbl, + probe: wdt_init_one, +- remove: __devexit(wdt_remove_one), ++ remove: __devexit_p(wdt_remove_one), + suspend: wdt_pci_suspend, + resume: wdt_pci_resume, + }; +@@ -1393,12 +1393,12 @@ static int wdt_ioctl(struct inode *inode + + /* + * Function Name: wdt_isr() +- * Parameter: int irq - irq number, void *dev_id, struct pt_regs *regs ++ * Parameter: int irq - irq number, void *dev_id + * Return Value:: IRQ_NONE - if the interrupt is not for wdt. + * IRQ_HANDLED - if it is for wdt. + * Description: This is the interrupt service routine of the WDT. + */ +-static irqreturn_t wdt_isr(int irq, void *dev_id, struct pt_regs *regs) ++static irqreturn_t wdt_isr(int irq, void *dev_id) + { + u8 val; + diff --git a/package/ep80579-drivers/patches/400-edma_fix_irq_request_warning.patch b/package/ep80579-drivers/patches/400-edma_fix_irq_request_warning.patch new file mode 100644 index 000000000..d858aff1f --- /dev/null +++ b/package/ep80579-drivers/patches/400-edma_fix_irq_request_warning.patch @@ -0,0 +1,22 @@ +--- a/Embedded/src/EDMA/dma_linux.c ++++ b/Embedded/src/EDMA/dma_linux.c +@@ -149,8 +149,7 @@ int32_t edma_suspend (struct pci_dev *de + int32_t edma_resume(struct pci_dev *dev); + int32_t initialize_edma_device(struct edma_device *device); + +-static irqreturn_t edma_irq_handler(int32_t irq, void * dev_id, +- struct pt_regs * regs); ++static irqreturn_t edma_irq_handler(int32_t irq, void * dev_id); + + /* Prototypes - Misc. */ + +@@ -429,8 +428,7 @@ int32_t edma_release(struct inode * inod + * Return Values: HANDLED = 1, NOT_HANDLED = 0 + *****************************************************************************/ + +-static irqreturn_t edma_irq_handler(int32_t irq, void * dev_id, +- struct pt_regs * regs) ++static irqreturn_t edma_irq_handler(int32_t irq, void * dev_id) + { + + uint32_t clear_bits; diff --git a/package/ep80579-drivers/patches/500-1588_fix_irq_request_warning.patch b/package/ep80579-drivers/patches/500-1588_fix_irq_request_warning.patch new file mode 100644 index 000000000..f3f9acb1e --- /dev/null +++ b/package/ep80579-drivers/patches/500-1588_fix_irq_request_warning.patch @@ -0,0 +1,22 @@ +--- a/Embedded/src/1588/1588.c ++++ b/Embedded/src/1588/1588.c +@@ -631,7 +631,7 @@ int restore_interrupts(void) + IRQ_NONE => this device did not interrupt + + ******************************************************************************/ +-irqreturn_t timesync_isr(int irq, void *dev_id, struct pt_regs *regs) ++irqreturn_t timesync_isr(int irq, void *dev_id) + { + if ( !ixTimeSyncAccEventAmmsFlagGet() && !ixTimeSyncAccEventAsmsFlagGet()&& + !ixTimeSyncAccEventAtmFlagGet() && !ixTimeSyncAccEventPpsmFlagGet()&& +--- a/Embedded/src/1588/1588.h ++++ b/Embedded/src/1588/1588.h +@@ -128,7 +128,7 @@ int pci_suspend(struct pci_dev *dev, pm_ + int pci_resume(struct pci_dev *dev); + int pci_probe(struct pci_dev *dev, const struct pci_device_id *id); + void pci_remove(struct pci_dev *dev); +-irqreturn_t timesync_isr(int irq, void *dev_id, struct pt_regs *regs); ++irqreturn_t timesync_isr(int irq, void *dev_id); + + // private functions + int save_reg_state(void); diff --git a/package/ep80579-drivers/patches/600-2.6.27_includes.patch b/package/ep80579-drivers/patches/600-2.6.27_includes.patch new file mode 100644 index 000000000..c11275ece --- /dev/null +++ b/package/ep80579-drivers/patches/600-2.6.27_includes.patch @@ -0,0 +1,22 @@ +--- a/Embedded/src/CAN/can_main.h ++++ b/Embedded/src/CAN/can_main.h +@@ -65,7 +65,7 @@ + + #include + #include +-#include ++#include + #include + #include + #include +--- a/Embedded/src/EDMA/dma_linux.c ++++ b/Embedded/src/EDMA/dma_linux.c +@@ -87,7 +87,7 @@ + #include /* O_ACCMODE */ + #include /* cli, *_flags */ + #include /* copy_to_user */ +-#include ++#include + #include /* inb(), outb() */ + #include + #include /* request_region */ diff --git a/package/ep80579-drivers/patches/601-2.6.32_includes.patch b/package/ep80579-drivers/patches/601-2.6.32_includes.patch new file mode 100644 index 000000000..680bbf11b --- /dev/null +++ b/package/ep80579-drivers/patches/601-2.6.32_includes.patch @@ -0,0 +1,33 @@ +diff -Nur a/Embedded/src/1588/1588.c b/Embedded/src/1588/1588.c +--- a/Embedded/src/1588/1588.c 2009-11-10 14:20:46.563322192 +0100 ++++ b/Embedded/src/1588/1588.c 2009-11-30 10:44:22.144270452 +0100 +@@ -72,6 +72,7 @@ + * + ****************************************************************************/ + ++#include + #include "1588.h" + + MODULE_AUTHOR("Intel(R) Corporation"); +diff -Nur a/Embedded/src/CAN/can_main.c b/Embedded/src/CAN/can_main.c +--- a/Embedded/src/CAN/can_main.c 2009-11-10 14:20:46.563322192 +0100 ++++ b/Embedded/src/CAN/can_main.c 2009-11-30 10:44:39.044269751 +0100 +@@ -68,6 +68,7 @@ + * + **************************************************************************/ + ++#include + #include "can_main.h" + #include "can_ioctl.h" + +diff -Nur a/Embedded/src/WDT/iwdt.c b/Embedded/src/WDT/iwdt.c +--- a/Embedded/src/WDT/iwdt.c 2009-11-10 14:20:46.563322192 +0100 ++++ b/Embedded/src/WDT/iwdt.c 2009-11-30 10:44:54.024262744 +0100 +@@ -137,6 +137,7 @@ + #include + #include + #include ++#include + #include "iwdt.h" + + MODULE_AUTHOR("Intel(R) Corporation"); diff --git a/package/ep80579-drivers/patches/700-iegbe_kcompat_2.6.30.patch b/package/ep80579-drivers/patches/700-iegbe_kcompat_2.6.30.patch new file mode 100644 index 000000000..ca8c1bb9e --- /dev/null +++ b/package/ep80579-drivers/patches/700-iegbe_kcompat_2.6.30.patch @@ -0,0 +1,31 @@ +--- a/Embedded/src/GbE/kcompat.h ++++ b/Embedded/src/GbE/kcompat.h +@@ -46,12 +46,6 @@ GPL LICENSE SUMMARY + #include + #include + +-#ifndef IRQ_HANDLED +-#define irqreturn_t void +-#define IRQ_HANDLED +-#define IRQ_NONE +-#endif +- + #ifndef SET_NETDEV_DEV + #define SET_NETDEV_DEV(net, pdev) + #endif +@@ -748,6 +742,15 @@ extern void dump_stack(void); + + #endif /* 2.4.24 */ + ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) ) ++#ifndef IRQ_HANDLED ++#define irqreturn_t void ++#define IRQ_HANDLED ++#define IRQ_NONE ++#endif ++#endif /* < 2.6.30 */ ++ + #endif /* _KCOMPAT_H_ */ + + diff --git a/package/ep80579-drivers/patches/701-iegbe_poll_dev.patch b/package/ep80579-drivers/patches/701-iegbe_poll_dev.patch new file mode 100644 index 000000000..63a132685 --- /dev/null +++ b/package/ep80579-drivers/patches/701-iegbe_poll_dev.patch @@ -0,0 +1,11 @@ +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -3534,7 +3534,7 @@ static int iegbe_clean(struct napi_struc + int tx_cleaned = 0, work_done = 0; + + /* Must NOT use netdev_priv macro here. */ +- adapter = poll_dev->priv; ++ adapter = netdev_priv(poll_dev); + + /* iegbe_clean is called per-cpu. This lock protects + * tx_ring[0] from being cleaned by multiple cpus diff --git a/package/hostapd/Makefile b/package/hostapd/Makefile index f4142f76d..0ccba9ad9 100644 --- a/package/hostapd/Makefile +++ b/package/hostapd/Makefile @@ -25,6 +25,7 @@ PKG_BUILD_DEPENDS:= \ PKG_CONFIG_DEPENDS:= \ CONFIG_WPA_SUPPLICANT_NO_TIMESTAMP_CHECK \ CONFIG_PACKAGE_kmod-ath9k \ + CONFIG_PACKAGE_kmod-rt2800-lib \ CONFIG_PACKAGE_kmod-mac80211 \ CONFIG_PACKAGE_kmod-madwifi \ CONFIG_PACKAGE_hostapd \ @@ -50,11 +51,19 @@ PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSI include $(INCLUDE_DIR)/package.mk +ifneq ($(CONFIG_PACKAGE_kmod-rt2800-lib),) + HOSTAPD_IEEE80211N:=y +endif + +ifneq ($(CONFIG_PACKAGE_kmod-ath9k),) + HOSTAPD_IEEE80211N:=y +endif + DRIVER_MAKEOPTS= \ CONFIG_DRIVER_NL80211=$(CONFIG_PACKAGE_kmod-mac80211) \ CONFIG_DRIVER_MADWIFI=$(CONFIG_PACKAGE_kmod-madwifi) \ CONFIG_DRIVER_HOSTAP=$(CONFIG_PACKAGE_kmod-hostap) \ - CONFIG_IEEE80211N=$(CONFIG_PACKAGE_kmod-ath9k) \ + CONFIG_IEEE80211N=$(HOSTAPD_IEEE80211N) \ CONFIG_IEEE80211W=$(CONFIG_PACKAGE_kmod-ath9k) ifneq ($(LOCAL_TYPE),hostapd) diff --git a/package/ifx-tapi/Config.in b/package/ifx-tapi/Config.in new file mode 100644 index 000000000..56defb3dd --- /dev/null +++ b/package/ifx-tapi/Config.in @@ -0,0 +1,71 @@ +config VOICE_CPE_TAPI_FAX + bool "fax relay and modem support" + default n + help + Option to enable fax/modem support in TAPI. + Note: Newer platforms as AR9 and VR9 support a T.38 fax relay stack + in FW while older platforms like Danube or VINETIC-CPE require a + separate SW stack executed as an application. + +config VOICE_CPE_TAPI_CID + bool "CID support" + default y + help + Option to enable Caller ID support. + +config VOICE_CPE_TAPI_LT_GR909 + bool "Linetesting GR-909 support" + default y + help + Option to enable linetesting GR-909. + +config VOICE_CPE_TAPI_DECT + bool "DECT encoding for COSIC modem" + default n + help + Option to enable DECT encoding for COSIC modem. + +config VOICE_CPE_TAPI_KPI + bool "KPI (Kernel Packet Interface)" + default y + help + Option to enable the generic kernel level packet interface + which allows accelerated packet transfer for various purposes. + The most important example is the QOS option, which allows + to redirect RTP packets directly into the IP stack. + Other options relying on KPI are DECT and HDLC. + +config VOICE_CPE_TAPI_QOS + bool "QOS for accelerated RTP packet handling" + default y + help + Option to enable an accelerated RTP packet transfer inside + the LINUX kernel space. This option requires the KPI2UDP + packet, which actually provides the OS specific hooks in + the IP stack. + +config VOICE_CPE_TAPI_STATISTICS + bool "TAPI statistics via /proc fs" + default y + help + Option to enable /proc fs statistics for packet counts etc. + +config VOICE_CPE_TAPI_METERING + bool "Metering (TTX) support" + default n + help + Option to enable metering (TTX) support. + +config VOICE_CPE_TAPI_HDLC + bool "PCM HDLC support, evaluation" + default n + help + Option to enable PCM HDLC framing inside the firmware, e.g. for + ISDN D-Channel access. + +config VOICE_CPE_TAPI_TRACES + bool "enable driver traces" + default y + help + enable driver traces with different trace levels to be + configured dynamically from the application or during insmod diff --git a/package/ifx-tapi/Makefile b/package/ifx-tapi/Makefile new file mode 100644 index 000000000..fe91ad015 --- /dev/null +++ b/package/ifx-tapi/Makefile @@ -0,0 +1,70 @@ +# +# Copyright (C) 2008 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=drv_tapi +PKG_VERSION:=3.11.0 +PKG_RELEASE:=1 + +PKG_SOURCE:=drv_tapi-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources +PKG_MD5SUM:=1ffee83ce69f55915468c309d8ae2138 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/ifx-tapi + SUBMENU:=Voice over IP + TITLE:=Lantiq TAPI subsystem + URL:=http://www.lantiq.com/ + MAINTAINER:=Lantiq + DEPENDS:=+kmod-ifxos @BROKEN + FILES:=$(PKG_BUILD_DIR)/src/drv_tapi.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoLoad,20,drv_tapi) +endef + +define KernelPackage/ifx-tapi/description + Voice Subsystem Telephony API High Level Driver +endef + +define KernelPackage/ifx-tapi/config + if PACKAGE_kmod-ifx-tapi + source "$(SOURCE)/Config.in" + endif +endef + +CONFIGURE_ARGS += \ + ARCH=$(LINUX_KARCH) \ + --enable-linux-26 \ + --enable-kernelbuild="$(LINUX_DIR)" \ + --enable-kernelincl="$(LINUX_DIR)/include" \ + --with-ifxos-incl=$(STAGING_DIR)/usr/include/ifxos \ + $(call autoconf_bool,CONFIG_IFX_DRV_TAPI_EVENT_LOGGER,el-debug) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_FAX,fax t38) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_CID,cid) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_DECT,dect) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_KPI,kpi) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_QOS,qos) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_LT_GR909,lt) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_STATISTICS,statistics) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_METERING,metering) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_HDLC,hdlc) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_TRACES,trace) + +define Build/Configure + (cd $(PKG_BUILD_DIR); aclocal && autoconf && automake) + $(call Build/Configure/Default) +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/drv_tapi + $(CP) --dereference $(PKG_BUILD_DIR)/include/* $(1)/usr/include/drv_tapi + (cd $(1)/usr/include/drv_tapi && ln -s . include && ln -s ../ifxos/ifx_types.h .) +endef + +$(eval $(call KernelPackage,ifx-tapi)) diff --git a/package/ifx-tapi/patches/001-portability.patch b/package/ifx-tapi/patches/001-portability.patch new file mode 100644 index 000000000..807a64b12 --- /dev/null +++ b/package/ifx-tapi/patches/001-portability.patch @@ -0,0 +1,26 @@ +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -149,7 +149,7 @@ if KERNEL_2_6 + drv_tapi_OBJS = "$(subst .c,.o, $(drv_tapi_SOURCES))" + + drv_tapi.ko: $(drv_tapi_SOURCES) $(EXTRA_DIST) +- @echo -e "Making Linux 2.6.x kernel object" ++ @echo "Making Linux 2.6.x kernel object" + @for f in $(drv_tapi_SOURCES) ; do \ + if test ! -e $(PWD)/$$f; then \ + echo " LN $$f" ; \ +@@ -157,10 +157,10 @@ drv_tapi.ko: $(drv_tapi_SOURCES) $(EXTRA + ln -s @abs_srcdir@/$$f $(PWD)/$$f; \ + fi; \ + done; +- @echo -e "# drv_tapi: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild +- @echo -e "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild +- @echo -e "$(subst .ko,,$@)-y := $(drv_tapi_OBJS)" >> $(PWD)/Kbuild +- @echo -e "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(CFLAGS) $(drv_tapi_CFLAGS) $(INCLUDES)" >> $(PWD)/Kbuild ++ @echo "# drv_tapi: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild ++ @echo "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild ++ @echo "$(subst .ko,,$@)-y := $(drv_tapi_OBJS)" >> $(PWD)/Kbuild ++ @echo "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(CFLAGS) $(drv_tapi_CFLAGS) $(INCLUDES)" >> $(PWD)/Kbuild + $(MAKE) ARCH=@KERNEL_ARCH@ -C @KERNEL_BUILD_PATH@ O=@KERNEL_BUILD_PATH@ M=$(PWD) modules + + clean-generic: diff --git a/package/ifx-tapi/patches/100-ifxmips.patch b/package/ifx-tapi/patches/100-ifxmips.patch new file mode 100644 index 000000000..bce831c08 --- /dev/null +++ b/package/ifx-tapi/patches/100-ifxmips.patch @@ -0,0 +1,108 @@ +--- a/src/drv_tapi_linux.c ++++ b/src/drv_tapi_linux.c +@@ -544,7 +544,7 @@ static ssize_t ifx_tapi_write (struct fi + IFX_uint8_t *pData; + IFX_size_t buf_size; + #endif /* TAPI_PACKET */ +- IFX_ssize_t size = 0; ++ ssize_t size = 0; + + #ifdef TAPI_PACKET + if (pTapiDev->bInitialized == IFX_FALSE) +@@ -3600,7 +3600,11 @@ IFX_void_t TAPI_OS_ThreadKill(IFXOS_Thre + flag and released after the down() call. */ + lock_kernel(); + mb(); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) + kill_proc(pThrCntrl->tid, SIGKILL, 1); ++#else ++ kill_pid(find_vpid(pThrCntrl->tid), SIGKILL, 1); ++#endif + /* release the big kernel lock */ + unlock_kernel(); + wait_for_completion (&pThrCntrl->thrCompletion); +--- a/src/drv_tapi_osmap.h ++++ b/src/drv_tapi_osmap.h +@@ -17,39 +17,6 @@ + */ + + #include "ifx_types.h" /* ifx type definitions */ +- +-#ifndef HAVE_IFX_ULONG_T +- #warning please update your ifx_types.h, using local definition of IFX_ulong_t +- /* unsigned long type - valid for 32bit systems only */ +- typedef unsigned long IFX_ulong_t; +- #define HAVE_IFX_ULONG_T +-#endif /* HAVE_IFX_ULONG_T */ +- +-#ifndef HAVE_IFX_LONG_T +- #warning please update your ifx_types.h, using local definition of IFX_long_t +- /* long type - valid for 32bit systems only */ +- typedef long IFX_long_t; +- #define HAVE_IFX_LONG_T +-#endif /* HAVE_IFX_LONG_T */ +- +-#ifndef HAVE_IFX_INTPTR_T +- #warning please update your ifx_types.h, using local definition of IFX_intptr_t +- typedef IFX_long_t IFX_intptr_t; +- #define HAVE_IFX_INTPTR_T +-#endif /* HAVE_IFX_INTPTR_T */ +- +-#ifndef HAVE_IFX_SIZE_T +- #warning please update your ifx_types.h, using local definition of IFX_size_t +- typedef IFX_ulong_t IFX_size_t; +- #define HAVE_IFX_SIZE_T +-#endif /* HAVE_IFX_SIZE_T */ +- +-#ifndef HAVE_IFX_SSIZE_T +- #warning please update your ifx_types.h, using local definition of IFX_ssize_t +- typedef IFX_long_t IFX_ssize_t; +- #define HAVE_IFX_SSIZE_T +-#endif /* HAVE_IFX_SSIZE_T */ +- + #include "ifxos_interrupt.h" + #include "ifxos_memory_alloc.h" + #include "ifxos_copy_user_space.h" +--- a/include/drv_tapi_ll_interface.h ++++ b/include/drv_tapi_ll_interface.h +@@ -40,13 +40,6 @@ + #include "ifxos_select.h" + #endif /* TAPI_PACKET */ + +-#ifndef HAVE_IFX_ULONG_T +- #warning please update your ifx_types.h, using local definition of IFX_ulong_t +- /* unsigned long type - valid for 32bit systems only */ +- typedef unsigned long IFX_ulong_t; +- #define HAVE_IFX_ULONG_T +-#endif /* HAVE_IFX_ULONG_T */ +- + /* ============================= */ + /* Local Macros Definitions */ + /* ============================= */ +--- a/src/lib/lib_bufferpool/lib_bufferpool.c ++++ b/src/lib/lib_bufferpool/lib_bufferpool.c +@@ -80,24 +80,6 @@ + #include + #endif /* LINUX */ + +- +-/* ============================= */ +-/* Extra type definitions */ +-/* ============================= */ +-#ifndef HAVE_IFX_ULONG_T +- #warning please update your ifx_types.h, using local definition of IFX_ulong_t +- /* unsigned long type - valid for 32bit systems only */ +- typedef unsigned long IFX_ulong_t; +- #define HAVE_IFX_ULONG_T +-#endif /* HAVE_IFX_ULONG_T */ +- +-#ifndef HAVE_IFX_UINTPTR_T +- #warning please update your ifx_types.h, using local definition of IFX_uintptr_t +- typedef IFX_ulong_t IFX_uintptr_t; +- #define HAVE_IFX_UINTPTR_T +-#endif /* HAVE_IFX_UINTPTR_T */ +- +- + /* ============================= */ + /* Local Macros & Definitions */ + /* ============================= */ diff --git a/package/ifx-tapidemo/Config.in b/package/ifx-tapidemo/Config.in new file mode 100644 index 000000000..32594ba9c --- /dev/null +++ b/package/ifx-tapidemo/Config.in @@ -0,0 +1,36 @@ +choice + prompt "board selection" + default VOICE_CPE_TAPIDEMO_BOARD_EASY50712_V3 if TARGET_ifxmips_platform_danube + default VOICE_CPE_TAPIDEMO_BOARD_EASY508xx if TARGET_ifxmips_platform_ar9 + default VOICE_CPE_TAPIDEMO_BOARD_EASY80910 if TARGET_ifxmips_platform_vr9 + default VOICE_CPE_TAPIDEMO_BOARD_EASY50812 + help + Select the target platform. + + config VOICE_CPE_TAPIDEMO_BOARD_EASY50712 + bool "Danube reference board" + + config VOICE_CPE_TAPIDEMO_BOARD_EASY50712_V3 + bool "Danube reference board V3" + + config VOICE_CPE_TAPIDEMO_BOARD_EASY508xx + bool "AR9/GR9 reference board" + + config VOICE_CPE_TAPIDEMO_BOARD_EASY80910 + bool "VR9 reference board" +endchoice + +config VOICE_CPE_TAPIDEMO_QOS + bool "enable QOS support" + default n + help + Option to enable the KPI2UDP RTP packet acceleration path + (highly recommended for VoIP). + +config VOICE_CPE_TAPIDEMO_FAX_T.38_FW + bool "enable T.38 fax relay" + depends on (TARGET_ifxmips_platform_ar9 || TARGET_ifxmips_platform_vr9) + default n + help + enable T.38 fax relay demo. + diff --git a/package/ifx-tapidemo/Makefile b/package/ifx-tapidemo/Makefile new file mode 100644 index 000000000..217d4641a --- /dev/null +++ b/package/ifx-tapidemo/Makefile @@ -0,0 +1,70 @@ +# +# Copyright (C) 2008 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +# $Id: $ + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=tapidemo +PKG_VERSION:=5.0.1.27 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources +PKG_MD5SUM:=a38a7bf3242aad607f50f57b988bc87c + +include $(INCLUDE_DIR)/package.mk + +define Package/ifx-tapidemo + SECTION:=utils + CATEGORY:=Utilities + TITLE:=TAPIdemo application for Lantiq boards + URL:=http://www.lantiq.com/ + MAINTAINER:=Lantiq + DEPENDS:=+kmod-ifx-tapi +kmod-ifx-vmmc @BROKEN +endef + +define Package/ifx-tapidemo/description + Voice Access mini-PBX Demo Application +endef + +define Package/ifx-tapidemo/config + if PACKAGE_ifx-tapidemo + source "$(SOURCE)/Config.in" + endif +endef + +CONFIGURE_ARGS += \ + ARCH=$(LINUX_KARCH) \ + --enable-linux-26 \ + --enable-kernelincl="$(LINUX_DIR)/include" \ + --with-drvincl="$(STAGING_DIR)/usr/include" \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_QOS,qos) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPIDEMO_FAX_T,fax-t38) \ + --enable-trace \ + --enable-fs + +ifeq ($(CONFIG_VOICE_CPE_TAPIDEMO_BOARD_EASY50712),y) + CONFIGURE_ARGS += --enable-boardname=EASY50712 +endif +ifeq ($(CONFIG_VOICE_CPE_TAPIDEMO_BOARD_EASY50712_V3),y) + CONFIGURE_ARGS += --enable-boardname=EASY50712_V3 +endif +ifeq ($(CONFIG_VOICE_CPE_TAPIDEMO_BOARD_EASY508xx),y) + CONFIGURE_ARGS += --enable-boardname=EASY508XX +endif +ifeq ($(CONFIG_VOICE_CPE_TAPIDEMO_BOARD_EASY80910),y) + CONFIGURE_ARGS += --enable-boardname=EASY508XX +endif + +define Package/ifx-tapidemo/install + $(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/init.d/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/tapidemo $(1)/usr/sbin + $(INSTALL_BIN) ./files/bringup_tapidemo $(1)/etc/init.d/tapidemo +endef + +$(eval $(call BuildPackage,ifx-tapidemo)) diff --git a/package/ifx-tapidemo/files/bringup_tapidemo b/package/ifx-tapidemo/files/bringup_tapidemo new file mode 100644 index 000000000..6eb13d25f --- /dev/null +++ b/package/ifx-tapidemo/files/bringup_tapidemo @@ -0,0 +1,89 @@ +#!/bin/sh /etc/rc.common +# (C) 2008 openwrt.org + +START=96 + +[ ! -f /dev/vmmc10 ] && { + mknod /dev/vmmc10 c 122 10 + mknod /dev/vmmc11 c 122 11 + mknod /dev/vmmc12 c 122 12 + mknod /dev/vmmc13 c 122 13 + mknod /dev/vmmc14 c 122 14 + mknod /dev/vmmc15 c 122 15 + mknod /dev/vmmc16 c 122 16 + mknod /dev/vmmc17 c 122 17 + mknod /dev/vmmc18 c 122 18 +} + +TD_EXTRA_FLAGS_FXO= +TD_EXTRA_FLAGS_KPI2UDP= +TD_DOWNLOAD_PATH=/lib/firmware/ +DEV_NODE_TERIDIAN=ter10 + + # Show help +help() +{ + echo "Usage:" + echo " - $0 WAN-IF-NAME - start TAPIDEMO without FXO support" + echo " - $0 WAN-IF-NAME fxo - start TAPIDEMO with FXO support." + echo " - $0 stop - stop TAPIDEMO" +} + +# Check if device node for Teridian exists +checkFxoSupport() +{ + if [ ! -e /dev/$DEV_NODE_TERIDIAN ];then + echo "FXO support is disabled. Can not find required driver's device node." + else + TD_EXTRA_FLAGS_FXO="-x" + fi +} + +# Check if module drv_kpi2udp is loaded +checkKpi2UdpSupport() +{ + tmp=`cat /proc/modules | grep 'drv_kpi2udp '` + if [ "$tmp" != "" ]; then + TD_EXTRA_FLAGS_KPI2UDP="-q" + fi +} + +start() +{ + TD_WANIF=$1 + + TD_WANIF_IP=`ifconfig $TD_WANIF | grep 'inet addr:' | cut -f2 -d: | cut -f1 -d' '` + if [ "$TD_WANIF_IP" = "" ]; then + echo "Error, getting IP address for network device $TD_WANIF failed." + exit 1 + fi + + if [ "$2" = "" ];then + # FXO support is disabled. + continue + elif [ "$2" = "fxo" ];then + checkFxoSupport + else + echo "Error, unknown second parameter." + help + exit 1 + fi + + checkKpi2UdpSupport + + if [ -r /etc/rc.conf ]; then + . /etc/rc.conf + fi + + TD_DEBUG_LEVEL=$tapiDebugLevel + if [ "$TD_DEBUG_LEVEL" = "" ]; then + TD_DEBUG_LEVEL=3 + fi + + /usr/sbin/tapidemo -d $TD_DEBUG_LEVEL $TD_EXTRA_FLAGS_FXO $TD_EXTRA_FLAGS_KPI2UDP -i $TD_WANIF_IP -l $TD_DOWNLOAD_PATH & +} + +stop() +{ + killall tapidemo > /dev/null 2> /dev/null +} diff --git a/package/ifx-tapidemo/patches/100-ifxmips.patch b/package/ifx-tapidemo/patches/100-ifxmips.patch new file mode 100644 index 000000000..43fa988ef --- /dev/null +++ b/package/ifx-tapidemo/patches/100-ifxmips.patch @@ -0,0 +1,78 @@ +--- a/src/board_easy50712.c Mon Mar 15 14:47:53 2010 +0300 ++++ b/src/board_easy50712.c Tue Mar 16 17:25:55 2010 +0300 +@@ -40,7 +40,9 @@ + #endif /* DUSLIC_FXO */ + #endif /* EASY50712_V3 */ + +-#include "asm/ifx/ifx_gpio.h" ++#ifdef FXO ++# include "asm/ifx/ifx_gpio.h" ++#endif + + /* ============================= */ + /* Defines */ +@@ -896,6 +898,7 @@ + /* Global function definition */ + /* ============================= */ + ++#ifdef FXO + /** + Set direction of GPIO pin to out which is used for set/clear reset. + +@@ -944,7 +947,7 @@ + return IFX_SUCCESS; + } + break; +- ++ + case GPIO_DUSLIC_EASY50510: + { + TRACE(TAPIDEMO, DBG_LEVEL_LOW, +@@ -982,8 +985,9 @@ + + return IFX_SUCCESS; + }; ++#endif + +- ++#ifdef FXO + /* + Set/Clear reset of device by using GPIO port. + +@@ -1086,7 +1090,9 @@ + /* usleep(100000); karol - workaround, */ + return ret; + } ++#endif + ++#ifdef EASY50510 + /** + Set PCM master mode. + +@@ -1178,15 +1184,16 @@ + + return ret; + } ++#endif + + /** + Register board. + + \param pBoard - pointer to board +- ++ + \return IFX_SUCCESS if successful, otherwise IFX_ERROR. + +- \remarks ++ \remarks + */ + IFX_return_t BOARD_Easy50712_Register(BOARD_t* pBoard) + { +@@ -1204,7 +1211,3 @@ + pBoard->RemoveBoard = BOARD_Easy50712_RemoveBoard; + return IFX_SUCCESS; + } +- +- +- +- diff --git a/package/ifx-tapidemo/patches/110-no_echo_cancelation.patch b/package/ifx-tapidemo/patches/110-no_echo_cancelation.patch new file mode 100644 index 000000000..d424d4847 --- /dev/null +++ b/package/ifx-tapidemo/patches/110-no_echo_cancelation.patch @@ -0,0 +1,12 @@ +Index: tapidemo-5.0.1.27/src/device_vmmc.c +=================================================================== +--- tapidemo-5.0.1.27.orig/src/device_vmmc.c 2009-11-09 15:40:31.000000000 +0100 ++++ tapidemo-5.0.1.27/src/device_vmmc.c 2010-03-30 21:32:51.000000000 +0200 +@@ -240,7 +240,6 @@ + TRACE(TAPIDEMO, DBG_LEVEL_HIGH, + ("Error, BBD file %s is not found.\n(File: %s, line: %d)\n", + pCpuDevice->pszBBD_CRAM_File, __FILE__, __LINE__)); +- return IFX_ERROR; + } + + #endif /* USE_FILESYSTEM */ diff --git a/package/ifx-vmmc/Config.in b/package/ifx-vmmc/Config.in new file mode 100644 index 000000000..bd3c032d3 --- /dev/null +++ b/package/ifx-vmmc/Config.in @@ -0,0 +1,49 @@ +choice + prompt "device selection" + default VOICE_CPE_VMMC_WITH_DEVICE_DANUBE_extract + help + Select the target device. + + config VOICE_CPE_VMMC_WITH_DEVICE_DANUBE_extract + bool "Danube, Twinpass, Vinax - extract binaries" + + config VOICE_CPE_VMMC_WITH_DEVICE_DANUBE + bool "Danube, Twinpass, Vinax" + + config VOICE_CPE_VMMC_WITH_DEVICE_AR9 + bool "AR9 family" + + config VOICE_CPE_VMMC_WITH_DEVICE_VR9 + bool "VR9 family" + +endchoice + +config VOICE_CPE_VMMC_PMC + depends on (VOICE_CPE_VMMC_WITH_DEVICE_AR9 || VOICE_CPE_VMMC_WITH_DEVICE_VR9) + bool "Power Management Control support" + default n + help + Option to enable Power Management Control on AR9, VR9. Not supported for Danube. + +config VOICE_CPE_VMMC_DISABLE_DECT_NIBBLE_SWAP + bool "Disable DECT nibble swap" + default n + help + Option to disable DECT nibble swap for COSIC modem (for backward compatibility only). + +config VOICE_CPE_VMMC_EVENT_LOGGER + depends on BROKEN + bool "Event logger support" + default n + help + Option to enable details traces between drv_vmmc and the voice FW + - for debugging only + - requires package ifx-evtlog + +config VOICE_CPE_VMMC_MPS_HISTORY_SIZE + int "MPS history buffer in words (0<=size<=512)" + default "128" + help + MPS history buffer (default=128 words, maximum=512 words, 0=disable) + To opimize the memory footprint in RAM, you might want to set the + buffer size to 0. diff --git a/package/ifx-vmmc/Makefile b/package/ifx-vmmc/Makefile new file mode 100644 index 000000000..945d5ba7e --- /dev/null +++ b/package/ifx-vmmc/Makefile @@ -0,0 +1,158 @@ +# +# Copyright (C) 2008 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=drv_vmmc +PKG_VERSION:=1.7.0 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_MD5SUM:=3f1b44e79408a3320aa9f8b21a260fd0 +PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/ifx-vmmc + SUBMENU:=Voice over IP + TITLE:=TAPI LL driver for Voice Macro + URL:=http://www.lantiq.com/ + MAINTAINER:=Lantiq + DEPENDS:=+kmod-ifx-tapi @BROKEN + FILES:=$(PKG_BUILD_DIR)/src/drv_vmmc.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoLoad,25,drv_vmmc) +endef + +define KernelPackage/ifx-vmmc/description + Voice Subsystem Low Level Driver for Danube, AR9, VR9 device families +endef + +define KernelPackage/ifx-vmmc/config + if PACKAGE_kmod-ifx-vmmc + source "$(SOURCE)/Config.in" + endif +endef + +CONFIGURE_ARGS += \ + ARCH=$(LINUX_KARCH) \ + --enable-linux-26 \ + --enable-kernelbuild="$(LINUX_DIR)" \ + --enable-kernelincl="$(LINUX_DIR)/include" \ + --enable-tapiincl="$(STAGING_DIR)/usr/include/drv_tapi" \ + --with-ifxos-incl=$(STAGING_DIR)/usr/include/ifxos \ + $(call autoconf_bool,CONFIG_VOICE_CPE_VMMC_EVENT_LOGGER,el-debug) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_VMMC_PMC,pmc) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_VMMC_DISABLE_DECT_NIBBLE_SWAP,dect-nibble-swap) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_FAX,fax t38) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_CID,cid) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_DECT,dect) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_KPI,kpi) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_LT_GR909,lt calibration) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_HDLC,hdlc) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_TRACES,trace) + +ifneq ($(CONFIG_VOICE_CPE_VMMC_MPS_HISTORY_SIZE),128) + CONFIGURE_ARGS += --enable-history-buf=$(CONFIG_VOICE_CPE_VMMC_MPS_HISTORY_SIZE) +endif + +#defaults +FW_URL:=http://localhost/ +FW_TARGET:=ifx_firmware.bin +FW_FILE:=fw_voip_ifx.tar.gz +COEF_TARGET:=ifx_bbd_fxs.bin +COEF_FILE:=coef_voip_ifx.tar.gz + +FW_DIR:=lib/firmware +ifeq ($(CONFIG_VOICE_CPE_VMMC_WITH_DEVICE_DANUBE_extract),y) + CONFIGURE_ARGS += --with-device=DANUBE + FW_TARGET:=danube_firmware.bin + FW_URL:=http://www.arcor.de/hilfe/files/pdf/ + FW_FILE=arcor_A800_452CPW_FW_1.02.206(20081201).bin + FW_MD5SUM:=19d9af4e369287a0f0abaed415cdac10 + COEF_TARGET:=danube_bbd_fxs.bin + COEF_FILE:=arcor_A800_452CPW_FW_1.02.206(20081201).bin + COEF_MD5SUM:=19d9af4e369287a0f0abaed415cdac10 +endif + +ifeq ($(CONFIG_VOICE_CPE_VMMC_WITH_DEVICE_DANUBE),y) + CONFIGURE_ARGS += --with-device=DANUBE + FW_TARGET:=danube_firmware.bin + FW_FILE=fw_voip_danube-12.1.0.1.0.tar.gz + FW_MD5SUM:=51868b88dee9dbc65d3dbba355ded91c + COEF_TARGET:=danube_bbd_fxs.bin + COEF_FILE:=coef_voip_danube-0.9.0.tar.gz + COEF_MD5SUM:=c8ac6592b304b03829a8123560e15710 +endif + +ifeq ($(CONFIG_VOICE_CPE_VMMC_WITH_DEVICE_AR9),y) + CONFIGURE_ARGS += --with-device=AR9 + # TODO: add fw/coef +endif + +ifeq ($(CONFIG_VOICE_CPE_VMMC_WITH_DEVICE_VR9),y) + CONFIGURE_ARGS += --with-device=VR9 + # TODO: add fw/coef +endif + +ifeq ($(CONFIG_VOICE_CPE_VMMC_WITH_DEVICE_DANUBE_extract),y) +define Download/decode + FILE:=ifxmips_fw_decode.tar.bz2 + URL:=http://downloads.openwrt.org/sources/ + MD5SUM:=1197ff6cace6a7c86492a468f5fbfe07 +endef +$(eval $(call Download,decode)) +endif + +define Download/firmware + FILE:=$(FW_FILE) + URL:=$(FW_URL) + MD5SUM:=$(FW_MD5SUM) +endef +$(eval $(call Download,firmware)) + +define Download/coef + FILE:=$(COEF_FILE) + URL:=$(FW_URL) + MD5SUM:=$(COEF_MD5SUM) +endef +$(eval $(call Download,coef)) + +define Build/Configure + rm -rf \ + $(PKG_BUILD_DIR)/coef \ + $(PKG_BUILD_DIR)/firmware + mkdir -p \ + $(PKG_BUILD_DIR)/coef \ + $(PKG_BUILD_DIR)/firmware +ifeq ($(CONFIG_VOICE_CPE_VMMC_WITH_DEVICE_DANUBE_extract),y) + $(PLATFORM_DIR)/extract.sh $(DL_DIR) '$(FW_FILE)' + $(CP) $(DL_DIR)/voip.bin $(PKG_BUILD_DIR)/firmware/$(FW_TARGET) + $(CP) $(DL_DIR)/voip_coef.bin $(PKG_BUILD_DIR)/coef/$(COEF_TARGET) +else + $(TAR) -C $(PKG_BUILD_DIR)/firmware -xvzf $(DL_DIR)/$(FW_FILE) + $(TAR) -C $(PKG_BUILD_DIR)/coef -xvzf $(DL_DIR)/$(COEF_FILE) +endif + (cd $(PKG_BUILD_DIR); aclocal && autoconf && automake) + $(call Build/Configure/Default) +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + mkdir -p $(1)/usr/include/drv_vmmc + $(CP) -v --dereference $(PKG_BUILD_DIR)/include/* $(1)/usr/include/drv_vmmc + (cd $(1)/usr/include/drv_vmmc && ln -snf . include) +endef + +define KernelPackage/ifx-vmmc/install + $(INSTALL_DIR) $(1)/etc/init.d $(1)/$(FW_DIR) + $(INSTALL_BIN) ./files/vmmc.init $(1)/etc/init.d/vmmc + $(CP) $(PKG_BUILD_DIR)/firmware/$(FW_TARGET) $(1)/$(FW_DIR)/$(FW_TARGET) + $(CP) $(PKG_BUILD_DIR)/coef/$(COEF_TARGET) $(1)/$(FW_DIR)/$(COEF_TARGET) +endef + +$(eval $(call KernelPackage,ifx-vmmc)) diff --git a/package/ifx-vmmc/files/vmmc.init b/package/ifx-vmmc/files/vmmc.init new file mode 100644 index 000000000..bae7badaf --- /dev/null +++ b/package/ifx-vmmc/files/vmmc.init @@ -0,0 +1,25 @@ +#!/bin/sh /etc/rc.common +# +# Activate Voice CPE TAPI subsystem LL driver for VMMC + +START=31 + +start() { + # TODO: clean up this mess + [ `cat /proc/cpuinfo | grep system | cut -f 3 -d ' '` = "Twinpass-VE" ] && { + [ ! -e /dev/danube-port ] && mknod /dev/danube-port c 254 0 + return; + } + [ `cat /proc/cpuinfo | grep system | cut -f 3 -d ' '` != "Danube" ] && { + [ ! -e /dev/amazon_s-port ] && mknod /dev/amazon_s-port c 240 1 + echo "INFO configuring HW scheduling 33/66" + echo "t0 0x0" > /proc/mips/mtsched + echo "t1 0x1" > /proc/mips/mtsched + echo "v0 0x0" > /proc/mips/mtsched + } + [ `cat /proc/cpuinfo | grep system | cut -f 3 -d ' '` = "Danube" ] && { + [ ! -e /dev/danube-port ] && mknod /dev/danube-port c 240 1 + # switch life-line relais + echo 1 > /sys/class/leds/fxs_relay/brightness + } +} diff --git a/package/ifx-vmmc/patches/001-portability.patch b/package/ifx-vmmc/patches/001-portability.patch new file mode 100644 index 000000000..fb8ab68ed --- /dev/null +++ b/package/ifx-vmmc/patches/001-portability.patch @@ -0,0 +1,26 @@ +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -227,7 +227,7 @@ drv_vmmc_CFLAGS += -fno-common + drv_vmmc_OBJS = "$(subst .c,.o, $(drv_vmmc_SOURCES) $(nodist_drv_vmmc_SOURCES))" + + drv_vmmc.ko: $(drv_vmmc_SOURCES) $(EXTRA_DIST) +- @echo -e "Making Linux 2.6.x kernel object" ++ @echo "Making Linux 2.6.x kernel object" + @for f in $(drv_vmmc_SOURCES) $(nodist_drv_vmmc_SOURCES) ; do \ + if test ! -e $(PWD)/$$f; then \ + echo " LN $$f" ; \ +@@ -235,10 +235,10 @@ drv_vmmc.ko: $(drv_vmmc_SOURCES) $(EXTRA + ln -s @abs_srcdir@/$$f $(PWD)/$$f; \ + fi; \ + done; +- @echo -e "# drv_vmmc: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild +- @echo -e "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild +- @echo -e "$(subst .ko,,$@)-y := $(drv_vmmc_OBJS)" >> $(PWD)/Kbuild +- @echo -e "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(CFLAGS) $(drv_vmmc_CFLAGS) $(INCLUDES)" >> $(PWD)/Kbuild ++ @echo "# drv_vmmc: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild ++ @echo "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild ++ @echo "$(subst .ko,,$@)-y := $(drv_vmmc_OBJS)" >> $(PWD)/Kbuild ++ @echo "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(CFLAGS) $(drv_vmmc_CFLAGS) $(INCLUDES)" >> $(PWD)/Kbuild + $(MAKE) ARCH=@KERNEL_ARCH@ -C @KERNEL_BUILD_PATH@ O=@KERNEL_BUILD_PATH@ M=$(PWD) modules + + clean-generic: diff --git a/package/ifx-vmmc/patches/100-ifxmips.patch b/package/ifx-vmmc/patches/100-ifxmips.patch new file mode 100644 index 000000000..6a4cc8d59 --- /dev/null +++ b/package/ifx-vmmc/patches/100-ifxmips.patch @@ -0,0 +1,491 @@ +--- a/src/drv_vmmc_access.h ++++ b/src/drv_vmmc_access.h +@@ -24,6 +24,10 @@ + #include "drv_mps_vmmc.h" + #endif + ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# define IFX_MPS IFXMIPS_MPS_BASE_ADDR ++#endif ++ + /* ============================= */ + /* Global Defines */ + /* ============================= */ +--- a/src/drv_vmmc_bbd.c ++++ b/src/drv_vmmc_bbd.c +@@ -939,7 +939,11 @@ static IFX_int32_t vmmc_BBD_DownloadChCr + IFX_uint8_t padBytes = 0; + #endif + IFX_uint16_t cram_offset, cram_crc, +- pCmd [MAX_CMD_WORD] = {0}; ++ pCmd [MAX_CMD_WORD] ++#if defined (__GNUC__) || defined (__GNUG__) ++ __attribute__ ((aligned(4))) ++#endif ++ = {0}; + + /* read offset */ + cpb2w (&cram_offset, &bbd_cram->pData[0], sizeof (IFX_uint16_t)); +--- a/src/drv_vmmc_danube.h ++++ b/src/drv_vmmc_danube.h +@@ -15,12 +15,59 @@ + */ + + #if defined SYSTEM_DANUBE +-#include ++# if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# include ++ ++# define IFX_GPIO_PIN_NUMBER_PER_PORT 16 ++# define IFX_GPIO_PIN_ID(port, pin) ((port) \ ++ * IFX_GPIO_PIN_NUMBER_PER_PORT \ ++ + (pin)) ++# define IFX_GPIO_PIN_ID_TO_PORT(pin_id) (pin_id >> 4) ++# define IFX_GPIO_PIN_ID_TO_PIN(pin_id) (pin_id & 0x0F) ++ ++# define IFX_GPIO_MODULE_TAPI_VMMC 0 /* not used */ ++ ++# define ifx_gpio_pin_reserve(a,b) 0 /* obsolete */ ++ ++# define ifx_gpio_open_drain_set(a,b) ifxmips_port_set_open_drain( \ ++ IFX_GPIO_PIN_ID_TO_PORT(a), \ ++ IFX_GPIO_PIN_ID_TO_PIN(a)) ++ ++# define ifx_gpio_altsel0_set(a,b) ifxmips_port_set_altsel0( \ ++ IFX_GPIO_PIN_ID_TO_PORT(a), \ ++ IFX_GPIO_PIN_ID_TO_PIN(a)) ++ ++# define ifx_gpio_altsel1_set(a,b) ifxmips_port_set_altsel1( \ ++ IFX_GPIO_PIN_ID_TO_PORT(a), \ ++ IFX_GPIO_PIN_ID_TO_PIN(a)) ++ ++# define ifx_gpio_altsel0_clear(a,b) ifxmips_port_clear_altsel0( \ ++ IFX_GPIO_PIN_ID_TO_PORT(a), \ ++ IFX_GPIO_PIN_ID_TO_PIN(a)) ++ ++# define ifx_gpio_altsel1_clear(a,b) ifxmips_port_clear_altsel1( \ ++ IFX_GPIO_PIN_ID_TO_PORT(a), \ ++ IFX_GPIO_PIN_ID_TO_PIN(a)) ++ ++# define ifx_gpio_dir_in_set(a,b) ifxmips_port_set_dir_in( \ ++ IFX_GPIO_PIN_ID_TO_PORT(a), \ ++ IFX_GPIO_PIN_ID_TO_PIN(a)) ++ ++# define ifx_gpio_dir_out_set(a,b) ifxmips_port_set_dir_out( \ ++ IFX_GPIO_PIN_ID_TO_PORT(a), \ ++ IFX_GPIO_PIN_ID_TO_PIN(a)) ++ ++# define ifx_gpio_pin_free(a,b) ifxmips_port_free_pin( \ ++ IFX_GPIO_PIN_ID_TO_PORT(a), \ ++ IFX_GPIO_PIN_ID_TO_PIN(a)) ++# else ++# include ++# endif + #else + #error no system selected + #endif + +-#define VMMC_TAPI_GPIO_MODULE_ID IFX_GPIO_MODULE_TAPI_VMMC ++#define VMMC_TAPI_GPIO_MODULE_ID IFX_GPIO_MODULE_TAPI_VMMC + /** + + */ +--- a/src/drv_vmmc_init.c ++++ b/src/drv_vmmc_init.c +@@ -48,6 +48,14 @@ + #include "drv_vmmc_pmc.h" + #endif /* PMC_SUPPORTED */ + ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# define IFX_MPS_CAD0SR IFXMIPS_MPS_CAD0SR ++# define IFX_MPS_CAD1SR IFXMIPS_MPS_CAD1SR ++# define IFX_MPS_CVC0SR IFXMIPS_MPS_CVC0SR ++# define IFX_MPS_CVC1SR IFXMIPS_MPS_CVC1SR ++# define IFX_MPS_CVC2SR IFXMIPS_MPS_CVC2SR ++# define IFX_MPS_CVC3SR IFXMIPS_MPS_CVC3SR ++#endif + + /* ============================= */ + /* Local Macros & Definitions */ +--- a/src/drv_vmmc_init_cap.c ++++ b/src/drv_vmmc_init_cap.c +@@ -22,6 +22,11 @@ + #include "drv_mps_vmmc.h" + #include "drv_mps_vmmc_device.h" + ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# define IFX_MPS_CHIPID_VERSION_GET IFXMIPS_MPS_CHIPID_VERSION_GET ++# define IFX_MPS_CHIPID IFXMIPS_MPS_CHIPID ++#endif ++ + /* ============================= */ + /* Configuration defintions */ + /* ============================= */ +--- a/src/mps/drv_mps_vmmc_common.c ++++ b/src/mps/drv_mps_vmmc_common.c +@@ -35,8 +35,35 @@ + #include "ifxos_interrupt.h" + #include "ifxos_time.h" + +-#include +-#include ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# include ++# include ++# include ++ ++# define ifx_gptu_timer_request ifxmips_request_timer ++# define ifx_gptu_timer_start ifxmips_start_timer ++# define ifx_gptu_countvalue_get ifxmips_get_count_value ++# define ifx_gptu_timer_free ifxmips_free_timer ++ ++# define IFX_MPS_SRAM IFXMIPS_MPS_SRAM ++# define IFX_MPS_AD0ENR IFXMIPS_MPS_AD0ENR ++# define IFX_MPS_AD1ENR IFXMIPS_MPS_AD1ENR ++# define IFX_MPS_VC0ENR IFXMIPS_MPS_VC0ENR ++# define IFX_MPS_SAD0SR IFXMIPS_MPS_SAD0SR ++# define IFX_MPS_RAD0SR IFXMIPS_MPS_RAD0SR ++# define IFX_MPS_RAD1SR IFXMIPS_MPS_RAD1SR ++# define IFX_MPS_CAD0SR IFXMIPS_MPS_CAD0SR ++# define IFX_MPS_CAD1SR IFXMIPS_MPS_CAD1SR ++# define IFX_MPS_RVC0SR IFXMIPS_MPS_RVC0SR ++# define IFX_MPS_CVC0SR IFXMIPS_MPS_CVC0SR ++ ++# define INT_NUM_IM4_IRL14 (INT_NUM_IM4_IRL0 + 14) ++ ++# define bsp_mask_and_ack_irq ifxmips_mask_and_ack_irq ++#else ++# include ++# include ++#endif + + #include "drv_mps_vmmc.h" + #include "drv_mps_vmmc_dbg.h" +@@ -193,7 +220,8 @@ IFX_boolean_t ifx_mps_ext_bufman () + */ + IFX_void_t *ifx_mps_fastbuf_malloc (IFX_size_t size, IFX_int32_t priority) + { +- IFX_uint32_t ptr, flags; ++ unsigned long flags; ++ IFX_uint32_t ptr; + IFX_int32_t index = fastbuf_index; + + if (fastbuf_initialized == 0) +@@ -219,11 +247,11 @@ IFX_void_t *ifx_mps_fastbuf_malloc (IFX_ + if ((volatile IFX_uint32_t) fastbuf_pool[index] & FASTBUF_USED) + continue; + ptr = fastbuf_pool[index]; +- (volatile IFX_uint32_t) fastbuf_pool[index] |= FASTBUF_USED; ++ fastbuf_pool[index] = (volatile IFX_uint32_t) fastbuf_pool[index] | FASTBUF_USED; + if ((priority == FASTBUF_FW_OWNED) || (priority == FASTBUF_CMD_OWNED) || + (priority == FASTBUF_EVENT_OWNED) || + (priority == FASTBUF_WRITE_OWNED)) +- (volatile IFX_uint32_t) fastbuf_pool[index] |= priority; ++ fastbuf_pool[index] = (volatile IFX_uint32_t) fastbuf_pool[index] | priority; + fastbuf_index = index; + IFXOS_UNLOCKINT (flags); + return (IFX_void_t *) ptr; +@@ -247,7 +275,7 @@ IFX_void_t *ifx_mps_fastbuf_malloc (IFX_ + */ + IFX_void_t ifx_mps_fastbuf_free (const IFX_void_t * ptr) + { +- IFX_uint32_t flags; ++ unsigned long flags; + IFX_int32_t index = fastbuf_index; + + IFXOS_LOCKINT (flags); +@@ -261,8 +289,9 @@ IFX_void_t ifx_mps_fastbuf_free (const I + FASTBUF_EVENT_OWNED | FASTBUF_WRITE_OWNED)) + == ((IFX_uint32_t) ptr | FASTBUF_USED)) + { +- (volatile IFX_uint32_t) fastbuf_pool[index] &= ~FASTBUF_USED; +- (volatile IFX_uint32_t) fastbuf_pool[index] &= ++ fastbuf_pool[index] = (volatile IFX_uint32_t) fastbuf_pool[index] & ~FASTBUF_USED; ++ ++ fastbuf_pool[index] = (volatile IFX_uint32_t) fastbuf_pool[index] & + ~(FASTBUF_FW_OWNED | FASTBUF_CMD_OWNED | FASTBUF_EVENT_OWNED | + FASTBUF_WRITE_OWNED); + IFXOS_UNLOCKINT (flags); +@@ -444,7 +473,7 @@ static mps_buffer_state_e ifx_mps_bufman + */ + static IFX_int32_t ifx_mps_bufman_inc_level (IFX_uint32_t value) + { +- IFX_uint32_t flags; ++ unsigned long flags; + + if (mps_buffer.buf_level + value > MPS_BUFFER_MAX_LEVEL) + { +@@ -471,7 +500,7 @@ static IFX_int32_t ifx_mps_bufman_inc_le + */ + static IFX_int32_t ifx_mps_bufman_dec_level (IFX_uint32_t value) + { +- IFX_uint32_t flags; ++ unsigned long flags; + + if (mps_buffer.buf_level < value) + { +@@ -932,7 +961,7 @@ IFX_int32_t ifx_mps_common_open (mps_com + mps_mbx_dev * pMBDev, IFX_int32_t bcommand, + IFX_boolean_t from_kernel) + { +- IFX_uint32_t flags; ++ unsigned long flags; + + IFXOS_LOCKINT (flags); + +@@ -1048,7 +1077,7 @@ IFX_int32_t ifx_mps_common_close (mps_mb + IFX_void_t ifx_mps_release_structures (mps_comm_dev * pDev) + { + IFX_int32_t count; +- IFX_uint32_t flags; ++ unsigned long flags; + + IFXOS_LOCKINT (flags); + IFXOS_BlockFree (pFW_img_data); +@@ -1544,7 +1573,7 @@ IFX_int32_t ifx_mps_mbx_read_message (mp + IFX_uint32_t * bytes) + { + IFX_int32_t i, ret; +- IFX_uint32_t flags; ++ unsigned long flags; + + IFXOS_LOCKINT (flags); + +@@ -1751,7 +1780,7 @@ IFX_int32_t ifx_mps_mbx_write_message (m + { + mps_fifo *mbx; + IFX_uint32_t i; +- IFX_uint32_t flags; ++ unsigned long flags; + IFX_int32_t retval = -EAGAIN; + IFX_int32_t retries = 0; + IFX_uint32_t word = 0; +@@ -2138,6 +2167,7 @@ IFX_int32_t ifx_mps_mbx_write_cmd (mps_m + TRACE (MPS, DBG_LEVEL_HIGH, + ("%s(): Invalid device ID %d !\n", __FUNCTION__, pMBDev->devID)); + } ++ + return retval; + } + +@@ -2161,7 +2191,7 @@ IFX_void_t ifx_mps_mbx_data_upstream (IF + mps_mbx_dev *mbx_dev; + MbxMsg_s msg; + IFX_uint32_t bytes_read = 0; +- IFX_uint32_t flags; ++ unsigned long flags; + IFX_int32_t ret; + + /* set pointer to data upstream mailbox, no matter if 0,1,2 or 3 because +@@ -2252,7 +2282,7 @@ IFX_void_t ifx_mps_mbx_data_upstream (IF + { + ifx_mps_bufman_dec_level (1); + if ((ifx_mps_bufman_get_level () <= mps_buffer.buf_threshold) && +- (atomic_read (&pMPSDev->provide_buffer->object.count) == 0)) ++ ((volatile unsigned int)pMPSDev->provide_buffer->object.count == 0)) + { + IFXOS_LockRelease (pMPSDev->provide_buffer); + } +@@ -2295,7 +2325,7 @@ IFX_void_t ifx_mps_mbx_data_upstream (IF + #endif /* CONFIG_PROC_FS */ + ifx_mps_bufman_dec_level (1); + if ((ifx_mps_bufman_get_level () <= mps_buffer.buf_threshold) && +- (atomic_read (&pMPSDev->provide_buffer->object.count) == 0)) ++ ((volatile unsigned int)pMPSDev->provide_buffer->object.count == 0)) + { + IFXOS_LockRelease (pMPSDev->provide_buffer); + } +@@ -2325,7 +2355,7 @@ IFX_void_t ifx_mps_mbx_data_upstream (IF + IFX_void_t ifx_mps_mbx_cmd_upstream (IFX_ulong_t dummy) + { + mps_fifo *mbx; +- IFX_uint32_t flags; ++ unsigned long flags; + + /* set pointer to upstream command mailbox */ + mbx = &(pMPSDev->cmd_upstrm_fifo); +@@ -2373,7 +2403,7 @@ IFX_void_t ifx_mps_mbx_event_upstream (I + mps_event_msg msg; + IFX_int32_t length = 0; + IFX_int32_t read_length = 0; +- IFX_uint32_t flags; ++ unsigned long flags; + + /* set pointer to upstream event mailbox */ + mbx = &(pMPSDev->event_upstrm_fifo); +@@ -2616,7 +2646,7 @@ IFX_void_t ifx_mps_disable_mailbox_int ( + */ + IFX_void_t ifx_mps_dd_mbx_int_enable (IFX_void_t) + { +- IFX_uint32_t flags; ++ unsigned long flags; + MPS_Ad0Reg_u Ad0Reg; + + IFXOS_LOCKINT (flags); +@@ -2642,7 +2672,7 @@ IFX_void_t ifx_mps_dd_mbx_int_enable (IF + */ + IFX_void_t ifx_mps_dd_mbx_int_disable (IFX_void_t) + { +- IFX_uint32_t flags; ++ unsigned long flags; + MPS_Ad0Reg_u Ad0Reg; + + IFXOS_LOCKINT (flags); +@@ -2769,6 +2799,7 @@ irqreturn_t ifx_mps_ad0_irq (IFX_int32_t + } + } + ++ + if (MPS_Ad0StatusReg.fld.du_mbx) + { + #ifdef CONFIG_PROC_FS +@@ -3062,7 +3093,8 @@ IFX_int32_t ifx_mps_get_fw_version (IFX_ + */ + IFX_return_t ifx_mps_init_gpt () + { +- IFX_uint32_t flags, timer_flags, timer, loops = 0; ++ unsigned long flags; ++ IFX_uint32_t timer_flags, timer, loops = 0; + IFX_ulong_t count; + #if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) + timer = TIMER1A; +--- a/src/mps/drv_mps_vmmc_danube.c ++++ b/src/mps/drv_mps_vmmc_danube.c +@@ -32,9 +32,22 @@ + #include "ifxos_select.h" + #include "ifxos_interrupt.h" + +-#include +-#include +-#include ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# include ++# include ++# include ++# include ++ ++# define IFX_RCU_RST_REQ IFXMIPS_RCU_RST ++# define IFX_RCU_RST_REQ_CPU1 IFXMIPS_RCU_RST_CPU1 ++ ++# define ifx_get_cp1_base prom_get_cp1_base ++# define ifx_get_cp1_size prom_get_cp1_size ++#else ++# include ++# include ++# include ++#endif + + #include "drv_mps_vmmc.h" + #include "drv_mps_vmmc_dbg.h" +@@ -119,6 +132,15 @@ IFX_int32_t ifx_mps_download_firmware (m + } + + /* check if FW image fits in available memory space */ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++ if (mem > ifx_get_cp1_size()<<20) ++ { ++ TRACE (MPS, DBG_LEVEL_HIGH, ++ ("[%s %s %d]: error, firmware memory exceeds reserved space (%i > %i)!\n", ++ __FILE__, __func__, __LINE__, mem, ifx_get_cp1_size()<<20)); ++ return IFX_ERROR; ++ } ++#else + if (mem > ifx_get_cp1_size()) + { + TRACE (MPS, DBG_LEVEL_HIGH, +@@ -126,6 +148,7 @@ IFX_int32_t ifx_mps_download_firmware (m + __FILE__, __func__, __LINE__, mem, ifx_get_cp1_size())); + return IFX_ERROR; + } ++#endif + + /* reset the driver */ + ifx_mps_reset (); +@@ -337,7 +360,7 @@ IFX_void_t ifx_mps_release (IFX_void_t) + */ + IFX_void_t ifx_mps_wdog_expiry() + { +- IFX_uint32_t flags; ++ unsigned long flags; + + IFXOS_LOCKINT (flags); + /* recalculate and compare the firmware checksum */ +--- a/src/mps/drv_mps_vmmc_device.h ++++ b/src/mps/drv_mps_vmmc_device.h +@@ -16,8 +16,15 @@ + declarations. + *******************************************************************************/ + +-#include +-#include ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# include ++# include ++# include ++# include ++#else ++# include ++# include ++#endif + + /* ============================= */ + /* MPS Common defines */ +--- a/src/mps/drv_mps_vmmc_linux.c ++++ b/src/mps/drv_mps_vmmc_linux.c +@@ -40,10 +40,26 @@ + #include + #endif /* */ + +- +-#include +-#include +-#include ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# include ++# include ++ ++# define IFX_MPS_AD0ENR IFXMIPS_MPS_AD0ENR ++# define IFX_MPS_AD1ENR IFXMIPS_MPS_AD1ENR ++# define IFX_MPS_RAD0SR IFXMIPS_MPS_RAD0SR ++# define IFX_MPS_RAD1SR IFXMIPS_MPS_RAD1SR ++# define IFX_MPS_VC0ENR IFXMIPS_MPS_VC0ENR ++# define IFX_MPS_RVC0SR IFXMIPS_MPS_RVC0SR ++ ++# define INT_NUM_IM4_IRL14 (INT_NUM_IM4_IRL0 + 14) ++# define INT_NUM_IM4_IRL18 (INT_NUM_IM4_IRL0 + 18) ++# define INT_NUM_IM4_IRL19 (INT_NUM_IM4_IRL0 + 19) ++# define IFX_ICU_IM4_IER IFXMIPS_ICU_IM4_IER ++#else ++# include ++# include ++# include ++#endif + + /* lib_ifxos headers */ + #include "ifx_types.h" +@@ -914,7 +930,7 @@ IFX_int32_t ifx_mps_ioctl (struct inode + #endif /* MPS_FIFO_BLOCKING_WRITE */ + case FIO_MPS_GET_STATUS: + { +- IFX_uint32_t flags; ++ unsigned long flags; + + IFXOS_LOCKINT (flags); + +@@ -949,7 +965,7 @@ IFX_int32_t ifx_mps_ioctl (struct inode + #if CONFIG_MPS_HISTORY_SIZE > 0 + case FIO_MPS_GET_CMD_HISTORY: + { +- IFX_uint32_t flags; ++ unsigned long flags; + + if (from_kernel) + { +@@ -1637,6 +1653,7 @@ IFX_int32_t ifx_mps_get_status_proc (IFX + sprintf (buf + len, " minLv: \t %8d\n", + ifx_mps_dev.voice_mb[i].upstrm_fifo->min_space); + } ++ + return len; + } + diff --git a/package/ifxmips-dsl-api/Config.in b/package/ifxmips-dsl-api/Config.in index f27181e31..56177d168 100644 --- a/package/ifxmips-dsl-api/Config.in +++ b/package/ifxmips-dsl-api/Config.in @@ -17,6 +17,13 @@ config IFXMIPS_ANNEX_B endchoice +config IFXMIPS_DSL_FIRMWARE + bool "ifxmips-dsl firmware extractor" + default y + depends on PACKAGE_kmod-ifxmips-dsl-api + help + Say Y, if you need ifxmips-dsl to auto extract the firmware for you from the a800 firmware image + config IFXMIPS_DSL_DEBUG bool "ifxmips-dsl debugging" depends on PACKAGE_kmod-ifxmips-dsl-api diff --git a/package/ifxmips-dsl-api/Makefile b/package/ifxmips-dsl-api/Makefile index 3fc31eda4..b1952b5ed 100644 --- a/package/ifxmips-dsl-api/Makefile +++ b/package/ifxmips-dsl-api/Makefile @@ -34,7 +34,7 @@ define KernelPackage/ifxmips-dsl-api TITLE:=DSL CPE API driver URL:=http://www.infineon.com/ MAINTAINER:=Infineon Technologies AG / Lantiq / blogic@openwrt.org - DEPENDS:=@TARGET_ifxmips + DEPENDS:=@TARGET_ifxmips @BROKEN FILES:=$(PKG_BUILD_DIR)/src/mei/ifxmips_mei.$(LINUX_KMOD_SUFFIX) \ $(PKG_BUILD_DIR)/src/drv_dsl_cpe_api.$(LINUX_KMOD_SUFFIX) \ $(PKG_BUILD_DIR)/src/mei/ifxmips_atm.$(LINUX_KMOD_SUFFIX) @@ -57,6 +57,17 @@ define KernelPackage/ifxmips-dsl-api/config source "$(SOURCE)/Config.in" endef +ifeq ($(CONFIG_IFXMIPS_DSL_FIRMWARE),y) +FW_FILE:=arcor_A800_452CPW_FW_1.02.206(20081201).bin +define Download/firmware + URL:=http://www.arcor.de/hilfe/files/pdf/ + FILE=$(FW_FILE) + MD5SUM:=19d9af4e369287a0f0abaed415cdac10 +endef +$(eval $(call Download,firmware)) + +else + define Download/annex-a FILE:=$(FW_BASE_NAME)_a-$(FW_A_VER).tar.gz URL:=http://mirror2.openwrt.org/sources/ @@ -70,6 +81,7 @@ define Download/annex-b MD5SUM:=$(FW_B_MD5) endef $(eval $(call Download,annex-b)) +endif IFX_DSL_MAX_DEVICE=1 IFX_DSL_LINES_PER_DEVICE=1 @@ -145,7 +157,12 @@ endef define KernelPackage/ifxmips-dsl-api/install $(INSTALL_DIR) $(1)/lib/firmware/ +ifeq ($(CONFIG_IFXMIPS_DSL_FIRMWARE),y) + $(PLATFORM_DIR)/extract.sh $(DL_DIR) '$(FW_FILE)' + $(CP) $(DL_DIR)/dsl_$(if $(CONFIG_IFXMIPS_ANNEX_A),a,b).bin $(1)/lib/firmware/ModemHWE.bin +else $(CP) $(PKG_BUILD_DIR)/$(FW_BASE_NAME)_$(if $(CONFIG_IFXMIPS_ANNEX_A),a_$(FW_A_FILE_VER),b_$(FW_B_FILE_VER)).bin $(1)/lib/firmware/ModemHWE.bin +endif endef $(eval $(call KernelPackage,ifxmips-dsl-api)) diff --git a/package/ifxmips-dsl-control/Makefile b/package/ifxmips-dsl-control/Makefile index 035deada1..bd35d2f9c 100644 --- a/package/ifxmips-dsl-control/Makefile +++ b/package/ifxmips-dsl-control/Makefile @@ -24,7 +24,7 @@ define Package/ifxmips-dsl-control TITLE:=DSL CPE control application URL:=http://www.infineon.com/ MAINTAINER:=Infineon Technologies AG / Lantiq / blogic@openwrt.org - DEPENDS:=+kmod-ifxmips-dsl-api +libpthread + DEPENDS:=+kmod-ifxmips-dsl-api +libpthread @BROKEN endef define Package/ifxmips-dsl-control/description diff --git a/package/ifxos/Makefile b/package/ifxos/Makefile index de4da7de8..e0fac2303 100644 --- a/package/ifxos/Makefile +++ b/package/ifxos/Makefile @@ -10,20 +10,20 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=lib_ifxos -PKG_VERSION:=1.5.10 +PKG_VERSION:=1.5.12 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_RELEASE:=1 PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources -PKG_MD5SUM:=3602797b0f531f37546c6beb748d50cf +PKG_MD5SUM:=ba775356bdd5e1b73b3e11a152710ed6 include $(INCLUDE_DIR)/package.mk define KernelPackage/ifxos - SUBMENU:=Lantiq + SUBMENU:=Other modules TITLE:=Lantiq OS abstraction library URL:=http://www.lantiq.com/ MAINTAINER:=Lantiq - DEPENDS:=@TARGET_ifxmips + DEPENDS:=@TARGET_ifxmips @BROKEN FILES:=$(PKG_BUILD_DIR)/src/drv_ifxos.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,10,drv_ifxos) endef diff --git a/package/ifxos/patches/100-portability.patch b/package/ifxos/patches/100-portability.patch index 92b0ea01c..51d6bbd16 100644 --- a/package/ifxos/patches/100-portability.patch +++ b/package/ifxos/patches/100-portability.patch @@ -1,23 +1,8 @@ ---- a/configure.in -+++ b/configure.in -@@ -149,12 +149,12 @@ AC_ARG_ENABLE(targetincl, - echo Set the target image include path $enableval - AC_SUBST([TARGET_INCL_PATH],[$enableval]) - else -- echo -e Set the default target image include path $DEFAULT_TARGET_INCL_PATH -+ echo Set the default target image include path $DEFAULT_TARGET_INCL_PATH - AC_SUBST([TARGET_INCL_PATH],[$DEFAULT_TARGET_INCL_PATH]) - fi - ], - [ -- echo -e Set the default target image include path $DEFAULT_TARGET_INCL_PATH -+ echo Set the default target image include path $DEFAULT_TARGET_INCL_PATH - AC_SUBST([TARGET_INCL_PATH],[$DEFAULT_TARGET_INCL_PATH]) - ] - ) ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -610,7 +610,7 @@ if KERNEL_2_6 +Index: lib_ifxos-1.5.12/src/Makefile.am +=================================================================== +--- lib_ifxos-1.5.12.orig/src/Makefile.am 2010-01-08 18:12:15.000000000 +0100 ++++ lib_ifxos-1.5.12/src/Makefile.am 2010-03-31 18:56:12.000000000 +0200 +@@ -639,7 +639,7 @@ drv_ifxos_OBJS = "$(subst .c,.o,$(filter %.c,$(drv_ifxos_SOURCES)))" drv_ifxos.ko: $(drv_ifxos_SOURCES) @@ -26,7 +11,7 @@ if test ! -e common/ifxos_debug.c ; then \ echo "copy source files (as links only!)"; \ for f in $(filter %.c,$(drv_ifxos_SOURCES)); do \ -@@ -618,10 +618,10 @@ drv_ifxos.ko: $(drv_ifxos_SOURCES) +@@ -647,10 +647,10 @@ cp -s $(addprefix @abs_srcdir@/,$$f) $(PWD)/`dirname $$f`/ ; \ done \ fi diff --git a/package/kernel/modules/other.mk b/package/kernel/modules/other.mk index 8d51f90d2..48bf1ab99 100644 --- a/package/kernel/modules/other.mk +++ b/package/kernel/modules/other.mk @@ -261,7 +261,7 @@ $(eval $(call KernelPackage,ssb)) define KernelPackage/bluetooth SUBMENU:=$(OTHER_MENU) TITLE:=Bluetooth support - DEPENDS:=@USB_SUPPORT +kmod-usb-core +kmod-hid + DEPENDS:=@USB_SUPPORT +kmod-usb-core +!TARGET_x86:kmod-hid KCONFIG:= \ CONFIG_BLUEZ \ CONFIG_BLUEZ_L2CAP \ @@ -651,7 +651,7 @@ $(eval $(call KernelPackage,sc520-wdt)) define KernelPackage/input-core SUBMENU:=$(OTHER_MENU) TITLE:=Input device core - DEPENDS:=@LINUX_2_6 + DEPENDS:=@LINUX_2_6 @!TARGET_x86 KCONFIG:=CONFIG_INPUT FILES:=$(LINUX_DIR)/drivers/input/input-core.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,19,input-core) @@ -667,7 +667,7 @@ $(eval $(call KernelPackage,input-core)) define KernelPackage/input-evdev SUBMENU:=$(OTHER_MENU) TITLE:=Input event device - DEPENDS:=+kmod-input-core + DEPENDS:=+!TARGET_x86:kmod-input-core KCONFIG:=CONFIG_INPUT_EVDEV FILES:=$(LINUX_DIR)/drivers/input/evdev.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,60,evdev) @@ -683,7 +683,7 @@ $(eval $(call KernelPackage,input-evdev)) define KernelPackage/hid SUBMENU:=$(OTHER_MENU) TITLE:=HID Devices - DEPENDS:=+kmod-input-core +kmod-input-evdev + DEPENDS:=+kmod-input-core +kmod-input-evdev @!TARGET_x86 KCONFIG:=CONFIG_HID FILES:=$(LINUX_DIR)/drivers/hid/hid.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,61,hid) @@ -699,7 +699,7 @@ $(eval $(call KernelPackage,hid)) define KernelPackage/input-polldev SUBMENU:=$(OTHER_MENU) TITLE:=Polled Input device support - DEPENDS:=+kmod-input-core @LINUX_2_6 + DEPENDS:=+!TARGET_x86:kmod-input-core @LINUX_2_6 KCONFIG:=CONFIG_INPUT_POLLDEV FILES:=$(LINUX_DIR)/drivers/input/input-polldev.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,20,input-polldev) @@ -715,7 +715,7 @@ $(eval $(call KernelPackage,input-polldev)) define KernelPackage/input-gpio-keys SUBMENU:=$(OTHER_MENU) TITLE:=GPIO key support - DEPENDS:= @GPIO_SUPPORT +kmod-input-core + DEPENDS:= @GPIO_SUPPORT +!TARGET_x86:kmod-input-core KCONFIG:=CONFIG_KEYBOARD_GPIO FILES:=$(LINUX_DIR)/drivers/input/keyboard/gpio_keys.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,60,gpio_keys) @@ -749,7 +749,7 @@ $(eval $(call KernelPackage,input-gpio-buttons)) define KernelPackage/input-joydev SUBMENU:=$(OTHER_MENU) TITLE:=Joystick device support - DEPENDS:=+kmod-input-core + DEPENDS:=+!TARGET_x86:kmod-input-core KCONFIG:=CONFIG_INPUT_JOYDEV FILES:=$(LINUX_DIR)/drivers/input/joydev.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,62,joydev) diff --git a/package/kernel/modules/usb.mk b/package/kernel/modules/usb.mk index 322c62398..c962e340e 100644 --- a/package/kernel/modules/usb.mk +++ b/package/kernel/modules/usb.mk @@ -777,7 +777,7 @@ $(eval $(call KernelPackage,usb-net-rndis)) define KernelPackage/usb-hid -$(call KernelPackage/usb/Depends,@LINUX_2_6 +kmod-input-core +kmod-input-evdev +kmod-hid) +$(call KernelPackage/usb/Depends,@LINUX_2_6 +!TARGET_x86:kmod-input-core +kmod-input-evdev +!TARGET_x86:kmod-hid) TITLE:=Support for USB Human Input Devices KCONFIG:=CONFIG_HID_SUPPORT=y CONFIG_USB_HID FILES:=$(LINUX_DIR)/drivers/$(USBHID_DIR)/usbhid.ko @@ -793,7 +793,7 @@ $(eval $(call KernelPackage,usb-hid)) define KernelPackage/usb-yealink -$(call KernelPackage/usb/Depends,@LINUX_2_6 +kmod-input-core +kmod-input-evdev) +$(call KernelPackage/usb/Depends,@LINUX_2_6 +!TARGET_x86:kmod-input-core +kmod-input-evdev) TITLE:=USB Yealink VOIP phone KCONFIG:=CONFIG_USB_YEALINK CONFIG_INPUT_YEALINK CONFIG_INPUT=m CONFIG_INPUT_MISC=y FILES:=$(LINUX_DIR)/drivers/$(USBINPUT_DIR)/yealink.ko @@ -808,7 +808,7 @@ $(eval $(call KernelPackage,usb-yealink)) define KernelPackage/usb-cm109 -$(call KernelPackage/usb/Depends,@LINUX_2_6 +kmod-input-core +kmod-input-evdev) +$(call KernelPackage/usb/Depends,@LINUX_2_6 +!TARGET_x86:kmod-input-core +kmod-input-evdev) TITLE:=Support for CM109 device KCONFIG:=CONFIG_USB_CM109 CONFIG_INPUT_CM109 CONFIG_INPUT=m CONFIG_INPUT_MISC=y FILES:=$(LINUX_DIR)/drivers/$(USBINPUT_DIR)/cm109.ko diff --git a/package/lua/Makefile b/package/lua/Makefile index c8c64badf..0a5e8f343 100644 --- a/package/lua/Makefile +++ b/package/lua/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=lua PKG_VERSION:=5.1.4 -PKG_RELEASE:=5 +PKG_RELEASE:=6 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=http://www.lua.org/ftp/ \ diff --git a/package/lua/patches/600-refcounting.patch b/package/lua/patches/600-refcounting.patch deleted file mode 100644 index 554a7c42e..000000000 --- a/package/lua/patches/600-refcounting.patch +++ /dev/null @@ -1,1128 +0,0 @@ ---- a/src/lapi.c -+++ b/src/lapi.c -@@ -27,8 +27,8 @@ - #include "ltable.h" - #include "ltm.h" - #include "lundump.h" --#include "lvm.h" - #include "lnum.h" -+#include "lvm.h" - - - const char lua_ident[] = -@@ -117,6 +117,7 @@ LUA_API void lua_xmove (lua_State *from, - from->top -= n; - for (i = 0; i < n; i++) { - setobj2s(to, to->top++, from->top + i); -+ setnilvalue(from, from->top + i); - } - lua_unlock(to); - } -@@ -166,12 +167,14 @@ LUA_API void lua_settop (lua_State *L, i - if (idx >= 0) { - api_check(L, idx <= L->stack_last - L->base); - while (L->top < L->base + idx) -- setnilvalue(L->top++); -+ setnilvalue(L, L->top++); - L->top = L->base + idx; -+ setnilvalue(L, L->top); - } - else { -+ int i; - api_check(L, -(idx+1) <= (L->top - L->base)); -- L->top += idx+1; /* `subtract' index (index is negative) */ -+ setlvmtop(L, L->top + idx + 1); /* `subtract' index (index is negative) */ - } - lua_unlock(L); - } -@@ -183,7 +186,7 @@ LUA_API void lua_remove (lua_State *L, i - p = index2adr(L, idx); - api_checkvalidindex(L, p); - while (++p < L->top) setobjs2s(L, p-1, p); -- L->top--; -+ setlvmtop(L, L->top - 1); - lua_unlock(L); - } - -@@ -196,6 +199,7 @@ LUA_API void lua_insert (lua_State *L, i - api_checkvalidindex(L, p); - for (q = L->top; q>p; q--) setobjs2s(L, q, q-1); - setobjs2s(L, p, L->top); -+ setnilvalue(L, L->top); - lua_unlock(L); - } - -@@ -220,7 +224,7 @@ LUA_API void lua_replace (lua_State *L, - if (idx < LUA_GLOBALSINDEX) /* function upvalue? */ - luaC_barrier(L, curr_func(L), L->top - 1); - } -- L->top--; -+ setlvmtop(L, L->top - 1); - lua_unlock(L); - } - -@@ -259,14 +263,14 @@ LUA_API int lua_iscfunction (lua_State * - - - LUA_API int lua_isnumber (lua_State *L, int idx) { -- TValue n; -+ TValue n = tvinit(); - const TValue *o = index2adr(L, idx); - return tonumber(o, &n); - } - - - LUA_API int lua_isinteger (lua_State *L, int idx) { -- TValue tmp; -+ TValue tmp = tvinit(); - lua_Integer dum; - const TValue *o = index2adr(L, idx); - return tonumber(o,&tmp) && (ttisint(o) || tt_integer_valued(o,&dum)); -@@ -319,7 +323,7 @@ LUA_API int lua_lessthan (lua_State *L, - - - LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { -- TValue n; -+ TValue n = tvinit(); - const TValue *o = index2adr(L, idx); - if (tonumber(o, &n)) { - #ifdef LNUM_COMPLEX -@@ -333,7 +337,7 @@ LUA_API lua_Number lua_tonumber (lua_Sta - - - LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { -- TValue n; -+ TValue n = tvinit(); - /* Lua 5.1 documented behaviour is to return nonzero for non-integer: - * "If the number is not an integer, it is truncated in some non-specified way." - * I would suggest to change this, to return 0 for anything that would -@@ -369,7 +373,7 @@ LUA_API lua_Integer lua_tointeger (lua_S - - #ifdef LNUM_COMPLEX - LUA_API lua_Complex lua_tocomplex (lua_State *L, int idx) { -- TValue tmp; -+ TValue tmp = tvinit(); - const TValue *o = index2adr(L, idx); - if (tonumber(o, &tmp)) - return nvalue_complex(o); -@@ -465,7 +469,7 @@ LUA_API const void *lua_topointer (lua_S - - LUA_API void lua_pushnil (lua_State *L) { - lua_lock(L); -- setnilvalue(L->top); -+ setnilvalue(L, L->top); - api_incr_top(L); - lua_unlock(L); - } -@@ -548,8 +552,10 @@ LUA_API void lua_pushcclosure (lua_State - cl = luaF_newCclosure(L, n, getcurrenv(L)); - cl->c.f = fn; - L->top -= n; -- while (n--) -+ while (n--) { - setobj2n(L, &cl->c.upvalue[n], L->top+n); -+ setnilvalue(L, L->top + n); -+ } - setclvalue(L, L->top, cl); - lua_assert(iswhite(obj2gco(cl))); - api_incr_top(L); -@@ -600,7 +606,7 @@ LUA_API void lua_gettable (lua_State *L, - - LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { - StkId t; -- TValue key; -+ TValue key = tvinit(); - lua_lock(L); - t = index2adr(L, idx); - api_checkvalidindex(L, t); -@@ -689,7 +695,7 @@ LUA_API void lua_getfenv (lua_State *L, - setobj2s(L, L->top, gt(thvalue(o))); - break; - default: -- setnilvalue(L->top); -+ setnilvalue(L, L->top); - break; - } - api_incr_top(L); -@@ -709,21 +715,21 @@ LUA_API void lua_settable (lua_State *L, - t = index2adr(L, idx); - api_checkvalidindex(L, t); - luaV_settable(L, t, L->top - 2, L->top - 1); -- L->top -= 2; /* pop index and value */ -+ setlvmtop(L, L->top - 2); /* pop index and value */ - lua_unlock(L); - } - - - LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { - StkId t; -- TValue key; -+ TValue key = tvinit(); - lua_lock(L); - api_checknelems(L, 1); - t = index2adr(L, idx); - api_checkvalidindex(L, t); - setsvalue(L, &key, luaS_new(L, k)); - luaV_settable(L, t, &key, L->top - 1); -- L->top--; /* pop value */ -+ setlvmtop(L, L->top - 1); /* pop value */ - lua_unlock(L); - } - -@@ -736,7 +742,7 @@ LUA_API void lua_rawset (lua_State *L, i - api_check(L, ttistable(t)); - setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); - luaC_barriert(L, hvalue(t), L->top-1); -- L->top -= 2; -+ setlvmtop(L, L->top - 2); - lua_unlock(L); - } - -@@ -749,7 +755,7 @@ LUA_API void lua_rawseti (lua_State *L, - api_check(L, ttistable(o)); - setobj2t(L, luaH_setint(L, hvalue(o), n), L->top-1); - luaC_barriert(L, hvalue(o), L->top-1); -- L->top--; -+ setlvmtop(L, L->top - 1); - lua_unlock(L); - } - -@@ -785,7 +791,7 @@ LUA_API int lua_setmetatable (lua_State - break; - } - } -- L->top--; -+ setlvmtop(L, L->top - 1); - lua_unlock(L); - return 1; - } -@@ -814,7 +820,7 @@ LUA_API int lua_setfenv (lua_State *L, i - break; - } - if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); -- L->top--; -+ setlvmtop(L, L->top - 1); - lua_unlock(L); - return res; - } -@@ -1040,8 +1046,9 @@ LUA_API int lua_next (lua_State *L, int - if (more) { - api_incr_top(L); - } -- else /* no more elements */ -- L->top -= 1; /* remove key */ -+ else { /* no more elements */ -+ setlvmtop(L, L->top - 1); /* remove key */ -+ } - lua_unlock(L); - return more; - } -@@ -1053,7 +1060,7 @@ LUA_API void lua_concat (lua_State *L, i - if (n >= 2) { - luaC_checkGC(L); - luaV_concat(L, n, cast_int(L->top - L->base) - 1); -- L->top -= (n-1); -+ setlvmtop(L, L->top - (n-1)); - } - else if (n == 0) { /* push empty string */ - setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); -@@ -1139,6 +1146,7 @@ LUA_API const char *lua_setupvalue (lua_ - if (name) { - L->top--; - setobj(L, val, L->top); -+ setnilvalue(L, L->top); - luaC_barrier(L, clvalue(fi), L->top); - } - lua_unlock(L); -@@ -1160,7 +1168,7 @@ LUA_API const char *lua_setupvalue (lua_ - int lua_pushvalue_as_number (lua_State *L, int idx) - { - const TValue *o = index2adr(L, idx); -- TValue tmp; -+ TValue tmp = tvinit(); - lua_Integer i; - if (ttisnumber(o)) { - if ( (!ttisint(o)) && tt_integer_valued(o,&i)) { ---- a/src/lcode.c -+++ b/src/lcode.c -@@ -23,6 +23,7 @@ - #include "lparser.h" - #include "ltable.h" - #include "lnum.h" -+#include "lvm.h" - - - #define hasjumps(e) ((e)->t != (e)->f) -@@ -248,7 +249,7 @@ static int addk (FuncState *fs, TValue * - setivalue(idx, fs->nk); - luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, - MAXARG_Bx, "constant table overflow"); -- while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); -+ while (oldsize < f->sizek) setnilvalue(L, &f->k[oldsize++]); - setobj(L, &f->k[fs->nk], v); - luaC_barrier(L, f, v); - return fs->nk++; -@@ -257,21 +258,24 @@ static int addk (FuncState *fs, TValue * - - - int luaK_stringK (FuncState *fs, TString *s) { -- TValue o; -+ TValue o = tvinit(); - setsvalue(fs->L, &o, s); -+ luaV_unref(fs->L, &o); - return addk(fs, &o, &o); - } - - - int luaK_numberK (FuncState *fs, lua_Number r) { -- TValue o; -+ lua_State *L = fs->L; -+ TValue o = tvinit(); - setnvalue(&o, r); - return addk(fs, &o, &o); - } - - - int luaK_integerK (FuncState *fs, lua_Integer r) { -- TValue o; -+ lua_State *L = fs->L; -+ TValue o = tvinit(); - setivalue(&o, r); - return addk(fs, &o, &o); - } -@@ -279,22 +283,24 @@ int luaK_integerK (FuncState *fs, lua_In - - #ifdef LNUM_COMPLEX - static int luaK_imagK (FuncState *fs, lua_Number r) { -- TValue o; -+ lua_State *L = fs->L; -+ TValue o = tvinit(); - setnvalue_complex(&o, r*I); - return addk(fs, &o, &o); - } - #endif - - static int boolK (FuncState *fs, int b) { -- TValue o; -+ lua_State *L = fs->L; -+ TValue o = tvinit(); - setbvalue(&o, b); - return addk(fs, &o, &o); - } - - - static int nilK (FuncState *fs) { -- TValue k, v; -- setnilvalue(&v); -+ TValue k = tvinit(), v = tvinit(); -+ setnilvalue(fs->L, &v); - /* cannot use nil as key; instead use table itself to represent nil */ - sethvalue(fs->L, &k, fs->h); - return addk(fs, &k, &v); ---- a/src/ldebug.c -+++ b/src/ldebug.c -@@ -142,6 +142,7 @@ LUA_API const char *lua_setlocal (lua_St - if (name) - setobjs2s(L, ci->base + (n - 1), L->top - 1); - L->top--; /* pop value */ -+ setnilvalue(L, L->top); - lua_unlock(L); - return name; - } -@@ -176,7 +177,7 @@ static void info_tailcall (lua_Debug *ar - - static void collectvalidlines (lua_State *L, Closure *f) { - if (f == NULL || f->c.isC) { -- setnilvalue(L->top); -+ setnilvalue(L, L->top); - } - else { - Table *t = luaH_new(L, 0, 0); -@@ -248,7 +249,7 @@ LUA_API int lua_getinfo (lua_State *L, c - } - status = auxgetinfo(L, what, ar, f, ci); - if (strchr(what, 'f')) { -- if (f == NULL) setnilvalue(L->top); -+ if (f == NULL) setnilvalue(L, L->top); - else setclvalue(L, L->top, f); - incr_top(L); - } -@@ -586,7 +587,7 @@ void luaG_concaterror (lua_State *L, Stk - - - void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { -- TValue temp; -+ TValue temp = tvinit(); - if (luaV_tonumber(p1, &temp) == NULL) - p2 = p1; /* first operand is wrong */ - luaG_typeerror(L, p2, "perform arithmetic on"); ---- a/src/ldo.c -+++ b/src/ldo.c -@@ -211,7 +211,7 @@ static StkId adjust_varargs (lua_State * - Table *htab = NULL; - StkId base, fixed; - for (; actual < nfixargs; ++actual) -- setnilvalue(L->top++); -+ setnilvalue(L, L->top++); - #if defined(LUA_COMPAT_VARARG) - if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */ - int nvar = actual - nfixargs; /* number of extra arguments */ -@@ -229,7 +229,7 @@ static StkId adjust_varargs (lua_State * - base = L->top; /* final position of first argument */ - for (i=0; itop++, fixed+i); -- setnilvalue(fixed+i); -+ setnilvalue(L, fixed+i); - } - /* add `arg' parameter */ - if (htab) { -@@ -294,7 +294,7 @@ int luaD_precall (lua_State *L, StkId fu - ci->tailcalls = 0; - ci->nresults = nresults; - for (st = L->top; st < ci->top; st++) -- setnilvalue(st); -+ setnilvalue(L, st); - L->top = ci->top; - if (L->hookmask & LUA_MASKCALL) { - L->savedpc++; /* hooks assume 'pc' is already incremented */ -@@ -354,8 +354,8 @@ int luaD_poscall (lua_State *L, StkId fi - for (i = wanted; i != 0 && firstResult < L->top; i--) - setobjs2s(L, res++, firstResult++); - while (i-- > 0) -- setnilvalue(res++); -- L->top = res; -+ setnilvalue(L, res++); -+ setlvmtop(L, res); - return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */ - } - -@@ -463,8 +463,12 @@ int luaD_pcall (lua_State *L, Pfunc func - status = luaD_rawrunprotected(L, func, u); - if (status != 0) { /* an error occurred? */ - StkId oldtop = restorestack(L, old_top); -+ StkId curtop = L->top; -+ int i; - luaF_close(L, oldtop); /* close eventual pending closures */ - luaD_seterrorobj(L, status, oldtop); -+ for (i = (curtop - L->top); i-- > 0;) -+ setnilvalue(L, L->top + i); - L->nCcalls = oldnCcalls; - L->ci = restoreci(L, old_ci); - L->base = L->ci->base; ---- a/src/lfunc.c -+++ b/src/lfunc.c -@@ -17,7 +17,7 @@ - #include "lmem.h" - #include "lobject.h" - #include "lstate.h" -- -+#include "lvm.h" - - - Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) { -@@ -45,7 +45,7 @@ UpVal *luaF_newupval (lua_State *L) { - UpVal *uv = luaM_new(L, UpVal); - luaC_link(L, obj2gco(uv), LUA_TUPVAL); - uv->v = &uv->u.value; -- setnilvalue(uv->v); -+ setnilvalue(L, uv->v); - return uv; - } - -@@ -67,8 +67,14 @@ UpVal *luaF_findupval (lua_State *L, Stk - uv = luaM_new(L, UpVal); /* not found: create a new one */ - uv->tt = LUA_TUPVAL; - uv->marked = luaC_white(g); -- uv->v = level; /* current value lives in the stack */ -+ uv->v = luaV_ref(level); /* current value lives in the stack */ - uv->next = *pp; /* chain it in the proper position */ -+ if (uv->next) { -+ uv->prev = uv->next->gch.prev; -+ uv->next->gch.prev = (GCObject *)uv; -+ } else { -+ uv->prev = NULL; -+ } - *pp = obj2gco(uv); - uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ - uv->u.l.next = g->uvhead.u.l.next; ---- a/src/lgc.c -+++ b/src/lgc.c -@@ -21,6 +21,7 @@ - #include "lstring.h" - #include "ltable.h" - #include "ltm.h" -+#include "lvm.h" - - - #define GCSTEPSIZE 1024u -@@ -265,7 +266,7 @@ static void traversestack (global_State - for (o = l->stack; o < l->top; o++) - markvalue(g, o); - for (; o <= lim; o++) -- setnilvalue(o); -+ setnilvalue(l, o); - checkstacksizes(l, lim); - } - -@@ -348,7 +349,7 @@ static int iscleared (const TValue *o, i - /* - ** clear collected entries from weaktables - */ --static void cleartable (GCObject *l) { -+static void cleartable (lua_State *L, GCObject *l) { - while (l) { - Table *h = gco2h(l); - int i = h->sizearray; -@@ -358,7 +359,7 @@ static void cleartable (GCObject *l) { - while (i--) { - TValue *o = &h->array[i]; - if (iscleared(o, 0)) /* value was collected? */ -- setnilvalue(o); /* remove value */ -+ setnilvalue(L, o); /* remove value */ - } - } - i = sizenode(h); -@@ -366,7 +367,7 @@ static void cleartable (GCObject *l) { - Node *n = gnode(h, i); - if (!ttisnil(gval(n)) && /* non-empty entry? */ - (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) { -- setnilvalue(gval(n)); /* remove value ... */ -+ setnilvalue(L, gval(n)); /* remove value ... */ - removeentry(n); /* remove entry from table */ - } - } -@@ -375,7 +376,7 @@ static void cleartable (GCObject *l) { - } - - --static void freeobj (lua_State *L, GCObject *o) { -+void luaC_freeobj (lua_State *L, GCObject *o) { - switch (o->gch.tt) { - case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; - case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; -@@ -418,10 +419,12 @@ static GCObject **sweeplist (lua_State * - } - else { /* must erase `curr' */ - lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); -+ if (curr->gch.next) -+ curr->gch.next->gch.prev = curr->gch.prev; - *p = curr->gch.next; - if (curr == g->rootgc) /* is the first element of the list? */ - g->rootgc = curr->gch.next; /* adjust first */ -- freeobj(L, curr); -+ luaC_freeobj(L, curr); - } - } - return p; -@@ -543,7 +546,7 @@ static void atomic (lua_State *L) { - udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */ - marktmu(g); /* mark `preserved' userdata */ - udsize += propagateall(g); /* remark, to propagate `preserveness' */ -- cleartable(g->weak); /* remove collected objects from weak tables */ -+ cleartable(L, g->weak); /* remove collected objects from weak tables */ - /* flip current white */ - g->currentwhite = cast_byte(otherwhite(g)); - g->sweepstrgc = 0; -@@ -685,8 +688,11 @@ void luaC_barrierback (lua_State *L, Tab - - void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { - global_State *g = G(L); -+ o->gch.prev = (GCObject*)&g->rootgc; - o->gch.next = g->rootgc; - g->rootgc = o; -+ if (o->gch.next) -+ o->gch.next->gch.prev = o; - o->gch.marked = luaC_white(g); - o->gch.tt = tt; - } ---- a/src/lgc.h -+++ b/src/lgc.h -@@ -105,6 +105,6 @@ LUAI_FUNC void luaC_link (lua_State *L, - LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); - LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); - LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); -- -+LUAI_FUNC void luaC_freeobj (lua_State *L, GCObject *o); - - #endif ---- a/src/lmem.c -+++ b/src/lmem.c -@@ -6,6 +6,7 @@ - - - #include -+#include - - #define lmem_c - #define LUA_CORE -@@ -80,6 +81,8 @@ void *luaM_realloc_ (lua_State *L, void - if (block == NULL && nsize > 0) - luaD_throw(L, LUA_ERRMEM); - lua_assert((nsize == 0) == (block == NULL)); -+ if (nsize > osize) -+ memset((char *)block + osize, 0, nsize - osize); - g->totalbytes = (g->totalbytes - osize) + nsize; - return block; - } ---- a/src/lobject.h -+++ b/src/lobject.h -@@ -44,7 +44,7 @@ typedef union GCObject GCObject; - ** Common Header for all collectable objects (in macro form, to be - ** included in other objects) - */ --#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked -+#define CommonHeader GCObject *next; GCObject *prev; lu_byte tt; lu_byte marked - - - /* -@@ -83,6 +83,7 @@ typedef struct lua_TValue { - TValuefields; - } TValue; - -+#define tvinit() { .value.b = 0, .tt = 0 } - - /* Macros to test type */ - #define ttisnil(o) (ttype(o) == LUA_TNIL) -@@ -145,15 +146,15 @@ typedef struct lua_TValue { - - - /* Macros to set values */ --#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) -+#define setnilvalue(L, obj) (luaV_unref(L, (obj))->tt=LUA_TNIL) - - /* Must not have side effects, 'x' may be expression. - */ - #define setivalue(obj,x) \ -- { TValue *i_o=(obj); i_o->value.i=(x); i_o->tt=LUA_TINT; } -+ { TValue *i_o=luaV_unref(L, (obj)); i_o->value.i=(x); i_o->tt=LUA_TINT; } - - # define setnvalue(obj,x) \ -- { TValue *i_o=(obj); i_o->value.n= (x); i_o->tt=LUA_TNUMBER; } -+ { TValue *i_o=luaV_unref(L, (obj)); i_o->value.n= (x); i_o->tt=LUA_TNUMBER; } - - /* Note: Complex always has "inline", both are C99. - */ -@@ -170,45 +171,45 @@ typedef struct lua_TValue { - - - #define setpvalue(obj,x) \ -- { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } -+ { TValue *i_o=luaV_unref(L, (obj)); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } - - #define setbvalue(obj,x) \ -- { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } -+ { TValue *i_o=luaV_unref(L, (obj)); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } - - #define setsvalue(L,obj,x) \ -- { TValue *i_o=(obj); \ -- i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \ -+ { TValue *i_o=(obj); TString *val=(x); luaS_ref(val); luaV_unref(L, obj); \ -+ i_o->value.gc=cast(GCObject *, (val)); i_o->tt=LUA_TSTRING; \ - checkliveness(G(L),i_o); } - - #define setuvalue(L,obj,x) \ -- { TValue *i_o=(obj); \ -+ { TValue *i_o=luaV_unref(L, (obj)); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \ - checkliveness(G(L),i_o); } - - #define setthvalue(L,obj,x) \ -- { TValue *i_o=(obj); \ -+ { TValue *i_o=luaV_unref(L, (obj)); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \ - checkliveness(G(L),i_o); } - - #define setclvalue(L,obj,x) \ -- { TValue *i_o=(obj); \ -+ { TValue *i_o=luaV_unref(L, (obj)); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \ - checkliveness(G(L),i_o); } - - #define sethvalue(L,obj,x) \ -- { TValue *i_o=(obj); \ -+ { TValue *i_o=luaV_unref(L, (obj)); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \ - checkliveness(G(L),i_o); } - - #define setptvalue(L,obj,x) \ -- { TValue *i_o=(obj); \ -+ { TValue *i_o=luaV_unref(L, (obj)); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ - checkliveness(G(L),i_o); } - - #define setobj(L,obj1,obj2) \ -- { const TValue *o2=(obj2); TValue *o1=(obj1); \ -+ do { const TValue *o2=luaV_ref((TValue *)(obj2)); TValue *o1=luaV_unref(L, (obj1)); \ - o1->value = o2->value; o1->tt=o2->tt; \ -- checkliveness(G(L),o1); } -+ checkliveness(G(L),o1); } while(0) - - - /* -@@ -253,6 +254,7 @@ typedef union TString { - lu_byte reserved; - unsigned int hash; - size_t len; -+ int refcount; - } tsv; - } TString; - -@@ -409,6 +411,7 @@ typedef struct Table { - #define twoto(x) (1<<(x)) - #define sizenode(t) (twoto((t)->lsizenode)) - -+#include "lstring.h" - - #define luaO_nilobject (&luaO_nilobject_) - ---- a/src/lparser.c -+++ b/src/lparser.c -@@ -24,6 +24,7 @@ - #include "lstate.h" - #include "lstring.h" - #include "ltable.h" -+#include "lvm.h" - - - -@@ -146,7 +147,7 @@ static int registerlocalvar (LexState *l - luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, - LocVar, SHRT_MAX, "too many local variables"); - while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; -- f->locvars[fs->nlocvars].varname = varname; -+ f->locvars[fs->nlocvars].varname = luaS_ref(varname); - luaC_objbarrier(ls->L, f, varname); - return fs->nlocvars++; - } -@@ -194,7 +195,7 @@ static int indexupvalue (FuncState *fs, - luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues, - TString *, MAX_INT, ""); - while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL; -- f->upvalues[f->nups] = name; -+ f->upvalues[f->nups] = luaS_ref(name); - luaC_objbarrier(fs->L, f, name); - lua_assert(v->k == VLOCAL || v->k == VUPVAL); - fs->upvalues[f->nups].k = cast_byte(v->k); -@@ -341,7 +342,7 @@ static void open_func (LexState *ls, Fun - fs->nlocvars = 0; - fs->nactvar = 0; - fs->bl = NULL; -- f->source = ls->source; -+ f->source = luaS_ref(ls->source); - f->maxstacksize = 2; /* registers 0/1 are always valid */ - fs->h = luaH_new(L, 0, 0); - /* anchor table of constants and prototype (to avoid being collected) */ ---- a/src/lstate.c -+++ b/src/lstate.c -@@ -22,6 +22,7 @@ - #include "lstring.h" - #include "ltable.h" - #include "ltm.h" -+#include "lvm.h" - - - #define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) -@@ -52,7 +53,7 @@ static void stack_init (lua_State *L1, l - L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; - /* initialize first ci */ - L1->ci->func = L1->top; -- setnilvalue(L1->top++); /* `function' entry for this `ci' */ -+ setnilvalue(L1, L1->top++); /* `function' entry for this `ci' */ - L1->base = L1->ci->base = L1->top; - L1->ci->top = L1->top + LUA_MINSTACK; - } -@@ -98,7 +99,7 @@ static void preinit_state (lua_State *L, - L->base_ci = L->ci = NULL; - L->savedpc = NULL; - L->errfunc = 0; -- setnilvalue(gt(L)); -+ setnilvalue(L, gt(L)); - } - - -@@ -163,7 +164,7 @@ LUA_API lua_State *lua_newstate (lua_All - g->strt.size = 0; - g->strt.nuse = 0; - g->strt.hash = NULL; -- setnilvalue(registry(L)); -+ setnilvalue(L, registry(L)); - luaZ_initbuffer(L, &g->buff); - g->panic = NULL; - g->gcstate = GCSpause; ---- a/src/lstring.c -+++ b/src/lstring.c -@@ -37,6 +37,9 @@ void luaS_resize (lua_State *L, int news - int h1 = lmod(h, newsize); /* new position */ - lua_assert(cast_int(h%newsize) == lmod(h, newsize)); - p->gch.next = newhash[h1]; /* chain it */ -+ if (p->gch.next) -+ p->gch.next->gch.prev = p; -+ p->gch.prev = NULL; - newhash[h1] = p; - p = next; - } -@@ -59,11 +62,15 @@ static TString *newlstr (lua_State *L, c - ts->tsv.marked = luaC_white(G(L)); - ts->tsv.tt = LUA_TSTRING; - ts->tsv.reserved = 0; -+ ts->tsv.refcount = 0; - memcpy(ts+1, str, l*sizeof(char)); - ((char *)(ts+1))[l] = '\0'; /* ending 0 */ - tb = &G(L)->strt; - h = lmod(h, tb->size); - ts->tsv.next = tb->hash[h]; /* chain new entry */ -+ if (ts->tsv.next) -+ ts->tsv.next->gch.prev = (GCObject *)ts; -+ ts->tsv.prev = NULL; - tb->hash[h] = obj2gco(ts); - tb->nuse++; - if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) -@@ -109,3 +116,29 @@ Udata *luaS_newudata (lua_State *L, size - return u; - } - -+void luaS_unref(lua_State *L, TString *ts) { -+ if (!L || !ts) -+ return; -+ if (testbit(ts->tsv.marked, FIXEDBIT)) -+ return; -+ ts->tsv.refcount--; -+ if (ts->tsv.refcount < 0) { -+ fprintf(stderr, "REFCOUNT BUG, COUNT=%d, str=%s, len=%d\n", ts->tsv.refcount, (char *) (ts + 1), (int) ts->tsv.len); -+ } else if (ts->tsv.refcount) -+ return; -+ -+ if (ts->tsv.prev) { -+ ts->tsv.prev->gch.next = ts->tsv.next; -+ } else { -+ unsigned int idx = lmod(ts->tsv.hash, G(L)->strt.size); -+ lua_assert(G(L)->strt.hash[index] == (GCObject*)ts); -+ G(L)->strt.hash[idx] = ts->tsv.next; -+ } -+ -+ if (ts->tsv.next) -+ ts->tsv.next->gch.prev = ts->tsv.prev; -+ -+ luaC_freeobj(L, (GCObject *) ts); -+} -+ -+ ---- a/src/lstring.h -+++ b/src/lstring.h -@@ -7,7 +7,7 @@ - #ifndef lstring_h - #define lstring_h - -- -+#include - #include "lgc.h" - #include "lobject.h" - #include "lstate.h" -@@ -23,6 +23,12 @@ - - #define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) - -+static inline TString *luaS_ref(TString *ts) { -+ ts->tsv.refcount++; -+ return ts; -+} -+ -+LUA_API void luaS_unref(lua_State *L, TString *ts); - LUAI_FUNC void luaS_resize (lua_State *L, int newsize); - LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); - LUA_API TString *luaS_newlstr (lua_State *L, const char *str, size_t l); ---- a/src/ltable.c -+++ b/src/ltable.c -@@ -34,6 +34,7 @@ - #include "lstate.h" - #include "ltable.h" - #include "lnum.h" -+#include "lvm.h" - - - /* -@@ -278,7 +279,7 @@ static void setarrayvector (lua_State *L - int i; - luaM_reallocvector(L, t->array, t->sizearray, size, TValue); - for (i=t->sizearray; iarray[i]); -+ setnilvalue(L, &t->array[i]); - t->sizearray = size; - } - -@@ -299,8 +300,8 @@ static void setnodevector (lua_State *L, - for (i=0; ilsizenode = cast_byte(lsize); -@@ -427,9 +428,11 @@ static TValue *newkey (lua_State *L, Tab - othern = gnext(othern); /* find previous */ - } - gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ -+ luaV_ref((TValue *) gkey(mp)); -+ luaV_ref(gval(mp)); - *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ - gnext(mp) = NULL; /* now `mp' is free */ -- setnilvalue(gval(mp)); -+ setnilvalue(L, gval(mp)); - } - else { /* colliding node is in its own main position */ - /* new node will go into free position */ -@@ -438,6 +441,7 @@ static TValue *newkey (lua_State *L, Tab - mp = n; - } - } -+ luaV_ref((TValue *) key); - gkey(mp)->value = key->value; gkey(mp)->tt = key->tt; - luaC_barriert(L, t, key); - lua_assert(ttisnil(gval(mp))); -@@ -530,7 +534,7 @@ TValue *luaH_setint (lua_State *L, Table - if (p != luaO_nilobject) - return cast(TValue *, p); - else { -- TValue k; -+ TValue k = tvinit(); - setivalue(&k, key); - return newkey(L, t, &k); - } -@@ -542,7 +546,7 @@ TValue *luaH_setstr (lua_State *L, Table - if (p != luaO_nilobject) - return cast(TValue *, p); - else { -- TValue k; -+ TValue k = tvinit(); - setsvalue(L, &k, key); - return newkey(L, t, &k); - } ---- a/src/luac.c -+++ b/src/luac.c -@@ -20,8 +20,9 @@ - #include "lmem.h" - #include "lobject.h" - #include "lopcodes.h" --#include "lstring.h" - #include "lundump.h" -+#include "lvm.h" -+#include "lstring.h" - - #define PROGNAME "luac" /* default program name */ - #define OUTPUT PROGNAME ".out" /* default output file */ ---- a/src/lundump.c -+++ b/src/lundump.c -@@ -19,6 +19,7 @@ - #include "lstring.h" - #include "lundump.h" - #include "lzio.h" -+#include "lvm.h" - - typedef struct { - lua_State* L; -@@ -133,7 +134,7 @@ static TString* LoadString(LoadState* S) - { - char* s=luaZ_openspace(S->L,S->b,size); - LoadBlock(S,s,size); -- return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ -+ return luaS_ref(luaS_newlstr(S->L,s,size-1)); /* remove trailing '\0' */ - } - } - -@@ -149,11 +150,12 @@ static Proto* LoadFunction(LoadState* S, - - static void LoadConstants(LoadState* S, Proto* f) - { -+ lua_State *L = S->L; - int i,n; - n=LoadInt(S); - f->k=luaM_newvector(S->L,n,TValue); - f->sizek=n; -- for (i=0; ik[i]); -+ for (i=0; ik[i]); - for (i=0; ik[i]; -@@ -161,7 +163,7 @@ static void LoadConstants(LoadState* S, - switch (t) - { - case LUA_TNIL: -- setnilvalue(o); -+ setnilvalue(L, o); - break; - case LUA_TBOOLEAN: - setbvalue(o,LoadChar(S)!=0); -@@ -229,6 +231,7 @@ static Proto* LoadFunction(LoadState* S, - LoadDebug(S,f); - IF (!luaG_checkcode(f), "bad code"); - S->L->top--; -+ setnilvalue(S->L, S->L->top); - S->L->nCcalls--; - return f; - } ---- a/src/lvm.c -+++ b/src/lvm.c -@@ -39,6 +39,7 @@ - * If 'obj' is a string, it is tried to be interpreted as a number. - */ - const TValue *luaV_tonumber ( const TValue *obj, TValue *n) { -+ lua_State *L = NULL; /* FIXME */ - lua_Number d; - lua_Integer i; - -@@ -384,6 +385,7 @@ void luaV_concat (lua_State *L, int tota - size_t l = tsvalue(top-i)->len; - memcpy(buffer+tl, svalue(top-i), l); - tl += l; -+ setnilvalue(L, top - i); - } - setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); - } -@@ -420,7 +422,7 @@ void luaV_concat (lua_State *L, int tota - */ - static void Arith (lua_State *L, StkId ra, const TValue *rb, - const TValue *rc, TMS op) { -- TValue tempb, tempc; -+ TValue tempb = tvinit(), tempc = tvinit(); - const TValue *b, *c; - lua_Number nb,nc; - -@@ -663,7 +665,7 @@ void luaV_execute (lua_State *L, int nex - OPCODE_TARGET(LOADNIL) { - TValue *rb = RB(i); - do { -- setnilvalue(rb--); -+ setnilvalue(L, rb--); - } while (rb >= ra); - continue; - } -@@ -673,7 +675,7 @@ void luaV_execute (lua_State *L, int nex - continue; - } - OPCODE_TARGET(GETGLOBAL) { -- TValue g; -+ TValue g = tvinit(); - TValue *rb = KBx(i); - sethvalue(L, &g, cl->env); - lua_assert(ttisstring(rb)); -@@ -685,7 +687,7 @@ void luaV_execute (lua_State *L, int nex - continue; - } - OPCODE_TARGET(SETGLOBAL) { -- TValue g; -+ TValue g = tvinit(); - sethvalue(L, &g, cl->env); - lua_assert(ttisstring(KBx(i))); - Protect(luaV_settable(L, &g, KBx(i), ra)); -@@ -895,7 +897,7 @@ void luaV_execute (lua_State *L, int nex - if (--nexeccalls == 0) /* was previous function running `here'? */ - return; /* no: return */ - else { /* yes: continue its execution */ -- if (b) L->top = L->ci->top; -+ if (b) setlvmtop(L, L->ci->top); - lua_assert(isLua(L->ci)); - lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL); - goto reentry; -@@ -986,6 +988,7 @@ void luaV_execute (lua_State *L, int nex - for (; n > 0; n--) { - TValue *val = ra+n; - setobj2t(L, luaH_setint(L, h, last--), val); -+ setnilvalue(L, val); - luaC_barriert(L, h, val); - } - continue; -@@ -1030,7 +1033,7 @@ void luaV_execute (lua_State *L, int nex - setobjs2s(L, ra + j, ci->base - n + j); - } - else { -- setnilvalue(ra + j); -+ setnilvalue(L, ra + j); - } - } - continue; ---- a/src/lvm.h -+++ b/src/lvm.h -@@ -11,6 +11,7 @@ - #include "ldo.h" - #include "lobject.h" - #include "ltm.h" -+#include "lstring.h" - - - #define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) -@@ -19,6 +20,19 @@ - - #define equalobj(L,o1,o2) (ttype_ext_same(o1,o2) && luaV_equalval(L, o1, o2)) - -+static inline TValue *luaV_ref(TValue *tv) -+{ -+ if (ttisstring(tv)) -+ luaS_ref(rawtsvalue(tv)); -+ return tv; -+} -+ -+static inline TValue *luaV_unref(lua_State *L, TValue *tv) -+{ -+ if (ttisstring(tv)) -+ luaS_unref(L, rawtsvalue(tv)); -+ return tv; -+} - - LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); - LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2); ---- a/src/llex.c -+++ b/src/llex.c -@@ -23,6 +23,7 @@ - #include "ltable.h" - #include "lzio.h" - #include "lnum.h" -+#include "lvm.h" - - - -@@ -69,7 +70,7 @@ static void save (LexState *ls, int c) { - void luaX_init (lua_State *L) { - int i; - for (i=0; itsv.reserved = cast_byte(i+1); /* reserved word */ -@@ -125,7 +126,7 @@ void luaX_syntaxerror (LexState *ls, con - - TString *luaX_newstring (LexState *ls, const char *str, size_t l) { - lua_State *L = ls->L; -- TString *ts = luaS_newlstr(L, str, l); -+ TString *ts = luaS_ref(luaS_newlstr(L, str, l)); - TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */ - if (ttisnil(o)) - setbvalue(o, 1); /* make sure `str' will not be collected */ -@@ -152,7 +153,7 @@ void luaX_setinput (lua_State *L, LexSta - ls->fs = NULL; - ls->linenumber = 1; - ls->lastline = 1; -- ls->source = source; -+ ls->source = luaS_ref(source); - luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ - next(ls); /* read first char */ - } ---- a/src/lstate.h -+++ b/src/lstate.h -@@ -144,6 +144,13 @@ union GCObject { - struct lua_State th; /* thread */ - }; - -+#define setlvmtop(L, val) do { \ -+ int __i; \ -+ for (__i = L->top - val; __i-- > 0;) \ -+ setnilvalue(L, val + __i); \ -+ L->top = val; \ -+} while (0) -+ - - /* macros to convert a GCObject into a specific value */ - #define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) diff --git a/package/mac80211/Config.in.rt2x00 b/package/mac80211/Config.in.rt2x00 new file mode 100644 index 000000000..f9855145b --- /dev/null +++ b/package/mac80211/Config.in.rt2x00 @@ -0,0 +1,15 @@ +# rt2x00 configuration + +config PACKAGE_RT2X00_LIB_DEBUGFS + bool "Enable rt2x00 debugfs support" + depends PACKAGE_kmod-rt2x00-lib && PACKAGE_MAC80211_DEBUGFS + ---help--- + Enable creation of debugfs files for the rt2x00 drivers. + These debugfs files support both reading and writing of the + most important register types of the rt2x00 hardware. + +config PACKAGE_RT2X00_DEBUG + bool "Enable rt2x00 debug output" + depends PACKAGE_kmod-rt2x00-lib + ---help--- + Enable debugging output for all rt2x00 modules diff --git a/package/mac80211/Makefile b/package/mac80211/Makefile index 549e83896..d93c982f6 100644 --- a/package/mac80211/Makefile +++ b/package/mac80211/Makefile @@ -11,7 +11,7 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=mac80211 PKG_VERSION:=2010-03-24 -PKG_RELEASE:=3 +PKG_RELEASE:=5 PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources # http://www.orbit-lab.org/kernel/compat-wireless-2.6/2010/11 \ # http://wireless.kernel.org/download/compat-wireless-2.6 @@ -42,12 +42,12 @@ define KernelPackage/cfg80211 $(call KernelPackage/mac80211/Default) TITLE:=cfg80211 - wireless configuration API DEPENDS+= +wireless-tools +iw @!LINUX_2_6_25 -ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.33)),1) +ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.33)),1) FILES:= \ $(PKG_BUILD_DIR)/compat/compat.$(LINUX_KMOD_SUFFIX) \ $(PKG_BUILD_DIR)/net/wireless/cfg80211.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,20,compat cfg80211) -else +else FILES:= \ $(PKG_BUILD_DIR)/compat/compat.$(LINUX_KMOD_SUFFIX) \ $(PKG_BUILD_DIR)/compat/compat_firmware_class.$(LINUX_KMOD_SUFFIX) \ @@ -170,6 +170,11 @@ define Download/ar9170 endef $(eval $(call Download,ar9170)) +NEED_RT2X00_LIB_CRYPTO:=y +NEED_RT2X00_LIB_FIRMWARE:=y +NEED_RT2X00_LIB_HT:=y +NEED_RT2X00_LIB_LEDS:=y + define KernelPackage/rt2x00/Default $(call KernelPackage/mac80211/Default) TITLE:=Ralink Drivers for RT2x00 cards @@ -177,15 +182,19 @@ endef define KernelPackage/rt2x00-lib $(call KernelPackage/rt2x00/Default) - DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT) +kmod-mac80211 +kmod-crc-itu-t + DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT||TARGET_ramips) +kmod-mac80211 +kmod-crc-itu-t TITLE+= (LIB) FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00lib.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,25,rt2x00lib) endef +define KernelPackage/rt2x00-lib/config + source "$(SOURCE)/Config.in.rt2x00" +endef + define KernelPackage/rt2x00-pci $(call KernelPackage/rt2x00/Default) - DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-lib +kmod-eeprom-93cx6 + DEPENDS+= @(PCI_SUPPORT||TARGET_ramips) +kmod-rt2x00-lib +kmod-eeprom-93cx6 TITLE+= (PCI) FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00pci.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,26,rt2x00pci) @@ -199,9 +208,17 @@ $(call KernelPackage/rt2x00/Default) AUTOLOAD:=$(call AutoLoad,26,rt2x00usb) endef +define KernelPackage/rt2x00-soc +$(call KernelPackage/rt2x00/Default) + DEPENDS+= @TARGET_ramips +kmod-rt2x00-lib + TITLE+= (SoC) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00soc.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoLoad,26,rt2x00soc) +endef + define KernelPackage/rt2800-lib $(call KernelPackage/rt2x00/Default) - DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT) +kmod-rt2x00-lib +USB_SUPPORT:kmod-rt2x00-usb + DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT||TARGET_ramips) +kmod-rt2x00-lib +USB_SUPPORT:kmod-rt2x00-usb +TARGET_ramips:kmod-rt2x00-soc TITLE+= (rt2800 LIB) FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800lib.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,27,rt2800lib) @@ -249,7 +266,7 @@ endef define KernelPackage/rt2800-pci $(call KernelPackage/rt2x00/Default) - DEPENDS+= +kmod-rt2x00-pci +kmod-rt2800-lib +kmod-crc-ccitt + DEPENDS+= +kmod-rt2x00-pci +kmod-rt2800-lib +kmod-crc-ccitt +TARGET_ramips:kmod-rt2x00-soc TITLE+= (RT2860 PCI) FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800pci.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,28,rt2800pci) @@ -599,7 +616,18 @@ BUILDFLAGS:= \ $(if $(CONFIG_PACKAGE_ATH_DEBUG),-DCONFIG_ATH_DEBUG) \ -D__CONFIG_MAC80211_RC_DEFAULT=minstrel \ $(if $(CONFIG_ATH_USER_REGD),-DATH_USER_REGD=1) \ - $(if $(CONFIG_PACKAGE_ATH9K_USE_MINSTREL),-DATH9K_USE_MINSTREL) + $(if $(CONFIG_PACKAGE_ATH9K_USE_MINSTREL),-DATH9K_USE_MINSTREL) \ + $(if $(CONFIG_PACKAGE_RT2X00_LIB_DEBUGFS),-DCONFIG_RT2X00_LIB_DEBUGFS) \ + $(if $(CONFIG_PACKAGE_RT2X00_DEBUG),-DCONFIG_RT2X00_DEBUG) \ + $(if $(NEED_RT2X00_LIB_HT),-DCONFIG_RT2X00_LIB_HT) \ + $(if $(NEED_RT2X00_LIB_CRYPTO),-DCONFIG_RT2X00_LIB_CRYPTO) \ + $(if $(NEED_RT2X00_LIB_FIRMWARE),-DCONFIG_RT2X00_LIB_FIRMWARE) \ + $(if $(NEED_RT2X00_LIB_LEDS),-DCONFIG_RT2X00_LIB_LEDS) \ + $(if $(CONFIG_PACKAGE_kmod-rt2x00-pci),-DCONFIG_RT2X00_LIB_PCI) \ + $(if $(CONFIG_PACKAGE_kmod-rt2x00-usb),-DCONFIG_RT2X00_LIB_USB) \ + $(if $(CONFIG_PACKAGE_kmod-rt2x00-soc),-DCONFIG_RT2X00_LIB_SOC) \ + $(if $(CONFIG_PCI_SUPPORT),-DCONFIG_RT2800PCI_PCI) \ + $(if $(CONFIG_TARGET_ramips),-DCONFIG_RT2800PCI_SOC) \ MAKE_OPTS:= \ CROSS_COMPILE="$(KERNEL_CROSS)" \ @@ -638,6 +666,12 @@ MAKE_OPTS:= \ CONFIG_RT2X00_LIB=$(if $(CONFIG_PACKAGE_kmod-rt2x00-lib),m) \ CONFIG_RT2X00_LIB_PCI=$(if $(CONFIG_PACKAGE_kmod-rt2x00-pci),m) \ CONFIG_RT2X00_LIB_USB=$(if $(CONFIG_PACKAGE_kmod-rt2x00-usb),m) \ + CONFIG_RT2X00_LIB_SOC=$(if $(CONFIG_PACKAGE_kmod-rt2x00-soc),m) \ + CONFIG_RT2X00_LIB_DEBUGFS=$(CONFIG_PACKAGE_RT2X00_LIB_DEBUGFS) \ + CONFIG_RT2X00_LIB_CRYPTO=$(NEED_RT2X00_LIB_CRYPTO) \ + CONFIG_RT2X00_LIB_FIRMWARE=$(NEED_RT2X00_LIB_FIRMWARE) \ + CONFIG_RT2X00_LIB_HT=$(NEED_RT2X00_LIB_HT) \ + CONFIG_RT2X00_LIB_LEDS=$(NEED_RT2X00_LIB_LEDS) \ CONFIG_RT2400PCI=$(if $(CONFIG_PACKAGE_kmod-rt2400-pci),m) \ CONFIG_RT2500PCI=$(if $(CONFIG_PACKAGE_kmod-rt2500-pci),m) \ CONFIG_RT2500USB=$(if $(CONFIG_PACKAGE_kmod-rt2500-usb),m) \ @@ -645,6 +679,8 @@ MAKE_OPTS:= \ CONFIG_RT73USB=$(if $(CONFIG_PACKAGE_kmod-rt73-usb),m) \ CONFIG_RT2800_LIB=$(if $(CONFIG_PACKAGE_kmod-rt2800-lib),m) \ CONFIG_RT2800PCI=$(if $(CONFIG_PACKAGE_kmod-rt2800-pci),m) \ + CONFIG_RT2800PCI_PCI=$(if $(CONFIG_PCI_SUPPORT),y) \ + CONFIG_RT2800PCI_SOC=$(if $(CONFIG_TARGET_ramips),y) \ CONFIG_RT2800USB=$(if $(CONFIG_PACKAGE_kmod-rt2800-usb),m) \ CONFIG_RTL8180=$(if $(CONFIG_PACKAGE_kmod-rtl8180),m) \ CONFIG_RTL8187=$(if $(CONFIG_PACKAGE_kmod-rtl8187),m) \ @@ -843,6 +879,7 @@ $(eval $(call KernelPackage,p54-usb)) $(eval $(call KernelPackage,rt2x00-lib)) $(eval $(call KernelPackage,rt2x00-pci)) $(eval $(call KernelPackage,rt2x00-usb)) +$(eval $(call KernelPackage,rt2x00-soc)) $(eval $(call KernelPackage,rt2800-lib)) $(eval $(call KernelPackage,rt2400-pci)) $(eval $(call KernelPackage,rt2500-pci)) diff --git a/package/mac80211/patches/015-remove-rt2x00-options.patch b/package/mac80211/patches/015-remove-rt2x00-options.patch new file mode 100644 index 000000000..f980979cc --- /dev/null +++ b/package/mac80211/patches/015-remove-rt2x00-options.patch @@ -0,0 +1,26 @@ +--- a/config.mk ++++ b/config.mk +@@ -276,12 +276,12 @@ CONFIG_RTL8180=m + + CONFIG_ADM8211=m + +-CONFIG_RT2X00_LIB_PCI=m ++# CONFIG_RT2X00_LIB_PCI=m + CONFIG_RT2400PCI=m + CONFIG_RT2500PCI=m + ifneq ($(CONFIG_CRC_CCITT),) + CONFIG_RT2800PCI=m +-CONFIG_RT2800PCI_PCI=y ++# CONFIG_RT2800PCI_PCI=y + # CONFIG_RT2800PCI_RT30XX=y + # CONFIG_RT2800PCI_RT35XX=y + # CONFIG_RT2800PCI_SOC=y +@@ -381,7 +381,7 @@ CONFIG_RT2800USB=m + # CONFIG_RT2800USB_RT35XX=y + # CONFIG_RT2800USB_UNKNOWN=y + endif +-CONFIG_RT2X00_LIB_USB=m ++# CONFIG_RT2X00_LIB_USB=m + NEED_RT2X00=y + # RT73USB requires firmware + ifneq ($(CONFIG_CRC_ITU_T),) diff --git a/package/mac80211/patches/300-fix-mesh.patch b/package/mac80211/patches/300-fix-mesh.patch new file mode 100644 index 000000000..554565615 --- /dev/null +++ b/package/mac80211/patches/300-fix-mesh.patch @@ -0,0 +1,45 @@ +From 181ce6f71d907f42ab73376ce154015a835a6d8a Mon Sep 17 00:00:00 2001 +From: Javier Cardona +Date: Mon, 29 Mar 2010 11:00:20 -0700 +Subject: [PATCH] mac80211: Handle mesh action frames in ieee80211_rx_h_action + +This fixes the problem introduced in commit +8404080568613d93ad7cf0a16dfb68 which broke mesh peer link establishment. + +changes: +v2 Added missing break (Johannes) +v3 Broke original patch into two (Johannes) + +Signed-off-by: Javier Cardona +Signed-off-by: Hauke Mehrtens +--- + net/mac80211/mesh.c | 3 --- + net/mac80211/rx.c | 5 +++++ + 2 files changed, 5 insertions(+), 3 deletions(-) + +--- a/net/mac80211/mesh.c ++++ b/net/mac80211/mesh.c +@@ -749,9 +749,6 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_ + + switch (fc & IEEE80211_FCTL_STYPE) { + case IEEE80211_STYPE_ACTION: +- if (skb->len < IEEE80211_MIN_ACTION_SIZE) +- return RX_DROP_MONITOR; +- /* fall through */ + case IEEE80211_STYPE_PROBE_RESP: + case IEEE80211_STYPE_BEACON: + skb_queue_tail(&ifmsh->skb_queue, skb); +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1964,6 +1964,11 @@ ieee80211_rx_h_action(struct ieee80211_r + goto handled; + } + break; ++ case MESH_PLINK_CATEGORY: ++ case MESH_PATH_SEL_CATEGORY: ++ if (ieee80211_vif_is_mesh(&sdata->vif)) ++ return ieee80211_mesh_rx_mgmt(sdata, rx->skb); ++ break; + } + + /* diff --git a/package/mac80211/patches/600-rt2x00-disable-pci-code-if-CONFIG_PCI-not-defined.patch b/package/mac80211/patches/600-rt2x00-disable-pci-code-if-CONFIG_PCI-not-defined.patch new file mode 100644 index 000000000..3971413b0 --- /dev/null +++ b/package/mac80211/patches/600-rt2x00-disable-pci-code-if-CONFIG_PCI-not-defined.patch @@ -0,0 +1,18 @@ +--- a/drivers/net/wireless/rt2x00/rt2x00pci.c ++++ b/drivers/net/wireless/rt2x00/rt2x00pci.c +@@ -223,6 +223,7 @@ void rt2x00pci_uninitialize(struct rt2x0 + } + EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize); + ++#ifdef CONFIG_PCI + /* + * PCI driver handlers. + */ +@@ -397,6 +398,7 @@ int rt2x00pci_resume(struct pci_dev *pci + } + EXPORT_SYMBOL_GPL(rt2x00pci_resume); + #endif /* CONFIG_PM */ ++#endif /* CONFIG_PCI */ + + /* + * rt2x00pci module information. diff --git a/package/mac80211/patches/601-rt2x00-lib-use-rt2x00dev-irq.patch b/package/mac80211/patches/601-rt2x00-lib-use-rt2x00dev-irq.patch new file mode 100644 index 000000000..22bfc2ebe --- /dev/null +++ b/package/mac80211/patches/601-rt2x00-lib-use-rt2x00dev-irq.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/rt2x00/rt2x00pci.c ++++ b/drivers/net/wireless/rt2x00/rt2x00pci.c +@@ -213,7 +213,7 @@ void rt2x00pci_uninitialize(struct rt2x0 + /* + * Free irq line. + */ +- free_irq(to_pci_dev(rt2x00dev->dev)->irq, rt2x00dev); ++ free_irq(rt2x00dev->irq, rt2x00dev); + + /* + * Free DMA diff --git a/package/mac80211/patches/602-rt2x00-remove-mcu-requests-for-soc.patch b/package/mac80211/patches/602-rt2x00-remove-mcu-requests-for-soc.patch new file mode 100644 index 000000000..9cecf3a03 --- /dev/null +++ b/package/mac80211/patches/602-rt2x00-remove-mcu-requests-for-soc.patch @@ -0,0 +1,59 @@ +The ralink SoC platforms do not have an MCU. + +Signed-off-by: Luis Correia +--- + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -221,9 +221,9 @@ void rt2800_mcu_request(struct rt2x00_de + u32 reg; + + /* +- * SOC devices don't support MCU requests. ++ * some devices don't support MCU requests. + */ +- if (rt2x00_is_soc(rt2x00dev)) ++ if (!test_bit(DRIVER_REQUIRE_MCU, &rt2x00dev->flags)) + return; + + mutex_lock(&rt2x00dev->csr_mutex); +--- a/drivers/net/wireless/rt2x00/rt2800pci.c ++++ b/drivers/net/wireless/rt2x00/rt2800pci.c +@@ -60,6 +60,12 @@ static void rt2800pci_mcu_status(struct + unsigned int i; + u32 reg; + ++ /* ++ * some devices don't support MCU requests. ++ */ ++ if (!test_bit(DRIVER_REQUIRE_MCU, &rt2x00dev->flags)) ++ return; ++ + for (i = 0; i < 200; i++) { + rt2800_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); + +@@ -1098,10 +1104,12 @@ static int rt2800pci_probe_hw(struct rt2 + __set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags); + + /* +- * This device requires firmware. ++ * This device requires firmware and MCU access. + */ +- if (!rt2x00_is_soc(rt2x00dev)) ++ if (!rt2x00_is_soc(rt2x00dev)){ + __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); ++ __set_bit(DRIVER_REQUIRE_MCU, &rt2x00dev->flags); ++ } + __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); + if (!modparam_nohwcrypt) +--- a/drivers/net/wireless/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/rt2x00/rt2x00.h +@@ -631,6 +631,7 @@ enum rt2x00_flags { + * Driver requirements + */ + DRIVER_REQUIRE_FIRMWARE, ++ DRIVER_REQUIRE_MCU, + DRIVER_REQUIRE_BEACON_GUARD, + DRIVER_REQUIRE_ATIM_QUEUE, + DRIVER_REQUIRE_DMA, diff --git a/package/openssl/Makefile b/package/openssl/Makefile index e7a74905f..9f80a98f3 100644 --- a/package/openssl/Makefile +++ b/package/openssl/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=openssl PKG_VERSION:=0.9.8m -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=http://www.openssl.org/source/ \ diff --git a/package/openssl/patches/400-cve-2010-0740.patch b/package/openssl/patches/400-cve-2010-0740.patch new file mode 100644 index 000000000..4c893eb38 --- /dev/null +++ b/package/openssl/patches/400-cve-2010-0740.patch @@ -0,0 +1,15 @@ +--- a/ssl/s3_pkt.c ++++ b/ssl/s3_pkt.c +@@ -291,9 +291,9 @@ again: + if (version != s->version) + { + SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER); +- /* Send back error using their +- * version number :-) */ +- s->version=version; ++ if ((s->version & 0xFF00) == (version & 0xFF00)) ++ /* Send back error using their minor version number :-) */ ++ s->version = (unsigned short)version; + al=SSL_AD_PROTOCOL_VERSION; + goto f_err; + } diff --git a/package/uboot-ifxmips/Makefile b/package/uboot-ifxmips/Makefile index 932c17f41..6b78c3d0a 100644 --- a/package/uboot-ifxmips/Makefile +++ b/package/uboot-ifxmips/Makefile @@ -23,7 +23,7 @@ include $(INCLUDE_DIR)/package.mk define Package/uboot-ifxmips SECTION:=boot CATEGORY:=Boot Loaders - DEPENDS:=@TARGET_ifxmips + DEPENDS:=@TARGET_ifxmips @BROKEN TITLE:=U-Boot for Infineon MIPS boards URL:=http://www.denx.de/wiki/U-Boot endef diff --git a/package/uboot-lantiq/Config.in b/package/uboot-lantiq/Config.in new file mode 100644 index 000000000..e2c156d88 --- /dev/null +++ b/package/uboot-lantiq/Config.in @@ -0,0 +1,35 @@ +config UBOOT_TARGET + string "target" + default "easy50712_DDR166M" + depends on PACKAGE_uboot-lantiq + help + The configuration reflects the settings for a dedicated board hardware. + Select for Danube evaluation board easy50712_DDR166M . + Select for AR9 evaluation board easy50812_DDR166M . + +config UBOOT_RAMBOOT + bool "Enable RAM boot image" + depends on PACKAGE_uboot-lantiq + help + Using the UART boot mode of the ROM code this image could be loaded to the RAM. + While executing the image in the RAM the functionality of the uboot image can be + tested first without touching the original flash. + Note: Be carefull, by saving the environment the flash will be modified. + The OWRT flash layout differs from the layout provided by Lantiq / Infineon. + +config UBOOT_RAMBOOT_DDR_CONFIG + string "DDR configuration file" + default "easy50712_DDR166M.conf" + depends on UBOOT_RAMBOOT + help + The DDR configuration file should reflect the DDR memory device configuration . + It will be used to create a RAM boot image + Select for Danube evalution board easy50712_DDR166M.conf . + Select for AR9 evalution board easy50812.conf . + + +config UBOOT_A800 + bool "add ARV452 Switch bringup hack" + depends on PACKAGE_uboot-lantiq + help + Say Y, if you have a arv452 board (wav-281, A800, ..) diff --git a/package/uboot-lantiq/Makefile b/package/uboot-lantiq/Makefile index 3ffe8846e..fc7c65371 100644 --- a/package/uboot-lantiq/Makefile +++ b/package/uboot-lantiq/Makefile @@ -20,6 +20,10 @@ PKG_TARGETS:=bin include $(INCLUDE_DIR)/package.mk +ifeq ($(DUMP),) + STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell grep '^CONFIG_UBOOT_' $(TOPDIR)/.config | md5s) +endif + define Package/uboot-lantiq SECTION:=boot CATEGORY:=Boot Loaders @@ -35,12 +39,18 @@ define Build/Prepare find $(PKG_BUILD_DIR) -name .svn | $(XARGS) rm -rf endef -UBOOT_CONFIG:=easy50712_DDR166M +UBOOT_TARGET:=$(call qstrip,$(CONFIG_UBOOT_TARGET)) +UBOOT_RAMBOOT_DDR_CONFIG:=$(call qstrip,$(CONFIG_UBOOT_RAMBOOT_DDR_CONFIG)) + UBOOT_MAKE_OPTS:= \ CROSS_COMPILE=$(TARGET_CROSS) \ ENDIANNESS= \ V=1 +define Package/uboot-lantiq/config + source "$(SOURCE)/Config.in" +endef + define Build/Configure/Target $(MAKE) -s -C $(PKG_BUILD_DIR) \ $(UBOOT_MAKE_OPTS) \ @@ -49,8 +59,10 @@ define Build/Configure/Target endef define Build/Configure - $(call Build/Configure/Target,$(UBOOT_CONFIG)) - $(call Build/Configure/Target,$(UBOOT_CONFIG)_ramboot) + $(call Build/Configure/Target,$(UBOOT_TARGET)) +ifeq ($(CONFIG_UBOOT_RAMBOOT),y) + $(call Build/Configure/Target,$(UBOOT_TARGET)_ramboot) +endif endef define Build/Compile/Target @@ -61,22 +73,26 @@ define Build/Compile/Target endef define Build/Compile - $(call Build/Compile/Target,$(UBOOT_CONFIG)) - $(call Build/Compile/Target,$(UBOOT_CONFIG)_ramboot) + $(call Build/Compile/Target,$(UBOOT_TARGET)) +ifeq ($(CONFIG_UBOOT_RAMBOOT),y) + $(call Build/Compile/Target,$(UBOOT_TARGET)_ramboot) +endif endef define Package/uboot-lantiq/install - mkdir -p $(1)/$(UBOOT_CONFIG) + mkdir -p $(1)/$(UBOOT_TARGET) dd \ - if=$(PKG_BUILD_DIR)/$(UBOOT_CONFIG)/u-boot.bin \ - of=$(1)/$(UBOOT_CONFIG)/u-boot.bin \ + if=$(PKG_BUILD_DIR)/$(UBOOT_TARGET)/u-boot.bin \ + of=$(1)/$(UBOOT_TARGET)/u-boot.bin \ bs=64k conv=sync - if [ -e $(UBOOT_CONFIG).conf ]; then \ +ifeq ($(CONFIG_UBOOT_RAMBOOT),y) + if [ -e $(UBOOT_RAMBOOT_DDR_CONFIG) ]; then \ perl ./gct \ - $(UBOOT_CONFIG).conf \ - $(PKG_BUILD_DIR)/$(UBOOT_CONFIG)_ramboot/u-boot.srec \ - $(1)/$(UBOOT_CONFIG)/u-boot.asc; \ + $(UBOOT_RAMBOOT_DDR_CONFIG) \ + $(PKG_BUILD_DIR)/$(UBOOT_TARGET)_ramboot/u-boot.srec \ + $(1)/$(UBOOT_TARGET)/u-boot.asc; \ fi +endif endef $(eval $(call BuildPackage,uboot-lantiq)) diff --git a/package/uboot-lantiq/easy50812.conf b/package/uboot-lantiq/easy50812.conf new file mode 100644 index 000000000..d28198c2f --- /dev/null +++ b/package/uboot-lantiq/easy50812.conf @@ -0,0 +1,55 @@ +0xbf800060 0x0000000f +0xbf800010 0x00000000 +0xbf800020 0x00000000 +0xbf800200 0x00000002 +0xbf800210 0x00000000 +0xbf801000 0x00001b1b +0xbf801010 0x00000000 +0xbf801020 0x00000000 +0xbf801030 0x00000000 +0xbf801040 0x00000000 +0xbf801050 0x00000200 +0xbf801060 0x00000306 +0xbf801070 0x00000303 +0xbf801080 0x00000102 +0xbf801090 0x0000070a +0xbf8010a0 0x00000203 +0xbf8010b0 0x00000c02 +0xbf8010c0 0x000001c8 +0xbf8010d0 0x00000001 +0xbf8010e0 0x00000000 +0xbf8010f0 0x00000139 +0xbf801100 0x00002200 +0xbf801110 0x0000000d +0xbf801120 0x00000301 +0xbf801130 0x00000200 +0xbf801140 0x00000a04 +0xbf801150 0x00001800 +0xbf801160 0x00001818 +0xbf801170 0x00000000 +0xbf801180 0x00000059 +0xbf801190 0x00000000 +0xbf8011a0 0x00000000 +0xbf8011b0 0x00000000 +0xbf8011c0 0x00000514 +0xbf8011d0 0x00002d93 +0xbf8011e0 0x00008235 +0xbf8011f0 0x00000000 +0xbf801200 0x00000000 +0xbf801210 0x00000000 +0xbf801220 0x00000000 +0xbf801230 0x00000000 +0xbf801240 0x00000000 +0xbf801250 0x00000000 +0xbf801260 0x00000000 +0xbf801270 0x00000000 +0xbf801280 0x00000000 +0xbf801290 0x00000000 +0xbf8012a0 0x00000000 +0xbf8012b0 0x00000000 +0xbf8012c0 0x00000000 +0xbf8012d0 0x00000600 +0xbf8012e0 0x00000000 +0xbf800060 0x0000000d +0xbf801030 0x00000100 + diff --git a/package/uboot-lantiq/files/board/infineon/easy50712/danube.c b/package/uboot-lantiq/files/board/infineon/easy50712/danube.c index 473436692..0b33a3ad4 100644 --- a/package/uboot-lantiq/files/board/infineon/easy50712/danube.c +++ b/package/uboot-lantiq/files/board/infineon/easy50712/danube.c @@ -32,6 +32,9 @@ #include #include #include +#if defined(CONFIG_CMD_HTTPD) +#include +#endif extern ulong ifx_get_ddr_hz(void); extern ulong ifx_get_cpuclk(void); @@ -336,3 +339,56 @@ int board_eth_init(bd_t *bis) return 0; } +#if defined(CONFIG_CMD_HTTPD) +int do_http_upgrade(const unsigned char *data, const ulong size) +{ + char buf[128]; + + if(getenv ("ram_addr") == NULL) + return -1; + if(getenv ("kernel_addr") == NULL) + return -1; + /* check the image */ + if(run_command("imi ${ram_addr}", 0) < 0) { + return -1; + } + /* write the image to the flash */ + puts("http ugrade ...\n"); + sprintf(buf, "era ${kernel_addr} +0x%x; cp.b ${ram_addr} ${kernel_addr} 0x%x", size, size); + return run_command(buf, 0); +} + +int do_http_progress(const int state) +{ + /* toggle LED's here */ + switch(state) { + case HTTP_PROGRESS_START: + puts("http start\n"); + break; + case HTTP_PROGRESS_TIMEOUT: + puts("."); + break; + case HTTP_PROGRESS_UPLOAD_READY: + puts("http upload ready\n"); + break; + case HTTP_PROGRESS_UGRADE_READY: + puts("http ugrade ready\n"); + break; + case HTTP_PROGRESS_UGRADE_FAILED: + puts("http ugrade failed\n"); + break; + } + return 0; +} + +unsigned long do_http_tmp_address(void) +{ + char *s = getenv ("ram_addr"); + if (s) { + ulong tmp = simple_strtoul (s, NULL, 16); + return tmp; + } + return 0 /*0x80a00000*/; +} + +#endif diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/Makefile b/package/uboot-lantiq/files/board/infineon/easy50812/Makefile new file mode 100644 index 000000000..44d8ea344 --- /dev/null +++ b/package/uboot-lantiq/files/board/infineon/easy50812/Makefile @@ -0,0 +1,47 @@ +# +# (C) Copyright 2003-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# 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 $(TOPDIR)/config.mk + +LIB = $(obj)lib$(BOARD).a + +#COBJS := $(BOARD).o +COBJS-y += ar9.o + +SOBJS = lowlevel_init.o pmuenable.o + +SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS-y)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/ar9.c b/package/uboot-lantiq/files/board/infineon/easy50812/ar9.c new file mode 100644 index 000000000..d4cd049af --- /dev/null +++ b/package/uboot-lantiq/files/board/infineon/easy50812/ar9.c @@ -0,0 +1,619 @@ +/* +* (C) Copyright 2003 +* Wolfgang Denk, DENX Software Engineering, wd@denx.de. +* +* (C) Copyright 2010 +* Thomas Langer, Ralph Hempel +* +* See file CREDITS for list of people who contributed to this +* project. +* +* 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 +#include +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_CMD_HTTPD) +#include +#endif + +extern ulong ifx_get_ddr_hz(void); +extern ulong ifx_get_cpuclk(void); + +/* definitions for external PHYs / Switches */ +/* Split values into phy address and register address */ +#define PHYADDR(_reg) ((_reg >> 5) & 0xff), (_reg & 0x1f) + +/* IDs and registers of known external switches */ +#define ID_SAMURAI_0 0x1020 +#define ID_SAMURAI_1 0x0007 +#define SAMURAI_ID_REG0 0xA0 +#define SAMURAI_ID_REG1 0xA1 +#define ID_TANTOS 0x2599 + +#define RGMII_MODE 0 +#define MII_MODE 1 +#define REV_MII_MODE 2 +#define RED_MII_MODE_IC 3 /*Input clock */ +#define RGMII_MODE_100MB 4 +#define TURBO_REV_MII_MODE 6 /*Turbo Rev Mii mode */ +#define RED_MII_MODE_OC 7 /*Output clock */ +#define RGMII_MODE_10MB 8 + +#define mdelay(n) udelay((n)*1000) + +static void ar9_sw_chip_init(u8 port, u8 mode); +static void ar9_enable_sw_port(u8 port, u8 state); +static void ar9_configure_sw_port(u8 port, u8 mode); +static u16 ar9_smi_reg_read(u16 reg); +static u16 ar9_smi_reg_write(u16 reg, u16 data); +static char * const name = "lq_cpe_eth"; +static int external_switch_init(void); + +void _machine_restart(void) +{ + *AR9_RCU_RST_REQ |= AR9_RST_ALL; +} + +#ifdef CONFIG_SYS_RAMBOOT +phys_size_t initdram(int board_type) +{ + return get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, CONFIG_SYS_MAX_RAM); +} +#elif defined(CONFIG_USE_DDR_RAM) +phys_size_t initdram(int board_type) +{ + return (CONFIG_SYS_MAX_RAM); +} +#else + +static ulong max_sdram_size(void) /* per Chip Select */ +{ + /* The only supported SDRAM data width is 16bit. + */ +#define CFG_DW 4 + + /* The only supported number of SDRAM banks is 4. + */ +#define CFG_NB 4 + + ulong cfgpb0 = *AR9_SDRAM_MC_CFGPB0; + int cols = cfgpb0 & 0xF; + int rows = (cfgpb0 & 0xF0) >> 4; + ulong size = (1 << (rows + cols)) * CFG_DW * CFG_NB; + + return size; +} + +/* +* Check memory range for valid RAM. A simple memory test determines +* the actually available RAM size between addresses `base' and +* `base + maxsize'. +*/ + +static long int dram_size(long int *base, long int maxsize) +{ + volatile long int *addr; + ulong cnt, val; + ulong save[32]; /* to make test non-destructive */ + unsigned char i = 0; + + for (cnt = (maxsize / sizeof (long)) >> 1; cnt > 0; cnt >>= 1) { + addr = base + cnt; /* pointer arith! */ + + save[i++] = *addr; + *addr = ~cnt; + } + + /* write 0 to base address */ + addr = base; + save[i] = *addr; + *addr = 0; + + /* check at base address */ + if ((val = *addr) != 0) { + *addr = save[i]; + return (0); + } + + for (cnt = 1; cnt < maxsize / sizeof (long); cnt <<= 1) { + addr = base + cnt; /* pointer arith! */ + + val = *addr; + *addr = save[--i]; + + if (val != (~cnt)) { + return (cnt * sizeof (long)); + } + } + return (maxsize); +} + +phys_size_t initdram(int board_type) +{ + int rows, cols, best_val = *AR9_SDRAM_MC_CFGPB0; + ulong size, max_size = 0; + ulong our_address; + + /* load t9 into our_address */ + asm volatile ("move %0, $25" : "=r" (our_address) :); + + /* Can't probe for RAM size unless we are running from Flash. + * find out whether running from DRAM or Flash. + */ + if (CPHYSADDR(our_address) < CPHYSADDR(PHYS_FLASH_1)) + { + return max_sdram_size(); + } + + for (cols = 0x8; cols <= 0xC; cols++) + { + for (rows = 0xB; rows <= 0xD; rows++) + { + *AR9_SDRAM_MC_CFGPB0 = (0x14 << 8) | + (rows << 4) | cols; + size = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, + max_sdram_size()); + + if (size > max_size) + { + best_val = *AR9_SDRAM_MC_CFGPB0; + max_size = size; + } + } + } + + *AR9_SDRAM_MC_CFGPB0 = best_val; + return max_size; +} +#endif + +int checkboard (void) +{ + unsigned long chipid = *AR9_MPS_CHIPID; + int part_num; + + puts ("Board: "); + + part_num = AR9_MPS_CHIPID_PARTNUM_GET(chipid); + switch (part_num) + { + case 0x16C: + puts("ARX188 "); + break; + case 0x16D: + puts("ARX168 "); + break; + case 0x16F: + puts("ARX182 "); + break; + case 0x170: + puts("GRX188 "); + break; + case 0x171: + puts("GRX168 "); + break; + default: + printf ("unknown, chip part number 0x%03X ", part_num); + break; + } + printf ("V1.%ld, ", AR9_MPS_CHIPID_VERSION_GET(chipid)); + + printf("DDR Speed %ld MHz, ", ifx_get_ddr_hz()/1000000); + printf("CPU Speed %ld MHz\n", ifx_get_cpuclk()/1000000); + + return 0; +} + +#ifdef CONFIG_SKIP_LOWLEVEL_INIT +int board_early_init_f(void) +{ +#ifdef CONFIG_EBU_ADDSEL0 + (*AR9_EBU_ADDSEL0) = CONFIG_EBU_ADDSEL0; +#endif +#ifdef CONFIG_EBU_ADDSEL1 + (*AR9_EBU_ADDSEL1) = CONFIG_EBU_ADDSEL1; +#endif +#ifdef CONFIG_EBU_ADDSEL2 + (*AR9_EBU_ADDSEL2) = CONFIG_EBU_ADDSEL2; +#endif +#ifdef CONFIG_EBU_ADDSEL3 + (*AR9_EBU_ADDSEL3) = CONFIG_EBU_ADDSEL3; +#endif +#ifdef CONFIG_EBU_BUSCON0 + (*AR9_EBU_BUSCON0) = CONFIG_EBU_BUSCON0; +#endif +#ifdef CONFIG_EBU_BUSCON1 + (*AR9_EBU_BUSCON1) = CONFIG_EBU_BUSCON1; +#endif +#ifdef CONFIG_EBU_BUSCON2 + (*AR9_EBU_BUSCON2) = CONFIG_EBU_BUSCON2; +#endif +#ifdef CONFIG_EBU_BUSCON3 + (*AR9_EBU_BUSCON3) = CONFIG_EBU_BUSCON3; +#endif + + return 0; +} +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ + +int board_eth_init(bd_t *bis) +{ +#if defined(CONFIG_IFX_ETOP) + + *AR9_PMU_PWDCR &= 0xFFFFEFDF; + *AR9_PMU_PWDCR &= ~AR9_PMU_DMA; /* enable DMA from PMU */ + + if (lq_eth_initialize(bis) < 0) + return -1; + + *AR9_RCU_RST_REQ |= 1; + udelay(200000); + *AR9_RCU_RST_REQ &= (unsigned long)~1; + udelay(1000); + +#ifdef CONFIG_EXTRA_SWITCH + if (external_switch_init()<0) + return -1; +#endif /* CONFIG_EXTRA_SWITCH */ +#endif /* CONFIG_IFX_ETOP */ + + return 0; +} + +static void ar9_configure_sw_port(u8 port, u8 mode) +{ + if(port) + { + if (mode == 1) //MII mode + { + *AR9_GPIO_P2_ALTSEL0 = *AR9_GPIO_P2_ALTSEL0 | (0xf000); + *AR9_GPIO_P2_ALTSEL1 = *AR9_GPIO_P2_ALTSEL1 & ~(0xf000); + *AR9_GPIO_P2_DIR = (*AR9_GPIO_P2_DIR & ~(0xf000)) | 0x2000; + *AR9_GPIO_P2_OD = *AR9_GPIO_P2_OD | 0x2000; + } + else if(mode == 2 || mode == 6) //Rev Mii mode + { + *AR9_GPIO_P2_ALTSEL0 = *AR9_GPIO_P2_ALTSEL0 | (0xf000); + *AR9_GPIO_P2_ALTSEL1 = *AR9_GPIO_P2_ALTSEL1 & ~(0xf000); + *AR9_GPIO_P2_DIR = (*AR9_GPIO_P2_DIR | (0xf000)) & ~0x2000; + *AR9_GPIO_P2_OD = *AR9_GPIO_P2_OD | 0xd000; + } + } + else //Port 0 + { + if (mode == 1) //MII mode + { + *AR9_GPIO_P2_ALTSEL0 = *AR9_GPIO_P2_ALTSEL0 | (0x0303); + *AR9_GPIO_P2_ALTSEL1 = *AR9_GPIO_P2_ALTSEL1 & ~(0x0303); + *AR9_GPIO_P2_DIR = (*AR9_GPIO_P2_DIR & ~(0x0303)) | 0x0100; + *AR9_GPIO_P2_OD = *AR9_GPIO_P2_OD | 0x0100; + } + else if(mode ==2 || mode ==6) //Rev Mii mode + { + *AR9_GPIO_P2_ALTSEL0 = *AR9_GPIO_P2_ALTSEL0 | (0x0303); + *AR9_GPIO_P2_ALTSEL1 = *AR9_GPIO_P2_ALTSEL1 & ~(0x0303); + *AR9_GPIO_P2_DIR = (*AR9_GPIO_P2_DIR | (0x0303)) & ~0x0100; + *AR9_GPIO_P2_OD = *AR9_GPIO_P2_OD | 0x0203; + } + } +} + +/* +Call this function to place either MAC port 0 or 1 into working mode. +Parameters: +port - select ports 0 or 1. +state of interface : state +0: RGMII +1: MII +2: Rev MII +3: Reduce MII (input clock) +4: RGMII 100mb +5: Reserve +6: Turbo Rev MII +7: Reduce MII (output clock) +*/ +void ar9_enable_sw_port(u8 port, u8 state) +{ + REG32(AR9_SW_GCTL0) |= 0x80000000; + if (port == 0) + { + REG32(AR9_SW_RGMII_CTL) &= 0xffcffc0e ; + //#if AR9_REFBOARD_TANTOS + REG32(0xbf20302c) &= 0xffff81ff; + REG32(0xbf20302c) |= 4<<9 ; + //#endif + REG32(AR9_SW_RGMII_CTL) |= ((u32)(state &0x3))<<8; + if((state &0x3) == 0) + { + REG32(AR9_SW_RGMII_CTL) &= 0xfffffff3; + if(state == 4) + REG32(AR9_SW_RGMII_CTL) |= 0x4; + else + REG32(AR9_SW_RGMII_CTL) |= 0x8; + } + if(state == 6) + REG32(AR9_SW_RGMII_CTL) |= ((u32) (1<<20)); + if(state == 7) + REG32(AR9_SW_RGMII_CTL) |= ((u32) (1<<21)); + } +// *AR9_PPE32_ETOP_CFG = *AR9_PPE32_ETOP_CFG & 0xfffffffe; + else + { + REG32(AR9_SW_RGMII_CTL) &= 0xff303fff ; + REG32(AR9_SW_RGMII_CTL) |= ((u32)(state &0x3))<<18; + if((state &0x3) == 0) + { + REG32(AR9_SW_RGMII_CTL) &= 0xffffcfff; + if(state == 4) + REG32(AR9_SW_RGMII_CTL) |= 0x1000; + else + REG32(AR9_SW_RGMII_CTL) |= 0x2000; + } + if(state == 6) + REG32(AR9_SW_RGMII_CTL) |= ((u32) (1<<22)); + if(state == 7) + REG32(AR9_SW_RGMII_CTL) |= ((u32) (1<<23)); + } +} + +void pci_reset(void) +{ + int i,j; +#define AR9_V1_PCI_RST_FIX 1 +#if AR9_V1_PCI_RST_FIX // 5th June 2008 Add GPIO19 to control EJTAG_TRST + *AR9_GPIO_P1_ALTSEL0 = *AR9_GPIO_P1_ALTSEL0 & ~0x8; + *AR9_GPIO_P1_ALTSEL1 = *AR9_GPIO_P1_ALTSEL1 & ~0x8; + *AR9_GPIO_P1_DIR = *AR9_GPIO_P1_DIR | 0x8; + *AR9_GPIO_P1_OD = *AR9_GPIO_P1_OD | 0x8; + *AR9_GPIO_P1_OUT = *AR9_GPIO_P1_OUT | 0x8; + *AR9_GPIO_P0_ALTSEL0 = *AR9_GPIO_P0_ALTSEL0 & ~0x4000; + *AR9_GPIO_P0_ALTSEL1 = *AR9_GPIO_P0_ALTSEL1 & ~0x4000; + *AR9_GPIO_P0_DIR = *AR9_GPIO_P0_DIR | 0x4000; + *AR9_GPIO_P0_OD = *AR9_GPIO_P0_OD | 0x4000; + for(j=0;j<5;j++) { + *AR9_GPIO_P0_OUT = *AR9_GPIO_P0_OUT & ~0x4000; + for(i=0;i<0x10000;i++); + *AR9_GPIO_P0_OUT = *AR9_GPIO_P0_OUT | 0x4000; + for(i=0;i<0x10000;i++); + } + *AR9_GPIO_P0_DIR = *AR9_GPIO_P0_DIR & ~0x4000; + *AR9_GPIO_P1_DIR = *AR9_GPIO_P1_DIR & ~0x8; +#endif +} + +static u16 ar9_smi_reg_read(u16 reg) +{ + int i; + while(REG32(AR9_SW_MDIO_CTL) & 0x8000); + REG32(AR9_SW_MDIO_CTL) = 0x8000| 0x2<<10 | ((u32) (reg&0x3ff)) ; /*0x10=MDIO_OP_READ*/ + for(i=0;i<0x3fff;i++); + udelay(50); + while(REG32(AR9_SW_MDIO_CTL) & 0x8000); + return((u16) (REG32(AR9_SW_MDIO_DATA))); +} + +static u16 ar9_smi_reg_write(u16 reg, u16 data) +{ + int i; + while(REG32(AR9_SW_MDIO_CTL) & 0x8000); + REG32(AR9_SW_MDIO_CTL) = 0x8000| (((u32) data)<<16) | 0x01<<10 | ((u32) (reg&0x3ff)) ; /*0x01=MDIO_OP_WRITE*/ + for(i=0;i<0x3fff;i++); + udelay(50); + return 0; +} + +static void ar9_sw_chip_init(u8 port, u8 mode) +{ + int i; + u16 chipid; + + debug("\nsearching for switches ... "); + + asm("sync"); + pci_reset(); + + /* 25mhz clock out */ + *AR9_CGU_IFCCR &= ~(3<<10); + *AR9_GPIO_P0_ALTSEL0 = *AR9_GPIO_P0_ALTSEL0 | (1<<3); + *AR9_GPIO_P0_ALTSEL1 = *AR9_GPIO_P0_ALTSEL1 & ~(1<<3); + *AR9_GPIO_P0_DIR = *AR9_GPIO_P0_DIR | (1<<3); + *AR9_GPIO_P0_OD = *AR9_GPIO_P0_OD | (1<<3); + *AR9_GPIO_P2_ALTSEL0 = *AR9_GPIO_P2_ALTSEL0 & ~(1<<0); + *AR9_GPIO_P2_ALTSEL1 = *AR9_GPIO_P2_ALTSEL1 & ~(1<<0); + *AR9_GPIO_P2_DIR = *AR9_GPIO_P2_DIR | (1<<0); + *AR9_GPIO_P2_OD = *AR9_GPIO_P2_OD | (1<<0); + + *AR9_PMU_PWDCR = (*AR9_PMU_PWDCR & 0xFFFBDFDF) ; + *AR9_PMU_PWDCR = (*AR9_PMU_PWDCR & ~(AR9_PMU_DMA | AR9_PMU_SWITCH)); + *AR9_PMU_PWDCR = (*AR9_PMU_PWDCR | AR9_PMU_USB0 | AR9_PMU_USB0_P); + + *AR9_GPIO_P2_OUT &= ~(1<<0); + asm("sync"); + + ar9_configure_sw_port(port, mode); + ar9_enable_sw_port(port, mode); + REG32(AR9_SW_P0_CTL) |= 0x400000; /* disable mdio polling for tantos */ + asm("sync"); + + /*GPIO 55(P3.7) used as output, set high*/ + *AR9_GPIO_P3_OD |=(1<<7); + *AR9_GPIO_P3_DIR |= (1<<7); + *AR9_GPIO_P3_ALTSEL0 &=~(1<<7); + *AR9_GPIO_P3_ALTSEL1 &=~(1<<7); + asm("sync"); + udelay(10); + + *AR9_GPIO_P3_OUT &= ~(1<<7); + for(i=0;i<1000;i++) + udelay(110); + *AR9_GPIO_P3_OUT |=(1<<7); + udelay(100); + + if(port==0) + REG32(AR9_SW_P0_CTL) |= 0x40001; + else + REG32(AR9_SW_P1_CTL) |= 0x40001; + + REG32(AR9_SW_P2_CTL) |= 0x40001; + REG32(AR9_SW_PMAC_HD_CTL) |= 0x40000; /* enable CRC */ + + *AR9_GPIO_P2_ALTSEL0 = *AR9_GPIO_P2_ALTSEL0 | (0xc00); + *AR9_GPIO_P2_ALTSEL1 = *AR9_GPIO_P2_ALTSEL1 & ~(0xc00); + *AR9_GPIO_P2_DIR = *AR9_GPIO_P2_DIR | 0xc00; + *AR9_GPIO_P2_OD = *AR9_GPIO_P2_OD | 0xc00; + + asm("sync"); + chipid = (unsigned short)(ar9_smi_reg_read(0x101)); + printf("\nswitch chip id=%08x\n",chipid); + if (chipid != ID_TANTOS) { + debug("whatever detected\n"); + ar9_smi_reg_write(0x1,0x840f); + ar9_smi_reg_write(0x3,0x840f); + ar9_smi_reg_write(0x5,0x840f); + ar9_smi_reg_write(0x7,0x840f); + ar9_smi_reg_write(0x8,0x840f); + ar9_smi_reg_write(0x12,0x3602); +#ifdef CLK_OUT2_25MHZ + ar9_smi_reg_write(0x33,0x4000); +#endif + } else { // Tantos switch ship + debug("Tantos switch detected\n"); + ar9_smi_reg_write(0xa1,0x0004); /*port 5 force link up*/ + ar9_smi_reg_write(0xc1,0x0004); /*port 6 force link up*/ + ar9_smi_reg_write(0xf5,0x0BBB); /*port 4 duplex mode, flow control enable,1000Mbit/s*/ + /*port 5 duplex mode, flow control enable, 1000Mbit/s*/ + /*port 6 duplex mode, flow control enable, 1000Mbit/s*/ + } + asm("sync"); + + /*reset GPHY*/ + mdelay(200); + *AR9_RCU_RST_REQ |= (AR9_RCU_RST_REQ_DMA | AR9_RCU_RST_REQ_PPE) ; + udelay(50); + *AR9_GPIO_P2_OUT |= (1<<0); +} + +static void ar9_dma_init(void) +{ + /* select port */ + *AR9_DMA_PS = 0; + + /* + TXWGT 14:12 rw Port Weight for Transmit Direction (the default value “001”) + + TXENDI 11:10 rw Endianness for Transmit Direction + Determine a byte swap between memory interface (left hand side) and + peripheral interface (right hand side). + 00B B0_B1_B2_B3 No byte switching + 01B B1_B0_B3_B2 B0B1B2B3 => B1B0B3B2 + 10B B2_B3_B0_B1 B0B1B2B3 => B2B3B0B1 + + RXENDI 9:8 rw Endianness for Receive Direction + Determine a byte swap between peripheral (left hand side) and memory + interface (right hand side). + 00B B0_B1_B2_B3 No byte switching + 01B B1_B0_B3_B2 B0B1B2B3 => B1B0B3B2 + 10B B2_B3_B0_B1 B0B1B2B3 => B2B3B0B1 + 11B B3_B2_B1_B0 B0B1B2B3 => B3B2B1B0 + + TXBL 5:4 rw Burst Length for Transmit Direction + Selects burst length for TX direction. + Others are reserved and will result in 2_WORDS burst length. + 01B 2_WORDS 2 words + 10B 4_WORDS 4 words + 11B 8_WORDS 8 words + + RXBL 3:2 rw Burst Length for Receive Direction + Selects burst length for RX direction. + Others are reserved and will result in 2_WORDS burst length. + 01B 2_WORDS 2 words + 10B 4_WORDS 4 words + 11B 8_WORDS 8 words + */ + *AR9_DMA_PCTRL = 0x1f28; +} + +#ifdef CONFIG_EXTRA_SWITCH +static int external_switch_init(void) +{ + ar9_sw_chip_init(0, RGMII_MODE); + + ar9_dma_init(); + + return 0; +} +#endif /* CONFIG_EXTRA_SWITCH */ + +#if defined(CONFIG_CMD_HTTPD) +int do_http_upgrade(const unsigned char *data, const ulong size) +{ + char buf[128]; + + if(getenv ("ram_addr") == NULL) + return -1; + if(getenv ("kernel_addr") == NULL) + return -1; + /* check the image */ + if(run_command("imi ${ram_addr}", 0) < 0) { + return -1; + } + /* write the image to the flash */ + puts("http ugrade ...\n"); + sprintf(buf, "era ${kernel_addr} +0x%x; cp.b ${ram_addr} ${kernel_addr} 0x%x", size, size); + return run_command(buf, 0); +} + +int do_http_progress(const int state) +{ + /* toggle LED's here */ + switch(state) { + case HTTP_PROGRESS_START: + puts("http start\n"); + break; + case HTTP_PROGRESS_TIMEOUT: + puts("."); + break; + case HTTP_PROGRESS_UPLOAD_READY: + puts("http upload ready\n"); + break; + case HTTP_PROGRESS_UGRADE_READY: + puts("http ugrade ready\n"); + break; + case HTTP_PROGRESS_UGRADE_FAILED: + puts("http ugrade failed\n"); + break; + } + return 0; +} + +unsigned long do_http_tmp_address(void) +{ + char *s = getenv ("ram_addr"); + if (s) { + ulong tmp = simple_strtoul (s, NULL, 16); + return tmp; + } + return 0 /*0x80a00000*/; +} + +#endif diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr111_settings.h b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr111_settings.h new file mode 100644 index 000000000..766f1e00d --- /dev/null +++ b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr111_settings.h @@ -0,0 +1,51 @@ +/* Settings for Denali DDR SDRAM controller */ +/* Optimise for Samsung DDR K4H561638H Danube Ref Board DDR 166 Mhz - by Ng Aik Ann 27th Nov 2006 */ + +#define MC_DC0_VALUE 0x1B1B +#define MC_DC1_VALUE 0x0 +#define MC_DC2_VALUE 0x0 +#define MC_DC3_VALUE 0x0 +#define MC_DC4_VALUE 0x0 +#define MC_DC5_VALUE 0x200 +#define MC_DC6_VALUE 0x306 +#define MC_DC7_VALUE 0x303 +#define MC_DC8_VALUE 0x102 +#define MC_DC9_VALUE 0x70a +#define MC_DC10_VALUE 0x203 +#define MC_DC11_VALUE 0xc02 +#define MC_DC12_VALUE 0x1C8 +#define MC_DC13_VALUE 0x1 +#define MC_DC14_VALUE 0x0 +#define MC_DC15_VALUE 0x139 /* WDQS tuning for clk_wr*/ +#define MC_DC16_VALUE 0x2200 +#define MC_DC17_VALUE 0xd +#define MC_DC18_VALUE 0x301 +#define MC_DC19_VALUE 0x200 +#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */ +#define MC_DC21_VALUE 0x1800 +#define MC_DC22_VALUE 0x1818 +#define MC_DC23_VALUE 0x0 +#define MC_DC24_VALUE 0x59 /* WDQS Tuning for DQS */ +#define MC_DC25_VALUE 0x0 +#define MC_DC26_VALUE 0x0 +#define MC_DC27_VALUE 0x0 +#define MC_DC28_VALUE 0x514 +#define MC_DC29_VALUE 0x2d93 +#define MC_DC30_VALUE 0x8235 +#define MC_DC31_VALUE 0x0 +#define MC_DC32_VALUE 0x0 +#define MC_DC33_VALUE 0x0 +#define MC_DC34_VALUE 0x0 +#define MC_DC35_VALUE 0x0 +#define MC_DC36_VALUE 0x0 +#define MC_DC37_VALUE 0x0 +#define MC_DC38_VALUE 0x0 +#define MC_DC39_VALUE 0x0 +#define MC_DC40_VALUE 0x0 +#define MC_DC41_VALUE 0x0 +#define MC_DC42_VALUE 0x0 +#define MC_DC43_VALUE 0x0 +#define MC_DC44_VALUE 0x0 +#define MC_DC45_VALUE 0x600 +//#define MC_DC45_VALUE 0x400 +#define MC_DC46_VALUE 0x0 diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr166_settings.h b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr166_settings.h new file mode 100644 index 000000000..6d940ac6c --- /dev/null +++ b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr166_settings.h @@ -0,0 +1,51 @@ +/* Settings for Denali DDR SDRAM controller */ +/* Optimise for Samsung DDR K4H561638H Danube Ref Board DDR 166 Mhz - by Ng Aik Ann 27th Nov 2006 */ + +#define MC_DC0_VALUE 0x1B1B +#define MC_DC1_VALUE 0x0 +#define MC_DC2_VALUE 0x0 +#define MC_DC3_VALUE 0x0 +#define MC_DC4_VALUE 0x0 +#define MC_DC5_VALUE 0x200 +#define MC_DC6_VALUE 0x306 +#define MC_DC7_VALUE 0x303 +#define MC_DC8_VALUE 0x102 +#define MC_DC9_VALUE 0x70a +#define MC_DC10_VALUE 0x203 +#define MC_DC11_VALUE 0xc02 +#define MC_DC12_VALUE 0x1C8 +#define MC_DC13_VALUE 0x1 +#define MC_DC14_VALUE 0x0 +#define MC_DC15_VALUE 0x13f /* WDQS tuning for clk_wr*/ +#define MC_DC16_VALUE 0x2200 +#define MC_DC17_VALUE 0xd +#define MC_DC18_VALUE 0x301 +#define MC_DC19_VALUE 0x200 +#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */ +#define MC_DC21_VALUE 0x1600 +#define MC_DC22_VALUE 0x1616 +#define MC_DC23_VALUE 0x0 +#define MC_DC24_VALUE 0x5d /* WDQS Tuning for DQS */ +#define MC_DC25_VALUE 0x0 +#define MC_DC26_VALUE 0x0 +#define MC_DC27_VALUE 0x0 +#define MC_DC28_VALUE 0x514 +#define MC_DC29_VALUE 0x2d93 +#define MC_DC30_VALUE 0x8235 +#define MC_DC31_VALUE 0x0 +#define MC_DC32_VALUE 0x0 +#define MC_DC33_VALUE 0x0 +#define MC_DC34_VALUE 0x0 +#define MC_DC35_VALUE 0x0 +#define MC_DC36_VALUE 0x0 +#define MC_DC37_VALUE 0x0 +#define MC_DC38_VALUE 0x0 +#define MC_DC39_VALUE 0x0 +#define MC_DC40_VALUE 0x0 +#define MC_DC41_VALUE 0x0 +#define MC_DC42_VALUE 0x0 +#define MC_DC43_VALUE 0x0 +#define MC_DC44_VALUE 0x0 +#define MC_DC45_VALUE 0x600 +//#define MC_DC45_VALUE 0x400 +#define MC_DC46_VALUE 0x0 diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr196_settings.h b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr196_settings.h new file mode 100644 index 000000000..b00177e0a --- /dev/null +++ b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr196_settings.h @@ -0,0 +1,51 @@ +/* Settings for Denali DDR SDRAM controller */ +/* Optimise for Samsung DDR K4H561638H Danube Ref Board DDR 166 Mhz - by Ng Aik Ann 27th Nov 2006 */ + +#define MC_DC0_VALUE 0x1B1B +#define MC_DC1_VALUE 0x0 +#define MC_DC2_VALUE 0x0 +#define MC_DC3_VALUE 0x0 +#define MC_DC4_VALUE 0x0 +#define MC_DC5_VALUE 0x200 +#define MC_DC6_VALUE 0x306 +#define MC_DC7_VALUE 0x303 +#define MC_DC8_VALUE 0x102 +#define MC_DC9_VALUE 0x80B +#define MC_DC10_VALUE 0x203 +#define MC_DC11_VALUE 0xD02 +#define MC_DC12_VALUE 0x1C8 +#define MC_DC13_VALUE 0x1 +#define MC_DC14_VALUE 0x0 +#define MC_DC15_VALUE 0x144 /* WDQS tuning for clk_wr*/ +#define MC_DC16_VALUE 0xC800 +#define MC_DC17_VALUE 0xF +#define MC_DC18_VALUE 0x301 +#define MC_DC19_VALUE 0x200 +#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */ +#define MC_DC21_VALUE 0x1200 +#define MC_DC22_VALUE 0x1212 +#define MC_DC23_VALUE 0x0 +#define MC_DC24_VALUE 0x66 /* WDQS Tuning for DQS */ +#define MC_DC25_VALUE 0x0 +#define MC_DC26_VALUE 0x0 +#define MC_DC27_VALUE 0x0 +#define MC_DC28_VALUE 0x5FB +#define MC_DC29_VALUE 0x35DF +#define MC_DC30_VALUE 0x99E9 +#define MC_DC31_VALUE 0x0 +#define MC_DC32_VALUE 0x0 +#define MC_DC33_VALUE 0x0 +#define MC_DC34_VALUE 0x0 +#define MC_DC35_VALUE 0x0 +#define MC_DC36_VALUE 0x0 +#define MC_DC37_VALUE 0x0 +#define MC_DC38_VALUE 0x0 +#define MC_DC39_VALUE 0x0 +#define MC_DC40_VALUE 0x0 +#define MC_DC41_VALUE 0x0 +#define MC_DC42_VALUE 0x0 +#define MC_DC43_VALUE 0x0 +#define MC_DC44_VALUE 0x0 +#define MC_DC45_VALUE 0x600 +//#define MC_DC45_VALUE 0x400 +#define MC_DC46_VALUE 0x0 diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr221_settings.h b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr221_settings.h new file mode 100644 index 000000000..7f87d43f7 --- /dev/null +++ b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr221_settings.h @@ -0,0 +1,51 @@ +/* Settings for Denali DDR SDRAM controller */ +/* Optimise for AR9 Ref Board DDR 221 Mhz - by Ng Aik Ann 16th May 2008 */ + +#define MC_DC0_VALUE 0x1B1B +#define MC_DC1_VALUE 0x0 +#define MC_DC2_VALUE 0x0 +#define MC_DC3_VALUE 0x0 +#define MC_DC4_VALUE 0x0 +#define MC_DC5_VALUE 0x200 +#define MC_DC6_VALUE 0x306 +#define MC_DC7_VALUE 0x403 +#define MC_DC8_VALUE 0x102 +#define MC_DC9_VALUE 0x90c +#define MC_DC10_VALUE 0x203 +#define MC_DC11_VALUE 0xf02 +#define MC_DC12_VALUE 0x2c8 +#define MC_DC13_VALUE 0x1 +#define MC_DC14_VALUE 0x0 +#define MC_DC15_VALUE 0x12f /* WDQS tuning for clk_wr*/ +#define MC_DC16_VALUE 0xc800 +#define MC_DC17_VALUE 0xf +#define MC_DC18_VALUE 0x301 +#define MC_DC19_VALUE 0x200 +#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */ +#define MC_DC21_VALUE 0x1500 +#define MC_DC22_VALUE 0x1515 +#define MC_DC23_VALUE 0x0 +#define MC_DC24_VALUE 0x57 /* WDQS Tuning for DQS */ +#define MC_DC25_VALUE 0x0 +#define MC_DC26_VALUE 0x0 +#define MC_DC27_VALUE 0x0 +#define MC_DC28_VALUE 0x6b8 +#define MC_DC29_VALUE 0x3c84 +#define MC_DC30_VALUE 0xace5 +#define MC_DC31_VALUE 0x0 +#define MC_DC32_VALUE 0x0 +#define MC_DC33_VALUE 0x0 +#define MC_DC34_VALUE 0x0 +#define MC_DC35_VALUE 0x0 +#define MC_DC36_VALUE 0x0 +#define MC_DC37_VALUE 0x0 +#define MC_DC38_VALUE 0x0 +#define MC_DC39_VALUE 0x0 +#define MC_DC40_VALUE 0x0 +#define MC_DC41_VALUE 0x0 +#define MC_DC42_VALUE 0x0 +#define MC_DC43_VALUE 0x0 +#define MC_DC44_VALUE 0x0 +#define MC_DC45_VALUE 0x600 +//#define MC_DC45_VALUE 0x400 +#define MC_DC46_VALUE 0x0 diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr250_settings.h b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr250_settings.h new file mode 100644 index 000000000..2e49db99d --- /dev/null +++ b/package/uboot-lantiq/files/board/infineon/easy50812/ar9_ddr250_settings.h @@ -0,0 +1,51 @@ +/* Settings for Denali DDR SDRAM controller */ +/* Optimise for AR9 Ref Board DDR 221 Mhz - by Ng Aik Ann 16th May 2008 */ + +#define MC_DC0_VALUE 0x1B1B +#define MC_DC1_VALUE 0x0 +#define MC_DC2_VALUE 0x0 +#define MC_DC3_VALUE 0x0 +#define MC_DC4_VALUE 0x0 +#define MC_DC5_VALUE 0x200 +#define MC_DC6_VALUE 0x306 +#define MC_DC7_VALUE 0x403 +#define MC_DC8_VALUE 0x103 +#define MC_DC9_VALUE 0xb0e +#define MC_DC10_VALUE 0x204 +#define MC_DC11_VALUE 0x1102 +#define MC_DC12_VALUE 0x2c8 +#define MC_DC13_VALUE 0x1 +#define MC_DC14_VALUE 0x0 +#define MC_DC15_VALUE 0x155 /* WDQS tuning for clk_wr*/ +#define MC_DC16_VALUE 0xc800 +#define MC_DC17_VALUE 0x13 +#define MC_DC18_VALUE 0x401 +#define MC_DC19_VALUE 0x200 +#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */ +#define MC_DC21_VALUE 0xc00 +#define MC_DC22_VALUE 0xc0c +#define MC_DC23_VALUE 0x0 +#define MC_DC24_VALUE 0x74 /* WDQS Tuning for DQS */ +#define MC_DC25_VALUE 0x0 +#define MC_DC26_VALUE 0x0 +#define MC_DC27_VALUE 0x0 +#define MC_DC28_VALUE 0x798 +#define MC_DC29_VALUE 0x445d +#define MC_DC30_VALUE 0xc351 +#define MC_DC31_VALUE 0x0 +#define MC_DC32_VALUE 0x0 +#define MC_DC33_VALUE 0x0 +#define MC_DC34_VALUE 0x0 +#define MC_DC35_VALUE 0x0 +#define MC_DC36_VALUE 0x0 +#define MC_DC37_VALUE 0x0 +#define MC_DC38_VALUE 0x0 +#define MC_DC39_VALUE 0x0 +#define MC_DC40_VALUE 0x0 +#define MC_DC41_VALUE 0x0 +#define MC_DC42_VALUE 0x0 +#define MC_DC43_VALUE 0x0 +#define MC_DC44_VALUE 0x0 +#define MC_DC45_VALUE 0x600 +//#define MC_DC45_VALUE 0x400 +#define MC_DC46_VALUE 0x0 diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/config.mk b/package/uboot-lantiq/files/board/infineon/easy50812/config.mk new file mode 100644 index 000000000..c0e5d8244 --- /dev/null +++ b/package/uboot-lantiq/files/board/infineon/easy50812/config.mk @@ -0,0 +1,60 @@ +# +# (C) Copyright 2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# 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 +# + +# +# Danube board with MIPS 24Kc CPU core +# +sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp + +ifdef CONFIG_LZMA_BOOTSTRAP + +ifdef BUILD_BOOTSTRAP + +$(info BUILD_BOOTSTRAP ) +#TEXT_BASE = 0xB0000000 +TEXT_BASE = 0x80010000 + +else # BUILD_BOOTSTRAP + +ifndef TEXT_BASE +$(info redefine TEXT_BASE = 0x80040000 ) +TEXT_BASE = 0x80040000 +endif + +endif # BUILD_BOOTSTRAP + +else + +ifdef BUILD_BOOTSTRAP +$(error BUILD_BOOTSTRAP but not enabled in config) +endif + +ifndef TEXT_BASE +## Standard: boot from ebu +$(info redefine TEXT_BASE = 0xB0000000 ) +TEXT_BASE = 0xB0000000 +## For testing: boot from RAM +# TEXT_BASE = 0x80100000 +endif + +endif # CONFIG_LZMA_BOOTSTRAP diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/lowlevel_init.S b/package/uboot-lantiq/files/board/infineon/easy50812/lowlevel_init.S new file mode 100644 index 000000000..58f7a16ea --- /dev/null +++ b/package/uboot-lantiq/files/board/infineon/easy50812/lowlevel_init.S @@ -0,0 +1,543 @@ +/* + * Memory sub-system initialization code for AR9 board. + * + * Copyright (c) 2003 Wolfgang Denk + * Copyright (c) 2005 Andre Messerschmidt Infineon + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ +/* History: + peng liu May 25, 2006, for PLL setting after reset, 05252006 + */ +#include +#include +#include + +#if defined(CONFIG_USE_DDR_RAM) + +#if defined(CONFIG_CPU_111M_RAM_111M) || defined(CONFIG_CPU_333M_RAM_111M) +# include "ar9_ddr111_settings.h" +#elif defined(CONFIG_CPU_166M_RAM_166M) || defined(CONFIG_CPU_333M_RAM_166M) || defined(CONFIG_CPU_500M_RAM_166M) +# include "ar9_ddr166_settings.h" +#elif defined(CONFIG_CPU_442M_RAM_147M) +# include "ar9_ddr166_settings.h" +#elif defined(CONFIG_CPU_393M_RAM_196M) +# ifdef CONFIG_ETRON_RAM +# include "etron_ddr196_settings.h" +# else +# include "ar9_ddr196_settings.h" +# endif +#elif defined(CONFIG_CPU_442M_RAM_221M) +# include "ar9_ddr221_settings.h" +#elif defined(CONFIG_CPU_500M_RAM_250M) +# include "ar9_ddr250_settings.h" +#else +# warning "missing definition for ddr_settings.h, use default!" +# include "ar9_ddr_settings.h" +#endif +#endif /* CONFIG_USE_DDR_RAM */ + +#if defined(CONFIG_USE_DDR_RAM) && !defined(MC_DC0_VALUE) +#error "missing include of ddr_settings.h" +#endif + +#define EBU_MODUL_BASE 0xBE105300 +#define EBU_CLC(value) 0x0000(value) +#define EBU_CON(value) 0x0010(value) +#define EBU_ADDSEL0(value) 0x0020(value) +#define EBU_ADDSEL1(value) 0x0024(value) +#define EBU_ADDSEL2(value) 0x0028(value) +#define EBU_ADDSEL3(value) 0x002C(value) +#define EBU_BUSCON0(value) 0x0060(value) +#define EBU_BUSCON1(value) 0x0064(value) +#define EBU_BUSCON2(value) 0x0068(value) +#define EBU_BUSCON3(value) 0x006C(value) + +#define MC_MODUL_BASE 0xBF800000 +#define MC_ERRCAUSE(value) 0x0010(value) +#define MC_ERRADDR(value) 0x0020(value) +#define MC_CON(value) 0x0060(value) + +#define MC_SRAM_ENABLE 0x00000004 +#define MC_SDRAM_ENABLE 0x00000002 +#define MC_DDRRAM_ENABLE 0x00000001 + +#define MC_SDR_MODUL_BASE 0xBF800200 +#define MC_IOGP(value) 0x0000(value) +#define MC_CTRLENA(value) 0x0010(value) +#define MC_MRSCODE(value) 0x0020(value) +#define MC_CFGDW(value) 0x0030(value) +#define MC_CFGPB0(value) 0x0040(value) +#define MC_LATENCY(value) 0x0080(value) +#define MC_TREFRESH(value) 0x0090(value) +#define MC_SELFRFSH(value) 0x00A0(value) + +#define MC_DDR_MODUL_BASE 0xBF801000 +#define MC_DC00(value) 0x0000(value) +#define MC_DC01(value) 0x0010(value) +#define MC_DC02(value) 0x0020(value) +#define MC_DC03(value) 0x0030(value) +#define MC_DC04(value) 0x0040(value) +#define MC_DC05(value) 0x0050(value) +#define MC_DC06(value) 0x0060(value) +#define MC_DC07(value) 0x0070(value) +#define MC_DC08(value) 0x0080(value) +#define MC_DC09(value) 0x0090(value) +#define MC_DC10(value) 0x00A0(value) +#define MC_DC11(value) 0x00B0(value) +#define MC_DC12(value) 0x00C0(value) +#define MC_DC13(value) 0x00D0(value) +#define MC_DC14(value) 0x00E0(value) +#define MC_DC15(value) 0x00F0(value) +#define MC_DC16(value) 0x0100(value) +#define MC_DC17(value) 0x0110(value) +#define MC_DC18(value) 0x0120(value) +#define MC_DC19(value) 0x0130(value) +#define MC_DC20(value) 0x0140(value) +#define MC_DC21(value) 0x0150(value) +#define MC_DC22(value) 0x0160(value) +#define MC_DC23(value) 0x0170(value) +#define MC_DC24(value) 0x0180(value) +#define MC_DC25(value) 0x0190(value) +#define MC_DC26(value) 0x01A0(value) +#define MC_DC27(value) 0x01B0(value) +#define MC_DC28(value) 0x01C0(value) +#define MC_DC29(value) 0x01D0(value) +#define MC_DC30(value) 0x01E0(value) +#define MC_DC31(value) 0x01F0(value) +#define MC_DC32(value) 0x0200(value) +#define MC_DC33(value) 0x0210(value) +#define MC_DC34(value) 0x0220(value) +#define MC_DC35(value) 0x0230(value) +#define MC_DC36(value) 0x0240(value) +#define MC_DC37(value) 0x0250(value) +#define MC_DC38(value) 0x0260(value) +#define MC_DC39(value) 0x0270(value) +#define MC_DC40(value) 0x0280(value) +#define MC_DC41(value) 0x0290(value) +#define MC_DC42(value) 0x02A0(value) +#define MC_DC43(value) 0x02B0(value) +#define MC_DC44(value) 0x02C0(value) +#define MC_DC45(value) 0x02D0(value) +#define MC_DC46(value) 0x02E0(value) + +#define RCU_OFFSET 0xBF203000 +#define RCU_RST_REQ (RCU_OFFSET + 0x0010) +#define RCU_STS (RCU_OFFSET + 0x0014) + +#define CGU_OFFSET 0xBF103000 +#define PLL0_CFG (CGU_OFFSET + 0x0004) +#define PLL1_CFG (CGU_OFFSET + 0x0008) +#define PLL2_CFG (CGU_OFFSET + 0x000C) +#define CGU_SYS (CGU_OFFSET + 0x0010) +#define CGU_UPDATE (CGU_OFFSET + 0x0014) +#define IF_CLK (CGU_OFFSET + 0x0018) +#define CGU_SMD (CGU_OFFSET + 0x0020) +#define CGU_CT1SR (CGU_OFFSET + 0x0028) +#define CGU_CT2SR (CGU_OFFSET + 0x002C) +#define CGU_PCMCR (CGU_OFFSET + 0x0030) +#define PCI_CR_PCI (CGU_OFFSET + 0x0034) +#define CGU_OSC_CTRL (CGU_OFFSET + 0x001C) +#define CGU_MIPS_PWR_DWN (CGU_OFFSET + 0x0038) +#define CLK_MEASURE (CGU_OFFSET + 0x003C) + +#define pll1_36MHz_CONFIG 0x9800f25f + + .set noreorder + + +/* + * void ebu_init(void) + */ + .globl ebu_init + .ent ebu_init +ebu_init: + +#if defined(CONFIG_EBU_ADDSEL0) || defined(CONFIG_EBU_ADDSEL1) || \ + defined(CONFIG_EBU_ADDSEL2) || defined(CONFIG_EBU_ADDSEL3) || \ + defined(CONFIG_EBU_BUSCON0) || defined(CONFIG_EBU_BUSCON1) || \ + defined(CONFIG_EBU_BUSCON2) || defined(CONFIG_EBU_BUSCON3) + + li t1, EBU_MODUL_BASE +#if defined(CONFIG_EBU_ADDSEL0) + li t2, CONFIG_EBU_ADDSEL0 + sw t2, EBU_ADDSEL0(t1) +#endif +#if defined(CONFIG_EBU_ADDSEL1) + li t2, CONFIG_EBU_ADDSEL1 + sw t2, EBU_ADDSEL1(t1) +#endif +#if defined(CONFIG_EBU_ADDSEL2) + li t2, CONFIG_EBU_ADDSEL2 + sw t2, EBU_ADDSEL2(t1) +#endif +#if defined(CONFIG_EBU_ADDSEL3) + li t2, CONFIG_EBU_ADDSEL3 + sw t2, EBU_ADDSEL3(t1) +#endif + +#if defined(CONFIG_EBU_BUSCON0) + li t2, CONFIG_EBU_BUSCON0 + sw t2, EBU_BUSCON0(t1) +#endif +#if defined(CONFIG_EBU_BUSCON1) + li t2, CONFIG_EBU_BUSCON1 + sw t2, EBU_BUSCON1(t1) +#endif +#if defined(CONFIG_EBU_BUSCON2) + li t2, CONFIG_EBU_BUSCON2 + sw t2, EBU_BUSCON2(t1) +#endif +#if defined(CONFIG_EBU_BUSCON3) + li t2, CONFIG_EBU_BUSCON3 + sw t2, EBU_BUSCON3(t1) +#endif + +#endif + + j ra + nop + + .end ebu_init + + +/* + * void cgu_init(long) + * + * a0 has the clock value + */ + .globl cgu_init + .ent cgu_init +cgu_init: + li t2, CGU_SYS + lw t2,0(t2) + beq t2,a0,freq_up2date + nop + li t1, CGU_SYS + sw a0,0(t1) + +#if defined(CONFIG_CPU_333M_RAM_166M) && defined(CONFIG_USE_PLL1) + li t1, PLL1_CFG + li a1, pll1_36MHz_CONFIG + sw a1, 0(t1) +#endif + +#if defined(CONFIG_CLASS_II_DDR_PAD) + li t1, CGU_SMD + li a1, 0x200000 + sw a1, 0(t1) // Turn on DDR PAD Class II to INC drive. +#endif + + li t1, RCU_RST_REQ + li t2, 0x40000008 + sw t2,0(t1) + b wait_reset + nop + +wait_reset: + b wait_reset + nop + +freq_up2date: + j ra + nop + .end cgu_init + + +#ifndef CONFIG_USE_DDR_RAM +/* + * void sdram_init(long) + * + * a0 has the clock value + */ + .globl sdram_init + .ent sdram_init +sdram_init: + + /* SDRAM Initialization + */ + li t1, MC_MODUL_BASE + + /* Clear Error log registers */ + sw zero, MC_ERRCAUSE(t1) + sw zero, MC_ERRADDR(t1) + + /* Enable SDRAM module in memory controller */ + li t3, MC_SDRAM_ENABLE + lw t2, MC_CON(t1) + or t3, t2, t3 + sw t3, MC_CON(t1) + + li t1, MC_SDR_MODUL_BASE + + /* disable the controller */ + li t2, 0 + sw t2, MC_CTRLENA(t1) + + li t2, 0x822 + sw t2, MC_IOGP(t1) + + li t2, 0x2 + sw t2, MC_CFGDW(t1) + + /* Set CAS Latency */ + li t2, 0x00000020 + sw t2, MC_MRSCODE(t1) + + /* Set CS0 to SDRAM parameters */ + li t2, 0x000014d8 + sw t2, MC_CFGPB0(t1) + + /* Set SDRAM latency parameters */ + li t2, 0x00036325; /* BC PC100 */ + sw t2, MC_LATENCY(t1) + + /* Set SDRAM refresh rate */ + li t2, 0x00000C30 + sw t2, MC_TREFRESH(t1) + + /* Clear Power-down registers */ + sw zero, MC_SELFRFSH(t1) + + /* Finally enable the controller */ + li t2, 1 + sw t2, MC_CTRLENA(t1) + + j ra + nop + + .end sdram_init + +#endif /* !CONFIG_USE_DDR_RAM */ + +#ifdef CONFIG_USE_DDR_RAM +/* + * void ddrram_init(long) + * + * a0 has the clock value + */ + .globl ddrram_init + .ent ddrram_init +ddrram_init: + + /* DDR-DRAM Initialization + */ + li t1, MC_MODUL_BASE + + /* Clear Error log registers */ + sw zero, MC_ERRCAUSE(t1) + sw zero, MC_ERRADDR(t1) + + /* Enable DDR module in memory controller */ + li t3, MC_DDRRAM_ENABLE + lw t2, MC_CON(t1) + or t3, t2, t3 + sw t3, MC_CON(t1) + + li t1, MC_DDR_MODUL_BASE + + /* Write configuration to DDR controller registers */ + li t2, MC_DC0_VALUE + sw t2, MC_DC00(t1) + + li t2, MC_DC1_VALUE + sw t2, MC_DC01(t1) + + li t2, MC_DC2_VALUE + sw t2, MC_DC02(t1) + + li t2, MC_DC3_VALUE + sw t2, MC_DC03(t1) + + li t2, MC_DC4_VALUE + sw t2, MC_DC04(t1) + + li t2, MC_DC5_VALUE + sw t2, MC_DC05(t1) + + li t2, MC_DC6_VALUE + sw t2, MC_DC06(t1) + + li t2, MC_DC7_VALUE + sw t2, MC_DC07(t1) + + li t2, MC_DC8_VALUE + sw t2, MC_DC08(t1) + + li t2, MC_DC9_VALUE + sw t2, MC_DC09(t1) + + li t2, MC_DC10_VALUE + sw t2, MC_DC10(t1) + + li t2, MC_DC11_VALUE + sw t2, MC_DC11(t1) + + li t2, MC_DC12_VALUE + sw t2, MC_DC12(t1) + + li t2, MC_DC13_VALUE + sw t2, MC_DC13(t1) + + li t2, MC_DC14_VALUE + sw t2, MC_DC14(t1) + + li t2, MC_DC15_VALUE + sw t2, MC_DC15(t1) + + li t2, MC_DC16_VALUE + sw t2, MC_DC16(t1) + + li t2, MC_DC17_VALUE + sw t2, MC_DC17(t1) + + li t2, MC_DC18_VALUE + sw t2, MC_DC18(t1) + + li t2, MC_DC19_VALUE + sw t2, MC_DC19(t1) + + li t2, MC_DC20_VALUE + sw t2, MC_DC20(t1) + + li t2, MC_DC21_VALUE + sw t2, MC_DC21(t1) + + li t2, MC_DC22_VALUE + sw t2, MC_DC22(t1) + + li t2, MC_DC23_VALUE + sw t2, MC_DC23(t1) + + li t2, MC_DC24_VALUE + sw t2, MC_DC24(t1) + + li t2, MC_DC25_VALUE + sw t2, MC_DC25(t1) + + li t2, MC_DC26_VALUE + sw t2, MC_DC26(t1) + + li t2, MC_DC27_VALUE + sw t2, MC_DC27(t1) + + li t2, MC_DC28_VALUE + sw t2, MC_DC28(t1) + + li t2, MC_DC29_VALUE + sw t2, MC_DC29(t1) + + li t2, MC_DC30_VALUE + sw t2, MC_DC30(t1) + + li t2, MC_DC31_VALUE + sw t2, MC_DC31(t1) + + li t2, MC_DC32_VALUE + sw t2, MC_DC32(t1) + + li t2, MC_DC33_VALUE + sw t2, MC_DC33(t1) + + li t2, MC_DC34_VALUE + sw t2, MC_DC34(t1) + + li t2, MC_DC35_VALUE + sw t2, MC_DC35(t1) + + li t2, MC_DC36_VALUE + sw t2, MC_DC36(t1) + + li t2, MC_DC37_VALUE + sw t2, MC_DC37(t1) + + li t2, MC_DC38_VALUE + sw t2, MC_DC38(t1) + + li t2, MC_DC39_VALUE + sw t2, MC_DC39(t1) + + li t2, MC_DC40_VALUE + sw t2, MC_DC40(t1) + + li t2, MC_DC41_VALUE + sw t2, MC_DC41(t1) + + li t2, MC_DC42_VALUE + sw t2, MC_DC42(t1) + + li t2, MC_DC43_VALUE + sw t2, MC_DC43(t1) + + li t2, MC_DC44_VALUE + sw t2, MC_DC44(t1) + + li t2, MC_DC45_VALUE + sw t2, MC_DC45(t1) + + li t2, MC_DC46_VALUE + sw t2, MC_DC46(t1) + + li t2, 0x00000100 + sw t2, MC_DC03(t1) + + j ra + nop + + .end ddrram_init +#endif /* CONFIG_USE_DDR_RAM */ + + .globl lowlevel_init + .ent lowlevel_init +lowlevel_init: + /* EBU, CGU and SDRAM/DDR-RAM Initialization. + */ + move t0, ra + /* We rely on the fact that non of the following ..._init() functions + * modify t0 + */ +#if defined(CONFIG_SYS_EBU_BOOT) +/* + using PPL1 value +*/ + li a0,0x90 + bal cgu_init + nop +#endif /* CONFIG_SYS_EBU_BOOT */ + + bal ebu_init + nop + +#ifdef CONFIG_SYS_EBU_BOOT +#ifndef CONFIG_SYS_RAMBOOT +#ifdef CONFIG_USE_DDR_RAM + bal ddrram_init + nop +#else + bal sdram_init + nop +#endif +#endif /* CONFIG_SYS_RAMBOOT */ +#endif /* CONFIG_SYS_EBU_BOOT */ + + move ra, t0 + j ra + nop + + .end lowlevel_init diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/pmuenable.S b/package/uboot-lantiq/files/board/infineon/easy50812/pmuenable.S new file mode 100644 index 000000000..e0d7971d8 --- /dev/null +++ b/package/uboot-lantiq/files/board/infineon/easy50812/pmuenable.S @@ -0,0 +1,48 @@ +/* + * Power Management unit initialization code for AMAZON development board. + * + * Copyright (c) 2003 Ou Ke, Infineon. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 +#include +#include + +#define PMU_PWDCR 0xBF10201C +#define PMU_SR 0xBF102020 + + .globl pmuenable + +pmuenable: + li t0, PMU_PWDCR + li t1, 0x2 /* enable everything */ + sw t1, 0(t0) +#if 0 +1: + li t0, PMU_SR + lw t2, 0(t0) + bne t1, t2, 1b + nop +#endif + j ra + nop + + diff --git a/package/uboot-lantiq/files/board/infineon/easy50812/u-boot.lds b/package/uboot-lantiq/files/board/infineon/easy50812/u-boot.lds new file mode 100644 index 000000000..9a6cd1b8a --- /dev/null +++ b/package/uboot-lantiq/files/board/infineon/easy50812/u-boot.lds @@ -0,0 +1,70 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +/* +OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-bigmips") +*/ +OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips", "elf32-tradbigmips") +OUTPUT_ARCH(mips) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + *(.text) + } + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + + . = ALIGN(4); + .data : { *(.data) } + + . = .; + _gp = ALIGN(16) + 0x7ff0; + + .got : { + __got_start = .; + *(.got) + __got_end = .; + } + + .sdata : { *(.sdata) } + + .u_boot_cmd : { + __u_boot_cmd_start = .; + *(.u_boot_cmd) + __u_boot_cmd_end = .; + } + + uboot_end_data = .; + num_got_entries = (__got_end - __got_start) >> 2; + + . = ALIGN(4); + .sbss (NOLOAD) : { *(.sbss) } + .bss (NOLOAD) : { *(.bss) . = ALIGN(4); } + uboot_end = .; +} diff --git a/package/uboot-lantiq/files/cpu/mips/ar9/Makefile b/package/uboot-lantiq/files/cpu/mips/ar9/Makefile new file mode 100644 index 000000000..c48d02eaa --- /dev/null +++ b/package/uboot-lantiq/files/cpu/mips/ar9/Makefile @@ -0,0 +1,46 @@ +######################################################################### +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# 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 $(TOPDIR)/config.mk + +LIB = $(obj)lib$(SOC).a + +COBJS = clock.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/package/uboot-lantiq/files/cpu/mips/ar9/clock.c b/package/uboot-lantiq/files/cpu/mips/ar9/clock.c new file mode 100644 index 000000000..a8aecb422 --- /dev/null +++ b/package/uboot-lantiq/files/cpu/mips/ar9/clock.c @@ -0,0 +1,67 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 +#include + +ulong ifx_get_ddr_hz(void) +{ + switch((*AR9_CGU_SYS) & 0x05) { + case 0x01: + case 0x05: + return CLOCK_111M; + + case 0x00: + case 0x04: + return CLOCK_166M; + } + + return 0; +} + +ulong ifx_get_cpuclk(void) +{ + switch((*AR9_CGU_SYS) & 0x05) { + case 0x00: + case 0x01: + return CLOCK_333M; + + case 0x04: + return CLOCK_166M; + + case 0x05: + return CLOCK_111M; + } + + return 0; +} + +ulong get_bus_freq(ulong dummy) +{ + unsigned int ddr_clock=ifx_get_ddr_hz(); + if((*AR9_CGU_SYS) & 0x40){ + return ddr_clock/2; + } else { + return ddr_clock; + } +} diff --git a/package/uboot-lantiq/files/cpu/mips/ar9/ifx_cache.S b/package/uboot-lantiq/files/cpu/mips/ar9/ifx_cache.S new file mode 100644 index 000000000..fc482dcd6 --- /dev/null +++ b/package/uboot-lantiq/files/cpu/mips/ar9/ifx_cache.S @@ -0,0 +1,60 @@ + +#define IFX_CACHE_EXTRA_INVALID_TAG \ + mtc0 zero, CP0_TAGLO, 1; \ + mtc0 zero, CP0_TAGLO, 2; \ + mtc0 zero, CP0_TAGLO, 3; \ + mtc0 zero, CP0_TAGLO, 4; + +#define IFX_CACHE_EXTRA_OPERATION \ + /* set WST bit */ \ + mfc0 a0, CP0_ECC; \ + li a1, ECCF_WST; \ + or a0, a1; \ + mtc0 a0, CP0_ECC; \ + \ + li a0, K0BASE; \ + move a2, t2; /* icacheSize */ \ + move a3, t4; /* icacheLineSize */ \ + move a1, a2; \ + icacheop(a0,a1,a2,a3,(Index_Store_Tag_I)); \ + \ + /* clear WST bit */ \ + mfc0 a0, CP0_ECC; \ + li a1, ~ECCF_WST; \ + and a0, a1; \ + mtc0 a0, CP0_ECC; \ + \ + /* 1: initialise dcache tags. */ \ + \ + /* cache line size */ \ + li a2, CFG_CACHELINE_SIZE; \ + /* kseg0 mem address */ \ + li a1, 0; \ + li a3, CFG_CACHE_SETS * CFG_CACHE_WAYS; \ +1: \ + /* store tag (invalid, not locked) */ \ + cache 0x8, 0(a1); \ + cache 0x9, 0(a1); \ + \ + add a3, -1; \ + bne a3, zero, 1b; \ + add a1, a2; \ + \ + /* set WST bit */ \ + mfc0 a0, CP0_ECC; \ + li a1, ECCF_WST; \ + or a0, a1; \ + mtc0 a0, CP0_ECC; \ + \ + li a0, K0BASE; \ + move a2, t3; /* dcacheSize */ \ + move a3, t5; /* dcacheLineSize */ \ + move a1, a2; \ + icacheop(a0,a1,a2,a3,(Index_Store_Tag_D)); \ + \ + /* clear WST bit */ \ + mfc0 a0, CP0_ECC; \ + li a1, ~ECCF_WST; \ + and a0, a1; \ + mtc0 a0, CP0_ECC; + diff --git a/package/uboot-lantiq/files/drivers/net/ifx_etop.c b/package/uboot-lantiq/files/drivers/net/ifx_etop.c index 9a9e51fa0..8a03683c0 100644 --- a/package/uboot-lantiq/files/drivers/net/ifx_etop.c +++ b/package/uboot-lantiq/files/drivers/net/ifx_etop.c @@ -36,11 +36,17 @@ #include #include #include +#include #include "ifx_etop.h" +#if defined(CONFIG_AR9) +#define TX_CHAN_NO 1 +#define RX_CHAN_NO 0 +#else #define TX_CHAN_NO 7 #define RX_CHAN_NO 6 +#endif #define NUM_RX_DESC PKTBUFSRX #define NUM_TX_DESC 8 @@ -245,7 +251,19 @@ static void lq_eth_halt(struct eth_device *dev) } } -static int lq_eth_send(struct eth_device *dev, volatile void *packet,int length) +#ifdef DEBUG +static void lq_dump(const u8 *data, const u32 length) +{ + u32 i; + debug("\n"); + for(i=0;istatus.field.DataLen = (u32)length; flush_cache((u32)packet, tx_desc->status.field.DataLen); + asm("SYNC"); tx_desc->status.field.OWN=1; res=length; tx_num++; if (tx_num==NUM_TX_DESC) tx_num=0; +#ifdef DEBUG + lq_dump(tx_desc->DataPtr, tx_desc->status.field.DataLen); +#endif + dma_writel(dma_cs, TX_CHAN_NO); if (!(dma_readl(dma_cctrl) & 1)) { dma_writel(dma_cctrl, dma_readl(dma_cctrl) | 1); @@ -298,6 +321,10 @@ static int lq_eth_recv(struct eth_device *dev) if ((rx_desc->status.field.C == 0) || (rx_desc->status.field.OWN == 1)) { return 0; } + debug("rx"); +#ifdef DEBUG + lq_dump(rx_desc->DataPtr, rx_desc->status.field.DataLen); +#endif length = rx_desc->status.field.DataLen; if (length > 4) { invalidate_dcache_range((u32)CKSEG0ADDR(rx_desc->DataPtr), (u32) CKSEG0ADDR(rx_desc->DataPtr) + length); diff --git a/package/uboot-lantiq/files/include/asm-mips/ar9.h b/package/uboot-lantiq/files/include/asm-mips/ar9.h new file mode 100644 index 000000000..cfafe4490 --- /dev/null +++ b/package/uboot-lantiq/files/include/asm-mips/ar9.h @@ -0,0 +1,424 @@ +/* + * (C) Copyright 2010 + * Ralph Hempel + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +/***********************************************************************/ +/* Module : PMU register address and bits */ +/***********************************************************************/ +#define AR9_PMU (0xBF102000) +/* PMU Power down Control Register */ +#define AR9_PMU_PWDCR ((volatile u32*)(AR9_PMU + 0x001C)) +/* PMU Status Register */ +#define AR9_PMU_SR ((volatile u32*)(AR9_PMU + 0x0020)) +/** DMA block */ +#define AR9_PMU_DMA (1<<5) +#define AR9_PMU_SDIO (1<<16) +#define AR9_PMU_USB0 (1<<6) +#define AR9_PMU_USB0_P (1<<0) +#define AR9_PMU_SWITCH (1<<28) + + +/***********************************************************************/ +/* Module : RCU register address and bits */ +/***********************************************************************/ +#define AR9_RCU_BASE_ADDR (0xBF203000) +#define AR9_RCU_RST_REQ ((volatile u32*)(AR9_RCU_BASE_ADDR + 0x0010)) +#define AR9_RCU_RST_STAT ((volatile u32*)(AR9_RCU_BASE_ADDR + 0x0014)) +#define AR9_RST_ALL (1 << 30) + +/*** Reset Request Register Bits ***/ +#define AR9_RCU_RST_REQ_SRST (1 << 30) +#define AR9_RCU_RST_REQ_ARC_JTAG (1 << 20) +#define AR9_RCU_RST_REQ_PCI (1 << 13) +#define AR9_RCU_RST_REQ_AFE (1 << 11) +#define AR9_RCU_RST_REQ_SDIO (1 << 19) +#define AR9_RCU_RST_REQ_DMA (1 << 9) +#define AR9_RCU_RST_REQ_PPE (1 << 8) +#define AR9_RCU_RST_REQ_DFE (1 << 7) + +/***********************************************************************/ +/* Module : GPIO register address and bits */ +/***********************************************************************/ +#define AR9_GPIO (0xBE100B00) +/***Port 0 Data Output Register (0010H)***/ +#define AR9_GPIO_P0_OUT ((volatile u32 *)(AR9_GPIO+ 0x0010)) +/***Port 1 Data Output Register (0040H)***/ +#define AR9_GPIO_P1_OUT ((volatile u32 *)(AR9_GPIO+ 0x0040)) +/***Port 2 Data Output Register (0070H)***/ +#define AR9_GPIO_P2_OUT ((volatile u32 *)(AR9_GPIO+ 0x0070)) +/***Port 3 Data Output Register (00A0H)***/ +#define AR9_GPIO_P3_OUT ((volatile u32 *)(AR9_GPIO+ 0x00A0)) +/***Port 0 Data Input Register (0014H)***/ +#define AR9_GPIO_P0_IN ((volatile u32 *)(AR9_GPIO+ 0x0014)) +/***Port 1 Data Input Register (0044H)***/ +#define AR9_GPIO_P1_IN ((volatile u32 *)(AR9_GPIO+ 0x0044)) +/***Port 2 Data Input Register (0074H)***/ +#define AR9_GPIO_P2_IN ((volatile u32 *)(AR9_GPIO+ 0x0074)) +/***Port 3 Data Input Register (00A4H)***/ +#define AR9_GPIO_P3_IN ((volatile u32 *)(AR9_GPIO+ 0x00A4)) +/***Port 0 Direction Register (0018H)***/ +#define AR9_GPIO_P0_DIR ((volatile u32 *)(AR9_GPIO+ 0x0018)) +/***Port 1 Direction Register (0048H)***/ +#define AR9_GPIO_P1_DIR ((volatile u32 *)(AR9_GPIO+ 0x0048)) +/***Port 2 Direction Register (0078H)***/ +#define AR9_GPIO_P2_DIR ((volatile u32 *)(AR9_GPIO+ 0x0078)) +/***Port 3 Direction Register (0048H)***/ +#define AR9_GPIO_P3_DIR ((volatile u32 *)(AR9_GPIO+ 0x00A8)) +/***Port 0 Alternate Function Select Register 0 (001C H) ***/ +#define AR9_GPIO_P0_ALTSEL0 ((volatile u32 *)(AR9_GPIO+ 0x001C)) +/***Port 1 Alternate Function Select Register 0 (004C H) ***/ +#define AR9_GPIO_P1_ALTSEL0 ((volatile u32 *)(AR9_GPIO+ 0x004C)) +/***Port 2 Alternate Function Select Register 0 (007C H) ***/ +#define AR9_GPIO_P2_ALTSEL0 ((volatile u32 *)(AR9_GPIO+ 0x007C)) +/***Port 3 Alternate Function Select Register 0 (00AC H) ***/ +#define AR9_GPIO_P3_ALTSEL0 ((volatile u32 *)(AR9_GPIO+ 0x00AC)) +/***Port 0 Alternate Function Select Register 1 (0020 H) ***/ +#define AR9_GPIO_P0_ALTSEL1 ((volatile u32 *)(AR9_GPIO+ 0x0020)) +/***Port 1 Alternate Function Select Register 0 (0050 H) ***/ +#define AR9_GPIO_P1_ALTSEL1 ((volatile u32 *)(AR9_GPIO+ 0x0050)) +/***Port 2 Alternate Function Select Register 0 (0080 H) ***/ +#define AR9_GPIO_P2_ALTSEL1 ((volatile u32 *)(AR9_GPIO+ 0x0080)) +/***Port 3 Alternate Function Select Register 0 (0064 H) ***/ +#define AR9_GPIO_P3_ALTSEL1 ((volatile u32 *)(AR9_GPIO+ 0x0064)) +/***Port 0 Open Drain Control Register (0024H)***/ +#define AR9_GPIO_P0_OD ((volatile u32 *)(AR9_GPIO+ 0x0024)) +/***Port 1 Open Drain Control Register (0054H)***/ +#define AR9_GPIO_P1_OD ((volatile u32 *)(AR9_GPIO+ 0x0054)) +/***Port 2 Open Drain Control Register (0084H)***/ +#define AR9_GPIO_P2_OD ((volatile u32 *)(AR9_GPIO+ 0x0084)) +/***Port 3 Open Drain Control Register (0034H)***/ +#define AR9_GPIO_P3_OD ((volatile u32 *)(AR9_GPIO+ 0x0034)) +/***Port 0 Input Schmitt-Trigger Off Register (0028 H) ***/ +#define AR9_GPIO_P0_STOFF ((volatile u32 *)(AR9_GPIO+ 0x0028)) +/***Port 1 Input Schmitt-Trigger Off Register (0058 H) ***/ +#define AR9_GPIO_P1_STOFF ((volatile u32 *)(AR9_GPIO+ 0x0058)) +/***Port 2 Input Schmitt-Trigger Off Register (0088 H) ***/ +#define AR9_GPIO_P2_STOFF ((volatile u32 *)(AR9_GPIO+ 0x0088)) +/***Port 3 Input Schmitt-Trigger Off Register (0094 H) ***/ +//#define AR9_GPIO_P3_STOFF ((volatile u32 *)(AR9_GPIO+ 0x0094)) +/***Port 0 Pull Up/Pull Down Select Register (002C H)***/ +#define AR9_GPIO_P0_PUDSEL ((volatile u32 *)(AR9_GPIO+ 0x002C)) +/***Port 1 Pull Up/Pull Down Select Register (005C H)***/ +#define AR9_GPIO_P1_PUDSEL ((volatile u32 *)(AR9_GPIO+ 0x005C)) +/***Port 2 Pull Up/Pull Down Select Register (008C H)***/ +#define AR9_GPIO_P2_PUDSEL ((volatile u32 *)(AR9_GPIO+ 0x008C)) +/***Port 3 Pull Up/Pull Down Select Register (0038 H)***/ +#define AR9_GPIO_P3_PUDSEL ((volatile u32 *)(AR9_GPIO+ 0x0038)) +/***Port 0 Pull Up Device Enable Register (0030 H)***/ +#define AR9_GPIO_P0_PUDEN ((volatile u32 *)(AR9_GPIO+ 0x0030)) +/***Port 1 Pull Up Device Enable Register (0060 H)***/ +#define AR9_GPIO_P1_PUDEN ((volatile u32 *)(AR9_GPIO+ 0x0060)) +/***Port 2 Pull Up Device Enable Register (0090 H)***/ +#define AR9_GPIO_P2_PUDEN ((volatile u32 *)(AR9_GPIO+ 0x0090)) +/***Port 3 Pull Up Device Enable Register (003c H)***/ +#define AR9_GPIO_P3_PUDEN ((volatile u32 *)(AR9_GPIO+ 0x003C)) + +/***********************************************************************/ +/* Module : CGU register address and bits */ +/***********************************************************************/ +#define AR9_CGU (0xBF103000) +/***CGU Clock PLL0 ***/ +#define AR9_CGU_PLL0_CFG ((volatile u32*)(AR9_CGU+ 0x0004)) +/***CGU Clock PLL1 ***/ +#define AR9_CGU_PLL1_CFG ((volatile u32*)(AR9_CGU+ 0x0008)) +/***CGU Clock SYS Mux Register***/ +#define AR9_CGU_SYS ((volatile u32*)(AR9_CGU+ 0x0010)) +/***CGU Interface Clock Control Register***/ +#define AR9_CGU_IFCCR ((volatile u32*)(AR9_CGU+ 0x0018)) +/***CGU PCI Clock Control Register**/ +#define AR9_CGU_PCICR ((volatile u32*)(AR9_CGU+ 0x0034)) +#define CLOCK_60M 60000000 +#define CLOCK_83M 83333333 +#define CLOCK_111M 111111111 +#define CLOCK_133M 133333333 +#define CLOCK_166M 166666667 +#define CLOCK_196M 196666667 +#define CLOCK_333M 333333333 +#define CLOCK_366M 366666667 +#define CLOCK_500M 500000000 + +/***********************************************************************/ +/* Module : MPS register address and bits */ +/***********************************************************************/ +#define AR9_MPS (KSEG1+0x1F107000) +#define AR9_MPS_CHIPID ((volatile u32*)(AR9_MPS + 0x0344)) +#define AR9_MPS_CHIPID_VERSION_GET(value) (((value) >> 28) & ((1 << 4) - 1)) +#define AR9_MPS_CHIPID_PARTNUM_GET(value) (((value) >> 12) & ((1 << 16) - 1)) +#define AR9_MPS_CHIPID_MANID_GET(value) (((value) >> 1) & ((1 << 10) - 1)) + +/***********************************************************************/ +/* Module : EBU register address and bits */ +/***********************************************************************/ +#define AR9_EBU (0xBE105300) + +#define AR9_EBU_CLC ((volatile u32*)(AR9_EBU+ 0x0000)) +#define AR9_EBU_CLC_DISS (1 << 1) +#define AR9_EBU_CLC_DISR (1 << 0) + +#define AR9_EBU_ID ((volatile u32*)(AR9_EBU+ 0x0008)) + +/***EBU Global Control Register***/ +#define AR9_EBU_CON ((volatile u32*)(AR9_EBU+ 0x0010)) +#define AR9_EBU_CON_DTACS (value) (((( 1 << 3) - 1) & (value)) << 20) +#define AR9_EBU_CON_DTARW (value) (((( 1 << 3) - 1) & (value)) << 16) +#define AR9_EBU_CON_TOUTC (value) (((( 1 << 8) - 1) & (value)) << 8) +#define AR9_EBU_CON_ARBMODE (value) (((( 1 << 2) - 1) & (value)) << 6) +#define AR9_EBU_CON_ARBSYNC (1 << 5) +//#define AR9_EBU_CON_1 (1 << 3) + +/***EBU Address Select Register 0***/ +#define AR9_EBU_ADDSEL0 ((volatile u32*)(AR9_EBU + 0x0020)) +/***EBU Address Select Register 1***/ +#define AR9_EBU_ADDSEL1 ((volatile u32*)(AR9_EBU + 0x0024)) +/***EBU Address Select Register 2***/ +#define AR9_EBU_ADDSEL2 ((volatile u32*)(AR9_EBU + 0x0028)) +/***EBU Address Select Register 3***/ +#define AR9_EBU_ADDSEL3 ((volatile u32*)(AR9_EBU + 0x002C)) +#define AR9_EBU_ADDSEL_BASE (value) (((( 1 << 20) - 1) & (value)) << 12) +#define AR9_EBU_ADDSEL_MASK (value) (((( 1 << 4) - 1) & (value)) << 4) +#define AR9_EBU_ADDSEL_MIRRORE (1 << 1) +#define AR9_EBU_ADDSEL_REGEN (1 << 0) + +/***EBU Bus Configuration Register 0***/ +#define AR9_EBU_BUSCON0 ((volatile u32*)(AR9_EBU+ 0x0060)) +#define AR9_EBU_BUSCON0_WRDIS (1 << 31) +#define AR9_EBU_BUSCON0_ADSWP (value) (1 << 30) +#define AR9_EBU_BUSCON0_PG_EN (value) (1 << 29) +#define AR9_EBU_BUSCON0_AGEN (value) (((( 1 << 3) - 1) & (value)) << 24) +#define AR9_EBU_BUSCON0_SETUP (1 << 22) +#define AR9_EBU_BUSCON0_WAIT (value) (((( 1 << 2) - 1) & (value)) << 20) +#define AR9_EBU_BUSCON0_WAITINV (1 << 19) +#define AR9_EBU_BUSCON0_VN_EN (1 << 18) +#define AR9_EBU_BUSCON0_PORTW (value) (((( 1 << 2) - 1) & (value)) << 16) +#define AR9_EBU_BUSCON0_ALEC (value) (((( 1 << 2) - 1) & (value)) << 14) +#define AR9_EBU_BUSCON0_BCGEN (value) (((( 1 << 2) - 1) & (value)) << 12) +#define AR9_EBU_BUSCON0_WAITWDC (value) (((( 1 << 4) - 1) & (value)) << 8) +#define AR9_EBU_BUSCON0_WAITRRC (value) (((( 1 << 2) - 1) & (value)) << 6) +#define AR9_EBU_BUSCON0_HOLDC (value) (((( 1 << 2) - 1) & (value)) << 4) +#define AR9_EBU_BUSCON0_RECOVC (value) (((( 1 << 2) - 1) & (value)) << 2) +#define AR9_EBU_BUSCON0_CMULT (value) (((( 1 << 2) - 1) & (value)) << 0) + +/***EBU Bus Configuration Register 1***/ +#define AR9_EBU_BUSCON1 ((volatile u32*)(AR9_EBU+ 0x0064)) +#define AR9_EBU_BUSCON1_WRDIS (1 << 31) +#define AR9_EBU_BUSCON1_ALEC (value) (((( 1 << 2) - 1) & (value)) << 29) +#define AR9_EBU_BUSCON1_BCGEN (value) (((( 1 << 2) - 1) & (value)) << 27) +#define AR9_EBU_BUSCON1_AGEN (value) (((( 1 << 2) - 1) & (value)) << 24) +#define AR9_EBU_BUSCON1_CMULTR (value) (((( 1 << 2) - 1) & (value)) << 22) +#define AR9_EBU_BUSCON1_WAIT (value) (((( 1 << 2) - 1) & (value)) << 20) +#define AR9_EBU_BUSCON1_WAITINV (1 << 19) +#define AR9_EBU_BUSCON1_SETUP (1 << 18) +#define AR9_EBU_BUSCON1_PORTW (value) (((( 1 << 2) - 1) & (value)) << 16) +#define AR9_EBU_BUSCON1_WAITRDC (value) (((( 1 << 7) - 1) & (value)) << 9) +#define AR9_EBU_BUSCON1_WAITWRC (value) (((( 1 << 3) - 1) & (value)) << 6) +#define AR9_EBU_BUSCON1_HOLDC (value) (((( 1 << 2) - 1) & (value)) << 4) +#define AR9_EBU_BUSCON1_RECOVC (value) (((( 1 << 2) - 1) & (value)) << 2) +#define AR9_EBU_BUSCON1_CMULT (value) (((( 1 << 2) - 1) & (value)) << 0) + +/***EBU Bus Configuration Register 2***/ +#define AR9_EBU_BUSCON2 ((volatile u32*)(AR9_EBU+ 0x0068)) +#define AR9_EBU_BUSCON2_WRDIS (1 << 31) +#define AR9_EBU_BUSCON2_ALEC (value) (((( 1 << 2) - 1) & (value)) << 29) +#define AR9_EBU_BUSCON2_BCGEN (value) (((( 1 << 2) - 1) & (value)) << 27) +#define AR9_EBU_BUSCON2_AGEN (value) (((( 1 << 2) - 1) & (value)) << 24) +#define AR9_EBU_BUSCON2_CMULTR (value) (((( 1 << 2) - 1) & (value)) << 22) +#define AR9_EBU_BUSCON2_WAIT (value) (((( 1 << 2) - 1) & (value)) << 20) +#define AR9_EBU_BUSCON2_WAITINV (1 << 19) +#define AR9_EBU_BUSCON2_SETUP (1 << 18) +#define AR9_EBU_BUSCON2_PORTW (value) (((( 1 << 2) - 1) & (value)) << 16) +#define AR9_EBU_BUSCON2_WAITRDC (value) (((( 1 << 7) - 1) & (value)) << 9) +#define AR9_EBU_BUSCON2_WAITWRC (value) (((( 1 << 3) - 1) & (value)) << 6) +#define AR9_EBU_BUSCON2_HOLDC (value) (((( 1 << 2) - 1) & (value)) << 4) +#define AR9_EBU_BUSCON2_RECOVC (value) (((( 1 << 2) - 1) & (value)) << 2) +#define AR9_EBU_BUSCON2_CMULT (value) (((( 1 << 2) - 1) & (value)) << 0) + +/***EBU Bus Configuration Register 2***/ +#define AR9_EBU_BUSCON3 ((volatile u32*)(AR9_EBU+ 0x006C)) +#define AR9_EBU_BUSCON3_WRDIS (1 << 31) +#define AR9_EBU_BUSCON3_ADSWP (value) (1 << 30) +#define AR9_EBU_BUSCON3_PG_EN (value) (1 << 29) +#define AR9_EBU_BUSCON3_AGEN (value) (((( 1 << 3) - 1) & (value)) << 24) +#define AR9_EBU_BUSCON3_SETUP (1 << 22) +#define AR9_EBU_BUSCON3_WAIT (value) (((( 1 << 2) - 1) & (value)) << 20) +#define AR9_EBU_BUSCON3_WAITINV (1 << 19) +#define AR9_EBU_BUSCON3_VN_EN (1 << 18) +#define AR9_EBU_BUSCON3_PORTW (value) (((( 1 << 2) - 1) & (value)) << 16) +#define AR9_EBU_BUSCON3_ALEC (value) (((( 1 << 2) - 1) & (value)) << 14) +#define AR9_EBU_BUSCON3_BCGEN (value) (((( 1 << 2) - 1) & (value)) << 12) +#define AR9_EBU_BUSCON3_WAITWDC (value) (((( 1 << 4) - 1) & (value)) << 8) +#define AR9_EBU_BUSCON3_WAITRRC (value) (((( 1 << 2) - 1) & (value)) << 6) +#define AR9_EBU_BUSCON3_HOLDC (value) (((( 1 << 2) - 1) & (value)) << 4) +#define AR9_EBU_BUSCON3_RECOVC (value) (((( 1 << 2) - 1) & (value)) << 2) +#define AR9_EBU_BUSCON3_CMULT (value) (((( 1 << 2) - 1) & (value)) << 0) + +/***********************************************************************/ +/* Module : SDRAM register address and bits */ +/***********************************************************************/ +#define AR9_SDRAM (0xBF800000) + +/***********************************************************************/ +/* Module : ASC0 register address and bits */ +/***********************************************************************/ +#define AR9_ASC0 (KSEG1 | 0x1E100400) +#define AR9_ASC0_TBUF ((volatile u32*)(AR9_ASC0 + 0x0020)) +#define AR9_ASC0_RBUF ((volatile u32*)(AR9_ASC0 + 0x0024)) +#define AR9_ASC0_FSTAT ((volatile u32*)(AR9_ASC0 + 0x0048)) + +/***********************************************************************/ +/* Module : ASC1 register address and bits */ +/***********************************************************************/ +#define AR9_ASC1 (KSEG1 | 0x1E100C00) +#define AR9_ASC1_TBUF ((volatile u32*)(AR9_ASC1 + 0x0020)) +#define AR9_ASC1_RBUF ((volatile u32*)(AR9_ASC1 + 0x0024)) +#define AR9_ASC1_FSTAT ((volatile u32*)(AR9_ASC1 + 0x0048)) + +/***********************************************************************/ +/* Module : DMA register address and bits */ +/***********************************************************************/ +#define AR9_DMA_OFFSET (0xBE104100) +/***********************************************************************/ +#define AR9_DMA_CLC ((volatile u32*)(AR9_DMA_OFFSET + 0x0000)) +#define AR9_DMA_ID ((volatile u32*)(AR9_DMA_OFFSET + 0x0008)) +#define AR9_DMA_CTRL (volatile u32*)(AR9_DMA_BASE + 0x10) + +/** DMA Port Select Register */ +#define AR9_DMA_PS ((volatile u32*)(AR9_DMA_OFFSET + 0x0040)) +/** DMA Port Control Register */ +#define AR9_DMA_PCTRL ((volatile u32*)(AR9_DMA_OFFSET + 0x0044)) +#define AR9_DMA_IRNEN ((volatile u32*)(AR9_DMA_OFFSET + 0x00F4)) +#define AR9_DMA_IRNCR ((volatile u32*)(AR9_DMA_OFFSET + 0x00F8)) +#define AR9_DMA_IRNICR ((volatile u32*)(AR9_DMA_OFFSET + 0x00FC)) + +#define AR9_DMA_CS ((volatile u32*)(AR9_DMA_OFFSET + 0x0018)) +#define AR9_DMA_CCTRL ((volatile u32*)(AR9_DMA_OFFSET + 0x001C)) +#define AR9_DMA_CDBA ((volatile u32*)(AR9_DMA_OFFSET + 0x0020)) +#define AR9_DMA_CIE ((volatile u32*)(AR9_DMA_OFFSET + 0x002C)) +#define AR9_DMA_CIS ((volatile u32*)(AR9_DMA_OFFSET + 0x0028)) +#define AR9_DMA_CDLEN ((volatile u32*)(AR9_DMA_OFFSET + 0x0024)) +#define AR9_DMA_CPOLL ((volatile u32*)(AR9_DMA_OFFSET + 0x0014)) + +/***********************************************************************/ +/* Module : GPORT switch register */ +/***********************************************************************/ +#define AR9_SW (0xBE108000) +#define AR9_SW_PS (AR9_SW + 0x000) +#define AR9_SW_P0_CTL (AR9_SW + 0x004) +#define AR9_SW_P1_CTL (AR9_SW + 0x008) +#define AR9_SW_P2_CTL (AR9_SW + 0x00C) +#define AR9_SW_P0_VLAN (AR9_SW + 0x010) +#define AR9_SW_P1_VLAN (AR9_SW + 0x014) +#define AR9_SW_P2_VLAN (AR9_SW + 0x018) +#define AR9_SW_P0_INCTL (AR9_SW + 0x020) +#define AR9_SW_P1_INCTL (AR9_SW + 0x024) +#define AR9_SW_P2_INCTL (AR9_SW + 0x028) +#define AR9_SW_DF_PORTMAP (AR9_SW + 0x02C) +#define AR9_SW_P0_ECS_Q32 (AR9_SW + 0x030) +#define AR9_SW_P0_ECS_Q10 (AR9_SW + 0x034) +#define AR9_SW_P0_ECW_Q32 (AR9_SW + 0x038) +#define AR9_SW_P0_ECW_Q10 (AR9_SW + 0x03C) +#define AR9_SW_P1_ECS_Q32 (AR9_SW + 0x040) +#define AR9_SW_P1_ECS_Q10 (AR9_SW + 0x044) +#define AR9_SW_P1_ECW_Q32 (AR9_SW + 0x048) +#define AR9_SW_P1_ECW_Q10 (AR9_SW + 0x04C) +#define AR9_SW_P2_ECS_Q32 (AR9_SW + 0x050) +#define AR9_SW_P2_ECS_Q10 (AR9_SW + 0x054) +#define AR9_SW_P2_ECW_Q32 (AR9_SW + 0x058) +#define AR9_SW_P2_ECW_Q10 (AR9_SW + 0x05C) +#define AR9_SW_INT_ENA (AR9_SW + 0x060) +#define AR9_SW_INT_ST (AR9_SW + 0x064) +#define AR9_SW_GCTL0 (AR9_SW + 0x068) +#define AR9_SW_GCTL1 (AR9_SW + 0x06C) +#define AR9_SW_ARP (AR9_SW + 0x070) +#define AR9_SW_STRM_CTL (AR9_SW + 0x074) +#define AR9_SW_RGMII_CTL (AR9_SW + 0x078) +#define AR9_SW_1P_PRT (AR9_SW + 0x07C) +#define AR9_SW_GBKT_SZBS (AR9_SW + 0x080) +#define AR9_SW_GBKT_SZEBS (AR9_SW + 0x084) +#define AR9_SW_BF_TH (AR9_SW + 0x088) +#define AR9_SW_PMAC_HD_CTL (AR9_SW + 0x08C) +#define AR9_SW_PMAC_SA1 (AR9_SW + 0x090) +#define AR9_SW_PMAC_SA2 (AR9_SW + 0x094) +#define AR9_SW_PMAC_DA1 (AR9_SW + 0x098) +#define AR9_SW_PMAC_DA2 (AR9_SW + 0x09C) +#define AR9_SW_PMAC_VLAN (AR9_SW + 0x0A0) +#define AR9_SW_PMAC_TX_IPG (AR9_SW + 0x0A4) +#define AR9_SW_PMAC_RX_IPG (AR9_SW + 0x0A8) +#define AR9_SW_ADR_TB_CTL0 (AR9_SW + 0x0AC) +#define AR9_SW_ADR_TB_CTL1 (AR9_SW + 0x0B0) +#define AR9_SW_ADR_TB_CTL2 (AR9_SW + 0x0B4) +#define AR9_SW_ADR_TB_ST0 (AR9_SW + 0x0B8) +#define AR9_SW_ADR_TB_ST1 (AR9_SW + 0x0BC) +#define AR9_SW_ADR_TB_ST2 (AR9_SW + 0x0C0) +#define AR9_SW_RMON_CTL (AR9_SW + 0x0C4) +#define AR9_SW_RMON_ST (AR9_SW + 0x0C8) +#define AR9_SW_MDIO_CTL (AR9_SW + 0x0CC) +#define AR9_SW_MDIO_DATA (AR9_SW + 0x0D0) +#define AR9_SW_TP_FLT_ACT (AR9_SW + 0x0D4) +#define AR9_SW_PRTCL_FLT_ACT (AR9_SW + 0x0D8) +#define AR9_SW_VLAN_FLT0 (AR9_SW + 0x100) +#define AR9_SW_VLAN_FLT1 (AR9_SW + 0x104) +#define AR9_SW_VLAN_FLT2 (AR9_SW + 0x108) +#define AR9_SW_VLAN_FLT3 (AR9_SW + 0x10C) +#define AR9_SW_VLAN_FLT4 (AR9_SW + 0x110) +#define AR9_SW_VLAN_FLT5 (AR9_SW + 0x114) +#define AR9_SW_VLAN_FLT6 (AR9_SW + 0x118) +#define AR9_SW_VLAN_FLT7 (AR9_SW + 0x11C) +#define AR9_SW_VLAN_FLT8 (AR9_SW + 0x120) +#define AR9_SW_VLAN_FLT9 (AR9_SW + 0x124) +#define AR9_SW_VLAN_FLT10 (AR9_SW + 0x128) +#define AR9_SW_VLAN_FLT11 (AR9_SW + 0x12C) +#define AR9_SW_VLAN_FLT12 (AR9_SW + 0x130) +#define AR9_SW_VLAN_FLT13 (AR9_SW + 0x134) +#define AR9_SW_VLAN_FLT14 (AR9_SW + 0x138) +#define AR9_SW_VLAN_FLT15 (AR9_SW + 0x13C) +#define AR9_SW_TP_FLT10 (AR9_SW + 0x140) +#define AR9_SW_TP_FLT32 (AR9_SW + 0x144) +#define AR9_SW_TP_FLT54 (AR9_SW + 0x148) +#define AR9_SW_TP_FLT76 (AR9_SW + 0x14C) +#define AR9_SW_DFSRV_MAP0 (AR9_SW + 0x150) +#define AR9_SW_DFSRV_MAP1 (AR9_SW + 0x154) +#define AR9_SW_DFSRV_MAP2 (AR9_SW + 0x158) +#define AR9_SW_DFSRV_MAP3 (AR9_SW + 0x15C) +#define AR9_SW_TCP_PF0 (AR9_SW + 0x160) +#define AR9_SW_TCP_PF1 (AR9_SW + 0x164) +#define AR9_SW_TCP_PF2 (AR9_SW + 0x168) +#define AR9_SW_TCP_PF3 (AR9_SW + 0x16C) +#define AR9_SW_TCP_PF4 (AR9_SW + 0x170) +#define AR9_SW_TCP_PF5 (AR9_SW + 0x174) +#define AR9_SW_TCP_PF6 (AR9_SW + 0x178) +#define AR9_SW_TCP_PF7 (AR9_SW + 0x17C) +#define AR9_SW_RA_03_00 (AR9_SW + 0x180) +#define AR9_SW_RA_07_04 (AR9_SW + 0x184) +#define AR9_SW_RA_0B_08 (AR9_SW + 0x188) +#define AR9_SW_RA_0F_0C (AR9_SW + 0x18C) +#define AR9_SW_RA_13_10 (AR9_SW + 0x190) +#define AR9_SW_RA_17_14 (AR9_SW + 0x194) +#define AR9_SW_RA_1B_18 (AR9_SW + 0x198) +#define AR9_SW_RA_1F_1C (AR9_SW + 0x19C) +#define AR9_SW_RA_23_20 (AR9_SW + 0x1A0) +#define AR9_SW_RA_27_24 (AR9_SW + 0x1A4) +#define AR9_SW_RA_2B_28 (AR9_SW + 0x1A8) +#define AR9_SW_RA_2F_2C (AR9_SW + 0x1AC) +#define AR9_SW_F0 (AR9_SW + 0x1B0) +#define AR9_SW_F1 (AR9_SW + 0x1B4) + +#define REG32(addr) *((volatile u32 *)(addr)) diff --git a/package/uboot-lantiq/files/include/configs/easy50712.h b/package/uboot-lantiq/files/include/configs/easy50712.h index e061b831d..8eeb6c06a 100644 --- a/package/uboot-lantiq/files/include/configs/easy50712.h +++ b/package/uboot-lantiq/files/include/configs/easy50712.h @@ -112,4 +112,6 @@ # define CONFIG_EBU_BUSCON0 0x0001D7FF #endif +#define CONFIG_CMD_HTTPD /* enable upgrade via HTTPD */ + #endif /* __CONFIG_H */ diff --git a/package/uboot-lantiq/files/include/configs/easy50812.h b/package/uboot-lantiq/files/include/configs/easy50812.h new file mode 100644 index 000000000..c7e96c1bc --- /dev/null +++ b/package/uboot-lantiq/files/include/configs/easy50812.h @@ -0,0 +1,104 @@ +/* + * (C) Copyright 2003-2005 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +/* + * This file contains the configuration parameters for the Danube reference board. + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* #define DEBUG */ + +#define CONFIG_MIPS32 1 /* MIPS32 CPU compatible */ +#define CONFIG_MIPS34KC 1 /* MIPS 34Kc CPU core */ +#define CONFIG_AR9 1 /* an AR9 device */ +#define CONFIG_EASY50812 1 /* on the AR9 reference board */ +#define CONFIG_SYS_MAX_RAM 32*1024*1024 /* 32 MB */ +#define CONFIG_FLASH_CFI_DRIVER 1 /* using CFI flash driver */ + +#define CONFIG_SYS_INIT_RAM_LOCK_MIPS + +/* use PPL1 and fixed values for CPU / DDR and bus speed */ +#define CONFIG_USE_PLL1 +#define CONFIG_CPU_333M_RAM_166M +#define CONFIG_CLASS_II_DDR_PAD + +#ifdef CONFIG_SYS_RAMBOOT + #define CONFIG_SKIP_LOWLEVEL_INIT /* no cache */ +#else + #define CONFIG_SYS_EBU_BOOT + #define INFINEON_EBU_BOOTCFG 0x688C688C /* CMULT = 8 for 150 MHz */ +#endif + +#ifndef CPU_CLOCK_RATE +#define CPU_CLOCK_RATE (ifx_get_cpuclk()) +#endif + +#define CONFIG_SYS_PROMPT "AR9 => " /* Monitor Command Prompt */ +#undef CONFIG_SYS_HUSH_PARSER /* Use the HUSH parser */ + +/* + * Include common defines/options for all Lantiq boards + */ +#include "ifx-common.h" + +/* + * Cache Configuration (cpu/chip specific, ar9) + */ +#define CONFIG_SYS_DCACHE_SIZE (16384) +#define CONFIG_SYS_ICACHE_SIZE (16384) +#define CONFIG_SYS_CACHELINE_SIZE (32) +#define CONFIG_SYS_MIPS_CACHE_OPER_MODE CONF_CM_CACHABLE_NO_WA + +#define CONFIG_NET_MULTI +#if 0 +#define CONFIG_M4530_ETH +#define CONFIG_M4530_FPGA +#endif + +#define CONFIG_IFX_ETOP /* lantiq ethernet cpe interface */ +#define CLK_OUT2_25MHZ +#define CONFIG_EXTRA_SWITCH /* search for external switches like tantos */ +#define CONFIG_RMII /* use interface in RMII mode */ +#define CONFIG_MII +#define CONFIG_CMD_MII /* enable MII command */ + +#define CONFIG_IFX_ASC /* use lantiq ASC driver */ +#ifdef CONFIG_USE_ASC0 +#define CONFIG_SYS_IFX_ASC_BASE 0x1E100400 +#else +#define CONFIG_SYS_IFX_ASC_BASE 0x1E100C00 +#endif + +#ifdef CONFIG_SYS_RAMBOOT +/* Configuration of EBU: */ +/* starting address from 0xb0000000 */ +/* make the flash available from RAM boot */ +# define CONFIG_EBU_ADDSEL0 0x10000031 +# define CONFIG_EBU_BUSCON0 0x0001D7FF +#endif + +#define CONFIG_CMD_HTTPD /* enable upgrade via HTTPD */ + +#endif /* __CONFIG_H */ diff --git a/package/uboot-lantiq/patches/100-ifx_targets.patch b/package/uboot-lantiq/patches/100-ifx_targets.patch index 9c313e0a4..da4cd4864 100644 --- a/package/uboot-lantiq/patches/100-ifx_targets.patch +++ b/package/uboot-lantiq/patches/100-ifx_targets.patch @@ -23,7 +23,7 @@ ${LIST_au1xx0} \ --- a/Makefile +++ b/Makefile -@@ -474,7 +475,7 @@ $(obj)include/autoconf.mk: $(obj)include +@@ -474,7 +474,7 @@ $(obj)include/autoconf.mk: $(obj)include set -e ; \ : Extract the config macros ; \ $(CPP) $(CFLAGS) -DDO_DEPS_ONLY -dM include/common.h | \ @@ -32,7 +32,7 @@ mv $@.tmp $@ ######################################################################### -@@ -3354,7 +3355,7 @@ incaip_config: unconfig +@@ -3354,7 +3354,7 @@ incaip_config: unconfig { echo "#define CPU_CLOCK_RATE 150000000" >>$(obj)include/config.h ; \ $(XECHO) "... with 150MHz system clock" ; \ } @@ -41,7 +41,7 @@ tb0229_config: unconfig @$(MKCONFIG) $(@:_config=) mips mips tb0229 -@@ -3395,6 +3396,30 @@ vct_platinumavc_onenand_small_config: un +@@ -3395,6 +3395,50 @@ vct_platinumavc_onenand_small_config: un @$(MKCONFIG) -a vct mips mips vct micronas ######################################################################### @@ -68,6 +68,26 @@ + fi + @$(MKCONFIG) -a $(word 1,$(subst _, ,$@)) mips mips easy50712 infineon danube + ++easy50812%config : unconfig ++ @mkdir -p $(obj)include ++ @mkdir -p $(obj)board/infineon/easy50812 ++ @[ -z "$(findstring ramboot,$@)" ] || \ ++ { echo "TEXT_BASE = 0xA0400000" >$(obj)board/infineon/easy50812/config.tmp ; \ ++ echo "#define CONFIG_SYS_RAMBOOT" >>$(obj)include/config.h ; \ ++ $(XECHO) "... with ramboot configuration" ; \ ++ } ++ @if [ "$(findstring _DDR,$@)" ] ; then \ ++ echo "#define CONFIG_USE_DDR_RAM" >>$(obj)include/config.h ; \ ++ DDR=$(subst DDR,,$(filter DDR%,$(subst _, ,$@))); \ ++ case "$${DDR}" in \ ++ 111M|166M|e111M|e166M|promos400|samsung166|psc166) \ ++ $(XECHO) "... with DDR RAM config $${DDR}" ; \ ++ echo "#define CONFIG_USE_DDR_RAM_CFG_$${DDR}" >>$(obj)include/config.h ;; \ ++ *) $(XECHO) "... DDR RAM config \\\"$${DDR}\\\" unknown, use default"; \ ++ esac; \ ++ fi ++ @$(MKCONFIG) -a $(word 1,$(subst _, ,$@)) mips mips easy50812 infineon ar9 ++ +######################################################################### ## MIPS32 AU1X00 ######################################################################### diff --git a/package/uboot-lantiq/patches/300-httpd.patch b/package/uboot-lantiq/patches/300-httpd.patch new file mode 100644 index 000000000..25e84cde3 --- /dev/null +++ b/package/uboot-lantiq/patches/300-httpd.patch @@ -0,0 +1,9350 @@ +--- a/common/cmd_net.c ++++ b/common/cmd_net.c +@@ -43,6 +43,18 @@ U_BOOT_CMD( + "[loadAddress] [[hostIPaddr:]bootfilename]" + ); + ++#if defined(CONFIG_CMD_HTTPD) ++int do_httpd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) ++{ ++ return NetLoopHttpd(); ++} ++ ++U_BOOT_CMD( ++ httpd, 1, 1, do_httpd, ++ "httpd\t- start webserver\n", "\n" ++); ++#endif ++ + int do_tftpb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) + { + return netboot_common (TFTP, cmdtp, argc, argv); +--- a/include/net.h ++++ b/include/net.h +@@ -383,7 +383,8 @@ extern int NetTimeOffset; /* offset ti + + /* Initialize the network adapter */ + extern int NetLoop(proto_t); +- ++extern int NetLoopHttpd(void); ++extern void NetSendHttpd(void); + /* Shutdown adapters and cleanup */ + extern void NetStop(void); + +--- /dev/null ++++ b/net/httpd.c +@@ -0,0 +1,52 @@ ++/* ++ * Copyright 1994, 1995, 2000 Neil Russell. ++ * (See License) ++ * Copyright 2000, 2001 DENX Software Engineering, Wolfgang Denk, wd@denx.de ++ */ ++ ++#include ++#include ++#include ++#include "uip-0.9/uipopt.h" ++#include "uip-0.9/uip.h" ++#include "uip-0.9/uip_arp.h" ++ ++ ++#if defined(CONFIG_CMD_HTTPD) ++ ++#define TIMEOUT 5 ++ ++static int arptimer = 0; ++ ++void ++HttpdHandler (void) ++{ ++ int i; ++ for(i = 0; i < UIP_CONNS; i++) { ++ uip_periodic(i); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ NetSendHttpd(); ++ } ++ } ++ if(++arptimer == 20) { ++ uip_arp_timer(); ++ arptimer = 0; ++ } ++} ++ ++static void ++HttpdTimeout (void) ++{ ++ puts ("T "); ++ NetSetTimeout (TIMEOUT * 1000, HttpdTimeout); ++} ++ ++void ++HttpdStart (void) ++{ ++ uip_init(); ++ httpd_init(); ++} ++ ++#endif +--- /dev/null ++++ b/include/httpd.h +@@ -0,0 +1,17 @@ ++#ifndef _UIP_HTTPD_H__ ++#define _UIP_HTTPD_H__ ++ ++void HttpdStart (void); ++void HttpdHandler (void); ++ ++/* board specific implementation */ ++extern int do_http_upgrade(const unsigned char *data, const ulong size); ++ ++#define HTTP_PROGRESS_START 0 ++#define HTTP_PROGRESS_TIMEOUT 1 ++#define HTTP_PROGRESS_UPLOAD_READY 2 ++#define HTTP_PROGRESS_UGRADE_READY 3 ++#define HTTP_PROGRESS_UGRADE_FAILED 4 ++extern int do_http_progress(const int state); ++ ++#endif +--- a/net/Makefile ++++ b/net/Makefile +@@ -26,6 +26,10 @@ include $(TOPDIR)/config.mk + # CFLAGS += -DDEBUG + + LIB = $(obj)libnet.a ++UIPDIR = uip-0.9 ++RSADIR = uip-0.9 ++$(shell mkdir -p $(obj)$(UIPDIR)) ++$(shell mkdir -p $(obj)$(RSADIR)) + + COBJS-y += bootp.o + COBJS-$(CONFIG_CMD_DNS) += dns.o +@@ -36,6 +40,9 @@ COBJS-y += rarp.o + COBJS-$(CONFIG_CMD_SNTP) += sntp.o + COBJS-y += tftp.o + ++COBJS-$(CONFIG_CMD_HTTPD) += httpd.o $(UIPDIR)/fs.o $(UIPDIR)/httpd.o $(UIPDIR)/uip_arp.o $(UIPDIR)/uip_arch.o $(UIPDIR)/uip.o ++COBJS-$(CONFIG_CMD_RSA) += $(RSADIR)/bigint.o $(RSADIR)/base64.o $(RSADIR)/rmd160.o $(RSADIR)/rsa.o ++ + COBJS := $(COBJS-y) + SRCS := $(COBJS:.o=.c) + OBJS := $(addprefix $(obj),$(COBJS)) +--- a/net/net.c ++++ b/net/net.c +@@ -95,6 +95,19 @@ + #if defined(CONFIG_CMD_DNS) + #include "dns.h" + #endif ++#if defined(CONFIG_CMD_HTTPD) ++#include "httpd.h" ++#include "uip-0.9/uipopt.h" ++#include "uip-0.9/uip.h" ++#include "uip-0.9/uip_arp.h" ++static int https_running = 0; ++int httpd_upload_complete = 0; ++unsigned char *httpd_upload_data = 0; ++extern int upload_running; ++void NetReceiveHttpd(volatile uchar * inpkt, int len); ++void NetSendHttpd(void); ++extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); ++#endif + + #if defined(CONFIG_CMD_NET) + +@@ -1310,6 +1323,13 @@ NetReceive(volatile uchar * inpkt, int l + + debug("packet received\n"); + ++#if defined(CONFIG_CMD_HTTPD) ++ if(https_running) { ++ NetReceiveHttpd(inpkt, len); ++ return; ++ } ++#endif ++ + NetRxPacket = inpkt; + NetRxPacketLen = len; + et = (Ethernet_t *)inpkt; +@@ -1952,3 +1972,162 @@ ushort getenv_VLAN(char *var) + { + return (string_to_VLAN(getenv(var))); + } ++ ++#if defined(CONFIG_CMD_HTTPD) ++ ++void ++NetSendHttpd(void) ++{ ++ volatile uchar *tmpbuf = NetTxPacket; ++ int i; ++ ++ for(i = 0; i < 40 + UIP_LLH_LEN; i++) { ++ tmpbuf[i] = uip_buf[i]; ++ } ++ ++ for(; i < uip_len; i++) { ++ tmpbuf[i] = uip_appdata[i - 40 - UIP_LLH_LEN]; ++ } ++ eth_send(NetTxPacket, uip_len); ++} ++ ++#define BUF ((struct uip_eth_hdr *)&uip_buf[0]) ++ ++void ++NetReceiveHttpd(volatile uchar * inpkt, int len) ++{ ++ memcpy(uip_buf, inpkt, len); ++ uip_len = len; ++ if(BUF->type == htons(UIP_ETHTYPE_IP)) { ++ uip_arp_ipin(); ++ uip_input(); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ NetSendHttpd(); ++ } ++ } else if(BUF->type == htons(UIP_ETHTYPE_ARP)) { ++ uip_arp_arpin(); ++ if(uip_len > 0) { ++ NetSendHttpd(); ++ } ++ } ++} ++ ++int ++NetLoopHttpd(void) ++{ ++ unsigned long long tout = 0; ++ bd_t *bd = gd->bd; ++ unsigned short int ip[2]; ++ ++#ifdef CONFIG_NET_MULTI ++ NetRestarted = 0; ++ NetDevExists = 0; ++#endif ++ ++ /* XXX problem with bss workaround */ ++ NetArpWaitPacketMAC = NULL; ++ NetArpWaitTxPacket = NULL; ++ NetArpWaitPacketIP = 0; ++ NetArpWaitReplyIP = 0; ++ NetArpWaitTxPacket = NULL; ++ NetTxPacket = NULL; ++ NetTryCount = 1; ++ ++ if (!NetTxPacket) { ++ int i; ++ /* ++ * Setup packet buffers, aligned correctly. ++ */ ++ NetTxPacket = &PktBuf[0] + (PKTALIGN - 1); ++ NetTxPacket -= (ulong)NetTxPacket % PKTALIGN; ++ for (i = 0; i < PKTBUFSRX; i++) { ++ NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN; ++ } ++ } ++ ++ if (!NetArpWaitTxPacket) { ++ NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1); ++ NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN; ++ NetArpWaitTxPacketSize = 0; ++ } ++ ++restart: ++ ++ eth_halt(); ++#ifdef CONFIG_NET_MULTI ++ eth_set_current(); ++#endif ++ if (eth_init(bd) < 0) { ++ eth_halt(); ++ return(-1); ++ } ++ ++#ifdef CONFIG_NET_MULTI ++ memcpy (NetOurEther, eth_get_dev()->enetaddr, 6); ++#else ++ eth_getenv_enetaddr("ethaddr", NetOurEther); ++#endif ++ ++ NetCopyIP(&NetOurIP, &bd->bi_ip_addr); ++ NetOurGatewayIP = getenv_IPaddr ("gatewayip"); ++ NetOurSubnetMask= getenv_IPaddr ("netmask"); ++ NetOurVLAN = getenv_VLAN("vlan"); ++ NetOurNativeVLAN = getenv_VLAN("nvlan"); ++ ++ printf("starting httpd server from server %ld.%ld.%ld.%ld\n", ++ (bd->bi_ip_addr & 0xff000000) >> 24, ++ (bd->bi_ip_addr & 0x00ff0000) >> 16, ++ (bd->bi_ip_addr & 0x0000ff00) >> 8, ++ (bd->bi_ip_addr & 0x000000ff)); ++ ++ HttpdStart(); ++ ++ ip[0] = ((bd->bi_ip_addr & 0xffff0000) >> 16); ++ ip[1] = (bd->bi_ip_addr & 0x0000ffff); ++ uip_sethostaddr(ip); ++ ++ do_http_progress(HTTP_PROGRESS_START); ++ ++ https_running = 1; ++ for (;;) { ++ unsigned long long t1; ++ WATCHDOG_RESET(); ++ if(eth_rx() > 0) { ++ HttpdHandler(); ++ } else { ++ t1 = get_ticks(); ++ if(t1 - tout > 1000) { ++ do_http_progress(HTTP_PROGRESS_TIMEOUT); ++ tout = t1; ++ } ++ } ++ if(!httpd_upload_complete) ++ continue; ++ printf("Bytes transferred = %ld (%lx hex)\n", ++ NetBootFileXferSize, ++ NetBootFileXferSize); ++ eth_halt(); ++ do_http_progress(HTTP_PROGRESS_UPLOAD_READY); ++ if(do_http_upgrade(&httpd_upload_data[0], NetBootFileXferSize) == 0) { ++ do_http_progress(HTTP_PROGRESS_UGRADE_READY); ++ udelay(1000 * 10); ++ do_reset (0,0,0,0); ++ return 0; ++ } ++ break; ++ } ++ https_running = 0; ++ NetBootFileXferSize = 0; ++ httpd_upload_complete = 0; ++ upload_running = 0; ++// free(httpd_upload_data); ++ ++ do_http_progress(HTTP_PROGRESS_UGRADE_FAILED); ++ ++ goto restart; ++ ++ return -1; ++} ++ ++#endif +--- /dev/null ++++ b/net/rsa/base64.c +@@ -0,0 +1,137 @@ ++#include "base64.h" ++ ++static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; ++/* Note that '=' (padding) is 0 */ ++static const unsigned char fb64[256] = { ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63, ++ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255, ++ 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, ++ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255, ++ 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, ++ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, ++}; ++ ++static int encodeblock( unsigned char *in, char *out, int len ) ++{ ++ char s[3]; ++ int i; ++ ++ for (i = 0; i < len; i++) ++ s[i] = in[i]; ++ for (i = len; i < 3; i++) ++ s[i] = 0; ++ out[0] = (unsigned char)(cb64[(s[0] & 0xfc) >> 2 ]); ++ out[1] = (unsigned char)(cb64[((s[0] & 0x03) << 4) | ((s[1] & 0xf0) >> 4) ]); ++ out[2] = (unsigned char)(cb64[((s[1] & 0x0f) << 2) | ((s[2] & 0xc0) >> 6) ]); ++ out[3] = (unsigned char)(cb64[s[2] & 0x3f ]); ++ switch (len) { ++ case 1: ++ out[3] = '='; ++ case 2: ++ out[2] = '='; ++ break; ++ default: ++ break; ++ } ++ ++ return 4; ++} ++ ++static int decodeblock(char *ins, unsigned char *out, int len) ++{ ++ int i; ++ unsigned char in[4]; ++ int skip = 0; ++ ++ if (len != 4) ++ return -1; ++ for (i = 0; i < len; i++) { ++ if (ins[i] == '=') { ++ in[i] = 0; ++ skip++; ++ } else ++ in[i] = fb64[(int)(ins[i])]; ++ if (in[i] == 255) { ++ return -1; ++ } ++ } ++ out[0] = (unsigned char ) (in[0] << 2 | in[1] >> 4); ++ if (skip == 2) { ++ return 1; ++ } ++ out[1] = (unsigned char )((in[1] & 0x0f) << 4 | in[2] >> 2); ++ if (skip == 1) { ++ return 2; ++ } ++ out[2] = (unsigned char ) (((in[2] << 6) & 0xc0) | in[3]); ++ ++ return 3; ++} ++ ++int B64_encode(char *source, char *destination, int size_source, int size_destination) ++{ ++ int chunks, reminder, size, d, i, size_expected; ++ char *s; ++ unsigned char *t; ++ ++ chunks = size_source / 3; ++ reminder = size_source % 3; ++ size = 0; ++ size_expected = (chunks * 4) + (reminder?(reminder + 1):0); ++ if (size_destination < ((chunks * 4) + (reminder?4:0))) { ++ return 1; ++ } ++ for (i = 0; i < chunks; i++) { ++ s = source + (i * 3); ++ t = destination + (i * 4); ++ d = encodeblock(s, t, 3); ++ if (d == -1) { ++ return 1; ++ } ++ size += d; ++ } ++ if (reminder) { ++ d = encodeblock(source + (chunks * 3), destination + (chunks * 4), reminder); ++ if (d == -1) { ++ return 1; ++ } ++ size += d; ++ } ++ return size; ++} ++ ++int B64_decode(char *source, char *destination, int size_source, int size_destination) ++{ ++ int chunks, reminder, size, d, i; ++ ++ chunks = size_source / 4; ++ reminder = size_source % 4; ++ size = 0; ++ if (reminder) { ++ return 1; ++ } ++ if (size_destination < ((chunks * 3))) { ++ printf("%d, %d\n", ++ size_destination, ((chunks * 3) + reminder)); ++ return -1; ++ } ++ for (i = 0; i < chunks; i++) { ++ d = decodeblock(source + (i * 4), destination + (i * 3), 4); ++ if (d == -1) { ++ return -1; ++ } ++ size += d; ++ } ++ return size; ++} ++ +--- /dev/null ++++ b/net/rsa/base64.h +@@ -0,0 +1,11 @@ ++#ifndef _BASE64_H_ ++#define _BASE64_H_ ++#ifdef __cplusplus ++extern "C" { ++#endif ++int B64_encode(char *source, char *destination, int size_source, int size_destination); ++int B64_decode(char *source, char *destination, int size_source, int size_destination); ++#ifdef __cplusplus ++} ++#endif ++#endif +--- /dev/null ++++ b/net/rsa/bigint.c +@@ -0,0 +1,906 @@ ++/* ++ * Copyright(C) 2006 ++ * ++ * This library is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License as published by ++ * the Free Software Foundation; either version 2.1 of the License, or ++ * (at your option) any later version. ++ * ++ * This library 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 Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++/** ++ * @defgroup bigint_api Big Integer API ++ * @brief The bigint implementation as used by the axTLS project. ++ * ++ * The bigint library is for RSA encryption/decryption as well as signing. ++ * This code tries to minimise use of malloc/free by maintaining a small ++ * cache. A bigint context may maintain state by being made "permanent". ++ * It be be later released with a bi_depermanent() and bi_free() call. ++ * ++ * It supports the following reduction techniques: ++ * - Classical ++ * - Barrett ++ * - Montgomery ++ * ++ * It also implements the following: ++ * - Karatsuba multiplication ++ * - Squaring ++ * - Sliding window exponentiation ++ * - Chinese Remainder Theorem (implemented in rsa.c). ++ * ++ * All the algorithms used are pretty standard, and designed for different ++ * data bus sizes. Negative numbers are not dealt with at all, so a subtraction ++ * may need to be tested for negativity. ++ * ++ * This library steals some ideas from Jef Poskanzer ++ * ++ * and GMP . It gets most of its implementation ++ * detail from "The Handbook of Applied Cryptography" ++ * ++ * @{ ++ */ ++ ++#include "bigint.h" ++#include ++#include "div64.h" ++ ++static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bi, comp i); ++static bigint *bi_int_divide(BI_CTX *ctx, bigint *biR, comp denom); ++static bigint *alloc(BI_CTX *ctx, int size); ++static bigint *trim(bigint *bi); ++static void more_comps(bigint *bi, int n); ++ ++/** ++ * @brief Start a new bigint context. ++ * @return A bigint context. ++ */ ++BI_CTX *bi_initialize(void) ++{ ++ BI_CTX *ctx = (BI_CTX *)calloc(1, sizeof(BI_CTX)); ++ ++ ctx->active_list = NULL; ++ ctx->active_count = 0; ++ ctx->free_list = NULL; ++ ctx->free_count = 0; ++ ctx->mod_offset = 0; ++ ++ /* the radix */ ++ ctx->bi_radix = alloc(ctx, 2); ++ ctx->bi_radix->comps[0] = 0; ++ ctx->bi_radix->comps[1] = 1; ++ bi_permanent(ctx->bi_radix); ++ ++ return ctx; ++} ++ ++/** ++ * @brief Close the bigint context and free any resources. ++ * ++ * Free up any used memory - a check is done if all objects were not ++ * properly freed. ++ * @param ctx [in] The bigint session context. ++ */ ++void bi_terminate(BI_CTX *ctx) ++{ ++ bigint *p, *pn; ++ ++ bi_depermanent(ctx->bi_radix); ++ bi_free(ctx, ctx->bi_radix); ++ ++ if (ctx->active_count != 0) ++ { ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ return; ++ } ++ ++ for (p = ctx->free_list; p != NULL; p = pn) ++ { ++ pn = p->next; ++ free(p->comps); ++ free(p); ++ } ++ ++ free(ctx); ++} ++ ++/** ++ * @brief Increment the number of references to this object. ++ * It does not do a full copy. ++ * @param bi [in] The bigint to copy. ++ * @return A referent to the same bigint. ++ */ ++bigint *bi_copy(bigint *bi) ++{ ++ check(bi); ++ if (bi->refs != PERMANENT) ++ bi->refs++; ++ return bi; ++} ++ ++/** ++ * @brief Simply make a bigint object "unfreeable" if bi_free() is called on it. ++ * ++ * For this object to be freed, bi_depermanent() must be called. ++ * @param bi [in] The bigint to be made permanent. ++ */ ++void bi_permanent(bigint *bi) ++{ ++ check(bi); ++ if (bi->refs != 1) ++ { ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ return; ++ } ++ ++ bi->refs = PERMANENT; ++} ++ ++/** ++ * @brief Take a permanent object and make it elligible for freedom. ++ * @param bi [in] The bigint to be made back to temporary. ++ */ ++void bi_depermanent(bigint *bi) ++{ ++ check(bi); ++ if (bi->refs != PERMANENT) ++ { ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ return; ++ } ++ ++ bi->refs = 1; ++} ++ ++/** ++ * @brief Free a bigint object so it can be used again. ++ * ++ * The memory itself it not actually freed, just tagged as being available ++ * @param ctx [in] The bigint session context. ++ * @param bi [in] The bigint to be freed. ++ */ ++void bi_free(BI_CTX *ctx, bigint *bi) ++{ ++ check(bi); ++ if (bi->refs == PERMANENT) ++ { ++ return; ++ } ++ ++ if (--bi->refs > 0) ++ { ++ return; ++ } ++ ++ bi->next = ctx->free_list; ++ ctx->free_list = bi; ++ ctx->free_count++; ++ ++ if (--ctx->active_count < 0) ++ { ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ return; ++ } ++} ++ ++/** ++ * @brief Convert an (unsigned) integer into a bigint. ++ * @param ctx [in] The bigint session context. ++ * @param i [in] The (unsigned) integer to be converted. ++ * ++ */ ++bigint *int_to_bi(BI_CTX *ctx, comp i) ++{ ++ bigint *biR = alloc(ctx, 1); ++ biR->comps[0] = i; ++ return biR; ++} ++ ++/** ++ * @brief Do a full copy of the bigint object. ++ * @param ctx [in] The bigint session context. ++ * @param bi [in] The bigint object to be copied. ++ */ ++bigint *bi_clone(BI_CTX *ctx, const bigint *bi) ++{ ++ bigint *biR = alloc(ctx, bi->size); ++ check(bi); ++ memcpy(biR->comps, bi->comps, bi->size*COMP_BYTE_SIZE); ++ return biR; ++} ++ ++/** ++ * @brief Perform an additon operation between two bigints. ++ * @param ctx [in] The bigint session context. ++ * @param bia [in] A bigint. ++ * @param bib [in] Another bigint. ++ * @return The result of the addition. ++ */ ++bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib) ++{ ++ int n; ++ comp carry = 0; ++ comp *pa, *pb; ++ ++ check(bia); ++ check(bib); ++ ++ if (bia->size > bib->size) ++ n = bia->size; ++ else ++ n = bib->size; ++ more_comps(bia, n+1); ++ more_comps(bib, n); ++ pa = bia->comps; ++ pb = bib->comps; ++ ++ do ++ { ++ comp sl, rl, cy1; ++ sl = *pa + *pb++; ++ rl = sl + carry; ++ cy1 = sl < *pa; ++ carry = cy1 | (rl < sl); ++ *pa++ = rl; ++ } while (--n != 0); ++ ++ *pa = carry; /* do overflow */ ++ bi_free(ctx, bib); ++ return trim(bia); ++} ++ ++/** ++ * @brief Perform a subtraction operation between two bigints. ++ * @param ctx [in] The bigint session context. ++ * @param bia [in] A bigint. ++ * @param bib [in] Another bigint. ++ * @param is_negative [out] If defined, indicates that the result was negative. ++ * is_negative may be NULL. ++ * @return The result of the subtraction. The result is always positive. ++ */ ++bigint *bi_subtract(BI_CTX *ctx, ++ bigint *bia, bigint *bib, int *is_negative) ++{ ++ int n = bia->size; ++ comp *pa, *pb, carry = 0; ++ ++ check(bia); ++ check(bib); ++ ++ more_comps(bib, n); ++ pa = bia->comps; ++ pb = bib->comps; ++ ++ do ++ { ++ comp sl, rl, cy1; ++ sl = *pa - *pb++; ++ rl = sl - carry; ++ cy1 = sl > *pa; ++ carry = cy1 | (rl > sl); ++ *pa++ = rl; ++ } while (--n != 0); ++ ++ if (is_negative) /* indicate a negative result */ ++ { ++ *is_negative = carry; ++ } ++ ++ bi_free(ctx, trim(bib)); /* put bib back to the way it was */ ++ return trim(bia); ++} ++ ++/** ++ * Perform a multiply between a bigint an an (unsigned) integer ++ */ ++static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bia, comp b) ++{ ++ int j = 0, n = bia->size; ++ bigint *biR = alloc(ctx, n + 1); ++ comp carry = 0; ++ comp *r = biR->comps; ++ comp *a = bia->comps; ++ ++ check(bia); ++ ++ /* clear things to start with */ ++ memset(r, 0, ((n+1)*COMP_BYTE_SIZE)); ++ ++ do ++ { ++ long_comp tmp = *r + (long_comp)a[j]*b + carry; ++ *r++ = (comp)tmp; /* downsize */ ++ carry = (comp)(tmp >> COMP_BIT_SIZE); ++ } while (++j < n); ++ ++ *r = carry; ++ bi_free(ctx, bia); ++ return trim(biR); ++} ++ ++/** ++ * @brief Does both division and modulo calculations. ++ * ++ * Used extensively when doing classical reduction. ++ * @param ctx [in] The bigint session context. ++ * @param u [in] A bigint which is the numerator. ++ * @param v [in] Either the denominator or the modulus depending on the mode. ++ * @param is_mod [n] Determines if this is a normal division (0) or a reduction ++ * (1). ++ * @return The result of the division/reduction. ++ */ ++bigint *bi_divide(BI_CTX *ctx, bigint *u, bigint *v, int is_mod) ++{ ++ int n = v->size, m = u->size-n; ++ int j = 0, orig_u_size = u->size; ++ uint8_t mod_offset = ctx->mod_offset; ++ comp d; ++ bigint *quotient, *tmp_u; ++ comp q_dash; ++ ++ check(u); ++ check(v); ++ ++ /* if doing reduction and we are < mod, then return mod */ ++ if (is_mod && bi_compare(v, u) > 0) ++ { ++ bi_free(ctx, v); ++ return u; ++ } ++ ++ quotient = alloc(ctx, m+1); ++ tmp_u = alloc(ctx, n+1); ++ v = trim(v); /* make sure we have no leading 0's */ ++ // d = (comp)((long_comp)COMP_RADIX/(V1+1)); ++ long_comp x = COMP_RADIX; do_div(x, V1+1); d = x; ++ ++ /* clear things to start with */ ++ memset(quotient->comps, 0, ((quotient->size)*COMP_BYTE_SIZE)); ++ ++ /* normalise */ ++ if (d > 1) ++ { ++ u = bi_int_multiply(ctx, u, d); ++ ++ if (is_mod) ++ { ++ v = ctx->bi_normalised_mod[mod_offset]; ++ } ++ else ++ { ++ v = bi_int_multiply(ctx, v, d); ++ } ++ } ++ ++ if (orig_u_size == u->size) /* new digit position u0 */ ++ { ++ more_comps(u, orig_u_size + 1); ++ } ++ ++ do ++ { ++ /* get a temporary short version of u */ ++ memcpy(tmp_u->comps, &u->comps[u->size-n-1-j], (n+1)*COMP_BYTE_SIZE); ++ ++ /* calculate q' */ ++ if (U(0) == V1) ++ { ++ q_dash = COMP_RADIX-1; ++ } ++ else ++ { ++ //q_dash = (comp)(((long_comp)U(0)*COMP_RADIX + U(1))/V1); ++ long_comp x = U(0)*COMP_RADIX + U(1); do_div(x, V1); q_dash = x; ++ ++ } ++ ++ if (v->size > 1 && V2) ++ { ++ /* we are implementing the following ++ if (V2*q_dash > (((U(0)*COMP_RADIX + U(1) - ++ q_dash*V1)*COMP_RADIX) + U(2))) ... */ ++ comp inner = (comp)((long_comp)COMP_RADIX*U(0) + U(1) - ++ (long_comp)q_dash*V1); ++ if ((long_comp)V2*q_dash > (long_comp)inner*COMP_RADIX + U(2)) ++ { ++ q_dash--; ++ } ++ } ++ ++ /* multiply and subtract */ ++ if (q_dash) ++ { ++ int is_negative; ++ tmp_u = bi_subtract(ctx, tmp_u, ++ bi_int_multiply(ctx, bi_copy(v), q_dash), &is_negative); ++ more_comps(tmp_u, n+1); ++ ++ Q(j) = q_dash; ++ ++ /* add back */ ++ if (is_negative) ++ { ++ Q(j)--; ++ tmp_u = bi_add(ctx, tmp_u, bi_copy(v)); ++ /* lop off the carry */ ++ tmp_u->size--; ++ v->size--; ++ } ++ } ++ else ++ { ++ Q(j) = 0; ++ } ++ ++ /* copy back to u */ ++ memcpy(&u->comps[u->size-n-1-j], tmp_u->comps, (n+1)*COMP_BYTE_SIZE); ++ } while (++j <= m); ++ ++ bi_free(ctx, tmp_u); ++ bi_free(ctx, v); ++ ++ if (is_mod) /* get the remainder */ ++ { ++ bi_free(ctx, quotient); ++ return bi_int_divide(ctx, trim(u), d); ++ } ++ else /* get the quotient */ ++ { ++ bi_free(ctx, u); ++ return trim(quotient); ++ } ++} ++ ++/** ++ * Perform an integer divide on a bigint. ++ */ ++static bigint *bi_int_divide(BI_CTX *ctx, bigint *biR, comp denom) ++{ ++ int i = biR->size - 1; ++ long_comp r = 0; ++ ++ check(biR); ++ ++ do ++ { ++ r = (r<comps[i]; ++ //biR->comps[i] = (comp)(r / denom); ++ long_comp x = r; do_div(x, denom); biR->comps[i] = x; ++/* while(r > denom) ++ { ++ r -= denom; ++ }*/ ++ r%=denom; ++ } while (--i != 0); ++ ++ return trim(biR); ++} ++ ++/** ++ * @brief Allow a binary sequence to be imported as a bigint. ++ * @param ctx [in] The bigint session context. ++ * @param data [in] The data to be converted. ++ * @param size [in] The number of bytes of data. ++ * @return A bigint representing this data. ++ */ ++bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int size) ++{ ++ bigint *biR = alloc(ctx, (size+COMP_BYTE_SIZE-1)/COMP_BYTE_SIZE); ++ int i, j = 0, offset = 0; ++ ++ memset(biR->comps, 0, biR->size*COMP_BYTE_SIZE); ++ ++ for (i = size-1; i >= 0; i--) ++ { ++ biR->comps[offset] += data[i] << (j*8); ++ ++ if (++j == COMP_BYTE_SIZE) ++ { ++ j = 0; ++ offset ++; ++ } ++ } ++ ++ return trim(biR); ++} ++ ++/** ++ * @brief Take a bigint and convert it into a byte sequence. ++ * ++ * This is useful after a decrypt operation. ++ * @param ctx [in] The bigint session context. ++ * @param x [in] The bigint to be converted. ++ * @param data [out] The converted data as a byte stream. ++ * @param size [in] The maximum size of the byte stream. Unused bytes will be ++ * zeroed. ++ */ ++void bi_export(BI_CTX *ctx, bigint *x, uint8_t *data, int size) ++{ ++ int i, j, k = size-1; ++ ++ check(x); ++ memset(data, 0, size); /* ensure all leading 0's are cleared */ ++ ++ for (i = 0; i < x->size; i++) ++ { ++ for (j = 0; j < COMP_BYTE_SIZE; j++) ++ { ++ comp mask = 0xff << (j*8); ++ int num = (x->comps[i] & mask) >> (j*8); ++ data[k--] = num; ++ ++ if (k < 0) ++ { ++ break; ++ } ++ } ++ } ++ ++ bi_free(ctx, x); ++} ++ ++/** ++ * @brief Pre-calculate some of the expensive steps in reduction. ++ * ++ * This function should only be called once (normally when a session starts). ++ * When the session is over, bi_free_mod() should be called. bi_mod_power() ++ * relies on this function being called. ++ * @param ctx [in] The bigint session context. ++ * @param bim [in] The bigint modulus that will be used. ++ * @param mod_offset [in] There are three moduluii that can be stored - the ++ * standard modulus, and it's two primes p and q. This offset refers to which ++ * modulus we are referring to. ++ * @see bi_free_mod(), bi_mod_power(). ++ */ ++void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset) ++{ ++ int k = bim->size; ++ comp d; ++// comp d = (comp)((long_comp)COMP_RADIX/(bim->comps[k-1]+1)); ++ long_comp x = COMP_RADIX; do_div(x, bim->comps[k-1]+1); d = x; ++ ++ ctx->bi_mod[mod_offset] = bim; ++ bi_permanent(ctx->bi_mod[mod_offset]); ++ ctx->bi_normalised_mod[mod_offset] = bi_int_multiply(ctx, bim, d); ++ bi_permanent(ctx->bi_normalised_mod[mod_offset]); ++} ++ ++/** ++ * @brief Used when cleaning various bigints at the end of a session. ++ * @param ctx [in] The bigint session context. ++ * @param mod_offset [in] The offset to use. ++ * @see bi_set_mod(). ++ */ ++void bi_free_mod(BI_CTX *ctx, int mod_offset) ++{ ++ bi_depermanent(ctx->bi_mod[mod_offset]); ++ bi_free(ctx, ctx->bi_mod[mod_offset]); ++ bi_depermanent(ctx->bi_normalised_mod[mod_offset]); ++ bi_free(ctx, ctx->bi_normalised_mod[mod_offset]); ++} ++ ++/** ++ * Perform a standard multiplication between two bigints. ++ */ ++static bigint *regular_multiply(BI_CTX *ctx, bigint *bia, bigint *bib) ++{ ++ int i, j, i_plus_j, n = bia->size, t = bib->size; ++ bigint *biR = alloc(ctx, n + t); ++ comp *sr = biR->comps; ++ comp *sa = bia->comps; ++ comp *sb = bib->comps; ++ ++ check(bia); ++ check(bib); ++ ++ /* clear things to start with */ ++ memset(biR->comps, 0, ((n+t)*COMP_BYTE_SIZE)); ++ i = 0; ++ ++ do ++ { ++ comp carry = 0; ++ comp b = *sb++; ++ i_plus_j = i; ++ j = 0; ++ ++ do ++ { ++ long_comp tmp = sr[i_plus_j] + (long_comp)sa[j]*b + carry; ++ sr[i_plus_j++] = (comp)tmp; /* downsize */ ++ carry = (comp)(tmp >> COMP_BIT_SIZE); ++ } while (++j < n); ++ ++ sr[i_plus_j] = carry; ++ } while (++i < t); ++ ++ bi_free(ctx, bia); ++ bi_free(ctx, bib); ++ return trim(biR); ++} ++ ++/** ++ * @brief Perform a multiplication operation between two bigints. ++ * @param ctx [in] The bigint session context. ++ * @param bia [in] A bigint. ++ * @param bib [in] Another bigint. ++ * @return The result of the multiplication. ++ */ ++bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib) ++{ ++ check(bia); ++ check(bib); ++ ++ return regular_multiply(ctx, bia, bib); ++} ++ ++ ++/** ++ * @brief Compare two bigints. ++ * @param bia [in] A bigint. ++ * @param bib [in] Another bigint. ++ * @return -1 if smaller, 1 if larger and 0 if equal. ++ */ ++int bi_compare(bigint *bia, bigint *bib) ++{ ++ int r, i; ++ ++ check(bia); ++ check(bib); ++ ++ if (bia->size > bib->size) ++ r = 1; ++ else if (bia->size < bib->size) ++ r = -1; ++ else ++ { ++ comp *a = bia->comps; ++ comp *b = bib->comps; ++ ++ /* Same number of components. Compare starting from the high end ++ * and working down. */ ++ r = 0; ++ i = bia->size - 1; ++ ++ do ++ { ++ if (a[i] > b[i]) ++ { ++ r = 1; ++ break; ++ } ++ else if (a[i] < b[i]) ++ { ++ r = -1; ++ break; ++ } ++ } while (--i >= 0); ++ } ++ ++ return r; ++} ++ ++/** ++ * Allocate and zero more components. Does not consume bi. ++ */ ++static void more_comps(bigint *bi, int n) ++{ ++ if (n > bi->max_comps) ++ { ++ if ((bi->max_comps * 2) > n) { ++ bi->max_comps = bi->max_comps * 2; ++ } else { ++ bi->max_comps = n; ++ } ++ bi->comps = (comp*)realloc(bi->comps, bi->max_comps * COMP_BYTE_SIZE); ++ } ++ ++ if (n > bi->size) ++ { ++ memset(&bi->comps[bi->size], 0, (n-bi->size)*COMP_BYTE_SIZE); ++ } ++ ++ bi->size = n; ++} ++ ++/* ++ * Make a new empty bigint. It may just use an old one if one is available. ++ * Otherwise get one of the heap. ++ */ ++static bigint *alloc(BI_CTX *ctx, int size) ++{ ++ bigint *biR; ++ ++ /* Can we recycle an old bigint? */ ++ if (ctx->free_list != NULL) ++ { ++ biR = ctx->free_list; ++ ctx->free_list = biR->next; ++ ctx->free_count--; ++ if (biR->refs != 0) ++ { ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); ++ return 0; ++ } ++ ++ more_comps(biR, size); ++ } ++ else ++ { ++ /* No free bigints available - create a new one. */ ++ biR = (bigint *)malloc(sizeof(bigint)); ++ biR->comps = (comp*) malloc(size * COMP_BYTE_SIZE); ++ biR->max_comps = size; /* give some space to spare */ ++ } ++ ++ biR->size = size; ++ biR->refs = 1; ++ biR->next = NULL; ++ ctx->active_count++; ++ return biR; ++} ++ ++/* ++ * Work out the highest '1' bit in an exponent. Used when doing sliding-window ++ * exponentiation. ++ */ ++static int find_max_exp_index(bigint *biexp) ++{ ++ int i = COMP_BIT_SIZE-1; ++ comp shift = COMP_RADIX/2; ++ comp test = biexp->comps[biexp->size-1]; /* assume no leading zeroes */ ++ ++ check(biexp); ++ ++ do ++ { ++ if (test & shift) ++ { ++ return i+(biexp->size-1)*COMP_BIT_SIZE; ++ } ++ ++ shift >>= 1; ++ } while (--i != 0); ++ ++ return -1; /* error - must have been a leading 0 */ ++} ++ ++/* ++ * Is a particular bit is an exponent 1 or 0? Used when doing sliding-window ++ * exponentiation. ++ */ ++static int exp_bit_is_one(bigint *biexp, int offset) ++{ ++ comp test = biexp->comps[offset / COMP_BIT_SIZE]; ++ int num_shifts = offset % COMP_BIT_SIZE; ++ comp shift = 1; ++ int i; ++ ++ check(biexp); ++ ++ for (i = 0; i < num_shifts; i++) ++ { ++ shift <<= 1; ++ } ++ ++ return test & shift; ++} ++ ++/* ++ * Delete any leading 0's (and allow for 0). ++ */ ++static bigint *trim(bigint *bi) ++{ ++ check(bi); ++ ++ while (bi->comps[bi->size-1] == 0 && bi->size > 1) ++ { ++ bi->size--; ++ } ++ ++ return bi; ++} ++ ++/** ++ * @brief Perform a modular exponentiation. ++ * ++ * This function requires bi_set_mod() to have been called previously. This is ++ * one of the optimisations used for performance. ++ * @param ctx [in] The bigint session context. ++ * @param bi [in] The bigint on which to perform the mod power operation. ++ * @param biexp [in] The bigint exponent. ++ * @see bi_set_mod(). ++ */ ++bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp) ++{ ++ int i = find_max_exp_index(biexp), j, window_size = 1; ++ bigint *biR = int_to_bi(ctx, 1); ++ ++ check(bi); ++ check(biexp); ++ ++ ctx->g = (bigint **)malloc(sizeof(bigint *)); ++ ctx->g[0] = bi_clone(ctx, bi); ++ ctx->window = 1; ++ bi_permanent(ctx->g[0]); ++ ++ /* if sliding-window is off, then only one bit will be done at a time and ++ * will reduce to standard left-to-right exponentiation */ ++ do ++ { ++ if (exp_bit_is_one(biexp, i)) ++ { ++ int l = i-window_size+1; ++ int part_exp = 0; ++ ++ if (l < 0) /* LSB of exponent will always be 1 */ ++ { ++ l = 0; ++ } ++ else ++ { ++ while (exp_bit_is_one(biexp, l) == 0) ++ { ++ l++; /* go back up */ ++ } ++ } ++ ++ /* build up the section of the exponent */ ++ for (j = i; j >= l; j--) ++ { ++ biR = bi_residue(ctx, bi_square(ctx, biR)); ++ if (exp_bit_is_one(biexp, j)) ++ part_exp++; ++ ++ if (j != l) ++ part_exp <<= 1; ++ } ++ ++ part_exp = (part_exp-1)/2; /* adjust for array */ ++ biR = bi_residue(ctx, ++ bi_multiply(ctx, biR, ctx->g[part_exp])); ++ i = l-1; ++ } ++ else /* square it */ ++ { ++ biR = bi_residue(ctx, bi_square(ctx, biR)); ++ i--; ++ } ++ } while (i >= 0); ++ ++ /* cleanup */ ++ for (i = 0; i < ctx->window; i++) ++ { ++ bi_depermanent(ctx->g[i]); ++ bi_free(ctx, ctx->g[i]); ++ } ++ ++ free(ctx->g); ++ bi_free(ctx, bi); ++ bi_free(ctx, biexp); ++ return biR; ++} ++ ++/** @} */ +--- /dev/null ++++ b/net/rsa/bigint.h +@@ -0,0 +1,73 @@ ++/* ++ * Copyright(C) 2006 ++ * ++ * This library is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This library 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 Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * Trimmed down from axTLS ++ * ++ * $Id: bigint.h 392 2007-06-25 16:24:51Z pablo.martin $ ++ * ++ */ ++ ++#ifndef BIGINT_HEADER ++#define BIGINT_HEADER ++ ++#define CONFIG_BIGINT_CLASSICAL 1 ++ ++#define SOCKET_READ(A,B,C) read(A,B,C) ++#define SOCKET_WRITE(A,B,C) write(A,B,C) ++#define SOCKET_CLOSE(A) close(A) ++#define TTY_FLUSH() ++ ++#include "bigint_impl.h" ++ ++#ifndef CONFIG_BIGINT_CHECK_ON ++#define check(A) /**< disappears in normal production mode */ ++#endif ++BI_CTX *bi_initialize(void); ++void bi_terminate(BI_CTX *ctx); ++void bi_permanent(bigint *bi); ++void bi_depermanent(bigint *bi); ++void bi_free(BI_CTX *ctx, bigint *bi); ++bigint *bi_copy(bigint *bi); ++bigint *bi_clone(BI_CTX *ctx, const bigint *bi); ++void bi_export(BI_CTX *ctx, bigint *bi, uint8_t *data, int size); ++bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int len); ++bigint *int_to_bi(BI_CTX *ctx, comp i); ++ ++/* the functions that actually do something interesting */ ++bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib); ++bigint *bi_subtract(BI_CTX *ctx, bigint *bia, ++ bigint *bib, int *is_negative); ++bigint *bi_divide(BI_CTX *ctx, bigint *bia, bigint *bim, int is_mod); ++bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib); ++bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp); ++bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi, bigint *bim, bigint *biexp); ++int bi_compare(bigint *bia, bigint *bib); ++void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset); ++void bi_free_mod(BI_CTX *ctx, int mod_offset); ++ ++/** ++ * @def bi_mod ++ * Find the residue of B. bi_set_mod() must be called before hand. ++ */ ++#define bi_mod(A, B) bi_divide(A, B, ctx->bi_mod[ctx->mod_offset], 1) ++ ++#define bi_residue(A, B) bi_mod(A, B) ++ ++#define bi_square(A, B) bi_multiply(A, bi_copy(B), B) ++ ++#endif ++ +--- /dev/null ++++ b/net/rsa/bigint_impl.h +@@ -0,0 +1,109 @@ ++/* ++ * Copyright(C) 2006 ++ * ++ * This library is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License as published by ++ * the Free Software Foundation; either version 2.1 of the License, or ++ * (at your option) any later version. ++ * ++ * This library 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 Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#ifndef BIGINT_IMPL_HEADER ++#define BIGINT_IMPL_HEADER ++ ++#include ++#include ++ ++/* Maintain a number of precomputed variables when doing reduction */ ++#define BIGINT_M_OFFSET 0 /**< Normal modulo offset. */ ++#ifdef CONFIG_BIGINT_CRT ++#define BIGINT_P_OFFSET 1 /**< p modulo offset. */ ++#define BIGINT_Q_OFFSET 2 /**< q module offset. */ ++#define BIGINT_NUM_MODS 3 /**< The number of modulus constants used. */ ++#else ++#define BIGINT_NUM_MODS 1 ++#endif ++ ++/* Architecture specific functions for big ints */ ++// #ifdef WIN32 ++// #define COMP_RADIX 4294967296i64 ++// #define COMP_BIG_MSB 0x8000000000000000i64 ++// #else ++#define COMP_RADIX 4294967296ULL /**< Max component + 1 */ ++#define COMP_BIG_MSB 0x8000000000000000ULL /**< (Max dbl comp + 1)/ 2 */ ++//#endif ++#define COMP_BIT_SIZE 32 /**< Number of bits in a component. */ ++#define COMP_BYTE_SIZE 4 /**< Number of bytes in a component. */ ++#define COMP_NUM_NIBBLES 8 /**< Used For diagnostics only. */ ++ ++typedef uint32_t comp; /**< A single precision component. */ ++typedef uint64_t long_comp; /**< A double precision component. */ ++typedef int64_t slong_comp; /**< A signed double precision component. */ ++ ++/** ++ * @struct _bigint ++ * @brief A big integer basic object ++ */ ++struct _bigint ++{ ++ struct _bigint* next; /**< The next bigint in the cache. */ ++ short size; /**< The number of components in this bigint. */ ++ short max_comps; /**< The heapsize allocated for this bigint */ ++ int refs; /**< An internal reference count. */ ++ comp* comps; /**< A ptr to the actual component data */ ++}; ++ ++typedef struct _bigint bigint; /**< An alias for _bigint */ ++ ++/** ++ * Maintains the state of the cache, and a number of variables used in ++ * reduction. ++ */ ++typedef struct /**< A big integer "session" context. */ ++{ ++ bigint *active_list; /**< Bigints currently used. */ ++ bigint *free_list; /**< Bigints not used. */ ++ bigint *bi_radix; /**< The radix used. */ ++ bigint *bi_mod[BIGINT_NUM_MODS]; /**< modulus */ ++ ++#if defined(CONFIG_BIGINT_MONTGOMERY) ++ bigint *bi_RR_mod_m[BIGINT_NUM_MODS]; /**< R^2 mod m */ ++ bigint *bi_R_mod_m[BIGINT_NUM_MODS]; /**< R mod m */ ++ comp N0_dash[BIGINT_NUM_MODS]; ++#elif defined(CONFIG_BIGINT_BARRETT) ++ bigint *bi_mu[BIGINT_NUM_MODS]; /**< Storage for mu */ ++#endif ++ bigint *bi_normalised_mod[BIGINT_NUM_MODS]; /**< Normalised mod storage. */ ++ bigint **g; /**< Used by sliding-window. */ ++ int window; /**< The size of the sliding window */ ++ ++ int active_count; /**< Number of active bigints. */ ++ int free_count; /**< Number of free bigints. */ ++ ++#ifdef CONFIG_BIGINT_MONTGOMERY ++ uint8_t use_classical; /**< Use classical reduction. */ ++#endif ++ uint8_t mod_offset; /**< The mod offset we are using */ ++} BI_CTX; ++ ++#if 0 ++#define max(a,b) ((a)>(b)?(a):(b)) /**< Find the maximum of 2 numbers. */ ++#define min(a,b) ((a)<(b)?(a):(b)) /**< Find the minimum of 2 numbers. */ ++#endif ++ ++#define PERMANENT 0x7FFF55AA /**< A magic number for permanents. */ ++ ++#define V1 v->comps[v->size-1] /**< v1 for division */ ++#define V2 v->comps[v->size-2] /**< v2 for division */ ++#define U(j) tmp_u->comps[tmp_u->size-j-1] /**< uj for division */ ++#define Q(j) quotient->comps[quotient->size-j-1] /**< qj for division */ ++ ++#endif +--- /dev/null ++++ b/net/rsa/div64.h +@@ -0,0 +1,113 @@ ++/* ++ * Copyright (C) 2000, 2004 Maciej W. Rozycki ++ * Copyright (C) 2003 Ralf Baechle ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file "COPYING" in the main directory of this archive ++ * for more details. ++ */ ++#ifndef _ASM_DIV64_H ++#define _ASM_DIV64_H ++ ++#if (_MIPS_SZLONG == 32) ++ ++#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) ++#define GCC_REG_ACCUM "$0" ++#else ++#define GCC_REG_ACCUM "accum" ++#endif ++ ++ ++//#include ++ ++/* ++ * No traps on overflows for any of these... ++ */ ++ ++#define do_div64_32(res, high, low, base) ({ \ ++ unsigned long __quot, __mod; \ ++ unsigned long __cf, __tmp, __tmp2, __i; \ ++ \ ++ __asm__(".set push\n\t" \ ++ ".set noat\n\t" \ ++ ".set noreorder\n\t" \ ++ "move %2, $0\n\t" \ ++ "move %3, $0\n\t" \ ++ "b 1f\n\t" \ ++ " li %4, 0x21\n" \ ++ "0:\n\t" \ ++ "sll $1, %0, 0x1\n\t" \ ++ "srl %3, %0, 0x1f\n\t" \ ++ "or %0, $1, %5\n\t" \ ++ "sll %1, %1, 0x1\n\t" \ ++ "sll %2, %2, 0x1\n" \ ++ "1:\n\t" \ ++ "bnez %3, 2f\n\t" \ ++ " sltu %5, %0, %z6\n\t" \ ++ "bnez %5, 3f\n" \ ++ "2:\n\t" \ ++ " addiu %4, %4, -1\n\t" \ ++ "subu %0, %0, %z6\n\t" \ ++ "addiu %2, %2, 1\n" \ ++ "3:\n\t" \ ++ "bnez %4, 0b\n\t" \ ++ " srl %5, %1, 0x1f\n\t" \ ++ ".set pop" \ ++ : "=&r" (__mod), "=&r" (__tmp), "=&r" (__quot), "=&r" (__cf), \ ++ "=&r" (__i), "=&r" (__tmp2) \ ++ : "Jr" (base), "0" (high), "1" (low)); \ ++ \ ++ (res) = __quot; \ ++ __mod; }) ++ ++#define do_div(n, base) ({ \ ++ unsigned long long __quot; \ ++ unsigned long __mod; \ ++ unsigned long long __div; \ ++ unsigned long __upper, __low, __high, __base; \ ++ \ ++ __div = (n); \ ++ __base = (base); \ ++ \ ++ __high = __div >> 32; \ ++ __low = __div; \ ++ __upper = __high; \ ++ \ ++ if (__high) \ ++ __asm__("divu $0, %z2, %z3" \ ++ : "=h" (__upper), "=l" (__high) \ ++ : "Jr" (__high), "Jr" (__base) \ ++ : GCC_REG_ACCUM); \ ++ \ ++ __mod = do_div64_32(__low, __upper, __low, __base); \ ++ \ ++ __quot = __high; \ ++ __quot = __quot << 32 | __low; \ ++ (n) = __quot; \ ++ __mod; }) ++#endif /* (_MIPS_SZLONG == 32) */ ++ ++#if (_MIPS_SZLONG == 64) ++ ++/* ++ * Hey, we're already 64-bit, no ++ * need to play games.. ++ */ ++#define do_div(n, base) ({ \ ++ unsigned long __quot; \ ++ unsigned int __mod; \ ++ unsigned long __div; \ ++ unsigned int __base; \ ++ \ ++ __div = (n); \ ++ __base = (base); \ ++ \ ++ __mod = __div % __base; \ ++ __quot = __div / __base; \ ++ \ ++ (n) = __quot; \ ++ __mod; }) ++ ++#endif /* (_MIPS_SZLONG == 64) */ ++ ++#endif /* _ASM_DIV64_H */ +--- /dev/null ++++ b/net/rsa/dump_key.c +@@ -0,0 +1,29 @@ ++#include ++#include ++#include ++#include ++#include ++ ++int main(int argc, char **argv) ++{ ++ FILE *fp = fopen("public_fon_rsa_key_6.pem", "r"); ++ struct stat s; ++ unsigned char *b; ++ int i; ++ if(!fp) ++ return 1; ++ stat("public_fon_rsa_key_6.pem", &s); ++ b = malloc(s.st_size); ++ fread(b, s.st_size, 1, fp); ++ fclose(fp); ++ printf("unsigned char public_key[] = {\n\t"); ++ for(i = 0;i < s.st_size; i++) ++ { ++ printf("0x%02X,", b[i]); ++ if(i%16 == 15) ++ printf("\n\t"); ++ } ++ printf("};\n"); ++// printf("\n%d %d\n", i, s.st_size); ++ return 0; ++} +--- /dev/null ++++ b/net/rsa/foncheckrsa.c +@@ -0,0 +1,79 @@ ++/* ++ * RSA + RIPEMD160 signature verification command ++ * ++ * Copyright (C) 2007 FON Wireless Ltd. ++ * ++ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ * ++ * Created: 20060728 Pablo Martín Medrano ++ * ++ * $Id: foncheckrsa.c 332 2007-05-02 09:45:54Z pablo.martin $ ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "fonrsa.h" ++ ++int main(int argc, char **argv) ++{ ++ int fd, i; ++ FONRSA_ERROR fonrsa_error; ++ void *handle; ++ ++ if (argc != 4) { ++ fprintf(stderr, " Usage: foncheckrsa [public_key.der] [signature] [file]\n"); ++ fprintf(stderr, " Pablo Martín Medrano \n"); ++ fprintf(stderr, " RIPEMD-160 software written by Antoon Bosselaers,\n"); ++ fprintf(stderr, " available at http://www.esat.kuleuven.be/~cosicart/ps/AB-9601/.\n"); ++ fprintf(stderr, " Uses the axTLS library bigint implementation (libfonrsa)\n"); ++ fprintf(stderr, " http://www.leroc.com.au/axTLS/\n"); ++ return -1; ++ } ++ /* Check the existence of input files */ ++ for (i = 1; i < 4; i++) { ++ if ((fd = open(argv[i], O_RDONLY)) == -1) { ++ fprintf(stderr, "Error: opening \"%s\": %s\n", argv[i], ++ strerror(errno)); ++ fprintf(stderr, "Bailing out..."); ++ exit(-2); ++ } ++ close(fd); ++ } ++ handle = FR_init(argv[1]); ++ if (handle == NULL) { ++ printf("Error loading keys in %s\n", argv[1]); ++ return 1; ++ } ++ fonrsa_error = FR_verify_file(handle, argv[3], argv[2]); ++ FR_end(handle); ++ switch (fonrsa_error) { ++ case FONRSA_OK: ++ printf("Verified OK\n"); ++ return 0; ++ case FONRSA_VERIFICATION_FAILURE: ++ printf("Verification failure\n"); ++ return 1; ++ default: ++ printf("Verification error\n"); ++ return -1; ++ } ++ return -1; ++} ++ +--- /dev/null ++++ b/net/rsa/fonrsa.c +@@ -0,0 +1,584 @@ ++/* ++ * FONSM RSA handling library ++ * ++ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. ++ * ++ * This library is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This library 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 Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * Created: 20070306 Pablo Martin Medrano ++ * ++ * Based on axTLS ++ * ++ * $Id: fonrsa.c 405 2007-09-19 15:26:17Z jesus.pico $ ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rmd160.h" ++#include "bigint.h" ++#include "fonrsa.h" ++#include "base64.h" ++ ++typedef struct { ++ uint8_t *buffer; ++ size_t size; ++} DER_key; ++ ++typedef struct { ++ bigint *m; /* modulus */ ++ bigint *e; /* public exponent */ ++ int num_octets; ++ BI_CTX *bi_ctx; /* big integer handle */ ++} RSA_parameters; ++ ++typedef struct { ++ DER_key *derkey; ++ RSA_parameters *rsaparms; ++} RSA; ++ ++static uint8_t *CH_load_raw_file(char *filename, size_t *size); ++static DER_key *CH_load_der_key(char *filename); ++static void CH_free_der_key(DER_key *key); ++static int asn1_get_public_key(const uint8_t *buf, int len, RSA_parameters **rsa_parameters); ++void CH_pub_key_new(RSA_parameters **rsa_parameters, const uint8_t *modulus, int mod_len, const uint8_t *pub_exp, int pub_len); ++int CH_decrypt(RSA_parameters *rsa, uint8_t *buffer_in, uint8_t *buffer_out); ++byte *RMDbinary(char *fname); ++int CH_get_rmd160_hash_from_signature(byte *hash, char *signature_file, char *public_key_file); ++static unsigned char *load_file_in_buffer(char *path, int *size); ++static int save_file_from_buffer(char *path, unsigned char *buffer, int size); ++int ExtractPadding(uint8_t* OutputBuffer, uint8_t* InputBuffer, int LengthOfInputBuffer); ++ ++#define RMDsize 160 /* A RIPEMD-160 hash has 160 bits */ ++ ++/* ++ * returns RMD(message in file fname) fname is read as binary data. ++ * non-reentrant ++ */ ++byte *RMDbinary(char *fname) ++{ ++ FILE *mf; /* pointer to file */ ++ byte data[1024]; /* contains current mess. block */ ++ dword nbytes; /* length of this block */ ++ dword MDbuf[RMDsize / 32]; /* contains (A, B, C, D(, E)) */ ++ static byte hashcode[RMDsize / 8]; /* for final hash-value */ ++ dword X[16]; /* current 16-word chunk */ ++ unsigned int i, j; /* counters */ ++ dword length[2]; /* length in bytes of message */ ++ dword offset; /* # of unprocessed bytes at */ ++ /* call of MDfinish */ ++ ++ /* initialize */ ++ if ((mf = fopen(fname, "rb")) == NULL) { ++ fprintf(stderr, "\nRMDbinary: cannot open file \"%s\".\n", ++ fname); ++ exit(1); ++ } ++ MDinit(MDbuf); ++ length[0] = 0; ++ length[1] = 0; ++ while ((nbytes = fread(data, 1, 1024, mf)) != 0) { ++ /* process all complete blocks */ ++ for (i = 0; i < (nbytes >> 6); i++) { ++ for (j = 0; j < 16; j++) ++ X[j] = BYTES_TO_DWORD(data + 64 * i + 4 * j); ++ compress(MDbuf, X); ++ } ++ /* update length[] */ ++ if (length[0] + nbytes < length[0]) ++ length[1]++; /* overflow to msb of length */ ++ length[0] += nbytes; ++ } ++ /* finish: */ ++ offset = length[0] & 0x3C0; /* extract bytes 6 to 10 inclusive */ ++ MDfinish(MDbuf, data + offset, length[0], length[1]); ++ ++ for (i = 0; i < RMDsize / 8; i += 4) { ++ hashcode[i] = MDbuf[i >> 2]; ++ hashcode[i + 1] = (MDbuf[i >> 2] >> 8); ++ hashcode[i + 2] = (MDbuf[i >> 2] >> 16); ++ hashcode[i + 3] = (MDbuf[i >> 2] >> 24); ++ } ++ fclose(mf); ++ ++ return (byte *) hashcode; ++} ++byte *RMDbinary_buffer(char *buffer, int size_buffer) ++{ ++ return NULL; ++} ++ ++/* ++ * Extracts the RMD 160 hash from the signature file ++ */ ++int CH_get_rmd160_hash_from_signature(byte *hash, char *signature_file, char *public_key_file) ++{ ++ RSA_parameters *rsa_parameters; ++ DER_key *derkey; ++ uint8_t *signature; ++ size_t signature_size; ++ uint8_t *decrypted; ++ ++ signature = CH_load_raw_file(signature_file, &signature_size); ++ if ((signature == NULL)||(signature_size != 512)) { ++ fprintf(stderr, "Error: Loading signature key '%s'\n", signature_file); ++ exit(-1); ++ } ++ derkey = CH_load_der_key(public_key_file); ++ if (derkey == NULL) { ++ fprintf(stderr, "Error: opening DER key file '%s'\n", public_key_file); ++ exit(-1); ++ } ++ if ((asn1_get_public_key(derkey->buffer, derkey->size, &rsa_parameters)) != 0) { ++ fprintf(stderr, "Error: Extracting public key from DER file\n"); ++ exit(-1); ++ } ++ CH_free_der_key(derkey); ++ if (rsa_parameters->num_octets != 512) ++ fprintf(stderr, "Error: The RSA public key size is not 4096 bits %d\n", rsa_parameters->num_octets); ++ decrypted = (uint8_t *)malloc(rsa_parameters->num_octets); ++ if (CH_decrypt(rsa_parameters, signature, decrypted)) { ++ fprintf(stderr, "Error: Decrypting signature\n"); ++ exit(-1); ++ } ++ memcpy(hash, decrypted + 492, 20); ++ free(decrypted); ++ free(signature); ++ return 0; ++} ++ ++/* ++ * Decrypts the signature buffer using the rsa public key loaded ++ */ ++int CH_decrypt(RSA_parameters *rsa, uint8_t *buffer_in, uint8_t *buffer_out) ++{ ++ bigint *dat_bi; ++ bigint *decrypted_bi; ++ int byte_size; ++ ++ byte_size = rsa->num_octets; ++ dat_bi = bi_import(rsa->bi_ctx, buffer_in, byte_size); ++ rsa->bi_ctx->mod_offset = BIGINT_M_OFFSET; ++ bi_copy(rsa->m); ++ decrypted_bi = bi_mod_power(rsa->bi_ctx, dat_bi, rsa->e); ++ bi_export(rsa->bi_ctx, decrypted_bi, buffer_out, byte_size); ++ return 0; ++} ++/* ++ * Loads a file in a uint8_t buffer ++ */ ++static uint8_t *CH_load_raw_file(char *filename, size_t *size) ++{ ++ struct stat st; ++ int fd; ++ ssize_t br; ++ uint8_t *ret; ++ ++ if ((stat(filename, &st)) == -1) ++ return NULL; ++ if ((ret = (uint8_t *)malloc(st.st_size)) == NULL) ++ return NULL; ++ fd = open(filename, O_RDONLY); ++ if (fd == -1) { ++ free(ret); ++ return NULL; ++ } ++ br = read(fd, ret, st.st_size); ++ close(fd); ++ if (br != st.st_size) { ++ free(ret); ++ return NULL; ++ } ++ *size = st.st_size; ++ return ret; ++} ++/* ++ * Loads a .der file in a buffer ++ */ ++static DER_key *CH_load_der_key(char *filename) ++{ ++ DER_key *ret; ++ ++ if ((ret = (DER_key *)malloc(sizeof(DER_key))) == NULL) ++ return NULL; ++ if ((ret->buffer = CH_load_raw_file(filename, &(ret->size))) == NULL) { ++ free(ret); ++ return NULL; ++ } ++ return ret; ++} ++/* ++ * CH_load_pem_key ++ */ ++static DER_key *CH_load_pem_key(char *filename) ++{ ++ DER_key *ret; ++ uint8_t *buffer; ++ char *b64,*p,*t; ++ char key[1024]; ++ size_t filesize; ++ int size; ++ ++ if ((ret = (DER_key *)malloc(sizeof(DER_key))) == NULL) ++ return NULL; ++ if ((buffer = CH_load_raw_file(filename, &filesize)) == NULL) { ++ free(ret); ++ return NULL; ++ } ++ p = (char *)buffer; ++ while ((*p != '\n') && (*p != '\0')) ++ p++; ++ if (*p == '\0') { ++ free(ret); ++ return NULL; ++ } ++ p++; ++ b64 = t = p; ++ while((p - b64) <= filesize) { ++ if ((*p == '-')) { ++ break; ++ } else if ((*p != '\n') && (*p != ' ') && (*p != '\t')) { ++ *t = *p; ++ t++; ++ } ++ p++; ++ } ++ *t = '\0'; ++ size = B64_decode(b64, key, strlen(b64), 1024); ++ if (size < 0) { ++ free(buffer); ++ free(ret); ++ return NULL; ++ } ++ free(buffer); ++ ret->buffer = (char *)malloc(size); ++ ret->size = size; ++ memcpy((void *)ret->buffer, (void *)key, size); ++ return ret; ++} ++ ++/* ++ * CH_free_der_key ++ */ ++static void CH_free_der_key(DER_key *key) ++{ ++ free(key->buffer); ++ free(key); ++} ++ ++/* ++ * Get the public key specifics from an ASN.1 encoded file ++ * A function lacking in the exported axTLS API ++ * ++ * This is a really weird hack that only works with RSA public key ++ * files ++ */ ++static int asn1_get_public_key(const uint8_t *buf, int len, RSA_parameters **rsa_parameters) ++{ ++ uint8_t *modulus, *pub_exp; ++ int mod_len, pub_len; ++ ++ pub_len = 3; ++ mod_len = len - 37; ++ if (buf[0] != 0x30) { ++ return -1; ++ } ++ ++ pub_exp = (uint8_t *)malloc(3); ++ modulus = (uint8_t *)malloc(mod_len); ++ memcpy(modulus, buf + 32 , mod_len); ++ memcpy(pub_exp, buf + 34 + mod_len, 3); ++ if (mod_len <= 0 || pub_len <= 0 ) ++ return -1; ++ CH_pub_key_new(rsa_parameters, modulus, mod_len, pub_exp, pub_len); ++ ++ free(modulus); ++ free(pub_exp); ++ return 0; ++} ++ ++/* ++ * Similar to RSA_pub_key_new, rewritten to make this program depend only on bi module ++ */ ++void CH_pub_key_new(RSA_parameters **rsa, const uint8_t *modulus, int mod_len, const uint8_t *pub_exp, int pub_len) ++{ ++ RSA_parameters *rsa_parameters; ++ ++ BI_CTX *bi_ctx = bi_initialize(); ++ *rsa = (RSA_parameters *)calloc(1, sizeof(RSA_parameters)); ++ rsa_parameters = *rsa; ++ rsa_parameters->bi_ctx = bi_ctx; ++ rsa_parameters->num_octets = (mod_len & 0xFFF0); ++ rsa_parameters->m = bi_import(bi_ctx, modulus, mod_len); ++ bi_set_mod(bi_ctx, rsa_parameters->m, BIGINT_M_OFFSET); ++ rsa_parameters->e = bi_import(bi_ctx, pub_exp, pub_len); ++ bi_permanent(rsa_parameters->e); ++} ++ ++static unsigned char *load_file_in_buffer(char *path, int *size) ++{ ++ unsigned char *buffer; ++ struct stat st; ++ int fd; ++ ++ if (stat(path, &st)) ++ return NULL; ++ buffer = (unsigned char *)malloc(st.st_size); ++ if (buffer == NULL) ++ return NULL; ++ if ((fd = open(path, O_RDONLY)) == -1) { ++ free(buffer); ++ return NULL; ++ } ++ if (read(fd, (void *)buffer,st.st_size) != (ssize_t)st.st_size) { ++ free(buffer); ++ close(fd); ++ return NULL; ++ } ++ *size = (int)st.st_size; ++ close(fd); ++ return buffer; ++} ++ ++static int save_file_from_buffer(char *path, unsigned char *buffer, int size) ++{ ++ int fd; ++ ++ if ((fd = open(path, O_WRONLY | O_CREAT, 0644)) == -1) ++ return -1; ++ if (write(fd, buffer, (size_t)size) != ((ssize_t)size)) { ++ close(fd); ++ return -1; ++ } ++ close(fd); ++ return 0; ++} ++ ++/* FR_init */ ++void *FR_init(char *public_key_path) ++{ ++ DER_key *derkey; ++ RSA_parameters *rsa_parameters; ++ char *ending; ++ ++ ending = public_key_path + strlen(public_key_path) - 3; ++ if (!strcmp(ending, "der")) ++ derkey = CH_load_der_key(public_key_path); ++ else if (!strcmp(ending, "pem")) ++ derkey = CH_load_pem_key(public_key_path); ++ else { ++ fprintf(stderr, "Error: unknown key format\n"); ++ exit(-1); ++ } ++ if (derkey == NULL) { ++ fprintf(stderr, "Error: opening key file '%s'\n", public_key_path); ++ exit(-1); ++ } ++ if ((asn1_get_public_key(derkey->buffer, derkey->size, &rsa_parameters)) != 0) { ++ fprintf(stderr, "Error: Extracting public key from file\n"); ++ exit(-1); ++ } ++ CH_free_der_key(derkey); ++ return (void *)rsa_parameters; ++} ++ ++/* FR_end */ ++FONRSA_ERROR FR_end(void *handle) ++{ ++ RSA_parameters *rsa_parameters = (RSA_parameters *)handle; ++ ++ free(rsa_parameters); ++ return FONRSA_OK; ++} ++ ++/* FR_decrypt_buffer */ ++FONRSA_ERROR FR_decrypt_buffer(void *handler, unsigned char *cryptext, int cryptext_size, ++ unsigned char *plaintext, int plaintext_buffer_size, int *plaintext_size) ++{ ++ RSA_parameters *rsaparms = (RSA_parameters *)handler; ++ ++ if (cryptext_size != rsaparms->num_octets) { ++ return FONRSA_SIZE; ++ } ++ if (plaintext_buffer_size < cryptext_size) { ++ return FONRSA_SIZE; ++ } ++ if (CH_decrypt(rsaparms, (uint8_t *)cryptext, (uint8_t *)plaintext)) { ++ return FONRSA_DECRYPT; ++ } ++ *plaintext_size = cryptext_size; ++ return FONRSA_OK; ++} ++ ++FONRSA_ERROR FR_decrypt_buffer_v2(void *handler, unsigned char *cryptext, int cryptext_size, ++ unsigned char *plaintext, int plaintext_buffer_size, int *plaintext_size) ++{ ++ unsigned char* AuxBuffer; ++ int AuxSize; ++ ++ AuxBuffer = (unsigned char*)malloc(cryptext_size); ++ ++ RSA_parameters *rsaparms = (RSA_parameters *)handler; ++ ++ if (cryptext_size != rsaparms->num_octets) { ++ return FONRSA_SIZE; ++ } ++ if (plaintext_buffer_size < cryptext_size) { ++ return FONRSA_SIZE; ++ } ++ if (CH_decrypt(rsaparms, (uint8_t *)cryptext, (uint8_t *)AuxBuffer)) { ++ return FONRSA_DECRYPT; ++ } ++ if ((AuxSize = ExtractPadding((uint8_t*)plaintext, (uint8_t*)AuxBuffer, cryptext_size)) < 0) ++ { ++ printf("Incorrect Padding decrypting buffer"); ++ return FONRSA_DECRYPT; ++ } ++ *plaintext_size = AuxSize; ++ return FONRSA_OK; ++} ++ ++/* ++ * ++ * Implementation of PKCS 1.5 padding, borrowed from ++ * Tom's code (public domain) ++ */ ++ ++/* Standalone FR_verify_file */ ++FONRSA_ERROR FR_verify_file(void *handler, char *file_path, char *signature_file_path) ++{ ++ int j; ++ byte *hashcode; ++ byte hash[20]; ++ uint8_t *decrypted; ++ RSA_parameters *rsa_parameters = (RSA_parameters *)handler; ++ char *signature_buffer; ++ int signature_size; ++ ++ /* Calculates the RIPEMD-160 hash of the file */ ++ hashcode = RMDbinary (file_path); ++ /* Decrypts the signature file using the RSA public key */ ++ signature_buffer = load_file_in_buffer(signature_file_path, &signature_size); ++ if (signature_buffer == NULL) ++ return FONRSA_OPENKEY; ++ ++ if (rsa_parameters->num_octets != signature_size) ++ return FONRSA_SIZE; ++ decrypted = (uint8_t *)malloc(rsa_parameters->num_octets); ++ if (CH_decrypt(rsa_parameters, signature_buffer, decrypted)) { ++ fprintf(stderr, "Error: Decrypting signature\n"); ++ exit(-1); ++ } ++ memcpy(hash, decrypted + 492, 20); ++ free(decrypted); ++ free(signature_buffer); ++ for (j = 0; j < RMDsize/8; j++) { ++ if (hash[j] != hashcode[j]) ++ return FONRSA_VERIFICATION_FAILURE; ++ } ++ return FONRSA_OK; ++} ++ ++/* FR_decrypt_file */ ++FONRSA_ERROR FR_decrypt_file(void *handle, char *crypted_file_path, char *plaintext_file_path) ++{ ++ int size; ++ FONRSA_ERROR ret; ++ char *filebuffer; ++ char crypted[1024]; ++ int crypted_size; ++ ++ if ((filebuffer = load_file_in_buffer(crypted_file_path, &size)) == NULL) { ++ return FONRSA_LOADFILE; ++ } ++ ++ ret = FR_decrypt_buffer(handle, filebuffer, size, crypted, 1024, &crypted_size); ++ if (ret != FONRSA_OK) { ++ free(filebuffer); ++ return ret; ++ } ++ free(filebuffer); ++ ++ if (save_file_from_buffer(plaintext_file_path, crypted, crypted_size)) { ++ printf("Error writing %lu bytes into %s", crypted_size, plaintext_file_path); ++ return FONRSA_SAVEFILE; ++ } ++ return FONRSA_OK; ++} ++ ++int ExtractPadding(uint8_t* OutputBuffer, uint8_t* InputBuffer, int LengthOfInputBuffer) ++{ ++ int i; ++ ++ //First typical checks... ++ if (LengthOfInputBuffer < MINIMUM_PADING_BYTES_PKCS_1_5) ++ { ++ fprintf(stderr, "Error:ExtractPadding: Error, Length of input buffer is too short.\n"); ++ return -1; ++ } ++ else if((InputBuffer[0] != 0) || (InputBuffer[1] > 2)) //Necessary header of Padding... ++ { ++ fprintf(stderr, "Error:ExtractPadding: Error, Padding header is incorrect.\n"); ++ return -1; ++ } ++ for (i=2; i < LengthOfInputBuffer; i++) //Variable size of non-zero padding.... ++ { ++ if (InputBuffer[i] == 0) break; //This is the end of Padding. ++ } ++ //We need to evaluate if there is an existing message... ++ if (i < LengthOfInputBuffer - 2) ++ {//Ok, Padding is extracted... copying the message and finishing... ++ memcpy(OutputBuffer, &(InputBuffer[i + 1]), LengthOfInputBuffer - (i + 1)); ++ return LengthOfInputBuffer - (i + 1); ++ } ++ //If we have reached to this point, then an error has occurred... ++ return -1; ++} ++ ++#ifdef __MAINTEST__ ++int main(int argc, char **argv) ++{ ++ void *handle = NULL; ++ FONRSA_ERROR ret; ++ char *filebuffer = NULL; ++ char crypted[1024]; ++ int size, crypted_size; ++ ++ if (argc != 4) { ++ printf("Usage: %s \n", argv[0]); ++ return 1; ++ } ++ ++ handle = FR_init(argv[1]); ++ if (handle == NULL) { ++ printf("Error loading keys\n"); ++ return 1; ++ } ++ ret = FR_decrypt_file(handle, argv[2], argv[3]); ++ if (ret != FONRSA_OK) { ++ printf("FR_decrypt_file returns %d\n", ret); ++ } ++ FR_end(handle); ++ return (int)ret; ++} ++ ++#endif ++ ++ +--- /dev/null ++++ b/net/rsa/fonrsa.h +@@ -0,0 +1,53 @@ ++/* ++ * FONSM RSA handling library, used by fonsmcd and foncheckrsa ++ * ++ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. ++ * ++ * This library is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This library 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 Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * Created: 20070306 Pablo Martin Medrano ++ * ++ * $Id: fonrsa.h 404 2007-09-17 10:41:31Z jesus.pico $ ++ */ ++#ifndef _FONRSA_H ++#define _FONRSA_H ++ ++#define MINIMUM_PADING_BYTES_PKCS_1_5 3 ++ ++typedef enum { ++ FONRSA_OK = 0, ++ FONRSA_VERIFICATION_FAILURE = 1, ++ FONRSA_OPENKEY = 2, ++ FONRSA_SIZE = 3, ++ FONRSA_LOADFILE = 4, ++ FONRSA_CRYPT = 5, ++ FONRSA_DECRYPT = 6, ++ FONRSA_SAVEFILE = 7, ++ FONRSA_NOSYS = 8, ++ FONRSA_VERIFY = 9 ++} FONRSA_ERROR; ++ ++void *FR_init(char *public_key_path); ++FONRSA_ERROR FR_end(void *handle); ++FONRSA_ERROR FR_decrypt_buffer(void *handler, unsigned char *cryptext, int cryptext_size, ++ unsigned char *plaintext, int plaintext_buffer_size, int *plaintext_size); ++FONRSA_ERROR FR_decrypt_buffer_v2(void *handler, unsigned char *cryptext, int cryptext_size, ++ unsigned char *plaintext, int plaintext_buffer_size, int *plaintext_size); ++FONRSA_ERROR FR_verify_file(void *handler, char *file_path, char *signature_file_path); ++FONRSA_ERROR FR_decrypt_file(void *handler, char *crypted_file_path, char *plaintext_file_path); ++ ++#endif ++ ++ +--- /dev/null ++++ b/net/rsa/log.c +@@ -0,0 +1,138 @@ ++/* ++ * Fonsm log module. Used inside the fonsm backend module and on the client. ++ * ++ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. ++ * ++ * Created: 20070202 Pablo Martin Medrano ++ * ++ * $Id: log.c 392 2007-06-25 16:24:51Z pablo.martin $ ++ */ ++#include ++#include ++#include ++#include ++#include ++#ifndef WIN32 ++#include ++#endif ++#include "log.h" ++ ++#define MAX_SESSION_PREFIX 256 ++ ++typedef struct { ++ char domain[256]; ++ LG_LEVEL watermark; ++ int mode; ++ LG_log_function_pointer function; ++} ST_fslog; ++ ++static ST_fslog fslog; ++static void LG_log_string(LG_LEVEL level, const char *message); ++ ++/*! ++ \brief Starts the log subsystem, redirecting glog() to stderr/syslog depending ++ on mode ++ \retval FSLOG_ERROR : FSLOG_OK if everything goes well ++ \param lg : handle that will be returned ++ \param ident : program identifier, any string ++ \param low_watermark : if the log level is less than this value, it will not be logged ++ \param mode : FSLOG_MODE_SYSLOG (log to syslog) or FSLOG_MODE_STDERR (log to stderr) ++*/ ++FSLOG_ERROR LG_start(const char *domain, LG_LEVEL watermark, int mode, ++ LG_log_function_pointer log_function, int facility) ++{ ++#ifndef WIN32 ++ strncpy(fslog.domain, domain, MAX_LG_DOMAIN); ++ fslog.domain[MAX_LG_DOMAIN - 1] = '\0'; ++ fslog.watermark = watermark; ++ fslog.mode = mode; ++ fslog.function = log_function?log_function:LG_log_string; ++ if (fslog.mode & LG_SYSLOG) ++ openlog(domain, LOG_NDELAY, facility); ++ return FSLOG_OK; ++#else ++ return FSLOG_OK; ++#endif ++} ++ ++/*! ++ \brief Set the low watermark ++ \retval FSLOG_ERROR : FSLOG_OK ++ \param lg : log handle ++ \param low_watermark : new watermark ++*/ ++FSLOG_ERROR LG_set_loglevel(LG_LEVEL watermark) ++{ ++ fslog.watermark = watermark; ++ return FSLOG_OK; ++} ++ ++/*! ++ \brief Ends the log subsystem, unregisteing glog handle ++ \retval FSLOG_ERROR : FSLOG_OK if everything goes well ++ \param handle : log handle to free ++*/ ++FSLOG_ERROR LG_end(void) ++{ ++#ifndef WIN32 ++ if (fslog.mode & LG_SYSLOG) ++ closelog(); ++#endif ++ return FSLOG_OK; ++} ++ ++ ++void LG_log(LG_LEVEL loglevel, const char *message, ...) ++{ ++#ifndef WIN32 ++ va_list ap; ++ char buffer[4096]; ++ int n; ++ ++ va_start(ap, message); ++ n = vsnprintf(buffer, MAX_LOG_STRING, message, ap); ++ va_end(ap); ++ if (n > -1 && n < MAX_LOG_STRING) ++ fslog.function(loglevel, buffer); ++ else ++ fon_critical("%s: Message too big to be logged", __FUNCTION__); ++#else ++ return; ++#endif ++} ++ ++/* Default log function (when mode is LG_SYSLOG or LG_STDERR) */ ++static void LG_log_string(LG_LEVEL level, const char *message) ++{ ++#ifndef WIN32 ++ static struct { ++ int syslog_level; ++ char *log_string; ++ } fonlog_to_syslog[] = { ++ [LG_DEBUG] = {LOG_ERR, "DEBUG"}, ++ [LG_MESSAGE] = {LOG_ERR, "MESSAGE"}, ++ [LG_WARNING] = {LOG_ERR, "WARNING"}, ++ [LG_CRITICAL] = {LOG_ERR, "CRITICAL"}, ++ [LG_ERROR] = {LOG_ERR, "ERROR"} ++ }; ++ ++ if (level < fslog.watermark) ++ return; ++ if (fslog.mode & LG_SYSLOG) { ++ if (level == LG_MESSAGE) { ++ syslog(LOG_INFO, "%s", message); ++ } else { ++ syslog(fonlog_to_syslog[level].syslog_level, "%s: %s", fonlog_to_syslog[level].log_string, message); ++ } ++ } ++ if (fslog.mode & LG_STDERR) { ++ fprintf(stderr, "%s[%d]: %8.8s: %s\n", fslog.domain, ++ getpid(), fonlog_to_syslog[level].log_string, ++ message); ++ } ++#else ++ /* FIXE: todo */ ++ return; ++#endif ++} ++ +--- /dev/null ++++ b/net/rsa/log.h +@@ -0,0 +1,77 @@ ++/* ++ * Fonsm log module. Used inside the fonsm backend module and on the client. ++ * ++ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. ++ * ++ * Created: 20070202 Pablo Martin Medrano ++ * ++ * $Id: log.h 379 2007-05-28 09:17:48Z pablo.martin $ ++ */ ++#ifndef _LOG_H ++#define _LOG_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include ++ ++typedef enum { ++ FSLOG_OK = 0, ++ FSLOG_UNKNOWN = -1 ++} FSLOG_ERROR; ++ ++ ++typedef void * LG_HANDLE; ++ ++typedef enum { ++ LG_DEBUG = 0, ++ LG_MESSAGE = 1, ++ LG_INFO = 2, ++ LG_WARNING = 3, ++ LG_CRITICAL = 4, ++ LG_ERROR = 5 ++} LG_LEVEL; ++ ++#define LG_SYSLOG 0x01 ++#define LG_STDERR 0x02 ++#define LG_CUSTOM 0x04 ++ ++#define MAX_LG_DOMAIN 256 ++#define MAX_LOG_STRING 4096 ++ ++#ifndef NDEBUG ++#ifndef LOGPRINTF ++#define fon_debug(...) LG_log (LG_DEBUG, __VA_ARGS__) ++#else ++#define fon_debug(...) { printf("DEBUG: "); printf(__VA_ARGS__); printf("\n"); } ++#endif ++#else ++/* fon_debug evaluates to nothing when NDEBUG is defined */ ++#define fon_debug(...) ++#endif ++#ifndef LOGPRINTF ++#define fon_message(...) LG_log (LG_MESSAGE, __VA_ARGS__) ++#define fon_warning(...) LG_log (LG_WARNING, __VA_ARGS__) ++#define fon_critical(...) LG_log (LG_CRITICAL, __VA_ARGS__) ++#define fon_error(...) LG_log (LG_ERROR, __VA_ARGS__) ++#else ++#define fon_message(...) { printf("MESSAGE: "); printf(__VA_ARGS__); printf("\n"); } ++#define fon_warning(...) { printf("WARNING: "); printf(__VA_ARGS__); printf("\n"); } ++#define fon_critical(...) { printf("CRITICAL: "); printf(__VA_ARGS__); printf("\n"); } ++#define fon_error(...) { printf("ERROR: "); printf(__VA_ARGS__); printf("\n"); } ++#endif ++ ++typedef void (*LG_log_function_pointer)(LG_LEVEL level, const char *message); ++ ++FSLOG_ERROR LG_start(const char *domain, LG_LEVEL watermark, int mode, LG_log_function_pointer log_function, int facility); ++FSLOG_ERROR LG_set_loglevel(LG_LEVEL watermark); ++FSLOG_ERROR LG_end(void); ++void LG_log(LG_LEVEL loglevel, const char *message, ...); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif ++ +--- /dev/null ++++ b/net/rsa/Makefile +@@ -0,0 +1,31 @@ ++# ++# FONRSA & FONSIGN libraries unit testing ++# ++# This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. ++# ++# Execute in this directory ++# ++# Created: 20070422 Pablo Martin Medrano ++# ++# $Id: Makefile 389 2007-06-11 08:29:56Z pablo.martin $ ++# ++# FIXME: Put this in the main Makefile.am ++# ++all: fonsign dump_key ++ ++fonsign: ++ gcc -g sign_openssl.c -D__MAINTEST__ -o fonsign -lssl ++ ++dump_key: ++ gcc -o dump_key dump_key.c ++ ./dump_key > public_key.h ++ ++foncheckrsa: ++ gcc -g bigint.c fonrsa.c rmd160.c foncheckrsa.c base64.c log.c -o foncheckrsa ++ ++#private_fon_rsa_key.pem: ++# openssl genrsa -out private_fon_rsa_key.pem 4096 ++# openssl rsa -in private_fon_rsa_key.pem -pubout -out public_fon_rsa_key.pem ++ ++clean: ++ rm fonsign dump_key +--- /dev/null ++++ b/net/rsa/public_key.h +@@ -0,0 +1,52 @@ ++unsigned char public_key[] = { ++ 0x2D,0x2D,0x2D,0x2D,0x2D,0x42,0x45,0x47,0x49,0x4E,0x20,0x50,0x55,0x42,0x4C,0x49, ++ 0x43,0x20,0x4B,0x45,0x59,0x2D,0x2D,0x2D,0x2D,0x2D,0x0A,0x4D,0x49,0x49,0x43,0x49, ++ 0x6A,0x41,0x4E,0x42,0x67,0x6B,0x71,0x68,0x6B,0x69,0x47,0x39,0x77,0x30,0x42,0x41, ++ 0x51,0x45,0x46,0x41,0x41,0x4F,0x43,0x41,0x67,0x38,0x41,0x4D,0x49,0x49,0x43,0x43, ++ 0x67,0x4B,0x43,0x41,0x67,0x45,0x41,0x34,0x4C,0x42,0x76,0x59,0x43,0x4B,0x38,0x38, ++ 0x6D,0x75,0x57,0x61,0x73,0x31,0x4F,0x53,0x73,0x71,0x30,0x0A,0x38,0x39,0x38,0x79, ++ 0x76,0x54,0x4B,0x71,0x41,0x6E,0x4F,0x37,0x78,0x2F,0x44,0x53,0x57,0x72,0x46,0x53, ++ 0x30,0x42,0x72,0x47,0x53,0x51,0x31,0x52,0x69,0x44,0x39,0x55,0x62,0x78,0x77,0x6F, ++ 0x64,0x76,0x36,0x65,0x51,0x4B,0x55,0x30,0x67,0x36,0x52,0x6B,0x2F,0x39,0x54,0x70, ++ 0x4C,0x6E,0x4F,0x2F,0x76,0x51,0x4B,0x70,0x69,0x41,0x30,0x30,0x0A,0x2B,0x32,0x59, ++ 0x30,0x74,0x6B,0x4C,0x39,0x73,0x6A,0x37,0x64,0x33,0x57,0x4B,0x47,0x39,0x62,0x6A, ++ 0x64,0x51,0x58,0x2F,0x43,0x49,0x35,0x57,0x46,0x42,0x42,0x64,0x77,0x57,0x73,0x74, ++ 0x4D,0x43,0x38,0x77,0x74,0x4C,0x6A,0x6A,0x45,0x59,0x79,0x43,0x58,0x46,0x32,0x31, ++ 0x30,0x39,0x7A,0x31,0x47,0x54,0x4C,0x73,0x53,0x44,0x34,0x57,0x4F,0x0A,0x45,0x50, ++ 0x6D,0x45,0x37,0x34,0x63,0x6E,0x6F,0x35,0x78,0x53,0x43,0x71,0x71,0x33,0x74,0x54, ++ 0x49,0x6D,0x38,0x50,0x78,0x49,0x77,0x54,0x46,0x6D,0x46,0x6F,0x6D,0x6A,0x76,0x31, ++ 0x4F,0x56,0x50,0x32,0x73,0x42,0x49,0x70,0x35,0x4E,0x2B,0x59,0x6F,0x56,0x61,0x53, ++ 0x58,0x6A,0x47,0x66,0x4E,0x63,0x54,0x36,0x4E,0x6B,0x39,0x76,0x6B,0x56,0x0A,0x57, ++ 0x69,0x67,0x39,0x30,0x71,0x50,0x4E,0x4C,0x58,0x6E,0x39,0x39,0x50,0x78,0x48,0x61, ++ 0x49,0x31,0x36,0x52,0x7A,0x78,0x48,0x4C,0x39,0x54,0x42,0x2B,0x50,0x43,0x33,0x68, ++ 0x33,0x61,0x58,0x33,0x71,0x57,0x30,0x4B,0x4C,0x4A,0x41,0x66,0x6F,0x35,0x70,0x48, ++ 0x6C,0x39,0x79,0x75,0x55,0x70,0x37,0x66,0x46,0x65,0x6A,0x4A,0x2B,0x41,0x58,0x0A, ++ 0x51,0x4F,0x4A,0x62,0x53,0x45,0x67,0x56,0x74,0x76,0x72,0x68,0x44,0x39,0x73,0x55, ++ 0x6D,0x4B,0x30,0x74,0x36,0x63,0x51,0x44,0x65,0x32,0x32,0x4E,0x4E,0x6E,0x77,0x37, ++ 0x43,0x4F,0x4F,0x61,0x59,0x49,0x57,0x55,0x55,0x6A,0x79,0x6A,0x68,0x35,0x50,0x4B, ++ 0x64,0x64,0x45,0x4B,0x5A,0x38,0x68,0x62,0x62,0x47,0x65,0x61,0x5A,0x4A,0x6F,0x76, ++ 0x0A,0x63,0x6F,0x51,0x64,0x55,0x56,0x51,0x6D,0x71,0x44,0x53,0x2B,0x6B,0x63,0x2F, ++ 0x41,0x51,0x6C,0x65,0x55,0x36,0x68,0x51,0x6A,0x63,0x55,0x4C,0x57,0x44,0x6B,0x4E, ++ 0x2F,0x6F,0x4F,0x6C,0x33,0x43,0x53,0x65,0x70,0x67,0x54,0x37,0x6B,0x67,0x73,0x52, ++ 0x63,0x63,0x47,0x74,0x66,0x4B,0x65,0x37,0x77,0x4D,0x70,0x35,0x66,0x59,0x4A,0x2B, ++ 0x41,0x0A,0x43,0x46,0x44,0x41,0x6F,0x4C,0x6E,0x58,0x4E,0x6A,0x4E,0x56,0x6C,0x65, ++ 0x73,0x43,0x6B,0x78,0x74,0x6A,0x62,0x4C,0x62,0x49,0x72,0x66,0x32,0x6E,0x43,0x62, ++ 0x32,0x61,0x4D,0x65,0x64,0x31,0x5A,0x48,0x4E,0x4A,0x51,0x75,0x6F,0x4E,0x58,0x67, ++ 0x72,0x43,0x41,0x44,0x31,0x71,0x2B,0x58,0x6E,0x66,0x77,0x63,0x69,0x6D,0x57,0x50, ++ 0x64,0x51,0x0A,0x44,0x59,0x6A,0x6D,0x65,0x44,0x70,0x35,0x77,0x36,0x41,0x4A,0x33, ++ 0x2F,0x35,0x59,0x39,0x55,0x74,0x78,0x47,0x34,0x72,0x51,0x72,0x61,0x68,0x78,0x53, ++ 0x42,0x77,0x43,0x4B,0x57,0x39,0x4B,0x79,0x53,0x31,0x71,0x53,0x76,0x73,0x37,0x7A, ++ 0x59,0x2F,0x52,0x59,0x37,0x4A,0x66,0x36,0x63,0x56,0x6B,0x54,0x43,0x78,0x69,0x33, ++ 0x7A,0x32,0x53,0x0A,0x50,0x46,0x33,0x51,0x64,0x6B,0x30,0x50,0x44,0x2F,0x73,0x2B, ++ 0x6B,0x77,0x39,0x71,0x4F,0x4E,0x79,0x69,0x33,0x67,0x6E,0x61,0x42,0x46,0x6E,0x54, ++ 0x77,0x48,0x7A,0x59,0x69,0x77,0x34,0x2F,0x77,0x6A,0x46,0x33,0x64,0x47,0x68,0x47, ++ 0x4E,0x6B,0x78,0x36,0x70,0x63,0x4E,0x4F,0x52,0x55,0x46,0x4E,0x65,0x4F,0x7A,0x59, ++ 0x76,0x39,0x6F,0x6A,0x0A,0x51,0x59,0x70,0x73,0x55,0x31,0x33,0x6A,0x6D,0x30,0x33, ++ 0x42,0x6F,0x45,0x2B,0x42,0x31,0x64,0x38,0x50,0x47,0x75,0x57,0x2B,0x49,0x7A,0x2F, ++ 0x41,0x4F,0x44,0x7A,0x6B,0x6F,0x56,0x6B,0x39,0x2B,0x57,0x79,0x49,0x33,0x37,0x50, ++ 0x30,0x53,0x7A,0x47,0x4B,0x72,0x2B,0x53,0x33,0x72,0x72,0x74,0x61,0x50,0x6C,0x41, ++ 0x70,0x71,0x4B,0x48,0x55,0x0A,0x6E,0x64,0x35,0x6C,0x30,0x63,0x76,0x75,0x59,0x66, ++ 0x31,0x4C,0x37,0x45,0x52,0x75,0x49,0x58,0x64,0x47,0x4C,0x6A,0x30,0x43,0x41,0x77, ++ 0x45,0x41,0x41,0x51,0x3D,0x3D,0x0A,0x2D,0x2D,0x2D,0x2D,0x2D,0x45,0x4E,0x44,0x20, ++ 0x50,0x55,0x42,0x4C,0x49,0x43,0x20,0x4B,0x45,0x59,0x2D,0x2D,0x2D,0x2D,0x2D,0x0A, ++ }; +--- /dev/null ++++ b/net/rsa/rmd160.c +@@ -0,0 +1,292 @@ ++/********************************************************************\ ++ * ++ * FILE: rmd160.c ++ * ++ * CONTENTS: A sample C-implementation of the RIPEMD-160 ++ * hash-function. ++ * TARGET: any computer with an ANSI C compiler ++ * ++ * AUTHOR: Antoon Bosselaers, ESAT-COSIC ++ * DATE: 1 March 1996 ++ * VERSION: 1.0 ++ * ++ * Copyright (c) Katholieke Universiteit Leuven ++ * 1996, All Rights Reserved ++ * ++ * Conditions for use of the RIPEMD-160 Software ++ * ++ * The RIPEMD-160 software is freely available for use under the terms and ++ * conditions described hereunder, which shall be deemed to be accepted by ++ * any user of the software and applicable on any use of the software: ++ * ++ * 1. K.U.Leuven Department of Electrical Engineering-ESAT/COSIC shall for ++ * all purposes be considered the owner of the RIPEMD-160 software and of ++ * all copyright, trade secret, patent or other intellectual property ++ * rights therein. ++ * 2. The RIPEMD-160 software is provided on an "as is" basis without ++ * warranty of any sort, express or implied. K.U.Leuven makes no ++ * representation that the use of the software will not infringe any ++ * patent or proprietary right of third parties. User will indemnify ++ * K.U.Leuven and hold K.U.Leuven harmless from any claims or liabilities ++ * which may arise as a result of its use of the software. In no ++ * circumstances K.U.Leuven R&D will be held liable for any deficiency, ++ * fault or other mishappening with regard to the use or performance of ++ * the software. ++ * 3. User agrees to give due credit to K.U.Leuven in scientific publications ++ * or communications in relation with the use of the RIPEMD-160 software ++ * as follows: RIPEMD-160 software written by Antoon Bosselaers, ++ * available at http://www.esat.kuleuven.be/~cosicart/ps/AB-9601/. ++ * ++\********************************************************************/ ++ ++/* header files */ ++#include ++#include "rmd160.h" ++ ++/********************************************************************/ ++ ++void MDinit(dword *MDbuf) ++{ ++ MDbuf[0] = 0x67452301UL; ++ MDbuf[1] = 0xefcdab89UL; ++ MDbuf[2] = 0x98badcfeUL; ++ MDbuf[3] = 0x10325476UL; ++ MDbuf[4] = 0xc3d2e1f0UL; ++ ++ return; ++} ++ ++/********************************************************************/ ++ ++void compress(dword *MDbuf, dword *X) ++{ ++ dword aa = MDbuf[0], bb = MDbuf[1], cc = MDbuf[2], ++ dd = MDbuf[3], ee = MDbuf[4]; ++ dword aaa = MDbuf[0], bbb = MDbuf[1], ccc = MDbuf[2], ++ ddd = MDbuf[3], eee = MDbuf[4]; ++ ++ /* round 1 */ ++ FF(aa, bb, cc, dd, ee, X[ 0], 11); ++ FF(ee, aa, bb, cc, dd, X[ 1], 14); ++ FF(dd, ee, aa, bb, cc, X[ 2], 15); ++ FF(cc, dd, ee, aa, bb, X[ 3], 12); ++ FF(bb, cc, dd, ee, aa, X[ 4], 5); ++ FF(aa, bb, cc, dd, ee, X[ 5], 8); ++ FF(ee, aa, bb, cc, dd, X[ 6], 7); ++ FF(dd, ee, aa, bb, cc, X[ 7], 9); ++ FF(cc, dd, ee, aa, bb, X[ 8], 11); ++ FF(bb, cc, dd, ee, aa, X[ 9], 13); ++ FF(aa, bb, cc, dd, ee, X[10], 14); ++ FF(ee, aa, bb, cc, dd, X[11], 15); ++ FF(dd, ee, aa, bb, cc, X[12], 6); ++ FF(cc, dd, ee, aa, bb, X[13], 7); ++ FF(bb, cc, dd, ee, aa, X[14], 9); ++ FF(aa, bb, cc, dd, ee, X[15], 8); ++ ++ /* round 2 */ ++ GG(ee, aa, bb, cc, dd, X[ 7], 7); ++ GG(dd, ee, aa, bb, cc, X[ 4], 6); ++ GG(cc, dd, ee, aa, bb, X[13], 8); ++ GG(bb, cc, dd, ee, aa, X[ 1], 13); ++ GG(aa, bb, cc, dd, ee, X[10], 11); ++ GG(ee, aa, bb, cc, dd, X[ 6], 9); ++ GG(dd, ee, aa, bb, cc, X[15], 7); ++ GG(cc, dd, ee, aa, bb, X[ 3], 15); ++ GG(bb, cc, dd, ee, aa, X[12], 7); ++ GG(aa, bb, cc, dd, ee, X[ 0], 12); ++ GG(ee, aa, bb, cc, dd, X[ 9], 15); ++ GG(dd, ee, aa, bb, cc, X[ 5], 9); ++ GG(cc, dd, ee, aa, bb, X[ 2], 11); ++ GG(bb, cc, dd, ee, aa, X[14], 7); ++ GG(aa, bb, cc, dd, ee, X[11], 13); ++ GG(ee, aa, bb, cc, dd, X[ 8], 12); ++ ++ /* round 3 */ ++ HH(dd, ee, aa, bb, cc, X[ 3], 11); ++ HH(cc, dd, ee, aa, bb, X[10], 13); ++ HH(bb, cc, dd, ee, aa, X[14], 6); ++ HH(aa, bb, cc, dd, ee, X[ 4], 7); ++ HH(ee, aa, bb, cc, dd, X[ 9], 14); ++ HH(dd, ee, aa, bb, cc, X[15], 9); ++ HH(cc, dd, ee, aa, bb, X[ 8], 13); ++ HH(bb, cc, dd, ee, aa, X[ 1], 15); ++ HH(aa, bb, cc, dd, ee, X[ 2], 14); ++ HH(ee, aa, bb, cc, dd, X[ 7], 8); ++ HH(dd, ee, aa, bb, cc, X[ 0], 13); ++ HH(cc, dd, ee, aa, bb, X[ 6], 6); ++ HH(bb, cc, dd, ee, aa, X[13], 5); ++ HH(aa, bb, cc, dd, ee, X[11], 12); ++ HH(ee, aa, bb, cc, dd, X[ 5], 7); ++ HH(dd, ee, aa, bb, cc, X[12], 5); ++ ++ /* round 4 */ ++ II(cc, dd, ee, aa, bb, X[ 1], 11); ++ II(bb, cc, dd, ee, aa, X[ 9], 12); ++ II(aa, bb, cc, dd, ee, X[11], 14); ++ II(ee, aa, bb, cc, dd, X[10], 15); ++ II(dd, ee, aa, bb, cc, X[ 0], 14); ++ II(cc, dd, ee, aa, bb, X[ 8], 15); ++ II(bb, cc, dd, ee, aa, X[12], 9); ++ II(aa, bb, cc, dd, ee, X[ 4], 8); ++ II(ee, aa, bb, cc, dd, X[13], 9); ++ II(dd, ee, aa, bb, cc, X[ 3], 14); ++ II(cc, dd, ee, aa, bb, X[ 7], 5); ++ II(bb, cc, dd, ee, aa, X[15], 6); ++ II(aa, bb, cc, dd, ee, X[14], 8); ++ II(ee, aa, bb, cc, dd, X[ 5], 6); ++ II(dd, ee, aa, bb, cc, X[ 6], 5); ++ II(cc, dd, ee, aa, bb, X[ 2], 12); ++ ++ /* round 5 */ ++ JJ(bb, cc, dd, ee, aa, X[ 4], 9); ++ JJ(aa, bb, cc, dd, ee, X[ 0], 15); ++ JJ(ee, aa, bb, cc, dd, X[ 5], 5); ++ JJ(dd, ee, aa, bb, cc, X[ 9], 11); ++ JJ(cc, dd, ee, aa, bb, X[ 7], 6); ++ JJ(bb, cc, dd, ee, aa, X[12], 8); ++ JJ(aa, bb, cc, dd, ee, X[ 2], 13); ++ JJ(ee, aa, bb, cc, dd, X[10], 12); ++ JJ(dd, ee, aa, bb, cc, X[14], 5); ++ JJ(cc, dd, ee, aa, bb, X[ 1], 12); ++ JJ(bb, cc, dd, ee, aa, X[ 3], 13); ++ JJ(aa, bb, cc, dd, ee, X[ 8], 14); ++ JJ(ee, aa, bb, cc, dd, X[11], 11); ++ JJ(dd, ee, aa, bb, cc, X[ 6], 8); ++ JJ(cc, dd, ee, aa, bb, X[15], 5); ++ JJ(bb, cc, dd, ee, aa, X[13], 6); ++ ++ /* parallel round 1 */ ++ JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8); ++ JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); ++ JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9); ++ JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11); ++ JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13); ++ JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15); ++ JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); ++ JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5); ++ JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); ++ JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7); ++ JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); ++ JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11); ++ JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14); ++ JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); ++ JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12); ++ JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); ++ ++ /* parallel round 2 */ ++ III(eee, aaa, bbb, ccc, ddd, X[ 6], 9); ++ III(ddd, eee, aaa, bbb, ccc, X[11], 13); ++ III(ccc, ddd, eee, aaa, bbb, X[ 3], 15); ++ III(bbb, ccc, ddd, eee, aaa, X[ 7], 7); ++ III(aaa, bbb, ccc, ddd, eee, X[ 0], 12); ++ III(eee, aaa, bbb, ccc, ddd, X[13], 8); ++ III(ddd, eee, aaa, bbb, ccc, X[ 5], 9); ++ III(ccc, ddd, eee, aaa, bbb, X[10], 11); ++ III(bbb, ccc, ddd, eee, aaa, X[14], 7); ++ III(aaa, bbb, ccc, ddd, eee, X[15], 7); ++ III(eee, aaa, bbb, ccc, ddd, X[ 8], 12); ++ III(ddd, eee, aaa, bbb, ccc, X[12], 7); ++ III(ccc, ddd, eee, aaa, bbb, X[ 4], 6); ++ III(bbb, ccc, ddd, eee, aaa, X[ 9], 15); ++ III(aaa, bbb, ccc, ddd, eee, X[ 1], 13); ++ III(eee, aaa, bbb, ccc, ddd, X[ 2], 11); ++ ++ /* parallel round 3 */ ++ HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); ++ HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7); ++ HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15); ++ HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11); ++ HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8); ++ HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); ++ HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6); ++ HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14); ++ HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); ++ HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13); ++ HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); ++ HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14); ++ HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); ++ HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13); ++ HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7); ++ HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); ++ ++ /* parallel round 4 */ ++ GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15); ++ GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5); ++ GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8); ++ GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11); ++ GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14); ++ GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); ++ GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); ++ GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14); ++ GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6); ++ GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); ++ GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12); ++ GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); ++ GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12); ++ GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5); ++ GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); ++ GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); ++ ++ /* parallel round 5 */ ++ FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8); ++ FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5); ++ FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12); ++ FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9); ++ FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12); ++ FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5); ++ FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14); ++ FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6); ++ FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8); ++ FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13); ++ FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6); ++ FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5); ++ FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15); ++ FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13); ++ FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11); ++ FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11); ++ ++ /* combine results */ ++ ddd += cc + MDbuf[1]; /* final result for MDbuf[0] */ ++ MDbuf[1] = MDbuf[2] + dd + eee; ++ MDbuf[2] = MDbuf[3] + ee + aaa; ++ MDbuf[3] = MDbuf[4] + aa + bbb; ++ MDbuf[4] = MDbuf[0] + bb + ccc; ++ MDbuf[0] = ddd; ++ ++ return; ++} ++ ++/********************************************************************/ ++ ++void MDfinish(dword *MDbuf, byte *strptr, dword lswlen, dword mswlen) ++{ ++ unsigned int i; /* counter */ ++ dword X[16]; /* message words */ ++ ++ memset(X, 0, 16*sizeof(dword)); ++ ++ /* put bytes from strptr into X */ ++ for (i=0; i<(lswlen&63); i++) { ++ /* byte i goes into word X[i div 4] at pos. 8*(i mod 4) */ ++ X[i>>2] ^= (dword) *strptr++ << (8 * (i&3)); ++ } ++ ++ /* append the bit m_n == 1 */ ++ X[(lswlen>>2)&15] ^= (dword)1 << (8*(lswlen&3) + 7); ++ ++ if ((lswlen & 63) > 55) { ++ /* length goes to next block */ ++ compress(MDbuf, X); ++ memset(X, 0, 16*sizeof(dword)); ++ } ++ ++ /* append length in bits*/ ++ X[14] = lswlen << 3; ++ X[15] = (lswlen >> 29) | (mswlen << 3); ++ compress(MDbuf, X); ++ ++ return; ++} ++ ++/************************ end of file rmd160.c **********************/ ++ +--- /dev/null ++++ b/net/rsa/rmd160.h +@@ -0,0 +1,154 @@ ++/********************************************************************\ ++ * ++ * FILE: rmd160.h ++ * ++ * CONTENTS: Header file for a sample C-implementation of the ++ * RIPEMD-160 hash-function. ++ * TARGET: any computer with an ANSI C compiler ++ * ++ * AUTHOR: Antoon Bosselaers, ESAT-COSIC ++ * DATE: 1 March 1996 ++ * VERSION: 1.0 ++ * ++ * Copyright (c) Katholieke Universiteit Leuven ++ * 1996, All Rights Reserved ++ * ++ * Conditions for use of the RIPEMD-160 Software ++ * ++ * The RIPEMD-160 software is freely available for use under the terms and ++ * conditions described hereunder, which shall be deemed to be accepted by ++ * any user of the software and applicable on any use of the software: ++ * ++ * 1. K.U.Leuven Department of Electrical Engineering-ESAT/COSIC shall for ++ * all purposes be considered the owner of the RIPEMD-160 software and of ++ * all copyright, trade secret, patent or other intellectual property ++ * rights therein. ++ * 2. The RIPEMD-160 software is provided on an "as is" basis without ++ * warranty of any sort, express or implied. K.U.Leuven makes no ++ * representation that the use of the software will not infringe any ++ * patent or proprietary right of third parties. User will indemnify ++ * K.U.Leuven and hold K.U.Leuven harmless from any claims or liabilities ++ * which may arise as a result of its use of the software. In no ++ * circumstances K.U.Leuven R&D will be held liable for any deficiency, ++ * fault or other mishappening with regard to the use or performance of ++ * the software. ++ * 3. User agrees to give due credit to K.U.Leuven in scientific publications ++ * or communications in relation with the use of the RIPEMD-160 software ++ * as follows: RIPEMD-160 software written by Antoon Bosselaers, ++ * available at http://www.esat.kuleuven.be/~cosicart/ps/AB-9601/. ++ * ++\********************************************************************/ ++ ++#ifndef RMD160H /* make sure this file is read only once */ ++#define RMD160H ++ ++/********************************************************************/ ++ ++/* typedef 8 and 32 bit types, resp. */ ++/* adapt these, if necessary, ++ for your operating system and compiler */ ++typedef unsigned char byte; ++typedef unsigned long dword; ++ ++ ++/********************************************************************/ ++ ++/* macro definitions */ ++ ++/* collect four bytes into one word: */ ++#define BYTES_TO_DWORD(strptr) \ ++ (((dword) *((strptr)+3) << 24) | \ ++ ((dword) *((strptr)+2) << 16) | \ ++ ((dword) *((strptr)+1) << 8) | \ ++ ((dword) *(strptr))) ++ ++/* ROL(x, n) cyclically rotates x over n bits to the left */ ++/* x must be of an unsigned 32 bits type and 0 <= n < 32. */ ++#define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n)))) ++ ++/* the five basic functions F(), G() and H() */ ++#define F(x, y, z) ((x) ^ (y) ^ (z)) ++#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) ++#define H(x, y, z) (((x) | ~(y)) ^ (z)) ++#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) ++#define J(x, y, z) ((x) ^ ((y) | ~(z))) ++ ++/* the ten basic operations FF() through III() */ ++#define FF(a, b, c, d, e, x, s) {\ ++ (a) += F((b), (c), (d)) + (x);\ ++ (a) = ROL((a), (s)) + (e);\ ++ (c) = ROL((c), 10);\ ++ } ++#define GG(a, b, c, d, e, x, s) {\ ++ (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ ++ (a) = ROL((a), (s)) + (e);\ ++ (c) = ROL((c), 10);\ ++ } ++#define HH(a, b, c, d, e, x, s) {\ ++ (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ ++ (a) = ROL((a), (s)) + (e);\ ++ (c) = ROL((c), 10);\ ++ } ++#define II(a, b, c, d, e, x, s) {\ ++ (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ ++ (a) = ROL((a), (s)) + (e);\ ++ (c) = ROL((c), 10);\ ++ } ++#define JJ(a, b, c, d, e, x, s) {\ ++ (a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ ++ (a) = ROL((a), (s)) + (e);\ ++ (c) = ROL((c), 10);\ ++ } ++#define FFF(a, b, c, d, e, x, s) {\ ++ (a) += F((b), (c), (d)) + (x);\ ++ (a) = ROL((a), (s)) + (e);\ ++ (c) = ROL((c), 10);\ ++ } ++#define GGG(a, b, c, d, e, x, s) {\ ++ (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ ++ (a) = ROL((a), (s)) + (e);\ ++ (c) = ROL((c), 10);\ ++ } ++#define HHH(a, b, c, d, e, x, s) {\ ++ (a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ ++ (a) = ROL((a), (s)) + (e);\ ++ (c) = ROL((c), 10);\ ++ } ++#define III(a, b, c, d, e, x, s) {\ ++ (a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ ++ (a) = ROL((a), (s)) + (e);\ ++ (c) = ROL((c), 10);\ ++ } ++#define JJJ(a, b, c, d, e, x, s) {\ ++ (a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ ++ (a) = ROL((a), (s)) + (e);\ ++ (c) = ROL((c), 10);\ ++ } ++ ++/********************************************************************/ ++ ++/* function prototypes */ ++ ++void MDinit(dword *MDbuf); ++/* ++ * initializes MDbuffer to "magic constants" ++ */ ++ ++void compress(dword *MDbuf, dword *X); ++/* ++ * the compression function. ++ * transforms MDbuf using message bytes X[0] through X[15] ++ */ ++ ++void MDfinish(dword *MDbuf, byte *strptr, dword lswlen, dword mswlen); ++/* ++ * puts bytes from strptr into X and pad out; appends length ++ * and finally, compresses the last block(s) ++ * note: length in bits == 8 * (lswlen + 2^32 mswlen). ++ * note: there are (lswlen mod 64) bytes left in strptr. ++ */ ++ ++#endif /* RMD160H */ ++ ++/*********************** end of file rmd160.h ***********************/ ++ +--- /dev/null ++++ b/net/rsa/rsa.c +@@ -0,0 +1,303 @@ ++/* ++ * FONSM RSA handling library ++ * ++ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. ++ * ++ * This library is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This library 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 Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * Created: 20070306 Pablo Martin Medrano ++ * ++ * Based on axTLS ++ * ++ * $Id: fonrsa.c 405 2007-09-19 15:26:17Z jesus.pico $ ++ */ ++#include ++#include ++#include "rsa.h" ++#include "rmd160.h" ++#include "bigint.h" ++#include "base64.h" ++ ++#include "public_key.h" ++ ++#define RMDsize 160 /* A RIPEMD-160 hash has 160 bits */ ++ ++typedef struct { ++ uint8_t *buffer; ++ size_t size; ++} DER_key; ++ ++typedef struct { ++ bigint *m; /* modulus */ ++ bigint *e; /* public exponent */ ++ int num_octets; ++ BI_CTX *bi_ctx; /* big integer handle */ ++} RSA_parameters; ++ ++typedef struct { ++ DER_key *derkey; ++ RSA_parameters *rsaparms; ++} RSA; ++ ++static void CH_free_der_key(DER_key *key) ++{ ++ free(key->buffer); ++ free(key); ++} ++ ++int CH_decrypt(RSA_parameters *rsa, uint8_t *buffer_in, uint8_t *buffer_out) ++{ ++ bigint *dat_bi; ++ bigint *decrypted_bi; ++ int byte_size; ++ ++ byte_size = rsa->num_octets; ++ dat_bi = bi_import(rsa->bi_ctx, buffer_in, byte_size); ++ rsa->bi_ctx->mod_offset = BIGINT_M_OFFSET; ++ bi_copy(rsa->m); ++ decrypted_bi = bi_mod_power(rsa->bi_ctx, dat_bi, rsa->e); ++ bi_export(rsa->bi_ctx, decrypted_bi, buffer_out, byte_size); ++ return 0; ++} ++ ++byte *RMDbinary(char *buffer, int len) ++{ ++ byte data[1024]; /* contains current mess. block */ ++ dword nbytes; /* length of this block */ ++ dword MDbuf[RMDsize / 32]; /* contains (A, B, C, D(, E)) */ ++ static byte hashcode[RMDsize / 8]; /* for final hash-value */ ++ dword X[16]; /* current 16-word chunk */ ++ unsigned int i, j; /* counters */ ++ dword length[2]; /* length in bytes of message */ ++ dword offset; /* # of unprocessed bytes at */ ++ /* call of MDfinish */ ++ int total = len; ++ char *tmp = buffer; ++ MDinit(MDbuf); ++ length[0] = 0; ++ length[1] = 0; ++ while ( len) { ++ memcpy(data, tmp, 1024); ++ if(len > 1024) ++ { ++ nbytes = 1024; ++ len -= 1024; ++ tmp += 1024; ++ } else { ++ nbytes = len; ++ len = 0; ++ } ++ /* process all complete blocks */ ++ for (i = 0; i < (nbytes >> 6); i++) { ++ for (j = 0; j < 16; j++) ++ X[j] = BYTES_TO_DWORD(data + 64 * i + 4 * j); ++ compress(MDbuf, X); ++ } ++ /* update length[] */ ++ if (length[0] + nbytes < length[0]) ++ length[1]++; /* overflow to msb of length */ ++ length[0] += nbytes; ++ } ++ /* finish: */ ++ offset = length[0] & 0x3C0; /* extract bytes 6 to 10 inclusive */ ++ MDfinish(MDbuf, data + offset, length[0], length[1]); ++ ++ for (i = 0; i < RMDsize / 8; i += 4) { ++ hashcode[i] = MDbuf[i >> 2]; ++ hashcode[i + 1] = (MDbuf[i >> 2] >> 8); ++ hashcode[i + 2] = (MDbuf[i >> 2] >> 16); ++ hashcode[i + 3] = (MDbuf[i >> 2] >> 24); ++ } ++ ++ return (byte *) hashcode; ++} ++ ++static DER_key *CH_load_pem_key(void) ++{ ++ DER_key *ret; ++ uint8_t *buffer; ++ char *b64,*p,*t; ++ char key[1024]; ++ size_t filesize; ++ int size; ++ ++ if ((ret = (DER_key *)malloc(sizeof(DER_key))) == NULL) ++ return NULL; ++ buffer = public_key; ++ p = (char *)buffer; ++ while ((*p != '\n') && (*p != '\0')) ++ p++; ++ if (*p == '\0') { ++ free(ret); ++ return NULL; ++ } ++ p++; ++ b64 = t = p; ++ while((p - b64) <= filesize) { ++ if ((*p == '-')) { ++ break; ++ } else if ((*p != '\n') && (*p != ' ') && (*p != '\t')) { ++ *t = *p; ++ t++; ++ } ++ p++; ++ } ++ *t = '\0'; ++ size = B64_decode(b64, key, strlen(b64), 1024); ++ if (size < 0) { ++ free(buffer); ++ free(ret); ++ return NULL; ++ } ++ //free(buffer); ++ ret->buffer = (char *)malloc(size); ++ ret->size = size; ++ memcpy((void *)ret->buffer, (void *)key, size); ++ return ret; ++} ++ ++/* ++ * Similar to RSA_pub_key_new, rewritten to make this program depend only on bi module ++ */ ++void CH_pub_key_new(RSA_parameters **rsa, const uint8_t *modulus, int mod_len, const uint8_t *pub_exp, int pub_len) ++{ ++ RSA_parameters *rsa_parameters; ++ ++ BI_CTX *bi_ctx = bi_initialize(); ++ *rsa = (RSA_parameters *)calloc(1, sizeof(RSA_parameters)); ++ rsa_parameters = *rsa; ++ rsa_parameters->bi_ctx = bi_ctx; ++ rsa_parameters->num_octets = (mod_len & 0xFFF0); ++ rsa_parameters->m = bi_import(bi_ctx, modulus, mod_len); ++ bi_set_mod(bi_ctx, rsa_parameters->m, BIGINT_M_OFFSET); ++ rsa_parameters->e = bi_import(bi_ctx, pub_exp, pub_len); ++ bi_permanent(rsa_parameters->e); ++} ++ ++/* ++ * Get the public key specifics from an ASN.1 encoded file ++ * A function lacking in the exported axTLS API ++ * ++ * This is a really weird hack that only works with RSA public key ++ * files ++ */ ++static int asn1_get_public_key(const uint8_t *buf, int len, RSA_parameters **rsa_parameters) ++{ ++ uint8_t *modulus, *pub_exp; ++ int mod_len, pub_len; ++ ++ pub_len = 3; ++ mod_len = len - 37; ++ if (buf[0] != 0x30) { ++ return -1; ++ } ++ ++ pub_exp = (uint8_t *)malloc(3); ++ modulus = (uint8_t *)malloc(mod_len); ++ memcpy(modulus, buf + 32 , mod_len); ++ memcpy(pub_exp, buf + 34 + mod_len, 3); ++ if (mod_len <= 0 || pub_len <= 0 ) ++ return -1; ++ CH_pub_key_new(rsa_parameters, modulus, mod_len, pub_exp, pub_len); ++ ++ free(modulus); ++ free(pub_exp); ++ return 0; ++} ++ ++ ++/* FR_init */ ++void *FR_init(void) ++{ ++ DER_key *derkey; ++ RSA_parameters *rsa_parameters; ++ ++ derkey = CH_load_pem_key(); ++ if ((asn1_get_public_key(derkey->buffer, derkey->size, &rsa_parameters)) != 0) { ++ fprintf(stderr, "Error: Extracting public key from file\n"); ++ return 0; ++ } ++ CH_free_der_key(derkey); ++ return (void *)rsa_parameters; ++} ++ ++FONRSA_ERROR FR_end(void *handle) ++{ ++ RSA_parameters *rsa_parameters = (RSA_parameters *)handle; ++ ++ free(rsa_parameters); ++ return FONRSA_OK; ++} ++ ++/* ++ * ++ * Implementation of PKCS 1.5 padding, borrowed from ++ * Tom's code (public domain) ++ */ ++ ++/* Standalone FR_verify_file */ ++FONRSA_ERROR FR_verify_file(void *handler, char *file_data, int file_len, ++ char *signature_buffer, int signature_size) ++{ ++ int j; ++ byte *hashcode; ++ byte hash[20]; ++ uint8_t *decrypted; ++ RSA_parameters *rsa_parameters = (RSA_parameters *)handler; ++ ++ /* Calculates the RIPEMD-160 hash of the file */ ++ hashcode = RMDbinary (file_data, file_len); ++ ++ if (rsa_parameters->num_octets != signature_size) ++ return FONRSA_SIZE; ++ decrypted = (uint8_t *)malloc(rsa_parameters->num_octets); ++ if (CH_decrypt(rsa_parameters, signature_buffer, decrypted)) { ++ printf("Error: Decrypting signature\n"); ++ return FONRSA_VERIFICATION_FAILURE; ++ } ++ memcpy(hash, decrypted + 492, 20); ++ //free(decrypted); ++ //free(signature_buffer); ++ for (j = 0; j < RMDsize/8; j++) { ++ if (hash[j] != hashcode[j]) ++ return FONRSA_VERIFICATION_FAILURE; ++ } ++ return FONRSA_OK; ++} ++ ++int rsa_check_signature(char *signature, int signature_len, char *buffer, int buffer_len) ++{ ++ FONRSA_ERROR fonrsa_error; ++ void *handle; ++ handle = FR_init(); ++ if (handle == NULL) { ++ printf("Error loading keys\n"); ++ return 1; ++ } ++ fonrsa_error = FR_verify_file(handle, buffer, buffer_len, signature, signature_len); ++ FR_end(handle); ++ switch (fonrsa_error) { ++ case FONRSA_OK: ++ printf("Verified OK\n"); ++ return 0; ++ case FONRSA_VERIFICATION_FAILURE: ++ printf("Verification failure\n"); ++ return 1; ++ default: ++ printf("Verification error\n"); ++ return -1; ++ } ++ ++} +--- /dev/null ++++ b/net/rsa/rsa.h +@@ -0,0 +1,46 @@ ++/* ++ * FONSM RSA handling library, used by fonsmcd and foncheckrsa ++ * ++ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. ++ * ++ * This library is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This library 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 Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * Created: 20070306 Pablo Martin Medrano ++ * ++ * $Id: fonrsa.h 404 2007-09-17 10:41:31Z jesus.pico $ ++ */ ++#ifndef _FONRSA_H ++#define _FONRSA_H ++ ++#define MINIMUM_PADING_BYTES_PKCS_1_5 3 ++ ++typedef enum { ++ FONRSA_OK = 0, ++ FONRSA_VERIFICATION_FAILURE = 1, ++ FONRSA_OPENKEY = 2, ++ FONRSA_SIZE = 3, ++ FONRSA_LOADFILE = 4, ++ FONRSA_CRYPT = 5, ++ FONRSA_DECRYPT = 6, ++ FONRSA_SAVEFILE = 7, ++ FONRSA_NOSYS = 8, ++ FONRSA_VERIFY = 9 ++} FONRSA_ERROR; ++ ++int rsa_check_signature(char *signature, int signature_len, char *buffer, int buffer_len); ++ ++#endif ++ ++ +--- /dev/null ++++ b/net/rsa/sign.h +@@ -0,0 +1,27 @@ ++/* ++ * Signature interface ++ * ++ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. ++ * ++ * Created: 20070417 Pablo Martín Medrano ++ * ++ * $Id: sign.h 389 2007-06-11 08:29:56Z pablo.martin $ ++ */ ++#ifndef __SIGN_H__ ++#define __SIGN_H__ ++#ifdef __cplusplus ++ extern "C" { ++#endif ++ ++void SG_init(void); ++void *SG_start(char *private_key_path, char *public_key_path); ++void SG_stop(void *handle); ++int SG_crypt(void *data, unsigned char *text, int size_text, unsigned char *crypted_text, ++ unsigned int crypted_text_buffer_size, int *crypted_size); ++int SG_crypt_v2(void *data, unsigned char *text, int size_text, unsigned char *crypted_text, ++ unsigned int crypted_text_buffer_size, int *crypted_size); ++#ifdef __cplusplus ++} ++#endif ++#endif /* #ifdef __SIGN_H__ */ ++ +--- /dev/null ++++ b/net/rsa/sign_openssl.c +@@ -0,0 +1,437 @@ ++/* ++ * Signature using OpenSSL ++ * ++ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. ++ * ++ * Created: 20070417 Pablo Martín Medrano ++ * ++ * $Id: sign_openssl.c 346 2007-05-10 19:51:38Z pablo.martin $ ++ */ ++/* ++ * ++ * How the RSA public and private key was generated ++ * To check .FON files ++ * openssl genrsa -out private_fon_rsa_key.pem 4096 ++ * openssl rsa -in private_fon_rsa_key.pem -pubout -out public_fon_rsa_key.pem ++ * ++ * How the Status Manager public and private key was generated ++ * openssl genrsa -out private_sm_rsa_key.pem 2048 ++ * openssl rsa -in private_sm_rsa_key.pem -pubout -out public_sm_rsa_key.pem ++ * ++ * How to sign using the RSA private key (This is what fonsign does) ++ * openssl dgst -rmd160 -sign private_fon_rsa_key.pem FILE > SIGNATURE ++ * How to verify using the RSA public key (This is what fonverify + foncheckrsa does) ++ * openssl dgst -rmd160 -verify public_fon_rsa_key.pem -signature SIGNATURE FILE ++ * Convert to DER file (to use it in La Fonera) ++ * openssl rsa -inform PEM -outform DER -pubin -in public_fon_rsa_key.pem -pubout -out public_fon_rsa_key.der ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifndef __MAINTEST__ ++#include "log.h" ++#else ++#define fon_warning printf ++#define fon_debug printf ++#define fon_critical printf ++#endif ++#include "sign.h" ++ ++typedef struct { ++ RSA *rsa; ++ int rsa_size; ++ EVP_PKEY *pkey; ++ int pkey_size; ++ RSA *public_rsa; ++ int public_rsa_size; ++ EVP_PKEY *public_pkey; ++ int public_pkey_size; ++} Sign; ++ ++typedef enum { ++ KEY_PUBLIC = 0, ++ KEY_PRIVATE ++} KEY_TYPE; ++ ++static EVP_PKEY *SG_load_key(char *key_path, KEY_TYPE type); ++static unsigned char *load_file_in_buffer(char *path, int *size); ++static int save_file_from_buffer(char *path, char *buffer, int size); ++ ++void SG_init(void) ++{ ++ SSL_load_error_strings(); ++ SSL_library_init(); ++ OpenSSL_add_all_algorithms(); ++ OpenSSL_add_all_ciphers(); ++ OpenSSL_add_all_digests(); ++} ++ ++static unsigned char *load_file_in_buffer(char *path, int *size) ++{ ++ char *buffer; ++ struct stat st; ++ int fd; ++ ++ if (stat(path, &st)) ++ return NULL; ++ buffer = (char *)malloc(st.st_size); ++ if (buffer == NULL) ++ return NULL; ++ if ((fd = open(path, O_RDONLY)) == -1) { ++ free(buffer); ++ return NULL; ++ } ++ if (read(fd,buffer,st.st_size) != (ssize_t)st.st_size) { ++ free(buffer); ++ close(fd); ++ return NULL; ++ } ++ *size = (int)st.st_size; ++ close(fd); ++ return buffer; ++} ++ ++static int save_file_from_buffer(char *path, char *buffer, int size) ++{ ++ int fd; ++ ++ if ((fd = open(path, O_WRONLY | O_CREAT, 0644)) == -1) ++ return -1; ++ if (write(fd, buffer, (size_t)size) != ((ssize_t)size)) { ++ close(fd); ++ return -1; ++ } ++ close(fd); ++ return 0; ++} ++ ++static EVP_PKEY *SG_load_key(char *key_path, KEY_TYPE type) ++{ ++ BIO *key = NULL; ++ EVP_PKEY *pkey; ++ ++ if ((key = BIO_new(BIO_s_file())) == NULL) { ++ //ERR_print_errors(err); ++ fon_warning("%s: Error calling BIO_new()\n", __FUNCTION__); ++ return NULL; ++ } ++ if (BIO_read_filename(key, key_path) <= 0) { ++ fon_warning("%s: Error opening %s\n", __FUNCTION__, key_path); ++ // ERR_print_errors(err); ++ BIO_free(key); ++ } ++ if (type == KEY_PUBLIC) { ++ pkey = PEM_read_bio_PUBKEY(key, NULL, NULL, NULL); ++ } else if (type == KEY_PRIVATE) { ++ pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, NULL); ++ } else { ++ return NULL; ++ } ++ ++ if (pkey == NULL) { ++ fon_warning("%s: Error reading %s\n", __FUNCTION__, key_path); ++ BIO_free(key); ++ return NULL; ++ } ++ BIO_free(key); ++ return pkey; ++} ++ ++void *SG_start(char *private_key_path, char *public_key_path) ++{ ++ Sign *sign; ++ ++ if ((sign = (Sign *)malloc(sizeof(Sign))) == NULL) ++ return NULL; ++ memset(sign, 0, sizeof(Sign)); ++ if (private_key_path != NULL) { ++ if ((sign->pkey = SG_load_key(private_key_path, KEY_PRIVATE)) == NULL) { ++ fon_warning("%s: Error loading %s", __FUNCTION__, private_key_path); ++ return NULL; ++ } ++ } ++ if (public_key_path != NULL) { ++ if ((sign->public_pkey = SG_load_key(public_key_path, KEY_PUBLIC)) == NULL) { ++ fon_warning("%s: Error loading %s", __FUNCTION__, public_key_path); ++ return NULL; ++ } ++ } ++ if (sign->pkey != NULL) { ++ sign->pkey_size = EVP_PKEY_size(sign->pkey); ++ if ((sign->rsa = EVP_PKEY_get1_RSA(sign->pkey)) == NULL) { ++ EVP_PKEY_free(sign->pkey); ++ return NULL; ++ } ++ } ++ if (sign->public_pkey != NULL) { ++ sign->public_pkey_size = EVP_PKEY_size(sign->public_pkey); ++ if ((sign->public_rsa = EVP_PKEY_get1_RSA(sign->public_pkey)) == NULL) { ++ EVP_PKEY_free(sign->pkey); ++ return NULL; ++ } ++ } ++ if (((sign->rsa == NULL) && (private_key_path != NULL)) || ++ ((sign->public_rsa == NULL) && (public_key_path != NULL))) { ++ fon_warning("%s: Error calling EVP_PKEY_get1_RSA()", __FUNCTION__); ++ return NULL; ++ } ++ if (sign->rsa != NULL) { ++ sign->rsa_size = RSA_size(sign->rsa); ++ if (RSA_check_key(sign->rsa) != 1) { ++ fon_warning("%s: RSA key failure", __FUNCTION__); ++ return NULL; ++ } ++ } ++ ++ return (void *)sign; ++} ++ ++void SG_stop(void *handle) ++{ ++ Sign *sign = (Sign *)handle; ++ ++ EVP_PKEY_free(sign->pkey); ++ EVP_PKEY_free(sign->public_pkey); ++ if (sign->rsa != NULL) ++ RSA_free(sign->rsa); ++ if (sign->public_rsa != NULL) ++ RSA_free(sign->public_rsa); ++ free(sign); ++} ++ ++int SG_verify(void *data, unsigned char *text, unsigned int size_text, ++ unsigned char *signature, unsigned int size_signature) ++{ ++ EVP_MD_CTX mdctx; ++ EVP_MD *md; ++ EVP_PKEY *pkey; ++ int ret; ++ Sign *sign = (Sign *)data; ++ ++ md = (EVP_MD *)EVP_ripemd160(); ++ if(!EVP_VerifyInit(&mdctx, md)) ++ return 4; ++ if (!EVP_VerifyUpdate(&mdctx, (const void *)text, (unsigned int)size_text)) { ++ return 5; ++ } ++ ret = EVP_VerifyFinal(&mdctx, (const char *)signature, size_signature, sign->public_pkey); ++ EVP_PKEY_free(pkey); ++ EVP_MD_CTX_cleanup(&mdctx); ++ return ret; ++} ++ ++int SG_sign(void *data, void *text, unsigned int size_text, void *signature_buffer, ++ unsigned int size_signature_buffer, unsigned int *size_signature) ++{ ++ unsigned char *digest[EVP_MAX_MD_SIZE]; ++ EVP_MD_CTX mdctx; ++ EVP_MD *md; ++ int ret; ++ Sign *sign = (Sign *)data; ++ ++ if (size_signature_buffer < sign->pkey_size) ++ return 1; ++ ++ md = (EVP_MD *)EVP_ripemd160(); ++ EVP_SignInit(&mdctx, md); ++ if (!EVP_SignUpdate(&mdctx, (const void *)text, (unsigned int)size_text)) { ++ return 2; ++ } ++ if (!EVP_SignFinal(&mdctx, (unsigned char *)signature_buffer, (unsigned int *)size_signature, sign->pkey)) { ++ return 3; ++ } ++ EVP_MD_CTX_cleanup(&mdctx); ++ ++ return 0; ++} ++ ++/* ++ * It's not advised to crypt using RAW ... unless you have crypted the buffer using AES before. ++ */ ++int SG_crypt(void *data, unsigned char *text, int size_text, ++ unsigned char *crypted_text, unsigned int crypted_text_buffer_size, ++ int *crypted_size) ++{ ++ EVP_MD_CTX mdctx; ++ EVP_MD *md; ++ int retsize; ++ Sign *sign = (Sign *)data; ++ ++ if (crypted_text_buffer_size < sign->pkey_size) { ++ fon_critical("%s: size_signature_buffer [%u] < %u", __FUNCTION__, size_text, sign->pkey_size); ++ return 1; ++ } ++ if (size_text != sign->pkey_size) { ++ fon_critical("%s: size_text [%u] != %u", __FUNCTION__, size_text, sign->pkey_size); ++ return 2; ++ } ++ /* The buffer is pre-padded with random data ... */ ++ fon_debug("%s: About to call RSA_private_encrypt(%d, %x, %x, %x, %d)", ++ __FUNCTION__, size_text, crypted_text, sign->rsa, RSA_NO_PADDING); ++ retsize = RSA_private_encrypt(size_text, text, crypted_text, sign->rsa, RSA_NO_PADDING); ++ if (retsize == -1) { ++ fon_critical("%s: Error calling RSA_private_encrypt(%d, %x, %x, %x, %d)", ++ __FUNCTION__, size_text, crypted_text, sign->rsa, RSA_NO_PADDING); ++ return 1; ++ } ++ *crypted_size = retsize; ++ return 0; ++} ++ ++/* SG_decrypt */ ++int SG_decrypt(void *data, unsigned char *cryptext, int cryptext_size, unsigned char *plaintext, ++ int plaintext_buffer_size, int *plaintext_size) ++{ ++ EVP_MD_CTX mdctx; ++ EVP_MD *md; ++ int retsize; ++ Sign *sign = (Sign *)data; ++ ++ if (plaintext_buffer_size < sign->public_pkey_size) { ++ fon_critical("%s: plaintext_buffer_size [%u] < %u", __FUNCTION__, plaintext_buffer_size, sign->public_pkey_size); ++ return 1; ++ } ++ if (cryptext_size != sign->public_pkey_size) { ++ fon_critical("%s: cryptext_size [%u] != %u", __FUNCTION__, cryptext_size, sign->public_pkey_size); ++ return 2; ++ } ++ retsize = RSA_public_decrypt(cryptext_size, cryptext, plaintext, sign->public_rsa, RSA_NO_PADDING); ++ if (retsize == -1) ++ return 1; ++ *plaintext_size = retsize; ++ return 0; ++} ++ ++#ifdef __MAINTEST__ ++int main(int argc, char **argv) ++{ ++ size_t argv0_size; ++ char *token; ++ ++ argv0_size = strlen(argv[0]); ++ if (argv0_size < 7) { ++ fprintf(stderr, "%s?", argv[0]); ++ return 1; ++ } ++ token = argv[0] + argv0_size - 7; ++ ++ SG_init(); ++ if (!strcmp(token, "fonsign")) { ++ return main_fonsign(argc, argv); ++ } else if (!strcmp(token, "foncryp")) { ++ return main_foncryp(argc, argv); ++ } ++ fprintf(stderr, "%s?", argv[0]); ++ return 1; ++} ++ ++int main_foncryp(int argc, char **argv) ++{ ++ void *handle = NULL; ++ int encrypt = 0; ++ char *filebuffer = NULL; ++ char crypted[1024]; ++ int size, crypted_size, ret; ++ ++ if (argc != 5) { ++ printf("Usage: %s encrypt|decrypt \n", argv[0]); ++ return 1; ++ } ++ if (!strcmp(argv[1], "encrypt")) { ++ printf("Encryption mode\n"); ++ encrypt = 1; ++ } else ++ printf("Decryption mode\n"); ++ if (encrypt) ++ handle = SG_start(argv[2], NULL); ++ else ++ handle = SG_start(NULL, argv[2]); ++ if (handle == NULL) { ++ printf("Error loading keys\n"); ++ return 1; ++ } ++ ++ filebuffer = load_file_in_buffer(argv[3], &size); ++ if (filebuffer == NULL) { ++ printf("Error reading %s\n", argv[3]); ++ SG_stop(handle); ++ return 1; ++ } ++ if (encrypt) ++ ret = SG_crypt(handle, filebuffer, size, crypted, 1024, &crypted_size); ++ else ++ ret = SG_decrypt(handle, filebuffer, size, crypted, 1024, &crypted_size); ++ ++ if (ret) { ++ printf("Error crypting %d bytes\n", size); ++ SG_stop(handle); ++ return 1; ++ } ++ printf("Crypted size %d\n", crypted_size); ++ if (save_file_from_buffer(argv[4], crypted, crypted_size)) { ++ printf("Error saving file\n"); ++ SG_stop(handle); ++ return 1; ++ } ++ ++ SG_stop(handle); ++ return 0; ++} ++ ++int main_fonsign(int argc, char **argv) ++{ ++ void *handle = NULL; ++ char signature_buffer[4096]; ++ char *signature; ++ unsigned int signature_size; ++ struct stat st; ++ char *filebuffer = NULL; ++ int size; ++ int ret = -1; ++ ++ if (argc != 5) { ++ fprintf(stderr, "usage: %s \n", argv[0]); ++ goto end; ++ } ++ handle = SG_start(argv[1], argv[2]); ++ if (handle == NULL) { ++ fprintf(stderr, "Error calling SG_start(%s)\n", argv[1]); ++ goto end; ++ } ++ filebuffer = load_file_in_buffer(argv[3], &size); ++ if (filebuffer == NULL) { ++ fprintf(stderr, "Error reading %s\n", argv[3]); ++ goto end; ++ } ++ if (SG_sign(handle, filebuffer, size, signature_buffer, 4096, &signature_size)) { ++ fprintf(stderr, "Error calling SG_sign()\n"); ++ goto end; ++ } ++ ret = SG_verify(handle, filebuffer, size, signature_buffer, signature_size); ++ if (ret == 0) ++ fprintf(stderr, "signature failure\n"); ++ else if (ret == 1) { ++ fprintf(stderr, "signature ok\n"); ++ ret = 0; ++ } else { ++ fprintf(stderr, "signature error\n"); ++ goto end; ++ } ++ if (save_file_from_buffer(argv[4], signature_buffer, signature_size)) { ++ fprintf(stderr, "Error writing to %s\n", argv[4]); ++ goto end; ++ } ++ ret = 0; ++end: ++ if (filebuffer != NULL) ++ free(filebuffer); ++ if (handle != NULL) ++ SG_stop(handle); ++ return ret; ++} ++#endif ++ +--- /dev/null ++++ b/net/uip-0.9/fs.c +@@ -0,0 +1,154 @@ ++/** ++ * \addtogroup httpd ++ * @{ ++ */ ++ ++/** ++ * \file ++ * HTTP server read-only file system code. ++ * \author Adam Dunkels ++ * ++ * A simple read-only filesystem. ++ */ ++ ++/* ++ * Copyright (c) 2001, Swedish Institute of Computer Science. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. Neither the name of the Institute nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * This file is part of the lwIP TCP/IP stack. ++ * ++ * Author: Adam Dunkels ++ * ++ * $Id: fs.c,v 1.7.2.3 2003/10/07 13:22:27 adam Exp $ ++ */ ++ ++#include "uip.h" ++#include "httpd.h" ++#include "fs.h" ++#include "fsdata.h" ++ ++#include "fsdata.c" ++ ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++static u16_t count[FS_NUMFILES]; ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++ ++/*-----------------------------------------------------------------------------------*/ ++static u8_t ++fs_strcmp(const char *str1, const char *str2) ++{ ++ u8_t i; ++ i = 0; ++ loop: ++ ++ if(str2[i] == 0 || ++ str1[i] == '\r' || ++ str1[i] == '\n') { ++ return 0; ++ } ++ ++ if(str1[i] != str2[i]) { ++ return 1; ++ } ++ ++ ++ ++i; ++ goto loop; ++} ++/*-----------------------------------------------------------------------------------*/ ++int ++fs_open(const char *name, struct fs_file *file) ++{ ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++ u16_t i = 0; ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++ struct fsdata_file_noconst *f; ++ ++ for(f = (struct fsdata_file_noconst *)FS_ROOT; ++ f != NULL; ++ f = (struct fsdata_file_noconst *)f->next) { ++ ++ if(fs_strcmp(name, f->name) == 0) { ++ file->data = f->data; ++ file->len = f->len; ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++ ++count[i]; ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++ return 1; ++ } ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++ ++i; ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++ ++ } ++ return 0; ++} ++/*-----------------------------------------------------------------------------------*/ ++void ++fs_init(void) ++{ ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++ u16_t i; ++ for(i = 0; i < FS_NUMFILES; i++) { ++ count[i] = 0; ++ } ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++} ++/*-----------------------------------------------------------------------------------*/ ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++u16_t fs_count ++(char *name) ++{ ++ struct fsdata_file_noconst *f; ++ u16_t i; ++ ++ i = 0; ++ for(f = (struct fsdata_file_noconst *)FS_ROOT; ++ f != NULL; ++ f = (struct fsdata_file_noconst *)f->next) { ++ ++ if(fs_strcmp(name, f->name) == 0) { ++ return count[i]; ++ } ++ ++i; ++ } ++ return 0; ++} ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++/*-----------------------------------------------------------------------------------*/ +--- /dev/null ++++ b/net/uip-0.9/fsdata.c +@@ -0,0 +1,199 @@ ++static const char data_flashing_html[] = { ++ /* /flashing.html */ ++ 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, ++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, ++ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, ++ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, ++ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, ++ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, ++ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, ++ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, ++ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, ++ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, ++ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x3c, 0x62, ++ 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3d, ++ 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30, ++ 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x20, 0x68, ++ 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x31, 0x30, 0x30, 0x25, ++ 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, ++ 0x66, 0x66, 0x66, 0x3b, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, ++ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, ++ 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, 0x62, 0x30, 0x33, 0x34, ++ 0x3b, 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, ++ 0x3e, 0x3c, 0x68, 0x31, 0x3e, 0x55, 0x70, 0x67, 0x72, 0x61, ++ 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, ++ 0x6d, 0x20, 0x2e, 0x2e, 0x2e, 0x2e, 0x3c, 0x2f, 0x68, 0x31, ++ 0x3e, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, ++ 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, ++ 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; ++ ++static const char data_fail_html[] = { ++ /* /fail.html */ ++ 0x2f, 0x66, 0x61, 0x69, 0x6c, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, ++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, ++ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, ++ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, ++ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, ++ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, ++ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, ++ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, ++ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, ++ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, ++ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9, ++ 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c, ++ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9, ++ 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46, ++ 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49, ++ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, ++ 0x3e, 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, ++ 0x9, 0x9, 0x3c, 0x68, 0x31, 0x3e, 0x46, 0x6c, 0x61, 0x73, ++ 0x68, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, ++ 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x9, 0x9, 0x45, ++ 0x52, 0x52, 0x4f, 0x52, 0x20, 0x2d, 0x20, 0x74, 0x68, 0x65, ++ 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x79, 0x6f, 0x75, ++ 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x20, ++ 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, ++ 0x70, 0x61, 0x73, 0x73, 0x20, 0x76, 0x65, 0x72, 0x69, 0x66, ++ 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x50, ++ 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x6d, 0x61, 0x6b, 0x65, ++ 0x20, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x75, ++ 0x73, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x66, 0x66, 0x69, ++ 0x63, 0x69, 0x61, 0x6c, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, ++ 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, ++ 0x20, 0x62, 0x79, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, ++ 0x2f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2e, ++ 0x66, 0x6f, 0x6e, 0x6f, 0x73, 0x66, 0x65, 0x72, 0x61, 0x2e, ++ 0x6f, 0x72, 0x67, 0x2f, 0xa, 0x9, 0x3c, 0x2f, 0x62, 0x6f, ++ 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, ++ 0x3e, 0xa, }; ++ ++static const char data_404_html[] = { ++ /* /404.html */ ++ 0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, ++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x34, ++ 0x30, 0x34, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, ++ 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0xd, 0xa, 0x53, ++ 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, ++ 0x2f, 0x30, 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, ++ 0x3a, 0x2f, 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, ++ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, ++ 0x75, 0x69, 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, ++ 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, ++ 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, ++ 0xd, 0xa, 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, ++ 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, ++ 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, ++ 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, ++ 0x3c, 0x68, 0x31, 0x3e, 0x34, 0x30, 0x34, 0x20, 0x2d, 0x20, ++ 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, ++ 0x6f, 0x75, 0x6e, 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0x3c, ++ 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0x3c, 0x2f, ++ 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, 0x74, 0x6d, ++ 0x6c, 0x3e, }; ++ ++static const char data_index_html[] = { ++ /* /index.html */ ++ 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, ++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, ++ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, ++ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, ++ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, ++ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, ++ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, ++ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, ++ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, ++ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, ++ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9, ++ 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c, ++ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9, ++ 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46, ++ 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49, ++ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, ++ 0x3e, 0xa, 0x9, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, ++ 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, ++ 0x79, 0x6c, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, ++ 0x6e, 0x3a, 0x20, 0x30, 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, ++ 0x6f, 0x3b, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, ++ 0x31, 0x30, 0x30, 0x25, 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, ++ 0x72, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x20, 0x62, ++ 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, ++ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, ++ 0x62, 0x30, 0x33, 0x34, 0x3b, 0x22, 0x3e, 0xa, 0x9, 0x9, ++ 0x3c, 0x68, 0x31, 0x3e, 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, ++ 0x72, 0x61, 0x20, 0x46, 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, ++ 0x65, 0x20, 0x55, 0x49, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, ++ 0x9, 0x9, 0x3c, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6d, 0x65, ++ 0x74, 0x68, 0x6f, 0x64, 0x3d, 0x22, 0x70, 0x6f, 0x73, 0x74, ++ 0x22, 0x20, 0x65, 0x6e, 0x63, 0x74, 0x79, 0x70, 0x65, 0x3d, ++ 0x22, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, ++ 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x64, 0x61, 0x74, 0x61, ++ 0x22, 0x3e, 0xa, 0x9, 0x9, 0x9, 0x3c, 0x69, 0x6e, 0x70, ++ 0x75, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69, ++ 0x6c, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x66, 0x69, ++ 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x3e, 0xa, 0x9, 0x9, ++ 0x9, 0x3c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x74, 0x79, ++ 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x3e, ++ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x3e, ++ 0xa, 0x9, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, ++ 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; ++ ++static const char data_flash_html[] = { ++ /* /flash.html */ ++ 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, ++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, ++ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, ++ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, ++ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, ++ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, ++ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, ++ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, ++ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, ++ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, ++ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9, ++ 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c, ++ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9, ++ 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46, ++ 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49, ++ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, ++ 0x3e, 0xa, 0x9, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, ++ 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, ++ 0x79, 0x6c, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, ++ 0x6e, 0x3a, 0x20, 0x30, 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, ++ 0x6f, 0x3b, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, ++ 0x31, 0x30, 0x30, 0x25, 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, ++ 0x72, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x20, 0x62, ++ 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, ++ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, ++ 0x62, 0x30, 0x33, 0x34, 0x3b, 0x22, 0x3e, 0xa, 0x9, 0x9, ++ 0x3c, 0x68, 0x31, 0x3e, 0x46, 0x6c, 0x61, 0x73, 0x68, 0x69, ++ 0x6e, 0x67, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x9, 0x9, ++ 0x54, 0x68, 0x65, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, ++ 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x72, ++ 0x79, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x6c, ++ 0x61, 0x73, 0x68, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, ++ 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x70, ++ 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x2c, 0x20, 0x74, 0x68, ++ 0x65, 0x20, 0x6c, 0x65, 0x64, 0x73, 0x20, 0x77, 0x69, 0x6c, ++ 0x6c, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x6f, ++ 0x20, 0x62, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0xa, 0xa, 0x9, ++ 0x9, 0x41, 0x66, 0x74, 0x65, 0x72, 0x20, 0x61, 0x20, 0x73, ++ 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x6c, ++ 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68, ++ 0x65, 0x20, 0x62, 0x6f, 0x78, 0x20, 0x77, 0x69, 0x6c, 0x6c, ++ 0x20, 0x72, 0x65, 0x62, 0x6f, 0x6f, 0x74, 0xa, 0x9, 0x3c, ++ 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, ++ 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; ++ ++const struct fsdata_file file_flashing_html[] = {{NULL, data_flashing_html, data_flashing_html + 15, sizeof(data_flashing_html) - 15}}; ++ ++const struct fsdata_file file_fail_html[] = {{file_flashing_html, data_fail_html, data_fail_html + 11, sizeof(data_fail_html) - 11}}; ++ ++const struct fsdata_file file_404_html[] = {{file_fail_html, data_404_html, data_404_html + 10, sizeof(data_404_html) - 10}}; ++ ++const struct fsdata_file file_index_html[] = {{file_404_html, data_index_html, data_index_html + 12, sizeof(data_index_html) - 12}}; ++ ++const struct fsdata_file file_flash_html[] = {{file_index_html, data_flash_html, data_flash_html + 12, sizeof(data_flash_html) - 12}}; ++ ++#define FS_ROOT file_flash_html ++ ++#define FS_NUMFILES 5 +\ No newline at end of file +--- /dev/null ++++ b/net/uip-0.9/fsdata.h +@@ -0,0 +1,64 @@ ++/* ++ * Copyright (c) 2001, Swedish Institute of Computer Science. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. Neither the name of the Institute nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * This file is part of the lwIP TCP/IP stack. ++ * ++ * Author: Adam Dunkels ++ * ++ * $Id: fsdata.h,v 1.4.2.1 2003/10/04 22:54:06 adam Exp $ ++ */ ++#ifndef __FSDATA_H__ ++#define __FSDATA_H__ ++ ++#include "uipopt.h" ++ ++struct fsdata_file { ++ const struct fsdata_file *next; ++ const char *name; ++ const char *data; ++ const int len; ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++ u16_t count; ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++}; ++ ++struct fsdata_file_noconst { ++ struct fsdata_file *next; ++ char *name; ++ char *data; ++ int len; ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++ u16_t count; ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++}; ++ ++#endif /* __FSDATA_H__ */ +--- /dev/null ++++ b/net/uip-0.9/fs.h +@@ -0,0 +1,80 @@ ++/** ++ * \addtogroup httpd ++ * @{ ++ */ ++ ++/** ++ * \file ++ * HTTP server read-only file system header file. ++ * \author Adam Dunkels ++ */ ++ ++/* ++ * Copyright (c) 2001, Swedish Institute of Computer Science. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. Neither the name of the Institute nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * This file is part of the lwIP TCP/IP stack. ++ * ++ * Author: Adam Dunkels ++ * ++ * $Id: fs.h,v 1.6.2.3 2003/10/07 13:22:27 adam Exp $ ++ */ ++#ifndef __FS_H__ ++#define __FS_H__ ++ ++#include "uip.h" ++ ++/** ++ * An open file in the read-only file system. ++ */ ++struct fs_file { ++ char *data; /**< The actual file data. */ ++ int len; /**< The length of the file data. */ ++}; ++ ++/** ++ * Open a file in the read-only file system. ++ * ++ * \param name The name of the file. ++ * ++ * \param file The file pointer, which must be allocated by caller and ++ * will be filled in by the function. ++ */ ++int fs_open(const char *name, struct fs_file *file); ++ ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++u16_t fs_count(char *name); ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++ ++/** ++ * Initialize the read-only file system. ++ */ ++void fs_init(void); ++ ++#endif /* __FS_H__ */ +--- /dev/null ++++ b/net/uip-0.9/httpd.c +@@ -0,0 +1,278 @@ ++#include "uip.h" ++#include "httpd.h" ++#include "fs.h" ++#include "fsdata.h" ++#include ++ ++#define HTTP_NONE 0 ++#define HTTP_FILE 1 ++#define HTTP_FIRMWARE 2 ++ ++#define PRINT(x) printf("%s", x) ++#define PRINTLN(x) printf("%s\n", x) ++ ++extern unsigned long do_http_tmp_address(void); ++ ++struct httpd_state *hs; ++ ++extern const struct fsdata_file file_index_html; ++extern const struct fsdata_file file_404_html; ++extern const struct fsdata_file file_flash_html; ++extern int httpd_upload_complete; ++extern unsigned char *httpd_upload_data; ++unsigned char *upload_data; ++extern ulong NetBootFileXferSize; ++int upload_running = 0; ++ ++#define ISO_G 0x47 ++#define ISO_E 0x45 ++#define ISO_T 0x54 ++#define ISO_P 0x50 ++#define ISO_O 0x4f ++#define ISO_S 0x53 ++#define ISO_T 0x54 ++#define ISO_slash 0x2f ++#define ISO_c 0x63 ++#define ISO_g 0x67 ++#define ISO_i 0x69 ++#define ISO_space 0x20 ++#define ISO_nl 0x0a ++#define ISO_cr 0x0d ++#define ISO_a 0x61 ++#define ISO_t 0x74 ++#define ISO_hash 0x23 ++#define ISO_period 0x2e ++ ++static char eol[3] = { 0x0d, 0x0a, 0x00 }; ++static char eol2[5] = { 0x0d, 0x0a, 0x0d, 0x0a, 0x00 }; ++static char boundary[128]; ++static int boundary_len = 0; ++ ++/* we use this so that we can do without the ctype library */ ++#define is_digit(c) ((c) >= '0' && (c) <= '9') ++static int atoi(const char *s) ++{ ++ int i=0; ++ ++ while (is_digit(*s)) ++ i = i*10 + *(s++) - '0'; ++ return i; ++} ++ ++void ++httpd_init(void) ++{ ++ fs_init(); ++ uip_listen(HTONS(80)); ++} ++ ++void ++httpd_appcall(void) ++{ ++ struct fs_file fsfile; ++ u8_t i; ++ switch(uip_conn->lport) { ++ case HTONS(80): ++ hs = (struct httpd_state *)(uip_conn->appstate); ++ if(uip_connected()) ++ { ++ hs->state = HTTP_NONE; ++ hs->count = 0; ++ return; ++ } else if(uip_poll()) ++ { ++ if(hs->count++ >= 1000) { ++ uip_abort(); ++ } ++ return; ++ } else if(uip_newdata() && hs->state == HTTP_NONE) ++ { ++ if(uip_appdata[0] == ISO_G && ++ uip_appdata[1] == ISO_E && ++ uip_appdata[2] == ISO_T && ++ uip_appdata[3] == ISO_space) ++ { ++ hs->state = HTTP_FILE; ++ } ++ if(uip_appdata[0] == ISO_P && ++ uip_appdata[1] == ISO_O && ++ uip_appdata[2] == ISO_S && ++ uip_appdata[3] == ISO_T && ++ uip_appdata[4] == ISO_space) ++ { ++ hs->state = HTTP_FIRMWARE; ++ } ++ if(hs->state == HTTP_NONE) ++ { ++ uip_abort(); ++ return; ++ } ++ if(hs->state == HTTP_FILE) ++ { ++ for(i = 4; i < 40; ++i) ++ { ++ if(uip_appdata[i] == ISO_space || ++ uip_appdata[i] == ISO_cr || ++ uip_appdata[i] == ISO_nl) ++ { ++ uip_appdata[i] = 0; ++ break; ++ } ++ } ++ ++ PRINT("request for file "); ++ PRINTLN(&uip_appdata[4]); ++ if(uip_appdata[4] == ISO_slash && ++ uip_appdata[5] == 0) ++ { ++ fs_open(file_index_html.name, &fsfile); ++ } else { ++ if(!fs_open((const char *)&uip_appdata[4], &fsfile)) ++ { ++ PRINTLN("couldn't open file"); ++ fs_open(file_index_html.name, &fsfile); ++ } ++ } ++ hs->script = 0; ++ hs->state = HTTP_FILE; ++ hs->dataptr = fsfile.data; ++ hs->count = fsfile.len; ++ } ++ if(hs->state == HTTP_FIRMWARE) ++ { ++ unsigned char *start = (unsigned char*)uip_appdata; ++ char *clen = strstr(start, "Content-Length:"); ++ int len = 0; ++ unsigned char *next, *end; ++ unsigned char *boundary_start; ++ int i; ++ uip_appdata[uip_len] = '\0'; ++ if(clen) ++ { ++ clen += sizeof("Content-Length:"); ++ next = strstr(clen, eol); ++ if(next) ++ { ++ len = atoi(clen); ++ next++; ++ printf("expecting %d bytes\n", len); ++ upload_data = httpd_upload_data = (unsigned char *)do_http_tmp_address(); ++ printf("received data will be stored at 0x%08X\n", upload_data); ++ if(!upload_data) ++ { ++ printf("failed to allocate memory\n"); ++ uip_close(); ++ return; ++ } ++ } else { ++ uip_close(); ++ return; ++ } ++ } ++ if(len < 4 * 1024) ++ { ++ uip_close(); ++ return; ++ } ++ boundary_start = strstr(next, "---"); ++ if(!boundary_start) ++ { ++ uip_close(); ++ return; ++ } ++ end = strstr(boundary_start, eol); ++ if(!eol) ++ { ++ uip_close(); ++ return; ++ } ++ boundary_len = end - boundary_start; ++ memcpy(boundary, boundary_start, boundary_len); ++ boundary[boundary_len] = 0; ++ next = strstr(boundary_start, "name=\"firmware\";"); ++ if(!next) ++ { ++ uip_close(); ++ return; ++ } ++ next = strstr(next, eol2); ++ if(!next) ++ { ++ printf("could not find start of data\n"); ++ uip_close(); ++ return; ++ } ++ next += 4; ++ hs->script = 0; ++ hs->state = HTTP_FIRMWARE; ++ hs->upload = uip_len - (next - start); ++ hs->upload_total = len - (int)(next - boundary_start); ++ hs->upload_total -= (strlen(boundary) + 6); ++ //printf("storing %d bytes at %p\n", (int)hs->upload, upload_data); ++ for(i = 0; i < hs->upload; i++) ++ upload_data[i] = next[i]; ++ upload_data += (int)hs->upload; ++ printf("%d / %d\n", (int)hs->upload, hs->upload_total); ++ uip_slen = 0; ++ return; ++ } ++ } ++ ++ if(hs->state == HTTP_FIRMWARE) ++ { ++ if(uip_newdata()) ++ { ++ int i; ++ hs->count = 0; ++ uip_appdata[uip_len] = '\0'; ++ hs->upload += uip_len; ++ //printf("storing %d bytes at %p\n", uip_len, upload_data); ++ printf("%d / %d\n", (int)hs->upload, hs->upload_total); ++ for(i = 0; i < uip_len; i++) ++ upload_data[i] = uip_appdata[i]; ++ upload_data += uip_len; ++ uip_slen = 0; ++ if(hs->upload >= hs->upload_total) ++ { ++ upload_running = 1; ++ NetBootFileXferSize = hs->upload_total; ++ fs_open(file_flash_html.name, &fsfile); ++ hs->script = 0; ++ hs->state = HTTP_FILE; ++ hs->dataptr = fsfile.data; ++ hs->count = fsfile.len; ++ } ++ } ++ } ++ if(hs->state == HTTP_FILE) ++ { ++ if(uip_acked()) ++ { ++ if(hs->count >= uip_conn->len) ++ { ++ hs->count -= uip_conn->len; ++ hs->dataptr += uip_conn->len; ++ } else { ++ hs->count = 0; ++ } ++ if(hs->count == 0) ++ { ++ if(upload_running) ++ { ++ int i; ++ httpd_upload_complete = 1; ++ // for(i = 0; i < hs->upload_total; i++) ++ // printf("%c", httpd_upload_data[i]); ++ } ++ uip_close(); ++ } ++ } ++ uip_send(hs->dataptr, hs->count); ++ } ++ break; ++ ++ default: ++ uip_abort(); ++ break; ++ } ++} +--- /dev/null ++++ b/net/uip-0.9/httpd.h +@@ -0,0 +1,83 @@ ++/** ++ * \addtogroup httpd ++ * @{ ++ */ ++ ++/** ++ * \file ++ * HTTP server header file. ++ * \author Adam Dunkels ++ */ ++ ++/* ++ * Copyright (c) 2001, Adam Dunkels. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: httpd.h,v 1.4.2.3 2003/10/06 22:56:44 adam Exp $ ++ * ++ */ ++ ++#ifndef __HTTPD_H__ ++#define __HTTPD_H__ ++ ++void httpd_init(void); ++void httpd_appcall(void); ++ ++/* UIP_APPCALL: the name of the application function. This function ++ must return void and take no arguments (i.e., C type "void ++ appfunc(void)"). */ ++#ifndef UIP_APPCALL ++#define UIP_APPCALL httpd_appcall ++#endif ++ ++struct httpd_state { ++ u8_t state; ++ u16_t count; ++ char *dataptr; ++ char *script; ++ unsigned int upload; ++ unsigned int upload_total; ++}; ++ ++ ++/* UIP_APPSTATE_SIZE: The size of the application-specific state ++ stored in the uip_conn structure. */ ++#ifndef UIP_APPSTATE_SIZE ++#define UIP_APPSTATE_SIZE (sizeof(struct httpd_state)) ++#endif ++ ++#define FS_STATISTICS 1 ++ ++extern struct httpd_state *hs; ++ ++ ++/* we copy the data to RAM+10MB */ ++#define TMP_DATA 0x8A100000 ++ ++#endif /* __HTTPD_H__ */ +--- /dev/null ++++ b/net/uip-0.9/main.c +@@ -0,0 +1,88 @@ ++/* ++ * Copyright (c) 2001-2003, Adam Dunkels. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: main.c,v 1.10.2.1 2003/10/04 22:54:17 adam Exp $ ++ * ++ */ ++ ++ ++#include "uip.h" ++#include "uip_arp.h" ++#include "tapdev.h" ++#include "httpd.h" ++ ++#define BUF ((struct uip_eth_hdr *)&uip_buf[0]) ++ ++#ifndef NULL ++#define NULL (void *)0 ++#endif /* NULL */ ++ ++/*-----------------------------------------------------------------------------------*/ ++int ++main(void) ++{ ++ u8_t i, arptimer; ++ tapdev_init(); ++ uip_init(); ++ httpd_init(); ++ arptimer = 0; ++ while(1) { ++ uip_len = tapdev_read(); ++ if(uip_len == 0) { ++ for(i = 0; i < UIP_CONNS; i++) { ++ uip_periodic(i); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ tapdev_send(); ++ } ++ } ++ ++ if(++arptimer == 20) { ++ uip_arp_timer(); ++ arptimer = 0; ++ } ++ } else { ++ if(BUF->type == htons(UIP_ETHTYPE_IP)) { ++ uip_arp_ipin(); ++ uip_input(); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ tapdev_send(); ++ } ++ } else if(BUF->type == htons(UIP_ETHTYPE_ARP)) { ++ uip_arp_arpin(); ++ if(uip_len > 0) { ++ tapdev_send(); ++ } ++ } ++ } ++ } ++ return 0; ++} +--- /dev/null ++++ b/net/uip-0.9/Makefile +@@ -0,0 +1,54 @@ ++# Copyright (c) 2001, Adam Dunkels. ++# All rights reserved. ++# ++# Redistribution and use in source and binary forms, with or without ++# modification, are permitted provided that the following conditions ++# are met: ++# 1. Redistributions of source code must retain the above copyright ++# notice, this list of conditions and the following disclaimer. ++# 2. Redistributions in binary form must reproduce the above copyright ++# notice, this list of conditions and the following disclaimer in the ++# documentation and/or other materials provided with the distribution. ++# 3. All advertising materials mentioning features or use of this software ++# must display the following acknowledgement: ++# This product includes software developed by Adam Dunkels. ++# 4. The name of the author may not be used to endorse or promote ++# products derived from this software without specific prior ++# written permission. ++# ++# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ++# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ++# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++# ++# This file is part of the uIP TCP/IP stack. ++# ++# $Id: Makefile,v 1.8.2.2 2003/10/04 22:54:17 adam Exp $ ++# ++ ++CC=gcc ++CFLAGS=-Wall -fpack-struct -DDUMP=0 ++ ++all: uip ++ ++uip: uip.o uip_arch.o tapdev.o httpd.o main.o fs.o uip_arp.o ++ $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ ++ ++%.o: %.c ++ $(CC) $(CFLAGS) -c $^ -o $@ ++ ++clean: ++ rm -f *.o *~ *core uip ++ ++ ++ ++ ++ ++ +--- /dev/null ++++ b/net/uip-0.9/tapdev.c +@@ -0,0 +1,192 @@ ++/* ++ * Copyright (c) 2001, Swedish Institute of Computer Science. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * 3. Neither the name of the Institute nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * Author: Adam Dunkels ++ * ++ * $Id: tapdev.c,v 1.7.2.1 2003/10/07 13:23:19 adam Exp $ ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef linux ++#include ++#include ++#include ++#define DEVTAP "/dev/net/tun" ++#else /* linux */ ++#define DEVTAP "/dev/tap0" ++#endif /* linux */ ++ ++#include "uip.h" ++ ++static int fd; ++ ++static unsigned long lasttime; ++static struct timezone tz; ++ ++/*-----------------------------------------------------------------------------------*/ ++void ++tapdev_init(void) ++{ ++ char buf[1024]; ++ ++ fd = open(DEVTAP, O_RDWR); ++ if(fd == -1) { ++ perror("tapdev: tapdev_init: open"); ++ exit(1); ++ } ++ ++#ifdef linux ++ { ++ struct ifreq ifr; ++ memset(&ifr, 0, sizeof(ifr)); ++ ifr.ifr_flags = IFF_TAP|IFF_NO_PI; ++ if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) { ++ perror(buf); ++ exit(1); ++ } ++ } ++#endif /* Linux */ ++ ++ snprintf(buf, sizeof(buf), "ifconfig tap0 inet %d.%d.%d.%d", ++ UIP_DRIPADDR0, UIP_DRIPADDR1, UIP_DRIPADDR2, UIP_DRIPADDR3); ++ system(buf); ++ ++ lasttime = 0; ++} ++ ++void dump_mem(int type, int len) ++{ ++#if DUMP == 1 ++ int i; ++ for(i = 0; i < len; i++) ++ printf("%c", uip_buf[i]); ++ if(type) ++ { ++ printf("\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"); ++ printf("\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"); ++ } else { ++ printf("\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02"); ++ printf("\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02"); ++ } ++ fflush(stdout); ++#endif ++} ++ ++/*-----------------------------------------------------------------------------------*/ ++unsigned int ++tapdev_read(void) ++{ ++ fd_set fdset; ++ struct timeval tv, now; ++ int ret; ++ ++ if(lasttime >= 500000) { ++ lasttime = 0; ++ return 0; ++ } ++ ++ tv.tv_sec = 0; ++ tv.tv_usec = 500000 - lasttime; ++ ++ ++ FD_ZERO(&fdset); ++ FD_SET(fd, &fdset); ++ ++ gettimeofday(&now, &tz); ++ ret = select(fd + 1, &fdset, NULL, NULL, &tv); ++ if(ret == 0) { ++ lasttime = 0; ++ return 0; ++ } ++ ret = read(fd, uip_buf, UIP_BUFSIZE); ++ if(ret == -1) { ++ perror("tap_dev: tapdev_read: read"); ++ } ++ gettimeofday(&tv, &tz); ++ lasttime += (tv.tv_sec - now.tv_sec) * 1000000 + (tv.tv_usec - now.tv_usec); ++ dump_mem(0, ret); ++ return ret; ++} ++/*-----------------------------------------------------------------------------------*/ ++void ++tapdev_send(void) ++{ ++ int ret; ++ struct iovec iov[2]; ++ ++#ifdef linux ++ { ++ char tmpbuf[UIP_BUFSIZE]; ++ int i; ++ ++ for(i = 0; i < 40 + UIP_LLH_LEN; i++) { ++ tmpbuf[i] = uip_buf[i]; ++ } ++ ++ for(; i < uip_len; i++) { ++ tmpbuf[i] = uip_appdata[i - 40 - UIP_LLH_LEN]; ++ } ++ ++ ret = write(fd, tmpbuf, uip_len); ++ } ++#else ++ ++ if(uip_len < 40 + UIP_LLH_LEN) { ++ ret = write(fd, uip_buf, uip_len + UIP_LLH_LEN); ++ } else { ++ iov[0].iov_base = uip_buf; ++ iov[0].iov_len = 40 + UIP_LLH_LEN; ++ iov[1].iov_base = (char *)uip_appdata; ++ iov[1].iov_len = uip_len - (40 + UIP_LLH_LEN); ++ ++ ret = writev(fd, iov, 2); ++ } ++#endif ++ dump_mem(1, ret); ++ ++ if(ret == -1) { ++ perror("tap_dev: tapdev_send: writev"); ++ exit(1); ++ } ++} ++/*-----------------------------------------------------------------------------------*/ +--- /dev/null ++++ b/net/uip-0.9/tapdev.h +@@ -0,0 +1,42 @@ ++/* ++ * Copyright (c) 2001, Adam Dunkels. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: tapdev.h,v 1.1.2.1 2003/10/04 22:54:17 adam Exp $ ++ * ++ */ ++ ++#ifndef __TAPDEV_H__ ++#define __TAPDEV_H__ ++ ++void tapdev_init(void); ++unsigned int tapdev_read(void); ++void tapdev_send(void); ++ ++#endif /* __TAPDEV_H__ */ +--- /dev/null ++++ b/net/uip-0.9/uip_arch.c +@@ -0,0 +1,145 @@ ++/* ++ * Copyright (c) 2001, Adam Dunkels. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: uip_arch.c,v 1.2.2.1 2003/10/04 22:54:17 adam Exp $ ++ * ++ */ ++ ++ ++#include "uip.h" ++#include "uip_arch.h" ++ ++#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) ++#define IP_PROTO_TCP 6 ++ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_add32(u8_t *op32, u16_t op16) ++{ ++ ++ uip_acc32[3] = op32[3] + (op16 & 0xff); ++ uip_acc32[2] = op32[2] + (op16 >> 8); ++ uip_acc32[1] = op32[1]; ++ uip_acc32[0] = op32[0]; ++ ++ if(uip_acc32[2] < (op16 >> 8)) { ++ ++uip_acc32[1]; ++ if(uip_acc32[1] == 0) { ++ ++uip_acc32[0]; ++ } ++ } ++ ++ ++ if(uip_acc32[3] < (op16 & 0xff)) { ++ ++uip_acc32[2]; ++ if(uip_acc32[2] == 0) { ++ ++uip_acc32[1]; ++ if(uip_acc32[1] == 0) { ++ ++uip_acc32[0]; ++ } ++ } ++ } ++} ++/*-----------------------------------------------------------------------------------*/ ++u16_t ++uip_chksum(u16_t *sdata, u16_t len) ++{ ++ u16_t acc; ++ ++ for(acc = 0; len > 1; len -= 2) { ++ acc += *sdata; ++ if(acc < *sdata) { ++ /* Overflow, so we add the carry to acc (i.e., increase by ++ one). */ ++ ++acc; ++ } ++ ++sdata; ++ } ++ ++ /* add up any odd byte */ ++ if(len == 1) { ++ acc += htons(((u16_t)(*(u8_t *)sdata)) << 8); ++ if(acc < htons(((u16_t)(*(u8_t *)sdata)) << 8)) { ++ ++acc; ++ } ++ } ++ ++ return acc; ++} ++/*-----------------------------------------------------------------------------------*/ ++u16_t ++uip_ipchksum(void) ++{ ++ return uip_chksum((u16_t *)&uip_buf[UIP_LLH_LEN], 20); ++} ++/*-----------------------------------------------------------------------------------*/ ++u16_t ++uip_tcpchksum(void) ++{ ++ u16_t hsum, sum; ++ ++ ++ /* Compute the checksum of the TCP header. */ ++ hsum = uip_chksum((u16_t *)&uip_buf[20 + UIP_LLH_LEN], 20); ++ ++ /* Compute the checksum of the data in the TCP packet and add it to ++ the TCP header checksum. */ ++ sum = uip_chksum((u16_t *)uip_appdata, ++ (u16_t)(((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 40))); ++ ++ if((sum += hsum) < hsum) { ++ ++sum; ++ } ++ ++ if((sum += BUF->srcipaddr[0]) < BUF->srcipaddr[0]) { ++ ++sum; ++ } ++ if((sum += BUF->srcipaddr[1]) < BUF->srcipaddr[1]) { ++ ++sum; ++ } ++ if((sum += BUF->destipaddr[0]) < BUF->destipaddr[0]) { ++ ++sum; ++ } ++ if((sum += BUF->destipaddr[1]) < BUF->destipaddr[1]) { ++ ++sum; ++ } ++ if((sum += (u16_t)htons((u16_t)IP_PROTO_TCP)) < (u16_t)htons((u16_t)IP_PROTO_TCP)) { ++ ++sum; ++ } ++ ++ hsum = (u16_t)htons((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 20); ++ ++ if((sum += hsum) < hsum) { ++ ++sum; ++ } ++ ++ return sum; ++} ++/*-----------------------------------------------------------------------------------*/ +--- /dev/null ++++ b/net/uip-0.9/uip_arch.h +@@ -0,0 +1,130 @@ ++/** ++ * \defgroup uiparch Architecture specific uIP functions ++ * @{ ++ * ++ * The functions in the architecture specific module implement the IP ++ * check sum and 32-bit additions. ++ * ++ * The IP checksum calculation is the most computationally expensive ++ * operation in the TCP/IP stack and it therefore pays off to ++ * implement this in efficient assembler. The purpose of the uip-arch ++ * module is to let the checksum functions to be implemented in ++ * architecture specific assembler. ++ * ++ */ ++ ++/** ++ * \file ++ * Declarations of architecture specific functions. ++ * \author Adam Dunkels ++ */ ++ ++/* ++ * Copyright (c) 2001, Adam Dunkels. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: uip_arch.h,v 1.1.2.2 2003/10/06 15:10:22 adam Exp $ ++ * ++ */ ++ ++#ifndef __UIP_ARCH_H__ ++#define __UIP_ARCH_H__ ++ ++#include "uip.h" ++ ++/** ++ * Carry out a 32-bit addition. ++ * ++ * Because not all architectures for which uIP is intended has native ++ * 32-bit arithmetic, uIP uses an external C function for doing the ++ * required 32-bit additions in the TCP protocol processing. This ++ * function should add the two arguments and place the result in the ++ * global variable uip_acc32. ++ * ++ * \note The 32-bit integer pointed to by the op32 parameter and the ++ * result in the uip_acc32 variable are in network byte order (big ++ * endian). ++ * ++ * \param op32 A pointer to a 4-byte array representing a 32-bit ++ * integer in network byte order (big endian). ++ * ++ * \param op16 A 16-bit integer in host byte order. ++ */ ++void uip_add32(u8_t *op32, u16_t op16); ++ ++/** ++ * Calculate the Internet checksum over a buffer. ++ * ++ * The Internet checksum is the one's complement of the one's ++ * complement sum of all 16-bit words in the buffer. ++ * ++ * See RFC1071. ++ * ++ * \note This function is not called in the current version of uIP, ++ * but future versions might make use of it. ++ * ++ * \param buf A pointer to the buffer over which the checksum is to be ++ * computed. ++ * ++ * \param len The length of the buffer over which the checksum is to ++ * be computed. ++ * ++ * \return The Internet checksum of the buffer. ++ */ ++u16_t uip_chksum(u16_t *buf, u16_t len); ++ ++/** ++ * Calculate the IP header checksum of the packet header in uip_buf. ++ * ++ * The IP header checksum is the Internet checksum of the 20 bytes of ++ * the IP header. ++ * ++ * \return The IP header checksum of the IP header in the uip_buf ++ * buffer. ++ */ ++u16_t uip_ipchksum(void); ++ ++/** ++ * Calculate the TCP checksum of the packet in uip_buf and uip_appdata. ++ * ++ * The TCP checksum is the Internet checksum of data contents of the ++ * TCP segment, and a pseudo-header as defined in RFC793. ++ * ++ * \note The uip_appdata pointer that points to the packet data may ++ * point anywhere in memory, so it is not possible to simply calculate ++ * the Internet checksum of the contents of the uip_buf buffer. ++ * ++ * \return The TCP checksum of the TCP segment in uip_buf and pointed ++ * to by uip_appdata. ++ */ ++u16_t uip_tcpchksum(void); ++ ++/** @} */ ++ ++#endif /* __UIP_ARCH_H__ */ +--- /dev/null ++++ b/net/uip-0.9/uip_arp.c +@@ -0,0 +1,421 @@ ++/** ++ * \addtogroup uip ++ * @{ ++ */ ++ ++/** ++ * \defgroup uiparp uIP Address Resolution Protocol ++ * @{ ++ * ++ * The Address Resolution Protocol ARP is used for mapping between IP ++ * addresses and link level addresses such as the Ethernet MAC ++ * addresses. ARP uses broadcast queries to ask for the link level ++ * address of a known IP address and the host which is configured with ++ * the IP address for which the query was meant, will respond with its ++ * link level address. ++ * ++ * \note This ARP implementation only supports Ethernet. ++ */ ++ ++/** ++ * \file ++ * Implementation of the ARP Address Resolution Protocol. ++ * \author Adam Dunkels ++ * ++ */ ++ ++/* ++ * Copyright (c) 2001-2003, Adam Dunkels. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: uip_arp.c,v 1.7.2.3 2003/10/06 22:42:30 adam Exp $ ++ * ++ */ ++ ++ ++#include "uip_arp.h" ++ ++struct arp_hdr { ++ struct uip_eth_hdr ethhdr; ++ u16_t hwtype; ++ u16_t protocol; ++ u8_t hwlen; ++ u8_t protolen; ++ u16_t opcode; ++ struct uip_eth_addr shwaddr; ++ u16_t sipaddr[2]; ++ struct uip_eth_addr dhwaddr; ++ u16_t dipaddr[2]; ++}; ++ ++struct ethip_hdr { ++ struct uip_eth_hdr ethhdr; ++ /* IP header. */ ++ u8_t vhl, ++ tos, ++ len[2], ++ ipid[2], ++ ipoffset[2], ++ ttl, ++ proto; ++ u16_t ipchksum; ++ u16_t srcipaddr[2], ++ destipaddr[2]; ++}; ++ ++#define ARP_REQUEST 1 ++#define ARP_REPLY 2 ++ ++#define ARP_HWTYPE_ETH 1 ++ ++struct arp_entry { ++ u16_t ipaddr[2]; ++ struct uip_eth_addr ethaddr; ++ u8_t time; ++}; ++ ++struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0, ++ UIP_ETHADDR1, ++ UIP_ETHADDR2, ++ UIP_ETHADDR3, ++ UIP_ETHADDR4, ++ UIP_ETHADDR5}}; ++ ++static struct arp_entry arp_table[UIP_ARPTAB_SIZE]; ++static u16_t ipaddr[2]; ++static u8_t i, c; ++ ++static u8_t arptime; ++static u8_t tmpage; ++ ++#define BUF ((struct arp_hdr *)&uip_buf[0]) ++#define IPBUF ((struct ethip_hdr *)&uip_buf[0]) ++/*-----------------------------------------------------------------------------------*/ ++/** ++ * Initialize the ARP module. ++ * ++ */ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_arp_init(void) ++{ ++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { ++ memset(arp_table[i].ipaddr, 0, 4); ++ } ++} ++/*-----------------------------------------------------------------------------------*/ ++/** ++ * Periodic ARP processing function. ++ * ++ * This function performs periodic timer processing in the ARP module ++ * and should be called at regular intervals. The recommended interval ++ * is 10 seconds between the calls. ++ * ++ */ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_arp_timer(void) ++{ ++ struct arp_entry *tabptr; ++ ++ ++arptime; ++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { ++ tabptr = &arp_table[i]; ++ if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 && ++ arptime - tabptr->time >= UIP_ARP_MAXAGE) { ++ memset(tabptr->ipaddr, 0, 4); ++ } ++ } ++ ++} ++/*-----------------------------------------------------------------------------------*/ ++static void ++uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr) ++{ ++ register struct arp_entry *tabptr; ++ /* Walk through the ARP mapping table and try to find an entry to ++ update. If none is found, the IP -> MAC address mapping is ++ inserted in the ARP table. */ ++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { ++ ++ tabptr = &arp_table[i]; ++ /* Only check those entries that are actually in use. */ ++ if(tabptr->ipaddr[0] != 0 && ++ tabptr->ipaddr[1] != 0) { ++ ++ /* Check if the source IP address of the incoming packet matches ++ the IP address in this ARP table entry. */ ++ if(ipaddr[0] == tabptr->ipaddr[0] && ++ ipaddr[1] == tabptr->ipaddr[1]) { ++ ++ /* An old entry found, update this and return. */ ++ memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); ++ tabptr->time = arptime; ++ ++ return; ++ } ++ } ++ } ++ ++ /* If we get here, no existing ARP table entry was found, so we ++ create one. */ ++ ++ /* First, we try to find an unused entry in the ARP table. */ ++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { ++ tabptr = &arp_table[i]; ++ if(tabptr->ipaddr[0] == 0 && ++ tabptr->ipaddr[1] == 0) { ++ break; ++ } ++ } ++ ++ /* If no unused entry is found, we try to find the oldest entry and ++ throw it away. */ ++ if(i == UIP_ARPTAB_SIZE) { ++ tmpage = 0; ++ c = 0; ++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { ++ tabptr = &arp_table[i]; ++ if(arptime - tabptr->time > tmpage) { ++ tmpage = arptime - tabptr->time; ++ c = i; ++ } ++ } ++ i = c; ++ } ++ ++ /* Now, i is the ARP table entry which we will fill with the new ++ information. */ ++ memcpy(tabptr->ipaddr, ipaddr, 4); ++ memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); ++ tabptr->time = arptime; ++} ++/*-----------------------------------------------------------------------------------*/ ++/** ++ * ARP processing for incoming IP packets ++ * ++ * This function should be called by the device driver when an IP ++ * packet has been received. The function will check if the address is ++ * in the ARP cache, and if so the ARP cache entry will be ++ * refreshed. If no ARP cache entry was found, a new one is created. ++ * ++ * This function expects an IP packet with a prepended Ethernet header ++ * in the uip_buf[] buffer, and the length of the packet in the global ++ * variable uip_len. ++ */ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_arp_ipin(void) ++{ ++ uip_len -= sizeof(struct uip_eth_hdr); ++ ++ /* Only insert/update an entry if the source IP address of the ++ incoming IP packet comes from a host on the local network. */ ++ if((IPBUF->srcipaddr[0] & uip_arp_netmask[0]) != ++ (uip_hostaddr[0] & uip_arp_netmask[0])) { ++ return; ++ } ++ if((IPBUF->srcipaddr[1] & uip_arp_netmask[1]) != ++ (uip_hostaddr[1] & uip_arp_netmask[1])) { ++ return; ++ } ++ uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src)); ++ ++ return; ++} ++/*-----------------------------------------------------------------------------------*/ ++/** ++ * ARP processing for incoming ARP packets. ++ * ++ * This function should be called by the device driver when an ARP ++ * packet has been received. The function will act differently ++ * depending on the ARP packet type: if it is a reply for a request ++ * that we previously sent out, the ARP cache will be filled in with ++ * the values from the ARP reply. If the incoming ARP packet is an ARP ++ * request for our IP address, an ARP reply packet is created and put ++ * into the uip_buf[] buffer. ++ * ++ * When the function returns, the value of the global variable uip_len ++ * indicates whether the device driver should send out a packet or ++ * not. If uip_len is zero, no packet should be sent. If uip_len is ++ * non-zero, it contains the length of the outbound packet that is ++ * present in the uip_buf[] buffer. ++ * ++ * This function expects an ARP packet with a prepended Ethernet ++ * header in the uip_buf[] buffer, and the length of the packet in the ++ * global variable uip_len. ++ */ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_arp_arpin(void) ++{ ++ ++ if(uip_len < sizeof(struct arp_hdr)) { ++ uip_len = 0; ++ return; ++ } ++ ++ uip_len = 0; ++ ++ switch(BUF->opcode) { ++ case HTONS(ARP_REQUEST): ++ /* ARP request. If it asked for our address, we send out a ++ reply. */ ++ if(BUF->dipaddr[0] == uip_hostaddr[0] && ++ BUF->dipaddr[1] == uip_hostaddr[1]) { ++ /* The reply opcode is 2. */ ++ BUF->opcode = HTONS(2); ++ ++ memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6); ++ memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); ++ memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); ++ memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6); ++ ++ BUF->dipaddr[0] = BUF->sipaddr[0]; ++ BUF->dipaddr[1] = BUF->sipaddr[1]; ++ BUF->sipaddr[0] = uip_hostaddr[0]; ++ BUF->sipaddr[1] = uip_hostaddr[1]; ++ ++ BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); ++ uip_len = sizeof(struct arp_hdr); ++ } ++ break; ++ case HTONS(ARP_REPLY): ++ /* ARP reply. We insert or update the ARP table if it was meant ++ for us. */ ++ if(BUF->dipaddr[0] == uip_hostaddr[0] && ++ BUF->dipaddr[1] == uip_hostaddr[1]) { ++ ++ uip_arp_update(BUF->sipaddr, &BUF->shwaddr); ++ } ++ break; ++ } ++ ++ return; ++} ++/*-----------------------------------------------------------------------------------*/ ++/** ++ * Prepend Ethernet header to an outbound IP packet and see if we need ++ * to send out an ARP request. ++ * ++ * This function should be called before sending out an IP packet. The ++ * function checks the destination IP address of the IP packet to see ++ * what Ethernet MAC address that should be used as a destination MAC ++ * address on the Ethernet. ++ * ++ * If the destination IP address is in the local network (determined ++ * by logical ANDing of netmask and our IP address), the function ++ * checks the ARP cache to see if an entry for the destination IP ++ * address is found. If so, an Ethernet header is prepended and the ++ * function returns. If no ARP cache entry is found for the ++ * destination IP address, the packet in the uip_buf[] is replaced by ++ * an ARP request packet for the IP address. The IP packet is dropped ++ * and it is assumed that they higher level protocols (e.g., TCP) ++ * eventually will retransmit the dropped packet. ++ * ++ * If the destination IP address is not on the local network, the IP ++ * address of the default router is used instead. ++ * ++ * When the function returns, a packet is present in the uip_buf[] ++ * buffer, and the length of the packet is in the global variable ++ * uip_len. ++ */ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_arp_out(void) ++{ ++ struct arp_entry *tabptr; ++ /* Find the destination IP address in the ARP table and construct ++ the Ethernet header. If the destination IP addres isn't on the ++ local network, we use the default router's IP address instead. ++ ++ If not ARP table entry is found, we overwrite the original IP ++ packet with an ARP request for the IP address. */ ++ ++ /* Check if the destination address is on the local network. */ ++ if((IPBUF->destipaddr[0] & uip_arp_netmask[0]) != ++ (uip_hostaddr[0] & uip_arp_netmask[0]) || ++ (IPBUF->destipaddr[1] & uip_arp_netmask[1]) != ++ (uip_hostaddr[1] & uip_arp_netmask[1])) { ++ /* Destination address was not on the local network, so we need to ++ use the default router's IP address instead of the destination ++ address when determining the MAC address. */ ++ ipaddr[0] = uip_arp_draddr[0]; ++ ipaddr[1] = uip_arp_draddr[1]; ++ } else { ++ /* Else, we use the destination IP address. */ ++ ipaddr[0] = IPBUF->destipaddr[0]; ++ ipaddr[1] = IPBUF->destipaddr[1]; ++ } ++ ++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { ++ tabptr = &arp_table[i]; ++ if(ipaddr[0] == tabptr->ipaddr[0] && ++ ipaddr[1] == tabptr->ipaddr[1]) ++ break; ++ } ++ ++ if(i == UIP_ARPTAB_SIZE) { ++ /* The destination address was not in our ARP table, so we ++ overwrite the IP packet with an ARP request. */ ++ ++ memset(BUF->ethhdr.dest.addr, 0xff, 6); ++ memset(BUF->dhwaddr.addr, 0x00, 6); ++ memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); ++ memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); ++ ++ BUF->dipaddr[0] = ipaddr[0]; ++ BUF->dipaddr[1] = ipaddr[1]; ++ BUF->sipaddr[0] = uip_hostaddr[0]; ++ BUF->sipaddr[1] = uip_hostaddr[1]; ++ BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */ ++ BUF->hwtype = HTONS(ARP_HWTYPE_ETH); ++ BUF->protocol = HTONS(UIP_ETHTYPE_IP); ++ BUF->hwlen = 6; ++ BUF->protolen = 4; ++ BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); ++ ++ uip_appdata = &uip_buf[40 + UIP_LLH_LEN]; ++ ++ uip_len = sizeof(struct arp_hdr); ++ return; ++ } ++ ++ /* Build an ethernet header. */ ++ memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6); ++ memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6); ++ ++ IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP); ++ ++ uip_len += sizeof(struct uip_eth_hdr); ++} ++/*-----------------------------------------------------------------------------------*/ ++ ++/** @} */ ++/** @} */ +--- /dev/null ++++ b/net/uip-0.9/uip_arp.h +@@ -0,0 +1,201 @@ ++/** ++ * \addtogroup uip ++ * @{ ++ */ ++ ++/** ++ * \addtogroup uiparp ++ * @{ ++ */ ++ ++/** ++ * \file ++ * Macros and definitions for the ARP module. ++ * \author Adam Dunkels ++ */ ++ ++ ++/* ++ * Copyright (c) 2001-2003, Adam Dunkels. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: uip_arp.h,v 1.3.2.2 2003/10/06 15:10:22 adam Exp $ ++ * ++ */ ++ ++#ifndef __UIP_ARP_H__ ++#define __UIP_ARP_H__ ++ ++#include "uip.h" ++ ++ ++/** ++ * Representation of a 48-bit Ethernet address. ++ */ ++struct uip_eth_addr { ++ u8_t addr[6]; ++}; ++ ++extern struct uip_eth_addr uip_ethaddr; ++ ++/** ++ * The Ethernet header. ++ */ ++struct uip_eth_hdr { ++ struct uip_eth_addr dest; ++ struct uip_eth_addr src; ++ u16_t type; ++}; ++ ++#define UIP_ETHTYPE_ARP 0x0806 ++#define UIP_ETHTYPE_IP 0x0800 ++#define UIP_ETHTYPE_IP6 0x86dd ++ ++ ++/* The uip_arp_init() function must be called before any of the other ++ ARP functions. */ ++void uip_arp_init(void); ++ ++/* The uip_arp_ipin() function should be called whenever an IP packet ++ arrives from the Ethernet. This function refreshes the ARP table or ++ inserts a new mapping if none exists. The function assumes that an ++ IP packet with an Ethernet header is present in the uip_buf buffer ++ and that the length of the packet is in the uip_len variable. */ ++void uip_arp_ipin(void); ++ ++/* The uip_arp_arpin() should be called when an ARP packet is received ++ by the Ethernet driver. This function also assumes that the ++ Ethernet frame is present in the uip_buf buffer. When the ++ uip_arp_arpin() function returns, the contents of the uip_buf ++ buffer should be sent out on the Ethernet if the uip_len variable ++ is > 0. */ ++void uip_arp_arpin(void); ++ ++/* The uip_arp_out() function should be called when an IP packet ++ should be sent out on the Ethernet. This function creates an ++ Ethernet header before the IP header in the uip_buf buffer. The ++ Ethernet header will have the correct Ethernet MAC destination ++ address filled in if an ARP table entry for the destination IP ++ address (or the IP address of the default router) is present. If no ++ such table entry is found, the IP packet is overwritten with an ARP ++ request and we rely on TCP to retransmit the packet that was ++ overwritten. In any case, the uip_len variable holds the length of ++ the Ethernet frame that should be transmitted. */ ++void uip_arp_out(void); ++ ++/* The uip_arp_timer() function should be called every ten seconds. It ++ is responsible for flushing old entries in the ARP table. */ ++void uip_arp_timer(void); ++ ++/** @} */ ++ ++/** ++ * \addtogroup uipconffunc ++ * @{ ++ */ ++ ++/** ++ * Set the default router's IP address. ++ * ++ * \param addr A pointer to a 4-byte array containing the IP address ++ * of the default router. ++ * ++ * \hideinitializer ++ */ ++#define uip_setdraddr(addr) do { uip_arp_draddr[0] = addr[0]; \ ++ uip_arp_draddr[1] = addr[1]; } while(0) ++ ++/** ++ * Set the netmask. ++ * ++ * \param addr A pointer to a 4-byte array containing the IP address ++ * of the netmask. ++ * ++ * \hideinitializer ++ */ ++#define uip_setnetmask(addr) do { uip_arp_netmask[0] = addr[0]; \ ++ uip_arp_netmask[1] = addr[1]; } while(0) ++ ++ ++/** ++ * Get the default router's IP address. ++ * ++ * \param addr A pointer to a 4-byte array that will be filled in with ++ * the IP address of the default router. ++ * ++ * \hideinitializer ++ */ ++#define uip_getdraddr(addr) do { addr[0] = uip_arp_draddr[0]; \ ++ addr[1] = uip_arp_draddr[1]; } while(0) ++ ++/** ++ * Get the netmask. ++ * ++ * \param addr A pointer to a 4-byte array that will be filled in with ++ * the value of the netmask. ++ * ++ * \hideinitializer ++ */ ++#define uip_getnetmask(addr) do { addr[0] = uip_arp_netmask[0]; \ ++ addr[1] = uip_arp_netmask[1]; } while(0) ++ ++ ++/** ++ * Specifiy the Ethernet MAC address. ++ * ++ * The ARP code needs to know the MAC address of the Ethernet card in ++ * order to be able to respond to ARP queries and to generate working ++ * Ethernet headers. ++ * ++ * \note This macro only specifies the Ethernet MAC address to the ARP ++ * code. It cannot be used to change the MAC address of the Ethernet ++ * card. ++ * ++ * \param eaddr A pointer to a struct uip_eth_addr containing the ++ * Ethernet MAC address of the Ethernet card. ++ * ++ * \hideinitializer ++ */ ++#define uip_setethaddr(eaddr) do {uip_ethaddr.addr[0] = eaddr.addr[0]; \ ++ uip_ethaddr.addr[1] = eaddr.addr[1];\ ++ uip_ethaddr.addr[2] = eaddr.addr[2];\ ++ uip_ethaddr.addr[3] = eaddr.addr[3];\ ++ uip_ethaddr.addr[4] = eaddr.addr[4];\ ++ uip_ethaddr.addr[5] = eaddr.addr[5];} while(0) ++ ++/** @} */ ++ ++/** ++ * \internal Internal variables that are set using the macros ++ * uip_setdraddr and uip_setnetmask. ++ */ ++extern u16_t uip_arp_draddr[2], uip_arp_netmask[2]; ++#endif /* __UIP_ARP_H__ */ ++ ++ +--- /dev/null ++++ b/net/uip-0.9/uip.c +@@ -0,0 +1,1503 @@ ++/** ++ * \addtogroup uip ++ * @{ ++ */ ++ ++/** ++ * \file ++ * The uIP TCP/IP stack code. ++ * \author Adam Dunkels ++ */ ++ ++/* ++ * Copyright (c) 2001-2003, Adam Dunkels. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: uip.c,v 1.62.2.10 2003/10/07 13:23:01 adam Exp $ ++ * ++ */ ++ ++/* ++This is a small implementation of the IP and TCP protocols (as well as ++some basic ICMP stuff). The implementation couples the IP, TCP and the ++application layers very tightly. To keep the size of the compiled code ++down, this code also features heavy usage of the goto statement. ++ ++The principle is that we have a small buffer, called the uip_buf, in ++which the device driver puts an incoming packet. The TCP/IP stack ++parses the headers in the packet, and calls upon the application. If ++the remote host has sent data to the application, this data is present ++in the uip_buf and the application read the data from there. It is up ++to the application to put this data into a byte stream if needed. The ++application will not be fed with data that is out of sequence. ++ ++If the application whishes to send data to the peer, it should put its ++data into the uip_buf, 40 bytes from the start of the buffer. The ++TCP/IP stack will calculate the checksums, and fill in the necessary ++header fields and finally send the packet back to the peer. ++*/ ++ ++#include "uip.h" ++#include "uipopt.h" ++#include "uip_arch.h" ++ ++/*-----------------------------------------------------------------------------------*/ ++/* Variable definitions. */ ++ ++ ++/* The IP address of this host. If it is defined to be fixed (by setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set here. Otherwise, the address */ ++#if UIP_FIXEDADDR > 0 ++const unsigned short int uip_hostaddr[2] = ++ {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1), ++ HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)}; ++const unsigned short int uip_arp_draddr[2] = ++ {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1), ++ HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)}; ++const unsigned short int uip_arp_netmask[2] = ++ {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1), ++ HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)}; ++#else ++unsigned short int uip_hostaddr[2]; ++unsigned short int uip_arp_draddr[2], uip_arp_netmask[2]; ++#endif /* UIP_FIXEDADDR */ ++ ++u8_t uip_buf[UIP_BUFSIZE+2]; /* The packet buffer that contains ++ incoming packets. */ ++volatile u8_t *uip_appdata; /* The uip_appdata pointer points to ++ application data. */ ++volatile u8_t *uip_sappdata; /* The uip_appdata pointer points to the ++ application data which is to be sent. */ ++#if UIP_URGDATA > 0 ++volatile u8_t *uip_urgdata; /* The uip_urgdata pointer points to ++ urgent data (out-of-band data), if ++ present. */ ++volatile u8_t uip_urglen, uip_surglen; ++#endif /* UIP_URGDATA > 0 */ ++ ++volatile unsigned short int uip_len, uip_slen; ++ /* The uip_len is either 8 or 16 bits, ++ depending on the maximum packet ++ size. */ ++ ++volatile u8_t uip_flags; /* The uip_flags variable is used for ++ communication between the TCP/IP stack ++ and the application program. */ ++struct uip_conn *uip_conn; /* uip_conn always points to the current ++ connection. */ ++ ++struct uip_conn uip_conns[UIP_CONNS]; ++ /* The uip_conns array holds all TCP ++ connections. */ ++unsigned short int uip_listenports[UIP_LISTENPORTS]; ++ /* The uip_listenports list all currently ++ listning ports. */ ++#if UIP_UDP ++struct uip_udp_conn *uip_udp_conn; ++struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; ++#endif /* UIP_UDP */ ++ ++ ++static unsigned short int ipid; /* Ths ipid variable is an increasing ++ number that is used for the IP ID ++ field. */ ++ ++static u8_t iss[4]; /* The iss variable is used for the TCP ++ initial sequence number. */ ++ ++#if UIP_ACTIVE_OPEN ++static unsigned short int lastport; /* Keeps track of the last port used for ++ a new connection. */ ++#endif /* UIP_ACTIVE_OPEN */ ++ ++/* Temporary variables. */ ++volatile u8_t uip_acc32[4]; ++static u8_t c, opt; ++static unsigned short int tmp16; ++ ++/* Structures and definitions. */ ++#define TCP_FIN 0x01 ++#define TCP_SYN 0x02 ++#define TCP_RST 0x04 ++#define TCP_PSH 0x08 ++#define TCP_ACK 0x10 ++#define TCP_URG 0x20 ++#define TCP_CTL 0x3f ++ ++#define ICMP_ECHO_REPLY 0 ++#define ICMP_ECHO 8 ++ ++/* Macros. */ ++#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) ++#define FBUF ((uip_tcpip_hdr *)&uip_reassbuf[0]) ++#define ICMPBUF ((uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN]) ++#define UDPBUF ((uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN]) ++ ++#if UIP_STATISTICS == 1 ++struct uip_stats uip_stat; ++#define UIP_STAT(s) s ++#else ++#define UIP_STAT(s) ++#endif /* UIP_STATISTICS == 1 */ ++ ++#if UIP_LOGGING == 1 ++extern void puts(const char *s); ++#define UIP_LOG(m) puts(m) ++#else ++#define UIP_LOG(m) ++#endif /* UIP_LOGGING == 1 */ ++ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_init(void) ++{ ++ for(c = 0; c < UIP_LISTENPORTS; ++c) { ++ uip_listenports[c] = 0; ++ } ++ for(c = 0; c < UIP_CONNS; ++c) { ++ uip_conns[c].tcpstateflags = CLOSED; ++ } ++#if UIP_ACTIVE_OPEN ++ lastport = 1024; ++#endif /* UIP_ACTIVE_OPEN */ ++ ++#if UIP_UDP ++ for(c = 0; c < UIP_UDP_CONNS; ++c) { ++ uip_udp_conns[c].lport = 0; ++ } ++#endif /* UIP_UDP */ ++ ++ ++ /* IPv4 initialization. */ ++#if UIP_FIXEDADDR == 0 ++ uip_hostaddr[0] = uip_hostaddr[1] = 0; ++#endif /* UIP_FIXEDADDR */ ++ ++} ++/*-----------------------------------------------------------------------------------*/ ++#if UIP_ACTIVE_OPEN ++struct uip_conn * ++uip_connect(unsigned short int *ripaddr, unsigned short int rport) ++{ ++ register struct uip_conn *conn, *cconn; ++ ++ /* Find an unused local port. */ ++ again: ++ ++lastport; ++ ++ if(lastport >= 32000) { ++ lastport = 4096; ++ } ++ ++ /* Check if this port is already in use, and if so try to find ++ another one. */ ++ for(c = 0; c < UIP_CONNS; ++c) { ++ conn = &uip_conns[c]; ++ if(conn->tcpstateflags != CLOSED && ++ conn->lport == htons(lastport)) { ++ goto again; ++ } ++ } ++ ++ ++ conn = 0; ++ for(c = 0; c < UIP_CONNS; ++c) { ++ cconn = &uip_conns[c]; ++ if(cconn->tcpstateflags == CLOSED) { ++ conn = cconn; ++ break; ++ } ++ if(cconn->tcpstateflags == TIME_WAIT) { ++ if(conn == 0 || ++ cconn->timer > uip_conn->timer) { ++ conn = cconn; ++ } ++ } ++ } ++ ++ if(conn == 0) { ++ return 0; ++ } ++ ++ conn->tcpstateflags = SYN_SENT; ++ ++ conn->snd_nxt[0] = iss[0]; ++ conn->snd_nxt[1] = iss[1]; ++ conn->snd_nxt[2] = iss[2]; ++ conn->snd_nxt[3] = iss[3]; ++ ++ conn->initialmss = conn->mss = UIP_TCP_MSS; ++ ++ conn->len = 1; /* TCP length of the SYN is one. */ ++ conn->nrtx = 0; ++ conn->timer = 1; /* Send the SYN next time around. */ ++ conn->rto = UIP_RTO; ++ conn->sa = 0; ++ conn->sv = 16; ++ conn->lport = htons(lastport); ++ conn->rport = rport; ++ conn->ripaddr[0] = ripaddr[0]; ++ conn->ripaddr[1] = ripaddr[1]; ++ ++ return conn; ++} ++#endif /* UIP_ACTIVE_OPEN */ ++/*-----------------------------------------------------------------------------------*/ ++#if UIP_UDP ++struct uip_udp_conn * ++uip_udp_new(unsigned short int *ripaddr, unsigned short int rport) ++{ ++ register struct uip_udp_conn *conn; ++ ++ /* Find an unused local port. */ ++ again: ++ ++lastport; ++ ++ if(lastport >= 32000) { ++ lastport = 4096; ++ } ++ ++ for(c = 0; c < UIP_UDP_CONNS; ++c) { ++ if(uip_udp_conns[c].lport == lastport) { ++ goto again; ++ } ++ } ++ ++ ++ conn = 0; ++ for(c = 0; c < UIP_UDP_CONNS; ++c) { ++ if(uip_udp_conns[c].lport == 0) { ++ conn = &uip_udp_conns[c]; ++ break; ++ } ++ } ++ ++ if(conn == 0) { ++ return 0; ++ } ++ ++ conn->lport = HTONS(lastport); ++ conn->rport = HTONS(rport); ++ conn->ripaddr[0] = ripaddr[0]; ++ conn->ripaddr[1] = ripaddr[1]; ++ ++ return conn; ++} ++#endif /* UIP_UDP */ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_unlisten(unsigned short int port) ++{ ++ for(c = 0; c < UIP_LISTENPORTS; ++c) { ++ if(uip_listenports[c] == port) { ++ uip_listenports[c] = 0; ++ return; ++ } ++ } ++} ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_listen(unsigned short int port) ++{ ++ for(c = 0; c < UIP_LISTENPORTS; ++c) { ++ if(uip_listenports[c] == 0) { ++ uip_listenports[c] = port; ++ return; ++ } ++ } ++} ++/*-----------------------------------------------------------------------------------*/ ++/* XXX: IP fragment reassembly: not well-tested. */ ++ ++#if UIP_REASSEMBLY ++#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN) ++static u8_t uip_reassbuf[UIP_REASS_BUFSIZE]; ++static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)]; ++static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f, ++ 0x0f, 0x07, 0x03, 0x01}; ++static unsigned short int uip_reasslen; ++static u8_t uip_reassflags; ++#define UIP_REASS_FLAG_LASTFRAG 0x01 ++static u8_t uip_reasstmr; ++ ++#define IP_HLEN 20 ++#define IP_MF 0x20 ++ ++static u8_t ++uip_reass(void) ++{ ++ unsigned short int offset, len; ++ unsigned short int i; ++ ++ /* If ip_reasstmr is zero, no packet is present in the buffer, so we ++ write the IP header of the fragment into the reassembly ++ buffer. The timer is updated with the maximum age. */ ++ if(uip_reasstmr == 0) { ++ memcpy(uip_reassbuf, &BUF->vhl, IP_HLEN); ++ uip_reasstmr = UIP_REASS_MAXAGE; ++ uip_reassflags = 0; ++ /* Clear the bitmap. */ ++ memset(uip_reassbitmap, sizeof(uip_reassbitmap), 0); ++ } ++ ++ /* Check if the incoming fragment matches the one currently present ++ in the reasembly buffer. If so, we proceed with copying the ++ fragment into the buffer. */ ++ if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] && ++ BUF->srcipaddr[1] == FBUF->srcipaddr[1] && ++ BUF->destipaddr[0] == FBUF->destipaddr[0] && ++ BUF->destipaddr[1] == FBUF->destipaddr[1] && ++ BUF->ipid[0] == FBUF->ipid[0] && ++ BUF->ipid[1] == FBUF->ipid[1]) { ++ ++ len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4; ++ offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8; ++ ++ /* If the offset or the offset + fragment length overflows the ++ reassembly buffer, we discard the entire packet. */ ++ if(offset > UIP_REASS_BUFSIZE || ++ offset + len > UIP_REASS_BUFSIZE) { ++ uip_reasstmr = 0; ++ goto nullreturn; ++ } ++ ++ /* Copy the fragment into the reassembly buffer, at the right ++ offset. */ ++ memcpy(&uip_reassbuf[IP_HLEN + offset], ++ (char *)BUF + (int)((BUF->vhl & 0x0f) * 4), ++ len); ++ ++ /* Update the bitmap. */ ++ if(offset / (8 * 8) == (offset + len) / (8 * 8)) { ++ /* If the two endpoints are in the same byte, we only update ++ that byte. */ ++ ++ uip_reassbitmap[offset / (8 * 8)] |= ++ bitmap_bits[(offset / 8 ) & 7] & ++ ~bitmap_bits[((offset + len) / 8 ) & 7]; ++ } else { ++ /* If the two endpoints are in different bytes, we update the ++ bytes in the endpoints and fill the stuff inbetween with ++ 0xff. */ ++ uip_reassbitmap[offset / (8 * 8)] |= ++ bitmap_bits[(offset / 8 ) & 7]; ++ for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) { ++ uip_reassbitmap[i] = 0xff; ++ } ++ uip_reassbitmap[(offset + len) / (8 * 8)] |= ++ ~bitmap_bits[((offset + len) / 8 ) & 7]; ++ } ++ ++ /* If this fragment has the More Fragments flag set to zero, we ++ know that this is the last fragment, so we can calculate the ++ size of the entire packet. We also set the ++ IP_REASS_FLAG_LASTFRAG flag to indicate that we have received ++ the final fragment. */ ++ ++ if((BUF->ipoffset[0] & IP_MF) == 0) { ++ uip_reassflags |= UIP_REASS_FLAG_LASTFRAG; ++ uip_reasslen = offset + len; ++ } ++ ++ /* Finally, we check if we have a full packet in the buffer. We do ++ this by checking if we have the last fragment and if all bits ++ in the bitmap are set. */ ++ if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) { ++ /* Check all bytes up to and including all but the last byte in ++ the bitmap. */ ++ for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) { ++ if(uip_reassbitmap[i] != 0xff) { ++ goto nullreturn; ++ } ++ } ++ /* Check the last byte in the bitmap. It should contain just the ++ right amount of bits. */ ++ if(uip_reassbitmap[uip_reasslen / (8 * 8)] != ++ (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) { ++ goto nullreturn; ++ } ++ ++ /* If we have come this far, we have a full packet in the ++ buffer, so we allocate a pbuf and copy the packet into it. We ++ also reset the timer. */ ++ uip_reasstmr = 0; ++ memcpy(BUF, FBUF, uip_reasslen); ++ ++ /* Pretend to be a "normal" (i.e., not fragmented) IP packet ++ from now on. */ ++ BUF->ipoffset[0] = BUF->ipoffset[1] = 0; ++ BUF->len[0] = uip_reasslen >> 8; ++ BUF->len[1] = uip_reasslen & 0xff; ++ BUF->ipchksum = 0; ++ BUF->ipchksum = ~(uip_ipchksum()); ++ ++ return uip_reasslen; ++ } ++ } ++ ++ nullreturn: ++ return 0; ++} ++#endif /* UIP_REASSEMBL */ ++/*-----------------------------------------------------------------------------------*/ ++static void ++uip_add_rcv_nxt(unsigned short int n) ++{ ++ uip_add32(uip_conn->rcv_nxt, n); ++ uip_conn->rcv_nxt[0] = uip_acc32[0]; ++ uip_conn->rcv_nxt[1] = uip_acc32[1]; ++ uip_conn->rcv_nxt[2] = uip_acc32[2]; ++ uip_conn->rcv_nxt[3] = uip_acc32[3]; ++} ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_process(u8_t flag) ++{ ++ register struct uip_conn *uip_connr = uip_conn; ++ ++ uip_appdata = &uip_buf[40 + UIP_LLH_LEN]; ++ ++ ++ /* Check if we were invoked because of the perodic timer fireing. */ ++ if(flag == UIP_TIMER) { ++#if UIP_REASSEMBLY ++ if(uip_reasstmr != 0) { ++ --uip_reasstmr; ++ } ++#endif /* UIP_REASSEMBLY */ ++ /* Increase the initial sequence number. */ ++ if(++iss[3] == 0) { ++ if(++iss[2] == 0) { ++ if(++iss[1] == 0) { ++ ++iss[0]; ++ } ++ } ++ } ++ uip_len = 0; ++ if(uip_connr->tcpstateflags == TIME_WAIT || ++ uip_connr->tcpstateflags == FIN_WAIT_2) { ++ ++(uip_connr->timer); ++ if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) { ++ uip_connr->tcpstateflags = CLOSED; ++ } ++ } else if(uip_connr->tcpstateflags != CLOSED) { ++ /* If the connection has outstanding data, we increase the ++ connection's timer and see if it has reached the RTO value ++ in which case we retransmit. */ ++ if(uip_outstanding(uip_connr)) { ++ if(uip_connr->timer-- == 0) { ++ if(uip_connr->nrtx == UIP_MAXRTX || ++ ((uip_connr->tcpstateflags == SYN_SENT || ++ uip_connr->tcpstateflags == SYN_RCVD) && ++ uip_connr->nrtx == UIP_MAXSYNRTX)) { ++ uip_connr->tcpstateflags = CLOSED; ++ ++ /* We call UIP_APPCALL() with uip_flags set to ++ UIP_TIMEDOUT to inform the application that the ++ connection has timed out. */ ++ uip_flags = UIP_TIMEDOUT; ++ UIP_APPCALL(); ++ ++ /* We also send a reset packet to the remote host. */ ++ BUF->flags = TCP_RST | TCP_ACK; ++ goto tcp_send_nodata; ++ } ++ ++ /* Exponential backoff. */ ++ uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4? ++ 4: ++ uip_connr->nrtx); ++ ++(uip_connr->nrtx); ++ ++ /* Ok, so we need to retransmit. We do this differently ++ depending on which state we are in. In ESTABLISHED, we ++ call upon the application so that it may prepare the ++ data for the retransmit. In SYN_RCVD, we resend the ++ SYNACK that we sent earlier and in LAST_ACK we have to ++ retransmit our FINACK. */ ++ UIP_STAT(++uip_stat.tcp.rexmit); ++ switch(uip_connr->tcpstateflags & TS_MASK) { ++ case SYN_RCVD: ++ /* In the SYN_RCVD state, we should retransmit our ++ SYNACK. */ ++ goto tcp_send_synack; ++ ++#if UIP_ACTIVE_OPEN ++ case SYN_SENT: ++ /* In the SYN_SENT state, we retransmit out SYN. */ ++ BUF->flags = 0; ++ goto tcp_send_syn; ++#endif /* UIP_ACTIVE_OPEN */ ++ ++ case ESTABLISHED: ++ /* In the ESTABLISHED state, we call upon the application ++ to do the actual retransmit after which we jump into ++ the code for sending out the packet (the apprexmit ++ label). */ ++ uip_len = 0; ++ uip_slen = 0; ++ uip_flags = UIP_REXMIT; ++ UIP_APPCALL(); ++ goto apprexmit; ++ ++ case FIN_WAIT_1: ++ case CLOSING: ++ case LAST_ACK: ++ /* In all these states we should retransmit a FINACK. */ ++ goto tcp_send_finack; ++ ++ } ++ } ++ } else if((uip_connr->tcpstateflags & TS_MASK) == ESTABLISHED) { ++ /* If there was no need for a retransmission, we poll the ++ application for new data. */ ++ uip_len = 0; ++ uip_slen = 0; ++ uip_flags = UIP_POLL; ++ UIP_APPCALL(); ++ goto appsend; ++ } ++ } ++ goto drop; ++ } ++#if UIP_UDP ++ if(flag == UIP_UDP_TIMER) { ++ if(uip_udp_conn->lport != 0) { ++ uip_appdata = &uip_buf[UIP_LLH_LEN + 28]; ++ uip_len = uip_slen = 0; ++ uip_flags = UIP_POLL; ++ UIP_UDP_APPCALL(); ++ goto udp_send; ++ } else { ++ goto drop; ++ } ++ } ++#endif ++ ++ /* This is where the input processing starts. */ ++ UIP_STAT(++uip_stat.ip.recv); ++ ++ ++ /* Start of IPv4 input header processing code. */ ++ ++ /* Check validity of the IP header. */ ++ if(BUF->vhl != 0x45) { /* IP version and header length. */ ++ UIP_STAT(++uip_stat.ip.drop); ++ UIP_STAT(++uip_stat.ip.vhlerr); ++ UIP_LOG("ip: invalid version or header length."); ++ goto drop; ++ } ++ ++ /* Check the size of the packet. If the size reported to us in ++ uip_len doesn't match the size reported in the IP header, there ++ has been a transmission error and we drop the packet. */ ++ ++ if(BUF->len[0] != (uip_len >> 8)) { /* IP length, high byte. */ ++ uip_len = (uip_len & 0xff) | (BUF->len[0] << 8); ++ } ++ if(BUF->len[1] != (uip_len & 0xff)) { /* IP length, low byte. */ ++ uip_len = (uip_len & 0xff00) | BUF->len[1]; ++ } ++ ++ /* Check the fragment flag. */ ++ if((BUF->ipoffset[0] & 0x3f) != 0 || ++ BUF->ipoffset[1] != 0) { ++#if UIP_REASSEMBLY ++ uip_len = uip_reass(); ++ if(uip_len == 0) { ++ goto drop; ++ } ++#else ++ UIP_STAT(++uip_stat.ip.drop); ++ UIP_STAT(++uip_stat.ip.fragerr); ++ UIP_LOG("ip: fragment dropped."); ++ goto drop; ++#endif /* UIP_REASSEMBLY */ ++ } ++ ++ /* If we are configured to use ping IP address configuration and ++ hasn't been assigned an IP address yet, we accept all ICMP ++ packets. */ ++#if UIP_PINGADDRCONF ++ if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) { ++ if(BUF->proto == UIP_PROTO_ICMP) { ++ UIP_LOG("ip: possible ping config packet received."); ++ goto icmp_input; ++ } else { ++ UIP_LOG("ip: packet dropped since no address assigned."); ++ goto drop; ++ } ++ } ++#endif /* UIP_PINGADDRCONF */ ++ ++ /* Check if the packet is destined for our IP address. */ ++ if(BUF->destipaddr[0] != uip_hostaddr[0]) { ++ UIP_STAT(++uip_stat.ip.drop); ++ UIP_LOG("ip: packet not for us."); ++ goto drop; ++ } ++ if(BUF->destipaddr[1] != uip_hostaddr[1]) { ++ UIP_STAT(++uip_stat.ip.drop); ++ UIP_LOG("ip: packet not for us."); ++ goto drop; ++ } ++ ++ if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header ++ checksum. */ ++ UIP_STAT(++uip_stat.ip.drop); ++ UIP_STAT(++uip_stat.ip.chkerr); ++ UIP_LOG("ip: bad checksum."); ++ goto drop; ++ } ++ ++ if(BUF->proto == UIP_PROTO_TCP) /* Check for TCP packet. If so, jump ++ to the tcp_input label. */ ++ goto tcp_input; ++ ++#if UIP_UDP ++ if(BUF->proto == UIP_PROTO_UDP) ++ goto udp_input; ++#endif /* UIP_UDP */ ++ ++ if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from ++ here. */ ++ UIP_STAT(++uip_stat.ip.drop); ++ UIP_STAT(++uip_stat.ip.protoerr); ++ UIP_LOG("ip: neither tcp nor icmp."); ++ goto drop; ++ } ++ ++ //icmp_input: ++ UIP_STAT(++uip_stat.icmp.recv); ++ ++ /* ICMP echo (i.e., ping) processing. This is simple, we only change ++ the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP ++ checksum before we return the packet. */ ++ if(ICMPBUF->type != ICMP_ECHO) { ++ UIP_STAT(++uip_stat.icmp.drop); ++ UIP_STAT(++uip_stat.icmp.typeerr); ++ UIP_LOG("icmp: not icmp echo."); ++ goto drop; ++ } ++ ++ /* If we are configured to use ping IP address assignment, we use ++ the destination IP address of this ping packet and assign it to ++ ourself. */ ++#if UIP_PINGADDRCONF ++ if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) { ++ uip_hostaddr[0] = BUF->destipaddr[0]; ++ uip_hostaddr[1] = BUF->destipaddr[1]; ++ } ++#endif /* UIP_PINGADDRCONF */ ++ ++ ICMPBUF->type = ICMP_ECHO_REPLY; ++ ++ if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) { ++ ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1; ++ } else { ++ ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8); ++ } ++ ++ /* Swap IP addresses. */ ++ tmp16 = BUF->destipaddr[0]; ++ BUF->destipaddr[0] = BUF->srcipaddr[0]; ++ BUF->srcipaddr[0] = tmp16; ++ tmp16 = BUF->destipaddr[1]; ++ BUF->destipaddr[1] = BUF->srcipaddr[1]; ++ BUF->srcipaddr[1] = tmp16; ++ ++ UIP_STAT(++uip_stat.icmp.sent); ++ goto send; ++ ++ /* End of IPv4 input header processing code. */ ++ ++ ++#if UIP_UDP ++ /* UDP input processing. */ ++ udp_input: ++ /* UDP processing is really just a hack. We don't do anything to the ++ UDP/IP headers, but let the UDP application do all the hard ++ work. If the application sets uip_slen, it has a packet to ++ send. */ ++#if UIP_UDP_CHECKSUMS ++ if(uip_udpchksum() != 0xffff) { ++ UIP_STAT(++uip_stat.udp.drop); ++ UIP_STAT(++uip_stat.udp.chkerr); ++ UIP_LOG("udp: bad checksum."); ++ goto drop; ++ } ++#endif /* UIP_UDP_CHECKSUMS */ ++ ++ /* Demultiplex this UDP packet between the UDP "connections". */ ++ for(uip_udp_conn = &uip_udp_conns[0]; ++ uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS]; ++ ++uip_udp_conn) { ++ if(uip_udp_conn->lport != 0 && ++ UDPBUF->destport == uip_udp_conn->lport && ++ (uip_udp_conn->rport == 0 || ++ UDPBUF->srcport == uip_udp_conn->rport) && ++ BUF->srcipaddr[0] == uip_udp_conn->ripaddr[0] && ++ BUF->srcipaddr[1] == uip_udp_conn->ripaddr[1]) { ++ goto udp_found; ++ } ++ } ++ goto drop; ++ ++ udp_found: ++ uip_len = uip_len - 28; ++ uip_appdata = &uip_buf[UIP_LLH_LEN + 28]; ++ uip_flags = UIP_NEWDATA; ++ uip_slen = 0; ++ UIP_UDP_APPCALL(); ++ udp_send: ++ if(uip_slen == 0) { ++ goto drop; ++ } ++ uip_len = uip_slen + 28; ++ ++ BUF->len[0] = (uip_len >> 8); ++ BUF->len[1] = (uip_len & 0xff); ++ ++ BUF->proto = UIP_PROTO_UDP; ++ ++ UDPBUF->udplen = HTONS(uip_slen + 8); ++ UDPBUF->udpchksum = 0; ++#if UIP_UDP_CHECKSUMS ++ /* Calculate UDP checksum. */ ++ UDPBUF->udpchksum = ~(uip_udpchksum()); ++ if(UDPBUF->udpchksum == 0) { ++ UDPBUF->udpchksum = 0xffff; ++ } ++#endif /* UIP_UDP_CHECKSUMS */ ++ ++ BUF->srcport = uip_udp_conn->lport; ++ BUF->destport = uip_udp_conn->rport; ++ ++ BUF->srcipaddr[0] = uip_hostaddr[0]; ++ BUF->srcipaddr[1] = uip_hostaddr[1]; ++ BUF->destipaddr[0] = uip_udp_conn->ripaddr[0]; ++ BUF->destipaddr[1] = uip_udp_conn->ripaddr[1]; ++ ++ uip_appdata = &uip_buf[UIP_LLH_LEN + 40]; ++ goto ip_send_nolen; ++#endif /* UIP_UDP */ ++ ++ /* TCP input processing. */ ++ tcp_input: ++ UIP_STAT(++uip_stat.tcp.recv); ++ ++ /* Start of TCP input header processing code. */ ++ ++ if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP ++ checksum. */ ++ UIP_STAT(++uip_stat.tcp.drop); ++ UIP_STAT(++uip_stat.tcp.chkerr); ++ UIP_LOG("tcp: bad checksum."); ++ goto drop; ++ } ++ ++ /* Demultiplex this segment. */ ++ /* First check any active connections. */ ++ for(uip_connr = &uip_conns[0]; uip_connr < &uip_conns[UIP_CONNS]; ++uip_connr) { ++ if(uip_connr->tcpstateflags != CLOSED && ++ BUF->destport == uip_connr->lport && ++ BUF->srcport == uip_connr->rport && ++ BUF->srcipaddr[0] == uip_connr->ripaddr[0] && ++ BUF->srcipaddr[1] == uip_connr->ripaddr[1]) { ++ goto found; ++ } ++ } ++ ++ /* If we didn't find and active connection that expected the packet, ++ either this packet is an old duplicate, or this is a SYN packet ++ destined for a connection in LISTEN. If the SYN flag isn't set, ++ it is an old packet and we send a RST. */ ++ if((BUF->flags & TCP_CTL) != TCP_SYN) ++ goto reset; ++ ++ tmp16 = BUF->destport; ++ /* Next, check listening connections. */ ++ for(c = 0; c < UIP_LISTENPORTS; ++c) { ++ if(tmp16 == uip_listenports[c]) ++ goto found_listen; ++ } ++ ++ /* No matching connection found, so we send a RST packet. */ ++ UIP_STAT(++uip_stat.tcp.synrst); ++ reset: ++ ++ /* We do not send resets in response to resets. */ ++ if(BUF->flags & TCP_RST) ++ goto drop; ++ ++ UIP_STAT(++uip_stat.tcp.rst); ++ ++ BUF->flags = TCP_RST | TCP_ACK; ++ uip_len = 40; ++ BUF->tcpoffset = 5 << 4; ++ ++ /* Flip the seqno and ackno fields in the TCP header. */ ++ c = BUF->seqno[3]; ++ BUF->seqno[3] = BUF->ackno[3]; ++ BUF->ackno[3] = c; ++ ++ c = BUF->seqno[2]; ++ BUF->seqno[2] = BUF->ackno[2]; ++ BUF->ackno[2] = c; ++ ++ c = BUF->seqno[1]; ++ BUF->seqno[1] = BUF->ackno[1]; ++ BUF->ackno[1] = c; ++ ++ c = BUF->seqno[0]; ++ BUF->seqno[0] = BUF->ackno[0]; ++ BUF->ackno[0] = c; ++ ++ /* We also have to increase the sequence number we are ++ acknowledging. If the least significant byte overflowed, we need ++ to propagate the carry to the other bytes as well. */ ++ if(++BUF->ackno[3] == 0) { ++ if(++BUF->ackno[2] == 0) { ++ if(++BUF->ackno[1] == 0) { ++ ++BUF->ackno[0]; ++ } ++ } ++ } ++ ++ /* Swap port numbers. */ ++ tmp16 = BUF->srcport; ++ BUF->srcport = BUF->destport; ++ BUF->destport = tmp16; ++ ++ /* Swap IP addresses. */ ++ tmp16 = BUF->destipaddr[0]; ++ BUF->destipaddr[0] = BUF->srcipaddr[0]; ++ BUF->srcipaddr[0] = tmp16; ++ tmp16 = BUF->destipaddr[1]; ++ BUF->destipaddr[1] = BUF->srcipaddr[1]; ++ BUF->srcipaddr[1] = tmp16; ++ ++ ++ /* And send out the RST packet! */ ++ goto tcp_send_noconn; ++ ++ /* This label will be jumped to if we matched the incoming packet ++ with a connection in LISTEN. In that case, we should create a new ++ connection and send a SYNACK in return. */ ++ found_listen: ++ /* First we check if there are any connections avaliable. Unused ++ connections are kept in the same table as used connections, but ++ unused ones have the tcpstate set to CLOSED. Also, connections in ++ TIME_WAIT are kept track of and we'll use the oldest one if no ++ CLOSED connections are found. Thanks to Eddie C. Dost for a very ++ nice algorithm for the TIME_WAIT search. */ ++ uip_connr = 0; ++ for(c = 0; c < UIP_CONNS; ++c) { ++ if(uip_conns[c].tcpstateflags == CLOSED) { ++ uip_connr = &uip_conns[c]; ++ break; ++ } ++ if(uip_conns[c].tcpstateflags == TIME_WAIT) { ++ if(uip_connr == 0 || ++ uip_conns[c].timer > uip_connr->timer) { ++ uip_connr = &uip_conns[c]; ++ } ++ } ++ } ++ ++ if(uip_connr == 0) { ++ /* All connections are used already, we drop packet and hope that ++ the remote end will retransmit the packet at a time when we ++ have more spare connections. */ ++ UIP_STAT(++uip_stat.tcp.syndrop); ++ UIP_LOG("tcp: found no unused connections."); ++ goto drop; ++ } ++ uip_conn = uip_connr; ++ ++ /* Fill in the necessary fields for the new connection. */ ++ uip_connr->rto = uip_connr->timer = UIP_RTO; ++ uip_connr->sa = 0; ++ uip_connr->sv = 4; ++ uip_connr->nrtx = 0; ++ uip_connr->lport = BUF->destport; ++ uip_connr->rport = BUF->srcport; ++ uip_connr->ripaddr[0] = BUF->srcipaddr[0]; ++ uip_connr->ripaddr[1] = BUF->srcipaddr[1]; ++ uip_connr->tcpstateflags = SYN_RCVD; ++ ++ uip_connr->snd_nxt[0] = iss[0]; ++ uip_connr->snd_nxt[1] = iss[1]; ++ uip_connr->snd_nxt[2] = iss[2]; ++ uip_connr->snd_nxt[3] = iss[3]; ++ uip_connr->len = 1; ++ ++ /* rcv_nxt should be the seqno from the incoming packet + 1. */ ++ uip_connr->rcv_nxt[3] = BUF->seqno[3]; ++ uip_connr->rcv_nxt[2] = BUF->seqno[2]; ++ uip_connr->rcv_nxt[1] = BUF->seqno[1]; ++ uip_connr->rcv_nxt[0] = BUF->seqno[0]; ++ uip_add_rcv_nxt(1); ++ ++ /* Parse the TCP MSS option, if present. */ ++ if((BUF->tcpoffset & 0xf0) > 0x50) { ++ for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { ++ opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c]; ++ if(opt == 0x00) { ++ /* End of options. */ ++ break; ++ } else if(opt == 0x01) { ++ ++c; ++ /* NOP option. */ ++ } else if(opt == 0x02 && ++ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) { ++ /* An MSS option with the right option length. */ ++ tmp16 = ((unsigned short int)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | ++ (unsigned short int)uip_buf[40 + UIP_LLH_LEN + 3 + c]; ++ uip_connr->initialmss = uip_connr->mss = ++ tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; ++ ++ /* And we are done processing options. */ ++ break; ++ } else { ++ /* All other options have a length field, so that we easily ++ can skip past them. */ ++ if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { ++ /* If the length field is zero, the options are malformed ++ and we don't process them further. */ ++ break; ++ } ++ c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; ++ } ++ } ++ } ++ ++ /* Our response will be a SYNACK. */ ++#if UIP_ACTIVE_OPEN ++ tcp_send_synack: ++ BUF->flags = TCP_ACK; ++ ++ tcp_send_syn: ++ BUF->flags |= TCP_SYN; ++#else /* UIP_ACTIVE_OPEN */ ++ tcp_send_synack: ++ BUF->flags = TCP_SYN | TCP_ACK; ++#endif /* UIP_ACTIVE_OPEN */ ++ ++ /* We send out the TCP Maximum Segment Size option with our ++ SYNACK. */ ++ BUF->optdata[0] = 2; ++ BUF->optdata[1] = 4; ++ BUF->optdata[2] = (UIP_TCP_MSS) / 256; ++ BUF->optdata[3] = (UIP_TCP_MSS) & 255; ++ uip_len = 44; ++ BUF->tcpoffset = 6 << 4; ++ goto tcp_send; ++ ++ /* This label will be jumped to if we found an active connection. */ ++ found: ++ uip_conn = uip_connr; ++ uip_flags = 0; ++ ++ /* We do a very naive form of TCP reset processing; we just accept ++ any RST and kill our connection. We should in fact check if the ++ sequence number of this reset is wihtin our advertised window ++ before we accept the reset. */ ++ if(BUF->flags & TCP_RST) { ++ uip_connr->tcpstateflags = CLOSED; ++ UIP_LOG("tcp: got reset, aborting connection."); ++ uip_flags = UIP_ABORT; ++ UIP_APPCALL(); ++ goto drop; ++ } ++ /* Calculated the length of the data, if the application has sent ++ any data to us. */ ++ c = (BUF->tcpoffset >> 4) << 2; ++ /* uip_len will contain the length of the actual TCP data. This is ++ calculated by subtracing the length of the TCP header (in ++ c) and the length of the IP header (20 bytes). */ ++ uip_len = uip_len - c - 20; ++ ++ /* First, check if the sequence number of the incoming packet is ++ what we're expecting next. If not, we send out an ACK with the ++ correct numbers in. */ ++ if(uip_len > 0 && ++ (BUF->seqno[0] != uip_connr->rcv_nxt[0] || ++ BUF->seqno[1] != uip_connr->rcv_nxt[1] || ++ BUF->seqno[2] != uip_connr->rcv_nxt[2] || ++ BUF->seqno[3] != uip_connr->rcv_nxt[3])) { ++ goto tcp_send_ack; ++ } ++ ++ /* Next, check if the incoming segment acknowledges any outstanding ++ data. If so, we update the sequence number, reset the length of ++ the outstanding data, calculate RTT estimations, and reset the ++ retransmission timer. */ ++ if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) { ++ uip_add32(uip_connr->snd_nxt, uip_connr->len); ++ if(BUF->ackno[0] == uip_acc32[0] && ++ BUF->ackno[1] == uip_acc32[1] && ++ BUF->ackno[2] == uip_acc32[2] && ++ BUF->ackno[3] == uip_acc32[3]) { ++ /* Update sequence number. */ ++ uip_connr->snd_nxt[0] = uip_acc32[0]; ++ uip_connr->snd_nxt[1] = uip_acc32[1]; ++ uip_connr->snd_nxt[2] = uip_acc32[2]; ++ uip_connr->snd_nxt[3] = uip_acc32[3]; ++ ++ ++ /* Do RTT estimation, unless we have done retransmissions. */ ++ if(uip_connr->nrtx == 0) { ++ signed char m; ++ m = uip_connr->rto - uip_connr->timer; ++ /* This is taken directly from VJs original code in his paper */ ++ m = m - (uip_connr->sa >> 3); ++ uip_connr->sa += m; ++ if(m < 0) { ++ m = -m; ++ } ++ m = m - (uip_connr->sv >> 2); ++ uip_connr->sv += m; ++ uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv; ++ ++ } ++ /* Set the acknowledged flag. */ ++ uip_flags = UIP_ACKDATA; ++ /* Reset the retransmission timer. */ ++ uip_connr->timer = uip_connr->rto; ++ } ++ ++ } ++ ++ /* Do different things depending on in what state the connection is. */ ++ switch(uip_connr->tcpstateflags & TS_MASK) { ++ /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not ++ implemented, since we force the application to close when the ++ peer sends a FIN (hence the application goes directly from ++ ESTABLISHED to LAST_ACK). */ ++ case SYN_RCVD: ++ /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and ++ we are waiting for an ACK that acknowledges the data we sent ++ out the last time. Therefore, we want to have the UIP_ACKDATA ++ flag set. If so, we enter the ESTABLISHED state. */ ++ if(uip_flags & UIP_ACKDATA) { ++ uip_connr->tcpstateflags = ESTABLISHED; ++ uip_flags = UIP_CONNECTED; ++ uip_connr->len = 0; ++ if(uip_len > 0) { ++ uip_flags |= UIP_NEWDATA; ++ uip_add_rcv_nxt(uip_len); ++ } ++ uip_slen = 0; ++ UIP_APPCALL(); ++ goto appsend; ++ } ++ goto drop; ++#if UIP_ACTIVE_OPEN ++ case SYN_SENT: ++ /* In SYN_SENT, we wait for a SYNACK that is sent in response to ++ our SYN. The rcv_nxt is set to sequence number in the SYNACK ++ plus one, and we send an ACK. We move into the ESTABLISHED ++ state. */ ++ if((uip_flags & UIP_ACKDATA) && ++ BUF->flags == (TCP_SYN | TCP_ACK)) { ++ ++ /* Parse the TCP MSS option, if present. */ ++ if((BUF->tcpoffset & 0xf0) > 0x50) { ++ for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { ++ opt = uip_buf[40 + UIP_LLH_LEN + c]; ++ if(opt == 0x00) { ++ /* End of options. */ ++ break; ++ } else if(opt == 0x01) { ++ ++c; ++ /* NOP option. */ ++ } else if(opt == 0x02 && ++ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) { ++ /* An MSS option with the right option length. */ ++ tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | ++ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c]; ++ uip_connr->initialmss = ++ uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; ++ ++ /* And we are done processing options. */ ++ break; ++ } else { ++ /* All other options have a length field, so that we easily ++ can skip past them. */ ++ if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { ++ /* If the length field is zero, the options are malformed ++ and we don't process them further. */ ++ break; ++ } ++ c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; ++ } ++ } ++ } ++ uip_connr->tcpstateflags = ESTABLISHED; ++ uip_connr->rcv_nxt[0] = BUF->seqno[0]; ++ uip_connr->rcv_nxt[1] = BUF->seqno[1]; ++ uip_connr->rcv_nxt[2] = BUF->seqno[2]; ++ uip_connr->rcv_nxt[3] = BUF->seqno[3]; ++ uip_add_rcv_nxt(1); ++ uip_flags = UIP_CONNECTED | UIP_NEWDATA; ++ uip_connr->len = 0; ++ uip_len = 0; ++ uip_slen = 0; ++ UIP_APPCALL(); ++ goto appsend; ++ } ++ goto reset; ++#endif /* UIP_ACTIVE_OPEN */ ++ ++ case ESTABLISHED: ++ /* In the ESTABLISHED state, we call upon the application to feed ++ data into the uip_buf. If the UIP_ACKDATA flag is set, the ++ application should put new data into the buffer, otherwise we are ++ retransmitting an old segment, and the application should put that ++ data into the buffer. ++ ++ If the incoming packet is a FIN, we should close the connection on ++ this side as well, and we send out a FIN and enter the LAST_ACK ++ state. We require that there is no outstanding data; otherwise the ++ sequence numbers will be screwed up. */ ++ ++ if(BUF->flags & TCP_FIN) { ++ if(uip_outstanding(uip_connr)) { ++ goto drop; ++ } ++ uip_add_rcv_nxt(1 + uip_len); ++ uip_flags = UIP_CLOSE; ++ if(uip_len > 0) { ++ uip_flags |= UIP_NEWDATA; ++ } ++ UIP_APPCALL(); ++ uip_connr->len = 1; ++ uip_connr->tcpstateflags = LAST_ACK; ++ uip_connr->nrtx = 0; ++ tcp_send_finack: ++ BUF->flags = TCP_FIN | TCP_ACK; ++ goto tcp_send_nodata; ++ } ++ ++ /* Check the URG flag. If this is set, the segment carries urgent ++ data that we must pass to the application. */ ++ if(BUF->flags & TCP_URG) { ++#if UIP_URGDATA > 0 ++ uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1]; ++ if(uip_urglen > uip_len) { ++ /* There is more urgent data in the next segment to come. */ ++ uip_urglen = uip_len; ++ } ++ uip_add_rcv_nxt(uip_urglen); ++ uip_len -= uip_urglen; ++ uip_urgdata = uip_appdata; ++ uip_appdata += uip_urglen; ++ } else { ++ uip_urglen = 0; ++#endif /* UIP_URGDATA > 0 */ ++ uip_appdata += (BUF->urgp[0] << 8) | BUF->urgp[1]; ++ uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1]; ++ } ++ ++ ++ /* If uip_len > 0 we have TCP data in the packet, and we flag this ++ by setting the UIP_NEWDATA flag and update the sequence number ++ we acknowledge. If the application has stopped the dataflow ++ using uip_stop(), we must not accept any data packets from the ++ remote host. */ ++ if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) { ++ uip_flags |= UIP_NEWDATA; ++ uip_add_rcv_nxt(uip_len); ++ } ++ ++ /* Check if the available buffer space advertised by the other end ++ is smaller than the initial MSS for this connection. If so, we ++ set the current MSS to the window size to ensure that the ++ application does not send more data than the other end can ++ handle. ++ ++ If the remote host advertises a zero window, we set the MSS to ++ the initial MSS so that the application will send an entire MSS ++ of data. This data will not be acknowledged by the receiver, ++ and the application will retransmit it. This is called the ++ "persistent timer" and uses the retransmission mechanim. ++ */ ++ tmp16 = ((unsigned short int)BUF->wnd[0] << 8) + (unsigned short int)BUF->wnd[1]; ++ if(tmp16 > uip_connr->initialmss || ++ tmp16 == 0) { ++ tmp16 = uip_connr->initialmss; ++ } ++ uip_connr->mss = tmp16; ++ ++ /* If this packet constitutes an ACK for outstanding data (flagged ++ by the UIP_ACKDATA flag, we should call the application since it ++ might want to send more data. If the incoming packet had data ++ from the peer (as flagged by the UIP_NEWDATA flag), the ++ application must also be notified. ++ ++ When the application is called, the global variable uip_len ++ contains the length of the incoming data. The application can ++ access the incoming data through the global pointer ++ uip_appdata, which usually points 40 bytes into the uip_buf ++ array. ++ ++ If the application wishes to send any data, this data should be ++ put into the uip_appdata and the length of the data should be ++ put into uip_len. If the application don't have any data to ++ send, uip_len must be set to 0. */ ++ if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) { ++ uip_slen = 0; ++ UIP_APPCALL(); ++ ++ appsend: ++ ++ if(uip_flags & UIP_ABORT) { ++ uip_slen = 0; ++ uip_connr->tcpstateflags = CLOSED; ++ BUF->flags = TCP_RST | TCP_ACK; ++ goto tcp_send_nodata; ++ } ++ ++ if(uip_flags & UIP_CLOSE) { ++ uip_slen = 0; ++ uip_connr->len = 1; ++ uip_connr->tcpstateflags = FIN_WAIT_1; ++ uip_connr->nrtx = 0; ++ BUF->flags = TCP_FIN | TCP_ACK; ++ goto tcp_send_nodata; ++ } ++ ++ /* If uip_slen > 0, the application has data to be sent. */ ++ if(uip_slen > 0) { ++ ++ /* If the connection has acknowledged data, the contents of ++ the ->len variable should be discarded. */ ++ if((uip_flags & UIP_ACKDATA) != 0) { ++ uip_connr->len = 0; ++ } ++ ++ /* If the ->len variable is non-zero the connection has ++ already data in transit and cannot send anymore right ++ now. */ ++ if(uip_connr->len == 0) { ++ ++ /* The application cannot send more than what is allowed by ++ the mss (the minumum of the MSS and the available ++ window). */ ++ if(uip_slen > uip_connr->mss) { ++ uip_slen = uip_connr->mss; ++ } ++ ++ /* Remember how much data we send out now so that we know ++ when everything has been acknowledged. */ ++ uip_connr->len = uip_slen; ++ } else { ++ ++ /* If the application already had unacknowledged data, we ++ make sure that the application does not send (i.e., ++ retransmit) out more than it previously sent out. */ ++ uip_slen = uip_connr->len; ++ } ++ } else { ++ uip_connr->len = 0; ++ } ++ uip_connr->nrtx = 0; ++ apprexmit: ++ uip_appdata = uip_sappdata; ++ ++ /* If the application has data to be sent, or if the incoming ++ packet had new data in it, we must send out a packet. */ ++ if(uip_slen > 0 && uip_connr->len > 0) { ++ /* Add the length of the IP and TCP headers. */ ++ uip_len = uip_connr->len + UIP_TCPIP_HLEN; ++ /* We always set the ACK flag in response packets. */ ++ BUF->flags = TCP_ACK | TCP_PSH; ++ /* Send the packet. */ ++ goto tcp_send_noopts; ++ } ++ /* If there is no data to send, just send out a pure ACK if ++ there is newdata. */ ++ if(uip_flags & UIP_NEWDATA) { ++ uip_len = UIP_TCPIP_HLEN; ++ BUF->flags = TCP_ACK; ++ goto tcp_send_noopts; ++ } ++ } ++ goto drop; ++ case LAST_ACK: ++ /* We can close this connection if the peer has acknowledged our ++ FIN. This is indicated by the UIP_ACKDATA flag. */ ++ if(uip_flags & UIP_ACKDATA) { ++ uip_connr->tcpstateflags = CLOSED; ++ uip_flags = UIP_CLOSE; ++ UIP_APPCALL(); ++ } ++ break; ++ ++ case FIN_WAIT_1: ++ /* The application has closed the connection, but the remote host ++ hasn't closed its end yet. Thus we do nothing but wait for a ++ FIN from the other side. */ ++ if(uip_len > 0) { ++ uip_add_rcv_nxt(uip_len); ++ } ++ if(BUF->flags & TCP_FIN) { ++ if(uip_flags & UIP_ACKDATA) { ++ uip_connr->tcpstateflags = TIME_WAIT; ++ uip_connr->timer = 0; ++ uip_connr->len = 0; ++ } else { ++ uip_connr->tcpstateflags = CLOSING; ++ } ++ uip_add_rcv_nxt(1); ++ uip_flags = UIP_CLOSE; ++ UIP_APPCALL(); ++ goto tcp_send_ack; ++ } else if(uip_flags & UIP_ACKDATA) { ++ uip_connr->tcpstateflags = FIN_WAIT_2; ++ uip_connr->len = 0; ++ goto drop; ++ } ++ if(uip_len > 0) { ++ goto tcp_send_ack; ++ } ++ goto drop; ++ ++ case FIN_WAIT_2: ++ if(uip_len > 0) { ++ uip_add_rcv_nxt(uip_len); ++ } ++ if(BUF->flags & TCP_FIN) { ++ uip_connr->tcpstateflags = TIME_WAIT; ++ uip_connr->timer = 0; ++ uip_add_rcv_nxt(1); ++ uip_flags = UIP_CLOSE; ++ UIP_APPCALL(); ++ goto tcp_send_ack; ++ } ++ if(uip_len > 0) { ++ goto tcp_send_ack; ++ } ++ goto drop; ++ ++ case TIME_WAIT: ++ goto tcp_send_ack; ++ ++ case CLOSING: ++ if(uip_flags & UIP_ACKDATA) { ++ uip_connr->tcpstateflags = TIME_WAIT; ++ uip_connr->timer = 0; ++ } ++ } ++ goto drop; ++ ++ ++ /* We jump here when we are ready to send the packet, and just want ++ to set the appropriate TCP sequence numbers in the TCP header. */ ++ tcp_send_ack: ++ BUF->flags = TCP_ACK; ++ tcp_send_nodata: ++ uip_len = 40; ++ tcp_send_noopts: ++ BUF->tcpoffset = 5 << 4; ++ tcp_send: ++ /* We're done with the input processing. We are now ready to send a ++ reply. Our job is to fill in all the fields of the TCP and IP ++ headers before calculating the checksum and finally send the ++ packet. */ ++ BUF->ackno[0] = uip_connr->rcv_nxt[0]; ++ BUF->ackno[1] = uip_connr->rcv_nxt[1]; ++ BUF->ackno[2] = uip_connr->rcv_nxt[2]; ++ BUF->ackno[3] = uip_connr->rcv_nxt[3]; ++ ++ BUF->seqno[0] = uip_connr->snd_nxt[0]; ++ BUF->seqno[1] = uip_connr->snd_nxt[1]; ++ BUF->seqno[2] = uip_connr->snd_nxt[2]; ++ BUF->seqno[3] = uip_connr->snd_nxt[3]; ++ ++ BUF->proto = UIP_PROTO_TCP; ++ ++ BUF->srcport = uip_connr->lport; ++ BUF->destport = uip_connr->rport; ++ ++ BUF->srcipaddr[0] = uip_hostaddr[0]; ++ BUF->srcipaddr[1] = uip_hostaddr[1]; ++ BUF->destipaddr[0] = uip_connr->ripaddr[0]; ++ BUF->destipaddr[1] = uip_connr->ripaddr[1]; ++ ++ ++ if(uip_connr->tcpstateflags & UIP_STOPPED) { ++ /* If the connection has issued uip_stop(), we advertise a zero ++ window so that the remote host will stop sending data. */ ++ BUF->wnd[0] = BUF->wnd[1] = 0; ++ } else { ++ BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8); ++ BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff); ++ } ++ ++ tcp_send_noconn: ++ ++ BUF->len[0] = (uip_len >> 8); ++ BUF->len[1] = (uip_len & 0xff); ++ ++ /* Calculate TCP checksum. */ ++ BUF->tcpchksum = 0; ++ BUF->tcpchksum = ~(uip_tcpchksum()); ++ ++ //ip_send_nolen: ++ ++ BUF->vhl = 0x45; ++ BUF->tos = 0; ++ BUF->ipoffset[0] = BUF->ipoffset[1] = 0; ++ BUF->ttl = UIP_TTL; ++ ++ipid; ++ BUF->ipid[0] = ipid >> 8; ++ BUF->ipid[1] = ipid & 0xff; ++ ++ /* Calculate IP checksum. */ ++ BUF->ipchksum = 0; ++ BUF->ipchksum = ~(uip_ipchksum()); ++ ++ UIP_STAT(++uip_stat.tcp.sent); ++ send: ++ UIP_STAT(++uip_stat.ip.sent); ++ /* Return and let the caller do the actual transmission. */ ++ return; ++ drop: ++ uip_len = 0; ++ return; ++} ++/*-----------------------------------------------------------------------------------*/ ++/*unsigned short int ++htons(unsigned short int val) ++{ ++ return HTONS(val); ++}*/ ++/*-----------------------------------------------------------------------------------*/ ++/** @} */ +--- /dev/null ++++ b/net/uip-0.9/uip.h +@@ -0,0 +1,1066 @@ ++/** ++ * \addtogroup uip ++ * @{ ++ */ ++ ++/** ++ * \file ++ * Header file for the uIP TCP/IP stack. ++ * \author Adam Dunkels ++ * ++ * The uIP TCP/IP stack header file contains definitions for a number ++ * of C macros that are used by uIP programs as well as internal uIP ++ * structures, TCP/IP header structures and function declarations. ++ * ++ */ ++ ++ ++/* ++ * Copyright (c) 2001-2003, Adam Dunkels. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: uip.h,v 1.36.2.7 2003/10/07 13:47:51 adam Exp $ ++ * ++ */ ++ ++#ifndef __UIP_H__ ++#define __UIP_H__ ++#include ++#include ++#include ++#include ++#include ++ ++ ++#include "uipopt.h" ++ ++/*-----------------------------------------------------------------------------------*/ ++/* First, the functions that should be called from the ++ * system. Initialization, the periodic timer and incoming packets are ++ * handled by the following three functions. ++ */ ++ ++/** ++ * \defgroup uipconffunc uIP configuration functions ++ * @{ ++ * ++ * The uIP configuration functions are used for setting run-time ++ * parameters in uIP such as IP addresses. ++ */ ++ ++/** ++ * Set the IP address of this host. ++ * ++ * The IP address is represented as a 4-byte array where the first ++ * octet of the IP address is put in the first member of the 4-byte ++ * array. ++ * ++ * \param addr A pointer to a 4-byte representation of the IP address. ++ * ++ * \hideinitializer ++ */ ++#define uip_sethostaddr(addr) do { uip_hostaddr[0] = addr[0]; \ ++ uip_hostaddr[1] = addr[1]; } while(0) ++ ++/** ++ * Get the IP address of this host. ++ * ++ * The IP address is represented as a 4-byte array where the first ++ * octet of the IP address is put in the first member of the 4-byte ++ * array. ++ * ++ * \param addr A pointer to a 4-byte array that will be filled in with ++ * the currently configured IP address. ++ * ++ * \hideinitializer ++ */ ++#define uip_gethostaddr(addr) do { addr[0] = uip_hostaddr[0]; \ ++ addr[1] = uip_hostaddr[1]; } while(0) ++ ++/** @} */ ++ ++/** ++ * \defgroup uipinit uIP initialization functions ++ * @{ ++ * ++ * The uIP initialization functions are used for booting uIP. ++ */ ++ ++/** ++ * uIP initialization function. ++ * ++ * This function should be called at boot up to initilize the uIP ++ * TCP/IP stack. ++ */ ++void uip_init(void); ++ ++/** @} */ ++ ++/** ++ * \defgroup uipdevfunc uIP device driver functions ++ * @{ ++ * ++ * These functions are used by a network device driver for interacting ++ * with uIP. ++ */ ++ ++/** ++ * Process an incoming packet. ++ * ++ * This function should be called when the device driver has received ++ * a packet from the network. The packet from the device driver must ++ * be present in the uip_buf buffer, and the length of the packet ++ * should be placed in the uip_len variable. ++ * ++ * When the function returns, there may be an outbound packet placed ++ * in the uip_buf packet buffer. If so, the uip_len variable is set to ++ * the length of the packet. If no packet is to be sent out, the ++ * uip_len variable is set to 0. ++ * ++ * The usual way of calling the function is presented by the source ++ * code below. ++ \code ++ uip_len = devicedriver_poll(); ++ if(uip_len > 0) { ++ uip_input(); ++ if(uip_len > 0) { ++ devicedriver_send(); ++ } ++ } ++ \endcode ++ * ++ * \note If you are writing a uIP device driver that needs ARP ++ * (Address Resolution Protocol), e.g., when running uIP over ++ * Ethernet, you will need to call the uIP ARP code before calling ++ * this function: ++ \code ++ #define BUF ((struct uip_eth_hdr *)&uip_buf[0]) ++ uip_len = ethernet_devicedrver_poll(); ++ if(uip_len > 0) { ++ if(BUF->type == HTONS(UIP_ETHTYPE_IP)) { ++ uip_arp_ipin(); ++ uip_input(); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ ethernet_devicedriver_send(); ++ } ++ } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) { ++ uip_arp_arpin(); ++ if(uip_len > 0) { ++ ethernet_devicedriver_send(); ++ } ++ } ++ \endcode ++ * ++ * \hideinitializer ++ */ ++#define uip_input() uip_process(UIP_DATA) ++ ++/** ++ * Periodic processing for a connection identified by its number. ++ * ++ * This function does the necessary periodic processing (timers, ++ * polling) for a uIP TCP conneciton, and should be called when the ++ * periodic uIP timer goes off. It should be called for every ++ * connection, regardless of whether they are open of closed. ++ * ++ * When the function returns, it may have an outbound packet waiting ++ * for service in the uIP packet buffer, and if so the uip_len ++ * variable is set to a value larger than zero. The device driver ++ * should be called to send out the packet. ++ * ++ * The ususal way of calling the function is through a for() loop like ++ * this: ++ \code ++ for(i = 0; i < UIP_CONNS; ++i) { ++ uip_periodic(i); ++ if(uip_len > 0) { ++ devicedriver_send(); ++ } ++ } ++ \endcode ++ * ++ * \note If you are writing a uIP device driver that needs ARP ++ * (Address Resolution Protocol), e.g., when running uIP over ++ * Ethernet, you will need to call the uip_arp_out() function before ++ * calling the device driver: ++ \code ++ for(i = 0; i < UIP_CONNS; ++i) { ++ uip_periodic(i); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ ethernet_devicedriver_send(); ++ } ++ } ++ \endcode ++ * ++ * \param conn The number of the connection which is to be periodically polled. ++ * ++ * \hideinitializer ++ */ ++#define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \ ++ uip_process(UIP_TIMER); } while (0) ++ ++/** ++ * Periodic processing for a connection identified by a pointer to its structure. ++ * ++ * Same as uip_periodic() but takes a pointer to the actual uip_conn ++ * struct instead of an integer as its argument. This function can be ++ * used to force periodic processing of a specific connection. ++ * ++ * \param conn A pointer to the uip_conn struct for the connection to ++ * be processed. ++ * ++ * \hideinitializer ++ */ ++#define uip_periodic_conn(conn) do { uip_conn = conn; \ ++ uip_process(UIP_TIMER); } while (0) ++ ++#if UIP_UDP ++/** ++ * Periodic processing for a UDP connection identified by its number. ++ * ++ * This function is essentially the same as uip_prerioic(), but for ++ * UDP connections. It is called in a similar fashion as the ++ * uip_periodic() function: ++ \code ++ for(i = 0; i < UIP_UDP_CONNS; i++) { ++ uip_udp_periodic(i); ++ if(uip_len > 0) { ++ devicedriver_send(); ++ } ++ } ++ \endcode ++ * ++ * \note As for the uip_periodic() function, special care has to be ++ * taken when using uIP together with ARP and Ethernet: ++ \code ++ for(i = 0; i < UIP_UDP_CONNS; i++) { ++ uip_udp_periodic(i); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ ethernet_devicedriver_send(); ++ } ++ } ++ \endcode ++ * ++ * \param conn The number of the UDP connection to be processed. ++ * ++ * \hideinitializer ++ */ ++#define uip_udp_periodic(conn) do { uip_udp_conn = &uip_udp_conns[conn]; \ ++ uip_process(UIP_UDP_TIMER); } while (0) ++ ++/** ++ * Periodic processing for a UDP connection identified by a pointer to ++ * its structure. ++ * ++ * Same as uip_udp_periodic() but takes a pointer to the actual ++ * uip_conn struct instead of an integer as its argument. This ++ * function can be used to force periodic processing of a specific ++ * connection. ++ * ++ * \param conn A pointer to the uip_udp_conn struct for the connection ++ * to be processed. ++ * ++ * \hideinitializer ++ */ ++#define uip_udp_periodic_conn(conn) do { uip_udp_conn = conn; \ ++ uip_process(UIP_UDP_TIMER); } while (0) ++ ++ ++#endif /* UIP_UDP */ ++ ++/** ++ * The uIP packet buffer. ++ * ++ * The uip_buf array is used to hold incoming and outgoing ++ * packets. The device driver should place incoming data into this ++ * buffer. When sending data, the device driver should read the link ++ * level headers and the TCP/IP headers from this buffer. The size of ++ * the link level headers is configured by the UIP_LLH_LEN define. ++ * ++ * \note The application data need not be placed in this buffer, so ++ * the device driver must read it from the place pointed to by the ++ * uip_appdata pointer as illustrated by the following example: ++ \code ++ void ++ devicedriver_send(void) ++ { ++ hwsend(&uip_buf[0], UIP_LLH_LEN); ++ hwsend(&uip_buf[UIP_LLH_LEN], 40); ++ hwsend(uip_appdata, uip_len - 40 - UIP_LLH_LEN); ++ } ++ \endcode ++ */ ++extern u8_t uip_buf[UIP_BUFSIZE+2]; ++ ++/** @} */ ++ ++/*-----------------------------------------------------------------------------------*/ ++/* Functions that are used by the uIP application program. Opening and ++ * closing connections, sending and receiving data, etc. is all ++ * handled by the functions below. ++*/ ++/** ++ * \defgroup uipappfunc uIP application functions ++ * @{ ++ * ++ * Functions used by an application running of top of uIP. ++ */ ++ ++/** ++ * Start listening to the specified port. ++ * ++ * \note Since this function expects the port number in network byte ++ * order, a conversion using HTONS() or htons() is necessary. ++ * ++ \code ++ uip_listen(HTONS(80)); ++ \endcode ++ * ++ * \param port A 16-bit port number in network byte order. ++ */ ++void uip_listen(u16_t port); ++ ++/** ++ * Stop listening to the specified port. ++ * ++ * \note Since this function expects the port number in network byte ++ * order, a conversion using HTONS() or htons() is necessary. ++ * ++ \code ++ uip_unlisten(HTONS(80)); ++ \endcode ++ * ++ * \param port A 16-bit port number in network byte order. ++ */ ++void uip_unlisten(u16_t port); ++ ++/** ++ * Connect to a remote host using TCP. ++ * ++ * This function is used to start a new connection to the specified ++ * port on the specied host. It allocates a new connection identifier, ++ * sets the connection to the SYN_SENT state and sets the ++ * retransmission timer to 0. This will cause a TCP SYN segment to be ++ * sent out the next time this connection is periodically processed, ++ * which usually is done within 0.5 seconds after the call to ++ * uip_connect(). ++ * ++ * \note This function is avaliable only if support for active open ++ * has been configured by defining UIP_ACTIVE_OPEN to 1 in uipopt.h. ++ * ++ * \note Since this function requires the port number to be in network ++ * byte order, a convertion using HTONS() or htons() is necessary. ++ * ++ \code ++ u16_t ipaddr[2]; ++ ++ uip_ipaddr(ipaddr, 192,168,1,2); ++ uip_connect(ipaddr, HTONS(80)); ++ \endcode ++ * ++ * \param ripaddr A pointer to a 4-byte array representing the IP ++ * address of the remote hot. ++ * ++ * \param port A 16-bit port number in network byte order. ++ * ++ * \return A pointer to the uIP connection identifier for the new connection, ++ * or NULL if no connection could be allocated. ++ * ++ */ ++struct uip_conn *uip_connect(u16_t *ripaddr, u16_t port); ++ ++ ++ ++/** ++ * \internal ++ * ++ * Check if a connection has outstanding (i.e., unacknowledged) data. ++ * ++ * \param conn A pointer to the uip_conn structure for the connection. ++ * ++ * \hideinitializer ++ */ ++#define uip_outstanding(conn) ((conn)->len) ++ ++/** ++ * Send data on the current connection. ++ * ++ * This function is used to send out a single segment of TCP ++ * data. Only applications that have been invoked by uIP for event ++ * processing can send data. ++ * ++ * The amount of data that actually is sent out after a call to this ++ * funcion is determined by the maximum amount of data TCP allows. uIP ++ * will automatically crop the data so that only the appropriate ++ * amount of data is sent. The function uip_mss() can be used to query ++ * uIP for the amount of data that actually will be sent. ++ * ++ * \note This function does not guarantee that the sent data will ++ * arrive at the destination. If the data is lost in the network, the ++ * application will be invoked with the uip_rexmit() event being ++ * set. The application will then have to resend the data using this ++ * function. ++ * ++ * \param data A pointer to the data which is to be sent. ++ * ++ * \param len The maximum amount of data bytes to be sent. ++ * ++ * \hideinitializer ++ */ ++#define uip_send(data, len) do { uip_sappdata = (data); uip_slen = (len);} while(0) ++ ++/** ++ * The length of any incoming data that is currently avaliable (if avaliable) ++ * in the uip_appdata buffer. ++ * ++ * The test function uip_data() must first be used to check if there ++ * is any data available at all. ++ * ++ * \hideinitializer ++ */ ++#define uip_datalen() uip_len ++ ++/** ++ * The length of any out-of-band data (urgent data) that has arrived ++ * on the connection. ++ * ++ * \note The configuration parameter UIP_URGDATA must be set for this ++ * function to be enabled. ++ * ++ * \hideinitializer ++ */ ++#define uip_urgdatalen() uip_urglen ++ ++/** ++ * Close the current connection. ++ * ++ * This function will close the current connection in a nice way. ++ * ++ * \hideinitializer ++ */ ++#define uip_close() (uip_flags = UIP_CLOSE) ++ ++/** ++ * Abort the current connection. ++ * ++ * This function will abort (reset) the current connection, and is ++ * usually used when an error has occured that prevents using the ++ * uip_close() function. ++ * ++ * \hideinitializer ++ */ ++#define uip_abort() (uip_flags = UIP_ABORT) ++ ++/** ++ * Tell the sending host to stop sending data. ++ * ++ * This function will close our receiver's window so that we stop ++ * receiving data for the current connection. ++ * ++ * \hideinitializer ++ */ ++#define uip_stop() (uip_conn->tcpstateflags |= UIP_STOPPED) ++ ++/** ++ * Find out if the current connection has been previously stopped with ++ * uip_stop(). ++ * ++ * \hideinitializer ++ */ ++#define uip_stopped(conn) ((conn)->tcpstateflags & UIP_STOPPED) ++ ++/** ++ * Restart the current connection, if is has previously been stopped ++ * with uip_stop(). ++ * ++ * This function will open the receiver's window again so that we ++ * start receiving data for the current connection. ++ * ++ * \hideinitializer ++ */ ++#define uip_restart() do { uip_flags |= UIP_NEWDATA; \ ++ uip_conn->tcpstateflags &= ~UIP_STOPPED; \ ++ } while(0) ++ ++ ++/* uIP tests that can be made to determine in what state the current ++ connection is, and what the application function should do. */ ++ ++/** ++ * Is new incoming data available? ++ * ++ * Will reduce to non-zero if there is new data for the application ++ * present at the uip_appdata pointer. The size of the data is ++ * avaliable through the uip_len variable. ++ * ++ * \hideinitializer ++ */ ++#define uip_newdata() (uip_flags & UIP_NEWDATA) ++ ++/** ++ * Has previously sent data been acknowledged? ++ * ++ * Will reduce to non-zero if the previously sent data has been ++ * acknowledged by the remote host. This means that the application ++ * can send new data. ++ * ++ * \hideinitializer ++ */ ++#define uip_acked() (uip_flags & UIP_ACKDATA) ++ ++/** ++ * Has the connection just been connected? ++ * ++ * Reduces to non-zero if the current connection has been connected to ++ * a remote host. This will happen both if the connection has been ++ * actively opened (with uip_connect()) or passively opened (with ++ * uip_listen()). ++ * ++ * \hideinitializer ++ */ ++#define uip_connected() (uip_flags & UIP_CONNECTED) ++ ++/** ++ * Has the connection been closed by the other end? ++ * ++ * Is non-zero if the connection has been closed by the remote ++ * host. The application may then do the necessary clean-ups. ++ * ++ * \hideinitializer ++ */ ++#define uip_closed() (uip_flags & UIP_CLOSE) ++ ++/** ++ * Has the connection been aborted by the other end? ++ * ++ * Non-zero if the current connection has been aborted (reset) by the ++ * remote host. ++ * ++ * \hideinitializer ++ */ ++#define uip_aborted() (uip_flags & UIP_ABORT) ++ ++/** ++ * Has the connection timed out? ++ * ++ * Non-zero if the current connection has been aborted due to too many ++ * retransmissions. ++ * ++ * \hideinitializer ++ */ ++#define uip_timedout() (uip_flags & UIP_TIMEDOUT) ++ ++/** ++ * Do we need to retransmit previously data? ++ * ++ * Reduces to non-zero if the previously sent data has been lost in ++ * the network, and the application should retransmit it. The ++ * application should send the exact same data as it did the last ++ * time, using the uip_send() function. ++ * ++ * \hideinitializer ++ */ ++#define uip_rexmit() (uip_flags & UIP_REXMIT) ++ ++/** ++ * Is the connection being polled by uIP? ++ * ++ * Is non-zero if the reason the application is invoked is that the ++ * current connection has been idle for a while and should be ++ * polled. ++ * ++ * The polling event can be used for sending data without having to ++ * wait for the remote host to send data. ++ * ++ * \hideinitializer ++ */ ++#define uip_poll() (uip_flags & UIP_POLL) ++ ++/** ++ * Get the initial maxium segment size (MSS) of the current ++ * connection. ++ * ++ * \hideinitializer ++ */ ++#define uip_initialmss() (uip_conn->initialmss) ++ ++/** ++ * Get the current maxium segment size that can be sent on the current ++ * connection. ++ * ++ * The current maxiumum segment size that can be sent on the ++ * connection is computed from the receiver's window and the MSS of ++ * the connection (which also is available by calling ++ * uip_initialmss()). ++ * ++ * \hideinitializer ++ */ ++#define uip_mss() (uip_conn->mss) ++ ++/** ++ * Set up a new UDP connection. ++ * ++ * \param ripaddr A pointer to a 4-byte structure representing the IP ++ * address of the remote host. ++ * ++ * \param rport The remote port number in network byte order. ++ * ++ * \return The uip_udp_conn structure for the new connection or NULL ++ * if no connection could be allocated. ++ */ ++struct uip_udp_conn *uip_udp_new(u16_t *ripaddr, u16_t rport); ++ ++/** ++ * Removed a UDP connection. ++ * ++ * \param conn A pointer to the uip_udp_conn structure for the connection. ++ * ++ * \hideinitializer ++ */ ++#define uip_udp_remove(conn) (conn)->lport = 0 ++ ++/** ++ * Send a UDP datagram of length len on the current connection. ++ * ++ * This function can only be called in response to a UDP event (poll ++ * or newdata). The data must be present in the uip_buf buffer, at the ++ * place pointed to by the uip_appdata pointer. ++ * ++ * \param len The length of the data in the uip_buf buffer. ++ * ++ * \hideinitializer ++ */ ++#define uip_udp_send(len) uip_slen = (len) ++ ++/** @} */ ++ ++/* uIP convenience and converting functions. */ ++ ++/** ++ * \defgroup uipconvfunc uIP conversion functions ++ * @{ ++ * ++ * These functions can be used for converting between different data ++ * formats used by uIP. ++ */ ++ ++/** ++ * Pack an IP address into a 4-byte array which is used by uIP to ++ * represent IP addresses. ++ * ++ * Example: ++ \code ++ u16_t ipaddr[2]; ++ ++ uip_ipaddr(&ipaddr, 192,168,1,2); ++ \endcode ++ * ++ * \param addr A pointer to a 4-byte array that will be filled in with ++ * the IP addres. ++ * \param addr0 The first octet of the IP address. ++ * \param addr1 The second octet of the IP address. ++ * \param addr2 The third octet of the IP address. ++ * \param addr3 The forth octet of the IP address. ++ * ++ * \hideinitializer ++ */ ++#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \ ++ (addr)[0] = HTONS(((addr0) << 8) | (addr1)); \ ++ (addr)[1] = HTONS(((addr2) << 8) | (addr3)); \ ++ } while(0) ++ ++/** ++ * Convert 16-bit quantity from host byte order to network byte order. ++ * ++ * This macro is primarily used for converting constants from host ++ * byte order to network byte order. For converting variables to ++ * network byte order, use the htons() function instead. ++ * ++ * \hideinitializer ++ */ ++#ifndef HTONS ++# if BYTE_ORDER == BIG_ENDIAN ++# define HTONS(n) (n) ++# else /* BYTE_ORDER == BIG_ENDIAN */ ++# define HTONS(n) ((((u16_t)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8)) ++# endif /* BYTE_ORDER == BIG_ENDIAN */ ++#endif /* HTONS */ ++ ++/** ++ * Convert 16-bit quantity from host byte order to network byte order. ++ * ++ * This function is primarily used for converting variables from host ++ * byte order to network byte order. For converting constants to ++ * network byte order, use the HTONS() macro instead. ++ */ ++#ifndef htons ++u16_t htons(u16_t val); ++#endif /* htons */ ++ ++/** @} */ ++ ++/** ++ * Pointer to the application data in the packet buffer. ++ * ++ * This pointer points to the application data when the application is ++ * called. If the application wishes to send data, the application may ++ * use this space to write the data into before calling uip_send(). ++ */ ++extern volatile u8_t *uip_appdata; ++extern volatile u8_t *uip_sappdata; ++ ++#if UIP_URGDATA > 0 ++/* u8_t *uip_urgdata: ++ * ++ * This pointer points to any urgent data that has been received. Only ++ * present if compiled with support for urgent data (UIP_URGDATA). ++ */ ++extern volatile u8_t *uip_urgdata; ++#endif /* UIP_URGDATA > 0 */ ++ ++ ++/* u[8|16]_t uip_len: ++ * ++ * When the application is called, uip_len contains the length of any ++ * new data that has been received from the remote host. The ++ * application should set this variable to the size of any data that ++ * the application wishes to send. When the network device driver ++ * output function is called, uip_len should contain the length of the ++ * outgoing packet. ++ */ ++extern volatile u16_t uip_len, uip_slen; ++ ++#if UIP_URGDATA > 0 ++extern volatile u8_t uip_urglen, uip_surglen; ++#endif /* UIP_URGDATA > 0 */ ++ ++ ++/** ++ * Representation of a uIP TCP connection. ++ * ++ * The uip_conn structure is used for identifying a connection. All ++ * but one field in the structure are to be considered read-only by an ++ * application. The only exception is the appstate field whos purpose ++ * is to let the application store application-specific state (e.g., ++ * file pointers) for the connection. The size of this field is ++ * configured in the "uipopt.h" header file. ++ */ ++struct uip_conn { ++ u16_t ripaddr[2]; /**< The IP address of the remote host. */ ++ ++ u16_t lport; /**< The local TCP port, in network byte order. */ ++ u16_t rport; /**< The local remote TCP port, in network byte ++ order. */ ++ ++ u8_t rcv_nxt[4]; /**< The sequence number that we expect to ++ receive next. */ ++ u8_t snd_nxt[4]; /**< The sequence number that was last sent by ++ us. */ ++ u16_t len; /**< Length of the data that was previously sent. */ ++ u16_t mss; /**< Current maximum segment size for the ++ connection. */ ++ u16_t initialmss; /**< Initial maximum segment size for the ++ connection. */ ++ u8_t sa; /**< Retransmission time-out calculation state ++ variable. */ ++ u8_t sv; /**< Retransmission time-out calculation state ++ variable. */ ++ u8_t rto; /**< Retransmission time-out. */ ++ u8_t tcpstateflags; /**< TCP state and flags. */ ++ u8_t timer; /**< The retransmission timer. */ ++ u8_t nrtx; /**< The number of retransmissions for the last ++ segment sent. */ ++ ++ /** The application state. */ ++ u8_t appstate[UIP_APPSTATE_SIZE]; ++}; ++ ++ ++/* Pointer to the current connection. */ ++extern struct uip_conn *uip_conn; ++/* The array containing all uIP connections. */ ++extern struct uip_conn uip_conns[UIP_CONNS]; ++/** ++ * \addtogroup uiparch ++ * @{ ++ */ ++ ++/** ++ * 4-byte array used for the 32-bit sequence number calculations. ++ */ ++extern volatile u8_t uip_acc32[4]; ++ ++/** @} */ ++ ++ ++#if UIP_UDP ++/** ++ * Representation of a uIP UDP connection. ++ */ ++struct uip_udp_conn { ++ u16_t ripaddr[2]; /**< The IP address of the remote peer. */ ++ u16_t lport; /**< The local port number in network byte order. */ ++ u16_t rport; /**< The remote port number in network byte order. */ ++}; ++ ++extern struct uip_udp_conn *uip_udp_conn; ++extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; ++#endif /* UIP_UDP */ ++ ++/** ++ * The structure holding the TCP/IP statistics that are gathered if ++ * UIP_STATISTICS is set to 1. ++ * ++ */ ++struct uip_stats { ++ struct { ++ uip_stats_t drop; /**< Number of dropped packets at the IP ++ layer. */ ++ uip_stats_t recv; /**< Number of received packets at the IP ++ layer. */ ++ uip_stats_t sent; /**< Number of sent packets at the IP ++ layer. */ ++ uip_stats_t vhlerr; /**< Number of packets dropped due to wrong ++ IP version or header length. */ ++ uip_stats_t hblenerr; /**< Number of packets dropped due to wrong ++ IP length, high byte. */ ++ uip_stats_t lblenerr; /**< Number of packets dropped due to wrong ++ IP length, low byte. */ ++ uip_stats_t fragerr; /**< Number of packets dropped since they ++ were IP fragments. */ ++ uip_stats_t chkerr; /**< Number of packets dropped due to IP ++ checksum errors. */ ++ uip_stats_t protoerr; /**< Number of packets dropped since they ++ were neither ICMP, UDP nor TCP. */ ++ } ip; /**< IP statistics. */ ++ struct { ++ uip_stats_t drop; /**< Number of dropped ICMP packets. */ ++ uip_stats_t recv; /**< Number of received ICMP packets. */ ++ uip_stats_t sent; /**< Number of sent ICMP packets. */ ++ uip_stats_t typeerr; /**< Number of ICMP packets with a wrong ++ type. */ ++ } icmp; /**< ICMP statistics. */ ++ struct { ++ uip_stats_t drop; /**< Number of dropped TCP segments. */ ++ uip_stats_t recv; /**< Number of recived TCP segments. */ ++ uip_stats_t sent; /**< Number of sent TCP segments. */ ++ uip_stats_t chkerr; /**< Number of TCP segments with a bad ++ checksum. */ ++ uip_stats_t ackerr; /**< Number of TCP segments with a bad ACK ++ number. */ ++ uip_stats_t rst; /**< Number of recevied TCP RST (reset) segments. */ ++ uip_stats_t rexmit; /**< Number of retransmitted TCP segments. */ ++ uip_stats_t syndrop; /**< Number of dropped SYNs due to too few ++ connections was avaliable. */ ++ uip_stats_t synrst; /**< Number of SYNs for closed ports, ++ triggering a RST. */ ++ } tcp; /**< TCP statistics. */ ++}; ++ ++/** ++ * The uIP TCP/IP statistics. ++ * ++ * This is the variable in which the uIP TCP/IP statistics are gathered. ++ */ ++extern struct uip_stats uip_stat; ++ ++ ++/*-----------------------------------------------------------------------------------*/ ++/* All the stuff below this point is internal to uIP and should not be ++ * used directly by an application or by a device driver. ++ */ ++/*-----------------------------------------------------------------------------------*/ ++/* u8_t uip_flags: ++ * ++ * When the application is called, uip_flags will contain the flags ++ * that are defined in this file. Please read below for more ++ * infomation. ++ */ ++extern volatile u8_t uip_flags; ++ ++/* The following flags may be set in the global variable uip_flags ++ before calling the application callback. The UIP_ACKDATA and ++ UIP_NEWDATA flags may both be set at the same time, whereas the ++ others are mutualy exclusive. Note that these flags should *NOT* be ++ accessed directly, but through the uIP functions/macros. */ ++ ++#define UIP_ACKDATA 1 /* Signifies that the outstanding data was ++ acked and the application should send ++ out new data instead of retransmitting ++ the last data. */ ++#define UIP_NEWDATA 2 /* Flags the fact that the peer has sent ++ us new data. */ ++#define UIP_REXMIT 4 /* Tells the application to retransmit the ++ data that was last sent. */ ++#define UIP_POLL 8 /* Used for polling the application, to ++ check if the application has data that ++ it wants to send. */ ++#define UIP_CLOSE 16 /* The remote host has closed the ++ connection, thus the connection has ++ gone away. Or the application signals ++ that it wants to close the ++ connection. */ ++#define UIP_ABORT 32 /* The remote host has aborted the ++ connection, thus the connection has ++ gone away. Or the application signals ++ that it wants to abort the ++ connection. */ ++#define UIP_CONNECTED 64 /* We have got a connection from a remote ++ host and have set up a new connection ++ for it, or an active connection has ++ been successfully established. */ ++ ++#define UIP_TIMEDOUT 128 /* The connection has been aborted due to ++ too many retransmissions. */ ++ ++ ++/* uip_process(flag): ++ * ++ * The actual uIP function which does all the work. ++ */ ++void uip_process(u8_t flag); ++ ++/* The following flags are passed as an argument to the uip_process() ++ function. They are used to distinguish between the two cases where ++ uip_process() is called. It can be called either because we have ++ incoming data that should be processed, or because the periodic ++ timer has fired. */ ++ ++#define UIP_DATA 1 /* Tells uIP that there is incoming data in ++ the uip_buf buffer. The length of the ++ data is stored in the global variable ++ uip_len. */ ++#define UIP_TIMER 2 /* Tells uIP that the periodic timer has ++ fired. */ ++#if UIP_UDP ++#define UIP_UDP_TIMER 3 ++#endif /* UIP_UDP */ ++ ++/* The TCP states used in the uip_conn->tcpstateflags. */ ++#define CLOSED 0 ++#define SYN_RCVD 1 ++#define SYN_SENT 2 ++#define ESTABLISHED 3 ++#define FIN_WAIT_1 4 ++#define FIN_WAIT_2 5 ++#define CLOSING 6 ++#define TIME_WAIT 7 ++#define LAST_ACK 8 ++#define TS_MASK 15 ++ ++#define UIP_STOPPED 16 ++ ++#define UIP_TCPIP_HLEN 40 ++ ++/* The TCP and IP headers. */ ++typedef struct { ++ /* IP header. */ ++ u8_t vhl, ++ tos, ++ len[2], ++ ipid[2], ++ ipoffset[2], ++ ttl, ++ proto; ++ u16_t ipchksum; ++ u16_t srcipaddr[2], ++ destipaddr[2]; ++ ++ /* TCP header. */ ++ u16_t srcport, ++ destport; ++ u8_t seqno[4], ++ ackno[4], ++ tcpoffset, ++ flags, ++ wnd[2]; ++ u16_t tcpchksum; ++ u8_t urgp[2]; ++ u8_t optdata[4]; ++} uip_tcpip_hdr; ++ ++/* The ICMP and IP headers. */ ++typedef struct { ++ /* IP header. */ ++ u8_t vhl, ++ tos, ++ len[2], ++ ipid[2], ++ ipoffset[2], ++ ttl, ++ proto; ++ u16_t ipchksum; ++ u16_t srcipaddr[2], ++ destipaddr[2]; ++ /* ICMP (echo) header. */ ++ u8_t type, icode; ++ u16_t icmpchksum; ++ u16_t id, seqno; ++} uip_icmpip_hdr; ++ ++ ++/* The UDP and IP headers. */ ++typedef struct { ++ /* IP header. */ ++ u8_t vhl, ++ tos, ++ len[2], ++ ipid[2], ++ ipoffset[2], ++ ttl, ++ proto; ++ u16_t ipchksum; ++ u16_t srcipaddr[2], ++ destipaddr[2]; ++ ++ /* UDP header. */ ++ u16_t srcport, ++ destport; ++ u16_t udplen; ++ u16_t udpchksum; ++} uip_udpip_hdr; ++ ++#define UIP_PROTO_ICMP 1 ++#define UIP_PROTO_TCP 6 ++#define UIP_PROTO_UDP 17 ++ ++#if UIP_FIXEDADDR ++extern const u16_t uip_hostaddr[2]; ++#else /* UIP_FIXEDADDR */ ++extern u16_t uip_hostaddr[2]; ++#endif /* UIP_FIXEDADDR */ ++ ++#endif /* __UIP_H__ */ ++ ++ ++/** @} */ ++ +--- /dev/null ++++ b/net/uip-0.9/uipopt.h +@@ -0,0 +1,557 @@ ++/** ++ * \defgroup uipopt Configuration options for uIP ++ * @{ ++ * ++ * uIP is configured using the per-project configuration file ++ * "uipopt.h". This file contains all compile-time options for uIP and ++ * should be tweaked to match each specific project. The uIP ++ * distribution contains a documented example "uipopt.h" that can be ++ * copied and modified for each project. ++ */ ++ ++/** ++ * \file ++ * Configuration options for uIP. ++ * \author Adam Dunkels ++ * ++ * This file is used for tweaking various configuration options for ++ * uIP. You should make a copy of this file into one of your project's ++ * directories instead of editing this example "uipopt.h" file that ++ * comes with the uIP distribution. ++ */ ++ ++/* ++ * Copyright (c) 2001-2003, Adam Dunkels. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ++ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: uipopt.h,v 1.16.2.5 2003/10/07 13:22:51 adam Exp $ ++ * ++ */ ++ ++#ifndef __UIPOPT_H__ ++#define __UIPOPT_H__ ++ ++/*------------------------------------------------------------------------------*/ ++/** ++ * \defgroup uipopttypedef uIP type definitions ++ * @{ ++ */ ++ ++/** ++ * The 8-bit unsigned data type. ++ * ++ * This may have to be tweaked for your particular compiler. "unsigned ++ * char" works for most compilers. ++ */ ++typedef unsigned char u8_t; ++ ++/** ++ * The 16-bit unsigned data type. ++ * ++ * This may have to be tweaked for your particular compiler. "unsigned ++ * short" works for most compilers. ++ */ ++typedef unsigned short u16_t; ++ ++/** ++ * The statistics data type. ++ * ++ * This datatype determines how high the statistics counters are able ++ * to count. ++ */ ++typedef unsigned short uip_stats_t; ++ ++/** @} */ ++ ++/*------------------------------------------------------------------------------*/ ++ ++/** ++ * \defgroup uipoptstaticconf Static configuration options ++ * @{ ++ * ++ * These configuration options can be used for setting the IP address ++ * settings statically, but only if UIP_FIXEDADDR is set to 1. The ++ * configuration options for a specific node includes IP address, ++ * netmask and default router as well as the Ethernet address. The ++ * netmask, default router and Ethernet address are appliciable only ++ * if uIP should be run over Ethernet. ++ * ++ * All of these should be changed to suit your project. ++*/ ++ ++/** ++ * Determines if uIP should use a fixed IP address or not. ++ * ++ * If uIP should use a fixed IP address, the settings are set in the ++ * uipopt.h file. If not, the macros uip_sethostaddr(), ++ * uip_setdraddr() and uip_setnetmask() should be used instead. ++ * ++ * \hideinitializer ++ */ ++#define UIP_FIXEDADDR 0 ++ ++/** ++ * Ping IP address asignment. ++ * ++ * uIP uses a "ping" packets for setting its own IP address if this ++ * option is set. If so, uIP will start with an empty IP address and ++ * the destination IP address of the first incoming "ping" (ICMP echo) ++ * packet will be used for setting the hosts IP address. ++ * ++ * \note This works only if UIP_FIXEDADDR is 0. ++ * ++ * \hideinitializer ++ */ ++#define UIP_PINGADDRCONF 0 ++ ++#define UIP_IPADDR0 192 /**< The first octet of the IP address of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_IPADDR1 168 /**< The second octet of the IP address of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_IPADDR2 0 /**< The third octet of the IP address of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_IPADDR3 250 /**< The fourth octet of the IP address of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++ ++#define UIP_NETMASK0 255 /**< The first octet of the netmask of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_NETMASK1 255 /**< The second octet of the netmask of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_NETMASK2 255 /**< The third octet of the netmask of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_NETMASK3 0 /**< The fourth octet of the netmask of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++ ++#define UIP_DRIPADDR0 192 /**< The first octet of the IP address of ++ the default router, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_DRIPADDR1 168 /**< The second octet of the IP address of ++ the default router, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_DRIPADDR2 0 /**< The third octet of the IP address of ++ the default router, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_DRIPADDR3 1 /**< The fourth octet of the IP address of ++ the default router, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++ ++/** ++ * Specifies if the uIP ARP module should be compiled with a fixed ++ * Ethernet MAC address or not. ++ * ++ * If this configuration option is 0, the macro uip_setethaddr() can ++ * be used to specify the Ethernet address at run-time. ++ * ++ * \hideinitializer ++ */ ++#define UIP_FIXEDETHADDR 0 ++ ++#define UIP_ETHADDR0 0x00 /**< The first octet of the Ethernet ++ address if UIP_FIXEDETHADDR is ++ 1. \hideinitializer */ ++#define UIP_ETHADDR1 0xbd /**< The second octet of the Ethernet ++ address if UIP_FIXEDETHADDR is ++ 1. \hideinitializer */ ++#define UIP_ETHADDR2 0x3b /**< The third octet of the Ethernet ++ address if UIP_FIXEDETHADDR is ++ 1. \hideinitializer */ ++#define UIP_ETHADDR3 0x33 /**< The fourth octet of the Ethernet ++ address if UIP_FIXEDETHADDR is ++ 1. \hideinitializer */ ++#define UIP_ETHADDR4 0x05 /**< The fifth octet of the Ethernet ++ address if UIP_FIXEDETHADDR is ++ 1. \hideinitializer */ ++#define UIP_ETHADDR5 0x71 /**< The sixth octet of the Ethernet ++ address if UIP_FIXEDETHADDR is ++ 1. \hideinitializer */ ++ ++/** @} */ ++/*------------------------------------------------------------------------------*/ ++/** ++ * \defgroup uipoptip IP configuration options ++ * @{ ++ * ++ */ ++/** ++ * The IP TTL (time to live) of IP packets sent by uIP. ++ * ++ * This should normally not be changed. ++ */ ++#define UIP_TTL 255 ++ ++/** ++ * Turn on support for IP packet reassembly. ++ * ++ * uIP supports reassembly of fragmented IP packets. This features ++ * requires an additonal amount of RAM to hold the reassembly buffer ++ * and the reassembly code size is approximately 700 bytes. The ++ * reassembly buffer is of the same size as the uip_buf buffer ++ * (configured by UIP_BUFSIZE). ++ * ++ * \note IP packet reassembly is not heavily tested. ++ * ++ * \hideinitializer ++ */ ++#define UIP_REASSEMBLY 0 ++ ++/** ++ * The maximum time an IP fragment should wait in the reassembly ++ * buffer before it is dropped. ++ * ++ */ ++#define UIP_REASS_MAXAGE 40 ++ ++/** @} */ ++ ++/*------------------------------------------------------------------------------*/ ++/** ++ * \defgroup uipoptudp UDP configuration options ++ * @{ ++ * ++ * \note The UDP support in uIP is still not entirely complete; there ++ * is no support for sending or receiving broadcast or multicast ++ * packets, but it works well enough to support a number of vital ++ * applications such as DNS queries, though ++ */ ++ ++/** ++ * Toggles wether UDP support should be compiled in or not. ++ * ++ * \hideinitializer ++ */ ++#define UIP_UDP 0 ++ ++/** ++ * Toggles if UDP checksums should be used or not. ++ * ++ * \note Support for UDP checksums is currently not included in uIP, ++ * so this option has no function. ++ * ++ * \hideinitializer ++ */ ++#define UIP_UDP_CHECKSUMS 0 ++ ++/** ++ * The maximum amount of concurrent UDP connections. ++ * ++ * \hideinitializer ++ */ ++#define UIP_UDP_CONNS 10 ++ ++/** ++ * The name of the function that should be called when UDP datagrams arrive. ++ * ++ * \hideinitializer ++ */ ++#define UIP_UDP_APPCALL udp_appcall ++ ++/** @} */ ++/*------------------------------------------------------------------------------*/ ++/** ++ * \defgroup uipopttcp TCP configuration options ++ * @{ ++ */ ++ ++/** ++ * Determines if support for opening connections from uIP should be ++ * compiled in. ++ * ++ * If the applications that are running on top of uIP for this project ++ * do not need to open outgoing TCP connections, this configration ++ * option can be turned off to reduce the code size of uIP. ++ * ++ * \hideinitializer ++ */ ++#define UIP_ACTIVE_OPEN 1 ++ ++/** ++ * The maximum number of simultaneously open TCP connections. ++ * ++ * Since the TCP connections are statically allocated, turning this ++ * configuration knob down results in less RAM used. Each TCP ++ * connection requires approximatly 30 bytes of memory. ++ * ++ * \hideinitializer ++ */ ++#define UIP_CONNS 10 ++ ++/** ++ * The maximum number of simultaneously listening TCP ports. ++ * ++ * Each listening TCP port requires 2 bytes of memory. ++ * ++ * \hideinitializer ++ */ ++#define UIP_LISTENPORTS 10 ++ ++/** ++ * The size of the advertised receiver's window. ++ * ++ * Should be set low (i.e., to the size of the uip_buf buffer) is the ++ * application is slow to process incoming data, or high (32768 bytes) ++ * if the application processes data quickly. ++ * ++ * \hideinitializer ++ */ ++#define UIP_RECEIVE_WINDOW 32768 ++ ++/** ++ * Determines if support for TCP urgent data notification should be ++ * compiled in. ++ * ++ * Urgent data (out-of-band data) is a rarely used TCP feature that ++ * very seldom would be required. ++ * ++ * \hideinitializer ++ */ ++#define UIP_URGDATA 1 ++ ++/** ++ * The initial retransmission timeout counted in timer pulses. ++ * ++ * This should not be changed. ++ */ ++#define UIP_RTO 3 ++ ++/** ++ * The maximum number of times a segment should be retransmitted ++ * before the connection should be aborted. ++ * ++ * This should not be changed. ++ */ ++#define UIP_MAXRTX 8 ++ ++/** ++ * The maximum number of times a SYN segment should be retransmitted ++ * before a connection request should be deemed to have been ++ * unsuccessful. ++ * ++ * This should not need to be changed. ++ */ ++#define UIP_MAXSYNRTX 3 ++ ++/** ++ * The TCP maximum segment size. ++ * ++ * This is should not be to set to more than UIP_BUFSIZE - UIP_LLH_LEN - 40. ++ */ ++#define UIP_TCP_MSS (UIP_BUFSIZE - UIP_LLH_LEN - 40) ++ ++/** ++ * How long a connection should stay in the TIME_WAIT state. ++ * ++ * This configiration option has no real implication, and it should be ++ * left untouched. ++ */ ++#define UIP_TIME_WAIT_TIMEOUT 120 ++ ++ ++/** @} */ ++/*------------------------------------------------------------------------------*/ ++/** ++ * \defgroup uipoptarp ARP configuration options ++ * @{ ++ */ ++ ++/** ++ * The size of the ARP table. ++ * ++ * This option should be set to a larger value if this uIP node will ++ * have many connections from the local network. ++ * ++ * \hideinitializer ++ */ ++#define UIP_ARPTAB_SIZE 8 ++ ++/** ++ * The maxium age of ARP table entries measured in 10ths of seconds. ++ * ++ * An UIP_ARP_MAXAGE of 120 corresponds to 20 minutes (BSD ++ * default). ++ */ ++#define UIP_ARP_MAXAGE 120 ++ ++/** @} */ ++ ++/*------------------------------------------------------------------------------*/ ++ ++/** ++ * \defgroup uipoptgeneral General configuration options ++ * @{ ++ */ ++ ++/** ++ * The size of the uIP packet buffer. ++ * ++ * The uIP packet buffer should not be smaller than 60 bytes, and does ++ * not need to be larger than 1500 bytes. Lower size results in lower ++ * TCP throughput, larger size results in higher TCP throughput. ++ * ++ * \hideinitializer ++ */ ++#define UIP_BUFSIZE 1500 ++ ++ ++/** ++ * Determines if statistics support should be compiled in. ++ * ++ * The statistics is useful for debugging and to show the user. ++ * ++ * \hideinitializer ++ */ ++#define UIP_STATISTICS 1 ++ ++/** ++ * Determines if logging of certain events should be compiled in. ++ * ++ * This is useful mostly for debugging. The function uip_log() ++ * must be implemented to suit the architecture of the project, if ++ * logging is turned on. ++ * ++ * \hideinitializer ++ */ ++#define UIP_LOGGING 0 ++ ++/** ++ * Print out a uIP log message. ++ * ++ * This function must be implemented by the module that uses uIP, and ++ * is called by uIP whenever a log message is generated. ++ */ ++void uip_log(char *msg); ++ ++/** ++ * The link level header length. ++ * ++ * This is the offset into the uip_buf where the IP header can be ++ * found. For Ethernet, this should be set to 14. For SLIP, this ++ * should be set to 0. ++ * ++ * \hideinitializer ++ */ ++#define UIP_LLH_LEN 14 ++ ++ ++/** @} */ ++/*------------------------------------------------------------------------------*/ ++/** ++ * \defgroup uipoptcpu CPU architecture configuration ++ * @{ ++ * ++ * The CPU architecture configuration is where the endianess of the ++ * CPU on which uIP is to be run is specified. Most CPUs today are ++ * little endian, and the most notable exception are the Motorolas ++ * which are big endian. The BYTE_ORDER macro should be changed to ++ * reflect the CPU architecture on which uIP is to be run. ++ */ ++#ifndef LITTLE_ENDIAN ++#define LITTLE_ENDIAN 3412 ++#endif /* LITTLE_ENDIAN */ ++#ifndef BIG_ENDIAN ++#define BIG_ENDIAN 1234 ++#endif /* BIGE_ENDIAN */ ++ ++/** ++ * The byte order of the CPU architecture on which uIP is to be run. ++ * ++ * This option can be either BIG_ENDIAN (Motorola byte order) or ++ * LITTLE_ENDIAN (Intel byte order). ++ * ++ * \hideinitializer ++ */ ++/*#ifndef BYTE_ORDER*/ ++#define BYTE_ORDER BIG_ENDIAN ++/*#endif*/ /* BYTE_ORDER */ ++ ++/** @} */ ++/*------------------------------------------------------------------------------*/ ++ ++/** ++ * \defgroup uipoptapp Appication specific configurations ++ * @{ ++ * ++ * An uIP application is implemented using a single application ++ * function that is called by uIP whenever a TCP/IP event occurs. The ++ * name of this function must be registered with uIP at compile time ++ * using the UIP_APPCALL definition. ++ * ++ * uIP applications can store the application state within the ++ * uip_conn structure by specifying the size of the application ++ * structure with the UIP_APPSTATE_SIZE macro. ++ * ++ * The file containing the definitions must be included in the ++ * uipopt.h file. ++ * ++ * The following example illustrates how this can look. ++ \code ++ ++void httpd_appcall(void); ++#define UIP_APPCALL httpd_appcall ++ ++struct httpd_state { ++ u8_t state; ++ u16_t count; ++ char *dataptr; ++ char *script; ++}; ++#define UIP_APPSTATE_SIZE (sizeof(struct httpd_state)) ++ \endcode ++ */ ++ ++/** ++ * \var #define UIP_APPCALL ++ * ++ * The name of the application function that uIP should call in ++ * response to TCP/IP events. ++ * ++ */ ++ ++/** ++ * \var #define UIP_APPSTATE_SIZE ++ * ++ * The size of the application state that is to be stored in the ++ * uip_conn structure. ++ */ ++/** @} */ ++ ++/* Include the header file for the application program that should be ++ used. If you don't use the example web server, you should change ++ this. */ ++#include "httpd.h" ++ ++ ++#endif /* __UIPOPT_H__ */ diff --git a/rules.mk b/rules.mk index f913d9856..0cb72ac6b 100644 --- a/rules.mk +++ b/rules.mk @@ -104,7 +104,7 @@ TARGET_PATH:=$(STAGING_DIR_HOST)/bin:$(PATH) TARGET_CFLAGS:=$(TARGET_OPTIMIZATION)$(if $(CONFIG_DEBUG), -g3) TARGET_CPPFLAGS:=-I$(STAGING_DIR)/usr/include -I$(STAGING_DIR)/include TARGET_LDFLAGS:=-L$(STAGING_DIR)/usr/lib -L$(STAGING_DIR)/lib -LIBGCC_S=$(if $(wildcard $(TOOLCHAIN_DIR)/lib/libgcc_s.so),-L$(TOOLCHAIN_DIR)/lib -lgcc_s,$(wildcard $(TOOLCHAIN_DIR)/lib/gcc/*/*/libgcc.a)) +LIBGCC_S=$(if $(wildcard $(TOOLCHAIN_DIR)/lib/libgcc_s.so),-L$(TOOLCHAIN_DIR)/lib -lgcc_s,$(wildcard $(TOOLCHAIN_DIR)/usr/lib/gcc/*/*/libgcc.a)) ifndef DUMP ifeq ($(CONFIG_EXTERNAL_TOOLCHAIN),) diff --git a/target/imagebuilder/Config.in b/target/imagebuilder/Config.in index a31526599..23a418bf5 100644 --- a/target/imagebuilder/Config.in +++ b/target/imagebuilder/Config.in @@ -1,7 +1,6 @@ config IB bool "Build the OpenWrt Image Builder" depends !TARGET_ROOTFS_INITRAMFS - depends !TARGET_uml depends !PROFILE_KCONFIG depends !EXTERNAL_TOOLCHAIN help diff --git a/target/imagebuilder/Makefile b/target/imagebuilder/Makefile index 923c1e94b..e0b64ead4 100644 --- a/target/imagebuilder/Makefile +++ b/target/imagebuilder/Makefile @@ -31,17 +31,15 @@ $(BIN_DIR)/$(IB_NAME).tar.bz2: clean $(TMP_DIR)/.packageinfo \ $(PKG_BUILD_DIR)/ $(CP) $(PACKAGE_DIR) $(PKG_BUILD_DIR)/packages - $(CP) $(TOOLCHAIN_DIR)/bin $(PKG_BUILD_DIR)/staging_dir/host/ - $(CP) $(STAGING_DIR_HOST)/bin/* $(PKG_BUILD_DIR)/staging_dir/host/bin/ + $(CP) $(STAGING_DIR_HOST)/bin $(PKG_BUILD_DIR)/staging_dir/host/ $(CP) $(TOPDIR)/target/linux $(PKG_BUILD_DIR)/target/ rm -rf \ - $(PKG_BUILD_DIR)/target/linux/*/patches \ - $(PKG_BUILD_DIR)/target/linux/*/*/patches + $(PKG_BUILD_DIR)/target/linux/*/files{,-*} \ + $(PKG_BUILD_DIR)/target/linux/*/patches{,-*} -cp $(KERNEL_BUILD_DIR)/* $(IB_KDIR)/ # don't copy subdirectories here echo REVISION:="$(REVISION)" > $(PKG_BUILD_DIR)/include/version.mk - find $(PKG_BUILD_DIR) -name .svn | $(XARGS) rm -rf - find $(PKG_BUILD_DIR) -name CVS | $(XARGS) rm -rf - find $(PKG_BUILD_DIR) -name .git | $(XARGS) rm -rf + find $(PKG_BUILD_DIR) -name CVS -o -name .git -o -name .svn \ + | $(XARGS) rm -rf $(TAR) c -C $(BUILD_DIR) $(IB_NAME) | bzip2 -c > $@ download: diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/prom.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/prom.c index f635b4a6c..c9745746c 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/prom.c +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/prom.c @@ -21,25 +21,32 @@ void __init prom_init(int argc, const char **argv) { unsigned long mem; + unsigned long max; mips_machgroup = MACH_GROUP_BRCM; mips_machtype = MACH_BCM947XX; - /* Figure out memory size by finding aliases */ + /* Figure out memory size by finding aliases + * + * BCM47XX uses 128MB for addressing the ram, if the system contains + * less that that amount of ram it remaps the ram more often into the + * available space. + * Accessing memory after 128MB will cause an exception. + * max contains the biggest possible address supported by the platform. + * If the method wants to try something above we assume 128MB ram. + */ + max = ((unsigned long)(prom_init) | ((128 << 20) - 1)); for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) { + if (((unsigned long)(prom_init) + mem) > max) { + mem = (128 << 20); + printk("assume 128MB RAM\n"); + break; + } if (*(unsigned long *)((unsigned long)(prom_init) + mem) == *(unsigned long *)(prom_init)) break; } - /* Ignoring the last page when ddr size is 128M. Cached - * accesses to last page is causing the processor to prefetch - * using address above 128M stepping out of the ddr address - * space. - */ - if (mem == 0x8000000) - mem -= 0x1000; - add_memory_region(0, mem, BOOT_MEM_RAM); } diff --git a/target/linux/brcm63xx/files/arch/mips/include/asm/mach-bcm63xx/bcm_tag.h b/target/linux/brcm63xx/files/arch/mips/include/asm/mach-bcm63xx/bcm_tag.h index c06f66894..d79256272 100644 --- a/target/linux/brcm63xx/files/arch/mips/include/asm/mach-bcm63xx/bcm_tag.h +++ b/target/linux/brcm63xx/files/arch/mips/include/asm/mach-bcm63xx/bcm_tag.h @@ -1,178 +1,69 @@ #ifndef __BCM63XX_TAG_H #define __BCM63XX_TAG_H -#define IMAGE_LEN 10 /* Length of Length Field */ -#define ADDRESS_LEN 12 /* Length of Address field */ -#define TAGID_LEN 6 /* Length of tag ID */ -#define TAGINFO_LEN 20 /* Length of vendor information field in tag */ #define TAGVER_LEN 4 /* Length of Tag Version */ #define TAGLAYOUT_LEN 4 /* Length of FlashLayoutVer */ +#define SIG1_LEN 20 /* Company Signature 1 Length */ +#define SIG2_LEN 14 /* Company Signature 2 Lenght */ +#define BOARDID_LEN 16 /* Length of BoardId */ +#define ENDIANFLAG_LEN 2 /* Endian Flag Length */ +#define CHIPID_LEN 6 /* Chip Id Length */ +#define IMAGE_LEN 10 /* Length of Length Field */ +#define ADDRESS_LEN 12 /* Length of Address field */ +#define DUALFLAG_LEN 2 /* Dual Image flag Length */ +#define INACTIVEFLAG_LEN 2 /* Inactie Flag Length */ +#define RSASIG_LEN 20 /* Length of RSA Signature in tag */ +#define TAGINFO1_LEN 30 /* Length of vendor information field1 in tag */ +#define FLASHLAYOUTVER_LEN 4 /* Length of Flash Layout Version String tag */ +#define TAGINFO2_LEN 16 /* Length of vendor information field2 in tag */ +#define CRC_LEN 4 /* Length of CRC in bytes */ +#define ALTTAGINFO_LEN 54 /* Alternate length for vendor information; Pirelli */ -#define NUM_TAGID 5 +#define NUM_PIRELLI 2 #define IMAGETAG_CRC_START 0xFFFFFFFF -struct tagiddesc_t { - char tagid[TAGID_LEN + 1]; - char tagiddesc[80]; -}; - - // bc221 is used by BT Voyager and should be right - // bc310 should be right, and may apply to 3.08 code as well -#define TAGID_DEFINITIONS { \ - { "bccfe", "Broadcom CFE flash image" }, \ - { "bc300", "Broadcom code version 3.00-3.06 and all ftp/tftp flash" }, \ - { "ag306", "Alice Gate (Pirelli, based on Broadcom 3.06)" }, \ - { "bc221", "Broadcom code version 2.21" }, \ - { "bc310", "Broadcom code version 3.10-3.12" }, \ +#define PIRELLI_BOARDS { \ + "AGPF_S0", \ + "DWV_SO", \ } -struct bcm_tag_bccfe { - unsigned char tagVersion[TAGVER_LEN]; // 0-3: Version of the image tag - unsigned char sig_1[20]; // 4-23: Company Line 1 - unsigned char sig_2[14]; // 24-37: Company Line 2 - unsigned char chipid[6]; // 38-43: Chip this image is for - unsigned char boardid[16]; // 44-59: Board name - unsigned char big_endian[2]; // 60-61: Map endianness -- 1 BE 0 LE - unsigned char totalLength[IMAGE_LEN]; // 62-71: Total length of image - unsigned char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE - unsigned char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE - unsigned char rootAddress[ADDRESS_LEN]; // 94-105: Address in memory of rootfs - unsigned char rootLength[IMAGE_LEN]; // 106-115: Size of rootfs - unsigned char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel - unsigned char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel - unsigned char dualImage[2]; // 138-139: Unused at present - unsigned char inactiveFlag[2]; // 140-141: Unused at present - unsigned char information1[TAGINFO_LEN]; // 142-161: Unused at present - unsigned char tagId[TAGID_LEN]; // 162-167: Identifies which type of tag this is, currently two-letter company code, and then three digits for version of broadcom code in which this tag was first introduced - unsigned char tagIdCRC[4]; // 168-171: CRC32 of tagId - unsigned char reserved1[44]; // 172-215: Reserved area not in use - unsigned char imageCRC[4]; // 216-219: CRC32 of images - unsigned char reserved2[16]; // 220-235: Unused at present - unsigned char headerCRC[4]; // 236-239: CRC32 of header excluding tagVersion - unsigned char reserved3[16]; // 240-255: Unused at present -}; +/* + * The broadcom firmware assumes the rootfs starts the image, + * therefore uses the rootfs start (flashImageAddress) + * to determine where to flash the image. Since we have the kernel first + * we have to give it the kernel address, but the crc uses the length + * associated with this address (rootLength), which is added to the kernel + * length (kernelLength) to determine the length of image to flash and thus + * needs to be rootfs + deadcode (jffs2 EOF marker) +*/ -struct bcm_tag_bc300 { - unsigned char tagVersion[TAGVER_LEN]; // 0-3: Version of the image tag - unsigned char sig_1[20]; // 4-23: Company Line 1 - unsigned char sig_2[14]; // 24-37: Company Line 2 - unsigned char chipid[6]; // 38-43: Chip this image is for - unsigned char boardid[16]; // 44-59: Board name - unsigned char big_endian[2]; // 60-61: Map endianness -- 1 BE 0 LE - unsigned char totalLength[IMAGE_LEN]; // 62-71: Total length of image - unsigned char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE - unsigned char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE - unsigned char flashImageStart[ADDRESS_LEN]; // 94-105: Address in memory of kernel (start of image) - unsigned char flashRootLength[IMAGE_LEN]; // 106-115: Size of rootfs + deadcode (web flash uses this + kernelLength to determine the size of the kernel+rootfs flash image) - unsigned char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel - unsigned char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel - unsigned char dualImage[2]; // 138-139: Unused at present - unsigned char inactiveFlag[2]; // 140-141: Unused at present - unsigned char information1[TAGINFO_LEN]; // 142-161: Unused at present - unsigned char tagId[TAGID_LEN]; // 162-167: Identifies which type of tag this is, currently two-letter company code, and then three digits for version of broadcom code in which this tag was first introduced - unsigned char tagIdCRC[4]; // 168-173: CRC32 to ensure validity of tagId - unsigned char rootAddress[ADDRESS_LEN]; // 174-183: Address in memory of rootfs partition - unsigned char rootLength[IMAGE_LEN]; // 184-193: Size of rootfs partition - unsigned char reserved1[22]; // 194-215: Reserved area not in use - unsigned char imageCRC[4]; // 216-219: CRC32 of images - unsigned char reserved2[16]; // 220-235: Unused at present - unsigned char headerCRC[4]; // 236-239: CRC32 of header excluding tagVersion - unsigned char reserved3[16]; // 240-255: Unused at present -}; - -struct bcm_tag_ag306 { - unsigned char tagVersion[TAGVER_LEN]; // 0-3: Version of the image tag - unsigned char sig_1[20]; // 4-23: Company Line 1 - unsigned char sig_2[14]; // 24-37: Company Line 2 - unsigned char chipid[6]; // 38-43: Chip this image is for - unsigned char boardid[16]; // 44-59: Board name - unsigned char big_endian[2]; // 60-61: Map endianness -- 1 BE 0 LE - unsigned char totalLength[IMAGE_LEN]; // 62-71: Total length of image - unsigned char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE - unsigned char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE - unsigned char flashImageStart[ADDRESS_LEN]; // 94-105: Address in memory of kernel (start of image) - unsigned char flashRootLength[IMAGE_LEN]; // 106-115: Size of rootfs + deadcode (web flash uses this + kernelLength to determine the size of the kernel+rootfs flash image) - unsigned char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel - unsigned char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel - unsigned char dualImage[2]; // 138-139: Unused at present - unsigned char inactiveFlag[2]; // 140-141: Unused at present - unsigned char information1[TAGINFO_LEN]; // 142-161: Unused at present - unsigned char information2[54]; // 162-215: Compilation and related information (not generated/used by OpenWRT) - unsigned char kernelCRC[4] ; // 216-219: CRC32 of images - unsigned char rootAddress[ADDRESS_LEN]; // 220-231: Address in memory of rootfs partition - unsigned char tagIdCRC[4]; // 232-235: Checksum to ensure validity of tagId - unsigned char headerCRC[4]; // 236-239: CRC32 of header excluding tagVersion - unsigned char rootLength[IMAGE_LEN]; // 240-249: Size of rootfs - unsigned char tagId[TAGID_LEN]; // 250-255: Identifies which type of tag this is, currently two-letter company code, and then three digits for version of broadcom code in which this tag was first introduced -}; - -struct bcm_tag_bc221 { - unsigned char tagVersion[TAGVER_LEN]; // 0-3: Version of the image tag - unsigned char sig_1[20]; // 4-23: Company Line 1 - unsigned char sig_2[14]; // 24-37: Company Line 2 - unsigned char chipid[6]; // 38-43: Chip this image is for - unsigned char boardid[16]; // 44-59: Board name - unsigned char big_endian[2]; // 60-61: Map endianness -- 1 BE 0 LE - unsigned char totalLength[IMAGE_LEN]; // 62-71: Total length of image - unsigned char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE - unsigned char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE - unsigned char flashImageStart[ADDRESS_LEN]; // 94-105: Address in memory of kernel (start of image) - unsigned char flashRootLength[IMAGE_LEN]; // 106-115: Size of rootfs + deadcode (web flash uses this + kernelLength to determine the size of the kernel+rootfs flash image) - unsigned char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel - unsigned char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel - unsigned char dualImage[2]; // 138-139: Unused at present - unsigned char inactiveFlag[2]; // 140-141: Unused at present - unsigned char rsa_signature[TAGINFO_LEN]; // 142-161: RSA Signature (unused at present; some vendors may use this) - unsigned char reserved5[2]; // 162-163: Unused at present - unsigned char tagId[TAGID_LEN]; // 164-169: Identifies which type of tag this is, currently two-letter company code, and then three digits for version of broadcom code in which this tag was first introduced - unsigned char rootAddress[ADDRESS_LEN]; // 170-181: Address in memory of rootfs partition - unsigned char rootLength[IMAGE_LEN]; // 182-191: Size of rootfs partition - unsigned char flashLayoutVer[4]; // 192-195: Version flash layout - unsigned char fskernelCRC[4]; // 196-199: Guessed to be kernel CRC - unsigned char reserved4[16]; // 200-215: Reserved area; unused at present - unsigned char imageCRC[4]; // 216-219: CRC32 of images - unsigned char reserved2[12]; // 220-231: Unused at present - unsigned char tagIdCRC[4]; // 232-235: CRC32 to ensure validity of tagId - unsigned char headerCRC[4]; // 236-239: CRC32 of header excluding tagVersion - unsigned char reserved3[16]; // 240-255: Unused at present -}; - -struct bcm_tag_bc310 { - unsigned char tagVersion[4]; // 0-3: Version of the image tag - unsigned char sig_1[20]; // 4-23: Company Line 1 - unsigned char sig_2[14]; // 24-37: Company Line 2 - unsigned char chipid[6]; // 38-43: Chip this image is for - unsigned char boardid[16]; // 44-59: Board name - unsigned char big_endian[2]; // 60-61: Map endianness -- 1 BE 0 LE - unsigned char totalLength[IMAGE_LEN]; // 62-71: Total length of image - unsigned char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE - unsigned char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE - unsigned char flashImageStart[ADDRESS_LEN]; // 94-105: Address in memory of kernel (start of image) - unsigned char flashRootLength[IMAGE_LEN]; // 106-115: Size of rootfs + deadcode (web flash uses this + kernelLength to determine the size of the kernel+rootfs flash image) - unsigned char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel - unsigned char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel - unsigned char dualImage[2]; // 138-139: Unused at present - unsigned char inactiveFlag[2]; // 140-141: Unused at present - unsigned char information1[TAGINFO_LEN]; // 142-161: Unused at present; Some vendors use this for optional information - unsigned char tagId[6]; // 162-167: Identifies which type of tag this is, currently two-letter company code, and then three digits for version of broadcom code in which this tag was first introduced - unsigned char tagIdCRC[4]; // 168-171: CRC32 to ensure validity of tagId - unsigned char rootAddress[ADDRESS_LEN]; // 172-183: Address in memory of rootfs partition - unsigned char rootLength[IMAGE_LEN]; // 184-193: Size of rootfs partition - unsigned char reserved1[22]; // 193-215: Reserved area not in use - unsigned char imageCRC[4]; // 216-219: CRC32 of images - unsigned char rootfsCRC[4]; // 220-227: CRC32 of rootfs partition - unsigned char kernelCRC[4]; // 224-227: CRC32 of kernel partition - unsigned char reserved2[8]; // 228-235: Unused at present - unsigned char headerCRC[4]; // 235-239: CRC32 of header excluding tagVersion - unsigned char reserved3[16]; // 240-255: Unused at present -}; - -union bcm_tag { - struct bcm_tag_bccfe bccfe; - struct bcm_tag_bc300 bc300; - struct bcm_tag_ag306 ag306; - struct bcm_tag_bc221 bc221; - struct bcm_tag_bc310 bc310; +struct bcm_tag { + char tagVersion[TAGVER_LEN]; // 0-3: Version of the image tag + char sig_1[SIG1_LEN]; // 4-23: Company Line 1 + char sig_2[SIG2_LEN]; // 24-37: Company Line 2 + char chipid[CHIPID_LEN]; // 38-43: Chip this image is for + char boardid[BOARDID_LEN]; // 44-59: Board name + char big_endian[ENDIANFLAG_LEN]; // 60-61: Map endianness -- 1 BE 0 LE + char totalLength[IMAGE_LEN]; // 62-71: Total length of image + char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE + char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE + char flashImageStart[ADDRESS_LEN]; // 94-105: Address in memory of image start (kernel for OpenWRT, rootfs for stock firmware) + char rootLength[IMAGE_LEN]; // 106-115: Size of rootfs + char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel + char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel + char dualImage[DUALFLAG_LEN]; // 138-139: Unused at present + char inactiveFlag[INACTIVEFLAG_LEN]; // 140-141: Unused at present + char rsa_signature[RSASIG_LEN]; // 142-161: RSA Signature (unused at present; some vendors may use this) + char information1[TAGINFO1_LEN]; // 162-191: Compilation and related information (not generated/used by OpenWRT) + char flashLayoutVer[FLASHLAYOUTVER_LEN];// 192-195: Version flash layout + char fskernelCRC[CRC_LEN]; // 196-199: kernel+rootfs CRC32 + char information2[TAGINFO2_LEN]; // 200-215: Unused at present except Alice Gate where is is information + char imageCRC[CRC_LEN]; // 216-219: CRC32 of image less imagetag (kernel for Alice Gate) + char rootfsCRC[CRC_LEN]; // 220-223: CRC32 of rootfs partition + char kernelCRC[CRC_LEN]; // 224-227: CRC32 of kernel partition + char reserved1[8]; // 228-235: Unused at present + char headerCRC[CRC_LEN]; // 236-239: CRC32 of header excluding tagVersion + char reserved2[16]; // 240-255: Unused at present }; #endif /* __BCM63XX_TAG_H */ diff --git a/target/linux/brcm63xx/image/Makefile b/target/linux/brcm63xx/image/Makefile index 5d17c2baf..f7d1473ad 100644 --- a/target/linux/brcm63xx/image/Makefile +++ b/target/linux/brcm63xx/image/Makefile @@ -30,9 +30,9 @@ endef define Image/Build/CFE # Generate the tagged image $(STAGING_DIR_HOST)/bin/imagetag -i $(KDIR)/vmlinux.lzma.cfe -f $(KDIR)/root.$(1) \ - -o $(BIN_DIR)/openwrt-$(2)-$(1)-$(6)-cfe.bin \ + -o $(BIN_DIR)/openwrt-$(4)-$(1)-cfe.bin \ -b $(2) -c $(3) -e $(LOADADDR) -l $(LOADADDR) \ - -t $(4) -d "$(5)" $(7) + -r "$(5)" $(6) # -b $(2) -c $(3) -e $(KERNEL_ENTRY) -l $(LOADADDR) endef @@ -40,17 +40,17 @@ endef define Image/Build/CFEAGPF # Generate the tagged image $(STAGING_DIR_HOST)/bin/imagetag -i $(KDIR)/vmlinux.lzma.cfe -f $(KDIR)/root.$(1) \ - -o $(BIN_DIR)/openwrt-$(2)-$(1)-$(7)-cfe.bin \ + -o $(BIN_DIR)/openwrt-$(5)-$(1)-cfe.bin \ -b $(2) -c $(3) -e $(LOADADDR) -l $(LOADADDR) \ - -v 8 -m IMAGE -k 0x20000 -n $(4) -t $(5) + -v 8 -m IMAGE -k 0x20000 -n $(4) endef define Image/Build/RG100A # Generate the tagged image $(STAGING_DIR_HOST)/bin/imagetag -i $(KDIR)/vmlinux.lzma.cfe -f $(KDIR)/root.$(1) \ - -o $(BIN_DIR)/openwrt-$(6)-$(1)-$(7)-cfe.bin \ + -o $(BIN_DIR)/openwrt-$(5)-$(1)-cfe.bin \ -b $(2) -c $(3) -e $(LOADADDR) -l $(LOADADDR) \ - -k 0x20000 -n $(4) -t $(5) + -k 0x20000 -n $(4) endef @@ -105,84 +105,70 @@ endef define Image/Build dd if=$(KDIR)/root.$(1) of=$(BIN_DIR)/openwrt-$(BOARD)-root.$(1) bs=128k conv=sync # Various routers - $(call Image/Build/CFE,$(1),96345GW2,6345,bccfe,,bccfe,) - $(call Image/Build/CFE,$(1),96345GW2,6345,bc221,,bc221,-y 5) - $(call Image/Build/CFE,$(1),96345GW2,6345,bc300,,bc300,) - $(call Image/Build/CFE,$(1),96345GW2,6345,bc310,OpenWRT-$(REVISION),bc310,) - $(call Image/Build/CFE,$(1),96348GW,6348,bccfe,,bccfe,) - $(call Image/Build/CFE,$(1),96348GW,6348,bc221,,bc221,-y 5) + $(call Image/Build/CFE,$(1),96345GW2,6345,96345GW2-generic) + $(call Image/Build/CFE,$(1),96345GW2,6345,96348GW2-bc221,,-y 5) + $(call Image/Build/CFE,$(1),96345GW2,6345,92345GW2-revision,OpenWRT-$(REVISION)) + $(call Image/Build/CFE,$(1),96348GW,6348,96348GW-generic,,) + $(call Image/Build/CFE,$(1),96348GW,6348,96348GW-bc221,,-y 5) + $(call Image/Build/CFE,$(1),6338GW,6338,6338GW-generic,,) + $(call Image/Build/CFE,$(1),6338W,6338,6338W-generic,,) + # BT Voyager V210_BTR - $(call Image/Build/CFE,$(1),V210_BB,6348,bc221,,btvgr,-y 5) + $(call Image/Build/CFE,$(1),V210_BB,6348,BTV210_BTR,,-y 5) # BT Voyager V210_ROI, V210_WB - $(call Image/Build/CFE,$(1),V210,6348,bc221,,btvgr,-y 5) + $(call Image/Build/CFE,$(1),V210,6348,BTV210_ROI_WB,,-y 5) # BT Voyager V2091_BTR - $(call Image/Build/CFE,$(1),V2091_BB,6348,bc221,,btvgr,-y 5) + $(call Image/Build/CFE,$(1),V2091_BB,6348,BTV2091_BTR,,y 5) # BT Voyager V2091_ROI, V2091_WB - $(call Image/Build/CFE,$(1),V2091,6348,bc221,,btvgr,-y 5) + $(call Image/Build/CFE,$(1),V2091,6348,BTV2091_ROI_WB,,-y 5) # BT Voyager V220V, V220V_MGCP_BTR - $(call Image/Build/CFE,$(1),RTA1052V,6348,bc221,,btvgr,-y 5) + $(call Image/Build/CFE,$(1),RTA1052V,6348,BTV220V_MGCP_BTR,,-y 5) # BT Voyager V2110, V2110_AA, V2110_ROI - $(call Image/Build/CFE,$(1),V2110,6348,bc221,,btvgr,-y 5) + $(call Image/Build/CFE,$(1),V2110,6348,BTV2110,,-y 5) # BT Voyager V2500V, V2500V_SIP_CLUB, V2500V_AA - $(call Image/Build/CFE,$(1),V2500V_BB,6348,bc221,,btvgr,-y 5) + $(call Image/Build/CFE,$(1),V2500V_BB,6348,BTV2500V,,-y 5) # RTA1025W_16 (numerous routers) - $(call Image/Build/CFE,$(1),RTA1025W_16,6348,bc221,,btrta,-y 5) + $(call Image/Build/CFE,$(1),RTA1025W_16,6348,RTA1025W_16,,-y 5) # Tecom GW6000 - $(call Image/Build/CFE,$(1),96348GW,6348,bc300,,bc300,) + $(call Image/Build/CFE,$(1),96348GW,6348,GW6000) # Tecom GW6200 - $(call Image/Build/CFE,$(1),96348GW,6348,bc310,$(shell printf '\x99'),gw6200) + $(call Image/Build/CFE,$(1),96348GW,6348,GW6200,$(shell printf '\x99')) # Neufbox4 - $(call Image/Build/CFE,$(1),96358VW,6358,bccfe,,bccfe) - $(call Image/Build/CFE,$(1),96358VW,6358,bc310,OpenWRT-$(REVISION),nb4) + $(call Image/Build/CFE,$(1),96358VW,6358,NEUFBOX4,OpenWRT-$(REVISION)) # Comtrend 536, 5621 - $(call Image/Build/CFE,$(1),96348GW-11,6348,bccfe,,bccfe) - $(call Image/Build/CFE,$(1),96348GW-11,6348,bc300,,bc300) - # TP-Link 8900GB - $(call Image/Build/CFE,$(1),96348GW-11,6348,bc310,$(shell printf 'PRID\x89\x10\x00\x02'),td8900GB) + $(call Image/Build/CFE,$(1),96348GW-11,6348,CT536_CT5621) # Davolink DV201AMR $(call Image/Build/CFEOLD,$(1),DV201AMR,6348) # USR 9108 - $(call Image/Build/CFE,$(1),96348GW-A,6348,bccfe,,bccfe) - $(call Image/Build/CFE,$(1),96348GW-A,6348,bc300,,bc300) + $(call Image/Build/CFE,$(1),96348GW-A,6348,USR9108) # NetGear DG834GT, DG834PN - $(call Image/Build/CFE,$(1),96348GW-10,6348,bccfe,,bccfe) - $(call Image/Build/CFE,$(1),96348GW-10,6348,bc300,,bc300) + $(call Image/Build/CFE,$(1),96348GW-10,6348,DG834GT_DG834PN) # Belkin f5d7633 - $(call Image/Build/CFE,$(1),96348GW-10,6348,bc310,,bc310) + $(call Image/Build/CFE,$(1),96348GW-10,6348,F5D7633) # D-Link DSL-2640B - $(call Image/Build/CFE,$(1),D-4P-W,6348,bc310,,bc310) + $(call Image/Build/CFE,$(1),D-4P-W,6348,DSL2640B) + # D-Link DSL-2740B + $(call Image/Build/CFE,$(1),96358GW,6358,DSL2740B) # TP-Link TD-8810A, TD-8810B, TD-8811A, TD-8811B - $(call Image/Build/CFE,$(1),8L-2M-8M,6338,bccfe,,bccfe) - $(call Image/Build/CFE,$(1),8L-2M-8M,6338,bc300,,bc300) - - # Generic 6338 images - $(call Image/Build/CFE,$(1),6338GW,6338,bccfe,,bccfe) - $(call Image/Build/CFE,$(1),6338GW,6338,bc221,,bc221) - $(call Image/Build/CFE,$(1),6338GW,6338,bc300,,bc300) - $(call Image/Build/CFE,$(1),6338GW,6338,bc310,,bc310) - $(call Image/Build/CFE,$(1),6338W,6338,bccfe,,bccfe) - $(call Image/Build/CFE,$(1),6338W,6338,bc221,,bc221) - $(call Image/Build/CFE,$(1),6338W,6338,bc300,,bc300) - $(call Image/Build/CFE,$(1),6338W,6338,bc310,,bc310) + $(call Image/Build/CFE,$(1),8L-2M-8M,6338,TP8810_8811) + # TP-Link 8900GB + $(call Image/Build/CFE,$(1),96348GW-11,6348,TD8900GB,$(shell printf 'PRID\x89\x10\x00\x02')) # Sagem F@ST2404 - $(call Image/Build/CFE,$(1),F@ST2404,6348,bccfe,,bccfe) - $(call Image/Build/CFE,$(1),F@ST2404,6348,bc300,,bc300) - $(call Image/Build/CFE,$(1),F@ST2404,6348,bc310,OpenWRT-$(REVISION),bc310) + $(call Image/Build/CFE,$(1),F@ST2404,6348,F@ST2404-cfe) + $(call Image/Build/CFE,$(1),F@ST2404,6348,F@ST2404,OpenWRT-$(REVISION)) # Inventel Livebox $(call Image/Build/RedBoot,livebox) - # D-Link DSL-2740B - $(call Image/Build/CFE,$(1),96358GW,6358,bc310,,dsl2740b) # Pirelli Alice Gate VoIP 2 Plus Wi-Fi AGPF-S0 - $(call Image/Build/CFEAGPF,$(1),AGPF-S0,6358,0x20000,bccfe,,bccfe) - $(call Image/Build/CFEAGPF,$(1),AGPF-S0,6358,0x20000,ag306,,agv2+w) + $(call Image/Build/CFEAGPF,$(1),AGPF-S0,6358,0x20000,AGV2+W-cfe) + $(call Image/Build/CFEAGPF,$(1),AGPF-S0,6358,0x20000,AGV2+W) # Pirelli A226G - $(call Image/Build/CFEAGPF,$(1),DWV-S0,6358,0x10000,bccfe,,bccfe) - $(call Image/Build/CFEAGPF,$(1),DWV-S0,6358,0x10000,ag306,DWV_96358,a226g) + $(call Image/Build/CFEAGPF,$(1),DWV-S0,6358,0x10000,A226G-cfe) + $(call Image/Build/CFEAGPF,$(1),DWV-S0,6358,0x10000,A226G) # RG100A,DB120 etc. - $(call Image/Build/RG100A,$(1),96358VW2,6358,0x20000,bc310,rg100a,bc310) + $(call Image/Build/RG100A,$(1),96358VW2,6358,0x20000,RG100A_DB120) endef diff --git a/target/linux/brcm63xx/image/README.images-bcm63xx b/target/linux/brcm63xx/image/README.images-bcm63xx index 9cf05743a..91b6d019e 100644 --- a/target/linux/brcm63xx/image/README.images-bcm63xx +++ b/target/linux/brcm63xx/image/README.images-bcm63xx @@ -16,6 +16,11 @@ Images flashable using cfe are labelled openwrt---cfe.bin The imagetags for tftp/ftp flashing is based on Broadcom 3.00-3.04 imagetags and is known to be correct as the source code GPL and is available for reading. +Broadcom code 2.21 is based on the BT Voyager firmware image I looked at. It +may in fact be BT Voyager-specific. 2.21 is actually more difficult to deal +with the imagetag from 3.00 as it has three different CRC calculations in +addtition to the header CRC. + Broadcom 3.00-3.02 flashing has been tested on Comtrend CT-5261, CT-536 and Tecom GW6000, and is the version of the flashing that was present before the imagetags were split by broadcom code version (early June 2009) @@ -27,16 +32,11 @@ this author (Daniel Dickinson) has seen is the Alice Gate (Pirelli) firmware which is known to be different due to vendor (Pirelli) modifications to the Broadcom code. -Broadcom 3.08 introduced changes to the imagetag to deal with TR69 (a remote -router management system developed by the DSL Forum). The version we are -using as 3.08 is based on the BT Voyager firmware image I looked at. It may -in fact be BT Voyager-specific, and may in fact not be 3.08, but modified 3.06 -and not apply to all 3.08 versions. - Broadcom 3.10 uses an imagetag that is believed to apply to all 3.10 and 3.12 -versions, and has been tested on the Tecom GW6200. It is similar to 3.08. -There is a field for vendor-specific information, that at least in some cases -is not optional. It is based on the hexedit of a neufbox4 firmware image, the +versions, and has been tested on the Tecom GW6200. This version introdec changes to +the imagetag to deal with TR69 (a remote rouer management system developed by the +DSL forum). There is a field for vendor-specific information, that at least in some +cases is not optional. It is based on the hexedit of a neufbox4 firmware image, the information in https://dev.openwrt.org/ticket/4987, and the hexedit of a Tecom GW6200 image. @@ -44,43 +44,41 @@ Some boards share the same tag format, but require vendor-specific fields in the board. In that case the tagid is shared, but the filename of the generated image reflects the router for which the image was created. -router |method| codever |tagid |filename -+-------------+------+---------+------+---------------------------------------- -|any |cfe | any |bccfe |openwrt---bccfe-cfe.bin -|any |t/ftp | any |bc300 |openwrt---bc300-cfe.bin -| |web |3.00-3.06|bc300 |openwrt---bc300-cfe.bin -| |web |3.10-3.12|bc310 |openwrt---bc310-cfe.bin -|AGVoIP2+WiFi |web |alice3.06|ag306 |openwrt-AGPF-S0--agv2+w-cfe.bin -|CT536 |web |3.02 |bc300 |openwrt-96348GW-11--bc300-cfe.bin -|CT5621 |web |3.02 |bc300 |openwrt-96348GW-11--bc300-cfe.bin -|DG834GT |web |3.02 |bc300 |openwrt-96348GW-10--bc300-cfe.bin -|DG834PN |web |3.02 |bc300 |openwrt-96348GW-10--bc300-cfe.bin -|DSL-2640B |web |3.10 |bc310 |openwrt-D-4P-W--bc310-cfe.bin -|DSL-2740B |web |3.10 |bc310 |openwrt-96358GW--dsl2740b-cfe.bin -|F5D7633 |web |3.10 |bc310 |openwrt-96348GW-10--bc310-cfe.bin -|F@ST2404 |web |? |bc300 |openwrt-F@ST2404--bc300-cfe.bin -|F@ST2404 |web |? |bc310 |openwrt-F@ST2404--bc310-cfe.bin -|GW6000 |web |3.00 |bc300 |openwrt-96348GW--bc300-cfe.bin -|GW6200 |web |3.10 |bc310 |openwrt-96348GW--gw6200-cfe.bin -|Neufbox4 |web |3.12 |bc310 |openwrt-96358VW--nb4-cfe.bin -|TD8810A |web |3.06 |bc300 |openwrt-8L-2M-8M--bc306-cfe.bin -|TD8810B |web |3.06 |bc300 |openwrt-8L-2M-8M--bc306-cfe.bin -|TD8811A |web |3.06 |bc300 |openwrt-8L-2M-8M--bc306-cfe.bin -|TD8811B |web |3.06 |bc300 |openwrt-8L-2M-8M--bc306-cfe.bin -|TD8900GB |web |3.06 |bc300 |openwrt-96348GW-11--td8900gb-cfe.bin -|USR9108 |web |? |bc300 |openwrt-96348GW-A--bc300-cfe.bin -|V2091_BTR |web |2.21 |bc221 |openwrt-V2091_BB--btvgr-cfe.bin -|V2091_ROI |web |2.21 |bc221 |openwrt-V2091--btvgr-cfe.bin -|V2091_WB |web |2.21 |bc221 |openwrt-V2091--btvgr-cfe.bin -|V210_BTR |web |2.21 |bc221 |openwrt-V210_BB--btvgr-cfe.bin -|V210_ROI |web |2.21 |bc221 |openwrt-V210--btvgr-cfe.bin -|V210_WB |web |2.21 |bc221 |openwrt-V210--btvgr-cfe.bin -|V2110 |web |2.21 |bc221 |openwrt-V2110--btvgr-cfe.bin -|V2110_AA |web |2.21 |bc221 |openwrt-V2110--btvgr-cfe.bin -|V2110_ROI |web |2.21 |bc221 |openwrt-V2110--btvgr-cfe.bin -|V2500V |web |2.21 |bc221 |openwrt-V2500V_BB--btvgr-cfe.bin -|V2500V_AA |web |2.21 |bc221 |openwrt-V2500V_BB--btvgr-cfe.bin -|V2500V_SIP_CLUB |web|2.21 |bc221 |openwrt-V2500V_BB--btvgr-cfe.bin +router |method | codever |filename ++-------------+-------------+---------+--------------------------------------- +|any |cfe+most web | any |openwrt---cfe.bin +|AGVoIP2+WiFi |cfe |alice3.06|openwrt-AGV2+W-cfe--cfe.bin +|AGVoIP2+WiFi |web |alice3.06|openwrt-AGV2+W-cfe--cfe.bin +|CT536 |web |3.02 |openwrt-CT536_CT5621--cfe.bin +|CT5621 |web |3.02 |openwrt-CT536_CT5621--cfe.bin +|DG834GT |web |3.02 |openwrt-DG834GT_DG834PN--cfe.bin +|DG834PN |web |3.02 |openwrt-DG834GT_DG834PN--cfe.bin +|DSL-2640B |web |3.10 |openwrt-DSL2640B--cfe.bin +|DSL-2740B |web |3.10 |openwrt-DSL2670B--cfe.bin +|F5D7633 |web |3.10 |openwrt-F5D7633--cfe.bin +|F@ST2404 |web |3.0X? |openwrt-F@ST2404-cfe--cfe.bin +|F@ST2404 |web |3.1X? |openwrt-F@ST2404--cfe.bin +|GW6000 |web |3.00 |openwrt-GW6000--cfe.bin +|GW6200 |web |3.10 |openwrt-GW6200--cfe.bin +|Neufbox4 |web |3.12 |openwrt-NEUFBOX4--cfe.bin +|TD8810A |web |3.06 |openwrt-TD8810--cfe.bin +|TD8810B |web |3.06 |openwrt-TD8810--cfe.bin +|TD8811A |web |3.06 |openwrt-TD8811--cfe.bin +|TD8811B |web |3.06 |openwrt-TD881--cfe.bin +|TD8900GB |web |3.06 |openwrt-TD8900DB-cfe.bin +|USR9108 |web |3.0X? |openwrt-USR9108--cfe.bin +|V2091_BTR |web |2.21 |openwrt-V2091_BTR--cfe.bin +|V2091_ROI |web |2.21 |openwrt-V2091--cfe.bin +|V2091_WB |web |2.21 |openwrt-V2091--cfe.bin +|V210_BTR |web |2.21 |openwrt-V210_BTR--cfe.bin +|V210_ROI |web |2.21 |openwrt-V210-ROI_WB-cfe.bin +|V210_WB |web |2.21 |openwrt-V210-ROI_WB-cfe.bin +|V2110 |web |2.21 |openwrt-V2110--cfe.bin +|V2110_AA |web |2.21 |openwrt-V2110--cfe.bin +|V2110_ROI |web |2.21 |openwrt-V2110--cfe.bin +|V2500V |web |2.21 |openwrt-V2500V-cfe.bin +|V2500V_AA |web |2.21 |openwrt-V2500V--cfe.bin +|V2500V_SIP_CLUB |web |2.21 |openwrt-V2500V--cfe.bin Old imagetag routers -------------------- @@ -126,3 +124,4 @@ TP-Link |TD-W8900GB |3.06 Tecom |GW6000 |3.00 Tecom |GW6200 |3.10 USR |9108 |? + diff --git a/target/linux/brcm63xx/patches-2.6.32/040-bcm963xx_flashmap.patch b/target/linux/brcm63xx/patches-2.6.32/040-bcm963xx_flashmap.patch index 556e8cb85..117074b99 100644 --- a/target/linux/brcm63xx/patches-2.6.32/040-bcm963xx_flashmap.patch +++ b/target/linux/brcm63xx/patches-2.6.32/040-bcm963xx_flashmap.patch @@ -11,9 +11,11 @@ Signed-off-by: Axel Gembe drivers/mtd/redboot.c | 13 ++++++++++--- 3 files changed, 18 insertions(+), 3 deletions(-) ---- a/drivers/mtd/maps/Kconfig -+++ b/drivers/mtd/maps/Kconfig -@@ -259,6 +259,13 @@ config MTD_ALCHEMY +Index: linux-2.6.32.10/drivers/mtd/maps/Kconfig +=================================================================== +--- linux-2.6.32.10.orig/drivers/mtd/maps/Kconfig 2010-03-29 06:35:59.987293878 -0400 ++++ linux-2.6.32.10/drivers/mtd/maps/Kconfig 2010-03-29 06:37:14.968545954 -0400 +@@ -259,6 +259,13 @@ help Flash memory access on AMD Alchemy Pb/Db/RDK Reference Boards @@ -27,9 +29,11 @@ Signed-off-by: Axel Gembe config MTD_DILNETPC tristate "CFI Flash device mapped on DIL/Net PC" depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN ---- a/drivers/mtd/redboot.c -+++ b/drivers/mtd/redboot.c -@@ -39,7 +39,7 @@ static inline int redboot_checksum(struc +Index: linux-2.6.32.10/drivers/mtd/redboot.c +=================================================================== +--- linux-2.6.32.10.orig/drivers/mtd/redboot.c 2010-03-29 06:36:00.017292877 -0400 ++++ linux-2.6.32.10/drivers/mtd/redboot.c 2010-03-29 06:37:14.968545954 -0400 +@@ -39,7 +39,7 @@ return 1; } @@ -38,7 +42,7 @@ Signed-off-by: Axel Gembe struct mtd_partition **pparts, unsigned long fis_origin) { -@@ -162,6 +162,14 @@ static int parse_redboot_partitions(stru +@@ -162,6 +162,14 @@ goto out; } @@ -53,7 +57,7 @@ Signed-off-by: Axel Gembe for (i = 0; i < numslots; i++) { struct fis_list *new_fl, **prev; -@@ -184,9 +192,8 @@ static int parse_redboot_partitions(stru +@@ -184,9 +192,8 @@ new_fl->img = &buf[i]; if (fis_origin) { buf[i].flash_base -= fis_origin; @@ -64,16 +68,20 @@ Signed-off-by: Axel Gembe /* I'm sure the JFFS2 code has done me permanent damage. * I now think the following is _normal_ ---- a/drivers/mtd/maps/Makefile -+++ b/drivers/mtd/maps/Makefile -@@ -61,3 +61,4 @@ obj-$(CONFIG_MTD_BFIN_ASYNC) += bfin-asy +Index: linux-2.6.32.10/drivers/mtd/maps/Makefile +=================================================================== +--- linux-2.6.32.10.orig/drivers/mtd/maps/Makefile 2010-03-29 06:35:59.947294290 -0400 ++++ linux-2.6.32.10/drivers/mtd/maps/Makefile 2010-03-29 06:37:14.968545954 -0400 +@@ -61,3 +61,4 @@ obj-$(CONFIG_MTD_RBTX4939) += rbtx4939-flash.o obj-$(CONFIG_MTD_VMU) += vmu-flash.o obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr-flash.o +obj-$(CONFIG_MTD_BCM963XX) += bcm963xx-flash.o ---- /dev/null -+++ b/drivers/mtd/maps/bcm963xx-flash.c -@@ -0,0 +1,399 @@ +Index: linux-2.6.32.10/drivers/mtd/maps/bcm963xx-flash.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.32.10/drivers/mtd/maps/bcm963xx-flash.c 2010-03-29 13:33:58.797288897 -0400 +@@ -0,0 +1,266 @@ +/* + * Copyright (C) 2006-2008 Florian Fainelli + * Mike Albon @@ -119,179 +127,46 @@ Signed-off-by: Axel Gembe + .bankwidth = BUSWIDTH, +}; + -+static struct tagiddesc_t tagidtab[NUM_TAGID] = TAGID_DEFINITIONS; -+ -+static uint32_t tagcrc32tab[256] = { -+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, -+ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, -+ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, -+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, -+ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, -+ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, -+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, -+ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, -+ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, -+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, -+ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, -+ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, -+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, -+ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, -+ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, -+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, -+ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, -+ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, -+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, -+ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, -+ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, -+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, -+ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, -+ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, -+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, -+ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, -+ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, -+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, -+ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, -+ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, -+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, -+ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D -+}; -+ -+static uint32_t tagcrc32(uint32_t crc, uint8_t *data, size_t len) -+{ -+ while (len--) -+ crc = (crc >> 8) ^ tagcrc32tab[(crc ^ *data++) & 0xFF]; -+ -+ return crc; -+} + +static int parse_cfe_partitions( struct mtd_info *master, struct mtd_partition **pparts) +{ + int nrparts = 3, curpart = 0; /* CFE,NVRAM and global LINUX are always present. */ -+ union bcm_tag *buf; ++ struct bcm_tag *buf; + struct mtd_partition *parts; + int ret; + size_t retlen; + unsigned int rootfsaddr, kerneladdr, spareaddr; + unsigned int rootfslen, kernellen, sparelen, totallen; -+ unsigned char *tagid; + int namelen = 0; + int i; -+ uint32_t tagidcrc; -+ uint32_t calctagidcrc; -+ bool tagid_match = false; + char *boardid; + char *tagversion; -+ char *matchtagid; + + /* Allocate memory for buffer */ -+ buf = vmalloc(sizeof(union bcm_tag)); ++ buf = vmalloc(sizeof(struct bcm_tag)); + if (!buf) + return -ENOMEM; + + /* Get the tag */ -+ ret = master->read(master,master->erasesize,sizeof(union bcm_tag), &retlen, (void *)buf); -+ if (retlen != sizeof(union bcm_tag)){ ++ ret = master->read(master,master->erasesize,sizeof(struct bcm_tag), &retlen, (void *)buf); ++ if (retlen != sizeof(struct bcm_tag)){ + vfree(buf); + return -EIO; + } + -+ /* tagId isn't in the same location, so we check each tagid against the -+ * tagid CRC. If the CRC is valid we have found the right tag and so -+ * use that tag -+ */ ++ sscanf(buf->kernelAddress, "%u", &kerneladdr); ++ sscanf(buf->kernelLength, "%u", &kernellen); ++ sscanf(buf->totalLength, "%u", &totallen); ++ tagversion = &(buf->tagVersion[0]); ++ boardid = &(buf->boardid[0]); + -+ for (i = 0; i < NUM_TAGID; i++) { -+ switch(i) { -+ case 0: -+ matchtagid = "bccfe"; -+ tagid = &(buf->bccfe.tagId[0]); -+ sscanf(buf->bccfe.rootAddress,"%u", &rootfsaddr); -+ sscanf(buf->bccfe.rootLength, "%u", &rootfslen); -+ sscanf(buf->bccfe.kernelAddress, "%u", &kerneladdr); -+ sscanf(buf->bccfe.kernelLength, "%u", &kernellen); -+ sscanf(buf->bccfe.totalLength, "%u", &totallen); -+ tagidcrc = *(uint32_t *)&(buf->bccfe.tagIdCRC[0]); -+ tagversion = &(buf->bccfe.tagVersion[0]); -+ boardid = &(buf->bccfe.boardid[0]); -+ break; -+ case 1: -+ matchtagid = "bc300"; -+ tagid = &(buf->bc300.tagId[0]); -+ sscanf(buf->bc300.rootAddress,"%u", &rootfsaddr); -+ sscanf(buf->bc300.rootLength, "%u", &rootfslen); -+ sscanf(buf->bc300.kernelAddress, "%u", &kerneladdr); -+ sscanf(buf->bc300.kernelLength, "%u", &kernellen); -+ sscanf(buf->bc300.totalLength, "%u", &totallen); -+ tagidcrc = *(uint32_t *)&(buf->bc300.tagIdCRC[0]); -+ tagversion = &(buf->bc300.tagVersion[0]); -+ boardid = &(buf->bc300.boardid[0]); -+ break; -+ case 2: -+ matchtagid = "ag306"; -+ tagid = &(buf->ag306.tagId[0]); -+ sscanf(buf->ag306.rootAddress,"%u", &rootfsaddr); -+ sscanf(buf->ag306.rootLength, "%u", &rootfslen); -+ sscanf(buf->ag306.kernelAddress, "%u", &kerneladdr); -+ sscanf(buf->ag306.kernelLength, "%u", &kernellen); -+ sscanf(buf->ag306.totalLength, "%u", &totallen); -+ tagidcrc = *(uint32_t *)&(buf->ag306.tagIdCRC[0]); -+ tagversion = &(buf->ag306.tagVersion[0]); -+ boardid = &(buf->ag306.boardid[0]); -+ break; -+ case 3: -+ matchtagid = "bc221"; -+ tagid = &(buf->bc221.tagId[0]); -+ sscanf(buf->bc221.rootAddress,"%u", &rootfsaddr); -+ sscanf(buf->bc221.rootLength, "%u", &rootfslen); -+ sscanf(buf->bc221.kernelAddress, "%u", &kerneladdr); -+ sscanf(buf->bc221.kernelLength, "%u", &kernellen); -+ sscanf(buf->bc221.totalLength, "%u", &totallen); -+ tagidcrc = *(uint32_t *)&(buf->bc221.tagIdCRC[0]); -+ tagversion = &(buf->bc221.tagVersion[0]); -+ boardid = &(buf->bc221.boardid[0]); -+ break; -+ case 4: -+ matchtagid = "bc310"; -+ tagid = &(buf->bc310.tagId[0]); -+ sscanf(buf->bc310.rootAddress,"%u", &rootfsaddr); -+ sscanf(buf->bc310.rootLength, "%u", &rootfslen); -+ sscanf(buf->bc310.kernelAddress, "%u", &kerneladdr); -+ sscanf(buf->bc310.kernelLength, "%u", &kernellen); -+ sscanf(buf->bc310.totalLength, "%u", &totallen); -+ tagidcrc = *(uint32_t *)&(buf->bc310.tagIdCRC[0]); -+ tagversion = &(buf->bc310.tagVersion[0]); -+ boardid = &(buf->bc310.boardid[0]); -+ break; -+ } -+ if (strncmp(tagid, matchtagid, TAGID_LEN) != 0) { -+ continue; -+ } ++ printk(KERN_INFO PFX "CFE boot tag found with version %s and board type %s\n",tagversion, boardid); + -+ calctagidcrc = htonl(tagcrc32(IMAGETAG_CRC_START, tagid, TAGID_LEN)); -+ if (tagidcrc == calctagidcrc) { -+ tagid_match = true; -+ break; -+ } -+ } -+ -+ if (!tagid_match) { -+ tagid = "bcram"; -+ sscanf(buf->bccfe.rootAddress,"%u", &rootfsaddr); -+ sscanf(buf->bccfe.rootLength, "%u", &rootfslen); -+ sscanf(buf->bccfe.kernelAddress, "%u", &kerneladdr); -+ sscanf(buf->bccfe.kernelLength, "%u", &kernellen); -+ sscanf(buf->bccfe.totalLength, "%u", &totallen); -+ tagidcrc = *(uint32_t *)&(buf->bccfe.tagIdCRC[0]); -+ tagversion = &(buf->bccfe.tagVersion[0]); -+ boardid = &(buf->bccfe.boardid[0]); -+ } -+ -+ printk(KERN_INFO PFX "CFE boot tag found with version %s, board type %s, and tagid %s.\n",tagversion,boardid,tagid); -+ -+ rootfsaddr = rootfsaddr - EXTENDED_SIZE; + kerneladdr = kerneladdr - EXTENDED_SIZE; -+ spareaddr = roundup(totallen,master->erasesize) + master->erasesize; ++ rootfsaddr = kerneladdr + kernellen; ++ spareaddr = roundup(totallen, master->erasesize) + master->erasesize; + sparelen = master->size - spareaddr - master->erasesize; ++ rootfslen = spareaddr - rootfsaddr; + + /* Determine number of partitions */ + namelen = 8; @@ -342,9 +217,9 @@ Signed-off-by: Axel Gembe + parts[curpart].name = "linux"; + parts[curpart].offset = parts[0].size; + parts[curpart].size = master->size - parts[0].size - parts[3].size; -+ ++ + for (i = 0; i < nrparts; i++) -+ printk(KERN_INFO PFX "Partition %d is %s offset %lx and length %lx\n", i, parts[i].name, parts[i].offset, parts[i].size); ++ printk(KERN_INFO PFX "Partition %d is %s offset %lx and length %lx\n", i, parts[i].name, (long unsigned int)(parts[i].offset), (long unsigned int)(parts[i].size)); + + printk(KERN_INFO PFX "Spare partition is %x offset and length %x\n", spareaddr, sparelen); + *pparts = parts; @@ -375,7 +250,7 @@ Signed-off-by: Axel Gembe + char *part_type; + struct resource *r; + -+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + bcm963xx_map.phys = r->start; + bcm963xx_map.size = (r->end - r->start) + 1; + bcm963xx_map.virt = ioremap(r->start, r->end - r->start + 1); @@ -473,9 +348,11 @@ Signed-off-by: Axel Gembe +MODULE_DESCRIPTION("Broadcom BCM63xx MTD partition parser/mapping for CFE and RedBoot"); +MODULE_AUTHOR("Florian Fainelli "); +MODULE_AUTHOR("Mike Albon "); ---- a/arch/mips/bcm63xx/boards/board_bcm963xx.c -+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c -@@ -722,20 +722,6 @@ static int board_get_mac_address(u8 *mac +Index: linux-2.6.32.10/arch/mips/bcm63xx/boards/board_bcm963xx.c +=================================================================== +--- linux-2.6.32.10.orig/arch/mips/bcm63xx/boards/board_bcm963xx.c 2010-03-29 06:35:59.927292275 -0400 ++++ linux-2.6.32.10/arch/mips/bcm63xx/boards/board_bcm963xx.c 2010-03-29 06:37:35.178541753 -0400 +@@ -722,20 +722,6 @@ return 0; } @@ -496,7 +373,7 @@ Signed-off-by: Axel Gembe static struct resource mtd_resources[] = { { .start = 0, /* filled at runtime */ -@@ -745,12 +731,9 @@ static struct resource mtd_resources[] = +@@ -745,12 +731,9 @@ }; static struct platform_device mtd_dev = { diff --git a/target/linux/generic-2.4/patches/629-netlink_types_h.patch b/target/linux/generic-2.4/patches/629-netlink_types_h.patch index 8347d170b..9c5b45df6 100644 --- a/target/linux/generic-2.4/patches/629-netlink_types_h.patch +++ b/target/linux/generic-2.4/patches/629-netlink_types_h.patch @@ -9,3 +9,14 @@ #define NETLINK_ROUTE 0 /* Routing/device hook */ #define NETLINK_SKIP 1 /* Reserved for ENskip */ #define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */ +--- a/include/linux/filter.h 2010-02-01 22:04:46.000000000 +0100 ++++ b/include/linux/filter.h 2010-03-29 20:57:08.000000000 +0200 +@@ -5,6 +5,8 @@ + #ifndef __LINUX_FILTER_H__ + #define __LINUX_FILTER_H__ + ++#include ++ + /* + * Current version of the filter code architecture. + */ diff --git a/target/linux/generic-2.6/config-2.6.32 b/target/linux/generic-2.6/config-2.6.32 index a9c4bfb82..b869c9ae9 100644 --- a/target/linux/generic-2.6/config-2.6.32 +++ b/target/linux/generic-2.6/config-2.6.32 @@ -550,6 +550,7 @@ CONFIG_EXPERIMENTAL=y # CONFIG_EXT4_DEBUG is not set # CONFIG_EXT4DEV_FS is not set # CONFIG_EXT4_FS is not set +# CONFIG_EXT4_FS_XATTR is not set CONFIG_EXTRA_FIRMWARE="" CONFIG_EXTRA_TARGETS="" # CONFIG_EZX_PCAP is not set diff --git a/target/linux/ifxmips/Makefile b/target/linux/ifxmips/Makefile index addeef681..b82f78263 100644 --- a/target/linux/ifxmips/Makefile +++ b/target/linux/ifxmips/Makefile @@ -16,7 +16,8 @@ LINUX_VERSION:=2.6.30.10 CFLAGS=-Os -pipe -mips32r2 -mtune=mips32r2 -funit-at-a-time include $(INCLUDE_DIR)/target.mk -DEFAULT_PACKAGES+=kmod-pppoa ppp-mod-pppoa linux-atm atm-tools br2684ctl ifxmips-dsl-api ifxmips-dsl-control +DEFAULT_PACKAGES+=uboot-lantiq +#kmod-pppoa ppp-mod-pppoa linux-atm atm-tools br2684ctl ifxmips-dsl-api ifxmips-dsl-control ifx-tapidemo define Target/Description Build firmware images for Infineon Mips Controllers diff --git a/target/linux/ifxmips/extract.py b/target/linux/ifxmips/extract.py new file mode 100755 index 000000000..91b4a578d --- /dev/null +++ b/target/linux/ifxmips/extract.py @@ -0,0 +1,9 @@ +#!/usr/bin/python +from sys import stdin, stdout +while True: + c = stdin.read(2) + if len(c) < 2: + break + n1, n2 = ord(c[0]), ord(c[1]) + stdout.write(chr(((n2 & 15) << 4) + ((n2 & 240) >> 4))) + stdout.write(chr(((n1 & 15) << 4) + ((n1 & 240) >> 4))) diff --git a/target/linux/ifxmips/extract.sh b/target/linux/ifxmips/extract.sh new file mode 100755 index 000000000..7b1c1da0b --- /dev/null +++ b/target/linux/ifxmips/extract.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +DIR="$1/" +FILE="$1/$2" + +echo "This tool downloads the arcor a800 firmware release and extracts the voip firmware for the danube." +echo "Please only do so if it is legal in your country" + +[ ! -f ${FILE} ] && { + echo ${FILE} is missing + exit 1 +} + +[ -f ${DIR}/ifxmips_fw_decode.tar.bz2 -a ! -f ${DIR}voip_coef.bin ] && { + [ ! -f ${DIR}decode_ifx_fw ] && { + tar xjf ${DIR}ifxmips_fw_decode.tar.bz2 ifxmips_fw_decode/decode.c -O > ${DIR}decode.c + gcc -o ${DIR}decode_ifx_fw ${DIR}decode.c + } + [ ! -f ${DIR}voip_coef.lzma ] && { + ${DIR}decode_ifx_fw $FILE ${DIR}voip_coef.lzma + } + lzma d ${DIR}voip_coef.lzma ${DIR}voip_coef.bin +} +[ ! -f ${DIR}dsl_a.bin ] && { + dd if=${FILE} of=${DIR}dsl1.lzma bs=1 skip=2168832 count=150724 + lzma d ${DIR}dsl2.lzma ${DIR}dsl_a.bin +} + +[ ! -f ${DIR}dsl_b.bin ] && { + dd if=${FILE} of=${DIR}dsl2.lzma bs=1 skip=2320384 count=148343 + lzma d ${DIR}dsl1.lzma ${DIR}dsl_b.bin +} + +[ ! -f ${DIR}voip.bin ] && { + dd if=${FILE} of=${DIR}voip.lzma bs=1 skip=2468864 count=452105 + lzma d ${DIR}voip.lzma ${DIR}voip.bin +} +exit 0 + +# get lzma offsets +# hexdump -C arcor_A800_452CPW_FW_1.02.206\(20081201\).bin | grep "5d 00 00 80" +# hexdump -C arcor_A800_452CPW_FW_1.02.206\(20081201\).bin | grep "00 d5 08 00" diff --git a/target/linux/ifxmips/files/arch/mips/ifxmips/Makefile b/target/linux/ifxmips/files/arch/mips/ifxmips/Makefile index 9710645b9..c330be634 100644 --- a/target/linux/ifxmips/files/arch/mips/ifxmips/Makefile +++ b/target/linux/ifxmips/files/arch/mips/ifxmips/Makefile @@ -1 +1 @@ -obj-y := reset.o prom.o setup.o irq.o dma-core.o pmu.o board.o clock.o gpio.o +obj-y := reset.o prom.o setup.o irq.o dma-core.o pmu.o board.o clock.o gpio.o timer.o diff --git a/target/linux/ifxmips/files/arch/mips/ifxmips/timer.c b/target/linux/ifxmips/files/arch/mips/ifxmips/timer.c index d05df2283..31e606c85 100644 --- a/target/linux/ifxmips/files/arch/mips/ifxmips/timer.c +++ b/target/linux/ifxmips/files/arch/mips/ifxmips/timer.c @@ -13,11 +13,11 @@ #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #define MAX_NUM_OF_32BIT_TIMER_BLOCKS 6 diff --git a/target/linux/ramips/Makefile b/target/linux/ramips/Makefile index 8eac4f6ef..23eb5280d 100644 --- a/target/linux/ramips/Makefile +++ b/target/linux/ramips/Makefile @@ -16,7 +16,7 @@ FEATURES:=squashfs broken LINUX_VERSION:=2.6.32.10 include $(INCLUDE_DIR)/target.mk -DEFAULT_PACKAGES+=kmod-leds-gpio +DEFAULT_PACKAGES+=kmod-leds-gpio wpad-mini define Target/Description Build firmware images for Ralink RT288x/RT305x based boards. diff --git a/target/linux/ramips/files/arch/mips/include/asm/mach-ralink/rt305x_regs.h b/target/linux/ramips/files/arch/mips/include/asm/mach-ralink/rt305x_regs.h index 4056b163d..6e7b9e8e6 100644 --- a/target/linux/ramips/files/arch/mips/include/asm/mach-ralink/rt305x_regs.h +++ b/target/linux/ramips/files/arch/mips/include/asm/mach-ralink/rt305x_regs.h @@ -28,7 +28,7 @@ #define RT305X_UART1_BASE 0x10000c00 #define RT305X_FE_BASE 0x10100000 #define RT305X_SWITCH_BASE 0x10110000 -#define RT305X_WMAC_BASE 0x00180000 +#define RT305X_WMAC_BASE 0x10180000 #define RT305X_OTG_BASE 0x101c0000 #define RT305X_ROM_BASE 0x00400000 #define RT305X_FLASH1_BASE 0x1b000000 diff --git a/target/linux/ramips/files/arch/mips/ralink/rt288x/devices.c b/target/linux/ramips/files/arch/mips/ralink/rt288x/devices.c index 64ce0a9e6..086d9a999 100644 --- a/target/linux/ramips/files/arch/mips/ralink/rt288x/devices.c +++ b/target/linux/ramips/files/arch/mips/ralink/rt288x/devices.c @@ -96,3 +96,29 @@ void __init rt288x_register_flash(unsigned int id, platform_device_register(pdev); rt288x_flash_instance++; } + +static struct resource rt288x_wifi_resources[] = { + { + .start = RT2880_WMAC_BASE, + .end = RT2880_WMAC_BASE + 0x3FFFF, + .flags = IORESOURCE_MEM, + }, { + .start = RT288X_CPU_IRQ_WNIC, + .end = RT288X_CPU_IRQ_WNIC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device rt288x_wifi_device = { + .name = "rt2800_wmac", + .resource = rt288x_wifi_resources, + .num_resources = ARRAY_SIZE(rt288x_wifi_resources), + .dev = { + .platform_data = NULL, + } +}; + +void __init rt288x_register_wifi(void) +{ + platform_device_register(&rt288x_wifi_device); +} diff --git a/target/linux/ramips/files/arch/mips/ralink/rt288x/devices.h b/target/linux/ramips/files/arch/mips/ralink/rt288x/devices.h index 4585d8b56..78daf3ad0 100644 --- a/target/linux/ramips/files/arch/mips/ralink/rt288x/devices.h +++ b/target/linux/ramips/files/arch/mips/ralink/rt288x/devices.h @@ -16,5 +16,6 @@ struct physmap_flash_data; extern void rt288x_register_flash(unsigned int id, struct physmap_flash_data *pdata) __init; +void rt288x_register_wifi(void) __init; #endif /* __ASM_MACH_RT288X_PLATFORM_H */ diff --git a/target/linux/ramips/files/arch/mips/ralink/rt288x/mach-rt-n15.c b/target/linux/ramips/files/arch/mips/ralink/rt288x/mach-rt-n15.c index d6bebf494..1a869afac 100644 --- a/target/linux/ramips/files/arch/mips/ralink/rt288x/mach-rt-n15.c +++ b/target/linux/ramips/files/arch/mips/ralink/rt288x/mach-rt-n15.c @@ -125,6 +125,8 @@ static void __init rt_n15_init(void) rt_n15_gpio_buttons); platform_device_register(&rt_n15_rtl8366s_device); + + rt288x_register_wifi(); } MIPS_MACHINE(RAMIPS_MACH_RT_N15, "RT-N15", "Asus RT-N15", rt_n15_init); diff --git a/target/linux/ramips/files/arch/mips/ralink/rt288x/mach-wzr-agl300nh.c b/target/linux/ramips/files/arch/mips/ralink/rt288x/mach-wzr-agl300nh.c index d37af91ab..2e5f46744 100644 --- a/target/linux/ramips/files/arch/mips/ralink/rt288x/mach-wzr-agl300nh.c +++ b/target/linux/ramips/files/arch/mips/ralink/rt288x/mach-wzr-agl300nh.c @@ -75,6 +75,7 @@ static void __init wzr_agl300nh_init(void) rt288x_gpio_init(RT2880_GPIO_MODE_UART0); rt288x_register_flash(0, &wzr_agl300nh_flash_data); + rt288x_register_wifi(); } MIPS_MACHINE(RAMIPS_MACH_WZR_AGL300NH, "WZR-AGL300NH", diff --git a/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.c b/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.c index 6a810a3a0..4ee0d4f1b 100644 --- a/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.c +++ b/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.c @@ -136,3 +136,29 @@ void __init rt305x_register_ethernet(void) platform_device_register(&rt305x_eth_device); } + +static struct resource rt305x_wifi_resources[] = { + { + .start = RT305X_WMAC_BASE, + .end = RT305X_WMAC_BASE + 0x3FFFF, + .flags = IORESOURCE_MEM, + }, { + .start = RT305X_CPU_IRQ_WNIC, + .end = RT305X_CPU_IRQ_WNIC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device rt305x_wifi_device = { + .name = "rt2800_wmac", + .resource = rt305x_wifi_resources, + .num_resources = ARRAY_SIZE(rt305x_wifi_resources), + .dev = { + .platform_data = NULL, + } +}; + +void __init rt305x_register_wifi(void) +{ + platform_device_register(&rt305x_wifi_device); +} diff --git a/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.h b/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.h index 3d6210e0e..b731f8683 100644 --- a/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.h +++ b/target/linux/ramips/files/arch/mips/ralink/rt305x/devices.h @@ -15,7 +15,8 @@ struct physmap_flash_data; extern void rt305x_register_flash(unsigned int id, struct physmap_flash_data *pdata) __init; -extern void rt305x_register_ethernet(void); +extern void rt305x_register_ethernet(void) __init; +extern void rt305x_register_wifi(void) __init; #endif /* __RT305X_DEVICES_H */ diff --git a/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-dir-300-revb.c b/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-dir-300-revb.c index dd2a5f474..27fad6ad9 100644 --- a/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-dir-300-revb.c +++ b/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-dir-300-revb.c @@ -116,6 +116,7 @@ static void __init dir_300b_init(void) ramips_register_gpio_buttons(-1, DIR_300B_BUTTONS_POLL_INTERVAL, ARRAY_SIZE(dir_300b_gpio_buttons), dir_300b_gpio_buttons); + rt305x_register_wifi(); } MIPS_MACHINE(RAMIPS_MACH_DIR_300_REVB, "DIR-300-revB", "D-Link DIR-300 revB", diff --git a/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-fonera20n.c b/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-fonera20n.c index 6dc4b9d3f..c87bdaf3e 100644 --- a/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-fonera20n.c +++ b/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-fonera20n.c @@ -119,6 +119,7 @@ static void __init fonera20n_init(void) fonera20n_gpio_buttons); rt305x_register_ethernet(); + rt305x_register_wifi(); } MIPS_MACHINE(RAMIPS_MACH_FONERA20N, "FONERA20N", "La Fonera 2.0N", diff --git a/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-v22rw-2x2.c b/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-v22rw-2x2.c index 89822c3cf..812dfb4a9 100644 --- a/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-v22rw-2x2.c +++ b/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-v22rw-2x2.c @@ -110,6 +110,7 @@ static void __init v22rw_2x2_init(void) ramips_register_gpio_buttons(-1, V22RW_2X2_BUTTONS_POLL_INTERVAL, ARRAY_SIZE(v22rw_2x2_gpio_buttons), v22rw_2x2_gpio_buttons); + rt305x_register_wifi(); } MIPS_MACHINE(RAMIPS_MACH_V22RW_2X2, "V22RW-2X2", "Ralink AP-RT3052-V22RW-2X2", diff --git a/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-whr-g300n.c b/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-whr-g300n.c index 5d015e264..4e0e810bb 100644 --- a/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-whr-g300n.c +++ b/target/linux/ramips/files/arch/mips/ralink/rt305x/mach-whr-g300n.c @@ -136,6 +136,7 @@ static void __init whr_g300n_init(void) ramips_register_gpio_buttons(-1, WHR_G300N_BUTTONS_POLL_INTERVAL, ARRAY_SIZE(whr_g300n_gpio_buttons), whr_g300n_gpio_buttons); + rt305x_register_wifi(); } MIPS_MACHINE(RAMIPS_MACH_WHR_G300N, "WHR-G300N", "Buffalo WHR-G300N", diff --git a/target/linux/ramips/rt288x/config-2.6.32 b/target/linux/ramips/rt288x/config-2.6.32 index 7d7a45adf..fa912e044 100644 --- a/target/linux/ramips/rt288x/config-2.6.32 +++ b/target/linux/ramips/rt288x/config-2.6.32 @@ -16,8 +16,8 @@ CONFIG_BITREVERSE=y # CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set # CONFIG_CAVIUM_OCTEON_SIMULATOR is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_CEVT_R4K_LIB=y CONFIG_CEVT_R4K=y +CONFIG_CEVT_R4K_LIB=y CONFIG_CFG80211_DEFAULT_PS_VALUE=0 CONFIG_CMDLINE="console=ttyS1,57600 rootfstype=squashfs,jffs2" # CONFIG_CPU_BIG_ENDIAN is not set @@ -26,9 +26,9 @@ CONFIG_CPU_HAS_PREFETCH=y CONFIG_CPU_HAS_SYNC=y CONFIG_CPU_LITTLE_ENDIAN=y # CONFIG_CPU_LOONGSON2E is not set +CONFIG_CPU_MIPS32=y # CONFIG_CPU_MIPS32_R1 is not set CONFIG_CPU_MIPS32_R2=y -CONFIG_CPU_MIPS32=y # CONFIG_CPU_MIPS64_R1 is not set # CONFIG_CPU_MIPS64_R2 is not set CONFIG_CPU_MIPSR2=y @@ -50,8 +50,8 @@ CONFIG_CPU_SUPPORTS_HIGHMEM=y # CONFIG_CPU_TX39XX is not set # CONFIG_CPU_TX49XX is not set # CONFIG_CPU_VR41XX is not set -CONFIG_CSRC_R4K_LIB=y CONFIG_CSRC_R4K=y +CONFIG_CSRC_R4K_LIB=y CONFIG_DECOMPRESS_LZMA=y CONFIG_DEVPORT=y # CONFIG_DM9000 is not set @@ -59,8 +59,8 @@ CONFIG_DMA_NEED_PCI_MAP_STATE=y CONFIG_DMA_NONCOHERENT=y CONFIG_EARLY_PRINTK=y # CONFIG_FSNOTIFY is not set -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_GENERIC_FIND_LAST_BIT=y CONFIG_GENERIC_FIND_NEXT_BIT=y @@ -80,6 +80,8 @@ CONFIG_HW_HAS_PCI=y CONFIG_HW_RANDOM=m CONFIG_INITRAMFS_SOURCE="" CONFIG_IRQ_CPU=y +# CONFIG_ISDN_CAPI is not set +# CONFIG_ISDN_I4L is not set # CONFIG_LEDS_GPIO is not set # CONFIG_MACH_ALCHEMY is not set # CONFIG_MACH_DECSTATION is not set @@ -90,6 +92,7 @@ CONFIG_IRQ_CPU=y # CONFIG_MACH_VR41XX is not set # CONFIG_MII is not set # CONFIG_MIKROTIK_RB532 is not set +CONFIG_MIPS=y # CONFIG_MIPS_COBALT is not set CONFIG_MIPS_L1_CACHE_SHIFT=4 CONFIG_MIPS_MACHINE=y @@ -100,7 +103,6 @@ CONFIG_MIPS_MT_DISABLED=y CONFIG_MIPS_RALINK=y # CONFIG_MIPS_RAMIPS_NET is not set # CONFIG_MIPS_SIM is not set -CONFIG_MIPS=y # CONFIG_MTD_CFI_INTELEXT is not set # CONFIG_MTD_COMPLEX_MAPPINGS is not set CONFIG_MTD_PHYSMAP=y @@ -115,15 +117,14 @@ CONFIG_PHYLIB=y # CONFIG_PMC_YOSEMITE is not set # CONFIG_PNX8550_JBS is not set # CONFIG_PNX8550_STB810 is not set -# CONFIG_PROBE_INITRD_HEADER is not set CONFIG_RALINK_DEV_GPIO_BUTTONS=y CONFIG_RALINK_DEV_GPIO_LEDS=y CONFIG_RALINK_RT288X=y # CONFIG_RALINK_RT305X is not set CONFIG_RT288X_MACH_RT_N15=y CONFIG_RT288X_MACH_WZR_AGL300NH=y -CONFIG_RTL8366_SMI=y CONFIG_RTL8366S_PHY=y +CONFIG_RTL8366_SMI=y CONFIG_SCHED_OMIT_FRAME_POINTER=y # CONFIG_SCSI_DMA is not set # CONFIG_SERIAL_8250_EXTENDED is not set diff --git a/target/linux/ramips/rt305x/config-2.6.32 b/target/linux/ramips/rt305x/config-2.6.32 index 6058fed0e..186000a21 100644 --- a/target/linux/ramips/rt305x/config-2.6.32 +++ b/target/linux/ramips/rt305x/config-2.6.32 @@ -16,8 +16,8 @@ CONFIG_BITREVERSE=y # CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set # CONFIG_CAVIUM_OCTEON_SIMULATOR is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_CEVT_R4K_LIB=y CONFIG_CEVT_R4K=y +CONFIG_CEVT_R4K_LIB=y CONFIG_CFG80211_DEFAULT_PS_VALUE=0 CONFIG_CMDLINE="console=ttyS1,57600 rootfstype=squashfs,jffs2" # CONFIG_CPU_BIG_ENDIAN is not set @@ -26,9 +26,9 @@ CONFIG_CPU_HAS_PREFETCH=y CONFIG_CPU_HAS_SYNC=y CONFIG_CPU_LITTLE_ENDIAN=y # CONFIG_CPU_LOONGSON2E is not set +CONFIG_CPU_MIPS32=y # CONFIG_CPU_MIPS32_R1 is not set CONFIG_CPU_MIPS32_R2=y -CONFIG_CPU_MIPS32=y # CONFIG_CPU_MIPS64_R1 is not set # CONFIG_CPU_MIPS64_R2 is not set CONFIG_CPU_MIPSR2=y @@ -50,16 +50,16 @@ CONFIG_CPU_SUPPORTS_HIGHMEM=y # CONFIG_CPU_TX39XX is not set # CONFIG_CPU_TX49XX is not set # CONFIG_CPU_VR41XX is not set -CONFIG_CSRC_R4K_LIB=y CONFIG_CSRC_R4K=y +CONFIG_CSRC_R4K_LIB=y CONFIG_DECOMPRESS_LZMA=y # CONFIG_DM9000 is not set CONFIG_DMA_NEED_PCI_MAP_STATE=y CONFIG_DMA_NONCOHERENT=y CONFIG_EARLY_PRINTK=y # CONFIG_FSNOTIFY is not set -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_GENERIC_FIND_LAST_BIT=y CONFIG_GENERIC_FIND_NEXT_BIT=y @@ -78,6 +78,8 @@ CONFIG_HAVE_OPROFILE=y CONFIG_HW_RANDOM=m CONFIG_INITRAMFS_SOURCE="" CONFIG_IRQ_CPU=y +# CONFIG_ISDN_CAPI is not set +# CONFIG_ISDN_I4L is not set # CONFIG_LEDS_GPIO is not set # CONFIG_MACH_ALCHEMY is not set # CONFIG_MACH_DECSTATION is not set @@ -88,6 +90,7 @@ CONFIG_IRQ_CPU=y # CONFIG_MACH_VR41XX is not set # CONFIG_MII is not set # CONFIG_MIKROTIK_RB532 is not set +CONFIG_MIPS=y # CONFIG_MIPS_COBALT is not set CONFIG_MIPS_L1_CACHE_SHIFT=5 CONFIG_MIPS_MACHINE=y @@ -98,20 +101,17 @@ CONFIG_MIPS_MT_DISABLED=y CONFIG_MIPS_RALINK=y CONFIG_MIPS_RAMIPS_NET=y # CONFIG_MIPS_SIM is not set -CONFIG_MIPS=y # CONFIG_MTD_CFI_INTELEXT is not set CONFIG_MTD_PHYSMAP=y # CONFIG_NO_IOPORT is not set # CONFIG_NXP_STB220 is not set # CONFIG_NXP_STB225 is not set CONFIG_PAGEFLAGS_EXTENDED=y -CONFIG_PCI=y CONFIG_PHYLIB=y # CONFIG_PMC_MSP is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_PNX8550_JBS is not set # CONFIG_PNX8550_STB810 is not set -# CONFIG_PROBE_INITRD_HEADER is not set CONFIG_RALINK_DEV_GPIO_BUTTONS=y CONFIG_RALINK_DEV_GPIO_LEDS=y # CONFIG_RALINK_RT288X is not set diff --git a/target/linux/rdc/config-2.6.30 b/target/linux/rdc/config-2.6.30 index b18048b4b..b8d222d9c 100644 --- a/target/linux/rdc/config-2.6.30 +++ b/target/linux/rdc/config-2.6.30 @@ -38,7 +38,6 @@ CONFIG_CLOCKSOURCE_WATCHDOG=y CONFIG_CMDLINE_BOOL=y CONFIG_CMDLINE="console=ttyS0,38400 rootfstype=squashfs,jffs2" # CONFIG_CMDLINE_OVERRIDE is not set -# CONFIG_COMPAT_NET_DEV_OPS is not set # CONFIG_COMPAT_VDSO is not set # CONFIG_CPU5_WDT is not set # CONFIG_CPU_SUP_AMD is not set diff --git a/target/linux/x86/Makefile b/target/linux/x86/Makefile index cd7c1b5c0..4cf011af7 100644 --- a/target/linux/x86/Makefile +++ b/target/linux/x86/Makefile @@ -10,7 +10,7 @@ ARCH:=i386 BOARD:=x86 BOARDNAME:=x86 FEATURES:=squashfs jffs2 ext2 vdi vmdk pcmcia tgz -SUBTARGETS=generic olpc xen_domu +SUBTARGETS=generic olpc xen_domu ep80579 LINUX_VERSION:=2.6.32.10 diff --git a/target/linux/x86/ep80579/config-default b/target/linux/x86/ep80579/config-default new file mode 100644 index 000000000..2a89b4fe6 --- /dev/null +++ b/target/linux/x86/ep80579/config-default @@ -0,0 +1,12 @@ +CONFIG_ATA=y +CONFIG_BLK_DEV_SD=y +# CONFIG_MTD_BLOCK2MTD is not set +CONFIG_HIGHMEM4G=y +# CONFIG_HIGHPTE is not set +# CONFIG_MTD is not set +# CONFIG_NOHIGHMEM is not set +CONFIG_SATA_AHCI=y +# CONFIG_SQUASHFS is not set +CONFIG_ITCO_WDT=y +# CONFIG_ITCO_VENDOR_SUPPORT is not set +CONFIG_LOG_BUF_SHIFT=17 diff --git a/target/linux/x86/ep80579/target.mk b/target/linux/x86/ep80579/target.mk new file mode 100644 index 000000000..00fe1abc3 --- /dev/null +++ b/target/linux/x86/ep80579/target.mk @@ -0,0 +1,9 @@ +BOARDNAME:=Intel EP80579 +DEFAULT_PACKAGES += kmod-ep80579-can kmod-ep80579-eth kmod-ep80579-misc \ + kmod-usb-core kmod-usb2 kmod-usb-hid kmod-usb-uhci + +define Target/Description + Build firmware images for Intel EP80579 based boards + (e.g : ADI Engineering Ocracoke Island) +endef + diff --git a/toolchain/binutils/patches/2.18/112-arm-uclibc-gas-needs-libm.patch b/toolchain/binutils/patches/2.18/112-arm-uclibc-gas-needs-libm.patch new file mode 100644 index 000000000..2f46afbd4 --- /dev/null +++ b/toolchain/binutils/patches/2.18/112-arm-uclibc-gas-needs-libm.patch @@ -0,0 +1,38 @@ +Source: Khem Raj +Disposition: submit upstream. + +Description: + +We do not need to have the libtool patch anymore for binutils after +libtool has been updated upstream it include support for it. However +for building gas natively on uclibc systems we have to link it with +-lm so that it picks up missing symbols. + +/local/build_area/BUILD/arm_v5t_le_uclibc/binutils-2.17.50/objdir/libiberty/pic/libiberty.a(floatformat.o): In function `floatformat_from_double': +floatformat.c:(.text+0x1ec): undefined reference to `frexp' +floatformat.c:(.text+0x2f8): undefined reference to `ldexp' +/local/build_area/BUILD/arm_v5t_le_uclibc/binutils-2.17.50/objdir/libiberty/pic/libiberty.a(floatformat.o): In function `floatformat_to_double': +floatformat.c:(.text+0x38a): undefined reference to `ldexp' +floatformat.c:(.text+0x3d2): undefined reference to `ldexp' +floatformat.c:(.text+0x43e): undefined reference to `ldexp' floatformat.c:(.text+0x4e2): undefined reference to `ldexp' +collect2: ld returned 1 exit status +make[4]: *** [as-new] Error 1 + +Index: binutils-2.17.50/gas/configure.tgt +=================================================================== +--- binutils-2.17.50.orig/gas/configure.tgt ++++ binutils-2.17.50/gas/configure.tgt +@@ -411,6 +411,12 @@ case ${generic_target} in + *-*-netware) fmt=elf em=netware ;; + esac + ++case ${generic_target} in ++ arm-*-*uclibc*) ++ need_libm=yes ++ ;; ++esac ++ + case ${cpu_type} in + alpha | arm | i386 | ia64 | mips | ns32k | pdp11 | ppc | sparc | z80 | z8k) + bfd_gas=yes + diff --git a/toolchain/binutils/patches/2.19.1+cs/112-arm-uclibc-gas-needs-libm.patch b/toolchain/binutils/patches/2.19.1+cs/112-arm-uclibc-gas-needs-libm.patch new file mode 100644 index 000000000..f7731613f --- /dev/null +++ b/toolchain/binutils/patches/2.19.1+cs/112-arm-uclibc-gas-needs-libm.patch @@ -0,0 +1,38 @@ +Source: Khem Raj +Disposition: submit upstream. + +Description: + +We do not need to have the libtool patch anymore for binutils after +libtool has been updated upstream it include support for it. However +for building gas natively on uclibc systems we have to link it with +-lm so that it picks up missing symbols. + +/local/build_area/BUILD/arm_v5t_le_uclibc/binutils-2.17.50/objdir/libiberty/pic/libiberty.a(floatformat.o): In function `floatformat_from_double': +floatformat.c:(.text+0x1ec): undefined reference to `frexp' +floatformat.c:(.text+0x2f8): undefined reference to `ldexp' +/local/build_area/BUILD/arm_v5t_le_uclibc/binutils-2.17.50/objdir/libiberty/pic/libiberty.a(floatformat.o): In function `floatformat_to_double': +floatformat.c:(.text+0x38a): undefined reference to `ldexp' +floatformat.c:(.text+0x3d2): undefined reference to `ldexp' +floatformat.c:(.text+0x43e): undefined reference to `ldexp' floatformat.c:(.text+0x4e2): undefined reference to `ldexp' +collect2: ld returned 1 exit status +make[4]: *** [as-new] Error 1 + +Index: binutils-2.17.50/gas/configure.tgt +=================================================================== +--- binutils-2.17.50.orig/gas/configure.tgt ++++ binutils-2.17.50/gas/configure.tgt +@@ -415,6 +415,12 @@ case ${generic_target} in + *-*-netware) fmt=elf em=netware ;; + esac + ++case ${generic_target} in ++ arm-*-*uclibc*) ++ need_libm=yes ++ ;; ++esac ++ + case ${cpu_type} in + alpha | arm | i386 | ia64 | mips | ns32k | pdp11 | ppc | sparc | z80 | z8k) + bfd_gas=yes + diff --git a/toolchain/binutils/patches/2.19.1/112-arm-uclibc-gas-needs-libm.patch b/toolchain/binutils/patches/2.19.1/112-arm-uclibc-gas-needs-libm.patch new file mode 100644 index 000000000..f7731613f --- /dev/null +++ b/toolchain/binutils/patches/2.19.1/112-arm-uclibc-gas-needs-libm.patch @@ -0,0 +1,38 @@ +Source: Khem Raj +Disposition: submit upstream. + +Description: + +We do not need to have the libtool patch anymore for binutils after +libtool has been updated upstream it include support for it. However +for building gas natively on uclibc systems we have to link it with +-lm so that it picks up missing symbols. + +/local/build_area/BUILD/arm_v5t_le_uclibc/binutils-2.17.50/objdir/libiberty/pic/libiberty.a(floatformat.o): In function `floatformat_from_double': +floatformat.c:(.text+0x1ec): undefined reference to `frexp' +floatformat.c:(.text+0x2f8): undefined reference to `ldexp' +/local/build_area/BUILD/arm_v5t_le_uclibc/binutils-2.17.50/objdir/libiberty/pic/libiberty.a(floatformat.o): In function `floatformat_to_double': +floatformat.c:(.text+0x38a): undefined reference to `ldexp' +floatformat.c:(.text+0x3d2): undefined reference to `ldexp' +floatformat.c:(.text+0x43e): undefined reference to `ldexp' floatformat.c:(.text+0x4e2): undefined reference to `ldexp' +collect2: ld returned 1 exit status +make[4]: *** [as-new] Error 1 + +Index: binutils-2.17.50/gas/configure.tgt +=================================================================== +--- binutils-2.17.50.orig/gas/configure.tgt ++++ binutils-2.17.50/gas/configure.tgt +@@ -415,6 +415,12 @@ case ${generic_target} in + *-*-netware) fmt=elf em=netware ;; + esac + ++case ${generic_target} in ++ arm-*-*uclibc*) ++ need_libm=yes ++ ;; ++esac ++ + case ${cpu_type} in + alpha | arm | i386 | ia64 | mips | ns32k | pdp11 | ppc | sparc | z80 | z8k) + bfd_gas=yes + diff --git a/toolchain/binutils/patches/2.20.1/112-arm-uclibc-gas-needs-libm.patch b/toolchain/binutils/patches/2.20.1/112-arm-uclibc-gas-needs-libm.patch new file mode 100644 index 000000000..abc8117e2 --- /dev/null +++ b/toolchain/binutils/patches/2.20.1/112-arm-uclibc-gas-needs-libm.patch @@ -0,0 +1,38 @@ +Source: Khem Raj +Disposition: submit upstream. + +Description: + +We do not need to have the libtool patch anymore for binutils after +libtool has been updated upstream it include support for it. However +for building gas natively on uclibc systems we have to link it with +-lm so that it picks up missing symbols. + +/local/build_area/BUILD/arm_v5t_le_uclibc/binutils-2.17.50/objdir/libiberty/pic/libiberty.a(floatformat.o): In function `floatformat_from_double': +floatformat.c:(.text+0x1ec): undefined reference to `frexp' +floatformat.c:(.text+0x2f8): undefined reference to `ldexp' +/local/build_area/BUILD/arm_v5t_le_uclibc/binutils-2.17.50/objdir/libiberty/pic/libiberty.a(floatformat.o): In function `floatformat_to_double': +floatformat.c:(.text+0x38a): undefined reference to `ldexp' +floatformat.c:(.text+0x3d2): undefined reference to `ldexp' +floatformat.c:(.text+0x43e): undefined reference to `ldexp' floatformat.c:(.text+0x4e2): undefined reference to `ldexp' +collect2: ld returned 1 exit status +make[4]: *** [as-new] Error 1 + +Index: binutils-2.17.50/gas/configure.tgt +=================================================================== +--- binutils-2.17.50.orig/gas/configure.tgt ++++ binutils-2.17.50/gas/configure.tgt +@@ -431,6 +431,12 @@ case ${generic_target} in + *-*-netware) fmt=elf em=netware ;; + esac + ++case ${generic_target} in ++ arm-*-*uclibc*) ++ need_libm=yes ++ ;; ++esac ++ + case ${cpu_type} in + alpha | arm | i386 | ia64 | microblaze | mips | ns32k | pdp11 | ppc | sparc | z80 | z8k) + bfd_gas=yes + diff --git a/toolchain/binutils/patches/2.20/112-arm-uclibc-gas-needs-libm.patch b/toolchain/binutils/patches/2.20/112-arm-uclibc-gas-needs-libm.patch new file mode 100644 index 000000000..abc8117e2 --- /dev/null +++ b/toolchain/binutils/patches/2.20/112-arm-uclibc-gas-needs-libm.patch @@ -0,0 +1,38 @@ +Source: Khem Raj +Disposition: submit upstream. + +Description: + +We do not need to have the libtool patch anymore for binutils after +libtool has been updated upstream it include support for it. However +for building gas natively on uclibc systems we have to link it with +-lm so that it picks up missing symbols. + +/local/build_area/BUILD/arm_v5t_le_uclibc/binutils-2.17.50/objdir/libiberty/pic/libiberty.a(floatformat.o): In function `floatformat_from_double': +floatformat.c:(.text+0x1ec): undefined reference to `frexp' +floatformat.c:(.text+0x2f8): undefined reference to `ldexp' +/local/build_area/BUILD/arm_v5t_le_uclibc/binutils-2.17.50/objdir/libiberty/pic/libiberty.a(floatformat.o): In function `floatformat_to_double': +floatformat.c:(.text+0x38a): undefined reference to `ldexp' +floatformat.c:(.text+0x3d2): undefined reference to `ldexp' +floatformat.c:(.text+0x43e): undefined reference to `ldexp' floatformat.c:(.text+0x4e2): undefined reference to `ldexp' +collect2: ld returned 1 exit status +make[4]: *** [as-new] Error 1 + +Index: binutils-2.17.50/gas/configure.tgt +=================================================================== +--- binutils-2.17.50.orig/gas/configure.tgt ++++ binutils-2.17.50/gas/configure.tgt +@@ -431,6 +431,12 @@ case ${generic_target} in + *-*-netware) fmt=elf em=netware ;; + esac + ++case ${generic_target} in ++ arm-*-*uclibc*) ++ need_libm=yes ++ ;; ++esac ++ + case ${cpu_type} in + alpha | arm | i386 | ia64 | microblaze | mips | ns32k | pdp11 | ppc | sparc | z80 | z8k) + bfd_gas=yes + diff --git a/toolchain/kernel-headers/Makefile b/toolchain/kernel-headers/Makefile index 47e7b245b..394e1d109 100644 --- a/toolchain/kernel-headers/Makefile +++ b/toolchain/kernel-headers/Makefile @@ -21,6 +21,7 @@ PKG_SOURCE_URL:=$(LINUX_SITE) HOST_BUILD_DIR:=$(KERNEL_BUILD_DIR)/linux-$(LINUX_VERSION) PKG_MD5SUM:=$(LINUX_KERNEL_MD5SUM) LINUX_DIR := $(HOST_BUILD_DIR) +FILES_DIR := include $(INCLUDE_DIR)/toolchain-build.mk include $(INCLUDE_DIR)/kernel-defaults.mk diff --git a/tools/firmware-utils/src/imagetag.c b/tools/firmware-utils/src/imagetag.c index e93f5f45e..658674ec7 100644 --- a/tools/firmware-utils/src/imagetag.c +++ b/tools/firmware-utils/src/imagetag.c @@ -29,7 +29,7 @@ union int2char { uint32_t input; - unsigned char output[4]; + char output[4]; }; /* This appears to be necessary due to alignment issues */ @@ -43,7 +43,7 @@ struct kernelhdr { uint32_t lzmalen; /* Compressed length of the LZMA data that follows */ }; -static struct tagiddesc_t tagidtab[NUM_TAGID] = TAGID_DEFINITIONS; +static char pirellitab[NUM_PIRELLI][BOARDID_LEN] = PIRELLI_BOARDS; static uint32_t crc32tab[256] = { 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, @@ -130,9 +130,9 @@ int tagfile(const char *kernel, const char *rootfs, const char *bin, const char *boardid, const char *chipid, const uint32_t fwaddr, const uint32_t loadaddr, const uint32_t entry, const char *ver, const char *magic2, const uint32_t flash_bs, - const char *tagid, const char *information, const char *layoutver) + const char *rsignature, const char *layoutver) { - union bcm_tag tag; + struct bcm_tag tag; struct kernelhdr khdr; FILE *kernelfile = NULL, *rootfsfile = NULL, *binfile; size_t kerneloff, kernellen, rootfsoff, rootfslen, read, imagelen, rootfsoffpadlen, kernelfslen; @@ -143,23 +143,26 @@ int tagfile(const char *kernel, const char *rootfs, const char *bin, uint32_t kernelfscrc = IMAGETAG_CRC_START; const uint32_t deadcode = htonl(DEADCODE); union int2char intchar; + int i; + int is_pirelli = 0; - memset(&tag, 0, sizeof(union bcm_tag)); + memset(&tag, 0, sizeof(struct bcm_tag)); - /* All imagetags have boardid in the same location and of the same - * size, so we just use the bccfe one - */ - if (strlen(boardid) >= sizeof(tag.bccfe.boardid)) { + if (strlen(boardid) >= sizeof(tag.boardid)) { fprintf(stderr, "Board id is too long!\n"); return 1; } /* Likewise chipid */ - if (strlen(chipid) >= sizeof(tag.bccfe.chipid)) { + if (strlen(chipid) >= sizeof(tag.chipid)) { fprintf(stderr, "Chip id is too long!\n"); return 1; } + if (!kernel || !rootfs) { + fprintf(stderr, "imagetag can't create an image without both kernel and rootfs\n"); + } + if (kernel && !(kernelfile = fopen(kernel, "rb"))) { fprintf(stderr, "Unable to open kernel \"%s\"\n", kernel); return 1; @@ -224,203 +227,70 @@ int tagfile(const char *kernel, const char *rootfs, const char *bin, */ fflush(binfile); - /* Choose and compute the CRC32 that should be inserted in the tag */ - if ( tagid && ( (strncmp(tagid, "bccfe", TAGID_LEN) == 0)) || ( strncmp(tagid, "bc300", TAGID_LEN) == 0)) { - /* Compute the crc32 of the entire image (deadC0de included) */ - imagecrc = compute_crc32(imagecrc, binfile, kerneloff - fwaddr, imagelen); - } else if ( tagid && (strncmp(tagid, "ag306", TAGID_LEN) == 0)) { - /* Compute the crc32 of the kernel and padding between kernel and rootfs) */ - kernelcrc = compute_crc32(kernelcrc, binfile, kerneloff - fwaddr, kernellen + rootfsoffpadlen); - } else if ( tagid && ( (strncmp(tagid, "bc221", TAGID_LEN) == 0))) { - /* Compute the crc32 of the entire image (deadC0de included) */ - imagecrc = compute_crc32(imagecrc, binfile, kerneloff - fwaddr, imagelen); - /* Compute the crc32 of the kernel and padding between kernel and rootfs) */ - kernelfscrc = compute_crc32(kernelfscrc, binfile, kerneloff - fwaddr, kernellen + rootfsoffpadlen + rootfslen + sizeof(deadcode)); - } else if ( tagid && (strncmp(tagid, "bc310", TAGID_LEN) == 0) ) { - /* Compute the crc32 of the entire image (deadC0de included) */ - imagecrc = compute_crc32(imagecrc, binfile, kerneloff - fwaddr, imagelen); - /* Compute the crc32 of the kernel and padding between kernel and rootfs) */ - kernelcrc = compute_crc32(kernelcrc, binfile, kerneloff - fwaddr, kernellen + rootfsoffpadlen); - /* Compute the crc32 of the flashImageStart to rootLength. - * The broadcom firmware assumes the rootfs starts the image, - * therefore uses the rootfs start to determine where to flash - * the image. Since we have the kernel first we have to give - * it the kernel address, but the crc uses the length - * associated with this address, which is added to the kernel - * length to determine the length of image to flash and thus - * needs to be rootfs + deadcode - */ - rootfscrc = compute_crc32(rootfscrc, binfile, kerneloff - fwaddr, rootfslen + sizeof(deadcode)); - } + /* Compute the crc32 of the entire image (deadC0de included) */ + imagecrc = compute_crc32(imagecrc, binfile, kerneloff - fwaddr, imagelen); + /* Compute the crc32 of the kernel and padding between kernel and rootfs) */ + kernelcrc = compute_crc32(kernelcrc, binfile, kerneloff - fwaddr, kernellen + rootfsoffpadlen); + /* Compute the crc32 of the kernel and padding between kernel and rootfs) */ + kernelfscrc = compute_crc32(kernelfscrc, binfile, kerneloff - fwaddr, kernellen + rootfsoffpadlen + rootfslen + sizeof(deadcode)); + /* Compute the crc32 of the flashImageStart to rootLength. + * The broadcom firmware assumes the rootfs starts the image, + * therefore uses the rootfs start to determine where to flash + * the image. Since we have the kernel first we have to give + * it the kernel address, but the crc uses the length + * associated with this address, which is added to the kernel + * length to determine the length of image to flash and thus + * needs to be rootfs + deadcode + */ + rootfscrc = compute_crc32(rootfscrc, binfile, kerneloff - fwaddr, rootfslen + sizeof(deadcode)); /* Close the files */ fclose(kernelfile); fclose(rootfsfile); - if ( tagid && (strcmp(tagid, "bccfe") == 0)) { - /* Build the tag */ - strncpy(tag.bccfe.tagVersion, ver, TAGVER_LEN); - strncpy(tag.bccfe.sig_1, IMAGETAG_MAGIC1, sizeof(tag.bccfe.sig_1) - 1); - strncpy(tag.bccfe.sig_2, magic2, sizeof(tag.bccfe.sig_2) - 1); - strcpy(tag.bccfe.chipid, chipid); - strcpy(tag.bccfe.boardid, boardid); - strcpy(tag.bccfe.big_endian, "1"); - sprintf(tag.bccfe.totalLength, "%lu", imagelen); + /* Build the tag */ + strncpy(tag.tagVersion, ver, TAGVER_LEN); + strncpy(tag.sig_1, IMAGETAG_MAGIC1, sizeof(tag.sig_1) - 1); + strncpy(tag.sig_2, magic2, sizeof(tag.sig_2) - 1); + strcpy(tag.chipid, chipid); + strcpy(tag.boardid, boardid); + strcpy(tag.big_endian, "1"); + sprintf(tag.totalLength, "%lu", imagelen); - /* We don't include CFE */ - strcpy(tag.bccfe.cfeAddress, "0"); - strcpy(tag.bccfe.cfeLength, "0"); + /* We don't include CFE */ + strcpy(tag.cfeAddress, "0"); + strcpy(tag.cfeLength, "0"); - if (kernelfile) { - sprintf(tag.bccfe.kernelAddress, "%lu", kerneloff); - sprintf(tag.bccfe.kernelLength, "%lu", kernellen + rootfsoffpadlen); - } + sprintf(tag.kernelAddress, "%lu", kerneloff); + sprintf(tag.kernelLength, "%lu", kernellen + rootfsoffpadlen); + sprintf(tag.flashImageStart, "%lu", kerneloff); + sprintf(tag.rootLength, "%lu", rootfslen + sizeof(deadcode)); - if (rootfsfile) { - sprintf(tag.bccfe.rootAddress, "%lu", rootfsoff); - sprintf(tag.bccfe.rootLength, "%lu", rootfslen); - } - - strncpy(tag.bccfe.tagId, "bccfe", TAGID_LEN); - - int2tag(tag.bccfe.tagIdCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&(tag.bccfe.tagId[0]), TAGID_LEN)); - int2tag(tag.bccfe.imageCRC, imagecrc); - int2tag(tag.bccfe.headerCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&tag, sizeof(tag) - 20)); - } else if ( tagid && (strcmp(tagid, "bc300") == 0)) { - /* Build the tag */ - strncpy(tag.bc300.tagVersion, ver, TAGVER_LEN); - strncpy(tag.bc300.sig_1, IMAGETAG_MAGIC1, sizeof(tag.bc300.sig_1) - 1); - strncpy(tag.bc300.sig_2, magic2, sizeof(tag.bc300.sig_2) - 1); - strcpy(tag.bc300.chipid, chipid); - strcpy(tag.bc300.boardid, boardid); - strcpy(tag.bc300.big_endian, "1"); - sprintf(tag.bc300.totalLength, "%lu", imagelen); - - /* We don't include CFE */ - strcpy(tag.bc300.cfeAddress, "0"); - strcpy(tag.bc300.cfeLength, "0"); - - if (kernelfile) { - sprintf(tag.bc300.kernelAddress, "%lu", kerneloff); - sprintf(tag.bc300.kernelLength, "%lu", kernellen + rootfsoffpadlen); - } - - if (rootfsfile) { - sprintf(tag.bc300.flashImageStart, "%lu", kerneloff); - sprintf(tag.bc300.flashRootLength, "%lu", rootfslen + sizeof(deadcode)); - sprintf(tag.bc300.rootAddress, "%lu", rootfsoff); - sprintf(tag.bc300.rootLength, "%lu", rootfslen); - } - - strncpy(tag.bc300.tagId, "bc300", TAGID_LEN); - - int2tag(tag.bc300.tagIdCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&(tag.bc300.tagId[0]), TAGID_LEN)); - int2tag(tag.bc300.imageCRC, imagecrc); - int2tag(tag.bc300.headerCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&tag, sizeof(tag) - 20)); - } else if ( tagid && (strcmp(tagid, "ag306") == 0)) { - /* Build the tag */ - strncpy(tag.ag306.tagVersion, ver, TAGVER_LEN); - strncpy(tag.ag306.sig_1, IMAGETAG_MAGIC1, sizeof(tag.ag306.sig_1) - 1); - strncpy(tag.ag306.sig_2, magic2, sizeof(tag.ag306.sig_2) - 1); - strcpy(tag.ag306.chipid, chipid); - strcpy(tag.ag306.boardid, boardid); - strcpy(tag.ag306.big_endian, "1"); - sprintf(tag.ag306.totalLength, "%lu", imagelen); - - /* We don't include CFE */ - strcpy(tag.ag306.cfeAddress, "0"); - strcpy(tag.ag306.cfeLength, "0"); - - if (kernelfile) { - sprintf(tag.ag306.kernelAddress, "%lu", kerneloff); - sprintf(tag.ag306.kernelLength, "%lu", kernellen + rootfsoffpadlen); - } - - if (rootfsfile) { - sprintf(tag.ag306.flashImageStart, "%lu", kerneloff); - sprintf(tag.ag306.flashRootLength, "%lu", rootfslen + sizeof(deadcode)); - sprintf(tag.ag306.rootAddress, "%lu", rootfsoff); - sprintf(tag.ag306.rootLength, "%lu", rootfslen); - } - - strncpy(tag.ag306.tagId, "ag306", TAGID_LEN); - - int2tag(tag.ag306.tagIdCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&(tag.ag306.tagId[0]), TAGID_LEN)); - int2tag(tag.ag306.kernelCRC, kernelcrc); - int2tag(tag.ag306.headerCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&tag, sizeof(tag) - 20)); - } else if ( tagid && (strcmp(tagid, "bc221") == 0)) { - /* Build the tag */ - strncpy(tag.bc221.tagVersion, ver, TAGVER_LEN); - strncpy(tag.bc221.sig_1, IMAGETAG_MAGIC1, sizeof(tag.bc221.sig_1) - 1); - strncpy(tag.bc221.sig_2, magic2, sizeof(tag.bc221.sig_2) - 1); - strcpy(tag.bc221.chipid, chipid); - strcpy(tag.bc221.boardid, boardid); - strcpy(tag.bc221.big_endian, "1"); - sprintf(tag.bc221.totalLength, "%lu", imagelen); - - /* We don't include CFE */ - strcpy(tag.bc221.cfeAddress, "0"); - strcpy(tag.bc221.cfeLength, "0"); - - if (kernelfile) { - sprintf(tag.bc221.kernelAddress, "%lu", kerneloff); - sprintf(tag.bc221.kernelLength, "%lu", kernellen + rootfsoffpadlen); - } - - if (rootfsfile) { - sprintf(tag.bc221.flashImageStart, "%lu", kerneloff); - sprintf(tag.bc221.flashRootLength, "%lu", rootfslen + sizeof(deadcode)); - sprintf(tag.bc221.rootAddress, "%lu", rootfsoff); - sprintf(tag.bc221.rootLength, "%lu", rootfslen); - } - - strncpy(tag.bc221.tagId, "bc221", TAGID_LEN); - if (layoutver) { - strncpy(tag.bc221.flashLayoutVer, layoutver, TAGLAYOUT_LEN); - } - - int2tag(tag.bc221.tagIdCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&(tag.bc221.tagId[0]), TAGID_LEN)); - int2tag(tag.bc221.imageCRC, imagecrc); - int2tag(tag.bc221.fskernelCRC, kernelfscrc); - int2tag(tag.bc221.headerCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&tag, sizeof(tag) - 20)); - } else if ( tagid && (strcmp(tagid, "bc310") == 0)) { - /* Build the tag */ - strncpy(tag.bc310.tagVersion, ver, TAGVER_LEN); - strncpy(tag.bc310.sig_1, IMAGETAG_MAGIC1, sizeof(tag.bc310.sig_1) - 1); - strncpy(tag.bc310.sig_2, magic2, sizeof(tag.bc310.sig_2) - 1); - strcpy(tag.bc310.chipid, chipid); - strcpy(tag.bc310.boardid, boardid); - strcpy(tag.bc310.big_endian, "1"); - sprintf(tag.bc310.totalLength, "%lu", imagelen); - - /* We don't include CFE */ - strcpy(tag.bc310.cfeAddress, "0"); - strcpy(tag.bc310.cfeLength, "0"); - - if (kernelfile) { - sprintf(tag.bc310.kernelAddress, "%lu", kerneloff); - sprintf(tag.bc310.kernelLength, "%lu", kernellen + rootfsoffpadlen); - } - - if (rootfsfile) { - sprintf(tag.bc310.flashImageStart, "%lu", kerneloff); - sprintf(tag.bc310.flashRootLength, "%lu", rootfslen + sizeof(deadcode)); - sprintf(tag.bc310.rootAddress, "%lu", rootfsoff); - sprintf(tag.bc310.rootLength, "%lu", rootfslen); - } - - strncpy(tag.bc310.tagId, "bc310", TAGID_LEN); - if (information) { - strncpy(tag.bc310.information1, information, TAGINFO_LEN); - } - - int2tag(tag.bc310.tagIdCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&(tag.bc310.tagId[0]), TAGID_LEN)); - int2tag(tag.bc310.imageCRC, imagecrc); - int2tag(tag.bc310.kernelCRC, kernelcrc); - int2tag(tag.bc310.rootfsCRC, rootfscrc); - int2tag(tag.bc310.headerCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&tag, sizeof(tag) - 20)); + if (rsignature) { + strncpy(tag.rsa_signature, rsignature, RSASIG_LEN); } + if (layoutver) { + strncpy(tag.flashLayoutVer, layoutver, TAGLAYOUT_LEN); + } + + for (i = 0; i < NUM_PIRELLI; i++) { + if (strncmp(boardid, pirellitab[i], BOARDID_LEN) == 0) { + is_pirelli = 1; + break; + } + } + + if ( !is_pirelli ) { + int2tag(tag.imageCRC, imagecrc); + } else { + int2tag(tag.imageCRC, kernelcrc); + } + int2tag(tag.kernelCRC, kernelcrc); + int2tag(tag.rootfsCRC, rootfscrc); + int2tag(tag.fskernelCRC, kernelfscrc); + int2tag(tag.headerCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&tag, sizeof(tag) - 20)); + fseek(binfile, 0L, SEEK_SET); fwrite(&tag, sizeof(uint8_t), sizeof(tag), binfile); @@ -432,12 +302,12 @@ int tagfile(const char *kernel, const char *rootfs, const char *bin, int main(int argc, char **argv) { int c, i; - char *kernel, *rootfs, *bin, *boardid, *chipid, *magic2, *ver, *tagid, *information, *layoutver; + char *kernel, *rootfs, *bin, *boardid, *chipid, *magic2, *ver, *tagid, *rsignature, *layoutver; uint32_t flashstart, fwoffset, loadaddr, entry; uint32_t fwaddr, flash_bs; int tagidfound = 0; - kernel = rootfs = bin = boardid = chipid = magic2 = ver = tagid = information = layoutver = NULL; + kernel = rootfs = bin = boardid = chipid = magic2 = ver = rsignature = layoutver = NULL; entry = 0; flashstart = DEFAULT_FLASH_START; @@ -445,11 +315,11 @@ int main(int argc, char **argv) loadaddr = IMAGETAG_DEFAULT_LOADADDR; flash_bs = DEFAULT_FLASH_BS; - printf("Broadcom image tagger - v0.2.0\n"); + printf("Broadcom image tagger - v1.0.0\n"); printf("Copyright (C) 2008 Axel Gembe\n"); - printf("Copyright (C) 2009 Daniel Dickinson\n"); + printf("Copyright (C) 2009-2010 Daniel Dickinson\n"); - while ((c = getopt(argc, argv, "i:f:o:b:c:s:n:v:m:k:l:e:h:t:d:y:")) != -1) { + while ((c = getopt(argc, argv, "i:f:o:b:c:s:n:v:m:k:l:e:h:r:y:")) != -1) { switch (c) { case 'i': kernel = optarg; @@ -487,11 +357,8 @@ int main(int argc, char **argv) case 'e': entry = strtoul(optarg, NULL, 16); break; - case 't': - tagid = optarg; - break; - case 'd': - information = optarg; + case 'r': + rsignature = optarg; break; case 'y': layoutver = optarg; @@ -511,9 +378,8 @@ int main(int argc, char **argv) fprintf(stderr, " -k - flash erase block size\n"); fprintf(stderr, " -l - Address where the kernel expects to be loaded (defaults to 0x80010000)\n"); fprintf(stderr, " -e - Address where the kernel entry point will end up\n"); - fprintf(stderr, " -t - type if imagetag to create, use 'list' to see available choices"); - fprintf(stderr, " -d - vendor specific information, for those that need it"); - fprintf(stderr, " -y - Flash Layout Version (2.2x code versions need this)"); + fprintf(stderr, " -r - vendor specific signature, for those that need it"); + fprintf(stderr, " -y - Flash Layout Version (2.2x code versions need this)"); fprintf(stderr, " -h - Displays this text\n\n"); return 1; } @@ -529,38 +395,6 @@ int main(int argc, char **argv) return 1; } - tagidfound = 0; - if (!tagid) { - fprintf(stderr, "You must specify a tagid (-t)\n"); - } else { - if (strncmp(tagid, "list", 4) == 0) { - fprintf(stderr, "\n----------------------------------------\n"); - fprintf(stderr, "\tAvailable tagId:"); - fprintf(stderr, "\n\n"); - for (i = 0; i < NUM_TAGID; i++) { - fprintf(stderr, "\t%s\t%s", tagidtab[i].tagid, tagidtab[i].tagiddesc); - } - fprintf(stderr, "\n----------------------------------------\n"); - return 0; - } - } - - if (tagid) { - for(i = 0; i < NUM_TAGID; i++) { - if (strncmp(tagid, tagidtab[i].tagid, TAGID_LEN) == 0) { - tagidfound = 1; - break; - } - } - if (!tagidfound) { - if (tagid) { - fprintf(stderr, "The tagid you selected '%s' does't exist.\n", tagid); - } - fprintf(stderr, "Use -t list to see the list of available ids"); - return 1; - } - } - /* Fallback to defaults */ fwaddr = flashstart + fwoffset; @@ -584,5 +418,5 @@ int main(int argc, char **argv) } - return tagfile(kernel, rootfs, bin, boardid, chipid, fwaddr, loadaddr, entry, ver, magic2, flash_bs, tagid, information, layoutver); + return tagfile(kernel, rootfs, bin, boardid, chipid, fwaddr, loadaddr, entry, ver, magic2, flash_bs, rsignature, layoutver); }